Skip to content

core ¤

bioimageio.core --- core functionality for BioImage.IO resources

The main focus on this library is to provide functionality to run prediction with BioImage.IO models, including standardized pre- and postprocessing operations. The BioImage.IO models (and other resources) are described by---and can be loaded with---the bioimageio.spec package.

See predict and predict_many for straight-forward model inference and create_prediction_pipeline for finer control of the inference process.

Other notable bioimageio.core functionalities include: - Testing BioImage.IO resources beyond format validation, e.g. by generating model outputs from test inputs. See test_model or for arbitrary resource types test_description. - Extending available model weight formats by converting existing ones, see add_weights. - Creating and manipulating Samples consisting of tensors with associated statistics. - Computing statistics on datasets (represented as sequences of samples), see compute_dataset_measures.

Modules:

Name Description
__main__
axis
backends
block
block_meta
cli

bioimageio CLI

commands

These functions are used in the bioimageio command line interface

common
dataset
digest_spec
io
model_adapters

DEPRECATED

prediction
proc_ops
proc_setup
sample
stat_calculators
stat_measures
tensor
utils
weight_converters

Classes:

Name Description
PredictionPipeline

Represents model computation including preprocessing and postprocessing

Settings

environment variables for bioimageio.spec and bioimageio.core

Functions:

Name Description
create_prediction_pipeline

Creates prediction pipeline which includes:

enable_determinism

Seed and configure ML frameworks for maximum reproducibility.

load_description_and_test

Test a bioimage.io resource dynamically,

test_description

Test a bioimage.io resource dynamically,

test_model

Test model inference

Attributes:

Name Type Description
Axis
AxisId
BlockMeta
MemberId
Sample
Stat
Tensor
ValidationSummary
__version__
add_weights
build_description
compute_dataset_measures
create_model_adapter
dump_description
load_dataset_description
load_description
load_description_and_validate_format_only
load_model

alias of load_model_description

load_model_description
load_resource

alias of load_description

predict
predict_many
save_bioimageio_package
save_bioimageio_package_as_folder
save_bioimageio_yaml_only
settings

parsed environment variables for bioimageio.spec and bioimageio.core

test_resource

alias of test_description

validate_format

Axis module-attribute ¤

Axis = axis.Axis

AxisId module-attribute ¤

AxisId = axis.AxisId

BlockMeta module-attribute ¤

BlockMeta = block_meta.BlockMeta

MemberId module-attribute ¤

MemberId = common.MemberId

Sample module-attribute ¤

Sample = sample.Sample

Stat module-attribute ¤

Tensor module-attribute ¤

Tensor = tensor.Tensor

ValidationSummary module-attribute ¤

ValidationSummary = bioimageio.spec.ValidationSummary

__version__ module-attribute ¤

__version__ = '0.9.6'

add_weights module-attribute ¤

build_description module-attribute ¤

build_description = bioimageio.spec.build_description

compute_dataset_measures module-attribute ¤

compute_dataset_measures = stat_calculators.compute_dataset_measures

create_model_adapter module-attribute ¤

create_model_adapter = backends.create_model_adapter

dump_description module-attribute ¤

dump_description = bioimageio.spec.dump_description

load_dataset_description module-attribute ¤

load_dataset_description = bioimageio.spec.load_dataset_description

load_description module-attribute ¤

load_description = bioimageio.spec.load_description

load_description_and_validate_format_only module-attribute ¤

load_description_and_validate_format_only = bioimageio.spec.load_description_and_validate_format_only

load_model module-attribute ¤

alias of load_model_description

load_model_description module-attribute ¤

load_model_description = bioimageio.spec.load_model_description

load_resource module-attribute ¤

load_resource = load_description

alias of load_description

predict module-attribute ¤

predict = prediction.predict

predict_many module-attribute ¤

predict_many = prediction.predict_many

save_bioimageio_package module-attribute ¤

save_bioimageio_package = bioimageio.spec.save_bioimageio_package

save_bioimageio_package_as_folder module-attribute ¤

save_bioimageio_package_as_folder = bioimageio.spec.save_bioimageio_package_as_folder

save_bioimageio_yaml_only module-attribute ¤

save_bioimageio_yaml_only = bioimageio.spec.save_bioimageio_yaml_only

settings module-attribute ¤

settings = Settings()

parsed environment variables for bioimageio.spec and bioimageio.core

test_resource module-attribute ¤

test_resource = test_description

alias of test_description

validate_format module-attribute ¤

validate_format = bioimageio.spec.validate_format

PredictionPipeline ¤

PredictionPipeline(*, name: str, model_description: AnyModelDescr, preprocessing: List[Processing], postprocessing: List[Processing], model_adapter: ModelAdapter, default_ns: Optional[BlocksizeParameter] = None, default_blocksize_parameter: BlocksizeParameter = 10, default_batch_size: int = 1)

Represents model computation including preprocessing and postprocessing Note: Ideally use the PredictionPipeline in a with statement (as a context manager).

Methods:

Name Description
__enter__
__exit__
apply_postprocessing

apply postprocessing in-place, also updates samples stats

apply_preprocessing

apply preprocessing in-place, also updates sample stats

get_output_sample_id
load

optional step: load model onto devices before calling forward if not using it as context manager

predict_sample_block
predict_sample_with_blocking

predict a sample by splitting it into blocks according to the model and the ns parameter

predict_sample_with_fixed_blocking
predict_sample_without_blocking

predict a sample.

unload

free any device memory in use

Attributes:

