AllenCellModeling / aicsimageio

Image Reading, Metadata Conversion, and Image Writing for Microscopy Images in Python
https://allencellmodeling.github.io/aicsimageio
Other
204 stars 51 forks source link

Fully construct and return the mosaic image for CZI files #163

Closed snowformatics closed 3 years ago

snowformatics commented 3 years ago

Hi again,

I have a question regarding reading a CZI file. czifile.py library gives me the shape (2, 1, 10, 22800, 28960, 3) of my czi file. When I use aicsimageio I get this shape:

img = AICSImage('my.czi')

Shape: (1, 1, 3, 10, 1200, 1600)

I have two questions: 1) How to read the entire image and not only a part of it? 2) How to extract the number of scenes in the slide? 'S' refers to 1 but I have two scenes in the slide.

Thank you very much in advance

heeler commented 3 years ago

What can you tell us about the file?

Is it a mosaic file? If so you might be better off using aicspylibczi to access it.

It sounds like it might have pixeltype RGB as well but I'm guessing. I'm assuming you mean Gohlke's czifile.py. I believe he treats the RGB as Samples whereas I treat them as channels so the shape comes out somewhat different in the 2 implementations.

I don't know if you've found the docs pages yet but they can be helpful and we do try to make them informative. The default order is “STCZYX” for aicsimageio. It doesn't currently explain the handling of RGB images as in this case that's actually being done by aicspylibczi.

The .shape might be of use as well as the individual properties size_s size_z size_c etc.

