2
2
3
3
import napari
4
4
import numpy as np
5
- from qtpy .QtWidgets import QComboBox , QHBoxLayout , QSpinBox
5
+ from qtpy .QtWidgets import QComboBox , QHBoxLayout , QLabel , QSpinBox
6
6
7
7
from napari_matplotlib .base import NapariMPLWidget
8
8
9
9
__all__ = ["SliceWidget" ]
10
10
11
+ _dims_sel = ["x" , "y" ]
11
12
_dims = ["x" , "y" , "z" ]
12
13
13
14
@@ -19,21 +20,30 @@ class SliceWidget(NapariMPLWidget):
19
20
n_layers_input = 1
20
21
21
22
def __init__ (self , napari_viewer : napari .viewer .Viewer ):
23
+ # Setup figure/axes
22
24
super ().__init__ (napari_viewer )
23
25
self .axes = self .canvas .figure .subplots ()
24
26
25
27
button_layout = QHBoxLayout ()
26
28
self .layout ().addLayout (button_layout )
27
29
28
30
self .dim_selector = QComboBox ()
31
+ button_layout .addWidget (QLabel ("Slice axis:" ))
29
32
button_layout .addWidget (self .dim_selector )
30
33
self .dim_selector .addItems (_dims )
31
34
32
35
self .slice_selectors = {}
33
- for d in _dims :
36
+ for d in _dims_sel :
34
37
self .slice_selectors [d ] = QSpinBox ()
38
+ button_layout .addWidget (QLabel (f"{ d } :" ))
35
39
button_layout .addWidget (self .slice_selectors [d ])
36
40
41
+ # Setup callbacks
42
+ # Re-draw when any of the combon/spin boxes are updated
43
+ self .dim_selector .currentTextChanged .connect (self ._draw )
44
+ for d in _dims_sel :
45
+ self .slice_selectors [d ].textChanged .connect (self ._draw )
46
+
37
47
self .update_layers (None )
38
48
39
49
@property
@@ -58,32 +68,34 @@ def current_dim_index(self) -> int:
58
68
59
69
@property
60
70
def selector_values (self ) -> Dict [str , int ]:
61
- return {d : self .slice_selectors [d ].value () for d in _dims }
71
+ return {d : self .slice_selectors [d ].value () for d in _dims_sel }
62
72
63
73
def update_slice_selectors (self ) -> None :
64
74
"""
65
75
Update range and enabled status of the slice selectors, and the value
66
76
of the z slice selector.
67
77
"""
68
78
# Update min/max
69
- for i , dim in enumerate (_dims ):
79
+ for i , dim in enumerate (_dims_sel ):
70
80
self .slice_selectors [dim ].setRange (0 , self .layer .data .shape [i ])
71
81
72
- # The z dimension is always set by current z in the viewer
73
- self .slice_selectors ["z" ].setValue (self .current_z )
74
- self .slice_selectors [self .current_dim ].setEnabled (False )
75
-
76
82
def get_xy (self ) -> Tuple [np .ndarray , np .ndarray ]:
83
+ """
84
+ Get data for plotting.
85
+ """
77
86
x = np .arange (self .layer .data .shape [self .current_dim_index ])
78
87
88
+ vals = self .selector_values
89
+ vals .update ({"z" : self .current_z })
90
+
79
91
slices = []
80
92
for d in _dims :
81
93
if d == self .current_dim :
82
94
# Select all data along this axis
83
95
slices .append (slice (None ))
84
96
else :
85
97
# Select specific index
86
- val = self . selector_values [d ]
98
+ val = vals [d ]
87
99
slices .append (slice (val , val + 1 ))
88
100
89
101
# Reverse since z is the first axis in napari
@@ -99,7 +111,6 @@ def draw(self) -> None:
99
111
"""
100
112
Clear axes and draw a 1D plot.
101
113
"""
102
- self .update_slice_selectors ()
103
114
x , y = self .get_xy ()
104
115
105
116
self .axes .plot (x , y )
0 commit comments