Skip to content

Commit d513bc2

Browse files
committed
DOC: Merge units doc page into units tutorial
1 parent f3d292f commit d513bc2

File tree

2 files changed

+121
-169
lines changed

2 files changed

+121
-169
lines changed

docs/userguide/units.rst

Lines changed: 0 additions & 125 deletions
This file was deleted.

tutorials/unit_tutorial.py

Lines changed: 121 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,131 @@
22
# Distributed under the terms of the BSD 3-Clause License.
33
# SPDX-License-Identifier: BSD-3-Clause
44
"""
5-
==============
6-
Units Tutorial
7-
==============
5+
==================
6+
Working With Units
7+
==================
88
99
Early in our scientific careers we all learn about the importance of paying
1010
attention to units in our calculations. Unit conversions can still get the best
1111
of us and have caused more than one major technical disaster, including the
1212
crash and complete loss of the $327 million Mars Climate Orbiter.
1313
14-
In MetPy, we use the pint library and a custom unit registry to help prevent
14+
In MetPy, we use the :mod:`pint` library and a custom unit registry to help prevent
1515
unit mistakes in calculations. That means that every quantity you pass to MetPy
1616
should have units attached, just like if you were doing the calculation on
17-
paper!
18-
19-
In MetPy units are attached by multiplying them with the integer, float, array,
20-
etc. In this tutorial we'll show some examples of working with units and get
21-
you on your way to utilizing the computation functions in MetPy.
17+
paper! This simplifies the MetPy API by eliminating the need to specify units
18+
various functions. Instead, only the final results need to be converted to desired units. For
19+
more information on unit support, see the documentation for
20+
`Pint <http://pint.readthedocs.io>`_. Particular attention should be paid to the support
21+
for `temperature units <https://pint.readthedocs.io/en/latest/nonmult.html>`_.
22+
23+
In this tutorial we'll show some examples of working with units and get you on your way to
24+
utilizing the computation functions in MetPy.
2225
"""
2326

27+
#########################################################################
28+
# Getting Started
29+
# ---------------
30+
# To use units, the first step is to import the default MetPy units registry from the
31+
# :mod:`~metpy.units` module:
32+
2433
import numpy as np
2534

2635
from metpy.units import units
2736

2837
#########################################################################
29-
# Simple Calculation
30-
# ------------------
38+
# The unit registry encapsulates all of the available units, as well as any pertinent settings.
39+
# The registry also understands unit prefixes and suffixes; this allows the registry to
40+
# understand ``'kilometer'`` and ``'meters'`` in addition to the base ``'meter'`` unit.
41+
#
42+
# In general, using units is only a small step on top of using the :class:`numpy.ndarray`
43+
# object.
44+
#
45+
# Adding Units to Data
46+
# --------------------
47+
# The easiest way to attach units to an array (or integer, float, etc.) is to multiply by the
48+
# units:
49+
50+
distance = np.arange(1, 5) * units.meters
51+
52+
#########################################################################
53+
# It is also possible to directly construct a :class:`pint.Quantity`, with a full units string:
54+
55+
time = units.Quantity(np.arange(2, 10, 2), 'sec')
56+
57+
#########################################################################
58+
# Compound units can be constructed by the direct mathematical operations necessary:
59+
60+
g = 9.81 * units.meter / (units.second * units.second)
61+
62+
#########################################################################
63+
# This verbose syntax can be reduced by using the unit registry's support for parsing units:
64+
65+
g = 9.81 * units('m/s^2')
66+
67+
#########################################################################
68+
# Operations With Units
69+
# ---------------------
70+
# With units attached, it is possible to perform mathematical operations, resulting in the
71+
# proper units:
72+
73+
print(distance / time)
74+
75+
#########################################################################
76+
# For multiplication and division, units can combine and cancel. For addition and subtraction,
77+
# instead the operands must have compatible units. For instance, this works:
78+
79+
print(distance + distance)
80+
81+
#########################################################################
82+
# But for instance, `distance + time` would not work; instead it gives an error:
83+
#
84+
# `DimensionalityError: Cannot convert from 'meter' ([length]) to 'second' ([time])`
3185
#
32-
# Let's say we want to calculate the area of a rectangle. It so happens that
33-
# one of our colleagues measures their side of the rectangle in imperial units
34-
# and the other in metric units. No problem! First we need to attach units to
35-
# our measurements. For many units the easiest way is by find the unit as an
36-
# attribute of the unit registry:
86+
# Even if the units are not identical, as long as they are dimensionally equivalent, the
87+
# operation can be performed:
3788