To retrieve the data in one go using .data, assuming the shape of the data is consistent across channels (otherwise you have to specify the scene you want and deal with the 2 Scenes separately.

Hope this helps.

evamaxfield commented 3 years ago

Clarification on @heeler's comment:

The AICSImage object will only pull the Scene, Time, Channel, Z, Y, X dimensions from the reader. If your file has dimensions outside of those, use the base reader classes CziReader, OmeTiffReader, TiffReader, or DefaultReader.

In this case, it may be worth giving aicsimageio.readers.CziReader a try.

However, I do agree with @heeler, just based off shape alone. It looks like you have a BGR CZI file. aicsimageio doesn't support BGR files yet unfortunately.

evamaxfield commented 3 years ago

And, further expanding. @heeler made a great comment about "if your scenes are the same shape". If you have different shaped / sized scenes, you will need to specify which scene you want to read when you load the object.

img = AICSImage("my.czi", S=0) or img = AICSImage("my.czi", S=1) for example.

This process will be much easier to manage come release 4.0.

snowformatics commented 3 years ago

Thanks a lot for your comments. Indeed I am working with mosaic RGB files. I will try again as soon as release 4.0 is out, looking forward for it and thanks for offering this as open source library. A short comment, at least in my case it is not known before how many scenes are on a slide.

In case you need some beta testing on RGB files, just let me know.

heeler commented 3 years ago

If you are working with mosaic czi files I would suggest working with aicspylibczi directly. This is the library that does CZI reading for AICSImageIO but by dealing with it directly you'll get support to reassemble your mosaic files automatically. There is a function on the CziFile class defined in aicspylibczi called read_mosaic() that should give you the reassembled image. Hope this helps.

evamaxfield commented 3 years ago

So there is a lot to unpack in this single GitHub issue and it spawned a lot of great questions in our dev meeting.

  1. You are reading a multi-scene file
  2. You are reading a mosiac file
  3. You are reading an RGB file

  1. Multi-scene will be much better handled by aicsimageio==4.0.0
  2. We discussed the difference between czifile and aicsimageio and how czifile "reconstructs" the full mosaic image. Two things are happening here to cause the difference.
    • The AICSImage object only pulls the S, T, C, Z, Y, and X dimensions from the base CziReader. So while the CziReader will have an M dimension for "Mosaic tile", the AICSImage object is only pulling the first dimension (M=0) (i.e. the first / every tile is 1200, 1600 YX). But, this alone doesn't explain the behavior.
    • czifile is "reconstructing" the mosaic image into one large 22800, 28960 YX RGB plane where as our CziReader has the M dimension to select individual tiles, which may not be ideal. To resolve this, we can't say when, but we did discuss that at some point it would make sense to do this operation for the user just like czifile is doing. As @heeler said, you can use aicspylibczi.read_mosaic if you want the same functionality.
  3. RGB volumetric data is a doozy. Different standard amongst the formats. We know how we are going to better handle this and have made a decision for 4.0.

These are mostly just notes for us for later but also for you if you are curious. And to that end, I am going to leave this issue open until we put more thought or implementation into "reconstructing" the full mosaic image directly as functionality of aicsimageio.

evamaxfield commented 3 years ago

I have also changed the name of your issue to better reflect the current known issues with reading it.

toloudis commented 3 years ago

I'll just chime in here to say that we probably should change the aicsimageio czi reader to automatically reconstruct the full mosaic image, as default behavior. I'm not sure what that implies for chunked reads etc, and we might be relying on libCZI to be smart enough to handle that internally.

Once we know we are reading the full image, which we consider the main use case, we can then add some extra api (maybe already exists in aicspylibczi?) to get the individual mosaic tiles out for users who need that.

MosGeo commented 3 years ago

I will add my two cents here. I am currently reading a CZI file that is multichannel and is a mosiac. aicspylibczi is able to read the file perfectly as of 2.8.0 thanks to @heeler but I am thinking of using aicsimageio to utilize dask (my images are GBs in size).

Using the CziReader directly as suggested here results in reading the tiles dimensions but it seems to only read one channel. I am still investigating the issue. I will also try to create a simple example with the same characteristics to add to the tests in aicsimageioand aicspylibczi.

evamaxfield commented 3 years ago

Hey @MosGeo

Unfortunately aicsimageio 3.x doesn't support reading RGB / BGR CZI images. I would say your specific image of "BGR" + multichannel + mosaic is one we are actively trying to support in aicsimageio in the next release (4.x).

We aren't too far out for that to be honest, maybe a couple of weeks? But yea just know we don't support it yet. We are working on it!

evamaxfield commented 3 years ago

Related, in supporting those images, we are actually planning an aicspylibczi major release to its own 3.0.0 to make some changes to align with aicsimageio

MosGeo commented 3 years ago

@JacksonMaxfield Thanks for the update. This is awesome news. I look forward to aicsimageio 4 and aicspylibczi 3.

p.s. I have been looking at the source code of the project and you guys did a great job at laying the foundation. It is very accessible and clean. After I learn more and depending on my time commitments at the time,, I might be able to contribute if there are some small issues open.

evamaxfield commented 3 years ago

Thanks for the kind words. I personally think we have gotten even better about managing the codebase in 4.x too so hopefully it will be even easier to help out if you do end up having the time! :slightly_smiling_face:

evamaxfield commented 3 years ago

Hey @snowformatics @MosGeo it happened -- CZI mosaic file stitching is now in the 4.0 dev release! :tada:

from aicsimageio import AICSImage

img = AICSImage("tiled.czi")
img.data  # stitched numpy array
img.dask_data  # stitched dask array
# each chunk is a couple of tiles so can load portions of the image instead of the whole mosaic

img.reader.data  # unstitched numpy array (with 'M' dimension for tiles)
img.reader.dask_data  # unstitched dask array (with 'M' dimension for tiles)

If either of you have time and a desire to check it out, please do! The docs are live and the README has some details. The API has changed a decent bit from 3.* to 4.0 so please be aware of that.

To install: pip install aicsimageio --pre

If you have any issues please let us know by making a new GitHub issue!

snowformatics commented 3 years ago

That's awsome, thanks a lot for your efforts! I will test ASAP and give feedback!

MosGeo commented 3 years ago

@JacksonMaxfield Awesome! I will give it a go. Excited about V4. Also, already excited about V4.1 (specifically #140) as it will make it possible to make fast web image viewers with rest api.

p.s. Thanks for the merge for the small fix. This was my first official contribution to open source public repository where I am not the owner :)

evamaxfield commented 3 years ago

Awesome! I will give it a go. Excited about V4. Also, already excited about V4.1 (specifically #140) as it will make it possible to make fast web image viewers with rest api.

Zarr will be the best for that and things like viv already exist and are excellent. Highly recommend checking it out: https://github.com/hms-dbmi/viv

And awesome. I myself need to make more general open source contributions haha.