Dedup format layer; public accessors replace private reach-throughs

- SrasFile: _parse_v6 now retains per-angle x_delta and the verbatim
  preamble/background byte spans, and gains public data_offset,
  y_pos_per_angle, and iter_angle_blocks() (which now owns the ragged
  block-offset walk used three separate places before).
- sras_edit_scans: the 70-line re-parse of the v6 header sections
  (_read_v6_sections/_reread_span/_v6_angle_offsets) collapses into a
  _write_v6 that consumes SrasFile directly — verified byte-identical
  round-trip on v6 int8/int16 and legacy files. Eight print-and-exit
  pairs become _die().
- tools/make_test_sras imports the struct layouts from sras_format and
  the rotation matrix from sras_compute instead of re-declaring them
  (byte assembly stays independent of the reader).
- sras_compute: block_mean_2d, pixel_pitch_mm, nominal_delta_deg made
  public (they were GUI-facing); registration_workers() and
  default_max_workers() wrap the remaining private reach-throughs from
  sras_workers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Thomas Ales
2026-08-06 10:40:42 -05:00
parent e80717d5c5
commit 00a7afade0
10 changed files with 134 additions and 156 deletions
+3 -3
View File
@@ -261,7 +261,7 @@ def test_manual_alignment_geometry(ctx):
assert np.allclose(compute._center_idx(s, 0),
[(n_rows - 1) / 2, (n_frames - 1) / 2]), \
"array center is the geometric center of the pixel grid"
dx0, dy0 = compute._pixel_pitch_mm(s, 0)
dx0, dy0 = compute.pixel_pitch_mm(s, 0)
assert np.allclose(compute._local_half_extent_mm(s, 0),
[(n_frames - 1) / 2 * abs(dx0), (n_rows - 1) / 2 * abs(dy0)]), \
"local half-extent is derived from shape and pitch alone"
@@ -270,7 +270,7 @@ def test_manual_alignment_geometry(ctx):
moved = SrasFile(str(ctx.path))
for a in range(1, moved.n_angles):
moved.x_start_mm[a] += 7.5
moved._y_pos_per_angle[a] = moved._y_pos_per_angle[a] + 3.25
moved.y_pos_per_angle[a] = moved.y_pos_per_angle[a] + 3.25
origin_b, shape_b = compute.canvas_for_params(moved, 0, (dx0, dy0), identity)
assert shape_a == shape_b and np.allclose(origin_a, origin_b), \
("moving every non-reference angle's scan window must leave the canvas "
@@ -356,7 +356,7 @@ def test_auto_derotate(ctx):
dlg, s, active = ctx.dlg, ctx.s, ctx.active
shift_before_derotate = dlg._angle_params[active].shift_mm
dlg._on_auto_derotate()
nominal = compute._nominal_delta_deg(s, active, dlg._ref_angle_idx)
nominal = compute.nominal_delta_deg(s, active, dlg._ref_angle_idx)
assert abs(dlg._angle_params[active].rotation_deg - nominal) < 1e-6, \
"auto de-rotate seeded rotation from the stage's reported angle"
assert dlg._angle_params[active].shift_mm == shift_before_derotate, \