Skip to content

ndv.v1 #

Here to allow access to the original (legacy) version of NDViewer.

Warning

This module should not be used for new code. It will be removed in a future release.

Classes:

  • DataWrapper

    Interface for wrapping different array-like data types.

  • NDViewer

    A viewer for ND arrays.

Functions:

  • imshow

    Display an array or DataWrapper in a new NDViewer window.

DataWrapper #

DataWrapper(data: ArrayT)

Bases: Generic[ArrayT]

Interface for wrapping different array-like data types.

DataWrapper.create is a factory method that returns a DataWrapper instance for the given data type. If your datastore type is not supported, you may implement a new DataWrapper subclass to handle your data type. To do this, import and subclass DataWrapper, and (minimally) implement the supports and isel methods. Ensure that your class is imported before the DataWrapper.create method is called, and it will be automatically detected and used to wrap your data.

Methods:

  • guess_channel_axis

    Return the (best guess) axis name for the channel dimension.

  • isel

    Select a slice from a data store using (possibly) named indices.

  • isel_async

    Asynchronous version of isel.

  • sizes

    Return a mapping of {dimkey: size} for the data.

  • summary_info

    Return info label with information about the data.

  • supports

    Return True if this wrapper can handle the given object.

Source code in ndv/v1/_old_data_wrapper.py
102
103
def __init__(self, data: ArrayT) -> None:
    self._data = data

guess_channel_axis #

guess_channel_axis() -> Any | None

Return the (best guess) axis name for the channel dimension.

Source code in ndv/v1/_old_data_wrapper.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
def guess_channel_axis(self) -> Any | None:
    """Return the (best guess) axis name for the channel dimension."""
    # for arrays with labeled dimensions,
    # see if any of the dimensions are named "channel"
    for dimkey, val in self.sizes().items():
        if str(dimkey).lower() in self.COMMON_CHANNEL_NAMES:
            if val <= self.MAX_CHANNELS:
                return dimkey

    # for shaped arrays, use the smallest dimension as the channel axis
    shape = getattr(self._data, "shape", None)
    if isinstance(shape, Sequence):
        with suppress(ValueError):
            smallest_dim = min(shape)
            if smallest_dim <= self.MAX_CHANNELS:
                return shape.index(smallest_dim)
    return None

isel abstractmethod #

isel(indexers: Indices) -> ndarray

Select a slice from a data store using (possibly) named indices.

This follows the xarray-style indexing, where indexers is a mapping of dimension names to indices or slices. Subclasses should implement this method to return a numpy array.

Source code in ndv/v1/_old_data_wrapper.py
119
120
121
122
123
124
125
126
127
@abstractmethod
def isel(self, indexers: Indices) -> np.ndarray:
    """Select a slice from a data store using (possibly) named indices.

    This follows the xarray-style indexing, where indexers is a mapping of
    dimension names to indices or slices.  Subclasses should implement this
    method to return a numpy array.
    """
    raise NotImplementedError

isel_async #

isel_async(
    indexers: list[Indices],
) -> Future[Iterable[tuple[Indices, ndarray]]]

Asynchronous version of isel.

Source code in ndv/v1/_old_data_wrapper.py
129
130
131
132
133
def isel_async(
    self, indexers: list[Indices]
) -> Future[Iterable[tuple[Indices, np.ndarray]]]:
    """Asynchronous version of isel."""
    return _EXECUTOR.submit(lambda: [(idx, self.isel(idx)) for idx in indexers])

sizes #

sizes() -> Sizes

Return a mapping of {dimkey: size} for the data.

The default implementation uses the shape attribute of the data, and tries to find dimension names in the dims, names, or labels attributes. (dims is used by xarray, names is used by torch, etc...). If no labels are found, the dimensions are just named by their integer index.

Source code in ndv/v1/_old_data_wrapper.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
def sizes(self) -> Sizes:
    """Return a mapping of {dimkey: size} for the data.

    The default implementation uses the shape attribute of the data, and
    tries to find dimension names in the `dims`, `names`, or `labels` attributes.
    (`dims` is used by xarray, `names` is used by torch, etc...). If no labels
    are found, the dimensions are just named by their integer index.
    """
    shape = getattr(self._data, "shape", None)
    if not isinstance(shape, Sequence) or not all(
        isinstance(x, int) for x in shape
    ):
        raise NotImplementedError(f"Cannot determine sizes for {type(self._data)}")
    dims = range(len(shape))
    return {dim: int(size) for dim, size in zip(dims, shape)}

