supprimer la barre de couleur de la figure dans matplotlib

ça devrait être facile mais j'ai du mal avec ça. Fondamentalement, j'ai un subplot dans matplotlib que je dessine un tracé hexbin à chaque fois qu'une fonction est appelée, mais chaque fois que j'appelle la fonction j'obtiens une nouvelle barre de couleur, donc ce que je voudrais vraiment faire est de mettre à jour la barre de couleur. Malheureusement, cela ne semble pas fonctionner puisque l'objet auquel la barre de couleur est attachée est recréé par subplot.hexbin.

def foo(self):
   self.subplot.clear()
   hb = self.subplot.hexbin(...)
   if self.cb:
      self.cb.update_bruteforce() # Doesn't work (hb is new)
   else:
      self.cb = self.figure.colorbar(hb)

je suis maintenant dans cet endroit ennuyeux où je suis essayer de supprimer les axes de barre de couleur tout à fait et simplement le recréer. Malheureusement, quand j'efface les axes de la barre de couleur, les axes des sous-lots ne récupèrent pas l'espace, et s'appellent eux-mêmes.intrigue secondaire.reset_position () ne fait pas ce que je pensais qu'il ferait.

def foo(self):
   self.subplot.clear()
   hb = self.subplot.hexbin(...)
   if self.cb:
      self.figure.delaxes(self.figure.axes[1])
      del self.cb
      # TODO: resize self.subplot so it fills the 
      #    whole figure before adding the new colorbar
   self.cb = self.figure.colorbar(hb)

est-ce que quelqu'un a des suggestions?

très apprécié! Adam

21
demandé sur Adam Fraser 2011-03-10 19:55:03

8 réponses

je pense que le problème est qu'avec del vous annulez la variable, mais pas la barre de couleur de l'objet référencé. Si vous voulez que la barre de couleur soit retirée de la parcelle et disparaisse, vous devez utiliser la méthode remove de l'instance de barre de couleur et pour ce faire, vous devez avoir la barre de couleur dans une variable, pour laquelle vous avez deux options:

  1. maintenir la barre de couleur dans une valeur au moment de la création, comme indiqué dans d'autres réponses par exemple cb=plt.colorbar()
  2. récupérez une barre de couleur existante, que vous pouvez faire en suivant (et upvoting :)) ce que j'ai écrit ici: comment récupérer une instance de barre de couleur à partir de la figure dans matplotlib puis:

cb.remove() plt.draw() #update plot

17
répondu Vincenzooo 2018-01-25 14:56:12

Voilà ma solution. Pas très élégant, mais pas terrible hack.

def foo(self):
   self.subplot.clear()
   hb = self.subplot.hexbin(...)
   if self.cb:
      self.figure.delaxes(self.figure.axes[1])
      self.figure.subplots_adjust(right=0.90)  #default right padding
   self.cb = self.figure.colorbar(hb)

cela fonctionne pour mes besoins puisque je n'ai jamais un seul sous-lot. Les personnes qui rencontrent le même problème en utilisant plusieurs sous-lots ou en dessinant la barre de couleur dans une position différente auront besoin de tweak.

8
répondu Adam Fraser 2011-03-10 20:37:14

j'ai réussi à résoudre le même problème en utilisant fig.clear() et de l'affichage.clear_output ()

import matplotlib.pyplot as plt
import IPython.display as display
import matplotlib.tri as tri
from pylab import *
%matplotlib inline

def plot_res(fig):
    ax=fig.add_axes([0,0,1,1])
    ax.set_xlabel("x")
    ax.set_ylabel('y')
    plotted=ax.imshow(rand(250, 250))
    ax.set_title("title")
    cbar=fig.colorbar(mappable=plotted)
    display.clear_output(wait=True)
    display.display(plt.gcf())
    fig.clear()

fig=plt.figure()
N=20
for j in range(N):
    plot_res(fig)
4
répondu kenissur 2015-11-25 11:38:48

j'ai eu un problème similaire et a joué un petit peu. J'ai proposé deux solutions qui pourraient être un peu plus élégantes:

  1. effacer la figure entière et ajouter le sous-lot (+barre de couleur si désiré) à nouveau.

  2. S'il y a toujours une barre de couleur, vous pouvez simplement mettre à jour les axes avec une échelle automatique qui met également à jour la barre de couleur.

j'ai essayé avec imshow, mais je suppose que cela fonctionne de la même façon pour les autres méthodes de pointage.

from pylab import *
close('all') #close all figures in memory

#1. Figures for fig.clf method
fig1 = figure()
fig2 = figure()
cbar1=None
cbar2=None
data = rand(250, 250)

