Skip to content

Commit

Permalink
Merge pull request #697 from oda-hub/extra-metadata-with-label
Browse files Browse the repository at this point in the history
extra metadata dict, initialized inside `from_owl_uri`
  • Loading branch information
burnout87 authored Aug 16, 2024
2 parents 6f20aa8 + 453b374 commit 6483081
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 34 deletions.
98 changes: 65 additions & 33 deletions cdci_data_analysis/analysis/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ def __init__(self,
allowed_values=None,
min_value = None,
max_value = None,

extra_metadata=None,
**kwargs
):

Expand Down Expand Up @@ -261,6 +263,7 @@ def __init__(self,
self._max_value = max_value
self._bound_units = self.units
self.value = value
self.extra_metadata = extra_metadata


self._arg_list = [self.name]
Expand Down Expand Up @@ -463,6 +466,8 @@ def reprJSONifiable(self):
restrictions['schema'] = self.schema
if restrictions:
reprjson[0]['restrictions'] = restrictions
if getattr(self, 'extra_metadata', None) is not None:
reprjson[0]['extra_metadata'] = self.extra_metadata
if getattr(self, 'owl_uris', None):
if isinstance(self.owl_uris, str):
reprjson[0]['owl_uri'] = [ self.owl_uris ]
Expand All @@ -487,14 +492,16 @@ def from_owl_uri(cls,
**kwargs):
from oda_api.ontology_helper import Ontology

metadata_keys = ['label', 'description', 'group']

if ontology_path is not None and ontology_object is not None:
raise RuntimeError("Both ontology_path and ontology_object parameters are set.")
elif ontology_path is None and ontology_object is None:
logger.warning('Ontology path/object not set in Parameter.from_owl_uri(). '
'Trying to find parameter which have %s directly set. '
'extra_ttl will be ignored ', owl_uri)
parameter_hierarchy = [ owl_uri ]
par_format = par_unit = allowed_values = min_value = max_value = None
par_format = par_unit = allowed_values = min_value = max_value = label = description = group = None
else:
if ontology_path is not None:
if isinstance(ontology_path, (str, os.PathLike)):
Expand All @@ -514,13 +521,18 @@ def from_owl_uri(cls,
par_unit = onto.get_parameter_unit(owl_uri)
min_value, max_value = onto.get_limits(owl_uri)
allowed_values = onto.get_allowed_values(owl_uri)

label = onto.get_direct_annotation(owl_uri, "label")
description = onto.get_direct_annotation(owl_uri, "description")
group = onto.get_direct_annotation(owl_uri, "group")

for owl_superclass_uri in parameter_hierarchy:
for python_subclass in subclasses_recursive(cls):
logger.debug("searching for class with owl_uri=%s, found %s", owl_superclass_uri, python_subclass)
if python_subclass.matches_owl_uri(owl_superclass_uri):
logger.info("will construct %s by owl_uri %s", python_subclass, owl_superclass_uri)
call_kwargs = {}
call_kwargs = {
'extra_metadata': {key: val for key, val in zip(metadata_keys, [label, description, group]) if
val is not None}}
call_signature = signature(python_subclass)
var_kw_signature = call_parameter.VAR_KEYWORD in [x.kind for x in call_signature.parameters.values()]

Expand Down Expand Up @@ -566,15 +578,16 @@ def from_owl_uri(cls,
class String(Parameter):
owl_uris = ("http://www.w3.org/2001/XMLSchema#str", "http://odahub.io/ontology#String")

def __init__(self, value=None, name_format='str', name=None, allowed_values = None):
def __init__(self, value=None, name_format='str', name=None, allowed_values = None, extra_metadata = None):

_allowed_units = ['str']
super().__init__(value=value,
units=name_format,
check_value=self.check_name_value,
name=name,
allowed_units=_allowed_units,
allowed_values=allowed_values)
allowed_values=allowed_values,
extra_metadata=extra_metadata)

@staticmethod
def check_name_value(value, units=None, name=None, par_format=None):
Expand Down Expand Up @@ -671,7 +684,8 @@ def __init__(self,
check_value=None,
min_value= None,
max_value = None,
units_name = None):
units_name = None,
extra_metadata=None):

super().__init__(value=value,
units=units,
Expand All @@ -684,7 +698,8 @@ def __init__(self,
allowed_units=allowed_units,
min_value=min_value,
max_value=max_value,
units_name = units_name)
units_name = units_name,
extra_metadata=extra_metadata)



Expand All @@ -700,7 +715,8 @@ def __init__(self,
max_value = None,
units_name = None,
default_units = None,
allowed_units = None):
allowed_units = None,
extra_metadata=None):

