03414e1c9bbd4bfa5e88295ebe52c5e3e48eef61
[u/mrichter/AliRoot.git] / STEER / AliRunDigitizer.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 // AliRunDigitizer.cxx
21 //
22 // Manager object for merging/digitization
23 //
24 // Instance of this class manages the digitization and/or merging of
25 // Sdigits into Digits. 
26 //
27 // Only one instance of this class is created in the macro:
28 //   AliRunDigitizer * manager = 
29 //      new AliRunDigitizer(nInputStreams,SPERB);
30 // where nInputStreams is number of input streams and SPERB is
31 // signals per background variable, which determines how combinations
32 // of signal and background events are generated.
33 // Then instances of specific detector digitizers are created:
34 //   AliMUONDigitizer *dMUON  = new AliMUONDigitizer(manager)
35 // and the I/O configured (you have to specify input files 
36 // and an output file). The manager connects appropriate trees from 
37 // the input files according a combination returned by AliMergeCombi 
38 // class. It creates TreeD in the output and runs once per 
39 // event Digitize method of all existing AliDetDigitizers 
40 // (without any option). AliDetDigitizers ask manager
41 // for a TTree with input (manager->GetInputTreeS(Int_t i),
42 // merge all inputs, digitize it, and save it in the TreeD 
43 // obtained by manager->GetTreeD(). Output events are stored with 
44 // numbers from 0, this default can be changed by 
45 // manager->SetFirstOutputEventNr(Int_t) method. The particle numbers
46 // in the output are shifted by MASK, which is taken from manager.
47 //
48 // The default output is to the signal file (stream 0). This can be 
49 // changed with the SetOutputFile(TString fn)  method.
50 //
51 // Single input file is permitted. Maximum MAXSTREAMSTOMERGE can be merged.
52 // Input from the memory (on-the-fly merging) is not yet 
53 // supported, as well as access to the input data by invoking methods
54 // on the output data.
55 //
56 // Access to the some data is via gAlice for now (supposing the 
57 // same geometry in all input files), gAlice is taken from the first 
58 // input file on the first stream.
59 //
60 // Example with MUON digitizer, no merging, just digitization
61 //
62 //  AliRunDigitizer * manager = new AliRunDigitizer(1,1);
63 //  manager->SetInputStream(0,"galice.root");
64 //  AliMUONDigitizer *dMUON  = new AliMUONDigitizer(manager);
65 //  manager->Exec("");
66 //
67 // Example with MUON digitizer, merge all events from 
68 //   galice.root (signal) file with events from bgr.root 
69 //   (background) file. Number of merged events is
70 //   min(number of events in galice.root, number of events in bgr.root)
71 //
72 //  AliRunDigitizer * manager = new AliRunDigitizer(2,1);
73 //  manager->SetInputStream(0,"galice.root");
74 //  manager->SetInputStream(1,"bgr.root");
75 //  AliMUONDigitizer *dMUON  = new AliMUONDigitizer(manager);
76 //  manager->Exec("");
77 //
78 // Example with MUON digitizer, save digits in a new file digits.root,
79 //   process only 1 event
80 //
81 //  AliRunDigitizer * manager = new AliRunDigitizer(2,1);
82 //  manager->SetInputStream(0,"galice.root");
83 //  manager->SetInputStream(1,"bgr.root");
84 //  manager->SetOutputFile("digits.root");
85 //  AliMUONDigitizer *dMUON  = new AliMUONDigitizer(manager);
86 //  manager->SetNrOfEventsToWrite(1);
87 //  manager->Exec("");
88 //
89 //_______________________________________________________________________ 
90
91 // system includes
92
93 // ROOT includes
94
95 #include <Riostream.h>
96 class TList;
97
98 // AliROOT includes
99
100 #include "AliDigitizer.h"
101 #include "AliHeader.h"
102 #include "AliLoader.h"
103 #include "AliMergeCombi.h"
104 #include "AliRun.h"
105 #include "AliRunDigitizer.h"
106 #include "AliRunLoader.h"
107
108 ClassImp(AliRunDigitizer)
109
110 const TString AliRunDigitizer::fgkDefOutFolderName("Output");
111 const TString AliRunDigitizer::fgkBaseInFolderName("Input");
112
113
114 //_______________________________________________________________________
115 AliRunDigitizer::AliRunDigitizer():
116  fkMASKSTEP(0),
117  fOutputFileName(0),
118  fOutputDirName(0),
119  fEvent(0),
120  fNrOfEventsToWrite(0),
121  fNrOfEventsWritten(0),
122  fCopyTreesFromInput(0),
123  fNinputs(0),
124  fNinputsGiven(0),
125  fInputStreams(0x0),
126  fOutRunLoader(0x0),
127  fOutputInitialized(kFALSE),
128  fCombi(0),
129  fCombination(0),
130  fCombinationFileName(0),
131  fDebug(0)
132 {
133   //
134   // root requires default ctor, where no new objects can be created
135   // do not use this ctor, it is supplied only for root needs
136 }
137
138 //_______________________________________________________________________
139 AliRunDigitizer::AliRunDigitizer(Int_t nInputStreams, Int_t sperb):
140  TTask("AliRunDigitizer","The manager for Merging"),
141  fkMASKSTEP(10000000),
142  fOutputFileName(""),
143  fOutputDirName("."),
144  fEvent(0),
145  fNrOfEventsToWrite(-1),
146  fNrOfEventsWritten(0),
147  fCopyTreesFromInput(-1),
148  fNinputs(nInputStreams),
149  fNinputsGiven(0),
150  fInputStreams(new TClonesArray("AliStream",nInputStreams)),
151  fOutRunLoader(0x0),
152  fOutputInitialized(kFALSE),
153  fCombi(new AliMergeCombi(nInputStreams,sperb)),
154  fCombination(MAXSTREAMSTOMERGE),
155  fCombinationFileName(0),
156  fDebug(0)
157
158 {
159   //
160   // ctor which should be used to create 
161   // a manager for merging/digitization
162   //
163   if (nInputStreams == 0) 
164    {//kidding
165     Fatal("AliRunDigitizer","Specify nr of input streams");
166     return;
167    }
168   Int_t i;
169   
170   fkMASK[0] = 0;
171   
172   for (i=1;i<MAXSTREAMSTOMERGE;i++) 
173    {
174     fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
175    }
176   
177   TClonesArray &lInputStreams = *fInputStreams;
178   
179   new(lInputStreams[0]) AliStream(fgkBaseInFolderName+(Long_t)0,"UPDATE");
180   for (i=1;i<nInputStreams;i++) {
181     new(lInputStreams[i]) AliStream(fgkBaseInFolderName+(Long_t)i,"READ");
182   }
183 }
184 //_______________________________________________________________________
185
186 AliRunDigitizer::AliRunDigitizer(const AliRunDigitizer& dig):
187  TTask(dig),
188  fkMASKSTEP(0),
189  fOutputFileName(0),
190  fOutputDirName(0),
191  fEvent(0),
192  fNrOfEventsToWrite(0),
193  fNrOfEventsWritten(0),
194  fCopyTreesFromInput(0),
195  fNinputs(0),
196  fNinputsGiven(0),
197  fInputStreams(0x0),
198  fOutRunLoader(0x0),
199  fOutputInitialized(kFALSE),
200  fCombi(0),
201  fCombination(0),
202  fCombinationFileName(0),
203  fDebug(0)
204 {
205   //
206   // Copy ctor
207   //
208   dig.Copy(*this);
209 }
210 //_______________________________________________________________________
211
212 void AliRunDigitizer::Copy(TObject&) const
213 {
214   //
215   // Non implemented copy function
216   //
217   Fatal("Copy","Not installed\n");
218 }
219
220 //_______________________________________________________________________
221
222 AliRunDigitizer::~AliRunDigitizer() 
223 {
224   //
225   // dtor
226   //
227   delete fInputStreams;
228   delete fCombi;
229   delete fOutRunLoader;
230 }
231 //_______________________________________________________________________
232 void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
233 {
234   //
235   // add digitizer to the list of active digitizers
236   //
237   this->Add(digitizer);
238 }
239 //_______________________________________________________________________
240 void AliRunDigitizer::SetInputStream(Int_t i, const char *inputFile, TString foldername)
241 {
242 //
243 // Sets the name of the input file
244 //
245   if (i > fInputStreams->GetLast()) {
246     Error("SetInputStream","Input stream number too high");
247     return;
248   }
249   AliStream * stream = static_cast<AliStream*>(fInputStreams->At(i)) ; 
250   if ( !foldername.IsNull() ) {
251     if ( i > 0 ) 
252       foldername += i ; // foldername should stay unchanged for the default output 
253     stream->SetFolderName(foldername) ;
254   } 
255   stream->AddFile(inputFile);
256 }
257
258 //_______________________________________________________________________
259 void AliRunDigitizer::Digitize(Option_t* option)
260 {
261 // get a new combination of inputs, loads events to folders
262
263 // take gAlice from the first input file. It is needed to access
264 //  geometry data
265 // If gAlice is already in memory, use it
266   
267   if (!static_cast<AliStream*>(fInputStreams->At(0))->ImportgAlice()) 
268    {
269      Error("Digitize","Error occured while getting gAlice from Input 0");
270      return;
271    }
272     
273   if (!InitGlobal()) //calls Init() for all (sub)digitizers
274    {
275      Error("Digitize","InitGlobal returned error");
276      return;
277    }
278    
279   Int_t eventsCreated = 0;
280 // loop until there is anything on the input in case fNrOfEventsToWrite < 0
281   while ((eventsCreated++ < fNrOfEventsToWrite) || (fNrOfEventsToWrite < 0)) 
282    {
283       if (!ConnectInputTrees()) break;
284       InitEvent();//this must be after call of Connect Input tress.
285       if (fOutRunLoader)
286        {
287          fOutRunLoader->SetEventNumber(eventsCreated-1);
288        }
289       static_cast<AliStream*>(fInputStreams->At(0))->ImportgAlice(); // use gAlice of the first input stream
290       ExecuteTasks(option);// loop over all registered digitizers and let them do the work
291       FinishEvent();
292       CleanTasks();
293    }
294   FinishGlobal();
295 }
296
297 //_______________________________________________________________________
298 Bool_t AliRunDigitizer::ConnectInputTrees()
299 {
300   //
301   // loads events 
302   //
303   Int_t eventNr[MAXSTREAMSTOMERGE], delta[MAXSTREAMSTOMERGE];
304   fCombi->Combination(eventNr, delta);
305   for (Int_t i=0;i<fNinputs;i++) 
306    {
307     if (delta[i] == 1)
308      {
309       AliStream *iStream = static_cast<AliStream*>(fInputStreams->At(i));//gets the "i" defined  in combination
310       if (!iStream->NextEventInStream()) return kFALSE; //sets serial number
311      } 
312     else if (delta[i] != 0) 
313      {
314       Error("ConnectInputTrees","Only delta 0 or 1 is implemented");
315       return kFALSE;
316      }
317    }
318
319   return kTRUE;
320 }
321
322 //_______________________________________________________________________
323 Bool_t AliRunDigitizer::InitGlobal()
324 {
325   //
326   // Method called once before Digitize() is called
327   // initialize digitizers and output
328   //
329   fOutputInitialized = kFALSE;
330   TList* subTasks = this->GetListOfTasks();
331   if (subTasks) {
332     TIter next(subTasks);
333     while (AliDigitizer * dig = (AliDigitizer *) next())
334      dig->Init();
335   }
336   return kTRUE;
337 }
338
339 //_______________________________________________________________________
340
341 void AliRunDigitizer::SetOutputFile(TString fn)
342 {
343   //
344   // The output will be to separate file, 
345   // not to the signal file here should be protection 
346   //to avoid setting the same file as any input 
347   //
348   Info("SetOutputFile","Setting Output File Name %s ",fn.Data());
349   fOutputFileName = fn;
350   // InitOutputGlobal();
351 }
352
353 //_______________________________________________________________________
354 Bool_t AliRunDigitizer::InitOutputGlobal()
355 {
356   //
357   // Creates the output file, called by InitEvent()
358   // Needs to be called after all inputs are opened  
359   //
360   if (fOutputInitialized) return kTRUE;
361   
362   if ( !fOutputFileName.IsNull())
363    {
364     fOutRunLoader = AliRunLoader::Open(fOutputFileName,fgkDefOutFolderName,"recreate");
365     
366     if (fOutRunLoader == 0x0)
367      {
368        Error("InitOutputGlobal","Can not open ooutput");
369        return kFALSE;
370      }
371     Info("InitOutputGlobal", " 1 %s = ", GetInputFolderName(0).Data()) ; 
372     AliRunLoader* inrl = AliRunLoader::GetRunLoader(GetInputFolderName(0));
373     if (inrl == 0x0)
374      {
375        Error("InitOutputGlobal","Can not get Run Loader Input 0. Maybe yet not initialized?");
376        return kFALSE;
377      }
378     Info("InitOutputGlobal", " 2 %#x = ", inrl) ; 
379
380     //Copy all detector loaders from input 0 to output
381     const TObjArray* inloaders = inrl->GetArrayOfLoaders();
382     TIter next(inloaders);
383     AliLoader *loader;
384     while((loader = (AliLoader*)next()))
385      {
386        AliLoader* cloneloader = (AliLoader*)loader->Clone();
387        cloneloader->Register(fOutRunLoader->GetEventFolder());//creates folders for this loader in Output Folder Structure
388        GetOutRunLoader()->AddLoader(cloneloader);//adds a loader for output
389      }
390
391     fOutRunLoader->MakeTree("E");
392     
393     if (GetDebug()>2)  Info("InitOutputGlobal","file %s was opened.",fOutputFileName.Data());
394    }
395   fOutputInitialized = kTRUE; 
396   return kTRUE;
397 }
398 //_______________________________________________________________________
399
400 void AliRunDigitizer::InitEvent()
401 {
402   //
403   // redirects output properly
404   //
405   if (GetDebug()>2)
406    {
407     Info("InitEvent","fEvent = %d",fEvent);
408     Info("InitEvent","fOutputFileName \"%s\"",fOutputFileName.Data());
409    }
410   if (fOutputInitialized == kFALSE) InitOutputGlobal();
411   
412   // if fOutputFileName was not given, write output to signal directory
413 }
414 //_______________________________________________________________________
415
416 void AliRunDigitizer::FinishEvent()
417 {
418   //
419   // called at the end of loop over digitizers
420   //
421   
422   if (GetOutRunLoader() == 0x0)
423    {
424      Error("FinishEvent","fOutRunLoader is null");
425      return;
426    }
427   
428   fEvent++;
429   fNrOfEventsWritten++;
430   
431   if (fOutRunLoader)
432   {
433      AliRunLoader* inrl = AliRunLoader::GetRunLoader(GetInputFolderName(0));
434      AliHeader* outheader = fOutRunLoader->GetHeader();
435      AliHeader* inheader = inrl->GetHeader();
436      if (inheader == 0x0)
437      {
438        inrl->LoadHeader();
439        inheader = inrl->GetHeader();
440        if (inheader == 0x0) Fatal("FinishEvent","Can not get header from input 0");
441      }
442      
443      outheader->SetNprimary(inheader->GetNprimary());
444      outheader->SetNtrack(inheader->GetNtrack());
445      outheader->SetEvent(inheader->GetEvent());
446      outheader->SetEventNrInRun(inheader->GetEventNrInRun());
447      outheader->SetNvertex(inheader->GetNvertex());
448      fOutRunLoader->TreeE()->Fill();
449   }
450       
451   if (fCopyTreesFromInput > -1) 
452    {
453     //this is sensless since no information would be coherent in case of merging
454     //
455     cout<<"Copy trees from input: Copy or link files manually"<<endl;
456     return;
457    }
458 }
459 //_______________________________________________________________________
460
461 void AliRunDigitizer::FinishGlobal()
462 {
463   //
464   // called at the end of Exec
465   // save unique objects to the output file
466   //
467   if (GetOutRunLoader() == 0x0)
468    {
469      Error("FinishGlobal","Can not get RunLoader from Output Stream folder");
470      return;
471    }
472   GetOutRunLoader()->CdGAFile();
473   this->Write(NULL, TObject::kOverwrite);
474   if (fOutRunLoader)
475    {
476      fOutRunLoader->WriteHeader("OVERWRITE");
477      fOutRunLoader->WriteRunLoader("OVERWRITE");
478      TFolder* outfolder = fOutRunLoader->GetEventFolder();
479      if (outfolder == 0x0)
480      {
481        Error("FinishEvent","Can not get Event Folder");
482        return;
483      }    
484   
485      AliRunLoader* inRN = AliRunLoader::GetRunLoader(GetInputFolderName(0));
486      outfolder->Add(inRN->GetAliRun());
487      fOutRunLoader->WriteAliRun("OVERWRITE");
488    }
489    
490   if (fCopyTreesFromInput > -1) 
491    {
492      //copy files manually
493    }
494 }
495 //_______________________________________________________________________
496
497 Int_t  AliRunDigitizer::GetNParticles(Int_t event) const
498 {
499 // return number of particles in all input files for a given
500 // event (as numbered in the output file)
501 // return -1 if some file cannot be accessed
502
503   Int_t sum = 0;
504   Int_t sumI;
505   for (Int_t i = 0; i < fNinputs; i++) {
506     sumI = GetNParticles(GetInputEventNumber(event,i), i);
507     if (sumI < 0) return -1;
508     sum += sumI;
509   }
510   return sum;
511 }
512 //_______________________________________________________________________
513
514 Int_t  AliRunDigitizer::GetNParticles(Int_t /*event*/, Int_t /*input*/) const
515 {
516 // return number of particles in input file input for a given
517 // event (as numbered in this input file)
518 // return -1 if some error
519
520 // Must be revised in the version with AliStream
521
522   return -1;
523
524 }
525
526 //_______________________________________________________________________
527 Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event) const
528 {
529 // return pointer to an int array with input event numbers which were
530 // merged in the output event event
531
532 // simplified for now, implement later
533   Int_t * a = new Int_t[MAXSTREAMSTOMERGE];
534   for (Int_t i = 0; i < fNinputs; i++) {
535     a[i] = event;
536   }
537   return a;
538 }
539 //_______________________________________________________________________
540 Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t /*input*/) const
541 {
542 // return an event number of an eventInput from input file input
543 // which was merged to create output event event
544
545 // simplified for now, implement later
546   return event;
547 }
548 //_______________________________________________________________________
549 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event) const
550 {
551 // return pointer to particle with index i (index with mask)
552
553 // decode the MASK
554   Int_t input = i/fkMASKSTEP;
555   return GetParticle(i,input,GetInputEventNumber(event,input));
556 }
557
558 //_______________________________________________________________________
559 TParticle* AliRunDigitizer::GetParticle(Int_t /*i*/, Int_t /*input*/, Int_t /*event*/) const
560 {
561 // return pointer to particle with index i in the input file input
562 // (index without mask)
563 // event is the event number in the file input
564 // return 0 i fit does not exist
565
566 // Must be revised in the version with AliStream
567
568   return 0;
569 }
570
571 //_______________________________________________________________________
572 void AliRunDigitizer::ExecuteTask(Option_t* option)
573 {
574   //
575   // overwrite ExecuteTask to do Digitize only
576   //
577   if (!IsActive()) return;
578   Digitize(option);
579   fHasExecuted = kTRUE;
580   return;
581 }
582
583 //_______________________________________________________________________
584 const TString& AliRunDigitizer::GetInputFolderName(Int_t i) const
585 {
586   //
587   // Get the input Folder Name
588   //
589   AliStream* stream = dynamic_cast<AliStream*>(fInputStreams->At(i));
590   if (stream == 0x0)
591     Fatal("GetInputFolderName","Can not get the input stream. Index = %d. Exiting",i);
592   return stream->GetFolderName();
593 }
594 //_______________________________________________________________________
595
596 const char* AliRunDigitizer::GetOutputFolderName()
597 {
598   //
599   // Get output folder name
600   //
601   return GetOutRunLoader()->GetEventFolder()->GetName();
602 }
603 //_______________________________________________________________________
604
605 AliRunLoader* AliRunDigitizer::GetOutRunLoader()
606 {
607   //
608   // Returns Run Loader
609   //
610   if (fOutRunLoader) return fOutRunLoader;
611   
612   if ( fOutputFileName.IsNull() )
613    {//guard that sombody calls it without settting file name
614     if (GetDebug()>0) {
615       Info("GetOutRunLoader", 
616            "Output file name is empty. Using Input 0 for output");
617     }
618     return AliRunLoader::GetRunLoader(GetInputFolderName(0));
619    }
620 //  InitOutputGlobal();
621   return fOutRunLoader;
622 }
623 //_______________________________________________________________________
624
625 TString AliRunDigitizer::GetInputFileName(Int_t input, Int_t order) const 
626 {
627 // returns file name of the order-th file in the input stream input
628 // returns empty string if such file does not exist
629 // first input stream is 0
630 // first file in the input stream is 0
631   TString fileName("");
632   if (input >= fNinputs) return fileName;
633   AliStream * stream = static_cast<AliStream*>(fInputStreams->At(input));
634   if (order > stream->GetNInputFiles()) return fileName;
635   fileName = stream->GetFileName(order);
636   return fileName;
637 }