def makefig(fig,cbar):
  fig.clf()
  ax = fig.add_subplot(111)
  im = ax.imshow(data)
  if cbar:
    cbar=None
  else:
    cbar = fig.colorbar(im)
  return cbar


#2. Update method
fig_update = figure()
cbar3=None
data_update = rand(250, 250)
img=None

def makefig_update(fig,im,cbar,data):
  if im:
    data*=2 #change data, so there is change in output (look at colorbar)
    #im.set_data(data) #use this if you use new array
    im.autoscale()
    #cbar.update_normal(im) #cbar is updated automatically
  else:
    ax = fig.add_subplot(111)
    im = ax.imshow(data)
    cbar=fig.colorbar(im)
  return im,cbar,data

#Execute functions a few times
for i in range(3):
  print i
  cbar1=makefig(fig1,cbar1)
  cbar2=makefig(fig2,cbar2)
  img,cbar3,data_update=makefig_update(fig_update,img,cbar3,data_update)
cbar2=makefig(fig2,cbar2)

fig1.show()
fig2.show()
fig_update.show()
3
répondu cass 2013-05-27 14:23:59

Ne veux rien enlever à l'auteur de ce blog post (Joseph de Long) mais c'est clairement la meilleure solution que j'ai trouvé jusqu'à présent. Il comprend des morceaux de code, de grandes explications et de nombreux exemples.

pour résumer, à partir de n'importe quelle sortie d'un axe ax de la commande: parcelle , image , scatter , collection , etc. tels que:

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5,5), dpi=300)
ax = fig.add_subplot(1, 1, 1)

data = ax.plot(x,y)
# or
data = ax.scatter(x, y, z)
# or
data = ax.imshow(z)
# or 
data = matplotlib.collection(patches)
ax.add_collection(data)

vous créez un axe de barre de couleur en utilisant le make_axes_locatable et l'axe original de la parcelle.

from mpl_toolkits.axes_grid1 import make_axes_locatable

# the magical part
divider = make_axes_locatable(ax)
caxis = divider.append_axes("right", size="5%", pad=0.05)
fig.colorbar(data, cax=caxis)

plt.show()

la barre de couleurs créée aura la même taille que la figure ou le sous-placage et vous pouvez la modifier largeur , emplacement , rembourrage en utilisant le diviseur .appendic_axes commande.

1
répondu philefou 2017-11-20 19:29:44

j'utilise matplotlib 1.4.0. Voici comment je résous ce problème:

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

# A contour plot example:
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10.0 * (Z2 - Z1)
#

# first drawing
fig = plt.figure()
ax = fig.add_subplot(111)  # drawing axes
c = ax.contourf(Z)   # contour fill c
cb = fig.colorbar(c)  # colorbar for contour c

# clear first drawimg
ax.clear()  # clear drawing axes
cb.ax.clear()  # clear colorbar axes

# replace with new drawing
# 1. drawing new contour at drawing axes
c_new = ax.contour(Z)  
# 2. create new colorbar for new contour at colorbar axes
cb_new = ax.get_figure().colorbar(c_new, cax=cb.ax) 

plt.show()

ci-dessus le code dessine une courbe de remplissage de contour avec la barre de couleur, l'éclaircir et dessiner une nouvelle courbe de contour avec la nouvelle barre de couleur à la même figure.

en utilisant cb.ax je suis capable d'identifier la barre de couleur axes et effacer les anciennes barre de couleur. Et en spécifiant cax=cb.ax dessine simplement la nouvelle barre de couleur dans les anciens axes de barre de couleur.

0
répondu Northern 2014-08-26 04:54:29

j'ai dû enlever les barres de couleur parce que je traçais un pcolormesh et ajoutant barre de couleur à une figure dans une boucle. Chaque boucle créerait une nouvelle barre de couleur et après dix boucles j'aurais dix barres de couleur. Ce qui était mauvais.

pour supprimer les barres de couleur, je nomme le pcolormesh et la barre de couleur une variable, puis à la fin de ma boucle je supprime chacun. Il est important de supprimer la barre de couleur avant en enlevant le pcolormesh.

Code Psudo:

 for i in range(0,10):
   p = plt.pcolormesh(datastuff[i])
   cb = plt.colorbar(p)
   plt.savefig('name_'+i)

   cb.remove()
   p.remove()

encore une fois, il a fallu enlever la barre de couleur avant le pcolormesh

0
répondu blaylockbk 2016-10-06 20:54:08

"on_mappable_changed" a fonctionné dans mon cas. Cependant, selon docs, la méthode "typiquement ... ne devrait pas être appelé manuellement."

if self.cb:
    self.cb.on_mappable_changed(hb)
else:
    self.cb = self.fig.colorbar(hb)
-1
répondu bejota 2016-06-02 21:13:32