@@ -95,6 +95,26 @@ def on_update_layers(self) -> None:
95
95
for layer in self .viewer .layers :
96
96
layer .events .contrast_limits .connect (self ._update_contrast_lims )
97
97
98
+ if not self .layers :
99
+ return
100
+
101
+ # Reset to bin start, stop and step
102
+ layer_data = self ._get_layer_data (self .layers [0 ])
103
+ self .autoset_widget_bins (data = layer_data )
104
+
105
+ # Only allow integer bins for integer data
106
+ # And only allow values greater than 0 for unsigned integers
107
+ n_decimals = 0 if np .issubdtype (layer_data .dtype , np .integer ) else 2
108
+ is_unsigned = layer_data .dtype .kind == "u"
109
+ minimum_value = 0 if is_unsigned else - 1e10
110
+
111
+ bins_start = self .findChild (QDoubleSpinBox , name = "bins start" )
112
+ bins_stop = self .findChild (QDoubleSpinBox , name = "bins stop" )
113
+ bins_start .setDecimals (n_decimals )
114
+ bins_stop .setDecimals (n_decimals )
115
+ bins_start .setMinimum (minimum_value )
116
+ bins_stop .setMinimum (minimum_value )
117
+
98
118
def _update_contrast_lims (self ) -> None :
99
119
for lim , line in zip (
100
120
self .layers [0 ].contrast_limits , self ._contrast_lines
@@ -103,6 +123,25 @@ def _update_contrast_lims(self) -> None:
103
123
104
124
self .figure .canvas .draw ()
105
125
126
+ def autoset_widget_bins (self , data : npt .NDArray [Any ]) -> None :
127
+ """Update widgets with bins determined from the image data"""
128
+
129
+ if data .dtype .kind in {"i" , "u" }:
130
+ # Make sure integer data types have integer sized bins
131
+ # We can't use unsigned ints when calculating the step, otherwise
132
+ # the following warning is raised:
133
+ # 'RuntimeWarning: overflow encountered in scalar subtract'
134
+ step = abs (np .min (data ).astype (int ) - np .max (data ).astype (int ) // 100 )
135
+ step = max (1 , step )
136
+ bins = np .arange (np .min (data ), np .max (data ) + step , step )
137
+ else :
138
+ bins = np .linspace (np .min (data ), np .max (data ), 100 )
139
+
140
+ self .bins_start = bins [0 ]
141
+ self .bins_stop = bins [- 1 ]
142
+ self .bins_num = bins .size
143
+
144
+
106
145
@property
107
146
def bins_start (self ) -> float :
108
147
"""Minimum bin edge"""
@@ -133,25 +172,6 @@ def bins_num(self, num: int) -> None:
133
172
"""Set the number of bins to use"""
134
173
self .findChild (QSpinBox , name = "bins num" ).setValue (num )
135
174
136
- def autoset_widget_bins (self , data : npt .NDArray [Any ]) -> None :
137
- """Update widgets with bins determined from the image data"""
138
- if data .dtype .kind in {"i" , "u" }:
139
- # Make sure integer data types have integer sized bins
140
- # We can't use unsigned ints when calculating the step, otherwise
141
- # the following warning is raised:
142
- # 'RuntimeWarning: overflow encountered in scalar subtract'
143
- step = (
144
- abs (np .min (data ).astype (int ) - np .max (data ).astype (int )) // 100
145
- )
146
- step = max (1 , step )
147
- bins = np .arange (np .min (data ), np .max (data ) + step , step )
148
- else :
149
- bins = np .linspace (np .min (data ), np .max (data ), 100 )
150
-
151
- self .bins_start = bins [0 ]
152
- self .bins_stop = bins [- 1 ]
153
- self .bins_num = bins .size
154
-
155
175
def _get_layer_data (self , layer : napari .layers .Layer ) -> npt .NDArray [Any ]:
156
176
"""Get the data associated with a given layer"""
157
177
if layer .data .ndim - layer .rgb == 3 :
@@ -166,30 +186,6 @@ def _get_layer_data(self, layer: napari.layers.Layer) -> npt.NDArray[Any]:
166
186
167
187
return data
168
188
169
- def on_update_layers (self ) -> None :
170
- """
171
- Called when the layer selection changes by ``self._update_layers()``.
172
- """
173
- if not self .layers :
174
- return
175
-
176
- # Reset to bin start, stop and step
177
- layer_data = self ._get_layer_data (self .layers [0 ])
178
- self .autoset_widget_bins (data = layer_data )
179
-
180
- # Only allow integer bins for integer data
181
- # And only allow values greater than 0 for unsigned integers
182
- n_decimals = 0 if np .issubdtype (layer_data .dtype , np .integer ) else 2
183
- is_unsigned = layer_data .dtype .kind == "u"
184
- minimum_value = 0 if is_unsigned else - 1e10
185
-
186
- bins_start = self .findChild (QDoubleSpinBox , name = "bins start" )
187
- bins_stop = self .findChild (QDoubleSpinBox , name = "bins stop" )
188
- bins_start .setDecimals (n_decimals )
189
- bins_stop .setDecimals (n_decimals )
190
- bins_start .setMinimum (minimum_value )
191
- bins_stop .setMinimum (minimum_value )
192
-
193
189
def draw (self ) -> None :
194
190
"""
195
191
Clear the axes and histogram the currently selected layer/slice.
@@ -201,7 +197,7 @@ def draw(self) -> None:
201
197
# whole cube into memory.
202
198
if data .dtype .kind in {"i" , "u" }:
203
199
# Make sure integer data types have integer sized bins
204
- step = ( self .bins_start - self .bins_stop ) // self .bins_num
200
+ step = abs (( self .bins_start - self .bins_stop ) // self .bins_num )
205
201
step = max (1 , step )
206
202
bins = np .arange (self .bins_start , self .bins_stop + step , step )
207
203
else :
0 commit comments