.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials/unit_tutorial.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorials_unit_tutorial.py: ================== Working With Units ================== Early in our scientific careers we all learn about the importance of paying attention to units in our calculations. Unit conversions can still get the best of us and have caused more than one major technical disaster, including the crash and complete loss of the $327 million Mars Climate Orbiter. In MetPy, we use the ``pint`` library and a custom unit registry to help prevent unit mistakes in calculations. That means that every quantity you pass to MetPy should have units attached, just like if you were doing the calculation on paper! This simplifies the MetPy API by eliminating the need to specify units various functions. Instead, only the final results need to be converted to desired units. For more information on unit support, see the documentation for `Pint `_. Particular attention should be paid to the support for `temperature units `_. In this tutorial we'll show some examples of working with units and get you on your way to utilizing the computation functions in MetPy. .. GENERATED FROM PYTHON SOURCE LINES 28-32 Getting Started --------------- To use units, the first step is to import the default MetPy units registry from the :mod:`~metpy.units` module: .. GENERATED FROM PYTHON SOURCE LINES 32-37 .. code-block:: Python import numpy as np import metpy.calc as mpcalc from metpy.units import units .. GENERATED FROM PYTHON SOURCE LINES 38-49 The unit registry encapsulates all of the available units, as well as any pertinent settings. The registry also understands unit prefixes and suffixes; this allows the registry to understand ``'kilometer'`` and ``'meters'`` in addition to the base ``'meter'`` unit. In general, using units is only a small step on top of using the :class:`numpy.ndarray` object. Adding Units to Data -------------------- The easiest way to attach units to an array (or integer, float, etc.) is to multiply by the units: .. GENERATED FROM PYTHON SOURCE LINES 49-51 .. code-block:: Python distance = np.arange(1, 5) * units.meters .. GENERATED FROM PYTHON SOURCE LINES 52-53 It is also possible to directly construct a :class:`pint.Quantity`, with a full units string: .. GENERATED FROM PYTHON SOURCE LINES 53-55 .. code-block:: Python time = units.Quantity(np.arange(2, 10, 2), 'sec') .. GENERATED FROM PYTHON SOURCE LINES 56-57 Compound units can be constructed by the direct mathematical operations necessary: .. GENERATED FROM PYTHON SOURCE LINES 57-59 .. code-block:: Python 9.81 * units.meter / (units.second * units.second) .. raw:: html
9.81 meter/second2


.. GENERATED FROM PYTHON SOURCE LINES 60-61 This verbose syntax can be reduced by using the unit registry's support for parsing units: .. GENERATED FROM PYTHON SOURCE LINES 61-63 .. code-block:: Python 9.81 * units('m/s^2') .. raw:: html
9.81 meter/second2


