]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliSimulation.cxx
First prototype of the trigger classes (E. Lopez Torres)
[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 #include "AliCentralTrigger.h"
122
123 #include "AliDAQConfig.h"
124 #include "AliAlignObj.h"
125 #include "AliAlignObjAngles.h"
126 #include "AliAlignObjMatrix.h"
127
128 ClassImp(AliSimulation)
129
130
131 //_____________________________________________________________________________
132 AliSimulation::AliSimulation(const char* configFileName,
133                              const char* name, const char* title) :
134   TNamed(name, title),
135
136   fRunGeneration(kTRUE),
137   fRunSimulation(kTRUE),
138   fMakeSDigits("ALL"),
139   fMakeDigits("ALL"),
140   fMakeTrigger(""),
141   fMakeDigitsFromHits(""),
142   fWriteRawData(""),
143   fRawDataFileName(""),
144   fDeleteIntermediateFiles(kFALSE),
145   fStopOnError(kFALSE),
146
147   fNEvents(1),
148   fConfigFileName(configFileName),
149   fGAliceFileName("galice.root"),
150   fEventsPerFile(),
151   fBkgrdFileNames(NULL),
152   fUseBkgrdVertex(kTRUE),
153   fRegionOfInterest(kFALSE)
154 {
155 // create simulation object with default parameters
156
157   SetGAliceFile("galice.root");
158 }
159
160 //_____________________________________________________________________________
161 AliSimulation::AliSimulation(const AliSimulation& sim) :
162   TNamed(sim),
163
164   fRunGeneration(sim.fRunGeneration),
165   fRunSimulation(sim.fRunSimulation),
166   fMakeSDigits(sim.fMakeSDigits),
167   fMakeDigits(sim.fMakeDigits),
168   fMakeTrigger(sim.fMakeTrigger),
169   fMakeDigitsFromHits(sim.fMakeDigitsFromHits),
170   fWriteRawData(sim.fWriteRawData),
171   fRawDataFileName(""),
172   fDeleteIntermediateFiles(kFALSE),
173   fStopOnError(sim.fStopOnError),
174
175   fNEvents(sim.fNEvents),
176   fConfigFileName(sim.fConfigFileName),
177   fGAliceFileName(sim.fGAliceFileName),
178   fEventsPerFile(),
179   fBkgrdFileNames(NULL),
180   fUseBkgrdVertex(sim.fUseBkgrdVertex),
181   fRegionOfInterest(sim.fRegionOfInterest)
182 {
183 // copy constructor
184
185   for (Int_t i = 0; i < sim.fEventsPerFile.GetEntriesFast(); i++) {
186     if (!sim.fEventsPerFile[i]) continue;
187     fEventsPerFile.Add(sim.fEventsPerFile[i]->Clone());
188   }
189
190   fBkgrdFileNames = new TObjArray;
191   for (Int_t i = 0; i < sim.fBkgrdFileNames->GetEntriesFast(); i++) {
192     if (!sim.fBkgrdFileNames->At(i)) continue;
193     fBkgrdFileNames->Add(sim.fBkgrdFileNames->At(i)->Clone());
194   }
195 }
196
197 //_____________________________________________________________________________
198 AliSimulation& AliSimulation::operator = (const AliSimulation& sim)
199 {
200 // assignment operator
201
202   this->~AliSimulation();
203   new(this) AliSimulation(sim);
204   return *this;
205 }
206
207 //_____________________________________________________________________________
208 AliSimulation::~AliSimulation()
209 {
210 // clean up
211
212   fEventsPerFile.Delete();
213
214   if (fBkgrdFileNames) {
215     fBkgrdFileNames->Delete();
216     delete fBkgrdFileNames;
217   }
218 }
219
220
221 //_____________________________________________________________________________
222 void AliSimulation::SetNumberOfEvents(Int_t nEvents)
223 {
224 // set the number of events for one run
225
226   fNEvents = nEvents;
227 }
228
229 //_____________________________________________________________________________
230 void AliSimulation::SetConfigFile(const char* fileName)
231 {
232 // set the name of the config file
233
234   fConfigFileName = fileName;
235 }
236
237 //_____________________________________________________________________________
238 void AliSimulation::SetGAliceFile(const char* fileName)
239 {
240 // set the name of the galice file
241 // the path is converted to an absolute one if it is relative
242
243   fGAliceFileName = fileName;
244   if (!gSystem->IsAbsoluteFileName(fGAliceFileName)) {
245     char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
246                                                 fGAliceFileName);
247     fGAliceFileName = absFileName;
248     delete[] absFileName;
249   }
250
251   AliDebug(2, Form("galice file name set to %s", fileName));
252 }
253
254 //_____________________________________________________________________________
255 void AliSimulation::SetEventsPerFile(const char* detector, const char* type, 
256                                      Int_t nEvents)
257 {
258 // set the number of events per file for the given detector and data type
259 // ("Hits", "Summable Digits", "Digits", "Reconstructed Points" or "Tracks")
260
261   TNamed* obj = new TNamed(detector, type);
262   obj->SetUniqueID(nEvents);
263   fEventsPerFile.Add(obj);
264 }
265
266 //_____________________________________________________________________________
267 Bool_t AliSimulation::ApplyDisplacements(const char* fileName, const char* ClArrayName)
268 {
269   // read collection of alignment objects (AliAlignObj derived) saved
270   // in the TClonesArray ClArrayName in the file fileName and apply
271   // them to the TGeo geometry passed as argument
272   //
273
274   TFile* inFile = TFile::Open(fileName,"READ");
275   if (!inFile || !inFile->IsOpen()) {
276     AliErrorClass(Form("Could not open file %s !",fileName));
277     return kFALSE;
278   }
279
280   TClonesArray* AlObjArray = ((TClonesArray*) inFile->Get(ClArrayName));
281   inFile->Close();
282
283   return AliSimulation::ApplyDisplacements(AlObjArray);
284
285 }
286
287 //_____________________________________________________________________________
288 Bool_t AliSimulation::ApplyDisplacements(TClonesArray* AlObjArray)
289 {
290   // Read collection of alignment objects (AliAlignObj derived) saved
291   // in the TClonesArray ClArrayName and apply them to the geometry
292   // manager singleton.
293   //
294   Int_t nvols = AlObjArray->GetEntriesFast();
295
296   AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
297   Int_t modId; // unique identity for volume in the alobj
298   Bool_t ispathvalid; // false if volume path for alobj is not valid for TGeo
299
300   TGeoHMatrix dm;
301
302   for(Int_t j=0; j<nvols; j++)
303     {
304       AliAlignObj* alobj = (AliAlignObj*) AlObjArray->UncheckedAt(j);
305       const char* volpath = alobj->GetVolPath();
306       TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
307       alobj->GetMatrix(dm);
308       alobj->GetVolUID(layerId, modId);
309       ispathvalid = gGeoManager->cd(volpath);
310       if(!ispathvalid){
311         AliWarningClass(Form("Volume path %s not valid!",volpath));
312         return kFALSE;
313       }
314       TGeoHMatrix* hm = gGeoManager->GetCurrentMatrix();
315       hm->MultiplyLeft(&dm);
316       AliInfoClass(Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
317       node->Align(hm);
318     }
319
320   return kTRUE;
321
322 }
323
324 //_____________________________________________________________________________
325 Bool_t AliSimulation::ApplyDisplacements(AliCDBParam* param, AliCDBId& Id)
326 {
327   // read collection of alignment objects (AliAlignObj derived) saved
328   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
329   // param (to get the AliCDBStorage) and Id; apply the alignment objects
330   // to the TGeo geometry passed as argument
331   //
332
333   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
334   AliCDBEntry* entry = storage->Get(Id);
335   TClonesArray* AlObjArray = ((TClonesArray*) entry->GetObject());
336
337   return AliSimulation::ApplyDisplacements(AlObjArray);
338
339 }
340
341 //_____________________________________________________________________________
342 Bool_t AliSimulation::ApplyDisplacements(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
343 {
344   // read collection of alignment objects (AliAlignObj derived) saved
345   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
346   // param (to get the AliCDBStorage) and Id; apply the alignment objects
347   // to the TGeo geometry passed as argument
348   //
349
350   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
351   AliCDBId id(path, runnum, runnum, version, sversion);
352
353   return ApplyDisplacements(param, id);
354
355 }
356
357 //_____________________________________________________________________________
358 void AliSimulation::MergeWith(const char* fileName, Int_t nSignalPerBkgrd)
359 {
360 // add a file with background events for merging
361
362   TObjString* fileNameStr = new TObjString(fileName);
363   fileNameStr->SetUniqueID(nSignalPerBkgrd);
364   if (!fBkgrdFileNames) fBkgrdFileNames = new TObjArray;
365   fBkgrdFileNames->Add(fileNameStr);
366 }
367
368
369 //_____________________________________________________________________________
370 Bool_t AliSimulation::Run(Int_t nEvents)
371 {
372 // run the generation, simulation and digitization
373
374   if (nEvents > 0) fNEvents = nEvents;
375
376   // generation and simulation -> hits
377   if (fRunGeneration) {
378     if (!RunSimulation()) if (fStopOnError) return kFALSE;
379   }
380
381   // hits -> summable digits
382   if (!fMakeSDigits.IsNull()) {
383     if (!RunSDigitization(fMakeSDigits)) if (fStopOnError) return kFALSE;
384   }
385
386   // summable digits -> digits
387   if (!fMakeDigits.IsNull()) {
388     if (!RunDigitization(fMakeDigits, fMakeDigitsFromHits)) {
389       if (fStopOnError) return kFALSE;
390     }
391   }
392
393   // hits -> digits
394   if (!fMakeDigitsFromHits.IsNull()) {
395     if (fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
396       AliWarning(Form("Merging and direct creation of digits from hits " 
397                  "was selected for some detectors. "
398                  "No merging will be done for the following detectors: %s",
399                  fMakeDigitsFromHits.Data()));
400     }
401     if (!RunHitsDigitization(fMakeDigitsFromHits)) {
402       if (fStopOnError) return kFALSE;
403     }
404   }
405
406   // digits -> trigger
407   if (!fMakeTrigger.IsNull()) {
408     if (!RunTrigger(fMakeTrigger)) {
409       if (fStopOnError) return kFALSE;
410     }
411   }
412
413   // digits -> raw data
414   if (!fWriteRawData.IsNull()) {
415     if (!WriteRawData(fWriteRawData, fRawDataFileName, 
416                       fDeleteIntermediateFiles)) {
417       if (fStopOnError) return kFALSE;
418     }
419   }
420
421   return kTRUE;
422 }
423
424 //_____________________________________________________________________________
425 Bool_t AliSimulation::RunTrigger(const char* descriptors)
426 {
427   // run the trigger
428
429   TStopwatch stopwatch;
430   stopwatch.Start();
431
432   AliRunLoader* runLoader = LoadRun("READ");
433   if (!runLoader) return kFALSE;
434   TString des = descriptors;
435   // Load Descriptors
436   AliCentralTrigger* aCTP = new AliCentralTrigger( des );
437
438   // digits -> trigger
439   if( !aCTP->RunTrigger( runLoader ) ) {
440     if (fStopOnError) {
441       delete aCTP;
442       return kFALSE;
443     }
444   }
445
446 /*
447   // Process each event
448   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
449     AliInfo(Form("processing event %d", iEvent));
450     runLoader->GetEvent(iEvent);
451
452     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
453     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
454       AliModule* det = (AliModule*) detArray->At(iDet);
455       if (!det || !det->IsActive()) continue;
456       if (IsSelected(det->GetName(), detStr)) {
457         AliInfo(Form("triggering from digits for %s", det->GetName()));
458
459      //   AliLoader* loader = fLoader[iDet];
460      //   loader->LoadDigits("read");
461      //   TTree* digitsTree = loader->TreeD();
462      //   det->Trigger( digitsTree );
463      // or
464         AliTriggerDetector* tdet = det->CreateTriggerDetector();
465         TObjArray* detInp = dtrg->GetTriggerInputs();
466         for( Int_t i=0; i<detInp->GetEntriesFast(); i++ )
467                fInputs.AddLast( detInp->At(i) );
468
469         AliInfo(Form("Execution time for %s: R:%.2fs C:%.2fs",
470                 det->GetName(),stopwatchDet.RealTime(),stopwatchDet.CpuTime()));
471       }
472     }
473
474     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
475       AliError(Form("the following detectors were not found: %s",
476                     detStr.Data()));
477       if (fStopOnError) {
478          delete centralTP;
479          return kFALSE;
480       }
481     }
482
483     // Check trigger conditions
484     centralTP->TriggerConditions();
485
486     // Write trigger ????
487     centralTP->Write();
488
489   } */
490
491   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
492                stopwatch.RealTime(),stopwatch.CpuTime()));
493
494   delete aCTP;
495   delete runLoader;
496
497   return kTRUE;
498 }
499
500
501
502 //_____________________________________________________________________________
503 Bool_t AliSimulation::RunSimulation(Int_t nEvents)
504 {
505 // run the generation and simulation
506
507   TStopwatch stopwatch;
508   stopwatch.Start();
509
510   if (!gAlice) {
511     AliError("no gAlice object. Restart aliroot and try again.");
512     return kFALSE;
513   }
514   if (gAlice->Modules()->GetEntries() > 0) {
515     AliError("gAlice was already run. Restart aliroot and try again.");
516     return kFALSE;
517   }
518
519   AliInfo(Form("initializing gAlice with config file %s",
520           fConfigFileName.Data()));
521   StdoutToAliInfo(StderrToAliError(
522     gAlice->Init(fConfigFileName.Data());
523   ););
524   AliRunLoader* runLoader = gAlice->GetRunLoader();
525   if (!runLoader) {
526     AliError(Form("gAlice has no run loader object. "
527                   "Check your config file: %s", fConfigFileName.Data()));
528     return kFALSE;
529   }
530   SetGAliceFile(runLoader->GetFileName());
531
532   if (!gAlice->Generator()) {
533     AliError(Form("gAlice has no generator object. "
534                   "Check your config file: %s", fConfigFileName.Data()));
535     return kFALSE;
536   }
537   if (nEvents <= 0) nEvents = fNEvents;
538
539   // get vertex from background file in case of merging
540   if (fUseBkgrdVertex &&
541       fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
542     Int_t signalPerBkgrd = GetNSignalPerBkgrd(nEvents);
543     const char* fileName = ((TObjString*)
544                             (fBkgrdFileNames->At(0)))->GetName();
545     AliInfo(Form("The vertex will be taken from the background "
546                  "file %s with nSignalPerBackground = %d", 
547                  fileName, signalPerBkgrd));
548     AliVertexGenFile* vtxGen = new AliVertexGenFile(fileName, signalPerBkgrd);
549     gAlice->Generator()->SetVertexGenerator(vtxGen);
550   }
551
552   if (!fRunSimulation) {
553     gAlice->Generator()->SetTrackingFlag(0);
554   }
555
556   // set the number of events per file for given detectors and data types
557   for (Int_t i = 0; i < fEventsPerFile.GetEntriesFast(); i++) {
558     if (!fEventsPerFile[i]) continue;
559     const char* detName = fEventsPerFile[i]->GetName();
560     const char* typeName = fEventsPerFile[i]->GetTitle();
561     TString loaderName(detName);
562     loaderName += "Loader";
563     AliLoader* loader = runLoader->GetLoader(loaderName);
564     if (!loader) {
565       AliError(Form("RunSimulation", "no loader for %s found\n"
566                     "Number of events per file not set for %s %s", 
567                     detName, typeName, detName));
568       continue;
569     }
570     AliDataLoader* dataLoader = 
571       loader->GetDataLoader(typeName);
572     if (!dataLoader) {
573       AliError(Form("no data loader for %s found\n"
574                     "Number of events per file not set for %s %s", 
575                     typeName, detName, typeName));
576       continue;
577     }
578     dataLoader->SetNumberOfEventsPerFile(fEventsPerFile[i]->GetUniqueID());
579     AliDebug(1, Form("number of events per file set to %d for %s %s",
580                      fEventsPerFile[i]->GetUniqueID(), detName, typeName));
581   }
582
583   AliInfo("running gAlice");
584   StdoutToAliInfo(StderrToAliError(
585     gAlice->Run(nEvents);
586   ););
587
588   delete runLoader;
589
590   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
591                stopwatch.RealTime(),stopwatch.CpuTime()));
592
593   return kTRUE;
594 }
595
596 //_____________________________________________________________________________
597 Bool_t AliSimulation::RunSDigitization(const char* detectors)
598 {
599 // run the digitization and produce summable digits
600
601   TStopwatch stopwatch;
602   stopwatch.Start();
603
604   AliRunLoader* runLoader = LoadRun();
605   if (!runLoader) return kFALSE;
606
607   TString detStr = detectors;
608   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
609   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
610     AliModule* det = (AliModule*) detArray->At(iDet);
611     if (!det || !det->IsActive()) continue;
612     if (IsSelected(det->GetName(), detStr)) {
613       AliInfo(Form("creating summable digits for %s", det->GetName()));
614       TStopwatch stopwatchDet;
615       stopwatchDet.Start();
616       det->Hits2SDigits();
617       AliInfo(Form("Execution time for %s: R:%.2fs C:%.2fs",
618            det->GetName(),stopwatchDet.RealTime(),stopwatchDet.CpuTime()));
619     }
620   }
621
622   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
623     AliError(Form("the following detectors were not found: %s",
624                   detStr.Data()));
625     if (fStopOnError) return kFALSE;
626   }
627
628   delete runLoader;
629
630   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
631            stopwatch.RealTime(),stopwatch.CpuTime()));
632
633   return kTRUE;
634 }
635
636
637 //_____________________________________________________________________________
638 Bool_t AliSimulation::RunDigitization(const char* detectors, 
639                                       const char* excludeDetectors)
640 {
641 // run the digitization and produce digits from sdigits
642
643   TStopwatch stopwatch;
644   stopwatch.Start();
645
646   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
647   if (gAlice) delete gAlice;
648   gAlice = NULL;
649
650   Int_t nStreams = 1;
651   if (fBkgrdFileNames) nStreams = fBkgrdFileNames->GetEntriesFast() + 1;
652   Int_t signalPerBkgrd = GetNSignalPerBkgrd();
653   AliRunDigitizer* manager = new AliRunDigitizer(nStreams, signalPerBkgrd);
654   manager->SetInputStream(0, fGAliceFileName.Data());
655   for (Int_t iStream = 1; iStream < nStreams; iStream++) {
656     const char* fileName = ((TObjString*)
657                             (fBkgrdFileNames->At(iStream-1)))->GetName();
658     manager->SetInputStream(iStream, fileName);
659   }
660
661   TString detStr = detectors;
662   TString detExcl = excludeDetectors;
663   manager->GetInputStream(0)->ImportgAlice();
664   AliRunLoader* runLoader = 
665     AliRunLoader::GetRunLoader(manager->GetInputStream(0)->GetFolderName());
666   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
667   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
668     AliModule* det = (AliModule*) detArray->At(iDet);
669     if (!det || !det->IsActive()) continue;
670     if (IsSelected(det->GetName(), detStr) && 
671         !IsSelected(det->GetName(), detExcl)) {
672       AliDigitizer* digitizer = det->CreateDigitizer(manager);
673       if (!digitizer) {
674         AliError(Form("no digitizer for %s", det->GetName()));
675         if (fStopOnError) return kFALSE;
676       } else {
677         digitizer->SetRegionOfInterest(fRegionOfInterest);
678       }
679     }
680   }
681
682   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
683     AliError(Form("the following detectors were not found: %s", 
684                   detStr.Data()));
685     if (fStopOnError) return kFALSE;
686   }
687
688   if (!manager->GetListOfTasks()->IsEmpty()) {
689     AliInfo("executing digitization");
690     manager->Exec("");
691   }
692
693   delete manager;
694
695   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
696                stopwatch.RealTime(),stopwatch.CpuTime()));
697   
698   return kTRUE;
699 }
700
701 //_____________________________________________________________________________
702 Bool_t AliSimulation::RunHitsDigitization(const char* detectors)
703 {
704 // run the digitization and produce digits from hits
705
706   TStopwatch stopwatch;
707   stopwatch.Start();
708
709   AliRunLoader* runLoader = LoadRun("READ");
710   if (!runLoader) return kFALSE;
711
712   TString detStr = detectors;
713   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
714   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
715     AliModule* det = (AliModule*) detArray->At(iDet);
716     if (!det || !det->IsActive()) continue;
717     if (IsSelected(det->GetName(), detStr)) {
718       AliInfo(Form("creating digits from hits for %s", det->GetName()));
719       det->Hits2Digits();
720     }
721   }
722
723   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
724     AliError(Form("the following detectors were not found: %s", 
725                   detStr.Data()));
726     if (fStopOnError) return kFALSE;
727   }
728
729   delete runLoader;
730   //PH Temporary fix to avoid interference with the PHOS loder/getter
731   //PH The problem has to be solved in more general way 09/06/05
732
733   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
734                stopwatch.RealTime(),stopwatch.CpuTime()));
735
736   return kTRUE;
737 }
738
739 //_____________________________________________________________________________
740 Bool_t AliSimulation::WriteRawData(const char* detectors, 
741                                    const char* fileName,
742                                    Bool_t deleteIntermediateFiles)
743 {
744 // convert the digits to raw data
745 // First DDL raw data files for the given detectors are created.
746 // If a file name is given, the DDL files are then converted to a DATE file.
747 // If deleteIntermediateFiles is true, the DDL raw files are deleted 
748 // afterwards.
749 // If the file name has the extension ".root", the DATE file is converted
750 // to a root file.
751 // If deleteIntermediateFiles is true, the DATE file is deleted afterwards.
752
753   TStopwatch stopwatch;
754   stopwatch.Start();
755
756   if (!WriteRawFiles(detectors)) {
757     if (fStopOnError) return kFALSE;
758   }
759
760   TString dateFileName(fileName);
761   if (!dateFileName.IsNull()) {
762     Bool_t rootOutput = dateFileName.EndsWith(".root");
763     if (rootOutput) dateFileName += ".date";
764     if (!ConvertRawFilesToDate(dateFileName)) {
765       if (fStopOnError) return kFALSE;
766     }
767     if (deleteIntermediateFiles) {
768       AliRunLoader* runLoader = LoadRun("READ");
769       if (runLoader) for (Int_t iEvent = 0; 
770                           iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
771         char command[256];
772         sprintf(command, "rm -r raw%d", iEvent);
773         gSystem->Exec(command);
774       }
775     }
776
777     if (rootOutput) {
778       if (!ConvertDateToRoot(dateFileName, fileName)) {
779         if (fStopOnError) return kFALSE;
780       }
781       if (deleteIntermediateFiles) {
782         gSystem->Unlink(dateFileName);
783       }
784     }
785   }
786
787   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
788                stopwatch.RealTime(),stopwatch.CpuTime()));
789
790   return kTRUE;
791 }
792
793 //_____________________________________________________________________________
794 Bool_t AliSimulation::WriteRawFiles(const char* detectors)
795 {
796 // convert the digits to raw data DDL files
797
798   AliRunLoader* runLoader = LoadRun("READ");
799   if (!runLoader) return kFALSE;
800
801   // write raw data to DDL files
802   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
803     AliInfo(Form("processing event %d", iEvent));
804     runLoader->GetEvent(iEvent);
805     TString baseDir = gSystem->WorkingDirectory();
806     char dirName[256];
807     sprintf(dirName, "raw%d", iEvent);
808     gSystem->MakeDirectory(dirName);
809     if (!gSystem->ChangeDirectory(dirName)) {
810       AliError(Form("couldn't change to directory %s", dirName));
811       if (fStopOnError) return kFALSE; else continue;
812     }
813
814     TString detStr = detectors;
815     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
816     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
817       AliModule* det = (AliModule*) detArray->At(iDet);
818       if (!det || !det->IsActive()) continue;
819       if (IsSelected(det->GetName(), detStr)) {
820         AliInfo(Form("creating raw data from digits for %s", det->GetName()));
821         det->Digits2Raw();
822       }
823     }
824
825     gSystem->ChangeDirectory(baseDir);
826     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
827       AliError(Form("the following detectors were not found: %s", 
828                     detStr.Data()));
829       if (fStopOnError) return kFALSE;
830     }
831   }
832
833   delete runLoader;
834   return kTRUE;
835 }
836
837 //_____________________________________________________________________________
838 Bool_t AliSimulation::ConvertRawFilesToDate(const char* dateFileName)
839 {
840 // convert raw data DDL files to a DATE file with the program "dateStream"
841
842   char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
843   if (!path) {
844     AliError("the program dateStream was not found");
845     if (fStopOnError) return kFALSE;
846   } else {
847     delete[] path;
848   }
849
850   AliRunLoader* runLoader = LoadRun("READ");
851   if (!runLoader) return kFALSE;
852
853   AliInfo(Form("converting raw data DDL files to DATE file %s", dateFileName));
854   char command[256];
855   sprintf(command, "dateStream -o %s -# %d -C", 
856           dateFileName, runLoader->GetNumberOfEvents());
857   FILE* pipe = gSystem->OpenPipe(command, "w");
858
859   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
860     fprintf(pipe, "GDC\n");
861     Float_t ldc = 0;
862     Int_t prevLDC = -1;
863
864     // loop over detectors and DDLs
865     for (Int_t iDet = 0; iDet < kNDetectors; iDet++) {
866       for (Int_t iDDL = 0; iDDL < kDetectorDDLs[iDet]; iDDL++) {
867
868         Int_t ddlID = 0x100*iDet + iDDL;
869         Int_t ldcID = Int_t(ldc + 0.0001);
870         ldc += kDetectorLDCs[iDet] / kDetectorDDLs[iDet];
871
872         char rawFileName[256];
873         sprintf(rawFileName, "raw%d/%s_%d.ddl", 
874                 iEvent, kDetectors[iDet], ddlID);
875
876         // check existence and size of raw data file
877         FILE* file = fopen(rawFileName, "rb");
878         if (!file) continue;
879         fseek(file, 0, SEEK_END);
880         unsigned long size = ftell(file);
881         fclose(file);
882         if (!size) continue;
883
884         if (ldcID != prevLDC) {
885           fprintf(pipe, " LDC Id %d\n", ldcID);
886           prevLDC = ldcID;
887         }
888         fprintf(pipe, "  Equipment Id %d Payload %s\n", ddlID, rawFileName);
889       }
890     }
891   }
892
893   Int_t result = gSystem->ClosePipe(pipe);
894
895   delete runLoader;
896   return (result == 0);
897 }
898
899 //_____________________________________________________________________________
900 Bool_t AliSimulation::ConvertDateToRoot(const char* dateFileName,
901                                         const char* rootFileName)
902 {
903 // convert a DATE file to a root file with the program "alimdc"
904
905   // ALIMDC setup
906   const Int_t kDBSize = 1000000000;
907   const Int_t kTagDBSize = 1000000000;
908   const Bool_t kFilter = kFALSE;
909   const Int_t kCompression = 1;
910
911   char* path = gSystem->Which(gSystem->Getenv("PATH"), "alimdc");
912   if (!path) {
913     AliError("the program alimdc was not found");
914     if (fStopOnError) return kFALSE;
915   } else {
916     delete[] path;
917   }
918
919   AliInfo(Form("converting DATE file %s to root file %s", 
920                dateFileName, rootFileName));
921
922   gSystem->Exec("rm -rf /tmp/mdc1");
923   gSystem->Exec("rm -rf /tmp/mdc2");
924
925   gSystem->Exec("mkdir /tmp/mdc1");
926   gSystem->Exec("mkdir /tmp/mdc2");
927
928   char command[256];
929   sprintf(command, "alimdc %d %d %d %d %s", 
930           kDBSize, kTagDBSize, kFilter, kCompression, dateFileName);
931   Int_t result = gSystem->Exec(command);
932   sprintf(command, "mv /tmp/mdc1/*.root %s", rootFileName);
933   gSystem->Exec(command);
934   gSystem->Exec("rm -rf /tmp/mdc1");
935   gSystem->Exec("rm -rf /tmp/mdc2");
936
937   return (result == 0);
938 }
939
940
941 //_____________________________________________________________________________
942 AliRunLoader* AliSimulation::LoadRun(const char* mode) const
943 {
944 // delete existing run loaders, open a new one and load gAlice
945
946   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
947   AliRunLoader* runLoader = 
948     AliRunLoader::Open(fGAliceFileName.Data(), 
949                        AliConfig::GetDefaultEventFolderName(), mode);
950   if (!runLoader) {
951     AliError(Form("no run loader found in file %s", fGAliceFileName.Data()));
952     return NULL;
953   }
954   runLoader->LoadgAlice();
955   gAlice = runLoader->GetAliRun();
956   if (!gAlice) {
957     AliError(Form("no gAlice object found in file %s", 
958                   fGAliceFileName.Data()));
959     return NULL;
960   }
961   return runLoader;
962 }
963
964 //_____________________________________________________________________________
965 Int_t AliSimulation::GetNSignalPerBkgrd(Int_t nEvents) const
966 {
967 // get or calculate the number of signal events per background event
968
969   if (!fBkgrdFileNames) return 1;
970   Int_t nBkgrdFiles = fBkgrdFileNames->GetEntriesFast();
971   if (nBkgrdFiles == 0) return 1;
972
973   // get the number of signal events
974   if (nEvents <= 0) {
975     AliRunLoader* runLoader = 
976       AliRunLoader::Open(fGAliceFileName.Data(), "SIGNAL");
977     if (!runLoader) return 1;
978     nEvents = runLoader->GetNumberOfEvents();
979     delete runLoader;
980   }
981
982   Int_t result = 0;
983   for (Int_t iBkgrdFile = 0; iBkgrdFile < nBkgrdFiles; iBkgrdFile++) {
984     // get the number of background events
985     const char* fileName = ((TObjString*)
986                             (fBkgrdFileNames->At(iBkgrdFile)))->GetName();
987     AliRunLoader* runLoader = 
988       AliRunLoader::Open(fileName, "BKGRD");
989     if (!runLoader) continue;
990     Int_t nBkgrdEvents = runLoader->GetNumberOfEvents();
991     delete runLoader;
992
993     // get or calculate the number of signal per background events
994     Int_t nSignalPerBkgrd = fBkgrdFileNames->At(iBkgrdFile)->GetUniqueID();
995     if (nSignalPerBkgrd <= 0) {
996       nSignalPerBkgrd = (nEvents-1) / nBkgrdEvents + 1;
997     } else if (result && (result != nSignalPerBkgrd)) {
998       AliInfo(Form("the number of signal events per background event "
999                    "will be changed from %d to %d for stream %d", 
1000                    nSignalPerBkgrd, result, iBkgrdFile+1));
1001       nSignalPerBkgrd = result;
1002     }
1003
1004     if (!result) result = nSignalPerBkgrd;
1005     if (nSignalPerBkgrd * nBkgrdEvents < nEvents) {
1006       AliWarning(Form("not enough background events (%d) for %d signal events "
1007                       "using %d signal per background events for stream %d",
1008                       nBkgrdEvents, nEvents, nSignalPerBkgrd, iBkgrdFile+1));
1009     }
1010   }
1011
1012   return result;
1013 }
1014
1015 //_____________________________________________________________________________
1016 Bool_t AliSimulation::IsSelected(TString detName, TString& detectors) const
1017 {
1018 // check whether detName is contained in detectors
1019 // if yes, it is removed from detectors
1020
1021   // check if all detectors are selected
1022   if ((detectors.CompareTo("ALL") == 0) ||
1023       detectors.BeginsWith("ALL ") ||
1024       detectors.EndsWith(" ALL") ||
1025       detectors.Contains(" ALL ")) {
1026     detectors = "ALL";
1027     return kTRUE;
1028   }
1029
1030   // search for the given detector
1031   Bool_t result = kFALSE;
1032   if ((detectors.CompareTo(detName) == 0) ||
1033       detectors.BeginsWith(detName+" ") ||
1034       detectors.EndsWith(" "+detName) ||
1035       detectors.Contains(" "+detName+" ")) {
1036     detectors.ReplaceAll(detName, "");
1037     result = kTRUE;
1038   }
1039
1040   // clean up the detectors string
1041   while (detectors.Contains("  ")) detectors.ReplaceAll("  ", " ");
1042   while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
1043   while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
1044
1045   return result;
1046 }