import numpy as np
import napari
from .utils import *
# Shift, Control, Alt, Meta, Up, Down, Left, Right, PageUp, PageDown, Insert,
# Delete, Home, End, Escape, Backspace, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10,
# F11, F12, Space, Enter, Tab
KEYS = {"focus_next": "]",
"focus_previous": "[",
"hide_others": "Control-Shift-A",
"reslice": "/",
"to_front": "Control-Shift-F",
"reset_view": "Control-Shift-R",
}
# Overwrite napari shortcut
@napari.Viewer.bind_key("Alt-Up", overwrite=True)
def z_up(viewer:"napari.Viewer"):
axes = "".join(viewer.dims.axis_labels)
i = axes.find("z")
if i < 0:
return None
else:
step = list(viewer.dims.current_step)
step[i] = min(step[i]+1, viewer.dims.nsteps[i]-1)
viewer.dims.current_step = step
return None
@napari.Viewer.bind_key("Alt-Down", overwrite=True)
def z_down(viewer:"napari.Viewer"):
axes = "".join(viewer.dims.axis_labels)
i = axes.find("z")
if i < 0:
return None
else:
step = list(viewer.dims.current_step)
step[i] = max(step[i]-1, 0)
viewer.dims.current_step = step
return None
__all__ = list(KEYS.keys())
def bind_key(func):
return napari.Viewer.bind_key(KEYS[func.__name__])(func)
[docs]@bind_key
def focus_next(viewer:"napari.Viewer"):
_change_focus(viewer, 1)
return None
[docs]@bind_key
def focus_previous(viewer:"napari.Viewer"):
_change_focus(viewer, -1)
return None
def _change_focus(viewer:"napari.Viewer", ind:int):
# assert one Shapes or Points layer is selected
selected_layer = get_a_selected_layer(viewer)
if not isinstance(selected_layer, (napari.layers.Shapes, napari.layers.Points)):
return None
# check if one shape/point is selected
selected_data = list(selected_layer.selected_data)
if len(selected_data) != 1:
return None
selected_data = selected_data[0]
# determine next/previous index/data to select
ndata = len(selected_layer.data)
next_to_select = (selected_data + ind) % ndata
next_data = np.atleast_2d(selected_layer.data[next_to_select])
# update camera
scale = selected_layer.scale
next_center = np.mean(next_data, axis=0) * scale
viewer.dims.current_step = list(next_data[0, :].astype(np.int64))
viewer.camera.center = next_center
zoom = viewer.camera.zoom
viewer.camera.events.zoom() # Here events are emitted and zoom changes automatically.
viewer.camera.zoom = zoom
selected_layer.selected_data = {next_to_select}
selected_layer._set_highlight()
return None
[docs]@bind_key
def hide_others(viewer:"napari.Viewer"):
"""
Make selected layers visible and others invisible.
"""
selected = viewer.layers.selection
visibility_old = [layer.visible for layer in viewer.layers]
visibility_new = [layer in selected for layer in viewer.layers]
if visibility_old != visibility_new:
for layer, vis in zip(viewer.layers, visibility_new):
layer.visible = vis
else:
for layer in viewer.layers:
layer.visible = True
[docs]@bind_key
def to_front(viewer:"napari.Viewer"):
"""
Let selected layers move to front.
"""
not_selected_index = [i for i, l in enumerate(viewer.layers)
if l not in viewer.layers.selection]
viewer.layers.move_multiple(not_selected_index, 0)
[docs]@bind_key
def reset_view(viewer:"napari.Viewer"):
"""
Reset translate/scale parameters to the initial value.
"""
for layer in viewer.layers.selection:
layer.translate -= (layer.translate - layer.metadata["init_translate"])
layer.scale = layer.metadata["init_scale"]
[docs]@bind_key
def reslice(viewer:"napari.Viewer"):
"""
2D Reslice with currently selected lines/paths and images.
"""
if viewer.dims.ndisplay == 3:
viewer.status = "Cannot reslice in 3D mode."
imglist = list(iter_selected_layer(viewer, "Image"))
ndim = np.unique([shape_layer.ndim for shape_layer
in iter_selected_layer(viewer, "Shapes")])
if len(ndim) > 1:
viewer.status = "Cannot crop using Shapes layers with different number of dimensions."
else:
ndim = ndim[0]
if ndim == viewer.dims.ndim == 3:
active_plane = [-3, -2, -1]
else:
active_plane = [-2, -1]
if len(imglist) == 0:
imglist = [front_image(viewer)]
paths = []
for shape_layer in iter_selected_layer(viewer, "Shapes"):
for shape, type_ in zip(shape_layer.data, shape_layer.shape_type):
if type_ in ("line", "path"):
paths.append((shape, shape_layer.scale)) # shape = float pixel
out = []
for path, shape_layer_scale in paths:
for layer in imglist:
factor = layer.scale[active_plane]/shape_layer_scale[active_plane]
dr = layer.translate[active_plane] / layer.scale[active_plane]
out_ = layer.data.reslice(path[:,active_plane]/factor - dr)
out.append(out_)
viewer.window._results.append(out)
return None