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