示例#1
0
class Mesh(BaseWidget):
    """Representation of an unstructured mesh."""
    _model_name = Unicode('MeshModel').tag(sync=True)
    auto_orient = CBool(True).tag(sync=True)
    cells = DataUnion(dtype=np.int32,
                      shape_constraint=shape_constraints(None,
                                                         4)).tag(sync=True)
    points = DataUnion(dtype=np.float32,
                       shape_constraint=shape_constraints(None,
                                                          3)).tag(sync=True)
示例#2
0
class DataWidget(RegulusWidget):
    _model_name = Unicode('RegulusData').tag(sync=True)

    pts_loc = List().tag(sync=True)
    pts = DataUnion(np.zeros(0)).tag(sync=True)
    pts_idx = List().tag(sync=True)
    pts_extent = List().tag(sync=True)
    attrs = DataUnion(np.zeros(0)).tag(sync=True)
    attrs_idx = List().tag(sync=True)
    attrs_extent = List().tag(sync=True)
    partitions = List().tag(sync=True)
    measure = Unicode().tag(sync=True)

    _data = None

    def __init__(self, data=None):
        super().__init__()
        if data is not None:
            self.data = data

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, regulus):
        self._data = regulus
        if regulus is not None:
            self.measure = regulus.measure
            self.pts_loc = regulus.pts_loc
            pts = regulus.pts
            original_x = pts.original_x
            self.pts = original_x
            self.pts_idx = list(pts.x.columns)
            self.pts_extent = list(zip(original_x.min(), original_x.max()))

            self.attrs = pts.values.values
            self.attrs_idx = list(pts.values.columns)
            self.attrs_extent = list(zip(pts.values.min(), pts.values.max()))

            self.partitions = [{
                'id': p.id,
                'persistence': p.persistence,
                'pts_span': p.pts_span,
                'minmax_idx': p.minmax_idx,
                'max_merge': p.max_merge,
                'extrema': p.extrema,
                'x': None,
                'y': None
            } for p in regulus.partitions()]
        else:
            self.measure = ''
            self.pts = []
            self.attrs = []
            self.partitions = []
示例#3
0
class ScaledArray(NDArraySource):
    """A widget that provides a scaled version of the array.

    The widget will compute the scaled version of the array on the
    frontend side in order to avoid re-transmission of data when
    only the scale changes.
    """

    _model_name = Unicode("ScaledArrayModel").tag(sync=True)
    _model_module = Unicode(module_name).tag(sync=True)
    _model_module_version = Unicode(module_version).tag(sync=True)

    data = DataUnion(help="The data to scale.").tag(sync=True,
                                                    **data_union_serialization)

    scale = Instance(Scale).tag(sync=True, **widget_serialization)

    # TODO: Use Enum instead of free-text:
    output_dtype = Unicode("inherit").tag(sync=True)

    def __init__(self, data=Undefined, scale=Undefined, **kwargs):
        super(ScaledArray, self).__init__(data=data, scale=scale, **kwargs)

    def _get_dtype(self):
        if self.output_dtype == "inherit":
            return self.data.dtype
        return self.output_dtype

    def _get_shape(self):
        if isinstance(self.scale, ColorScale):
            return self.data.shape + (4, )
        return self.data.shape
示例#4
0
class ArrayColorMap(ColorMap):
    """Representation of a color lookup table by an array of values."""
    _model_name = Unicode('ArrayColorMapModel').tag(sync=True)
    values = DataUnion(dtype=np.float32,
                       shape_constraint=shape_constraints(None, 3)).tag(
                           sync=True, **data_union_serialization)
    space = Enum(["rgb", "hsv"], "rgb").tag(sync=True)
