//-------------------------------------------------------------------------- // Description: // ----------- // Class FillStntupleModule : fills Stntuple // // //------------------------------------------------------------------------ #ifdef __GNUG__ #pragma implementation #endif #include "TTree.h" #include "TBranchElement.h" #include "TBranchObject.h" #include "TLeafObject.h" #include #include #include #include #include #include ClassImp(FillStntupleModule) //------------------------------------------------------------------------------ // constructors //------------------------------------------------------------------------------ FillStntupleModule::FillStntupleModule(const char* name, const char* desc): StntupleModule (name,desc) { fLastRun = -1; } //------------------------------------------------------------------------------ FillStntupleModule::~FillStntupleModule() { } //------------------------------------------------------------------------------ AppResult FillStntupleModule::beginRun(AbsEvent* Event) { int runnum = AbsEnv::instance()->runNumber(); if (runnum != fLastRun) { // create new subdirectory and store // calibration constants in there ProcessNewRun(Event); fLastRun = runnum; } return AppResult::OK; } //------------------------------------------------------------------------------ AppResult FillStntupleModule::endRun( AbsEvent* aRun ) { return AppResult::OK; } //------------------------------------------------------------------------------ Int_t FillStntupleModule::ProcessNewRun(AbsEvent* event) { // create subdirectory with the name run_xxxxxxxx to store database-type // constants for this run char dir_name[200]; TDirectory* olddir = gDirectory; // AbsEnv* env = AbsEnv::instance(); sprintf(dir_name,"run_%i",env->runNumber()); // make sure that "db" directory exists if (fgFile->GetKey("db") == 0) { fgFile->mkdir("db"); } fgFile->cd("db"); // curent directory - "db" // check if subdirectory for this // run has already been created if (gDirectory->GetKey(dir_name) != 0) return 0; gDirectory->mkdir(dir_name); gDirectory->cd(dir_name); //----------------------------------------------------------------------------- // directory is created, time to store there whatever we need // start from the beam position (note, that we cd'ed into the new directory) //----------------------------------------------------------------------------- TStnDBManager* dbm = TStnDBManager::Instance(); dbm->Write(); gDirectory = olddir; gDirectory->cd(); return 0; } //------------------------------------------------------------------------------ AppResult FillStntupleModule::event(AbsEvent* event) { // it only fills the tree TTree* tree; // TFile* file; TFile* old_file; char line[100]; int rc, run_section; static int old_rs = -1; TIter it(Event()->GetListOfNodes()); while(TStnNode* node = (TStnNode*) it.Next()) { TStnDataBlock* block = node->GetDataBlock(); rc = block->ResolveLinks(event,0); if (rc != 0) { // pass all the messages/warnings // to the error logger TIter it(block->MessageList()); while (TObjString* mess = (TObjString*) it.Next()) { ERRLOG(ELwarning,mess->GetString().Data()) << endmsg; } // and don't forget to delete the // messages after printing them block->MessageList()->Delete(); } } //----------------------------------------------------------------------------- // if we need to close a file and to write a new one, make such a decision here // fgOpenNextFile will be reset by FillStntupleModule after it writes the file //----------------------------------------------------------------------------- run_section = AbsEnv::instance()->sectionNumber(); int mbytes_written = (int) fgFile->GetBytesWritten()/1000000; if (mbytes_written >= fgMaxFileSize) { if (run_section != old_rs) { RootHistModule::fgOpenNextFile = 1; } } //----------------------------------------------------------------------------- // now fill the tree, however before doing it check if the output file is not // too large and it is time to switch to writing a new file //----------------------------------------------------------------------------- if (RootHistModule::fgOpenNextFile) { // open the new file RootHistModule::fgFileNumber++; sprintf(line,"_%i",RootHistModule::fgFileNumber); TString fn = RootHistModule::fgFileName; fn += line; // open new file old_file = RootHistModule::fgFile; RootHistModule::fgFile = new TFile(fn.Data(),"RECREATE"); // and create the tree in it tree = new TTree ("STNTUPLE","STNTUPLE"); // loop over the branches of still // opened fgTree and duplicate them // in `tree' TObjArray* list = fgTree->GetListOfBranches(); TIter it(list); TBranch* input_branch; TBranch* output_branch; TLeafObject* leaf; const char* class_name; const char* input_branch_name; while ((input_branch = (TBranch*) it.Next())) { input_branch_name = input_branch->GetName(); if (strcmp(input_branch->ClassName(),"TBranchElement") == 0) { class_name = ((TBranchElement*)input_branch)->GetClassName(); } else { leaf = (TLeafObject*) ((TBranchObject*)input_branch)->GetLeaf(input_branch_name); class_name = leaf->GetTypeName(); } TStnNode* node = fgEvent->FindNode(input_branch_name); // preserve split level output_branch = tree->Branch(input_branch_name,class_name, node->GetDataBlockAddress(), input_branch->GetBasketSize(), input_branch->GetSplitLevel()); output_branch->SetCompressionLevel(input_branch->GetCompressionLevel()); output_branch->SetAutoDelete(kFALSE); // and also redefine branch in the node node->SetBranch(output_branch); // store calib consts for the last event ProcessNewRun(event); } // close the old file old_file->Write(); delete old_file; // redefine the static variables RootHistModule::fgTree = tree; RootHistModule::fgOpenNextFile = 0; } // and finally fill the tree // this is the first entry in the // new file fgTree->Fill(); old_rs = run_section; return AppResult::OK; }