10d2f557cbf9352f7940ca7dfe710c15ee15a8ac
[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   SetDebug(10);
267   
268   if (!static_cast<AliStream*>(fInputStreams->At(0))->ImportgAlice()) 
269    {
270      Error("Digitize","Error occured while getting gAlice from Input 0");
271      return;
272    }
273     
274   if (!InitGlobal()) //calls Init() for all (sub)digitizers
275    {
276      Error("Digitize","InitGlobal returned error");
277      return;
278    }
279    
280   Int_t eventsCreated = 0;
281 // loop until there is anything on the input in case fNrOfEventsToWrite < 0
282   while ((eventsCreated++ < fNrOfEventsToWrite) || (fNrOfEventsToWrite < 0)) 
283    {
284       if (!ConnectInputTrees()) break;
285       InitEvent();//this must be after call of Connect Input tress.
286       if (fOutRunLoader)
287        {
288          fOutRunLoader->SetEventNumber(eventsCreated-1);
289        }
290       static_cast<AliStream*>(fInputStreams->At(0))->ImportgAlice(); // use gAlice of the first input stream
291       ExecuteTasks(option);// loop over all registered digitizers and let them do the work
292       FinishEvent();
293       CleanTasks();
294    }
295   FinishGlobal();
296 }
297
298 //_______________________________________________________________________
299 Bool_t AliRunDigitizer::ConnectInputTrees()
300 {
301   //
302   // loads events 
303   //
304   Int_t eventNr[MAXSTREAMSTOMERGE], delta[MAXSTREAMSTOMERGE];
305   fCombi->Combination(eventNr, delta);
306   for (Int_t i=0;i<fNinputs;i++) 
307    {
308     if (delta[i] == 1)
309      {
310       AliStream *iStream = static_cast<AliStream*>(fInputStreams->At(i));//gets the "i" defined  in combination
311       if (!iStream->NextEventInStream()) return kFALSE; //sets serial number
312      } 
313     else if (delta[i] != 0) 
314      {
315       Error("ConnectInputTrees","Only delta 0 or 1 is implemented");
316       return kFALSE;
317      }
318    }
319
320   return kTRUE;
321 }
322
323 //_______________________________________________________________________
324 Bool_t AliRunDigitizer::InitGlobal()
325 {
326   //
327   // Method called once before Digitize() is called
328   // initialize digitizers and output
329   //
330   fOutputInitialized = kFALSE;
331   TList* subTasks = this->GetListOfTasks();
332   if (subTasks) {
333     TIter next(subTasks);
334     while (AliDigitizer * dig = (AliDigitizer *) next())
335      dig->Init();
336   }
337   return kTRUE;
338 }
339
340 //_______________________________________________________________________
341
342 void AliRunDigitizer::SetOutputFile(TString fn)
343 {
344   //
345   // The output will be to separate file, 
346   // not to the signal file here should be protection 
347   //to avoid setting the same file as any input 
348   //
349   Info("SetOutputFile","Setting Output File Name %s ",fn.Data());
350   fOutputFileName = fn;
351   // InitOutputGlobal();
352 }
353
354 //_______________________________________________________________________
355 Bool_t AliRunDigitizer::InitOutputGlobal()
356 {
357   //
358   // Creates the output file, called by InitEvent()
359   // Needs to be called after all inputs are opened  
360   //
361   if (fOutputInitialized) return kTRUE;
362   
363   if ( !fOutputFileName.IsNull())
364    {
365     fOutRunLoader = AliRunLoader::Open(fOutputFileName,fgkDefOutFolderName,"recreate");
366     
367     if (fOutRunLoader == 0x0)
368      {
369        Error("InitOutputGlobal","Can not open ooutput");
370        return kFALSE;
371      }
372     Info("InitOutputGlobal", " 1 %s = ", GetInputFolderName(0).Data()) ; 
373     AliRunLoader* inrl = AliRunLoader::GetRunLoader(GetInputFolderName(0));
374     if (inrl == 0x0)
375      {
376        Error("InitOutputGlobal","Can not get Run Loader Input 0. Maybe yet not initialized?");
377        return kFALSE;
378      }
379     Info("InitOutputGlobal", " 2 %#x = ", inrl) ; 
380
381     //Copy all detector loaders from input 0 to output
382     const TObjArray* inloaders = inrl->GetArrayOfLoaders();
383     TIter next(inloaders);
384     AliLoader *loader;
385     while((loader = (AliLoader*)next()))
386      {
387        AliLoader* cloneloader = (AliLoader*)loader->Clone();
388        cloneloader->Register(fOutRunLoader->GetEventFolder());//creates folders for this loader in Output Folder Structure
389        GetOutRunLoader()->AddLoader(cloneloader);//adds a loader for output
390      }
391
392     fOutRunLoader->MakeTree("E");
393     
394     if (GetDebug()>2)  Info("InitOutputGlobal","file %s was opened.",fOutputFileName.Data());
395    }
396   fOutputInitialized = kTRUE; 
397   return kTRUE;
398 }
399 //_______________________________________________________________________
400
401 void AliRunDigitizer::InitEvent()
402 {
403   //
404   // redirects output properly
405   //
406   if (GetDebug()>2)
407    {
408     Info("InitEvent","fEvent = %d",fEvent);
409     Info("InitEvent","fOutputFileName \"%s\"",fOutputFileName.Data());
410    }
411   if (fOutputInitialized == kFALSE) InitOutputGlobal();
412   
413   // if fOutputFileName was not given, write output to signal directory
414 }
415 //_______________________________________________________________________
416
417 void AliRunDigitizer::FinishEvent()
418 {
419   //
420   // called at the end of loop over digitizers
421   //
422   
423   if (GetOutRunLoader() == 0x0)
424    {
425      Error("FinishEvent","fOutRunLoader is null");
426      return;
427    }
428   
429   fEvent++;
430   fNrOfEventsWritten++;
431   
432   if (fOutRunLoader)
433   {
434      AliRunLoader* inrl = AliRunLoader::GetRunLoader(GetInputFolderName(0));
435      AliHeader* outheader = fOutRunLoader->GetHeader();
436      AliHeader* inheader = inrl->GetHeader();
437      if (inheader == 0x0)
438      {
439        inrl->LoadHeader();
440        inheader = inrl->GetHeader();
441        if (inheader == 0x0) Fatal("FinishEvent","Can not get header from input 0");
442      }
443      
444      outheader->SetNprimary(inheader->GetNprimary());
445      outheader->SetNtrack(inheader->GetNtrack());
446      outheader->SetEvent(inheader->GetEvent());
447      outheader->SetEventNrInRun(inheader->GetEventNrInRun());
448      outheader->SetNvertex(inheader->GetNvertex());
449      fOutRunLoader->TreeE()->Fill();
450   }
451       
452   if (fCopyTreesFromInput > -1) 
453    {
454     //this is sensless since no information would be coherent in case of merging
455     //
456     cout<<"Copy trees from input: Copy or link files manually"<<endl;
457     return;
458    }
459 }
460 //_______________________________________________________________________
461
462 void AliRunDigitizer::FinishGlobal()
463 {
464   //
465   // called at the end of Exec
466   // save unique objects to the output file
467   //
468   if (GetOutRunLoader() == 0x0)
469    {
470      Error("FinishGlobal","Can not get RunLoader from Output Stream folder");
471      return;
472    }
473   GetOutRunLoader()->CdGAFile();
474   this->Write(NULL, TObject::kOverwrite);
475   if (fOutRunLoader)
476    {
477      fOutRunLoader->WriteHeader("OVERWRITE");
478      fOutRunLoader->WriteRunLoader("OVERWRITE");
479      TFolder* outfolder = fOutRunLoader->GetEventFolder();
480      if (outfolder == 0x0)
481      {
482        Error("FinishEvent","Can not get Event Folder");
483        return;
484      }    
485   
486      AliRunLoader* inRN = AliRunLoader::GetRunLoader(GetInputFolderName(0));
487      outfolder->Add(inRN->GetAliRun());
488      fOutRunLoader->WriteAliRun("OVERWRITE");
489    }
490    
491   if (fCopyTreesFromInput > -1) 
492    {
493      //copy files manually
494    }
495 }
496 //_______________________________________________________________________
497
498 Int_t  AliRunDigitizer::GetNParticles(Int_t event) const
499 {
500 // return number of particles in all input files for a given
501 // event (as numbered in the output file)
502 // return -1 if some file cannot be accessed
503
504   Int_t sum = 0;
505   Int_t sumI;
506   for (Int_t i = 0; i < fNinputs; i++) {
507     sumI = GetNParticles(GetInputEventNumber(event,i), i);
508     if (sumI < 0) return -1;
509     sum += sumI;
510   }
511   return sum;
512 }
513 //_______________________________________________________________________
514
515 Int_t  AliRunDigitizer::GetNParticles(Int_t /*event*/, Int_t /*input*/) const
516 {
517 // return number of particles in input file input for a given
518 // event (as numbered in this input file)
519 // return -1 if some error
520
521 // Must be revised in the version with AliStream
522
523   return -1;
524
525 }
526
527 //_______________________________________________________________________
528 Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event) const
529 {
530 // return pointer to an int array with input event numbers which were
531 // merged in the output event event
532
533 // simplified for now, implement later
534   Int_t * a = new Int_t[MAXSTREAMSTOMERGE];
535   for (Int_t i = 0; i < fNinputs; i++) {
536     a[i] = event;
537   }
538   return a;
539 }
540 //_______________________________________________________________________
541 Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t /*input*/) const
542 {
543 // return an event number of an eventInput from input file input
544 // which was merged to create output event event
545
546 // simplified for now, implement later
547   return event;
548 }
549 //_______________________________________________________________________
550 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event) const
551 {
552 // return pointer to particle with index i (index with mask)
553
554 // decode the MASK
555   Int_t input = i/fkMASKSTEP;
556   return GetParticle(i,input,GetInputEventNumber(event,input));
557 }
558
559 //_______________________________________________________________________
560 TParticle* AliRunDigitizer::GetParticle(Int_t /*i*/, Int_t /*input*/, Int_t /*event*/) const
561 {
562 // return pointer to particle with index i in the input file input
563 // (index without mask)
564 // event is the event number in the file input
565 // return 0 i fit does not exist
566
567 // Must be revised in the version with AliStream
568
569   return 0;
570 }
571
572 //_______________________________________________________________________
573 void AliRunDigitizer::ExecuteTask(Option_t* option)
574 {
575   //
576   // overwrite ExecuteTask to do Digitize only
577   //
578   if (!IsActive()) return;
579   Digitize(option);
580   fHasExecuted = kTRUE;
581   return;
582 }
583
584 //_______________________________________________________________________
585 const TString& AliRunDigitizer::GetInputFolderName(Int_t i) const
586 {
587   //
588   // Get the input Folder Name
589   //
590   AliStream* stream = dynamic_cast<AliStream*>(fInputStreams->At(i));
591   if (stream == 0x0)
592     Fatal("GetInputFolderName","Can not get the input stream. Index = %d. Exiting",i);
593   return stream->GetFolderName();
594 }
595 //_______________________________________________________________________
596
597 const char* AliRunDigitizer::GetOutputFolderName()
598 {
599   //
600   // Get output folder name
601   //
602   return GetOutRunLoader()->GetEventFolder()->GetName();
603 }
604 //_______________________________________________________________________
605
606 AliRunLoader* AliRunDigitizer::GetOutRunLoader()
607 {
608   //
609   // Returns Run Loader
610   //
611   if (fOutRunLoader) return fOutRunLoader;
612   
613   if ( fOutputFileName.IsNull() )
614    {//guard that sombody calls it without settting file name
615     cout<<"Output file name is empty. Using Input 0 for output\n";
616     return AliRunLoader::GetRunLoader(GetInputFolderName(0));
617    }
618 //  InitOutputGlobal();
619   return fOutRunLoader;
620 }
621 //_______________________________________________________________________
622
623 TString AliRunDigitizer::GetInputFileName(Int_t input, Int_t order) const 
624 {
625 // returns file name of the order-th file in the input stream input
626 // returns empty string if such file does not exist
627 // first input stream is 0
628 // first file in the input stream is 0
629   TString fileName("");
630   if (input >= fNinputs) return fileName;
631   AliStream * stream = static_cast<AliStream*>(fInputStreams->At(input));
632   if (order > stream->GetNInputFiles()) return fileName;
633   fileName = stream->GetFileName(order);
634   return fileName;
635 }