Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to import dimension with multiple indices #435

Closed
guiwitz opened this issue Sep 9, 2022 · 4 comments · Fixed by #438
Closed

Impossible to import dimension with multiple indices #435

guiwitz opened this issue Sep 9, 2022 · 4 comments · Fixed by #438
Assignees

Comments

@guiwitz
Copy link

guiwitz commented Sep 9, 2022

System and Software

  • aicsimageio Version: 4.9.2
  • Python Version: 3.8.13
  • Operating System: macOS 12.5.1 (arm64)

Description

Since the release of 4.9.2 it's apparently impossible to import multiple indices for a given dimension using the get_image_data method e.g. in im_aics.get_image_data('CYX', C=[0,1] , T=0, Z=0)

Expected Behavior

In 4.9.1. the example above would have generated an array of dimensions (2, n_pixX, n_pixY)

Reproduction

This creates an image with 2 time points and 3 channels. The reported dimensions when re-importing the file are correct:

>>> from aicsimageio.writers import OmeTiffWriter
>>> image = np.random.rand(2, 3,1024, 2048)
>>> OmeTiffWriter.save(image, "file.ome.tif", dim_order="TCYX")
>>> im_read = AICSImage('file.ome.tif')
>>> im_read.dims
<Dimensions [T: 2, C: 3, Z: 1, Y: 1024, X: 2048]>

However when trying to read e.g. two of the three channels, one gets:

>>> im_aics.get_image_data('CYX', C=[0,1] , T=0, Z=0)

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Input In [25], in <cell line: 1>()
----> 1 im_aics.get_image_data('CYX', C=[0,1] , T=0, Z=0)

File ~/mambaforge/envs/serial_cellv6/lib/python3.8/site-packages/aicsimageio/aics_image.py:714, in AICSImage.get_image_data(self, dimension_order_out, **kwargs)
    711     return self.data
    713 # Transform and return
--> 714 return transforms.reshape_data(
    715     data=self.data,
    716     given_dims=self.dims.order,
    717     return_dims=dimension_order_out,
    718     **kwargs,
    719 )

File ~/mambaforge/envs/serial_cellv6/lib/python3.8/site-packages/aicsimageio/transforms.py:260, in reshape_data(data, given_dims, return_dims, **kwargs)
    258 # Check that fixed integer request isn't outside of request
    259 if check_selection_max > data.shape[dim_index]:
--> 260     raise IndexError(
    261         f"Dimension specified with {dim}={display_dim_spec} "
    262         f"but Dimension shape is {data.shape[dim_index]}."
    263     )
    265 # All checks and operations passed, append dim operation to getitem ops
    266 dim_specs.append(dim_spec)

IndexError: Dimension specified with C=[0, 1] but Dimension shape is 1.

Environment

Any additional information about your environment

@evamaxfield
Copy link
Collaborator

evamaxfield commented Sep 9, 2022

Hey @guiwitz sorry you are encountering the issue. Unfortunately I cannot reproduce:
bash:

conda create --name aicsimageio-bugtest python=3.8.13 -y
conda activate aicsimageio-bugtest
pip install --no-cache-dir --force-reinstall aicsimageio==4.9.2
python

python:

from aicsimageio import AICSImage, writers
import numpy as np
image = np.random.rand(2, 3, 1024, 2048)
writers.OmeTiffWriter.save(image, "file.ome.tiff", dim_order="TCYX")
im_read = AICSImage("file.ome.tiff")
print(im_read.dims)
print(im_read.get_image_data("CYX", C=[0,1], T=0, Z=0).shape)

That all works for me and prints out what I expect.


That said, I am wondering if you are trying to read an OME TIFF or just a TIFF? If you are reading a TIFF (or an OME-TIFF with malformed metadata), then we use just the TIFF reader and try to guess the dims. In which case, I think what may be happening is that our guess is incorrect. If you add dim_order to the AICSImage init it should all work: AICSImage("file.tiff", dim_order="TCYX").

@guiwitz
Copy link
Author

guiwitz commented Sep 9, 2022

Hi @evamaxfield, you are absolutely right, I mixed things up and the minimal example above does actually work and my error came from a regular tiff, sorry!

However there's still a problem with imports, so let me come back to my original problem which lead to this wrong minimal example: what used to work before was passing a list with a single element for one of the dimensions e.g :

from aicsimageio.writers import OmeTiffWriter
import numpy as np

image = np.random.rand(2, 3,1024, 2048)
OmeTiffWriter.save(image, "file.ome.tif", dim_order="TCYX")
im_read = AICSImage('file.ome.tif')

im_read.get_image_data('CYX', C=[0] , T=0, Z=0).shape

In 4.9.1 this would generate an array of dimensions (1, n_pixX, n_pixY), and now in 4.9.2 I get:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [6], in <cell line: 1>()
----> 1 im_read.get_image_data('CYX', C=[0] , T=0, Z=0).shape

File ~/mambaforge/envs/serial_cellv6/lib/python3.8/site-packages/aicsimageio/aics_image.py:714, in AICSImage.get_image_data(self, dimension_order_out, **kwargs)
    711     return self.data
    713 # Transform and return
--> 714 return transforms.reshape_data(
    715     data=self.data,
    716     given_dims=self.dims.order,
    717     return_dims=dimension_order_out,
    718     **kwargs,
    719 )

File ~/mambaforge/envs/serial_cellv6/lib/python3.8/site-packages/aicsimageio/transforms.py:280, in reshape_data(data, given_dims, return_dims, **kwargs)
    277         data = data.reshape(*data.shape[:i], 1, *data.shape[i:])
    279 # Any extra dimensions have been removed, only a problem if the depth is > 1
--> 280 return transpose_to_dims(
    281     data, given_dims=new_dims, return_dims=return_dims
    282 )

File ~/mambaforge/envs/serial_cellv6/lib/python3.8/site-packages/aicsimageio/transforms.py:79, in transpose_to_dims(data, given_dims, return_dims)
     77 for dim in return_dims:
     78     transposer.append(match_map[dim])
---> 79 data = data.transpose(transposer)
     81 return data

ValueError: axes don't match array

I know that I could just pass this single index without the list, but I think it's cleaner to have the possibility to pass list of any size (including 1) and always return arrays with the same number of dimensions, including when one of these dimensions has as size of 1. So the old behaviour seemed more consistent.

@evamaxfield
Copy link
Collaborator

Sorry for the delay. The fix for this should be released in about an hour or so in v4.9.3

@guiwitz
Copy link
Author

guiwitz commented Nov 16, 2022

Great, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants