]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliSimulation.cxx
option to set the number of events per file for individual detectors and data types
[u/mrichter/AliRoot.git] / STEER / AliSimulation.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 // class for running generation, simulation and digitization                 //
21 //                                                                           //
22 // Hits, sdigits and digits are created for all detectors by typing:         //
23 //                                                                           //
24 //   AliSimulation sim;                                                      //
25 //   sim.Run();                                                              //
26 //                                                                           //
27 // The Run method returns kTRUE in case of successful execution.             //
28 // The number of events can be given as argument to the Run method or it     //
29 // can be set by                                                             //
30 //                                                                           //
31 //   sim.SetNumberOfEvents(n);                                               //
32 //                                                                           //
33 // The name of the configuration file can be passed as argument to the       //
34 // AliSimulation constructor or can be specified by                          //
35 //                                                                           //
36 //   sim.SetConfigFile("...");                                               //
37 //                                                                           //
38 // The generation of particles and the simulation of detector hits can be    //
39 // switched on or off by                                                     //
40 //                                                                           //
41 //   sim.SetRunGeneration(kTRUE);   // generation of primary particles       //
42 //   sim.SetRunSimulation(kFALSE);  // but no tracking                       //
43 //                                                                           //
44 // For which detectors sdigits and digits will be created, can be steered    //
45 // by                                                                        //
46 //                                                                           //
47 //   sim.SetMakeSDigits("ALL");     // make sdigits for all detectors        //
48 //   sim.SetMakeDigits("ITS TPC");  // make digits only for ITS and TPC      //
49 //                                                                           //
50 // The argument is a (case sensitive) string with the names of the           //
51 // detectors separated by a space. An empty string ("") can be used to       //
52 // disable the creation of sdigits or digits. The special string "ALL"       //
53 // selects all available detectors. This is the default.                     //
54 //                                                                           //
55 // The creation of digits from hits instead of from sdigits can be selected  //
56 // by                                                                        //
57 //                                                                           //
58 //   sim.SetMakeDigitsFromHits("TRD");                                       //
59 //                                                                           //
60 // The argument is again a string with the selected detectors. Be aware that //
61 // this feature is not available for all detectors and that merging is not   //
62 // possible, when digits are created directly from hits.                     //
63 //                                                                           //
64 // Background events can be merged by calling                                //
65 //                                                                           //
66 //   sim.MergeWith("background/galice.root", 2);                             //
67 //                                                                           //
68 // The first argument is the file name of the background galice file. The    //
69 // second argument is the number of signal events per background event.      //
70 // By default this number is calculated from the number of available         //
71 // background events. MergeWith can be called several times to merge more    //
72 // than two event streams. It is assumed that the sdigits were already       //
73 // produced for the background events.                                       //
74 //                                                                           //
75 // The output of raw data can be switched on by calling                      //
76 //                                                                           //
77 //   sim.SetWriteRawData("MUON");   // write raw data for MUON               //
78 //                                                                           //
79 // The methods RunSimulation, RunSDigitization, RunDigitization,             //
80 // RunHitsDigitization and WriteRawData can be used to run only parts of     //
81 // the full simulation chain.                                                //
82 //                                                                           //
83 // The default number of events per file, which is usually set in the        //
84 // config file, can be changed for individual detectors and data types       //
85 // by calling                                                                //
86 //                                                                           //
87 //   sim.SetEventsPerFile("PHOS", "Reconstructed Points", 3);                //
88 //                                                                           //
89 // The first argument is the detector, the second one the data type and the  //
90 // last one the number of events per file. Valid data types are "Hits",      //
91 // "Summable Digits", "Digits", "Reconstructed Points" and "Tracks".         //
92 // The number of events per file has to be set before the simulation of      //
93 // hits. Otherwise it has no effect.                                         //
94 //                                                                           //
95 ///////////////////////////////////////////////////////////////////////////////
96
97 #include <TObjString.h>
98 #include <TStopwatch.h>
99 #include <TSystem.h>
100
101 #include "AliDigitizer.h"
102 #include "AliGenerator.h"
103 #include "AliModule.h"
104 #include "AliRun.h"
105 #include "AliRunDigitizer.h"
106 #include "AliRunLoader.h"
107 #include "AliSimulation.h"
108 #include "AliVertexGenFile.h"
109
110 ClassImp(AliSimulation)
111
112
113 //_____________________________________________________________________________
114 AliSimulation::AliSimulation(const char* configFileName,
115                              const char* name, const char* title) :
116   TNamed(name, title),
117
118   fRunGeneration(kTRUE),
119   fRunSimulation(kTRUE),
120   fMakeSDigits("ALL"),
121   fMakeDigits("ALL"),
122   fMakeDigitsFromHits(""),
123   fWriteRawData(""),
124   fStopOnError(kFALSE),
125
126   fNEvents(1),
127   fConfigFileName(configFileName),
128   fGAliceFileName("galice.root"),
129   fEventsPerFile(),
130   fBkgrdFileNames(NULL),
131   fUseBkgrdVertex(kTRUE),
132   fRegionOfInterest(kTRUE)
133 {
134 // create simulation object with default parameters
135
136   SetGAliceFile("galice.root");
137 }
138
139 //_____________________________________________________________________________
140 AliSimulation::AliSimulation(const AliSimulation& sim) :
141   TNamed(sim),
142
143   fRunGeneration(sim.fRunGeneration),
144   fRunSimulation(sim.fRunSimulation),
145   fMakeSDigits(sim.fMakeSDigits),
146   fMakeDigits(sim.fMakeDigits),
147   fMakeDigitsFromHits(sim.fMakeDigitsFromHits),
148   fWriteRawData(sim.fWriteRawData),
149   fStopOnError(sim.fStopOnError),
150
151   fNEvents(sim.fNEvents),
152   fConfigFileName(sim.fConfigFileName),
153   fGAliceFileName(sim.fGAliceFileName),
154   fEventsPerFile(),
155   fBkgrdFileNames(NULL),
156   fUseBkgrdVertex(sim.fUseBkgrdVertex),
157   fRegionOfInterest(sim.fRegionOfInterest)
158 {
159 // copy constructor
160
161   for (Int_t i = 0; i < sim.fEventsPerFile.GetEntriesFast(); i++) {
162     if (!sim.fEventsPerFile[i]) continue;
163     fEventsPerFile.Add(sim.fEventsPerFile[i]->Clone());
164   }
165
166   fBkgrdFileNames = new TObjArray;
167   for (Int_t i = 0; i < sim.fBkgrdFileNames->GetEntriesFast(); i++) {
168     if (!sim.fBkgrdFileNames->At(i)) continue;
169     fBkgrdFileNames->Add(sim.fBkgrdFileNames->At(i)->Clone());
170   }
171 }
172
173 //_____________________________________________________________________________
174 AliSimulation& AliSimulation::operator = (const AliSimulation& sim)
175 {
176 // assignment operator
177
178   this->~AliSimulation();
179   new(this) AliSimulation(sim);
180   return *this;
181 }
182
183 //_____________________________________________________________________________
184 AliSimulation::~AliSimulation()
185 {
186 // clean up
187
188   fEventsPerFile.Delete();
189
190   if (fBkgrdFileNames) {
191     fBkgrdFileNames->Delete();
192     delete fBkgrdFileNames;
193   }
194 }
195
196
197 //_____________________________________________________________________________
198 void AliSimulation::SetNumberOfEvents(Int_t nEvents)
199 {
200 // set the number of events for one run
201
202   fNEvents = nEvents;
203 }
204
205 //_____________________________________________________________________________
206 void AliSimulation::SetConfigFile(const char* fileName)
207 {
208 // set the name of the config file
209
210   fConfigFileName = fileName;
211 }
212
213 //_____________________________________________________________________________
214 void AliSimulation::SetGAliceFile(const char* fileName)
215 {
216 // set the name of the galice file
217 // the path is converted to an absolute one if it is relative
218
219   fGAliceFileName = fileName;
220   if (!gSystem->IsAbsoluteFileName(fGAliceFileName)) {
221     char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
222                                                 fGAliceFileName);
223     fGAliceFileName = absFileName;
224     delete[] absFileName;
225   }
226 }
227
228 //_____________________________________________________________________________
229 void AliSimulation::SetEventsPerFile(const char* detector, const char* type, 
230                                      Int_t nEvents)
231 {
232 // set the number of events per file for the given detector and data type
233 // ("Hits", "Summable Digits", "Digits", "Reconstructed Points" or "Tracks")
234
235   TNamed* obj = new TNamed(detector, type);
236   obj->SetUniqueID(nEvents);
237   fEventsPerFile.Add(obj);
238 }
239
240 //_____________________________________________________________________________
241 void AliSimulation::MergeWith(const char* fileName, Int_t nSignalPerBkgrd)
242 {
243 // add a file with background events for merging
244
245   TObjString* fileNameStr = new TObjString(fileName);
246   fileNameStr->SetUniqueID(nSignalPerBkgrd);
247   if (!fBkgrdFileNames) fBkgrdFileNames = new TObjArray;
248   fBkgrdFileNames->Add(fileNameStr);
249 }
250
251
252 //_____________________________________________________________________________
253 Bool_t AliSimulation::Run(Int_t nEvents)
254 {
255 // run the generation, simulation and digitization
256
257   if (nEvents > 0) fNEvents = nEvents;
258
259   // generation and simulation -> hits
260   if (fRunGeneration) {
261     if (!RunSimulation()) if (fStopOnError) return kFALSE;
262   }
263
264   // hits -> summable digits
265   if (!fMakeSDigits.IsNull()) {
266     if (!RunSDigitization(fMakeSDigits)) if (fStopOnError) return kFALSE;
267   }
268
269   // summable digits -> digits
270   if (!fMakeDigits.IsNull()) {
271     if (!RunDigitization(fMakeDigits, fMakeDigitsFromHits)) {
272       if (fStopOnError) return kFALSE;
273     }
274   }
275
276   // hits -> digits
277   if (!fMakeDigitsFromHits.IsNull()) {
278     if (fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
279       Warning("Run", "Merging and direct creation of digits from hits " 
280               "was selected for some detectors. "
281               "No merging will be done for the following detectors: %s",
282               fMakeDigitsFromHits.Data());
283     }
284     if (!RunHitsDigitization(fMakeDigitsFromHits)) {
285       if (fStopOnError) return kFALSE;
286     }
287   }
288
289   // digits -> raw data
290   if (!fWriteRawData.IsNull()) {
291     if (!WriteRawData(fWriteRawData)) {
292       if (fStopOnError) return kFALSE;
293     }
294   }
295
296   return kTRUE;
297 }
298
299 //_____________________________________________________________________________
300 Bool_t AliSimulation::RunSimulation(Int_t nEvents)
301 {
302 // run the generation and simulation
303
304   TStopwatch stopwatch;
305   stopwatch.Start();
306
307   if (!gAlice) {
308     Error("RunSimulation", "no gAlice object. Restart aliroot and try again.");
309     return kFALSE;
310   }
311   if (gAlice->Modules()->GetEntries() > 0) {
312     Error("RunSimulation", 
313           "gAlice was already run. Restart aliroot and try again.");
314     return kFALSE;
315   }
316
317   Info("RunSimulation", "initializing gAlice with config file %s",
318        fConfigFileName.Data());
319   gAlice->Init(fConfigFileName.Data());
320   AliRunLoader* runLoader = gAlice->GetRunLoader();
321   if (!runLoader) {
322     Error("RunSimulation", "gAlice has no run loader object. "
323           "Check your config file: %s", fConfigFileName.Data());
324     return kFALSE;
325   }
326   SetGAliceFile(runLoader->GetFileName());
327
328   if (!gAlice->Generator()) {
329     Error("RunSimulation", "gAlice has no generator object. "
330           "Check your config file: %s", fConfigFileName.Data());
331     return kFALSE;
332   }
333   if (nEvents <= 0) nEvents = fNEvents;
334
335   // get vertex from background file in case of merging
336   if (fUseBkgrdVertex &&
337       fBkgrdFileNames && (fBkgrdFileNames->GetEntriesFast() > 0)) {
338     Int_t signalPerBkgrd = GetNSignalPerBkgrd(nEvents);
339     const char* fileName = ((TObjString*)
340                             (fBkgrdFileNames->At(0)))->GetName();
341     Info("RunSimulation", "The vertex will be taken from the background "
342          "file %s with nSignalPerBackground = %d", 
343          fileName, signalPerBkgrd);
344     AliVertexGenFile* vtxGen = new AliVertexGenFile(fileName, signalPerBkgrd);
345     gAlice->Generator()->SetVertexGenerator(vtxGen);
346   }
347
348   if (!fRunSimulation) {
349     gAlice->Generator()->SetTrackingFlag(0);
350   }
351
352   // set the number of events per file for given detectors and data types
353   for (Int_t i = 0; i < fEventsPerFile.GetEntriesFast(); i++) {
354     if (!fEventsPerFile[i]) continue;
355     const char* detName = fEventsPerFile[i]->GetName();
356     const char* typeName = fEventsPerFile[i]->GetTitle();
357     TString loaderName(detName);
358     loaderName += "Loader";
359     AliLoader* loader = runLoader->GetLoader(loaderName);
360     if (!loader) {
361       Error("RunSimulation", "no loader for %s found\n"
362             "Number of events per file not set for %s %s", 
363             detName, typeName, detName);
364       continue;
365     }
366     AliDataLoader* dataLoader = 
367       loader->GetDataLoader(typeName);
368     if (!dataLoader) {
369       Error("RunSimulation", "no data loader for %s found\n"
370             "Number of events per file not set for %s %s", 
371             typeName, detName, typeName);
372       continue;
373     }
374     dataLoader->SetNumberOfEventsPerFile(fEventsPerFile[i]->GetUniqueID());
375     Info("RunSimulation", "number of events per file set to %d for %s %s",
376          fEventsPerFile[i]->GetUniqueID(), detName, typeName);
377   }
378
379   Info("RunSimulation", "running gAlice");
380   gAlice->Run(nEvents);
381
382   delete runLoader;
383
384   Info("RunSimulation", "execution time:");
385   stopwatch.Print();
386
387   return kTRUE;
388 }
389
390 //_____________________________________________________________________________
391 Bool_t AliSimulation::RunSDigitization(const char* detectors)
392 {
393 // run the digitization and produce summable digits
394
395   TStopwatch stopwatch;
396   stopwatch.Start();
397
398   AliRunLoader* runLoader = LoadRun();
399   if (!runLoader) return kFALSE;
400
401   TString detStr = detectors;
402   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
403   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
404     AliModule* det = (AliModule*) detArray->At(iDet);
405     if (!det || !det->IsActive()) continue;
406     if (IsSelected(det->GetName(), detStr)) {
407       Info("RunSDigitization", "creating summable digits for %s", 
408            det->GetName());
409       TStopwatch stopwatchDet;
410       stopwatchDet.Start();
411       det->Hits2SDigits();
412       Info("RunSDigitization", "execution time for %s:", det->GetName());
413       stopwatchDet.Print();
414     }
415   }
416
417   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
418     Error("RunSDigitization", "the following detectors were not found: %s", 
419           detStr.Data());
420     if (fStopOnError) return kFALSE;
421   }
422
423   delete runLoader;
424
425   Info("RunSDigitization", "execution time:");
426   stopwatch.Print();
427
428   return kTRUE;
429 }
430
431
432 //_____________________________________________________________________________
433 Bool_t AliSimulation::RunDigitization(const char* detectors, 
434                                       const char* excludeDetectors)
435 {
436 // run the digitization and produce digits from sdigits
437
438   TStopwatch stopwatch;
439   stopwatch.Start();
440
441   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
442   if (gAlice) delete gAlice;
443   gAlice = NULL;
444
445   Int_t nStreams = 1;
446   if (fBkgrdFileNames) nStreams = fBkgrdFileNames->GetEntriesFast() + 1;
447   Int_t signalPerBkgrd = GetNSignalPerBkgrd();
448   AliRunDigitizer* manager = new AliRunDigitizer(nStreams, signalPerBkgrd);
449   manager->SetInputStream(0, fGAliceFileName.Data());
450   for (Int_t iStream = 1; iStream < nStreams; iStream++) {
451     const char* fileName = ((TObjString*)
452                             (fBkgrdFileNames->At(iStream-1)))->GetName();
453     manager->SetInputStream(iStream, fileName);
454   }
455
456   TString detStr = detectors;
457   TString detExcl = excludeDetectors;
458   manager->GetInputStream(0)->ImportgAlice();
459   AliRunLoader* runLoader = 
460     AliRunLoader::GetRunLoader(manager->GetInputStream(0)->GetFolderName());
461   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
462   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
463     AliModule* det = (AliModule*) detArray->At(iDet);
464     if (!det || !det->IsActive()) continue;
465     if (IsSelected(det->GetName(), detStr) && 
466         !IsSelected(det->GetName(), detExcl)) {
467       AliDigitizer* digitizer = det->CreateDigitizer(manager);
468       if (!digitizer) {
469         Error("RunDigitization", "no digitizer for %s", det->GetName());
470         if (fStopOnError) return kFALSE;
471       } else {
472         digitizer->SetRegionOfInterest(fRegionOfInterest);
473       }
474     }
475   }
476
477   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
478     Error("RunDigitization", "the following detectors were not found: %s", 
479           detStr.Data());
480     if (fStopOnError) return kFALSE;
481   }
482
483   if (!manager->GetListOfTasks()->IsEmpty()) {
484     Info("RunDigitization", "executing digitization");
485     manager->Exec("");
486   }
487
488   delete manager;
489
490   Info("RunDigitization", "execution time:");
491   stopwatch.Print();
492
493   return kTRUE;
494 }
495
496 //_____________________________________________________________________________
497 Bool_t AliSimulation::RunHitsDigitization(const char* detectors)
498 {
499 // run the digitization and produce digits from hits
500
501   TStopwatch stopwatch;
502   stopwatch.Start();
503
504   AliRunLoader* runLoader = LoadRun();
505   if (!runLoader) return kFALSE;
506
507   TString detStr = detectors;
508   TObjArray* detArray = runLoader->GetAliRun()->Detectors();
509   for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
510     AliModule* det = (AliModule*) detArray->At(iDet);
511     if (!det || !det->IsActive()) continue;
512     if (IsSelected(det->GetName(), detStr)) {
513       Info("RunHitsDigitization", "creating digits from hits for %s", 
514            det->GetName());
515       det->Hits2Digits();
516     }
517   }
518
519   if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
520     Error("RunHitsDigitization", "the following detectors were not found: %s", 
521           detStr.Data());
522     if (fStopOnError) return kFALSE;
523   }
524
525   delete runLoader;
526
527   Info("RunHitsDigitization", "execution time:");
528   stopwatch.Print();
529
530   return kTRUE;
531 }
532
533 //_____________________________________________________________________________
534 Bool_t AliSimulation::WriteRawData(const char* detectors)
535 {
536 // convert the digits to raw data
537
538   TStopwatch stopwatch;
539   stopwatch.Start();
540
541   AliRunLoader* runLoader = LoadRun();
542   if (!runLoader) return kFALSE;
543
544   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++) {
545     Info("WriteRawData", "processing event %d", iEvent);
546     runLoader->GetEvent(iEvent);
547     TString baseDir = gSystem->WorkingDirectory();
548     char dirName[256];
549     sprintf(dirName, "raw%d", iEvent);
550     gSystem->MakeDirectory(dirName);
551     if (!gSystem->ChangeDirectory(dirName)) {
552       Error("WriteRawData", "couldn't change to directory %s", dirName);
553       if (fStopOnError) return kFALSE; else continue;
554     }
555
556     TString detStr = detectors;
557     TObjArray* detArray = runLoader->GetAliRun()->Detectors();
558     for (Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++) {
559       AliModule* det = (AliModule*) detArray->At(iDet);
560       if (!det || !det->IsActive()) continue;
561       if (IsSelected(det->GetName(), detStr)) {
562         Info("WriteRawData", "creating raw data from digits for %s", 
563              det->GetName());
564         det->Digits2Raw();
565       }
566     }
567
568     gSystem->ChangeDirectory(baseDir);
569     if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
570       Error("WriteRawData", "the following detectors were not found: %s", 
571             detStr.Data());
572       if (fStopOnError) return kFALSE;
573     }
574   }
575
576   delete runLoader;
577
578   Info("WriteRawData", "execution time:");
579   stopwatch.Print();
580
581   return kTRUE;
582 }
583
584
585 //_____________________________________________________________________________
586 AliRunLoader* AliSimulation::LoadRun() const
587 {
588 // delete existing run loaders, open a new one and load gAlice
589
590   while (AliRunLoader::GetRunLoader()) delete AliRunLoader::GetRunLoader();
591   AliRunLoader* runLoader = 
592     AliRunLoader::Open(fGAliceFileName.Data(), 
593                        AliConfig::GetDefaultEventFolderName(), "UPDATE");
594   if (!runLoader) {
595     Error("LoadRun", "no run loader found in file %s", 
596           fGAliceFileName.Data());
597     return NULL;
598   }
599   runLoader->LoadgAlice();
600   gAlice = runLoader->GetAliRun();
601   if (!gAlice) {
602     Error("LoadRun", "no gAlice object found in file %s", 
603           fGAliceFileName.Data());
604     return NULL;
605   }
606   return runLoader;
607 }
608
609 //_____________________________________________________________________________
610 Int_t AliSimulation::GetNSignalPerBkgrd(Int_t nEvents) const
611 {
612 // get or calculate the number of signal events per background event
613
614   if (!fBkgrdFileNames) return 1;
615   Int_t nBkgrdFiles = fBkgrdFileNames->GetEntriesFast();
616   if (nBkgrdFiles == 0) return 1;
617
618   // get the number of signal events
619   if (nEvents <= 0) {
620     AliRunLoader* runLoader = 
621       AliRunLoader::Open(fGAliceFileName.Data(), "SIGNAL");
622     if (!runLoader) return 1;
623     nEvents = runLoader->GetNumberOfEvents();
624     delete runLoader;
625   }
626
627   Int_t result = 0;
628   for (Int_t iBkgrdFile = 0; iBkgrdFile < nBkgrdFiles; iBkgrdFile++) {
629     // get the number of background events
630     const char* fileName = ((TObjString*)
631                             (fBkgrdFileNames->At(iBkgrdFile)))->GetName();
632     AliRunLoader* runLoader = 
633       AliRunLoader::Open(fileName, "BKGRD");
634     if (!runLoader) continue;
635     Int_t nBkgrdEvents = runLoader->GetNumberOfEvents();
636     delete runLoader;
637
638     // get or calculate the number of signal per background events
639     Int_t nSignalPerBkgrd = fBkgrdFileNames->At(iBkgrdFile)->GetUniqueID();
640     if (nSignalPerBkgrd <= 0) {
641       nSignalPerBkgrd = (nEvents-1) / nBkgrdEvents + 1;
642     } else if (result && (result != nSignalPerBkgrd)) {
643       Info("GetNSignalPerBkgrd", "the number of signal events per "
644            "background event will be changed from %d to %d for stream %d", 
645            nSignalPerBkgrd, result, iBkgrdFile+1);
646       nSignalPerBkgrd = result;
647     }
648
649     if (!result) result = nSignalPerBkgrd;
650     if (nSignalPerBkgrd * nBkgrdEvents < nEvents) {
651       Warning("GetNSignalPerBkgrd", "not enough background events (%d) for "
652               "%d signal events using %d signal per background events for "
653               "stream %d", 
654               nBkgrdEvents, nEvents, nSignalPerBkgrd, iBkgrdFile+1);
655     }
656   }
657
658   return result;
659 }
660
661 //_____________________________________________________________________________
662 Bool_t AliSimulation::IsSelected(TString detName, TString& detectors) const
663 {
664 // check whether detName is contained in detectors
665 // if yes, it is removed from detectors
666
667   // check if all detectors are selected
668   if ((detectors.CompareTo("ALL") == 0) ||
669       detectors.BeginsWith("ALL ") ||
670       detectors.EndsWith(" ALL") ||
671       detectors.Contains(" ALL ")) {
672     detectors = "ALL";
673     return kTRUE;
674   }
675
676   // search for the given detector
677   Bool_t result = kFALSE;
678   if ((detectors.CompareTo(detName) == 0) ||
679       detectors.BeginsWith(detName+" ") ||
680       detectors.EndsWith(" "+detName) ||
681       detectors.Contains(" "+detName+" ")) {
682     detectors.ReplaceAll(detName, "");
683     result = kTRUE;
684   }
685
686   // clean up the detectors string
687   while (detectors.Contains("  ")) detectors.ReplaceAll("  ", " ");
688   while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
689   while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
690
691   return result;
692 }