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& beampairs = it.second();
00090           vector<PdgIdPair> beam_pairs;
00091           if (beampairs.size() == 2 &&
00092               beampairs[0].GetType() == YAML::CT_SCALAR &&
00093               beampairs[1].GetType() == YAML::CT_SCALAR) {
00094             string bstr0, bstr1;
00095             beampairs[0] >> bstr0;
00096             beampairs[1] >> bstr1;
00097             beam_pairs += make_pdgid_pair(bstr0, bstr1);
00098           } else {
00099             for (YAML::Iterator bpi = beampairs.begin(); bpi != beampairs.end(); ++bpi) {
00100               const YAML::Node& bp = *bpi;
00101               if (bp.size() == 2 &&
00102                   bp[0].GetType() == YAML::CT_SCALAR &&
00103                   bp[1].GetType() == YAML::CT_SCALAR) {
00104                 string bstr0, bstr1;
00105                 bp[0] >> bstr0;
00106                 bp[1] >> bstr1;
00107                 beam_pairs += make_pdgid_pair(bstr0, bstr1);
00108               } else {
00109                 assert(0 && "Beam ID pairs have to be either a 2-tuple or a list of 2-tuples of particle names");
00110               }
00111             }
00112           }
00113           ai->_beams = beam_pairs;
00114         }
00115         else if (key == "Energies") {
00116           const YAML::Node& energies = it.second();
00117           vector<pair<double,double> > beam_energy_pairs;
00118           for (YAML::Iterator be = energies.begin(); be != energies.end(); ++be) {
00119             if (be->GetType() == YAML::CT_SCALAR) {
00120               // If beam energy is a scalar, then assume symmetric beams each with half that energy
00121               double sqrts;
00122               *be >> sqrts;
00123               beam_energy_pairs += make_pair(sqrts/2.0, sqrts/2.0);
00124             } else if (be->GetType() == YAML::CT_SEQUENCE) {
00125               const YAML::Node& beseq = *be;
00126               // If the sub-sequence is of length 1, then it's another scalar sqrt(s)!
00127               if (beseq.size() == 1) {
00128                 double sqrts;
00129                 (*be)[0] >> sqrts;
00130                 beam_energy_pairs += make_pair(sqrts/2.0, sqrts/2.0);
00131               } else if (beseq.size() == 2) {
00132                 vector<double> beamenergies;
00133                 double beamenergy0, beamenergy1;
00134                 beseq[0] >> beamenergy0;
00135                 beseq[1] >> beamenergy1;
00136                 beam_energy_pairs += make_pair(beamenergy0, beamenergy1);
00137               } else {
00138                 assert(0 && "Beam energies have to be a list of either numbers or pairs of numbers");
00139               }
00140             } else {
00141               assert(0 && "Beam energies have to be a list of either numbers or pairs of numbers");
00142             }
00143           }
00144           ai->_energies = beam_energy_pairs;
00145         } else if (key == "Collider") {
00146           it.second() >> ai->_collider;
00147         } else if (key == "SpiresID") {
00148           it.second() >> ai->_spiresId;
00149         } else if (key == "BibKey") {
00150           it.second() >> ai->_bibKey;
00151         } else if (key == "BibTeX") {
00152           it.second() >> ai->_bibTeX;//Body;
00153         } else if (key == "Status") {
00154           it.second() >> ai->_status;
00155         } else if (key == "ToDo") {
00156           const YAML::Node& todos = it.second();
00157           for (YAML::Iterator todo = todos.begin(); todo != todos.end(); ++todo) {
00158             string s;
00159             *todo >> s;
00160             ai->_todos += s;
00161           }
00162         } else if (key == "NeedCrossSection") {
00163           it.second() >> ai->_needsCrossSection;
00164         } else if (key == "RunInfo") {
00165           it.second() >> ai->_runInfo;
00166         } else if (key == "Description") {
00167           it.second() >> ai->_description;
00168         } else if (key == "Year") {
00169           it.second() >> ai->_year;
00170         } else if (key == "Authors") {
00171           const YAML::Node& authors = it.second();
00172           for (YAML::Iterator a = authors.begin(); a != authors.end(); ++a) {
00173             string astr;
00174             *a >> astr;
00175             ai->_authors += astr;
00176           }
00177         } else if (key == "References") {
00178           const YAML::Node& refs = it.second();
00179           for (YAML::Iterator r = refs.begin(); r != refs.end(); ++r) {
00180             string rstr;
00181             *r >> rstr;
00182             ai->_references += rstr;
00183           }
00184         }
00185       } catch (const YAML::RepresentationException& ex) {
00186         Log::getLog("Rivet.Analysis")
00187           << Log::WARN << "Type error when reading analysis data '"
00188           << key << "' from " << datapath << endl;
00189       }
00190     }
00191     Log::getLog("Rivet.AnalysisInfo") << Log::TRACE << "AnalysisInfo pointer = " << ai << endl;
00192     return ai;
00193   }
00194 
00195 
00196   string toString(const AnalysisInfo& ai) {
00197     stringstream ss;
00198     ss << ai.name();
00199     ss << " - " << ai.summary();
00200     // ss << " - " << ai.beams();
00201     // ss << " - " << ai.energies();
00202     ss << " (" << ai.status() << ")";
00203     return ss.str();
00204   }
00205 
00206 
00207 }