Commit 7a793de1 authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: promote CuasRtParameters to a CLTParameters peer (clt_parameters.curt)

Per Andrey: CuasRtParameters should be instantiated like the other parameter
classes at CLTParameters:1175..1185 (img_dtt/ofp/imp/ilp/...), not nested
inside IntersceneMatchParameters. Changes:
- CLTParameters: new peer field curt, set/getProperties wiring, own
  "CUAS RT" dialog tab right after imp's questions/answers (tab content
  unchanged; tab position moves from inside imp's tab row to after it).
- IntersceneMatchParameters: the six curt wiring sites removed (field,
  dialogQ/A, set/getProperties, clone).
- Access rename: clt_parameters.imp.curt.X -> clt_parameters.curt.X
  (105 sites: OpticalFlow, CuasDetectRT, CuasPoseRT).
- corr-xml keys change _imp_curt_* -> _curt_*. getProperties keeps a legacy
  fallback (reads _imp_curt_* first, _curt_* overrides), so old configs
  still load unmigrated.
- NEW scripts/migrate_curt_config.py: renames _imp_curt_* keys in existing
  corr-xml files (in-place with .bak, --dry-run, idempotent, drops duplicate
  legacy entries with a warning). Validated on a copy of
  LV396-v013-...-POSEJP4-ENMB.corr-xml: 87 keys renamed, byte-identical
  otherwise.

