From 3739b6192062b5fcc13a22e7a224ed2a3f2d9329 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinkin Date: Tue, 7 May 2024 19:55:38 -0400 Subject: [PATCH 1/5] Fix compilation issues (#1427) Fixes a compilation error: ``` fatal error: catch2/catch_test_macros.hpp: No such file or directory 5 | #include // for AssertionHandler, operator""_catch_sr, StringRef, REQUIRE, operator<, operator==, operator>, TEST_CASE | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated. ``` Removes another test that serves no purpose. --- src/tests/CMakeLists.txt | 1 - src/tests/algorithms_test/CMakeLists.txt | 4 +- .../reco_FarForwardNeutronReconstruction.cc | 0 src/tests/reco_test/CMakeLists.txt | 25 ---- .../GlobalReconstructionTest_processor.cc | 130 ------------------ .../GlobalReconstructionTest_processor.h | 52 ------- src/tests/reco_test/README.md | 61 -------- src/tests/reco_test/reco_test.cc | 19 --- 8 files changed, 3 insertions(+), 289 deletions(-) rename src/tests/{reco_test => algorithms_test}/reco_FarForwardNeutronReconstruction.cc (100%) delete mode 100644 src/tests/reco_test/CMakeLists.txt delete mode 100644 src/tests/reco_test/GlobalReconstructionTest_processor.cc delete mode 100644 src/tests/reco_test/GlobalReconstructionTest_processor.h delete mode 100644 src/tests/reco_test/README.md delete mode 100644 src/tests/reco_test/reco_test.cc diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 73148f8662..da4765543c 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -8,7 +8,6 @@ else() STATUS "Catch2 is not found. Skipping algorithms_test, omnifactory_test...") endif() -add_subdirectory(reco_test) add_subdirectory(tracking_test) add_subdirectory(track_propagation_test) add_subdirectory(geometry_navigation_test) diff --git a/src/tests/algorithms_test/CMakeLists.txt b/src/tests/algorithms_test/CMakeLists.txt index a545afffa9..0ad3e1bb5d 100644 --- a/src/tests/algorithms_test/CMakeLists.txt +++ b/src/tests/algorithms_test/CMakeLists.txt @@ -10,7 +10,8 @@ add_executable( calorimetry_CalorimeterHitDigi.cc calorimetry_HEXPLIT.cc pid_MergeTracks.cc - pid_MergeParticleID.cc) + pid_MergeParticleID.cc + reco_FarForwardNeutronReconstruction.cc) # Explicit linking to podio::podio is needed due to # https://github.com/JeffersonLab/JANA2/issues/151 @@ -20,6 +21,7 @@ target_link_libraries( algorithms_calorimetry_library algorithms_fardetectors_library algorithms_pid_library + algorithms_reco_library evaluator_library podio::podio podio::podioRootIO) diff --git a/src/tests/reco_test/reco_FarForwardNeutronReconstruction.cc b/src/tests/algorithms_test/reco_FarForwardNeutronReconstruction.cc similarity index 100% rename from src/tests/reco_test/reco_FarForwardNeutronReconstruction.cc rename to src/tests/algorithms_test/reco_FarForwardNeutronReconstruction.cc diff --git a/src/tests/reco_test/CMakeLists.txt b/src/tests/reco_test/CMakeLists.txt deleted file mode 100644 index e478607bc7..0000000000 --- a/src/tests/reco_test/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Automatically set plugin name the same as the directory name Don't forget -# string(REPLACE " " "_" PLUGIN_NAME ${PLUGIN_NAME}) if this dir has spaces in -# its name -get_filename_component(PLUGIN_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) - -# Function creates ${PLUGIN_NAME}_plugin and ${PLUGIN_NAME}_library targets -# Setting default includes, libraries and installation paths -plugin_add(${PLUGIN_NAME}) - -# Find dependencies -plugin_add_dd4hep(${PLUGIN_NAME}) -plugin_add_acts(${PLUGIN_NAME}) -plugin_add_cern_root(${PLUGIN_NAME}) -plugin_add_event_model(${PLUGIN_NAME}) - -# The macro grabs sources as *.cc *.cpp *.c and headers as *.h *.hh *.hpp Then -# correctly sets sources for ${_name}_plugin and ${_name}_library targets Adds -# headers to the correct installation directory -plugin_glob_all(${PLUGIN_NAME}) - -# Add include directories (works same as target_include_directories) -# plugin_include_directories(${PLUGIN_NAME} SYSTEM PUBLIC ... ) - -# Add libraries (same as target_include_directories but for both plugin and -# library) plugin_link_libraries(${PLUGIN_NAME} ...) diff --git a/src/tests/reco_test/GlobalReconstructionTest_processor.cc b/src/tests/reco_test/GlobalReconstructionTest_processor.cc deleted file mode 100644 index 7b50bc3563..0000000000 --- a/src/tests/reco_test/GlobalReconstructionTest_processor.cc +++ /dev/null @@ -1,130 +0,0 @@ - -#include "GlobalReconstructionTest_processor.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "extensions/spdlog/SpdlogExtensions.h" -#include "services/log/Log_service.h" -#include "services/rootfile/RootFile_service.h" - -using namespace fmt; - -//------------------ -// OccupancyAnalysis (Constructor) -//------------------ -GlobalReconstructionTest_processor::GlobalReconstructionTest_processor(JApplication *app) : - JEventProcessor(app) -{ -} - -//------------------ -// Init -//------------------ -void GlobalReconstructionTest_processor::Init() -{ - std::string plugin_name=("reco_test"); - - // Get JANA application - auto *app = GetApplication(); - - // Ask service locator a file to write histograms to - auto root_file_service = app->GetService(); - - // Get TDirectory for histograms root file - auto globalRootLock = app->GetService(); - globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); - globalRootLock->release_lock(); - - // Create a directory for this plugin. And subdirectories for series of histograms - m_dir_main = file->mkdir(plugin_name.c_str()); - - // Get log level from user parameter or default - std::string log_level_str = "info"; - m_log = app->GetService()->logger(plugin_name); - app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, "LogLevel: trace, debug, info, warn, err, critical, off"); - m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); - for(auto pair: app->GetJParameterManager()->GetAllParameters()) { - m_log->info("{:<20} | {}", pair.first, pair.second->GetDescription()); - } -} - - -//------------------ -// Process -//------------------ -void GlobalReconstructionTest_processor::Process(const std::shared_ptr& event) -{ - using namespace ROOT; - - m_log->debug("----------- GlobalReconstructionTest_processor {}-----------", event->GetEventNumber()); - - /** RECONSTRUCTED PARTICLES **/ - auto reco_particles = event->Get("ReconstructedParticles"); - printRecoParticles(reco_particles, std::string("ReconstructedParticles")); - - /** GENERATED PARTICLES **/ - auto gen_particles = event->Get("GeneratedParticles"); - printRecoParticles(gen_particles, std::string("GeneratedParticles")); - - /** MC PARTICLES **/ - auto mc_particles = event->Get("MCParticles"); - m_log->debug("MC particles N={}: ", mc_particles.size()); - m_log->debug(" {:<5} {:<6} {:<7} {:>8} {:>8} {:>8} {:>8}","[i]", "status", "[PDG]", "[px]", "[py]", "[pz]", "[P]"); - for(size_t i=0; i < mc_particles.size(); i++) { - - const auto *particle=mc_particles[i]; - - if(particle->getGeneratorStatus() != 1) continue; -// - double px = particle->getMomentum().x; - double py = particle->getMomentum().y; - double pz = particle->getMomentum().z; - ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle->getMass()); - ROOT::Math::Cartesian3D p(px, py, pz); - if(p.R()<1) continue; - - m_log->debug(" {:<5} {:<6} {:<7} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, particle->getGeneratorStatus(), particle->getPDG(), px, py, pz, p.R()); - } -} - - -//------------------ -// Finish -//------------------ -void GlobalReconstructionTest_processor::Finish() -{ - fmt::print("GlobalReconstructionTest_processor::Finish() called\n"); - -} - -void GlobalReconstructionTest_processor::printRecoParticles(std::vector reco_particles, const std::string &title) { - m_log->debug("{} N={}: ", title, reco_particles.size()); - m_log->debug(" {:<5} {:>8} {:>8} {:>8} {:>8} {:>8}","[i]", "[px]", "[py]", "[pz]", "[P]", "[P*3]"); - - - for(size_t i=0; i < reco_particles.size(); i++) { - const auto *particle = reco_particles[i]; - - double px = particle->getMomentum().x; - double py = particle->getMomentum().y; - double pz = particle->getMomentum().z; - // ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle.getMass()); - ROOT::Math::Cartesian3D p(px, py, pz); - m_log->debug(" {:<5} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, px, py, pz, p.R(), p.R()*3); - } -} diff --git a/src/tests/reco_test/GlobalReconstructionTest_processor.h b/src/tests/reco_test/GlobalReconstructionTest_processor.h deleted file mode 100644 index b979c5b5f5..0000000000 --- a/src/tests/reco_test/GlobalReconstructionTest_processor.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class GlobalReconstructionTest_processor:public JEventProcessor -{ -public: - explicit GlobalReconstructionTest_processor(JApplication *); - ~GlobalReconstructionTest_processor() override = default; - - //---------------------------- - // Init - // - // This is called once before the first call to the Process method - // below. You may, for example, want to open an output file here. - // Only one thread will call this. - void Init() override; - - //---------------------------- - // Process - // - // This is called for every event. Multiple threads may call this - // simultaneously. If you write something to an output file here - // then make sure to protect it with a mutex or similar mechanism. - // Minimize what is done while locked since that directly affects - // the multi-threaded performance. - void Process(const std::shared_ptr& event) override; - - //---------------------------- - // Finish - // - // This is called once after all events have been processed. You may, - // for example, want to close an output file here. - // Only one thread will call this. - void Finish() override; - -private: - - - std::shared_ptr m_log; - TDirectory *m_dir_main; - - void printRecoParticles(std::vector reco_particles, const std::string &title); -}; diff --git a/src/tests/reco_test/README.md b/src/tests/reco_test/README.md deleted file mode 100644 index 773990c3ba..0000000000 --- a/src/tests/reco_test/README.md +++ /dev/null @@ -1,61 +0,0 @@ -This is guinea pig plugin for active development phase - -```bash - -# uniform spread inside an angle: - -ddsim --compactFile=$DETECTOR_PATH/epic.xml -N=2000 --random.seed 1 --enableGun --gun.energy 2*GeV --gun.thetaMin 0*deg --gun.thetaMax 90*deg --gun.distribution uniform --outputFile tracking_test_gun.root -ddsim --compactFile=$DETECTOR_PATH/epic.xml -N=200 --random.seed 1 --enableGun --gun.particle="e-" --gun.momentumMin 1*MeV --gun.momentumMax 30*GeV --gun.distribution uniform --outputFile 2022-09-04_pgun_e-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_200ev.edm4hep.root -ddsim --compactFile=$DETECTOR_PATH/epic.xml -N=1000 --random.seed 1 --enableGun --gun.particle="e-" --gun.momentumMin 1*MeV --gun.momentumMax 30*GeV --gun.distribution uniform --outputFile 2022-09-04_pgun_e-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_1k.edm4hep.root -ddsim --compactFile=$DETECTOR_PATH/epic.xml -N=2000 --random.seed 1 --enableGun --gun.particle="e-" --gun.momentumMin 1*MeV --gun.momentumMax 30*GeV --gun.distribution uniform --outputFile 2022-08-15_pgun_e-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_2k.edm4hep.root -ddsim --compactFile=$DETECTOR_PATH/epic.xml -N=10000 --random.seed 1 --enableGun --gun.particle="e-" --gun.momentumMin 1*MeV --gun.momentumMax 30*GeV --gun.distribution uniform --outputFile 2022-08-15_pgun_e-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_10k.edm4hep.root - -# 5 x e- per event -ddsim --compactFile=$DETECTOR_PATH/epic.xml -N=1000 --random.seed 1 --enableGun --gun.particle="e-" --gun.multiplicity 3 --gun.momentumMin 1*MeV --gun.momentumMax 30*GeV --gun.distribution uniform --outputFile 2022-09-10_pgun_3xe-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_1k.edm4hep.root -podio-0.15_edm4hep-0.6_0-30GeV_alldir_1k.edm4hep.root - ---gun.momentumMax ---gun.momentumMin - -# Reconstruct Charge Current DIS -# Detectors live in /opt/detectors -# one can select particular configuration as -# source /opt/detector/athena-deathvalley-1.5T/setup.sh -# -# or one can set the latest detector -source /opt/detector/setup.sh - -# 100 events -ddsim --compactFile=$DETECTOR_PATH/epic.xml --runType=run -N=100 --outputFile=2022-09-26_ccdis10x100_100ev.edm4hep.root --inputFiles pythia8CCDIS_10x100_minQ2=100_beamEffects_xAngle=-0.025_hiDiv_1.hepmc - -# 200 events -ddsim --compactFile=$DETECTOR_PATH/epic.xml --runType=run -N=200 --outputFile=2022-09-26_ccdis10x100_200ev.edm4hep.root --inputFiles pythia8CCDIS_10x100_minQ2=100_beamEffects_xAngle=-0.025_hiDiv_1.hepmc - -eicrecon --Pplugins=acts,tracking,BTRK,ECTRK,BVTX,MPGD,tracking_occupancy --Pnthreads=1 --Pjana:debug_plugin_loading=1 --Pjana:nevents=1 --Pjana:debug_mode=1 --Pjana:timeout=0 --PTracking:CentralTrackerSourceLinker:LogLevel=info --PCKFTracking:Trajectories:LogLevel=trace --Pdd4hep:xml_files=/home/romanov/eic/soft/detector/main/compiled/epic/share/epic/epic_tracking_only.xml --Phistsfile=/home/romanov/work/data/eicrecon_test/tracking_test_gun.ana.root -/home/romanov/work/data/eicrecon_test/2022-09-10_pgun_3xe-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_1k.edm4hep.root - -``` - -```bash -eicrecon --Pplugins=acts,BTRK_test,BTRK --Pnthreads=1 --Pjana:nevents=10 --Pjana:debug_plugin_loading=1 --PSiliconTrackerDigi_BarrelTrackerRawHit:LogLevel=trace --PTrackerHitReconstruction:BarrelTrackerHit:LogLevel=trace --PTrackerSourceLinker:CentralTrackerSourceLinker:LogLevel=trace --Pdd4hep:print_level=5 --Phistsfile=/home/romanov/work/data/eicrecon_test/tracking_test_gun.ana.root -/home/romanov/work/data/eicrecon_test/2022-09-04_pgun_e-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_100ev.edm4hep.root -``` diff --git a/src/tests/reco_test/reco_test.cc b/src/tests/reco_test/reco_test.cc deleted file mode 100644 index 447f119a5a..0000000000 --- a/src/tests/reco_test/reco_test.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2022, David Lawrence -// Subject to the terms in the LICENSE file found in the top-level directory. -// -// - -#include - -#include "GlobalReconstructionTest_processor.h" -//#include "JFactory_EcalBarrelRawCalorimeterHit.h.bck" -//#include "JFactory_RawCalorimeterHit_EcalBarrelRawCalorimeterHits.h.bck" - -extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new GlobalReconstructionTest_processor(app)); - //app->Add(new JFactoryGeneratorT()); - //app->Add(new JFactoryGeneratorT()); - } -} From c1ef8090552e1483b07f0a809676251098b97521 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Tue, 7 May 2024 23:00:28 -0500 Subject: [PATCH 2/5] fix: rm include unused SpdlogMixin (#1429) ### Briefly, what does this PR introduce? This PR removes the unused includes of SpdlogMixin in various factories. ### What kind of change does this PR introduce? - [x] Bug fix (issue #__) - [ ] New feature (issue #__) - [ ] Documentation update - [ ] Other: __ ### Please check if this PR fulfills the following: - [ ] Tests for the changes have been added - [ ] Documentation has been added / updated - [ ] Changes have been communicated to collaborators ### Does this PR introduce breaking changes? What changes might users need to make to their code? No. ### Does this PR change default behavior? No. --- .../reconstruction/femc_studies/femc_studiesProcessor.cc | 1 - .../reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc | 1 - src/factories/calorimetry/CalorimeterHitDigi_factory.h | 2 -- src/factories/calorimetry/CalorimeterHitsMerger_factory.h | 2 -- .../fardetectors/FarDetectorLinearProjection_factory.h | 1 - src/global/pid/MergeTrack_factory.h | 4 ---- src/global/pid/RichTrack_factory.h | 3 --- src/global/tracking/CKFTracking_factory.h | 1 - src/global/tracking/TrackParamTruthInit_factory.h | 1 - src/global/tracking/TrackPropagation_factory.h | 1 - src/global/tracking/TrackerMeasurementFromHits_factory.h | 1 - 11 files changed, 18 deletions(-) diff --git a/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.cc b/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.cc index 92de31be61..12c04807dc 100644 --- a/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.cc +++ b/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.cc @@ -45,7 +45,6 @@ void femc_studiesProcessor::Init() { std::string plugin_name = ("femc_studies"); - // InitLogger(plugin_name); // =============================================================================================== // Get JANA application and seup general variables // =============================================================================================== diff --git a/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc b/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc index d44794e557..84542e9920 100644 --- a/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc +++ b/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc @@ -45,7 +45,6 @@ void lfhcal_studiesProcessor::Init() { std::string plugin_name = ("lfhcal_studies"); - // InitLogger(plugin_name); // =============================================================================================== // Get JANA application and seup general variables // =============================================================================================== diff --git a/src/factories/calorimetry/CalorimeterHitDigi_factory.h b/src/factories/calorimetry/CalorimeterHitDigi_factory.h index 42e9c9d19f..36b4277562 100644 --- a/src/factories/calorimetry/CalorimeterHitDigi_factory.h +++ b/src/factories/calorimetry/CalorimeterHitDigi_factory.h @@ -6,8 +6,6 @@ #include "algorithms/calorimetry/CalorimeterHitDigi.h" #include "services/algorithms_init/AlgorithmsInit_service.h" #include "extensions/jana/JOmniFactory.h" -#include "extensions/spdlog/SpdlogMixin.h" - namespace eicrecon { diff --git a/src/factories/calorimetry/CalorimeterHitsMerger_factory.h b/src/factories/calorimetry/CalorimeterHitsMerger_factory.h index b1eaa796d9..9f6aefcd1b 100644 --- a/src/factories/calorimetry/CalorimeterHitsMerger_factory.h +++ b/src/factories/calorimetry/CalorimeterHitsMerger_factory.h @@ -6,8 +6,6 @@ #include "algorithms/calorimetry/CalorimeterHitsMerger.h" #include "services/algorithms_init/AlgorithmsInit_service.h" #include "extensions/jana/JOmniFactory.h" -#include "extensions/spdlog/SpdlogMixin.h" - namespace eicrecon { diff --git a/src/factories/fardetectors/FarDetectorLinearProjection_factory.h b/src/factories/fardetectors/FarDetectorLinearProjection_factory.h index 252cf35b66..39510d37ca 100644 --- a/src/factories/fardetectors/FarDetectorLinearProjection_factory.h +++ b/src/factories/fardetectors/FarDetectorLinearProjection_factory.h @@ -7,7 +7,6 @@ #include #include #include -#include #include namespace eicrecon { diff --git a/src/global/pid/MergeTrack_factory.h b/src/global/pid/MergeTrack_factory.h index 38c82e1cc9..e3fa78b518 100644 --- a/src/global/pid/MergeTrack_factory.h +++ b/src/global/pid/MergeTrack_factory.h @@ -13,14 +13,10 @@ // algorithms #include "algorithms/interfaces/WithPodConfig.h" #include "algorithms/pid/MergeTracks.h" -// JANA #include "extensions/jana/JOmniFactory.h" -// services -#include "extensions/spdlog/SpdlogMixin.h" namespace eicrecon { - class MergeTrack_factory : public JOmniFactory { private: diff --git a/src/global/pid/RichTrack_factory.h b/src/global/pid/RichTrack_factory.h index 2295b8a859..96d7139674 100644 --- a/src/global/pid/RichTrack_factory.h +++ b/src/global/pid/RichTrack_factory.h @@ -17,10 +17,7 @@ // algorithms #include "algorithms/tracking/TrackPropagation.h" #include "algorithms/tracking/TrackPropagationConfig.h" -// JANA #include "extensions/jana/JOmniFactory.h" -#include "extensions/spdlog/SpdlogMixin.h" -// configuration #include "services/geometry/acts/ACTSGeo_service.h" #include "services/geometry/dd4hep/DD4hep_service.h" diff --git a/src/global/tracking/CKFTracking_factory.h b/src/global/tracking/CKFTracking_factory.h index 4fe3457f2f..803e4e63e4 100644 --- a/src/global/tracking/CKFTracking_factory.h +++ b/src/global/tracking/CKFTracking_factory.h @@ -17,7 +17,6 @@ #include "algorithms/tracking/CKFTracking.h" #include "algorithms/tracking/CKFTrackingConfig.h" #include "extensions/jana/JOmniFactory.h" -#include "extensions/spdlog/SpdlogMixin.h" #include "services/geometry/acts/ACTSGeo_service.h" namespace eicrecon { diff --git a/src/global/tracking/TrackParamTruthInit_factory.h b/src/global/tracking/TrackParamTruthInit_factory.h index eb7b4e2d60..4196b66c8b 100644 --- a/src/global/tracking/TrackParamTruthInit_factory.h +++ b/src/global/tracking/TrackParamTruthInit_factory.h @@ -15,7 +15,6 @@ #include "algorithms/tracking/TrackParamTruthInit.h" #include "algorithms/tracking/TrackParamTruthInitConfig.h" #include "extensions/jana/JOmniFactory.h" -#include "extensions/spdlog/SpdlogMixin.h" namespace eicrecon { diff --git a/src/global/tracking/TrackPropagation_factory.h b/src/global/tracking/TrackPropagation_factory.h index 697e127193..efaa4f6609 100644 --- a/src/global/tracking/TrackPropagation_factory.h +++ b/src/global/tracking/TrackPropagation_factory.h @@ -15,7 +15,6 @@ #include "algorithms/tracking/TrackPropagation.h" #include "algorithms/tracking/TrackPropagationConfig.h" #include "extensions/jana/JOmniFactory.h" -#include "extensions/spdlog/SpdlogMixin.h" #include "services/geometry/acts/ACTSGeo_service.h" #include "services/geometry/dd4hep/DD4hep_service.h" diff --git a/src/global/tracking/TrackerMeasurementFromHits_factory.h b/src/global/tracking/TrackerMeasurementFromHits_factory.h index c55af36761..d63f160b7d 100644 --- a/src/global/tracking/TrackerMeasurementFromHits_factory.h +++ b/src/global/tracking/TrackerMeasurementFromHits_factory.h @@ -14,7 +14,6 @@ #include "algorithms/interfaces/WithPodConfig.h" #include "algorithms/tracking/TrackerMeasurementFromHits.h" #include "extensions/jana/JOmniFactory.h" -#include "extensions/spdlog/SpdlogMixin.h" #include "services/geometry/acts/ACTSGeo_service.h" #include "services/geometry/dd4hep/DD4hep_service.h" From 8f66e97c7ad8c8d9f57dc60cbf1332b95d9d73cd Mon Sep 17 00:00:00 2001 From: Nathan Brei Date: Wed, 8 May 2024 01:23:28 -0400 Subject: [PATCH 3/5] Implement PID lookup table (#1365) ### Briefly, what does this PR introduce? Implement PID lookup table as per: - https://docs.google.com/document/d/1ViIBV0448Vnob0zE_Sm7kQsggsKOJZ9oYdmPp--QPvE/edit#heading=h.tf2uykgho79e - https://github.com/rdom/fastpid/ ### What kind of change does this PR introduce? - [ ] Bug fix (issue #__) - [x] New feature (issue #__) - [ ] Documentation update - [ ] Other: __ ### Please check if this PR fulfills the following: - [x] Tests for the changes have been added - [ ] Documentation has been added / updated - [ ] Changes have been communicated to collaborators ### Does this PR introduce breaking changes? What changes might users need to make to their code? No ### Does this PR change default behavior? No However, it does download a ~100MB file to the working directory. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Dmitry Kalinkin Co-authored-by: Wouter Deconinck --- .github/iwyu.imp | 1 + .github/workflows/linux-eic-shell.yml | 6 +- src/algorithms/CMakeLists.txt | 1 + src/algorithms/calorimetry/CMakeLists.txt | 2 +- src/algorithms/pid_lut/CMakeLists.txt | 14 ++ src/algorithms/pid_lut/PIDLookup.cc | 142 +++++++++++++++++ src/algorithms/pid_lut/PIDLookup.h | 44 ++++++ src/algorithms/pid_lut/PIDLookupConfig.h | 26 ++++ src/algorithms/tracking/TracksToParticles.cc | 3 - src/detectors/BTOF/BTOF.cc | 47 +++++- src/detectors/DIRC/CMakeLists.txt | 4 + src/detectors/DIRC/DIRC.cc | 43 ++++++ src/detectors/DRICH/DRICH.cc | 43 ++++++ src/detectors/PFRICH/CMakeLists.txt | 4 + src/detectors/PFRICH/PFRICH.cc | 47 ++++++ src/global/CMakeLists.txt | 1 + src/global/pid/pid.cc | 22 +-- src/global/pid_lut/CMakeLists.txt | 2 + src/global/pid_lut/PIDLookup_factory.h | 49 ++++++ src/services/CMakeLists.txt | 1 + src/services/io/podio/JEventProcessorPODIO.cc | 14 +- src/services/pid_lut/CMakeLists.txt | 13 ++ src/services/pid_lut/PIDLookupTable.cc | 145 ++++++++++++++++++ src/services/pid_lut/PIDLookupTable.h | 59 +++++++ src/services/pid_lut/PIDLookupTableSvc.h | 48 ++++++ src/services/pid_lut/pid_lut.cc | 18 +++ src/tests/algorithms_test/CMakeLists.txt | 3 + src/tests/algorithms_test/algorithmsInit.cc | 4 + .../algorithms_test/pid_lut_PIDLookup.cc | 88 +++++++++++ src/utilities/eicrecon/eicrecon.cc | 1 + 30 files changed, 867 insertions(+), 28 deletions(-) create mode 100644 src/algorithms/pid_lut/CMakeLists.txt create mode 100644 src/algorithms/pid_lut/PIDLookup.cc create mode 100644 src/algorithms/pid_lut/PIDLookup.h create mode 100644 src/algorithms/pid_lut/PIDLookupConfig.h create mode 100644 src/global/pid_lut/CMakeLists.txt create mode 100644 src/global/pid_lut/PIDLookup_factory.h create mode 100644 src/services/pid_lut/CMakeLists.txt create mode 100644 src/services/pid_lut/PIDLookupTable.cc create mode 100644 src/services/pid_lut/PIDLookupTable.h create mode 100644 src/services/pid_lut/PIDLookupTableSvc.h create mode 100644 src/services/pid_lut/pid_lut.cc create mode 100644 src/tests/algorithms_test/pid_lut_PIDLookup.cc diff --git a/.github/iwyu.imp b/.github/iwyu.imp index 8c6a1ecf13..99bbfe7c25 100644 --- a/.github/iwyu.imp +++ b/.github/iwyu.imp @@ -3,6 +3,7 @@ # Boost { ref: '/usr/local/share/include-what-you-use/boost-all.imp' }, + { include: ['@', private, '', public] }, # libc++ { ref: '/usr/local/share/include-what-you-use/libcxx.imp' }, diff --git a/.github/workflows/linux-eic-shell.yml b/.github/workflows/linux-eic-shell.yml index 04c6bede7a..39b91a4079 100644 --- a/.github/workflows/linux-eic-shell.yml +++ b/.github/workflows/linux-eic-shell.yml @@ -144,6 +144,7 @@ jobs: platform-release: "${{ env.platform }}:${{ matrix.release }}" run: | export LD_LIBRARY_PATH=$PWD/install/lib:$LD_LIBRARY_PATH + export JANA_PLUGIN_PATH=$PWD/install/lib/EICrecon/plugins${JANA_PLUGIN_PATH:+:${JANA_PLUGIN_PATH}} ctest --test-dir build -V - name: Compress install directory run: tar -caf install.tar.zst install/ @@ -267,8 +268,9 @@ jobs: llvm-profdata-15 merge -sparse src/tests/algorithms_test/algorithms_test.profraw \ -o src/tests/algorithms_test/algorithms_test.profdata LIB_PATHS=() - for LIB_NAME in algorithms_calorimetry algorithms_digi algorithms_pid algorithms_reco algorithms_tracking; do - LIB_PATH="$(find src/ -type f -name "*$LIB_NAME.so")" + for LIB_PATH in $(find src/ -type f -name "libalgorithms_*.so"); do + LIB_NAME="$(basename ${LIB_PATH%%.so})" + LIB_NAME="${LIB_NAME##lib}" LIB_PATHS+=("$LIB_PATH") llvm-cov-15 report $LIB_PATH \ -instr-profile=src/tests/algorithms_test/algorithms_test.profdata \ diff --git a/src/algorithms/CMakeLists.txt b/src/algorithms/CMakeLists.txt index 013ea11931..9adcb8fb49 100644 --- a/src/algorithms/CMakeLists.txt +++ b/src/algorithms/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(interfaces) add_subdirectory(calorimetry) add_subdirectory(tracking) add_subdirectory(pid) +add_subdirectory(pid_lut) add_subdirectory(digi) add_subdirectory(reco) add_subdirectory(fardetectors) diff --git a/src/algorithms/calorimetry/CMakeLists.txt b/src/algorithms/calorimetry/CMakeLists.txt index 5b940b7af5..d80e4abd6b 100644 --- a/src/algorithms/calorimetry/CMakeLists.txt +++ b/src/algorithms/calorimetry/CMakeLists.txt @@ -12,7 +12,7 @@ plugin_add(${PLUGIN_NAME} WITH_SHARED_LIBRARY WITHOUT_PLUGIN) plugin_glob_all(${PLUGIN_NAME}) # Find dependencies -plugin_add_algorithms(${PLUGIN_NAME} algocalorimetry) +plugin_add_algorithms(${PLUGIN_NAME}) plugin_add_dd4hep(${PLUGIN_NAME}) plugin_add_event_model(${PLUGIN_NAME}) plugin_add_eigen3(${PLUGIN_NAME}) diff --git a/src/algorithms/pid_lut/CMakeLists.txt b/src/algorithms/pid_lut/CMakeLists.txt new file mode 100644 index 0000000000..e2d37590c2 --- /dev/null +++ b/src/algorithms/pid_lut/CMakeLists.txt @@ -0,0 +1,14 @@ +set(PLUGIN_NAME "algorithms_pid_lut") + +# Function creates ${PLUGIN_NAME}_plugin and ${PLUGIN_NAME}_library targets +# Setting default includes, libraries and installation paths +plugin_add(${PLUGIN_NAME} WITH_SHARED_LIBRARY WITHOUT_PLUGIN) + +# The macro grabs sources as *.cc *.cpp *.c and headers as *.h *.hh *.hpp Then +# correctly sets sources for ${_name}_plugin and ${_name}_library targets Adds +# headers to the correct installation directory +plugin_glob_all(${PLUGIN_NAME}) + +# Find dependencies +plugin_add_algorithms(${PLUGIN_NAME}) +plugin_add_event_model(${PLUGIN_NAME}) diff --git a/src/algorithms/pid_lut/PIDLookup.cc b/src/algorithms/pid_lut/PIDLookup.cc new file mode 100644 index 0000000000..0fc1aac45e --- /dev/null +++ b/src/algorithms/pid_lut/PIDLookup.cc @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Nathan Brei, Dmitry Kalinkin + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "algorithms/pid_lut/PIDLookup.h" +#include "algorithms/pid_lut/PIDLookupConfig.h" +#include "services/pid_lut/PIDLookupTableSvc.h" + +namespace eicrecon { + +void PIDLookup::init() { + auto& serviceSvc = algorithms::ServiceSvc::instance(); + auto lut_svc = serviceSvc.service("PIDLookupTableSvc"); + + m_lut = lut_svc->load(m_cfg.filename, { + .pdg_values=m_cfg.pdg_values, + .charge_values=m_cfg.charge_values, + .momentum_edges=m_cfg.momentum_edges, + .polar_edges=m_cfg.polar_edges, + .azimuthal_binning=m_cfg.azimuthal_binning, + .azimuthal_bin_centers_in_lut=m_cfg.azimuthal_bin_centers_in_lut, + .momentum_bin_centers_in_lut=m_cfg.momentum_bin_centers_in_lut, + .polar_bin_centers_in_lut=m_cfg.polar_bin_centers_in_lut, + .skip_legacy_header=m_cfg.skip_legacy_header, + .use_radians=m_cfg.use_radians, + .missing_electron_prob=m_cfg.missing_electron_prob, + }); + if (m_lut == nullptr) { + throw std::runtime_error("LUT not available"); + } +} + +void PIDLookup::process(const Input& input, const Output& output) const { + const auto [recoparts_in, partassocs_in] = input; + auto [recoparts_out, partassocs_out, partids_out] = output; + + for (const auto& recopart_without_pid : *recoparts_in) { + edm4hep::MCParticle mcpart; + auto recopart = recopart_without_pid.clone(); + + // Find MCParticle from associations and propagate the relevant ones further + bool assoc_found = false; + for (auto assoc_in : *partassocs_in) { + if (assoc_in.getRec() == recopart_without_pid) { + if (assoc_found) { + warning("Found a duplicate association for ReconstructedParticle at index {}", recopart_without_pid.getObjectID().index); + warning("The previous MCParticle was at {} and the duplicate is at {}", mcpart.getObjectID().index, assoc_in.getSim().getObjectID().index); + } + assoc_found = true; + mcpart = assoc_in.getSim(); + auto assoc_out = assoc_in.clone(); + assoc_out.setRec(recopart); + partassocs_out->push_back(assoc_out); + } + } + if (not assoc_found) { + recoparts_out->push_back(recopart); + continue; + } + + int true_pdg = mcpart.getPDG(); + int true_charge = mcpart.getCharge(); + int charge = recopart.getCharge(); + double momentum = edm4hep::utils::magnitude(recopart.getMomentum()); + + double theta = edm4hep::utils::anglePolar(recopart.getMomentum()) / M_PI * 180.; + double phi = edm4hep::utils::angleAzimuthal(recopart.getMomentum()) / M_PI * 180.; + + trace("lookup for true_pdg={}, true_charge={}, momentum={:.2f} GeV, polar={:.2f}, aziumthal={:.2f}", + true_pdg, true_charge, momentum, theta, phi); + auto entry = m_lut->Lookup(true_pdg, true_charge, momentum, theta, phi); + + int identified_pdg = 0; // unknown + + if ((entry != nullptr) && ((entry->prob_electron != 0.) || (entry->prob_pion != 0.) || (entry->prob_kaon != 0.) || (entry->prob_electron != 0.))) { + double random_unit_interval = m_dist(m_gen); + + trace("entry with e:pi:K:P={}:{}:{}:{}", entry->prob_electron, entry->prob_pion, entry->prob_kaon, entry->prob_proton); + + recopart.addToParticleIDs(partids_out->create( + m_cfg.system, // std::int32_t type + std::copysign(11, charge), // std::int32_t PDG + 0, // std::int32_t algorithmType + static_cast(entry->prob_electron) // float likelihood + )); + recopart.addToParticleIDs(partids_out->create( + m_cfg.system, // std::int32_t type + std::copysign(211, charge), // std::int32_t PDG + 0, // std::int32_t algorithmType + static_cast(entry->prob_pion) // float likelihood + )); + recopart.addToParticleIDs(partids_out->create( + m_cfg.system, // std::int32_t type + std::copysign(321, charge), // std::int32_t PDG + 0, // std::int32_t algorithmType + static_cast(entry->prob_kaon) // float likelihood + )); + recopart.addToParticleIDs(partids_out->create( + m_cfg.system, // std::int32_t type + std::copysign(2212, charge), // std::int32_t PDG + 0, // std::int32_t algorithmType + static_cast(entry->prob_proton) // float likelihood + )); + + if (random_unit_interval < entry->prob_electron) { + identified_pdg = 11; // electron + recopart.setParticleIDUsed((*partids_out)[partids_out->size() - 4]); + } else if (random_unit_interval < (entry->prob_electron + entry->prob_pion)) { + identified_pdg = 211; // pion + recopart.setParticleIDUsed((*partids_out)[partids_out->size() - 3]); + } else if (random_unit_interval < + (entry->prob_electron + entry->prob_pion + entry->prob_kaon)) { + identified_pdg = 321; // kaon + recopart.setParticleIDUsed((*partids_out)[partids_out->size() - 2]); + } else if (random_unit_interval < (entry->prob_electron + entry->prob_pion + + entry->prob_kaon + entry->prob_electron)) { + identified_pdg = 2212; // proton + recopart.setParticleIDUsed((*partids_out)[partids_out->size() - 1]); + } + } + + recopart.setPDG(std::copysign(identified_pdg, charge)); + + if (identified_pdg != 0) { + trace("randomized PDG is {}", recopart.getPDG()); + } + + recoparts_out->push_back(recopart); + } +} + +} // namespace eicrecon diff --git a/src/algorithms/pid_lut/PIDLookup.h b/src/algorithms/pid_lut/PIDLookup.h new file mode 100644 index 0000000000..3f05c41573 --- /dev/null +++ b/src/algorithms/pid_lut/PIDLookup.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Nathan Brei, Dmitry Kalinkin + +#include +#include +#include +#include +#include +#include +#include + +#include "PIDLookupConfig.h" +#include "algorithms/interfaces/WithPodConfig.h" +#include "services/pid_lut/PIDLookupTable.h" + +namespace eicrecon { + +using PIDLookupAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +class PIDLookup : public PIDLookupAlgorithm, public WithPodConfig { + +public: + PIDLookup(std::string_view name) + : PIDLookupAlgorithm{name, + {"inputParticlesCollection", "inputParticleAssociationsCollection"}, + {"outputParticlesCollection", "outputParticleAssociationsCollection", + "outputParticleIDCollection"}, + ""} {} + + void init() final; + void process(const Input&, const Output&) const final; + +private: + mutable std::mt19937 m_gen{}; + mutable std::uniform_real_distribution m_dist{0, 1}; + const PIDLookupTable* m_lut; +}; + +} // namespace eicrecon diff --git a/src/algorithms/pid_lut/PIDLookupConfig.h b/src/algorithms/pid_lut/PIDLookupConfig.h new file mode 100644 index 0000000000..df8fd37b6f --- /dev/null +++ b/src/algorithms/pid_lut/PIDLookupConfig.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Nathan Brei, Dmitry Kalinkin + +#pragma once + +#include + +namespace eicrecon { + +struct PIDLookupConfig { + std::string filename; + int system; + std::vector pdg_values; + std::vector charge_values; + std::vector momentum_edges; + std::vector polar_edges; + std::vector azimuthal_binning; + bool azimuthal_bin_centers_in_lut {false}; + bool momentum_bin_centers_in_lut {false}; + bool polar_bin_centers_in_lut {false}; + bool skip_legacy_header {false}; + bool use_radians {false}; + bool missing_electron_prob {false}; +}; + +} // namespace eicrecon diff --git a/src/algorithms/tracking/TracksToParticles.cc b/src/algorithms/tracking/TracksToParticles.cc index eb40e7aafb..12399d2737 100644 --- a/src/algorithms/tracking/TracksToParticles.cc +++ b/src/algorithms/tracking/TracksToParticles.cc @@ -127,7 +127,6 @@ namespace eicrecon { } auto rec_part = parts->create(); rec_part.addToTracks(track); - int32_t best_pid = 0; auto referencePoint = rec_part.getReferencePoint(); // float time = 0; float mass = 0; @@ -135,7 +134,6 @@ namespace eicrecon { trace("Best match is found and is: {}", best_match); mc_prt_is_consumed[best_match] = true; const auto &best_mc_part = (*mc_particles)[best_match]; - best_pid = best_mc_part.getPDG(); referencePoint = { static_cast(best_mc_part.getVertex().x), static_cast(best_mc_part.getVertex().y), @@ -151,7 +149,6 @@ namespace eicrecon { rec_part.setCharge(charge_rec); rec_part.setMass(mass); rec_part.setGoodnessOfPID(0); // assume no PID until proven otherwise - rec_part.setPDG(best_pid); // rec_part.covMatrix() // @TODO: covariance matrix on 4-momentum // Also write MC <--> truth particle association if match was found diff --git a/src/detectors/BTOF/BTOF.cc b/src/detectors/BTOF/BTOF.cc index e5839dfd80..ef0ba38593 100644 --- a/src/detectors/BTOF/BTOF.cc +++ b/src/detectors/BTOF/BTOF.cc @@ -1,16 +1,27 @@ // Copyright 2022, Dmitry Romanov // Subject to the terms in the LICENSE file found in the top-level directory. // -// +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Dmitry Kalinkin + +#include #include #include +#include +#include +#include +#include +#include #include +#include #include "algorithms/interfaces/WithPodConfig.h" #include "extensions/jana/JOmniFactoryGeneratorT.h" #include "factories/digi/SiliconTrackerDigi_factory.h" #include "factories/tracking/TrackerHitReconstruction_factory.h" +#include "global/pid_lut/PIDLookup_factory.h" +#include "services/geometry/dd4hep/DD4hep_service.h" extern "C" { void InitPlugin(JApplication *app) { @@ -46,5 +57,39 @@ void InitPlugin(JApplication *app) { app )); // Hit reco default config for factories + int BarrelTOF_ID = 0; + try { + auto detector = app->GetService()->detector(); + BarrelTOF_ID = detector->constant("BarrelTOF_ID"); + } catch(const std::runtime_error&) { + // Nothing + } + for (auto qualifier : std::vector({"", "Seeded"})) { + app->Add(new JOmniFactoryGeneratorT( + fmt::format("CombinedTOF{}LUTPID", qualifier), + { + fmt::format("Reconstructed{}ChargedWithPFRICHPIDParticles", qualifier), + fmt::format("Reconstructed{}ChargedWithPFRICHPIDParticleAssociations", qualifier), + }, + { + fmt::format("Reconstructed{}ChargedWithPFRICHTOFPIDParticles", qualifier), + fmt::format("Reconstructed{}ChargedWithPFRICHTOFPIDParticleAssociations", qualifier), + fmt::format("CombinedTOF{}ParticleIDs", qualifier), + }, + { + .filename="calibrations/tof.lut", + .system=BarrelTOF_ID, + .pdg_values={11, 211, 321, 2212}, + .charge_values={1}, + .momentum_edges={0.0, 0.3, 0.6, 0.9, 1.2, 1.5, 1.8, 2.1, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.2, 4.5, 4.8, 5.1, 5.4, 5.7, 6.0}, + .polar_edges={2.50, 10.95, 19.40, 27.85, 36.30, 44.75, 53.20, 61.65, 70.10, 78.55, 87.00, 95.45, 103.90, 112.35, 120.80, 129.25, 137.70, 146.15, 154.60}, + .azimuthal_binning={0., 360., 360.}, // lower, upper, step + .momentum_bin_centers_in_lut=true, + .polar_bin_centers_in_lut=true, + }, + app + )); + } + } } // extern "C" diff --git a/src/detectors/DIRC/CMakeLists.txt b/src/detectors/DIRC/CMakeLists.txt index dc05000d4b..effa4d8cb6 100644 --- a/src/detectors/DIRC/CMakeLists.txt +++ b/src/detectors/DIRC/CMakeLists.txt @@ -15,3 +15,7 @@ plugin_glob_all(${PLUGIN_NAME}) # Find dependencies plugin_add_event_model(${PLUGIN_NAME}) plugin_add_dd4hep(${PLUGIN_NAME}) + +# Add libraries (same as target_include_directories but for both plugin and +# library) +plugin_link_libraries(${PLUGIN_NAME} algorithms_pid_lut_library) diff --git a/src/detectors/DIRC/DIRC.cc b/src/detectors/DIRC/DIRC.cc index f8c64fa58a..bd1d11f0bd 100644 --- a/src/detectors/DIRC/DIRC.cc +++ b/src/detectors/DIRC/DIRC.cc @@ -3,9 +3,18 @@ // // +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Dmitry Kalinkin + +#include #include +#include #include #include +#include +#include +#include +#include #include #include @@ -14,6 +23,8 @@ #include "extensions/jana/JOmniFactoryGeneratorT.h" // factories #include "global/digi/PhotoMultiplierHitDigi_factory.h" +#include "global/pid_lut/PIDLookup_factory.h" +#include "services/geometry/dd4hep/DD4hep_service.h" extern "C" { @@ -73,5 +84,37 @@ extern "C" { app )); + int BarrelDIRC_ID = 0; + try { + auto detector = app->GetService()->detector(); + BarrelDIRC_ID = detector->constant("BarrelDIRC_ID"); + } catch(const std::runtime_error&) { + // Nothing + } + for (auto qualifier : std::vector({"", "Seeded"})) { + app->Add(new JOmniFactoryGeneratorT( + fmt::format("DIRC{}LUTPID", qualifier), + { + fmt::format("Reconstructed{}ChargedWithPFRICHTOFPIDParticles", qualifier), + fmt::format("Reconstructed{}ChargedWithPFRICHTOFPIDParticleAssociations", qualifier), + }, + { + fmt::format("Reconstructed{}ChargedWithPFRICHTOFDIRCPIDParticles", qualifier), + fmt::format("Reconstructed{}ChargedWithPFRICHTOFDIRCPIDParticleAssociations", qualifier), + fmt::format("DIRC{}ParticleIDs", qualifier), + }, + { + .filename="calibrations/hpdirc_positive.lut", + .system=BarrelDIRC_ID, + .pdg_values={11, 211, 321, 2212}, + .charge_values={1}, + .momentum_edges={0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2, 6.4, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8, 8.0, 8.2, 8.4, 8.6, 8.8, 9.0, 9.2, 9.4, 9.6, 9.8, 10.0, 10.2}, + .polar_edges={25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 81.0, 82.0, 83.0, 84.0, 85.0, 86.0, 87.0, 88.0, 89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0, 97.0, 98.0, 99.0, 100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0, 107.0, 108.0, 109.0, 110.0, 111.0, 112.0, 113.0, 114.0, 115.0, 116.0, 117.0, 118.0, 119.0, 120.0, 121.0, 122.0, 123.0, 124.0, 125.0, 126.0, 127.0, 128.0, 129.0, 130.0, 131.0, 132.0, 133.0, 134.0, 135.0, 136.0, 137.0, 138.0, 139.0, 140.0, 141.0, 142.0, 143.0, 144.0, 145.0, 146.0, 147.0, 148.0, 149.0, 150.0, 151.0, 152.0, 153.0, 154.0, 155.0, 156.0, 157.0, 158.0, 159.0, 160.0}, + .azimuthal_binning={0.0, 30.5, 0.5}, // lower, upper, step + .skip_legacy_header=true, // originally used to define binning inside the file + }, + app + )); + } } } diff --git a/src/detectors/DRICH/DRICH.cc b/src/detectors/DRICH/DRICH.cc index ff0e8df84c..a3d3c78945 100644 --- a/src/detectors/DRICH/DRICH.cc +++ b/src/detectors/DRICH/DRICH.cc @@ -1,13 +1,20 @@ // Copyright (C) 2022, 2023, Christopher Dilks, Luigi Dello Stritto // Subject to the terms in the LICENSE file found in the top-level directory. +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Dmitry Kalinkin + #include #include #include #include +#include +#include #include +#include #include #include +#include #include #include #include @@ -24,6 +31,8 @@ #include "global/pid/MergeCherenkovParticleID_factory.h" #include "global/pid/MergeTrack_factory.h" #include "global/pid/RichTrack_factory.h" +#include "global/pid_lut/PIDLookup_factory.h" +#include "services/geometry/dd4hep/DD4hep_service.h" #include "services/geometry/richgeo/ActsGeo.h" #include "services/geometry/richgeo/RichGeo.h" #include "services/geometry/richgeo/RichGeo_service.h" @@ -179,6 +188,40 @@ extern "C" { app )); + int ForwardRICH_ID = 0; + try { + auto detector = app->GetService()->detector(); + ForwardRICH_ID = detector->constant("ForwardRICH_ID"); + } catch(const std::runtime_error&) { + // Nothing + } + for (auto qualifier : std::vector({"", "Seeded"})) { + app->Add(new JOmniFactoryGeneratorT( + fmt::format("DRICH{}LUTPID", qualifier), + { + fmt::format("Reconstructed{}ChargedWithPFRICHTOFDIRCPIDParticles", qualifier), + fmt::format("Reconstructed{}ChargedWithPFRICHTOFDIRCPIDParticleAssociations", qualifier), + }, + { + fmt::format("Reconstructed{}ChargedParticles", qualifier), + fmt::format("Reconstructed{}ChargedParticleAssociations", qualifier), + fmt::format("DRICH{}ParticleIDs", qualifier), + }, + { + .filename="calibrations/drich.lut", + .system=ForwardRICH_ID, + .pdg_values={211, 321, 2212}, + .charge_values={1}, + .momentum_edges={0.25, 0.75, 1.25, 1.75, 2.25, 2.75, 3.25, 3.75, 4.25, 4.75, 5.25, 5.75, 6.25, 6.75, 7.25, 7.75, 8.25, 8.75, 9.25, 9.75, 10.25, 10.75, 11.25, 11.75, 12.25, 12.75, 13.25, 13.75, 14.25, 14.75, 15.25, 15.75, 16.25, 16.75, 17.25, 17.75, 18.25, 18.75, 19.25, 19.75, 20.50, 21.50, 22.50, 23.50, 24.50, 25.50, 26.50, 27.50, 28.50, 29.50, 30.50}, + .polar_edges={0.060, 0.164, 0.269, 0.439}, + .azimuthal_binning={0., 2 * M_PI, 2 * M_PI}, // lower, upper, step + .polar_bin_centers_in_lut=true, + .use_radians=true, + .missing_electron_prob=true, + }, + app + )); + } // clang-format on } } diff --git a/src/detectors/PFRICH/CMakeLists.txt b/src/detectors/PFRICH/CMakeLists.txt index 561c2111dc..9f61a0aa69 100644 --- a/src/detectors/PFRICH/CMakeLists.txt +++ b/src/detectors/PFRICH/CMakeLists.txt @@ -17,3 +17,7 @@ plugin_add_irt(${PLUGIN_NAME}) plugin_add_event_model(${PLUGIN_NAME}) plugin_add_dd4hep(${PLUGIN_NAME}) plugin_add_acts(${PLUGIN_NAME}) + +# Add libraries (same as target_include_directories but for both plugin and +# library) +plugin_link_libraries(${PLUGIN_NAME} algorithms_pid_lut_library) diff --git a/src/detectors/PFRICH/PFRICH.cc b/src/detectors/PFRICH/PFRICH.cc index 6237af16b7..3a414b24e8 100644 --- a/src/detectors/PFRICH/PFRICH.cc +++ b/src/detectors/PFRICH/PFRICH.cc @@ -1,9 +1,19 @@ // Copyright (C) 2022, 2023, Christopher Dilks, Luigi Dello Stritto // Subject to the terms in the LICENSE file found in the top-level directory. +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Dmitry Kalinkin + +#include #include #include +#include +#include #include +#include +#include +#include +#include #include #include @@ -12,6 +22,8 @@ #include "extensions/jana/JOmniFactoryGeneratorT.h" // factories #include "global/digi/PhotoMultiplierHitDigi_factory.h" +#include "global/pid_lut/PIDLookup_factory.h" +#include "services/geometry/dd4hep/DD4hep_service.h" extern "C" { void InitPlugin(JApplication *app) { @@ -66,5 +78,40 @@ extern "C" { app )); + int BackwardRICH_ID = 0; + try { + auto detector = app->GetService()->detector(); + BackwardRICH_ID = detector->constant("BackwardRICH_ID"); + } catch(const std::runtime_error&) { + // Nothing + } + for (auto qualifier : std::vector({"", "Seeded"})) { + app->Add(new JOmniFactoryGeneratorT( + fmt::format("RICHEndcapN{}LUTPID", qualifier), + { + fmt::format("Reconstructed{}ChargedWithoutPIDParticles", qualifier), + fmt::format("Reconstructed{}ChargedWithoutPIDParticleAssociations", qualifier), + }, + { + fmt::format("Reconstructed{}ChargedWithPFRICHPIDParticles", qualifier), + fmt::format("Reconstructed{}ChargedWithPFRICHPIDParticleAssociations", qualifier), + fmt::format("RICHEndcapN{}ParticleIDs", qualifier), + }, + { + .filename="calibrations/pfrich.lut", + .system=BackwardRICH_ID, + .pdg_values={11, 211, 321, 2212}, + .charge_values={1}, + .momentum_edges={0.4, 0.8, 1.2, 1.6, 2, 2.4, 2.8, 3.2, 3.6, 4, 4.4, 4.8, 5.2, 5.6, 6, 6.4, 6.8, 7.2, 7.6, 8, 8.4, 8.8, 9.2, 9.6, 10, 10.4, 10.8, 11.2, 11.6, 12, 12.4, 12.8, 13.2, 13.6, 14, 14.4, 14.8, 15.2}, + .polar_edges={2.65, 2.6725, 2.695, 2.7175, 2.74, 2.7625, 2.785, 2.8075, 2.83, 2.8525, 2.875, 2.8975, 2.92, 2.9425, 2.965, 2.9875, 3.01, 3.0325, 3.055, 3.0775}, + .azimuthal_binning={0., 2 * M_PI, 2 * M_PI / 120.}, // lower, upper, step + .azimuthal_bin_centers_in_lut=true, + .momentum_bin_centers_in_lut=true, + .polar_bin_centers_in_lut=true, + .use_radians=true, + }, + app + )); + } } } diff --git a/src/global/CMakeLists.txt b/src/global/CMakeLists.txt index 165c5e0d49..4d12e01fc8 100644 --- a/src/global/CMakeLists.txt +++ b/src/global/CMakeLists.txt @@ -3,4 +3,5 @@ cmake_minimum_required(VERSION 3.16) add_subdirectory(tracking) add_subdirectory(reco) add_subdirectory(pid) +add_subdirectory(pid_lut) add_subdirectory(beam) diff --git a/src/global/pid/pid.cc b/src/global/pid/pid.cc index 53848c4178..612bf4fae3 100644 --- a/src/global/pid/pid.cc +++ b/src/global/pid/pid.cc @@ -28,27 +28,11 @@ extern "C" { "DRICHMergedIrtCherenkovParticleID", // edm4eic::CherenkovParticleID }, { - "ReconstructedChargedParticles", // edm4eic::ReconstructedParticle - "ReconstructedChargedParticleAssociations", // edm4eic::MCRecoParticleAssociationCollection - "ReconstructedChargedParticleIDs", // edm4hep::ParticleID + "ReconstructedChargedRealPIDParticles", // edm4eic::ReconstructedParticle + "ReconstructedChargedRealPIDParticleAssociations", // edm4eic::MCRecoParticleAssociationCollection + "ReconstructedChargedRealPIDParticleIDs", // edm4hep::ParticleID }, app )); - - app->Add(new JOmniFactoryGeneratorT( - "SeededChargedParticlesWithAssociations", - { - "ReconstructedSeededChargedWithoutPIDParticles", // edm4eic::ReconstructedParticle - "ReconstructedSeededChargedWithoutPIDParticleAssociations", // edm4eic::MCRecoParticleAssociationCollection - "DRICHMergedIrtCherenkovParticleID", // edm4eic::CherenkovParticleID - }, - { - "ReconstructedSeededChargedParticles", // edm4eic::ReconstructedParticle - "ReconstructedSeededChargedParticleAssociations", // edm4eic::MCRecoParticleAssociationCollection - "ReconstructedSeededChargedParticleIDs", // edm4hep::ParticleID - }, - app - )); - } } diff --git a/src/global/pid_lut/CMakeLists.txt b/src/global/pid_lut/CMakeLists.txt new file mode 100644 index 0000000000..2c4aaead3d --- /dev/null +++ b/src/global/pid_lut/CMakeLists.txt @@ -0,0 +1,2 @@ +set(PLUGIN_NAME "factories_pid_lut") +plugin_headers_only(${PLUGIN_NAME}) diff --git a/src/global/pid_lut/PIDLookup_factory.h b/src/global/pid_lut/PIDLookup_factory.h new file mode 100644 index 0000000000..964fa85ddc --- /dev/null +++ b/src/global/pid_lut/PIDLookup_factory.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Nathan Brei + +#pragma once + +#include +#include +#include +#include + +#include "algorithms/pid_lut/PIDLookup.h" +#include "extensions/jana/JOmniFactory.h" + +namespace eicrecon { + +class PIDLookup_factory : public JOmniFactory { +public: + using AlgoT = eicrecon::PIDLookup; + +private: + std::unique_ptr m_algo; + + PodioInput m_recoparticles_input{this}; + PodioInput m_recoparticle_assocs_input{this}; + PodioOutput m_recoparticles_output{this}; + PodioOutput m_recoparticle_assocs_output{this}; + PodioOutput m_particleids_output{this}; + + ParameterRef m_filename{this, "filename", config().filename, + "Relative to current working directory"}; + ParameterRef m_system{this, "system", config().system, "For the ParticleID record"}; + +public: + void Configure() { + m_algo = std::make_unique(this->GetPrefix()); + m_algo->level(static_cast(logger()->level())); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_recoparticles_input(), m_recoparticle_assocs_input()}, + {m_recoparticles_output().get(), m_recoparticle_assocs_output().get(), m_particleids_output().get()}); + } +}; + +} // namespace eicrecon diff --git a/src/services/CMakeLists.txt b/src/services/CMakeLists.txt index 8eb1fbe332..4587344f41 100644 --- a/src/services/CMakeLists.txt +++ b/src/services/CMakeLists.txt @@ -6,3 +6,4 @@ add_subdirectory(geometry/richgeo) add_subdirectory(io/podio) add_subdirectory(log) add_subdirectory(rootfile) +add_subdirectory(pid_lut) diff --git a/src/services/io/podio/JEventProcessorPODIO.cc b/src/services/io/podio/JEventProcessorPODIO.cc index 175a6823eb..db9247b3cd 100644 --- a/src/services/io/podio/JEventProcessorPODIO.cc +++ b/src/services/io/podio/JEventProcessorPODIO.cc @@ -89,6 +89,9 @@ JEventProcessorPODIO::JEventProcessorPODIO() { "TOFBarrelHitAssociations", "TOFEndcapHitAssociations", + "CombinedTOFParticleIDs", + "CombinedTOFSeededParticleIDs", + // DRICH "DRICHRawHits", "DRICHRawHitsAssociations", @@ -96,10 +99,14 @@ JEventProcessorPODIO::JEventProcessorPODIO() { "DRICHGasTracks", "DRICHAerogelIrtCherenkovParticleID", "DRICHGasIrtCherenkovParticleID", + "DRICHParticleIDs", + "DRICHSeededParticleIDs", // PFRICH "RICHEndcapNRawHits", "RICHEndcapNRawHitsAssociations", + "RICHEndcapNParticleIDs", + "RICHEndcapNSeededParticleIDs", // MPGD "MPGDBarrelRecHits", @@ -158,6 +165,7 @@ JEventProcessorPODIO::JEventProcessorPODIO() { "ReconstructedParticleAssociations", "ReconstructedChargedParticles", "ReconstructedChargedParticleAssociations", + "ReconstructedChargedRealPIDParticles", "ReconstructedSeededChargedParticles", "ReconstructedSeededChargedParticleAssociations", "MCScatteredElectronAssociations", // Remove if/when used internally @@ -279,9 +287,11 @@ JEventProcessorPODIO::JEventProcessorPODIO() { "HcalFarForwardZDCTruthClusterAssociations", "HcalFarForwardZDCNeutronCandidates", - // DIRC - "DIRCRawHits" + "DIRCRawHits", + "DIRCPID", + "DIRCParticleIDs", + "DIRCSeededParticleIDs", }; std::vector output_exclude_collections; // need to get as vector, then convert to set japp->SetDefaultParameter( diff --git a/src/services/pid_lut/CMakeLists.txt b/src/services/pid_lut/CMakeLists.txt new file mode 100644 index 0000000000..20524f230e --- /dev/null +++ b/src/services/pid_lut/CMakeLists.txt @@ -0,0 +1,13 @@ +# Automatically set plugin name the same as the directory name Don't forget +# string(REPLACE " " "_" PLUGIN_NAME ${PLUGIN_NAME}) if this dir has spaces in +# its name +get_filename_component(PLUGIN_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) + +# Function creates ${PLUGIN_NAME}_plugin Setting default includes, libraries and +# installation paths +plugin_add(${PLUGIN_NAME} WITH_SHARED_LIBRARY) + +# The macro grabs sources as *.cc *.cpp *.c and headers as *.h *.hh *.hpp Then +# correctly sets sources for ${_name}_plugin and ${_name}_library targets Adds +# headers to the correct installation directory +plugin_glob_all(${PLUGIN_NAME}) diff --git a/src/services/pid_lut/PIDLookupTable.cc b/src/services/pid_lut/PIDLookupTable.cc new file mode 100644 index 0000000000..417858428e --- /dev/null +++ b/src/services/pid_lut/PIDLookupTable.cc @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Nathan Brei, Dmitry Kalinkin + +#include "services/pid_lut/PIDLookupTable.h" + +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: keep +#include +#include // IWYU pragma: keep +#include +// IWYU pragma: no_include + +namespace bh = boost::histogram; + +namespace eicrecon { + +const PIDLookupTable::Entry* PIDLookupTable::Lookup(int pdg, int charge, double momentum, double theta_deg, double phi_deg) const { + // Our lookup table expects _unsigned_ PDGs. The charge information is passed separately. + pdg = std::abs(pdg); + + if (m_symmetrizing_charges) { + charge = std::abs(charge); + } + + return &m_hist[ + decltype(m_hist)::multi_index_type { + m_hist.axis(0).index(pdg), + m_hist.axis(1).index(charge), + m_hist.axis(2).index(momentum), + m_hist.axis(3).index(theta_deg), + m_hist.axis(4).index(phi_deg) + } + ]; +} + +void PIDLookupTable::load_file(const std::string& filename, const PIDLookupTable::Binning &binning) { + std::ifstream file(filename); + if (!file) { + throw std::runtime_error("Unable to open LUT file!"); + } + + std::string line; + std::istringstream iss; + double step; + + if (binning.skip_legacy_header) { + do { std::getline(file, line); } while (line.empty() || line[0] == '#'); + debug("Parsing pdg binning: {}", line); + + do { std::getline(file, line); } while (line.empty() || line[0] == '#'); + debug("Ignoring charge binning: {}", line); + + do { std::getline(file, line); } while (line.empty() || line[0] == '#'); + debug("Ignoring momentum binning: {}", line); + + do { std::getline(file, line); } while (line.empty() || line[0] == '#'); + debug("Ignoring theta binning: {}", line); + + do { std::getline(file, line); } while (line.empty() || line[0] == '#'); + debug("Ignoring phi binning: ", line); + } + + const double angle_fudge = binning.use_radians ? 180. / M_PI : 1.; + + bh::axis::category pdg_bins(binning.pdg_values); + bh::axis::category charge_bins(binning.charge_values); + bh::axis::variable<> momentum_bins(binning.momentum_edges); + std::vector polar_edges = binning.polar_edges; + for (double &edge : polar_edges) { + edge *= angle_fudge; + } + bh::axis::variable<> polar_bins(polar_edges); + bh::axis::circular<> azimuthal_bins(bh::axis::step(binning.azimuthal_binning.at(2) * angle_fudge), binning.azimuthal_binning.at(0) * angle_fudge, binning.azimuthal_binning.at(1) * angle_fudge); + + m_hist = bh::make_histogram_with(bh::dense_storage(), pdg_bins, charge_bins, momentum_bins, polar_bins, azimuthal_bins); + + m_symmetrizing_charges = binning.charge_values.size() == 1; + + while (std::getline(file, line)) { + Entry entry; + if (line.empty() || line[0] == '#' || std::all_of(std::begin(line), std::end(line), [](unsigned char c) { return std::isspace(c); })) continue; + + iss.str(line); + iss.clear(); + double pdg, charge, momentum, eta, phi, prob_electron, prob_pion, prob_kaon, prob_proton; + // Read each field from the line and assign to Entry struct members + if ((bool)(iss >> pdg + >> charge + >> momentum + >> eta + >> phi) && (binning.missing_electron_prob || (bool)(iss + >> prob_electron)) && (bool)(iss + >> prob_pion + >> prob_kaon + >> prob_proton)) { + + if (m_symmetrizing_charges) { + charge = std::abs(charge); + } + + // operator() here allows to lookup mutable entry and increases the access counter + auto &entry = *m_hist( + pdg, + charge, + momentum + (binning.momentum_bin_centers_in_lut ? 0. : (momentum_bins.bin(0).width() / 2)), + eta * angle_fudge + (binning.polar_bin_centers_in_lut ? 0. : (polar_bins.bin(0).width() / 2)), + phi * angle_fudge + (binning.azimuthal_bin_centers_in_lut ? 0. : (azimuthal_bins.bin(0).width() / 2)) + ); // N.B. bin(0) may not be of a correct width + entry.prob_electron = prob_electron; + entry.prob_pion = prob_pion; + entry.prob_kaon = prob_kaon; + entry.prob_proton = prob_proton; + } + else { + error("Unable to parse LUT file!"); + throw std::runtime_error("Unable to parse LUT file!"); + } + } + + for (auto&& b : bh::indexed(m_hist)) { + if (b->value() != 1) { + error( + "Bin {} {} {}:{} {}:{} {}:{} is defined {} times in the PID table", + b.bin(0).lower(), + b.bin(1).lower(), + b.bin(2).lower(), + b.bin(2).upper(), + b.bin(3).lower() / angle_fudge, + b.bin(3).upper() / angle_fudge, + b.bin(4).lower() / angle_fudge, + b.bin(4).upper() / angle_fudge, + b->value() + ); + } + } + + file.close(); +} + +} diff --git a/src/services/pid_lut/PIDLookupTable.h b/src/services/pid_lut/PIDLookupTable.h new file mode 100644 index 0000000000..86f7bc1ccf --- /dev/null +++ b/src/services/pid_lut/PIDLookupTable.h @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Nathan Brei, Dmitry Kalinkin + +#pragma once + +#include +#include +#include +#include +#include +// IWYU pragma: no_include + +namespace eicrecon { + +class PIDLookupTable : public algorithms::LoggerMixin { + +public: + /// The histogram entry with access counter, where the probabilities are stored in metadata + struct Entry : public boost::histogram::accumulators::count { + double prob_electron, prob_pion, prob_kaon, prob_proton; + }; + + struct Binning { + std::vector pdg_values; + std::vector charge_values; + std::vector momentum_edges; + std::vector polar_edges; + std::vector azimuthal_binning; + bool azimuthal_bin_centers_in_lut; + bool momentum_bin_centers_in_lut; + bool polar_bin_centers_in_lut; + bool skip_legacy_header; + bool use_radians; + bool missing_electron_prob; + }; + +private: + boost::histogram::histogram< + std::tuple< + boost::histogram::axis::category, + boost::histogram::axis::category, + boost::histogram::axis::variable<>, + boost::histogram::axis::variable<>, + boost::histogram::axis::circular<> + > + , boost::histogram::dense_storage + > m_hist; + bool m_symmetrizing_charges; + +public: + + PIDLookupTable() : algorithms::LoggerMixin("PIDLookupTable") {}; + + const Entry* Lookup(int pdg, int charge, double momentum, double theta_deg, double phi_deg) const; + + void load_file(const std::string& filename, const Binning &binning); +}; + +} diff --git a/src/services/pid_lut/PIDLookupTableSvc.h b/src/services/pid_lut/PIDLookupTableSvc.h new file mode 100644 index 0000000000..9aa735d1bd --- /dev/null +++ b/src/services/pid_lut/PIDLookupTableSvc.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Nathan Brei, Dmitry Kalinkin + +#pragma once + +#include +#include "PIDLookupTable.h" +#include +#include +#include +#include + +namespace eicrecon { + +class PIDLookupTableSvc : public algorithms::LoggedService { +public: + void init() {}; + + const PIDLookupTable* load(std::string filename, const PIDLookupTable::Binning &binning) { + std::lock_guard lock(m_mutex); + auto pair = m_cache.find(filename); + if (pair == m_cache.end()) { + auto lut = std::make_unique(); + info("Loading PID lookup table \"{}\"", filename); + + if (!std::filesystem::exists(filename)) { + error("PID lookup table \"{}\" not found", filename); + return nullptr; + } + + lut->load_file(filename, binning); // load_file can except + auto result_ptr = lut.get(); + m_cache.insert({filename, std::move(lut)}); + return result_ptr; + } + else { + return pair->second.get(); + } + } + +private: + std::mutex m_mutex; + std::map> m_cache; + + ALGORITHMS_DEFINE_LOGGED_SERVICE(PIDLookupTableSvc); +}; + +} diff --git a/src/services/pid_lut/pid_lut.cc b/src/services/pid_lut/pid_lut.cc new file mode 100644 index 0000000000..cf5e0b8e19 --- /dev/null +++ b/src/services/pid_lut/pid_lut.cc @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024, Nathan Brei, Dmitry Kalinkin + +#include +#include + +#include "PIDLookupTableSvc.h" + +extern "C" { + +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + + auto& serviceSvc = algorithms::ServiceSvc::instance(); + auto& pidLookupTableSvc = eicrecon::PIDLookupTableSvc::instance(); + serviceSvc.add(&pidLookupTableSvc); +} +} diff --git a/src/tests/algorithms_test/CMakeLists.txt b/src/tests/algorithms_test/CMakeLists.txt index 0ad3e1bb5d..93aa04a4a6 100644 --- a/src/tests/algorithms_test/CMakeLists.txt +++ b/src/tests/algorithms_test/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable( calorimetry_HEXPLIT.cc pid_MergeTracks.cc pid_MergeParticleID.cc + pid_lut_PIDLookup.cc reco_FarForwardNeutronReconstruction.cc) # Explicit linking to podio::podio is needed due to @@ -21,8 +22,10 @@ target_link_libraries( algorithms_calorimetry_library algorithms_fardetectors_library algorithms_pid_library + algorithms_pid_lut_library algorithms_reco_library evaluator_library + pid_lut_library podio::podio podio::podioRootIO) diff --git a/src/tests/algorithms_test/algorithmsInit.cc b/src/tests/algorithms_test/algorithmsInit.cc index 85846abe03..cdbb8b0779 100644 --- a/src/tests/algorithms_test/algorithmsInit.cc +++ b/src/tests/algorithms_test/algorithmsInit.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,9 @@ class algorithmsInitListener : public Catch::EventListenerBase { auto& evaluatorSvc = eicrecon::EvaluatorSvc::instance(); serviceSvc.add(&evaluatorSvc); + auto& lutSvc = eicrecon::PIDLookupTableSvc::instance(); + serviceSvc.add(&lutSvc); + serviceSvc.init(); } }; diff --git a/src/tests/algorithms_test/pid_lut_PIDLookup.cc b/src/tests/algorithms_test/pid_lut_PIDLookup.cc new file mode 100644 index 0000000000..0bfc8db7f9 --- /dev/null +++ b/src/tests/algorithms_test/pid_lut_PIDLookup.cc @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2023, Dmitry Kalinkin + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "algorithms/pid_lut/PIDLookup.h" +#include "algorithms/pid_lut/PIDLookupConfig.h" + +using eicrecon::PIDLookup; +using eicrecon::PIDLookupConfig; + +TEST_CASE( "particles acquire PID", "[PIDLookup]" ) { + PIDLookup algo("test"); + + PIDLookupConfig cfg { + .filename="/dev/null", + .system=0xFF, + .pdg_values={11}, + .charge_values={1}, + .momentum_edges={0., 1., 2.}, + .polar_edges={0., M_PI}, + .azimuthal_binning={0., 2 * M_PI, 2 * M_PI}, // lower, upper, step + .momentum_bin_centers_in_lut=true, + .polar_bin_centers_in_lut=true, + .use_radians=true, + }; + + SECTION( "single hit with couple contributions" ) { + algo.level(algorithms::LogLevel(spdlog::level::trace)); + algo.applyConfig(cfg); + algo.init(); + + auto parts_in = std::make_unique(); + auto assocs_in = std::make_unique(); + auto mcparts = std::make_unique(); + + parts_in->create( + 0, // std::int32_t type + 0.5, // float energy + edm4hep::Vector3f({0.5, 0., 0.}), // edm4hep::Vector3f momentum + edm4hep::Vector3f({0., 0., 0.}), // edm4hep::Vector3f referencePoint + 1., // float charge + 0., // float mass + 0., // float goodnessOfPID + edm4eic::Cov4f(), // edm4eic::Cov4f covMatrix + 0 // std::int32_t PDG + ); + mcparts->create( + 11, // std::int32_t PDG + 0, // std::int32_t generatorStatus + 0, // std::int32_t simulatorStatus + 0., // float charge + 0., // float time + 0., // double mass + edm4hep::Vector3d(), // edm4hep::Vector3d vertex + edm4hep::Vector3d(), // edm4hep::Vector3d endpoint + edm4hep::Vector3f(), // edm4hep::Vector3f momentum + edm4hep::Vector3f(), // edm4hep::Vector3f momentumAtEndpoint + edm4hep::Vector3f(), // edm4hep::Vector3f spin + edm4hep::Vector2i() // edm4hep::Vector2i colorFlow + ); + + auto assoc_in = assocs_in->create(); + assoc_in.setRec((*parts_in)[0]); + assoc_in.setSim((*mcparts)[0]); + + auto parts_out = std::make_unique(); + auto assocs_out = std::make_unique(); + auto partids_out = std::make_unique(); + algo.process({parts_in.get(), assocs_in.get()}, {parts_out.get(), assocs_out.get(), partids_out.get()}); + + REQUIRE( (*parts_in).size() == (*parts_out).size() ); + REQUIRE( (*assocs_in).size() == (*assocs_out).size() ); + REQUIRE( (*partids_out).size() == (*partids_out).size() ); + } +} diff --git a/src/utilities/eicrecon/eicrecon.cc b/src/utilities/eicrecon/eicrecon.cc index 0eeba84914..e8c75c6948 100644 --- a/src/utilities/eicrecon/eicrecon.cc +++ b/src/utilities/eicrecon/eicrecon.cc @@ -18,6 +18,7 @@ std::vector EICRECON_DEFAULT_PLUGINS = { "acts", "algorithms_init", "evaluator", + "pid_lut", "richgeo", "rootfile", "beam", From 01ef6804bc9b6cb88f7cd3d144bd9836616d9be1 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinkin Date: Wed, 8 May 2024 12:38:41 -0400 Subject: [PATCH 4/5] cmake: force linkage of shared libraries (#1431) This is brought by an issue that plagued pid_lut builds inside the container: https://eicweb.phy.anl.gov/EIC/benchmarks/physics_benchmarks/-/jobs/3070278#L1611 Our build process produces two shared objects: - A foo_plugin that incorporates src/foo/foo.cc (containing JANA2-related enty point) - A foo_library that contains all other *.cc files In order to have a complete set of symbols we ask linker to kindly link foo_library to foo_plugin. Unfortunately, it can ignore our request if it deems that the foo_library symbols are not referenced anywhere. This commit modifies the linking process to incorporate --no-as-needed option. The fancy feature from the https://gitlab.kitware.com/cmake/cmake/-/commit/42965799b4747ab1e0afa6546be13444f68c1987 makes it so that other libraries (e.g. external ones like podio) can still be linked lazily. At this point we can remove WITH_STATIC_LIBRARY per-plugin configuration. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CMakeLists.txt | 9 ++++++++- cmake/jana_plugin.cmake | 25 +++++++++++++++--------- src/services/log/CMakeLists.txt | 2 +- src/tests/algorithms_test/CMakeLists.txt | 8 -------- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bfcd51e89..88a00b8e9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ # # cmake-format: on -cmake_minimum_required(VERSION 3.18) +cmake_minimum_required(VERSION 3.24) project(EICrecon) @@ -65,6 +65,13 @@ endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +# Infrastructure to support use of --no-as-needed +include(CheckLinkerFlag) +check_linker_flag(CXX "LINKER:--no-as-needed" CXX_LINKER_HAS_no_as_needed) +set(CMAKE_CXX_LINK_LIBRARY_USING_NO_AS_NEEDED_SUPPORTED TRUE) +set(CMAKE_CXX_LINK_LIBRARY_USING_NO_AS_NEEDED + "LINKER:--push-state,--no-as-needed" "" "LINKER:--pop-state") + # Export compile commands as json for run-clang-tidy set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/cmake/jana_plugin.cmake b/cmake/jana_plugin.cmake index ef090303f7..dc3082fc51 100644 --- a/cmake/jana_plugin.cmake +++ b/cmake/jana_plugin.cmake @@ -51,9 +51,7 @@ macro(plugin_add _name) PUBLIC $ $) target_include_directories(${_name}_plugin SYSTEM - PUBLIC ${JANA_INCLUDE_DIR}) - target_include_directories(${_name}_plugin SYSTEM - PUBLIC ${ROOT_INCLUDE_DIRS}) + PUBLIC ${JANA_INCLUDE_DIR} ${ROOT_INCLUDE_DIRS}) set_target_properties( ${_name}_plugin PROPERTIES PREFIX "" @@ -91,11 +89,14 @@ macro(plugin_add _name) $) target_include_directories(${_name}_library SYSTEM PUBLIC ${JANA_INCLUDE_DIR}) - target_link_libraries(${_name}_library ${JANA_LIB} podio::podio - podio::podioRootIO spdlog::spdlog) - target_link_libraries(${_name}_library ${JANA_LIB} podio::podio - podio::podioRootIO fmt::fmt) - target_link_libraries(${_name}_library Microsoft.GSL::GSL) + target_link_libraries( + ${_name}_library + ${JANA_LIB} + podio::podio + podio::podioRootIO + spdlog::spdlog + fmt::fmt + Microsoft.GSL::GSL) # Install library install( @@ -105,7 +106,13 @@ macro(plugin_add _name) endif(${_name}_WITH_LIBRARY) if(${_name}_WITH_LIBRARY AND ${_name}_WITH_PLUGIN) - target_link_libraries(${_name}_plugin ${_name}_library) + # Ensure that whenever a plugin is loaded its library is loaded as well + if(CXX_LINKER_HAS_no_as_needed) + target_link_libraries(${_name}_plugin + $) + else() + target_link_libraries(${_name}_plugin ${_name}_library>) + endif() endif() endmacro() diff --git a/src/services/log/CMakeLists.txt b/src/services/log/CMakeLists.txt index a1a0449324..4bbe0ebb2b 100644 --- a/src/services/log/CMakeLists.txt +++ b/src/services/log/CMakeLists.txt @@ -7,7 +7,7 @@ get_filename_component(PLUGIN_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) # Function creates ${PLUGIN_NAME}_plugin and ${PLUGIN_NAME}_library targets # Setting default includes, libraries and installation paths -plugin_add(${PLUGIN_NAME} WITH_STATIC_LIBRARY) +plugin_add(${PLUGIN_NAME} WITH_SHARED_LIBRARY) # The macro grabs sources as *.cc *.cpp *.c and headers as *.h *.hh *.hpp Then # correctly sets sources for ${_name}_plugin and ${_name}_library targets Adds diff --git a/src/tests/algorithms_test/CMakeLists.txt b/src/tests/algorithms_test/CMakeLists.txt index 93aa04a4a6..3ca06a1d97 100644 --- a/src/tests/algorithms_test/CMakeLists.txt +++ b/src/tests/algorithms_test/CMakeLists.txt @@ -29,14 +29,6 @@ target_link_libraries( podio::podio podio::podioRootIO) -# As-needed fails due to absent podio symbols in libJANA.so -# (https://github.com/JeffersonLab/JANA2/pull/255) -include(CheckLinkerFlag) -check_linker_flag(CXX "-Wl,--no-as-needed" CXX_LINKER_HAS_no_as_needed) -if(CXX_LINKER_HAS_no_as_needed) - target_link_options(${TEST_NAME} PRIVATE "-Wl,--no-as-needed") -endif() - # Install executable install(TARGETS ${TEST_NAME} DESTINATION bin) From 9fceb229d5c4db99e0a8d870519c6c5376809c4c Mon Sep 17 00:00:00 2001 From: Dmitry Kalinkin Date: Wed, 8 May 2024 13:16:45 -0400 Subject: [PATCH 5/5] linux-eic-shell.yml: remove eicrecon-test-plugins[reco_test] (#1433) Was removed in https://github.com/eic/EICrecon/pull/1427, where the tests got away ``` [INFO] JPluginLoader: Initializing plugin "/usr/local/lib/EICrecon/plugins/reco_test.so" ``` Once nightly had hit cvmfs, that wouldn't work anymore. --- .github/workflows/linux-eic-shell.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/linux-eic-shell.yml b/.github/workflows/linux-eic-shell.yml index 39b91a4079..7d5bc4bf7b 100644 --- a/.github/workflows/linux-eic-shell.yml +++ b/.github/workflows/linux-eic-shell.yml @@ -556,7 +556,6 @@ jobs: detector_config: [craterlake] test_plugins: - geometry_navigation_test - - reco_test - tracking_test - track_propagation_test steps: