]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliRunDigitizer.cxx
Add methods to get access to names of files used in merging.
[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.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.
20
21 Revision 1.15  2002/04/09 13:38:47  jchudoba
22 Add const to the filename argument
23
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.
26
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.
29
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
32
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
35
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.
38
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
41
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
44
45 Revision 1.7  2001/10/04 15:56:07  jchudoba
46 TTask inheritance
47
48 Revision 1.4  2001/09/19 06:23:50  jchudoba
49 Move some tasks to AliStream and AliMergeCombi classes
50
51 Revision 1.3  2001/07/30 14:04:18  jchudoba
52 correct bug in the initialization
53
54 Revision 1.2  2001/07/28 10:44:32  hristov
55 Loop variable declared once; typos corrected
56
57 Revision 1.1  2001/07/27 12:59:00  jchudoba
58 Manager class for merging/digitization
59
60 */
61
62 ////////////////////////////////////////////////////////////////////////
63 //
64 // AliRunDigitizer.cxx
65 //
66 // Manager object for merging/digitization
67 //
68 // Instance of this class manages the digitization and/or merging of
69 // Sdigits into Digits. 
70 //
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.
91 //
92 // The default output is to the signal file (stream 0). This can be 
93 // changed with the SetOutputFile(TString fn)  method.
94 //
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.
99 //
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.
103 //
104 // Example with MUON digitizer, no merging, just digitization
105 //
106 //  AliRunDigitizer * manager = new AliRunDigitizer(1,1);
107 //  manager->SetInputStream(0,"galice.root");
108 //  AliMUONDigitizer *dMUON  = new AliMUONDigitizer(manager);
109 //  manager->Exec("");
110 //
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)
115 //
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("");
121 //
122 // Example with MUON digitizer, save digits in a new file digits.root,
123 //   process only 1 event
124 //
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("");
132 //
133 //////////////////////////////////////////////////////////////////////// 
134
135 // system includes
136
137 #include <iostream.h>
138
139 // ROOT includes
140
141 #include "TFile.h"
142 #include "TTree.h"
143 #include "TList.h"
144
145 // AliROOT includes
146
147 #include "AliRunDigitizer.h"
148 #include "AliDigitizer.h"
149 #include "AliRun.h"
150 #include "AliHeader.h"
151 #include "TParticle.h"
152 #include "AliStream.h"
153 #include "AliMergeCombi.h"
154
155 ClassImp(AliRunDigitizer)
156
157 ////////////////////////////////////////////////////////////////////////
158 AliRunDigitizer::AliRunDigitizer()
159 {
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
162   
163 // just set all pointers - data members to 0
164   fOutput = 0;
165   fTreeD = 0;
166   fTreeR = 0;
167   fTreeDTPC = 0;
168   fTreeDTRD = 0;
169   fInputStreams = 0;
170   for (Int_t i=0;i<kMaxStreamsToMerge;i++) {
171     fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=fArrayTreeTRDS[i]=NULL;
172     fInputFiles[i]=0;
173   }
174   fCombi = 0;
175
176 }
177
178 ////////////////////////////////////////////////////////////////////////
179 AliRunDigitizer::AliRunDigitizer(Int_t nInputStreams, Int_t sperb) : TTask("AliRunDigitizer","The manager for Merging")
180 {
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");
184     return;
185   }
186   Int_t i;
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;
193     fCombination[i]=-1;
194   }
195   fkMASKSTEP = 10000000;
196   fkMASK[0] = 0;
197   for (i=1;i<kMaxStreamsToMerge;i++) {
198     fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
199   }
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");
206   }
207   fOutput = 0;
208   fEvent = 0;
209   fNrOfEventsToWrite = -1;
210   fNrOfEventsWritten = 0;
211   fCopyTreesFromInput = -1;
212   fCombi = new AliMergeCombi(nInputStreams,sperb);
213   fDebug = 0;
214   fTreeD = 0;
215   fTreeR = 0;
216   fTreeDTPC = 0;
217   fTreeDTRD = 0;
218   fTreeDTPCBaseName = "TreeD_75x40_100x60_150x60_";
219   fTreeTPCSBaseName = "TreeS_75x40_100x60_150x60_";
220
221   for (i=0; i<kMaxStreamsToMerge; i++) fInputFiles[i]=0;
222 }
223
224 ////////////////////////////////////////////////////////////////////////
225
226 AliRunDigitizer::~AliRunDigitizer() {
227 // dtor
228
229   if (fInputStreams) {
230     delete fInputStreams;
231     fInputStreams = 0;
232   }
233   if (fCombi) {
234     delete fCombi;
235     fCombi = 0;
236   }
237
238 }
239 ////////////////////////////////////////////////////////////////////////
240 void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
241 {
242 // add digitizer to the list of active digitizers
243   this->Add(digitizer);
244 }
245 ////////////////////////////////////////////////////////////////////////
246 void AliRunDigitizer::SetInputStream(Int_t i, const char *inputFile)
247 {
248   if (i > fInputStreams->GetLast()) {
249     Error("SetInputStream","Input stream number too high");
250     return;
251   }
252   static_cast<AliStream*>(fInputStreams->At(i))->AddFile(inputFile);
253 }
254
255 ////////////////////////////////////////////////////////////////////////
256 void AliRunDigitizer::Digitize(Option_t* option)
257 {
258 // get a new combination of inputs, connect input trees and loop 
259 // over all digitizers
260
261 // take gAlice from the first input file. It is needed to access
262 //  geometry data
263 // If gAlice is already in memory, use it
264   if (!gAlice) {
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;
268       return;
269     }
270   }
271   if (!InitGlobal()) {
272     cerr<<"False from InitGlobal"<<endl;
273     return;
274   }
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;
279     InitEvent();
280 // loop over all registered digitizers and let them do the work
281     ExecuteTasks(option);
282     CleanTasks();
283     FinishEvent();
284   }
285   FinishGlobal();
286 }
287
288 ////////////////////////////////////////////////////////////////////////
289 Bool_t AliRunDigitizer::ConnectInputTrees()
290 {
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
294
295   TTree *tree;
296   char treeName[50];
297   Int_t serialNr;
298   Int_t eventNr[kMaxStreamsToMerge], delta[kMaxStreamsToMerge];
299   fCombi->Combination(eventNr, delta);
300   for (Int_t i=0;i<fNinputs;i++) {
301     if (delta[i] == 1) {
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];
309         fArrayTreeS[i] = 0;
310       }
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];
316         fArrayTreeH[i] = 0;
317       }
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;
324       }
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;
331       }
332       fArrayTreeTRDS[i] = tree;
333     } else if (delta[i] != 0) {
334       Error("ConnectInputTrees","Only delta 0 or 1 is implemented");
335       return kFALSE;
336     }
337   }
338   return kTRUE;
339 }
340
341 ////////////////////////////////////////////////////////////////////////
342 Bool_t AliRunDigitizer::InitGlobal()
343 {
344 // called once before Digitize() is called, initialize digitizers and output
345
346   TList* subTasks = this->GetListOfTasks();
347   if (subTasks) {
348     subTasks->ForEach(AliDigitizer,Init)();
349   }  
350   return kTRUE;
351 }
352
353 ////////////////////////////////////////////////////////////////////////
354
355 void AliRunDigitizer::SetOutputFile(TString fn)
356 // the output will be to separate file, not to the signal file
357 {
358   fOutputFileName = fn;
359   (static_cast<AliStream*>(fInputStreams->At(0)))->ChangeMode("READ");
360   InitOutputGlobal();
361 }
362
363 ////////////////////////////////////////////////////////////////////////
364 Bool_t AliRunDigitizer::InitOutputGlobal()
365 {
366 // Creates the output file, called by InitEvent()
367
368   TString fn;
369   fn = fOutputDirName + '/' + fOutputFileName;
370   fOutput = new TFile(fn,"update");
371   if (GetDebug()>2) {
372     cerr<<"AliRunDigitizer::InitOutputGlobal(): file "<<fn.Data()<<" was opened"<<endl;
373   }
374   if (fOutput) return kTRUE;
375   Error("InitOutputGlobal","Could not create output file.");
376   return kFALSE;
377 }
378
379
380 ////////////////////////////////////////////////////////////////////////
381 void AliRunDigitizer::InitEvent()
382 {
383 // Creates TreeDxx in the output file, called from Digitize() once for 
384 //  each event. xx = fEvent
385
386   if (GetDebug()>2) 
387     cerr<<"AliRunDigitizer::InitEvent: fEvent = "<<fEvent<<endl;
388
389 // if fOutputFileName was not given, write output to signal file
390   if (fOutputFileName == "") {
391     fOutput = (static_cast<AliStream*>(fInputStreams->At(0)))->CurrentFile();
392   }
393   fOutput->cd();
394   char treeName[30];
395   sprintf(treeName,"TreeD%d",fEvent);
396   fTreeD = static_cast<TTree*>(fOutput->Get(treeName));
397   if (!fTreeD) {
398     fTreeD = new TTree(treeName,"Digits");
399     fTreeD->Write(0,TObject::kOverwrite);
400   }
401
402 // tree for ITS fast points
403   sprintf(treeName,"TreeR%d",fEvent);
404   fTreeR = static_cast<TTree*>(fOutput->Get(treeName));
405   if (!fTreeR) {
406     fTreeR = new TTree(treeName,"Reconstruction");
407     fTreeR->Write(0,TObject::kOverwrite);
408   }
409
410 // special tree for TPC
411   sprintf(treeName,"%s%d",fTreeDTPCBaseName,fEvent);
412   fTreeDTPC = static_cast<TTree*>(fOutput->Get(treeName));
413   if (!fTreeDTPC) {
414     fTreeDTPC = new TTree(treeName,"TPC_Digits");
415     fTreeDTPC->Write(0,TObject::kOverwrite);
416   }
417
418 // special tree for TRD
419   sprintf(treeName,"TreeD%d_TRD",fEvent);
420   fTreeDTRD = static_cast<TTree*>(fOutput->Get(treeName));
421   if (!fTreeDTRD) {
422     fTreeDTRD = new TTree(treeName,"TRD_Digits");
423     fTreeDTRD->Write(0,TObject::kOverwrite);
424   }
425
426 }
427
428 ////////////////////////////////////////////////////////////////////////
429 void AliRunDigitizer::FinishEvent()
430 {
431 // called at the end of loop over digitizers
432
433   Int_t i;
434   fOutput->cd();
435   if (fCopyTreesFromInput > -1) {
436     char treeName[20];
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();
442   }
443   fEvent++;
444   fNrOfEventsWritten++;
445   if (fTreeD) {
446     delete fTreeD;
447     fTreeD = 0;
448   }
449   if (fTreeR) {
450     delete fTreeR;
451     fTreeR = 0;
452   }
453   if (fTreeDTPC) {
454     delete fTreeDTPC;
455     fTreeDTPC = 0;
456   }
457   if (fTreeDTRD) {
458     delete fTreeDTRD;
459     fTreeDTRD = 0;
460   }
461 }
462 ////////////////////////////////////////////////////////////////////////
463 void AliRunDigitizer::FinishGlobal()
464 {
465 // called at the end of Exec
466 // save unique objects to the output file
467
468   fOutput->cd();
469   this->Write(0,TObject::kOverwrite);
470   if (fCopyTreesFromInput > -1) {
471     fInputFiles[fCopyTreesFromInput]->Get("TE")->Clone()->Write();
472     gAlice->Write();
473   }
474   fOutput->Close();
475 }
476
477
478 ////////////////////////////////////////////////////////////////////////
479 Int_t  AliRunDigitizer::GetNParticles(Int_t event) const
480 {
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
484
485   Int_t sum = 0;
486   Int_t sumI;
487   for (Int_t i = 0; i < fNinputs; i++) {
488     sumI = GetNParticles(GetInputEventNumber(event,i), i);
489     if (sumI < 0) return -1;
490     sum += sumI;
491   }
492   return sum;
493 }
494
495 ////////////////////////////////////////////////////////////////////////
496 Int_t  AliRunDigitizer::GetNParticles(Int_t event, Int_t input) const
497 {
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
501
502 // Must be revised in the version with AliStream
503
504   return -1;
505
506 /*
507   TFile *file = ConnectInputFile(input);
508   if (!file) {
509     Error("GetNParticles","Cannot open input file");
510     return -1;
511   }
512
513 // find the header and get Nprimaries and Nsecondaries
514   TTree* tE = (TTree *)file->Get("TE") ;
515   if (!tE) {
516     Error("GetNParticles","input file does not contain TE");
517     return -1;
518   }
519   AliHeader* header;
520   header = 0;
521   tE->SetBranchAddress("Header", &header);
522   if (!tE->GetEntry(event)) {
523     Error("GetNParticles","event %d not found",event);
524     return -1;
525   }
526   if (GetDebug()>2) {
527     cerr<<"Nprimary: "<< header->GetNprimary()<<endl;
528     cerr<<"Nsecondary: "<<header->GetNsecondary()<<endl;
529   }
530   return header->GetNprimary() + header->GetNsecondary();
531 */
532 }
533
534 ////////////////////////////////////////////////////////////////////////
535 Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event) const
536 {
537 // return pointer to an int array with input event numbers which were
538 // merged in the output event event
539
540 // simplified for now, implement later
541   Int_t * a = new Int_t[kMaxStreamsToMerge];
542   for (Int_t i = 0; i < fNinputs; i++) {
543     a[i] = event;
544   }
545   return a;
546 }
547 ////////////////////////////////////////////////////////////////////////
548 Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t input) const
549 {
550 // return an event number of an eventInput from input file input
551 // which was merged to create output event event
552
553 // simplified for now, implement later
554   return event;
555 }
556 ////////////////////////////////////////////////////////////////////////
557 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event) const
558 {
559 // return pointer to particle with index i (index with mask)
560
561 // decode the MASK
562   Int_t input = i/fkMASKSTEP;
563   return GetParticle(i,input,GetInputEventNumber(event,input));
564 }
565
566 ////////////////////////////////////////////////////////////////////////
567 TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t input, Int_t event) const
568 {
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
573
574 // Must be revised in the version with AliStream
575
576   return 0;
577 /*
578   TFile *file = ConnectInputFile(input);
579   if (!file) {
580     Error("GetParticle","Cannot open input file");
581     return 0;
582   }
583
584 // find the header and get Nprimaries and Nsecondaries
585   TTree* tE = (TTree *)file->Get("TE") ;
586   if (!tE) {
587     Error("GetParticle","input file does not contain TE");
588     return 0;
589   }
590   AliHeader* header;
591   header = 0;
592   tE->SetBranchAddress("Header", &header);
593   if (!tE->GetEntry(event)) {
594     Error("GetParticle","event %d not found",event);
595     return 0;
596   }
597   
598 // connect TreeK  
599   char treeName[30];
600   sprintf(treeName,"TreeK%d",event);  
601   TTree* tK = static_cast<TTree*>(file->Get(treeName));
602   if (!tK) {
603     Error("GetParticle","input file does not contain TreeK%d",event);
604     return 0;
605   }
606   TParticle *particleBuffer;
607   particleBuffer = 0;
608   tK->SetBranchAddress("Particles", &particleBuffer);
609
610
611 // algorithmic way of getting entry index
612 // (primary particles are filled after secondaries)
613   Int_t entry;
614   if (i<header->GetNprimary())
615     entry = i+header->GetNsecondary();
616   else 
617     entry = i-header->GetNprimary();
618   Int_t bytesRead = tK->GetEntry(entry);
619 //  new ((*fParticles)[nentries]) TParticle(*fParticleBuffer);
620   if (bytesRead)
621     return particleBuffer;
622   return  0;
623 */
624 }
625
626 ////////////////////////////////////////////////////////////////////////
627 void AliRunDigitizer::ExecuteTask(Option_t* option)
628 {
629 // overwrite ExecuteTask to do Digitize only
630
631   if (!IsActive()) return;
632   Digitize(option);
633   fHasExecuted = kTRUE;
634   return;
635 }
636 ////////////////////////////////////////////////////////////////////////
637 TString AliRunDigitizer::GetInputFileName(const Int_t input, const Int_t order) const 
638 {
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);
648   return fileName;
649 }
650 ////////////////////////////////////////////////////////////////////////