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