]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliSimulation.cxx
New version of CDB framework. Proper initialization of CDB inside AliSimulation and...
[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 <TGeoManager.h>
109 #include <TObjString.h>
110 #include <TStopwatch.h>
111 #include <TSystem.h>
112 #include <TFile.h>
113
114 #include "AliCDBStorage.h"
115 #include "AliCDBEntry.h"
116 #include "AliCDBManager.h"
117 #include "AliAlignObj.h"
118 #include "AliCentralTrigger.h"
119 #include "AliDAQConfig.h"
120 #include "AliDigitizer.h"
121 #include "AliGenerator.h"
122 #include "AliLog.h"
123 #include "AliModule.h"
124 #include "AliRun.h"
125 #include "AliRunDigitizer.h"
126 #include "AliRunLoader.h"
127 #include "AliSimulation.h"
128 #include "AliVertexGenFile.h"
129 #include "AliCentralTrigger.h"
130
131 ClassImp(AliSimulation)
132
133
134 //_____________________________________________________________________________
135 AliSimulation::AliSimulation(const char* configFileName, const char* cdbUri,
136                              const char* name, const char* title) :
137   TNamed(name, title),
138
139   fRunGeneration(kTRUE),
140   fRunSimulation(kTRUE),
141   fLoadAlignFromCDB(kTRUE),
142   fLoadAlignData("ALL"),
143   fMakeSDigits("ALL"),
144   fMakeDigits("ALL"),
145   fMakeTrigger(""),
146   fMakeDigitsFromHits(""),
147   fWriteRawData(""),
148   fRawDataFileName(""),
149   fDeleteIntermediateFiles(kFALSE),
150   fStopOnError(kFALSE),
151
152   fNEvents(1),
153   fConfigFileName(configFileName),
154   fGAliceFileName("galice.root"),
155   fEventsPerFile(),
156   fBkgrdFileNames(NULL),
157   fAlignObjArray(NULL),
158   fUseBkgrdVertex(kTRUE),
159   fRegionOfInterest(kFALSE),
160   fCDBUri(cdbUri)
161 {
162 // create simulation object with default parameters
163
164   SetGAliceFile("galice.root");
165 }
166
167 //_____________________________________________________________________________
168 AliSimulation::AliSimulation(const AliSimulation& sim) :
169   TNamed(sim),
170
171   fRunGeneration(sim.fRunGeneration),
172   fRunSimulation(sim.fRunSimulation),
173   fLoadAlignFromCDB(sim.fLoadAlignFromCDB),
174   fLoadAlignData(sim.fLoadAlignData),
175   fMakeSDigits(sim.fMakeSDigits),
176   fMakeDigits(sim.fMakeDigits),
177   fMakeTrigger(sim.fMakeTrigger),
178   fMakeDigitsFromHits(sim.fMakeDigitsFromHits),
179   fWriteRawData(sim.fWriteRawData),
180   fRawDataFileName(""),
181   fDeleteIntermediateFiles(kFALSE),
182   fStopOnError(sim.fStopOnError),
183
184   fNEvents(sim.fNEvents),
185   fConfigFileName(sim.fConfigFileName),
186   fGAliceFileName(sim.fGAliceFileName),
187   fEventsPerFile(),
188   fBkgrdFileNames(NULL),
189   fAlignObjArray(NULL),
190   fUseBkgrdVertex(sim.fUseBkgrdVertex),
191   fRegionOfInterest(sim.fRegionOfInterest),
192   fCDBUri(sim.fCDBUri)
193 {
194 // copy constructor
195
196   for (Int_t i = 0; i < sim.fEventsPerFile.GetEntriesFast(); i++) {
197     if (!sim.fEventsPerFile[i]) continue;
198     fEventsPerFile.Add(sim.fEventsPerFile[i]->Clone());
199   }
200
201   fBkgrdFileNames = new TObjArray;
202   for (Int_t i = 0; i < sim.fBkgrdFileNames->GetEntriesFast(); i++) {
203     if (!sim.fBkgrdFileNames->At(i)) continue;
204     fBkgrdFileNames->Add(sim.fBkgrdFileNames->At(i)->Clone());
205   }
206 }
207
208 //_____________________________________________________________________________
209 AliSimulation& AliSimulation::operator = (const AliSimulation& sim)
210 {
211 // assignment operator
212
213   this->~AliSimulation();
214   new(this) AliSimulation(sim);
215   return *this;
216 }
217
218 //_____________________________________________________________________________
219 AliSimulation::~AliSimulation()
220 {
221 // clean up
222
223   fEventsPerFile.Delete();
224 //  if(fAlignObjArray) fAlignObjArray->Delete(); // fAlignObjArray->RemoveAll() ???
225 //  delete fAlignObjArray; fAlignObjArray=0;
226
227   if (fBkgrdFileNames) {
228     fBkgrdFileNames->Delete();
229     delete fBkgrdFileNames;
230   }
231 }
232
233
234 //_____________________________________________________________________________
235 void AliSimulation::SetNumberOfEvents(Int_t nEvents)
236 {
237 // set the number of events for one run
238
239   fNEvents = nEvents;
240 }
241
242 //_____________________________________________________________________________
243 void AliSimulation::InitCDBStorage(const char* uri)
244 {
245 // activate a default CDB storage
246 // First check if we have any CDB storage set, because it is used 
247 // to retrieve the calibration and alignment constants
248
249   AliCDBManager* man = AliCDBManager::Instance();
250   if (!man->IsDefaultStorageSet())
251   {
252     AliWarningClass("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
253     AliWarningClass("Default CDB storage not yet set");
254     AliWarningClass(Form("Using default storage declared in AliSimulation: %s",uri));
255     AliWarningClass("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
256     SetDefaultStorage(uri);
257   }  
258   
259 }
260
261 //_____________________________________________________________________________
262 void AliSimulation::SetDefaultStorage(const char* uri) {
263 // activate a default CDB storage 
264
265    AliCDBManager::Instance()->SetDefaultStorage(uri);
266
267 }
268
269 //_____________________________________________________________________________
270 void AliSimulation::SetSpecificStorage(const char* detName, const char* uri) {
271 // activate a detector-specific CDB storage 
272
273    AliCDBManager::Instance()->SetSpecificStorage(detName, uri);
274
275 }
276
277 //_____________________________________________________________________________
278 void AliSimulation::SetConfigFile(const char* fileName)
279 {
280 // set the name of the config file
281
282   fConfigFileName = fileName;
283 }
284
285 //_____________________________________________________________________________
286 void AliSimulation::SetGAliceFile(const char* fileName)
287 {
288 // set the name of the galice file
289 // the path is converted to an absolute one if it is relative
290
291   fGAliceFileName = fileName;
292   if (!gSystem->IsAbsoluteFileName(fGAliceFileName)) {
293     char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
294                                                 fGAliceFileName);
295     fGAliceFileName = absFileName;
296     delete[] absFileName;
297   }
298
299   AliDebug(2, Form("galice file name set to %s", fileName));
300 }
301
302 //_____________________________________________________________________________
303 void AliSimulation::SetEventsPerFile(const char* detector, const char* type, 
304                                      Int_t nEvents)
305 {
306 // set the number of events per file for the given detector and data type
307 // ("Hits", "Summable Digits", "Digits", "Reconstructed Points" or "Tracks")
308
309   TNamed* obj = new TNamed(detector, type);
310   obj->SetUniqueID(nEvents);
311   fEventsPerFile.Add(obj);
312 }
313
314 //_____________________________________________________________________________
315 Bool_t AliSimulation::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
316 {
317   // read collection of alignment objects (AliAlignObj derived) saved
318   // in the TClonesArray ClArrayName in the file fileName and apply
319   // them to the TGeo geometry passed as argument
320   //
321
322   TFile* inFile = TFile::Open(fileName,"READ");
323   if (!inFile || !inFile->IsOpen()) {
324     AliErrorClass(Form("Could not open file %s !",fileName));
325     return kFALSE;
326   }
327
328   TClonesArray* alObjArray = ((TClonesArray*) inFile->Get(clArrayName));
329   inFile->Close();
330   if (!alObjArray) {
331     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
332     return kFALSE;
333   }
334
335   return gAlice->ApplyAlignObjsToGeom(alObjArray);
336
337 }
338
339 //_____________________________________________________________________________
340 Bool_t AliSimulation::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
341 {
342   // read collection of alignment objects (AliAlignObj derived) saved
343   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
344   // param (to get the AliCDBStorage) and Id; apply the alignment objects
345   // to the TGeo geometry passed as argument
346   //
347
348   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
349   AliCDBEntry* entry = storage->Get(Id);
350   TClonesArray* AlObjArray = ((TClonesArray*) entry->GetObject());
351
352   return gAlice->ApplyAlignObjsToGeom(AlObjArray);
353
354 }
355
356 //_____________________________________________________________________________
357 Bool_t AliSimulation::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
358 {
359   // read collection of alignment objects (AliAlignObj derived) saved
360   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
361   // param (to get the AliCDBStorage) and Id; apply the alignment objects
362   // to the TGeo geometry passed as argument
363   //
364
365   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
366   AliCDBId id(path, runnum, runnum, version, sversion);
367
368   return ApplyAlignObjsToGeom(param, id);
369
370 }
371
372 //_____________________________________________________________________________
373 Bool_t AliSimulation::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
374 {
375   // read collection of alignment objects (AliAlignObj derived) saved
376   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
377   // param (to get the AliCDBStorage) and Id; apply the alignment objects
378   // to the TGeo geometry passed as argument
379   //
380
381   InitCDBStorage("local://$ALICE_ROOT");
382   AliCDBPath path(detName,"Align","Data");
383   AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
384
385   if(!entry) return kFALSE;
386   TClonesArray* AlObjArray = ((TClonesArray*) entry->GetObject());
387
388   return gAlice->ApplyAlignObjsToGeom(AlObjArray);
389 }
390
391
392 //_____________________________________________________________________________
393 void AliSimulation::SetAlignObjArray(const char* detectors)
394 {
395   // Fills array of detectors' alignable objects from CDB
396   // detectors can be "ALL" or "ITS TPC ..."
397   
398   AliRunLoader* runLoader = LoadRun();
399   if (!runLoader) return;
400
401   InitCDBStorage(fCDBUri);
402
403   if(!fAlignObjArray) fAlignObjArray = new TObjArray();
404   fAlignObjArray->SetOwner(0); // AliCDBEntry is owner of the align objects!
405   fAlignObjArray->Clear(); 
406
407   TString detStr = detectors;
408   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
409   TString dataNotLoaded="";
410   TString dataLoaded="";
411
412   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
413     AliModule* det = (AliModule*) detArray->At(iDet);
414     if (!det || !det->IsActive()) continue;
415     if (IsSelected(det->GetName(), detStr)) {
416     
417         if(!SetAlignObjArraySingleDet(det->GetName())){
418                 dataNotLoaded += det->GetName();
419                 dataNotLoaded += " ";
420                         } else {
421                                 dataLoaded += det->GetName();
422                                 dataLoaded += " ";
423                         }
424         }
425   } // end loop over all detectors
426
427   if ((detStr.CompareTo("ALL") == 0)) detStr = "";
428   dataNotLoaded += detStr;
429   AliInfo(Form("Alignment data loaded for: %s",
430                 dataLoaded.Data()));
431   AliInfo(Form("Didn't/couldn't load alignment data for: %s",
432                 dataNotLoaded.Data()));
433
434   AliDebug(2, Form("fAlignObjArray entries: %d",fAlignObjArray->GetEntries() ));
435   delete detArray;
436
437 }
438
439 //_____________________________________________________________________________
440 Bool_t AliSimulation::SetAlignObjArraySingleDet(const char* detName)
441 {
442   // Fills array of single detector's alignable objects from CDB
443   
444   AliDebug(2, Form("Loading alignment data for detector: %s",detName));
445   
446   AliCDBEntry *entry;
447         
448   AliCDBPath path(detName,"Align","Data");
449         
450   entry=AliCDBManager::Instance()->Get(path.GetPath());
451   if(!entry){ 
452         AliDebug(2,Form("Couldn't load alignment data for detector %s",detName));
453         return kFALSE;
454   }
455   entry->SetOwner(1);
456   TClonesArray *alignArray = (TClonesArray*) entry->GetObject();        
457   alignArray->SetOwner(0);
458   AliDebug(2,Form("Found %d alignment objects for %s",
459                         alignArray->GetEntries(),detName));
460
461   AliAlignObj *alignObj=0;
462   TIter iter(alignArray);
463         
464   // loop over align objects in detector
465   while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
466         fAlignObjArray->Add(alignObj);
467   }
468   // delete entry --- Don't delete, it is cached!
469         
470   AliDebug(2, Form("fAlignObjArray entries: %d",fAlignObjArray->GetEntries() ));
471   return kTRUE;
472
473 }
474
475 //_____________________________________________________________________________
476 void AliSimulation::MergeWith(const char* fileName, Int_t nSignalPerBkgrd)
477 {
478 // add a file with background events for merging
479
480   TObjString* fileNameStr = new TObjString(fileName);
481   fileNameStr->SetUniqueID(nSignalPerBkgrd);
482   if (!fBkgrdFileNames) fBkgrdFileNames = new TObjArray;
483   fBkgrdFileNames->Add(fileNameStr);
484 }
485
486
487 //_____________________________________________________________________________
488 Bool_t AliSimulation::Run(Int_t nEvents)
489 {
490 // run the generation, simulation and digitization
491
492   InitCDBStorage(fCDBUri);
493
494   if (nEvents > 0) fNEvents = nEvents;
495
496   // generation and simulation -> hits
497   if (fRunGeneration) {
498     if (!RunSimulation()) if (fStopOnError) return kFALSE;
499   }
500
501   // hits -> summable digits
502   if (!fMakeSDigits.IsNull()) {
503     if (!RunSDigitization(fMakeSDigits)) if (fStopOnError) return kFALSE;
504   }
505
506   // summable digits -> digits
507   if (!fMakeDigits.IsNull()) {
508     if (!RunDigitization(fMakeDigits, fMakeDigitsFromHits)) {
509       if (fStopOnError) return kFALSE;
510     }
511   }
512
513   // hits -> digits
514   if (!fMakeDigitsFromHits.IsNull()) {
515     if (fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
516       AliWarning(Form("Merging and direct creation of digits from hits " 
517                  "was selected for some detectors. "
518                  "No merging will be done for the following detectors: %s",
519                  fMakeDigitsFromHits.Data()));
520     }
521     if (!RunHitsDigitization(fMakeDigitsFromHits)) {
522       if (fStopOnError) return kFALSE;
523     }
524   }
525
526   // digits -> trigger
527   if (!fMakeTrigger.IsNull()) {
528     if (!RunTrigger(fMakeTrigger)) {
529       if (fStopOnError) return kFALSE;
530     }
531   }
532
533   // digits -> raw data
534   if (!fWriteRawData.IsNull()) {
535     if (!WriteRawData(fWriteRawData, fRawDataFileName, 
536                       fDeleteIntermediateFiles)) {
537       if (fStopOnError) return kFALSE;
538     }
539   }
540
541   return kTRUE;
542 }
543
544 //_____________________________________________________________________________
545 Bool_t AliSimulation::RunTrigger(const char* descriptors)
546 {
547   // run the trigger
548
549   TStopwatch stopwatch;
550   stopwatch.Start();
551
552   AliRunLoader* runLoader = LoadRun("READ");
553   if (!runLoader) return kFALSE;
554   TString des = descriptors;
555   // Load Descriptors
556   AliCentralTrigger* aCTP = new AliCentralTrigger( des );
557
558   // digits -> trigger
559   if( !aCTP->RunTrigger( runLoader ) ) {
560     if (fStopOnError) {
561       delete aCTP;
562       return kFALSE;
563     }
564   }
565
566 /*
567   // Process each event
568   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
569     AliInfo(Form("processing event %d", iEvent));
570     runLoader->GetEvent(iEvent);
571
572     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
573     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
574       AliModule* det = (AliModule*) detArray->At(iDet);
575       if (!det || !det->IsActive()) continue;
576       if (IsSelected(det->GetName(), detStr)) {
577         AliInfo(Form("triggering from digits for %s", det->GetName()));
578
579      //   AliLoader* loader = fLoader[iDet];
580      //   loader->LoadDigits("read");
581      //   TTree* digitsTree = loader->TreeD();
582      //   det->Trigger( digitsTree );
583      // or
584         AliTriggerDetector* tdet = det->CreateTriggerDetector();
585         TObjArray* detInp = dtrg->GetTriggerInputs();
586         for( Int_t i=0; i<detInp->GetEntriesFast(); i++ )
587                fInputs.AddLast( detInp->At(i) );
588
589         AliInfo(Form("Execution time for %s: R:%.2fs C:%.2fs",
590                 det->GetName(),stopwatchDet.RealTime(),stopwatchDet.CpuTime()));
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) {
598          delete centralTP;
599          return kFALSE;
600       }
601     }
602
603     // Check trigger conditions
604     centralTP->TriggerConditions();
605
606     // Write trigger ????
607     centralTP->Write();
608
609   } */
610
611   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
612                stopwatch.RealTime(),stopwatch.CpuTime()));
613
614   delete aCTP;
615   delete runLoader;
616
617   return kTRUE;
618 }
619
620
621
622 //_____________________________________________________________________________
623 Bool_t AliSimulation::RunSimulation(Int_t nEvents)
624 {
625 // run the generation and simulation
626
627   TStopwatch stopwatch;
628   stopwatch.Start();
629
630   if (!gAlice) {
631     AliError("no gAlice object. Restart aliroot and try again.");
632     return kFALSE;
633   }
634   if (gAlice->Modules()->GetEntries() > 0) {
635     AliError("gAlice was already run. Restart aliroot and try again.");
636     return kFALSE;
637   }
638
639   AliInfo(Form("initializing gAlice with config file %s",
640           fConfigFileName.Data()));
641   StdoutToAliInfo(StderrToAliError(
642     gAlice->Init(fConfigFileName.Data());
643   ););
644
645   // Set run number in CDBManager (here????)
646   AliCDBManager::Instance()->SetRun(gAlice->GetRunNumber());
647   AliInfo(Form("Run number: %d",AliCDBManager::Instance()->GetRun()));
648
649   AliRunLoader* runLoader = gAlice->GetRunLoader();
650   if (!runLoader) {
651              AliError(Form("gAlice has no run loader object. "
652                              "Check your config file: %s", fConfigFileName.Data()));
653              return kFALSE;
654   }
655   SetGAliceFile(runLoader->GetFileName());
656  
657   // Load alignment data from CDB and fill fAlignObjArray 
658
659   if(fLoadAlignFromCDB){
660         if(!fAlignObjArray) fAlignObjArray = new TObjArray();
661         
662         //fAlignObjArray->RemoveAll(); 
663         fAlignObjArray->Clear();        
664         fAlignObjArray->SetOwner(0);
665  
666         TString detStr = fLoadAlignData;
667         TString dataNotLoaded="";
668         TString dataLoaded="";
669   
670         TObjArray* detArray = runLoader->GetAliRun()->Detectors();
671         for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
672                 AliModule* det = (AliModule*) detArray->At(iDet);
673                 if (!det || !det->IsActive()) continue;
674                 if (IsSelected(det->GetName(), detStr)) {
675                         if(!SetAlignObjArraySingleDet(det->GetName())){
676                                 dataNotLoaded += det->GetName();
677                                 dataNotLoaded += " ";
678                         } else {
679                                 dataLoaded += det->GetName();
680                                 dataLoaded += " ";
681                         }
682                 }
683         } // end loop over detectors
684   
685         if ((detStr.CompareTo("ALL") == 0)) detStr = "";
686         dataNotLoaded += detStr;
687         AliInfo(Form("Alignment data loaded for: %s",
688                           dataLoaded.Data()));
689         AliInfo(Form("Didn't/couldn't load alignment data for: %s",
690                           dataNotLoaded.Data()));
691   } // fLoadAlignFromCDB flag
692  
693   // Check if the array with alignment objects was
694   // provided by the user. If yes, apply the objects
695   // to the present TGeo geometry
696   if (fAlignObjArray) {
697     if (gGeoManager && gGeoManager->IsClosed()) {
698       if (gAlice->ApplyAlignObjsToGeom(fAlignObjArray) == kFALSE) {
699         AliError("The application of misalignment failed! Restart aliroot and try again. ");
700         return kFALSE;
701       }
702     }
703     else {
704       AliError("Can't apply the misalignment! gGeoManager doesn't exist or it is still opened!");
705       return kFALSE;
706     }
707   }
708
709   // Export TGeo geometry
710   if (gGeoManager) gGeoManager->Export("geometry.root");
711
712 //   AliRunLoader* runLoader = gAlice->GetRunLoader();
713 //   if (!runLoader) {
714 //     AliError(Form("gAlice has no run loader object. "
715 //                   "Check your config file: %s", fConfigFileName.Data()));
716 //     return kFALSE;
717 //   }
718 //   SetGAliceFile(runLoader->GetFileName());
719
720   if (!gAlice->Generator()) {
721     AliError(Form("gAlice has no generator object. "
722                   "Check your config file: %s", fConfigFileName.Data()));
723     return kFALSE;
724   }
725   if (nEvents <= 0) nEvents = fNEvents;
726
727   // get vertex from background file in case of merging
728   if (fUseBkgrdVertex &&
729       fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
730     Int_t signalPerBkgrd = GetNSignalPerBkgrd(nEvents);
731     const char* fileName = ((TObjString*)
732                             (fBkgrdFileNames->At(0)))->GetName();
733     AliInfo(Form("The vertex will be taken from the background "
734                  "file %s with nSignalPerBackground = %d", 
735                  fileName, signalPerBkgrd));
736     AliVertexGenFile* vtxGen = new AliVertexGenFile(fileName, signalPerBkgrd);
737     gAlice->Generator()->SetVertexGenerator(vtxGen);
738   }
739
740   if (!fRunSimulation) {
741     gAlice->Generator()->SetTrackingFlag(0);
742   }
743
744   // set the number of events per file for given detectors and data types
745   for (Int_t i = 0; i < fEventsPerFile.GetEntriesFast(); i++) {
746     if (!fEventsPerFile[i]) continue;
747     const char* detName = fEventsPerFile[i]->GetName();
748     const char* typeName = fEventsPerFile[i]->GetTitle();
749     TString loaderName(detName);
750     loaderName += "Loader";
751     AliLoader* loader = runLoader->GetLoader(loaderName);
752     if (!loader) {
753       AliError(Form("RunSimulation", "no loader for %s found\n"
754                     "Number of events per file not set for %s %s", 
755                     detName, typeName, detName));
756       continue;
757     }
758     AliDataLoader* dataLoader = 
759       loader->GetDataLoader(typeName);
760     if (!dataLoader) {
761       AliError(Form("no data loader for %s found\n"
762                     "Number of events per file not set for %s %s", 
763                     typeName, detName, typeName));
764       continue;
765     }
766     dataLoader->SetNumberOfEventsPerFile(fEventsPerFile[i]->GetUniqueID());
767     AliDebug(1, Form("number of events per file set to %d for %s %s",
768                      fEventsPerFile[i]->GetUniqueID(), detName, typeName));
769   }
770
771   AliInfo("running gAlice");
772   StdoutToAliInfo(StderrToAliError(
773     gAlice->Run(nEvents);
774   ););
775
776   delete runLoader;
777
778   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
779                stopwatch.RealTime(),stopwatch.CpuTime()));
780
781   return kTRUE;
782 }
783
784 //_____________________________________________________________________________
785 Bool_t AliSimulation::RunSDigitization(const char* detectors)
786 {
787 // run the digitization and produce summable digits
788
789   TStopwatch stopwatch;
790   stopwatch.Start();
791
792   AliRunLoader* runLoader = LoadRun();
793   if (!runLoader) return kFALSE;
794
795   TString detStr = detectors;
796   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
797   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
798     AliModule* det = (AliModule*) detArray->At(iDet);
799     if (!det || !det->IsActive()) continue;
800     if (IsSelected(det->GetName(), detStr)) {
801       AliInfo(Form("creating summable digits for %s", det->GetName()));
802       TStopwatch stopwatchDet;
803       stopwatchDet.Start();
804       det->Hits2SDigits();
805       AliInfo(Form("Execution time for %s: R:%.2fs C:%.2fs",
806            det->GetName(),stopwatchDet.RealTime(),stopwatchDet.CpuTime()));
807     }
808   }
809
810   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
811     AliError(Form("the following detectors were not found: %s",
812                   detStr.Data()));
813     if (fStopOnError) return kFALSE;
814   }
815
816   delete runLoader;
817
818   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
819            stopwatch.RealTime(),stopwatch.CpuTime()));
820
821   return kTRUE;
822 }
823
824
825 //_____________________________________________________________________________
826 Bool_t AliSimulation::RunDigitization(const char* detectors, 
827                                       const char* excludeDetectors)
828 {
829 // run the digitization and produce digits from sdigits
830
831   TStopwatch stopwatch;
832   stopwatch.Start();
833
834   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
835   if (gAlice) delete gAlice;
836   gAlice = NULL;
837
838   Int_t nStreams = 1;
839   if (fBkgrdFileNames) nStreams = fBkgrdFileNames->GetEntriesFast() + 1;
840   Int_t signalPerBkgrd = GetNSignalPerBkgrd();
841   AliRunDigitizer* manager = new AliRunDigitizer(nStreams, signalPerBkgrd);
842   manager->SetInputStream(0, fGAliceFileName.Data());
843   for (Int_t iStream = 1; iStream < nStreams; iStream++) {
844     const char* fileName = ((TObjString*)
845                             (fBkgrdFileNames->At(iStream-1)))->GetName();
846     manager->SetInputStream(iStream, fileName);
847   }
848
849   TString detStr = detectors;
850   TString detExcl = excludeDetectors;
851   manager->GetInputStream(0)->ImportgAlice();
852   AliRunLoader* runLoader = 
853     AliRunLoader::GetRunLoader(manager->GetInputStream(0)->GetFolderName());
854   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
855   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
856     AliModule* det = (AliModule*) detArray->At(iDet);
857     if (!det || !det->IsActive()) continue;
858     if (IsSelected(det->GetName(), detStr) && 
859         !IsSelected(det->GetName(), detExcl)) {
860       AliDigitizer* digitizer = det->CreateDigitizer(manager);
861       if (!digitizer) {
862         AliError(Form("no digitizer for %s", det->GetName()));
863         if (fStopOnError) return kFALSE;
864       } else {
865         digitizer->SetRegionOfInterest(fRegionOfInterest);
866       }
867     }
868   }
869
870   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
871     AliError(Form("the following detectors were not found: %s", 
872                   detStr.Data()));
873     if (fStopOnError) return kFALSE;
874   }
875
876   if (!manager->GetListOfTasks()->IsEmpty()) {
877     AliInfo("executing digitization");
878     manager->Exec("");
879   }
880
881   delete manager;
882
883   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
884                stopwatch.RealTime(),stopwatch.CpuTime()));
885   
886   return kTRUE;
887 }
888
889 //_____________________________________________________________________________
890 Bool_t AliSimulation::RunHitsDigitization(const char* detectors)
891 {
892 // run the digitization and produce digits from hits
893
894   TStopwatch stopwatch;
895   stopwatch.Start();
896
897   AliRunLoader* runLoader = LoadRun("READ");
898   if (!runLoader) return kFALSE;
899
900   TString detStr = detectors;
901   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
902   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
903     AliModule* det = (AliModule*) detArray->At(iDet);
904     if (!det || !det->IsActive()) continue;
905     if (IsSelected(det->GetName(), detStr)) {
906       AliInfo(Form("creating digits from hits for %s", det->GetName()));
907       det->Hits2Digits();
908     }
909   }
910
911   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
912     AliError(Form("the following detectors were not found: %s", 
913                   detStr.Data()));
914     if (fStopOnError) return kFALSE;
915   }
916
917   delete runLoader;
918   //PH Temporary fix to avoid interference with the PHOS loder/getter
919   //PH The problem has to be solved in more general way 09/06/05
920
921   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
922                stopwatch.RealTime(),stopwatch.CpuTime()));
923
924   return kTRUE;
925 }
926
927 //_____________________________________________________________________________
928 Bool_t AliSimulation::WriteRawData(const char* detectors, 
929                                    const char* fileName,
930                                    Bool_t deleteIntermediateFiles)
931 {
932 // convert the digits to raw data
933 // First DDL raw data files for the given detectors are created.
934 // If a file name is given, the DDL files are then converted to a DATE file.
935 // If deleteIntermediateFiles is true, the DDL raw files are deleted 
936 // afterwards.
937 // If the file name has the extension ".root", the DATE file is converted
938 // to a root file.
939 // If deleteIntermediateFiles is true, the DATE file is deleted afterwards.
940
941   TStopwatch stopwatch;
942   stopwatch.Start();
943
944   if (!WriteRawFiles(detectors)) {
945     if (fStopOnError) return kFALSE;
946   }
947
948   TString dateFileName(fileName);
949   if (!dateFileName.IsNull()) {
950     Bool_t rootOutput = dateFileName.EndsWith(".root");
951     if (rootOutput) dateFileName += ".date";
952     if (!ConvertRawFilesToDate(dateFileName)) {
953       if (fStopOnError) return kFALSE;
954     }
955     if (deleteIntermediateFiles) {
956       AliRunLoader* runLoader = LoadRun("READ");
957       if (runLoader) for (Int_t iEvent = 0; 
958                           iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
959         char command[256];
960         sprintf(command, "rm -r raw%d", iEvent);
961         gSystem->Exec(command);
962       }
963     }
964
965     if (rootOutput) {
966       if (!ConvertDateToRoot(dateFileName, fileName)) {
967         if (fStopOnError) return kFALSE;
968       }
969       if (deleteIntermediateFiles) {
970         gSystem->Unlink(dateFileName);
971       }
972     }
973   }
974
975   AliInfo(Form("Execution time: R:%.2fs C:%.2fs",
976                stopwatch.RealTime(),stopwatch.CpuTime()));
977
978   return kTRUE;
979 }
980
981 //_____________________________________________________________________________
982 Bool_t AliSimulation::WriteRawFiles(const char* detectors)
983 {
984 // convert the digits to raw data DDL files
985
986   AliRunLoader* runLoader = LoadRun("READ");
987   if (!runLoader) return kFALSE;
988
989   // write raw data to DDL files
990   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
991     AliInfo(Form("processing event %d", iEvent));
992     runLoader->GetEvent(iEvent);
993     TString baseDir = gSystem->WorkingDirectory();
994     char dirName[256];
995     sprintf(dirName, "raw%d", iEvent);
996     gSystem->MakeDirectory(dirName);
997     if (!gSystem->ChangeDirectory(dirName)) {
998       AliError(Form("couldn't change to directory %s", dirName));
999       if (fStopOnError) return kFALSE; else continue;
1000     }
1001
1002     TString detStr = detectors;
1003     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
1004     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
1005       AliModule* det = (AliModule*) detArray->At(iDet);
1006       if (!det || !det->IsActive()) continue;
1007       if (IsSelected(det->GetName(), detStr)) {
1008         AliInfo(Form("creating raw data from digits for %s", det->GetName()));
1009         det->Digits2Raw();
1010       }
1011     }
1012
1013     gSystem->ChangeDirectory(baseDir);
1014     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
1015       AliError(Form("the following detectors were not found: %s", 
1016                     detStr.Data()));
1017       if (fStopOnError) return kFALSE;
1018     }
1019   }
1020
1021   delete runLoader;
1022   return kTRUE;
1023 }
1024
1025 //_____________________________________________________________________________
1026 Bool_t AliSimulation::ConvertRawFilesToDate(const char* dateFileName)
1027 {
1028 // convert raw data DDL files to a DATE file with the program "dateStream"
1029
1030   char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
1031   if (!path) {
1032     AliError("the program dateStream was not found");
1033     if (fStopOnError) return kFALSE;
1034   } else {
1035     delete[] path;
1036   }
1037
1038   AliRunLoader* runLoader = LoadRun("READ");
1039   if (!runLoader) return kFALSE;
1040
1041   AliInfo(Form("converting raw data DDL files to DATE file %s", dateFileName));
1042   char command[256];
1043   sprintf(command, "dateStream -o %s -# %d -C", 
1044           dateFileName, runLoader->GetNumberOfEvents());
1045   FILE* pipe = gSystem->OpenPipe(command, "w");
1046
1047   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
1048     fprintf(pipe, "GDC\n");
1049     Float_t ldc = 0;
1050     Int_t prevLDC = -1;
1051
1052     // loop over detectors and DDLs
1053     for (Int_t iDet = 0; iDet < kNDetectors; iDet++) {
1054       for (Int_t iDDL = 0; iDDL < kDetectorDDLs[iDet]; iDDL++) {
1055
1056         Int_t ddlID = 0x100*iDet + iDDL;
1057         Int_t ldcID = Int_t(ldc + 0.0001);
1058         ldc += kDetectorLDCs[iDet] / kDetectorDDLs[iDet];
1059
1060         char rawFileName[256];
1061         sprintf(rawFileName, "raw%d/%s_%d.ddl", 
1062                 iEvent, kDetectors[iDet], ddlID);
1063
1064         // check existence and size of raw data file
1065         FILE* file = fopen(rawFileName, "rb");
1066         if (!file) continue;
1067         fseek(file, 0, SEEK_END);
1068         unsigned long size = ftell(file);
1069         fclose(file);
1070         if (!size) continue;
1071
1072         if (ldcID != prevLDC) {
1073           fprintf(pipe, " LDC Id %d\n", ldcID);
1074           prevLDC = ldcID;
1075         }
1076         fprintf(pipe, "  Equipment Id %d Payload %s\n", ddlID, rawFileName);
1077       }
1078     }
1079   }
1080
1081   Int_t result = gSystem->ClosePipe(pipe);
1082
1083   delete runLoader;
1084   return (result == 0);
1085 }
1086
1087 //_____________________________________________________________________________
1088 Bool_t AliSimulation::ConvertDateToRoot(const char* dateFileName,
1089                                         const char* rootFileName)
1090 {
1091 // convert a DATE file to a root file with the program "alimdc"
1092
1093   // ALIMDC setup
1094   const Int_t kDBSize = 1000000000;
1095   const Int_t kTagDBSize = 1000000000;
1096   const Bool_t kFilter = kFALSE;
1097   const Int_t kCompression = 1;
1098
1099   char* path = gSystem->Which(gSystem->Getenv("PATH"), "alimdc");
1100   if (!path) {
1101     AliError("the program alimdc was not found");
1102     if (fStopOnError) return kFALSE;
1103   } else {
1104     delete[] path;
1105   }
1106
1107   AliInfo(Form("converting DATE file %s to root file %s", 
1108                dateFileName, rootFileName));
1109
1110   const char* rawDBFS[2] = { "/tmp/mdc1", "/tmp/mdc2" };
1111   const char* tagDBFS    = "/tmp/mdc1/tags";
1112   const char* runDBFS    = "/tmp/mdc1/meta";
1113
1114   // User defined file system locations
1115   if (gSystem->Getenv("ALIMDC_RAWDB1")) 
1116     rawDBFS[0] = gSystem->Getenv("ALIMDC_RAWDB1");
1117   if (gSystem->Getenv("ALIMDC_RAWDB2")) 
1118     rawDBFS[1] = gSystem->Getenv("ALIMDC_RAWDB2");
1119   if (gSystem->Getenv("ALIMDC_TAGDB")) 
1120     tagDBFS = gSystem->Getenv("ALIMDC_TAGDB");
1121   if (gSystem->Getenv("ALIMDC_RUNDB")) 
1122     runDBFS = gSystem->Getenv("ALIMDC_RUNDB");
1123
1124   gSystem->Exec(Form("rm -rf %s",rawDBFS[0]));
1125   gSystem->Exec(Form("rm -rf %s",rawDBFS[1]));
1126   gSystem->Exec(Form("rm -rf %s",tagDBFS));
1127   gSystem->Exec(Form("rm -rf %s",runDBFS));
1128
1129   gSystem->Exec(Form("mkdir %s",rawDBFS[0]));
1130   gSystem->Exec(Form("mkdir %s",rawDBFS[1]));
1131   gSystem->Exec(Form("mkdir %s",tagDBFS));
1132   gSystem->Exec(Form("mkdir %s",runDBFS));
1133
1134   Int_t result = gSystem->Exec(Form("alimdc %d %d %d %d %s", 
1135                                     kDBSize, kTagDBSize, kFilter, kCompression, dateFileName));
1136   gSystem->Exec(Form("mv %s/*.root %s", rawDBFS[0], rootFileName));
1137
1138   gSystem->Exec(Form("rm -rf %s",rawDBFS[0]));
1139   gSystem->Exec(Form("rm -rf %s",rawDBFS[1]));
1140   gSystem->Exec(Form("rm -rf %s",tagDBFS));
1141   gSystem->Exec(Form("rm -rf %s",runDBFS));
1142
1143   return (result == 0);
1144 }
1145
1146
1147 //_____________________________________________________________________________
1148 AliRunLoader* AliSimulation::LoadRun(const char* mode) const
1149 {
1150 // delete existing run loaders, open a new one and load gAlice
1151
1152   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
1153   AliRunLoader* runLoader = 
1154     AliRunLoader::Open(fGAliceFileName.Data(), 
1155                        AliConfig::GetDefaultEventFolderName(), mode);
1156   if (!runLoader) {
1157     AliError(Form("no run loader found in file %s", fGAliceFileName.Data()));
1158     return NULL;
1159   }
1160   runLoader->LoadgAlice();
1161   gAlice = runLoader->GetAliRun();
1162   if (!gAlice) {
1163     AliError(Form("no gAlice object found in file %s", 
1164                   fGAliceFileName.Data()));
1165     return NULL;
1166   }
1167   return runLoader;
1168 }
1169
1170 //_____________________________________________________________________________
1171 Int_t AliSimulation::GetNSignalPerBkgrd(Int_t nEvents) const
1172 {
1173 // get or calculate the number of signal events per background event
1174
1175   if (!fBkgrdFileNames) return 1;
1176   Int_t nBkgrdFiles = fBkgrdFileNames->GetEntriesFast();
1177   if (nBkgrdFiles == 0) return 1;
1178
1179   // get the number of signal events
1180   if (nEvents <= 0) {
1181     AliRunLoader* runLoader = 
1182       AliRunLoader::Open(fGAliceFileName.Data(), "SIGNAL");
1183     if (!runLoader) return 1;
1184     nEvents = runLoader->GetNumberOfEvents();
1185     delete runLoader;
1186   }
1187
1188   Int_t result = 0;
1189   for (Int_t iBkgrdFile = 0; iBkgrdFile < nBkgrdFiles; iBkgrdFile++) {
1190     // get the number of background events
1191     const char* fileName = ((TObjString*)
1192                             (fBkgrdFileNames->At(iBkgrdFile)))->GetName();
1193     AliRunLoader* runLoader = 
1194       AliRunLoader::Open(fileName, "BKGRD");
1195     if (!runLoader) continue;
1196     Int_t nBkgrdEvents = runLoader->GetNumberOfEvents();
1197     delete runLoader;
1198
1199     // get or calculate the number of signal per background events
1200     Int_t nSignalPerBkgrd = fBkgrdFileNames->At(iBkgrdFile)->GetUniqueID();
1201     if (nSignalPerBkgrd <= 0) {
1202       nSignalPerBkgrd = (nEvents-1) / nBkgrdEvents + 1;
1203     } else if (result && (result != nSignalPerBkgrd)) {
1204       AliInfo(Form("the number of signal events per background event "
1205                    "will be changed from %d to %d for stream %d", 
1206                    nSignalPerBkgrd, result, iBkgrdFile+1));
1207       nSignalPerBkgrd = result;
1208     }
1209
1210     if (!result) result = nSignalPerBkgrd;
1211     if (nSignalPerBkgrd * nBkgrdEvents < nEvents) {
1212       AliWarning(Form("not enough background events (%d) for %d signal events "
1213                       "using %d signal per background events for stream %d",
1214                       nBkgrdEvents, nEvents, nSignalPerBkgrd, iBkgrdFile+1));
1215     }
1216   }
1217
1218   return result;
1219 }
1220
1221 //_____________________________________________________________________________
1222 Bool_t AliSimulation::IsSelected(TString detName, TString& detectors) const
1223 {
1224 // check whether detName is contained in detectors
1225 // if yes, it is removed from detectors
1226
1227   // check if all detectors are selected
1228   if ((detectors.CompareTo("ALL") == 0) ||
1229       detectors.BeginsWith("ALL ") ||
1230       detectors.EndsWith(" ALL") ||
1231       detectors.Contains(" ALL ")) {
1232     detectors = "ALL";
1233     return kTRUE;
1234   }
1235
1236   // search for the given detector
1237   Bool_t result = kFALSE;
1238   if ((detectors.CompareTo(detName) == 0) ||
1239       detectors.BeginsWith(detName+" ") ||
1240       detectors.EndsWith(" "+detName) ||
1241       detectors.Contains(" "+detName+" ")) {
1242     detectors.ReplaceAll(detName, "");
1243     result = kTRUE;
1244   }
1245
1246   // clean up the detectors string
1247   while (detectors.Contains("  ")) detectors.ReplaceAll("  ", " ");
1248   while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
1249   while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
1250
1251   return result;
1252 }