# Example for FFT on Quantities
##In this section we show how to integrate SCUQ in NumPys fft module.
# Although we implemented most of NumPys ufuncs, we cannot use quantities
# directly in the fft module of NumPy. The reason for this drawback is
# the fft module being directly implemented in C requiring floating
# point ndarrays as input parameters. In compensation, we implemented
# the floating-point conversion functions of NumPy. Thus our type quantity
# can be converted to a floating-point number. In order to avoid an
# unwanted conversion, we require weak consistency checking be enabled
# to perform the conversion.
# In Line 5 we create an array of input data. These values are quantities
# and thus have a unit. To convert these values to float strict
# consistency checking has to be disabled as shown in Line 15.
# The converted array can be used as usual, however it lost the
# information about the unit. We suggest saving the default unit from
# the quantity before conversion takes place and reassign it to the result.
# \example dft_example.py
# This example shows the integration of SCUQ in NumPys linear algebra module
# <tt>linalg</tt>. The functions of the module convert their arguments to
# floating point numbers; therefore, a direct integration of our quantities
# type is not feasible. However we implemented floating-point conversion
# for quantities to solve this issue.
# If a quantity or an ndarray of quantities is used with functions like
# <tt>linalg.inv</tt>, create a floating-point ndarray explicitly. In order
# to avoid unwanted conversions to floating point strict consistency checking
# must be disabled first. Otherwise, the type <tt>Quantity</tt> raises a
# <tt>ConversionException</tt>.
# In Line 5 we create the quantity that will be stored in a matrix. Our
# goal is to invert the matrix using NumPys <tt>linalg.inv</tt> method.
# We disable strict consistency checking in Line 11 and perform the
# operation in Line 14. Finally, the result has the type float.
# \example linalg_example.py
## \file quantities.py
# \brief This file contains the classes to model, handle, and use physical
# quantities.
#
# It also contains some base quantities that can be used
# to derive combined quantities.
# \author <a href="http://thomas.reidemeister.org/" target="_blank">
# Thomas Reidemeister</a>
## \namespace scuq::quantities
# \brief This namespace contains the class Quantity that models
# physical quantities.
## \defgroup quantities The Quantities Module
#
# This module contains the classes to model, handle, and use physical
# quantities. Because of Pythons nature of weak typing, this implementation
# strongly differs from the jsr-275. In our interpretation a
# Quantity is a tuple of a numeric value and a unit. Therefore we
# provide a class Quantity that emulates a numeric type and checks
# explicitly for consistency for each operation. Thus, this module
# is able to provide at least runtime checking for physical dimensions.
# For quantities you may choose between strict and non-strict unit
# checks. Strict type checking means that this instance
# raises an error whenever unequal units are
# compared. If strict checking is disabled
# this instance tries to convert among the units.
# An error will only be raised, if the units are
# not compatible (i.e. describe a different physical
# dimension). For example if you want to add a quantity
# measured in feet to a quantity measured in meters.
# If Strict type checking is enabled an error is raised.
# Otherwise the quantity measured in feet will be
# transformed to meters before being added.
# Strict type checking is enabled by default. In this
# class we use comparable for the case that the units
# can be converted to each other and no strict checking
# is used or for strict type checking and equal units.
# \see Quantity
# \author <a href="http://thomas.reidemeister.org/" target="_blank">
# Thomas Reidemeister</a>
# \see Quantity.set_strict
# \see Quantity.is_strict
# \addtogroup quantities
# @{
# standard module
# import operator
import numbers
import collections.abc
import numpy
import warnings
# local modules
import scuq.arithmetic as arithmetic
import scuq.qexceptions as qexceptions
import scuq.ucomponents as ucomponents
import scuq.cucomponents as cucomponents
# import scuq.si as si
import scuq.units as units
[docs]
def set_strict(bValue=True):
"""An abbreviation for Quantity.set_strict."""
Quantity.set_strict(bValue)
[docs]
def is_strict():
"""An abbreviation for Quantity.is_strict."""
return Quantity.is_strict()
def _deprecated_python2_method(name, replacement):
warnings.warn(
"%s is deprecated and kept only for Python 2 compatibility; use %s instead"
% (name, replacement),
DeprecationWarning,
stacklevel=2,
)
[docs]
class Quantity:
"""Base class that provides an interface to model quantities.
arithmetic.RationalNumber) are
automatically transformed to an dimensionless quantity if
the operations are performed on them. This also applies if
a quantity is the right operand of the numeric types stated
above.
"""
_STRICT = True
[docs]
def eval(self):
u = self._unit
v = self._value
try:
v = v.eval()
except AttributeError:
pass
return Quantity(u, v)
def _unitComparsion(unit1, unit2):
"""Helper method.
:param unit1: A unit.
:param unit2: Another unit.
:returns: True if they are compatible and strict is disabled or True if they are equal and strict is enabled.
"""
Quantity._require_unit(unit1, "unit1")
Quantity._require_unit(unit2, "unit2")
if unit1 is unit2:
return True
strict = Quantity.is_strict()
return (unit1 == unit2) or (unit1.is_compatible(unit2) and (not strict))
_unitComparsion = staticmethod(_unitComparsion)
def _require_unit(value, name="unit"):
if not isinstance(value, units.Unit):
raise TypeError("%s must be a Unit" % name)
_require_unit = staticmethod(_require_unit)
def _require_quantity(value, name="other"):
if not isinstance(value, Quantity):
raise TypeError("%s must be a Quantity" % name)
_require_quantity = staticmethod(_require_quantity)
def _require_quantity_or_number(value, name="other"):
if not isinstance(value, (Quantity, numbers.Number)):
raise TypeError("%s must be a Quantity or number" % name)
_require_quantity_or_number = staticmethod(_require_quantity_or_number)
def _require_value(value, name="value"):
if isinstance(value, units.Unit):
raise TypeError("%s must not be a Unit" % name)
if isinstance(value, Quantity):
raise TypeError("%s must not be a Quantity" % name)
if not isinstance(
value,
(
numbers.Number,
numpy.ndarray,
collections.abc.Sequence,
ucomponents.UncertainComponent,
cucomponents.CUncertainComponent,
cucomponents.Context,
arithmetic.RationalNumber,
),
):
raise TypeError("%s must be a numeric or supported component value" % name)
_require_value = staticmethod(_require_value)
[docs]
def __init__(self, unit, value):
"""Default constructor.
:param unit: The corresponding unit.
:param value: The value assigned
instances of ucomponents.UncertainInput as values.
"""
Quantity._require_unit(unit)
Quantity._require_value(value)
self._unit = unit
self._value = Quantity._accuracy(value)
[docs]
def reduce_to(self, unit):
"""Return this quantity expressed in ``unit``.
If the target unit has the same physical dimension as this quantity's
current unit, the numeric value is converted with the corresponding
unit operator and a new :class:`Quantity` in the target unit is
returned. If the target unit is dimensionally incompatible, this
quantity is returned unchanged.
This is an explicit unit conversion and is therefore performed
consistently regardless of the global strict-mode setting. Strict mode
only affects implicit compatibility checks, such as addition,
subtraction, comparisons, and :meth:`get_value`.
"""
Quantity._require_unit(unit)
if self._unit is unit:
return Quantity(unit, self._value)
sdimen = self._unit.get_dimension()
udimen = unit.get_dimension()
if sdimen == udimen:
operator = self._unit.get_operator_to(unit)
return Quantity(unit, operator.convert(self._value))
else:
return self
[docs]
def get_value(self, unit):
"""Get the absolute value of the quantity using the specified unit.
:param unit: The unit in which the quantity should be expressed in.
:returns: The absolute value of the quantity. comparable.
"""
if self._unit is unit:
return self._value
if not Quantity._unitComparsion(self._unit, unit):
raise qexceptions.ConversionException(
unit, " is not comparable to " + str(self._unit)
)
operator = self._unit.get_operator_to(unit)
return operator.convert(self._value)
[docs]
def get_default_unit(self):
"""Get the unit that is used commonly for this quantity.
:returns: The corresponding unit.
"""
return self._unit
[docs]
def is_dimensionless(self):
"""Check if this quantity copatible to dimensionless.
:returns: True, if the unit assigned is comparable to units.ONE.
"""
return self._unit.is_compatible(units.ONE)
[docs]
def is_dimensionless_strict(self):
"""Check if this quantity is dimensionless (strict).
:returns: True, if the unit assigned IS units.ONE.
"""
return Quantity._unitComparsion(self._unit, units.ONE)
# emulate numeric behaviour
[docs]
def __add__(self, other):
"""Get the sum of another instance of Quantity and this instance.
:param other: Another instance of Quantity or numeric value.
:returns: A new instance of Quantity representing the sum of both quantities. comparable.
"""
if isinstance(other, numbers.Number):
if self.is_dimensionless_strict():
result = self._value + other
else:
raise qexceptions.ConversionException(
self._unit, "is not compatible to dimensionless"
)
else:
Quantity._require_quantity(other)
# check if the units are comparable
if self._unit is other._unit:
result = self._value + other._value
elif not Quantity._unitComparsion(self._unit, other._unit):
raise qexceptions.ConversionException(
other._unit, "is not compatible to " + str(self._unit)
)
else:
# get the other quantity in this unit
result = self._value + other.get_value(self._unit)
return Quantity(self._unit, result)
[docs]
def __sub__(self, other):
"""Get the difference of another instance of Quantity and this instance.
:param other: Another instance of Quantity.
:returns: A new instance of Quantity representing the difference of both quantities. comparable.
"""
return self.__add__(-other)
[docs]
def __mul__(self, other):
r"""Get the product of another instance of Quantity and this instance.
Even if the units are defined in the same dimension. For example,
if one takes m \times ft the result will be ft m
not m^2 nor ft^2.
:param other: Another instance of Quantity or numeric value.
:returns: A new instance of Quantity representing the product of both quantities.
"""
Quantity._require_quantity_or_number(other)
if isinstance(other, numbers.Number):
newUnit = self._unit
newValue = self._value * other
else:
newUnit = self._unit * other._unit
newValue = self._value * other._value
return Quantity(newUnit, newValue)
[docs]
def __pow__(self, other):
"""Get the power of of this instance.
:param other: The power to which this instance is raised (must be
an integer or dimensionless quantity).
:returns: A new instance of Quantity representing the power of this instance. is not dimensionless.
"""
Quantity._require_quantity_or_number(other)
if isinstance(other, numbers.Number):
newUnit = self._unit**other
newValue = self._value**other
else:
if not Quantity._unitComparsion(other.get_default_unit(), units.ONE):
raise qexceptions.ConversionException(
self._unit,
"The argument is not comparable to a dimensionless "
+ "quantity "
+ str(other._unit),
)
newValue = self._value**other._value
newUnit = self._unit**other._value
return Quantity(newUnit, newValue)
[docs]
def __truediv__(self, other):
r"""Get the fraction of another instance of Quantity and this instance.
Even if the units are defined in the same dimension. For example,
if one takes m \div ft the result will be
:param other: Another instance of Quantity or numeric value used as
divisor.
:returns: A new instance of Quantity representing the sum of both quantities.
"""
Quantity._require_quantity_or_number(other)
if isinstance(other, numbers.Number):
newUnit = self._unit
newValue = self._value / other
else:
newUnit = self._unit / other._unit
newValue = self._value / other._value
return Quantity(newUnit, newValue)
[docs]
def __radd__(self, other):
"""Get the sum of this instance of Quantity and another value.
:param other: Another value (not an instance of Quantity).
:returns: A new instance of Quantity representing the sum. comparable.
"""
# since the addition is symetric
return self.__add__(other)
[docs]
def __rsub__(self, other):
"""Get the difference of another value and this instance of Quantity.
:param other: Another value (not an instance of Quantity).
:returns: A new instance of Quantity representing the difference of both quantities. comparable.
"""
# other - self = -self+other
v = -1 * self
return v.__add__(other)
[docs]
def __rmul__(self, other):
"""Get the product of this instance of Quantity and another value.
:param other: Another value (not an instance of Quantity).
:returns: A new instance of Quantity representing the product of both quantities.
"""
Quantity._require_quantity_or_number(other)
if isinstance(other, numbers.Number):
newValue = other * self._value
newUnit = self._unit
else:
newValue = other._value * self._value
newUnit = other._unit * self._unit
return Quantity(newUnit, newValue)
[docs]
def __rtruediv__(self, other):
"""Get the fraction of another value and this instance.
:param other: Another instance of Quantity or numeric value used as
dividend.
:returns: A new instance of Quantity representing the sum of both quantities.
"""
Quantity._require_quantity_or_number(other)
if isinstance(other, numbers.Number):
newValue = other / self._value
newUnit = units.ONE / self._unit
else:
newValue = other._value / self._value
newUnit = other._unit / self._unit
return Quantity(newUnit, newValue)
[docs]
def __rpow__(self, other):
"""Get the power of another value and this instance.
instance also accepts floating point powers.
:param other: Another instance of Quantity.
:returns: A new instance of Quantity representing the sum of both quantities. comparable to units.ONE.
"""
Quantity._require_quantity_or_number(other)
if not Quantity._unitComparsion(self._unit, units.ONE):
raise qexceptions.ConversionException(
self, "this unit is not" + " dimensionless!"
)
return other**self._value
[docs]
def __iadd__(self, other):
"""Add the argument to this instance.
:param other: Another instance of Quantity or numeric value.
comparable.
"""
if isinstance(other, numbers.Number):
if self.is_dimensionless_strict():
self._value += other
else:
raise qexceptions.ConversionException(self._unit)
else:
Quantity._require_quantity(other)
result = self + other # may throw exception
# assign the values
self._unit = result._unit
self._value = result._value
return self
[docs]
def __isub__(self, other):
"""Substract the argument from this instance.
:param other: Another instance of Quantity or numeric value.
comparable.
"""
if isinstance(other, numbers.Number):
if self.is_dimensionless_strict():
self._value -= other
else:
raise qexceptions.ConversionException(self._unit)
else:
Quantity._require_quantity(other)
result = self - other # may throw exception
# assign the values
self._unit = result._unit
self._value = result._value
return self
[docs]
def __imul__(self, other):
"""Multiply this instance with the argument.
:param other: Another instance of Quantity or numeric value.
"""
Quantity._require_quantity_or_number(other)
result = self * other
# assign the values
self._unit = result._unit
self._value = result._value
return self
[docs]
def __idiv__(self, other):
"""Divide this instance by the argument.
:param other: Another instance of Quantity or numeric value..
"""
_deprecated_python2_method("__idiv__", "__itruediv__ or /=")
Quantity._require_quantity_or_number(other)
result = self / other
# assign the values
self._unit = result._unit
self._value = result._value
return self
[docs]
def __ipow__(self, other):
"""Raise the this instance to the argument.
:param other: Another instance of Quantity or numeric value.
"""
Quantity._require_quantity_or_number(other)
result = self**other
# assign the values
self._unit = result._unit
self._value = result._value
return self
[docs]
def __neg__(self):
"""Negate the value of this quantity.
:returns: A new instance of Quantity representing the negative of this quantity.
"""
return Quantity(self._unit, -self._value)
[docs]
def __pos__(self):
"""Copy this instance.
:returns: A copy of the current instance.
"""
return Quantity(self._unit, self._value)
[docs]
def __abs__(self):
"""Get the absolute value of this Quantity.
:returns: The absolute value of this quantity.
"""
return Quantity(self._unit, abs(self._value))
[docs]
def __invert__(self):
r"""Return the inverted instance of this Quantity.
For example, let your quantity be \frac{1}{2} \frac{m}{s} ,
then the result of this operation is 2 \frac{s}{m} .
:returns: The inverted quantity.
"""
return Quantity(~self._unit, ~self._value)
[docs]
def __complex__(self):
"""Cast this instance to the numeric type complex.
stripped from the result.
:returns: The value of this instance casted to complex.
"""
if Quantity.is_strict() and self.get_default_unit() != units.ONE:
raise qexceptions.ConversionException(
"Only dimensionless quantities can be converted to complex"
)
return complex(self._value)
[docs]
def __long__(self):
"""Cast this instance to the numeric type long.
stripped from the result.
:returns: The value of this instance casted to long.
"""
_deprecated_python2_method("__long__", "int(quantity)")
if Quantity.is_strict() and self.get_default_unit() != units.ONE:
raise qexceptions.ConversionException(
"Only dimensionless quantities can be converted to long"
)
return int(self._value)
[docs]
def __float__(self):
"""Cast this instance to the numeric type float.
stripped from the result.
checking is enabled.
:returns: The value of this instance casted to float.
"""
if Quantity.is_strict() and self.get_default_unit() != units.ONE:
raise qexceptions.ConversionException(
"Only dimensionless quantities can be converted to float"
)
return float(self._value)
[docs]
def __int__(self):
"""Cast this instance to the numeric type int.
stripped from the result.
:returns: The value of this instance casted to int.
"""
if Quantity.is_strict() and self.get_default_unit() != units.ONE:
raise qexceptions.ConversionException(
"Only dimensionless quantities can be converted to int"
)
return int(self._value)
[docs]
def __str__(self):
"""Get a string describing this Quantity.
The result will be of the form ``value unit``
(i.e. "12.0 m").
:returns: A string describing this quantity.
"""
return str(self._value) + " " + str(self._unit)
[docs]
def __repr__(self):
"""Get a string describing this Quantity.
The result will be of the form ``Quantity(unit, value)``
(i.e. "Quantity(si.METER, 12.0)").
:returns: A string describing this quantity.
"""
return "Quantity(%s, %s)" % (self._unit, self._value)
[docs]
def __lt__(self, other):
"""Check, if this instance is less than the argument.
A comparsion will be done, if the units are comparable.
:param other: Another instance of Quantity.
:returns: True, if this instance is less than the argument. comparable.
"""
if not isinstance(other, Quantity):
a, b = self._coerce(other)
return a < b
if self._unit is other._unit:
otherValue = other._value
elif not Quantity._unitComparsion(self._unit, other._unit):
raise qexceptions.ConversionException(
self, " is not comparable to " + str(other)
)
else:
otherValue = other.get_value(self._unit)
return self._value < otherValue
[docs]
def __le__(self, other):
"""Check, if this instance is less or equal to the argument.
A comparsion will be done, if the units are comparable.
:param other: Another instance of Quantity.
:returns: True, if this instance is less or equal to the argument. comparable.
"""
if not isinstance(other, Quantity):
a, b = self._coerce(other)
return a <= b
if self._unit is other._unit:
otherValue = other._value
elif not Quantity._unitComparsion(self._unit, other._unit):
raise qexceptions.ConversionException(
self, " is not comparable to " + str(other)
)
else:
otherValue = other.get_value(self._unit)
return self._value <= otherValue
[docs]
def __eq__(self, other):
"""Check, if this instance is equal to the argument.
A comparsion will be done, if the units are comparable.
:param other: Another instance of Quantity.
:returns: True, if this instance is equal to the argument.
"""
if not isinstance(other, Quantity):
try:
a, b = self._coerce(other)
return a == b
except NotImplementedError:
return False
if self._unit is other._unit:
otherValue = other._value
elif not Quantity._unitComparsion(self._unit, other._unit):
return False
else:
otherValue = other.get_value(self._unit)
return self._value == otherValue
[docs]
def __ne__(self, other):
"""Check, if this instance is not equal to the argument.
A comparsion will be done, if the units are comparable.
:param other: Another instance of Quantity.
:returns: True, if this instance is not equal to the argument.
"""
if not isinstance(other, Quantity):
a, b = self._coerce(other)
return a != b
if self._unit is other._unit:
otherValue = other._value
elif not Quantity._unitComparsion(self._unit, other._unit):
return True
else:
otherValue = other.get_value(self._unit)
return self._value != otherValue
[docs]
def __gt__(self, other):
"""Check, if this instance is greater than the argument.
A comparsion will be done, if the units are comparable.
:param other: Another instance of Quantity.
:returns: True, if this instance is greater than the argument. comparable.
"""
if not isinstance(other, Quantity):
a, b = self._coerce(other)
return a > b
if self._unit is other._unit:
otherValue = other._value
elif not Quantity._unitComparsion(self._unit, other._unit):
raise qexceptions.ConversionException(
self, " is not comparable to " + str(other)
)
else:
otherValue = other.get_value(self._unit)
return self._value > otherValue
[docs]
def __ge__(self, other):
"""Check, if this instance is greater or equal to the argument.
A comparsion will be done, if the units are comparable.
:param other: Another instance of Quantity.
:returns: True, if this instance is greater or equal to the argument. comparable.
"""
if not isinstance(other, Quantity):
a, b = self._coerce(other)
return a >= b
if self._unit is other._unit:
otherValue = other._value
elif not Quantity._unitComparsion(self._unit, other._unit):
raise qexceptions.ConversionException(
self, " is not comparable to " + str(other)
)
else:
otherValue = other.get_value(self._unit)
return self._value >= otherValue
[docs]
def __cmp__(self, other):
"""Compare two instances of quantity.
:param other: Another instance of Quantity or numeric value.
:returns: -1, if the this instance is less than the argument, 0, if this instance is equal to the argument, +1, if this instance is greater than the argument. comparable.
"""
_deprecated_python2_method("__cmp__", "the rich comparison operators")
def cmp(a, b):
return (a > b) - (a < b)
if not isinstance(other, Quantity):
a, b = self._coerce(other)
return cmp(a, b)
if not Quantity._unitComparsion(self._unit, other._unit):
raise qexceptions.ConversionException(
self, " is not comparable to " + str(other)
)
if self < other:
return -1
if self > other:
return 1
if self == other:
return 0
# this should not happen
raise RuntimeError("Quantity comparison produced no ordering result")
[docs]
def __getstate__(self):
"""Serialization using pickle.
:returns: A string that represents the serialized form of this instance.
"""
return (self._unit, self._value)
[docs]
def __setstate__(self, state):
"""Deserialization using pickle.
:param state: The state of the object.
"""
self._unit, self._value = state
[docs]
def value_of(other):
"""Factory for generating quantities.
:param other: A quantity, or another value.
:returns: A Quantity. If the argument is a quantity this method returns it. If the argument is a numeric value, this method generates a dimensionless quantity having the argument as value. instances of ucomponents.UncertainInput as values.
"""
if isinstance(other, Quantity):
return other
if isinstance(other, units.Unit):
raise TypeError("other must not be a Unit")
if not (
isinstance(other, numbers.Number)
or isinstance(other, collections.abc.Sequence)
or isinstance(other, ucomponents.UncertainInput)
or isinstance(other, arithmetic.RationalNumber)
):
raise TypeError("other must be a Quantity, number, sequence, or uncertain input")
# Create a dimensionless quantity having the
# argument as value.
return Quantity(units.ONE, other)
value_of = staticmethod(value_of)
def _accuracy(value):
"""Helper method, to increase the accuracy of integer operations.
As soon an int or long is provided, it is converted to a
rational number.
:param value: The value to be converted.
"""
if isinstance(value, int) or isinstance(value, int):
return arithmetic.RationalNumber(value, 1)
else:
return value
_accuracy = staticmethod(_accuracy)
# Support for numpy
[docs]
def arccos(self):
"""This method provides the broadcast interface for
numpy.arccos.
:returns: The inverse Cosine of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.arccos(self._value)
return Quantity(units.ONE, value)
[docs]
def arccosh(self):
"""This method provides the broadcast interface for
numpy.arccosh.
:returns: The inverse hyperbolic Cosine of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.arccosh(self._value)
return Quantity(units.ONE, value)
[docs]
def arcsin(self):
"""This method provides the broadcast interface for
numpy.arcsin.
:returns: The inverse Sine of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.arcsin(self._value)
return Quantity(units.ONE, value)
[docs]
def arcsinh(self):
"""This method provides the broadcast interface for
numpy.arcsinh.
:returns: The inverse hyperbolic Sine of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.arcsinh(self._value)
return Quantity(units.ONE, value)
[docs]
def arctan(self):
"""This method provides the broadcast interface for
numpy.arctan.
:returns: The inverse Tangent of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.arctan(self._value)
return Quantity(units.ONE, value)
[docs]
def arctanh(self):
"""This method provides the broadcast interface for
numpy.arctanh.
:returns: The inverse hyperbolic Tangent of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.arctanh(self._value)
return Quantity(units.ONE, value)
[docs]
def cos(self):
"""This method provides the broadcast interface for
numpy.cos.
:returns: The Cosine of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.cos(self._value)
return Quantity(units.ONE, value)
[docs]
def cosh(self):
"""This method provides the broadcast interface for
numpy.cosh.
:returns: The hyperbolic Cosine of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.cosh(self._value)
return Quantity(units.ONE, value)
[docs]
def tan(self):
"""This method provides the broadcast interface for
numpy.tan.
:returns: The Tangent of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.tan(self._value)
return Quantity(units.ONE, value)
[docs]
def tanh(self):
"""This method provides the broadcast interface for
numpy.tanh.
:returns: The hyperbolic Tangent of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.tanh(self._value)
return Quantity(units.ONE, value)
[docs]
def log10(self):
"""This method provides the broadcast interface for
numpy.log10.
:returns: The decadic Logarithm of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.log10(self._value)
return Quantity(units.ONE, value)
[docs]
def log2(self):
"""This method provides the broadcast interface for
numpy.log2.
:returns: The binary logarithm of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.log2(self._value)
return Quantity(units.ONE, value)
[docs]
def sin(self):
"""This method provides the broadcast interface for
numpy.sin.
:returns: The Sine of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.sin(self._value)
return Quantity(units.ONE, value)
[docs]
def sinh(self):
"""This method provides the broadcast interface for
numpy.sinh.
:returns: The hyperbolic Sine of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.sinh(self._value)
return Quantity(units.ONE, value)
[docs]
def sqrt(self):
"""This method provides the broadcast interface for
numpy.sqrt.
:returns: The Square Root of this quantity.
"""
value = numpy.sqrt(self._value)
unit = numpy.sqrt(self._unit)
return Quantity(unit, value)
[docs]
def square(self):
"""This method provides the broadcast interface for
numpy.sqrt.
:returns: The Square Root of this quantity.
"""
return self * self
[docs]
def fabs(self):
"""This method provides the broadcast interface for
numpy.fabs.
:returns: The absolute value of this quantity.
"""
value = numpy.fabs(self._value)
return Quantity(self._unit, value)
[docs]
def absolute(self):
"""This method provides the broadcast interface for
numpy.absolute.
:returns: The absolute value of this quantity.
"""
value = numpy.absolute(self._value)
return Quantity(self._unit, value)
[docs]
def __floor__(self):
"""This method provides the broadcast interface for
numpy.floor.
:returns: The largest integer less than or equal to this quantity.
"""
try:
value = self._value.__floor__()
except AttributeError:
value = numpy.floor(self._value)
return Quantity(self._unit, value)
[docs]
def __ceil__(self):
"""This method provides the broadcast interface for
numpy.ceil.
:returns: The largest integer greater than or equal to this quantity.
"""
try:
value = self._value.__ceil__()
except AttributeError:
value = numpy.ceil(self._value)
return Quantity(self._unit, value)
[docs]
def exp(self):
"""This method provides the broadcast interface for
numpy.exp.
:returns: The Exponential of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.exp(self._value)
return Quantity(units.ONE, value)
[docs]
def log(self):
"""This method provides the broadcast interface for
numpy.log.
:returns: The Natural Logarithm of this quantity. If the unit assigned is not dimensionless.
"""
if not self.is_dimensionless():
raise qexceptions.NotDimensionlessException(self._unit)
value = numpy.log(self._value)
return Quantity(units.ONE, value)
[docs]
def arctan2(self, other):
"""This method provides the broadcast interface for
numpy.arctan2.
:param other: Another instance of Quantity.
:returns: The inverse two-argument tangent of the arguments. If the unit assigned is not dimensionless.
"""
if isinstance(other, numbers.Number):
if self.is_dimensionless():
value = numpy.arctan2(float(self._value), other)
return Quantity(units.ONE, value)
else:
raise qexceptions.NotDimensionlessException(self._unit)
elif isinstance(other, Quantity):
other_val = other.get_val(
self.get_default_unit()
) # may raise a qexceptions.ConversionException
return Quantity(
units.ONE, numpy.arctan2(float(self._value), float(other_val))
)
else:
raise NotImplementedError
[docs]
def hypot(self, other):
"""This method provides the broadcast interface for
hypothenusis.
:param other: Another instance of Quantity.
:returns: The hypothenusis of the arguments.
"""
if not isinstance(other, Quantity):
tmp, other = self._coerce(other)
return numpy.hypot(tmp, other)
Quantity._require_quantity(other)
return numpy.sqrt(self * self + other * other)
[docs]
def conjugate(self):
"""This method provides the broadcast interface for
numpy.conjugate.
:returns: This quantity.
"""
try:
value = self._value.conjugate()
except AttributeError:
value = numpy.conjugate(self._value)
return Quantity(self._unit, value)
[docs]
def set_strict(bValue=True):
"""Turn on/off the strict evaluation of quantities. This will
affect any quantities calculation beyond this point.
:param bValue: True or False
"""
if bValue:
Quantity._STRICT = True
else:
Quantity._STRICT = False
set_strict = staticmethod(set_strict)
[docs]
def is_strict():
"""Get the type of quantities calculation. If either
strict or non strict evaluation of quantities is
implemented.
:returns: True (i.e. strict enabled) or False (i.e. strict disabled).
"""
return Quantity._STRICT
is_strict = staticmethod(is_strict)
def _coerce(self, other):
"""Implementation of coercion rules.
See also: Coercion - The page describing the coercion rules.
"""
if isinstance(other, Quantity):
return (self, other)
elif (
isinstance(other, int)
or isinstance(other, float)
or isinstance(other, complex)
or isinstance(other, arithmetic.RationalNumber)
):
other = Quantity.value_of(other)
return (self, other)
elif isinstance(other, numpy.ndarray):
if other.dtype == Quantity:
raise NotImplementedError(
"Cannot encapsulate ndarrays of" + "quantities in quantities"
)
else:
raise NotImplementedError()
[docs]
def get_expectation_value_as_float(self):
v = self._value
try:
v = v.get_value()
except AttributeError:
pass
return v
[docs]
def get_expectation_value(self):
v = self.get_expectation_value_as_float()
return Quantity(self._unit, v)
## @}