Verified: mvn -DskipTests clean package OK; no imp.curt references remain.
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent 45f1f35b
#!/usr/bin/env python3
# By Claude on 07/04/2026
"""Migrate corr-xml configuration files to the current curt_* key format.
CuasRtParameters history:
pre-07/2026 keys CLT_PARAMETERS._imp_curt_<name> (curt_* fields inside IntersceneMatchParameters,
then the extracted class still saved under imp with the same keys)
07/2026 - keys CLT_PARAMETERS._curt_<name> (CuasRtParameters is a CLTParameters peer,
like imp/ofp/ilp)
The Java reader keeps a legacy fallback (it reads _imp_curt_* when present, then
_curt_* overrides), so unmigrated files still load. This script rewrites the keys
so files are in the current format and future removal of the fallback is safe.
Usage:
migrate_curt_config.py FILE [FILE ...] # in-place, keeps FILE.bak
migrate_curt_config.py --dry-run FILE ... # report only, no changes
migrate_curt_config.py --no-backup FILE ... # in-place without .bak
Only the literal substring '_imp_curt_' inside key="..." attributes is renamed to
'_curt_'; everything else (values, formatting, comments) is byte-preserved. If a
file already contains a _curt_ key that a rename would duplicate, the old key is
dropped (the new one wins) and a warning is printed.
"""
import argparse
import re
import shutil
import sys
KEY_RE = re.compile(r'(<entry key=")([^"]*)_imp_curt_([^"]*)(")')
def migrate_text(text):
"""Return (new_text, n_renamed, dropped_keys)."""
existing_new = set(re.findall(r'<entry key="([^"]*_curt_[^"]*)"', text))
existing_new = {k for k in existing_new if '_imp_curt_' not in k}
renamed = [0]
dropped = []
out_lines = []
for line in text.splitlines(keepends=True):
m = KEY_RE.search(line)
if m:
new_key = m.group(2) + '_curt_' + m.group(3)
if new_key in existing_new:
dropped.append(m.group(2) + '_imp_curt_' + m.group(3))
continue # drop the whole legacy entry line - the new key already exists
line = KEY_RE.sub(r'\g<1>\g<2>_curt_\g<3>\g<4>', line)
renamed[0] += 1
out_lines.append(line)
return ''.join(out_lines), renamed[0], dropped
def main():
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
ap.add_argument('files', nargs='+', help='corr-xml files to migrate')
ap.add_argument('--dry-run', action='store_true', help='report only, do not modify')
ap.add_argument('--no-backup', action='store_true', help='do not keep a .bak copy')
args = ap.parse_args()
status = 0
for path in args.files:
try:
with open(path, encoding='utf-8') as f:
text = f.read()
except OSError as e:
print(f"{path}: ERROR - {e}", file=sys.stderr)
status = 1
continue
new_text, n, dropped = migrate_text(text)
for k in dropped:
print(f"{path}: WARNING - dropped legacy entry '{k}' (current-format key already present)")
if n == 0 and not dropped:
print(f"{path}: already current (no _imp_curt_ keys)")
continue
if args.dry_run:
print(f"{path}: would rename {n} key(s)" +
(f", drop {len(dropped)} duplicate legacy entrie(s)" if dropped else ""))
continue
if not args.no_backup:
shutil.copy2(path, path + '.bak')
with open(path, 'w', encoding='utf-8') as f:
f.write(new_text)
print(f"{path}: renamed {n} key(s)" +
(f", dropped {len(dropped)} duplicate legacy entrie(s)" if dropped else "") +
("" if args.no_backup else f" (backup: {path}.bak)"))
return status
if __name__ == '__main__':
sys.exit(main())
...@@ -40,6 +40,7 @@ import com.elphel.imagej.common.WindowTools; ...@@ -40,6 +40,7 @@ import com.elphel.imagej.common.WindowTools;
import com.elphel.imagej.correction.CorrectionColorProc; import com.elphel.imagej.correction.CorrectionColorProc;
import com.elphel.imagej.lwir.LwirReaderParameters; import com.elphel.imagej.lwir.LwirReaderParameters;
import com.elphel.imagej.tileprocessor.BiQuadParameters; import com.elphel.imagej.tileprocessor.BiQuadParameters;
import com.elphel.imagej.tileprocessor.CuasRtParameters; // By Claude on 07/04/2026
import com.elphel.imagej.tileprocessor.ImageDtt; import com.elphel.imagej.tileprocessor.ImageDtt;
import com.elphel.imagej.tileprocessor.ImageDttParameters; import com.elphel.imagej.tileprocessor.ImageDttParameters;
import com.elphel.imagej.tileprocessor.IntersceneGlobalLmaParameters; import com.elphel.imagej.tileprocessor.IntersceneGlobalLmaParameters;
...@@ -1183,6 +1184,7 @@ public class CLTParameters { ...@@ -1183,6 +1184,7 @@ public class CLTParameters {
public IntersceneGlobalLmaParameters iglp = new IntersceneGlobalLmaParameters(); public IntersceneGlobalLmaParameters iglp = new IntersceneGlobalLmaParameters();
public InterNoiseParameters inp = new InterNoiseParameters(); public InterNoiseParameters inp = new InterNoiseParameters();
public LWIRWorldParameters lwp = new LWIRWorldParameters(); public LWIRWorldParameters lwp = new LWIRWorldParameters();
public CuasRtParameters curt = new CuasRtParameters(); // CUAS real-time (was imp.curt) // By Claude on 07/04/2026
public HashMap<String,Double> z_corr_map = new HashMap<String,Double>(); //old one public HashMap<String,Double> z_corr_map = new HashMap<String,Double>(); //old one
public HashMap<String,Double> infinity_distace_map = new HashMap<String,Double>(); //new one public HashMap<String,Double> infinity_distace_map = new HashMap<String,Double>(); //new one
...@@ -2338,6 +2340,7 @@ public class CLTParameters { ...@@ -2338,6 +2340,7 @@ public class CLTParameters {
iglp.setProperties (prefix+"_iglp_", properties); iglp.setProperties (prefix+"_iglp_", properties);
inp.setProperties (prefix+"_inp_", properties); inp.setProperties (prefix+"_inp_", properties);
lwp.setProperties (prefix+"_lwp_", properties); lwp.setProperties (prefix+"_lwp_", properties);
curt.setProperties (prefix+"_curt_", properties); // By Claude on 07/04/2026
} }
...@@ -3408,6 +3411,8 @@ public class CLTParameters { ...@@ -3408,6 +3411,8 @@ public class CLTParameters {
iglp.getProperties (prefix+"_iglp_", properties); iglp.getProperties (prefix+"_iglp_", properties);
inp.getProperties (prefix+"_inp_", properties); inp.getProperties (prefix+"_inp_", properties);
lwp.getProperties (prefix+"_lwp_", properties); lwp.getProperties (prefix+"_lwp_", properties);
curt.getProperties (prefix+"_imp_curt_", properties); // legacy keys (curt was inside imp until 07/2026) // By Claude on 07/04/2026
curt.getProperties (prefix+"_curt_", properties); // current keys override legacy if both present // By Claude on 07/04/2026
} }
public boolean showJDialog() { public boolean showJDialog() {
...@@ -4898,6 +4903,9 @@ public class CLTParameters { ...@@ -4898,6 +4903,9 @@ public class CLTParameters {
this.imp.dialogQuestions(gd); this.imp.dialogQuestions(gd);
gd.addTab ("CUAS RT", "CUAS Real Time");
this.curt.dialogQuestions(gd); // By Claude on 07/04/2026
this.lwp.dialogQuestions(gd); this.lwp.dialogQuestions(gd);
gd.addTab ("Inter-LMA", "parameters for the interscene LMA fitting"); gd.addTab ("Inter-LMA", "parameters for the interscene LMA fitting");
...@@ -5965,6 +5973,7 @@ public class CLTParameters { ...@@ -5965,6 +5973,7 @@ public class CLTParameters {
this.lwir.dialogAnswers(gd); this.lwir.dialogAnswers(gd);
this.ofp.dialogAnswers(gd); this.ofp.dialogAnswers(gd);
this.imp.dialogAnswers(gd); this.imp.dialogAnswers(gd);
this.curt.dialogAnswers(gd); // By Claude on 07/04/2026
this.lwp.dialogAnswers(gd); this.lwp.dialogAnswers(gd);
this.ilp.dialogAnswers(gd); this.ilp.dialogAnswers(gd);
this.iglp.dialogAnswers(gd); this.iglp.dialogAnswers(gd);
......
...@@ -158,14 +158,14 @@ public class CuasDetectRT { ...@@ -158,14 +158,14 @@ public class CuasDetectRT {
fpixels[i] = (float[]) stack.getPixels (first_slice + i); fpixels[i] = (float[]) stack.getPixels (first_slice + i);
} }
base_name = core_base_name; base_name = core_base_name;
if (clt_parameters.imp.curt.subtract_avg) base_name += "-SUBAVG"; // distinct output filenames for average-subtracted runs (don't overwrite) // By Claude on 06/14/2026 if (clt_parameters.curt.subtract_avg) base_name += "-SUBAVG"; // distinct output filenames for average-subtracted runs (don't overwrite) // By Claude on 06/14/2026
if (clt_parameters.imp.curt.synth_src) { // load the synthetic reference grid separately (NOT mixed here) // By Claude on 06/14/2026 if (clt_parameters.curt.synth_src) { // load the synthetic reference grid separately (NOT mixed here) // By Claude on 06/14/2026
// Real (loaded above) is the pyramid base. The synthetic file holds NORMALIZED // Real (loaded above) is the pyramid base. The synthetic file holds NORMALIZED
// (peak 1) clean targets / a velocity-reference grid: load + scale it, keep it // (peak 1) clean targets / a velocity-reference grid: load + scale it, keep it
// aside (NO LoG - it has no slowly-varying background), and inject it TILED into // aside (NO LoG - it has no slowly-varying background), and inject it TILED into
// each pyramid level just before conv5d/DNN, so it is never averaged across levels // each pyramid level just before conv5d/DNN, so it is never averaged across levels
// and looks the same at every level while the real noise is averaged (SNR up ~sqrt2/level). // and looks the same at every level while the real noise is averaged (SNR up ~sqrt2/level).
double synth_scale = clt_parameters.imp.curt.synth_scale; double synth_scale = clt_parameters.curt.synth_scale;
// Synthetic grid is sequence-INDEPENDENT: read it from the shared dir (list SET "cuasSynth") // Synthetic grid is sequence-INDEPENDENT: read it from the shared dir (list SET "cuasSynth")
// when set; otherwise fall back to the per-sequence model_directory (old behavior / single- // when set; otherwise fall back to the per-sequence model_directory (old behavior / single-
// sequence mode where the SET key is absent). By Claude on 06/24/2026 // sequence mode where the SET key is absent). By Claude on 06/24/2026
...@@ -284,8 +284,8 @@ public class CuasDetectRT { ...@@ -284,8 +284,8 @@ public class CuasDetectRT {
/** [i0,i1) scene-index window for the timing ROI (curt_time_from/to), or full range if open/empty. // By Claude on 06/14/2026 */ /** [i0,i1) scene-index window for the timing ROI (curt_time_from/to), or full range if open/empty. // By Claude on 06/14/2026 */
private int [] timeWindow(String [] ts) { private int [] timeWindow(String [] ts) {
int n = (ts == null) ? 0 : ts.length; int n = (ts == null) ? 0 : ts.length;
double from = clt_parameters.imp.curt.time_from; double from = clt_parameters.curt.time_from;
double to = clt_parameters.imp.curt.time_to; double to = clt_parameters.curt.time_to;
if ((n == 0) || ((from <= 0) && (to <= 0))) return new int[]{0, n}; if ((n == 0) || ((from <= 0) && (to <= 0))) return new int[]{0, n};
double minSec = Double.POSITIVE_INFINITY; double minSec = Double.POSITIVE_INFINITY;
double [] tv = new double [n]; double [] tv = new double [n];
...@@ -560,19 +560,19 @@ public class CuasDetectRT { ...@@ -560,19 +560,19 @@ public class CuasDetectRT {
Rectangle roi, Rectangle roi,
String title_base, String title_base,
boolean save_individual) { boolean save_individual) {
int period = clt_parameters.imp.curt.recur_period; int period = clt_parameters.curt.recur_period;
double w = clt_parameters.imp.curt.recur_w; double w = clt_parameters.curt.recur_w;
double leak = clt_parameters.imp.curt.recur_leak; double leak = clt_parameters.curt.recur_leak;
double wthresh = clt_parameters.imp.curt.recur_wthresh; double wthresh = clt_parameters.curt.recur_wthresh;
double spread = clt_parameters.imp.curt.recur_spread; double spread = clt_parameters.curt.recur_spread;
int max_clust = clt_parameters.imp.curt.recur_max_clust; int max_clust = clt_parameters.curt.recur_max_clust;
double fit_rat = clt_parameters.imp.curt.recur_fit_rat; double fit_rat = clt_parameters.curt.recur_fit_rat;
double rs_frac = clt_parameters.imp.curt.recur_rs_frac; double rs_frac = clt_parameters.curt.recur_rs_frac;
double rs_min = clt_parameters.imp.curt.recur_rs_min; double rs_min = clt_parameters.curt.recur_rs_min;
int pix_decimate = clt_parameters.imp.curt.pix_decimate; int pix_decimate = clt_parameters.curt.pix_decimate;
int vel_radius = clt_parameters.imp.curt.vel_radius; int vel_radius = clt_parameters.curt.vel_radius;
int vel_decimate = clt_parameters.imp.curt.vel_decimate; int vel_decimate = clt_parameters.curt.vel_decimate;
double dbg_min = clt_parameters.imp.curt.vel_dbgmin; double dbg_min = clt_parameters.curt.vel_dbgmin;
int num_5d = conv5d_roi.length; int num_5d = conv5d_roi.length;
CuasRecurrentBuffer recurrentBuffer = new CuasRecurrentBuffer( CuasRecurrentBuffer recurrentBuffer = new CuasRecurrentBuffer(
roi.width, // int roi_width, roi.width, // int roi_width,
...@@ -735,25 +735,25 @@ public class CuasDetectRT { ...@@ -735,25 +735,25 @@ public class CuasDetectRT {
int [] c5_levels, int [] c5_levels,
Rectangle roi, Rectangle roi,
String title_conv5d) { String title_conv5d) {
final int dnn_stride = Math.max(1, clt_parameters.imp.curt.dnn_stride); final int dnn_stride = Math.max(1, clt_parameters.curt.dnn_stride);
final boolean use_l2 = clt_parameters.imp.curt.dnn_l2; // run Layer-2 on the DGX: -OFFSET carries L2 det+vel instead of L1. By Claude 06/22/2026 final boolean use_l2 = clt_parameters.curt.dnn_l2; // run Layer-2 on the DGX: -OFFSET carries L2 det+vel instead of L1. By Claude 06/22/2026
final String l2model = use_l2 ? clt_parameters.imp.curt.dnn_l2_model : ""; // L2 run dir on the DGX; empty = L1-only (old way) final String l2model = use_l2 ? clt_parameters.curt.dnn_l2_model : ""; // L2 run dir on the DGX; empty = L1-only (old way)
// L2 model id appended as the LAST filename suffix on -OFFSET so runs of different L2 models don't // L2 model id appended as the LAST filename suffix on -OFFSET so runs of different L2 models don't
// collide (and Dolphin's begin...end.tiff truncation still shows the model). By Claude on 06/24/2026 // collide (and Dolphin's begin...end.tiff truncation still shows the model). By Claude on 06/24/2026
final String l2tag = use_l2 ? ("-" + l2model.substring(l2model.lastIndexOf('/') + 1)) : ""; final String l2tag = use_l2 ? ("-" + l2model.substring(l2model.lastIndexOf('/') + 1)) : "";
final int W = getWidth(), H = getHeight(); final int W = getWidth(), H = getHeight();
final boolean save_rect = clt_parameters.imp.curt.save_c5rect; final boolean save_rect = clt_parameters.curt.save_c5rect;
final boolean save_hyper = clt_parameters.imp.curt.save_c5hyper; final boolean save_hyper = clt_parameters.curt.save_c5hyper;
final boolean synth = clt_parameters.imp.curt.synth_src && (synth_pixels != null) && (synth_pixels.length > 0); final boolean synth = clt_parameters.curt.synth_src && (synth_pixels != null) && (synth_pixels.length > 0);
final boolean synth_bg = clt_parameters.imp.curt.synth_bg; final boolean synth_bg = clt_parameters.curt.synth_bg;
final int n_synth = synth ? synth_pixels.length : 0; final int n_synth = synth ? synth_pixels.length : 0;
try { // auto-launch the DGX server if not already running (deploy bundled/override scripts, ssh-start, poll) // By Claude on 06/20/2026 try { // auto-launch the DGX server if not already running (deploy bundled/override scripts, ssh-start, poll) // By Claude on 06/20/2026
if (!clt_parameters.imp.curt.dnn_local) // local native backend has no server to launch. By Claude on 06/27/2026 if (!clt_parameters.curt.dnn_local) // local native backend has no server to launch. By Claude on 06/27/2026
CuasDnnRemote.ensureServer(clt_parameters.imp.curt.dnn_remote_host, clt_parameters.imp.curt.dnn_remote_model, l2model, clt_parameters.imp.curt.dnn_remote_srcdir); CuasDnnRemote.ensureServer(clt_parameters.curt.dnn_remote_host, clt_parameters.curt.dnn_remote_model, l2model, clt_parameters.curt.dnn_remote_srcdir);
} catch (Exception e) { System.out.println("runDnnRemote(): server auto-launch failed: "+e); } } catch (Exception e) { System.out.println("runDnnRemote(): server auto-launch failed: "+e); }
try (CuasDnnBackend remote = clt_parameters.imp.curt.dnn_local try (CuasDnnBackend remote = clt_parameters.curt.dnn_local
? new CuasDnnLocal(clt_parameters.imp.curt.dnn_local_dir, clt_parameters.imp.curt.dnn_remote_model, l2model) ? new CuasDnnLocal(clt_parameters.curt.dnn_local_dir, clt_parameters.curt.dnn_remote_model, l2model)
: new CuasDnnRemote(clt_parameters.imp.curt.dnn_remote_host)) { : new CuasDnnRemote(clt_parameters.curt.dnn_remote_host)) {
// Build the upload array: LoG-conditioned real (optionally synth_bg_avg-decimated upstream), optionally // Build the upload array: LoG-conditioned real (optionally synth_bg_avg-decimated upstream), optionally
// with synthetic targets mixed in (tiled synth[t % n_synth]; clean = zero bg first) - matching the local // with synthetic targets mixed in (tiled synth[t % n_synth]; clean = zero bg first) - matching the local
// per-level injection (CuasDetectRT.java synth block) but PRE-pyramid; the DGX then averages it into levels. // per-level injection (CuasDetectRT.java synth block) but PRE-pyramid; the DGX then averages it into levels.
...@@ -817,8 +817,8 @@ public class CuasDetectRT { ...@@ -817,8 +817,8 @@ public class CuasDetectRT {
// batched: request the level's in-window scenes in chunks; the DGX runs them continuously // batched: request the level's in-window scenes in chunks; the DGX runs them continuously
// (production throughput) and ghostbusts on the GPU (so -OFFSET s + ROI 121 are both clean - // (production throughput) and ghostbusts on the GPU (so -OFFSET s + ROI 121 are both clean -
// no Java-side ghostbust). rmax_cells = vmax*vel_decimate (<=0 disables). By Claude on 06/20/2026 // no Java-side ghostbust). rmax_cells = vmax*vel_decimate (<=0 disables). By Claude on 06/20/2026
double rmax = (clt_parameters.imp.curt.dnn_vmax > 0) ? double rmax = (clt_parameters.curt.dnn_vmax > 0) ?
clt_parameters.imp.curt.dnn_vmax * clt_parameters.imp.curt.vel_decimate : 0.0; clt_parameters.curt.dnn_vmax * clt_parameters.curt.vel_decimate : 0.0;
final int REQ = 64; // scenes per round-trip (reply byte[] ~419MB at 640x512, < 2GB array cap) final int REQ = 64; // scenes per round-trip (reply byte[] ~419MB at 640x512, < 2GB array cap)
for (int j0 = 0; j0 < num; j0 += REQ) { for (int j0 = 0; j0 < num; j0 += REQ) {
int cnt = Math.min(REQ, num - j0); int cnt = Math.min(REQ, num - j0);
...@@ -850,8 +850,8 @@ public class CuasDetectRT { ...@@ -850,8 +850,8 @@ public class CuasDetectRT {
final int [] ord = use_l2 ? new int[]{2, 3, 4, 0, 1, 5} : new int[]{2, 3, 4, 0, 1}; final int [] ord = use_l2 ? new int[]{2, 3, 4, 0, 1, 5} : new int[]{2, 3, 4, 0, 1};
final String [] off_labels = use_l2 ? new String[]{"s","Vx","Vy","dx","dy","age"} : new String[]{"s","Vx","Vy","dx","dy"}; final String [] off_labels = use_l2 ? new String[]{"s","Vx","Vy","dx","dy","age"} : new String[]{"s","Vx","Vy","dx","dy"};
// NaN Vx,Vy,dx,dy where s < curt_dnn_thresh so velocity shows only at detections (ImageJ ignores NaN); keep s + age full. By Claude on 06/20/2026 // NaN Vx,Vy,dx,dy where s < curt_dnn_thresh so velocity shows only at detections (ImageJ ignores NaN); keep s + age full. By Claude on 06/20/2026
final double off_thr = clt_parameters.imp.curt.dnn_thresh; final double off_thr = clt_parameters.curt.dnn_thresh;
final double velScale = 1.0 / Math.max(1, clt_parameters.imp.curt.vel_decimate); // Vx,Vy: cells -> px/level-frame (1/vel_decimate) // By Claude on 06/20/2026 final double velScale = 1.0 / Math.max(1, clt_parameters.curt.vel_decimate); // Vx,Vy: cells -> px/level-frame (1/vel_decimate) // By Claude on 06/20/2026
double [][][] off5_w = new double [ord.length][nsc][]; // window the full-frame offset for -OFFSET double [][][] off5_w = new double [ord.length][nsc][]; // window the full-frame offset for -OFFSET
for (int k = 0; k < nsc; k++) { for (int k = 0; k < nsc; k++) {
double [] sCh = off5[2][win_dnn[0]+k]; // s channel (off5 index 2) double [] sCh = off5[2][win_dnn[0]+k]; // s channel (off5 index 2)
...@@ -885,35 +885,35 @@ public class CuasDetectRT { ...@@ -885,35 +885,35 @@ public class CuasDetectRT {
boolean batch_mode, boolean batch_mode,
int debugLevel) { int debugLevel) {
boolean save_linear_cuas = true; boolean save_linear_cuas = true;
int curt_pyramid = clt_parameters.imp.curt.pyramid; int curt_pyramid = clt_parameters.curt.pyramid;
double curt_psf_radius = clt_parameters.imp.curt.psf_radius; double curt_psf_radius = clt_parameters.curt.psf_radius;
double curt_n_sigma = clt_parameters.imp.curt.n_sigma; double curt_n_sigma = clt_parameters.curt.n_sigma;
// rleak0 local removed 2026-06-20 (LReLU conditioning now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026 // rleak0 local removed 2026-06-20 (LReLU conditioning now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
int curt_pix_decimate = clt_parameters.imp.curt.pix_decimate; int curt_pix_decimate = clt_parameters.curt.pix_decimate;
int curt_vel_decimate = clt_parameters.imp.curt.vel_decimate; int curt_vel_decimate = clt_parameters.curt.vel_decimate;
int curt_vel_radius = clt_parameters.imp.curt.vel_radius; int curt_vel_radius = clt_parameters.curt.vel_radius;
boolean curt_vel_thresh_en =clt_parameters.imp.curt.vel_thresh_en; boolean curt_vel_thresh_en =clt_parameters.curt.vel_thresh_en;
int curt_vel_suppr_rad =clt_parameters.imp.curt.vel_suppr_rad; int curt_vel_suppr_rad =clt_parameters.curt.vel_suppr_rad;
double curt_vel_athresh = clt_parameters.imp.curt.vel_athresh; double curt_vel_athresh = clt_parameters.curt.vel_athresh;
double curt_vel_rthresh = clt_parameters.imp.curt.vel_rthresh; double curt_vel_rthresh = clt_parameters.curt.vel_rthresh;
double curt_vel_dbg_min = clt_parameters.imp.curt.vel_dbgmin; // temporary, testing with strong targets, make clean background double curt_vel_dbg_min = clt_parameters.curt.vel_dbgmin; // temporary, testing with strong targets, make clean background
boolean curt_recur_en = clt_parameters.imp.curt.recur_en; // By Claude on 06/09/2026 boolean curt_recur_en = clt_parameters.curt.recur_en; // By Claude on 06/09/2026
int curt_recur_period = clt_parameters.imp.curt.recur_period; // By Claude on 06/09/2026 int curt_recur_period = clt_parameters.curt.recur_period; // By Claude on 06/09/2026
double curt_recur_w = clt_parameters.imp.curt.recur_w; // By Claude on 06/09/2026 double curt_recur_w = clt_parameters.curt.recur_w; // By Claude on 06/09/2026
double curt_recur_leak = clt_parameters.imp.curt.recur_leak; // By Claude on 06/09/2026 double curt_recur_leak = clt_parameters.curt.recur_leak; // By Claude on 06/09/2026
double curt_recur_wthresh =clt_parameters.imp.curt.recur_wthresh; // By Claude on 06/09/2026 double curt_recur_wthresh =clt_parameters.curt.recur_wthresh; // By Claude on 06/09/2026
double curt_recur_spread = clt_parameters.imp.curt.recur_spread; // By Claude on 06/09/2026 double curt_recur_spread = clt_parameters.curt.recur_spread; // By Claude on 06/09/2026
int curt_recur_max_clust = clt_parameters.imp.curt.recur_max_clust; // By Claude on 06/09/2026 int curt_recur_max_clust = clt_parameters.curt.recur_max_clust; // By Claude on 06/09/2026
double curt_recur_fit_rat = clt_parameters.imp.curt.recur_fit_rat; // By Claude on 06/10/2026 double curt_recur_fit_rat = clt_parameters.curt.recur_fit_rat; // By Claude on 06/10/2026
double curt_recur_rs_frac = clt_parameters.imp.curt.recur_rs_frac; // By Claude on 06/10/2026 double curt_recur_rs_frac = clt_parameters.curt.recur_rs_frac; // By Claude on 06/10/2026
double curt_recur_rs_min = clt_parameters.imp.curt.recur_rs_min; // By Claude on 06/10/2026 double curt_recur_rs_min = clt_parameters.curt.recur_rs_min; // By Claude on 06/10/2026
double[] curt_temp_weights = clt_parameters.imp.curt.temp_weights.clone(); double[] curt_temp_weights = clt_parameters.curt.temp_weights.clone();
boolean curt_save_c5full = clt_parameters.imp.curt.save_c5full; boolean curt_save_c5full = clt_parameters.curt.save_c5full;
boolean curt_save_c5rect = clt_parameters.imp.curt.save_c5rect; boolean curt_save_c5rect = clt_parameters.curt.save_c5rect;
Rectangle curt_save_select = clt_parameters.imp.curt.save_select; Rectangle curt_save_select = clt_parameters.curt.save_select;
if (clt_parameters.imp.curt.synth_src) { // synthetic grid: HONOR the user ROI so it can be shrunk - the full-grid SYNTH_ROI (320x320) OOMs the per-velocity render (~12x expansion per axis); fall back to SYNTH_ROI only when no ROI is set // By Claude on 06/15/2026 if (clt_parameters.curt.synth_src) { // synthetic grid: HONOR the user ROI so it can be shrunk - the full-grid SYNTH_ROI (320x320) OOMs the per-velocity render (~12x expansion per axis); fall back to SYNTH_ROI only when no ROI is set // By Claude on 06/15/2026
if (curt_save_select == null) { if (curt_save_select == null) {
curt_save_select = new Rectangle(SYNTH_ROI); curt_save_select = new Rectangle(SYNTH_ROI);
System.out.println("Synthetic input: no ROI set - using full-grid SYNTH_ROI = "+curt_save_select); System.out.println("Synthetic input: no ROI set - using full-grid SYNTH_ROI = "+curt_save_select);
...@@ -922,8 +922,8 @@ public class CuasDetectRT { ...@@ -922,8 +922,8 @@ public class CuasDetectRT {
+ " (synthetic 11x11 grid spans ~"+SYNTH_ROI+"; aim the ROI inside it)"); // By Claude on 06/15/2026 + " (synthetic 11x11 grid spans ~"+SYNTH_ROI+"; aim the ROI inside it)"); // By Claude on 06/15/2026
} }
} }
final double min_frac_last = clt_parameters.imp.curt.min_frac; // By Claude on 06/12/2026 final double min_frac_last = clt_parameters.curt.min_frac; // By Claude on 06/12/2026
if (clt_parameters.imp.curt.synth_src && (min_frac_last > 0)) { // By Claude on 06/12/2026 if (clt_parameters.curt.synth_src && (min_frac_last > 0)) { // By Claude on 06/12/2026
System.out.println("WARNING: synthetic (B-measurement) run with curt_min_frac = "+min_frac_last+ System.out.println("WARNING: synthetic (B-measurement) run with curt_min_frac = "+min_frac_last+
" - this NONLINEAR gate punches zeros into the strongest ridge cells; set 0 for a linear measurement"); " - this NONLINEAR gate punches zeros into the strongest ridge cells; set 0 for a linear measurement");
} }
...@@ -964,9 +964,9 @@ public class CuasDetectRT { ...@@ -964,9 +964,9 @@ public class CuasDetectRT {
// (the LEV-L noise floor, N=2^L) into a sequence (length = the "Time ROI" window; open/-1 = all frames) and force a single level - restoring the // (the LEV-L noise floor, N=2^L) into a sequence (length = the "Time ROI" window; open/-1 = all frames) and force a single level - restoring the
// old synthetic+background mode speed. SUBAVG then runs over this short sequence; the SYNTHETIC targets are // old synthetic+background mode speed. SUBAVG then runs over this short sequence; the SYNTHETIC targets are
// injected later (after SUBAVG), so they never enter the average. Velocity cells then encode LEV1/2/3. // injected later (after SUBAVG), so they never enter the average. Velocity cells then encode LEV1/2/3.
final boolean synth_fast = clt_parameters.imp.curt.synth_src && (clt_parameters.imp.curt.synth_bg_avg > 1); final boolean synth_fast = clt_parameters.curt.synth_src && (clt_parameters.curt.synth_bg_avg > 1);
if (synth_fast && (dpixels != null) && (dpixels.length >= clt_parameters.imp.curt.synth_bg_avg)) { if (synth_fast && (dpixels != null) && (dpixels.length >= clt_parameters.curt.synth_bg_avg)) {
final int navg = clt_parameters.imp.curt.synth_bg_avg; final int navg = clt_parameters.curt.synth_bg_avg;
int ngrp = dpixels.length / navg; // each group = navg input frames -> one averaged (LEV) frame int ngrp = dpixels.length / navg; // each group = navg input frames -> one averaged (LEV) frame
String [] ts_grp = new String [ngrp]; String [] ts_grp = new String [ngrp];
for (int k = 0; k < ngrp; k++) ts_grp[k] = time_stamps[k*navg + navg - 1]; // last ts of each navg-group (the LEV timestamp) for (int k = 0; k < ngrp; k++) ts_grp[k] = time_stamps[k*navg + navg - 1]; // last ts of each navg-group (the LEV timestamp)
...@@ -985,7 +985,7 @@ public class CuasDetectRT { ...@@ -985,7 +985,7 @@ public class CuasDetectRT {
this.dpixels = davg; this.time_stamps = tsavg; dpixels = davg; this.dpixels = davg; this.time_stamps = tsavg; dpixels = davg;
System.out.println(now()+" detectTargets(): synth fast path - bg-averaged x"+navg+" -> "+kout+"/"+ngrp+" frames (Time ROI groups ["+g0+","+g1+")), single level"); // By Claude on 06/20/2026 System.out.println(now()+" detectTargets(): synth fast path - bg-averaged x"+navg+" -> "+kout+"/"+ngrp+" frames (Time ROI groups ["+g0+","+g1+")), single level"); // By Claude on 06/20/2026
} }
if (clt_parameters.imp.curt.subtract_avg && (dpixels != null) && (dpixels.length > 0)) { // de-streak: subtract the static background before LoG so the sharp treeline edge (and its tile-grid ringing) is gone; the moving target is not in the average // By Claude on 06/14/2026 if (clt_parameters.curt.subtract_avg && (dpixels != null) && (dpixels.length > 0)) { // de-streak: subtract the static background before LoG so the sharp treeline edge (and its tile-grid ringing) is gone; the moving target is not in the average // By Claude on 06/14/2026
int npx = dpixels[0].length; int npx = dpixels[0].length;
double [] mean = new double [npx]; double [] mean = new double [npx];
int [] cnt = new int [npx]; int [] cnt = new int [npx];
...@@ -1039,13 +1039,13 @@ public class CuasDetectRT { ...@@ -1039,13 +1039,13 @@ public class CuasDetectRT {
// The fine-velocity detector is now the DNN front-end fed from dpixels_pyramid; nothing consumes a 3d3 coarse-velocity history. // The fine-velocity detector is now the DNN front-end fed from dpixels_pyramid; nothing consumes a 3d3 coarse-velocity history.
// building pyramid // building pyramid
int pyramid_levels = synth_fast ? 1 : clt_parameters.imp.curt.pyramid; // synth fast path forces a single level // By Claude on 06/20/2026 int pyramid_levels = synth_fast ? 1 : clt_parameters.curt.pyramid; // synth fast path forces a single level // By Claude on 06/20/2026
// Single level selector for ALL heavy per-level paths (3d3/conv5d, C5P-direct, DNN): // By Claude on 06/13/2026 // Single level selector for ALL heavy per-level paths (3d3/conv5d, C5P-direct, DNN): // By Claude on 06/13/2026
// curt_c5_levels = {} -> all built levels; {k} -> run the heavy stages only at level k // curt_c5_levels = {} -> all built levels; {k} -> run the heavy stages only at level k
// (the cheap temporalAverageLReLU/convolve3D3LReLU pyramid chain still builds up to k). // (the cheap temporalAverageLReLU/convolve3D3LReLU pyramid chain still builds up to k).
// Synthetic input now uses the same pyramid + level selection as real data (the old // Synthetic input now uses the same pyramid + level selection as real data (the old
// pyramid_levels=1 force and the curt_synth_bg_avg N= decimation were retired). // pyramid_levels=1 force and the curt_synth_bg_avg N= decimation were retired).
final int [] c5_levels = synth_fast ? new int[0] : clt_parameters.imp.curt.c5_levels; // synth fast path -> all built (= level 0 only) // By Claude on 06/20/2026 final int [] c5_levels = synth_fast ? new int[0] : clt_parameters.curt.c5_levels; // synth fast path -> all built (= level 0 only) // By Claude on 06/20/2026
double [][][] dpixels_pyramid = new double [pyramid_levels][][]; double [][][] dpixels_pyramid = new double [pyramid_levels][][];
String [][] ts_pyramid = new String [pyramid_levels][]; String [][] ts_pyramid = new String [pyramid_levels][];
...@@ -1115,7 +1115,7 @@ public class CuasDetectRT { ...@@ -1115,7 +1115,7 @@ public class CuasDetectRT {
} }
} }
// --- Synthetic reference grid injection + sqrt(2) noise check ---------------------- // By Claude on 06/14/2026 // --- Synthetic reference grid injection + sqrt(2) noise check ---------------------- // By Claude on 06/14/2026
if (clt_parameters.imp.curt.synth_src && (synth_pixels != null) && (synth_pixels.length > 0)) { if (clt_parameters.curt.synth_src && (synth_pixels != null) && (synth_pixels.length > 0)) {
// sqrt(2) check: full-frame std of the PURE real frame 0 should drop ~/sqrt(2) per level. // sqrt(2) check: full-frame std of the PURE real frame 0 should drop ~/sqrt(2) per level.
for (int nlev = 0; nlev < pyramid_levels; nlev++) { for (int nlev = 0; nlev < pyramid_levels; nlev++) {
if ((dpixels_pyramid[nlev] == null) || (dpixels_pyramid[nlev].length == 0)) continue; if ((dpixels_pyramid[nlev] == null) || (dpixels_pyramid[nlev].length == 0)) continue;
...@@ -1130,7 +1130,7 @@ public class CuasDetectRT { ...@@ -1130,7 +1130,7 @@ public class CuasDetectRT {
// across levels) while the real noise is averaged. Moving cells wrap every n_synth frames // across levels) while the real noise is averaged. Moving cells wrap every n_synth frames
// (a deliberate recurrent-decay test case). C5P/DNN read this; legacy 3d3-conv5d does not. // (a deliberate recurrent-decay test case). C5P/DNN read this; legacy 3d3-conv5d does not.
int n_synth = synth_pixels.length; int n_synth = synth_pixels.length;
boolean synth_bg = clt_parameters.imp.curt.synth_bg; // false = clean targets only: drop the real background (+its noise/NaNs) before injecting // By Claude on 06/15/2026 boolean synth_bg = clt_parameters.curt.synth_bg; // false = clean targets only: drop the real background (+its noise/NaNs) before injecting // By Claude on 06/15/2026
for (int nlev = 0; nlev < pyramid_levels; nlev++) { for (int nlev = 0; nlev < pyramid_levels; nlev++) {
if (!c5LevelSelected(c5_levels, nlev)) continue; if (!c5LevelSelected(c5_levels, nlev)) continue;
double [][] lev = dpixels_pyramid[nlev]; double [][] lev = dpixels_pyramid[nlev];
...@@ -1150,7 +1150,7 @@ public class CuasDetectRT { ...@@ -1150,7 +1150,7 @@ public class CuasDetectRT {
if (save_LoG_pixels) { if (save_LoG_pixels) {
for (int nlev = 0; nlev < pyramid_levels; nlev++) { for (int nlev = 0; nlev < pyramid_levels; nlev++) {
if (!c5LevelSelected(c5_levels, nlev) || (dpixels_pyramid[nlev] == null)) continue; if (!c5LevelSelected(c5_levels, nlev) || (dpixels_pyramid[nlev] == null)) continue;
String title_mix = getBaseName()+"-SYNTHMIX"+(synth_bg?"B":"")+(clt_parameters.imp.curt.subtract_avg?"-SUBAVG":"")+"-LEV"+nlev; String title_mix = getBaseName()+"-SYNTHMIX"+(synth_bg?"B":"")+(clt_parameters.curt.subtract_avg?"-SUBAVG":"")+"-LEV"+nlev;
ImagePlus imp_mix = ShowDoubleFloatArrays.makeArrays( ImagePlus imp_mix = ShowDoubleFloatArrays.makeArrays(
dpixels_pyramid[nlev], getWidth(), getHeight(), title_mix, ts_pyramid[nlev]); dpixels_pyramid[nlev], getWidth(), getHeight(), title_mix, ts_pyramid[nlev]);
imp_mix.setDisplayRange(CuasRTUtils.IMP_MINMAX[0], CuasRTUtils.IMP_MINMAX[1]); imp_mix.setDisplayRange(CuasRTUtils.IMP_MINMAX[0], CuasRTUtils.IMP_MINMAX[1]);
...@@ -1166,12 +1166,12 @@ public class CuasDetectRT { ...@@ -1166,12 +1166,12 @@ public class CuasDetectRT {
// same shape as the C5P output, saved as -DNN-RECT / -DNN-HYPER-RECT. N (temporal // same shape as the C5P output, saved as -DNN-RECT / -DNN-HYPER-RECT. N (temporal
// depth, 8 or 9) is read from the loaded ONNX. Reuses curt_c5_levels for level gating. Recurrent feed is the next step // depth, 8 or 9) is read from the loaded ONNX. Reuses curt_c5_levels for level gating. Recurrent feed is the next step
// (the field is [0,1]-scaled, unlike the C5P matched-filter response - needs rescale). // (the field is [0,1]-scaled, unlike the C5P matched-filter response - needs rescale).
if (!clt_parameters.imp.curt.dnn_model.isEmpty() && (curt_save_select != null) && !clt_parameters.imp.curt.dnn_remote && !clt_parameters.imp.curt.dnn_local) { // local CPU path (remote=DGX / curt_dnn_local=native LibTorch blocks below) // By Claude on 06/13/2026, remote guard 06/20/2026, local guard 06/27/2026 if (!clt_parameters.curt.dnn_model.isEmpty() && (curt_save_select != null) && !clt_parameters.curt.dnn_remote && !clt_parameters.curt.dnn_local) { // local CPU path (remote=DGX / curt_dnn_local=native LibTorch blocks below) // By Claude on 06/13/2026, remote guard 06/20/2026, local guard 06/27/2026
final int vr_dnn = clt_parameters.imp.curt.vel_radius; // By Claude on 06/13/2026 final int vr_dnn = clt_parameters.curt.vel_radius; // By Claude on 06/13/2026
final int dnn_stride = Math.max(1, clt_parameters.imp.curt.dnn_stride); // 1 = every slice (testing), 4 = production 50% overlap // By Claude on 06/14/2026 final int dnn_stride = Math.max(1, clt_parameters.curt.dnn_stride); // 1 = every slice (testing), 4 = production 50% overlap // By Claude on 06/14/2026
try { // By Claude on 06/13/2026 try { // By Claude on 06/13/2026
CuasDnnInfer dnn = new CuasDnnInfer(clt_parameters.imp.curt.dnn_model, 8); // 8 = fallback hint only // By Claude on 06/13/2026 CuasDnnInfer dnn = new CuasDnnInfer(clt_parameters.curt.dnn_model, 8); // 8 = fallback hint only // By Claude on 06/13/2026
dnn.setPatch(clt_parameters.imp.curt.dnn_patch); // 24 or 32 (RF/training patch) - must match the loaded model // By Claude on 06/16/2026 dnn.setPatch(clt_parameters.curt.dnn_patch); // 24 or 32 (RF/training patch) - must match the loaded model // By Claude on 06/16/2026
final int N_dnn = dnn.getNFrames(); // 8 or 9, read from the loaded ONNX input shape -> 8/9 models swap at runtime // By Claude on 06/15/2026 final int N_dnn = dnn.getNFrames(); // 8 or 9, read from the loaded ONNX input shape -> 8/9 models swap at runtime // By Claude on 06/15/2026
for (int nlev = 0; nlev < pyramid_levels; nlev++) { // By Claude on 06/13/2026 for (int nlev = 0; nlev < pyramid_levels; nlev++) { // By Claude on 06/13/2026
if (!c5LevelSelected(c5_levels, nlev)) continue; // level gating (curt_c5_levels) // By Claude on 06/13/2026 if (!c5LevelSelected(c5_levels, nlev)) continue; // level gating (curt_c5_levels) // By Claude on 06/13/2026
...@@ -1185,7 +1185,7 @@ public class CuasDetectRT { ...@@ -1185,7 +1185,7 @@ public class CuasDetectRT {
for (int k = 0; k < num_all; k++) cand_ts[k] = ts_pyramid[nlev][k * dnn_stride + N_dnn - 1]; // By Claude on 06/14/2026 for (int k = 0; k < num_all; k++) cand_ts[k] = ts_pyramid[nlev][k * dnn_stride + N_dnn - 1]; // By Claude on 06/14/2026
int [] tw = timeWindow(cand_ts); int w0 = tw[0], num = tw[1] - tw[0]; // By Claude on 06/14/2026 int [] tw = timeWindow(cand_ts); int w0 = tw[0], num = tw[1] - tw[0]; // By Claude on 06/14/2026
if (num <= 0) continue; // By Claude on 06/14/2026 if (num <= 0) continue; // By Claude on 06/14/2026
double dnn_thresh = clt_parameters.imp.curt.dnn_thresh; // By Claude on 06/13/2026 double dnn_thresh = clt_parameters.curt.dnn_thresh; // By Claude on 06/13/2026
if (dnn.isReg()) { // continuous-velocity (reg) head: save {S,Vx,Vy,sigma} + offset hyperstacks; no grid/ghostbuster/recurrent. By Claude on 06/17/2026 if (dnn.isReg()) { // continuous-velocity (reg) head: save {S,Vx,Vy,sigma} + offset hyperstacks; no grid/ghostbuster/recurrent. By Claude on 06/17/2026
String title_reg = title_conv5d+"-DNN"+((nlev > 0)?("-LEV"+nlev):"")+"-ROI"+curt_save_select.x+"_"+curt_save_select.y+"_"+curt_save_select.width+"_"+curt_save_select.height; String title_reg = title_conv5d+"-DNN"+((nlev > 0)?("-LEV"+nlev):"")+"-ROI"+curt_save_select.x+"_"+curt_save_select.y+"_"+curt_save_select.width+"_"+curt_save_select.height;
int rnpr = curt_save_select.width * curt_save_select.height; int rnpr = curt_save_select.width * curt_save_select.height;
...@@ -1216,13 +1216,13 @@ public class CuasDetectRT { ...@@ -1216,13 +1216,13 @@ public class CuasDetectRT {
svxys, curt_save_select.width, title_reg+"-VXYS", ts_reg, new String[]{"S","Vx","Vy","sigma"}, false), clt_parameters.imp), getModelDirectory()); svxys, curt_save_select.width, title_reg+"-VXYS", ts_reg, new String[]{"S","Vx","Vy","sigma"}, false), clt_parameters.imp), getModelDirectory());
QuadCLTCPU.saveImagePlusInDirectory(tagCuasImp(ShowDoubleFloatArrays.showArraysHyperstack( QuadCLTCPU.saveImagePlusInDirectory(tagCuasImp(ShowDoubleFloatArrays.showArraysHyperstack(
soffr, curt_save_select.width, title_reg+"-OFFSET", ts_reg, new String[]{"dx","dy","s"}, false), clt_parameters.imp), getModelDirectory()); soffr, curt_save_select.width, title_reg+"-OFFSET", ts_reg, new String[]{"dx","dy","s"}, false), clt_parameters.imp), getModelDirectory());
if (!clt_parameters.imp.curt.stage2_model.isEmpty()) { // v2 Stage-2: vote + learned refine views // By Claude on 06/18/2026 if (!clt_parameters.curt.stage2_model.isEmpty()) { // v2 Stage-2: vote + learned refine views // By Claude on 06/18/2026
int rw2 = curt_save_select.width, rh2 = curt_save_select.height, Nm1v = N_dnn - 1; int rw2 = curt_save_select.width, rh2 = curt_save_select.height, Nm1v = N_dnn - 1;
double [][][] votem = new double [1][num][rnpr]; // vote heatmap (accS), tail-indexed double [][][] votem = new double [1][num][rnpr]; // vote heatmap (accS), tail-indexed
double [][][] refd = new double [3][num][rnpr]; // refined {S,Vx,Vy}, tail-indexed double [][][] refd = new double [3][num][rnpr]; // refined {S,Vx,Vy}, tail-indexed
double [][][] heads = new double [1][num][rnpr]; // detection re-indexed to head (T0) // By Claude on 06/18/2026 double [][][] heads = new double [1][num][rnpr]; // detection re-indexed to head (T0) // By Claude on 06/18/2026
try { try {
CuasStage2Infer s2 = new CuasStage2Infer(clt_parameters.imp.curt.stage2_model); CuasStage2Infer s2 = new CuasStage2Infer(clt_parameters.curt.stage2_model);
for (int j = 0; j < num; j++) { for (int j = 0; j < num; j++) {
double [][] acc = voteScatter(svxys[0][j], svxys[1][j], svxys[2][j], rw2, rh2, Nm1v); double [][] acc = voteScatter(svxys[0][j], svxys[1][j], svxys[2][j], rw2, rh2, Nm1v);
votem[0][j] = acc[0].clone(); // raw vote heatmap (display) votem[0][j] = acc[0].clone(); // raw vote heatmap (display)
...@@ -1268,8 +1268,8 @@ public class CuasDetectRT { ...@@ -1268,8 +1268,8 @@ public class CuasDetectRT {
// grid distribution-vote (-GVOTE / -GHEADS via voteScatterGrid) removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026 // grid distribution-vote (-GVOTE / -GHEADS via voteScatterGrid) removed 2026-06-20; predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
// Ghostbuster: drop untrained corner velocities (cell-R > vmax*vel_decimate) before save // By Claude on 06/15/2026 // Ghostbuster: drop untrained corner velocities (cell-R > vmax*vel_decimate) before save // By Claude on 06/15/2026
// + recurrent feed, so the spurious corner sidelobes don't confuse the recurrent (s=0 for ghost-peak pixels) // + recurrent feed, so the spurious corner sidelobes don't confuse the recurrent (s=0 for ghost-peak pixels)
if (clt_parameters.imp.curt.dnn_vmax > 0) { // By Claude on 06/15/2026 if (clt_parameters.curt.dnn_vmax > 0) { // By Claude on 06/15/2026
double rmax_cells = clt_parameters.imp.curt.dnn_vmax * clt_parameters.imp.curt.vel_decimate; double rmax_cells = clt_parameters.curt.dnn_vmax * clt_parameters.curt.vel_decimate;
for (int j = 0; j < num; j++) dnnGhostbust(dnn_roi[j], dnn_off[j], vr_dnn, rmax_cells); for (int j = 0; j < num; j++) dnnGhostbust(dnn_roi[j], dnn_off[j], vr_dnn, rmax_cells);
} }
// ROI tag in the filename (x_y_w_h) so the python flight-log analysis auto-restores the ROI - no manual entry. By Claude on 06/16/2026 // ROI tag in the filename (x_y_w_h) so the python flight-log analysis auto-restores the ROI - no manual entry. By Claude on 06/16/2026
...@@ -1281,7 +1281,7 @@ public class CuasDetectRT { ...@@ -1281,7 +1281,7 @@ public class CuasDetectRT {
QuadCLTCPU.saveImagePlusInDirectory(tagCuasImp(cuasRTUtils.showConvKernel5d( // By Claude on 06/13/2026 QuadCLTCPU.saveImagePlusInDirectory(tagCuasImp(cuasRTUtils.showConvKernel5d( // By Claude on 06/13/2026
dnn_w, curt_save_select, ts_dnn_w, title_dnn+"-RECT"), clt_parameters.imp), getModelDirectory()); // metadata: all curt_* // By Claude on 06/16/2026 dnn_w, curt_save_select, ts_dnn_w, title_dnn+"-RECT"), clt_parameters.imp), getModelDirectory()); // metadata: all curt_* // By Claude on 06/16/2026
} // By Claude on 06/13/2026 } // By Claude on 06/13/2026
if (clt_parameters.imp.curt.save_c5hyper) { // By Claude on 06/13/2026 if (clt_parameters.curt.save_c5hyper) { // By Claude on 06/13/2026
QuadCLTCPU.saveImagePlusInDirectory(tagCuasImp(cuasRTUtils.showConvKernel5dHyperRect( // By Claude on 06/13/2026 QuadCLTCPU.saveImagePlusInDirectory(tagCuasImp(cuasRTUtils.showConvKernel5dHyperRect( // By Claude on 06/13/2026
dnn_w, curt_save_select, ts_dnn_w, title_dnn+"-HYPER-RECT"), clt_parameters.imp), getModelDirectory()); // metadata: all curt_* // By Claude on 06/16/2026 dnn_w, curt_save_select, ts_dnn_w, title_dnn+"-HYPER-RECT"), clt_parameters.imp), getModelDirectory()); // metadata: all curt_* // By Claude on 06/16/2026
} // By Claude on 06/13/2026 } // By Claude on 06/13/2026
...@@ -1307,8 +1307,8 @@ public class CuasDetectRT { ...@@ -1307,8 +1307,8 @@ public class CuasDetectRT {
// Feed the DNN field to the recurrent layer (Layer 2): as-is, or offset-splatted (px+dx,py+dy). // By Claude on 06/14/2026 // Feed the DNN field to the recurrent layer (Layer 2): as-is, or offset-splatted (px+dx,py+dy). // By Claude on 06/14/2026
// Tune the recurrent blend with curt_recur_w (0.25/0.75) etc.; the field is [0,1]-scaled so rs_min may need lowering. // Tune the recurrent blend with curt_recur_w (0.25/0.75) etc.; the field is [0,1]-scaled so rs_min may need lowering.
if (run_recur && (num > 0)) { if (run_recur && (num > 0)) {
boolean splat = clt_parameters.imp.curt.dnn_recur_splat; boolean splat = clt_parameters.curt.dnn_recur_splat;
double rscale = clt_parameters.imp.curt.dnn_recur_scale; // DNN field ~0.1 -> recurrent rs_min ~1.0 // By Claude on 06/14/2026 double rscale = clt_parameters.curt.dnn_recur_scale; // DNN field ~0.1 -> recurrent rs_min ~1.0 // By Claude on 06/14/2026
double [][][][] dnn_feed = new double [num][][][]; double [][][][] dnn_feed = new double [num][][][];
for (int j = 0; j < num; j++) { for (int j = 0; j < num; j++) {
double [][][] f = splat ? splatField(dnn_roi[j], dnn_off[j], curt_save_select) : dnn_roi[j]; double [][][] f = splat ? splatField(dnn_roi[j], dnn_off[j], curt_save_select) : dnn_roi[j];
...@@ -1333,7 +1333,7 @@ public class CuasDetectRT { ...@@ -1333,7 +1333,7 @@ public class CuasDetectRT {
} // By Claude on 06/13/2026 } // By Claude on 06/13/2026
} // By Claude on 06/13/2026 } // By Claude on 06/13/2026
// Remote DGX inference path (curt_dnn_remote): upload conditioned stack, DGX builds pyramid + infers. // By Claude on 06/20/2026 // Remote DGX inference path (curt_dnn_remote): upload conditioned stack, DGX builds pyramid + infers. // By Claude on 06/20/2026
if ((curt_save_select != null) && (clt_parameters.imp.curt.dnn_remote || clt_parameters.imp.curt.dnn_local)) { // DGX server OR in-process native LibTorch (curt_dnn_local). By Claude on 06/27/2026 if ((curt_save_select != null) && (clt_parameters.curt.dnn_remote || clt_parameters.curt.dnn_local)) { // DGX server OR in-process native LibTorch (curt_dnn_local). By Claude on 06/27/2026
runDnnRemote(clt_parameters, cuasRTUtils, dpixels_log, ts_pyramid, pyramid_levels, c5_levels, curt_save_select, title_conv5d); // By Claude on 06/20/2026 runDnnRemote(clt_parameters, cuasRTUtils, dpixels_log, ts_pyramid, pyramid_levels, c5_levels, curt_save_select, title_conv5d); // By Claude on 06/20/2026
} }
System.out.println(now()+" detectTargets(): done"); // By Claude on 06/11/2026 System.out.println(now()+" detectTargets(): done"); // By Claude on 06/11/2026
......
...@@ -466,7 +466,7 @@ public class CuasPoseRT { ...@@ -466,7 +466,7 @@ public class CuasPoseRT {
/** /**
* Re-generate per-scene poses against the virtual-center reference, RT-style. * Re-generate per-scene poses against the virtual-center reference, RT-style.
* *
* @param clt_parameters processing parameters (uses imp.curt.pose_str threshold, * @param clt_parameters processing parameters (uses curt.pose_str threshold,
* imp.lma_use_R, LMA/offset limits as the offline flow) * imp.lma_use_R, LMA/offset limits as the offline flow)
* @param center_CLT virtual-center reference: must have CenterClt (fclt) and * @param center_CLT virtual-center reference: must have CenterClt (fclt) and
* the final combo DSI restored * the final combo DSI restored
...@@ -480,7 +480,7 @@ public class CuasPoseRT { ...@@ -480,7 +480,7 @@ public class CuasPoseRT {
final QuadCLT center_CLT, final QuadCLT center_CLT,
final QuadCLT [] quadCLTs, final QuadCLT [] quadCLTs,
final int debugLevel) { final int debugLevel) {
final double min_str = clt_parameters.imp.curt.pose_str; // e.g. 1.0 final double min_str = clt_parameters.curt.pose_str; // e.g. 1.0
final boolean use_lma_dsi = clt_parameters.imp.use_lma_dsi; final boolean use_lma_dsi = clt_parameters.imp.use_lma_dsi;
final int margin = clt_parameters.imp.margin; final int margin = clt_parameters.imp.margin;
final double mb_tau = clt_parameters.imp.mb_tau; final double mb_tau = clt_parameters.imp.mb_tau;
...@@ -530,9 +530,9 @@ public class CuasPoseRT { ...@@ -530,9 +530,9 @@ public class CuasPoseRT {
// rank-N budget) and AND with the strength mask - a filtered run. Otherwise run FULL // rank-N budget) and AND with the strength mask - a filtered run. Otherwise run FULL
// (all strength-selected tiles) and generate the calibration at the end. // (all strength-selected tiles) and generate the calibration at the end.
boolean full_selection = true; // the tile calibration is (re)saved only from a full-selection run boolean full_selection = true; // the tile calibration is (re)saved only from a full-selection run
ImagePlus imp_max = clt_parameters.imp.curt.pose_recalc ? null : ImagePlus imp_max = clt_parameters.curt.pose_recalc ? null :
center_CLT.readImagePlusFromModelDirectory(TILE_CALIB_SUFFIX); center_CLT.readImagePlusFromModelDirectory(TILE_CALIB_SUFFIX);
if ((imp_max == null) && !clt_parameters.imp.curt.pose_recalc) { // legacy name fallback if ((imp_max == null) && !clt_parameters.curt.pose_recalc) { // legacy name fallback
imp_max = center_CLT.readImagePlusFromModelDirectory(TILE_CALIB_SUFFIX_OLD); imp_max = center_CLT.readImagePlusFromModelDirectory(TILE_CALIB_SUFFIX_OLD);
} }
if (imp_max != null) { if (imp_max != null) {
...@@ -540,8 +540,8 @@ public class CuasPoseRT { ...@@ -540,8 +540,8 @@ public class CuasPoseRT {
final boolean [] filt = deriveSelection( final boolean [] filt = deriveSelection(
fmax, fmax,
center_CLT.getTilesX(), center_CLT.getTilesX(),
clt_parameters.imp.curt.pose_dxy_k, clt_parameters.curt.pose_dxy_k,
clt_parameters.imp.curt.pose_num_tiles, clt_parameters.curt.pose_num_tiles,
debugLevel); debugLevel);
int num_filt = 0; int num_filt = 0;
for (int i = 0; i < reliable_ref.length; i++) { for (int i = 0; i < reliable_ref.length; i++) {
...@@ -553,7 +553,7 @@ public class CuasPoseRT { ...@@ -553,7 +553,7 @@ public class CuasPoseRT {
num_filt+" tiles (of "+num_reliable+" by strength)"); num_filt+" tiles (of "+num_reliable+" by strength)");
} else { } else {
System.out.println("CuasPoseRT.testPoseSequence(): "+ System.out.println("CuasPoseRT.testPoseSequence(): "+
(clt_parameters.imp.curt.pose_recalc ? "curt_pose_recalc ON" : TILE_CALIB_SUFFIX+" not found")+ (clt_parameters.curt.pose_recalc ? "curt_pose_recalc ON" : TILE_CALIB_SUFFIX+" not found")+
" - FULL run, will generate the calibration"); " - FULL run, will generate the calibration");
} }
final double [][] pXpYD_center = OpticalFlow.transformToScenePxPyD( final double [][] pXpYD_center = OpticalFlow.transformToScenePxPyD(
...@@ -620,7 +620,7 @@ public class CuasPoseRT { ...@@ -620,7 +620,7 @@ public class CuasPoseRT {
} }
// Phase B lean engine (curt_pose_lean): ImageDtt instance for the convert stage, // Phase B lean engine (curt_pose_lean): ImageDtt instance for the convert stage,
// created once (mirrors interCorrPair's construction) // created once (mirrors interCorrPair's construction)
final ImageDtt image_dtt_lean = clt_parameters.imp.curt.pose_lean ? new ImageDtt( final ImageDtt image_dtt_lean = clt_parameters.curt.pose_lean ? new ImageDtt(
center_CLT.getNumSensors(), center_CLT.getNumSensors(),
clt_parameters.transform_size, clt_parameters.transform_size,
clt_parameters.img_dtt, clt_parameters.img_dtt,
...@@ -629,7 +629,7 @@ public class CuasPoseRT { ...@@ -629,7 +629,7 @@ public class CuasPoseRT {
center_CLT.isLwir(), center_CLT.isLwir(),
clt_parameters.getScaleStrength(center_CLT.isAux()), clt_parameters.getScaleStrength(center_CLT.isAux()),
center_CLT.getGPU()) : null; center_CLT.getGPU()) : null;
if (clt_parameters.imp.curt.pose_lean) { if (clt_parameters.curt.pose_lean) {
System.out.println("CuasPoseRT.testPoseSequence(): LEAN measurement engine (phase B): "+ System.out.println("CuasPoseRT.testPoseSequence(): LEAN measurement engine (phase B): "+
"TD-average(16) x virtual-center single conj-multiply. NOTE: no MB compensation "+ "TD-average(16) x virtual-center single conj-multiply. NOTE: no MB compensation "+
"in lean v1 - compare against the NOMB baseline"); "in lean v1 - compare against the NOMB baseline");
...@@ -666,7 +666,7 @@ public class CuasPoseRT { ...@@ -666,7 +666,7 @@ public class CuasPoseRT {
// the upload alive through interCorrPair's own setBayerImages(false). // the upload alive through interCorrPair's own setBayerImages(false).
// A2 results legitimately diverge from phase A (cleaner input) - judge by own // A2 results legitimately diverge from phase A (cleaner input) - judge by own
// dstored quality. By Claude on 07/05/2026, from Andrey's design. // dstored quality. By Claude on 07/05/2026, from Andrey's design.
if (clt_parameters.imp.curt.pose_raw) { if (clt_parameters.curt.pose_raw) {
final boolean raw_ok = CuasConditioning.conditionSceneToGpu( final boolean raw_ok = CuasConditioning.conditionSceneToGpu(
quadCLTs[nscene], // QuadCLT scene (jp4 + calibration + FPN) quadCLTs[nscene], // QuadCLT scene (jp4 + calibration + FPN)
null, // Config (defaults: rowcol + photometric + FPN) null, // Config (defaults: rowcol + photometric + FPN)
...@@ -711,7 +711,7 @@ public class CuasPoseRT { ...@@ -711,7 +711,7 @@ public class CuasPoseRT {
fail_reason[0] = 0; fail_reason[0] = 0;
final double [][][] coord_motion_rslt = new double [3][][]; // [centers, vector_XYS, eigen] of the last LMA cycle final double [][][] coord_motion_rslt = new double [3][][]; // [centers, vector_XYS, eigen] of the last LMA cycle
double [][] pose; double [][] pose;
if (clt_parameters.imp.curt.pose_lean) { if (clt_parameters.curt.pose_lean) {
pose = leanFitScene( pose = leanFitScene(
clt_parameters, // CLTParameters clt_parameters, clt_parameters, // CLTParameters clt_parameters,
image_dtt_lean, // ImageDtt image_dtt, image_dtt_lean, // ImageDtt image_dtt,
...@@ -882,8 +882,8 @@ public class CuasPoseRT { ...@@ -882,8 +882,8 @@ public class CuasPoseRT {
final boolean [] keep = deriveSelection( final boolean [] keep = deriveSelection(
fmax, fmax,
tilesX, tilesX,
clt_parameters.imp.curt.pose_dxy_k, clt_parameters.curt.pose_dxy_k,
clt_parameters.imp.curt.pose_num_tiles, clt_parameters.curt.pose_num_tiles,
debugLevel); debugLevel);
final float [] fkeep = new float [num_pix]; final float [] fkeep = new float [num_pix];
for (int i = 0; i < num_pix; i++) fkeep[i] = keep[i] ? 1.0f : 0.0f; for (int i = 0; i < num_pix; i++) fkeep[i] = keep[i] ? 1.0f : 0.0f;
......
...@@ -1123,8 +1123,6 @@ min_str_neib_fpn 0.35 ...@@ -1123,8 +1123,6 @@ min_str_neib_fpn 0.35
public double cuas_min_disp_str = 0.4; // Minimal disparity strength to consider disparity valid public double cuas_min_disp_str = 0.4; // Minimal disparity strength to consider disparity valid
public double cuas_rng_limit = 5000; // maximal displayed distance to target public double cuas_rng_limit = 5000; // maximal displayed distance to target
// CUAS Realtime
public CuasRtParameters curt = new CuasRtParameters(); // all curt_* extracted here // By Claude on 07/05/2026
//=== LoG prefilter === //=== LoG prefilter ===
// rleak0 removed 2026-06-20: LReLU conditioning is now LINEAR (alpha=1.0); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026 // rleak0 removed 2026-06-20: LReLU conditioning is now LINEAR (alpha=1.0); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
//=== Temporal binary pyramid === //=== Temporal binary pyramid ===
...@@ -3356,9 +3354,6 @@ min_str_neib_fpn 0.35 ...@@ -3356,9 +3354,6 @@ min_str_neib_fpn 0.35
gd.addNumericField("Maximal displayed distance", this.cuas_rng_limit, 6,8,"m", gd.addNumericField("Maximal displayed distance", this.cuas_rng_limit, 6,8,"m",
"Maximal displayed distance to target."); "Maximal displayed distance to target.");
gd.addTab("CUAS RT", "CUAS Real Time");
curt.dialogQuestions(gd); // By Claude on 07/05/2026
gd.addTab("Airplane","Airplane mode (fast forward movement, low vertical speed"); gd.addTab("Airplane","Airplane mode (fast forward movement, low vertical speed");
gd.addCheckbox ("Enable airplane mode", this.air_mode_en, gd.addCheckbox ("Enable airplane mode", this.air_mode_en,
"Apply algorithms specific to the airplane mode."); "Apply algorithms specific to the airplane mode.");
...@@ -4829,8 +4824,6 @@ min_str_neib_fpn 0.35 ...@@ -4829,8 +4824,6 @@ min_str_neib_fpn 0.35
this.cuas_min_disp_str = gd.getNextNumber(); this.cuas_min_disp_str = gd.getNextNumber();
this.cuas_rng_limit = gd.getNextNumber(); this.cuas_rng_limit = gd.getNextNumber();
curt.dialogAnswers(gd); // By Claude on 07/05/2026
this.air_mode_en = gd.getNextBoolean(); this.air_mode_en = gd.getNextBoolean();
this.air_sync_ims = gd.getNextBoolean(); this.air_sync_ims = gd.getNextBoolean();
this.air_disp_corr = gd.getNextBoolean(); this.air_disp_corr = gd.getNextBoolean();
...@@ -6131,8 +6124,6 @@ min_str_neib_fpn 0.35 ...@@ -6131,8 +6124,6 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"cuas_min_disp_str", this.cuas_min_disp_str+""); // double properties.setProperty(prefix+"cuas_min_disp_str", this.cuas_min_disp_str+""); // double
properties.setProperty(prefix+"cuas_rng_limit", this.cuas_rng_limit+""); // double properties.setProperty(prefix+"cuas_rng_limit", this.cuas_rng_limit+""); // double
curt.setProperties(prefix+"curt_", properties); // By Claude on 07/05/2026
properties.setProperty(prefix+"air_mode_en", this.air_mode_en+""); // boolean properties.setProperty(prefix+"air_mode_en", this.air_mode_en+""); // boolean
properties.setProperty(prefix+"air_sync_ims", this.air_sync_ims+""); // boolean properties.setProperty(prefix+"air_sync_ims", this.air_sync_ims+""); // boolean
properties.setProperty(prefix+"air_disp_corr", this.air_disp_corr+""); // boolean properties.setProperty(prefix+"air_disp_corr", this.air_disp_corr+""); // boolean
...@@ -7421,8 +7412,6 @@ min_str_neib_fpn 0.35 ...@@ -7421,8 +7412,6 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"cuas_min_disp_str")!=null) this.cuas_min_disp_str=Double.parseDouble(properties.getProperty(prefix+"cuas_min_disp_str")); if (properties.getProperty(prefix+"cuas_min_disp_str")!=null) this.cuas_min_disp_str=Double.parseDouble(properties.getProperty(prefix+"cuas_min_disp_str"));
if (properties.getProperty(prefix+"cuas_rng_limit")!=null) this.cuas_rng_limit=Double.parseDouble(properties.getProperty(prefix+"cuas_rng_limit")); if (properties.getProperty(prefix+"cuas_rng_limit")!=null) this.cuas_rng_limit=Double.parseDouble(properties.getProperty(prefix+"cuas_rng_limit"));
curt.getProperties(prefix+"curt_", properties); // By Claude on 07/05/2026
if (properties.getProperty(prefix+"air_mode_en")!=null) this.air_mode_en=Boolean.parseBoolean(properties.getProperty(prefix+"air_mode_en")); if (properties.getProperty(prefix+"air_mode_en")!=null) this.air_mode_en=Boolean.parseBoolean(properties.getProperty(prefix+"air_mode_en"));
if (properties.getProperty(prefix+"air_sync_ims")!=null) this.air_sync_ims=Boolean.parseBoolean(properties.getProperty(prefix+"air_sync_ims")); if (properties.getProperty(prefix+"air_sync_ims")!=null) this.air_sync_ims=Boolean.parseBoolean(properties.getProperty(prefix+"air_sync_ims"));
if (properties.getProperty(prefix+"air_disp_corr")!=null) this.air_disp_corr=Boolean.parseBoolean(properties.getProperty(prefix+"air_disp_corr")); if (properties.getProperty(prefix+"air_disp_corr")!=null) this.air_disp_corr=Boolean.parseBoolean(properties.getProperty(prefix+"air_disp_corr"));
...@@ -8687,8 +8676,6 @@ min_str_neib_fpn 0.35 ...@@ -8687,8 +8676,6 @@ min_str_neib_fpn 0.35
imp.cuas_min_disp_str = this.cuas_min_disp_str; imp.cuas_min_disp_str = this.cuas_min_disp_str;
imp.cuas_rng_limit = this.cuas_rng_limit; imp.cuas_rng_limit = this.cuas_rng_limit;
try { imp.curt = this.curt.clone(); } catch (CloneNotSupportedException e) {} // By Claude on 07/05/2026
imp.air_mode_en = this.air_mode_en; imp.air_mode_en = this.air_mode_en;
imp.air_sync_ims = this.air_sync_ims; imp.air_sync_ims = this.air_sync_ims;
imp.air_disp_corr = this.air_disp_corr; imp.air_disp_corr = this.air_disp_corr;
......
...@@ -7239,7 +7239,7 @@ java.lang.NullPointerException ...@@ -7239,7 +7239,7 @@ java.lang.NullPointerException
// Moved to the very end, after 3D // Moved to the very end, after 3D
// boolean test_vegetation = true; // boolean test_vegetation = true;
if (master_CLT.hasCenterClt() && clt_parameters.imp.cuas_targets_en && !clt_parameters.imp.curt.en) { // cuas mode if (master_CLT.hasCenterClt() && clt_parameters.imp.cuas_targets_en && !clt_parameters.curt.en) { // cuas mode
if (debugLevel >-3) { if (debugLevel >-3) {
System.out.println("===== Running CUAS ranging in Oracle mode. ====="); System.out.println("===== Running CUAS ranging in Oracle mode. =====");
} }
...@@ -7264,7 +7264,7 @@ java.lang.NullPointerException ...@@ -7264,7 +7264,7 @@ java.lang.NullPointerException
// Generate the merged-CUAS stack on the GPU EXPLICITLY here (CuasRanging.prepareFpixels() uses the CUDA // Generate the merged-CUAS stack on the GPU EXPLICITLY here (CuasRanging.prepareFpixels() uses the CUDA
// tile-processor kernels - may be incompatible with a future CUDA), then hand the plain ImagePlus to the // tile-processor kernels - may be incompatible with a future CUDA), then hand the plain ImagePlus to the
// CUDA-free CuasDetectRT. By Claude on 06/24/2026 // CUDA-free CuasDetectRT. By Claude on 06/24/2026
if (clt_parameters.imp.curt.en && master_CLT.hasCenterClt()) { if (clt_parameters.curt.en && master_CLT.hasCenterClt()) {
System.out.println("===== Running CUAS RT detection (curt_en). ====="); System.out.println("===== Running CUAS RT detection (curt_en). =====");
CuasRanging cuasRangingRT = new CuasRanging( CuasRanging cuasRangingRT = new CuasRanging(
clt_parameters, // CLTParameters clt_parameters, clt_parameters, // CLTParameters clt_parameters,
...@@ -7274,7 +7274,7 @@ java.lang.NullPointerException ...@@ -7274,7 +7274,7 @@ java.lang.NullPointerException
ImagePlus imp_targets = cuasRangingRT.prepareFpixels(); // GPU generator (explicit, CUDA-sensitive); also builds the QuadCLT instances = borrowed-calibration source ImagePlus imp_targets = cuasRangingRT.prepareFpixels(); // GPU generator (explicit, CUDA-sensitive); also builds the QuadCLT instances = borrowed-calibration source
if (clt_parameters.imp.curt.calib) { if (clt_parameters.curt.calib) {
// By Claude on 07/03/2026: first step of the CUAS RT processing flow - per-sensor photometric // By Claude on 07/03/2026: 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, // (re)calibration: fit a+b*x over safe (weak/far) tiles, fold into the 16+16 lwir offsets/scales,
// apply in memory (master_CLT + reference scene + quadCLT_main -> top-menu config, template for // apply in memory (master_CLT + reference scene + quadCLT_main -> top-menu config, template for
...@@ -7285,11 +7285,11 @@ java.lang.NullPointerException ...@@ -7285,11 +7285,11 @@ java.lang.NullPointerException
master_CLT, // QuadCLT master_CLT (combo DSI source, in-memory apply) master_CLT, // QuadCLT master_CLT (combo DSI source, in-memory apply)
quadCLTs[ref_index], // QuadCLT ref_scene (photometric owner, INTERFRAME corr-xml) quadCLTs[ref_index], // QuadCLT ref_scene (photometric owner, INTERFRAME corr-xml)
quadCLT_main, // QuadCLT quadCLT_main (main config + new-instance template) quadCLT_main, // QuadCLT quadCLT_main (main config + new-instance template)
clt_parameters.imp.curt.cond_test, // boolean save_stacks clt_parameters.curt.cond_test, // boolean save_stacks
ImageDtt.THREADS_MAX, // int threadsMax, ImageDtt.THREADS_MAX, // int threadsMax,
debugLevel); // int debugLevel debugLevel); // int debugLevel
} }
if (clt_parameters.imp.curt.pose_test) { if (clt_parameters.curt.pose_test) {
// RT pose-adjustment prototype phase A (curt_pose_test), runs INSTEAD of RT detection: // RT pose-adjustment prototype phase A (curt_pose_test), runs INSTEAD of RT detection:
// re-generate per-scene 3-angle poses against the virtual-center reference, ascending, // re-generate per-scene 3-angle poses against the virtual-center reference, ascending,
// prediction-seeded, single pass on the final combo DSI. Output: -POSE-RT-TEST.csv + // prediction-seeded, single pass on the final combo DSI. Output: -POSE-RT-TEST.csv +
...@@ -7301,14 +7301,14 @@ java.lang.NullPointerException ...@@ -7301,14 +7301,14 @@ java.lang.NullPointerException
master_CLT, // QuadCLT center_CLT, master_CLT, // QuadCLT center_CLT,
quadCLTs, // QuadCLT [] quadCLTs, quadCLTs, // QuadCLT [] quadCLTs,
debugLevel); // int debugLevel debugLevel); // int debugLevel
} else if (clt_parameters.imp.curt.cond_test) { } else if (clt_parameters.curt.cond_test) {
// Conditioning/calibration diagnostic (curt_cond_test), runs INSTEAD of RT detection: // Conditioning/calibration diagnostic (curt_cond_test), runs INSTEAD of RT detection:
// raw /jp4/ baseline (no photometric/FPN/conditioning), saved as -CUAS-PERSENSOR-RAW for // raw /jp4/ baseline (no photometric/FPN/conditioning), saved as -CUAS-PERSENSOR-RAW for
// side-by-side compare with the conditioned -CUAS-PERSENSOR (saved by the calibration step when // side-by-side compare with the conditioned -CUAS-PERSENSOR (saved by the calibration step when
// curt_calib is on, or rendered here otherwise). Both stacks use the same uniform sensor-domain // curt_calib is on, or rendered here otherwise). Both stacks use the same uniform sensor-domain
// task grid - never leftover GPU task state. By Claude on 07/01/2026, restructured 07/03/2026. // task grid - never leftover GPU task state. By Claude on 07/01/2026, restructured 07/03/2026.
System.out.println("===== CUAS RT conditioning test (curt_cond_test): per-sensor average spread ====="); System.out.println("===== CUAS RT conditioning test (curt_cond_test): per-sensor average spread =====");
if (!clt_parameters.imp.curt.calib) { // conditioned baseline not yet rendered by the calibration step if (!clt_parameters.curt.calib) { // conditioned baseline not yet rendered by the calibration step
QuadCLT cond_phys = master_CLT.getGPUQuad().getQuadCLT(); // physical scene bound to the GPU QuadCLT cond_phys = master_CLT.getGPUQuad().getQuadCLT(); // physical scene bound to the GPU
if (cond_phys != null) { // the actual image_data (bypass image_data_alt), same grid as raw if (cond_phys != null) { // the actual image_data (bypass image_data_alt), same grid as raw
CuasMotion.perSensorFromData(clt_parameters, master_CLT, cond_phys.getOrigImageData(), CuasMotion.perSensorFromData(clt_parameters, master_CLT, cond_phys.getOrigImageData(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment