diff --git a/examples/options/include/traccc/options/truth_finding.hpp b/examples/options/include/traccc/options/truth_finding.hpp index c7e9e53ac9..6d6f258468 100644 --- a/examples/options/include/traccc/options/truth_finding.hpp +++ b/examples/options/include/traccc/options/truth_finding.hpp @@ -7,17 +7,30 @@ #pragma once +#include + #include "traccc/definitions/common.hpp" +#include "traccc/options/details/config_provider.hpp" #include "traccc/options/details/interface.hpp" +#include "traccc/utils/truth_matching_config.hpp" namespace traccc::opts { -class truth_finding : public interface { +class truth_finding : public interface, + public config_provider { public: - float m_min_pt = 0.5f * unit::GeV; + float m_pT_min = 0.5f * unit::GeV; + float m_z_min = -500.f * unit::mm; + float m_z_max = 500.f * unit::mm; + float m_r_max = 200.f * unit::mm; + float m_matching_ratio = 0.5f; + unsigned int m_min_track_candidates = 3; + bool m_double_matching = true; truth_finding(); + operator truth_matching_config() const override; + void read(const boost::program_options::variables_map &) override; std::unique_ptr as_printable() const override; diff --git a/examples/options/src/truth_finding.cpp b/examples/options/src/truth_finding.cpp index 488d9a62e3..d4922024fa 100644 --- a/examples/options/src/truth_finding.cpp +++ b/examples/options/src/truth_finding.cpp @@ -17,19 +17,68 @@ namespace traccc::opts { truth_finding::truth_finding() : interface("Truth Track Finding Options") { m_desc.add_options()( "truth-finding-min-pt", - boost::program_options::value(&m_min_pt)->default_value(m_min_pt), - "Candidate particule pT cut [GeV]"); + boost::program_options::value(&m_pT_min)->default_value(m_pT_min), + "Candidate particle pT cut [GeV]"); + m_desc.add_options()( + "truth-finding-min-z", + boost::program_options::value(&m_z_min)->default_value(m_z_min), + "Candidate particle min z cut [mm]"); + m_desc.add_options()( + "truth-finding-max-z", + boost::program_options::value(&m_z_max)->default_value(m_z_max), + "Candidate particle max z cut [mm]"); + m_desc.add_options()( + "truth-finding-max-r", + boost::program_options::value(&m_r_max)->default_value(m_r_max), + "Candidate particle max r cut [mm]"); + m_desc.add_options()("truth-finding-matching-ratio", + boost::program_options::value(&m_matching_ratio) + ->default_value(m_matching_ratio), + "Minimum track state matching ratio"); + m_desc.add_options()("truth-finding-min-track-candidates", + boost::program_options::value(&m_min_track_candidates) + ->default_value(m_min_track_candidates), + "Minimum track candidates on track"); + m_desc.add_options()("truth-finding-double-matching", + boost::program_options::bool_switch(&m_double_matching) + ->default_value(m_double_matching), + "Enable double truth-reco matching"); } void truth_finding::read(const boost::program_options::variables_map &) { - m_min_pt *= unit::GeV; + m_pT_min *= unit::GeV; + m_z_min *= unit::mm; + m_z_max *= unit::mm; + m_r_max *= unit::mm; +} + +truth_finding::operator truth_matching_config() const { + return truth_matching_config{.pT_min = m_pT_min, + .z_min = m_z_min, + .z_max = m_z_max, + .r_max = m_r_max, + .matching_ratio = m_matching_ratio, + .min_track_candidates = m_min_track_candidates, + .double_matching = m_double_matching}; } std::unique_ptr truth_finding::as_printable() const { auto cat = std::make_unique(m_description); cat->add_child(std::make_unique( - "Minimum pT", std::format("{} GeV", m_min_pt / unit::GeV))); + "Minimum pT", std::format("{} GeV", m_pT_min / unit::GeV))); + cat->add_child(std::make_unique( + "Minimum z", std::format("{} mm", m_z_min / unit::mm))); + cat->add_child(std::make_unique( + "Maximum z", std::format("{} mm", m_z_max / unit::mm))); + cat->add_child(std::make_unique( + "Maximum r", std::format("{} mm", m_r_max / unit::mm))); + cat->add_child(std::make_unique( + "Matching ratio", std::format("{}", m_matching_ratio))); + cat->add_child(std::make_unique( + "Minimum track candidates", std::format("{}", m_min_track_candidates))); + cat->add_child(std::make_unique( + "Double matching", std::format("{}", m_double_matching))); return cat; } diff --git a/examples/run/alpaka/seeding_example_alpaka.cpp b/examples/run/alpaka/seeding_example_alpaka.cpp index 45d9240303..c1b9df8403 100644 --- a/examples/run/alpaka/seeding_example_alpaka.cpp +++ b/examples/run/alpaka/seeding_example_alpaka.cpp @@ -38,6 +38,7 @@ #include "traccc/options/track_fitting.hpp" #include "traccc/options/track_propagation.hpp" #include "traccc/options/track_seeding.hpp" +#include "traccc/options/truth_finding.hpp" #include "traccc/performance/collection_comparator.hpp" #include "traccc/performance/soa_comparator.hpp" #include "traccc/performance/timer.hpp" @@ -63,6 +64,7 @@ int seq_run(const traccc::opts::track_seeding& seeding_opts, const traccc::opts::magnetic_field& bfield_opts, const traccc::opts::performance& performance_opts, const traccc::opts::accelerator& accelerator_opts, + const traccc::opts::truth_finding& truth_finding_opts, [[maybe_unused]] std::unique_ptr ilogger) { TRACCC_LOCAL_LOGGER(std::move(ilogger)); @@ -80,7 +82,8 @@ int seq_run(const traccc::opts::track_seeding& seeding_opts, traccc::seeding_performance_writer::config{}, logger().clone("SeedingPerformanceWriter")); traccc::finding_performance_writer find_performance_writer( - traccc::finding_performance_writer::config{}, + traccc::finding_performance_writer::config{.truth_config = + truth_finding_opts}, logger().clone("FindingPerformanceWriter")); traccc::fitting_performance_writer fit_performance_writer( traccc::fitting_performance_writer::config{}, @@ -452,10 +455,12 @@ int main(int argc, char* argv[]) { traccc::opts::track_fitting fitting_opts; traccc::opts::performance performance_opts; traccc::opts::accelerator accelerator_opts; + traccc::opts::truth_finding truth_finding_opts; traccc::opts::program_options program_opts{ "Full Tracking Chain Using Alpaka (without clusterization)", {detector_opts, bfield_opts, input_opts, seeding_opts, finding_opts, - propagation_opts, fitting_opts, performance_opts, accelerator_opts}, + propagation_opts, fitting_opts, performance_opts, accelerator_opts, + truth_finding_opts}, argc, argv, logger->cloneWithSuffix("Options")}; @@ -463,5 +468,5 @@ int main(int argc, char* argv[]) { // Run the application. return seq_run(seeding_opts, finding_opts, propagation_opts, fitting_opts, input_opts, detector_opts, bfield_opts, performance_opts, - accelerator_opts, logger->clone()); + accelerator_opts, truth_finding_opts, logger->clone()); } diff --git a/examples/run/cpu/seeding_example.cpp b/examples/run/cpu/seeding_example.cpp index 37e451098c..3b8eab0602 100644 --- a/examples/run/cpu/seeding_example.cpp +++ b/examples/run/cpu/seeding_example.cpp @@ -43,6 +43,7 @@ #include "traccc/options/track_propagation.hpp" #include "traccc/options/track_resolution.hpp" #include "traccc/options/track_seeding.hpp" +#include "traccc/options/truth_finding.hpp" // VecMem include(s). #include @@ -64,6 +65,7 @@ int seq_run(const traccc::opts::track_seeding& seeding_opts, const traccc::opts::detector& detector_opts, const traccc::opts::magnetic_field& bfield_opts, const traccc::opts::performance& performance_opts, + const traccc::opts::truth_finding& truth_finding_opts, std::unique_ptr ilogger) { TRACCC_LOCAL_LOGGER(std::move(ilogger)); @@ -78,7 +80,8 @@ int seq_run(const traccc::opts::track_seeding& seeding_opts, traccc::seeding_performance_writer::config{}, logger().clone("SeedingPerformanceWriter")); traccc::finding_performance_writer find_performance_writer( - traccc::finding_performance_writer::config{}, + traccc::finding_performance_writer::config{.truth_config = + truth_finding_opts}, logger().clone("FindingPerformanceWriter")); traccc::finding_performance_writer::config ar_writer_cfg; ar_writer_cfg.file_path = "performance_track_ambiguity_resolution.root"; @@ -282,10 +285,12 @@ int main(int argc, char* argv[]) { traccc::opts::track_resolution resolution_opts; traccc::opts::track_fitting fitting_opts; traccc::opts::performance performance_opts; + traccc::opts::truth_finding truth_finding_opts; traccc::opts::program_options program_opts{ "Full Tracking Chain on the Host (without clusterization)", {detector_opts, bfield_opts, input_opts, seeding_opts, finding_opts, - propagation_opts, resolution_opts, fitting_opts, performance_opts}, + propagation_opts, resolution_opts, fitting_opts, performance_opts, + truth_finding_opts}, argc, argv, logger->cloneWithSuffix("Options")}; @@ -293,5 +298,6 @@ int main(int argc, char* argv[]) { // Run the application. return seq_run(seeding_opts, finding_opts, propagation_opts, resolution_opts, fitting_opts, input_opts, detector_opts, - bfield_opts, performance_opts, logger->clone()); + bfield_opts, performance_opts, truth_finding_opts, + logger->clone()); } diff --git a/examples/run/cpu/seq_example.cpp b/examples/run/cpu/seq_example.cpp index 95fbd1f4c2..c100900596 100644 --- a/examples/run/cpu/seq_example.cpp +++ b/examples/run/cpu/seq_example.cpp @@ -45,6 +45,7 @@ #include "traccc/options/track_propagation.hpp" #include "traccc/options/track_resolution.hpp" #include "traccc/options/track_seeding.hpp" +#include "traccc/options/truth_finding.hpp" // examples #include "../common/make_magnetic_field.hpp" @@ -72,6 +73,7 @@ int seq_run(const traccc::opts::input_data& input_opts, const traccc::opts::track_resolution& resolution_opts, const traccc::opts::track_fitting& fitting_opts, const traccc::opts::performance& performance_opts, + const traccc::opts::truth_finding& truth_finding_opts, std::unique_ptr ilogger) { TRACCC_LOCAL_LOGGER(std::move(ilogger)); @@ -156,7 +158,8 @@ int seq_run(const traccc::opts::input_data& input_opts, traccc::seeding_performance_writer::config{}, logger().clone("SeedingPerformanceWriter")); traccc::finding_performance_writer find_performance_writer( - traccc::finding_performance_writer::config{}, + traccc::finding_performance_writer::config{.truth_config = + truth_finding_opts}, logger().clone("FindingPerformanceWriter")); traccc::finding_performance_writer::config ar_writer_cfg; ar_writer_cfg.file_path = "performance_track_ambiguity_resolution.root"; @@ -386,11 +389,12 @@ int main(int argc, char* argv[]) { traccc::opts::track_resolution resolution_opts; traccc::opts::track_fitting fitting_opts; traccc::opts::performance performance_opts; + traccc::opts::truth_finding truth_finding_opts; traccc::opts::program_options program_opts{ "Full Tracking Chain on the Host", {detector_opts, bfield_opts, input_opts, output_opts, clusterization_opts, seeding_opts, finding_opts, resolution_opts, - fitting_opts, propagation_opts, performance_opts}, + fitting_opts, propagation_opts, performance_opts, truth_finding_opts}, argc, argv, logger->cloneWithSuffix("Options")}; @@ -399,5 +403,5 @@ int main(int argc, char* argv[]) { return seq_run(input_opts, output_opts, detector_opts, bfield_opts, clusterization_opts, seeding_opts, finding_opts, propagation_opts, resolution_opts, fitting_opts, - performance_opts, logger->clone()); + performance_opts, truth_finding_opts, logger->clone()); } diff --git a/examples/run/cpu/truth_finding_example.cpp b/examples/run/cpu/truth_finding_example.cpp index e9a8d1aee5..7983347075 100644 --- a/examples/run/cpu/truth_finding_example.cpp +++ b/examples/run/cpu/truth_finding_example.cpp @@ -61,7 +61,8 @@ int seq_run(const traccc::opts::track_finding& finding_opts, // Performance writer traccc::finding_performance_writer find_performance_writer( - traccc::finding_performance_writer::config{}, + traccc::finding_performance_writer::config{.truth_config = + truth_finding_opts}, logger().clone("FindingPerformanceWriter")); traccc::fitting_performance_writer fit_performance_writer( traccc::fitting_performance_writer::config{}, @@ -128,7 +129,7 @@ int seq_run(const traccc::opts::track_finding& finding_opts, traccc::edm::track_candidate_container::host truth_track_candidates{host_mr}; evt_data.generate_truth_candidates(truth_track_candidates, sg, host_mr, - truth_finding_opts.m_min_pt); + truth_finding_opts.m_pT_min); // Prepare truth seeds traccc::bound_track_parameters_collection_types::host seeds(&host_mr); diff --git a/examples/run/cuda/seeding_example_cuda.cpp b/examples/run/cuda/seeding_example_cuda.cpp index e17f1cb397..dc24125594 100644 --- a/examples/run/cuda/seeding_example_cuda.cpp +++ b/examples/run/cuda/seeding_example_cuda.cpp @@ -37,6 +37,7 @@ #include "traccc/options/track_fitting.hpp" #include "traccc/options/track_propagation.hpp" #include "traccc/options/track_seeding.hpp" +#include "traccc/options/truth_finding.hpp" #include "traccc/performance/collection_comparator.hpp" #include "traccc/performance/soa_comparator.hpp" #include "traccc/performance/timer.hpp" @@ -69,6 +70,7 @@ int seq_run(const traccc::opts::track_seeding& seeding_opts, const traccc::opts::magnetic_field& bfield_opts, const traccc::opts::performance& performance_opts, const traccc::opts::accelerator& accelerator_opts, + const traccc::opts::truth_finding& truth_finding_opts, std::unique_ptr ilogger) { TRACCC_LOCAL_LOGGER(std::move(ilogger)); @@ -84,7 +86,8 @@ int seq_run(const traccc::opts::track_seeding& seeding_opts, traccc::seeding_performance_writer::config{}, logger().clone("SeedingPerformanceWriter")); traccc::finding_performance_writer find_performance_writer( - traccc::finding_performance_writer::config{}, + traccc::finding_performance_writer::config{.truth_config = + truth_finding_opts}, logger().clone("FindingPerformanceWriter")); traccc::fitting_performance_writer fit_performance_writer( traccc::fitting_performance_writer::config{}, @@ -474,10 +477,12 @@ int main(int argc, char* argv[]) { traccc::opts::track_fitting fitting_opts; traccc::opts::performance performance_opts; traccc::opts::accelerator accelerator_opts; + traccc::opts::truth_finding truth_finding_opts; traccc::opts::program_options program_opts{ "Full Tracking Chain Using CUDA (without clusterization)", {detector_opts, bfield_opts, input_opts, seeding_opts, finding_opts, - propagation_opts, fitting_opts, performance_opts, accelerator_opts}, + propagation_opts, fitting_opts, performance_opts, accelerator_opts, + truth_finding_opts}, argc, argv, logger->cloneWithSuffix("Options")}; @@ -485,5 +490,5 @@ int main(int argc, char* argv[]) { // Run the application. return seq_run(seeding_opts, finding_opts, propagation_opts, fitting_opts, input_opts, detector_opts, bfield_opts, performance_opts, - accelerator_opts, logger->clone()); + accelerator_opts, truth_finding_opts, logger->clone()); } diff --git a/examples/run/cuda/truth_finding_example_cuda.cpp b/examples/run/cuda/truth_finding_example_cuda.cpp index cc920b7a1e..ea1633791b 100644 --- a/examples/run/cuda/truth_finding_example_cuda.cpp +++ b/examples/run/cuda/truth_finding_example_cuda.cpp @@ -76,7 +76,8 @@ int seq_run(const traccc::opts::track_finding& finding_opts, // Performance writer traccc::finding_performance_writer find_performance_writer( - traccc::finding_performance_writer::config{}, + traccc::finding_performance_writer::config{.truth_config = + truth_finding_opts}, logger().clone("FindingPerformanceWriter")); traccc::fitting_performance_writer fit_performance_writer( traccc::fitting_performance_writer::config{}, @@ -169,7 +170,7 @@ int seq_run(const traccc::opts::track_finding& finding_opts, traccc::edm::track_candidate_container::host truth_track_candidates{host_mr}; evt_data.generate_truth_candidates(truth_track_candidates, sg, host_mr, - truth_finding_opts.m_min_pt); + truth_finding_opts.m_pT_min); // Prepare truth seeds traccc::bound_track_parameters_collection_types::host seeds(mr.host); diff --git a/performance/include/traccc/efficiency/finding_performance_writer.hpp b/performance/include/traccc/efficiency/finding_performance_writer.hpp index 072ceb7a3a..b240619a4c 100644 --- a/performance/include/traccc/efficiency/finding_performance_writer.hpp +++ b/performance/include/traccc/efficiency/finding_performance_writer.hpp @@ -11,6 +11,7 @@ #include "traccc/resolution/stat_plot_tool_config.hpp" #include "traccc/utils/helpers.hpp" #include "traccc/utils/messaging.hpp" +#include "traccc/utils/truth_matching_config.hpp" // Project include(s). #include "traccc/edm/track_candidate_collection.hpp" @@ -52,15 +53,9 @@ class finding_performance_writer : public messaging { {"Pt", plot_helpers::binning("p_{T} [GeV/c]", 40, 0.f, 100.f)}, {"Num", plot_helpers::binning("N", 30, -0.5f, 29.5f)}}; - /// Cut values - scalar pT_cut = 0.5f * traccc::unit::GeV; - scalar z_min = -500.f * traccc::unit::mm; - scalar z_max = 500.f * traccc::unit::mm; - scalar r_max = 200.f * traccc::unit::mm; - scalar matching_ratio = 0.5f; - bool double_matching = true; + truth_matching_config truth_config; - stat_plot_tool_config stat_config; + stat_plot_tool_config stat_config{}; }; /// Construct from configuration and log level. diff --git a/performance/include/traccc/utils/truth_matching_config.hpp b/performance/include/traccc/utils/truth_matching_config.hpp new file mode 100644 index 0000000000..ebb87b8f39 --- /dev/null +++ b/performance/include/traccc/utils/truth_matching_config.hpp @@ -0,0 +1,29 @@ +/** TRACCC library, part of the ACTS project (R&D line) + * + * (c) 2025 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +#include "traccc/definitions/common.hpp" + +namespace traccc { + +struct truth_matching_config { + float pT_min = 0.5f * traccc::unit::GeV; + + float z_min = -500.f * traccc::unit::mm; + float z_max = 500.f * traccc::unit::mm; + + float r_max = 200.f * traccc::unit::mm; + + float matching_ratio = 0.5f; + + unsigned int min_track_candidates = 3; + + bool double_matching = true; +}; + +} // namespace traccc diff --git a/performance/src/efficiency/finding_performance_writer.cpp b/performance/src/efficiency/finding_performance_writer.cpp index 7f1765f9eb..9790b1c731 100644 --- a/performance/src/efficiency/finding_performance_writer.cpp +++ b/performance/src/efficiency/finding_performance_writer.cpp @@ -167,6 +167,8 @@ void finding_performance_writer::write_common( // Iterate over the tracks. const std::size_t n_tracks = tracks.size(); + std::size_t total_fake_tracks = 0; + for (std::size_t i = 0; i < n_tracks; i++) { const std::vector& found_measurements = tracks[i]; @@ -206,14 +208,15 @@ void finding_performance_writer::write_common( const bool reco_matched = static_cast(n_major_hits) / static_cast(found_measurements.size()) > - m_cfg.matching_ratio; + m_cfg.truth_config.matching_ratio; const bool truth_matched = static_cast(n_major_hits) / static_cast(truth_measurements.size()) > - m_cfg.matching_ratio; + m_cfg.truth_config.matching_ratio; - if ((!m_cfg.double_matching && reco_matched) || - (m_cfg.double_matching && reco_matched && truth_matched)) { + if ((!m_cfg.truth_config.double_matching && reco_matched) || + (m_cfg.truth_config.double_matching && reco_matched && + truth_matched)) { const auto pid = major_ptc.particle_id; match_counter[pid]++; } else { @@ -221,19 +224,38 @@ void finding_performance_writer::write_common( const auto pid = phc.ptc.particle_id; fake_counter[pid]++; } + total_fake_tracks++; } } + std::size_t total_truth_particles = 0; + std::size_t total_matched_truth_particles = 0; + std::size_t total_duplicate_tracks = 0; + // For each truth particle... for (auto const& [pid, ptc] : evt_data.m_particle_map) { + std::size_t num_measurements = 0; + + // Find the number of measurements belonging to this track + if (auto it = evt_data.m_ptc_to_meas_map.find(ptc); + it != evt_data.m_ptc_to_meas_map.end()) { + num_measurements = it->second.size(); + } else { + continue; + } - // Count only charged particles which satisfy pT_cut - if (ptc.charge == 0 || vector::perp(ptc.momentum) < m_cfg.pT_cut || - ptc.vertex[2] < m_cfg.z_min || ptc.vertex[2] > m_cfg.z_max || - vector::perp(ptc.vertex) > m_cfg.r_max) { + // Count only charged particles which satisfy pT_cut and vertex cut + if (ptc.charge == 0 || + vector::perp(ptc.momentum) < m_cfg.truth_config.pT_min || + ptc.vertex[2] < m_cfg.truth_config.z_min || + ptc.vertex[2] > m_cfg.truth_config.z_max || + vector::perp(ptc.vertex) > m_cfg.truth_config.r_max || + num_measurements < m_cfg.truth_config.min_track_candidates) { continue; } + total_truth_particles++; + // Finds how many tracks were made solely by hits from the current truth // particle bool is_matched = false; @@ -241,7 +263,9 @@ void finding_performance_writer::write_common( auto it = match_counter.find(pid); if (it != match_counter.end()) { is_matched = true; + total_matched_truth_particles++; n_matched_seeds_for_particle = it->second; + total_duplicate_tracks += n_matched_seeds_for_particle - 1; } // Finds how many (fake) tracks were made with at least one hit from the @@ -259,6 +283,25 @@ void finding_performance_writer::write_common( m_data->m_fake_tracks_plot_tool.fill(m_data->m_fake_tracks_plot_cache, ptc, fake_count); } + + TRACCC_INFO("Total number of truth particles was " + << total_truth_particles); + TRACCC_INFO("Total number of found tracks was " << n_tracks); + TRACCC_INFO("Total number of matched particles was " + << total_matched_truth_particles); + TRACCC_INFO("Total number of duplicated tracks was " + << total_duplicate_tracks); + TRACCC_INFO("Total number of fake tracks was " << total_fake_tracks); + TRACCC_INFO("Total efficiency was " + << (100. * static_cast(total_matched_truth_particles) / + static_cast(total_truth_particles)) + << "%"); + TRACCC_INFO("Total duplicate rate was " + << (static_cast(total_duplicate_tracks) / + static_cast(total_matched_truth_particles))); + TRACCC_INFO("Total fake rate was " + << (static_cast(total_fake_tracks) / + static_cast(total_truth_particles))); } /// For track finding