Skip to content

Commit

Permalink
proj dialog, bug fix in duplicate
Browse files Browse the repository at this point in the history
  • Loading branch information
hanjinliu committed Aug 17, 2021
1 parent 220ef3b commit 52b7959
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 53 deletions.
91 changes: 52 additions & 39 deletions impy/viewer/keybinds.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from impy.viewer.widgets.dialog import ProjectionDialog
from ..arrays import LabeledArray
from ..core import array as ip_array
from .utils import *
Expand Down Expand Up @@ -289,51 +290,63 @@ def proj(viewer:"napari.Viewer"):
"""
Projection
"""
layers = list(viewer.layers.selection)
for layer in layers:
data = layer.data
kwargs = {}
kwargs.update({"scale": layer.scale[-2:],
"translate": layer.translate[-2:],
"blending": layer.blending,
"opacity": layer.opacity,
"ndim": 2,
"name": layer.name+"-proj"})
if isinstance(layer, (napari.layers.Image, napari.layers.Labels)):
raise TypeError("Projection not supported.")
elif isinstance(layer, napari.layers.Shapes):
data = [d[:,-2:] for d in data]

if layer.nshapes > 0:
for k in ["face_color", "edge_color", "edge_width"]:
kwargs[k] = getattr(layer, k)
else:
data = None
kwargs["ndim"] = 2
kwargs["shape_type"] = layer.shape_type
viewer.add_shapes(data, **kwargs)
elif isinstance(layer, napari.layers.Points):
data = data[:, -2:]
for k in ["face_color", "edge_color", "size", "symbol"]:
kwargs[k] = getattr(layer, k, None)
kwargs["size"] = layer.size[:,-2:]
if len(data) == 0:
data = None
kwargs["ndim"] = 2
viewer.add_points(data, **kwargs)
elif isinstance(layer, napari.layers.Tracks):
data = data[:, [0,-2,-1]]
viewer.add_tracks(data, **kwargs)
else:
raise NotImplementedError(type(layer))
layer = get_a_selected_layer(viewer)

data = layer.data
kwargs = {}
kwargs.update({"scale": layer.scale[-2:],
"translate": layer.translate[-2:],
"blending": layer.blending,
"opacity": layer.opacity,
"ndim": 2,
"name": layer.name+"-proj"})
if isinstance(layer, napari.layers.Image):
if layer.data.ndim < 3:
return None
dlg = ProjectionDialog(viewer, layer)
dlg.exec_()
elif isinstance(layer, napari.layers.Labels):
raise TypeError("Projection not supported.")
elif isinstance(layer, napari.layers.Shapes):
data = [d[:,-2:] for d in data]

if layer.nshapes > 0:
for k in ["face_color", "edge_color", "edge_width"]:
kwargs[k] = getattr(layer, k)
else:
data = None
kwargs["ndim"] = 2
kwargs["shape_type"] = layer.shape_type
viewer.add_shapes(data, **kwargs)
elif isinstance(layer, napari.layers.Points):
data = data[:, -2:]
for k in ["face_color", "edge_color", "size", "symbol"]:
kwargs[k] = getattr(layer, k, None)
kwargs["size"] = layer.size[:,-2:]
if len(data) == 0:
data = None
kwargs["ndim"] = 2
viewer.add_points(data, **kwargs)
elif isinstance(layer, napari.layers.Tracks):
data = data[:, [0,-2,-1]]
viewer.add_tracks(data, **kwargs)
else:
raise NotImplementedError(type(layer))

@bind_key
def duplicate_layer(viewer:"napari.Viewer"):
"""
Duplicate selected layer(s).
"""
dlg = DuplicateDialog(viewer)
dlg.exec_()
layer = get_a_selected_layer(viewer)

if isinstance(layer, (napari.layers.Image, napari.layers.Labels)):
dlg = DuplicateDialog(viewer, layer)
dlg.exec_()
else:
new_layer = copy_layer(layer)
viewer.add_layer(new_layer)
return None

def _crop_rotated_rectangle(img, crds, dims):
translate = np.min(crds, axis=0)
Expand Down
16 changes: 15 additions & 1 deletion impy/viewer/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@
def copy_layer(layer):
args, kwargs, *_ = layer.as_layer_data_tuple()
# linear interpolation is valid only in 3D mode.
if kwargs["interpolation"] == "linear":
if kwargs.get("interpolation", None) == "linear":
kwargs = kwargs.copy()
kwargs["interpolation"] = "nearest"

