AnalysisInfo.cc

Go to the documentation of this file.
00001 #include "Rivet/Rivet.hh"
00002 #include "Rivet/RivetBoost.hh"
00003 #include "Rivet/AnalysisInfo.hh"
00004 #include "Rivet/Tools/Utils.hh"
00005 #include "Rivet/Tools/Logging.hh"
00006 #include "yaml-cpp/yaml.h"
00007 #include <iostream>
00008 #include <fstream>
00009 #include <unistd.h>
00010 
00011 namespace Rivet {
00012 
00013 
00014   /// Ideas:
00015   ///  * search RIVET_INFO_PATH etc. for <name>.info.yaml
00016   ///  * how to determine the name?
00017   ///  * only populate pointer on Analysis when requested
00018   ///  * use smart pointer: deletes automatically when Analysis
00019   ///    goes out of scope
00020 
00021 
00022   /// Static factory method
00023   AnalysisInfo* AnalysisInfo::make(const std::string& ananame) {
00024     // Build the list of directories to search
00025     vector<string> dirs;
00026     char* env = 0;
00027     // First try to use the Rivet data path variable
00028     env = getenv("RIVET_INFO_PATH");
00029     if (env) dirs += split(env);
00030     // Then try to use the Rivet data install path
00031     dirs += getRivetDataPath();
00032     // And the current dir
00033     dirs += ".";
00034 
00035     bool found = false;
00036     string datapath = "";
00037     foreach (const string& d, dirs) {
00038       if (d.empty()) continue;
00039       /// @todo Use system-independent separator (e.g. Boost.File)
00040       datapath = d + "/" + ananame + ".info";
00041       Log::getLog("Rivet.AnalysisInfo")
00042         << Log::TRACE << "Looking for analysis data file '" << datapath << "'" << endl;
00043       if (access(datapath.c_str(), R_OK) == 0) {
00044         found = true;
00045         break;
00046       }
00047     }
00048 
00049     // Returned AI, in semi-null state
00050     AnalysisInfo* ai = new AnalysisInfo();
00051     ai->_beams = make_pair(ANY,ANY);
00052     ai->_name = ananame;
00053 
00054     /// If no ana data file found, return null AI
00055     if (!found) return ai;
00056 
00057     // Read data from YAML document
00058     Log::getLog("Rivet.AnalysisInfo")
00059       << Log::DEBUG << "Reading analysis data from " << datapath << endl;
00060     std::ifstream io(datapath.c_str());
00061     YAML::Parser parser(io);
00062     YAML::Node doc;
00063     try {
00064       parser.GetNextDocument(doc);
00065       //cout << doc << endl;
00066     } catch (const YAML::ParserException& ex) {
00067       Log::getLog("Rivet.AnalysisInfo")
00068         << Log::ERROR << "Parse error when reading analysis data from "
00069         << datapath << endl;
00070       return ai;
00071     }
00072 
00073     for (YAML::Iterator it = doc.begin(); it != doc.end(); ++it) {
00074       string key;
00075       it.first() >> key;
00076       stringstream sec;
00077       sec << it.second();
00078       const string secstr = sec.str().substr(0, sec.str().length()-1);
00079       Log::getLog("Rivet.AnalysisInfo")
00080         << Log::TRACE << key << ": " << secstr << endl;
00081       try {
00082         if (key == "Name") {
00083           it.second() >> ai->_name;
00084         } else if (key == "Summary") {
00085           it.second() >> ai->_summary;
00086         } else if (key == "Experiment") {
00087           it.second() >> ai->_experiment;
00088         } else if (key == "Beams") {
00089           const YAML::Node& beams = it.second();
00090           vector<ParticleName> beampair;
00091           for (YAML::Iterator b = beams.begin(); b != beams.end(); ++b) {
00092             string bstr;
00093             *b >> bstr;
00094             ParticleName beamname = getParticleNameEnum(bstr);
00095             beampair += beamname;
00096           }
00097           assert(beampair.size() == 2);
00098           ai->_beams = make_pair<ParticleName,ParticleName>(beampair[0], beampair[1]);
00099         // } else if (key == "NeedCrossSection") {
00100         //   // it.second() >> ai->_needsCrossSection;
00101         } else if (key == "Energies") {
00102           const YAML::Node& energies = it.second();
00103           vector<pair<double,double> > beam_energy_pairs;
00104           for (YAML::Iterator be = energies.begin(); be != energies.end(); ++be) {
00105             if (be->GetType() == YAML::CT_SCALAR) {
00106               // If beam energy is a scalar, then assume symmetric beams each with half that energy
00107               double sqrts;
00108               *be >> sqrts;
00109               beam_energy_pairs += make_pair(sqrts/2.0, sqrts/2.0);
00110             } else if (be->GetType() == YAML::CT_SEQUENCE) {
00111               const YAML::Node& beamenergy_strs = be.second();
00112               vector<double> beamenergies;
00113               for (YAML::Iterator e = beamenergy_strs.begin(); e != beamenergy_strs.end(); ++e) {
00114                 double beamenergy;
00115                 *e >> beamenergy;
00116                 beamenergies += beamenergy;
00117               }
00118               assert(beamenergies.size() == 2);
00119               beam_energy_pairs += make_pair(beamenergies[0], beamenergies[1]);
00120             } else {
00121               assert(0 && "Beam energies have to be a list of either numbers or pairs of numbers");
00122             }
00123           }
00124           ai->_energies = beam_energy_pairs;
00125         } else if (key == "Collider") {
00126           it.second() >> ai->_collider;
00127         } else if (key == "SpiresID") {
00128           it.second() >> ai->_spiresId;
00129         } else if (key == "Status") {
00130           it.second() >> ai->_status;
00131         } else if (key == "RunInfo") {
00132           it.second() >> ai->_runInfo;
00133         } else if (key == "Description") {
00134           it.second() >> ai->_description;
00135         } else if (key == "Year") {
00136           it.second() >> ai->_year;
00137         } else if (key == "Authors") {
00138           const YAML::Node& authors = it.second();
00139           for (YAML::Iterator a = authors.begin(); a != authors.end(); ++a) {
00140             string astr;
00141             *a >> astr;
00142             ai->_authors += astr;
00143           }
00144         } else if (key == "References") {
00145           const YAML::Node& refs = it.second();
00146           for (YAML::Iterator r = refs.begin(); r != refs.end(); ++r) {
00147             string rstr;
00148             *r >> rstr;
00149             ai->_references += rstr;
00150           }
00151         }
00152       } catch (const YAML::RepresentationException& ex) {
00153         Log::getLog("Rivet.Analysis")
00154           << Log::WARN << "Type error when reading analysis data '"
00155           << key << "' from " << datapath << endl;
00156       }
00157     }
00158     Log::getLog("Rivet.AnalysisInfo") << Log::DEBUG << ai << endl;
00159     return ai;
00160   }
00161 
00162 
00163   string toString(const AnalysisInfo& ai) {
00164     stringstream ss;
00165     ss << ai.name();
00166     ss << " - " << ai.summary();
00167     // ss << " - " << ai.beams();
00168     // ss << " - " << ai.energies();
00169     ss << " (" << ai.status() << ")";
00170     return ss.str();
00171   }
00172 
00173 
00174 }