Name Type Description
model_description
name
Source code in src/bioimageio/core/_prediction_pipeline.py
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
def __init__(
    self,
    *,
    name: str,
    model_description: AnyModelDescr,
    preprocessing: List[Processing],
    postprocessing: List[Processing],
    model_adapter: ModelAdapter,
    default_ns: Optional[BlocksizeParameter] = None,
    default_blocksize_parameter: BlocksizeParameter = 10,
    default_batch_size: int = 1,
) -> None:
    """Consider using `create_prediction_pipeline` to create a `PredictionPipeline` with sensible defaults."""
    super().__init__()
    default_blocksize_parameter = default_ns or default_blocksize_parameter
    if default_ns is not None:
        warnings.warn(
            "Argument `default_ns` is deprecated in favor of"
            + " `default_blocksize_paramter` and will be removed soon."
        )
    del default_ns

    if model_description.run_mode:
        warnings.warn(
            f"Not yet implemented inference for run mode '{model_description.run_mode.name}'"
        )

    self.name = name
    self._preprocessing = preprocessing
    self._postprocessing = postprocessing

    self.model_description = model_description
    if isinstance(model_description, v0_4.ModelDescr):
        self._default_input_halo: PerMember[PerAxis[Halo]] = {}
        self._block_transform = None
    else:
        default_output_halo = {
            t.id: {
                a.id: Halo(a.halo, a.halo)
                for a in t.axes
                if isinstance(a, v0_5.WithHalo)
            }
            for t in model_description.outputs
        }
        self._default_input_halo = get_input_halo(
            model_description, default_output_halo
        )
        self._block_transform = get_block_transform(model_description)

    self._default_blocksize_parameter = default_blocksize_parameter
    self._default_batch_size = default_batch_size

    self._input_ids = get_member_ids(model_description.inputs)
    self._output_ids = get_member_ids(model_description.outputs)

    self._adapter: ModelAdapter = model_adapter

model_description instance-attribute ¤

model_description = model_description

name instance-attribute ¤

name = name

__enter__ ¤

__enter__()
Source code in src/bioimageio/core/_prediction_pipeline.py
114
115
116
def __enter__(self):
    self.load()
    return self

__exit__ ¤

__exit__(exc_type, exc_val, exc_tb)
Source code in src/bioimageio/core/_prediction_pipeline.py
118
119
120
def __exit__(self, exc_type, exc_val, exc_tb):  # type: ignore
    self.unload()
    return False

apply_postprocessing ¤

apply_postprocessing(sample: Union[Sample, SampleBlock, SampleBlockWithOrigin]) -> None

apply postprocessing in-place, also updates samples stats

Source code in src/bioimageio/core/_prediction_pipeline.py
289
290
291
292
293
294
295
296
297
298
299
300
301
def apply_postprocessing(
    self, sample: Union[Sample, SampleBlock, SampleBlockWithOrigin]
) -> None:
    """apply postprocessing in-place, also updates samples stats"""
    for op in self._postprocessing:
        if isinstance(sample, (Sample, SampleBlockWithOrigin)):
            op(sample)
        elif not isinstance(op, BlockedOperator):
            raise NotImplementedError(
                "block wise update of output statistics not yet implemented"
            )
        else:
            op(sample)

apply_preprocessing ¤

apply_preprocessing(sample: Union[Sample, SampleBlockWithOrigin]) -> None

apply preprocessing in-place, also updates sample stats

Source code in src/bioimageio/core/_prediction_pipeline.py
284
285
286
287
def apply_preprocessing(self, sample: Union[Sample, SampleBlockWithOrigin]) -> None:
    """apply preprocessing in-place, also updates sample stats"""
    for op in self._preprocessing:
        op(sample)

get_output_sample_id ¤

get_output_sample_id(input_sample_id: SampleId)
Source code in src/bioimageio/core/_prediction_pipeline.py
166
167
168
169
170
171
172
def get_output_sample_id(self, input_sample_id: SampleId):
    warnings.warn(
        "`PredictionPipeline.get_output_sample_id()` is deprecated and will be"
        + " removed soon. Output sample id is equal to input sample id, hence this"
        + " function is not needed."
    )
    return input_sample_id

load ¤

load()

optional step: load model onto devices before calling forward if not using it as context manager

Source code in src/bioimageio/core/_prediction_pipeline.py
303
304
305
306
307
def load(self):
    """
    optional step: load model onto devices before calling forward if not using it as context manager
    """
    pass

predict_sample_block ¤

predict_sample_block(sample_block: SampleBlockWithOrigin, skip_preprocessing: bool = False, skip_postprocessing: bool = False) -> SampleBlock
Source code in src/bioimageio/core/_prediction_pipeline.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
def predict_sample_block(
    self,
    sample_block: SampleBlockWithOrigin,
    skip_preprocessing: bool = False,
    skip_postprocessing: bool = False,
) -> SampleBlock:
    if isinstance(self.model_description, v0_4.ModelDescr):
        raise NotImplementedError(
            f"predict_sample_block not implemented for model {self.model_description.format_version}"
        )
    else:
        assert self._block_transform is not None

    if not skip_preprocessing:
        self.apply_preprocessing(sample_block)

    output_meta = sample_block.get_transformed_meta(self._block_transform)
    local_output = self._adapter.forward(sample_block)

    output = output_meta.with_data(local_output.members, stat=local_output.stat)
    if not skip_postprocessing:
        self.apply_postprocessing(output)

    return output

predict_sample_with_blocking ¤

predict_sample_with_blocking(sample: Sample, skip_preprocessing: bool = False, skip_postprocessing: bool = False, ns: Optional[Union[v0_5.ParameterizedSize_N, Mapping[Tuple[MemberId, AxisId], v0_5.ParameterizedSize_N]]] = None, batch_size: Optional[int] = None) -> Sample

predict a sample by splitting it into blocks according to the model and the ns parameter

