Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide contour linestroke on pyplot.contourf to get only fills

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:

enter image description here

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.

like image 549
heltonbiker Avatar asked Nov 25 '11 00:11

heltonbiker


People also ask

How do I change the contour color in Matplotlib?

Color maps on contour plots The default color scheme of Matplotlib contour and filled contour plots can be modified. A general way to modify the color scheme is to call Matplotlib's plt. get_cmap() function that outputs a color map object. There are many different colormaps available to apply to contour plots.

What is the difference between contour and Contourf?

contour() and contourf() draw contour lines and filled contours, respectively. Except as noted, function signatures and return values are the same for both versions. contourf() differs from the MATLAB version in that it does not draw the polygon edges. To draw edges, add line contours with calls to contour() .

What does the Matplotlib function Contourf () exactly do?

Matplotlib API contains contour() and contourf() functions that draw contour lines and filled contours, respectively. Both functions need three parameters x,y and z.


2 Answers

I finally found a proper solution to this long-standing problem (currently in Matplotlib 3), which does not require multiple calls to contour or rasterizing 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 for c in cnt.collections:     c.set_edgecolor("face")  plt.savefig("test.pdf")     

Here below is an example of contours before the fix

enter image description here

And here below is the same figure after the above fix

enter image description here

like image 150
divenex Avatar answered Sep 21 '22 22:09

divenex


The solution to the problem, despite not being a real solution, but more a workaround, is simple: Just repeat the same contourf command and this will magically get rid of spurious contours.

As stated by the OP, spurious contours show up when doing contour fill (contourf) with intervals too close to each other. We can reproduce this behavior by setting a very large number of intervals, e.g.:

plt.contourf(plon,plat,ssh,np.arange(-1,1.001,0.001)) # 2001 intervals 

This gives us as output:

enter image description here

The thin spurious contours obviously affect the net color of the contour fill.

If you do the command twice:

plt.contourf(plon,plat,ssh,np.arange(-1,1.001,0.001)) # Not once, plt.contourf(plon,plat,ssh,np.arange(-1,1.001,0.001)) # but twice! 

gives me:

enter image description here

Much better now. Here's the finest one, with 3 successive contourf commands:

enter image description here

I can't see any thin contours anymore! Unfortunately, this may slow down your scripts significantly, depending on array size and number of contour intervals. The spurious contours stand out more if more contour intervals are used. What usually works best for me is to use 50 to 100 contour intervals, and do the contourf twice.

Notice that the version of matplotlib I am using is not the latest one. This issue might have been resolved in version 1.1.0. If it has, please let me know.

Python 2.7.1 |EPD 7.0-2 (32-bit)| (r271:86832, Nov 29 2010, 13:52:51) In [1]: matplotlib.__version__ Out[1]: '1.0.1' 
like image 33
milancurcic Avatar answered Sep 18 '22 22:09

milancurcic