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