HepMC3 event record library
HEPEVT_Helpers.h
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of HepMC
4// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
5//
6#ifndef HEPEVT_HELPERS_H
7#define HEPEVT_HELPERS_H
8/**
9 * @file HEPEVT_Helpers.h
10 * @brief Helper functions used to manipulate with HEPEVT block
11 *
12 */
13#if defined(WIN32)&&(!defined(HEPMC3_NO_EXPORTS))
14#if defined(HepMC3_EXPORTS)
15#define HEPMC3_EXPORT_API __declspec(dllexport)
16#else
17#define HEPMC3_EXPORT_API __declspec(dllimport)
18#endif
19#else
20#define HEPMC3_EXPORT_API
21#endif
22#include <algorithm>
23#include <map>
24
25#include "HepMC3/GenEvent.h"
26#include "HepMC3/GenParticle.h"
27#include "HepMC3/GenVertex.h"
28namespace HepMC3
29{
30
31/** @struct HEPEVT_Templated
32 * @brief C structure representing Fortran common block HEPEVT
33 * T. Sjöstrand et al., "A proposed standard event record",
34 * in `Z physics at LEP 1', eds. G. Altarelli, R. Kleiss and C. Verzegnassi,
35 * Geneva, Switzerland, September 4-5, 1989, CERN 89-08 (Geneva, 1989), Vol. 3, p. 327
36 * Disk representation is given by Fortran WRITE/READ format.
37 */
38template <int max_particles, typename momentum_type = double>
40{
41 int nevhep; //!< Event number
42 int nhep; //!< Number of entries in the event
43 int isthep[max_particles]; //!< Status code
44 int idhep [max_particles]; //!< PDG ID
45 int jmohep[max_particles][2]; //!< Position of 1st and 2nd (or last!) mother
46 int jdahep[max_particles][2]; //!< Position of 1nd and 2nd (or last!) daughter
47 momentum_type phep [max_particles][5]; //!< Momentum: px, py, pz, e, m
48 momentum_type vhep [max_particles][4]; //!< Time-space position: x, y, z, t
49};
50
51/** @struct HEPEVT_Templated
52 * @brief C structure representing Fortran common block HEPEVT
53 * T. Sjöstrand et al., "A proposed standard event record",
54 * in `Z physics at LEP 1', eds. G. Altarelli, R. Kleiss and C. Verzegnassi,
55 * Geneva, Switzerland, September 4-5, 1989, CERN 89-08 (Geneva, 1989), Vol. 3, p. 327
56 * Disk representation is given by Fortran WRITE/READ format.
57 */
58template <int max_particles, typename momentum_type = double>
60{
61 int nevhep; //!< Event number
62 int nhep; //!< Number of entries in the event
63 int isthep[max_particles]; //!< Status code
64 int idhep [max_particles]; //!< PDG ID
65 int jmohep[max_particles*2]; //!< Position of 1st and 2nd (or last!) mother
66 int jdahep[max_particles*2]; //!< Position of 1nd and 2nd (or last!) daughter
67 momentum_type phep [max_particles*5]; //!< Momentum: px, py, pz, e, m
68 momentum_type vhep [max_particles*4]; //!< Time-space position: x, y, z, t
69};
70
71/** @struct HEPEVT_Pointers
72 * @brief C structure representing Fortran common block HEPEVT
73 * T. Sjöstrand et al., "A proposed standard event record",
74 * in `Z physics at LEP 1', eds. G. Altarelli, R. Kleiss and C. Verzegnassi,
75 * Geneva, Switzerland, September 4-5, 1989, CERN 89-08 (Geneva, 1989), Vol. 3, p. 327
76 * Disk representation is given by Fortran WRITE/READ format.
77 */
78template<typename momentum_type = double>
80{
81 int* nevhep; //!< Pointer to Event number
82 int* nhep; //!< Pointer to Number of entries in the event
83 int* isthep; //!< Pointer to Status code
84 int* idhep; //!< Pointer to PDG ID
85 int* jmohep; //!< Pointer to position of 1st and 2nd (or last!) mother
86 int* jdahep; //!< Pointer to position of 1nd and 2nd (or last!) daughter
87 momentum_type* phep; //!< Pointer to momentum: px, py, pz, e, m
88 momentum_type* vhep; //!< Pointer to time-space position: x, y, z, t
89};
90
91/** @brief comparison of two particles */
93{
94 /** @brief comparison of two particles */
95 bool operator()(ConstGenParticlePtr lx, ConstGenParticlePtr rx) const;
96};
97/** @brief Order vertices with equal paths. */
99{
100 /** @brief Order vertices with equal paths. If the paths are equal, order in other quantities.
101 * We cannot use id, as it can be assigned in different way*/
102 bool operator()(const std::pair<ConstGenVertexPtr, int>& lx, const std::pair<ConstGenVertexPtr, int>& rx) const;
103};
104/** @brief Calculates the path to the top (beam) particles */
105void calculate_longest_path_to_top(ConstGenVertexPtr v, std::map<ConstGenVertexPtr, int>& pathl);
106
107
108/** @brief Converts HEPEVT into GenEvent. */
109template <class T>
111{
112 if ( !evt ) { std::cerr << "HEPEVT_to_GenEvent_nonstatic - passed null event." << std::endl; return false;}
113 evt->set_event_number(A->event_number());
114 std::map<GenParticlePtr, int > hepevt_particles;
115 std::map<int, GenParticlePtr > particles_index;
116 std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > > hepevt_vertices;
117 std::map<int, GenVertexPtr > vertex_index;
118 int ne=0;
119 ne=A->number_entries();
120 for ( int i = 1; i <= ne; i++ )
121 {
122 GenParticlePtr p = std::make_shared<GenParticle>();
123 p->set_momentum(FourVector(A->px(i), A->py(i), A->pz(i), A->e(i)));
124 p->set_status(A->status(i));
125 p->set_pid(A->id(i)); //Confusing!
126 p->set_generated_mass(A->m(i));
127 hepevt_particles[p] = i;
128 particles_index[i] = p;
129 GenVertexPtr v = std::make_shared<GenVertex>();
130 v->set_position(FourVector(A->x(i), A->y(i), A->z(i), A->t(i)));
131 v->add_particle_out(p);
132 std::set<int> in;
133 std::set<int> out;
134 out.insert(i);
135 vertex_index[i] = v;
136 hepevt_vertices[v] = std::pair<std::set<int>, std::set<int> >(in, out);
137 }
138 /* The part above is always correct as it is a raw information without any topology.*/
139
140 /* In this way we trust mother information. The "Trust daughters" is not implemented.*/
141 for (std::map<GenParticlePtr, int >::iterator it1 = hepevt_particles.begin(); it1 != hepevt_particles.end(); ++it1)
142 for (std::map<GenParticlePtr, int >::iterator it2 = hepevt_particles.begin(); it2 != hepevt_particles.end(); ++it2) {
143 if (A->first_parent(it2->second) <= it1->second && it1->second <= A->last_parent(it2->second)) hepevt_vertices[it2->first->production_vertex()].first.insert(it1->second);
144 }
145 /* Now all incoming sets are correct for all vertices. But we have duplicates.*/
146
147 /* Disconnect all particles from the vertices*/
148 for ( int i = 1; i <= A->number_entries(); i++ ) vertex_index[i]->remove_particle_out(particles_index[i]);
149
150 /*Fill container with vertices with unique sets of incoming particles. Merge the outcoming particle sets.*/
151 std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > > final_vertices_map;
152 for (std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > >::iterator vs = hepevt_vertices.begin(); vs != hepevt_vertices.end(); ++vs)
153 {
154 if ((final_vertices_map.size() == 0) || (vs->second.first.size() == 0 && vs->second.second.size() != 0)) { final_vertices_map.insert(*vs); continue; } /*Always insert particles out of nowhere*/
155 std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > >::iterator v2;
156 for (v2 = final_vertices_map.begin(); v2 != final_vertices_map.end(); ++v2) if (vs->second.first == v2->second.first) {v2->second.second.insert(vs->second.second.begin(), vs->second.second.end()); break;}
157 if (v2 == final_vertices_map.end()) final_vertices_map.insert(*vs);
158 }
159
160 std::vector<GenParticlePtr> final_particles;
161 std::set<int> used;
162 for (std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > >:: iterator it = final_vertices_map.begin(); it != final_vertices_map.end(); ++it)
163 {
164 GenVertexPtr v = it->first;
165 std::set<int> in = it->second.first;
166 std::set<int> out = it->second.second;
167 used.insert(in.begin(), in.end());
168 used.insert(out.begin(), out.end());
169 for (std::set<int>::iterator el = in.begin(); el != in.end(); ++el) v->add_particle_in(particles_index[*el]);
170 if (in.size() !=0 ) for (std::set<int>::iterator el = out.begin(); el != out.end(); ++el) v->add_particle_out(particles_index[*el]);
171 }
172 for (std::set<int>::iterator el = used.begin(); el != used.end(); ++el) final_particles.push_back(particles_index[*el]);
173 /* One can put here a check on the number of particles/vertices*/
174
175 evt->add_tree(final_particles);
176
177 return true;
178}
179/** @brief Converts GenEvent into HEPEVT. */
180template <class T>
182{
183 /// This writes an event out to the HEPEVT common block. The daughters
184 /// field is NOT filled, because it is possible to contruct graphs
185 /// for which the mothers and daughters cannot both be make sequential.
186 /// This is consistent with how pythia fills HEPEVT (daughters are not
187 /// necessarily filled properly) and how IO_HEPEVT reads HEPEVT.
188 if ( !evt ) return false;
189
190 /*AV Sorting the vertices by the lengths of their longest incoming paths assures the mothers will not go before the daughters*/
191 /* Calculate all paths*/
192 std::map<ConstGenVertexPtr, int> longest_paths;
193 for (ConstGenVertexPtr v: evt->vertices()) calculate_longest_path_to_top(v, longest_paths);
194 /* Sort paths*/
195 std::vector<std::pair<ConstGenVertexPtr, int> > sorted_paths;
196 std::copy(longest_paths.begin(), longest_paths.end(), std::back_inserter(sorted_paths));
197 std::sort(sorted_paths.begin(), sorted_paths.end(), pair_GenVertexPtr_int_greater());
198
199 std::vector<ConstGenParticlePtr> sorted_particles;
200 std::vector<ConstGenParticlePtr> stable_particles;
201 /*For a valid "Trust mothers" HEPEVT record we must keep mothers together*/
202 for (std::pair<ConstGenVertexPtr, int> it: sorted_paths)
203 {
204 std::vector<ConstGenParticlePtr> Q = it.first->particles_in();
205 std::sort(Q.begin(), Q.end(), GenParticlePtr_greater());
206 std::copy(Q.begin(), Q.end(), std::back_inserter(sorted_particles));
207 /*For each vertex put all outgoing particles w/o end vertex. Ordering of particles to produces reproduceable record*/
208 for (ConstGenParticlePtr pp: it.first->particles_out())
209 if (!(pp->end_vertex())) stable_particles.push_back(pp);
210 }
211 std::sort(stable_particles.begin(), stable_particles.end(), GenParticlePtr_greater());
212 std::copy(stable_particles.begin(), stable_particles.end(), std::back_inserter(sorted_particles));
213
214 int particle_counter;
215 particle_counter = std::min(int(sorted_particles.size()), A->max_number_entries());
216 /* fill the HEPEVT event record (MD code)*/
217 A->set_event_number(evt->event_number());
218 A->set_number_entries(particle_counter);
219 for ( int i = 1; i <= particle_counter; ++i )
220 {
221 A->set_status(i, sorted_particles[i-1]->status());
222 A->set_id(i, sorted_particles[i-1]->pid());
223 FourVector m = sorted_particles[i-1]->momentum();
224 A->set_momentum(i, m.px(), m.py(), m.pz(), m.e());
225 A->set_mass(i, sorted_particles[i-1]->generated_mass());
226 if ( sorted_particles[i-1]->production_vertex() &&
227 sorted_particles[i-1]->production_vertex()->particles_in().size())
228 {
229 FourVector p = sorted_particles[i-1]->production_vertex()->position();
230 A->set_position(i, p.x(), p.y(), p.z(), p.t() );
231 std::vector<int> mothers;
232 mothers.clear();
233
234 for (ConstGenParticlePtr it: sorted_particles[i-1]->production_vertex()->particles_in())
235 for ( int j = 1; j <= particle_counter; ++j )
236 if (sorted_particles[j-1] == (it))
237 mothers.push_back(j);
238 std::sort(mothers.begin(), mothers.end());
239 if (mothers.size() == 0)
240 mothers.push_back(0);
241 if (mothers.size() == 1) mothers.push_back(mothers[0]);
242
243 A->set_parents(i, mothers.front(), mothers.back());
244 }
245 else
246 {
247 A->set_position(i, 0, 0, 0, 0);
248 A->set_parents(i, 0, 0);
249 }
250 A->set_children(i, 0, 0);
251 }
252 return true;
253}
254
255
256/** @brief Converts HEPEVT into GenEvent. */
257template <class T>
259{
260 if ( !evt ) { std::cerr << "HEPEVT_to_GenEvent_static - passed null event." << std::endl; return false;}
261 evt->set_event_number(T::event_number());
262 std::map<GenParticlePtr, int > hepevt_particles;
263 std::map<int, GenParticlePtr > particles_index;
264 std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > > hepevt_vertices;
265 std::map<int, GenVertexPtr > vertex_index;
266 int ne=0;
267 ne=T::number_entries();
268 for ( int i = 1; i <= ne; i++ )
269 {
270 GenParticlePtr p = std::make_shared<GenParticle>();
271 p->set_momentum(FourVector(T::px(i), T::py(i), T::pz(i), T::e(i)));
272 p->set_status(T::status(i));
273 p->set_pid(T::id(i)); //Confusing!
274 p->set_generated_mass(T::m(i));
275 hepevt_particles[p] = i;
276 particles_index[i] = p;
277 GenVertexPtr v = std::make_shared<GenVertex>();
278 v->set_position(FourVector(T::x(i), T::y(i), T::z(i), T::t(i)));
279 v->add_particle_out(p);
280 std::set<int> in;
281 std::set<int> out;
282 out.insert(i);
283 vertex_index[i] = v;
284 hepevt_vertices[v] = std::pair<std::set<int>, std::set<int> >(in, out);
285 }
286 /* The part above is always correct as it is a raw information without any topology.*/
287
288 /* In this way we trust mother information. The "Trust daughters" is not implemented.*/
289 for (std::map<GenParticlePtr, int >::iterator it1 = hepevt_particles.begin(); it1 != hepevt_particles.end(); ++it1)
290 for (std::map<GenParticlePtr, int >::iterator it2 = hepevt_particles.begin(); it2 != hepevt_particles.end(); ++it2) {
291 if (T::first_parent(it2->second) <= it1->second && it1->second <= T::last_parent(it2->second)) hepevt_vertices[it2->first->production_vertex()].first.insert(it1->second);
292 }
293 /* Now all incoming sets are correct for all vertices. But we have duplicates.*/
294
295 /* Disconnect all particles from the vertices*/
296 for ( int i = 1; i <= T::number_entries(); i++ ) vertex_index[i]->remove_particle_out(particles_index[i]);
297
298 /*Fill container with vertices with unique sets of incoming particles. Merge the outcoming particle sets.*/
299 std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > > final_vertices_map;
300 for (std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > >::iterator vs = hepevt_vertices.begin(); vs != hepevt_vertices.end(); ++vs)
301 {
302 if ((final_vertices_map.size() == 0) || (vs->second.first.size() == 0 && vs->second.second.size() != 0)) { final_vertices_map.insert(*vs); continue; } /*Always insert particles out of nowhere*/
303 std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > >::iterator v2;
304 for (v2 = final_vertices_map.begin(); v2 != final_vertices_map.end(); ++v2) if (vs->second.first == v2->second.first) {v2->second.second.insert(vs->second.second.begin(), vs->second.second.end()); break;}
305 if (v2 == final_vertices_map.end()) final_vertices_map.insert(*vs);
306 }
307
308 std::vector<GenParticlePtr> final_particles;
309 std::set<int> used;
310 for (std::map<GenVertexPtr, std::pair<std::set<int>, std::set<int> > >:: iterator it = final_vertices_map.begin(); it != final_vertices_map.end(); ++it)
311 {
312 GenVertexPtr v = it->first;
313 std::set<int> in = it->second.first;
314 std::set<int> out = it->second.second;
315 used.insert(in.begin(), in.end());
316 used.insert(out.begin(), out.end());
317 for (const auto& el: in) v->add_particle_in(particles_index[el]);
318 if (in.size() !=0 ) for (const auto& el: out) v->add_particle_out(particles_index[el]);
319 }
320 for (const auto& el: used) final_particles.emplace_back(particles_index[el]);
321 /* One can put here a check on the number of particles/vertices*/
322
323 evt->add_tree(final_particles);
324
325 return true;
326}
327
328/** @brief Converts GenEvent into HEPEVT. */
329template <class T>
331{
332 /// This writes an event out to the HEPEVT common block. The daughters
333 /// field is NOT filled, because it is possible to contruct graphs
334 /// for which the mothers and daughters cannot both be make sequential.
335 /// This is consistent with how pythia fills HEPEVT (daughters are not
336 /// necessarily filled properly) and how IO_HEPEVT reads HEPEVT.
337 if ( !evt ) return false;
338
339 /*AV Sorting the vertices by the lengths of their longest incoming paths assures the mothers will not go before the daughters*/
340 /* Calculate all paths*/
341 std::map<ConstGenVertexPtr, int> longest_paths;
342 for (ConstGenVertexPtr v: evt->vertices()) calculate_longest_path_to_top(v, longest_paths);
343 /* Sort paths*/
344 std::vector<std::pair<ConstGenVertexPtr, int> > sorted_paths;
345 std::copy(longest_paths.begin(), longest_paths.end(), std::back_inserter(sorted_paths));
346 std::sort(sorted_paths.begin(), sorted_paths.end(), pair_GenVertexPtr_int_greater());
347
348 std::vector<ConstGenParticlePtr> sorted_particles;
349 std::vector<ConstGenParticlePtr> stable_particles;
350 /*For a valid "Trust mothers" HEPEVT record we must keep mothers together*/
351 for (std::pair<ConstGenVertexPtr, int> it: sorted_paths)
352 {
353 std::vector<ConstGenParticlePtr> Q = it.first->particles_in();
354 std::sort(Q.begin(), Q.end(), GenParticlePtr_greater());
355 std::copy(Q.begin(), Q.end(), std::back_inserter(sorted_particles));
356 /*For each vertex put all outgoing particles w/o end vertex. Ordering of particles to produces reproduceable record*/
357 for (ConstGenParticlePtr pp: it.first->particles_out())
358 if (!(pp->end_vertex())) stable_particles.push_back(pp);
359 }
360 std::sort(stable_particles.begin(), stable_particles.end(), GenParticlePtr_greater());
361 std::copy(stable_particles.begin(), stable_particles.end(), std::back_inserter(sorted_particles));
362
363 int particle_counter;
364 particle_counter = std::min(int(sorted_particles.size()), T::max_number_entries());
365 /* fill the HEPEVT event record (MD code)*/
366 T::set_event_number(evt->event_number());
367 T::set_number_entries(particle_counter);
368 for ( int i = 1; i <= particle_counter; ++i )
369 {
370 T::set_status(i, sorted_particles[i-1]->status());
371 T::set_id(i, sorted_particles[i-1]->pid());
372 FourVector m = sorted_particles[i-1]->momentum();
373 T::set_momentum(i, m.px(), m.py(), m.pz(), m.e());
374 T::set_mass(i, sorted_particles[i-1]->generated_mass());
375 if ( sorted_particles[i-1]->production_vertex() &&
376 sorted_particles[i-1]->production_vertex()->particles_in().size())
377 {
378 FourVector p = sorted_particles[i-1]->production_vertex()->position();
379 T::set_position(i, p.x(), p.y(), p.z(), p.t() );
380 std::vector<int> mothers;
381 mothers.clear();
382
383 for (ConstGenParticlePtr it: sorted_particles[i-1]->production_vertex()->particles_in())
384 for ( int j = 1; j <= particle_counter; ++j )
385 if (sorted_particles[j-1] == (it))
386 mothers.push_back(j);
387 std::sort(mothers.begin(), mothers.end());
388 if (mothers.size() == 0)
389 mothers.push_back(0);
390 if (mothers.size() == 1) mothers.push_back(mothers[0]);
391
392 T::set_parents(i, mothers.front(), mothers.back());
393 }
394 else
395 {
396 T::set_position(i, 0, 0, 0, 0);
397 T::set_parents(i, 0, 0);
398 }
399 T::set_children(i, 0, 0);
400 }
401 return true;
402}
403
404}
405#endif
Definition of class GenEvent.
Definition of class GenParticle.
Definition of class GenVertex.
Generic 4-vector.
Definition FourVector.h:36
double e() const
Energy component of momentum.
Definition FourVector.h:135
double pz() const
z-component of momentum
Definition FourVector.h:128
double t() const
Time component of position/displacement.
Definition FourVector.h:106
double px() const
x-component of momentum
Definition FourVector.h:114
double py() const
y-component of momentum
Definition FourVector.h:121
double x() const
x-component of position/displacement
Definition FourVector.h:85
double y() const
y-component of position/displacement
Definition FourVector.h:92
double z() const
z-component of position/displacement
Definition FourVector.h:99
Stores event-related information.
Definition GenEvent.h:47
int event_number() const
Get event number.
Definition GenEvent.h:155
void set_event_number(const int &num)
Set event number.
Definition GenEvent.h:157
const std::vector< ConstGenVertexPtr > & vertices() const
Get list of vertices (const)
Definition GenEvent.cc:43
void add_tree(const std::vector< GenParticlePtr > &parts)
Add whole tree in topological order.
Definition GenEvent.cc:268
HepMC3 main namespace.
bool HEPEVT_to_GenEvent_static(GenEvent *evt)
Converts HEPEVT into GenEvent.
bool HEPEVT_to_GenEvent_nonstatic(GenEvent *evt, T *A)
Converts HEPEVT into GenEvent.
void calculate_longest_path_to_top(ConstGenVertexPtr v, std::map< ConstGenVertexPtr, int > &pathl)
Calculates the path to the top (beam) particles.
bool GenEvent_to_HEPEVT_static(const GenEvent *evt)
Converts GenEvent into HEPEVT.
bool GenEvent_to_HEPEVT_nonstatic(const GenEvent *evt, T *A)
Converts GenEvent into HEPEVT.
comparison of two particles
bool operator()(ConstGenParticlePtr lx, ConstGenParticlePtr rx) const
comparison of two particles
C structure representing Fortran common block HEPEVT T. Sjöstrand et al., "A proposed standard event ...
int * jdahep
Pointer to position of 1nd and 2nd (or last!) daughter.
int * isthep
Pointer to Status code.
int * nevhep
Pointer to Event number.
int * idhep
Pointer to PDG ID.
momentum_type * vhep
Pointer to time-space position: x, y, z, t.
momentum_type * phep
Pointer to momentum: px, py, pz, e, m.
int * jmohep
Pointer to position of 1st and 2nd (or last!) mother.
int * nhep
Pointer to Number of entries in the event.
int idhep[max_particles]
PDG ID.
momentum_type vhep[max_particles *4]
Time-space position: x, y, z, t.
int jdahep[max_particles *2]
Position of 1nd and 2nd (or last!) daughter.
int jmohep[max_particles *2]
Position of 1st and 2nd (or last!) mother.
momentum_type phep[max_particles *5]
Momentum: px, py, pz, e, m.
int isthep[max_particles]
Status code.
int nhep
Number of entries in the event.
C structure representing Fortran common block HEPEVT T. Sjöstrand et al., "A proposed standard event ...
int jmohep[max_particles][2]
Position of 1st and 2nd (or last!) mother.
momentum_type vhep[max_particles][4]
Time-space position: x, y, z, t.
momentum_type phep[max_particles][5]
Momentum: px, py, pz, e, m.
int idhep[max_particles]
PDG ID.
int jdahep[max_particles][2]
Position of 1nd and 2nd (or last!) daughter.
int isthep[max_particles]
Status code.
int nevhep
Event number.
int nhep
Number of entries in the event.
Order vertices with equal paths.
bool operator()(const std::pair< ConstGenVertexPtr, int > &lx, const std::pair< ConstGenVertexPtr, int > &rx) const
Order vertices with equal paths. If the paths are equal, order in other quantities....