HepMC3 event record library
HEPEVT_Wrapper.cc
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/**
7 * @file HEPEVT_Wrapper.cc
8 * @brief Implementation of helper functions used to manipulate with HEPEVT block
9 */
10#include <algorithm>
11#include <array>
12#include <set>
13#include <vector>
14
19namespace HepMC3
20{
21
22
23/** @brief comparison of two particles */
24bool GenParticlePtr_greater::operator()(ConstGenParticlePtr lx, ConstGenParticlePtr rx) const
25{
26 /* Cannot use id as it could be different.*/
27 if (lx->pid() != rx->pid()) return (lx->pid() < rx->pid());
28 if (lx->status() != rx->status()) return (lx->status() < rx->status());
29 /*Hopefully it will reach this point not too often.*/
30 return (lx->momentum().e() < rx->momentum().e());
31}
32
33/** @brief Order vertices with equal paths. If the paths are equal, order in other quantities.
34 * We cannot use id, as it can be assigned in different way*/
35bool pair_GenVertexPtr_int_greater::operator()(const std::pair<ConstGenVertexPtr, int>& lx, const std::pair<ConstGenVertexPtr, int>& rx) const
36{
37 if (lx.second != rx.second) return (lx.second < rx.second);
38 if (lx.first->particles_in().size() != rx.first->particles_in().size()) return (lx.first->particles_in().size() < rx.first->particles_in().size());
39 if (lx.first->particles_out().size() != rx.first->particles_out().size()) return (lx.first->particles_out().size() < rx.first->particles_out().size());
40 /* The code below is usefull mainly for debug. Assures strong ordering.*/
41 std::vector<int> lx_id_in;
42 lx_id_in.reserve(lx.first->particles_in().size());
43 std::vector<int> rx_id_in;
44 rx_id_in.reserve(rx.first->particles_in().size());
45 for (const ConstGenParticlePtr& pp: lx.first->particles_in()) lx_id_in.emplace_back(pp->pid());
46 for (const ConstGenParticlePtr& pp: rx.first->particles_in()) rx_id_in.emplace_back(pp->pid());
47 std::sort(lx_id_in.begin(), lx_id_in.end());
48 std::sort(rx_id_in.begin(), rx_id_in.end());
49 for (unsigned int i = 0; i < lx_id_in.size(); i++) if (lx_id_in[i] != rx_id_in[i]) return (lx_id_in[i] < rx_id_in[i]);
50
51 std::vector<int> lx_id_out;
52 lx_id_out.reserve(lx.first->particles_out().size());
53 std::vector<int> rx_id_out;
54 rx_id_out.reserve(rx.first->particles_out().size());
55 for (const ConstGenParticlePtr& pp: lx.first->particles_in()) lx_id_out.emplace_back(pp->pid());
56 for (const ConstGenParticlePtr& pp: rx.first->particles_in()) rx_id_out.emplace_back(pp->pid());
57 std::sort(lx_id_out.begin(), lx_id_out.end());
58 std::sort(rx_id_out.begin(), rx_id_out.end());
59 for (unsigned int i = 0; i < lx_id_out.size(); i++) if (lx_id_out[i] != rx_id_out[i]) return (lx_id_out[i] < rx_id_out[i]);
60
61 std::vector<double> lx_mom_in;
62 std::vector<double> rx_mom_in;
63 for (const ConstGenParticlePtr& pp: lx.first->particles_in()) lx_mom_in.emplace_back(pp->momentum().e());
64 for (const ConstGenParticlePtr& pp: rx.first->particles_in()) rx_mom_in.emplace_back(pp->momentum().e());
65 std::sort(lx_mom_in.begin(), lx_mom_in.end());
66 std::sort(rx_mom_in.begin(), rx_mom_in.end());
67 for (unsigned int i = 0; i < lx_mom_in.size(); i++) if (lx_mom_in[i] != rx_mom_in[i]) return (lx_mom_in[i] < rx_mom_in[i]);
68
69 std::vector<double> lx_mom_out;
70 std::vector<double> rx_mom_out;
71 for (const ConstGenParticlePtr& pp: lx.first->particles_in()) lx_mom_out.emplace_back(pp->momentum().e());
72 for (const ConstGenParticlePtr& pp: rx.first->particles_in()) rx_mom_out.emplace_back(pp->momentum().e());
73 std::sort(lx_mom_out.begin(), lx_mom_out.end());
74 std::sort(rx_mom_out.begin(), rx_mom_out.end());
75 for (unsigned int i = 0; i < lx_mom_out.size(); i++) if (lx_mom_out[i] != rx_mom_out[i]) return (lx_mom_out[i] < rx_mom_out[i]);
76 /* The code above is usefull mainly for debug*/
77
78 //return (lx.first < lx.first); /*This is random. This should never happen*/
79 return false;
80}
81/** @brief Calculates the path to the top (beam) particles */
82void calculate_longest_path_to_top(ConstGenVertexPtr v, std::map<ConstGenVertexPtr, int>& pathl)
83{
84 int p = 0;
85 for (const ConstGenParticlePtr& pp: v->particles_in()) {
86 ConstGenVertexPtr v2 = pp->production_vertex();
87 if (v2 == v) continue; //LOOP! THIS SHOULD NEVER HAPPEN FOR A PROPER EVENT!
88 if (!v2) { p = std::max(p, 1); }
89 else
90 {if (pathl.count(v2) == 0) calculate_longest_path_to_top(v2, pathl); p = std::max(p, pathl[v2]+1);}
91 }
92 pathl[v] = p;
93}
94
95/** @brief pointer to the common block */
96HEPMC3_EXPORT_API struct HEPEVT* hepevtptr = nullptr;
97HEPMC3_EXPORT_API std::shared_ptr<struct HEPEVT_Pointers<double> > HEPEVT_Wrapper_Runtime_Static::m_hepevtptr = nullptr;
99
100/** @brief Set the address */
102 m_hepevtptr = std::make_shared<struct HEPEVT_Pointers<double> >();
103 char* x = c;
104 m_hepevtptr->nevhep = reinterpret_cast<int*> (x);
105 x += sizeof(int);
106 m_hepevtptr->nhep = reinterpret_cast<int*> (x);
107 x += sizeof(int);
108 m_hepevtptr->isthep = reinterpret_cast<int*> (x);
109 x += sizeof(int)*m_max_particles;
110 m_hepevtptr->idhep = reinterpret_cast<int*> (x);
111 x += sizeof(int)*m_max_particles;
112 m_hepevtptr->jmohep = reinterpret_cast<int*> (x);
113 x += sizeof(int)*m_max_particles*2;
114 m_hepevtptr->jdahep = reinterpret_cast<int*> (x);
115 x += sizeof(int)*m_max_particles*2;
116 m_hepevtptr->phep = reinterpret_cast<double*> (x);
117 x += sizeof(double)*m_max_particles*5;
118 m_hepevtptr->vhep = reinterpret_cast<double*> (x);
119}
120
121
122void HEPEVT_Wrapper_Runtime::print_hepevt( std::ostream& ostr ) const
123{
124 ostr << " Event No.: " << *(m_hepevtptr->nevhep) << std::endl;
125 ostr << " Nr Type Parent(s) Daughter(s) Px Py Pz E Inv. M." << std::endl;
126 for ( int i = 1; i <= *(m_hepevtptr->nhep); ++i )
127 {
128 print_hepevt_particle( i, ostr );
129 }
130}
131
132
133void HEPEVT_Wrapper_Runtime::print_hepevt_particle( int index, std::ostream& ostr ) const
134{
135 std::array<char, 255> buf{};//Note: the format is fixed, so no reason for complicated treatment
136
137 snprintf(buf.data(), buf.size(), "%5i %6i%4i - %4i %4i - %4i %8.2f %8.2f %8.2f %8.2f %8.2f",
138 index, m_hepevtptr->idhep[index-1],
139 m_hepevtptr->jmohep[2*(index-1)], m_hepevtptr->jmohep[2*(index-1)+1],
140 m_hepevtptr->jdahep[2*(index-1)], m_hepevtptr->jdahep[2*(index-1)+1],
141 m_hepevtptr->phep[5*(index-1)], m_hepevtptr->phep[5*(index-1)+1], m_hepevtptr->phep[5*(index-1)+2], m_hepevtptr->phep[5*(index-1)+3], m_hepevtptr->phep[5*(index-1)+4]);
142 ostr << buf.data() << std::endl;
143}
144
145
147{
148 *(m_hepevtptr->nevhep) = 0;
149 *(m_hepevtptr->nhep) = 0;
150 memset(m_hepevtptr->isthep, 0, sizeof(int)*m_max_particles);
151 memset(m_hepevtptr->idhep, 0, sizeof(int)*m_max_particles);
152 memset(m_hepevtptr->jmohep, 0, sizeof(int)*m_max_particles*2);
153 memset(m_hepevtptr->jdahep, 0, sizeof(int)*m_max_particles*2);
154 memset(m_hepevtptr->phep, 0, sizeof(double)*m_max_particles*5);
155 memset(m_hepevtptr->vhep, 0, sizeof(double)*m_max_particles*4);
156}
157
158
159int HEPEVT_Wrapper_Runtime::number_parents( const int index ) const
160{
161 return (m_hepevtptr->jmohep[2*(index-1)]) ? (m_hepevtptr->jmohep[2*(index-1)+1]) ? m_hepevtptr->jmohep[2*(index-1)+1]
162 -m_hepevtptr->jmohep[2*(index-1)] : 1 : 0;
163}
164
165
166int HEPEVT_Wrapper_Runtime::number_children( const int index ) const
167{
168 return (m_hepevtptr->jdahep[2*(index-1)]) ? (m_hepevtptr->jdahep[2*(index-1)+1]) ? m_hepevtptr->jdahep[2*(index-1)+1]-m_hepevtptr->jdahep[2*(index-1)] : 1 : 0;
169}
170
172{
173 int nc = 0;
174 for ( int i = 1; i <= *(m_hepevtptr->nhep); ++i ) {
175 if (((m_hepevtptr->jmohep[2*(i-1)] <= index && m_hepevtptr->jmohep[2*(i-1)+1] >= index)) || (m_hepevtptr->jmohep[2*(i-1)] == index) ||
176 (m_hepevtptr->jmohep[2*(index-1)+1]==index)) nc++;
177 }
178 return nc;
179}
180
181void HEPEVT_Wrapper_Runtime::set_parents( const int index, const int firstparent, const int lastparent )
182{
183 m_hepevtptr->jmohep[2*(index-1)] = firstparent;
184 m_hepevtptr->jmohep[2*(index-1)+1] = lastparent;
185}
186
187void HEPEVT_Wrapper_Runtime::set_children( const int index, const int firstchild, const int lastchild )
188{
189 m_hepevtptr->jdahep[2*(index-1)] = firstchild;
190 m_hepevtptr->jdahep[2*(index-1)+1] = lastchild;
191}
192
193
194void HEPEVT_Wrapper_Runtime::set_momentum( const int index, const double px, const double py, const double pz, const double e )
195{
196 m_hepevtptr->phep[5*(index-1)] = px;
197 m_hepevtptr->phep[5*(index-1)+1] = py;
198 m_hepevtptr->phep[5*(index-1)+2] = pz;
199 m_hepevtptr->phep[5*(index-1)+3] = e;
200}
201
202
203void HEPEVT_Wrapper_Runtime::set_mass( const int index, double mass )
204{
205 m_hepevtptr->phep[5*(index-1)+4] = mass;
206}
207
208
209void HEPEVT_Wrapper_Runtime::set_position( const int index, const double x, const double y, const double z, const double t )
210{
211 m_hepevtptr->vhep[4*(index-1)] = x;
212 m_hepevtptr->vhep[4*(index-1)+1] = y;
213 m_hepevtptr->vhep[4*(index-1)+2] = z;
214 m_hepevtptr->vhep[4*(index-1)+3] = t;
215}
216
217
219{
220 /*AV The function should be called for a record that has correct particle ordering and mother ids.
221 As a result it produces a record with ranges where the daughters can be found.
222 Not every particle in the range will be a daughter. It is true only for proper events.
223 The return tells if the record was fixed succesfully.
224 */
225 for ( int i = 1; i <= number_entries(); i++ ) {
226 for ( int k=1; k <= number_entries(); k++ ) {
227 if (i != k) {
228 if ((first_parent(k) <= i) && (i <= last_parent(k))) {
229 set_children(i, (first_child(i) == 0 ? k : std::min(first_child(i), k)), (last_child(i) == 0 ? k : std::max(last_child(i), k)));
230 }
231 }
232 }
233 }
234 bool is_fixed = true;
235 for ( int i = 1; i <= number_entries(); i++ ) {
236 is_fixed = (is_fixed && (number_children_exact(i) == number_children(i)));
237 }
238 return is_fixed;
239}
240
241
243{
244 m_internal_storage.reserve(2*sizeof(int)+m_max_particles*(6*sizeof(int)+9*sizeof(double)));
246}
247
249{
250 if ( N < 1 || N > m_max_particles) return;
251 char* dest = m_internal_storage.data();
252 char* src = c;
253 memcpy(dest, src, 2*sizeof(int));
254 src += 2*sizeof(int);
255 dest += 2*sizeof(int);
256 memcpy(dest, src, N*sizeof(int));
257 src += N*sizeof(int);
258 dest += m_max_particles*sizeof(int);
259 memcpy(dest, src, N*sizeof(int));
260 src += N*sizeof(int);
261 dest += m_max_particles*sizeof(int);
262 memcpy(dest, src, 2*N*sizeof(int));
263 src += 2*N*sizeof(int);
264 dest += 2*m_max_particles*sizeof(int);
265 memcpy(dest, src, 2*N*sizeof(int));
266 src += 2*N*sizeof(int);
267 dest += 2*m_max_particles*sizeof(int);
268 memcpy(dest, src, 5*N*sizeof(double));
269 src += 5*N*sizeof(double);
270 dest += 5*m_max_particles*sizeof(double);
271 memcpy(dest, src, 4*N*sizeof(double));
272}
273
274} // namespace HepMC3
Helper functions used to manipulate with HEPEVT block.
Definition of class HEPEVT_Wrapper.
Definition of class HEPEVT_Wrapper_Runtime.
Definition of class HEPEVT_Wrapper_Runtime_Static.
static HEPMC3_EXPORT_API int m_max_particles
Block size.
static HEPMC3_EXPORT_API std::shared_ptr< struct HEPEVT_Pointers< double > > m_hepevtptr
Fortran common block HEPEVT.
int first_child(const int index) const
Get index of 1st daughter.
int last_parent(const int index) const
Get index of last mother.
int last_child(const int index) const
Get index of last daughter.
void allocate_internal_storage()
Allocates m_internal_storage storage in smart pointer to hold HEPEVT of fixed size.
int first_parent(const int index) const
Get index of 1st mother.
double pz(const int index) const
Get Z momentum.
void zero_everything()
Set all entries in HEPEVT to zero.
double py(const int index) const
Get Y momentum.
void set_parents(const int index, const int firstparent, const int lastparent)
Set parents.
int number_children_exact(const int index) const
Get number of children by counting.
void print_hepevt_particle(int index, std::ostream &ostr=std::cout) const
Print particle information.
double t(const int index) const
Get production time.
void set_momentum(const int index, const double px, const double py, const double pz, const double e)
Set 4-momentum.
void set_children(const int index, const int firstchild, const int lastchild)
Set children.
int number_parents(const int index) const
Get number of parents.
void set_position(const int index, const double x, const double y, const double z, const double t)
Set position in time-space.
double y(const int index) const
Get Y Production vertex.
bool fix_daughters()
Tries to fix list of daughters.
int number_entries() const
Get number of entries.
void set_hepevt_address(char *c)
Set Fortran block address.
double px(const int index) const
Get X momentum.
std::vector< char > m_internal_storage
Internalstorage storage. Optional.
int number_children(const int index) const
Get number of children from the range of daughters.
double z(const int index) const
Get Z Production vertex.
void print_hepevt(std::ostream &ostr=std::cout) const
Print information from HEPEVT common block.
void set_mass(const int index, double mass)
Set mass.
double x(const int index) const
Get X Production vertex.
void copy_to_internal_storage(char *c, int N)
Copies the content of foreign common block into the internal storage.
std::shared_ptr< struct HEPEVT_Pointers< double > > m_hepevtptr
Fortran common block HEPEVT.
double e(const int index) const
Get Energy.
HepMC3 main namespace.
void calculate_longest_path_to_top(ConstGenVertexPtr v, std::map< ConstGenVertexPtr, int > &pathl)
Calculates the path to the top (beam) particles.
HEPMC3_EXPORT_API struct HEPEVT * hepevtptr
pointer to the common block
Fortran common block HEPEVT.
bool operator()(ConstGenParticlePtr lx, ConstGenParticlePtr rx) const
comparison of two particles
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....