def syntheticSeqfish(x, y, z, codebook, nSpots, jitter, error): nRound = codebook.shape[1] nChannel = codebook.shape[2] img = np.zeros((nRound, nChannel, z, y, x), dtype=np.float32) intCodes = np.argmax(codebook.data, axis=2) targets = [] for _ in range(nSpots): randx = random.choice(range(5, x - 5)) randy = random.choice(range(5, y - 5)) randz = random.choice(range(2, z - 2)) randCode = random.choice(range(len(codebook))) targets.append((randCode, (randx, randy, randz))) if jitter > 0: randx += random.choice(range(jitter + 1)) * random.choice([1, -1]) randy += random.choice(range(jitter + 1)) * random.choice([1, -1]) if error: skip = random.choice(range(nRound)) else: skip = 100 for r, ch in enumerate(intCodes[randCode]): if r != skip: img[r, ch, randz, randy, randx] = 10 gaussian_filter(img, (0, 0, 0.5, 1.5, 1.5), output=img) return ImageStack.from_numpy(img / img.max()), targets
def decoded_intensity_table_factory() -> Tuple[IntensityTable, np.ndarray]: """ Create an IntensityTable that has gene labels, including null labels. The data doesn't matter, so will use np.zeros """ data = np.zeros((1, 1, 2, 3, 3), dtype=np.float32) labels = np.array( [[[0, 1, 1], [0, 2, 2], [1, 1, 1]], [[0, 1, 1], [1, 1, 1], [0, 1, 2]]], dtype='<U3' ) labels_with_nan = labels.copy() labels_with_nan[labels == '0'] = 'nan' # create an intensity table and add the labels image_stack = ImageStack.from_numpy(data) intensities = IntensityTable.from_image_stack(image_stack) intensities[Features.TARGET] = (Features.AXIS, np.ravel(labels_with_nan)) # label the third column of this data as failing filters passes_filters = np.ones(data.shape, dtype=bool) passes_filters[:, :, :, :, -1] = 0 intensities[Features.PASSES_THRESHOLDS] = (Features.AXIS, np.ravel(passes_filters)) return intensities, labels_with_nan
def make_expected_image_stack(func): """Make the expected image stack result""" if func == 'max': reduced = np.array( [[[[[0.75, 0.1], [0.1, 0.1]]], [[[0.1, 1], [0.1, 0.1]]], [[[0.1, 0.1], [1, 0.1]]], [[[0.1, 0.1], [0.1, 1]]]]], dtype='float32') elif func == 'mean': reduced = np.array( [[[[[0.425, 0.1], [0.1, 0.1]]], [[[0.1, 0.55], [0.1, 0.1]]], [[[0.1, 0.1], [0.55, 0.1]]], [[[0.1, 0.1], [0.1, 0.55]]]]], dtype='float32') elif func == 'sum': reduced = np.array( [[[[[0.85, 0.2], [0.2, 0.2]]], [[[0.2, 1], [0.2, 0.2]]], [[[0.2, 0.2], [1, 0.2]]], [[[0.2, 0.2], [0.2, 1]]]]], dtype='float32') elif func == 'norm': reduced = np.array( [[[[[0.75663730, 0.14142136], [0.14142136, 0.14142136]]], [[[0.14142136, 1.00000000], [0.14142136, 0.14142136]]], [[[0.14142136, 0.14142136], [1.00000000, 0.14142136]]], [[[0.14142136, 0.14142136], [0.14142136, 1.00000000]]]]], dtype=np.float32) else: raise ValueError("Unsupported func") expected_stack = ImageStack.from_numpy(reduced) return expected_stack
def test_garbage_collection(): """Test that recipe execution discards intermediate results that are no longer necessary.""" recipe_str = """ a = compute(Filter.SimpleFilterAlgorithm, file_inputs[0], multiplicand=0.5) b = compute(Filter.SimpleFilterAlgorithm, a, multiplicand=0.3) c = compute(Filter.SimpleFilterAlgorithm, b, multiplicand=4.) d = compute(Filter.SimpleFilterAlgorithm, c, multiplicand=0.5) file_outputs[0] = compute(Filter.SimpleFilterAlgorithm, d, multiplicand=0.5) """ with tempfile.TemporaryDirectory() as tempdir: output_path = os.path.join(tempdir, "output.json") recipe = Recipe(recipe_str, [URL], [output_path]) execution = recipe._execution() execution._run_one_tick() execution._run_one_tick() assert len(execution._completed_results) == 1 execution.run_and_save() result_stack = ImageStack.from_path_or_url(output_path) assert np.allclose(BASE_EXPECTED * .15, result_stack.xarray[2, 2, 0, 40:50, 40:50])
def test_spot_finding_reference_image_sequential( data_stack: ImageStack, spot_detector: FindSpotsAlgorithm, max_intensity: float, ): """ This testing method uses a reference image to identify spot locations then builds traces using the sequential strategy. It finds 2 spots in the max projected image, then measures the two spots on each tile totally 2*num_chs*num_rounds spots. When building spot traces it treats each spot as it's own trace totally 8 traces. This workflow doesn't really make sense but we're testing it anyway. """ reference_image = data_stack.reduce((Axes.ROUND, Axes.CH), func="max", module=FunctionSource.np) spots = spot_detector.run(image_stack=data_stack, reference_image=reference_image) intensity_table = trace_builders.build_traces_sequential(spots) expected_num_traces = (2 * data_stack.num_chs * data_stack.num_rounds) assert intensity_table.sizes[Features.AXIS] == expected_num_traces, "wrong number of " \ "spots traces detected" reference_image = EMPTY_IMAGESTACK.reduce((Axes.ROUND, Axes.CH), func="max", module=FunctionSource.np) spots = spot_detector.run(image_stack=EMPTY_IMAGESTACK, reference_image=reference_image) empty_intensity_table = trace_builders.build_traces_sequential(spots) assert empty_intensity_table.sizes[Features.AXIS] == 0
def test_spot_detection_with_reference_image_exact_match( data_stack: ImageStack, spot_detector: FindSpotsAlgorithm, max_intensity: float, ): """This testing method uses a reference image to identify spot locations then builds traces using the exact_match strategy. This represents a workflow common in a multiplexed assays. Each method should detect 2 total spots in the max projected reference image then group them into 2 distinct spot traces across the ImageStack. """ reference_image = data_stack.reduce((Axes.ROUND, Axes.CH), func=FunctionSource.np("max")) spots = spot_detector.run(image_stack=data_stack, reference_image=reference_image) intensity_table = trace_builders.build_spot_traces_exact_match(spots) assert intensity_table.sizes[ Features.AXIS] == 2, "wrong number of spots traces detected" expected = [max_intensity * 2, max_intensity * 2] assert np.allclose(intensity_table.sum((Axes.ROUND, Axes.CH)).values, expected), \ "wrong spot intensities detected" # verify this execution strategy produces an empty intensitytable when called with a blank image reference_image = EMPTY_IMAGESTACK.reduce((Axes.ROUND, Axes.CH), func=FunctionSource.np("max")) spots = spot_detector.run(image_stack=EMPTY_IMAGESTACK, reference_image=reference_image) empty_intensity_table = trace_builders.build_spot_traces_exact_match(spots) assert empty_intensity_table.sizes[Features.AXIS] == 0
def setup_linear_unmixing_test(): """ Create the image stack, coeff matrix, and reference result for the linear unmixing test """ # Create image r, c, z, y, x = 1, 3, 6, 5, 4 im = np.ones((r, c, z, y, x), dtype=np.float32) # Create a single pixel with zero intensity im[0, 0, 0, 0, 0] = 0 stack = ImageStack.from_numpy(im) # Create coefficients matrix coeff_mat = np.array([ [1.00, -0.25, 0.00], # noqa [-0.25, 1.00, -0.25], # noqa [-0.10, 0.00, 1.00] ] # noqa ) # Create reference result ref_result = im.copy() ref_result[:, 0, ...] = 0.65 * np.ones((z, y, x)) ref_result[:, 1, ...] = 0.75 * np.ones((z, y, x)) ref_result[:, 2, ...] = 0.75 * np.ones((z, y, x)) # Account for the zero-value pixel ref_result[0, 0, 0, 0, 0] = 0 ref_result[0, 1, 0, 0, 0] = 1 return stack, coeff_mat, ref_result
def labeled_intensities_factory( ) -> Tuple[IntensityTable, np.ndarray, np.ndarray]: """ Create a decoded IntensityTable with distance scores, and a corresponding label_image and decoded_image. """ data = np.array( [ [ [[0., 0.], [.1, .1]], # ch 1 [[.5, .5], [.2, .3]] ], [ [[.1, .1], [0, 0]], # ch 2, x & y are reversed [[.2, .3], [.5, .5]] ] ], dtype=np.float32) image_stack = ImageStack.from_numpy(data.reshape(1, 2, 2, 2, 2)) intensity_table = IntensityTable.from_image_stack(image_stack) intensity_table[Features.DISTANCE] = (Features.AXIS, np.zeros(intensity_table.shape[0])) label_image = np.array([[[1, 2], [3, 4]], [[1, 2], [3, 4]]]) decoded_image = np.array([[[5, 4], [3, 2]], [[5, 4], [3, 2]]]) # verify that the listed label image is what would be created by the function we use in the # code assert np.array_equal(label(decoded_image), label_image) return intensity_table, label_image, decoded_image
def get_image_stack(db_credentials: str, image_id: str, channels, pos: int = 0, time: int = 0): """ Downloads an image stack from the imaging database and returns it as a starfish ImageStack. Parameters ---------- db_credentials : str Path to the database credentials file image_ids : List[str] A list of the image ids in the order of the channels : Optional[] A list of the channels to be downloaded in the index order. pos : int Index of the position to download. The default value is 0. time : int Index of the time point to download. The default value is 0. returns ---------- im_stack : ImageStack image stack """ im_stack = get_numpy_stack(db_credentials, image_id, channels, pos, time) # Suppress the loss of precision warning with warnings.catch_warnings(): warnings.simplefilter("ignore") stack = ImageStack.from_numpy(im_stack) return stack
def create_imagestack_with_magnitude_scale(): """create an imagestack with increasing magnitudes""" data = np.linspace(0, 1, 11, dtype=np.float32) data = np.repeat(data[None, :], 2, axis=0) # reshape data into a 2-channel, (1, 11, 1) image in (x, y, z) data = data.reshape(1, 2, 1, 11, 1) imagestack = ImageStack.from_numpy_array(data) return imagestack
def test_imagestack_xarray_deepcopy(nitems: int=10) -> None: """ Instantiate an :py:class:`ImageStack` and deepcopy the xarray directly. This should work, but prompt a warning. """ shape = (nitems, 3, 4, 5, 6) dtype = np.float32 source = np.zeros(shape, dtype=dtype) imagestack = ImageStack.from_numpy(source) with warnings.catch_warnings(record=True) as warnings_: copy.deepcopy(imagestack.xarray) assert len(warnings_) == 1 # type: ignore
def test_binarize_non_3d(num_rounds, num_chs, num_zplanes=4, ysize=5, xsize=6): data = np.linspace(0, 1, num_rounds * num_chs * num_zplanes * ysize * xsize, dtype=np.float32) data = data.reshape((num_rounds, num_chs, num_zplanes, ysize, xsize)) imagestack = ImageStack.from_numpy(data) binarizer = ThresholdBinarize(0.0) with pytest.raises(ValueError): binarizer.run(imagestack)
def jitter_code() -> ImageStack: """this code has some minor jitter <= 3px at the most distant point""" img = np.zeros((3, 2, 20, 50, 50), dtype=np.float32) # code 1 img[0, 0, 5, 35, 35] = 10 img[1, 1, 5, 34, 35] = 10 img[2, 0, 6, 35, 33] = 10 # blur points gaussian_filter(img, (0, 0, 0.5, 1.5, 1.5), output=img) return ImageStack.from_numpy(img)
def traversing_code() -> ImageStack: """this code walks in a sequential direction, and should only be detectable from some anchors""" img = np.zeros((3, 2, 20, 50, 50), dtype=np.float32) # code 1 img[0, 0, 5, 35, 35] = 10 img[1, 1, 5, 32, 32] = 10 img[2, 0, 5, 29, 29] = 10 # blur points gaussian_filter(img, (0, 0, 0.5, 1.5, 1.5), output=img) return ImageStack.from_numpy(img)
def make_expected_image_stack(): ''' Make the expected image stack result ''' base_calls = np.array( [[[[[0, 0], [0, 0]]], [[[0, 0.755929], [0, 0]]], [[[0, 0], [0.755929, 0]]], [[[0, 0], [0, 0.755929]]]]], dtype='float32') expected_stack = ImageStack.from_numpy(base_calls) return expected_stack
def test_intensity_table_concatenation(): """create two IntensityTables and assert that they are being concatenated properly.""" r, c, z, y, x = 3, 3, 2, 2, 5 data = np.zeros(180, dtype=np.float32).reshape(r, c, z, y, x) image_stack = ImageStack.from_numpy_array(data) intensities = IntensityTable.from_image_stack(image_stack) intensities2 = intensities.copy() original_shape = intensities.shape expected_shape = list(original_shape) expected_shape[0] *= 2 # only features is concatenated assert np.array_equal( concatenate([intensities, intensities2]).shape, expected_shape) # slice out a single channel and round from both experiments, such that the data no longer match # across all dimensions but the concatenation dimension. The resulting structure should be # 2 (r) * 2 (c) * 5 (z), 2, 2 = 40, 2, 2 i1 = intensities.where(np.logical_and(intensities.r == 0, intensities.c == 0), drop=True) i2 = intensities.where(np.logical_and(intensities.r == 1, intensities.c == 1), drop=True) expected_shape = (i1.shape[0] + i2.shape[0], 2, 2) result = concatenate([i1, i2]) assert expected_shape == result.shape # slice a larger r value for second array, however, there are still only two values, so # shape should be 40, 2, 2 i3 = intensities.where(np.logical_and(intensities.r == 2, intensities.c == 1), drop=True) expected_shape = (i1.shape[0] + i3.shape[0], 2, 2) result = concatenate([i1, i3]) assert expected_shape == result.shape # slice out z in addition to reduce the total feature number by 1/2 i4 = intensities.where(np.logical_and(intensities.r == 0, intensities.z == 1), drop=True) expected_shape = (i1.shape[0] + i4.shape[0], 3, 1) result = concatenate([i1, i4]) assert expected_shape == result.shape
def test_spot_detection_with_reference_image( data_stack: ImageStack, spot_detector: FindSpotsAlgorithm, ): """This testing method uses a reference image to identify spot locations. Each method should find 2 spots in the reference image then measure the intensity of those locations in each r/ch pair. The final spot results should represent 2 spots for each r/ch totalling 2*num_rounds*num_ch spots """ reference_image = data_stack.reduce((Axes.ROUND, Axes.CH), func=FunctionSource.np("max")) spots_results = spot_detector.run(image_stack=data_stack, reference_image=reference_image) assert spots_results.count_total_spots() == (2 * data_stack.num_chs * data_stack.num_rounds), \ "wrong number of spots detected"
def test_from_fiji_roi_set(): # set up empty dapi imagestack of correct size fake_dapi = ImageStack.from_numpy(array=np.zeros(shape=(1, 1, 1, 2048, 2048))) cwd = os.path.dirname(__file__) file_path = os.path.join(cwd, "RoiSet.zip") # load test roi_set.zip masks = BinaryMaskCollection.from_fiji_roi_set(file_path, fake_dapi) # check data and offsets set correctly assert len(masks) == 4 assert masks._masks[0].offsets == (782, 760) assert masks._masks[1].offsets == (234, 680) assert masks._masks[2].offsets == (10, 980) assert masks._masks[3].offsets == (16, 768)
def test_lmpf_uniform_peak(): data_array = np.zeros(shape=(1, 1, 1, 100, 100), dtype=np.float32) data_array[0, 0, 0, 45:55, 45:55] = 1 imagestack = ImageStack.from_numpy(data_array) # standard local max peak finder, should find spots for all the evenly illuminated pixels. lmpf_no_kwarg = FindSpots.LocalMaxPeakFinder(1, 1, 1, sys.maxsize) peaks = lmpf_no_kwarg.run(imagestack) results_no_kwarg = peaks[{Axes.ROUND: 0, Axes.CH: 0}] assert len(results_no_kwarg.spot_attrs.data) == 100 # local max peak finder, capped at one peak per label. lmpf_kwarg = FindSpots.LocalMaxPeakFinder(1, 1, 1, sys.maxsize, num_peaks_per_label=1) peaks = lmpf_kwarg.run(imagestack) results_kwarg = peaks[{Axes.ROUND: 0, Axes.CH: 0}] assert len(results_kwarg.spot_attrs.data) == 1
def test_simple_recipe(): """Test that a simple recipe can execute correctly.""" recipe_str = """ file_outputs[0] = compute(Filter.SimpleFilterAlgorithm, file_inputs[0], multiplicand=0.5) """ with tempfile.TemporaryDirectory() as tempdir: output_path = os.path.join(tempdir, "output.json") recipe = Recipe(recipe_str, [URL], [output_path]) execution = recipe._execution() execution.run_and_save() result_stack = ImageStack.from_path_or_url(output_path) assert np.allclose(BASE_EXPECTED * .5, result_stack.xarray[2, 2, 0, 40:50, 40:50])
def make_image_stack(): """Make a test ImageStack.""" # Make the test image test = np.ones((2, 4, 1, 2, 2), dtype='float32') * 0.1 x = [0, 0, 1, 1] y = [0, 1, 0, 1] for i in range(4): test[0, i, 0, x[i], y[i]] = 1 test[0, 0, 0, 0, 0] = 0.75 # Make the ImageStack test_stack = ImageStack.from_numpy(test) return test_stack
def imagestack_with_coords_factory(stack_shape: OrderedDict, coords: OrderedDict) -> ImageStack: """ Create an ImageStack of given shape and assigns the given x,y,z min/max physical coordinates to each tile. Parameters ---------- stack_shape: OrderedDict Dict[Axes, int] defining the size of each dimension for an ImageStack coords: OrderedDict Dict[PhysicalCoordinateTypes, float] defining the min/max values of physical coordinates to assign to the Imagestack """ stack = ImageStack.synthetic_stack(num_round=stack_shape[Axes.ROUND], num_ch=stack_shape[Axes.CH], num_z=stack_shape[Axes.ZPLANE], tile_height=stack_shape[Axes.Y], tile_width=stack_shape[Axes.X]) stack.xarray[Coordinates.X.value] = xr.DataArray(np.linspace( coords[PhysicalCoordinateTypes.X_MIN], coords[PhysicalCoordinateTypes.X_MAX], stack.xarray.sizes[Axes.X.value]), dims=Axes.X.value) stack.xarray[Coordinates.Y.value] = xr.DataArray(np.linspace( coords[PhysicalCoordinateTypes.Y_MIN], coords[PhysicalCoordinateTypes.Y_MAX], stack.xarray.sizes[Axes.Y.value]), dims=Axes.Y.value) z_coord = physical_coordinate_calculator.\ get_physical_coordinates_of_z_plane((coords[PhysicalCoordinateTypes.Z_MIN], coords[PhysicalCoordinateTypes.Z_MAX])) stack.xarray[Coordinates.Z.value] = xr.DataArray(np.zeros( stack.xarray.sizes[Axes.ZPLANE.value]), dims=Axes.ZPLANE.value) for z in stack.axis_labels(Axes.ZPLANE): stack.xarray[Coordinates.Z.value].loc[z] = z_coord return stack
def two_perfect_codes() -> ImageStack: """this code has no jitter""" img = np.zeros((3, 2, 20, 50, 50), dtype=np.float32) # code 1 img[0, 0, 5, 20, 35] = 10 img[1, 1, 5, 20, 35] = 10 img[2, 0, 5, 20, 35] = 10 # code 1 img[0, 0, 5, 40, 45] = 10 img[1, 1, 5, 40, 45] = 10 img[2, 0, 5, 40, 45] = 10 # blur points gaussian_filter(img, (0, 0, 0.5, 1.5, 1.5), output=img) return ImageStack.from_numpy(img)
def test_imagestack_deepcopy(nitems: int=10) -> None: """ Instantiate an :py:class:`ImageStack` and deepcopy it. Worker processes reconstitute a numpy array from the buffer and attempts to writes to the numpy array. Writes in the worker process should be visible in the parent process. """ shape = (nitems, 3, 4, 5, 6) dtype = np.float32 source = np.zeros(shape, dtype=np.float32) imagestack = ImageStack.from_numpy(source) imagestack_copy = copy.deepcopy(imagestack) _start_process_to_test_shmem( array_holder=imagestack_copy._data._backing_mp_array, decoder=partial(_decode_imagestack_array_to_numpy_array, shape, dtype), nitems=nitems) for ix in range(nitems): assert (imagestack.xarray[ix] == 0).all() assert np.allclose(imagestack_copy.xarray[ix], ix)
def imagestack_with_coords_factory(stack_shape: OrderedDict, coords: OrderedDict) -> ImageStack: """ Create an ImageStack of given shape and assigns the given x,y,z min/max physical coordinates to each tile. Parameters ---------- stack_shape: OrderedDict Dict[Axes, int] defining the size of each dimension for an ImageStack coords: OrderedDict Dict[PhysicalCoordinateTypes, float] defining the min/max values of physical coordinates to assign to each tile of the return ImageStack """ stack = ImageStack.synthetic_stack(num_round=stack_shape[Axes.ROUND], num_ch=stack_shape[Axes.CH], num_z=stack_shape[Axes.ZPLANE], tile_height=stack_shape[Axes.Y], tile_width=stack_shape[Axes.X]) coords_array = [ coords[PhysicalCoordinateTypes.X_MIN], coords[PhysicalCoordinateTypes.X_MAX], coords[PhysicalCoordinateTypes.Y_MIN], coords[PhysicalCoordinateTypes.Y_MAX], coords[PhysicalCoordinateTypes.Z_MIN], coords[PhysicalCoordinateTypes.Z_MAX] ] for _round in stack.axis_labels(Axes.ROUND): for ch in stack.axis_labels(Axes.CH): for z in stack.axis_labels(Axes.ZPLANE): coordinate_selector = { Axes.ROUND.value: _round, Axes.CH.value: ch, Axes.ZPLANE.value: z, } stack._coordinates.loc[coordinate_selector] = np.array( coords_array) return stack
def test_intensity_table_serialization(): """ Test that an IntensityTable can be saved to disk, and that when it is reloaded, the data is unchanged """ # create an IntensityTable data = np.zeros(100, dtype=np.float32).reshape(1, 5, 2, 2, 5) image_stack = ImageStack.from_numpy_array(data) intensities = IntensityTable.from_image_stack(image_stack) # dump it to disk tempdir = tempfile.mkdtemp() filename = os.path.join(tempdir, 'test.nc') intensities.save(filename) # verify the data has not changed loaded = intensities.load(filename) assert intensities.equals(loaded)
def setup_linear_unmixing_test(): """ Create the image stack, coeff matrix, and reference result for the linear unmixing test """ # Create image r, c, z, y, x = 2, 3, 6, 5, 4 im = np.ones((r, c, z, y, x), dtype=np.float32) stack = ImageStack.from_numpy_array(im) # Create coefficients matrix coeff_mat = np.array([[1, 0, 0], [-0.25, 1, -0.25], [0, 0, 1]]) # Create reference result ref_result = np.ones((r, c, z, y, x)) ref_result[:, 1, ...] = 0.5 * np.ones((z, y, x)) return stack, coeff_mat, ref_result
def make_expected_image_stack(func): ''' Make the expected image stack result ''' if func == 'max': reduced = np.array( [[[[[0.75, 0.1], [0.1, 0.1]]], [[[0.1, 1], [0.1, 0.1]]], [[[0.1, 0.1], [1, 0.1]]], [[[0.1, 0.1], [0.1, 1]]]]], dtype='float32' ) elif func == 'mean': reduced = np.array( [[[[[0.425, 0.1], [0.1, 0.1]]], [[[0.1, 0.55], [0.1, 0.1]]], [[[0.1, 0.1], [0.55, 0.1]]], [[[0.1, 0.1], [0.1, 0.55]]]]], dtype='float32' ) elif func == 'sum': reduced = np.array( [[[[[0.85, 0.2], [0.2, 0.2]]], [[[0.2, 1], [0.2, 0.2]]], [[[0.2, 0.2], [1, 0.2]]], [[[0.2, 0.2], [0.2, 1]]]]], dtype='float32' ) expected_stack = ImageStack.from_numpy(reduced) return expected_stack
def test_recipe_constructor_extra_args(): """Test that recipe construction detects missing arguments to the constructor.""" recipe_str = """ file_outputs[0] = compute(Filter.SimpleFilterAlgorithm, file_inputs[0], multiplicand=.5, x=1) """ with tempfile.TemporaryDirectory() as tempdir: output_path = os.path.join(tempdir, "output.json") with warnings.catch_warnings(record=True) as w: recipe = Recipe(recipe_str, [URL], [output_path]) assert len(w) == 1 assert issubclass(w[-1].category, ConstructorExtraParameterWarning) execution = recipe._execution() execution.run_and_save() result_stack = ImageStack.from_path_or_url(output_path) assert np.allclose(BASE_EXPECTED * .5, result_stack.xarray[2, 2, 0, 40:50, 40:50])
def multiple_possible_neighbors() -> ImageStack: """this image is intended to be tested with anchor_round in {0, 1}, last round has more spots""" img = np.zeros((3, 2, 20, 50, 50), dtype=np.float32) # round 1 img[0, 0, 5, 20, 40] = 10 img[0, 0, 5, 40, 20] = 10 # round 2 img[1, 1, 5, 20, 40] = 10 img[1, 1, 5, 40, 20] = 10 # round 3 img[2, 0, 5, 20, 40] = 10 img[2, 0, 5, 35, 35] = 10 img[2, 0, 5, 40, 20] = 10 # blur points gaussian_filter(img, (0, 0, 0.5, 1.5, 1.5), output=img) return ImageStack.from_numpy(img)