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.18 2002/07/17 08:59:39 jchudoba
19 Do not delete subtasks when AliRunDigitizer is deleted. Owner should delete them itself.
21 Revision 1.17 2002/07/16 13:47:53 jchudoba
22 Add methods to get access to names of files used in merging.
24 Revision 1.16 2002/06/07 09:18:47 jchudoba
25 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.
27 Revision 1.15 2002/04/09 13:38:47 jchudoba
28 Add const to the filename argument
30 Revision 1.14 2002/04/04 09:28:04 jchudoba
31 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.
33 Revision 1.13 2002/02/13 09:03:32 jchudoba
34 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.
36 Revision 1.12 2001/12/10 16:40:52 jchudoba
37 Import gAlice from the signal file before InitGlobal() to allow detectors to use it during initialization
39 Revision 1.11 2001/12/03 07:10:13 jchudoba
40 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
42 Revision 1.10 2001/11/15 11:07:25 jchudoba
43 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.
45 Revision 1.9 2001/11/15 09:00:11 jchudoba
46 Add special treatment for TPC and TRD, they use different trees than other detectors
48 Revision 1.8 2001/10/21 18:38:43 hristov
49 Several pointers were set to zero in the default constructors to avoid memory management problems
51 Revision 1.7 2001/10/04 15:56:07 jchudoba
54 Revision 1.4 2001/09/19 06:23:50 jchudoba
55 Move some tasks to AliStream and AliMergeCombi classes
57 Revision 1.3 2001/07/30 14:04:18 jchudoba
58 correct bug in the initialization
60 Revision 1.2 2001/07/28 10:44:32 hristov
61 Loop variable declared once; typos corrected
63 Revision 1.1 2001/07/27 12:59:00 jchudoba
64 Manager class for merging/digitization
68 ////////////////////////////////////////////////////////////////////////
70 // AliRunDigitizer.cxx
72 // Manager object for merging/digitization
74 // Instance of this class manages the digitization and/or merging of
75 // Sdigits into Digits.
77 // Only one instance of this class is created in the macro:
78 // AliRunDigitizer * manager =
79 // new AliRunDigitizer(nInputStreams,SPERB);
80 // where nInputStreams is number of input streams and SPERB is
81 // signals per background variable, which determines how combinations
82 // of signal and background events are generated.
83 // Then instances of specific detector digitizers are created:
84 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager)
85 // and the I/O configured (you have to specify input files
86 // and an output file). The manager connects appropriate trees from
87 // the input files according a combination returned by AliMergeCombi
88 // class. It creates TreeD in the output and runs once per
89 // event Digitize method of all existing AliDetDigitizers
90 // (without any option). AliDetDigitizers ask manager
91 // for a TTree with input (manager->GetInputTreeS(Int_t i),
92 // merge all inputs, digitize it, and save it in the TreeD
93 // obtained by manager->GetTreeD(). Output events are stored with
94 // numbers from 0, this default can be changed by
95 // manager->SetFirstOutputEventNr(Int_t) method. The particle numbers
96 // in the output are shifted by MASK, which is taken from manager.
98 // The default output is to the signal file (stream 0). This can be
99 // changed with the SetOutputFile(TString fn) method.
101 // Single input file is permitted. Maximum kMaxStreamsToMerge can be merged.
102 // Input from the memory (on-the-fly merging) is not yet
103 // supported, as well as access to the input data by invoking methods
104 // on the output data.
106 // Access to the some data is via gAlice for now (supposing the
107 // same geometry in all input files), gAlice is taken from the first
108 // input file on the first stream.
110 // Example with MUON digitizer, no merging, just digitization
112 // AliRunDigitizer * manager = new AliRunDigitizer(1,1);
113 // manager->SetInputStream(0,"galice.root");
114 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
115 // manager->Exec("");
117 // Example with MUON digitizer, merge all events from
118 // galice.root (signal) file with events from bgr.root
119 // (background) file. Number of merged events is
120 // min(number of events in galice.root, number of events in bgr.root)
122 // AliRunDigitizer * manager = new AliRunDigitizer(2,1);
123 // manager->SetInputStream(0,"galice.root");
124 // manager->SetInputStream(1,"bgr.root");
125 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
126 // manager->Exec("");
128 // Example with MUON digitizer, save digits in a new file digits.root,
129 // process only 1 event
131 // AliRunDigitizer * manager = new AliRunDigitizer(2,1);
132 // manager->SetInputStream(0,"galice.root");
133 // manager->SetInputStream(1,"bgr.root");
134 // manager->SetOutputFile("digits.root");
135 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
136 // manager->SetNrOfEventsToWrite(1);
137 // manager->Exec("");
139 ////////////////////////////////////////////////////////////////////////
143 #include <iostream.h>
153 #include "AliRunDigitizer.h"
154 #include "AliDigitizer.h"
156 #include "AliHeader.h"
157 #include "TParticle.h"
158 #include "AliStream.h"
159 #include "AliMergeCombi.h"
161 ClassImp(AliRunDigitizer)
163 ////////////////////////////////////////////////////////////////////////
164 AliRunDigitizer::AliRunDigitizer()
166 // root requires default ctor, where no new objects can be created
167 // do not use this ctor, it is supplied only for root needs
169 // just set all pointers - data members to 0
176 for (Int_t i=0;i<kMaxStreamsToMerge;i++) {
177 fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
184 ////////////////////////////////////////////////////////////////////////
185 AliRunDigitizer::AliRunDigitizer(Int_t nInputStreams, Int_t sperb) : TTask("AliRunDigitizer","The manager for Merging")
187 // ctor which should be used to create a manager for merging/digitization
188 if (nInputStreams == 0) {
189 Error("AliRunDigitizer","Specify nr of input streams");
193 fNinputs = nInputStreams;
194 fOutputFileName = "";
195 fOutputDirName = ".";
196 fCombination.Set(kMaxStreamsToMerge);
197 for (i=0;i<kMaxStreamsToMerge;i++) {
198 fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
201 fkMASKSTEP = 10000000;
203 for (i=1;i<kMaxStreamsToMerge;i++) {
204 fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
206 fInputStreams = new TClonesArray("AliStream",nInputStreams);
207 TClonesArray &lInputStreams = *fInputStreams;
208 // the first Input is open RW to be output as well
209 new(lInputStreams[0]) AliStream("UPDATE");
210 for (i=1;i<nInputStreams;i++) {
211 new(lInputStreams[i]) AliStream("READ");
215 fNrOfEventsToWrite = -1;
216 fNrOfEventsWritten = 0;
217 fCopyTreesFromInput = -1;
218 fCombi = new AliMergeCombi(nInputStreams,sperb);
224 fTreeDTPCBaseName = "TreeD_75x40_100x60_150x60_";
225 fTreeTPCSBaseName = "TreeS_75x40_100x60_150x60_";
227 for (i=0; i<kMaxStreamsToMerge; i++) fInputFiles[i]=0;
230 ////////////////////////////////////////////////////////////////////////
232 AliRunDigitizer::~AliRunDigitizer() {
235 // do not delete subtasks, let the creator delete them
236 if (GetListOfTasks())
237 GetListOfTasks()->Clear("nodelete");
240 delete fInputStreams;
249 ////////////////////////////////////////////////////////////////////////
250 void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
252 // add digitizer to the list of active digitizers
253 this->Add(digitizer);
255 ////////////////////////////////////////////////////////////////////////
256 void AliRunDigitizer::SetInputStream(Int_t i, const char *inputFile)
258 if (i > fInputStreams->GetLast()) {
259 Error("SetInputStream","Input stream number too high");
262 static_cast<AliStream*>(fInputStreams->At(i))->AddFile(inputFile);
265 ////////////////////////////////////////////////////////////////////////
266 void AliRunDigitizer::Digitize(Option_t* option)
268 // get a new combination of inputs, connect input trees and loop
269 // over all digitizers
271 // take gAlice from the first input file. It is needed to access
273 // If gAlice is already in memory, use it
275 if (!static_cast<AliStream*>(fInputStreams->At(0))->ImportgAlice()) {
276 cerr<<"gAlice object not found in the first file of "
277 <<"the 1st stream"<<endl;
282 cerr<<"False from InitGlobal"<<endl;
285 Int_t eventsCreated = 0;
286 // loop until there is anything on the input in case fNrOfEventsToWrite < 0
287 while ((eventsCreated++ < fNrOfEventsToWrite) || (fNrOfEventsToWrite < 0)) {
288 if (!ConnectInputTrees()) break;
290 // loop over all registered digitizers and let them do the work
291 ExecuteTasks(option);
298 ////////////////////////////////////////////////////////////////////////
299 Bool_t AliRunDigitizer::ConnectInputTrees()
301 // fill arrays fArrayTreeS, fArrayTreeH and fArrayTreeTPCS with
302 // pointers to the correct events according fCombination values
303 // null pointers can be in the output, AliDigitizer has to check it
308 Int_t eventNr[kMaxStreamsToMerge], delta[kMaxStreamsToMerge];
309 fCombi->Combination(eventNr, delta);
310 for (Int_t i=0;i<fNinputs;i++) {
312 AliStream *iStream = static_cast<AliStream*>(fInputStreams->At(i));
313 if (!iStream->NextEventInStream(serialNr)) return kFALSE;
314 fInputFiles[i]=iStream->CurrentFile();
315 sprintf(treeName,"TreeS%d",serialNr);
316 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
317 if (fArrayTreeS[i]) {
318 delete fArrayTreeS[i];
321 fArrayTreeS[i] = tree;
322 sprintf(treeName,"TreeH%d",serialNr);
323 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
324 if (fArrayTreeH[i]) {
325 delete fArrayTreeH[i];
328 fArrayTreeH[i] = tree;
329 sprintf(treeName,"%s%d",fTreeTPCSBaseName,serialNr);
330 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
331 if (fArrayTreeTPCS[i]) {
332 delete fArrayTreeTPCS[i];
333 fArrayTreeTPCS[i] = 0;
335 fArrayTreeTPCS[i] = tree;
336 sprintf(treeName,"TreeS%d_TRD",serialNr);
337 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
338 if (fArrayTreeTRDS[i]) {
339 delete fArrayTreeTRDS[i];
340 fArrayTreeTRDS[i] = 0;
342 fArrayTreeTRDS[i] = tree;
343 } else if (delta[i] != 0) {
344 Error("ConnectInputTrees","Only delta 0 or 1 is implemented");
351 ////////////////////////////////////////////////////////////////////////
352 Bool_t AliRunDigitizer::InitGlobal()
354 // called once before Digitize() is called, initialize digitizers and output
356 TList* subTasks = this->GetListOfTasks();
358 subTasks->ForEach(AliDigitizer,Init)();
363 ////////////////////////////////////////////////////////////////////////
365 void AliRunDigitizer::SetOutputFile(TString fn)
366 // the output will be to separate file, not to the signal file
368 fOutputFileName = fn;
369 (static_cast<AliStream*>(fInputStreams->At(0)))->ChangeMode("READ");
373 ////////////////////////////////////////////////////////////////////////
374 Bool_t AliRunDigitizer::InitOutputGlobal()
376 // Creates the output file, called by InitEvent()
379 fn = fOutputDirName + '/' + fOutputFileName;
380 fOutput = new TFile(fn,"update");
382 cerr<<"AliRunDigitizer::InitOutputGlobal(): file "<<fn.Data()<<" was opened"<<endl;
384 if (fOutput) return kTRUE;
385 Error("InitOutputGlobal","Could not create output file.");
390 ////////////////////////////////////////////////////////////////////////
391 void AliRunDigitizer::InitEvent()
393 // Creates TreeDxx in the output file, called from Digitize() once for
394 // each event. xx = fEvent
397 cerr<<"AliRunDigitizer::InitEvent: fEvent = "<<fEvent<<endl;
399 // if fOutputFileName was not given, write output to signal file
400 if (fOutputFileName == "") {
401 fOutput = (static_cast<AliStream*>(fInputStreams->At(0)))->CurrentFile();
405 sprintf(treeName,"TreeD%d",fEvent);
406 fTreeD = static_cast<TTree*>(fOutput->Get(treeName));
408 fTreeD = new TTree(treeName,"Digits");
409 fTreeD->Write(0,TObject::kOverwrite);
412 // tree for ITS fast points
413 sprintf(treeName,"TreeR%d",fEvent);
414 fTreeR = static_cast<TTree*>(fOutput->Get(treeName));
416 fTreeR = new TTree(treeName,"Reconstruction");
417 fTreeR->Write(0,TObject::kOverwrite);
420 // special tree for TPC
421 sprintf(treeName,"%s%d",fTreeDTPCBaseName,fEvent);
422 fTreeDTPC = static_cast<TTree*>(fOutput->Get(treeName));
424 fTreeDTPC = new TTree(treeName,"TPC_Digits");
425 fTreeDTPC->Write(0,TObject::kOverwrite);
428 // special tree for TRD
429 sprintf(treeName,"TreeD%d_TRD",fEvent);
430 fTreeDTRD = static_cast<TTree*>(fOutput->Get(treeName));
432 fTreeDTRD = new TTree(treeName,"TRD_Digits");
433 fTreeDTRD->Write(0,TObject::kOverwrite);
438 ////////////////////////////////////////////////////////////////////////
439 void AliRunDigitizer::FinishEvent()
441 // called at the end of loop over digitizers
445 if (fCopyTreesFromInput > -1) {
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();
454 fNrOfEventsWritten++;
472 ////////////////////////////////////////////////////////////////////////
473 void AliRunDigitizer::FinishGlobal()
475 // called at the end of Exec
476 // save unique objects to the output file
479 this->Write(0,TObject::kOverwrite);
480 if (fCopyTreesFromInput > -1) {
481 fInputFiles[fCopyTreesFromInput]->Get("TE")->Clone()->Write();
488 ////////////////////////////////////////////////////////////////////////
489 Int_t AliRunDigitizer::GetNParticles(Int_t event) const
491 // return number of particles in all input files for a given
492 // event (as numbered in the output file)
493 // return -1 if some file cannot be accessed
497 for (Int_t i = 0; i < fNinputs; i++) {
498 sumI = GetNParticles(GetInputEventNumber(event,i), i);
499 if (sumI < 0) return -1;
505 ////////////////////////////////////////////////////////////////////////
506 Int_t AliRunDigitizer::GetNParticles(Int_t event, Int_t input) const
508 // return number of particles in input file input for a given
509 // event (as numbered in this input file)
510 // return -1 if some error
512 // Must be revised in the version with AliStream
517 TFile *file = ConnectInputFile(input);
519 Error("GetNParticles","Cannot open input file");
523 // find the header and get Nprimaries and Nsecondaries
524 TTree* tE = (TTree *)file->Get("TE") ;
526 Error("GetNParticles","input file does not contain TE");
531 tE->SetBranchAddress("Header", &header);
532 if (!tE->GetEntry(event)) {
533 Error("GetNParticles","event %d not found",event);
537 cerr<<"Nprimary: "<< header->GetNprimary()<<endl;
538 cerr<<"Nsecondary: "<<header->GetNsecondary()<<endl;
540 return header->GetNprimary() + header->GetNsecondary();
544 ////////////////////////////////////////////////////////////////////////
545 Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event) const
547 // return pointer to an int array with input event numbers which were
548 // merged in the output event event
550 // simplified for now, implement later
551 Int_t * a = new Int_t[kMaxStreamsToMerge];
552 for (Int_t i = 0; i < fNinputs; i++) {
557 ////////////////////////////////////////////////////////////////////////
558 Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t input) const
560 // return an event number of an eventInput from input file input
561 // which was merged to create output event event
563 // simplified for now, implement later
566 ////////////////////////////////////////////////////////////////////////
567 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event) const
569 // return pointer to particle with index i (index with mask)
572 Int_t input = i/fkMASKSTEP;
573 return GetParticle(i,input,GetInputEventNumber(event,input));
576 ////////////////////////////////////////////////////////////////////////
577 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t input, Int_t event) const
579 // return pointer to particle with index i in the input file input
580 // (index without mask)
581 // event is the event number in the file input
582 // return 0 i fit does not exist
584 // Must be revised in the version with AliStream
588 TFile *file = ConnectInputFile(input);
590 Error("GetParticle","Cannot open input file");
594 // find the header and get Nprimaries and Nsecondaries
595 TTree* tE = (TTree *)file->Get("TE") ;
597 Error("GetParticle","input file does not contain TE");
602 tE->SetBranchAddress("Header", &header);
603 if (!tE->GetEntry(event)) {
604 Error("GetParticle","event %d not found",event);
610 sprintf(treeName,"TreeK%d",event);
611 TTree* tK = static_cast<TTree*>(file->Get(treeName));
613 Error("GetParticle","input file does not contain TreeK%d",event);
616 TParticle *particleBuffer;
618 tK->SetBranchAddress("Particles", &particleBuffer);
621 // algorithmic way of getting entry index
622 // (primary particles are filled after secondaries)
624 if (i<header->GetNprimary())
625 entry = i+header->GetNsecondary();
627 entry = i-header->GetNprimary();
628 Int_t bytesRead = tK->GetEntry(entry);
629 // new ((*fParticles)[nentries]) TParticle(*fParticleBuffer);
631 return particleBuffer;
636 ////////////////////////////////////////////////////////////////////////
637 void AliRunDigitizer::ExecuteTask(Option_t* option)
639 // overwrite ExecuteTask to do Digitize only
641 if (!IsActive()) return;
643 fHasExecuted = kTRUE;
646 ////////////////////////////////////////////////////////////////////////
647 TString AliRunDigitizer::GetInputFileName(const Int_t input, const Int_t order) const
649 // returns file name of the order-th file in the input stream input
650 // returns empty string if such file does not exist
651 // first input stream is 0
652 // first file in the input stream is 0
653 TString fileName("");
654 if (input >= fNinputs) return fileName;
655 AliStream * stream = static_cast<AliStream*>(fInputStreams->At(input));
656 if (order > stream->GetNInputFiles()) return fileName;
657 fileName = stream->GetFileName(order);
660 ////////////////////////////////////////////////////////////////////////