38-
length = 10.4 * units.inches
39-
width = 20 * units.meters
40-
print(length, width)
89+
print(3 * units.inch + 5 * units.cm)
4190

4291
#########################################################################
43-
# Don't forget that you can use tab completion to see what units are available!
44-
# Just about every imaginable quantity is there, but if you find one that isn't,
45-
# we're happy to talk about adding it.
92+
# Converting Units
93+
# ----------------
4694
#
47-
# While it may seem like a lot of trouble, let's compute the area of a rectangle
48-
# defined by our length and width variables above. Without units attached, you'd
49-
# need to remember to perform a unit conversion before multiplying or you would
50-
# end up with an area in inch-meters and likely forget about it. With units
51-
# attached, the units are tracked for you.
95+
# Converting a :class:`~pint.Quantity` between units can be accomplished by using the
96+
# :meth:`~pint.Quantity.to` method call, which constructs a new :class:`~pint.Quantity` in the
97+
# desired units:
5298

53-
area = length * width
54-
print(area)
99+
print((1 * units.inch).to(units.mm))
55100

56101
#########################################################################
57-
# That's great, now we have an area, but it is not in a very useful unit still.
58-
# Units can be converted using the `to()` method. While you won't see square meters in
59-
# the units list, we can parse complex/compound units as strings:
102+
# There is also the :meth:`~pint.Quantity.ito` method which performs the same operation
103+
# in-place:
60104

105+
a = np.arange(5.) * units.meter
106+
a.ito('feet')
107+
print(a)
108+
109+
#########################################################################
110+
# To simplify units, there is also the :meth:`~pint.Quantity.to_base_units` method,
111+
# which converts a quantity to SI units, performing any needed cancellation:
112+
113+
Lf = 3.34e6 * units('J/kg')
114+
print(Lf, Lf.to_base_units(), sep='\n')
115+
116+
#########################################################################
117+
# :meth:`~pint.Quantity.to_base_units` can also be done in-place via the
118+
# :meth:`~pint.Quantity.ito_base_units` method.
119+
#
120+
# By default Pint does not do any more than simple unit simplification, so when you perform
121+
# operations you could get some seemingly odd results:
122+
123+
l = 10.4 * units.inch
124+
w = 5 * units.cm
125+
area = l * w
126+
print(area)
127+
128+
#########################################################################
129+
# This is another place where :meth:`~pint.Quantity.to` comes in handy:
61130
print(area.to('m^2'))
62131

63132
#########################################################################
@@ -103,28 +172,36 @@
103172
print(273 * units.kelvin - 10 * units.kelvin)
104173

105174
#########################################################################
175+
# MetPy Calculations
176+
# ------------------
177+
# All MetPy calculations are unit-aware and rely on this information to ensure
178+
# that the calculations operate correctly. For example, we can use units to take
179+
# an observation in whatever units are most convenient and let MetPy handle everything
180+
# under the hood. Below we calculate dewpoint from the temperature and relative humidity:
106181

107-
#########################################################################
108-
# Compound Units
109-
# --------------
110-
# We can create compound units for things like speed by parsing a string of
111-
# units. Abbreviations or full unit names are acceptable.
182+
import metpy.calc as mpcalc
183+
184+
temperature = 73.2 * units.degF
185+
rh = 64 * units.percent
186+
dewpoint = mpcalc.dewpoint_from_relative_humidity(temperature, rh)
112187

113-
u = np.random.randint(0, 15, 10) * units('m/s')
114-
v = np.random.randint(0, 15, 10) * units('meters/second')
188+
print(dewpoint)
189+
190+
#########################################################################
191+
# or back to Fahrenheit:
115192

116-
print(u)
117-
print(v)
193+
print(dewpoint.to('degF'))
118194

119195
#########################################################################
120196
# Common Mistakes
121197
# ---------------
122198
# There are a few common mistakes the new users often make. Be sure to check
123-
# these when you're having issues
199+
# these when you're having issues.
124200
#
125201
# * Pressure units are `mbar` or `hPa` for common atmospheric measurements. The
126-
# unit `mb` is actually millibarns.
202+
# unit `mb` is actually millibarns--a unit used in particle physics.
127203
# * When using masked arrays, units must be multiplied on the left side. This
128204
# will be addressed in the future, but is a current limitation in the
129205
# ecosystem. The expected error will be
130-
# `AttributeError: 'MaskedArray' object has no attribute 'units'`
206+
# `AttributeError: 'MaskedArray' object has no attribute 'units'` or calculation
207+
# functions complaining about expecting a units and getting "dimensionless".

0 commit comments

Comments
 (0)