Tests for coercing stack params to valid values.
Co-authored with Julian Stirling
This commit is contained in:
parent
fa6fdb1a67
commit
089beae01a
3 changed files with 111 additions and 4 deletions
|
|
@ -538,7 +538,7 @@ class AutofocusThing(lt.Thing):
|
||||||
images_to_save = 1
|
images_to_save = 1
|
||||||
elif images_to_save > min_images_to_test:
|
elif images_to_save > min_images_to_test:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"Cannot save {min_images_to_test} images as this above the minimum "
|
f"Cannot save {images_to_save} images as this above the minimum "
|
||||||
f"number to test. Setting images to save to {MAX_TEST_IMAGE_COUNT}."
|
f"number to test. Setting images to save to {MAX_TEST_IMAGE_COUNT}."
|
||||||
)
|
)
|
||||||
images_to_save = min_images_to_test
|
images_to_save = min_images_to_test
|
||||||
|
|
|
||||||
|
|
@ -292,8 +292,11 @@ def scan_thing_mocked_for_scan_data(smart_scan_thing, mocker):
|
||||||
mock_stage = mocker.Mock()
|
mock_stage = mocker.Mock()
|
||||||
type(mock_stage).position = mocker.PropertyMock(return_value=MOCK_START_POS)
|
type(mock_stage).position = mocker.PropertyMock(return_value=MOCK_START_POS)
|
||||||
|
|
||||||
|
mock_autofocus = mocker.Mock()
|
||||||
|
|
||||||
smart_scan_thing._ongoing_scan = mock_ongoing_scan
|
smart_scan_thing._ongoing_scan = mock_ongoing_scan
|
||||||
smart_scan_thing._stage = mock_stage
|
smart_scan_thing._stage = mock_stage
|
||||||
|
smart_scan_thing._autofocus = mock_autofocus
|
||||||
return smart_scan_thing
|
return smart_scan_thing
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,29 @@ Currently these tests don't test the Thing itself, just surrounding functionalit
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
import tempfile
|
||||||
from random import randint
|
from random import randint
|
||||||
|
import logging
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from hypothesis import given, strategies as st
|
from hypothesis import given, strategies as st
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
|
import labthings_fastapi as lt
|
||||||
|
|
||||||
from openflexure_microscope_server.things.autofocus import (
|
from openflexure_microscope_server.things.autofocus import (
|
||||||
|
AutofocusThing,
|
||||||
StackParams,
|
StackParams,
|
||||||
CaptureInfo,
|
CaptureInfo,
|
||||||
|
MIN_TEST_IMAGE_COUNT,
|
||||||
|
MAX_TEST_IMAGE_COUNT,
|
||||||
_get_capture_by_id,
|
_get_capture_by_id,
|
||||||
_get_capture_index_by_id,
|
_get_capture_index_by_id,
|
||||||
)
|
)
|
||||||
from openflexure_microscope_server.scan_directories import IMAGE_REGEX
|
from openflexure_microscope_server.scan_directories import IMAGE_REGEX
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger("mock-invocation_logger")
|
||||||
RANDOM_GENERATOR = np.random.default_rng()
|
RANDOM_GENERATOR = np.random.default_rng()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -42,21 +51,24 @@ def even_integers(min_value=0, max_value=1000):
|
||||||
|
|
||||||
|
|
||||||
@given(
|
@given(
|
||||||
save_ims=odd_integers(min_value=0, max_value=10),
|
save_ims=odd_integers(min_value=1, max_value=9),
|
||||||
extra_ims=even_integers(min_value=0, max_value=10),
|
extra_ims=even_integers(min_value=0, max_value=10),
|
||||||
)
|
)
|
||||||
def test_stack_params_validation(save_ims, extra_ims):
|
def test_stack_params_validation(save_ims, extra_ims):
|
||||||
"""Test the validation of the image numbers for a stack.
|
"""Test the validation of the image numbers for a stack for valid combinations.
|
||||||
|
|
||||||
save_ims is the number to save (must be odd and positive)
|
save_ims is the number to save (must be odd and positive)
|
||||||
extra_ims is how many more images there are in min_images_to_test than
|
extra_ims is how many more images there are in min_images_to_test than
|
||||||
images_to_save. (even so that, min_images_to_test is odd and larger than
|
images_to_save. (even so that, min_images_to_test is odd and larger than
|
||||||
images_to_save
|
images_to_save
|
||||||
"""
|
"""
|
||||||
|
# Coerce min_images_to_test as the max extra ims depends on save_ims so is hard
|
||||||
|
# to do automatically in hypothesis. This clamps the number between 3 and 9.
|
||||||
|
min_images_to_test = max(min(save_ims + extra_ims, 9), 3)
|
||||||
StackParams(
|
StackParams(
|
||||||
stack_dz=50,
|
stack_dz=50,
|
||||||
images_to_save=save_ims,
|
images_to_save=save_ims,
|
||||||
min_images_to_test=save_ims + extra_ims,
|
min_images_to_test=min_images_to_test,
|
||||||
autofocus_dz=2000,
|
autofocus_dz=2000,
|
||||||
images_dir="/this/is/fake",
|
images_dir="/this/is/fake",
|
||||||
save_resolution=(1640, 1232),
|
save_resolution=(1640, 1232),
|
||||||
|
|
@ -228,3 +240,95 @@ def test_retrieval_of_captures(start):
|
||||||
_get_capture_by_id(captures, start - 1)
|
_get_capture_by_id(captures, start - 1)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
_get_capture_by_id(captures, start + 21)
|
_get_capture_by_id(captures, start + 21)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def autofocus_thing():
|
||||||
|
"""Yield an autofocus thing connected to a server."""
|
||||||
|
autofocus_thing = AutofocusThing()
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
server = lt.ThingServer(settings_folder=tmpdir)
|
||||||
|
server.add_thing(autofocus_thing, "/autofocus/")
|
||||||
|
with TestClient(server.app):
|
||||||
|
yield autofocus_thing
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_stack(autofocus_thing, caplog):
|
||||||
|
"""Run create stack with default values and check there is no coercion or logging."""
|
||||||
|
initial_min_images_to_test = autofocus_thing.stack_min_images_to_test
|
||||||
|
initial_images_to_save = autofocus_thing.stack_images_to_save
|
||||||
|
with caplog.at_level(logging.INFO):
|
||||||
|
stack_params = autofocus_thing.create_stack_params(
|
||||||
|
autofocus_dz=2000,
|
||||||
|
images_dir="/this/is/fake",
|
||||||
|
save_resolution=(1640, 1232),
|
||||||
|
logger=LOGGER,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(caplog.records) == 0
|
||||||
|
assert autofocus_thing.stack_min_images_to_test == initial_min_images_to_test
|
||||||
|
assert autofocus_thing.stack_images_to_save == initial_images_to_save
|
||||||
|
assert stack_params.min_images_to_test == autofocus_thing.stack_min_images_to_test
|
||||||
|
assert stack_params.images_to_save == autofocus_thing.stack_images_to_save
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("initial_test_ims", "coerced_test_ims", "expected_log_start"),
|
||||||
|
[
|
||||||
|
(0, MIN_TEST_IMAGE_COUNT, "Cannot test only 0"),
|
||||||
|
(-1, MIN_TEST_IMAGE_COUNT, "Cannot test only -1"),
|
||||||
|
(10, MAX_TEST_IMAGE_COUNT, "Testing 10 images will"),
|
||||||
|
(4, 5, "Minimum number of images to test should be odd"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_coercing_stack_test_ims(
|
||||||
|
initial_test_ims, coerced_test_ims, expected_log_start, autofocus_thing, caplog
|
||||||
|
):
|
||||||
|
"""Run create stack with images to test set to values requiring coercion, and check result."""
|
||||||
|
autofocus_thing.stack_min_images_to_test = initial_test_ims
|
||||||
|
|
||||||
|
with caplog.at_level(logging.WARNING):
|
||||||
|
stack_params = autofocus_thing.create_stack_params(
|
||||||
|
autofocus_dz=2000,
|
||||||
|
images_dir="/this/is/fake",
|
||||||
|
save_resolution=(1640, 1232),
|
||||||
|
logger=LOGGER,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(caplog.records) == 1
|
||||||
|
assert str(caplog.records[0].msg).startswith(expected_log_start)
|
||||||
|
# Check the value is coerced in the stack_params
|
||||||
|
assert stack_params.min_images_to_test == coerced_test_ims
|
||||||
|
# Check that the setting in the Thing was updated to the coerced value
|
||||||
|
assert stack_params.min_images_to_test == autofocus_thing.stack_min_images_to_test
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("initial_save_ims", "coerced_save_ims", "expected_log_start"),
|
||||||
|
[
|
||||||
|
(0, 1, "At least 1 images must be saved"),
|
||||||
|
(-1, 1, "At least 1 images must be saved"),
|
||||||
|
(10, 9, "Cannot save 10 images"),
|
||||||
|
(4, 5, "Images to save should be odd, setting to 5"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_coercing_stack_save_ims(
|
||||||
|
initial_save_ims, coerced_save_ims, expected_log_start, autofocus_thing, caplog
|
||||||
|
):
|
||||||
|
"""Run create stack with images to save set to values requiring coercion, and check result."""
|
||||||
|
autofocus_thing.stack_images_to_save = initial_save_ims
|
||||||
|
|
||||||
|
with caplog.at_level(logging.WARNING):
|
||||||
|
stack_params = autofocus_thing.create_stack_params(
|
||||||
|
autofocus_dz=2000,
|
||||||
|
images_dir="/this/is/fake",
|
||||||
|
save_resolution=(1640, 1232),
|
||||||
|
logger=LOGGER,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(caplog.records) == 1
|
||||||
|
assert str(caplog.records[0].msg).startswith(expected_log_start)
|
||||||
|
# Check the value is coerced in the stack_params
|
||||||
|
assert stack_params.images_to_save == coerced_save_ims
|
||||||
|
# Check that the setting in the Thing was updated to the coerced value
|
||||||
|
assert stack_params.images_to_save == autofocus_thing.stack_images_to_save
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue