diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 815fbe8e370..63544aeba05 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -266,19 +266,6 @@ jobs: export DPF_DEFAULT_GRPC_MODE=insecure tox --installpkg "$TOX_INSTALLPKG" ${TOX_XARG:+-x "$TOX_XARG"} -e test-api_entry,kill-servers - - name: "Run compatible tests in parallel" - uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 - env: - TOX_INSTALLPKG: ${{ steps.tox-cli-arguments.outputs.TOX_INSTALLPKG }} - TOX_XARG: ${{ steps.tox-cli-arguments.outputs.TOX_XARG }} - with: - timeout_minutes: 20 - max_attempts: 2 - shell: bash - command: | - export DPF_DEFAULT_GRPC_MODE=insecure - tox run-parallel --installpkg "$TOX_INSTALLPKG" ${TOX_XARG:+-x "$TOX_XARG"} -m ciparalleltests - - name: "Test API test_server" uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 env: @@ -340,6 +327,32 @@ jobs: export DPF_DEFAULT_GRPC_MODE=insecure tox --installpkg "$TOX_INSTALLPKG" ${TOX_XARG:+-x "$TOX_XARG"} -e test-service,kill-servers + - name: "Run compatible tests in parallel" + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 + env: + TOX_INSTALLPKG: ${{ steps.tox-cli-arguments.outputs.TOX_INSTALLPKG }} + TOX_XARG: ${{ steps.tox-cli-arguments.outputs.TOX_XARG }} + with: + timeout_minutes: 20 + max_attempts: 2 + shell: bash + command: | + export DPF_DEFAULT_GRPC_MODE=insecure + tox run-parallel --installpkg "$TOX_INSTALLPKG" ${TOX_XARG:+-x "$TOX_XARG"} -m ciparalleltests + + - name: "Run api and launcher tests in parallel" + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 + env: + TOX_INSTALLPKG: ${{ steps.tox-cli-arguments.outputs.TOX_INSTALLPKG }} + TOX_XARG: ${{ steps.tox-cli-arguments.outputs.TOX_XARG }} + with: + timeout_minutes: 20 + max_attempts: 2 + shell: bash + command: | + export DPF_DEFAULT_GRPC_MODE=insecure + tox --installpkg "$TOX_INSTALLPKG" ${TOX_XARG:+-x "$TOX_XARG"} -e pretest,test-api,test-launcher,posttest,kill-servers + - name: "Combine coverage results" shell: bash run: | diff --git a/doc/source/conf.py b/doc/source/conf.py index 31f7e86eb9d..3a4b51d4385 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,6 +1,7 @@ from datetime import datetime from glob import glob import os +import shutil import sys from pathlib import Path import subprocess @@ -381,6 +382,24 @@ # A list of files that should not be packed into the epub file. epub_exclude_files = ["search.html"] +def _copy_labels_images(app, exception): + """Override sphinx-gallery images for 03-labels.py example. + + The images captured during CI run do not show the labels as expected, + and the behavior is not reproducible locally. This hook replaces whatever + sphinx-gallery generated during the CI run. + """ + _LABELS_IMAGES_SRC = Path(__file__).parent / "images" / "plotting" + _LABELS_IMAGES_PATTERN = "sphx_glr_03-labels" + if exception: + return + target_dir = Path(app.outdir) / "_images" + if not target_dir.exists(): + return + for src in _LABELS_IMAGES_SRC.glob(f"{_LABELS_IMAGES_PATTERN}*"): + dst = target_dir / src.name + shutil.copy2(src, dst) + # Define custom docutils roles for solver badges from sphinx_design.badges_buttons import BadgeRole @@ -393,7 +412,9 @@ def setup(app): } for role_name, color in badge_roles.items(): - app.add_role(name=role_name, role=BadgeRole(color=color)) + app.add_role(name=role_name, role=BadgeRole(color)) + + app.connect("build-finished", _copy_labels_images) # Common content for every RST file such us links rst_epilog = "" diff --git a/doc/source/images/plotting/sphx_glr_03-labels_001.png b/doc/source/images/plotting/sphx_glr_03-labels_001.png new file mode 100644 index 00000000000..a97fa6d695d Binary files /dev/null and b/doc/source/images/plotting/sphx_glr_03-labels_001.png differ diff --git a/doc/source/images/plotting/sphx_glr_03-labels_002.png b/doc/source/images/plotting/sphx_glr_03-labels_002.png new file mode 100644 index 00000000000..a8250888d72 Binary files /dev/null and b/doc/source/images/plotting/sphx_glr_03-labels_002.png differ diff --git a/doc/source/images/plotting/sphx_glr_03-labels_thumb.png b/doc/source/images/plotting/sphx_glr_03-labels_thumb.png new file mode 100644 index 00000000000..73aa010fabd Binary files /dev/null and b/doc/source/images/plotting/sphx_glr_03-labels_thumb.png differ diff --git a/doc/sphinx_gallery_examples/06-plotting/07-plot_on_geometries.py b/doc/sphinx_gallery_examples/06-plotting/07-plot_on_geometries.py index fd913985d3c..95ada09bb40 100644 --- a/doc/sphinx_gallery_examples/06-plotting/07-plot_on_geometries.py +++ b/doc/sphinx_gallery_examples/06-plotting/07-plot_on_geometries.py @@ -81,7 +81,7 @@ ############################################################################### # Show points together with the mesh -points.plot(mesh, cpos=cpos, point_size=15, color="blue") +points.plot(mesh, cpos=cpos, point_size=25, color="blue") ############################################################################### # Create line passing through the geometry's diagonal: @@ -89,7 +89,7 @@ ############################################################################### # Show line with the 3D mesh -line.plot(mesh, cpos=cpos, color="black") +line.plot(mesh, cpos=cpos, color="black", width=5.0) ############################################################################### # Create vertical plane passing through the mid point: @@ -150,7 +150,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # 3D plot of Points and display mesh: pl = DpfPlotter() -pl.add_field(field_points, render_points_as_spheres=True, point_size=10) +pl.add_field(field_points, render_points_as_spheres=True, point_size=25) pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) pl.show_figure(show_axes=True, cpos=cpos) @@ -159,7 +159,7 @@ # Note that the line is only displayed if some points are found inside the mesh: pl = DpfPlotter() if not len(field_line) == 0: - pl.add_field(field_line, line.mesh, line_width=5) + pl.add_field(field_line, line.mesh, line_width=10) pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) pl.show_figure(show_axes=True, cpos=cpos) diff --git a/pyproject.toml b/pyproject.toml index ad6ce02661c..b3c00d5c169 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,7 @@ graphics = [ "matplotlib>=3.2", # 3D plotting "pyvista>=0.32.0", + "ansys-tools-visualization-interface==1.0.0a1", "vtk!=9.4.0", # Animations "imageio", @@ -55,6 +56,7 @@ plotting = [ "matplotlib>=3.2", # 3D plotting "pyvista>=0.32.0", + "ansys-tools-visualization-interface==1.0.0a1", "vtk", # Animations "imageio", @@ -70,6 +72,7 @@ operator_doc = [ doc = [ "ansys-sphinx-theme[autoapi]==1.7.2", + "ansys-tools-visualization-interface==1.0.0a1", "enum-tools[sphinx]==0.13.0", "graphviz==0.21", "imageio==2.37.2", @@ -94,6 +97,7 @@ doc = [ test = [ "ansys-platform-instancemanagement==1.1.2", "ansys-tools-common==0.4.5", + "ansys-tools-visualization-interface==1.0.0a1", "coverage==7.13.4", "graphviz==0.21", "imageio==2.37.2", diff --git a/src/ansys/dpf/core/meshes_container.py b/src/ansys/dpf/core/meshes_container.py index 03999002f7e..09febb716ba 100644 --- a/src/ansys/dpf/core/meshes_container.py +++ b/src/ansys/dpf/core/meshes_container.py @@ -93,7 +93,7 @@ def plot(self, fields_container=None, deform_by=None, scale_factor=1.0, **kwargs ... ) >>> disp_fc = disp_op.outputs.fields_container() >>> meshes_cont.plot(disp_fc) - (None, ) + ([], ) """ # DPF defaults diff --git a/src/ansys/dpf/core/model.py b/src/ansys/dpf/core/model.py index afa45b442bd..6bb821b917a 100644 --- a/src/ansys/dpf/core/model.py +++ b/src/ansys/dpf/core/model.py @@ -255,7 +255,7 @@ def plot(self, color="w", show_edges=True, **kwargs): >>> transient = examples.download_transient_result() >>> model = Model(transient) >>> model.plot() - (None, ) + ([], ) """ from ansys.dpf.core.plotter import DpfPlotter diff --git a/src/ansys/dpf/core/plotter.py b/src/ansys/dpf/core/plotter.py index ad319f1e81c..95d139f69a6 100644 --- a/src/ansys/dpf/core/plotter.py +++ b/src/ansys/dpf/core/plotter.py @@ -778,15 +778,21 @@ def get_label_at_grid_point(index): # The scalar data used will be the one of the last field added. active_scalars = None if parse(pv.__version__) >= parse("0.42.0"): - # Get actors of active renderer + # Get actors of active renderer. + # base_plotter.actors may return raw VTK actors (not PyVista Actor + # wrappers), so use GetMapper()/GetInput() for VTK-level access. actors = list(self._backend.base_plotter.actors.values()) for actor in actors: - mapper = actor.mapper if hasattr(actor, "mapper") else None - if mapper: - dataset = mapper.dataset - if type(dataset) is pv.core.pointset.UnstructuredGrid: - active_scalars = dataset.active_scalars - break + vtk_mapper = actor.GetMapper() if hasattr(actor, "GetMapper") else None + if vtk_mapper is None: + continue + vtk_input = vtk_mapper.GetInput() + if vtk_input is None: + continue + dataset = pv.wrap(vtk_input) + if type(dataset) is pv.core.pointset.UnstructuredGrid: + active_scalars = dataset.active_scalars + break elif parse(pv.__version__) >= parse("0.35.2"): for data_set in self._backend.base_plotter._datasets: if type(data_set) is pv.core.pointset.UnstructuredGrid: @@ -1385,7 +1391,7 @@ def add_streamlines( ... radius=0.001, ... ) >>> pl.show_figure(show_axes=True) - (None, ) + ([], ) """ self._internal_plotter.add_streamlines( streamlines=streamlines, @@ -1505,7 +1511,7 @@ def add_scoping( >>> plt.add_scoping(node_scoping, mesh, show_mesh=True, color="red") >>> plt.add_scoping(element_scoping, mesh, color="green") >>> plt.show_figure() - (None, ) + ([], ) """ self._internal_plotter.add_scoping( scoping=scoping, mesh=mesh, show_mesh=show_mesh, **kwargs @@ -1531,7 +1537,7 @@ def show_figure(self, **kwargs): >>> pl = DpfPlotter() >>> pl.add_field(field, mesh) >>> pl.show_figure() - (None, ) + ([], ) """ if "notebook" in kwargs.keys(): warnings.simplefilter("once") diff --git a/src/ansys/dpf/core/scoping.py b/src/ansys/dpf/core/scoping.py index 2f279822e96..1ff624b4185 100644 --- a/src/ansys/dpf/core/scoping.py +++ b/src/ansys/dpf/core/scoping.py @@ -520,13 +520,13 @@ def plot(self, mesh, show_mesh: bool = False, **kwargs): ... ids=mesh.nodes.scoping.ids[0:100] ... ) >>> node_scoping.plot(mesh=mesh, color="red") - (None, ) + ([], ) >>> element_scoping = dpf.Scoping( ... location=dpf.locations.elemental, ... ids=mesh.elements.scoping.ids[0:100] ... ) >>> element_scoping.plot(mesh=mesh, color="green") - (None, ) + ([], ) """ from ansys.dpf.core.plotter import DpfPlotter diff --git a/src/ansys/dpf/core/scopings_container.py b/src/ansys/dpf/core/scopings_container.py index 451f991baed..51d5393ccae 100644 --- a/src/ansys/dpf/core/scopings_container.py +++ b/src/ansys/dpf/core/scopings_container.py @@ -180,7 +180,7 @@ def plot( >>> node_sc.add_scoping(label_space={"scoping": 1}, scoping=node_scoping_1) >>> node_sc.add_scoping(label_space={"scoping": 2}, scoping=node_scoping_2) >>> node_sc.plot(mesh=mesh, show_mesh=True) - (None, ) + ([], ) """ from itertools import cycle diff --git a/tox.ini b/tox.ini index 0aa14e18573..a2d42a313f5 100644 --- a/tox.ini +++ b/tox.ini @@ -34,7 +34,7 @@ envlist = pretest,test-{api,documentation,launcher,server,local_server,multi_ser labels = localparalleltests = pretest,test-{api,documentation,launcher,server,local_server,multi_server,custom_type_field,operators,server_errors},posttest,kill-servers othertests = pretest,test-{workflow,remote_workflow,remote_operator,service},posttest,kill-servers - ciparalleltests = test-{api,documentation,launcher,local_server,multi_server,custom_type_field,operators,server_errors},kill-servers + ciparalleltests = test-{documentation,local_server,multi_server,custom_type_field,operators,server_errors},kill-servers isolated_build_env = build