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.13.6.2 2002/07/24 10:08:13 alibrary
21 Revision 1.19 2002/07/19 12:46:05 hristov
22 Write file instead of closing it
24 Revision 1.18 2002/07/17 08:59:39 jchudoba
25 Do not delete subtasks when AliRunDigitizer is deleted. Owner should delete them itself.
27 Revision 1.17 2002/07/16 13:47:53 jchudoba
28 Add methods to get access to names of files used in merging.
30 Revision 1.16 2002/06/07 09:18:47 jchudoba
31 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.
33 Revision 1.15 2002/04/09 13:38:47 jchudoba
34 Add const to the filename argument
36 Revision 1.14 2002/04/04 09:28:04 jchudoba
37 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.
39 Revision 1.13 2002/02/13 09:03:32 jchudoba
40 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.
42 Revision 1.12 2001/12/10 16:40:52 jchudoba
43 Import gAlice from the signal file before InitGlobal() to allow detectors to use it during initialization
45 Revision 1.11 2001/12/03 07:10:13 jchudoba
46 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
48 Revision 1.10 2001/11/15 11:07:25 jchudoba
49 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.
51 Revision 1.9 2001/11/15 09:00:11 jchudoba
52 Add special treatment for TPC and TRD, they use different trees than other detectors
54 Revision 1.8 2001/10/21 18:38:43 hristov
55 Several pointers were set to zero in the default constructors to avoid memory management problems
57 Revision 1.7 2001/10/04 15:56:07 jchudoba
60 Revision 1.4 2001/09/19 06:23:50 jchudoba
61 Move some tasks to AliStream and AliMergeCombi classes
63 Revision 1.3 2001/07/30 14:04:18 jchudoba
64 correct bug in the initialization
66 Revision 1.2 2001/07/28 10:44:32 hristov
67 Loop variable declared once; typos corrected
69 Revision 1.1 2001/07/27 12:59:00 jchudoba
70 Manager class for merging/digitization
74 ////////////////////////////////////////////////////////////////////////
76 // AliRunDigitizer.cxx
78 // Manager object for merging/digitization
80 // Instance of this class manages the digitization and/or merging of
81 // Sdigits into Digits.
83 // Only one instance of this class is created in the macro:
84 // AliRunDigitizer * manager =
85 // new AliRunDigitizer(nInputStreams,SPERB);
86 // where nInputStreams is number of input streams and SPERB is
87 // signals per background variable, which determines how combinations
88 // of signal and background events are generated.
89 // Then instances of specific detector digitizers are created:
90 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager)
91 // and the I/O configured (you have to specify input files
92 // and an output file). The manager connects appropriate trees from
93 // the input files according a combination returned by AliMergeCombi
94 // class. It creates TreeD in the output and runs once per
95 // event Digitize method of all existing AliDetDigitizers
96 // (without any option). AliDetDigitizers ask manager
97 // for a TTree with input (manager->GetInputTreeS(Int_t i),
98 // merge all inputs, digitize it, and save it in the TreeD
99 // obtained by manager->GetTreeD(). Output events are stored with
100 // numbers from 0, this default can be changed by
101 // manager->SetFirstOutputEventNr(Int_t) method. The particle numbers
102 // in the output are shifted by MASK, which is taken from manager.
104 // The default output is to the signal file (stream 0). This can be
105 // changed with the SetOutputFile(TString fn) method.
107 // Single input file is permitted. Maximum kMaxStreamsToMerge can be merged.
108 // Input from the memory (on-the-fly merging) is not yet
109 // supported, as well as access to the input data by invoking methods
110 // on the output data.
112 // Access to the some data is via gAlice for now (supposing the
113 // same geometry in all input files), gAlice is taken from the first
114 // input file on the first stream.
116 // Example with MUON digitizer, no merging, just digitization
118 // AliRunDigitizer * manager = new AliRunDigitizer(1,1);
119 // manager->SetInputStream(0,"galice.root");
120 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
121 // manager->Exec("");
123 // Example with MUON digitizer, merge all events from
124 // galice.root (signal) file with events from bgr.root
125 // (background) file. Number of merged events is
126 // min(number of events in galice.root, number of events in bgr.root)
128 // AliRunDigitizer * manager = new AliRunDigitizer(2,1);
129 // manager->SetInputStream(0,"galice.root");
130 // manager->SetInputStream(1,"bgr.root");
131 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
132 // manager->Exec("");
134 // Example with MUON digitizer, save digits in a new file digits.root,
135 // process only 1 event
137 // AliRunDigitizer * manager = new AliRunDigitizer(2,1);
138 // manager->SetInputStream(0,"galice.root");
139 // manager->SetInputStream(1,"bgr.root");
140 // manager->SetOutputFile("digits.root");
141 // AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
142 // manager->SetNrOfEventsToWrite(1);
143 // manager->Exec("");
145 ////////////////////////////////////////////////////////////////////////
149 #include <iostream.h>
159 #include "AliRunDigitizer.h"
160 #include "AliDigitizer.h"
162 #include "AliHeader.h"
163 #include "TParticle.h"
164 #include "AliStream.h"
165 #include "AliMergeCombi.h"
167 ClassImp(AliRunDigitizer)
169 ////////////////////////////////////////////////////////////////////////
170 AliRunDigitizer::AliRunDigitizer()
172 // root requires default ctor, where no new objects can be created
173 // do not use this ctor, it is supplied only for root needs
175 // just set all pointers - data members to 0
182 for (Int_t i=0;i<kMaxStreamsToMerge;i++) {
183 fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
190 ////////////////////////////////////////////////////////////////////////
191 AliRunDigitizer::AliRunDigitizer(Int_t nInputStreams, Int_t sperb) : TTask("AliRunDigitizer","The manager for Merging")
193 // ctor which should be used to create a manager for merging/digitization
194 if (nInputStreams == 0) {
195 Error("AliRunDigitizer","Specify nr of input streams");
199 fNinputs = nInputStreams;
200 fOutputFileName = "";
201 fOutputDirName = ".";
202 fCombination.Set(kMaxStreamsToMerge);
203 for (i=0;i<kMaxStreamsToMerge;i++) {
204 fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
207 fkMASKSTEP = 10000000;
209 for (i=1;i<kMaxStreamsToMerge;i++) {
210 fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
212 fInputStreams = new TClonesArray("AliStream",nInputStreams);
213 TClonesArray &lInputStreams = *fInputStreams;
214 // the first Input is open RW to be output as well
215 new(lInputStreams[0]) AliStream("UPDATE");
216 for (i=1;i<nInputStreams;i++) {
217 new(lInputStreams[i]) AliStream("READ");
221 fNrOfEventsToWrite = -1;
222 fNrOfEventsWritten = 0;
223 fCopyTreesFromInput = -1;
224 fCombi = new AliMergeCombi(nInputStreams,sperb);
230 fTreeDTPCBaseName = "TreeD_75x40_100x60_150x60_";
231 fTreeTPCSBaseName = "TreeS_75x40_100x60_150x60_";
233 for (i=0; i<kMaxStreamsToMerge; i++) fInputFiles[i]=0;
236 ////////////////////////////////////////////////////////////////////////
238 AliRunDigitizer::~AliRunDigitizer() {
241 // do not delete subtasks, let the creator delete them
242 if (GetListOfTasks())
243 GetListOfTasks()->Clear("nodelete");
246 delete fInputStreams;
255 ////////////////////////////////////////////////////////////////////////
256 void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
258 // add digitizer to the list of active digitizers
259 this->Add(digitizer);
261 ////////////////////////////////////////////////////////////////////////
262 void AliRunDigitizer::SetInputStream(Int_t i, const char *inputFile)
264 if (i > fInputStreams->GetLast()) {
265 Error("SetInputStream","Input stream number too high");
268 static_cast<AliStream*>(fInputStreams->At(i))->AddFile(inputFile);
271 ////////////////////////////////////////////////////////////////////////
272 void AliRunDigitizer::Digitize(Option_t* option)
274 // get a new combination of inputs, connect input trees and loop
275 // over all digitizers
277 // take gAlice from the first input file. It is needed to access
279 // If gAlice is already in memory, use it
281 if (!static_cast<AliStream*>(fInputStreams->At(0))->ImportgAlice()) {
282 cerr<<"gAlice object not found in the first file of "
283 <<"the 1st stream"<<endl;
288 cerr<<"False from InitGlobal"<<endl;
291 Int_t eventsCreated = 0;
292 // loop until there is anything on the input in case fNrOfEventsToWrite < 0
293 while ((eventsCreated++ < fNrOfEventsToWrite) || (fNrOfEventsToWrite < 0)) {
294 if (!ConnectInputTrees()) break;
296 // loop over all registered digitizers and let them do the work
297 ExecuteTasks(option);
304 ////////////////////////////////////////////////////////////////////////
305 Bool_t AliRunDigitizer::ConnectInputTrees()
307 // fill arrays fArrayTreeS, fArrayTreeH and fArrayTreeTPCS with
308 // pointers to the correct events according fCombination values
309 // null pointers can be in the output, AliDigitizer has to check it
314 Int_t eventNr[kMaxStreamsToMerge], delta[kMaxStreamsToMerge];
315 fCombi->Combination(eventNr, delta);
316 for (Int_t i=0;i<fNinputs;i++) {
318 AliStream *iStream = static_cast<AliStream*>(fInputStreams->At(i));
319 if (!iStream->NextEventInStream(serialNr)) return kFALSE;
320 fInputFiles[i]=iStream->CurrentFile();
321 sprintf(treeName,"TreeS%d",serialNr);
322 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
323 if (fArrayTreeS[i]) {
324 delete fArrayTreeS[i];
327 fArrayTreeS[i] = tree;
328 sprintf(treeName,"TreeH%d",serialNr);
329 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
330 if (fArrayTreeH[i]) {
331 delete fArrayTreeH[i];
334 fArrayTreeH[i] = tree;
335 sprintf(treeName,"%s%d",fTreeTPCSBaseName,serialNr);
336 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
337 if (fArrayTreeTPCS[i]) {
338 delete fArrayTreeTPCS[i];
339 fArrayTreeTPCS[i] = 0;
341 fArrayTreeTPCS[i] = tree;
342 sprintf(treeName,"TreeS%d_TRD",serialNr);
343 tree = static_cast<TTree*>(iStream->CurrentFile()->Get(treeName));
344 if (fArrayTreeTRDS[i]) {
345 delete fArrayTreeTRDS[i];
346 fArrayTreeTRDS[i] = 0;
348 fArrayTreeTRDS[i] = tree;
349 } else if (delta[i] != 0) {
350 Error("ConnectInputTrees","Only delta 0 or 1 is implemented");
357 ////////////////////////////////////////////////////////////////////////
358 Bool_t AliRunDigitizer::InitGlobal()
360 // called once before Digitize() is called, initialize digitizers and output
362 TList* subTasks = this->GetListOfTasks();
364 subTasks->ForEach(AliDigitizer,Init)();
369 ////////////////////////////////////////////////////////////////////////
371 void AliRunDigitizer::SetOutputFile(TString fn)
372 // the output will be to separate file, not to the signal file
374 fOutputFileName = fn;
375 (static_cast<AliStream*>(fInputStreams->At(0)))->ChangeMode("READ");
379 ////////////////////////////////////////////////////////////////////////
380 Bool_t AliRunDigitizer::InitOutputGlobal()
382 // Creates the output file, called by InitEvent()
385 fn = fOutputDirName + '/' + fOutputFileName;
386 fOutput = new TFile(fn,"update");
388 cerr<<"AliRunDigitizer::InitOutputGlobal(): file "<<fn.Data()<<" was opened"<<endl;
390 if (fOutput) return kTRUE;
391 Error("InitOutputGlobal","Could not create output file.");
396 ////////////////////////////////////////////////////////////////////////
397 void AliRunDigitizer::InitEvent()
399 // Creates TreeDxx in the output file, called from Digitize() once for
400 // each event. xx = fEvent
403 cerr<<"AliRunDigitizer::InitEvent: fEvent = "<<fEvent<<endl;
405 // if fOutputFileName was not given, write output to signal file
406 if (fOutputFileName == "") {
407 fOutput = (static_cast<AliStream*>(fInputStreams->At(0)))->CurrentFile();
411 sprintf(treeName,"TreeD%d",fEvent);
412 fTreeD = static_cast<TTree*>(fOutput->Get(treeName));
414 fTreeD = new TTree(treeName,"Digits");
415 fTreeD->Write(0,TObject::kOverwrite);
418 // tree for ITS fast points
419 sprintf(treeName,"TreeR%d",fEvent);
420 fTreeR = static_cast<TTree*>(fOutput->Get(treeName));
422 fTreeR = new TTree(treeName,"Reconstruction");
423 fTreeR->Write(0,TObject::kOverwrite);
426 // special tree for TPC
427 sprintf(treeName,"%s%d",fTreeDTPCBaseName,fEvent);
428 fTreeDTPC = static_cast<TTree*>(fOutput->Get(treeName));
430 fTreeDTPC = new TTree(treeName,"TPC_Digits");
431 fTreeDTPC->Write(0,TObject::kOverwrite);
434 // special tree for TRD
435 sprintf(treeName,"TreeD%d_TRD",fEvent);
436 fTreeDTRD = static_cast<TTree*>(fOutput->Get(treeName));
438 fTreeDTRD = new TTree(treeName,"TRD_Digits");
439 fTreeDTRD->Write(0,TObject::kOverwrite);
444 ////////////////////////////////////////////////////////////////////////
445 void AliRunDigitizer::FinishEvent()
447 // called at the end of loop over digitizers
451 if (fCopyTreesFromInput > -1) {
453 i = fCopyTreesFromInput;
454 sprintf(treeName,"TreeK%d",fCombination[i]);
455 fInputFiles[i]->Get(treeName)->Clone()->Write();
456 sprintf(treeName,"TreeH%d",fCombination[i]);
457 fInputFiles[i]->Get(treeName)->Clone()->Write();
460 fNrOfEventsWritten++;
478 ////////////////////////////////////////////////////////////////////////
479 void AliRunDigitizer::FinishGlobal()
481 // called at the end of Exec
482 // save unique objects to the output file
485 this->Write(0,TObject::kOverwrite);
486 if (fCopyTreesFromInput > -1) {
487 fInputFiles[fCopyTreesFromInput]->Get("TE")->Clone()->Write();
494 ////////////////////////////////////////////////////////////////////////
495 Int_t AliRunDigitizer::GetNParticles(Int_t event) const
497 // return number of particles in all input files for a given
498 // event (as numbered in the output file)
499 // return -1 if some file cannot be accessed
503 for (Int_t i = 0; i < fNinputs; i++) {
504 sumI = GetNParticles(GetInputEventNumber(event,i), i);
505 if (sumI < 0) return -1;
511 ////////////////////////////////////////////////////////////////////////
512 Int_t AliRunDigitizer::GetNParticles(Int_t event, Int_t input) const
514 // return number of particles in input file input for a given
515 // event (as numbered in this input file)
516 // return -1 if some error
518 // Must be revised in the version with AliStream
523 TFile *file = ConnectInputFile(input);
525 Error("GetNParticles","Cannot open input file");
529 // find the header and get Nprimaries and Nsecondaries
530 TTree* tE = (TTree *)file->Get("TE") ;
532 Error("GetNParticles","input file does not contain TE");
537 tE->SetBranchAddress("Header", &header);
538 if (!tE->GetEntry(event)) {
539 Error("GetNParticles","event %d not found",event);
543 cerr<<"Nprimary: "<< header->GetNprimary()<<endl;
544 cerr<<"Nsecondary: "<<header->GetNsecondary()<<endl;
546 return header->GetNprimary() + header->GetNsecondary();
550 ////////////////////////////////////////////////////////////////////////
551 Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event) const
553 // return pointer to an int array with input event numbers which were
554 // merged in the output event event
556 // simplified for now, implement later
557 Int_t * a = new Int_t[kMaxStreamsToMerge];
558 for (Int_t i = 0; i < fNinputs; i++) {
563 ////////////////////////////////////////////////////////////////////////
564 Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t input) const
566 // return an event number of an eventInput from input file input
567 // which was merged to create output event event
569 // simplified for now, implement later
572 ////////////////////////////////////////////////////////////////////////
573 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event) const
575 // return pointer to particle with index i (index with mask)
578 Int_t input = i/fkMASKSTEP;
579 return GetParticle(i,input,GetInputEventNumber(event,input));
582 ////////////////////////////////////////////////////////////////////////
583 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t input, Int_t event) const
585 // return pointer to particle with index i in the input file input
586 // (index without mask)
587 // event is the event number in the file input
588 // return 0 i fit does not exist
590 // Must be revised in the version with AliStream
594 TFile *file = ConnectInputFile(input);
596 Error("GetParticle","Cannot open input file");
600 // find the header and get Nprimaries and Nsecondaries
601 TTree* tE = (TTree *)file->Get("TE") ;
603 Error("GetParticle","input file does not contain TE");
608 tE->SetBranchAddress("Header", &header);
609 if (!tE->GetEntry(event)) {
610 Error("GetParticle","event %d not found",event);
616 sprintf(treeName,"TreeK%d",event);
617 TTree* tK = static_cast<TTree*>(file->Get(treeName));
619 Error("GetParticle","input file does not contain TreeK%d",event);
622 TParticle *particleBuffer;
624 tK->SetBranchAddress("Particles", &particleBuffer);
627 // algorithmic way of getting entry index
628 // (primary particles are filled after secondaries)
630 if (i<header->GetNprimary())
631 entry = i+header->GetNsecondary();
633 entry = i-header->GetNprimary();
634 Int_t bytesRead = tK->GetEntry(entry);
635 // new ((*fParticles)[nentries]) TParticle(*fParticleBuffer);
637 return particleBuffer;
642 ////////////////////////////////////////////////////////////////////////
643 void AliRunDigitizer::ExecuteTask(Option_t* option)
645 // overwrite ExecuteTask to do Digitize only
647 if (!IsActive()) return;
649 fHasExecuted = kTRUE;
652 ////////////////////////////////////////////////////////////////////////
653 TString AliRunDigitizer::GetInputFileName(const Int_t input, const Int_t order) const
655 // returns file name of the order-th file in the input stream input
656 // returns empty string if such file does not exist
657 // first input stream is 0
658 // first file in the input stream is 0
659 TString fileName("");
660 if (input >= fNinputs) return fileName;
661 AliStream * stream = static_cast<AliStream*>(fInputStreams->At(input));
662 if (order > stream->GetNInputFiles()) return fileName;
663 fileName = stream->GetFileName(order);
666 ////////////////////////////////////////////////////////////////////////