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