pyapp-kit / superqt

Missing widgets and components for Qt-python
https://pyapp-kit.github.io/superqt/
BSD 3-Clause "New" or "Revised" License
210 stars 38 forks source link

Add colormap combobox and utils #195

Closed tlambert03 closed 1 year ago

tlambert03 commented 1 year ago

this is a work-in-progress PR that will add two things:

  1. superqt.cmap.draw_colormap: the ability to draw any cmap recognized by the cmap library into any PaintDevice (i.e. QWidget, QPixmap, etc...)
  2. superqt.cmap.CmapCatalogComboBox A combobox to search/pick any colormap from the cmap catalog
  3. QColormapItemDelegate: a general purpose item delegate that can be reused in any QAbstractItemView that wants to represent a selection of colormaps
  4. QColormapLineEdit: a line edit that shows a colormap.
  5. QColormapComboBox: a combobox that displays a subset of cmaps (like the one in napari), and optionally lets the user pick more,

(note/reminder, cmap is a minimal dependency library that implements a colormapping API that also exports to native objects for many common python libraries like matplotlib, vispy, napari, etc...)

Example combo box that gives access to the full cmap library with text completion:

https://github.com/pyapp-kit/superqt/assets/1609449/727e10d7-1d6f-4d86-9e8a-8db629bff57b

style variant that puts the colormap to the left of the text:

Screenshot 2023-09-07 at 11 09 05 AM
codecov[bot] commented 1 year ago

Codecov Report

Patch coverage: 93.75% and project coverage change: +0.83% :tada:

Comparison is base (6993c88) 86.50% compared to head (c39bceb) 87.33%.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #195 +/- ## ========================================== + Coverage 86.50% 87.33% +0.83% ========================================== Files 37 44 +7 Lines 2824 3175 +351 ========================================== + Hits 2443 2773 +330 - Misses 381 402 +21 ``` | [Files Changed](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit) | Coverage Δ | | |---|---|---| | [src/superqt/cmap/\_cmap\_combo.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvY21hcC9fY21hcF9jb21iby5weQ==) | `88.23% <88.23%> (ø)` | | | [src/superqt/cmap/\_catalog\_combo.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvY21hcC9fY2F0YWxvZ19jb21iby5weQ==) | `90.00% <90.00%> (ø)` | | | [src/superqt/cmap/\_cmap\_line\_edit.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvY21hcC9fY21hcF9saW5lX2VkaXQucHk=) | `94.91% <94.91%> (ø)` | | | [src/superqt/cmap/\_cmap\_utils.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvY21hcC9fY21hcF91dGlscy5weQ==) | `98.41% <98.41%> (ø)` | | | [src/superqt/\_\_init\_\_.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvX19pbml0X18ucHk=) | `90.90% <100.00%> (+1.43%)` | :arrow_up: | | [src/superqt/cmap/\_\_init\_\_.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvY21hcC9fX2luaXRfXy5weQ==) | `100.00% <100.00%> (ø)` | | | [src/superqt/cmap/\_cmap\_item\_delegate.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvY21hcC9fY21hcF9pdGVtX2RlbGVnYXRlLnB5) | `100.00% <100.00%> (ø)` | | | [src/superqt/combobox/\_\_init\_\_.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvY29tYm9ib3gvX19pbml0X18ucHk=) | `100.00% <100.00%> (ø)` | | | [src/superqt/utils/\_\_init\_\_.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvdXRpbHMvX19pbml0X18ucHk=) | `100.00% <100.00%> (ø)` | | | [src/superqt/utils/\_img\_utils.py](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit#diff-c3JjL3N1cGVycXQvdXRpbHMvX2ltZ191dGlscy5weQ==) | `100.00% <100.00%> (ø)` | | ... and [1 file with indirect coverage changes](https://app.codecov.io/gh/pyapp-kit/superqt/pull/195/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyapp-kit)

:umbrella: View full report in Codecov by Sentry.

:loudspeaker: Have feedback on the report? Share it here.

Czaki commented 1 year ago

At first, looks nice. But it may be nice to allow exactly a specific set of colormap to select. Not one is predefined, and support colormaps are not defined in any set. (see https://github.com/napari/napari/pull/6102).

tlambert03 commented 1 year ago

But it may be nice to allow exactly a specific set of colormap to select. Not one is predefined, and support colormaps are not defined in any set. (see https://github.com/napari/napari/pull/6102).

it can already be added to the combobox, but it looks like the line edit itself is looking for a known name, I'll fix that:

Screen Shot 2023-09-08 at 7 16 27 AM
tlambert03 commented 1 year ago

note, you can add anything that is a recognized "colormap-like" object: https://cmap-docs.readthedocs.io/en/latest/colormaps/#colormaplike-objects

so it's extremely flexible

tlambert03 commented 1 year ago

ok, fixed... and if you wanted to give the new colormap a custom name, you can do so by passing a cmap.Colormap object:

Screen Shot 2023-09-08 at 7 26 47 AM
tlambert03 commented 1 year ago

and also, @Czaki ... if you're not familiar with cmap and it's goals, you can easily cast to any third part colormap (including napari):

from cmap import Colormap
from qtpy.QtWidgets import QApplication

from superqt import QColormapComboBox

app = QApplication([])
wdg = QColormapComboBox()
wdg.addColormaps([("#f0F", "#fdff00fF"), Colormap(("#230777",), name='MyMap')])
wdg.show()
wdg.currentColormapChanged.connect(lambda cm: print(cm.to_napari()))

app.exec()
Screen Shot 2023-09-08 at 7 30 01 AM

list of supported third party libs here

tlambert03 commented 1 year ago

i double checked to make sure that all the styles work in napari as well:

Screen Shot 2023-09-08 at 7 41 24 AM
aganders3 commented 1 year ago

This looks nice to me. One idea I have is an optional checkerboard background to make it more obvious where a colormap is transparent.

tlambert03 commented 1 year ago

One idea I have is an optional checkerboard background to make it more obvious where a colormap is transparent.

I like it! lemme see what I can do

tlambert03 commented 1 year ago

hows this @aganders3 ?

Screen Shot 2023-09-08 at 11 24 22 AM

edit ... just made the default a little smaller:

Screen Shot 2023-09-08 at 11 25 28 AM
aganders3 commented 1 year ago

That looks great! It might not look good on all backgrounds but I also wouldn't want to get too finicky with configuration so on/off is probably good. Thanks!