ngio 0.5.0b6__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.
Files changed (88) hide show
  1. ngio/__init__.py +69 -0
  2. ngio/common/__init__.py +28 -0
  3. ngio/common/_dimensions.py +335 -0
  4. ngio/common/_masking_roi.py +153 -0
  5. ngio/common/_pyramid.py +408 -0
  6. ngio/common/_roi.py +315 -0
  7. ngio/common/_synt_images_utils.py +101 -0
  8. ngio/common/_zoom.py +188 -0
  9. ngio/experimental/__init__.py +5 -0
  10. ngio/experimental/iterators/__init__.py +15 -0
  11. ngio/experimental/iterators/_abstract_iterator.py +390 -0
  12. ngio/experimental/iterators/_feature.py +189 -0
  13. ngio/experimental/iterators/_image_processing.py +130 -0
  14. ngio/experimental/iterators/_mappers.py +48 -0
  15. ngio/experimental/iterators/_rois_utils.py +126 -0
  16. ngio/experimental/iterators/_segmentation.py +235 -0
  17. ngio/hcs/__init__.py +19 -0
  18. ngio/hcs/_plate.py +1354 -0
  19. ngio/images/__init__.py +44 -0
  20. ngio/images/_abstract_image.py +967 -0
  21. ngio/images/_create_synt_container.py +132 -0
  22. ngio/images/_create_utils.py +423 -0
  23. ngio/images/_image.py +926 -0
  24. ngio/images/_label.py +411 -0
  25. ngio/images/_masked_image.py +531 -0
  26. ngio/images/_ome_zarr_container.py +1237 -0
  27. ngio/images/_table_ops.py +471 -0
  28. ngio/io_pipes/__init__.py +75 -0
  29. ngio/io_pipes/_io_pipes.py +361 -0
  30. ngio/io_pipes/_io_pipes_masked.py +488 -0
  31. ngio/io_pipes/_io_pipes_roi.py +146 -0
  32. ngio/io_pipes/_io_pipes_types.py +56 -0
  33. ngio/io_pipes/_match_shape.py +377 -0
  34. ngio/io_pipes/_ops_axes.py +344 -0
  35. ngio/io_pipes/_ops_slices.py +411 -0
  36. ngio/io_pipes/_ops_slices_utils.py +199 -0
  37. ngio/io_pipes/_ops_transforms.py +104 -0
  38. ngio/io_pipes/_zoom_transform.py +180 -0
  39. ngio/ome_zarr_meta/__init__.py +65 -0
  40. ngio/ome_zarr_meta/_meta_handlers.py +536 -0
  41. ngio/ome_zarr_meta/ngio_specs/__init__.py +77 -0
  42. ngio/ome_zarr_meta/ngio_specs/_axes.py +515 -0
  43. ngio/ome_zarr_meta/ngio_specs/_channels.py +462 -0
  44. ngio/ome_zarr_meta/ngio_specs/_dataset.py +89 -0
  45. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +539 -0
  46. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +438 -0
  47. ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +122 -0
  48. ngio/ome_zarr_meta/v04/__init__.py +27 -0
  49. ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
  50. ngio/ome_zarr_meta/v04/_v04_spec.py +473 -0
  51. ngio/ome_zarr_meta/v05/__init__.py +27 -0
  52. ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
  53. ngio/ome_zarr_meta/v05/_v05_spec.py +511 -0
  54. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
  55. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
  56. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
  57. ngio/resources/__init__.py +55 -0
  58. ngio/resources/resource_model.py +36 -0
  59. ngio/tables/__init__.py +43 -0
  60. ngio/tables/_abstract_table.py +270 -0
  61. ngio/tables/_tables_container.py +449 -0
  62. ngio/tables/backends/__init__.py +57 -0
  63. ngio/tables/backends/_abstract_backend.py +240 -0
  64. ngio/tables/backends/_anndata.py +139 -0
  65. ngio/tables/backends/_anndata_utils.py +90 -0
  66. ngio/tables/backends/_csv.py +19 -0
  67. ngio/tables/backends/_json.py +92 -0
  68. ngio/tables/backends/_parquet.py +19 -0
  69. ngio/tables/backends/_py_arrow_backends.py +222 -0
  70. ngio/tables/backends/_table_backends.py +226 -0
  71. ngio/tables/backends/_utils.py +608 -0
  72. ngio/tables/v1/__init__.py +23 -0
  73. ngio/tables/v1/_condition_table.py +71 -0
  74. ngio/tables/v1/_feature_table.py +125 -0
  75. ngio/tables/v1/_generic_table.py +49 -0
  76. ngio/tables/v1/_roi_table.py +575 -0
  77. ngio/transforms/__init__.py +5 -0
  78. ngio/transforms/_zoom.py +19 -0
  79. ngio/utils/__init__.py +45 -0
  80. ngio/utils/_cache.py +48 -0
  81. ngio/utils/_datasets.py +165 -0
  82. ngio/utils/_errors.py +37 -0
  83. ngio/utils/_fractal_fsspec_store.py +42 -0
  84. ngio/utils/_zarr_utils.py +534 -0
  85. ngio-0.5.0b6.dist-info/METADATA +148 -0
  86. ngio-0.5.0b6.dist-info/RECORD +88 -0
  87. ngio-0.5.0b6.dist-info/WHEEL +4 -0
  88. ngio-0.5.0b6.dist-info/licenses/LICENSE +28 -0
