AnalysisInfo.cc
Go to the documentation of this file.
00001 #include "Rivet/Rivet.hh" 00002 #include "Rivet/AnalysisInfo.hh" 00003 #include "Rivet/Tools/RivetBoost.hh" 00004 #include "Rivet/Tools/RivetPaths.hh" 00005 #include "Rivet/Tools/Utils.hh" 00006 #include "Rivet/Tools/Logging.hh" 00007 #include "yaml-cpp/yaml.h" 00008 #include <iostream> 00009 #include <fstream> 00010 #include <unistd.h> 00011 00012 namespace Rivet { 00013 00014 00015 namespace { 00016 Log& getLog() { 00017 return Log::getLog("Rivet.AnalysisInfo"); 00018 } 00019 } 00020 00021 00022 /// Static factory method 00023 AnalysisInfo* AnalysisInfo::make(const std::string& ananame) { 00024 // Returned AI, in semi-null state 00025 AnalysisInfo* ai = new AnalysisInfo(); 00026 ai->_beams += make_pair(PID::ANY, PID::ANY); 00027 ai->_name = ananame; 00028 00029 /// If no ana data file found, return null AI 00030 const string datapath = findAnalysisInfoFile(ananame + ".info"); 00031 if (datapath.empty()) { 00032 MSG_DEBUG("No datafile " << ananame + ".info found"); 00033 return ai; 00034 } 00035 00036 // Read data from YAML document 00037 MSG_DEBUG("Reading analysis data from " << datapath); 00038 YAML::Node doc; 00039 try { 00040 #if YAMLCPP_API_VERSION == 3 00041 std::ifstream file(datapath.c_str()); 00042 YAML::Parser parser(file); 00043 parser.GetNextDocument(doc); 00044 #elif YAMLCPP_API_VERSION == 5 00045 doc = YAML::LoadFile(datapath); 00046 #endif 00047 } catch (const YAML::ParserException& ex) { 00048 MSG_ERROR("Parse error when reading analysis data from " << datapath << " (" << ex.what() << ")"); 00049 return ai; 00050 } 00051 00052 #define THROW_INFOERR(KEY) throw InfoError("Problem in info parsing while accessing key " + string(KEY) + " in file " + datapath) 00053 00054 // Simple scalars (test for nullness before casting) 00055 #if YAMLCPP_API_VERSION == 3 00056 /// @todo Fix 00057 #define TRY_GETINFO(KEY, VAR) try { if (doc.FindValue(KEY)) { string val; doc[KEY] >> val; ai->_ ## VAR = val; } } catch (...) { THROW_INFOERR(KEY); } 00058 #elif YAMLCPP_API_VERSION == 5 00059 #define TRY_GETINFO(KEY, VAR) try { if (doc[KEY] && !doc[KEY].IsNull()) ai->_ ## VAR = doc[KEY].as<string>(); } catch (...) { THROW_INFOERR(KEY); } 00060 #endif 00061 TRY_GETINFO("Name", name); 00062 TRY_GETINFO("Summary", summary); 00063 TRY_GETINFO("Status", status); 00064 TRY_GETINFO("RunInfo", runInfo); 00065 TRY_GETINFO("Description", description); 00066 TRY_GETINFO("Experiment", experiment); 00067 TRY_GETINFO("Collider", collider); 00068 TRY_GETINFO("Year", year); 00069 TRY_GETINFO("SpiresID", spiresId); 00070 TRY_GETINFO("InspireID", inspireId); 00071 TRY_GETINFO("BibKey", bibKey); 00072 TRY_GETINFO("BibTeX", bibTeX); 00073 #undef TRY_GETINFO 00074 00075 // Sequences (test the seq *and* each entry for nullness before casting) 00076 #if YAMLCPP_API_VERSION == 3 00077 /// @todo Fix 00078 #define TRY_GETINFO_SEQ(KEY, VAR) try { \ 00079 if (const YAML::Node* VAR = doc.FindValue(KEY)) { \ 00080 for (size_t i = 0; i < VAR->size(); ++i) { \ 00081 string val; (*VAR)[i] >> val; ai->_ ## VAR += val; \ 00082 } } } catch (...) { THROW_INFOERR(KEY); } 00083 #elif YAMLCPP_API_VERSION == 5 00084 #define TRY_GETINFO_SEQ(KEY, VAR) try { \ 00085 if (doc[KEY] && !doc[KEY].IsNull()) { \ 00086 const YAML::Node& VAR = doc[KEY]; \ 00087 for (size_t i = 0; i < VAR.size(); ++i) \ 00088 if (!VAR[i].IsNull()) ai->_ ## VAR += VAR[i].as<string>(); \ 00089 } } catch (...) { THROW_INFOERR(KEY); } 00090 #endif 00091 TRY_GETINFO_SEQ("Authors", authors); 00092 TRY_GETINFO_SEQ("References", references); 00093 TRY_GETINFO_SEQ("ToDo", todos); 00094 #undef TRY_GETINFO_SEQ 00095 00096 00097 // A boolean with some name flexibility 00098 try { 00099 #if YAMLCPP_API_VERSION == 3 00100 bool val; 00101 if (const YAML::Node* n = doc.FindValue("NeedsCrossSection")) { *n >> val; ai->_needsCrossSection = val; } 00102 if (const YAML::Node* n = doc.FindValue("NeedCrossSection")) { *n >> val; ai->_needsCrossSection = val; } 00103 #elif YAMLCPP_API_VERSION == 5 00104 if (doc["NeedsCrossSection"]) ai->_needsCrossSection = doc["NeedsCrossSection"].as<bool>(); 00105 else if (doc["NeedCrossSection"]) ai->_needsCrossSection = doc["NeedCrossSection"].as<bool>(); 00106 #endif 00107 } catch (...) { 00108 THROW_INFOERR("NeedsCrossSection|NeedCrossSection"); 00109 } 00110 00111 00112 // Beam particle identities 00113 try { 00114 #if YAMLCPP_API_VERSION == 3 00115 00116 if (const YAML::Node* pbeampairs = doc.FindValue("Beams")) { 00117 const YAML::Node& beampairs = *pbeampairs; 00118 vector<PdgIdPair> beam_pairs; 00119 if (beampairs.size() == 2 && 00120 beampairs[0].Type() == YAML::NodeType::Scalar && 00121 beampairs[1].Type() == YAML::NodeType::Scalar) { 00122 string bstr0, bstr1; 00123 beampairs[0] >> bstr0; 00124 beampairs[1] >> bstr1; 00125 beam_pairs += PID::make_pdgid_pair(bstr0, bstr1); 00126 } else { 00127 for (YAML::Iterator bpi = beampairs.begin(); bpi != beampairs.end(); ++bpi) { 00128 const YAML::Node& bp = *bpi; 00129 if (bp.size() == 2 && 00130 bp[0].Type() == YAML::NodeType::Scalar && 00131 bp[1].Type() == YAML::NodeType::Scalar) { 00132 string bstr0, bstr1; 00133 bp[0] >> bstr0; 00134 bp[1] >> bstr1; 00135 beam_pairs += PID::make_pdgid_pair(bstr0, bstr1); 00136 } else { 00137 throw InfoError("Beam ID pairs have to be either a 2-tuple or a list of 2-tuples of particle names"); 00138 } 00139 } 00140 } 00141 ai->_beams = beam_pairs; 00142 } 00143 00144 #elif YAMLCPP_API_VERSION == 5 00145 00146 if (doc["Beams"]) { 00147 const YAML::Node& beams = doc["Beams"]; 00148 vector<PdgIdPair> beam_pairs; 00149 if (beams.size() == 2 && beams[0].IsScalar() && beams[0].IsScalar()) { 00150 beam_pairs += PID::make_pdgid_pair(beams[0].as<string>(), beams[1].as<string>()); 00151 } else { 00152 for (size_t i = 0; i < beams.size(); ++i) { 00153 const YAML::Node& bp = beams[i]; 00154 if (bp.size() != 2 || !bp[0].IsScalar() || !bp[0].IsScalar()) 00155 throw InfoError("Beam ID pairs have to be either a 2-tuple or a list of 2-tuples of particle names"); 00156 beam_pairs += PID::make_pdgid_pair(bp[0].as<string>(), bp[1].as<string>()); 00157 } 00158 } 00159 ai->_beams = beam_pairs; 00160 } 00161 00162 #endif 00163 } catch (...) { THROW_INFOERR("Beams"); } 00164 00165 00166 // Beam energies 00167 try { 00168 #if YAMLCPP_API_VERSION == 3 00169 00170 if (const YAML::Node* penergies = doc.FindValue("Energies")) { 00171 const YAML::Node& energies = *penergies; 00172 vector<pair<double,double> > beam_energy_pairs; 00173 for (YAML::Iterator be = energies.begin(); be != energies.end(); ++be) { 00174 if (be->Type() == YAML::NodeType::Scalar) { 00175 // If beam energy is a scalar, then assume symmetric beams each with half that energy 00176 double sqrts; 00177 *be >> sqrts; 00178 beam_energy_pairs += make_pair(sqrts/2.0, sqrts/2.0); 00179 } else if (be->Type() == YAML::NodeType::Sequence) { 00180 const YAML::Node& beseq = *be; 00181 // If the sub-sequence is of length 1, then it's another scalar sqrt(s)! 00182 if (beseq.size() == 1) { 00183 double sqrts; 00184 (*be)[0] >> sqrts; 00185 beam_energy_pairs += make_pair(sqrts/2.0, sqrts/2.0); 00186 } else if (beseq.size() == 2) { 00187 vector<double> beamenergies; 00188 double beamenergy0, beamenergy1; 00189 beseq[0] >> beamenergy0; 00190 beseq[1] >> beamenergy1; 00191 beam_energy_pairs += make_pair(beamenergy0, beamenergy1); 00192 } else { 00193 throw InfoError("Beam energies have to be a list of either numbers or pairs of numbers"); 00194 } 00195 } else { 00196 throw InfoError("Beam energies have to be a list of either numbers or pairs of numbers"); 00197 } 00198 } 00199 ai->_energies = beam_energy_pairs; 00200 } 00201 00202 #elif YAMLCPP_API_VERSION == 5 00203 00204 if (doc["Energies"]) { 00205 vector< pair<double,double> > beam_energy_pairs; 00206 for (size_t i = 0; i < doc["Energies"].size(); ++i) { 00207 const YAML::Node& be = doc["Energies"][i]; 00208 if (be.IsScalar()) { 00209 // If beam energy is a scalar, then assume symmetric beams each with half that energy 00210 beam_energy_pairs += make_pair(be.as<double>()/2.0, be.as<double>()/2.0); 00211 } else if (be.IsSequence()) { 00212 if (be.size() != 2) 00213 throw InfoError("Beam energies have to be a list of either numbers or pairs of numbers"); 00214 beam_energy_pairs += make_pair(be[0].as<double>(), be[1].as<double>()); 00215 } else { 00216 throw InfoError("Beam energies have to be a list of either numbers or pairs of numbers"); 00217 } 00218 } 00219 ai->_energies = beam_energy_pairs; 00220 } 00221 00222 #endif 00223 00224 } catch (...) { THROW_INFOERR("Energies"); } 00225 00226 #undef THROW_INFOERR 00227 00228 00229 MSG_TRACE("AnalysisInfo pointer = " << ai); 00230 return ai; 00231 } 00232 00233 00234 string toString(const AnalysisInfo& ai) { 00235 stringstream ss; 00236 ss << ai.name(); 00237 ss << " - " << ai.summary(); 00238 // ss << " - " << ai.beams(); 00239 // ss << " - " << ai.energies(); 00240 ss << " (" << ai.status() << ")"; 00241 return ss.str(); 00242 } 00243 00244 00245 } Generated on Fri Oct 25 2013 12:41:43 for The Rivet MC analysis system by ![]() |