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