Source code in src/bioimageio/core/_prediction_pipeline.py
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
def predict_sample_with_blocking(
    self,
    sample: Sample,
    skip_preprocessing: bool = False,
    skip_postprocessing: bool = False,
    ns: Optional[
        Union[
            v0_5.ParameterizedSize_N,
            Mapping[Tuple[MemberId, AxisId], v0_5.ParameterizedSize_N],
        ]
    ] = None,
    batch_size: Optional[int] = None,
) -> Sample:
    """predict a sample by splitting it into blocks according to the model and the `ns` parameter"""

    if isinstance(self.model_description, v0_4.ModelDescr):
        raise NotImplementedError(
            "`predict_sample_with_blocking` not implemented for v0_4.ModelDescr"
            + f" {self.model_description.name}."
            + " Consider using `predict_sample_with_fixed_blocking`"
        )

    ns = ns or self._default_blocksize_parameter
    if isinstance(ns, int):
        ns = {
            (ipt.id, a.id): ns
            for ipt in self.model_description.inputs
            for a in ipt.axes
            if isinstance(a.size, v0_5.ParameterizedSize)
        }
    input_block_shape = self.model_description.get_tensor_sizes(
        ns, batch_size or self._default_batch_size
    ).inputs

    return self.predict_sample_with_fixed_blocking(
        sample,
        input_block_shape=input_block_shape,
        skip_preprocessing=skip_preprocessing,
        skip_postprocessing=skip_postprocessing,
    )

predict_sample_with_fixed_blocking ¤

predict_sample_with_fixed_blocking(sample: Sample, input_block_shape: Mapping[MemberId, Mapping[AxisId, int]], *, skip_preprocessing: bool = False, skip_postprocessing: bool = False) -> Sample
Source code in src/bioimageio/core/_prediction_pipeline.py
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
def predict_sample_with_fixed_blocking(
    self,
    sample: Sample,
    input_block_shape: Mapping[MemberId, Mapping[AxisId, int]],
    *,
    skip_preprocessing: bool = False,
    skip_postprocessing: bool = False,
) -> Sample:
    if not skip_preprocessing:
        self.apply_preprocessing(sample)

    n_blocks, input_blocks = sample.split_into_blocks(
        input_block_shape,
        halo=self._default_input_halo,
        pad_mode="reflect",
    )
    input_blocks = list(input_blocks)
    predicted_blocks: List[SampleBlock] = []
    logger.info(
        "split sample shape {} into {} blocks of {}.",
        {k: dict(v) for k, v in sample.shape.items()},
        n_blocks,
        {k: dict(v) for k, v in input_block_shape.items()},
    )
    for b in tqdm(
        input_blocks,
        desc=f"predict {sample.id or ''} with {self.model_description.id or self.model_description.name}",
        unit="block",
        unit_divisor=1,
        total=n_blocks,
    ):
        predicted_blocks.append(
            self.predict_sample_block(
                b, skip_preprocessing=True, skip_postprocessing=True
            )
        )

    predicted_sample = Sample.from_blocks(predicted_blocks)
    if not skip_postprocessing:
        self.apply_postprocessing(predicted_sample)

    return predicted_sample

predict_sample_without_blocking ¤

predict_sample_without_blocking(sample: Sample, skip_preprocessing: bool = False, skip_postprocessing: bool = False) -> Sample

predict a sample. The sample's tensor shapes have to match the model's input tensor description. If that is not the case, consider predict_sample_with_blocking

Source code in src/bioimageio/core/_prediction_pipeline.py
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
def predict_sample_without_blocking(
    self,
    sample: Sample,
    skip_preprocessing: bool = False,
    skip_postprocessing: bool = False,
) -> Sample:
    """predict a sample.
    The sample's tensor shapes have to match the model's input tensor description.
    If that is not the case, consider `predict_sample_with_blocking`"""

    if not skip_preprocessing:
        self.apply_preprocessing(sample)

    output = self._adapter.forward(sample)
    if not skip_postprocessing:
        self.apply_postprocessing(output)

    return output

unload ¤

unload()

free any device memory in use

Source code in src/bioimageio/core/_prediction_pipeline.py
309
310
311
312
313
def unload(self):
    """
    free any device memory in use
    """
    self._adapter.unload()

Settings ¤

Bases: SpecSettings


              flowchart TD
              bioimageio.core.Settings[Settings]
              bioimageio.spec._internal._settings.Settings[Settings]

                              bioimageio.spec._internal._settings.Settings --> bioimageio.core.Settings
                


              click bioimageio.core.Settings href "" "bioimageio.core.Settings"
              click bioimageio.spec._internal._settings.Settings href "" "bioimageio.spec._internal._settings.Settings"
            

environment variables for bioimageio.spec and bioimageio.core

Methods:

Name Description
__setattr__

Attributes:

Name Type Description
CI Annotated[Union[bool, str], Field(alias=CI)]

Wether or not the execution happens in a continuous integration (CI) environment.

allow_pickle bool

Sets the allow_pickle argument for numpy.load()

cache_path Path

bioimageio cache location

collection_http_pattern str

A pattern to map bioimageio IDs to bioimageio.yaml URLs.

disk_cache
github_auth
github_token Optional[str]

GitHub token for API requests

github_username Optional[str]

GitHub username for API requests

http_timeout float

Timeout in seconds for http requests.

huggingface_http_pattern str

A pattern to map huggingface repo IDs to bioimageio.yaml URLs.

hypha_upload str

URL to the upload endpoint for bioimageio resources.

hypha_upload_token Optional[str]

Hypha API token to use for uploads.

id_map str

URL to bioimageio id_map.json to resolve resource IDs.

id_map_draft str

URL to bioimageio id_map_draft.json to resolve draft IDs ending with '/draft'.

keras_backend Annotated[Literal['torch', 'tensorflow', 'jax'], Field(alias=KERAS_BACKEND)]
log_warnings bool

Log validation warnings to console.

model_config
perform_io_checks bool

Wether or not to perform validation that requires file io,

resolve_draft bool

