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