Version: SMASH-3.4
hepmcoutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2020-2026
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/hepmcoutput.h"
11 
12 #include "HepMC3/Print.h"
13 #include "HepMC3/WriterAscii.h"
14 
15 #ifdef SMASH_USE_HEPMC_ROOTIO
16 #include "HepMC3/WriterRootTree.h"
17 #endif
18 
19 namespace smash {
20 // clang-format off
21 /*!\Userguide
22  * \page doxypage_output_hepmc
23  *
24  * SMASH HepMC output is an implementation of the HepMC3 Event Record Library.
25  * The aim is to provide a format compatible with other frameworks like Rivet
26  * (https://rivet.hepforge.org). For resources regarding HepMC, see
27  * http://hepmc.web.cern.ch/hepmc/ and \iref{Buckley:2019xhk}.
28  *
29  * The SMASH HepMC output can be:
30  * - _HepMC_asciiv3_ plain human readable ASCII format
31  * - _HepMC_treeroot_ ROOT Tree binary format, readable by ROOT
32  *
33  * You can find a snippet of the configuration for this output in \ref
34  * doxypage_input_conf_output_examples.
35  *
36  * Producing HepMC output in asciiv3 format requires HepMC3 to be installed.
37  * Download the tarball from http://hepmc.web.cern.ch/hepmc/
38  * and follow the instructions or use the pre-compiled packages for your
39  * OS distribution.
40  * If the user wants to produce HepMC output in ROOT Tree format,
41  * ROOT must be installed (https://root.cern.ch/), as well, and HepMC should
42  * be compiled with ROOT IO support (`-DHEPMC3_ENABLE_ROOTIO:BOOL=ON`) or,
43  * when using a binary precompiled distribution, the appropriate rootIO
44  * package must be installed.
45  *
46  * \attention
47  * At the moment **it is not possible to produce HepMC output with multiple
48  * parallel ensembles** and trying to do so will result in an error.
49  *
50  * \note
51  * - Since some HepMC readers (e.g. Rivet) need a value for the
52  * nuclei-nuclei cross section, a dummy cross section of 1.0 is written to the
53  * output.
54  * - To avoid confusion with the definition of these quantities within the
55  * Glauber model, in the header of an event we set the numbers of participants
56  * and of collisions to -1.
57  * - If you use Fermi motion and want to read in the HepMC
58  * ouput into Rivet, you need to disable the check for the beam particle
59  * energies with the \key --ignore-beams option. When using the Rivet output
60  * this check is disabled by default.
61  * - The HepMC output is best suited to \ref doxypage_input_conf_modi_collider modus, where
62  * the two ion "particles" are constructed and included as the initial incoming
63  * particles in the particle list, as well.
64  * - In other SMASH modi (box, sphere, list, etc.) only the inital
65  * and final hadrons are written out as the incoming and outgoing particles
66  * of a single vertex.
67  * - Even though in the HepMC library root and treeroot outputs are distinct, in
68  * SMASH the extension of the HepMC treeroot output is simply .root because
69  * the ROOT browser tool does not recognize the .treeroot extension.
70  *
71  * \section output_particles_collisions_ Particles and Collisions
72  *
73  * HepMC generally structures each event into particles and vertices
74  * connecting them, basically storing a graph of the event.
75  * However, in SMASH it is possible to filter the amount of information
76  * available in the output, depending on whether the HepMC_asciiv3 or
77  * HepMC_treeroot output options are specified under \key %Particles or
78  * \key Collisions (see \ref doxypage_input_conf_output for an example).
79  * - \key %Particles: the output only provides a particle
80  * <b>list of the final state</b>. In HepMC only one central vertex is created.
81  * All initial state particles are incoming particles and all final state
82  * particles are outgoing particles of this vertex. Scatterings
83  * happening during the SMASH event are not recorded. For the collider
84  * modus, the initial state particles are combined into two single
85  * colliding nucleus "particles" with a nuclear pdg code.
86  * - \key Collisions: with this format, the <b>full event tree</b> is written.
87  * Furthermore, as in the previous \key %Particles case, in collider modus
88  * we lump all incoming nucleons into nuclei, but split them out immediately
89  * afterwards to allow tracking of the individual nucleons.
90  *
91  * \attention
92  * - If the HepMC output is intended to be part of a Rivet analysis that requires
93  * access to the parent particles of the final state particles, then the \key Collisions
94  * output should be used.
95  * - By default, SMASH exclusively handles strong decays at the end of the evolution.
96  * If one intends to include all non-strong decays as well,
97  * the \key Ignore_Minimum_Decay_Width_For_Decays_At_The_End option in the
98  * \ref doxypage_input_conf_collision_term section of the configuration should be enabled.
99  *
100  * \section output_hepmc_asciiv3_ ASCII HepMC Format
101  *
102  * In this case the information about each event is inserted into a plain,
103  * human readable ascii text file.
104  *
105  * In most cases the HepMC output is read by using tools like Rivet,
106  * however it can be useful to have a basic knowledge about the most important
107  * pieces of information contained there. We refer to the official HepMC
108  * documentation for more details.
109  *
110  * Here there is an example of the first lines of the HepMC_asciiv3 output, in
111  * \key Collider modus and \key %Particles output type:
112 
113  \verbatim
114 
115  HepMC::Version 3.02.05
116  HepMC::Asciiv3-START_EVENT_LISTING
117  W Default
118  T SMASH\|SMASH-2.2.1-81-g450bc31amaster\|
119  E 0 1 772
120  U GEV MM
121  W 1.0000000000000000000000e+00
122  A 0 GenHeavyIon v0 -1 -1 -1 -1 -1 -1 -1 -1 -1 1.6090284 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 0
123  P 1 0 1000791970 -1.0269562977782698e-15 1.3877787807814457e-16 3.0788744605039813e+02 3.6105628807654466e+02 1.8859205636552139e+02 4
124  P 2 0 1000791970 -5.6898930012039273e-16 9.7144514654701197e-17 -3.0817189202123001e+02 3.6138985479939856e+02 1.8876628968114440e+02 4
125  V -1 0 [1,2]
126  P 3 -1 2112 -1.3955349705352910e-01 -3.2052252367927581e-01 -1.3070952483948553e-01 1.0095240693561323e+00 9.3799999999999994e-01 1
127  P 4 -1 2112 2.2504221328938548e-02 -8.1112446752570233e-02 1.8331677117778440e+00 2.0609302580389826e+00 9.3799999999999994e-01 1
128  P 5 -1 111 -1.7932505641335714e-01 -2.3234517783752556e-01 7.9030334352518175e-02 3.3381364751890524e-01 1.3800000000000001e-01 1
129  P 6 -1 -211 5.3428615692750892e-01 9.5409650270284543e-02 -1.6651817800882954e-01 5.8424053475982385e-01 1.3800000000000001e-01 1
130 
131  \endverbatim
132  *
133  * The first 4 lines provide information about the version of HepMC3 and
134  * of the generator (i.e. SMASH) which have been used. These lines are not
135  * repeated.
136  *
137  * Row 5: "E 0 1 772" marks the beginning of a new event, with the numbers
138  * referring to the event ID, the number of vertexes and the number of
139  * particles, respectively, which have been recorded.
140  *
141  * The content of line 8 _"A 0 GenHeavyIon ..."_ is described in
142  * Appendix A.3.3 of \iref{Buckley:2019xhk}, however SMASH
143  * prints only the value of the impact parameter (1.6090284 in the example).
144  * This line closes the header, from now on, until the record of the next
145  * event, there are only lines starting with P (for particle data) or V
146  * (vertex data).
147  *
148  * Lines 9 and 10: these are the data regarding the two colliding ions,
149  * which are treated like two big particles, with PDG code based on their
150  * atomic and mass number (79 and 197, respectively, in this example with
151  * gold).
152  *
153  * Row 11: V, i.e. vertex. The first number is the ID of the vertex, which
154  * decreases by 1 at each interaction. The square bracket contains the IDs
155  * of the incoming particles.
156  *
157  * Lines from 12: P, i.e. particle. The contents of the columns are:
158  * - "P", identifying a particle data line
159  * - the internal particle ID
160  * - the ID of the originating vertex
161  * - the particle PDG ID
162  * - particle momentum along x
163  * - particle momentum along y
164  * - particle momentum along z
165  * - particle energy
166  * - particle rest mass
167  * - interaction code ( 1: final state, 2: decay, 4: beam particle)
168  *
169  * The HepMC3_asciiv3 with output under \key Collisions presents has a similar
170  * structure, but, in addition to containing all the interaction vertexes and
171  * the non final particles, it has the following differences after the header:
172  * - a list of lines starting with "A", like
173  * "A -6311 partial_weight 99.6726",
174  * where the first number refers to a vertex ID and the partial_weights are
175  * cross sections, followed by a similar list with lines like
176  * "A -6311 weight 100.876",
177  * where the weights are total cross sections
178  * - a list of particles and vertexes, in which the interaction code now
179  * can be also one of those used by SMASH, shifted by 100 (e.g. 103 or 145)
180  *
181  * In both cases, the HepMC output file ends with the line:
182  * _HepMC::Asciiv3-END_EVENT_LISTING_, followed by an empty line.
183  *
184  * \section output_hepmc_root_ ROOT HepMC Format
185  *
186  * In this case the information about each event is inserted into a ROOT
187  * Tree structure and saved in a binary file that can be read by ROOT.
188  *
189  * Here is an example of a basic ROOT macro that displays the structure of
190  * the tree, assuming that the output file is in the same directory as the
191  * macro:
192  * \code
193  * // file name: read_treeroot.C
194  * #include <TFile.h>
195  * #include <TTree.h>
196  *
197  * int read_hempc3_treeroot() {
198  * // Opens a SMASH HepMC3 treeroot output file to be read in
199  * TFile *input_file = TFile::Open("SMASH_HepMC_particles.root","read");
200  * if (input_file->IsOpen()) {
201  * printf("Successfully opened file %s\n", input_file->GetName());
202  * } else {
203  * printf("Error at opening file %s\n", input_file->GetName());
204  * }
205  *
206  * // Shows the top level contents of the file
207  * input_file->ls();
208  *
209  * // Gets a tree from file
210  * TTree *tree = static_cast<TTree*>(input_file->Get("hepmc3_tree"));
211  *
212  * // Gets the number of entries (i.e. events) stored in the tree
213  * Int_t nentries = tree->GetEntries();
214  * std::cout << "\nThe number of entries in the tree is " << nentries <<
215  std::endl;
216  *
217  * // Prints the branches of the tree
218  * std::cout << "\n\nA bit more info:" << std::endl;
219  *
220  * tree->Print();
221  *
222  * // Extracts a bit more information
223  * std::cout << "\n\nInfo about the branch hepmc3_event:" << std::endl;
224  *
225  * TBranch *b = tree->GetBranch("hepmc3_event");
226  *
227  * tree->Show(0);
228  *
229  * input_file->Close();
230  *
231  * return 0;
232  * }
233  * \endcode
234  *
235  * To load and execute the macro with ROOT:
236  * \code
237  * root
238  * .L read_treeroot.C
239  * read_hempc3_treeroot()
240  * \endcode
241  *
242  * In the subdirectory `examples/reading_HepMC3_treeroot_output` under the
243  * SMASH source code main directory there is a basic example of a C++ code
244  * that reads the output without requiring HepMC3, but only ROOT.
245  *
246  * Among the examples of the HepMC3 library source code there is a converter
247  * between different formats. The converter allows to transform the SMASH
248  * HepMC3 output of a subtype (asciiv3 or treeroot) into the other without
249  * loss of information.
250  *
251  */
252 
253 // clang-format on
254 HepMcOutput::HepMcOutput(const std::filesystem::path &path, std::string name,
255  const bool full_event, std::string HepMC3_output_type)
256  : HepMcInterface(name, full_event),
257  filename_(path / (name + "." + HepMC3_output_type)) {
259  filename_unfinished_ += +".unfinished";
260 #ifdef SMASH_USE_HEPMC_ROOTIO
261  if (HepMC3_output_type == "asciiv3") {
262 #endif
263  output_file_ = std::make_unique<HepMC3::WriterAscii>(
264  filename_unfinished_.string(), event_.run_info());
266 #ifdef SMASH_USE_HEPMC_ROOTIO
267  } else {
268  output_file_ = std::make_unique<HepMC3::WriterRootTree>(
269  filename_unfinished_.string(), event_.run_info());
271  }
272 #endif
273 }
275  logg[LOutput].debug() << "Renaming file " << filename_unfinished_ << " to "
276  << filename_ << std::endl;
277  output_file_->close();
278  std::filesystem::rename(filename_unfinished_, filename_);
279 }
280 
281 void HepMcOutput::at_eventend(const Particles &particles,
282  const EventLabel &event_label,
283  const EventInfo &event) {
284  HepMcInterface::at_eventend(particles, event_label, event);
285  logg[LOutput].debug() << "Writing event " << event_label.event_number
286  << " with " << event_.particles().size()
287  << " particles and " << event_.vertices().size()
288  << " vertices to output " << std::endl;
289  output_file_->write_event(event_);
290 }
291 
292 } // namespace smash
Base class for output handlers that need the HepMC3 structure.
void at_eventend(const Particles &particles, const EventLabel &event_label, const EventInfo &event) override
Add the final particles information of an event to the central vertex.
HepMC3::GenEvent event_
The event.
const std::filesystem::path filename_
Filename of output.
Definition: hepmcoutput.h:66
HepMcOutput(const std::filesystem::path &path, std::string name, const bool full_event, std::string HepMC3_output_type)
Create HepMC particle output.
Definition: hepmcoutput.cc:254
void at_eventend(const Particles &particles, const EventLabel &event_label, const EventInfo &event) override
Add the final particles information of an event to the central vertex.
Definition: hepmcoutput.cc:281
~HepMcOutput()
Destructor renames file.
Definition: hepmcoutput.cc:274
std::filesystem::path filename_unfinished_
Filename of output as long as simulation is still running.
Definition: hepmcoutput.h:68
type_of_HepMC3_output output_type_
HepMC3 output type.
Definition: hepmcoutput.h:74
std::unique_ptr< HepMC3::Writer > output_file_
Pointers to the base class of HepMC3 output files.
Definition: hepmcoutput.h:70
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > & logg
An array that stores all pre-configured Logger objects.
Definition: logging.h:245
Definition: action.h:24
static constexpr int LOutput
Structure to contain custom data for output.
Structure to contain information about the event and ensemble numbers.
int32_t event_number
The number of the event.