def test_undo_redo( brush_shape, brush_size, mode, selected_label, preserve_labels, n_dimensional, ): blobs = data.binary_blobs(length=64, volume_fraction=0.3, n_dim=3) layer = Labels(blobs) data_history = [blobs.copy()] with pytest.warns(FutureWarning): layer.brush_shape = brush_shape layer.brush_size = brush_size layer.mode = mode layer.selected_label = selected_label layer.preserve_labels = preserve_labels layer.n_edit_dimensions = 3 if n_dimensional else 2 coord = np.random.random((3, )) * (np.array(blobs.shape) - 1) while layer.data[tuple(coord.astype(int))] == 0 and np.any(layer.data): coord = np.random.random((3, )) * (np.array(blobs.shape) - 1) if layer.mode == 'fill': layer.fill(coord, layer.selected_label) if layer.mode == 'erase': layer.paint(coord, 0) if layer.mode == 'paint': layer.paint(coord, layer.selected_label) data_history.append(np.copy(layer.data)) layer.undo() np.testing.assert_array_equal(layer.data, data_history[0]) layer.redo() np.testing.assert_array_equal(layer.data, data_history[1])
def test_fill_tensorstore(): labels = np.zeros((5, 7, 8, 9), dtype=int) labels[1, 2:4, 4:6, 4:6] = 1 labels[1, 3:5, 5:7, 6:8] = 2 labels[2, 3:5, 5:7, 6:8] = 3 with TemporaryDirectory(suffix='.zarr') as fout: labels_temp = zarr.open( fout, mode='w', shape=labels.shape, dtype=np.uint32, chunks=(1, 1, 8, 9), ) labels_temp[:] = labels labels_ts_spec = { 'driver': 'zarr', 'kvstore': { 'driver': 'file', 'path': fout }, 'path': '', 'metadata': { 'dtype': labels_temp.dtype.str, 'order': labels_temp.order, 'shape': labels.shape, }, } data = ts.open(labels_ts_spec, create=False, open=True).result() layer = Labels(data) layer.n_edit_dimensions = 3 layer.fill((1, 4, 6, 7), 4) modified_labels = np.where(labels == 2, 4, labels) np.testing.assert_array_equal(modified_labels, np.asarray(data))
class Labels2DSuite: """Benchmarks for the Labels layer with 2D data""" params = [2**i for i in range(4, 13)] def setup(self, n): np.random.seed(0) self.data = np.random.randint(20, size=(n, n)) self.layer = Labels(self.data) def time_create_layer(self, n): """Time to create layer.""" Labels(self.data) def time_set_view_slice(self, n): """Time to set view slice.""" self.layer._set_view_slice() def time_refresh(self, n): """Time to refresh view.""" self.layer.refresh() def time_update_thumbnail(self, n): """Time to update thumbnail.""" self.layer._update_thumbnail() def time_get_value(self, n): """Time to get current value.""" self.layer.get_value((0, ) * 2) def time_raw_to_displayed(self, n): """Time to convert raw to displayed.""" self.layer._raw_to_displayed(self.layer._data_raw) def time_paint_square(self, n): """Time to paint square.""" self.layer.brush_shape = 'square' self.layer.paint((0, ) * 2, self.layer.selected_label) def time_paint_circle(self, n): """Time to paint circle.""" self.layer.brush_shape = 'circle' self.layer.paint((0, ) * 2, self.layer.selected_label) def time_fill(self, n): """Time to fill.""" self.layer.fill( (0, ) * 2, 1, self.layer.selected_label, ) def mem_layer(self, n): """Memory used by layer.""" return self.layer def mem_data(self, n): """Memory used by raw data.""" return self.data
class Labels3DSuite: """Benchmarks for the Labels layer with 3D data.""" params = [2**i for i in range(4, 11)] def setup(self, n): np.random.seed(0) self.data = np.random.randint(20, size=(n, n, n)) self.layer = Labels(self.data) def time_create_layer(self, n): """Time to create layer.""" Labels(self.data) def time_set_view_slice(self, n): """Time to set view slice.""" self.layer._set_view_slice() def time_refresh(self, n): """Time to refresh view.""" self.layer.refresh() def time_update_thumbnail(self, n): """Time to update thumbnail.""" self.layer._update_thumbnail() def time_get_value(self, n): """Time to get current value.""" self.layer.get_value() def time_save_history(self, n): """Time to save history.""" self.layer._save_history() def time_raw_to_displayed(self, n): """Time to convert raw to displayed.""" self.layer._raw_to_displayed(self.layer._data_raw) def time_paint(self, n): """Time to paint.""" self.layer.paint(self.layer.coordinates, self.layer.selected_label) def time_fill(self, n): """Time to fill.""" self.layer.fill( self.layer.coordinates, self.layer._value, self.layer.selected_label, ) def mem_layer(self, n): """Memory used by layer.""" return self.layer def mem_data(self, n): """Memory used by raw data.""" return self.data
class Labels3DSuite: """Benchmarks for the Labels layer with 3D data.""" params = [2**i for i in range(4, 11)] def setup(self, n): if "CI" in os.environ and n > 512: raise NotImplementedError("Skip on CI (not enough memory)") np.random.seed(0) self.data = np.random.randint(20, size=(n, n, n)) self.layer = Labels(self.data) def time_create_layer(self, n): """Time to create layer.""" Labels(self.data) def time_set_view_slice(self, n): """Time to set view slice.""" self.layer._set_view_slice() def time_refresh(self, n): """Time to refresh view.""" self.layer.refresh() def time_update_thumbnail(self, n): """Time to update thumbnail.""" self.layer._update_thumbnail() def time_get_value(self, n): """Time to get current value.""" self.layer.get_value((0, ) * 3) def time_raw_to_displayed(self, n): """Time to convert raw to displayed.""" self.layer._raw_to_displayed(self.layer._slice.image.raw) def time_paint_circle(self, n): """Time to paint circle.""" self.layer.paint((0, ) * 3, self.layer.selected_label) def time_fill(self, n): """Time to fill.""" self.layer.fill( (0, ) * 3, 1, self.layer.selected_label, ) def mem_layer(self, n): """Memory used by layer.""" return self.layer def mem_data(self, n): """Memory used by raw data.""" return self.data
def test_fill(): """Test filling labels with different brush sizes.""" np.random.seed(0) data = np.random.randint(20, size=(10, 15)) data[:10, :10] = 2 data[:5, :5] = 1 layer = Labels(data) assert np.unique(layer.data[:5, :5]) == 1 assert np.unique(layer.data[5:10, 5:10]) == 2 layer.fill([0, 0], 1, 3) assert np.unique(layer.data[:5, :5]) == 3 assert np.unique(layer.data[5:10, 5:10]) == 2
def test_fill_with_xarray(): """See https://github.com/napari/napari/issues/2374""" data = xr.DataArray(np.zeros((5, 4, 4), dtype=int)) layer = Labels(data) layer.fill((0, 2, 2), 1) np.testing.assert_array_equal(layer.data[0, :, :], np.ones((4, 4))) np.testing.assert_array_equal(layer.data[1:, :, :], np.zeros((4, 4, 4))) # In the associated issue, using xarray.DataArray caused memory allocation # problems due to different read indexing rules, so check that the data # saved for undo has the expected vectorized shape and values. undo_data = layer._undo_history[0][0][1] np.testing.assert_array_equal(undo_data, np.zeros((16,)))
def test_ndim_fill(): test_array = np.zeros((5, 5, 5, 5), dtype=int) test_array[:, 1:3, 1:3, 1:3] = 1 layer = Labels(test_array) layer.n_edit_dimensions = 3 layer.fill((0, 1, 1, 1), 2) np.testing.assert_equal(layer.data[0, 1:3, 1:3, 1:3], 2) np.testing.assert_equal(layer.data[1, 1:3, 1:3, 1:3], 1) layer.n_edit_dimensions = 4 layer.fill((1, 1, 1, 1), 3) np.testing.assert_equal(layer.data[0, 1:3, 1:3, 1:3], 2) np.testing.assert_equal(layer.data[1:, 1:3, 1:3, 1:3], 3)