Flag to resolve draft resource versions following the pattern

user_agent Optional[str]

user agent for http requests

CI class-attribute instance-attribute ¤

CI: Annotated[Union[bool, str], Field(alias=CI)] = False

Wether or not the execution happens in a continuous integration (CI) environment.

allow_pickle class-attribute instance-attribute ¤

allow_pickle: bool = False

Sets the allow_pickle argument for numpy.load()

cache_path class-attribute instance-attribute ¤

cache_path: Path = Path(platformdirs.user_cache_dir('bioimageio'))

bioimageio cache location

collection_http_pattern class-attribute instance-attribute ¤

collection_http_pattern: str = 'https://hypha.aicell.io/bioimage-io/artifacts/{bioimageio_id}/files/rdf.yaml'

A pattern to map bioimageio IDs to bioimageio.yaml URLs. Notes: - '{bioimageio_id}' is replaced with user query, e.g. "affable-shark" when calling load_description("affable-shark"). - This method takes precedence over resolving via id_map. - If this endpoints fails, we fall back to id_map.

disk_cache cached property ¤

disk_cache

github_auth property ¤

github_auth

github_token class-attribute instance-attribute ¤

github_token: Optional[str] = None

GitHub token for API requests

github_username class-attribute instance-attribute ¤

github_username: Optional[str] = None

GitHub username for API requests

http_timeout class-attribute instance-attribute ¤

http_timeout: float = 10.0

Timeout in seconds for http requests.

huggingface_http_pattern class-attribute instance-attribute ¤

huggingface_http_pattern: str = 'https://huggingface.co/{repo_id}/resolve/{branch}/package/bioimageio.yaml'

A pattern to map huggingface repo IDs to bioimageio.yaml URLs. Notes: - Used for loading source strings of the form "huggingface/{user_or_org}/{resource_id}[/{version}]" - example use: load_description("huggingface/fynnbe/ambitious-sloth/1.3") - A given version {version} is mapped to a branch name "v{version}", e.g. "v1.3". - If no version is provided the "main" branch is used. - This method takes precedence over resolving via id_map. - If this endpoints fails, we fall back to id_map.

hypha_upload class-attribute instance-attribute ¤

hypha_upload: str = 'https://hypha.aicell.io/public/services/artifact-manager/create'

URL to the upload endpoint for bioimageio resources.

hypha_upload_token class-attribute instance-attribute ¤

hypha_upload_token: Optional[str] = None

Hypha API token to use for uploads.

By setting this token you agree to our terms of service at https://bioimage.io/#/toc.

How to obtain a token
  1. Login to https://bioimage.io
  2. Generate a new token at https://bioimage.io/#/api?tab=hypha-rpc

id_map class-attribute instance-attribute ¤

id_map: str = 'https://uk1s3.embassy.ebi.ac.uk/public-datasets/bioimage.io/id_map.json'

URL to bioimageio id_map.json to resolve resource IDs.

id_map_draft class-attribute instance-attribute ¤

id_map_draft: str = 'https://uk1s3.embassy.ebi.ac.uk/public-datasets/bioimage.io/id_map_draft.json'

URL to bioimageio id_map_draft.json to resolve draft IDs ending with '/draft'.

keras_backend class-attribute instance-attribute ¤

keras_backend: Annotated[Literal['torch', 'tensorflow', 'jax'], Field(alias=KERAS_BACKEND)] = 'torch'

log_warnings class-attribute instance-attribute ¤

log_warnings: bool = True

Log validation warnings to console.

model_config class-attribute instance-attribute ¤

model_config = SettingsConfigDict(env_prefix='BIOIMAGEIO_', env_file='.env', env_file_encoding='utf-8')

perform_io_checks class-attribute instance-attribute ¤

perform_io_checks: bool = True

Wether or not to perform validation that requires file io, e.g. downloading a remote files.

Existence of any local absolute file paths is still being checked.

resolve_draft class-attribute instance-attribute ¤

resolve_draft: bool = True

Flag to resolve draft resource versions following the pattern /draft.

Note that anyone may stage a new draft and that such a draft version may not have been reviewed yet. Set this flag to False to avoid this potential security risk and disallow loading draft versions.

user_agent class-attribute instance-attribute ¤

user_agent: Optional[str] = None

user agent for http requests

__setattr__ ¤

__setattr__(name: str, value: Any)
Source code in bioimageio/spec/_internal/_settings.py
31
32
33
34
35
36
37
38
39
def __setattr__(self, name: str, value: Any):
    super().__setattr__(name, value)
    # if cache_path is being changed, we need to reset the disk_cache so that it gets re-created with the new path when accessed next time
    if (
        name == "cache_path"
        and "disk_cache" in self.__dict__
        and self.disk_cache.dir_path != value
    ):
        del self.disk_cache

create_prediction_pipeline ¤

create_prediction_pipeline(bioimageio_model: AnyModelDescr, *, devices: Optional[Sequence[str]] = None, weight_format: Optional[SupportedWeightsFormat] = None, weights_format: Optional[SupportedWeightsFormat] = None, dataset_for_initial_statistics: Iterable[Union[Sample, Sequence[Tensor]]] = tuple(), keep_updating_initial_dataset_statistics: bool = False, fixed_dataset_statistics: Mapping[DatasetMeasure, MeasureValue] = MappingProxyType({}), model_adapter: Optional[ModelAdapter] = None, ns: Optional[BlocksizeParameter] = None, default_blocksize_parameter: BlocksizeParameter = 10, **deprecated_kwargs: Any) -> PredictionPipeline

Creates prediction pipeline which includes: * computation of input statistics * preprocessing * model prediction * computation of output statistics * postprocessing

Parameters:

Name Type Description Default

bioimageio_model ¤

AnyModelDescr

A bioimageio model description.

required

devices ¤

Optional[Sequence[str]]

