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

aicsimageio on Apple Silicon Macs #2

Open
evamaxfield opened this issue Apr 20, 2022 · 12 comments
Open

aicsimageio on Apple Silicon Macs #2

evamaxfield opened this issue Apr 20, 2022 · 12 comments

Comments

@evamaxfield
Copy link

evamaxfield commented Apr 20, 2022

Hey @petebankhead! 👋

Really enjoyed reading basically all of the Python sections of the book this morning! I honestly might pass this along to others that are interested in general image handling and not just microscopy image handling. It's a great Python intro to images in general!

On the file formats and dimensions and metadata section, I think you were having issues with installing aicsimageio on Apple Silicon; I am wondering when the last time you tried installing was because a couple of recent patches should have ironed out a lot of the issues with installing.

pip install --upgrade --force-reinstall --no-cache-dir aicsimageio should be a good check?

If there are still issues please let me know. Would love to get it working for you!

Thanks again

@petebankhead
Copy link
Contributor

Thanks! I tried it yesterday or the day before... but admittedly on a tight deadline, since I really wanted the book out before next week's QuPath webinar & hackathon....

It failed with

imagecodecs/_aec.c:697:10: fatal error: 'libaec.h' file not found

I have the feeling all the Python stuff needs a big revision when I get around to it, and maybe embrace aicsimagio from the beginning - it looks a fantastic project. Sorry the first version doesn't properly reflect that!

@evamaxfield
Copy link
Author

evamaxfield commented Apr 20, 2022

I have the feeling all the Python stuff needs a big revision when I get around to it, and maybe embrace aicsimagio from the beginning - it looks a fantastic project. Sorry the first version doesn't properly reflect that!

No worries at all! It turns out that simply reading images turns out to be a large issue (even just installing!) so I understand 😂

Seems like it's an error with imagecodecs and not aicsimageio (yay?) but still, from my recollection we just needed to install an older version of imagecodecs ahead of time?

So maybe for M1 macs I should add documentation to the aicsimageio README that specifies to do:

pip install imagecodecs==2021.4.28
pip install aicsimageio

From my search on imagecodecs install issues:
https://stackoverflow.com/questions/67907014/install-imagecodecs-on-mac-big-sur
cgohlke/imagecodecs#6

@evamaxfield
Copy link
Author

evamaxfield commented Apr 20, 2022

Also, please dont feel pressure to try that now -- prep for the webinar and hackathon haha. We can come back to this whenever you have the time

@petebankhead
Copy link
Contributor

Ah, that sounds familiar - I think pip install imagecodecs==2021.4.28 was the one thing I did try, but then it failed with

  clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O2 -Wall -fPIC -O2 -isystem /Users/petebankhead/miniconda3/envs/jupyter-book/include -arch arm64 -fPIC -O2 -isystem /Users/petebankhead/miniconda3/envs/jupyter-book/include -arch arm64 -Iimagecodecs -I/Users/petebankhead/miniconda3/envs/jupyter-book/include/python3.10 -I/Users/petebankhead/miniconda3/envs/jupyter-book/lib/python3.10/site-packages/numpy/core/include -c imagecodecs/_aec.c -o build/temp.macosx-11.1-arm64-3.10/imagecodecs/_aec.o
  In file included from imagecodecs/_aec.c:708:
  In file included from /Users/petebankhead/miniconda3/envs/jupyter-book/lib/python3.10/site-packages/numpy/core/include/numpy/arrayobject.h:4:
  In file included from /Users/petebankhead/miniconda3/envs/jupyter-book/lib/python3.10/site-packages/numpy/core/include/numpy/ndarrayobject.h:12:
  In file included from /Users/petebankhead/miniconda3/envs/jupyter-book/lib/python3.10/site-packages/numpy/core/include/numpy/ndarraytypes.h:1969:
  /Users/petebankhead/miniconda3/envs/jupyter-book/lib/python3.10/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: "Using deprecated NumPy API, disable it with "          "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-W#warnings]
  #warning "Using deprecated NumPy API, disable it with " \
   ^
  imagecodecs/_aec.c:718:10: fatal error: 'libaec.h' file not found
  #include "libaec.h"
           ^~~~~~~~~~
  1 warning and 1 error generated.
  error: command '/usr/bin/clang' failed with exit code 1

