… add an affix-function to a standard name table during runtime?

… add an affix-function to a standard name table during runtime?#

If you are using the standard name convention, you are familiar with transformation functions like “derivative_of_<SN1>wrt<SN2>” or “square_of_<SN>”.

Now, you want to add your custom transformation function without changing the package code. Say, you want to add the transformation “maximum_of_”, referring to the maximum value of your data.

Here is the current state, which fails as expected:

import h5rdmtoolbox as h5tbx
from h5rdmtoolbox.convention.standard_names.transformation import Transformation
from h5rdmtoolbox.convention.standard_names import StandardName

snt = h5tbx.convention.standard_names.StandardNameTable.from_zenodo(doi_or_recid=10428795)

# check if the problem really exists:
try:
    snt['maximum_of_pressure']
except h5tbx.errors.StandardNameError as e:
    print(e)
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 1
----> 1 import h5rdmtoolbox as h5tbx
      2 from h5rdmtoolbox.convention.standard_names.transformation import Transformation
      3 from h5rdmtoolbox.convention.standard_names import StandardName

File ~/checkouts/readthedocs.org/user_builds/h5rdmtoolbox/checkouts/v1.7.0/h5rdmtoolbox/__init__.py:129
    125     with File(src) as h5:
    126         return h5.dumps()
--> 129 from h5rdmtoolbox.wrapper.ld.hdf.file import get_ld as hdf_get_ld
    130 from h5rdmtoolbox.wrapper.ld.user.file import get_ld as user_get_ld
    133 def get_ld(
    134         hdf_filename: Union[str, pathlib.Path],
    135         structural: bool = True,
    136         semantic: bool = True,
    137         blank_node_iri_base: Optional[str] = None,
    138         **kwargs) -> rdflib.Graph:

File ~/checkouts/readthedocs.org/user_builds/h5rdmtoolbox/checkouts/v1.7.0/h5rdmtoolbox/wrapper/ld/__init__.py:1
----> 1 import ssnolib.ssno.standard_name
      2 from ontolutils.namespacelib import M4I
      3 from ontolutils.namespacelib import SCHEMA

ModuleNotFoundError: No module named 'ssnolib'

Implementing a new transformation function#

We need to do two things:

  1. write a function which takes a regex result and generates the new standard name

  2. init a Transformation object which performs the regex match

The respective regex pattern to the above is ^maximum_of_(.*)$.

The respective function is implemented in the following. It takes the result from a re.match() call and the standard name table object. The function then constructs a new standard name and returns it. Even if the regex match succeeded, it is still possible, that the function raises an error because the base standard_name may not exist.

def maximum_of(match, snt):
    # match is the result of `re.match(`^maximum_of_(.*)$, <user_input_value>)`
    groups = match.groups()
    assert len(groups) == 1
    sn = snt[groups[0]]
    new_description = f"Maximum of {sn.name}. {sn.description}"
    return StandardName(match.string, sn.units, new_description)

The actual transformation is managed by the class Transformation. It takes the above defined function and the respective regex pattern:

max_of = Transformation(r"^maximum_of_(.*)$", maximum_of)

We can already check if the pattern matching works:

max_of.match('maximum_static_pressure') is None
True
max_of.match('maximum_of_static_pressure') is None
False

Add it to an existing standard name table during runtime:#

snt.add_transformation(max_of)
snt['maximum_of_static_pressure']
    • units : Pa
    • description : Maximum of static_pressure. Static pressure refers to the force per unit area exerted by a fluid. Pressure is a scalar quantity.
snt.transformations[-1] == max_of
True