How to reproduce a plotly.express timeline, BUT using only graph_objects

Hello there !

I use anvil works (a web app dev framework using python) to create a vehicle rental management app.

I created a gantt chart to visualize the bookings.
In the current state of anvil, i can only use plotly.express in anvil’s servers code, create the gantt chart (using plotly.express timeline) in the server, and send it to the client code to render it in the UI.

Instead of this, i would like to directly create the gantt chart in the client code, instead of doing it in the server code.
It is indeed possible, but not with plotly.express as this package is not available in the skulpt environment, which is the base of anvil client side code.
Only the graphic_objects package can be used in the client side code.

I’ve read that any plotly.express method could be reproduced with graph_objects, but after a few hours trying, i can’t figure out how to.

Here is my plotly.express code :

def _plot_planning():
    bookings = GLOBAL_VAR.bookings
    tzstr = GLOBAL_VAR.timezone_str
    # ================================
    data = []
    for booking in bookings:
        vehicle = GLOBAL_VAR.vehicles[booking["vehicle_id"]]
        starting = booking['starting'].astimezone(ZoneInfo(tzstr))
        ending = booking['ending'].astimezone(ZoneInfo(tzstr))
        data.append({
            'id': f"{vehicle[immatriculation]}",
            'starting': starting.strftime("%Y-%m-%d %H:%M"),
            'ending': ending.strftime("%Y-%m-%d %H:%M"),
            'status': booking['status'],
        })
    df = pd.DataFrame(data)
    df = df.sort_values(by='id')
    fig = px.timeline(df, x_start="starting", x_end="ending", y="id", color="status", custom_data="status")
    # ================================
    fig.update_traces(
        hovertemplate='<b>%{y}</b> <br><b>Status:</b> %{customdata} <br><b>Départ:</b> %{base|%d/%m %Hh%M} <br><b>Retour:</b> %{x|%d/%m %Hh%M}<extra></extra>', # <b>Status:</b> %{customdata} <br>,
        opacity=0.8,
        marker=dict(
            line_color="#1D1D1D",
            line_width=1
        ),
    )
    fig.update_xaxes(
        automargin='bottom',
        ticks="outside",
        side='bottom',
        tickmode='linear',
        tickformat="%-d",
        type='date',
        ticklabelmode='period',
        ticklabelposition='outside',
        tickcolor="darkgrey",
        ticklen=0,
        title_text = "",
        title_standoff = 0,
        showgrid=True,
        showline=True,
        range=my_range,
        mirror=True,
        linecolor='darkgrey',
        gridcolor='darkgrey',
        #constrain="domain",
        autorange=False,
        fixedrange=True,
    )
    fig.update_layout(
        #modebar_color,
        #modebar_activecolor,
        modebar_remove=['select', 'lasso2d', 'zoom'],
        modebar_add=['toImage', 'drawline', 'drawopenpath', 'drawclosedpath', 'drawcircle', 'drawrect', 'eraseshape'],
        modebar_orientation='v',
        legend=dict(
            orientation="h",
            tracegroupgap=0,
        ),
        bargap=0,
        #barcornerradius=12,
        #plot_bgcolor='white',
        template='seaborn',
        legend_title_text='',
        margin=dict(
            autoexpand=True,
            l=0,
            r=30,
            b=10,
            t=0,
            pad=0
        ),
        font_family="Montserrat",
        font_size=14,
        dragmode='pan',
    )
    fig.update_yaxes(
        autorange="reversed",
        automargin='left',
        title_text = "",
        title_standoff = 0,
        showgrid=True,
        showline=True,
        mirror=True,
        tickson='boundaries',
        ticklen=20,
        ticks='outside',
        tickcolor="darkgrey",
        linecolor='darkgrey',
        gridcolor='darkgrey',
        fixedrange=True,
    )
    return fig # fig sent to the client side code

So… If anyone knows how to reproduce this code with plotly graph_objects only, any help would be greatly appreciated !

It’s probably worth looking at the plotly express code base on Github here

The definition of px.timelines is in _chart_types.py around line 400

This calls make_figure, defined in _core.py. If you search through this file you can see that it uses go.bar (~line 2100), and the args conversion is done in the process_dataframe_timeline function around line 1750.

1 Like

Well, thank you i didn’t even knew where to find the source.

As first i thought i would simply copy the source code in modules in my app, but hell there are other packages and modules required that are also not implemented in the skulpt environment.

So my next guess will be to try to mimic the approach in the make figure function as much as i can using only the go.bar method.

1 Like