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:
@@ -90,14 +90,19 @@ _WEB_LIVE_SCHEMA = [
|
|||||||
("gpr_speed_m_s", "Motion", _GPR_LIKE_MODES, _dual("_gpr_speed_m_s", {"legacy_gpr": "_legacy_gpr_speed_m_s", "sar3d": "_sar3d_speed_m_s"})),
|
("gpr_speed_m_s", "Motion", _GPR_LIKE_MODES, _dual("_gpr_speed_m_s", {"legacy_gpr": "_legacy_gpr_speed_m_s", "sar3d": "_sar3d_speed_m_s"})),
|
||||||
("sar3d_frame_radius", "3D SAR", ("sar3d",), _attr("_sar3d_frame_radius")),
|
("sar3d_frame_radius", "3D SAR", ("sar3d",), _attr("_sar3d_frame_radius")),
|
||||||
("sar3d_edge_frame_weight", "3D SAR", ("sar3d",), _attr("_sar3d_edge_frame_weight")),
|
("sar3d_edge_frame_weight", "3D SAR", ("sar3d",), _attr("_sar3d_edge_frame_weight")),
|
||||||
|
("sar3d_pitch_override_enabled", "3D SAR", ("sar3d",), _attr("_sar3d_pitch_override_enabled")),
|
||||||
("sar3d_pitch_deg", "3D SAR", ("sar3d",), _attr("_sar3d_pitch_deg")),
|
("sar3d_pitch_deg", "3D SAR", ("sar3d",), _attr("_sar3d_pitch_deg")),
|
||||||
("sar3d_center_depth_m", "3D SAR", ("sar3d",), _attr("_sar3d_center_depth_m")),
|
("sar3d_ground_depth_m", "3D SAR", ("sar3d",), _attr("_sar3d_ground_depth_m")),
|
||||||
("sar3d_half_width_x_m", "3D SAR", ("sar3d",), _attr("_sar3d_half_width_x_m")),
|
("sar3d_x_margin_m", "3D SAR", ("sar3d",), _attr("_sar3d_x_margin_m")),
|
||||||
("sar3d_half_width_y_m", "3D SAR", ("sar3d",), _attr("_sar3d_half_width_y_m")),
|
("sar3d_y_min_m", "3D SAR", ("sar3d",), _attr("_sar3d_y_min_m")),
|
||||||
("sar3d_half_width_z_m", "3D SAR", ("sar3d",), _attr("_sar3d_half_width_z_m")),
|
("sar3d_y_max_m", "3D SAR", ("sar3d",), _attr("_sar3d_y_max_m")),
|
||||||
("sar3d_grid_nx", "3D SAR", ("sar3d",), _attr("_sar3d_grid_nx")),
|
("sar3d_voxel_x_m", "3D SAR", ("sar3d",), _attr("_sar3d_voxel_x_m")),
|
||||||
("sar3d_grid_ny", "3D SAR", ("sar3d",), _attr("_sar3d_grid_ny")),
|
("sar3d_voxel_y_m", "3D SAR", ("sar3d",), _attr("_sar3d_voxel_y_m")),
|
||||||
("sar3d_grid_nz", "3D SAR", ("sar3d",), _attr("_sar3d_grid_nz")),
|
("sar3d_voxel_z_m", "3D SAR", ("sar3d",), _attr("_sar3d_voxel_z_m")),
|
||||||
|
("sar3d_norm_edge_margin_m", "3D SAR", ("sar3d",), _attr("_sar3d_norm_edge_margin_m")),
|
||||||
|
("sar3d_smooth_sigma", "3D SAR", ("sar3d",), _attr("_sar3d_smooth_sigma")),
|
||||||
|
("sar3d_comp_range_power", "3D SAR", ("sar3d",), _attr("_sar3d_comp_range_power")),
|
||||||
|
("sar3d_tx_per_segment", "3D SAR", ("sar3d",), _attr("_sar3d_tx_per_segment")),
|
||||||
("sar3d_use_compensation", "3D SAR", ("sar3d",), _attr("_sar3d_use_compensation")),
|
("sar3d_use_compensation", "3D SAR", ("sar3d",), _attr("_sar3d_use_compensation")),
|
||||||
("sar3d_normalize_pairs", "3D SAR", ("sar3d",), _attr("_sar3d_normalize_pairs")),
|
("sar3d_normalize_pairs", "3D SAR", ("sar3d",), _attr("_sar3d_normalize_pairs")),
|
||||||
("sar3d_bottom_view_deg", "3D SAR", ("sar3d",), _attr("_sar3d_bottom_view")),
|
("sar3d_bottom_view_deg", "3D SAR", ("sar3d",), _attr("_sar3d_bottom_view")),
|
||||||
@@ -553,9 +558,8 @@ class AppWindowLiveProcessingMixin:
|
|||||||
f"depth={self._sar3d_min_depth_m.value():g}..{self._sar3d_max_depth_m.value():g} m, "
|
f"depth={self._sar3d_min_depth_m.value():g}..{self._sar3d_max_depth_m.value():g} m, "
|
||||||
f"freq={self._sar3d_start_freq_mhz.value():g}..{self._sar3d_stop_freq_mhz.value():g} MHz, "
|
f"freq={self._sar3d_start_freq_mhz.value():g}..{self._sar3d_stop_freq_mhz.value():g} MHz, "
|
||||||
f"frame_radius={self._sar3d_frame_radius.value()}, "
|
f"frame_radius={self._sar3d_frame_radius.value()}, "
|
||||||
f"grid={self._sar3d_grid_nx.value()}x{self._sar3d_grid_ny.value()}x{self._sar3d_grid_nz.value()}, "
|
f"voxel={self._sar3d_voxel_x_m.value():g}x{self._sar3d_voxel_y_m.value():g}x{self._sar3d_voxel_z_m.value():g} m, "
|
||||||
f"center_depth={self._sar3d_center_depth_m.value():g} m, "
|
f"ground_depth={self._sar3d_ground_depth_m.value():g} m)"
|
||||||
f"pitch={self._sar3d_pitch_deg.value():g} deg)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def _clear_history_mode_caches(self) -> None:
|
def _clear_history_mode_caches(self) -> None:
|
||||||
|
|||||||
@@ -350,14 +350,19 @@ class AppWindowConfigProfileIOMixin:
|
|||||||
self._sar3d_apply_freq_phase_correction,
|
self._sar3d_apply_freq_phase_correction,
|
||||||
self._sar3d_frame_radius,
|
self._sar3d_frame_radius,
|
||||||
self._sar3d_edge_frame_weight,
|
self._sar3d_edge_frame_weight,
|
||||||
|
self._sar3d_pitch_override_enabled,
|
||||||
self._sar3d_pitch_deg,
|
self._sar3d_pitch_deg,
|
||||||
self._sar3d_center_depth_m,
|
self._sar3d_ground_depth_m,
|
||||||
self._sar3d_half_width_x_m,
|
self._sar3d_x_margin_m,
|
||||||
self._sar3d_half_width_y_m,
|
self._sar3d_y_min_m,
|
||||||
self._sar3d_half_width_z_m,
|
self._sar3d_y_max_m,
|
||||||
self._sar3d_grid_nx,
|
self._sar3d_voxel_x_m,
|
||||||
self._sar3d_grid_ny,
|
self._sar3d_voxel_y_m,
|
||||||
self._sar3d_grid_nz,
|
self._sar3d_voxel_z_m,
|
||||||
|
self._sar3d_norm_edge_margin_m,
|
||||||
|
self._sar3d_smooth_sigma,
|
||||||
|
self._sar3d_comp_range_power,
|
||||||
|
self._sar3d_tx_per_segment,
|
||||||
self._sar3d_use_compensation,
|
self._sar3d_use_compensation,
|
||||||
self._sar3d_normalize_pairs,
|
self._sar3d_normalize_pairs,
|
||||||
self._save_count,
|
self._save_count,
|
||||||
@@ -562,14 +567,19 @@ class AppWindowConfigProfileIOMixin:
|
|||||||
self._sar3d_apply_freq_phase_correction.setChecked(bool(sar3d_state.apply_freq_phase_correction))
|
self._sar3d_apply_freq_phase_correction.setChecked(bool(sar3d_state.apply_freq_phase_correction))
|
||||||
self._sar3d_frame_radius.setValue(int(sar3d_state.frame_radius))
|
self._sar3d_frame_radius.setValue(int(sar3d_state.frame_radius))
|
||||||
self._sar3d_edge_frame_weight.setValue(float(sar3d_state.edge_frame_weight))
|
self._sar3d_edge_frame_weight.setValue(float(sar3d_state.edge_frame_weight))
|
||||||
|
self._sar3d_pitch_override_enabled.setChecked(bool(sar3d_state.pitch_override_enabled))
|
||||||
self._sar3d_pitch_deg.setValue(float(sar3d_state.pitch_deg))
|
self._sar3d_pitch_deg.setValue(float(sar3d_state.pitch_deg))
|
||||||
self._sar3d_center_depth_m.setValue(float(sar3d_state.center_depth_m))
|
self._sar3d_ground_depth_m.setValue(float(sar3d_state.ground_depth_m))
|
||||||
self._sar3d_half_width_x_m.setValue(float(sar3d_state.half_width_x_m))
|
self._sar3d_x_margin_m.setValue(float(sar3d_state.x_margin_m))
|
||||||
self._sar3d_half_width_y_m.setValue(float(sar3d_state.half_width_y_m))
|
self._sar3d_y_min_m.setValue(float(sar3d_state.y_min_m))
|
||||||
self._sar3d_half_width_z_m.setValue(float(sar3d_state.half_width_z_m))
|
self._sar3d_y_max_m.setValue(float(sar3d_state.y_max_m))
|
||||||
self._sar3d_grid_nx.setValue(int(sar3d_state.grid_nx))
|
self._sar3d_voxel_x_m.setValue(float(sar3d_state.voxel_x_m))
|
||||||
self._sar3d_grid_ny.setValue(int(sar3d_state.grid_ny))
|
self._sar3d_voxel_y_m.setValue(float(sar3d_state.voxel_y_m))
|
||||||
self._sar3d_grid_nz.setValue(int(sar3d_state.grid_nz))
|
self._sar3d_voxel_z_m.setValue(float(sar3d_state.voxel_z_m))
|
||||||
|
self._sar3d_norm_edge_margin_m.setValue(float(sar3d_state.norm_edge_margin_m))
|
||||||
|
self._sar3d_smooth_sigma.setValue(float(sar3d_state.smooth_sigma))
|
||||||
|
self._sar3d_comp_range_power.setValue(float(sar3d_state.comp_range_power))
|
||||||
|
self._sar3d_tx_per_segment.setValue(int(sar3d_state.tx_per_segment))
|
||||||
self._sar3d_use_compensation.setChecked(bool(sar3d_state.use_compensation))
|
self._sar3d_use_compensation.setChecked(bool(sar3d_state.use_compensation))
|
||||||
self._sar3d_normalize_pairs.setChecked(bool(sar3d_state.normalize_pairs))
|
self._sar3d_normalize_pairs.setChecked(bool(sar3d_state.normalize_pairs))
|
||||||
self._set_combo_current_text(
|
self._set_combo_current_text(
|
||||||
|
|||||||
@@ -438,14 +438,19 @@ class AppWindowConfigStateBuildersMixin:
|
|||||||
apply_freq_phase_correction=bool(self._sar3d_apply_freq_phase_correction.isChecked()),
|
apply_freq_phase_correction=bool(self._sar3d_apply_freq_phase_correction.isChecked()),
|
||||||
frame_radius=int(self._sar3d_frame_radius.value()),
|
frame_radius=int(self._sar3d_frame_radius.value()),
|
||||||
edge_frame_weight=float(self._sar3d_edge_frame_weight.value()),
|
edge_frame_weight=float(self._sar3d_edge_frame_weight.value()),
|
||||||
|
pitch_override_enabled=bool(self._sar3d_pitch_override_enabled.isChecked()),
|
||||||
pitch_deg=float(self._sar3d_pitch_deg.value()),
|
pitch_deg=float(self._sar3d_pitch_deg.value()),
|
||||||
center_depth_m=float(self._sar3d_center_depth_m.value()),
|
ground_depth_m=float(self._sar3d_ground_depth_m.value()),
|
||||||
half_width_x_m=float(self._sar3d_half_width_x_m.value()),
|
x_margin_m=float(self._sar3d_x_margin_m.value()),
|
||||||
half_width_y_m=float(self._sar3d_half_width_y_m.value()),
|
y_min_m=float(self._sar3d_y_min_m.value()),
|
||||||
half_width_z_m=float(self._sar3d_half_width_z_m.value()),
|
y_max_m=float(self._sar3d_y_max_m.value()),
|
||||||
grid_nx=int(self._sar3d_grid_nx.value()),
|
voxel_x_m=float(self._sar3d_voxel_x_m.value()),
|
||||||
grid_ny=int(self._sar3d_grid_ny.value()),
|
voxel_y_m=float(self._sar3d_voxel_y_m.value()),
|
||||||
grid_nz=int(self._sar3d_grid_nz.value()),
|
voxel_z_m=float(self._sar3d_voxel_z_m.value()),
|
||||||
|
norm_edge_margin_m=float(self._sar3d_norm_edge_margin_m.value()),
|
||||||
|
smooth_sigma=float(self._sar3d_smooth_sigma.value()),
|
||||||
|
comp_range_power=float(self._sar3d_comp_range_power.value()),
|
||||||
|
tx_per_segment=int(self._sar3d_tx_per_segment.value()),
|
||||||
use_compensation=bool(self._sar3d_use_compensation.isChecked()),
|
use_compensation=bool(self._sar3d_use_compensation.isChecked()),
|
||||||
normalize_pairs=bool(self._sar3d_normalize_pairs.isChecked()),
|
normalize_pairs=bool(self._sar3d_normalize_pairs.isChecked()),
|
||||||
bottom_view_deg=sar3d_bottom_view_deg_from_label(
|
bottom_view_deg=sar3d_bottom_view_deg_from_label(
|
||||||
|
|||||||
@@ -660,49 +660,97 @@ def build_processing_group(owner) -> QGroupBox:
|
|||||||
"Weight of the outermost aperture frames (1 = flat window, 0 = strong taper)."
|
"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 = QDoubleSpinBox()
|
||||||
owner._sar3d_pitch_deg.setDecimals(2)
|
owner._sar3d_pitch_deg.setDecimals(2)
|
||||||
owner._sar3d_pitch_deg.setRange(-90.0, 90.0)
|
owner._sar3d_pitch_deg.setRange(-90.0, 90.0)
|
||||||
owner._sar3d_pitch_deg.setSingleStep(0.5)
|
owner._sar3d_pitch_deg.setSingleStep(0.5)
|
||||||
owner._sar3d_pitch_deg.setValue(float(sar3d_defaults.pitch_deg))
|
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_ground_depth_m = QDoubleSpinBox()
|
||||||
owner._sar3d_center_depth_m.setDecimals(2)
|
owner._sar3d_ground_depth_m.setDecimals(2)
|
||||||
owner._sar3d_center_depth_m.setRange(0.0, 50.0)
|
owner._sar3d_ground_depth_m.setRange(0.0, 10.0)
|
||||||
owner._sar3d_center_depth_m.setSingleStep(0.1)
|
owner._sar3d_ground_depth_m.setSingleStep(0.05)
|
||||||
owner._sar3d_center_depth_m.setValue(float(sar3d_defaults.center_depth_m))
|
owner._sar3d_ground_depth_m.setValue(float(sar3d_defaults.ground_depth_m))
|
||||||
owner._sar3d_center_depth_m.setToolTip("Range distance to the center of the imaged volume (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_x_margin_m = QDoubleSpinBox()
|
||||||
owner._sar3d_half_width_x_m.setDecimals(2)
|
owner._sar3d_x_margin_m.setDecimals(2)
|
||||||
owner._sar3d_half_width_x_m.setRange(0.01, 50.0)
|
owner._sar3d_x_margin_m.setRange(0.0, 20.0)
|
||||||
owner._sar3d_half_width_x_m.setSingleStep(0.1)
|
owner._sar3d_x_margin_m.setSingleStep(0.1)
|
||||||
owner._sar3d_half_width_x_m.setValue(float(sar3d_defaults.half_width_x_m))
|
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_y_min_m = QDoubleSpinBox()
|
||||||
owner._sar3d_half_width_y_m.setDecimals(2)
|
owner._sar3d_y_min_m.setDecimals(2)
|
||||||
owner._sar3d_half_width_y_m.setRange(0.01, 50.0)
|
owner._sar3d_y_min_m.setRange(-10.0, 10.0)
|
||||||
owner._sar3d_half_width_y_m.setSingleStep(0.1)
|
owner._sar3d_y_min_m.setSingleStep(0.1)
|
||||||
owner._sar3d_half_width_y_m.setValue(float(sar3d_defaults.half_width_y_m))
|
owner._sar3d_y_min_m.setValue(float(sar3d_defaults.y_min_m))
|
||||||
|
|
||||||
owner._sar3d_half_width_z_m = QDoubleSpinBox()
|
owner._sar3d_y_max_m = QDoubleSpinBox()
|
||||||
owner._sar3d_half_width_z_m.setDecimals(2)
|
owner._sar3d_y_max_m.setDecimals(2)
|
||||||
owner._sar3d_half_width_z_m.setRange(0.01, 50.0)
|
owner._sar3d_y_max_m.setRange(-10.0, 10.0)
|
||||||
owner._sar3d_half_width_z_m.setSingleStep(0.1)
|
owner._sar3d_y_max_m.setSingleStep(0.1)
|
||||||
owner._sar3d_half_width_z_m.setValue(float(sar3d_defaults.half_width_z_m))
|
owner._sar3d_y_max_m.setValue(float(sar3d_defaults.y_max_m))
|
||||||
|
|
||||||
owner._sar3d_grid_nx = QSpinBox()
|
owner._sar3d_voxel_x_m = QDoubleSpinBox()
|
||||||
owner._sar3d_grid_nx.setRange(2, 1024)
|
owner._sar3d_voxel_x_m.setDecimals(3)
|
||||||
owner._sar3d_grid_nx.setValue(int(sar3d_defaults.grid_nx))
|
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_voxel_y_m = QDoubleSpinBox()
|
||||||
owner._sar3d_grid_ny.setRange(2, 1024)
|
owner._sar3d_voxel_y_m.setDecimals(3)
|
||||||
owner._sar3d_grid_ny.setValue(int(sar3d_defaults.grid_ny))
|
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_voxel_z_m = QDoubleSpinBox()
|
||||||
owner._sar3d_grid_nz.setRange(2, 1024)
|
owner._sar3d_voxel_z_m.setDecimals(3)
|
||||||
owner._sar3d_grid_nz.setValue(int(sar3d_defaults.grid_nz))
|
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 = QCheckBox("Use per-voxel compensation")
|
||||||
owner._sar3d_use_compensation.setChecked(bool(sar3d_defaults.use_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,
|
owner._sar3d_apply_freq_phase_correction,
|
||||||
("Frame radius", owner._sar3d_frame_radius),
|
("Frame radius", owner._sar3d_frame_radius),
|
||||||
("Edge frame weight", owner._sar3d_edge_frame_weight),
|
("Edge frame weight", owner._sar3d_edge_frame_weight),
|
||||||
|
owner._sar3d_pitch_override_enabled,
|
||||||
("Pitch deg", owner._sar3d_pitch_deg),
|
("Pitch deg", owner._sar3d_pitch_deg),
|
||||||
("Center depth m", owner._sar3d_center_depth_m),
|
("Ground depth m", owner._sar3d_ground_depth_m),
|
||||||
("Half width X m", owner._sar3d_half_width_x_m),
|
("X margin m", owner._sar3d_x_margin_m),
|
||||||
("Half width Y m", owner._sar3d_half_width_y_m),
|
("Y min m", owner._sar3d_y_min_m),
|
||||||
("Half width Z m", owner._sar3d_half_width_z_m),
|
("Y max m", owner._sar3d_y_max_m),
|
||||||
("Grid Nx", owner._sar3d_grid_nx),
|
("Voxel X m", owner._sar3d_voxel_x_m),
|
||||||
("Grid Ny", owner._sar3d_grid_ny),
|
("Voxel Y m", owner._sar3d_voxel_y_m),
|
||||||
("Grid Nz", owner._sar3d_grid_nz),
|
("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),
|
("Bottom view", owner._sar3d_bottom_view),
|
||||||
owner._sar3d_use_compensation,
|
owner._sar3d_use_compensation,
|
||||||
owner._sar3d_normalize_pairs,
|
owner._sar3d_normalize_pairs,
|
||||||
],
|
],
|
||||||
split_index=11,
|
split_index=13,
|
||||||
)
|
)
|
||||||
owner._processing_mode_pages.addWidget(sar3d_page)
|
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_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_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_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_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_ground_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_x_margin_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_y_min_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_y_max_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||||
owner._sar3d_grid_nx.valueChanged.connect(owner._on_processing_live_settings_changed)
|
owner._sar3d_voxel_x_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||||
owner._sar3d_grid_ny.valueChanged.connect(owner._on_processing_live_settings_changed)
|
owner._sar3d_voxel_y_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||||
owner._sar3d_grid_nz.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_use_compensation.toggled.connect(owner._on_processing_live_settings_changed)
|
||||||
owner._sar3d_normalize_pairs.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)
|
owner._sar3d_bottom_view.currentTextChanged.connect(owner._on_processing_live_settings_changed)
|
||||||
|
|||||||
@@ -533,39 +533,84 @@ def gui_profile_from_dict(payload: dict[str, Any]) -> GuiProfileModel:
|
|||||||
gui.processing.sar3d.edge_frame_weight,
|
gui.processing.sar3d.edge_frame_weight,
|
||||||
"gui.processing.sar3d",
|
"gui.processing.sar3d",
|
||||||
),
|
),
|
||||||
|
pitch_override_enabled=_optional_bool(
|
||||||
|
sar3d_object,
|
||||||
|
"pitch_override_enabled",
|
||||||
|
gui.processing.sar3d.pitch_override_enabled,
|
||||||
|
"gui.processing.sar3d",
|
||||||
|
),
|
||||||
pitch_deg=_optional_float(
|
pitch_deg=_optional_float(
|
||||||
sar3d_object,
|
sar3d_object,
|
||||||
"pitch_deg",
|
"pitch_deg",
|
||||||
gui.processing.sar3d.pitch_deg,
|
gui.processing.sar3d.pitch_deg,
|
||||||
"gui.processing.sar3d",
|
"gui.processing.sar3d",
|
||||||
),
|
),
|
||||||
center_depth_m=_optional_float(
|
ground_depth_m=_optional_float(
|
||||||
sar3d_object,
|
sar3d_object,
|
||||||
"center_depth_m",
|
"ground_depth_m",
|
||||||
gui.processing.sar3d.center_depth_m,
|
gui.processing.sar3d.ground_depth_m,
|
||||||
"gui.processing.sar3d",
|
"gui.processing.sar3d",
|
||||||
),
|
),
|
||||||
half_width_x_m=_optional_float(
|
x_margin_m=_optional_float(
|
||||||
sar3d_object,
|
sar3d_object,
|
||||||
"half_width_x_m",
|
"x_margin_m",
|
||||||
gui.processing.sar3d.half_width_x_m,
|
gui.processing.sar3d.x_margin_m,
|
||||||
"gui.processing.sar3d",
|
"gui.processing.sar3d",
|
||||||
),
|
),
|
||||||
half_width_y_m=_optional_float(
|
y_min_m=_optional_float(
|
||||||
sar3d_object,
|
sar3d_object,
|
||||||
"half_width_y_m",
|
"y_min_m",
|
||||||
gui.processing.sar3d.half_width_y_m,
|
gui.processing.sar3d.y_min_m,
|
||||||
"gui.processing.sar3d",
|
"gui.processing.sar3d",
|
||||||
),
|
),
|
||||||
half_width_z_m=_optional_float(
|
y_max_m=_optional_float(
|
||||||
sar3d_object,
|
sar3d_object,
|
||||||
"half_width_z_m",
|
"y_max_m",
|
||||||
gui.processing.sar3d.half_width_z_m,
|
gui.processing.sar3d.y_max_m,
|
||||||
|
"gui.processing.sar3d",
|
||||||
|
),
|
||||||
|
voxel_x_m=_optional_float(
|
||||||
|
sar3d_object,
|
||||||
|
"voxel_x_m",
|
||||||
|
gui.processing.sar3d.voxel_x_m,
|
||||||
|
"gui.processing.sar3d",
|
||||||
|
),
|
||||||
|
voxel_y_m=_optional_float(
|
||||||
|
sar3d_object,
|
||||||
|
"voxel_y_m",
|
||||||
|
gui.processing.sar3d.voxel_y_m,
|
||||||
|
"gui.processing.sar3d",
|
||||||
|
),
|
||||||
|
voxel_z_m=_optional_float(
|
||||||
|
sar3d_object,
|
||||||
|
"voxel_z_m",
|
||||||
|
gui.processing.sar3d.voxel_z_m,
|
||||||
|
"gui.processing.sar3d",
|
||||||
|
),
|
||||||
|
norm_edge_margin_m=_optional_float(
|
||||||
|
sar3d_object,
|
||||||
|
"norm_edge_margin_m",
|
||||||
|
gui.processing.sar3d.norm_edge_margin_m,
|
||||||
|
"gui.processing.sar3d",
|
||||||
|
),
|
||||||
|
smooth_sigma=_optional_float(
|
||||||
|
sar3d_object,
|
||||||
|
"smooth_sigma",
|
||||||
|
gui.processing.sar3d.smooth_sigma,
|
||||||
|
"gui.processing.sar3d",
|
||||||
|
),
|
||||||
|
comp_range_power=_optional_float(
|
||||||
|
sar3d_object,
|
||||||
|
"comp_range_power",
|
||||||
|
gui.processing.sar3d.comp_range_power,
|
||||||
|
"gui.processing.sar3d",
|
||||||
|
),
|
||||||
|
tx_per_segment=_optional_int(
|
||||||
|
sar3d_object,
|
||||||
|
"tx_per_segment",
|
||||||
|
gui.processing.sar3d.tx_per_segment,
|
||||||
"gui.processing.sar3d",
|
"gui.processing.sar3d",
|
||||||
),
|
),
|
||||||
grid_nx=_optional_int(sar3d_object, "grid_nx", gui.processing.sar3d.grid_nx, "gui.processing.sar3d"),
|
|
||||||
grid_ny=_optional_int(sar3d_object, "grid_ny", gui.processing.sar3d.grid_ny, "gui.processing.sar3d"),
|
|
||||||
grid_nz=_optional_int(sar3d_object, "grid_nz", gui.processing.sar3d.grid_nz, "gui.processing.sar3d"),
|
|
||||||
use_compensation=_optional_bool(
|
use_compensation=_optional_bool(
|
||||||
sar3d_object,
|
sar3d_object,
|
||||||
"use_compensation",
|
"use_compensation",
|
||||||
@@ -628,8 +673,14 @@ def gui_profile_from_dict(payload: dict[str, Any]) -> GuiProfileModel:
|
|||||||
raise ValueError("gui.processing.sar3d.frame_radius must be >= 0")
|
raise ValueError("gui.processing.sar3d.frame_radius must be >= 0")
|
||||||
if not 0.0 <= gui.processing.sar3d.edge_frame_weight <= 1.0:
|
if not 0.0 <= gui.processing.sar3d.edge_frame_weight <= 1.0:
|
||||||
raise ValueError("gui.processing.sar3d.edge_frame_weight must be within [0, 1]")
|
raise ValueError("gui.processing.sar3d.edge_frame_weight must be within [0, 1]")
|
||||||
if min(gui.processing.sar3d.grid_nx, gui.processing.sar3d.grid_ny, gui.processing.sar3d.grid_nz) < 2:
|
if min(gui.processing.sar3d.voxel_x_m, gui.processing.sar3d.voxel_y_m, gui.processing.sar3d.voxel_z_m) <= 0.0:
|
||||||
raise ValueError("gui.processing.sar3d.grid_nx/ny/nz must each be >= 2")
|
raise ValueError("gui.processing.sar3d.voxel_x/y/z_m must each be > 0")
|
||||||
|
if gui.processing.sar3d.y_max_m <= gui.processing.sar3d.y_min_m:
|
||||||
|
raise ValueError("gui.processing.sar3d.y_max_m must be > y_min_m")
|
||||||
|
if gui.processing.sar3d.ground_depth_m < 0.0:
|
||||||
|
raise ValueError("gui.processing.sar3d.ground_depth_m must be >= 0")
|
||||||
|
if gui.processing.sar3d.tx_per_segment < 1:
|
||||||
|
raise ValueError("gui.processing.sar3d.tx_per_segment must be >= 1")
|
||||||
|
|
||||||
data_actions_object = _as_dict(gui_object.get("data_actions"), "gui.data_actions")
|
data_actions_object = _as_dict(gui_object.get("data_actions"), "gui.data_actions")
|
||||||
gui.data_actions = GuiDataActionsStateModel(
|
gui.data_actions = GuiDataActionsStateModel(
|
||||||
@@ -795,14 +846,19 @@ def gui_profile_to_dict(model: GuiProfileModel) -> dict[str, Any]:
|
|||||||
"apply_freq_phase_correction": gui.processing.sar3d.apply_freq_phase_correction,
|
"apply_freq_phase_correction": gui.processing.sar3d.apply_freq_phase_correction,
|
||||||
"frame_radius": gui.processing.sar3d.frame_radius,
|
"frame_radius": gui.processing.sar3d.frame_radius,
|
||||||
"edge_frame_weight": gui.processing.sar3d.edge_frame_weight,
|
"edge_frame_weight": gui.processing.sar3d.edge_frame_weight,
|
||||||
|
"pitch_override_enabled": gui.processing.sar3d.pitch_override_enabled,
|
||||||
"pitch_deg": gui.processing.sar3d.pitch_deg,
|
"pitch_deg": gui.processing.sar3d.pitch_deg,
|
||||||
"center_depth_m": gui.processing.sar3d.center_depth_m,
|
"ground_depth_m": gui.processing.sar3d.ground_depth_m,
|
||||||
"half_width_x_m": gui.processing.sar3d.half_width_x_m,
|
"x_margin_m": gui.processing.sar3d.x_margin_m,
|
||||||
"half_width_y_m": gui.processing.sar3d.half_width_y_m,
|
"y_min_m": gui.processing.sar3d.y_min_m,
|
||||||
"half_width_z_m": gui.processing.sar3d.half_width_z_m,
|
"y_max_m": gui.processing.sar3d.y_max_m,
|
||||||
"grid_nx": gui.processing.sar3d.grid_nx,
|
"voxel_x_m": gui.processing.sar3d.voxel_x_m,
|
||||||
"grid_ny": gui.processing.sar3d.grid_ny,
|
"voxel_y_m": gui.processing.sar3d.voxel_y_m,
|
||||||
"grid_nz": gui.processing.sar3d.grid_nz,
|
"voxel_z_m": gui.processing.sar3d.voxel_z_m,
|
||||||
|
"norm_edge_margin_m": gui.processing.sar3d.norm_edge_margin_m,
|
||||||
|
"smooth_sigma": gui.processing.sar3d.smooth_sigma,
|
||||||
|
"comp_range_power": gui.processing.sar3d.comp_range_power,
|
||||||
|
"tx_per_segment": gui.processing.sar3d.tx_per_segment,
|
||||||
"use_compensation": gui.processing.sar3d.use_compensation,
|
"use_compensation": gui.processing.sar3d.use_compensation,
|
||||||
"normalize_pairs": gui.processing.sar3d.normalize_pairs,
|
"normalize_pairs": gui.processing.sar3d.normalize_pairs,
|
||||||
"bottom_view_deg": gui.processing.sar3d.bottom_view_deg,
|
"bottom_view_deg": gui.processing.sar3d.bottom_view_deg,
|
||||||
|
|||||||
@@ -128,31 +128,36 @@ class GuiSar3dStateModel:
|
|||||||
"""UI-only defaults for the 3D SAR (sar3d) live settings.
|
"""UI-only defaults for the 3D SAR (sar3d) live settings.
|
||||||
|
|
||||||
The band, depth gate, antenna selection and motion knobs mirror the shared
|
The band, depth gate, antenna selection and motion knobs mirror the shared
|
||||||
gpr_* live-config fields; the sar3d_* knobs mirror the VNA_AlGo gpr_core
|
gpr_* live-config fields; the sar3d_* knobs mirror the reference notebook
|
||||||
defaults used by the C++ sar3d processor.
|
(Multi_antenna_3D_clean_v1.ipynb) defaults used by the C++ sar3d processor.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
input_positions: str = ""
|
input_positions: str = ""
|
||||||
output_positions: str = ""
|
output_positions: str = ""
|
||||||
min_depth_m: float = 2.0
|
min_depth_m: float = 2.5
|
||||||
max_depth_m: float = 14.0
|
max_depth_m: float = 8.0
|
||||||
start_freq_mhz: float = 3000.0
|
start_freq_mhz: float = 2000.0
|
||||||
stop_freq_mhz: float = 6000.0
|
stop_freq_mhz: float = 6000.0
|
||||||
speed_m_s: float = 0.0
|
speed_m_s: float = 0.0
|
||||||
ignore_socket_speed_enabled: bool = False
|
ignore_socket_speed_enabled: bool = False
|
||||||
look_angle_deg: float = 0.0
|
look_angle_deg: float = 17.5
|
||||||
direction_sign: float = 1.0
|
direction_sign: float = 1.0
|
||||||
apply_freq_phase_correction: bool = True
|
apply_freq_phase_correction: bool = True
|
||||||
frame_radius: int = 6
|
frame_radius: int = 0
|
||||||
edge_frame_weight: float = 0.75
|
edge_frame_weight: float = 0.8
|
||||||
pitch_deg: float = 6.0
|
pitch_override_enabled: bool = False
|
||||||
center_depth_m: float = 5.6
|
pitch_deg: float = 17.5
|
||||||
half_width_x_m: float = 1.8
|
ground_depth_m: float = 1.25
|
||||||
half_width_y_m: float = 1.0
|
x_margin_m: float = 2.0
|
||||||
half_width_z_m: float = 1.8
|
y_min_m: float = -0.5
|
||||||
grid_nx: int = 150
|
y_max_m: float = 2.0
|
||||||
grid_ny: int = 120
|
voxel_x_m: float = 0.025
|
||||||
grid_nz: int = 160
|
voxel_y_m: float = 0.02
|
||||||
|
voxel_z_m: float = 0.02
|
||||||
|
norm_edge_margin_m: float = 0.3
|
||||||
|
smooth_sigma: float = 1.5
|
||||||
|
comp_range_power: float = 0.3
|
||||||
|
tx_per_segment: int = 2
|
||||||
use_compensation: bool = True
|
use_compensation: bool = True
|
||||||
normalize_pairs: bool = True
|
normalize_pairs: bool = True
|
||||||
# Bottom-view projection angle around the vertical Y axis, degrees:
|
# Bottom-view projection angle around the vertical Y axis, degrees:
|
||||||
|
|||||||
@@ -72,19 +72,31 @@ class ProcessingLiveConfig:
|
|||||||
gpr_visible_x_max_m: float = 2.0
|
gpr_visible_x_max_m: float = 2.0
|
||||||
gpr_visible_z_min_m: float = 0.0
|
gpr_visible_z_min_m: float = 0.0
|
||||||
gpr_visible_z_max_m: float = 14.0
|
gpr_visible_z_max_m: float = 14.0
|
||||||
# 3D SAR (sar3d processor) parameters; defaults mirror VNA_AlGo gpr_core.
|
# 3D SAR (sar3d processor) parameters; defaults mirror the reference
|
||||||
# The frequency band, depth gate, antenna selection and motion parameters
|
# notebook Multi_antenna_3D_clean_v1.ipynb. The frequency band, depth gate,
|
||||||
# are shared with the gpr_* fields above.
|
# antenna selection and motion parameters are shared with the gpr_* fields.
|
||||||
sar3d_frame_radius: int = 6
|
sar3d_frame_radius: int = 0
|
||||||
sar3d_edge_frame_weight: float = 0.75
|
sar3d_edge_frame_weight: float = 0.8
|
||||||
sar3d_pitch_deg: float = 6.0
|
# Frame pitch override; disabled -> the pitch follows gpr_look_angle_deg.
|
||||||
sar3d_center_depth_m: float = 5.6
|
sar3d_pitch_override_enabled: bool = False
|
||||||
sar3d_half_width_x_m: float = 1.8
|
sar3d_pitch_deg: float = 17.5
|
||||||
sar3d_half_width_y_m: float = 1.0
|
# Height of the lower antenna row above the ground (scene Y=0 = ground).
|
||||||
sar3d_half_width_z_m: float = 1.8
|
sar3d_ground_depth_m: float = 1.25
|
||||||
sar3d_grid_nx: int = 150
|
# Full-region grid: X spans the antennas +- margin, Y is height above the
|
||||||
sar3d_grid_ny: int = 120
|
# ground, Z covers the radar depth gate over the Y range.
|
||||||
sar3d_grid_nz: int = 160
|
sar3d_x_margin_m: float = 2.0
|
||||||
|
sar3d_y_min_m: float = -0.5
|
||||||
|
sar3d_y_max_m: float = 2.0
|
||||||
|
sar3d_voxel_x_m: float = 0.025
|
||||||
|
sar3d_voxel_y_m: float = 0.02
|
||||||
|
sar3d_voxel_z_m: float = 0.02
|
||||||
|
# Volume finalization: Y-edge margin excluded from normalization, Gaussian
|
||||||
|
# smoothing sigma over (Z, X) planes.
|
||||||
|
sar3d_norm_edge_margin_m: float = 0.3
|
||||||
|
sar3d_smooth_sigma: float = 1.5
|
||||||
|
sar3d_comp_range_power: float = 0.3
|
||||||
|
# Fallback frame segmentation when per-trace capture stamps are absent.
|
||||||
|
sar3d_tx_per_segment: int = 2
|
||||||
sar3d_use_compensation: bool = True
|
sar3d_use_compensation: bool = True
|
||||||
sar3d_normalize_pairs: bool = True
|
sar3d_normalize_pairs: bool = True
|
||||||
# Bottom-view projection angle around the vertical Y axis, degrees:
|
# Bottom-view projection angle around the vertical Y axis, degrees:
|
||||||
@@ -156,14 +168,19 @@ class ProcessingLiveConfig:
|
|||||||
"gpr_visible_z_max_m": float(self.gpr_visible_z_max_m),
|
"gpr_visible_z_max_m": float(self.gpr_visible_z_max_m),
|
||||||
"sar3d_frame_radius": int(self.sar3d_frame_radius),
|
"sar3d_frame_radius": int(self.sar3d_frame_radius),
|
||||||
"sar3d_edge_frame_weight": float(self.sar3d_edge_frame_weight),
|
"sar3d_edge_frame_weight": float(self.sar3d_edge_frame_weight),
|
||||||
|
"sar3d_pitch_override_enabled": bool(self.sar3d_pitch_override_enabled),
|
||||||
"sar3d_pitch_deg": float(self.sar3d_pitch_deg),
|
"sar3d_pitch_deg": float(self.sar3d_pitch_deg),
|
||||||
"sar3d_center_depth_m": float(self.sar3d_center_depth_m),
|
"sar3d_ground_depth_m": float(self.sar3d_ground_depth_m),
|
||||||
"sar3d_half_width_x_m": float(self.sar3d_half_width_x_m),
|
"sar3d_x_margin_m": float(self.sar3d_x_margin_m),
|
||||||
"sar3d_half_width_y_m": float(self.sar3d_half_width_y_m),
|
"sar3d_y_min_m": float(self.sar3d_y_min_m),
|
||||||
"sar3d_half_width_z_m": float(self.sar3d_half_width_z_m),
|
"sar3d_y_max_m": float(self.sar3d_y_max_m),
|
||||||
"sar3d_grid_nx": int(self.sar3d_grid_nx),
|
"sar3d_voxel_x_m": float(self.sar3d_voxel_x_m),
|
||||||
"sar3d_grid_ny": int(self.sar3d_grid_ny),
|
"sar3d_voxel_y_m": float(self.sar3d_voxel_y_m),
|
||||||
"sar3d_grid_nz": int(self.sar3d_grid_nz),
|
"sar3d_voxel_z_m": float(self.sar3d_voxel_z_m),
|
||||||
|
"sar3d_norm_edge_margin_m": float(self.sar3d_norm_edge_margin_m),
|
||||||
|
"sar3d_smooth_sigma": float(self.sar3d_smooth_sigma),
|
||||||
|
"sar3d_comp_range_power": float(self.sar3d_comp_range_power),
|
||||||
|
"sar3d_tx_per_segment": int(self.sar3d_tx_per_segment),
|
||||||
"sar3d_use_compensation": bool(self.sar3d_use_compensation),
|
"sar3d_use_compensation": bool(self.sar3d_use_compensation),
|
||||||
"sar3d_normalize_pairs": bool(self.sar3d_normalize_pairs),
|
"sar3d_normalize_pairs": bool(self.sar3d_normalize_pairs),
|
||||||
"sar3d_bottom_view_deg": float(self.sar3d_bottom_view_deg),
|
"sar3d_bottom_view_deg": float(self.sar3d_bottom_view_deg),
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ never see time jump backwards. ``collection_id`` increases forever.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
@@ -75,6 +76,22 @@ def _load_dataset(dataset_dir: Path, combos: list[ComboKey], expected_points: in
|
|||||||
timestamps_ns: list[int] = []
|
timestamps_ns: list[int] = []
|
||||||
for name, timestamp_ns in named:
|
for name, timestamp_ns in named:
|
||||||
folder = dataset_dir / name
|
folder = dataset_dir / name
|
||||||
|
# Recorded per-trace capture windows from the snapshot's meta.json: the
|
||||||
|
# sar3d segmented timing model reconstructs the acquisition segments
|
||||||
|
# from them. Missing/partial meta leaves the zero "unmeasured" sentinel
|
||||||
|
# and the consumer falls back to its uniform-segment model.
|
||||||
|
windows: dict[tuple[int, int], tuple[int, int]] = {}
|
||||||
|
meta_path = folder / "meta.json"
|
||||||
|
if meta_path.is_file():
|
||||||
|
try:
|
||||||
|
meta = json.loads(meta_path.read_text())
|
||||||
|
for entry in meta.get("traces", []):
|
||||||
|
windows[(int(entry["input"]), int(entry["output"]))] = (
|
||||||
|
int(entry["capture_start_ns"]),
|
||||||
|
int(entry["capture_end_ns"]),
|
||||||
|
)
|
||||||
|
except (OSError, ValueError, KeyError, TypeError):
|
||||||
|
windows = {}
|
||||||
traces: list[TraceData] = []
|
traces: list[TraceData] = []
|
||||||
for combo in combos:
|
for combo in combos:
|
||||||
s21_path = folder / f"i{combo.input}_o{combo.output}_s21.npy"
|
s21_path = folder / f"i{combo.input}_o{combo.output}_s21.npy"
|
||||||
@@ -94,12 +111,15 @@ def _load_dataset(dataset_dir: Path, combos: list[ComboKey], expected_points: in
|
|||||||
f"{s21_path}: {s21.size} points, but radar.sweep.points = "
|
f"{s21_path}: {s21.size} points, but radar.sweep.points = "
|
||||||
f"{expected_points}. Align the profile's sweep with the dataset."
|
f"{expected_points}. Align the profile's sweep with the dataset."
|
||||||
)
|
)
|
||||||
|
window = windows.get((combo.input, combo.output), (0, 0))
|
||||||
traces.append(
|
traces.append(
|
||||||
TraceData(
|
TraceData(
|
||||||
combo=combo,
|
combo=combo,
|
||||||
frequency_hz=freq,
|
frequency_hz=freq,
|
||||||
s11=np.zeros_like(s21),
|
s11=np.zeros_like(s21),
|
||||||
s21=s21,
|
s21=s21,
|
||||||
|
capture_start_ns=window[0],
|
||||||
|
capture_end_ns=window[1],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
snapshots.append(traces)
|
snapshots.append(traces)
|
||||||
@@ -114,28 +134,38 @@ def _build_collection(
|
|||||||
collection_id: int,
|
collection_id: int,
|
||||||
frame_ns: int,
|
frame_ns: int,
|
||||||
) -> SweepCollection:
|
) -> SweepCollection:
|
||||||
"""Wrap one preloaded snapshot in a SweepCollection at the given frame time."""
|
"""Wrap one preloaded snapshot in a SweepCollection at the given frame time.
|
||||||
|
|
||||||
|
Recorded per-trace capture windows are re-anchored by the same shift as the
|
||||||
|
frame time, preserving the real intra-frame segment layout. Traces without
|
||||||
|
recorded windows get a synthetic window spanning the median frame gap.
|
||||||
|
"""
|
||||||
span_ns = dataset.median_gap_ns
|
span_ns = dataset.median_gap_ns
|
||||||
start_ns = frame_ns - span_ns // 2
|
start_ns = frame_ns - span_ns // 2
|
||||||
end_ns = frame_ns + span_ns // 2
|
end_ns = frame_ns + span_ns // 2
|
||||||
|
shift_ns = frame_ns - dataset.timestamps_ns[index]
|
||||||
traces = []
|
traces = []
|
||||||
for source in dataset.snapshots[index]:
|
for source in dataset.snapshots[index]:
|
||||||
|
if source.capture_end_ns > source.capture_start_ns:
|
||||||
|
capture = (source.capture_start_ns + shift_ns, source.capture_end_ns + shift_ns)
|
||||||
|
else:
|
||||||
|
capture = (start_ns, end_ns)
|
||||||
traces.append(
|
traces.append(
|
||||||
TraceData(
|
TraceData(
|
||||||
combo=source.combo,
|
combo=source.combo,
|
||||||
frequency_hz=source.frequency_hz,
|
frequency_hz=source.frequency_hz,
|
||||||
s11=source.s11,
|
s11=source.s11,
|
||||||
s21=source.s21,
|
s21=source.s21,
|
||||||
capture_start_ns=start_ns,
|
capture_start_ns=capture[0],
|
||||||
capture_end_ns=end_ns,
|
capture_end_ns=capture[1],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return SweepCollection(
|
return SweepCollection(
|
||||||
collection_id=collection_id,
|
collection_id=collection_id,
|
||||||
monotonic_ns=frame_ns,
|
monotonic_ns=frame_ns,
|
||||||
traces=traces,
|
traces=traces,
|
||||||
capture_start_ns=start_ns,
|
capture_start_ns=min(t.capture_start_ns for t in traces),
|
||||||
capture_end_ns=end_ns,
|
capture_end_ns=max(t.capture_end_ns for t in traces),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -84,14 +84,25 @@ def _sar3d_live_config(profile_path: Path) -> ProcessingLiveConfig:
|
|||||||
live.sar3d_edge_frame_weight = float(
|
live.sar3d_edge_frame_weight = float(
|
||||||
sar3d.get("edge_frame_weight", live.sar3d_edge_frame_weight)
|
sar3d.get("edge_frame_weight", live.sar3d_edge_frame_weight)
|
||||||
)
|
)
|
||||||
|
live.sar3d_pitch_override_enabled = bool(
|
||||||
|
sar3d.get("pitch_override_enabled", live.sar3d_pitch_override_enabled)
|
||||||
|
)
|
||||||
live.sar3d_pitch_deg = float(sar3d.get("pitch_deg", live.sar3d_pitch_deg))
|
live.sar3d_pitch_deg = float(sar3d.get("pitch_deg", live.sar3d_pitch_deg))
|
||||||
live.sar3d_center_depth_m = float(sar3d.get("center_depth_m", live.sar3d_center_depth_m))
|
live.sar3d_ground_depth_m = float(sar3d.get("ground_depth_m", live.sar3d_ground_depth_m))
|
||||||
live.sar3d_half_width_x_m = float(sar3d.get("half_width_x_m", live.sar3d_half_width_x_m))
|
live.sar3d_x_margin_m = float(sar3d.get("x_margin_m", live.sar3d_x_margin_m))
|
||||||
live.sar3d_half_width_y_m = float(sar3d.get("half_width_y_m", live.sar3d_half_width_y_m))
|
live.sar3d_y_min_m = float(sar3d.get("y_min_m", live.sar3d_y_min_m))
|
||||||
live.sar3d_half_width_z_m = float(sar3d.get("half_width_z_m", live.sar3d_half_width_z_m))
|
live.sar3d_y_max_m = float(sar3d.get("y_max_m", live.sar3d_y_max_m))
|
||||||
live.sar3d_grid_nx = int(sar3d.get("grid_nx", live.sar3d_grid_nx))
|
live.sar3d_voxel_x_m = float(sar3d.get("voxel_x_m", live.sar3d_voxel_x_m))
|
||||||
live.sar3d_grid_ny = int(sar3d.get("grid_ny", live.sar3d_grid_ny))
|
live.sar3d_voxel_y_m = float(sar3d.get("voxel_y_m", live.sar3d_voxel_y_m))
|
||||||
live.sar3d_grid_nz = int(sar3d.get("grid_nz", live.sar3d_grid_nz))
|
live.sar3d_voxel_z_m = float(sar3d.get("voxel_z_m", live.sar3d_voxel_z_m))
|
||||||
|
live.sar3d_norm_edge_margin_m = float(
|
||||||
|
sar3d.get("norm_edge_margin_m", live.sar3d_norm_edge_margin_m)
|
||||||
|
)
|
||||||
|
live.sar3d_smooth_sigma = float(sar3d.get("smooth_sigma", live.sar3d_smooth_sigma))
|
||||||
|
live.sar3d_comp_range_power = float(
|
||||||
|
sar3d.get("comp_range_power", live.sar3d_comp_range_power)
|
||||||
|
)
|
||||||
|
live.sar3d_tx_per_segment = int(sar3d.get("tx_per_segment", live.sar3d_tx_per_segment))
|
||||||
live.sar3d_use_compensation = bool(sar3d.get("use_compensation", live.sar3d_use_compensation))
|
live.sar3d_use_compensation = bool(sar3d.get("use_compensation", live.sar3d_use_compensation))
|
||||||
live.sar3d_normalize_pairs = bool(sar3d.get("normalize_pairs", live.sar3d_normalize_pairs))
|
live.sar3d_normalize_pairs = bool(sar3d.get("normalize_pairs", live.sar3d_normalize_pairs))
|
||||||
live.sar3d_bottom_view_deg = float(sar3d.get("bottom_view_deg", live.sar3d_bottom_view_deg))
|
live.sar3d_bottom_view_deg = float(sar3d.get("bottom_view_deg", live.sar3d_bottom_view_deg))
|
||||||
|
|||||||
Reference in New Issue
Block a user