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 n_ch = data_image.shape[Axes.CH] n_round = data_image.shape[Axes.ROUND] # construct the empty intensity table intensity_table = IntensityTable.empty_intensity_table( spot_attributes=spot_attributes, n_ch=n_ch, n_round=n_round, ) # 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(range(n_ch), range(n_round)) 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[:, c, r] = blob_intensities return intensity_table
def concatenate_spot_attributes_to_intensities( spot_attributes: Sequence[Tuple[SpotAttributes, Dict[Indices, int]]] ) -> IntensityTable: """ Merge multiple spot attributes frames into a single IntensityTable without merging across channels and imaging rounds Parameters ---------- spot_attributes : Sequence[Tuple[SpotAttributes, Dict[Indices, int]]] A sequence of SpotAttribute objects and the Indices (channel, round) that each object is associated with. Returns ------- IntensityTable : concatenated input SpotAttributes, converted to an IntensityTable object """ n_ch: int = max(inds[Indices.CH] for _, inds in spot_attributes) + 1 n_round: int = max(inds[Indices.ROUND] for _, inds in spot_attributes) + 1 all_spots = pd.concat([sa.data for sa, inds in spot_attributes]) # this drop call ensures only x, y, z, radius, and quality, are passed to the IntensityTable features_coordinates = all_spots.drop(['spot_id', 'intensity'], axis=1) intensity_table = IntensityTable.empty_intensity_table( SpotAttributes(features_coordinates), n_ch, n_round, ) i = 0 for attrs, inds in spot_attributes: for _, row in attrs.data.iterrows(): intensity_table[i, inds[Indices.CH], inds[Indices.ROUND]] = row['intensity'] i += 1 return intensity_table