def get_tile(self, r: int, ch: int, z: int) -> TileData: return SlicedImageTile( self.tiles[TileKey(round=r, ch=ch, zplane=z)], r, ch, z, )
def __init__(self, tileset: TileSet) -> None: self.tiles: MutableMapping[TileKey, Tile] = dict() for tile in tileset.tiles(): key = TileKey( round=tile.indices[Axes.ROUND], ch=tile.indices[Axes.CH], zplane=tile.indices.get(Axes.ZPLANE, 0)) self.tiles[key] = tile self._extras = tileset.extras self._expectations = _TileSetConsistencyDetector()
def __init__(self, tileset: TileSet) -> None: tile_extras: MutableMapping[TileKey, dict] = dict() for tile in tileset.tiles(): round_ = tile.indices[Indices.ROUND] ch = tile.indices[Indices.CH] z = tile.indices.get(Indices.Z, 0) tile_extras[TileKey(round=round_, ch=ch, z=z)] = tile.extras self.tile_extras: Mapping[TileKey, dict] = tile_extras self._extras = tileset.extras
def tile_metadata(self) -> pd.DataFrame: """return a table containing Tile metadata Returns ------- pd.DataFrame : dataframe containing per-tile metadata information for each image. Guaranteed to include information on channel, imaging round, z plane, and barcode index. Also contains any information stored in the extras field for each tile. """ data: collections.defaultdict = collections.defaultdict(list) keys = self._tile_data.keys() index_keys = set( key.value for key in AXES_DATA.keys() ) extras_keys = set( key for tilekey in keys for key in self._tile_data[tilekey].keys()) duplicate_keys = index_keys.intersection(extras_keys) if len(duplicate_keys) > 0: duplicate_keys_str = ", ".join([str(key) for key in duplicate_keys]) raise ValueError( f"keys ({duplicate_keys_str}) was found in both the Tile specification and extras " f"field. Tile specification keys may not be duplicated in the extras field.") for selector in self._iter_axes({Axes.ROUND, Axes.CH, Axes.ZPLANE}): tilekey = TileKey( round=selector[Axes.ROUND], ch=selector[Axes.CH], zplane=selector[Axes.ZPLANE]) extras = self._tile_data[tilekey] for index, index_value in selector.items(): data[index.value].append(index_value) for k in extras_keys: data[k].append(extras.get(k, None)) if 'barcode_index' not in extras: barcode_index = ((((selector[Axes.ZPLANE] * self.num_rounds) + selector[Axes.ROUND]) * self.num_chs) + selector[Axes.CH]) data['barcode_index'].append(barcode_index) return pd.DataFrame(data)
def __init__(self, tileset: TileSet) -> None: self._tile_shape = tileset.default_tile_shape self.tiles: MutableMapping[TileKey, Tile] = dict() for tile in tileset.tiles(): key = TileKey(round=tile.indices[Axes.ROUND], ch=tile.indices[Axes.CH], zplane=tile.indices.get(Axes.ZPLANE, 0)) self.tiles[key] = tile # if we don't have the tile shape, then we peek at the tile and get its shape. if self._tile_shape is None: self._tile_shape = tile.tile_shape self._extras = tileset.extras
def keys(self) -> Collection[TileKey]: """Returns a Collection of the TileKey's for all the tiles.""" keys: MutableSequence[TileKey] = list() axis_names: MutableSequence[Axes] = list() labels: MutableSequence[Sequence[int]] = list() for index_name, index_labels in self.index_labels.items(): axis_names.append(index_name) labels.append(index_labels) for indices in product(*labels): selector: MutableMapping[Axes, int] = dict() for index_name, index_value in zip(axis_names, indices): selector[index_name] = index_value keys.append( TileKey( round=selector[Axes.ROUND], ch=selector[Axes.CH], zplane=selector[Axes.ZPLANE], )) return keys
def export(self, filepath: str, tile_opener=None, tile_format: ImageFormat = ImageFormat.NUMPY) -> None: """write the image tensor to disk in spaceTx format Parameters ---------- filepath : str Path + prefix for the images and primary_images.json written by this function tile_opener : TODO ttung: doc me. tile_format : ImageFormat Format in which each 2D plane should be written. """ tileset = TileSet( dimensions={ Indices.ROUND, Indices.CH, Indices.Z, Indices.Y, Indices.X, }, shape={ Indices.ROUND: self.num_rounds, Indices.CH: self.num_chs, Indices.Z: self.num_zlayers, }, default_tile_shape=self._tile_shape, extras=self._tile_metadata.extras, ) for round_ in range(self.num_rounds): for ch in range(self.num_chs): for zlayer in range(self.num_zlayers): tilekey = TileKey(round=round_, ch=ch, z=zlayer) extras: dict = self._tile_metadata[tilekey] tile_indices = { Indices.ROUND: round_, Indices.CH: ch, Indices.Z: zlayer, } coordinates: MutableMapping[Coordinates, Tuple[Number, Number]] = dict() x_coordinates = self.tile_coordinates( tile_indices, Coordinates.X) y_coordinates = self.tile_coordinates( tile_indices, Coordinates.Y) z_coordinates = self.tile_coordinates( tile_indices, Coordinates.Z) coordinates[Coordinates.X] = x_coordinates coordinates[Coordinates.Y] = y_coordinates if z_coordinates[0] != np.nan and z_coordinates[ 1] != np.nan: coordinates[Coordinates.Z] = z_coordinates tile = Tile( coordinates=coordinates, indices=tile_indices, extras=extras, ) tile.numpy_array, _ = self.get_slice(indices={ Indices.ROUND: round_, Indices.CH: ch, Indices.Z: zlayer }) tileset.add_tile(tile) if tile_opener is None: def tile_opener(tileset_path, tile, ext): tile_basename = os.path.splitext(tileset_path)[0] if Indices.Z in tile.indices: zval = tile.indices[Indices.Z] zstr = "-Z{}".format(zval) else: zstr = "" return open( "{}-H{}-C{}{}.{}".format( tile_basename, tile.indices[Indices.ROUND], tile.indices[Indices.CH], zstr, ext, ), "wb") if not filepath.endswith('.json'): filepath += '.json' Writer.write_to_path(tileset, filepath, pretty=True, tile_opener=tile_opener, tile_format=tile_format)