Module i2pp.core.visualizers.visualizer
Functions for visualizations.
Classes
class Visualizer (pixel_type: PixelValueType,
pixel_range: numpy.ndarray,
title: str | None = None)-
Expand source code
class Visualizer(ABC): """A class for visualizing structured and unstructured grids using PyVista. Provides interactive controls for adjusting opacity, slicing the grid, and toggling NaN element visibility. """ def __init__( self, pixel_type: PixelValueType, pixel_range: np.ndarray, title: str | None = None, ): """Initialize the Visualizer. Arguments: pixel_type (PixelValueType): Specifies whether the pixel data is RGB or scalar. title (str | None, optional): The title of the plot window. Defaults to None. """ self.plotter = pv.Plotter() self.pixel_type = pixel_type self.pixel_range = pixel_range self.title = title self.slice_height = 0.00 self.opacity = 1.00 self.show_3d = True self.nan_exist = False self.grid = pv.UnstructuredGrid() self.extracted_grid = None self.grid_visible = pv.UnstructuredGrid() self.current_actor = None self.show_edges = False @abstractmethod def compute_grid(self, *args, **kwargs) -> None: """Abstract method to compute the grid to be visualized. This method is intended to be implemented by subclasses to compute the grid to be visualized based on their specific requirements. The implementation of this method should modify the relevant attributes of the class, such as the grid data or any other internal state that is necessary for visualization. """ pass def _update_display( self, grid: Union[pv.StructuredGrid, pv.UnstructuredGrid], **kwargs ) -> None: """Updates the currently displayed mesh in the plotter. Removes the previous mesh actor (if any) and adds the provided mesh with the given visualization settings. Arguments: grid (Union[pv.StructuredGrid, pv.UnstructuredGrid]): The new grid to display. **kwargs: Additional keyword arguments for PyVista's `add_mesh`. Returns: None """ if self.current_actor is not None: self.plotter.remove_actor(self.current_actor) self.current_actor = self.plotter.add_mesh(grid, **kwargs) def _toggle_slicer(self) -> None: """Toggles between 3D model visualization and 2D slice visualization. Clears any existing slider widgets and re-adds the appropriate slider depending on the current visualization mode (opacity for 3D, slice height for 2D). Returns: None """ self.plotter.clear_slider_widgets() if self.show_3d: self.plotter.add_slider_widget( self._update_opacity, rng=[0, 1], value=self.opacity, title="Opacity", pointa=(0.4, 0.9), pointb=(0.9, 0.9), ) else: self.plotter.add_slider_widget( self._update_slice_height, rng=[self.grid_visible.bounds[4], self.grid_visible.bounds[5]], value=self.slice_height, title="Slice Height", pointa=(0.4, 0.9), pointb=(0.9, 0.9), ) def _update_grid(self, is_checked: bool) -> None: """Updates the displayed grid based on the NaN elements toggle state. If checked, all elements are displayed. If unchecked, only elements with assigned values are shown. Arguments: is_checked (bool): Whether to show all elements or only those with values. Returns: None """ self.grid_visible = ( self.extracted_grid if not is_checked else self.grid ) def _show_3d_model(self) -> None: """Displays the 3D model of the grid with the specified opacity. Arguments: opacity (float): The opacity level (0 to 1). Returns: None """ self.show_3d = True if self.pixel_type == PixelValueType.RGB: self._update_display( self.grid_visible, scalars=f"{self.pixel_type.value}_values", rgb=True, opacity=self.opacity, ) elif ( self.pixel_type == PixelValueType.CT or self.pixel_type == PixelValueType.MRT ): self._update_display( self.grid_visible, scalars=f"{self.pixel_type.value}_values", cmap="viridis", opacity=self.opacity, clim=(self.pixel_range[0], self.pixel_range[1]), ) else: raise ValueError( f"Unsupported pixel type: {self.pixel_type.value}" ) self._update_edges() self.plotter.add_axes() self.plotter.render() def _slice_at_height(self) -> None: """Displays a 2D slice of the grid at the specified height. Extracts a slice along the Z-axis and updates the display. Arguments: height (float): The Z-coordinate where the slice is taken. Returns: None """ self.show_3d = False slice_mesh = self.grid_visible.slice( normal=[0, 0, 1], origin=(0, 0, self.slice_height) ) if self.pixel_type == PixelValueType.RGB: self._update_display( slice_mesh, scalars=f"{self.pixel_type.value}_values", rgb=True ) elif ( self.pixel_type == PixelValueType.CT or self.pixel_type == PixelValueType.MRT ): self._update_display( slice_mesh, scalars=f"{self.pixel_type.value}_values", cmap="viridis", clim=(self.pixel_range[0], self.pixel_range[1]), ) else: raise ValueError( f"Unsupported pixel type: {self.pixel_type.value}" ) self._update_edges() self.plotter.add_axes() self.plotter.render() def _toggle_nan_view(self, is_checked: bool = True) -> None: """Toggles the visibility of elements without assigned values. Updates the displayed grid and maintains the current view mode (3D model or slice). Arguments: is_checked (bool, optional): Whether to show or hide NaN elements. Defaults to True. Returns: None """ self._update_grid(is_checked) if self.show_3d: self._show_3d_model() else: self._slice_at_height() self._toggle_slicer() def _toggle_view(self, is_checked: bool = True) -> None: """Toggles between 3D and 2D slice visualization. Resets the visualization mode and updates the sliders accordingly. Arguments: is_checked (bool, optional): Whether to switch to 3D mode (True) or 2D slice mode (False). Defaults to True. Returns: None """ if is_checked: self._show_3d_model() else: self._slice_at_height() self._toggle_slicer() def _update_opacity(self, value: float) -> None: """Updates the opacity of the 3D model. If the current view mode is 3D, the displayed mesh is updated. Arguments: value (float): The new opacity level (0 to 1). Returns: None """ self.opacity = value if self.show_3d: self._show_3d_model() def _update_slice_height(self, value: float) -> None: """Updates the height of the 2D slice. If the current view mode is a 2D slice, the displayed slice is updated. Arguments: value (float): The new Z-coordinate for the slice. Returns: None """ self.slice_height = value if not self.show_3d: self._slice_at_height() def _toggle_edges(self, is_checked: bool = False): """Toggle the visibility of mesh edges in the plotter. This method updates the internal `show_edges` attribute based on the input checkbox state (`is_checked`) and triggers an update of the edge visibility in the currently displayed actor. Args: is_checked (bool, optional): Indicates whether edges should be shown. Defaults to False. """ self.show_edges = is_checked self._update_edges() def _update_edges(self): """Update the visibility of edges for the currently active actor. If a mesh actor is currently displayed in the plotter (`self.current_actor`), this method applies the value of `self.show_edges` to control whether the mesh edges are visible. """ if self.current_actor is not None: self.current_actor.GetProperty().SetEdgeVisibility(self.show_edges) def plot_grid(self) -> None: """Visualizes a structured or unstructured grid using PyVista with interactive controls for opacity adjustment, slice visualization, and NaN element toggling. This function initializes a PyVista plotter, displays the grid, and provides UI elements to switch between a full 3D model and a 2D slice, adjust opacity, and optionally hide elements without assigned values. Arguments: grid (Union[pv.StructuredGrid, pv.UnstructuredGrid]): The grid to be visualized. pixel_type (PixelValueType): Specifies whether the pixel data is RGB or scalar. ele_has_value (np.ndarray | None, optional): A boolean array indicating which elements have assigned values. If None, all elements are assumed to have values. Defaults to None. title (str | None, optional): The title of the plot window. Defaults to None. Returns: None """ self.plotter.window_size = [1024, 768] self.plotter.title = self.title self.slice_height = (self.grid.bounds[4] + self.grid.bounds[5]) / 2 self._toggle_slicer() self._show_3d_model() if self.nan_exist: self.plotter.add_text( "Toggle Nan-Elements:", position="upper_left", font_size=8, color="black", ) self.plotter.add_checkbox_button_widget( self._toggle_nan_view, size=30, value=True, position=(210, 740) ) if isinstance(self.grid, pv.UnstructuredGrid): self.plotter.add_text( "Toggle Edges", position=(35, 605), font_size=8, color="black" ) self.plotter.add_checkbox_button_widget( self._toggle_edges, size=30, value=False, position=(1, 600) ) self.plotter.add_text( "Toggle 3D/Slice View", position=(35, 655), font_size=8, color="black", ) self.plotter.add_checkbox_button_widget( self._toggle_view, value=True, position=(1, 650), size=30, ) self.plotter.show()
A class for visualizing structured and unstructured grids using PyVista.
Provides interactive controls for adjusting opacity, slicing the grid, and toggling NaN element visibility.
Initialize the Visualizer.
Arguments
pixel_type (PixelValueType): Specifies whether the pixel data is RGB or scalar. title (str | None, optional): The title of the plot window. Defaults to None.
Ancestors
- abc.ABC
Subclasses
Methods
def compute_grid(self, *args, **kwargs) ‑> None
-
Expand source code
@abstractmethod def compute_grid(self, *args, **kwargs) -> None: """Abstract method to compute the grid to be visualized. This method is intended to be implemented by subclasses to compute the grid to be visualized based on their specific requirements. The implementation of this method should modify the relevant attributes of the class, such as the grid data or any other internal state that is necessary for visualization. """ pass
Abstract method to compute the grid to be visualized.
This method is intended to be implemented by subclasses to compute the grid to be visualized based on their specific requirements. The implementation of this method should modify the relevant attributes of the class, such as the grid data or any other internal state that is necessary for visualization.
def plot_grid(self) ‑> None
-
Expand source code
def plot_grid(self) -> None: """Visualizes a structured or unstructured grid using PyVista with interactive controls for opacity adjustment, slice visualization, and NaN element toggling. This function initializes a PyVista plotter, displays the grid, and provides UI elements to switch between a full 3D model and a 2D slice, adjust opacity, and optionally hide elements without assigned values. Arguments: grid (Union[pv.StructuredGrid, pv.UnstructuredGrid]): The grid to be visualized. pixel_type (PixelValueType): Specifies whether the pixel data is RGB or scalar. ele_has_value (np.ndarray | None, optional): A boolean array indicating which elements have assigned values. If None, all elements are assumed to have values. Defaults to None. title (str | None, optional): The title of the plot window. Defaults to None. Returns: None """ self.plotter.window_size = [1024, 768] self.plotter.title = self.title self.slice_height = (self.grid.bounds[4] + self.grid.bounds[5]) / 2 self._toggle_slicer() self._show_3d_model() if self.nan_exist: self.plotter.add_text( "Toggle Nan-Elements:", position="upper_left", font_size=8, color="black", ) self.plotter.add_checkbox_button_widget( self._toggle_nan_view, size=30, value=True, position=(210, 740) ) if isinstance(self.grid, pv.UnstructuredGrid): self.plotter.add_text( "Toggle Edges", position=(35, 605), font_size=8, color="black" ) self.plotter.add_checkbox_button_widget( self._toggle_edges, size=30, value=False, position=(1, 600) ) self.plotter.add_text( "Toggle 3D/Slice View", position=(35, 655), font_size=8, color="black", ) self.plotter.add_checkbox_button_widget( self._toggle_view, value=True, position=(1, 650), size=30, ) self.plotter.show()
Visualizes a structured or unstructured grid using PyVista with interactive controls for opacity adjustment, slice visualization, and NaN element toggling.
This function initializes a PyVista plotter, displays the grid, and provides UI elements to switch between a full 3D model and a 2D slice, adjust opacity, and optionally hide elements without assigned values.
Arguments
grid (Union[pv.StructuredGrid, pv.UnstructuredGrid]): The grid to be visualized. pixel_type (PixelValueType): Specifies whether the pixel data is RGB or scalar. ele_has_value (np.ndarray | None, optional): A boolean array indicating which elements have assigned values. If None, all elements are assumed to have values. Defaults to None. title (str | None, optional): The title of the plot window. Defaults to None.
Returns
None