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