Commit abca0375 authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: CuasPoseRT: -POSE-RT-MAXDXY calibration artifact, NMAD outlier gate + rank-N selection

Replaces the absolute curt_pose_max_dxy with the scale-free scheme (Andrey's
histogram rule formalized + robustness for worse footage):
- Calibration artifact -POSE-RT-MAXDXY.tiff: per-tile max-over-scenes residual,
  +inf where any scene NaN (auto-reject, mergeable across runs by max), NaN
  where unmeasured. Saved only from FULL-selection runs (a filtered run never
  shrinks coverage). Continuous statistic persisted, boolean selection derived
  at load - policy can change without re-measuring.
- deriveSelection(): stage 1 outlier gate keep max <= median + k*NMAD of finite
  per-tile maxes (curt_pose_dxy_k=0.75; on the reference footage: MBEN gate
  0.477 keeps 595, degraded NOMB self-adapts to 0.728 keeps 626 - same ~65%);
  stage 2 rank-N budget keep curt_pose_num_tiles=150 best (threshold-free).
- curt_pose_use_filt now loads MAXDXY and derives; missing -> full run
  generates it (FPN-style reuse pattern).
Importance-greedy (3x3 information matrix) ranking = next step.

mvn compile clean.
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent 3f96868f
...@@ -86,6 +86,59 @@ public class CuasPoseRT { ...@@ -86,6 +86,59 @@ public class CuasPoseRT {
public static final String [] HYPER_COMPONENTS = public static final String [] HYPER_COMPONENTS =
{"dx", "dy", "strength", "dxy", "sqrt_l0", "sqrt_l1", "elong", "eig0_ang"}; {"dx", "dy", "strength", "dxy", "sqrt_l0", "sqrt_l1", "elong", "eig0_ang"};
/**
* Derive the tile selection from the per-tile max-residual calibration array
* (-POSE-RT-MAXDXY: max over scenes of measured dxy; +inf = NaN in some scene;
* NaN = tile not measured). Two scale-free stages, both adapt to footage quality
* and sequence length (no absolute pixel constants):
* 1 - robust outlier gate: keep finite values <= median + k_nmad*NMAD of the
* finite population (the "single high bump + long tail" histogram rule);
* 2 - compute budget: if more remain, keep the num_tiles best (smallest max).
* By Claude on 07/04/2026, from Andrey's design.
*/
public static boolean [] deriveSelection(
final float [] fmax,
final double k_nmad, // <=0 - skip the gate
final int num_tiles, // <=0 - no cap
final int debugLevel) {
final boolean [] sel = new boolean [fmax.length];
float [] finite = new float [fmax.length];
int num_finite = 0;
for (float f : fmax) if (!Float.isNaN(f) && !Float.isInfinite(f)) finite[num_finite++] = f;
if (num_finite == 0) return sel;
finite = Arrays.copyOf(finite, num_finite);
Arrays.sort(finite);
final double median = finite[num_finite/2];
final float [] adev = new float [num_finite];
for (int i = 0; i < num_finite; i++) adev[i] = (float) Math.abs(finite[i] - median);
Arrays.sort(adev);
final double nmad = 1.4826 * adev[num_finite/2];
final double gate = (k_nmad > 0) ? (median + k_nmad * nmad) : Double.POSITIVE_INFINITY;
int num_gated = 0;
for (int i = 0; i < fmax.length; i++) {
sel[i] = !Float.isNaN(fmax[i]) && !Float.isInfinite(fmax[i]) && (fmax[i] <= gate);
if (sel[i]) num_gated++;
}
double worst = gate;
if ((num_tiles > 0) && (num_gated > num_tiles)) { // rank: keep the num_tiles best
final Integer [] order = new Integer [num_gated];
final int [] idx = new int [num_gated];
for (int i = 0, j = 0; i < fmax.length; i++) if (sel[i]) idx[j++] = i;
for (int j = 0; j < num_gated; j++) order[j] = j;
Arrays.sort(order, (a,b) -> Float.compare(fmax[idx[a]], fmax[idx[b]]));
Arrays.fill(sel, false);
for (int j = 0; j < num_tiles; j++) sel[idx[order[j]]] = true;
worst = fmax[idx[order[num_tiles-1]]];
num_gated = num_tiles;
}
if (debugLevel > -4) {
System.out.println(String.format(
"CuasPoseRT.deriveSelection(): finite=%d, median=%.3f, NMAD=%.3f, gate=%.3f (k=%.2f) -> %d tiles, worst kept max=%.3f pix",
num_finite, median, nmad, gate, k_nmad, num_gated, worst));
}
return sel;
}
/** /**
* Re-generate per-scene poses against the virtual-center reference, RT-style. * Re-generate per-scene poses against the virtual-center reference, RT-style.
* *
...@@ -148,22 +201,30 @@ public class CuasPoseRT { ...@@ -148,22 +201,30 @@ public class CuasPoseRT {
System.out.println("CuasPoseRT.testPoseSequence(): num_reliable="+num_reliable+ System.out.println("CuasPoseRT.testPoseSequence(): num_reliable="+num_reliable+
" (strength > "+min_str+")"); " (strength > "+min_str+")");
} }
// Two-pass workflow: optionally AND with the outlier-filtered selection saved by a // Two-pass workflow: optionally derive the selection from the -POSE-RT-MAXDXY
// previous full run (-POSE-RT-RELIABLE-FILT: no NaN in any scene, dxy never > curt_pose_max_dxy) // calibration saved by a previous full run (per-tile max residual, +inf where any
// scene was NaN) - NMAD outlier gate + rank-N budget, then AND with the strength mask.
boolean full_selection = true; // MAXDXY calibration is (re)saved only from a full-selection run
if (clt_parameters.imp.curt_pose_use_filt) { if (clt_parameters.imp.curt_pose_use_filt) {
final ImagePlus imp_filt = center_CLT.readImagePlusFromModelDirectory("-POSE-RT-RELIABLE-FILT"); final ImagePlus imp_max = center_CLT.readImagePlusFromModelDirectory("-POSE-RT-MAXDXY");
if (imp_filt != null) { if (imp_max != null) {
final float [] ffilt = (float []) imp_filt.getProcessor().getPixels(); final float [] fmax = (float []) imp_max.getProcessor().getPixels();
final boolean [] filt = deriveSelection(
fmax,
clt_parameters.imp.curt_pose_dxy_k,
clt_parameters.imp.curt_pose_num_tiles,
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++) {
reliable_ref[i] &= (i < ffilt.length) && (ffilt[i] > 0.5f); reliable_ref[i] &= (i < filt.length) && filt[i];
if (reliable_ref[i]) num_filt++; if (reliable_ref[i]) num_filt++;
} }
System.out.println("CuasPoseRT.testPoseSequence(): applied -POSE-RT-RELIABLE-FILT, "+ full_selection = false;
System.out.println("CuasPoseRT.testPoseSequence(): applied -POSE-RT-MAXDXY-derived selection, "+
num_filt+" tiles remain (of "+num_reliable+" by strength)"); num_filt+" tiles remain (of "+num_reliable+" by strength)");
} else { } else {
System.out.println("CuasPoseRT.testPoseSequence(): WARNING - curt_pose_use_filt is ON but "+ System.out.println("CuasPoseRT.testPoseSequence(): curt_pose_use_filt is ON but "+
"-POSE-RT-RELIABLE-FILT.tiff not found, using the strength-only selection"); "-POSE-RT-MAXDXY.tiff not found - FULL run (will generate the calibration)");
} }
} }
final double [][] pXpYD_center = OpticalFlow.transformToScenePxPyD( final double [][] pXpYD_center = OpticalFlow.transformToScenePxPyD(
...@@ -400,30 +461,35 @@ public class CuasPoseRT { ...@@ -400,30 +461,35 @@ public class CuasPoseRT {
new FloatProcessor(tilesX, tilesY, frel)); new FloatProcessor(tilesX, tilesY, frel));
center_CLT.saveImagePlusInModelDirectory(null, imp_rel); // title as filename center_CLT.saveImagePlusInModelDirectory(null, imp_rel); // title as filename
} }
// Outlier post-filter: a selected tile is BAD if its dxy is NaN in any scene or // -POSE-RT-MAXDXY calibration: per-tile max-over-scenes residual, +inf where any
// exceeds curt_pose_max_dxy (absolute, pix) in at least one scene. Survivors -> // scene was NaN (auto-reject and mergeable across runs by simple max), NaN where
// -POSE-RT-RELIABLE-FILT (consumed by a next run with curt_pose_use_filt). // not selected/measured. Saved only from a FULL-selection run so a filtered run
final double max_dxy = clt_parameters.imp.curt_pose_max_dxy; // never shrinks the calibration coverage. The derived boolean selection is also
if ((max_dxy > 0) && !hyper_scenes.isEmpty()) { // saved (-POSE-RT-RELIABLE-FILT) for visualization.
final boolean [] keep = reliable_ref.clone(); if (full_selection && !hyper_scenes.isEmpty()) {
final float [] fmax = new float [num_pix];
Arrays.fill(fmax, Float.NaN);
for (int i = 0; i < num_pix; i++) if (reliable_ref[i]) {
float mx = 0f;
boolean has = false, has_nan = false;
for (float [][] comps : hyper_scenes) { for (float [][] comps : hyper_scenes) {
for (int i = 0; i < num_pix; i++) if (keep[i]) {
final float d = comps[3][i]; // dxy final float d = comps[3][i]; // dxy
if (Float.isNaN(d) || (d > max_dxy)) keep[i] = false; if (Float.isNaN(d)) has_nan = true;
} else { has = true; if (d > mx) mx = d; }
} }
int num_keep = 0; fmax[i] = has_nan ? Float.POSITIVE_INFINITY : (has ? mx : Float.NaN);
}
center_CLT.saveImagePlusInModelDirectory(null, new ImagePlus(
center_CLT.getImageName()+"-POSE-RT-MAXDXY", new FloatProcessor(tilesX, tilesY, fmax)));
final boolean [] keep = deriveSelection(
fmax,
clt_parameters.imp.curt_pose_dxy_k,
clt_parameters.imp.curt_pose_num_tiles,
debugLevel);
final float [] fkeep = new float [num_pix]; final float [] fkeep = new float [num_pix];
for (int i = 0; i < num_pix; i++) { for (int i = 0; i < num_pix; i++) fkeep[i] = keep[i] ? 1.0f : 0.0f;
fkeep[i] = keep[i] ? 1.0f : 0.0f; center_CLT.saveImagePlusInModelDirectory(null, new ImagePlus(
if (keep[i]) num_keep++; center_CLT.getImageName()+"-POSE-RT-RELIABLE-FILT", new FloatProcessor(tilesX, tilesY, fkeep)));
}
final ImagePlus imp_filt = new ImagePlus(center_CLT.getImageName()+"-POSE-RT-RELIABLE-FILT",
new FloatProcessor(tilesX, tilesY, fkeep));
center_CLT.saveImagePlusInModelDirectory(null, imp_filt);
System.out.println("CuasPoseRT.testPoseSequence(): outlier filter (dxy NaN or > "+max_dxy+
" pix in at least one scene): "+num_keep+" tiles kept of "+num_reliable+
" selected -> -POSE-RT-RELIABLE-FILT");
} }
// -POSE-RT-HYPER: z = scenes (top slider), t = components (bottom slider) - // -POSE-RT-HYPER: z = scenes (top slider), t = components (bottom slider) -
// same layout as renderSceneSequence make_hyper (component is the outer slice order) // same layout as renderSceneSequence make_hyper (component is the outer slice order)
......
...@@ -1129,8 +1129,9 @@ min_str_neib_fpn 0.35 ...@@ -1129,8 +1129,9 @@ min_str_neib_fpn 0.35
public boolean curt_cond_test = false; // conditioning/calibration isolation test inside the curt_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 curt_cond_test = false; // conditioning/calibration isolation test inside the curt_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 curt_pose_test = false; // RT pose-adjustment prototype (phase A) inside the curt_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 boolean curt_pose_test = false; // RT pose-adjustment prototype (phase A) inside the curt_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 curt_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 curt_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 curt_pose_max_dxy = 0.25; // post-filter (absolute, pix): a tile is BAD if its measured dxy exceeds this in at least one scene, or is NaN in any scene; survivors saved as -POSE-RT-RELIABLE-FILT (0 - skip). 0.25 ~ 70th percentile of all measurements on 1773135476_186641 (kept 191 of 1074 tiles, mean dxy 0.087). // By Claude on 07/04/2026 public double curt_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 boolean curt_pose_use_filt = false; // use the previously saved -POSE-RT-RELIABLE-FILT tile selection (AND with the strength threshold) - the two-pass workflow: full run generates the filtered selection, next run uses it. // By Claude on 07/04/2026 public int curt_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 boolean curt_pose_use_filt = false; // use the previously saved -POSE-RT-MAXDXY calibration (per-tile max residual, +inf where NaN): derive the selection (NMAD gate + rank-N) and AND with the strength threshold. Two-pass workflow: full run generates the calibration, next runs use it. // By Claude on 07/04/2026
//=== LoG prefilter === //=== LoG prefilter ===
public double curt_psf_radius = 1.0; // sensor PSF radius for LoG pre-filter public double curt_psf_radius = 1.0; // sensor PSF radius for LoG pre-filter
public double curt_n_sigma = 4.0; // cutoff LoG kernel array, number of sigmas public double curt_n_sigma = 4.0; // cutoff LoG kernel array, number of sigmas
...@@ -3424,10 +3425,12 @@ min_str_neib_fpn 0.35 ...@@ -3424,10 +3425,12 @@ min_str_neib_fpn 0.35
"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."); "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.addNumericField("Pose test reliable strength", this.curt_pose_str, 5,7,"", // By Claude on 07/03/2026 gd.addNumericField("Pose test reliable strength", this.curt_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)."); "Tile selection for the pose test: combo-DSI strength threshold (1.0 gives ~ the old getReliableTiles population).");
gd.addNumericField("Pose test max dxy (outlier filter)", this.curt_pose_max_dxy, 5,7,"pix", // By Claude on 07/04/2026 gd.addNumericField("Pose test outlier gate k (NMAD)", this.curt_pose_dxy_k, 5,7,"", // By Claude on 07/04/2026
"Post-filter: a tile is BAD if measured dxy exceeds this in at least one scene or is NaN in any scene; survivors saved as -POSE-RT-RELIABLE-FILT.tiff. 0 - skip."); "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.curt_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.addCheckbox ("Pose test use filtered selection", this.curt_pose_use_filt, // By Claude on 07/04/2026 gd.addCheckbox ("Pose test use filtered selection", this.curt_pose_use_filt, // By Claude on 07/04/2026
"Load the previously saved -POSE-RT-RELIABLE-FILT.tiff and AND it with the strength selection (two-pass workflow: full run generates it, next run uses it)."); "Load the previously saved -POSE-RT-MAXDXY.tiff calibration, derive the selection (NMAD gate + rank-N) and AND with the strength selection (two-pass workflow).");
gd.addMessage("=== LoG prefilter ==="); gd.addMessage("=== LoG prefilter ===");
gd.addNumericField("Optical PSF radius", this.curt_psf_radius, 6,8,"pix", gd.addNumericField("Optical PSF radius", this.curt_psf_radius, 6,8,"pix",
...@@ -5022,7 +5025,8 @@ min_str_neib_fpn 0.35 ...@@ -5022,7 +5025,8 @@ min_str_neib_fpn 0.35
this.curt_cond_test = gd.getNextBoolean(); this.curt_cond_test = gd.getNextBoolean();
this.curt_pose_test = gd.getNextBoolean(); // By Claude on 07/03/2026 this.curt_pose_test = gd.getNextBoolean(); // By Claude on 07/03/2026
this.curt_pose_str = gd.getNextNumber(); // By Claude on 07/03/2026 this.curt_pose_str = gd.getNextNumber(); // By Claude on 07/03/2026
this.curt_pose_max_dxy = gd.getNextNumber(); // By Claude on 07/04/2026 this.curt_pose_dxy_k = gd.getNextNumber(); // By Claude on 07/04/2026
this.curt_pose_num_tiles =(int) gd.getNextNumber(); // By Claude on 07/04/2026
this.curt_pose_use_filt = gd.getNextBoolean(); // By Claude on 07/04/2026 this.curt_pose_use_filt = gd.getNextBoolean(); // By Claude on 07/04/2026
this.curt_psf_radius = gd.getNextNumber(); this.curt_psf_radius = gd.getNextNumber();
...@@ -6392,7 +6396,8 @@ min_str_neib_fpn 0.35 ...@@ -6392,7 +6396,8 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"curt_cond_test", this.curt_cond_test+""); // boolean properties.setProperty(prefix+"curt_cond_test", this.curt_cond_test+""); // boolean
properties.setProperty(prefix+"curt_pose_test", this.curt_pose_test+""); // boolean // By Claude on 07/03/2026 properties.setProperty(prefix+"curt_pose_test", this.curt_pose_test+""); // boolean // By Claude on 07/03/2026
properties.setProperty(prefix+"curt_pose_str", this.curt_pose_str+""); // double // By Claude on 07/03/2026 properties.setProperty(prefix+"curt_pose_str", this.curt_pose_str+""); // double // By Claude on 07/03/2026
properties.setProperty(prefix+"curt_pose_max_dxy", this.curt_pose_max_dxy+""); // double // By Claude on 07/04/2026 properties.setProperty(prefix+"curt_pose_dxy_k", this.curt_pose_dxy_k+""); // double // By Claude on 07/04/2026
properties.setProperty(prefix+"curt_pose_num_tiles", this.curt_pose_num_tiles+""); // int // By Claude on 07/04/2026
properties.setProperty(prefix+"curt_pose_use_filt", this.curt_pose_use_filt+""); // boolean // By Claude on 07/04/2026 properties.setProperty(prefix+"curt_pose_use_filt", this.curt_pose_use_filt+""); // boolean // By Claude on 07/04/2026
properties.setProperty(prefix+"curt_psf_radius", this.curt_psf_radius+""); // double properties.setProperty(prefix+"curt_psf_radius", this.curt_psf_radius+""); // double
...@@ -6796,7 +6801,8 @@ min_str_neib_fpn 0.35 ...@@ -6796,7 +6801,8 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"curt_cond_test")!=null) this.curt_cond_test=Boolean.parseBoolean(properties.getProperty(prefix+"curt_cond_test")); if (properties.getProperty(prefix+"curt_cond_test")!=null) this.curt_cond_test=Boolean.parseBoolean(properties.getProperty(prefix+"curt_cond_test"));
if (properties.getProperty(prefix+"curt_pose_test")!=null) this.curt_pose_test=Boolean.parseBoolean(properties.getProperty(prefix+"curt_pose_test")); // By Claude on 07/03/2026 if (properties.getProperty(prefix+"curt_pose_test")!=null) this.curt_pose_test=Boolean.parseBoolean(properties.getProperty(prefix+"curt_pose_test")); // By Claude on 07/03/2026
if (properties.getProperty(prefix+"curt_pose_str")!=null) this.curt_pose_str=Double.parseDouble(properties.getProperty(prefix+"curt_pose_str")); // By Claude on 07/03/2026 if (properties.getProperty(prefix+"curt_pose_str")!=null) this.curt_pose_str=Double.parseDouble(properties.getProperty(prefix+"curt_pose_str")); // By Claude on 07/03/2026
if (properties.getProperty(prefix+"curt_pose_max_dxy")!=null) this.curt_pose_max_dxy=Double.parseDouble(properties.getProperty(prefix+"curt_pose_max_dxy")); // By Claude on 07/04/2026 if (properties.getProperty(prefix+"curt_pose_dxy_k")!=null) this.curt_pose_dxy_k=Double.parseDouble(properties.getProperty(prefix+"curt_pose_dxy_k")); // By Claude on 07/04/2026
if (properties.getProperty(prefix+"curt_pose_num_tiles")!=null) this.curt_pose_num_tiles=Integer.parseInt(properties.getProperty(prefix+"curt_pose_num_tiles")); // By Claude on 07/04/2026
if (properties.getProperty(prefix+"curt_pose_use_filt")!=null) this.curt_pose_use_filt=Boolean.parseBoolean(properties.getProperty(prefix+"curt_pose_use_filt")); // By Claude on 07/04/2026 if (properties.getProperty(prefix+"curt_pose_use_filt")!=null) this.curt_pose_use_filt=Boolean.parseBoolean(properties.getProperty(prefix+"curt_pose_use_filt")); // By Claude on 07/04/2026
if (properties.getProperty(prefix+"curt_psf_radius")!=null) this.curt_psf_radius=Double.parseDouble(properties.getProperty(prefix+"curt_psf_radius")); if (properties.getProperty(prefix+"curt_psf_radius")!=null) this.curt_psf_radius=Double.parseDouble(properties.getProperty(prefix+"curt_psf_radius"));
...@@ -9085,7 +9091,8 @@ min_str_neib_fpn 0.35 ...@@ -9085,7 +9091,8 @@ min_str_neib_fpn 0.35
imp.curt_cond_test = this.curt_cond_test; imp.curt_cond_test = this.curt_cond_test;
imp.curt_pose_test = this.curt_pose_test; // By Claude on 07/03/2026 imp.curt_pose_test = this.curt_pose_test; // By Claude on 07/03/2026
imp.curt_pose_str = this.curt_pose_str; // By Claude on 07/03/2026 imp.curt_pose_str = this.curt_pose_str; // By Claude on 07/03/2026
imp.curt_pose_max_dxy = this.curt_pose_max_dxy; // By Claude on 07/04/2026 imp.curt_pose_dxy_k = this.curt_pose_dxy_k; // By Claude on 07/04/2026
imp.curt_pose_num_tiles = this.curt_pose_num_tiles; // By Claude on 07/04/2026
imp.curt_pose_use_filt = this.curt_pose_use_filt; // By Claude on 07/04/2026 imp.curt_pose_use_filt = this.curt_pose_use_filt; // By Claude on 07/04/2026
imp.curt_psf_radius = this.curt_psf_radius; imp.curt_psf_radius = this.curt_psf_radius;
imp.curt_n_sigma = this.curt_n_sigma; imp.curt_n_sigma = this.curt_n_sigma;
......
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