Source code for smif.convert.unit
"""Handles conversion between units used in the `SosModel`
"""
from pint import DimensionalityError, UndefinedUnitError, UnitRegistry # type: ignore
from smif.convert.adaptor import Adaptor
from smif.data_layer.data_handle import DataHandle
[docs]class UnitAdaptor(Adaptor):
"""Scalar conversion of units"""
def __init__(self, name):
self._register = UnitRegistry()
super().__init__(name)
[docs] def simulate(self, data_handle: DataHandle):
"""Register unit definitions in registry for model run"""
units = data_handle.read_unit_definitions()
for unit in units:
self._register.define(unit)
super().simulate(data_handle)
[docs] def convert(self, data_array, to_spec, coefficients):
data = data_array.data
from_spec = data_array.spec
try:
quantity = self._register.Quantity(data, from_spec.unit)
except UndefinedUnitError:
raise ValueError(
"Cannot convert from undefined unit {}".format(from_spec.unit)
)
try:
converted_quantity = quantity.to(to_spec.unit)
except UndefinedUnitError as ex:
raise ValueError(
"Cannot convert undefined unit {}".format(to_spec.unit)
) from ex
except DimensionalityError as ex:
msg = "Cannot convert unit from {} to {}"
raise ValueError(msg.format(from_spec.unit, to_spec.unit)) from ex
return converted_quantity.magnitude
[docs] def get_coefficients(self, data_handle, from_spec, to_spec):
# override with no-op - all the work is done in convert with scalar operations
pass
[docs] def generate_coefficients(self, from_spec, to_spec):
# override with no-op - all the work is done in convert with scalar operations
pass
[docs] def parse_unit(self, unit_string):
"""Parse a unit string (abbreviation or full) into a Unit object
Parameters
----------
unit : str
Returns
-------
quantity : :class:`pint.Unit`
"""
try:
unit = self._register.parse_units(unit_string)
except UndefinedUnitError:
self.logger.warning("Unrecognised unit: %s", unit_string)
unit = None
return unit