.. GENERATED FROM PYTHON SOURCE LINES 64-68 Operations With Units --------------------- With units attached, it is possible to perform mathematical operations, resulting in the proper units: .. GENERATED FROM PYTHON SOURCE LINES 68-70 .. code-block:: Python print(distance / time) .. rst-class:: sphx-glr-script-out .. code-block:: none [0.5 0.5 0.5 0.5] meter / second .. GENERATED FROM PYTHON SOURCE LINES 71-73 For multiplication and division, units can combine and cancel. For addition and subtraction, instead the operands must have compatible units. For instance, this works: .. GENERATED FROM PYTHON SOURCE LINES 73-75 .. code-block:: Python print(distance + distance) .. rst-class:: sphx-glr-script-out .. code-block:: none [2 4 6 8] meter .. GENERATED FROM PYTHON SOURCE LINES 76-82 But for instance, `distance + time` would not work; instead it gives an error: `DimensionalityError: Cannot convert from 'meter' ([length]) to 'second' ([time])` Even if the units are not identical, as long as they are dimensionally equivalent, the operation can be performed: .. GENERATED FROM PYTHON SOURCE LINES 82-84 .. code-block:: Python print(3 * units.inch + 5 * units.cm) .. rst-class:: sphx-glr-script-out .. code-block:: none 4.968503937007874 inch .. GENERATED FROM PYTHON SOURCE LINES 85-86 ``pint`` by default will print full unit names for :class:`~pint.Quantity`. .. GENERATED FROM PYTHON SOURCE LINES 86-88 .. code-block:: Python print(f'{20 * units.meter ** 2}') .. rst-class:: sphx-glr-script-out .. code-block:: none 20 meter ** 2 .. GENERATED FROM PYTHON SOURCE LINES 89-90 This can be reduced to symbolic by specifying a compact (~) formatter: .. GENERATED FROM PYTHON SOURCE LINES 90-92 .. code-block:: Python print(f'{20 * units.meter ** 2:~}') .. rst-class:: sphx-glr-script-out .. code-block:: none 20 m ** 2 .. GENERATED FROM PYTHON SOURCE LINES 93-94 A compact (~), pretty (P) formatter: .. GENERATED FROM PYTHON SOURCE LINES 94-96 .. code-block:: Python print(f'{20 * units.meter ** 2:~P}') .. rst-class:: sphx-glr-script-out .. code-block:: none 20 m² .. GENERATED FROM PYTHON SOURCE LINES 97-98 Place formatters following other print specifications: .. GENERATED FROM PYTHON SOURCE LINES 98-100 .. code-block:: Python print(f'{20 * units.meter ** 2:0.3f~P}') .. rst-class:: sphx-glr-script-out .. code-block:: none 20.000 m² .. GENERATED FROM PYTHON SOURCE LINES 101-103 Other string formatting options are available, see the `Pint string formatting specification `_. .. GENERATED FROM PYTHON SOURCE LINES 105-111 Converting Units ---------------- Converting a :class:`~pint.Quantity` between units can be accomplished by using the :meth:`~pint.Quantity.to` method call, which constructs a new :class:`~pint.Quantity` in the desired units: .. GENERATED FROM PYTHON SOURCE LINES 111-114 .. code-block:: Python print((1 * units.inch).to(units.mm)) .. rst-class:: sphx-glr-script-out .. code-block:: none 25.4 millimeter .. GENERATED FROM PYTHON SOURCE LINES 115-117 There is also the :meth:`~pint.Quantity.ito` method which performs the same operation in-place: .. GENERATED FROM PYTHON SOURCE LINES 117-121 .. code-block:: Python a = np.arange(5.) * units.meter a.ito('feet') print(a) .. rst-class:: sphx-glr-script-out .. code-block:: none [0.0 3.2808398950131235 6.561679790026247 9.84251968503937 13.123359580052494] foot .. GENERATED FROM PYTHON SOURCE LINES 122-124 To simplify units, there is also the :meth:`~pint.Quantity.to_base_units` method, which converts a quantity to SI units, performing any needed cancellation: .. GENERATED FROM PYTHON SOURCE LINES 124-127 .. code-block:: Python Lf = 3.34e6 * units('J/kg') print(Lf, Lf.to_base_units(), sep='\n') .. rst-class:: sphx-glr-script-out .. code-block:: none 3340000.0 joule / kilogram 3340000.0 meter ** 2 / second ** 2 .. GENERATED FROM PYTHON SOURCE LINES 128-133 :meth:`~pint.Quantity.to_base_units` can also be done in-place via the :meth:`~pint.Quantity.ito_base_units` method. By default Pint does not do any more than simple unit simplification, so when you perform operations you could get some seemingly odd results: .. GENERATED FROM PYTHON SOURCE LINES 133-138 .. code-block:: Python length = 10.4 * units.inch width = 5 * units.cm area = length * width print(area) .. rst-class:: sphx-glr-script-out .. code-block:: none 52.0 centimeter * inch .. GENERATED FROM PYTHON SOURCE LINES 139-140 This is another place where :meth:`~pint.Quantity.to` comes in handy: .. GENERATED FROM PYTHON SOURCE LINES 140-142 .. code-block:: Python print(area.to('m^2')) .. rst-class:: sphx-glr-script-out .. code-block:: none 0.013208 meter ** 2 .. GENERATED FROM PYTHON SOURCE LINES 143-165 Temperature ----------- Temperature units are actually relatively tricky (more like absolutely tricky as you'll see). Temperature is a non-multiplicative unit - they are in a system with a reference point. That means that not only is there a scaling factor, but also an offset. This makes the math and unit book-keeping a little more complex. Imagine adding 10 degrees Celsius to 100 degrees Celsius. Is the answer 110 degrees Celsius or 383.15 degrees Celsius (283.15 K + 373.15 K)? That's why there are delta degrees units in the unit registry for offset units. For more examples and explanation you can watch MetPy Monday #13: https://www.youtube.com/watch?v=iveJCqxe3Z4. Let's take a look at how this works and fails: We would expect this to fail because we cannot add two offset units (and it does fail as an "Ambiguous operation with offset unit"). `10 * units.degC + 5 * units.degC` On the other hand, we can subtract two offset quantities and get a delta. A delta unit is pint's way of representing a relative change in two offset units, indicating that this is not an absolute value of 5 degrees Celsius, but a relative change of 5 degrees Celsius. .. GENERATED FROM PYTHON SOURCE LINES 165-167 .. code-block:: Python print(10 * units.degC - 5 * units.degC) .. rst-class:: sphx-glr-script-out .. code-block:: none 5 delta_degree_Celsius .. GENERATED FROM PYTHON SOURCE LINES 168-169 We can add a delta to an offset unit as well since it is a relative change. .. GENERATED FROM PYTHON SOURCE LINES 169-171 .. code-block:: Python print(25 * units.degC + 5 * units.delta_degF) .. rst-class:: sphx-glr-script-out .. code-block:: none 27.77777777777778 degree_Celsius .. GENERATED FROM PYTHON SOURCE LINES 172-175 Absolute temperature scales like Kelvin and Rankine do not have an offset and therefore can be used in addition/subtraction without the need for a delta version of the unit. .. GENERATED FROM PYTHON SOURCE LINES 175-177 .. code-block:: Python print(273 * units.kelvin + 10 * units.kelvin) .. rst-class:: sphx-glr-script-out .. code-block:: none 283 kelvin .. GENERATED FROM PYTHON SOURCE LINES 178-180 .. code-block:: Python print(273 * units.kelvin - 10 * units.kelvin) .. rst-class:: sphx-glr-script-out .. code-block:: none 263 kelvin .. GENERATED FROM PYTHON SOURCE LINES 181-187 MetPy Calculations ------------------ All MetPy calculations are unit-aware and rely on this information to ensure that the calculations operate correctly. For example, we can use units to take an observation in whatever units are most convenient and let MetPy handle everything under the hood. Below we calculate dewpoint from the temperature and relative humidity: .. GENERATED FROM PYTHON SOURCE LINES 187-193 .. code-block:: Python temperature = 73.2 * units.degF rh = 64 * units.percent dewpoint = mpcalc.dewpoint_from_relative_humidity(temperature, rh) print(dewpoint) .. rst-class:: sphx-glr-script-out .. code-block:: none 15.726236381245258 degree_Celsius .. GENERATED FROM PYTHON SOURCE LINES 194-195 or back to Fahrenheit: .. GENERATED FROM PYTHON SOURCE LINES 195-197 .. code-block:: Python print(dewpoint.to('degF')) .. rst-class:: sphx-glr-script-out .. code-block:: none 60.3072254862414 degree_Fahrenheit .. GENERATED FROM PYTHON SOURCE LINES 198-204 Dropping Units -------------- While units are part of the MetPy ecosystem, they can be a headache after we have computed the desired quantities with MetPy and would like to move on. For example, we might have computed the dewpoint temperature for two points, say A and B, and would like to compute the average: .. GENERATED FROM PYTHON SOURCE LINES 204-212 .. code-block:: Python temperature_a = 73.2 * units.degF rh_a = 64 * units.percent dewpoint_a = mpcalc.dewpoint_from_relative_humidity(temperature_a, rh_a) temperature_b = 71.1 * units.degF rh_b = 52 * units.percent dewpoint_b = mpcalc.dewpoint_from_relative_humidity(temperature_b, rh_b) .. GENERATED FROM PYTHON SOURCE LINES 213-216 Per our previous discussion on temperature units, adding two temperatures together won't work. In this case, the easiest way to add two quantities and compute an average is by dropping the units attached to the values via ``.magnitude``: .. GENERATED FROM PYTHON SOURCE LINES 216-218 .. code-block:: Python print(dewpoint_b.magnitude) .. rst-class:: sphx-glr-script-out .. code-block:: none 11.445590005179099 .. GENERATED FROM PYTHON SOURCE LINES 219-222 .. code-block:: Python dewpoint_mean = (dewpoint_a.magnitude + dewpoint_b.magnitude) / 2. print(dewpoint_mean) .. rst-class:: sphx-glr-script-out .. code-block:: none 13.585913193212178 .. GENERATED FROM PYTHON SOURCE LINES 223-235 Common Mistakes --------------- There are a few common mistakes the new users often make. Be sure to check these when you're having issues. * Pressure units are `mbar` or `hPa` for common atmospheric measurements. The unit `mb` is actually millibarns--a unit used in particle physics. * When using masked arrays, units must be multiplied on the left side. This will be addressed in the future, but is a current limitation in the ecosystem. The expected error will be `AttributeError: 'MaskedArray' object has no attribute 'units'` or calculation functions complaining about expecting a units and getting "dimensionless". .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.012 seconds) .. _sphx_glr_download_tutorials_unit_tutorial.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: unit_tutorial.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: unit_tutorial.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: unit_tutorial.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_