Is it possible to use extendData for distplot?

Hi,

Iā€™m trying to display a KDE plot (or distplot) of a live stream of data coming from an MQTT broker using dash and plotly.
For performance reason Iā€™m doing most of the stuff in client_side callback, and so far Iā€™ve managed to plot in ā€œreal timeā€ my data on a simple scatter graph.

Now Iā€™m trying to use a distplot but I canā€™t find out the expected format of the trace my callback should return for the extendData property, I donā€™t even know if distplot support thatā€¦ and donā€™t know where to look to find some info about it.

Here is the python code :

figure = ff.create_distplot([[0,1]], ["A"])
app.layout = html.Div([
    dcc.Interval(id="graph_updater", interval=100),
    dcc.Graph(id="graph", figure=figure)
])

clientside_callback(
    ClientsideFunction(
        namespace='clientside',
        function_name='graph_updater'
    ),
    Output('graph', 'extendData'),
    Input('graph_updater', 'n_intervals')
)

And my client_side callback, do not worry about how I retrieve my SENSORS_DATA this is working fine :


window.dash_clientside = Object.assign({}, window.dash_clientside, {
    clientside: {
        graph_updater: function(n_interval) {
            const sensor_path = "IMU_A";
            if(window.SENSORS_DATA == null)
                return window.dash_clientside.no_update;

            if(!(sensor_path in window.SENSORS_DATA))
                return window.dash_clientside.no_update;

            if(window.LATEST_INDEX_GRAPHED == null)
                window.LATEST_INDEX_GRAPHED = 0;

            //Prepare the new data
            nx = window.SENSORS_DATA[sensor_path]["timestamp"].slice(window.LATEST_INDEX_GRAPHED);
            ny = window.SENSORS_DATA[sensor_path]["roll"].slice(window.LATEST_INDEX_GRAPHED);

            window.LATEST_INDEX_GRAPHED = window.SENSORS_DATA[sensor_path]["timestamp"].length + 1; //Don't forget the +1 because the slice method is inclusive.
            //Need to return a tuple (dict(graph data to extend), [trace_index], number of data point to keep)
            return [{x: [ny]/*, y: [ny]*/}, [0], 5000];
        }
    }
});

I donā€™t know what to return in the client_side callbackā€¦ for the moment itā€™s not working and nothing change in the visualisation (but no error is thrown either).

Any help is appreciated, thanks !

To dynamically display a live KDE plot using Dash and Plotly while leveraging extendData, consider this alternative approach that sidesteps create_distplot()'s limitations by building the plot from foundational components: Rather than relying on create_distplot(), break the KDE visualization into two parts:

Histogram Bars: Represent the evolving frequency distribution.
KDE Line: A dynamically smoothed line, recalculated in real-time using client-side smoothing. Step 1: Server-Side Setup for Histogram Base
Instead of constructing the full figure server-side, initiate a simple histogram with empty data points: import dash
from dash import dcc, html
import plotly.graph_objs as go

app = dash.Dash(name)

app.layout = html.Div([
dcc.Graph(id=ā€˜live-kde-graphā€™),
dcc.Interval(id=ā€˜update-intervalā€™, interval=100)
])

@app.callback(
dash.Output(ā€˜live-kde-graphā€™, ā€˜figureā€™),
[dash.Input(ā€˜update-intervalā€™, ā€˜n_intervalsā€™)]
)
def initialize_graph(n):
if n == 0:
return go.Figure(data=[go.Bar(x=, y=, name=ā€˜Histogramā€™), go.Scatter(x=, y=, mode=ā€˜linesā€™, name=ā€˜KDEā€™)])
return dash.no_update

if name == ā€˜mainā€™:
app.run_server(debug=True)
Step 2: Client-Side Callback for Real-Time KDE Smoothing
Implement the KDE smoothing using Gaussian or moving average logic in JavaScript: window.dash_clientside = Object.assign({}, window.dash_clientside, {
clientside: {
graph_updater: function(n_interval) {
const data = window.LIVE_DATA || ; // Replace with your MQTT data source
if (data.length < 5) return window.dash_clientside.no_update;

        const latestData = data.slice(-50);  // Control how much data to display  

        const smoothedData = latestData.map((_, i) => {  
            const slice = latestData.slice(Math.max(i - 5, 0), i + 1);  
            return slice.reduce((sum, val) => sum + val, 0) / slice.length;  
        });  

        return [{  
            x: [Array.from({ length: smoothedData.length }, (_, i) => i)],  
            y: [smoothedData]  
        }, [1], 100];  // [1] refers to the KDE trace index  
    }  
}  

});

Yeah I figured I had to move away from distplot and create my own histogram. I actually went to use violin plot instead but now Iā€™m running into performance issueā€¦ Iā€™ve created a post here about it : Plotly Violin performance for live update