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