15b4a4f57291f2b2fabce7f77e556f9813e71816
[u/mrichter/AliRoot.git] / STEER / AliSimulation.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 // class for running generation, simulation and digitization                 //
21 //                                                                           //
22 // Hits, sdigits and digits are created for all detectors by typing:         //
23 //                                                                           //
24 //   AliSimulation sim;                                                      //
25 //   sim.Run();                                                              //
26 //                                                                           //
27 // The Run method returns kTRUE in case of successful execution.             //
28 // The number of events can be given as argument to the Run method or it     //
29 // can be set by                                                             //
30 //                                                                           //
31 //   sim.SetNumberOfEvents(n);                                               //
32 //                                                                           //
33 // The name of the configuration file can be passed as argument to the       //
34 // AliSimulation constructor or can be specified by                          //
35 //                                                                           //
36 //   sim.SetConfigFile("...");                                               //
37 //                                                                           //
38 // The generation of particles and the simulation of detector hits can be    //
39 // switched on or off by                                                     //
40 //                                                                           //
41 //   sim.SetRunGeneration(kTRUE);   // generation of primary particles       //
42 //   sim.SetRunSimulation(kFALSE);  // but no tracking                       //
43 //                                                                           //
44 // For which detectors sdigits and digits will be created, can be steered    //
45 // by                                                                        //
46 //                                                                           //
47 //   sim.SetMakeSDigits("ALL");     // make sdigits for all detectors        //
48 //   sim.SetMakeDigits("ITS TPC");  // make digits only for ITS and TPC      //
49 //                                                                           //
50 // The argument is a (case sensitive) string with the names of the           //
51 // detectors separated by a space. An empty string ("") can be used to       //
52 // disable the creation of sdigits or digits. The special string "ALL"       //
53 // selects all available detectors. This is the default.                     //
54 //                                                                           //
55 // The creation of digits from hits instead of from sdigits can be selected  //
56 // by                                                                        //
57 //                                                                           //
58 //   sim.SetMakeDigitsFromHits("TRD");                                       //
59 //                                                                           //
60 // The argument is again a string with the selected detectors. Be aware that //
61 // this feature is not available for all detectors and that merging is not   //
62 // possible, when digits are created directly from hits.                     //
63 //                                                                           //
64 // Background events can be merged by calling                                //
65 //                                                                           //
66 //   sim.MergeWith("background/galice.root", 2);                             //
67 //                                                                           //
68 // The first argument is the file name of the background galice file. The    //
69 // second argument is the number of signal events per background event.      //
70 // By default this number is calculated from the number of available         //
71 // background events. MergeWith can be called several times to merge more    //
72 // than two event streams. It is assumed that the sdigits were already       //
73 // produced for the background events.                                       //
74 //                                                                           //
75 // The output of raw data can be switched on by calling                      //
76 //                                                                           //
77 //   sim.SetWriteRawData("MUON");   // write raw data for MUON               //
78 //                                                                           //
79 // The default output format of the raw data are DDL files. They are         //
80 // converted to a DATE file, if a file name is given as second argument.     //
81 // For this conversion the program "dateStream" is required. If the file     //
82 // name has the extension ".root", the DATE file is converted to a root      //
83 // file. The program "alimdc" is used for this purpose. For the conversion   //
84 // to DATE and root format the two conversion programs have to be installed. //
85 // Only the raw data in the final format is kept if the third argument is    //
86 // kTRUE.                                                                    //
87 //                                                                           //
88 // The methods RunSimulation, RunSDigitization, RunDigitization,             //
89 // RunHitsDigitization and WriteRawData can be used to run only parts of     //
90 // the full simulation chain. The creation of raw data DDL files and their   //
91 // conversion to the DATE or root format can be run directly by calling      //
92 // the methods WriteRawFiles, ConvertRawFilesToDate and ConvertDateToRoot.   //
93 //                                                                           //
94 // The default number of events per file, which is usually set in the        //
95 // config file, can be changed for individual detectors and data types       //
96 // by calling                                                                //
97 //                                                                           //
98 //   sim.SetEventsPerFile("PHOS", "Reconstructed Points", 3);                //
99 //                                                                           //
100 // The first argument is the detector, the second one the data type and the  //
101 // last one the number of events per file. Valid data types are "Hits",      //
102 // "Summable Digits", "Digits", "Reconstructed Points" and "Tracks".         //
103 // The number of events per file has to be set before the simulation of      //
104 // hits. Otherwise it has no effect.                                         //
105 //                                                                           //
106 ///////////////////////////////////////////////////////////////////////////////
107
108 #include <TGeoManager.h>
109 #include <TObjString.h>
110 #include <TStopwatch.h>
111 #include <TSystem.h>
112 #include <TFile.h>
113
114 #include "AliCDBStorage.h"
115 #include "AliCDBEntry.h"
116 #include "AliCDBManager.h"
117 #include "AliAlignObj.h"
118 #include "AliCentralTrigger.h"
119 #include "AliDAQConfig.h"
120 #include "AliDigitizer.h"
121 #include "AliGenerator.h"
122 #include "AliLog.h"
123 #include "AliModule.h"
124 #include "AliRun.h"
125 #include "AliRunDigitizer.h"
126 #include "AliRunLoader.h"
127 #include "AliSimulation.h"
128 #include "AliVertexGenFile.h"
129 #include "AliCentralTrigger.h"
130
131 ClassImp(AliSimulation)
132
133
134 //_____________________________________________________________________________
135 AliSimulation::AliSimulation(const char* configFileName,
136                              const char* name, const char* title) :
137   TNamed(name, title),
138
139   fRunGeneration(kTRUE),
140   fRunSimulation(kTRUE),
141   fMakeSDigits("ALL"),
142   fMakeDigits("ALL"),
143   fMakeTrigger(""),
144   fMakeDigitsFromHits(""),
145   fWriteRawData(""),
146   fRawDataFileName(""),
147   fDeleteIntermediateFiles(kFALSE),
148   fStopOnError(kFALSE),
149
150   fNEvents(1),
151   fConfigFileName(configFileName),
152   fGAliceFileName("galice.root"),
153   fEventsPerFile(),
154   fBkgrdFileNames(NULL),
155   fAlignObjArray(NULL),
156   fUseBkgrdVertex(kTRUE),
157   fRegionOfInterest(kFALSE)
158 {
159 // create simulation object with default parameters
160
161   SetGAliceFile("galice.root");
162 }
163
164 //_____________________________________________________________________________
165 AliSimulation::AliSimulation(const AliSimulation& sim) :
166   TNamed(sim),
167
168   fRunGeneration(sim.fRunGeneration),
169   fRunSimulation(sim.fRunSimulation),
170   fMakeSDigits(sim.fMakeSDigits),
171   fMakeDigits(sim.fMakeDigits),
172   fMakeTrigger(sim.fMakeTrigger),
173   fMakeDigitsFromHits(sim.fMakeDigitsFromHits),
174   fWriteRawData(sim.fWriteRawData),
175   fRawDataFileName(""),
176   fDeleteIntermediateFiles(kFALSE),
177   fStopOnError(sim.fStopOnError),
178
179   fNEvents(sim.fNEvents),
180   fConfigFileName(sim.fConfigFileName),
181   fGAliceFileName(sim.fGAliceFileName),
182   fEventsPerFile(),
183   fBkgrdFileNames(NULL),
184   fAlignObjArray(NULL),
185   fUseBkgrdVertex(sim.fUseBkgrdVertex),
186   fRegionOfInterest(sim.fRegionOfInterest)
187 {
188 // copy constructor
189
190   for (Int_t i = 0; i < sim.fEventsPerFile.GetEntriesFast(); i++) {
191     if (!sim.fEventsPerFile[i]) continue;
192     fEventsPerFile.Add(sim.fEventsPerFile[i]->Clone());
193   }
194
195   fBkgrdFileNames = new TObjArray;
196   for (Int_t i = 0; i < sim.fBkgrdFileNames->GetEntriesFast(); i++) {
197     if (!sim.fBkgrdFileNames->At(i)) continue;
198     fBkgrdFileNames->Add(sim.fBkgrdFileNames->At(i)->Clone());
199   }
200 }
201
202 //_____________________________________________________________________________
203 AliSimulation& AliSimulation::operator = (const AliSimulation& sim)
204 {
205 // assignment operator
206
207   this->~AliSimulation();
208   new(this) AliSimulation(sim);
209   return *this;
210 }
211
212 //_____________________________________________________________________________
213 AliSimulation::~AliSimulation()
214 {
215 // clean up
216
217   fEventsPerFile.Delete();
218
219   if (fBkgrdFileNames) {
220     fBkgrdFileNames->Delete();
221     delete fBkgrdFileNames;
222   }
223 }
224
225
226 //_____________________________________________________________________________
227 void AliSimulation::SetNumberOfEvents(Int_t nEvents)
228 {
229 // set the number of events for one run
230
231   fNEvents = nEvents;
232 }
233
234 //_____________________________________________________________________________
235 void AliSimulation::SetConfigFile(const char* fileName)
236 {
237 // set the name of the config file
238
239   fConfigFileName = fileName;
240 }
241
242 //_____________________________________________________________________________
243 void AliSimulation::SetGAliceFile(const char* fileName)
244 {
245 // set the name of the galice file
246 // the path is converted to an absolute one if it is relative
247
248   fGAliceFileName = fileName;
249   if (!gSystem->IsAbsoluteFileName(fGAliceFileName)) {
250     char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
251                                                 fGAliceFileName);
252     fGAliceFileName = absFileName;
253     delete[] absFileName;
254   }
255
256   AliDebug(2, Form("galice file name set to %s", fileName));
257 }
258
259 //_____________________________________________________________________________
260 void AliSimulation::SetEventsPerFile(const char* detector, const char* type, 
261                                      Int_t nEvents)
262 {
263 // set the number of events per file for the given detector and data type
264 // ("Hits", "Summable Digits", "Digits", "Reconstructed Points" or "Tracks")
265
266   TNamed* obj = new TNamed(detector, type);
267   obj->SetUniqueID(nEvents);
268   fEventsPerFile.Add(obj);
269 }
270
271 //_____________________________________________________________________________
272 Bool_t AliSimulation::ApplyDisplacements(const char* fileName, const char* clArrayName)
273 {
274   // read collection of alignment objects (AliAlignObj derived) saved
275   // in the TClonesArray ClArrayName in the file fileName and apply
276   // them to the TGeo geometry passed as argument
277   //
278
279   TFile* inFile = TFile::Open(fileName,"READ");
280   if (!inFile || !inFile->IsOpen()) {
281     AliErrorClass(Form("Could not open file %s !",fileName));
282     return kFALSE;
283   }
284
285   TClonesArray* alObjArray = ((TClonesArray*) inFile->Get(clArrayName));
286   inFile->Close();
287   if (!alObjArray) {
288     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
289     return kFALSE;
290   }
291
292   return gAlice->ApplyDisplacements(alObjArray);
293
294 }
295
296 //_____________________________________________________________________________
297 Bool_t AliSimulation::ApplyDisplacements(AliCDBParam* param, AliCDBId& Id)
298 {
299   // read collection of alignment objects (AliAlignObj derived) saved
300   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
301   // param (to get the AliCDBStorage) and Id; apply the alignment objects
302   // to the TGeo geometry passed as argument
303   //
304
305   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
306   AliCDBEntry* entry = storage->Get(Id);
307   TClonesArray* AlObjArray = ((TClonesArray*) entry->GetObject());
308
309   return gAlice->ApplyDisplacements(AlObjArray);
310
311 }
312
313 //_____________________________________________________________________________
314 Bool_t AliSimulation::ApplyDisplacements(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
315 {
316   // read collection of alignment objects (AliAlignObj derived) saved
317   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
318   // param (to get the AliCDBStorage) and Id; apply the alignment objects
319   // to the TGeo geometry passed as argument
320   //
321
322   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
323   AliCDBId id(path, runnum, runnum, version, sversion);
324
325   return ApplyDisplacements(param, id);
326
327 }
328
329 //_____________________________________________________________________________
330 void AliSimulation::MergeWith(const char* fileName, Int_t nSignalPerBkgrd)
331 {
332 // add a file with background events for merging
333
334   TObjString* fileNameStr = new TObjString(fileName);
335   fileNameStr->SetUniqueID(nSignalPerBkgrd);
336   if (!fBkgrdFileNames) fBkgrdFileNames = new TObjArray;
337   fBkgrdFileNames->Add(fileNameStr);
338 }
339
340
341 //_____________________________________________________________________________
342 Bool_t AliSimulation::Run(Int_t nEvents)
343 {
344 // run the generation, simulation and digitization
345
346   // First check if we have any CDB storage set, because it is used 
347   // to retrieve the calibration and alignment constants
348
349   AliCDBManager* man = AliCDBManager::Instance();
350   if (!man->IsDefaultStorageSet())
351   {
352     AliWarning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
353     AliWarning("No default CDB storage set, so I will use $ALICE_ROOT");
354     AliWarning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
355     man->SetDefaultStorage("local://$ALICE_ROOT");
356   }  
357
358   if (nEvents > 0) fNEvents = nEvents;
359
360   // generation and simulation -> hits
361   if (fRunGeneration) {
362     if (!RunSimulation()) if (fStopOnError) return kFALSE;
363   }
364
365   // hits -> summable digits
366   if (!fMakeSDigits.IsNull()) {
367     if (!RunSDigitization(fMakeSDigits)) if (fStopOnError) return kFALSE;
368   }
369
370   // summable digits -> digits
371   if (!fMakeDigits.IsNull()) {
372     if (!RunDigitization(fMakeDigits, fMakeDigitsFromHits)) {
373       if (fStopOnError) return kFALSE;
374     }
375   }
376
377   // hits -> digits
378   if (!fMakeDigitsFromHits.IsNull()) {
379     if (fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
380       AliWarning(Form("Merging and direct creation of digits from hits " 
381                  "was selected for some detectors. "
382                  "No merging will be done for the following detectors: %s",
383                  fMakeDigitsFromHits.Data()));
384     }
385     if (!RunHitsDigitization(fMakeDigitsFromHits)) {
386       if (fStopOnError) return kFALSE;
387     }
388   }
389
390   // digits -> trigger
391   if (!fMakeTrigger.IsNull()) {
392     if (!RunTrigger(fMakeTrigger)) {
393       if (fStopOnError) return kFALSE;
394     }
395   }
396
397   // digits -> raw data
398   if (!fWriteRawData.IsNull()) {
399     if (!WriteRawData(fWriteRawData, fRawDataFileName, 
400                       fDeleteIntermediateFiles)) {
401       if (fStopOnError) return kFALSE;
402     }
403   }
404
405   return kTRUE;
406 }
407
408 //_____________________________________________________________________________
409 Bool_t AliSimulation::RunTrigger(const char* descriptors)
410 {
411   // run the trigger
412
413   TStopwatch stopwatch;
414   stopwatch.Start();
415
416   AliRunLoader* runLoader = LoadRun("READ");
417   if (!runLoader) return kFALSE;
418   TString des = descriptors;
419   // Load Descriptors
420   AliCentralTrigger* aCTP = new AliCentralTrigger( des );
421
422   // digits -> trigger
423   if( !aCTP->RunTrigger( runLoader ) ) {
424     if (fStopOnError) {
425       delete aCTP;
426       return kFALSE;
427     }
428   }
429
430 /*
431   // Process each event
432   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
433     AliInfo(Form("processing event %d", iEvent));
434     runLoader->GetEvent(iEvent);
435
436     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
437     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
438       AliModule* det = (AliModule*) detArray->At(iDet);
439       if (!det || !det->IsActive()) continue;
440       if (IsSelected(det->GetName(), detStr)) {
441         AliInfo(Form("triggering from digits for %s", det->GetName()));
442
443      //   AliLoader* loader = fLoader[iDet];
444      //   loader->LoadDigits("read");
445      //   TTree* digitsTree = loader->TreeD();
446      //   det->Trigger( digitsTree );
447      // or
448         AliTriggerDetector* tdet = det->CreateTriggerDetector();
449         TObjArray* detInp = dtrg->GetTriggerInputs();
450         for( Int_t i=0; i<detInp->GetEntriesFast(); i++ )
451                fInputs.AddLast( detInp->At(i) );
452
453         AliInfo(Form("Execution time for %s: R:%.2fs C:%.2fs",
454                 det->GetName(),stopwatchDet.RealTime(),stopwatchDet.CpuTime()));
455       }
456     }
457
458     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
459       AliError(Form("the following detectors were not found: %s",
460                     detStr.Data()));
461       if (fStopOnError) {
462          delete centralTP;
463          return kFALSE;
464       }
465     }
466
467     // Check trigger conditions
468     centralTP->TriggerConditions();
469
470     // Write trigger ????
471     centralTP->Write();
472
473   } */
474
475   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
476                stopwatch.RealTime(),stopwatch.CpuTime()));
477
478   delete aCTP;
479   delete runLoader;
480
481   return kTRUE;
482 }
483
484
485
486 //_____________________________________________________________________________
487 Bool_t AliSimulation::RunSimulation(Int_t nEvents)
488 {
489 // run the generation and simulation
490
491   TStopwatch stopwatch;
492   stopwatch.Start();
493
494   if (!gAlice) {
495     AliError("no gAlice object. Restart aliroot and try again.");
496     return kFALSE;
497   }
498   if (gAlice->Modules()->GetEntries() > 0) {
499     AliError("gAlice was already run. Restart aliroot and try again.");
500     return kFALSE;
501   }
502
503   AliInfo(Form("initializing gAlice with config file %s",
504           fConfigFileName.Data()));
505   StdoutToAliInfo(StderrToAliError(
506     gAlice->Init(fConfigFileName.Data());
507   ););
508
509   // Check if the array with alignment objects was
510   // provided by the user. If yes, apply the objects
511   // to the present TGeo geometry
512   if (fAlignObjArray) {
513     if (gGeoManager && gGeoManager->IsClosed()) {
514       if (gAlice->ApplyDisplacements(fAlignObjArray) == kFALSE) {
515         AliError("The application of misalignment failed! Restart aliroot and try again. ");
516         return kFALSE;
517       }
518     }
519     else {
520       AliError("Can't apply the misalignment! gGeoManager doesn't exist or it is still opened!");
521       return kFALSE;
522     }
523   }
524
525   // Export TGeo geometry
526   if (gGeoManager) gGeoManager->Export("geometry.root");
527
528   AliRunLoader* runLoader = gAlice->GetRunLoader();
529   if (!runLoader) {
530     AliError(Form("gAlice has no run loader object. "
531                   "Check your config file: %s", fConfigFileName.Data()));
532     return kFALSE;
533   }
534   SetGAliceFile(runLoader->GetFileName());
535
536   if (!gAlice->Generator()) {
537     AliError(Form("gAlice has no generator object. "
538                   "Check your config file: %s", fConfigFileName.Data()));
539     return kFALSE;
540   }
541   if (nEvents <= 0) nEvents = fNEvents;
542
543   // get vertex from background file in case of merging
544   if (fUseBkgrdVertex &&
545       fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
546     Int_t signalPerBkgrd = GetNSignalPerBkgrd(nEvents);
547     const char* fileName = ((TObjString*)
548                             (fBkgrdFileNames->At(0)))->GetName();
549     AliInfo(Form("The vertex will be taken from the background "
550                  "file %s with nSignalPerBackground = %d", 
551                  fileName, signalPerBkgrd));
552     AliVertexGenFile* vtxGen = new AliVertexGenFile(fileName, signalPerBkgrd);
553     gAlice->Generator()->SetVertexGenerator(vtxGen);
554   }
555
556   if (!fRunSimulation) {
557     gAlice->Generator()->SetTrackingFlag(0);
558   }
559
560   // set the number of events per file for given detectors and data types
561   for (Int_t i = 0; i < fEventsPerFile.GetEntriesFast(); i++) {
562     if (!fEventsPerFile[i]) continue;
563     const char* detName = fEventsPerFile[i]->GetName();
564     const char* typeName = fEventsPerFile[i]->GetTitle();
565     TString loaderName(detName);
566     loaderName += "Loader";
567     AliLoader* loader = runLoader->GetLoader(loaderName);
568     if (!loader) {
569       AliError(Form("RunSimulation", "no loader for %s found\n"
570                     "Number of events per file not set for %s %s", 
571                     detName, typeName, detName));
572       continue;
573     }
574     AliDataLoader* dataLoader = 
575       loader->GetDataLoader(typeName);
576     if (!dataLoader) {
577       AliError(Form("no data loader for %s found\n"
578                     "Number of events per file not set for %s %s", 
579                     typeName, detName, typeName));
580       continue;
581     }
582     dataLoader->SetNumberOfEventsPerFile(fEventsPerFile[i]->GetUniqueID());
583     AliDebug(1, Form("number of events per file set to %d for %s %s",
584                      fEventsPerFile[i]->GetUniqueID(), detName, typeName));
585   }
586
587   AliInfo("running gAlice");
588   StdoutToAliInfo(StderrToAliError(
589     gAlice->Run(nEvents);
590   ););
591
592   delete runLoader;
593
594   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
595                stopwatch.RealTime(),stopwatch.CpuTime()));
596
597   return kTRUE;
598 }
599
600 //_____________________________________________________________________________
601 Bool_t AliSimulation::RunSDigitization(const char* detectors)
602 {
603 // run the digitization and produce summable digits
604
605   TStopwatch stopwatch;
606   stopwatch.Start();
607
608   AliRunLoader* runLoader = LoadRun();
609   if (!runLoader) return kFALSE;
610
611   TString detStr = detectors;
612   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
613   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
614     AliModule* det = (AliModule*) detArray->At(iDet);
615     if (!det || !det->IsActive()) continue;
616     if (IsSelected(det->GetName(), detStr)) {
617       AliInfo(Form("creating summable digits for %s", det->GetName()));
618       TStopwatch stopwatchDet;
619       stopwatchDet.Start();
620       det->Hits2SDigits();
621       AliInfo(Form("Execution time for %s: R:%.2fs C:%.2fs",
622            det->GetName(),stopwatchDet.RealTime(),stopwatchDet.CpuTime()));
623     }
624   }
625
626   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
627     AliError(Form("the following detectors were not found: %s",
628                   detStr.Data()));
629     if (fStopOnError) return kFALSE;
630   }
631
632   delete runLoader;
633
634   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
635            stopwatch.RealTime(),stopwatch.CpuTime()));
636
637   return kTRUE;
638 }
639
640
641 //_____________________________________________________________________________
642 Bool_t AliSimulation::RunDigitization(const char* detectors, 
643                                       const char* excludeDetectors)
644 {
645 // run the digitization and produce digits from sdigits
646
647   TStopwatch stopwatch;
648   stopwatch.Start();
649
650   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
651   if (gAlice) delete gAlice;
652   gAlice = NULL;
653
654   Int_t nStreams = 1;
655   if (fBkgrdFileNames) nStreams = fBkgrdFileNames->GetEntriesFast() + 1;
656   Int_t signalPerBkgrd = GetNSignalPerBkgrd();
657   AliRunDigitizer* manager = new AliRunDigitizer(nStreams, signalPerBkgrd);
658   manager->SetInputStream(0, fGAliceFileName.Data());
659   for (Int_t iStream = 1; iStream < nStreams; iStream++) {
660     const char* fileName = ((TObjString*)
661                             (fBkgrdFileNames->At(iStream-1)))->GetName();
662     manager->SetInputStream(iStream, fileName);
663   }
664
665   TString detStr = detectors;
666   TString detExcl = excludeDetectors;
667   manager->GetInputStream(0)->ImportgAlice();
668   AliRunLoader* runLoader = 
669     AliRunLoader::GetRunLoader(manager->GetInputStream(0)->GetFolderName());
670   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
671   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
672     AliModule* det = (AliModule*) detArray->At(iDet);
673     if (!det || !det->IsActive()) continue;
674     if (IsSelected(det->GetName(), detStr) && 
675         !IsSelected(det->GetName(), detExcl)) {
676       AliDigitizer* digitizer = det->CreateDigitizer(manager);
677       if (!digitizer) {
678         AliError(Form("no digitizer for %s", det->GetName()));
679         if (fStopOnError) return kFALSE;
680       } else {
681         digitizer->SetRegionOfInterest(fRegionOfInterest);
682       }
683     }
684   }
685
686   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
687     AliError(Form("the following detectors were not found: %s", 
688                   detStr.Data()));
689     if (fStopOnError) return kFALSE;
690   }
691
692   if (!manager->GetListOfTasks()->IsEmpty()) {
693     AliInfo("executing digitization");
694     manager->Exec("");
695   }
696
697   delete manager;
698
699   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
700                stopwatch.RealTime(),stopwatch.CpuTime()));
701   
702   return kTRUE;
703 }
704
705 //_____________________________________________________________________________
706 Bool_t AliSimulation::RunHitsDigitization(const char* detectors)
707 {
708 // run the digitization and produce digits from hits
709
710   TStopwatch stopwatch;
711   stopwatch.Start();
712
713   AliRunLoader* runLoader = LoadRun("READ");
714   if (!runLoader) return kFALSE;
715
716   TString detStr = detectors;
717   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
718   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
719     AliModule* det = (AliModule*) detArray->At(iDet);
720     if (!det || !det->IsActive()) continue;
721     if (IsSelected(det->GetName(), detStr)) {
722       AliInfo(Form("creating digits from hits for %s", det->GetName()));
723       det->Hits2Digits();
724     }
725   }
726
727   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
728     AliError(Form("the following detectors were not found: %s", 
729                   detStr.Data()));
730     if (fStopOnError) return kFALSE;
731   }
732
733   delete runLoader;
734   //PH Temporary fix to avoid interference with the PHOS loder/getter
735   //PH The problem has to be solved in more general way 09/06/05
736
737   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
738                stopwatch.RealTime(),stopwatch.CpuTime()));
739
740   return kTRUE;
741 }
742
743 //_____________________________________________________________________________
744 Bool_t AliSimulation::WriteRawData(const char* detectors, 
745                                    const char* fileName,
746                                    Bool_t deleteIntermediateFiles)
747 {
748 // convert the digits to raw data
749 // First DDL raw data files for the given detectors are created.
750 // If a file name is given, the DDL files are then converted to a DATE file.
751 // If deleteIntermediateFiles is true, the DDL raw files are deleted 
752 // afterwards.
753 // If the file name has the extension ".root", the DATE file is converted
754 // to a root file.
755 // If deleteIntermediateFiles is true, the DATE file is deleted afterwards.
756
757   TStopwatch stopwatch;
758   stopwatch.Start();
759
760   if (!WriteRawFiles(detectors)) {
761     if (fStopOnError) return kFALSE;
762   }
763
764   TString dateFileName(fileName);
765   if (!dateFileName.IsNull()) {
766     Bool_t rootOutput = dateFileName.EndsWith(".root");
767     if (rootOutput) dateFileName += ".date";
768     if (!ConvertRawFilesToDate(dateFileName)) {
769       if (fStopOnError) return kFALSE;
770     }
771     if (deleteIntermediateFiles) {
772       AliRunLoader* runLoader = LoadRun("READ");
773       if (runLoader) for (Int_t iEvent = 0; 
774                           iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
775         char command[256];
776         sprintf(command, "rm -r raw%d", iEvent);
777         gSystem->Exec(command);
778       }
779     }
780
781     if (rootOutput) {
782       if (!ConvertDateToRoot(dateFileName, fileName)) {
783         if (fStopOnError) return kFALSE;
784       }
785       if (deleteIntermediateFiles) {
786         gSystem->Unlink(dateFileName);
787       }
788     }
789   }
790
791   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
792                stopwatch.RealTime(),stopwatch.CpuTime()));
793
794   return kTRUE;
795 }
796
797 //_____________________________________________________________________________
798 Bool_t AliSimulation::WriteRawFiles(const char* detectors)
799 {
800 // convert the digits to raw data DDL files
801
802   AliRunLoader* runLoader = LoadRun("READ");
803   if (!runLoader) return kFALSE;
804
805   // write raw data to DDL files
806   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
807     AliInfo(Form("processing event %d", iEvent));
808     runLoader->GetEvent(iEvent);
809     TString baseDir = gSystem->WorkingDirectory();
810     char dirName[256];
811     sprintf(dirName, "raw%d", iEvent);
812     gSystem->MakeDirectory(dirName);
813     if (!gSystem->ChangeDirectory(dirName)) {
814       AliError(Form("couldn't change to directory %s", dirName));
815       if (fStopOnError) return kFALSE; else continue;
816     }
817
818     TString detStr = detectors;
819     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
820     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
821       AliModule* det = (AliModule*) detArray->At(iDet);
822       if (!det || !det->IsActive()) continue;
823       if (IsSelected(det->GetName(), detStr)) {
824         AliInfo(Form("creating raw data from digits for %s", det->GetName()));
825         det->Digits2Raw();
826       }
827     }
828
829     gSystem->ChangeDirectory(baseDir);
830     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
831       AliError(Form("the following detectors were not found: %s", 
832                     detStr.Data()));
833       if (fStopOnError) return kFALSE;
834     }
835   }
836
837   delete runLoader;
838   return kTRUE;
839 }
840
841 //_____________________________________________________________________________
842 Bool_t AliSimulation::ConvertRawFilesToDate(const char* dateFileName)
843 {
844 // convert raw data DDL files to a DATE file with the program "dateStream"
845
846   char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
847   if (!path) {
848     AliError("the program dateStream was not found");
849     if (fStopOnError) return kFALSE;
850   } else {
851     delete[] path;
852   }
853
854   AliRunLoader* runLoader = LoadRun("READ");
855   if (!runLoader) return kFALSE;
856
857   AliInfo(Form("converting raw data DDL files to DATE file %s", dateFileName));
858   char command[256];
859   sprintf(command, "dateStream -o %s -# %d -C", 
860           dateFileName, runLoader->GetNumberOfEvents());
861   FILE* pipe = gSystem->OpenPipe(command, "w");
862
863   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
864     fprintf(pipe, "GDC\n");
865     Float_t ldc = 0;
866     Int_t prevLDC = -1;
867
868     // loop over detectors and DDLs
869     for (Int_t iDet = 0; iDet < kNDetectors; iDet++) {
870       for (Int_t iDDL = 0; iDDL < kDetectorDDLs[iDet]; iDDL++) {
871
872         Int_t ddlID = 0x100*iDet + iDDL;
873         Int_t ldcID = Int_t(ldc + 0.0001);
874         ldc += kDetectorLDCs[iDet] / kDetectorDDLs[iDet];
875
876         char rawFileName[256];
877         sprintf(rawFileName, "raw%d/%s_%d.ddl", 
878                 iEvent, kDetectors[iDet], ddlID);
879
880         // check existence and size of raw data file
881         FILE* file = fopen(rawFileName, "rb");
882         if (!file) continue;
883         fseek(file, 0, SEEK_END);
884         unsigned long size = ftell(file);
885         fclose(file);
886         if (!size) continue;
887
888         if (ldcID != prevLDC) {
889           fprintf(pipe, " LDC Id %d\n", ldcID);
890           prevLDC = ldcID;
891         }
892         fprintf(pipe, "  Equipment Id %d Payload %s\n", ddlID, rawFileName);
893       }
894     }
895   }
896
897   Int_t result = gSystem->ClosePipe(pipe);
898
899   delete runLoader;
900   return (result == 0);
901 }
902
903 //_____________________________________________________________________________
904 Bool_t AliSimulation::ConvertDateToRoot(const char* dateFileName,
905                                         const char* rootFileName)
906 {
907 // convert a DATE file to a root file with the program "alimdc"
908
909   // ALIMDC setup
910   const Int_t kDBSize = 1000000000;
911   const Int_t kTagDBSize = 1000000000;
912   const Bool_t kFilter = kFALSE;
913   const Int_t kCompression = 1;
914
915   char* path = gSystem->Which(gSystem->Getenv("PATH"), "alimdc");
916   if (!path) {
917     AliError("the program alimdc was not found");
918     if (fStopOnError) return kFALSE;
919   } else {
920     delete[] path;
921   }
922
923   AliInfo(Form("converting DATE file %s to root file %s", 
924                dateFileName, rootFileName));
925
926   gSystem->Exec("rm -rf /tmp/mdc1");
927   gSystem->Exec("rm -rf /tmp/mdc2");
928
929   gSystem->Exec("mkdir /tmp/mdc1");
930   gSystem->Exec("mkdir /tmp/mdc2");
931
932   char command[256];
933   sprintf(command, "alimdc %d %d %d %d %s", 
934           kDBSize, kTagDBSize, kFilter, kCompression, dateFileName);
935   Int_t result = gSystem->Exec(command);
936   sprintf(command, "mv /tmp/mdc1/*.root %s", rootFileName);
937   gSystem->Exec(command);
938   gSystem->Exec("rm -rf /tmp/mdc1");
939   gSystem->Exec("rm -rf /tmp/mdc2");
940
941   return (result == 0);
942 }
943
944
945 //_____________________________________________________________________________
946 AliRunLoader* AliSimulation::LoadRun(const char* mode) const
947 {
948 // delete existing run loaders, open a new one and load gAlice
949
950   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
951   AliRunLoader* runLoader = 
952     AliRunLoader::Open(fGAliceFileName.Data(), 
953                        AliConfig::GetDefaultEventFolderName(), mode);
954   if (!runLoader) {
955     AliError(Form("no run loader found in file %s", fGAliceFileName.Data()));
956     return NULL;
957   }
958   runLoader->LoadgAlice();
959   gAlice = runLoader->GetAliRun();
960   if (!gAlice) {
961     AliError(Form("no gAlice object found in file %s", 
962                   fGAliceFileName.Data()));
963     return NULL;
964   }
965   return runLoader;
966 }
967
968 //_____________________________________________________________________________
969 Int_t AliSimulation::GetNSignalPerBkgrd(Int_t nEvents) const
970 {
971 // get or calculate the number of signal events per background event
972
973   if (!fBkgrdFileNames) return 1;
974   Int_t nBkgrdFiles = fBkgrdFileNames->GetEntriesFast();
975   if (nBkgrdFiles == 0) return 1;
976
977   // get the number of signal events
978   if (nEvents <= 0) {
979     AliRunLoader* runLoader = 
980       AliRunLoader::Open(fGAliceFileName.Data(), "SIGNAL");
981     if (!runLoader) return 1;
982     nEvents = runLoader->GetNumberOfEvents();
983     delete runLoader;
984   }
985
986   Int_t result = 0;
987   for (Int_t iBkgrdFile = 0; iBkgrdFile < nBkgrdFiles; iBkgrdFile++) {
988     // get the number of background events
989     const char* fileName = ((TObjString*)
990                             (fBkgrdFileNames->At(iBkgrdFile)))->GetName();
991     AliRunLoader* runLoader = 
992       AliRunLoader::Open(fileName, "BKGRD");
993     if (!runLoader) continue;
994     Int_t nBkgrdEvents = runLoader->GetNumberOfEvents();
995     delete runLoader;
996
997     // get or calculate the number of signal per background events
998     Int_t nSignalPerBkgrd = fBkgrdFileNames->At(iBkgrdFile)->GetUniqueID();
999     if (nSignalPerBkgrd <= 0) {
1000       nSignalPerBkgrd = (nEvents-1) / nBkgrdEvents + 1;
1001     } else if (result && (result != nSignalPerBkgrd)) {
1002       AliInfo(Form("the number of signal events per background event "
1003                    "will be changed from %d to %d for stream %d", 
1004                    nSignalPerBkgrd, result, iBkgrdFile+1));
1005       nSignalPerBkgrd = result;
1006     }
1007
1008     if (!result) result = nSignalPerBkgrd;
1009     if (nSignalPerBkgrd * nBkgrdEvents < nEvents) {
1010       AliWarning(Form("not enough background events (%d) for %d signal events "
1011                       "using %d signal per background events for stream %d",
1012                       nBkgrdEvents, nEvents, nSignalPerBkgrd, iBkgrdFile+1));
1013     }
1014   }
1015
1016   return result;
1017 }
1018
1019 //_____________________________________________________________________________
1020 Bool_t AliSimulation::IsSelected(TString detName, TString& detectors) const
1021 {
1022 // check whether detName is contained in detectors
1023 // if yes, it is removed from detectors
1024
1025   // check if all detectors are selected
1026   if ((detectors.CompareTo("ALL") == 0) ||
1027       detectors.BeginsWith("ALL ") ||
1028       detectors.EndsWith(" ALL") ||
1029       detectors.Contains(" ALL ")) {
1030     detectors = "ALL";
1031     return kTRUE;
1032   }
1033
1034   // search for the given detector
1035   Bool_t result = kFALSE;
1036   if ((detectors.CompareTo(detName) == 0) ||
1037       detectors.BeginsWith(detName+" ") ||
1038       detectors.EndsWith(" "+detName) ||
1039       detectors.Contains(" "+detName+" ")) {
1040     detectors.ReplaceAll(detName, "");
1041     result = kTRUE;
1042   }
1043
1044   // clean up the detectors string
1045   while (detectors.Contains("  ")) detectors.ReplaceAll("  ", " ");
1046   while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
1047   while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
1048
1049   return result;
1050 }