Files
navigate/test/controller/sub_controllers/test_channels_tab.py
2025-12-04 16:07:30 +08:00

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()