fix(flomni): clear busy heartbeat on scan end, fix duplicated tomo math
Two independent fixes:
- GUI "beamline busy" indicators (TomoParamsWidget's banner,
FlomniWebpageGenerator's status page) purely wait for
progress["heartbeat"] to go stale (120s / 90s respectively) - there was
no explicit "scan finished" signal to react to instead, since
tomo_scan() wrote a heartbeat at the start of every projection but
never cleared it on exit. Wrapped the scan loop in try/finally so
heartbeat is cleared on every exit path (normal completion, exception,
or interrupt/abort), not just at the next scan's start - both
busy-detectors now see this on their very next poll instead of waiting
out the timeout. Live-verified: heartbeat is None immediately after
tomo_scan() returns.
- Found while investigating a related report ("angular step of the final
combined tomogram shown different between 180 and 360 mode, although
it has to be identical" + "GUI shows projection count doubling when
switching 180->360"): TomoParamsWidget's _compute_type1()/
_requested_to_stepsize() (tomo_params.py) and the generated status
webpage's calcProjections() JS (flomni_webpage_generator.py) are both
independent, un-synced duplicates of the exact old N=int(angle_range/
stepsize) formula fixed in flomni.py's own _tomo_type1_actual_grid()
two commits ago - they were never updated when that fix landed, so the
GUI and webpage kept reporting double the projection count for 360
mode. Fixed both to match flomni.py: N/step/total are always computed
against a fixed 180 degrees, independent of angle_range. Also fixed
the "angular step of the final (combined) tomogram" CLI/wizard lines
in flomni.py itself, which used tomo_angle_range/total_projections
(correct for 180 mode by coincidence, wrong for 360 mode - the true
combined resolution is always 180/total_projections, identical
between modes). Added a regression test asserting the widget's
formulas match flomni.py's for both modes, to catch this exact kind of
drift if it recurs. Live-verified against the running sim: both modes
now report identical total_projections and combined-tomogram step for
the same stepsize.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
"""Regression test for TomoParamsWidget's independent (duplicated)
|
||||
projection-count math: it must stay in sync with Flomni's own
|
||||
_tomo_type1_actual_grid()/_subtomo_angle_plan() -- this exact drift (the
|
||||
widget kept using the old, angle-range-dependent formula after flomni.py
|
||||
was fixed to be mode-independent) is what caused the GUI to show the
|
||||
projection count doubling when switching from 180 to 360 mode.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from csaxs_bec.bec_ipython_client.plugins.flomni.flomni import Flomni
|
||||
from csaxs_bec.bec_widgets.widgets.tomo_params.tomo_params import (
|
||||
_compute_type1,
|
||||
_requested_to_stepsize,
|
||||
)
|
||||
|
||||
STEPSIZES = [10.0, 7.0, 25.0, 12.5]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("stepsize", STEPSIZES)
|
||||
@pytest.mark.parametrize("angle_range", [180, 360])
|
||||
def test_compute_type1_matches_flomni(stepsize, angle_range):
|
||||
total, step, N = _flomni_reference(stepsize)
|
||||
actual_total, achievable_step, _ = _compute_type1(angle_range, stepsize)
|
||||
assert actual_total == total
|
||||
assert achievable_step == pytest.approx(step)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("requested_total", [24, 48, 96, 144, 200])
|
||||
@pytest.mark.parametrize("angle_range", [180, 360])
|
||||
def test_requested_to_stepsize_matches_flomni_wizard_formula(requested_total, angle_range):
|
||||
"""Mirrors the exact line in Flomni.tomo_parameters()'s wizard:
|
||||
self.tomo_angle_stepsize = (180.0 / tomo_numberofprojections) * 8"""
|
||||
stepsize = _requested_to_stepsize(angle_range, requested_total)
|
||||
assert stepsize == pytest.approx((180.0 / requested_total) * 8)
|
||||
|
||||
|
||||
def test_total_projections_identical_between_modes_for_same_stepsize():
|
||||
for stepsize in STEPSIZES:
|
||||
total_180, _, _ = _compute_type1(180, stepsize)
|
||||
total_360, _, _ = _compute_type1(360, stepsize)
|
||||
assert total_180 == total_360
|
||||
|
||||
|
||||
def _flomni_reference(stepsize):
|
||||
N = int(180.0 / stepsize)
|
||||
step = 180.0 / N
|
||||
return N * 8, step, N
|
||||
Reference in New Issue
Block a user