Example #1
0
 def _cli(ctx, input, output, codebook):
     ctx.obj = dict(
         component=Decoder,
         input=input,
         output=output,
         intensities=IntensityTable.load(input),
         codebook=Codebook.from_json(codebook),
     )
Example #2
0
 def _cli(ctx, input, output, codebook):
     """pixel-wise spot detection and decoding"""
     print('Detecting Spots ...')
     ctx.obj = dict(
         component=PixelSpotDecoder,
         image_stack=ImageStack.from_path_or_url(input),
         output=output,
         codebook=Codebook.from_json(codebook),
     )
Example #3
0
    def _cli(ctx, input, output, blobs_stack,
             reference_image_from_max_projection, codebook):
        print('Detecting Spots ...')
        ctx.obj = dict(
            component=SpotFinder,
            image_stack=ImageStack.from_path_or_url(input),
            output=output,
            blobs_stack=blobs_stack,
            reference_image_from_max_projection=
            reference_image_from_max_projection,
            codebook=None,
        )

        if codebook is not None:
            ctx.obj["codebook"] = Codebook.from_json(codebook)
Example #4
0
    def _cli(cls, args, print_help=False):
        """Runs the decoder component based on parsed arguments."""

        if args.decoder_algorithm_class is None or print_help:
            cls.decoder_group.print_help()
            cls.decoder_group.exit(status=2)

        instance = args.decoder_algorithm_class(**vars(args))

        # load intensities and codebook
        intensities = IntensityTable.load(args.input)
        codebook = Codebook.from_json(args.codebook)

        # decode and save output
        intensities = instance.run(intensities, codebook)
        intensities.save(args.output)
Example #5
0
    def run(self, intensities: IntensityTable, codebook: Codebook, *args) -> IntensityTable:
        """Decode spots by selecting the max-valued channel in each sequencing round

        Parameters
        ----------
        intensities : IntensityTable
            IntensityTable to be decoded
        codebook : Codebook
            Contains codes to decode IntensityTable

        Returns
        -------
        IntensityTable :
            IntensityTable decoded and appended with Features.TARGET and Features.QUALITY values.

        """
        return codebook.decode_per_round_max(intensities)
Example #6
0
    def from_json(cls,
                  json_url: str,
                  strict: bool = None,
                  config: Optional[Union[str, Dict]] = None) -> "Experiment":
        """
        Construct an `Experiment` from an experiment.json file format specifier

        Parameters
        ----------
        json_url : str
            file path or web link to an experiment.json file
        strict : bool
            if true, then all JSON loaded by this method will be
            passed to the appropriate validator
        config : str or dict
            configuration property that will be passed to
            starfish.util.config.Config
        STARISH_CONFIG :
            This parameter is read from the environment to permit setting configuration
            values either directly or via a file. Keys read include:
             - cache.allow_caching
        STARFISH_STRICT_LOADING :
             This parameter is read from the environment. If set, then all JSON loaded by this
             method will be passed to the appropriate validator. The `strict` parameter to this
             method has priority over the environment variable.

        Returns
        -------
        Experiment :
            Experiment object serving the requested experiment data

        """
        if strict is None:
            strict = "STARFISH_STRICT_LOADING" in os.environ
        if strict:
            valid = validate_sptx.validate(json_url)
            if not valid:
                raise Exception("validation failed")

        config_obj = Config(config)  # STARFISH_CONFIG is assumed
        allow_caching = config_obj.lookup(["cache", "allow_caching"], True)

        backend, name, baseurl = resolve_path_or_url(json_url, allow_caching)
        with backend.read_contextmanager(name) as fh:
            experiment_document = json.load(fh)

        version = cls.verify_version(experiment_document['version'])

        _, codebook_name, codebook_baseurl = resolve_url(
            experiment_document['codebook'], baseurl, allow_caching)
        codebook_absolute_url = pathjoin(codebook_baseurl, codebook_name)
        codebook = Codebook.from_json(codebook_absolute_url)

        extras = experiment_document['extras']

        fovs: MutableSequence[FieldOfView] = list()
        fov_tilesets: MutableMapping[str, TileSet] = dict()
        if version < Version("5.0.0"):
            primary_image: Collection = Reader.parse_doc(
                experiment_document['primary_images'], baseurl)
            auxiliary_images: MutableMapping[str, Collection] = dict()
            for aux_image_type, aux_image_url in experiment_document[
                    'auxiliary_images'].items():
                auxiliary_images[aux_image_type] = Reader.parse_doc(
                    aux_image_url, baseurl)

            for fov_name, primary_tileset in primary_image.all_tilesets():
                fov_tilesets[FieldOfView.PRIMARY_IMAGES] = primary_tileset
                for aux_image_type, aux_image_collection in auxiliary_images.items(
                ):
                    aux_image_tileset = aux_image_collection.find_tileset(
                        fov_name)
                    if aux_image_tileset is not None:
                        fov_tilesets[aux_image_type] = aux_image_tileset

                fov = FieldOfView(fov_name, image_tilesets=fov_tilesets)
                fovs.append(fov)
        else:
            images: MutableMapping[str, Collection] = dict()
            all_fov_names: MutableSet[str] = set()
            for image_type, image_url in experiment_document['images'].items():
                image = Reader.parse_doc(image_url, baseurl)
                images[image_type] = image
                for fov_name, _ in image.all_tilesets():
                    all_fov_names.add(fov_name)

            for fov_name in all_fov_names:
                for image_type, image_collection in images.items():
                    image_tileset = image_collection.find_tileset(fov_name)
                    if image_tileset is not None:
                        fov_tilesets[image_type] = image_tileset

                fov = FieldOfView(fov_name, image_tilesets=fov_tilesets)
                fovs.append(fov)

        return Experiment(fovs, codebook, extras, src_doc=experiment_document)
