python - usar - Oculte la línea de contorno en pyplot.contourf para obtener solo rellenos
matplotlib python 3 (4)
Finalmente encontré una solución adecuada para este problema de larga data (actualmente en Matplotlib 2.0), que no requiere múltiples llamadas para contornear o rasterizar la figura.
Tenga en cuenta que el problema ilustrado en la pregunta aparece solo en formatos de figuras con calidad de publicación guardada como PDF, no en archivos raster de menor calidad como PNG.
Mi solución se inspiró en this respuesta, relacionada con un problema similar con la barra de colores. Una solución similar resulta resolver el diagrama de contorno también, como sigue:
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")
A continuación se muestra un ejemplo de contornos antes de la corrección.
Y aquí abajo está la misma figura después de la corrección anterior.
Tengo un proyecto favorito para crear imágenes de mapas, donde dibujo las carreteras y otras cosas sobre un diagrama de contorno de la elevación del terreno. Está pensado para planificar rutas en bicicleta de montaña (en el pasado he hecho algunos dibujos vectoriales a mano, y funcionan muy bien para la visualización).
Actualmente, descargo el Modelo de elevación digital, en GeoTIFF, desde aquí: http://www.ecologia.ufrgs.br/labgeo/arquivos/downloads/dados/SRTM/geotiff/rs.rar
y luego cree la trama con GDAL y 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()
Lo que da:
El problema es que las curvas de nivel son "blancas" y generan cierta contaminación visual, lo cual no es deseable ya que quiero trazar carreteras y ríos más tarde.
Por lo tanto, estoy tratando de modificar la forma en que contourf
crea estas líneas más claras, ya sea a través de la configuración de parámetros o a través de hack (cambio de código fuente), similar al propuesto aquí:
Cómo dar formato a las curvas de nivel de Matplotlib
Además, si alguien sabe cómo generar dicho mapa de una manera más elegante, utilizando otras bibliotecas, apreciaría mucho la sugerencia.
Gracias por leer.
Heltonbiker, ¿encontraste una solución a tu problema? Me topé accidentalmente con esta pregunta, y tuve el mismo problema por un tiempo. Intenté sugerencias de Zhenya, sin embargo, tampoco me funcionan. La solución al problema, a pesar de no ser una solución real, sino más bien una solución alternativa, es simple: simplemente repita el mismo comando de contourf
y esto mágicamente eliminará los contornos espurios.
Como lo indica el OP, los contornos espurios se muestran cuando se realiza el relleno de contorno ( contourf
) con intervalos demasiado cercanos entre sí. Podemos reproducir este comportamiento estableciendo una gran cantidad de intervalos, por ejemplo:
plt.contourf(plon,plat,ssh,np.arange(-1,1.001,0.001)) # 2001 intervals
Esto nos da como salida:
Los contornos espurios finos obviamente afectan el color neto del relleno del contorno.
Si haces el comando dos veces:
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!
me da
Mucho mejor ahora. Aquí está el mejor, con 3 comandos de contourf
sucesivos:
¡Ya no puedo ver ningún contorno delgado! Desafortunadamente, esto puede ralentizar significativamente sus scripts, dependiendo del tamaño de la matriz y la cantidad de intervalos de contorno. Los contornos espurios se destacan más si se utilizan más intervalos de contorno. Lo que por lo general me funciona mejor es usar intervalos de contorno de 50 a 100, y hacer el contourf
dos veces.
Tenga en cuenta que la versión de matplotlib que estoy usando no es la última. Este problema podría haberse resuelto en la versión 1.1.0
. Si es así, por favor hágamelo saber.
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''
Intente agregar el documento kw a la llamada de plt.contourf(...)
: lw=0
o ls=None
. http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.contourf
La solución publicada no me funcionó con el conjunto alfa en <1, pero encontré la respuesta en esta solución: Matplotlib Contourf traza contornos no deseados cuando Alfa <1
Agregar el argumento antialiased=True
resolvió el problema por mí.