Removing timer from AliRun
[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 methods RunSimulation, RunSDigitization, RunDigitization,             //
80 // RunHitsDigitization and WriteRawData can be used to run only parts of     //
81 // the full simulation chain.                                                //
82 //                                                                           //
83 ///////////////////////////////////////////////////////////////////////////////
84
85
86 #include "AliSimulation.h"
87 #include "AliRunLoader.h"
88 #include "AliRun.h"
89 #include "AliModule.h"
90 #include "AliGenerator.h"
91 #include "AliVertexGenFile.h"
92 #include "AliRunDigitizer.h"
93 #include "AliDigitizer.h"
94 #include <TObjString.h>
95 #include <TSystem.h>
96 #include <TStopwatch.h>
97
98
99 ClassImp(AliSimulation)
100
101
102 //_____________________________________________________________________________
103 AliSimulation::AliSimulation(const char* configFileName,
104                              const char* name, const char* title) :
105   TNamed(name, title),
106
107   fRunGeneration(kTRUE),
108   fRunSimulation(kTRUE),
109   fMakeSDigits("ALL"),
110   fMakeDigits("ALL"),
111   fMakeDigitsFromHits(""),
112   fWriteRawData(""),
113   fStopOnError(kFALSE),
114
115   fNEvents(1),
116   fConfigFileName(configFileName),
117   fGAliceFileName("galice.root"),
118   fBkgrdFileNames(NULL),
119   fUseBkgrdVertex(kTRUE),
120   fRegionOfInterest(kTRUE)
121 {
122 // create simulation object with default parameters
123
124   SetGAliceFile("galice.root");
125 }
126
127 //_____________________________________________________________________________
128 AliSimulation::AliSimulation(const AliSimulation& sim) :
129   TNamed(sim),
130
131   fRunGeneration(sim.fRunGeneration),
132   fRunSimulation(sim.fRunSimulation),
133   fMakeSDigits(sim.fMakeSDigits),
134   fMakeDigits(sim.fMakeDigits),
135   fMakeDigitsFromHits(sim.fMakeDigitsFromHits),
136   fWriteRawData(sim.fWriteRawData),
137   fStopOnError(sim.fStopOnError),
138
139   fNEvents(sim.fNEvents),
140   fConfigFileName(sim.fConfigFileName),
141   fGAliceFileName(sim.fGAliceFileName),
142   fBkgrdFileNames(NULL),
143   fUseBkgrdVertex(sim.fUseBkgrdVertex),
144   fRegionOfInterest(sim.fRegionOfInterest)
145 {
146 // copy constructor
147
148   fBkgrdFileNames = new TObjArray;
149   for (Int_t i = 0; i < sim.fBkgrdFileNames->GetEntriesFast(); i++) {
150     if (!sim.fBkgrdFileNames->At(i)) continue;
151     fBkgrdFileNames->Add(sim.fBkgrdFileNames->At(i)->Clone());
152   }
153 }
154
155 //_____________________________________________________________________________
156 AliSimulation& AliSimulation::operator = (const AliSimulation& sim)
157 {
158 // assignment operator
159
160   this->~AliSimulation();
161   new(this) AliSimulation(sim);
162   return *this;
163 }
164
165 //_____________________________________________________________________________
166 AliSimulation::~AliSimulation()
167 {
168 // clean up
169
170   if (fBkgrdFileNames) {
171     fBkgrdFileNames->Delete();
172     delete fBkgrdFileNames;
173   }
174 }
175
176
177 //_____________________________________________________________________________
178 void AliSimulation::SetNumberOfEvents(Int_t nEvents)
179 {
180 // set the number of events for one run
181
182   fNEvents = nEvents;
183 }
184
185 //_____________________________________________________________________________
186 void AliSimulation::SetConfigFile(const char* fileName)
187 {
188 // set the name of the config file
189
190   fConfigFileName = fileName;
191 }
192
193 //_____________________________________________________________________________
194 void AliSimulation::SetGAliceFile(const char* fileName)
195 {
196 // set the name of the galice file
197 // the path is converted to an absolute one if it is relative
198
199   fGAliceFileName = fileName;
200   if (!gSystem->IsAbsoluteFileName(fGAliceFileName)) {
201     char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
202                                                 fGAliceFileName);
203     fGAliceFileName = absFileName;
204     delete[] absFileName;
205   }
206 }
207
208 //_____________________________________________________________________________
209 void AliSimulation::MergeWith(const char* fileName, Int_t nSignalPerBkgrd)
210 {
211 // add a file with background events for merging
212
213   TObjString* fileNameStr = new TObjString(fileName);
214   fileNameStr->SetUniqueID(nSignalPerBkgrd);
215   if (!fBkgrdFileNames) fBkgrdFileNames = new TObjArray;
216   fBkgrdFileNames->Add(fileNameStr);
217 }
218
219
220 //_____________________________________________________________________________
221 Bool_t AliSimulation::Run(Int_t nEvents)
222 {
223 // run the generation, simulation and digitization
224
225   if (nEvents > 0) fNEvents = nEvents;
226
227   // generation and simulation -> hits
228   if (fRunGeneration) {
229     if (!RunSimulation()) if (fStopOnError) return kFALSE;
230   }
231
232   // hits -> summable digits
233   if (!fMakeSDigits.IsNull()) {
234     if (!RunSDigitization(fMakeSDigits)) if (fStopOnError) return kFALSE;
235   }
236
237   // summable digits -> digits
238   if (!fMakeDigits.IsNull()) {
239     if (!RunDigitization(fMakeDigits, fMakeDigitsFromHits)) {
240       if (fStopOnError) return kFALSE;
241     }
242   }
243
244   // hits -> digits
245   if (!fMakeDigitsFromHits.IsNull()) {
246     if (fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
247       Warning("Run", "Merging and direct creation of digits from hits " 
248               "was selected for some detectors. "
249               "No merging will be done for the following detectors: %s",
250               fMakeDigitsFromHits.Data());
251     }
252     if (!RunHitsDigitization(fMakeDigitsFromHits)) {
253       if (fStopOnError) return kFALSE;
254     }
255   }
256
257   // digits -> raw data
258   if (!fWriteRawData.IsNull()) {
259     if (!WriteRawData(fWriteRawData)) {
260       if (fStopOnError) return kFALSE;
261     }
262   }
263
264   return kTRUE;
265 }
266
267 //_____________________________________________________________________________
268 Bool_t AliSimulation::RunSimulation(Int_t nEvents)
269 {
270 // run the generation and simulation
271
272   TStopwatch stopwatch;
273   stopwatch.Start();
274
275   if (!gAlice) {
276     Error("RunSimulation", "no gAlice object. Restart aliroot and try again.");
277     return kFALSE;
278   }
279   if (gAlice->Modules()->GetEntries() > 0) {
280     Error("RunSimulation", 
281           "gAlice was already run. Restart aliroot and try again.");
282     return kFALSE;
283   }
284
285   Info("RunSimulation", "initializing gAlice with config file %s",
286        fConfigFileName.Data());
287   gAlice->Init(fConfigFileName.Data());
288   AliRunLoader* runLoader = gAlice->GetRunLoader();
289   if (!runLoader) {
290     Error("RunSimulation", "gAlice has no run loader object. "
291           "Check your config file: %s", fConfigFileName.Data());
292     return kFALSE;
293   }
294   SetGAliceFile(runLoader->GetFileName());
295
296   if (!gAlice->Generator()) {
297     Error("RunSimulation", "gAlice has no generator object. "
298           "Check your config file: %s", fConfigFileName.Data());
299     return kFALSE;
300   }
301   if (nEvents <= 0) nEvents = fNEvents;
302
303   // get vertex from background file in case of merging
304   if (fUseBkgrdVertex &&
305       fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
306     Int_t signalPerBkgrd = GetNSignalPerBkgrd(nEvents);
307     const char* fileName = ((TObjString*)
308                             (fBkgrdFileNames->At(0)))->GetName();
309     Info("RunSimulation", "The vertex will be taken from the background "
310          "file %s with nSignalPerBackground = %d", 
311          fileName, signalPerBkgrd);
312     AliVertexGenFile* vtxGen = new AliVertexGenFile(fileName, signalPerBkgrd);
313     gAlice->Generator()->SetVertexGenerator(vtxGen);
314   }
315
316   if (!fRunSimulation) {
317     gAlice->Generator()->SetTrackingFlag(0);
318   }
319
320   Info("RunSimulation", "running gAlice");
321   gAlice->Run(nEvents);
322
323   delete runLoader;
324
325   Info("RunSimulation", "execution time:");
326   stopwatch.Print();
327
328   return kTRUE;
329 }
330
331 //_____________________________________________________________________________
332 Bool_t AliSimulation::RunSDigitization(const char* detectors)
333 {
334 // run the digitization and produce summable digits
335
336   TStopwatch stopwatch;
337   stopwatch.Start();
338
339   AliRunLoader* runLoader = LoadRun();
340   if (!runLoader) return kFALSE;
341
342   TString detStr = detectors;
343   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
344   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
345     AliModule* det = (AliModule*) detArray->At(iDet);
346     if (!det || !det->IsActive()) continue;
347     if (IsSelected(det->GetName(), detStr)) {
348       Info("RunSDigitization", "creating summable digits for %s", 
349            det->GetName());
350       TStopwatch stopwatchDet;
351       stopwatchDet.Start();
352       det->Hits2SDigits();
353       Info("RunSDigitization", "execution time for %s:", det->GetName());
354       stopwatchDet.Print();
355     }
356   }
357
358   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
359     Error("RunSDigitization", "the following detectors were not found: %s", 
360           detStr.Data());
361     if (fStopOnError) return kFALSE;
362   }
363
364   delete runLoader;
365
366   Info("RunSDigitization", "execution time:");
367   stopwatch.Print();
368
369   return kTRUE;
370 }
371
372
373 //_____________________________________________________________________________
374 Bool_t AliSimulation::RunDigitization(const char* detectors, 
375                                       const char* excludeDetectors)
376 {
377 // run the digitization and produce digits from sdigits
378
379   TStopwatch stopwatch;
380   stopwatch.Start();
381
382   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
383   if (gAlice) delete gAlice;
384   gAlice = NULL;
385
386   Int_t nStreams = 1;
387   if (fBkgrdFileNames) nStreams = fBkgrdFileNames->GetEntriesFast() + 1;
388   Int_t signalPerBkgrd = GetNSignalPerBkgrd();
389   AliRunDigitizer* manager = new AliRunDigitizer(nStreams, signalPerBkgrd);
390   manager->SetInputStream(0, fGAliceFileName.Data());
391   for (Int_t iStream = 1; iStream < nStreams; iStream++) {
392     const char* fileName = ((TObjString*)
393                             (fBkgrdFileNames->At(iStream-1)))->GetName();
394     manager->SetInputStream(iStream, fileName);
395   }
396
397   TString detStr = detectors;
398   TString detExcl = excludeDetectors;
399   manager->GetInputStream(0)->ImportgAlice();
400   AliRunLoader* runLoader = 
401     AliRunLoader::GetRunLoader(manager->GetInputStream(0)->GetFolderName());
402   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
403   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
404     AliModule* det = (AliModule*) detArray->At(iDet);
405     if (!det || !det->IsActive()) continue;
406     if (IsSelected(det->GetName(), detStr) && 
407         !IsSelected(det->GetName(), detExcl)) {
408       AliDigitizer* digitizer = det->CreateDigitizer(manager);
409       if (!digitizer) {
410         Error("RunDigitization", "no digitizer for %s", det->GetName());
411         if (fStopOnError) return kFALSE;
412       } else {
413         digitizer->SetRegionOfInterest(fRegionOfInterest);
414       }
415     }
416   }
417
418   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
419     Error("RunDigitization", "the following detectors were not found: %s", 
420           detStr.Data());
421     if (fStopOnError) return kFALSE;
422   }
423
424   if (!manager->GetListOfTasks()->IsEmpty()) {
425     Info("RunDigitization", "executing digitization");
426     manager->Exec("");
427   }
428
429   delete manager;
430
431   Info("RunDigitization", "execution time:");
432   stopwatch.Print();
433
434   return kTRUE;
435 }
436
437 //_____________________________________________________________________________
438 Bool_t AliSimulation::RunHitsDigitization(const char* detectors)
439 {
440 // run the digitization and produce digits from hits
441
442   TStopwatch stopwatch;
443   stopwatch.Start();
444
445   AliRunLoader* runLoader = LoadRun();
446   if (!runLoader) return kFALSE;
447
448   TString detStr = detectors;
449   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
450   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
451     AliModule* det = (AliModule*) detArray->At(iDet);
452     if (!det || !det->IsActive()) continue;
453     if (IsSelected(det->GetName(), detStr)) {
454       Info("RunHitsDigitization", "creating digits from hits for %s", 
455            det->GetName());
456       det->Hits2Digits();
457     }
458   }
459
460   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
461     Error("RunHitsDigitization", "the following detectors were not found: %s", 
462           detStr.Data());
463     if (fStopOnError) return kFALSE;
464   }
465
466   delete runLoader;
467
468   Info("RunHitsDigitization", "execution time:");
469   stopwatch.Print();
470
471   return kTRUE;
472 }
473
474 //_____________________________________________________________________________
475 Bool_t AliSimulation::WriteRawData(const char* detectors)
476 {
477 // convert the digits to raw data
478
479   TStopwatch stopwatch;
480   stopwatch.Start();
481
482   AliRunLoader* runLoader = LoadRun();
483   if (!runLoader) return kFALSE;
484
485   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
486     Info("WriteRawData", "processing event %d", iEvent);
487     runLoader->GetEvent(iEvent);
488     TString baseDir = gSystem->WorkingDirectory();
489     char dirName[256];
490     sprintf(dirName, "raw%d", iEvent);
491     gSystem->MakeDirectory(dirName);
492     if (!gSystem->ChangeDirectory(dirName)) {
493       Error("WriteRawData", "couldn't change to directory %s", dirName);
494       if (fStopOnError) return kFALSE; else continue;
495     }
496
497     TString detStr = detectors;
498     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
499     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
500       AliModule* det = (AliModule*) detArray->At(iDet);
501       if (!det || !det->IsActive()) continue;
502       if (IsSelected(det->GetName(), detStr)) {
503         Info("WriteRawData", "creating raw data from digits for %s", 
504              det->GetName());
505         det->Digits2Raw();
506       }
507     }
508
509     gSystem->ChangeDirectory(baseDir);
510     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
511       Error("WriteRawData", "the following detectors were not found: %s", 
512             detStr.Data());
513       if (fStopOnError) return kFALSE;
514     }
515   }
516
517   delete runLoader;
518
519   Info("WriteRawData", "execution time:");
520   stopwatch.Print();
521
522   return kTRUE;
523 }
524
525
526 //_____________________________________________________________________________
527 AliRunLoader* AliSimulation::LoadRun() const
528 {
529 // delete existing run loaders, open a new one and load gAlice
530
531   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
532   AliRunLoader* runLoader = 
533     AliRunLoader::Open(fGAliceFileName.Data(), 
534                        AliConfig::GetDefaultEventFolderName(), "UPDATE");
535   if (!runLoader) {
536     Error("LoadRun", "no run loader found in file %s", 
537           fGAliceFileName.Data());
538     return NULL;
539   }
540   runLoader->LoadgAlice();
541   gAlice = runLoader->GetAliRun();
542   if (!gAlice) {
543     Error("LoadRun", "no gAlice object found in file %s", 
544           fGAliceFileName.Data());
545     return NULL;
546   }
547   return runLoader;
548 }
549
550 //_____________________________________________________________________________
551 Int_t AliSimulation::GetNSignalPerBkgrd(Int_t nEvents) const
552 {
553 // get or calculate the number of signal events per background event
554
555   if (!fBkgrdFileNames) return 1;
556   Int_t nBkgrdFiles = fBkgrdFileNames->GetEntriesFast();
557   if (nBkgrdFiles == 0) return 1;
558
559   // get the number of signal events
560   if (nEvents <= 0) {
561     AliRunLoader* runLoader = 
562       AliRunLoader::Open(fGAliceFileName.Data(), "SIGNAL");
563     if (!runLoader) return 1;
564     nEvents = runLoader->GetNumberOfEvents();
565     delete runLoader;
566   }
567
568   Int_t result = 0;
569   for (Int_t iBkgrdFile = 0; iBkgrdFile < nBkgrdFiles; iBkgrdFile++) {
570     // get the number of background events
571     const char* fileName = ((TObjString*)
572                             (fBkgrdFileNames->At(iBkgrdFile)))->GetName();
573     AliRunLoader* runLoader = 
574       AliRunLoader::Open(fileName, "BKGRD");
575     if (!runLoader) continue;
576     Int_t nBkgrdEvents = runLoader->GetNumberOfEvents();
577     delete runLoader;
578
579     // get or calculate the number of signal per background events
580     Int_t nSignalPerBkgrd = fBkgrdFileNames->At(iBkgrdFile)->GetUniqueID();
581     if (nSignalPerBkgrd <= 0) {
582       nSignalPerBkgrd = (nEvents-1) / nBkgrdEvents + 1;
583     } else if (result && (result != nSignalPerBkgrd)) {
584       Info("GetNSignalPerBkgrd", "the number of signal events per "
585            "background event will be changed from %d to %d for stream %d", 
586            nSignalPerBkgrd, result, iBkgrdFile+1);
587       nSignalPerBkgrd = result;
588     }
589
590     if (!result) result = nSignalPerBkgrd;
591     if (nSignalPerBkgrd * nBkgrdEvents < nEvents) {
592       Warning("GetNSignalPerBkgrd", "not enough background events (%d) for "
593               "%d signal events using %d signal per background events for "
594               "stream %d", 
595               nBkgrdEvents, nEvents, nSignalPerBkgrd, iBkgrdFile+1);
596     }
597   }
598
599   return result;
600 }
601
602 //_____________________________________________________________________________
603 Bool_t AliSimulation::IsSelected(TString detName, TString& detectors) const
604 {
605 // check whether detName is contained in detectors
606 // if yes, it is removed from detectors
607
608   // check if all detectors are selected
609   if ((detectors.CompareTo("ALL") == 0) ||
610       detectors.BeginsWith("ALL ") ||
611       detectors.EndsWith(" ALL") ||
612       detectors.Contains(" ALL ")) {
613     detectors = "ALL";
614     return kTRUE;
615   }
616
617   // search for the given detector
618   Bool_t result = kFALSE;
619   if ((detectors.CompareTo(detName) == 0) ||
620       detectors.BeginsWith(detName+" ") ||
621       detectors.EndsWith(" "+detName) ||
622       detectors.Contains(" "+detName+" ")) {
623     detectors.ReplaceAll(detName, "");
624     result = kTRUE;
625   }
626
627   // clean up the detectors string
628   while (detectors.Contains("  ")) detectors.ReplaceAll("  ", " ");
629   while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
630   while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
631
632   return result;
633 }