feat/add zero-deg radiation-damage reference shot for lamni tomo_type 1
Ports flomni's zero_deg_reference_at_each_subtomo to lamni's "8 equally spaced sub-tomograms" mode: an extra dedicated projection at exactly 0 degrees before every sub-tomogram where the rotation naturally passes back through 0, plus one final shot once the tomogram completes, for tracking radiation damage over a long acquisition. lamni's tomo_type 2/3 already had the equivalent (golden_projections_at_0_deg_for_damage_estimation, byte-for-byte identical to flomni's) -- only tomo_type 1 was missing. _subtomo_starts_near_zero() uses subtomo_number % 2 (every odd sub-tomogram) rather than flomni's 360-mode subtomo_number % 4 == 1 -- confirmed against lamni's actual rotation behavior rather than derived from the position-array math, which doesn't cleanly split odd/even. The GUI (tomo_params.py) needed no new UI code: _build_type1_section() already gated this control on a per-setup has_zero_deg_reference flag, so enabling it for lamni was just flipping that flag plus adding the param name/default, mirroring flomni's entries exactly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -268,3 +268,68 @@ def test_tomo_scan_clears_heartbeat_even_if_scan_raises():
|
||||
lamni.tomo_scan()
|
||||
|
||||
assert lamni.progress["heartbeat"] is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"subtomo_number,expected",
|
||||
[(1, True), (2, False), (3, True), (4, False), (5, True), (6, False), (7, True), (8, False)],
|
||||
)
|
||||
def test_subtomo_starts_near_zero(subtomo_number, expected):
|
||||
"""Every odd sub-tomogram is where lamni's rotation naturally passes
|
||||
back through 0 degrees (confirmed against lamni's own hardware
|
||||
behavior -- not flomni's 360-mode subtomo_number % 4 == 1, which is
|
||||
specific to flomni's split into two 180-degree halves)."""
|
||||
lamni = make_lamni(10.0)
|
||||
assert lamni._subtomo_starts_near_zero(subtomo_number) is expected
|
||||
|
||||
|
||||
def test_zero_deg_reference_disabled_by_default():
|
||||
"""zero_deg_reference_at_each_subtomo defaults to False -- a fresh
|
||||
tomo_scan() must not fire any extra 0-deg shots."""
|
||||
lamni = make_lamni_for_tomo_scan(45.0, active_account="")
|
||||
lamni.add_sample_database = lambda *a, **k: 0
|
||||
recorded = []
|
||||
lamni._tomo_scan_at_angle = lambda angle, subtomo_number: recorded.append(
|
||||
(angle, subtomo_number)
|
||||
)
|
||||
lamni.sub_tomo_scan = lambda subtomo_number, start_angle=None: None
|
||||
|
||||
lamni.tomo_scan()
|
||||
|
||||
assert recorded == []
|
||||
|
||||
|
||||
def test_zero_deg_reference_fires_for_odd_subtomos_and_final_shot():
|
||||
"""With the flag on, a fresh tomo_scan() must fire an extra angle-0 shot
|
||||
before each odd sub-tomogram (1, 3, 5, 7) plus one final shot after
|
||||
sub-tomogram 8 completes -- mirrors Flomni.tomo_scan()'s equivalent."""
|
||||
lamni = make_lamni_for_tomo_scan(45.0, active_account="")
|
||||
lamni.add_sample_database = lambda *a, **k: 0
|
||||
lamni.zero_deg_reference_at_each_subtomo = True
|
||||
recorded = []
|
||||
lamni._tomo_scan_at_angle = lambda angle, subtomo_number: recorded.append(
|
||||
(angle, subtomo_number)
|
||||
)
|
||||
lamni.sub_tomo_scan = lambda subtomo_number, start_angle=None: None
|
||||
|
||||
lamni.tomo_scan()
|
||||
|
||||
assert recorded == [(0, 1), (0, 3), (0, 5), (0, 7), (0, 8)]
|
||||
|
||||
|
||||
def test_zero_deg_reference_skipped_when_resuming_mid_subtomo():
|
||||
"""A resume (start_angle given explicitly for the first sub-tomogram of
|
||||
this call) must skip the extra shot for that first sub-tomogram --
|
||||
we're not actually passing through 0 deg at that moment -- but must
|
||||
still fire normally for later sub-tomograms in the same call."""
|
||||
lamni = make_lamni_for_tomo_scan(45.0, active_account="")
|
||||
lamni.zero_deg_reference_at_each_subtomo = True
|
||||
recorded = []
|
||||
lamni._tomo_scan_at_angle = lambda angle, subtomo_number: recorded.append(
|
||||
(angle, subtomo_number)
|
||||
)
|
||||
lamni.sub_tomo_scan = lambda subtomo_number, start_angle=None: None
|
||||
|
||||
lamni.tomo_scan(subtomo_start=3, start_angle=45.0)
|
||||
|
||||
assert recorded == [(0, 5), (0, 7), (0, 8)]
|
||||
|
||||
Reference in New Issue
Block a user