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

814 lines
31 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.
#
from navigate.controller.sub_controllers.camera_view import CameraViewController
import pytest
import random
from unittest.mock import MagicMock
import numpy as np
class TestCameraViewController:
@pytest.fixture(autouse=True)
def setup_class(self, dummy_controller):
c = dummy_controller
self.v = dummy_controller.view
c.model = MagicMock()
c.model.get_offset_variance_maps = MagicMock(return_value=[None, None])
self.camera_view = CameraViewController(self.v.camera_waveform.camera_tab, c)
self.microscope_state = {
"channels": {
"channel_1": {
"is_selected": True,
"laser": "488nm",
"laser_index": 0,
"camera_exposure_time": 200.0,
"laser_power": 20.0,
"interval_time": 1.0,
"defocus": 100.0,
"filter_wheel_0": "Empty-Alignment",
"filter_position_0": 0,
"filter_wheel_1": "Empty-Alignment",
"filter_position_1": 0,
},
"channel_2": {
"is_selected": True,
"laser": "488nm",
"laser_index": 0,
"camera_exposure_time": 200.0,
"laser_power": 20.0,
"interval_time": 1.0,
"defocus": 100.0,
"filter_wheel_0": "Empty-Alignment",
"filter_position_0": 0,
"filter_wheel_1": "Empty-Alignment",
"filter_position_1": 0,
},
"channel_3": {
"is_selected": True,
"laser": "488nm",
"laser_index": 0,
"camera_exposure_time": 200.0,
"laser_power": 20.0,
"interval_time": 1.0,
"defocus": 100.0,
"filter_wheel_0": "Empty-Alignment",
"filter_position_0": 0,
"filter_wheel_1": "Empty-Alignment",
"filter_position_1": 0,
},
},
"number_z_steps": np.random.randint(10, 100),
"stack_cycling_mode": "per_stack",
"image_mode": "z-stack",
}
def test_init(self):
assert isinstance(self.camera_view, CameraViewController)
def test_update_display_state(self):
pass
def test_get_absolute_position(self, monkeypatch):
def mock_winfo_pointerx():
self.x = int(random.random())
return self.x
def mock_winfo_pointery():
self.y = int(random.random())
return self.y
monkeypatch.setattr(self.v, "winfo_pointerx", mock_winfo_pointerx)
monkeypatch.setattr(self.v, "winfo_pointery", mock_winfo_pointery)
# call the function under test
x, y = self.camera_view.get_absolute_position()
# make assertions about the return value
assert x == self.x
assert y == self.y
def test_popup_menu(self, monkeypatch):
# create a fake event object
self.startx = int(random.random())
self.starty = int(random.random())
event = type("Event", (object,), {"x": self.startx, "y": self.starty})()
self.grab_released = False
self.x = int(random.random())
self.y = int(random.random())
self.absx = int(random.random())
self.absy = int(random.random())
# monkey patch the get_absolute_position method to return specific values
def mock_get_absolute_position():
self.absx = int(random.random())
self.absy = int(random.random())
return self.absx, self.absy
monkeypatch.setattr(
self.camera_view, "get_absolute_position", mock_get_absolute_position
)
def mock_tk_popup(x, y):
self.x = x
self.y = y
def mock_grab_release():
self.grab_released = True
monkeypatch.setattr(self.camera_view.menu, "tk_popup", mock_tk_popup)
monkeypatch.setattr(self.camera_view.menu, "grab_release", mock_grab_release)
# call the function under test
self.camera_view.popup_menu(event)
# make assertions about the state of the view object
assert self.camera_view.move_to_x == self.startx
assert self.camera_view.move_to_y == self.starty
assert self.x == self.absx
assert self.y == self.absy
assert self.grab_released is True
@pytest.mark.parametrize("name", ["minmax", "image"])
@pytest.mark.parametrize("data", [[random.randint(0, 49), random.randint(50, 100)]])
def test_initialize(self, name, data):
self.camera_view.initialize(name, data)
# Checking values
if name == "minmax":
assert self.camera_view.image_palette["Min"].get() == data[0]
assert self.camera_view.image_palette["Max"].get() == data[1]
if name == "image":
assert self.camera_view.image_metrics["Frames"].get() == data[0]
def test_set_mode(self):
# Test default mode
self.camera_view.set_mode()
assert self.camera_view.mode == ""
assert self.camera_view.menu.entrycget("Move Here", "state") == "disabled"
# Test 'live' mode
self.camera_view.set_mode("live")
assert self.camera_view.mode == "live"
assert self.camera_view.menu.entrycget("Move Here", "state") == "normal"
# Test 'stop' mode
self.camera_view.set_mode("stop")
assert self.camera_view.mode == "stop"
assert self.camera_view.menu.entrycget("Move Here", "state") == "normal"
# Test invalid mode
self.camera_view.set_mode("invalid")
assert self.camera_view.mode == "invalid"
assert self.camera_view.menu.entrycget("Move Here", "state") == "disabled"
@pytest.mark.parametrize("mode", ["stop", "live"])
def test_move_stage(self, mode):
# Setup to check formula inside func is correct
microscope_name = self.camera_view.parent_controller.configuration[
"experiment"
]["MicroscopeState"]["microscope_name"]
zoom_value = self.camera_view.parent_controller.configuration["experiment"][
"MicroscopeState"
]["zoom"]
pixel_size = self.camera_view.parent_controller.configuration["configuration"][
"microscopes"
][microscope_name]["zoom"]["pixel_size"][zoom_value]
current_center_x = (
self.camera_view.zoom_rect[0][0] + self.camera_view.zoom_rect[0][1]
) / 2
current_center_y = (
self.camera_view.zoom_rect[1][0] + self.camera_view.zoom_rect[1][1]
) / 2
self.camera_view.move_to_x = int(random.random())
self.camera_view.move_to_y = int(random.random())
# This is the formula to check
offset_x = (
(self.camera_view.move_to_x - current_center_x)
/ self.camera_view.zoom_scale
* self.camera_view.canvas_width_scale
* pixel_size
)
offset_y = (
(self.camera_view.move_to_y - current_center_y)
/ self.camera_view.zoom_scale
* self.camera_view.canvas_width_scale
* pixel_size
)
# Set the mode to check if statements
self.camera_view.mode = mode
# Act
self.camera_view.move_stage()
# Check
assert self.camera_view.parent_controller.pop() == "get_stage_position"
res = self.camera_view.parent_controller.pop()
if mode == "stop":
assert res == "move_stage_and_acquire_image"
else:
assert res == "move_stage_and_update_info"
# Checking that move stage properly changed pos
new_pos = self.camera_view.parent_controller.pop()
self.camera_view.parent_controller.stage_pos["x"] -= offset_x
self.camera_view.parent_controller.stage_pos["y"] += offset_y
assert new_pos == self.camera_view.parent_controller.stage_pos
def test_reset_display(self, monkeypatch):
# Mock process image function
process_image_called = False
def mock_process_image():
nonlocal process_image_called
process_image_called = True
monkeypatch.setattr(self.camera_view, "process_image", mock_process_image)
# Reset and check
self.camera_view.reset_display()
assert np.array_equal(
self.camera_view.zoom_rect,
np.array(
[
[0, self.camera_view.view.canvas_width],
[0, self.camera_view.view.canvas_height],
]
),
)
assert np.array_equal(self.camera_view.zoom_offset, np.array([[0], [0]]))
assert self.camera_view.zoom_value == 1
assert self.camera_view.zoom_scale == 1
assert self.camera_view.zoom_width == self.camera_view.view.canvas_width
assert self.camera_view.zoom_height == self.camera_view.view.canvas_height
assert process_image_called is True
def test_process_image(self):
self.camera_view.image = np.random.randint(0, 256, (600, 800))
self.camera_view.digital_zoom = MagicMock()
# self.camera_view.detect_saturation = MagicMock()
self.camera_view.down_sample_image = MagicMock()
self.camera_view.scale_image_intensity = MagicMock()
self.camera_view.add_crosshair = MagicMock()
self.camera_view.apply_lut = MagicMock()
self.camera_view.populate_image = MagicMock()
self.camera_view.process_image()
self.camera_view.digital_zoom.assert_called()
# self.camera_view.detect_saturation.assert_called()
self.camera_view.down_sample_image.assert_called()
self.camera_view.scale_image_intensity.assert_called()
self.camera_view.add_crosshair.assert_called()
self.camera_view.apply_lut.assert_called()
self.camera_view.populate_image.assert_called()
@pytest.mark.parametrize("num,value", [(4, 0.95), (5, 1.05)])
def test_mouse_wheel(self, num, value):
# Test zoom in and out
event = MagicMock()
event.num = num
event.x = int(random.random())
event.y = int(random.random())
event.delta = 120
self.camera_view.zoom_value = 1
self.camera_view.zoom_scale = 1
self.camera_view.zoom_width = self.camera_view.view.canvas_width
self.camera_view.zoom_height = self.camera_view.view.canvas_height
self.camera_view.reset_display = MagicMock()
self.camera_view.process_image = MagicMock()
self.camera_view.mouse_wheel(event)
assert self.camera_view.zoom_value == value
assert self.camera_view.zoom_scale == value
assert self.camera_view.zoom_width == self.camera_view.view.canvas_width / value
assert (
self.camera_view.zoom_height == self.camera_view.view.canvas_height / value
)
if (
self.camera_view.zoom_width > self.camera_view.view.canvas_width
or self.camera_view.zoom_height > self.camera_view.view.canvas_height
):
assert self.camera_view.reset_display.called is True
self.camera_view.process_image.assert_called()
else:
assert self.camera_view.reset_display.called is False
not self.camera_view.process_image.assert_called()
@pytest.mark.skip("AssertionError: Expected 'mock' to have been called.")
def test_digital_zoom(self):
# Setup
a, b, c, d, e, f = [random.randint(1, 100) for _ in range(6)]
g, h = [random.randint(100, 400) for _ in range(2)]
i, j = [random.randint(500, 1000) for _ in range(2)]
val, scale, widthsc, heightsc = [random.randint(2, 4) for _ in range(4)]
self.camera_view.zoom_rect = np.array([[a, b], [c, d]])
self.camera_view.zoom_offset = np.array([[e], [f]])
self.camera_view.zoom_value = val
self.camera_view.zoom_scale = scale
self.camera_view.zoom_width = g # 300
self.camera_view.zoom_height = h # 400
self.camera_view.view.canvas_width = i # 800
self.camera_view.view.canvas_height = j # 600
self.camera_view.canvas_width_scale = widthsc
self.camera_view.canvas_height_scale = heightsc
self.camera_view.image = np.random.randint(0, 256, (600, 800))
self.camera_view.reset_display = MagicMock()
# Preprocess
new_zoom_rec = self.camera_view.zoom_rect - self.camera_view.zoom_offset
new_zoom_rec *= self.camera_view.zoom_value
new_zoom_rec += self.camera_view.zoom_offset
x_start_index = int(-new_zoom_rec[0][0] / self.camera_view.zoom_scale)
x_end_index = int(x_start_index + self.camera_view.zoom_width)
y_start_index = int(-new_zoom_rec[1][0] / self.camera_view.zoom_scale)
y_end_index = int(y_start_index + self.camera_view.zoom_height)
crosshair_x = (new_zoom_rec[0][0] + new_zoom_rec[0][1]) / 2
crosshair_y = (new_zoom_rec[1][0] + new_zoom_rec[1][1]) / 2
if crosshair_x < 0 or crosshair_x >= self.camera_view.view.canvas_width:
crosshair_x = -1
if crosshair_y < 0 or crosshair_y >= self.camera_view.view.canvas_height:
crosshair_y = -1
new_image = self.camera_view.image[
y_start_index
* self.camera_view.canvas_height_scale : y_end_index
* self.camera_view.canvas_height_scale,
x_start_index
* self.camera_view.canvas_width_scale : x_end_index
* self.camera_view.canvas_width_scale,
]
# Call func
self.camera_view.digital_zoom()
# Check zoom rec
assert np.array_equal(self.camera_view.zoom_rect, new_zoom_rec)
# Check zoom offset
assert np.array_equal(self.camera_view.zoom_offset, np.array([[0], [0]]))
# Check zoom_value
assert self.camera_view.zoom_value == 1
# Check zoom_image
assert np.array_equal(self.camera_view.zoom_image, new_image)
# Check crosshairs
assert self.camera_view.crosshair_x == int(crosshair_x)
assert self.camera_view.crosshair_y == int(crosshair_y)
# Check reset display
self.camera_view.reset_display.assert_called()
@pytest.mark.parametrize("onoff", [True, False])
def test_left_click(self, onoff):
self.camera_view.add_crosshair = MagicMock()
self.camera_view.digital_zoom = MagicMock()
# self.camera_view.detect_saturation = MagicMock()
self.camera_view.down_sample_image = MagicMock()
self.camera_view.transpose_image = MagicMock()
self.camera_view.scale_image_intensity = MagicMock()
self.camera_view.apply_lut = MagicMock()
self.camera_view.populate_image = MagicMock()
event = MagicMock()
self.camera_view.image = np.random.randint(0, 256, (600, 800))
self.camera_view.apply_cross_hair = onoff
self.camera_view.left_click(event)
self.camera_view.add_crosshair.assert_called()
self.camera_view.populate_image.assert_called()
assert self.camera_view.apply_cross_hair == (not onoff)
@pytest.mark.parametrize("frames", [0, 1, 2, 10])
def test_update_max_count(self, frames):
self.camera_view.image_metrics["Frames"].set(frames)
idx = 0
temp = [0] * 40
while idx < 40:
self.camera_view._last_frame_display_max = np.random.randint(0, 500)
temp[idx] = self.camera_view._last_frame_display_max
idx += 1
# Act
self.camera_view.update_max_counts()
assert self.camera_view._max_intensity_history_idx == idx % 32
assert (
self.camera_view.max_intensity_history[
self.camera_view._max_intensity_history_idx - 1
]
== self.camera_view._last_frame_display_max
)
# Assert
if frames == 0:
assert self.camera_view.image_metrics["Frames"].get() == 1
frame_num = 1
else:
frame_num = frames
if frame_num <= idx:
rolling_average = sum(temp[idx - frame_num : idx]) / frame_num
else:
rolling_average = sum(temp[:idx]) / frame_num
assert self.camera_view.image_metrics["Image"].get() == round(
rolling_average, 0
)
def test_down_sample_image(self, monkeypatch):
import cv2
# create a test image
test_image = np.random.rand(100, 100)
self.zoom_image = test_image
# set the widget size
widget = type("MyWidget", (object,), {"widget": self.camera_view.view})
event = type(
"MyEvent",
(object,),
{
"widget": widget,
"width": np.random.randint(5, 1000),
"height": np.random.randint(5, 1000),
},
)
self.camera_view.resize(event)
# monkeypatch cv2.resize
def mocked_resize(src, dsize, interpolation=1):
return np.ones((dsize[0], dsize[1]))
monkeypatch.setattr(cv2, "resize", mocked_resize)
# call the function
down_sampled_image = self.camera_view.down_sample_image(test_image)
# assert that the image has been resized correctly
assert np.shape(down_sampled_image) == (
self.camera_view.view.canvas_width,
self.camera_view.view.canvas_height,
)
# assert that the image has not been modified
assert not np.array_equal(down_sampled_image, test_image)
@pytest.mark.parametrize("auto", [True, False])
def test_scale_image_intensity(self, auto):
# Create a test image
test_image = np.random.rand(100, 100)
# Set autoscale to True
self.camera_view.autoscale = auto
if auto is False:
self.camera_view.max_counts = 1.5
self.camera_view.min_counts = 0.5
# Call the function
scaled_image = self.camera_view.scale_image_intensity(test_image)
# Assert that max_counts and min_counts have been set correctly
if auto is True:
assert self.camera_view._last_frame_display_max == np.max(test_image)
# Assert that the image has been scaled correctly
assert np.min(scaled_image) >= 0
assert np.max(scaled_image) <= 255
def test_populate_image(self, monkeypatch):
from PIL import Image, ImageTk
import cv2
# Create test image
self.camera_view.cross_hair_image = np.random.rand(100, 100)
self.camera_view.ilastik_seg_mask = np.random.rand(100, 100)
# Set display_mask_flag to True
self.camera_view.display_mask_flag = True
# Monkeypatch the Image.fromarray() method of PIL
def mocked_fromarray(arr):
return arr
monkeypatch.setattr(Image, "fromarray", mocked_fromarray)
# Monkeypatch the cv2.resize() function
def mocked_resize(arr, size):
return arr
monkeypatch.setattr(cv2, "resize", mocked_resize)
# Monkeypatch the Image.blend() method of PIL
def mocked_blend(img1, img2, alpha):
return img1 * alpha + img2 * (1 - alpha)
monkeypatch.setattr(Image, "blend", mocked_blend)
def mocked_PhotoImage(img):
mock_photo = MagicMock()
# Set up width and height methods to return appropriate dimensions
mock_photo.width.return_value = 100
mock_photo.height.return_value = 100
return mock_photo
monkeypatch.setattr(ImageTk, "PhotoImage", mocked_PhotoImage)
self.camera_view.canvas.create_image = MagicMock()
self.camera_view.image_cache_flag = True
# Call the function
self.camera_view.populate_image(self.camera_view.cross_hair_image)
# Assert that the tk_image has been created correctly
assert self.camera_view._img_buf is not None
# Set display_mask_flag to True
self.camera_view.display_mask_flag = False
# Call the function
self.camera_view.populate_image(self.camera_view.cross_hair_image)
def test_initialize_non_live_display(self):
# Create test buffer and microscope_state
camera_parameters = {
"img_x_pixels": np.random.randint(1, 200),
"img_y_pixels": np.random.randint(1, 200),
}
# Call the function
self.camera_view.initialize_non_live_display(
self.microscope_state, camera_parameters
)
# Assert that the variables have been set correctly
assert self.camera_view.image_count == 0
assert self.camera_view.slice_index == 0
assert self.camera_view.number_of_channels == len(
self.microscope_state["channels"]
)
assert (
self.camera_view.number_of_slices == self.microscope_state["number_z_steps"]
)
assert (
self.camera_view.total_images_per_volume
== self.camera_view.number_of_channels * self.camera_view.number_of_slices
)
assert self.camera_view.original_image_width == int(
camera_parameters["img_x_pixels"]
)
assert self.camera_view.original_image_height == int(
camera_parameters["img_y_pixels"]
)
assert self.camera_view.canvas_width_scale == float(
self.camera_view.original_image_width / self.camera_view.canvas_width
)
assert self.camera_view.canvas_height_scale == float(
self.camera_view.original_image_height / self.camera_view.canvas_height
)
def test_identify_channel_index_and_slice(self):
# Not currently in use
pass
def test_retrieve_image_slice_from_volume(self):
# Not currently in use
pass
@pytest.mark.parametrize("transpose", [True, False])
def test_display_image(self, transpose):
"""Test the display of an image on the camera view
TODO: The recent refactor makes this test non-functional. It needs to be updated
The newer code does not use the camera_view.image attribute after the
transpose operation, so any transpose/image flipping is not reflected in the
final image. The test should be updated to reflect this.,
"""
self.camera_view.initialize_non_live_display(
self.microscope_state, {"img_x_pixels": 50, "img_y_pixels": 100}
)
self.camera_view.digital_zoom = MagicMock()
# self.camera_view.detect_saturation = MagicMock()
self.camera_view.down_sample_image = MagicMock()
self.camera_view.scale_image_intensity = MagicMock()
self.camera_view.apply_lut = MagicMock()
self.camera_view.populate_image = MagicMock()
images = np.random.rand(10, 100, 50)
self.camera_view.transpose = transpose
count = 0
self.camera_view.image_count = count
self.camera_view.image_metrics = {"Channel": MagicMock()}
self.camera_view.update_max_counts = MagicMock()
self.camera_view.flip_flags = {"x": False, "y": False}
image_id = np.random.randint(0, 10)
self.camera_view.try_to_display_image(images[image_id])
assert (
self.camera_view.spooled_images.size_y,
self.camera_view.spooled_images.size_x,
) == np.shape(images[image_id])
assert self.camera_view.image_count == count + 1
self.camera_view.flip_flags = {"x": True, "y": False}
image_id = np.random.randint(0, 10)
self.camera_view.try_to_display_image(images[image_id])
# assert np.shape(self.camera_view.image) == np.shape(images[image_id])
# if not transpose:
# assert (self.camera_view.image == images[image_id][:, ::-1]).all()
# else:
# assert (self.camera_view.image == images[image_id][:, ::-1].T).all()
assert self.camera_view.image_count == count + 2
self.camera_view.flip_flags = {"x": False, "y": True}
image_id = np.random.randint(0, 10)
self.camera_view.try_to_display_image(images[image_id])
# assert np.shape(self.camera_view.image) == np.shape(images[image_id])
# if not transpose:
# assert (self.camera_view.image == images[image_id][::-1, :]).all()
# else:
# assert (self.camera_view.image == images[image_id][::-1, :].T).all()
assert self.camera_view.image_count == count + 3
self.camera_view.flip_flags = {"x": True, "y": True}
image_id = np.random.randint(0, 10)
self.camera_view.try_to_display_image(images[image_id])
# assert np.shape(self.camera_view.image) == np.shape(images[image_id])
# if not transpose:
# assert (self.camera_view.image == images[image_id][::-1, ::-1]).all()
# else:
# assert (self.camera_view.image == images[image_id][::-1, ::-1].T).all()
assert self.camera_view.image_count == count + 4
def test_add_crosshair(self):
# Arrange
x = self.camera_view.canvas_width
y = self.camera_view.canvas_height
image = np.random.rand(x, y)
self.camera_view.apply_cross_hair = True
# Act
image2 = self.camera_view.add_crosshair(image)
# Assert
assert np.all(image2[:, self.camera_view.zoom_rect[0][1] // 2] == 255)
assert np.all(image2[self.camera_view.zoom_rect[1][1] // 2, :] == 255)
def test_apply_LUT(self):
# Someone else with better numpy understanding will need to do this TODO
pass
def test_update_LUT(self):
# Same as apply LUT TODO
pass
def test_toggle_min_max_button(self):
# Setup for true path
self.camera_view.image_palette["Autoscale"].set(True)
# Act by calling function
self.camera_view.toggle_min_max_buttons()
# Assert things are correct
assert str(self.camera_view.image_palette["Min"].widget["state"]) == "disabled"
assert str(self.camera_view.image_palette["Max"].widget["state"]) == "disabled"
# Setup for false path
self.camera_view.image_palette["Autoscale"].set(False)
# Mock function call to isolate
self.camera_view.update_min_max_counts = MagicMock()
# Act by calling function
self.camera_view.toggle_min_max_buttons()
# Assert things are correct and called
assert str(self.camera_view.image_palette["Min"].widget["state"]) == "normal"
assert str(self.camera_view.image_palette["Max"].widget["state"]) == "normal"
self.camera_view.update_min_max_counts.assert_called()
def test_transpose_image(self):
# Create test data
self.camera_view.image_palette["Flip XY"].set(True)
self.camera_view.transpose = None
# Call the function
self.camera_view.update_transpose_state()
# Assert the output
assert self.camera_view.transpose is True
# Create test data
self.camera_view.image_palette["Flip XY"].set(False)
self.camera_view.transpose = None
# Call the function
self.camera_view.update_transpose_state()
# Assert the output
assert self.camera_view.transpose is False
def test_update_min_max_counts(self):
# Create test data
min = np.random.randint(0, 10)
max = np.random.randint(0, 10)
self.camera_view.image_palette["Min"].set(min)
self.camera_view.image_palette["Max"].set(max)
self.camera_view.min_counts = None
self.camera_view.max_counts = None
# Call the function
self.camera_view.update_min_max_counts()
# Assert the output
assert self.camera_view.min_counts == min
assert self.camera_view.max_counts == max
def test_set_mask_color_table(self):
# This is beyond me currently TODO
pass
def test_display_mask(self, monkeypatch):
import cv2
# Create test data
self.camera_view.ilastik_seg_mask = None
self.camera_view.ilastik_mask_ready_lock.acquire()
mask = np.zeros((5, 5), dtype=np.uint8)
self.camera_view.mask_color_table = np.zeros((256, 1, 3), dtype=np.uint8)
# Define the monkeypatch
def mock_applyColorMap(mask, mask_color_table):
return mask
# Apply the monkeypatch
monkeypatch.setattr(cv2, "applyColorMap", mock_applyColorMap)
# Call the function
self.camera_view.display_mask(mask)
# Assert the output
assert (self.camera_view.ilastik_seg_mask == mask).all()
assert not self.camera_view.ilastik_mask_ready_lock.locked()
def test_update_canvas_size(self):
self.camera_view.view.canvas["width"] = random.randint(1, 2000)
self.camera_view.view.canvas["height"] = random.randint(1, 2000)
self.camera_view.update_canvas_size()
assert self.camera_view.canvas_width > 0
assert self.camera_view.canvas_height > 0