]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliRunDigitizer.cxx
Fixed memory leaks from objects posting to TFolders and TTasks, AliPHOSQAAlarms
[u/mrichter/AliRoot.git] / STEER / AliRunDigitizer.cxx
CommitLineData
9ce40367 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/*
17$Log$
aee2ebe9 18Revision 1.1 2001/07/27 12:59:00 jchudoba
19Manager class for merging/digitization
20
9ce40367 21*/
22
23////////////////////////////////////////////////////////////////////////
24//
25// AliRunDigitizer.cxx
26//
27// Manager object for merging/digitization
28//
29// Instance of this class manages the digitization and/or merging of
30// Sdigits into Digits.
31//
32// Only one instance of this class is created in the macro:
33// AliRunDigitizer * manager = new AliRunDigitizer();
34// Then instances of specific detector digitizers are created:
35// AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager)
36// and the manager is configured (you have to specify input files
37// and an output file). The manager generates a combination of input
38// events according to an option set by SetCombinationType. Then it
39// connects appropriate trees from the input files, creates TreeD
40// in the output and runs once per event Digitize method of all existing
41// AliDetDigitizers (without any option). AliDetDigitizers ask manager
42// for a TTree with input (manager->GetNextTreeH(TTree *)
43// or manager->GetNextTreeS(TTree *),
44// merge all inputs, digitize it, and save it in the TreeD
45// obtained by manager->GetTreeD(). Output events are stored with
46// numbers from 0, this default can be changed by
47// manager->SetFirstOutputEventNr(Int_t) method. The particle numbers
48// in the output are shifted by MASK, which is taken from manager.
49//
50// Single input file is permitted. Maximum MAXFILESTOMERGE can be merged.
51// Input from the memory (on-the-fly merging) is not yet
52// supported, as well as access to the input data by invoking methods
53// on the output data.
54//
55// Access to the geometrical data is via gAlice for now (supposing the
56// same geometry in all input files), gAlice is taken from the defined
57// input file.
58//
59// Example with MUON digitizer:
60//
61// AliRunDigitizer * manager = new AliRunDigitizer();
62// manager->SetInput("1track_10events_phi45_60.root");
63// manager->SetInput("1track_10events_phi120_135.root");
64// manager->SetOutputDir("/home/z2/jchudoba/batch/jobtmp");
65// manager->SetOutputFile("digits.root");
66// AliMUONDigitizer *dMUON = new AliMUONDigitizer(manager);
67// manager->SetNrOfEventsToWrite(3);
68// manager->SetCopyTreesFromInput(1);
69// manager->Digitize();
70//
71////////////////////////////////////////////////////////////////////////
72
73// system includes
74
75#include <iostream.h>
76
77// ROOT includes
78
79#include "TFile.h"
80#include "TTree.h"
81
82// AliROOT includes
83
84#include "AliRunDigitizer.h"
85#include "AliDigitizer.h"
86#include "AliRun.h"
87#include "AliHeader.h"
88#include "TParticle.h"
89
90ClassImp(AliRunDigitizer)
91
92////////////////////////////////////////////////////////////////////////
93
94 AliRunDigitizer::AliRunDigitizer() : TNamed("AliRunDigitizer","")
95{
96// default ctor
97
aee2ebe9 98 Int_t i;
99
100 for (i=0;i<MAXDETECTORS;i++) fDigitizers[i]=0;
9ce40367 101 fNDigitizers = 0;
102 fNinputs = 0;
103 fOutputFileName = "digits.root";
104 fOutputDirName = "/tmp/";
105 fCombination.Set(MAXFILESTOMERGE);
aee2ebe9 106 for (i=0;i<MAXFILESTOMERGE;i++) {
9ce40367 107 fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=NULL;
108 fCombination[i]=-1;
109 }
110 fkMASKSTEP = 10000000;
111 fkMASK[0] = 0;
aee2ebe9 112 for (i=0;i<MAXFILESTOMERGE;i++) {
9ce40367 113 fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
114 }
115 fInputFileNames = new TClonesArray("TObjString",1);
116 fInputFiles = new TClonesArray("TFile",1);
117 fMinNEvents = 99999999;
118 fCombinationType=1;
119 fCombinationFileName = "combination.txt";
120 fOutput = 0;
121 fEvent = 0;
122 fNrOfEventsToWrite = 0;
123 fNrOfEventsWritten = 0;
124 fCopyTreesFromInput = -1;
125 fDebug = 3;
126 if (GetDebug()>2)
127 cerr<<"AliRunDigitizer::AliRunDigitizer() called"<<endl;
128}
129
130////////////////////////////////////////////////////////////////////////
131
132AliRunDigitizer::~AliRunDigitizer() {
133// dtor
134
135 if (fInputFiles) delete fInputFiles;
136 if (fInputFileNames) delete fInputFileNames;
137}
138
139////////////////////////////////////////////////////////////////////////
140void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
141{
142// add digitizer to the list of active digitizers
143
144 if (fNDigitizers >= MAXDETECTORS) {
145 cerr<<"Too many detectors to digitize. Increase value of MAXDETECTORS"
146 <<" constant in AliRunDigitizer.h and recompile or decrease the"
147 <<" the number of detectors"<<endl;
148 } else {
149 fDigitizers[fNDigitizers++] = digitizer;
150 }
151}
152
153////////////////////////////////////////////////////////////////////////
154
155Bool_t AliRunDigitizer::SetInput(char *inputFile)
156{
157// receives the name of the input file. Opens it and stores pointer
158// to it, returns kFALSE if fails
159// if inputFile = MEMORY, uses pointers from gAlice - not yet implemented
160
161// input cannot be output - open READ only
162 TFile *file = new((*fInputFiles)[fNinputs]) TFile(inputFile,"READ");
163
164 if (GetDebug()>2) cerr<<"AliRunDigitizer::SetInput: file = "<<file<<endl;
165 if (!file->IsOpen()) {
166 cerr<<"ERROR: AliRunDigitizer::SetInput: cannot open file "
167 <<inputFile<<endl;
168 return kFALSE;
169 }
170
171// find Header and get nr of events there
172 TTree * te = (TTree *) file->Get("TE") ;
173 if (!te) {
174 cerr<<"ERROR: AliRunDigitizer::SetInput: input file does "
175 <<"not contain TE"<<endl;
176 return kFALSE;
177 }
178 Int_t nEntries = (Int_t) te->GetEntries();
179
180 if (GetDebug()>2) cerr<<"AliRunDigitizer::SetInput: nEntries = "
181 <<nEntries<<endl;
182 if (nEntries < 1) {
183 cerr<<"ERROR: AliRunDigitizer::SetInput: input file does "
184 <<"not contain any event"<<endl;
185 return kFALSE;
186 }
187
188 if (nEntries < fMinNEvents) fNrOfEventsToWrite = fMinNEvents = nEntries;
189
190// find gAlice object if it is a first input file
191// this is only temporary solution, we need gAlice to access detector
192// geometry parameters. Unfortunately I have to include AliRun header file.
193 if (fNinputs == 0) {
194 gAlice = (AliRun*)file->Get("gAlice");
195 if (GetDebug() > 2) cerr<<"gAlice taken from the first input: "
196 <<gAlice<<endl;
197 if (!gAlice) {
198 cerr<<"ERROR: AliRunDigitizer::SetInput: first input file "
199 <<"does not contain gAlice object"<<endl;
200 return kFALSE;
201 }
202 }
203
204// store this file name if it is OK
205 new((*fInputFileNames)[fNinputs]) TObjString(inputFile);
206 fNinputs++;
207 if (GetDebug() > 2) cerr<<"fNinputs = "<<fNinputs<<endl;
208 return kTRUE;
209}
210
211////////////////////////////////////////////////////////////////////////
212Bool_t AliRunDigitizer::MakeCombination()
213{
214// make a new combination of events from different files
215
216 Int_t type = fCombinationType;
217 if (fNrOfEventsWritten >= fNrOfEventsToWrite) return kFALSE;
218
219 switch (type) {
220
221 case 1:
222// type = 1: 1-1-1 - take the same event number from each file
223 if (fCombination[0]<fMinNEvents-1) {
224 for (Int_t i=0;i<fNinputs;i++) fCombination[i]++;
225 return kTRUE;
226 }
227 if (GetDebug()>2)
228 cerr<<"AliRunDigitizer::MakeCombination: Warning: "
229 <<"maximum number of Events in an input file "
230 <<"was reached."<<endl;
231 break;
232
233 case 2:
234// type = 2: read from the file combinations.ascii
235// not yet implemented 100% correctly - requires 4 entries in the row
236 static FILE *fp ;
237 static Int_t linesRead;
238 if (!fp) {
239 fp = fopen(fCombinationFileName.Data(),"r");
240 linesRead = 0;
241 }
242 if (!fp) {
243 cerr<<"AliRunDigitizer::MakeCombination ERROR: "
244 <<"Cannot open input file with combinations."<<endl;
245 return kFALSE;
246 }
247 Int_t var[4], nInputs;
248 char line[80];
249// since I do not close or rewind the file, the position should be correct
250 if (fgets(line,80,fp)) {
251 nInputs = sscanf(&line[0],"%d%d%d%d",&var[0],&var[1],&var[2],&var[3]);
252 if (nInputs != fNinputs) {
253 cerr<<"AliRunDigitizer::MakeCombination ERROR: "
254 <<"Nr. of input files is different from nr "
255 <<"integers defining the combination"<<endl;
256 return kFALSE;
257 }
258 while(nInputs--) {
259 fCombination[nInputs] = var[nInputs];
260 }
261 return kTRUE;
262 } else {
263 cerr<<"AliRunDigitizer::MakeCombination ERROR: "
264 <<"no more input in the file with combinations"<<endl;
265 return kFALSE;
266 }
267
268 default:
269 cerr<<"AliRunDigitizer::MakeCombination: ERROR: "
270 <<"wrong type of required combination type: "<<type<<endl;
271 }
272 return kFALSE;
273}
274
275////////////////////////////////////////////////////////////////////////
276void AliRunDigitizer::PrintCombination()
277{
278// debug method to print current combination
279
280 cerr<<"AliRunDigitizer::PrintCombination: Current events combination:"<<endl;
281 for (Int_t i=0;i<fNinputs;i++) {
282 cerr<<"File: "<<((TObjString *)fInputFileNames->At(i))->GetString()<<"\tEvent: "<<fCombination[i]<<endl;
283 }
284}
285
286////////////////////////////////////////////////////////////////////////
287void AliRunDigitizer::Digitize()
288{
289// get a new combination of inputs, connect input trees and loop
290// over all digitizers
291
292 if (!InitGlobal()) {
293 cerr<<"False from InitGlobal"<<endl;
294 return;
295 }
296// take gAlice from the first input file. It is needed to access
297// geometry data
298 while (MakeCombination()) {
299 if (GetDebug()>2) PrintCombination();
300 ConnectInputTrees();
301 InitPerEvent();
302// loop over all registered digitizers and let them do the work
303 for (Int_t i=0;i<fNDigitizers; i++) {
304 fDigitizers[i]->Digitize();
305 }
306 FinishPerEvent();
307 }
308 FinishGlobal();
309}
310
311////////////////////////////////////////////////////////////////////////
312void AliRunDigitizer::ConnectInputTrees()
313{
314// fill arrays fArrayTreeS, fArrayTreeH and fArrayTreeTPCS with
315// pointers to the correct events according fCombination values
316// null pointers can be in the output, AliDigitizer has to check it
317
318 TFile *file;
319 TTree *tree;
320 char treeName[20];
321 for (Int_t i=0;i<fNinputs;i++) {
322 file = (TFile*)(*fInputFiles)[i];
323 sprintf(treeName,"TreeS%d",fCombination[i]);
324 tree = (TTree *) file->Get(treeName);
325 fArrayTreeS[i] = tree;
326 sprintf(treeName,"TreeH%d",fCombination[i]);
327 tree = (TTree *) file->Get(treeName);
328 fArrayTreeH[i] = tree;
329 sprintf(treeName,"TreeD_75x40_100x60_%d",fCombination[i]);
330 tree = (TTree *) file->Get(treeName);
331 fArrayTreeTPCS[i] = tree;
332 }
333}
334
335////////////////////////////////////////////////////////////////////////
336Bool_t AliRunDigitizer::InitGlobal()
337{
338// called once before Digitize() is called, initialize digitizers and output
339
340 if (!InitOutputGlobal()) return kFALSE;
341 for (Int_t i=0;i<fNDigitizers; i++) {
342 if (!fDigitizers[i]->Init()) return kFALSE;
343 }
344 return kTRUE;
345}
346
347////////////////////////////////////////////////////////////////////////
348Bool_t AliRunDigitizer::InitOutputGlobal()
349{
350// Creates the output file, called once by InitGlobal()
351
352 TString fn;
353 fn = fOutputDirName + '/' + fOutputFileName;
354 fOutput = new TFile(fn,"recreate");
355 if (GetDebug()>2) {
356 cerr<<"file "<<fn.Data()<<" was opened"<<endl;
357 cerr<<"fOutput = "<<fOutput<<endl;
358 }
359 if (fOutput) return kTRUE;
360 Error("InitOutputGlobal","Could not create output file.");
361 return kFALSE;
362}
363
364
365////////////////////////////////////////////////////////////////////////
366void AliRunDigitizer::InitPerEvent()
367{
368// Creates TreeDxx in the output file, called from Digitize() once for
369// each event. xx = fEvent
370
371 if (GetDebug()>2)
372 cerr<<"AliRunDigitizer::InitPerEvent: fEvent = "<<fEvent<<endl;
373 fOutput->cd();
374 char hname[30];
375 sprintf(hname,"TreeD%d",fEvent);
376 fTreeD = new TTree(hname,"Digits");
377// fTreeD->Write(); // Do I have to write it here???
378}
379
380
381////////////////////////////////////////////////////////////////////////
382TTree* AliRunDigitizer::GetNextTreeH(TTree *current) const
383{
384// returns next one after the current one
385// returns the first if the current is NULL
386// returns NULL if the current is the last one
387
388 if (fNinputs <= 0) return 0;
389 if (current == 0) return fArrayTreeH[0];
390 for (Int_t i=0; i<fNinputs-1; i++) {
391 if (current == fArrayTreeH[i]) return fArrayTreeH[i+1];
392 }
393 return 0;
394}
395////////////////////////////////////////////////////////////////////////
396TTree* AliRunDigitizer::GetNextTreeS(TTree *current) const
397{
398// returns next one after the current one
399// returns the first if the current is NULL
400// returns NULL if the current is the last one
401
402 if (fNinputs <= 0) return 0;
403 if (current == 0) return fArrayTreeS[0];
404 for (Int_t i=0; i<fNinputs-1; i++) {
405 if (current == fArrayTreeS[i]) return fArrayTreeS[i+1];
406 }
407 return 0;
408}
409////////////////////////////////////////////////////////////////////////
410TTree* AliRunDigitizer::GetNextTreeTPCS(TTree *current) const
411{
412// returns next one after the current one
413// returns the first if the current is NULL
414// returns NULL if the current is the last one
415
416 if (fNinputs <= 0) return 0;
417 if (current == 0) return fArrayTreeTPCS[0];
418 for (Int_t i=0; i<fNinputs-1; i++) {
419 if (current == fArrayTreeTPCS[i]) return fArrayTreeTPCS[i+1];
420 }
421 return 0;
422}
423
424////////////////////////////////////////////////////////////////////////
425Int_t AliRunDigitizer::GetNextMask(Int_t current) const
426{
427// returns next one after the current one
428// returns the first if the current is negative
429// returns negative if the current is the last one
430
431 if (fNinputs <= 0) return -1;
432 if (current < 0) return fkMASK[0];
433 for (Int_t i=0; i<fNinputs-1; i++) {
434 if (current == fkMASK[i]) return fkMASK[i+1];
435 }
436 return -1;
437}
438////////////////////////////////////////////////////////////////////////
439void AliRunDigitizer::FinishPerEvent()
440{
441// called at the end of loop over digitizers
442
443 fOutput->cd();
444 if (fCopyTreesFromInput > -1) {
445 char treeName[20];
446 Int_t i = fCopyTreesFromInput;
447 sprintf(treeName,"TreeK%d",fCombination[i]);
448 ((TFile*)fInputFiles->At(i))->Get(treeName)->Clone()->Write();
449 sprintf(treeName,"TreeH%d",fCombination[i]);
450 ((TFile*)fInputFiles->At(i))->Get(treeName)->Clone()->Write();
451 }
452 fEvent++;
453 fNrOfEventsWritten++;
454 if (fTreeD) {
455 delete fTreeD;
456 fTreeD = 0;
457 }
458}
459////////////////////////////////////////////////////////////////////////
460void AliRunDigitizer::FinishGlobal()
461{
462// called at the end of Exec
463// save unique objects to the output file
464
465 fOutput->cd();
466 this->Write();
467 if (fCopyTreesFromInput > -1) {
468 ((TFile*)fInputFiles->At(fCopyTreesFromInput))->Get("TE")
469 ->Clone()->Write();
470 gAlice->Write();
471 }
472 fOutput->Close();
473}
474
475
476////////////////////////////////////////////////////////////////////////
477Int_t AliRunDigitizer::GetNParticles(Int_t event)
478{
479// return number of particles in all input files for a given
480// event (as numbered in the output file)
481// return -1 if some file cannot be accessed
482
483 Int_t sum = 0;
484 Int_t sumI;
485 for (Int_t i = 0; i < fNinputs; i++) {
486 sumI = GetNParticles(GetInputEventNumber(event,i), i);
487 if (sumI < 0) return -1;
488 sum += sumI;
489 }
490 return sum;
491}
492
493////////////////////////////////////////////////////////////////////////
494Int_t AliRunDigitizer::GetNParticles(Int_t event, Int_t input)
495{
496// return number of particles in input file input for a given
497// event (as numbered in this input file)
498// return -1 if some error
499
500 TFile *file = ConnectInputFile(input);
501 if (!file) {
502 Error("GetNParticles","Cannot open input file");
503 return -1;
504 }
505
506// find the header and get Nprimaries and Nsecondaries
507 TTree* tE = (TTree *)file->Get("TE") ;
508 if (!tE) {
509 Error("GetNParticles","input file does not contain TE");
510 return -1;
511 }
512 AliHeader* header;
513 header = 0;
514 tE->SetBranchAddress("Header", &header);
515 if (!tE->GetEntry(event)) {
516 Error("GetNParticles","event %d not found",event);
517 return -1;
518 }
519 if (GetDebug()>2) {
520 cerr<<"Nprimary: "<< header->GetNprimary()<<endl;
521 cerr<<"Nsecondary: "<<header->GetNsecondary()<<endl;
522 }
523 return header->GetNprimary() + header->GetNsecondary();
524}
525
526////////////////////////////////////////////////////////////////////////
527Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event)
528{
529// return pointer to an int array with input event numbers which were
530// merged in the output event event
531
532// simplified for now, implement later
533 Int_t a[MAXFILESTOMERGE];
534 for (Int_t i = 0; i < fNinputs; i++) {
535 a[i] = event;
536 }
537 return a;
538}
539////////////////////////////////////////////////////////////////////////
540Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t input)
541{
542// return an event number of an eventInput from input file input
543// which was merged to create output event event
544
545// simplified for now, implement later
546 return event;
547}
548////////////////////////////////////////////////////////////////////////
549TFile* AliRunDigitizer::ConnectInputFile(Int_t input)
550{
551// open input file with index input
552// 1st file has index 0
553// return 0x0 if fails
554
555// check if file with index input is already open
556 TFile *file = 0;
557 if (fInputFiles->GetEntriesFast() > input)
558 file = static_cast<TFile *>(fInputFiles->At(input));
559
560 if (!file) {
561 // find the file name and open it
562 TObjString *fn = static_cast<TObjString *>(fInputFileNames->At(input));
563 file = new((*fInputFiles)[input]) TFile((fn->GetString()).Data(),"READ");
564 if (!file) {
565 Error("ConnectInputFile","Cannot open input file");
566 return 0;
567 }
568 if (!file->IsOpen()) {
569 Error("ConnectInputFile","Cannot open input file");
570 return 0;
571 }
572 }
573 return file;
574}
575
576////////////////////////////////////////////////////////////////////////
577TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event)
578{
579// return pointer to particle with index i (index with mask)
580
581// decode the MASK
582 Int_t input = i/fkMASKSTEP;
583 return GetParticle(i,input,GetInputEventNumber(event,input));
584}
585
586////////////////////////////////////////////////////////////////////////
587TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t input, Int_t event)
588{
589// return pointer to particle with index i in the input file input
590// (index without mask)
591// event is the event number in the file input
592// return 0 i fit does not exist
593
594 TFile *file = ConnectInputFile(input);
595 if (!file) {
596 Error("GetParticle","Cannot open input file");
597 return 0;
598 }
599
600// find the header and get Nprimaries and Nsecondaries
601 TTree* tE = (TTree *)file->Get("TE") ;
602 if (!tE) {
603 Error("GetParticle","input file does not contain TE");
604 return 0;
605 }
606 AliHeader* header;
607 header = 0;
608 tE->SetBranchAddress("Header", &header);
609 if (!tE->GetEntry(event)) {
610 Error("GetParticle","event %d not found",event);
611 return 0;
612 }
613
614// connect TreeK
615 char treeName[30];
616 sprintf(treeName,"TreeK%d",event);
617 TTree* tK = static_cast<TTree*>(file->Get(treeName));
618 if (!tK) {
619 Error("GetParticle","input file does not contain TreeK%d",event);
620 return 0;
621 }
622 TParticle *particleBuffer;
623 particleBuffer = 0;
624 tK->SetBranchAddress("Particles", &particleBuffer);
625
626
627// algorithmic way of getting entry index
628// (primary particles are filled after secondaries)
629 Int_t entry;
630 if (i<header->GetNprimary())
631 entry = i+header->GetNsecondary();
632 else
633 entry = i-header->GetNprimary();
634// tK->GetEntry(0); // do I need this???
635 Int_t bytesRead = tK->GetEntry(entry);
636// new ((*fParticles)[nentries]) TParticle(*fParticleBuffer);
637 if (bytesRead)
638 return particleBuffer;
639 return 0;
640}
641////////////////////////////////////////////////////////////////////////
642