def run(self, stack: ImageStack, transforms_list: TransformsList, in_place: bool = False, verbose: bool = False, *args, **kwargs) -> Optional[ImageStack]: if not in_place: # create a copy of the ImageStack, call apply on that stack with in_place=True image_stack = deepcopy(stack) self.run(image_stack, transforms_list, in_place=True, **kwargs) return image_stack if verbose and StarfishConfig().verbose: transforms_list.transforms = tqdm(transforms_list.transforms) all_axes = {Axes.ROUND, Axes.CH, Axes.ZPLANE} for selector, _, transformation_object in transforms_list.transforms: other_axes = all_axes - set(selector.keys()) # iterate through remaining axes for axes in stack._iter_axes(other_axes): # combine all axes data to select one tile selector.update(axes) # type: ignore selected_image, _ = stack.get_slice(selector) warped_image = warp(selected_image, transformation_object, **kwargs).astype(np.float32) stack.set_slice(selector, warped_image) return None
def measure_spot_intensities( data_image: ImageStack, spot_attributes: SpotAttributes, measurement_function: Callable[[Sequence], Number], radius_is_gyration: bool = False, ) -> IntensityTable: """given spots found from a reference image, find those spots across a data_image Parameters ---------- data_image : ImageStack ImageStack containing multiple volumes for which spots' intensities must be calculated spot_attributes : pd.Dataframe Locations and radii of spots measurement_function : Callable[[Sequence], Number]) Function to apply over the spot volumes to identify the intensity (e.g. max, mean, ...) 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) Returns ------- IntensityTable : 3d tensor of (spot, channel, round) information for each coded spot """ # determine the shape of the intensity table ch_labels = data_image.axis_labels(Axes.CH) round_labels = data_image.axis_labels(Axes.ROUND) # construct the empty intensity table intensity_table = IntensityTable.zeros( spot_attributes=spot_attributes, ch_labels=ch_labels, round_labels=round_labels, ) # if no spots were detected, return the empty IntensityTable if intensity_table.sizes[Features.AXIS] == 0: return intensity_table # fill the intensity table indices = product(ch_labels, round_labels) for c, r in indices: image, _ = data_image.get_slice({Axes.CH: c, Axes.ROUND: r}) blob_intensities: pd.Series = measure_spot_intensity( image, spot_attributes, measurement_function, radius_is_gyration=radius_is_gyration) intensity_table.loc[dict(c=c, r=r)] = blob_intensities return intensity_table
def measure_intensities_at_spot_locations_across_imagestack( data_image: ImageStack, reference_spots: PerImageSliceSpotResults, measurement_function: Callable[[np.ndarray], Number], radius_is_gyration: bool = False) -> SpotFindingResults: """given spots found from a reference image, find those spots across a data_image Parameters ---------- data_image : ImageStack ImageStack containing multiple volumes for which spots' intensities must be calculated reference_spots : PerImageSliceSpotResults Spots found in a reference image measurement_function : Callable[[np.ndarray], Number]) Function to apply over the spot volumes to identify the intensity (e.g. max, mean, ...) 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) Returns ------- SpotFindingResults : A Dict of tile indices and their corresponding measured SpotAttributes """ ch_labels = data_image.axis_labels(Axes.CH) round_labels = data_image.axis_labels(Axes.ROUND) spot_results = SpotFindingResults( imagestack_coords=data_image.xarray.coords, log=data_image.log) # measure spots in each tile indices = product(ch_labels, round_labels) for c, r in indices: tile_indices = {Axes.ROUND: r, Axes.CH: c} if reference_spots.spot_attrs.data.empty: # if no spots found don't measure spot_results[tile_indices] = reference_spots else: image, _ = data_image.get_slice({Axes.CH: c, Axes.ROUND: r}) blob_intensities: pd.Series = measure_intensities_at_spot_locations_in_image( image, reference_spots.spot_attrs, measurement_function, radius_is_gyration=radius_is_gyration) # copy reference spot positions and attributes tile_spots = SpotAttributes(reference_spots.spot_attrs.data.copy()) # fill in intensities tile_spots.data[Features.INTENSITY] = blob_intensities spot_results[tile_indices] = PerImageSliceSpotResults( spot_attrs=tile_spots, extras=None) return spot_results