Including TFile.h
[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   if (nEvents > 0) fNEvents = nEvents;
347
348   // generation and simulation -> hits
349   if (fRunGeneration) {
350     if (!RunSimulation()) if (fStopOnError) return kFALSE;
351   }
352
353   // hits -> summable digits
354   if (!fMakeSDigits.IsNull()) {
355     if (!RunSDigitization(fMakeSDigits)) if (fStopOnError) return kFALSE;
356   }
357
358   // summable digits -> digits
359   if (!fMakeDigits.IsNull()) {
360     if (!RunDigitization(fMakeDigits, fMakeDigitsFromHits)) {
361       if (fStopOnError) return kFALSE;
362     }
363   }
364
365   // hits -> digits
366   if (!fMakeDigitsFromHits.IsNull()) {
367     if (fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
368       AliWarning(Form("Merging and direct creation of digits from hits " 
369                  "was selected for some detectors. "
370                  "No merging will be done for the following detectors: %s",
371                  fMakeDigitsFromHits.Data()));
372     }
373     if (!RunHitsDigitization(fMakeDigitsFromHits)) {
374       if (fStopOnError) return kFALSE;
375     }
376   }
377
378   // digits -> trigger
379   if (!fMakeTrigger.IsNull()) {
380     if (!RunTrigger(fMakeTrigger)) {
381       if (fStopOnError) return kFALSE;
382     }
383   }
384
385   // digits -> raw data
386   if (!fWriteRawData.IsNull()) {
387     if (!WriteRawData(fWriteRawData, fRawDataFileName, 
388                       fDeleteIntermediateFiles)) {
389       if (fStopOnError) return kFALSE;
390     }
391   }
392
393   return kTRUE;
394 }
395
396 //_____________________________________________________________________________
397 Bool_t AliSimulation::RunTrigger(const char* descriptors)
398 {
399   // run the trigger
400
401   TStopwatch stopwatch;
402   stopwatch.Start();
403
404   AliRunLoader* runLoader = LoadRun("READ");
405   if (!runLoader) return kFALSE;
406   TString des = descriptors;
407   // Load Descriptors
408   AliCentralTrigger* aCTP = new AliCentralTrigger( des );
409
410   // digits -> trigger
411   if( !aCTP->RunTrigger( runLoader ) ) {
412     if (fStopOnError) {
413       delete aCTP;
414       return kFALSE;
415     }
416   }
417
418 /*
419   // Process each event
420   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
421     AliInfo(Form("processing event %d", iEvent));
422     runLoader->GetEvent(iEvent);
423
424     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
425     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
426       AliModule* det = (AliModule*) detArray->At(iDet);
427       if (!det || !det->IsActive()) continue;
428       if (IsSelected(det->GetName(), detStr)) {
429         AliInfo(Form("triggering from digits for %s", det->GetName()));
430
431      //   AliLoader* loader = fLoader[iDet];
432      //   loader->LoadDigits("read");
433      //   TTree* digitsTree = loader->TreeD();
434      //   det->Trigger( digitsTree );
435      // or
436         AliTriggerDetector* tdet = det->CreateTriggerDetector();
437         TObjArray* detInp = dtrg->GetTriggerInputs();
438         for( Int_t i=0; i<detInp->GetEntriesFast(); i++ )
439                fInputs.AddLast( detInp->At(i) );
440
441         AliInfo(Form("Execution time for %s: R:%.2fs C:%.2fs",
442                 det->GetName(),stopwatchDet.RealTime(),stopwatchDet.CpuTime()));
443       }
444     }
445
446     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
447       AliError(Form("the following detectors were not found: %s",
448                     detStr.Data()));
449       if (fStopOnError) {
450          delete centralTP;
451          return kFALSE;
452       }
453     }
454
455     // Check trigger conditions
456     centralTP->TriggerConditions();
457
458     // Write trigger ????
459     centralTP->Write();
460
461   } */
462
463   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
464                stopwatch.RealTime(),stopwatch.CpuTime()));
465
466   delete aCTP;
467   delete runLoader;
468
469   return kTRUE;
470 }
471
472
473
474 //_____________________________________________________________________________
475 Bool_t AliSimulation::RunSimulation(Int_t nEvents)
476 {
477 // run the generation and simulation
478
479   TStopwatch stopwatch;
480   stopwatch.Start();
481
482   if (!gAlice) {
483     AliError("no gAlice object. Restart aliroot and try again.");
484     return kFALSE;
485   }
486   if (gAlice->Modules()->GetEntries() > 0) {
487     AliError("gAlice was already run. Restart aliroot and try again.");
488     return kFALSE;
489   }
490
491   AliInfo(Form("initializing gAlice with config file %s",
492           fConfigFileName.Data()));
493   StdoutToAliInfo(StderrToAliError(
494     gAlice->Init(fConfigFileName.Data());
495   ););
496
497   // Check if the array with alignment objects was
498   // provided by the user. If yes, apply the objects
499   // to the present TGeo geometry
500   if (fAlignObjArray) {
501     if (gGeoManager && gGeoManager->IsClosed()) {
502       if (gAlice->ApplyDisplacements(fAlignObjArray) == kFALSE) {
503         AliError("The application of misalignment failed! Restart aliroot and try again. ");
504         return kFALSE;
505       }
506     }
507     else {
508       AliError("Can't apply the misalignment! gGeoManager doesn't exist or it is still opened!");
509       return kFALSE;
510     }
511   }
512
513   // Export TGeo geometry
514   if (gGeoManager) gGeoManager->Export("geometry.root");
515
516   AliRunLoader* runLoader = gAlice->GetRunLoader();
517   if (!runLoader) {
518     AliError(Form("gAlice has no run loader object. "
519                   "Check your config file: %s", fConfigFileName.Data()));
520     return kFALSE;
521   }
522   SetGAliceFile(runLoader->GetFileName());
523
524   if (!gAlice->Generator()) {
525     AliError(Form("gAlice has no generator object. "
526                   "Check your config file: %s", fConfigFileName.Data()));
527     return kFALSE;
528   }
529   if (nEvents <= 0) nEvents = fNEvents;
530
531   // get vertex from background file in case of merging
532   if (fUseBkgrdVertex &&
533       fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
534     Int_t signalPerBkgrd = GetNSignalPerBkgrd(nEvents);
535     const char* fileName = ((TObjString*)
536                             (fBkgrdFileNames->At(0)))->GetName();
537     AliInfo(Form("The vertex will be taken from the background "
538                  "file %s with nSignalPerBackground = %d", 
539                  fileName, signalPerBkgrd));
540     AliVertexGenFile* vtxGen = new AliVertexGenFile(fileName, signalPerBkgrd);
541     gAlice->Generator()->SetVertexGenerator(vtxGen);
542   }
543
544   if (!fRunSimulation) {
545     gAlice->Generator()->SetTrackingFlag(0);
546   }
547
548   // set the number of events per file for given detectors and data types
549   for (Int_t i = 0; i < fEventsPerFile.GetEntriesFast(); i++) {
550     if (!fEventsPerFile[i]) continue;
551     const char* detName = fEventsPerFile[i]->GetName();
552     const char* typeName = fEventsPerFile[i]->GetTitle();
553     TString loaderName(detName);
554     loaderName += "Loader";
555     AliLoader* loader = runLoader->GetLoader(loaderName);
556     if (!loader) {
557       AliError(Form("RunSimulation", "no loader for %s found\n"
558                     "Number of events per file not set for %s %s", 
559                     detName, typeName, detName));
560       continue;
561     }
562     AliDataLoader* dataLoader = 
563       loader->GetDataLoader(typeName);
564     if (!dataLoader) {
565       AliError(Form("no data loader for %s found\n"
566                     "Number of events per file not set for %s %s", 
567                     typeName, detName, typeName));
568       continue;
569     }
570     dataLoader->SetNumberOfEventsPerFile(fEventsPerFile[i]->GetUniqueID());
571     AliDebug(1, Form("number of events per file set to %d for %s %s",
572                      fEventsPerFile[i]->GetUniqueID(), detName, typeName));
573   }
574
575   AliInfo("running gAlice");
576   StdoutToAliInfo(StderrToAliError(
577     gAlice->Run(nEvents);
578   ););
579
580   delete runLoader;
581
582   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
583                stopwatch.RealTime(),stopwatch.CpuTime()));
584
585   return kTRUE;
586 }
587
588 //_____________________________________________________________________________
589 Bool_t AliSimulation::RunSDigitization(const char* detectors)
590 {
591 // run the digitization and produce summable digits
592
593   TStopwatch stopwatch;
594   stopwatch.Start();
595
596   AliRunLoader* runLoader = LoadRun();
597   if (!runLoader) return kFALSE;
598
599   TString detStr = detectors;
600   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
601   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
602     AliModule* det = (AliModule*) detArray->At(iDet);
603     if (!det || !det->IsActive()) continue;
604     if (IsSelected(det->GetName(), detStr)) {
605       AliInfo(Form("creating summable digits for %s", det->GetName()));
606       TStopwatch stopwatchDet;
607       stopwatchDet.Start();
608       det->Hits2SDigits();
609       AliInfo(Form("Execution time for %s: R:%.2fs C:%.2fs",
610            det->GetName(),stopwatchDet.RealTime(),stopwatchDet.CpuTime()));
611     }
612   }
613
614   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
615     AliError(Form("the following detectors were not found: %s",
616                   detStr.Data()));
617     if (fStopOnError) return kFALSE;
618   }
619
620   delete runLoader;
621
622   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
623            stopwatch.RealTime(),stopwatch.CpuTime()));
624
625   return kTRUE;
626 }
627
628
629 //_____________________________________________________________________________
630 Bool_t AliSimulation::RunDigitization(const char* detectors, 
631                                       const char* excludeDetectors)
632 {
633 // run the digitization and produce digits from sdigits
634
635   TStopwatch stopwatch;
636   stopwatch.Start();
637
638   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
639   if (gAlice) delete gAlice;
640   gAlice = NULL;
641
642   Int_t nStreams = 1;
643   if (fBkgrdFileNames) nStreams = fBkgrdFileNames->GetEntriesFast() + 1;
644   Int_t signalPerBkgrd = GetNSignalPerBkgrd();
645   AliRunDigitizer* manager = new AliRunDigitizer(nStreams, signalPerBkgrd);
646   manager->SetInputStream(0, fGAliceFileName.Data());
647   for (Int_t iStream = 1; iStream < nStreams; iStream++) {
648     const char* fileName = ((TObjString*)
649                             (fBkgrdFileNames->At(iStream-1)))->GetName();
650     manager->SetInputStream(iStream, fileName);
651   }
652
653   TString detStr = detectors;
654   TString detExcl = excludeDetectors;
655   manager->GetInputStream(0)->ImportgAlice();
656   AliRunLoader* runLoader = 
657     AliRunLoader::GetRunLoader(manager->GetInputStream(0)->GetFolderName());
658   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
659   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
660     AliModule* det = (AliModule*) detArray->At(iDet);
661     if (!det || !det->IsActive()) continue;
662     if (IsSelected(det->GetName(), detStr) && 
663         !IsSelected(det->GetName(), detExcl)) {
664       AliDigitizer* digitizer = det->CreateDigitizer(manager);
665       if (!digitizer) {
666         AliError(Form("no digitizer for %s", det->GetName()));
667         if (fStopOnError) return kFALSE;
668       } else {
669         digitizer->SetRegionOfInterest(fRegionOfInterest);
670       }
671     }
672   }
673
674   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
675     AliError(Form("the following detectors were not found: %s", 
676                   detStr.Data()));
677     if (fStopOnError) return kFALSE;
678   }
679
680   if (!manager->GetListOfTasks()->IsEmpty()) {
681     AliInfo("executing digitization");
682     manager->Exec("");
683   }
684
685   delete manager;
686
687   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
688                stopwatch.RealTime(),stopwatch.CpuTime()));
689   
690   return kTRUE;
691 }
692
693 //_____________________________________________________________________________
694 Bool_t AliSimulation::RunHitsDigitization(const char* detectors)
695 {
696 // run the digitization and produce digits from hits
697
698   TStopwatch stopwatch;
699   stopwatch.Start();
700
701   AliRunLoader* runLoader = LoadRun("READ");
702   if (!runLoader) return kFALSE;
703
704   TString detStr = detectors;
705   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
706   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
707     AliModule* det = (AliModule*) detArray->At(iDet);
708     if (!det || !det->IsActive()) continue;
709     if (IsSelected(det->GetName(), detStr)) {
710       AliInfo(Form("creating digits from hits for %s", det->GetName()));
711       det->Hits2Digits();
712     }
713   }
714
715   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
716     AliError(Form("the following detectors were not found: %s", 
717                   detStr.Data()));
718     if (fStopOnError) return kFALSE;
719   }
720
721   delete runLoader;
722   //PH Temporary fix to avoid interference with the PHOS loder/getter
723   //PH The problem has to be solved in more general way 09/06/05
724
725   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
726                stopwatch.RealTime(),stopwatch.CpuTime()));
727
728   return kTRUE;
729 }
730
731 //_____________________________________________________________________________
732 Bool_t AliSimulation::WriteRawData(const char* detectors, 
733                                    const char* fileName,
734                                    Bool_t deleteIntermediateFiles)
735 {
736 // convert the digits to raw data
737 // First DDL raw data files for the given detectors are created.
738 // If a file name is given, the DDL files are then converted to a DATE file.
739 // If deleteIntermediateFiles is true, the DDL raw files are deleted 
740 // afterwards.
741 // If the file name has the extension ".root", the DATE file is converted
742 // to a root file.
743 // If deleteIntermediateFiles is true, the DATE file is deleted afterwards.
744
745   TStopwatch stopwatch;
746   stopwatch.Start();
747
748   if (!WriteRawFiles(detectors)) {
749     if (fStopOnError) return kFALSE;
750   }
751
752   TString dateFileName(fileName);
753   if (!dateFileName.IsNull()) {
754     Bool_t rootOutput = dateFileName.EndsWith(".root");
755     if (rootOutput) dateFileName += ".date";
756     if (!ConvertRawFilesToDate(dateFileName)) {
757       if (fStopOnError) return kFALSE;
758     }
759     if (deleteIntermediateFiles) {
760       AliRunLoader* runLoader = LoadRun("READ");
761       if (runLoader) for (Int_t iEvent = 0; 
762                           iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
763         char command[256];
764         sprintf(command, "rm -r raw%d", iEvent);
765         gSystem->Exec(command);
766       }
767     }
768
769     if (rootOutput) {
770       if (!ConvertDateToRoot(dateFileName, fileName)) {
771         if (fStopOnError) return kFALSE;
772       }
773       if (deleteIntermediateFiles) {
774         gSystem->Unlink(dateFileName);
775       }
776     }
777   }
778
779   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
780                stopwatch.RealTime(),stopwatch.CpuTime()));
781
782   return kTRUE;
783 }
784
785 //_____________________________________________________________________________
786 Bool_t AliSimulation::WriteRawFiles(const char* detectors)
787 {
788 // convert the digits to raw data DDL files
789
790   AliRunLoader* runLoader = LoadRun("READ");
791   if (!runLoader) return kFALSE;
792
793   // write raw data to DDL files
794   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
795     AliInfo(Form("processing event %d", iEvent));
796     runLoader->GetEvent(iEvent);
797     TString baseDir = gSystem->WorkingDirectory();
798     char dirName[256];
799     sprintf(dirName, "raw%d", iEvent);
800     gSystem->MakeDirectory(dirName);
801     if (!gSystem->ChangeDirectory(dirName)) {
802       AliError(Form("couldn't change to directory %s", dirName));
803       if (fStopOnError) return kFALSE; else continue;
804     }
805
806     TString detStr = detectors;
807     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
808     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
809       AliModule* det = (AliModule*) detArray->At(iDet);
810       if (!det || !det->IsActive()) continue;
811       if (IsSelected(det->GetName(), detStr)) {
812         AliInfo(Form("creating raw data from digits for %s", det->GetName()));
813         det->Digits2Raw();
814       }
815     }
816
817     gSystem->ChangeDirectory(baseDir);
818     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
819       AliError(Form("the following detectors were not found: %s", 
820                     detStr.Data()));
821       if (fStopOnError) return kFALSE;
822     }
823   }
824
825   delete runLoader;
826   return kTRUE;
827 }
828
829 //_____________________________________________________________________________
830 Bool_t AliSimulation::ConvertRawFilesToDate(const char* dateFileName)
831 {
832 // convert raw data DDL files to a DATE file with the program "dateStream"
833
834   char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
835   if (!path) {
836     AliError("the program dateStream was not found");
837     if (fStopOnError) return kFALSE;
838   } else {
839     delete[] path;
840   }
841
842   AliRunLoader* runLoader = LoadRun("READ");
843   if (!runLoader) return kFALSE;
844
845   AliInfo(Form("converting raw data DDL files to DATE file %s", dateFileName));
846   char command[256];
847   sprintf(command, "dateStream -o %s -# %d -C", 
848           dateFileName, runLoader->GetNumberOfEvents());
849   FILE* pipe = gSystem->OpenPipe(command, "w");
850
851   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
852     fprintf(pipe, "GDC\n");
853     Float_t ldc = 0;
854     Int_t prevLDC = -1;
855
856     // loop over detectors and DDLs
857     for (Int_t iDet = 0; iDet < kNDetectors; iDet++) {
858       for (Int_t iDDL = 0; iDDL < kDetectorDDLs[iDet]; iDDL++) {
859
860         Int_t ddlID = 0x100*iDet + iDDL;
861         Int_t ldcID = Int_t(ldc + 0.0001);
862         ldc += kDetectorLDCs[iDet] / kDetectorDDLs[iDet];
863
864         char rawFileName[256];
865         sprintf(rawFileName, "raw%d/%s_%d.ddl", 
866                 iEvent, kDetectors[iDet], ddlID);
867
868         // check existence and size of raw data file
869         FILE* file = fopen(rawFileName, "rb");
870         if (!file) continue;
871         fseek(file, 0, SEEK_END);
872         unsigned long size = ftell(file);
873         fclose(file);
874         if (!size) continue;
875
876         if (ldcID != prevLDC) {
877           fprintf(pipe, " LDC Id %d\n", ldcID);
878           prevLDC = ldcID;
879         }
880         fprintf(pipe, "  Equipment Id %d Payload %s\n", ddlID, rawFileName);
881       }
882     }
883   }
884
885   Int_t result = gSystem->ClosePipe(pipe);
886
887   delete runLoader;
888   return (result == 0);
889 }
890
891 //_____________________________________________________________________________
892 Bool_t AliSimulation::ConvertDateToRoot(const char* dateFileName,
893                                         const char* rootFileName)
894 {
895 // convert a DATE file to a root file with the program "alimdc"
896
897   // ALIMDC setup
898   const Int_t kDBSize = 1000000000;
899   const Int_t kTagDBSize = 1000000000;
900   const Bool_t kFilter = kFALSE;
901   const Int_t kCompression = 1;
902
903   char* path = gSystem->Which(gSystem->Getenv("PATH"), "alimdc");
904   if (!path) {
905     AliError("the program alimdc was not found");
906     if (fStopOnError) return kFALSE;
907   } else {
908     delete[] path;
909   }
910
911   AliInfo(Form("converting DATE file %s to root file %s", 
912                dateFileName, rootFileName));
913
914   gSystem->Exec("rm -rf /tmp/mdc1");
915   gSystem->Exec("rm -rf /tmp/mdc2");
916
917   gSystem->Exec("mkdir /tmp/mdc1");
918   gSystem->Exec("mkdir /tmp/mdc2");
919
920   char command[256];
921   sprintf(command, "alimdc %d %d %d %d %s", 
922           kDBSize, kTagDBSize, kFilter, kCompression, dateFileName);
923   Int_t result = gSystem->Exec(command);
924   sprintf(command, "mv /tmp/mdc1/*.root %s", rootFileName);
925   gSystem->Exec(command);
926   gSystem->Exec("rm -rf /tmp/mdc1");
927   gSystem->Exec("rm -rf /tmp/mdc2");
928
929   return (result == 0);
930 }
931
932
933 //_____________________________________________________________________________
934 AliRunLoader* AliSimulation::LoadRun(const char* mode) const
935 {
936 // delete existing run loaders, open a new one and load gAlice
937
938   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
939   AliRunLoader* runLoader = 
940     AliRunLoader::Open(fGAliceFileName.Data(), 
941                        AliConfig::GetDefaultEventFolderName(), mode);
942   if (!runLoader) {
943     AliError(Form("no run loader found in file %s", fGAliceFileName.Data()));
944     return NULL;
945   }
946   runLoader->LoadgAlice();
947   gAlice = runLoader->GetAliRun();
948   if (!gAlice) {
949     AliError(Form("no gAlice object found in file %s", 
950                   fGAliceFileName.Data()));
951     return NULL;
952   }
953   return runLoader;
954 }
955
956 //_____________________________________________________________________________
957 Int_t AliSimulation::GetNSignalPerBkgrd(Int_t nEvents) const
958 {
959 // get or calculate the number of signal events per background event
960
961   if (!fBkgrdFileNames) return 1;
962   Int_t nBkgrdFiles = fBkgrdFileNames->GetEntriesFast();
963   if (nBkgrdFiles == 0) return 1;
964
965   // get the number of signal events
966   if (nEvents <= 0) {
967     AliRunLoader* runLoader = 
968       AliRunLoader::Open(fGAliceFileName.Data(), "SIGNAL");
969     if (!runLoader) return 1;
970     nEvents = runLoader->GetNumberOfEvents();
971     delete runLoader;
972   }
973
974   Int_t result = 0;
975   for (Int_t iBkgrdFile = 0; iBkgrdFile < nBkgrdFiles; iBkgrdFile++) {
976     // get the number of background events
977     const char* fileName = ((TObjString*)
978                             (fBkgrdFileNames->At(iBkgrdFile)))->GetName();
979     AliRunLoader* runLoader = 
980       AliRunLoader::Open(fileName, "BKGRD");
981     if (!runLoader) continue;
982     Int_t nBkgrdEvents = runLoader->GetNumberOfEvents();
983     delete runLoader;
984
985     // get or calculate the number of signal per background events
986     Int_t nSignalPerBkgrd = fBkgrdFileNames->At(iBkgrdFile)->GetUniqueID();
987     if (nSignalPerBkgrd <= 0) {
988       nSignalPerBkgrd = (nEvents-1) / nBkgrdEvents + 1;
989     } else if (result && (result != nSignalPerBkgrd)) {
990       AliInfo(Form("the number of signal events per background event "
991                    "will be changed from %d to %d for stream %d", 
992                    nSignalPerBkgrd, result, iBkgrdFile+1));
993       nSignalPerBkgrd = result;
994     }
995
996     if (!result) result = nSignalPerBkgrd;
997     if (nSignalPerBkgrd * nBkgrdEvents < nEvents) {
998       AliWarning(Form("not enough background events (%d) for %d signal events "
999                       "using %d signal per background events for stream %d",
1000                       nBkgrdEvents, nEvents, nSignalPerBkgrd, iBkgrdFile+1));
1001     }
1002   }
1003
1004   return result;
1005 }
1006
1007 //_____________________________________________________________________________
1008 Bool_t AliSimulation::IsSelected(TString detName, TString& detectors) const
1009 {
1010 // check whether detName is contained in detectors
1011 // if yes, it is removed from detectors
1012
1013   // check if all detectors are selected
1014   if ((detectors.CompareTo("ALL") == 0) ||
1015       detectors.BeginsWith("ALL ") ||
1016       detectors.EndsWith(" ALL") ||
1017       detectors.Contains(" ALL ")) {
1018     detectors = "ALL";
1019     return kTRUE;
1020   }
1021
1022   // search for the given detector
1023   Bool_t result = kFALSE;
1024   if ((detectors.CompareTo(detName) == 0) ||
1025       detectors.BeginsWith(detName+" ") ||
1026       detectors.EndsWith(" "+detName) ||
1027       detectors.Contains(" "+detName+" ")) {
1028     detectors.ReplaceAll(detName, "");
1029     result = kTRUE;
1030   }
1031
1032   // clean up the detectors string
1033   while (detectors.Contains("  ")) detectors.ReplaceAll("  ", " ");
1034   while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
1035   while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
1036
1037   return result;
1038 }