rivet is hosted by Hepforge, IPPP Durham
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 }