cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
ParametersDescription.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2021-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#include <sstream>
20
24#include "CepGen/Utils/String.h"
25
26using namespace std::string_literals;
27
28namespace cepgen {
30 if (!mod_key.empty())
31 setKey(mod_key);
32 }
33
35 for (const auto& key : ParametersList::keys()) {
36 if (obj_descr_.count(key) == 0)
37 obj_descr_[key] = ParametersList::has<ParametersList>(key)
38 ? ParametersDescription(ParametersList::get<ParametersList>(key))
40 }
41 // avoid doubly-defined Limits/vector<double> situations
42 for (const auto& klim : ParametersList::keysOf<Limits>())
43 if (utils::contains(ParametersList::keysOf<std::vector<double> >(), klim))
44 // hack to ensure vector<double> is dropped by set<Limits>(...)
45 ParametersList::set<Limits>(klim, ParametersList::get<Limits>(klim));
46 }
47
49 // description is declared empty if
50 // 1) it has no sub-description object, and
51 // 2) it is not itself describing anything
52 return obj_descr_.empty() && mod_descr_.empty();
53 }
54
56 for (const auto& key : ParametersList::keysOf<std::vector<ParametersList> >())
57 // particular case if one describes a set of key-indexed parameters list as a vector of parameters lists
58 if (oth.parameters().has<ParametersList>(key)) {
59 const auto& desc = get(key);
61 add<ParametersDescription>(key, oth.get(key))
62 .setDescription(desc.description())
63 .allowedValues()
64 .append(desc.allowedValues());
65 }
66 obj_descr_.insert(oth.obj_descr_.begin(), oth.obj_descr_.end());
67 obj_values_.append(oth.obj_values_);
69 return *this;
70 }
71
72 bool ParametersDescription::has(const std::string& key) const { return obj_descr_.count(key) != 0; }
73
74 const ParametersDescription& ParametersDescription::get(const std::string& key) const {
75 if (!has(key))
76 throw CG_FATAL("ParametersDescription:get").log([&](auto& log) {
77 log << "Failed to retrieve a parameters description member named \'" << key << "\'.\n"
78 << "List of keys registered: ";
79 std::string sep;
80 for (const auto& k : obj_descr_)
81 log << sep << "'" << k.first << "'", sep = ", ";
82 });
83 return obj_descr_.at(key);
84 }
85
87 if (is_vec_params_)
89 if (obj_descr_.empty())
90 return Type::Value;
91 if (const auto& mod_name = ParametersList::getNameString(); mod_name.empty())
92 return Type::Parameters;
93 return Type::Module;
94 }
95
96 std::string ParametersDescription::describe(size_t offset) const {
97 static auto sep = [](size_t offset) -> std::string { return std::string(2 * offset, ' '); };
98 const auto& mod_name = ParametersList::getNameString();
99 const auto& pdtype = type();
100 const auto& keys = ParametersList::keys(false);
101 std::ostringstream os;
102 // write collection type (if collection)
103 if (pdtype == Type::Parameters)
105 << " collection";
106 else if (pdtype == Type::Module)
107 os << utils::boldify(mod_name) << " module";
108 // write human-readable description (if exists)
109 if (pdtype != Type::ParametersVector && !mod_descr_.empty())
111 if (keys.empty()) // no keys to this module ; can return
112 return os.str();
113 if (pdtype == Type::ParametersVector) {
114 os << parameters();
115 return os.str();
116 }
117 if (pdtype == Type::Module)
118 os << " with parameters";
119 os << ":";
120 // write list of parameters (if has some)
121 for (const auto& key : keys) {
122 if (pdtype == Type::ParametersVector && !ParametersList::has<ParametersList>(key))
123 continue;
124 os << "\n" << sep(offset + 1) << utils::colourise(key, utils::Colour::none, utils::Modifier::underline) << " ";
125 if (obj_descr_.count(key) == 0)
126 continue;
127 os << "= ";
128 const auto& obj = obj_descr_.at(key);
129 switch (obj.type()) {
130 case Type::Value: {
131 if (ParametersList::has<std::string>(key))
132 os << "\"" << ParametersList::getString(key) << "\"";
133 else
135 if (const auto& par_desc = obj.description(); !par_desc.empty())
137 if (const auto& allowed_vals = obj.allowedValues(); !allowed_vals.empty()) {
138 os << " with allowed values:\n" << sep(offset + 2);
139 std::string list_sep;
140 for (const auto& kv : allowed_vals.allowed())
141 os << list_sep << kv.first << (!kv.second.empty() ? " (" + kv.second + ")" : ""), list_sep = ", ";
142 }
143 } break;
145 os << utils::colourise("Vector of parameters collections",
148 const auto& par_desc = obj.description();
149 if (!par_desc.empty())
150 os << " (" << utils::colourise(par_desc, utils::Colour::none, utils::Modifier::italic) << ")";
151 const auto& params = ParametersList::get<ParametersList>(key);
152 if (!params.empty())
153 os << " with user-steered content: " << obj.steer(params).describe(offset + 1);
154 else
155 os << " with expected content: " << obj.describe(offset + 1);
156 } break;
157 default: {
158 const auto& descr = obj.describe(offset + 1);
159 if (!utils::trim(descr).empty())
160 os << descr;
161 } break;
162 }
163 }
164 return os.str();
165 }
166
168 mod_descr_ = descr;
169 return *this;
170 }
171
172 template <>
173 ParametersDescription& ParametersDescription::add<ParametersDescription>(const std::string& name,
174 const ParametersDescription& desc) {
175 obj_descr_[name] += desc;
176 ParametersList::set<ParametersList>(name, desc.parameters());
177 CG_DEBUG_LOOP("ParametersDescription:add").log([this, &name, &desc](auto& log) {
178 log << "Added a new parameters collection \"" << name << "\" as: " << desc;
179 const auto& mod_name = this->getNameString();
180 if (!mod_name.empty())
181 log << "\n"
182 << "to the object with name: " << mod_name;
183 log << ".";
184 });
185 return obj_descr_[name];
186 }
187
188 template <>
189 ParametersDescription& ParametersDescription::add<ParametersList>(const std::string& name, const ParametersList&) {
190 throw CG_FATAL("ParametersDescription:add")
191 << "Using a ParametersList object for the description of a collection of parameters is not allowed.\n"
192 << "Please use a ParametersDescription object instead for the description of the '" << name << "' collection.";
193 }
194
196 const ParametersDescription& desc,
197 const std::vector<ParametersList>& def) {
198 obj_descr_[name] += desc;
199 obj_descr_[name].setParametersVector(true);
200 auto& values = ParametersList::operator[]<std::vector<ParametersList> >(name);
201 for (const auto& val : def)
202 values.emplace_back(desc.validate(val));
203 CG_DEBUG_LOOP("ParametersDescription:addParametersDescriptionVector").log([this, &name, &desc, &def](auto& log) {
204 log << "Added a new vector of parameters descriptions \"" << name << "\" as: " << desc;
205 const auto& mod_name = this->getNameString();
206 if (!mod_name.empty())
207 log << "\n"
208 << "to the object with name: " << mod_name;
209 log << ".\n";
210 if (!def.empty())
211 log << "It is now composed of " << def << ".";
212 });
213 return obj_descr_[name];
214 }
215
217
218 const ParametersList& ParametersDescription::parameters() const { return *this; }
219
221 auto plist = parameters(); // first copy the current parameters handled
222 plist += user_params;
223 for (const auto& key : keysOf<std::vector<ParametersList> >()) {
224 if (user_params.has<std::vector<ParametersList> >(key)) { // vector{ParametersList}
225 plist.erase(key);
226 for (const auto& pit : user_params.get<std::vector<ParametersList> >(key))
227 plist.operator[]<std::vector<ParametersList> >(key).emplace_back(obj_descr_.at(key).parameters() + pit);
228 } else if (user_params.has<ParametersList>(key)) { // map{key -> ParametersList}
229 plist.erase(key);
230 const auto& pit = user_params.get<ParametersList>(key);
231 for (const auto& kit : pit.keys())
232 plist.operator[]<ParametersList>(key).operator[]<ParametersList>(kit) =
233 obj_descr_.at(key).validate(pit.get<ParametersList>(kit));
234 }
235 }
236 for (const auto& kv : obj_descr_) { // simple value
237 if (!kv.second.allowedValues().allAllowed()) {
238 const auto validation_error =
239 [](const auto& key, const auto& val, const ParametersDescription& desc) -> std::string {
240 std::ostringstream os;
241 os << "Invalid value for key '" << key << "'"
242 << (!desc.description().empty() ? " ("s + desc.description() + ")" : "") << ".\n"
243 << "Allowed values:\n";
244 for (const auto& kv : desc.allowedValues().allowed())
245 os << " * " << kv.first << (!kv.second.empty() ? " (" + kv.second + ")" : "") << "\n";
246 os << "Steered value: '" << utils::toString(val) + "'.";
247 return os.str();
248 };
249 if (plist.has<int>(kv.first) && !kv.second.allowedValues().validate(plist.get<int>(kv.first)))
250 throw CG_FATAL("ParametersDescription:validate")
251 << validation_error(kv.first, plist.get<int>(kv.first), kv.second);
252 if (plist.has<std::string>(kv.first) && !kv.second.allowedValues().validate(plist.get<std::string>(kv.first)))
253 throw CG_FATAL("ParametersDescription:validate")
254 << validation_error(kv.first, plist.get<std::string>(kv.first), kv.second);
255 }
256 }
257 CG_DEBUG_LOOP("ParametersDescription:validate") << "Validating user parameters:\n"
258 << "User-steered: " << user_params << ".\n"
259 << "Base/default: " << parameters() << ".\n"
260 << "-> Resulting: " << plist << ".\n";
261 return plist;
262 }
263
265 ParametersDescription pdesc(*this);
266 pdesc += ParametersDescription(params);
267 return pdesc;
268 }
269
270 template <>
271 ParametersDescription& ParametersDescription::setKey<std::string>(const std::string& key) {
272 mod_key_ = key;
273 return *this;
274 }
275
276 ParametersDescription& ParametersDescription::allow(int val, const std::string& descr) {
277 obj_values_.int_vals_[val] = descr;
278 obj_values_.all_allowed_ = false;
279 return *this;
280 }
281
282 ParametersDescription& ParametersDescription::allow(const std::string& val, const std::string& descr) {
283 obj_values_.str_vals_[val] = descr;
284 obj_values_.all_allowed_ = false;
285 return *this;
286 }
287
288 std::ostream& operator<<(std::ostream& os, const ParametersDescription& desc) { return os << desc.describe(); }
289
290 std::ostream& operator<<(std::ostream& os, const ParametersDescription::Type& type) {
291 switch (type) {
293 return os << "Value";
295 return os << "Module";
297 return os << "Parameters";
299 return os << "Parameters vector";
300 }
301 return os << "{invalid}";
302 }
303
304 bool ParametersDescription::ParameterValues::empty() const { return int_vals_.empty() && str_vals_.empty(); }
305
308 int_vals_.insert(oth.int_vals_.begin(), oth.int_vals_.end());
309 str_vals_.insert(oth.str_vals_.begin(), oth.str_vals_.end());
310 return *this;
311 }
312
313 std::map<std::string, std::string> ParametersDescription::ParameterValues::allowed() const {
314 auto out = str_vals_;
315 for (const auto& val : int_vals_)
316 out[std::to_string(val.first)] = val.second;
317 return out;
318 }
319
321 if (allAllowed())
322 return true;
323 return int_vals_.count(val) > 0;
324 }
325
326 bool ParametersDescription::ParameterValues::validate(const std::string& val) const {
327 if (allAllowed())
328 return true;
329 return str_vals_.count(val) > 0;
330 }
331
332 std::ostream& operator<<(std::ostream& os, const ParametersDescription::ParameterValues& vals) {
333 os << "Allowed values:";
334 if (vals.allAllowed())
335 return os << " any";
336 if (vals.empty())
337 return os << " none";
338 if (!vals.int_vals_.empty())
339 os << " integer{" << utils::repr(utils::keys(vals.int_vals_)) << "}";
340 if (!vals.str_vals_.empty())
341 os << " string{" << utils::repr(utils::keys(vals.str_vals_)) << "}";
342 return os;
343 }
344} // namespace cepgen
#define CG_FATAL(mod)
Definition Exception.h:61
#define CG_DEBUG_LOOP(mod)
Definition Message.h:224
A collection of valid values for a given parameter.
bool empty() const
Check if a parameter has a limited set of allowed values.
bool allAllowed() const
Are all values allowed?
ParameterValues & append(const ParameterValues &)
Merge two collections of allowed values.
bool validate(int) const
Check if an integer value is allowed for a parameter.
std::map< std::string, std::string > allowed() const
Helper list of allowed values (all types) for a parameter.
A description object for parameters collection.
ParametersList & parameters()
List of parameters associated to this description object.
bool has(const std::string &) const
Ensure the description exists.
friend std::ostream & operator<<(std::ostream &, const ParametersDescription &)
Human-readable description.
ParametersDescription(const std::string &mod_key="")
Build the description of a parameters collection object.
ParametersDescription & setDescription(const std::string &descr)
Set the description of this parameter (or parameters collection)
ParametersDescription & operator+=(const ParametersDescription &)
Concatenate another description to this one.
bool empty() const
Does a description of this parameter (or parameters collection) exist?
ParametersDescription & allow(int, const std::string &="")
Allow an integer value for a parameter.
Type type() const
Get the type of parameter considered.
const ParametersDescription & get(const std::string &) const
Get the description of a sub-object.
ParametersDescription & addParametersDescriptionVector(const std::string &, const ParametersDescription &, const std::vector< ParametersList > &def={})
Add the description to a collection of ParametersList objects.
ParametersDescription steer(const ParametersList &) const
Set parameters value for this description object.
ParametersDescription & setKey(const I &key)
Set the module name for this parameter (or parameters collection)
const std::string & key() const
Module name for this parameter.
std::string describe(size_t offset=0) const
Human-readable description of parameters and their default value.
ParametersList validate(const ParametersList &) const
Validate a set of used-steered parameters.
bool has(const std::string &key) const
Check if a given parameter is handled in this list.
std::string name(const std::string &def="") const
Retrieve the module name if any.
ParametersList & operator+=(const ParametersList &oth)
Concatenate two parameters containers.
std::vector< std::string > keys(bool name_key=true) const
size_t erase(const std::string &)
Erase a parameter with key.
T get(const std::string &key, const T &def=default_arg< T >::get()) const
Get a parameter value.
std::string getNameString(bool wrap=false) const
Get a string-converted version of the module name if any.
std::vector< std::string > keysOf() const
List of keys for one type in this list of parameters List of keys handled in this list of parameters.
std::string getString(const std::string &key, bool wrap=false) const
Get a string-converted version of a value.
std::vector< K > keys(const std::map< K, T > &coll)
Retrieve all keys from a map.
Definition Collections.h:33
std::string boldify(std::string str)
String implementation of the boldification procedure.
Definition String.cpp:49
std::string repr(const std::vector< T > &vec, const std::function< std::string(const T &)> &printer, const std::string &sep=",")
Helper to print a vector.
Definition String.h:156
std::string trim(const std::string &str)
Trim leading and trailing spaces.
Definition String.h:174
std::string toString(const std::wstring &str)
Convert a wide characters to a standard characters string.
Definition String.cpp:151
bool contains(const std::vector< T > &coll, const T &item)
Check if a vector contains an item.
Definition Collections.h:47
std::string colourise(const std::string &str, const Colour &col, const Modifier &mod)
Colourise a string for TTY-type output streams.
Definition String.cpp:70
Common namespace for this Monte Carlo generator.
std::ostream & operator<<(std::ostream &os, const Exception::Type &type)
Definition Exception.cpp:59