Skip to content

Tracking dev progress#451

Draft
HaiwangYu wants to merge 352 commits intomasterfrom
apply-pointcloud
Draft

Tracking dev progress#451
HaiwangYu wants to merge 352 commits intomasterfrom
apply-pointcloud

Conversation

@HaiwangYu
Copy link
Copy Markdown
Member

@HaiwangYu HaiwangYu commented Dec 2, 2025

Make this new one, as #444 seems not working for the tracking purpose

lastgeorge and others added 30 commits April 16, 2026 10:22
Section 5.4 now documents the actual C++ comparison app
(wire-cell-uboone-tagger-compare) replacing the earlier Python script
placeholder.  Implementation sequence table updated with DONE/TODO
status for each step.  Key file reference table extended with the new
visitor header/impl and comparison app.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reclassify all SPDLOG_LOGGER_DEBUG/->debug() calls in clus sub-loggers
(clus.Cluster, clus.TrackFitting, clus.NeutrinoPattern, and other clus
component loggers) to TRACE level. MultiAlgBlobClustering high-level
flow logs remain at DEBUG.

With -L clus:debug (default), only high-level flow is shown. To re-enable
detail per subsystem, add e.g. -L clus.NeutrinoPattern:trace or -L clus:trace.
Requires building with --with-spdlog-active-level=trace (new wscript default).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Keep DEBUG only for configure-time roll-call, event milestones (loading
tensor set, Produce pctrees, performance summary, EOS), and the rare
diagnostic skip. Demote to TRACE: the dump() ensemble printouts (fired
before/after every visitor, ~60 lines/event), per-segment fitted-point
counts, and bee-points fill summaries.

With -L clus:debug the MABC log footprint drops from ~72 to ~22 lines/event.
Full detail returns with -L clus:trace.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pass "!V:Silent" to all TMVA::Reader constructors in UbooneNueBDTScorer
and UbooneNumuBDTScorer to suppress the verbose booking/loading messages
that fire at startup for every BDT reader.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TaggerCheckNeutrino: add per-step DEBUG-level wall-clock timing in
  visit() gated by m_perf, covering preload, PR, vertex determination,
  taggers, kine fill, and a TOTAL line (~12 lines/event when enabled)
- NeutrinoPatternBase: fix init_first_segment always passing &cluster as
  main_cluster causing false flag/pointer mismatch WARN for non-main
  clusters; pass nullptr for non-main clusters instead; demote the
  nullptr fallback message from WARN to TRACE
- BlobSampler: demote wire-index out-of-range from WARN to TRACE since
  the boundary clamping is already correct; consolidate into one TRACE line

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends the existing `struct Perf` in MultiAlgBlobClustering with
std::chrono so each perf checkpoint emits a DEBUG-level line showing
the step name, its wall-clock duration, and cumulative time since the
start of operator(). Gated by `m_perf` (existing config knob).

Also minor whitespace cleanup in SteinerGrapher.cxx and
ClusteringRecoveringBundle.cxx (trailing spaces, missing newline).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rename three fields to match prototype output tree names:
  shw_sp_br3_7_shower_main_length → shw_sp_br3_7_main_length
  br3_7_shower_main_length        → br3_7_main_length
  numu_cc_3_acc_track_length      → numu_cc_3_track_length

Also remove match_isFC from the output visitor (not written by prototype).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
numu_tagger3.weights.xml was trained with "numu_cc_3_acc_track_length"
so the numu3 Reader::AddVariable must keep that label, even though the
TaggerInfo field and xgboost reader now use the prototype name
"numu_cc_3_track_length".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When -v is given and a branch differs, print the prototype and toolkit
values from the first differing event alongside the existing stats.
Scalars show inline; vectors print on separate indented lines.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add -n<NeutrinoTaggerInfo.h> option: parses the header at runtime to
build a branch→default map (float/int fields read {init}, vectors → []).
Verbose output now prints a fixed-width table with aligned columns for
n_diff/n_cmp, max|diff|, proto, toolkit, and default.  Vectors get a
two-row proto/toolkit dump below the stats line.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
detect_type now returns SCALAR_D for Double_t leaves.  setup_branch_stat
allows mixed Double_t/Float_t pairs (canonicalised as SCALAR_D) by
reading each side into its native buffer and promoting to double in
compare_one.  Verbose output prints SCALAR_D values the same way as
SCALAR_F.  Fixes [SKIP unsupported type] for nu_x/y/z after prototype
changed their type to Double_t.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
nu_x/y/z are written under alias names in the output visitor but live
as kine_nu_x/y/z_corr in NeutrinoTaggerInfo.h.  Add a small static
alias table so the default-value lookup follows the indirection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The header is installed at <prefix>/include/WireCellClus/NeutrinoTaggerInfo.h
alongside the binary at <prefix>/bin/.  Use readlink(/proc/self/exe) to
find the prefix at runtime so defaults are shown without needing -n.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…se mode

