2016-06-15 17 views
5

Ci sono molte possibilità incredibili per creare immagini animate usando mpld3. Tuttavia, sembra che tutte le "parti mobili" siano responsabilità di JavaScript. Inoltre, ci sono molte richieste su Internet e Stack Overflow in cui le persone chiedono direttamente questa possibilità.È effettivamente possibile passare dati (callback) da mpld3 a ipython?

Retrieve Data From Dynamic mpld3 plot in python

Get point information after dragging

How to "dump" points selected with the LinkedBrush plugin for mpld3?

mpld3 ~ Select points and get their coordinates?

con i riferimenti ivi, ma tutte le risposte sono sbagliate, in quanto si propongono di utilizzare una sorta di avvisi o didascalie. Il secondo collegamento è, tuttavia, il più interessante, dal momento che suggerisce di aggiungere un modulo HTML e di premere il pulsante per inviare i dati a "server-python" dal "client-javascript". V'è un altro notebook interessante

http://nbviewer.jupyter.org/gist/aflaxman/11156203

che è menzionato da molte persone come una fonte di ispirazione - salva la configurazione di uscita del file .html. Forse questo scambio di hard-disk può essere usato per procedere ulteriormente con Python.

Spostandomi, ho scoperto IPYwidgets, con un sacco di esempi e persino possibilità di VERO client-server di interazione. In sostanza, potremmo partire da cursori e pulsanti di base, ma poi vediamo che alcuni pacchetti più complessi sono costruiti su questa base: principalmente bqplot e alcuni altri pacchetti ereditati.

Quello che voglio - è solo trascinare e rilasciare alcuni punti sull'immagine, e poi passarli a iPython per fare ulteriori trame - è molto complicato e sicuramente non può essere spostato su JavaScript. Ma sembra che nonostante il team di bqplot abbia svolto un lavoro enorme, è possibile utilizzare solo alcune serie di interazioni "predefinite", quindi il comportamento di trascinamento della selezione non è ancora incluso.

Quando ho provato (non molto profondamente) per inserire il codice sorgente di mpld3 e modificarlo ed eventualmente unirmi con ipywidgets, ho riscontrato che molte cose sono deprecate, il codice si evolve molto velocemente, cosa che non si accorda con l'esistente esempi in internet: la maggior parte dei pioppi sono molto vecchi, e le richieste sono anche molto vecchie. Quindi non ho potuto fare nulla a causa del caos, molti esempi falliscono a causa della mancanza di compatibilità con le versioni precedenti.

Riepilogo. Sarei felice se qualcuno fornisse un modo per trascinare i punti e per passare le loro coordinate a Python, ma quale potrebbe essere più utile - è la possibilità di passare informazioni da mpld3 in un modo più "astratto", in modo che altri casi possono essere inclusi.

+0

UPD: A proposito, un po 'di tempo dopo aver postato la domanda originale, ho trovato una soluzione piuttosto valida sullo stack overflow: [Grafici interattivi in ​​jupyter notebook con punti trascinabili] (http://stackoverflow.com/questions/30207912/interactive-plots-in-jupyter-ipython-notebook-with-draggable-points-that-call? rq = 1), ha funzionato per me, ma con alcuni bug di visualizzazione, che non ho potuto correggere. La risposta non è accettata lì per qualche motivo. Ad ogni modo, l'intera procedura è piuttosto complicata. –

risposta

3

Quasi un anno è trascorso da quando è stata posta la domanda. Bene, la risposta non è circa mpld3, ma non aderisco a quella particolare tecnologia. L'utente @Drew suggerisce di utilizzare bqplot, così ho postare un link ad un notebook correlata

https://github.com/bloomberg/bqplot/blob/master/examples/Interactions/Interaction%20Layer.ipynb

da bloomberg. Se apri questo, ti consiglio di trovare il link nell'angolo in alto a destra che ti reindirizza a nbviewer esterno con le immagini. Quasi tutto è contenuto lì, cerco solo di riprodurre un esempio di lavoro minimalista.

