#include #include #include #include #include #include #include #include #include #include "IAnalysisLoop.hxx" #include "IAnalysisModuleBase.hxx" #include "IBasicHeaderModule.hxx" #include "IBasicDataQualityModule.hxx" #include "ITruthVerticesModule.hxx" #include "ITruthTrajectoriesModule.hxx" #include "IP0DReconModule.hxx" #include "ITrackerReconECalModule.hxx" #include "ITrackerECALPi0ReconModule.hxx" #include "IGlobalReconModule.hxx" #include "IGlobalReconModuleP6.hxx" #include "IECALTestbeamModule.hxx" #include "ILowLevelInfoModule.hxx" #include "IReconSMRDModule.hxx" #include "IFgdOnlyModule.hxx" #include "IBeamSummaryDataModule.hxx" #include "IReconTrackerModule.hxx" #include "IP0DReconECalModule.hxx" #include "IReconPerformanceEvalModule.hxx" #include "ICOMETInput.hxx" #include "IGeometrySummaryModule.hxx" // set the environment variable // CMTEXTRATAGS to OAANALYSIS_WITHOUT_RECON_CALIB // to avoid modules which depend on CalibGlobal and ReconGlobal etc #ifndef OAANALYSIS_WITHOUT_RECON_CALIB #include "IExample2010aAnalysis1Module.hxx" #endif // OAANALYSIS_WITHOUT_RECON_CALIB /// Initialize any class specific variables, but most of the work can be /// done in Initialize. Don't create histograms here! COMET::IAnalysisLoop::IAnalysisLoop() : fEventCount(0), fSaveOriginalFullEvent(false), fSaveOutputOaEventTree(false), fDisableAll(false), fEnableAll(false), fProduction(false), fExit(false){ fAnalysisModules.push_back(new COMET::IBasicHeaderModule); fAnalysisModules.push_back(new COMET::IBasicDataQualityModule); fAnalysisModules.push_back(new COMET::ITruthTrajectoriesModule); fAnalysisModules.push_back(new COMET::ITruthVerticesModule); fAnalysisModules.push_back(new COMET::IP0DReconModule); fAnalysisModules.push_back(new COMET::IP0DReconECalModule); fAnalysisModules.push_back(new COMET::ITrackerReconECalModule); fAnalysisModules.push_back(new COMET::ITrackerECALPi0ReconModule); fAnalysisModules.push_back(new COMET::IGlobalReconModule); fAnalysisModules.push_back(new COMET::IGlobalReconModuleP6); fAnalysisModules.push_back(new COMET::IReconTrackerModule); fAnalysisModules.push_back(new COMET::IECALTestbeamModule); fAnalysisModules.push_back(new COMET::IReconSMRDModule); fAnalysisModules.push_back(new COMET::ILowLevelInfoModule); fAnalysisModules.push_back(new COMET::IFgdOnlyModule); fAnalysisModules.push_back(new COMET::IBeamSummaryDataModule); fAnalysisModules.push_back(new COMET::IReconPerformanceEvalModule); #ifndef OAANALYSIS_WITHOUT_RECON_CALIB fAnalysisModules.push_back(new COMET::IExample2010aAnalysis1Module); #endif // OAANALYSIS_WITHOUT_RECON_CALIB fAnalysisModules.push_back(new COMET::IGeometrySummaryModule); // Save pointer to these modules; this has to be done, because we // no longer have access to the input file pointer, except in BeginFile. fGRooTracker = new COMET::IGRooTrackerVtxModule(); fAnalysisModules.push_back(fGRooTracker); fNRooTracker = new COMET::INRooTrackerVtxModule(); fAnalysisModules.push_back(fNRooTracker); // Set defaults for enabling or disabling modules. this->SetModuleDefaults(); } COMET::IAnalysisLoop::~IAnalysisLoop() { } /// Print a usage message. This is generally called when there is a /// command line input error. void COMET::IAnalysisLoop::Usage(void) { std::cout << " -O inputdir= Set an input directory where the modules " " can pick up non-comet files. For example use this if you need to " " recover pass-through information from a given directory" << std::endl; std::cout << " -O enable= Enable a particular module (overrides all other disable/enable)" << std::endl; std::cout << " -O disable= Disable a particular module (overrides disable/enable all)" << std::endl; std::cout << " -O enable=all Enable all modules (overrides disable all)" << std::endl; std::cout << " -O disable=all Disable all modules" << std::endl; std::cout << " -O preselection= Use module to output pre-selected"< Configure module" << std::endl; std::cout << " (for example. -O ITruthTrajectoriesModule=saveall)" << std::endl; std::cout << " Available module class names are:" << std::endl; for(std::list::iterator m = fAnalysisModules.begin(); m != fAnalysisModules.end(); ++m) { std::string className((*m)->ClassName()); className.replace(className.find("COMET::"), 4, ""); // remove the "COMET::" std::cout<<" "< // [Yoshi todo] writegeometry } /// Set an option and return true if it is valid. This is called by the /// event loop command line argument processing code for each "-O /// [name]=[value]" option found on the command line. If the command line /// has "-O [name]" without a value, then the value string will be equal /// to "". This must return false if the option was not correctly /// processed. /// Any -O name=value options where name is not explicitly given here will /// be checked against all the modules, and the value sent to module::Configure() /// in the case of a match. bool COMET::IAnalysisLoop::SetOption(std::string option,std::string value) { if (option == "production"){ COMETLog("IAnalysisLoop: Running in production mode"); fProduction = true; return true; } if (option == "disable" && value == "all"){ COMETInfo("IAnalysisLoop: " << value); COMETLog("IAnalysisLoop: Disabling all modules due to user command line option"); fDisableAll = true; return true; } if (option == "enable" && value == "all"){ COMETInfo("IAnalysisLoop: " << value); COMETLog("IAnalysisLoop: Enabling all modules due to user command line option "<< "(takes precedence over the disable=all option)"); fEnableAll = true; return true; } if (option == "disable" || option == "enable" || option == "preselection") { for(std::list::iterator m = fAnalysisModules.begin(); m != fAnalysisModules.end(); ++m) { std::string className((*m)->ClassName()); className.replace(className.find("COMET::"), 4, ""); // remove the "COMET::" if (value == className) { if(option == "disable"){ COMETInfo("IAnalysisLoop: " << value); COMETLog("IAnalysisLoop: Disabling module " << value << " due to user cmd line option "<< "(takes precedence over disable/enable all options)"); // Enabling takes precedence over disabling so only set to // false if not already set to true. if(fUserEnabled.find(className) == fUserEnabled.end()){ fUserEnabled[className] = false; } } else if(option == "enable"){ COMETInfo("IAnalysisLoop: " << value); COMETLog("IAnalysisLoop: Enabling module " << value << " due to user cmd line option "<< "(takes precedence over disable/enable all and disable=ModuleName options)"); // Enabling takes precedence over disabling. fUserEnabled[className] = true; } else if(option == "preselection"){ COMETInfo("IAnalysisLoop: " << value); COMETLog("IAnalysisLoop: Enabling module " << value << ", and using it for \n\ oaEvent output preselection, due to user cmd line option (takes precedence over all disable/enable module options) "); (*m)->SetEnabled(); (*m)->SetUsedForPreselection(); fSaveOutputOaEventTree = true; } return true; } } COMETInfo("IAnalysisLoop: Module name " << value << " does not match any module.\n\ This is most likely fine, but it could be a typing error"<< std::endl); return true; } else if (option == "save") { fSaveOriginalFullEvent = true; fSaveOutputOaEventTree = true; } // Add the input directory to all the modules. else if (option == "inputdir"){ void * dir = gSystem->OpenDirectory(value.c_str()); if(dir != NULL){ for(std::list::iterator m = fAnalysisModules.begin(); m != fAnalysisModules.end(); ++m) { (*m)->SetInputDirectory(value); } return true; } COMETError("Unable to open specified input directory: "<< value.c_str() << " so not setting this option!"); return false; } else { // for options of the type ITruthTrajectoriesModule=SaveAll // Test if the option name is that of a module for(std::list::iterator m = fAnalysisModules.begin(); m != fAnalysisModules.end(); ++m) { std::string className((*m)->ClassName()); className.replace(className.find("COMET::"), 4, ""); // remove the "COMET::" if (option == className) { return (*m)->Configure(value); // true if value was recognised by the module } } return false; } return false; // should never get here } /// Called for each event inside the event loop, and returns true if the /// event should be saved to the output file. If the remainder of the /// current file should be skipped, this should through the /// ENextEventLoopFile exception. bool COMET::IAnalysisLoop::operator () (COMET::ICOMETEvent& event) { if ((++fEventCount % 100) == 1) { COMETInfo("## Processed Events " << fEventCount); } // Need to make sure we can get geoemtry before going through analysis modules. COMET::IOADatabase::Get().Geometry(); bool saveThisFullOaEvent = false; std::list::iterator rooModIter; for(std::list::iterator modIter = fAnalysisModules.begin(); modIter != fAnalysisModules.end(); modIter++) { rooModIter = modIter; COMET::IAnalysisModuleBase *mod = *modIter; if(mod->IsEnabled()) { COMETVerbose("Processing with mod" << mod->GetName()); bool noPassThrough = false; try { if(fEventCount == 1) { // As a special case, call ProcessFirstEvent() for the first event. // This is a good time to save persistent quantities in modules' // data members, which will be retrievable from the oaAnalysis output // file. // Not intended for filling in the tree with the first event, as // Process() will also be called. mod->ProcessFirstEvent(event); } // Call the module's own Process, passing it the event. If returns true // and module is selected for preselection then save original comet // event as well as the output analysis trees. saveThisFullOaEvent = mod->Process(event) && mod->IsUsedForPreselection(); } catch (COMET::EDataFile &ex) { COMETVerbose("Analysing data file therefore will disable Monte Carlo module: " << mod->GetName()<<" module"); mod->SetDisabled(); continue; } catch (COMET::ENoKinematicsPassThroughTrees &ex) { noPassThrough = true; } catch (COMET::EIncorrectInputGenerator &ex) { noPassThrough = true; } catch(std::exception &ex) { COMETError(ex.what()); COMETError("#### Disabling module "<GetName()); if(fProduction){ fExit = true; COMETError("oaAnalysis is running in production mode and has caught an exception so will exit"); } mod->SetDisabled(); continue; } catch (...) { COMETError("#### Disabling module "<GetName()); if(fProduction){ fExit = true; COMETError("oaAnalysis is running in production mode and has caught an exception so will exit"); } mod->SetDisabled(); continue; } if(noPassThrough) { const char* foundRooModule = strstr(mod->GetName(), "GRoo"); if(foundRooModule != NULL) { ++rooModIter; } else { --rooModIter; } if((*rooModIter)->IsEnabled()) { COMETVerbose("No neutrino interaction pass-through information found for the " << mod->GetName() << " module, so it will be disabled"); mod->SetDisabled(); } else { COMETError("No pass through information could be found from the neutrino generators. Both RooTracker modules have therefore been disabled so no generator information will be available in the oaAnalysis file."); if(fProduction){ fExit = true; COMETError("No pass through information has been found for this MC file and oaAnalysis is running in production mode, so will exit"); } mod->SetDisabled(); } continue; } } } if(fExit){ throw EProductionException(); } if(saveThisFullOaEvent || fSaveOriginalFullEvent){ return true; } else { return false; } } /// Called after the arguments are processes by before reading the first /// event. The output file is open so any histograms will be added to the /// output file. void COMET::IAnalysisLoop::Initialize(void) { // Check that the output file is writable first if(!gFile) { COMETError("#### Output file not specified. Please use the -o filename option"); exit(1); } // Override default enable/disable based on usr cmd line options. for(std::list::iterator m=fAnalysisModules.begin(); m != fAnalysisModules.end(); ++m) { std::string className((*m)->ClassName()); className.replace(className.find("COMET::"), 4, ""); // remove the "COMET::" // Ignore enable/disable options if selected for preselection. if(!(*m)->IsUsedForPreselection()){ if(fDisableAll) (*m)->SetDisabled(); // Overrides default values. if(fEnableAll) (*m)->SetEnabled(); // Overrides disable all. if(fUserEnabled.find(className) != fUserEnabled.end()){ // Override enable/disable all. if(fUserEnabled.find(className)->second == true) (*m)->SetEnabled(); else (*m)->SetDisabled(); } } } // Move modules with fIsUsedForPreselection set to the end of the // fAnalysisModules list for(std::list::reverse_iterator m = fAnalysisModules.rbegin(); m != fAnalysisModules.rend(); ++m) { if((*m)->IsUsedForPreselection()){ fAnalysisModules.push_back(*m); fAnalysisModules.erase(--m.base()); } } // Print list of modules for(std::list::iterator m = fAnalysisModules.begin(); m != fAnalysisModules.end(); ++m) { (*m)->Print(); } for(std::list::iterator modIter = fAnalysisModules.begin(); modIter != fAnalysisModules.end(); ++modIter) { COMET::IAnalysisModuleBase *mod = *modIter; // if(mod->IsEnabled()) { // Ask the modules to fill the appropriate directory std::string dirname = mod->GetDirectoryName(); gFile->cd("/"); gDirectory->cd("/"); if(gFile && !gFile->GetDirectory(dirname.c_str())) { COMETVerbose("Making "<mkdir(dirname.c_str()); gDirectory->cd(dirname.c_str()); gDirectory->ls(); gDirectory->mkdir("Modules"); gDirectory->cd("/"); } if(mod->IsEnabled()) { gDirectory->cd(dirname.c_str()); try { // Call the module's own Initialize, passing it its own tree mod->Initialize(new TTree(mod->GetName(), mod->GetTitle())); } catch (std::exception &ex) { COMETError(ex.what()); COMETError("### Disabling module (unable to initialise) "<GetName()); mod->SetDisabled(); continue; } catch (...) { COMETError("### Disabling module (unable to initialise) "<GetName()); mod->SetDisabled(); continue; } } } // [Yoshi todo] add catalogue keyfile output // std::ifstream keyfile(fKeyFilename.c_str()); // TObjString KeyFile; // KeyFile.String().ReadFile(keyfile); // KeyFile.Write("CatalogueKey"); // keyfile.close(); } /// Called before the first event of a file is read, but you should prefer /// Initialize() for general initialization. This method will be called /// once for each input file. void COMET::IAnalysisLoop::BeginFile(COMET::IVInputFile *vinput) { COMETLog("Begin reading input file"); COMET::ICOMETInput *input = dynamic_cast(vinput); if(input){ std::cout << "successful cast!" << std::endl; TFile* file = input->GetFilePointer(); if(file){ std::cout << "Setting file..." << std::endl; fGRooTracker->SetBeginFile(file); fNRooTracker->SetBeginFile(file); } } } /// Called after the last event of a file is read, but you should prefer /// Finalize() for general finalization. This method will be called once /// for each input file. void COMET::IAnalysisLoop::EndFile(COMET::IVInputFile *) {} /// Called after reading the last event. The output file is still open, /// so you can add extra information. Because of an idiosyncrasy in the /// way root handles histograms, objects created in Initialize() will /// already be stored in the output file. void COMET::IAnalysisLoop::Finalize(COMET::ICOMETOutput* const output) { // Write geometry if needed // Write a version of the analysis utils to avoid errors when // compiling AnalysisTools which use definition from COMET::IoaAnalysisUtils. COMET::IoaAnalysisUtils * utils = new IoaAnalysisUtils(); std::string utilsdir("UtilsDir"); output->mkdir(utilsdir.c_str()); output->cd(utilsdir.c_str()); utils->Write("Utils"); // Write module itself inside [Header|Truth|Recon]Dir/Modules/ for(std::list::iterator modIter = fAnalysisModules.begin(); modIter != fAnalysisModules.end(); ++modIter) { COMET::IAnalysisModuleBase *mod = *modIter; // For now save a copy of each intance of a module even if it disabled.. // if(/*mod->IsEnabled()*/true) { // Write the modules themselves in the Module directory. std::string moduledir("/"); moduledir += mod->GetDirectoryName(); moduledir += "/Modules"; COMETLog("ModulesDir: "<cd(moduledir.c_str())){ if(output->cd(moduledir.c_str())==false) output->mkdir(moduledir.c_str()); // I'd rather not change the name, but the browser gets // confused if the module has the same name as the tree.... std::string moduleName(mod->GetName()); moduleName += "Mod"; mod->Write(moduleName.c_str()); COMETLog("Saved module as "<IsEnabled() == false) { // Delete the output tree if the module is disabled std::string dirname = mod->GetDirectoryName(); output->cd("/"); gDirectory->cd(dirname.c_str()); gDirectory->Delete(TString(mod->GetName()) + ";*"); } // Call the modules destructor to clean up memory resident objects so they // are not saved in the output file. For some reason std::list::clear() does // not call the destructors so doing it explicitly. delete (*modIter); } COMETLog("Total number of events processed in Analysis Format: "<cd("//"); if(!fSaveOutputOaEventTree){ output->Delete("COMETEvents;*"); } } // // Called just before setting user options so that modules start off with // default enabled/disabled option. void COMET::IAnalysisLoop::SetModuleDefaults(){ for(std::list::iterator m=fAnalysisModules.begin(); m != fAnalysisModules.end(); ++m) { //COMETLog("IAnalysisLoop: Setting default enabled = " << // (*m)->IsEnabledByDefault() << " for module "<< (*m)->ClassName()); (*m)->SetEnabled((*m)->IsEnabledByDefault()); } }