示例#5
0
class VoxelsIpyDW(Drawable):
    """
    3D volumetric data.

    By default, the voxels are a grid inscribed in the -0.5 < x, y, z < 0.5 cube
    regardless of the passed voxel array shape (aspect ratio etc.).
    Different grid size, shape and rotation can be obtained using the model_matrix.

    Attributes:
        voxels: `array_like`. 
            3D array of `int` in range (0, 255).
            0 means empty voxel, 1 and above refer to consecutive color_map entries.
        color_map: `array_like`. 
            Flat array of `int` packed RGB colors (0xff0000 is red, 0xff is blue).

            The color defined at index i is for voxel value (i+1), e.g.:

            color_map = [0xff, 0x00ff]

            voxels = 
            [[[
                0, # empty voxel

                1, # blue voxel

                2  # red voxel
            ]]]
        model_matrix: `array_like`. 
            4x4 model transform matrix.
        wireframe: `bool`. 
            Whether mesh should display as wireframe.
        opacity: `float`.
            Opacity of voxels.
        outlines: `bool`. 
            Whether mesh should display with outlines.
        outlines_color: `int`. 
            Packed RGB color of the resulting outlines (0xff0000 is red, 0xff is blue)
    """

    type = Unicode(read_only=True).tag(sync=True)
    voxels = DataUnion(default_value=[], dtype=np.uint8).tag(sync=True, **data_union_serialization)
    color_map = Array(dtype=np.uint32).tag(sync=True, **array_serialization)
    wireframe = Bool().tag(sync=True)
    outlines = Bool().tag(sync=True)
    outlines_color = Int(min=0, max=0xffffff).tag(sync=True)
    click_callback = None
    opacity = Float(min=EPSILON, max=1.0, default_value=1.0).tag(sync=True)
    model_matrix = Array(dtype=np.float32).tag(sync=True, **array_serialization)

    def __init__(self, **kwargs):
        super(VoxelsIpyDW, self).__init__(**kwargs)

        self.set_trait('type', 'Voxels')
        self.on_msg(self._handle_custom_msg)

    def _handle_custom_msg(self, content, buffers):
        if content.get('msg_type', '') == 'click_callback':
            if self.click_callback is not None:
                self.click_callback(content['coord']['x'], content['coord']['y'], content['coord']['z'])
示例#6
0
class segmenter(DOMWidget):
    """TODO: Add docstring here
    """
    _model_name = Unicode('segmentModel').tag(sync=True)
    _model_module = Unicode(module_name).tag(sync=True)
    _model_module_version = Unicode(module_version).tag(sync=True)
    _view_name = Unicode('segmentView').tag(sync=True)
    _view_module = Unicode(module_name).tag(sync=True)
    _view_module_version = Unicode(module_version).tag(sync=True)

    classColor = Color('red').tag(sync=True)
    erasing = Bool(True).tag(sync=True)
    # underlying info for labels - this handles the syncing to ts
    _labels = Bytes(default_value=None, allow_none=True,
                    read_only=True).tag(sync=True, **labels_serialization)
    # yikes =

    data = DataUnion(
        np.zeros([10, 10, 4], dtype=np.uint8),
        dtype='uint8',
        shape_constraint=shape_constraints(None, None, 4),  # 2D RGBA
    ).tag(sync=True, **data_union_serialization)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.on_msg(self.handle_msg)

    width = CInt(700).tag(sync=True)
    height = CInt(700).tag(sync=True)

    def set_image(self, arr):
        """
        Set the image to be segmented
        arr : numpy array
            Shape (WxHx1) or (WxHx3)
        TODO: transparency here? I removed the transparency enabling code
        on the typescript side to make things simpler with the class canvas
        """
        image_metadata, image_buffer = binary_image(arr)
        command = {'name': 'image', 'metadata': image_metadata}
        self.send(command, (image_buffer, ))

    def gogogo(self):
        command = {'name': 'gogogo'}
        self.send(command, [])

    def beep(self):
        command = {'name': 'beep'}
        self.send(command, [])

    def gimme(self):
        command = {'name': 'gimme'}
        self.send(command, [])

    def handle_msg(self, widget, content, buffers):
        # print('widget:', widget)
        # print(content)
        # self.gogogo()
        self.yikes(content['start'])
