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