summary_info #

summary_info() -> str

Return info label with information about the data.

Source code in ndv/v1/_old_data_wrapper.py
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
def summary_info(self) -> str:
    """Return info label with information about the data."""
    package = getattr(self._data, "__module__", "").split(".")[0]
    info = f"{package}.{getattr(type(self._data), '__qualname__', '')}"

    if sizes := self.sizes():
        # if all of the dimension keys are just integers, omit them from size_str
        if all(isinstance(x, int) for x in sizes):
            size_str = repr(tuple(sizes.values()))
        # otherwise, include the keys in the size_str
        else:
            size_str = ", ".join(f"{k}:{v}" for k, v in sizes.items())
            size_str = f"({size_str})"
        info += f" {size_str}"
    if dtype := getattr(self._data, "dtype", ""):
        info += f", {dtype}"
    if nbytes := getattr(self._data, "nbytes", 0) / 1e6:
        info += f", {nbytes:.2f}MB"
    return info

supports abstractmethod classmethod #

supports(obj: Any) -> bool

Return True if this wrapper can handle the given object.

Any exceptions raised by this method will be suppressed, so it is safe to directly import necessary dependencies without a try/except block.

Source code in ndv/v1/_old_data_wrapper.py
109
110
111
112
113
114
115
116
117
@classmethod
@abstractmethod
def supports(cls, obj: Any) -> bool:
    """Return True if this wrapper can handle the given object.

    Any exceptions raised by this method will be suppressed, so it is safe to
    directly import necessary dependencies without a try/except block.
    """
    raise NotImplementedError

NDViewer #

NDViewer(
    data: DataWrapper | Any | None = None,
    *,
    colormaps: Iterable[ColorStopsLike] | None = None,
    parent: QWidget | None = None,
    channel_axis: DimKey | None = None,
    channel_mode: ChannelMode | str = MONO,
)

Bases: QWidget

A viewer for ND arrays.

This widget displays a single slice from an ND array (or a composite of slices in different colormaps). The widget provides sliders to select the slice to display, and buttons to control the display mode of the channels.

An important concept in this widget is the "index". The index is a mapping of dimensions to integers or slices that define the slice of the data to display. For example, a numpy slice of [0, 1, 5:10] would be represented as {0: 0, 1: 1, 2: slice(5, 10)}, but dimensions can also be named, e.g. {'t': 0, 'c': 1, 'z': slice(5, 10)}. The index is used to select the data from the datastore, and to determine the position of the sliders.

The flow of data is as follows:

  • The user sets the data using the set_data method. This will set the number and range of the sliders to the shape of the data, and display the first slice.
  • The user can then use the sliders to select the slice to display. The current slice is defined as a Mapping of {dim -> int|slice} and can be retrieved with the _dims_sliders.value() method. To programmatically set the current position, use the setIndex method. This will set the values of the sliders, which in turn will trigger the display of the new slice via the _update_data_for_index method.
  • _update_data_for_index is an asynchronous method that retrieves the data for the given index from the datastore (using _isel) and queues the _on_data_slice_ready method to be called when the data is ready. The logic for extracting data from the datastore is defined in _data_wrapper.py, which handles idiosyncrasies of different datastores (e.g. xarray, tensorstore, etc).
  • _on_data_slice_ready is called when the data is ready, and updates the image. Note that if the slice is multidimensional, the data will be reduced to 2D using max intensity projection (and double-clicking on any given dimension slider will turn it into a range slider allowing a projection to be made over that dimension).
  • The image is displayed on the canvas, which is an object that implements the PCanvas protocol (mostly, it has an add_image method that returns a handle to the added image that can be used to update the data and display). This small abstraction allows for various backends to be used (e.g. vispy, pygfx, etc).

Parameters:

  • data #

    (Any, default: None ) –

    The data to display. This can be any duck-like ND array, including numpy, dask, xarray, jax, tensorstore, zarr, etc. You can add support for new datastores by subclassing DataWrapper and implementing the required methods. See DataWrapper for more information.

  • parent #

    (QWidget, default: None ) –

    The parent widget of this widget.

  • channel_axis #

    (Hashable, default: None ) –

    The axis that represents the channels in the data. If not provided, this will be guessed from the data.

  • channel_mode #

    (ChannelMode, default: MONO ) –

    The initial mode for displaying the channels. If not provided, this will be set to ChannelMode.MONO.

