Skip to content

Commit de03ff2

Browse files
committed
[fix] fixed _checkcancelled and merged unittests goffset + goffset_alignment
1 parent 1d430b9 commit de03ff2

4 files changed

Lines changed: 101 additions & 15 deletions

File tree

src/odemis/acq/align/goffset.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def find_peak_position(data: numpy.ndarray, window_radius: int = 15) -> float:
9191

9292
def estimate_goffset_scale(spgr: model.Actuator, detector: model.Detector, delta=5.0, retries = 1) -> Tuple[float, float, float]:
9393
"""
94-
Estimate the scale factor between a change in the grating offset ('goffset')
94+
Estimate the scale factor between a change in the grating offset ('goffset')
9595
and the resulting shift of the spectral peak on the detector.
9696
9797
The function moves the actuator by a small step (delta) and measures the peak position before and after the move.
@@ -106,7 +106,6 @@ def estimate_goffset_scale(spgr: model.Actuator, detector: model.Detector, delta
106106
:param delta: The relative goffset step size to apply when measuring the scale (default: 5.0).
107107
The actual step may be negated to avoid exceeding hardware limits.
108108
:param retries: number of retries allowed if the estimated scale is unreliable (default: 1).
109-
110109
:return: Tuple (scale, p0, p1)
111110
scale: estimated pixels per unit of goffset
112111
p0: peak position at the initial goffset
@@ -226,7 +225,7 @@ def _do_sparc_auto_grating_offset(future: model.ProgressiveFuture,
226225
max_step = 0.1 * (maxv - minv) # max 10% of range
227226

228227
for i in range(max_it):
229-
_checkCancelled()
228+
_checkCancelled(future)
230229

231230
if i == 0:
232231
peak_px = p0
@@ -253,7 +252,8 @@ def _do_sparc_auto_grating_offset(future: model.ProgressiveFuture,
253252
logging.debug(
254253
"DEBUG | Iter: %d | Peak: %.1f | Error: %.1f | Move: %.4f | Total Change: %.4f",
255254
i, peak_px, error_px, delta_goffset, total_goffset_displacement
256-
) spgr.moveRelSync({"goffset": delta_goffset})
255+
)
256+
spgr.moveRelSync({"goffset": delta_goffset})
257257

258258
future.set_progress(
259259
end=time.time() + (max_it - i - 1) * 0.5) # update estimated end time
@@ -464,4 +464,4 @@ def _cancel_auto_align_grating_detector_offsets(future: model.ProgressiveFuture)
464464
future._subfuture.cancel()
465465
logging.debug("Auto-alignment cancellation requested")
466466

467-
return True
467+
return True

src/odemis/acq/align/goffset_alignment.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,4 @@ def _cancel_auto_align_grating_detector_offsets(future: model.ProgressiveFuture)
197197
future._subfuture.cancel()
198198
logging.debug("Auto-alignment cancellation requested")
199199

200-
return True
200+
return True

src/odemis/acq/align/test/goffset_alignment_test.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,11 @@ def test_multi_detector_iteration(self):
114114
# move to spectral camera
115115
self.selector.moveAbsSync({"rx": 1.5707963267948966})
116116
data = spccd.data.get(asap=False)
117-
118117
# check data is not flat
119118
if data.max() == data.min():
120119
print("WARNING: sp-ccd is returning a flat image!")
121120
else:
122121
print(f"sp-ccd signal range: {data.min()} to {data.max()}")
123122

124123
if __name__ == '__main__':
125-
unittest.main()
124+
unittest.main()

src/odemis/acq/align/test/goffset_test.py

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@
88
import unittest
99
import logging
1010
import numpy as np
11+
import odemis
1112

1213
from concurrent.futures._base import CancelledError
13-
1414
from odemis import model
1515
from odemis.util import testing, timeout
1616

1717
from odemis.acq.align.goffset import (find_peak_position,
1818
estimate_goffset_scale,
19-
sparc_auto_grating_offset)
20-
21-
import odemis
19+
sparc_auto_grating_offset,
20+
auto_align_grating_detector_offsets)
2221

2322
logging.getLogger().setLevel(logging.DEBUG)
2423

@@ -59,7 +58,7 @@ def test_find_peak_position_synthetic(self):
5958
"""
6059
x = np.arange(200)
6160
true_center = 83.4
62-
spectrum = np.exp(-0.5*((x-true_center)/3.0)**2)
61+
spectrum = np.exp(-0.5 * ((x - true_center) / 3.0)**2)
6362