Two additions to the -v output:

1. Fingerprint cluster report (before the per-branch table): groups scalar
   branches that share identical (proto, toolkit) first-diff values and prints
   any cluster of >= 3 branches.  This surfaces the common pattern where one
   upstream quantity (e.g. main-shower energy, main-shower length, main vertex)
   drives dozens of apparent diffs.  For the nue_5384_132_6604 event the
   energy cluster alone has 45 members, collapsing the apparent 16-category
   diff into ~5 root causes.

2. 'note' column in the per-branch table: sentinel_note() flags rows where one
   side is a known sentinel and the other is not:
     |v| >= 1e7  ->  [SENT proto] or [SENT tool]  (no-segment-found style)
     int == -1   ->  [UNINIT proto] or [UNINIT tool]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- clus/test/doctest_tagger_info.cxx: checks all non-zero TaggerInfo defaults
  (cosmic_flag, gap_flag, mip_quality_flag, mip_flag, MIP counters/values,
  SSM sentinels) and KineInfo zero-init + empty vectors. 42+15 assertions.

- clus/inc/WireCellClus/PatternDebugIO.h,
  clus/src/PatternDebugIO.cxx: add TaggerTestData struct (LoadedTestData +
  other_clusters vector), dump_tagger_inputs() and load_tagger_inputs() that
  capture main_cluster + beam-flash other_clusters + TrackFitting params.
  Also serialize beam_flash flag in dump_cluster_data / make_cluster_node.

- clus/src/TaggerCheckNeutrino.cxx: add WCT_DUMP_TAGGER_INPUTS env-var gate
  after preload_clusters to generate replay fixtures.

- clus/test/doctest_tagger_check_neutrino.cxx: loads fixture + WCT config,
  runs full pattern recognition chain (find_proto_vertex → shower_clustering
  → cosmic_tagger + numu_tagger), asserts cosmic_filled==1 and key fields
  are finite. Default fixtures from clus/test/data/ (to be generated).

- clus/docs/tagger/tagger_validation_plan.md: bump steps 6-9 to DONE,
  rewrite Section 5 to document the full-chain replay approach.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add clus/test/data/tagger_check_neutrino_input.json (event 5384/130/6501)
- Fix factory lookups to use full type:name form (ParticleDataSet:ParticleDataSet,
  BoxRecombination:box_recomb) matching the uboone-mabc_config.json registration
- Fix MESSAGE calls to use std::string locals (MessageBuilder has no operator<< for const char*)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two test suites in doctest_pattern_recognition.cxx:

  pattern_recognition pure helpers (5 tests):
    - calc_PCA_main_axis: collinear points → direction ≈ ±x; single-point no-crash
    - order_segments: sorts by track length descending
    - find_cluster_segments/vertices: hand-built graph returns correct counts
    - clean_up_graph: removes all cluster-tagged content

  pattern_recognition replay [A] (7 tests, fixture tagger_check_neutrino_input.json):
    Event 5384/130/6501 produces an empty PR graph (no convincing vertex).
    Tests verify each step runs without exception and leaves graph consistent.

  pattern_recognition replay [B] (4 tests, fixture pattern_recognition_vertex_input.json):
    Skipped gracefully when the vertex-found fixture is not present.
    When available: asserts determine_main_vertex finds a vertex inside the
    active volume, improve_vertex shifts < 20 cm, shower maps are self-consistent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PRSegmentFunctions: null-guard dEdx/range function lookups before use in
do_track_comp/segment_do_track_pid so missing functions return a fallback
instead of crashing.

