Source code for descarteslabs.workflows.interactive.widgets.slider

from typing import Union, Optional, Generic, T, ClassVar

from ._ipywidgets import ipywidgets

from descarteslabs.common.proto.widgets import widgets_pb2

from ...types import Int, Float
from ...types.widget import Widget


class Slider(Widget, Generic[T]):
    _widget_type: ClassVar[ipywidgets.DOMWidget]

    def __init__(self, name: str, default: T, min: T, max: T, step: T, label: str = ""):
        super().__init__(name, default, label)
        self._min = min
        self._max = max
        self._step = step
        self.widget = self._widget_type(value=default, min=min, max=max, step=step)
        self.widget._label = label


class IntSlider(Slider[int], Int):
    _proto_type = widgets_pb2.IntSlider
    _widget_type = ipywidgets.IntSlider


class FloatSlider(Slider[float], Float):
    _proto_type = widgets_pb2.FloatSlider
    _widget_type = ipywidgets.FloatSlider


[docs]def slider( name: str, min: Union[int, float], max: Union[int, float], step: Optional[Union[int, float]] = None, default: Optional[Union[int, float]] = None, label: str = "", ): """ A slider, which acts as an `.Int` or `.Float` parameter. If any of ``min``, ``max``, or ``step`` are a float, then the slider will represent a `.Float` value, otherise an `.Int`. Example ------- >>> import descarteslabs.workflows as wf >>> wf.widgets.slider("param_name", 0, 10, step=0.5, default=3, label="A float parameter") # doctest: +SKIP >>> s2 = wf.ImageCollection.from_id("sentinel-2:L1C", "2018-01-01", "2018-04-01") >>> nir, red = s2.unpack_bands("nir red") >>> ndvi = (nir - red) / (nir + red) >>> high_ndvi = ndvi > wf.widgets.slider("thresh", 0, 0.8, default=0.24, label="Minimum NDVI threshold") >>> high_ndvi.visualize("NDVI", scales=[0, 1], colormap="Greens") # doctest: +SKIP >>> # ^ when you call .visualize, the `slider` widget will automatically show up below The map will show areas where NDVI is greater than the amount on the slider, and update when you drag the slider. (If you haven't already, run ``wf.map`` in another notebook cell to see your layer.) Parameters ---------- name: str The name of the parameter. min: int, float The minimum value for the slider. Must be less than max. max: int, float The maximum value for the slider. Must be greater than min. step: int, float, optional, default None The interval between "ticks" on the slider. Must be less than ``max - min``. If None (default) and one of ``min`` or ``max`` are floats, defaults to ``(min - max) / 10``, meaning having 10 steps on the slider. If None and both are ints, and ``5 <= (min - max) <= 10``, ``step`` becomes 1, meaning 5-10 steps on the slider. Otherwise, ``step`` becomes ``(min - max) / 10``, rounded to an int if that int would evenly divide the slider, otherwise a float. default: int, float, optional, default None The default value for the slider. If None (default), defaults to ``min``. Must be between ``min`` and ``max``. label: str, default "" The longform label to display next to the widget. If not given, the widget will display as ``name`` Returns ------- widget: Union[IntSlider, FloatSlider] A Widget object that acts just like a Workflows `.Str`, `.Int`, or `.Float` and displays as a slider. """ if default is None: default = min assert max > min, f"max ({max}) must be greater than min ({min})" assert ( min <= default <= max ), f"default ({default}) must be between min and max: {min} !<= {default} !<= {max}" any_float = any(isinstance(x, float) for x in (min, max, step, default)) if step is None: step = (max - min) / 10 if not any_float: if step < 0.5: # Moving to a stepsize of 1 would yield an int slider with less than 5 steps, # so we use a float slider instead. any_float = True elif step < 1: step = 1 elif step % 1 != 0: rounded_step = int(round(step)) if (max - min) % rounded_step == 0: # The `rounded_step` stepsize evenly divides the slider, so we can use it. step = rounded_step else: # Otherwise, use a float slider instead. any_float = True else: # step is a multiple of 1, but truediv always produces floats step = int(step) assert step < ( max - min ), f"Step ({step}) must be less than max - min ({max - min})." widget_type = FloatSlider if any_float else IntSlider return widget_type(name, default, min, max, step, label=label)