super().__init__(value=value,
units=units,
Expand All @@ -712,7 +728,8 @@ def __init__(self,
allowed_units=allowed_units,
min_value = min_value,
max_value = max_value,
units_name = units_name)
units_name = units_name,
extra_metadata=extra_metadata)

def set_par_internal_value(self, value):
if isinstance(value, float):
Expand All @@ -725,13 +742,14 @@ class Time(Parameter):
owl_uris = ("http://odahub.io/ontology#TimeInstant",)
format_kw = 'T_format'

def __init__(self, value=None, T_format='isot', name=None, Time_format_name='T_format', par_default_format='isot'):
def __init__(self, value=None, T_format='isot', name=None, Time_format_name='T_format', par_default_format='isot', extra_metadata=None):

super().__init__(value=value,
par_format=T_format,
par_format_name=Time_format_name,
par_default_format=par_default_format,
name=name)
name=name,
extra_metadata=extra_metadata)

def get_default_value(self):
return self.get_value_in_default_format()
Expand Down Expand Up @@ -776,15 +794,16 @@ class TimeDelta(Time):
owl_uris = ("http://odahub.io/ontology#TimeDeltaIsDeprecated",)
format_kw = 'delta_T_format'

def __init__(self, value=None, delta_T_format='sec', name=None, delta_T_format_name=None, par_default_format='sec'):
def __init__(self, value=None, delta_T_format='sec', name=None, delta_T_format_name=None, par_default_format='sec', extra_metadata=None):
logging.warning(('TimeDelta parameter is deprecated. '
'It derives from Time, which is confusing. '
'Consider using TimeInterval parameter.'))
super().__init__(value=value,
T_format=delta_T_format,
Time_format_name=delta_T_format_name,
par_default_format=par_default_format,
name=name)
name=name,
extra_metadata=extra_metadata)

def get_value_in_format(self, units):
return getattr(self._astropy_time_delta, units)
Expand Down Expand Up @@ -816,7 +835,8 @@ def __init__(self,
default_units='s',
min_value=None,
max_value=None,
units_name = None):
units_name = None,
extra_metadata=None):

_allowed_units = ['s', 'minute', 'hour', 'day', 'year']
super().__init__(value=value,
Expand All @@ -826,13 +846,14 @@ def __init__(self,
min_value=min_value,
max_value=max_value,
units_name = units_name,
allowed_units=_allowed_units)
allowed_units=_allowed_units,
extra_metadata=extra_metadata)

class InputProdList(Parameter):
owl_uris = ('http://odahub.io/ontology#InputProdList',)

# TODO removal of the leading underscore cannot be done for compatibility with the plugins
def __init__(self, value=None, _format='names_list', name: str = None):
def __init__(self, value=None, _format='names_list', name: str = None, extra_metadata=None):
_allowed_units = ['names_list']

if value is None:
Expand All @@ -842,7 +863,8 @@ def __init__(self, value=None, _format='names_list', name: str = None):
par_format=_format,
check_value=self.check_list_value,
name=name,
allowed_units=_allowed_units)
allowed_units=_allowed_units,
extra_metadata=extra_metadata)

@staticmethod
def _split(str_list):
Expand Down Expand Up @@ -903,7 +925,8 @@ def __init__(self,
name=None,
min_value = None,
max_value = None,
units_name = None):
units_name = None,
extra_metadata=None):

super().__init__(value=value,
units=units,
Expand All @@ -913,7 +936,8 @@ def __init__(self,
allowed_units=None,
min_value = min_value,
max_value = max_value,
units_name = units_name)
units_name = units_name,
extra_metadata=extra_metadata)


class Energy(Float):
Expand All @@ -928,7 +952,8 @@ def __init__(self,
check_value=None,
min_value = None,
max_value = None,
units_name = None):
units_name = None,
extra_metadata=None):

_allowed_units = ['keV', 'eV', 'MeV', 'GeV', 'TeV', 'Hz', 'MHz', 'GHz']

Expand All @@ -940,7 +965,8 @@ def __init__(self,
allowed_units=_allowed_units,
min_value = min_value,
max_value = max_value,
units_name = units_name)
units_name = units_name,
extra_metadata=extra_metadata)

class SpectralBoundary(Energy):
def __init__(self,
Expand All @@ -951,7 +977,8 @@ def __init__(self,
check_value=None,
min_value=None,
max_value=None,
units_name=None):
units_name=None,
extra_metadata=None):

