internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: napari/napari

Issue:
to_labels broken in nD_shapes.py
>
> Hi Nicolas,
>
> Thanks for building such a great visualization tool for python!
>
> I have been trying to use (napari version `0.2.10+7.g47af135`) the `.to_labels` functionality on an image stack and not getting the behavior I expected. For example, if I add the line `print(np.unique(labels))` at line number 36 of the nD_shapes.py example, expecting this to reflect the labels of all unique shapes, the output that I get is `array([0])`, indicating no labels present.
>
> If I change line 34 to read:
`labels = layer.to_labels(labels_shape=(128, 128))`
I get an index for all 128 shapes, but of course they are now compressed into one image plane, but if line 34 reads:
`labels = layer.to_labels()`
I again get only zeros (but with shape `(127,128,128)`).
>
> It does seem that `to_labels` is meant to be compatible with n-dimensional images, am I expecting the wrong behavior, or otherwise misusing this functionality?
>
_Originally posted by @miketaormina in https://github.com/napari/napari-tutorials/issues/46#issuecomment-578882563_


Discussion:
Sounds like a bug, I can look into it
@kevinyamauchi if you have time and are interested can you take this one too? Will force you into the Shapes layer a bit :-) :-)
No problem. On it!

Resolving patch:
diff --git a/napari/layers/shapes/shape_models/shape.py b/napari/layers/shapes/shape_models/shape.py
--- a/napari/layers/shapes/shape_models/shape.py
+++ b/napari/layers/shapes/shape_models/shape.py
@@ -521,7 +521,7 @@ def to_mask(self, mask_shape=None, zoom_factor=1, offset=[0, 0]):
             displayed_order[np.argsort(displayed_order)] = list(
                 range(len(displayed_order))
             )
-            mask[tuple(slice_key)] == mask_p.transpose(displayed_order)
+            mask[tuple(slice_key)] = mask_p.transpose(displayed_order)
         else:
             mask = mask_p
 


Test patch:
diff --git a/napari/layers/shapes/_tests/test_shapes.py b/napari/layers/shapes/_tests/test_shapes.py
--- a/napari/layers/shapes/_tests/test_shapes.py
+++ b/napari/layers/shapes/_tests/test_shapes.py
@@ -912,6 +912,20 @@ def test_to_labels():
     assert len(np.unique(labels)) <= 11
 
 
+def test_to_labels_3D():
+    """Test label generation for 3D data"""
+    data = [
+        [[0, 100, 100], [0, 100, 200], [0, 200, 200], [0, 200, 100]],
+        [[1, 125, 125], [1, 125, 175], [1, 175, 175], [1, 175, 125]],
+        [[2, 100, 100], [2, 100, 200], [2, 200, 200], [2, 200, 100]],
+    ]
+    labels_shape = (3, 300, 300)
+    layer = Shapes(np.array(data), shape_type='polygon')
+    labels = layer.to_labels(labels_shape=labels_shape)
+    assert np.all(labels.shape == labels_shape)
+    assert np.all(np.unique(labels) == [0, 1, 2, 3])
+
+
 def test_xml_list():
     """Test the xml generation."""
     shape = (10, 4, 2)
Repository: napari/napari