Si noti che per avviare un jupyter notebook con l'estensione bqplot, così come alcuni ipywidgets, potrebbe essere necessario fare una sorta di "magia" per farlo funzionare. È necessario avere familiarità con alcuni comandi bash come jupyter install nbextension e jupyter nbextension enable. Personalmente ho dovuto lottare con bqplot per un paio d'ore per farlo funzionare. Ma questo è chiaramente un problema separato.

Facciamo un tentativo di prova per lanciare la funzione observe. La funzione test my_callback(...) stampa gli eventi.

%matplotlib inline 
from bqplot import pyplot as plt 

def my_callback(change): 
    print change 

scatt = plt.scatter([1,2,3],[4,5,6],enable_move=True) 
scatt.observe(my_callback) 
plt.show() 

si ottiene un bel terreno come questo: Random plot from bqplot

con l'aggiunta di capacità di trascinare punti. Una volta trascinato un punto, si osserva un elenco stampato di modifiche che è una struttura python, ogni evento su una riga separata.

enter image description here

{ 'titolare':, 'nuovo': {u'hovered_point ': 1}, 'vecchio': traitlets.Undefined, 'name': '_property_lock', 'tipo': 'cambiamento'}

{ 'titolare':, 'nuovo': 1, 'vecchio': None, 'name': 'hovered_point', 'tipo': 'cambiamento'}

{ 'proprietario' :, 'nuovo': {}, 'vecchio': {u'hovered_point ': 1},' nome ':' _property_lock ',' tipo ':' cambia '}

{'owner':, 'new': {u'y ': {u'type': u'float ', u'values': [4, 4.863453784620906, 6]}, u'x ': {u' digita ': u'float', u'values ​​': [1, 2.016078455307904, 3]}},' vecchio ': {},' nome ':' _property_lock ',' tipo ':' cambia '}

{'owner':, 'new': array ([4., 4.86345378, 6.]), 'old': array ([4, 5, 6]), 'name': 'y', 'type' : 'change'}

{'owner':, 'new': array ([1., 2.01607846, 3.]), 'old': array ([1, 2, 3]), 'name' : 'x', 'type': 'change'}

{'owner':, 'new': {}, 'old': {u'y ': {u'type': u'float ' , u'values ​​': [4, 4.863453784620906, 6]}, u'x': {u'type ': u'float', u'values ​​': [1, 2.016078455307904, 3]}}, 'nome': '_property_lock', 'tipo': 'cambia'}

{'owner':, 'new': {u'hovered_point ': None},' old ': {}, 'nome': '_property_lock', 'type': 'change'}

{'owner':, 'new': None, 'old': 1, 'name': 'hovered_point', ' digita ':' cambia '}

{' owner ':,' new ': {},' old ': {u'hovered_point': None}, 'name': '_property_lock', 'type': ' cambiamento '}

ammetto che la struttura è un po' difficile da decomporre, ma dopo un po 'attenta Glancing, notiamo che il la linea in grassetto ha 'name' uguale a '_property_lock', quindi la sottostruttura 'new' contiene i campi u'x' e u'y', che è Unicode per "x" e "y".

Quindi è possibile tenere traccia di questi cambiamenti e di conseguenza eseguire del codice python all'interno della funzione my_callback(...), si può anche disegnare qualcosa all'interno di questa trama, o crearne uno nuovo, ecc Sorprendentemente, questo funziona in qualche modo, e con il nuovo jupyter si può anche salvare il notebook con i widget che è completamente mindblowing.

+0

È fantastico: hai visto il codice che estrae i dati modificati? –

+0

Sono passato a un altro dominio quindi non sto più lavorando con questo oggetto .. Quindi, in generale, no, sfortunatamente no, non ho visto tali esempi. Ora puoi crearlo :) –

+0

Ne ho giocherellato alcuni in bqplot in un taccuino jupyter: puoi ottenere la funzione di callback per modificare le variabili globali o non locali e utilizzare i dati modificati altrove. Puoi 'scatt.observe (foo, ['x', 'y']) e ottenere i dati, quindi nel callback usare un' global pdata' e 'pdata = [scatter_plot.x, scatter_plot.y]' per aggiornare la variabile globale. –

