8

How can I add a colorbar after using rio.plot.show? I've tried a bunch of things but have gotten various errors

Here's one way I tried:

fig, ax = plt.subplots(figsize = (16, 16))

retted = rio.plot.show(ds, ax=ax, cmap='Greys_r')  

fig.colorbar(retted, ax=ax)
plt.title("Original")
plt.show()

This has error: AttributeError: 'AxesSubplot' object has no attribute 'get_array'

rasen58
  • 4,672
  • 8
  • 39
  • 74
  • 3
    I guess a workaround would be to plot with `i = ax.imshow(ds, cmap='Greys_r')` then cover this with the rio plot and finally add the colorbar `plt.colorbar(i)` – david Apr 21 '20 at 07:15

4 Answers4

9

I did what david suggested above and it worked!

fig, ax = plt.subplots(figsize=(5, 5))

# use imshow so that we have something to map the colorbar to
image_hidden = ax.imshow(image_data, 
                         cmap='Greys', 
                         vmin=-30, 
                         vmax=30)

# plot on the same axis with rio.plot.show
image = rio.plot.show(image_data, 
                      transform=src.transform, 
                      ax=ax, 
                      cmap='Greys', 
                      vmin=-30, 
                      vmax=30)

# add colorbar using the now hidden image
fig.colorbar(image_hidden, ax=ax)
steven
  • 91
  • 1
  • 3
  • 2
    Nice formatting. And you gave credit to David. Very good job for your first answer. I don't have time at the moment to test your solution, so I can't comment on correctness. – Marjeta Jul 22 '20 at 22:30
  • 1
    @Marjeta I had the same problem of the OP. I tested this answer and it works. According to this page https://sigon.gitlab.io/post/2018-11-08-plot-raster-nodata-values/ it seems to me the colorbar was added by default... – Alessandro Jacopson Dec 28 '20 at 15:15
  • 1
    I had stumbled upon this solution while trying different things. Stumbled on to this answer while exploring if there is a more elegant solution. This seems to be the only way to do it for now. – DotPi Sep 03 '21 at 16:27
  • 1
    Note that if the raster is rotated, then the current code will plot the rotated image on top of the non rotated (and not hidden anymore) image. I tumbled into this problem and solved it by adding `image_hidden.set_visible(False)` – WaterFox Jan 25 '22 at 14:46
4

Different objects are returned by plt.imshow() and rasterio.plot.show(). plt.colorbar() is expecting a mappable object so it gets confused. Because rasterio plotting is a wrapper over matplotlib, I think the most straightforward approach is to provide the underlying object maptlotlib is expecting.

retted = rio.plot.show(ds, ax=ax, cmap='Greys_r')
im = retted.get_images()[0]
fig.colorbar(im, ax=ax)
jasmit
  • 76
  • 3
1

I agree with this solution, but I'd add that if you're like me, I usually have a rasterio datasetreader object (the result of reading in georeffed raster data with rasterio.open), not just a raw numpy array. So with rasterio v1.1.8 I have to do the extra step of extracting the numpy array from the datasetreader object. So for example, with a single band:

dem = rasterio.open("GIS/anaPlotDEM.tif")
fig, ax = plt.subplots(figsize=(10,10))
image_hidden = ax.imshow(dem.read()[0])
fig.colorbar(image_hidden, ax=ax)
rasterio.plot.show(dem, ax=ax)

(I'd add this as a comment but don't have the reputation points)

Daniel81
  • 81
  • 4
0

If the data use different coordinate system. When you add the hidden image, you changed the x-axis and y-axis. Add the following code will solve:

# set the plot boundary to data.bounds
ax.set_xlim(data.bounds.left, data.bounds.right)
ax.set_ylim(data.bounds.bottom, data.bounds.top)