Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
c0fbf2c
feat: Add PyVista Qt support
AlejandroFernandezLuces Nov 20, 2024
3bb9f2b
feat: Add example
AlejandroFernandezLuces Nov 20, 2024
492e9fc
test: Add test for Qt backend
AlejandroFernandezLuces Nov 20, 2024
c6208cb
chore: adding changelog file 192.added.md [dependabot-skip]
pyansys-ci-bot Nov 20, 2024
c864bc7
feat: Add PyVistaQt as optional dependency
AlejandroFernandezLuces Nov 20, 2024
8aacc0f
Merge branch 'feat/add-pyvistaqt-support' of https://github.com/ansys…
AlejandroFernandezLuces Nov 20, 2024
87d0227
fix(temp): Try windows machine
AlejandroFernandezLuces Nov 20, 2024
1357f71
fix(temp): Windows test
AlejandroFernandezLuces Nov 20, 2024
d7ba564
fix: Update python version in CICD
AlejandroFernandezLuces Nov 20, 2024
d931271
fix: Possible missing installations
AlejandroFernandezLuces Nov 20, 2024
2211c18
fix: Add qt plugin
AlejandroFernandezLuces Nov 20, 2024
f8d065d
fix: Installable
AlejandroFernandezLuces Nov 20, 2024
26934fa
fix: Missing sudo
AlejandroFernandezLuces Nov 20, 2024
ed4a6fb
fix: More installations
AlejandroFernandezLuces Nov 20, 2024
e8958de
temp: Downgrade PySide6
AlejandroFernandezLuces Nov 21, 2024
6cc09ec
fix: Doc dependency
AlejandroFernandezLuces Nov 21, 2024
430570d
fix: Dependencies
AlejandroFernandezLuces Nov 21, 2024
5595c57
fix: Dependency
AlejandroFernandezLuces Nov 21, 2024
e93241b
test
AlejandroFernandezLuces Nov 21, 2024
54cf87a
fix: deps
AlejandroFernandezLuces Nov 21, 2024
f7eb4cc
fix: Deps
AlejandroFernandezLuces Nov 21, 2024
2ca6e59
fix deps
AlejandroFernandezLuces Nov 21, 2024
1128b44
fix: Deps
AlejandroFernandezLuces Nov 21, 2024
3bdb57d
examples test
AlejandroFernandezLuces Nov 21, 2024
cd4df1b
fixes
AlejandroFernandezLuces Nov 21, 2024
fcdf1d9
feat: Implement close for PyvistaQT
AlejandroFernandezLuces Nov 21, 2024
8151f48
fix: linux deps
AlejandroFernandezLuces Nov 21, 2024
37b173c
fix: linux deps
AlejandroFernandezLuces Nov 21, 2024
3fc8d5b
fix: Linux deps
AlejandroFernandezLuces Nov 21, 2024
a638e99
fix: linux deps
AlejandroFernandezLuces Nov 21, 2024
3000aab
fix: deps
AlejandroFernandezLuces Nov 21, 2024
0639461
test
AlejandroFernandezLuces Nov 21, 2024
2ffbcef
test
AlejandroFernandezLuces Nov 21, 2024
c08845b
fix: linux dep
AlejandroFernandezLuces Nov 21, 2024
c18d570
test
AlejandroFernandezLuces Nov 21, 2024
48f6f5c
test
AlejandroFernandezLuces Nov 21, 2024
02cb7bc
test
AlejandroFernandezLuces Nov 21, 2024
d6e1480
fix: Skip Qt test
AlejandroFernandezLuces Nov 21, 2024
0f3ac43
fix: Remove code execution from example
AlejandroFernandezLuces Nov 21, 2024
508b625
fix: Refactor to have independent backend
AlejandroFernandezLuces Nov 22, 2024
e688320
fix: Depenency pinning, remove sys deps
AlejandroFernandezLuces Nov 22, 2024
42a3459
fix: Minor details
AlejandroFernandezLuces Nov 22, 2024
aba32e4
fix: Sys deps
AlejandroFernandezLuces Nov 22, 2024
cb593a4
Revert "fix: Sys deps"
AlejandroFernandezLuces Nov 22, 2024
5678add
fix: Revert refactor commits
AlejandroFernandezLuces Nov 22, 2024
c6c68d3
Merge branch 'feat/add-pyvistaqt-support' of https://github.com/ansys…
AlejandroFernandezLuces Nov 22, 2024
7915d3b
fix: Review comments
AlejandroFernandezLuces Nov 22, 2024
a4ed118
fix: Commented code
AlejandroFernandezLuces Nov 22, 2024
b5995f1
fix: Revert code block comment in examples
AlejandroFernandezLuces Nov 22, 2024
74f6b87
fix: Add missing import check
AlejandroFernandezLuces Nov 22, 2024
6c6fcc5
fix: Align env variables
AlejandroFernandezLuces Nov 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci_cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ on:
- main

