@@ -95,6 +95,26 @@ def on_update_layers(self) -> None:
9595 for layer in self .viewer .layers :
9696 layer .events .contrast_limits .connect (self ._update_contrast_lims )
9797
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+
98118 def _update_contrast_lims (self ) -> None :
99119 for lim , line in zip (
100120 self .layers [0 ].contrast_limits , self ._contrast_lines
@@ -103,6 +123,25 @@ def _update_contrast_lims(self) -> None:
103123
104124 self .figure .canvas .draw ()
105125
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+
106145 @property
107146 def bins_start (self ) -> float :
108147 """Minimum bin edge"""
@@ -133,25 +172,6 @@ def bins_num(self, num: int) -> None:
133172 """Set the number of bins to use"""
134173 self .findChild (QSpinBox , name = "bins num" ).setValue (num )
135174
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-
155175 def _get_layer_data (self , layer : napari .layers .Layer ) -> npt .NDArray [Any ]:
156176 """Get the data associated with a given layer"""
157177 if layer .data .ndim - layer .rgb == 3 :
@@ -166,30 +186,6 @@ def _get_layer_data(self, layer: napari.layers.Layer) -> npt.NDArray[Any]:
166186
167187 return data
168188
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-
193189 def draw (self ) -> None :
194190 """
195191 Clear the axes and histogram the currently selected layer/slice.
@@ -201,7 +197,7 @@ def draw(self) -> None:
201197 # whole cube into memory.
202198 if data .dtype .kind in {"i" , "u" }:
203199 # 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 )
205201 step = max (1 , step )
206202 bins = np .arange (self .bins_start , self .bins_stop + step , step )
207203 else :
0 commit comments