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