Better fix for exposure drift with more complete testing. Also fix return value for capture_to_memory

This commit is contained in:
Julian Stirling 2025-07-29 12:11:45 +01:00
parent 376780ea28
commit b90b02cf7d
3 changed files with 58 additions and 8 deletions

View file

@ -16,11 +16,19 @@ from openflexure_microscope_server.things.camera.picamera import StreamingPiCame
logging.basicConfig(level=logging.DEBUG)
# The tolerance used to be a setting of the camera, and any changes within tolerance
# were ignored. Now this isn't needed we always set a value 1 larger than the last
# accepted value as the PiCamera always rounds down.
# The tolerance is needed in this test as when setting an arbitrary value it is rounded
# down to a hardware compatible one.
EXPOSURE_TOL = 30
def _test_exposure_time_drift(desired_time):
"""Capture 10 full resolution images and check that the exposure time remains constant.
"""Capture 10 full res images and check that the exposure time remains constant.
This confirms that automatic exposure time adjustment is fully turned off
This confirms that automatic exposure time adjustment is fully turned off during
capture.
"""
cam = StreamingPiCamera2()
server = ThingServer()
@ -28,21 +36,20 @@ def _test_exposure_time_drift(desired_time):
with TestClient(server.app) as test_client:
client = ThingClient.from_url("/camera/", client=test_client)
exposure_tol = cam.persistent_control_tolerances["ExposureTime"]
client.exposure_time = desired_time
print(f"Setting desired time of {desired_time}")
time.sleep(0.5)
pre_capture_et = client.exposure_time
print(f"Pre-capture the time is set to {pre_capture_et}")
# Check exp is set correctly within known tolerance
assert abs(pre_capture_et - desired_time) < exposure_tol
assert abs(pre_capture_et - desired_time) < EXPOSURE_TOL
for i in range(10):
client.capture_jpeg(resolution="full")
if i == 0:
# Exposure can update on first capture, due to frame rate restrictions
first_et = client.exposure_time
assert abs(first_et - pre_capture_et) < exposure_tol
assert abs(first_et - desired_time) < EXPOSURE_TOL
else:
frame_et = client.exposure_time
print(f"Frame {i} captured with exposure time {frame_et}")
@ -65,3 +72,45 @@ def test_exposure_time_drift():
"""Performs the exposure time test for a range of exposure time values."""
for desired_time in [100, 1000, 10000]:
_test_exposure_time_drift(desired_time)
def test_exposure_time_on_start_and_stop_stream():
"""Capture 10 full res images and check that the exposure time remains constant.
This confirms that automatic exposure time adjustment is fully turned off during
capture.
"""
cam = StreamingPiCamera2()
server = ThingServer()
server.add_thing(cam, "/camera/")
desired_time = 1000
# Create a test client
with TestClient(server.app) as test_client:
client = ThingClient.from_url("/camera/", client=test_client)
# Set a desired exposure time
client.exposure_time = desired_time
print(f"Setting desired time of {desired_time}")
time.sleep(0.5)
# Take a couple of images to make sure that the exposure is adjusted to
# a hardware compatible value.
for i in range(2):
client.capture_jpeg(resolution="full")
# Save this time.
set_time = client.exposure_time
assert abs(set_time - desired_time) < EXPOSURE_TOL
# Mimick doing 10 smart scans. Change to full res, take some images. Return
# to standard preview resolution.
for i in range(10):
print(f"Starting simulation scan {i}")
# This will need updating if we start supporting other Picamera models
# It is currently used here to mimick the behaviour in in scanning.
client.start_streaming(main_resolution=(3280, 2464))
time.sleep(0.5)
for _j in range(5):
client.capture_to_memory(buffer_max=1)
# Reset to main resolution
time.sleep(0.5)
client.start_streaming()
# Check after all of this the exposure time is the same.
assert abs(client.exposure_time - set_time) < EXPOSURE_TOL