AnalysisHandler.cc
Go to the documentation of this file.
00001 // -*- C++ -*- 00002 #include "Rivet/Rivet.hh" 00003 #include "Rivet/Tools/Logging.hh" 00004 #include "Rivet/ParticleName.hh" 00005 #include "Rivet/AnalysisHandler.hh" 00006 #include "Rivet/RivetYODA.hh" 00007 #include "Rivet/Analysis.hh" 00008 #include "Rivet/Event.hh" 00009 #include "Rivet/Projections/Beam.hh" 00010 00011 namespace { 00012 bool AOSortByPath(const Rivet::AnalysisObjectPtr a, 00013 const Rivet::AnalysisObjectPtr b) { 00014 return a->path() < b->path(); 00015 } 00016 } 00017 00018 00019 namespace Rivet { 00020 00021 00022 AnalysisHandler::AnalysisHandler(const string& runname) 00023 : _runname(runname), _numEvents(0), 00024 _sumOfWeights(0.0), _xs(-1.0), 00025 _initialised(false), _ignoreBeams(false) 00026 {} 00027 00028 AnalysisHandler::~AnalysisHandler() 00029 {} 00030 00031 00032 Log& AnalysisHandler::getLog() const { 00033 return Log::getLog("Rivet.Analysis.Handler"); 00034 } 00035 00036 00037 void AnalysisHandler::init(const GenEvent& ge) { 00038 assert(!_initialised); 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 ((!a->isCompatible(beams())) && (!_ignoreBeams)) { 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().size() == 0) { 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 // Proceed with event analysis 00100 assert(_initialised); 00101 // Ensure that beam details match those from 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 << toBeamsString(beams) << " @ " << sqrts/GeV << " GeV" << " vs. first beams " 00107 << this->beams() << " @ " << this->sqrtS()/GeV << " GeV" << endl; 00108 exit(1); 00109 } 00110 00111 00112 Event event(ge); 00113 _numEvents++; 00114 // Weights 00115 const double weight = event.weight(); 00116 _sumOfWeights += weight; 00117 MSG_DEBUG("Event #" << _numEvents << " weight = " << weight); 00118 #ifdef HEPMC_HAS_CROSS_SECTION 00119 if (ge.cross_section()) { 00120 const double xs = ge.cross_section()->cross_section(); 00121 setCrossSection(xs); 00122 } 00123 #endif 00124 foreach (AnaHandle a, _analyses) { 00125 //MSG_DEBUG("About to run analysis " << a->name()); 00126 try { 00127 a->analyze(event); 00128 } catch (const Error& err) { 00129 cerr << "Error in " << a->name() << "::analyze method: " 00130 << err.what() << endl; 00131 exit(1); 00132 } 00133 //MSG_DEBUG("Finished running analysis " << a->name()); 00134 } 00135 } 00136 00137 00138 void AnalysisHandler::finalize() { 00139 assert(_initialised); 00140 MSG_INFO("Finalising analyses"); 00141 foreach (AnaHandle a, _analyses) { 00142 try { 00143 a->finalize(); 00144 } catch (const Error& err) { 00145 cerr << "Error in " << a->name() << "::finalize method: " 00146 << err.what() << endl; 00147 exit(1); 00148 } 00149 } 00150 00151 // Print out number of events processed 00152 MSG_INFO("Processed " << _numEvents << " event" << (_numEvents == 1 ? "" : "s")); 00153 00154 // // Delete analyses 00155 // MSG_DEBUG("Deleting analyses"); 00156 // _analyses.clear(); 00157 00158 // Print out MCnet boilerplate 00159 cout << endl; 00160 cout << "The MCnet usage guidelines apply to Rivet: see http://www.montecarlonet.org/GUIDELINES" << endl; 00161 cout << "Please acknowledge plots made with Rivet analyses, and cite arXiv:1003.0694 (http://arxiv.org/abs/1003.0694)" << endl; 00162 } 00163 00164 00165 AnalysisHandler& AnalysisHandler::addAnalysis(const string& analysisname) { 00166 // Check for a duplicate analysis 00167 /// @todo Might we want to be able to run an analysis twice, with different params? 00168 /// Requires avoiding histo tree clashes, i.e. storing the histos on the analysis objects. 00169 foreach (const AnaHandle& a, _analyses) { 00170 if (a->name() == analysisname) { 00171 MSG_WARNING("Analysis '" << analysisname << "' already registered: skipping duplicate"); 00172 return *this; 00173 } 00174 } 00175 AnaHandle analysis( AnalysisLoader::getAnalysis(analysisname) ); 00176 if (analysis.get() != 0) { // < Check for null analysis. 00177 MSG_DEBUG("Adding analysis '" << analysisname << "'"); 00178 analysis->_analysishandler = this; 00179 _analyses.insert(analysis); 00180 } else { 00181 MSG_WARNING("Analysis '" << analysisname << "' not found."); 00182 } 00183 return *this; 00184 } 00185 00186 00187 AnalysisHandler& AnalysisHandler::removeAnalysis(const string& analysisname) { 00188 shared_ptr<Analysis> toremove; 00189 foreach (const AnaHandle a, _analyses) { 00190 if (a->name() == analysisname) { 00191 toremove = a; 00192 break; 00193 } 00194 } 00195 if (toremove.get() != 0) { 00196 MSG_DEBUG("Removing analysis '" << analysisname << "'"); 00197 _analyses.erase(toremove); 00198 } 00199 return *this; 00200 } 00201 00202 void AnalysisHandler::writeData(const string& filename) { 00203 vector<AnalysisObjectPtr> allPlots; 00204 foreach (const AnaHandle a, _analyses) { 00205 vector<AnalysisObjectPtr> plots = a->plots(); 00206 sort(plots.begin(), plots.end(), AOSortByPath); 00207 allPlots.insert(allPlots.end(), plots.begin(), plots.end()); 00208 } 00209 WriterYODA::write(filename, allPlots.begin(), allPlots.end()); 00210 } 00211 00212 00213 string AnalysisHandler::runName() const { return _runname; } 00214 size_t AnalysisHandler::numEvents() const { return _numEvents; } 00215 double AnalysisHandler::sumOfWeights() const { return _sumOfWeights; } 00216 00217 00218 void AnalysisHandler::setSumOfWeights(const double& sum) { 00219 _sumOfWeights=sum; 00220 } 00221 00222 00223 std::vector<std::string> AnalysisHandler::analysisNames() const { 00224 std::vector<std::string> rtn; 00225 foreach (AnaHandle a, _analyses) { 00226 rtn.push_back(a->name()); 00227 } 00228 return rtn; 00229 } 00230 00231 00232 AnalysisHandler& AnalysisHandler::addAnalyses(const std::vector<std::string>& analysisnames) { 00233 foreach (const string& aname, analysisnames) { 00234 //MSG_DEBUG("Adding analysis '" << aname << "'"); 00235 addAnalysis(aname); 00236 } 00237 return *this; 00238 } 00239 00240 00241 AnalysisHandler& AnalysisHandler::removeAnalyses(const std::vector<std::string>& analysisnames) { 00242 foreach (const string& aname, analysisnames) { 00243 removeAnalysis(aname); 00244 } 00245 return *this; 00246 } 00247 00248 00249 bool AnalysisHandler::needCrossSection() const { 00250 bool rtn = false; 00251 foreach (const AnaHandle a, _analyses) { 00252 if (!rtn) rtn = a->needsCrossSection(); 00253 if (rtn) break; 00254 } 00255 return rtn; 00256 } 00257 00258 00259 AnalysisHandler& AnalysisHandler::setCrossSection(double xs) { 00260 _xs = xs; 00261 foreach (AnaHandle a, _analyses) { 00262 a->setCrossSection(xs); 00263 } 00264 return *this; 00265 } 00266 00267 00268 bool AnalysisHandler::hasCrossSection() const { 00269 return (!std::isnan(crossSection())); 00270 } 00271 00272 00273 AnalysisHandler& AnalysisHandler::addAnalysis(Analysis* analysis) { 00274 analysis->_analysishandler = this; 00275 _analyses.insert(AnaHandle(analysis)); 00276 return *this; 00277 } 00278 00279 00280 PdgIdPair AnalysisHandler::beamIds() const { 00281 return Rivet::beamIds(beams()); 00282 } 00283 00284 00285 double AnalysisHandler::sqrtS() const { 00286 return Rivet::sqrtS(beams()); 00287 } 00288 00289 void AnalysisHandler::setIgnoreBeams(bool ignore) { 00290 _ignoreBeams=ignore; 00291 } 00292 00293 00294 } Generated on Fri Dec 21 2012 15:03:38 for The Rivet MC analysis system by ![]() |