sar3d: python plumbing for the new parameters and real replay timing

- replay_raw_producer carries the RECORDED per-trace capture windows
  from each snapshot's meta.json (re-anchored by the same shift as the
  frame time) instead of one synthetic window for all traces — without
  this the segmented timing model degenerates in replay;
- GUI/profile/orchestration swap the removed window knobs
  (center_depth, half_width_*, grid_n*) for the notebook parameters
  (ground depth, pitch override, voxel pitch, Y range, X margin, norm
  edge margin, smooth sigma, comp power, tx per segment).

Headless replay smoke on the 20260922_mine_fast_true dataset passes:
51 sar3d result collections, transparent preprocessor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
awe
2026-09-25 16:42:14 +03:00
co-authored by Claude Fable 5
parent b8cb572bc4
commit e1dfbec712
9 changed files with 345 additions and 149 deletions
@@ -660,49 +660,97 @@ def build_processing_group(owner) -> QGroupBox:
"Weight of the outermost aperture frames (1 = flat window, 0 = strong taper)."
)
owner._sar3d_pitch_override_enabled = QCheckBox("Override pitch")
owner._sar3d_pitch_override_enabled.setChecked(bool(sar3d_defaults.pitch_override_enabled))
owner._sar3d_pitch_override_enabled.setToolTip(
"When unchecked, the frame pitch follows the look angle (notebook "
"BP_GROUND_PITCH_DEG = None); check to set it separately below."
)
owner._sar3d_pitch_deg = QDoubleSpinBox()
owner._sar3d_pitch_deg.setDecimals(2)
owner._sar3d_pitch_deg.setRange(-90.0, 90.0)
owner._sar3d_pitch_deg.setSingleStep(0.5)
owner._sar3d_pitch_deg.setValue(float(sar3d_defaults.pitch_deg))
owner._sar3d_pitch_deg.setToolTip("Antenna pitch above the horizon (deg); tilts the imaged volume.")
owner._sar3d_pitch_deg.setToolTip(
"Frame pitch (deg) used for ground coordinates and aperture offsets when the override is on."
)
owner._sar3d_center_depth_m = QDoubleSpinBox()
owner._sar3d_center_depth_m.setDecimals(2)
owner._sar3d_center_depth_m.setRange(0.0, 50.0)
owner._sar3d_center_depth_m.setSingleStep(0.1)
owner._sar3d_center_depth_m.setValue(float(sar3d_defaults.center_depth_m))
owner._sar3d_center_depth_m.setToolTip("Range distance to the center of the imaged volume (m).")
owner._sar3d_ground_depth_m = QDoubleSpinBox()
owner._sar3d_ground_depth_m.setDecimals(2)
owner._sar3d_ground_depth_m.setRange(0.0, 10.0)
owner._sar3d_ground_depth_m.setSingleStep(0.05)
owner._sar3d_ground_depth_m.setValue(float(sar3d_defaults.ground_depth_m))
owner._sar3d_ground_depth_m.setToolTip(
"Height of the lower antenna row above the ground (m); scene Y=0 is the ground."
)
owner._sar3d_half_width_x_m = QDoubleSpinBox()
owner._sar3d_half_width_x_m.setDecimals(2)
owner._sar3d_half_width_x_m.setRange(0.01, 50.0)
owner._sar3d_half_width_x_m.setSingleStep(0.1)
owner._sar3d_half_width_x_m.setValue(float(sar3d_defaults.half_width_x_m))
owner._sar3d_x_margin_m = QDoubleSpinBox()
owner._sar3d_x_margin_m.setDecimals(2)
owner._sar3d_x_margin_m.setRange(0.0, 20.0)
owner._sar3d_x_margin_m.setSingleStep(0.1)
owner._sar3d_x_margin_m.setValue(float(sar3d_defaults.x_margin_m))
owner._sar3d_x_margin_m.setToolTip("Grid X margin beyond the antenna span (m).")
owner._sar3d_half_width_y_m = QDoubleSpinBox()
owner._sar3d_half_width_y_m.setDecimals(2)
owner._sar3d_half_width_y_m.setRange(0.01, 50.0)
owner._sar3d_half_width_y_m.setSingleStep(0.1)
owner._sar3d_half_width_y_m.setValue(float(sar3d_defaults.half_width_y_m))
owner._sar3d_y_min_m = QDoubleSpinBox()
owner._sar3d_y_min_m.setDecimals(2)
owner._sar3d_y_min_m.setRange(-10.0, 10.0)
owner._sar3d_y_min_m.setSingleStep(0.1)
owner._sar3d_y_min_m.setValue(float(sar3d_defaults.y_min_m))
owner._sar3d_half_width_z_m = QDoubleSpinBox()
owner._sar3d_half_width_z_m.setDecimals(2)
owner._sar3d_half_width_z_m.setRange(0.01, 50.0)
owner._sar3d_half_width_z_m.setSingleStep(0.1)
owner._sar3d_half_width_z_m.setValue(float(sar3d_defaults.half_width_z_m))
owner._sar3d_y_max_m = QDoubleSpinBox()
owner._sar3d_y_max_m.setDecimals(2)
owner._sar3d_y_max_m.setRange(-10.0, 10.0)
owner._sar3d_y_max_m.setSingleStep(0.1)
owner._sar3d_y_max_m.setValue(float(sar3d_defaults.y_max_m))
owner._sar3d_grid_nx = QSpinBox()
owner._sar3d_grid_nx.setRange(2, 1024)
owner._sar3d_grid_nx.setValue(int(sar3d_defaults.grid_nx))
owner._sar3d_voxel_x_m = QDoubleSpinBox()
owner._sar3d_voxel_x_m.setDecimals(3)
owner._sar3d_voxel_x_m.setRange(0.005, 1.0)
owner._sar3d_voxel_x_m.setSingleStep(0.005)
owner._sar3d_voxel_x_m.setValue(float(sar3d_defaults.voxel_x_m))
owner._sar3d_grid_ny = QSpinBox()
owner._sar3d_grid_ny.setRange(2, 1024)
owner._sar3d_grid_ny.setValue(int(sar3d_defaults.grid_ny))
owner._sar3d_voxel_y_m = QDoubleSpinBox()
owner._sar3d_voxel_y_m.setDecimals(3)
owner._sar3d_voxel_y_m.setRange(0.005, 1.0)
owner._sar3d_voxel_y_m.setSingleStep(0.005)
owner._sar3d_voxel_y_m.setValue(float(sar3d_defaults.voxel_y_m))
owner._sar3d_grid_nz = QSpinBox()
owner._sar3d_grid_nz.setRange(2, 1024)
owner._sar3d_grid_nz.setValue(int(sar3d_defaults.grid_nz))
owner._sar3d_voxel_z_m = QDoubleSpinBox()
owner._sar3d_voxel_z_m.setDecimals(3)
owner._sar3d_voxel_z_m.setRange(0.005, 1.0)
owner._sar3d_voxel_z_m.setSingleStep(0.005)
owner._sar3d_voxel_z_m.setValue(float(sar3d_defaults.voxel_z_m))
owner._sar3d_norm_edge_margin_m = QDoubleSpinBox()
owner._sar3d_norm_edge_margin_m.setDecimals(2)
owner._sar3d_norm_edge_margin_m.setRange(0.0, 5.0)
owner._sar3d_norm_edge_margin_m.setSingleStep(0.05)
owner._sar3d_norm_edge_margin_m.setValue(float(sar3d_defaults.norm_edge_margin_m))
owner._sar3d_norm_edge_margin_m.setToolTip(
"Grid Y edges excluded from volume normalization (constant-range ridge)."
)
owner._sar3d_smooth_sigma = QDoubleSpinBox()
owner._sar3d_smooth_sigma.setDecimals(2)
owner._sar3d_smooth_sigma.setRange(0.0, 10.0)
owner._sar3d_smooth_sigma.setSingleStep(0.25)
owner._sar3d_smooth_sigma.setValue(float(sar3d_defaults.smooth_sigma))
owner._sar3d_smooth_sigma.setToolTip("Gaussian smoothing sigma over (Z, X) planes, voxels.")
owner._sar3d_comp_range_power = QDoubleSpinBox()
owner._sar3d_comp_range_power.setDecimals(2)
owner._sar3d_comp_range_power.setRange(0.0, 2.0)
owner._sar3d_comp_range_power.setSingleStep(0.05)
owner._sar3d_comp_range_power.setValue(float(sar3d_defaults.comp_range_power))
owner._sar3d_comp_range_power.setToolTip("Geometric spreading compensation power.")
owner._sar3d_tx_per_segment = QSpinBox()
owner._sar3d_tx_per_segment.setRange(1, 64)
owner._sar3d_tx_per_segment.setValue(int(sar3d_defaults.tx_per_segment))
owner._sar3d_tx_per_segment.setToolTip(
"Fallback Tx-per-segment split of a frame when per-trace capture stamps are absent."
)
owner._sar3d_use_compensation = QCheckBox("Use per-voxel compensation")
owner._sar3d_use_compensation.setChecked(bool(sar3d_defaults.use_compensation))
@@ -738,19 +786,24 @@ def build_processing_group(owner) -> QGroupBox:
owner._sar3d_apply_freq_phase_correction,
("Frame radius", owner._sar3d_frame_radius),
("Edge frame weight", owner._sar3d_edge_frame_weight),
owner._sar3d_pitch_override_enabled,
("Pitch deg", owner._sar3d_pitch_deg),
("Center depth m", owner._sar3d_center_depth_m),
("Half width X m", owner._sar3d_half_width_x_m),
("Half width Y m", owner._sar3d_half_width_y_m),
("Half width Z m", owner._sar3d_half_width_z_m),
("Grid Nx", owner._sar3d_grid_nx),
("Grid Ny", owner._sar3d_grid_ny),
("Grid Nz", owner._sar3d_grid_nz),
("Ground depth m", owner._sar3d_ground_depth_m),
("X margin m", owner._sar3d_x_margin_m),
("Y min m", owner._sar3d_y_min_m),
("Y max m", owner._sar3d_y_max_m),
("Voxel X m", owner._sar3d_voxel_x_m),
("Voxel Y m", owner._sar3d_voxel_y_m),
("Voxel Z m", owner._sar3d_voxel_z_m),
("Norm edge margin m", owner._sar3d_norm_edge_margin_m),
("Smooth sigma", owner._sar3d_smooth_sigma),
("Comp range power", owner._sar3d_comp_range_power),
("Tx per segment", owner._sar3d_tx_per_segment),
("Bottom view", owner._sar3d_bottom_view),
owner._sar3d_use_compensation,
owner._sar3d_normalize_pairs,
],
split_index=11,
split_index=13,
)
owner._processing_mode_pages.addWidget(sar3d_page)
@@ -839,14 +892,19 @@ def build_processing_group(owner) -> QGroupBox:
owner._sar3d_apply_freq_phase_correction.toggled.connect(owner._on_processing_live_settings_changed)
owner._sar3d_frame_radius.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_edge_frame_weight.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_pitch_override_enabled.toggled.connect(owner._on_processing_live_settings_changed)
owner._sar3d_pitch_deg.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_center_depth_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_half_width_x_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_half_width_y_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_half_width_z_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_grid_nx.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_grid_ny.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_grid_nz.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_ground_depth_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_x_margin_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_y_min_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_y_max_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_voxel_x_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_voxel_y_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_voxel_z_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_norm_edge_margin_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_smooth_sigma.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_comp_range_power.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_tx_per_segment.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_use_compensation.toggled.connect(owner._on_processing_live_settings_changed)
owner._sar3d_normalize_pairs.toggled.connect(owner._on_processing_live_settings_changed)
owner._sar3d_bottom_view.currentTextChanged.connect(owner._on_processing_live_settings_changed)