env:
MAIN_PYTHON_VERSION: '3.11'
MAIN_PYTHON_VERSION: '3.12'
RESET_IMAGE_CACHE: 0
PACKAGE_NAME: ansys-tools-visualization-interface
DOCUMENTATION_CNAME: visualization-interface.tools.docs.pyansys.com
IN_GITHUB_ACTIONS: true

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -104,6 +105,8 @@ jobs:
needs: [ smoke-tests ]
runs-on: ubuntu-latest
steps:
- name: Install system dependencies
run: sudo apt install libegl1 libxcb-cursor0 libsm6 libxext6 libxcb-xinerama0 -y
- name: Restore images cache
uses: actions/cache@v4
with:
Expand Down
1 change: 1 addition & 0 deletions doc/changelog.d/192.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
feat: Add PyVista Qt support
71 changes: 71 additions & 0 deletions examples/00-basic-pyvista-examples/qt_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
.. _ref_backgroundplotter:

========================
Use a PyVista Qt backend
========================

PyVista Qt is a package that extends the PyVista functionality through the
usage of Qt. Qt applications operate in a separate thread than VTK, you can
simultaneously have an active VTK plot and a non-blocking Python session.

This example shows how to use the PyVista Qt backend to create a plotter
"""

import pyvista as pv

from ansys.tools.visualization_interface import Plotter
from ansys.tools.visualization_interface.backends.pyvista import PyVistaBackend

#########################
# Open a pyvistaqt window
# =======================
# .. code-block:: python
#
# cube = pv.Cube()
# pv_backend = PyVistaBackend(use_qt=True)
# pl = Plotter(backend=pv_backend)
# pl.plot(cube)
# pl.show()
#


#####################
# Parallel VTK window
# ===================

sphere = pv.Sphere()

pl_parallel = Plotter()
pl_parallel.plot(sphere)
pl_parallel.show()

############################
# Close the pyvistaqt window
# ==========================
# .. code-block:: python
#
# pv_backend.close()
#
14 changes: 13 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,19 @@ dependencies = [
]

[project.optional-dependencies]
tests = ["pytest==8.3.3", "pytest-pyvista==0.1.9", "pytest-cov==6.0.0"]
pyvistaqt = [
"pyside6 >= 6.8.0,<7",
"pyvistaqt >= 0.11.1,<1",
]
tests = [
"pytest==8.3.3",
"pytest-pyvista==0.1.9",
"pytest-cov==6.0.0",
"pyside6==6.7.3",
"pyvistaqt==0.11.1,<1",
"pytest-qt"
]

doc = [
"ansys-sphinx-theme==1.2.0",
"jupyter_sphinx==0.5.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ class PyVistaBackendInterface(BaseBackend):
allow_hovering : Optional[bool], default: False
Whether to allow hovering capabilities in the window. Incompatible with picking.
Picking will take precedence over hovering.
plot_picked_names : Optional[bool], default: False
Whether to plot the names of the picked objects.
show_plane : Optional[bool], default: False
Whether to show the plane in the plotter.
use_qt : Optional[bool], default: False
Whether to use the Qt backend for the plotter.
"""