Methods:

  • eventFilter

    Event filter installed on the canvas to handle mouse events.

  • refresh

    Refresh the canvas.

  • set_channel_mode

    Set the mode for displaying the channels.

  • set_current_index

    Set the index of the displayed image.

  • set_data

    Set the datastore, and, optionally, the sizes of the data.

  • set_ndim

    Set the number of dimensions to display.

  • set_roi

    Set the properties of the ROI overlaid on the displayed data.

  • set_visualized_dims

    Set the dimensions that will be visualized.

Attributes:

Source code in ndv/v1/_old_viewer.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
def __init__(
    self,
    data: DataWrapper | Any | None = None,
    *,
    colormaps: Iterable[cmap._colormap.ColorStopsLike] | None = None,
    parent: QWidget | None = None,
    channel_axis: DimKey | None = None,
    channel_mode: ChannelMode | str = ChannelMode.MONO,
):
    super().__init__(parent=parent)

    # ATTRIBUTES ----------------------------------------------------
    self._data_wrapper: DataWrapper | None = None

    # mapping of key to a list of objects that control image nodes in the canvas
    self._img_handles: defaultdict[ImgKey, list[ImageHandle]] = defaultdict(list)
    # mapping of same keys to the LutControl objects control image display props
    self._lut_ctrls: dict[ImgKey, LutControl] = {}
    self._lut_ctrl_state: dict[ImgKey, dict] = {}
    # the set of dimensions we are currently visualizing (e.g. XY)
    # this is used to control which dimensions have sliders and the behavior
    # of isel when selecting data from the datastore
    self._visualized_dims: set[DimKey] = set()
    # the axis that represents the channels in the data
    self._channel_axis = channel_axis
    self._channel_mode: ChannelMode = None  # type: ignore # set in set_channel_mode
    # colormaps that will be cycled through when displaying composite images
    if colormaps is not None:
        self._cmaps = [cmap.Colormap(c) for c in colormaps]
    else:
        self._cmaps = DEFAULT_COLORMAPS
    self._cmap_cycle = cycle(self._cmaps)
    # the last future that was created by _update_data_for_index
    self._last_future: Future | None = None

    # number of dimensions to display
    self._ndims: Literal[2, 3] = 2

    # Canvas selection
    self._selection: CanvasElement | None = None
    # ROI
    self._roi: RoiHandle | None = None

    # WIDGETS ----------------------------------------------------

    # the button that controls the display mode of the channels
    self._channel_mode_btn = ChannelModeButton(self)
    self._channel_mode_btn.clicked.connect(self.set_channel_mode)
    # button to reset the zoom of the canvas
    self._set_range_btn = QPushButton(
        QIconifyIcon("fluent:full-screen-maximize-24-filled"), "", self
    )
    self._set_range_btn.clicked.connect(self._on_set_range_clicked)
    # button to draw ROIs
    self._add_roi_btn = ROIButton()
    self._add_roi_btn.toggled.connect(self._on_add_roi_clicked)

    # button to change number of displayed dimensions
    self._ndims_btn = DimToggleButton(self)
    self._ndims_btn.clicked.connect(self._toggle_3d)

    # place to display dataset summary
    self._data_info_label = QElidingLabel("", parent=self)
    self._progress_spinner = QSpinner(self)

    # place to display arbitrary text
    self._hover_info_label = QLabel("", self)
    # the canvas that displays the images
    self._canvas: ArrayCanvas = get_array_canvas_class()()
    self._canvas.set_ndim(self._ndims)
    self._qcanvas = self._canvas.frontend_widget()

    # Install an event filter so we can intercept mouse/key events
    self._qcanvas.installEventFilter(self)

    # the sliders that control the index of the displayed image
    self._dims_sliders = DimsSliders(self)
    self._dims_sliders.valueChanged.connect(
        qthrottled(self._update_data_for_index, 20, leading=True)
    )

    self._lut_drop = QCollapsible("LUTs", self)
    self._lut_drop.setCollapsedIcon(QIconifyIcon("bi:chevron-down", color=MID_GRAY))
    self._lut_drop.setExpandedIcon(QIconifyIcon("bi:chevron-up", color=MID_GRAY))
    lut_layout = cast("QVBoxLayout", self._lut_drop.layout())
    lut_layout.setContentsMargins(0, 1, 0, 1)
    lut_layout.setSpacing(0)
    if (
        hasattr(self._lut_drop, "_content")
        and (layout := self._lut_drop._content.layout()) is not None
    ):
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

    # LAYOUT -----------------------------------------------------

    self._btns = btns = QHBoxLayout()
    btns.setContentsMargins(0, 0, 0, 0)
    btns.setSpacing(0)
    btns.addStretch()
    btns.addWidget(self._channel_mode_btn)
    btns.addWidget(self._ndims_btn)
    btns.addWidget(self._set_range_btn)
    btns.addWidget(self._add_roi_btn)

    info_widget = QWidget()
    info = QHBoxLayout(info_widget)
    info.setContentsMargins(0, 0, 0, 2)
    info.setSpacing(0)
    info.addWidget(self._data_info_label)
    info.addWidget(self._progress_spinner)
    info_widget.setFixedHeight(16)

    layout = QVBoxLayout(self)
    layout.setSpacing(2)
    layout.setContentsMargins(6, 6, 6, 6)
    layout.addWidget(info_widget)
    layout.addWidget(self._qcanvas, 1)
    layout.addWidget(self._hover_info_label)
    layout.addWidget(self._dims_sliders)
    layout.addWidget(self._lut_drop)
    layout.addLayout(btns)

    # SETUP ------------------------------------------------------

    self.set_channel_mode(channel_mode)
    self.set_data(data)

