Uh oh!
There was an error while loading. Please reload this page.
Handle CAF making when Pandora runs after the NuGraph2 filter - #616
Handle CAF making when Pandora runs after the NuGraph2 filter#616rtriozzi wants to merge 13 commits into
Conversation
cerati
left a comment
There was a problem hiding this comment.
Thanks, overall it looks great -- especially removing the need for the hit mapping makes things much simpler.
The two things I would suggest to change are:
- Avoid erasing elements from vectors. I think it should be much easier to simply add a check that the element is non-null in the Fill*NuGraph method. Or is there another reason for erasing the elements with null nugraph score?
- There is no need to get the NuGraph slices from the event if then we just use
slices(whenUsePandoraAfterNuGraph=true)
rtriozzi
commented
Jan 12, 2026
I have addressed Giuseppe’s comments (with which I agree). I also added more code to fill some new NuGraph2 CAF variables we developed. I opened the corresponding sbnanaobj PR #183. |
kjplows
commented
Jan 15, 2026
Thanks! @cerati do the changes look good to you? |
Uh oh!
There was an error while loading. Please reload this page.
cerati
commented
Jan 15, 2026
Looks great! I only left a single comment above |
cerati
left a comment
There was a problem hiding this comment.
Thanks for addressing my comments!
kjplows
commented
Feb 11, 2026
@PetrilloAtWork sorry to add more to your plate, just bumping this 🙂 -- could you take a look please? Thanks! |
kjplows
commented
Mar 12, 2026
@PetrilloAtWork , @acampani -- could you please take a look at this? Thanks. |
3017213 to
6aa4a4cCompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
sparshitadey
commented
May 30, 2026
Hi! The fix is to compute it directly from collection sizes - see commit 363b5120 on my branch. Gives mean ~0.81, varying event to event, consistent with Stage 1 filter retention (and the printouts). Happy to open a separate PR if preferred! |
PetrilloAtWork
left a comment
There was a problem hiding this comment.
My usual burst of comments.
There is at least one which must be addressed, about uninitialised variables.
| nuGraphSlices = slices; | ||
| } else { | ||
| nuGraphSlices = evt.getProduct<std::vector<art::Ptr<recob::Slice>>>(fParams.NuGraphSlicesLabel().label() + pandora_tag_suffix); | ||
| } |
There was a problem hiding this comment.
I don't understand this logic.
If fParams.UsePandoraAfterNuGraph() is true, nugraphSlices will be the same as slices (so that case could easily live outside the loop); in the other case, nuGraphSlices is overwritten with the content of each tag until the last one, hence holding only slices from the data product with the last tag.
I suspect what was meant to add slices, something like
if (!fParams.UsePandoraAfterNuGraph()) {
autoconst& moreSlices = evt.getProduct<std::vector<art::Ptr<recob::Slice>>>(fParams.NuGraphSlicesLabel().label() + pandora_tag_suffix);
nuGraphSlices.insert(nuGraphSlices.end(), moreSlices.begin(), moreSlices.end());
}| } | ||
| fmPFPartHits.push_back(pfphits); | ||
| std::vector<art::Ptr<recob::Hit>> pfphits; | ||
| std::vector<art::Ptr<recob::Cluster>> pfclusters = fmPFPClusters.at(ipf); |
There was a problem hiding this comment.
Avoid copies:
| std::vector<art::Ptr<recob::Cluster>> pfclusters = fmPFPClusters.at(ipf); | |
| std::vector<art::Ptr<recob::Cluster>> const& pfclusters = fmPFPClusters.at(ipf); |
| std::vector<art::Ptr<recob::Cluster>> pfclusters = fmPFPClusters.at(ipf); | ||
| art::FindManyP<recob::Hit> fmCluHits = FindManyPStrict<recob::Hit>(pfclusters, evt, fParams.PFParticleLabel() + slice_tag_suff); | ||
| for (size_t icl=0; icl<fmCluHits.size();icl++) { | ||
| for (auto hit : fmCluHits.at(icl)) { |
There was a problem hiding this comment.
Avoid copies:
| for (auto hit : fmCluHits.at(icl)) { | |
| for (autoconst& hit : fmCluHits.at(icl)) { |
| art::FindOneP<anab::FeatureVector<1>> findOneFilter(slcHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); | ||
| art::FindOneP<anab::FeatureVector<5>> findOneSemantic(slcHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); |
There was a problem hiding this comment.
It's hard to see whether the labels are the same. Define the tag first:
| art::FindOneP<anab::FeatureVector<1>> findOneFilter(slcHits, evt, fParams.NuGraphFilterLabel().label() + slice_tag_suff + ":" + fParams.NuGraphFilterLabel().instance()); | |
| art::FindOneP<anab::FeatureVector<5>> findOneSemantic(slcHits, evt, fParams.NuGraphSemanticLabel().label() + slice_tag_suff + ":" + fParams.NuGraphSemanticLabel().instance()); | |
| art::InputTag const filtTag{ | |
| fParams.NuGraphFilterLabel().label() + slice_tag_suff, | |
| fParams.NuGraphFilterLabel().instance() | |
| }; | |
| art::FindOneP<anab::FeatureVector<1>> findOneFilter(slcHits, filtTag); | |
| art::FindOneP<anab::FeatureVector<5>> findOneSemantic(slcHits, filtTag); |
| float vtx_wire[3]; | ||
| float vtx_tick[3]; | ||
| if (vertex != NULL) { |
There was a problem hiding this comment.
What kind of garbage is going to end into the tree if the vertex is null? The arrays need to be initialised somehow.
This is a request, as we don't want uninitialised values to end into the trees as it compromises tree comparisons.
Also, NULL is C, and we need to keep a façade here.
| if (vertex != NULL) { | |
| if (vertex) { |
There was a problem hiding this comment.
going through the comments right now! about this: every slice has to have a vertex, sort of by definition in Pandora (e.g., even if the reconstruction is sure that the slice is a cosmic, the vertex will just be the highest-y hit)
I think there are also protections for failed vertexing (which should be very rare: we really just need a hit to define a vertex...) within Pandora, so that we always get something when we grab the vertex in the CAF maker...
anyway, I agree it's bad practice from the CAF maker stand point (+ the NULL check was therefore strange), I'll fix this! thanks!
| std::max_element(semVec.begin(), semVec.end()) | ||
| ); | ||
| // `MIP` hits |
There was a problem hiding this comment.
This sequence may be better served with a switch block.
| slice.ng_plane[plane].mip_hits = nMIPHits; | ||
| slice.ng_plane[plane].hip_hits = nHIPHits; | ||
| slice.ng_plane[plane].shr_hits = nShrHits; | ||
| slice.ng_plane[plane].mhl_hits = nMhlHits; | ||
| slice.ng_plane[plane].dif_hits = nDifHits; | ||
| slice.ng_plane[plane].ng_vtx_hip_hits = nVtxHIPHits; | ||
| slice.ng_plane[plane].unclustered_shr_hits = nUnclusteredShrHits; |
There was a problem hiding this comment.
| slice.ng_plane[plane].mip_hits = nMIPHits; | |
| slice.ng_plane[plane].hip_hits = nHIPHits; | |
| slice.ng_plane[plane].shr_hits = nShrHits; | |
| slice.ng_plane[plane].mhl_hits = nMhlHits; | |
| slice.ng_plane[plane].dif_hits = nDifHits; | |
| slice.ng_plane[plane].ng_vtx_hip_hits = nVtxHIPHits; | |
| slice.ng_plane[plane].unclustered_shr_hits = nUnclusteredShrHits; | |
| auto& hitInfo = slice.ng_plane[plane]; | |
| hitInfo.mip_hits = nMIPHits; | |
| hitInfo.hip_hits = nHIPHits; | |
| hitInfo.shr_hits = nShrHits; | |
| hitInfo.mhl_hits = nMhlHits; | |
| hitInfo.dif_hits = nDifHits; | |
| hitInfo.ng_vtx_hip_hits = nVtxHIPHits; | |
| hitInfo.unclustered_shr_hits = nUnclusteredShrHits; |
| size_t sem_label = std::distance(ng2semscores.begin(), std::max_element(ng2semscores.begin(), ng2semscores.end()));//arg_max(ng2semscores); | ||
| ng2sempfpcounts[sem_label]++; | ||
| } | ||
| if (ngFilterResult.at(pos).isNull()) continue; |
| std::vector<float> ng2semscores; | ||
| for (size_t i=0;i<scores->size();i++) ng2semscores.push_back(scores->at(i)); |
There was a problem hiding this comment.
| std::vector<float> ng2semscores; | |
| for (size_t i=0;i<scores->size();i++) ng2semscores.push_back(scores->at(i)); | |
| std::vector<float> ng2semscores{ scores.begin(), scores.end() }; |
| const std::vector<art::Ptr<anab::FeatureVector<1>>> &ngFilterResult, | ||
| const std::vector<art::Ptr<anab::FeatureVector<5>>> &ngSemanticResult, | ||
| const std::vector<art::Ptr<recob::Hit>> &pfpHits, | ||
| const float filter_cut, |
This PR adds a mode governed by the
UsePandoraAfterNuGraphFHiCL flag to handle NuGraph2 variables in the CAF maker, when using a second-pass Pandora after filtering noise with NuGraph2, based on work by summer intern Leonardo Lena.This PR also provides code to fill new NuGraph2 slice-level variables in CAF files.
Relevant information about the NuGraph2 chain is provided in icaruscode PR #868.
Associated PRs
Review
Tagging for review @acampani and @PetrilloAtWork as reconstruction and infrastructure experts. Thanks a lot!
Description
Please provide a detailed description of the changes this pull request introduces. If available, also link to a docdb link where the issue/change have been presented on/discussed.