Skip to content

Commit

Permalink
Handle renaming of xarray after regridding
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Feb 2, 2018
1 parent 46c4d16 commit 73d4931
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 24 deletions.
7 changes: 4 additions & 3 deletions geoviews/operation/regrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ def _get_regridder(self, element):
tx, ty = self.p.target.kdims[:2]
if issubclass(self.p.target.interface, XArrayInterface):
ds_out = self.p.target.data
ds_out.rename({tx.name: 'lon', ty.name: 'lat'},
inplace=True)
ds_out = ds_out.rename({tx.name: 'lon', ty.name: 'lat'})
height, width = ds_out[tx.name].shape
else:
xs = self.p.target.dimension_values(0, expanded=False)
Expand Down Expand Up @@ -97,8 +96,10 @@ def _get_regridder(self, element):

def _process(self, element, key=None):
regridder, arrays = self._get_regridder(element)
x, y = element.kdims
ds = xr.Dataset({vd: regridder(arr) for vd, arr in arrays.items()})
params = dict(get_param_values(element), kdims=['lon', 'lat'])
ds.rename({'lon': x.name, 'lat': y.name}, inplace=True)
params = get_param_values(element)
if is_geographic(element):
try:
return Image(ds, crs=element.crs, **params)
Expand Down
64 changes: 43 additions & 21 deletions notebooks/user_guide/Resampling_Grids.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"source": [
"In geographical applications grids and meshes of different kinds are very common and for visualization and analysis it is often very important to be able to resample them in different ways. Regridding can refer both to upsampling and downsampling a grid or mesh, which is achieved through interpolation and aggregation.\n",
"\n",
"Naive approaches to regridding treat the space as flat, which is often simpler but can also give incorrect results when working with a spherical space such as the earth. In this user guide we will summarize how to work with different grid types including rectilinear, curvilinear grids and trimeshes. Additionally we will discuss different approaches to regridding working based on the assumption of a flat earth (using [datashader](http://datashader.org/)) and a spherical earth ([xESMF](http://xesmf.readthedocs.io/en/latest/Curvilinear_grid.html))."
"Naive approaches to regridding treat the space as flat, which is often simpler but can also give less accurate results when working with a spherical space such as the earth. In this user guide we will summarize how to work with different grid types including rectilinear, curvilinear grids and trimeshes. Additionally we will discuss different approaches to regridding working based on the assumption of a flat earth (using [datashader](http://datashader.org/)) and a spherical earth ([xESMF](http://xesmf.readthedocs.io/en/latest/Curvilinear_grid.html))."
]
},
{
Expand All @@ -49,8 +49,6 @@
"outputs": [],
"source": [
"ds = xr.tutorial.load_dataset('air_temperature').isel(time=slice(0, 100))\n",
"# Ensure data is in range (-180, 180)\n",
"ds['lon'] = np.where(ds.lon>180, ds.lon-360, ds.lon)\n",
"ds"
]
},
Expand Down Expand Up @@ -93,11 +91,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"It is important to note that if we look at the longitude coordinates above we can see that they are defined in the range (0, 360), while GeoViews generally expects it to be in the range (-180, 180). To correct this we have one of two options:\n",
"\n",
"1. We use the ``project_image`` operation to correct this.\n",
"\n",
"2. We explicitly adjust the coordinates."
"It is important to note that if we look at the longitude coordinates above we can see that they are defined in the range (0, 360), while GeoViews generally expects it to be in the range (-180, 180). To correct this we can apply a simple fix:"
]
},
{
Expand All @@ -106,11 +100,7 @@
"metadata": {},
"outputs": [],
"source": [
"# Option 1\n",
"images = gv.operation.project_image(images, projection=ccrs.PlateCarree())\n",
"\n",
"# Option 2\n",
"# ds['lon'] = np.where(ds.lon>180, ds.lon-360, ds.lon)"
"ds['lon'] = np.where(ds.lon>180, ds.lon-360, ds.lon)"
]
},
{
Expand Down Expand Up @@ -167,9 +157,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The xESMF library is specifically designed to provide an easy way to correctly resample grids defined in geographic coordinate systems and differs significantly from the simpler approach used by datashader, which applies simple upsampling and downsampling. xESMF is a wrapper around the [ESMF regridding algorithms](https://www.earthsystemcog.org/projects/esmf/regridding), which compute an interpolation weight matrix which is applied to remap the values of the source grid onto the destination grid. \n",
"The xESMF library is specifically designed to provide an easy way to accurately resample grids defined in geographic coordinate systems and differs significantly from the simpler approach used by datashader, which applies simple upsampling and downsampling. xESMF is a wrapper around the [ESMF regridding algorithms](https://www.earthsystemcog.org/projects/esmf/regridding), which compute an interpolation weight matrix which is applied to remap the values of the source grid onto the destination grid. \n",
"\n",
"In GeoViews these algorithms are made available via the simple ``weighted_regrid`` operation, which supports the different interpolation modes including: 'bilinear', 'nearest_s2d', 'nearest_d2s' and 'conservative'. Since generating the sparse weight matrix takes much longer than applying it the operation will cache the weight matrix on disk for later use, this optimization can be disabled via the ``reuse_weights`` parameter or customized by defining a custom ``file_pattern``."
"In GeoViews these algorithms are made available via the ``weighted_regrid`` operation, which supports the different interpolation modes including: 'bilinear', 'nearest_s2d', 'nearest_d2s' and 'conservative'. Since generating the sparse weight matrix takes much longer than applying it the operation will cache the weight matrix on disk for later use; this optimization can be disabled via the ``reuse_weights`` parameter or customized by defining a custom ``file_pattern``."
]
},
{
Expand All @@ -182,6 +172,22 @@
"weighted_regrid(images) * gv.feature.coastline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since this operation creates local weight files we will want to clean up after ourselves once we are done, to do so we can call the ``weighted_regrid.clean_weight_files`` method."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"weighted_regrid.clean_weight_files()"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -193,7 +199,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The operation also allows us to define a target grid, which we can either define manually or by using a utility provided by the xESMF library. Here we will define a $2^{\\circ}x1^{\\circ}$ grid."
"The operation also allows us to define a target grid, which we can either define manually or by using a utility provided by the xESMF library. Here we will define a $2^{\\circ}\\times2^{\\circ}$ grid."
]
},
{
Expand Down Expand Up @@ -221,7 +227,7 @@
"outputs": [],
"source": [
"target = gv.Dataset(grid, kdims=['lon', 'lat'])\n",
"weighted_regrid(images, target=target, streams=[])"
"weighted_regrid(images, target=target, streams=[]) * gv.feature.coastline"
]
},
{
Expand Down Expand Up @@ -254,7 +260,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Just like the rectilinear grids GeoViews understands this kind of data natively. So we again wrap this dataset in a ``gv.Dataset`` and define a fixed range for the ``Tair`` values:"
"Just like the rectilinear grids GeoViews understands this kind of data natively. So we again wrap this dataset in a ``gv.Dataset`` and define a fixed range for the air teperature (``Tair``) values:"
]
},
{
Expand Down Expand Up @@ -307,7 +313,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"If we want to explore a very large grid it therefore often makes sense to resample the data onto a rectilinear grid, which can be rendered much more efficiently. Once again we have the option of using the datashader based approach or the more correct xESMF based approach."
"If we want to explore a very large grid it therefore often makes sense to resample the data onto a rectilinear grid, which can be rendered much more efficiently. Once again we have the option of using the datashader based approach or the more accurate xESMF based approach."
]
},
{
Expand Down Expand Up @@ -360,6 +366,22 @@
"weighted_regrid(quadmeshes, streams=[]) * gv.feature.coastline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally lets clean up after ourselves one last time:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"weighted_regrid.clean_weight_files()"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -371,7 +393,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Another commonly used mesh/grid type are trimeshes, here we will load a 3dm file and demonstrate how to visualize it using HoloViews:"
"Another commonly used mesh/grid type are trimeshes defined as a set of edges and vertices. Here we will load a 3dm file and demonstrate how to visualize it using HoloViews:"
]
},
{
Expand Down Expand Up @@ -418,7 +440,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"This is a reasonably large mesh with >1 million triangles and cannot easily be displayed directly with matplotlib or especially bokeh. Therefore we will once again regrid this dataset onto a rectilinear grid. Additionally, to speed up plotting of meshes, we can do two things, first of all since all data displayed with bokeh is first projected to Web Mercator coordinates we can project the mesh immediately, secondly we can use the ``precompute`` during rasterization, which will cache an optimized mesh datastructure:"
"This is a reasonably large mesh with >1 million triangles and cannot easily be displayed directly with matplotlib or especially bokeh. Therefore we will once again regrid this dataset onto a rectilinear grid. Additionally, to speed up plotting of meshes, we can do two things: first of all since all data displayed with bokeh is first projected to Web Mercator coordinates we can project the mesh immediately; secondly, we can use the ``precompute`` during rasterization, which will cache an optimized mesh datastructure:"
]
},
{
Expand Down

0 comments on commit 73d4931

Please sign in to comment.