Source code for pyiem.datatypes
"""
Classes Representing various variables
"""
# pylint: disable=no-member
import numpy as np
from pyiem.exceptions import UnitsError
[docs]
class basetype:
"""Base Object for all our vars"""
def __init__(self, value, units):
"""constructor with value and units required"""
if units.upper() not in self.known_units:
raise UnitsError(
f"unrecognized temperature unit: {units} "
f"known: {self.known_units}"
)
self._units = units.upper()
if isinstance(value, list):
self._value = np.ma.array(value, mask=[v is None for v in value])
else:
self._value = value
[docs]
def get_units(self):
"""Returns the units for this current datatype
Returns:
(str): the unit of this datatype
"""
return self._units
[docs]
class mixingratio(basetype):
"""Mixing Ratio."""
known_units = ["KG/KG"]
[docs]
def value(self, units):
"""Convert the value into the provided units"""
if units.upper() not in mixingratio.known_units:
raise UnitsError(
f"unrecognized mixingratio unit: {units} "
f"known: {mixingratio.known_units}"
)
return self._value
[docs]
class distance(basetype):
"""Distance"""
known_units = ["SM", "MI", "M", "KM", "FT", "MM", "IN", "CM"]
[docs]
def value(self, units):
"""Convert to a value in the given units"""
units = units.upper()
if units not in distance.known_units:
raise UnitsError(
f"unrecognized distance unit: {units} "
f"known: {distance.known_units}"
)
if units == self._units:
return self._value
# MKS
if self._units in ["SM", "MI"]:
meters = self._value * 1609.344
elif self._units == "FT":
meters = self._value / 3.28084
elif self._units == "KM":
meters = self._value * 1000.0
elif self._units == "MM":
meters = self._value / 1000.0
elif self._units == "CM":
meters = self._value / 100.0
elif self._units == "IN":
meters = self._value * 0.0254
else:
meters = self._value
# Output
if units in ["SM", "MI"]:
return meters / 1609.344
if units == "FT":
return meters * 3.28084
if units == "KM":
return meters / 1000.0
if units == "MM":
return meters * 1000.0
if units == "CM":
return meters * 100.0
if units == "IN":
return meters / 0.0254
return meters
[docs]
class precipitation(basetype):
"""Precipitation"""
known_units = ["IN", "CM", "MM"]
[docs]
def value(self, units):
"""Convert to a value in the given units"""
units = units.upper()
if units not in precipitation.known_units:
raise UnitsError(
f"unrecognized precipitation unit: {units} "
"known: {precipitation.known_units}"
)
if units == self._units:
return self._value
# MKS
if self._units == "IN":
mm = self._value * 25.4
elif self._units == "CM":
mm = self._value * 10.0
else:
mm = self._value
# Convert
if units == "MM":
return mm
if units == "CM":
return mm * 10.0
return mm / 25.4
[docs]
class speed(basetype):
"""Speed"""
known_units = ["KT", "MPH", "MPS", "KMH", "KTS"]
[docs]
def value(self, units=None):
"""Convert to a value in the given units"""
if units is None:
units = self._units
units = units.upper()
if units not in speed.known_units:
raise UnitsError(
f"unrecognized speed unit: {units} known: {speed.known_units}"
)
if units == self._units:
return self._value
# MKS
if self._units == "KMH":
mps_value = self._value / 3.6
elif self._units in ["KT", "KTS"]:
mps_value = self._value * 0.514444
elif self._units == "MPH":
mps_value = self._value * 0.447000
else:
mps_value = self._value
if units == "KMH":
return mps_value * 3.6
if units in ["KT", "KTS"]:
return mps_value / 0.514444
if units == "MPH":
return mps_value / 0.447000
return mps_value
[docs]
class humidity(basetype):
"""Humidity, this is not as straight forward as the others"""
known_units = ["%"]
[docs]
def value(self, units):
"""Convert to a value in the given units"""
if units.upper() not in humidity.known_units:
raise UnitsError(
f"unrecognized humidity unit: {units} "
f"known: {humidity.known_units}"
)
return self._value
[docs]
class direction(basetype):
"""Direction from North"""
known_units = ["DEG", "RAD"]
[docs]
def value(self, units):
"""Convert to a value in the given units"""
if units.upper() not in direction.known_units:
raise UnitsError(
f"unrecognized direction unit: {units} "
f"known: {direction.known_units}"
)
if units.upper() == self._units:
return self._value
if self._units == "DEG" and units.upper() == "RAD":
return self._value * 3.1415926535897931 / 180.0
return self._value * 180 / 3.1415926535897931
[docs]
class pressure(basetype):
"""Pressure"""
known_units = ["MB", "HPA", "IN", "PA"]
[docs]
def value(self, units):
"""Convert to a value in the given units"""
if units.upper() not in pressure.known_units:
raise UnitsError(
f"unrecognized pressure unit: {units} "
f"known: {pressure.known_units}"
)
if units.upper() == self._units:
return self._value
# MKS
if self._units == "IN":
mb_value = self._value * 33.86398
elif self._units == "PA":
mb_value = self._value / 100.0
else:
mb_value = self._value
# Now convert
if units.upper() in ["MB", "HPA"]:
return mb_value
if units.upper() == "PA":
return mb_value * 100.0
return mb_value / 33.86398
[docs]
class temperature(basetype):
"""Temperature"""
known_units = ["F", "K", "C"]
[docs]
def value(self, units):
"""Convert to a value in the given units"""
units = units.upper()
if units not in temperature.known_units:
raise UnitsError(
f"unrecognized temperature unit: {units} "
f"known: {temperature.known_units}"
)
if units == self._units:
return self._value
# Convert to Celsius first
celsius_value = self._value
if self._units == "F":
celsius_value = (self._value - 32.0) / 1.8
elif self._units == "K":
celsius_value = self._value - 273.15
# Dump back
if units == "C":
return celsius_value
if units == "K":
return 273.15 + celsius_value
return 32.0 + celsius_value * 1.8