2015-07-14 13 views
7

Sto usando pyplot per visualizzare un grafico a linee composto da un massimo di 30 righe. Vorrei aggiungere un modo per mostrare e nascondere rapidamente le singole linee sul grafico. Pyplot ha un menu in cui puoi modificare le proprietà della linea per cambiare il colore o lo stile, ma è piuttosto goffo quando vuoi nascondere le linee per isolare quella che ti interessa. Idealmente, mi piacerebbe usare le checkbox sulla legenda per mostrare e nascondere le linee. (Simile a mostrare e nascondere i livelli in editor di immagini come Paint.Net) Non sono sicuro che ciò sia possibile con pyplot, quindi sono aperto ad altri moduli purché siano abbastanza facili da distribuire.Nascondere le linee dopo aver visualizzato una figura pyplot

+0

Solo per arricchire la vostra domanda, è possibile trovare questo tipo di comportamento (selezionare quali linee mostreranno sul grafico facendo clic sui sottotitoli della legenda) in gnuplot, ad es. http://gnuplot.sourceforge.net/demo_svg_5.0/simple.html Non sono sicuro di quanto sia disposto a passare da pyplot a un altro strumento (gnuplot) , ma se vuoi tenere il passo con python e usare gnuplot c'è un'interfaccia 'gnuplot.py'. – David

+0

Questa è esattamente la funzionalità che sto cercando. Lo scaverò e vedrò quanto funzionerà bene con il mio programma. Aggiornamento – sommerjj

+0

: sto rinunciando a gnuplot. Non stava funzionando bene per me. – sommerjj

risposta

13

Se si desidera, è possibile collegare una richiamata alla legenda che mostrerà/nasconderà le linee quando vengono cliccati. Ecco un semplice esempio: http://matplotlib.org/examples/event_handling/legend_picking.html

Ecco un esempio di "fanciulle" che dovrebbe funzionare senza la necessità di specificare manualmente la relazione delle linee e dei marcatori di legenda (ha anche alcune altre funzionalità).

import numpy as np 
import matplotlib.pyplot as plt 

def main(): 
    x = np.arange(10) 
    fig, ax = plt.subplots() 
    for i in range(1, 31): 
     ax.plot(x, i * x, label=r'$y={}x$'.format(i)) 

    ax.legend(loc='upper left', bbox_to_anchor=(1.05, 1), 
       ncol=2, borderaxespad=0) 
    fig.subplots_adjust(right=0.55) 
    fig.suptitle('Right-click to hide all\nMiddle-click to show all', 
       va='top', size='large') 

    interactive_legend().show() 

def interactive_legend(ax=None): 
    if ax is None: 
     ax = plt.gca() 
    if ax.legend_ is None: 
     ax.legend() 

    return InteractiveLegend(ax.legend_) 

class InteractiveLegend(object): 
    def __init__(self, legend): 
     self.legend = legend 
     self.fig = legend.axes.figure 

     self.lookup_artist, self.lookup_handle = self._build_lookups(legend) 
     self._setup_connections() 

     self.update() 

    def _setup_connections(self): 
     for artist in self.legend.texts + self.legend.legendHandles: 
      artist.set_picker(10) # 10 points tolerance 

     self.fig.canvas.mpl_connect('pick_event', self.on_pick) 
     self.fig.canvas.mpl_connect('button_press_event', self.on_click) 

    def _build_lookups(self, legend): 
     labels = [t.get_text() for t in legend.texts] 
     handles = legend.legendHandles 
     label2handle = dict(zip(labels, handles)) 
     handle2text = dict(zip(handles, legend.texts)) 

     lookup_artist = {} 
     lookup_handle = {} 
     for artist in legend.axes.get_children(): 
      if artist.get_label() in labels: 
       handle = label2handle[artist.get_label()] 
       lookup_handle[artist] = handle 
       lookup_artist[handle] = artist 
       lookup_artist[handle2text[handle]] = artist 

     lookup_handle.update(zip(handles, handles)) 
     lookup_handle.update(zip(legend.texts, handles)) 

     return lookup_artist, lookup_handle 

    def on_pick(self, event): 
     handle = event.artist 
     if handle in self.lookup_artist: 
      artist = self.lookup_artist[handle] 
      artist.set_visible(not artist.get_visible()) 
      self.update() 

    def on_click(self, event): 
     if event.button == 3: 
      visible = False 
     elif event.button == 2: 
      visible = True 
     else: 
      return 

     for artist in self.lookup_artist.values(): 
      artist.set_visible(visible) 
     self.update() 

    def update(self): 
     for artist in self.lookup_artist.values(): 
      handle = self.lookup_handle[artist] 
      if artist.get_visible(): 
       handle.set_visible(True) 
      else: 
       handle.set_visible(False) 
     self.fig.canvas.draw() 

    def show(self): 
     plt.show() 

if __name__ == '__main__': 
    main() 

Ciò consente di fare clic sulle voci della legenda per attivare/disattivare i relativi artisti. Ad esempio, si può andare da questo:

enter image description here

A tal:

enter image description here

+1

Questa è esattamente la funzionalità che sto cercando! Stavo cercando di trovare strane soluzioni alternative come utilizzare una GUI di Tkinter con caselle di controllo che ridisegnavano il grafico ogni volta che veniva apportata una modifica alle selezioni. Questo è molto più semplice – sommerjj

+0

Ma sta ancora mostrando le leggende delle trame nascoste! – hbaromega

Problemi correlati