def test_empty_intensity_table(): x = [1, 2] y = [2, 3] z = [1, 1] r = [1, 1] spot_attributes = pd.MultiIndex.from_arrays([x, y, z, r], names=('x', 'y', 'z', 'r')) empty = IntensityTable.empty_intensity_table(spot_attributes, 2, 2) assert empty.shape == (2, 2, 2) assert np.sum(empty.values) == 0
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[Indices.CH] n_round = data_image.shape[Indices.ROUND] # construct the empty intensity table intensity_table = IntensityTable.empty_intensity_table( spot_attributes=spot_attributes, n_ch=n_ch, n_round=n_round, ) # fill the intensity table indices = product(range(n_ch), range(n_round)) for c, r in indices: image, _ = data_image.get_slice({Indices.CH: c, Indices.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 _measure_spot_intensities( self, stack: ImageStack, spot_attributes: pd.DataFrame) -> IntensityTable: n_ch = stack.shape[Indices.CH] n_hyb = stack.shape[Indices.HYB] spot_attribute_index = dataframe_to_multiindex(spot_attributes) intensity_table = IntensityTable.empty_intensity_table( spot_attribute_index, n_ch, n_hyb) indices = product(range(n_ch), range(n_hyb)) for c, h in indices: image, _ = stack.get_slice({Indices.CH: c, Indices.HYB: h}) blob_intensities: pd.Series = self._measure_blob_intensity( image, spot_attributes, self.measurement_function) intensity_table[:, c, h] = 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