How to plot a raster file with its scale bar in Python

plotpythonraster

Suppose I have a file file.tif. I want to plot a scale bar based on its CRS, using Python.

I've tried using a mix of rasterio, matplotlib and other techniques, but I fail because of the scale bar part, where I can't find a method that makes use of its CRS:

import numpy as np
import matplotlib.pyplot as plt
import rasterio as rio

raster = rio.open('./file.tif')
data = raster.read()

plt.imshow(data)
plt.colorbar(label='clusters', fraction=0.02)
# generating the scale bar should go here and take advantage of the `raster.crs` attribute
plt.plot()

raster plot without a scale bar

Best Answer

The easiest way is to use matplotlib-scalebar

pip install matplotlib-scalebar

The key to getting the scale right is to use rasterio.plot.plotting_extent to set the extent that you then pass to pyplot.imshow.

Then you can do something like:

import matplotlib.pyplot as plt
from matplotlib_scalebar.scalebar import ScaleBar

import rasterio
from rasterio.plot import plotting_extent

fig, ax = plt.subplots(1, figsize=(6, 6))

with rasterio.open("https://github.com/rasterio/rasterio/raw/main/tests/data/float.tif") as raster:
    extent = plotting_extent(raster)
    data = raster.read(1)
    plt.imshow(data, extent=extent)
    scalebar = ScaleBar(1, location="lower left")
    plt.colorbar(label='clusters', fraction=0.02, ax=ax)
    ax.add_artist(scalebar)

plt.show()

enter image description here

Another example of output of above code that uses "https://github.com/rasterio/rasterio/raw/main/tests/data/RGB.byte.tif":

enter image description here

For simpler use cases where you don't need a legend, i.e if you are plotting RGB imagery, you don't need to set the extent, just use rasterio.plot.show which will set it correctly for you:

import matplotlib.pyplot as plt
from matplotlib_scalebar.scalebar import ScaleBar

import rasterio
from rasterio.plot import show

fig, ax = plt.subplots(1, figsize=(6, 6))

with rasterio.open("https://github.com/rasterio/rasterio/raw/main/tests/data/RGB.byte.tif") as raster:
    show(raster, ax=ax)
    scalebar = ScaleBar(1, location="lower left")
    ax.add_artist(scalebar)

plt.show()

enter image description here

Related Question