Cherry-pick PR479 to master instead of match#482
Conversation
ISCEField is a pure-virtual IComponent providing per-TPC backward X-displacement queries. SCEFieldTH3 implements it backed by per-TPC TH3F histograms loaded from a ROOT file -- for example, the SBND dualmap SCEoffsets_SBND_E500_dualmap_CV_voxelTH3.root model. Separating the interface from the ROOT-backed implementation lets SCECorrection in clus/ depend only on the interface, keeping the clus/ subpackage ROOT-free.
SCECorrection is an IPCTransform that composes a T0 correction [per-APA drift_speed from DetectorVolumes metadata] with an optional SCE backward displacement delegated to an externally-provided ISCEField. This keeps clus/ ROOT-free; the ROOT-backed displacement field lives in root/ as SCEFieldTH3. PCTransforms looks up the ISCEField by TypeName from the DetectorVolumes metadata key 'sce_field' via Factory::find_tn and passes it to the SCECorrection constructor. If 'sce_field' is not present in the metadata, SCECorrection runs as T0-only -- the SCE step is a no-op. Validated on 50 SBND crossing-muon DETSIM events against the dualmap SCE model: per-point residual rms 1.83e-04 cm East, 2.23e-04 cm West, max 8.42e-04 cm; pooled mean|dx| ratio W/E = 1.327. The reco reproduces the TH3 backward map to interpolation precision.
…ments
Adds the transverse components to the SCECorrection chain introduced
in this PR. ISCEField gains optional displacement_y / displacement_z
[default no-op, so maps without transverse components are unaffected].
SCEFieldTH3 soft-loads the TrueBkwd_Displacement_{Y,Z}_{E,W}
histograms and routes all three components through a single shared
interp() helper. SCECorrection now outputs the fully-corrected triple.
Behavior change [intentional]: SCECorrection output_scope goes from
{x_sce, y, z} to {x_sce, y_sce, z_sce}; stored_array_names likewise.
Downstream configs that cluster on the SCE scope therefore cluster in
fully-corrected 3D.
Validated end-to-end on 50 SBND crossing-muon DETSIM events: per-point
Dx residual vs the TH3 map is unchanged from the prior baseline
[1.83 / 2.23 um E/W], and the new Dy / Dz residuals close at the same
interpolation precision -- Dy 2.63 / 1.65 um, Dz 3.35 / 2.99 um;
max <= 9.91 um across all three components. Evidence in the
companion wcp-porting-validation PR (sbnd-sce-036-stage3a-yz branch).
./test/scripts/check-build all 482 >& 482.logTest-failure analysis for the SCE cherry-pick (build log
|
| Binary | Signal | Root cause | Related to SCE? |
|---|---|---|---|
pytorch/test_from_blob, pytorch/test_util |
SIGABRT (-6) | libtorch c10::Error "not CUDA available" on a CPU-only node |
No — environmental |
clus/wcdoctest-clus |
SIGSEGV (-11) | pre-existing breakage in doctest_clustering_prototype.cxx |
No — pre-existing |
sigproc/wcdoctest-sigproc |
SIGSEGV (-11) | pre-existing crash in doctest_l1sp_kernel.cxx:130 |
No — sigproc untouched |
test/wcdoctest-test |
SIGSEGV (-11) | failed to load plugin: WireCellSigProc (stale/missing install) |
No — environmental |
Details
1. pytorch/test_from_blob, pytorch/test_util — SIGABRT
libtorch throws c10::Error from getDeviceGuardImpl → "not CUDA available". Configure explicitly dropped CUDA ("Removing package cuda due to lack of external dependency HAVE_CUDA"). The tests attempt a CUDA device op on a CPU-only node and abort. Environmental.
2. clus/wcdoctest-clus — SIGSEGV
Two pre-existing issues in clus/test/doctest_clustering_prototype.cxx:
:347CHECK(pcc.sanity())fails in "create cluster graph"; the test prints its own warning "not actually creating graph as test needs updating to avoid 'Anode is null' exception".:356"Simple3DPointCloud" SIGSEGV.
The file references IPCTransform only in an #include and commented-out code (never constructs PCTransformSet/SCECorrection), and was not touched by the cherry-pick. Pre-existing.
3. sigproc/wcdoctest-sigproc — SIGSEGV
Crash in sigproc/test/doctest_l1sp_kernel.cxx:130. The sigproc subpackage is entirely untouched by SCE. Pre-existing/environmental.
4. test/wcdoctest-test — SIGSEGV
:179throwsWireCell::IOError"failed to load plugin: WireCellSigProc" viaPluginManager::add. The stacktrace loads libraries from the install prefix (/exp/.../opt/lib), not the freshbuild/tree — the build was not installed (./wcb installnot run), so the installed plugin is stale/missing on the dlopen path.:308"envfiducial" then SIGSEGV (knock-on after the failed plugin load).
Environmental; likely clears after ./wcb install.
Conclusion
All four failures are either environmental (no CUDA; stale install for plugin loading) or pre-existing test breakage (clus prototype test self-flagged as needing update; sigproc l1sp). The same clus + sigproc crashes also appear in an earlier build log on a different base, confirming they predate this work. No failing test exercises ISCEField/SCECorrection/SCEFieldTH3, and no crash backtrace contains SCE symbols.
To make this airtight, rebuild plain master (no SCE) and run the same test target — identical failures there would definitively rule out the cherry-pick. The test/wcdoctest-test plugin failure specifically should clear after a ./wcb install.
Ref: #479