I have a pet project to create images of maps, where I draw the roads and other stuff over a contour plot of the terrain elevation. It is intended to plan mountain bike routes (I have made some vectorial drawings by hand, in the past, and they work great for visualization).
Currently, I download Digital Elevation Model, in GeoTIFF, from here: http://www.ecologia.ufrgs.br/labgeo/arquivos/downloads/dados/SRTM/geotiff/rs.rar
and then create the plot with GDAL and Matplotlib contourf
function:
from osgeo import gdal
import matplotlib
import matplotlib.pyplot as plt
from pylab import cm
import numpy
f = 'rs.tif'
elev = gdal.Open(f)
a = elev.GetRasterBand(1).ReadAsArray()
w = elev.RasterXSize
h = elev.RasterYSize
print w, h
altura = (0.35, 0.42)
largura = (0.70, 0.82)
a = a[int(h*altura[0]):int(h*altura[1]),
int(w*largura[0]):int(w*largura[1])]
cont = plt.contourf(a, origin='upper', cmap=cm.gist_earth, levels=numpy.arange(0,1000,20))
plt.title('Altitudes - max: %d m; min: %d m' % (numpy.amax(a), numpy.amin(a)))
plt.show()
Which gives:
The problem is that contour lines are "white", and generate some visual pollution, which is undesired since I want to plot roads and rivers later.
So, I am trying to modify the way contourf
create these lighter lines, either via parameter setting, or via hack (changing source code), similar to the one proposed here:
How to format contour lines from Matplotlib
Also, if anyone knows how to generate such a map in a more elegant way, using other libraries, I would appreciate the tip very much!
Thanks for reading.
I finally found a proper solution to this long-standing problem (currently in Matplotlib 3), which does not require multiple calls to contour or rasterize the figure.
Note that the problem illustrated in the question appears only in saved publication-quality figures formats like PDF, not in lower-quality raster files like PNG.
My solution was inspired by this answer, related to a similar problem with the colorbar. A similar solution turns out to solve the contour plot as well, as follows:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(123)
x, y = np.random.uniform(size=(100, 2)).T
z = np.exp(-x**2 - y**2)
levels = np.linspace(0, 1, 100)
cnt = plt.tricontourf(x, y, z, levels=levels, cmap="ocean")
# This is the fix for the white lines between contour levels
cnt.set_edgecolor("face")
plt.savefig("test.pdf")
Here below is an example of contours before the fix
And here below is the same figure after the above fix