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