(optional)

None

weight_format ¤

Optional[SupportedWeightsFormat]

deprecated in favor of weights_format

None

weights_format ¤

Optional[SupportedWeightsFormat]

(optional) Use a specific weights_format rather than choosing one automatically. A corresponding bioimageio.core.model_adapters.ModelAdapter will be created to run inference with the bioimageio_model.

None

dataset_for_initial_statistics ¤

Iterable[Union[Sample, Sequence[Tensor]]]

(optional) If preprocessing steps require input dataset statistics, dataset_for_initial_statistics allows you to specifcy a dataset from which these statistics are computed.

tuple()

keep_updating_initial_dataset_statistics ¤

bool

(optional) Set to True if you want to update dataset statistics with each processed sample.

False

fixed_dataset_statistics ¤

Mapping[DatasetMeasure, MeasureValue]

(optional) Allows you to specify a mapping of DatasetMeasures to precomputed MeasureValues.

MappingProxyType({})

model_adapter ¤

Optional[ModelAdapter]

(optional) Allows you to use a custom model_adapter instead of creating one according to the present/selected weights_format.

None

ns ¤

Optional[BlocksizeParameter]

deprecated in favor of default_blocksize_parameter

None

default_blocksize_parameter ¤

BlocksizeParameter

Allows to control the default block size for blockwise predictions, see BlocksizeParameter.

10
Source code in src/bioimageio/core/_prediction_pipeline.py
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
def create_prediction_pipeline(
    bioimageio_model: AnyModelDescr,
    *,
    devices: Optional[Sequence[str]] = None,
    weight_format: Optional[SupportedWeightsFormat] = None,
    weights_format: Optional[SupportedWeightsFormat] = None,
    dataset_for_initial_statistics: Iterable[Union[Sample, Sequence[Tensor]]] = tuple(),
    keep_updating_initial_dataset_statistics: bool = False,
    fixed_dataset_statistics: Mapping[DatasetMeasure, MeasureValue] = MappingProxyType(
        {}
    ),
    model_adapter: Optional[ModelAdapter] = None,
    ns: Optional[BlocksizeParameter] = None,
    default_blocksize_parameter: BlocksizeParameter = 10,
    **deprecated_kwargs: Any,
) -> PredictionPipeline:
    """
    Creates prediction pipeline which includes:
    * computation of input statistics
    * preprocessing
    * model prediction
    * computation of output statistics
    * postprocessing

    Args:
        bioimageio_model: A bioimageio model description.
        devices: (optional)
        weight_format: deprecated in favor of **weights_format**
        weights_format: (optional) Use a specific **weights_format** rather than
            choosing one automatically.
            A corresponding `bioimageio.core.model_adapters.ModelAdapter` will be
            created to run inference with the **bioimageio_model**.
        dataset_for_initial_statistics: (optional) If preprocessing steps require input
            dataset statistics, **dataset_for_initial_statistics** allows you to
            specifcy a dataset from which these statistics are computed.
        keep_updating_initial_dataset_statistics: (optional) Set to `True` if you want
            to update dataset statistics with each processed sample.
        fixed_dataset_statistics: (optional) Allows you to specify a mapping of
            `DatasetMeasure`s to precomputed `MeasureValue`s.
        model_adapter: (optional) Allows you to use a custom **model_adapter** instead
            of creating one according to the present/selected **weights_format**.
        ns: deprecated in favor of **default_blocksize_parameter**
        default_blocksize_parameter: Allows to control the default block size for
            blockwise predictions, see `BlocksizeParameter`.

    """
    weights_format = weight_format or weights_format
    del weight_format
    default_blocksize_parameter = ns or default_blocksize_parameter
    del ns
    if deprecated_kwargs:
        warnings.warn(
            f"deprecated create_prediction_pipeline kwargs: {set(deprecated_kwargs)}"
        )

    model_adapter = model_adapter or create_model_adapter(
        model_description=bioimageio_model,
        devices=devices,
        weight_format_priority_order=weights_format and (weights_format,),
    )

    input_ids = get_member_ids(bioimageio_model.inputs)

    def dataset():
        common_stat: Stat = {}
        for i, x in enumerate(dataset_for_initial_statistics):
            if isinstance(x, Sample):
                yield x
            else:
                yield Sample(members=dict(zip(input_ids, x)), stat=common_stat, id=i)

    preprocessing, postprocessing = setup_pre_and_postprocessing(
        bioimageio_model,
        dataset(),
        keep_updating_initial_dataset_stats=keep_updating_initial_dataset_statistics,
        fixed_dataset_stats=fixed_dataset_statistics,
    )

    return PredictionPipeline(
        name=bioimageio_model.name,
        model_description=bioimageio_model,
        model_adapter=model_adapter,
        preprocessing=preprocessing,
        postprocessing=postprocessing,
        default_blocksize_parameter=default_blocksize_parameter,
    )

enable_determinism ¤

enable_determinism(mode: Literal['seed_only', 'full'] = 'full', weight_formats: Optional[Sequence[SupportedWeightsFormat]] = None)

Seed and configure ML frameworks for maximum reproducibility. May degrade performance. Only recommended for testing reproducibility!

Seed any random generators and (if mode=="full") request ML frameworks to use deterministic algorithms.

Parameters:

Name Type Description Default

mode ¤

Literal['seed_only', 'full']

determinism mode - 'seed_only' -- only set seeds, or - 'full' determinsm features (might degrade performance or throw exceptions)

'full'

weight_formats ¤

Optional[Sequence[SupportedWeightsFormat]]

Limit deep learning importing deep learning frameworks based on weight_formats. E.g. this allows to avoid importing tensorflow when testing with pytorch.

None
Notes
  • mode == "full" might degrade performance or throw exceptions.
  • Subsequent inference calls might still differ. Call before each function (sequence) that is expected to be reproducible.
  • Degraded performance: Use for testing reproducibility only!
  • Recipes:
