Releases: napari/napari
0.4.19.post1
v0.4.19.post1 Add dummy release notes
0.4.19
napari 0.4.19
We're happy to announce the release of napari 0.4.19! napari is a fast, interactive, multi-dimensional image viewer for Python.
It's designed for browsing, annotating, and analyzing large multi-dimensional images. It's built on top of Qt (for the GUI), vispy (for performant GPU-based rendering), and the scientific Python stack (numpy, scipy).
For more information, examples, and documentation, please visit our website: https://napari.org/stable/
Highlights
This release mostly contains a lot of bug fixes and performance improvements. But look out for 0.5.0, coming to a software repository near you — we expect to release a lot of new features then!
BIG improvements to the Labels layer
#3308 closed many long-standing bugs in the handling of colors in the Labels layer: the color swatch in the Labels controls now always matches the color on the canvas, direct color mapping with thousands of colors works fine, and shuffling colors (when two touching labels coincidentally had the same color) is now much more likely to map them to different colors. 🎨🚀🚀🚀
Unfortunately, the fix turned out to have rather terrible consequences for the rendering performance of 3D Labels, and each time we fixed one thing something else reappeared in a game of bug fix whack-a-mole that any programmer would recognize. A great many fixes later (#6411, #6439, #6459, #6460, #6461, #6467, #6479, #6520, #6540, #6571, #6580, #6596, #6602, #6607, #6616, #6618) — thank you for your patience! 😅 — Labels are faster than ever and color accurate. But, to get the best performance, if you can use 8- or 16-bit integers as your data type, you should do so, and if not, you should install numba, a just-in-time compiler for numerical code in Python. (Ultimately, the data sent to the GPU will be 8- or 16-bit, so if you use a larger data type, you will pay some conversion cost.)
These improvements in color handling are accompanied by updates to the Labels API. You can now easily set a specific color cycle for Labels data. For example, to use the famous Glasbey look-up table/color cycle, you can combine the glasbey
Python package with the new CyclicLabelColormap
API:
import glasbey
from napari.utils.colormaps import CyclicLabelColormap
# ...
labels_layer = viewer.add_labels(
segmentation, colormap=CyclicLabelColormap(glasbey.create_palette(256))
)
See the "Deprecations" section below for more information on
the new API. (#6542)
More on colormaps!
Yes, this is the colors update! 🌈
Making image layers with linear colormaps using custom colors is easier than ever! You can just do viewer.add_image(data, color='turquoise')
to get a black-to-turquoise linear colormap for that image. For the full list of colors available, see the VisPy color dict (#6102). You can also pass in an RGB hex color prefixed with #
, as in napari.imshow(data, colormap=
#88ff1a)
.
(For an amusing side note, though, check out the API Changes note related to this PR. 😅)
Some technical stuff
If you were worried about those pesky "public access to qt_viewer
will be removed" warnings, fret not! Its removal has been postponed until at least 0.6.0! We want to spend more time working with the community to ensure your use case is supported before pulling out the rug. 🤝 If you are using the qt_viewer
because we don't have another public API to do what you need, please raise an issue so we can make sure your use case is supported before we remove it. (#6283)
Finally, although we still use pydantic 1.0 objects internally, napari installs correctly with both pydantic v1 and pydantic v2. If you wanted to upgrade your napari library or plugin to use Pydantic 2, now you can!
Note though, for 0.4.19, the napari bundled app still ships with Pydantic 1.x. However, we will bundle v2 starting with 0.5.0, so if you use Pydantic internally, now is a good time to check that you are compatible either v2 or both v1 and v2 (#6358).
Onwards!
As always, napari is developed by the community, for the community. We want to hear from you and help you get your napari visualization and/or plugin use done faster! And if napari is missing something you need, we can help you add it! So please remember to ask questions on image.sc, join our Zulip chat room, come to our community meetings, or tag us on Mastodon!
Read on for the full list of changes that went into this release.
New Features
- Add show_debug notification (napari/napari#5101)
- Automatic recognition of hex colour strings in layer data (napari/napari#6102)
Improvements
- Bump vispy to 0.13 (napari/napari#6025)
- Extend "No Qt bindings found" error message with details about conda (napari/napari#6095)
- Implement direct color calculation in shaders for Labels auto color mode (napari/napari#6179)
- Update "toggle ndview" text (napari/napari#6192)
- Add collision check when set colors for labels layer (napari/napari#6193)
- Add numpy as
np
to console predefined variables (napari/napari#6314) - Pydantic 2 compatibility using
pydantic.v1
(napari/napari#6358)
Performance
- Use a shader for low discrepancy label conversion (napari/napari#3308)
- Fix lagging 3d view for big data in auto color mode (napari/napari#6411)
- Fix cycle in _update_draw/_set_highlight for Points and Shapes (high CPU background usage) (napari/napari#6425)
- Update performance and reduce memory usage for big Labels layer in direct color mode (napari/napari#6439)
- Add _data_to_texture method to LabelColormap and remove caching of (u)int8 and (uint16) (napari/napari#6602)
Bug Fixes
- Use a shader for low discrepancy label conversion (napari/napari#3308)
- Workaround Qt bug on Windows with fullscreen mode in some screen resolutions/scaling configurations (napari/napari#5401)
- Fix point selection highlight (napari/napari#5737)
- Fix shapes interactivity with scale != 1 (selection, rotate/resize) (napari/napari#5802)
- Fix taskbar icon grouping in Windows bundle (add
app_user_model_id
to bundle shortcut) (napari/napari#6056) - Add basic tests for the
ScreenshotDialog
widget and fixes (napari/napari#6057) - Install napari from repository in docker image (napari/napari#6097)
- Fix automatic selection of points when setting data (napari/napari#6098)
- Fix exception raised on empty pattern in search plugin in preferences (napari/napari#6107)
- Ensure visual is updated when painting into zarr array (napari/napari#6112)
- Emit event from Points data setter (napari/napari#6117)
- Emit event from Shapes data setter (napari/napari#6134)
- Fix oblique button by chekcing if action is generator (napari/napari#6145)
- Fix bug in
examples/multiple_viewer_widget.py
copy layer logic (napari/napari#6162) - Fix split logic in shortcut editor (napari/napari#6163)
- Layer data events before and after (napari/napari#6178)
- Implement direct color calculation in shaders for Labels auto color mode (napari/napari#6179)
- Update
QLabeledRangeSlider
style rule to prevent labels from being cut off ([#6180](https:/...
0.4.19rc8
Fix rendering of vertexes of shape layers with small scale (#6628) # References and relevant issues Bug spotted in context #6627 # Description After changes in #5802 the vertex border is very thick: ![Zrzut ekranu z 2024-01-29 15-09-03](https://github.com/napari/napari/assets/3826210/4f2ca013-b4cc-4b86-bd2f-7e668895846e) This PR reverts this change as Marker's size is in absolute unit, not data unit. ![image](https://github.com/napari/napari/assets/3826210/d087d373-3f31-4258-bba9-ffe7c34458bf) Script for reproduce: ```python import napari import numpy as np s = (0.01, 0.005, 0.005) s = (0.005, 0.005, 0.005) s = (0.01, 0.01, 0.01) s = (0.1, 0.1, 0.1) # s = (1, 1, 1) viewer = napari.Viewer() layers = viewer.open_sample("napari", "cells3d") for l in layers: l.scale = s shapes = viewer.add_shapes( np.array( [ [29.0, 130.70802005, 86.37901572], [29.0, 130.70802005, 137.70733652], [29.0, 182.32797904, 137.70733652], [29.0, 182.32797904, 86.37901572], ] ), scale=s, ) shapes.mode = "select" viewer.dims.current_step = (29, 0, 0) viewer.reset_view() napari.run() ```
0.4.19rc7
Fix points `changed` event emission (#6611) # References and relevant issues This PR fixes an issue reported on [forum.image.sc](https://forum.image.sc/t/napari-how-to-distinguish-between-shape-added-removed-by-user-and-back-end/78529/12). It s one of the latest posts. # Description This PR moves the event emission when a point has changed from `_move` in the `Points` layer to `select` in `_points_mouse_bindings`. This because in `_move` events where emitted during moving and then the last event to be emitted when the dragging stops and the user releases the mouse does not have `selected_indices`. For example below, move the point and then check console output once drag is finished. You see the action is `CHANGED` but `data_indices` is empty while it should be `(0)` ```python import napari def check_call(event): print(event.action) print(event.data_indices) viewer = napari.Viewer() layer = viewer.add_points([5,5]) layer.events.data.connect(check_call) napari.run() ``` The event now is only emitted when dragging stops and the output for the example is now as expected. The downside is that it is more challenging to test this as `Mock` with `layer.data.events` does not emit anything now by purely using the `_move` method. This still needs to be fixed. --------- Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
0.4.19rc6
Bug fixes to multiple issues with linked layers (#6623) # References and relevant issues Closes https://github.com/napari/napari/issues/6619 # Description While testing https://github.com/napari/napari/pull/6622 I noted a number of issues with linked layers: 1) a removed layer remains linked (this was also reported in https://github.com/napari/napari/issues/6619 ) 2) if two points layers are linked and you try to add a point to either one you get: `ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().` 3) if you have a Labels layer linked to points, shapes, image and try to paint, you get: `ValueError: 'paint' is not a valid Mode` 4) if you have a Shapes layer linked to any other layer and try to draw a shape, you get: `ValueError: 'add_rectangle' is not a valid Mode` This is a PR to fix them. - unlink layers before removing from layer list - add equality operator for pandas DF, so that `pick_equality_operator` works for Points - add things to the `exclude` list that are problematic because: - they either are data related (e.g. features/properties) - depend on number of <data elements> (e.g. edge_width, face_color, edge_color) - are not compatible between layers (e.g. mode) I've added tests for: - unlinking of removed layers (this fails on main) - the pandas equality operator - linked points layers (this fails on main) - linked layer modes (this fails on main) --------- Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
0.4.19rc5
Fix `Labels.data_setitem` setting of view by taking dims order into a… …ccount (#6616) closes #6615 In #6607, we started painting into both the data and the slice view. (And this was already happening and broken when painting into lazy arrays such as zarr and dask, #6112.) However, when setting the view we need to take into account the axis ordering used when slicing (some axes may be transposed). This manifested as an index error in #6615. In this PR, we add an `indices_order` argument to `index_in_slice` function and the function returns indices in the requested order, which we can then use to set the view.
0.4.19rc4
v0.4.19rc4 fix drawing logic
0.4.19rc3
Update performance and reduce memory usage for big Labels layer in di… …rect color mode (#6439) Closes #6518 Closes #6084 In this PR, similarly to #6411, instead of using `float32` to pass data to the GPU there we introduce heuristics for choosing smaller data types, while keeping high performance. Instead of complex calculation of color in the shader, a precomputed texture array is used. To avoid repetitive texture calculation, the textures are cached in the `Colormap` objects. For data of type uint8/int8/uint16/int16 we do not perform any transform of data. We send them to the GPU as it is. This allows to reduce computational time. Based on experiments, the rendering performance is a little worse for uint16/int16 than for uint8/int8. But it may depend on the GPU. Also, using uint16/int16 means usage more GPU memory than for 8 bits type. Still less than current main. For datatypes using at least 32 bits, we add a preprocessing step where we identify a set of labels that are mapped to the same color and map all of them to the same value. This often saves enough space to fall back to uint8/uint16. It allows using a smaller additional array, and use less GPU memory. If there are more than `2**16` distinct colors, then float32 is used, though performance will be reduced. We support only up to `2**23` distinct colors for now. For reduced memory usage, part of the functions used for data preprocessing are compiled using numba. We provide a version of the function that does not require `numba` but it limits the number of distinct colors to `2**16` and involves additional array creation (more memory usage). --------- Co-authored-by: Juan Nunez-Iglesias <jni@fastmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Lorenzo Gaifas <brisvag@gmail.com> Co-authored-by: Andy Sweet <andrew.d.sweet@gmail.com>
0.4.19rc2
v0.4.19rc2 Separate concurency group for 0.4.19, fix pre-commit
0.4.19rc1
Exclude the loaded property when linking two layers (#6377) Closes #6372 This fixes a bug when linking layers and using the experimental async loading/slicing feature. The bug exists for both the old implementation available in v0.4.* and the new implementation available on the main branch, which are the only things that can cause `Layer.loaded` to change value and therefore cause the corresponding `Layer.events.loaded` to be emitted. The underlying cause is that the `loaded` property (which returns `True` when a layer's slice/view is fully loaded) is read-only from the public API (i.e. there is no public property setter). The fix is to add `loaded` to the attribute/property names excluded when finding the common evented attributes. Even if this were user-settable (which it should *not* be), it should still be excluded because it corresponds to a slice/view of a layer which is not state that should be shared between two linked layers. I added a test to cover this specific case. I also fixed some nearby typos.