From 351d3797a2f94c76a96ec88ca0797aacfce8fefa Mon Sep 17 00:00:00 2001 From: Leonardo Lena Date: Mon, 6 Oct 2025 15:24:42 -0500 Subject: [PATCH 1/9] Updated CAFMaker to work with NuGraph inference on multiple slices. --- sbncode/CAFMaker/CAFMakerParams.h | 8 ++-- sbncode/CAFMaker/CAFMaker_module.cc | 71 +++++++++++++++++++---------- sbncode/CAFMaker/FillReco.cxx | 44 +++++++----------- sbncode/CAFMaker/FillReco.h | 4 +- 4 files changed, 69 insertions(+), 58 deletions(-) diff --git a/sbncode/CAFMaker/CAFMakerParams.h b/sbncode/CAFMaker/CAFMakerParams.h index 253f0d4c2..ce76fa4f5 100644 --- a/sbncode/CAFMaker/CAFMakerParams.h +++ b/sbncode/CAFMaker/CAFMakerParams.h @@ -350,10 +350,10 @@ namespace caf "" //Empty by default, configured in icaruscode cafmaker_defs }; - Atom NuGraphSliceHitLabel { - Name("NuGraphSliceHitLabel"), - Comment("Label of NuGraph slice hit map."), - "" //Empty by default, please set to e.g. art::InputTag("nuslhits") + Atom NCCSlicesLabel { + Name("NCCSlicesLabel"), + Comment("Label of NotClearCosmic slices."), + "" //Empty by default, please set to e.g. art::InputTag("NCCSlices") }; Atom NuGraphFilterLabel { diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index 48da84e8f..03ab5c886 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -1717,6 +1717,7 @@ void CAFMaker::produce(art::Event& evt) noexcept { // collect the TPC slices std::vector> slices; + std::vector> nccSlices; std::vector slice_tag_suffixes; std::vector slice_tag_indices; for (unsigned i_tag = 0; i_tag < pandora_tag_suffixes.size(); i_tag++) { @@ -1726,6 +1727,8 @@ void CAFMaker::produce(art::Event& evt) noexcept { GetByLabelStrict(evt, fParams.PFParticleLabel() + pandora_tag_suffix, thisSlices); if (thisSlices.isValid()) { art::fill_ptr_vector(slices, thisSlices); + const std::vector>& tempNCCSlices = evt.getProduct>>(fParams.NCCSlicesLabel().label() + pandora_tag_suffix); + nccSlices.insert(nccSlices.end(), tempNCCSlices.begin(), tempNCCSlices.end()); for (unsigned i = 0; i < thisSlices->size(); i++) { slice_tag_suffixes.push_back(pandora_tag_suffix); slice_tag_indices.push_back(i_tag); @@ -1733,17 +1736,6 @@ void CAFMaker::produce(art::Event& evt) noexcept { } } - // nu graph - std::vector< art::Handle> > ng2_slice_hit_map_handle(pandora_tag_suffixes.size()); - std::vector< art::Handle>> > ng2_filter_handle(pandora_tag_suffixes.size()); - std::vector< art::Handle>> > ng2_semantic_handle(pandora_tag_suffixes.size()); - for (unsigned i_tag = 0; i_tag < pandora_tag_suffixes.size(); i_tag++) { - const std::string &pandora_tag_suffix = pandora_tag_suffixes[i_tag]; - GetByLabelIfExists(evt, fParams.NuGraphSliceHitLabel().encode() + pandora_tag_suffix, ng2_slice_hit_map_handle[i_tag]); - GetByLabelIfExists(evt, fParams.NuGraphFilterLabel().label() + pandora_tag_suffix + ":" + fParams.NuGraphFilterLabel().instance(), ng2_filter_handle[i_tag]); - GetByLabelIfExists(evt, fParams.NuGraphSemanticLabel().label() + pandora_tag_suffix + ":" + fParams.NuGraphSemanticLabel().instance(), ng2_semantic_handle[i_tag]); - } - // The Standard Record // Branch entry definition -- contains list of slices, CRT information, and truth information StandardRecord rec; @@ -1799,17 +1791,30 @@ void CAFMaker::produce(art::Event& evt) noexcept { fmatch_assn_map.emplace(std::make_pair(fname_opdet, sfm_assn)); } } + + if (std::find(nccSlices.begin(), nccSlices.end(), slice) != nccSlices.end()) { + // this check is required: if FindOneP does not find an associated item instead of returning nullptr it throws an exception. + // I believe a change of this behaviour could be handy. + std::vector>> ng2_filter_vec; + std::vector>> ng2_semantic_vec; + art::FindOneP> findOneFilter(slcHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); + art::FindOneP> findOneSemantic(slcHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); + // iteration is the only way to get something out of a FindOne or FindMany... + if (findOneFilter.isValid()) { + for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { + ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); + } + } - std::vector>> ng2_filter_vec; - std::vector>> ng2_semantic_vec; - if (ng2_filter_handle[producer].isValid()) { - art::fill_ptr_vector(ng2_filter_vec,ng2_filter_handle[producer]); - } - if (ng2_semantic_handle[producer].isValid()) { - art::fill_ptr_vector(ng2_semantic_vec,ng2_semantic_handle[producer]); - } - if (ng2_slice_hit_map_handle[producer].isValid()) { - FillSliceNuGraph(slcHits,*ng2_slice_hit_map_handle[producer],ng2_filter_vec,ng2_semantic_vec,recslc); + if (findOneSemantic.isValid()) { + for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { + ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); + } + } + + if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { + FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, recslc); + } } art::FindManyP fmOpT0 = @@ -2189,8 +2194,28 @@ void CAFMaker::produce(art::Event& evt) noexcept { FillCNNScores(thisParticle, cnnScores, pfp); } - if (ng2_slice_hit_map_handle[producer].isValid()) { - FillPFPNuGraph(*ng2_slice_hit_map_handle[producer], ng2_filter_vec, ng2_semantic_vec, fmPFPartHits.at(iPart), pfp); + if (std::find(nccSlices.begin(), nccSlices.end(), slice) != nccSlices.end()) { + const std::vector>& PFPHits = fmPFPartHits.at(iPart); + art::FindOneP> findOneFilter(PFPHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); + art::FindOneP> findOneSemantic(PFPHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); + std::vector>> ng2_filter_vec; + std::vector>> ng2_semantic_vec; + + if (findOneFilter.isValid()) { + for (size_t hitIdx = 0; hitIdx < PFPHits.size(); ++hitIdx) { + ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); + } + } + + if (findOneSemantic.isValid()) { + for (size_t hitIdx = 0; hitIdx < PFPHits.size(); ++hitIdx) { + ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); + } + } + + if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { + FillPFPNuGraph(PFPHits, ng2_filter_vec, ng2_semantic_vec, pfp); + } } if (!thisTrack.empty()) { // it has a track! diff --git a/sbncode/CAFMaker/FillReco.cxx b/sbncode/CAFMaker/FillReco.cxx index d81cb5890..9f14b9d5f 100644 --- a/sbncode/CAFMaker/FillReco.cxx +++ b/sbncode/CAFMaker/FillReco.cxx @@ -581,16 +581,16 @@ namespace caf } void FillSliceNuGraph(const std::vector> &inputHits, - const std::vector &sliceHitsMap, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, caf::SRSlice &slice) { //need to double check that the slice processed by NuGraph is the same under consideration - //std::cout << "sizes=" << inputHits.size() << " " << sliceHitsMap.size() << " " << ngFilterResult.size() << " " << ngSemanticResult.size() << std::endl; + // std::cout << "sizes=" << inputHits.size() << " " << " " << ngFilterResult.size() << " " << ngSemanticResult.size() << std::endl; unsigned int nHits = inputHits.size(); - if (nHits==0 || nHits!=sliceHitsMap.size() || inputHits[0].key()!=sliceHitsMap[0]) return;//not the same slice! + // implementing this same-slice check with the updated architecture would be a major headache and I believe is not required given how inputHits is retrieved. + // if (nHits==0 || nHits!=sliceHitsMap.size() || inputHits[0].key()!=sliceHitsMap[0]) return;//not the same slice! unsigned int npass = 0; for ( unsigned int i = 0; i < nHits; i++ ) { @@ -1024,38 +1024,26 @@ namespace caf srpfp.cnnscore.nclusters = cnnscore->nClusters; } - void FillPFPNuGraph(const std::vector &sliceHitsMap, + void FillPFPNuGraph(const std::vector> &pfpHits, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, - const std::vector> &pfpHits, caf::SRPFP& srpfp, bool allowEmpty) { - - // the nugraph elements are ordered the same as the sliceHitsMap - std::vector mappedhits; - for (auto& hit : pfpHits) { - auto it = std::find(sliceHitsMap.begin(), sliceHitsMap.end(), hit.key()); - if (it != sliceHitsMap.end()) { - size_t index = std::distance(sliceHitsMap.begin(), it); - mappedhits.push_back(index); - } - } - - if (mappedhits.size()>0) { + if (pfpHits.size()>0) { std::vector ng2sempfpcounts(5,0); size_t ng2bkgpfpcount = 0; - for (size_t pos : mappedhits) { - auto const& bkgscore = ngFilterResult.at(pos); - if (bkgscore->at(0) ng2semscores; - for (size_t i=0;isize();i++) ng2semscores.push_back(scores->at(i)); - size_t sem_label = std::distance(ng2semscores.begin(), std::max_element(ng2semscores.begin(), ng2semscores.end()));//arg_max(ng2semscores); - ng2sempfpcounts[sem_label]++; - } + for (size_t pos = 0; pos < pfpHits.size(); pos++) { + auto const& bkgscore = ngFilterResult.at(pos); + if (bkgscore->at(0) ng2semscores; + for (size_t i=0;isize();i++) ng2semscores.push_back(scores->at(i)); + size_t sem_label = std::distance(ng2semscores.begin(), std::max_element(ng2semscores.begin(), ng2semscores.end()));//arg_max(ng2semscores); + ng2sempfpcounts[sem_label]++; + } } srpfp.ngscore.sem_cat = SRNuGraphScore::NuGraphCategory(std::distance(ng2sempfpcounts.begin(), std::max_element(ng2sempfpcounts.begin(), ng2sempfpcounts.end())));//arg_max(ng2sempfpcounts); size_t nonBkgHits = (pfpHits.size() > ng2bkgpfpcount ? pfpHits.size()-ng2bkgpfpcount : 0); diff --git a/sbncode/CAFMaker/FillReco.h b/sbncode/CAFMaker/FillReco.h index 6e8ecf292..204dbaaf8 100644 --- a/sbncode/CAFMaker/FillReco.h +++ b/sbncode/CAFMaker/FillReco.h @@ -117,7 +117,6 @@ namespace caf * Hits with filter value (`ngFilterResult`) lower than `ng_filter_cut` are counted as background. */ void FillSliceNuGraph(const std::vector> &inputHits, - const std::vector &sliceHitsMap, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, caf::SRSlice &slice); @@ -158,10 +157,9 @@ namespace caf * * Hits with filter value (`ngFilterResult`) lower than `ng_filter_cut` are counted as background. */ - void FillPFPNuGraph(const std::vector &sliceHitsMap, + void FillPFPNuGraph(const std::vector> &pfpHits, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, - const std::vector> &pfpHits, caf::SRPFP& srpfp, bool allowEmpty= false); From 762e6ed3ee21f7761538a9c3091ed72fc965d38e Mon Sep 17 00:00:00 2001 From: Leonardo Lena Date: Tue, 14 Oct 2025 14:21:05 -0500 Subject: [PATCH 2/9] Fixed memory leak issues. --- sbncode/CAFMaker/CAFMakerParams.h | 6 ++--- sbncode/CAFMaker/CAFMaker_module.cc | 34 ++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/sbncode/CAFMaker/CAFMakerParams.h b/sbncode/CAFMaker/CAFMakerParams.h index ce76fa4f5..6d4ffd8db 100644 --- a/sbncode/CAFMaker/CAFMakerParams.h +++ b/sbncode/CAFMaker/CAFMakerParams.h @@ -350,9 +350,9 @@ namespace caf "" //Empty by default, configured in icaruscode cafmaker_defs }; - Atom NCCSlicesLabel { - Name("NCCSlicesLabel"), - Comment("Label of NotClearCosmic slices."), + Atom NuGraphSlicesLabel { + Name("NuGraphSlicesLabel"), + Comment("Label of slices that have NuGraph inference."), "" //Empty by default, please set to e.g. art::InputTag("NCCSlices") }; diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index 03ab5c886..31fd631dc 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -1717,7 +1717,7 @@ void CAFMaker::produce(art::Event& evt) noexcept { // collect the TPC slices std::vector> slices; - std::vector> nccSlices; + std::vector> nuGraphSlices; std::vector slice_tag_suffixes; std::vector slice_tag_indices; for (unsigned i_tag = 0; i_tag < pandora_tag_suffixes.size(); i_tag++) { @@ -1727,8 +1727,8 @@ void CAFMaker::produce(art::Event& evt) noexcept { GetByLabelStrict(evt, fParams.PFParticleLabel() + pandora_tag_suffix, thisSlices); if (thisSlices.isValid()) { art::fill_ptr_vector(slices, thisSlices); - const std::vector>& tempNCCSlices = evt.getProduct>>(fParams.NCCSlicesLabel().label() + pandora_tag_suffix); - nccSlices.insert(nccSlices.end(), tempNCCSlices.begin(), tempNCCSlices.end()); + const std::vector>& tempNuGraphSlices = evt.getProduct>>(fParams.NuGraphSlicesLabel().label() + pandora_tag_suffix); + nuGraphSlices.insert(nuGraphSlices.end(), tempNuGraphSlices.begin(), tempNuGraphSlices.end()); for (unsigned i = 0; i < thisSlices->size(); i++) { slice_tag_suffixes.push_back(pandora_tag_suffix); slice_tag_indices.push_back(i_tag); @@ -1792,9 +1792,7 @@ void CAFMaker::produce(art::Event& evt) noexcept { } } - if (std::find(nccSlices.begin(), nccSlices.end(), slice) != nccSlices.end()) { - // this check is required: if FindOneP does not find an associated item instead of returning nullptr it throws an exception. - // I believe a change of this behaviour could be handy. + if (std::find(nuGraphSlices.begin(), nuGraphSlices.end(), slice) != nuGraphSlices.end()) { std::vector>> ng2_filter_vec; std::vector>> ng2_semantic_vec; art::FindOneP> findOneFilter(slcHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); @@ -1802,12 +1800,22 @@ void CAFMaker::produce(art::Event& evt) noexcept { // iteration is the only way to get something out of a FindOne or FindMany... if (findOneFilter.isValid()) { for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { + if (findOneFilter.at(hitIdx).isNull()) { + slcHits.erase(slcHits.begin()+hitIdx); + hitIdx--; + continue; + } ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); } } if (findOneSemantic.isValid()) { for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { + if (findOneSemantic.at(hitIdx).isNull()) { + slcHits.erase(slcHits.begin()+hitIdx); + hitIdx--; + continue; + } ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); } } @@ -2194,8 +2202,8 @@ void CAFMaker::produce(art::Event& evt) noexcept { FillCNNScores(thisParticle, cnnScores, pfp); } - if (std::find(nccSlices.begin(), nccSlices.end(), slice) != nccSlices.end()) { - const std::vector>& PFPHits = fmPFPartHits.at(iPart); + if (std::find(nuGraphSlices.begin(), nuGraphSlices.end(), slice) != nuGraphSlices.end()) { + std::vector>& PFPHits = fmPFPartHits.at(iPart); art::FindOneP> findOneFilter(PFPHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); art::FindOneP> findOneSemantic(PFPHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); std::vector>> ng2_filter_vec; @@ -2203,12 +2211,22 @@ void CAFMaker::produce(art::Event& evt) noexcept { if (findOneFilter.isValid()) { for (size_t hitIdx = 0; hitIdx < PFPHits.size(); ++hitIdx) { + if (findOneFilter.at(hitIdx).isNull()) { + PFPHits.erase(PFPHits.begin() + hitIdx); + hitIdx--; + continue; + } ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); } } if (findOneSemantic.isValid()) { for (size_t hitIdx = 0; hitIdx < PFPHits.size(); ++hitIdx) { + if (findOneSemantic.at(hitIdx).isNull()) { + PFPHits.erase(PFPHits.begin() + hitIdx); + hitIdx--; + continue; + } ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); } } From 78a0667afdad4df68c8459d2dbea36d84b3798ed Mon Sep 17 00:00:00 2001 From: Leonardo Lena Date: Thu, 23 Oct 2025 11:06:18 -0500 Subject: [PATCH 3/9] FEATURE: implemented CAFMaker compatibility with PandoraAfterNuGraph. --- sbncode/CAFMaker/CAFMakerParams.h | 6 ++++++ sbncode/CAFMaker/CAFMaker_module.cc | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/sbncode/CAFMaker/CAFMakerParams.h b/sbncode/CAFMaker/CAFMakerParams.h index 6d4ffd8db..1ee49e694 100644 --- a/sbncode/CAFMaker/CAFMakerParams.h +++ b/sbncode/CAFMaker/CAFMakerParams.h @@ -368,6 +368,12 @@ namespace caf "" //Empty by default, please set to e.g. art::InputTag("NuGraph","semantic") }; + Atom UsePandoraAfterNuGraph { + Name("UsePandoraAfterNuGraph"), + Comment("Whether to use the second pass Pandora outputs for NuGraph reco."), + false + }; + Atom OpFlashLabel { Name("OpFlashLabel"), Comment("Label of PMT flash."), diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index 31fd631dc..32d97b694 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -1727,8 +1727,10 @@ void CAFMaker::produce(art::Event& evt) noexcept { GetByLabelStrict(evt, fParams.PFParticleLabel() + pandora_tag_suffix, thisSlices); if (thisSlices.isValid()) { art::fill_ptr_vector(slices, thisSlices); - const std::vector>& tempNuGraphSlices = evt.getProduct>>(fParams.NuGraphSlicesLabel().label() + pandora_tag_suffix); - nuGraphSlices.insert(nuGraphSlices.end(), tempNuGraphSlices.begin(), tempNuGraphSlices.end()); + nuGraphSlices = evt.getProduct>>(fParams.NuGraphSlicesLabel().label() + pandora_tag_suffix); + if (fParams.UsePandoraAfterNuGraph()) { + nuGraphSlices = slices; + } for (unsigned i = 0; i < thisSlices->size(); i++) { slice_tag_suffixes.push_back(pandora_tag_suffix); slice_tag_indices.push_back(i_tag); From d5d32a08da9f53d075088c5409157efb0929c414 Mon Sep 17 00:00:00 2001 From: Riccardo Triozzi Date: Wed, 24 Dec 2025 11:54:51 -0600 Subject: [PATCH 4/9] fill nugraph hip tagger --- sbncode/CAFMaker/CAFMaker_module.cc | 134 +++++++++++++++++++--------- sbncode/CAFMaker/FillReco.cxx | 41 +++++++-- sbncode/CAFMaker/FillReco.h | 5 +- 3 files changed, 132 insertions(+), 48 deletions(-) diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index 32d97b694..3417f6e46 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -1794,38 +1794,38 @@ void CAFMaker::produce(art::Event& evt) noexcept { } } - if (std::find(nuGraphSlices.begin(), nuGraphSlices.end(), slice) != nuGraphSlices.end()) { - std::vector>> ng2_filter_vec; - std::vector>> ng2_semantic_vec; - art::FindOneP> findOneFilter(slcHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); - art::FindOneP> findOneSemantic(slcHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); - // iteration is the only way to get something out of a FindOne or FindMany... - if (findOneFilter.isValid()) { - for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { - if (findOneFilter.at(hitIdx).isNull()) { - slcHits.erase(slcHits.begin()+hitIdx); - hitIdx--; - continue; - } - ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); - } - } - - if (findOneSemantic.isValid()) { - for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { - if (findOneSemantic.at(hitIdx).isNull()) { - slcHits.erase(slcHits.begin()+hitIdx); - hitIdx--; - continue; - } - ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); - } - } - - if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { - FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, recslc); - } - } + // if (std::find(nuGraphSlices.begin(), nuGraphSlices.end(), slice) != nuGraphSlices.end()) { + // std::vector>> ng2_filter_vec; + // std::vector>> ng2_semantic_vec; + // art::FindOneP> findOneFilter(slcHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); + // art::FindOneP> findOneSemantic(slcHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); + + // if (findOneFilter.isValid()) { + // for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { + // if (findOneFilter.at(hitIdx).isNull()) { + // slcHits.erase(slcHits.begin()+hitIdx); + // hitIdx--; + // continue; + // } + // ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); + // } + // } + + // if (findOneSemantic.isValid()) { + // for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { + // if (findOneSemantic.at(hitIdx).isNull()) { + // slcHits.erase(slcHits.begin()+hitIdx); + // hitIdx--; + // continue; + // } + // ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); + // } + // } + + // if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { + // FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, recslc); + // } + // } art::FindManyP fmOpT0 = FindManyPStrict(sliceList, evt, fParams.OpT0Label() + slice_tag_suff); @@ -1880,15 +1880,15 @@ void CAFMaker::produce(art::Event& evt) noexcept { // make Ptr's to clusters for cluster -> other object associations if (fmPFPClusters.isValid()) { for (size_t ipf=0; ipf> pfphits; - std::vector> pfclusters = fmPFPClusters.at(ipf); - art::FindManyP fmCluHits = FindManyPStrict(pfclusters, evt, fParams.PFParticleLabel() + slice_tag_suff); - for (size_t icl=0; icl> pfphits; + std::vector> pfclusters = fmPFPClusters.at(ipf); + art::FindManyP fmCluHits = FindManyPStrict(pfclusters, evt, fParams.PFParticleLabel() + slice_tag_suff); + for (size_t icl=0; icl fmatch_map; std::map>::iterator fmatch_it; for(fmatch_it = fmatch_assn_map.begin();fmatch_it != fmatch_assn_map.end();fmatch_it++) { @@ -2075,12 +2075,62 @@ void CAFMaker::produce(art::Event& evt) noexcept { } } } + // get the primary vertex const recob::Vertex *vertex = (iPart == fmPFPart.size() || !fmVertex.at(iPart).size()) ? NULL : fmVertex.at(iPart).at(0).get(); //####################################################### // Add slice info. //####################################################### + if (std::find(nuGraphSlices.begin(), nuGraphSlices.end(), slice) != nuGraphSlices.end()) { + std::vector>> ng2_filter_vec; + std::vector>> ng2_semantic_vec; + art::FindOneP> findOneFilter(slcHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); + art::FindOneP> findOneSemantic(slcHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); + + // filter + if (findOneFilter.isValid()) { + for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { + if (findOneFilter.at(hitIdx).isNull()) { + slcHits.erase(slcHits.begin()+hitIdx); + hitIdx--; + continue; + } + ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); + } + } + + // semantic tagging + if (findOneSemantic.isValid()) { + for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { + if (findOneSemantic.at(hitIdx).isNull()) { + slcHits.erase(slcHits.begin()+hitIdx); + hitIdx--; + continue; + } + ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); + } + } + + // vertex projection onto the three wire planes + float vtx_wire[3]; + float vtx_tick[3]; + + if (vertex != NULL) { + auto const& tpcID = geom->FindTPCAtPosition(vertex->position()); + for (geo::PlaneID const& p : wireReadout.Iterate()) { + auto const& planeID = geo::PlaneID{tpcID, p.Plane}; + const geo::PlaneGeo& planeGeo = wireReadout.Plane(planeID); + vtx_wire[p.Plane] = planeGeo.WireCoordinate(vertex->position()); ///< wire projection + vtx_tick[p.Plane] = dprop.ConvertXToTicks(vertex->position().X(), planeID); ///< drift projection + } + } + + if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { + FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, vtx_wire, vtx_tick, recslc); + } + } + FillSliceVars(*slice, primary, producer, recslc); FillSliceMetadata(primary_meta, recslc); FillSliceFlashMatch(fmatch_map["fmatch"], recslc.fmatch); diff --git a/sbncode/CAFMaker/FillReco.cxx b/sbncode/CAFMaker/FillReco.cxx index 9f14b9d5f..5a71ee60a 100644 --- a/sbncode/CAFMaker/FillReco.cxx +++ b/sbncode/CAFMaker/FillReco.cxx @@ -583,20 +583,51 @@ namespace caf void FillSliceNuGraph(const std::vector> &inputHits, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, + const float vtx_wire[3], + const float vtx_tick[3], caf::SRSlice &slice) { - //need to double check that the slice processed by NuGraph is the same under consideration - // std::cout << "sizes=" << inputHits.size() << " " << " " << ngFilterResult.size() << " " << ngSemanticResult.size() << std::endl; + // nugraph filter fraction unsigned int nHits = inputHits.size(); - // implementing this same-slice check with the updated architecture would be a major headache and I believe is not required given how inputHits is retrieved. - // if (nHits==0 || nHits!=sliceHitsMap.size() || inputHits[0].key()!=sliceHitsMap[0]) return;//not the same slice! - unsigned int npass = 0; + + std::cout << "number of hits: " << nHits << std::endl; + for ( unsigned int i = 0; i < nHits; i++ ) { if (ngFilterResult.at(i)->at(0)>=ng_filter_cut) npass++; } slice.ng_filt_pass_frac = float(npass)/nHits; + + // nugraph HIP vertex tagging + for (unsigned int plane = 0; plane < 3; ++plane) { + + unsigned int nHIPHits = 0; + + for ( unsigned int i = 0; i < nHits; i++ ) { + const recob::Hit& hit = *inputHits.at(i); + if (hit.WireID().Plane != plane) continue; + + auto const& sem = *ngSemanticResult.at(i); + std::vector semVec; + for (size_t k = 0; k < sem.size(); ++k) semVec.push_back(sem.at(k)); + auto highestScoreIdx = std::distance( + semVec.begin(), + std::max_element(semVec.begin(), semVec.end()) + ); + if (highestScoreIdx != 1) continue; // look for HIP hits + + float dwire = std::abs(float(hit.WireID().Wire) - vtx_wire[plane]); + if (dwire > 10) continue; + + float dtick = std::abs(hit.PeakTime() - vtx_tick[plane]); + if (dtick > 50) continue; + + nHIPHits += 1; + } + + slice.ng_plane[plane].ng_vtx_hip_hits = nHIPHits; + } } //...................................................................... diff --git a/sbncode/CAFMaker/FillReco.h b/sbncode/CAFMaker/FillReco.h index 204dbaaf8..68f41d15d 100644 --- a/sbncode/CAFMaker/FillReco.h +++ b/sbncode/CAFMaker/FillReco.h @@ -109,9 +109,10 @@ namespace caf /** * @brief Fills the results from NuGraph at slice level * @param inputHits (pointers to) the hits associated to the slice - * @param sliceHitsMap maps position of hits in collection input to NuGraph (slice only) to the one input to Pandora (all gaus hits) * @param ngFilterResult NuGraph filter result, for each hit * @param ngSemanticResult NuGraph semnatic result, for each hit (MIP track, HIP, shower, Michel electron, diffuse activity) + * @param vtx_wire vertex coordinates projected onto wires, per plane + * @param vtx_tick vertex coordinates projected onto ticks, per plane * @param[out] slice the destination slice object * * Hits with filter value (`ngFilterResult`) lower than `ng_filter_cut` are counted as background. @@ -119,6 +120,8 @@ namespace caf void FillSliceNuGraph(const std::vector> &inputHits, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, + const float vtx_wire[3], + const float vtx_tick[3], caf::SRSlice &slice); bool SelectSlice(const caf::SRSlice &slice, bool cut_clear_cosmic); From cf283cbaaed94443f74a49c918112eafa5bbc59a Mon Sep 17 00:00:00 2001 From: Riccardo Triozzi Date: Tue, 6 Jan 2026 08:06:51 -0600 Subject: [PATCH 5/9] change to int to allow for negative default --- sbncode/CAFMaker/FillReco.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sbncode/CAFMaker/FillReco.cxx b/sbncode/CAFMaker/FillReco.cxx index 5a71ee60a..ddc8fff0a 100644 --- a/sbncode/CAFMaker/FillReco.cxx +++ b/sbncode/CAFMaker/FillReco.cxx @@ -592,8 +592,6 @@ namespace caf unsigned int nHits = inputHits.size(); unsigned int npass = 0; - std::cout << "number of hits: " << nHits << std::endl; - for ( unsigned int i = 0; i < nHits; i++ ) { if (ngFilterResult.at(i)->at(0)>=ng_filter_cut) npass++; } @@ -602,7 +600,7 @@ namespace caf // nugraph HIP vertex tagging for (unsigned int plane = 0; plane < 3; ++plane) { - unsigned int nHIPHits = 0; + int nHIPHits = 0; for ( unsigned int i = 0; i < nHits; i++ ) { const recob::Hit& hit = *inputHits.at(i); From 98a4654f3641b16608669daea3af8970567ee858 Mon Sep 17 00:00:00 2001 From: Riccardo Triozzi Date: Wed, 7 Jan 2026 05:47:27 -0600 Subject: [PATCH 6/9] more shower vars --- sbncode/CAFMaker/CAFMaker_module.cc | 2 +- sbncode/CAFMaker/FillReco.cxx | 39 +++++++++++++++++++++++------ sbncode/CAFMaker/FillReco.h | 4 ++- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index 3417f6e46..fd202cdcb 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -2127,7 +2127,7 @@ void CAFMaker::produce(art::Event& evt) noexcept { } if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { - FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, vtx_wire, vtx_tick, recslc); + FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, fmPFPartHits, vtx_wire, vtx_tick, recslc); } } diff --git a/sbncode/CAFMaker/FillReco.cxx b/sbncode/CAFMaker/FillReco.cxx index ddc8fff0a..aa9332d11 100644 --- a/sbncode/CAFMaker/FillReco.cxx +++ b/sbncode/CAFMaker/FillReco.cxx @@ -583,12 +583,13 @@ namespace caf void FillSliceNuGraph(const std::vector> &inputHits, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, + const std::vector>> &fmPFPartHits, const float vtx_wire[3], const float vtx_tick[3], caf::SRSlice &slice) { - // nugraph filter fraction + // NuGraph2 filter fraction unsigned int nHits = inputHits.size(); unsigned int npass = 0; @@ -597,10 +598,20 @@ namespace caf } slice.ng_filt_pass_frac = float(npass)/nHits; - // nugraph HIP vertex tagging + // look-up between hits and PFPs + std::set> pfpHitSet; + for (const auto& pfpHits : fmPFPartHits) { + for (const auto& hit : pfpHits) { + if (hit) pfpHitSet.insert(hit); + } + } + + // NuGraph2 plane-by-plane slice variables for (unsigned int plane = 0; plane < 3; ++plane) { - int nHIPHits = 0; + int nHIPHits = 0; ///< HIP tagging at interaction vertex + int nShrHits = 0; ///< shower hits in the slice + int nUnclusteredShrHits = 0; ///< shower hits in the slice not belonging to a PFP for ( unsigned int i = 0; i < nHits; i++ ) { const recob::Hit& hit = *inputHits.at(i); @@ -613,18 +624,30 @@ namespace caf semVec.begin(), std::max_element(semVec.begin(), semVec.end()) ); - if (highestScoreIdx != 1) continue; // look for HIP hits + // HIP tagging float dwire = std::abs(float(hit.WireID().Wire) - vtx_wire[plane]); - if (dwire > 10) continue; - float dtick = std::abs(hit.PeakTime() - vtx_tick[plane]); - if (dtick > 50) continue; + if ((highestScoreIdx == 1) && (dwire <= 10) && (dtick <= 50)) + nHIPHits += 1; - nHIPHits += 1; + // shower hits + if (highestScoreIdx == 2) { + + // all shower hits + nShrHits += 1; + + // unclustered shower hits + art::Ptr hitPtr = inputHits.at(i); + if (pfpHitSet.find(hitPtr) == pfpHitSet.end()) { + nUnclusteredShrHits += 1; + } + } } slice.ng_plane[plane].ng_vtx_hip_hits = nHIPHits; + slice.ng_plane[plane].shr_hits = nShrHits; + slice.ng_plane[plane].unclustered_shr_hits = nUnclusteredShrHits; } } diff --git a/sbncode/CAFMaker/FillReco.h b/sbncode/CAFMaker/FillReco.h index 68f41d15d..0fdc1cc2f 100644 --- a/sbncode/CAFMaker/FillReco.h +++ b/sbncode/CAFMaker/FillReco.h @@ -110,7 +110,8 @@ namespace caf * @brief Fills the results from NuGraph at slice level * @param inputHits (pointers to) the hits associated to the slice * @param ngFilterResult NuGraph filter result, for each hit - * @param ngSemanticResult NuGraph semnatic result, for each hit (MIP track, HIP, shower, Michel electron, diffuse activity) + * @param ngSemanticResult NuGraph semantic result, for each hit (MIP track, HIP, shower, Michel electron, diffuse activity) + * @param fmPFPartHits vector of pointers-to-hits lists, for each PFP * @param vtx_wire vertex coordinates projected onto wires, per plane * @param vtx_tick vertex coordinates projected onto ticks, per plane * @param[out] slice the destination slice object @@ -120,6 +121,7 @@ namespace caf void FillSliceNuGraph(const std::vector> &inputHits, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, + const std::vector>> &fmPFPartHits, const float vtx_wire[3], const float vtx_tick[3], caf::SRSlice &slice); From 612ae6a8f5d142318d89c6e657bbda9c1fcb3e9d Mon Sep 17 00:00:00 2001 From: Riccardo Triozzi Date: Mon, 12 Jan 2026 04:30:14 -0600 Subject: [PATCH 7/9] move HIP tagging params to fcl --- sbncode/CAFMaker/CAFMakerParams.h | 12 ++++++++++++ sbncode/CAFMaker/CAFMaker_module.cc | 4 +++- sbncode/CAFMaker/FillReco.cxx | 4 +++- sbncode/CAFMaker/FillReco.h | 16 ++++++++++------ 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/sbncode/CAFMaker/CAFMakerParams.h b/sbncode/CAFMaker/CAFMakerParams.h index 1ee49e694..d02686600 100644 --- a/sbncode/CAFMaker/CAFMakerParams.h +++ b/sbncode/CAFMaker/CAFMakerParams.h @@ -373,6 +373,18 @@ namespace caf Comment("Whether to use the second pass Pandora outputs for NuGraph reco."), false }; + + Atom NuGraphHIPTagWireDist { + Name("NuGraphHIPTagWireDist"), + Comment("TPC wire distance from the vertex used to count NuGraph2–tagged HIP hits."), + 10 + }; + + Atom NuGraphHIPTagTickDist { + Name("NuGraphHIPTagTickDist"), + Comment("TPC tick distance from the vertex used to count NuGraph-2–tagged HIP hits."), + 50 + }; Atom OpFlashLabel { Name("OpFlashLabel"), diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index fd202cdcb..948c2917d 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -2127,7 +2127,9 @@ void CAFMaker::produce(art::Event& evt) noexcept { } if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { - FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, fmPFPartHits, vtx_wire, vtx_tick, recslc); + FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, fmPFPartHits, + vtx_wire, vtx_tick, fParams.NuGraphHIPTagWireDist(), fParams.NuGraphHIPTagTickDist(), + recslc); } } diff --git a/sbncode/CAFMaker/FillReco.cxx b/sbncode/CAFMaker/FillReco.cxx index aa9332d11..218fb255f 100644 --- a/sbncode/CAFMaker/FillReco.cxx +++ b/sbncode/CAFMaker/FillReco.cxx @@ -586,6 +586,8 @@ namespace caf const std::vector>> &fmPFPartHits, const float vtx_wire[3], const float vtx_tick[3], + const float vtx_wire_dist, + const float vtx_tick_dist, caf::SRSlice &slice) { @@ -628,7 +630,7 @@ namespace caf // HIP tagging float dwire = std::abs(float(hit.WireID().Wire) - vtx_wire[plane]); float dtick = std::abs(hit.PeakTime() - vtx_tick[plane]); - if ((highestScoreIdx == 1) && (dwire <= 10) && (dtick <= 50)) + if ((highestScoreIdx == 1) && (dwire <= vtx_wire_dist) && (dtick <= vtx_tick_dist)) nHIPHits += 1; // shower hits diff --git a/sbncode/CAFMaker/FillReco.h b/sbncode/CAFMaker/FillReco.h index 0fdc1cc2f..feef3e930 100644 --- a/sbncode/CAFMaker/FillReco.h +++ b/sbncode/CAFMaker/FillReco.h @@ -114,17 +114,21 @@ namespace caf * @param fmPFPartHits vector of pointers-to-hits lists, for each PFP * @param vtx_wire vertex coordinates projected onto wires, per plane * @param vtx_tick vertex coordinates projected onto ticks, per plane + * @param vtx_wire_dist TPC wire distance from the vertex used to count NuGraph2–tagged HIP hits + * @param vtx_tick_dist TPC tick distance from the vertex used to count NuGraph2–tagged HIP hits * @param[out] slice the destination slice object * * Hits with filter value (`ngFilterResult`) lower than `ng_filter_cut` are counted as background. */ void FillSliceNuGraph(const std::vector> &inputHits, - const std::vector>> &ngFilterResult, - const std::vector>> &ngSemanticResult, - const std::vector>> &fmPFPartHits, - const float vtx_wire[3], - const float vtx_tick[3], - caf::SRSlice &slice); + const std::vector>> &ngFilterResult, + const std::vector>> &ngSemanticResult, + const std::vector>> &fmPFPartHits, + const float vtx_wire[3], + const float vtx_tick[3], + const float vtx_wire_dist, + const float vtx_tick_dist, + caf::SRSlice &slice); bool SelectSlice(const caf::SRSlice &slice, bool cut_clear_cosmic); From 55812bc99feacc9b5c874627f9783f5a2b4e9a91 Mon Sep 17 00:00:00 2001 From: Riccardo Triozzi Date: Mon, 12 Jan 2026 05:31:44 -0600 Subject: [PATCH 8/9] move more params to fcl, address Giuseppe's comments --- sbncode/CAFMaker/CAFMakerParams.h | 6 +++++ sbncode/CAFMaker/CAFMaker_module.cc | 35 ++++++++++------------------- sbncode/CAFMaker/FillReco.cxx | 24 +++++++++++++------- sbncode/CAFMaker/FillReco.h | 4 ++++ 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/sbncode/CAFMaker/CAFMakerParams.h b/sbncode/CAFMaker/CAFMakerParams.h index d02686600..93ffab1c2 100644 --- a/sbncode/CAFMaker/CAFMakerParams.h +++ b/sbncode/CAFMaker/CAFMakerParams.h @@ -374,6 +374,12 @@ namespace caf false }; + Atom NuGraphFilterCut { + Name("NuGraphFilterCut"), + Comment("Cut on the NuGraph2 filter score to define hit as signal or noise."), + 0.5 + }; + Atom NuGraphHIPTagWireDist { Name("NuGraphHIPTagWireDist"), Comment("TPC wire distance from the vertex used to count NuGraph2–tagged HIP hits."), diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index 948c2917d..1166ec6b1 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -1722,14 +1722,17 @@ void CAFMaker::produce(art::Event& evt) noexcept { std::vector slice_tag_indices; for (unsigned i_tag = 0; i_tag < pandora_tag_suffixes.size(); i_tag++) { const std::string &pandora_tag_suffix = pandora_tag_suffixes[i_tag]; + // Get a handle on the slices art::Handle> thisSlices; GetByLabelStrict(evt, fParams.PFParticleLabel() + pandora_tag_suffix, thisSlices); + if (thisSlices.isValid()) { art::fill_ptr_vector(slices, thisSlices); - nuGraphSlices = evt.getProduct>>(fParams.NuGraphSlicesLabel().label() + pandora_tag_suffix); if (fParams.UsePandoraAfterNuGraph()) { nuGraphSlices = slices; + } else { + nuGraphSlices = evt.getProduct>>(fParams.NuGraphSlicesLabel().label() + pandora_tag_suffix); } for (unsigned i = 0; i < thisSlices->size(); i++) { slice_tag_suffixes.push_back(pandora_tag_suffix); @@ -2090,24 +2093,16 @@ void CAFMaker::produce(art::Event& evt) noexcept { // filter if (findOneFilter.isValid()) { + ng2_filter_vec.reserve(slcHits.size()); for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { - if (findOneFilter.at(hitIdx).isNull()) { - slcHits.erase(slcHits.begin()+hitIdx); - hitIdx--; - continue; - } ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); } } // semantic tagging if (findOneSemantic.isValid()) { + ng2_semantic_vec.reserve(slcHits.size()); for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { - if (findOneSemantic.at(hitIdx).isNull()) { - slcHits.erase(slcHits.begin()+hitIdx); - hitIdx--; - continue; - } ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); } } @@ -2129,7 +2124,7 @@ void CAFMaker::produce(art::Event& evt) noexcept { if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, fmPFPartHits, vtx_wire, vtx_tick, fParams.NuGraphHIPTagWireDist(), fParams.NuGraphHIPTagTickDist(), - recslc); + fParams.NuGraphFilterCut(), recslc); } } @@ -2263,30 +2258,24 @@ void CAFMaker::produce(art::Event& evt) noexcept { std::vector>> ng2_filter_vec; std::vector>> ng2_semantic_vec; + // filter if (findOneFilter.isValid()) { + ng2_filter_vec.reserve(PFPHits.size()); for (size_t hitIdx = 0; hitIdx < PFPHits.size(); ++hitIdx) { - if (findOneFilter.at(hitIdx).isNull()) { - PFPHits.erase(PFPHits.begin() + hitIdx); - hitIdx--; - continue; - } ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); } } + // semantic tagging if (findOneSemantic.isValid()) { + ng2_semantic_vec.reserve(PFPHits.size()); for (size_t hitIdx = 0; hitIdx < PFPHits.size(); ++hitIdx) { - if (findOneSemantic.at(hitIdx).isNull()) { - PFPHits.erase(PFPHits.begin() + hitIdx); - hitIdx--; - continue; - } ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); } } if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { - FillPFPNuGraph(PFPHits, ng2_filter_vec, ng2_semantic_vec, pfp); + FillPFPNuGraph(PFPHits, ng2_filter_vec, ng2_semantic_vec, fParams.NuGraphFilterCut(), pfp); } } diff --git a/sbncode/CAFMaker/FillReco.cxx b/sbncode/CAFMaker/FillReco.cxx index 218fb255f..f8021abfd 100644 --- a/sbncode/CAFMaker/FillReco.cxx +++ b/sbncode/CAFMaker/FillReco.cxx @@ -12,8 +12,6 @@ namespace caf { - const float ng_filter_cut = 0.5; - //...................................................................... bool SelectSlice(const caf::SRSlice &slice, bool cut_clear_cosmic) { return (!slice.is_clear_cosmic || !cut_clear_cosmic) // No clear cosmics @@ -588,6 +586,7 @@ namespace caf const float vtx_tick[3], const float vtx_wire_dist, const float vtx_tick_dist, + const float filter_cut, caf::SRSlice &slice) { @@ -596,9 +595,10 @@ namespace caf unsigned int npass = 0; for ( unsigned int i = 0; i < nHits; i++ ) { - if (ngFilterResult.at(i)->at(0)>=ng_filter_cut) npass++; + if (ngFilterResult.at(i).isNull()) continue; + if (ngFilterResult.at(i)->at(0) >= filter_cut) npass++; } - slice.ng_filt_pass_frac = float(npass)/nHits; + slice.ng_filt_pass_frac = (nHits > 0) ? float(npass) / nHits : 0.f; // look-up between hits and PFPs std::set> pfpHitSet; @@ -619,6 +619,8 @@ namespace caf const recob::Hit& hit = *inputHits.at(i); if (hit.WireID().Plane != plane) continue; + if (ngSemanticResult.at(i).isNull()) continue; + auto const& sem = *ngSemanticResult.at(i); std::vector semVec; for (size_t k = 0; k < sem.size(); ++k) semVec.push_back(sem.at(k)); @@ -1081,17 +1083,23 @@ namespace caf void FillPFPNuGraph(const std::vector> &pfpHits, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, + const float filter_cut, caf::SRPFP& srpfp, bool allowEmpty) { - if (pfpHits.size()>0) { - std::vector ng2sempfpcounts(5,0); + if (pfpHits.size() > 0) { + std::vector ng2sempfpcounts(5, 0); size_t ng2bkgpfpcount = 0; + for (size_t pos = 0; pos < pfpHits.size(); pos++) { + + if (ngFilterResult.at(pos).isNull()) continue; + auto const& bkgscore = ngFilterResult.at(pos); - if (bkgscore->at(0)at(0) < filter_cut) { ng2bkgpfpcount++; } else { + if (ngSemanticResult.at(pos).isNull()) continue; auto const& scores = ngSemanticResult.at(pos); std::vector ng2semscores; for (size_t i=0;isize();i++) ng2semscores.push_back(scores->at(i)); @@ -1099,6 +1107,7 @@ namespace caf ng2sempfpcounts[sem_label]++; } } + srpfp.ngscore.sem_cat = SRNuGraphScore::NuGraphCategory(std::distance(ng2sempfpcounts.begin(), std::max_element(ng2sempfpcounts.begin(), ng2sempfpcounts.end())));//arg_max(ng2sempfpcounts); size_t nonBkgHits = (pfpHits.size() > ng2bkgpfpcount ? pfpHits.size()-ng2bkgpfpcount : 0); srpfp.ngscore.mip_frac = (nonBkgHits>0 ? float(ng2sempfpcounts[0])/nonBkgHits : -1.); @@ -1116,7 +1125,6 @@ namespace caf srpfp.ngscore.dif_frac = -1.; srpfp.ngscore.bkg_frac = -1.; } - } void FillHitVars(const recob::Hit& hit, diff --git a/sbncode/CAFMaker/FillReco.h b/sbncode/CAFMaker/FillReco.h index feef3e930..211f791fd 100644 --- a/sbncode/CAFMaker/FillReco.h +++ b/sbncode/CAFMaker/FillReco.h @@ -116,6 +116,7 @@ namespace caf * @param vtx_tick vertex coordinates projected onto ticks, per plane * @param vtx_wire_dist TPC wire distance from the vertex used to count NuGraph2–tagged HIP hits * @param vtx_tick_dist TPC tick distance from the vertex used to count NuGraph2–tagged HIP hits + * @param filter_cut cut on the NuGraph2 filter score to define hit as signal or noise * @param[out] slice the destination slice object * * Hits with filter value (`ngFilterResult`) lower than `ng_filter_cut` are counted as background. @@ -128,6 +129,7 @@ namespace caf const float vtx_tick[3], const float vtx_wire_dist, const float vtx_tick_dist, + const float filter_cut, caf::SRSlice &slice); bool SelectSlice(const caf::SRSlice &slice, bool cut_clear_cosmic); @@ -161,6 +163,7 @@ namespace caf * @param sliceHitsMap maps position of hits in collection input to NuGraph (slice only) to the one input to Pandora (all gaus hits) * @param ngFilterResult NuGraph filter result, for each hit * @param ngSemanticResult NuGraph semnatic result, for each hit (MIP track, HIP, shower, Michel electron, diffuse activity) + * @param filter_cut cut on the NuGraph2 filter score to define hit as signal or noise * @param pfpHits Vector of hits associated to the PFParticle * @param[out] srpfp the destination PFParticle object * @@ -169,6 +172,7 @@ namespace caf void FillPFPNuGraph(const std::vector> &pfpHits, const std::vector>> &ngFilterResult, const std::vector>> &ngSemanticResult, + const float filter_cut, caf::SRPFP& srpfp, bool allowEmpty= false); From d483222c84dc8be7a6531200107a83f86b36bb0b Mon Sep 17 00:00:00 2001 From: Riccardo Triozzi Date: Mon, 12 Jan 2026 05:37:24 -0600 Subject: [PATCH 9/9] removed spare comments --- sbncode/CAFMaker/CAFMaker_module.cc | 33 ----------------------------- 1 file changed, 33 deletions(-) diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index 1166ec6b1..a231ae719 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -1797,39 +1797,6 @@ void CAFMaker::produce(art::Event& evt) noexcept { } } - // if (std::find(nuGraphSlices.begin(), nuGraphSlices.end(), slice) != nuGraphSlices.end()) { - // std::vector>> ng2_filter_vec; - // std::vector>> ng2_semantic_vec; - // art::FindOneP> findOneFilter(slcHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); - // art::FindOneP> findOneSemantic(slcHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); - - // if (findOneFilter.isValid()) { - // for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { - // if (findOneFilter.at(hitIdx).isNull()) { - // slcHits.erase(slcHits.begin()+hitIdx); - // hitIdx--; - // continue; - // } - // ng2_filter_vec.emplace_back(findOneFilter.at(hitIdx)); - // } - // } - - // if (findOneSemantic.isValid()) { - // for (size_t hitIdx = 0; hitIdx < slcHits.size(); ++hitIdx) { - // if (findOneSemantic.at(hitIdx).isNull()) { - // slcHits.erase(slcHits.begin()+hitIdx); - // hitIdx--; - // continue; - // } - // ng2_semantic_vec.emplace_back(findOneSemantic.at(hitIdx)); - // } - // } - - // if (ng2_filter_vec.size() > 0 || ng2_semantic_vec.size() > 0) { - // FillSliceNuGraph(slcHits, ng2_filter_vec, ng2_semantic_vec, recslc); - // } - // } - art::FindManyP fmOpT0 = FindManyPStrict(sliceList, evt, fParams.OpT0Label() + slice_tag_suff); std::vector> slcOpT0;