Closed evamaxfield closed 1 year ago
See #174 for more info.
This should be like scene 1 has shape (1, 2, 3, 4, 5) and scene 2 has shape (2, 3, 4, 5, 6)
Hey @sebi06 hoping I can pick your thoughts / knowledge of CZI files.
Is it possible to have a multi-scene pyramid CZI file? And if so what dimensions names are attached?
My mental model of a pyramid file was that each pyramid level basically acted as a different scene but that may be incorrect.
Can bfconvert
the existing RGB CZI from aicspylibczi test resources
Hi @JacksonMaxfield
I know that the scene concept is not really "super-easy" .... :-)
scene
basically is a TileRegion (any shape is possible) --> this is what we call a scene
The pyramid concept is something else for use. Let's focus on the 1st scene (S=0) from the example above:
Sidenote: When opening a CZI via BioFormats, BF (because of the limitations of OME-TIFF) somewhat "interprets" the pyramid levels of a individual scene as "BF Series"
Regarding the bfconvert question, I am not sure. But BF can read RGB CZIs with scenes for sure. But usually it gives you a 3CH image afterwards. So I would assume, yes this works.
What type of images with which dimensions do you need? I can get you basically everything with my "simulated microscope" or dig a bit insider our image storage. I am happy to help here.
Feel free to contact me or even ask for a call, if you need info about the CZI (sebastian.rhode@zeiss.com)
My mental model of a pyramid file was that each pyramid level basically acted as a different scene but that may be incorrect.
Seconding @zeissmicroscopy's https://github.com/AllenCellModeling/aicsimageio/issues/175#issuecomment-765418806, I think the concept of scenes/positions should be kept orthogonal to the concept of resolutions/pyramidal levels.
Using another public example (and another file format) from the Whole Slide Imaging domain, this public Leica SCN file from the OpenSlide project contains mutiple whole slide images acquired at separate positions where each position is itself a pyramid.
Sidenote: When opening a CZI via BioFormats, BF (because of the limitations of OME-TIFF) somewhat "interprets" the pyramid levels of a individual scene as "BF Series"
I think this will happen when the Bio-Formats API is set to flatten the resolutions. This was introduced during the early work on the multi-resolution and is still the default API mostly because changing it requires a breaking version increment. Calling setFlattenedResolutions(false)
should allow the reader to do the right thing i.e. map each scene as a Bio-Formats series and each pyramidal level as a resolution.
Is it possible to have a multi-scene pyramid CZI file? And if so what dimensions names are attached?
I have been quickly browsing through the public data available in IDR as several lightsheet studies have been submitted as Zeiss CZI files e.g. idr0038 or idr0077. However it looks like none of these are are both multi-position and pyramidal CZI files.
@zeissmicroscopy can I use the occasion to clarify a scenario in the use case of lightsheet data? In the example of https://idr.openmicroscopy.org/webclient/?show=image-9836847, the CZI file contains acquisitions at two different orientations of the sample. So these images are related to each other via a 3D transformation which includes a rotation. Are these also be included in the scenes
in the CZI vocabulary or is this another concept?
Thanks for the replies!
I think the concept of scenes/positions should be kept orthogonal to the concept of resolutions/pyramidal levels.
After this discussion, I totally agree. Now it will just be about how to expose these to the readers and writers of aicsimageio
.... We have already planned to talk about it in our next dev meeting :joy: My immediate thought would be that we mirror the planned 4.0 API and make level
stateful to the image container, i.e.:
img.levels # returns tuple of level ids specific to active scene
img.set_level("2x") # update current level for active scene
img.current_level # returns current level for active scene
Defaulting to level 0?
img.set_scene("Image:0")
img.levels # levels for scene 0
img.set_scene("Image:1")
img.levels # levels for scene 1
Fortunately, considering a proposal like this isn't a breaking change we could simply introduce this function in 4.1 instead of holding off on 4.0 even longer.
Calling
setFlattenedResolutions(false)
should allow the reader to do the right thing i.e. map each scene as a Bio-Formats series and each pyramidal level as a resolution.
Do you happen to know if this command is available in the CLI bfconvert
tool? My Java is a bit rusty...
the CZI file contains acquisitions at two different orientations of the sample. So these images are related to each other via a 3D transformation which includes a rotation.
I will let @zeissmicroscopy answer but my first thought would that that is the "Rotation" dimension that we have encountered in aicspylibczi
Hi @JacksonMaxfield
Fortunately, considering a proposal like this isn't a breaking change we could simply introduce this function in 4.1 instead of holding off on 4.0 even longer.
The resolution API as you drafted it above largely mirrors the way it is implemented in Bio-Formats - see IPyramidHandler so it makes sense to me. Do you have a rough idea for the ideal 4.0.0 timeline?
Do you happen to know if this command is available in the CLI bfconvert tool? My Java is a bit rusty...
Yes bfconvert -noflat
should ensure the resolution levels are not flattened during the conversion.
The resolution API as you drafted it above largely mirrors the way it is implemented in Bio-Formats - see IPyramidHandler so it makes sense to me.
Well that is wonderful to see. Will work with @AllenCellModeling/aicsimageio-core-devs to see if we need to do anything more than that (with Reader
changes accordingly).
Yes bfconvert -noflat should ensure the resolution levels are not flattened during the conversion.
Thank you so much! Will give this a quick go over the weekend just to get a feel for the data.
Do you have a rough idea for the ideal 4.0.0 timeline?
Oof. Well, I was originally planning and still aiming for the end of this month, ~Feb 2 would be ideal imo but likely looking like mid Feb. I really don't know as all of this is in my free time since I no longer work at AICS :sweat_smile:
A long and probably too-much-info version full rundown of what's left on the todo list:
CziReader
(requires aicspylibczi==3.0.0
, @heeler is there an update on that?) -- expect about a week of time to implementLifReader
(hoping to use readlif==0.4.0
to allow for mosaic LIFs, @nimne do you have a schedule for release?) -- expect about a week of time to implement, ~could also push reading mosaic LIFs to 4.1~ZarrReader
/ OmeZarrReader
-- "easy" considering da.from_zarr
and ome-zarr
lib already exist, planned for dev next week ArrayLikeReader
-- easy, likely done over this upcoming weekendWriters
module -- expect about a week to implement, planned for dev next weekmain
Cutting dev / beta releases:
dev_release0
planned as soon as: #185 is merged, needs a patch to numcodecs
. This release will include only functionality for DefaultReader
(imageio
), TiffReader
, OmeTiffReader
, and the AICSImage
object.dev_release1
planned for after ArrayLikeReader
and Writers
get added.dev_release2
planned for after ZarrReader
+ OmeZarrReader
get added.dev_release3
planned for after CziReader
+ LifReader
get added.4.0.0
planned for after above.This is also just a call to anyone reading this issue that if you want to see aicsimageio==4.0.0
faster, any help on the above list would be greatly appreciated. The active branch is feature/update-to-4.0-api
:pray: .
I'll push a 0.4.0 of readlif
this weekend (next day or two) - finishing up a few big projects today!
Hi all,
to my knowledge we use the following inside our CZI format:
Information CZI Dimension Characters:
- '0': 'Sample' # e.g. RGBA
- 'X': 'Width'
- 'Y': 'Height'
- 'C': 'Channel'
- 'Z': 'Slice'
- 'T': 'Time'
- 'R': 'Rotation'
- 'S': 'Scene' # contiguous regions of interest in a mosaic image (TileRegion)
- 'I': 'Illumination' # direction
- 'B': 'Block' # acquisition block form Multiblock experimente´s
- 'M': 'Mosaic' # index of single tiles from a TileRegion
- 'H': 'Phase' # e.g. Airy detector fibers
- 'V': 'View' # e.g. for SPIM
And this is orthogonal with the actual pyramid levels in case of larger Tileregions. I am just collecting some test CZI image. Would it be OK to share them with you via Dropbox?
I am just collecting some test CZI image. Would it be OK to share them with you via Dropbox?
Totally fine and would be much appreciated!
@JacksonMaxfield reaflif
0.4.0 with mosaic support is up on pypi! As far as I can tell, it works as expected. There are no image stitching utilities, but data access works.
Thanks @nimne! I will get started on LifReader
as soon as possible. I think because we at this point have (or plan to support) multiple readers that can return mosaic images, I may just write a utility function to stitch tiles together in this repo / pull it from aicspylibczi
so no worries there!
Thanks again. Really appreciate the work you put in :slightly_smiling_face:
Hi @JacksonMaxfield
here come the link to some CZI files:
https://www.dropbox.com/sh/1sbhwrnwsh6umf6/AADvad9sxC1luU70aC3t0a6na?dl=0
Please let me know, when you downloaded what you need.
Thanks @sebi06 I got the files all downloaded!
Cool. I also recommend to get the latest ZEN 3.3 (free download) to be able to see the CZI in their natural environment... 😉
A couple of updates and a couple of questions for everyone:
We have tentatively set a release schedule for 4.0! :tada: Full details can be found in the meeting minutes of #188, but in short, we aim to have 4.0 released ~ Feb 16.
We have agreed that handling pyramid levels makes sense and we want to do it with the API described above. Unfortunately, we will probably push it back to 4.1
. So in 4.0 you woulld likely be able to read pyramid files but the data will just be level=0
.
Hey @sebi06 we got some more questions (I'm so sorry)...
For our 4.0 API, one of the goals is to stitch back together the mosaic image prior to returning the data (See #163, #174). For large files, this is probably really bad, but this is where dask could come in handy with each tile of the mosaic being a single chunk of the array. Now the question: For mosaic images, we know that it is possible to have Scenes and mosaic tiles in the same image, i.e.: S: 3, M: 40, Y: 200, X: 200
-> "Three Scenes, each composed of a mosaic image of 40, 200x200 YX Tiles". But is it common to split mosaic images across Scenes? Or is our planned 4.0 API of scene being stateful still work for this behavior. i.e.:
img = AICSImage("my-mosaic.czi")
img.set_scene("Scene:0") # this the default but being explicit for the example
img.dask_data # returns a dask array of the fully reconstructed / stitched mosaic image from scene 0
img.set_scene("Scene:1") # change scene
img.dask_data # returns a dask array of the fully reconstructed / stitched mosaic image from scene 1
Expanding, would anyone ever want to create a mosaic using data from both / all Scenes at once?
Hi @JacksonMaxfield ,
no reason to be sorry if you have question. It is part of my job to answer those :-). I still think I did not explain the difference between scenes and tile well enough (but maybe I am wrong).
"... we know that it is possible to have Scenes and mosaic tiles in the same image ..."
If one created an image acquisition with a single position (1x1 tile) or any TileRegion, there will be automatically one scene. There is no way not to acquire scene, as soon as you have tiles etc. And yes, if one can have multiple scenes with arbitrary size inside one CZI. This is actually a quite common use case especially for slides, where people put several tissue sections one slide (TileRgeion of arbitrary size) and image all of them in on run. This will yield in a CZI with several scenes with different sizes.
I like the idea of using Dask for the tiles a lot. But maybe it is better to use
img.set_scene("0")
or img.set_scene(0)
because it might be easier to loop over those scenes without the need for a "complicated" string as an identifier?
"Expanding, would anyone ever want to create a mosaic using data from both / all Scenes at once?"
I would argue that this is a very unlikely use case and therefore I would drop this for now because the added value for a user is not big enough and it makes things complicated. In our ZEN software we have a slider for scenes, which allows to display individual scenes and cycle trough them. This slider can be deactivated and then ZEN shows all scenes in one image (one CZI) with the correct scale. But this view is just useful to get an overview and depending on the spatial dimensions not even useful. It is mainly useful for tissue slides, where there is a lot of "image" and little "empty space" between scenes.
But for example for wellplate this view is hard uses. Imagine one acquires a single image in every well. In this case it might look like below.
Therefore I think it is fine to not implement something that allows to combine all scenes at once in one array, especially not for the 1st release. Let's see what the feedback is, but also in my team we try to follow the rule of not implementing things because they might be needed ... :-) (unless it is crystal clear, that this will be required)
I would argue that this is a very unlikely use case and therefore I would drop this for now because the added value for a user is not big enough and it makes things complicated. In our ZEN software we have a slider for scenes, which allows to display individual scenes and cycle trough them.
This was exactly the answer I was hoping for. I think this basically sets us up nicely for mosaic support then :smile:
Therefore I think it is fine to not implement something that allows to combine all scenes at once in one array, especially not for the 1st release.
This is basically our idea too. If possible, we would like to generalize our stitching function but at the bare minimum just stitch one scene as that has consistent shape and dtype at least!
Answering your comment:
I like the idea of using Dask for the tiles a lot. But maybe it is better to use
img.set_scene("0")
orimg.set_scene(0)
because it might be easier to loop over those scenes without the need for a "complicated" string as an identifier?
Ahhh don't worry. We thought about that as well. We think going off of metadata named values for scenes makes the most sense because it allows for named specificity and not just integer indices. But, to solve this you could do something like:
for scene_id in img.scenes:
img.set_scene(scene_id)
img.dask_data # returns mosaic for this scene
Perfect. This looks cool to me. Once all this works we can collect feedback and see what makes sense. Obviously I already have a lot of ideas else would be useful. And in order to set the focus I think there a two clear use cases that can provide guidance.
One thing we should at least think of is the option to read a specific ROI / Tile of a dedicated scene, because one scene itself might be still very big.
One thing we should at least think of is the option to read a specific ROI / Tile of a dedicated scene, because one scene itself might be still very big.
Still possible. I didn't give you the full spec that we had thought of.
On the Reader
classes, CziReader
for example, would still have an M
dimension. On the AICSImage
object it would be merged. So if you really wanted just individual tiles you could simply go to the Reader
. We think that should work but not entirely sure how optimized we can make it speed / reading time wise. So will keep you updated.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.