00001
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
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
00071 a->_allowProjReg = true;
00072 a->init();
00073
00074
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
00084 if (!_initialised) {
00085 init(ge);
00086 }
00087
00088 assert(_initialised);
00089
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
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
00128 getLog() << Log::INFO << "Processed " << _numEvents << " event" << (_numEvents == 1 ? "" : "s") << endl;
00129
00130
00131 getLog() << Log::DEBUG << "Converting histograms to scatter plots" << endl;
00132 assert(_theTree != 0);
00133 _normalizeTree(tree());
00134
00135
00136 getLog() << Log::DEBUG << "Deleting analyses" << endl;
00137 foreach (Analysis* a, _analyses) {
00138 delete a;
00139 }
00140 _analyses.clear();
00141
00142
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) {
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);
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
00229
00230 IHistogram1D *histo = 0;
00231 IProfile1D* prof = dynamic_cast<IProfile1D*>(hobj);
00232 if(!prof) histo = dynamic_cast<IHistogram1D*>(hobj);
00233
00234
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
00244 datapointsetFactory().create(path, *tmphisto);
00245 }
00246 tree.rm(tmppath);
00247 }
00248
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
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
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 }