openflexure-microscope-server/hardware-specific-tests/picamera2/test_calibration.py

116 lines
5.1 KiB
Python

"""Test data collection from the Raspberry Picamera."""
from copy import deepcopy
import tempfile
import pytest
import labthings_fastapi as lt
from openflexure_microscope_server.things.camera.picamera import (
MissingCalibrationError,
)
from .cam_test_utils import camera_test_client
def test_get_tuning_algo(picamera_thing):
"""Test that get_tuning algorithm retrieves tuning algorithms."""
# Missing algorithm raises an error.
with pytest.raises(MissingCalibrationError):
picamera_thing.get_tuning_algo("foo")
# Or returns None if explicitly told not to error.
assert picamera_thing.get_tuning_algo("foo", raise_if_missing=False) is None
# Real algorithm is a dict and contains expected keys
assert isinstance(picamera_thing.get_tuning_algo("rpi.geq"), dict)
assert "offset" in picamera_thing.get_tuning_algo("rpi.geq")
# Set the tuning to None as it is technically optional. And check this
# is handled gracefully. This needs to be done in a try block as LabThings
# tries and fails to emit an event.
try:
picamera_thing.tuning = None
except lt.exceptions.NotConnectedToServerError:
# Labthings will complain that it is not connected to a server
pass
# Check it is set to None despite the above LabThings issue.
assert picamera_thing.tuning is None
# Raises an error as there is no tuning file set.
with pytest.raises(MissingCalibrationError):
picamera_thing.get_tuning_algo("rpi.geq")
# Or returns None if explicitly told not to error.
assert picamera_thing.get_tuning_algo("rpi.geq", raise_if_missing=False) is None
def test_calibration(picamera_thing, picamera_client):
"""Check that full auto calibrate completes and set the expected values."""
# Check the calibration_required property used by the calibration wizard
assert picamera_thing.calibration_required
# Save copy of default tuning file for end of test
original_default = deepcopy(picamera_thing.default_tuning)
# Tuning should start the same as the server is loading with no settings.
assert picamera_thing.default_tuning == picamera_thing.tuning
# lens_shading tables should be None when loaded on default tuning as it is
# adaptive
assert picamera_thing.lens_shading_tables is None
# The background detector isn't ready as there is no background image.
assert not picamera_thing.background_detector_status.ready
# Run full auto calibrate
picamera_client.full_auto_calibrate()
# After calibration it should report that calibration is no longer required
assert not picamera_thing.calibration_required
# The tuning files should be different
assert picamera_thing.default_tuning != picamera_thing.tuning
# The default should be unchanged
assert picamera_thing.default_tuning == original_default
# Lens shading tables should no longer be None
assert picamera_thing.lens_shading_tables is not None
# There should be exactly one colour correction matrix
# (no variations by colour temp)
assert len(picamera_thing.get_tuning_algo("rpi.ccm")["ccms"]) == 1
# Green equalisation offset should be set to maximum.
assert picamera_thing.get_tuning_algo("rpi.geq")["offset"] == 65535
assert picamera_thing.background_detector_status.ready
def test_tuning_is_persistent():
"""Check that tuning file adjustments are persistent."""
# First check full auto-calibrate is persistent if same save dir is used.
with tempfile.TemporaryDirectory() as tmpdir:
with camera_test_client(settings_folder=tmpdir) as client:
initial_tuning = deepcopy(client.tuning)
client.full_auto_calibrate()
calibrated_tuning = deepcopy(client.tuning)
# Full auto calibrate should have saved the tuning.
assert initial_tuning != calibrated_tuning
# Reload the camera and server from scratch
with camera_test_client(settings_folder=tmpdir) as client:
initial_tuning = deepcopy(client.tuning)
# On reload the initial tuning is as it was when calibrated last run
assert initial_tuning == calibrated_tuning
# Set the lens shading to be flat
client.flat_lens_shading()
flat_tuning = deepcopy(client.tuning)
assert flat_tuning != calibrated_tuning
# Reload to check the flat lst persists
with camera_test_client(settings_folder=tmpdir) as client:
initial_tuning = deepcopy(client.tuning)
# On reload the initial tuning the flat tuning
assert initial_tuning == flat_tuning
# Reset the lens shading to what is in the default tuning file
client.reset_lens_shading()
flat_tuning = deepcopy(client.tuning)
assert flat_tuning != calibrated_tuning
# Reload the one more time to check the reset lst persists
with camera_test_client(settings_folder=tmpdir) as client:
initial_tuning = deepcopy(client.tuning)
# On reload the initial tuning the flat tuning
assert initial_tuning == flat_tuning