/**
 ** CuasRtParameters.java - CUAS real-time (curt_*) parameters, extracted from
 ** IntersceneMatchParameters (2026-07-05) to keep it under the 64KB method-bytecode
 ** limit and group all curt_* in one navigable place. Held as
 ** IntersceneMatchParameters.curt; persisted with the same property keys
 ** (prefix+"curt_"+short) so old .corr-xml files still load. GPLv3 (Elphel norm).
 ** By Claude on 07/05/2026, from Andrey's design.
 */
package com.elphel.imagej.tileprocessor;

import java.awt.Rectangle;
import java.util.Properties;

import com.elphel.imagej.common.GenericJTabbedDialogMcp;
import com.elphel.imagej.cuas.rt.CuasTD; // OOB margin defaults (single source, frozen spec) // By Claude on 07/12/2026

public class CuasRtParameters {
	public boolean  en =              true; // enable cuas rt calculation (not needed with a separate button)
	public boolean  calib =           false; // first step of the CUAS RT processing flow: per-sensor photometric (re)calibration - fit a+b*x over safe (weak/far) tiles, fold into the 16+16 lwir offsets/scales, apply + save (reference scene INTERFRAME corr-xml, quadCLT_main -> main config). Bypass when off. // By Claude on 07/03/2026
	public boolean  cond_test =       false; // conditioning/calibration isolation test inside the en branch: build the QuadCLT instances (borrowed calibration) then print per-sensor average spread (CuasMotion.perSensorAveragesFromTD) instead of normal RT detection; well-calibrated -> 16 sensor averages match (spread ~0). // By Claude on 07/01/2026
	public boolean  pose_test =       false; // RT pose-adjustment prototype (phase A) inside the en branch: re-generate per-scene 3-angle poses against the virtual-center reference, ascending, prediction-seeded (CuasPoseRT.testPoseSequence) instead of RT detection; writes -POSE-RT-TEST.csv + fitted-vs-stored summary. // By Claude on 07/03/2026
	public double   pose_str =        1.0;   // reliable-tile strength threshold over the combo-DSI strength for the pose test tile selection (1.0 ~ old getReliableTiles population). // By Claude on 07/03/2026
	public double   pose_dxy_k =      0.75;  // tile-selection outlier gate: keep tiles with max-over-scenes residual <= median + k*NMAD of the finite per-tile maxes (scale-free - adapts to footage quality/sequence length; NaN-in-any-scene = +inf, always rejected). <=0 - skip the gate. // By Claude on 07/04/2026
	public int      pose_num_tiles =  150;   // tile-selection compute budget: after the gate, keep this many BEST (smallest max-residual) tiles; threshold-free rank - always yields the best available population. <=0 - no cap. // By Claude on 07/04/2026
	public int      pose_shrink =     4;     // tile-selection interior gate (3-A3, Andrey's rulings 07/13/2026): exclude tiles within this many tiles of the tile-array BORDER before selection (pure ring, NO morphological shrink - the calibration is NaN wherever a tile was not strength-selected, ~21% finite density, so a blind shrink annihilated the selection to ~2 tiles in the first attempt). The OOB-missing band is geometrically confined to the frame border (margin-dropped ring 1-2 tiles + partial 16-sensor OOB soft band 12 px = 1.5 tiles); ring 4 = hard+soft+slack, guaranteeing all-16-interior tiles at every scene pose - the GPU pose chain can then bypass the consolidation OOB pass with a FIXED per-sequence tile list. 0 = off (legacy selection). // By Claude on 07/13/2026
	public boolean  pose_raw =        false; // phase A2/RT ingest: preload all RAW /jp4/ scenes before the measured loop; apply borrowed Row/Col profiles there when enabled; then condition with the current scale/offset/FPN/DC and force-upload. Bypasses prepared image_data and excludes file I/O from RT timing. // By Claude on 07/05/2026, preload Codex 07/15/2026
	public boolean  pose_pace =       false; // preloaded pose RT harness: false = maximum-throughput run; true = release every input at exactly 60 Hz, process every scene with no skipping, and report queue/latency/deadline statistics. Saved as curt_pose_pace for run provenance. // By Codex on 07/15/2026
	public boolean  pose_lean =       false; // phase B measurement engine: TD-average the 16 sensors (CuasTD, CPU bridge) then ONE conj-multiply vs the virtual-center TD -> FZ-normalize -> PD -> argmax+eigen (getMaxXYCmEig) -> 3-angle LMA. All existing GPU kernels. v1: NO motion-blur compensation - compare vs the NOMB baseline. // By Claude on 07/05/2026
	public boolean  pose_full =       false; // DEBUG: use ALL strength-selected tiles (~1074) - the -POSE-RT-TILE-CALIB calibration is neither read nor written (temporary bypass of the 150-tile filter for measurement debugging). // By Claude on 07/04/2026
	public boolean  pose_corr_save =  false; // DEBUG: save the per-scene 2D correlations vs the virtual center in the pixel domain (-POSE-RT-CORR2D: z=scenes, tile grid of 16x16 cells, last LMA cycle) - lean engine only. // By Claude on 07/04/2026
	public boolean  pose_img_save =   false; // DEBUG: save the composite scenes actually correlated - imclt render of the consolidated 16-sensor TD average at the converged pose (-POSE-RT-COMPOSITE: z=scenes; NaN outside task tiles) + the virtual-center reference render (-POSE-RT-CENTER-REF). Lean engine only. // By Claude on 07/04/2026
	public boolean  pose_stored =     false; // DEBUG: decouple rendering/measurement from the LMA - use the STORED (oracle vintage) pose for every scene, no adjustment; one leanMeasure per scene feeds -POSE-RT-HYPER/-CORR2D/-COMPOSITE. The composite must then match the oracle CUAS-MERGED-CUAS-DBG renders tile-for-tile. Lean engine only. // By Claude on 07/04/2026
	public boolean  pose_mb_uniform = true;  // lean v2 (Andrey's ruling 07/12/2026): ONE uniform motion-blur vector per scene, shared by ALL tiles - under constant-rpm rotation the image flow is uniform across the frame up to the roll flow component (roll rate << azimuth/tilt) and the wobble contribution (second-degree), both ignored. Same Jacobian-times-rates product as the per-tile OpticalFlow.getMotionBlur (identical sign/scale conventions), evaluated at ONE representative point (frame center, mean reference disparity) and broadcast; rates source unchanged (finite differences of predicted poses). OFF = legacy per-tile getMotionBlur (the A/B knob). // By Claude on 07/12/2026
	public int      pose_cycles =     3;     // lean v2 (Andrey's ruling 07/12/2026): run EXACTLY this many LMA measure<->solve cycles per scene, no convergence-based early exit - CUAS scenes are near-identical perturbations of the same view, so the needed count is a constant of the setup (and a fixed count gives the GPU pipeline a static launch shape). The convergence delta is still computed: a QC line flags scenes whose last ATR change misses the legacy imp.exit_change_atr threshold (diagnostic only). 0 = legacy convergence exit (imp.max_cycles cap + exit_change thresholds - for varying-scene/flying-camera applications). // By Claude on 07/12/2026
	public double   pose_lambda =     0.001; // lean v2 (Andrey 07/12/2026): INITIAL LMA lambda for the inner pose solve, replacing ilp.ilma_lambda (0.1) which restarts every outer measure<->solve cycle. 0.1 + the 0.1%-improvement inner exit = under-relaxation: the inner loop quits while still lambda-limited, the outer cycle re-measures and lambda resets - hence the observed ~0.8/cycle outer decay needing 6-13 cycles. The 3-angle/150-tile problem is heavily overdetermined and near-linear: a near-zero lambda makes the first inner steps ~Gauss-Newton so each outer cycle closes the measurable gap. 0 = legacy (use ilp.ilma_lambda). // By Claude on 07/12/2026
	public int      pose_max_lma =    1;     // lean pose: INNER LMA iteration cap, replacing the shared imp.max_LMA (which stays at ~25 for flying-camera/varying-scene applications). VALIDATED 07/13: with the near-GN start (pose_lambda) the first inner step reaches the model optimum - step 2 only confirms <0.1% - so 1 halves the solver work and makes the shape fully static (pose_cycles x 1); dstored RMS identical to unlimited (0.0350/0.0377/0.0213). 0 = legacy (use imp.max_LMA). // By Claude on 07/13/2026, Andrey's design
	public int      pose_recenter =   0;     // rung-2 frozen GPU contract (Andrey's ruling 07/13/2026): recentering passes for the lean peak measurement - the 15-arg Correlation2d.getMaxXYCmEig cosine-mask refinement (window over the eigen-ellipse, imp.eig_scale_axes*sqrt(lambda)+imp.eig_inc_axes half-axes, re-centroid each pass). 0 = single-pass (today's validated baseline behavior); imp.eig_recenter (2) = the oracle engine's setting - candidate for wide lean peaks, needs its own A/B run. The GPU argmax/centroid/eigen kernel implements the SAME superset contract with this as a runtime parameter. // By Claude on 07/13/2026
	public double   pose_debias =     0.0;   // rung-2 optional envelope de-bias hook (Andrey's ruling 07/13/2026, default OFF): fraction of the MCLT window-autocorr envelope divided out of the pixel-domain correlation BEFORE peak extraction (corr *= envelope^-frac, envelope normalized 1.0 at center). The envelope multiplies the true correlation peak and pulls the centroid toward center - argmax under-reports offsets by alpha ~0.75-0.9 (probed 07/13, the residual per-cycle convergence tax). 0 = off (bit-identical to no hook); 1 = full divide. GPU kernel contract: optional precomputed de-bias array pointer, NULL = off. Enabling needs its own A/B run. // By Claude on 07/13/2026
	public int      pose_lma_debug =  0;     // inner-LMA debug level, passed to the inner runLma (max with the run's own debugLevel): 0 = quiet (default; ALSO gates the per-scene "CuasPoseRT cycles:" trace line - >=1 to print it); 2 = one line PER INNER STEP ("LMA step N: {good,done} full RMS= ... pure RMS= ... + lambda=...") - the convergence trajectory INSIDE each outer cycle; 3-4 = progressively deeper solver dumps (parameter vectors, matrices). VERBOSE at >=2 - use for short investigation runs, not production. // By Claude on 07/12/2026, trace gate 07/13
	public int      pose_freeze_cycle = 0;   // rung C3/C3b FALSIFIED 07/16 (freeze@1: az +48% roll +100%; freeze@2: az +30% roll +54%, NOT-settled 51->228): conditioning re-derivation matters through ALL cycles. 0 = never freeze = per-cycle (DEFAULT, restores C2 quality). Mechanism kept validated (bit-exact light path) for DP-era experiments (e.g. previous-scene conditioning). Was: freeze the lean-pose LMA conditioning (weights/eigen/selection/pull/reg) at this FULL prepare count; later cycles run light (fresh offsets only). 0 = never freeze = re-derive every cycle (highest accuracy, the pre-C3 behavior); 1 = freeze at cycle 1 (FAILED its gate: blurriest-pose conditioning, azimuth +48%); 2 = freeze at cycle 2 (post-first-correction measurement ~= converged). Keeps the high-accuracy opportunity selectable at runtime (Andrey 07/16). // By Claude on 07/16/2026
	public boolean  pose_scene_dp =   true;  // DP rung D4 (ladder ratified 07/16/2026): run the FULL per-scene lean pose solve as ONE device entry (pose_scene_dp parent: pose_cycles x [measure chain -> full prepare -> resident LMA step -> commit], self-chained on-device, one end-of-scene readback). Scene 0 always runs the host-driven (B3) loop to seed the resident per-sequence state AND is replayed through the DP entry as a one-shot bit-exact oracle; FAIL disables DP for the run (fail-safe). Requires JNA backend + uniform MB + fixed cycles + inner cap 1 + freeze 0; ineligible scenes/configs fall back to the host-driven loop automatically. OFF = the validated B3 host-driven loop (the A/B knob). // By Claude on 07/17/2026
	public boolean  pose_h2d_overlap = true; // D5 overlap rung (design ratified 07/17/2026): while scene N's DP entry runs on-device, condition scene N+1 into the OTHER device image-set ring slot (staged H2D + conditioning kernel on the copy stream) - the ~5.6 ms/scene conditioning+H2D stage hides under the ~12.5 ms chain. Requires pose_scene_dp + the preloaded RT harness (pose_preload); any overlap failure reverts to the serial order for the rest of the run (fail-safe). Bytes identical by construction (same kernels, different buffer). OFF = the serial condition-then-solve order (the A/B knob). // By Claude on 07/17/2026
	public boolean  rend_test =       false; // RT full-render product (CuasRender.testRenderSequence): per scene raw /jp4/ -> conditionSceneToGpu -> virtual-grid render at BORROWED stored pose+ERS rates -> -CUAS-RT-RENDER hyperstack [s00..s15, merged][scenes], comparable to -CUAS-INDIVIDUAL/MERGED-CUAS-DBG. NON-exclusive: runs AFTER the pose stage when both are ON (the pose stage is part of the RT cycle - Andrey 07/06/2026). // By Claude on 07/05/2026
	public boolean  log_test =        false; // LoG A/B with the RT render (CuasRender): also save -CUAS-RT-RENDER-LOG-ORACLE (product convolved with the EXISTING pre-DNN pixel LoG, LINEAR alpha=1) and -CUAS-RT-RENDER-LOG-FOLDED (same render, LoG folded into the GPU aberration kernels via CuasLogFold - no pixel convolution; originals restored). The aberration+LoG kernel-fold validation (RT-seed step 1b). // By Claude on 07/06/2026
	public boolean  log_ident =       false; // LoG ISOLATION test with the RT render (CuasRender): render with IDENTITY kernels (-CUAS-RT-RENDER-ID, aberrations skipped), pixel-LoG it (-ID-LOG-ORACLE), and render with PURE-LoG kernels (-LOG-ONLY). If -LOG-ONLY vs -ID-LOG-ORACLE residual persists, the fold/L0 is wrong; if it collapses to the wrap floor, the aberration-kernel interaction was responsible (Andrey 07/06/2026). // By Claude on 07/06/2026
	public static final String[] KERNEL_TESTS = {"none", "avg_td", "avg_td_oob", "pose_corr"}; // GPU-kernel test registry: one dropdown entry per CUDA kernel under oracle validation (roadmap kernel ladder); add one name here + one case in CuasRT.kernelTest() per new kernel. pose_corr = lean pose-chain checkpoint 1 (roadmap 3-C rung 1): per-LMA-iteration task streams + resident center TD + expected raw TD correlation after correlate2D_inter, captured from the first fitted scene of a normal pose run (requires pose_lean + pose_raw, existing -POSE-RT-TILE-CALIB, pose_stored OFF). // By Claude on 07/12/2026, pose_corr 07/13/2026
	public String   kernel_test =     KERNEL_TESTS[0]; // GPU-kernel test to run this pass (EXCLUSIVE diagnostic, ONE kernel per Java run - Andrey 07/12/2026): run the kernel's CPU oracle on live GPU data and export a self-describing testdata case for the standalone NSight-debuggable CUDA test (tile_processor_gpu tests_bin/test_<kernel> --data <case> --tol 0). "none" = normal operation. // By Claude on 07/12/2026
	public boolean  show_kernels =    false; // show selected convolution kernel
	public boolean  dbg_fpixels =     true;  // save the ORACLE debug renders during ingest (prepareFpixels): -CUAS-INDIVIDUAL-CUAS-DBG (an EXTRA per-sensor render pass, ~11GB) + -CUAS-MERGED-CUAS-DBG (save only - the merged render is the production input regardless). Was hardcoded. Turn OFF to save the render time and disk once the RT chain (-CUAS-RT-RENDER) is the trusted full render. // By Claude on 07/05/2026
	public double   fz_inter =        10000.0; // RT fat zero, INTER (pose/motion: scene x virtual-center correlation). DECOUPLED from the legacy gpu_fatz*/AUX switches (which stay untouched for non-RT/FOPEN). Value is for a single physical-pair amplitude; FZ ~ amplitude^2 in the GPU normalize - scale down x4..x16 for consolidated-average applications as needed. 10000 = the proven oracle INTER operating point (the lean code erroneously used the INTRA value before). // By Claude on 07/05/2026
	public double   fz_intra =        2000.0; // RT fat zero, INTRA (ranging/disparity: sensor-pair correlations within one scene). Reserved for the RT ranging path; same decoupling/scaling notes as fz_inter. // By Claude on 07/05/2026
	public double   dc_center =       0.0; // DC level of the BORROWED center (CLT-RESTORED/average): subtracted from the center CLT at appropriation (CuasRT initialization) so it matches the zero-sky conditioned scenes (MCLT has no clean DC/AC split - a DC constant costs float32 accuracy). 0 = AUTO: reuse the PER-SEQUENCE value from <center>-RT-STATE.json; when absent, derive as the median of the top (sky) half of the reference buffer render and store it there (erase the file/field to re-derive - the missing-file rule). Nonzero = manual override; this config value is never mutated. Slow targets do not influence this shift. // By Claude on 07/05/2026
	public double   oob_soft =        CuasTD.OOB_SOFT_DEFAULT; // 16-sensor TD consolidation, OOB source-margin priority (roadmap 2c, frozen spec Andrey 07/12/2026): SOFT margin, px - a sensor whose tile center is closer than this to its source-frame edge (in EITHER MB pass) is deprioritized (24x24 MCLT support overhangs the frame - defined-but-synthetic replicated rows): used only when NO sensor has the tile deeper. ~12. 0 = tier disabled. Consumed by the GPU consolidate_oob kernel (JNA backend) and the CPU oracle CuasTD.oobSensorMasks identically. // By Claude on 07/12/2026
	public double   oob_hard =        CuasTD.OOB_HARD_DEFAULT; // OOB HARD margin, px - closer than this the 16x16 tile core itself overhangs the frame: the sensor is always skipped. All 16 below hard -> tile poisoned (NaN, v0 semantics - never a synthetic average). ~8. 0 = tier disabled; both margins 0 = v0-compatible unfiltered average (the A/B knob for judging whether coordinate-based filtering suffices). // By Claude on 07/12/2026
	public boolean  cond_gpu =        true;  // Preloaded RT linear-conditioning backend: GPU two-map scale/offset/FPN/common-DC; false = double Java CPU oracle for A/B. Borrowed Row/Col profiles, when enabled, are already applied during preload. The legacy direct reader still requires Row/Col OFF for GPU. Saved as curt_cond_gpu, not a JVM argument. // By Codex on 07/15/2026
	public boolean  rowcol_en =       true;  // Preloaded RT setup: apply the already-calculated borrowed per-scene profiles to raw input using their prior corr-xml scales; never calculate them here. The timed loop then disables Row/Col. Turn OFF for data already corrected inside FLIR. Legacy direct-reader users retain the conditioned-domain estimator. // By Claude on 07/07/2026, separation by Codex on 07/15/2026
	public boolean  rowcol_hpf =      true;  // RT conditioning: high-pass the 1-D row/col average profiles before subtracting (preserve low frequencies for the downstream LoG). // By Claude on 07/07/2026
	public double   rowcol_hpf_sigma = 8.0;  // RT conditioning: Gaussian sigma (px) of the profile high-pass, ~ the LoG scale (the noise band the LoG would pass). // By Claude on 07/07/2026
	public double   rowcol_um_sigma = 10.0;  // RT conditioning: unsharp-mask sigma for the row/col profile MEASUREMENT (content suppression borrowed from the oracle path; the max_abs gate then acts on residual counts); 0 = measure on the data as-is (pre-07/07 behavior). // By Claude on 07/07/2026
	public double   rowcol_max_abs =  50.0;  // Current direct-reader estimator: only average pixels with |UM residual| within this calibrated-count limit; 0 = no limit. Configs saved before 07/07/2026 evening carry 0 - set 50 to enable. // By Claude on 07/07/2026
	public double   rowcol_outlier =  0.01;  // RT conditioning: weight of out-of-range pixels in the line averages (prevents undefined values on all-outlier lines). // By Claude on 07/07/2026
	public int      disp_fg_tiles =   8;     // disparity conditioning: fill connected FOREGROUND clusters up to this many tiles (local near-outliers, e.g. the 3-tile roadside sign) with zero-curvature background disparity so a drone flying exactly behind stays detectable; 0 = off (Andrey 07/07/2026). // By Claude on 07/07/2026
	public double   disp_fg_over =    2.0;   // disparity conditioning: a tile is a near-outlier when its disparity exceeds the local 7x7 median by this many pixels. // By Claude on 07/07/2026
	public double   psf_radius =      1.0;   // sensor PSF radius for LoG pre-filter
	public double   n_sigma =         4.0;   // cutoff LoG kernel array, number of sigmas
	public int      pyramid =         7;     // temporal pyramid levels
	public int      pix_decimate =    1;     // decimate pixel resolution
	public int      vel_decimate =    4;     // decimate velocities
	public int      vel_radius =      5;     // velocities radius in decimated samples
	public boolean  vel_thresh_en =   true;  // zero out per-(sub)pixel velocities, if they have stronger neighbors in 4D space
	public int      vel_suppr_rad =   3;   // suppress weaker in this radius
	public double   vel_athresh =     1.0;   // absolute threshold: discard this pixel-velocity if it has immediate neighbor (of 80=81-1) stronger by this value 
	public double   vel_rthresh =     0.1;   // relative threshold: discard this pixel-velocity if it has immediate neighbor stronger by this value times stronger value 
	public double   vel_dbgmin =      0.0;   // For testing recurrent with strong targets, zero out lower values 
	public double[] temp_weights =    {1,1,1,1,1}; // historic weights for 5D convolution ([0] is the latest sample)
	public boolean  recur_en =        true;  // enable recurrent accumulation buffer (Layer 2) // By Claude on 06/09/2026
	public int      recur_period =    4;     // time units between buffer updates (= vel_decimate for integer-pixel shifts) // By Claude on 06/09/2026
	public double   recur_w =         0.25;  // measurement weight w: buf = leak*(1-w)*shift(buf) + w*conditioned(meas) // By Claude on 06/09/2026
	public double   recur_leak =      1.0;   // extra decay of the shifted prediction per update (gap decay = leak*(1-w) for fixed w) // By Claude on 06/09/2026
	public double   recur_wthresh =   0.0;   // if >0: adaptive per-pixel weight w_eff=w*tanh(strength/wthresh); 0 - fixed w // By Claude on 06/09/2026
	public double   recur_spread =    0.5;   // predict-step velocity diffusion: 3-tap (spread,1,spread) normalized, lets the max migrate between velocity cells; <=0 - off // By Claude on 06/10/2026
	public int      recur_max_clust = 5;     // max 4D-connected survivor cluster size treated as one target (half-cosine bump fit); larger - linear pass-through // By Claude on 06/10/2026
	public double   recur_fit_rat =   2.0;   // max disagreement of per-survivor peak estimates (max/min) for the bump fit; failed fit - per-survivor single-point bumps // By Claude on 06/10/2026
	public double   recur_rs_frac =   0.5;   // re-sharpen blob growth threshold as fraction of the blob max; <=0 - re-sharpening off // By Claude on 06/10/2026
	public double   recur_rs_min =    1.0;   // re-sharpen minimal blob maximum to re-fit; weaker content passes through as residue // By Claude on 06/10/2026
	public int []   c5_levels =       {};    // pyramid levels to process (empty - all); skips the heavy DNN front-end on others; retained as the DNN level gate // By Claude on 06/13/2026
	public String   dnn_model =       "";    // C5P DNN front-end model (ONNX): empty = disabled; local path, scp user@host:path, or http(s) URL fetched to cache; overrides bundled resource (mirrors tile_processor_gpu) // By Claude on 06/13/2026
	public String   stage2_model =    "";    // C5P DNN v2 Stage-2 (learned Hough-vote refine) ONNX: empty = Stage-1 reg field only; when set + a reg Stage-1 model, the reg branch votes (tail T=P-V*(N-1), s^2-weighted) + refines -> saves -VOTE heatmap + -REFINED detection views. By Claude on 06/18/2026
	public double   dnn_thresh =      0.0;   // VISUALIZATION-ONLY s-threshold: NaN's the -OFFSET Vx,Vy,dx,dy where s < this (0 = show all) so velocity shows only at detections. Does NOT gate Layer 2 / the recurrent (always full field) nor the -RECT/-HYPER-RECT data - do NOT use for critical computation. // By Claude on 06/13/2026, viz-only 06/20/2026
	public int      dnn_stride =      1;     // DNN temporal output stride (per pyramid-level slice): 1 = every step (testing, watch each temporal unit); 4 = production (50% overlap, matches the convolver's integer-pixel-shift cadence = recur_period) // By Claude on 06/14/2026
	public double   dnn_vmax =        1.4;   // "ghostbuster": trained DNN velocity limit (px/frame); zero velocity-grid cells beyond this radius (cell-R > vmax*vel_decimate) and discard pixels whose peak lands there (s=0) - the untrained corner cells emit spurious sidelobes that would confuse the recurrent. Set to match the loaded model's training vmax_px (PM models=1.4, base=1.0); <=0 disables // By Claude on 06/15/2026
	public int      dnn_patch =       24;    // DNN receptive-field / training patch size (px): inferROI extracts this PxP patch per ROI pixel (half=P/2 = the output pixel). MUST match the loaded model (24 = base/PM models, 32 = larger-attention model) // By Claude on 06/16/2026
	public boolean  dnn_remote =      false; // run the DNN front-end on the remote DGX server (CuasDnnRemote) instead of local CPU ORT: upload the conditioned stack once, DGX builds the pyramid + full-res shift-and-stitch, returns full-frame {dx,dy,s,Vx,Vy} (-OFFSET) + ROI 121-cell softmax*s (-RECT/-HYPER-RECT). Local CPU path + recurrent feed untouched when off. // By Claude on 06/20/2026
	public String   dnn_remote_host = "192.168.0.62:5577"; // DGX inference server host:port for dnn_remote (see attic/imagej-elphel-internal/c5p_dnn/infer_server.py) // By Claude on 06/20/2026
	public String   dnn_remote_model = "runs/weighted9_pm_s"; // DGX-side run dir (with model.pt) the auto-launched server loads (passed as RUN=) // By Claude on 06/20/2026
	public String   dnn_remote_srcdir = ""; // server-scripts override dir: empty = bundled jar resource (cuas_dnn/), set = local dir - same default-vs-override scheme as the GPU kernels (cuda_project_directory) // By Claude on 06/20/2026
	public boolean  dnn_local =       false; // run the DNN front-end in-process via native LibTorch (CuasDnnLocal/libtpdnn.so) instead of the remote Python server - identical L1+L2 result, no DGX/server. Overrides dnn_remote when set. // By Claude on 06/27/2026
	public String   dnn_local_dir =   ""; // override dir holding <model>/model.ts.pt (+.meta.json) for dnn_local: empty = bundled jar resource (cuas_dnn/) - same default-vs-override scheme as the kernels. // By Claude on 06/27/2026
	public boolean  dnn_l2 =          false; // run the trained Layer-2 (track-before-detect ConvGRU) on the DGX after L1: -OFFSET then carries L2 {det,Vx,Vy} (L1's full-res, NON-ghostbusted field fed in, recurrence over the scene/time axis). Off = L1 offset5 as before (re-run with this off to inspect L1). Requires dnn_remote. // By Claude on 06/22/2026
	public String   dnn_l2_model =    "runs/l2_v1"; // DGX-side Layer-2 run dir (with model.pt) the auto-launched server loads (passed as RUN2=) // By Claude on 06/22/2026
	public boolean  dnn_recur_splat = false; // when feeding the DNN field to the recurrent layer: false = feed per-pixel field as-is; true = splat each pixel's velocity vector to its fractional offset (px+dx,py+dy) so neighbours reinforce in one sub-pixel bin // By Claude on 06/14/2026
	public double   dnn_recur_scale = 10.0;  // multiply the DNN field (softmax*s, peaks ~0.1) by this before the recurrent feed, to reach the recurrent's tuned scale (rs_min=1.0); ~10 -> peak ~1.0. Alternative to lowering recur_rs_min // By Claude on 06/14/2026
	public boolean  synth_src =       true;  // default set for the synthetic B-measurement experiment (set false for real-data runs); reads *-CUAS-SYNTHETIC-CUAS.tiff, output titles get -SYNTH // By Claude on 06/12/2026
	public double   synth_scale =     5.0;   // synthetic target peak, counts (synthetic file is peak-1 normalized; scaled at load) // By Claude on 06/12/2026
	public int      synth_bg_avg =    1;     // synth quick-run: average this many real frames per output frame (=2^LEV noise floor, e.g. 8=LEV3) + force single level; 1=off // By Claude on 06/20/2026
	public boolean  synth_bg =        true;  // add the real *-CUAS-MERGED-CUAS.tiff scene under the synthetic targets (label-matched frames); false - clean targets only // By Claude on 06/12/2026
	public boolean  subtract_avg =    false; // subtract the input temporal average (over the whole sequence) before LoG - removes static background (treeline edge -> kills its tile-grid streak); moving targets survive. NOTE: uses the whole sequence (not realtime); realtime would use a prior-run average // By Claude on 06/14/2026
	public double   min_frac =        0.0;   // default 0 for linear synthetic/B runs (production value ~0.1); zeroes conv5d outputs where the newest frame contributes less than this fraction (NONLINEAR dark-frame gate) // By Claude on 06/12/2026
	public boolean  save_c5full =     false; // save fine velocities [direction][scene][subpixels]
	public boolean  save_c5rect =     true;  // save fine velocities for selected rectangle only [scene][flattened image]
	public boolean  save_c5hyper =    true;  // save per-velocity HYPER-RECT hyperstacks (bottom slider=velocity, second=time) for C5P and posterior outputs - watch a low-SNR target evolve at fixed velocity // By Claude on 06/13/2026
	public Rectangle save_select =    new Rectangle(98, 265, 82, 24); // Example selection for 1773135527_803834
	public double   time_from =      -1.0;  // timing ROI start (timestamp seconds): <=0 open; 0<v<10000 = last-4 of seconds (expanded from the file's range, rollover-aware); >=10000 explicit. Clips saved RECT/HYPER/DNN/C5P stacks to the time window // By Claude on 06/14/2026
	public double   time_to =        -1.0;  // timing ROI end (timestamp seconds): same convention as time_from; the whole 'to' second is included // By Claude on 06/14/2026

