importtypingfromtypingimportTYPE_CHECKING,OptionalfromweakrefimportWeakSetimportmagicguiasmguiimportnumpyasnpfromnapari.components.viewer_modelimportViewerModelfromnapari.utilsimport_magicguifromnapari.utils.events.event_utilsimportdisconnect_eventsifTYPE_CHECKING:# helpful for IDE supportfromnapari._qt.qt_main_windowimportWindow
[docs]@mgui.register_type(bind=_magicgui.proxy_viewer_ancestor)classViewer(ViewerModel):"""Napari ndarray viewer. Parameters ---------- title : string, optional The title of the viewer window. By default 'napari'. ndisplay : {2, 3}, optional Number of displayed dimensions. By default 2. order : tuple of int, optional Order in which dimensions are displayed where the last two or last three dimensions correspond to row x column or plane x row x column if ndisplay is 2 or 3. By default None axis_labels : list of str, optional Dimension names. By default they are labeled with sequential numbers show : bool, optional Whether to show the viewer after instantiation. By default True. """_window:'Window'=None# type: ignore_instances:typing.ClassVar[WeakSet['Viewer']]=WeakSet()def__init__(self,*,title='napari',ndisplay=2,order=(),axis_labels=(),show=True,**kwargs,)->None:super().__init__(title=title,ndisplay=ndisplay,order=order,axis_labels=axis_labels,**kwargs,)# we delay initialization of plugin system to the first instantiation# of a viewer... rather than just on import of plugins modulefromnapari.pluginsimport_initialize_plugins# having this import here makes all of Qt imported lazily, upon# instantiating the first Viewer.fromnapari.windowimportWindow_initialize_plugins()self._window=Window(self,show=show)self._instances.add(self)# Expose private window publicly. This is needed to keep window off pydantic model@propertydefwindow(self)->'Window':returnself._window
[docs]defupdate_console(self,variables):"""Update console's namespace with desired variables. Parameters ---------- variables : dict, str or list/tuple of str The variables to inject into the console's namespace. If a dict, a simple update is done. If a str, the string is assumed to have variable names separated by spaces. A list/tuple of str can also be used to give the variable names. If just the variable names are give (list/tuple/str) then the variable values looked up in the callers frame. """ifself.window._qt_viewer._consoleisNone:self.window._qt_viewer.add_to_console_backlog(variables)returnself.window._qt_viewer.console.push(variables)
[docs]defexport_figure(self,path:Optional[str]=None,*,scale_factor:float=1,flash:bool=True,)->np.ndarray:"""Export an image of the full extent of the displayed layer data. This function finds a tight boundary around the data, resets the view around that boundary, takes a screenshot for which each pixel is equal to the pixel resolution of the data, then restores the previous zoom and canvas sizes. The pixel resolution can be upscaled or downscaled by the given `scale_factor`. For example, an image with 800 x 600 pixels with scale_factor 1 will be saved as 800 x 600, or 1200 x 900 with scale_factor 1.5. For anisotropic images, the resolution is set by the highest-resolution dimension. For an anisotropic 800 x 600 image with scale set to [0.25, 0.5], the screenshot will be 800 x 1200, or 1200 x 1800 with a scale_factor of 1.5. Upscaling will be done using the interpolation mode set on each layer. Parameters ---------- path : str, optional Filename for saving screenshot image. scale_factor : float By default, the zoom will export approximately 1 pixel per smallest-scale pixel on the viewer. For example, if a layer has scale 0.004nm/pixel and another has scale 1µm/pixel, the exported figure will have 0.004nm/pixel. Upscaling by 2 will produce a figure with 0.002nm/pixel through the interpolation mode set on each layer. flash : bool Flag to indicate whether flash animation should be shown after the screenshot was captured. By default, True. Returns ------- image : array Numpy array of type ubyte and shape (h, w, 4). Index [0, 0] is the upper-left corner of the rendered region. """returnself.window.export_figure(path=path,scale=scale_factor,flash=flash,)
[docs]defscreenshot(self,path:Optional[str]=None,*,size:Optional[tuple[str,str]]=None,scale:Optional[float]=None,canvas_only:bool=True,flash:bool=True,):"""Take currently displayed screen and convert to an image array. Parameters ---------- path : str, optional Filename for saving screenshot image. size : tuple of two ints, optional Size (resolution height x width) of the screenshot. By default, the currently displayed size. Only used if `canvas_only` is True. scale : float, optional Scale factor used to increase resolution of canvas for the screenshot. By default, the currently displayed resolution.Only used if `canvas_only` is True. canvas_only : bool If True, screenshot shows only the image display canvas, and if False include the napari viewer frame in the screenshot, By default, True. flash : bool Flag to indicate whether flash animation should be shown after the screenshot was captured. By default, True. Returns ------- image : array Numpy array of type ubyte and shape (h, w, 4). Index [0, 0] is the upper-left corner of the rendered region. """returnself.window.screenshot(path=path,size=size,scale=scale,flash=flash,canvas_only=canvas_only,)
[docs]defshow(self,*,block=False):"""Resize, show, and raise the viewer window."""self.window.show(block=block)
[docs]defclose(self):"""Close the viewer window."""# Shutdown the slicer first to avoid processing any more tasks.self._layer_slicer.shutdown()# Disconnect changes to dims before removing layers one-by-one# to avoid any unnecessary slicing.disconnect_events(self.dims.events,self)# Remove all the layers from the viewerself.layers.clear()# Close the main windowself.window.close()self._instances.discard(self)
[docs]@classmethoddefclose_all(cls)->int:""" Class method, Close all existing viewer instances. This is mostly exposed to avoid leaking of viewers when running tests. As having many non-closed viewer can adversely affect performances. It will return the number of viewer closed. Returns ------- int number of viewer closed. """# copy to not iterate while changing.viewers=list(cls._instances)ret=len(viewers)forviewerinviewers:viewer.close()returnret
[docs]defcurrent_viewer()->Optional[Viewer]:"""Return the currently active napari viewer."""try:fromnapari._qt.qt_main_windowimport_QtMainWindowexceptImportError:returnNoneelse:return_QtMainWindow.current_viewer()