1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 Revision 1.16 2002/06/07 09:18:47 jchudoba
19 Changes to enable merging of ITS fast rec points. Although this class should be responsible for a creation of digits only, other solutions would be more complicated.
21 Revision 1.15 2002/04/09 13:38:47 jchudoba
22 Add const to the filename argument
24 Revision 1.14 2002/04/04 09:28:04 jchudoba
25 Change default names of TPC trees. Use update instead of recreate for the output file. Overwrite the AliRunDigitizer object in the output if it exists.
27 Revision 1.13 2002/02/13 09:03:32 jchudoba
28 Pass option to subtasks. Delete input TTrees. Use gAlice from memory if it is present (user must delete the default one created by aliroot if he/she wants to use gAlice from the input file!). Add new data member to store name of the special TPC TTrees.
30 Revision 1.12 2001/12/10 16:40:52 jchudoba
31 Import gAlice from the signal file before InitGlobal() to allow detectors to use it during initialization
33 Revision 1.11 2001/12/03 07:10:13 jchudoba
34 Default ctor cannot create new objects, create dummy default ctor which leaves object in not well defined state - to be used only by root for I/O
36 Revision 1.10 2001/11/15 11:07:25 jchudoba
37 Set to zero new pointers to TPC and TRD special trees in the default ctor. Add const to all Get functions. Remove unused constant, rename constant according coding rules.
39 Revision 1.9 2001/11/15 09:00:11 jchudoba
40 Add special treatment for TPC and TRD, they use different trees than other detectors
42 Revision 1.8 2001/10/21 18:38:43 hristov
43 Several pointers were set to zero in the default constructors to avoid memory management problems
45 Revision 1.7 2001/10/04 15:56:07 jchudoba
48 Revision 1.4 2001/09/19 06:23:50 jchudoba
49 Move some tasks to AliStream and AliMergeCombi classes
51 Revision 1.3 2001/07/30 14:04:18 jchudoba
52 correct bug in the initialization
54 Revision 1.2 2001/07/28 10:44:32 hristov
55 Loop variable declared once; typos corrected
57 Revision 1.1 2001/07/27 12:59:00 jchudoba
58 Manager class for merging/digitization
62 ////////////////////////////////////////////////////////////////////////
64 // AliRunDigitizer.cxx
66 // Manager object for merging/digitization
68 // Instance of this class manages the digitization and/or merging of
69 // Sdigits into Digits.
71 // Only one instance of this class is created in the macro:
72 // AliRunDigitizer * manager =
73 // new AliRunDigitizer(nInputStreams,SPERB);
74 // where nInputStreams is number of input streams and SPERB is
75 // signals per background variable, which determines how combinations
76 // of signal and background events are generated.
77 // Then instances of specific detector digitizers are created:
78 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager)
79 // and the I/O configured (you have to specify input files
80 // and an output file). The manager connects appropriate trees from
81 // the input files according a combination returned by AliMergeCombi
82 // class. It creates TreeD in the output and runs once per
83 // event Digitize method of all existing AliDetDigitizers
84 // (without any option). AliDetDigitizers ask manager
85 // for a TTree with input (manager->GetInputTreeS(Int_t i),
86 // merge all inputs, digitize it, and save it in the TreeD
87 // obtained by manager->GetTreeD(). Output events are stored with
88 // numbers from 0, this default can be changed by
89 // manager->SetFirstOutputEventNr(Int_t) method. The particle numbers
90 // in the output are shifted by MASK, which is taken from manager.
92 // The default output is to the signal file (stream 0). This can be
93 // changed with the SetOutputFile(TString fn) method.
95 // Single input file is permitted. Maximum kMaxStreamsToMerge can be merged.
96 // Input from the memory (on-the-fly merging) is not yet
97 // supported, as well as access to the input data by invoking methods
98 // on the output data.
100 // Access to the some data is via gAlice for now (supposing the
101 // same geometry in all input files), gAlice is taken from the first
102 // input file on the first stream.
104 // Example with MUON digitizer, no merging, just digitization
106 // AliRunDigitizer * manager = new AliRunDigitizer(1,1);
107 // manager->SetInputStream(0,"galice.root");
108 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
109 // manager->Exec("");
111 // Example with MUON digitizer, merge all events from
112 // galice.root (signal) file with events from bgr.root
113 // (background) file. Number of merged events is
114 // min(number of events in galice.root, number of events in bgr.root)
116 // AliRunDigitizer * manager = new AliRunDigitizer(2,1);
117 // manager->SetInputStream(0,"galice.root");
118 // manager->SetInputStream(1,"bgr.root");
119 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
120 // manager->Exec("");
122 // Example with MUON digitizer, save digits in a new file digits.root,
123 // process only 1 event
125 // AliRunDigitizer * manager = new AliRunDigitizer(2,1);
126 // manager->SetInputStream(0,"galice.root");
127 // manager->SetInputStream(1,"bgr.root");
128 // manager->SetOutputFile("digits.root");
129 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
130 // manager->SetNrOfEventsToWrite(1);
131 // manager->Exec("");
133 ////////////////////////////////////////////////////////////////////////
137 #include <iostream.h>
147 #include "AliRunDigitizer.h"
148 #include "AliDigitizer.h"
150 #include "AliHeader.h"
151 #include "TParticle.h"
152 #include "AliStream.h"
153 #include "AliMergeCombi.h"
155 ClassImp(AliRunDigitizer)
157 ////////////////////////////////////////////////////////////////////////
158 AliRunDigitizer::AliRunDigitizer()
160 // root requires default ctor, where no new objects can be created
161 // do not use this ctor, it is supplied only for root needs
163 // just set all pointers - data members to 0
170 for (Int_t i=0;i<kMaxStreamsToMerge;i++) {
171 fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
178 ////////////////////////////////////////////////////////////////////////
179 AliRunDigitizer::AliRunDigitizer(Int_t nInputStreams, Int_t sperb) : TTask("AliRunDigitizer","The manager for Merging")
181 // ctor which should be used to create a manager for merging/digitization
182 if (nInputStreams == 0) {
183 Error("AliRunDigitizer","Specify nr of input streams");
187 fNinputs = nInputStreams;
188 fOutputFileName = "";
189 fOutputDirName = ".";
190 fCombination.Set(kMaxStreamsToMerge);
191 for (i=0;i<kMaxStreamsToMerge;i++) {
192 fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
195 fkMASKSTEP = 10000000;
197 for (i=1;i<kMaxStreamsToMerge;i++) {
198 fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
200 fInputStreams = new TClonesArray("AliStream",nInputStreams);
201 TClonesArray &lInputStreams = *fInputStreams;
202 // the first Input is open RW to be output as well
203 new(lInputStreams[0]) AliStream("UPDATE");
204 for (i=1;i<nInputStreams;i++) {
205 new(lInputStreams[i]) AliStream("READ");
209 fNrOfEventsToWrite = -1;
210 fNrOfEventsWritten = 0;
211 fCopyTreesFromInput = -1;
212 fCombi = new AliMergeCombi(nInputStreams,sperb);
218 fTreeDTPCBaseName = "TreeD_75x40_100x60_150x60_";
219 fTreeTPCSBaseName = "TreeS_75x40_100x60_150x60_";
221 for (i=0; i<kMaxStreamsToMerge; i++) fInputFiles[i]=0;
224 ////////////////////////////////////////////////////////////////////////
226 AliRunDigitizer::~AliRunDigitizer() {
230 delete fInputStreams;
239 ////////////////////////////////////////////////////////////////////////
240 void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
242 // add digitizer to the list of active digitizers
243 this->Add(digitizer);
245 ////////////////////////////////////////////////////////////////////////
246 void AliRunDigitizer::SetInputStream(Int_t i, const char *inputFile)
248 if (i > fInputStreams->GetLast()) {
249 Error("SetInputStream","Input stream number too high");
252 static_cast<AliStream*>(fInputStreams->At(i))->AddFile(inputFile);
255 ////////////////////////////////////////////////////////////////////////
256 void AliRunDigitizer::Digitize(Option_t* option)
258 // get a new combination of inputs, connect input trees and loop
259 // over all digitizers
261 // take gAlice from the first input file. It is needed to access
263 // If gAlice is already in memory, use it
265 if (!static_cast<AliStream*>(fInputStreams->At(0))->ImportgAlice()) {
266 cerr<<"gAlice object not found in the first file of "
267 <<"the 1st stream"<<endl;
272 cerr<<"False from InitGlobal"<<endl;
275 Int_t eventsCreated = 0;
276 // loop until there is anything on the input in case fNrOfEventsToWrite < 0
277 while ((eventsCreated++ < fNrOfEventsToWrite) || (fNrOfEventsToWrite < 0)) {
278 if (!ConnectInputTrees()) break;
280 // loop over all registered digitizers and let them do the work
281 ExecuteTasks(option);
288 ////////////////////////////////////////////////////////////////////////
289 Bool_t AliRunDigitizer::ConnectInputTrees()
291 // fill arrays fArrayTreeS, fArrayTreeH and fArrayTreeTPCS with
292 // pointers to the correct events according fCombination values
293 // null pointers can be in the output, AliDigitizer has to check it
298 Int_t eventNr[kMaxStreamsToMerge], delta[kMaxStreamsToMerge];
299 fCombi->Combination(eventNr, delta);
300 for (Int_t i=0;i<fNinputs;i++) {
302 AliStream *iStream = static_cast<AliStream*>(fInputStreams->At(i));
303 if (!iStream->NextEventInStream(serialNr)) return kFALSE;
304 fInputFiles[i]=iStream->CurrentFile();
305 sprintf(treeName,"TreeS%d",serialNr);
306 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
307 if (fArrayTreeS[i]) {
308 delete fArrayTreeS[i];
311 fArrayTreeS[i] = tree;
312 sprintf(treeName,"TreeH%d",serialNr);
313 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
314 if (fArrayTreeH[i]) {
315 delete fArrayTreeH[i];
318 fArrayTreeH[i] = tree;
319 sprintf(treeName,"%s%d",fTreeTPCSBaseName,serialNr);
320 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
321 if (fArrayTreeTPCS[i]) {
322 delete fArrayTreeTPCS[i];
323 fArrayTreeTPCS[i] = 0;
325 fArrayTreeTPCS[i] = tree;
326 sprintf(treeName,"TreeS%d_TRD",serialNr);
327 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
328 if (fArrayTreeTRDS[i]) {
329 delete fArrayTreeTRDS[i];
330 fArrayTreeTRDS[i] = 0;
332 fArrayTreeTRDS[i] = tree;
333 } else if (delta[i] != 0) {
334 Error("ConnectInputTrees","Only delta 0 or 1 is implemented");
341 ////////////////////////////////////////////////////////////////////////
342 Bool_t AliRunDigitizer::InitGlobal()
344 // called once before Digitize() is called, initialize digitizers and output
346 TList* subTasks = this->GetListOfTasks();
348 subTasks->ForEach(AliDigitizer,Init)();
353 ////////////////////////////////////////////////////////////////////////
355 void AliRunDigitizer::SetOutputFile(TString fn)
356 // the output will be to separate file, not to the signal file
358 fOutputFileName = fn;
359 (static_cast<AliStream*>(fInputStreams->At(0)))->ChangeMode("READ");
363 ////////////////////////////////////////////////////////////////////////
364 Bool_t AliRunDigitizer::InitOutputGlobal()
366 // Creates the output file, called by InitEvent()
369 fn = fOutputDirName + '/' + fOutputFileName;
370 fOutput = new TFile(fn,"update");
372 cerr<<"AliRunDigitizer::InitOutputGlobal(): file "<<fn.Data()<<" was opened"<<endl;
374 if (fOutput) return kTRUE;
375 Error("InitOutputGlobal","Could not create output file.");
380 ////////////////////////////////////////////////////////////////////////
381 void AliRunDigitizer::InitEvent()
383 // Creates TreeDxx in the output file, called from Digitize() once for
384 // each event. xx = fEvent
387 cerr<<"AliRunDigitizer::InitEvent: fEvent = "<<fEvent<<endl;
389 // if fOutputFileName was not given, write output to signal file
390 if (fOutputFileName == "") {
391 fOutput = (static_cast<AliStream*>(fInputStreams->At(0)))->CurrentFile();
395 sprintf(treeName,"TreeD%d",fEvent);
396 fTreeD = static_cast<TTree*>(fOutput->Get(treeName));
398 fTreeD = new TTree(treeName,"Digits");
399 fTreeD->Write(0,TObject::kOverwrite);
402 // tree for ITS fast points
403 sprintf(treeName,"TreeR%d",fEvent);
404 fTreeR = static_cast<TTree*>(fOutput->Get(treeName));
406 fTreeR = new TTree(treeName,"Reconstruction");
407 fTreeR->Write(0,TObject::kOverwrite);
410 // special tree for TPC
411 sprintf(treeName,"%s%d",fTreeDTPCBaseName,fEvent);
412 fTreeDTPC = static_cast<TTree*>(fOutput->Get(treeName));
414 fTreeDTPC = new TTree(treeName,"TPC_Digits");
415 fTreeDTPC->Write(0,TObject::kOverwrite);
418 // special tree for TRD
419 sprintf(treeName,"TreeD%d_TRD",fEvent);
420 fTreeDTRD = static_cast<TTree*>(fOutput->Get(treeName));
422 fTreeDTRD = new TTree(treeName,"TRD_Digits");
423 fTreeDTRD->Write(0,TObject::kOverwrite);
428 ////////////////////////////////////////////////////////////////////////
429 void AliRunDigitizer::FinishEvent()
431 // called at the end of loop over digitizers
435 if (fCopyTreesFromInput > -1) {
437 i = fCopyTreesFromInput;
438 sprintf(treeName,"TreeK%d",fCombination[i]);
439 fInputFiles[i]->Get(treeName)->Clone()->Write();
440 sprintf(treeName,"TreeH%d",fCombination[i]);
441 fInputFiles[i]->Get(treeName)->Clone()->Write();
444 fNrOfEventsWritten++;
462 ////////////////////////////////////////////////////////////////////////
463 void AliRunDigitizer::FinishGlobal()
465 // called at the end of Exec
466 // save unique objects to the output file
469 this->Write(0,TObject::kOverwrite);
470 if (fCopyTreesFromInput > -1) {
471 fInputFiles[fCopyTreesFromInput]->Get("TE")->Clone()->Write();
478 ////////////////////////////////////////////////////////////////////////
479 Int_t AliRunDigitizer::GetNParticles(Int_t event) const
481 // return number of particles in all input files for a given
482 // event (as numbered in the output file)
483 // return -1 if some file cannot be accessed
487 for (Int_t i = 0; i < fNinputs; i++) {
488 sumI = GetNParticles(GetInputEventNumber(event,i), i);
489 if (sumI < 0) return -1;
495 ////////////////////////////////////////////////////////////////////////
496 Int_t AliRunDigitizer::GetNParticles(Int_t event, Int_t input) const
498 // return number of particles in input file input for a given
499 // event (as numbered in this input file)
500 // return -1 if some error
502 // Must be revised in the version with AliStream
507 TFile *file = ConnectInputFile(input);
509 Error("GetNParticles","Cannot open input file");
513 // find the header and get Nprimaries and Nsecondaries
514 TTree* tE = (TTree *)file->Get("TE") ;
516 Error("GetNParticles","input file does not contain TE");
521 tE->SetBranchAddress("Header", &header);
522 if (!tE->GetEntry(event)) {
523 Error("GetNParticles","event %d not found",event);
527 cerr<<"Nprimary: "<< header->GetNprimary()<<endl;
528 cerr<<"Nsecondary: "<<header->GetNsecondary()<<endl;
530 return header->GetNprimary() + header->GetNsecondary();
534 ////////////////////////////////////////////////////////////////////////
535 Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event) const
537 // return pointer to an int array with input event numbers which were
538 // merged in the output event event
540 // simplified for now, implement later
541 Int_t * a = new Int_t[kMaxStreamsToMerge];
542 for (Int_t i = 0; i < fNinputs; i++) {
547 ////////////////////////////////////////////////////////////////////////
548 Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t input) const
550 // return an event number of an eventInput from input file input
551 // which was merged to create output event event
553 // simplified for now, implement later
556 ////////////////////////////////////////////////////////////////////////
557 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event) const
559 // return pointer to particle with index i (index with mask)
562 Int_t input = i/fkMASKSTEP;
563 return GetParticle(i,input,GetInputEventNumber(event,input));
566 ////////////////////////////////////////////////////////////////////////
567 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t input, Int_t event) const
569 // return pointer to particle with index i in the input file input
570 // (index without mask)
571 // event is the event number in the file input
572 // return 0 i fit does not exist
574 // Must be revised in the version with AliStream
578 TFile *file = ConnectInputFile(input);
580 Error("GetParticle","Cannot open input file");
584 // find the header and get Nprimaries and Nsecondaries
585 TTree* tE = (TTree *)file->Get("TE") ;
587 Error("GetParticle","input file does not contain TE");
592 tE->SetBranchAddress("Header", &header);
593 if (!tE->GetEntry(event)) {
594 Error("GetParticle","event %d not found",event);
600 sprintf(treeName,"TreeK%d",event);
601 TTree* tK = static_cast<TTree*>(file->Get(treeName));
603 Error("GetParticle","input file does not contain TreeK%d",event);
606 TParticle *particleBuffer;
608 tK->SetBranchAddress("Particles", &particleBuffer);
611 // algorithmic way of getting entry index
612 // (primary particles are filled after secondaries)
614 if (i<header->GetNprimary())
615 entry = i+header->GetNsecondary();
617 entry = i-header->GetNprimary();
618 Int_t bytesRead = tK->GetEntry(entry);
619 // new ((*fParticles)[nentries]) TParticle(*fParticleBuffer);
621 return particleBuffer;
626 ////////////////////////////////////////////////////////////////////////
627 void AliRunDigitizer::ExecuteTask(Option_t* option)
629 // overwrite ExecuteTask to do Digitize only
631 if (!IsActive()) return;
633 fHasExecuted = kTRUE;
636 ////////////////////////////////////////////////////////////////////////
637 TString AliRunDigitizer::GetInputFileName(const Int_t input, const Int_t order) const
639 // returns file name of the order-th file in the input stream input
640 // returns empty string if such file does not exist
641 // first input stream is 0
642 // first file in the input stream is 0
643 TString fileName("");
644 if (input >= fNinputs) return fileName;
645 AliStream * stream = static_cast<AliStream*>(fInputStreams->At(input));
646 if (order > stream->GetNInputFiles()) return fileName;
647 fileName = stream->GetFileName(order);
650 ////////////////////////////////////////////////////////////////////////