diff --git a/doc/source/api/mapdl.rst b/doc/source/api/mapdl.rst index 81d06094e1..abb93abca8 100644 --- a/doc/source/api/mapdl.rst +++ b/doc/source/api/mapdl.rst @@ -35,6 +35,8 @@ Mapdl.input_strings Mapdl.set_log_level Mapdl.version + Mapdl.use_vtk + Mapdl.file_type_for_plots Constants diff --git a/src/ansys/mapdl/core/mapdl.py b/src/ansys/mapdl/core/mapdl.py index 2a6edf851c..cf2fde75bd 100644 --- a/src/ansys/mapdl/core/mapdl.py +++ b/src/ansys/mapdl/core/mapdl.py @@ -73,6 +73,12 @@ DEBUG_LEVELS = Literal["DEBUG", "INFO", "WARNING", "ERROR"] +VALID_DEVICES = ["PNG", "TIFF", "VRML", "TERM", "CLOSE"] +VALID_DEVICES_LITERAL = Literal[tuple(["PNG", "TIFF", "VRML", "TERM", "CLOSE"])] + +VALID_FILE_TYPE_FOR_PLOT = VALID_DEVICES.copy() +VALID_FILE_TYPE_FOR_PLOT.remove("CLOSE") +VALID_FILE_TYPE_FOR_PLOT_LITERAL = Literal[tuple(VALID_FILE_TYPE_FOR_PLOT)] _PERMITTED_ERRORS = [ r"(\*\*\* ERROR \*\*\*).*(?:[\r\n]+.*)+highly distorted.", @@ -204,6 +210,7 @@ def __init__( log_file: Union[bool, str] = False, local: bool = True, print_com: bool = False, + file_type_for_plots: VALID_FILE_TYPE_FOR_PLOT_LITERAL = "PNG", **start_parm, ): """Initialize connection with MAPDL.""" @@ -222,6 +229,8 @@ def __init__( self._launched: bool = False self._stderr = None self._stdout = None + self._file_type_for_plots = file_type_for_plots + self._default_file_type_for_plots = file_type_for_plots if _HAS_PYVISTA: if use_vtk is not None: # pragma: no cover @@ -331,6 +340,48 @@ def is_console(self): """Return true if using console to connect to the MAPDL instance.""" return self._mode == "console" + @property + def file_type_for_plots(self): + """Returns the current file type for plotting.""" + return self._file_type_for_plots + + @file_type_for_plots.setter + def file_type_for_plots(self, value: VALID_DEVICES_LITERAL): + """Modify the current file type for plotting.""" + if isinstance(value, str) and value.upper() in VALID_DEVICES: + self._run( + f"/show, {value.upper()}" + ) # To avoid recursion we need to use _run. + self._file_type_for_plots = value.upper() + else: + raise ValueError(f"'{value}' is not allowed as file output for plots.") + + @property + def default_file_type_for_plots(self): + """Default file type for plots. + + Use when device is not properly set, for instance when the device is closed.""" + return self._default_file_type_for_plots + + @default_file_type_for_plots.setter + def default_file_type_for_plots(self, value: VALID_FILE_TYPE_FOR_PLOT_LITERAL): + """Set default file type for plots. + + Used when device is not properly set, for instance when the device is closed.""" + if not isinstance(value, str) and value.upper() not in VALID_FILE_TYPE_FOR_PLOT: + raise ValueError(f"'{value}' is not allowed as file output for plots.") + return self._default_file_type_for_plots + + @property + def use_vtk(self): + """Returns if using VTK by default or not.""" + return self._use_vtk + + @use_vtk.setter + def use_vtk(self, value: bool): + """Set VTK to be used by default or not.""" + self._use_vtk = value + def _wrap_listing_functions(self): # Wrapping LISTING FUNCTIONS. def wrap_listing_function(func): @@ -1878,6 +1929,11 @@ def __enter__(self) -> None: self._parent().show("PNG", mute=True) self._parent().gfile(self._pixel_res, mute=True) + self.previous_device = self._parent().file_type_for_plots + + if self._parent().file_type_for_plots not in ["PNG", "TIFF", "PNG", "VRML"]: + self._parent().show(self._parent().default_file_type_for_plots) + def __exit__(self, *args) -> None: self._parent()._log.debug("Exiting in 'WithInterativePlotting' mode") self._parent().show("close", mute=True) @@ -1885,6 +1941,8 @@ def __exit__(self, *args) -> None: self._parent().show("PNG", mute=True) self._parent().gfile(self._pixel_res, mute=True) + self._parent().file_type_for_plots = self.previous_device + def __exit__(self, *args) -> None: self._parent()._log.debug("Exiting in 'WithInterativePlotting' mode") self._parent().show("close", mute=True) @@ -3039,6 +3097,10 @@ def run( # https://github.com/pyansys/pymapdl/issues/380 command = "/CLE,NOSTART" + # Tracking output device + if command[:4].upper() == "/SHO": + self._file_type_for_plots = command.split(",")[1].upper() + # Invalid commands silently ignored. cmd_ = command.split(",")[0].upper() if cmd_ in INVAL_COMMANDS_SILENT: diff --git a/src/ansys/mapdl/core/mapdl_grpc.py b/src/ansys/mapdl/core/mapdl_grpc.py index a2e073c382..767e1e0405 100644 --- a/src/ansys/mapdl/core/mapdl_grpc.py +++ b/src/ansys/mapdl/core/mapdl_grpc.py @@ -251,6 +251,11 @@ class MapdlGrpc(_MapdlCore): PyPIM. This instance will be deleted when calling :func:`Mapdl.exit `. + file_type_for_plots: ["PNG", "TIFF", "PNG", "VRML", "TERM"], Optional + Change the default file type for plots using ``/SHOW``, by + default it is ``PNG``. + + Examples -------- Connect to an instance of MAPDL already running on locally on the @@ -867,6 +872,8 @@ def _run_at_connect(self): with self.run_as_routine("POST26"): self.numvar(200, mute=True) + self.show(self._file_type_for_plots) + def _reset_cache(self): """Reset cached items.""" if self._mesh_rep is not None: diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 6f1ec7decc..f58a75ed46 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -593,3 +593,25 @@ def filtering(file_name): # cleaning os.remove(last_png) + + +def test_file_type_for_plots(mapdl): + assert mapdl.file_type_for_plots in ["PNG", "TIFF", "PNG", "VRML", "TERM", "CLOSE"] + + mapdl.file_type_for_plots = "TIFF" + assert mapdl.file_type_for_plots == "TIFF" + + with pytest.raises(ValueError): + mapdl.file_type_for_plots = "asdf" + + mapdl.default_plot_file_type = "PNG" + n_files_ending_png_before = len( + [each for each in mapdl.list_files() if each.endswith(".png")] + ) + + mapdl.eplot(vtk=False) + n_files_ending_png_after = len( + [each for each in mapdl.list_files() if each.endswith(".png")] + ) + + assert n_files_ending_png_before + 1 == n_files_ending_png_after