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