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.

Note

This example requires the Premium ServerContext. For more information, see Server context.

Create the operator#

Creating a basic operator plugin consists of writing a single Python script. An operator implementation derives from the ansys.dpf.core.custom_operator.CustomOperatorBase class and a call to the 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
from ansys.dpf import core as dpf


dpf.set_default_server_context(dpf.AvailableServerContexts.premium)

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)
import numpy as np

from ansys.dpf import core as dpf

from ansys.dpf.core.custom_operator import CustomOperatorBase, record_operator

from ansys.dpf.core.operator_specification import CustomSpecification, SpecificationProperties, \

    PinSpecification





class EasyStatistics(CustomOperatorBase):

    @property

    def name(self):

        return "easy_statistics"



    @property

    def specification(self) -> CustomSpecification:

        spec = CustomSpecification()

        spec.description = "Compute the first quartile, the median, the third quartile and the variance of a scalar Field with numpy"

        spec.inputs = {0: PinSpecification("field", [dpf.Field, dpf.FieldsContainer], "scalar Field on which the statistics quantities is computed.")}

        spec.outputs = {

            0: PinSpecification("first_quartile", [float]),

            1: PinSpecification("median", [float]),

            2: PinSpecification("third_quartile", [float]),

            3: PinSpecification("variance", [float]),

        }

        spec.properties = SpecificationProperties("easy statistics", "math")

        return spec



    def run(self):

        field = self.get_input(0, dpf.Field)

        if field is None:

            field = self.get_input(0, dpf.FieldsContainer)[0]

        # compute stats

        first_quartile_val = np.quantile(field.data, 0.25)

        median_val = np.quantile(field.data, 0.5)

        third_quartile_val = np.quantile(field.data, 0.75)

        variance_val = np.var(field.data)

        self.set_output(0, first_quartile_val)

        self.set_output(1, median_val)

        self.set_output(2, third_quartile_val)

        self.set_output(3, float(variance_val))

        self.set_succeeded()





def load_operators(*args):

    record_operator(EasyStatistics, *args)

Load the plugin#

You use the 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")
'py_easy_statistics successfully loaded'

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.

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.find_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())
first quartile is 0.0
median is 7.491665033689507e-09
third quartile is 1.4276663319275634e-08
variance is 3.054190175494998e-17

Total running time of the script: ( 0 minutes 3.939 seconds)

Gallery generated by Sphinx-Gallery