Commit 189b7f39 authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: curt.kernel_test dropdown - one GPU-kernel oracle test per run

Replaces the would-be per-kernel checkbox sprawl (Andrey 07/12 design):
- CuasRtParameters: KERNEL_TESTS registry {none, avg_td} + kernel_test
  String param (addChoice, corr-xml _curt_kernel_test, unknown values
  sanitized to none); one dropdown entry per kernel in the 2c+ ladder.
- CuasRT.diagnostics(): kernel_test != none -> EXCLUSIVE kernelTest()
  dispatch, nothing else runs that pass.
- kernelTest() avg_td case = the AvgTdExport call site (settles the open
  pick): conditioned image_data of the GPU-bound scene -> uniform-grid
  convert -> CPU oracle + testdata case export (<model>/testdata/avg_td,
  incl. per-sensor TpTask XY for the OOB soft/hard-margin stage) ->
  validateConsolidation; imports+compares C++ results/ when present,
  else prints the exact tests_bin command to run.
- CuasMotion.convertFromData: overload with tasks_out (old signature
  delegates) so the export gets the conversion TpTask grid.

mvn -DskipTests clean package: OK. Run validation in Eclipse = Andrey's.
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent aa681507
......@@ -4111,6 +4111,24 @@ public class CuasMotion {
String name_tag,
int threadsMax,
int debugLevel) {
return convertFromData(clt_parameters, gpuQuad, data, name_tag, null, threadsMax, debugLevel); // By Claude on 07/12/2026
}
/**
* Same as {@link #convertFromData} but also hands back the uniform-grid TpTask
* array used for the conversion (tasks_out[0]) - the GPU-kernel testdata export
* (curt.kernel_test) needs the per-sensor tile XY for the OOB soft/hard-margin
* stage of clt_average_sensors (roadmap 2c). By Claude on 07/12/2026.
* @param tasks_out null, or TpTask[1][] filled with the conversion task grid.
*/
public static boolean convertFromData( // By Claude on 07/12/2026
CLTParameters clt_parameters,
GpuQuad gpuQuad,
double [][][] data,
String name_tag,
TpTask [][] tasks_out,
int threadsMax,
int debugLevel) {
final QuadCLT qclt = gpuQuad.getQuadCLT(); // physical scene bound to the GPU (geometry already loaded)
if (qclt == null) {
System.out.println("convertFromData(): no physical scene bound to the GPU - skipping");
......@@ -4120,6 +4138,7 @@ public class CuasMotion {
qclt, // final QuadCLT qclt,
clt_parameters.imp.disparity_corr + qclt.getDispInfinityRef(), // final double disparity_corr,
threadsMax); // final int threadsMax)
if (tasks_out != null) tasks_out[0] = tp_tasks; // By Claude on 07/12/2026
final ImageDtt image_dtt = new ImageDtt(
qclt.getNumSensors(),
clt_parameters.transform_size,
......
......@@ -22,9 +22,12 @@
*/
package com.elphel.imagej.cuas.rt;
import java.io.File; // By Claude on 07/12/2026
import java.io.IOException; // By Claude on 07/12/2026
import java.util.Arrays;
import com.elphel.imagej.cuas.CuasMotion;
import com.elphel.imagej.gpu.testdata.AvgTdExport; // By Claude on 07/12/2026
import com.elphel.imagej.cuas.CuasRanging;
import com.elphel.imagej.gpu.GpuQuad;
import com.elphel.imagej.gpu.TpTask;
......@@ -350,6 +353,14 @@ public class CuasRT {
final QuadCLT [] quadCLTs,
final int debugLevel) {
boolean ran = false;
if (!"none".equals(clt_parameters.curt.kernel_test)) {
// GPU-kernel oracle test (curt_kernel_test dropdown): EXCLUSIVE - one Java run
// exports ONE kernel's testdata case; nothing else runs, so a saved config
// can't accidentally mix a kernel test into other diagnostics/production.
// By Claude on 07/12/2026, from Andrey's design.
kernelTest(clt_parameters, master_CLT, debugLevel);
return true;
}
if (clt_parameters.curt.pose_test) {
// The POSE stage (part of the RT cycle): re-generate per-scene 3-angle poses
// against the virtual-center reference, ascending, prediction-seeded, single
......@@ -407,6 +418,64 @@ public class CuasRT {
return ran;
}
/**
* GPU-kernel oracle test dispatch (curt.kernel_test dropdown - one kernel per
* Java run, Andrey 07/12/2026). For the selected kernel: build/borrow its live
* inputs, run the CPU oracle, and export a self-describing testdata case
* (<model>/testdata/<kernel>) for the standalone NSight-debuggable CUDA test
* (tile_processor_gpu: tests_bin/test_<kernel> --data <case> --tol 0). When the
* C++ test already ran on this case, its results/ are imported and compared
* Java-side too (round-trip). Adding a kernel = one name in
* CuasRtParameters.KERNEL_TESTS + one case here. By Claude on 07/12/2026.
*/
private static void kernelTest(
final CLTParameters clt_parameters,
final QuadCLT master_CLT,
final int debugLevel) {
final String kernel = clt_parameters.curt.kernel_test;
System.out.println("===== CUAS RT GPU-kernel test (curt_kernel_test): "+kernel+" =====");
final GpuQuad gpuQuad = master_CLT.getGPUQuad();
final QuadCLT phys = gpuQuad.getQuadCLT(); // physical scene bound to the GPU: conditioned data + geometry
if (phys == null) {
System.out.println("kernelTest("+kernel+"): no physical scene bound to the GPU - skipping");
return;
}
final String dir_path = new File(new File(master_CLT.getX3dDirectory(), "testdata"), kernel).getPath();
try {
switch (kernel) {
case "avg_td": {
// clt_average_sensors (roadmap 2c): convert the bound scene's conditioned
// image_data with the uniform calibration task grid (identical to the
// cond_test/calib conversion), run the CPU oracle
// (CuasTD.consolidateSensorsTD) and export the case including per-sensor
// TpTask XY - the input of the OOB soft/hard-margin priority stage.
final TpTask [][] tasks_out = new TpTask [1][];
if (!CuasMotion.convertFromData(clt_parameters, gpuQuad, phys.getOrigImageData(),
"-KERNEL-TEST-AVG-TD", tasks_out, ImageDtt.THREADS_MAX, debugLevel)) {
return;
}
AvgTdExport.export(gpuQuad, false, tasks_out[0], dir_path, phys.getImageName(), debugLevel);
CuasTD.validateConsolidation(gpuQuad, master_CLT, debugLevel); // imclt-linearity check + counts stats
break;
}
default:
System.out.println("kernelTest(): unknown kernel test '"+kernel+
"' - update CuasRT.kernelTest() to match CuasRtParameters.KERNEL_TESTS");
return;
}
if (new File(dir_path, "results").isDirectory()) { // C++ results from a previous run of THIS case
System.out.println("kernelTest("+kernel+"): NOTE - results/ predate this export if the case just changed");
AvgTdExport.compareResults(dir_path, debugLevel);
} else {
System.out.println("kernelTest("+kernel+"): now run (tile_processor_gpu): tests_bin/test_"+
kernel+" --data "+dir_path+" --tol 0");
}
} catch (IOException e) {
System.out.println("kernelTest("+kernel+"): export/compare FAILED: "+e.getMessage());
e.printStackTrace();
}
}
/**
* Production target detection (CUDA-free from here on: consumes the plain ImagePlus).
* By Claude on 06/24/2026 (moved 07/05/2026).
......
......@@ -30,6 +30,8 @@ public class CuasRtParameters {
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"}; // 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. // By Claude on 07/12/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
......@@ -95,6 +97,11 @@ public class CuasRtParameters {
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.addCheckbox ("CUAS realtime enable", this.en,
"Enable testing of the realtime CUAS detection.");
......@@ -129,6 +136,8 @@ public class CuasRtParameters {
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.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.");
......@@ -295,6 +304,7 @@ public class CuasRtParameters {
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
......@@ -390,6 +400,7 @@ public class CuasRtParameters {
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
......@@ -485,6 +496,7 @@ public class CuasRtParameters {
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
......@@ -583,6 +595,7 @@ public class CuasRtParameters {
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
......
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