Javascript Jupyter(IPython)笔记本中的交互式绘图,带有可拖动点,拖动点时调用Python代码
我想在Jupyter笔记本中制作一些交互式绘图,其中用户可以拖动绘图中的某些点。然后,这些点的位置应作为Python函数(在笔记本中)的输入,用于更新绘图 这里已经完成了类似的工作: 但是回调是针对Javascript函数的。在某些情况下,更新绘图的代码需要非常复杂,并且需要很长时间才能用Javascript重写。如果需要的话,我愿意用Javascript指定可拖动的点,但是可以调用Python来更新绘图吗 我想知道像Bokeh或Plotly这样的工具是否可以提供这种功能;博士Javascript Jupyter(IPython)笔记本中的交互式绘图,带有可拖动点,拖动点时调用Python代码,javascript,python,matplotlib,ipython-notebook,Javascript,Python,Matplotlib,Ipython Notebook,我想在Jupyter笔记本中制作一些交互式绘图,其中用户可以拖动绘图中的某些点。然后,这些点的位置应作为Python函数(在笔记本中)的输入,用于更新绘图 这里已经完成了类似的工作: 但是回调是针对Javascript函数的。在某些情况下,更新绘图的代码需要非常复杂,并且需要很长时间才能用Javascript重写。如果需要的话,我愿意用Javascript指定可拖动的点,但是可以调用Python来更新绘图吗 我想知道像Bokeh或Plotly这样的工具是否可以提供这种功能;博士 为此,您需要
为此,您需要知道:
- 如何从Jupyter的Javascript与IPython内核交互
前端。现在是通过
()Jupyter.Kernel.execute
- 足够舒服了。(与屏幕到绘图坐标转换类似。)
- D3Via Python库是您选择的。对于这个例子
input
元素链接到Jupyter笔记本绘图的方法,因此不是你想要的。但比我提议的要容易一千倍。IPyWidget在其示例套件中获取github repo到的链接
关于Jupyter笔记本电脑与IPython内核的直接交互的最佳博客文章来自2013年。这是给伊皮顿的你试过了吗?
Scatter
有一个enable\u move
参数,当您设置为True
时,它们允许拖动点。此外,拖动时,您可以观察到Scatter
或Label
的x
或y
值的变化,并通过该值触发python函数,从而生成新的绘图。他们在笔记本上这样做
Jupyter笔记本代码:
# Let's begin by importing some libraries we'll need
import numpy as np
from __future__ import print_function # So that this notebook becomes both Python 2 and Python 3 compatible
# 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)
from bqplot import pyplot as plt
# Creating a new Figure and setting it's title
plt.figure(title='My Second Chart')
# Let's assign the scatter plot to a variable
scatter_plot = plt.scatter(x_data, y_data)
# Let's show the plot
plt.show()
# then enable modification and attach a callback function:
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]
# First, we hook up our function `foo` to the colors attribute (or Trait) of the scatter plot
scatter_plot.observe(foo, ['y','x'])
scatter_plot.enable_move = True
您可能想使用bokeh而不是matplotlib@MaxNoe如果你能提供一个bokeh的工作示例,我会接受这个答案。哇,谢谢你,我从来没有听说过mpld3。改变一切。这有用吗@slushy谢谢,但该示例只使用了常用的小部件。它不会对鼠标单击绘图做出响应。
javascriptCallback = function(out) {
// Error checking omitted for brevity.
output = out.content.user_expressions.out1;
res = output.data["text/plain"];
newValue = JSON.parse(res); // If necessary
//
// Use newValue to do something now.
//
}
var kernel = Jupyter.notebook.kernel;
var callbacks = {shell: {reply: javascriptCallback }};
kernel.execute(
"print('only the success/fail status of this code is reported')",
callbacks,
{user_expressions:
{out1: "python_callback(" + 10 + ")"} // function call as a string
}
);
import matplotlib as mpl
import mpld3
class DragPlugin(mpld3.plugins.PluginBase):
JAVASCRIPT = r"""
// Beginning content unchanged, and removed for brevity.
DragPlugin.prototype.draw = function(){
var obj = mpld3.get_element(this.props.id);
var drag = d3.behavior.drag()
.origin(function(d) { return {x:obj.ax.x(d[0]),
y:obj.ax.y(d[1])}; })
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
// Additional content unchanged, and removed for brevity
obj.elements()
.data(obj.offsets)
.style("cursor", "default")
.attr("name", "redrawable") // DIFFERENT
.call(drag);
// Also modify the 'dragstarted' function to store
// the starting position, and the 'dragended' function
// to initiate the exchange with the IPython kernel
// that will update the plot.
};
"""
def __init__(self, points):
if isinstance(points, mpl.lines.Line2D):
suffix = "pts"
else:
suffix = None
self.dict_ = {"type": "drag",
"id": mpld3.utils.get_id(points, suffix)}
# Let's begin by importing some libraries we'll need
import numpy as np
from __future__ import print_function # So that this notebook becomes both Python 2 and Python 3 compatible
# 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)
from bqplot import pyplot as plt
# Creating a new Figure and setting it's title
plt.figure(title='My Second Chart')
# Let's assign the scatter plot to a variable
scatter_plot = plt.scatter(x_data, y_data)
# Let's show the plot
plt.show()
# then enable modification and attach a callback function:
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]
# First, we hook up our function `foo` to the colors attribute (or Trait) of the scatter plot
scatter_plot.observe(foo, ['y','x'])
scatter_plot.enable_move = True