def test_background_plotting_menu_bar(qtbot): with pytest.raises(TypeError, match='menu_bar'): BackgroundPlotter(off_screen=False, menu_bar="foo") plotter = BackgroundPlotter(off_screen=False, menu_bar=False) assert plotter.main_menu is None assert plotter._menu_close_action is None plotter.close() plotter = BackgroundPlotter(off_screen=False) # menu_bar=True assert _hasattr(plotter, "app_window", MainWindow) assert _hasattr(plotter, "main_menu", QMenuBar) assert _hasattr(plotter, "_menu_close_action", QAction) window = plotter.app_window main_menu = plotter.main_menu assert not main_menu.isNativeMenuBar() with qtbot.wait_exposed(window, timeout=500): window.show() assert main_menu.isVisible() plotter.close() assert not main_menu.isVisible()
def test_background_plotting_toolbar(qtbot, plotting): with pytest.raises(TypeError, match='toolbar'): p = BackgroundPlotter(off_screen=False, toolbar="foo") p.close() plotter = BackgroundPlotter(off_screen=False, toolbar=False) assert plotter.default_camera_tool_bar is None assert plotter.saved_camera_positions is None assert plotter.saved_cameras_tool_bar is None plotter.close() plotter = BackgroundPlotter(off_screen=False) assert_hasattr(plotter, "app_window", MainWindow) assert_hasattr(plotter, "default_camera_tool_bar", QToolBar) assert_hasattr(plotter, "saved_camera_positions", list) assert_hasattr(plotter, "saved_cameras_tool_bar", QToolBar) window = plotter.app_window default_camera_tool_bar = plotter.default_camera_tool_bar saved_cameras_tool_bar = plotter.saved_cameras_tool_bar with qtbot.wait_exposed(window): window.show() assert default_camera_tool_bar.isVisible() assert saved_cameras_tool_bar.isVisible() # triggering a view action plotter._view_action.trigger() plotter.close()
def _create_testing_scene(empty_scene, show=False, off_screen=False): if empty_scene: plotter = BackgroundPlotter(show=show, off_screen=off_screen) else: plotter = BackgroundPlotter(shape=(2, 2), border=True, border_width=10, border_color='grey', show=show, off_screen=off_screen) plotter.set_background('black', top='blue') plotter.subplot(0, 0) cone = pyvista.Cone(resolution=4) actor = plotter.add_mesh(cone) plotter.remove_actor(actor) plotter.add_text('Actor is removed') plotter.subplot(0, 1) plotter.add_mesh(pyvista.Box(), color='green', opacity=0.8) plotter.subplot(1, 0) cylinder = pyvista.Cylinder(resolution=6) plotter.add_mesh(cylinder, smooth_shading=True) plotter.show_bounds() plotter.subplot(1, 1) sphere = pyvista.Sphere(phi_resolution=6, theta_resolution=6) plotter.add_mesh(sphere) plotter.enable_cell_picking() return plotter
def test_off_screen(qtbot): plotter = BackgroundPlotter(off_screen=False) qtbot.addWidget(plotter.app_window) assert not plotter.ren_win.GetOffScreenRendering() plotter.close() plotter = BackgroundPlotter(off_screen=True) qtbot.addWidget(plotter.app_window) assert plotter.ren_win.GetOffScreenRendering() plotter.close()
def test_editor(qtbot): timeout = 1000 # adjusted timeout for MacOS # editor=True by default plotter = BackgroundPlotter(shape=(2, 1)) qtbot.addWidget(plotter.app_window) assert_hasattr(plotter, "editor", Editor) # add at least an actor plotter.subplot(0, 0) plotter.add_mesh(pyvista.Sphere()) plotter.subplot(1, 0) plotter.show_axes() editor = plotter.editor assert not editor.isVisible() with qtbot.wait_exposed(editor, timeout=timeout): editor.toggle() assert editor.isVisible() assert_hasattr(editor, "tree_widget", QTreeWidget) tree_widget = editor.tree_widget top_item = tree_widget.topLevelItem(0) # any renderer will do assert top_item is not None # simulate selection with qtbot.wait_signals([tree_widget.itemSelectionChanged], timeout=timeout): top_item.setSelected(True) # toggle all the renderer-associated checkboxes twice # to ensure that slots are called for True and False assert_hasattr(editor, "stacked_widget", QStackedWidget) stacked_widget = editor.stacked_widget page_idx = top_item.data(0, Qt.ItemDataRole.UserRole) page_widget = stacked_widget.widget(page_idx) page_layout = page_widget.layout() number_of_widgets = page_layout.count() for widget_idx in range(number_of_widgets): widget_item = page_layout.itemAt(widget_idx) widget = widget_item.widget() if isinstance(widget, QCheckBox): with qtbot.wait_signals([widget.toggled], timeout=500): widget.toggle() with qtbot.wait_signals([widget.toggled], timeout=500): widget.toggle() # hide the editor for coverage editor.toggle() plotter.close() plotter = BackgroundPlotter(editor=False) qtbot.addWidget(plotter.app_window) assert plotter.editor is None plotter.close()
def test_depth_peeling(qtbot): plotter = BackgroundPlotter() qtbot.addWidget(plotter.app_window) assert not plotter.renderer.GetUseDepthPeeling() plotter.close() global_theme.depth_peeling["enabled"] = True plotter = BackgroundPlotter() qtbot.addWidget(plotter.app_window) assert plotter.renderer.GetUseDepthPeeling() plotter.close() global_theme.depth_peeling["enabled"] = False
def test_smoothing(qtbot): plotter = BackgroundPlotter() qtbot.addWidget(plotter.app_window) assert not plotter.ren_win.GetPolygonSmoothing() assert not plotter.ren_win.GetLineSmoothing() assert not plotter.ren_win.GetPointSmoothing() plotter.close() plotter = BackgroundPlotter( polygon_smoothing=True, line_smoothing=True, point_smoothing=True, ) qtbot.addWidget(plotter.app_window) assert plotter.ren_win.GetPolygonSmoothing() assert plotter.ren_win.GetLineSmoothing() assert plotter.ren_win.GetPointSmoothing() plotter.close()
def test_background_plotting_menu_bar(qtbot, plotting): with pytest.raises(TypeError, match='menu_bar'): p = BackgroundPlotter(off_screen=False, menu_bar="foo") p.close() plotter = BackgroundPlotter(off_screen=False, menu_bar=False) assert plotter.main_menu is None assert plotter._menu_close_action is None plotter.close() plotter = BackgroundPlotter(off_screen=False) # menu_bar=True assert_hasattr(plotter, "app_window", MainWindow) assert_hasattr(plotter, "main_menu", QMenuBar) assert_hasattr(plotter, "_menu_close_action", QAction) assert_hasattr(plotter, "_edl_action", QAction) assert_hasattr(plotter, "_parallel_projection_action", QAction) window = plotter.app_window main_menu = plotter.main_menu assert not main_menu.isNativeMenuBar() with qtbot.wait_exposed(window): window.show() # EDL action assert not hasattr(plotter.renderer, 'edl_pass') plotter._edl_action.trigger() assert hasattr(plotter.renderer, 'edl_pass') # and now test reset plotter._edl_action.trigger() # Parallel projection action assert not plotter.camera.GetParallelProjection() plotter._parallel_projection_action.trigger() assert plotter.camera.GetParallelProjection() # and now test reset plotter._parallel_projection_action.trigger() assert main_menu.isVisible() plotter.close() assert not main_menu.isVisible() assert plotter._last_update_time == -np.inf
def test_background_plotting_add_callback(qtbot): class CallBack(object): def __init__(self, sphere): self.sphere = sphere def __call__(self): self.sphere.points *= 0.5 plotter = BackgroundPlotter(show=False, off_screen=False, title='Testing Window') sphere = pyvista.Sphere() mycallback = CallBack(sphere) plotter.add_mesh(sphere) plotter.add_callback(mycallback, interval=200, count=3) # check that timers are set properly in add_callback() assert _hasattr(plotter, "app_window", MainWindow) assert _hasattr(plotter, "_callback_timer", QTimer) assert _hasattr(plotter, "counters", list) window = plotter.app_window # MainWindow callback_timer = plotter._callback_timer # QTimer counter = plotter.counters[-1] # Counter # ensure that the window is showed assert not window.isVisible() with qtbot.wait_exposed(window, timeout=500): window.show() assert window.isVisible() # ensure that self.callback_timer send a signal callback_blocker = qtbot.wait_signals([callback_timer.timeout], timeout=300) callback_blocker.wait() # ensure that self.counters send a signal counter_blocker = qtbot.wait_signals([counter.signal_finished], timeout=700) counter_blocker.wait() assert not callback_timer.isActive() # counter stops the callback plotter.add_callback(mycallback, interval=200) callback_timer = plotter._callback_timer # QTimer # ensure that self.callback_timer send a signal callback_blocker = qtbot.wait_signals([callback_timer.timeout], timeout=300) callback_blocker.wait() assert callback_timer.isActive() plotter.close() assert not callback_timer.isActive() # window stops the callback
def draw_3D( self, opacity: float = 1, display_p_int: bool = True, molecule_opacity: float = 1, atom_scale: float = 1, ) -> None: """Draw surface with mapped P_int values. Args: opacity: Surface opacity display_p_int: Whether to display P_int mapped onto the surface molecule_opacity: Molecule opacity atom_scale: Scale factor for atom size """ # Set up plotter p = BackgroundPlotter() # Draw molecule for atom in self._atoms: color = hex2color(jmol_colors[atom.element]) radius = atom.radius * atom_scale sphere = pv.Sphere(center=list(atom.coordinates), radius=radius) p.add_mesh(sphere, color=color, opacity=molecule_opacity, name=str(atom.index)) cmap: Optional[str] # Set up plotting of mapped surface if display_p_int is True: color = None cmap = "coolwarm" else: color = "tan" cmap = None # Draw surface if self._surface: p.add_mesh(self._surface, opacity=opacity, color=color, cmap=cmap) else: point_cloud = pv.PolyData(self._points) point_cloud["values"] = self.p_values p.add_mesh( point_cloud, opacity=opacity, color=color, cmap=cmap, render_points_as_spheres=True, )
def draw_3D( self, atom_scale: float = 1, background_color: str = "white", cone_color: str = "steelblue", cone_opacity: float = 0.75, ) -> None: """Draw a 3D representation of the molecule with the cone. Args: atom_scale: Scaling factor for atom size background_color: Background color for plot cone_color: Cone color cone_opacity: Cone opacity """ # Set up plotter p = BackgroundPlotter() p.set_background(background_color) # Draw molecule for atom in self._atoms: color = hex2color(jmol_colors[atom.element]) radius = atom.radius * atom_scale sphere = pv.Sphere(center=list(atom.coordinates), radius=radius) p.add_mesh(sphere, color=color, opacity=1, name=str(atom.index)) # Determine direction and extension of cone angle = math.degrees(self._cone.angle) coordinates: Array2DFloat = np.array([atom.coordinates for atom in self._atoms]) radii: Array1DFloat = np.array([atom.radius for atom in self._atoms]) if angle > 180: normal = -self._cone.normal else: normal = self._cone.normal projected = np.dot(normal, coordinates.T) + np.array(radii) max_extension = np.max(projected) if angle > 180: max_extension += 1 # Make the cone cone = get_drawing_cone( center=[0, 0, 0] + (max_extension * normal) / 2, direction=-normal, angle=angle, height=max_extension, capping=False, resolution=100, ) p.add_mesh(cone, opacity=cone_opacity, color=cone_color)
def test_background_plotter_export_vtkjs(qtbot, tmpdir, show_plotter, plotting): # setup filesystem output_dir = str(tmpdir.mkdir("tmpdir")) assert os.path.isdir(output_dir) plotter = BackgroundPlotter( show=show_plotter, off_screen=False, title='Testing Window' ) assert_hasattr(plotter, "app_window", MainWindow) window = plotter.app_window # MainWindow qtbot.addWidget(window) # register the window # show the window if not show_plotter: assert not window.isVisible() with qtbot.wait_exposed(window): window.show() assert window.isVisible() plotter.add_mesh(pyvista.Sphere()) assert_hasattr(plotter, "renderer", Renderer) renderer = plotter.renderer assert len(renderer._actors) == 1 assert np.any(plotter.mesh.points) dlg = plotter._qt_export_vtkjs(show=False) # FileDialog qtbot.addWidget(dlg) # register the dialog filename = str(os.path.join(output_dir, "tmp")) dlg.selectFile(filename) # show the dialog assert not dlg.isVisible() with qtbot.wait_exposed(dlg): dlg.show() assert dlg.isVisible() # synchronise signal and callback with qtbot.wait_signals([dlg.dlg_accepted], timeout=1000): dlg.accept() assert not dlg.isVisible() # dialog is closed after accept() plotter.close() assert not window.isVisible() assert os.path.isfile(filename + '.vtkjs')
def test_background_plotting_axes_scale(qtbot, show_plotter, plotting): plotter = BackgroundPlotter( show=show_plotter, off_screen=False, title='Testing Window' ) assert_hasattr(plotter, "app_window", MainWindow) window = plotter.app_window # MainWindow qtbot.addWidget(window) # register the window # show the window if not show_plotter: assert not window.isVisible() with qtbot.wait_exposed(window): window.show() assert window.isVisible() plotter.add_mesh(pyvista.Sphere()) assert_hasattr(plotter, "renderer", Renderer) renderer = plotter.renderer assert len(renderer._actors) == 1 assert np.any(plotter.mesh.points) dlg = plotter.scale_axes_dialog(show=False) # ScaleAxesDialog qtbot.addWidget(dlg) # register the dialog # show the dialog assert not dlg.isVisible() with qtbot.wait_exposed(dlg): dlg.show() assert dlg.isVisible() value = 2.0 dlg.x_slider_group.value = value assert plotter.scale[0] == value dlg.x_slider_group.spinbox.setValue(-1) assert dlg.x_slider_group.value == 0 dlg.x_slider_group.spinbox.setValue(1000.0) assert dlg.x_slider_group.value < 100 plotter._last_update_time = 0.0 plotter.update() plotter.update_app_icon() plotter.close() assert not window.isVisible() assert not dlg.isVisible()
def test_background_plotting_camera(qtbot, plotting): plotter = BackgroundPlotter(off_screen=False, title='Testing Window') plotter.add_mesh(pyvista.Sphere()) cpos = [(0.0, 0.0, 1.0), (0.0, 0.0, 0.0), (0.0, 1.0, 0.0)] plotter.camera_position = cpos plotter.save_camera_position() plotter.camera_position = [(0.0, 0.0, 3.0), (0.0, 0.0, 0.0), (0.0, 1.0, 0.0)] # load existing position # NOTE: 2 because first two (0 and 1) buttons save and clear positions plotter.saved_cameras_tool_bar.actions()[2].trigger() assert plotter.camera_position == cpos plotter.clear_camera_positions() # 2 because the first two buttons are save and clear assert len(plotter.saved_cameras_tool_bar.actions()) == 2 plotter.close()
def plot_boreholes(self, notebook=False, background=False, **kwargs): """ Uses the previously calculated borehole tubes in self._get_polygon_data() when a borehole dictionary is available This will generate a pyvista object that can be visualized with .show() Args: notebook: If using in notebook to show inline background: Returns: Pyvista object with all the boreholes """ self._get_polygon_data() if background: try: p = pv.BackgroundPlotter(**kwargs) except pv.QtDeprecationError: from pyvistaqt import BackgroundPlotter p = BackgroundPlotter(**kwargs) else: p = pv.Plotter(notebook=notebook, **kwargs) for i in range(len(self.borehole_tube)): cmap = self.colors_bh[i] p.add_mesh(self.borehole_tube[i], cmap=[cmap[j] for j in range(len(cmap)-1)], smooth_shading=False) # for i in range(len(self.faults_bh)): # for plotting the faults # TODO: Messing with the colors when faults if len(self.faults_bh) > 0: point = pv.PolyData(self.faults_bh) p.add_mesh(point, render_points_as_spheres=True, point_size=self._radius_borehole) # p.add_mesh(point, cmap = self.faults_color_bh[i], # render_points_as_spheres=True, point_size=self._radius_borehole) extent = numpy.copy(self._model_extent) # extent[-1] = numpy.ceil(self.modelspace_arucos.box_z.max()/100)*100 p.show_bounds(bounds=extent) p.show_grid() p.set_scale(zscale=self._ve) # self.vtk = pn.panel(p.ren_win, sizing_mode='stretch_width', orientation_widget=True) # self.vtk = pn.Row(pn.Column(pan, pan.construct_colorbars()), pn.pane.Str(type(p.ren_win), width=500)) return p
def __init__(self, parent=None, show=True): Qt.QMainWindow.__init__(self, parent) self.ds = reader.DataSet("") self.meshes = [] self.plotter = BackgroundPlotter(shape=(1, 2), border_color='white', title="MMR Visualization") self.setWindowTitle('MMR UI') self.frame = Qt.QFrame() vlayout = Qt.QVBoxLayout() self.normalizer = Normalizer() self.frame.setLayout(vlayout) self.setCentralWidget(self.frame) mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('File') exitButton = Qt.QAction('Exit', self) exitButton.setShortcut('Ctrl+Q') exitButton.triggered.connect(self.close) fileMenu.addAction(exitButton) meshMenu = mainMenu.addMenu('Mesh') self.load_mesh = Qt.QAction('Load mesh', self) self.load_mesh.triggered.connect( lambda: self.add_mesh(self.open_file_name_dialog())) meshMenu.addAction(self.load_mesh) self.show_norm_pipeline = Qt.QAction('Show norm pipeline', self) self.show_norm_pipeline.triggered.connect( lambda: self.show_processing(self.open_file_name_dialog())) meshMenu.addAction(self.show_norm_pipeline) self.extract_features = Qt.QAction('Extract features', self) self.extract_features.triggered.connect(lambda: print( FeatureExtractor.mono_run_pipeline(self.open_file_name_dialog()))) meshMenu.addAction(self.extract_features) if show: self.show()
def draw_3D( self, atom_scale: float = 1, background_color: str = "white", point_color: str = "steelblue", opacity: float = 0.25, size: float = 1, ) -> None: """Draw a 3D representation. Draws the molecule with the solvent accessible surface area. Args: atom_scale: Scaling factor for atom size background_color: Background color for plot point_color: Color of surface points opacity: Point opacity size: Point size """ # Set up plotter p = BackgroundPlotter() p.set_background(background_color) # Draw molecule for atom in self._atoms: color = hex2color(jmol_colors[atom.element]) radius = atom.radius * atom_scale - self._probe_radius sphere = pv.Sphere(center=list(atom.coordinates), radius=radius) p.add_mesh(sphere, color=color, opacity=1, name=str(atom.index)) # Draw surface points surface_points: Array2DFloat = np.vstack( [atom.accessible_points for atom in self._atoms]) p.add_points(surface_points, color=point_color, opacity=opacity, point_size=size)
def show_processing(self, mesh): if not mesh: print(f"Can't render mesh of type {type(mesh)}") return None new_data = self.normalizer.mono_run_pipeline(mesh) history = new_data["history"] num_of_operations = len(history) plt = BackgroundPlotter(shape=(2, num_of_operations // 2)) elements = history plt.show_axes_all() for idx in range(num_of_operations): plt.subplot(int(idx / 3), idx % 3) if elements[idx]["op"] == "Center": plt.add_mesh(pv.Cube().extract_all_edges()) curr_mesh = pv.PolyData(elements[idx]["data"]["vertices"], elements[idx]["data"]["faces"]) plt.add_mesh(curr_mesh, color='w', show_edges=True) plt.reset_camera() plt.view_isometric() plt.add_text(elements[idx]["op"] + "\nVertices: " + str(len(curr_mesh.points)) + "\nFaces: " + str(curr_mesh.n_faces)) plt.show_grid()
def __init__(self, model, plotter_type: str = 'basic', extent=None, lith_c=None, live_updating=False, **kwargs): """GemPy 3-D visualization using pyVista. Args: model (gp.Model): Geomodel instance with solutions. plotter_type (str): Set the plotter type. Defaults to 'basic'. extent (List[float], optional): Custom extent. Defaults to None. lith_c (pn.DataFrame, optional): Custom color scheme in the form of a look-up table. Defaults to None. live_updating (bool, optional): Toggles real-time updating of the plot. Defaults to False. **kwargs: """ # Override default notebook value pv.set_plot_theme("document") kwargs['notebook'] = kwargs.get('notebook', False) # Model properties self.model = model self.extent = model._grid.regular_grid.extent if extent is None else extent # plotting options self.live_updating = live_updating # Choosing plotter if plotter_type == 'basic': self.p = pv.Plotter(**kwargs) self.p.view_isometric(negative=False) elif plotter_type == 'notebook': raise NotImplementedError # self.p = pv.PlotterITK() elif plotter_type == 'background': try: self.p = pv.BackgroundPlotter(**kwargs) except pv.QtDeprecationError: from pyvistaqt import BackgroundPlotter self.p = BackgroundPlotter(**kwargs) self.p.view_isometric(negative=False) else: raise AttributeError( 'Plotter type must be basic, background or notebook.') self.plotter_type = plotter_type # Default camera and bounds self.set_bounds() self.p.view_isometric(negative=False) # Actors containers self.surface_actors = {} self.surface_poly = {} self.regular_grid_actor = None self.regular_grid_mesh = None self.surface_points_actor = None self.surface_points_mesh = None self.surface_points_widgets = {} self.orientations_actor = None self.orientations_mesh = None self.orientations_widgets = {} # Private attributes self._grid_values = None col = matplotlib.cm.get_cmap('viridis')(np.linspace(0, 1, 255)) * 255 nv = numpy_to_vtk(col, array_type=3) self._cmaps = {'viridis': nv} # Topology properties self.topo_edges = None self.topo_ctrs = None
def draw_3D( self, atom_scale: float = 0.5, background_color: str = "white", arrow_color: str = "steelblue", ) -> None: """Draw a 3D representation of the molecule with the Sterimol vectors. Args: atom_scale: Scaling factor for atom size background_color: Background color for plot arrow_color: Arrow color """ # Set up plotter p = BackgroundPlotter() p.set_background(background_color) # Draw molecule for atom in self._atoms: color = hex2color(jmol_colors[atom.element]) if atom.element == 0: radius = 0.5 * atom_scale else: radius = atom.radius * atom_scale sphere = pv.Sphere(center=list(atom.coordinates), radius=radius) if atom.index in self._excluded_atoms: opacity = 0.25 else: opacity = 1 p.add_mesh(sphere, color=color, opacity=opacity, name=str(atom.index)) # Draw sphere for Buried Sterimol if hasattr(self, "_sphere_radius"): sphere = pv.Sphere(center=self._dummy_atom.coordinates, radius=self._sphere_radius) p.add_mesh(sphere, opacity=0.25) if hasattr(self, "_points"): p.add_points(self._points, color="gray") # Get arrow starting points start_L = self._dummy_atom.coordinates start_B = self._attached_atom.coordinates # Add L arrow with label length = np.linalg.norm(self.L) direction = self.L / length stop_L = start_L + length * direction L_arrow = get_drawing_arrow(start=start_L, direction=direction, length=length) p.add_mesh(L_arrow, color=arrow_color) # Add B_1 arrow length = np.linalg.norm(self.B_1) direction = self.B_1 / length stop_B_1 = start_B + length * direction B_1_arrow = get_drawing_arrow(start=start_B, direction=direction, length=length) p.add_mesh(B_1_arrow, color=arrow_color) # Add B_5 arrow length = np.linalg.norm(self.B_5) direction = self.B_5 / length stop_B_5 = start_B + length * direction B_5_arrow = get_drawing_arrow(start=start_B, direction=direction, length=length) p.add_mesh(B_5_arrow, color=arrow_color) # Add labels points = np.vstack([stop_L, stop_B_1, stop_B_5]) labels = ["L", "B1", "B5"] p.add_point_labels( points, labels, text_color="black", font_size=30, bold=False, show_points=False, point_size=1, ) self._plotter = p
def test_background_plotting_add_callback(qtbot, monkeypatch, plotting): class CallBack(object): def __init__(self, sphere): self.sphere = sphere def __call__(self): self.sphere.points *= 0.5 update_count = [0] orig_update_app_icon = BackgroundPlotter.update_app_icon def update_app_icon(slf): update_count[0] = update_count[0] + 1 return orig_update_app_icon(slf) monkeypatch.setattr(BackgroundPlotter, 'update_app_icon', update_app_icon) plotter = BackgroundPlotter( show=False, off_screen=False, title='Testing Window', update_app_icon=True, # also does add_callback ) assert plotter._last_update_time == -np.inf sphere = pyvista.Sphere() mycallback = CallBack(sphere) plotter.add_mesh(sphere) plotter.add_callback(mycallback, interval=200, count=3) # check that timers are set properly in add_callback() assert_hasattr(plotter, "app_window", MainWindow) assert_hasattr(plotter, "_callback_timer", QTimer) assert_hasattr(plotter, "counters", list) window = plotter.app_window # MainWindow callback_timer = plotter._callback_timer # QTimer counter = plotter.counters[-1] # Counter # ensure that the window is showed assert not window.isVisible() with qtbot.wait_exposed(window): window.show() assert window.isVisible() assert update_count[0] in [0, 1] # macOS sometimes updates (1) # don't check _last_update_time for non-inf-ness, won't be updated on Win plotter.update_app_icon() # the timer doesn't call it right away, so do it assert update_count[0] in [1, 2] plotter.update_app_icon() # should be a no-op assert update_count[0] in [2, 3] with pytest.raises(ValueError, match="ndarray with shape"): plotter.set_icon(0.) # Maybe someday manually setting "set_icon" should disable update_app_icon? # Strings also supported directly by QIcon plotter.set_icon(os.path.join( os.path.dirname(pyvistaqt.__file__), "data", "pyvista_logo_square.png")) # ensure that self.callback_timer send a signal callback_blocker = qtbot.wait_signals([callback_timer.timeout], timeout=300) callback_blocker.wait() # ensure that self.counters send a signal counter_blocker = qtbot.wait_signals([counter.signal_finished], timeout=700) counter_blocker.wait() assert not callback_timer.isActive() # counter stops the callback plotter.add_callback(mycallback, interval=200) callback_timer = plotter._callback_timer # QTimer # ensure that self.callback_timer send a signal callback_blocker = qtbot.wait_signals([callback_timer.timeout], timeout=300) callback_blocker.wait() assert callback_timer.isActive() plotter.close() assert not callback_timer.isActive() # window stops the callback
# -*- coding: utf-8 -*- """ Simplest possible PyVista Background plotter code Author: Jari Honkanen """ import pyvista as pv from pyvistaqt import BackgroundPlotter # Get Sphere shape sphere = pv.Sphere() # Instantiate Background Plotter plotter = BackgroundPlotter() plotter.add_mesh(sphere) # Run in Python (iPython not needed) plotter.app.exec_()
def test_background_plotting_orbit(qtbot, plotting): plotter = BackgroundPlotter(off_screen=False, title='Testing Window') plotter.add_mesh(pyvista.Sphere()) # perform the orbit: plotter.orbit_on_path(threaded=True, step=0.0) plotter.close()