Skip to content

Commit 802616a

Browse files
committed
feat: implement Truthiness processor for event quality assessment (uses algorithm)
1 parent 3da4aca commit 802616a

File tree

5 files changed

+135
-12
lines changed

5 files changed

+135
-12
lines changed

src/algorithms/reco/Truthiness.cc

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ void Truthiness::process(const Truthiness::Input& input,
5858

5959
const double assoc_penalty = energy_penalty + momentum_penalty + pdg_penalty;
6060

61-
debug("Association: MC PDG={} (E={:.3f}, p=[{:.3f},{:.3f},{:.3f}]) <-> "
61+
trace("Association: MC PDG={} (E={:.3f}, p=[{:.3f},{:.3f},{:.3f}]) <-> "
6262
"RC PDG={} (E={:.3f}, p=[{:.3f},{:.3f},{:.3f}])",
6363
mc_part.getPDG(), mc_energy, mc_momentum.x, mc_momentum.y, mc_momentum.z,
6464
rc_part.getPDG(), rc_energy, rc_momentum.x, rc_momentum.y, rc_momentum.z);
65-
debug(" Energy penalty: {:.6f}, Momentum penalty: {:.6f}, PDG penalty: {:.0f}", energy_penalty,
65+
trace(" Energy penalty: {:.6f}, Momentum penalty: {:.6f}, PDG penalty: {:.0f}", energy_penalty,
6666
momentum_penalty, pdg_penalty);
6767

6868
truthiness += assoc_penalty;
@@ -74,13 +74,13 @@ void Truthiness::process(const Truthiness::Input& input,
7474
if (mc_part.getGeneratorStatus() == 2 && mc_part.getCharge() != 0.0) {
7575
if (associated_mc_particles.find(mc_part) == associated_mc_particles.end()) {
7676
unassociated_mc_count++;
77-
debug("Unassociated MC particle: PDG={}, charge={:.1f}, status={}", mc_part.getPDG(),
77+
trace("Unassociated MC particle: PDG={}, charge={:.1f}, status={}", mc_part.getPDG(),
7878
mc_part.getCharge(), mc_part.getGeneratorStatus());
7979
}
8080
}
8181
}
8282
const double mc_penalty = static_cast<double>(unassociated_mc_count);
83-
debug("Unassociated charged MC particles (status 2): {} (penalty: {:.0f})", unassociated_mc_count,
83+
trace("Unassociated charged MC particles (status 2): {} (penalty: {:.0f})", unassociated_mc_count,
8484
mc_penalty);
8585
truthiness += mc_penalty;
8686

@@ -89,19 +89,24 @@ void Truthiness::process(const Truthiness::Input& input,
8989
for (const auto& rc_part : *rc_particles) {
9090
if (associated_rc_particles.find(rc_part) == associated_rc_particles.end()) {
9191
unassociated_rc_count++;
92-
debug("Unassociated reconstructed particle: PDG={}, E={:.3f}, p=[{:.3f},{:.3f},{:.3f}]",
92+
trace("Unassociated reconstructed particle: PDG={}, E={:.3f}, p=[{:.3f},{:.3f},{:.3f}]",
9393
rc_part.getPDG(), rc_part.getEnergy(), rc_part.getMomentum().x, rc_part.getMomentum().y,
9494
rc_part.getMomentum().z);
9595
}
9696
}
9797
const double rc_penalty = static_cast<double>(unassociated_rc_count);
98-
debug("Unassociated reconstructed particles: {} (penalty: {:.0f})", unassociated_rc_count,
98+
trace("Unassociated reconstructed particles: {} (penalty: {:.0f})", unassociated_rc_count,
9999
rc_penalty);
100100
truthiness += rc_penalty;
101101

102+
// Update statistics using online updating formula
103+
// avg_n = avg_(n-1) + (x_n - avg_(n-1)) / n
104+
m_event_count++;
105+
m_average_truthiness += (truthiness - m_average_truthiness) / m_event_count;
106+
102107
// Report final truthiness
103-
info("Event truthiness: {:.6f} (from {} associations, {} unassociated MC, {} unassociated RC)",
104-
truthiness, associations->size(), unassociated_mc_count, unassociated_rc_count);
108+
debug("Event truthiness: {:.6f} (from {} associations, {} unassociated MC, {} unassociated RC)",
109+
truthiness, associations->size(), unassociated_mc_count, unassociated_rc_count);
105110
}
106111

107112
} // namespace eicrecon

src/algorithms/reco/Truthiness.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ using TruthinessAlgorithm = algorithms::Algorithm<
2222

2323
class Truthiness : public TruthinessAlgorithm, public WithPodConfig<TruthinessConfig> {
2424

25+
private:
26+
mutable double m_average_truthiness{0.0};
27+
mutable uint64_t m_event_count{0};
28+
2529
public:
2630
Truthiness(std::string_view name)
2731
: TruthinessAlgorithm{
@@ -33,6 +37,10 @@ class Truthiness : public TruthinessAlgorithm, public WithPodConfig<TruthinessCo
3337

3438
void init() final {};
3539
void process(const Input&, const Output&) const final;
40+
41+
// Accessors for statistics
42+
double getAverageTruthiness() const { return m_average_truthiness; }
43+
uint64_t getEventCount() const { return m_event_count; }
3644
};
3745

3846
} // namespace eicrecon
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// SPDX-License-Identifier: LGPL-3.0-or-later
2+
// Copyright (C) 2025 Wouter Deconinck
3+
4+
#include "Truthiness_processor.h"
5+
6+
#include <JANA/JApplication.h>
7+
#include <edm4eic/MCRecoParticleAssociationCollection.h>
8+
#include <edm4eic/ReconstructedParticleCollection.h>
9+
#include <edm4hep/MCParticleCollection.h>
10+
#include <string>
11+
12+
#include "services/log/Log_service.h"
13+
14+
namespace eicrecon {
15+
16+
void Truthiness_processor::Init() {
17+
std::string plugin_name = "Truthiness";
18+
auto* app = GetApplication();
19+
20+
// Get logger
21+
m_log = app->GetService<Log_service>()->logger(plugin_name);
22+
23+
// Initialize algorithm
24+
m_algo = std::make_unique<Truthiness>(plugin_name);
25+
// Set algorithm log level to match processor log level
26+
m_algo->level(static_cast<algorithms::LogLevel>(m_log->level()));
27+
m_algo->init();
28+
29+
// Get input collection names from parameters
30+
app->SetDefaultParameter(plugin_name + ":inputMCParticles", m_inputMCParticles,
31+
"Name of input MC particles collection");
32+
app->SetDefaultParameter(plugin_name + ":inputReconstructedParticles",
33+
m_inputReconstructedParticles,
34+
"Name of input reconstructed particles collection");
35+
app->SetDefaultParameter(plugin_name + ":inputAssociations", m_inputAssociations,
36+
"Name of input MC-reco associations collection");
37+
38+
m_log->info("Initialized with collections: MC='{}', Reco='{}', Assoc='{}'", m_inputMCParticles,
39+
m_inputReconstructedParticles, m_inputAssociations);
40+
}
41+
42+
void Truthiness_processor::Process(const std::shared_ptr<const JEvent>& event) {
43+
// Get input collections
44+
const auto* mc_particles = event->GetCollection<edm4hep::MCParticle>(m_inputMCParticles);
45+
const auto* rc_particles =
46+
event->GetCollection<edm4eic::ReconstructedParticle>(m_inputReconstructedParticles);
47+
const auto* associations =
48+
event->GetCollection<edm4eic::MCRecoParticleAssociation>(m_inputAssociations);
49+
50+
if (!mc_particles || !rc_particles || !associations) {
51+
m_log->debug("Event {}: Missing required collections", event->GetEventNumber());
52+
return;
53+
}
54+
55+
m_log->debug("Event {}: Processing {} MC particles, {} reco particles, {} associations",
56+
event->GetEventNumber(), mc_particles->size(), rc_particles->size(),
57+
associations->size());
58+
59+
// Call the algorithm
60+
Truthiness::Input input{mc_particles, rc_particles, associations};
61+
Truthiness::Output output{};
62+
m_algo->process(input, output);
63+
}
64+
65+
void Truthiness_processor::Finish() {
66+
if (m_algo) {
67+
const auto event_count = m_algo->getEventCount();
68+
if (event_count > 0) {
69+
const auto average_truthiness = m_algo->getAverageTruthiness();
70+
m_log->info("Processed {} events, average truthiness: {:.6f}", event_count,
71+
average_truthiness);
72+
} else {
73+
m_log->info("No events processed");
74+
}
75+
}
76+
}
77+
78+
} // namespace eicrecon
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// SPDX-License-Identifier: LGPL-3.0-or-later
2+
// Copyright (C) 2025 Wouter Deconinck
3+
4+
#pragma once
5+
6+
#include <JANA/JEventProcessor.h>
7+
#include <edm4eic/MCRecoParticleAssociationCollection.h>
8+
#include <edm4eic/ReconstructedParticleCollection.h>
9+
#include <edm4hep/MCParticleCollection.h>
10+
#include <memory>
11+
#include <string>
12+
#include <spdlog/logger.h>
13+
14+
#include "algorithms/reco/Truthiness.h"
15+
16+
namespace eicrecon {
17+
18+
class Truthiness_processor : public JEventProcessor {
19+
private:
20+
std::unique_ptr<Truthiness> m_algo;
21+
std::shared_ptr<spdlog::logger> m_log;
22+
std::string m_inputMCParticles{"MCParticles"};
23+
std::string m_inputReconstructedParticles{"ReconstructedParticles"};
24+
std::string m_inputAssociations{"ReconstructedParticleAssociations"};
25+
26+
public:
27+
Truthiness_processor() { SetTypeName(NAME_OF_THIS); }
28+
29+
void Init() override;
30+
void Process(const std::shared_ptr<const JEvent>& event) override;
31+
void Finish() override;
32+
};
33+
34+
} // namespace eicrecon

src/global/reco/reco.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
#include "factories/reco/ScatteredElectronsTruth_factory.h"
4343
#include "factories/reco/TrackClusterMatch_factory.h"
4444
#include "factories/reco/TransformBreitFrame_factory.h"
45-
#include "factories/reco/Truthiness_factory.h"
4645
#include "factories/reco/UndoAfterBurnerMCParticles_factory.h"
46+
#include "global/reco/Truthiness_processor.h"
4747

4848
extern "C" {
4949
void InitPlugin(JApplication* app) {
@@ -270,8 +270,6 @@ void InitPlugin(JApplication* app) {
270270
"PrimaryVertices", {"CentralTrackVertices"}, {"PrimaryVertices"}, {}, app));
271271

272272
// Truthiness metric for event quality assessment
273-
app->Add(new JOmniFactoryGeneratorT<Truthiness_factory>(
274-
"Truthiness", {"MCParticles", "ReconstructedParticles", "ReconstructedParticleAssociations"},
275-
{}, app));
273+
app->Add(new Truthiness_processor());
276274
}
277275
} // extern "C"

0 commit comments

Comments
 (0)