def keys(self) -> Collection[TileKey]: """Returns a Collection of the TileKey's for all the tiles.""" axes_sizes = join_axes_labels( self._axes_order, rounds=self._rounds, chs=self._chs, zplanes=self._zplanes) return [ TileKey(round=selector[Axes.ROUND], ch=selector[Axes.CH], zplane=selector[Axes.ZPLANE]) for selector in ordered_iterator(axes_sizes) ]
def build_image( fovs: Sequence[int], rounds: Sequence[int], chs: Sequence[int], zplanes: Sequence[int], image_fetcher: TileFetcher, default_shape: Optional[Mapping[Axes, int]] = None, axes_order: Sequence[Axes] = DEFAULT_DIMENSION_ORDER, ) -> Collection: """ Build and returns an image set with the following characteristics: Parameters ---------- fovs : Sequence[int] Sequence of field of view ids in this image set. rounds : Sequence[int] Sequence of the round numbers in this image set. chs : Sequence[int] Sequence of the ch numbers in this image set. zplanes : Sequence[int] Sequence of the zplane numbers in this image set. image_fetcher : TileFetcher Instance of TileFetcher that provides the data for the tile. default_shape : Optional[Tuple[int, int]] Default shape of the individual tiles in this image set. axes_order : Sequence[Axes] Ordering for which axes vary, in order of the slowest changing axis to the fastest. For instance, if the order is (ROUND, Z, CH) and each dimension has size 2, then the sequence is: (ROUND=0, CH=0, Z=0) (ROUND=0, CH=1, Z=0) (ROUND=0, CH=0, Z=1) (ROUND=0, CH=1, Z=1) (ROUND=1, CH=0, Z=0) (ROUND=1, CH=1, Z=0) (ROUND=1, CH=0, Z=1) (ROUND=1, CH=1, Z=1) (default = (Axes.Z, Axes.ROUND, Axes.CH)) Returns ------- The slicedimage collection representing the image. """ axes_sizes = join_axes_labels(axes_order, rounds=rounds, chs=chs, zplanes=zplanes) tile_identifiers = [ TileIdentifier(fov_id, selector[Axes.ROUND], selector[Axes.CH], selector[Axes.ZPLANE]) for fov_id in fovs for selector in ordered_iterator(axes_sizes) ] return build_irregular_image(tile_identifiers, image_fetcher, default_shape)
def test_round_then_ch(): results = list( ordered_iterator(((Axes.ROUND, range(3)), (Axes.CH, range(2))))) for ix in (0, 1): assert results[ix][Axes.ROUND] == 0 for ix in (2, 3): assert results[ix][Axes.ROUND] == 1 for ix in (4, 5): assert results[ix][Axes.ROUND] == 2 for ix in (0, 2, 4): assert results[ix][Axes.CH] == 0 for ix in (1, 3, 5): assert results[ix][Axes.CH] == 1
def test_ch_then_round(): results = list( ordered_iterator(((Axes.CH, range(2)), (Axes.ROUND, range(3))))) for ix in (0, 3): assert results[ix][Axes.ROUND] == 0 for ix in (1, 4): assert results[ix][Axes.ROUND] == 1 for ix in (2, 5): assert results[ix][Axes.ROUND] == 2 for ix in (0, 1, 2): assert results[ix][Axes.CH] == 0 for ix in (3, 4, 5): assert results[ix][Axes.CH] == 1
def write_experiment_json( path: str, fov_count: int, tile_format: ImageFormat, *, primary_image_dimensions: Mapping[Union[str, Axes], int], aux_name_to_dimensions: Mapping[str, Mapping[Union[str, Axes], int]], primary_tile_fetcher: Optional[TileFetcher]=None, aux_tile_fetcher: Optional[Mapping[str, TileFetcher]]=None, postprocess_func: Optional[Callable[[dict], dict]]=None, default_shape: Optional[Mapping[Axes, int]]=None, dimension_order: Sequence[Axes]=(Axes.ZPLANE, Axes.ROUND, Axes.CH), fov_path_generator: Optional[Callable[[Path, str], Path]] = None, tile_opener: Optional[Callable[[Path, Tile, str], BinaryIO]] = None, ) -> None: """ Build and returns a top-level experiment description with the following characteristics: Parameters ---------- path : str Directory to write the files to. fov_count : int Number of fields of view in this experiment. tile_format : ImageFormat File format to write the tiles as. primary_image_dimensions : Mapping[Union[str, Axes], int] Dictionary mapping dimension name to dimension size for the primary image. aux_name_to_dimensions : Mapping[str, Mapping[Union[str, Axes], int]] Dictionary mapping the auxiliary image type to dictionaries, which map from dimension name to dimension size. primary_tile_fetcher : Optional[TileFetcher] TileFetcher for primary images. Set this if you want specific image data to be set for the primary images. If not provided, the image data is set to random noise via :class:`RandomNoiseTileFetcher`. aux_tile_fetcher : Optional[Mapping[str, TileFetcher]] TileFetchers for auxiliary images. Set this if you want specific image data to be set for one or more aux image types. If not provided for any given aux image, the image data is set to random noise via :class:`RandomNoiseTileFetcher`. postprocess_func : Optional[Callable[[dict], dict]] If provided, this is called with the experiment document for any postprocessing. An example of this would be to add something to one of the top-level extras field. The callable should return what is to be written as the experiment document. default_shape : Optional[Tuple[int, int]] (default = None) Default shape for the tiles in this experiment. dimension_order : Sequence[Axes] Ordering for which dimensions vary, in order of the slowest changing dimension to the fastest. For instance, if the order is (ROUND, Z, CH) and each dimension has size 2, then the sequence is: (ROUND=0, CH=0, Z=0) (ROUND=0, CH=1, Z=0) (ROUND=0, CH=0, Z=1) (ROUND=0, CH=1, Z=1) (ROUND=1, CH=0, Z=0) (ROUND=1, CH=1, Z=0) (ROUND=1, CH=0, Z=1) (ROUND=1, CH=1, Z=1) (default = (Axes.Z, Axes.ROUND, Axes.CH)) fov_path_generator : Callable[[Path, str], Path] Generates the path for a FOV's json file. If one is not provided, the default generates the FOV's json file at the same level as the top-level json file for an image. If this is not provided, a reasonable default will be provided. tile_opener : Callable[[Path, Tile, str], BinaryIO] Callable that gets invoked with the following arguments: 1. the directory of the experiment that is being constructed, 2. the tile that is being written, and 3. the file extension that the tile should be written with. The callable is expected to return an open file handle. If this is not provided, a reasonable default will be provided. """ all_tile_fetcher: MutableMapping[str, TileFetcher] = {} if aux_tile_fetcher is not None: all_tile_fetcher.update(aux_tile_fetcher) if primary_tile_fetcher is not None: all_tile_fetcher[FieldOfView.PRIMARY_IMAGES] = primary_tile_fetcher image_tile_identifiers: MutableMapping[str, Iterable[TileIdentifier]] = dict() image_tile_fetchers: MutableMapping[str, TileFetcher] = dict() dimension_cardinality_of_images = {FieldOfView.PRIMARY_IMAGES: primary_image_dimensions} for image_type, image_dimension in aux_name_to_dimensions.items(): dimension_cardinality_of_images[image_type] = image_dimension for image_type, dimension_cardinality_of_image in dimension_cardinality_of_images.items(): axes_sizes = join_axes_labels( dimension_order, rounds=range(dimension_cardinality_of_image[Axes.ROUND]), chs=range(dimension_cardinality_of_image[Axes.CH]), zplanes=range(dimension_cardinality_of_image[Axes.ZPLANE]), ) image_tile_identifiers[image_type] = [ TileIdentifier(fov_id, selector[Axes.ROUND], selector[Axes.CH], selector[Axes.ZPLANE]) for fov_id in range(fov_count) for selector in ordered_iterator(axes_sizes) ] image_tile_fetchers[image_type] = all_tile_fetcher.get( image_type, tile_fetcher_factory(RandomNoiseTile)) return write_irregular_experiment_json( path, tile_format, image_tile_identifiers=image_tile_identifiers, tile_fetchers=image_tile_fetchers, postprocess_func=postprocess_func, default_shape=default_shape, fov_path_generator=fov_path_generator, tile_opener=tile_opener, )
def build_image( fovs: Sequence[int], rounds: Sequence[int], chs: Sequence[int], zplanes: Sequence[int], image_fetcher: TileFetcher, default_shape: Optional[Mapping[Axes, int]] = None, axes_order: Sequence[Axes] = DEFAULT_DIMENSION_ORDER, ) -> Collection: """ Build and returns an image set with the following characteristics: Parameters ---------- fovs : Sequence[int] Sequence of field of view ids in this image set. rounds : Sequence[int] Sequence of the round numbers in this image set. chs : Sequence[int] Sequence of the ch numbers in this image set. zplanes : Sequence[int] Sequence of the zplane numbers in this image set. image_fetcher : TileFetcher Instance of TileFetcher that provides the data for the tile. default_shape : Optional[Tuple[int, int]] Default shape of the individual tiles in this image set. axes_order : Sequence[Axes] Ordering for which axes vary, in order of the slowest changing axis to the fastest. For instance, if the order is (ROUND, Z, CH) and each dimension has size 2, then the sequence is: (ROUND=0, CH=0, Z=0) (ROUND=0, CH=1, Z=0) (ROUND=0, CH=0, Z=1) (ROUND=0, CH=1, Z=1) (ROUND=1, CH=0, Z=0) (ROUND=1, CH=1, Z=0) (ROUND=1, CH=0, Z=1) (ROUND=1, CH=1, Z=1) (default = (Axes.Z, Axes.ROUND, Axes.CH)) Returns ------- The slicedimage collection representing the image. """ axes_sizes = join_axes_labels(axes_order, rounds=rounds, chs=chs, zplanes=zplanes) collection = Collection() for fov_id in fovs: fov_images = TileSet( [ Coordinates.X, Coordinates.Y, Coordinates.Z, Axes.ZPLANE, Axes.ROUND, Axes.CH, Axes.X, Axes.Y, ], { Axes.ROUND: len(rounds), Axes.CH: len(chs), Axes.ZPLANE: len(zplanes) }, default_shape, ImageFormat.TIFF, ) for selector in ordered_iterator(axes_sizes): image = image_fetcher.get_tile(fov_id, selector[Axes.ROUND], selector[Axes.CH], selector[Axes.ZPLANE]) tile = Tile( image.coordinates, { Axes.ZPLANE: (selector[Axes.ZPLANE]), Axes.ROUND: (selector[Axes.ROUND]), Axes.CH: (selector[Axes.CH]), }, image.shape, extras=image.extras, ) tile.set_numpy_array_future(image.tile_data) # Astute readers might wonder why we set this variable. This is to support in-place # experiment construction. We monkey-patch slicedimage's Tile class such that checksum # computation is done by finding the FetchedTile object, which allows us to calculate # the checksum of the original file. tile.provider = image fov_images.add_tile(tile) collection.add_partition("fov_{:03}".format(fov_id), fov_images) return collection