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/AnalysisHandler.hh"
00005 #include "Rivet/RivetAIDA.hh"
00006 #include "Rivet/Analysis.hh"
00007 #include "Rivet/Event.hh"
00008 #include "Rivet/Projections/Beam.hh"
00009 #include "LWH/AIManagedObject.h"
00010 
00011 using namespace AIDA;
00012 
00013 namespace Rivet {
00014 
00015 
00016   AnalysisHandler::AnalysisHandler(string basefilename,
00017                                    string runname, HistoFormat storetype)
00018     : _runname(runname), _numEvents(0), 
00019       _sumOfWeights(0.0), _xs(-1.0), _initialised(false)
00020   {
00021     _theAnalysisFactory = createAnalysisFactory();
00022     _setupFactories(basefilename, storetype);
00023   }
00024 
00025 
00026   AnalysisHandler::AnalysisHandler(IAnalysisFactory& afac, string basefilename,
00027                                    string runname, HistoFormat storetype)
00028     : _runname(runname), _numEvents(0), 
00029       _sumOfWeights(0.0), _xs(-1.0), _initialised(false), 
00030       _theAnalysisFactory(&afac) 
00031   {
00032     _setupFactories(basefilename, storetype);
00033   }
00034 
00035 
00036   AnalysisHandler::~AnalysisHandler()
00037   {  }
00038 
00039 
00040   Log& AnalysisHandler::getLog() {
00041     return Log::getLog("Rivet.Analysis.Handler");
00042   }
00043 
00044 
00045   void AnalysisHandler::init(const GenEvent& ge) {
00046     assert(!_initialised);
00047     setRunBeams(Rivet::beams(ge));
00048     getLog() << Log::DEBUG << "Initialising the analysis handler" << endl;
00049     _numEvents = 0;
00050     _sumOfWeights = 0.0;
00051     
00052     // Check that analyses are beam-compatible
00053     const size_t num_anas_requested = analysisNames().size();
00054     removeIncompatibleAnalyses(beamIds());
00055     foreach (const Analysis* a, analyses()) {
00056       if (toUpper(a->status()) != "VALIDATED") {
00057         getLog() << Log::WARN 
00058                  << "Analysis '" << a->name() << "' is unvalidated: be careful!" << endl;
00059       }
00060     }
00061     if (num_anas_requested > 0 && analysisNames().size() == 0) {
00062       getLog() << Log::ERROR
00063                << "All analyses were incompatible with the first event's beams\n"
00064                << "Exiting, since this probably isn't intentional!" << endl;
00065       exit(1);
00066     }
00067     
00068     foreach (Analysis* a, _analyses) {
00069       getLog() << Log::DEBUG << "Initialising analysis: " << a->name() << endl;
00070       // Allow projection registration in the init phase onwards
00071       a->_allowProjReg = true;
00072       a->init();
00073       //getLog() << Log::DEBUG << "Checking consistency of analysis: " << a->name() << endl;
00074       //a->checkConsistency();
00075       getLog() << Log::DEBUG << "Done initialising analysis: " << a->name() << endl;
00076     }
00077     _initialised = true;
00078     getLog() << Log::DEBUG << "Analysis handler initialised" << endl;
00079   }
00080 
00081 
00082   void AnalysisHandler::analyze(const GenEvent& ge) {
00083     // Call init with event as template if not already initialised
00084     if (!_initialised) {
00085       init(ge);
00086     }
00087     // Proceed with event analysis
00088     assert(_initialised);
00089     // Ensure that beam details match those from first event
00090     const BeamPair beams = Rivet::beamIds(ge);
00091     const double sqrts = Rivet::sqrtS(ge);
00092     if (!compatible(beams, _beams) || !fuzzyEquals(sqrts, sqrtS())) {
00093       getLog() << Log::ERROR << "Event beams mismatch: "
00094                << beams << " @ " << sqrts/GeV << " GeV" << " vs. first beams "
00095                << this->beams() << " @ " << this->sqrtS()/GeV << " GeV" << endl;
00096       exit(1);
00097     }
00098 
00099     
00100     Event event(ge);
00101     _numEvents++;
00102     // Weights
00103     const double weight = event.weight();
00104     _sumOfWeights += weight;
00105     getLog() << Log::DEBUG << "Event #" << _numEvents << " weight = " << weight << endl;
00106     #ifdef HEPMC_HAS_CROSS_SECTION
00107     if (ge.cross_section()) {
00108       const double xs = ge.cross_section()->cross_section();
00109       setCrossSection(xs);
00110     }
00111     #endif
00112     foreach (Analysis* a, _analyses) {
00113       getLog() << Log::DEBUG << "About to run analysis " << a->name() << endl;
00114       a->analyze(event);
00115       getLog() << Log::DEBUG << "Finished running analysis " << a->name() << endl;
00116     }
00117   }
00118 
00119 
00120   void AnalysisHandler::finalize() {
00121     assert(_initialised);
00122     getLog() << Log::INFO << "Finalising analyses" << endl;
00123     foreach (Analysis* a, _analyses) {
00124       a->finalize();
00125     }
00126 
00127     // Print out number of events processed
00128     getLog() << Log::INFO << "Processed " << _numEvents << " event" << (_numEvents == 1 ? "" : "s") << endl;
00129 
00130     // Change AIDA histos into data point sets
00131     getLog() << Log::DEBUG << "Converting histograms to scatter plots" << endl;
00132     assert(_theTree != 0);
00133     _normalizeTree(tree());
00134 
00135     // Delete analyses
00136     getLog() << Log::DEBUG << "Deleting analyses" << endl;
00137     foreach (Analysis* a, _analyses) {
00138       delete a;
00139     }
00140     _analyses.clear();
00141 
00142     // Print out MCnet boilerplate
00143     cout << endl;
00144     cout << "The MCnet usage guidelines apply to Rivet: see http://www.montecarlonet.org/GUIDELINES" << endl;
00145     cout << "Please acknowledge plots made with Rivet analyses, and cite arXiv:1003.0694 (http://arxiv.org/abs/1003.0694)" << endl;
00146   }
00147 
00148 
00149   AnalysisHandler& AnalysisHandler::addAnalysis(const string& analysisname) {
00150     Analysis* analysis = AnalysisLoader::getAnalysis(analysisname);
00151     if (analysis) { // < Check for null analysis.
00152       getLog() << Log::DEBUG << "Adding analysis '" << analysisname << "'" << endl;
00153       analysis->_analysishandler = this;
00154       _analyses.insert(analysis);
00155     }
00156     return *this;
00157   }
00158 
00159 
00160   AnalysisHandler& AnalysisHandler::removeAnalysis(const string& analysisname) {
00161     Analysis* toremove = 0;
00162     foreach (Analysis* a, _analyses) {
00163       if (a->name() == analysisname) {
00164         toremove = a;
00165         break;
00166       }
00167     }
00168     if (toremove) {
00169       getLog() << Log::DEBUG << "Removing analysis '" << analysisname << "'" << endl;
00170       _analyses.erase(toremove);
00171       delete toremove;
00172     }
00173     return *this;
00174   }
00175 
00176 
00177   AnalysisHandler& AnalysisHandler::removeIncompatibleAnalyses(const BeamPair& beams) {
00178     vector<Analysis*> todelete;
00179     foreach (Analysis* a, _analyses) {
00180       if (! a->isCompatible(beams)) {
00181         todelete.push_back(a);
00182       }
00183     }
00184     foreach (Analysis* a, todelete) {
00185       getLog() << Log::WARN << "Removing incompatible analysis '"
00186                << a->name() << "'" << endl;
00187       _analyses.erase(a);
00188       delete a;
00189     }
00190     return *this;
00191   }
00192 
00193 
00194   void AnalysisHandler::_setupFactories(string basefilename, HistoFormat storetype) {
00195     string filename(basefilename), storetypestr("");
00196     if (storetype == AIDAML) {
00197       if (!endsWith(filename, ".aida")) filename += ".aida";
00198       storetypestr = "xml";
00199     } else if (storetype == FLAT) {
00200       if (!endsWith(filename, ".data")) filename += ".data";
00201       storetypestr = "flat";
00202     } else if (storetype == ROOT) {
00203       if (!endsWith(filename, ".root")) filename += ".root";
00204       storetypestr = "root";
00205     }
00206     _theTree = _theAnalysisFactory->createTreeFactory()->create(filename, storetypestr, false, true);
00207     _theHistogramFactory = _theAnalysisFactory->createHistogramFactory(tree());
00208     _theDataPointSetFactory = _theAnalysisFactory->createDataPointSetFactory(tree());
00209   }
00210 
00211 
00212   void AnalysisHandler::commitData() {
00213     tree().commit();
00214   }
00215 
00216 
00217   void AnalysisHandler::_normalizeTree(ITree& tree) {
00218     Log& log = getLog();
00219     const vector<string> paths = tree.listObjectNames("/", true); // args set recursive listing
00220     log << Log::TRACE << "Number of objects in AIDA tree = " << paths.size() << endl;
00221     const string tmpdir = "/RivetNormalizeTmp";
00222     tree.mkdir(tmpdir);
00223     foreach (const string& path, paths) {
00224    
00225       IManagedObject* hobj = tree.find(path);
00226       if (hobj) {
00227         
00228         // Weird seg fault on SLC4 when trying to dyn cast an IProfile ptr to a IHistogram
00229         // Fix by attempting to cast to IProfile first, only try IHistogram if it fails.
00230         IHistogram1D *histo = 0;
00231         IProfile1D* prof = dynamic_cast<IProfile1D*>(hobj);
00232         if(!prof) histo = dynamic_cast<IHistogram1D*>(hobj);
00233         
00234         // If it's a normal histo:
00235         if (histo) {
00236           log << Log::TRACE << "Converting histo " << path << " to DPS" << endl;
00237           tree.mv(path, tmpdir);
00238           const size_t lastslash = path.find_last_of("/");
00239           const string basename = path.substr(lastslash+1, path.length() - (lastslash+1));
00240           const string tmppath = tmpdir + "/" + basename;
00241           IHistogram1D* tmphisto = dynamic_cast<IHistogram1D*>(tree.find(tmppath));
00242           if (tmphisto) {
00243             //getLog() << Log::TRACE << "Temp histo " << tmppath << " exists" << endl;
00244             datapointsetFactory().create(path, *tmphisto);
00245           }
00246           tree.rm(tmppath);
00247         }
00248         // If it's a profile histo:
00249         else if (prof) {
00250           log << Log::TRACE << "Converting profile histo " << path << " to DPS" << endl;
00251           tree.mv(path, tmpdir);
00252           const size_t lastslash = path.find_last_of("/");
00253           const string basename = path.substr(lastslash+1, path.length() - (lastslash+1));
00254           const string tmppath = tmpdir + "/" + basename;
00255           IProfile1D* tmpprof = dynamic_cast<IProfile1D*>(tree.find(tmppath));
00256           if (tmpprof) {
00257             //getLog() << Log::TRACE << "Temp profile histo " << tmppath << " exists" << endl;
00258             datapointsetFactory().create(path, *tmpprof);
00259           }
00260           tree.rm(tmppath);
00261         }
00262 
00263       }
00264    
00265     }
00266     tree.rmdir(tmpdir);
00267   }
00268 
00269 
00270   string AnalysisHandler::runName() const { return _runname; }
00271   size_t AnalysisHandler::numEvents() const { return _numEvents; }
00272   double AnalysisHandler::sumOfWeights() const { return _sumOfWeights; }
00273 
00274   void AnalysisHandler::setSumOfWeights(const double& sum) {
00275     _sumOfWeights=sum;
00276   }
00277 
00278 
00279   std::vector<std::string> AnalysisHandler::analysisNames() const {
00280     std::vector<std::string> rtn;
00281     foreach (Analysis* a, _analyses) {
00282       rtn.push_back(a->name());
00283     }
00284     return rtn;
00285   }
00286 
00287 
00288   AnalysisHandler& AnalysisHandler::addAnalyses(const std::vector<std::string>& analysisnames) {
00289     foreach (const string& aname, analysisnames) {
00290       //getLog() << Log::DEBUG << "Adding analysis '" << aname << "'" << endl;
00291       addAnalysis(aname);
00292     }
00293     return *this;
00294   }
00295 
00296 
00297   AnalysisHandler& AnalysisHandler::removeAnalyses(const std::vector<std::string>& analysisnames) {
00298     foreach (const string& aname, analysisnames) {
00299       removeAnalysis(aname);
00300     }
00301     return *this;
00302   }
00303 
00304 
00305 
00306   AIDA::IAnalysisFactory& AnalysisHandler::analysisFactory() {
00307     return *_theAnalysisFactory;
00308   }
00309 
00310 
00311   AIDA::ITree& AnalysisHandler::tree() {
00312     return *_theTree;
00313   }
00314 
00315 
00316   AIDA::IHistogramFactory& AnalysisHandler::histogramFactory() {
00317     return *_theHistogramFactory;
00318   }
00319 
00320 
00321   AIDA::IDataPointSetFactory& AnalysisHandler::datapointsetFactory() {
00322     return *_theDataPointSetFactory;
00323   }
00324 
00325 
00326   bool AnalysisHandler::needCrossSection() const {
00327     bool rtn = false;
00328     foreach (const Analysis* a, _analyses) {
00329       if (!rtn) rtn = a->needsCrossSection();
00330       if (rtn) break;
00331     }
00332     return rtn;
00333   }
00334 
00335 
00336   AnalysisHandler& AnalysisHandler::setCrossSection(double xs) {
00337     _xs = xs;
00338     foreach (Analysis* a, _analyses) {
00339       a->setCrossSection(xs);
00340     }
00341     return *this;
00342   }
00343 
00344 
00345   bool AnalysisHandler::hasCrossSection() const {
00346     return (crossSection() >= 0);
00347   }
00348 
00349   AnalysisHandler& AnalysisHandler::addAnalysis(Analysis* analysis) {
00350     analysis->_analysishandler = this;
00351     _analyses.insert(analysis);
00352     return *this;
00353   }
00354 
00355   BeamPair AnalysisHandler::beamIds() const { 
00356     return Rivet::beamIds(beams());
00357   }
00358 
00359   double AnalysisHandler::sqrtS() const {
00360     return Rivet::sqrtS(beams());
00361   }
00362 
00363 
00364 }