Issue:
ListModel.append does not check type
## 🐛 Bug
in working on layer groups, I found a strange lack of type checking when appending to a `ListModel` (which inherits from `TypedList`).  [`ListModel.append`](https://github.com/napari/napari/blob/59ed366e9d492a2389c451468fd8b9f96508b4e2/napari/utils/list/_model.py#L59)  jumps right over `TypedList.append`
https://github.com/napari/napari/blob/59ed366e9d492a2389c451468fd8b9f96508b4e2/napari/utils/list/_model.py#L58-L60

... and if you try to something that is not a `Layer` to a `LayerList`, it works fine up until throwing an error (unrelated to typing) in `components.layerlist._add`.  Is that supposed to be `TypedList.append(self, obj)`?  or was that intentional?


Discussion:
Maybe @kne42 can comment on this one?

Resolving patch:
diff --git a/napari/utils/list/_model.py b/napari/utils/list/_model.py
--- a/napari/utils/list/_model.py
+++ b/napari/utils/list/_model.py
@@ -56,7 +56,7 @@ def insert(self, index, obj):
         self.events.added(item=obj, index=self.__locitem__(index))
 
     def append(self, obj):
-        super(TypedList, self).append(obj)
+        TypedList.append(self, obj)
         self.events.added(item=obj, index=len(self) - 1)
 
     def pop(self, key):


Test patch:
diff --git a/napari/components/_tests/test_layers_list.py b/napari/components/_tests/test_layers_list.py
--- a/napari/components/_tests/test_layers_list.py
+++ b/napari/components/_tests/test_layers_list.py
@@ -1,6 +1,7 @@
 from napari.components import LayerList
 from napari.layers import Image
 import numpy as np
+import pytest
 
 
 def test_empty_layers_list():
@@ -27,6 +28,10 @@ def test_adding_layer():
     layer = Image(np.random.random((10, 10)))
     layers.append(layer)
 
+    # LayerList should err if you add anything other than a layer
+    with pytest.raises(TypeError):
+        layers.append('something')
+
     assert len(layers) == 1
Repository: napari/napari

Issue:
Label painting modifies the input array in-place
## 📚 Documentation

It was brought to my attention by @VolkerH that not everyone will expect that painting/editing labels will modify the input array in-place. It might be worth documenting this fact and also suggesting that an array copy should be made if this behaviour is not desired (e.g. `viewer.add_labels(segmentation.copy())`).


Discussion:
Hi, I am interested in working on this issue. Shall I add this documentation to the docstring of `add_labels` method in the file [napari/components/add_layers_mixin.py](https://github.com/napari/napari/blob/e07158c3c850f79d08671a806c3bc2258f280479/napari/components/add_layers_mixin.py#L376) as follows:

```
Modifies the input array in-place. 

Notes
-----
Pass a deep copy of the input array as a parameter to avoid this modification. 

For example, call add_labels as follows::
viewer.add_labels(data.copy())
where data is the input array.
```

Resolving patch:
diff --git a/napari/components/add_layers_mixin.py b/napari/components/add_layers_mixin.py
--- a/napari/components/add_layers_mixin.py
+++ b/napari/components/add_layers_mixin.py
@@ -394,6 +394,16 @@ def add_labels(
         An image-like layer where every pixel contains an integer ID
         corresponding to the region it belongs to.
 
+        Using the viewer's label editing tools (painting, erasing) will
+        modify the input-array in-place.
+
+        To avoid this, pass a copy as follows:
+            layer = viewer.add_labels(data.copy())
+            # do some painting/editing
+
+        Get the modified labels as follows:
+            result = layer.data
+
         Parameters
         ----------
         data : array or list of array
diff --git a/napari/view_layers.py b/napari/view_layers.py
--- a/napari/view_layers.py
+++ b/napari/view_layers.py
@@ -371,6 +371,16 @@ def view_labels(
     An image-like layer where every pixel contains an integer ID
     corresponding to the region it belongs to.
 
+    Using the viewer's label editing tools (painting, erasing) will
+    modify the input-array in-place.
+
+        To avoid this, pass a copy as follows:
+            viewer = napari.view_labels(data.copy(), name="sample")
+            # do some painting/editing
+
+        Get the painted labels as follows:
+            result = viewer.layers["sample"].data
+
     Parameters
     ----------
     data : array or list of array


Test patch:
Repository: napari/napari

Issue:
Consistent behavior when deleting points with hotkeys
## 🚀 Feature
When adding points, it would be nice to be able to use the 'delete' key to delete points. 

Behavior should be consistent. Current behavior when on a points layer:
- Selecting a point and using the delete(mac) or backspace(windows), deletes the selected point.
- If a point is selected and I click the 'Delete selected points' button (x), the selected point is deleted.

However, if I am in the adding points mode and I use the delete/backspace key, nothing happens even though the last created point is selected.

## Pitch

The last created point should be deleted after pressing the delete/backspace key.



Discussion:
I think this is a good call, @justinelarsen . Do we want this in 0.3.0? It's a real quick one. I _think_ we just need to add `Mode.ADD` to line 65 below.

https://github.com/napari/napari/blob/cfd4eaf85114690161c197e920bb1574157e5671/napari/layers/points/_points_key_bindings.py#L62-L66
@kevinyamauchi i don’t think it’s urgent but if it’s a simple fix it would be great to get this in!

Resolving patch:
diff --git a/napari/_viewer_key_bindings.py b/napari/_viewer_key_bindings.py
--- a/napari/_viewer_key_bindings.py
+++ b/napari/_viewer_key_bindings.py
@@ -75,6 +75,7 @@ def focus_axes_down(viewer):
 
 
 @Viewer.bind_key('Control-Backspace')
+@Viewer.bind_key('Control-Delete')
 def remove_selected(viewer):
     """Remove selected layers."""
     viewer.layers.remove_selected()
@@ -87,6 +88,7 @@ def select_all(viewer):
 
 
 @Viewer.bind_key('Control-Shift-Backspace')
+@Viewer.bind_key('Control-Shift-Delete')
 def remove_all_layers(viewer):
     """Remove all layers."""
     viewer.layers.select_all()
diff --git a/napari/layers/points/_points_key_bindings.py b/napari/layers/points/_points_key_bindings.py
--- a/napari/layers/points/_points_key_bindings.py
+++ b/napari/layers/points/_points_key_bindings.py
@@ -60,7 +60,8 @@ def select_all(layer):
 
 
 @Points.bind_key('Backspace')
+@Points.bind_key('Delete')
 def delete_selected(layer):
     """Delet all selected points."""
-    if layer._mode == Mode.SELECT:
+    if layer._mode in (Mode.SELECT, Mode.ADD):
         layer.remove_selected()


Test patch:
diff --git a/napari/layers/points/_tests/test_points.py b/napari/layers/points/_tests/test_points.py
--- a/napari/layers/points/_tests/test_points.py
+++ b/napari/layers/points/_tests/test_points.py
@@ -262,6 +262,10 @@ def test_adding_points():
     assert len(layer.data) == 13
     assert np.all(layer.data[11:, :] == coords)
 
+    # test that the last added points can be deleted
+    layer.remove_selected()
+    np.testing.assert_equal(layer.data, np.vstack((data, coord)))
+
 
 def test_adding_points_to_empty():
     """Test adding Points data to empty."""
Repository: napari/napari

Issue:
Implicit pyramids will cause AttributeError in add_image(channel_axis=...)
## 🐛 Bug
as @jni pointed out here https://github.com/napari/napari/pull/1092#discussion_r404757426, we have a bug in `Viewer.add_image()`:  If the user passes an implicit pyramid (a `list` of arrays _withouth_ explicitly using `is_pyramid=True`) and tries to use `channel_axis != None`, then there will be an `AttributeError` here, since a `list` does not have `.shape`:
https://github.com/napari/napari/blob/871825e9ca9f570575e0681132d638e03cb39708/napari/components/add_layers_mixin.py#L227

(note, the syntax of of that line changed in #1092, but the potential error was always there).



Discussion:
😞 any ideas on how we should fix this? this part of the api has always been prone to a little confusion. there was a time where we had a separate `add_pyramid` method but so much code was duplicated and it was unclear how to achieve parity with the labels layer. `add_pyramid_labels` felt like a bit much

Resolving patch:
diff --git a/napari/components/add_layers_mixin.py b/napari/components/add_layers_mixin.py
--- a/napari/components/add_layers_mixin.py
+++ b/napari/components/add_layers_mixin.py
@@ -8,6 +8,7 @@
 import numpy as np
 
 from .. import layers
+from ..layers.image._image_utils import guess_multiscale
 from ..plugins.io import read_data_with_plugins
 from ..utils import colormaps
 from ..utils.misc import (
@@ -226,6 +227,9 @@ def add_image(
 
             return self.add_layer(layers.Image(data, **kwargs))
         else:
+            # Determine if data is a multiscale
+            if multiscale is None:
+                multiscale = guess_multiscale(data)
             n_channels = (data[0] if multiscale else data).shape[channel_axis]
             kwargs['blending'] = kwargs['blending'] or 'additive'
 


Test patch:
diff --git a/napari/components/_tests/test_multichannel.py b/napari/components/_tests/test_multichannel.py
--- a/napari/components/_tests/test_multichannel.py
+++ b/napari/components/_tests/test_multichannel.py
@@ -147,6 +147,28 @@ def test_multichannel_multiscale():
         assert viewer.layers[i].colormap[0] == base_colormaps[i]
 
 
+def test_multichannel_implicit_multiscale():
+    """Test adding multichannel implicit multiscale."""
+    viewer = ViewerModel()
+    np.random.seed(0)
+    shapes = [(40, 20, 4), (20, 10, 4), (10, 5, 4)]
+    np.random.seed(0)
+    data = [np.random.random(s) for s in shapes]
+    viewer.add_image(data, channel_axis=-1)
+    assert len(viewer.layers) == data[0].shape[-1]
+    for i in range(data[0].shape[-1]):
+        assert np.all(
+            [
+                np.all(l_d == d)
+                for l_d, d in zip(
+                    viewer.layers[i].data,
+                    [data[j].take(i, axis=-1) for j in range(len(data))],
+                )
+            ]
+        )
+        assert viewer.layers[i].colormap[0] == base_colormaps[i]
+
+
 def test_multichannel_dask_array():
     """Test adding multichannel dask array."""
     viewer = ViewerModel()
Repository: napari/napari

Issue:
view_image with axis_labels doesn't resize labels
## 🐛 Bug
Just noticed that calling `napari.view_image` with `axis_labels` doesn't immediately "resize" the labels to fit long text.  will fix later, just didn't want to forget.


Discussion:

Resolving patch:
diff --git a/napari/_qt/qt_main_window.py b/napari/_qt/qt_main_window.py
--- a/napari/_qt/qt_main_window.py
+++ b/napari/_qt/qt_main_window.py
@@ -409,6 +409,8 @@ def show(self):
         """Resize, show, and bring forward the window."""
         self._qt_window.resize(self._qt_window.layout().sizeHint())
         self._qt_window.show()
+        # Resize axis labels now that window is shown
+        self.qt_viewer.dims._resize_axis_labels()
 
         # We want to call Window._qt_window.raise_() in every case *except*
         # when instantiating a viewer within a gui_qt() context for the


Test patch:
Repository: napari/napari

Issue:
Don't use magenta when `channel_axis` is given but nchannels is 1
## 🐛 Bug

The OME-zarr [plugin](https://github.com/ome/ome-zarr-py) nicely grabs the channel axis from the OME standard layout. However, for single channel images, this results in the selected colormap being magenta. It should be gray if there is only one channel.

```python
import numpy as np
import napari

with napari.gui_qt():
    _ = napari.view_image(
        np.random.random(1, 100, 100), channel_axis=0, name='I ❤️ purple!'
    )
```

<img width="1200" alt="Screen Shot 2020-05-07 at 5 00 29 pm" src="https://user-images.githubusercontent.com/492549/81264137-42dbb800-9084-11ea-80d3-6e25a54a04d3.png">



Discussion:

Resolving patch:
diff --git a/napari/components/add_layers_mixin.py b/napari/components/add_layers_mixin.py
--- a/napari/components/add_layers_mixin.py
+++ b/napari/components/add_layers_mixin.py
@@ -237,7 +237,9 @@ def add_image(
             # so that we can use {k: next(v) for k, v in kwargs.items()} below
             for key, val in kwargs.items():
                 if key == 'colormap' and val is None:
-                    if n_channels < 3:
+                    if n_channels == 1:
+                        kwargs[key] = iter(['gray'])
+                    elif n_channels == 2:
                         kwargs[key] = iter(colormaps.MAGENTA_GREEN)
                     else:
                         kwargs[key] = itertools.cycle(colormaps.CYMRGB)


Test patch:
diff --git a/napari/components/_tests/test_multichannel.py b/napari/components/_tests/test_multichannel.py
--- a/napari/components/_tests/test_multichannel.py
+++ b/napari/components/_tests/test_multichannel.py
@@ -99,7 +99,9 @@ def test_multichannel(shape, kwargs):
         assert np.all(viewer.layers[i].data == data.take(i, axis=channel_axis))
         # make sure colors have been assigned properly
         if 'colormap' not in kwargs:
-            if n_channels < 3:
+            if n_channels == 1:
+                assert viewer.layers[i].colormap[0] == 'gray'
+            elif n_channels == 2:
                 assert viewer.layers[i].colormap[0] == two_colormaps[i]
             else:
                 assert viewer.layers[i].colormap[0] == base_colormaps[i]
Repository: napari/napari

Issue:
Some keyboard combinations crash napari
## 🐛 Bug

On Linux, I can kill napari by pressing and releasing the Super key. I get the following error:

```pytb
WARNING: Traceback (most recent call last):
  File "/home/jni/miniconda3/envs/all/lib/python3.8/site-packages/vispy/app/backends/_qt.py", line 505, in keyReleaseEvent
    self._keyEvent(self._vispy_canvas.events.key_release, ev)
  File "/home/jni/miniconda3/envs/all/lib/python3.8/site-packages/vispy/app/backends/_qt.py", line 551, in _keyEvent
    func(native=ev, key=key, text=text_type(ev.text()), modifiers=mod)
  File "/home/jni/miniconda3/envs/all/lib/python3.8/site-packages/vispy/util/event.py", line 455, in __call__
    self._invoke_callback(cb, event)
  File "/home/jni/miniconda3/envs/all/lib/python3.8/site-packages/vispy/util/event.py", line 473, in _invoke_callback
    _handle_exception(self.ignore_callback_errors,
  File "/home/jni/miniconda3/envs/all/lib/python3.8/site-packages/vispy/util/event.py", line 471, in _invoke_callback
    cb(event)
  File "/home/jni/miniconda3/envs/all/lib/python3.8/site-packages/napari/_qt/qt_viewer.py", line 574, in on_key_release
    combo = components_to_key_combo(event.key.name, event.modifiers)
AttributeError: 'NoneType' object has no attribute 'name'
```

This might be specific to i3.


Discussion:

Resolving patch:
diff --git a/napari/_qt/qt_viewer.py b/napari/_qt/qt_viewer.py
--- a/napari/_qt/qt_viewer.py
+++ b/napari/_qt/qt_viewer.py
@@ -571,6 +571,8 @@ def on_key_release(self, event):
         event : qtpy.QtCore.QEvent
             Event from the Qt context.
         """
+        if event.key is None:
+            return
         combo = components_to_key_combo(event.key.name, event.modifiers)
         self.viewer.release_key(combo)
 


Test patch:
Repository: napari/napari

Issue:
UnboundLocalError in create_worker
## 🐛 Bug

When creating a local worker with multiple yield connections, I get an unboundlocalerror:

```pytb
-------------------------------------------------------------------------
UnboundLocalError                       Traceback (most recent call last)
<ipython-input-23-1749d5f75cac> in <module>
     52 
     53 viewer.window.add_dock_widget(loss_canvas)
---> 54 worker = train(model, data_loader, 500)

~/projects/napari/napari/_qt/threading.py in worker_function(*args, **kwargs)
    628         kwargs['_worker_class'] = kwargs.get('_worker_class', worker_class)
    629         kwargs['_ignore_errors'] = kwargs.get('_ignore_errors', ignore_errors)
--> 630         return create_worker(function, *args, **kwargs,)
    631 
    632     return worker_function

~/projects/napari/napari/_qt/threading.py in create_worker(func, _start_thread, _connect, _worker_class, _ignore_errors, *args, **kwargs)
    505             if not isinstance(val, (tuple, list)):
    506                 _val = [val]
--> 507             for v in _val:
    508                 if not callable(v):
    509                     raise TypeError(

UnboundLocalError: local variable '_val' referenced before assignment
```

napari info:

```
napari: 0.3.2rc0
Platform: Linux-4.15.0-29-generic-x86_64-with-glibc2.10
Python: 3.8.2 (default, Mar 26 2020, 15:53:00) [GCC 7.3.0]
Qt: 5.14.2
PyQt5: 5.14.2
NumPy: 1.19.0rc1
SciPy: 1.4.1
Dask: 2.15.0
VisPy: 0.6.4

GL version: 3.0 Mesa 19.2.8
MAX_TEXTURE_SIZE: 16384

Plugins:
- napari-plugin-engine: 0.1.4
- ome_zarr: 0.0.7
- svg: 0.1.2
```


Discussion:

Resolving patch:
diff --git a/napari/_qt/threading.py b/napari/_qt/threading.py
--- a/napari/_qt/threading.py
+++ b/napari/_qt/threading.py
@@ -502,8 +502,7 @@ def long_function(duration):
             _start_thread = True
 
         for key, val in _connect.items():
-            if not isinstance(val, (tuple, list)):
-                _val = [val]
+            _val = val if isinstance(val, (tuple, list)) else [val]
             for v in _val:
                 if not callable(v):
                     raise TypeError(


Test patch:
Repository: napari/napari

Issue:
Keybinding ("A") for selecting all points in the current view slice crashes napari
## 🐛 Bug

When selecting points, using the keybinding "A" (Select all points in the current view slice), crashes napari.

## To Reproduce

```bash
conda create --name naparibugtest python=3.7
conda activate naparibugtest
pip install napari[all]
python
```
```python
import napari
with napari.gui_qt():
    napari.view_points()
```
If you then choose the point selecting tool and press "A", you get:
```python
  File "/home/adam/miniconda3/envs/naparibugtest/lib/python3.7/site-packages/napari/layers/points/_points_key_bindings.py", line 58, in select_all
    layer.selected_data = layer._indices_view[: len(layer._data_view)]
AttributeError: 'Points' object has no attribute '_data_view'
Aborted (core dumped)
```

## Expected behavior

To select all the points

## Environment
```
napari: 0.3.4
Platform: Linux-4.18.2-041802-generic-x86_64-with-debian-buster-sid
Python: 3.7.7 (default, May 7 2020, 21:25:33) [GCC 7.3.0]
Qt: 5.14.2
PyQt5: 5.14.2
NumPy: 1.18.5
SciPy: 1.4.1
Dask: 2.18.1
VisPy: 0.6.4

GL version: 4.6.0 NVIDIA 418.67
MAX_TEXTURE_SIZE: 32768

Plugins:
- napari-plugin-engine: 0.1.6
- svg: 0.1.3



Discussion:
That's a bug! I just reproduced. Should be `_view_data` instead of `_data_view` we swapped the name a while back. Can you test/ submit a PR - ideally with that swap and a minimal test that would have caught the bug.

Resolving patch:
diff --git a/napari/layers/points/_points_key_bindings.py b/napari/layers/points/_points_key_bindings.py
--- a/napari/layers/points/_points_key_bindings.py
+++ b/napari/layers/points/_points_key_bindings.py
@@ -55,7 +55,7 @@ def paste(layer):
 def select_all(layer):
     """Select all points in the current view slice."""
     if layer._mode == Mode.SELECT:
-        layer.selected_data = layer._indices_view[: len(layer._data_view)]
+        layer.selected_data = set(layer._indices_view[: len(layer._view_data)])
         layer._set_highlight()
 
 


Test patch:
diff --git a/napari/layers/points/_tests/test_points_key_bindings.py b/napari/layers/points/_tests/test_points_key_bindings.py
new file mode 100644
--- /dev/null
+++ b/napari/layers/points/_tests/test_points_key_bindings.py
@@ -0,0 +1,14 @@
+from napari.layers import Points
+
+
+def test_select_all():
+    """Test select all key binding."""
+    data = [[1, 3], [8, 4], [10, 10], [15, 4]]
+    layer = Points(data, size=1)
+
+    assert len(layer.data) == 4
+    assert len(layer.selected_data) == 0
+
+    layer.mode = 'select'
+    layer.class_keymap['A'](layer)
+    assert len(layer.selected_data) == 4