00001
00002 #include "Rivet/Rivet.hh"
00003 #include "Rivet/Tools/Logging.hh"
00004 #include "Rivet/ParticleName.hh"
00005 #include "Rivet/AnalysisHandler.hh"
00006 #include "Rivet/RivetAIDA.hh"
00007 #include "Rivet/Analysis.hh"
00008 #include "Rivet/Event.hh"
00009 #include "Rivet/Projections/Beam.hh"
00010 #include "LWH/AIManagedObject.h"
00011
00012 using namespace AIDA;
00013
00014 namespace Rivet {
00015
00016
00017 AnalysisHandler::AnalysisHandler(const string& runname)
00018 : _runname(runname), _numEvents(0),
00019 _sumOfWeights(0.0), _xs(-1.0),
00020 _initialised(false)
00021 {
00022 _theAnalysisFactory.reset( createAnalysisFactory() );
00023 _setupFactories();
00024 }
00025
00026
00027 AnalysisHandler::AnalysisHandler(const string& basefilename,
00028 const string& runname, HistoFormat storetype)
00029 : _runname(runname), _numEvents(0),
00030 _sumOfWeights(0.0), _xs(-1.0),
00031 _initialised(false)
00032 {
00033 cerr << "AnalysisHandler(basefilename, runname, format) constructor is deprecated: "
00034 << "please migrate your code to use the one-arg constructor" << endl;
00035 _theAnalysisFactory.reset( createAnalysisFactory() );
00036 _setupFactories(basefilename, storetype);
00037 }
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 AnalysisHandler::~AnalysisHandler()
00052 { }
00053
00054
00055 Log& AnalysisHandler::getLog() {
00056 return Log::getLog("Rivet.Analysis.Handler");
00057 }
00058
00059
00060 void AnalysisHandler::init(const GenEvent& ge) {
00061 assert(!_initialised);
00062 setRunBeams(Rivet::beams(ge));
00063 getLog() << Log::DEBUG << "Initialising the analysis handler" << endl;
00064 _numEvents = 0;
00065 _sumOfWeights = 0.0;
00066
00067
00068 const size_t num_anas_requested = analysisNames().size();
00069 removeIncompatibleAnalyses(beamIds());
00070 foreach (const AnaHandle a, analyses()) {
00071 if (toUpper(a->status()) != "VALIDATED") {
00072 getLog() << Log::WARN
00073 << "Analysis '" << a->name() << "' is unvalidated: be careful!" << endl;
00074 }
00075 }
00076 if (num_anas_requested > 0 && analysisNames().size() == 0) {
00077 getLog() << Log::ERROR
00078 << "All analyses were incompatible with the first event's beams\n"
00079 << "Exiting, since this probably isn't intentional!" << endl;
00080 exit(1);
00081 }
00082
00083 foreach (AnaHandle a, _analyses) {
00084 getLog() << Log::DEBUG << "Initialising analysis: " << a->name() << endl;
00085 try {
00086
00087 a->_allowProjReg = true;
00088 a->init();
00089
00090
00091 } catch (const Error& err) {
00092 getLog() << Log::ERROR << "Error in " << a->name() << "::init method: "
00093 << err.what() << endl;
00094 exit(1);
00095 }
00096 getLog() << Log::DEBUG << "Done initialising analysis: " << a->name() << endl;
00097 }
00098 _initialised = true;
00099 getLog() << Log::DEBUG << "Analysis handler initialised" << endl;
00100 }
00101
00102
00103 void AnalysisHandler::analyze(const GenEvent& ge) {
00104
00105 if (!_initialised) {
00106 init(ge);
00107 }
00108
00109 assert(_initialised);
00110
00111 const PdgIdPair beams = Rivet::beamIds(ge);
00112 const double sqrts = Rivet::sqrtS(ge);
00113 if (!compatible(beams, _beams) || !fuzzyEquals(sqrts, sqrtS())) {
00114 getLog() << Log::ERROR << "Event beams mismatch: "
00115 << toBeamsString(beams) << " @ " << sqrts/GeV << " GeV" << " vs. first beams "
00116 << this->beams() << " @ " << this->sqrtS()/GeV << " GeV" << endl;
00117 exit(1);
00118 }
00119
00120
00121 Event event(ge);
00122 _numEvents++;
00123
00124 const double weight = event.weight();
00125 _sumOfWeights += weight;
00126 getLog() << Log::DEBUG << "Event #" << _numEvents << " weight = " << weight << endl;
00127 #ifdef HEPMC_HAS_CROSS_SECTION
00128 if (ge.cross_section()) {
00129 const double xs = ge.cross_section()->cross_section();
00130 setCrossSection(xs);
00131 }
00132 #endif
00133 foreach (AnaHandle a, _analyses) {
00134
00135 try {
00136 a->analyze(event);
00137 } catch (const Error& err) {
00138 getLog() << Log::ERROR << "Error in " << a->name() << "::analyze method: "
00139 << err.what() << endl;
00140 exit(1);
00141 }
00142
00143 }
00144 }
00145
00146
00147 void AnalysisHandler::finalize() {
00148 assert(_initialised);
00149 getLog() << Log::INFO << "Finalising analyses" << endl;
00150 foreach (AnaHandle a, _analyses) {
00151 try {
00152 a->finalize();
00153 } catch (const Error& err) {
00154 getLog() << Log::ERROR << "Error in " << a->name() << "::finalize method: "
00155 << err.what() << endl;
00156 exit(1);
00157 }
00158 }
00159
00160
00161 getLog() << Log::INFO << "Processed " << _numEvents << " event" << (_numEvents == 1 ? "" : "s") << endl;
00162
00163
00164 getLog() << Log::DEBUG << "Converting histograms to scatter plots" << endl;
00165 assert(_theTree != 0);
00166 _normalizeTree(tree());
00167
00168
00169 getLog() << Log::DEBUG << "Deleting analyses" << endl;
00170 _analyses.clear();
00171
00172
00173 cout << endl;
00174 cout << "The MCnet usage guidelines apply to Rivet: see http://www.montecarlonet.org/GUIDELINES" << endl;
00175 cout << "Please acknowledge plots made with Rivet analyses, and cite arXiv:1003.0694 (http://arxiv.org/abs/1003.0694)" << endl;
00176 }
00177
00178
00179 AnalysisHandler& AnalysisHandler::addAnalysis(const string& analysisname) {
00180
00181
00182
00183 foreach (const AnaHandle& a, _analyses) {
00184 if (a->name() == analysisname) {
00185 getLog() << Log::WARNING
00186 << "Analysis '" << analysisname
00187 << "' already registered: skipping duplicate" << endl;
00188 return *this;
00189 }
00190 }
00191 AnaHandle analysis( AnalysisLoader::getAnalysis(analysisname) );
00192 if (analysis.get() != 0) {
00193 getLog() << Log::DEBUG << "Adding analysis '" << analysisname << "'" << endl;
00194 analysis->_analysishandler = this;
00195 _analyses.insert(analysis);
00196 }
00197 else {
00198 getLog() << Log::WARNING
00199 << "Analysis '" << analysisname
00200 << "' not found." << endl;
00201 }
00202 return *this;
00203 }
00204
00205
00206 AnalysisHandler& AnalysisHandler::removeAnalysis(const string& analysisname) {
00207 shared_ptr<Analysis> toremove;
00208 foreach (const AnaHandle a, _analyses) {
00209 if (a->name() == analysisname) {
00210 toremove.reset( a.get() );
00211 break;
00212 }
00213 }
00214 if (toremove.get() != 0) {
00215 getLog() << Log::DEBUG << "Removing analysis '" << analysisname << "'" << endl;
00216 _analyses.erase(toremove);
00217 }
00218 return *this;
00219 }
00220
00221
00222 AnalysisHandler& AnalysisHandler::removeIncompatibleAnalyses(const PdgIdPair& beams) {
00223 vector<string> anamestodelete;
00224 foreach (const AnaHandle a, _analyses) {
00225 if (! a->isCompatible(beams)) {
00226 anamestodelete.push_back(a->name());
00227 }
00228 }
00229 foreach (const string& aname, anamestodelete) {
00230 getLog() << Log::WARN << "Removing incompatible analysis '"
00231 << aname << "'" << endl;
00232 removeAnalysis(aname);
00233 }
00234 return *this;
00235 }
00236
00237
00238 void AnalysisHandler::_setupFactories(const string& basefilename, HistoFormat storetype) {
00239 string filename(basefilename), storetypestr("");
00240 if (storetype == AIDAML) {
00241 if (!endsWith(filename, ".aida")) filename += ".aida";
00242 storetypestr = "xml";
00243 } else if (storetype == FLAT) {
00244 if (!endsWith(filename, ".data")) filename += ".data";
00245 storetypestr = "flat";
00246 } else if (storetype == ROOT) {
00247 if (!endsWith(filename, ".root")) filename += ".root";
00248 storetypestr = "root";
00249 }
00250 _theTreeFactory = _theAnalysisFactory->createTreeFactory();
00251 _theTree = _theTreeFactory->create(filename, storetypestr, false, true);
00252 _theHistogramFactory = _theAnalysisFactory->createHistogramFactory(tree());
00253 _theDataPointSetFactory = _theAnalysisFactory->createDataPointSetFactory(tree());
00254 }
00255
00256
00257 void AnalysisHandler::_setupFactories() {
00258 _theTreeFactory = _theAnalysisFactory->createTreeFactory();
00259 _theTree = _theTreeFactory->create();
00260 _theHistogramFactory = _theAnalysisFactory->createHistogramFactory(tree());
00261 _theDataPointSetFactory = _theAnalysisFactory->createDataPointSetFactory(tree());
00262 }
00263
00264
00265 void AnalysisHandler::commitData() {
00266 tree().commit();
00267 }
00268
00269
00270 void AnalysisHandler::writeData(const string& filename) {
00271 tree().commit(filename);
00272 }
00273
00274
00275 void AnalysisHandler::_normalizeTree(ITree& tree) {
00276 Log& log = getLog();
00277 const vector<string> paths = tree.listObjectNames("/", true);
00278 log << Log::TRACE << "Number of objects in AIDA tree = " << paths.size() << endl;
00279 const string tmpdir = "/RivetNormalizeTmp";
00280 tree.mkdir(tmpdir);
00281 foreach (const string& path, paths) {
00282
00283 IManagedObject* hobj = tree.find(path);
00284 if (hobj) {
00285
00286
00287
00288 IHistogram1D* histo = 0;
00289 IProfile1D* prof = dynamic_cast<IProfile1D*>(hobj);
00290 if (!prof) histo = dynamic_cast<IHistogram1D*>(hobj);
00291
00292
00293 if (histo) {
00294 log << Log::TRACE << "Converting histo " << path << " to DPS" << endl;
00295 tree.mv(path, tmpdir);
00296 const size_t lastslash = path.find_last_of("/");
00297 const string basename = path.substr(lastslash+1, path.length() - (lastslash+1));
00298 const string tmppath = tmpdir + "/" + basename;
00299 IHistogram1D* tmphisto = dynamic_cast<IHistogram1D*>(tree.find(tmppath));
00300 if (tmphisto) {
00301
00302 datapointsetFactory().create(path, *tmphisto);
00303 }
00304 tree.rm(tmppath);
00305 }
00306
00307 else if (prof) {
00308 log << Log::TRACE << "Converting profile histo " << path << " to DPS" << endl;
00309 tree.mv(path, tmpdir);
00310 const size_t lastslash = path.find_last_of("/");
00311 const string basename = path.substr(lastslash+1, path.length() - (lastslash+1));
00312 const string tmppath = tmpdir + "/" + basename;
00313 IProfile1D* tmpprof = dynamic_cast<IProfile1D*>(tree.find(tmppath));
00314 if (tmpprof) {
00315
00316 datapointsetFactory().create(path, *tmpprof);
00317 }
00318 tree.rm(tmppath);
00319 }
00320
00321 }
00322
00323 }
00324 tree.rmdir(tmpdir);
00325 }
00326
00327
00328 string AnalysisHandler::runName() const { return _runname; }
00329 size_t AnalysisHandler::numEvents() const { return _numEvents; }
00330 double AnalysisHandler::sumOfWeights() const { return _sumOfWeights; }
00331
00332
00333 void AnalysisHandler::setSumOfWeights(const double& sum) {
00334 _sumOfWeights=sum;
00335 }
00336
00337
00338 std::vector<std::string> AnalysisHandler::analysisNames() const {
00339 std::vector<std::string> rtn;
00340 foreach (AnaHandle a, _analyses) {
00341 rtn.push_back(a->name());
00342 }
00343 return rtn;
00344 }
00345
00346
00347 AnalysisHandler& AnalysisHandler::addAnalyses(const std::vector<std::string>& analysisnames) {
00348 foreach (const string& aname, analysisnames) {
00349
00350 addAnalysis(aname);
00351 }
00352 return *this;
00353 }
00354
00355
00356 AnalysisHandler& AnalysisHandler::removeAnalyses(const std::vector<std::string>& analysisnames) {
00357 foreach (const string& aname, analysisnames) {
00358 removeAnalysis(aname);
00359 }
00360 return *this;
00361 }
00362
00363
00364
00365 AIDA::IAnalysisFactory& AnalysisHandler::analysisFactory() {
00366 return *_theAnalysisFactory;
00367 }
00368
00369
00370 AIDA::ITree& AnalysisHandler::tree() {
00371 return *_theTree;
00372 }
00373
00374
00375 AIDA::IHistogramFactory& AnalysisHandler::histogramFactory() {
00376 return *_theHistogramFactory;
00377 }
00378
00379
00380 AIDA::IDataPointSetFactory& AnalysisHandler::datapointsetFactory() {
00381 return *_theDataPointSetFactory;
00382 }
00383
00384
00385 bool AnalysisHandler::needCrossSection() const {
00386 bool rtn = false;
00387 foreach (const AnaHandle a, _analyses) {
00388 if (!rtn) rtn = a->needsCrossSection();
00389 if (rtn) break;
00390 }
00391 return rtn;
00392 }
00393
00394
00395 AnalysisHandler& AnalysisHandler::setCrossSection(double xs) {
00396 _xs = xs;
00397 foreach (AnaHandle a, _analyses) {
00398 a->setCrossSection(xs);
00399 }
00400 return *this;
00401 }
00402
00403
00404 bool AnalysisHandler::hasCrossSection() const {
00405 return (crossSection() >= 0);
00406 }
00407
00408
00409 AnalysisHandler& AnalysisHandler::addAnalysis(Analysis* analysis) {
00410 analysis->_analysishandler = this;
00411 _analyses.insert(AnaHandle(analysis));
00412 return *this;
00413 }
00414
00415
00416 PdgIdPair AnalysisHandler::beamIds() const {
00417 return Rivet::beamIds(beams());
00418 }
00419
00420
00421 double AnalysisHandler::sqrtS() const {
00422 return Rivet::sqrtS(beams());
00423 }
00424
00425
00426 }