示例#7
0
class IndicatorField(BaseWidget):
    """Representation of a set of nominal indicator values for each mesh entity."""
    _model_name = Unicode('IndicatorFieldModel').tag(sync=True)
    mesh = Instance(Mesh, allow_none=False).tag(sync=True,
                                                **widget_serialization)
    values = DataUnion(dtype=np.int32,
                       shape_constraint=shape_constraints(None)).tag(
                           sync=True, **data_union_serialization)
    space = Enum(indicator_field_types, "I3").tag(sync=True)
示例#8
0
class Field(BaseWidget):
    """Representation of a discrete scalar field over a mesh."""
    _model_name = Unicode('FieldModel').tag(sync=True)
    mesh = Instance(Mesh, allow_none=False).tag(sync=True,
                                                **widget_serialization)
    values = DataUnion(dtype=np.float32,
                       shape_constraint=shape_constraints(None)).tag(
                           sync=True, **data_union_serialization)
    space = Enum(field_types, "P1").tag(sync=True)
示例#9
0
class DataArray(VtkWidget):
    """TODO: Add docstring here
    """
    _model_name = Unicode('DataArrayModel').tag(sync=True)

    name = Unicode(None, allow_none=True).tag(sync=True)
    data = DataUnion().tag(sync=True, **data_union_serialization)

    def __init__(self, data, name=None, **kwargs):
        super(DataArray, self).__init__(data=data, name=name, **kwargs)
示例#10
0
class ImageCanvas(ipywidgets.DOMWidget):
    """An example widget."""
    _view_name = traitlets.Unicode('ImageCanvasView').tag(sync=True)
    _model_name = traitlets.Unicode('ImageCanvasModel').tag(sync=True)
    _view_module = traitlets.Unicode('@data-exp-lab/yt-jscanvas').tag(sync=True)
    _model_module = traitlets.Unicode('@data-exp-lab/yt-jscanvas').tag(sync=True)
    _view_module_version = traitlets.Unicode('^0.1.8').tag(sync=True)
    _model_module_version = traitlets.Unicode('^0.1.8').tag(sync=True)
    image_array = DataUnion(dtype=np.uint8,
            shape_constraint=rgba_image_shape).tag(sync=True,
                    **data_union_serialization)
    width = traitlets.Int(256).tag(sync=True)
    height = traitlets.Int(256).tag(sync=True)
示例#11
0
class ArrayColorScale(SequentialScale, ColorScale):
    """A sequential color scale with array domain/range.
    """

    _model_name = Unicode("ArrayColorScaleModel").tag(sync=True)

    def __init__(self, colors=Undefined, space="rgb", gamma=1.0, **kwargs):
        if colors is not Undefined:
            kwargs["colors"] = colors
        super(ArrayColorScale, self).__init__(space=space,
                                              gamma=gamma,
                                              **kwargs)

    colors = DataUnion(
        [[0, 0, 0], [1, 1, 1]],  # [black, white]
        shape_constraint=color_array_minlen_validator(2),
        help="An array of RGB(A) or HSL(A) values, normalized between 0 and 1.",
    ).tag(sync=True, **data_union_serialization)

    space = Enum(["rgb", "hsl"], "rgb",
                 help="The color space of the range.").tag(sync=True)

    gamma = CFloat(
        1.0, help="Gamma to use if interpolating in RGB space.").tag(sync=True)