At that point I bailed out, for fear of making such a mess of requirements.txt that I wouldn't get it working on mybinder... and I was reluctant to switch to conda at this point.

I'll give it a proper go in a couple of weeks though. Thanks again!

@psobolewskiPhD
Copy link

yeah imagecodecs is a pain via pip because it has some many compiled library depends. You'd need to go whack-a-mole with brew to get 'em all.
Thankfully, it's on conda-forge so you can just install that way.

petebankhead added a commit to petebankhead/bioimagebook.github.io that referenced this issue Jun 3, 2023
Introduce AICSImageIO and compare its use with imageio.v3.
Inspired by bioimagebook#2
@petebankhead
Copy link
Contributor

Thanks @evamaxfield and @psobolewskiPhD - I finally got around to making the switch to conda-forge and have updated the book accordingly. AICSImageIO is wonderful, I expect to be using a lot from now on :)

I've updated the notebook on pixel sizes as dimensions (and a few other bits) to include it now. Since I was discovering AICSImageIO while writing about it, I may well have made mistakes or missed some crucial stuff - please let me know if you would like to change anything :)

I'll close the issue, but feel free to add comments or reopen if there's more to do. Thanks again!

@psobolewskiPhD
Copy link

psobolewskiPhD commented Jun 3, 2023

@petebankhead
The book is awesome.
Just a thought, in the AICSImageIO section, there is the consideration of the extra dimensions and what they may be:

We can see the number of pixels are the same, but there are some extra ‘singleton’ dimensions stuck into the results from AICSImageIO (i.e. with length 1).

I personally find that getting the xarray info is much more useful than the raw numpy—if we're already using AICSImageIO, then maybe it makes sense to leverage this?
For that same image:

In [8]: image.xarray_data
Out[8]: 
<xarray.DataArray (T: 1, C: 5, Z: 1, Y: 512, X: 512)>
array([[[[[ 575,  576,  507, ...,  530,  578,  575],
          [ 627,  562,  537, ...,  497,  501,  575],
          [ 595,  581,  558, ...,  590,  520,  502],
          ...,
          [ 546,  563,  585, ...,  624,  590,  735],
          [ 702,  676,  588, ...,  649,  619,  641],
          [ 594,  638,  662, ...,  782,  668,  619]]],


        [[[ 569,  581,  617, ...,  588,  546,  557],
          [ 572,  584,  596, ...,  579,  571,  568],
          [ 564,  590,  587, ...,  586,  597,  600],
          ...,
          [ 599,  604,  623, ...,  608,  600,  591],
          [ 594,  636,  620, ...,  594,  589,  572],
          [ 652,  664,  639, ...,  607,  579,  583]]],


        [[[ 531,  547,  519, ...,  513,  507,  518],
          [ 535,  530,  545, ...,  511,  510,  514],
...
          [ 543,  588,  557, ...,  550,  543,  536],
          [ 621,  656,  647, ...,  536,  526,  528]]],


        [[[ 530,  561,  548, ...,  555,  561,  563],
          [ 553,  544,  541, ...,  567,  574,  533],
          [ 525,  555,  539, ...,  563,  551,  564],
          ...,
          [ 559,  565,  577, ...,  562,  552,  540],
          [ 573,  572,  589, ...,  561,  537,  546],
          [ 564,  601,  598, ...,  536,  535,  552]]],


        [[[1957, 2368, 2296, ..., 2884, 2914, 2952],
          [1923, 2261, 2293, ..., 2728, 2724, 2741],
          [1935, 2323, 2315, ..., 2693, 2639, 2646],
          ...,
          [2212, 2435, 2344, ..., 2637, 2564, 2563],
          [2167, 2500, 2412, ..., 2607, 2568, 2506],
          [2134, 2545, 2481, ..., 2558, 2495, 2455]]]]], dtype=uint16)
