diff --git a/examples/07-python-operators/00-wrapping_numpy_capabilities.py b/examples/07-python-operators/00-wrapping_numpy_capabilities.py deleted file mode 100644 index 3f272f8b79..0000000000 --- a/examples/07-python-operators/00-wrapping_numpy_capabilities.py +++ /dev/null @@ -1,105 +0,0 @@ -""" -.. _ref_wrapping_numpy_capabilities: - -Create a basic operator plugin -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This example shows how to create a basic operator plugin, which is for -a single custom operator. This custom operator, ``easy_statistics``, -computes simple statistics quantities on a scalar field with the help of -the ``numpy`` package. - -The objective of this simple example is to show how routines for DPF can -be wrapped in Python plugins. -""" - -############################################################################### -# Create the operator -# ------------------- -# Creating a basic operator plugin consists of writing a single Python script. -# An operator implementation derives from the -# :class:`ansys.dpf.core.custom_operator.CustomOperatorBase` class -# and a call to the :py:func:`ansys.dpf.core.custom_operator.record_operator` -# method. -# -# The ``easy_statistics`` operator takes a field as an input and returns -# the first quartile, the median, the third quartile, and the variance. -# The Python operator and its recording are available in the -# ``easy_statistics.py`` file. -# -# Download and display the Python script. - -from ansys.dpf.core import examples - -GITHUB_SOURCE_URL = "https://github.com/pyansys/pydpf-core/" \ - "raw/examples/first_python_plugins/python_plugins" -EXAMPLE_FILE = GITHUB_SOURCE_URL + "/easy_statistics.py" -operator_file_path = examples.downloads._retrieve_file( - EXAMPLE_FILE, "easy_statistics.py", "python_plugins" -) - -with open(operator_file_path, "r") as f: - for line in f.readlines(): - print('\t\t\t' + line) - -############################################################################### -# Load the plugin -# --------------- -# You use the :py:func:`ansys.dpf.core.core.load_library` method to load the -# plugin. - -# - The first argument is the path to the directory where the plugin -# is located. -# - The second argument is ``py_`` plus the name of the Python script. -# - The third argument is the name of the function used to record operators. -# - -import os -from ansys.dpf import core as dpf -from ansys.dpf.core import examples - -# Python plugins are not supported in process. -dpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer) - -operator_server_file_path = dpf.upload_file_in_tmp_folder(operator_file_path) -dpf.load_library(os.path.dirname(operator_server_file_path), "py_easy_statistics", "load_operators") - -############################################################################### -# Instantiate the operator. - -new_operator = dpf.Operator("easy_statistics") - -############################################################################### -# Connect a workflow -# ------------------ -# Connect a workflow that computes the norm of the displacement to the -# ``easy_statistics`` operator. Methods of the ``easy_statistics`` class -# are dynamically added because specifications for the operator are -# defined in the plugin. - -# %% -# .. graphviz:: -# -# digraph foo { -# graph [pad="0.5", nodesep="0.3", ranksep="0.3"] -# node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; -# rankdir=LR; -# splines=line; -# ds [label="ds", shape=box, style=filled, fillcolor=cadetblue2]; -# ds -> displacement [style=dashed]; -# displacement -> norm; -# norm -> easy_statistics; -# } - -############################################################################### -# Use the operator -# ---------------- - -ds = dpf.DataSources(dpf.upload_file_in_tmp_folder(examples.static_rst)) -displacement = dpf.operators.result.displacement(data_sources=ds) -norm = dpf.operators.math.norm(displacement) -new_operator.inputs.connect(norm) - -print("first quartile is", new_operator.outputs.first_quartile()) -print("median is", new_operator.outputs.median()) -print("third quartile is", new_operator.outputs.third_quartile()) -print("variance is", new_operator.outputs.variance()) diff --git a/examples/07-python-operators/01-package_python_operators.py b/examples/07-python-operators/01-package_python_operators.py deleted file mode 100644 index 5d145e3795..0000000000 --- a/examples/07-python-operators/01-package_python_operators.py +++ /dev/null @@ -1,124 +0,0 @@ -""" -.. _ref_python_plugin_package: - -Create a plug-in package with multiple operators -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This example shows how to create a plug-in package with multiple operators. -The benefits of writing packages rather than simple scripts are: - -- **Componentization:** You can split the code into several Python modules or files. -- **Distribution:** You can use standard Python tools to upload and download packages. -- **Documentation:** You can add README files, documentation, tests, and examples to the package. - -For this example, the plug-in package contains two different operators: - -- One that returns all scoping ID having data higher than the average -- One that returns all scoping IDs having data lower than the average - -""" - -############################################################################### -# Create the plug-in package -# -------------------------- -# Each operator implementation derives from the -# :class:`ansys.dpf.core.custom_operator.CustomOperatorBase` class -# and a call to the :py:func:`ansys.dpf.core.custom_operator.record_operator` -# method, which records the operators of the plug-in package. -# -# Download the ``average_filter_plugin`` plug-in package that has already been -# created for you. - -import os -from ansys.dpf.core import examples - -print('\033[1m average_filter_plugin') -file_list = ["__init__.py", "operators.py", "operators_loader.py", "common.py"] -plugin_folder = None -GITHUB_SOURCE_URL = "https://github.com/pyansys/pydpf-core/raw/" \ - "examples/first_python_plugins/python_plugins/average_filter_plugin" - -for file in file_list: - EXAMPLE_FILE = GITHUB_SOURCE_URL + "/average_filter_plugin/" + file - operator_file_path = examples.downloads._retrieve_file( - EXAMPLE_FILE, file, "python_plugins/average_filter_plugin" - ) - plugin_folder = os.path.dirname(operator_file_path) - print(f'\033[1m {file}:\n \033[0m') - with open(operator_file_path, "r") as f: - for line in f.readlines(): - print('\t\t\t' + line) - print("\n\n") - - -############################################################################### -# Load the plug-in package -# ------------------------ -# You use the function :py:func:`ansys.dpf.core.core.load_library` to load the -# plug-in package. -# -# - The first argument is the path to the directory where the plug-in package -# is located. -# - The second argument is ``py_`` plus any name identifying the plug-in package. -# - The third argument is the name of the function exposed in the ``__init__ file`` -# for the plug-in package that is used to record operators. -# - -import os -from ansys.dpf import core as dpf -from ansys.dpf.core import examples - -# Python plugins are not supported in process. -dpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer) - -tmp = dpf.make_tmp_dir_server() -dpf.upload_files_in_folder( - dpf.path_utilities.join(tmp, "average_filter_plugin"), - plugin_folder -) -dpf.load_library( - os.path.join(dpf.path_utilities.join(tmp, "average_filter_plugin")), - "py_average_filter", - "load_operators") - -############################################################################### -# Instantiate the operator. - -new_operator = dpf.Operator("ids_with_data_lower_than_average") - -############################################################################### -# Connect a workflow -# ------------------ -# Connect a workflow that computes the norm of the displacement -# to the ``ids_with_data_lower_than_average`` operator. -# Methods of the ``ids_with_data_lower_than_average`` class are dynamically -# added because specifications for the operator are defined in the plug-in -# package. - -# %% -# .. graphviz:: -# -# digraph foo { -# graph [pad="0.5", nodesep="0.3", ranksep="0.3"] -# node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; -# rankdir=LR; -# splines=line; -# ds [label="ds", shape=box, style=filled, fillcolor=cadetblue2]; -# ds -> displacement [style=dashed]; -# displacement -> norm; -# norm -> ids_with_data_lower_than_average; -# } - -############################################################################### -# Use the operator -# ---------------- - -ds = dpf.DataSources(dpf.upload_file_in_tmp_folder(examples.static_rst)) -displacement = dpf.operators.result.displacement(data_sources=ds) -norm = dpf.operators.math.norm(displacement) -new_operator.inputs.connect(norm) - - -new_scoping = new_operator.outputs.scoping() -print("scoping in was:", norm.outputs.field().scoping) -print("----------------------------------------------") -print("scoping out is:", new_scoping) diff --git a/examples/07-python-operators/02-python_operators_with_dependencies.py b/examples/07-python-operators/02-python_operators_with_dependencies.py deleted file mode 100644 index 09a2f62df8..0000000000 --- a/examples/07-python-operators/02-python_operators_with_dependencies.py +++ /dev/null @@ -1,233 +0,0 @@ -""" -.. _ref_python_operators_with_deps: - -Create a plug-in package that has third-party dependencies -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This example shows how to create a Python plug-in package with -third-party dependencies. You should be familiar with these -examples before proceeding with this more advanced one: - -- :ref:`ref_wrapping_numpy_capabilities` -- :ref:`ref_python_plugin_package` - -This plug-in contains an operator whose implementation depends on a -third-party Python module named `gltf `_. -This operator takes a path, a mesh, and a 3D vector field as inputs -and then exports the mesh and the norm of the 3D vector field to a GLTF -file at the given path. -""" - -############################################################################### -# Create the plug-in package -# -------------------------- -# Each operator implementation derives from the -# :class:`ansys.dpf.core.custom_operator.CustomOperatorBase` class -# and a call to the :py:func:`ansys.dpf.core.custom_operator.record_operator` -# method, which records the operators of the plug-in package. -# -# Download the ```gltf_plugin`` plug-in package that has already been -# created for you. - -import os -from ansys.dpf.core import examples - -print('\033[1m gltf_plugin') -file_list = ["gltf_plugin/__init__.py", "gltf_plugin/operators.py", - "gltf_plugin/operators_loader.py", "gltf_plugin/requirements.txt", - "gltf_plugin/gltf_export.py", "gltf_plugin/texture.png", "gltf_plugin.xml" - ] -plugin_path = None -GITHUB_SOURCE_URL = "https://github.com/pyansys/pydpf-core/raw/" \ - "" \ - "examples/first_python_plugins/python_plugins" - -for file in file_list: - EXAMPLE_FILE = GITHUB_SOURCE_URL + "/gltf_plugin/" + file - operator_file_path = examples.downloads._retrieve_file( - EXAMPLE_FILE, file, os.path.join("python_plugins", os.path.dirname(file))) - - print(f'\033[1m {file}\n \033[0m') - if (os.path.splitext(file)[1] == ".py" or os.path.splitext(file)[1] == ".xml") \ - and file != "gltf_plugin/gltf_export.py": - with open(operator_file_path, "r") as f: - for line in f.readlines(): - print('\t\t\t' + line) - print("\n\n") - if plugin_path is None: - plugin_path = os.path.dirname(operator_file_path) - -# %% -# To add third-party modules as dependencies to a plug-in package, you must -# create and reference a folder or ZIP file with the sites of the dependencies -# in an XML file located next to the folder for the plug-in package. The XML -# file must have the same name as the plug-in package plus an ``.xml`` extension. -# -# When the :py:func:`ansys.dpf.core.core.load_library` method is called, -# DPF-Core uses the ``site`` Python module to add custom to the path -# for the Python interpreter. -# -# To create these custom sites, requirements of the plug-in package should be -# installed in a Python virtual environment, the site-packages -# (with unnecessary folders removed) should be compressed to a ZIP file and -# placed with the plugin. The path to this ZIP file should be referenced in -# the XML as shown in the preceding code. -# -# To simplify this step, you can add a requirements file in the plug-in package: -# -print(f'\033[1m gltf_plugin/requirements.txt: \n \033[0m') -with open(os.path.join(plugin_path, "requirements.txt"), "r") as f: - for line in f.readlines(): - print('\t\t\t' + line) - - -# %% -# Download the script for your operating system. -# -# - For Windows, download this -# :download:`PowerShell script `. -# - For Linux, download this -# :download:`Shell script `. -# -# Run the downloaded script with the mandatory arguments: -# -# - ``-pluginpath``: Path to the folder with the plug-in package. -# - ``-zippath``: Path and name for the ZIP file. -# -# Optional arguments are: -# -# - ``-pythonexe``: Path to a Python executable of your choice. -# - ``-tempfolder``: Path to a temporary folder to work in. The default is the environment variable -# ``TEMP`` on Windows and ``/tmp/`` on Linux. -# -# Run the command for your operating system. -# -# - From Windows PowerShell, run:: -# -# create_sites_for_python_operators.ps1 -pluginpath /path/to/plugin -zippath /path/to/plugin/assets/winx64.zip # noqa: E501 -# -# - From Linux Shell, run:: -# -# create_sites_for_python_operators.sh -pluginpath /path/to/plugin -zippath /path/to/plugin/assets/linx64.zip # noqa: E501 - - -if os.name == "nt" and \ - not os.path.exists(os.path.join(plugin_path, 'assets', 'gltf_sites_winx64.zip')): - CMD_FILE_URL = GITHUB_SOURCE_URL + "/create_sites_for_python_operators.ps1" - cmd_file = examples.downloads._retrieve_file( - CMD_FILE_URL, "create_sites_for_python_operators.ps1", "python_plugins") - run_cmd = f"powershell {cmd_file}" - args = f" -pluginpath \"{plugin_path}\" " \ - f"-zippath {os.path.join(plugin_path, 'assets', 'gltf_sites_winx64.zip')}" - print(run_cmd + args) - import subprocess - process = subprocess.run(run_cmd + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - if process.stderr: - raise RuntimeError( - "Installing pygltf in a virtual environment failed with error:\n" - + process.stderr.decode()) - else: - print("Installing pygltf in a virtual environment succeeded") -elif os.name == "posix" and \ - not os.path.exists(os.path.join(plugin_path, 'assets', 'gltf_sites_linx64.zip')): - CMD_FILE_URL = GITHUB_SOURCE_URL + "/create_sites_for_python_operators.sh" - cmd_file = examples.downloads._retrieve_file( - CMD_FILE_URL, "create_sites_for_python_operators.ps1", "python_plugins" - ) - run_cmd = f"{cmd_file}" - args = f" -pluginpath \"{plugin_path}\" " \ - f"-zippath \"{os.path.join(plugin_path, 'assets', 'gltf_sites_linx64.zip')}\"" - print(run_cmd + args) - os.system(f"chmod u=rwx,o=x {cmd_file}") - os.system(run_cmd + args) - print("\nInstalling pygltf in a virtual environment succeeded") - -############################################################################### -# Load the plug-in package -# ------------------------ -# You use the function :py:func:`ansys.dpf.core.core.load_library` to load the -# plug-in package. -# -# - The first argument is the path to the directory where the plug-in package -# is located. -# - The second argument is ``py_`` plus any name identifying the plug-in package. -# - The third argument is the name of the function exposed in the ``__init__ file`` -# for the plug-in package that is used to record operators. - -from ansys.dpf import core as dpf -from ansys.dpf.core import examples - -# Python plugins are not supported in process. -dpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer) - -tmp = dpf.make_tmp_dir_server() -dpf.upload_files_in_folder( - dpf.path_utilities.join(tmp, "plugins", "gltf_plugin"), - plugin_path -) -dpf.upload_file( - plugin_path + ".xml", - dpf.path_utilities.join(tmp, "plugins", "gltf_plugin.xml") -) - -dpf.load_library( - dpf.path_utilities.join(tmp, "plugins", "gltf_plugin"), - "py_dpf_gltf", - "load_operators") - -############################################################################### -# Instantiate the operator. - -new_operator = dpf.Operator("gltf_export") - -############################################################################### -# This new ``gltf_export`` operator requires the following as inputs: a triangle -# surface mesh, a displacement field on this surface mesh, and a path to export -# the GLTF file to. -# -# To demonstrate this new operator, a :class:`ansys.dpf.core.model.Model` class -# is created on a simple file and the -# :class:`ansys.dpf.core.operators.mesh.tri_mesh_skin` operator is used -# to extract the surface of the mesh in triangle elements. - -# %% -# .. graphviz:: -# -# digraph workflow { -# graph [pad="0.5", nodesep="0.3", ranksep="0.3"] -# node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; -# rankdir=LR; -# splines=line; -# ds [label="data_sources", shape=box, style=filled, fillcolor=cadetblue2]; -# ds -> mesh_provider [style=dashed]; -# mesh_provider -> skin_mesh [splines=ortho]; -# ds -> displacement [style=dashed]; -# skin_mesh -> displacement [splines=ortho]; -# skin_mesh -> gltf_export [splines=ortho]; -# displacement -> gltf_export [splines=ortho]; -# } - -############################################################################### -# Use the custom operator -# ----------------------- - -import os - -model = dpf.Model(dpf.upload_file_in_tmp_folder(examples.static_rst)) - -mesh = model.metadata.meshed_region -skin_mesh = dpf.operators.mesh.tri_mesh_skin(mesh=mesh) - -displacement = model.results.displacement() -displacement.inputs.mesh_scoping(skin_mesh) -displacement.inputs.mesh(skin_mesh) -new_operator.inputs.path(os.path.join(tmp, "out")) -new_operator.inputs.mesh(skin_mesh) -new_operator.inputs.field(displacement.outputs.fields_container()[0]) -new_operator.run() - -print("operator ran successfully") - -dpf.download_file(os.path.join(tmp, "out.glb"), os.path.join(os.getcwd(), "out.glb")) - -# %% -# You can download :download:`output ` from the ``gltf`` operator.