Skip to content

ndv.controllers #

Controllers are the primary public interfaces that wrap models & views.

Classes:

  • ArrayViewer

    Viewer dedicated to displaying a single n-dimensional array.

ArrayViewer #

ArrayViewer(
    data: Any | DataWrapper = None,
    /,
    display_model: ArrayDisplayModel | None = None,
    **kwargs: Unpack[ArrayDisplayModelKwargs],
)

Viewer dedicated to displaying a single n-dimensional array.

This wraps a model and sview into a single object, and defines the public API.

See also

ndv.imshow - a convenience function that constructs and shows an ArrayViewer.

Future plans

In the future, ndv would like to support multiple, layered data sources with coordinate transforms. We reserve the name Viewer for a more fully featured viewer. ArrayViewer assumes you're viewing a single array.

Parameters:

  • data #

    ( DataWrapper | Any, default: None ) –

    Data to be displayed.

  • display_model #

    (ArrayDisplayModel, default: None ) –

    Just the display model to use. If provided, data_or_model must be an array or DataWrapper... and kwargs will be ignored.

  • **kwargs #

    (Unpack[ArrayDisplayModelKwargs], default: {} ) –

    Keyword arguments to pass to the ArrayDisplayModel constructor. If display_model is provided, these will be ignored.

Methods:

  • clone

    Return a new ArrayViewer instance with the same data and display model.

  • close

    Close the viewer.

  • hide

    Hide the viewer.

  • show

    Show the viewer.

  • widget

    Return the native front-end widget.

Attributes:

Source code in ndv/controllers/_array_viewer.py
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def __init__(
    self,
    data: Any | DataWrapper = None,
    /,
    display_model: ArrayDisplayModel | None = None,
    **kwargs: Unpack[ArrayDisplayModelKwargs],
) -> None:
    if display_model is not None and kwargs:
        warnings.warn(
            "When display_model is provided, kwargs are be ignored.",
            stacklevel=2,
        )
    self._data_model = _ArrayDataDisplayModel(
        data_wrapper=data, display=display_model or ArrayDisplayModel(**kwargs)
    )

    app = _app.gui_frontend()

    # whether to fetch data asynchronously.  Not publicly exposed yet...
    # but can use 'NDV_SYNCHRONOUS' env var to set globally
    # jupyter doesn't need async because it's already async (in that the
    # GUI is already running in JS)
    NDV_SYNCHRONOUS = os.getenv("NDV_SYNCHRONOUS", "0") in {"1", "True", "true"}
    self._async = not NDV_SYNCHRONOUS and app != _app.GuiFrontend.JUPYTER
    # set of futures for data requests
    self._futures: set[Future[DataResponse]] = set()

    # mapping of channel keys to their respective controllers
    # where None is the default channel
    self._lut_controllers: dict[LutKey, ChannelController] = {}

    # get and create the front-end and canvas classes
    frontend_cls = _app.get_array_view_class()
    canvas_cls = _app.get_array_canvas_class()
    self._canvas = canvas_cls()

    self._histogram: HistogramCanvas | None = None
    self._view = frontend_cls(self._canvas.frontend_widget(), self._data_model)

    self._set_model_connected(self._data_model.display)
    self._canvas.set_ndim(self.display_model.n_visible_axes)

    self._view.currentIndexChanged.connect(self._on_view_current_index_changed)
    self._view.resetZoomClicked.connect(self._on_view_reset_zoom_clicked)
    self._view.histogramRequested.connect(self._add_histogram)
    self._view.channelModeChanged.connect(self._on_view_channel_mode_changed)
    self._view.visibleAxesChanged.connect(self._on_view_visible_axes_changed)

    self._canvas.mouseMoved.connect(self._on_canvas_mouse_moved)

    if self._data_model.data_wrapper is not None:
        self._fully_synchronize_view()

data property writable #

data: Any

Return data being displayed.

data_wrapper property #

data_wrapper: Any

Return data being displayed.

display_model property writable #

display_model: ArrayDisplayModel

Return the current ArrayDisplayModel.

clone #

clone() -> ArrayViewer

Return a new ArrayViewer instance with the same data and display model.

Currently, this is a shallow copy. Modifying one viewer will affect the state of the other.

Source code in ndv/controllers/_array_viewer.py
178
179
180
181
182
183
184
185
186
187
def clone(self) -> ArrayViewer:
    """Return a new ArrayViewer instance with the same data and display model.

    Currently, this is a shallow copy.  Modifying one viewer will affect the state
    of the other.
    """
    # TODO: provide deep_copy option
    return ArrayViewer(
        self._data_model.data_wrapper, display_model=self.display_model
    )

close #

close() -> None

Close the viewer.

Source code in ndv/controllers/_array_viewer.py
174
175
176
def close(self) -> None:
    """Close the viewer."""
    self._view.set_visible(False)

hide #

hide() -> None

Hide the viewer.

Source code in ndv/controllers/_array_viewer.py
170
171
172
def hide(self) -> None:
    """Hide the viewer."""
    self._view.set_visible(False)

show #

show() -> None

Show the viewer.

Source code in ndv/controllers/_array_viewer.py
166
167
168
def show(self) -> None:
    """Show the viewer."""
    self._view.set_visible(True)

widget #

widget() -> Any

Return the native front-end widget.

Warning

If you directly manipulate the frontend widget, you're on your own 😄. No guarantees can be made about synchronization with the model. It is exposed for embedding in an application, and for experimentation and custom use cases. Please open an issue if you have questions.

Source code in ndv/controllers/_array_viewer.py
116
117
118
119
120
121
122
123
124
125
126
127
def widget(self) -> Any:
    """Return the native front-end widget.

    !!! Warning

        If you directly manipulate the frontend widget, you're on your own :smile:.
        No guarantees can be made about synchronization with the model.  It is
        exposed for embedding in an application, and for experimentation and custom
        use cases.  Please [open an
        issue](https://github.com/pyapp-kit/ndv/issues/new) if you have questions.
    """
    return self._view.frontend_widget()