Coordinates:
  * C        (C) <U11 'Channel:0:0' 'Channel:0:1' ... 'Channel:0:4'
Dimensions without coordinates: T, Z, Y, X
Attributes:
    unprocessed:  {254: <FILETYPE.UNDEFINED: 0>, 256: 512, 257: 512, 258: 16,...
    processed:    ImageJ=1.44o\nimages=5\nchannels=5\nmode=color\nunit=um\nlo...

So now we know explicitly that the 5 is Channels and we have just 1 T and Z slice.
And squeezing is easy too:
image.xarray_data.squeeze()

(Also can segue to use xarray_dask_data at some point).

Or maybe this is all just too esoteric...

@petebankhead
Copy link
Contributor

Ah, I like it! Didn't know about this - I really need to do more pythoning and explore xarray

@evamaxfield
Copy link
Author

evamaxfield commented Jun 3, 2023

!!!! @petebankhead ❤️ this is so awesome to see!

Ya there are a lot of neat little things we have tried to build into AICSImageIO that are weird at first try (unfortunately 😅 hopefully we can make them better / more well documented as we go). One of my biggest reasons for writing it the way we did was in the get_image_data API.

As a research engineer I was always somewhat frustrated when scientists would hand me there code or ask me to help and to see:

img = "some numpy array with five dimensions"

# get the brightfield channel out
channel_0 = img[:, 0, :, :, :]

I just think that "assuming the right index to use" isn't as clean or as documentable as "using the channel information from metadata" (which could be wrong but is generally pretty good)

So I have always tried to get people to use the get_image_data API combined with other stuff

img = AICSImage()

# give me back a 3D array for JUST the brightfield channel
brightfield = img.get_image_data("ZYX", C=img.channel_names.index("brightfield"))

It's more verbose but that is sort of the point. It is verbose and legible AND potentially generalizes better because "regardless of what index the brightfield channel is, we can find it"

ANYWAY. Love to see this made it in and can't tell you how excited I am. Thanks!!

@evamaxfield
Copy link
Author

Also general note on the reason that "the channels dimension is separate from the samples dimension" its because there are some image file formats that allow multi-channel RGB images. where each channel has unique RGB data.

File formats are truly the wild west.

@petebankhead
Copy link
Contributor

This is excellent info, thanks!

I mostly do Java stuff, but I have a Python side project that I finally got to work on for a bit today - and after spending some hours playing around with AICSImageIO I'm converted :) xarray is great, and I especially like get_image_data.

I'll reopen this to remind myself to update the page with some more of this info.

Two small things I was missing (but might be too obscure to care about):

  1. Is there any way to read from a .zip file (other than via Bio-Formats), and/or from an in-memory byte array?
  2. Is there any way to handle image pyramids...?
    • I could do it using AICSImageIO + bioformats_jar + dask + a bit of extra logic to try to figure out if the different 'scenes' were really different resolutions... but I wasn't sure if there was an easier way

@evamaxfield
Copy link
Author

evamaxfield commented Jun 5, 2023

Is there any way to read from a .zip file (other than via Bio-Formats), and/or from an in-memory byte array?
It's possible with imageio, although the method is changing: https://imageio.readthedocs.io/en/stable/examples.html#reading-images-from-zip-archives

We used to allow in-memory byte strings / arrays in v3 iirc, but we moved off of it mainly because it was becoming very hard to maintain properly, annndd we really wanted to support were delayed/ chunked file reading and remote reading (from S3, Azure, etc.)

Is there any way to handle image pyramids...?

I could do it using AICSImageIO + bioformats_jar + dask + a bit of extra logic to try to figure out if the different 'scenes' were really different resolutions... but I wasn't sure if there was an easier way

not yet, its a long standing request but we just havent gotten around to it. I think there is going to be experimental support for it in the OmeZarrReader we just added but the API / plan hasn't been set for "all formats"

@petebankhead petebankhead reopened this Jun 5, 2023
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

3 participants