From b1e09f564ea82db197505be9f19cfe086f2d7939 Mon Sep 17 00:00:00 2001 From: garypenman Date: Fri, 7 Aug 2026 13:28:50 +0100 Subject: [PATCH 01/15] Added 10ns bunch aware hit partitioning to far detector tracking, for lowq2 bremsstrahlung background studies --- .../fardetectors/FarDetectorLinearTracking.cc | 321 +++++++++++++++--- 1 file changed, 270 insertions(+), 51 deletions(-) diff --git a/src/algorithms/fardetectors/FarDetectorLinearTracking.cc b/src/algorithms/fardetectors/FarDetectorLinearTracking.cc index 6d59689cf4..98df439152 100644 --- a/src/algorithms/fardetectors/FarDetectorLinearTracking.cc +++ b/src/algorithms/fardetectors/FarDetectorLinearTracking.cc @@ -85,77 +85,260 @@ void FarDetectorLinearTracking::process(const FarDetectorLinearTracking::Input& if (do_assoc) { link_nav.emplace(*hitLinks); } - + std::vector> convertedHits; std::vector> assocParts; convertedHits.reserve(m_cfg.n_layer); assocParts.reserve(m_cfg.n_layer); - // Check there aren't too many hits in any layer to handle - // Temporary limit of number of hits per layer before Kalman filtering/GNN implemented - // TODO - Implement more sensible solution + ///////////////////////////////////////////// + //G. Penman August 2026 + //1. Find time offsets + std::vector tmin(m_cfg.n_layer, 1e9); + std::vector tmax(m_cfg.n_layer, -1e9); + int ilayer = 0; + for (const auto& layerHits : inputhits) { - if ((*layerHits).size() > m_cfg.layer_hits_max) { - info("Too many hits in layer"); - return; + for (const auto& cluster : *layerHits) { + double t = cluster.getTime(); + + tmin[ilayer] = std::min(tmin[ilayer], t); + tmax[ilayer] = std::max(tmax[ilayer], t); } - if ((*layerHits).empty()) { - trace("No hits in layer"); - return; + + // info("Layer {} nhits {}", ilayer, layerHits->size()); + // info("Layer {} timing range {} -> {}", ilayer, tmin[ilayer], tmax[ilayer]); + ilayer++; + } + + //2. created sorted times of hits in each layer by ~10ns bunch + using BXHits_t = std::unordered_map>>; + BXHits_t bxHits; + std::map bxCount; + ilayer = 0; + + for (const auto& layerHits : inputhits) { + + for (const auto& cluster : *layerHits) { + double t = cluster.getTime(); + + //later using tmin[ilayer], tmax[ilayer] + int bx = static_cast(std::floor(t / 10.0)); + bxCount[bx]++; //total hits in time window + if(bxHits.find(bx) == bxHits.end()) { + bxHits[bx] = std::vector>(m_cfg.n_layer); + } + + bxHits[bx][ilayer].push_back(cluster); } - ConvertClusters(*layerHits, *link_nav, *assocHits, convertedHits, assocParts); + ilayer++; } - // Create a matrix to store the hit positions - Eigen::MatrixXd hitMatrix(3, m_cfg.n_layer); + + // for (const auto& [bx,n] : bxCount) { + // info("BX {} : {} hits", bx, n); + // } - // Create vector to store indexes of hits in the track - std::vector layerHitIndex(m_cfg.n_layer, 0); + // bool validBX = true; - int layer = 0; + // for(size_t layer=0; layer 0 && m_cfg.restrict_direction) { - isValid = checkHitPair(hitMatrix.col(layer - 1), hitMatrix.col(layer)); - } + // if(!validBX) + // continue; + + + for (const auto& [bx, bxLayers] : bxHits) { + + debug("Processing BX {}", bx); + + std::vector> convertedHits; + std::vector> assocParts; - // If valid hit combination, move to the next layer or check the combination - if (isValid) { - if (layer == static_cast(m_cfg.n_layer) - 1) { - // Check the combination, if chi2 limit is passed, add the track to the output - checkHitCombination(&hitMatrix, outputTracks, trackLinks, assocTracks, inputhits, - assocParts, layerHitIndex); - } else { - layer++; - continue; + convertedHits.reserve(m_cfg.n_layer); + assocParts.reserve(m_cfg.n_layer); + + + std::vector bxCollections; + std::vector> bxInputHits; + + bxCollections.reserve(m_cfg.n_layer); + bxInputHits.reserve(m_cfg.n_layer); + + bool validBX = true; + + for (std::size_t layer = 0; layer < m_cfg.n_layer; ++layer) { + + const auto& hits = bxLayers[layer]; + + if (hits.empty()) { + validBX = false; + break; + } + + if (hits.size() > m_cfg.layer_hits_max) { + validBX = false; + break; } + + bxCollections.emplace_back(); + + auto& tmpCollection = bxCollections.back(); + + tmpCollection.setSubsetCollection(); + + for (const auto& h : hits) { + tmpCollection.push_back(h); + } + + bxInputHits.push_back(gsl::not_null(&tmpCollection)); + //bxInputHits.push_back(tmpCollection); + + ConvertClusters(tmpCollection, + *link_nav, + *assocHits, + convertedHits, + assocParts); + + //info("BX {} layer {} converted {} hits", bx, layer, convertedHits.back().size()); } - // Iterate current layer - layerHitIndex[layer]++; + + if (!validBX) + continue; + + Eigen::MatrixXd hitMatrix(3, m_cfg.n_layer); + + std::vector layerHitIndex(m_cfg.n_layer, 0); - bool doBreak = false; - // Set up next combination to check - while (layerHitIndex[layer] >= convertedHits[layer].size()) { - layerHitIndex[layer] = 0; - if (layer == 0) { - doBreak = true; - break; + int layer = 0; + + while (true) { + + hitMatrix.col(layer) << convertedHits[layer][layerHitIndex[layer]]; + + bool isValid = true; + + if (layer > 0 && m_cfg.restrict_direction) { + isValid = checkHitPair(hitMatrix.col(layer-1), + hitMatrix.col(layer)); } - layer--; - // Iterate previous layer + + if (isValid) { + + if (layer == + static_cast(m_cfg.n_layer)-1) { + + checkHitCombination(&hitMatrix, + outputTracks, + trackLinks, + assocTracks, + bxInputHits, + assocParts, + layerHitIndex); + + } else { + + layer++; + continue; + } + } + layerHitIndex[layer]++; - } - if (doBreak) { - break; + + bool doBreak = false; + + while (layerHitIndex[layer] >= + convertedHits[layer].size()) { + + layerHitIndex[layer] = 0; + + if (layer == 0) { + doBreak = true; + break; + } + + layer--; + layerHitIndex[layer]++; + } + + if (doBreak) + break; } } } + + // Check there aren't too many hits in any layer to handle + // Temporary limit of number of hits per layer before Kalman filtering/GNN implemented + // TODO - Implement more sensible solution + // for (const auto& layerHits : inputhits) { + // if ((*layerHits).size() > m_cfg.layer_hits_max) { + // info("Too many hits in layer"); + // return; + // } + // if ((*layerHits).empty()) { + // trace("No hits in layer"); + // return; + // } + // ConvertClusters(*layerHits, *link_nav, *assocHits, convertedHits, assocParts); + // } + + // // Create a matrix to store the hit positions +// Eigen::MatrixXd hitMatrix(3, m_cfg.n_layer); + +// // Create vector to store indexes of hits in the track +// std::vector layerHitIndex(m_cfg.n_layer, 0); + +// int layer = 0; + +// // Iterate over all combinations of measurements in the layers without recursion +// while (true) { +// hitMatrix.col(layer) << convertedHits[layer][layerHitIndex[layer]]; + +// bool isValid = true; +// // Check the last two hits are within a certain angle of the optimum direction +// if (layer > 0 && m_cfg.restrict_direction) { +// isValid = checkHitPair(hitMatrix.col(layer - 1), hitMatrix.col(layer)); +// } + +// // If valid hit combination, move to the next layer or check the combination +// if (isValid) { +// if (layer == static_cast(m_cfg.n_layer) - 1) { +// // Check the combination, if chi2 limit is passed, add the track to the output +// checkHitCombination(&hitMatrix, outputTracks, trackLinks, assocTracks, inputhits, +// assocParts, layerHitIndex); +// } else { +// layer++; +// continue; +// } +// } + +// // Iterate current layer +// layerHitIndex[layer]++; + +// bool doBreak = false; +// // Set up next combination to check +// while (layerHitIndex[layer] >= convertedHits[layer].size()) { +// layerHitIndex[layer] = 0; +// if (layer == 0) { +// doBreak = true; +// break; +// } +// layer--; +// // Iterate previous layer +// layerHitIndex[layer]++; +// } +// if (doBreak) { +// break; +// } +// } +// } void FarDetectorLinearTracking::checkHitCombination( Eigen::MatrixXd* hitMatrix, edm4eic::TrackCollection* outputTracks, @@ -191,12 +374,48 @@ void FarDetectorLinearTracking::checkHitCombination( outVec = outVec * -1; } + + // for (std::size_t layer = 0; + // layer < layerHitIndex.size(); + // layer++) { + + // auto t = + // (*inputHits[layer])[layerHitIndex[layer]].getTime(); + + // info("Layer {} time {}", layer, t); + // } + + //get a nonzero time + double sumTime = 0.0; + std::vector times; + + for (std::size_t layer = 0; layer < layerHitIndex.size(); layer++) { + + double t = + (*inputHits[layer])[layerHitIndex[layer]].getTime(); + + times.push_back(t); + sumTime += t; + } + + float time = sumTime / times.size(); + + double variance = 0.0; + + for (const auto& t : times) { + variance += (t - time) * (t - time); + } + + variance /= (times.size() - 1); + + double timeError = std::sqrt(variance); + int32_t type{0}; // Type of track edm4hep::Vector3f position(outPos.x, outPos.y, outPos.z); // Position of the trajectory point [mm] edm4hep::Vector3f momentum(outVec.x, outVec.y, outVec.z); // 3-momentum at the point [GeV] edm4eic::Cov6f positionMomentumCovariance; // Error on the position - float time{0}; // Time at this point [ns] - float timeError{0}; // Error on the time at this point + //float time{0}; // Time at this point [ns] + //float timeError{0}; // Error on the time at this point float charge{-1}; // Charge of the particle int32_t ndf{static_cast(m_cfg.n_layer) - 1}; // Number of degrees of freedom int32_t pdg{11}; // PDG code of the particle @@ -245,8 +464,8 @@ bool FarDetectorLinearTracking::checkHitPair(const Eigen::Vector3d& hit1, } // Convert measurements into global coordinates -void FarDetectorLinearTracking::ConvertClusters( - const edm4eic::Measurement2DCollection& clusters, + void FarDetectorLinearTracking::ConvertClusters( + const edm4eic::Measurement2DCollection& clusters, const podio::LinkNavigator& link_nav, [[maybe_unused]] const edm4eic::MCRecoTrackerHitAssociationCollection& assoc_hits, std::vector>& pointPositions, From 62fa86b26979105b67af63ef81202580667ed344 Mon Sep 17 00:00:00 2001 From: garypenman Date: Fri, 7 Aug 2026 13:30:42 +0100 Subject: [PATCH 02/15] Propagate track associatoins through transportation ML for far detectors --- .../FarDetectorTransportationPostML.cc | 6 +++++- .../FarDetectorTransportationPostML.h | 15 ++++++++++----- .../FarDetectorTransportationPostML_factory.h | 7 ++++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc index 5b44a46207..0f070d6fd3 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc @@ -28,7 +28,7 @@ void FarDetectorTransportationPostML::process( const FarDetectorTransportationPostML::Input& input, const FarDetectorTransportationPostML::Output& output) const { - const auto [prediction_tensors, track_associations, beamElectrons] = input; + const auto [prediction_tensors, tracks, track_associations, beamElectrons] = input; auto [out_particles, out_links, out_associations] = output; //Set beam energy from first MCBeamElectron, using std::call_once @@ -111,6 +111,10 @@ void FarDetectorTransportationPostML::process( particle.setMass(m_mass); particle.setPDG(m_cfg.pdg_value); + if (tracks != nullptr && i < tracks->size()) { + particle.addToTracks((*tracks)[i]); + } + //Check if both association collections are set and copy the MCParticle association if ((track_associations != nullptr) && (track_associations->size() > i)) { // Copy the association from the input to the output diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.h b/src/algorithms/fardetectors/FarDetectorTransportationPostML.h index 6b74a2f608..e014e4fd6a 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.h +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -21,10 +22,14 @@ namespace eicrecon { using FarDetectorTransportationPostMLAlgorithm = algorithms::Algorithm< - algorithms::Input, - std::optional>, - algorithms::Output, + // std::optional>, + algorithms::Input, + std::optional>, + algorithms::Output>; @@ -36,7 +41,7 @@ class FarDetectorTransportationPostML FarDetectorTransportationPostML(std::string_view name) : FarDetectorTransportationPostMLAlgorithm{ name, - {"inputPredictionsTensor", "trackAssociations", "beamElectrons"}, + {"inputPredictionsTensor", "tracks", "trackAssociations", "beamElectrons"}, {"outputParticles", "outputLinks", "outputAssociations"}, "Convert ML output tensor into reconstructed electron"} {} diff --git a/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h b/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h index a0e831d445..083f3810da 100644 --- a/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h +++ b/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h @@ -7,6 +7,7 @@ #include "algorithms/fardetectors/FarDetectorTransportationPostML.h" #include "services/algorithms_init/AlgorithmsInit_service.h" #include "extensions/jana/JOmniFactory.h" +#include namespace eicrecon { @@ -21,6 +22,7 @@ class FarDetectorTransportationPostML_factory std::unique_ptr m_algo; PodioInput m_prediction_tensor_input{this}; + PodioInput m_tracks_input{this}; PodioInput m_association_input{this}; PodioInput m_beamelectrons_input{this}; @@ -46,9 +48,8 @@ class FarDetectorTransportationPostML_factory } void Process(int32_t /* run_number */, uint64_t /* event_number */) { - m_algo->process( - {m_prediction_tensor_input(), m_association_input(), m_beamelectrons_input()}, - {m_particle_output().get(), m_links_output().get(), m_association_output().get()}); + m_algo->process({m_prediction_tensor_input(), m_tracks_input(), m_association_input(), m_beamelectrons_input()}, + {m_particle_output().get(), m_links_output().get(), m_association_output().get()}); } }; From b2f7b9e9d0dead594f904368d493619a49417d7a Mon Sep 17 00:00:00 2001 From: garypenman Date: Fri, 7 Aug 2026 15:16:51 +0100 Subject: [PATCH 03/15] minor syntax change --- src/algorithms/fardetectors/FarDetectorTransportationPostML.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc index 0f070d6fd3..a93f7e0056 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc @@ -112,7 +112,8 @@ void FarDetectorTransportationPostML::process( particle.setPDG(m_cfg.pdg_value); if (tracks != nullptr && i < tracks->size()) { - particle.addToTracks((*tracks)[i]); + auto trk = tracks->at(i); + particle.addToTracks(trk); } //Check if both association collections are set and copy the MCParticle association From 6daeab1f2b6f5d407b90c0b369466898c1b5f69a Mon Sep 17 00:00:00 2001 From: garypenman Date: Fri, 7 Aug 2026 15:17:20 +0100 Subject: [PATCH 04/15] update LOWQ2.cc for farforward ML factory track propagation changes --- src/detectors/LOWQ2/LOWQ2.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detectors/LOWQ2/LOWQ2.cc b/src/detectors/LOWQ2/LOWQ2.cc index 4ef8cffa8f..a6e11b81de 100644 --- a/src/detectors/LOWQ2/LOWQ2.cc +++ b/src/detectors/LOWQ2/LOWQ2.cc @@ -210,7 +210,7 @@ void InitPlugin(JApplication* app) { app)); app->Add(new JOmniFactoryGeneratorT( "TaggerTrackerTransportationPostML", - {"TaggerTrackerPredictionTensor", "TaggerTrackerLocalTrackAssociations", "MCBeamElectrons"}, + {"TaggerTrackerPredictionTensor", "TaggerTrackerLocalTracks", "TaggerTrackerLocalTrackAssociations", "MCBeamElectrons"}, {"TaggerTrackerReconstructedParticles", "TaggerTrackerReconstructedParticleLinks", "TaggerTrackerReconstructedParticleAssociations"}, { From d1119141a4f188ecf17e9a40115beccc3253c0dc Mon Sep 17 00:00:00 2001 From: garypenman Date: Fri, 7 Aug 2026 15:20:13 +0100 Subject: [PATCH 05/15] added protections to instances of trk->getTrajectory for LOWQ2 tracks to safeguard seg faults --- src/algorithms/reco/Helix.cc | 1 + src/algorithms/tracking/IterativeVertexFinder.cc | 3 ++- src/algorithms/tracking/SecondaryVertexFinder.cc | 3 ++- src/algorithms/tracking/TracksToParticles.cc | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/algorithms/reco/Helix.cc b/src/algorithms/reco/Helix.cc index 5d4437515e..3914275e94 100644 --- a/src/algorithms/reco/Helix.cc +++ b/src/algorithms/reco/Helix.cc @@ -37,6 +37,7 @@ Helix::Helix(const edm4eic::ReconstructedParticle& p, const double b_field) { const auto& tracks = p.getTracks(); for (const auto& trk : tracks) { const auto& traj = trk.getTrajectory(); + if(!traj.isAvailable()) continue; const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { setParameters(par, b_field); diff --git a/src/algorithms/tracking/IterativeVertexFinder.cc b/src/algorithms/tracking/IterativeVertexFinder.cc index 9a74698a42..f8c7afeb25 100644 --- a/src/algorithms/tracking/IterativeVertexFinder.cc +++ b/src/algorithms/tracking/IterativeVertexFinder.cc @@ -171,7 +171,8 @@ void eicrecon::IterativeVertexFinder::process(const Input& input, const Output& const auto& tracks = part.getTracks(); for (const auto& trk : tracks) { const auto& traj = trk.getTrajectory(); - const auto& trkPars = traj.getTrackParameters(); + if(!traj.isAvailable()) continue; + const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { const double EPSILON = 1.0e-4; // mm if (std::abs((par.getLoc().a / edm4eic::unit::mm) - (loc_a / Acts::UnitConstants::mm)) < diff --git a/src/algorithms/tracking/SecondaryVertexFinder.cc b/src/algorithms/tracking/SecondaryVertexFinder.cc index 08775d7d1a..6d32ea1042 100644 --- a/src/algorithms/tracking/SecondaryVertexFinder.cc +++ b/src/algorithms/tracking/SecondaryVertexFinder.cc @@ -95,7 +95,8 @@ void SecondaryVertexFinder::storeVertices( const auto& tracks = part.getTracks(); for (const auto& trk : tracks) { const auto& traj = trk.getTrajectory(); - const auto& trkPars = traj.getTrackParameters(); + if(!traj.isAvailable()) continue; + const auto& trkPars = traj.getTrackParameters(); for (const auto& trkPar : trkPars) { double EPSILON = std::numeric_limits::epsilon(); if (std::abs((trkPar.getLoc().a / edm4eic::unit::mm) - diff --git a/src/algorithms/tracking/TracksToParticles.cc b/src/algorithms/tracking/TracksToParticles.cc index ed1593b81b..6b22735253 100644 --- a/src/algorithms/tracking/TracksToParticles.cc +++ b/src/algorithms/tracking/TracksToParticles.cc @@ -28,6 +28,7 @@ void TracksToParticles::process(const TracksToParticles::Input& input, for (const auto& track : *tracks) { auto trajectory = track.getTrajectory(); + if(!trajectory.isAvailable()) continue; for (const auto& trk : trajectory.getTrackParameters()) { const auto mom = edm4hep::utils::sphericalToVector(1.0 / std::abs(trk.getQOverP()), trk.getTheta(), trk.getPhi()); From 411b4a950094da539ade76c851d6e99c7b52ea88 Mon Sep 17 00:00:00 2001 From: simonge Date: Fri, 7 Aug 2026 15:32:12 +0100 Subject: [PATCH 06/15] Revert "Added 10ns bunch aware hit partitioning to far detector tracking, for lowq2 bremsstrahlung background studies" This reverts commit b1e09f564ea82db197505be9f19cfe086f2d7939. --- .../fardetectors/FarDetectorLinearTracking.cc | 321 +++--------------- 1 file changed, 51 insertions(+), 270 deletions(-) diff --git a/src/algorithms/fardetectors/FarDetectorLinearTracking.cc b/src/algorithms/fardetectors/FarDetectorLinearTracking.cc index 98df439152..6d59689cf4 100644 --- a/src/algorithms/fardetectors/FarDetectorLinearTracking.cc +++ b/src/algorithms/fardetectors/FarDetectorLinearTracking.cc @@ -85,260 +85,77 @@ void FarDetectorLinearTracking::process(const FarDetectorLinearTracking::Input& if (do_assoc) { link_nav.emplace(*hitLinks); } - + std::vector> convertedHits; std::vector> assocParts; convertedHits.reserve(m_cfg.n_layer); assocParts.reserve(m_cfg.n_layer); - ///////////////////////////////////////////// - //G. Penman August 2026 - //1. Find time offsets - std::vector tmin(m_cfg.n_layer, 1e9); - std::vector tmax(m_cfg.n_layer, -1e9); - int ilayer = 0; - + // Check there aren't too many hits in any layer to handle + // Temporary limit of number of hits per layer before Kalman filtering/GNN implemented + // TODO - Implement more sensible solution for (const auto& layerHits : inputhits) { - for (const auto& cluster : *layerHits) { - double t = cluster.getTime(); - - tmin[ilayer] = std::min(tmin[ilayer], t); - tmax[ilayer] = std::max(tmax[ilayer], t); + if ((*layerHits).size() > m_cfg.layer_hits_max) { + info("Too many hits in layer"); + return; } - - // info("Layer {} nhits {}", ilayer, layerHits->size()); - // info("Layer {} timing range {} -> {}", ilayer, tmin[ilayer], tmax[ilayer]); - ilayer++; - } - - //2. created sorted times of hits in each layer by ~10ns bunch - using BXHits_t = std::unordered_map>>; - BXHits_t bxHits; - std::map bxCount; - ilayer = 0; - - for (const auto& layerHits : inputhits) { - - for (const auto& cluster : *layerHits) { - double t = cluster.getTime(); - - //later using tmin[ilayer], tmax[ilayer] - int bx = static_cast(std::floor(t / 10.0)); - bxCount[bx]++; //total hits in time window - if(bxHits.find(bx) == bxHits.end()) { - bxHits[bx] = std::vector>(m_cfg.n_layer); - } - - bxHits[bx][ilayer].push_back(cluster); + if ((*layerHits).empty()) { + trace("No hits in layer"); + return; } - ilayer++; + ConvertClusters(*layerHits, *link_nav, *assocHits, convertedHits, assocParts); } - - // for (const auto& [bx,n] : bxCount) { - // info("BX {} : {} hits", bx, n); - // } - - // bool validBX = true; - - // for(size_t layer=0; layer layerHitIndex(m_cfg.n_layer, 0); - debug("Processing BX {}", bx); + int layer = 0; - std::vector> convertedHits; - std::vector> assocParts; + // Iterate over all combinations of measurements in the layers without recursion + while (true) { + hitMatrix.col(layer) << convertedHits[layer][layerHitIndex[layer]]; - convertedHits.reserve(m_cfg.n_layer); - assocParts.reserve(m_cfg.n_layer); - - - std::vector bxCollections; - std::vector> bxInputHits; - - bxCollections.reserve(m_cfg.n_layer); - bxInputHits.reserve(m_cfg.n_layer); - - bool validBX = true; - - for (std::size_t layer = 0; layer < m_cfg.n_layer; ++layer) { - - const auto& hits = bxLayers[layer]; - - if (hits.empty()) { - validBX = false; - break; - } - - if (hits.size() > m_cfg.layer_hits_max) { - validBX = false; - break; - } - - bxCollections.emplace_back(); - - auto& tmpCollection = bxCollections.back(); - - tmpCollection.setSubsetCollection(); - - for (const auto& h : hits) { - tmpCollection.push_back(h); - } - - bxInputHits.push_back(gsl::not_null(&tmpCollection)); - //bxInputHits.push_back(tmpCollection); - - ConvertClusters(tmpCollection, - *link_nav, - *assocHits, - convertedHits, - assocParts); - - //info("BX {} layer {} converted {} hits", bx, layer, convertedHits.back().size()); + bool isValid = true; + // Check the last two hits are within a certain angle of the optimum direction + if (layer > 0 && m_cfg.restrict_direction) { + isValid = checkHitPair(hitMatrix.col(layer - 1), hitMatrix.col(layer)); } - - if (!validBX) - continue; - - Eigen::MatrixXd hitMatrix(3, m_cfg.n_layer); - - std::vector layerHitIndex(m_cfg.n_layer, 0); - - int layer = 0; - - while (true) { - - hitMatrix.col(layer) << convertedHits[layer][layerHitIndex[layer]]; - - bool isValid = true; - - if (layer > 0 && m_cfg.restrict_direction) { - isValid = checkHitPair(hitMatrix.col(layer-1), - hitMatrix.col(layer)); + // If valid hit combination, move to the next layer or check the combination + if (isValid) { + if (layer == static_cast(m_cfg.n_layer) - 1) { + // Check the combination, if chi2 limit is passed, add the track to the output + checkHitCombination(&hitMatrix, outputTracks, trackLinks, assocTracks, inputhits, + assocParts, layerHitIndex); + } else { + layer++; + continue; } - - if (isValid) { - - if (layer == - static_cast(m_cfg.n_layer)-1) { - - checkHitCombination(&hitMatrix, - outputTracks, - trackLinks, - assocTracks, - bxInputHits, - assocParts, - layerHitIndex); + } - } else { + // Iterate current layer + layerHitIndex[layer]++; - layer++; - continue; - } + bool doBreak = false; + // Set up next combination to check + while (layerHitIndex[layer] >= convertedHits[layer].size()) { + layerHitIndex[layer] = 0; + if (layer == 0) { + doBreak = true; + break; } - + layer--; + // Iterate previous layer layerHitIndex[layer]++; - - bool doBreak = false; - - while (layerHitIndex[layer] >= - convertedHits[layer].size()) { - - layerHitIndex[layer] = 0; - - if (layer == 0) { - doBreak = true; - break; - } - - layer--; - layerHitIndex[layer]++; - } - - if (doBreak) - break; + } + if (doBreak) { + break; } } } - - // Check there aren't too many hits in any layer to handle - // Temporary limit of number of hits per layer before Kalman filtering/GNN implemented - // TODO - Implement more sensible solution - // for (const auto& layerHits : inputhits) { - // if ((*layerHits).size() > m_cfg.layer_hits_max) { - // info("Too many hits in layer"); - // return; - // } - // if ((*layerHits).empty()) { - // trace("No hits in layer"); - // return; - // } - // ConvertClusters(*layerHits, *link_nav, *assocHits, convertedHits, assocParts); - // } - - // // Create a matrix to store the hit positions -// Eigen::MatrixXd hitMatrix(3, m_cfg.n_layer); - -// // Create vector to store indexes of hits in the track -// std::vector layerHitIndex(m_cfg.n_layer, 0); - -// int layer = 0; - -// // Iterate over all combinations of measurements in the layers without recursion -// while (true) { -// hitMatrix.col(layer) << convertedHits[layer][layerHitIndex[layer]]; - -// bool isValid = true; -// // Check the last two hits are within a certain angle of the optimum direction -// if (layer > 0 && m_cfg.restrict_direction) { -// isValid = checkHitPair(hitMatrix.col(layer - 1), hitMatrix.col(layer)); -// } - -// // If valid hit combination, move to the next layer or check the combination -// if (isValid) { -// if (layer == static_cast(m_cfg.n_layer) - 1) { -// // Check the combination, if chi2 limit is passed, add the track to the output -// checkHitCombination(&hitMatrix, outputTracks, trackLinks, assocTracks, inputhits, -// assocParts, layerHitIndex); -// } else { -// layer++; -// continue; -// } -// } - -// // Iterate current layer -// layerHitIndex[layer]++; - -// bool doBreak = false; -// // Set up next combination to check -// while (layerHitIndex[layer] >= convertedHits[layer].size()) { -// layerHitIndex[layer] = 0; -// if (layer == 0) { -// doBreak = true; -// break; -// } -// layer--; -// // Iterate previous layer -// layerHitIndex[layer]++; -// } -// if (doBreak) { -// break; -// } -// } -// } void FarDetectorLinearTracking::checkHitCombination( Eigen::MatrixXd* hitMatrix, edm4eic::TrackCollection* outputTracks, @@ -374,48 +191,12 @@ void FarDetectorLinearTracking::checkHitCombination( outVec = outVec * -1; } - - // for (std::size_t layer = 0; - // layer < layerHitIndex.size(); - // layer++) { - - // auto t = - // (*inputHits[layer])[layerHitIndex[layer]].getTime(); - - // info("Layer {} time {}", layer, t); - // } - - //get a nonzero time - double sumTime = 0.0; - std::vector times; - - for (std::size_t layer = 0; layer < layerHitIndex.size(); layer++) { - - double t = - (*inputHits[layer])[layerHitIndex[layer]].getTime(); - - times.push_back(t); - sumTime += t; - } - - float time = sumTime / times.size(); - - double variance = 0.0; - - for (const auto& t : times) { - variance += (t - time) * (t - time); - } - - variance /= (times.size() - 1); - - double timeError = std::sqrt(variance); - int32_t type{0}; // Type of track edm4hep::Vector3f position(outPos.x, outPos.y, outPos.z); // Position of the trajectory point [mm] edm4hep::Vector3f momentum(outVec.x, outVec.y, outVec.z); // 3-momentum at the point [GeV] edm4eic::Cov6f positionMomentumCovariance; // Error on the position - //float time{0}; // Time at this point [ns] - //float timeError{0}; // Error on the time at this point + float time{0}; // Time at this point [ns] + float timeError{0}; // Error on the time at this point float charge{-1}; // Charge of the particle int32_t ndf{static_cast(m_cfg.n_layer) - 1}; // Number of degrees of freedom int32_t pdg{11}; // PDG code of the particle @@ -464,8 +245,8 @@ bool FarDetectorLinearTracking::checkHitPair(const Eigen::Vector3d& hit1, } // Convert measurements into global coordinates - void FarDetectorLinearTracking::ConvertClusters( - const edm4eic::Measurement2DCollection& clusters, +void FarDetectorLinearTracking::ConvertClusters( + const edm4eic::Measurement2DCollection& clusters, const podio::LinkNavigator& link_nav, [[maybe_unused]] const edm4eic::MCRecoTrackerHitAssociationCollection& assoc_hits, std::vector>& pointPositions, From fa7c55beede563d5f7fe00e99a70d904d8d44774 Mon Sep 17 00:00:00 2001 From: simonge Date: Fri, 7 Aug 2026 15:38:30 +0100 Subject: [PATCH 07/15] Remove comments and change formatting --- .../FarDetectorTransportationPostML.h | 17 +++++++---------- .../FarDetectorTransportationPostML_factory.h | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.h b/src/algorithms/fardetectors/FarDetectorTransportationPostML.h index e014e4fd6a..8dcb5c4b0c 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.h +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.h @@ -22,16 +22,13 @@ namespace eicrecon { using FarDetectorTransportationPostMLAlgorithm = algorithms::Algorithm< - // algorithms::Input, - // std::optional>, - algorithms::Input, - std::optional>, - algorithms::Output>; + algorithms::Input, + std::optional>, + algorithms::Output>; class FarDetectorTransportationPostML : public FarDetectorTransportationPostMLAlgorithm, diff --git a/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h b/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h index 083f3810da..f1f24f4447 100644 --- a/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h +++ b/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h @@ -49,7 +49,7 @@ class FarDetectorTransportationPostML_factory void Process(int32_t /* run_number */, uint64_t /* event_number */) { m_algo->process({m_prediction_tensor_input(), m_tracks_input(), m_association_input(), m_beamelectrons_input()}, - {m_particle_output().get(), m_links_output().get(), m_association_output().get()}); + {m_particle_output().get(), m_links_output().get(), m_association_output().get()}); } }; From 867df6560c3b2e0b053e715129a758d1dae5a63a Mon Sep 17 00:00:00 2001 From: simonge Date: Fri, 7 Aug 2026 15:39:56 +0100 Subject: [PATCH 08/15] Remove todo comment --- src/algorithms/fardetectors/FarDetectorTransportationPostML.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc index a93f7e0056..3fb7e1783e 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc @@ -131,7 +131,6 @@ void FarDetectorTransportationPostML::process( } } - // TODO: Implement the association of the reconstructed particles with the tracks } } // namespace eicrecon From 1e3af5e6a376cd278fadeaa88abcae6b8b354914 Mon Sep 17 00:00:00 2001 From: simonge Date: Fri, 7 Aug 2026 15:45:34 +0100 Subject: [PATCH 09/15] tab tab tab --- src/algorithms/tracking/IterativeVertexFinder.cc | 4 ++-- src/algorithms/tracking/SecondaryVertexFinder.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/algorithms/tracking/IterativeVertexFinder.cc b/src/algorithms/tracking/IterativeVertexFinder.cc index f8c7afeb25..21f13d4acb 100644 --- a/src/algorithms/tracking/IterativeVertexFinder.cc +++ b/src/algorithms/tracking/IterativeVertexFinder.cc @@ -171,8 +171,8 @@ void eicrecon::IterativeVertexFinder::process(const Input& input, const Output& const auto& tracks = part.getTracks(); for (const auto& trk : tracks) { const auto& traj = trk.getTrajectory(); - if(!traj.isAvailable()) continue; - const auto& trkPars = traj.getTrackParameters(); + if(!traj.isAvailable()) continue; + const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { const double EPSILON = 1.0e-4; // mm if (std::abs((par.getLoc().a / edm4eic::unit::mm) - (loc_a / Acts::UnitConstants::mm)) < diff --git a/src/algorithms/tracking/SecondaryVertexFinder.cc b/src/algorithms/tracking/SecondaryVertexFinder.cc index 6d32ea1042..7692728be9 100644 --- a/src/algorithms/tracking/SecondaryVertexFinder.cc +++ b/src/algorithms/tracking/SecondaryVertexFinder.cc @@ -95,8 +95,8 @@ void SecondaryVertexFinder::storeVertices( const auto& tracks = part.getTracks(); for (const auto& trk : tracks) { const auto& traj = trk.getTrajectory(); - if(!traj.isAvailable()) continue; - const auto& trkPars = traj.getTrackParameters(); + if(!traj.isAvailable()) continue; + const auto& trkPars = traj.getTrackParameters(); for (const auto& trkPar : trkPars) { double EPSILON = std::numeric_limits::epsilon(); if (std::abs((trkPar.getLoc().a / edm4eic::unit::mm) - From 9f447624edf54bb9be4eaf5853a3552f5bb0ef78 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:47:50 +0000 Subject: [PATCH 10/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../fardetectors/FarDetectorTransportationPostML.cc | 5 ++--- .../fardetectors/FarDetectorTransportationPostML.h | 9 ++++----- src/algorithms/reco/Helix.cc | 5 +++-- src/algorithms/tracking/IterativeVertexFinder.cc | 5 +++-- src/algorithms/tracking/SecondaryVertexFinder.cc | 5 +++-- src/algorithms/tracking/TracksToParticles.cc | 3 ++- src/detectors/LOWQ2/LOWQ2.cc | 3 ++- .../FarDetectorTransportationPostML_factory.h | 6 ++++-- 8 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc index 3fb7e1783e..b7dcaddf9f 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc @@ -29,7 +29,7 @@ void FarDetectorTransportationPostML::process( const FarDetectorTransportationPostML::Output& output) const { const auto [prediction_tensors, tracks, track_associations, beamElectrons] = input; - auto [out_particles, out_links, out_associations] = output; + auto [out_particles, out_links, out_associations] = output; //Set beam energy from first MCBeamElectron, using std::call_once if (beamElectrons != nullptr) { @@ -115,7 +115,7 @@ void FarDetectorTransportationPostML::process( auto trk = tracks->at(i); particle.addToTracks(trk); } - + //Check if both association collections are set and copy the MCParticle association if ((track_associations != nullptr) && (track_associations->size() > i)) { // Copy the association from the input to the output @@ -130,7 +130,6 @@ void FarDetectorTransportationPostML::process( out_association.setWeight(association.getWeight()); } } - } } // namespace eicrecon diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.h b/src/algorithms/fardetectors/FarDetectorTransportationPostML.h index 8dcb5c4b0c..5346c34f01 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.h +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.h @@ -22,13 +22,12 @@ namespace eicrecon { using FarDetectorTransportationPostMLAlgorithm = algorithms::Algorithm< - algorithms::Input, - std::optional>, + std::optional>, algorithms::Output>; + edm4eic::MCRecoParticleLinkCollection, + edm4eic::MCRecoParticleAssociationCollection>>; class FarDetectorTransportationPostML : public FarDetectorTransportationPostMLAlgorithm, diff --git a/src/algorithms/reco/Helix.cc b/src/algorithms/reco/Helix.cc index 3914275e94..c8144eee38 100644 --- a/src/algorithms/reco/Helix.cc +++ b/src/algorithms/reco/Helix.cc @@ -36,8 +36,9 @@ Helix::Helix(const edm4hep::Vector3f& p, const edm4hep::Vector3f& o, const doubl Helix::Helix(const edm4eic::ReconstructedParticle& p, const double b_field) { const auto& tracks = p.getTracks(); for (const auto& trk : tracks) { - const auto& traj = trk.getTrajectory(); - if(!traj.isAvailable()) continue; + const auto& traj = trk.getTrajectory(); + if (!traj.isAvailable()) + continue; const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { setParameters(par, b_field); diff --git a/src/algorithms/tracking/IterativeVertexFinder.cc b/src/algorithms/tracking/IterativeVertexFinder.cc index 21f13d4acb..ac28b6495d 100644 --- a/src/algorithms/tracking/IterativeVertexFinder.cc +++ b/src/algorithms/tracking/IterativeVertexFinder.cc @@ -170,8 +170,9 @@ void eicrecon::IterativeVertexFinder::process(const Input& input, const Output& for (const auto& part : *reconParticles) { const auto& tracks = part.getTracks(); for (const auto& trk : tracks) { - const auto& traj = trk.getTrajectory(); - if(!traj.isAvailable()) continue; + const auto& traj = trk.getTrajectory(); + if (!traj.isAvailable()) + continue; const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { const double EPSILON = 1.0e-4; // mm diff --git a/src/algorithms/tracking/SecondaryVertexFinder.cc b/src/algorithms/tracking/SecondaryVertexFinder.cc index 7692728be9..412d16bb0e 100644 --- a/src/algorithms/tracking/SecondaryVertexFinder.cc +++ b/src/algorithms/tracking/SecondaryVertexFinder.cc @@ -94,8 +94,9 @@ void SecondaryVertexFinder::storeVertices( for (const auto& part : reconParticles) { const auto& tracks = part.getTracks(); for (const auto& trk : tracks) { - const auto& traj = trk.getTrajectory(); - if(!traj.isAvailable()) continue; + const auto& traj = trk.getTrajectory(); + if (!traj.isAvailable()) + continue; const auto& trkPars = traj.getTrackParameters(); for (const auto& trkPar : trkPars) { double EPSILON = std::numeric_limits::epsilon(); diff --git a/src/algorithms/tracking/TracksToParticles.cc b/src/algorithms/tracking/TracksToParticles.cc index 6b22735253..00c493e2a7 100644 --- a/src/algorithms/tracking/TracksToParticles.cc +++ b/src/algorithms/tracking/TracksToParticles.cc @@ -28,7 +28,8 @@ void TracksToParticles::process(const TracksToParticles::Input& input, for (const auto& track : *tracks) { auto trajectory = track.getTrajectory(); - if(!trajectory.isAvailable()) continue; + if (!trajectory.isAvailable()) + continue; for (const auto& trk : trajectory.getTrackParameters()) { const auto mom = edm4hep::utils::sphericalToVector(1.0 / std::abs(trk.getQOverP()), trk.getTheta(), trk.getPhi()); diff --git a/src/detectors/LOWQ2/LOWQ2.cc b/src/detectors/LOWQ2/LOWQ2.cc index a6e11b81de..928bfa6655 100644 --- a/src/detectors/LOWQ2/LOWQ2.cc +++ b/src/detectors/LOWQ2/LOWQ2.cc @@ -210,7 +210,8 @@ void InitPlugin(JApplication* app) { app)); app->Add(new JOmniFactoryGeneratorT( "TaggerTrackerTransportationPostML", - {"TaggerTrackerPredictionTensor", "TaggerTrackerLocalTracks", "TaggerTrackerLocalTrackAssociations", "MCBeamElectrons"}, + {"TaggerTrackerPredictionTensor", "TaggerTrackerLocalTracks", + "TaggerTrackerLocalTrackAssociations", "MCBeamElectrons"}, {"TaggerTrackerReconstructedParticles", "TaggerTrackerReconstructedParticleLinks", "TaggerTrackerReconstructedParticleAssociations"}, { diff --git a/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h b/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h index f1f24f4447..209db52434 100644 --- a/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h +++ b/src/factories/fardetectors/FarDetectorTransportationPostML_factory.h @@ -48,8 +48,10 @@ class FarDetectorTransportationPostML_factory } void Process(int32_t /* run_number */, uint64_t /* event_number */) { - m_algo->process({m_prediction_tensor_input(), m_tracks_input(), m_association_input(), m_beamelectrons_input()}, - {m_particle_output().get(), m_links_output().get(), m_association_output().get()}); + m_algo->process( + {m_prediction_tensor_input(), m_tracks_input(), m_association_input(), + m_beamelectrons_input()}, + {m_particle_output().get(), m_links_output().get(), m_association_output().get()}); } }; From 61e970953c50d3fba3ca5ddf225d83549c4e1044 Mon Sep 17 00:00:00 2001 From: Simon Gardner Date: Fri, 7 Aug 2026 16:00:12 +0100 Subject: [PATCH 11/15] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../fardetectors/FarDetectorTransportationPostML.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc index b7dcaddf9f..2e7daf9f40 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc @@ -111,10 +111,15 @@ void FarDetectorTransportationPostML::process( particle.setMass(m_mass); particle.setPDG(m_cfg.pdg_value); - if (tracks != nullptr && i < tracks->size()) { - auto trk = tracks->at(i); - particle.addToTracks(trk); + if (tracks == nullptr) { + error("No tracks collection provided; cannot set ReconstructedParticle-Track relation"); + throw std::runtime_error("No tracks collection provided"); } + if (i >= tracks->size()) { + error("Prediction tensor row {} has no corresponding track (tracks size={})", i, tracks->size()); + throw std::runtime_error("Prediction tensor/track size mismatch"); + } + particle.addToTracks(tracks->at(i)); //Check if both association collections are set and copy the MCParticle association if ((track_associations != nullptr) && (track_associations->size() > i)) { From b0a74931e7136e5e7f85a37cbbdcf04e5f2a8aa6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 15:00:26 +0000 Subject: [PATCH 12/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/algorithms/fardetectors/FarDetectorTransportationPostML.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc index 2e7daf9f40..a8fc2779ad 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc @@ -116,7 +116,8 @@ void FarDetectorTransportationPostML::process( throw std::runtime_error("No tracks collection provided"); } if (i >= tracks->size()) { - error("Prediction tensor row {} has no corresponding track (tracks size={})", i, tracks->size()); + error("Prediction tensor row {} has no corresponding track (tracks size={})", i, + tracks->size()); throw std::runtime_error("Prediction tensor/track size mismatch"); } particle.addToTracks(tracks->at(i)); From d57ba38e4c12e3e53bbcad457312f279da6b2abb Mon Sep 17 00:00:00 2001 From: Simon Gardner Date: Fri, 7 Aug 2026 17:13:10 +0100 Subject: [PATCH 13/15] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/algorithms/reco/Helix.cc | 3 ++- src/algorithms/tracking/IterativeVertexFinder.cc | 3 ++- src/algorithms/tracking/SecondaryVertexFinder.cc | 3 ++- src/algorithms/tracking/TracksToParticles.cc | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/algorithms/reco/Helix.cc b/src/algorithms/reco/Helix.cc index c8144eee38..eec3acabee 100644 --- a/src/algorithms/reco/Helix.cc +++ b/src/algorithms/reco/Helix.cc @@ -37,8 +37,9 @@ Helix::Helix(const edm4eic::ReconstructedParticle& p, const double b_field) { const auto& tracks = p.getTracks(); for (const auto& trk : tracks) { const auto& traj = trk.getTrajectory(); - if (!traj.isAvailable()) + if (!traj.isAvailable()) { continue; +} const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { setParameters(par, b_field); diff --git a/src/algorithms/tracking/IterativeVertexFinder.cc b/src/algorithms/tracking/IterativeVertexFinder.cc index ac28b6495d..3cdccb3e08 100644 --- a/src/algorithms/tracking/IterativeVertexFinder.cc +++ b/src/algorithms/tracking/IterativeVertexFinder.cc @@ -171,8 +171,9 @@ void eicrecon::IterativeVertexFinder::process(const Input& input, const Output& const auto& tracks = part.getTracks(); for (const auto& trk : tracks) { const auto& traj = trk.getTrajectory(); - if (!traj.isAvailable()) + if (!traj.isAvailable()) { continue; +} const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { const double EPSILON = 1.0e-4; // mm diff --git a/src/algorithms/tracking/SecondaryVertexFinder.cc b/src/algorithms/tracking/SecondaryVertexFinder.cc index 412d16bb0e..9b2a1eb620 100644 --- a/src/algorithms/tracking/SecondaryVertexFinder.cc +++ b/src/algorithms/tracking/SecondaryVertexFinder.cc @@ -95,8 +95,9 @@ void SecondaryVertexFinder::storeVertices( const auto& tracks = part.getTracks(); for (const auto& trk : tracks) { const auto& traj = trk.getTrajectory(); - if (!traj.isAvailable()) + if (!traj.isAvailable()) { continue; +} const auto& trkPars = traj.getTrackParameters(); for (const auto& trkPar : trkPars) { double EPSILON = std::numeric_limits::epsilon(); diff --git a/src/algorithms/tracking/TracksToParticles.cc b/src/algorithms/tracking/TracksToParticles.cc index 00c493e2a7..7dea15d169 100644 --- a/src/algorithms/tracking/TracksToParticles.cc +++ b/src/algorithms/tracking/TracksToParticles.cc @@ -28,8 +28,9 @@ void TracksToParticles::process(const TracksToParticles::Input& input, for (const auto& track : *tracks) { auto trajectory = track.getTrajectory(); - if (!trajectory.isAvailable()) + if (!trajectory.isAvailable()) { continue; +} for (const auto& trk : trajectory.getTrackParameters()) { const auto mom = edm4hep::utils::sphericalToVector(1.0 / std::abs(trk.getQOverP()), trk.getTheta(), trk.getPhi()); From 073ce92e862dc9ed47d2145cd19493ad59ba36c4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 16:13:23 +0000 Subject: [PATCH 14/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/algorithms/reco/Helix.cc | 2 +- src/algorithms/tracking/IterativeVertexFinder.cc | 2 +- src/algorithms/tracking/SecondaryVertexFinder.cc | 2 +- src/algorithms/tracking/TracksToParticles.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/algorithms/reco/Helix.cc b/src/algorithms/reco/Helix.cc index eec3acabee..47ab20d713 100644 --- a/src/algorithms/reco/Helix.cc +++ b/src/algorithms/reco/Helix.cc @@ -39,7 +39,7 @@ Helix::Helix(const edm4eic::ReconstructedParticle& p, const double b_field) { const auto& traj = trk.getTrajectory(); if (!traj.isAvailable()) { continue; -} + } const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { setParameters(par, b_field); diff --git a/src/algorithms/tracking/IterativeVertexFinder.cc b/src/algorithms/tracking/IterativeVertexFinder.cc index 3cdccb3e08..2da70e4421 100644 --- a/src/algorithms/tracking/IterativeVertexFinder.cc +++ b/src/algorithms/tracking/IterativeVertexFinder.cc @@ -173,7 +173,7 @@ void eicrecon::IterativeVertexFinder::process(const Input& input, const Output& const auto& traj = trk.getTrajectory(); if (!traj.isAvailable()) { continue; -} + } const auto& trkPars = traj.getTrackParameters(); for (const auto& par : trkPars) { const double EPSILON = 1.0e-4; // mm diff --git a/src/algorithms/tracking/SecondaryVertexFinder.cc b/src/algorithms/tracking/SecondaryVertexFinder.cc index 9b2a1eb620..61ab8a593f 100644 --- a/src/algorithms/tracking/SecondaryVertexFinder.cc +++ b/src/algorithms/tracking/SecondaryVertexFinder.cc @@ -97,7 +97,7 @@ void SecondaryVertexFinder::storeVertices( const auto& traj = trk.getTrajectory(); if (!traj.isAvailable()) { continue; -} + } const auto& trkPars = traj.getTrackParameters(); for (const auto& trkPar : trkPars) { double EPSILON = std::numeric_limits::epsilon(); diff --git a/src/algorithms/tracking/TracksToParticles.cc b/src/algorithms/tracking/TracksToParticles.cc index 7dea15d169..cabd2258fa 100644 --- a/src/algorithms/tracking/TracksToParticles.cc +++ b/src/algorithms/tracking/TracksToParticles.cc @@ -30,7 +30,7 @@ void TracksToParticles::process(const TracksToParticles::Input& input, auto trajectory = track.getTrajectory(); if (!trajectory.isAvailable()) { continue; -} + } for (const auto& trk : trajectory.getTrackParameters()) { const auto mom = edm4hep::utils::sphericalToVector(1.0 / std::abs(trk.getQOverP()), trk.getTheta(), trk.getPhi()); From af5e56c130429683ebbbda3de970836ad8684216 Mon Sep 17 00:00:00 2001 From: Simon Gardner Date: Thu, 20 Aug 2026 16:56:37 +0100 Subject: [PATCH 15/15] Apply suggestions from code review Co-authored-by: Dmitry Kalinkin --- .../fardetectors/FarDetectorTransportationPostML.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc index a8fc2779ad..a442a9832a 100644 --- a/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc +++ b/src/algorithms/fardetectors/FarDetectorTransportationPostML.cc @@ -111,10 +111,6 @@ void FarDetectorTransportationPostML::process( particle.setMass(m_mass); particle.setPDG(m_cfg.pdg_value); - if (tracks == nullptr) { - error("No tracks collection provided; cannot set ReconstructedParticle-Track relation"); - throw std::runtime_error("No tracks collection provided"); - } if (i >= tracks->size()) { error("Prediction tensor row {} has no corresponding track (tracks size={})", i, tracks->size());