def _merge_spots_by_round( spot_results: SpotFindingResults) -> Dict[int, pd.DataFrame]: """Merge DataFrames containing spots from different channels into one DataFrame per round. Parameters ---------- spot_results : Dict[Tuple[int, int], pd.DataFrame] Output of _find_spots. Dictionary mapping (round, channel) volumes to the spots detected in them. Returns ------- Dict[int, pd.DataFrame] Dictionary mapping round volumes to the spots detected in them. Contains an additional column labeled by Axes.CH which identifies the channel in which a given spot was detected. """ # add channel information to each table and add it to round_data round_data: Mapping[int, List] = defaultdict(list) for (r, c), df in spot_results.items(): df = df.spot_attrs.data df[Axes.CH.value] = np.full(df.shape[0], c) round_data[r].append(df) # create one dataframe per round round_dataframes = { k: pd.concat(v, axis=0).reset_index().drop('index', axis=1) for k, v in round_data.items() } return round_dataframes
def run(self, spots: SpotFindingResults, *args) -> DecodedIntensityTable: """ Decode spots by looking up the associated target value for the round and ch each spot is in. Parameters ---------- spots: SpotFindingResults A Dict of tile indices and their corresponding measured spots Returns ------- DecodedIntensityTable : IntensityTable decoded and appended with Features.TARGET and values. """ lookup_table: Dict[Tuple, str] = {} for target in self.codebook[Features.TARGET]: for ch_label in self.codebook[Axes.CH.value]: for round_label in self.codebook[Axes.ROUND.value]: if self.codebook.loc[target, round_label, ch_label]: lookup_table[(int(round_label), int(ch_label))] = str(target.values) for r_ch_index, results in spots.items(): target = lookup_table[ r_ch_index] if r_ch_index in lookup_table else 'nan' results.spot_attrs.data[Features.TARGET] = target intensities = build_traces_sequential(spots) return DecodedIntensityTable(intensities)
def build_traces_sequential(spot_results: SpotFindingResults, **kwargs) -> IntensityTable: """ Build spot traces without merging across channels and imaging rounds. Used for sequential methods like smFIsh. Parameters ---------- spot_results: SpotFindingResults Spots found across rounds/channels of an ImageStack Returns ------- IntensityTable : concatenated input SpotAttributes, converted to an IntensityTable object """ all_spots = pd.concat([sa.data for sa in spot_results.values()], sort=True) intensity_table = IntensityTable.zeros( spot_attributes=SpotAttributes(all_spots), ch_labels=spot_results.ch_labels, round_labels=spot_results.round_labels, ) i = 0 for (r, c), attrs in spot_results.items(): for _, row in attrs.data.iterrows(): selector = dict(features=i, c=c, r=r) intensity_table.loc[selector] = row[Features.INTENSITY] i += 1 return intensity_table