Stop seeding Manual Alignment translation from the automatic result

The dialog was seeding rotation_deg/shift_mm from self._alignment_result
whenever it was non-None, with no way to tell whether that result came
from a user's own manual Save or from the automatic Fusion -> Angle
Alignment run. The automatic path's translation comes from FFT phase
correlation - the exact thing manual mode exists to work around - so
opening Manual Alignment after running the automatic pass silently
inherited its unreliable shifts on top of the (correct) analytic
rotation, reproducing the same scattered-scan symptom under a "manual"
label.

Manual mode should always start from identity (each angle's centroid
already coincides with every other's, per the prior pivot fix) unless
the user previously used this same dialog to save their own deliberate
translation - which is exactly what the sidecar file already records.
Seed exclusively from load_manual_alignment() and drop the
self._alignment_result branch entirely; the automatic result is never
an appropriate seed for a manual editing session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Thomas Ales
2026-07-31 11:07:55 -05:00
parent 8312668c02
commit 52e91d46fd
2 changed files with 23 additions and 19 deletions
+13 -10
View File
@@ -2540,16 +2540,19 @@ class SrasViewerWindow(QMainWindow):
ref_idx = 0
threshold_mv = self.spin_threshold_mv.value()
seed: dict[int, ManualAngleParams] = {}
if (self._alignment_result is not None
and self._alignment_result.ref_angle_idx == ref_idx):
seed = {a: ManualAngleParams(t.rotation_deg, t.shift_mm)
for a, t in self._alignment_result.per_angle.items()}
threshold_mv = self._alignment_result.dc_threshold_mv
else:
sidecar = load_manual_alignment(self._sras)
if sidecar is not None and sidecar.ref_angle_idx == ref_idx:
seed = dict(sidecar.per_angle)
threshold_mv = sidecar.dc_threshold_mv
# Seed only from a previously *saved manual* alignment (this dialog's
# own Save also writes this sidecar) -- never from self._alignment_result
# when it holds the automatic Fusion -> Angle Alignment's output. That
# path's translation comes from FFT phase correlation, which is the
# very thing manual mode exists to work around; inheriting it here
# would silently reintroduce the same bad translations under a
# "manual" label, on top of the (correct) analytic rotation, which is
# exactly what makes manual mode look like it "still does the same
# thing" the automatic one does.
sidecar = load_manual_alignment(self._sras)
if sidecar is not None and sidecar.ref_angle_idx == ref_idx:
seed = dict(sidecar.per_angle)
threshold_mv = sidecar.dc_threshold_mv
cached_dc4 = {a: img for (a, ch), img in self._dc_cache.items() if ch == CH4_IDX}
dlg = ManualAlignmentDialog(