6463
peak = find_peak_position(spectrum)
6564
self.assertAlmostEqual(peak, true_center, places=1)
@@ -70,7 +69,7 @@ def test_find_peak_position_2d(self):
7069
"""
7170
x = np.arange(200)
7271
true_center = 120.0
73-
line = np.exp(-0.5*((x-true_center)/4.0)**2)
72+
line = np.exp(-0.5 * ((x - true_center) / 4.0)**2)
7473
image = np.tile(line, (50, 1))
7574

7675
peak = find_peak_position(image)
@@ -115,6 +114,94 @@ def test_cancel(self):
115114
except:
116115
pass
117116
self.assertTrue(f.done())
117+
118+
119+
120+
class TestAutoAlignGratingDetectorOffsets(unittest.TestCase):
121+
122+
@classmethod
123+
def setUpClass(cls):
124+
cls.spgr = model.getComponent(role="spectrograph")
125+
cls.ccd = model.getComponent(role="ccd")
126+
#cls.spccd = model.getComponent(role="sp-ccd")
127+
cls.selector = model.getComponent(role="spec-det-selector")
128+
129+
def setUp(self):
130+
# Speed up acquisition
131+
self.ccd.exposureTime.value = self.ccd.exposureTime.range[0]
132+
133+
@timeout(1000)
134+
def test_single_detector_iteration(self):
135+
f = auto_align_grating_detector_offsets(spectrograph=self.spgr, detectors=[self.ccd], selector=self.selector)
136+
res = f.result(timeout=900)
137+
138+
n_gratings = len(self.spgr.axes["grating"].choices)
139+
n_detectors = 1
140+
expected = n_detectors + (n_gratings - 1)
141+
142+
self.assertEqual(len(res), expected)
143+
144+
first_grating = list(self.spgr.axes["grating"].choices.keys())[0]
145+
dets_first = [d for (g, d) in res.keys() if g == first_grating]
146+
147+
self.assertEqual(len(dets_first), n_detectors)
148+
149+
def test_multi_detector_iteration(self):
150+
spccd = model.getComponent(role="sp-ccd")
151+
spccd.exposureTime.value = spccd.exposureTime.range[0]
152+
153+
detectors = [self.ccd, spccd]
154+
155+
# run alignment
156+
f = auto_align_grating_detector_offsets(spectrograph=self.spgr, detectors=detectors, selector=self.selector)
157+
res = f.result(timeout=900)
158+
159+
# calculate expected results
160+
n_gratings = len(self.spgr.axes["grating"].choices)
161+
n_detectors = len(detectors)
162+
expected_count = n_detectors + (n_gratings - 1)
163+
164+
self.assertEqual(len(res), expected_count, f"Expected {expected_count} results, got {len(res)}")
165+
166+
# verify that every detector was used for the first grating
167+
gratings_list = list(self.spgr.axes["grating"].choices.keys())
168+
first_grating = gratings_list[0]
169+
170+
dets_for_first_grating = [d for (g, d) in res.keys() if g == first_grating]
171+
self.assertEqual(len(dets_for_first_grating), n_detectors)
172+
self.assertIn(self.ccd.name, dets_for_first_grating)
173+
self.assertIn(spccd.name, dets_for_first_grating)
174+
175+
# verify that only first detector is used for remaining gratings
176+
for g in gratings_list[1:]:
177+
# Ensure only the first detector (index 0) is present for these gratings
178+
dets_for_this_grating = [d for (grating, d) in res.keys() if grating == g]
179+
self.assertEqual(len(dets_for_this_grating), 1)
180+
self.assertEqual(dets_for_this_grating[0], detectors[0].name)
181+
182+
# move to spectral camera
183+
self.selector.moveAbsSync({"rx": 1.5707963267948966})
184+
data = spccd.data.get(asap=False)
185+
186+
# check data is not flat
187+
if data.max() == data.min():
188+
print("WARNING: sp-ccd is returning a flat image!")
189+
else:
190+
print(f"sp-ccd signal range: {data.min()} to {data.max()}")
191+
192+
@timeout(100)
193+
def test_cancel(self):
194+
f = auto_align_grating_detector_offsets(spectrograph=self.spgr, detectors=[self.ccd],)
195+
196+
time.sleep(1)
197+
198+
cancelled = f.cancel()
199+
self.assertTrue(cancelled)
200+
self.assertTrue(f.cancelled())
201+
202+
with self.assertRaises(CancelledError):
203+
f.result(timeout=900)
204+
118205

119206
if __name__ == "__main__":
120-
unittest.main()
207+
unittest.main()

0 commit comments

Comments
 (0)