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