2013-02-21 12 views
33

Modifica: Poiché questo sembra essere un post popolare, ecco la soluzione che sembra funzionare bene per me. Grazie a @gazzar e @mfra.perché la mia barra dei colori contiene delle linee?

cbar.solids.set_rasterized(True) 
cbar.solids.set_edgecolor("face") 

Qualcuno sa il motivo per cui il mio colorbar ha quello che sembrano essere le linee in esso? O meglio, perché la transizione dei colori non è fluida? Sto usando la mappa di base, ovviamente, ma non dovrebbe importare dato che sono tutte le chiamate di matplotlib sotto il cofano AFAICT. Creo la mappa facendo qualcosa come

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") 

Ho provato senza e senza alfa e il risultato è stato lo stesso. Forse è perché il mio array color_values ​​non è abbastanza buono? Posso impostare i valori sottostanti che sono mappati sulla barra dei colori da qualche parte? Non vedo come, e non vedo questo problema altrove. Cioè, posso replicare l'esempio di matplotlib show_colorbars senza questo problema.

Bad Colorbar Example

+1

Hai provato a salvare la figura in diversi formati? Se sì, ottieni sempre questi problemi? –

+0

L'ho visto solo a causa dell'alfa, sei proprio sicuro che sia lo stesso con alpha = 1.0? –

+0

Sì, succede con png, ma non ho risolto il problema. Sì, l'ho visto per alpha = 1.0 con SVG. – jseabold

risposta

25

Nel caso in cui si crea la grafica vettoriale, avete provato questo (tratto da http://matplotlib.org/api/pyplot_api.html?highlight=colorbar#matplotlib.pyplot.colorbar):.

"E 'noto che alcuni visualizzatore di grafica vettoriale (SVG e PDF) rende gli spazi bianchi tra i segmenti del colorbar Questo è a causa di errori nei visualizzatori non matplotlib Come soluzione il colorbar può essere reso con segmenti sovrapposti:.

cbar = colorbar() 
cbar.solids.set_edgecolor("face") 
draw() 

Tuttavia questo ha conseguenze negative in altre circostanze particolarmente con immagini semitrasparenti (alfa < 1) ed estensioni colorbar. e non è abilitato per impostazione predefinita vedi (numero 1188). "

+0

Grazie. Questo sembra essere il problema di leggere attraverso # 1188 e il PR (ripristinato) allegato. È interessante notare che gli SVG rendono in modo diverso in Firefox e Chrome, cosa a cui non avevo pensato. – jseabold

+0

Sembra che i migliori risultati per alpha <1 provengano dall'utilizzo di drawedges = False e set_edgecolor ("face"). Ora ho delle linee nere, ma sono meno pronunciate e solo nei colori più scuri. – jseabold

+0

È effettivamente un bug nel/i visualizzatore/i, ma è anche vero che viene usato un modo subottimale per rendere la barra dei colori. L'intera figura dovrebbe essere disegnata come un singolo pezzo utilizzando ombreggiatura uniforme anziché 256 piccoli rettangoli. Entrambi i formati PDF e SVG supportano l'ombreggiatura lineare uniforme con un numero arbitrario di colori. – Mojca

1

Prova:

cbar = mymap.colorbar(sc, drawedges=False, location="bottom") 

E 'ormai ben documentato sul web (che ho potuto trovare), ma

*drawedges* [ False | True ] If true, draw lines at color 
       boundaries. 

(tirato da matplotlib/lib/matplotlib/colorbar.py) Penso impostando drawedges a True stai dicendo di disegnare quelle linee.

+0

disegnano effettivamente i bordi per me, ma li disegna in nero! Non particolarmente utile. La soluzione di mfra funziona senza drawedges per me. (matplotlib v1.3.1) – travc

5

Sembra che la trama utilizzi alcuni valori trasparenti (alfa). Stavo avendo lo stesso problema (trama semi-trasparente, ma volevo che la barra dei colori fosse solida), e questo question e answer lo ha risolto per me! Per riferimento:

cbar.set_alpha(1) 
cbar.draw_all() 
8

io in genere preferisco rasterizzare il contenuto colorbar per evitare questo problema usando il consiglio di Eric Firing here aggiungendo la seguente riga.

cbar.solids.set_rasterized(True) 

Questa soluzione presumibilmente non riesce per le immagini con la trasparenza, ma per la maggior parte dei casi normali si produce il risultato desiderato.

+1

Tornando indietro intorno a questo due anni dopo. Questo in effetti aiuta un bel po '. – jseabold

+1

Eccellente. Sembra migliore, e anche l'output svg più piccolo! – Bram

4

ho provato entrambe le impostazioni date alle altre osservazioni, vale a dire

cbar.solids.set_rasterized(True) 
cbar.solids.set_edgecolor("face") 

e, purtroppo, non ha lavorato per me.

Così ho provato un approccio completamente diverso che è un enorme hack, ma almeno ottiene il lavoro svolto. Quando si passa alpha a imshow si imposta un valore alfa che verrà utilizzato per fondere con altre immagini. A causa di una maggiore potenza (come ha detto @mfra), ciò crea le linee bianche che disprezziamo. Chiaramente, la chiave è quindi non passare un valore alfa a imshow. Tuttavia, dobbiamo ancora creare in qualche modo la barra dei colori.

Quindi, come soluzione alternativa, possiamo fare l'alpha che si fonde prima di dare le coordinate colore a imshow. Per fare un esempio, usiamo la winter mappa colore:

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') 

Qui creo una nuova mappa di colori, my_cmap_rgb, sulla base di winter e quindi modificare i canali non-alfa (0, 1 e 2) per fare l'alpha blending me stesso . Posso quindi semplicemente usare questa nuova mappa dei colori per tracciare la mia figura.

f, ax = plt.subplots() 
cim = ax.imshow(zz, cmap=my_cmap) 
cbar = plt.colorbar(cim) 
ax.set_title("No lines and no transparency") 

No lines and no transparency Ora confrontarlo con l'immagine che ci si ottiene senza questo trucco:

f, ax = plt.subplots() 
cim = ax.imshow(zz, cmap='winter', alpha=0.5) 
cbar = plt.colorbar(cim) 
ax.set_title("Lines and transparency") 

Lines and transparency

Chiaramente il problema è risolto se si richiede alcuna trasparenza. D'altra parte, se si richiede trasparenza, c'è ancora una soluzione alternativa. Per prima cosa è necessario tracciare un'immagine senza trasparenza per ottenere la barra dei colori e quindi tracciarne una con trasparenza, ma la cui barra colori non verrà utilizzata.

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") 

Ciò restituisce un'immagine la cui barra colori non ha linee e tuttavia conserva la trasparenza. Anche se rimane un enorme trucco, almeno non dobbiamo più sopportare queste righe!

No lines and transparency

+0

Ho applicato l'ultimo trucco (trama senza alfa, diagramma di colore, trama con alfa), poiché dovevo eseguire le immagini attraverso imshow, con il secondo sovrapposto in modo trasparente sul primo e il secondo con la barra del colore. In questo modo si imbatte nella questione delle strisce trasparenti. – Evert

0

Il seguente può essere un'altra soluzione, anche se non è 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) 
0

Dal momento che nessuno degli altri suggerimenti ha funzionato per me ho finito per rimuovere il canale alfa dall'istanza colorbar:

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 colorbar doveva essere disegnato una volta prima di poter accedere ai colori delle facce .

Problemi correlati