data property writable #

data: Any

Return the data backing the view.

data_wrapper property #

data_wrapper: DataWrapper | None

Return the DataWrapper object around the datastore.

dims_sliders property #

dims_sliders: DimsSliders

Return the DimsSliders widget.

eventFilter #

eventFilter(
    obj: QObject | None, event: QEvent | None
) -> bool

Event filter installed on the canvas to handle mouse events.

Source code in ndv/v1/_old_viewer.py
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
def eventFilter(self, obj: QObject | None, event: QEvent | None) -> bool:
    """Event filter installed on the canvas to handle mouse events."""
    if event is None:
        return False  # pragma: no cover

    # here is where we get a chance to intercept mouse events before passing them
    # to the canvas. Return `True` to prevent the event from being passed to
    # the backend widget.
    intercept = False
    # use children in case backend has a subwidget stealing events.
    if obj is self._qcanvas or obj in (self._qcanvas.children()):
        if isinstance(event, QMouseEvent):
            intercept |= self._canvas_mouse_event(event)
        if event.type() == QEvent.Type.KeyPress:
            self.keyPressEvent(cast("QKeyEvent", event))
    return intercept

refresh #

refresh() -> None

Refresh the canvas.

Source code in ndv/v1/_old_viewer.py
420
421
422
423
def refresh(self) -> None:
    """Refresh the canvas."""
    self._clear_images()
    self._update_data_for_index(self._dims_sliders.value())

set_channel_mode #

set_channel_mode(
    mode: ChannelMode | str | None = None,
) -> None

Set the mode for displaying the channels.

In "composite" mode, the channels are displayed as a composite image, using self._channel_axis as the channel axis. In "grayscale" mode, each channel is displayed separately. (If mode is None, the current value of the channel_mode_picker button is used)

Parameters:

  • mode #

    (ChannelMode | str | None, default: None ) –

    The mode to set, must be one of 'composite' or 'mono'.

Source code in ndv/v1/_old_viewer.py
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
def set_channel_mode(self, mode: ChannelMode | str | None = None) -> None:
    """Set the mode for displaying the channels.

    In "composite" mode, the channels are displayed as a composite image, using
    self._channel_axis as the channel axis. In "grayscale" mode, each channel is
    displayed separately. (If mode is None, the current value of the
    channel_mode_picker button is used)

    Parameters
    ----------
    mode : ChannelMode | str | None
        The mode to set, must be one of 'composite' or 'mono'.
    """
    # bool may happen when called from the button clicked signal
    if mode is None or isinstance(mode, bool):
        mode = self._channel_mode_btn.mode()
    else:
        mode = ChannelMode(mode)
        self._channel_mode_btn.setMode(mode)
    if mode == self._channel_mode:
        return

    self._channel_mode = mode
    self._cmap_cycle = cycle(self._cmaps)  # reset the colormap cycle
    if self._channel_axis is not None:
        # set the visibility of the channel slider
        self._dims_sliders.set_dimension_visible(
            self._channel_axis, mode != ChannelMode.COMPOSITE
        )

    self.refresh()

