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