def test_cursor_ray_3d_transposed(): """Test that the cursor works when the displayed viewer axes have been transposed """ # make a mock mouse event mouse_event_1 = MouseEvent( pos=[25, 25], position=[10, 27, 10, 1], dims_point=[0, 0, 0, 1], dims_displayed=[0, 2, 1], view_direction=[1, 0, 0, 0], ) data = np.zeros((20, 20, 20, 5), dtype=int) data[0:10, 0:10, 0:10, 1] = 1 labels = Labels(data, scale=(1, 2, 1, 1), translate=(5, 5, 5, 0)) # set the slice to one with data and the view to 3D labels._slice_dims([0, 0, 0, 1], ndisplay=3) start_point, end_point = labels.get_ray_intersections( mouse_event_1.position, mouse_event_1.view_direction, mouse_event_1.dims_displayed, ) np.testing.assert_allclose(start_point, [0, 11, 5, 1]) np.testing.assert_allclose(end_point, [20, 11, 5, 1])
def test_get_value_ray_2d(): """_get_value_ray currently only returns None in 2D (i.e., it shouldn't be used for 2D). """ # make a mock mouse event mouse_event = MouseEvent( pos=[25, 25], position=[5, 5], dims_point=[1, 10, 0, 0], dims_displayed=[2, 3], view_direction=[1, 0, 0], ) data = np.zeros((5, 20, 20, 20), dtype=int) data[1, 0:10, 0:10, 0:10] = 1 labels = Labels(data, scale=(1, 2, 1, 1), translate=(5, 5, 5)) # set the dims to the slice with labels, but 2D labels._slice_dims([1, 10, 0, 0], ndisplay=2) value = labels._get_value_ray( start_point=np.empty([]), end_point=np.empty([]), dims_displayed=mouse_event.dims_displayed, ) assert value is None
def test_cursor_ray_3d(): # make a mock mouse event mouse_event_1 = MouseEvent( pos=[25, 25], position=[1, 10, 27, 10], dims_point=[1, 0, 0, 0], dims_displayed=[1, 2, 3], view_direction=[0, 1, 0, 0], ) data = np.zeros((5, 20, 20, 20), dtype=int) data[1, 0:10, 0:10, 0:10] = 1 labels = Labels(data, scale=(1, 1, 2, 1), translate=(5, 5, 5)) # set the slice to one with data and the view to 3D labels._slice_dims([1, 0, 0, 0], ndisplay=3) # axis 0 : [0, 20], bounding box extents along view axis, [1, 0, 0] # click is transformed: (value - translation) / scale # axis 1: click at 27 in world coords -> (27 - 5) / 2 = 11 # axis 2: click at 10 in world coords -> (10 - 5) / 1 = 5 start_point, end_point = labels.get_ray_intersections( mouse_event_1.position, mouse_event_1.view_direction, mouse_event_1.dims_displayed, ) np.testing.assert_allclose(start_point, [1, 0, 11, 5]) np.testing.assert_allclose(end_point, [1, 20, 11, 5]) # click in the background mouse_event_2 = MouseEvent( pos=[25, 25], position=[1, 10, 65, 10], dims_point=[1, 0, 0, 0], dims_displayed=[1, 2, 3], view_direction=[0, 1, 0, 0], ) start_point, end_point = labels.get_ray_intersections( mouse_event_2.position, mouse_event_2.view_direction, mouse_event_2.dims_displayed, ) assert start_point is None assert end_point is None # click in a slice with no labels mouse_event_3 = MouseEvent( pos=[25, 25], position=[0, 10, 27, 10], dims_point=[0, 0, 0, 0], dims_displayed=[1, 2, 3], view_direction=[0, 1, 0, 0], ) labels._slice_dims([0, 0, 0, 0], ndisplay=3) start_point, end_point = labels.get_ray_intersections( mouse_event_3.position, mouse_event_3.view_direction, mouse_event_3.dims_displayed, ) np.testing.assert_allclose(start_point, [0, 0, 11, 5]) np.testing.assert_allclose(end_point, [0, 20, 11, 5])
def test_get_value_ray_3d_transposed(): """Test using _get_value_ray to interrogate labels in 3D with the dimensions trasposed. """ # make a mock mouse event mouse_event = MouseEvent( pos=[25, 25], position=[10, 5, 5, 1], dims_point=[0, 0, 0, 1], dims_displayed=[1, 3, 2], view_direction=[1, 0, 0, 0], ) data = np.zeros((5, 20, 20, 20), dtype=int) data[1, 0:10, 0:10, 0:10] = 1 labels = Labels(data, scale=(1, 2, 1, 1), translate=(0, 5, 5, 5)) # set the dims to the slice with labels labels._slice_dims((1, 0, 0, 0), ndisplay=3, order=(0, 1, 3, 2)) labels.set_view_slice() value = labels._get_value_ray( start_point=np.array([1, 0, 5, 5]), end_point=np.array([1, 20, 5, 5]), dims_displayed=mouse_event.dims_displayed, ) assert value == 1
def test_value_3d(position, view_direction, dims_displayed, world): """get_value should return label value in 3D""" data = np.zeros((20, 20, 20), dtype=int) data[0:10, 0:10, 0:10] = 1 layer = Labels(data) layer._slice_dims([0, 0, 0], ndisplay=3) value = layer.get_value( position, view_direction=view_direction, dims_displayed=dims_displayed, world=world, ) assert value == 1
def test_3D_labels(): """Test instantiating Labels layer with random 3D data.""" shape = (6, 10, 15) np.random.seed(0) data = np.random.randint(20, size=shape) layer = Labels(data) assert np.all(layer.data == data) assert layer.ndim == len(shape) np.testing.assert_array_equal(layer.extent.data[1] + 1, shape) assert layer._data_view.shape == shape[-2:] assert layer.editable is True layer._slice_dims(ndisplay=3) assert layer._ndisplay == 3 assert layer.editable is False assert layer.mode == 'pan_zoom'
def test_paint_3d(MouseEvent): """Test filling label nD.""" data = np.zeros((21, 21, 21), dtype=np.int32) data[10, 10, 10] = 1 layer = Labels(data) layer._slice_dims(point=(0, 0, 0), ndisplay=3) layer.n_edit_dimensions = 3 layer.mode = 'paint' layer.selected_label = 4 layer.brush_size = 3 # Simulate click event = ReadOnlyWrapper( MouseEvent( type='mouse_press', is_dragging=False, position=(0.1, 0, 0), view_direction=np.full(3, np.sqrt(3)), dims_displayed=(0, 1, 2), dims_point=(0, 0, 0), ) ) mouse_press_callbacks(layer, event) np.testing.assert_array_equal(np.unique(layer.data), [0, 4]) num_filled = np.bincount(layer.data.ravel())[4] assert num_filled > 1 layer.mode = 'erase' # Simulate click event = ReadOnlyWrapper( MouseEvent( type='mouse_press', is_dragging=False, position=(0, 10, 10), view_direction=(1, 0, 0), dims_displayed=(0, 1, 2), dims_point=(0, 0, 0), ) ) mouse_press_callbacks(layer, event) new_num_filled = np.bincount(layer.data.ravel())[4] assert new_num_filled < num_filled
def test_get_value_ray_3d(): """Test using _get_value_ray to interrogate labels in 3D""" # make a mock mouse event mouse_event = MouseEvent( pos=[25, 25], position=[10, 5, 5], dims_point=[1, 0, 0, 0], dims_displayed=[1, 2, 3], view_direction=[1, 0, 0], ) data = np.zeros((5, 20, 20, 20), dtype=int) data[1, 0:10, 0:10, 0:10] = 1 labels = Labels(data, scale=(1, 2, 1, 1), translate=(5, 5, 5)) # set the dims to the slice with labels labels._slice_dims([1, 0, 0, 0], ndisplay=3) value = labels._get_value_ray( start_point=np.array([1, 0, 5, 5]), end_point=np.array([1, 20, 5, 5]), dims_displayed=mouse_event.dims_displayed, ) assert value == 1 # check with a ray that only goes through background value = labels._get_value_ray( start_point=np.array([1, 0, 15, 15]), end_point=np.array([1, 20, 15, 15]), dims_displayed=mouse_event.dims_displayed, ) assert value is None # set the dims to a slice without labels labels._slice_dims([0, 0, 0, 0], ndisplay=3) value = labels._get_value_ray( start_point=np.array([0, 0, 5, 5]), end_point=np.array([0, 20, 5, 5]), dims_displayed=mouse_event.dims_displayed, ) assert value is None
def test_erase_3d_undo_empty(MouseEvent): """Nothing should be added to undo queue when clicks fall outside data.""" data = np.zeros((20, 20, 20), dtype=np.int32) data[10, :, :] = 1 layer = Labels(data) layer.brush_size = 5 layer.mode = 'erase' layer._slice_dims(point=(0, 0, 0), ndisplay=3) layer.n_edit_dimensions = 3 # Simulate click, outside data event = ReadOnlyWrapper( MouseEvent( type='mouse_press', is_dragging=False, position=(-1, -1, -1), view_direction=(1, 0, 0), dims_displayed=(0, 1, 2), dims_point=(0, 0, 0), ) ) mouse_press_callbacks(layer, event) # Simulate release event = ReadOnlyWrapper( MouseEvent( type='mouse_release', is_dragging=False, position=(-1, -1, -1), view_direction=(1, 0, 0), dims_displayed=(0, 1, 2), dims_point=(0, 0, 0), ) ) mouse_release_callbacks(layer, event) # Undo queue should be empty assert len(layer._undo_history) == 0
def test_erase_3d_undo(MouseEvent): """Test erasing labels in 3D then undoing the erase. Specifically, this test checks that undo is correctly filled even when a click and drag starts outside of the data volume. """ data = np.zeros((20, 20, 20), dtype=np.int32) data[10, :, :] = 1 layer = Labels(data) layer.brush_size = 5 layer.mode = 'erase' layer._slice_dims(point=(0, 0, 0), ndisplay=3) layer.n_edit_dimensions = 3 # Simulate click event = ReadOnlyWrapper( MouseEvent( type='mouse_press', is_dragging=False, position=(-1, -1, -1), view_direction=(1, 0, 0), dims_displayed=(0, 1, 2), dims_point=(0, 0, 0), ) ) mouse_press_callbacks(layer, event) # Simulate drag. Note: we need to include top left and bottom right in the # drag or there are no coordinates to interpolate event = ReadOnlyWrapper( MouseEvent( type='mouse_move', is_dragging=True, position=(-1, 0.1, 0.1), view_direction=(1, 0, 0), dims_displayed=(0, 1, 2), dims_point=(0, 0, 0), ) ) mouse_move_callbacks(layer, event) event = ReadOnlyWrapper( MouseEvent( type='mouse_move', is_dragging=True, position=(-1, 18.9, 18.9), view_direction=(1, 0, 0), dims_displayed=(0, 1, 2), dims_point=(0, 0, 0), ) ) mouse_move_callbacks(layer, event) # Simulate release event = ReadOnlyWrapper( MouseEvent( type='mouse_release', is_dragging=False, position=(-1, 21, 21), view_direction=(1, 0, 0), dims_displayed=(0, 1, 2), dims_point=(0, 0, 0), ) ) mouse_release_callbacks(layer, event) # Erasing goes from (-1, -1, -1) to (-1, 21, 21), should split the labels # into two sections. Undoing should work and reunite the labels to one # square assert ndi.label(layer.data)[1] == 2 layer.undo() assert ndi.label(layer.data)[1] == 1