Apply suggestions from code review of branch jpeg-capture-in-stacking

Co-authored-by: Beth Probert <beth_probert@outlook.com>
This commit is contained in:
Julian Stirling 2025-06-25 14:22:01 +00:00
parent 2d49bf2061
commit 0933ece63a
8 changed files with 43 additions and 15 deletions

View file

@ -11,6 +11,11 @@ from openflexure_microscope_server.things.camera.picamera import StreamingPiCame
@fixture(scope="module")
def client():
"""
A pytest fixture that initialises a test client for the StreamingPiCamera2 Thing.
This fixture sets up a ThingServer, registers a StreamingPiCamera2 instance at the
"/camera/" endpoint, and provides a ThingClient for interacting with it during tests.
"""
server = ThingServer()
server.add_thing(StreamingPiCamera2(), "/camera/")
with TestClient(server.app) as test_client:
@ -30,13 +35,20 @@ def test_jpeg_and_array(client):
Check that grabbing a jpeg from the stream results in the same size
image as a array capture or a jpeg capture.
"""
# Grab a jpeg from the stream
blob = client.grab_jpeg()
mjpeg_frame = Image.open(blob.open())
assert mjpeg_frame
# Capture a jpeg
blob = client.capture_jpeg(resolution="main")
jpeg_capture = Image.open(blob.open())
assert jpeg_capture
# Capture an array
arrlist = client.capture_array(stream_name="main")
array_main = np.array(arrlist)
# Verify image sizes are the same
assert mjpeg_frame.size == jpeg_capture.size
assert array_main.shape[1::-1] == jpeg_capture.size

View file

@ -1,7 +1,7 @@
"""
Check exposure times do not drift.
This can get very tedious. Recommende running pytest with -s option
This can get very tedious. Recommend running pytest with -s option
to monitor progress.
"""
@ -38,16 +38,18 @@ def _test_exposure_time_drift(desired_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
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
frame_et = client.exposure_time
print(f"Frame {i} captured with exposure time {frame_et}")
# Check no further drift in value
assert first_et == frame_et
else:
frame_et = client.exposure_time
print(f"Frame {i} captured with exposure time {frame_et}")
# Check no further drift in value
assert first_et == frame_et
# Set the exposure time to the value it already is. To check it doesn't shift
print(f"Setting exposure time to {frame_et} to check it doesn't change")
@ -62,6 +64,9 @@ def _test_exposure_time_drift(desired_time):
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)

View file

@ -24,6 +24,9 @@ def test_sensor_mode():
for size in [(3280, 2464), (1640, 1232)]:
client.sensor_mode = {"output_size": size, "bit_depth": 10}
arr = np.array(client.capture_array(stream_name="raw"))
# Check that the array dimensions match the requested image size.
# Note: Numpy array shape is (y,x), but the sensor is set with (x,y)
# hence the need to compare index 0 with index 1.
assert arr.shape[0] == size[1]

View file

@ -33,14 +33,14 @@ def generate_bad_tuning():
return bad_tuning
def print_tuning(read_file=False):
def print_tuning(read_file: bool = False):
"""
Print the path of the default tuning file from the the environment variable.
:param read_file: Boolean, set true to also print the file contents.
This is useful for debuging. As PyTest suppresses the printing by default the
-s option is needed when running pylint to see this.
This is useful for debugging. As pytest suppresses the printing by default the
-s option is needed when running pytest to see this.
"""
key = "LIBCAMERA_RPI_TUNING_FILE"
if key in os.environ:
@ -52,7 +52,7 @@ def print_tuning(read_file=False):
print("Tuning file environment variable not set")
def _test_bad_tuning_after_good_tuning(configure):
def _test_bad_tuning_after_good_tuning(configure: bool = False):
"""
Load the default tuning file into the camera, re-load with a broken tuning file,
check it errors. Finally check the default tuning file will load again afterwards.
@ -66,14 +66,14 @@ def _test_bad_tuning_after_good_tuning(configure):
bad_tuning = generate_bad_tuning()
default_tuning = load_default_tuning()
print_tuning()
print("opening camera with explicitly specified tuning")
print("opening camera with default tuning")
with Picamera2(tuning=default_tuning) as cam:
print_tuning()
if configure:
cam.configure(cam.create_preview_configuration())
del cam
recalibrate_utils.recreate_camera_manager()
print(f"Opening camera with tuning['version'] = {bad_tuning['version']}")
print(f"Opening camera with bad tuning - ['version'] = {bad_tuning['version']}")
with pytest.raises(IndexError):
# The bad version should cause a problem
cam = Picamera2(tuning=bad_tuning)