Example #7
0
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),
) -> 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.
    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))
    """
    if primary_tile_fetcher is None:
        primary_tile_fetcher = tile_fetcher_factory(RandomNoiseTile)
    if aux_tile_fetcher is None:
        aux_tile_fetcher = {}
    if postprocess_func is None:
        postprocess_func = lambda doc: doc

    experiment_doc: Dict[str, Any] = {
        'version': str(CURRENT_VERSION),
        'images': {},
        'extras': {},
    }
    primary_image = build_image(
        range(fov_count),
        range(primary_image_dimensions[Axes.ROUND]),
        range(primary_image_dimensions[Axes.CH]),
        range(primary_image_dimensions[Axes.ZPLANE]),
        primary_tile_fetcher,
        axes_order=dimension_order,
        default_shape=default_shape,
    )
    Writer.write_to_path(
        primary_image,
        os.path.join(path, "primary_images.json"),
        pretty=True,
        partition_path_generator=_fov_path_generator,
        tile_opener=_tile_opener,
        tile_format=tile_format,
    )
    experiment_doc['images']['primary'] = "primary_images.json"

    for aux_name, aux_dimensions in aux_name_to_dimensions.items():
        if aux_dimensions is None:
            continue
        auxiliary_image = build_image(
            range(fov_count),
            range(aux_dimensions[Axes.ROUND]),
            range(aux_dimensions[Axes.CH]),
            range(aux_dimensions[Axes.ZPLANE]),
            aux_tile_fetcher.get(aux_name, tile_fetcher_factory(RandomNoiseTile)),
            axes_order=dimension_order,
            default_shape=default_shape,
        )
        Writer.write_to_path(
            auxiliary_image,
            os.path.join(path, "{}.json".format(aux_name)),
            pretty=True,
            partition_path_generator=_fov_path_generator,
            tile_opener=_tile_opener,
            tile_format=tile_format,
        )
        experiment_doc['images'][aux_name] = "{}.json".format(aux_name)

    experiment_doc["codebook"] = "codebook.json"
    codebook_array = [
        {
            "codeword": [
                {"r": 0, "c": 0, "v": 1},
            ],
            "target": "PLEASE_REPLACE_ME"
        },
    ]
    codebook = Codebook.from_code_array(codebook_array)
    codebook_json_filename = "codebook.json"
    codebook.to_json(os.path.join(path, codebook_json_filename))

    experiment_doc = postprocess_func(experiment_doc)

    with open(os.path.join(path, "experiment.json"), "w") as fh:
        json.dump(experiment_doc, fh, indent=4)
Example #8
0
def loaded_codebook(simple_codebook_json):
    return Codebook.from_json(simple_codebook_json, n_ch=2, n_round=2)
Example #9
0
def simple_codebook_json(simple_codebook_array) -> Generator[str, None, None]:
    with tempfile.NamedTemporaryFile() as tf:
        codebook = Codebook.from_code_array(simple_codebook_array)
        codebook.to_json(tf.name)

        yield tf.name
Example #10
0
    def from_json(cls, json_url: str) -> "Experiment":
        """
        Construct an `Experiment` from an experiment.json file format specifier.
        Loads configuration from StarfishConfig.

        Parameters
        ----------
        json_url : str
            file path or web link to an experiment.json file

        Returns
        -------
        Experiment :
            Experiment object serving the requested experiment data

        """

        config = StarfishConfig()

        if config.strict:
            valid = validate_sptx.validate(json_url)
            if not valid:
                raise Exception("validation failed")

        backend, name, baseurl = resolve_path_or_url(json_url,
                                                     config.slicedimage)
        with backend.read_contextmanager(name) as fh:
            experiment_document = json.load(fh)

        version = cls.verify_version(experiment_document['version'])

        _, codebook_name, codebook_baseurl = resolve_url(
            experiment_document['codebook'], baseurl, config.slicedimage)
        codebook_absolute_url = pathjoin(codebook_baseurl, codebook_name)
        codebook = Codebook.from_json(codebook_absolute_url)

        extras = experiment_document['extras']

        fovs: MutableSequence[FieldOfView] = list()
        fov_tilesets: MutableMapping[str, TileSet]
        if version < Version("5.0.0"):
            primary_image: Collection = Reader.parse_doc(
                experiment_document['primary_images'], baseurl,
                config.slicedimage)
            auxiliary_images: MutableMapping[str, Collection] = dict()
            for aux_image_type, aux_image_url in experiment_document[
                    'auxiliary_images'].items():
                auxiliary_images[aux_image_type] = Reader.parse_doc(
                    aux_image_url, baseurl, config.slicedimage)

            for fov_name, primary_tileset in primary_image.all_tilesets():
                fov_tilesets = dict()
                fov_tilesets[FieldOfView.PRIMARY_IMAGES] = primary_tileset
                for aux_image_type, aux_image_collection in auxiliary_images.items(
                ):
                    aux_image_tileset = aux_image_collection.find_tileset(
                        fov_name)
                    if aux_image_tileset is not None:
                        fov_tilesets[aux_image_type] = aux_image_tileset

                fov = FieldOfView(fov_name, image_tilesets=fov_tilesets)
                fovs.append(fov)
        else:
            images: MutableMapping[str, Collection] = dict()
            all_fov_names: MutableSet[str] = set()
            for image_type, image_url in experiment_document['images'].items():
                image = Reader.parse_doc(image_url, baseurl,
                                         config.slicedimage)
                images[image_type] = image
                for fov_name, _ in image.all_tilesets():
                    all_fov_names.add(fov_name)

            for fov_name in all_fov_names:
                fov_tilesets = dict()
                for image_type, image_collection in images.items():
                    image_tileset = image_collection.find_tileset(fov_name)
                    if image_tileset is not None:
                        fov_tilesets[image_type] = image_tileset

                fov = FieldOfView(fov_name, image_tilesets=fov_tilesets)
                fovs.append(fov)

        return Experiment(fovs, codebook, extras, src_doc=experiment_document)
Example #11
0
 def codebook(self) -> Codebook:
     return Codebook.synthetic_one_hot_codebook(self.n_round, self.n_ch,
                                                self.n_codes)
Example #12
0
 def load(self, input_parameter: str) -> Codebook:
     return Codebook.from_json(input_parameter)
Example #13
0
    def from_json(cls, json_url: str, strict: bool=None) -> "Experiment":
        """
        Construct an `Experiment` from an experiment.json file format specifier

        Parameters
        ----------
        json_url : str
            file path or web link to an experiment.json file
        strict : bool
            if true, then all JSON loaded by this method will be
            passed to the appropriate validator

        Returns
        -------
        Experiment :
            Experiment object serving the requested experiment data

        Environment variables
        ---------------------
        STARFISH_STRICT_LOADING :
             If set, then all JSON loaded by this method will be
             passed to the appropriate validator. The `strict`
             parameter to this method has priority over the
             environment variable.

        """
        if strict is None:
            strict = "STARFISH_STRICT_LOADING" in os.environ
        if strict:
            valid = validate_sptx.validate(json_url)
            if not valid:
                raise Exception("validation failed")

        backend, name, baseurl = resolve_path_or_url(json_url)
        with backend.read_contextmanager(name) as fh:
            experiment_document = json.load(fh)

        cls.verify_version(experiment_document['version'])

        _, codebook_name, codebook_baseurl = resolve_url(experiment_document['codebook'], baseurl)
        codebook_absolute_url = pathjoin(codebook_baseurl, codebook_name)
        codebook = Codebook.from_json(codebook_absolute_url)

        extras = experiment_document['extras']

        primary_image: Collection = Reader.parse_doc(experiment_document['primary_images'], baseurl)
        auxiliary_images: MutableMapping[str, Collection] = dict()
        for aux_image_type, aux_image_url in experiment_document['auxiliary_images'].items():
            auxiliary_images[aux_image_type] = Reader.parse_doc(aux_image_url, baseurl)

        fovs: MutableSequence[FieldOfView] = list()
        for fov_name, primary_tileset in primary_image.all_tilesets():
            aux_image_tilesets_for_fov: MutableMapping[str, TileSet] = dict()
            for aux_image_type, aux_image_collection in auxiliary_images.items():
                aux_image_tileset = aux_image_collection.find_tileset(fov_name)
                if aux_image_tileset is not None:
                    aux_image_tilesets_for_fov[aux_image_type] = aux_image_tileset

            fov = FieldOfView(
                fov_name,
                primary_image_tileset=primary_tileset,
                auxiliary_image_tilesets=aux_image_tilesets_for_fov,
            )
            fovs.append(fov)

        return Experiment(fovs, codebook, extras, src_doc=experiment_document)