def _find_spots( self, data_stack: ImageStack, verbose: bool = False, n_processes: Optional[int] = None ) -> Dict[Tuple[int, int], np.ndarray]: """Find spots in all (z, y, x) volumes of an ImageStack. Parameters ---------- data_stack : ImageStack Stack containing spots to find. Returns ------- Dict[Tuple[int, int], np.ndarray] Dictionary mapping (round, channel) pairs to a spot table generated by skimage blob_log or blob_dog. """ # find spots in each (r, c) volume transform_results = data_stack.transform( self._spot_finder, group_by=determine_axes_to_group_by(self.is_volume), n_processes=n_processes, ) # create output dictionary spot_results = {} for spot_calls, axes_dict in transform_results: r = axes_dict[Axes.ROUND] c = axes_dict[Axes.CH] spot_results[r, c] = spot_calls return spot_results
def detect_spots(data_stack: ImageStack, spot_finding_method: Callable[..., SpotAttributes], spot_finding_kwargs: Dict = None, reference_image: Union[xr.DataArray, np.ndarray] = None, reference_image_from_max_projection: bool = False, measurement_function: Callable[[Sequence], Number] = np.max, radius_is_gyration: bool = False) -> IntensityTable: """Apply a spot_finding_method to a ImageStack Parameters ---------- data_stack : ImageStack The ImageStack containing spots spot_finding_method : Callable[..., IntensityTable] The method to identify spots spot_finding_kwargs : Dict additional keyword arguments to pass to spot_finding_method reference_image : xr.DataArray (Optional) a reference image. If provided, spots will be found in this image, and then the locations that correspond to these spots will be measured across each channel and round, filling in the values in the IntensityTable reference_image_from_max_projection : Tuple[Indices] (Optional) if True, create a reference image by max-projecting the channels and imaging rounds found in data_image. measurement_function : Callable[[Sequence], Number] the function to apply over the spot area to extract the intensity value (default 'np.max') radius_is_gyration : bool if True, indicates that the radius corresponds to radius of gyration, which is a function of spot intensity, but typically is a smaller unit than the sigma generated by blob_log. In this case, the spot's bounding box is rounded up instead of down when measuring intensity. (default False) is_volume: bool If True, pass 3d volumes (x, y, z) to func, else pass 2d tiles (x, y) to func. (default True) Notes ----- - This class will always detect spots in 3d. If 2d spot detection is desired, the data should be projected down to "fake 3d" prior to submission to this function - If neither reference_image nor reference_from_max_projection are passed, spots will be detected _independently_ in each channel. This assumes a non-multiplex imaging experiment, as only one (ch, round) will be measured for each spot. Returns ------- IntensityTable : IntensityTable containing the intensity of each spot, its radius, and location in pixel coordinates """ if spot_finding_kwargs is None: spot_finding_kwargs = {} if reference_image is not None and reference_image_from_max_projection: raise ValueError( 'Please pass only one of reference_image and reference_image_from_max_projection' ) if reference_image_from_max_projection: reference_image = data_stack.max_proj(Indices.CH, Indices.ROUND) reference_image = reference_image._squeezed_numpy( Indices.CH, Indices.ROUND) group_by = {Indices.ROUND, Indices.CH} if reference_image is not None: reference_spot_locations = spot_finding_method(reference_image, **spot_finding_kwargs) intensity_table = measure_spot_intensities( data_image=data_stack, spot_attributes=reference_spot_locations, measurement_function=measurement_function, radius_is_gyration=radius_is_gyration, ) else: # don't use a reference image, measure each spot_finding_method = partial(spot_finding_method, **spot_finding_kwargs) spot_attributes_list = data_stack.transform(func=spot_finding_method, group_by=group_by) intensity_table = concatenate_spot_attributes_to_intensities( spot_attributes_list) return intensity_table