use AliLog for messages
[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(kTRUE)
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   gAlice->Init(fConfigFileName.Data());
338   AliRunLoader* runLoader = gAlice->GetRunLoader();
339   if (!runLoader) {
340     AliError(Form("gAlice has no run loader object. "
341                   "Check your config file: %s", fConfigFileName.Data()));
342     return kFALSE;
343   }
344   SetGAliceFile(runLoader->GetFileName());
345
346   if (!gAlice->Generator()) {
347     AliError(Form("gAlice has no generator object. "
348                   "Check your config file: %s", fConfigFileName.Data()));
349     return kFALSE;
350   }
351   if (nEvents <= 0) nEvents = fNEvents;
352
353   // get vertex from background file in case of merging
354   if (fUseBkgrdVertex &&
355       fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
356     Int_t signalPerBkgrd = GetNSignalPerBkgrd(nEvents);
357     const char* fileName = ((TObjString*)
358                             (fBkgrdFileNames->At(0)))->GetName();
359     AliInfo(Form("The vertex will be taken from the background "
360                  "file %s with nSignalPerBackground = %d", 
361                  fileName, signalPerBkgrd));
362     AliVertexGenFile* vtxGen = new AliVertexGenFile(fileName, signalPerBkgrd);
363     gAlice->Generator()->SetVertexGenerator(vtxGen);
364   }
365
366   if (!fRunSimulation) {
367     gAlice->Generator()->SetTrackingFlag(0);
368   }
369
370   // set the number of events per file for given detectors and data types
371   for (Int_t i = 0; i < fEventsPerFile.GetEntriesFast(); i++) {
372     if (!fEventsPerFile[i]) continue;
373     const char* detName = fEventsPerFile[i]->GetName();
374     const char* typeName = fEventsPerFile[i]->GetTitle();
375     TString loaderName(detName);
376     loaderName += "Loader";
377     AliLoader* loader = runLoader->GetLoader(loaderName);
378     if (!loader) {
379       AliError(Form("RunSimulation", "no loader for %s found\n"
380                     "Number of events per file not set for %s %s", 
381                     detName, typeName, detName));
382       continue;
383     }
384     AliDataLoader* dataLoader = 
385       loader->GetDataLoader(typeName);
386     if (!dataLoader) {
387       AliError(Form("no data loader for %s found\n"
388                     "Number of events per file not set for %s %s", 
389                     typeName, detName, typeName));
390       continue;
391     }
392     dataLoader->SetNumberOfEventsPerFile(fEventsPerFile[i]->GetUniqueID());
393     AliDebug(1, Form("number of events per file set to %d for %s %s",
394                      fEventsPerFile[i]->GetUniqueID(), detName, typeName));
395   }
396
397   AliInfo("running gAlice");
398   gAlice->Run(nEvents);
399
400   delete runLoader;
401
402   AliInfo("execution time:");
403   stopwatch.Print();
404
405   return kTRUE;
406 }
407
408 //_____________________________________________________________________________
409 Bool_t AliSimulation::RunSDigitization(const char* detectors)
410 {
411 // run the digitization and produce summable digits
412
413   TStopwatch stopwatch;
414   stopwatch.Start();
415
416   AliRunLoader* runLoader = LoadRun();
417   if (!runLoader) return kFALSE;
418
419   TString detStr = detectors;
420   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
421   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
422     AliModule* det = (AliModule*) detArray->At(iDet);
423     if (!det || !det->IsActive()) continue;
424     if (IsSelected(det->GetName(), detStr)) {
425       AliInfo(Form("creating summable digits for %s", det->GetName()));
426       TStopwatch stopwatchDet;
427       stopwatchDet.Start();
428       det->Hits2SDigits();
429       AliInfo(Form("execution time for %s:", det->GetName()));
430       stopwatchDet.Print();
431     }
432   }
433
434   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
435     AliError(Form("the following detectors were not found: %s",
436                   detStr.Data()));
437     if (fStopOnError) return kFALSE;
438   }
439
440   delete runLoader;
441
442   AliInfo("execution time:");
443   stopwatch.Print();
444
445   return kTRUE;
446 }
447
448
449 //_____________________________________________________________________________
450 Bool_t AliSimulation::RunDigitization(const char* detectors, 
451                                       const char* excludeDetectors)
452 {
453 // run the digitization and produce digits from sdigits
454
455   TStopwatch stopwatch;
456   stopwatch.Start();
457
458   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
459   if (gAlice) delete gAlice;
460   gAlice = NULL;
461
462   Int_t nStreams = 1;
463   if (fBkgrdFileNames) nStreams = fBkgrdFileNames->GetEntriesFast() + 1;
464   Int_t signalPerBkgrd = GetNSignalPerBkgrd();
465   AliRunDigitizer* manager = new AliRunDigitizer(nStreams, signalPerBkgrd);
466   manager->SetInputStream(0, fGAliceFileName.Data());
467   for (Int_t iStream = 1; iStream < nStreams; iStream++) {
468     const char* fileName = ((TObjString*)
469                             (fBkgrdFileNames->At(iStream-1)))->GetName();
470     manager->SetInputStream(iStream, fileName);
471   }
472
473   TString detStr = detectors;
474   TString detExcl = excludeDetectors;
475   manager->GetInputStream(0)->ImportgAlice();
476   AliRunLoader* runLoader = 
477     AliRunLoader::GetRunLoader(manager->GetInputStream(0)->GetFolderName());
478   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
479   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
480     AliModule* det = (AliModule*) detArray->At(iDet);
481     if (!det || !det->IsActive()) continue;
482     if (IsSelected(det->GetName(), detStr) && 
483         !IsSelected(det->GetName(), detExcl)) {
484       AliDigitizer* digitizer = det->CreateDigitizer(manager);
485       if (!digitizer) {
486         AliError(Form("no digitizer for %s", det->GetName()));
487         if (fStopOnError) return kFALSE;
488       } else {
489         digitizer->SetRegionOfInterest(fRegionOfInterest);
490       }
491     }
492   }
493
494   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
495     AliError(Form("the following detectors were not found: %s", 
496                   detStr.Data()));
497     if (fStopOnError) return kFALSE;
498   }
499
500   if (!manager->GetListOfTasks()->IsEmpty()) {
501     AliInfo("executing digitization");
502     manager->Exec("");
503   }
504
505   delete manager;
506
507   AliInfo("execution time:");
508   stopwatch.Print();
509
510   return kTRUE;
511 }
512
513 //_____________________________________________________________________________
514 Bool_t AliSimulation::RunHitsDigitization(const char* detectors)
515 {
516 // run the digitization and produce digits from hits
517
518   TStopwatch stopwatch;
519   stopwatch.Start();
520
521   AliRunLoader* runLoader = LoadRun();
522   if (!runLoader) return kFALSE;
523
524   TString detStr = detectors;
525   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
526   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
527     AliModule* det = (AliModule*) detArray->At(iDet);
528     if (!det || !det->IsActive()) continue;
529     if (IsSelected(det->GetName(), detStr)) {
530       AliInfo(Form("creating digits from hits for %s", det->GetName()));
531       det->Hits2Digits();
532     }
533   }
534
535   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
536     AliError(Form("the following detectors were not found: %s", 
537                   detStr.Data()));
538     if (fStopOnError) return kFALSE;
539   }
540
541   delete runLoader;
542
543   AliInfo("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   AliInfo("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     AliInfo(Form("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       AliError(Form("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         AliInfo(Form("creating raw data from digits for %s", det->GetName()));
631         det->Digits2Raw();
632       }
633     }
634
635     gSystem->ChangeDirectory(baseDir);
636     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
637       AliError(Form("the following detectors were not found: %s", 
638                     detStr.Data()));
639       if (fStopOnError) return kFALSE;
640     }
641   }
642
643   delete runLoader;
644   return kTRUE;
645 }
646
647 //_____________________________________________________________________________
648 Bool_t AliSimulation::ConvertRawFilesToDate(const char* dateFileName)
649 {
650 // convert raw data DDL files to a DATE file with the program "dateStream"
651
652   // DATE setup
653   const Int_t kNDetectors = 17;
654   const char* kDetectors[kNDetectors] = {"TPC", "ITSSPD", "ITSSDD", "ITSSSD", 
655                                          "TRD", "TOF", "PHOS", "RICH", 
656                                          "EMCAL", "MUON", "MUTR", "ZDC", 
657                                          "PMD", "START", "VZERO", "CRT",
658                                          "FMD"};
659   const Int_t kDetectorDDLs[kNDetectors]   = {216, 20, 12, 16, 
660                                               18, 72, 20, 20, 
661                                               22, 20, 2, 1, 
662                                               6, 1, 1, 1,
663                                               1};
664   const Float_t kDetectorLDCs[kNDetectors] = {46, 2, 2, 1, 
665                                               4, 2, 1, 2, 
666                                               1, 2, 1, 1,
667                                               1, 0.5, 0.5, 1,
668                                               1};
669
670   char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
671   if (!path) {
672     AliError("the program dateStream was not found");
673     if (fStopOnError) return kFALSE;
674   } else {
675     delete[] path;
676   }
677
678   AliRunLoader* runLoader = LoadRun("READ");
679   if (!runLoader) return kFALSE;
680
681   AliInfo(Form("converting raw data DDL files to DATE file %s", dateFileName));
682   char command[256];
683   sprintf(command, "dateStream -o %s -# %d -C", 
684           dateFileName, runLoader->GetNumberOfEvents());
685   FILE* pipe = gSystem->OpenPipe(command, "w");
686
687   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
688     fprintf(pipe, "GDC\n");
689     Float_t ldc = 0;
690     Int_t prevLDC = -1;
691
692     // loop over detectors and DDLs
693     for (Int_t iDet = 0; iDet < kNDetectors; iDet++) {
694       for (Int_t iDDL = 0; iDDL < kDetectorDDLs[iDet]; iDDL++) {
695
696         Int_t ddlID = 0x100*iDet + iDDL;
697         Int_t ldcID = Int_t(ldc + 0.0001);
698         ldc += kDetectorLDCs[iDet] / kDetectorDDLs[iDet];
699
700         char rawFileName[256];
701         sprintf(rawFileName, "raw%d/%s_%d.ddl", 
702                 iEvent, kDetectors[iDet], ddlID);
703
704         // check existence and size of raw data file
705         FILE* file = fopen(rawFileName, "rb");
706         if (!file) continue;
707         fseek(file, 0, SEEK_END);
708         unsigned long size = ftell(file);
709         fseek(file, 0, SEEK_SET);
710         if (!size) {
711           fclose(file);
712           continue;
713         }
714
715         if (ldcID != prevLDC) {
716           fprintf(pipe, " LDC Id %d\n", ldcID);
717           prevLDC = ldcID;
718         }
719         fprintf(pipe, "  Equipment Id %d Payload %s\n", ddlID, rawFileName);
720       }
721     }
722   }
723
724   Int_t result = gSystem->ClosePipe(pipe);
725
726   delete runLoader;
727   return (result == 0);
728 }
729
730 //_____________________________________________________________________________
731 Bool_t AliSimulation::ConvertDateToRoot(const char* dateFileName,
732                                         const char* rootFileName)
733 {
734 // convert a DATE file to a root file with the program "alimdc"
735
736   // ALIMDC setup
737   const Int_t kDBSize = 1000000000;
738   const Bool_t kFilter = kFALSE;
739   const Int_t kCompression = 1;
740
741   char* path = gSystem->Which(gSystem->Getenv("PATH"), "alimdc");
742   if (!path) {
743     AliError("the program alimdc was not found");
744     if (fStopOnError) return kFALSE;
745   } else {
746     delete[] path;
747   }
748
749   AliInfo(Form("converting DATE file %s to root file %s", 
750                dateFileName, rootFileName));
751
752   gSystem->Exec("rm -rf /tmp/mdc1");
753   gSystem->Exec("rm -rf /tmp/mdc2");
754   char command[256];
755   sprintf(command, "alimdc %d %d %d %s", 
756           kDBSize, kFilter, kCompression, dateFileName);
757   Int_t result = gSystem->Exec(command);
758   sprintf(command, "mv /tmp/mdc1/*.root %s", rootFileName);
759   gSystem->Exec(command);
760   gSystem->Exec("rm -rf /tmp/mdc1");
761   gSystem->Exec("rm -rf /tmp/mdc2");
762
763   return (result == 0);
764 }
765
766
767 //_____________________________________________________________________________
768 AliRunLoader* AliSimulation::LoadRun(const char* mode) const
769 {
770 // delete existing run loaders, open a new one and load gAlice
771
772   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
773   AliRunLoader* runLoader = 
774     AliRunLoader::Open(fGAliceFileName.Data(), 
775                        AliConfig::GetDefaultEventFolderName(), mode);
776   if (!runLoader) {
777     AliError(Form("no run loader found in file %s", fGAliceFileName.Data()));
778     return NULL;
779   }
780   runLoader->LoadgAlice();
781   gAlice = runLoader->GetAliRun();
782   if (!gAlice) {
783     AliError(Form("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       AliInfo(Form("the number of signal events per background event "
825                    "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       AliWarning(Form("not enough background events (%d) for %d signal events "
833                       "using %d signal per background events for stream %d",
834                       nBkgrdEvents, nEvents, nSignalPerBkgrd, iBkgrdFile+1));
835     }
836   }
837
838   return result;
839 }
840
841 //_____________________________________________________________________________
842 Bool_t AliSimulation::IsSelected(TString detName, TString& detectors) const
843 {
844 // check whether detName is contained in detectors
845 // if yes, it is removed from detectors
846
847   // check if all detectors are selected
848   if ((detectors.CompareTo("ALL") == 0) ||
849       detectors.BeginsWith("ALL ") ||
850       detectors.EndsWith(" ALL") ||
851       detectors.Contains(" ALL ")) {
852     detectors = "ALL";
853     return kTRUE;
854   }
855
856   // search for the given detector
857   Bool_t result = kFALSE;
858   if ((detectors.CompareTo(detName) == 0) ||
859       detectors.BeginsWith(detName+" ") ||
860       detectors.EndsWith(" "+detName) ||
861       detectors.Contains(" "+detName+" ")) {
862     detectors.ReplaceAll(detName, "");
863     result = kTRUE;
864   }
865
866   // clean up the detectors string
867   while (detectors.Contains("  ")) detectors.ReplaceAll("  ", " ");
868   while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
869   while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
870
871   return result;
872 }