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/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 }