cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
Utils.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2020-2024 Laurent Forthomme
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef MADGRAPH_BIN
20#error "*** MADGRAPH_BIN variable not set! ***"
21#endif
22
23#include <array>
24#include <fstream>
25
27#include "CepGen/Physics/PDG.h"
28#include "CepGen/Utils/Caller.h"
30#include "CepGen/Utils/String.h"
35
36namespace cepgen {
37 namespace mg5amc {
38 ProcessParticles unpackProcessParticles(const std::string& proc) {
40 auto trim_all = [](std::vector<std::string> coll) -> std::vector<std::string> {
41 std::for_each(coll.begin(), coll.end(), [](std::string& it) { it = utils::trim(it); });
42 return coll;
43 };
44 //--- dirty fix to specify incoming- and outgoing states
45 // as extracted from the mg5_aMC process string
46 const auto prim_proc = utils::split(utils::trim(proc), ',')[0];
47 auto parts = trim_all(utils::split(prim_proc, '>'));
48 if (parts.size() != 2)
49 throw CG_FATAL("MadGraphInterface:unpackProcessParticles")
50 << "Unable to unpack particles from process name: \"" << proc << "\" -> " << parts << "!";
51 //--- incoming parton-like particles
52 auto prim_parts = trim_all(utils::split(parts[0], ' '));
53 CG_DEBUG("MadGraphInterface:unpackProcessParticles") << "Primary particles: " << prim_parts;
54 if (prim_parts.size() != 2)
55 throw CG_FATAL("MadGraphInterface:unpackProcessParticles")
56 << "Unable to unpack particles from primary particles list: \"" << parts[0] << "\" -> " << prim_parts
57 << "!";
58 for (const auto& p : prim_parts)
59 out.first.emplace_back(p);
60 //---- outgoing system
61 auto dec_parts = trim_all(utils::split(parts[1], ' '));
62 CG_DEBUG("MadGraphInterface:unpackProcessParticles") << "Outgoing system: " << dec_parts;
63 for (auto& p : dec_parts)
64 out.second.emplace_back(p);
65 return out;
66 }
67
68 ParticleProperties describeParticle(const std::string& part_name, const std::string& model) {
69 ParametersList plist_part;
70 { // this part retrieves the list of parameters for a given particle name, using a python call to MadGraph
71 python::Environment env({});
72 const std::string name_part_dict = "part_dict";
73 std::vector<std::string> cmds;
74 if (!model.empty()) {
75 cmds.emplace_back("set auto_convert_model T");
76 cmds.emplace_back("import model " + model);
77 }
78 try {
79 cmds.emplace_back("display particles " + part_name);
80 std::string py_output;
81 bool found_properties{false};
82 for (const auto& line : runCommand(cmds, "/tmp/mg5_aMC_part_query.dat", true)) {
83 if (!found_properties) {
84 if (line.find("has the following properties") != std::string::npos)
85 found_properties = true;
86 continue;
87 }
88 if (utils::startsWith(line, "exit"))
89 break;
90 py_output += line;
91 }
92 if (py_output.empty())
93 throw CG_ERROR("MadGraphInterface:describeParticle")
94 << "No output retrieved from MadGraph command '" << cmds << "'. See the possible message output above.";
95 if (auto mod = python::ObjectPtr::defineModule("part", name_part_dict + "=" + py_output); mod) {
96 if (auto part_prop = mod.attribute(name_part_dict); part_prop)
97 plist_part = part_prop.value<ParametersList>();
98 } else
99 throw CG_ERROR("MadGraphInterface:describeParticle")
100 << "Error while parsing the MadGraph python output for particle '" << part_name << "' of model '"
101 << model << ". Python output:\n"
102 << py_output;
103 } catch (const Exception& exc) {
104 switch (part_name[part_name.size() - 1]) {
105 case '+':
106 case '-':
107 throw;
108 default:
109 return describeParticle(part_name + "+", model);
110 }
111 }
112 }
113 // recast all the properties retrieved from the MG output into CepGen-specific particle properties
114 const auto pdg_id = plist_part.get<int>("pdg_code", 0);
115 if (pdg_id == 0)
116 throw CG_FATAL("MadGraphInterface:describeParticle")
117 << "Failed to retrieve a 'pdg_code' key to the unpacked particle properties: " << plist_part << ".";
118 CG_DEBUG("MadGraphInterface:describeParticle") << "List of parameters retrieved from MadGraph on particle '"
119 << part_name << "' from model '" << model << "':\n"
120 << plist_part << ".";
121 ParticleProperties props;
122 if (auto name = plist_part.get<std::string>("name"); !name.empty()) {
123 if (const auto last_chr = name[name.size() - 1]; last_chr == '-' || last_chr == '+')
124 name.pop_back();
125 props.name = name;
126 props.descr = name;
127 }
128 props.pdgid = plist_part.get<int>("pdg_code");
129 plist_part.fill<int>("color", props.colours); //FIXME might not be correct
130 props.mass = plist_part.has<double>("mass") ? plist_part.get<double>("mass") : PDG::get().mass(props.pdgid);
131 props.width = plist_part.has<double>("width") ? plist_part.get<double>("width") : PDG::get().width(props.pdgid);
132 if (plist_part.has<double>("charge")) {
133 const auto ch = std::floor(plist_part.get<double>("charge") * 3.);
134 if (ch != 0) {
135 props.charges.emplace_back(ch);
136 if (!plist_part.get<bool>("self_antipart"))
137 props.charges.emplace_back(-ch);
138 }
139 }
140 props.fermion = plist_part.get<int>("spin", 0) % 2 == 0;
141 CG_DEBUG("MadGraphInterface:describeParticle")
142 << "Particle '" << part_name << "' of model '" << model
143 << "' was successfully described from MG5 with properties: " << props << ".";
144 return props;
145 }
146
147 std::vector<std::string> runCommand(const std::vector<std::string>& cmds,
148 const std::string& card_path,
149 bool keep_output) {
150 std::ofstream tmp_card(card_path);
151 for (const auto& cmd : cmds)
152 tmp_card << cmd << "\n";
153 tmp_card << "exit\n";
154 tmp_card.close();
155 std::vector<std::string> output;
156 {
157 utils::Caller caller;
158 for (const auto& line : utils::split(caller.call({MADGRAPH_BIN, "-f", card_path}), '\n'))
159 if (!utils::startsWith(line, "MG5_aMC>"))
160 output.emplace_back(line);
161 }
162 CG_DEBUG("MadGraphInterface:runCommand") << "\nCommands:\n"
163 << cmds << "\nOutput:\n"
164 << utils::merge(output, "\n");
165 if (!keep_output) {
166 fs::remove(card_path);
167 CG_DEBUG("MadGraphInterface:runCommand") << "Steering card file '" << card_path << "' was removed.";
168 }
169 return output;
170 }
171
172 std::string normalise(const std::string& proc_name, const std::string& model) {
173 return (!model.empty() ? model + "__" : "") +
174 utils::replaceAll(proc_name, {{" ", "_"}, {">", "_to_"}, {"+", "p"}, {"-", "m"}, {"~", "bar"}});
175 }
176 } // namespace mg5amc
177} // namespace cepgen
#define CG_FATAL(mod)
Definition Exception.h:61
#define CG_ERROR(mod)
Definition Exception.h:60
#define CG_DEBUG(mod)
Definition Message.h:220
double width(spdgid_t) const
Resonance width (in GeV)
Definition PDG.cpp:96
double mass(spdgid_t) const
Particle mass (in GeV)
Definition PDG.cpp:90
static PDG & get()
Retrieve a unique instance of this particles info collection.
Definition PDG.cpp:41
bool has(const std::string &key) const
Check if a given parameter is handled in this list.
T get(const std::string &key, const T &def=default_arg< T >::get()) const
Get a parameter value.
const ParametersList & fill(const std::string &key, T &value) const
Fill a variable with the key content if exists.
static ObjectPtr defineModule(const std::string &, const std::string &)
Define a Python module from a Python code in a new reference-counted Python object.
External command piping utility.
Definition Caller.h:29
static std::string call(const std::vector< std::string > &commands)
Start a logged call command.
Definition Caller.cpp:45
ParticleProperties describeParticle(const std::string &part_name, const std::string &model)
Unpack all particle properties from MadGraph.
Definition Utils.cpp:68
std::pair< std::vector< std::string >, std::vector< std::string > > ProcessParticles
Definition Utils.h:26
ProcessParticles unpackProcessParticles(const std::string &proc)
Unpack the particles' content and role in the process from a string.
Definition Utils.cpp:38
std::string normalise(const std::string &proc_name, const std::string &model)
Normalise a process name to make it computer-readable.
Definition Utils.cpp:172
std::vector< std::string > runCommand(const std::vector< std::string > &cmds, const std::string &card_path, bool keep_output)
Run a mg5_aMC command and return its result.
Definition Utils.cpp:147
std::string trim(const std::string &str)
Trim leading and trailing spaces.
Definition String.h:174
bool startsWith(const std::string &str, const std::string &beg)
Check if a string starts with a given token.
Definition String.cpp:365
size_t replaceAll(std::string &str, const std::string &from, const std::string &to)
Replace all occurrences of a text by another.
Definition String.cpp:118
std::string merge(const std::vector< T > &vec, const std::string &delim)
Merge a collection of a printable type in a single string.
Definition String.cpp:248
std::vector< std::string > split(const std::string &str, char delim, bool trim)
Split a string according to a separation character.
Definition String.cpp:233
Common namespace for this Monte Carlo generator.
A collection of physics constants associated to a single particle.
std::string descr
Human-readable name.
double mass
Mass, in GeV/c .
pdgid_t pdgid
PDG identifier.
std::vector< int > charges
Electric charges, in /3.
std::string name
Particle name.
double width
Decay width, in GeV/c .
bool fermion
Is the particle a fermion?