Skip to content

Commit 6d88e4a

Browse files
Adjusting tiffile versioning (#487)
* Adjusting tiffile versioning * Adding pinned version of tifffile for bfio * new tiff.series logic to mmstack in tifffile 2023.3.15 * removing codecov from setup.py * applying reshape for mmstack tiff images * removing dim overwrite from tiff_reader * override mmstack parser with is_mmstack=False in Tifffile * set default parser for tiff_glob_reader to is_mmstack=False * reverting tifffile versioning for bfio * changing range of tifffile version * removing non-bfio readers from bfio reader tests * pillow 9.5.0 breaks tests * comment on mmstack reading * Adjusting tiffile versioning * Adding pinned version of tifffile for bfio * new tiff.series logic to mmstack in tifffile 2023.3.15 * applying reshape for mmstack tiff images * removing dim overwrite from tiff_reader * override mmstack parser with is_mmstack=False in Tifffile * set default parser for tiff_glob_reader to is_mmstack=False * reverting tifffile versioning for bfio * changing range of tifffile version * removing non-bfio readers from bfio reader tests * pillow 9.5.0 breaks tests * comment on mmstack reading * pinning tifffile verison 9.4.0 * unpinning pillow, pinning imageio to 2.27.0
1 parent d4ae290 commit 6d88e4a

File tree

5 files changed

+29
-47
lines changed

5 files changed

+29
-47
lines changed

aicsimageio/readers/ome_tiff_reader.py

+5-13
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class OmeTiffReader(TiffReader):
3838
"""
3939
Wraps the tifffile and ome-types APIs to provide the same aicsimageio Reader
4040
API but for volumetric OME-TIFF images.
41-
4241
Parameters
4342
----------
4443
image: types.PathLike
@@ -56,12 +55,10 @@ class OmeTiffReader(TiffReader):
5655
fs_kwargs: Dict[str, Any]
5756
Any specific keyword arguments to pass down to the fsspec created filesystem.
5857
Default: {}
59-
6058
Notes
6159
-----
6260
If the OME metadata in your file isn't OME schema compilant or does not validate
6361
this will fail to read your file and raise an exception.
64-
6562
If the OME metadata in your file doesn't use the latest OME schema (2016-06),
6663
this reader will make a request to the referenced remote OME schema to validate.
6764
"""
@@ -82,6 +79,8 @@ def _is_supported_image(
8279
with fs.open(path) as open_resource:
8380
with TiffFile(open_resource) as tiff:
8481
# Get first page description (aka the description tag in general)
82+
# after Tifffile version 2023.3.15 mmstack images read all scenes
83+
# into tiff.pages[0]
8584
xml = tiff.pages[0].description
8685
ome = OmeTiffReader._get_ome(xml, clean_metadata)
8786

@@ -126,7 +125,6 @@ def _is_supported_image(
126125
def _guess_ome_dim_order(tiff: TiffFile, ome: OME, scene_index: int) -> List[str]:
127126
"""
128127
Guess the dimension order based on OME metadata and actual TIFF data.
129-
130128
Parameters
131129
-------
132130
tiff: TiffFile
@@ -135,7 +133,6 @@ def _guess_ome_dim_order(tiff: TiffFile, ome: OME, scene_index: int) -> List[str
135133
A constructed OME object to retrieve data from.
136134
scene_index: int
137135
The current operating scene index to pull metadata from.
138-
139136
Returns
140137
-------
141138
dims: List[str]
@@ -188,7 +185,7 @@ def __init__(
188185

189186
# Get ome-types object and warn of other behaviors
190187
with self._fs.open(self._path) as open_resource:
191-
with TiffFile(open_resource) as tiff:
188+
with TiffFile(open_resource, is_mmstack=False) as tiff:
192189
# Get and store OME
193190
self._ome = self._get_ome(
194191
tiff.pages[0].description, self.clean_metadata
@@ -299,21 +296,19 @@ def _general_data_array_constructor(
299296
def _read_delayed(self) -> xr.DataArray:
300297
"""
301298
Construct the delayed xarray DataArray object for the image.
302-
303299
Returns
304300
-------
305301
image: xr.DataArray
306302
The fully constructed and fully delayed image as a DataArray object.
307303
Metadata is attached in some cases as coords, dims, and attrs contains
308304
unprocessed tags and processed OME object.
309-
310305
Raises
311306
------
312307
exceptions.UnsupportedFileFormatError
313308
The file could not be read or is not supported.
314309
"""
315310
with self._fs.open(self._path) as open_resource:
316-
with TiffFile(open_resource) as tiff:
311+
with TiffFile(open_resource, is_mmstack=False) as tiff:
317312
# Get unprocessed metadata from tags
318313
tiff_tags = self._get_tiff_tags(tiff)
319314

@@ -346,21 +341,19 @@ def _read_delayed(self) -> xr.DataArray:
346341
def _read_immediate(self) -> xr.DataArray:
347342
"""
348343
Construct the in-memory xarray DataArray object for the image.
349-
350344
Returns
351345
-------
352346
image: xr.DataArray
353347
The fully constructed and fully read into memory image as a DataArray
354348
object. Metadata is attached in some cases as coords, dims, and attrs
355349
contains unprocessed tags and processed OME object.
356-
357350
Raises
358351
------
359352
exceptions.UnsupportedFileFormatError
360353
The file could not be read or is not supported.
361354
"""
362355
with self._fs.open(self._path) as open_resource:
363-
with TiffFile(open_resource) as tiff:
356+
with TiffFile(open_resource, is_mmstack=False) as tiff:
364357
# Get unprocessed metadata from tags
365358
tiff_tags = self._get_tiff_tags(tiff)
366359

@@ -397,7 +390,6 @@ def physical_pixel_sizes(self) -> PhysicalPixelSizes:
397390
sizes: PhysicalPixelSizes
398391
Using available metadata, the floats representing physical pixel sizes for
399392
dimensions Z, Y, and X.
400-
401393
Notes
402394
-----
403395
We currently do not handle unit attachment to these values. Please see the file

aicsimageio/readers/tiff_glob_reader.py

+11-5
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def _is_supported_image(
117117
) -> bool:
118118
try:
119119
with fs.open(path) as open_resource:
120-
with TiffFile(open_resource):
120+
with TiffFile(open_resource, is_mmstack=False):
121121
return True
122122

123123
except (TiffFileError, TypeError):
@@ -256,7 +256,7 @@ def indexer(x: str) -> pd.Series:
256256

257257
if single_file_shape is None:
258258
with self._fs.open(self._path) as open_resource:
259-
with TiffFile(open_resource) as tiff:
259+
with TiffFile(open_resource, is_mmstack=False) as tiff:
260260
self._single_file_shape = tiff.series[0].shape
261261

262262
else:
@@ -299,7 +299,9 @@ def _read_delayed(self) -> xr.DataArray:
299299
scene_files = scene_files.drop(self.scene_glob_character, axis=1)
300300
scene_nunique = scene_files.nunique()
301301

302-
tiff_tags = self._get_tiff_tags(TiffFile(scene_files.filename.iloc[0]))
302+
tiff_tags = self._get_tiff_tags(
303+
TiffFile(scene_files.filename.iloc[0], is_mmstack=False)
304+
)
303305

304306
group_dims = [
305307
x for x in scene_files.columns if x not in ["filename", *self.chunk_dims]
@@ -364,7 +366,9 @@ def _read_delayed(self) -> xr.DataArray:
364366
dims = list(expanded_blocks_sizes.keys())
365367

366368
else: # assemble array in a single chunk
367-
zarr_im = imread(scene_files.filename.tolist(), aszarr=True, level=0)
369+
zarr_im = imread(
370+
scene_files.filename.tolist(), aszarr=True, level=0, is_mmstack=False
371+
)
368372
darr = da.from_zarr(zarr_im).rechunk(-1)
369373
darr = darr.reshape(reshape_sizes)
370374
darr = darr.transpose(axes_order)
@@ -403,7 +407,9 @@ def _read_immediate(self) -> xr.DataArray:
403407
scene_files = scene_files.drop(self.scene_glob_character, axis=1)
404408
scene_nunique = scene_files.nunique()
405409

406-
tiff_tags = self._get_tiff_tags(TiffFile(scene_files.filename.iloc[0]))
410+
tiff_tags = self._get_tiff_tags(
411+
TiffFile(scene_files.filename.iloc[0], is_mmstack=False)
412+
)
407413

408414
chunk_sizes = self._get_chunk_sizes(scene_nunique)
409415

aicsimageio/readers/tiff_reader.py

+10-14
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class TiffReader(Reader):
3333
"""
3434
Wraps the tifffile API to provide the same aicsimageio Reader API but for
3535
volumetric Tiff (and other tifffile supported) images.
36-
3736
Parameters
3837
----------
3938
image: types.PathLike
@@ -127,7 +126,7 @@ def __init__(
127126
def scenes(self) -> Tuple[str, ...]:
128127
if self._scenes is None:
129128
with self._fs.open(self._path) as open_resource:
130-
with TiffFile(open_resource) as tiff:
129+
with TiffFile(open_resource, is_mmstack=False) as tiff:
131130
# This is non-metadata tiff, just use available series indices
132131
self._scenes = tuple(
133132
metadata_utils.generate_ome_image_id(i)
@@ -163,7 +162,6 @@ def _get_image_data(
163162
"""
164163
Open a file for reading, construct a Zarr store, select data, and compute to
165164
numpy.
166-
167165
Parameters
168166
----------
169167
fs: AbstractFileSystem
@@ -176,15 +174,19 @@ def _get_image_data(
176174
The image indices to retrieve.
177175
transpose_indices: List[int]
178176
The indices to transpose to prior to requesting data.
179-
180177
Returns
181178
-------
182179
chunk: np.ndarray
183180
The image chunk as a numpy array.
184181
"""
185182
with fs.open(path) as open_resource:
186183
with imread(
187-
open_resource, aszarr=True, series=scene, level=0, chunkmode="page"
184+
open_resource,
185+
aszarr=True,
186+
series=scene,
187+
level=0,
188+
chunkmode="page",
189+
is_mmstack=False,
188190
) as store:
189191
arr = da.from_zarr(store)
190192
arr = arr.transpose(transpose_indices)
@@ -335,15 +337,13 @@ def _create_dask_array(
335337
) -> da.Array:
336338
"""
337339
Creates a delayed dask array for the file.
338-
339340
Parameters
340341
----------
341342
tiff: TiffFile
342343
An open TiffFile for processing.
343344
selected_scene_dims_list: List[str]
344345
The dimensions to use for constructing the array with.
345346
Required for managing chunked vs non-chunked dimensions.
346-
347347
Returns
348348
-------
349349
image_data: da.Array
@@ -445,20 +445,18 @@ def _create_dask_array(
445445
def _read_delayed(self) -> xr.DataArray:
446446
"""
447447
Construct the delayed xarray DataArray object for the image.
448-
449448
Returns
450449
-------
451450
image: xr.DataArray
452451
The fully constructed and fully delayed image as a DataArray object.
453452
Metadata is attached in some cases as coords, dims, and attrs.
454-
455453
Raises
456454
------
457455
exceptions.UnsupportedFileFormatError
458456
The file could not be read or is not supported.
459457
"""
460458
with self._fs.open(self._path) as open_resource:
461-
with TiffFile(open_resource) as tiff:
459+
with TiffFile(open_resource, is_mmstack=False) as tiff:
462460
# Get dims from provided or guess
463461
dims = self._get_dims_for_scene(tiff)
464462

@@ -500,20 +498,18 @@ def _read_delayed(self) -> xr.DataArray:
500498
def _read_immediate(self) -> xr.DataArray:
501499
"""
502500
Construct the in-memory xarray DataArray object for the image.
503-
504501
Returns
505502
-------
506503
image: xr.DataArray
507504
The fully constructed and fully read into memory image as a DataArray
508505
object. Metadata is attached in some cases as coords, dims, and attrs.
509-
510506
Raises
511507
------
512508
exceptions.UnsupportedFileFormatError
513509
The file could not be read or is not supported.
514510
"""
515511
with self._fs.open(self._path) as open_resource:
516-
with TiffFile(open_resource) as tiff:
512+
with TiffFile(open_resource, is_mmstack=False) as tiff:
517513
# Get dims from provided or guess
518514
dims = self._get_dims_for_scene(tiff)
519515

@@ -581,7 +577,7 @@ def _get_pixel_size(
581577
) -> Tuple[Optional[float], Optional[float], Optional[float]]:
582578
"""Return the pixel size in microns (z,y,x) for the given series in a tiff path."""
583579

584-
with TiffFile(path_or_file) as tiff:
580+
with TiffFile(path_or_file, is_mmstack=False) as tiff:
585581
tags = tiff.series[series_index].pages[0].tags
586582

587583
if tiff.is_imagej:

aicsimageio/tests/readers/extra_readers/test_ome_tiled_tiff_reader.py

-12
Original file line numberDiff line numberDiff line change
@@ -214,22 +214,10 @@ def test_ome_tiff_reader_large_files(
214214
@pytest.mark.parametrize(
215215
"filename, expected_reader",
216216
[
217-
(
218-
"s_1_t_1_c_1_z_1.tiff",
219-
readers.TiffReader,
220-
),
221-
(
222-
"s_1_t_1_c_1_z_1.ome.tiff",
223-
readers.OmeTiffReader,
224-
),
225217
(
226218
"s_1_t_1_c_1_z_1_ome_tiff_tiles.ome.tif",
227219
readers.OmeTiledTiffReader,
228220
),
229-
( # Multiscene tiff
230-
"variable_scene_shape_first_scene_pyramid.ome.tiff",
231-
readers.OmeTiffReader,
232-
),
233221
],
234222
)
235223
def test_selected_tiff_reader(

setup.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def run(self):
3131
# "READER_TO_INSTALL" lookup table from aicsimageio/formats.py.
3232
format_libs: Dict[str, List[str]] = {
3333
"base-imageio": [
34-
"imageio[ffmpeg]>=2.11.0",
35-
"Pillow>=9.3",
34+
"imageio[ffmpeg]>=2.11.0,<2.28.0",
35+
"Pillow>=9.3.0",
3636
],
3737
"nd2": ["nd2[legacy]>=0.2.0"],
3838
"dv": ["mrc>=0.2.0"],
@@ -108,7 +108,7 @@ def run(self):
108108
"ome-zarr>=0.6.1",
109109
"wrapt>=1.12",
110110
"resource-backed-dask-array>=0.1.0",
111-
"tifffile>=2021.8.30,<2023.3.15",
111+
"tifffile>=2021.8.30",
112112
"xarray>=0.16.1,<2023.02.0",
113113
"xmlschema", # no pin because it's pulled in from OME types
114114
"zarr>=2.6,<3",

0 commit comments

Comments
 (0)