//_____________________________________________________________________________ //BEGIN_HTML // TStnAna provides a simple utility to loop over the events stored in // STNTUPLE. See *_ana.C scripts in Stntuple/ana // directory for the examples of its use //END_HTML // // fPrintLevel = 10: print lumi statistics on all the runs // fPrintLevel = 11: print lumi statistics on good runs only //_____________________________________________________________________________ #include "cstdlib" #include "TROOT.h" #include "TChain.h" #include "TInterpreter.h" #include "TDirectory.h" #include "TSystem.h" #include "TBranchElement.h" #include "TBranchObject.h" #include "TLeafObject.h" #include "TObjString.h" #include "TFolder.h" #include "TH1.h" #include "TEventList.h" #include "Stntuple/obj/TStnNode.hh" #include "Stntuple/obj/TStnDataBlock.hh" #include "Stntuple/obj/TStnHeaderBlock.hh" #include "Stntuple/obj/TStnEvent.hh" #include "Stntuple/obj/TStnDBManager.hh" #include "Stntuple/obj/TStnRunSummary.hh" #include "Stntuple/obj/TStnGoodRunList.hh" #include "Stntuple/loop/TStnAna.hh" #include "Stntuple/loop/TStnModule.hh" #include "Stntuple/loop/TStnRun2InputModule.hh" #include "Stntuple/loop/TStnOutputModule.hh" ClassImp(TStnAna) //_____________________________________________________________________________ TStnAna::TStnAna(const char* Filename, const char* Mode) : TNamed ("StnAna","STNTUPLE event loop utility"), fMode (Mode) { // Input parameters: // ----------------- // filename: a name of the ROOT (.root) file with the STNTUPLE tree // if `filename' is a directory, then all the .root files are // chained // Mode : "run2" - working with RUN2 STNTUPLE's // the rest - not implemented yet Init(); if (fMode == "run2") { fInputModule = new TStnRun2InputModule(Filename); fInputModule->SetAna(this); } } //_____________________________________________________________________________ TStnAna::TStnAna(TChain* Chain, const char* Mode) : TNamed ("StnAna","STNTUPLE event loop utility"), fMode(Mode) { // Input parameters: // ----------------- // Chain : input chain, as it is created outside, it also has to be deleted // outside if (! Chain) { Error("TStnAna","input tree is not defined"); return; } Init(); if (fMode == "run2") { fInputModule = new TStnRun2InputModule(Chain); fInputModule->SetAna(this); } } //_____________________________________________________________________________ TStnAna::TStnAna(TStnDataset* Dataset, const char* Mode) : TNamed ("StnAna","STNTUPLE event loop utility"), fMode (Mode) { // Input parameters: // ----------------- // Dataset : input dataset created outside. As such it also has to be deleted // outside if (! Dataset) { Error("TStnAna","input tree is not defined"); return; } Init(); if (fMode == "run2") { fInputModule = new TStnRun2InputModule(Dataset); fInputModule->SetAna(this); } } //_____________________________________________________________________________ int TStnAna::Init() { fInitialized = 0; fModuleList = new TList(); fEventNumber = -1; fRunNumber = -1; fMinRunNumber = -1; fMaxRunNumber = INT_MAX; fEvent = 0; fNProcessedEvents = 0; fNPassedEvents = 0; fNEventsToReport = 500; fOutputFile = 0; fOutputTree = 0; fOutputModule = 0; fDBManager = TStnDBManager::Instance(); TObject* o = gROOT->GetRootFolder()->FindObject("Ana"); if (o != 0) { gROOT->GetRootFolder()->Remove(o); o->Delete(); } fFolder = gROOT->GetRootFolder()->AddFolder("Ana","TStnAna Folder"); TH1::AddDirectory(0); // fListOfGoodRuns = 0; fGoodRun = 1; fListOfRuns = new TList(); fPrintLevel = 0; fGoodRunList = 0; fEventList = 0; return 0; } //_____________________________________________________________________________ TStnAna::~TStnAna() { // Get ride of the event //printf(" TStnAna: event.\n"); fflush(stdout); fflush(stderr); delete fEvent; fListOfRuns->Delete(); delete fListOfRuns; //----------------------------------------------------------------------------- // so far deleting a folder leads to deletion of the histograms as well... //----------------------------------------------------------------------------- //printf(" TStnAna: folder.\n"); fflush(stdout); fflush(stderr); gROOT->GetRootFolder()->Remove(fFolder); fFolder->Clear(); delete fFolder; //printf(" TStnAna: mods.\n"); fflush(stdout); fflush(stderr); fModuleList->Delete(); delete fModuleList; //printf(" TStnAna: input.\n"); fflush(stdout); fflush(stderr); delete fInputModule; //printf(" TStnAna: output.\n"); fflush(stdout); fflush(stderr); delete fOutputModule; //printf(" TStnAna: output file.\n"); fflush(stdout); fflush(stderr); delete fOutputFile; //printf(" TStnAna: eventlist.\n"); fflush(stdout); fflush(stderr); delete fEventList; //printf(" TStnAna: goodruns.\n"); fflush(stdout); fflush(stderr); if (fGoodRunList) delete fGoodRunList; // Get ride of the profile histograms //printf(" TStnAna: profiles.\n"); fflush(stdout); fflush(stderr); delete fIntLumiTev; delete fIntLumiLive; delete fIntLumiOffl; } //_____________________________________________________________________________ Int_t TStnAna::SetSplit(Int_t ind, Int_t tot) { if(TStnInputModule* inp = GetInputModule()){ inp->SetSplit(ind,tot); } else { Error("TStnAna","Could not find input module"); } } //_____________________________________________________________________________ Int_t TStnAna::AddDataset(TStnDataset* d) { if(TStnInputModule* inp = GetInputModule()){ inp->AddDataset(d); } else { Error("TStnAna","Could not find input module"); } } //_____________________________________________________________________________ Int_t TStnAna::SetOutputFile(const char* filename) { if (! filename) return -1; fOutputFile = new TFile(filename,"RECREATE"); if (! fOutputFile->IsOpen()) return -2; return 0; } //_____________________________________________________________________________ void TStnAna::SetInputModule(TStnInputModule* module) { // module is specified explicitly, // non-default name module->SetAna(this); fInputModule = module; } //_____________________________________________________________________________ void TStnAna::SetOutputModule(TStnOutputModule* module) { // module is specified explicitly, // non-default name module->SetAna(this); fOutputModule = module; } //_____________________________________________________________________________ int TStnAna::AddModule(TStnModule* Module, Int_t FilteringMode) { // module is specified explicitly, // non-default name Module->SetAna(this); Module->SetFilteringMode(FilteringMode); fModuleList->Add(Module); return 0; } //_____________________________________________________________________________ TStnModule* TStnAna::AddModule(const char* ClName , const char* ModuleName, const char* Title , int FilteringMode) { // assume that "Name" is the name of the module class and that this class // is already known to the interpreter. Module is created using default // constructor, so // newly created module is owned by *this TStnModule* m = 0; TClass* cl = gROOT->GetClass(ClName); if (! cl) { Error("AddModule","class %s is not known to the interpreter",ClName); } else { m = (TStnModule*) cl->New(); if (ModuleName) m->SetName(ModuleName); if (Title ) m->SetTitle(Title); else if (ModuleName) m->SetTitle(ModuleName); m->SetAna(this); m->SetFilteringMode(FilteringMode); fModuleList->Add(m); } return m; } //_____________________________________________________________________________ int TStnAna::DeleteModule(const char* name) { TObject* m = fModuleList->FindObject(name); if (m) { fModuleList->Remove(m); delete m; } return 0; } //_____________________________________________________________________________ int TStnAna::ReloadModule(const char* name, const char* filename) { char fname[200], soname[200], cmd[200]; char class_name[100]; if (this) { printf(">>> TStnAna::ReloadModule not implemented yet\n"); return -1; } DeleteModule(name); // define .so and .cc files sprintf(class_name,"T%sModule",name); sprintf(soname,"%s/./%s.so",getenv("PWD"),class_name); sprintf(fname ,"%s/./%s.cc",getenv("PWD"),class_name); // unload the library sprintf(cmd,".U %s",soname); gInterpreter->ProcessLine(cmd); // load modified library sprintf(cmd,".L %s+",fname); gInterpreter->ProcessLine(cmd); // and finally add new module TClass* cl = gROOT->GetClass(class_name); // if (! cl) { // printf(">>> TStnAna::ReloadModule: class %s doesn exist\n",class_name); // return -2; // } // else if (! cl->InheritsFrom("TStnModule")) { // printf(">>> TStnAna::ReloadModule: class %s doesn inherit from TStnModule", // class_name); // return -3; // } AddModule((TStnModule*) cl->New()); return 0; } //_____________________________________________________________________________ int TStnAna::BeginRun() { fRunNumber = fHeaderBlock->RunNumber(); //----------------------------------------------------------------------------- // initialize DB manager //----------------------------------------------------------------------------- TFile* file; TDirectory* olddir; TChain* chain; chain = fInputModule->GetChain(); //----------------------------------------------------------------------------- // MC generator module returns chain=0 //----------------------------------------------------------------------------- if (chain) { file = chain->GetFile(); olddir = gDirectory; if (file && file->cd("db")) { // DB directory exists, read the calib const gDirectory->cd(Form("run_%i",fRunNumber)); fDBManager->Read(""); } olddir->cd(); } TStnRunSummary* new_rs = (TStnRunSummary*) fDBManager->GetTable("RunSummary"); //----------------------------------------------------------------------------- // if use bad run list and the run is marked as bad, return... //----------------------------------------------------------------------------- if (fGoodRunList != 0) fGoodRun = fGoodRunList->GoodRun(fRunNumber); else fGoodRun = 1; if (! fGoodRun) return -1; //----------------------------------------------------------------------------- // cache new run to calculate luminosity in the end of job //----------------------------------------------------------------------------- TIter it(fListOfRuns); int done = 0; TStnRunSummary* rs; while ((rs = (TStnRunSummary*) it.Next())) { if (rs->RunNumber() == new_rs->RunNumber()) { done = 1; break; } else if (rs->RunNumber() > new_rs->RunNumber()) { break; } } if (! done) { TStnRunSummary* run_sum = new TStnRunSummary(*new_rs); if (rs) fListOfRuns->AddBefore(rs,run_sum); else fListOfRuns->Add(run_sum); } return 0; } //_____________________________________________________________________________ int TStnAna::ProcessEventList(TEventList* EventList) { // process event list int n, ientry,rc; n = EventList->GetN(); for (int i=0; iGetEntry(i); rc = ProcessEntry(ientry); if(rc!=0 && rc!=-2 && rc!=-3) return rc; } return 0; } //_____________________________________________________________________________ int TStnAna::ProcessEventList(Int_t* EventList) { // process event list SetEventList(EventList); int rc = Run(); return rc; } //_____________________________________________________________________________ void TStnAna::SetEventList(Int_t* EventList) { // set event list int nev; //----------------------------------------------------------------------------- // determine number of events //----------------------------------------------------------------------------- nev = 0; for (int i=0; EventList[i] > 0; i+= 2) { nev++; } fEventList = new EventList_t[nev+1]; for (int i=0; i 0 and RunMax = -1, process only RunMin // if RunMin > 0 and RunMax > 0, process events from RunMin to RunMax // (including RunMin and RunMax) int passed, rn, ev, rc; // prepare to read next event (run2 case: load // the tree, run1 case: also read the event) if (! fInitialized) { rc = BeginJob(); if(rc!=0) return rc; } fEntry = Entry; Int_t tree_entry = fInputModule->NextEvent(int(fEntry)); if (tree_entry < 0) { //----------------------------------------------------------------------------- // end of the chain... //----------------------------------------------------------------------------- Warning("ProcessEntry","End of chain reached."); return -1; } //----------------------------------------------------------------------------- // clear all the data from the previous event //----------------------------------------------------------------------------- TIter nd(fEvent->GetListOfNodes()); while (TStnNode* node = (TStnNode*) nd.Next()) { node->GetDataBlock()->Clear(); } // always read event header branch rc = fHeaderBlock->GetEntry(tree_entry); if (rc == 0 || rc == -1) { // non existing entry or io error return -4; } rn = fHeaderBlock->RunNumber (); ev = fHeaderBlock->EventNumber(); fHeaderBlock->GetEvent()->SetEventNumber(rn,ev,fHeaderBlock->SectionNumber()); passed = 1; //----------------------------------------------------------------------------- // if event list is specified //----------------------------------------------------------------------------- if (fEventList != 0) { passed = 0; for (int i=0; fEventList[i].fRun > 0; i++) { if ((fEventList[i].fRun == rn) && (fEventList[i].fEvent == ev)) { passed = 1; fEventList[i].fFound++; break; } } if (passed == 0) return 0; } //----------------------------------------------------------------------------- // check run number and return if it is outside the range //----------------------------------------------------------------------------- if (( rn < fMinRunNumber) || (rn > fMaxRunNumber )) { return -2; } if (fHeaderBlock->RunNumber() != fRunNumber) { //----------------------------------------------------------------------------- // BeginRun returns -1 if the run is bad //----------------------------------------------------------------------------- BeginRun(); } if (fGoodRun <= 0) return -3; //----------------------------------------------------------------------------- // each module is supposed to talk to tree and to request the data (branches) // it needs //----------------------------------------------------------------------------- TListIter it(fModuleList); while (TStnModule* m = (TStnModule*) it.Next()) { if (m->GetEnabled()) { // make sure BeginJob was called at // least once if (! m->GetInitialized()) { m->BeginJob(); m->SetInitialized(1); } // check if the run # has changed if (fHeaderBlock->RunNumber() != m->GetLastRun()) { m->EndRun(); m->BeginRun(); m->SetLastRun(fHeaderBlock->RunNumber()); } // now it is safe to call the // event entry point if (fPrintLevel > 0) { printf(" ---------- Event entry point called for %s\n",m->GetName()); } m->Event(tree_entry); passed = m->GetPassed(); if (! passed) break; } } // see if output needs to be written if (passed) { fNPassedEvents++; if (fOutputModule) { if (fOutputModule->GetEnabled()) { if (! fOutputModule->GetInitialized()) { fOutputModule->BeginJob(); fOutputModule->SetInitialized(1); } if (fHeaderBlock->RunNumber() != fOutputModule->GetLastRun()) { fOutputModule->EndRun(); fOutputModule->BeginRun(); } fOutputModule->Event(tree_entry); } } } fNProcessedEvents++; if (fPrintLevel == 0) { if (fNProcessedEvents % fNEventsToReport == 0) { fHeaderBlock->Print(Form(" >>> TStnAna: Processed %10i events", fNProcessedEvents)); } } return 0; } //_____________________________________________________________________________ int TStnAna::ProcessEvent(int Run, int Event) { // process one event with the given run/event numbers. This method is not as // fast as ProcessEntry, because it starts searching from the beginning of // the tree // in this mode ignore bad run list TIter it(fModuleList); // prepare to read next event int found = 0; Int_t tree_entry, nb, rc; if (! fInitialized) { rc = BeginJob(); if (rc!=0) return rc; } //----------------------------------------------------------------------------- // clear previous event data not to think about it in the modules //----------------------------------------------------------------------------- TIter nd(fEvent->GetListOfNodes()); while (TStnNode* node = (TStnNode*) nd.Next()) { node->GetDataBlock()->Clear(); } //----------------------------------------------------------------------------- // try to find event in the chain //----------------------------------------------------------------------------- fEntry = 0; tree_entry = fInputModule->GetChain()->LoadTree(int(fEntry)); do { tree_entry = fInputModule->NextEvent(int(fEntry)); if (tree_entry < 0) break; nb = fHeaderBlock->GetEntry(tree_entry); if ((fHeaderBlock->EventNumber() == Event) && (fHeaderBlock->RunNumber () == Run ) ) { found = 1; break; } fEntry++; } while (nb); if (! found) { printf(" *** run %i event %i not found\n",Run,Event); return -1; } else { fHeaderBlock->Print(); } fHeaderBlock->GetEvent()->SetEventNumber(fHeaderBlock->RunNumber(), fHeaderBlock->EventNumber(), fHeaderBlock->SectionNumber()); //----------------------------------------------------------------------------- // each module is supposed to request data (branches) it needs //----------------------------------------------------------------------------- fEntry = fInputModule->GetEntry(); if (fHeaderBlock->RunNumber() != fRunNumber) { BeginRun(); } it.Reset(); while (TStnModule* m = (TStnModule*) it.Next()) { if (m->GetEnabled()) { // make sure BeginJob was called // at least once if (! m->GetInitialized()) { m->BeginJob(); m->SetInitialized(1); } // check if run # has changed if (fHeaderBlock->RunNumber() != m->GetLastRun()) { m->EndRun(); m->BeginRun(); m->SetLastRun(fHeaderBlock->RunNumber()); } // and only now it is safe to call // event entry point m->Event(tree_entry); } } if (fPrintLevel == 0) { if ((fNEventsToReport > 0) && (fNProcessedEvents % fNEventsToReport == 0)) { fHeaderBlock->Print(Form(" >>> TStnAna: Processed %10i events", fNProcessedEvents)); } } fNPassedEvents++; fNProcessedEvents++; //----------------------------------------------------------------------------- // ***** looks like call to the output module is missing here, // however this entry point is intended for debug purposes... //----------------------------------------------------------------------------- return 0; } //_____________________________________________________________________________ int TStnAna::BeginJob() { // initialization actions to be done after construction char name[200], title[200]; int rc; rc = fInputModule->BeginJob(); if(rc!=0) return rc; fInputModule->RegisterInputBranches(fEvent); fInputModule->SetInitialized(1); fFolder->Add(fInputModule->GetFolder()); //----------------------------------------------------------------------------- // always read in the header block //----------------------------------------------------------------------------- RegisterDataBlock("HeaderBlock",&fHeaderBlock); TIter it(fModuleList); // initialization while (TStnModule* m = (TStnModule*) it.Next()) { if (m->GetEnabled()) { m->BeginJob(); m->SetInitialized(1); // also pick up module's folder... fFolder->Add(m->GetFolder()); } } if (fOutputModule && fOutputModule->GetEnabled()) { // make sure that all the input branches made it // into the output list and being read in TIter itt(fEvent->GetListOfInputNodes()); TStnNode* node; TObjString* name; const char* branch_name; TObjArray* drop_list = fOutputModule->GetDropList(); TObjArray* keep_list = fOutputModule->GetKeepList(); int ndropped = drop_list->GetEntriesFast(); int nkept = keep_list->GetEntriesFast(); while (node = (TStnNode*) itt.Next()) { branch_name = node->GetName(); // If the keep list has an element we drop everything and only // check the keep list if (nkept < 1) { for (int i=0; iUncheckedAt(i); if (strcmp(name->GetString().Data(),branch_name) == 0) goto NEXT_BRANCH; } } else { bool dropIt = true; for (int i=0; iUncheckedAt(i); if (strcmp(name->GetString().Data(),branch_name) == 0) { dropIt = false; break; } } if (dropIt) goto NEXT_BRANCH; } // Add this node to the file if (! fEvent->GetListOfNodes()->FindObject(node)) fEvent->GetListOfNodes()->Add(node); fEvent->GetListOfOutputNodes()->Add(node); NEXT_BRANCH:; } fOutputModule->BeginJob(); fOutputModule->SetInitialized(1); fFolder->Add(fOutputModule->GetFolder()); } //----------------------------------------------------------------------------- // book luminosity histograms //----------------------------------------------------------------------------- sprintf(name, "int_lumi_tev"); sprintf(title,"Integrated delivered luminosity"); fIntLumiTev = new TProfile(name,title,1000,110000,210000,0,1e10); sprintf(name, "int_lumi_tape"); sprintf(title,"Integrated recorded luminosity"); fIntLumiLive = new TProfile(name,title,1000,110000,210000,0,1e10); sprintf(name, "int_lumi_offl"); sprintf(title,"Integrated offline luminosity"); fIntLumiOffl = new TProfile(name,title,1000,110000,210000,0,1e10); fFolder->Add(fIntLumiTev); fFolder->Add(fIntLumiLive); fFolder->Add(fIntLumiOffl); fInitialized = 1; return 0; } //_____________________________________________________________________________ int TStnAna::EndJob() { // actions at end of job static int nlines = 0; //----------------------------------------------------------------------------- // fill luminosity histograms //----------------------------------------------------------------------------- TIter it(fListOfRuns); float ltev = 0; float ltape = 0; float loffl = 0; while (TStnRunSummary* rs = (TStnRunSummary*) it.Next()) { if (fPrintLevel == 11) { if (nlines == 0) { printf("--------------------------------------------------"); printf("----------------------\n"); printf(" run rc status "); printf(" L(TeV) L(live) L(offline)\n"); printf("---------------------------------------------------"); printf("---------------------\n"); } printf(" %8i %3i %-20s %10.3f %10.3f %10.3f\n", rs->RunNumber(), 1, "GOOD", rs->LumiTev(), rs->LumiTape(), rs->OfflineLumiRS()); nlines++; if (nlines == 50) nlines = 0; } ltev += rs->LumiTev(); ltape += rs->LumiTape(); loffl += rs->OfflineLumiRS(); fIntLumiTev->Fill (rs->RunNumber(),ltev); fIntLumiLive->Fill(rs->RunNumber(),ltape); fIntLumiOffl->Fill(rs->RunNumber(),loffl); } if (fPrintLevel >= 0) { printf("----- end job: ---- %s\n", GetName()); printf(" L(TeV) : %10.3f\n",ltev); printf(" L(live): %10.3f\n",ltape); printf(" L(offl): %10.3f\n",loffl); } //----------------------------------------------------------------------------- // other actions //----------------------------------------------------------------------------- fInputModule->EndJob(); TIter itt(fModuleList); while (TStnModule* m = (TStnModule*) itt.Next()) { if (m->GetEnabled()) { m->EndRun(); m->EndJob(); } } if (fOutputModule && fOutputModule->GetEnabled()) { fOutputModule->EndJob(); } if (fPrintLevel > -2) printf(" >>> TStnAna::EndJob: processed %10i events, passed %10i events\n", fNProcessedEvents,fNPassedEvents); if (fEventList) { printf(" >>> strip summary:-\n"); for (int i=0; fEventList[i].fRun>0; i++) { printf (" run,event : %6i,%8i found=%i\n", fEventList[i].fRun, fEventList[i].fEvent, fEventList[i].fFound); } delete [] fEventList; fEventList = 0; } return 0; } //_____________________________________________________________________________ int TStnAna::Run(int NEvents, Int_t MinRunNumber, Int_t MaxRunNumber, Int_t StartEntry) { // process NEvents events starting from the first entry in the tree/chain // perform termination actions (whatever they are) in the end int rc; rc = BeginJob(); if(rc!=0) return rc; double nentries = fInputModule->GetEntries(); if (NEvents > 0) { if (NEvents <= nentries) { nentries = NEvents; } else { Warning("Run", " STNTUPLE has only %10.0f entries, those will be processed", nentries); } } fMinRunNumber = MinRunNumber; fMaxRunNumber = MaxRunNumber; fNProcessedEvents = 0; fNPassedEvents = 0; fEntry = StartEntry-1; Continue(int(nentries)); EndJob(); return 0; } //_____________________________________________________________________________ int TStnAna::ProcessRun(int RunMin, int RunMax) { // process all events of a given run // perform termination actions (whatever they are) in the end int rc; rc = BeginJob(); if (rc!=0) return rc; double nentries = fInputModule->GetEntries(); printf(" processing events for the run range from %8i to %8i\n", RunMin,RunMax); fNProcessedEvents = 0; fNPassedEvents = 0; fEntry = -1; fMinRunNumber = RunMin; if (RunMax == -1) fMaxRunNumber = RunMin; else fMaxRunNumber = RunMax; for (int i=0; i= nev) break; } } return 0; } //_____________________________________________________________________________ void* TStnAna::RegisterDataBlock(const char* BranchName, const char* ClassName) { // make sure branch exists: the branch // is a top-level branch TStnDataBlock* block; TStnNode* node, *exists; TClass* cl; node = (TStnNode*) fEvent->GetListOfInputNodes()->FindObject(BranchName); if (node) { // make sure we're not adding the same branch // twice exists = (TStnNode*) fEvent->GetListOfNodes()->FindObject(BranchName); if (exists) node = exists; else fEvent->GetListOfNodes()->Add(node); block = node->GetDataBlock(); block->SetNode(node); block->SetValid(1); } else { cl = gROOT->GetClass(ClassName); if (!cl || !cl->InheritsFrom("TStnDataBlock")) { Error("RegisterDataBlock", "class %s doesn\'t inherit from TStnDataBlock", ClassName); block = 0; } else { node = new TStnNode("",cl,fEvent); fEvent->GetListOfUnusedNodes()->Add(node); block = node->GetDataBlock(); block->SetNode(node); block->SetValid(0); } } return block; } //_____________________________________________________________________________ void TStnAna::RegisterDataBlock(const char* BranchName, void* DataBlock) { // make sure branch exists: the branch is a top-level branch TStnDataBlock** block = (TStnDataBlock**) DataBlock; TStnNode *node, *exists; node = (TStnNode*) fEvent->GetListOfInputNodes()->FindObject(BranchName); if (node) { //----------------------------------------------------------------------------- // make sure we're not adding the same branch twice //----------------------------------------------------------------------------- exists = (TStnNode*) fEvent->GetListOfNodes()->FindObject(BranchName); if (exists) node = exists; else fEvent->GetListOfNodes()->Add(node); (*block) = node->GetDataBlock(); (*block)->SetNode(node); (*block)->SetValid(1); } else { //----------------------------------------------------------------------------- // branch doesn't exist, no idea about the class name, // so the best we can do is to create a TStnBlock... //----------------------------------------------------------------------------- (*block) = new TStnDataBlock(); (*block)->SetValid(0); node = new TStnNode("",(*block),fEvent); (*block)->SetNode(node); fEvent->GetListOfUnusedNodes()->Add(node); } } //_____________________________________________________________________________ void TStnAna::RegisterDataBlock(const char* BranchName, const char* ClassName, void* DataBlock) { // make sure branch exists: the branch is a top-level branch TStnDataBlock** block = (TStnDataBlock**) DataBlock; TStnNode *node, *exists; TClass* cl; node = (TStnNode*) fEvent->GetListOfInputNodes()->FindObject(BranchName); if (node) { //----------------------------------------------------------------------------- // make sure we're not adding the same branch twice //----------------------------------------------------------------------------- exists = (TStnNode*) fEvent->GetListOfNodes()->FindObject(BranchName); if (exists) node = exists; else fEvent->GetListOfNodes()->Add(node); (*block) = node->GetDataBlock(); (*block)->SetNode(node); (*block)->SetValid(1); } else { //----------------------------------------------------------------------------- // branch doesn't exist, no idea about the class name, // so the best we can do is to create a TStnBlock... //----------------------------------------------------------------------------- cl = gROOT->GetClass(ClassName); if (!cl || !cl->InheritsFrom("TStnDataBlock")) { Error("RegisterDataBlock", "class %s doesn\'t inherit from TStnDataBlock", ClassName); (*block) = 0; } else { node = new TStnNode("",cl,fEvent); fEvent->GetListOfUnusedNodes()->Add(node); (*block) = node->GetDataBlock(); (*block)->SetNode(node); (*block)->SetValid(0); } } } //_____________________________________________________________________________ int TStnAna::Enable(const char* module_name) { TStnModule* m = (TStnModule*) fModuleList->FindObject(module_name); if (m) { m->SetEnabled(1); return 0; } else { return -1; } } //_____________________________________________________________________________ int TStnAna::Disable(const char* module_name) { TStnModule* m = (TStnModule*) fModuleList->FindObject(module_name); if (m) { m->SetEnabled(0); return 0; } else { return -1; } } //_____________________________________________________________________________ void TStnAna::Help(const char* item) { if (gSystem->Exec("which lynx >& /dev/null") == 0) { gSystem->Exec("xterm -geometry 100x40 lynx http://www-cdf.fnal.gov/upgrades/computing/projects/Stntuple/Stntuple.html"); } else { printf(" *** can\'t find lynx\n"); } } namespace { // local little struct to keep statistics struct BranchStat { //--------------------------- // data //--------------------------- TBranch* fBranch; Double_t fN; Double_t fX; Double_t fX2; Double_t fTotBytes; Double_t fZipBytes; Double_t fCompRatio; //--------------------------- // functions //--------------------------- BranchStat(): fN(0), fX(0), fX2(0), fTotBytes(0), fZipBytes(0) {} // ~BranchStat() {} Double_t XMean () { return fX/fN; } Double_t X2Mean() { return fX2/fN; } Double_t SigXX () { return X2Mean() - XMean()*XMean(); } Double_t TotBytes() {return fTotBytes;} Double_t ZipBytes() {return fZipBytes;} Double_t CompRatio() {return (fZipBytes>0 ? fTotBytes/fZipBytes : 0.0);} }; } //_____________________________________________________________________________ Int_t TStnAna::NBytesRead(TBranch* Branch, Double_t& TotBytes, Double_t& ZipBytes) { // returns total and zipped (on disk) sizes of the `Branch' TotBytes += 1.0 * Branch->GetTotBytes(); ZipBytes += 1.0 * Branch->GetZipBytes(); TObjArray* branches = Branch->GetListOfBranches(); int nbranches = branches->GetEntriesFast(); if (nbranches > 0) { for (int i=0; iAt(i); NBytesRead(b,TotBytes,ZipBytes); } } return 0; } //_____________________________________________________________________________ int TStnAna::SaveFolder(TFolder* Folder, TDirectory* Dir) { // save Folder into a subdirectory // do not write TStnModule's - for each TStnModule save contents of its // fFolder TFolder* fol; TDirectory* dir; TObject* o; //----------------------------------------------------------------------------- // create new subdirectory in Dir to save Folder //----------------------------------------------------------------------------- Dir->cd(); dir = new TDirectory(Folder->GetName(),Folder->GetName(),""); dir->cd(); // printf(" ------------------- Dir: %s, new dir: %s\n", // Dir->GetName(),dir->GetName()); TIter it(Folder->GetListOfFolders()); while ((o = it.Next())) { // printf(" o->GetName, o->ClassName : %-20s %-20s\n", // o->GetName(), // o->ClassName()); if (strcmp(o->ClassName(),"TFolder") == 0) { SaveFolder((TFolder*) o, dir); // dir->cd(); } else if (! o->InheritsFrom("TStnModule")) { // printf("gDirectory->GetPath = %s\n",gDirectory->GetPath()); o->Write(); // gDirectory->GetListOfKeys()->Print(); } } Dir->cd(); return 0; } //_____________________________________________________________________________ void TStnAna::SaveHist(const char* Filename, Int_t Mode) { // save histograms booked by all the modules into a file with the given name // Mode = 1: save folders // Mode = 2: save directories TFile* f = new TFile(Filename,"recreate"); if (Mode == 1) { fFolder->Write(); } else if (Mode == 2) { SaveFolder(fFolder,f); } f->Close(); delete f; } //_____________________________________________________________________________ void TStnAna::PrintStat(Int_t nevents, const char* BranchName) { // Prints status information after reading `nevents' from `BranchName' // `BranchName = "" means all the branches BeginJob(); TObjArray* list = fInputModule->GetChain()->GetListOfBranches(); // In case input was not properly specified if (! list) { Error("PrintStat","input chain seems empty."); return; } TIter it(list); TBranch* branch; TStnNode* node; TLeafObject* leaf; int nbranches = list->GetEntriesFast(); const char* class_name; TStnEvent* event = new TStnEvent(); BranchStat* stat = new BranchStat[nbranches+1]; int ibb = 0; while (branch = (TBranch*) it.Next()) { if ( (strcmp(BranchName,"" ) == 0) || (strcmp(BranchName,branch->GetName()) == 0) ) { if (strcmp(branch->ClassName(),"TBranchElement") == 0) { class_name = ((TBranchElement*)branch)->GetClassName(); } else { leaf = (TLeafObject*) ((TBranchObject*)branch)->GetLeaf(branch->GetName()); class_name = leaf->GetTypeName(); } TClass* cl = gROOT->GetClass(class_name); node = new TStnNode(branch->GetName(),cl,event); branch->SetAddress(node->GetDataBlockAddress()); branch->SetAutoDelete(kFALSE); event->GetListOfNodes()->Add(node); // printf("%s\n",branch->GetName()); stat[ibb].fBranch = branch; stat[ibb].fN = 0; stat[ibb].fX = 0; stat[ibb].fX2 = 0; ibb++; } } Double_t nev; // set the number of events to read nev = fInputModule->GetEntries(); if (nev >= nevents) { nev = nevents; } else { Warning("PrintStat"," STNTUPLE has only %g entries, those will be processed", nev); } Double_t nb_event, nb; for (int ientry=0; ientryClear(); for (int ib=0; ibGetEntry(ientry); stat[ib].fN += 1; stat[ib].fX += nb; stat[ib].fX2 += nb*nb; nb_event += nb; if (fPrintLevel == 2) { printf("%-48s %10.0f bytes \n",stat[ib].fBranch->GetName(),nb); } } stat[nbranches].fN += 1; stat[nbranches].fX += nb_event; stat[nbranches].fX2 += nb_event*nb_event; } // find compression ratio for (int ib=0; ib0 ? stat[nbranches].XMean()/stat[nbranches].CompRatio() : 0.0); // last piece: printing printf("----------------------------------------------------"); printf("----------------------------------------------------\n"); printf("........... branch name ..................... "); printf(" TotBytes ZipBytes CompFactor %% of File\n"); printf("----------------------------------------------------"); printf("----------------------------------------------------\n"); for (int ib=0; ib0.0 ? stat[ib].ZipBytes()/stat[nbranches].ZipBytes() : 0.0 ); printf("%-48s %7.0f %7.0f %10.0f %10.0f %6.2f %10.1f\n", stat[ib].fBranch->GetName(), stat[ib].XMean(), sqrt(stat[ib].SigXX()), stat[ib].TotBytes(), stat[ib].ZipBytes(), stat[ib].CompRatio(), 100.0*diskFrac); } printf("-------------------------------------------------"); printf("--------------------------------------------------\n"); printf("........... total .............. "); printf(" \n"); printf("-------------------------------------------------"); printf("--------------------------------------------------\n"); printf("%-30s %12.3f %12.3f %12.3f\n", " total event", stat[nbranches].XMean(), sqrt(stat[nbranches].SigXX()), meanCompSize); // Cleanup everything we booked here delete []stat; delete event; } //_____________________________________________________________________________ int TStnAna::AddArrays(TObjArray* Arr1, TObjArray* Arr2) { // in STNTUPLE files arrays are not allowed to have subfolders // TObjArrayIter it1(Arr1); // TObjArrayIter it2(Arr2); // // TObject *o1, *o2; // TH1 *h1, *h2; // TObjArray *a1, *a2; // while ((o1 = it1.Next())) { // o2 = Arr2->FindObject(o1->GetName()); // if (o1->InheritsFrom("TH1")) { // h1 = (TH1*) o1; // h2 = (TH1*) o2; // *h1 = *h1 + *h2; // } // else if (strcmp(o1->ClassName(),"TObjArray") == 0) { // //----------------------------------------------------------------------------- // // lists // //----------------------------------------------------------------------------- // a1 = (TObjArray*) o1; // a2 = (TObjArray*) o2; // add_arrays(a1,a2); // } // else { // printf("%-30s %-20s *************** add_array EMOE *****************\n", // o1->GetName(),o1->ClassName()); // } // } return 0; } //_____________________________________________________________________________ Int_t TStnAna::AddFolders(TFolder* Fol1, TFolder* Fol2) { // for each histogram from Fol1 add corresponding histogram from Fol2 to it // TIter it1(Fol1->GetListOfFolders()); // // TObject *o1, *o2; // TH1 *h1, *h2; // TFolder *f1, *f2; // TObjArray *a1, *a2; //----------------------------------------------------------------------------- // loop over the objects stored in this Fol1 //----------------------------------------------------------------------------- // while ((o1 = it1.Next())) { // o2 = Fol2->FindObject(o1->GetName()); // if (o1->InheritsFrom("TH1")) { // h1 = (TH1*) o1; // h2 = (TH1*) o2; // *h1 = *h1 + *h2; // } // else if (strcmp(o1->ClassName(),"TFolder") == 0) { // printf("%-30s %-20s folder \n",o1->GetName(),o1->ClassName()); // f1 = (TFolder*) o1; // f2 = (TFolder*) o2; // //----------------------------------------------------------------------------- // // compare histogram contents of 2 folders // //----------------------------------------------------------------------------- // AddFolders(f1,f2); // } // else if (strcmp(o1->ClassName(),"TObjArray") == 0) { // //----------------------------------------------------------------------------- // // compare lists of histograms // //----------------------------------------------------------------------------- // a1 = (TObjArray*) o1; // a2 = (TObjArray*) o2; // AddArrays(a1,a2); // } // else { // printf("%-30s %-20s *************** EMOE *****************\n", // o1->GetName(),o1->ClassName()); // } // } return 0; } //_____________________________________________________________________________ int TStnAna::MergeHistograms(const char* List, const char* OutputFile) { // given List of STNTUPLE histogram files (i.e. "a/*.root") merges them and // writes output into OutputFile char cmd[200]; //TFile* f; TFile* output_file; TFolder *fol1, *fol2; int first = 1; char fn[200]; FILE* file = gSystem->OpenPipe(Form("ls %s",List),"r"); while ( fscanf(file,"%s",fn) > 0) { printf("%s\n",fn); if (first) { first = 0; //----------------------------------------------------------------------------- // figure out list of histograms //----------------------------------------------------------------------------- sprintf(cmd,"cp %s %s",fn,OutputFile); gSystem->Exec(cmd); output_file = new TFile(OutputFile,"u"); } else { //----------------------------------------------------------------------------- // loop over the histograms in the OutputFile and for each histogram add the // same histogram from "fn" to it //----------------------------------------------------------------------------- // fol1 = read_folder(OutputFile,"Ana"); // fol2 = read_folder(fn,"Ana"); AddFolders(fol1,fol2); } } fclose(file); output_file->Write(); output_file->Close(); return 0; } //_____________________________________________________________________________ void TStnAna::Clear(const char* Opt) { // assume TStnAna has been already initialized once, reinitialize // leave fMode as it was fInitialized = 0; // delete contents of the lists, but not the // lists themselves fListOfRuns->Delete(); fModuleList->Delete(); //----------------------------------------------------------------------------- // so far deleting a folder leads to deletion of the histograms as well... // ... hmm ... is Delete() //----------------------------------------------------------------------------- fFolder->Clear(); fEventNumber = -1; fRunNumber = -1; fMinRunNumber = -1; fMaxRunNumber = INT_MAX; fEvent = 0; fEntry = -1; fNProcessedEvents = 0; fNPassedEvents = 0; fNEventsToReport = 500; fOutputFile = 0; fOutputTree = 0; fOutputModule = 0; fDBManager = TStnDBManager::Instance(); fGoodRun = 1; fGoodRunList = 0; fPrintLevel = 0; TH1::AddDirectory(0); } //_____________________________________________________________________________ void TStnAna::Print(const char* Opt) const { }