From 802cc84a32b925936e14bbab63d031618094a4af Mon Sep 17 00:00:00 2001 From: dcherian Date: Mon, 16 Dec 2019 09:10:18 -0700 Subject: [PATCH 1/4] apply_ufunc vectorize 1D function example --- ci/requirements/doc.yml | 1 + doc/examples.rst | 7 + doc/examples/apply_ufunc_vectorize_1d.ipynb | 2296 +++++++++++++++++++ doc/whats-new.rst | 3 + 4 files changed, 2307 insertions(+) create mode 100644 doc/examples/apply_ufunc_vectorize_1d.ipynb diff --git a/ci/requirements/doc.yml b/ci/requirements/doc.yml index a0c27a30b01..1b479ad4ca2 100644 --- a/ci/requirements/doc.yml +++ b/ci/requirements/doc.yml @@ -14,6 +14,7 @@ dependencies: - jupyter_client - nbsphinx - netcdf4 + - numba - numpy - numpydoc - pandas<0.25 # Hack around https://github.com/pydata/xarray/issues/3369 diff --git a/doc/examples.rst b/doc/examples.rst index ce56102cc9d..b58fa986fda 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -10,3 +10,10 @@ Examples examples/visualization_gallery examples/ROMS_ocean_model examples/ERA5-GRIB-example + +apply_ufunc +------------ +.. toctree:: + :maxdepth: 2 + + examples/apply_ufunc_vectorize_1d diff --git a/doc/examples/apply_ufunc_vectorize_1d.ipynb b/doc/examples/apply_ufunc_vectorize_1d.ipynb new file mode 100644 index 00000000000..fa41271f206 --- /dev/null +++ b/doc/examples/apply_ufunc_vectorize_1d.ipynb @@ -0,0 +1,2296 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Applying unvectorized functions with `apply_ufunc`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This example will illustrate how to conveniently apply an unvectorized function to xarray objects using `apply_ufunc`. This function will expect 1D numpy arrays and return a 1D numpy array. Our goal is to coveniently apply this function over xarray objects that may or may not wrap dask arrays.\n", + "\n", + "First lets load an example dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:21:52.494131Z", + "start_time": "2019-12-16T16:21:52.411269Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "Show/Hide data repr\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Show/Hide attributes\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
xarray.DataArray
'air'
  • time: 4
  • lat: 25
  • lon: 3
  • 296.29 296.79 297.1 295.9 ... 244.2 241.89 241.79999 241.79999
    array([[[296.29   , 296.79   , 297.1    ],\n",
    +       "        [295.9    , 296.19998, 296.79   ],\n",
    +       "        [296.6    , 296.19998, 296.4    ],\n",
    +       "        [297.     , 296.69998, 296.1    ],\n",
    +       "        [295.4    , 295.69998, 295.79   ],\n",
    +       "        [293.79   , 294.1    , 294.6    ],\n",
    +       "        [293.1    , 293.29   , 293.29   ],\n",
    +       "        [290.19998, 290.79   , 291.4    ],\n",
    +       "        [287.9    , 288.     , 288.29   ],\n",
    +       "        [286.5    , 286.5    , 285.69998],\n",
    +       "        [284.6    , 284.9    , 284.19998],\n",
    +       "        [282.79   , 283.19998, 282.6    ],\n",
    +       "        [280.     , 280.69998, 280.19998],\n",
    +       "        [278.4    , 279.     , 279.     ],\n",
    +       "        [277.29   , 277.4    , 277.79   ],\n",
    +       "        [276.69998, 277.4    , 277.69998],\n",
    +       "        [275.9    , 276.9    , 276.9    ],\n",
    +       "        [274.79   , 275.19998, 275.6    ],\n",
    +       "        [273.69998, 273.6    , 273.79   ],\n",
    +       "        [272.1    , 270.9    , 270.     ],\n",
    +       "        [274.5    , 274.29   , 274.1    ],\n",
    +       "        [266.5    , 267.1    , 267.1    ],\n",
    +       "        [250.     , 249.79999, 248.89   ],\n",
    +       "        [243.79999, 244.5    , 244.7    ],\n",
    +       "        [241.2    , 242.5    , 243.5    ]],\n",
    +       "\n",
    +       "       [[296.29   , 297.19998, 297.4    ],\n",
    +       "        [296.19998, 296.69998, 296.79   ],\n",
    +       "        [296.4    , 295.9    , 296.19998],\n",
    +       "        [295.79   , 295.79   , 296.1    ],\n",
    +       "        [295.1    , 295.79   , 295.79   ],\n",
    +       "        [294.29   , 294.79   , 294.69998],\n",
    +       "        [293.19998, 293.9    , 294.19998],\n",
    +       "        [290.19998, 291.1    , 292.4    ],\n",
    +       "        [287.5    , 288.5    , 289.4    ],\n",
    +       "        [285.69998, 287.4    , 287.1    ],\n",
    +       "        [283.29   , 285.19998, 285.19998],\n",
    +       "        [281.4    , 282.79   , 283.5    ],\n",
    +       "        [279.19998, 280.19998, 280.79   ],\n",
    +       "        [277.79   , 278.5    , 279.29   ],\n",
    +       "        [276.29   , 276.4    , 277.29   ],\n",
    +       "        [275.79   , 276.     , 276.5    ],\n",
    +       "        [275.6    , 276.1    , 276.29   ],\n",
    +       "        [274.     , 274.4    , 275.1    ],\n",
    +       "        [272.1    , 272.69998, 273.19998],\n",
    +       "        [269.19998, 268.5    , 267.6    ],\n",
    +       "        [272.5    , 271.5    , 270.4    ],\n",
    +       "        [269.69998, 269.4    , 268.6    ],\n",
    +       "        [253.2    , 252.89   , 252.09999],\n",
    +       "        [243.59999, 244.09999, 244.2    ],\n",
    +       "        [242.09999, 242.7    , 243.09999]],\n",
    +       "\n",
    +       "       [[296.4    , 296.29   , 296.4    ],\n",
    +       "        [296.19998, 296.5    , 296.29   ],\n",
    +       "        [295.6    , 295.4    , 295.4    ],\n",
    +       "        [295.     , 295.     , 294.9    ],\n",
    +       "        [293.9    , 294.79   , 295.     ],\n",
    +       "        [293.29   , 293.9    , 294.4    ],\n",
    +       "        [292.4    , 292.9    , 293.4    ],\n",
    +       "        [289.5    , 289.79   , 291.19998],\n",
    +       "        [287.     , 287.1    , 288.29   ],\n",
    +       "        [284.9    , 285.6    , 286.4    ],\n",
    +       "        [282.     , 283.29   , 284.69998],\n",
    +       "        [280.     , 280.79   , 282.4    ],\n",
    +       "        [278.6    , 279.1    , 280.     ],\n",
    +       "        [277.6    , 277.9    , 278.6    ],\n",
    +       "        [276.     , 275.79   , 276.6    ],\n",
    +       "        [275.29   , 275.5    , 276.     ],\n",
    +       "        [274.5    , 275.6    , 276.1    ],\n",
    +       "        [274.29   , 275.     , 275.4    ],\n",
    +       "        [275.5    , 275.9    , 275.29   ],\n",
    +       "        [273.     , 273.5    , 272.9    ],\n",
    +       "        [271.9    , 271.79   , 271.6    ],\n",
    +       "        [269.29   , 268.5    , 267.     ],\n",
    +       "        [256.19998, 255.5    , 254.2    ],\n",
    +       "        [244.59999, 244.39   , 244.     ],\n",
    +       "        [242.29999, 242.2    , 242.29999]],\n",
    +       "\n",
    +       "       [[297.5    , 297.69998, 297.5    ],\n",
    +       "        [297.     , 297.5    , 297.1    ],\n",
    +       "        [296.6    , 296.4    , 296.     ],\n",
    +       "        [295.9    , 295.79   , 295.5    ],\n",
    +       "        [294.4    , 295.     , 295.4    ],\n",
    +       "        [293.     , 293.5    , 294.29   ],\n",
    +       "        [291.9    , 291.9    , 292.19998],\n",
    +       "        [289.19998, 289.4    , 289.9    ],\n",
    +       "        [286.6    , 287.1    , 287.9    ],\n",
    +       "        [284.79   , 284.79   , 285.4    ],\n",
    +       "        [282.79   , 282.     , 282.69998],\n",
    +       "        [281.19998, 280.19998, 280.6    ],\n",
    +       "        [279.5    , 278.69998, 278.6    ],\n",
    +       "        [278.     , 277.69998, 277.6    ],\n",
    +       "        [276.4    , 275.9    , 276.4    ],\n",
    +       "        [275.6    , 275.69998, 276.1    ],\n",
    +       "        [274.5    , 275.6    , 276.29   ],\n",
    +       "        [273.4    , 274.5    , 275.5    ],\n",
    +       "        [274.1    , 274.     , 273.5    ],\n",
    +       "        [273.29   , 272.6    , 271.5    ],\n",
    +       "        [272.79   , 272.4    , 271.9    ],\n",
    +       "        [267.69998, 266.29   , 264.4    ],\n",
    +       "        [256.6    , 254.7    , 252.09999],\n",
    +       "        [246.29999, 245.29999, 244.2    ],\n",
    +       "        [241.89   , 241.79999, 241.79999]]], dtype=float32)
    • lat
      (lat)
      float32
      15.0 17.5 20.0 ... 70.0 72.5 75.0
      standard_name :
      latitude
      long_name :
      Latitude
      units :
      degrees_north
      axis :
      Y
      array([15. , 17.5, 20. , 22.5, 25. , 27.5, 30. , 32.5, 35. , 37.5, 40. , 42.5,\n",
      +       "       45. , 47.5, 50. , 52.5, 55. , 57.5, 60. , 62.5, 65. , 67.5, 70. , 72.5,\n",
      +       "       75. ], dtype=float32)
    • lon
      (lon)
      float32
      200.0 202.5 205.0
      standard_name :
      longitude
      long_name :
      Longitude
      units :
      degrees_east
      axis :
      X
      array([200. , 202.5, 205. ], dtype=float32)
    • time
      (time)
      datetime64[ns]
      2013-01-01 ... 2013-01-01T18:00:00
      standard_name :
      time
      long_name :
      Time
      array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
      +       "       '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000'],\n",
      +       "      dtype='datetime64[ns]')
  • long_name :
    4xDaily Air temperature at sigma level 995
    units :
    degK
    precision :
    2
    GRIB_id :
    11
    GRIB_name :
    TMP
    var_desc :
    Air temperature
    dataset :
    NMC Reanalysis
    level_desc :
    Surface
    statistic :
    Individual Obs
    parent_stat :
    Other
    actual_range :
    [185.16 322.1 ]
" + ], + "text/plain": [ + "\n", + "array([[[296.29 , 296.79 , 297.1 ],\n", + " [295.9 , 296.19998, 296.79 ],\n", + " [296.6 , 296.19998, 296.4 ],\n", + " [297. , 296.69998, 296.1 ],\n", + " [295.4 , 295.69998, 295.79 ],\n", + " [293.79 , 294.1 , 294.6 ],\n", + " [293.1 , 293.29 , 293.29 ],\n", + " [290.19998, 290.79 , 291.4 ],\n", + " [287.9 , 288. , 288.29 ],\n", + " [286.5 , 286.5 , 285.69998],\n", + " [284.6 , 284.9 , 284.19998],\n", + " [282.79 , 283.19998, 282.6 ],\n", + " [280. , 280.69998, 280.19998],\n", + " [278.4 , 279. , 279. ],\n", + " [277.29 , 277.4 , 277.79 ],\n", + " [276.69998, 277.4 , 277.69998],\n", + " [275.9 , 276.9 , 276.9 ],\n", + " [274.79 , 275.19998, 275.6 ],\n", + " [273.69998, 273.6 , 273.79 ],\n", + " [272.1 , 270.9 , 270. ],\n", + " [274.5 , 274.29 , 274.1 ],\n", + " [266.5 , 267.1 , 267.1 ],\n", + " [250. , 249.79999, 248.89 ],\n", + " [243.79999, 244.5 , 244.7 ],\n", + " [241.2 , 242.5 , 243.5 ]],\n", + "\n", + " [[296.29 , 297.19998, 297.4 ],\n", + " [296.19998, 296.69998, 296.79 ],\n", + " [296.4 , 295.9 , 296.19998],\n", + " [295.79 , 295.79 , 296.1 ],\n", + " [295.1 , 295.79 , 295.79 ],\n", + " [294.29 , 294.79 , 294.69998],\n", + " [293.19998, 293.9 , 294.19998],\n", + " [290.19998, 291.1 , 292.4 ],\n", + " [287.5 , 288.5 , 289.4 ],\n", + " [285.69998, 287.4 , 287.1 ],\n", + " [283.29 , 285.19998, 285.19998],\n", + " [281.4 , 282.79 , 283.5 ],\n", + " [279.19998, 280.19998, 280.79 ],\n", + " [277.79 , 278.5 , 279.29 ],\n", + " [276.29 , 276.4 , 277.29 ],\n", + " [275.79 , 276. , 276.5 ],\n", + " [275.6 , 276.1 , 276.29 ],\n", + " [274. , 274.4 , 275.1 ],\n", + " [272.1 , 272.69998, 273.19998],\n", + " [269.19998, 268.5 , 267.6 ],\n", + " [272.5 , 271.5 , 270.4 ],\n", + " [269.69998, 269.4 , 268.6 ],\n", + " [253.2 , 252.89 , 252.09999],\n", + " [243.59999, 244.09999, 244.2 ],\n", + " [242.09999, 242.7 , 243.09999]],\n", + "\n", + " [[296.4 , 296.29 , 296.4 ],\n", + " [296.19998, 296.5 , 296.29 ],\n", + " [295.6 , 295.4 , 295.4 ],\n", + " [295. , 295. , 294.9 ],\n", + " [293.9 , 294.79 , 295. ],\n", + " [293.29 , 293.9 , 294.4 ],\n", + " [292.4 , 292.9 , 293.4 ],\n", + " [289.5 , 289.79 , 291.19998],\n", + " [287. , 287.1 , 288.29 ],\n", + " [284.9 , 285.6 , 286.4 ],\n", + " [282. , 283.29 , 284.69998],\n", + " [280. , 280.79 , 282.4 ],\n", + " [278.6 , 279.1 , 280. ],\n", + " [277.6 , 277.9 , 278.6 ],\n", + " [276. , 275.79 , 276.6 ],\n", + " [275.29 , 275.5 , 276. ],\n", + " [274.5 , 275.6 , 276.1 ],\n", + " [274.29 , 275. , 275.4 ],\n", + " [275.5 , 275.9 , 275.29 ],\n", + " [273. , 273.5 , 272.9 ],\n", + " [271.9 , 271.79 , 271.6 ],\n", + " [269.29 , 268.5 , 267. ],\n", + " [256.19998, 255.5 , 254.2 ],\n", + " [244.59999, 244.39 , 244. ],\n", + " [242.29999, 242.2 , 242.29999]],\n", + "\n", + " [[297.5 , 297.69998, 297.5 ],\n", + " [297. , 297.5 , 297.1 ],\n", + " [296.6 , 296.4 , 296. ],\n", + " [295.9 , 295.79 , 295.5 ],\n", + " [294.4 , 295. , 295.4 ],\n", + " [293. , 293.5 , 294.29 ],\n", + " [291.9 , 291.9 , 292.19998],\n", + " [289.19998, 289.4 , 289.9 ],\n", + " [286.6 , 287.1 , 287.9 ],\n", + " [284.79 , 284.79 , 285.4 ],\n", + " [282.79 , 282. , 282.69998],\n", + " [281.19998, 280.19998, 280.6 ],\n", + " [279.5 , 278.69998, 278.6 ],\n", + " [278. , 277.69998, 277.6 ],\n", + " [276.4 , 275.9 , 276.4 ],\n", + " [275.6 , 275.69998, 276.1 ],\n", + " [274.5 , 275.6 , 276.29 ],\n", + " [273.4 , 274.5 , 275.5 ],\n", + " [274.1 , 274. , 273.5 ],\n", + " [273.29 , 272.6 , 271.5 ],\n", + " [272.79 , 272.4 , 271.9 ],\n", + " [267.69998, 266.29 , 264.4 ],\n", + " [256.6 , 254.7 , 252.09999],\n", + " [246.29999, 245.29999, 244.2 ],\n", + " [241.89 , 241.79999, 241.79999]]], dtype=float32)\n", + "Coordinates:\n", + " * lat (lat) float32 15.0 17.5 20.0 22.5 25.0 ... 65.0 67.5 70.0 72.5 75.0\n", + " * lon (lon) float32 200.0 202.5 205.0\n", + " * time (time) datetime64[ns] 2013-01-01 ... 2013-01-01T18:00:00\n", + "Attributes:\n", + " long_name: 4xDaily Air temperature at sigma level 995\n", + " units: degK\n", + " precision: 2\n", + " GRIB_id: 11\n", + " GRIB_name: TMP\n", + " var_desc: Air temperature\n", + " dataset: NMC Reanalysis\n", + " level_desc: Surface\n", + " statistic: Individual Obs\n", + " parent_stat: Other\n", + " actual_range: [185.16 322.1 ]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import xarray as xr\n", + "import numpy as np\n", + "\n", + "xr.set_options(display_style=\"html\")\n", + "\n", + "air = (xr.tutorial\n", + " .load_dataset(\"air_temperature\")\n", + " .air\n", + " .sortby(\"lat\") # np.interp needs coordinate in ascending order\n", + " .isel(time=slice(4), lon=slice(3))) # choose a small subset for convenience\n", + "air" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The function we will apply is `np.interp` which expects 1D numpy arrays. This functionality is already implemented in xarray so we use that capability to make sure we are not making mistakes." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:07.557732Z", + "start_time": "2019-12-16T16:21:54.012163Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.66 ms ± 23.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" + ] + } + ], + "source": [ + "newlat = np.linspace(15, 75,100)\n", + "%timeit air.interp(lat=newlat)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's define a function that works with one vector of data along `lat` at a time." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:44.229304Z", + "start_time": "2019-12-16T16:22:44.190341Z" + } + }, + "outputs": [], + "source": [ + "def interp1d_np(data, x, xi):\n", + " return np.interp(xi, x, data)\n", + "\n", + "interped = interp1d_np(air.isel(time=0, lon=0), air.lat, newlat)\n", + "expected = air.interp(lat=newlat)\n", + "\n", + "# no errors are raised if values are equal to within floating point precision\n", + "np.testing.assert_allclose(expected.isel(time=0, lon=0).values,\n", + " interped)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "No errors are raised so our interpolation is working.\n", + "\n", + "This function consumes and returns numpy arrays, which means we need to do a lot of work to convert the result back to an xarray object with meaningful metadata. Enter `apply_ufunc` \n", + "\n", + " Apply a vectorized function for unlabeled arrays on xarray objects.\n", + "\n", + " The function will be mapped over the data variable(s) of the input arguments using \n", + " xarray’s standard rules for labeled computation, including alignment, broadcasting, \n", + " looping over GroupBy/Dataset variables, and merging of coordinates.\n", + " \n", + "`apply_ufunc` has many capabilities but this example will be relatively simple and focus on the relatively common task of vectorizing 1D functions over nD xarray objects. We will iteratively build up the right set of arguments to `apply_ufunc` and read through many error messages in the process of doing so." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:45.805695Z", + "start_time": "2019-12-16T16:22:45.759727Z" + } + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "size of dimension 'lat' on inputs was unexpectedly changed by applied function from 25 to 100. Only dimensions specified in ``exclude_dims`` with xarray.apply_ufunc are allowed to change size.", + "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 2\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlon\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# now arguments in the order expected by 'interp1_np'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m newlat)\n\u001b[0m", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 633\u001b[0m \u001b[0;34m\"dimensions specified in ``exclude_dims`` with \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 634\u001b[0m \"xarray.apply_ufunc are allowed to change size.\".format(\n\u001b[0;32m--> 635\u001b[0;31m \u001b[0mdim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim_sizes\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdim\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew_size\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 636\u001b[0m )\n\u001b[1;32m 637\u001b[0m )\n", + "\u001b[0;31mValueError\u001b[0m: size of dimension 'lat' on inputs was unexpectedly changed by applied function from 25 to 100. Only dimensions specified in ``exclude_dims`` with xarray.apply_ufunc are allowed to change size." + ] + } + ], + "source": [ + "xr.apply_ufunc(interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### exclude_dims\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`apply_ufunc` needs to know a lot of information about what our function does so that it can reconstruct the outputs. In this case, the size of dimension lat has changed and we need to explicitly specify that this will happen. xarray helpfully tells us that we need to specify the kwarg `exclude_dims`.\n", + "\n", + "\n", + "```\n", + "exclude_dims : set, optional\n", + " Core dimensions on the inputs to exclude from alignment and\n", + " broadcasting entirely. Any input coordinates along these dimensions\n", + " will be dropped. Each excluded dimension must also appear in\n", + " ``input_core_dims`` for at least one argument. Only dimensions listed\n", + " here are allowed to change size between input and output objects.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:47.652680Z", + "start_time": "2019-12-16T16:22:47.609161Z" + } + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "each dimension in `exclude_dims` must also be a core dimension in the function signature", + "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 3\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mnewlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m )\n", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 982\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mexclude_dims\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mexclude_dims\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mall_core_dims\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 983\u001b[0m raise ValueError(\n\u001b[0;32m--> 984\u001b[0;31m \u001b[0;34m\"each dimension in `exclude_dims` must also be a \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 985\u001b[0m \u001b[0;34m\"core dimension in the function signature\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 986\u001b[0m )\n", + "\u001b[0;31mValueError\u001b[0m: each dimension in `exclude_dims` must also be a core dimension in the function signature" + ] + } + ], + "source": [ + "xr.apply_ufunc(interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Core dimensions\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "DESCRIBE CORE DIMENSIONS.\n", + "\n", + "Core dimensions are central to using `apply_ufunc`. In our case, our function expects to receive a 1D vector along `lat` — this is the dimension that is \"core\" to the function's functionality. Multiple core dimensions are possible. `apply_ufunc` needs to know which dimensions of each variable are core dimensions.\n", + "\n", + " input_core_dims : Sequence[Sequence], optional\n", + " List of the same length as ``args`` giving the list of core dimensions\n", + " on each input argument that should not be broadcast. By default, we\n", + " assume there are no core dimensions on any input arguments.\n", + "\n", + " For example, ``input_core_dims=[[], ['time']]`` indicates that all\n", + " dimensions on the first argument and all dimensions other than 'time'\n", + " on the second argument should be broadcast.\n", + "\n", + " Core dimensions are automatically moved to the last axes of input\n", + " variables before applying ``func``, which facilitates using NumPy style\n", + " generalized ufuncs [2]_.\n", + " \n", + " output_core_dims : List[tuple], optional\n", + " List of the same length as the number of output arguments from\n", + " ``func``, giving the list of core dimensions on each output that were\n", + " not broadcast on the inputs. By default, we assume that ``func``\n", + " outputs exactly one array, with axes corresponding to each broadcast\n", + " dimension.\n", + "\n", + " Core dimensions are assumed to appear as the last dimensions of each\n", + " output in the provided order.\n", + " \n", + "Next we specify `\"lat\"` as `input_core_dims` on both `air` and `air.lat`" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:50.002819Z", + "start_time": "2019-12-16T16:22:49.945144Z" + } + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "applied function returned data with unexpected number of dimensions: 1 vs 0, for dimensions ()", + "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 4\u001b[0m \u001b[0mnewlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0minput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\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[0;32m----> 6\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m )\n", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 621\u001b[0m \u001b[0;34m\"applied function returned data with unexpected \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \"number of dimensions: {} vs {}, for dimensions {}\".format(\n\u001b[0;32m--> 623\u001b[0;31m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdims\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdims\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 624\u001b[0m )\n\u001b[1;32m 625\u001b[0m )\n", + "\u001b[0;31mValueError\u001b[0m: applied function returned data with unexpected number of dimensions: 1 vs 0, for dimensions ()" + ] + } + ], + "source": [ + "xr.apply_ufunc(interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []],\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "xarray is telling us that it expected to receive back a numpy array with 0 dimensions but instead received an array with 1 dimension corresponding to `newlat`. We can fix this by specifying `output_core_dims`" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:52.333458Z", + "start_time": "2019-12-16T16:22:52.289070Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "Show/Hide data repr\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Show/Hide attributes\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
xarray.DataArray
  • lat: 100
  • 296.3 296.2 296.1 296.0 295.9 296.0 ... 243.7 243.1 242.5 241.8 241.2
    array([296.29000854, 296.19545954, 296.10091053, 296.00636153,\n",
    +       "       295.91181252, 296.04848133, 296.21818126, 296.38788119,\n",
    +       "       296.55758112, 296.67273227, 296.76970048, 296.8666687 ,\n",
    +       "       296.96363692, 296.75757483, 296.36969457, 295.9818143 ,\n",
    +       "       295.59393403, 295.20484416, 294.81454468, 294.4242452 ,\n",
    +       "       294.03394572, 293.72728105, 293.56000773, 293.39273441,\n",
    +       "       293.22546109, 292.92424705, 292.22121083, 291.5181746 ,\n",
    +       "       290.81513838, 290.13028509, 289.57271229, 289.01513949,\n",
    +       "       288.45756669, 287.8999939 , 287.56060144, 287.22120898,\n",
    +       "       286.88181652, 286.54242406, 286.09697099, 285.63636641,\n",
    +       "       285.17576183, 284.71515725, 284.27091564, 283.83212835,\n",
    +       "       283.39334106, 282.95455378, 282.36727998, 281.69091427,\n",
    +       "       281.01454856, 280.33818285, 279.80605987, 279.4181796 ,\n",
    +       "       279.03029933, 278.64241906, 278.29908614, 278.02999878,\n",
    +       "       277.76091142, 277.49182406, 277.25424934, 277.11121253,\n",
    +       "       276.96817571, 276.8251389 , 276.67573964, 276.4818032 ,\n",
    +       "       276.28786677, 276.09393033, 275.8999939 , 275.63090654,\n",
    +       "       275.36181918, 275.09273182, 274.82364446, 274.55879073,\n",
    +       "       274.29454179, 274.03029286, 273.76604392, 273.40907704,\n",
    +       "       273.02120417, 272.6333313 , 272.24545843, 272.46364154,\n",
    +       "       273.04545824, 273.62727495, 274.20909165, 273.53030303,\n",
    +       "       271.59090909, 269.65151515, 267.71212121, 265.        ,\n",
    +       "       261.        , 257.        , 253.        , 249.62424168,\n",
    +       "       248.12120842, 246.61817516, 245.1151419 , 243.72120019,\n",
    +       "       243.09089938, 242.46059857, 241.83029776, 241.19999695])
    • lon
      ()
      float32
      200.0
      standard_name :
      longitude
      long_name :
      Longitude
      units :
      degrees_east
      axis :
      X
      array(200., dtype=float32)
    • time
      ()
      datetime64[ns]
      2013-01-01
      standard_name :
      time
      long_name :
      Time
      array('2013-01-01T00:00:00.000000000', dtype='datetime64[ns]')
" + ], + "text/plain": [ + "\n", + "array([296.29000854, 296.19545954, 296.10091053, 296.00636153,\n", + " 295.91181252, 296.04848133, 296.21818126, 296.38788119,\n", + " 296.55758112, 296.67273227, 296.76970048, 296.8666687 ,\n", + " 296.96363692, 296.75757483, 296.36969457, 295.9818143 ,\n", + " 295.59393403, 295.20484416, 294.81454468, 294.4242452 ,\n", + " 294.03394572, 293.72728105, 293.56000773, 293.39273441,\n", + " 293.22546109, 292.92424705, 292.22121083, 291.5181746 ,\n", + " 290.81513838, 290.13028509, 289.57271229, 289.01513949,\n", + " 288.45756669, 287.8999939 , 287.56060144, 287.22120898,\n", + " 286.88181652, 286.54242406, 286.09697099, 285.63636641,\n", + " 285.17576183, 284.71515725, 284.27091564, 283.83212835,\n", + " 283.39334106, 282.95455378, 282.36727998, 281.69091427,\n", + " 281.01454856, 280.33818285, 279.80605987, 279.4181796 ,\n", + " 279.03029933, 278.64241906, 278.29908614, 278.02999878,\n", + " 277.76091142, 277.49182406, 277.25424934, 277.11121253,\n", + " 276.96817571, 276.8251389 , 276.67573964, 276.4818032 ,\n", + " 276.28786677, 276.09393033, 275.8999939 , 275.63090654,\n", + " 275.36181918, 275.09273182, 274.82364446, 274.55879073,\n", + " 274.29454179, 274.03029286, 273.76604392, 273.40907704,\n", + " 273.02120417, 272.6333313 , 272.24545843, 272.46364154,\n", + " 273.04545824, 273.62727495, 274.20909165, 273.53030303,\n", + " 271.59090909, 269.65151515, 267.71212121, 265. ,\n", + " 261. , 257. , 253. , 249.62424168,\n", + " 248.12120842, 246.61817516, 245.1151419 , 243.72120019,\n", + " 243.09089938, 242.46059857, 241.83029776, 241.19999695])\n", + "Coordinates:\n", + " lon float32 200.0\n", + " time datetime64[ns] 2013-01-01\n", + "Dimensions without coordinates: lat" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "xr.apply_ufunc(interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", + " output_core_dims=[[\"lat\"]],\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally we get some output! Let's check that this is right\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:53.929091Z", + "start_time": "2019-12-16T16:22:53.878782Z" + } + }, + "outputs": [], + "source": [ + "interped = xr.apply_ufunc(interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", + " output_core_dims=[[\"lat\"]],\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + ")\n", + "interped[\"lat\"] = newlat # need to add this manually\n", + "xr.testing.assert_allclose(expected.isel(time=0, lon=0), interped)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is right!\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Vectorization with `np.vectorize`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now our function currently only works on one vector of data which is not so useful given our 3D dataset.\n", + "Let's try passing the whole dataset. We add a `print` statement so we can see what our function receives." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:55.223514Z", + "start_time": "2019-12-16T16:22:55.191870Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data: (4, 3, 25) | x: (25,) | xi: (100,)\n" + ] + }, + { + "ename": "ValueError", + "evalue": "object too deep 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 9\u001b[0m \u001b[0minput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# list with one entry per arg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0moutput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\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[0;32m---> 11\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m )\n\u001b[1;32m 13\u001b[0m \u001b[0minterped\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewlat\u001b[0m \u001b[0;31m# need to add this manually\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\"apply_ufunc: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 600\u001b[0m )\n\u001b[0;32m--> 601\u001b[0;31m \u001b[0mresult_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput_data\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 602\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 603\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36minterp1d_np\u001b[0;34m(data, x, xi)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0minterp1d_np\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxi\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[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minterp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\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 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m interped = xr.apply_ufunc(interp1d_np, # first the function\n", + "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36minterp\u001b[0;34m(*args, **kwargs)\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/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 1410\u001b[0m \u001b[0mfp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconcatenate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\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[1;32m 1411\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1412\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[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1413\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1414\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: object too deep for desired array" + ] + } + ], + "source": [ + "def interp1d_np(data, x, xi):\n", + " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", + " return np.interp(xi, x, data)\n", + "\n", + "interped = xr.apply_ufunc(interp1d_np, # first the function\n", + " air.isel(lon=slice(3), time=slice(4)), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", + " output_core_dims=[[\"lat\"]],\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + ")\n", + "interped[\"lat\"] = newlat # need to add this manually\n", + "xr.testing.assert_allclose(expected.isel(time=0, lon=0), interped)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That's a hard-to-interpret error but our `print` statement output `data: (10, 53, 25) | x: (25,) | xi: (100,)`. `air` has been passed as a 3D numpy array which is not what `np.interp` can handle. Instead we want loop over all combinations of `lon` and `time`; and apply our function to each corresponding vector of data along `lat`.\n", + "Turns out this is easy by specifying `vectorize=True` (though not great on performance).\n", + "\n", + " vectorize : bool, optional\n", + " If True, then assume ``func`` only takes arrays defined over core\n", + " dimensions as input and vectorize it automatically with\n", + " :py:func:`numpy.vectorize`. This option exists for convenience, but is\n", + " almost always slower than supplying a pre-vectorized function.\n", + " Using this option requires NumPy version 1.12 or newer.\n", + " \n", + "Also see the documentation for `np.vectorize`: https://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html. Most importantly\n", + "\n", + " The vectorize function is provided primarily for convenience, not for performance. \n", + " The implementation is essentially a for loop." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:57.534630Z", + "start_time": "2019-12-16T16:22:57.468197Z" + } + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "shape mismatch: objects cannot be broadcast to a single shape", + "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 10\u001b[0m \u001b[0moutput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# returned data has one dimension\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0mvectorize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# loop over non-core dims\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 13\u001b[0m )\n\u001b[1;32m 14\u001b[0m \u001b[0minterped\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewlat\u001b[0m \u001b[0;31m# need to add this manually\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\"apply_ufunc: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 600\u001b[0m )\n\u001b[0;32m--> 601\u001b[0;31m \u001b[0mresult_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput_data\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 602\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 603\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 2089\u001b[0m \u001b[0mvargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0m_n\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_n\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mnames\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[1;32m 2090\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2091\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_vectorize_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvargs\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 2092\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2093\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_get_ufunc_and_otypes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m_vectorize_call\u001b[0;34m(self, func, args)\u001b[0m\n\u001b[1;32m 2155\u001b[0m \u001b[0;34m\"\"\"Vectorized call to `func` over positional `args`.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2156\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msignature\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2157\u001b[0;31m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_vectorize_call_with_signature\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\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 2158\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2159\u001b[0m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m_vectorize_call_with_signature\u001b[0;34m(self, func, args)\u001b[0m\n\u001b[1;32m 2185\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2186\u001b[0m broadcast_shape, dim_sizes = _parse_input_dimensions(\n\u001b[0;32m-> 2187\u001b[0;31m args, input_core_dims)\n\u001b[0m\u001b[1;32m 2188\u001b[0m input_shapes = _calculate_shapes(broadcast_shape, dim_sizes,\n\u001b[1;32m 2189\u001b[0m input_core_dims)\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m_parse_input_dimensions\u001b[0;34m(args, input_core_dims)\u001b[0m\n\u001b[1;32m 1858\u001b[0m \u001b[0mdummy_array\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstride_tricks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mas_strided\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mndim\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[1;32m 1859\u001b[0m \u001b[0mbroadcast_args\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdummy_array\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1860\u001b[0;31m \u001b[0mbroadcast_shape\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstride_tricks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_broadcast_shape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mbroadcast_args\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 1861\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mbroadcast_shape\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim_sizes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1862\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/stride_tricks.py\u001b[0m in \u001b[0;36m_broadcast_shape\u001b[0;34m(*args)\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;31m# use the old-iterator because np.nditer does not handle size 0 arrays\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 190\u001b[0m \u001b[0;31m# consistently\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 191\u001b[0;31m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbroadcast\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m32\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 192\u001b[0m \u001b[0;31m# unfortunately, it cannot handle 32 or more arguments directly\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 193\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mpos\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m32\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m31\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[0;31mValueError\u001b[0m: shape mismatch: objects cannot be broadcast to a single shape" + ] + } + ], + "source": [ + "def interp1d_np(data, x, xi):\n", + " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", + " return np.interp(xi, x, data)\n", + "\n", + "interped = xr.apply_ufunc(interp1d_np, # first the function\n", + " air, # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", + " output_core_dims=[[\"lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + " vectorize=True, # loop over non-core dims\n", + ")\n", + "interped[\"lat\"] = newlat # need to add this manually\n", + "xr.testing.assert_allclose(expected, interped)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This unfortunately is another cryptic error from numpy. \n", + "\n", + "Notice that `newlat` is not an xarray object. Let's add a dimension name `new_lat` and modify the call. Note this cannot be `lat` because xarray expects dimensions to be the same size (or broadcastable) among all inputs. `output_core_dims` needs to be modified appropriately. We'll manually rename `new_lat` back to `lat` for easy checking." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:22:59.872389Z", + "start_time": "2019-12-16T16:22:59.799915Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "Show/Hide data repr\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Show/Hide attributes\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
xarray.DataArray
  • time: 4
  • lon: 3
  • lat: 100
  • 296.3 296.2 296.1 296.0 295.9 296.0 ... 244.1 243.5 243.0 242.4 241.8
    array([[[296.29000854, 296.19545954, 296.10091053, ..., 242.46059857,\n",
    +       "         241.83029776, 241.19999695],\n",
    +       "        [296.79000854, 296.64697173, 296.50393492, ..., 243.46969697,\n",
    +       "         242.98484848, 242.5       ],\n",
    +       "        [297.1000061 , 297.02485518, 296.94970426, ..., 244.0818167 ,\n",
    +       "         243.79090835, 243.5       ]],\n",
    +       "\n",
    +       "       [[296.29000854, 296.26818385, 296.24635916, ..., 242.82726357,\n",
    +       "         242.46362721, 242.09999084],\n",
    +       "        [297.19998169, 297.07876957, 296.95755745, ..., 243.37878187,\n",
    +       "         243.03938941, 242.69999695],\n",
    +       "        [297.3999939 , 297.25211866, 297.10424342, ..., 243.63332714,\n",
    +       "         243.36665899, 243.09999084]],\n",
    +       "\n",
    +       "       [[296.3999939 , 296.35150609, 296.30301828, ..., 243.41514079,\n",
    +       "         242.85756429, 242.29998779],\n",
    +       "        [296.29000854, 296.34091556, 296.39182258, ..., 243.26181631,\n",
    +       "         242.73090663, 242.19999695],\n",
    +       "        [296.3999939 , 296.37333078, 296.34666767, ..., 243.12423614,\n",
    +       "         242.71211196, 242.29998779]],\n",
    +       "\n",
    +       "       [[297.5       , 297.37878788, 297.25757576, ..., 244.02817559,\n",
    +       "         242.95908749, 241.88999939],\n",
    +       "        [297.69998169, 297.65150128, 297.60302087, ..., 243.49695749,\n",
    +       "         242.64847264, 241.79998779],\n",
    +       "        [297.5       , 297.40303178, 297.30606357, ..., 242.9636286 ,\n",
    +       "         242.38180819, 241.79998779]]])
    • lon
      (lon)
      float32
      200.0 202.5 205.0
      standard_name :
      longitude
      long_name :
      Longitude
      units :
      degrees_east
      axis :
      X
      array([200. , 202.5, 205. ], dtype=float32)
    • time
      (time)
      datetime64[ns]
      2013-01-01 ... 2013-01-01T18:00:00
      standard_name :
      time
      long_name :
      Time
      array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
      +       "       '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000'],\n",
      +       "      dtype='datetime64[ns]')
    • lat
      (lat)
      float64
      15.0 15.61 16.21 ... 74.39 75.0
      array([15.      , 15.606061, 16.212121, 16.818182, 17.424242, 18.030303,\n",
      +       "       18.636364, 19.242424, 19.848485, 20.454545, 21.060606, 21.666667,\n",
      +       "       22.272727, 22.878788, 23.484848, 24.090909, 24.69697 , 25.30303 ,\n",
      +       "       25.909091, 26.515152, 27.121212, 27.727273, 28.333333, 28.939394,\n",
      +       "       29.545455, 30.151515, 30.757576, 31.363636, 31.969697, 32.575758,\n",
      +       "       33.181818, 33.787879, 34.393939, 35.      , 35.606061, 36.212121,\n",
      +       "       36.818182, 37.424242, 38.030303, 38.636364, 39.242424, 39.848485,\n",
      +       "       40.454545, 41.060606, 41.666667, 42.272727, 42.878788, 43.484848,\n",
      +       "       44.090909, 44.69697 , 45.30303 , 45.909091, 46.515152, 47.121212,\n",
      +       "       47.727273, 48.333333, 48.939394, 49.545455, 50.151515, 50.757576,\n",
      +       "       51.363636, 51.969697, 52.575758, 53.181818, 53.787879, 54.393939,\n",
      +       "       55.      , 55.606061, 56.212121, 56.818182, 57.424242, 58.030303,\n",
      +       "       58.636364, 59.242424, 59.848485, 60.454545, 61.060606, 61.666667,\n",
      +       "       62.272727, 62.878788, 63.484848, 64.090909, 64.69697 , 65.30303 ,\n",
      +       "       65.909091, 66.515152, 67.121212, 67.727273, 68.333333, 68.939394,\n",
      +       "       69.545455, 70.151515, 70.757576, 71.363636, 71.969697, 72.575758,\n",
      +       "       73.181818, 73.787879, 74.393939, 75.      ])
" + ], + "text/plain": [ + "\n", + "array([[[296.29000854, 296.19545954, 296.10091053, ..., 242.46059857,\n", + " 241.83029776, 241.19999695],\n", + " [296.79000854, 296.64697173, 296.50393492, ..., 243.46969697,\n", + " 242.98484848, 242.5 ],\n", + " [297.1000061 , 297.02485518, 296.94970426, ..., 244.0818167 ,\n", + " 243.79090835, 243.5 ]],\n", + "\n", + " [[296.29000854, 296.26818385, 296.24635916, ..., 242.82726357,\n", + " 242.46362721, 242.09999084],\n", + " [297.19998169, 297.07876957, 296.95755745, ..., 243.37878187,\n", + " 243.03938941, 242.69999695],\n", + " [297.3999939 , 297.25211866, 297.10424342, ..., 243.63332714,\n", + " 243.36665899, 243.09999084]],\n", + "\n", + " [[296.3999939 , 296.35150609, 296.30301828, ..., 243.41514079,\n", + " 242.85756429, 242.29998779],\n", + " [296.29000854, 296.34091556, 296.39182258, ..., 243.26181631,\n", + " 242.73090663, 242.19999695],\n", + " [296.3999939 , 296.37333078, 296.34666767, ..., 243.12423614,\n", + " 242.71211196, 242.29998779]],\n", + "\n", + " [[297.5 , 297.37878788, 297.25757576, ..., 244.02817559,\n", + " 242.95908749, 241.88999939],\n", + " [297.69998169, 297.65150128, 297.60302087, ..., 243.49695749,\n", + " 242.64847264, 241.79998779],\n", + " [297.5 , 297.40303178, 297.30606357, ..., 242.9636286 ,\n", + " 242.38180819, 241.79998779]]])\n", + "Coordinates:\n", + " * lon (lon) float32 200.0 202.5 205.0\n", + " * time (time) datetime64[ns] 2013-01-01 ... 2013-01-01T18:00:00\n", + " * lat (lat) float64 15.0 15.61 16.21 16.82 ... 73.18 73.79 74.39 75.0" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def interp1d_np(data, x, xi):\n", + " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", + " return np.interp(xi, x, data)\n", + "\n", + "interped = xr.apply_ufunc(interp1d_np, # first the function\n", + " air, # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", + " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be a set!\n", + " vectorize=True, # loop over non-core dims\n", + ")\n", + "interped = interped.rename({\"new_lat\": \"lat\"})\n", + "interped[\"lat\"] = newlat # need to add this manually\n", + "xr.testing.assert_allclose(expected.transpose(*interped.dims), # order of dims is different\n", + " interped)\n", + "interped" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that the printed input shapes are all 1D and correspond to one vector along the `lat` dimension.\n", + "\n", + "The result is now an xarray object with coordinate values copied over from `data`. This is why `apply_ufunc` is so convenient; it takes care of a lot of boilerplate necessary to apply functions that consume and produce numpy arrays to xarray objects.\n", + "\n", + "One final point: `lat` is now the *last* dimension in `interped`. This is a \"property\" of core dimensions: they are moved to the end before being sent to `interp1d_np` as was noted in the docstring for `input_core_dims`\n", + "\n", + " Core dimensions are automatically moved to the last axes of input\n", + " variables before applying ``func``, which facilitates using NumPy style\n", + " generalized ufuncs [2]_." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parallelization with dask\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So far our function can only handle numpy arrays. A real benefit of `apply_ufunc` is the ability to easily parallelize over dask chunks _when needed_. \n", + "\n", + "We want to apply this function in a vectorized fashion over each chunk of the dask array. This is possible using dask's `blockwise` or `map_blocks`. `apply_ufunc` wraps `blockwise` and asking it to map the function over chunks using `blockwise` is as simple as saying `dask=\"parallelized\"`. With this level of flexibility we need to provide dask with some extra information: \n", + " 1. `output_dtypes`: dtypes of all returned objects, and \n", + " 2. `output_sizes`: lengths of any new dimensions. \n", + " \n", + "Here we need to specify `output_dtypes` since `apply_ufunc` can infer the size of the new dimension `new_lat` from the argument corresponding to the third element in `input_core_dims`. Here I choose the chunk sizes to illustrate that `np.vectorize` is still applied so that our function receives 1D vectors even though the blocks are 3D." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:23:02.553343Z", + "start_time": "2019-12-16T16:23:02.487649Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)data: (25,) | x: (25,) | xi: (100,)\n", + "\n", + "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)\n" + ] + } + ], + "source": [ + "def interp1d_np(data, x, xi):\n", + " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", + " return np.interp(xi, x, data)\n", + "\n", + "interped = xr.apply_ufunc(interp1d_np, # first the function\n", + " air.chunk({\"time\": 2, \"lon\": 2}), # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", + " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be a set!\n", + " vectorize=True, # loop over non-core dims\n", + " dask=\"parallelized\",\n", + " output_dtypes=[float], # one per output\n", + ").rename({\"new_lat\": \"lat\"})\n", + "interped[\"lat\"] = newlat # need to add this manually\n", + "xr.testing.assert_allclose(expected.transpose(*interped.dims),\n", + " interped)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Yay! our function is receiving 1D vectors, so we've successfully parallelized applying a 1D function over a block. If you have a distributed dashboard up, you should see computes happening as equality is checked.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### High performance vectorization: gufuncs, numba & guvectorize\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`np.vectorize` is a very convenient function but is unfortunately slow. It is only marginally faster than writing a for loop in Python and looping. A common way to get around this is to write a base interpolation function that can handle nD arrays in a compiled language like Fortran and then pass that to `apply_ufunc`.\n", + "\n", + "Another option is to use the numba package which provides a very convenient `guvectorize` decorator: https://numba.pydata.org/numba-doc/latest/user/vectorize.html#the-guvectorize-decorator\n", + "\n", + "Any decorated function gets compiled and will loop over any non-core dimension in parallel when necessary. We need to specify some extra information:\n", + " 1. Our function cannot return a variable any more. Instead it must receive a variable (the last argument) whose contents the function will modify. So we change from `def interp1d_np(data, x, xi)` to `def interp1d_np_gufunc(data, x, xi, out)`. Our computed results must be assigned to `out`. All values of `out` must be assigned explicitly.\n", + " \n", + " 2. `guvectorize` needs to know the dtypes of the input and output. This is specified in string form as the first argument. Each element of the tuple corresponds to each argument of the function. In this case, we specify `float64` for all inputs and outputs: `\"(float64[:], float64[:], float64[:], float64[:])\"` corresponding to `data, x, xi, out`\n", + " \n", + " 3. Now we need to tell numba the size of the dimensions the function takes as inputs and returns as output i.e. core dimensions. This is done in symbolic form i.e. `data` and `x` are vectors of the same length, say `n`; `xi` and the output `out` have a different length, say `m`. So the second argument is (again as a string)\n", + " `\"(n), (n), (m) -> (m).\"` corresponding again to `data, x, xi, out`\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:23:05.780075Z", + "start_time": "2019-12-16T16:23:04.552713Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":2: NumbaWarning: \n", + "Compilation is falling back to object mode WITHOUT looplifting enabled because Function \"interp1d_np_gufunc\" failed type inference due to: Invalid use of Function() with argument(s) of type(s): (tuple(int64 x 1))\n", + " * parameterized\n", + "In definition 0:\n", + " All templates rejected with literals.\n", + "In definition 1:\n", + " All templates rejected without literals.\n", + "In definition 2:\n", + " All templates rejected with literals.\n", + "In definition 3:\n", + " All templates rejected without literals.\n", + "This error is usually caused by passing an argument of a type that is unsupported by the named function.\n", + "[1] During: resolving callee type: Function()\n", + "[2] During: typing of call at (7)\n", + "\n", + "\n", + "File \"\", line 7:\n", + "def interp1d_np_gufunc(data, x, xi, out):\n", + " \n", + " # seem to support fstrings so do it the old way\n", + " print(\"data: \" + str(data.shape) + \" | x:\" + str(x.shape) + \" | xi: \" + str(xi.shape))\n", + " ^\n", + "\n", + " @guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\",\n", + "/home/deepak/miniconda3/envs/dcpy/lib/python3.7/site-packages/numba/object_mode_passes.py:178: NumbaWarning: Function \"interp1d_np_gufunc\" was compiled in object mode without forceobj=True.\n", + "\n", + "File \"\", line 4:\n", + " \"(n), (n), (m) -> (m)\")\n", + "def interp1d_np_gufunc(data, x, xi, out):\n", + "^\n", + "\n", + " state.func_ir.loc))\n", + "/home/deepak/miniconda3/envs/dcpy/lib/python3.7/site-packages/numba/object_mode_passes.py:187: NumbaDeprecationWarning: \n", + "Fall-back from the nopython compilation path to the object mode compilation path has been detected, this is deprecated behaviour.\n", + "\n", + "For more information visit http://numba.pydata.org/numba-doc/latest/reference/deprecation.html#deprecation-of-object-mode-fall-back-behaviour-when-using-jit\n", + "\n", + "File \"\", line 4:\n", + " \"(n), (n), (m) -> (m)\")\n", + "def interp1d_np_gufunc(data, x, xi, out):\n", + "^\n", + "\n", + " warnings.warn(errors.NumbaDeprecationWarning(msg, state.func_ir.loc))\n" + ] + } + ], + "source": [ + "from numba import float64, guvectorize\n", + "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\",\n", + " \"(n), (n), (m) -> (m)\")\n", + "def interp1d_np_gufunc(data, x, xi, out):\n", + " # numba doesn't really like this.\n", + " # seem to support fstrings so do it the old way\n", + " print(\"data: \" + str(data.shape) + \" | x:\" + str(x.shape) + \" | xi: \" + str(xi.shape))\n", + " out[:] = np.interp(xi, x, data)\n", + " # gufuncs don't return data\n", + " # instead you assign to a the last arg\n", + " # return np.interp(xi, x, data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The warnings are about object-mode compilation relating to the `print` statement. This means we don't get much speed up: https://numba.pydata.org/numba-doc/latest/user/performance-tips.html#no-python-mode-vs-object-mode. We'll keep the `print` statement temporarily to make sure that `guvectorize` acts like we want it to." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:23:05.988773Z", + "start_time": "2019-12-16T16:23:05.957159Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)\n", + "data: (25,) | x:(25,) | xi: (100,)\n", + "data: (25,) | x:(25,) | xi: (100,)\n", + "\n", + "data: (25,) | x:(25,) | xi: (100,)\n", + "data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)\n", + "data: (25,) | x:(25,) | xi: (100,)\n", + "data: (25,) | x:(25,) | xi: (100,)\n", + "data: (25,) | x:(25,) | xi: (100,)\n", + "data: (25,) | x:(25,) | xi: (100,)\n", + "\n", + "data: (25,) | x:(25,) | xi: (100,)\n" + ] + } + ], + "source": [ + "interped = xr.apply_ufunc(interp1d_np_gufunc, # first the function\n", + " air.chunk({\"time\": 2, \"lon\": 2}), # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", + " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be a set!\n", + " # vectorize=True, # not needed since numba takes care of vectorizing\n", + " dask=\"parallelized\",\n", + " output_dtypes=[float], # one per output\n", + ").rename({\"new_lat\": \"lat\"})\n", + "interped[\"lat\"] = newlat # need to add this manually\n", + "xr.testing.assert_allclose(expected.transpose(*interped.dims),\n", + " interped)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Yay! Our function is receiving 1D vectors and is working automatically with dask arrays. Finally let's comment out the print line" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:23:08.538982Z", + "start_time": "2019-12-16T16:23:08.192798Z" + } + }, + "outputs": [], + "source": [ + "from numba import float64, guvectorize\n", + "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\",\n", + " \"(n), (n), (m) -> (m)\")\n", + "def interp1d_np_gufunc(data, x, xi, out):\n", + " out[:] = np.interp(xi, x, data)\n", + "\n", + "interped = xr.apply_ufunc(interp1d_np_gufunc, # first the function\n", + " air.chunk({\"time\": 2, \"lon\": 2}), # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", + " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be a set!\n", + " # vectorize=True, # not needed since numba takes care of vectorizing\n", + " dask=\"parallelized\",\n", + " output_dtypes=[float], # one per output\n", + ").rename({\"new_lat\": \"lat\"})\n", + "interped[\"lat\"] = newlat # need to add this manually\n", + "xr.testing.assert_allclose(expected.transpose(*interped.dims),\n", + " interped)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This works at basically the same speed as the original interpolation but the technique is generalizable to any 1D function" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "ExecuteTime": { + "end_time": "2019-12-16T16:03:39.896523Z", + "start_time": "2019-12-16T16:03:37.905326Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.42 ms ± 204 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "%timeit interped.compute()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "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.7.3" + }, + "nbsphinx": { + "allow_errors": true + }, + "org": null, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 1f60d457432..c2a26d847cb 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -65,6 +65,9 @@ Documentation - Added examples for :py:meth:`DataArray.quantile`, :py:meth:`Dataset.quantile` and ``GroupBy.quantile``. (:pull:`3576`) By `Justus Magin `_. +- Add new :py:func:`apply_ufunc` example notebook demonstrating vectorization of a 1D + function using dask and numba. + By `Deepak Cherian `_. Internal Changes ~~~~~~~~~~~~~~~~ From 9c10c98492e8bea5723bdab6e23524fc1baf8216 Mon Sep 17 00:00:00 2001 From: dcherian Date: Mon, 30 Dec 2019 09:12:42 -0700 Subject: [PATCH 2/4] Small udpates. --- doc/examples/apply_ufunc_vectorize_1d.ipynb | 954 +++++++++++++++----- 1 file changed, 710 insertions(+), 244 deletions(-) diff --git a/doc/examples/apply_ufunc_vectorize_1d.ipynb b/doc/examples/apply_ufunc_vectorize_1d.ipynb index fa41271f206..ccec9106cd9 100644 --- a/doc/examples/apply_ufunc_vectorize_1d.ipynb +++ b/doc/examples/apply_ufunc_vectorize_1d.ipynb @@ -11,18 +11,33 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This example will illustrate how to conveniently apply an unvectorized function to xarray objects using `apply_ufunc`. This function will expect 1D numpy arrays and return a 1D numpy array. Our goal is to coveniently apply this function over xarray objects that may or may not wrap dask arrays.\n", + "This example will illustrate how to conveniently apply an unvectorized function `func` to xarray objects using `apply_ufunc`. `func` expects 1D numpy arrays and returns a 1D numpy array. Our goal is to coveniently apply this function along a dimension of xarray objects that may or may not wrap dask arrays with a signature.\n", + "\n", + "We will illustrate this using `np.interp`: \n", + "\n", + " Signature: np.interp(x, xp, fp, left=None, right=None, period=None)\n", + " Docstring:\n", + " One-dimensional linear interpolation.\n", + "\n", + " Returns the one-dimensional piecewise linear interpolant to a function\n", + " with given discrete data points (`xp`, `fp`), evaluated at `x`.\n", + "\n", + "and write an `xr_interp` function with signature\n", + "\n", + " xr_interp(xarray_object, dimension_name, new_coordinate_to_interpolate_to)\n", + "\n", + "### Load data\n", "\n", "First lets load an example dataset" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 1, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:21:52.494131Z", - "start_time": "2019-12-16T16:21:52.411269Z" + "end_time": "2019-12-30T15:54:59.861486Z", + "start_time": "2019-12-30T15:54:58.773827Z" } }, "outputs": [ @@ -363,7 +378,7 @@ " stroke: currentColor;\n", " fill: currentColor;\n", "}\n", - "
xarray.DataArray
'air'
  • time: 4
  • lat: 25
  • lon: 3
  • 296.29 296.79 297.1 295.9 ... 244.2 241.89 241.79999 241.79999
    array([[[296.29   , 296.79   , 297.1    ],\n",
    +       "
    xarray.DataArray
    'air'
    • time: 4
    • lat: 25
    • lon: 3
    • 296.29 296.79 297.1 295.9 ... 244.2 241.89 241.79999 241.79999
      array([[[296.29   , 296.79   , 297.1    ],\n",
              "        [295.9    , 296.19998, 296.79   ],\n",
              "        [296.6    , 296.19998, 296.4    ],\n",
              "        [297.     , 296.69998, 296.1    ],\n",
      @@ -465,11 +480,11 @@
              "        [267.69998, 266.29   , 264.4    ],\n",
              "        [256.6    , 254.7    , 252.09999],\n",
              "        [246.29999, 245.29999, 244.2    ],\n",
      -       "        [241.89   , 241.79999, 241.79999]]], dtype=float32)
      • lat
        (lat)
        float32
        15.0 17.5 20.0 ... 70.0 72.5 75.0
        standard_name :
        latitude
        long_name :
        Latitude
        units :
        degrees_north
        axis :
        Y
        array([15. , 17.5, 20. , 22.5, 25. , 27.5, 30. , 32.5, 35. , 37.5, 40. , 42.5,\n",
        +       "        [241.89   , 241.79999, 241.79999]]], dtype=float32)
      • lat
        (lat)
        float32
        15.0 17.5 20.0 ... 70.0 72.5 75.0
        standard_name :
        latitude
        long_name :
        Latitude
        units :
        degrees_north
        axis :
        Y
        array([15. , 17.5, 20. , 22.5, 25. , 27.5, 30. , 32.5, 35. , 37.5, 40. , 42.5,\n",
                "       45. , 47.5, 50. , 52.5, 55. , 57.5, 60. , 62.5, 65. , 67.5, 70. , 72.5,\n",
        -       "       75. ], dtype=float32)
      • lon
        (lon)
        float32
        200.0 202.5 205.0
        standard_name :
        longitude
        long_name :
        Longitude
        units :
        degrees_east
        axis :
        X
        array([200. , 202.5, 205. ], dtype=float32)
      • time
        (time)
        datetime64[ns]
        2013-01-01 ... 2013-01-01T18:00:00
        standard_name :
        time
        long_name :
        Time
        array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
        +       "       75. ], dtype=float32)
      • lon
        (lon)
        float32
        200.0 202.5 205.0
        standard_name :
        longitude
        long_name :
        Longitude
        units :
        degrees_east
        axis :
        X
        array([200. , 202.5, 205. ], dtype=float32)
      • time
        (time)
        datetime64[ns]
        2013-01-01 ... 2013-01-01T18:00:00
        standard_name :
        time
        long_name :
        Time
        array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
                "       '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000'],\n",
        -       "      dtype='datetime64[ns]')
    • long_name :
      4xDaily Air temperature at sigma level 995
      units :
      degK
      precision :
      2
      GRIB_id :
      11
      GRIB_name :
      TMP
      var_desc :
      Air temperature
      dataset :
      NMC Reanalysis
      level_desc :
      Surface
      statistic :
      Individual Obs
      parent_stat :
      Other
      actual_range :
      [185.16 322.1 ]
    " + " dtype='datetime64[ns]')
  • long_name :
    4xDaily Air temperature at sigma level 995
    units :
    degK
    precision :
    2
    GRIB_id :
    11
    GRIB_name :
    TMP
    var_desc :
    Air temperature
    dataset :
    NMC Reanalysis
    level_desc :
    Surface
    statistic :
    Individual Obs
    parent_stat :
    Other
    actual_range :
    [185.16 322.1 ]
  • " ], "text/plain": [ "\n", @@ -594,7 +609,7 @@ " actual_range: [185.16 322.1 ]" ] }, - "execution_count": 4, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -603,13 +618,13 @@ "import xarray as xr\n", "import numpy as np\n", "\n", - "xr.set_options(display_style=\"html\")\n", + "xr.set_options(display_style=\"html\") # fancy HTML repr\n", "\n", - "air = (xr.tutorial\n", - " .load_dataset(\"air_temperature\")\n", - " .air\n", - " .sortby(\"lat\") # np.interp needs coordinate in ascending order\n", - " .isel(time=slice(4), lon=slice(3))) # choose a small subset for convenience\n", + "air = (\n", + " xr.tutorial.load_dataset(\"air_temperature\")\n", + " .air.sortby(\"lat\") # np.interp needs coordinate in ascending order\n", + " .isel(time=slice(4), lon=slice(3))\n", + ") # choose a small subset for convenience\n", "air" ] }, @@ -622,25 +637,460 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 19, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:07.557732Z", - "start_time": "2019-12-16T16:21:54.012163Z" + "end_time": "2019-12-30T15:57:16.214911Z", + "start_time": "2019-12-30T15:57:16.165994Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "1.66 ms ± 23.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" - ] + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + "Show/Hide data repr\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Show/Hide attributes\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    xarray.DataArray
    'air'
    • time: 4
    • lat: 100
    • lon: 3
    • 296.3 296.8 297.1 296.2 296.6 297.0 ... 242.6 242.4 241.9 241.8 241.8
      array([[[296.29000854, 296.79000854, 297.1000061 ],\n",
      +       "        [296.19545954, 296.64697173, 297.02485518],\n",
      +       "        [296.10091053, 296.50393491, 296.94970426],\n",
      +       "        ...,\n",
      +       "        [242.46059851, 243.46969695, 244.08181672],\n",
      +       "        [241.83029767, 242.98484846, 243.79090837],\n",
      +       "        [241.19999683, 242.49999997, 243.50000003]],\n",
      +       "\n",
      +       "       [[296.29000854, 297.19998169, 297.3999939 ],\n",
      +       "        [296.26818385, 297.07876957, 297.25211866],\n",
      +       "        [296.24635916, 296.95755744, 297.10424342],\n",
      +       "        ...,\n",
      +       "        [242.82726354, 243.37878187, 243.63332714],\n",
      +       "        [242.46362716, 243.03938941, 243.36665899],\n",
      +       "        [242.09999079, 242.69999695, 243.09999084]],\n",
      +       "\n",
      +       "       [[296.3999939 , 296.29000854, 296.3999939 ],\n",
      +       "        [296.35150609, 296.34091556, 296.37333078],\n",
      +       "        [296.30301828, 296.39182258, 296.34666767],\n",
      +       "        ...,\n",
      +       "        [243.4151408 , 243.26181628, 243.12423612],\n",
      +       "        [242.85756431, 242.73090659, 242.71211194],\n",
      +       "        [242.29998782, 242.19999689, 242.29998776]],\n",
      +       "\n",
      +       "       [[297.5       , 297.69998169, 297.5       ],\n",
      +       "        [297.37878788, 297.65150128, 297.40303179],\n",
      +       "        [297.25757575, 297.60302087, 297.30606357],\n",
      +       "        ...,\n",
      +       "        [244.02817552, 243.49695752, 242.96362858],\n",
      +       "        [242.9590874 , 242.64847269, 242.38180817],\n",
      +       "        [241.88999927, 241.79998785, 241.79998776]]])
      • lon
        (lon)
        float32
        200.0 202.5 205.0
        standard_name :
        longitude
        long_name :
        Longitude
        units :
        degrees_east
        axis :
        X
        array([200. , 202.5, 205. ], dtype=float32)
      • time
        (time)
        datetime64[ns]
        2013-01-01 ... 2013-01-01T18:00:00
        standard_name :
        time
        long_name :
        Time
        array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
        +       "       '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000'],\n",
        +       "      dtype='datetime64[ns]')
      • lat
        (lat)
        float64
        15.0 15.61 16.21 ... 74.39 75.0
        array([15.      , 15.606061, 16.212121, 16.818182, 17.424242, 18.030303,\n",
        +       "       18.636364, 19.242424, 19.848485, 20.454545, 21.060606, 21.666667,\n",
        +       "       22.272727, 22.878788, 23.484848, 24.090909, 24.69697 , 25.30303 ,\n",
        +       "       25.909091, 26.515152, 27.121212, 27.727273, 28.333333, 28.939394,\n",
        +       "       29.545455, 30.151515, 30.757576, 31.363636, 31.969697, 32.575758,\n",
        +       "       33.181818, 33.787879, 34.393939, 35.      , 35.606061, 36.212121,\n",
        +       "       36.818182, 37.424242, 38.030303, 38.636364, 39.242424, 39.848485,\n",
        +       "       40.454545, 41.060606, 41.666667, 42.272727, 42.878788, 43.484848,\n",
        +       "       44.090909, 44.69697 , 45.30303 , 45.909091, 46.515152, 47.121212,\n",
        +       "       47.727273, 48.333333, 48.939394, 49.545455, 50.151515, 50.757576,\n",
        +       "       51.363636, 51.969697, 52.575758, 53.181818, 53.787879, 54.393939,\n",
        +       "       55.      , 55.606061, 56.212121, 56.818182, 57.424242, 58.030303,\n",
        +       "       58.636364, 59.242424, 59.848485, 60.454545, 61.060606, 61.666667,\n",
        +       "       62.272727, 62.878788, 63.484848, 64.090909, 64.69697 , 65.30303 ,\n",
        +       "       65.909091, 66.515152, 67.121212, 67.727273, 68.333333, 68.939394,\n",
        +       "       69.545455, 70.151515, 70.757576, 71.363636, 71.969697, 72.575758,\n",
        +       "       73.181818, 73.787879, 74.393939, 75.      ])
    • long_name :
      4xDaily Air temperature at sigma level 995
      units :
      degK
      precision :
      2
      GRIB_id :
      11
      GRIB_name :
      TMP
      var_desc :
      Air temperature
      dataset :
      NMC Reanalysis
      level_desc :
      Surface
      statistic :
      Individual Obs
      parent_stat :
      Other
      actual_range :
      [185.16 322.1 ]
    " + ], + "text/plain": [ + "\n", + "array([[[296.29000854, 296.79000854, 297.1000061 ],\n", + " [296.19545954, 296.64697173, 297.02485518],\n", + " [296.10091053, 296.50393491, 296.94970426],\n", + " ...,\n", + " [242.46059851, 243.46969695, 244.08181672],\n", + " [241.83029767, 242.98484846, 243.79090837],\n", + " [241.19999683, 242.49999997, 243.50000003]],\n", + "\n", + " [[296.29000854, 297.19998169, 297.3999939 ],\n", + " [296.26818385, 297.07876957, 297.25211866],\n", + " [296.24635916, 296.95755744, 297.10424342],\n", + " ...,\n", + " [242.82726354, 243.37878187, 243.63332714],\n", + " [242.46362716, 243.03938941, 243.36665899],\n", + " [242.09999079, 242.69999695, 243.09999084]],\n", + "\n", + " [[296.3999939 , 296.29000854, 296.3999939 ],\n", + " [296.35150609, 296.34091556, 296.37333078],\n", + " [296.30301828, 296.39182258, 296.34666767],\n", + " ...,\n", + " [243.4151408 , 243.26181628, 243.12423612],\n", + " [242.85756431, 242.73090659, 242.71211194],\n", + " [242.29998782, 242.19999689, 242.29998776]],\n", + "\n", + " [[297.5 , 297.69998169, 297.5 ],\n", + " [297.37878788, 297.65150128, 297.40303179],\n", + " [297.25757575, 297.60302087, 297.30606357],\n", + " ...,\n", + " [244.02817552, 243.49695752, 242.96362858],\n", + " [242.9590874 , 242.64847269, 242.38180817],\n", + " [241.88999927, 241.79998785, 241.79998776]]])\n", + "Coordinates:\n", + " * lon (lon) float32 200.0 202.5 205.0\n", + " * time (time) datetime64[ns] 2013-01-01 ... 2013-01-01T18:00:00\n", + " * lat (lat) float64 15.0 15.61 16.21 16.82 ... 73.18 73.79 74.39 75.0\n", + "Attributes:\n", + " long_name: 4xDaily Air temperature at sigma level 995\n", + " units: degK\n", + " precision: 2\n", + " GRIB_id: 11\n", + " GRIB_name: TMP\n", + " var_desc: Air temperature\n", + " dataset: NMC Reanalysis\n", + " level_desc: Surface\n", + " statistic: Individual Obs\n", + " parent_stat: Other\n", + " actual_range: [185.16 322.1 ]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "newlat = np.linspace(15, 75,100)\n", - "%timeit air.interp(lat=newlat)" + "newlat = np.linspace(15, 75, 100)\n", + "air.interp(lat=newlat)" ] }, { @@ -652,11 +1102,11 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 3, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:44.229304Z", - "start_time": "2019-12-16T16:22:44.190341Z" + "end_time": "2019-12-30T15:55:17.947482Z", + "start_time": "2019-12-30T15:55:17.914823Z" } }, "outputs": [], @@ -664,21 +1114,23 @@ "def interp1d_np(data, x, xi):\n", " return np.interp(xi, x, data)\n", "\n", + "\n", "interped = interp1d_np(air.isel(time=0, lon=0), air.lat, newlat)\n", "expected = air.interp(lat=newlat)\n", "\n", "# no errors are raised if values are equal to within floating point precision\n", - "np.testing.assert_allclose(expected.isel(time=0, lon=0).values,\n", - " interped)" + "np.testing.assert_allclose(expected.isel(time=0, lon=0).values, interped)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "No errors are raised so our interpolation is working.\n", + "### No errors are raised so our interpolation is working.\n", "\n", - "This function consumes and returns numpy arrays, which means we need to do a lot of work to convert the result back to an xarray object with meaningful metadata. Enter `apply_ufunc` \n", + "This function consumes and returns numpy arrays, which means we need to do a lot of work to convert the result back to an xarray object with meaningful metadata. This is where `apply_ufunc` is very useful.\n", + "\n", + "### `apply_ufunc`\n", "\n", " Apply a vectorized function for unlabeled arrays on xarray objects.\n", "\n", @@ -686,16 +1138,16 @@ " xarray’s standard rules for labeled computation, including alignment, broadcasting, \n", " looping over GroupBy/Dataset variables, and merging of coordinates.\n", " \n", - "`apply_ufunc` has many capabilities but this example will be relatively simple and focus on the relatively common task of vectorizing 1D functions over nD xarray objects. We will iteratively build up the right set of arguments to `apply_ufunc` and read through many error messages in the process of doing so." + "`apply_ufunc` has many capabilities but for simplicity this example will focus on the common task of vectorizing 1D functions over nD xarray objects. We will iteratively build up the right set of arguments to `apply_ufunc` and read through many error messages in doing so." ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:45.805695Z", - "start_time": "2019-12-16T16:22:45.759727Z" + "end_time": "2019-12-30T15:55:23.185371Z", + "start_time": "2019-12-30T15:55:23.145380Z" } }, "outputs": [ @@ -706,35 +1158,41 @@ "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 2\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlon\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# now arguments in the order expected by 'interp1_np'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m newlat)\n\u001b[0m", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 633\u001b[0m \u001b[0;34m\"dimensions specified in ``exclude_dims`` with \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 634\u001b[0m \"xarray.apply_ufunc are allowed to change size.\".format(\n\u001b[0;32m--> 635\u001b[0;31m \u001b[0mdim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim_sizes\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdim\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew_size\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 636\u001b[0m )\n\u001b[1;32m 637\u001b[0m )\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlon\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# now arguments in the order expected by 'interp1_np'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mnewlat\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 6\u001b[0m )\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 633\u001b[0m \u001b[0;34m\"dimensions specified in ``exclude_dims`` with \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 634\u001b[0m \"xarray.apply_ufunc are allowed to change size.\".format(\n\u001b[0;32m--> 635\u001b[0;31m \u001b[0mdim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim_sizes\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdim\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew_size\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 636\u001b[0m )\n\u001b[1;32m 637\u001b[0m )\n", "\u001b[0;31mValueError\u001b[0m: size of dimension 'lat' on inputs was unexpectedly changed by applied function from 25 to 100. Only dimensions specified in ``exclude_dims`` with xarray.apply_ufunc are allowed to change size." ] } ], "source": [ - "xr.apply_ufunc(interp1d_np, # first the function\n", - " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", - " air.lat,\n", - " newlat)" + "xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### exclude_dims\n", - "\n" + "`apply_ufunc` needs to know a lot of information about what our function does so that it can reconstruct the outputs. In this case, the size of dimension lat has changed and we need to explicitly specify that this will happen. xarray helpfully tells us that we need to specify the kwarg `exclude_dims`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### `exclude_dims`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "`apply_ufunc` needs to know a lot of information about what our function does so that it can reconstruct the outputs. In this case, the size of dimension lat has changed and we need to explicitly specify that this will happen. xarray helpfully tells us that we need to specify the kwarg `exclude_dims`.\n", - "\n", "\n", "```\n", "exclude_dims : set, optional\n", @@ -748,11 +1206,11 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 6, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:47.652680Z", - "start_time": "2019-12-16T16:22:47.609161Z" + "end_time": "2019-12-30T15:55:24.910186Z", + "start_time": "2019-12-30T15:55:24.860198Z" } }, "outputs": [ @@ -763,18 +1221,19 @@ "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 3\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mnewlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m )\n", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 982\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mexclude_dims\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mexclude_dims\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mall_core_dims\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 983\u001b[0m raise ValueError(\n\u001b[0;32m--> 984\u001b[0;31m \u001b[0;34m\"each dimension in `exclude_dims` must also be a \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 985\u001b[0m \u001b[0;34m\"core dimension in the function signature\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 986\u001b[0m )\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mnewlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m )\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 982\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mexclude_dims\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mexclude_dims\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mall_core_dims\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 983\u001b[0m raise ValueError(\n\u001b[0;32m--> 984\u001b[0;31m \u001b[0;34m\"each dimension in `exclude_dims` must also be a \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 985\u001b[0m \u001b[0;34m\"core dimension in the function signature\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 986\u001b[0m )\n", "\u001b[0;31mValueError\u001b[0m: each dimension in `exclude_dims` must also be a core dimension in the function signature" ] } ], "source": [ - "xr.apply_ufunc(interp1d_np, # first the function\n", - " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", - " air.lat,\n", - " newlat,\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + "xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be set!\n", ")" ] }, @@ -790,8 +1249,6 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "DESCRIBE CORE DIMENSIONS.\n", - "\n", "Core dimensions are central to using `apply_ufunc`. In our case, our function expects to receive a 1D vector along `lat` — this is the dimension that is \"core\" to the function's functionality. Multiple core dimensions are possible. `apply_ufunc` needs to know which dimensions of each variable are core dimensions.\n", "\n", " input_core_dims : Sequence[Sequence], optional\n", @@ -822,11 +1279,11 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 7, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:50.002819Z", - "start_time": "2019-12-16T16:22:49.945144Z" + "end_time": "2019-12-30T15:55:26.828645Z", + "start_time": "2019-12-30T15:55:26.786129Z" } }, "outputs": [ @@ -837,21 +1294,22 @@ "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 4\u001b[0m \u001b[0mnewlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0minput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\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[0;32m----> 6\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m )\n", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 621\u001b[0m \u001b[0;34m\"applied function returned data with unexpected \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \"number of dimensions: {} vs {}, for dimensions {}\".format(\n\u001b[0;32m--> 623\u001b[0;31m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdims\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdims\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 624\u001b[0m )\n\u001b[1;32m 625\u001b[0m )\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mnewlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0minput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\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[0;32m----> 7\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m )\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 621\u001b[0m \u001b[0;34m\"applied function returned data with unexpected \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \"number of dimensions: {} vs {}, for dimensions {}\".format(\n\u001b[0;32m--> 623\u001b[0;31m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdims\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdims\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 624\u001b[0m )\n\u001b[1;32m 625\u001b[0m )\n", "\u001b[0;31mValueError\u001b[0m: applied function returned data with unexpected number of dimensions: 1 vs 0, for dimensions ()" ] } ], "source": [ - "xr.apply_ufunc(interp1d_np, # first the function\n", - " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", - " air.lat,\n", - " newlat,\n", - " input_core_dims=[[\"lat\"], [\"lat\"], []],\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + "xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []],\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be set!\n", ")" ] }, @@ -864,11 +1322,11 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 8, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:52.333458Z", - "start_time": "2019-12-16T16:22:52.289070Z" + "end_time": "2019-12-30T15:55:28.540895Z", + "start_time": "2019-12-30T15:55:28.491272Z" } }, "outputs": [ @@ -1209,7 +1667,7 @@ " stroke: currentColor;\n", " fill: currentColor;\n", "}\n", - "
    xarray.DataArray
    • lat: 100
    • 296.3 296.2 296.1 296.0 295.9 296.0 ... 243.7 243.1 242.5 241.8 241.2
      array([296.29000854, 296.19545954, 296.10091053, 296.00636153,\n",
      +       "
      xarray.DataArray
      • lat: 100
      • 296.3 296.2 296.1 296.0 295.9 296.0 ... 243.7 243.1 242.5 241.8 241.2
        array([296.29000854, 296.19545954, 296.10091053, 296.00636153,\n",
                "       295.91181252, 296.04848133, 296.21818126, 296.38788119,\n",
                "       296.55758112, 296.67273227, 296.76970048, 296.8666687 ,\n",
                "       296.96363692, 296.75757483, 296.36969457, 295.9818143 ,\n",
        @@ -1233,7 +1691,7 @@
                "       271.59090909, 269.65151515, 267.71212121, 265.        ,\n",
                "       261.        , 257.        , 253.        , 249.62424168,\n",
                "       248.12120842, 246.61817516, 245.1151419 , 243.72120019,\n",
        -       "       243.09089938, 242.46059857, 241.83029776, 241.19999695])
        • lon
          ()
          float32
          200.0
          standard_name :
          longitude
          long_name :
          Longitude
          units :
          degrees_east
          axis :
          X
          array(200., dtype=float32)
        • time
          ()
          datetime64[ns]
          2013-01-01
          standard_name :
          time
          long_name :
          Time
          array('2013-01-01T00:00:00.000000000', dtype='datetime64[ns]')
      " + " 243.09089938, 242.46059857, 241.83029776, 241.19999695])
    • lon
      ()
      float32
      200.0
      standard_name :
      longitude
      long_name :
      Longitude
      units :
      degrees_east
      axis :
      X
      array(200., dtype=float32)
    • time
      ()
      datetime64[ns]
      2013-01-01
      standard_name :
      time
      long_name :
      Time
      array('2013-01-01T00:00:00.000000000', dtype='datetime64[ns]')
  • " ], "text/plain": [ "\n", @@ -1268,19 +1726,20 @@ "Dimensions without coordinates: lat" ] }, - "execution_count": 12, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "xr.apply_ufunc(interp1d_np, # first the function\n", - " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", - " air.lat,\n", - " newlat,\n", - " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", - " output_core_dims=[[\"lat\"]],\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + "xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", + " output_core_dims=[[\"lat\"]],\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be set!\n", ")" ] }, @@ -1294,22 +1753,23 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:53.929091Z", - "start_time": "2019-12-16T16:22:53.878782Z" + "end_time": "2019-12-30T15:55:30.635880Z", + "start_time": "2019-12-30T15:55:30.597561Z" } }, "outputs": [], "source": [ - "interped = xr.apply_ufunc(interp1d_np, # first the function\n", - " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", - " air.lat,\n", - " newlat,\n", - " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", - " output_core_dims=[[\"lat\"]],\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + "interped = xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air.isel(time=0, lon=0), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", + " output_core_dims=[[\"lat\"]],\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be set!\n", ")\n", "interped[\"lat\"] = newlat # need to add this manually\n", "xr.testing.assert_allclose(expected.isel(time=0, lon=0), interped)" @@ -1319,8 +1779,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "It is right!\n", - "\n" + "No errors are raised so it is right!" ] }, { @@ -1340,11 +1799,11 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 10, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:55.223514Z", - "start_time": "2019-12-16T16:22:55.191870Z" + "end_time": "2019-12-30T15:55:49.784745Z", + "start_time": "2019-12-30T15:55:49.713572Z" } }, "outputs": [ @@ -1362,11 +1821,11 @@ "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 9\u001b[0m \u001b[0minput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# list with one entry per arg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0moutput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\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[0;32m---> 11\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m )\n\u001b[1;32m 13\u001b[0m \u001b[0minterped\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewlat\u001b[0m \u001b[0;31m# need to add this manually\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\"apply_ufunc: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 600\u001b[0m )\n\u001b[0;32m--> 601\u001b[0;31m \u001b[0mresult_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput_data\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 602\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 603\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m\u001b[0m in \u001b[0;36minterp1d_np\u001b[0;34m(data, x, xi)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0minterp1d_np\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxi\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[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minterp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\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 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m interped = xr.apply_ufunc(interp1d_np, # first the function\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0minput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# list with one entry per arg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0moutput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\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[0;32m---> 15\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m )\n\u001b[1;32m 17\u001b[0m \u001b[0minterped\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewlat\u001b[0m \u001b[0;31m# need to add this manually\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\"apply_ufunc: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 600\u001b[0m )\n\u001b[0;32m--> 601\u001b[0;31m \u001b[0mresult_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput_data\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 602\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 603\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36minterp1d_np\u001b[0;34m(data, x, xi)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0minterp1d_np\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxi\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[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minterp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\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 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36minterp\u001b[0;34m(*args, **kwargs)\u001b[0m\n", "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/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 1410\u001b[0m \u001b[0mfp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconcatenate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\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[1;32m 1411\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1412\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[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1413\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1414\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: object too deep for desired array" @@ -1378,13 +1837,17 @@ " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", " return np.interp(xi, x, data)\n", "\n", - "interped = xr.apply_ufunc(interp1d_np, # first the function\n", - " air.isel(lon=slice(3), time=slice(4)), # now arguments in the order expected by 'interp1_np'\n", - " air.lat,\n", - " newlat,\n", - " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", - " output_core_dims=[[\"lat\"]],\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", + "\n", + "interped = xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air.isel(\n", + " lon=slice(3), time=slice(4)\n", + " ), # now arguments in the order expected by 'interp1_np'\n", + " air.lat,\n", + " newlat,\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", + " output_core_dims=[[\"lat\"]],\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be set!\n", ")\n", "interped[\"lat\"] = newlat # need to add this manually\n", "xr.testing.assert_allclose(expected.isel(time=0, lon=0), interped)" @@ -1412,11 +1875,11 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 11, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:57.534630Z", - "start_time": "2019-12-16T16:22:57.468197Z" + "end_time": "2019-12-30T15:55:58.486339Z", + "start_time": "2019-12-30T15:55:58.420859Z" } }, "outputs": [ @@ -1427,10 +1890,10 @@ "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 10\u001b[0m \u001b[0moutput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# returned data has one dimension\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0mvectorize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# loop over non-core dims\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 13\u001b[0m )\n\u001b[1;32m 14\u001b[0m \u001b[0minterped\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewlat\u001b[0m \u001b[0;31m# need to add this manually\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/work/python/xarray/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\"apply_ufunc: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 600\u001b[0m )\n\u001b[0;32m--> 601\u001b[0;31m \u001b[0mresult_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput_data\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 602\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 603\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0moutput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# returned data has one dimension\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m \u001b[0mvectorize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# loop over non-core dims\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 15\u001b[0m )\n\u001b[1;32m 16\u001b[0m \u001b[0minterped\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewlat\u001b[0m \u001b[0;31m# need to add this manually\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\"apply_ufunc: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 600\u001b[0m )\n\u001b[0;32m--> 601\u001b[0;31m \u001b[0mresult_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput_data\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 602\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 603\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 2089\u001b[0m \u001b[0mvargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0m_n\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_n\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mnames\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[1;32m 2090\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2091\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_vectorize_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvargs\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 2092\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2093\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_get_ufunc_and_otypes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m_vectorize_call\u001b[0;34m(self, func, args)\u001b[0m\n\u001b[1;32m 2155\u001b[0m \u001b[0;34m\"\"\"Vectorized call to `func` over positional `args`.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2156\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msignature\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2157\u001b[0;31m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_vectorize_call_with_signature\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\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 2158\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2159\u001b[0m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m_vectorize_call_with_signature\u001b[0;34m(self, func, args)\u001b[0m\n\u001b[1;32m 2185\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2186\u001b[0m broadcast_shape, dim_sizes = _parse_input_dimensions(\n\u001b[0;32m-> 2187\u001b[0;31m args, input_core_dims)\n\u001b[0m\u001b[1;32m 2188\u001b[0m input_shapes = _calculate_shapes(broadcast_shape, dim_sizes,\n\u001b[1;32m 2189\u001b[0m input_core_dims)\n", @@ -1445,14 +1908,16 @@ " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", " return np.interp(xi, x, data)\n", "\n", - "interped = xr.apply_ufunc(interp1d_np, # first the function\n", - " air, # now arguments in the order expected by 'interp1_np'\n", - " air.lat, # as above\n", - " newlat, # as above\n", - " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", - " output_core_dims=[[\"lat\"]], # returned data has one dimension\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be set!\n", - " vectorize=True, # loop over non-core dims\n", + "\n", + "interped = xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air, # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], []], # list with one entry per arg\n", + " output_core_dims=[[\"lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be set!\n", + " vectorize=True, # loop over non-core dims\n", ")\n", "interped[\"lat\"] = newlat # need to add this manually\n", "xr.testing.assert_allclose(expected, interped)" @@ -1469,11 +1934,11 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 12, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:22:59.872389Z", - "start_time": "2019-12-16T16:22:59.799915Z" + "end_time": "2019-12-30T15:56:02.358157Z", + "start_time": "2019-12-30T15:56:02.301059Z" } }, "outputs": [ @@ -1832,7 +2297,7 @@ " stroke: currentColor;\n", " fill: currentColor;\n", "}\n", - "
    xarray.DataArray
    • time: 4
    • lon: 3
    • lat: 100
    • 296.3 296.2 296.1 296.0 295.9 296.0 ... 244.1 243.5 243.0 242.4 241.8
      array([[[296.29000854, 296.19545954, 296.10091053, ..., 242.46059857,\n",
      +       "
      xarray.DataArray
      • time: 4
      • lon: 3
      • lat: 100
      • 296.3 296.2 296.1 296.0 295.9 296.0 ... 244.1 243.5 243.0 242.4 241.8
        array([[[296.29000854, 296.19545954, 296.10091053, ..., 242.46059857,\n",
                "         241.83029776, 241.19999695],\n",
                "        [296.79000854, 296.64697173, 296.50393492, ..., 243.46969697,\n",
                "         242.98484848, 242.5       ],\n",
        @@ -1858,9 +2323,9 @@
                "        [297.69998169, 297.65150128, 297.60302087, ..., 243.49695749,\n",
                "         242.64847264, 241.79998779],\n",
                "        [297.5       , 297.40303178, 297.30606357, ..., 242.9636286 ,\n",
        -       "         242.38180819, 241.79998779]]])
        • lon
          (lon)
          float32
          200.0 202.5 205.0
          standard_name :
          longitude
          long_name :
          Longitude
          units :
          degrees_east
          axis :
          X
          array([200. , 202.5, 205. ], dtype=float32)
        • time
          (time)
          datetime64[ns]
          2013-01-01 ... 2013-01-01T18:00:00
          standard_name :
          time
          long_name :
          Time
          array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
          +       "         242.38180819, 241.79998779]]])
        • lon
          (lon)
          float32
          200.0 202.5 205.0
          standard_name :
          longitude
          long_name :
          Longitude
          units :
          degrees_east
          axis :
          X
          array([200. , 202.5, 205. ], dtype=float32)
        • time
          (time)
          datetime64[ns]
          2013-01-01 ... 2013-01-01T18:00:00
          standard_name :
          time
          long_name :
          Time
          array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
                  "       '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000'],\n",
          -       "      dtype='datetime64[ns]')
        • lat
          (lat)
          float64
          15.0 15.61 16.21 ... 74.39 75.0
          array([15.      , 15.606061, 16.212121, 16.818182, 17.424242, 18.030303,\n",
          +       "      dtype='datetime64[ns]')
        • lat
          (lat)
          float64
          15.0 15.61 16.21 ... 74.39 75.0
          array([15.      , 15.606061, 16.212121, 16.818182, 17.424242, 18.030303,\n",
                  "       18.636364, 19.242424, 19.848485, 20.454545, 21.060606, 21.666667,\n",
                  "       22.272727, 22.878788, 23.484848, 24.090909, 24.69697 , 25.30303 ,\n",
                  "       25.909091, 26.515152, 27.121212, 27.727273, 28.333333, 28.939394,\n",
          @@ -1876,7 +2341,7 @@
                  "       62.272727, 62.878788, 63.484848, 64.090909, 64.69697 , 65.30303 ,\n",
                  "       65.909091, 66.515152, 67.121212, 67.727273, 68.333333, 68.939394,\n",
                  "       69.545455, 70.151515, 70.757576, 71.363636, 71.969697, 72.575758,\n",
          -       "       73.181818, 73.787879, 74.393939, 75.      ])
      " + " 73.181818, 73.787879, 74.393939, 75. ])
  • " ], "text/plain": [ "\n", @@ -1913,7 +2378,7 @@ " * lat (lat) float64 15.0 15.61 16.21 16.82 ... 73.18 73.79 74.39 75.0" ] }, - "execution_count": 16, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -1923,19 +2388,22 @@ " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", " return np.interp(xi, x, data)\n", "\n", - "interped = xr.apply_ufunc(interp1d_np, # first the function\n", - " air, # now arguments in the order expected by 'interp1_np'\n", - " air.lat, # as above\n", - " newlat, # as above\n", - " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", - " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be a set!\n", - " vectorize=True, # loop over non-core dims\n", + "\n", + "interped = xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air, # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", + " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be a set!\n", + " vectorize=True, # loop over non-core dims\n", ")\n", "interped = interped.rename({\"new_lat\": \"lat\"})\n", "interped[\"lat\"] = newlat # need to add this manually\n", - "xr.testing.assert_allclose(expected.transpose(*interped.dims), # order of dims is different\n", - " interped)\n", + "xr.testing.assert_allclose(\n", + " expected.transpose(*interped.dims), interped # order of dims is different\n", + ")\n", "interped" ] }, @@ -1977,11 +2445,11 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 13, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:23:02.553343Z", - "start_time": "2019-12-16T16:23:02.487649Z" + "end_time": "2019-12-30T15:56:07.327214Z", + "start_time": "2019-12-30T15:56:07.265287Z" } }, "outputs": [ @@ -1993,11 +2461,11 @@ "data: (25,) | x: (25,) | xi: (100,)\n", "data: (25,) | x: (25,) | xi: (100,)\n", "data: (25,) | x: (25,) | xi: (100,)\n", + "data: (25,) | x: (25,) | xi: (100,)data: (25,) | x: (25,) | xi: (100,)data: (25,) | x: (25,) | xi: (100,)\n", "data: (25,) | x: (25,) | xi: (100,)\n", "data: (25,) | x: (25,) | xi: (100,)\n", + "\n", "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)data: (25,) | x: (25,) | xi: (100,)\n", "\n", "data: (25,) | x: (25,) | xi: (100,)\n", "data: (25,) | x: (25,) | xi: (100,)\n" @@ -2009,20 +2477,23 @@ " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", " return np.interp(xi, x, data)\n", "\n", - "interped = xr.apply_ufunc(interp1d_np, # first the function\n", - " air.chunk({\"time\": 2, \"lon\": 2}), # now arguments in the order expected by 'interp1_np'\n", - " air.lat, # as above\n", - " newlat, # as above\n", - " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", - " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be a set!\n", - " vectorize=True, # loop over non-core dims\n", - " dask=\"parallelized\",\n", - " output_dtypes=[float], # one per output\n", + "\n", + "interped = xr.apply_ufunc(\n", + " interp1d_np, # first the function\n", + " air.chunk(\n", + " {\"time\": 2, \"lon\": 2}\n", + " ), # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", + " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be a set!\n", + " vectorize=True, # loop over non-core dims\n", + " dask=\"parallelized\",\n", + " output_dtypes=[float], # one per output\n", ").rename({\"new_lat\": \"lat\"})\n", "interped[\"lat\"] = newlat # need to add this manually\n", - "xr.testing.assert_allclose(expected.transpose(*interped.dims),\n", - " interped)" + "xr.testing.assert_allclose(expected.transpose(*interped.dims), interped)" ] }, { @@ -2050,6 +2521,7 @@ "Another option is to use the numba package which provides a very convenient `guvectorize` decorator: https://numba.pydata.org/numba-doc/latest/user/vectorize.html#the-guvectorize-decorator\n", "\n", "Any decorated function gets compiled and will loop over any non-core dimension in parallel when necessary. We need to specify some extra information:\n", + "\n", " 1. Our function cannot return a variable any more. Instead it must receive a variable (the last argument) whose contents the function will modify. So we change from `def interp1d_np(data, x, xi)` to `def interp1d_np_gufunc(data, x, xi, out)`. Our computed results must be assigned to `out`. All values of `out` must be assigned explicitly.\n", " \n", " 2. `guvectorize` needs to know the dtypes of the input and output. This is specified in string form as the first argument. Each element of the tuple corresponds to each argument of the function. In this case, we specify `float64` for all inputs and outputs: `\"(float64[:], float64[:], float64[:], float64[:])\"` corresponding to `data, x, xi, out`\n", @@ -2060,11 +2532,11 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 14, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:23:05.780075Z", - "start_time": "2019-12-16T16:23:04.552713Z" + "end_time": "2019-12-30T15:56:26.013431Z", + "start_time": "2019-12-30T15:56:24.675876Z" } }, "outputs": [ @@ -2072,7 +2544,7 @@ "name": "stderr", "output_type": "stream", "text": [ - ":2: NumbaWarning: \n", + ":4: NumbaWarning: \n", "Compilation is falling back to object mode WITHOUT looplifting enabled because Function \"interp1d_np_gufunc\" failed type inference due to: Invalid use of Function() with argument(s) of type(s): (tuple(int64 x 1))\n", " * parameterized\n", "In definition 0:\n", @@ -2085,21 +2557,21 @@ " All templates rejected without literals.\n", "This error is usually caused by passing an argument of a type that is unsupported by the named function.\n", "[1] During: resolving callee type: Function()\n", - "[2] During: typing of call at (7)\n", + "[2] During: typing of call at (9)\n", "\n", "\n", - "File \"\", line 7:\n", + "File \"\", line 9:\n", "def interp1d_np_gufunc(data, x, xi, out):\n", " \n", - " # seem to support fstrings so do it the old way\n", - " print(\"data: \" + str(data.shape) + \" | x:\" + str(x.shape) + \" | xi: \" + str(xi.shape))\n", - " ^\n", + " print(\n", + " \"data: \" + str(data.shape) + \" | x:\" + str(x.shape) + \" | xi: \" + str(xi.shape)\n", + " ^\n", "\n", - " @guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\",\n", + " @guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", "/home/deepak/miniconda3/envs/dcpy/lib/python3.7/site-packages/numba/object_mode_passes.py:178: NumbaWarning: Function \"interp1d_np_gufunc\" was compiled in object mode without forceobj=True.\n", "\n", - "File \"\", line 4:\n", - " \"(n), (n), (m) -> (m)\")\n", + "File \"\", line 5:\n", + "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", "def interp1d_np_gufunc(data, x, xi, out):\n", "^\n", "\n", @@ -2109,8 +2581,8 @@ "\n", "For more information visit http://numba.pydata.org/numba-doc/latest/reference/deprecation.html#deprecation-of-object-mode-fall-back-behaviour-when-using-jit\n", "\n", - "File \"\", line 4:\n", - " \"(n), (n), (m) -> (m)\")\n", + "File \"\", line 5:\n", + "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", "def interp1d_np_gufunc(data, x, xi, out):\n", "^\n", "\n", @@ -2120,12 +2592,15 @@ ], "source": [ "from numba import float64, guvectorize\n", - "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\",\n", - " \"(n), (n), (m) -> (m)\")\n", + "\n", + "\n", + "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", "def interp1d_np_gufunc(data, x, xi, out):\n", " # numba doesn't really like this.\n", " # seem to support fstrings so do it the old way\n", - " print(\"data: \" + str(data.shape) + \" | x:\" + str(x.shape) + \" | xi: \" + str(xi.shape))\n", + " print(\n", + " \"data: \" + str(data.shape) + \" | x:\" + str(x.shape) + \" | xi: \" + str(xi.shape)\n", + " )\n", " out[:] = np.interp(xi, x, data)\n", " # gufuncs don't return data\n", " # instead you assign to a the last arg\n", @@ -2141,11 +2616,11 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 15, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:23:05.988773Z", - "start_time": "2019-12-16T16:23:05.957159Z" + "end_time": "2019-12-30T15:56:28.007342Z", + "start_time": "2019-12-30T15:56:27.955422Z" } }, "outputs": [ @@ -2153,105 +2628,96 @@ "name": "stdout", "output_type": "stream", "text": [ + "data: (25,) | x:(25,) | xi: (100,)\n", "data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)\n", "data: (25,) | x:(25,) | xi: (100,)\n", "data: (25,) | x:(25,) | xi: (100,)\n", "\n", - "data: (25,) | x:(25,) | xi: (100,)\n", - "data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)\n", - "data: (25,) | x:(25,) | xi: (100,)\n", + "data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)\n", + "\n", + "\n", "data: (25,) | x:(25,) | xi: (100,)\n", "data: (25,) | x:(25,) | xi: (100,)\n", "data: (25,) | x:(25,) | xi: (100,)\n", - "\n", "data: (25,) | x:(25,) | xi: (100,)\n" ] } ], "source": [ - "interped = xr.apply_ufunc(interp1d_np_gufunc, # first the function\n", - " air.chunk({\"time\": 2, \"lon\": 2}), # now arguments in the order expected by 'interp1_np'\n", - " air.lat, # as above\n", - " newlat, # as above\n", - " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", - " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be a set!\n", - " # vectorize=True, # not needed since numba takes care of vectorizing\n", - " dask=\"parallelized\",\n", - " output_dtypes=[float], # one per output\n", + "interped = xr.apply_ufunc(\n", + " interp1d_np_gufunc, # first the function\n", + " air.chunk(\n", + " {\"time\": 2, \"lon\": 2}\n", + " ), # now arguments in the order expected by 'interp1_np'\n", + " air.lat, # as above\n", + " newlat, # as above\n", + " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", + " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", + " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be a set!\n", + " # vectorize=True, # not needed since numba takes care of vectorizing\n", + " dask=\"parallelized\",\n", + " output_dtypes=[float], # one per output\n", ").rename({\"new_lat\": \"lat\"})\n", "interped[\"lat\"] = newlat # need to add this manually\n", - "xr.testing.assert_allclose(expected.transpose(*interped.dims),\n", - " interped)" + "xr.testing.assert_allclose(expected.transpose(*interped.dims), interped)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Yay! Our function is receiving 1D vectors and is working automatically with dask arrays. Finally let's comment out the print line" + "Yay! Our function is receiving 1D vectors and is working automatically with dask arrays. Finally let's comment out the print line and wrap everything up in a nice reusable function" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 29, "metadata": { "ExecuteTime": { - "end_time": "2019-12-16T16:23:08.538982Z", - "start_time": "2019-12-16T16:23:08.192798Z" + "end_time": "2019-12-30T16:11:59.152918Z", + "start_time": "2019-12-30T16:11:58.820458Z" } }, "outputs": [], "source": [ - "from numba import float64, guvectorize\n", - "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\",\n", - " \"(n), (n), (m) -> (m)\")\n", + "from numba import float64, guvectorize, njit\n", + "\n", + "\n", + "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", "def interp1d_np_gufunc(data, x, xi, out):\n", " out[:] = np.interp(xi, x, data)\n", "\n", - "interped = xr.apply_ufunc(interp1d_np_gufunc, # first the function\n", - " air.chunk({\"time\": 2, \"lon\": 2}), # now arguments in the order expected by 'interp1_np'\n", - " air.lat, # as above\n", - " newlat, # as above\n", - " input_core_dims=[[\"lat\"], [\"lat\"], [\"new_lat\"]], # list with one entry per arg\n", - " output_core_dims=[[\"new_lat\"]], # returned data has one dimension\n", - " exclude_dims=set((\"lat\", )), # dimensions allowed to change size. Must be a set!\n", - " # vectorize=True, # not needed since numba takes care of vectorizing\n", - " dask=\"parallelized\",\n", - " output_dtypes=[float], # one per output\n", - ").rename({\"new_lat\": \"lat\"})\n", - "interped[\"lat\"] = newlat # need to add this manually\n", - "xr.testing.assert_allclose(expected.transpose(*interped.dims),\n", - " interped)" + "\n", + "def xr_interp(data, dim, newdim):\n", + "\n", + " interped = xr.apply_ufunc(\n", + " interp1d_np_gufunc, # first the function\n", + " data, # now arguments in the order expected by 'interp1_np'\n", + " data[dim], # as above\n", + " newdim, # as above\n", + " input_core_dims=[[dim], [dim], [\"__newdim__\"]], # list with one entry per arg\n", + " output_core_dims=[[\"__newdim__\"]], # returned data has one dimension\n", + " exclude_dims=set((dim,)), # dimensions allowed to change size. Must be a set!\n", + " # vectorize=True, # not needed since numba takes care of vectorizing\n", + " dask=\"parallelized\",\n", + " output_dtypes=[float], # one per output\n", + " ).rename({\"__newdim__\": dim})\n", + " interped[dim] = newdim # need to add this manually\n", + "\n", + " return interped\n", + "\n", + "\n", + "xr.testing.assert_allclose(\n", + " expected.transpose(*interped.dims),\n", + " xr_interp(air.chunk({\"time\": 2, \"lon\": 2}), \"lat\", newlat),\n", + ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This works at basically the same speed as the original interpolation but the technique is generalizable to any 1D function" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "metadata": { - "ExecuteTime": { - "end_time": "2019-12-16T16:03:39.896523Z", - "start_time": "2019-12-16T16:03:37.905326Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.42 ms ± 204 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" - ] - } - ], - "source": [ - "%timeit interped.compute()" + "This technique is generalizable to any 1D function." ] } ], @@ -2271,7 +2737,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.7.6" }, "nbsphinx": { "allow_errors": true From 8e5ec06f67f7130a3cc5bd4bf9dd1207b0211a90 Mon Sep 17 00:00:00 2001 From: dcherian Date: Mon, 30 Dec 2019 19:44:14 -0700 Subject: [PATCH 3/4] Review + strip output. --- doc/examples.rst | 4 +- doc/examples/apply_ufunc_vectorize_1d.ipynb | 2098 +------------------ 2 files changed, 36 insertions(+), 2066 deletions(-) diff --git a/doc/examples.rst b/doc/examples.rst index b58fa986fda..3067ca824be 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -11,8 +11,8 @@ Examples examples/ROMS_ocean_model examples/ERA5-GRIB-example -apply_ufunc ------------- +Using apply_ufunc +------------------ .. toctree:: :maxdepth: 2 diff --git a/doc/examples/apply_ufunc_vectorize_1d.ipynb b/doc/examples/apply_ufunc_vectorize_1d.ipynb index ccec9106cd9..0d98b6a6d33 100644 --- a/doc/examples/apply_ufunc_vectorize_1d.ipynb +++ b/doc/examples/apply_ufunc_vectorize_1d.ipynb @@ -33,587 +33,14 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:54:59.861486Z", "start_time": "2019-12-30T15:54:58.773827Z" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - "Show/Hide data repr\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "Show/Hide attributes\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
    xarray.DataArray
    'air'
    • time: 4
    • lat: 25
    • lon: 3
    • 296.29 296.79 297.1 295.9 ... 244.2 241.89 241.79999 241.79999
      array([[[296.29   , 296.79   , 297.1    ],\n",
      -       "        [295.9    , 296.19998, 296.79   ],\n",
      -       "        [296.6    , 296.19998, 296.4    ],\n",
      -       "        [297.     , 296.69998, 296.1    ],\n",
      -       "        [295.4    , 295.69998, 295.79   ],\n",
      -       "        [293.79   , 294.1    , 294.6    ],\n",
      -       "        [293.1    , 293.29   , 293.29   ],\n",
      -       "        [290.19998, 290.79   , 291.4    ],\n",
      -       "        [287.9    , 288.     , 288.29   ],\n",
      -       "        [286.5    , 286.5    , 285.69998],\n",
      -       "        [284.6    , 284.9    , 284.19998],\n",
      -       "        [282.79   , 283.19998, 282.6    ],\n",
      -       "        [280.     , 280.69998, 280.19998],\n",
      -       "        [278.4    , 279.     , 279.     ],\n",
      -       "        [277.29   , 277.4    , 277.79   ],\n",
      -       "        [276.69998, 277.4    , 277.69998],\n",
      -       "        [275.9    , 276.9    , 276.9    ],\n",
      -       "        [274.79   , 275.19998, 275.6    ],\n",
      -       "        [273.69998, 273.6    , 273.79   ],\n",
      -       "        [272.1    , 270.9    , 270.     ],\n",
      -       "        [274.5    , 274.29   , 274.1    ],\n",
      -       "        [266.5    , 267.1    , 267.1    ],\n",
      -       "        [250.     , 249.79999, 248.89   ],\n",
      -       "        [243.79999, 244.5    , 244.7    ],\n",
      -       "        [241.2    , 242.5    , 243.5    ]],\n",
      -       "\n",
      -       "       [[296.29   , 297.19998, 297.4    ],\n",
      -       "        [296.19998, 296.69998, 296.79   ],\n",
      -       "        [296.4    , 295.9    , 296.19998],\n",
      -       "        [295.79   , 295.79   , 296.1    ],\n",
      -       "        [295.1    , 295.79   , 295.79   ],\n",
      -       "        [294.29   , 294.79   , 294.69998],\n",
      -       "        [293.19998, 293.9    , 294.19998],\n",
      -       "        [290.19998, 291.1    , 292.4    ],\n",
      -       "        [287.5    , 288.5    , 289.4    ],\n",
      -       "        [285.69998, 287.4    , 287.1    ],\n",
      -       "        [283.29   , 285.19998, 285.19998],\n",
      -       "        [281.4    , 282.79   , 283.5    ],\n",
      -       "        [279.19998, 280.19998, 280.79   ],\n",
      -       "        [277.79   , 278.5    , 279.29   ],\n",
      -       "        [276.29   , 276.4    , 277.29   ],\n",
      -       "        [275.79   , 276.     , 276.5    ],\n",
      -       "        [275.6    , 276.1    , 276.29   ],\n",
      -       "        [274.     , 274.4    , 275.1    ],\n",
      -       "        [272.1    , 272.69998, 273.19998],\n",
      -       "        [269.19998, 268.5    , 267.6    ],\n",
      -       "        [272.5    , 271.5    , 270.4    ],\n",
      -       "        [269.69998, 269.4    , 268.6    ],\n",
      -       "        [253.2    , 252.89   , 252.09999],\n",
      -       "        [243.59999, 244.09999, 244.2    ],\n",
      -       "        [242.09999, 242.7    , 243.09999]],\n",
      -       "\n",
      -       "       [[296.4    , 296.29   , 296.4    ],\n",
      -       "        [296.19998, 296.5    , 296.29   ],\n",
      -       "        [295.6    , 295.4    , 295.4    ],\n",
      -       "        [295.     , 295.     , 294.9    ],\n",
      -       "        [293.9    , 294.79   , 295.     ],\n",
      -       "        [293.29   , 293.9    , 294.4    ],\n",
      -       "        [292.4    , 292.9    , 293.4    ],\n",
      -       "        [289.5    , 289.79   , 291.19998],\n",
      -       "        [287.     , 287.1    , 288.29   ],\n",
      -       "        [284.9    , 285.6    , 286.4    ],\n",
      -       "        [282.     , 283.29   , 284.69998],\n",
      -       "        [280.     , 280.79   , 282.4    ],\n",
      -       "        [278.6    , 279.1    , 280.     ],\n",
      -       "        [277.6    , 277.9    , 278.6    ],\n",
      -       "        [276.     , 275.79   , 276.6    ],\n",
      -       "        [275.29   , 275.5    , 276.     ],\n",
      -       "        [274.5    , 275.6    , 276.1    ],\n",
      -       "        [274.29   , 275.     , 275.4    ],\n",
      -       "        [275.5    , 275.9    , 275.29   ],\n",
      -       "        [273.     , 273.5    , 272.9    ],\n",
      -       "        [271.9    , 271.79   , 271.6    ],\n",
      -       "        [269.29   , 268.5    , 267.     ],\n",
      -       "        [256.19998, 255.5    , 254.2    ],\n",
      -       "        [244.59999, 244.39   , 244.     ],\n",
      -       "        [242.29999, 242.2    , 242.29999]],\n",
      -       "\n",
      -       "       [[297.5    , 297.69998, 297.5    ],\n",
      -       "        [297.     , 297.5    , 297.1    ],\n",
      -       "        [296.6    , 296.4    , 296.     ],\n",
      -       "        [295.9    , 295.79   , 295.5    ],\n",
      -       "        [294.4    , 295.     , 295.4    ],\n",
      -       "        [293.     , 293.5    , 294.29   ],\n",
      -       "        [291.9    , 291.9    , 292.19998],\n",
      -       "        [289.19998, 289.4    , 289.9    ],\n",
      -       "        [286.6    , 287.1    , 287.9    ],\n",
      -       "        [284.79   , 284.79   , 285.4    ],\n",
      -       "        [282.79   , 282.     , 282.69998],\n",
      -       "        [281.19998, 280.19998, 280.6    ],\n",
      -       "        [279.5    , 278.69998, 278.6    ],\n",
      -       "        [278.     , 277.69998, 277.6    ],\n",
      -       "        [276.4    , 275.9    , 276.4    ],\n",
      -       "        [275.6    , 275.69998, 276.1    ],\n",
      -       "        [274.5    , 275.6    , 276.29   ],\n",
      -       "        [273.4    , 274.5    , 275.5    ],\n",
      -       "        [274.1    , 274.     , 273.5    ],\n",
      -       "        [273.29   , 272.6    , 271.5    ],\n",
      -       "        [272.79   , 272.4    , 271.9    ],\n",
      -       "        [267.69998, 266.29   , 264.4    ],\n",
      -       "        [256.6    , 254.7    , 252.09999],\n",
      -       "        [246.29999, 245.29999, 244.2    ],\n",
      -       "        [241.89   , 241.79999, 241.79999]]], dtype=float32)
      • lat
        (lat)
        float32
        15.0 17.5 20.0 ... 70.0 72.5 75.0
        standard_name :
        latitude
        long_name :
        Latitude
        units :
        degrees_north
        axis :
        Y
        array([15. , 17.5, 20. , 22.5, 25. , 27.5, 30. , 32.5, 35. , 37.5, 40. , 42.5,\n",
        -       "       45. , 47.5, 50. , 52.5, 55. , 57.5, 60. , 62.5, 65. , 67.5, 70. , 72.5,\n",
        -       "       75. ], dtype=float32)
      • lon
        (lon)
        float32
        200.0 202.5 205.0
        standard_name :
        longitude
        long_name :
        Longitude
        units :
        degrees_east
        axis :
        X
        array([200. , 202.5, 205. ], dtype=float32)
      • time
        (time)
        datetime64[ns]
        2013-01-01 ... 2013-01-01T18:00:00
        standard_name :
        time
        long_name :
        Time
        array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
        -       "       '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000'],\n",
        -       "      dtype='datetime64[ns]')
    • long_name :
      4xDaily Air temperature at sigma level 995
      units :
      degK
      precision :
      2
      GRIB_id :
      11
      GRIB_name :
      TMP
      var_desc :
      Air temperature
      dataset :
      NMC Reanalysis
      level_desc :
      Surface
      statistic :
      Individual Obs
      parent_stat :
      Other
      actual_range :
      [185.16 322.1 ]
    " - ], - "text/plain": [ - "\n", - "array([[[296.29 , 296.79 , 297.1 ],\n", - " [295.9 , 296.19998, 296.79 ],\n", - " [296.6 , 296.19998, 296.4 ],\n", - " [297. , 296.69998, 296.1 ],\n", - " [295.4 , 295.69998, 295.79 ],\n", - " [293.79 , 294.1 , 294.6 ],\n", - " [293.1 , 293.29 , 293.29 ],\n", - " [290.19998, 290.79 , 291.4 ],\n", - " [287.9 , 288. , 288.29 ],\n", - " [286.5 , 286.5 , 285.69998],\n", - " [284.6 , 284.9 , 284.19998],\n", - " [282.79 , 283.19998, 282.6 ],\n", - " [280. , 280.69998, 280.19998],\n", - " [278.4 , 279. , 279. ],\n", - " [277.29 , 277.4 , 277.79 ],\n", - " [276.69998, 277.4 , 277.69998],\n", - " [275.9 , 276.9 , 276.9 ],\n", - " [274.79 , 275.19998, 275.6 ],\n", - " [273.69998, 273.6 , 273.79 ],\n", - " [272.1 , 270.9 , 270. ],\n", - " [274.5 , 274.29 , 274.1 ],\n", - " [266.5 , 267.1 , 267.1 ],\n", - " [250. , 249.79999, 248.89 ],\n", - " [243.79999, 244.5 , 244.7 ],\n", - " [241.2 , 242.5 , 243.5 ]],\n", - "\n", - " [[296.29 , 297.19998, 297.4 ],\n", - " [296.19998, 296.69998, 296.79 ],\n", - " [296.4 , 295.9 , 296.19998],\n", - " [295.79 , 295.79 , 296.1 ],\n", - " [295.1 , 295.79 , 295.79 ],\n", - " [294.29 , 294.79 , 294.69998],\n", - " [293.19998, 293.9 , 294.19998],\n", - " [290.19998, 291.1 , 292.4 ],\n", - " [287.5 , 288.5 , 289.4 ],\n", - " [285.69998, 287.4 , 287.1 ],\n", - " [283.29 , 285.19998, 285.19998],\n", - " [281.4 , 282.79 , 283.5 ],\n", - " [279.19998, 280.19998, 280.79 ],\n", - " [277.79 , 278.5 , 279.29 ],\n", - " [276.29 , 276.4 , 277.29 ],\n", - " [275.79 , 276. , 276.5 ],\n", - " [275.6 , 276.1 , 276.29 ],\n", - " [274. , 274.4 , 275.1 ],\n", - " [272.1 , 272.69998, 273.19998],\n", - " [269.19998, 268.5 , 267.6 ],\n", - " [272.5 , 271.5 , 270.4 ],\n", - " [269.69998, 269.4 , 268.6 ],\n", - " [253.2 , 252.89 , 252.09999],\n", - " [243.59999, 244.09999, 244.2 ],\n", - " [242.09999, 242.7 , 243.09999]],\n", - "\n", - " [[296.4 , 296.29 , 296.4 ],\n", - " [296.19998, 296.5 , 296.29 ],\n", - " [295.6 , 295.4 , 295.4 ],\n", - " [295. , 295. , 294.9 ],\n", - " [293.9 , 294.79 , 295. ],\n", - " [293.29 , 293.9 , 294.4 ],\n", - " [292.4 , 292.9 , 293.4 ],\n", - " [289.5 , 289.79 , 291.19998],\n", - " [287. , 287.1 , 288.29 ],\n", - " [284.9 , 285.6 , 286.4 ],\n", - " [282. , 283.29 , 284.69998],\n", - " [280. , 280.79 , 282.4 ],\n", - " [278.6 , 279.1 , 280. ],\n", - " [277.6 , 277.9 , 278.6 ],\n", - " [276. , 275.79 , 276.6 ],\n", - " [275.29 , 275.5 , 276. ],\n", - " [274.5 , 275.6 , 276.1 ],\n", - " [274.29 , 275. , 275.4 ],\n", - " [275.5 , 275.9 , 275.29 ],\n", - " [273. , 273.5 , 272.9 ],\n", - " [271.9 , 271.79 , 271.6 ],\n", - " [269.29 , 268.5 , 267. ],\n", - " [256.19998, 255.5 , 254.2 ],\n", - " [244.59999, 244.39 , 244. ],\n", - " [242.29999, 242.2 , 242.29999]],\n", - "\n", - " [[297.5 , 297.69998, 297.5 ],\n", - " [297. , 297.5 , 297.1 ],\n", - " [296.6 , 296.4 , 296. ],\n", - " [295.9 , 295.79 , 295.5 ],\n", - " [294.4 , 295. , 295.4 ],\n", - " [293. , 293.5 , 294.29 ],\n", - " [291.9 , 291.9 , 292.19998],\n", - " [289.19998, 289.4 , 289.9 ],\n", - " [286.6 , 287.1 , 287.9 ],\n", - " [284.79 , 284.79 , 285.4 ],\n", - " [282.79 , 282. , 282.69998],\n", - " [281.19998, 280.19998, 280.6 ],\n", - " [279.5 , 278.69998, 278.6 ],\n", - " [278. , 277.69998, 277.6 ],\n", - " [276.4 , 275.9 , 276.4 ],\n", - " [275.6 , 275.69998, 276.1 ],\n", - " [274.5 , 275.6 , 276.29 ],\n", - " [273.4 , 274.5 , 275.5 ],\n", - " [274.1 , 274. , 273.5 ],\n", - " [273.29 , 272.6 , 271.5 ],\n", - " [272.79 , 272.4 , 271.9 ],\n", - " [267.69998, 266.29 , 264.4 ],\n", - " [256.6 , 254.7 , 252.09999],\n", - " [246.29999, 245.29999, 244.2 ],\n", - " [241.89 , 241.79999, 241.79999]]], dtype=float32)\n", - "Coordinates:\n", - " * lat (lat) float32 15.0 17.5 20.0 22.5 25.0 ... 65.0 67.5 70.0 72.5 75.0\n", - " * lon (lon) float32 200.0 202.5 205.0\n", - " * time (time) datetime64[ns] 2013-01-01 ... 2013-01-01T18:00:00\n", - "Attributes:\n", - " long_name: 4xDaily Air temperature at sigma level 995\n", - " units: degK\n", - " precision: 2\n", - " GRIB_id: 11\n", - " GRIB_name: TMP\n", - " var_desc: Air temperature\n", - " dataset: NMC Reanalysis\n", - " level_desc: Surface\n", - " statistic: Individual Obs\n", - " parent_stat: Other\n", - " actual_range: [185.16 322.1 ]" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import xarray as xr\n", "import numpy as np\n", @@ -637,457 +64,14 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:57:16.214911Z", "start_time": "2019-12-30T15:57:16.165994Z" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - "Show/Hide data repr\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "Show/Hide attributes\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
    xarray.DataArray
    'air'
    • time: 4
    • lat: 100
    • lon: 3
    • 296.3 296.8 297.1 296.2 296.6 297.0 ... 242.6 242.4 241.9 241.8 241.8
      array([[[296.29000854, 296.79000854, 297.1000061 ],\n",
      -       "        [296.19545954, 296.64697173, 297.02485518],\n",
      -       "        [296.10091053, 296.50393491, 296.94970426],\n",
      -       "        ...,\n",
      -       "        [242.46059851, 243.46969695, 244.08181672],\n",
      -       "        [241.83029767, 242.98484846, 243.79090837],\n",
      -       "        [241.19999683, 242.49999997, 243.50000003]],\n",
      -       "\n",
      -       "       [[296.29000854, 297.19998169, 297.3999939 ],\n",
      -       "        [296.26818385, 297.07876957, 297.25211866],\n",
      -       "        [296.24635916, 296.95755744, 297.10424342],\n",
      -       "        ...,\n",
      -       "        [242.82726354, 243.37878187, 243.63332714],\n",
      -       "        [242.46362716, 243.03938941, 243.36665899],\n",
      -       "        [242.09999079, 242.69999695, 243.09999084]],\n",
      -       "\n",
      -       "       [[296.3999939 , 296.29000854, 296.3999939 ],\n",
      -       "        [296.35150609, 296.34091556, 296.37333078],\n",
      -       "        [296.30301828, 296.39182258, 296.34666767],\n",
      -       "        ...,\n",
      -       "        [243.4151408 , 243.26181628, 243.12423612],\n",
      -       "        [242.85756431, 242.73090659, 242.71211194],\n",
      -       "        [242.29998782, 242.19999689, 242.29998776]],\n",
      -       "\n",
      -       "       [[297.5       , 297.69998169, 297.5       ],\n",
      -       "        [297.37878788, 297.65150128, 297.40303179],\n",
      -       "        [297.25757575, 297.60302087, 297.30606357],\n",
      -       "        ...,\n",
      -       "        [244.02817552, 243.49695752, 242.96362858],\n",
      -       "        [242.9590874 , 242.64847269, 242.38180817],\n",
      -       "        [241.88999927, 241.79998785, 241.79998776]]])
      • lon
        (lon)
        float32
        200.0 202.5 205.0
        standard_name :
        longitude
        long_name :
        Longitude
        units :
        degrees_east
        axis :
        X
        array([200. , 202.5, 205. ], dtype=float32)
      • time
        (time)
        datetime64[ns]
        2013-01-01 ... 2013-01-01T18:00:00
        standard_name :
        time
        long_name :
        Time
        array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
        -       "       '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000'],\n",
        -       "      dtype='datetime64[ns]')
      • lat
        (lat)
        float64
        15.0 15.61 16.21 ... 74.39 75.0
        array([15.      , 15.606061, 16.212121, 16.818182, 17.424242, 18.030303,\n",
        -       "       18.636364, 19.242424, 19.848485, 20.454545, 21.060606, 21.666667,\n",
        -       "       22.272727, 22.878788, 23.484848, 24.090909, 24.69697 , 25.30303 ,\n",
        -       "       25.909091, 26.515152, 27.121212, 27.727273, 28.333333, 28.939394,\n",
        -       "       29.545455, 30.151515, 30.757576, 31.363636, 31.969697, 32.575758,\n",
        -       "       33.181818, 33.787879, 34.393939, 35.      , 35.606061, 36.212121,\n",
        -       "       36.818182, 37.424242, 38.030303, 38.636364, 39.242424, 39.848485,\n",
        -       "       40.454545, 41.060606, 41.666667, 42.272727, 42.878788, 43.484848,\n",
        -       "       44.090909, 44.69697 , 45.30303 , 45.909091, 46.515152, 47.121212,\n",
        -       "       47.727273, 48.333333, 48.939394, 49.545455, 50.151515, 50.757576,\n",
        -       "       51.363636, 51.969697, 52.575758, 53.181818, 53.787879, 54.393939,\n",
        -       "       55.      , 55.606061, 56.212121, 56.818182, 57.424242, 58.030303,\n",
        -       "       58.636364, 59.242424, 59.848485, 60.454545, 61.060606, 61.666667,\n",
        -       "       62.272727, 62.878788, 63.484848, 64.090909, 64.69697 , 65.30303 ,\n",
        -       "       65.909091, 66.515152, 67.121212, 67.727273, 68.333333, 68.939394,\n",
        -       "       69.545455, 70.151515, 70.757576, 71.363636, 71.969697, 72.575758,\n",
        -       "       73.181818, 73.787879, 74.393939, 75.      ])
    • long_name :
      4xDaily Air temperature at sigma level 995
      units :
      degK
      precision :
      2
      GRIB_id :
      11
      GRIB_name :
      TMP
      var_desc :
      Air temperature
      dataset :
      NMC Reanalysis
      level_desc :
      Surface
      statistic :
      Individual Obs
      parent_stat :
      Other
      actual_range :
      [185.16 322.1 ]
    " - ], - "text/plain": [ - "\n", - "array([[[296.29000854, 296.79000854, 297.1000061 ],\n", - " [296.19545954, 296.64697173, 297.02485518],\n", - " [296.10091053, 296.50393491, 296.94970426],\n", - " ...,\n", - " [242.46059851, 243.46969695, 244.08181672],\n", - " [241.83029767, 242.98484846, 243.79090837],\n", - " [241.19999683, 242.49999997, 243.50000003]],\n", - "\n", - " [[296.29000854, 297.19998169, 297.3999939 ],\n", - " [296.26818385, 297.07876957, 297.25211866],\n", - " [296.24635916, 296.95755744, 297.10424342],\n", - " ...,\n", - " [242.82726354, 243.37878187, 243.63332714],\n", - " [242.46362716, 243.03938941, 243.36665899],\n", - " [242.09999079, 242.69999695, 243.09999084]],\n", - "\n", - " [[296.3999939 , 296.29000854, 296.3999939 ],\n", - " [296.35150609, 296.34091556, 296.37333078],\n", - " [296.30301828, 296.39182258, 296.34666767],\n", - " ...,\n", - " [243.4151408 , 243.26181628, 243.12423612],\n", - " [242.85756431, 242.73090659, 242.71211194],\n", - " [242.29998782, 242.19999689, 242.29998776]],\n", - "\n", - " [[297.5 , 297.69998169, 297.5 ],\n", - " [297.37878788, 297.65150128, 297.40303179],\n", - " [297.25757575, 297.60302087, 297.30606357],\n", - " ...,\n", - " [244.02817552, 243.49695752, 242.96362858],\n", - " [242.9590874 , 242.64847269, 242.38180817],\n", - " [241.88999927, 241.79998785, 241.79998776]]])\n", - "Coordinates:\n", - " * lon (lon) float32 200.0 202.5 205.0\n", - " * time (time) datetime64[ns] 2013-01-01 ... 2013-01-01T18:00:00\n", - " * lat (lat) float64 15.0 15.61 16.21 16.82 ... 73.18 73.79 74.39 75.0\n", - "Attributes:\n", - " long_name: 4xDaily Air temperature at sigma level 995\n", - " units: degK\n", - " precision: 2\n", - " GRIB_id: 11\n", - " GRIB_name: TMP\n", - " var_desc: Air temperature\n", - " dataset: NMC Reanalysis\n", - " level_desc: Surface\n", - " statistic: Individual Obs\n", - " parent_stat: Other\n", - " actual_range: [185.16 322.1 ]" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "newlat = np.linspace(15, 75, 100)\n", "air.interp(lat=newlat)" @@ -1102,7 +86,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:55:17.947482Z", @@ -1143,29 +127,14 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:55:23.185371Z", "start_time": "2019-12-30T15:55:23.145380Z" } }, - "outputs": [ - { - "ename": "ValueError", - "evalue": "size of dimension 'lat' on inputs was unexpectedly changed by applied function from 25 to 100. Only dimensions specified in ``exclude_dims`` with xarray.apply_ufunc are allowed to change size.", - "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 3\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlon\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# now arguments in the order expected by 'interp1_np'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mnewlat\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 6\u001b[0m )\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 633\u001b[0m \u001b[0;34m\"dimensions specified in ``exclude_dims`` with \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 634\u001b[0m \"xarray.apply_ufunc are allowed to change size.\".format(\n\u001b[0;32m--> 635\u001b[0;31m \u001b[0mdim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim_sizes\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdim\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew_size\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 636\u001b[0m )\n\u001b[1;32m 637\u001b[0m )\n", - "\u001b[0;31mValueError\u001b[0m: size of dimension 'lat' on inputs was unexpectedly changed by applied function from 25 to 100. Only dimensions specified in ``exclude_dims`` with xarray.apply_ufunc are allowed to change size." - ] - } - ], + "outputs": [], "source": [ "xr.apply_ufunc(\n", " interp1d_np, # first the function\n", @@ -1206,27 +175,14 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:55:24.910186Z", "start_time": "2019-12-30T15:55:24.860198Z" } }, - "outputs": [ - { - "ename": "ValueError", - "evalue": "each dimension in `exclude_dims` must also be a core dimension in the function signature", - "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 4\u001b[0m \u001b[0mair\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mnewlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m )\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 982\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mexclude_dims\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mexclude_dims\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mall_core_dims\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 983\u001b[0m raise ValueError(\n\u001b[0;32m--> 984\u001b[0;31m \u001b[0;34m\"each dimension in `exclude_dims` must also be a \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 985\u001b[0m \u001b[0;34m\"core dimension in the function signature\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 986\u001b[0m )\n", - "\u001b[0;31mValueError\u001b[0m: each dimension in `exclude_dims` must also be a core dimension in the function signature" - ] - } - ], + "outputs": [], "source": [ "xr.apply_ufunc(\n", " interp1d_np, # first the function\n", @@ -1279,29 +235,14 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:55:26.828645Z", "start_time": "2019-12-30T15:55:26.786129Z" } }, - "outputs": [ - { - "ename": "ValueError", - "evalue": "applied function returned data with unexpected number of dimensions: 1 vs 0, for dimensions ()", - "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 5\u001b[0m \u001b[0mnewlat\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0minput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\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[0;32m----> 7\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m )\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 621\u001b[0m \u001b[0;34m\"applied function returned data with unexpected \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \"number of dimensions: {} vs {}, for dimensions {}\".format(\n\u001b[0;32m--> 623\u001b[0;31m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdims\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdims\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 624\u001b[0m )\n\u001b[1;32m 625\u001b[0m )\n", - "\u001b[0;31mValueError\u001b[0m: applied function returned data with unexpected number of dimensions: 1 vs 0, for dimensions ()" - ] - } - ], + "outputs": [], "source": [ "xr.apply_ufunc(\n", " interp1d_np, # first the function\n", @@ -1322,415 +263,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:55:28.540895Z", "start_time": "2019-12-30T15:55:28.491272Z" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - "Show/Hide data repr\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "Show/Hide attributes\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
    xarray.DataArray
    • lat: 100
    • 296.3 296.2 296.1 296.0 295.9 296.0 ... 243.7 243.1 242.5 241.8 241.2
      array([296.29000854, 296.19545954, 296.10091053, 296.00636153,\n",
      -       "       295.91181252, 296.04848133, 296.21818126, 296.38788119,\n",
      -       "       296.55758112, 296.67273227, 296.76970048, 296.8666687 ,\n",
      -       "       296.96363692, 296.75757483, 296.36969457, 295.9818143 ,\n",
      -       "       295.59393403, 295.20484416, 294.81454468, 294.4242452 ,\n",
      -       "       294.03394572, 293.72728105, 293.56000773, 293.39273441,\n",
      -       "       293.22546109, 292.92424705, 292.22121083, 291.5181746 ,\n",
      -       "       290.81513838, 290.13028509, 289.57271229, 289.01513949,\n",
      -       "       288.45756669, 287.8999939 , 287.56060144, 287.22120898,\n",
      -       "       286.88181652, 286.54242406, 286.09697099, 285.63636641,\n",
      -       "       285.17576183, 284.71515725, 284.27091564, 283.83212835,\n",
      -       "       283.39334106, 282.95455378, 282.36727998, 281.69091427,\n",
      -       "       281.01454856, 280.33818285, 279.80605987, 279.4181796 ,\n",
      -       "       279.03029933, 278.64241906, 278.29908614, 278.02999878,\n",
      -       "       277.76091142, 277.49182406, 277.25424934, 277.11121253,\n",
      -       "       276.96817571, 276.8251389 , 276.67573964, 276.4818032 ,\n",
      -       "       276.28786677, 276.09393033, 275.8999939 , 275.63090654,\n",
      -       "       275.36181918, 275.09273182, 274.82364446, 274.55879073,\n",
      -       "       274.29454179, 274.03029286, 273.76604392, 273.40907704,\n",
      -       "       273.02120417, 272.6333313 , 272.24545843, 272.46364154,\n",
      -       "       273.04545824, 273.62727495, 274.20909165, 273.53030303,\n",
      -       "       271.59090909, 269.65151515, 267.71212121, 265.        ,\n",
      -       "       261.        , 257.        , 253.        , 249.62424168,\n",
      -       "       248.12120842, 246.61817516, 245.1151419 , 243.72120019,\n",
      -       "       243.09089938, 242.46059857, 241.83029776, 241.19999695])
      • lon
        ()
        float32
        200.0
        standard_name :
        longitude
        long_name :
        Longitude
        units :
        degrees_east
        axis :
        X
        array(200., dtype=float32)
      • time
        ()
        datetime64[ns]
        2013-01-01
        standard_name :
        time
        long_name :
        Time
        array('2013-01-01T00:00:00.000000000', dtype='datetime64[ns]')
    " - ], - "text/plain": [ - "\n", - "array([296.29000854, 296.19545954, 296.10091053, 296.00636153,\n", - " 295.91181252, 296.04848133, 296.21818126, 296.38788119,\n", - " 296.55758112, 296.67273227, 296.76970048, 296.8666687 ,\n", - " 296.96363692, 296.75757483, 296.36969457, 295.9818143 ,\n", - " 295.59393403, 295.20484416, 294.81454468, 294.4242452 ,\n", - " 294.03394572, 293.72728105, 293.56000773, 293.39273441,\n", - " 293.22546109, 292.92424705, 292.22121083, 291.5181746 ,\n", - " 290.81513838, 290.13028509, 289.57271229, 289.01513949,\n", - " 288.45756669, 287.8999939 , 287.56060144, 287.22120898,\n", - " 286.88181652, 286.54242406, 286.09697099, 285.63636641,\n", - " 285.17576183, 284.71515725, 284.27091564, 283.83212835,\n", - " 283.39334106, 282.95455378, 282.36727998, 281.69091427,\n", - " 281.01454856, 280.33818285, 279.80605987, 279.4181796 ,\n", - " 279.03029933, 278.64241906, 278.29908614, 278.02999878,\n", - " 277.76091142, 277.49182406, 277.25424934, 277.11121253,\n", - " 276.96817571, 276.8251389 , 276.67573964, 276.4818032 ,\n", - " 276.28786677, 276.09393033, 275.8999939 , 275.63090654,\n", - " 275.36181918, 275.09273182, 274.82364446, 274.55879073,\n", - " 274.29454179, 274.03029286, 273.76604392, 273.40907704,\n", - " 273.02120417, 272.6333313 , 272.24545843, 272.46364154,\n", - " 273.04545824, 273.62727495, 274.20909165, 273.53030303,\n", - " 271.59090909, 269.65151515, 267.71212121, 265. ,\n", - " 261. , 257. , 253. , 249.62424168,\n", - " 248.12120842, 246.61817516, 245.1151419 , 243.72120019,\n", - " 243.09089938, 242.46059857, 241.83029776, 241.19999695])\n", - "Coordinates:\n", - " lon float32 200.0\n", - " time datetime64[ns] 2013-01-01\n", - "Dimensions without coordinates: lat" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "xr.apply_ufunc(\n", " interp1d_np, # first the function\n", @@ -1753,7 +293,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:55:30.635880Z", @@ -1799,39 +339,14 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:55:49.784745Z", "start_time": "2019-12-30T15:55:49.713572Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "data: (4, 3, 25) | x: (25,) | xi: (100,)\n" - ] - }, - { - "ename": "ValueError", - "evalue": "object too deep 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 13\u001b[0m \u001b[0minput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# list with one entry per arg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0moutput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\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[0;32m---> 15\u001b[0;31m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m )\n\u001b[1;32m 17\u001b[0m \u001b[0minterped\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewlat\u001b[0m \u001b[0;31m# need to add this manually\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\"apply_ufunc: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 600\u001b[0m )\n\u001b[0;32m--> 601\u001b[0;31m \u001b[0mresult_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput_data\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 602\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 603\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m\u001b[0m in \u001b[0;36minterp1d_np\u001b[0;34m(data, x, xi)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0minterp1d_np\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxi\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[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minterp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\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 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36minterp\u001b[0;34m(*args, **kwargs)\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/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 1410\u001b[0m \u001b[0mfp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconcatenate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\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[1;32m 1411\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1412\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[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1413\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1414\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mValueError\u001b[0m: object too deep for desired array" - ] - } - ], + "outputs": [], "source": [ "def interp1d_np(data, x, xi):\n", " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", @@ -1857,8 +372,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "That's a hard-to-interpret error but our `print` statement output `data: (10, 53, 25) | x: (25,) | xi: (100,)`. `air` has been passed as a 3D numpy array which is not what `np.interp` can handle. Instead we want loop over all combinations of `lon` and `time`; and apply our function to each corresponding vector of data along `lat`.\n", - "Turns out this is easy by specifying `vectorize=True` (though not great on performance).\n", + "That's a hard-to-interpret error but our `print` call helpfully printed the shapes of the input data: \n", + "\n", + " data: (10, 53, 25) | x: (25,) | xi: (100,)\n", + "\n", + "We see that `air` has been passed as a 3D numpy array which is not what `np.interp` expects. Instead we want loop over all combinations of `lon` and `time`; and apply our function to each corresponding vector of data along `lat`.\n", + "`apply_ufunc` makes this easy by specifying `vectorize=True`:\n", "\n", " vectorize : bool, optional\n", " If True, then assume ``func`` only takes arrays defined over core\n", @@ -1875,34 +394,14 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:55:58.486339Z", "start_time": "2019-12-30T15:55:58.420859Z" } }, - "outputs": [ - { - "ename": "ValueError", - "evalue": "shape mismatch: objects cannot be broadcast to a single shape", - "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 12\u001b[0m \u001b[0moutput_core_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# returned data has one dimension\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# dimensions allowed to change size. Must be set!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m \u001b[0mvectorize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;31m# loop over non-core dims\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 15\u001b[0m )\n\u001b[1;32m 16\u001b[0m \u001b[0minterped\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"lat\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewlat\u001b[0m \u001b[0;31m# need to add this manually\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_ufunc\u001b[0;34m(func, input_core_dims, output_core_dims, exclude_dims, vectorize, join, dataset_join, dataset_fill_value, keep_attrs, kwargs, dask, output_dtypes, output_sizes, *args)\u001b[0m\n\u001b[1;32m 1040\u001b[0m \u001b[0mjoin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0mexclude_dims\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexclude_dims\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mkeep_attrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeep_attrs\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 1043\u001b[0m )\n\u001b[1;32m 1044\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVariable\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_dataarray_vfunc\u001b[0;34m(func, signature, join, exclude_dims, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0mdata_vars\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"variable\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 232\u001b[0;31m \u001b[0mresult_var\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata_vars\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 233\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/xarray/core/computation.py\u001b[0m in \u001b[0;36mapply_variable_ufunc\u001b[0;34m(func, signature, exclude_dims, dask, output_dtypes, output_sizes, keep_attrs, *args)\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\"apply_ufunc: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 600\u001b[0m )\n\u001b[0;32m--> 601\u001b[0;31m \u001b[0mresult_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput_data\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 602\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 603\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_outputs\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 2089\u001b[0m \u001b[0mvargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0m_n\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_n\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mnames\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[1;32m 2090\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2091\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_vectorize_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvargs\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 2092\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2093\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_get_ufunc_and_otypes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m_vectorize_call\u001b[0;34m(self, func, args)\u001b[0m\n\u001b[1;32m 2155\u001b[0m \u001b[0;34m\"\"\"Vectorized call to `func` over positional `args`.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2156\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msignature\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2157\u001b[0;31m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_vectorize_call_with_signature\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\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 2158\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2159\u001b[0m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\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[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m_vectorize_call_with_signature\u001b[0;34m(self, func, args)\u001b[0m\n\u001b[1;32m 2185\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2186\u001b[0m broadcast_shape, dim_sizes = _parse_input_dimensions(\n\u001b[0;32m-> 2187\u001b[0;31m args, input_core_dims)\n\u001b[0m\u001b[1;32m 2188\u001b[0m input_shapes = _calculate_shapes(broadcast_shape, dim_sizes,\n\u001b[1;32m 2189\u001b[0m input_core_dims)\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36m_parse_input_dimensions\u001b[0;34m(args, input_core_dims)\u001b[0m\n\u001b[1;32m 1858\u001b[0m \u001b[0mdummy_array\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstride_tricks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mas_strided\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mndim\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[1;32m 1859\u001b[0m \u001b[0mbroadcast_args\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdummy_array\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1860\u001b[0;31m \u001b[0mbroadcast_shape\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstride_tricks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_broadcast_shape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mbroadcast_args\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 1861\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mbroadcast_shape\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdim_sizes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1862\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/dcpy/lib/python3.7/site-packages/numpy/lib/stride_tricks.py\u001b[0m in \u001b[0;36m_broadcast_shape\u001b[0;34m(*args)\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;31m# use the old-iterator because np.nditer does not handle size 0 arrays\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 190\u001b[0m \u001b[0;31m# consistently\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 191\u001b[0;31m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbroadcast\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m32\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 192\u001b[0m \u001b[0;31m# unfortunately, it cannot handle 32 or more arguments directly\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 193\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mpos\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m32\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m31\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[0;31mValueError\u001b[0m: shape mismatch: objects cannot be broadcast to a single shape" - ] - } - ], + "outputs": [], "source": [ "def interp1d_np(data, x, xi):\n", " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", @@ -1934,455 +433,14 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:56:02.358157Z", "start_time": "2019-12-30T15:56:02.301059Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n" - ] - }, - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - "Show/Hide data repr\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "Show/Hide attributes\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
    xarray.DataArray
    • time: 4
    • lon: 3
    • lat: 100
    • 296.3 296.2 296.1 296.0 295.9 296.0 ... 244.1 243.5 243.0 242.4 241.8
      array([[[296.29000854, 296.19545954, 296.10091053, ..., 242.46059857,\n",
      -       "         241.83029776, 241.19999695],\n",
      -       "        [296.79000854, 296.64697173, 296.50393492, ..., 243.46969697,\n",
      -       "         242.98484848, 242.5       ],\n",
      -       "        [297.1000061 , 297.02485518, 296.94970426, ..., 244.0818167 ,\n",
      -       "         243.79090835, 243.5       ]],\n",
      -       "\n",
      -       "       [[296.29000854, 296.26818385, 296.24635916, ..., 242.82726357,\n",
      -       "         242.46362721, 242.09999084],\n",
      -       "        [297.19998169, 297.07876957, 296.95755745, ..., 243.37878187,\n",
      -       "         243.03938941, 242.69999695],\n",
      -       "        [297.3999939 , 297.25211866, 297.10424342, ..., 243.63332714,\n",
      -       "         243.36665899, 243.09999084]],\n",
      -       "\n",
      -       "       [[296.3999939 , 296.35150609, 296.30301828, ..., 243.41514079,\n",
      -       "         242.85756429, 242.29998779],\n",
      -       "        [296.29000854, 296.34091556, 296.39182258, ..., 243.26181631,\n",
      -       "         242.73090663, 242.19999695],\n",
      -       "        [296.3999939 , 296.37333078, 296.34666767, ..., 243.12423614,\n",
      -       "         242.71211196, 242.29998779]],\n",
      -       "\n",
      -       "       [[297.5       , 297.37878788, 297.25757576, ..., 244.02817559,\n",
      -       "         242.95908749, 241.88999939],\n",
      -       "        [297.69998169, 297.65150128, 297.60302087, ..., 243.49695749,\n",
      -       "         242.64847264, 241.79998779],\n",
      -       "        [297.5       , 297.40303178, 297.30606357, ..., 242.9636286 ,\n",
      -       "         242.38180819, 241.79998779]]])
      • lon
        (lon)
        float32
        200.0 202.5 205.0
        standard_name :
        longitude
        long_name :
        Longitude
        units :
        degrees_east
        axis :
        X
        array([200. , 202.5, 205. ], dtype=float32)
      • time
        (time)
        datetime64[ns]
        2013-01-01 ... 2013-01-01T18:00:00
        standard_name :
        time
        long_name :
        Time
        array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',\n",
        -       "       '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000'],\n",
        -       "      dtype='datetime64[ns]')
      • lat
        (lat)
        float64
        15.0 15.61 16.21 ... 74.39 75.0
        array([15.      , 15.606061, 16.212121, 16.818182, 17.424242, 18.030303,\n",
        -       "       18.636364, 19.242424, 19.848485, 20.454545, 21.060606, 21.666667,\n",
        -       "       22.272727, 22.878788, 23.484848, 24.090909, 24.69697 , 25.30303 ,\n",
        -       "       25.909091, 26.515152, 27.121212, 27.727273, 28.333333, 28.939394,\n",
        -       "       29.545455, 30.151515, 30.757576, 31.363636, 31.969697, 32.575758,\n",
        -       "       33.181818, 33.787879, 34.393939, 35.      , 35.606061, 36.212121,\n",
        -       "       36.818182, 37.424242, 38.030303, 38.636364, 39.242424, 39.848485,\n",
        -       "       40.454545, 41.060606, 41.666667, 42.272727, 42.878788, 43.484848,\n",
        -       "       44.090909, 44.69697 , 45.30303 , 45.909091, 46.515152, 47.121212,\n",
        -       "       47.727273, 48.333333, 48.939394, 49.545455, 50.151515, 50.757576,\n",
        -       "       51.363636, 51.969697, 52.575758, 53.181818, 53.787879, 54.393939,\n",
        -       "       55.      , 55.606061, 56.212121, 56.818182, 57.424242, 58.030303,\n",
        -       "       58.636364, 59.242424, 59.848485, 60.454545, 61.060606, 61.666667,\n",
        -       "       62.272727, 62.878788, 63.484848, 64.090909, 64.69697 , 65.30303 ,\n",
        -       "       65.909091, 66.515152, 67.121212, 67.727273, 68.333333, 68.939394,\n",
        -       "       69.545455, 70.151515, 70.757576, 71.363636, 71.969697, 72.575758,\n",
        -       "       73.181818, 73.787879, 74.393939, 75.      ])
    " - ], - "text/plain": [ - "\n", - "array([[[296.29000854, 296.19545954, 296.10091053, ..., 242.46059857,\n", - " 241.83029776, 241.19999695],\n", - " [296.79000854, 296.64697173, 296.50393492, ..., 243.46969697,\n", - " 242.98484848, 242.5 ],\n", - " [297.1000061 , 297.02485518, 296.94970426, ..., 244.0818167 ,\n", - " 243.79090835, 243.5 ]],\n", - "\n", - " [[296.29000854, 296.26818385, 296.24635916, ..., 242.82726357,\n", - " 242.46362721, 242.09999084],\n", - " [297.19998169, 297.07876957, 296.95755745, ..., 243.37878187,\n", - " 243.03938941, 242.69999695],\n", - " [297.3999939 , 297.25211866, 297.10424342, ..., 243.63332714,\n", - " 243.36665899, 243.09999084]],\n", - "\n", - " [[296.3999939 , 296.35150609, 296.30301828, ..., 243.41514079,\n", - " 242.85756429, 242.29998779],\n", - " [296.29000854, 296.34091556, 296.39182258, ..., 243.26181631,\n", - " 242.73090663, 242.19999695],\n", - " [296.3999939 , 296.37333078, 296.34666767, ..., 243.12423614,\n", - " 242.71211196, 242.29998779]],\n", - "\n", - " [[297.5 , 297.37878788, 297.25757576, ..., 244.02817559,\n", - " 242.95908749, 241.88999939],\n", - " [297.69998169, 297.65150128, 297.60302087, ..., 243.49695749,\n", - " 242.64847264, 241.79998779],\n", - " [297.5 , 297.40303178, 297.30606357, ..., 242.9636286 ,\n", - " 242.38180819, 241.79998779]]])\n", - "Coordinates:\n", - " * lon (lon) float32 200.0 202.5 205.0\n", - " * time (time) datetime64[ns] 2013-01-01 ... 2013-01-01T18:00:00\n", - " * lat (lat) float64 15.0 15.61 16.21 16.82 ... 73.18 73.79 74.39 75.0" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "def interp1d_np(data, x, xi):\n", " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", @@ -2445,33 +503,14 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:56:07.327214Z", "start_time": "2019-12-30T15:56:07.265287Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)data: (25,) | x: (25,) | xi: (100,)data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "\n", - "data: (25,) | x: (25,) | xi: (100,)\n", - "data: (25,) | x: (25,) | xi: (100,)\n" - ] - } - ], + "outputs": [], "source": [ "def interp1d_np(data, x, xi):\n", " print(f\"data: {data.shape} | x: {x.shape} | xi: {xi.shape}\")\n", @@ -2532,64 +571,14 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:56:26.013431Z", "start_time": "2019-12-30T15:56:24.675876Z" } }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - ":4: NumbaWarning: \n", - "Compilation is falling back to object mode WITHOUT looplifting enabled because Function \"interp1d_np_gufunc\" failed type inference due to: Invalid use of Function() with argument(s) of type(s): (tuple(int64 x 1))\n", - " * parameterized\n", - "In definition 0:\n", - " All templates rejected with literals.\n", - "In definition 1:\n", - " All templates rejected without literals.\n", - "In definition 2:\n", - " All templates rejected with literals.\n", - "In definition 3:\n", - " All templates rejected without literals.\n", - "This error is usually caused by passing an argument of a type that is unsupported by the named function.\n", - "[1] During: resolving callee type: Function()\n", - "[2] During: typing of call at (9)\n", - "\n", - "\n", - "File \"\", line 9:\n", - "def interp1d_np_gufunc(data, x, xi, out):\n", - " \n", - " print(\n", - " \"data: \" + str(data.shape) + \" | x:\" + str(x.shape) + \" | xi: \" + str(xi.shape)\n", - " ^\n", - "\n", - " @guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", - "/home/deepak/miniconda3/envs/dcpy/lib/python3.7/site-packages/numba/object_mode_passes.py:178: NumbaWarning: Function \"interp1d_np_gufunc\" was compiled in object mode without forceobj=True.\n", - "\n", - "File \"\", line 5:\n", - "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", - "def interp1d_np_gufunc(data, x, xi, out):\n", - "^\n", - "\n", - " state.func_ir.loc))\n", - "/home/deepak/miniconda3/envs/dcpy/lib/python3.7/site-packages/numba/object_mode_passes.py:187: NumbaDeprecationWarning: \n", - "Fall-back from the nopython compilation path to the object mode compilation path has been detected, this is deprecated behaviour.\n", - "\n", - "For more information visit http://numba.pydata.org/numba-doc/latest/reference/deprecation.html#deprecation-of-object-mode-fall-back-behaviour-when-using-jit\n", - "\n", - "File \"\", line 5:\n", - "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", - "def interp1d_np_gufunc(data, x, xi, out):\n", - "^\n", - "\n", - " warnings.warn(errors.NumbaDeprecationWarning(msg, state.func_ir.loc))\n" - ] - } - ], + "outputs": [], "source": [ "from numba import float64, guvectorize\n", "\n", @@ -2616,33 +605,14 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T15:56:28.007342Z", "start_time": "2019-12-30T15:56:27.955422Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "data: (25,) | x:(25,) | xi: (100,)\n", - "data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)\n", - "data: (25,) | x:(25,) | xi: (100,)\n", - "data: (25,) | x:(25,) | xi: (100,)\n", - "\n", - "data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)data: (25,) | x:(25,) | xi: (100,)\n", - "\n", - "\n", - "data: (25,) | x:(25,) | xi: (100,)\n", - "data: (25,) | x:(25,) | xi: (100,)\n", - "data: (25,) | x:(25,) | xi: (100,)\n", - "data: (25,) | x:(25,) | xi: (100,)\n" - ] - } - ], + "outputs": [], "source": [ "interped = xr.apply_ufunc(\n", " interp1d_np_gufunc, # first the function\n", @@ -2671,7 +641,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-12-30T16:11:59.152918Z", @@ -2737,7 +707,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.7.3" }, "nbsphinx": { "allow_errors": true From 09e59d241e686ac935366dff43e7fa9c334be48c Mon Sep 17 00:00:00 2001 From: dcherian Date: Wed, 15 Jan 2020 07:50:32 -0700 Subject: [PATCH 4/4] Minor updates. --- doc/examples/apply_ufunc_vectorize_1d.ipynb | 78 +++++++++++---------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/doc/examples/apply_ufunc_vectorize_1d.ipynb b/doc/examples/apply_ufunc_vectorize_1d.ipynb index 0d98b6a6d33..6d18d48fdb5 100644 --- a/doc/examples/apply_ufunc_vectorize_1d.ipynb +++ b/doc/examples/apply_ufunc_vectorize_1d.ipynb @@ -36,8 +36,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:54:59.861486Z", - "start_time": "2019-12-30T15:54:58.773827Z" + "end_time": "2020-01-15T14:45:51.659160Z", + "start_time": "2020-01-15T14:45:50.528742Z" } }, "outputs": [], @@ -67,8 +67,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:57:16.214911Z", - "start_time": "2019-12-30T15:57:16.165994Z" + "end_time": "2020-01-15T14:45:55.431708Z", + "start_time": "2020-01-15T14:45:55.104701Z" } }, "outputs": [], @@ -89,8 +89,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:55:17.947482Z", - "start_time": "2019-12-30T15:55:17.914823Z" + "end_time": "2020-01-15T14:45:57.889496Z", + "start_time": "2020-01-15T14:45:57.792269Z" } }, "outputs": [], @@ -130,8 +130,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:55:23.185371Z", - "start_time": "2019-12-30T15:55:23.145380Z" + "end_time": "2020-01-15T14:45:59.768626Z", + "start_time": "2020-01-15T14:45:59.543808Z" } }, "outputs": [], @@ -178,8 +178,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:55:24.910186Z", - "start_time": "2019-12-30T15:55:24.860198Z" + "end_time": "2020-01-15T14:46:02.187012Z", + "start_time": "2020-01-15T14:46:02.105563Z" } }, "outputs": [], @@ -238,8 +238,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:55:26.828645Z", - "start_time": "2019-12-30T15:55:26.786129Z" + "end_time": "2020-01-15T14:46:05.031672Z", + "start_time": "2020-01-15T14:46:04.947588Z" } }, "outputs": [], @@ -266,8 +266,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:55:28.540895Z", - "start_time": "2019-12-30T15:55:28.491272Z" + "end_time": "2020-01-15T14:46:09.325218Z", + "start_time": "2020-01-15T14:46:09.303020Z" } }, "outputs": [], @@ -296,8 +296,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:55:30.635880Z", - "start_time": "2019-12-30T15:55:30.597561Z" + "end_time": "2020-01-15T14:46:11.295440Z", + "start_time": "2020-01-15T14:46:11.226553Z" } }, "outputs": [], @@ -342,8 +342,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:55:49.784745Z", - "start_time": "2019-12-30T15:55:49.713572Z" + "end_time": "2020-01-15T14:46:13.808646Z", + "start_time": "2020-01-15T14:46:13.680098Z" } }, "outputs": [], @@ -397,8 +397,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:55:58.486339Z", - "start_time": "2019-12-30T15:55:58.420859Z" + "end_time": "2020-01-15T14:46:26.633233Z", + "start_time": "2020-01-15T14:46:26.515209Z" } }, "outputs": [], @@ -436,8 +436,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:56:02.358157Z", - "start_time": "2019-12-30T15:56:02.301059Z" + "end_time": "2020-01-15T14:46:30.026663Z", + "start_time": "2020-01-15T14:46:29.893267Z" } }, "outputs": [], @@ -494,7 +494,7 @@ "source": [ "So far our function can only handle numpy arrays. A real benefit of `apply_ufunc` is the ability to easily parallelize over dask chunks _when needed_. \n", "\n", - "We want to apply this function in a vectorized fashion over each chunk of the dask array. This is possible using dask's `blockwise` or `map_blocks`. `apply_ufunc` wraps `blockwise` and asking it to map the function over chunks using `blockwise` is as simple as saying `dask=\"parallelized\"`. With this level of flexibility we need to provide dask with some extra information: \n", + "We want to apply this function in a vectorized fashion over each chunk of the dask array. This is possible using dask's `blockwise` or `map_blocks`. `apply_ufunc` wraps `blockwise` and asking it to map the function over chunks using `blockwise` is as simple as specifying `dask=\"parallelized\"`. With this level of flexibility we need to provide dask with some extra information: \n", " 1. `output_dtypes`: dtypes of all returned objects, and \n", " 2. `output_sizes`: lengths of any new dimensions. \n", " \n", @@ -506,8 +506,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:56:07.327214Z", - "start_time": "2019-12-30T15:56:07.265287Z" + "end_time": "2020-01-15T14:48:42.469341Z", + "start_time": "2020-01-15T14:48:42.344209Z" } }, "outputs": [], @@ -529,7 +529,7 @@ " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be a set!\n", " vectorize=True, # loop over non-core dims\n", " dask=\"parallelized\",\n", - " output_dtypes=[float], # one per output\n", + " output_dtypes=[air.dtype], # one per output\n", ").rename({\"new_lat\": \"lat\"})\n", "interped[\"lat\"] = newlat # need to add this manually\n", "xr.testing.assert_allclose(expected.transpose(*interped.dims), interped)" @@ -574,8 +574,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:56:26.013431Z", - "start_time": "2019-12-30T15:56:24.675876Z" + "end_time": "2020-01-15T14:48:45.267633Z", + "start_time": "2020-01-15T14:48:44.943939Z" } }, "outputs": [], @@ -608,8 +608,8 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T15:56:28.007342Z", - "start_time": "2019-12-30T15:56:27.955422Z" + "end_time": "2020-01-15T14:48:54.755405Z", + "start_time": "2020-01-15T14:48:54.634724Z" } }, "outputs": [], @@ -626,7 +626,7 @@ " exclude_dims=set((\"lat\",)), # dimensions allowed to change size. Must be a set!\n", " # vectorize=True, # not needed since numba takes care of vectorizing\n", " dask=\"parallelized\",\n", - " output_dtypes=[float], # one per output\n", + " output_dtypes=[air.dtype], # one per output\n", ").rename({\"new_lat\": \"lat\"})\n", "interped[\"lat\"] = newlat # need to add this manually\n", "xr.testing.assert_allclose(expected.transpose(*interped.dims), interped)" @@ -644,16 +644,20 @@ "execution_count": null, "metadata": { "ExecuteTime": { - "end_time": "2019-12-30T16:11:59.152918Z", - "start_time": "2019-12-30T16:11:58.820458Z" + "end_time": "2020-01-15T14:49:28.667528Z", + "start_time": "2020-01-15T14:49:28.103914Z" } }, "outputs": [], "source": [ - "from numba import float64, guvectorize, njit\n", + "from numba import float64, guvectorize\n", "\n", "\n", - "@guvectorize(\"(float64[:], float64[:], float64[:], float64[:])\", \"(n), (n), (m) -> (m)\")\n", + "@guvectorize(\n", + " \"(float64[:], float64[:], float64[:], float64[:])\",\n", + " \"(n), (n), (m) -> (m)\",\n", + " nopython=True,\n", + ")\n", "def interp1d_np_gufunc(data, x, xi, out):\n", " out[:] = np.interp(xi, x, data)\n", "\n", @@ -670,7 +674,7 @@ " exclude_dims=set((dim,)), # dimensions allowed to change size. Must be a set!\n", " # vectorize=True, # not needed since numba takes care of vectorizing\n", " dask=\"parallelized\",\n", - " output_dtypes=[float], # one per output\n", + " output_dtypes=[data.dtype], # one per output; could also be float or np.dtype(\"float64\")\n", " ).rename({\"__newdim__\": dim})\n", " interped[dim] = newdim # need to add this manually\n", "\n", @@ -707,7 +711,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.7.6" }, "nbsphinx": { "allow_errors": true