Operations development#

SimPhoNy operations are actions (written in Python) that can be executed on demand on any ontology individual belonging to the ontology class they are defined for.

Tip

File uploads and downloads in SimPhoNy are an example of SimPhoNy operations. Head to the assertional knowledge section to see them in action.

SimPhoNy operations are distributed as (or as part of) Python packages. Developing operations for an ontology class is fairly simple. To do so, import the Operations abstract class from the simphony_osp.development module, and create an implementation by subclassing it.

Then, define an iri attribute having as value the IRI of the ontology class that the operation should be associated to. Every public method (not starting with an underscore) defined on the implementation is automatically detected and assigned as an operation to said ontology class. The ontology individual object on which the operation is called is available as the private attribute _individual on every instance of the implementation. For a specific ontology individual, the implementation gets instantiated the first time that any operation defined on it is called by the user.

Finally, define an entry point (or many if implementing operations for several ontology classes) under the simphony_osp.ontology.operations group that points to your implementation of the Operations abstract class.

An example implementation of an operation that takes advantage of geopy to compute the distance between two points on Earth defined using the WGS84 Geo Positioning vocabulary is shown below.

"""Operations for classes from the WGS84 Geo Positioning vocabulary."""

from geopy import distance
from simphony_osp.namespaces import wgs84_pos
from simphony_osp.ontology import OntologyIndividual
from simphony_osp.ontology.operations import Operations


class Wgs84Pos(Operations):
    """Operations for the Point ontology class."""

    iri = wgs84_pos.Point.iri

    def distance(self, other: OntologyIndividual) -> float:
        """Compute the distance between two points on Earth.

        Args:
            other: Another point with respect to which the distance will be computed.

        Returns:
            The distance between this point and the given one in km.
        """
        lat_self = float(self._individual[wgs84_pos.latitude].one())
        long_self = float(self._individual[wgs84_pos.longitude].one())
        lat_other = float(other[wgs84_pos.latitude].one())
        long_other = float(other[wgs84_pos.longitude].one())
        return distance.geodesic(
            (lat_self, long_self),
            (lat_other, long_other),
            ellipsoid="WGS-84"
        ).km

Note

Remember that the implementation above is still not enough for the operation to work: the corresponding entry point for Wgs84Pos must have been defined and the wgs84_pos vocabulary needs to be installed using pico.

The operation can be used as follows.

[1]:
from simphony_osp.namespaces import wgs84_pos

location_freiburg = wgs84_pos.Point()
location_freiburg[wgs84_pos.latitude] = 47.997791
location_freiburg[wgs84_pos.longitude] = 7.842609

location_paris = wgs84_pos.Point()
location_paris[wgs84_pos.latitude] = 48.85333
location_paris[wgs84_pos.longitude] = 2.34885

location_freiburg.operations.distance(location_paris)
[1]:
417.4695920611045