Version: SMASH-2.2
rivetoutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2021 Christian Holm Christensen
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/rivetoutput.h"
11 
12 #include <Rivet/Rivet.hh>
13 #include <Rivet/Tools/Logging.hh>
14 
15 #include "smash/logging.h"
16 
17 namespace smash {
146 RivetOutput::RivetOutput(const bf::path& path, std::string name,
147  const bool full_event, const OutputParameters& out_par)
148  : HepMcInterface(name, full_event),
149  handler_(),
150  filename_(path / (name + ".yoda")),
151  need_init_(true),
152  rivet_confs_(out_par.subcon_for_rivet) {
153  handler_ = std::make_shared<Rivet::AnalysisHandler>();
154  setup();
155 }
156 
158  logg[LOutput].debug() << "Writing Rivet results to " << filename_
159  << std::endl;
160  analysis_handler_proxy()->finalize();
161  analysis_handler_proxy()->writeData(filename_.string());
162 }
163 
164 void RivetOutput::at_eventend(const Particles& particles,
165  const int32_t event_number,
166  const EventInfo& event) {
167  HepMcInterface::at_eventend(particles, event_number, event);
168 
169  // Initialize Rivet on first event
170  if (need_init_) {
171  logg[LOutput].debug() << "Initialising Rivet" << std::endl;
172  need_init_ = false;
174  }
175 
176  logg[LOutput].debug() << "Analysing event " << event_number << std::endl;
177  // Let Rivet analyse the event
178  analysis_handler_proxy()->analyze(event_);
179 }
180 
181 void RivetOutput::add_analysis(const std::string& name) {
182  analysis_handler_proxy()->addAnalysis(name);
183 }
184 
185 void RivetOutput::add_path(const std::string& path) {
186  Rivet::addAnalysisLibPath(path);
187  Rivet::addAnalysisDataPath(path);
188 }
189 
190 void RivetOutput::add_preload(const std::string& file) {
191  analysis_handler_proxy()->readData(file);
192 }
193 
194 void RivetOutput::set_ignore_beams(bool ignore) {
195  logg[LOutput].info() << "Ignore beams? " << (ignore ? "yes" : "no")
196  << std::endl;
197  analysis_handler_proxy()->setIgnoreBeams(ignore);
198 }
199 
200 void RivetOutput::set_log_level(const std::string& name,
201  const std::string& level) {
202  std::string fname(name);
203  if (fname.rfind("Rivet", 0) != 0) {
204  fname = "Rivet." + fname;
205  }
206 
207  auto upcase = [](const std::string& s) {
208  std::string out(s);
209  std::transform(out.begin(), out.end(), out.begin(),
210  [](char c) { return std::toupper(c); });
211  return out;
212  };
213 
214  try {
215  Rivet::Log::setLevel(fname, Rivet::Log::getLevelFromName(upcase(level)));
216  } catch (...) {
217  }
218 }
219 
220 void RivetOutput::set_cross_section(double xs, double xserr) {
221  analysis_handler_proxy()->setCrossSection(xs, xserr, true);
222 }
223 
225  logg[LOutput].debug() << "Setting up from configuration:\n"
226  << rivet_confs_.to_string() << std::endl;
227 
228  // Paths to analyses libraries and data
229  if (rivet_confs_.has_value({"Paths"})) {
230  logg[LOutput].info() << "Processing paths" << std::endl;
231  std::vector<std::string> path = rivet_confs_.take({"Paths"});
232  for (auto p : path)
233  add_path(p);
234  }
235 
236  // Data files to pre-load e.g., for centrality configurations
237  if (rivet_confs_.has_value({"Preloads"})) {
238  logg[LOutput].info() << "Processing preloads" << std::endl;
239  std::vector<std::string> prel = rivet_confs_.take({"Preloads"});
240  for (auto p : prel)
241  add_preload(p);
242  }
243 
244  // Analyses (including options) to add to run
245  if (rivet_confs_.has_value({"Analyses"})) {
246  logg[LOutput].info() << "Processing analyses" << std::endl;
247  std::vector<std::string> anas = rivet_confs_.take({"Analyses"});
248  for (auto p : anas)
249  add_analysis(p);
250  }
251 
252  // Whether Rivet should ignore beams
253  if (rivet_confs_.has_value({"Ignore_Beams"})) {
254  set_ignore_beams(rivet_confs_.take({"Ignore_Beams"}));
255  } else {
256  // we must explicity tell Rivet, through the handler, to ignore beam checks
257  set_ignore_beams(true);
258  }
259 
260  // Cross sections
261  if (rivet_confs_.has_value({"Cross_Section"})) {
262  std::array<double, 2> xs = rivet_confs_.take({"Cross_Section"});
263  set_cross_section(xs[0], xs[1]);
264  }
265 
266  // Logging in Rivet
267  if (rivet_confs_.has_value({"Logging"})) {
268  std::map<std::string, std::string> logs = rivet_confs_.take({"Logging"});
269  for (auto nl : logs)
270  set_log_level(nl.first, nl.second);
271  }
272 
273  // Treatment of event weights in Rivet
274  if (rivet_confs_.has_value({"Weights"})) {
275  auto wconf = rivet_confs_["Weights"];
276 
277  // Do not care about multi weights - bool
278  if (wconf.has_value({"No_Multi"})) {
279  analysis_handler_proxy()->skipMultiWeights(wconf.take({"No_Multi"}));
280  }
281 
282  // Set nominal weight name
283  if (wconf.has_value({"Nominal"})) {
284  analysis_handler_proxy()->setNominalWeightName(wconf.take({"Nominal"}));
285  }
286 
287  // Set cap (maximum) on weights
288  if (wconf.has_value({"Cap"})) {
289  analysis_handler_proxy()->setWeightCap(wconf.take({"Cap"}));
290  }
291 
292  // Whether to smear for NLO calculations
293  if (wconf.has_value({"NLO_Smearing"})) {
294  analysis_handler_proxy()->setNLOSmearing(wconf.take({"NLO_Smearing"}));
295  }
296 
297  // Select which weights to enable
298  if (wconf.has_value({"Select"})) {
299  std::vector<std::string> sel = wconf.take({"Select"});
300  std::stringstream s;
301  int comma = 0;
302  for (auto w : sel)
303  s << (comma++ ? "," : "") << w;
304  analysis_handler_proxy()->selectMultiWeights(s.str());
305  }
306 
307  // Select weights to disable
308  if (wconf.has_value({"Deselect"})) {
309  std::vector<std::string> sel = wconf.take({"Deselect"});
310  std::stringstream s;
311  int comma = 0;
312  for (auto w : sel)
313  s << (comma++ ? "," : "") << w;
314  analysis_handler_proxy()->deselectMultiWeights(s.str());
315  }
316  }
317  logg[LOutput].debug() << "After processing configuration:\n"
318  << rivet_confs_.to_string() << std::endl;
319 }
320 } // namespace smash
bool has_value(std::initializer_list< const char * > keys) const
Returns whether there is a non-empty value behind the requested keys.
std::string to_string() const
Returns a YAML string of the current tree.
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
Base class for output handlers that need the HepMC3 structure.
void at_eventend(const Particles &particles, const int32_t event_number, const EventInfo &event) override
Add the final particles information of an event to the central vertex.
HepMC3::GenEvent event_
The event.
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
Proxy analysis_handler_proxy()
Return a proxy that temporarily disables FP exceptions.
Definition: rivetoutput.h:117
void add_path(const std::string &path)
Add a load path to the Rivet handler.
Definition: rivetoutput.cc:185
void add_analysis(const std::string &name)
Add an analysis or analyses to Rivet.
Definition: rivetoutput.cc:181
void setup()
Read configuration of Rivet from SMASH configuration.
Definition: rivetoutput.cc:224
std::shared_ptr< Rivet::AnalysisHandler > handler_
Rivet analysis handler.
Definition: rivetoutput.h:120
bool need_init_
Whether we need initialisation.
Definition: rivetoutput.h:124
~RivetOutput()
Destructor.
Definition: rivetoutput.cc:157
bf::path filename_
Output file.
Definition: rivetoutput.h:122
void set_cross_section(double xs, double xserr)
Set X-section.
Definition: rivetoutput.cc:220
void add_preload(const std::string &file)
Add preload to Rivet handler.
Definition: rivetoutput.cc:190
void set_log_level(const std::string &name, const std::string &level)
Set log level in Rivet.
Definition: rivetoutput.cc:200
void at_eventend(const Particles &particles, const int32_t event_number, const EventInfo &event) override
Add the final particles information of an event to the central vertex.
Definition: rivetoutput.cc:164
Configuration rivet_confs_
Configutations for rivet.
Definition: rivetoutput.h:126
RivetOutput(const bf::path &path, std::string name, const bool full_event, const OutputParameters &out_par)
Create Rivet output.
Definition: rivetoutput.cc:146
void set_ignore_beams(bool ignore=true)
Do not insist on appropriate beams for analyses.
Definition: rivetoutput.cc:194
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
constexpr int p
Proton.
Definition: action.h:24
static constexpr int LOutput
Structure to contain custom data for output.
Helper structure for Experiment to hold output options and parameters.