Source code for scimath.units.convert

# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

""" Defines the convert, convert_str and parser function
"""

import numpy
from .unit import InvalidConversion


#####################################################################
# Definitions:
#####################################################################

[docs]def convert(value, from_unit, to_unit): """ Coverts value from one unit to another. Parameters ---------- value : float value to convert from_unit : scimath.unit object implied units of 'value' to_unit : scimath.unit object implied units of the returned float Returns ------- value * conversion_factor + offset : data type is the same as was passed in. Description ----------- Checks first to see if from_unit and to_unit are equal and passes value back in that case. Then convert() forms a conversion factor by dividing the units. The offset is zero unless explicitly set otherwise in the unit definition. Handling of UnitArrays is done by checking whether value is a numpy.ndarray. **Note**: Enthought has extended the original units implementation to handle temperature conversions. Temperature units are a special case because they can have a different origin. This causes a fundamental ambiguity. What behavior do we expect when we convert temperature? Option #1 When we convert 0 degrees centigrade we get 32 fahrenheit. Option #2 When we convert a temperature difference of 0 degrees centigrade we get a temperature difference of 0 degrees fahrenheit. By convention we have made the units system behave like in Option #1 so that convert() handles absolute temperatures, not temperature differences. """ # TODO: it would be nice if this function could handle inversion as well as # just scaling and also gave better error messages. For example: ''' res = from_unit / to_unit if from_unit / to_unit is dimensionless: # straight convert\ pass elif from_unit * to_unit is dimensionless: # invert pass else: # dimensionally incompatible pass ''' # TODO: This is my guess at what Lowell did to improve performance... # I need to confirm that I'm doing the same thing he did (TNV) if from_unit == to_unit: return value else: try: # try a straight conversion factor = float(from_unit / to_unit) except InvalidConversion as ex: # try an inversion factor = from_unit * to_unit if not isinstance(factor, float): raise ex try: offset = (from_unit.offset * factor) - to_unit.offset except AttributeError: offset = 0.0 # test if it is a UnitArray without importing UnitArray to keep # the dependencies low for this module if isinstance(value, numpy.ndarray) and hasattr(value, 'units'): return value * factor + value.units * offset return value * factor + offset
def convert_str(value, from_unit_string, to_unit_string): """ Convert functions to take in strings and conveniently parse them to units, to return the conversion factor Parameters ---------- from_unit_string: Str String representing from_unit, eg. 'm' to_unit_string: Str String representing to_unit, eg. 'ft' Returns: -------- return_value: Float Conversion factor between the from_unit and the to_unit """ from scimath.units import unit_parser return convert(value, unit_parser.unit_parser.parse_unit(from_unit_string), unit_parser.unit_parser.parse_unit(to_unit_string)) # Function to return a parser instance def parser(): from scimath.units import unit_parser return unit_parser.unit_parser()