//*-- Author : Manuel Sanchez //*-- Modified : 08/10/2003 by Romain Holzmann //*-- Modified : 24/02/2003 by Ilse Koenig //*-- Modified : 23/05/2002 by Manuel Sanchez //*-- Modified : 01/03/2000 by Manuel Sanchez //*-- Modified : 5/05/98 by Manuel Sanchez //*-- Copyright : GENP (Univ. Santiago de Compostela) //_HADES_CLASS_DESCRIPTION //////////////////////////////////////////////////////////////////////////// // HRootSource // // This data source can read data from a ROOT file generated by // HYDRA, this includes both the reconstruction and simulation software. // // The data source takes care of instantiating the appropriate classes even // if they are non-standard. That is, if you have an input file with // HMdcHitSim instead of HMdcHit; HRootSource will take care of using // HMdcHitSim during the analysis. // //////////////////////////////////////////////////////////////////////////// #include "hrootsource.h" #include "hades.h" #include "hrecevent.h" #include "heventheader.h" #include "hpartialevent.h" #include "hcategory.h" #include #include #include #include #include "TKey.h" using namespace std; ClassImp(HRootSource) HRootSource::HRootSource(Bool_t fPers, Bool_t fMerg) { // for fPers==kFALSE, input cats are suppressed in output // for fMerg==kTRUE, partial events in input tree are merged into current // event, if it exists already at init(). fInput = 0; fEventInFile = 0; fCursor = 0; fCurrentRunId = INT_MIN; fCurrentRefId = -1; fGlobalRefId = -1; fDirectory = "./"; fPersistency = fPers; fMerge = fMerg; fEventList = 0; fLastRunId = -1; overwriteVersion = kFALSE; replaceVersion = 0; } HRootSource::~HRootSource(void) { //Class destructor, it clears the data source. Clear(); } Text_t const *HRootSource::getCurrentFileName(void) { if(fInput){ TFile* file = fInput->GetCurrentFile(); if(file){ return file->GetName(); } else { return ""; } } return ""; } Bool_t HRootSource::init(void) { // Initializes the data source connecting the parts of the input tree in // the input ROOT file to the event structure used for the analysis. If // no event structure has been set by the user, HRootSource::init() will // set one read from the input file. If it exists, it will be used as such // (fMerge==kFALSE) or merged with the one in the input file (fMerge==kTRUE). Bool_t r = kTRUE; if (fEventInFile != 0) { //If there is an active event structure HRecEvent* fCurrentEvent = (HRecEvent*)gHades->getCurrentEvent(); if (fCurrentEvent != 0) { if (fMerge) { // merge the 2 event structures Warning("init","Merging with predefined event structure"); ((HRecEvent*)fEventInFile)->merge(fCurrentEvent); } else { Warning("init","Using predefined event structure"); } } else { gHades->setEvent(fEventInFile); } if ( fInput!=0) { Char_t sl=*(strchr(fInput->GetTitle(),'.')+1); switch (sl) { case '0' : fSplitLevel = 0; break; case '1' : fSplitLevel = 1; break; case '2' : fSplitLevel = 2; break; default : fSplitLevel = 0; } fInput->SetBranchStatus("*",kFALSE); gHades->activateTree(fInput); if (fEventList) { fEntries = fEventList->GetN(); } else { fEntries=fInput->GetEntries(); } if (fCursor >= fEntries) { Error("init","Entry not existing %i",fCursor); return kFALSE; //Entry not existing } if (fEventList) { fInput->GetEvent(fEventList->GetEntry(fCursor)); } else { fInput->GetEvent(fCursor); } fCurrentRunId = gHades->getCurrentEvent()->getHeader()->getEventRunNumber(); fLastRunId = fCurrentRunId; if(overwriteVersion) { // fix not set version in simulation gHades->getCurrentEvent()->getHeader()->setVersion(replaceVersion); } if (fRefIds.find(fCurrentRunId) != fRefIds.end()) { fCurrentRefId = fRefIds[fCurrentRunId]; } else { fCurrentRefId = fGlobalRefId; } if (fPersistency == kFALSE) { // set all input categories non-persistent for(Int_t i = 0; i < 16; i ++) { // loop over partial events HPartialEvent* fPar = ((HRecEvent*)fEventInFile)->getPartialEvent(i<setPersistency(kFALSE); } } } setCursorToPreviousEvent(); r = kTRUE; } else { Warning("init","Not input"); Clear(); r = kFALSE; } } else { r = kFALSE; } return r; } EDsState HRootSource::getNextEvent(Bool_t doUnpack) { //Retrieves next event in the input file. Int_t bread = 0; if (fInput) { if (fSplitLevel < 2) (*fEventAddr)->clearAll(fSplitLevel); if (fCursor < fEntries) { if (fEventList) { bread = fInput->GetEvent(fEventList->GetEntry(fCursor)); } else { bread = fInput->GetEvent(fCursor); } if (bread == 0) { return kDsEndData; } fCursor ++; fCurrentRunId = gHades->getCurrentEvent()->getHeader()->getEventRunNumber(); if(overwriteVersion) { // fix not set version in simulation gHades->getCurrentEvent()->getHeader()->setVersion(replaceVersion); } if (fCurrentRunId != fLastRunId) { if (fRefIds.find(fCurrentRunId) != fRefIds.end()) { fCurrentRefId = fRefIds[fCurrentRunId]; } else { fCurrentRefId = fGlobalRefId; } fLastRunId = fCurrentRunId; return kDsEndFile; } } else { return kDsEndData; } } else { return kDsError; } return kDsOk; } void HRootSource::setCursorToPreviousEvent() { // Rewinds the file cursour read by 1 event // The cursor does not point to next event as usual // but to the current event. This feature is needed // for the event embedding if a event is skipped // by the first data source or any task. The same // event (from second data source) will be read for // the next event from first data source. if(fCursor > 0) { fCursor --; } } Bool_t HRootSource::getEvent(Int_t eventN) { //Retrieves event in position eventN in the input file, copying the //information to the event structure. if (fInput) { if (fEventList) { if (fInput->GetEvent(fEventList->GetEntry(eventN)) > 0) { return kTRUE; } else { if (fInput->GetEvent(eventN)>0){ return kTRUE; } else { return kFALSE; } } } } return kFALSE; } void HRootSource::Clear(void) { //Closes the input file. if (fInput) { delete fInput; fInput = 0; } } void HRootSource::setDirectory(const Text_t dirName[]) { //Sets the directory where to read files from. fDirectory = dirName; if (fDirectory[fDirectory.Length()-1] != '/') { fDirectory += "/"; } } Bool_t HRootSource::fileExists(const TString &name) { //Checks for the existence on one file. return (access(name.Data(),F_OK) == 0) ? kTRUE : kFALSE; } TString HRootSource::getFileName(const Text_t *file) { TString fname; if (file[0] == '/') { //Absolute or relative path?? fname = file; } else { fname = fDirectory; fname += file; } return fname; } Bool_t HRootSource::addFile(const Text_t *file) { Text_t treeName[] = "T"; TString fname = getFileName(file); if (fileExists(fname)) { if (!fInput) { //If chain doesn't already exist TFile *fileTemp; TKey *key = 0; TString title; fileTemp = getFile(fname.Data()); //Obtain tree title //new TFile(fname.Data()); key = fileTemp->GetKey(treeName); //No need to delete this pointer fEventInFile = (HEvent *)fileTemp->Get("Event"); fCurrentRunId = fEventInFile->getHeader()->getEventRunNumber(); if (fRefIds.find(fCurrentRunId) != fRefIds.end()) { fCurrentRefId = fRefIds[fCurrentRunId]; } else { fCurrentRefId = fGlobalRefId; } title = key->GetTitle(); fileTemp->Close(); delete fileTemp; fInput = new TChain(treeName,title.Data()); } fInput->Add(fname.Data()); } else { Warning("addFile","File %s not found",fname.Data()); return kFALSE; } return kTRUE; } Bool_t HRootSource::setInput(const Text_t *fileName,const Text_t *treeName) { //Sets the input file and tree. Opening the corresponding files, it also //loads in memory the input event description so the disableCategory() //method can be used. if (strcmp(treeName,"T") != 0) { return kFALSE; } else { return addFile(fileName); } } Bool_t HRootSource::disableCategory(Cat_t aCat) { //Disables the category aCat so it is not read even if it is stored in //the input file. This method shouldn't be called after init() //Returns kTRUE if the aCat was stored in the input file and has succesfully //been disabled, otherwise the return value is kFALSE. if (!fEventInFile) { return kFALSE; } else { return fEventInFile->removeCategory(aCat); } } Bool_t HRootSource::disablePartialEvent(Cat_t aCat) { if (!fEventInFile) { return kFALSE; } else { return ((HRecEvent*)fEventInFile)->removePartialEvent(aCat); } } Int_t HRootSource::getSplitLevel(void) { //Returns the split level of the input tree. return fSplitLevel; } void HRootSource::deactivateBranch(const Text_t *branchName) { //Deactivates a branch so it is not read. //This method is deprecated, use disableCategory() instead. if (fInput) { fInput->SetBranchStatus(branchName,kFALSE); } } TTree *HRootSource::getTree(void) { //Returns the input tree. return fInput; } EDsState HRootSource::skipEvents(Int_t nEv) { enum EDsState state = kDsOk; if (nEv > 0) { Int_t newCursor = fCursor + nEv; if (newCursor < fEntries) { fCursor = newCursor - 1; state = getNextEvent(); } else { state = kDsEndData; } } return state; } TFile * HRootSource::getFile(TString name) { return TFile::Open(name.Data(),"READ"); }