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