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