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