]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
Manager class for merging/digitization
authorjchudoba <jchudoba@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 27 Jul 2001 12:59:11 +0000 (12:59 +0000)
committerjchudoba <jchudoba@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 27 Jul 2001 12:59:11 +0000 (12:59 +0000)
STEER/AliRunDigitizer.cxx [new file with mode: 0644]
STEER/AliRunDigitizer.h [new file with mode: 0644]

diff --git a/STEER/AliRunDigitizer.cxx b/STEER/AliRunDigitizer.cxx
new file mode 100644 (file)
index 0000000..6ae91ad
--- /dev/null
@@ -0,0 +1,637 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/*
+$Log$
+*/
+
+////////////////////////////////////////////////////////////////////////
+//
+// AliRunDigitizer.cxx
+//
+// Manager object for merging/digitization
+//
+// Instance of this class manages the digitization and/or merging of
+// Sdigits into Digits. 
+//
+// Only one instance of this class is created in the macro:
+//   AliRunDigitizer * manager = new AliRunDigitizer();
+// Then instances of specific detector digitizers are created:
+//   AliMUONDigitizer *dMUON  = new AliMUONDigitizer(manager)
+// and the manager is configured (you have to specify input files 
+// and an output file). The manager generates a combination of input 
+// events according to an option set by SetCombinationType. Then it
+// connects appropriate trees from the input files, creates TreeD 
+// in the output and runs once per event Digitize method of all existing 
+// AliDetDigitizers (without any option). AliDetDigitizers ask manager
+// for a TTree with input (manager->GetNextTreeH(TTree *) 
+// or manager->GetNextTreeS(TTree *),
+// merge all inputs, digitize it, and save it in the TreeD 
+// obtained by manager->GetTreeD(). Output events are stored with 
+// numbers from 0, this default can be changed by 
+// manager->SetFirstOutputEventNr(Int_t) method. The particle numbers
+// in the output are shifted by MASK, which is taken from manager.
+//
+// Single input file is permitted. Maximum MAXFILESTOMERGE can be merged.
+// Input from the memory (on-the-fly merging) is not yet 
+// supported, as well as access to the input data by invoking methods
+// on the output data.
+//
+// Access to the geometrical data is via gAlice for now (supposing the 
+// same geometry in all input files), gAlice is taken from the defined 
+// input file.
+//
+// Example with MUON digitizer:
+//
+//   AliRunDigitizer * manager = new AliRunDigitizer();
+//   manager->SetInput("1track_10events_phi45_60.root");
+//   manager->SetInput("1track_10events_phi120_135.root");
+//   manager->SetOutputDir("/home/z2/jchudoba/batch/jobtmp");
+//   manager->SetOutputFile("digits.root");
+//   AliMUONDigitizer *dMUON  = new AliMUONDigitizer(manager);
+//   manager->SetNrOfEventsToWrite(3);
+//   manager->SetCopyTreesFromInput(1);
+//   manager->Digitize();
+//
+//////////////////////////////////////////////////////////////////////// 
+
+// system includes
+
+#include <iostream.h>
+
+// ROOT includes
+
+#include "TFile.h"
+#include "TTree.h"
+
+// AliROOT includes
+
+#include "AliRunDigitizer.h"
+#include "AliDigitizer.h"
+#include "AliRun.h"
+#include "AliHeader.h"
+#include "TParticle.h"
+
+ClassImp(AliRunDigitizer)
+
+////////////////////////////////////////////////////////////////////////
+
+  AliRunDigitizer::AliRunDigitizer() : TNamed("AliRunDigitizer","")
+{
+// default ctor
+
+  for (Int_t i=0;i<MAXDETECTORS;i++) fDigitizers[i]=0;
+  fNDigitizers = 0;
+  fNinputs = 0;
+  fOutputFileName = "digits.root";
+  fOutputDirName = "/tmp/";
+  fCombination.Set(MAXFILESTOMERGE);
+  for (Int_t i=0;i<MAXFILESTOMERGE;i++) {
+    fArrayTreeS[i]=fArrayTreeH[i]=fArrayTreeTPCS[i]=NULL;
+    fCombination[i]=-1;
+  }
+  fkMASKSTEP = 10000000;
+  fkMASK[0] = 0;
+  for (Int_t i=0;i<MAXFILESTOMERGE;i++) {
+    fkMASK[i] = fkMASK[i-1] + fkMASKSTEP;
+  }
+  fInputFileNames = new TClonesArray("TObjString",1);
+  fInputFiles = new TClonesArray("TFile",1);
+  fMinNEvents = 99999999;
+  fCombinationType=1;
+  fCombinationFileName = "combination.txt";
+  fOutput = 0;
+  fEvent = 0;
+  fNrOfEventsToWrite = 0;
+  fNrOfEventsWritten = 0;
+  fCopyTreesFromInput = -1;
+  fDebug = 3;
+  if (GetDebug()>2) 
+    cerr<<"AliRunDigitizer::AliRunDigitizer() called"<<endl;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+AliRunDigitizer::~AliRunDigitizer() {
+// dtor
+
+  if (fInputFiles) delete fInputFiles;
+  if (fInputFileNames) delete fInputFileNames;
+}
+
+////////////////////////////////////////////////////////////////////////
+void AliRunDigitizer::AddDigitizer(AliDigitizer *digitizer)
+{
+// add digitizer to the list of active digitizers
+
+  if (fNDigitizers >= MAXDETECTORS) {
+    cerr<<"Too many detectors to digitize. Increase value of MAXDETECTORS"
+       <<" constant in AliRunDigitizer.h and recompile or decrease the"
+       <<" the number of detectors"<<endl;
+  } else {
+    fDigitizers[fNDigitizers++] = digitizer;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+Bool_t AliRunDigitizer::SetInput(char *inputFile)
+{
+// receives the name of the input file. Opens it and stores pointer 
+// to it, returns kFALSE if fails
+// if inputFile = MEMORY, uses pointers from gAlice - not yet implemented
+
+// input cannot be output - open READ only
+  TFile *file = new((*fInputFiles)[fNinputs]) TFile(inputFile,"READ"); 
+
+  if (GetDebug()>2) cerr<<"AliRunDigitizer::SetInput: file = "<<file<<endl;
+  if (!file->IsOpen()) {
+    cerr<<"ERROR: AliRunDigitizer::SetInput: cannot open file "
+       <<inputFile<<endl;
+    return kFALSE;
+  }
+
+// find Header and get nr of events there
+  TTree * te = (TTree *) file->Get("TE") ;
+  if (!te) {
+    cerr<<"ERROR: AliRunDigitizer::SetInput:  input file does "
+       <<"not contain TE"<<endl;
+    return kFALSE;
+  }
+  Int_t nEntries = (Int_t) te->GetEntries();
+
+  if (GetDebug()>2) cerr<<"AliRunDigitizer::SetInput: nEntries = "
+                       <<nEntries<<endl;
+  if (nEntries < 1) {
+    cerr<<"ERROR: AliRunDigitizer::SetInput:  input file does "
+       <<"not contain any event"<<endl;
+    return kFALSE;
+  }
+
+  if (nEntries < fMinNEvents) fNrOfEventsToWrite = fMinNEvents = nEntries;
+
+// find gAlice object if it is a first input file
+//  this is only temporary solution, we need gAlice to access detector
+//  geometry parameters. Unfortunately I have to include AliRun header file.
+  if (fNinputs == 0) {
+    gAlice = (AliRun*)file->Get("gAlice");
+    if (GetDebug() > 2) cerr<<"gAlice taken from the first input: "
+                           <<gAlice<<endl;
+    if (!gAlice) {
+      cerr<<"ERROR: AliRunDigitizer::SetInput:  first input file "
+         <<"does not contain gAlice object"<<endl;
+      return kFALSE;
+    }
+  }
+    
+// store this file name if it is OK
+  new((*fInputFileNames)[fNinputs])  TObjString(inputFile);
+  fNinputs++;
+  if (GetDebug() > 2) cerr<<"fNinputs = "<<fNinputs<<endl;
+  return kTRUE;
+}
+
+////////////////////////////////////////////////////////////////////////
+Bool_t AliRunDigitizer::MakeCombination()
+{
+// make a new combination of events from different files
+
+  Int_t type = fCombinationType;
+  if (fNrOfEventsWritten >= fNrOfEventsToWrite) return kFALSE;
+
+  switch (type) {
+       
+  case 1:
+// type = 1:  1-1-1 - take the same event number from each file
+    if (fCombination[0]<fMinNEvents-1) {       
+      for (Int_t i=0;i<fNinputs;i++) fCombination[i]++;
+      return kTRUE;
+    }
+    if (GetDebug()>2)
+      cerr<<"AliRunDigitizer::MakeCombination: Warning: "
+         <<"maximum number of Events in an input file "
+         <<"was reached."<<endl;
+    break;
+
+  case 2:
+// type = 2: read from the file combinations.ascii
+//  not yet implemented 100% correctly - requires 4 entries in the row
+    static FILE *fp ;
+    static Int_t linesRead;
+    if (!fp) {
+      fp = fopen(fCombinationFileName.Data(),"r");
+      linesRead = 0;
+    }
+    if (!fp) {
+      cerr<<"AliRunDigitizer::MakeCombination ERROR: "
+         <<"Cannot open input file with combinations."<<endl;
+      return kFALSE;
+    }
+    Int_t var[4], nInputs;
+    char line[80];
+// since I do not close or rewind the file, the position should be correct
+    if (fgets(line,80,fp)) {
+      nInputs = sscanf(&line[0],"%d%d%d%d",&var[0],&var[1],&var[2],&var[3]);
+      if (nInputs != fNinputs) {
+       cerr<<"AliRunDigitizer::MakeCombination ERROR: "
+           <<"Nr. of input files is different from nr "
+           <<"integers defining the combination"<<endl;
+       return kFALSE;
+      }
+      while(nInputs--) {
+       fCombination[nInputs] = var[nInputs];
+      }
+      return kTRUE;
+    } else {
+      cerr<<"AliRunDigitizer::MakeCombination ERROR: "
+         <<"no more input in the file with combinations"<<endl;
+      return kFALSE;
+    }
+
+  default:
+    cerr<<"AliRunDigitizer::MakeCombination: ERROR: "
+       <<"wrong type of required combination type: "<<type<<endl;
+  }
+  return kFALSE;
+}
+
+////////////////////////////////////////////////////////////////////////
+void AliRunDigitizer::PrintCombination()
+{
+// debug method to print current combination
+
+  cerr<<"AliRunDigitizer::PrintCombination: Current events combination:"<<endl;
+  for (Int_t i=0;i<fNinputs;i++) {
+    cerr<<"File: "<<((TObjString *)fInputFileNames->At(i))->GetString()<<"\tEvent: "<<fCombination[i]<<endl;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+void AliRunDigitizer::Digitize()
+{
+// get a new combination of inputs, connect input trees and loop 
+// over all digitizers
+
+  if (!InitGlobal()) {
+    cerr<<"False from InitGlobal"<<endl;
+    return;
+  }
+// take gAlice from the first input file. It is needed to access
+//  geometry data
+  while (MakeCombination()) {
+    if (GetDebug()>2) PrintCombination();
+    ConnectInputTrees();
+    InitPerEvent();
+// loop over all registered digitizers and let them do the work
+    for (Int_t i=0;i<fNDigitizers; i++) {
+      fDigitizers[i]->Digitize();
+    }
+    FinishPerEvent();
+  }
+  FinishGlobal();
+}
+
+////////////////////////////////////////////////////////////////////////
+void AliRunDigitizer::ConnectInputTrees()
+{
+// fill arrays fArrayTreeS, fArrayTreeH and fArrayTreeTPCS with 
+// pointers to the correct events according fCombination values
+// null pointers can be in the output, AliDigitizer has to check it
+
+  TFile *file;
+  TTree *tree;
+  char treeName[20];
+  for (Int_t i=0;i<fNinputs;i++) {
+    file = (TFile*)(*fInputFiles)[i];
+    sprintf(treeName,"TreeS%d",fCombination[i]);
+    tree = (TTree *) file->Get(treeName);
+    fArrayTreeS[i] = tree;
+    sprintf(treeName,"TreeH%d",fCombination[i]);
+    tree = (TTree *) file->Get(treeName);
+    fArrayTreeH[i] = tree;
+    sprintf(treeName,"TreeD_75x40_100x60_%d",fCombination[i]);
+    tree = (TTree *) file->Get(treeName);
+    fArrayTreeTPCS[i] = tree;
+   }
+}
+
+////////////////////////////////////////////////////////////////////////
+Bool_t AliRunDigitizer::InitGlobal()
+{
+// called once before Digitize() is called, initialize digitizers and output
+
+  if (!InitOutputGlobal()) return kFALSE;
+  for (Int_t i=0;i<fNDigitizers; i++) {
+    if (!fDigitizers[i]->Init()) return kFALSE;
+  }
+  return kTRUE;
+}
+
+////////////////////////////////////////////////////////////////////////
+Bool_t AliRunDigitizer::InitOutputGlobal()
+{
+// Creates the output file, called once by InitGlobal()
+
+  TString fn;
+  fn = fOutputDirName + '/' + fOutputFileName;
+  fOutput = new TFile(fn,"recreate");
+  if (GetDebug()>2) {
+    cerr<<"file "<<fn.Data()<<" was opened"<<endl;
+    cerr<<"fOutput = "<<fOutput<<endl;
+  }
+  if (fOutput) return kTRUE;
+  Error("InitOutputGlobal","Could not create output file.");
+  return kFALSE;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+void AliRunDigitizer::InitPerEvent()
+{
+// Creates TreeDxx in the output file, called from Digitize() once for 
+//  each event. xx = fEvent
+
+  if (GetDebug()>2) 
+    cerr<<"AliRunDigitizer::InitPerEvent: fEvent = "<<fEvent<<endl;
+  fOutput->cd();
+  char hname[30];
+  sprintf(hname,"TreeD%d",fEvent);
+  fTreeD = new TTree(hname,"Digits");
+//  fTreeD->Write();   // Do I have to write it here???
+}
+
+
+////////////////////////////////////////////////////////////////////////
+TTree* AliRunDigitizer::GetNextTreeH(TTree *current) const
+{
+// returns next one after the current one
+// returns the first if the current is NULL
+// returns NULL if the current is the last one
+
+  if (fNinputs <= 0) return 0;
+  if (current == 0) return fArrayTreeH[0];
+  for (Int_t i=0; i<fNinputs-1; i++) {
+    if (current == fArrayTreeH[i]) return fArrayTreeH[i+1];
+  }
+  return 0;
+}
+////////////////////////////////////////////////////////////////////////
+TTree* AliRunDigitizer::GetNextTreeS(TTree *current) const
+{
+// returns next one after the current one
+// returns the first if the current is NULL
+// returns NULL if the current is the last one
+
+  if (fNinputs <= 0) return 0;
+  if (current == 0) return fArrayTreeS[0];
+  for (Int_t i=0; i<fNinputs-1; i++) {
+    if (current == fArrayTreeS[i]) return fArrayTreeS[i+1];
+  }
+  return 0;
+}
+////////////////////////////////////////////////////////////////////////
+TTree* AliRunDigitizer::GetNextTreeTPCS(TTree *current) const
+{
+// returns next one after the current one
+// returns the first if the current is NULL
+// returns NULL if the current is the last one
+
+  if (fNinputs <= 0) return 0;
+  if (current == 0) return fArrayTreeTPCS[0];
+  for (Int_t i=0; i<fNinputs-1; i++) {
+    if (current == fArrayTreeTPCS[i]) return fArrayTreeTPCS[i+1];
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+Int_t AliRunDigitizer::GetNextMask(Int_t current) const
+{
+// returns next one after the current one
+// returns the first if the current is negative
+// returns negative if the current is the last one
+
+  if (fNinputs <= 0) return -1;
+  if (current < 0) return fkMASK[0]; 
+  for (Int_t i=0; i<fNinputs-1; i++) {
+    if (current == fkMASK[i]) return fkMASK[i+1];
+  }
+  return -1;
+}
+////////////////////////////////////////////////////////////////////////
+void AliRunDigitizer::FinishPerEvent()
+{
+// called at the end of loop over digitizers
+
+  fOutput->cd();
+  if (fCopyTreesFromInput > -1) {
+    char treeName[20];
+    Int_t i = fCopyTreesFromInput; 
+    sprintf(treeName,"TreeK%d",fCombination[i]);
+    ((TFile*)fInputFiles->At(i))->Get(treeName)->Clone()->Write();
+    sprintf(treeName,"TreeH%d",fCombination[i]);
+    ((TFile*)fInputFiles->At(i))->Get(treeName)->Clone()->Write();
+  }
+  fEvent++;
+  fNrOfEventsWritten++;
+  if (fTreeD) {
+    delete fTreeD;
+    fTreeD = 0;
+  }
+}
+////////////////////////////////////////////////////////////////////////
+void AliRunDigitizer::FinishGlobal()
+{
+// called at the end of Exec
+// save unique objects to the output file
+
+  fOutput->cd();
+  this->Write();
+  if (fCopyTreesFromInput > -1) {
+    ((TFile*)fInputFiles->At(fCopyTreesFromInput))->Get("TE")
+      ->Clone()->Write();
+    gAlice->Write();
+  }
+  fOutput->Close();
+}
+
+
+////////////////////////////////////////////////////////////////////////
+Int_t  AliRunDigitizer::GetNParticles(Int_t event)
+{
+// return number of particles in all input files for a given
+// event (as numbered in the output file)
+// return -1 if some file cannot be accessed
+
+  Int_t sum = 0;
+  Int_t sumI;
+  for (Int_t i = 0; i < fNinputs; i++) {
+    sumI = GetNParticles(GetInputEventNumber(event,i), i);
+    if (sumI < 0) return -1;
+    sum += sumI;
+  }
+  return sum;
+}
+
+////////////////////////////////////////////////////////////////////////
+Int_t  AliRunDigitizer::GetNParticles(Int_t event, Int_t input)
+{
+// return number of particles in input file input for a given
+// event (as numbered in this input file)
+// return -1 if some error
+
+  TFile *file = ConnectInputFile(input);
+  if (!file) {
+    Error("GetNParticles","Cannot open input file");
+    return -1;
+  }
+
+// find the header and get Nprimaries and Nsecondaries
+  TTree* tE = (TTree *)file->Get("TE") ;
+  if (!tE) {
+    Error("GetNParticles","input file does not contain TE");
+    return -1;
+  }
+  AliHeader* header;
+  header = 0;
+  tE->SetBranchAddress("Header", &header);
+  if (!tE->GetEntry(event)) {
+    Error("GetNParticles","event %d not found",event);
+    return -1;
+  }
+  if (GetDebug()>2) {
+    cerr<<"Nprimary: "<< header->GetNprimary()<<endl;
+    cerr<<"Nsecondary: "<<header->GetNsecondary()<<endl;
+  }
+  return header->GetNprimary() + header->GetNsecondary();
+}
+
+////////////////////////////////////////////////////////////////////////
+Int_t* AliRunDigitizer::GetInputEventNumbers(Int_t event)
+{
+// return pointer to an int array with input event numbers which were
+// merged in the output event event
+
+// simplified for now, implement later
+  Int_t a[MAXFILESTOMERGE];
+  for (Int_t i = 0; i < fNinputs; i++) {
+    a[i] = event;
+  }
+  return a;
+}
+////////////////////////////////////////////////////////////////////////
+Int_t AliRunDigitizer::GetInputEventNumber(Int_t event, Int_t input)
+{
+// return an event number of an eventInput from input file input
+// which was merged to create output event event
+
+// simplified for now, implement later
+  return event;
+}
+////////////////////////////////////////////////////////////////////////
+TFile* AliRunDigitizer::ConnectInputFile(Int_t input)
+{
+// open input file with index input
+// 1st file has index 0
+// return 0x0 if fails
+
+// check if file with index input is already open
+  TFile *file = 0;
+  if (fInputFiles->GetEntriesFast() > input)
+    file = static_cast<TFile *>(fInputFiles->At(input));
+
+  if (!file) {
+    // find the file name and open it
+    TObjString *fn = static_cast<TObjString *>(fInputFileNames->At(input));
+    file = new((*fInputFiles)[input]) TFile((fn->GetString()).Data(),"READ");
+    if (!file) {
+      Error("ConnectInputFile","Cannot open input file");
+      return 0;
+    }
+    if (!file->IsOpen()) {
+      Error("ConnectInputFile","Cannot open input file");
+      return 0;
+    }
+  }
+  return file;
+}
+
+////////////////////////////////////////////////////////////////////////
+TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t event)
+{
+// return pointer to particle with index i (index with mask)
+
+// decode the MASK
+  Int_t input = i/fkMASKSTEP;
+  return GetParticle(i,input,GetInputEventNumber(event,input));
+}
+
+////////////////////////////////////////////////////////////////////////
+TParticle* AliRunDigitizer::GetParticle(Int_t i, Int_t input, Int_t event)
+{
+// return pointer to particle with index i in the input file input
+// (index without mask)
+// event is the event number in the file input
+// return 0 i fit does not exist
+
+  TFile *file = ConnectInputFile(input);
+  if (!file) {
+    Error("GetParticle","Cannot open input file");
+    return 0;
+  }
+
+// find the header and get Nprimaries and Nsecondaries
+  TTree* tE = (TTree *)file->Get("TE") ;
+  if (!tE) {
+    Error("GetParticle","input file does not contain TE");
+    return 0;
+  }
+  AliHeader* header;
+  header = 0;
+  tE->SetBranchAddress("Header", &header);
+  if (!tE->GetEntry(event)) {
+    Error("GetParticle","event %d not found",event);
+    return 0;
+  }
+  
+// connect TreeK  
+  char treeName[30];
+  sprintf(treeName,"TreeK%d",event);  
+  TTree* tK = static_cast<TTree*>(file->Get(treeName));
+  if (!tK) {
+    Error("GetParticle","input file does not contain TreeK%d",event);
+    return 0;
+  }
+  TParticle *particleBuffer;
+  particleBuffer = 0;
+  tK->SetBranchAddress("Particles", &particleBuffer);
+
+
+// algorithmic way of getting entry index
+// (primary particles are filled after secondaries)
+  Int_t entry;
+  if (i<header->GetNprimary())
+    entry = i+header->GetNsecondary();
+  else 
+    entry = i-header->GetNprimary();
+//  tK->GetEntry(0);          // do I need this???
+  Int_t bytesRead = tK->GetEntry(entry);
+//  new ((*fParticles)[nentries]) TParticle(*fParticleBuffer);
+  if (bytesRead)
+    return particleBuffer;
+  return  0;
+}
+////////////////////////////////////////////////////////////////////////
+
diff --git a/STEER/AliRunDigitizer.h b/STEER/AliRunDigitizer.h
new file mode 100644 (file)
index 0000000..3cf97b2
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef ALIRUNDIGITIZER_H
+#define ALIRUNDIGITIZER_H
+/* Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id$ */
+
+////////////////////////////////////////////////////////////////////////
+//
+//  Manager Class for Merging/Digitization   
+//                  
+//  Author: Jiri Chudoba (CERN)
+//
+////////////////////////////////////////////////////////////////////////
+
+// --- ROOT system ---
+#include "TNamed.h"
+#include "TObjString.h"
+#include "TArrayI.h"
+#include "TClonesArray.h"
+#include "TTree.h"
+#include "TParticle.h"
+
+#define MAXDETECTORS 20
+#define MAXFILESTOMERGE  4
+
+// --- AliRoot header files ---
+
+class AliDigitizer;
+
+class AliRunDigitizer: public TNamed {
+
+public:
+  AliRunDigitizer();
+  virtual ~AliRunDigitizer();
+  void      AddDigitizer(AliDigitizer *digitizer);
+  void      SetOutputFile(TString fn) {fOutputFileName = fn;}
+  TString   GetOutputFile() {return fOutputFileName;}
+  void      SetOutputDir(TString dn) {fOutputDirName = dn;}
+  TString   GetOutputDir() {return fOutputDirName;}
+  void      SetFirstOutputEventNr(Int_t i) {fEvent = i;}
+  void      SetNrOfEventsToWrite(Int_t i) {fNrOfEventsToWrite = i;}
+  void      SetCopyTreesFromInput(Int_t i) {fCopyTreesFromInput = i;}
+  Int_t     GetCopyTreesFromInput() {return fCopyTreesFromInput;}
+  Int_t     GetOutputEventNr() {return fEvent;}
+  Bool_t    SetInput(char* inputFileString);
+  void      SetCombinationFileName(TString fn) {fCombinationFileName = fn;} 
+  TString   GetCombinationFileName() {return fCombinationFileName;}
+  void      SetCombinationType(Int_t i) {fCombinationType = i;}
+  Int_t     GetCombinationType() const {return fCombinationType;}
+  void      PrintCombination();   // debug method
+  Int_t     GetNinputs() const {return fNinputs;}
+  Int_t     GetMask(Int_t i) const {return fkMASK[i];}
+  TTree*    GetInputTreeS(Int_t i) const {return fArrayTreeS[i];}
+  TTree*    GetInputTreeH(Int_t i) const {return fArrayTreeH[i];}
+  TTree*    GetInputTreeTPCS(Int_t i) const {return fArrayTreeTPCS[i];}
+  Int_t     GetNextMask(Int_t i) const;
+  TTree*    GetNextTreeH(TTree *) const;
+  TTree*    GetNextTreeS(TTree *) const;
+  TTree*    GetNextTreeTPCS(TTree *) const;
+  TTree*    GetTreeD() const {return fTreeD;}
+  void      Digitize();
+
+// Nr of particles in all input files for a given event
+//     (as numbered in the output file)
+  Int_t GetNParticles(Int_t event);
+
+// Nr of particles in input file input for a given event
+//     (as numbered in this input file)
+  Int_t GetNParticles(Int_t event, Int_t input);
+
+// return pointer to an int array with input event numbers which were
+// merged in the output event event
+  Int_t* GetInputEventNumbers(Int_t event);
+
+// return an event number of an eventInput from input file input
+// which was merged to create output event event
+  Int_t GetInputEventNumber(Int_t event, Int_t input);
+  
+// return pointer to particle with index i (index with mask)
+  TParticle* GetParticle(Int_t i, Int_t event);
+
+// return pointer to particle with index i in the input file input
+// (index without mask)
+  TParticle* GetParticle(Int_t i, Int_t input, Int_t event);
+
+  
+  Int_t     GetDebug() const {return fDebug;}
+  void      SetDebug(Int_t level) {fDebug = level;}
+  
+private:
+  AliDigitizer *    fDigitizers[MAXDETECTORS];  //! pointers to registered
+                                                //  digitizers
+// the constant 20 corresponds to  MAXDETECTORS = 20 - could be done better
+  Int_t             fNDigitizers;         //! nr. of registered digitizers
+  Int_t             fkMASK[MAXFILESTOMERGE];  //! masks for track ids from
+                                              //  different source files
+  Int_t             fkMASKSTEP;           // step to increase MASK for
+                                          // each input file
+  TString           fOutputFileName;      // output file name
+  TString           fOutputDirName;       // output dir name
+  TFile *           fOutput;              //! pointer to the output file
+  Int_t             fEvent;               // output event nr.
+  Int_t             fNrOfEventsToWrite;   // Nr of events to write
+  Int_t             fNrOfEventsWritten;   // Nr of events written
+  Int_t             fCopyTreesFromInput;  // from which input file the trees
+                                          // should be copied, -1 for no copies
+  TTree *           fTreeD;               //! output TreeD
+  Int_t             fNinputs;             // nr of input files
+  TClonesArray *    fInputFileNames;      // input files names
+  TClonesArray *    fInputFiles;          //! pointers to file handles
+  TTree *           fArrayTreeS[MAXFILESTOMERGE];   //! array with p. to TreeS
+  TTree *           fArrayTreeTPCS[MAXFILESTOMERGE];   //! array with p. to TreeD_75x40_100x60_x (TPC Sdigits)
+  TTree *           fArrayTreeH[MAXFILESTOMERGE];   //! array with p. to TreeH
+  Int_t             fMinNEvents;          // min nr. of events found in inputs
+  TArrayI           fCombination;         //! combination of events from
+  Int_t             fCombinationType;     // defines the algorithm how
+                                          // to generated combination
+  TString           fCombinationFileName; // fn with combinations (used
+                                          // with type 2 of comb.)
+  Bool_t            MakeCombination();    // create next combination
+  void              ConnectInputTrees();
+  Bool_t            InitGlobal();
+  Bool_t            InitOutputGlobal();
+  void              InitPerEvent();
+  void              FinishPerEvent();
+  void              FinishGlobal();
+  Int_t             fDebug;                //! specifies debug level, 0 is min
+  
+  TFile* ConnectInputFile(Int_t input);    // open input file with index input
+
+  ClassDef(AliRunDigitizer,1)
+};
+
+#endif // ALIRUNDIGITIZER_H