ParticleDataSet: switch IScalarFunction lookup from find_tn to lookup_tn
so LinterpFunction singletons are created during configure() even when
configure_components processes ParticleDataSet before LinterpFunction
entries in the JSON config.

PatternDebugIO: add dump_grouping_ctpc helper for serialising CTPC
datasets from the grouping's local_pcs (used by extended fixture format).

TaggerCheckNeutrino: re-enable WCT_DUMP_INIT_FIRST_SEGMENT env-var dump
hook (was commented out).

doctest_pattern_recognition: mirror full TaggerCheckNeutrino::visit() in
run_through — add other-cluster PR loop (long/short split + init_point_-
segment fallback), deghosting, and map read-back after
determine_overall_main_vertex; add second configure_components pass to
ensure LinterpFunctions are populated before use; fix vertex coordinate
bounds to WireCell mm units; rename stale "returns null" test case.

doctest_tagger_check_neutrino: use full type:name form for factory
lookups (ParticleDataSet:ParticleDataSet, BoxRecombination:box_recomb);
fix MESSAGE macro calls to use std::string locals.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Regenerate init_first_segment_input.json and tagger_check_neutrino_input.json
from event 5384/130/6501 using the extended PatternDebugIO dump format that
now includes grouping CTPC datasets. The larger file size reflects the added
charge-tile point-cloud data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CoordBoundsSampled::distance() was using only the nearest KNN sample's
axis coordinate, which gives the wrong result for a bent surface: a
point just past the local cathode could appear "inside" if a nearby
sample at a higher-x part of the surface happened to be the nearest
3D neighbor. Fix by fitting a plane through all 3 nearest samples and
interpolating the surface coordinate at the test point's transverse
(y,z) position.

Also fix doctest_drifter.cxx line 155: depos.begin(), depos.begin()
was inserting nothing; changed to depos.end().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… cloud

charge_value() and charge_uncertainty() would silently dereference an empty
vector (UB/segfault) if BlobSampler's extra regex omitted ".*charge_val" or
".*charge_unc". Add an explicit check after points_property and raise a clear
ValueError naming the missing key and pointing at the BlobSampler config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two bugs in MagnifySink::do_shunt / cmmtree writing:

1. Trun branch address corruption: Branch() was called with &ints.back()
   after each push_back, but subsequent push_back calls can reallocate
   the vector, leaving every previously registered branch with a dangling
   pointer. Fix: reserve(nkeys+1) before the loop so no reallocation
   occurs, keeping all &ints[n] pointers valid through rtree->Fill().

2. Cross-anode channels in T_bad: the channel mask map in a per-anode
   SP frame archive is detector-global, so channels belonging to other
   anodes appear with plane=-1 when resolved against this anode's
   IAnodePlane. Fix: skip any channel whose resolved plane index is
   negative.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copied from Xuyang's working tree so the pdvd run scripts no longer
depend on an external WIRECELL_PATH entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…inputs

PointTreeMerging: new "tolerate_missing" config option (default false, so
existing configs are bit-identical). When true:
 - Missing "<inpath>/live" or "<inpath>/dead" datapath on any input is logged
   and merged as an empty tree (instead of raising KeyError).
 - Each input's own ident formats its own inpath ("pointtrees/%d"), so tensor
   sets emitted with different idents merge correctly (e.g. empty placeholder
   sets carry ident=0 while real sets carry the art event number). Legacy
   behaviour uses invec[0]'s ident for all inputs.
 - Promotes the merge-progress TRACE diagnostics to DEBUG to aid future
   debugging of fan-in merges.

ClusteringSwitchScope: when the live grouping has no wpids, log a warning and
return instead of throwing std::runtime_error. Consistent with the existing
"no live ensemble" graceful-skip one block up, and with the already-removed
similar checks in clustering_separate.cxx:65 and retile_cluster.cxx:476,485.
Needed for the "merge that includes empty APAs" case enabled by the
tolerate_missing path.

Use case: per-event selection that only covers one or two APAs. Downstream
imaging still runs for all APAs and produces empty placeholder cluster
tarballs; clus_all_apa's PointTreeMerging must accept them and fold the one
real APA's point tree into the merged output.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

3 participants