	private String validKernelTest() { // guard a stale/unknown corr-xml value against the registry -> "none" // By Claude on 07/12/2026
		for (String s : KERNEL_TESTS) if (s.equals(this.kernel_test)) return s;
		return KERNEL_TESTS[0];
	}

	public void dialogQuestions(GenericJTabbedDialogMcp gd) {
		gd.addMessage("=== CUAS RT flow selection ==="); // By Codex on 07/15/2026: stable visual locator for run instructions
		gd.addCheckbox ("CUAS realtime enable",                      this.en,
				"Enable testing of the realtime CUAS detection.");
		gd.addCheckbox ("CUAS RT photometric calibration",           this.calib, // By Claude on 07/03/2026
				"First step of the RT processing flow: per-sensor photometric (re)calibration - fit a+b*x over safe (weak/far) tiles, fold into the 16+16 lwir offsets/scales, apply and save (reference scene INTERFRAME corr-xml, quadCLT_main for the main configuration). Bypass when off.");
		gd.addCheckbox ("CUAS RT conditioning test",                 this.cond_test,
				"Isolation test inside the en branch: build QuadCLT instances (borrowed calibration), then print per-sensor average spread (CuasMotion.perSensorAveragesFromTD) instead of normal RT detection. Well-calibrated -> the 16 sensor averages match (spread ~0).");
		gd.addCheckbox ("CUAS RT pose test",                         this.pose_test, // By Claude on 07/03/2026
				"RT pose-adjustment prototype (phase A): re-generate per-scene 3-angle poses against the virtual-center reference (ascending, prediction-seeded) instead of RT detection. Writes -POSE-RT-TEST.csv and a fitted-vs-stored summary.");

		gd.addMessage("=== Pose RT tile selection and input ==="); // By Codex on 07/15/2026
		gd.addNumericField("Pose test reliable strength",            this.pose_str, 5,7,"", // By Claude on 07/03/2026
				"Tile selection for the pose test: combo-DSI strength threshold (1.0 gives ~ the old getReliableTiles population).");
		gd.addNumericField("Pose test outlier gate k (NMAD)",        this.pose_dxy_k, 5,7,"", // By Claude on 07/04/2026
				"Keep tiles with max-over-scenes residual <= median + k*NMAD of finite per-tile maxes (scale-free; NaN in any scene always rejected). <=0 - skip the gate.");
		gd.addNumericField("Pose test number of best tiles",         this.pose_num_tiles, 0,7,"", // By Claude on 07/04/2026
				"After the gate keep this many best (smallest max-residual) tiles - the RT compute budget. <=0 - no cap.");
		gd.addNumericField("Pose tile selection border ring (tiles)", this.pose_shrink, 0,7,"", // By Claude on 07/13/2026
				"Exclude tiles within this many tiles of the tile-array border before selection: the OOB band is confined to the frame border, so the ring guarantees every selected tile keeps all 16 sensors interior at every scene pose (enables the fixed GPU tile list + OOB-pass bypass). 0 = off (legacy).");
		gd.addCheckbox ("Pose test raw-jp4 ingest (A2)",             this.pose_raw, // By Claude on 07/05/2026
				"Preload every RAW /jp4/ scene before timing; optionally apply borrowed Row/Col profiles during setup, then condition with current scale/offset/FPN/DC and force-upload. File I/O is excluded from RT timing.");
		gd.addCheckbox ("Pace preloaded pose test at 60 FPS",        this.pose_pace, // By Codex on 07/15/2026
				"OFF = maximum-throughput run. ON = release all inputs at 60 Hz without skipping and report bounded-queue, latency and deadline statistics. Applies only when the all-scene preload succeeds.");
		gd.addCheckbox ("Pose test lean correlation (B)",            this.pose_lean, // By Claude on 07/05/2026
				"Phase B measurement: TD-average the 16 sensors, then ONE conj-multiply vs the virtual-center TD -> FZ-normalize -> PD -> argmax+eigen -> 3-angle LMA. v1 has NO motion-blur compensation (compare vs the NOMB baseline).");

		gd.addMessage("=== Pose RT debug modes and saved products ==="); // By Codex on 07/15/2026
		gd.addCheckbox ("Pose test ALL tiles (ignore calibration)",   this.pose_full, // By Claude on 07/04/2026
				"DEBUG: use all strength-selected tiles (~1074); the tile-selection calibration is neither read nor written.");
		gd.addCheckbox ("Pose test save 2D correlations",            this.pose_corr_save, // By Claude on 07/04/2026
				"DEBUG: save per-scene pixel-domain 2D correlations vs the virtual center (-POSE-RT-CORR2D, z=scenes, last LMA cycle). Lean engine only.");
		gd.addCheckbox ("Pose test save composite scenes",           this.pose_img_save, // By Claude on 07/04/2026
				"DEBUG: save the rendered composite (TD-averaged, grid-transformed) scenes correlated against the virtual center (-POSE-RT-COMPOSITE, z=scenes) + the center reference render (-POSE-RT-CENTER-REF). Lean engine only.");
		gd.addCheckbox ("Pose test stored poses (no LMA)",           this.pose_stored, // By Claude on 07/04/2026
				"DEBUG: measure/render every scene at its STORED pose, skip the LMA entirely - decouples the task/render/correlation chain from the solver. Lean engine only.");

		gd.addMessage("=== Pose RT LMA, peak and motion-blur controls ==="); // By Codex on 07/15/2026
		gd.addCheckbox ("Pose lean uniform MB vector (v2)",          this.pose_mb_uniform, // By Claude on 07/12/2026
				"Lean v2 (CUAS): ONE motion-blur vector per scene shared by all tiles - constant-rpm flow is uniform up to the (small) roll component; wobble is second-degree. Same Jacobian-times-rates as the per-tile oracle, evaluated at the frame center. OFF = legacy per-tile getMotionBlur (A/B).");
		gd.addNumericField("Pose lean fixed LMA cycles",             this.pose_cycles, 0,7,"", // By Claude on 07/12/2026
				"Lean v2 (CUAS): run EXACTLY this many measure<->solve cycles per scene (near-identical scenes need a constant count; fixed count = static GPU launch shape). A QC line flags scenes missing the legacy exit threshold. 0 = legacy convergence-based exit (imp.max_cycles + exit_change).");
		gd.addNumericField("Pose lean initial LMA lambda",           this.pose_lambda, 6,8,"", // By Claude on 07/12/2026
				"Initial lambda of the INNER pose LMA (restarts every outer cycle). The legacy 0.1 start + 0.1%-improvement inner exit under-relaxes the outer loop (~0.8/cycle decay, 6-13 cycles). Near-zero = ~Gauss-Newton first steps for the near-linear 3-angle problem. 0 = legacy ilp.ilma_lambda.");
		gd.addNumericField("Pose lean max inner LMA iterations",     this.pose_max_lma, 0,3,"", // By Claude on 07/13/2026
				"Inner LMA cap for the LEAN pose only (imp 'Max LMA iterations' stays for other applications). 1 = validated CUAS static shape (near-GN first step reaches the optimum; the second step only confirms). 0 = legacy imp.max_LMA.");
		gd.addNumericField("Pose peak recentering passes",           this.pose_recenter, 0,3,"", // By Claude on 07/13/2026
				"Rung-2 frozen GPU peak contract: cosine-mask recentering passes over the eigen-ellipse (the 15-arg getMaxXYCmEig refinement; helps wide lean peaks). 0 = single-pass (the validated baseline); 2 = the oracle engine's imp 'Number of recentering passes'. A/B by pose quality before enabling.");
		gd.addNumericField("Pose peak envelope de-bias fraction",    this.pose_debias, 5,7,"", // By Claude on 07/13/2026
				"Fraction of the MCLT window-autocorr envelope divided out of the correlation before peak extraction (argmax under-reports offsets by ~0.75-0.9x through the envelope). 0 = off (default, bit-identical); 1 = full divide. Enabling needs its own A/B run.");
		gd.addNumericField("Pose lean inner-LMA debug level",        this.pose_lma_debug, 0,3,"", // By Claude on 07/12/2026
				"0 = quiet (also hides the per-scene 'CuasPoseRT cycles:' trace; >=1 shows it); 2 = one line per INNER LMA step (good/done flags, full/pure RMS, lambda); 3-4 = deeper solver dumps. VERBOSE at >=2 - for short investigation runs.");
		gd.addNumericField("Pose freeze conditioning at cycle",      this.pose_freeze_cycle, 0,3,"", // By Claude on 07/16/2026
				"Freeze lean-pose LMA weights/eigen at this full-prepare count; later cycles reuse them (light prepare). 0 = never (re-derive every cycle, highest accuracy); 2 = recommended (post-first-correction measurement); 1 = falsified (blurry cycle-1 conditioning).");
		gd.addCheckbox ("Pose scene as ONE GPU DP entry",            this.pose_scene_dp, // By Claude on 07/17/2026
				"DP rung D4: the whole per-scene pose solve (cycles x measure+prepare+LMA step) as ONE device entry, one end-of-scene readback. Scene 0 runs the host-driven loop and is replayed through the DP entry as a one-shot bit-exact oracle; FAIL disables DP for the run. Ineligible configs (JCuda, non-uniform MB, convergence exit, inner cap != 1, freeze != 0, debug saves) fall back automatically. OFF = the host-driven (B3) loop.");
		gd.addCheckbox ("Overlap next-scene conditioning+H2D with pose DP", this.pose_h2d_overlap, // By Claude on 07/17/2026
				"D5 overlap: while scene N's DP entry runs, condition scene N+1 into the other device image-set ring slot on the copy stream - the conditioning+H2D stage hides under the chain (~20.9 -> ~15.5 ms/scene). Requires the DP entry + the preloaded harness; any failure reverts to the serial order for the rest of the run. OFF = serial condition-then-solve (the A/B knob).");

		gd.addMessage("=== RT render diagnostics ==="); // By Codex on 07/15/2026
		gd.addCheckbox ("CUAS RT render (full product)",             this.rend_test, // By Claude on 07/05/2026
				"Full RT-chain render: raw jp4 -> conditioning -> virtual-grid render at borrowed stored poses/ERS; saves -CUAS-RT-RENDER [s00..s15+merged][scenes], comparable to the -CUAS-*-DBG oracle products. NON-exclusive: runs AFTER the pose stage when both are ON.");
		gd.addCheckbox ("RT render LoG A/B (folded kernels)",        this.log_test, // By Claude on 07/06/2026
				"With the RT render ON: also save -CUAS-RT-RENDER-LOG-ORACLE (the product convolved with the EXISTING pre-DNN pixel-domain LoG, LINEAR) and -CUAS-RT-RENDER-LOG-FOLDED (same render with the LoG FOLDED into the GPU aberration kernels - no pixel convolution; original kernels restored after). Compare offline: the aberration+LoG kernel-fold validation (roadmap RT-seed step 1b).");
		gd.addCheckbox ("RT render LoG isolation (identity krnl)",   this.log_ident, // By Claude on 07/06/2026
				"With the RT render ON: render with IDENTITY kernels (-ID, aberrations skipped), apply the pixel LoG (-ID-LOG-ORACLE), then render with PURE-LoG kernels (-LOG-ONLY). Isolates the LoG fold mechanism from the aberration-kernel content: persistent -LOG-ONLY vs -ID-LOG-ORACLE residual = the fold is wrong; collapse to the wrap floor = kernel interaction. Two extra render passes.");

		gd.addMessage("=== CUDA/kernel and oracle diagnostics ==="); // By Codex on 07/15/2026
		gd.addChoice   ("GPU kernel test (one per run)",             KERNEL_TESTS, validKernelTest(), // By Claude on 07/12/2026
				"EXCLUSIVE diagnostic: run the selected CUDA kernel's CPU oracle on live GPU data and export a self-describing testdata case (<model>/testdata/<kernel>) for the standalone tile_processor_gpu test (NSight-debuggable, tests_bin/test_<kernel> --data <case> --tol 0). One kernel per Java run; also imports/compares the C++ results/ when present from a previous run. 'none' = normal operation.");
		gd.addCheckbox ("Show selected convolution kernel",          this.show_kernels,
				"Show convolution kernels for selected in General tab tile (ktilex = tileX/2, ktileY=tileY/2.");
		
		gd.addCheckbox ("Save oracle DBG renders (11GB)",            this.dbg_fpixels, // By Claude on 07/05/2026
				"Save -CUAS-INDIVIDUAL-CUAS-DBG (an EXTRA per-sensor render pass, ~11GB) and -CUAS-MERGED-CUAS-DBG during ingest. Turn OFF to save render time and disk once -CUAS-RT-RENDER (RT render test) is the trusted full render.");

		gd.addMessage("=== RT correlation and borrowed-center levels ==="); // By Codex on 07/15/2026
		gd.addNumericField("RT fat zero INTER (pose/motion)",        this.fz_inter, 1,9,"", // By Claude on 07/05/2026
				"RT-decoupled fat zero for INTERscene (pose/motion) correlations - the legacy gpu_fatz*/AUX parameters are not used by RT. For a single physical-pair amplitude; FZ ~ amplitude^2.");
		gd.addNumericField("RT fat zero INTRA (ranging)",            this.fz_intra, 1,9,"", // By Claude on 07/05/2026
				"RT-decoupled fat zero for INTRAscene (ranging/disparity) correlations (reserved).");
		gd.addNumericField("Center DC level (0 - auto)",              this.dc_center, 3,9,"counts", // By Claude on 07/05/2026
				"DC level subtracted from the borrowed center at appropriation (match the zero-sky scenes). 0 = AUTO: reuse the per-sequence value from <center>-RT-STATE.json, derive (sky-half median of the reference render) and store there when absent; erase the file/field to re-derive. Nonzero = manual override; this configuration value is never mutated.");

		gd.addMessage("=== 16-sensor TD consolidation: OOB source-margin priority ==="); // By Claude on 07/12/2026
		gd.addNumericField("OOB soft margin (support overhang)",      this.oob_soft, 1,7,"pix", // By Claude on 07/12/2026
				"Deprioritize a sensor whose tile center is closer than this to its SOURCE-frame edge (24x24 MCLT support overhangs - replicated synthetic rows): used only when no sensor has the tile deeper inside. ~12. 0 = tier disabled. Same value drives the GPU consolidate_oob kernel (JNA backend), the CPU fallback oracle and the avg_td_oob test export.");
		gd.addNumericField("OOB hard margin (core overhang)",         this.oob_hard, 1,7,"pix", // By Claude on 07/12/2026
				"Always skip a sensor whose tile center is closer than this to its source-frame edge (the 16x16 tile core itself overhangs). All 16 below -> tile poisoned (NaN), never a synthetic average. ~8. 0 = tier disabled; both margins 0 = v0 unfiltered (A/B knob).");

		gd.addMessage("=== RT conditioning: backend + Row/Col line noise ==="); // By Claude on 07/07/2026, backend Codex 07/15/2026
		gd.addCheckbox ("Condition scale/offset/FPN on GPU",         this.cond_gpu, // By Codex on 07/15/2026
				"Preloaded RT: OFF = double Java CPU oracle for A/B; ON = GPU after existing Row/Col profiles were applied during setup. GPU also requires fixed sequence DC and no quadratic term. The legacy direct reader requires Row/Col OFF for GPU.");
		gd.addCheckbox ("Subtract row/col noise (RT conditioning)",  this.rowcol_en, // By Claude on 07/07/2026
				"Preloaded RT: apply already-calculated per-scene profiles to raw input during setup using their prior corr-xml scales; do not calculate them. Turn OFF for data already corrected inside FLIR. The timed stage never performs Row/Col.");
		gd.addCheckbox ("Row/col high-pass profiles",                this.rowcol_hpf, // By Claude on 07/07/2026
				"High-pass the 1-D row/col average profiles before subtracting, preserving the low frequencies for the downstream LoG. Applies ONLY when the unsharp-mask sigma below is 0 - the UM measurement already band-limits, and stacking both under-removes mid-band line noise (measured x2).");
		gd.addNumericField("Row/col high-pass sigma",                this.rowcol_hpf_sigma, 3,7,"pix", // By Claude on 07/07/2026
				"Gaussian sigma of the profile high-pass, ~ the LoG scale (the noise band the LoG would pass).");
		gd.addNumericField("Row/col unsharp mask sigma (0 - off)",   this.rowcol_um_sigma, 3,7,"pix", // By Claude on 07/07/2026
				"Measure the row/col profiles on an unsharp-masked copy (content suppression, borrowed from the oracle path) - the gate below then acts on residual counts. 0 = measure on the data as-is.");
		gd.addNumericField("Row/col maximal |value| (0 - no limit)", this.rowcol_max_abs, 3,9,"counts", // By Claude on 07/07/2026
				"Current direct-reader estimator: only average pixels with |UM residual| within this calibrated-count limit. 0 = no limit. Configs saved before 07/07 evening carry 0 - set 50 to enable.");
		gd.addNumericField("Row/col outlier weight",                 this.rowcol_outlier, 5,7,"x", // By Claude on 07/07/2026
				"Weight of out-of-range pixels in the line averages (prevents undefined values on all-outlier lines).");
		gd.addNumericField("Fill small foreground clusters, tiles",  this.disp_fg_tiles, 0,3,"tiles", // By Claude on 07/07/2026
				"Disparity conditioning: fill connected foreground clusters up to this many tiles (local near-outliers, e.g. the 3-tile roadside sign) with zero-curvature background disparity - a drone flying exactly behind stays detectable. 0 = off.");
		gd.addNumericField("Foreground outlier threshold",           this.disp_fg_over, 3,7,"pix", // By Claude on 07/07/2026
				"A tile is a near-outlier when its disparity exceeds the local 7x7 median by this many pixels.");

		gd.addMessage("=== LoG prefilter ===");
		gd.addNumericField("Optical PSF radius",                     this.psf_radius, 6,8,"pix",
				"Sensor optical  PSF radius for the LoG pre-filter.");
		gd.addNumericField("N-sigmas for LoG cutoff",                this.n_sigma, 6,8,"x",
				"Cutoff LoG kernel array, number of sigmas.");
		// rleak0 dialog field removed 2026-06-20 (LReLU conditioning now LINEAR, alpha=1.0); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		gd.addMessage("=== Temporal binary pyramid ===");
		gd.addNumericField("Temporal pyramid levels",                this.pyramid, 0,3,"",
				"Number of binary temporal pyramid levels.");
		// rleak_pyr dialog field removed 2026-06-20 (pyramid averaging now LINEAR, alpha=1.0); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		// 3d3 coarse-velocity path removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		gd.addMessage("=== Fine velocities layer ===");
		gd.addNumericField("Pixel decimate",                         this.pix_decimate, 0,3,"",
				"Decimate pixels (increase resolution).");
		gd.addNumericField("Velocity decimate",                      this.vel_decimate, 0,3,"",
				"Decimate velocities (increase velocity resolution).");
		gd.addNumericField("Velocities radius",                      this.vel_radius, 0,3,"",
				"Velocities radius in decimated samples.");
		gd.addCheckbox ("Filter by stronger 4d space neighbors",     this.vel_thresh_en,
				"Zero-out velocity components if they have stronger neighbors");
		gd.addNumericField("Velocities suppress radius",            this.vel_suppr_rad, 0,3,"",
				"Suppress weaker in this radius.");
		gd.addNumericField("Absolute threshold",                     this.vel_athresh, 6,8,"",
				"Discard this pixel-velocity if it has immediate neighbor (of 80=81-1) stronger by this valuediscard this pixel-velocity if it has immediate neighbor (of 80=81-1) stronger by this value.");
		gd.addNumericField("Relative thershold",                     this.vel_rthresh, 6,8,"",
				"Discard this pixel-velocity if it has immediate neighbor stronger by this value times stronger value.");

		gd.addNumericField("Remove weaker velocities",               this.vel_dbgmin, 6,8,"",
				"Debug feature for testing recurrent with strong targets - zero out weaker (set 10.0).");
		
		gd.addStringField ("Historic weight for 5D convolution",  IntersceneMatchParameters.doublesToString(temp_weights), 80,
				"Historic weights for 5D convolution ([0] is the latest sample). Will be normalized");

		gd.addMessage("=== Layer 2 recurrent accumulation buffer ==="); // By Claude on 06/09/2026
		gd.addCheckbox ("Enable recurrent buffer",                   this.recur_en, // By Claude on 06/09/2026
				"Maintain a recurrent 4D (pixel, velocity) accumulation buffer over the selected rectangle."); // By Claude on 06/09/2026
		gd.addNumericField("Update period",                          this.recur_period, 0,3,"time units", // By Claude on 06/09/2026
				"Time units between buffer updates. Equal to velocity decimation for integer-pixel shifts (1 px per minimum velocity)."); // By Claude on 06/09/2026
		gd.addNumericField("Measurement weight",                     this.recur_w, 6,8,"", // By Claude on 06/09/2026
				"Update rule: buf = leak*(1-w)*shift(buf) + w*conditioned(measurement). Gap decay = leak*(1-w) with fixed w."); // By Claude on 06/09/2026
		gd.addNumericField("Prediction leak",                        this.recur_leak, 6,8,"", // By Claude on 06/09/2026
				"Extra decay of the velocity-shifted prediction per update. Keep leak^n_gap >= 0.2-0.3 for expected dark gaps."); // By Claude on 06/09/2026
		gd.addNumericField("Adaptive weight threshold",              this.recur_wthresh, 6,8,"", // By Claude on 06/09/2026
				"If >0: per-pixel adaptive weight w_eff = w*tanh(strength/wthresh), dark frames give w_eff~0 (pure prediction). 0 - fixed w."); // By Claude on 06/09/2026
		gd.addNumericField("Velocity diffusion weight",              this.recur_spread, 6,8,"", // By Claude on 06/10/2026
				"Predict-step process noise: 3-tap (spread,1,spread) normalized diffusion over vx,vy after the shift. Lets the buffer maximum migrate between velocity cells (half-grid velocities). <=0 - off."); // By Claude on 06/10/2026
		gd.addNumericField("Max target cluster size",                this.recur_max_clust, 0,3,"", // By Claude on 06/09/2026
				"Survivor clusters up to this size are one target: fit a 4D half-cosine bump (3-pix half-period, half-pixel-grid center) and inject its full grid sampling. Larger clusters (weak linear signal) pass through unchanged."); // By Claude on 06/10/2026
		gd.addNumericField("Bump fit max peak ratio",                this.recur_fit_rat, 6,8,"", // By Claude on 06/10/2026
				"Reject the single-bump fit when per-survivor peak estimates (value/model_weight) disagree by more than this ratio; then each survivor injects its own single-point bump."); // By Claude on 06/10/2026
		gd.addNumericField("Re-sharpen blob threshold fraction",     this.recur_rs_frac, 6,8,"", // By Claude on 06/10/2026
				"After merging the measurement, peel buffer blobs (4D-connected cells above this fraction of the blob max) and re-fit each as a canonical half-cosine at its fractional centroid, conserving total energy. <=0 - off."); // By Claude on 06/10/2026
		gd.addNumericField("Re-sharpen min blob max",                this.recur_rs_min, 6,8,"", // By Claude on 06/10/2026
				"Stop peeling when the strongest remaining cell is below this (filter-output units); sub-threshold residue passes through unchanged."); // By Claude on 06/10/2026
		// C5P matched-filter / Bayes-posterior / whitening dialog fields removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		gd.addStringField ("C5P/DNN pyramid levels",                 IntersceneMatchParameters.intsToString(this.c5_levels), 40, // By Claude on 06/13/2026
				"Process the DNN front-end only on these pyramid levels (space/comma separated, e.g. \"2 3\"). Empty - all levels. Skips the heavy work on others - main speedup. Pyramid frames still build for all levels up to the max selected."); // By Claude on 06/13/2026
		gd.addStringField ("C5P DNN model (ONNX)",                   this.dnn_model, 60, // By Claude on 06/13/2026
				"Trained DNN front-end model location. Empty = disabled (use matched-filter/posterior path). Local path, scp user@host:/path (fetched to cache), or http(s) URL. Overrides any bundled resource - same default-vs-override scheme as the GPU kernel sources."); // By Claude on 06/13/2026
		gd.addStringField ("C5P Stage-2 vote-refine (ONNX)",         this.stage2_model, 60, // By Claude on 06/18/2026
				"v2 Stage-2 learned Hough-vote refine model. Empty = Stage-1 reg field only. When set (with a reg Stage-1 model) the reg branch adds the vote heatmap (-VOTE) and refined detection (-REFINED) views.");
		gd.addCheckbox    ("DNN remote (run on DGX)",                this.dnn_remote, // grouped with the model fields // By Claude on 06/20/2026
				"Run the DNN on the remote DGX inference server instead of local CPU: upload the conditioned stack once, the DGX builds the pyramid + full-res shift-and-stitch, returns full-frame {dx,dy,s,Vx,Vy} (-OFFSET) and ROI 121-cell softmax*s (-RECT/-HYPER-RECT). Local CPU path (+ recurrent feed) used when off."); // By Claude on 06/20/2026
		gd.addStringField ("DNN remote host:port",                   this.dnn_remote_host, 24, // By Claude on 06/20/2026
				"DGX inference server address for 'DNN remote' (default 192.168.0.62:5577)."); // By Claude on 06/20/2026
		gd.addStringField ("DNN remote model (DGX run dir)",         this.dnn_remote_model, 24, // By Claude on 06/20/2026
				"DGX-side run directory (containing model.pt) the auto-launched server loads, e.g. runs/weighted9_pm_s.");
		gd.addStringField ("DNN remote server src (empty=bundled)",  this.dnn_remote_srcdir, 40, // By Claude on 06/20/2026
				"Override dir for the DGX server scripts (infer_server.py / run_infer_server.sh): empty = bundled jar resource (cuas_dnn/); set = local dir. Same default-vs-override (bundled resource vs local repo) scheme as the GPU kernels - bundled is the working version, refresh it after server-script dev.");
		gd.addCheckbox    ("DNN local (in-process LibTorch)",        this.dnn_local, // By Claude on 06/27/2026
				"Run the DNN front-end in-process via native LibTorch (libtpdnn.so / JNA) instead of the remote Python server - identical L1+L2 result, no DGX/server. When set, overrides 'DNN remote'. Needs -Djna.library.path pointing at libtpdnn.so.");
		gd.addStringField ("DNN local model dir (empty=bundled)",    this.dnn_local_dir, 40, // By Claude on 06/27/2026
				"Override dir holding <model>/model.ts.pt (+ .meta.json) for 'DNN local': empty = bundled jar resource (cuas_dnn/). Same default-vs-override scheme as the kernels. Uses the same model names as the remote fields.");
		gd.addCheckbox    ("DNN Layer-2 (run on DGX)",               this.dnn_l2, // By Claude on 06/22/2026
				"Run the trained Layer-2 track-before-detect ConvGRU on the DGX after L1 (requires 'DNN remote'). -OFFSET then shows L2 {det,Vx,Vy} (L1's full-res non-ghostbusted field fed in, recurrence over time), titled -DNN-L2-. Uncheck to re-run the old L1 way."); // By Claude on 06/22/2026
		gd.addStringField ("DNN Layer-2 model (DGX run dir)",        this.dnn_l2_model, 24, // By Claude on 06/22/2026
				"DGX-side Layer-2 run directory (containing model.pt) the auto-launched server loads as RUN2=, e.g. runs/l2_v1.");
		gd.addNumericField("DNN s-threshold (VIZ ONLY)",             this.dnn_thresh, 6,8,"", // By Claude on 06/13/2026, viz-only 06/20/2026
				"VISUALIZATION ONLY - NaN's the -OFFSET Vx,Vy,dx,dy where s < this (0 = show all) so velocity shows only at detections. Does NOT gate Layer 2 (the recurrent always sees the full field) nor the -RECT/-HYPER-RECT data. Do NOT use for critical computation - it is a display mask.");
		gd.addCheckbox ("DNN recurrent feed: offset-splat",          this.dnn_recur_splat, // By Claude on 06/14/2026
				"Feeding the DNN field to the recurrent layer: unchecked = feed per-pixel field as-is; checked = splat each pixel to its fractional (px+dx,py+dy) so neighbours reinforce in one sub-pixel bin. Output gets a -SPLAT mark."); // By Claude on 06/14/2026
		gd.addNumericField("DNN recurrent feed scale",               this.dnn_recur_scale, 4,8,"", // By Claude on 06/14/2026
				"Multiply the DNN field (peaks ~0.1) by this before the recurrent feed so it reaches the recurrent's tuned scale (rs_min=1.0); ~10 -> peak ~1.0. Set 1 and instead lower recur_rs_min if you prefer."); // By Claude on 06/14/2026
		gd.addNumericField("DNN ghostbuster vmax",                   this.dnn_vmax, 4,8,"pix/frame", // By Claude on 06/15/2026
				"Zero DNN velocities beyond this radius (untrained corner cells) and discard pixels peaking there (s=0); match the model's training vmax_px (PM=1.4, base=1.0); <=0 disables.");
		// dnn_t8frac dialog field removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		gd.addNumericField("DNN patch size (RF)",                    this.dnn_patch, 0,3,"pix", // By Claude on 06/16/2026
				"Receptive-field / training patch the model was built at (24 = base/PM, 32 = larger-attention). MUST match the loaded model.");
		gd.addNumericField("DNN temporal stride",                    this.dnn_stride, 0,3,"slices", // By Claude on 06/14/2026
				"DNN output stride along the pyramid-level time axis: 1 = a fresh inference at every slice (testing, watch each temporal step); 4 = production (50% overlap of the window, matches the convolver's integer-pixel-shift cadence)."); // By Claude on 06/14/2026
		gd.addCheckbox ("Use synthetic input",                       this.synth_src, // By Claude on 06/11/2026
				"Read *-CUAS-SYNTHETIC-CUAS.tiff (generated test targets) instead of *-CUAS-MERGED-CUAS.tiff from the same model directory; all output titles get a -SYNTH mark."); // By Claude on 06/11/2026
		gd.addNumericField("Synthetic target peak",                   this.synth_scale, 6,8,"counts", // By Claude on 06/12/2026
				"Scale applied to the (peak-1 normalized) synthetic targets at load = target peak in counts. Reference: birds ~3, background sigma ~1.7, strong targets >30."); // By Claude on 06/12/2026
		gd.addNumericField("Synthetic bg frame averaging",            this.synth_bg_avg, 0,3,"frames", // By Claude on 06/20/2026
				"Synth quick-run: average this many consecutive REAL frames per output frame (LEV noise floor = 2^LEV: 2=LEV1, 4=LEV2, 8=LEV3) and force a single level. 1 = off (full pyramid)."); // By Claude on 06/20/2026
		gd.addCheckbox ("Subtract input temporal average",          this.subtract_avg, // By Claude on 06/14/2026
				"Subtract the per-pixel temporal average of the input (whole sequence) before LoG. Removes the static treeline edge and its tile-grid streak; moving targets are not in the average so they survive. Uses the whole sequence (not realtime - realtime would use a prior-run average)."); // By Claude on 06/14/2026
		gd.addCheckbox ("Synthetic over real background",            this.synth_bg, // By Claude on 06/12/2026
				"Add the real *-CUAS-MERGED-CUAS.tiff scene under the scaled synthetic targets (frames matched by timestamp label). Unchecked - clean targets on zero background (linear B measurement)."); // By Claude on 06/12/2026
		gd.addNumericField("Min newest-frame fraction",              this.min_frac, 6,8,"", // By Claude on 06/12/2026
				"Zero fine-velocity outputs where the newest frame contributes less than this fraction of the accumulated response (dark-frame feedforward gate). NONLINEAR - punches holes into ridge maxima; set 0 for linear/synthetic B-measurement runs."); // By Claude on 06/12/2026

		gd.addMessage("=== Debug, saving images ===");
		gd.addCheckbox ("Save full velocities hyperstack",           this.save_c5full,
				"Save fine velocities [direction][scene][subpixels].");
		gd.addCheckbox ("Save velocities for rectangle",             this.save_c5rect,
				"Save fine velocities for selected rectangle only [scene][flattened image].");
		gd.addCheckbox ("Save per-velocity hyperstacks",             this.save_c5hyper, // By Claude on 06/13/2026
				"HYPER-RECT views (bottom slider = velocity, second slider/scrollwheel = time) for the C5P output and one per posterior lambda - watch a low-SNR target evolve at a fixed velocity."); // By Claude on 06/13/2026
		gd.addStringField ("Output selection Rectangle",             IntersceneMatchParameters.rectangleToString(save_select), 40, "Selection Rectangle:left, top, width,height");
		gd.addNumericField("Time ROI from (s)",                      this.time_from, 3,12,"s", // 3 decimals (fixed) - stable round-trip on OK // By Claude on 06/14/2026
				"Timing ROI start: clips saved RECT/HYPER/DNN/C5P stacks to this time window. -1 = open. Convenience: enter the last 4 digits of the seconds (0<v<10000) and the high digits are guessed from the file's timestamp range (rollover-aware); >=10000 = explicit seconds."); // By Claude on 06/14/2026
		gd.addNumericField("Time ROI to (s)",                        this.time_to, 3,12,"s", // 3 decimals (fixed) - stable round-trip on OK // By Claude on 06/14/2026
				"Timing ROI end: same convention as 'from'. The whole 'to' second is included. -1 = open."); // By Claude on 06/14/2026
	}

	public void dialogAnswers(GenericJTabbedDialogMcp gd) {
		this.en =                  gd.getNextBoolean();
		this.calib =               gd.getNextBoolean(); // By Claude on 07/03/2026
		this.cond_test =           gd.getNextBoolean();
		this.pose_test =           gd.getNextBoolean(); // By Claude on 07/03/2026
		this.pose_str =            gd.getNextNumber();  // By Claude on 07/03/2026
		this.pose_dxy_k =          gd.getNextNumber();       // By Claude on 07/04/2026
		this.pose_num_tiles =(int) gd.getNextNumber();       // By Claude on 07/04/2026
		this.pose_shrink =   (int) gd.getNextNumber();       // By Claude on 07/13/2026
		this.pose_raw =            gd.getNextBoolean();      // By Claude on 07/05/2026
		this.pose_pace =           gd.getNextBoolean();      // By Codex on 07/15/2026
		this.pose_lean =           gd.getNextBoolean();      // By Claude on 07/05/2026
		this.pose_full =           gd.getNextBoolean();      // By Claude on 07/04/2026
		this.pose_corr_save =      gd.getNextBoolean();      // By Claude on 07/04/2026
		this.pose_img_save =       gd.getNextBoolean();      // By Claude on 07/04/2026
		this.pose_stored =         gd.getNextBoolean();      // By Claude on 07/04/2026
		this.pose_mb_uniform =     gd.getNextBoolean();      // By Claude on 07/12/2026
		this.pose_cycles =   (int) gd.getNextNumber();       // By Claude on 07/12/2026
		this.pose_lambda =         gd.getNextNumber();       // By Claude on 07/12/2026
		this.pose_max_lma =  (int) gd.getNextNumber();       // By Claude on 07/13/2026
		this.pose_recenter = (int) gd.getNextNumber();       // By Claude on 07/13/2026
		this.pose_debias =         gd.getNextNumber();       // By Claude on 07/13/2026
		this.pose_lma_debug =(int) gd.getNextNumber();       // By Claude on 07/12/2026
		this.pose_freeze_cycle =(int) gd.getNextNumber();    // By Claude on 07/16/2026
		this.pose_scene_dp =       gd.getNextBoolean();      // By Claude on 07/17/2026
		this.pose_h2d_overlap =    gd.getNextBoolean();      // By Claude on 07/17/2026
		this.rend_test =           gd.getNextBoolean();      // By Claude on 07/05/2026
		this.log_test =            gd.getNextBoolean();      // By Claude on 07/06/2026
		this.log_ident =           gd.getNextBoolean();      // By Claude on 07/06/2026
		this.kernel_test =         KERNEL_TESTS[gd.getNextChoiceIndex()]; // By Claude on 07/12/2026
		this.show_kernels =        gd.getNextBoolean();
		this.dbg_fpixels =         gd.getNextBoolean();      // By Claude on 07/05/2026
		this.fz_inter =            gd.getNextNumber();       // By Claude on 07/05/2026
		this.fz_intra =            gd.getNextNumber();       // By Claude on 07/05/2026
		this.dc_center =           gd.getNextNumber();       // By Claude on 07/05/2026
		this.oob_soft =            gd.getNextNumber();       // By Claude on 07/12/2026
		this.oob_hard =            gd.getNextNumber();       // By Claude on 07/12/2026

		this.cond_gpu =            gd.getNextBoolean();      // By Codex on 07/15/2026
		this.rowcol_en =           gd.getNextBoolean();      // By Claude on 07/07/2026
		this.rowcol_hpf =          gd.getNextBoolean();      // By Claude on 07/07/2026
		this.rowcol_hpf_sigma =    gd.getNextNumber();       // By Claude on 07/07/2026
		this.rowcol_um_sigma =     gd.getNextNumber();       // By Claude on 07/07/2026
		this.rowcol_max_abs =      gd.getNextNumber();       // By Claude on 07/07/2026
		this.rowcol_outlier =      gd.getNextNumber();       // By Claude on 07/07/2026
		this.disp_fg_tiles = (int) gd.getNextNumber();       // By Claude on 07/07/2026
		this.disp_fg_over =        gd.getNextNumber();       // By Claude on 07/07/2026

		this.psf_radius =          gd.getNextNumber();
		this.n_sigma =             gd.getNextNumber();
		// rleak0 getNext removed 2026-06-20 (LReLU now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		this.pyramid =       (int) gd.getNextNumber();
		// rleak_pyr getNext removed 2026-06-20 (LReLU now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		// 3d3 coarse-velocity path removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		this.pix_decimate =  (int) gd.getNextNumber();
		this.vel_decimate =  (int) gd.getNextNumber();
		this.vel_radius =    (int) gd.getNextNumber();
		
		this.vel_thresh_en =       gd.getNextBoolean();
		this.vel_suppr_rad = (int) gd.getNextNumber();
		this.vel_athresh =         gd.getNextNumber();
		this.vel_rthresh =         gd.getNextNumber();
		this.vel_dbgmin =          gd.getNextNumber();
	    this.temp_weights = IntersceneMatchParameters.StringToDoubles(gd.getNextString(), 0);

		this.recur_en =            gd.getNextBoolean();     // By Claude on 06/09/2026
		this.recur_period =  (int) gd.getNextNumber();      // By Claude on 06/09/2026
		this.recur_w =             gd.getNextNumber();      // By Claude on 06/09/2026
		this.recur_leak =          gd.getNextNumber();      // By Claude on 06/09/2026
		this.recur_wthresh =       gd.getNextNumber();      // By Claude on 06/09/2026
		this.recur_spread =        gd.getNextNumber();      // By Claude on 06/09/2026
		this.recur_max_clust=(int) gd.getNextNumber();      // By Claude on 06/09/2026
		this.recur_fit_rat =       gd.getNextNumber();      // By Claude on 06/10/2026
		this.recur_rs_frac =       gd.getNextNumber();      // By Claude on 06/10/2026
		this.recur_rs_min =        gd.getNextNumber();      // By Claude on 06/10/2026
		// C5P matched-filter / Bayes-posterior / whitening getNext* removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		this.c5_levels =           IntersceneMatchParameters.StringToInts(gd.getNextString()); // By Claude on 06/13/2026
		this.dnn_model =           gd.getNextString().trim(); // By Claude on 06/13/2026
		this.stage2_model =        gd.getNextString().trim(); // By Claude on 06/18/2026
		this.dnn_remote =          gd.getNextBoolean();     // grouped with the model fields // By Claude on 06/20/2026
		this.dnn_remote_host =     gd.getNextString().trim(); // By Claude on 06/20/2026
		this.dnn_remote_model =    gd.getNextString().trim(); // By Claude on 06/20/2026
		this.dnn_remote_srcdir =   gd.getNextString().trim(); // By Claude on 06/20/2026
		this.dnn_local =           gd.getNextBoolean();     // By Claude on 06/27/2026
		this.dnn_local_dir =       gd.getNextString().trim(); // By Claude on 06/27/2026
		this.dnn_l2 =              gd.getNextBoolean();     // By Claude on 06/22/2026
		this.dnn_l2_model =        gd.getNextString().trim(); // By Claude on 06/22/2026
		this.dnn_thresh =          gd.getNextNumber();      // By Claude on 06/13/2026
		this.dnn_recur_splat =     gd.getNextBoolean();     // By Claude on 06/14/2026
		this.dnn_recur_scale =     gd.getNextNumber();      // By Claude on 06/14/2026
		this.dnn_vmax =            gd.getNextNumber();      // By Claude on 06/15/2026
		// dnn_t8frac getNext removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		this.dnn_patch =     (int) gd.getNextNumber();      // By Claude on 06/16/2026
		this.dnn_stride =    (int) gd.getNextNumber();      // By Claude on 06/14/2026
		this.synth_src =           gd.getNextBoolean();     // By Claude on 06/11/2026
		this.synth_scale =         gd.getNextNumber();      // By Claude on 06/12/2026
		this.synth_bg_avg =        (int) gd.getNextNumber(); // By Claude on 06/20/2026
		this.subtract_avg =        gd.getNextBoolean();     // By Claude on 06/14/2026
		this.synth_bg =            gd.getNextBoolean();     // By Claude on 06/12/2026
		this.min_frac =            gd.getNextNumber();      // By Claude on 06/12/2026

		this.save_c5full =         gd.getNextBoolean();
		this.save_c5rect =         gd.getNextBoolean();
		this.save_c5hyper =        gd.getNextBoolean();     // By Claude on 06/13/2026
		this.save_select =         IntersceneMatchParameters.stringToRectangle(gd.getNextString());// Rectangle
		this.time_from =           gd.getNextNumber();      // By Claude on 06/14/2026
		this.time_to =             gd.getNextNumber();      // By Claude on 06/14/2026
	}

	public void setProperties(String prefix, Properties properties){
		properties.setProperty(prefix+"en",              this.en+"");             // boolean
		properties.setProperty(prefix+"calib",           this.calib+"");          // boolean // By Claude on 07/03/2026
		properties.setProperty(prefix+"cond_test",       this.cond_test+"");      // boolean
		properties.setProperty(prefix+"pose_test",       this.pose_test+"");      // boolean // By Claude on 07/03/2026
		properties.setProperty(prefix+"pose_str",        this.pose_str+"");       // double  // By Claude on 07/03/2026
		properties.setProperty(prefix+"pose_dxy_k",      this.pose_dxy_k+"");     // double  // By Claude on 07/04/2026
		properties.setProperty(prefix+"pose_num_tiles",  this.pose_num_tiles+""); // int     // By Claude on 07/04/2026
		properties.setProperty(prefix+"pose_shrink",     this.pose_shrink+"");    // int     // By Claude on 07/13/2026
		properties.setProperty(prefix+"pose_raw",        this.pose_raw+"");       // boolean // By Claude on 07/05/2026
		properties.setProperty(prefix+"pose_pace",       this.pose_pace+"");      // boolean // By Codex on 07/15/2026
		properties.setProperty(prefix+"pose_lean",       this.pose_lean+"");      // boolean // By Claude on 07/05/2026
		properties.setProperty(prefix+"pose_full",       this.pose_full+"");      // boolean // By Claude on 07/04/2026
		properties.setProperty(prefix+"pose_corr_save",  this.pose_corr_save+""); // boolean // By Claude on 07/04/2026
		properties.setProperty(prefix+"pose_img_save",   this.pose_img_save+"");  // boolean // By Claude on 07/04/2026
		properties.setProperty(prefix+"pose_stored",     this.pose_stored+"");    // boolean // By Claude on 07/04/2026
		properties.setProperty(prefix+"pose_mb_uniform", this.pose_mb_uniform+"");// boolean // By Claude on 07/12/2026
		properties.setProperty(prefix+"pose_cycles",     this.pose_cycles+"");    // int     // By Claude on 07/12/2026
		properties.setProperty(prefix+"pose_lambda",     this.pose_lambda+"");    // double  // By Claude on 07/12/2026
		properties.setProperty(prefix+"pose_max_lma",    this.pose_max_lma+"");   // int     // By Claude on 07/13/2026
		properties.setProperty(prefix+"pose_recenter",   this.pose_recenter+""); // int     // By Claude on 07/13/2026
		properties.setProperty(prefix+"pose_debias",     this.pose_debias+"");    // double  // By Claude on 07/13/2026
		properties.setProperty(prefix+"pose_lma_debug",  this.pose_lma_debug+""); // int     // By Claude on 07/12/2026
		properties.setProperty(prefix+"pose_freeze_cycle", this.pose_freeze_cycle+""); // int // By Claude on 07/16/2026
		properties.setProperty(prefix+"pose_scene_dp",   this.pose_scene_dp+"");  // boolean // By Claude on 07/17/2026
		properties.setProperty(prefix+"pose_h2d_overlap",this.pose_h2d_overlap+"");// boolean // By Claude on 07/17/2026
		properties.setProperty(prefix+"rend_test",       this.rend_test+"");      // boolean // By Claude on 07/05/2026
		properties.setProperty(prefix+"log_test",        this.log_test+"");       // boolean // By Claude on 07/06/2026
		properties.setProperty(prefix+"log_ident",       this.log_ident+"");      // boolean // By Claude on 07/06/2026
		properties.setProperty(prefix+"kernel_test",     this.kernel_test+"");    // String  // By Claude on 07/12/2026
		properties.setProperty(prefix+"show_kernels",    this.show_kernels+"");   // boolean
		properties.setProperty(prefix+"dbg_fpixels",     this.dbg_fpixels+"");    // boolean // By Claude on 07/05/2026
		properties.setProperty(prefix+"fz_inter",        this.fz_inter+"");       // double  // By Claude on 07/05/2026
		properties.setProperty(prefix+"fz_intra",        this.fz_intra+"");       // double  // By Claude on 07/05/2026
		properties.setProperty(prefix+"dc_center",       this.dc_center+"");      // double  // By Claude on 07/05/2026
		properties.setProperty(prefix+"oob_soft",        this.oob_soft+"");       // double  // By Claude on 07/12/2026
		properties.setProperty(prefix+"oob_hard",        this.oob_hard+"");       // double  // By Claude on 07/12/2026

		properties.setProperty(prefix+"cond_gpu",        this.cond_gpu+"");       // boolean // By Codex on 07/15/2026
		properties.setProperty(prefix+"rowcol_en",       this.rowcol_en+"");      // boolean // By Claude on 07/07/2026
		properties.setProperty(prefix+"rowcol_hpf",      this.rowcol_hpf+"");     // boolean // By Claude on 07/07/2026
		properties.setProperty(prefix+"rowcol_hpf_sigma",this.rowcol_hpf_sigma+"");// double // By Claude on 07/07/2026
		properties.setProperty(prefix+"rowcol_um_sigma", this.rowcol_um_sigma+"");// double  // By Claude on 07/07/2026
		properties.setProperty(prefix+"rowcol_max_abs",  this.rowcol_max_abs+""); // double  // By Claude on 07/07/2026
		properties.setProperty(prefix+"rowcol_outlier",  this.rowcol_outlier+""); // double  // By Claude on 07/07/2026
		properties.setProperty(prefix+"disp_fg_tiles",   this.disp_fg_tiles+"");  // int     // By Claude on 07/07/2026
		properties.setProperty(prefix+"disp_fg_over",    this.disp_fg_over+"");   // double  // By Claude on 07/07/2026

		properties.setProperty(prefix+"psf_radius",      this.psf_radius+"");     // double
		properties.setProperty(prefix+"n_sigma",         this.n_sigma+"");        // double
		// rleak0 setProperty removed 2026-06-20 (LReLU now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		properties.setProperty(prefix+"pyramid",         this.pyramid+"");        // int
		// rleak_pyr setProperty removed 2026-06-20 (LReLU now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		// 3d3 coarse-velocity path removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		properties.setProperty(prefix+"pix_decimate",    this.pix_decimate+"");   // int
		properties.setProperty(prefix+"vel_decimate",    this.vel_decimate+"");   // int
		properties.setProperty(prefix+"vel_radius",      this.vel_radius+"");     // int
		properties.setProperty(prefix+"vel_thresh_en",   this.vel_thresh_en+"");  // boolean
		properties.setProperty(prefix+"vel_suppr_rad",   this.vel_suppr_rad+"");  // int
		properties.setProperty(prefix+"vel_athresh",     this.vel_athresh+"");    // double
		properties.setProperty(prefix+"vel_rthresh",     this.vel_rthresh+"");    // double
		properties.setProperty(prefix+"vel_dbgmin",      this.vel_dbgmin+"");     // double
		properties.setProperty(prefix+"temp_weights", IntersceneMatchParameters.doublesToString(this.temp_weights));

		properties.setProperty(prefix+"recur_en",        this.recur_en+"");       // boolean // By Claude on 06/09/2026
		properties.setProperty(prefix+"recur_period",    this.recur_period+"");   // int     // By Claude on 06/09/2026
		properties.setProperty(prefix+"recur_w",         this.recur_w+"");        // double  // By Claude on 06/09/2026
		properties.setProperty(prefix+"recur_leak",      this.recur_leak+"");     // double  // By Claude on 06/09/2026
		properties.setProperty(prefix+"recur_wthresh",   this.recur_wthresh+"");  // double  // By Claude on 06/09/2026
		properties.setProperty(prefix+"recur_spread",    this.recur_spread+"");   // double  // By Claude on 06/09/2026
		properties.setProperty(prefix+"recur_max_clust", this.recur_max_clust+"");// int     // By Claude on 06/09/2026
		properties.setProperty(prefix+"recur_fit_rat",   this.recur_fit_rat+"");  // double  // By Claude on 06/10/2026
		properties.setProperty(prefix+"recur_rs_frac",   this.recur_rs_frac+"");  // double  // By Claude on 06/10/2026
		properties.setProperty(prefix+"recur_rs_min",    this.recur_rs_min+"");   // double  // By Claude on 06/10/2026
		// C5P matched-filter / Bayes-posterior / whitening setProperty removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		properties.setProperty(prefix+"c5_levels",       IntersceneMatchParameters.intsToString(this.c5_levels)); // int [] // By Claude on 06/13/2026
		properties.setProperty(prefix+"dnn_model",       this.dnn_model);         // String // By Claude on 06/13/2026
		properties.setProperty(prefix+"stage2_model",    this.stage2_model);      // String // By Claude on 06/18/2026
		properties.setProperty(prefix+"dnn_thresh",      this.dnn_thresh+"");     // double // By Claude on 06/13/2026
		properties.setProperty(prefix+"dnn_recur_splat", this.dnn_recur_splat+""); // boolean // By Claude on 06/14/2026
		properties.setProperty(prefix+"dnn_recur_scale", this.dnn_recur_scale+""); // double // By Claude on 06/14/2026
		properties.setProperty(prefix+"dnn_stride",      this.dnn_stride+"");     // int // By Claude on 06/14/2026
		properties.setProperty(prefix+"dnn_vmax",        this.dnn_vmax+"");       // double // By Claude on 06/15/2026
		// dnn_t8frac setProperty removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		properties.setProperty(prefix+"dnn_patch",       this.dnn_patch+"");      // int // By Claude on 06/16/2026
		properties.setProperty(prefix+"dnn_remote",      this.dnn_remote+"");     // boolean // By Claude on 06/20/2026
		properties.setProperty(prefix+"dnn_remote_host", this.dnn_remote_host);   // String // By Claude on 06/20/2026
		properties.setProperty(prefix+"dnn_remote_model", this.dnn_remote_model); // String // By Claude on 06/20/2026
		properties.setProperty(prefix+"dnn_remote_srcdir", this.dnn_remote_srcdir); // String // By Claude on 06/20/2026
		properties.setProperty(prefix+"dnn_local",       this.dnn_local+"");      // boolean // By Claude on 06/27/2026
		properties.setProperty(prefix+"dnn_local_dir",   this.dnn_local_dir);     // String // By Claude on 06/27/2026
		properties.setProperty(prefix+"dnn_l2",          this.dnn_l2+"");         // boolean // By Claude on 06/22/2026
		properties.setProperty(prefix+"dnn_l2_model",    this.dnn_l2_model);      // String // By Claude on 06/22/2026
		properties.setProperty(prefix+"synth_src",       this.synth_src+"");      // boolean // By Claude on 06/11/2026
		properties.setProperty(prefix+"synth_scale",     this.synth_scale+"");    // double  // By Claude on 06/12/2026
		properties.setProperty(prefix+"synth_bg_avg",    this.synth_bg_avg+"");   // int     // By Claude on 06/20/2026
		properties.setProperty(prefix+"subtract_avg",    this.subtract_avg+"");   // boolean // By Claude on 06/14/2026
		properties.setProperty(prefix+"synth_bg",        this.synth_bg+"");       // boolean // By Claude on 06/12/2026
		properties.setProperty(prefix+"min_frac",        this.min_frac+"");       // double  // By Claude on 06/12/2026

		properties.setProperty(prefix+"save_c5full",     this.save_c5full+"");    // boolean
		properties.setProperty(prefix+"save_c5rect",     this.save_c5rect+"");    // boolean
		properties.setProperty(prefix+"save_c5hyper",    this.save_c5hyper+"");   // boolean // By Claude on 06/13/2026
		properties.setProperty(prefix+"save_select",     IntersceneMatchParameters.rectangleToString(save_select)+"");  // Rectangle
		properties.setProperty(prefix+"time_from",       this.time_from+"");      // double // By Claude on 06/14/2026
		properties.setProperty(prefix+"time_to",         this.time_to+"");        // double // By Claude on 06/14/2026
	}

	public void getProperties(String prefix, Properties properties){
		if (properties.getProperty(prefix+"en")!=null)              this.en=Boolean.parseBoolean(properties.getProperty(prefix+"en"));
		if (properties.getProperty(prefix+"calib")!=null)           this.calib=Boolean.parseBoolean(properties.getProperty(prefix+"calib")); // By Claude on 07/03/2026
		if (properties.getProperty(prefix+"cond_test")!=null)       this.cond_test=Boolean.parseBoolean(properties.getProperty(prefix+"cond_test"));
		if (properties.getProperty(prefix+"pose_test")!=null)       this.pose_test=Boolean.parseBoolean(properties.getProperty(prefix+"pose_test")); // By Claude on 07/03/2026
		if (properties.getProperty(prefix+"pose_str")!=null)        this.pose_str=Double.parseDouble(properties.getProperty(prefix+"pose_str"));    // By Claude on 07/03/2026
		if (properties.getProperty(prefix+"pose_dxy_k")!=null)      this.pose_dxy_k=Double.parseDouble(properties.getProperty(prefix+"pose_dxy_k"));           // By Claude on 07/04/2026
		if (properties.getProperty(prefix+"pose_num_tiles")!=null)  this.pose_num_tiles=Integer.parseInt(properties.getProperty(prefix+"pose_num_tiles"));     // By Claude on 07/04/2026
		if (properties.getProperty(prefix+"pose_shrink")!=null)     this.pose_shrink=Integer.parseInt(properties.getProperty(prefix+"pose_shrink"));           // By Claude on 07/13/2026
		if (properties.getProperty(prefix+"pose_raw")!=null)        this.pose_raw=Boolean.parseBoolean(properties.getProperty(prefix+"pose_raw"));             // By Claude on 07/05/2026
		if (properties.getProperty(prefix+"pose_pace")!=null)       this.pose_pace=Boolean.parseBoolean(properties.getProperty(prefix+"pose_pace"));           // By Codex on 07/15/2026
		if (properties.getProperty(prefix+"pose_lean")!=null)       this.pose_lean=Boolean.parseBoolean(properties.getProperty(prefix+"pose_lean"));           // By Claude on 07/05/2026
		if (properties.getProperty(prefix+"pose_full")!=null)       this.pose_full=Boolean.parseBoolean(properties.getProperty(prefix+"pose_full"));           // By Claude on 07/04/2026
		if (properties.getProperty(prefix+"pose_corr_save")!=null)  this.pose_corr_save=Boolean.parseBoolean(properties.getProperty(prefix+"pose_corr_save")); // By Claude on 07/04/2026
		if (properties.getProperty(prefix+"pose_img_save")!=null)   this.pose_img_save=Boolean.parseBoolean(properties.getProperty(prefix+"pose_img_save"));   // By Claude on 07/04/2026
		if (properties.getProperty(prefix+"pose_stored")!=null)     this.pose_stored=Boolean.parseBoolean(properties.getProperty(prefix+"pose_stored"));       // By Claude on 07/04/2026
		if (properties.getProperty(prefix+"pose_mb_uniform")!=null) this.pose_mb_uniform=Boolean.parseBoolean(properties.getProperty(prefix+"pose_mb_uniform")); // By Claude on 07/12/2026
		if (properties.getProperty(prefix+"pose_cycles")!=null)     this.pose_cycles=Integer.parseInt(properties.getProperty(prefix+"pose_cycles"));           // By Claude on 07/12/2026
		if (properties.getProperty(prefix+"pose_lambda")!=null)     this.pose_lambda=Double.parseDouble(properties.getProperty(prefix+"pose_lambda"));         // By Claude on 07/12/2026
		if (properties.getProperty(prefix+"pose_max_lma")!=null)    this.pose_max_lma=Integer.parseInt(properties.getProperty(prefix+"pose_max_lma"));         // By Claude on 07/13/2026
		if (properties.getProperty(prefix+"pose_recenter")!=null)   this.pose_recenter=Integer.parseInt(properties.getProperty(prefix+"pose_recenter"));       // By Claude on 07/13/2026
		if (properties.getProperty(prefix+"pose_debias")!=null)     this.pose_debias=Double.parseDouble(properties.getProperty(prefix+"pose_debias"));         // By Claude on 07/13/2026
		if (properties.getProperty(prefix+"pose_lma_debug")!=null)  this.pose_lma_debug=Integer.parseInt(properties.getProperty(prefix+"pose_lma_debug"));     // By Claude on 07/12/2026
		if (properties.getProperty(prefix+"pose_freeze_cycle")!=null) this.pose_freeze_cycle=Integer.parseInt(properties.getProperty(prefix+"pose_freeze_cycle")); // By Claude on 07/16/2026
		if (properties.getProperty(prefix+"pose_scene_dp")!=null)   this.pose_scene_dp=Boolean.parseBoolean(properties.getProperty(prefix+"pose_scene_dp"));       // By Claude on 07/17/2026
		if (properties.getProperty(prefix+"pose_h2d_overlap")!=null) this.pose_h2d_overlap=Boolean.parseBoolean(properties.getProperty(prefix+"pose_h2d_overlap")); // By Claude on 07/17/2026
		if (properties.getProperty(prefix+"rend_test")!=null)       this.rend_test=Boolean.parseBoolean(properties.getProperty(prefix+"rend_test"));           // By Claude on 07/05/2026
		if (properties.getProperty(prefix+"log_test")!=null)        this.log_test=Boolean.parseBoolean(properties.getProperty(prefix+"log_test"));             // By Claude on 07/06/2026
		if (properties.getProperty(prefix+"log_ident")!=null)       this.log_ident=Boolean.parseBoolean(properties.getProperty(prefix+"log_ident"));           // By Claude on 07/06/2026
		if (properties.getProperty(prefix+"kernel_test")!=null)     this.kernel_test=properties.getProperty(prefix+"kernel_test");                             // By Claude on 07/12/2026
		if (properties.getProperty(prefix+"show_kernels")!=null)    this.show_kernels=Boolean.parseBoolean(properties.getProperty(prefix+"show_kernels"));
		if (properties.getProperty(prefix+"dbg_fpixels")!=null)     this.dbg_fpixels=Boolean.parseBoolean(properties.getProperty(prefix+"dbg_fpixels"));       // By Claude on 07/05/2026
		if (properties.getProperty(prefix+"fz_inter")!=null)        this.fz_inter=Double.parseDouble(properties.getProperty(prefix+"fz_inter"));               // By Claude on 07/05/2026
		if (properties.getProperty(prefix+"fz_intra")!=null)        this.fz_intra=Double.parseDouble(properties.getProperty(prefix+"fz_intra"));               // By Claude on 07/05/2026
		if (properties.getProperty(prefix+"dc_center")!=null)       this.dc_center=Double.parseDouble(properties.getProperty(prefix+"dc_center"));             // By Claude on 07/05/2026
		if (properties.getProperty(prefix+"oob_soft")!=null)        this.oob_soft=Double.parseDouble(properties.getProperty(prefix+"oob_soft"));               // By Claude on 07/12/2026
		if (properties.getProperty(prefix+"oob_hard")!=null)        this.oob_hard=Double.parseDouble(properties.getProperty(prefix+"oob_hard"));               // By Claude on 07/12/2026

		if (properties.getProperty(prefix+"cond_gpu")!=null)        this.cond_gpu=Boolean.parseBoolean(properties.getProperty(prefix+"cond_gpu"));              // By Codex on 07/15/2026
		if (properties.getProperty(prefix+"rowcol_en")!=null)       this.rowcol_en=Boolean.parseBoolean(properties.getProperty(prefix+"rowcol_en"));           // By Claude on 07/07/2026
		if (properties.getProperty(prefix+"rowcol_hpf")!=null)      this.rowcol_hpf=Boolean.parseBoolean(properties.getProperty(prefix+"rowcol_hpf"));         // By Claude on 07/07/2026
		if (properties.getProperty(prefix+"rowcol_hpf_sigma")!=null)this.rowcol_hpf_sigma=Double.parseDouble(properties.getProperty(prefix+"rowcol_hpf_sigma"));// By Claude on 07/07/2026
		if (properties.getProperty(prefix+"rowcol_um_sigma")!=null) this.rowcol_um_sigma=Double.parseDouble(properties.getProperty(prefix+"rowcol_um_sigma")); // By Claude on 07/07/2026
		if (properties.getProperty(prefix+"rowcol_max_abs")!=null)  this.rowcol_max_abs=Double.parseDouble(properties.getProperty(prefix+"rowcol_max_abs"));   // By Claude on 07/07/2026
		if (properties.getProperty(prefix+"rowcol_outlier")!=null)  this.rowcol_outlier=Double.parseDouble(properties.getProperty(prefix+"rowcol_outlier"));   // By Claude on 07/07/2026
		if (properties.getProperty(prefix+"disp_fg_tiles")!=null)   this.disp_fg_tiles=Integer.parseInt(properties.getProperty(prefix+"disp_fg_tiles"));      // By Claude on 07/07/2026
		if (properties.getProperty(prefix+"disp_fg_over")!=null)    this.disp_fg_over=Double.parseDouble(properties.getProperty(prefix+"disp_fg_over"));      // By Claude on 07/07/2026

		if (properties.getProperty(prefix+"psf_radius")!=null)      this.psf_radius=Double.parseDouble(properties.getProperty(prefix+"psf_radius"));
		if (properties.getProperty(prefix+"n_sigma")!=null)         this.n_sigma=Double.parseDouble(properties.getProperty(prefix+"n_sigma"));
		// rleak0 getProperty removed 2026-06-20 (LReLU now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		if (properties.getProperty(prefix+"pyramid")!=null)         this.pyramid=Integer.parseInt(properties.getProperty(prefix+"pyramid"));
		// rleak_pyr getProperty removed 2026-06-20 (LReLU now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		// 3d3 coarse-velocity path removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026

		if (properties.getProperty(prefix+"pix_decimate")!=null)    this.pix_decimate=Integer.parseInt(properties.getProperty(prefix+"pix_decimate"));
		if (properties.getProperty(prefix+"vel_decimate")!=null)    this.vel_decimate=Integer.parseInt(properties.getProperty(prefix+"vel_decimate"));
		if (properties.getProperty(prefix+"vel_radius")!=null)      this.vel_radius=Integer.parseInt(properties.getProperty(prefix+"vel_radius"));
		if (properties.getProperty(prefix+"vel_thresh_en")!=null)   this.vel_thresh_en=Boolean.parseBoolean(properties.getProperty(prefix+"vel_thresh_en"));
		if (properties.getProperty(prefix+"vel_suppr_rad")!=null)   this.vel_suppr_rad=Integer.parseInt(properties.getProperty(prefix+"vel_suppr_rad"));
		if (properties.getProperty(prefix+"vel_athresh")!=null)     this.vel_athresh=Double.parseDouble(properties.getProperty(prefix+"vel_athresh"));
		if (properties.getProperty(prefix+"vel_rthresh")!=null)     this.vel_rthresh=Double.parseDouble(properties.getProperty(prefix+"vel_rthresh"));
		if (properties.getProperty(prefix+"vel_dbgmin")!=null)      this.vel_dbgmin=Double.parseDouble(properties.getProperty(prefix+"vel_dbgmin"));
		if (properties.getProperty(prefix+"temp_weights")!=null) this.temp_weights= IntersceneMatchParameters.StringToDoubles(properties.getProperty(prefix+"temp_weights"),0); // use 0

		if (properties.getProperty(prefix+"recur_en")!=null)        this.recur_en=Boolean.parseBoolean(properties.getProperty(prefix+"recur_en"));         // By Claude on 06/09/2026
		if (properties.getProperty(prefix+"recur_period")!=null)    this.recur_period=Integer.parseInt(properties.getProperty(prefix+"recur_period"));     // By Claude on 06/09/2026
		if (properties.getProperty(prefix+"recur_w")!=null)         this.recur_w=Double.parseDouble(properties.getProperty(prefix+"recur_w"));             // By Claude on 06/09/2026
		if (properties.getProperty(prefix+"recur_leak")!=null)      this.recur_leak=Double.parseDouble(properties.getProperty(prefix+"recur_leak"));       // By Claude on 06/09/2026
		if (properties.getProperty(prefix+"recur_wthresh")!=null)   this.recur_wthresh=Double.parseDouble(properties.getProperty(prefix+"recur_wthresh")); // By Claude on 06/09/2026
		if (properties.getProperty(prefix+"recur_spread")!=null)    this.recur_spread=Double.parseDouble(properties.getProperty(prefix+"recur_spread"));   // By Claude on 06/09/2026
		if (properties.getProperty(prefix+"recur_max_clust")!=null) this.recur_max_clust=Integer.parseInt(properties.getProperty(prefix+"recur_max_clust")); // By Claude on 06/09/2026
		if (properties.getProperty(prefix+"recur_fit_rat")!=null)   this.recur_fit_rat=Double.parseDouble(properties.getProperty(prefix+"recur_fit_rat"));   // By Claude on 06/10/2026
		if (properties.getProperty(prefix+"recur_rs_frac")!=null)   this.recur_rs_frac=Double.parseDouble(properties.getProperty(prefix+"recur_rs_frac"));   // By Claude on 06/10/2026
		if (properties.getProperty(prefix+"recur_rs_min")!=null)    this.recur_rs_min=Double.parseDouble(properties.getProperty(prefix+"recur_rs_min"));     // By Claude on 06/10/2026

		// C5P matched-filter / Bayes-posterior / whitening getProperty removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		if (properties.getProperty(prefix+"c5_levels")!=null)       this.c5_levels= IntersceneMatchParameters.StringToInts(properties.getProperty(prefix+"c5_levels")); // By Claude on 06/13/2026
		if (properties.getProperty(prefix+"dnn_model")!=null)       this.dnn_model=(String) properties.getProperty(prefix+"dnn_model"); // By Claude on 06/13/2026
		if (properties.getProperty(prefix+"stage2_model")!=null)    this.stage2_model=(String) properties.getProperty(prefix+"stage2_model"); // By Claude on 06/18/2026
		if (properties.getProperty(prefix+"dnn_thresh")!=null)      this.dnn_thresh=Double.parseDouble(properties.getProperty(prefix+"dnn_thresh")); // By Claude on 06/13/2026
		if (properties.getProperty(prefix+"dnn_recur_splat")!=null) this.dnn_recur_splat=Boolean.parseBoolean(properties.getProperty(prefix+"dnn_recur_splat")); // By Claude on 06/14/2026
		if (properties.getProperty(prefix+"dnn_recur_scale")!=null) this.dnn_recur_scale=Double.parseDouble(properties.getProperty(prefix+"dnn_recur_scale")); // By Claude on 06/14/2026
		if (properties.getProperty(prefix+"dnn_stride")!=null)      this.dnn_stride=Integer.parseInt(properties.getProperty(prefix+"dnn_stride")); // By Claude on 06/14/2026
		if (properties.getProperty(prefix+"dnn_vmax")!=null)        this.dnn_vmax=Double.parseDouble(properties.getProperty(prefix+"dnn_vmax")); // By Claude on 06/15/2026
		// dnn_t8frac getProperty removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
		if (properties.getProperty(prefix+"dnn_patch")!=null)       this.dnn_patch=Integer.parseInt(properties.getProperty(prefix+"dnn_patch")); // By Claude on 06/16/2026
		if (properties.getProperty(prefix+"dnn_remote")!=null)      this.dnn_remote=Boolean.parseBoolean(properties.getProperty(prefix+"dnn_remote")); // By Claude on 06/20/2026
		if (properties.getProperty(prefix+"dnn_remote_host")!=null) this.dnn_remote_host=(String) properties.getProperty(prefix+"dnn_remote_host"); // By Claude on 06/20/2026
		if (properties.getProperty(prefix+"dnn_remote_model")!=null)  this.dnn_remote_model=(String) properties.getProperty(prefix+"dnn_remote_model"); // By Claude on 06/20/2026
		if (properties.getProperty(prefix+"dnn_remote_srcdir")!=null) this.dnn_remote_srcdir=(String) properties.getProperty(prefix+"dnn_remote_srcdir"); // By Claude on 06/20/2026
		if (properties.getProperty(prefix+"dnn_local")!=null)       this.dnn_local=Boolean.parseBoolean(properties.getProperty(prefix+"dnn_local")); // By Claude on 06/27/2026
		if (properties.getProperty(prefix+"dnn_local_dir")!=null)   this.dnn_local_dir=(String) properties.getProperty(prefix+"dnn_local_dir"); // By Claude on 06/27/2026
		if (properties.getProperty(prefix+"dnn_l2")!=null)         this.dnn_l2=Boolean.parseBoolean(properties.getProperty(prefix+"dnn_l2")); // By Claude on 06/22/2026
		if (properties.getProperty(prefix+"dnn_l2_model")!=null)   this.dnn_l2_model=(String) properties.getProperty(prefix+"dnn_l2_model"); // By Claude on 06/22/2026

		if (properties.getProperty(prefix+"synth_src")!=null)       this.synth_src=Boolean.parseBoolean(properties.getProperty(prefix+"synth_src"));         // By Claude on 06/11/2026
		if (properties.getProperty(prefix+"synth_scale")!=null)     this.synth_scale=Double.parseDouble(properties.getProperty(prefix+"synth_scale"));       // By Claude on 06/12/2026
		if (properties.getProperty(prefix+"synth_bg_avg")!=null)    this.synth_bg_avg=Integer.parseInt(properties.getProperty(prefix+"synth_bg_avg"));      // By Claude on 06/20/2026
		if (properties.getProperty(prefix+"subtract_avg")!=null)    this.subtract_avg=Boolean.parseBoolean(properties.getProperty(prefix+"subtract_avg")); // By Claude on 06/14/2026
		if (properties.getProperty(prefix+"synth_bg")!=null)        this.synth_bg=Boolean.parseBoolean(properties.getProperty(prefix+"synth_bg"));           // By Claude on 06/12/2026
		if (properties.getProperty(prefix+"min_frac")!=null)        this.min_frac=Double.parseDouble(properties.getProperty(prefix+"min_frac"));             // By Claude on 06/12/2026

		if (properties.getProperty(prefix+"save_c5full")!=null)     this.save_c5full=Boolean.parseBoolean(properties.getProperty(prefix+"save_c5full"));
		if (properties.getProperty(prefix+"save_c5rect")!=null)     this.save_c5rect=Boolean.parseBoolean(properties.getProperty(prefix+"save_c5rect"));
		if (properties.getProperty(prefix+"save_c5hyper")!=null)    this.save_c5hyper=Boolean.parseBoolean(properties.getProperty(prefix+"save_c5hyper"));   // By Claude on 06/13/2026
		if (properties.getProperty(prefix+"save_select")!=null)     this.save_select=IntersceneMatchParameters.stringToRectangle((String) properties.getProperty(prefix+"save_select"));
		if (properties.getProperty(prefix+"time_from")!=null)       this.time_from=Double.parseDouble(properties.getProperty(prefix+"time_from")); // By Claude on 06/14/2026
		if (properties.getProperty(prefix+"time_to")!=null)         this.time_to=Double.parseDouble(properties.getProperty(prefix+"time_to")); // By Claude on 06/14/2026
	}

	public CuasRtParameters clone() throws CloneNotSupportedException {
		CuasRtParameters cp = new CuasRtParameters();
		cp.en = this.en;
		cp.calib = this.calib;
		cp.cond_test = this.cond_test;
		cp.pose_test = this.pose_test;
		cp.pose_str = this.pose_str;
		cp.pose_dxy_k = this.pose_dxy_k;
		cp.pose_num_tiles = this.pose_num_tiles;
		cp.pose_shrink = this.pose_shrink; // By Claude on 07/13/2026
		cp.pose_raw = this.pose_raw;
		cp.pose_pace = this.pose_pace; // By Codex on 07/15/2026
		cp.pose_lean = this.pose_lean;
		cp.pose_full = this.pose_full; // By Claude on 07/04/2026
		cp.pose_corr_save = this.pose_corr_save; // By Claude on 07/04/2026
		cp.pose_img_save = this.pose_img_save; // By Claude on 07/04/2026
		cp.pose_stored = this.pose_stored; // By Claude on 07/04/2026
		cp.pose_mb_uniform = this.pose_mb_uniform; // By Claude on 07/12/2026
		cp.pose_cycles = this.pose_cycles; // By Claude on 07/12/2026
		cp.pose_lambda = this.pose_lambda; // By Claude on 07/12/2026
		cp.pose_max_lma = this.pose_max_lma; // By Claude on 07/13/2026
		cp.pose_recenter = this.pose_recenter; // By Claude on 07/13/2026
		cp.pose_debias = this.pose_debias; // By Claude on 07/13/2026
		cp.pose_lma_debug = this.pose_lma_debug; // By Claude on 07/12/2026
		cp.pose_freeze_cycle = this.pose_freeze_cycle; // By Claude on 07/16/2026
		cp.pose_scene_dp = this.pose_scene_dp;         // By Claude on 07/17/2026
		cp.pose_h2d_overlap = this.pose_h2d_overlap;   // By Claude on 07/17/2026
		cp.rend_test = this.rend_test; // By Claude on 07/05/2026
		cp.log_test = this.log_test; // By Claude on 07/06/2026
		cp.log_ident = this.log_ident; // By Claude on 07/06/2026
		cp.kernel_test = this.kernel_test; // By Claude on 07/12/2026
		cp.show_kernels = this.show_kernels;
		cp.dbg_fpixels = this.dbg_fpixels; // By Claude on 07/05/2026
		cp.fz_inter = this.fz_inter; // By Claude on 07/05/2026
		cp.fz_intra = this.fz_intra; // By Claude on 07/05/2026
		cp.dc_center = this.dc_center; // By Claude on 07/05/2026
		cp.oob_soft = this.oob_soft; // By Claude on 07/12/2026
		cp.oob_hard = this.oob_hard; // By Claude on 07/12/2026
		cp.cond_gpu = this.cond_gpu; // By Codex on 07/15/2026
		cp.rowcol_en = this.rowcol_en; // By Claude on 07/07/2026
		cp.rowcol_hpf = this.rowcol_hpf; // By Claude on 07/07/2026
		cp.rowcol_hpf_sigma = this.rowcol_hpf_sigma; // By Claude on 07/07/2026
		cp.rowcol_um_sigma = this.rowcol_um_sigma; // By Claude on 07/07/2026
		cp.rowcol_max_abs = this.rowcol_max_abs; // By Claude on 07/07/2026
		cp.rowcol_outlier = this.rowcol_outlier; // By Claude on 07/07/2026
		cp.disp_fg_tiles = this.disp_fg_tiles; // By Claude on 07/07/2026
		cp.disp_fg_over = this.disp_fg_over; // By Claude on 07/07/2026
		cp.psf_radius = this.psf_radius;
		cp.n_sigma = this.n_sigma;
		cp.pyramid = this.pyramid;
		cp.pix_decimate = this.pix_decimate;
		cp.vel_decimate = this.vel_decimate;
		cp.vel_radius = this.vel_radius;
		cp.vel_thresh_en = this.vel_thresh_en;
		cp.vel_suppr_rad = this.vel_suppr_rad;
		cp.vel_athresh = this.vel_athresh;
		cp.vel_rthresh = this.vel_rthresh;
		cp.vel_dbgmin = this.vel_dbgmin;
		cp.temp_weights = (this.temp_weights == null) ? null : this.temp_weights.clone();
		cp.recur_en = this.recur_en;
		cp.recur_period = this.recur_period;
		cp.recur_w = this.recur_w;
		cp.recur_leak = this.recur_leak;
		cp.recur_wthresh = this.recur_wthresh;
		cp.recur_spread = this.recur_spread;
		cp.recur_max_clust = this.recur_max_clust;
		cp.recur_fit_rat = this.recur_fit_rat;
		cp.recur_rs_frac = this.recur_rs_frac;
		cp.recur_rs_min = this.recur_rs_min;
		cp.c5_levels = (this.c5_levels == null) ? null : this.c5_levels.clone();
		cp.dnn_model = this.dnn_model;
		cp.stage2_model = this.stage2_model;
		cp.dnn_thresh = this.dnn_thresh;
		cp.dnn_stride = this.dnn_stride;
		cp.dnn_vmax = this.dnn_vmax;
		cp.dnn_patch = this.dnn_patch;
		cp.dnn_remote = this.dnn_remote;
		cp.dnn_remote_host = this.dnn_remote_host;
		cp.dnn_remote_model = this.dnn_remote_model;
		cp.dnn_remote_srcdir = this.dnn_remote_srcdir;
		cp.dnn_local = this.dnn_local;
		cp.dnn_local_dir = this.dnn_local_dir;
		cp.dnn_l2 = this.dnn_l2;
		cp.dnn_l2_model = this.dnn_l2_model;
		cp.dnn_recur_splat = this.dnn_recur_splat;
		cp.dnn_recur_scale = this.dnn_recur_scale;
		cp.synth_src = this.synth_src;
		cp.synth_scale = this.synth_scale;
		cp.synth_bg_avg = this.synth_bg_avg;
		cp.synth_bg = this.synth_bg;
		cp.subtract_avg = this.subtract_avg;
		cp.min_frac = this.min_frac;
		cp.save_c5full = this.save_c5full;
		cp.save_c5rect = this.save_c5rect;
		cp.save_c5hyper = this.save_c5hyper;
		cp.save_select = (this.save_select == null) ? null : new Rectangle(this.save_select);
		cp.time_from = this.time_from;
		cp.time_to = this.time_to;
		return cp;
	}
}