示例#12
0
class FRBViewer(ipywidgets.DOMWidget):
    """Viewing a fixed resolution buffer"""
    _view_name = traitlets.Unicode('FRBView').tag(sync=True)
    _model_name = traitlets.Unicode('FRBModel').tag(sync=True)
    _view_module = traitlets.Unicode('@data-exp-lab/yt-jscanvas').tag(sync=True)
    _model_module = traitlets.Unicode('@data-exp-lab/yt-jscanvas').tag(sync=True)
    _view_module_version = traitlets.Unicode('^0.1.8').tag(sync=True)
    _model_module_version = traitlets.Unicode('^0.1.8').tag(sync=True)
    width = traitlets.Int(512).tag(sync=True)
    height = traitlets.Int(512).tag(sync=True)
    px = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    py = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    pdx = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    pdy = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    val = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    colormaps = traitlets.Instance(ColorMaps).tag(sync = True,
            **widget_serialization)
    view_center = traitlets.Tuple((0.5, 0.5)).tag(sync=True, config=True)
    view_width = traitlets.Tuple((0.2, 0.2)).tag(sync=True, config=True)

    @traitlets.default('layout')
    def _layout_default(self):
        return ipywidgets.Layout(width = '{}px'.format(self.width),
                                 height ='{}px'.format(self.height))

    @traitlets.default('colormaps')
    def _colormap_load(self):
        return ColorMaps()

    def setup_controls(self):
        down = ipywidgets.Button(icon="arrow-down",
                layout=ipywidgets.Layout(width='40px'))
        up = ipywidgets.Button(icon="arrow-up",
                layout=ipywidgets.Layout(width='40px'))
        right = ipywidgets.Button(icon="arrow-right",
                layout=ipywidgets.Layout(width='40px')
                )
        left = ipywidgets.Button(icon="arrow-left",
                layout=ipywidgets.Layout(width='40px')
                )
        zoom_start = 1./(self.view_width[0])
        zoom = ipywidgets.FloatSlider(min=0.1, max=10, step=0.1,
                value=zoom_start,
                description="Zoom")
        is_log = ipywidgets.Checkbox(value=False, description="Log colorscale")
        colormaps = ipywidgets.Dropdown(
                options=list(self.colormaps.cmaps.keys()),
                description="colormap",
                value = "viridis")
        min_val = ipywidgets.BoundedFloatText(description="lower colorbar bound:",
                value=self.val.min(), min=self.val.min(), max=self.val.max())
        max_val = ipywidgets.BoundedFloatText(description="upper colorbar bound:",
                value=self.val.max(), min=self.val.min(), max=self.val.max())
        minmax = ipywidgets.FloatRangeSlider(min=self.val.min(), max=self.val.max())


        down.on_click(self.on_ydownclick)
        up.on_click(self.on_yupclick)
        right.on_click(self.on_xrightclick)
        left.on_click(self.on_xleftclick)
        zoom.observe(self.on_zoom, names='value')
        # These can be jslinked, so we will do so.
        ipywidgets.jslink((is_log, 'value'), (self.colormaps, 'is_log'))
        ipywidgets.jslink((min_val, 'value'), (self.colormaps, 'min_val'))
        ipywidgets.jslink((max_val, 'value'), (self.colormaps, 'max_val'))
        # This one seemingly cannot be.
        ipywidgets.link((colormaps, 'value'), (self.colormaps, 'map_name'))

        sides = ipywidgets.HBox([left,right],
                layout=ipywidgets.Layout(justify_content='space-between',
                    width='122px'))
        nav_buttons = ipywidgets.VBox([up, sides, down],
                layout=ipywidgets.Layout(
                    align_items='center',
                    width='150px'))

        all_navigation = ipywidgets.VBox([nav_buttons, zoom],
                layout=ipywidgets.Layout(align_items='center')
                )
        all_normalizers = ipywidgets.VBox([is_log,
                colormaps, min_val, max_val],
                layout=ipywidgets.Layout(align_items='center')
                )
        accordion = ipywidgets.Accordion(children=[all_navigation,
            all_normalizers])
        accordion.set_title(0, 'navigation')
        accordion.set_title(1, 'colormap controls')
        return accordion

    def on_xrightclick(self, b):
        vc = self.view_center
        self.view_center = ((vc[0]+0.01),vc[1])

    def on_xleftclick(self, b):
        vc = self.view_center
        self.view_center = ((vc[0]-0.01),vc[1])

    def on_yupclick(self, b):
        vc = self.view_center
        self.view_center = (vc[0],(vc[1]+0.01))

    def on_ydownclick(self, b):
        vc = self.view_center
        self.view_center = (vc[0],(vc[1]-0.01))

    def on_zoom(self, change):
        vw = self.view_width
        width_x = 1.0/change["new"]
        ratio = width_x/vw[0]
        width_y = vw[1]*ratio
        self.view_width = (width_x, width_y)
