careamics 0.0.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- careamics/__init__.py +24 -0
- careamics/careamist.py +961 -0
- careamics/cli/__init__.py +5 -0
- careamics/cli/conf.py +394 -0
- careamics/cli/main.py +234 -0
- careamics/cli/utils.py +27 -0
- careamics/config/__init__.py +66 -0
- careamics/config/algorithms/__init__.py +21 -0
- careamics/config/algorithms/care_algorithm_config.py +122 -0
- careamics/config/algorithms/hdn_algorithm_config.py +103 -0
- careamics/config/algorithms/microsplit_algorithm_config.py +103 -0
- careamics/config/algorithms/n2n_algorithm_config.py +115 -0
- careamics/config/algorithms/n2v_algorithm_config.py +296 -0
- careamics/config/algorithms/pn2v_algorithm_config.py +301 -0
- careamics/config/algorithms/unet_algorithm_config.py +91 -0
- careamics/config/algorithms/vae_algorithm_config.py +178 -0
- careamics/config/architectures/__init__.py +7 -0
- careamics/config/architectures/architecture_config.py +37 -0
- careamics/config/architectures/lvae_config.py +262 -0
- careamics/config/architectures/unet_config.py +125 -0
- careamics/config/configuration.py +367 -0
- careamics/config/configuration_factories.py +2400 -0
- careamics/config/data/__init__.py +27 -0
- careamics/config/data/data_config.py +472 -0
- careamics/config/data/inference_config.py +237 -0
- careamics/config/data/ng_data_config.py +1038 -0
- careamics/config/data/patch_filter/__init__.py +15 -0
- careamics/config/data/patch_filter/filter_config.py +16 -0
- careamics/config/data/patch_filter/mask_filter_config.py +17 -0
- careamics/config/data/patch_filter/max_filter_config.py +15 -0
- careamics/config/data/patch_filter/meanstd_filter_config.py +18 -0
- careamics/config/data/patch_filter/shannon_filter_config.py +15 -0
- careamics/config/data/patching_strategies/__init__.py +15 -0
- careamics/config/data/patching_strategies/_overlapping_patched_config.py +102 -0
- careamics/config/data/patching_strategies/_patched_config.py +56 -0
- careamics/config/data/patching_strategies/random_patching_config.py +45 -0
- careamics/config/data/patching_strategies/sequential_patching_config.py +25 -0
- careamics/config/data/patching_strategies/tiled_patching_config.py +40 -0
- careamics/config/data/patching_strategies/whole_patching_config.py +12 -0
- careamics/config/data/tile_information.py +65 -0
- careamics/config/lightning/__init__.py +15 -0
- careamics/config/lightning/callbacks/__init__.py +8 -0
- careamics/config/lightning/callbacks/callback_config.py +116 -0
- careamics/config/lightning/optimizer_configs.py +186 -0
- careamics/config/lightning/training_config.py +70 -0
- careamics/config/losses/__init__.py +8 -0
- careamics/config/losses/loss_config.py +60 -0
- careamics/config/ng_configs/__init__.py +5 -0
- careamics/config/ng_configs/n2v_configuration.py +64 -0
- careamics/config/ng_configs/ng_configuration.py +256 -0
- careamics/config/ng_factories/__init__.py +9 -0
- careamics/config/ng_factories/algorithm_factory.py +120 -0
- careamics/config/ng_factories/data_factory.py +154 -0
- careamics/config/ng_factories/n2v_factory.py +256 -0
- careamics/config/ng_factories/training_factory.py +69 -0
- careamics/config/noise_model/__init__.py +12 -0
- careamics/config/noise_model/likelihood_config.py +60 -0
- careamics/config/noise_model/noise_model_config.py +149 -0
- careamics/config/support/__init__.py +31 -0
- careamics/config/support/supported_activations.py +27 -0
- careamics/config/support/supported_algorithms.py +40 -0
- careamics/config/support/supported_architectures.py +13 -0
- careamics/config/support/supported_data.py +122 -0
- careamics/config/support/supported_filters.py +17 -0
- careamics/config/support/supported_loggers.py +10 -0
- careamics/config/support/supported_losses.py +32 -0
- careamics/config/support/supported_optimizers.py +57 -0
- careamics/config/support/supported_patching_strategies.py +22 -0
- careamics/config/support/supported_pixel_manipulations.py +15 -0
- careamics/config/support/supported_struct_axis.py +21 -0
- careamics/config/support/supported_transforms.py +12 -0
- careamics/config/transformations/__init__.py +22 -0
- careamics/config/transformations/n2v_manipulate_config.py +79 -0
- careamics/config/transformations/normalize_config.py +59 -0
- careamics/config/transformations/transform_config.py +45 -0
- careamics/config/transformations/transform_unions.py +29 -0
- careamics/config/transformations/xy_flip_config.py +43 -0
- careamics/config/transformations/xy_random_rotate90_config.py +35 -0
- careamics/config/utils/__init__.py +8 -0
- careamics/config/utils/configuration_io.py +85 -0
- careamics/config/validators/__init__.py +18 -0
- careamics/config/validators/axes_validators.py +90 -0
- careamics/config/validators/model_validators.py +84 -0
- careamics/config/validators/patch_validators.py +55 -0
- careamics/conftest.py +39 -0
- careamics/dataset/__init__.py +17 -0
- careamics/dataset/dataset_utils/__init__.py +19 -0
- careamics/dataset/dataset_utils/dataset_utils.py +118 -0
- careamics/dataset/dataset_utils/file_utils.py +141 -0
- careamics/dataset/dataset_utils/iterate_over_files.py +84 -0
- careamics/dataset/dataset_utils/running_stats.py +189 -0
- careamics/dataset/in_memory_dataset.py +303 -0
- careamics/dataset/in_memory_pred_dataset.py +88 -0
- careamics/dataset/in_memory_tiled_pred_dataset.py +131 -0
- careamics/dataset/iterable_dataset.py +294 -0
- careamics/dataset/iterable_pred_dataset.py +121 -0
- careamics/dataset/iterable_tiled_pred_dataset.py +141 -0
- careamics/dataset/patching/__init__.py +1 -0
- careamics/dataset/patching/patching.py +300 -0
- careamics/dataset/patching/random_patching.py +110 -0
- careamics/dataset/patching/sequential_patching.py +212 -0
- careamics/dataset/patching/validate_patch_dimension.py +64 -0
- careamics/dataset/tiling/__init__.py +10 -0
- careamics/dataset/tiling/collate_tiles.py +33 -0
- careamics/dataset/tiling/lvae_tiled_patching.py +375 -0
- careamics/dataset/tiling/tiled_patching.py +166 -0
- careamics/dataset_ng/README.md +212 -0
- careamics/dataset_ng/__init__.py +0 -0
- careamics/dataset_ng/dataset.py +365 -0
- careamics/dataset_ng/demos/bsd68_demo.ipynb +361 -0
- careamics/dataset_ng/demos/bsd68_zarr_demo.ipynb +453 -0
- careamics/dataset_ng/demos/care_U2OS_demo.ipynb +330 -0
- careamics/dataset_ng/demos/demo_custom_image_stack.ipynb +736 -0
- careamics/dataset_ng/demos/demo_datamodule.ipynb +447 -0
- careamics/dataset_ng/demos/demo_dataset.ipynb +278 -0
- careamics/dataset_ng/demos/demo_patch_extractor.py +51 -0
- careamics/dataset_ng/demos/mouse_nuclei_demo.ipynb +293 -0
- careamics/dataset_ng/factory.py +180 -0
- careamics/dataset_ng/grouped_index_sampler.py +73 -0
- careamics/dataset_ng/image_stack/__init__.py +14 -0
- careamics/dataset_ng/image_stack/czi_image_stack.py +396 -0
- careamics/dataset_ng/image_stack/file_image_stack.py +140 -0
- careamics/dataset_ng/image_stack/image_stack_protocol.py +93 -0
- careamics/dataset_ng/image_stack/image_utils/__init__.py +6 -0
- careamics/dataset_ng/image_stack/image_utils/image_stack_utils.py +125 -0
- careamics/dataset_ng/image_stack/in_memory_image_stack.py +93 -0
- careamics/dataset_ng/image_stack/zarr_image_stack.py +170 -0
- careamics/dataset_ng/image_stack_loader/__init__.py +19 -0
- careamics/dataset_ng/image_stack_loader/image_stack_loader_protocol.py +70 -0
- careamics/dataset_ng/image_stack_loader/image_stack_loaders.py +273 -0
- careamics/dataset_ng/image_stack_loader/zarr_utils.py +130 -0
- careamics/dataset_ng/legacy_interoperability.py +175 -0
- careamics/dataset_ng/microsplit_input_synth.py +377 -0
- careamics/dataset_ng/patch_extractor/__init__.py +7 -0
- careamics/dataset_ng/patch_extractor/limit_file_extractor.py +50 -0
- careamics/dataset_ng/patch_extractor/patch_construction.py +151 -0
- careamics/dataset_ng/patch_extractor/patch_extractor.py +117 -0
- careamics/dataset_ng/patch_filter/__init__.py +20 -0
- careamics/dataset_ng/patch_filter/coordinate_filter_protocol.py +27 -0
- careamics/dataset_ng/patch_filter/filter_factory.py +95 -0
- careamics/dataset_ng/patch_filter/mask_filter.py +96 -0
- careamics/dataset_ng/patch_filter/max_filter.py +188 -0
- careamics/dataset_ng/patch_filter/mean_std_filter.py +218 -0
- careamics/dataset_ng/patch_filter/patch_filter_protocol.py +50 -0
- careamics/dataset_ng/patch_filter/shannon_filter.py +188 -0
- careamics/dataset_ng/patching_strategies/__init__.py +26 -0
- careamics/dataset_ng/patching_strategies/patching_strategy_factory.py +50 -0
- careamics/dataset_ng/patching_strategies/patching_strategy_protocol.py +161 -0
- careamics/dataset_ng/patching_strategies/random_patching.py +393 -0
- careamics/dataset_ng/patching_strategies/sequential_patching.py +99 -0
- careamics/dataset_ng/patching_strategies/tiling_strategy.py +207 -0
- careamics/dataset_ng/patching_strategies/whole_sample.py +61 -0
- careamics/file_io/__init__.py +15 -0
- careamics/file_io/read/__init__.py +11 -0
- careamics/file_io/read/get_func.py +57 -0
- careamics/file_io/read/tiff.py +58 -0
- careamics/file_io/write/__init__.py +15 -0
- careamics/file_io/write/get_func.py +63 -0
- careamics/file_io/write/tiff.py +40 -0
- careamics/lightning/__init__.py +32 -0
- careamics/lightning/callbacks/__init__.py +13 -0
- careamics/lightning/callbacks/data_stats_callback.py +33 -0
- careamics/lightning/callbacks/hyperparameters_callback.py +49 -0
- careamics/lightning/callbacks/prediction_writer_callback/__init__.py +20 -0
- careamics/lightning/callbacks/prediction_writer_callback/file_path_utils.py +56 -0
- careamics/lightning/callbacks/prediction_writer_callback/prediction_writer_callback.py +234 -0
- careamics/lightning/callbacks/prediction_writer_callback/write_strategy.py +399 -0
- careamics/lightning/callbacks/prediction_writer_callback/write_strategy_factory.py +215 -0
- careamics/lightning/callbacks/progress_bar_callback.py +90 -0
- careamics/lightning/dataset_ng/__init__.py +1 -0
- careamics/lightning/dataset_ng/callbacks/__init__.py +1 -0
- careamics/lightning/dataset_ng/callbacks/prediction_writer/__init__.py +29 -0
- careamics/lightning/dataset_ng/callbacks/prediction_writer/cached_tiles_strategy.py +164 -0
- careamics/lightning/dataset_ng/callbacks/prediction_writer/file_path_utils.py +33 -0
- careamics/lightning/dataset_ng/callbacks/prediction_writer/prediction_writer_callback.py +219 -0
- careamics/lightning/dataset_ng/callbacks/prediction_writer/write_image_strategy.py +91 -0
- careamics/lightning/dataset_ng/callbacks/prediction_writer/write_strategy.py +27 -0
- careamics/lightning/dataset_ng/callbacks/prediction_writer/write_strategy_factory.py +214 -0
- careamics/lightning/dataset_ng/callbacks/prediction_writer/write_tiles_zarr_strategy.py +375 -0
- careamics/lightning/dataset_ng/data_module.py +529 -0
- careamics/lightning/dataset_ng/data_module_utils.py +395 -0
- careamics/lightning/dataset_ng/lightning_modules/__init__.py +9 -0
- careamics/lightning/dataset_ng/lightning_modules/care_module.py +97 -0
- careamics/lightning/dataset_ng/lightning_modules/n2v_module.py +106 -0
- careamics/lightning/dataset_ng/lightning_modules/unet_module.py +221 -0
- careamics/lightning/dataset_ng/prediction/__init__.py +16 -0
- careamics/lightning/dataset_ng/prediction/convert_prediction.py +198 -0
- careamics/lightning/dataset_ng/prediction/stitch_prediction.py +171 -0
- careamics/lightning/lightning_module.py +914 -0
- careamics/lightning/microsplit_data_module.py +632 -0
- careamics/lightning/predict_data_module.py +341 -0
- careamics/lightning/train_data_module.py +666 -0
- careamics/losses/__init__.py +21 -0
- careamics/losses/fcn/__init__.py +1 -0
- careamics/losses/fcn/losses.py +125 -0
- careamics/losses/loss_factory.py +80 -0
- careamics/losses/lvae/__init__.py +1 -0
- careamics/losses/lvae/loss_utils.py +83 -0
- careamics/losses/lvae/losses.py +589 -0
- careamics/lvae_training/__init__.py +0 -0
- careamics/lvae_training/calibration.py +191 -0
- careamics/lvae_training/dataset/__init__.py +20 -0
- careamics/lvae_training/dataset/config.py +135 -0
- careamics/lvae_training/dataset/lc_dataset.py +274 -0
- careamics/lvae_training/dataset/ms_dataset_ref.py +1067 -0
- careamics/lvae_training/dataset/multich_dataset.py +1121 -0
- careamics/lvae_training/dataset/multicrop_dset.py +196 -0
- careamics/lvae_training/dataset/multifile_dataset.py +335 -0
- careamics/lvae_training/dataset/types.py +32 -0
- careamics/lvae_training/dataset/utils/__init__.py +0 -0
- careamics/lvae_training/dataset/utils/data_utils.py +114 -0
- careamics/lvae_training/dataset/utils/empty_patch_fetcher.py +65 -0
- careamics/lvae_training/dataset/utils/index_manager.py +491 -0
- careamics/lvae_training/dataset/utils/index_switcher.py +165 -0
- careamics/lvae_training/eval_utils.py +987 -0
- careamics/lvae_training/get_config.py +84 -0
- careamics/lvae_training/lightning_module.py +701 -0
- careamics/lvae_training/metrics.py +214 -0
- careamics/lvae_training/train_lvae.py +342 -0
- careamics/lvae_training/train_utils.py +121 -0
- careamics/model_io/__init__.py +7 -0
- careamics/model_io/bioimage/__init__.py +11 -0
- careamics/model_io/bioimage/_readme_factory.py +113 -0
- careamics/model_io/bioimage/bioimage_utils.py +56 -0
- careamics/model_io/bioimage/cover_factory.py +171 -0
- careamics/model_io/bioimage/model_description.py +341 -0
- careamics/model_io/bmz_io.py +251 -0
- careamics/model_io/model_io_utils.py +95 -0
- careamics/models/__init__.py +5 -0
- careamics/models/activation.py +40 -0
- careamics/models/layers.py +495 -0
- careamics/models/lvae/__init__.py +3 -0
- careamics/models/lvae/layers.py +1371 -0
- careamics/models/lvae/likelihoods.py +394 -0
- careamics/models/lvae/lvae.py +848 -0
- careamics/models/lvae/noise_models.py +738 -0
- careamics/models/lvae/stochastic.py +394 -0
- careamics/models/lvae/utils.py +404 -0
- careamics/models/model_factory.py +54 -0
- careamics/models/unet.py +449 -0
- careamics/nm_training_placeholder.py +203 -0
- careamics/prediction_utils/__init__.py +21 -0
- careamics/prediction_utils/lvae_prediction.py +158 -0
- careamics/prediction_utils/lvae_tiling_manager.py +362 -0
- careamics/prediction_utils/prediction_outputs.py +238 -0
- careamics/prediction_utils/stitch_prediction.py +193 -0
- careamics/py.typed +5 -0
- careamics/transforms/__init__.py +22 -0
- careamics/transforms/compose.py +173 -0
- careamics/transforms/n2v_manipulate.py +150 -0
- careamics/transforms/n2v_manipulate_torch.py +149 -0
- careamics/transforms/normalize.py +374 -0
- careamics/transforms/pixel_manipulation.py +406 -0
- careamics/transforms/pixel_manipulation_torch.py +388 -0
- careamics/transforms/struct_mask_parameters.py +20 -0
- careamics/transforms/transform.py +24 -0
- careamics/transforms/tta.py +88 -0
- careamics/transforms/xy_flip.py +131 -0
- careamics/transforms/xy_random_rotate90.py +108 -0
- careamics/utils/__init__.py +19 -0
- careamics/utils/autocorrelation.py +40 -0
- careamics/utils/base_enum.py +60 -0
- careamics/utils/context.py +67 -0
- careamics/utils/deprecation.py +63 -0
- careamics/utils/lightning_utils.py +71 -0
- careamics/utils/logging.py +323 -0
- careamics/utils/metrics.py +394 -0
- careamics/utils/path_utils.py +26 -0
- careamics/utils/plotting.py +76 -0
- careamics/utils/ram.py +15 -0
- careamics/utils/receptive_field.py +108 -0
- careamics/utils/serializers.py +62 -0
- careamics/utils/torch_utils.py +150 -0
- careamics/utils/version.py +38 -0
- careamics-0.0.19.dist-info/METADATA +80 -0
- careamics-0.0.19.dist-info/RECORD +279 -0
- careamics-0.0.19.dist-info/WHEEL +4 -0
- careamics-0.0.19.dist-info/entry_points.txt +2 -0
- careamics-0.0.19.dist-info/licenses/LICENSE +28 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from typing import Any, Protocol
|
|
3
|
+
|
|
4
|
+
from typing_extensions import ParamSpec
|
|
5
|
+
|
|
6
|
+
from careamics.utils import BaseEnum
|
|
7
|
+
|
|
8
|
+
from ..image_stack import GenericImageStack
|
|
9
|
+
|
|
10
|
+
P = ParamSpec("P")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SupportedDataDev(str, BaseEnum):
|
|
14
|
+
ZARR = "zarr"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ImageStackLoader(Protocol[P, GenericImageStack]):
|
|
18
|
+
"""
|
|
19
|
+
Protocol to define how `ImageStacks` should be loaded.
|
|
20
|
+
|
|
21
|
+
An `ImageStackLoader` is a callable that must take the `source` of the data as the
|
|
22
|
+
first argument, and the data `axes` as the second argument.
|
|
23
|
+
|
|
24
|
+
Additional `*args` and `**kwargs` are allowed, but they should only be used to
|
|
25
|
+
determine _how_ the data is loaded, not _what_ data is loaded. The `source`
|
|
26
|
+
argument has to wholly determine _what_ data is loaded, this is because,
|
|
27
|
+
downstream, both an input-source and a target-source have to be specified but they
|
|
28
|
+
will share `*args` and `**kwargs`.
|
|
29
|
+
|
|
30
|
+
An `ImageStackLoader` must return a sequence of the `ImageStack` class. This could
|
|
31
|
+
be a sequence of one of the existing concrete implementations, such as
|
|
32
|
+
`ZarrImageStack`, or a custom user defined `ImageStack`.
|
|
33
|
+
|
|
34
|
+
Example
|
|
35
|
+
-------
|
|
36
|
+
The following example demonstrates how an `ImageStackLoader` could be defined
|
|
37
|
+
for loading non-OME Zarr images. Returning a list of `ZarrImageStack` instances.
|
|
38
|
+
|
|
39
|
+
>>> from typing import TypedDict
|
|
40
|
+
|
|
41
|
+
>>> from zarr.storage import FsspecStore
|
|
42
|
+
|
|
43
|
+
>>> from careamics.config import DataConfig
|
|
44
|
+
>>> from careamics.dataset_ng.image_stack import ZarrImageStack
|
|
45
|
+
|
|
46
|
+
>>> # Define a zarr source
|
|
47
|
+
>>> # It encompasses multiple arguments that determine what data will be loaded
|
|
48
|
+
>>> class ZarrSource(TypedDict):
|
|
49
|
+
... store: FsspecStore
|
|
50
|
+
... data_paths: Sequence[str]
|
|
51
|
+
|
|
52
|
+
>>> def custom_image_stack_loader(
|
|
53
|
+
... source: ZarrSource, axes: str, *args, **kwargs
|
|
54
|
+
... ) -> list[ZarrImageStack]:
|
|
55
|
+
... image_stacks = [
|
|
56
|
+
... ZarrImageStack(store=source["store"], data_path=data_path, axes=axes)
|
|
57
|
+
... for data_path in source["data_paths"]
|
|
58
|
+
... ]
|
|
59
|
+
... return image_stacks
|
|
60
|
+
|
|
61
|
+
TODO: show example use in the `CAREamicsDataset`
|
|
62
|
+
|
|
63
|
+
The example above defines a `ZarrSource` dict because to determine _which_ ZARR
|
|
64
|
+
images will be loaded both a ZARR store and the internal data paths need to be
|
|
65
|
+
specified.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __call__(
|
|
69
|
+
self, source: Any, axes: str, *args: P.args, **kwargs: P.kwargs
|
|
70
|
+
) -> Sequence[GenericImageStack]: ...
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
4
|
+
|
|
5
|
+
import zarr
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from zarr.storage import StorePath
|
|
8
|
+
|
|
9
|
+
from careamics.config.validators import check_czi_axes_validity
|
|
10
|
+
from careamics.file_io import ReadFunc
|
|
11
|
+
|
|
12
|
+
from ..image_stack import (
|
|
13
|
+
FileImageStack,
|
|
14
|
+
InMemoryImageStack,
|
|
15
|
+
ZarrImageStack,
|
|
16
|
+
)
|
|
17
|
+
from ..image_stack.czi_image_stack import CziImageStack
|
|
18
|
+
from .zarr_utils import collect_arrays, decipher_zarr_uri, is_ome_zarr, is_valid_uri
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from careamics.file_io.read import ReadFunc
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def load_arrays(source: Sequence[NDArray[Any]], axes: str) -> list[InMemoryImageStack]:
|
|
25
|
+
"""
|
|
26
|
+
Load image stacks from a sequence of numpy arrays.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
source: sequence of numpy.ndarray
|
|
31
|
+
The source arrays of the data.
|
|
32
|
+
axes: str
|
|
33
|
+
The original axes of the data, must be a subset of "STCZYX".
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
list[InMemoryImageStack]
|
|
38
|
+
"""
|
|
39
|
+
return [InMemoryImageStack.from_array(data=array, axes=axes) for array in source]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# TIFF case
|
|
43
|
+
def load_tiffs(source: Sequence[Path], axes: str) -> list[InMemoryImageStack]:
|
|
44
|
+
"""
|
|
45
|
+
Load image stacks from a sequence of TIFF files.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
source: sequence of Path
|
|
50
|
+
The source files for the data.
|
|
51
|
+
axes: str
|
|
52
|
+
The original axes of the data, must be a subset of "STCZYX".
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
list[InMemoryImageStack]
|
|
57
|
+
"""
|
|
58
|
+
return [InMemoryImageStack.from_tiff(path=path, axes=axes) for path in source]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# TODO: better name
|
|
62
|
+
# iter Tiff
|
|
63
|
+
def load_iter_tiff(source: Sequence[Path], axes: str) -> list[FileImageStack]:
|
|
64
|
+
# TODO: better docs
|
|
65
|
+
"""
|
|
66
|
+
Load image stacks from a sequence of TIFF files.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
source: sequence of Path
|
|
71
|
+
The source files for the data.
|
|
72
|
+
axes: str
|
|
73
|
+
The original axes of the data, must be a subset of "STCZYX".
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
list[FileImageStack]
|
|
78
|
+
"""
|
|
79
|
+
return [FileImageStack.from_tiff(path=path, axes=axes) for path in source]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# Custom file type case (loaded into memory)
|
|
83
|
+
def load_custom_file(
|
|
84
|
+
source: Sequence[Path],
|
|
85
|
+
axes: str,
|
|
86
|
+
*,
|
|
87
|
+
read_func: ReadFunc,
|
|
88
|
+
read_kwargs: dict[str, Any],
|
|
89
|
+
) -> list[InMemoryImageStack]:
|
|
90
|
+
"""
|
|
91
|
+
Load image stacks from a sequence of files of a custom type.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
source: sequence of Path
|
|
96
|
+
The source files for the data.
|
|
97
|
+
axes: str
|
|
98
|
+
The original axes of the data, must be a subset of "STCZYX".
|
|
99
|
+
read_func : ReadFunc
|
|
100
|
+
A function to read the custom file type, see the `ReadFunc` protocol.
|
|
101
|
+
read_kwargs : dict of {str: Any}
|
|
102
|
+
Kwargs that will be passed to the custom `read_func`.
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
list[InMemoryImageStack]
|
|
107
|
+
"""
|
|
108
|
+
# TODO: lazy loading custom files
|
|
109
|
+
return [
|
|
110
|
+
InMemoryImageStack.from_custom_file_type(
|
|
111
|
+
path=path,
|
|
112
|
+
axes=axes,
|
|
113
|
+
read_func=read_func,
|
|
114
|
+
**read_kwargs,
|
|
115
|
+
)
|
|
116
|
+
for path in source
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def load_zarrs(
|
|
121
|
+
source: Sequence[str | Path | StorePath],
|
|
122
|
+
axes: str,
|
|
123
|
+
) -> list[ZarrImageStack]:
|
|
124
|
+
"""Create a list of ZarrImageStack from a sequence of zarr file paths or URIs.
|
|
125
|
+
|
|
126
|
+
File paths must point to a zarr store (ending with .zarr) and URIs must be in the
|
|
127
|
+
format "file://path/to/zarr_store.zarr/group/path/array_name".
|
|
128
|
+
|
|
129
|
+
If the zarr file is an OME-Zarr, the specified multiscale level will be used. Note
|
|
130
|
+
that OME-Zarrs are only supported when providing a path to the zarr store, not when
|
|
131
|
+
using a file URI. One can, however, provide a file URI to the specific resolution
|
|
132
|
+
array within the OME-Zarr.
|
|
133
|
+
|
|
134
|
+
Parameters
|
|
135
|
+
----------
|
|
136
|
+
source : sequence of str or Path
|
|
137
|
+
The source zarr file paths or URIs.
|
|
138
|
+
axes : str
|
|
139
|
+
The original axes of the data, must be a subset of "STCZYX".
|
|
140
|
+
|
|
141
|
+
Returns
|
|
142
|
+
-------
|
|
143
|
+
list of ZarrImageStack
|
|
144
|
+
A list of ZarrImageStack created from the sources.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
image_stacks: list[ZarrImageStack] = []
|
|
148
|
+
|
|
149
|
+
for data_source in source:
|
|
150
|
+
data_str = str(data_source)
|
|
151
|
+
|
|
152
|
+
# either a path to a zarr file or a uri "file://path/to/zarr/array_path"
|
|
153
|
+
if data_str.endswith(".zarr"):
|
|
154
|
+
zarr_group = zarr.open_group(data_str, mode="r")
|
|
155
|
+
|
|
156
|
+
# test if ome-zarr (minimum assumption of multiscales)
|
|
157
|
+
if is_ome_zarr(zarr_group):
|
|
158
|
+
# TODO placeholder for handling OME-Zarr
|
|
159
|
+
# - Need to potentially select multiscale level
|
|
160
|
+
# - Extract axes and compare with provided ones
|
|
161
|
+
raise NotImplementedError(
|
|
162
|
+
"OME-Zarr support is not yet implemented when providing a "
|
|
163
|
+
"path to the zarr store. Please provide a file URI to the "
|
|
164
|
+
"specific array within the OME-Zarr."
|
|
165
|
+
)
|
|
166
|
+
else:
|
|
167
|
+
# collect all arrays
|
|
168
|
+
array_paths = collect_arrays(zarr_group)
|
|
169
|
+
|
|
170
|
+
# sort names
|
|
171
|
+
array_paths.sort()
|
|
172
|
+
|
|
173
|
+
# instantiate image stacks
|
|
174
|
+
for array_path in array_paths:
|
|
175
|
+
image_stacks.append(
|
|
176
|
+
ZarrImageStack(group=zarr_group, data_path=array_path, axes=axes)
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
elif is_valid_uri(data_str):
|
|
180
|
+
# decipher the uri and open the group
|
|
181
|
+
store_path, parent_path, name = decipher_zarr_uri(data_str)
|
|
182
|
+
|
|
183
|
+
zarr_group = zarr.open_group(store_path, path=parent_path, mode="r")
|
|
184
|
+
content = zarr_group[name]
|
|
185
|
+
|
|
186
|
+
# assert if group or array
|
|
187
|
+
if isinstance(content, zarr.Group):
|
|
188
|
+
array_paths = collect_arrays(content)
|
|
189
|
+
|
|
190
|
+
# sort the names
|
|
191
|
+
array_paths.sort()
|
|
192
|
+
|
|
193
|
+
for array_path in array_paths:
|
|
194
|
+
image_stacks.append(
|
|
195
|
+
ZarrImageStack(group=content, data_path=array_path, axes=axes)
|
|
196
|
+
)
|
|
197
|
+
else:
|
|
198
|
+
if not isinstance(content, zarr.Array):
|
|
199
|
+
raise TypeError(
|
|
200
|
+
f"Content at '{data_str}' is neither a zarr.Group nor "
|
|
201
|
+
f"a zarr.Array."
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# create image stack from a single array
|
|
205
|
+
image_stacks.append(
|
|
206
|
+
ZarrImageStack(
|
|
207
|
+
group=zarr_group,
|
|
208
|
+
data_path=name,
|
|
209
|
+
axes=axes,
|
|
210
|
+
)
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
else:
|
|
214
|
+
raise ValueError(
|
|
215
|
+
f"Source '{data_source}' is neither a zarr file nor a file URI."
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
return image_stacks
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def load_czis(
|
|
222
|
+
source: Sequence[Path],
|
|
223
|
+
axes: str,
|
|
224
|
+
) -> list[CziImageStack]:
|
|
225
|
+
"""
|
|
226
|
+
Load CZI image stacks from a sequence of CZI files paths.
|
|
227
|
+
|
|
228
|
+
If the CZI files contain multiple scenes, one image stack will be created for
|
|
229
|
+
each scene.
|
|
230
|
+
|
|
231
|
+
Axes should be in the format "SC(Z/T)YX", where Z or T are optional, and S and C
|
|
232
|
+
can be singleton dimensions, but must be provided.
|
|
233
|
+
|
|
234
|
+
Parameters
|
|
235
|
+
----------
|
|
236
|
+
source: sequence of Path
|
|
237
|
+
The source files for the data.
|
|
238
|
+
axes: str
|
|
239
|
+
Specifies which axes of the data to use and how.
|
|
240
|
+
If this string ends with `"ZYX"` or `"TYX"`, the data will consist of 3-D
|
|
241
|
+
patches, using `Z` or `T` as third dimension, respectively.
|
|
242
|
+
If the string does not end with "ZYX", the data will consist of 2-D patches.
|
|
243
|
+
|
|
244
|
+
Returns
|
|
245
|
+
-------
|
|
246
|
+
list[CziImageStack]
|
|
247
|
+
|
|
248
|
+
Raises
|
|
249
|
+
------
|
|
250
|
+
ValueError
|
|
251
|
+
If the provided axes are not valid.
|
|
252
|
+
"""
|
|
253
|
+
if check_czi_axes_validity(axes) is False:
|
|
254
|
+
raise ValueError(
|
|
255
|
+
f"Provided axes '{axes}' are not valid. Axes must be in the `SC(Z/T)YX` "
|
|
256
|
+
f"format, where Z or T are optional, and S and C can be singleton "
|
|
257
|
+
f"dimensions, but must be provided."
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
depth_axis: Literal["none", "Z", "T"] = "none"
|
|
261
|
+
if axes.endswith("TYX"):
|
|
262
|
+
depth_axis = "T"
|
|
263
|
+
elif axes.endswith("ZYX"):
|
|
264
|
+
depth_axis = "Z"
|
|
265
|
+
|
|
266
|
+
image_stacks: list[CziImageStack] = []
|
|
267
|
+
for path in source:
|
|
268
|
+
scene_rectangles = CziImageStack.get_bounding_rectangles(path)
|
|
269
|
+
image_stacks.extend(
|
|
270
|
+
CziImageStack(path, scene=scene, depth_axis=depth_axis)
|
|
271
|
+
for scene in scene_rectangles.keys()
|
|
272
|
+
)
|
|
273
|
+
return image_stacks
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from urllib.parse import urlparse
|
|
4
|
+
|
|
5
|
+
import zarr
|
|
6
|
+
|
|
7
|
+
INPUT = str | Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def is_valid_uri(path: str | Path) -> bool:
|
|
11
|
+
"""
|
|
12
|
+
Check if a path is a valid URI.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
path : str | Path
|
|
17
|
+
The path to check.
|
|
18
|
+
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
21
|
+
bool
|
|
22
|
+
True if the path is valid URI, False otherwise.
|
|
23
|
+
"""
|
|
24
|
+
parsed = urlparse(str(path))
|
|
25
|
+
|
|
26
|
+
valid_schemes = {"file", "s3", "gs", "az", "https", "http", "zip"}
|
|
27
|
+
|
|
28
|
+
if parsed.scheme and parsed.scheme.lower() in valid_schemes:
|
|
29
|
+
return True
|
|
30
|
+
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def collect_arrays(zarr_group: zarr.Group) -> list[str]:
|
|
35
|
+
"""
|
|
36
|
+
Collect all arrays in a Zarr group into a list.
|
|
37
|
+
|
|
38
|
+
Only run on the first level of the group.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
zarr_group : zarr.Group
|
|
43
|
+
The Zarr group to collect arrays from.
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
listof str
|
|
48
|
+
A list of Zarr arrays contained in the group as relative path to the group.
|
|
49
|
+
"""
|
|
50
|
+
arrays: list[str] = []
|
|
51
|
+
|
|
52
|
+
for name in zarr_group.array_keys():
|
|
53
|
+
if isinstance(zarr_group[name], zarr.Array):
|
|
54
|
+
arrays.append(name)
|
|
55
|
+
|
|
56
|
+
if arrays == []:
|
|
57
|
+
warnings.warn(
|
|
58
|
+
f"No arrays found in zarr group at '{zarr_group.path}'.",
|
|
59
|
+
UserWarning,
|
|
60
|
+
stacklevel=2,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
return arrays
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def decipher_zarr_uri(source: str) -> tuple[str, str, str]:
|
|
67
|
+
"""Extract the zarr store path, group path and array path from a zarr source string.
|
|
68
|
+
|
|
69
|
+
The input string is expected to be in the format:
|
|
70
|
+
\"file://path/to/zarr_store.zarr/group/path/array_name\"
|
|
71
|
+
|
|
72
|
+
Note that the root folder of the zarr store must end with ".zarr".
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
source : str
|
|
77
|
+
The zarr source string.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
str
|
|
82
|
+
The path to the zarr store.
|
|
83
|
+
str
|
|
84
|
+
The parent group within the zarr store, if it is not the root, else "".
|
|
85
|
+
str
|
|
86
|
+
The group or array name the source is pointing to.
|
|
87
|
+
|
|
88
|
+
Raises
|
|
89
|
+
------
|
|
90
|
+
ValueError
|
|
91
|
+
If the source string does not start with "file://".
|
|
92
|
+
ValueError
|
|
93
|
+
If the source string does not contain a ".zarr" file extension.
|
|
94
|
+
"""
|
|
95
|
+
key = "file://"
|
|
96
|
+
|
|
97
|
+
if source[: len(key)] != key:
|
|
98
|
+
raise ValueError(f"Remote file not supported: {source}")
|
|
99
|
+
|
|
100
|
+
if ".zarr" not in source:
|
|
101
|
+
raise ValueError(f"No .zarr file extension found in source: {source}")
|
|
102
|
+
|
|
103
|
+
_source = source[len(key) :]
|
|
104
|
+
groups = _source.split("/")
|
|
105
|
+
|
|
106
|
+
# find .zarr entry
|
|
107
|
+
zarr_index = next((i for i, p in enumerate(groups) if p.endswith(".zarr")))
|
|
108
|
+
|
|
109
|
+
path_to_zarr = groups[: zarr_index + 1]
|
|
110
|
+
parent_path = groups[zarr_index + 1 : -1]
|
|
111
|
+
content_path = groups[-1]
|
|
112
|
+
|
|
113
|
+
return "/".join(path_to_zarr), "/".join(parent_path), content_path
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# TODO use yaozarrs models to validate OME-Zarr structure
|
|
117
|
+
def is_ome_zarr(zarr_group: zarr.Group) -> bool:
|
|
118
|
+
"""Check if a Zarr group is an OME-Zarr.
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
zarr_group : zarr.Group
|
|
123
|
+
The Zarr group to check.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
bool
|
|
128
|
+
True if the Zarr group is an OME-Zarr, False otherwise.
|
|
129
|
+
"""
|
|
130
|
+
return False
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A module for utility functions that adapts the new dataset outputs to work with previous
|
|
3
|
+
code until it is updated.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from collections.abc import Sequence
|
|
7
|
+
from typing import cast
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from numpy.typing import NDArray
|
|
11
|
+
|
|
12
|
+
from careamics.config.data.tile_information import TileInformation
|
|
13
|
+
from careamics.utils.deprecation import deprecated
|
|
14
|
+
|
|
15
|
+
from .dataset import ImageRegionData
|
|
16
|
+
from .patching_strategies import TileSpecs
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@deprecated(
|
|
20
|
+
"use careamics.lightning.dataset_ng.prediction functions instead for stitching and"
|
|
21
|
+
" combining predictions."
|
|
22
|
+
)
|
|
23
|
+
def imageregions_to_tileinfos(
|
|
24
|
+
image_regions: Sequence[ImageRegionData],
|
|
25
|
+
) -> list[tuple[NDArray, list[TileInformation]]]:
|
|
26
|
+
"""
|
|
27
|
+
Converts a series of `TileSpecs` dictionaries to `TileInformation` pydantic class.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
image_regions : sequence of ImageRegionData
|
|
32
|
+
A list of ImageRegionData, it must have an instance of `TileSpecs` as it's
|
|
33
|
+
`region_data` field.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
list of TileInformation
|
|
38
|
+
The converted tile information.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
tile_infos: list[TileInformation] = []
|
|
42
|
+
|
|
43
|
+
data = [image_region.data for image_region in image_regions]
|
|
44
|
+
tile_specs = [image_region.region_spec for image_region in image_regions]
|
|
45
|
+
|
|
46
|
+
data_indices: NDArray[np.int_] = np.array(
|
|
47
|
+
[tile_spec["data_idx"] for tile_spec in tile_specs], dtype=int
|
|
48
|
+
)
|
|
49
|
+
unique_data_indices = np.unique(data_indices)
|
|
50
|
+
# data_idx denotes which image stack a patch belongs to
|
|
51
|
+
# separate TileSpecs by image_stack
|
|
52
|
+
for data_idx in unique_data_indices:
|
|
53
|
+
# collect all ImageRegions
|
|
54
|
+
data_image_regions: list[ImageRegionData] = [
|
|
55
|
+
image_region
|
|
56
|
+
for image_region in image_regions
|
|
57
|
+
if image_region.region_spec["data_idx"] == data_idx
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
# --- find last indices
|
|
61
|
+
# make sure tiles belonging to the same sample are together
|
|
62
|
+
data_image_regions.sort(
|
|
63
|
+
key=lambda image_region: image_region.region_spec["sample_idx"]
|
|
64
|
+
)
|
|
65
|
+
sample_indices = np.array(
|
|
66
|
+
[
|
|
67
|
+
image_region.region_spec["sample_idx"]
|
|
68
|
+
for image_region in data_image_regions
|
|
69
|
+
]
|
|
70
|
+
)
|
|
71
|
+
# reverse array so indices returned are at far edge
|
|
72
|
+
_, unique_indices = np.unique(sample_indices[::-1], return_index=True)
|
|
73
|
+
# un reverse indices
|
|
74
|
+
last_indices = len(sample_indices) - 1 - unique_indices
|
|
75
|
+
|
|
76
|
+
# convert each ImageRegionData to tile_info
|
|
77
|
+
for i, image_region in enumerate(data_image_regions):
|
|
78
|
+
last_tile = i in last_indices
|
|
79
|
+
tile_info = _imageregion_to_tileinfo(image_region, last_tile)
|
|
80
|
+
tile_infos.append(tile_info)
|
|
81
|
+
|
|
82
|
+
return [
|
|
83
|
+
(data, [tile_info]) for data, tile_info in zip(data, tile_infos, strict=False)
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _imageregion_to_tileinfo(
|
|
88
|
+
image_region: ImageRegionData, last_tile: bool
|
|
89
|
+
) -> TileInformation:
|
|
90
|
+
"""
|
|
91
|
+
Convert a single `ImageRegionData` instance to a `TileInformation` instance. Whether
|
|
92
|
+
it is the last tile in a sequence needs to be supplied.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
image_region : ImageRegionData
|
|
97
|
+
An instance of `ImageRegionData`, it must have an instance of `TileSpecs` as
|
|
98
|
+
it's `region_data` field.
|
|
99
|
+
last_tile : bool
|
|
100
|
+
Whether a tile is the last tile in a sequence, for stitching.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
TileInformation
|
|
105
|
+
A tile information object.
|
|
106
|
+
|
|
107
|
+
Raises
|
|
108
|
+
------
|
|
109
|
+
KeyError
|
|
110
|
+
If `image_region.region_spec` does not contain the keys: {'crop_coords',
|
|
111
|
+
'crop_size', 'stitch_coords'}.
|
|
112
|
+
"""
|
|
113
|
+
patch_spec = image_region.region_spec
|
|
114
|
+
data_shape = image_region.data_shape
|
|
115
|
+
|
|
116
|
+
# TODO: In python 3.11 and greater, NamedTuples can inherit from Generic
|
|
117
|
+
# so we could do image_region: ImageRegionData[TileSpecs]
|
|
118
|
+
# and not have to do this check here + cast
|
|
119
|
+
# make sure image_region.region_spec is TileSpec
|
|
120
|
+
if (
|
|
121
|
+
("crop_coords" not in patch_spec)
|
|
122
|
+
or ("crop_size" not in patch_spec)
|
|
123
|
+
or ("stitch_coords" not in patch_spec)
|
|
124
|
+
):
|
|
125
|
+
raise KeyError(
|
|
126
|
+
"Could not find all keys: {'crop_coords', 'crop_size', 'stitch_coords'} in "
|
|
127
|
+
"`image_region.region_spec`."
|
|
128
|
+
)
|
|
129
|
+
tile_spec = cast(TileSpecs, patch_spec) # ugly cast for mypy
|
|
130
|
+
return _tilespec_to_tileinfo(tile_spec, data_shape, last_tile)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _tilespec_to_tileinfo(
|
|
134
|
+
tile_spec: TileSpecs, data_shape: Sequence[int], last_tile: bool
|
|
135
|
+
) -> TileInformation:
|
|
136
|
+
"""
|
|
137
|
+
Convert a single `TileSpec` to a `TileInformation`. Whether it is the last tile
|
|
138
|
+
needs to be supplied.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
tile_spec : TileSpecs
|
|
143
|
+
A tile spec dictionary.
|
|
144
|
+
data_shape : sequence of int
|
|
145
|
+
The original shape of the data the tile came from, labeling the dimensions of
|
|
146
|
+
axes SC(Z)YX.
|
|
147
|
+
last_tile : bool
|
|
148
|
+
Whether a tile is the last tile in a sequence, for stitching.
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
TileInformation
|
|
153
|
+
A tile information object.
|
|
154
|
+
"""
|
|
155
|
+
overlap_crop_coords = tuple(
|
|
156
|
+
(
|
|
157
|
+
tile_spec["crop_coords"][i],
|
|
158
|
+
tile_spec["crop_coords"][i] + tile_spec["crop_size"][i],
|
|
159
|
+
)
|
|
160
|
+
for i in range(len(tile_spec["crop_coords"]))
|
|
161
|
+
)
|
|
162
|
+
stitch_coords = tuple(
|
|
163
|
+
(
|
|
164
|
+
tile_spec["stitch_coords"][i],
|
|
165
|
+
tile_spec["stitch_coords"][i] + tile_spec["crop_size"][i],
|
|
166
|
+
)
|
|
167
|
+
for i in range(len(tile_spec["crop_coords"]))
|
|
168
|
+
)
|
|
169
|
+
return TileInformation(
|
|
170
|
+
array_shape=tuple(data_shape[1:]), # remove sample dimension
|
|
171
|
+
last_tile=last_tile,
|
|
172
|
+
overlap_crop_coords=overlap_crop_coords,
|
|
173
|
+
stitch_coords=stitch_coords,
|
|
174
|
+
sample_id=tile_spec["sample_idx"],
|
|
175
|
+
)
|