python - tutorial - ¿Por qué mi barra de color tiene líneas?
tutorial django (7)
Editar : Dado que esta parece ser una publicación popular, esta es la solución que parece funcionar bien para mí. Gracias @gazzar y @mfra.
cbar.solids.set_rasterized(True)
cbar.solids.set_edgecolor("face")
¿Alguien sabe por qué mi barra de color tiene lo que parecen ser líneas en ella? O más bien ¿por qué la transición de color no es suave? Estoy usando el mapa base, obviamente, pero eso no debería importar ya que todas las llamadas de matplotlib están bajo el capirote AFAICT. Creo el mapa haciendo algo así como
grays = plt.cm.get_cmap("Grays")
sc = mymap.scatter(xpoints, ypoints, s=sizes, c=color_values, cmap=grays, alpha=.75,
marker="o", zorder=10, vmin=0, vmax=1)
cbar = mymap.colorbar(sc, drawedges=True, location="bottom")
Intenté sin y sin alfa y el resultado fue el mismo. Tal vez es porque mi matriz color_values no es lo suficientemente fina? ¿Puedo establecer los valores subyacentes que están asignados a la barra de colores en algún lugar? No veo cómo, y no veo este problema en otro lado. Es decir, puedo replicar el ejemplo matplotlib show_colorbars sin este problema.
Como ninguna de las otras sugerencias me funcionó, terminé eliminando el canal alfa de la instancia de la barra de color:
from matplotlib.colors import to_rgb
lut = colorbar.solids.get_facecolor()
bg_color = to_rgb(''white'')
lut[:, :3] *= lut[:, 3:]
lut[:, :3] += (1 - lut[:, 3:]) * bg_color
lut[:, 3] = 1.
colorbar.solids.set_facecolor(lut)
La barra de color tuvo que dibujarse una vez antes de poder acceder a los colores de la cara.
En caso de que cree gráficos vectoriales, ha intentado esto (tomado de http://matplotlib.org/api/pyplot_api.html?highlight=colorbar#matplotlib.pyplot.colorbar ):
"Se sabe que algunos visualizadores de gráficos vectoriales (svg y pdf) generan espacios vacíos entre los segmentos de la barra de colores. Esto se debe a errores en los espectadores que no son matplotlib. Como solución alternativa, la barra de colores puede representarse con segmentos superpuestos:
cbar = colorbar()
cbar.solids.set_edgecolor("face")
draw()
Sin embargo, esto tiene consecuencias negativas en otras circunstancias. Particularmente con imágenes semitransparentes (alfa <1) y extensiones de barra de color y no está habilitado por defecto, vea (problema # 1188). "
Intenté ambas configuraciones dadas en los otros comentarios, a saber
cbar.solids.set_rasterized(True)
cbar.solids.set_edgecolor("face")
y desafortunadamente ninguno de los dos funcionó.
Así que probé un enfoque completamente diferente, que es un gran truco, pero al menos hace el trabajo. Cuando pasa alpha
para imshow
, establece un valor alfa que se usará para mezclar con otras imágenes. Debido a razones de mayor potencia (como ha mencionado @mfra), esto crea las líneas blancas que tanto despreciamos. Claramente, la clave es no pasar un valor alfa para imshow
. Sin embargo, todavía tenemos que crear de alguna manera la barra de colores.
Por lo tanto, como solución podemos hacer la mezcla alfa nosotros mismos antes de dar imshow
de imshow
para imshow
. Como ejemplo, usemos el mapa de colores de winter
:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
xx, yy = np.meshgrid(np.linspace(-1, 1, 100), np.linspace(-1, 1, 100))
zz = xx**2 + yy**2
my_cmap_rgb = plt.get_cmap(''winter'')(np.arange(256))
alpha = 0.5
for i in range(3): # Do not include the last column!
my_cmap_rgb[:,i] = (1 - alpha) + alpha*my_cmap_rgb[:,i]
my_cmap = mpl.colors.ListedColormap(my_cmap_rgb, name=''my_cmap'')
Aquí creo un nuevo mapa de my_cmap_rgb
, my_cmap_rgb
, basado en winter
y luego edito los canales no alfa (0, 1 y 2) para hacer la mezcla alfa yo mismo. Simplemente puedo usar este nuevo mapa de colores para trazar mi figura.
f, ax = plt.subplots()
cim = ax.imshow(zz, cmap=my_cmap)
cbar = plt.colorbar(cim)
ax.set_title("No lines and no transparency")
Ahora compáralo con la imagen que obtendrías sin este truco:
f, ax = plt.subplots()
cim = ax.imshow(zz, cmap=''winter'', alpha=0.5)
cbar = plt.colorbar(cim)
ax.set_title("Lines and transparency")
Claramente, el problema se resuelve si no requiere transparencia. Por otro lado, si necesita transparencia, hay una solución más. Primero debe trazar una imagen sin transparencia para obtener la barra de color, y luego trazar una con transparencia, pero cuya barra de color no se utilizará.
f, ax = plt.subplots()
cim = ax.imshow(zz, cmap=my_cmap)
cbar = plt.colorbar(cim)
plt.cla() # Clears axis
ax.plot(50,50, ''ko'')
ax.imshow(zz, cmap=''winter'', alpha=0.5)
ax.set_title("No lines and transparency")
Esto da como resultado una imagen cuya barra de colores no tiene líneas y aún retiene la transparencia. Si bien sigue siendo un truco masivo, ¡al menos ya no tenemos que aguantar más!
Lo siguiente puede ser otra solución, incluso si no es elegante.
In [1]: children = cbar.ax.get_children()
In [2]: children
Out[2]:
[<matplotlib.collections.QuadMesh at 0x21783c41b70>,
<matplotlib.collections.LineCollection at 0x21783bfdc18>,
<matplotlib.patches.Polygon at 0x21783ba0588>,
<matplotlib.patches.Polygon at 0x21783beef98>,
<matplotlib.spines.Spine at 0x21783b77c88>,
<matplotlib.spines.Spine at 0x21783b77470>,
<matplotlib.spines.Spine at 0x21783b70c88>,
<matplotlib.spines.Spine at 0x21783b70860>,
<matplotlib.axis.XAxis at 0x21783b6ac50>,
<matplotlib.axis.YAxis at 0x21783ba60f0>,
<matplotlib.text.Text at 0x21783bc2198>,
<matplotlib.text.Text at 0x21783bc2320>,
<matplotlib.text.Text at 0x21783bc22b0>,
<matplotlib.patches.Rectangle at 0x21783bc2358>]
In [3]: obj = children[1] # Get the LineCollection object
In [4]: obj.set_linewidth(0)
Parece que su trazado usa algunos valores transparentes (alfa). Estaba teniendo el mismo problema (una trama semitransparente, pero quería que la barra de colores fuera sólida), ¡y esta question y answer arreglaron! Para referencia:
cbar.set_alpha(1)
cbar.draw_all()
Por lo general, prefiero rasterizar los contenidos de la barra de color para evitar este problema usando los consejos de Eric Firing here agregando la siguiente línea.
cbar.solids.set_rasterized(True)
Esta solución alternativa supuestamente falla para las imágenes con transparencia, pero para la mayoría de los casos normales produce el resultado deseado.
Tratar:
cbar = mymap.colorbar(sc, drawedges=False, location="bottom")
Ahora está bien documentado en la web (que pude encontrar), pero
*drawedges* [ False | True ] If true, draw lines at color
boundaries.
(extraído de matplotlib/lib/matplotlib/colorbar.py
) Creo que estableciendo drawedges
en True
le está diciendo que dibuje esas líneas.