示例#13
0
class Scatterplot(DataWidget, widgets.DOMWidget):  # type: ignore
    """Progressivis Scatterplot widget."""

    # Name of the widget view class in front-end
    _view_name = Unicode("ScatterplotView").tag(sync=True)

    # Name of the widget model class in front-end
    _model_name = Unicode("ScatterplotModel").tag(sync=True)

    # Name of the front-end module containing widget view
    _view_module = Unicode("progressivis-nb-widgets").tag(sync=True)

    # Name of the front-end module containing widget model
    _model_module = Unicode("progressivis-nb-widgets").tag(sync=True)

    # Version of the front-end module containing widget view
    _view_module_version = Unicode("^0.1.0").tag(sync=True)
    # Version of the front-end module containing widget model
    _model_module_version = Unicode("^0.1.0").tag(sync=True)

    hists = DataUnion([], dtype="int32").tag(sync=True, **_serialization)
    samples = DataUnion(np.zeros((0, 0, 0), dtype="float32"),
                        dtype="float32").tag(sync=True, **_serialization)
    data = Unicode("{}").tag(sync=True)
    value = Any("{}").tag(sync=True)
    move_point = Any("{}").tag(sync=True)
    modal = Bool(False).tag(sync=True)
    to_hide = Any("[]").tag(sync=True)

    def link_module(
            self,
            module: MCScatterPlot,
            refresh: bool = True
    ) -> None:  # -> List[Coroutine[Any, Any, None]]:
        def _feed_widget(wg: WidgetType, m: MCScatterPlot) -> None:
            val = m.to_json()
            data_ = {
                k: v
                for (k, v) in val.items()
                if k not in ("hist_tensor", "sample_tensor")
            }
            ht = val.get("hist_tensor", None)
            if ht is not None:
                wg.hists = ht
            st = val.get("sample_tensor", None)
            if st is not None:
                wg.samples = st
            wg.data = JS.dumps(data_)

        async def _after_run(m: Module, run_number: int) -> None:  # pylint: disable=unused-argument
            if not self.modal:
                await asynchronize(_feed_widget, self, m)

        module.on_after_run(_after_run)

        def from_input_value(_val: Any) -> None:
            bounds = self.value

            async def _cbk():
                await module.min_value.from_input(bounds["min"])
                await module.max_value.from_input(bounds["max"])

            aio.create_task(_cbk())

        self.observe(from_input_value, "value")

        # def from_input_move_point(_val: Any) -> None:
        #     aio.create_task(module.move_point.from_input(self.move_point))

        # self.observe(from_input_move_point, "move_point")

        def awake(_val: Any) -> None:
            if module._json_cache is None or self.modal:
                return
            dummy = module._json_cache.get("dummy", 555)
            module._json_cache["dummy"] = -dummy
            aio.create_task(asynchronize(_feed_widget, self,
                                         module))  # TODO: improve

        self.observe(awake, "modal")

    def __init__(self, *, disable: Sequence[Any] = tuple()):
        super().__init__()
        self.to_hide = list(disable)