def __init__(
Expand All @@ -93,13 +99,14 @@ def __init__(
allow_hovering: Optional[bool] = False,
plot_picked_names: Optional[bool] = False,
show_plane: Optional[bool] = False,
use_qt: Optional[bool] = False,
**plotter_kwargs,
) -> None:
"""Initialize the ``use_trame`` parameter and save the current ``pv.OFF_SCREEN`` value."""
# Check if the use of trame was requested
if use_trame is None:
use_trame = ansys.tools.visualization_interface.USE_TRAME

self._use_qt = use_qt
self._use_trame = use_trame
self._allow_picking = allow_picking
self._allow_hovering = allow_hovering
Expand Down Expand Up @@ -146,7 +153,7 @@ def __init__(
logger.warning(warn_msg)
self._pl = PyVistaInterface(show_plane=show_plane)
else:
self._pl = PyVistaInterface(show_plane=show_plane)
self._pl = PyVistaInterface(show_plane=show_plane, use_qt=use_qt, **plotter_kwargs)

self._enable_widgets = self._pl._enable_widgets

Expand Down Expand Up @@ -175,7 +182,8 @@ def enable_widgets(self):
]
self._widgets.append(MeasureWidget(self))
self._widgets.append(ScreenshotButton(self))
self._widgets.append(MeshSliderWidget(self))
if not self._use_qt:
self._widgets.append(MeshSliderWidget(self))
self._widgets.append(HideButton(self))

def add_widget(self, widget: Union[PlotterWidget, List[PlotterWidget]]):
Expand Down Expand Up @@ -541,10 +549,11 @@ def __init__(
use_trame: Optional[bool] = None,
allow_picking: Optional[bool] = False,
allow_hovering: Optional[bool] = False,
plot_picked_names: Optional[bool] = True
plot_picked_names: Optional[bool] = True,
use_qt: Optional[bool] = False
) -> None:
"""Initialize the generic plotter."""
super().__init__(use_trame, allow_picking, allow_hovering, plot_picked_names)
super().__init__(use_trame, allow_picking, allow_hovering, plot_picked_names, use_qt=use_qt)

def plot_iter(
self,
Expand Down Expand Up @@ -591,3 +600,7 @@ def plot(self, plottable_object: Any, name_filter: str = None, **plotting_option
else:
self.pv_interface.plot(plottable_object, name_filter, **plotting_options)

def close(self):
"""Close the plotter for PyVistaQT."""
if self._use_qt:
self.pv_interface.scene.close()
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Provides plotting for various PyAnsys objects."""
import importlib
import re
from typing import Any, Dict, List, Optional, Union

Expand All @@ -33,6 +34,9 @@
from ansys.tools.visualization_interface.utils.color import Color
from ansys.tools.visualization_interface.utils.logger import logger

_HAS_PYVISTAQT = importlib.util.find_spec("pyvistaqt")
if _HAS_PYVISTAQT:
import pyvistaqt

class PyVistaInterface:
"""Provides the middle class between PyVista plotting operations and PyAnsys objects.
Expand All @@ -58,6 +62,8 @@ class PyVistaInterface:
for visualization.
show_plane : bool, default: False
Whether to show the XY plane in the plotter window.
use_qt : bool, default: False
Whether to use the Qt backend for the plotter window.

"""

Expand All @@ -68,15 +74,27 @@ def __init__(
num_points: int = 100,
enable_widgets: bool = True,
show_plane: bool = False,
use_qt: bool = False,
**plotter_kwargs,
) -> None:
"""Initialize the plotter."""
# Generate custom scene if ``None`` is provided
if scene is None:
if viz_interface.TESTING_MODE:
scene = pv.Plotter(off_screen=True, **plotter_kwargs)
if use_qt and _HAS_PYVISTAQT:
scene = pyvistaqt.BackgroundPlotter(off_screen=True)
else:
if use_qt and not _HAS_PYVISTAQT:
message = "PyVistaQt dependency is not installed. Install it with " + \
"`pip install ansys-tools-visualization-interface[pyvistaqt]`."
logger.warning(message)
scene = pv.Plotter(off_screen=True, **plotter_kwargs)
elif use_qt:
scene = pyvistaqt.BackgroundPlotter()
else:
scene = pv.Plotter(**plotter_kwargs)

self._use_qt = use_qt
# If required, use a white background with no gradient
if not color_opts:
color_opts = dict(color="white")
Expand All @@ -91,8 +109,9 @@ def __init__(

# Show the XY plane
self._show_plane = show_plane
if not use_qt:
self.scene.add_axes(interactive=False)

self.scene.add_axes(interactive=False)
# objects to actors mapping
self._object_to_actors_map = {}
self._enable_widgets = enable_widgets
Expand Down Expand Up @@ -335,7 +354,10 @@ def show(
if jupyter_backend:
self.scene.show(jupyter_backend=jupyter_backend, **kwargs)
else:
self.scene.show(**kwargs)
if self._use_qt:
self.scene.show()
else:
self.scene.show(**kwargs)

def set_add_mesh_defaults(self, plotting_options: Optional[Dict]) -> None:
"""Set the default values for the plotting options.
Expand Down
2 changes: 1 addition & 1 deletion src/ansys/tools/visualization_interface/plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,4 @@ def show(
screenshot=screenshot,
name_filter=name_filter,
**plotting_options
)
)
15 changes: 15 additions & 0 deletions tests/test_generic_plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Test module for the generic plotter."""
import os
from pathlib import Path

import numpy as np
import pytest
import pyvista as pv

from ansys.tools.visualization_interface import ClipPlane, MeshObjectPlot, Plotter
from ansys.tools.visualization_interface.backends.pyvista import PyVistaBackend

IN_GITHUB_ACTIONS = os.getenv("IN_GITHUB_ACTIONS") == "true"


class CustomTestClass:
Expand All @@ -43,6 +48,16 @@ def test_plotter_add_pd():
pl.plot(sphere)
pl.show()

@pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Qt breaks CICD.")
def test_plotter_pyvistaqt():
"""Adds polydata to the plotter."""
qt_backend = PyVistaBackend(use_qt=True)
pl = Plotter(backend=qt_backend)
sphere = pv.Sphere()
pl.plot(sphere)
# PyVista QT show() breaks PyTest, so we avoid it.
qt_backend.close()


def test_plotter_add_mb():
"""Adds multiblock to the plotter."""
Expand Down
Loading