set_current_index #

set_current_index(index: Indices | None = None) -> None

Set the index of the displayed image.

index is a mapping of dimensions to integers or slices that define the slice of the data to display. For example, a numpy slice of [0, 1, 5:10] would be represented as {0: 0, 1: 1, 2: slice(5, 10)}, but dimensions can also be named, e.g. {'t': 0, 'c': 1, 'z': slice(5, 10)} if the data has named dimensions.

Note, calling .set_current_index() with no arguments will force the widget to redraw the current slice.

Source code in ndv/v1/_old_viewer.py
425
426
427
428
429
430
431
432
433
434
435
436
437
def set_current_index(self, index: Indices | None = None) -> None:
    """Set the index of the displayed image.

    `index` is a mapping of dimensions to integers or slices that define the slice
    of the data to display.  For example, a numpy slice of `[0, 1, 5:10]` would be
    represented as `{0: 0, 1: 1, 2: slice(5, 10)}`, but dimensions can also be
    named, e.g. `{'t': 0, 'c': 1, 'z': slice(5, 10)}` if the data has named
    dimensions.

    Note, calling `.set_current_index()` with no arguments will force the widget
    to redraw the current slice.
    """
    self._dims_sliders.setValue(index or {})

set_data #

set_data(
    data: DataWrapper | Any,
    *,
    initial_index: Indices | None = None,
) -> None

Set the datastore, and, optionally, the sizes of the data.

Properties

data : DataWrapper | Any The data to display. This can be any duck-like ND array, including numpy, dask, xarray, jax, tensorstore, zarr, etc. You can add support for new datastores by subclassing DataWrapper and implementing the required methods. If a DataWrapper instance is passed, it is used directly. See DataWrapper for more information. initial_index : Indices | None The initial index to display. This is a mapping of dimensions to integers or slices that define the slice of the data to display. If not provided, the initial index will be set to the middle of the data.