Source code in src/bioimageio/core/_resource_tests.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
def enable_determinism(
    mode: Literal["seed_only", "full"] = "full",
    weight_formats: Optional[Sequence[SupportedWeightsFormat]] = None,
):
    """Seed and configure ML frameworks for maximum reproducibility.
    May degrade performance. Only recommended for testing reproducibility!

    Seed any random generators and (if **mode**=="full") request ML frameworks to use
    deterministic algorithms.

    Args:
        mode: determinism mode
            - 'seed_only' -- only set seeds, or
            - 'full' determinsm features (might degrade performance or throw exceptions)
        weight_formats: Limit deep learning importing deep learning frameworks
            based on weight_formats.
            E.g. this allows to avoid importing tensorflow when testing with pytorch.

    Notes:
        - **mode** == "full"  might degrade performance or throw exceptions.
        - Subsequent inference calls might still differ. Call before each function
          (sequence) that is expected to be reproducible.
        - Degraded performance: Use for testing reproducibility only!
        - Recipes:
            - [PyTorch](https://pytorch.org/docs/stable/notes/randomness.html)
            - [Keras](https://keras.io/examples/keras_recipes/reproducibility_recipes/)
            - [NumPy](https://numpy.org/doc/2.0/reference/random/generated/numpy.random.seed.html)
    """
    try:
        try:
            import numpy.random
        except ImportError:
            pass
        else:
            numpy.random.seed(0)
    except Exception as e:
        logger.debug(str(e))

    if (
        weight_formats is None
        or "pytorch_state_dict" in weight_formats
        or "torchscript" in weight_formats
    ):
        try:
            try:
                import torch
            except ImportError:
                pass
            else:
                _ = torch.manual_seed(0)
                torch.use_deterministic_algorithms(mode == "full")
        except Exception as e:
            logger.debug(str(e))

    if (
        weight_formats is None
        or "tensorflow_saved_model_bundle" in weight_formats
        or "keras_hdf5" in weight_formats
    ):
        try:
            os.environ["TF_ENABLE_ONEDNN_OPTS"] = "0"
            try:
                import tensorflow as tf  # pyright: ignore[reportMissingTypeStubs]
            except ImportError:
                pass
            else:
                tf.random.set_seed(0)
                if mode == "full":
                    tf.config.experimental.enable_op_determinism()
                # TODO: find possibility to switch it off again??
        except Exception as e:
            logger.debug(str(e))

    if weight_formats is None or "keras_hdf5" in weight_formats:
        try:
            try:
                import keras  # pyright: ignore[reportMissingTypeStubs]
            except ImportError:
                pass
            else:
                keras.utils.set_random_seed(0)
        except Exception as e:
            logger.debug(str(e))

load_description_and_test ¤

load_description_and_test(source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent], *, format_version: Literal['latest'], weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[Sequence[str]] = None, determinism: Literal['seed_only', 'full'] = 'seed_only', expected_type: Literal['model'], sha256: Optional[Sha256] = None, stop_early: bool = True, working_dir: Optional[Union[os.PathLike[str], str]] = None, **deprecated: Unpack[DeprecatedKwargs]) -> Union[ModelDescr, InvalidDescr]
load_description_and_test(source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent], *, format_version: Literal['latest'], weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[Sequence[str]] = None, determinism: Literal['seed_only', 'full'] = 'seed_only', expected_type: Literal['dataset'], sha256: Optional[Sha256] = None, stop_early: bool = True, working_dir: Optional[Union[os.PathLike[str], str]] = None, **deprecated: Unpack[DeprecatedKwargs]) -> Union[DatasetDescr, InvalidDescr]
load_description_and_test(source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent], *, format_version: Literal['latest'], weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[Sequence[str]] = None, determinism: Literal['seed_only', 'full'] = 'seed_only', expected_type: Optional[str] = None, sha256: Optional[Sha256] = None, stop_early: bool = True, working_dir: Optional[Union[os.PathLike[str], str]] = None, **deprecated: Unpack[DeprecatedKwargs]) -> Union[LatestResourceDescr, InvalidDescr]
load_description_and_test(source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent], *, format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[Sequence[str]] = None, determinism: Literal['seed_only', 'full'] = 'seed_only', expected_type: Literal['model'], sha256: Optional[Sha256] = None, stop_early: bool = True, working_dir: Optional[Union[os.PathLike[str], str]] = None, **deprecated: Unpack[DeprecatedKwargs]) -> Union[AnyModelDescr, InvalidDescr]
load_description_and_test(source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent], *, format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[Sequence[str]] = None, determinism: Literal['seed_only', 'full'] = 'seed_only', expected_type: Literal['dataset'], sha256: Optional[Sha256] = None, stop_early: bool = True, working_dir: Optional[Union[os.PathLike[str], str]] = None, **deprecated: Unpack[DeprecatedKwargs]) -> Union[AnyDatasetDescr, InvalidDescr]
load_description_and_test(source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent], *, format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[Sequence[str]] = None, determinism: Literal['seed_only', 'full'] = 'seed_only', expected_type: Optional[str] = None, sha256: Optional[Sha256] = None, stop_early: bool = True, working_dir: Optional[Union[os.PathLike[str], str]] = None, **deprecated: Unpack[DeprecatedKwargs]) -> Union[ResourceDescr, InvalidDescr]
load_description_and_test(source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent], *, format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[Sequence[str]] = None, determinism: Literal['seed_only', 'full'] = 'seed_only', expected_type: Optional[str] = None, sha256: Optional[Sha256] = None, stop_early: bool = True, working_dir: Optional[Union[os.PathLike[str], str]] = None, **deprecated: Unpack[DeprecatedKwargs]) -> Union[ResourceDescr, InvalidDescr]

