Write file instead of closing it
[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 /*
17 $Log$
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.
20
21 Revision 1.17  2002/07/16 13:47:53  jchudoba
22 Add methods to get access to names of files used in merging.
23
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.
26
27 Revision 1.15  2002/04/09 13:38:47  jchudoba
28 Add const to the filename argument
29
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.
32
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.
35
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
38
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
41
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.
44
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
47
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
50
51 Revision 1.7  2001/10/04 15:56:07  jchudoba
52 TTask inheritance
53
54 Revision 1.4  2001/09/19 06:23:50  jchudoba
55 Move some tasks to AliStream and AliMergeCombi classes
56
57 Revision 1.3  2001/07/30 14:04:18  jchudoba
58 correct bug in the initialization
59
60 Revision 1.2  2001/07/28 10:44:32  hristov
61 Loop variable declared once; typos corrected
62
63 Revision 1.1  2001/07/27 12:59:00  jchudoba
64 Manager class for merging/digitization
65
66 */
67
68 ////////////////////////////////////////////////////////////////////////
69 //
70 // AliRunDigitizer.cxx
71 //
72 // Manager object for merging/digitization
73 //
74 // Instance of this class manages the digitization and/or merging of
75 // Sdigits into Digits. 
76 //
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.
97 //
98 // The default output is to the signal file (stream 0). This can be 
99 // changed with the SetOutputFile(TString fn)  method.
100 //
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.
105 //
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.
109 //
110 // Example with MUON digitizer, no merging, just digitization
111 //
112 //  AliRunDigitizer * manager = new AliRunDigitizer(1,1);
113 //  manager->SetInputStream(0,"galice.root");
114 //  AliMUONDigitizer *dMUON  = new AliMUONDigitizer(manager);
115 //  manager->Exec("");
116 //
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)
121 //
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("");
127 //
128 // Example with MUON digitizer, save digits in a new file digits.root,
129 //   process only 1 event
130 //
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("");
138 //
139 //////////////////////////////////////////////////////////////////////// 
140
141 // system includes
142
143 #include <iostream.h>
144
145 // ROOT includes
146
147 #include "TFile.h"
148 #include "TTree.h"
149 #include "TList.h"
150
151 // AliROOT includes
152
153 #include "AliRunDigitizer.h"
154 #include "AliDigitizer.h"
155 #include "AliRun.h"
156 #include "AliHeader.h"
157 #include "TParticle.h"
158 #include "AliStream.h"
159 #include "AliMergeCombi.h"
160
161 ClassImp(AliRunDigitizer)
162
163 ////////////////////////////////////////////////////////////////////////
164 AliRunDigitizer::AliRunDigitizer()
165 {
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
168   
169 // just set all pointers - data members to 0
170   fOutput = 0;
171   fTreeD = 0;
172   fTreeR = 0;
173   fTreeDTPC = 0;
174   fTreeDTRD = 0;
175   fInputStreams = 0;
176   for (Int_t i=0;i<kMaxStreamsToMerge;i++) {
177     fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
178     fInputFiles[i]=0;
179   }
180   fCombi = 0;
181
182 }
183
184 ////////////////////////////////////////////////////////////////////////
185 AliRunDigitizer::AliRunDigitizer(Int_t nInputStreams, Int_t sperb) : TTask("AliRunDigitizer","The manager for Merging")
186 {
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");
190     return;
191   }
192   Int_t i;
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;
199     fCombination[i]=-1;
200   }
201   fkMASKSTEP = 10000000;
202   fkMASK[0] = 0;
203   for (i=1;i<kMaxStreamsToMerge;i++) {
204     fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
205   }
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");
212   }
213   fOutput = 0;
214   fEvent = 0;
215   fNrOfEventsToWrite = -1;
216   fNrOfEventsWritten = 0;
217   fCopyTreesFromInput = -1;
218   fCombi = new AliMergeCombi(nInputStreams,sperb);
219   fDebug = 0;
220   fTreeD = 0;
221   fTreeR = 0;
222   fTreeDTPC = 0;
223   fTreeDTRD = 0;
224   fTreeDTPCBaseName = "TreeD_75x40_100x60_150x60_";
225   fTreeTPCSBaseName = "TreeS_75x40_100x60_150x60_";
226
227   for (i=0; i<kMaxStreamsToMerge; i++) fInputFiles[i]=0;
228 }
229
230 ////////////////////////////////////////////////////////////////////////
231
232 AliRunDigitizer::~AliRunDigitizer() {
233 // dtor
234
235 // do not delete subtasks, let the creator delete them
236   if (GetListOfTasks()) 
237     GetListOfTasks()->Clear("nodelete");
238   
239   if (fInputStreams) {
240     delete fInputStreams;
241     fInputStreams = 0;
242   }
243   if (fCombi) {
244     delete fCombi;
245     fCombi = 0;
246   }
247
248 }
249 ////////////////////////////////////////////////////////////////////////
250 void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
251 {
252 // add digitizer to the list of active digitizers
253   this->Add(digitizer);
254 }
255 ////////////////////////////////////////////////////////////////////////
256 void AliRunDigitizer::SetInputStream(Int_t i, const char *inputFile)
257 {
258   if (i > fInputStreams->GetLast()) {
259     Error("SetInputStream","Input stream number too high");
260     return;
261   }
262   static_cast<AliStream*>(fInputStreams->At(i))->AddFile(inputFile);
263 }
264
265 ////////////////////////////////////////////////////////////////////////
266 void AliRunDigitizer::Digitize(Option_t* option)
267 {
268 // get a new combination of inputs, connect input trees and loop 
269 // over all digitizers
270
271 // take gAlice from the first input file. It is needed to access
272 //  geometry data
273 // If gAlice is already in memory, use it
274   if (!gAlice) {
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;
278       return;
279     }
280   }
281   if (!InitGlobal()) {
282     cerr<<"False from InitGlobal"<<endl;
283     return;
284   }
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;
289     InitEvent();
290 // loop over all registered digitizers and let them do the work
291     ExecuteTasks(option);
292     CleanTasks();
293     FinishEvent();
294   }
295   FinishGlobal();
296 }
297
298 ////////////////////////////////////////////////////////////////////////
299 Bool_t AliRunDigitizer::ConnectInputTrees()
300 {
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
304
305   TTree *tree;
306   char treeName[50];
307   Int_t serialNr;
308   Int_t eventNr[kMaxStreamsToMerge], delta[kMaxStreamsToMerge];
309   fCombi->Combination(eventNr, delta);
310   for (Int_t i=0;i<fNinputs;i++) {
311     if (delta[i] == 1) {
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];
319         fArrayTreeS[i] = 0;
320       }
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];
326         fArrayTreeH[i] = 0;
327       }
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;
334       }
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;
341       }
342       fArrayTreeTRDS[i] = tree;
343     } else if (delta[i] != 0) {
344       Error("ConnectInputTrees","Only delta 0 or 1 is implemented");
345       return kFALSE;
346     }
347   }
348   return kTRUE;
349 }
350
351 ////////////////////////////////////////////////////////////////////////
352 Bool_t AliRunDigitizer::InitGlobal()
353 {
354 // called once before Digitize() is called, initialize digitizers and output
355
356   TList* subTasks = this->GetListOfTasks();
357   if (subTasks) {
358     subTasks->ForEach(AliDigitizer,Init)();
359   }  
360   return kTRUE;
361 }
362
363 ////////////////////////////////////////////////////////////////////////
364
365 void AliRunDigitizer::SetOutputFile(TString fn)
366 // the output will be to separate file, not to the signal file
367 {
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 void AliRunDigitizer::FinishGlobal()
474 {
475 // called at the end of Exec
476 // save unique objects to the output file
477
478   fOutput->cd();
479   this->Write(0,TObject::kOverwrite);
480   if (fCopyTreesFromInput > -1) {
481     fInputFiles[fCopyTreesFromInput]->Get("TE")->Clone()->Write();
482     gAlice->Write();
483   }
484   fOutput->Write();
485 }
486
487
488 ////////////////////////////////////////////////////////////////////////
489 Int_t  AliRunDigitizer::GetNParticles(Int_t event) const
490 {
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
494
495   Int_t sum = 0;
496   Int_t sumI;
497   for (Int_t i = 0; i < fNinputs; i++) {
498     sumI = GetNParticles(GetInputEventNumber(event,i), i);
499     if (sumI < 0) return -1;
500     sum += sumI;
501   }
502   return sum;
503 }
504
505 ////////////////////////////////////////////////////////////////////////
506 Int_t  AliRunDigitizer::GetNParticles(Int_t event, Int_t input) const
507 {
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
511
512 // Must be revised in the version with AliStream
513
514   return -1;
515
516 /*
517   TFile *file = ConnectInputFile(input);
518   if (!file) {
519     Error("GetNParticles","Cannot open input file");
520     return -1;
521   }
522
523 // find the header and get Nprimaries and Nsecondaries
524   TTree* tE = (TTree *)file->Get("TE") ;
525   if (!tE) {
526     Error("GetNParticles","input file does not contain TE");
527     return -1;
528   }
529   AliHeader* header;
530   header = 0;
531   tE->SetBranchAddress("Header", &header);
532   if (!tE->GetEntry(event)) {
533     Error("GetNParticles","event %d not found",event);
534     return -1;
535   }
536   if (GetDebug()>2) {
537     cerr<<"Nprimary: "<< header->GetNprimary()<<endl;
538     cerr<<"Nsecondary: "<<header->GetNsecondary()<<endl;
539   }
540   return header->GetNprimary() + header->GetNsecondary();
541 */
542 }
543
544 ////////////////////////////////////////////////////////////////////////
545 Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event) const
546 {
547 // return pointer to an int array with input event numbers which were
548 // merged in the output event event
549
550 // simplified for now, implement later
551   Int_t * a = new Int_t[kMaxStreamsToMerge];
552   for (Int_t i = 0; i < fNinputs; i++) {
553     a[i] = event;
554   }
555   return a;
556 }
557 ////////////////////////////////////////////////////////////////////////
558 Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t input) const
559 {
560 // return an event number of an eventInput from input file input
561 // which was merged to create output event event
562
563 // simplified for now, implement later
564   return event;
565 }
566 ////////////////////////////////////////////////////////////////////////
567 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event) const
568 {
569 // return pointer to particle with index i (index with mask)
570
571 // decode the MASK
572   Int_t input = i/fkMASKSTEP;
573   return GetParticle(i,input,GetInputEventNumber(event,input));
574 }
575
576 ////////////////////////////////////////////////////////////////////////
577 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t input, Int_t event) const
578 {
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
583
584 // Must be revised in the version with AliStream
585
586   return 0;
587 /*
588   TFile *file = ConnectInputFile(input);
589   if (!file) {
590     Error("GetParticle","Cannot open input file");
591     return 0;
592   }
593
594 // find the header and get Nprimaries and Nsecondaries
595   TTree* tE = (TTree *)file->Get("TE") ;
596   if (!tE) {
597     Error("GetParticle","input file does not contain TE");
598     return 0;
599   }
600   AliHeader* header;
601   header = 0;
602   tE->SetBranchAddress("Header", &header);
603   if (!tE->GetEntry(event)) {
604     Error("GetParticle","event %d not found",event);
605     return 0;
606   }
607   
608 // connect TreeK  
609   char treeName[30];
610   sprintf(treeName,"TreeK%d",event);  
611   TTree* tK = static_cast<TTree*>(file->Get(treeName));
612   if (!tK) {
613     Error("GetParticle","input file does not contain TreeK%d",event);
614     return 0;
615   }
616   TParticle *particleBuffer;
617   particleBuffer = 0;
618   tK->SetBranchAddress("Particles", &particleBuffer);
619
620
621 // algorithmic way of getting entry index
622 // (primary particles are filled after secondaries)
623   Int_t entry;
624   if (i<header->GetNprimary())
625     entry = i+header->GetNsecondary();
626   else 
627     entry = i-header->GetNprimary();
628   Int_t bytesRead = tK->GetEntry(entry);
629 //  new ((*fParticles)[nentries]) TParticle(*fParticleBuffer);
630   if (bytesRead)
631     return particleBuffer;
632   return  0;
633 */
634 }
635
636 ////////////////////////////////////////////////////////////////////////
637 void AliRunDigitizer::ExecuteTask(Option_t* option)
638 {
639 // overwrite ExecuteTask to do Digitize only
640
641   if (!IsActive()) return;
642   Digitize(option);
643   fHasExecuted = kTRUE;
644   return;
645 }
646 ////////////////////////////////////////////////////////////////////////
647 TString AliRunDigitizer::GetInputFileName(const Int_t input, const Int_t order) const 
648 {
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);
658   return fileName;
659 }
660 ////////////////////////////////////////////////////////////////////////