# This is necessarry for text bound layers.
if "properties" in kwargs:
kwargs.pop("properties")

copy = layer.__class__(args, **kwargs)

return copy

def iter_layer(viewer:"napari.Viewer", layer_type:str):
Expand Down Expand Up @@ -391,6 +397,14 @@ def layer_to_impy_object(viewer:"napari.Viewer", layer):
else:
raise NotImplementedError(type(layer))

def get_a_selected_layer(viewer:"napari.Viewer"):
selected = list(viewer.layers.selection)
if len(selected) == 0:
raise ValueError("No layer is selected.")
elif len(selected) > 1:
raise ValueError("More than one layers are selected.")
return selected[0]


class ColorCycle:
def __init__(self, cmap="rainbow") -> None:
Expand Down
63 changes: 50 additions & 13 deletions impy/viewer/widgets/dialog.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from qtpy.QtWidgets import QDialog, QPushButton, QLabel, QGridLayout, QCheckBox, QLineEdit
from __future__ import annotations
from impy.utils.axesop import find_first_appeared
from PyQt5.QtWidgets import QVBoxLayout
from qtpy.QtWidgets import QDialog, QPushButton, QLabel, QGridLayout, QCheckBox, QLineEdit, QComboBox, QHBoxLayout
import napari
import numpy as np
from functools import wraps

from ..utils import copy_layer, front_image, add_labels
from ..utils import add_labeledarray, copy_layer, front_image, add_labels
from ..._const import SetConst
from ...utils.slicer import axis_targeted_slicing

Expand Down Expand Up @@ -82,8 +85,9 @@ def _add_widgets(self):


class DuplicateDialog(QDialog):
def __init__(self, viewer:"napari.Viewer"):
def __init__(self, viewer:"napari.Viewer", layer):
self.viewer = viewer
self.layer = layer
super().__init__(viewer.window._qt_window)
self.resize(180, 120)
self.setLayout(QGridLayout())
Expand All @@ -92,15 +96,14 @@ def __init__(self, viewer:"napari.Viewer"):
@close_anyway
def run(self, *args):
line = self.line.text()
for layer in list(self.viewer.layers.selection):
if line.strip() == "" and not self.check.isChecked():
new_layer = copy_layer(layer)
elif line.strip():
new_layer = self.duplicate_sliced_layer(layer)
else:
new_layer = self.duplicate_current_step(layer)

self.viewer.add_layer(new_layer)
if line.strip() == "" and not self.check.isChecked():
new_layer = copy_layer(self.layer)
elif line.strip():
new_layer = self.duplicate_sliced_layer(self.layer)
else:
new_layer = self.duplicate_current_step(self.layer)

self.viewer.add_layer(new_layer)
return None

def duplicate_current_step(self, layer):
Expand Down Expand Up @@ -164,4 +167,38 @@ def _add_widgets(self):
self.run_button.clicked.connect(self.run)
self.layout().addWidget(self.run_button)
return None


class ProjectionDialog(QDialog):
def __init__(self, viewer:"napari.Viewer", layer):
self.viewer = viewer
self.layer = layer
super().__init__(viewer.window._qt_window)
self.resize(180, 120)
self.setLayout(QHBoxLayout())
self._add_widgets()

@close_anyway
def run(self, *args):
img = self.layer.data
out = img.proj(axis=self.axis.currentText(), method=self.method.currentText())
translate = [t for a, t in zip(img.axes, self.layer.translate) if a in out.axes]
add_labeledarray(self.viewer, out, translate=translate)
return None

def _add_widgets(self):
self.method = QComboBox(self)
self.method.setToolTip("Projection method")
self.method.addItems(["mean", "max", "median", "min", "std"])
self.method.setCurrentText("mean")
self.layout().addWidget(self.method)

axes = str(self.layer.data.axes)
self.axis = QComboBox(self)
self.axis.setToolTip("Projection axis")
self.axis.addItems(list(axes[:-2]))
self.axis.setCurrentText(find_first_appeared("ztpi<c", axes, "yx"))
self.layout().addWidget(self.axis)

self.run_button= QPushButton("Run", self)
self.run_button.clicked.connect(self.run)
self.layout().addWidget(self.run_button)

0 comments on commit 52b7959

Please sign in to comment.