Test a bioimage.io resource dynamically, for example run prediction of test tensors for models.

See test_description for more details.

Returns:

Type Description
Union[ResourceDescr, InvalidDescr]

A (possibly invalid) resource description object with a populated .validation_summary attribute.

Source code in src/bioimageio/core/_resource_tests.py
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
def load_description_and_test(
    source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent],
    *,
    format_version: Union[FormatVersionPlaceholder, str] = DISCOVER,
    weight_format: Optional[SupportedWeightsFormat] = None,
    devices: Optional[Sequence[str]] = None,
    determinism: Literal["seed_only", "full"] = "seed_only",
    expected_type: Optional[str] = None,
    sha256: Optional[Sha256] = None,
    stop_early: bool = True,
    working_dir: Optional[Union[os.PathLike[str], str]] = None,
    **deprecated: Unpack[DeprecatedKwargs],
) -> Union[ResourceDescr, InvalidDescr]:
    """Test a bioimage.io resource dynamically,
    for example run prediction of test tensors for models.

    See `test_description` for more details.

    Returns:
        A (possibly invalid) resource description object
        with a populated `.validation_summary` attribute.
    """
    if isinstance(source, ResourceDescrBase):
        root = source.root
        file_name = source.file_name
        if (
            (
                format_version
                not in (
                    DISCOVER,
                    source.format_version,
                    ".".join(source.format_version.split(".")[:2]),
                )
            )
            or (c := source.validation_summary.details[0].context) is None
            or not c.perform_io_checks
        ):
            logger.debug(
                "deserializing source to ensure we validate and test using format {} and perform io checks",
                format_version,
            )
            source = dump_description(source)
    else:
        root = Path()
        file_name = None

    if isinstance(source, ResourceDescrBase):
        rd = source
    elif isinstance(source, dict):
        # check context for a given root; default to root of source
        context = get_validation_context(
            ValidationContext(root=root, file_name=file_name)
        ).replace(
            perform_io_checks=True  # make sure we perform io checks though
        )

        rd = build_description(
            source,
            format_version=format_version,
            context=context,
        )
    else:
        rd = load_description(
            source, format_version=format_version, sha256=sha256, perform_io_checks=True
        )

    rd.validation_summary.env.add(
        InstalledPackage(name="bioimageio.core", version=__version__)
    )

    if expected_type is not None:
        _test_expected_resource_type(rd, expected_type)

    if isinstance(rd, (v0_4.ModelDescr, v0_5.ModelDescr)):
        if weight_format is None:
            weight_formats: List[SupportedWeightsFormat] = [
                w for w, we in rd.weights if we is not None
            ]  # pyright: ignore[reportAssignmentType]
        else:
            weight_formats = [weight_format]

        enable_determinism(determinism, weight_formats=weight_formats)
        for w in weight_formats:
            _test_model_inference(
                rd,
                w,
                devices,
                stop_early=stop_early,
                working_dir=working_dir,
                verbose=working_dir is not None,
                **deprecated,
            )
            if stop_early and rd.validation_summary.status != "passed":
                break

            if not isinstance(rd, v0_4.ModelDescr):
                _test_model_inference_parametrized(
                    rd, w, devices, stop_early=stop_early
                )
                if stop_early and rd.validation_summary.status != "passed":
                    break

    # TODO: add execution of jupyter notebooks
    # TODO: add more tests

    return rd

test_description ¤

test_description(source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent], *, format_version: Union[FormatVersionPlaceholder, str] = 'discover', weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[Sequence[str]] = None, determinism: Literal['seed_only', 'full'] = 'seed_only', expected_type: Optional[str] = None, sha256: Optional[Sha256] = None, stop_early: bool = True, runtime_env: Union[Literal['currently-active', 'as-described'], Path, BioimageioCondaEnv] = 'currently-active', run_command: Callable[[Sequence[str]], None] = default_run_command, working_dir: Optional[Union[os.PathLike[str], str]] = None, **deprecated: Unpack[DeprecatedKwargs]) -> ValidationSummary

Test a bioimage.io resource dynamically, for example run prediction of test tensors for models.

Parameters:

Name Type Description Default

source ¤

Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent]

model description source.

required

weight_format ¤

Optional[SupportedWeightsFormat]

Weight format to test. Default: All weight formats present in source.

None

devices ¤

Optional[Sequence[str]]

Devices to test with, e.g. 'cpu', 'cuda'. Default (may be weight format dependent): ['cuda'] if available, ['cpu'] otherwise.

None

determinism ¤

Literal['seed_only', 'full']

Modes to improve reproducibility of test outputs.

'seed_only'

expected_type ¤

Optional[str]

Assert an expected resource description type.

None

sha256 ¤

Optional[Sha256]

Expected SHA256 value of source. (Ignored if source already is a loaded ResourceDescr object.)

None

stop_early ¤

bool

Do not run further subtests after a failed one.

True

runtime_env ¤

Union[Literal['currently-active', 'as-described'], Path, BioimageioCondaEnv]

(Experimental feature!) The Python environment to run the tests in - "currently-active": Use active Python interpreter. - "as-described": Use bioimageio.spec.get_conda_env to generate a conda environment YAML file based on the model weights description. - A BioimageioCondaEnv or a path to a conda environment YAML file. Note: The bioimageio.core dependency will be added automatically if not present.

'currently-active'

run_command ¤

Callable[[Sequence[str]], None]

(Experimental feature!) Function to execute (conda) terminal commands in a subprocess. The function should raise an exception if the command fails. run_command is ignored if runtime_env is "currently-active".

default_run_command

working_dir ¤

Optional[Union[os.PathLike[str], str]]

(for debugging) directory to save any temporary files (model packages, conda environments, test summaries). Defaults to a temporary directory.

