//*-- 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 <iostream>
#include <iomanip>
#include <limits.h>
#include <unistd.h>
#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<<kBitCategorySize);
		    if (fPar) { fPar->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");
}



Last change: Sat May 22 13:10:58 2010
Last generated: 2010-05-22 13:10

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.