386 lines
17 KiB
Python
386 lines
17 KiB
Python
# Copyright (c) 2021-2025 The University of Texas Southwestern Medical Center.
|
|
# All rights reserved.
|
|
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted for academic and research use only (subject to the
|
|
# limitations in the disclaimer below) provided that the following conditions are met:
|
|
|
|
# * Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions and the following disclaimer.
|
|
|
|
# * Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
|
|
# * Neither the name of the copyright holders nor the names of its
|
|
# contributors may be used to endorse or promote products derived from this
|
|
# software without specific prior written permission.
|
|
|
|
# NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
|
# THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
|
|
import random
|
|
import copy
|
|
|
|
import pytest
|
|
import numpy as np
|
|
from unittest.mock import patch
|
|
|
|
|
|
@pytest.fixture
|
|
def channels_tab_controller(dummy_controller):
|
|
from navigate.controller.sub_controllers.channels_tab import (
|
|
ChannelsTabController,
|
|
)
|
|
|
|
return ChannelsTabController(
|
|
dummy_controller.view.settings.channels_tab, dummy_controller
|
|
)
|
|
|
|
|
|
def test_update_z_steps(channels_tab_controller):
|
|
# Calculate params
|
|
z_start, f_start = random.randint(1, 1000), random.randint(1, 1000)
|
|
z_end, f_end = random.randint(1, 1000), random.randint(1, 1000)
|
|
if z_end < z_start:
|
|
# Sort so we are always going low to high
|
|
tmp = z_start
|
|
tmp_f = f_start
|
|
z_start = z_end
|
|
f_start = f_end
|
|
z_end = tmp
|
|
f_end = tmp_f
|
|
step_size = max(1, min(random.randint(1, 10), (z_end - z_start) // 2))
|
|
|
|
# Set params
|
|
channels_tab_controller.microscope_state_dict = (
|
|
channels_tab_controller.parent_controller.configuration["experiment"][
|
|
"MicroscopeState"
|
|
]
|
|
)
|
|
channels_tab_controller.in_initialization = False
|
|
channels_tab_controller.stack_acq_vals["start_position"].set(z_start)
|
|
channels_tab_controller.stack_acq_vals["start_focus"].set(f_start)
|
|
channels_tab_controller.stack_acq_vals["end_position"].set(z_end)
|
|
channels_tab_controller.stack_acq_vals["end_focus"].set(f_end)
|
|
channels_tab_controller.stack_acq_vals["step_size"].set(step_size)
|
|
|
|
# Run
|
|
channels_tab_controller.update_z_steps()
|
|
|
|
# Verify
|
|
number_z_steps = int(np.ceil(np.abs((z_start - z_end) / step_size)))
|
|
assert (
|
|
int(channels_tab_controller.stack_acq_vals["number_z_steps"].get())
|
|
== number_z_steps
|
|
)
|
|
|
|
# test flip_z is True
|
|
microscope_name = (
|
|
channels_tab_controller.parent_controller.configuration_controller.microscope_name
|
|
)
|
|
stage_config = channels_tab_controller.parent_controller.configuration[
|
|
"configuration"
|
|
]["microscopes"][microscope_name]["stage"]
|
|
stage_config["flip_z"] = True
|
|
channels_tab_controller.z_origin = (z_start + z_end) / 2
|
|
channels_tab_controller.stack_acq_vals["start_position"].set(z_end)
|
|
channels_tab_controller.stack_acq_vals["start_focus"].set(f_end)
|
|
channels_tab_controller.stack_acq_vals["end_position"].set(z_start)
|
|
channels_tab_controller.stack_acq_vals["end_focus"].set(f_start)
|
|
channels_tab_controller.update_z_steps()
|
|
assert channels_tab_controller.stack_acq_vals["step_size"].get() == step_size
|
|
assert channels_tab_controller.microscope_state_dict["step_size"] == -1 * step_size
|
|
assert (
|
|
channels_tab_controller.stack_acq_vals["number_z_steps"].get() == number_z_steps
|
|
)
|
|
stage_config["flip_z"] = False
|
|
|
|
|
|
def test_update_start_position(channels_tab_controller):
|
|
z, f = random.randint(0, 1000), random.randint(0, 1000)
|
|
channels_tab_controller.parent_controller.configuration["experiment"][
|
|
"StageParameters"
|
|
]["z"] = z
|
|
channels_tab_controller.parent_controller.configuration["experiment"][
|
|
"StageParameters"
|
|
]["f"] = f
|
|
|
|
channels_tab_controller.update_start_position()
|
|
|
|
assert channels_tab_controller.z_origin == z
|
|
assert channels_tab_controller.focus_origin == f
|
|
assert int(channels_tab_controller.stack_acq_vals["start_position"].get()) == 0
|
|
assert int(channels_tab_controller.stack_acq_vals["start_focus"].get()) == 0
|
|
|
|
# test flip_z is True
|
|
microscope_name = (
|
|
channels_tab_controller.parent_controller.configuration_controller.microscope_name
|
|
)
|
|
stage_config = channels_tab_controller.parent_controller.configuration[
|
|
"configuration"
|
|
]["microscopes"][microscope_name]["stage"]
|
|
stage_config["flip_z"] = True
|
|
channels_tab_controller.update_start_position()
|
|
|
|
assert channels_tab_controller.z_origin == z
|
|
assert channels_tab_controller.focus_origin == f
|
|
assert int(channels_tab_controller.stack_acq_vals["end_position"].get()) == 0
|
|
assert int(channels_tab_controller.stack_acq_vals["end_focus"].get()) == 0
|
|
stage_config["flip_z"] = False
|
|
|
|
|
|
def test_update_end_position(channels_tab_controller):
|
|
configuration = channels_tab_controller.parent_controller.configuration
|
|
|
|
# Initialize
|
|
z, f = random.randint(0, 1000), random.randint(0, 1000)
|
|
z_shift, f_shift = random.randint(1, 500), random.randint(1, 500)
|
|
configuration["experiment"]["StageParameters"]["z"] = z + z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f + f_shift
|
|
|
|
print(f"z: {z} z-shift: {z_shift} f: {f} f-shift: {f_shift}")
|
|
print(f'z-dict: {configuration["experiment"]["StageParameters"]["z"]}')
|
|
print(f'f-dict: {configuration["experiment"]["StageParameters"]["f"]}')
|
|
|
|
# Step backwards and record results
|
|
channels_tab_controller.z_origin = z - z_shift
|
|
channels_tab_controller.focus_origin = f - f_shift
|
|
channels_tab_controller.update_end_position()
|
|
z_origin_minus = copy.deepcopy(channels_tab_controller.z_origin)
|
|
f_origin_minus = copy.deepcopy(channels_tab_controller.focus_origin)
|
|
start_position_minus = copy.deepcopy(
|
|
channels_tab_controller.stack_acq_vals["start_position"].get()
|
|
)
|
|
end_position_minus = copy.deepcopy(
|
|
channels_tab_controller.stack_acq_vals["end_position"].get()
|
|
)
|
|
start_focus_minus = copy.deepcopy(
|
|
channels_tab_controller.stack_acq_vals["start_focus"].get()
|
|
)
|
|
end_focus_minus = copy.deepcopy(
|
|
channels_tab_controller.stack_acq_vals["end_focus"].get()
|
|
)
|
|
|
|
print("back")
|
|
print(f"z: {z} z-shift: {z_shift} f: {f} f-shift: {f_shift}")
|
|
print(f'z-dict: {configuration["experiment"]["StageParameters"]["z"]}')
|
|
print(f'f-dict: {configuration["experiment"]["StageParameters"]["f"]}')
|
|
|
|
# Step forward
|
|
configuration["experiment"]["StageParameters"]["z"] = z - z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f - f_shift
|
|
channels_tab_controller.z_origin = z + z_shift
|
|
channels_tab_controller.focus_origin = f + f_shift
|
|
channels_tab_controller.update_end_position()
|
|
|
|
print("forward")
|
|
print(f"z: {z} z-shift: {z_shift} f: {f} f-shift: {f_shift}")
|
|
print(f'z-dict: {configuration["experiment"]["StageParameters"]["z"]}')
|
|
print(f'f-dict: {configuration["experiment"]["StageParameters"]["f"]}')
|
|
|
|
# Ensure we achieve the same origin
|
|
assert channels_tab_controller.z_origin == z_origin_minus
|
|
assert channels_tab_controller.focus_origin == f_origin_minus
|
|
assert (
|
|
channels_tab_controller.stack_acq_vals["start_position"].get()
|
|
== start_position_minus
|
|
)
|
|
assert (
|
|
channels_tab_controller.stack_acq_vals["end_position"].get()
|
|
== end_position_minus
|
|
)
|
|
assert (
|
|
channels_tab_controller.stack_acq_vals["start_focus"].get() == start_focus_minus
|
|
)
|
|
assert channels_tab_controller.stack_acq_vals["end_focus"].get() == end_focus_minus
|
|
|
|
# test flip_z is True
|
|
microscope_name = (
|
|
channels_tab_controller.parent_controller.configuration_controller.microscope_name
|
|
)
|
|
stage_config = channels_tab_controller.parent_controller.configuration[
|
|
"configuration"
|
|
]["microscopes"][microscope_name]["stage"]
|
|
stage_config["flip_z"] = True
|
|
# forward
|
|
channels_tab_controller.z_origin = z
|
|
channels_tab_controller.focus_origin = f
|
|
configuration["experiment"]["StageParameters"]["z"] = z - 2 * z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f - 2 * f_shift
|
|
channels_tab_controller.update_end_position()
|
|
assert channels_tab_controller.z_origin == z - z_shift
|
|
assert channels_tab_controller.focus_origin == f - f_shift
|
|
assert channels_tab_controller.stack_acq_vals["start_position"].get() == z_shift
|
|
assert channels_tab_controller.stack_acq_vals["end_position"].get() == -1 * z_shift
|
|
assert channels_tab_controller.stack_acq_vals["start_focus"].get() == f_shift
|
|
assert channels_tab_controller.stack_acq_vals["end_focus"].get() == -1 * f_shift
|
|
|
|
# backward
|
|
channels_tab_controller.z_origin = z
|
|
channels_tab_controller.focus_origin = f
|
|
configuration["experiment"]["StageParameters"]["z"] = z + 2 * z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f + 2 * f_shift
|
|
channels_tab_controller.update_end_position()
|
|
assert channels_tab_controller.z_origin == z + z_shift
|
|
assert channels_tab_controller.focus_origin == f + f_shift
|
|
assert channels_tab_controller.stack_acq_vals["start_position"].get() == z_shift
|
|
assert channels_tab_controller.stack_acq_vals["end_position"].get() == -1 * z_shift
|
|
assert channels_tab_controller.stack_acq_vals["start_focus"].get() == f_shift
|
|
assert channels_tab_controller.stack_acq_vals["end_focus"].get() == -1 * f_shift
|
|
stage_config["flip_z"] = False
|
|
|
|
|
|
def test_update_start_update_end_position(channels_tab_controller):
|
|
configuration = channels_tab_controller.parent_controller.configuration
|
|
channels_tab_controller.microscope_state_dict = configuration["experiment"][
|
|
"MicroscopeState"
|
|
]
|
|
channels_tab_controller.in_initialization = False
|
|
|
|
# Initialize
|
|
z, f = random.randint(0, 1000), random.randint(0, 1000)
|
|
z_shift, f_shift = random.randint(1, 500), random.randint(1, 500)
|
|
configuration["experiment"]["StageParameters"]["z"] = z - z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f - f_shift
|
|
channels_tab_controller.update_start_position()
|
|
|
|
print(f"z: {z} z-shift: {z_shift} f: {f} f-shift: {f_shift}")
|
|
print(f'z-dict: {configuration["experiment"]["StageParameters"]["z"]}')
|
|
print(f'f-dict: {configuration["experiment"]["StageParameters"]["f"]}')
|
|
|
|
# Step forward and record results
|
|
configuration["experiment"]["StageParameters"]["z"] = z + z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f + f_shift
|
|
channels_tab_controller.update_end_position()
|
|
z_origin_minus = copy.deepcopy(channels_tab_controller.z_origin)
|
|
f_origin_minus = copy.deepcopy(channels_tab_controller.focus_origin)
|
|
start_position_minus = copy.deepcopy(
|
|
channels_tab_controller.stack_acq_vals["start_position"].get()
|
|
)
|
|
end_position_minus = copy.deepcopy(
|
|
channels_tab_controller.stack_acq_vals["end_position"].get()
|
|
)
|
|
start_focus_minus = copy.deepcopy(
|
|
channels_tab_controller.stack_acq_vals["start_focus"].get()
|
|
)
|
|
end_focus_minus = copy.deepcopy(
|
|
channels_tab_controller.stack_acq_vals["end_focus"].get()
|
|
)
|
|
|
|
print("back")
|
|
print(f"z: {z} z-shift: {z_shift} f: {f} f-shift: {f_shift}")
|
|
print(f'z-dict: {configuration["experiment"]["StageParameters"]["z"]}')
|
|
print(f'f-dict: {configuration["experiment"]["StageParameters"]["f"]}')
|
|
|
|
channels_tab_controller.update_start_position()
|
|
|
|
# Step back
|
|
configuration["experiment"]["StageParameters"]["z"] = z - z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f - f_shift
|
|
channels_tab_controller.update_end_position()
|
|
|
|
print("forward")
|
|
print(f"z: {z} z-shift: {z_shift} f: {f} f-shift: {f_shift}")
|
|
print(f'z-dict: {configuration["experiment"]["StageParameters"]["z"]}')
|
|
print(f'f-dict: {configuration["experiment"]["StageParameters"]["f"]}')
|
|
|
|
# Ensure we achieve the same origin
|
|
assert channels_tab_controller.z_origin == z_origin_minus
|
|
assert channels_tab_controller.focus_origin == f_origin_minus
|
|
assert (
|
|
channels_tab_controller.stack_acq_vals["start_position"].get()
|
|
== start_position_minus
|
|
)
|
|
assert (
|
|
channels_tab_controller.stack_acq_vals["end_position"].get()
|
|
== end_position_minus
|
|
)
|
|
assert (
|
|
channels_tab_controller.stack_acq_vals["start_focus"].get() == start_focus_minus
|
|
)
|
|
assert channels_tab_controller.stack_acq_vals["end_focus"].get() == end_focus_minus
|
|
|
|
# test flip_z is true
|
|
microscope_name = (
|
|
channels_tab_controller.parent_controller.configuration_controller.microscope_name
|
|
)
|
|
stage_config = channels_tab_controller.parent_controller.configuration[
|
|
"configuration"
|
|
]["microscopes"][microscope_name]["stage"]
|
|
stage_config["flip_z"] = True
|
|
configuration = channels_tab_controller.parent_controller.configuration
|
|
z, f = random.randint(0, 1000), random.randint(0, 1000)
|
|
z_shift, f_shift = random.randint(1, 500), random.randint(1, 500)
|
|
configuration["experiment"]["StageParameters"]["z"] = z - z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f - f_shift
|
|
channels_tab_controller.update_start_position()
|
|
configuration["experiment"]["StageParameters"]["z"] = z + z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f + f_shift
|
|
channels_tab_controller.update_end_position()
|
|
|
|
assert channels_tab_controller.z_origin == z
|
|
assert channels_tab_controller.focus_origin == f
|
|
assert channels_tab_controller.stack_acq_vals["start_position"].get() == z_shift
|
|
assert channels_tab_controller.stack_acq_vals["end_position"].get() == -1 * z_shift
|
|
assert channels_tab_controller.stack_acq_vals["start_focus"].get() == f_shift
|
|
assert channels_tab_controller.stack_acq_vals["end_focus"].get() == -1 * f_shift
|
|
|
|
assert configuration["experiment"]["MicroscopeState"]["start_position"] == z_shift
|
|
assert (
|
|
configuration["experiment"]["MicroscopeState"]["end_position"] == -1 * z_shift
|
|
)
|
|
assert configuration["experiment"]["MicroscopeState"]["abs_z_start"] == z - z_shift
|
|
assert configuration["experiment"]["MicroscopeState"]["abs_z_end"] == z + z_shift
|
|
assert configuration["experiment"]["MicroscopeState"]["start_focus"] == f_shift
|
|
assert configuration["experiment"]["MicroscopeState"]["end_focus"] == -1 * f_shift
|
|
|
|
configuration["experiment"]["StageParameters"]["z"] = z + z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f + f_shift
|
|
channels_tab_controller.update_start_position()
|
|
configuration["experiment"]["StageParameters"]["z"] = z - z_shift
|
|
configuration["experiment"]["StageParameters"]["f"] = f - f_shift
|
|
channels_tab_controller.update_end_position()
|
|
|
|
assert channels_tab_controller.z_origin == z
|
|
assert channels_tab_controller.focus_origin == f
|
|
assert channels_tab_controller.stack_acq_vals["start_position"].get() == z_shift
|
|
assert channels_tab_controller.stack_acq_vals["end_position"].get() == -1 * z_shift
|
|
assert channels_tab_controller.stack_acq_vals["start_focus"].get() == f_shift
|
|
assert channels_tab_controller.stack_acq_vals["end_focus"].get() == -1 * f_shift
|
|
|
|
assert configuration["experiment"]["MicroscopeState"]["start_position"] == z_shift
|
|
assert (
|
|
configuration["experiment"]["MicroscopeState"]["end_position"] == -1 * z_shift
|
|
)
|
|
assert configuration["experiment"]["MicroscopeState"]["abs_z_start"] == z - z_shift
|
|
assert configuration["experiment"]["MicroscopeState"]["abs_z_end"] == z + z_shift
|
|
assert configuration["experiment"]["MicroscopeState"]["start_focus"] == f_shift
|
|
assert configuration["experiment"]["MicroscopeState"]["end_focus"] == -1 * f_shift
|
|
stage_config["flip_z"] = False
|
|
|
|
|
|
@pytest.mark.parametrize("is_multiposition", [True, False])
|
|
def test_toggle_multiposition(channels_tab_controller, is_multiposition):
|
|
channels_tab_controller.populate_experiment_values()
|
|
channels_tab_controller.is_multiposition_val.set(is_multiposition)
|
|
with patch.object(channels_tab_controller, "update_timepoint_setting") as uts:
|
|
channels_tab_controller.toggle_multiposition()
|
|
assert channels_tab_controller.is_multiposition == is_multiposition
|
|
assert (
|
|
channels_tab_controller.microscope_state_dict["is_multiposition"]
|
|
== is_multiposition
|
|
)
|
|
uts.assert_called()
|