]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliRunDigitizer.cxx
f263d0c317ee597c8abf2598b965c90dc93a324a
[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 "AliRun.h"
106 #include "AliRunDigitizer.h"
107 #include "AliStream.h"
108
109 ClassImp(AliRunDigitizer)
110
111 //_______________________________________________________________________
112 AliRunDigitizer::AliRunDigitizer():
113   fkMASKSTEP(0),
114   fOutputFileName(0),
115   fOutputDirName(0),
116   fOutput(0),
117   fEvent(0),
118   fNrOfEventsToWrite(0),
119   fNrOfEventsWritten(0),
120   fCopyTreesFromInput(0),
121   fTreeD(0),
122   fTreeDTPC(0),
123   fTreeDTRD(0),
124   fTreeR(0),
125   fNinputs(0),
126   fNinputsGiven(0),
127   fInputStreams(0),
128   fTreeDTPCBaseName(0),
129   fTreeTPCSBaseName(0),
130   fCombi(0),
131   fCombination(0),
132   fCombinationFileName(0),
133   fDebug(0)
134 {
135   //
136   // default ctor, where no new objects can be created
137   // do not use this ctor, it is supplied only for root needs
138   //
139   for (Int_t i=0;i<kMaxStreamsToMerge;i++) {
140     fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
141     fInputFiles[i]=0;
142   }
143 }
144
145 //_______________________________________________________________________
146 AliRunDigitizer::AliRunDigitizer(const AliRunDigitizer& dig):
147   TTask(dig),
148   fkMASKSTEP(0),
149   fOutputFileName(0),
150   fOutputDirName(0),
151   fOutput(0),
152   fEvent(0),
153   fNrOfEventsToWrite(0),
154   fNrOfEventsWritten(0),
155   fCopyTreesFromInput(0),
156   fTreeD(0),
157   fTreeDTPC(0),
158   fTreeDTRD(0),
159   fTreeR(0),
160   fNinputs(0),
161   fNinputsGiven(0),
162   fInputStreams(0),
163   fTreeDTPCBaseName(0),
164   fTreeTPCSBaseName(0),
165   fCombi(0),
166   fCombination(0),
167   fCombinationFileName(0),
168   fDebug(0)
169 {
170   //
171   // Copy ctor
172   //
173   dig.Copy(*this);
174 }
175
176 //_______________________________________________________________________
177 void AliRunDigitizer::Copy(AliRunDigitizer&) const
178 {
179   Fatal("Copy","Not installed\n");
180 }
181
182
183 //_______________________________________________________________________
184 AliRunDigitizer::AliRunDigitizer(Int_t nInputStreams, Int_t sperb):
185   TTask("AliRunDigitizer","The manager for Merging"),
186   fkMASKSTEP(10000000),
187   fOutputFileName(""),
188   fOutputDirName("."),
189   fOutput(0),
190   fEvent(0),
191   fNrOfEventsToWrite(-1),
192   fNrOfEventsWritten(0),
193   fCopyTreesFromInput(-1),
194   fTreeD(0),
195   fTreeDTPC(0),
196   fTreeDTRD(0),
197   fTreeR(0),
198   fNinputs(nInputStreams),
199   fNinputsGiven(0),
200   fInputStreams(new TClonesArray("AliStream",nInputStreams)),
201   fTreeDTPCBaseName("TreeD_75x40_100x60_150x60_"),
202   fTreeTPCSBaseName("TreeS_75x40_100x60_150x60_"),
203   fCombi(new AliMergeCombi(nInputStreams,sperb)),
204   fCombination(kMaxStreamsToMerge),
205   fCombinationFileName(0),
206   fDebug(0)
207 {
208   //
209   // ctor which should be used to create a manager for merging/digitization
210   //
211   if (nInputStreams == 0) {
212     Error("AliRunDigitizer","Specify nr of input streams");
213     return;
214   }
215   for (Int_t i=0;i<kMaxStreamsToMerge;i++) {
216     fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
217     fCombination[i]=-1;
218   }
219   fkMASK[0] = 0;
220   for (Int_t i=1;i<kMaxStreamsToMerge;i++) {
221     fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
222   }
223
224   TClonesArray &lInputStreams = *fInputStreams;
225 // the first Input is open RW to be output as well
226   new(lInputStreams[0]) AliStream("UPDATE");
227   for (Int_t i=1;i<nInputStreams;i++) {
228     new(lInputStreams[i]) AliStream("READ");
229   }
230
231   for (Int_t i=0; i<kMaxStreamsToMerge; i++) fInputFiles[i]=0;
232 }
233
234 //_______________________________________________________________________
235 AliRunDigitizer::~AliRunDigitizer() {
236 // dtor
237
238 // do not delete subtasks, let the creator delete them
239   if (GetListOfTasks()) 
240     GetListOfTasks()->Clear("nodelete");
241   
242     delete fInputStreams;
243     delete fCombi;
244 }
245
246 //_______________________________________________________________________
247 void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
248 {
249 // add digitizer to the list of active digitizers
250   this->Add(digitizer);
251 }
252
253 //_______________________________________________________________________
254 void AliRunDigitizer::SetInputStream(Int_t i, const char *inputFile)
255 {
256   //
257   // Sets the name of the input file
258   //
259   if (i > fInputStreams->GetLast()) {
260     Error("SetInputStream","Input stream number too high");
261     return;
262   }
263   static_cast<AliStream*>(fInputStreams->At(i))->AddFile(inputFile);
264 }
265
266 //_______________________________________________________________________
267 void AliRunDigitizer::Digitize(Option_t* option)
268 {
269 // get a new combination of inputs, connect input trees and loop 
270 // over all digitizers
271
272 // take gAlice from the first input file. It is needed to access
273 //  geometry data
274 // If gAlice is already in memory, use it
275   if (!gAlice) {
276     if (!static_cast<AliStream*>(fInputStreams->At(0))->ImportgAlice()) {
277       cerr<<"gAlice object not found in the first file of "
278           <<"the 1st stream"<<endl;
279       return;
280     }
281   }
282   if (!InitGlobal()) {
283     cerr<<"False from InitGlobal"<<endl;
284     return;
285   }
286   Int_t eventsCreated = 0;
287 // loop until there is anything on the input in case fNrOfEventsToWrite < 0
288   while ((eventsCreated++ < fNrOfEventsToWrite) || (fNrOfEventsToWrite < 0)) {
289     if (!ConnectInputTrees()) break;
290     InitEvent();
291 // loop over all registered digitizers and let them do the work
292     ExecuteTasks(option);
293     CleanTasks();
294     FinishEvent();
295   }
296   FinishGlobal();
297 }
298
299 //_______________________________________________________________________
300 Bool_t AliRunDigitizer::ConnectInputTrees()
301 {
302 // fill arrays fArrayTreeS, fArrayTreeH and fArrayTreeTPCS with 
303 // pointers to the correct events according fCombination values
304 // null pointers can be in the output, AliDigitizer has to check it
305
306   TTree *tree;
307   char treeName[50];
308   Int_t serialNr;
309   Int_t eventNr[kMaxStreamsToMerge], delta[kMaxStreamsToMerge];
310   fCombi->Combination(eventNr, delta);
311   for (Int_t i=0;i<fNinputs;i++) {
312     if (delta[i] == 1) {
313       AliStream *iStream = static_cast<AliStream*>(fInputStreams->At(i));
314       if (!iStream->NextEventInStream(serialNr)) return kFALSE;
315       fInputFiles[i]=iStream->CurrentFile();
316       sprintf(treeName,"TreeS%d",serialNr);
317       tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
318       if (fArrayTreeS[i]) {
319         delete fArrayTreeS[i];
320         fArrayTreeS[i] = 0;
321       }
322       fArrayTreeS[i] = tree;
323       sprintf(treeName,"TreeH%d",serialNr);
324       tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
325       if (fArrayTreeH[i]) {
326         delete fArrayTreeH[i];
327         fArrayTreeH[i] = 0;
328       }
329       fArrayTreeH[i] = tree;
330       sprintf(treeName,"%s%d",fTreeTPCSBaseName,serialNr);
331       tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
332       if (fArrayTreeTPCS[i]) {
333         delete fArrayTreeTPCS[i];
334         fArrayTreeTPCS[i] = 0;
335       }
336       fArrayTreeTPCS[i] = tree;
337       sprintf(treeName,"TreeS%d_TRD",serialNr);
338       tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
339       if (fArrayTreeTRDS[i]) {
340         delete fArrayTreeTRDS[i];
341         fArrayTreeTRDS[i] = 0;
342       }
343       fArrayTreeTRDS[i] = tree;
344     } else if (delta[i] != 0) {
345       Error("ConnectInputTrees","Only delta 0 or 1 is implemented");
346       return kFALSE;
347     }
348   }
349   return kTRUE;
350 }
351
352 //_______________________________________________________________________
353 Bool_t AliRunDigitizer::InitGlobal()
354 {
355 // called once before Digitize() is called, initialize digitizers and output
356
357   TList* subTasks = GetListOfTasks();
358   if (subTasks) {
359     subTasks->ForEach(AliDigitizer,Init)();
360   }  
361   return kTRUE;
362 }
363
364 //_______________________________________________________________________
365 void AliRunDigitizer::SetOutputFile(TString fn)
366 {
367   // the output will be to separate file, not to the signal file
368   fOutputFileName = fn;
369   (static_cast<AliStream*>(fInputStreams->At(0)))->ChangeMode("READ");
370   InitOutputGlobal();
371 }
372
373 //_______________________________________________________________________
374 Bool_t AliRunDigitizer::InitOutputGlobal()
375 {
376 // Creates the output file, called by InitEvent()
377
378   TString fn;
379   fn = fOutputDirName + '/' + fOutputFileName;
380   fOutput = new TFile(fn,"update");
381   if (GetDebug()>2) {
382     cerr<<"AliRunDigitizer::InitOutputGlobal(): file "<<fn.Data()<<" was opened"<<endl;
383   }
384   if (fOutput) return kTRUE;
385   Error("InitOutputGlobal","Could not create output file.");
386   return kFALSE;
387 }
388
389
390 //_______________________________________________________________________
391 void AliRunDigitizer::InitEvent()
392 {
393 // Creates TreeDxx in the output file, called from Digitize() once for 
394 //  each event. xx = fEvent
395
396   if (GetDebug()>2) 
397     cerr<<"AliRunDigitizer::InitEvent: fEvent = "<<fEvent<<endl;
398
399 // if fOutputFileName was not given, write output to signal file
400   if (fOutputFileName == "") {
401     fOutput = (static_cast<AliStream*>(fInputStreams->At(0)))->CurrentFile();
402   }
403   fOutput->cd();
404   char treeName[30];
405   sprintf(treeName,"TreeD%d",fEvent);
406   fTreeD = static_cast<TTree*>(fOutput->Get(treeName));
407   if (!fTreeD) {
408     fTreeD = new TTree(treeName,"Digits");
409     fTreeD->Write(0,TObject::kOverwrite);
410   }
411
412 // tree for ITS fast points
413   sprintf(treeName,"TreeR%d",fEvent);
414   fTreeR = static_cast<TTree*>(fOutput->Get(treeName));
415   if (!fTreeR) {
416     fTreeR = new TTree(treeName,"Reconstruction");
417     fTreeR->Write(0,TObject::kOverwrite);
418   }
419
420 // special tree for TPC
421   sprintf(treeName,"%s%d",fTreeDTPCBaseName,fEvent);
422   fTreeDTPC = static_cast<TTree*>(fOutput->Get(treeName));
423   if (!fTreeDTPC) {
424     fTreeDTPC = new TTree(treeName,"TPC_Digits");
425     fTreeDTPC->Write(0,TObject::kOverwrite);
426   }
427
428 // special tree for TRD
429   sprintf(treeName,"TreeD%d_TRD",fEvent);
430   fTreeDTRD = static_cast<TTree*>(fOutput->Get(treeName));
431   if (!fTreeDTRD) {
432     fTreeDTRD = new TTree(treeName,"TRD_Digits");
433     fTreeDTRD->Write(0,TObject::kOverwrite);
434   }
435
436 }
437
438 //_______________________________________________________________________
439 void AliRunDigitizer::FinishEvent()
440 {
441 // called at the end of loop over digitizers
442
443   Int_t i;
444   fOutput->cd();
445   if (fCopyTreesFromInput > -1) {
446     char treeName[20];
447     i = fCopyTreesFromInput; 
448     sprintf(treeName,"TreeK%d",fCombination[i]);
449     fInputFiles[i]->Get(treeName)->Clone()->Write();
450     sprintf(treeName,"TreeH%d",fCombination[i]);
451     fInputFiles[i]->Get(treeName)->Clone()->Write();
452   }
453   fEvent++;
454   fNrOfEventsWritten++;
455   if (fTreeD) {
456     delete fTreeD;
457     fTreeD = 0;
458   }
459   if (fTreeR) {
460     delete fTreeR;
461     fTreeR = 0;
462   }
463   if (fTreeDTPC) {
464     delete fTreeDTPC;
465     fTreeDTPC = 0;
466   }
467   if (fTreeDTRD) {
468     delete fTreeDTRD;
469     fTreeDTRD = 0;
470   }
471 }
472
473 //_______________________________________________________________________
474 void AliRunDigitizer::FinishGlobal()
475 {
476 // called at the end of Exec
477 // save unique objects to the output file
478
479   fOutput->cd();
480   this->Write(0,TObject::kOverwrite);
481   if (fCopyTreesFromInput > -1) {
482     fInputFiles[fCopyTreesFromInput]->Get("TE")->Clone()->Write();
483     gAlice->Write();
484   }
485   fOutput->Write();
486 }
487
488
489 //_______________________________________________________________________
490 Int_t  AliRunDigitizer::GetNParticles(Int_t event) const
491 {
492 // return number of particles in all input files for a given
493 // event (as numbered in the output file)
494 // return -1 if some file cannot be accessed
495
496   Int_t sum = 0;
497   Int_t sumI;
498   for (Int_t i = 0; i < fNinputs; i++) {
499     sumI = GetNParticles(GetInputEventNumber(event,i), i);
500     if (sumI < 0) return -1;
501     sum += sumI;
502   }
503   return sum;
504 }
505
506 //_______________________________________________________________________
507 Int_t  AliRunDigitizer::GetNParticles(Int_t /* event */, Int_t /* input */) const
508 {
509 // return number of particles in input file input for a given
510 // event (as numbered in this input file)
511 // return -1 if some error
512
513 // Must be revised in the version with AliStream
514
515   return -1;
516
517 /*
518   TFile *file = ConnectInputFile(input);
519   if (!file) {
520     Error("GetNParticles","Cannot open input file");
521     return -1;
522   }
523
524 // find the header and get Nprimaries and Nsecondaries
525   TTree* tE = (TTree *)file->Get("TE") ;
526   if (!tE) {
527     Error("GetNParticles","input file does not contain TE");
528     return -1;
529   }
530   AliHeader* header;
531   header = 0;
532   tE->SetBranchAddress("Header", &header);
533   if (!tE->GetEntry(event)) {
534     Error("GetNParticles","event %d not found",event);
535     return -1;
536   }
537   if (GetDebug()>2) {
538     cerr<<"Nprimary: "<< header->GetNprimary()<<endl;
539     cerr<<"Nsecondary: "<<header->GetNsecondary()<<endl;
540   }
541   return header->GetNprimary() + header->GetNsecondary();
542 */
543 }
544
545 //_______________________________________________________________________
546 Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event) const
547 {
548 // return pointer to an int array with input event numbers which were
549 // merged in the output event event
550
551 // simplified for now, implement later
552   Int_t * a = new Int_t[kMaxStreamsToMerge];
553   for (Int_t i = 0; i < fNinputs; i++) {
554     a[i] = event;
555   }
556   return a;
557 }
558
559 //_______________________________________________________________________
560 Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t /* input */) const
561 {
562 // return an event number of an eventInput from input file input
563 // which was merged to create output event event
564
565 // simplified for now, implement later
566   return event;
567 }
568
569 //_______________________________________________________________________
570 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event) const
571 {
572 // return pointer to particle with index i (index with mask)
573
574 // decode the MASK
575   Int_t input = i/fkMASKSTEP;
576   return GetParticle(i,input,GetInputEventNumber(event,input));
577 }
578
579 //_______________________________________________________________________
580 TParticle* AliRunDigitizer::GetParticle(Int_t /* i */, Int_t /* input */, 
581                                         Int_t /* event */) const
582 {
583 // return pointer to particle with index i in the input file input
584 // (index without mask)
585 // event is the event number in the file input
586 // return 0 i fit does not exist
587
588 // Must be revised in the version with AliStream
589
590   return 0;
591 /*
592   TFile *file = ConnectInputFile(input);
593   if (!file) {
594     Error("GetParticle","Cannot open input file");
595     return 0;
596   }
597
598 // find the header and get Nprimaries and Nsecondaries
599   TTree* tE = (TTree *)file->Get("TE") ;
600   if (!tE) {
601     Error("GetParticle","input file does not contain TE");
602     return 0;
603   }
604   AliHeader* header;
605   header = 0;
606   tE->SetBranchAddress("Header", &header);
607   if (!tE->GetEntry(event)) {
608     Error("GetParticle","event %d not found",event);
609     return 0;
610   }
611   
612 // connect TreeK  
613   char treeName[30];
614   sprintf(treeName,"TreeK%d",event);  
615   TTree* tK = static_cast<TTree*>(file->Get(treeName));
616   if (!tK) {
617     Error("GetParticle","input file does not contain TreeK%d",event);
618     return 0;
619   }
620   TParticle *particleBuffer;
621   particleBuffer = 0;
622   tK->SetBranchAddress("Particles", &particleBuffer);
623
624
625 // algorithmic way of getting entry index
626 // (primary particles are filled after secondaries)
627   Int_t entry;
628   if (i<header->GetNprimary())
629     entry = i+header->GetNsecondary();
630   else 
631     entry = i-header->GetNprimary();
632   Int_t bytesRead = tK->GetEntry(entry);
633 //  new ((*fParticles)[nentries]) TParticle(*fParticleBuffer);
634   if (bytesRead)
635     return particleBuffer;
636   return  0;
637 */
638 }
639
640 //_______________________________________________________________________
641 void AliRunDigitizer::ExecuteTask(Option_t* option)
642 {
643 // overwrite ExecuteTask to do Digitize only
644
645   if (!IsActive()) return;
646   Digitize(option);
647   fHasExecuted = kTRUE;
648   return;
649 }
650
651 //_______________________________________________________________________
652 TString AliRunDigitizer::GetInputFileName(const Int_t input, const Int_t order) const 
653 {
654 // returns file name of the order-th file in the input stream input
655 // returns empty string if such file does not exist
656 // first input stream is 0
657 // first file in the input stream is 0
658   TString fileName("");
659   if (input >= fNinputs) return fileName;
660   AliStream * stream = static_cast<AliStream*>(fInputStreams->At(input));
661   if (order > stream->GetNInputFiles()) return fileName;
662   fileName = stream->GetFileName(order);
663   return fileName;
664 }