123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- """UnitDbl module."""
- import operator
- from matplotlib import cbook
- class UnitDbl:
- """Class UnitDbl in development.
- """
- # Unit conversion table. Small subset of the full one but enough
- # to test the required functions. First field is a scale factor to
- # convert the input units to the units of the second field. Only
- # units in this table are allowed.
- allowed = {
- "m": (0.001, "km"),
- "km": (1, "km"),
- "mile": (1.609344, "km"),
- "rad": (1, "rad"),
- "deg": (1.745329251994330e-02, "rad"),
- "sec": (1, "sec"),
- "min": (60.0, "sec"),
- "hour": (3600, "sec"),
- }
- _types = {
- "km": "distance",
- "rad": "angle",
- "sec": "time",
- }
- def __init__(self, value, units):
- """Create a new UnitDbl object.
- Units are internally converted to km, rad, and sec. The only
- valid inputs for units are [m, km, mile, rad, deg, sec, min, hour].
- The field UnitDbl.value will contain the converted value. Use
- the convert() method to get a specific type of units back.
- = ERROR CONDITIONS
- - If the input units are not in the allowed list, an error is thrown.
- = INPUT VARIABLES
- - value The numeric value of the UnitDbl.
- - units The string name of the units the value is in.
- """
- data = cbook._check_getitem(self.allowed, units=units)
- self._value = float(value * data[0])
- self._units = data[1]
- def convert(self, units):
- """Convert the UnitDbl to a specific set of units.
- = ERROR CONDITIONS
- - If the input units are not in the allowed list, an error is thrown.
- = INPUT VARIABLES
- - units The string name of the units to convert to.
- = RETURN VALUE
- - Returns the value of the UnitDbl in the requested units as a floating
- point number.
- """
- if self._units == units:
- return self._value
- data = cbook._check_getitem(self.allowed, units=units)
- if self._units != data[1]:
- raise ValueError(f"Error trying to convert to different units.\n"
- f" Invalid conversion requested.\n"
- f" UnitDbl: {self}\n"
- f" Units: {units}\n")
- return self._value / data[0]
- def __abs__(self):
- """Return the absolute value of this UnitDbl."""
- return UnitDbl(abs(self._value), self._units)
- def __neg__(self):
- """Return the negative value of this UnitDbl."""
- return UnitDbl(-self._value, self._units)
- def __bool__(self):
- """Return the truth value of a UnitDbl."""
- return bool(self._value)
- def __eq__(self, rhs):
- return self._cmp(rhs, operator.eq)
- def __ne__(self, rhs):
- return self._cmp(rhs, operator.ne)
- def __lt__(self, rhs):
- return self._cmp(rhs, operator.lt)
- def __le__(self, rhs):
- return self._cmp(rhs, operator.le)
- def __gt__(self, rhs):
- return self._cmp(rhs, operator.gt)
- def __ge__(self, rhs):
- return self._cmp(rhs, operator.ge)
- def _cmp(self, rhs, op):
- """Compare two UnitDbl's.
- = ERROR CONDITIONS
- - If the input rhs units are not the same as our units,
- an error is thrown.
- = INPUT VARIABLES
- - rhs The UnitDbl to compare against.
- - op The function to do the comparison
- = RETURN VALUE
- - Returns op(self, rhs)
- """
- self.checkSameUnits(rhs, "compare")
- return op(self._value, rhs._value)
- def __add__(self, rhs):
- """Add two UnitDbl's.
- = ERROR CONDITIONS
- - If the input rhs units are not the same as our units,
- an error is thrown.
- = INPUT VARIABLES
- - rhs The UnitDbl to add.
- = RETURN VALUE
- - Returns the sum of ourselves and the input UnitDbl.
- """
- self.checkSameUnits(rhs, "add")
- return UnitDbl(self._value + rhs._value, self._units)
- def __sub__(self, rhs):
- """Subtract two UnitDbl's.
- = ERROR CONDITIONS
- - If the input rhs units are not the same as our units,
- an error is thrown.
- = INPUT VARIABLES
- - rhs The UnitDbl to subtract.
- = RETURN VALUE
- - Returns the difference of ourselves and the input UnitDbl.
- """
- self.checkSameUnits(rhs, "subtract")
- return UnitDbl(self._value - rhs._value, self._units)
- def __mul__(self, rhs):
- """Scale a UnitDbl by a value.
- = INPUT VARIABLES
- - rhs The scalar to multiply by.
- = RETURN VALUE
- - Returns the scaled UnitDbl.
- """
- return UnitDbl(self._value * rhs, self._units)
- def __rmul__(self, lhs):
- """Scale a UnitDbl by a value.
- = INPUT VARIABLES
- - lhs The scalar to multiply by.
- = RETURN VALUE
- - Returns the scaled UnitDbl.
- """
- return UnitDbl(self._value * lhs, self._units)
- def __div__(self, rhs):
- """Divide a UnitDbl by a value.
- = INPUT VARIABLES
- - rhs The scalar to divide by.
- = RETURN VALUE
- - Returns the scaled UnitDbl.
- """
- return UnitDbl(self._value / rhs, self._units)
- def __str__(self):
- """Print the UnitDbl."""
- return "%g *%s" % (self._value, self._units)
- def __repr__(self):
- """Print the UnitDbl."""
- return "UnitDbl(%g, '%s')" % (self._value, self._units)
- def type(self):
- """Return the type of UnitDbl data."""
- return self._types[self._units]
- @staticmethod
- def range(start, stop, step=None):
- """Generate a range of UnitDbl objects.
- Similar to the Python range() method. Returns the range [
- start, stop) at the requested step. Each element will be a
- UnitDbl object.
- = INPUT VARIABLES
- - start The starting value of the range.
- - stop The stop value of the range.
- - step Optional step to use. If set to None, then a UnitDbl of
- value 1 w/ the units of the start is used.
- = RETURN VALUE
- - Returns a list containing the requested UnitDbl values.
- """
- if step is None:
- step = UnitDbl(1, start._units)
- elems = []
- i = 0
- while True:
- d = start + i * step
- if d >= stop:
- break
- elems.append(d)
- i += 1
- return elems
- @cbook.deprecated("3.2")
- def checkUnits(self, units):
- """Check to see if some units are valid.
- = ERROR CONDITIONS
- - If the input units are not in the allowed list, an error is thrown.
- = INPUT VARIABLES
- - units The string name of the units to check.
- """
- if units not in self.allowed:
- raise ValueError("Input units '%s' are not one of the supported "
- "types of %s" % (
- units, list(self.allowed.keys())))
- def checkSameUnits(self, rhs, func):
- """Check to see if units are the same.
- = ERROR CONDITIONS
- - If the units of the rhs UnitDbl are not the same as our units,
- an error is thrown.
- = INPUT VARIABLES
- - rhs The UnitDbl to check for the same units
- - func The name of the function doing the check.
- """
- if self._units != rhs._units:
- raise ValueError(f"Cannot {func} units of different types.\n"
- f"LHS: {self._units}\n"
- f"RHS: {rhs._units}")
|