b0f5284837dc8683036e588066e07a3f903b80f1
[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 <TObjString.h>
109 #include <TStopwatch.h>
110 #include <TSystem.h>
111
112 #include "AliLog.h"
113 #include "AliDigitizer.h"
114 #include "AliGenerator.h"
115 #include "AliModule.h"
116 #include "AliRun.h"
117 #include "AliRunDigitizer.h"
118 #include "AliRunLoader.h"
119 #include "AliSimulation.h"
120 #include "AliVertexGenFile.h"
121
122 ClassImp(AliSimulation)
123
124
125 //_____________________________________________________________________________
126 AliSimulation::AliSimulation(const char* configFileName,
127                              const char* name, const char* title) :
128   TNamed(name, title),
129
130   fRunGeneration(kTRUE),
131   fRunSimulation(kTRUE),
132   fMakeSDigits("ALL"),
133   fMakeDigits("ALL"),
134   fMakeDigitsFromHits(""),
135   fWriteRawData(""),
136   fRawDataFileName(""),
137   fDeleteIntermediateFiles(kFALSE),
138   fStopOnError(kFALSE),
139
140   fNEvents(1),
141   fConfigFileName(configFileName),
142   fGAliceFileName("galice.root"),
143   fEventsPerFile(),
144   fBkgrdFileNames(NULL),
145   fUseBkgrdVertex(kTRUE),
146   fRegionOfInterest(kFALSE)
147 {
148 // create simulation object with default parameters
149
150   SetGAliceFile("galice.root");
151 }
152
153 //_____________________________________________________________________________
154 AliSimulation::AliSimulation(const AliSimulation& sim) :
155   TNamed(sim),
156
157   fRunGeneration(sim.fRunGeneration),
158   fRunSimulation(sim.fRunSimulation),
159   fMakeSDigits(sim.fMakeSDigits),
160   fMakeDigits(sim.fMakeDigits),
161   fMakeDigitsFromHits(sim.fMakeDigitsFromHits),
162   fWriteRawData(sim.fWriteRawData),
163   fRawDataFileName(""),
164   fDeleteIntermediateFiles(kFALSE),
165   fStopOnError(sim.fStopOnError),
166
167   fNEvents(sim.fNEvents),
168   fConfigFileName(sim.fConfigFileName),
169   fGAliceFileName(sim.fGAliceFileName),
170   fEventsPerFile(),
171   fBkgrdFileNames(NULL),
172   fUseBkgrdVertex(sim.fUseBkgrdVertex),
173   fRegionOfInterest(sim.fRegionOfInterest)
174 {
175 // copy constructor
176
177   for (Int_t i = 0; i < sim.fEventsPerFile.GetEntriesFast(); i++) {
178     if (!sim.fEventsPerFile[i]) continue;
179     fEventsPerFile.Add(sim.fEventsPerFile[i]->Clone());
180   }
181
182   fBkgrdFileNames = new TObjArray;
183   for (Int_t i = 0; i < sim.fBkgrdFileNames->GetEntriesFast(); i++) {
184     if (!sim.fBkgrdFileNames->At(i)) continue;
185     fBkgrdFileNames->Add(sim.fBkgrdFileNames->At(i)->Clone());
186   }
187 }
188
189 //_____________________________________________________________________________
190 AliSimulation& AliSimulation::operator = (const AliSimulation& sim)
191 {
192 // assignment operator
193
194   this->~AliSimulation();
195   new(this) AliSimulation(sim);
196   return *this;
197 }
198
199 //_____________________________________________________________________________
200 AliSimulation::~AliSimulation()
201 {
202 // clean up
203
204   fEventsPerFile.Delete();
205
206   if (fBkgrdFileNames) {
207     fBkgrdFileNames->Delete();
208     delete fBkgrdFileNames;
209   }
210 }
211
212
213 //_____________________________________________________________________________
214 void AliSimulation::SetNumberOfEvents(Int_t nEvents)
215 {
216 // set the number of events for one run
217
218   fNEvents = nEvents;
219 }
220
221 //_____________________________________________________________________________
222 void AliSimulation::SetConfigFile(const char* fileName)
223 {
224 // set the name of the config file
225
226   fConfigFileName = fileName;
227 }
228
229 //_____________________________________________________________________________
230 void AliSimulation::SetGAliceFile(const char* fileName)
231 {
232 // set the name of the galice file
233 // the path is converted to an absolute one if it is relative
234
235   fGAliceFileName = fileName;
236   if (!gSystem->IsAbsoluteFileName(fGAliceFileName)) {
237     char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
238                                                 fGAliceFileName);
239     fGAliceFileName = absFileName;
240     delete[] absFileName;
241   }
242
243   AliDebug(2, Form("galice file name set to %s", fileName));
244 }
245
246 //_____________________________________________________________________________
247 void AliSimulation::SetEventsPerFile(const char* detector, const char* type, 
248                                      Int_t nEvents)
249 {
250 // set the number of events per file for the given detector and data type
251 // ("Hits", "Summable Digits", "Digits", "Reconstructed Points" or "Tracks")
252
253   TNamed* obj = new TNamed(detector, type);
254   obj->SetUniqueID(nEvents);
255   fEventsPerFile.Add(obj);
256 }
257
258 //_____________________________________________________________________________
259 void AliSimulation::MergeWith(const char* fileName, Int_t nSignalPerBkgrd)
260 {
261 // add a file with background events for merging
262
263   TObjString* fileNameStr = new TObjString(fileName);
264   fileNameStr->SetUniqueID(nSignalPerBkgrd);
265   if (!fBkgrdFileNames) fBkgrdFileNames = new TObjArray;
266   fBkgrdFileNames->Add(fileNameStr);
267 }
268
269
270 //_____________________________________________________________________________
271 Bool_t AliSimulation::Run(Int_t nEvents)
272 {
273 // run the generation, simulation and digitization
274
275   if (nEvents > 0) fNEvents = nEvents;
276
277   // generation and simulation -> hits
278   if (fRunGeneration) {
279     if (!RunSimulation()) if (fStopOnError) return kFALSE;
280   }
281
282   // hits -> summable digits
283   if (!fMakeSDigits.IsNull()) {
284     if (!RunSDigitization(fMakeSDigits)) if (fStopOnError) return kFALSE;
285   }
286
287   // summable digits -> digits
288   if (!fMakeDigits.IsNull()) {
289     if (!RunDigitization(fMakeDigits, fMakeDigitsFromHits)) {
290       if (fStopOnError) return kFALSE;
291     }
292   }
293
294   // hits -> digits
295   if (!fMakeDigitsFromHits.IsNull()) {
296     if (fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
297       AliWarning(Form("Merging and direct creation of digits from hits " 
298                  "was selected for some detectors. "
299                  "No merging will be done for the following detectors: %s",
300                  fMakeDigitsFromHits.Data()));
301     }
302     if (!RunHitsDigitization(fMakeDigitsFromHits)) {
303       if (fStopOnError) return kFALSE;
304     }
305   }
306
307   // digits -> raw data
308   if (!fWriteRawData.IsNull()) {
309     if (!WriteRawData(fWriteRawData, fRawDataFileName, 
310                       fDeleteIntermediateFiles)) {
311       if (fStopOnError) return kFALSE;
312     }
313   }
314
315   return kTRUE;
316 }
317
318 //_____________________________________________________________________________
319 Bool_t AliSimulation::RunSimulation(Int_t nEvents)
320 {
321 // run the generation and simulation
322
323   TStopwatch stopwatch;
324   stopwatch.Start();
325
326   if (!gAlice) {
327     AliError("no gAlice object. Restart aliroot and try again.");
328     return kFALSE;
329   }
330   if (gAlice->Modules()->GetEntries() > 0) {
331     AliError("gAlice was already run. Restart aliroot and try again.");
332     return kFALSE;
333   }
334
335   AliInfo(Form("initializing gAlice with config file %s",
336           fConfigFileName.Data()));
337   StdoutToAliInfo(StderrToAliError(
338     gAlice->Init(fConfigFileName.Data());
339   ););
340   AliRunLoader* runLoader = gAlice->GetRunLoader();
341   if (!runLoader) {
342     AliError(Form("gAlice has no run loader object. "
343                   "Check your config file: %s", fConfigFileName.Data()));
344     return kFALSE;
345   }
346   SetGAliceFile(runLoader->GetFileName());
347
348   if (!gAlice->Generator()) {
349     AliError(Form("gAlice has no generator object. "
350                   "Check your config file: %s", fConfigFileName.Data()));
351     return kFALSE;
352   }
353   if (nEvents <= 0) nEvents = fNEvents;
354
355   // get vertex from background file in case of merging
356   if (fUseBkgrdVertex &&
357       fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
358     Int_t signalPerBkgrd = GetNSignalPerBkgrd(nEvents);
359     const char* fileName = ((TObjString*)
360                             (fBkgrdFileNames->At(0)))->GetName();
361     AliInfo(Form("The vertex will be taken from the background "
362                  "file %s with nSignalPerBackground = %d", 
363                  fileName, signalPerBkgrd));
364     AliVertexGenFile* vtxGen = new AliVertexGenFile(fileName, signalPerBkgrd);
365     gAlice->Generator()->SetVertexGenerator(vtxGen);
366   }
367
368   if (!fRunSimulation) {
369     gAlice->Generator()->SetTrackingFlag(0);
370   }
371
372   // set the number of events per file for given detectors and data types
373   for (Int_t i = 0; i < fEventsPerFile.GetEntriesFast(); i++) {
374     if (!fEventsPerFile[i]) continue;
375     const char* detName = fEventsPerFile[i]->GetName();
376     const char* typeName = fEventsPerFile[i]->GetTitle();
377     TString loaderName(detName);
378     loaderName += "Loader";
379     AliLoader* loader = runLoader->GetLoader(loaderName);
380     if (!loader) {
381       AliError(Form("RunSimulation", "no loader for %s found\n"
382                     "Number of events per file not set for %s %s", 
383                     detName, typeName, detName));
384       continue;
385     }
386     AliDataLoader* dataLoader = 
387       loader->GetDataLoader(typeName);
388     if (!dataLoader) {
389       AliError(Form("no data loader for %s found\n"
390                     "Number of events per file not set for %s %s", 
391                     typeName, detName, typeName));
392       continue;
393     }
394     dataLoader->SetNumberOfEventsPerFile(fEventsPerFile[i]->GetUniqueID());
395     AliDebug(1, Form("number of events per file set to %d for %s %s",
396                      fEventsPerFile[i]->GetUniqueID(), detName, typeName));
397   }
398
399   AliInfo("running gAlice");
400   StdoutToAliInfo(StderrToAliError(
401     gAlice->Run(nEvents);
402   ););
403
404   delete runLoader;
405
406   AliInfo("execution time:");
407   StdoutToAliInfo(stopwatch.Print(););
408
409   return kTRUE;
410 }
411
412 //_____________________________________________________________________________
413 Bool_t AliSimulation::RunSDigitization(const char* detectors)
414 {
415 // run the digitization and produce summable digits
416
417   TStopwatch stopwatch;
418   stopwatch.Start();
419
420   AliRunLoader* runLoader = LoadRun();
421   if (!runLoader) return kFALSE;
422
423   TString detStr = detectors;
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("creating summable digits for %s", det->GetName()));
430       TStopwatch stopwatchDet;
431       stopwatchDet.Start();
432       det->Hits2SDigits();
433       AliInfo(Form("execution time for %s:", det->GetName()));
434       StdoutToAliInfo(stopwatchDet.Print(););
435     }
436   }
437
438   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
439     AliError(Form("the following detectors were not found: %s",
440                   detStr.Data()));
441     if (fStopOnError) return kFALSE;
442   }
443
444   delete runLoader;
445
446   AliInfo("execution time:");
447   StdoutToAliInfo(stopwatch.Print(););
448
449   return kTRUE;
450 }
451
452
453 //_____________________________________________________________________________
454 Bool_t AliSimulation::RunDigitization(const char* detectors, 
455                                       const char* excludeDetectors)
456 {
457 // run the digitization and produce digits from sdigits
458
459   TStopwatch stopwatch;
460   stopwatch.Start();
461
462   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
463   if (gAlice) delete gAlice;
464   gAlice = NULL;
465
466   Int_t nStreams = 1;
467   if (fBkgrdFileNames) nStreams = fBkgrdFileNames->GetEntriesFast() + 1;
468   Int_t signalPerBkgrd = GetNSignalPerBkgrd();
469   AliRunDigitizer* manager = new AliRunDigitizer(nStreams, signalPerBkgrd);
470   manager->SetInputStream(0, fGAliceFileName.Data());
471   for (Int_t iStream = 1; iStream < nStreams; iStream++) {
472     const char* fileName = ((TObjString*)
473                             (fBkgrdFileNames->At(iStream-1)))->GetName();
474     manager->SetInputStream(iStream, fileName);
475   }
476
477   TString detStr = detectors;
478   TString detExcl = excludeDetectors;
479   manager->GetInputStream(0)->ImportgAlice();
480   AliRunLoader* runLoader = 
481     AliRunLoader::GetRunLoader(manager->GetInputStream(0)->GetFolderName());
482   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
483   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
484     AliModule* det = (AliModule*) detArray->At(iDet);
485     if (!det || !det->IsActive()) continue;
486     if (IsSelected(det->GetName(), detStr) && 
487         !IsSelected(det->GetName(), detExcl)) {
488       AliDigitizer* digitizer = det->CreateDigitizer(manager);
489       if (!digitizer) {
490         AliError(Form("no digitizer for %s", det->GetName()));
491         if (fStopOnError) return kFALSE;
492       } else {
493         digitizer->SetRegionOfInterest(fRegionOfInterest);
494       }
495     }
496   }
497
498   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
499     AliError(Form("the following detectors were not found: %s", 
500                   detStr.Data()));
501     if (fStopOnError) return kFALSE;
502   }
503
504   if (!manager->GetListOfTasks()->IsEmpty()) {
505     AliInfo("executing digitization");
506     manager->Exec("");
507   }
508
509   delete manager;
510
511   AliInfo("execution time:");
512   StdoutToAliInfo(stopwatch.Print(););
513
514   return kTRUE;
515 }
516
517 //_____________________________________________________________________________
518 Bool_t AliSimulation::RunHitsDigitization(const char* detectors)
519 {
520 // run the digitization and produce digits from hits
521
522   TStopwatch stopwatch;
523   stopwatch.Start();
524
525   AliRunLoader* runLoader = LoadRun();
526   if (!runLoader) return kFALSE;
527
528   TString detStr = detectors;
529   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
530   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
531     AliModule* det = (AliModule*) detArray->At(iDet);
532     if (!det || !det->IsActive()) continue;
533     if (IsSelected(det->GetName(), detStr)) {
534       AliInfo(Form("creating digits from hits for %s", det->GetName()));
535       det->Hits2Digits();
536     }
537   }
538
539   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
540     AliError(Form("the following detectors were not found: %s", 
541                   detStr.Data()));
542     if (fStopOnError) return kFALSE;
543   }
544
545   delete runLoader;
546
547   AliInfo("execution time:");
548   StdoutToAliInfo(stopwatch.Print(););
549
550   return kTRUE;
551 }
552
553 //_____________________________________________________________________________
554 Bool_t AliSimulation::WriteRawData(const char* detectors, 
555                                    const char* fileName,
556                                    Bool_t deleteIntermediateFiles)
557 {
558 // convert the digits to raw data
559 // First DDL raw data files for the given detectors are created.
560 // If a file name is given, the DDL files are then converted to a DATE file.
561 // If deleteIntermediateFiles is true, the DDL raw files are deleted 
562 // afterwards.
563 // If the file name has the extension ".root", the DATE file is converted
564 // to a root file.
565 // If deleteIntermediateFiles is true, the DATE file is deleted afterwards.
566
567   TStopwatch stopwatch;
568   stopwatch.Start();
569
570   if (!WriteRawFiles(detectors)) {
571     if (fStopOnError) return kFALSE;
572   }
573
574   TString dateFileName(fileName);
575   if (!dateFileName.IsNull()) {
576     Bool_t rootOutput = dateFileName.EndsWith(".root");
577     if (rootOutput) dateFileName += ".date";
578     if (!ConvertRawFilesToDate(dateFileName)) {
579       if (fStopOnError) return kFALSE;
580     }
581     if (deleteIntermediateFiles) {
582       AliRunLoader* runLoader = LoadRun("READ");
583       if (runLoader) for (Int_t iEvent = 0; 
584                           iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
585         char command[256];
586         sprintf(command, "rm -r raw%d", iEvent);
587         gSystem->Exec(command);
588       }
589     }
590
591     if (rootOutput) {
592       if (!ConvertDateToRoot(dateFileName, fileName)) {
593         if (fStopOnError) return kFALSE;
594       }
595       if (deleteIntermediateFiles) {
596         gSystem->Unlink(dateFileName);
597       }
598     }
599   }
600
601   AliInfo("execution time:");
602   StdoutToAliInfo(stopwatch.Print(););
603
604   return kTRUE;
605 }
606
607 //_____________________________________________________________________________
608 Bool_t AliSimulation::WriteRawFiles(const char* detectors)
609 {
610 // convert the digits to raw data DDL files
611
612   AliRunLoader* runLoader = LoadRun("READ");
613   if (!runLoader) return kFALSE;
614
615   // write raw data to DDL files
616   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
617     AliInfo(Form("processing event %d", iEvent));
618     runLoader->GetEvent(iEvent);
619     TString baseDir = gSystem->WorkingDirectory();
620     char dirName[256];
621     sprintf(dirName, "raw%d", iEvent);
622     gSystem->MakeDirectory(dirName);
623     if (!gSystem->ChangeDirectory(dirName)) {
624       AliError(Form("couldn't change to directory %s", dirName));
625       if (fStopOnError) return kFALSE; else continue;
626     }
627
628     TString detStr = detectors;
629     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
630     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
631       AliModule* det = (AliModule*) detArray->At(iDet);
632       if (!det || !det->IsActive()) continue;
633       if (IsSelected(det->GetName(), detStr)) {
634         AliInfo(Form("creating raw data from digits for %s", det->GetName()));
635         det->Digits2Raw();
636       }
637     }
638
639     gSystem->ChangeDirectory(baseDir);
640     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
641       AliError(Form("the following detectors were not found: %s", 
642                     detStr.Data()));
643       if (fStopOnError) return kFALSE;
644     }
645   }
646
647   delete runLoader;
648   return kTRUE;
649 }
650
651 //_____________________________________________________________________________
652 Bool_t AliSimulation::ConvertRawFilesToDate(const char* dateFileName)
653 {
654 // convert raw data DDL files to a DATE file with the program "dateStream"
655
656   // DATE setup
657   const Int_t kNDetectors = 17;
658   const char* kDetectors[kNDetectors] = {"TPC", "ITSSPD", "ITSSDD", "ITSSSD", 
659                                          "TRD", "TOF", "PHOS", "RICH", 
660                                          "EMCAL", "MUON", "MUTR", "ZDC", 
661                                          "PMD", "START", "VZERO", "CRT",
662                                          "FMD"};
663   const Int_t kDetectorDDLs[kNDetectors]   = {216, 20, 12, 16, 
664                                               18, 72, 20, 20, 
665                                               22, 20, 2, 1, 
666                                               6, 1, 1, 1,
667                                               1};
668   const Float_t kDetectorLDCs[kNDetectors] = {46, 2, 2, 1, 
669                                               4, 2, 1, 2, 
670                                               1, 2, 1, 1,
671                                               1, 0.5, 0.5, 1,
672                                               1};
673
674   char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
675   if (!path) {
676     AliError("the program dateStream was not found");
677     if (fStopOnError) return kFALSE;
678   } else {
679     delete[] path;
680   }
681
682   AliRunLoader* runLoader = LoadRun("READ");
683   if (!runLoader) return kFALSE;
684
685   AliInfo(Form("converting raw data DDL files to DATE file %s", dateFileName));
686   char command[256];
687   sprintf(command, "dateStream -o %s -# %d -C", 
688           dateFileName, runLoader->GetNumberOfEvents());
689   FILE* pipe = gSystem->OpenPipe(command, "w");
690
691   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
692     fprintf(pipe, "GDC\n");
693     Float_t ldc = 0;
694     Int_t prevLDC = -1;
695
696     // loop over detectors and DDLs
697     for (Int_t iDet = 0; iDet < kNDetectors; iDet++) {
698       for (Int_t iDDL = 0; iDDL < kDetectorDDLs[iDet]; iDDL++) {
699
700         Int_t ddlID = 0x100*iDet + iDDL;
701         Int_t ldcID = Int_t(ldc + 0.0001);
702         ldc += kDetectorLDCs[iDet] / kDetectorDDLs[iDet];
703
704         char rawFileName[256];
705         sprintf(rawFileName, "raw%d/%s_%d.ddl", 
706                 iEvent, kDetectors[iDet], ddlID);
707
708         // check existence and size of raw data file
709         FILE* file = fopen(rawFileName, "rb");
710         if (!file) continue;
711         fseek(file, 0, SEEK_END);
712         unsigned long size = ftell(file);
713         fseek(file, 0, SEEK_SET);
714         if (!size) {
715           fclose(file);
716           continue;
717         }
718
719         if (ldcID != prevLDC) {
720           fprintf(pipe, " LDC Id %d\n", ldcID);
721           prevLDC = ldcID;
722         }
723         fprintf(pipe, "  Equipment Id %d Payload %s\n", ddlID, rawFileName);
724       }
725     }
726   }
727
728   Int_t result = gSystem->ClosePipe(pipe);
729
730   delete runLoader;
731   return (result == 0);
732 }
733
734 //_____________________________________________________________________________
735 Bool_t AliSimulation::ConvertDateToRoot(const char* dateFileName,
736                                         const char* rootFileName)
737 {
738 // convert a DATE file to a root file with the program "alimdc"
739
740   // ALIMDC setup
741   const Int_t kDBSize = 1000000000;
742   const Bool_t kFilter = kFALSE;
743   const Int_t kCompression = 1;
744
745   char* path = gSystem->Which(gSystem->Getenv("PATH"), "alimdc");
746   if (!path) {
747     AliError("the program alimdc was not found");
748     if (fStopOnError) return kFALSE;
749   } else {
750     delete[] path;
751   }
752
753   AliInfo(Form("converting DATE file %s to root file %s", 
754                dateFileName, rootFileName));
755
756   gSystem->Exec("rm -rf /tmp/mdc1");
757   gSystem->Exec("rm -rf /tmp/mdc2");
758   char command[256];
759   sprintf(command, "alimdc %d %d %d %s", 
760           kDBSize, kFilter, kCompression, dateFileName);
761   Int_t result = gSystem->Exec(command);
762   sprintf(command, "mv /tmp/mdc1/*.root %s", rootFileName);
763   gSystem->Exec(command);
764   gSystem->Exec("rm -rf /tmp/mdc1");
765   gSystem->Exec("rm -rf /tmp/mdc2");
766
767   return (result == 0);
768 }
769
770
771 //_____________________________________________________________________________
772 AliRunLoader* AliSimulation::LoadRun(const char* mode) const
773 {
774 // delete existing run loaders, open a new one and load gAlice
775
776   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
777   AliRunLoader* runLoader = 
778     AliRunLoader::Open(fGAliceFileName.Data(), 
779                        AliConfig::GetDefaultEventFolderName(), mode);
780   if (!runLoader) {
781     AliError(Form("no run loader found in file %s", fGAliceFileName.Data()));
782     return NULL;
783   }
784   runLoader->LoadgAlice();
785   gAlice = runLoader->GetAliRun();
786   if (!gAlice) {
787     AliError(Form("no gAlice object found in file %s", 
788                   fGAliceFileName.Data()));
789     return NULL;
790   }
791   return runLoader;
792 }
793
794 //_____________________________________________________________________________
795 Int_t AliSimulation::GetNSignalPerBkgrd(Int_t nEvents) const
796 {
797 // get or calculate the number of signal events per background event
798
799   if (!fBkgrdFileNames) return 1;
800   Int_t nBkgrdFiles = fBkgrdFileNames->GetEntriesFast();
801   if (nBkgrdFiles == 0) return 1;
802
803   // get the number of signal events
804   if (nEvents <= 0) {
805     AliRunLoader* runLoader = 
806       AliRunLoader::Open(fGAliceFileName.Data(), "SIGNAL");
807     if (!runLoader) return 1;
808     nEvents = runLoader->GetNumberOfEvents();
809     delete runLoader;
810   }
811
812   Int_t result = 0;
813   for (Int_t iBkgrdFile = 0; iBkgrdFile < nBkgrdFiles; iBkgrdFile++) {
814     // get the number of background events
815     const char* fileName = ((TObjString*)
816                             (fBkgrdFileNames->At(iBkgrdFile)))->GetName();
817     AliRunLoader* runLoader = 
818       AliRunLoader::Open(fileName, "BKGRD");
819     if (!runLoader) continue;
820     Int_t nBkgrdEvents = runLoader->GetNumberOfEvents();
821     delete runLoader;
822
823     // get or calculate the number of signal per background events
824     Int_t nSignalPerBkgrd = fBkgrdFileNames->At(iBkgrdFile)->GetUniqueID();
825     if (nSignalPerBkgrd <= 0) {
826       nSignalPerBkgrd = (nEvents-1) / nBkgrdEvents + 1;
827     } else if (result && (result != nSignalPerBkgrd)) {
828       AliInfo(Form("the number of signal events per background event "
829                    "will be changed from %d to %d for stream %d", 
830                    nSignalPerBkgrd, result, iBkgrdFile+1));
831       nSignalPerBkgrd = result;
832     }
833
834     if (!result) result = nSignalPerBkgrd;
835     if (nSignalPerBkgrd * nBkgrdEvents < nEvents) {
836       AliWarning(Form("not enough background events (%d) for %d signal events "
837                       "using %d signal per background events for stream %d",
838                       nBkgrdEvents, nEvents, nSignalPerBkgrd, iBkgrdFile+1));
839     }
840   }
841
842   return result;
843 }
844
845 //_____________________________________________________________________________
846 Bool_t AliSimulation::IsSelected(TString detName, TString& detectors) const
847 {
848 // check whether detName is contained in detectors
849 // if yes, it is removed from detectors
850
851   // check if all detectors are selected
852   if ((detectors.CompareTo("ALL") == 0) ||
853       detectors.BeginsWith("ALL ") ||
854       detectors.EndsWith(" ALL") ||
855       detectors.Contains(" ALL ")) {
856     detectors = "ALL";
857     return kTRUE;
858   }
859
860   // search for the given detector
861   Bool_t result = kFALSE;
862   if ((detectors.CompareTo(detName) == 0) ||
863       detectors.BeginsWith(detName+" ") ||
864       detectors.EndsWith(" "+detName) ||
865       detectors.Contains(" "+detName+" ")) {
866     detectors.ReplaceAll(detName, "");
867     result = kTRUE;
868   }
869
870   // clean up the detectors string
871   while (detectors.Contains("  ")) detectors.ReplaceAll("  ", " ");
872   while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
873   while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
874
875   return result;
876 }