✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐇 Announcing Dash VTK for 3d simulation graphics. Check out the March webinar.

Dash canvas with plotly figures

Is there a way to use the dash canvas capabilities (drawing things) with other types of figures than images (like scatter plots) ?

Thanks for your help

Hi @brunorigal welcome to the forum! At the moment this is not possible but it would be nice indeed to add such drawing possibilities to plotly figures. One thing you can do at the moment is to add shapes to your figure (like circles, rectangles, see https://plot.ly/python/shapes/) and show your figure in editable mode : fig.show(config={'editable': True}), also see https://plot.ly/python/configuration-options/#edit-mode--change-the-title-and-axis-titles. This way you can modify (move, rescale) shapes and trigger callbacks. See below an example which I wrote to measure intensity profiles through an image, maybe you can adapt it to your own application?

It would be interesting if you could give more details about what you would like to do, it could help us design future drawing features for plotly figures.

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import numpy as np
import plotly.graph_objs as go
import plotly.express as px
import numpy as np

from skimage import data
from skimage import draw
img = data.chelsea()
fig = px.imshow(img)
fig.add_shape(
        go.layout.Shape(
            type="line",
            x0=0,
            y0=250,
            x1=100,
            y1=250,
            xref='x',
            yref='y',
            line=dict(
                color="RoyalBlue",
                width=3
            )
))
#fig.update_xaxes(automargin=True)
#fig.update_yaxes(automargin=True)
fig.update_layout(margin=dict(t=0, l=0, r=0, b=0), height=450)

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    html.Div(
    dcc.Graph(
        id = 'graph-im',
        figure=fig,
        config={'editable':True}
        ),
    className="six columns"),
    html.Div(
    dcc.Graph(
        id = 'graph-prof',
    ),
    className="six columns"),
    dcc.Store(id='store', data={"shapes[0].x0": 0, "shapes[0].y0": 250, 
                                "shapes[0].x1": 100, "shapes[0].y1": 250})
])

@app.callback(
    Output('store', 'data'),
    [Input('graph-im', 'relayoutData')],
    [State('store', 'data')],
    )
def display_relayout_data(relayoutData, coords):
    if not relayoutData:
        return dash.no_update
    else:
        coords.update(relayoutData)
        return coords


@app.callback(
    Output('graph-prof', 'figure'),
    [Input('store', 'data')])
def plot_profile(coords):
    if not coords:
        return dash.no_update
    else:
        rr, cc = draw.line(int(coords["shapes[0].x0"]),
                       int(coords["shapes[0].y0"]),
                       int(coords["shapes[0].x1"]),
                       int(coords["shapes[0].y1"])
            )
        val = img[cc, rr]
        fig = go.Figure()
        colors = ['red', 'green', 'blue']
        fig = go.Figure()
        for i, color in enumerate(colors):
            fig.add_trace(go.Scatter(y=val[:, i], mode='lines', name=color, line_color=color))
        fig.update_layout(title_text='Intensity profile')
        return fig


if __name__ == '__main__':
    app.run_server(debug=True, port=8060)