From 1ba290db3f08dc7754d76c5cfe5040448dadd04e Mon Sep 17 00:00:00 2001 From: Pierre Gueth Date: Thu, 7 Feb 2013 14:37:24 +0100 Subject: [PATCH] copied gatemergemanager from gate-creatis --- tests_dav/GateMergeManager.cc | 750 ++++++++++++++++++++++++++++++++++ tests_dav/GateMergeManager.hh | 91 +++++ 2 files changed, 841 insertions(+) create mode 100644 tests_dav/GateMergeManager.cc create mode 100644 tests_dav/GateMergeManager.hh diff --git a/tests_dav/GateMergeManager.cc b/tests_dav/GateMergeManager.cc new file mode 100644 index 0000000..0de9794 --- /dev/null +++ b/tests_dav/GateMergeManager.cc @@ -0,0 +1,750 @@ +/*---------------------- + GATE version name: gate_v... + + Copyright (C): OpenGATE Collaboration + +This software is distributed under the terms +of the GNU Lesser General Public Licence (LGPL) +See GATE/LICENSE.txt for further details +----------------------*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GateMergeManager.hh" + +using namespace std; + +void GateMergeManager::StartMerging(string splitfileName){ + + // get the files to merge + ReadSplitFile(splitfileName); + //do the merging + if (m_fastMerge==true) FastMergeRoot(); + else MergeRoot(); + + //if we are here the merging has been successful + //we mark the directory as ready for cleanup + //string dir = splitfileName.substr(0,splitfileName.rfind("/")); + //string ready = "touch "+dir+"/ready_for_delete"; + //const int res=system(ready.c_str()); + //if(res) cout<<"Strange?? Can't mark "<0) return; + + stringstream ssnfiles; + char cline[512]; + while(splitfile){ //we allow for rubbish before "Number of files:" + splitfile.getline(cline,512); + if(!strncmp(cline,"Number of files:",16)){ + ssnfiles.str(cline+16); + ssnfiles>>m_Nfiles; // the number of files to merge + break; + } + } + + // now we look for the file names + int iRoot=0; + while(splitfile){ + splitfile.getline(cline,512); + // check for root + // input files + if(!strncmp(cline,"Root filename:",14)){ + m_vRootFileNames.push_back(strtok(cline+15," ")); + m_vRootFileNames[iRoot]+=".root"; + if(m_verboseLevel>2) cout<<"Root input file name: "<2) cout<<"Root output file name: "<Get("latest_event_ID"); + m_lastEvents[i+1]=int(h->GetMean()); + } + + if(!flgLstEvntID) { + cout<<"FastMerge: No latest_event_ID histogram - exit!"< treeNames; + TFile* node = TFile::Open(m_vRootFileNames[0].c_str(),"OLD"); + TIter nextkey(node->GetListOfKeys()); + TKey *key=0; + while ((key = (TKey*)nextkey())) + { + node->cd(); + TObject* obj = (TObject*)key->ReadObj(); + if( obj->IsA()->InheritsFrom("TTree")) + { + //no doubles + bool singleName=true; + for(unsigned int i=0;iGetName())==0) + { + singleName=false; + break; + } + } + if(singleName) treeNames.push_back(obj->GetName()); + } + } + //take care of all trees + for(unsigned int i=0;i1) cout<<"Problem with merging "<0) { + cout<<"Combining: "; + for(int i=0;i "<GetName()< treeNames; + TFile* node = TFile::Open(m_vRootFileNames[0].c_str(),"OLD"); + if(node==NULL){ + cout<<"Not a readable file "<GetListOfKeys()); + TKey *key=0; + while ((key = (TKey*)nextkey())) { + node->cd(); + TObject* obj = (TObject*)key->ReadObj(); + if( obj->IsA()->InheritsFrom("TH1")){ + m_RootTarget->cd(); + TH1 *h1 = (TH1 *)obj->Clone(); + if(strcmp(h1->GetName(),"latest_event_ID")){ + //any other histogram + for(int i=1;iGet( h1->GetName() ); + h1->Add( h2 ); + } + h1->Write(); + } else { + // latest_event_ID histogram + flgLstEvntID=true; + m_lastEvents[1]=int(h1->GetMean()); + TH1* h=NULL; + for(int i=1;iGet("latest_event_ID"); + m_lastEvents[i+1]=int(h->GetMean()); + } + if(h!=NULL) h->Write(); // we keep the highest latest_event_ID to allow for successive merging + else h1->Write(); + } + } + if( obj->IsA()->InheritsFrom("TH2")){ + m_RootTarget->cd(); + TH2 *h1 = (TH2 *)obj->Clone(); + for(int i=1;iGet( h1->GetName() ); + h1->Add( h2 ); + } + h1->Write(); + } + if( obj->IsA()->InheritsFrom("TTree")){ + //no doubles + bool singleName=true; + for(unsigned int i=0;iGetName())==0){ + singleName=false; + break; + } + } + if(singleName) treeNames.push_back(obj->GetName()); + } + } + if(!flgLstEvntID) { + cout<<"Merge: No latest_event_ID histogram - exit!"<1) cout<<"Problem with merging "<1) cout<<"Going to erase the following files:"<1||test){ + cout<<" --> "< "<Add(m_vRootFileNames[i].c_str()); + int nentries=chain->GetEntries(); + if(nentries<=0) { + if(m_verboseLevel>1) cout<GetName()<<" is empty!"<FindBranch("eventID1")!=NULL) { + if( (chain->FindBranch("runID")==NULL) + ||(chain->FindBranch("time1")==NULL) + ||(chain->FindBranch("time2")==NULL) ) { + cout<<"Cannot find one of: runID, time1, time2 in "<GetName()<FindBranch("runID")==NULL)||(chain->FindBranch("eventID")==NULL) + ||(chain->FindBranch("time")==NULL) ) + { + cout<<"Cannot find one of: runID, eventID, time in "<GetName()<ReOpen("UPDATE"); + TTree *oldTree = (TTree*)gDirectory->Get(name.c_str()); + TBranch *branch = oldTree->GetBranch("event"); + branch->SetAddress(&event); + TBranch* newBranch=oldTree->Branch("eventcluster",&event,"event"); + + Int_t nentries=(Int_t)oldTree->GetEntries(); + + if (j==0) offset=0; + else offset+=m_lastEvents[currentfile]; + currentfile++; + + for(int i=0;iGetEvent(i); + if(lastEvent!=event) + { + lastEvent=event; + event+=offset; + newBranch->Fill(); + } + else + { + if((i==nentries-1) && (j==m_Nfiles-1)) + { + event+=offset; + newBranch->Fill(); + } + else if (i!=nentries-1) + { + branch->GetEvent(i); + event+=offset; + newBranch->Fill(); + lastEvent=0; + offset=0; + } + } + } + oldTree->Write(); + } + return true; +} + +/*******************************************************************************************/ +bool GateMergeManager::FastMergeSing(string name) +{ +int eventID = 0; +int runID = 0; +int offset = 0; +int currentfile = 0; +float lastRun =-1; +string clusterName=name+"_cluster"; + +for(int j=0;jReOpen("UPDATE"); + TTree *oldTree = (TTree*)gDirectory->Get(name.c_str()); + TBranch *branch = oldTree->GetBranch("eventID"); + branch->SetAddress(&eventID); + TBranch *branch2 = oldTree->GetBranch("runID"); + branch2->SetAddress(&runID); + TBranch* newBranch=oldTree->Branch("eventIDcluster",&eventID,"eventID/I"); + + Int_t nentries=(Int_t)oldTree->GetEntries(); + + if (j==0) offset=0; + else offset+=m_lastEvents[currentfile]; + currentfile++; + + for(int i=0;iGetEvent(i); + if(lastRun!=runID) + { + lastRun=runID; + offset=0; + } + eventID+=offset; + newBranch->Fill(); + } + oldTree->Write(); + } + return true; +} + +/*******************************************************************************************/ +bool GateMergeManager::FastMergeCoin(string name) +{ +//create the output file +int eventID1 = 0; +int eventID2 = 0; +int runID = 0; +int offset = 0; +int currentfile = 0; +float lastRun =-1; +string clusterName=name+"_cluster"; +cout<<"starting coincidence merging..."<ReOpen("UPDATE"); + TTree *oldTree = (TTree*)gDirectory->Get(name.c_str()); + TBranch *branch1 = oldTree->GetBranch("eventID1"); + branch1->SetAddress(&eventID1); + TBranch *branch2 = oldTree->GetBranch("eventID2"); + branch2->SetAddress(&eventID2); + TBranch *branch3 = oldTree->GetBranch("runID"); + branch3->SetAddress(&runID); + + TBranch* newBranch1=oldTree->Branch("eventID1cluster",&eventID1,"eventID1/I"); + TBranch* newBranch2=oldTree->Branch("eventID2cluster",&eventID2,"eventID2/I"); + + Int_t nentries=(Int_t)oldTree->GetEntries(); + + if (j==0) offset=0; + else offset+=m_lastEvents[currentfile]; + cout<<"the offset in this file is: "<GetEvent(i); + branch2->GetEvent(i); + branch3->GetEvent(i); + if(lastRun!=runID) + { + lastRun=runID; + offset=0; + } + eventID1+=offset; + eventID2+=offset; + newBranch1->Fill(); + newBranch2->Fill(); + } + oldTree->Write(); + } + return true; +} + +/*******************************************************************************************/ +// Gate tree merger +bool GateMergeManager::MergeGate(TChain* chainG) { + + int nentries=chainG->GetEntries(); + + float event = 0; + chainG->SetBranchAddress("event",&event); + Float_t iontime = 0; + chainG->SetBranchAddress("iontime",&iontime); + + //create the new tree + //Allow for large files and do not write every bit separately + m_RootTarget->cd(); + TTree * newTree = chainG->CloneTree(0); + newTree->SetAutoSave(2000000000); + if(m_maxRoot!=0) newTree->SetMaxTreeSize(m_maxRoot); + else newTree->SetMaxTreeSize(17179869184LL); + + // changing the compression level everywhere + TBranch *br; + TIter next(newTree->GetListOfBranches()); + while ((br=(TBranch*)next())) br->SetCompressionLevel(m_CompLevel); + + // the main part: modify the eventID + int offset = 0; + int currentTree = 0; + float lastEvent =-1; + float maxtime =-999999999; + for(int i=0;iGetEntry(i) <= 0) break; //end of chain + if(chainG->GetTreeNumber()>currentTree) { + currentTree++; + offset+=m_lastEvents[currentTree]; + // check for overlaping time intervalls between different files + // (not within the same file i.e. no time order assumed) + if(iontime0) + cout<<"Warning - overlapping Gate iontime (" + <Fill(); + } else { + cout<<"Warning - inf or NaN in Gate tree for iontime! "<GetEntry(i+1) <= 0) { //chain end fill the double event + event+=offset; + newTree->Fill(); + } else if(chainG->GetTreeNumber()==currentTree //no new file or + ||(chainG->GetTreeNumber()>currentTree + &&m_lastEvents[chainG->GetTreeNumber()]==0) ) { //new file with no offset fill double event + chainG->GetEntry(i); + event+=offset; + newTree->Fill(); + lastEvent=0;// we may have triple 1 (1 event run) + offset=0; + } + } + } + newTree->Write(); + delete newTree; + return true; +} + +/*******************************************************************************************/ +// Singles and Hits tree merger +bool GateMergeManager::MergeSing(TChain* chainS){ + + int nentriesS=chainS->GetEntries(); + + int eventID = 0; + int runID = 0; + double time = 0; + + chainS->SetBranchAddress("eventID",&eventID); + chainS->SetBranchAddress("runID",&runID); + chainS->SetBranchAddress("time",&time); + + m_RootTarget->cd(); + TTree * newSing = chainS->CloneTree(0); + newSing->SetAutoSave(2000000000); + if(m_maxRoot!=0) newSing->SetMaxTreeSize(m_maxRoot); + else newSing->SetMaxTreeSize(17179869184LL); + + // changing CompLevel everywhere + TBranch *br; + TIter next(newSing->GetListOfBranches()); + while ((br=(TBranch*)next())) br->SetCompressionLevel(m_CompLevel); + + //the main part: changing eventID + int offset = 0; + int currentTree = 0; + float lastRun = 0; + float maxtime =-999999999; + for(int i=0;iGetEntry(i) <= 0) break; //end of chain + if(chainS->GetTreeNumber()>currentTree) { + currentTree++; + offset+=m_lastEvents[currentTree]; + // check for overlaping time intervalls between different files + // (not within the same file i.e. no time order assumed) + if(time0) + cout<<"Warning - overlapping Singles time (" + <Fill(); + if(maxtimeWrite(); + delete newSing; + return true; +}; + +/*******************************************************************************************/ +// Coincidences tree merger +bool GateMergeManager::MergeCoin(TChain* chainC){ + + int nentriesC=chainC->GetEntries(); + + int eventID1 = 0; + chainC->SetBranchAddress("eventID1",&eventID1); + double time1 = 0; + chainC->SetBranchAddress("time1",&time1); + int eventID2 = 0; + chainC->SetBranchAddress("eventID2",&eventID2); + double time2 = 0; + chainC->SetBranchAddress("time2",&time2); + int runID = 0; + chainC->SetBranchAddress("runID",&runID); + + m_RootTarget->cd(); + TTree * newCoin = chainC->CloneTree(0); + newCoin->SetAutoSave(2000000000); + if(m_maxRoot!=0) newCoin->SetMaxTreeSize(m_maxRoot); + else newCoin->SetMaxTreeSize(17179869184LL); + + // changing CompLevel everywhere + TBranch *br; + TIter next(newCoin->GetListOfBranches()); + while ((br=(TBranch*)next())) br->SetCompressionLevel(m_CompLevel); + + int offset = 0; + int currentTree = 0; + float lastRun = 0; + float maxtime =-999999999; + for(int i=0;iGetEntry(i) <= 0) break; //end of chain + if(chainC->GetTreeNumber()>currentTree) { + currentTree++; + offset+=m_lastEvents[currentTree]; + // check for overlaping time intervalls between different files + // (not within the same file i.e. no time order assumed) + if(time10) + cout<<"Warning - overlapping Coincidences time1 (" + <0) + cout<<"Warning - overlapping Coincidences time2 (" + <Fill(); + if(maxtimeWrite(); + delete newCoin; + return true; +} +/*******************************************************************************************/ diff --git a/tests_dav/GateMergeManager.hh b/tests_dav/GateMergeManager.hh new file mode 100644 index 0000000..f7fb095 --- /dev/null +++ b/tests_dav/GateMergeManager.hh @@ -0,0 +1,91 @@ +/*---------------------- + GATE version name: gate_v... + + Copyright (C): OpenGATE Collaboration + +This software is distributed under the terms +of the GNU Lesser General Public Licence (LGPL) +See GATE/LICENSE.txt for further details +----------------------*/ + + +#ifndef GateMergeManager_h +#define GateMergeManager_h 1 +#include +#include +#include +#include +#include +#include + +using namespace std; + +class GateMergeManager +{ +public: + + GateMergeManager(bool fastMerge,int verboseLevel,bool forced,Long64_t maxRoot,string outDir){ + m_verboseLevel = verboseLevel; + m_forced = forced; + m_maxRoot = maxRoot; + m_outDir = outDir; + m_CompLevel = 1; + m_fastMerge = fastMerge; + + //check if a .Gate directory can be found + if (!getenv("GC_DOT_GATE_DIR")) { + cout<<"Environment variable GC_DOT_GATE_DIR not set !"< m_lastEvents; // latestevent from al files + vector m_vRootFileNames; // names of root files to merge + TFile* m_RootTarget; // root output file + string m_RootTargetName; // name of target i.e. root output file + bool m_fastMerge; // fast merge option, corrects the eventIDs locally +}; + + +#endif -- 2.47.1