1313#include < cmath>
1414#include < set>
1515
16+ #if __has_include(<edm4eic/Truthiness.h>)
17+ #include < edm4eic/Truthiness.h>
18+ #include < edm4eic/TruthinessCollection.h>
19+ #endif
20+
1621namespace eicrecon {
1722
18- void Truthiness::process (const Truthiness::Input& input,
19- const Truthiness::Output& /* output */ ) const {
23+ void Truthiness::process (const Truthiness::Input& input, const Truthiness::Output& output) const {
2024
2125 const auto [mc_particles, rc_particles, associations] = input;
2226
23- double truthiness = 0.0 ;
27+ double truthiness = 0.0 ;
28+ double total_pid_contribution = 0.0 ;
29+ double total_energy_contribution = 0.0 ;
30+ double total_momentum_contribution = 0.0 ;
2431
2532 // Track which MC particles and reconstructed particles are covered by associations
2633 std::set<edm4hep::MCParticle> associated_mc_particles;
2734 std::set<edm4eic::ReconstructedParticle> associated_rc_particles;
2835
36+ #if __has_include(<edm4eic/Truthiness.h>)
37+ // Vectors to store per-association contributions
38+ std::vector<float > assoc_truthiness_vec;
39+ std::vector<float > assoc_pid_vec;
40+ std::vector<float > assoc_energy_vec;
41+ std::vector<float > assoc_momentum_vec;
42+ assoc_truthiness_vec.reserve (associations->size ());
43+ assoc_pid_vec.reserve (associations->size ());
44+ assoc_energy_vec.reserve (associations->size ());
45+ assoc_momentum_vec.reserve (associations->size ());
46+ #endif
47+
2948 // Process all associations
3049 for (const auto & assoc : *associations) {
3150 const auto & mc_part = assoc.getSim ();
@@ -66,14 +85,30 @@ void Truthiness::process(const Truthiness::Input& input,
6685 momentum_penalty, pdg_penalty);
6786
6887 truthiness += assoc_penalty;
88+ total_pid_contribution += pdg_penalty;
89+ total_energy_contribution += energy_penalty;
90+ total_momentum_contribution += momentum_penalty;
91+
92+ #if __has_include(<edm4eic/Truthiness.h>)
93+ assoc_truthiness_vec.push_back (static_cast <float >(assoc_penalty));
94+ assoc_pid_vec.push_back (static_cast <float >(pdg_penalty));
95+ assoc_energy_vec.push_back (static_cast <float >(energy_penalty));
96+ assoc_momentum_vec.push_back (static_cast <float >(momentum_penalty));
97+ #endif
6998 }
7099
71100 // Penalty for unassociated charged MC particles with generator status 2
72101 int unassociated_mc_count = 0 ;
102+ #if __has_include(<edm4eic/Truthiness.h>)
103+ std::vector<edm4hep::MCParticle> unassociated_mc_vec;
104+ #endif
73105 for (const auto & mc_part : *mc_particles) {
74106 if (mc_part.getGeneratorStatus () == 2 && mc_part.getCharge () != 0.0 ) {
75107 if (associated_mc_particles.find (mc_part) == associated_mc_particles.end ()) {
76108 unassociated_mc_count++;
109+ #if __has_include(<edm4eic/Truthiness.h>)
110+ unassociated_mc_vec.push_back (mc_part);
111+ #endif
77112 trace (" Unassociated MC particle: PDG={}, charge={:.1f}, status={}" , mc_part.getPDG (),
78113 mc_part.getCharge (), mc_part.getGeneratorStatus ());
79114 }
@@ -86,9 +121,15 @@ void Truthiness::process(const Truthiness::Input& input,
86121
87122 // Penalty for unassociated reconstructed particles
88123 int unassociated_rc_count = 0 ;
124+ #if __has_include(<edm4eic/Truthiness.h>)
125+ std::vector<edm4eic::ReconstructedParticle> unassociated_rc_vec;
126+ #endif
89127 for (const auto & rc_part : *rc_particles) {
90128 if (associated_rc_particles.find (rc_part) == associated_rc_particles.end ()) {
91129 unassociated_rc_count++;
130+ #if __has_include(<edm4eic/Truthiness.h>)
131+ unassociated_rc_vec.push_back (rc_part);
132+ #endif
92133 trace (" Unassociated reconstructed particle: PDG={}, E={:.3f}, p=[{:.3f},{:.3f},{:.3f}]" ,
93134 rc_part.getPDG (), rc_part.getEnergy (), rc_part.getMomentum ().x , rc_part.getMomentum ().y ,
94135 rc_part.getMomentum ().z );
@@ -107,6 +148,45 @@ void Truthiness::process(const Truthiness::Input& input,
107148 // Report final truthiness
108149 debug (" Event truthiness: {:.6f} (from {} associations, {} unassociated MC, {} unassociated RC)" ,
109150 truthiness, associations->size (), unassociated_mc_count, unassociated_rc_count);
151+
152+ #if __has_include(<edm4eic/Truthiness.h>)
153+ // Create output collection if available
154+ const auto [truthiness_output] = output;
155+ auto truthiness_obj = truthiness_output->create ();
156+
157+ // Set scalar values
158+ truthiness_obj.setEvent_truthiness (static_cast <float >(truthiness));
159+ truthiness_obj.setEvent_pid_contribution (static_cast <float >(total_pid_contribution));
160+ truthiness_obj.setEvent_energy_contribution (static_cast <float >(total_energy_contribution));
161+ truthiness_obj.setEvent_momentum_contribution (static_cast <float >(total_momentum_contribution));
162+ truthiness_obj.setUnassociated_mc_particles_contribution (static_cast <float >(mc_penalty));
163+ truthiness_obj.setUnassociated_rc_particles_contribution (static_cast <float >(rc_penalty));
164+
165+ // Add associations and their contributions
166+ for (const auto & assoc : *associations) {
167+ truthiness_obj.addToAssociations (assoc);
168+ }
169+ for (const auto & val : assoc_truthiness_vec) {
170+ truthiness_obj.addToAssociation_truthiness (val);
171+ }
172+ for (const auto & val : assoc_pid_vec) {
173+ truthiness_obj.addToAssociation_pid_contribution (val);
174+ }
175+ for (const auto & val : assoc_energy_vec) {
176+ truthiness_obj.addToAssociation_energy_contribution (val);
177+ }
178+ for (const auto & val : assoc_momentum_vec) {
179+ truthiness_obj.addToAssociation_momentum_contribution (val);
180+ }
181+
182+ // Add unassociated particles
183+ for (const auto & mc_part : unassociated_mc_vec) {
184+ truthiness_obj.addToUnassociated_mc_particles (mc_part);
185+ }
186+ for (const auto & rc_part : unassociated_rc_vec) {
187+ truthiness_obj.addToUnassociated_rc_particles (rc_part);
188+ }
189+ #endif
110190}
111191
112192} // namespace eicrecon
0 commit comments