Belle II Software development
HerwigFragHelper Class Reference

Helper class for Herwig fragmentation modules. More...

#include <HerwigFragHelper.h>

Public Member Functions

int addHepMCToGraph (HepMC::GenEvent *evt, MCParticleGraph &graph, const std::vector< int > &quarkIndices)
 Add an already-loaded HepMC::GenEvent to existing MCParticleGraph.
 

Detailed Description

Helper class for Herwig fragmentation modules.

Merges particles from an already-loaded HepMC2 GenEvent into an existing MCParticleGraph.

Definition at line 28 of file HerwigFragHelper.h.

Member Function Documentation

◆ addHepMCToGraph()

int addHepMCToGraph ( HepMC::GenEvent * evt,
MCParticleGraph & graph,
const std::vector< int > & quarkIndices )

Add an already-loaded HepMC::GenEvent to existing MCParticleGraph.

Parameters
[in]evtPointer to the HepMC2 event
[in,out]graphMCParticleGraph to extend; KKMC particles already present, Herwig particles appended after them
[in]quarkIndicesGraph indices of the original KKMC quarks, used for fallback parent linking
Returns
Number of particles added, or -1 on error

Definition at line 27 of file HerwigFragHelper.cc.

30{
31 if (!evt) { B2ERROR("HerwigFragHelper: null GenEvent passed"); return -1; }
32
33 const int nparticles = evt->particles_size();
34 if (nparticles <= 0) { B2ERROR("HepMC event has no particles"); return -1; }
35
36 const int event_offset = graph.size();
37 int n_added = 0;
38 std::unordered_map<int, int> hash_index_map;
39
40 // Build a map that takes barcode (HepMC format) -> graph-index (MCParticleGraph format).
41 // Done in two passes: identical conditions in both passes guarantees correct parent indices.
42
43 // First pass: build barcode map
44 {
45 int mapped_count = 0;
46 auto it = evt->particles_begin();
47 for (int i = 0; i < nparticles; ++i, ++it) {
48 const int st = (*it)->status();
49 const int pdg = (*it)->pdg_id();
50 if (st == 4 || st < 1) continue;
51 // PDG codes 81-99 are non-physical Herwig internal codes (undecayed clusters).
52 // Skip in both passes so the barcode->index map stays consistent.
53 if (pdg >= 81 && pdg <= 99) continue;
54 hash_index_map[(*it)->barcode()] = event_offset + mapped_count;
55 mapped_count++;
56 }
57 }
58
59 const double len_conv = HepMC::Units::conversion_factor(evt->length_unit(), HepMC::Units::CM);
60 const double mom_conv = HepMC::Units::conversion_factor(evt->momentum_unit(), HepMC::Units::GEV);
61
62 // Second pass: add particles to graph
63 auto rp = evt->particles_begin();
64 for (int i = 0; i < nparticles; ++i, ++rp) {
65 auto* dv = (*rp)->end_vertex();
66 auto* pv = (*rp)->production_vertex();
67 const int status = (*rp)->status();
68 const int pdg_code = (*rp)->pdg_id();
69
70 if (status == 4 || status < 1) continue; // identical to first pass
71 if (pdg_code >= 81 && pdg_code <= 99) continue; // identical to first pass
72
73 graph.addParticle();
74 MCParticleGraph::GraphParticle& p = graph[event_offset + n_added];
75
76 p.setPDG(pdg_code);
77
78 auto mom = (*rp)->momentum();
79 p.setMomentum(ROOT::Math::XYZVector(
80 mom.x() * mom_conv * Unit::GeV,
81 mom.y() * mom_conv * Unit::GeV,
82 mom.z() * mom_conv * Unit::GeV));
83 p.setMass((*rp)->generated_mass() * mom_conv);
84 // Recalculate E from p and m so the 4-momentum is exactly on-shell
85 const double e2 = p.getMomentum().Mag2() + p.getMass() * p.getMass();
86 p.setEnergy(e2 > 0.0 ? std::sqrt(e2) : 0.0);
87
88 if (pv) {
89 auto pos = pv->position();
90 p.setProductionVertex(ROOT::Math::XYZVector(pos.x(), pos.y(), pos.z()) * len_conv * Unit::cm);
91 p.setProductionTime(pos.t() * len_conv * Unit::cm / Const::speedOfLight);
92 p.setValidVertex(true);
93 }
94
96
97 // All status 1 photons here are Herwig QED shower / FSR photons;
98 // KKMC photons go through the sidecar files.
99 const bool isFinal = !dv && status == 1;
101 if (pdg_code == 22 && isFinal) p.addStatus(MCParticleGraph::GraphParticle::c_IsFSRPhoton);
102
103 // Note: No virtual-particle flagging needed. Herwig 7.2.0 HepMC output contains only status
104 // 1 (final), 4 (beam, skipped) and 11 (intermediates). The virtual particle
105 // (KKMC gamma*/Z0) receives c_IsVirtual via the sidecar.
106
107 // Parent linking: barcode map first, fall back to PDG-code match for beam/skipped parents
108 if (pv) {
109 auto par_it = pv->particles_begin(HepMC::parents);
110 if (par_it != pv->particles_end(HepMC::parents)) {
111 auto found = hash_index_map.find((*par_it)->barcode());
112 if (found != hash_index_map.end()) {
113 const int pidx = found->second;
114 const int sidx = event_offset + n_added;
115 if (static_cast<size_t>(pidx) < graph.size() && pidx != sidx)
116 p.comesFrom(graph[pidx]);
117 } else {
118 bool linked = false;
119 for (int qidx : quarkIndices)
120 if (static_cast<size_t>(qidx) < graph.size() && graph[qidx].getPDG() == pdg_code)
121 { p.comesFrom(graph[qidx]); linked = true; break; }
122 if (!linked && !quarkIndices.empty())
123 p.comesFrom(graph[quarkIndices[0]]);
124 }
125 }
126 }
127
128 n_added++;
129 }
130
131 // 4-momentum conservation debug check
132 {
133 double fsE = 0, fsPx = 0, fsPy = 0, fsPz = 0;
134 for (auto pit = evt->particles_begin(); pit != evt->particles_end(); ++pit) {
135 if ((*pit)->status() != 1) continue;
136 const auto& m2 = (*pit)->momentum();
137 fsE += m2.t() * mom_conv; fsPx += m2.x() * mom_conv;
138 fsPy += m2.y() * mom_conv; fsPz += m2.z() * mom_conv;
139 }
140 const double fsM2 = fsE * fsE - fsPx * fsPx - fsPy * fsPy - fsPz * fsPz;
141 B2DEBUG(10, "Post-Herwig final-state sum: E=" << fsE
142 << " M_inv=" << (fsM2 > 0.0 ? std::sqrt(fsM2) : 0.0));
143 }
144
145 B2DEBUG(10, "Added " << n_added << " particles to graph");
146 return n_added;
147}
static const double speedOfLight
[cm/ns]
Definition Const.h:695
size_t size() const
Return the number of particles in the graph.
@ c_IsFSRPhoton
bit 7: Particle is from final state radiation
Definition MCParticle.h:61
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition MCParticle.h:47
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
Definition MCParticle.h:49
static const double cm
Standard units with the value = 1.
Definition Unit.h:47
static const double GeV
Standard of [energy, momentum, mass].
Definition Unit.h:51
GraphParticle & addParticle()
Add new particle to the graph.

The documentation for this class was generated from the following files: