any Mac M1/M2 silicon #python users here who use #pyqt ?

I'm wondering if pyqt6 can be installed with pip on a Mac M1/M2 or if we should recommend conda in our installation instructions. thanks for the help! #pyqtgraph #pyqt #gui

(also bothering @jni, maybe you know the answer to this? we're using qtpy so in theory any qt could be used)

@computingnature @jni Native ARM64 support has been around for a while now, I think it got added with Qt 6.2? I generally suggest folks stay away from the conda version of Qt unless the conda version addresses an issue that they have.

qtpy is just an abstraction layer between the different Qt bindings, it's not a Qt binding on its own.

@ogi also thanks so much for your work on pyqtgraph!

@computingnature oh I use qtpy for all my projects, and am considering using it as a dependency for #PyQtGraph (and phasing out our own abstraction layer), it allows for quickly shifting between bindings if I’m suspicious of a pyqt-binding issue.

But just to confirm, native arm64 wheels of PyQt bindings have been available since Qt supported native Arm64 support.

@computingnature

Also thank you for your recognition! Are you familiar with PyQtGraph and if so do you use it in your own work?

@ogi thanks, I did not realize this before, that's great. and yes we use #pyqtgraph in a bunch of projects, love how fast and flexible it is! #cellpose is our most popular software tool that uses it: https://github.com/MouseLand/cellpose
GitHub - MouseLand/cellpose: a generalist algorithm for cellular segmentation with human-in-the-loop capabilities

a generalist algorithm for cellular segmentation with human-in-the-loop capabilities - MouseLand/cellpose

GitHub

@computingnature 😍😍😍

Glad to hear it works well for you. One downside for maintaining a library is you constantly see problems/issues, so I appreciate folks sharing examples of the library working for them.

We’ve made in recent years significant image item performance improvements, depending on data dtype, LUT (number of entries or none at all), and the usage of levels. If you feel like you would benefit from better render performance please reach out and I can provide more guidance.

@computingnature @ogi if you can share, would love to know a bit more about the image data being rendered. Like the dtype, shape of the array, what size LUT are you using and if you’re using the “levels” functionality.
@computingnature @ogi reason I ask is that there are many different code paths for rendering ImageItems based on those attributes. We are trying to get a feel of which code paths are more common and if any of the less-optimized ones could use more development effort to speed up further.

@pyqtgraph @ogi thanks for asking for feedback :) I'm not sure if I'm using the levels functionality, here is how we use the standard ImageItem for the images of cells: https://github.com/MouseLand/cellpose/blob/be14e5f65c3d992ce2243b72b69fdad43e629507/cellpose/gui/gui.py#L1320

and then I made a custom version of ImageItem for drawing which is displayed on top of the cell image: https://github.com/MouseLand/cellpose/blob/be14e5f65c3d992ce2243b72b69fdad43e629507/cellpose/gui/guiparts.py#L497 (this is based on the Draw.py example: https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/examples/Draw.py)

this ImageDraw class does start to get slow for very large images (10k by 10k) but most of our users are not at that scale (or are not labeling by hand at that scale)

cellpose/cellpose/gui/gui.py at be14e5f65c3d992ce2243b72b69fdad43e629507 · MouseLand/cellpose

a generalist algorithm for cellular segmentation with human-in-the-loop capabilities - MouseLand/cellpose

GitHub

@computingnature @pyqtgraph

If you have a LUT, you need 4 things for pyqtgraph to give you the fastest rendering performance

* 1-channel image data ✅
* lut.shape[0] needs to be <= 256 ✅
* levels needs to be None ✅
* image.dtype == np.ubyte/np.uint8 (can't tell)

Relevant method for reference: https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/graphicsItems/ImageItem.py#L800

If that method returns a QImage instance, you get the fastest rendering Qt can give you, as PyQtGraph won't manipulate your data.

pyqtgraph/pyqtgraph/graphicsItems/ImageItem.py at master · pyqtgraph/pyqtgraph

Fast data visualization and GUI tools for scientific / engineering applications - pyqtgraph/pyqtgraph

GitHub

@computingnature @pyqtgraph

for your image draw, only thing I can suggest is to have your setImage call arguments conform in a way that _try_make_qimage method returns a QImage instance. Since the slowdown is in large sizes; and I assume you don't want to limit yourself to grayscale, would do a 256 (or less) element LUT, and a uint8 dtype image data, and see if that makes things better. If you are ok with grayscale, can probably get even better performance with uint8 data and no LUT.

@computingnature @pyqtgraph The other suggestion, but this would come with some code complexity; is to have a number of smaller image items, one for each segment a user has drawn, that way you could avoid having one large image, but the complexity costs may not be worth it.
@ogi @pyqtgraph thanks so much this is super helpful advice! I will let you know if I have any other questions. IIRC we are always using image.dtype == uint8
@computingnature @pyqtgraph If you're already using uint8 with that combination, there likely isn't much in the way of performance that #PyQtGraph can give you unless we figure out how to get our #OpenGL implementation faster (given the expertise of the currently active maintainers, this is unlikely to occur). Sounds like (except for the drawing image) the current setup is working well for you, which is great news! Love seeing the library used in the wild!