实际上是否可以将数据(回调)从mpld3传递到ipython?

时间:2016-06-15 13:41:48

标签: javascript python mpld3 ipywidgets

使用mpld3制作动画图片有很多惊人的可能性。然而,似乎所有的"移动部件"是JavaScript的责任。此外,互联网和Stack Overflow上有很多请求,人们直接要求这种可能性。

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?

其中有引用,但所有答案都错了,因为他们建议使用某种警报或标题。然而,第二个链接最有趣,因为它建议添加一些HTML表单并按下按钮将数据发送到" server-python"来自" client-javascript"。还有另一个有趣的笔记本

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

很多人都提到了

作为灵感来源 - 它将输出配置保存为.html文件。也许这个硬盘交换可以用来通过python进一步处理这些信息。

进一步发展,我发现了IPYwidgets,其中包含大量示例甚至是TRUE交互客户端 - 服务器的可能性。从本质上讲,我们可以从基本的滑块和按钮开始,但后来我们看到在此基础上构建了一些更复杂的包:主要是bqplot,以及其他一些继承的包。

我想要的 - 只是拖放图片上的一些点,然后将它们传递给iPython以制作更多的图表 - 它非常复杂,绝对无法移动到JavaScript。但似乎尽管bqplot的团队做了大量的工作,但你只能使用一些"预定义的"交互集,因此再次不包括拖放行为。

当我尝试(不是非常深入)输入mpld3的源代码并修改它并可能与ipywidgets合并时,我遇到很多东西都被弃用了,代码发展得非常快,这并不符合互联网上现有的例子:大多数杨树都很老,查询也很老。所以由于混乱,我无法做任何事情,许多例子由于缺乏向后兼容性而失败。

摘要。如果有人提供某种方法来拖放点并将其坐标传递给python,我会很高兴,但这对我来说更有帮助 - 是从mpld3采用更抽象的方式",以便可以包含其他案例。

3 个答案:

答案 0 :(得分:4)

问题问题已经过去差不多一年了。好吧,答案不是mpld3,但我并不坚持这种特殊的技术。用户@Drew建议使用bqplot,因此我发布了相关笔记本的链接

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

来自bloomberg。如果您打开它,我建议您找到右上角的链接,该链接会将您重定向到带有图片的外部nbviewer。几乎所有内容都包含在那里,我只是尝试重现一个简约的工作示例。

请注意,为了推出扩展名为jupyter notebook的{​​{1}},以及某些bqplot,您可能需要执行某种" magic"使它工作。您需要熟悉一些bash命令,例如ipywidgetsjupyter install nbextension。我个人不得不与jupyter nbextension enable斗争几个小时才能使其发挥作用。但这显然是一个单独的问题。

让我们尝试启动函数bqplot。测试函数observe只打印事件。

my_callback(...)

你得到一个像这样的好情节: Random plot from bqplot

具有拖动点的附加功能。拖动一个点后,您会看到一个打印的更改列表,它是一个%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() 结构,每个事件都在一个单独的行上。

enter image description here

  

{'所有者':,'新':{u' hovered_point':1},' old&#39 ;: traitlets.Undefined,& #39;姓名':' _property_lock','输入':'更改'}

     

{'所有者':,'新':1,'旧':无,'名称':' hovered_point& #39;,'键入':'更改'}

     

{'所有者':,'新':{},' old':{u' hovered_point':1},&# 39;姓名':' _property_lock','输入':'更改'}

     

{'所有者':,'新':{u' y':{u' type':u'浮动',你':[4,4.863453784620906,6]},你':{u'输入':你'浮动' ,u'值':[1,2.016078455307904,3]}},' old':{},' name':' _property_lock', '键入':'更改'}

     

{'所有者':,'新':数组([4.,4.86345378,6。]),' old':数组([4, 5,6],'名称':' y','键入':'更改'}

     

{'所有者':,'新':数组([1.,2.01607846,3。]),' old':数组([1, 2,3],'姓名':' x','输入':'更改'}

     

{'所有者':,'新':{},' old':{u' y':{u'键入':你'浮动','价值':[4,4.863453784620906,6]},u' x':{u' type' :u' float',u'值':[1,20016078455307904,3]}},' name':' _property_lock',&#39 ;键入':'更改'}

     

{'所有者':,'新':{u' hovered_point':无},' old':{},&# 39;姓名':' _property_lock','输入':'更改'}

     

{'所有者':,'新':无,'旧':1,'名称':' hovered_point& #39;,'键入':'更改'}

     

{'所有者':,' new':{},' old':{u' hovered_point':无},&# 39;姓名':' _property_lock','输入':'更改'}

我承认结构分解有点棘手,但经过一些仔细的扫视后,我们注意到粗线的python等于'name',然后'_property_lock'子结构包含字段'new'u'x',这是" x"的Unicode和" y"。

然后你可以跟踪这些变化并相应地在函数u'y'中运行一些python代码,你甚至可以在这个图中绘制一些东西,或者创建一个新的等等。令人惊讶的是,这在某种程度上有效,使用新的jupyter,您甚至可以使用小部件保存笔记本,这是完全令人费解的。

答案 1 :(得分:2)

您可以使用新的bqplot ScatterLabel执行此操作,这两个参数都有enable_move参数,当您设置为True时,它们允许点被拖。此外,当您drag时,observex yScatter的{​​{1}}或Label值会发生变化ColorPicker并触发python函数通过它,反过来又产生了一个新的情节。

那是清楚的吗?

答案 2 :(得分:1)

这也不是import * as ko from 'knockout'; import 'isomorphic-fetch'; interface Item { name: KnockoutObservable<string>; itemNumber: KnockoutObservable<string>; amount: KnockoutObservable<number>; unitPrice: KnockoutObservable<number>; } interface Invoice { dateFormatted: KnockoutObservable<string>; invoiceNumber: KnockoutObservable<string>; items: KnockoutObservableArray<Item>; } class InvoiceViewModel { public invoice: KnockoutObservable<Invoice> = ko.observable<Invoice>(); public test: KnockoutObservable<string> = ko.observable<string>("test"); constructor() { fetch('api/SampleData/GetInvoice') .then(response => response.json() as Promise<Invoice>) .then(data => { this.invoice(data); }); } public changeDateFormatted = () => { this.test('123'); this.invoice().dateFormatted('123'); } } export default { viewModel: InvoiceViewModel, template: require('./invoice.html') }; ,但这里有一个在mpld3中使用bqplot的简单示例,受到谢尔盖在Is it actually possible to pass data (callback) from mpld3 to ipython?的评论/问题以及谢尔盖和德鲁的启发答案。

首先,在anaconda环境中安装jupyter notebook并打开笔记本

bqplot

然后将这个可调整的交互式散点图代码粘贴到第一个块中:

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

conda install bqplot

jupyter notebook

然后,在绘图出现后,单击并拖动一个或两个数据点,然后在下一个块中查看绘图中的更改:

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

我原以为https://github.com/bloomberg/bqplot/blob/master/examples/Introduction.ipynb中的回调内容是必需的,但如果你想在修改上触发一些代码,你只需要这样做。

为此,尝试类似:

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

然后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']) 坐标上的更改会触发x,y并更改全局变量foo。您将看到pdata的打印输出附加到第一个块的输出,更新的pdata将可用于未来的代码块。