/*---------------------- 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 #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 "<2) cout<<"Root input file name: "<2) cout<<"Root output file name: "<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; } /*******************************************************************************************/