2012-12-01 18 views
10

Uso i dispositivi di scorrimento Matplotlib, simili a this demo. I cursori usano attualmente 2 cifre decimali e "sentono" abbastanza continuo (anche se devono essere discreti su un certo livello). Posso decidere a che livello sono discreti? Passi interi? Passi di dimensioni pari a 0,1? 0.5? Il mio google-fu mi ha fallito.Posso rendere più discreti i cursori matplotlib?

+0

posso cambiare la visualizzazione in interi con: valfmt = '% 1.0f' ma non cambia l'output. Attualmente sto cercando di introdurre qualche arrotondamento da qualche parte, ma sembra che questa dovrebbe essere una proprietà del dispositivo di scorrimento. –

+1

Ho subito capito che posso arrotondare() l'input all'interno della funzione che aggiorna il cursore, oltre a visualizzare solo i numeri decimali corretti. Ma se voglio arrotondare a incrementi di 1/2, non posso fare in modo che il display corrisponda al valore (mostrerà comunque una precisione a 0.1) –

+0

Hai solo bisogno di impostare il valore di visualizzazione ogni volta. Finché stai bene con esso, non "sentendoti" come valori discreti (ad esempio, la barra continua a procedere senza intoppi), puoi comunque far sì che il display rifletta i valori discreti. (Aggiungendo un esempio in un po '...) –

risposta

22

Se si desidera solo valori interi, basta passare in un approriate valfmt quando si crea lo slider (ad esempio valfmt='%0.0f')

Tuttavia, se si desidera invervals non interi, sarà necessario impostare manualmente il valore di testo ogni volta. Anche se lo fai, il dispositivo di scorrimento procederà comunque in modo fluido e non "sentirà" come intervalli discreti.

Ecco un esempio:

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib.widgets import Slider 

class ChangingPlot(object): 
    def __init__(self): 
     self.inc = 0.5 

     self.fig, self.ax = plt.subplots() 
     self.sliderax = self.fig.add_axes([0.2, 0.02, 0.6, 0.03], 
              axisbg='yellow') 

     self.slider = Slider(self.sliderax, 'Value', 0, 10, valinit=self.inc) 
     self.slider.on_changed(self.update) 
     self.slider.drawon = False 

     x = np.arange(0, 10.5, self.inc) 
     self.ax.plot(x, x, 'ro') 
     self.dot, = self.ax.plot(self.inc, self.inc, 'bo', markersize=18) 

    def update(self, value): 
     value = int(value/self.inc) * self.inc 
     self.dot.set_data([[value],[value]]) 
     self.slider.valtext.set_text('{}'.format(value)) 
     self.fig.canvas.draw() 

    def show(self): 
     plt.show() 

p = ChangingPlot() 
p.show() 

Se si voleva fare il cursore "sentire" del tutto, come valori discreti, si potrebbe creare una sottoclasse matplotlib.widgets.Slider. L'effetto chiave è controllato da Slider.set_val

In tal caso, si farebbe qualcosa di simile:

class DiscreteSlider(Slider): 
    """A matplotlib slider widget with discrete steps.""" 
    def __init__(self, *args, **kwargs): 
     """Identical to Slider.__init__, except for the "increment" kwarg. 
     "increment" specifies the step size that the slider will be discritized 
     to.""" 
     self.inc = kwargs.pop('increment', 0.5) 
     Slider.__init__(self, *args, **kwargs) 

    def set_val(self, val): 
     discrete_val = int(val/self.inc) * self.inc 
     # We can't just call Slider.set_val(self, discrete_val), because this 
     # will prevent the slider from updating properly (it will get stuck at 
     # the first step and not "slide"). Instead, we'll keep track of the 
     # the continuous value as self.val and pass in the discrete value to 
     # everything else. 
     xy = self.poly.xy 
     xy[2] = discrete_val, 1 
     xy[3] = discrete_val, 0 
     self.poly.xy = xy 
     self.valtext.set_text(self.valfmt % discrete_val) 
     if self.drawon: 
      self.ax.figure.canvas.draw() 
     self.val = val 
     if not self.eventson: 
      return 
     for cid, func in self.observers.iteritems(): 
      func(discrete_val) 

E come un esempio completo di usarlo:

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib.widgets import Slider 

class ChangingPlot(object): 
    def __init__(self): 
     self.inc = 0.5 

     self.fig, self.ax = plt.subplots() 
     self.sliderax = self.fig.add_axes([0.2, 0.02, 0.6, 0.03], 
              axisbg='yellow') 

     self.slider = DiscreteSlider(self.sliderax, 'Value', 0, 10, 
            increment=self.inc, valinit=self.inc) 
     self.slider.on_changed(self.update) 

     x = np.arange(0, 10.5, self.inc) 
     self.ax.plot(x, x, 'ro') 
     self.dot, = self.ax.plot(self.inc, self.inc, 'bo', markersize=18) 

    def update(self, value): 
     self.dot.set_data([[value],[value]]) 
     self.fig.canvas.draw() 

    def show(self): 
     plt.show() 

class DiscreteSlider(Slider): 
    """A matplotlib slider widget with discrete steps.""" 
    def __init__(self, *args, **kwargs): 
     """Identical to Slider.__init__, except for the "increment" kwarg. 
     "increment" specifies the step size that the slider will be discritized 
     to.""" 
     self.inc = kwargs.pop('increment', 0.5) 
     Slider.__init__(self, *args, **kwargs) 

    def set_val(self, val): 
     discrete_val = int(val/self.inc) * self.inc 
     # We can't just call Slider.set_val(self, discrete_val), because this 
     # will prevent the slider from updating properly (it will get stuck at 
     # the first step and not "slide"). Instead, we'll keep track of the 
     # the continuous value as self.val and pass in the discrete value to 
     # everything else. 
     xy = self.poly.xy 
     xy[2] = discrete_val, 1 
     xy[3] = discrete_val, 0 
     self.poly.xy = xy 
     self.valtext.set_text(self.valfmt % discrete_val) 
     if self.drawon: 
      self.ax.figure.canvas.draw() 
     self.val = val 
     if not self.eventson: 
      return 
     for cid, func in self.observers.iteritems(): 
      func(discrete_val) 


p = ChangingPlot() 
p.show() 

enter image description here

+0

"+1", "grazie", scusa ragazzi , non potevo aiutare me stesso. – roadrunner66

0

Se preferisci non sottoclasse lo Slider, ho selezionato alcune linee @Joe Kington's risposta per realizzare la discretizzazione all'interno della funzione callback ione:

sldr = Slider(ax,'name',0.,5.,valinit=0.,valfmt="%i") 
sldr.on_changed(partial(set_slider,sldr)) 

e poi:

def set_slider(s,val): 
    s.val = round(val) 
    s.poly.xy[2] = s.val,1 
    s.poly.xy[3] = s.val,0 
    s.valtext.set_text(s.valfmt % s.val) 
Problemi correlati