{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "
Xarray
\n", "\n", "\n", "> *DS Python for GIS and Geoscience* \n", "> *October, 2020*\n", ">\n", "> *© 2020, Joris Van den Bossche and Stijn Van Hoey. Licensed under [CC BY 4.0 Creative Commons](http://creativecommons.org/licenses/by/4.0/)*\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "import rasterio\n", "from rasterio.plot import plotting_extent, reshape_as_image" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Introduction" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "By this moment you probably already know how to read data files with rasterio:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true }, "outputs": [], "source": [ "data_file = \"./data/gent/raster/2020-09-17_Sentinel_2_L1C_True_color.tiff\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true }, "outputs": [], "source": [ "with rasterio.open(data_file) as src:\n", " # extract data, metadata and extent into memory\n", " gent_profile = src.profile\n", " gent_data = src.read([1, 2, 3], out_dtype=float, masked=False)\n", " gent_ext = plotting_extent(src)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "plt.imshow(gent_data[0, :, :], extent=gent_ext, cmap=\"Reds\")" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Rasterio...\n", "\n", "__Benefits__\n", " - Direct link with Numpy data types\n", " - Rasterio supports important GIS transformations (clip, mask, warp, merge, transformation,...)\n", " - Only load a subset of a large data set into memory\n", "\n", "__Drawbacks__:\n", " - Coordinate information is decoupled from the data itself (keep track and organize the extent and meta data) \n", " - Make sure to keep track of what each dimension represents (y-first, as arrays are organized along rows first)\n", " - Functionality overlap with GDAL (and sometimes installation issues)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Meet `xarray`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true }, "outputs": [], "source": [ "import xarray as xr" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "gent = xr.open_rasterio(data_file)\n", "gent" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "plt.imshow(gent.sel(band=1), cmap=\"Reds\");" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Xarray brings its own plotting methods, but relies on Matplotlib as well for the actual plotting:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "ax = gent.sel(band=1).plot.imshow(cmap=\"Reds\", figsize=(12, 5)) # robust=True\n", "# ax.axes.set_aspect('equal')" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "As a preview, plot the intersection of the data at x coordinate closest to 400000 for each band:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "gent.sel(x=400_000, method='nearest').plot.line(col='band')" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "But first, let's have a look at the data again:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "gent" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The output of xarray is a bit different to what we've previous seen. Let's go through the different elements:\n", "\n", "- It is a `xarray.DataArray`, one of the main data types provided by xarray\n", "- It has 3 __dimensions__:\n", " - `band`: 3 bands (RGB)\n", " - `y`: the y coordinates of the data set\n", " - `x`: the x coordinates of the data set\n", "- Each of these dimensions are defined by a __coordinate__ (1D) array\n", "- Other metadata provided by the `tiff` are stored in the __`Attributes`__\n", "\n", "Looking to the data itself (click on the icons on the right), we can see this is still a Numpy array" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true }, "outputs": [], "source": [ "#gent.values" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "gent = gent.assign_coords(band=(\"band\", [\"R\", \"G\", \"B\"]))\n", "gent" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Hence, we can __name dimensions__ and also extract (slice) data using these names..." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": true, "editable": true, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "gent.sel(band='R')" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Using xarray:\n", "\n", "- Data stored as a Numpy arrays\n", "- Dimensions do have a name\n", "- The coordinates of each of the dimensions can represent coordinates, categories, dates,... instead of just an index\n", " " ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "