Plotly in Jupyterlab: difference between show method and display (effect on plotly on_change)

huangapple go评论52阅读模式
英文:

Plotly in Jupyterlab: difference between show method and display (effect on plotly on_change)

问题

在JupyterLab中,使用Plotly,我已经设置了一个回调来在缩放时更新y轴。

请参考下面的代码以获取完整示例。

缩放功能通过on_change与布局连接。

当使用IPython的display或直接使用fig显示图形时,y轴会正确更新。但是,如果使用figure.show()方法,则停止工作。

在这种特殊情况下,这种方法存在什么问题?为什么on_change不再起作用?

我知道figure.show()使用渲染器框架,但我无法理解它在这种“on_change”情况下的功能。

有人能解释一下这个问题或者指导我查阅相关文档吗?

谢谢!

英文:

In JupyterLab, using Plotly, I have set up a callback to update the y-axis when zooming.

Please refer to the code below for a complete example.

The zoom function is connected to the layout using on_change.

The yaxis updates correctly when the figure is displayed using IPython's display or directly with fig. However, it stops working if the figure.show() method is used.

What is the issue with this method in this particular scenario? Why does on_change no longer work?

import plotly.graph_objs as go
import pandas as pd
import numpy as np

x = np.linspace(0, 100, 1000)
y = 0.1* x * np.sin(2 * np.pi * 0.1 * x)

# Create the DataFrame
df = pd.DataFrame({'Time': x, 'Value': y})
df = df.set_index('Time')

fig = go.FigureWidget()

fig.add_trace(
    go.Scatter(x=df.index, y=df['Value'], mode='lines')
)

fig.update_layout(
        xaxis={'rangeslider_visible': True}
)

# callback function to update yaxis min and max upon zoom
def zoom(layout, xrange):
    in_view = df.loc[fig.layout.xaxis.range[0]:fig.layout.xaxis.range[1]]
    fig.layout.yaxis.range = [in_view.Value.min(), in_view.Value.max()]
    
fig.layout.on_change(zoom, 'xaxis.range')

#fig            # on_change (zoom) works!
display(fig)    # on_change (zoom) works!
#fig.show()     # on_change (zoom) doesn't work

I am aware that figure.show() utilizes the renderers framework, but I am unable to understand its functionality in this "on_change" scenario.

Could someone shed some light on this or direct me to the appropriate documentation?

Thank you!

答案1

得分: 1

  1. 使用 show() 方法会导致 on_change 处理程序不起作用的问题,是因为 fig.show() 实际上调用了 plotly.io.show() 方法,该方法根据指定的渲染器重新呈现对象本身。然而,on_change 事件处理程序是一个独立的事件模块,不是图形的属性的一部分。因此,在 plotly.io 重新呈现时,它不会包括在内,fig.show() 方法不会携带 on_change() 设置。另一方面,执行 fig/display(fig) 只是在 JupyterLab/Notebook 中显示对象,而不重新呈现,因此没有问题。

  2. 如果你使用 show() 来传递配置参数,那可能是问题所在。fig.show(config=config) 方法实际上设置了图形的私有属性 _config,它继承自父类 BaseFigure,唯一修改它的 API 接口是通过 show() 方法。因此,如果你想让 on_change 生效并同时设置配置,可以使用 fig.__setattr__('_config', config) 来设置图形的配置,例如 scrollZoom = True

顺便说一下,最好使用 fig.__getattributer__('_config') 先获取原始的 _config 值,然后与你要分配的新值合并。

# 设置回调
fig.layout.on_change(zoom, 'xaxis.range')

# 为示例准备鼠标滚轮缩放
_config = dict(scrollZoom=True)

# 获取原始 _config 属性并与你的合并
_config = fig.__getattribute__('_config') | _config
fig.__setattr__('_config', _config)

# 现在你同时拥有了 scrollZoom 配置和 on_change 缩放回调,不要使用 fig.show()
fig

这不是官方方式,但在 plotly 解决 show() 问题之前,这是一种可接受的做法。

英文:

I also ran into this problem where using the show() method prevented the on_change handler from working.

  1. The use of fig.show() actually calls the plotly.io.show() method, which re-renders the object itself based on the specified renderer. However, the on_change event handler is a standalone event module, and is not part of the Figure's property. Therefore, it will not be included when plotly.io re-renders it, and the fig.show() method won't carry on_change() settings. On the other hand, executing fig/display(fig) just displays the object in JupyterLab/Notebook, without re-rendering, so there is no issue.

  2. If you are using show() to pass the config parameter, that is likely where the problem is. The fig.show(config=config) method actually sets the figure's private attribute _config, which inherits from the parent class BaseFigure, and the only API interface to modify it is through the show() method. Therefore, if you want to make on_change work and set config at the same time, use fig.__setattr__('_config', config) to set fig's config, such as scrollZoom = True.

Btw, it's a good idea to use fig.__getattributer__('_config') to get the original _config value first, and then merge it with the new value you want to assign.

...

# set callback
fig.layout.on_change(zoom, 'xaxis.range')

# prepare mouse wheel zoom for example
_config = dict(scrollZoom=True)

# get original _config attribute and merge with yours
_config = fig.__getattribute__('_config') | _config
fig.__setattr__('_config', _config)

# now you have both scrollZoom config and on_change zoom
# callback work together, and don't use fig.show()
fig

It's not the official way, but it's an acceptable practice until plotly solves the show() issue.

huangapple
  • 本文由 发表于 2023年6月19日 05:35:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502612.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定