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 << "Analysis '" << analysisname << "' already registered: skipping duplicate" << endl;
00186 return *this;
00187 }
00188 }
00189 AnaHandle analysis( AnalysisLoader::getAnalysis(analysisname) );
00190 if (analysis.get() != 0) {
00191 getLog() << Log::DEBUG << "Adding analysis '" << analysisname << "'" << endl;
00192 analysis->_analysishandler = this;
00193 _analyses.insert(analysis);
00194 }
00195 return *this;
00196 }
00197
00198
00199 AnalysisHandler& AnalysisHandler::removeAnalysis(const string& analysisname) {
00200 shared_ptr<Analysis> toremove;
00201 foreach (const AnaHandle a, _analyses) {
00202 if (a->name() == analysisname) {
00203 toremove.reset( a.get() );
00204 break;
00205 }
00206 }
00207 if (toremove.get() != 0) {
00208 getLog() << Log::DEBUG << "Removing analysis '" << analysisname << "'" << endl;
00209 _analyses.erase(toremove);
00210 }
00211 return *this;
00212 }
00213
00214
00215 AnalysisHandler& AnalysisHandler::removeIncompatibleAnalyses(const PdgIdPair& beams) {
00216 vector<string> anamestodelete;
00217 foreach (const AnaHandle a, _analyses) {
00218 if (! a->isCompatible(beams)) {
00219 anamestodelete.push_back(a->name());
00220 }
00221 }
00222 foreach (const string& aname, anamestodelete) {
00223 getLog() << Log::WARN << "Removing incompatible analysis '"
00224 << aname << "'" << endl;
00225 removeAnalysis(aname);
00226 }
00227 return *this;
00228 }
00229
00230
00231 void AnalysisHandler::_setupFactories(const string& basefilename, HistoFormat storetype) {
00232 string filename(basefilename), storetypestr("");
00233 if (storetype == AIDAML) {
00234 if (!endsWith(filename, ".aida")) filename += ".aida";
00235 storetypestr = "xml";
00236 } else if (storetype == FLAT) {
00237 if (!endsWith(filename, ".data")) filename += ".data";
00238 storetypestr = "flat";
00239 } else if (storetype == ROOT) {
00240 if (!endsWith(filename, ".root")) filename += ".root";
00241 storetypestr = "root";
00242 }
00243 _theTreeFactory = _theAnalysisFactory->createTreeFactory();
00244 _theTree = _theTreeFactory->create(filename, storetypestr, false, true);
00245 _theHistogramFactory = _theAnalysisFactory->createHistogramFactory(tree());
00246 _theDataPointSetFactory = _theAnalysisFactory->createDataPointSetFactory(tree());
00247 }
00248
00249
00250 void AnalysisHandler::_setupFactories() {
00251 _theTreeFactory = _theAnalysisFactory->createTreeFactory();
00252 _theTree = _theTreeFactory->create();
00253 _theHistogramFactory = _theAnalysisFactory->createHistogramFactory(tree());
00254 _theDataPointSetFactory = _theAnalysisFactory->createDataPointSetFactory(tree());
00255 }
00256
00257
00258 void AnalysisHandler::commitData() {
00259 tree().commit();
00260 }
00261
00262
00263 void AnalysisHandler::writeData(const string& filename) {
00264 tree().commit(filename);
00265 }
00266
00267
00268 void AnalysisHandler::_normalizeTree(ITree& tree) {
00269 Log& log = getLog();
00270 const vector<string> paths = tree.listObjectNames("/", true);
00271 log << Log::TRACE << "Number of objects in AIDA tree = " << paths.size() << endl;
00272 const string tmpdir = "/RivetNormalizeTmp";
00273 tree.mkdir(tmpdir);
00274 foreach (const string& path, paths) {
00275
00276 IManagedObject* hobj = tree.find(path);
00277 if (hobj) {
00278
00279
00280
00281 IHistogram1D* histo = 0;
00282 IProfile1D* prof = dynamic_cast<IProfile1D*>(hobj);
00283 if (!prof) histo = dynamic_cast<IHistogram1D*>(hobj);
00284
00285
00286 if (histo) {
00287 log << Log::TRACE << "Converting histo " << path << " to DPS" << endl;
00288 tree.mv(path, tmpdir);
00289 const size_t lastslash = path.find_last_of("/");
00290 const string basename = path.substr(lastslash+1, path.length() - (lastslash+1));
00291 const string tmppath = tmpdir + "/" + basename;
00292 IHistogram1D* tmphisto = dynamic_cast<IHistogram1D*>(tree.find(tmppath));
00293 if (tmphisto) {
00294
00295 datapointsetFactory().create(path, *tmphisto);
00296 }
00297 tree.rm(tmppath);
00298 }
00299
00300 else if (prof) {
00301 log << Log::TRACE << "Converting profile histo " << path << " to DPS" << endl;
00302 tree.mv(path, tmpdir);
00303 const size_t lastslash = path.find_last_of("/");
00304 const string basename = path.substr(lastslash+1, path.length() - (lastslash+1));
00305 const string tmppath = tmpdir + "/" + basename;
00306 IProfile1D* tmpprof = dynamic_cast<IProfile1D*>(tree.find(tmppath));
00307 if (tmpprof) {
00308
00309 datapointsetFactory().create(path, *tmpprof);
00310 }
00311 tree.rm(tmppath);
00312 }
00313
00314 }
00315
00316 }
00317 tree.rmdir(tmpdir);
00318 }
00319
00320
00321 string AnalysisHandler::runName() const { return _runname; }
00322 size_t AnalysisHandler::numEvents() const { return _numEvents; }
00323 double AnalysisHandler::sumOfWeights() const { return _sumOfWeights; }
00324
00325
00326 void AnalysisHandler::setSumOfWeights(const double& sum) {
00327 _sumOfWeights=sum;
00328 }
00329
00330
00331 std::vector<std::string> AnalysisHandler::analysisNames() const {
00332 std::vector<std::string> rtn;
00333 foreach (AnaHandle a, _analyses) {
00334 rtn.push_back(a->name());
00335 }
00336 return rtn;
00337 }
00338
00339
00340 AnalysisHandler& AnalysisHandler::addAnalyses(const std::vector<std::string>& analysisnames) {
00341 foreach (const string& aname, analysisnames) {
00342
00343 addAnalysis(aname);
00344 }
00345 return *this;
00346 }
00347
00348
00349 AnalysisHandler& AnalysisHandler::removeAnalyses(const std::vector<std::string>& analysisnames) {
00350 foreach (const string& aname, analysisnames) {
00351 removeAnalysis(aname);
00352 }
00353 return *this;
00354 }
00355
00356
00357
00358 AIDA::IAnalysisFactory& AnalysisHandler::analysisFactory() {
00359 return *_theAnalysisFactory;
00360 }
00361
00362
00363 AIDA::ITree& AnalysisHandler::tree() {
00364 return *_theTree;
00365 }
00366
00367
00368 AIDA::IHistogramFactory& AnalysisHandler::histogramFactory() {
00369 return *_theHistogramFactory;
00370 }
00371
00372
00373 AIDA::IDataPointSetFactory& AnalysisHandler::datapointsetFactory() {
00374 return *_theDataPointSetFactory;
00375 }
00376
00377
00378 bool AnalysisHandler::needCrossSection() const {
00379 bool rtn = false;
00380 foreach (const AnaHandle a, _analyses) {
00381 if (!rtn) rtn = a->needsCrossSection();
00382 if (rtn) break;
00383 }
00384 return rtn;
00385 }
00386
00387
00388 AnalysisHandler& AnalysisHandler::setCrossSection(double xs) {
00389 _xs = xs;
00390 foreach (AnaHandle a, _analyses) {
00391 a->setCrossSection(xs);
00392 }
00393 return *this;
00394 }
00395
00396
00397 bool AnalysisHandler::hasCrossSection() const {
00398 return (crossSection() >= 0);
00399 }
00400
00401
00402 AnalysisHandler& AnalysisHandler::addAnalysis(Analysis* analysis) {
00403 analysis->_analysishandler = this;
00404 _analyses.insert(AnaHandle(analysis));
00405 return *this;
00406 }
00407
00408
00409 PdgIdPair AnalysisHandler::beamIds() const {
00410 return Rivet::beamIds(beams());
00411 }
00412
00413
00414 double AnalysisHandler::sqrtS() const {
00415 return Rivet::sqrtS(beams());
00416 }
00417
00418
00419 }