Example - Clip

API Reference for rio.clip:

[1]:
import rioxarray

%matplotlib inline

Load in xarray dataset

See docs for rioxarray.open_rasterio

Notes:

  • masked=True will convert from integer to float64 and fill with NaN. If this behavior is not desired, you can skip this.

[2]:
xds = rioxarray.open_rasterio(
    "../../test/test_data/compare/small_dem_3m_merged.tif",
    masked=True,
)
[3]:
xds.plot()
[3]:
<matplotlib.collections.QuadMesh at 0x7fc957fb1ac0>
../_images/examples_clip_geom_4_1.png

Clip using a geometry

By default, it assumes that the CRS of the geometry is the same as the CRS of the dataset. If it is different, make sure to pass in the CRS of the geometry.

[4]:
geometries = [
    {
        'type': 'Polygon',
        'coordinates': [[
            [425499.18381405267, 4615331.540546387],
            [425499.18381405267, 4615478.540546387],
            [425526.18381405267, 4615478.540546387],
            [425526.18381405267, 4615331.540546387],
            [425499.18381405267, 4615331.540546387]
        ]]
    }
]
clipped = xds.rio.clip(geometries)
[5]:
clipped.plot()
[5]:
<matplotlib.collections.QuadMesh at 0x7fc957829d90>
../_images/examples_clip_geom_7_1.png
[6]:
clipped.rio.to_raster("clipped.tif", compress='LZMA', tiled=True, dtype="int32")

Clip using a GeoDataFrame

[7]:
import geopandas
from shapely.geometry import box
[8]:
geodf = geopandas.GeoDataFrame(
    geometry=[
        box(425499.18381405267, 4615331.540546387, 425526.18381405267, 4615478.540546387)
    ],
    crs="EPSG:26915"
)
[9]:
clipped = xds.rio.clip(geodf.geometry.values, geodf.crs, drop=False, invert=True)
# Note: If you have rasterio < 1.2 you will need convert the geometries to dict-like objects if the projection
# of the geometries differ from the raster. For example:
#
# from shapely.geometry import mapping
#  geometries = geodf.geometry.apply(mapping)
[10]:
clipped.plot()
[10]:
<matplotlib.collections.QuadMesh at 0x7fc9572aa100>
../_images/examples_clip_geom_13_1.png
[11]:
clipped.rio.to_raster("clipped_invert.tif", compress='LZMA', tiled=True, dtype="int32")

Clipping larger rasters

Note: Loading from disk will likely only work directly after opening a raster with rioxarray.open_rasterio

The clip operation needs the full raster loaded with the default method. This can be an issue if you don’t have enough memory (RAM) on you machine. If this is something you have run into, it is recommended to use the from_disk=True option. This option uses rasterio.mask.mask when loading the data if possible.

But be careful, these two methods, as they use different core functions, can have different outputs: small discrepencies may appear on the borders (1 pixel added or removed on some borders, see issue #310)

Alternatively, you can also use rio.clip_box followed by rio.clip for a more consistent memory efficient clip operation.

[12]:
geometries = [
    {
        'type': 'Polygon',
        'coordinates': [[
            [425499.18381405267, 4615331.540546387],
            [425499.18381405267, 4615478.540546387],
            [425526.18381405267, 4615478.540546387],
            [425526.18381405267, 4615331.540546387],
            [425499.18381405267, 4615331.540546387]
        ]]
    }
]

clipped = rioxarray.open_rasterio(
    "../../test/test_data/compare/small_dem_3m_merged.tif",
    masked=True,
).rio.clip(geometries, from_disk=True)
[13]:
clipped.plot()
[13]:
<matplotlib.collections.QuadMesh at 0x7fc9571db850>
../_images/examples_clip_geom_17_1.png