@@ -0,0 +1,165 @@
1
+ """Download testing OME-Zarr datasets."""
2
+
3
+ import shutil
4
+ from pathlib import Path
5
+ from typing import Literal
6
+
7
+ import pooch
8
+
9
+ from ngio.utils._errors import NgioValueError
10
+
11
+
12
+ class UnzipAndRename(pooch.Unzip):
13
+ """Unzip and rename the extracted directory."""
14
+
15
+ def __init__(
16
+ self,
17
+ extract_dir: str = "",
18
+ out_name: str = "ome-zarr.zarr",
19
+ re_unzip: bool = True,
20
+ **kwargs,
21
+ ):
22
+ super().__init__(extract_dir=extract_dir, **kwargs)
23
+ self.out_name = out_name
24
+ self.re_unzip = re_unzip
25
+
26
+ def output_file(self) -> Path:
27
+ """Return the output file path."""
28
+ if self.extract_dir is None:
29
+ raise NgioValueError("extract_dir must be set for UnzipAndRename.")
30
+
31
+ return Path(self.extract_dir) / self.out_name
32
+
33
+ def _extract_file(self, fname, extract_dir):
34
+ """Extract the file and rename it."""
35
+ output_path = self.output_file()
36
+ if output_path.exists() and not self.re_unzip:
37
+ # Nothing to do, the file already exists and we are not re-unzipping
38
+ return None
39
+
40
+ tmp_dir = Path(extract_dir) / "tmp"
41
+ # If tmp_dir exists, remove it
42
+ if tmp_dir.exists():
43
+ shutil.rmtree(tmp_dir, ignore_errors=True)
44
+ tmp_dir.mkdir(parents=True, exist_ok=True)
45
+
46
+ super()._extract_file(fname, tmp_dir)
47
+
48
+ list_extracted_dirs = tmp_dir.iterdir()
49
+ # Keep only if ends with .zarr
50
+ list_extracted_dirs = filter(
51
+ lambda x: x.name.endswith(".zarr"),
52
+ list_extracted_dirs,
53
+ )
54
+ list_extracted_dirs = list(list_extracted_dirs)
55
+ if len(list_extracted_dirs) != 1:
56
+ raise NgioValueError(
57
+ "Expected one directory to be extracted, "
58
+ f"got {len(list_extracted_dirs)}."
59
+ )
60
+
61
+ extracted_dir = list_extracted_dirs[0]
62
+ if output_path.exists():
63
+ shutil.rmtree(output_path, ignore_errors=True)
64
+
65
+ extracted_dir.rename(output_path)
66
+ # Clean up the temporary directory
67
+ shutil.rmtree(tmp_dir, ignore_errors=True)
68
+
69
+
70
+ _ome_zarr_zoo = {
71
+ "CardiomyocyteTiny": {
72
+ "url": "https://zenodo.org/records/13305156/files/20200812-CardiomyocyteDifferentiation14-Cycle1.zarr.zip",
73
+ "known_hash": "md5:efc21fe8d4ea3abab76226d8c166452c",
74
+ "fname": "20200812-CardiomyocyteDifferentiation14-Cycle1-tiny.zarr.zip",
75
+ "description": "Tiny cardiomyocyte dataset 3D (32MB).",
76
+ },
77
+ "CardiomyocyteTinyMip": {
78
+ "url": "https://zenodo.org/records/13305156/files/20200812-CardiomyocyteDifferentiation14-Cycle1_mip.zarr.zip",
79
+ "known_hash": "md5:51809479777cafbe9ac0f9fa5636aa95",
80
+ "fname": "20200812-CardiomyocyteDifferentiation14-Cycle1-tiny-mip.zarr.zip",
81
+ "description": "Tiny cardiomyocyte dataset 2D MIP (16.4MB).",
82
+ },
83
+ "CardiomyocyteSmall": {
84
+ "url": "https://zenodo.org/records/13305316/files/20200812-CardiomyocyteDifferentiation14-Cycle1.zarr.zip",
85
+ "known_hash": "md5:d5752ed4b72a9092a0290b3c04c0b9c2",
86
+ "fname": "20200812-CardiomyocyteDifferentiation14-Cycle1-small.zarr.zip",
87
+ "description": "Small cardiomyocyte dataset 3D (750MB).",
88
+ },
89
+ "CardiomyocyteSmallMip": {
90
+ "url": "https://zenodo.org/records/13305316/files/20200812-CardiomyocyteDifferentiation14-Cycle1_mip.zarr.zip",
91
+ "known_hash": "md5:3ed3ea898e0ed42d397da2e1dbe40750",
92
+ "fname": "20200812-CardiomyocyteDifferentiation14-Cycle1-small-mip.zarr.zip",
93
+ "description": "Small cardiomyocyte dataset 2D MIP (106MB).",
94
+ },
95
+ "CardiomyocyteMediumMip": {
96
+ "url": "https://zenodo.org/records/14826000/files/20200812-CardiomyocyteDifferentiation14-Cycle1_mip.zarr.zip",
97
+ "known_hash": "md5:3f932bbf7fc0577f58b97471707816a1",
98
+ "fname": "20200812-CardiomyocyteDifferentiation14-Cycle1_mip.zarr.zip",
99
+ "description": "Medium cardiomyocyte dataset 2D MIP (30GB).",
100
+ },
101
+ }
102
+
103
+ AVAILABLE_DATASETS = Literal[
104
+ "CardiomyocyteTiny",
105
+ "CardiomyocyteTinyMip",
106
+ "CardiomyocyteSmall",
107
+ "CardiomyocyteSmallMip",
108
+ "CardiomyocyteMediumMip",
109
+ ]
110
+
111
+
112
+ def list_ome_zarr_datasets() -> list[str]:
113
+ """List available OME-Zarr datasets."""
114
+ return list(_ome_zarr_zoo.keys())
115
+
116
+
117
+ def print_datasets_infos() -> None:
118
+ for dataset_name, dataset_info in _ome_zarr_zoo.items():
119
+ print(f"{dataset_name} - Description: {dataset_info['description']}")
120
+
121
+
122
+ def download_ome_zarr_dataset(
123
+ dataset_name: AVAILABLE_DATASETS | str,
124
+ download_dir: str | Path = "data",
125
+ re_unzip: bool = True,
126
+ progressbar: bool = False,
127
+ ) -> Path:
128
+ """Download an OME-Zarr dataset.
129
+
130
+ To list available datasets, use `list_ome_zarr_datasets`.
131
+
132
+ Args:
133
+ dataset_name (str): The dataset name.
134
+ download_dir (str): The download directory. Defaults to "data".
135
+ re_unzip (bool): If True, it will unzip the dataset even if it already exists.
136
+ progressbar (bool): If True, show a progress bar during download.
137
+ """
138
+ if dataset_name not in _ome_zarr_zoo:
139
+ raise NgioValueError(f"Dataset {dataset_name} not found in the OME-Zarr zoo.")
140
+ zenodo_infos = _ome_zarr_zoo[dataset_name]
141
+
142
+ fname = zenodo_infos["fname"]
143
+ zarrname = fname.replace(".zip", "")
144
+
145
+ processor = UnzipAndRename(
146
+ extract_dir="",
147
+ out_name=zarrname,
148
+ re_unzip=re_unzip,
149
+ )
150
+
151
+ pooch.retrieve(
152
+ url=zenodo_infos["url"],
153
+ known_hash=zenodo_infos["known_hash"],
154
+ fname=fname,
155
+ path=download_dir,
156
+ processor=processor,
157
+ progressbar=progressbar,
158
+ # Add User-Agent to avoid 403 errors from Zenodo
159
+ downloader=pooch.HTTPDownloader(
160
+ headers={
161
+ "User-Agent": f"pooch/{pooch.__version__} (https://github.com/BioVisionCenter/ngio)"
162
+ }
163
+ ),
164
+ )
165
+ return processor.output_file()
ngio/utils/_errors.py ADDED
@@ -0,0 +1,37 @@
1
+ # Create a generic error class for the NGFF project
2
+
3
+
4
+ class NgioError(Exception):
5
+ """Base class for all errors in the NGFF project."""
6
+
7
+ pass
8
+
9
+
10
+ class NgioFileNotFoundError(NgioError, FileNotFoundError):
11
+ """Error raised when a file is not found."""
12
+
13
+ pass
14
+
15
+
16
+ class NgioFileExistsError(NgioError, FileExistsError):
17
+ """Error raised when a file already exists."""
18
+
19
+ pass
20
+
21
+
22
+ class NgioValidationError(NgioError, ValueError):
23
+ """Generic error raised when a file does not pass validation."""
24
+
25
+ pass
26
+
27
+
28
+ class NgioTableValidationError(NgioError):
29
+ """Error raised when a table does not pass validation."""
30
+
31
+ pass
32
+
33
+
34
+ class NgioValueError(NgioError, ValueError):
35
+ """Error raised when a value does not pass a run time test."""
36
+
37
+ pass
@@ -0,0 +1,42 @@
1
+ import fsspec.implementations.http
2
+ from aiohttp import ClientResponseError
3
+
4
+ from ngio.utils import NgioValueError
5
+
6
+
7
+ def fractal_fsspec_store(
8
+ url: str, fractal_token: str | None = None, client_kwargs: dict | None = None
9
+ ) -> fsspec.mapping.FSMap:
10
+ """Simple function to get an http fsspec store from a url."""
11
+ client_kwargs = {} if client_kwargs is None else client_kwargs
12
+ if fractal_token is not None:
13
+ client_kwargs["headers"] = {"Authorization": f"Bearer {fractal_token}"}
14
+ fs = fsspec.implementations.http.HTTPFileSystem(client_kwargs=client_kwargs)
15
+
16
+ store = fs.get_mapper(url)
17
+
18
+ possible_keys = [".zgroup", ".zarray"]
19
+ for key in possible_keys:
20
+ try:
21
+ value = store.get(key)
22
+ if value is not None:
23
+ break
24
+ except ClientResponseError as e:
25
+ if e.status == 401 and fractal_token is None:
26
+ raise NgioValueError(
27
+ "No auto token is provided. You need a valid "
28
+ f"'fractal_token' to access: {url}."
29
+ ) from e
30
+ elif e.status == 401 and fractal_token is not None:
31
+ raise NgioValueError(
32
+ f"The 'fractal_token' provided is invalid for: {url}."
33
+ ) from e
34
+ else:
35
+ raise e
36
+ else:
37
+ raise NgioValueError(
38
+ f"Store {url} can not be read. Possible problems are: \n"
39
+ "- The url does not exist. \n"
40
+ "- The url is not a valid .zarr. \n"
41
+ )
42
+ return store