2

Si può fare questo con il nuovo bqplotScatter e Label entrambi hanno un parametro enable_move, che quando si imposta True permettono punti da essere trascinati. Inoltre, quando si drag è possibile observe un cambiamento nel valore x o dello Scatter o Label e attivare una funzione Python attraverso quella, che a sua volta genera un nuovo grafico.

è chiaro?

+0

Questa è una buona notizia. Fammi controllare, ho bisogno di un po 'di tempo per farlo, perché è un problema molto vecchio per me, mi sono spostato su altre cose. Credo che dovrebbe essere importante per molte persone, quindi le commento appena lo controllo. Saluti. –

+0

A proposito, qualche tempo dopo aver postato la domanda originale, ho trovato una soluzione piuttosto valida sullo stack overflow: [Grafici interattivi in ​​jupyter notebook con punti trascinabili] (http://stackoverflow.com/questions/30207912/interactive-plots -in-jupyter-ipython-notebook-with-draggable-points-that-call? rq = 1), ha funzionato per me, ma con alcuni bug di visualizzazione, che non ho potuto correggere. La risposta non è accettata lì per qualche motivo. Ad ogni modo, l'intera procedura è piuttosto complicata. –

+1

Sembra buono. I widget di bqplot sono creati per attivare un collegamento continuo tra JavaScript e python, in modo tale che ogni componente della trama sia un widget. Ti permette di costruire interfacce grafiche molto complesse. – Drew

0

Anche questo non è mpld3, ma ecco un rapido esempio di utilizzo di bqplot in un jupyter notebook, ispirato da di Sergey commento/domanda a Is it actually possible to pass data (callback) from mpld3 to ipython? e Sergey e di risposte di Drew.

In primo luogo, installare bqplot in un ambiente anaconda e aprire un notebook

(... do whatever to make anaconda work for you....) 

conda install bqplot 

jupyter notebook 

Poi incollare questo codice dispersione interattivo regolabile nel primo blocco:

import numpy as np 
from __future__ import print_function # So that this notebook becomes both Python 2 and Python 3 compatible 
from bqplot import pyplot as plt 

# And creating some random data 
size = 10 
np.random.seed(0) 
x_data = np.arange(size) 
y_data = np.cumsum(np.random.randn(size) * 100.0) 


# Creating a new Figure and setting it's title 
plt.figure(title='An adjustable, extractable scatter plot') 
# Let's assign the scatter plot to a variable 
scatter_plot = plt.scatter(x_data, y_data) 
plt.show() 
scatter_plot.enable_move = True # make the points movable 

Poi, dopo la visualizzazione della trama, fai clic e trascina un punto dati o due intorno e nel prossimo blocco guarda le modifiche all'interno del grafico:

print([x_data-scatter_plot.x,y_data-scatter_plot.y]) 

Avevo pensato che fosse necessario il contenuto del callback in https://github.com/bloomberg/bqplot/blob/master/examples/Introduction.ipynb, ma è necessario solo se si desidera attivare un codice sulle modifiche.

Per questo, provare qualcosa di simile:

def foo(change): 
    print('This is a trait change. Foo was called by the fact that we moved the Scatter') 
    #print('In fact, the Scatter plot sent us all the new data: ') 
    #print('To access the data, try modifying the function and printing the data variable') 
    global pdata 
    pdata = [scatter_plot.x,scatter_plot.y] 
    #print (pdata) 

# Hook up our function `foo` to the coordinates attributes (or Traits) of the scatter plot 
scatter_plot.observe(foo, ['y','x']) 

cambia poi sul x,y coordinate innescano foo e cambiare la variabile globale pdata. Vedrai l'output stampato di foo() aggiunto all'output del primo blocco e il pdata aggiornato sarà disponibile per i futuri blocchi di codice.

Problemi correlati