From e3f25de8c77e4092e9767871fcc09b7ae237e206 Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Thu, 2 May 2013 21:40:45 -0300 Subject: [PATCH] More documentation --- CHANGES | 2 +- docs/_themes/flask/layout.html | 7 ++- docs/_themes/flask/theme.conf | 1 + docs/nonmult.rst | 94 ++++++++++++++++++++++++++-------- pint/testsuite/test_unit.py | 12 +++++ pint/unit.py | 13 ++++- 6 files changed, 104 insertions(+), 25 deletions(-) diff --git a/CHANGES b/CHANGES index ea8465b..d07d659 100644 --- a/CHANGES +++ b/CHANGES @@ -29,7 +29,7 @@ Pint Changelog - short forms of binary prefixes, more units and fix to less than comparison. (Issue #20, thanks muggenhor) - pint is now zip-safe - (Issue #22, thanks muggenhor) + (Issue #23, thanks muggenhor) Version 0.1.3 (2013-01-07) diff --git a/docs/_themes/flask/layout.html b/docs/_themes/flask/layout.html index b77f200..2854215 100644 --- a/docs/_themes/flask/layout.html +++ b/docs/_themes/flask/layout.html @@ -7,7 +7,12 @@ {% endblock %} -{%- block relbar2 %}{% endblock %} +{%- block relbar2 %} + {% if theme_github_fork %} + Fork me on GitHub + {% endif %} +{% endblock %} {% block header %} {{ super() }} {% if pagename == 'index' %} diff --git a/docs/_themes/flask/theme.conf b/docs/_themes/flask/theme.conf index 18c720f..420c609 100644 --- a/docs/_themes/flask/theme.conf +++ b/docs/_themes/flask/theme.conf @@ -7,3 +7,4 @@ pygments_style = flask_theme_support.FlaskyStyle index_logo = '' index_logo_height = 120px touch_icon = +github_fork = hgrecco/pint diff --git a/docs/nonmult.rst b/docs/nonmult.rst index b2b69fc..1f0d7cb 100644 --- a/docs/nonmult.rst +++ b/docs/nonmult.rst @@ -4,45 +4,97 @@ Temperature conversion ====================== -This is not supported by most +Unlike meters and seconds, fahrenheits, celsius and kelvin are not +multiplicative units. Temperature is expressed in a system with a +reference point, and relations between temperature units include +not only an scaling factor but also an offset. Pint supports these +type of units and conversions between them. The default definition +file includes fahrenheits, celsius, kelvin and rankine abbreviated +as degF, degC, degK, and degR. - >>> home = 25.4 * ureg.degC - >>> print(home.to('degF')) +For example, to convert from celsius to fahrenheit: +.. testsetup:: * -For every temperature unit in the registry, there is also a *delta* counterpart -to specify differences. For example, the + from pint import UnitRegistry + ureg = UnitRegistry() + Q_ = ureg.Quantity - >>> increase = 12.3 * ureg.delta_degC - >>> print(increase.to(ureg.delta_degK)) - 12.3 - >>> print(increase.to(ureg.delta_degF)) +.. doctest:: -which is different from: + >>> from pint import UnitRegistry + >>> ureg = UnitRegistry() + >>> home = 25.4 * ureg.degC + >>> print(home.to('degF')) + 77.7200004 degF - >>> print((12.3 * ureg.degC).to(ureg.delta_degK) - >>> print((12.3 * ureg.degC).to(ureg.delta_degC) +or to other kelvin or rankine: -Subtraction of two temperatures also yields a *delta* unit. +.. doctest:: - >>> 25.4 * ureg.degC - 10. * ureg.degC - 15.4 delta_degC + >>> print(home.to('degK')) + 298.55 degK + >>> print(home.to('degR')) + 537.39 degR + +Additionally, for every temperature unit in the registry, +there is also a *delta* counterpart to specify differences. +For example, the change in celsius is equal to the change +in kelvin, but not in fahrenheit (as the scaling factor +is different). + +.. doctest:: + + >>> increase = 12.3 * ureg.delta_degC + >>> print(increase.to(ureg.delta_degK)) + 12.3 delta_degK + >>> print(increase.to(ureg.delta_degF)) + 6.83333333333 delta_degF + +.. + Subtraction of two temperatures also yields a *delta* unit. + + .. doctest:: + + >>> 25.4 * ureg.degC - 10. * ureg.degC + 15.4 delta_degC Differences in temperature are multiplicative: -The parser knows about *delta* units and use them when a temperature unit is found -in a multiplicative context. For example, here: +.. doctest:: - >>> ureg.parse_units('degC/meter') + >>> speed = 60. * ureg.delta_degC / ureg.min + >>> print(speed.to('delta_degC/second')) + 1.0 delta_degC / second + +The parser knows about *delta* units and use them when a temperature unit +is found in a multiplicative context. For example, here: + +.. doctest:: + + >>> print(ureg.parse_units('degC/meter')) delta_degC / meter but not here: - >>> ureg.parse_units('degC') +.. doctest:: + + >>> print(ureg.parse_units('degC')) degC -You can override this behaviour +You can override this behaviour: - >>> ureg.parse_units('degC/meter', to_delta=False) +.. doctest:: + + >>> print(ureg.parse_units('degC/meter', to_delta=False)) degC / meter + +To define a new temperature, you need to specify the offset. For example, +this is the definition of the celsius and fahrenheit:: + + degC = degK; offset: 273.15 = celsius + degF = 9 / 5 * degK; offset: 255.372222 = fahrenheit + +You do not need to define *delta* units, as they are defined automatically. + diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py index 099d338..27194fe 100644 --- a/pint/testsuite/test_unit.py +++ b/pint/testsuite/test_unit.py @@ -233,3 +233,15 @@ class TestRegistry(TestCase): self.assertEqual(self.ureg.get_symbol('kilometer'), 'km') self.assertEqual(self.ureg.get_symbol('megahertz'), 'MHz') self.assertEqual(self.ureg.get_symbol('millisecond'), 'ms') + + @unittest.expectedFailure + def test_delta_in_diff(self): + """This might be supported in future versions + """ + xk = 1 * self.ureg.degK + yk = 2 * self.ureg.degK + yf = yk.to('degF') + yc = yk.to('degC') + self.assertEqual(yk - xk, 1 * self.ureg.delta_degK) + self.assertEqual(yf - xk, 1 * self.ureg.delta_degK) + self.assertEqual(yc - xk, 1 * self.ureg.delta_degK) diff --git a/pint/unit.py b/pint/unit.py index ac2490a..e0996f1 100644 --- a/pint/unit.py +++ b/pint/unit.py @@ -388,9 +388,11 @@ class UnitRegistry(object): Empty to load the default definition file. None to leave the UnitRegistry empty. :param force_ndarray: convert any input, scalar or not to a numpy.ndarray. + :param default_to_delta: In the context of a multiplication of units, interpret + non-multiplicative units as their *delta* counterparts. """ - def __init__(self, filename='', force_ndarray=False): + def __init__(self, filename='', force_ndarray=False, default_to_delta=True): self.Quantity = build_quantity_class(self, force_ndarray) #: Map dimension name (string) to its definition (DimensionDefinition). @@ -405,6 +407,10 @@ class UnitRegistry(object): #: Map suffix name (string) to canonical , and unit alias to canonical unit name self._suffixes = {'': None, 's': ''} + #: In the context of a multiplication of units, interpret + #: non-multiplicative units as their *delta* counterparts. + self.default_to_delta = default_to_delta + if filename == '': # Purposefully *not* using resource_stream as it may return a StringIO object for which we can't specify the encoding data = pkg_resources.resource_string(__name__, 'default_en.txt').decode('utf-8') @@ -694,7 +700,7 @@ class UnitRegistry(object): self._units[name].name, self._suffixes[suffix]) - def parse_units(self, input_string, to_delta=True): + def parse_units(self, input_string, to_delta=None): """Parse a units expression and returns a UnitContainer with the canonical names. @@ -707,6 +713,9 @@ class UnitRegistry(object): :class:`pint.UndefinedUnitError` if a unit is not in the registry :class:`ValueError` if the expression is invalid. """ + if to_delta is None: + to_delta = self.default_to_delta + if not input_string: return UnitsContainer()