Add SCECorrection IPCTransform with pluggable ISCEField (SBND)#479
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).
Review: SCE correction (SCECorrection / ISCEField / SCEFieldTH3)Adds SBND Space-Charge-Effect correction: a new ✅ Compilation — passesVerified against a full build log of this branch:
✅ No impact on existing functionality
Test segfaults in the build log — pre-existing, not from this PRThe test run shows 2 doctest crashes (
Recommend confirming both also fail on Non-blocking notes (relevant when the feature is enabled)
VerdictBoth requirements are met: the PR compiles cleanly and is additive / name-gated, so it cannot affect existing behavior unless explicitly enabled via metadata + jsonnet. The two test segfaults are unrelated/pre-existing. The notes above are quality considerations for when the feature is turned on, not blockers. |
|
@calcuttj perhaps interesting for you to note given your presentation yesterday about the VD non-uniform drift field issue. |
Summary
Adds an SBND-ready 3D SCE correction to the toolkit as an
IPCTransformcomposed from a newISCEFieldinterface. T0 correction is built in; the SCE backward displacements (X, optionally Y / Z) are delegated to whicheverISCEFieldimplementation is wired in via configuration. This PR ships one such implementation,SCEFieldTH3, backed by per-TPCTH3Fhistograms loaded from a ROOT file (e.g. the SBND dualmapSCEoffsets_SBND_E500_dualmap_CV_voxelTH3.rootmodel).Validation evidence: WireCell/wcp-porting-validation#9 (Stage 1, merged) and WireCell/wcp-porting-validation#12 (Stage 3a, transverse).
Architecture
iface/inc/WireCellIface/ISCEField.h— pure-virtualIComponent<ISCEField>withdisplacement_x(int apa, double x, double y, double z) const(required) plus optionaldisplacement_y/displacement_z(default no-op, so maps without transverse components are unaffected). WCT-internal mm in, mm out.root/inc/WireCellRoot/SCEFieldTH3.{h,cxx}— ROOT-backedISCEField+IConfigurable. Loads up to sixTH3Fs (X / Y / Z × East / West) from a single ROOT file via a sharedinterp()helper; transverse histograms soft-load (skipped without error if absent). Handles cm ↔ mm axis units, sign convention, andTH3::Interpolate's open-interval edge clamping.clus/inc/WireCellClus/SCECorrection.h+clus/src/PCTransforms.cxx—SCECorrectiondoes T0 (per-APAdrift_speedfromDetectorVolumesmetadata) plus the optional 3D SCE displacement via an injectedISCEField::pointer.PCTransformSet::configurelooks up the field by TypeName from theDetectorVolumesmetadata keysce_fieldviaFactory::find_tn. Ifsce_fieldis absent,SCECorrectionruns as T0-only.The interface lives in
iface/, the ROOT-backed implementation inroot/, the transform inclus/.clus/wscript_buildis untouched —clus/remains ROOT-free.Behavior change (intentional):
SCECorrection'soutput_scopeis{x_sce, y_sce, z_sce};stored_array_nameslikewise. Downstream configs that cluster on the SCE scope therefore cluster in fully-corrected 3D.Validation
50 SBND crossing-muon DETSIM events, 226 721 / 228 762 points paired by charge (99.1 %; 0.9 % dropped on ambiguous q), comparing the reco output to the input TH3 backward map at the corrected
(x_sce, y_sce, z_sce)coordinates:Pooled
W / E |Δx| = 1.326— consistent with the map volume-average (1.276) and the patched 0.33-era reco (1.271). The implementation reproduces the TH3 backward map to interpolation precision (≈ 2 µm) in all three components.Configuration
Minimal jsonnet wiring for the SBND dualmap (3D):
Files
5 files, +466 / 0 across 3 commits:
iface/inc/WireCellIface/ISCEField.hroot/inc/WireCellRoot/SCEFieldTH3.hroot/src/SCEFieldTH3.cxxclus/inc/WireCellClus/SCECorrection.hclus/src/PCTransforms.cxxcc @HaiwangYu