b930e8c6b933047a91ad3a3d22eaa6a5d150ffdb
[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 = 17;
655   const char* kDetectors[kNDetectors] = {"TPC", "ITSSPD", "ITSSDD", "ITSSSD", 
656                                          "TRD", "TOF", "PHOS", "RICH", 
657                                          "EMCAL", "MUON", "MUTR", "ZDC", 
658                                          "PMD", "START", "VZERO", "CRT",
659                                          "FMD"};
660   const Int_t kDetectorDDLs[kNDetectors]   = {216, 20, 12, 16, 
661                                               18, 72, 20, 20, 
662                                               22, 20, 2, 1, 
663                                               6, 1, 1, 1,
664                                               1};
665   const Float_t kDetectorLDCs[kNDetectors] = {46, 2, 2, 1, 
666                                               4, 2, 1, 2, 
667                                               1, 2, 1, 1,
668                                               1, 0.5, 0.5, 1,
669                                               1};
670
671   char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
672   if (!path) {
673     Error("ConvertRawFilesToDate", "the program dateStream was not found");
674     if (fStopOnError) return kFALSE;
675   } else {
676     delete[] path;
677   }
678
679   AliRunLoader* runLoader = LoadRun("READ");
680   if (!runLoader) return kFALSE;
681
682   Info("ConvertRawFilesToDate", 
683        "converting raw data DDL files to DATE file %s", dateFileName);
684   char command[256];
685   sprintf(command, "dateStream -o %s -# %d -C", 
686           dateFileName, runLoader->GetNumberOfEvents());
687   FILE* pipe = gSystem->OpenPipe(command, "w");
688
689   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
690     fprintf(pipe, "GDC\n");
691     Float_t ldc = 0;
692     Int_t prevLDC = -1;
693
694     // loop over detectors and DDLs
695     for (Int_t iDet = 0; iDet < kNDetectors; iDet++) {
696       for (Int_t iDDL = 0; iDDL < kDetectorDDLs[iDet]; iDDL++) {
697
698         Int_t ddlID = 0x100*iDet + iDDL;
699         Int_t ldcID = Int_t(ldc + 0.0001);
700         ldc += kDetectorLDCs[iDet] / kDetectorDDLs[iDet];
701
702         char rawFileName[256];
703         sprintf(rawFileName, "raw%d/%s_%d.ddl", 
704                 iEvent, kDetectors[iDet], ddlID);
705
706         // check existence and size of raw data file
707         FILE* file = fopen(rawFileName, "rb");
708         if (!file) continue;
709         fseek(file, 0, SEEK_END);
710         unsigned long size = ftell(file);
711         fseek(file, 0, SEEK_SET);
712         if (!size) {
713           fclose(file);
714           continue;
715         }
716
717         if (ldcID != prevLDC) {
718           fprintf(pipe, " LDC Id %d\n", ldcID);
719           prevLDC = ldcID;
720         }
721         fprintf(pipe, "  Equipment Id %d Payload %s\n", ddlID, rawFileName);
722       }
723     }
724   }
725
726   Int_t result = gSystem->ClosePipe(pipe);
727
728   delete runLoader;
729   return (result == 0);
730 }
731
732 //_____________________________________________________________________________
733 Bool_t AliSimulation::ConvertDateToRoot(const char* dateFileName,
734                                         const char* rootFileName)
735 {
736 // convert a DATE file to a root file with the program "alimdc"
737
738   // ALIMDC setup
739   const Int_t kDBSize = 1000000000;
740   const Bool_t kFilter = kFALSE;
741   const Int_t kCompression = 1;
742
743   char* path = gSystem->Which(gSystem->Getenv("PATH"), "alimdc");
744   if (!path) {
745     Error("ConvertDateToRoot", "the program alimdc was not found");
746     if (fStopOnError) return kFALSE;
747   } else {
748     delete[] path;
749   }
750
751   Info("ConvertDateToRoot", "converting DATE file %s to root file %s", 
752        dateFileName, rootFileName);
753
754   gSystem->Exec("rm -rf /tmp/mdc1");
755   gSystem->Exec("rm -rf /tmp/mdc2");
756   char command[256];
757   sprintf(command, "alimdc %d %d %d %s", 
758           kDBSize, kFilter, kCompression, dateFileName);
759   Int_t result = gSystem->Exec(command);
760   sprintf(command, "mv /tmp/mdc1/*.root %s", rootFileName);
761   gSystem->Exec(command);
762   gSystem->Exec("rm -rf /tmp/mdc1");
763   gSystem->Exec("rm -rf /tmp/mdc2");
764
765   return (result == 0);
766 }
767
768
769 //_____________________________________________________________________________
770 AliRunLoader* AliSimulation::LoadRun(const char* mode) const
771 {
772 // delete existing run loaders, open a new one and load gAlice
773
774   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
775   AliRunLoader* runLoader = 
776     AliRunLoader::Open(fGAliceFileName.Data(), 
777                        AliConfig::GetDefaultEventFolderName(), mode);
778   if (!runLoader) {
779     Error("LoadRun", "no run loader found in file %s", 
780           fGAliceFileName.Data());
781     return NULL;
782   }
783   runLoader->LoadgAlice();
784   gAlice = runLoader->GetAliRun();
785   if (!gAlice) {
786     Error("LoadRun", "no gAlice object found in file %s", 
787           fGAliceFileName.Data());
788     return NULL;
789   }
790   return runLoader;
791 }
792
793 //_____________________________________________________________________________
794 Int_t AliSimulation::GetNSignalPerBkgrd(Int_t nEvents) const
795 {
796 // get or calculate the number of signal events per background event
797
798   if (!fBkgrdFileNames) return 1;
799   Int_t nBkgrdFiles = fBkgrdFileNames->GetEntriesFast();
800   if (nBkgrdFiles == 0) return 1;
801
802   // get the number of signal events
803   if (nEvents <= 0) {
804     AliRunLoader* runLoader = 
805       AliRunLoader::Open(fGAliceFileName.Data(), "SIGNAL");
806     if (!runLoader) return 1;
807     nEvents = runLoader->GetNumberOfEvents();
808     delete runLoader;
809   }
810
811   Int_t result = 0;
812   for (Int_t iBkgrdFile = 0; iBkgrdFile < nBkgrdFiles; iBkgrdFile++) {
813     // get the number of background events
814     const char* fileName = ((TObjString*)
815                             (fBkgrdFileNames->At(iBkgrdFile)))->GetName();
816     AliRunLoader* runLoader = 
817       AliRunLoader::Open(fileName, "BKGRD");
818     if (!runLoader) continue;
819     Int_t nBkgrdEvents = runLoader->GetNumberOfEvents();
820     delete runLoader;
821
822     // get or calculate the number of signal per background events
823     Int_t nSignalPerBkgrd = fBkgrdFileNames->At(iBkgrdFile)->GetUniqueID();
824     if (nSignalPerBkgrd <= 0) {
825       nSignalPerBkgrd = (nEvents-1) / nBkgrdEvents + 1;
826     } else if (result && (result != nSignalPerBkgrd)) {
827       Info("GetNSignalPerBkgrd", "the number of signal events per "
828            "background event will be changed from %d to %d for stream %d", 
829            nSignalPerBkgrd, result, iBkgrdFile+1);
830       nSignalPerBkgrd = result;
831     }
832
833     if (!result) result = nSignalPerBkgrd;
834     if (nSignalPerBkgrd * nBkgrdEvents < nEvents) {
835       Warning("GetNSignalPerBkgrd", "not enough background events (%d) for "
836               "%d signal events using %d signal per background events for "
837               "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 }