None
Source code in src/bioimageio/core/_resource_tests.py
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
def test_description(
    source: Union[ResourceDescr, PermissiveFileSource, BioimageioYamlContent],
    *,
    format_version: Union[FormatVersionPlaceholder, str] = "discover",
    weight_format: Optional[SupportedWeightsFormat] = None,
    devices: Optional[Sequence[str]] = None,
    determinism: Literal["seed_only", "full"] = "seed_only",
    expected_type: Optional[str] = None,
    sha256: Optional[Sha256] = None,
    stop_early: bool = True,
    runtime_env: Union[
        Literal["currently-active", "as-described"], Path, BioimageioCondaEnv
    ] = ("currently-active"),
    run_command: Callable[[Sequence[str]], None] = default_run_command,
    working_dir: Optional[Union[os.PathLike[str], str]] = None,
    **deprecated: Unpack[DeprecatedKwargs],
) -> ValidationSummary:
    """Test a bioimage.io resource dynamically,
    for example run prediction of test tensors for models.

    Args:
        source: model description source.
        weight_format: Weight format to test.
            Default: All weight formats present in **source**.
        devices: Devices to test with, e.g. 'cpu', 'cuda'.
            Default (may be weight format dependent): ['cuda'] if available, ['cpu'] otherwise.
        determinism: Modes to improve reproducibility of test outputs.
        expected_type: Assert an expected resource description `type`.
        sha256: Expected SHA256 value of **source**.
                (Ignored if **source** already is a loaded `ResourceDescr` object.)
        stop_early: Do not run further subtests after a failed one.
        runtime_env: (Experimental feature!) The Python environment to run the tests in
            - `"currently-active"`: Use active Python interpreter.
            - `"as-described"`: Use `bioimageio.spec.get_conda_env` to generate a conda
                environment YAML file based on the model weights description.
            - A `BioimageioCondaEnv` or a path to a conda environment YAML file.
                Note: The `bioimageio.core` dependency will be added automatically if not present.
        run_command: (Experimental feature!) Function to execute (conda) terminal commands in a subprocess.
            The function should raise an exception if the command fails.
            **run_command** is ignored if **runtime_env** is `"currently-active"`.
        working_dir: (for debugging) directory to save any temporary files
            (model packages, conda environments, test summaries).
            Defaults to a temporary directory.
    """
    if runtime_env == "currently-active":
        rd = load_description_and_test(
            source,
            format_version=format_version,
            weight_format=weight_format,
            devices=devices,
            determinism=determinism,
            expected_type=expected_type,
            sha256=sha256,
            stop_early=stop_early,
            working_dir=working_dir,
            **deprecated,
        )
        return rd.validation_summary

    if runtime_env == "as-described":
        conda_env = None
    elif isinstance(runtime_env, (str, Path)):
        conda_env = BioimageioCondaEnv.model_validate(read_yaml(Path(runtime_env)))
    elif isinstance(runtime_env, BioimageioCondaEnv):
        conda_env = runtime_env
    else:
        assert_never(runtime_env)

    if run_command is not default_run_command:
        try:
            run_command(["thiscommandshouldalwaysfail", "please"])
        except Exception:
            pass
        else:
            raise RuntimeError(
                "given run_command does not raise an exception for a failing command"
            )

    verbose = working_dir is not None
    if working_dir is None:
        td_kwargs: Dict[str, Any] = (
            dict(ignore_cleanup_errors=True) if sys.version_info >= (3, 10) else {}
        )
        working_dir_ctxt = TemporaryDirectory(**td_kwargs)
    else:
        working_dir_ctxt = nullcontext(working_dir)

    with working_dir_ctxt as _d:
        working_dir = Path(_d)

        if isinstance(source, ResourceDescrBase):
            descr = source
        elif isinstance(source, dict):
            context = get_validation_context().replace(
                perform_io_checks=True  # make sure we perform io checks though
            )

            descr = build_description(source, context=context)
        else:
            descr = load_description(source, perform_io_checks=True)

        if isinstance(descr, InvalidDescr):
            return descr.validation_summary
        elif isinstance(source, (dict, ResourceDescrBase)):
            file_source = save_bioimageio_package(
                descr, output_path=working_dir / "package.zip"
            )
        else:
            file_source = source

        _test_in_env(
            file_source,
            descr=descr,
            working_dir=working_dir,
            weight_format=weight_format,
            conda_env=conda_env,
            devices=devices,
            determinism=determinism,
            expected_type=expected_type,
            sha256=sha256,
            stop_early=stop_early,
            run_command=run_command,
            verbose=verbose,
            **deprecated,
        )

    return descr.validation_summary

test_model ¤

test_model(source: Union[v0_4.ModelDescr, v0_5.ModelDescr, PermissiveFileSource], weight_format: Optional[SupportedWeightsFormat] = None, devices: Optional[List[str]] = None, *, determinism: Literal['seed_only', 'full'] = 'seed_only', sha256: Optional[Sha256] = None, stop_early: bool = True, **deprecated: Unpack[DeprecatedKwargs]) -> ValidationSummary

Test model inference

Source code in src/bioimageio/core/_resource_tests.py
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
def test_model(
    source: Union[v0_4.ModelDescr, v0_5.ModelDescr, PermissiveFileSource],
    weight_format: Optional[SupportedWeightsFormat] = None,
    devices: Optional[List[str]] = None,
    *,
    determinism: Literal["seed_only", "full"] = "seed_only",
    sha256: Optional[Sha256] = None,
    stop_early: bool = True,
    **deprecated: Unpack[DeprecatedKwargs],
) -> ValidationSummary:
    """Test model inference"""
    return test_description(
        source,
        weight_format=weight_format,
        devices=devices,
        determinism=determinism,
        expected_type="model",
        sha256=sha256,
        stop_early=stop_early,
        **deprecated,
    )