示例#14
0
class ArrayScalarMap(ScalarMap):
    """Representation of a scalar lookup table by an array of values."""
    _model_name = Unicode('ArrayScalarMapModel').tag(sync=True)
    values = DataUnion(dtype=np.float32,
                       shape_constraint=shape_constraints(None)).tag(
                           sync=True, **data_union_serialization)
示例#15
0
class FRBViewer(ipywidgets.DOMWidget):
    """View of a fixed resolution buffer.

    FRBViewer(width, height, px, py, pdx, pdy, val)

    This widget creates a view of a fixed resolution buffer of
    size (`width`, `height`) given data variables `px`, `py`, `pdx`, `pdy`,
    and val. Updates on the view of the fixed reolution buffer can be made
    by modifying traitlets `view_center`, `view_width`, or `Colormaps`

    Parameters
    ----------

    width : integer
        The width of the fixed resolution buffer output, in pixels
    height : integer
        The height of the fixed resolution buffer, in pixels
    px : array of floats
        x coordinates for the center of each grid box
    py : array of floats
        y coordinates for the center of each grid box
    pdx : array of floats
        Values of the half-widths for each grid box
    pdy : array of floats
        Values of the half-heights for each grid box
    val : array of floats
        Data values for each grid box
        The data values to be visualized in the fixed resolution buffer.
    colormaps : :class: `widgyts.Colormaps`
        This is the widgyt that controls traitlets associated with the
        colormap.
    view_center : tuple
        This is a length two tuple that represents the normalized center of
        the resulting FRBView.
    view_width : tuple
        This is a length two tuple that represents the height and with of the
        view, normalized to the original size of the image. (0.5, 0.5)
        represents a view of half the total data with and half the total
        data height.

    Examples
    --------
    To create a fixed resolution buffer view of a density field with this
    widget, and then to display it:

    >>> ds = yt.load("IsolatedGalaxy")
    >>> proj = ds.proj("density", "z")
    >>> frb1 = widgyts.FRBViewer(height=512, width=512, px=proj["px"],
    ...                          py=proj["py"], pdx=proj["pdx"],
    ...                          pdy=proj["pdy"], val = proj["density"])
    >>> display(frb1)

    """
    _view_name = traitlets.Unicode('FRBView').tag(sync=True)
    _model_name = traitlets.Unicode('FRBModel').tag(sync=True)
    _view_module = traitlets.Unicode('@data-exp-lab/yt-widgets').tag(sync=True)
    _model_module = traitlets.Unicode('@data-exp-lab/yt-widgets').tag(sync=True)
    _view_module_version = traitlets.Unicode(EXTENSION_VERSION).tag(sync=True)
    _model_module_version = traitlets.Unicode(EXTENSION_VERSION).tag(sync=True)
    width = traitlets.Int(512).tag(sync=True)
    height = traitlets.Int(512).tag(sync=True)
    px = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    py = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    pdx = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    pdy = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    val = DataUnion(dtype=np.float64,
            shape_constraint=vmesh_shape).tag(sync = True,
                    **data_union_serialization)
    colormaps = traitlets.Instance(ColorMaps).tag(sync = True,
            **widget_serialization)
    view_center = traitlets.Tuple((0.5, 0.5)).tag(sync=True, config=True)
    view_width = traitlets.Tuple((0.2, 0.2)).tag(sync=True, config=True)

    @traitlets.default('layout')
    def _layout_default(self):
        return ipywidgets.Layout(width = '{}px'.format(self.width),
                                 height ='{}px'.format(self.height))

    @traitlets.default('colormaps')
    def _colormap_load(self):
        return ColorMaps()

    def setup_controls(self):
        down = ipywidgets.Button(icon="arrow-down",
                layout=ipywidgets.Layout(width='auto', grid_area="down"))
        up = ipywidgets.Button(icon="arrow-up",
                layout=ipywidgets.Layout(width='auto', grid_area="up"))
        right = ipywidgets.Button(icon="arrow-right",
                layout=ipywidgets.Layout(width='auto', grid_area="right"))
        left = ipywidgets.Button(icon="arrow-left",
                layout=ipywidgets.Layout(width='auto', grid_area="left"))
        zoom_start = 1./(self.view_width[0])
        # By setting the dynamic range to be the ratio between coarsest and
        # finest, we ensure that at the fullest zoom, our smallest point will
        # be the size of our biggest point at the outermost zoom.
        dynamic_range = (max(self.pdx.max(), self.pdy.max()) /
                         min(self.pdx.min(), self.pdy.min()))

        zoom = ipywidgets.FloatSlider(min=0.5, max=dynamic_range, step=0.1,
                value=zoom_start, description="Zoom",
                layout=ipywidgets.Layout(width="auto", grid_area="zoom"))
        is_log = ipywidgets.Checkbox(value=False, description="Log colorscale")
        colormaps = ipywidgets.Dropdown(
                options=list(self.colormaps.cmaps.keys()),
                description="colormap",
                value = "viridis")
        min_val = ipywidgets.BoundedFloatText(description="lower colorbar bound:",
                value=self.val.min(), min=self.val.min(), max=self.val.max())
        max_val = ipywidgets.BoundedFloatText(description="upper colorbar bound:",
                value=self.val.max(), min=self.val.min(), max=self.val.max())
        minmax = ipywidgets.FloatRangeSlider(min=self.val.min(), max=self.val.max())


        down.on_click(self.on_ydownclick)
        up.on_click(self.on_yupclick)
        right.on_click(self.on_xrightclick)
        left.on_click(self.on_xleftclick)
        zoom.observe(self.on_zoom, names='value')
        # These can be jslinked, so we will do so.
        ipywidgets.jslink((is_log, 'value'), (self.colormaps, 'is_log'))
        ipywidgets.jslink((min_val, 'value'), (self.colormaps, 'min_val'))
        ipywidgets.jslink((max_val, 'value'), (self.colormaps, 'max_val'))
        # This one seemingly cannot be.
        ipywidgets.link((colormaps, 'value'), (self.colormaps, 'map_name'))

        nav_buttons = ipywidgets.GridBox(children = [up, left, right, down],
                         layout=ipywidgets.Layout(width='100%',
                                    grid_template_columns = '33% 34% 33%',
                                    grid_template_rows = 'auto auto auto',
                                    grid_template_areas = '''
                                    " . up . "
                                    " left . right "
                                    " . down . "
                                    ''',
                                    grid_area='nav_buttons'))

        all_navigation = ipywidgets.GridBox(children = [nav_buttons, zoom],
                layout=ipywidgets.Layout(width="300px",
                    grid_template_columns="25% 50% 25%",
                    grid_template_rows="auto auto",
                    grid_template_areas='''
                    ". nav_buttons ."
                    "zoom zoom zoom"
                    '''
                    ))

        all_normalizers = ipywidgets.GridBox(children = [is_log,
                colormaps, min_val, max_val],
                layout=ipywidgets.Layout(width="auto")
                )

        accordion = ipywidgets.Accordion(children=[all_navigation,
            all_normalizers])

        accordion.set_title(0, 'navigation')
        accordion.set_title(1, 'colormap controls')

        return accordion

    def on_xrightclick(self, b):
        vc = self.view_center
        self.view_center = ((vc[0]+0.01),vc[1])

    def on_xleftclick(self, b):
        vc = self.view_center
        self.view_center = ((vc[0]-0.01),vc[1])

    def on_yupclick(self, b):
        vc = self.view_center
        self.view_center = (vc[0],(vc[1]+0.01))

    def on_ydownclick(self, b):
        vc = self.view_center
        self.view_center = (vc[0],(vc[1]-0.01))

    def on_zoom(self, change):
        vw = self.view_width
        width_x = 1.0/change["new"]
        ratio = width_x/vw[0]
        width_y = vw[1]*ratio
        self.view_width = (width_x, width_y)