Crash while thumbnail generation when setting `layer.data` (in case of label layers)
See original GitHub issue🐛 Bug
I’m just trying to port napari-pyclesperanto-prototype (a napari plugin) from napari 0.4.5 to 0.4.7. When using the assistant, napari crashes inside a routine that draws thumbnails for the layer list. When surrounding the crash with a try-except-block, more things go wrong. Were there major changes in how layer.data and layer.name can be set?
To Reproduce
- Install the assistant (which brings napari 0.4.5) and afterwards install napari 0.4.7
git clone https://github.com/clesperanto/napari_pyclesperanto_assistant
cd napari_pyclesperanto_assistant
pip install -e .
pip install napari==0.4.7
- Run the assistant demo:
python docs/demo/start_assistant.py
- Click on the “Binarize” button on the right. It will try to add a “Label” layer and crash while setting
layer.data
in this line with this error message:
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\labels\labels.py in _raw_to_displayed(self=, raw=array([[1., 1., 1., ..., 0., 0., 0.],
[0.... [1., 1., 1., ..., 0., 0., 0.]], dtype=float32))
704 try:
--> 705 image = self._all_vals[raw]
image = undefined
self._all_vals = array([0. , 0.1210181])
raw = array([[1., 1., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.]], dtype=float32)
706 except IndexError:
IndexError: arrays used as indices must be of integer (or boolean) type
During handling of the above exception, another exception occurred:
IndexError Traceback (most recent call last)
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\widgets\_bases.py in (*x=(,))
429 self.changed = EventEmitter(source=self, type="changed")
430 self._widget._mgui_bind_change_callback(
--> 431 lambda *x: self.changed(value=x[0] if x else None)
x = (,)
global self.changed = undefined
global value = undefined
432 )
433
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\events.py in __call__(self=, *args=(), **kwargs={'value': })
601 continue
602
--> 603 self._invoke_callback(cb, event)
self._invoke_callback = >
cb = . at 0x0000022CC45800D0>
event =
604 if event.blocked:
605 break
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\events.py in _invoke_callback(self=, cb=.>, event=)
619 cb(event)
620 except Exception:
--> 621 _handle_exception(
global _handle_exception =
self.ignore_callback_errors = False
self.print_callback_errors = 'reminders'
self =
global cb_event = undefined
cb = . at 0x0000022CC45800D0>
event =
622 self.ignore_callback_errors,
623 self.print_callback_errors,
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\events.py in _invoke_callback(self=, cb=.>, event=)
617 def _invoke_callback(self, cb, event):
618 try:
--> 619 cb(event)
cb = . at 0x0000022CC45800D0>
event =
620 except Exception:
621 _handle_exception(
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\widgets\_bases.py in (x=)
1040 """Insert widget at ``key``."""
1041 if isinstance(widget, ValueWidget):
-> 1042 widget.changed.connect(lambda x: self.changed(value=self))
global widget.changed.connect = undefined
x =
global self.changed = undefined
global value = undefined
global self = undefined
1043 _widget = widget
1044
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\events.py in __call__(self=, *args=(), **kwargs={'value': })
601 continue
602
--> 603 self._invoke_callback(cb, event)
self._invoke_callback = >
cb = . at 0x0000022CC4589790>
event =
604 if event.blocked:
605 break
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\events.py in _invoke_callback(self=, cb=.>, event=)
619 cb(event)
620 except Exception:
--> 621 _handle_exception(
global _handle_exception =
self.ignore_callback_errors = False
self.print_callback_errors = 'reminders'
self =
global cb_event = undefined
cb = . at 0x0000022CC4589790>
event =
622 self.ignore_callback_errors,
623 self.print_callback_errors,
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\events.py in _invoke_callback(self=, cb=.>, event=)
617 def _invoke_callback(self, cb, event):
618 try:
--> 619 cb(event)
cb = . at 0x0000022CC4589790>
event =
620 except Exception:
621 _handle_exception(
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\function_gui.py in (e=)
106 self._auto_call = auto_call
107 if auto_call:
--> 108 self.changed.connect(lambda e: self.__call__())
global self.changed.connect = undefined
e =
global self.__call__ = undefined
109
110 if show:
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\magicgui\function_gui.py in __call__(self=, *args=(), **kwargs={})
171 bound.apply_defaults()
172
--> 173 value = self._function(*bound.args, **bound.kwargs)
value = undefined
self._function =
bound.args = (, 'threshold_otsu', 1, 1, 0)
bound.kwargs = {}
174 self._call_count += 1
175 if self._result_widget is not None:
c:\structure\code\napari_pyclesperanto_assistant\napari_pyclesperanto_assistant\_operations\_operations.py in binarize(input1=, operation_name='threshold_otsu', radius_x=1, radius_y=1, radius_z=0)
136 binarize.self.viewer.add_labels(output, translate=input1.translate)
137 else:
--> 138 binarize.self.layer.data = output
global binarize.self.layer.data = array([[1., 1., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.]], dtype=float32)
output = array([[1., 1., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.]], dtype=float32)
139 binarize.self.layer.contrast_limits = (0, 1)
140 binarize.self.layer.name = "Result of " + operation.__name__
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\image\image.py in data(self=, data=array([[1., 1., 1., ..., 0., 0., 0.],
[0.... [1., 1., 1., ..., 0., 0., 0.]], dtype=float32))
333 def data(self, data):
334 self._data = data
--> 335 self._update_dims()
self._update_dims = >
336 self.events.data(value=self.data)
337 self._set_editable()
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\base\base.py in _update_dims(self=, event=None)
543 self._ndim = ndim
544
--> 545 self.refresh()
self.refresh = >
546
547 @property
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\base\base.py in refresh(self=, event=None)
927 """Refresh all layer data based on current view slice."""
928 if self.visible:
--> 929 self.set_view_slice()
self.set_view_slice = >
930 self.events.set_data()
931 self._update_thumbnail()
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\base\base.py in set_view_slice(self=)
791 def set_view_slice(self):
792 with self.dask_optimized_slicing():
--> 793 self._set_view_slice()
self._set_view_slice = >
794
795 @abstractmethod
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\image\image.py in _set_view_slice(self=)
588 # Load our images, might be sync or async.
589 data = SliceDataClass(self, image_indices, image, thumbnail_source)
--> 590 self._load_slice(data)
self._load_slice = >
data =
591
592 def _load_slice(self, data: SliceDataClass):
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\image\image.py in _load_slice(self=, data=)
599 if self._slice.load(data):
600 # The load was synchronous.
--> 601 self._on_data_loaded(data, sync=True)
self._on_data_loaded = >
data =
global sync = undefined
602 else:
603 # The load will be asynchronous. Signal that our self.loaded
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\image\image.py in _on_data_loaded(self=, data=, sync=True)
623
624 # Pass the loaded data to the slice.
--> 625 if not self._slice.on_loaded(data):
self._slice.on_loaded = >
data =
626 # Slice rejected it, was it for the wrong indices?
627 return
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\image\_image_slice.py in on_loaded(self=, data=)
136
137 # Display the newly loaded data.
--> 138 self._set_raw_images(data.image, data.thumbnail_source)
self._set_raw_images = >
data.image = array([[1., 1., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.]], dtype=float32)
data.thumbnail_source = None
139 self.loaded = True
140 return True # data was used.
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\image\_image_slice.py in _set_raw_images(self=, image=array([[1., 1., 1., ..., 0., 0., 0.],
[0.... [1., 1., 1., ..., 0., 0., 0.]], dtype=float32), thumbnail_source=array([[1., 1., 1., ..., 0., 0., 0.],
[0.... [1., 1., 1., ..., 0., 0., 0.]], dtype=float32))
94 image = np.clip(image, 0, 1)
95 thumbnail_source = np.clip(thumbnail_source, 0, 1)
---> 96 self.image.raw = image
self.image.raw = array([[1., 1., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.]], dtype=float32)
image = array([[1., 1., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.]], dtype=float32)
97
98 # save a computation of view image if thumbnail and image is equal
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\image\_image_view.py in raw(self=, raw_image=array([[1., 1., 1., ..., 0., 0., 0.],
[0.... [1., 1., 1., ..., 0., 0., 0.]], dtype=float32))
71
72 # Update the view image based on this new raw image.
---> 73 self._view = self.image_converter(raw_image)
self._view = array([[0.]])
self.image_converter = >
raw_image = array([[1., 1., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.]], dtype=float32)
C:\Programs\miniconda3\envs\beetlesafari\lib\site-packages\napari\layers\labels\labels.py in _raw_to_displayed(self=, raw=array([[1., 1., 1., ..., 0., 0., 0.],
[0.... [1., 1., 1., ..., 0., 0., 0.]], dtype=float32))
710 )
711 self._all_vals[0] = 0
--> 712 image = self._all_vals[raw]
image = undefined
self._all_vals = array([0. , 0.1210181])
raw = array([[1., 1., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.],
[1., 1., 1., ..., 0., 0., 0.]], dtype=float32)
713 elif (
714 self.show_selected_label
IndexError: arrays used as indices must be of integer (or boolean) type
Expected behavior
It should not crash when layer.data is set.
Environment
- Please copy and paste the information at napari info option in help menubar here:
napari: 0.4.7
Platform: Windows-10-10.0.19041-SP0
Python: 3.8.8 (default, Feb 24 2021, 15:54:32) [MSC v.1928 64 bit (AMD64)]
Qt: 5.15.2
PyQt5: 5.15.2
NumPy: 1.19.2
SciPy: 1.6.1
Dask: 2021.03.0
VisPy: 0.6.6
OpenGL:
- GL version: 4.6.0 - Build 27.20.100.8681
- MAX_TEXTURE_SIZE: 16384
Screens:
- screen 1: resolution 1920x1080, scale 1.0
Plugins:
- clEsperanto: 0.7.3
- console: 0.0.2
- svg: 0.1.4
- Any other relevant information:
Additional context
Issue Analytics
- State:
- Created 2 years ago
- Comments:10 (10 by maintainers)
Top Results From Across the Web
Problem: Label tool crashes ArcMap - Esri Support
Using the Label tool, from the Drawing toolbar, to label features for a layer that has a join (Layer Properties Joins & Relates...
Read more >Fixed issues in prior versions of Photoshop - Adobe Support
(Win) A crash occurs when using the Eyedropper tool to draw on an image without the sky after clicking the sky preset thumbnail...
Read more >Django sorl thumbnail Crash - Lots of Large images
When ever I have lots of large images, like 800x650 etc in a template, Django just crashes. It works on my Mac locally...
Read more >Acorn Release Notes - Flying Meat Software
New "Auto Enhance" item under the Layer menu for bitmap layers. ... Fixed a problem where Acorn was crashing with certain images on...
Read more >Unreal Engine 5.1 Release Notes
World Partition Data Layer Improvements. Data Layers is a system designed to conditionally load and unload your world data by toggling data layers...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
But, to clarify: we should raise a more informative error message, not just let things crash the way they do now.
tbh I think we should raise, not warn. Labels should be specified as integers, maybe bools. Automatic float to int conversion is lossy in NumPy by default:
In the future, when we move the color hashing to OpenGL, we can start using
.view
since we will be doing that both ways, we can avoid lots of copies. =)