Skip to content

ClusterFinder: optional merging of clusters that are close in time - #401

Open
dhavvval wants to merge 3 commits into
ANNIEsoft:Applicationfrom
dhavvval:feature/ClusterFinderTimeMerge-application
Open

dhavvval wants to merge 3 commits into
ANNIEsoft:Applicationfrom
dhavvval:feature/ClusterFinderTimeMerge-application

Conversation

@dhavvval

Copy link
Copy Markdown
Contributor

Describe your changes

ClusterFinder groups hits in a fixed window (ClusterFindingWindow). Light from one particle that spreads a little longer, e.g. a Michel electron or a neutron capture, can be split into two clusters a few tens of ns apart. This adds an optional step that merges such clusters, controlled by two new keys in ClusterFinderConfig (both off by default):

 TimeMergeWindow 50     # ns; merge clusters whose median hit times are closer than this, chained in time order (0 or absent = off)
 TimeMergeMinTime 2000  # ns; clusters with an earlier median are never merged (leaves the prompt window alone)
  • The merge runs at the end of Execute, just before ClusterMap/ClusterMapMC/ClusterMapDetkey are put in the CStore, so every downstream tool sees the merged clusters and the three maps stay consistent.
  • Hits of a group are combined; a hit shared by two clusters (same PMT and time) is kept once. The merged cluster is keyed by the mean hit time, as ClusterFinder does.
  • The logic is in ClusterTimeMerge.h/.cpp in the ClusterFinder folder, compiled for Hit and MCHit, so data and both MC pulse models use the same code. It reads only hit times and PMT IDs.
  • It works on whatever ClusterFinder clusters: data and the PMTWaveformSim chain (HitStore Hits), and the parametric MC pulses (HitStore MCHits).
  • Why inside ClusterFinder rather than a separate tool: the merge has to rewrite the three cluster maps together before any other tool reads them. Here that happens where they are built, and there is no extra tool, config file, or toolchain-order requirement. Switching it off is removing the two keys.
  • The tool's own histograms are filled before merging (README updated).

Tests (BeamClusterAnalysisMC on Application; tank 500, world 700, AmBe 1000 events):

  • Keys absent: output identical to Application, 164/164 branches in all three samples.
  • TimeMergeWindow 50 / TimeMergeMinTime 2000, clusters after 2 µs, C++ against an independent Python implementation on the same hits:
hits clustered tank world AmBe same cluster count as Python
MC pulses (HitStore MCHits) 471 → 435 245 → 226 866 → 860 100 % of triggers
waveforms (PMTWaveformSim → PhaseIIADCHitFinder → HitStore Hits) 436 → 414 235 → 222 851 → 850 99.6 % (tank), 100 % (world, AmBe)

Checklist before submitting your PR

  • This PR implements a single change (one new/modified Tool, or a set of changes to implement one new/modified feature)
  • This PR alters the minimum number of files to affect this change
  • If this PR includes a new Tool, a README and minimal demonstration ToolChain is provided
  • If a new Tool/ToolChain requires model or configuration files, their paths are not hard-coded, and means of generating those files is described in the readme, with examples provided on /pnfs/annie/persistent
  • For every new usage, there is a reason the data must be on the heap
  • For every new there is a delete, unless I explicitly know why (e.g. ROOT or a BoostStore takes ownership)

Additional Material

Attach any validation or demonstration files here. You may also link to relavant docdb articles.
This presentation has outcomes from some of these changes. However, earlier I had standalone python script but now attempt to have integrated version of it in ToolAnalysis.

dhavvval and others added 3 commits October 26, 2026 10:16
Two new config keys, both off by default:
  TimeMergeWindow   ns; clusters whose median hit times are closer than
                    this are merged, chained in time order (0/absent = off)
  TimeMergeMinTime  ns; clusters with an earlier median are never merged
The merge runs just before the cluster maps are put in the CStore, so
every downstream tool sees the merged clusters. Hits of a group are
combined; a hit shared with an earlier cluster of the group (same PMT and
time) is kept once. The merged cluster is keyed by the mean hit time, as
ClusterFinder does. The logic is in ClusterTimeMerge.h, templated on the
hit type, so data (Hits) and MC (MCHits) use the same code. It reads only
hit times and PMT IDs.

Tested on this branch (BeamClusterAnalysisMC, tank 500 / world 700 /
AmBe 1000 events):
- keys absent: output identical to Application (164/164 branches);
- TimeMergeWindow 50 / TimeMergeMinTime 2000, delayed clusters, C++ vs
  the Python CF+NMS method on the same hits:
    MC pulses (HitStore MCHits): tank 471 -> 435, world 245 -> 226,
      AmBe 866 -> 860 clusters; same count in 100 % of triggers;
    waveforms (PMTWaveformSim -> PhaseIIADCHitFinder -> HitStore Hits):
      same count in 99.6 % (tank) / 100 % (world, AmBe) of triggers.
On MC with per-hit truth (ANNIEsoft/WCSim#27, ToolAnalysis#392) the
Michel/capture clusters that the fixed window split are rejoined (tank
37 -> 0, world 24 -> 0, AmBe 6 -> 0 split particles). No measurable
runtime cost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge code moves from the header into ClusterTimeMerge.cpp, compiled
for Hit and MCHit, following the usual .h/.cpp layout of helper files in
UserTools. The function bodies are unchanged, so ClusterFinder merges
exactly the same clusters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant