{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "
\n", "

MetPy’s Choice of Unit Support:
A Descent into Madness

\n", "
\n", "

14 July 2017\n", "
\n", "
\n", "Ryan May (@dopplershift)\n", "
\n", "John Leeman (@geo_leeman)\n", "

\n", "UCAR/Unidata

\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# MetPy\n", "\n", "- Community toolkit for solving meteorology and atmospheric science problems\n", "- Plotting\n", "- File Formats\n", "- **Calculations**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Units?\n", "- Handling of physical quantities (aka. \"units\") important in scientific applications" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ ">The MCO MIB has determined that the root cause for the loss of the MCO spacecraft was the failure to use metric units in the coding of a ground software file, “Small Forces,” used in trajectory models. Specifically, thruster performance data in English units instead of metric units was used in the software application code titled SM_FORCES (small forces)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- To avoid these problems, part of MetPy's core architecture is the use of a unit library, Pint\n", "- Simplifies documentation\n", "- Eliminates manual auditing of units in calculation functions\n", "- Supports data files with arbitrary units (e.g. netCDF) more easily" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "![tire swing](./TS-57566978_Boy-on-tire-swing_v.jpg.rend.hgtvcom.616.822.jpeg)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Pint?\n", "- Pure Python unit-handling library\n", "- Wraps Python scalars, lists, or NumPy arrays\n", "- Supports units using offsets (i.e. temperature)\n", "- Alternatives:\n", " - `astropy.units`\n", " - `quantities`\n", " - `cf_units`\n", " - Many others" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Example usage" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "import astropy.units as aunits" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "64.56301588685112 degF" ], "text/latex": [ "$64.56301588685112\\ \\mathrm{degF}$" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import metpy.calc as mpcalc\n", "from metpy.units import units\n", "\n", "temperature = 75 * units.degF\n", "relative_humidity = 70 * units.percent\n", "mpcalc.dewpoint_rh(temperature, relative_humidity).to('degF')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Without Pint" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "```python\n", "from scipy.constants import convert_temperature\n", "temperature = convert_temperature(75, 'F', 'C')\n", "relative_humidity = 0.7\n", "convert_temperature(mpcalc.dewpoint_rh(temperature,\n", " relative_humidity), 'C', 'F')\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "![Disgusted Clint](clint.gif)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# The End\n", "- Everything just works!" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "6.0560018454768532" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from metpy.constants import Rd\n", "import numpy as np\n", "\n", "t_diff = (np.random.randn(10) * units.degC -\n", " np.random.randn(10) * units.degC)\n", "np.trapz(t_diff)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "![fire tire](fire-tire.gif)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# The End--of sanity\n", "- ~~Everything just works!~~" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- The only thing worse than not using a unit library..." ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "fragment" } }, "source": [ "- ...is trying to use one with Python libraries expecting numpy arrays" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Everything I show broken here is *also* broken for `astropy.units`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# NumPy/SciPy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Let's start with concatenate" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 3., 4.])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([3.])\n", "b = np.array([4.])\n", "np.concatenate((a, b))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Now what about with units?" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 3., 4.])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([3.]) * units.m\n", "b = np.array([4.]) * units.m\n", "np.concatenate((a, b))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Units dropped because numpy creates a new array for storage\n", "- No way for subclasses/array-like to declare how to make a new instance\n", "- NumPy #4164" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Maybe calculating a gradient?" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 10., 10., 10., 10., 10.])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "a = np.arange(5)\n", "np.gradient(a, 0.1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "With units?" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "TypeError", "evalue": "object of type 'float' has no len()", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdegC\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgradient\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0.1\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mm\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m~/miniconda3/envs/py36/lib/python3.6/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36mgradient\u001b[0;34m(f, *varargs, **kwargs)\u001b[0m\n\u001b[1;32m 1692\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misscalar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdistances\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1693\u001b[0m \u001b[0;32mcontinue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1694\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdistances\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1695\u001b[0m raise ValueError(\"distances must be either scalars or match \"\n\u001b[1;32m 1696\u001b[0m \"the length of the corresponding dimension\")\n", "\u001b[0;32m~/miniconda3/envs/py36/lib/python3.6/site-packages/pint/quantity.py\u001b[0m in \u001b[0;36m__len__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1246\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1247\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__len__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1248\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_magnitude\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1249\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1250\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__iter__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: object of type 'float' has no len()" ] } ], "source": [ "a = np.arange(5) * units.degC\n", "np.gradient(a, 0.1 * units.m)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- `np.isscalar()` for a float with units attached returns `False`" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "source": [ "## Interpolating: `numpy.interp()`" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "1.5" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = np.arange(5)\n", "y = x\n", "np.interp(1.5, x, y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "With units?" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "ValueError", "evalue": "object of too small depth for desired array", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mm\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minterp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1.5\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m~/miniconda3/envs/py36/lib/python3.6/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36minterp\u001b[0;34m(x, xp, fp, left, right, period)\u001b[0m\n\u001b[1;32m 2037\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0minterp_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mleft\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mright\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitem\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2038\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2039\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0minterp_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mleft\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mright\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2040\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2041\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: object of too small depth for desired array" ] } ], "source": [ "x = np.arange(5) * units.m\n", "y = x\n", "np.interp(1.5 * units.m, x, y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- There's no way the average user is going to figure that out\n", "- Disappears into C code, so not sure where the problem lies..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## What about using scipy optimization?\n", "- Fixed point iteration `scipy.optimize.fixed_point`\n", "- Uses other calculations that need units" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "from scipy.optimize import fixed_point\n", "def step(p, p0, w, t):\n", " td = dewpoint(vapor_pressure(p, w))\n", " return (p0 * (td / t) ** (1. / kappa))\n", "\n", "fp = so.fixed_point(step, pressure,\n", " args=(pressure, w, temperature))\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Nope, that doesn't work..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "```python\n", "from scipy.optimize import fixed_point\n", "def step(p, p0, w, t):\n", " td = dewpoint(vapor_pressure(units.Quantity(p, pressure.units), w))\n", " return (p0 * (td / t) ** (1. / kappa)).magnitude\n", "\n", "fp = so.fixed_point(step, pressure.magnitude,\n", " args=(pressure.magnitude, w, temperature))\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Need to drop units when going into scipy code..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- ...and reattach before going into MetPy code.\n", "![I'm Cool](im_cool.gif)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Mitigation\n", "- Drop units as necessary when calling functions...\n", "- ...and reattach correct units on the way out\n", "- Essentially subverting all of the unit-handling\n", "- Not *so* bad if we're hiding inside calculation functions" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Matplotlib" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `Plot()`\n", "- Plotting with masked arrays in matplotlib\n", "- Breaks up line nicely around missing points" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "First with units:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nYCcIgmgx/i948UHevBMhLAAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "temp_data = np.random.randn(50)\n", "temp_units = temp_data * units.degC\n", "t = np.linspace(0, 5, 50)\n", "plt.plot(t, temp_units)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Looks good" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now masked arrays, no units:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "temp_masked = np.ma.masked_array(temp_data, mask=temp_data<0)\n", "plt.plot(t, temp_masked)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "- Ok, that's fine" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now what about masked *and* units?" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nB3fGGGtA/x8YO+l8/kPcXgAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "temp_units_masked = temp_masked * units.degC\n", "plt.plot(t, temp_units_masked)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "\"No\n", "\n", "
    \n", "
  • I have no idea what's going on here
  • \n", "
  • The filling is *not* the original values
  • \n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## `axhline()`/`axvline()`\n", "- Horizontal/Vertical line spanning the entire axis\n", "- Matplotlib has built-in support for unit conversions\n", "- In theory, allows plotting data with one unit but request axes in another\n", "- Let's see how this works" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "plt.axhline(0 * units.degC)\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "```pytb\n", "ValueError: Cannot compare Quantity and \n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Problem is comparison between plotted value and plot limits\n", "- Enabling Matplotlib's unit-conversion behavior doesn't help\n", "- There is literally no code path through that allows the proper comparison with unit-ed values" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Mitigation\n", "- Register with matplotlib's unit-handling..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- ...but use that to automatically drop units for every plotting function\n", "![Bang Computer](beating_computer.gif)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Xarray" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Xarray provides labeled axes for nd-grids\n", "- Sort of works with units?" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/html": [ "array([1, 2, 3])Coordinates: * x (x) int64 1 2 3 meter" ], "text/latex": [ "$array([1, 2, 3])Coordinates: * x (x) int64 1 2 3\\ \\mathrm{meter}$" ], "text/plain": [ "\n", "array([1, 2, 3])\n", "Coordinates:\n", " * x (x) int64 1 2 3, 'meter')>" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import xarray as xr\n", "data = xr.DataArray([1, 2, 3], dims=('x',), coords={'x':[1, 2, 3]})\n", "units.m * data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Ok, but I'm not wild about meters being next to the coordinate values" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Putting units to the right of the data looks more reasonable (to me):" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "\n", "array([1, 2, 3])\n", "Coordinates:\n", " * x (x) int64 1 2 3" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data * units.m" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Oh come on.\n", "\n", "![Head Smash](perry-headsmash.gif)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- One way uses `pint.Quantity.__add__`\n", "- The other `xarray.DataArray.__add__`\n", "- I will **not** teach users that the order of multiplication matters" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# The end of the story\n", "- This is the current state of things\n", "- There is no happy ending here--I don't have any implemented solutions" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Core problems:\n", " - `np.(as)array` == \"Please silently discard my units\"\n", " - Uses:\n", " - Convert lists/floats to array\n", " - Make sure something supports math and slicing\n", " - Enforce compatibility with numpy C-API\n", " - Things that *should* be considered arrays aren't\n", " - Other array-managing libraries need to know about your need for units\n", " - `np.asanyarray` only helps for subclasses" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Possible solutions\n", "- NumPy's new `__array_ufunc__` support\n", " - Available in numpy 1.13\n", " - Improves overriding behavior for ufuncs\n", " - Not how this plays out for operand order problem (like xarray example)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- NumPy Abstract Base Class(es) (ABCs)\n", " - Allow other array-like classes to declare they implement certain interface\n", " - Create separate ABCs for portions of numpy interface\n", " - `numpy.asarray` can perform `isinstance` check with (one) ABC\n", " - Will require downstream libraries to migrate away from `asarray` for other ABCs\n", " - Not sure how this plays with composition between array-like libraries" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Custom NumPy dtypes\n", " - Modify NumPy C-level code to allow custom datatypes\n", " - Encode units as part of datatype--then units don't drop\n", " - Would *probably* solve all of the problems\n", " - Most technically challenging" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "source": [ "# Concluding\n", "- The user experience when trying to substitute for numpy arrays with a unit-ed array is pretty frustrating\n", "- There **has** to be a way to make this work better\n", "- I'm open to suggestions (besides removing our unit support)\n", "- I'm not here to rag on anyone's work, this comes from a place of love..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- ...and immense frustration\n", "![Nerd Rage](nerdrage.gif)" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python [conda env:py36]", "language": "python", "name": "conda-env-py36-py" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.1" } }, "nbformat": 4, "nbformat_minor": 2 }