Get started 🚀¶
The plotly-resampler
package offers two primary modules:
figure_resampler
: a wrapper for plotly.graph_objects Figures, coupling dynamic resampling functionality with the Figure.aggregation
: This module contains interfaces for the various aggregation methods implemented in tsdownsample.
Installation ⚙️¶
Install via pip:
pip install plotly-resampler
Usage 📈¶
Plotly-Resampler facilitates dynamic resampling in two ways:
-
Automatic Approach (low code overhead)
- utilize the
register_plotly_resampler
function - steps:
- Import and invoke
register_plotly_resampler
- That’s it! 🎉
Just proceed with your standard gaph construction workflow.
- Import and invoke
- Upon invoking
register_plotly_resampler
, all new defined plotly graph objects are transformed into eitherFigureResampler
orFigureWidgetResampler
object. Themode
parameter in this method determines which resampling Figure type is used.
- utilize the
-
Manual Approach (data aggregation configurability, graph construction speedups)
-
By utilizing Dash callbacks to augment a
go.Figure
with dynamic aggregation functionality.- steps:
- wrap the plotly Figure with
FigureResampler
- call
.show_dash()
on the Figure
- wrap the plotly Figure with
Note
This is particularly advantageous when working with Dash or outside Jupyter environments.
- steps:
-
By utilizing FigureWidget.layout.on_change , when a
go.FigureWidget
is used within a.ipynb
environment.-
steps:
- wrap your plotly Figure
(can be a
go.Figure
withFigureWidgetResampler
) - output the
FigureWidgetResampler
instance in a cell
Note
This is especially useful when developing in
jupyter
environments and when you cannot open/forward a network-port. - wrap your plotly Figure
(can be a
-
-
Tip
For significant faster initial loading of the Figure, we advise to
- wrap the constructor of the plotly Figure with either
FigureResampler
orFigureWidgetResampler
- add the trace data as
hf_x
andhf_y
Note
Any plotly Figure can be wrapped with dynamic aggregation functionality! 🎉
But only go.Scatter/go.Scattergl
traces will be resampled!
Examples ✅¶
register_plotly_resampler¶
import plotly.graph_objects as go; import numpy as np
from plotly_resampler import register_plotly_resampler, unregister_plotly_resampler
# Call the register function once and all Figures/FigureWidgets will be wrapped
# according to the register_plotly_resampler its `mode` argument
register_plotly_resampler(mode='auto')
x = np.arange(1_000_000)
noisy_sin = (3 + np.sin(x / 200) + np.random.randn(len(x)) / 10) * x / 1_000
# when working in an IPython environment, this will automatically be a
# FigureWidgetResampler else, this will be an FigureResampler
f = go.Figure()
f.add_trace({"y": noisy_sin + 2, "name": "yp2"})
f
# to undo the wrapping, call the unregister_plotly_resampler function
FigureResampler¶
# NOTE: this example works in a notebook environment
import plotly.graph_objects as go; import numpy as np
from plotly_resampler import FigureResampler
x = np.arange(1_000_000)
sin = (3 + np.sin(x / 200) + np.random.randn(len(x)) / 10) * x / 1_000
fig = FigureResampler(go.Figure())
fig.add_trace(go.Scattergl(name='noisy sine', showlegend=True), hf_x=x, hf_y=sin)
fig.show_dash(mode='inline')
Overview¶
In the example below, we demonstrate the (x-axis)overview
feature of plotly-ressampler.
For more information you can check out the examples to find dash apps and in-notebook use-cases.
!!! Note:
- This overview is only available for the FigureResampler
and not for the FigureWidgetResampler
.
- As a recent and experimental feature, user feedback is crucial. Please report any issues encountered!
FigureWidget¶
The gif below demonstrates the example usage of FigureWidgetResampler
, where JupyterLab
is used as the environment and the FigureWidgetResampler
.
Note how (i) the figure output is redirected into a new view, and (ii) how you are able to dynamically add traces!
Furthermore, plotly’s FigureWidget
allows to conveniently add callbacks to for example click events. This allows creating a high-frequency time series annotation app in a couple of lines; as shown in the gif below and in this notebook.
Important considerations & tips 🚨¶
- When running the code on a server, you should forward the port of the
FigureResampler.show_dash
method to your local machine.
Note that you can add dynamic aggregation to plotly figures with theFigureWidgetResampler
wrapper without needing to forward a port! - In general, when using downsampling one should be aware of (possible) aliasing effects.
The
[R]
in the legend indicates when the corresponding trace is resampled (and thus possibly distorted). The~ delta
suffix in the legend represents the mean index delta for consecutive aggregated data points. - The plotly autoscale event (triggered by the autoscale button or a double-click within the graph), does not reset the axes but autoscales the current graph-view of plotly-resampler figures. This design choice was made as it seemed more intuitive for the developers to support this behavior with double-click than the default axes-reset behavior. The graph axes can ofcourse be resetted by using the reset_axis button. If you want to give feedback and discuss this further with the developers, see this issue #49.
Dynamically adjusting the scatter data 🔩¶
The raw high-frequency trace data of plotly-resampler figures can be adjusted using the hf_data
property.
Working example ⬇️:
import plotly.graph_objects as go; import numpy as np
from plotly_resampler import FigureResampler
# Note: a FigureWidgetResampler can be used here as well
# Construct the hf-data
x = np.arange(1_000_000)
sin = (3 + np.sin(x / 200) + np.random.randn(len(x)) / 10) * x / 1_000
fig = FigureResampler(go.Figure())
fig.add_trace(go.Scattergl(name='noisy sine', showlegend=True), hf_x=x, hf_y=sin)
fig.show_dash(mode='inline')
# After some time -> update the hf_data y property of the trace
# As we only have 1 trace, this needs to be mapped
fig.hf_data[-1]['y'] = - sin ** 2
Note
hf_data only withholds high-frequency traces (i.e., traces that are aggregated).
To add non high-frequency traces (i.e., traces with fewer data points than max_n_samples),
you need to set the limit_to_view
argument to True when adding the corresponding trace with the
add_trace
function.
Tip
The FigureWidgetResampler
graph will not be automatically redrawn after adjusting the fig its hf_data property.
The redrawing can be triggered by manually calling either:
FigureWidgetResampler.reload_data
, which keeps the current-graph range.FigureWidgetResampler.reset_axes
, which performs a graph update.
Plotly-resampler & not high-frequency traces 🔍¶
Tip
In the Skin conductance example of the basic_example.ipynb, we deal with such low-frequency traces.
The add_trace
method allows configuring argument which allows us to deal with low-frequency traces.
Use-cases¶
-
not resampling trace data: To achieve this, set:
-
max_n_samples = len(hf_x)
-
not resampling trace data, but slicing to the view: To achieve this, set:
max_n_samples = len(hf_x)
limit_to_view = True
Note
For, irregularly sampled traces which are filled (e.g. colored background signal quality trace of the skin conductance example),
it is important that you set gap_handler
to NoGapHandler
for that trace.
Otherwise, when you leave gap_handler
to MedDiffGapHandler
, you may get weird background shapes such as ⬇️:
When gap_handler
is set to NoGapHandler
you get ⬇️: