AnalysisHandler.cc
Go to the documentation of this file.
00001 // -*- C++ -*- 00002 #include "Rivet/Config/RivetCommon.hh" 00003 #include "Rivet/AnalysisHandler.hh" 00004 #include "Rivet/Analysis.hh" 00005 #include "Rivet/ParticleName.hh" 00006 #include "Rivet/BeamConstraint.hh" 00007 #include "Rivet/Tools/Logging.hh" 00008 #include "Rivet/Projections/Beam.hh" 00009 00010 namespace Rivet { 00011 00012 00013 namespace { 00014 inline bool cmpAOByPath(const AnalysisObjectPtr a, const AnalysisObjectPtr b) { 00015 return a->path() < b->path(); 00016 } 00017 } 00018 00019 00020 AnalysisHandler::AnalysisHandler(const string& runname) 00021 : _runname(runname), _numEvents(0), 00022 _sumOfWeights(0.0), _xs(NAN), 00023 _initialised(false), _ignoreBeams(false) 00024 {} 00025 00026 AnalysisHandler::~AnalysisHandler() 00027 {} 00028 00029 00030 Log& AnalysisHandler::getLog() const { 00031 return Log::getLog("Rivet.Analysis.Handler"); 00032 } 00033 00034 00035 void AnalysisHandler::init(const GenEvent& ge) { 00036 if (_initialised) 00037 throw UserError("AnalysisHandler::init has already been called: cannot re-initialize!"); 00038 00039 setRunBeams(Rivet::beams(ge)); 00040 MSG_DEBUG("Initialising the analysis handler"); 00041 _numEvents = 0; 00042 _sumOfWeights = 0.0; 00043 00044 // Check that analyses are beam-compatible, and remove those that aren't 00045 const size_t num_anas_requested = analysisNames().size(); 00046 vector<string> anamestodelete; 00047 foreach (const AnaHandle a, _analyses) { 00048 if (!_ignoreBeams && !a->isCompatible(beams())) { 00049 //MSG_DEBUG(a->name() << " requires beams " << a->requiredBeams() << " @ " << a->requiredEnergies() << " GeV"); 00050 anamestodelete.push_back(a->name()); 00051 } 00052 } 00053 foreach (const string& aname, anamestodelete) { 00054 MSG_WARNING("Analysis '" << aname << "' is incompatible with the provided beams: removing"); 00055 removeAnalysis(aname); 00056 } 00057 if (num_anas_requested > 0 && analysisNames().empty()) { 00058 cerr << "All analyses were incompatible with the first event's beams\n" 00059 << "Exiting, since this probably wasn't intentional!" << endl; 00060 exit(1); 00061 } 00062 00063 // Warn if any analysis' status is not unblemished 00064 foreach (const AnaHandle a, analyses()) { 00065 if (toUpper(a->status()) == "PRELIMINARY") { 00066 MSG_WARNING("Analysis '" << a->name() << "' is preliminary: be careful, it may change and/or be renamed!"); 00067 } else if (toUpper(a->status()) == "OBSOLETE") { 00068 MSG_WARNING("Analysis '" << a->name() << "' is obsolete: please update!"); 00069 } else if (toUpper(a->status()).find("UNVALIDATED") != string::npos) { 00070 MSG_WARNING("Analysis '" << a->name() << "' is unvalidated: be careful, it may be broken!"); 00071 } 00072 } 00073 00074 // Initialize the remaining analyses 00075 foreach (AnaHandle a, _analyses) { 00076 MSG_DEBUG("Initialising analysis: " << a->name()); 00077 try { 00078 // Allow projection registration in the init phase onwards 00079 a->_allowProjReg = true; 00080 a->init(); 00081 //MSG_DEBUG("Checking consistency of analysis: " << a->name()); 00082 //a->checkConsistency(); 00083 } catch (const Error& err) { 00084 cerr << "Error in " << a->name() << "::init method: " << err.what() << endl; 00085 exit(1); 00086 } 00087 MSG_DEBUG("Done initialising analysis: " << a->name()); 00088 } 00089 _initialised = true; 00090 MSG_DEBUG("Analysis handler initialised"); 00091 } 00092 00093 00094 void AnalysisHandler::analyze(const GenEvent& ge) { 00095 // Call init with event as template if not already initialised 00096 if (!_initialised) { 00097 init(ge); 00098 } 00099 assert(_initialised); 00100 00101 // Ensure that beam details match those from the first event 00102 const PdgIdPair beams = Rivet::beamIds(ge); 00103 const double sqrts = Rivet::sqrtS(ge); 00104 if (!compatible(beams, _beams) || !fuzzyEquals(sqrts, sqrtS())) { 00105 cerr << "Event beams mismatch: " 00106 << PID::toBeamsString(beams) << " @ " << sqrts/GeV << " GeV" << " vs. first beams " 00107 << this->beams() << " @ " << this->sqrtS()/GeV << " GeV" << endl; 00108 exit(1); 00109 } 00110 00111 // Create the Rivet event wrapper 00112 Event event(ge); 00113 00114 // Weights 00115 /// @todo Drop this / just report first weight when we support multiweight events 00116 _numEvents += 1; 00117 _sumOfWeights += event.weight(); 00118 MSG_DEBUG("Event #" << _numEvents << " weight = " << event.weight()); 00119 00120 // Cross-section 00121 #ifdef HEPMC_HAS_CROSS_SECTION 00122 if (ge.cross_section()) { 00123 _xs = ge.cross_section()->cross_section(); 00124 } 00125 #endif 00126 00127 // Run the analyses 00128 foreach (AnaHandle a, _analyses) { 00129 MSG_TRACE("About to run analysis " << a->name()); 00130 try { 00131 a->analyze(event); 00132 } catch (const Error& err) { 00133 cerr << "Error in " << a->name() << "::analyze method: " << err.what() << endl; 00134 exit(1); 00135 } 00136 MSG_TRACE("Finished running analysis " << a->name()); 00137 } 00138 } 00139 00140 00141 void AnalysisHandler::finalize() { 00142 if (!_initialised) return; 00143 MSG_INFO("Finalising analyses"); 00144 foreach (AnaHandle a, _analyses) { 00145 a->setCrossSection(_xs); 00146 try { 00147 a->finalize(); 00148 } catch (const Error& err) { 00149 cerr << "Error in " << a->name() << "::finalize method: " 00150 << err.what() << endl; 00151 exit(1); 00152 } 00153 } 00154 00155 // Print out number of events processed 00156 MSG_INFO("Processed " << _numEvents << " event" << (_numEvents == 1 ? "" : "s")); 00157 00158 // // Delete analyses 00159 // MSG_DEBUG("Deleting analyses"); 00160 // _analyses.clear(); 00161 00162 // Print out MCnet boilerplate 00163 cout << endl; 00164 cout << "The MCnet usage guidelines apply to Rivet: see http://www.montecarlonet.org/GUIDELINES" << endl; 00165 cout << "Please acknowledge plots made with Rivet analyses, and cite arXiv:1003.0694 (http://arxiv.org/abs/1003.0694)" << endl; 00166 } 00167 00168 00169 AnalysisHandler& AnalysisHandler::addAnalysis(const string& analysisname) { 00170 // Check for a duplicate analysis 00171 /// @todo Might we want to be able to run an analysis twice, with different params? 00172 /// Requires avoiding histo tree clashes, i.e. storing the histos on the analysis objects. 00173 foreach (const AnaHandle& a, _analyses) { 00174 if (a->name() == analysisname) { 00175 MSG_WARNING("Analysis '" << analysisname << "' already registered: skipping duplicate"); 00176 return *this; 00177 } 00178 } 00179 AnaHandle analysis( AnalysisLoader::getAnalysis(analysisname) ); 00180 if (analysis.get() != 0) { // < Check for null analysis. 00181 MSG_DEBUG("Adding analysis '" << analysisname << "'"); 00182 analysis->_analysishandler = this; 00183 _analyses.insert(analysis); 00184 } else { 00185 MSG_WARNING("Analysis '" << analysisname << "' not found."); 00186 } 00187 // MSG_WARNING(_analyses.size()); 00188 // foreach (const AnaHandle& a, _analyses) MSG_WARNING(a->name()); 00189 return *this; 00190 } 00191 00192 00193 AnalysisHandler& AnalysisHandler::removeAnalysis(const string& analysisname) { 00194 shared_ptr<Analysis> toremove; 00195 foreach (const AnaHandle a, _analyses) { 00196 if (a->name() == analysisname) { 00197 toremove = a; 00198 break; 00199 } 00200 } 00201 if (toremove.get() != 0) { 00202 MSG_DEBUG("Removing analysis '" << analysisname << "'"); 00203 _analyses.erase(toremove); 00204 } 00205 return *this; 00206 } 00207 00208 00209 vector<AnalysisObjectPtr> AnalysisHandler::getData() const { 00210 vector<AnalysisObjectPtr> rtn; 00211 foreach (const AnaHandle a, analyses()) { 00212 vector<AnalysisObjectPtr> aos = a->analysisObjects(); 00213 // MSG_WARNING(a->name() << " " << aos.size()); 00214 foreach (const AnalysisObjectPtr ao, aos) { 00215 // Exclude paths starting with /TMP/ from final write-out 00216 /// @todo This needs to be much more nuanced for re-entrant histogramming 00217 if (ao->path().find("/TMP/") != string::npos) continue; 00218 rtn.push_back(ao); 00219 } 00220 } 00221 sort(rtn.begin(), rtn.end(), cmpAOByPath); 00222 return rtn; 00223 } 00224 00225 00226 void AnalysisHandler::writeData(const string& filename) const { 00227 const vector<AnalysisObjectPtr> aos = getData(); 00228 WriterYODA::write(filename, aos.begin(), aos.end()); 00229 } 00230 00231 00232 string AnalysisHandler::runName() const { return _runname; } 00233 size_t AnalysisHandler::numEvents() const { return _numEvents; } 00234 double AnalysisHandler::sumOfWeights() const { return _sumOfWeights; } 00235 00236 00237 void AnalysisHandler::setSumOfWeights(const double& sum) { 00238 _sumOfWeights=sum; 00239 } 00240 00241 00242 std::vector<std::string> AnalysisHandler::analysisNames() const { 00243 std::vector<std::string> rtn; 00244 foreach (AnaHandle a, _analyses) { 00245 rtn.push_back(a->name()); 00246 } 00247 return rtn; 00248 } 00249 00250 00251 AnalysisHandler& AnalysisHandler::addAnalyses(const std::vector<std::string>& analysisnames) { 00252 foreach (const string& aname, analysisnames) { 00253 //MSG_DEBUG("Adding analysis '" << aname << "'"); 00254 addAnalysis(aname); 00255 } 00256 return *this; 00257 } 00258 00259 00260 AnalysisHandler& AnalysisHandler::removeAnalyses(const std::vector<std::string>& analysisnames) { 00261 foreach (const string& aname, analysisnames) { 00262 removeAnalysis(aname); 00263 } 00264 return *this; 00265 } 00266 00267 00268 bool AnalysisHandler::needCrossSection() const { 00269 bool rtn = false; 00270 foreach (const AnaHandle a, _analyses) { 00271 if (!rtn) rtn = a->needsCrossSection(); 00272 if (rtn) break; 00273 } 00274 return rtn; 00275 } 00276 00277 00278 AnalysisHandler& AnalysisHandler::setCrossSection(double xs) { 00279 _xs = xs; 00280 return *this; 00281 } 00282 00283 00284 bool AnalysisHandler::hasCrossSection() const { 00285 return (!std::isnan(crossSection())); 00286 } 00287 00288 00289 AnalysisHandler& AnalysisHandler::addAnalysis(Analysis* analysis) { 00290 analysis->_analysishandler = this; 00291 _analyses.insert(AnaHandle(analysis)); 00292 return *this; 00293 } 00294 00295 00296 PdgIdPair AnalysisHandler::beamIds() const { 00297 return Rivet::beamIds(beams()); 00298 } 00299 00300 00301 double AnalysisHandler::sqrtS() const { 00302 return Rivet::sqrtS(beams()); 00303 } 00304 00305 void AnalysisHandler::setIgnoreBeams(bool ignore) { 00306 _ignoreBeams=ignore; 00307 } 00308 00309 00310 } Generated on Tue Sep 30 2014 19:45:41 for The Rivet MC analysis system by ![]() |