There is a lot of amazing possibilities to create animated pictures using mpld3
. However, it seems that all the "moving parts" are responsibility of JavaScript. Moreover, there are lots of requests on the internet and Stack Overflow where people directly ask for that possibility.
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?
with references therein, but all the answers are WRONG, since they propose to use some kind of alerts or captions. The second link is, however, most interesting, since it suggests to add some HTML-form and push the button to send the data to "server-python" from the "client-javascript". There is another interesting notebook
http://nbviewer.jupyter.org/gist/aflaxman/11156203
which is mentioned by many people as a source of inspiration - it saves the output configuration the .html file. Maybe this hard-disk exchange can be used to proceed this information further by python.
Moving further, I discovered IPYwidgets
, with plenty of examples and even possibilities of TRUE interaction client-server. Essentially, we may start from basic sliders and buttons, but then we see that some more complex packages are built on this basis: mainly bqplot
, and some other inherited packages.
What I want - is just to drag and drop some points on the picture, and then pass them to iPython to make some further plots - it is very complicated and definitely can't be moved to JavaScript. But it seems that despite the team of bqplot
has done a huge work, you can use only some "predefined" set of interactions, so the drag-and-drop behavior is again not included.
When I tried (not very deeply) to enter the source code of mpld3 and modify it and possibly merge with ipywidgets, I encountered that many things are deprecated, the code evolves really fast, which doesn't accord to the existing examples in the internet: most poplar ones are very old, and inquiries are also very old. So I couldn't do anything because of the mess, many examples fail because of lack of backward-compatibility.
Summary. I would be glad if anyone provided some way to drag-and-drop points and to pass their coordinates to python, but which could me more helpful - is the ability to pass information from mpld3 in a more "abstract manner", so that other cases can be included.
Almost a year has passed since the question has been asked. Well, the answer is not about mpld3
, but I don't stick to that particular technology. The user @Drew suggested to use bqplot
, so I post a link to a related notebook
https://github.com/bloomberg/bqplot/blob/master/examples/Interactions/Interaction%20Layer.ipynb
from bloomberg
. If you open this, I recommend to find the link in the top right corner which redirects you to external nbviewer with pictures. Almost everything is contained there, I just try to reproduce a minimalistic working example.
Note that in order to launch a jupyter notebook
with extension bqplot
, as well as some ipywidgets
, you may need to do some kind of "magic" to make it work. You need to be familiar with some bash commands like jupyter install nbextension
and jupyter nbextension enable
. I personally had to struggle with bqplot
for a couple of hours to make it work. But this is clearly a separate issue.
Let's do a trial attempt to launch the function observe
. The test function my_callback(...)
just prints the events.
%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()
you obtain a nice plot like this:
with additional capability to drag points. Once you drag a point, you observe a printed list of changes which is a python
structure, each event on a separate line.
{'owner': , 'new': {u'hovered_point': 1}, 'old': traitlets.Undefined, 'name': '_property_lock', 'type': 'change'}
{'owner': , 'new': 1, 'old': None, 'name': 'hovered_point', 'type': 'change'}
{'owner': , 'new': {}, 'old': {u'hovered_point': 1}, 'name': '_property_lock', 'type': 'change'}
{'owner': , 'new': {u'y': {u'type': u'float', u'values': [4, 4.863453784620906, 6]}, u'x': {u'type': u'float', u'values': [1, 2.016078455307904, 3]}}, 'old': {}, 'name': '_property_lock', 'type': 'change'}
{'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]}}, 'name': '_property_lock', 'type': 'change'}
{'owner': , 'new': {u'hovered_point': None}, 'old': {}, 'name': '_property_lock', 'type': 'change'}
{'owner': , 'new': None, 'old': 1, 'name': 'hovered_point', 'type': 'change'}
{'owner': , 'new': {}, 'old': {u'hovered_point': None}, 'name': '_property_lock', 'type': 'change'}
I admit that the structure is a bit tricky to decompose, but after some careful glancing, we note that the bold line has 'name'
equal to '_property_lock'
, then the 'new'
substructure contains the fields u'x'
and u'y'
, which is Unicode for "x" and "y".
Then you can track these changes and accordingly run some python
code inside the function my_callback(...)
, you can even draw something inside this plot, or create a new one, etc. Surprisingly, this somehow works, and with new jupyter you can even save the notebook with widgets which is completely mindblowing.