diff --git a/doc/changelog.d/3820.fixed.md b/doc/changelog.d/3820.fixed.md new file mode 100644 index 00000000000..efdfe389971 --- /dev/null +++ b/doc/changelog.d/3820.fixed.md @@ -0,0 +1 @@ +feat: Add optional graphical target and rework graphics backend selection \ No newline at end of file diff --git a/doc/source/api/mapdl.rst b/doc/source/api/mapdl.rst index ea8e43e9837..c13a05b5b3e 100644 --- a/doc/source/api/mapdl.rst +++ b/doc/source/api/mapdl.rst @@ -75,7 +75,7 @@ Mapdl.screenshot Mapdl.set_log_level Mapdl.thermal_result - Mapdl.use_vtk + Mapdl.graphics_backend Mapdl.version diff --git a/doc/source/user_guide/plotting.rst b/doc/source/user_guide/plotting.rst index ce44b6b07bd..212380f003a 100644 --- a/doc/source/user_guide/plotting.rst +++ b/doc/source/user_guide/plotting.rst @@ -10,7 +10,7 @@ transfer the geometry to Python to visualize it: - :func:`Mapdl.kplot() ` - :func:`Mapdl.vplot() ` -- :func:`Mapdl.eplot() `). +- :func:`Mapdl.eplot() `). These methods rely on the :class:`ansys.mapdl.core.plotting.visualizer.MapdlPlotter` method. Combined with the MAPDL geometry commands, you can @@ -91,10 +91,10 @@ some element types, performs meshing, and then displays the mesh: Plotting non-interactively using MAPDL -------------------------------------- You can also plot using MAPDL's native plotting tools. To use the -native tools, pass ``vtk=False`` when running plotting commands such +native tools, pass ``graphics_backend=GraphicsBackend.MAPDL`` when running plotting commands such as the :func:`Mapdl.aplot ` and :func:`Mapdl.eplot ` methods. Plots are -generated within MAPDL and then shown using +generated within MAPDL and then shown using `Matplotlib `_. @@ -132,15 +132,16 @@ Each of these creates a Matplotlib figure and pause execution. .. code:: pycon - >>> mapdl.aplot(vtk=False) - >>> mapdl.lplot(vtk=False) - >>> mapdl.kplot(vtk=False) + >>> from ansys.mapdl.core.plotting import GraphicsBackend + >>> mapdl.aplot(graphics_backend=GraphicsBackend.MAPDL) + >>> mapdl.lplot(graphics_backend=GraphicsBackend.MAPDL) + >>> mapdl.kplot(graphics_backend=GraphicsBackend.MAPDL) .. figure:: ../images/aplot.png :width: 400pt - Area Plot from MAPDL displayed using + Area Plot from MAPDL displayed using `Matplotlib `_ @@ -149,7 +150,7 @@ For more information on plotting functions, see :ref:`ref_plotting_api`. Plotting keyword options ------------------------ -When ``vtk=True``, which is the default, all MAPDL plotting +When ``graphics_backend=GraphicsBackend.PYVISTA``, which is the default, all MAPDL plotting methods allow you to enter in additional keyword arguments to better control the plot. For example, you can automatically generate a screenshot of an area plot or element plot with this code: diff --git a/examples/00-mapdl-examples/2d_magnetostatic_solenoid-BodyFlux_Averaging.py b/examples/00-mapdl-examples/2d_magnetostatic_solenoid-BodyFlux_Averaging.py index ed8a9b9ef8b..adef07a0c00 100644 --- a/examples/00-mapdl-examples/2d_magnetostatic_solenoid-BodyFlux_Averaging.py +++ b/examples/00-mapdl-examples/2d_magnetostatic_solenoid-BodyFlux_Averaging.py @@ -84,6 +84,7 @@ import pyvista as pv from ansys.mapdl.core import launch_mapdl +from ansys.mapdl.core.plotting import GraphicsBackend ############################################################################### # Launch MAPDL service @@ -182,7 +183,7 @@ mapdl.pnum("MAT", 1) # Turn material numbers on mapdl.allsel("ALL") -mapdl.aplot(vtk=False) +mapdl.aplot(graphics_backend=GraphicsBackend.MAPDL) ############################################################################### # Mesh diff --git a/examples/00-mapdl-examples/2d_plate_with_a_hole.py b/examples/00-mapdl-examples/2d_plate_with_a_hole.py index 45396896589..2f074a054e5 100644 --- a/examples/00-mapdl-examples/2d_plate_with_a_hole.py +++ b/examples/00-mapdl-examples/2d_plate_with_a_hole.py @@ -120,7 +120,6 @@ mapdl.esize(plate_esize) mapdl.amesh(plate_with_hole_anum) mapdl.eplot( - vtk=True, cpos="xy", show_edges=True, show_axes=False, diff --git a/examples/00-mapdl-examples/3d_notch.py b/examples/00-mapdl-examples/3d_notch.py index 5c1cef162a2..2945ec0f31a 100644 --- a/examples/00-mapdl-examples/3d_notch.py +++ b/examples/00-mapdl-examples/3d_notch.py @@ -89,18 +89,18 @@ mapdl.lsla("S") -mapdl.lplot(vtk=True, show_keypoint_numbering=True) +mapdl.lplot(show_keypoint_numbering=True) mapdl.lsel("all") # plot the area using vtk/pyvista -mapdl.aplot(vtk=True, show_area_numbering=True, show_lines=True, cpos="xy") +mapdl.aplot(show_area_numbering=True, show_lines=True, cpos="xy") # Next, extrude the area to create volume thickness = 0.01 mapdl.vext(cut_area, dz=thickness) # Checking volume plot -mapdl.vplot(vtk=True, show_lines=True, show_axes=True, smooth_shading=True) +mapdl.vplot(show_lines=True, show_axes=True, smooth_shading=True) ############################################################################### @@ -126,7 +126,7 @@ # line and area numbers identified using aplot mapdl.asel("S", "AREA", vmin=1, vmax=1) -mapdl.aplot(vtk=True, show_line_numbering=True) +mapdl.aplot(show_line_numbering=True) mapdl.lsel("NONE") @@ -147,7 +147,7 @@ mapdl.esize() # this is tough to automate mapdl.et(1, "SOLID186") mapdl.vsweep("all") -mapdl.eplot(vtk=True, show_edges=True, show_axes=False, line_width=2, background="w") +mapdl.eplot(show_edges=True, show_axes=False, line_width=2, background="w") ############################################################################### diff --git a/examples/00-mapdl-examples/bracket_static.py b/examples/00-mapdl-examples/bracket_static.py index 5d4167c78bd..b31701d004b 100644 --- a/examples/00-mapdl-examples/bracket_static.py +++ b/examples/00-mapdl-examples/bracket_static.py @@ -215,7 +215,7 @@ circle1_Y = (box1[2] + box1[3]) / 2 mapdl.cyl4(circle1_X, circle1_Y, radius) -mapdl.aplot(vtk=True, cpos="xy", show_lines=True) +mapdl.aplot(cpos="xy", show_lines=True) ############################################################################### @@ -233,7 +233,7 @@ # as the first circle area. mapdl.cyl4(circle2_X, circle2_Y, radius) -mapdl.aplot(vtk=True, cpos="xy", show_lines=True) +mapdl.aplot(cpos="xy", show_lines=True) ############################################################################### @@ -299,7 +299,7 @@ line3 = mapdl.lfillt("line1", l2, fillet_radius) mapdl.allsel() -mapdl.lplot(vtk=True, cpos="xy") +mapdl.lplot(cpos="xy") ############################################################################### # Create fillet area @@ -334,7 +334,7 @@ mapdl.lsel("A", "LINE", "", line3) # plotting ares -mapdl.lplot(vtk=True, cpos="xy", show_line_numbering=True) +mapdl.lplot(cpos="xy", show_line_numbering=True) ############################################################################### # Then use :meth:`mapdl.al() ` command to create the areas @@ -355,7 +355,7 @@ # Add the area to the main area mapdl.aadd("all") -mapdl.aplot(vtk=True, cpos="xy", show_lines=True) +mapdl.aplot(cpos="xy", show_lines=True) ############################################################################### # Create first pin hole @@ -410,7 +410,7 @@ # Remove pin hole areas from bracket mapdl.asba("all", pinhole1) bracket = mapdl.asba("all", pinhole2) -mapdl.aplot(vtk=True, show_lines=True, cpos="xy") +mapdl.aplot(show_lines=True, cpos="xy") ############################################################################### # Model definition @@ -500,7 +500,6 @@ mapdl.esize(element_size) mapdl.amesh(bracket) mapdl.eplot( - vtk=True, cpos="xy", show_edges=True, show_axes=False, @@ -612,7 +611,7 @@ # mapdl.lsel("R", "LOC", "X", 0, pinhole2_X) -mapdl.lplot(vtk=True, cpos="xy") +mapdl.lplot(cpos="xy") ############################################################################### # @@ -634,7 +633,6 @@ mapdl.lsel("R", "LOC", "X", pinhole2_X, pinhole2_X + pinhole_radius) mapdl.lplot( - vtk=True, cpos="xy", show_line_numbering=True, ) diff --git a/examples/00-mapdl-examples/lathe_cutter.py b/examples/00-mapdl-examples/lathe_cutter.py index bd32b76305b..0d842e7b3d3 100644 --- a/examples/00-mapdl-examples/lathe_cutter.py +++ b/examples/00-mapdl-examples/lathe_cutter.py @@ -94,6 +94,7 @@ from ansys.mapdl.core import launch_mapdl from ansys.mapdl.core.examples.downloads import download_example_data +from ansys.mapdl.core.plotting import GraphicsBackend # cwd = current working directory path = os.getcwd() @@ -194,9 +195,9 @@ # # VTK plots do not show MAPDL plot symbols. # However, to use MAPDL plotting capabilities, you can set the keyword -# option ``vtk`` to ``False``. - -mapdl.lplot(vtk=False) +# option ``backend`` to ``GraphicsBackend.MAPDL``. +mapdl.set_graphics_backend(GraphicsBackend.MAPDL) +mapdl.lplot() ############################################################################### # Step 4: Pressure load @@ -244,7 +245,7 @@ mapdl.nlgeom("On") mapdl.psf("PRES", "NORM", 3, 0, 1) mapdl.view(1, -1, 1, 1) -mapdl.eplot(vtk=False) +mapdl.eplot() ############################################################################### # Solve the model. diff --git a/examples/00-mapdl-examples/mapdl_beam.py b/examples/00-mapdl-examples/mapdl_beam.py index 5caa6881332..d21c1b9bc25 100644 --- a/examples/00-mapdl-examples/mapdl_beam.py +++ b/examples/00-mapdl-examples/mapdl_beam.py @@ -69,7 +69,7 @@ print(mapdl.mesh.nnum) # plot the nodes using VTK -mapdl.nplot(vtk=True, nnum=True, cpos="xy", show_bounds=True, point_size=10) +mapdl.nplot(nnum=True, cpos="xy", show_bounds=True, point_size=10) ############################################################################### # create elements between the nodes diff --git a/examples/02-tips-n-tricks/01-smoothing-element-size-transitions.py b/examples/02-tips-n-tricks/01-smoothing-element-size-transitions.py index c8daf637ae0..e8cf75141ad 100644 --- a/examples/02-tips-n-tricks/01-smoothing-element-size-transitions.py +++ b/examples/02-tips-n-tricks/01-smoothing-element-size-transitions.py @@ -126,7 +126,7 @@ for k in [k2, k3, k6, k7]: mapdl.kesize(k, 0.2) mapdl.amesh("ALL") -mapdl.eplot(vtk=True, show_edges=True, show_axes=False, line_width=2, background="w") +mapdl.eplot(show_edges=True, show_axes=False, line_width=2, background="w") ############################################################################### diff --git a/pyproject.toml b/pyproject.toml index de8cb111420..042f6540511 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,10 +18,8 @@ dependencies = [ "ansys-math-core>=0.1.2", "ansys-platform-instancemanagement~=1.0", "ansys-tools-path>=0.3.1", - "ansys-tools-visualization-interface>=0.2.6", "click>=8.1.3", # for CLI interface "grpcio>=1.30.0", # tested up to grpcio==1.35 - "matplotlib>=3.0.0", # for colormaps for pyvista "numpy>=1.14.0,<3.0.0", "pexpect>=4.8.0 ; platform_system=='Linux'", "platformdirs>=3.6.0", @@ -53,6 +51,18 @@ jupyter = [ "ipywidgets", ] +graphics = [ + "ansys-tools-visualization-interface>=0.2.6", + "matplotlib>=3.0.0", # for colormaps for pyvista +] + +all = [ + "ansys-tools-visualization-interface>=0.2.6", + "matplotlib>=3.0.0", # for colormaps for pyvista + "jupyterlab>=3", + "ipywidgets", +] + tests = [ "ansys-dpf-core==0.10.1", "ansys-tools-visualization-interface==0.8.3", diff --git a/src/ansys/mapdl/core/__init__.py b/src/ansys/mapdl/core/__init__.py index 9d56358ad05..1e8d0b88633 100644 --- a/src/ansys/mapdl/core/__init__.py +++ b/src/ansys/mapdl/core/__init__.py @@ -73,7 +73,9 @@ _HAS_PYVISTA: bool = is_installed("pyvista") _HAS_REQUESTS: bool = is_installed("requests") _HAS_TQDM: bool = is_installed("tqdm") -_HAS_VISUALIZER: bool = is_installed("ansys.tools.visualization_interface") +_HAS_VISUALIZER: bool = is_installed( + "ansys.tools.visualization_interface" +) and is_installed("matplotlib") # Setup directories diff --git a/src/ansys/mapdl/core/_commands/graphics_/style.py b/src/ansys/mapdl/core/_commands/graphics_/style.py index e2ad27d1da2..d6a015f9726 100644 --- a/src/ansys/mapdl/core/_commands/graphics_/style.py +++ b/src/ansys/mapdl/core/_commands/graphics_/style.py @@ -293,7 +293,7 @@ def eshape( warnings.warn( "pymapdl does not support /ESHAPE when plotting in " "Python using ``mapdl.eplot()``. " - "Use ``mapdl.eplot(vtk=False)`` " + "Use ``mapdl.eplot(backend=GraphicsBackend.MAPDL)`` " ) command = f"/ESHAPE,{scale},{key}" return self.run(command, **kwargs) diff --git a/src/ansys/mapdl/core/_commands/post1_/controls.py b/src/ansys/mapdl/core/_commands/post1_/controls.py index 42709180667..b42d089c628 100644 --- a/src/ansys/mapdl/core/_commands/post1_/controls.py +++ b/src/ansys/mapdl/core/_commands/post1_/controls.py @@ -171,7 +171,7 @@ def efacet(self, num="", **kwargs): .. warning:: This will not change element plotting within PyMAPDL with - ``eplot(vtk=True)`` + ``eplot()`` Parameters ---------- diff --git a/src/ansys/mapdl/core/cli/convert.py b/src/ansys/mapdl/core/cli/convert.py index df2219eefec..fca31ce963c 100644 --- a/src/ansys/mapdl/core/cli/convert.py +++ b/src/ansys/mapdl/core/cli/convert.py @@ -24,6 +24,8 @@ import click +from ansys.mapdl.core.plotting import GraphicsBackend + @click.command( short_help="Convert APDL code to PyMAPDL code.", @@ -173,10 +175,10 @@ Overrides ``header``, ``add_imports`` and ``auto_exit``.""", ) @click.option( - "--use_vtk", + "--graphics_backend", default=None, - type=bool, - help="""It sets the `mapdl.use_vtk` argument equals True or False depending on + type=str, + help="""It sets the `mapdl.graphics_backend` argument depending on this value. Defaults to `None` which is Mapdl class default.""", ) @click.option( @@ -207,13 +209,32 @@ def convert( header: str, print_com: bool, only_commands: bool, - use_vtk: bool, + graphics_backend: str, clear_at_start: bool, check_parameter_names: bool, ) -> None: """Convert MAPDL code to PyMAPDL""" from ansys.mapdl.core.convert import convert_apdl_block + allowed_backends = GraphicsBackend.__members__ + backend = None + + if graphics_backend is not None: + if ( + isinstance(graphics_backend, str) + and graphics_backend.upper() in allowed_backends + ): + backend = GraphicsBackend[graphics_backend.upper()] + elif graphics_backend in list(allowed_backends.values()): + backend = graphics_backend + else: + allowed_backend_string = ", ".join( + [str(each) for each in allowed_backends.values()] + ) + raise ValueError( + f"Invalid graphics backend '{graphics_backend}'. Allowed values are: {allowed_backend_string}." + ) + converted_code = convert_apdl_block( apdl_strings=file.read(), loglevel=loglevel, @@ -229,7 +250,7 @@ def convert( header=header, print_com=print_com, only_commands=only_commands, - use_vtk=use_vtk, + graphics_backend=backend, clear_at_start=clear_at_start, check_parameter_names=check_parameter_names, ) diff --git a/src/ansys/mapdl/core/convert.py b/src/ansys/mapdl/core/convert.py index 8784c0f745f..19716ac305b 100644 --- a/src/ansys/mapdl/core/convert.py +++ b/src/ansys/mapdl/core/convert.py @@ -29,6 +29,7 @@ from ansys.mapdl.core import __version__ from ansys.mapdl.core.commands import Commands from ansys.mapdl.core.misc import is_float +from ansys.mapdl.core.plotting import GraphicsBackend # Because the APDL version has empty arguments, whereas the PyMAPDL # doesn't have them. Hence the order of arguments is messed up. @@ -51,7 +52,7 @@ HEADER_DEFAULT: bool = True PRINT_COM_DEFAULT: bool = True ONLY_COMMANDS_DEFAULT: bool = False -USE_VTK_DEFAULT: Optional[bool] = None +GRAPHICS_BACKEND_DEFAULT: Optional[GraphicsBackend] = None CLEAR_AT_START_DEFAULT: bool = False CHECK_PARAMETER_NAMES_DEFAULT: bool = True @@ -142,7 +143,7 @@ def convert_script( header: bool = True, print_com: bool = True, only_commands: bool = False, - use_vtk: Optional[bool] = None, + graphics_backend: Optional[GraphicsBackend] = None, clear_at_start: bool = False, check_parameter_names: bool = True, ) -> List[str]: @@ -216,8 +217,8 @@ def convert_script( and exit commands are NOT included (``auto_exit=False``). Overrides ``header``, ``add_imports`` and ``auto_exit``. - use_vtk : bool, optional - It sets the `mapdl.use_vtk` argument equals True or False depending on + graphics_backend : bool, optional + It sets the `mapdl.graphics_backend` argument equals True or False depending on this value. clear_at_start : bool, optional @@ -278,7 +279,7 @@ def convert_script( header=header, print_com=print_com, only_commands=only_commands, - use_vtk=use_vtk, + graphics_backend=graphics_backend, clear_at_start=clear_at_start, check_parameter_names=check_parameter_names, ) @@ -302,7 +303,7 @@ def convert_apdl_block( header: bool = True, print_com: bool = True, only_commands: bool = False, - use_vtk: Optional[bool] = None, + graphics_backend: Optional[GraphicsBackend] = None, clear_at_start: bool = False, check_parameter_names: bool = False, ) -> List[str]: @@ -372,8 +373,8 @@ def convert_apdl_block( and exit commands are NOT included (``auto_exit=False``). Overrides ``header``, ``add_imports`` and ``auto_exit``. - use_vtk : bool, optional - It sets the `mapdl.use_vtk` argument equals True or False depending on + graphics_backend : bool, optional + It sets the `mapdl.graphics_backend` argument equals True or False depending on this value. Defaults to `None` which is Mapdl class default. clear_at_start : bool, optional @@ -419,7 +420,7 @@ def convert_apdl_block( header=header, print_com=print_com, only_commands=only_commands, - use_vtk=use_vtk, + graphics_backend=graphics_backend, clear_at_start=clear_at_start, check_parameter_names=check_parameter_names, ) @@ -469,7 +470,7 @@ def __init__( cleanup_output: bool = True, header: bool = True, print_com: bool = True, - use_vtk: Optional[bool] = None, + graphics_backend: Optional[GraphicsBackend] = None, clear_at_start: bool = False, check_parameter_names: bool = False, ) -> None: @@ -490,7 +491,7 @@ def __init__( self._header = header self.print_com = print_com self.verification_example = False - self.use_vtk = use_vtk + self.graphics_backend = graphics_backend self.clear_at_start = clear_at_start self.check_parameter_names = check_parameter_names self.macros_names = [] @@ -602,8 +603,10 @@ def initialize_mapdl_object(self, loglevel: str, exec_file: str) -> None: if self.print_com: mapdl_arguments.append("print_com=True") - if self.use_vtk is not None: - mapdl_arguments.append(f"use_vtk={bool(self.use_vtk)}") + if self.graphics_backend is not None: + mapdl_arguments.append( + f"graphics_backend={GraphicsBackend(self.graphics_backend)}" + ) if self.check_parameter_names is not None and not self.check_parameter_names: mapdl_arguments.append("check_parameter_names=False") @@ -1203,7 +1206,7 @@ def _convert( header: bool = True, print_com: bool = True, only_commands: bool = False, - use_vtk: Optional[bool] = None, + graphics_backend: Optional[bool] = None, clear_at_start: bool = False, check_parameter_names: bool = False, ) -> FileTranslator: @@ -1224,7 +1227,7 @@ def _convert( cleanup_output=cleanup_output, header=header, print_com=print_com, - use_vtk=use_vtk, + graphics_backend=graphics_backend, clear_at_start=clear_at_start, check_parameter_names=check_parameter_names, ) diff --git a/src/ansys/mapdl/core/launcher.py b/src/ansys/mapdl/core/launcher.py index 5e9c9fc9cde..625924a148f 100644 --- a/src/ansys/mapdl/core/launcher.py +++ b/src/ansys/mapdl/core/launcher.py @@ -60,6 +60,7 @@ create_temp_dir, threaded, ) +from ansys.mapdl.core.plotting import GraphicsBackend if _HAS_PIM: import ansys.platform.instancemanagement as pypim @@ -134,7 +135,7 @@ def version_from_path(*args, **kwargs): "_debug_no_launch", "just_launch", "on_pool", - "use_vtk", + "graphics_backend", ] ON_WSL = os.name == "posix" and ( @@ -1544,7 +1545,7 @@ def launch_mapdl( cleanup_on_exit=False, loglevel=args["loglevel"], set_no_abort=args["set_no_abort"], - use_vtk=args["use_vtk"], + graphics_backend=args["graphics_backend"], log_apdl=args["log_apdl"], **start_parm, ) @@ -1583,7 +1584,7 @@ def launch_mapdl( mapdl = MapdlConsole( loglevel=args["loglevel"], log_apdl=args["log_apdl"], - use_vtk=args["use_vtk"], + graphics_backend=args["graphics_backend"], **start_parm, ) @@ -1664,7 +1665,7 @@ def launch_mapdl( remove_temp_dir_on_exit=args["remove_temp_dir_on_exit"], log_apdl=args["log_apdl"], process=process, - use_vtk=args["use_vtk"], + graphics_backend=args["graphics_backend"], **start_parm, ) @@ -2045,7 +2046,20 @@ def pack_arguments(locals_): args["broadcast"] = locals_.get( "broadcast", locals_["kwargs"].get("broadcast", None) ) - args["use_vtk"] = locals_.get("use_vtk", locals_["kwargs"].get("use_vtk", None)) + + args["graphics_backend"] = locals_.get( + "graphics_backend", locals_["kwargs"].get("graphics_backend", None) + ) + + if locals_.get("use_vtk"): + LOG.warn( + "'use_vtk' will be deprecated in the next releases. Please use `graphics_backend` instead" + ) + if locals_["use_vtk"]: + args["graphics_backend"] = GraphicsBackend.PYVISTA + else: + args["graphics_backend"] = GraphicsBackend.MAPDL + args["just_launch"] = locals_.get( "just_launch", locals_["kwargs"].get("just_launch", None) ) @@ -2354,7 +2368,7 @@ def create_gallery_instances( cleanup_on_exit=False, loglevel=args["loglevel"], set_no_abort=args["set_no_abort"], - use_vtk=args["use_vtk"], + graphics_backend=args["graphics_backend"], **start_parm, ) if args["clear_on_connect"]: diff --git a/src/ansys/mapdl/core/mapdl_console.py b/src/ansys/mapdl/core/mapdl_console.py index d48c3609755..1ad6dc01da0 100644 --- a/src/ansys/mapdl/core/mapdl_console.py +++ b/src/ansys/mapdl/core/mapdl_console.py @@ -111,7 +111,7 @@ def __init__( self, loglevel="INFO", log_apdl=None, - use_vtk=True, + graphics_backend=True, print_com=False, **start_parm, ): @@ -126,7 +126,7 @@ def __init__( self._launch(start_parm) super().__init__( loglevel=loglevel, - use_vtk=use_vtk, + graphics_backend=graphics_backend, log_apdl=log_apdl, print_com=print_com, mode="console", diff --git a/src/ansys/mapdl/core/mapdl_core.py b/src/ansys/mapdl/core/mapdl_core.py index a68a40b212b..8ed8444d63d 100644 --- a/src/ansys/mapdl/core/mapdl_core.py +++ b/src/ansys/mapdl/core/mapdl_core.py @@ -67,13 +67,16 @@ from ansys.mapdl.core.inline_functions import Query from ansys.mapdl.core.mapdl_types import MapdlFloat from ansys.mapdl.core.misc import ( + check_deprecated_vtk_kwargs, check_valid_routine, last_created, random_string, + requires_graphics, requires_package, run_as, supress_logging, ) +from ansys.mapdl.core.plotting import GraphicsBackend if TYPE_CHECKING: # pragma: no cover from ansys.mapdl.reader import Archive @@ -251,10 +254,11 @@ def _sanitize_start_parm(start_parm): class _MapdlCore(Commands): """Contains methods in common between all Mapdl subclasses""" + @check_deprecated_vtk_kwargs def __init__( self, loglevel: DEBUG_LEVELS = "DEBUG", - use_vtk: Optional[bool] = None, + graphics_backend: Optional[GraphicsBackend] = None, log_apdl: Optional[str] = None, log_file: Union[bool, str] = False, local: bool = True, @@ -283,18 +287,16 @@ def __init__( self._save_selection_obj = None if _HAS_VISUALIZER: - if use_vtk is not None: # pragma: no cover - self._use_vtk = use_vtk + if graphics_backend is not None: # pragma: no cover + self._graphics_backend = graphics_backend else: - self._use_vtk = True + self._graphics_backend = GraphicsBackend.PYVISTA else: # pragma: no cover - if use_vtk: + if graphics_backend: raise ModuleNotFoundError( - "Using the keyword argument 'use_vtk' requires having " - "'ansys-tools-visualization_interface' installed." + "Graphic libraries are required to use this class.\n" + "You can install this using `pip install ansys-mapdl-core[graphics]`." ) - else: - self._use_vtk = False self._log_filehandler = None self._local: bool = local @@ -1035,14 +1037,14 @@ def solution(self) -> "Solution": return self._solution @property - def use_vtk(self): - """Returns if using VTK by default or not.""" - return self._use_vtk + def graphics_backend(self) -> GraphicsBackend: + """Returns current graphics backend.""" + return self._graphics_backend - @use_vtk.setter - def use_vtk(self, value: bool): - """Set VTK to be used by default or not.""" - self._use_vtk = value + @graphics_backend.setter + def graphics_backend(self, value: GraphicsBackend): + """Set the graphics backend to be used.""" + self._graphics_backend = value @property @requires_package("ansys.mapdl.reader", softerror=True) @@ -1862,16 +1864,10 @@ def __init__(self, parent: "MapdlBase", pixel_res: int) -> None: self._parent = weakref.ref(parent) self._pixel_res = pixel_res + @requires_graphics def __enter__(self) -> None: self._parent()._log.debug("Entering in 'WithInterativePlotting' mode") - if not self._parent()._has_matplotlib: # pragma: no cover - raise ModuleNotFoundError( - "Install matplotlib to display plots from MAPDL ," - "from Python. Otherwise, plot with vtk with:\n" - "``vtk=True``" - ) - if not self._parent()._store_commands: if not self._parent()._png_mode: self._parent().show("PNG", mute=True) diff --git a/src/ansys/mapdl/core/mapdl_extended.py b/src/ansys/mapdl/core/mapdl_extended.py index 58a321f3aa4..fe7710da7d3 100644 --- a/src/ansys/mapdl/core/mapdl_extended.py +++ b/src/ansys/mapdl/core/mapdl_extended.py @@ -31,7 +31,6 @@ from numpy.typing import DTypeLike, NDArray from ansys.mapdl.core import LOG as logger -from ansys.mapdl.core import _HAS_VISUALIZER from ansys.mapdl.core.commands import CommandListingOutput from ansys.mapdl.core.errors import ( CommandDeprecated, @@ -45,15 +44,32 @@ from ansys.mapdl.core.misc import ( allow_iterables_vmin, allow_pickable_entities, + check_deprecated_vtk_kwargs, load_file, random_string, + requires_graphics, supress_logging, ) +from ansys.mapdl.core.plotting import GraphicsBackend class _MapdlCommandExtended(_MapdlCore): """Class that extended MAPDL capabilities by wrapping or overwriting commands""" + def __init__(self, *args, **kwargs): + """Initialize the MAPDL command extended class. + + Parameters + ---------- + *args : list + Positional arguments to pass to the base class. + + **kwargs : dict + Keyword arguments to pass to the base class. + """ + super().__init__(*args, **kwargs) + self._graphics_backend = GraphicsBackend.PYVISTA + def file(self, fname: str = "", ext: str = "", **kwargs) -> str: """Specifies the data file where results are to be found. @@ -95,6 +111,10 @@ def _file(self, filename: str, extension: str, **kwargs) -> str: """Run the MAPDL ``file`` command with a proper filename.""" return self.run(f"FILE,{filename},{extension}", **kwargs) + def set_graphics_backend(self, backend: GraphicsBackend): + """Set the graphics backend to use for plotting.""" + self._graphics_backend = backend + @wraps(_MapdlCore.lsread) def lsread(self, *args, **kwargs): """Wraps the ``LSREAD`` which does not work in interactive mode.""" @@ -390,13 +410,16 @@ def list(self, filename, ext=""): with open(path) as fid: return fid.read() + @check_deprecated_vtk_kwargs + @requires_graphics def kplot( self, np1="", np2="", ninc="", lab="", - vtk=None, + *, + graphics_backend=None, show_keypoint_numbering=True, **kwargs, ): @@ -405,7 +428,7 @@ def kplot( APDL Command: KPLOT .. note:: - PyMAPDL plotting commands with ``vtk=True`` ignore any + PyMAPDL plotting commands with ``graphics_backend=GraphicsBackend.PYVISTA`` ignore any values set with the ``PNUM`` command. Parameters @@ -423,11 +446,11 @@ def kplot( HPT - Plots only those keypoints that are hard points. - vtk : bool, optional + graphics_backend : GraphicsBackend, optional Plot the currently selected lines using ``ansys-tools-visualization_interface``. show_keypoint_numbering : bool, optional - Display keypoint numbers when ``vtk=True``. + Display keypoint numbers when ``graphics_backend=GraphicsBackend.PYVISTA``. @@ -435,14 +458,10 @@ def kplot( ----- This command is valid in any processor. """ - if vtk is None: - vtk = self._use_vtk - elif vtk is True: - if not _HAS_VISUALIZER: # pragma: no cover - raise ModuleNotFoundError( - "Using the keyword argument 'vtk' requires having 'ansys-tools-visualization_interface' installed." - ) - if vtk: + if graphics_backend is None: + graphics_backend = self._graphics_backend + + if graphics_backend is GraphicsBackend.PYVISTA: from ansys.mapdl.core.plotting.visualizer import MapdlPlotter pl = kwargs.get("plotter", None) @@ -468,16 +487,21 @@ def kplot( ) pl.plot([], points, labels, **kwargs) return pl.show(**kwargs) + # otherwise, use the legacy plotter - with self._enable_interactive_plotting(): - return super().kplot(np1=np1, np2=np2, ninc=ninc, lab=lab, **kwargs) + if graphics_backend is GraphicsBackend.MAPDL: + with self._enable_interactive_plotting(): + return super().kplot(np1=np1, np2=np2, ninc=ninc, lab=lab, **kwargs) + @check_deprecated_vtk_kwargs + @requires_graphics def lplot( self, nl1="", nl2="", ninc="", - vtk=None, + *, + graphics_backend=None, show_line_numbering=True, show_keypoint_numbering=False, color_lines=False, @@ -488,7 +512,7 @@ def lplot( APDL Command: LPLOT .. note:: - PyMAPDL plotting commands with ``vtk=True`` ignore any + PyMAPDL plotting commands with ``graphics_backend=GraphicsBackend.PYVISTA`` ignore any values set with the ``PNUM`` command. Parameters @@ -498,11 +522,11 @@ def lplot( of NINC (defaults to 1). If NL1 = ALL (default), NL2 and NINC are ignored and display all selected lines [LSEL]. - vtk : bool, optional + graphics_backend : GraphicsBackend, optional Plot the currently selected lines using ``ansys-tools-visualization_interface``. show_line_numbering : bool, optional - Display line and keypoint numbers when ``vtk=True``. + Display line and keypoint numbers when ``graphics_backend=GraphicsBackend.PYVISTA``. show_keypoint_numbering : bool, optional Number keypoints. Only valid when ``show_keypoints=True`` @@ -513,29 +537,24 @@ def lplot( **kwargs See :class:`ansys.mapdl.core.plotting.visualizer.MapdlPlotter` for more keyword arguments applicable when visualizing with - ``vtk=True``. + ``graphics_backend=GraphicsBackend.PYVISTA``. Notes ----- Mesh divisions on plotted lines are controlled by the ``ldiv`` - option of the ``psymb`` command when ``vtk=False``. + option of the ``psymb`` command when ``graphics_backend=GraphicsBackend.MAPDL``. Otherwise, line divisions are controlled automatically. This command is valid in any processor. Examples -------- - >>> mapdl.lplot(vtk=True, cpos='xy', line_width=10) + >>> mapdl.lplot(graphics_backend=GraphicsBackend.PYVISTA, cpos='xy', line_width=10) """ - if vtk is None: - vtk = self._use_vtk - elif vtk is True: - if not _HAS_VISUALIZER: # pragma: no cover - raise ModuleNotFoundError( - "Using the keyword argument 'vtk' requires having 'ansys-tools-visualization_interface' installed." - ) + if graphics_backend is None: + graphics_backend = self._graphics_backend - if vtk: + if graphics_backend: from ansys.mapdl.core.plotting.theme import get_ansys_colors from ansys.mapdl.core.plotting.visualizer import MapdlPlotter @@ -610,6 +629,8 @@ def lplot( with self._enable_interactive_plotting(): return super().lplot(nl1=nl1, nl2=nl2, ninc=ninc, **kwargs) + @check_deprecated_vtk_kwargs + @requires_graphics def aplot( self, na1="", @@ -617,7 +638,8 @@ def aplot( ninc="", degen="", scale="", - vtk=None, + *, + graphics_backend=None, quality=4, show_area_numbering=False, show_line_numbering=False, @@ -633,7 +655,7 @@ def aplot( APDL Command: ``APLOT`` .. note:: - PyMAPDL plotting commands with ``vtk=True`` ignore any + PyMAPDL plotting commands with ``graphics_backend=GraphicsBackend.PYVISTA`` ignore any values set with the ``PNUM`` command. Parameters @@ -648,31 +670,31 @@ def aplot( Increment between minimum and maximum area. degen, str, optional - Degeneracy marker. This option is ignored when ``vtk=True``. + Degeneracy marker. This option is ignored when ``graphics_backend=GraphicsBackend.PYVISTA``. scale : float, optional Scale factor for the size of the degeneracy-marker star. The scale is the size in window space (-1 to 1 in both directions) (defaults to 0.075). This option is ignored - when ``vtk=True``. + when ``graphics_backend != GraphicsBackend.MAPDL``. - vtk : bool, optional + graphics_backend : GraphicsBackend, optional Plot the currently selected areas using ``ansys-tools-visualization_interface``. As this creates a temporary surface mesh, this may have a long execution time for large meshes. quality : int, optional Quality of the mesh to display. Varies between 1 (worst) - to 10 (best) when ``vtk=True``. + to 10 (best) when ``graphics_backend=GraphicsBackend.PYVISTA``. show_area_numbering : bool, optional - Display area numbers when ``vtk=True``. + Display area numbers when ``graphics_backend=GraphicsBackend.PYVISTA``. show_line_numbering : bool, optional - Display line numbers when ``vtk=True``. + Display line numbers when ``graphics_backend=GraphicsBackend.PYVISTA``. color_areas : Union[bool, str, np.array], optional - Only used when ``vtk=True``. + Only used when ``graphics_backend=GraphicsBackend.PYVISTA``. If ``color_areas`` is a bool, randomly color areas when ``True``. If ``color_areas`` is a string, it must be a valid color string which will be applied to all areas. @@ -687,7 +709,7 @@ def aplot( **kwargs See :class:`ansys.mapdl.core.plotting.visualizer.MapdlPlotter` for more keyword arguments applicable when visualizing with - ``vtk=True``. + ``graphics_backend=GraphicsBackend.PYVISTA``. Examples -------- @@ -711,15 +733,10 @@ def aplot( >>> pl.show() """ - if vtk is None: - vtk = self._use_vtk - elif vtk is True: - if not _HAS_VISUALIZER: # pragma: no cover - raise ModuleNotFoundError( - "Using the keyword argument 'vtk' requires having 'ansys-tools-visualization_interface' installed." - ) + if graphics_backend is None: + graphics_backend = self._graphics_backend - if vtk: + if graphics_backend: from matplotlib.colors import to_rgba from ansys.mapdl.core.plotting.theme import get_ansys_colors @@ -841,12 +858,14 @@ def aplot( pl = MapdlPlotter() pl.plot(meshes, [], labels, **kwargs) return pl.show(**kwargs) + if graphics_backend is GraphicsBackend.MAPDL: + with self._enable_interactive_plotting(): + return super().aplot( + na1=na1, na2=na2, ninc=ninc, degen=degen, scale=scale, **kwargs + ) - with self._enable_interactive_plotting(): - return super().aplot( - na1=na1, na2=na2, ninc=ninc, degen=degen, scale=scale, **kwargs - ) - + @check_deprecated_vtk_kwargs + @requires_graphics def vplot( self, nv1="", @@ -854,7 +873,8 @@ def vplot( ninc="", degen="", scale="", - vtk=None, + *, + graphics_backend=None, quality=4, show_volume_numbering=False, show_area_numbering=False, @@ -868,7 +888,7 @@ def vplot( APDL Command: VPLOT .. note:: - PyMAPDL plotting commands with ``vtk=True`` ignore any + PyMAPDL plotting commands with ``graphics_backend=GraphicsBackend.PYVISTA`` ignore any values set with the ``PNUM`` command. Parameters @@ -877,36 +897,36 @@ def vplot( Display volumes from NV1 to NV2 (defaults to NV1) in steps of NINC (defaults to 1). If NV1 = ALL (default), NV2 and NINC are ignored and all selected volumes [VSEL] are - displayed. Ignored when ``vtk=True``. + displayed. Ignored when ``graphics_backend=GraphicsBackend.PYVISTA``. degen Degeneracy marker. ``"blank"`` No degeneracy marker is used (default), or ``"DEGE"``. A red star is placed on keypoints at degeneracies (see the Modeling and Meshing Guide). Not available if /FACET,WIRE is set. Ignored - when ``vtk=True``. + when ``graphics_backend=GraphicsBackend.PYVISTA``. scale Scale factor for the size of the degeneracy-marker star. The scale is the size in window space (-1 to 1 in both directions) (defaults - to .075). Ignored when ``vtk=True``. + to .075). Ignored when ``graphics_backend=GraphicsBackend.PYVISTA``. - vtk : bool, optional + graphics_backend : GraphicsBackend, optional Plot the currently selected volumes using ``ansys-tools-visualization_interface``. As this creates a temporary surface mesh, this may have a long execution time for large meshes. quality : int, optional quality of the mesh to display. Varies between 1 (worst) - to 10 (best). Applicable when ``vtk=True``. + to 10 (best). Applicable when ``graphics_backend=GraphicsBackend.PYVISTA``. show_numbering : bool, optional - Display line and keypoint numbers when ``vtk=True``. + Display line and keypoint numbers when ``graphics_backend=GraphicsBackend.PYVISTA``. **kwargs See :class:`ansys.mapdl.core.plotting.visualizer.MapdlPlotter` for more keyword arguments applicable when visualizing with - ``vtk=True``. + ``graphics_backend=GraphicsBackend.PYVISTA``. Examples -------- @@ -915,15 +935,10 @@ def vplot( >>> mapdl.vplot(show_area_numbering=True) """ - if vtk is None: - vtk = self._use_vtk - elif vtk is True: - if not _HAS_VISUALIZER: # pragma: no cover - raise ModuleNotFoundError( - "Using the keyword argument 'vtk' requires having 'ansys-tools-visualization_interface' installed." - ) + if graphics_backend is None: + graphics_backend = self._graphics_backend - if vtk: + if graphics_backend is GraphicsBackend.PYVISTA: from ansys.mapdl.core.plotting.visualizer import MapdlPlotter pl = kwargs.get("plotter", None) @@ -953,7 +968,7 @@ def vplot( self.aslv("S", mute=True) # select areas attached to active volumes pl_aplot = self.aplot( - vtk=True, + graphics_backend=GraphicsBackend.PYVISTA, color_areas=color_areas, quality=quality, show_area_numbering=show_area_numbering, @@ -975,19 +990,23 @@ def vplot( pl.plot(meshes, points, labels, **kwargs) return pl.show(return_plotter=return_plotter, **kwargs) - else: + elif graphics_backend is GraphicsBackend.MAPDL: with self._enable_interactive_plotting(): return super().vplot( nv1=nv1, nv2=nv2, ninc=ninc, degen=degen, scale=scale, **kwargs ) + else: + raise ValueError(f"Invalid graphics backend: {graphics_backend}. ") - def nplot(self, nnum="", vtk=None, **kwargs): + @check_deprecated_vtk_kwargs + @requires_graphics + def nplot(self, nnum="", *, graphics_backend=None, **kwargs): """APDL Command: NPLOT Displays nodes. .. note:: - PyMAPDL plotting commands with ``vtk=True`` ignore any + PyMAPDL plotting commands with ``graphics_backend=GraphicsBackend.PYVISTA`` ignore any values set with the ``PNUM`` command. Parameters @@ -999,11 +1018,11 @@ def nplot(self, nnum="", vtk=None, **kwargs): - ``True`` : Include node numbers on display. .. note:: - This parameter is only valid when ``vtk==True`` + This parameter is only valid when ``graphics_backend==GraphicsBackend.PYVISTA`` - vtk : bool, optional - Plot the currently selected nodes using ``pyvista``. - Defaults to current ``use_vtk`` setting as set on the + graphics_backend : GraphicsBackend, optional + Plot the currently selected nodes using an specific backend. + Defaults to current ``graphics_backend`` setting as set on the initialization of MAPDL. plot_bc : bool, optional @@ -1070,7 +1089,7 @@ def nplot(self, nnum="", vtk=None, **kwargs): >>> mapdl.fill(1, 11, 9) >>> mapdl.nplot( ... nnum=True, - ... vtk=True, + ... graphics_backend=GraphicsBackend.PYVISTA, ... background='w', ... color='k', ... show_bounds=True @@ -1082,7 +1101,7 @@ def nplot(self, nnum="", vtk=None, **kwargs): >>> mapdl.n(1, 0, 0, 0) >>> mapdl.n(11, 10, 0, 0) >>> mapdl.fill(1, 11, 9) - >>> mapdl.nplot(vtk=False) + >>> mapdl.nplot(graphics_backend=GraphicsBackend.MAPDL) Plot nodal boundary conditions. @@ -1093,22 +1112,15 @@ def nplot(self, nnum="", vtk=None, **kwargs): ... ) """ - if vtk is None: - vtk = self._use_vtk - - if vtk is True: - if _HAS_VISUALIZER: - # lazy import here to avoid top level import - import pyvista as pv - else: # pragma: no cover - raise ModuleNotFoundError( - "Using the keyword argument 'vtk' requires having 'ansys-tools-visualization_interface' installed." - ) + if graphics_backend is None: + graphics_backend = self._graphics_backend if "knum" in kwargs: raise ValueError("`knum` keyword deprecated. Please use `nnum` instead.") - if vtk: + if graphics_backend is GraphicsBackend.PYVISTA: + import pyvista as pv + from ansys.mapdl.core.plotting.visualizer import MapdlPlotter pl = kwargs.get("plotter", None) @@ -1134,27 +1146,32 @@ def nplot(self, nnum="", vtk=None, **kwargs): pl.plot([], points, labels, mapdl=self, **kwargs) return pl.show(**kwargs) - # otherwise, use the built-in nplot - if isinstance(nnum, bool): - nnum = int(nnum) + elif graphics_backend is GraphicsBackend.MAPDL: + # otherwise, use the built-in nplot + if isinstance(nnum, bool): + nnum = int(nnum) - with self._enable_interactive_plotting(): - return super().nplot(nnum, **kwargs) + with self._enable_interactive_plotting(): + return super().nplot(nnum, **kwargs) + else: + raise ValueError(f"Invalid graphics backend: {graphics_backend}. ") - def eplot(self, show_node_numbering=False, vtk=None, **kwargs): + @check_deprecated_vtk_kwargs + @requires_graphics + def eplot(self, show_node_numbering=False, *, graphics_backend=None, **kwargs): """Plots the currently selected elements. APDL Command: EPLOT .. note:: - PyMAPDL plotting commands with ``vtk=True`` ignore any + PyMAPDL plotting commands with ``graphics_backend=GraphicsBackend.PYVISTA`` ignore any values set with the ``PNUM`` command. Parameters ---------- - vtk : bool, optional - Plot the currently selected elements using ``ansys-tools-visualization_interface``. - Defaults to current ``use_vtk`` setting. + graphics_backend : GraphicsBackend, optional + Plot the currently selected elements using the picked backend. + Defaults to current ``graphics_backend`` setting. show_node_numbering : bool, optional Plot the node numbers of surface nodes. @@ -1215,7 +1232,7 @@ def eplot(self, show_node_numbering=False, vtk=None, **kwargs): **kwargs See ``help(ansys.mapdl.core.plotting.visualizer.MapdlPlotter)`` for more - keyword arguments related to visualizing using ``vtk``. + keyword arguments related to visualizing using ``graphics_backend``. Examples -------- @@ -1236,15 +1253,10 @@ def eplot(self, show_node_numbering=False, vtk=None, **kwargs): off_screen=True) """ - if vtk is None: - vtk = self._use_vtk - elif vtk is True: - if not _HAS_VISUALIZER: # pragma: no cover - raise ModuleNotFoundError( - "Using the keyword argument 'vtk' requires having 'ansys-tools-visualization_interface' installed." - ) + if graphics_backend is None: + graphics_backend = self._graphics_backend - if vtk: + if graphics_backend is GraphicsBackend.PYVISTA: from ansys.mapdl.core.plotting.visualizer import MapdlPlotter pl = kwargs.get("plotter", None) @@ -1279,10 +1291,10 @@ def eplot(self, show_node_numbering=False, vtk=None, **kwargs): **kwargs, ) return pl.show(**kwargs) - - # otherwise, use MAPDL plotter - with self._enable_interactive_plotting(): - return self.run("EPLOT", **kwargs) + elif graphics_backend is GraphicsBackend.MAPDL: + # otherwise, use MAPDL plotter + with self._enable_interactive_plotting(): + return self.run("EPLOT", **kwargs) def clear(self, *args, **kwargs): """Clear the database. diff --git a/src/ansys/mapdl/core/mapdl_inprocess.py b/src/ansys/mapdl/core/mapdl_inprocess.py index ca486cf9f4d..d7b9e95d6c8 100644 --- a/src/ansys/mapdl/core/mapdl_inprocess.py +++ b/src/ansys/mapdl/core/mapdl_inprocess.py @@ -23,6 +23,7 @@ from typing import Protocol from ansys.mapdl.core.mapdl import MapdlBase +from ansys.mapdl.core.plotting import GraphicsBackend class _Backend(Protocol): @@ -44,7 +45,10 @@ def exit(self) -> None: ... class MapdlInProcess(MapdlBase): def __init__(self, in_process_backend: _Backend): super().__init__( - loglevel="WARNING", use_vtk=False, log_apdl=None, print_com=False + loglevel="WARNING", + graphics_backend=GraphicsBackend.MAPDL, + log_apdl=None, + print_com=False, ) self._in_process_backend = in_process_backend self._cleanup: bool = True diff --git a/src/ansys/mapdl/core/misc.py b/src/ansys/mapdl/core/misc.py index ff0ddafb582..b2a34fe1640 100644 --- a/src/ansys/mapdl/core/misc.py +++ b/src/ansys/mapdl/core/misc.py @@ -37,7 +37,8 @@ import numpy as np -from ansys.mapdl.core import _HAS_PYVISTA, LOG +from ansys.mapdl.core import _HAS_PYVISTA, _HAS_VISUALIZER, LOG +from ansys.mapdl.core.plotting import GraphicsBackend # path of this module MODULE_PATH = os.path.dirname(inspect.getfile(inspect.currentframe())) @@ -425,6 +426,41 @@ def is_package_installed_cached(package_name): return False +def requires_graphics(function): + """Warn the user if the visualizer is not installed""" + + @wraps(function) + def wrapper(*args, **kwargs): + if not _HAS_VISUALIZER: + raise ModuleNotFoundError( + "Graphic libraries are required to use this method.\n" + "You can install this using `pip install ansys-mapdl-core[graphics]`." + ) + return function(*args, **kwargs) + + return wrapper + + +def check_deprecated_vtk_kwargs(func: Callable) -> Callable: + """Decorator to warn if 'vtk' or 'use_vtk' are passed as kwargs.""" + + @wraps(func) + def wrapper(*args, **kwargs): + if "vtk" in kwargs or "use_vtk" in kwargs: + warn( + "From 0.70.0, the arguments 'vtk' and 'use_vtk' are deprecated. " + "To use interactive plots, use 'graphics_backend=GraphicsBackend.PYVISTA' instead. ", + DeprecationWarning, + stacklevel=2, + ) + if kwargs.get("vtk") is False or kwargs.get("use_vtk") is False: + kwargs["graphics_backend"] = GraphicsBackend.MAPDL + + return func(*args, **kwargs) + + return wrapper + + def requires_package(package_name: str, softerror: bool = False) -> Callable: """ Decorator check whether a package is installed or not. diff --git a/src/ansys/mapdl/core/plotting/__init__.py b/src/ansys/mapdl/core/plotting/__init__.py index a3f379af201..474d6ba7554 100644 --- a/src/ansys/mapdl/core/plotting/__init__.py +++ b/src/ansys/mapdl/core/plotting/__init__.py @@ -19,6 +19,9 @@ # 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. + +from enum import Enum + from ansys.mapdl.core import _HAS_VISUALIZER from ansys.mapdl.core.plotting.consts import ( # noqa: F401 ALLOWED_TARGETS, @@ -30,6 +33,17 @@ POINT_SIZE, ) + +class GraphicsBackend(Enum): + """Graphics backend for PyMAPDL. + + This enum is used to set the graphics backend for PyMAPDL. + """ + + PYVISTA: str = "pyvista" + MAPDL: str = "mapdl" + + if _HAS_VISUALIZER: from ansys.mapdl.core.plotting.theme import MapdlTheme # noqa: F401 from ansys.mapdl.core.plotting.visualizer import MapdlPlotter # noqa: F401 diff --git a/src/ansys/mapdl/core/post.py b/src/ansys/mapdl/core/post.py index a0dcd3b0adc..def5a43d657 100644 --- a/src/ansys/mapdl/core/post.py +++ b/src/ansys/mapdl/core/post.py @@ -527,7 +527,7 @@ def plot_nodal_values(self, item, comp, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -599,7 +599,7 @@ def plot_element_values( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -910,7 +910,7 @@ def plot_nodal_temperature(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1030,7 +1030,7 @@ def plot_nodal_displacement( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1146,7 +1146,7 @@ def plot_nodal_rotation(self, component, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1280,7 +1280,7 @@ def plot_element_displacement( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1426,7 +1426,7 @@ def plot_element_stress( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1536,7 +1536,7 @@ def plot_element_temperature( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1606,7 +1606,7 @@ def plot_nodal_pressure(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1695,7 +1695,7 @@ def plot_nodal_voltage(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1798,7 +1798,7 @@ def plot_nodal_component_stress( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1889,7 +1889,7 @@ def plot_nodal_principal_stress( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -1966,7 +1966,7 @@ def plot_nodal_stress_intensity(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2062,7 +2062,7 @@ def plot_nodal_eqv_stress(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2167,7 +2167,7 @@ def plot_nodal_total_component_strain( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2266,7 +2266,7 @@ def plot_nodal_total_principal_strain( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2347,7 +2347,7 @@ def plot_nodal_total_strain_intensity(self, show_node_numbering=False, **kwargs) Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2443,7 +2443,7 @@ def plot_nodal_total_eqv_strain(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2541,7 +2541,7 @@ def plot_nodal_elastic_component_strain( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2637,7 +2637,7 @@ def plot_nodal_elastic_principal_strain( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2722,7 +2722,7 @@ def plot_nodal_elastic_strain_intensity(self, show_node_numbering=False, **kwarg Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2817,7 +2817,7 @@ def plot_nodal_elastic_eqv_strain(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -2920,7 +2920,7 @@ def plot_nodal_plastic_component_strain( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -3010,7 +3010,7 @@ def plot_nodal_plastic_principal_strain( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -3096,7 +3096,7 @@ def plot_nodal_plastic_strain_intensity(self, show_node_numbering=False, **kwarg Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -3198,7 +3198,7 @@ def plot_nodal_plastic_eqv_strain(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -3302,7 +3302,7 @@ def plot_nodal_thermal_component_strain( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -3398,7 +3398,7 @@ def plot_nodal_thermal_principal_strain( Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -3484,7 +3484,7 @@ def plot_nodal_thermal_strain_intensity(self, show_node_numbering=False, **kwarg Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -3586,7 +3586,7 @@ def plot_nodal_thermal_eqv_strain(self, show_node_numbering=False, **kwargs): Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using @@ -3678,7 +3678,7 @@ def plot_nodal_contact_friction_stress(self, show_node_numbering=False, **kwargs Notes ----- - If ``vkt=True`` (default), this function uses + If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses :class:`MapdlPlotter` You can pass key arguments to :class:`MapdlPlotter` using diff --git a/tests/conftest.py b/tests/conftest.py index 65dbcd2caba..7dab35e9738 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -229,6 +229,7 @@ def requires_dependency(dependency: str): from ansys.mapdl.core.examples import vmfiles from ansys.mapdl.core.launcher import get_start_instance, launch_mapdl from ansys.mapdl.core.mapdl_core import VALID_DEVICES +from ansys.mapdl.core.plotting import GraphicsBackend if has_dependency("ansys-tools-visualization_interface"): import ansys.tools.visualization_interface as viz_interface @@ -471,6 +472,7 @@ def run_before_and_after_tests( assert not mapdl.ignore_errors, "Mapdl class is ignoring errors!" assert not mapdl.mute assert mapdl.file_type_for_plots in VALID_DEVICES + assert mapdl._graphics_backend is GraphicsBackend.PYVISTA assert mapdl._jobid is None # Returning to default diff --git a/tests/test_cli.py b/tests/test_cli.py index af9945e3bb8..a9255291e4a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -29,6 +29,7 @@ import psutil import pytest +from ansys.mapdl.core.plotting import GraphicsBackend from conftest import VALID_PORTS, requires if VALID_PORTS: @@ -59,7 +60,7 @@ def make_fake_process(pid, name, port=PORT1, ansys_process=False, n_children=0): @pytest.fixture(scope="function") def run_cli(): - def do_run(arguments=""): + def do_run(arguments="", expect_error=False): from click.testing import CliRunner from ansys.mapdl.core.cli import main @@ -71,8 +72,10 @@ def do_run(arguments=""): runner = CliRunner() result = runner.invoke(main, args) - - assert result.exit_code == 0 + if expect_error: + assert result.exit_code != 0 + else: + assert result.exit_code == 0 return result.output return do_run @@ -390,7 +393,7 @@ def test_convert_pipe(output): "header": True, "print_com": True, "only_commands": False, - "use_vtk": None, + "graphics_backend": None, "clear_at_start": False, "check_parameter_names": False, } @@ -414,7 +417,11 @@ def test_convert_pipe(output): ("header", False), ("print_com", False), ("only_commands", True), - ("use_vtk", True), + ("graphics_backend", "MAPDL"), + ("graphics_backend", "mapdl"), + ("graphics_backend", "pyvista"), + ("graphics_backend", "pyVISTa"), + ("graphics_backend", "no_exists"), ("clear_at_start", True), ("check_parameter_names", True), ), @@ -429,15 +436,22 @@ def test_convert_passing(mock_conv, run_cli, tmpdir, arg, value): default_ = DEFAULT_ARGS.copy() default_[arg] = value - + expect_error = False + if value == "no_exists": + expect_error = True if arg not in ["only_commands"]: - run_cli(f"convert -f {input_file} --{arg} {value}") + run_cli(f"convert -f {input_file} --{arg} {value}", expect_error) else: - run_cli(f"convert -f {input_file} --{arg}") + run_cli(f"convert -f {input_file} --{arg}", expect_error) + # Early return if expect_error is True and function is not called + if expect_error: + return mock_conv.assert_called() kwargs = mock_conv.call_args.kwargs - for key in DEFAULT_ARGS: - assert kwargs[key] == default_[key] + if key == "graphics_backend" and arg == "graphics_backend": + assert kwargs[key] == GraphicsBackend[value.upper()] + else: + assert kwargs[key] == default_[key] diff --git a/tests/test_console.py b/tests/test_console.py index 91588aab3b4..dbc6e3848c3 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -48,6 +48,7 @@ from ansys.mapdl import core as pymapdl from ansys.mapdl.core.errors import MapdlRuntimeError +from ansys.mapdl.core.plotting import GraphicsBackend @pytest.fixture(scope="function") @@ -239,7 +240,7 @@ def test_invalid_area(mapdl_console, cleared): @requires("xserver") def test_kplot(cleared, mapdl_console, tmpdir): with pytest.raises(MapdlRuntimeError): - mapdl_console.kplot(vtk=True) + mapdl_console.kplot() mapdl_console.k("", 0, 0, 0) mapdl_console.k("", 1, 0, 0) @@ -251,7 +252,9 @@ def test_kplot(cleared, mapdl_console, tmpdir): assert cpos is None assert os.path.isfile(filename) - mapdl_console.kplot(knum=True, vtk=False) # make sure legacy still works + mapdl_console.kplot( + knum=True, backend=GraphicsBackend.MAPDL + ) # make sure legacy still works @requires("xserver") @@ -272,14 +275,14 @@ def test_aplot(cleared, mapdl_console): mapdl_console.aplot(quality=-1) # and legacy as well - mapdl_console.aplot(vtk=False) + mapdl_console.aplot(graphics_backend=GraphicsBackend.MAPDL) @requires("xserver") -@pytest.mark.parametrize("vtk", [True, False]) -def test_vplot(cleared, mapdl_console, vtk): +@pytest.mark.parametrize("backend", [GraphicsBackend.PYVISTA, GraphicsBackend.MAPDL]) +def test_vplot(cleared, mapdl_console, backend): mapdl_console.block(0, 1, 0, 1, 0, 1) - mapdl_console.vplot(vtk=vtk, color_areas=True) + mapdl_console.vplot(graphics_backend=backend, color_areas=True) def test_keypoints(cleared, mapdl_console): @@ -319,7 +322,7 @@ def test_lines(cleared, mapdl_console): @requires("xserver") def test_lplot(cleared, mapdl_console, tmpdir): with pytest.raises(MapdlRuntimeError): - mapdl_console.lplot(vtk=True) + mapdl_console.lplot() k0 = mapdl_console.k("", 0, 0, 0) k1 = mapdl_console.k("", 1, 0, 0) @@ -335,7 +338,9 @@ def test_lplot(cleared, mapdl_console, tmpdir): assert cpos is None assert os.path.isfile(filename) - mapdl_console.lplot(vtk=False) # make sure legacy still works + mapdl_console.lplot( + graphics_backend=GraphicsBackend.MAPDL + ) # make sure legacy still works def test_logging(mapdl_console, tmpdir): @@ -399,7 +404,7 @@ def test_nplot_vtk(cleared, mapdl_console, knum): mapdl_console.n(1, 0, 0, 0) mapdl_console.n(11, 10, 0, 0) mapdl_console.fill(1, 11, 9) - mapdl_console.nplot(vtk=True, knum=knum, background="w", color="k") + mapdl_console.nplot(knum=knum, background="w", color="k") @requires("xserver") @@ -407,7 +412,9 @@ def test_nplot(cleared, mapdl_console): mapdl_console.n(1, 0, 0, 0) mapdl_console.n(11, 10, 0, 0) mapdl_console.fill(1, 11, 9) - mapdl_console.nplot(vtk=False, background="w", color="k") + mapdl_console.nplot( + graphics_backend=GraphicsBackend.MAPDL, background="w", color="k" + ) def test_elements(cleared, mapdl_console): diff --git a/tests/test_convert.py b/tests/test_convert.py index 5f04596c11c..69c7a9bbfb8 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -31,6 +31,7 @@ FileTranslator, convert_apdl_block, ) +from ansys.mapdl.core.plotting import GraphicsBackend from conftest import requires nblock = """nblock,3,,326253 @@ -508,20 +509,22 @@ def test_only_commands(): assert "mapdl.exit" not in output -@pytest.mark.parametrize("vtk", [None, True, False]) -def test_use_vtk(vtk): +@pytest.mark.parametrize( + "backend", [None, GraphicsBackend.PYVISTA, GraphicsBackend.MAPDL] +) +def test_graphics_backend(backend): output = convert_apdl_block( "/view,1,1,1", only_commands=False, add_imports=True, - use_vtk=vtk, + graphics_backend=backend, ) assert "mapdl.view(1, 1, 1)" in output assert "launch_mapdl" in output - if vtk is None: - assert "use_vtk" not in output + if backend is None: + assert "graphics_backend" not in output else: - assert f"use_vtk={vtk}" in output + assert f"graphics_backend={backend}" in output @pytest.mark.parametrize("check_parameter_names", [None, True, False]) diff --git a/tests/test_mapdl.py b/tests/test_mapdl.py index 6e5cbbc95dd..d52089b10a7 100644 --- a/tests/test_mapdl.py +++ b/tests/test_mapdl.py @@ -66,6 +66,7 @@ from ansys.mapdl.core.launcher import launch_mapdl from ansys.mapdl.core.mapdl_grpc import SESSION_ID_NAME from ansys.mapdl.core.misc import random_string, stack +from ansys.mapdl.core.plotting import GraphicsBackend from conftest import IS_SMP, ON_CI, ON_LOCAL, QUICK_LAUNCH_SWITCHES, requires # Path to files needed for examples @@ -2453,14 +2454,14 @@ def test_default_file_type_for_plots(mapdl, cleared): @requires("matplotlib") -def test_use_vtk(mapdl, cleared): - assert isinstance(mapdl.use_vtk, bool) +def test_graphics_backend(mapdl, cleared): + assert isinstance(mapdl.graphics_backend, GraphicsBackend) - prev = mapdl.use_vtk - mapdl.use_vtk = False + prev = mapdl.graphics_backend + mapdl.graphics_backend = GraphicsBackend.MAPDL mapdl.eplot() - mapdl.use_vtk = prev + mapdl.graphics_backend = prev @requires("local") diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 85a93cfb44c..f597f7e8e81 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -33,6 +33,7 @@ pytest.skip(allow_module_level=True) from ansys.mapdl.core.errors import ComponentDoesNotExits, MapdlRuntimeError +from ansys.mapdl.core.plotting import GraphicsBackend from ansys.mapdl.core.plotting.visualizer import MapdlPlotter FORCE_LABELS = [["FX", "FY", "FZ"], ["HEAT"], ["CHRG"]] @@ -146,48 +147,49 @@ def check_geometry(mapdl, function): def test_plot_empty_mesh(mapdl, cleared): with pytest.warns(UserWarning): - mapdl.nplot(vtk=True) + mapdl.nplot() with pytest.warns(UserWarning): - mapdl.eplot(vtk=True) + mapdl.eplot() def test_download_file_with_vkt_false(mapdl, cube_solve, tmpdir): # Testing basic behaviour - mapdl.eplot(vtk=False, savefig="myfile.png") - assert os.path.exists("myfile.png") - ti_m = os.path.getmtime("myfile.png") + with patch.object(mapdl, "_graphics_backend", GraphicsBackend.MAPDL): + mapdl.eplot(savefig="myfile.png") + assert os.path.exists("myfile.png") + ti_m = os.path.getmtime("myfile.png") - # Testing overwriting - mapdl.eplot(vtk=False, savefig="myfile.png") - assert not os.path.exists("myfile_1.png") - assert os.path.getmtime("myfile.png") != ti_m # file has been modified. + # Testing overwriting + mapdl.eplot(savefig="myfile.png") + assert not os.path.exists("myfile_1.png") + assert os.path.getmtime("myfile.png") != ti_m # file has been modified. - os.remove("myfile.png") + os.remove("myfile.png") - # Testing no extension - mapdl.eplot(vtk=False, savefig="myfile") - assert os.path.exists("myfile") - os.remove("myfile") + # Testing no extension + mapdl.eplot(savefig="myfile") + assert os.path.exists("myfile") + os.remove("myfile") - # Testing update name when file exists. - mapdl.eplot(vtk=False, savefig=True) - assert os.path.exists("plot.png") + # Testing update name when file exists. + mapdl.eplot(savefig=True) + assert os.path.exists("plot.png") - mapdl.eplot(vtk=False, savefig=True) - assert os.path.exists("plot_1.png") + mapdl.eplot(savefig=True) + assert os.path.exists("plot_1.png") - os.remove("plot.png") - os.remove("plot_1.png") + os.remove("plot.png") + os.remove("plot_1.png") - # Testing full path for downloading - plot_ = os.path.join(tmpdir, "myplot.png") - mapdl.eplot(vtk=False, savefig=plot_) - assert os.path.exists(plot_) + # Testing full path for downloading + plot_ = os.path.join(tmpdir, "myplot.png") + mapdl.eplot(savefig=plot_) + assert os.path.exists(plot_) - plot_ = os.path.join(tmpdir, "myplot") - mapdl.eplot(vtk=False, savefig=plot_) - assert os.path.exists(plot_) + plot_ = os.path.join(tmpdir, "myplot") + mapdl.eplot(savefig=plot_) + assert os.path.exists(plot_) @pytest.mark.parametrize( @@ -202,25 +204,29 @@ def test_download_file_with_vkt_false(mapdl, cube_solve, tmpdir): ], ) def test_plots_no_vtk(mapdl, cube_solve, method): - _ = getattr(mapdl, method)(vtk=False) + _ = getattr(mapdl, method)(graphics_backend=GraphicsBackend.MAPDL) -@pytest.mark.parametrize("vtk", [True, False, None]) -def test_kplot(cleared, mapdl, tmpdir, vtk): +@pytest.mark.parametrize( + "backend", [GraphicsBackend.PYVISTA, GraphicsBackend.MAPDL, None] +) +def test_kplot(cleared, mapdl, tmpdir, backend): mapdl.k("", 0, 0, 0) mapdl.k("", 1, 0, 0) mapdl.k("", 1, 1, 0) mapdl.k("", 0, 1, 0) filename = str(tmpdir.mkdir("tmpdir").join("tmp.png")) - cpos = mapdl.kplot(vtk=vtk, savefig=filename) + cpos = mapdl.kplot(graphics_backend=backend, savefig=filename) assert cpos is None - if vtk: + if backend: assert os.path.isfile(filename) -@pytest.mark.parametrize("vtk", [True, False, None]) -def test_lplot(cleared, mapdl, tmpdir, vtk): +@pytest.mark.parametrize( + "backend", [GraphicsBackend.PYVISTA, GraphicsBackend.MAPDL, None] +) +def test_lplot(cleared, mapdl, tmpdir, backend): k0 = mapdl.k("", 0, 0, 0) k1 = mapdl.k("", 1, 0, 0) k2 = mapdl.k("", 1, 1, 0) @@ -231,14 +237,18 @@ def test_lplot(cleared, mapdl, tmpdir, vtk): mapdl.l(k3, k0) filename = str(tmpdir.mkdir("tmpdir").join("tmp.png")) - cpos = mapdl.lplot(vtk=vtk, show_keypoint_numbering=True, savefig=filename) + cpos = mapdl.lplot( + graphics_backend=backend, show_keypoint_numbering=True, savefig=filename + ) assert cpos is None - if vtk: + if backend: assert os.path.isfile(filename) -@pytest.mark.parametrize("vtk", [True, False, None]) -def test_aplot(cleared, mapdl, vtk): +@pytest.mark.parametrize( + "backend", [GraphicsBackend.PYVISTA, GraphicsBackend.MAPDL, None] +) +def test_aplot(cleared, mapdl, backend): k0 = mapdl.k("", 0, 0, 0) k1 = mapdl.k("", 1, 0, 0) k2 = mapdl.k("", 1, 1, 0) @@ -249,33 +259,47 @@ def test_aplot(cleared, mapdl, vtk): l3 = mapdl.l(k3, k0) mapdl.al(l0, l1, l2, l3) mapdl.aplot(show_area_numbering=True) - mapdl.aplot(vtk=vtk, color_areas=vtk, show_lines=True, show_line_numbering=True) + color_areas_bool = True if backend == GraphicsBackend.PYVISTA else False + mapdl.aplot( + backend=backend, + color_areas=color_areas_bool, + show_lines=True, + show_line_numbering=True, + ) mapdl.aplot(quality=10) mapdl.aplot(quality=1) -@pytest.mark.parametrize("vtk", [True, False, None]) -def test_vplot(cleared, mapdl, vtk): +@pytest.mark.parametrize( + "backend", [GraphicsBackend.PYVISTA, GraphicsBackend.MAPDL, None] +) +def test_vplot(cleared, mapdl, backend): mapdl.block(0, 1, 0, 1, 0, 1) - mapdl.vplot(vtk=vtk, color_areas=True) + mapdl.vplot(graphics_backend=backend, color_areas=True) @pytest.mark.parametrize("nnum", [True, False]) -@pytest.mark.parametrize("vtk", [True, False, None]) -def test_nplot(cleared, mapdl, nnum, vtk): +@pytest.mark.parametrize( + "backend", [GraphicsBackend.PYVISTA, GraphicsBackend.MAPDL, None] +) +def test_nplot(cleared, mapdl, nnum, backend): mapdl.n(1, 0, 0, 0) mapdl.n(11, 10, 0, 0) mapdl.fill(1, 11, 9) - mapdl.nplot(vtk=vtk, nnum=nnum, background="w", color="k") + mapdl.nplot(graphics_backend=backend, nnum=nnum, background="w", color="k") -@pytest.mark.parametrize("vtk", [True, False, None]) -def test_eplot(mapdl, make_block, vtk): +@pytest.mark.parametrize( + "backend", [GraphicsBackend.PYVISTA, GraphicsBackend.MAPDL, None] +) +def test_eplot(mapdl, make_block, backend): init_elem = mapdl.mesh.n_elem mapdl.aplot() # check aplot and verify it doesn't mess up the element plotting mapdl.eplot(show_node_numbering=True, background="w", color="b") - mapdl.eplot(vtk=vtk, show_node_numbering=True, background="w", color="b") + mapdl.eplot( + graphics_backend=backend, show_node_numbering=True, background="w", color="b" + ) mapdl.aplot() # check aplot and verify it doesn't mess up the element plotting assert mapdl.mesh.n_elem == init_elem @@ -950,7 +974,7 @@ def test_vsel_iterable_and_kswp(mapdl, make_block): def test_color_areas(mapdl, make_block): - mapdl.aplot(vtk=True, color_areas=True) + mapdl.aplot(color_areas=True) @pytest.mark.parametrize( @@ -971,17 +995,17 @@ def test_color_areas(mapdl, make_block): ) def test_color_areas_individual(mapdl, make_block, color_areas): # we do rely on the `pytest-pyvista` extension to deal with the differences - mapdl.aplot(vtk=True, color_areas=color_areas) + mapdl.aplot(color_areas=color_areas) def test_color_areas_error(mapdl, make_block): color_areas = ["red", "green", "blue"] with pytest.raises(ValueError): - mapdl.aplot(vtk=True, color_areas=color_areas) + mapdl.aplot(color_areas=color_areas) def test_WithInterativePlotting(mapdl, make_block): - mapdl.eplot(vtk=False) + mapdl.eplot(graphics_backend=GraphicsBackend.MAPDL) jobname = mapdl.jobname.upper() def filtering(file_name): @@ -1020,7 +1044,7 @@ def test_file_type_for_plots(mapdl, cleared): [each for each in mapdl.list_files() if each.endswith(".png")] ) - mapdl.eplot(vtk=False) + mapdl.eplot(graphics_backend=GraphicsBackend.MAPDL) n_files_ending_png_after = len( [each for each in mapdl.list_files() if each.endswith(".png")] ) @@ -1259,7 +1283,7 @@ def test_plot_path(mapdl, tmpdir): MapdlRuntimeError, match="One possible reason is that the graphics device is not correct", ): - mapdl.eplot(vtk=False) + mapdl.eplot(graphics_backend=GraphicsBackend.MAPDL) def test_add_mesh(): @@ -1305,3 +1329,10 @@ def test_plot_path_screenshoot(mapdl, cleared, tmpdir): # Returning to previous state. mapdl.graphics("FULL") + + +def test_deprecated_params(mapdl): + with pytest.warns(DeprecationWarning, match="'vtk' and 'use_vtk' are deprecated"): + mapdl.eplot(vtk=True) + with pytest.warns(DeprecationWarning, match="'vtk' and 'use_vtk' are deprecated"): + mapdl.eplot(vtk=False) diff --git a/tests/test_post.py b/tests/test_post.py index 56222823ab2..f1811bd0b0b 100644 --- a/tests/test_post.py +++ b/tests/test_post.py @@ -1324,8 +1324,9 @@ def test_meta_post_plot_docstrings(): ), f"The argument '{each_}' in '{meth.__name__}' is not in its docstring." assert ( - "If ``vkt=True`` (default), this function uses" in docstring - ), f"'vtk=True' part not found in {meth.__name__}" + "If ``graphics_backend=GraphicsBackend.PYVISTA`` (default), this function uses" + in docstring + ), f"'graphics_backend=GraphicsBackend.PYVISTA' part not found in {meth.__name__}" assert ( len( re.findall(