Source code in ndv/v1/_old_viewer.py
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
def set_data(
    self, data: DataWrapper | Any, *, initial_index: Indices | None = None
) -> None:
    """Set the datastore, and, optionally, the sizes of the data.

    Properties
    ----------
    data : DataWrapper | Any
        The data to display.  This can be any duck-like ND array, including numpy,
        dask, xarray, jax, tensorstore, zarr, etc.  You can add support for new
        datastores by subclassing `DataWrapper` and implementing the required
        methods. If a `DataWrapper` instance is passed, it is used directly.
        See `DataWrapper` for more information.
    initial_index : Indices | None
        The initial index to display.  This is a mapping of dimensions to integers
        or slices that define the slice of the data to display.  If not provided,
        the initial index will be set to the middle of the data.
    """
    # clear current data
    if data is None:
        self._data_wrapper = None
        self._clear_images()
        self._dims_sliders.clear()
        self._data_info_label.setText("")
        return

    # store the data
    self._data_wrapper = DataWrapper.create(data)

    # set channel axis
    self._channel_axis = self._data_wrapper.guess_channel_axis()

    # update the dimensions we are visualizing
    sizes = self._data_wrapper.sizes()
    visualized_dims = list(sizes)[-self._ndims :]
    self.set_visualized_dims(visualized_dims)

    # update the range of all the sliders to match the sizes we set above
    with signals_blocked(self._dims_sliders):
        self._update_slider_ranges()

    # redraw
    if initial_index is None:
        idx = self._dims_sliders.value() or {
            k: int(v // 2) for k, v in sizes.items()
        }
    else:
        if not isinstance(initial_index, dict):  # pragma: no cover
            raise TypeError("initial_index must be a dict")
        idx = initial_index
    with signals_blocked(self._dims_sliders):
        self.set_current_index(idx)
    # update the data info label
    self._data_info_label.setText(self._data_wrapper.summary_info())
    self.refresh()

set_ndim #

set_ndim(ndim: Literal[2, 3]) -> None

Set the number of dimensions to display.

Source code in ndv/v1/_old_viewer.py
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
def set_ndim(self, ndim: Literal[2, 3]) -> None:
    """Set the number of dimensions to display."""
    if ndim not in (2, 3):
        raise ValueError("ndim must be 2 or 3")

    self._ndims = ndim
    self._canvas.set_ndim(ndim)

    if self._data_wrapper is None:
        return

    # set the visibility of the last non-channel dimension
    sizes = list(self._data_wrapper.sizes())
    if self._channel_axis is not None:
        sizes = [x for x in sizes if x != self._channel_axis]
    if len(sizes) >= 3:
        dim3 = sizes[-3]
        self._dims_sliders.set_dimension_visible(dim3, True if ndim == 2 else False)

    # clear image handles and redraw
    self.refresh()

set_roi #

set_roi(
    vertices: list[tuple[float, float]] | None = None,
    color: Any = None,
    border_color: Any = None,
) -> None

Set the properties of the ROI overlaid on the displayed data.

Properties

vertices : list[tuple[float, float]] | None The vertices of the ROI. color : str, tuple, list, array, Color, or int The fill color. Can be any "ColorLike". border_color : str, tuple, list, array, Color, or int The border color. Can be any "ColorLike".

Source code in ndv/v1/_old_viewer.py
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
def set_roi(
    self,
    vertices: list[tuple[float, float]] | None = None,
    color: Any = None,
    border_color: Any = None,
) -> None:
    """Set the properties of the ROI overlaid on the displayed data.

    Properties
    ----------
    vertices : list[tuple[float, float]] | None
        The vertices of the ROI.
    color : str, tuple, list, array, Color, or int
        The fill color.  Can be any "ColorLike".
    border_color : str, tuple, list, array, Color, or int
        The border color.  Can be any "ColorLike".
    """
    # Remove the old ROI
    if self._roi:
        self._roi.remove()
    color = cmap.Color(color) if color is not None else None
    border_color = cmap.Color(border_color) if border_color is not None else None
    self._roi = self._canvas.add_roi(
        vertices=vertices, color=color, border_color=border_color
    )

set_visualized_dims #

set_visualized_dims(dims: Iterable[DimKey]) -> None

Set the dimensions that will be visualized.

This dims will NOT have sliders associated with them.

Source code in ndv/v1/_old_viewer.py
355
356
357
358
359
360
361
362
363
364
def set_visualized_dims(self, dims: Iterable[DimKey]) -> None:
    """Set the dimensions that will be visualized.

    This dims will NOT have sliders associated with them.
    """
    self._visualized_dims = set(dims)
    for d in self._dims_sliders._sliders:
        self._dims_sliders.set_dimension_visible(d, d not in self._visualized_dims)
    for d in self._visualized_dims:
        self._dims_sliders.set_dimension_visible(d, False)

imshow #

imshow(
    data: Any | DataWrapper,
    cmap: Any | None = None,
    *,
    channel_mode: Literal[
        "mono", "composite", "auto"
    ] = "auto",
) -> NDViewer

Display an array or DataWrapper in a new NDViewer window.

Parameters:

  • data #

    (Any | DataWrapper) –

    The data to be displayed. If not a DataWrapper, it will be wrapped in one.

  • cmap #

    (Any | None, default: None ) –

    The colormap(s) to use for displaying the data.

  • channel_mode #

    (Literal['mono', 'composite'], default: 'auto' ) –

    The initial mode for displaying the channels. By default "mono" will be used unless a cmap is provided, in which case "composite" will be used.

Returns:

Source code in ndv/v1/_util.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
def imshow(
    data: Any | DataWrapper,
    cmap: Any | None = None,
    *,
    channel_mode: Literal["mono", "composite", "auto"] = "auto",
) -> NDViewer:
    """Display an array or DataWrapper in a new NDViewer window.

    Parameters
    ----------
    data : Any | DataWrapper
        The data to be displayed. If not a DataWrapper, it will be wrapped in one.
    cmap : Any | None, optional
        The colormap(s) to use for displaying the data.
    channel_mode : Literal['mono', 'composite'], optional
        The initial mode for displaying the channels. By default "mono" will be
        used unless a cmap is provided, in which case "composite" will be used.

    Returns
    -------
    NDViewer
        The viewer window.
    """
    from . import NDViewer

    app, should_exec = _get_app()
    if cmap is not None:
        channel_mode = "composite"
        if not isinstance(cmap, (list, tuple)):
            cmap = [cmap]
    elif channel_mode == "auto":
        channel_mode = "mono"
    viewer = NDViewer(data, colormaps=cmap, channel_mode=channel_mode)
    viewer.show()
    viewer.raise_()
    if should_exec:
        app.exec()
    return viewer