Add min/max controls to the Jupyter image layer control widgets
Now by showing `my_image_layer.controls` you get widgets that let you adjust the opacity, stretch function, and data range. The best UI I could come up with for the data range has "coarse" controls that are typed in manually and "fine" controls that use a range slider widget. I note that in my testing, the adjustments don't apply until focus changes to another widget, which makes for a kind of weak UX. I checked the ipywidgets bug tracker but don't see any complaints about this; I'm not sure what's going on, since this seems like a pretty basic piece of functionality.
This commit is contained in:
Родитель
af97e29d1d
Коммит
ac8b91930a
|
@ -118,5 +118,43 @@ class JupyterImageLayer(ImageLayer):
|
|||
)
|
||||
link((stretch, 'value'), (self, 'stretch'))
|
||||
|
||||
self._controls = widgets.HBox([opacity, stretch])
|
||||
double_width = widgets.Layout(width='600px')
|
||||
|
||||
vrange = widgets.FloatRangeSlider(
|
||||
description = 'Fine min/max:',
|
||||
value = [self.vmin, self.vmax],
|
||||
min = self._data_min,
|
||||
max = self._data_max,
|
||||
readout = True,
|
||||
layout = double_width,
|
||||
)
|
||||
|
||||
# Linkage must be manual since vrange uses a pair of values whereas we
|
||||
# have two separate traitlets.
|
||||
vrange.observe(self._vrange_slider_updated, names=['value'])
|
||||
def update_vrange(change):
|
||||
# Note: when this function is called, these values are indeed updated.
|
||||
vrange.value = (self.vmin, self.vmax)
|
||||
self.observe(update_vrange, names=['vmin', 'vmax'])
|
||||
|
||||
coarse_min = widgets.FloatText(
|
||||
description = 'Coarse min:',
|
||||
value = self._data_min,
|
||||
)
|
||||
link((coarse_min, 'value'), (vrange, 'min'))
|
||||
|
||||
coarse_max = widgets.FloatText(
|
||||
description = 'Coarse max:',
|
||||
value = self._data_max,
|
||||
)
|
||||
link((coarse_max, 'value'), (vrange, 'max'))
|
||||
|
||||
self._controls = widgets.VBox([
|
||||
widgets.HBox([opacity, stretch]),
|
||||
widgets.HBox([coarse_min, coarse_max]),
|
||||
vrange,
|
||||
])
|
||||
return self._controls
|
||||
|
||||
def _vrange_slider_updated(self, change):
|
||||
self.vmin, self.vmax = change['new']
|
||||
|
|
|
@ -601,8 +601,8 @@ class ImageLayer(HasTraits):
|
|||
self._stretch_version = 0
|
||||
|
||||
data = fits.getdata(self._sanitized_image)
|
||||
self.vmin = np.nanpercentile(data, 0.5)
|
||||
self.vmax = np.nanpercentile(data, 99.5)
|
||||
self._data_min, self.vmin, self.vmax, self._data_max = \
|
||||
np.nanpercentile(data, [0, 0.5, 99.5, 100])
|
||||
|
||||
self._initialize_layer()
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче