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

LifImage.as_array() fails for 4D image #59

Open
lanery opened this issue Dec 18, 2024 · 1 comment
Open

LifImage.as_array() fails for 4D image #59

lanery opened this issue Dec 18, 2024 · 1 comment

Comments

@lanery
Copy link

lanery commented Dec 18, 2024

Main issue

Trying to load a 4D (X, Y, Λ, t) LIF image as a numpy array failed.

Code that produced the issue

The file in question is 6 GB, so it's too large to upload here, but it was read in via:

from pathlib import Path
from readlif.reader import LifFile

lif_file = LifFile("filepath/to/4d_image.lif")
lif_image = lif_file.get_image_by_name("Lambda_time_series")

Check the number of "planes" in each dimension:

>>> lif_image.dims_n
{1: 512, 2: 512, 9: 60, 4: 99}

Try to get image data as a numpy array:

>>> lif_image.as_array()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[70], line 1
----> 1 lif_image.as_array()

File ~/Repositories/readlif/readlif/reader.py:484, in LifImage.as_array(self, dims)
    479 # multichannel image -- get planes recursively for each dimension
    480 array = [
    481     [self.get_plane(requested_dims={dim: i}) for i in range(self.dims_n[dim])]
    482     for dim in dims
    483 ]
--> 484 return np.array(array).squeeze()

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.

It fails because the as_array() method does not properly iterate over multiple dimensions.

@lanery
Copy link
Author

lanery commented Dec 18, 2024

Possible partial fix

Something along the lines of this:

from itertools import product

lif_image = lif_file.get_image_by_name("Lambda_time_series")
dimensions = [i for i in range(3, 10) if i in lif_image.dims_n.keys()]
shape = tuple(lif_image.dims_n.values())

plane_ranges = [range(lif_image.dims_n[dim]) for dim in dimensions]
planes = []
for plane_indices in product(*plane_ranges):
    requested_dims = {dim: i for dim, i in zip(dimensions, plane_indices, strict=True)}
    plane = lif_image.get_plane(requested_dims=requested_dims)
    planes.append(plane)

image = np.array(planes).reshape(shape[::-1])

The above code seems to get the dimensions of the numpy array correct, at least for this particular LIF image:

>>> image.shape
(99, 60, 512, 512)  # (t, Λ, Y, X)

But I'm not sure how well this holds in general without more testing.

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

No branches or pull requests

1 participant