# retro-compatibility with integral plugin
if check_value is None:
Expand All @@ -964,7 +991,8 @@ def __init__(self,
check_value=check_value,
min_value=min_value,
max_value=max_value,
units_name=units_name)
units_name=units_name,
extra_metadata=extra_metadata)

@staticmethod
def check_energy_value(value, units, name):
Expand All @@ -973,7 +1001,7 @@ def check_energy_value(value, units, name):

class DetectionThreshold(Float):
owl_uris = ("http://odahub.io/ontology#DetectionThreshold",)
def __init__(self, value=None, units='sigma', name=None, min_value = None, max_value = None):
def __init__(self, value=None, units='sigma', name=None, min_value = None, max_value = None, extra_metadata=None):
_allowed_units = ['sigma']

super().__init__(value=value,
Expand All @@ -982,7 +1010,8 @@ def __init__(self, value=None, units='sigma', name=None, min_value = None, max_v
name=name,
allowed_units=_allowed_units,
min_value = min_value,
max_value = max_value)
max_value = max_value,
extra_metadata=extra_metadata)

# 'sigma' is not astropy unit, so need to override methods
def get_value_in_units(self, units):
Expand All @@ -995,24 +1024,26 @@ def set_par_internal_value(self, value):
self._value = None

class UserCatalog(Parameter):
def __init__(self, value=None, name_format='str', name=None):
def __init__(self, value=None, name_format='str', name=None, extra_metadata=None):
_allowed_units = ['str']
super().__init__(value=value,
par_format=name_format,
check_value=None,
name=name,
allowed_units=_allowed_units)
allowed_units=_allowed_units,
extra_metadata=extra_metadata)

class Boolean(Parameter):
owl_uris = ('http://www.w3.org/2001/XMLSchema#bool',"http://odahub.io/ontology#Boolean")

def __init__(self, value=None, name=None):
def __init__(self, value=None, name=None, extra_metadata=None):

self._true_rep = ['True', 'true', 'yes', '1', True]
self._false_rep = ['False', 'false', 'no', '0', False]
super().__init__(value=value,
name=name,
allowed_values=self._true_rep+self._false_rep
allowed_values=self._true_rep+self._false_rep,
extra_metadata = extra_metadata
)

@property
Expand All @@ -1031,15 +1062,16 @@ def value(self, v):
class StructuredParameter(Parameter):
owl_uris = ("http://odahub.io/ontology#StructuredParameter")

def __init__(self, value=None, name=None, schema={"oneOf": [{"type": "object"}, {"type": "array"}]}):
def __init__(self, value=None, name=None, schema={"oneOf": [{"type": "object"}, {"type": "array"}]}, extra_metadata=None):

self.schema = schema

if self.schema is None:
logger.warning("Parameter %s: Schema is not defined, will allow any structure.", name)

super().__init__(value=value,
name=name)
name=name,
extra_metadata=extra_metadata)

def check_schema(self):
if self.schema is not None:
Expand All @@ -1065,7 +1097,7 @@ def get_default_value(self):
class PhosphorosFiltersTable(StructuredParameter):
owl_uris = ('http://odahub.io/ontology#PhosphorosFiltersTable')

def __init__(self, value=None, name=None):
def __init__(self, value=None, name=None, extra_metadata=None):

# TODO: either list or the whole schema may be loaded from the external file, purely based on URI.
# If there is no additional check, this would allow to avoid even having the class.
Expand Down Expand Up @@ -1102,7 +1134,7 @@ def __init__(self, value=None, name=None):
"required": ["filter", "flux", "flux_error"]
}

super().__init__(value=value, name=name, schema=schema)
super().__init__(value=value, name=name, schema=schema, extra_metadata=extra_metadata)

def additional_check(self):
assert len(self._value['filter']) == len(self._value['flux']) == len(self._value['flux_error'])
Expand Down
3 changes: 2 additions & 1 deletion tests/test_parameters.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
import os

from cdci_data_analysis.analysis.instrument import Instrument
from cdci_data_analysis.analysis.queries import (
Expand Down Expand Up @@ -422,7 +423,7 @@ def test_boolean_parameter(inval, iswrong, expected):
True, 100, Energy),
])
def test_parameter_class_from_owl_uri(uri, extra_ttl, use_ontology, value, param_type):
ontology_path = 'tests/oda-ontology.ttl' if use_ontology else None
ontology_path = os.path.join(os.path.dirname(__file__), 'oda-ontology.ttl') if use_ontology else None
param = Parameter.from_owl_uri(uri,
value=value,
extra_ttl = extra_ttl,
Expand Down

0 comments on commit 6483081

Please sign in to comment.