Black Lives Matter. Please consider donating to Black Girls Code today.

Artifacts in plotly animation frames

Hi!
I am using Plotly animations to visualize data from a dataframe (I am not using plotly express --> see code below).


I have around 1500 frames with some points and lines for each frame.
When I use the redraw = True option, everything is fine but the runtime of each frame is far to high. When I use the redraw = False method, performance is fine but I get random artifacts in the plot. Does someone have a solution for this problem.

My code looks like that:

    # setup figure, slider, buttons etc.
    fig_dict = {"data": [], "layout": {}, "frames": []}
    fig_dict["layout"]["xaxis"] = {"title": "x distance", 'range': [-100, 150]}
    fig_dict["layout"]["yaxis"] = {"title": "y distance", "scaleanchor": "x", 'range': [-50, 50]}
    fig_dict["layout"]["hovermode"] = "closest"
    fig_dict["layout"]["height"] = 800
    fig_dict['layout']['template'] = 'plotly_white'

    fig_dict["layout"]["updatemenus"] = [{"buttons": [{"args": [None, {"frame": {"duration": 150, "redraw": False}, "fromcurrent": True}],
                                    "label": "Play", "method": "animate"}, {"args": [[None], {"frame": {"duration": 100, "redraw": True}, "mode": "immediate"}],
                                    "label": "Pause", "method": "animate"}], "direction": "left", "pad": {"r": 10, "t": 87}, "showactive": False, "type": "buttons", "x": 0.1, "xanchor": "right",
                                    "y": 0, "yanchor": "top"}]

    sliders_dict = {"active": 0, "yanchor": "top", "xanchor": "left", "currentvalue": {"font": {"size": 20}, "prefix": "time (s):", "visible": True, "xanchor": "right"},
                    "pad": {"b": 10, "t": 50}, "len": 0.9, "x": 0.1, "y": 0, "steps": []}

    # initial frame
    fig_dict["data"].append(self.get_ego_vehicle_shape_data_dict())

    sensors_in_rec = sorted(pd.unique(df[["sensor"]].values.ravel()))
    column_names = df.columns.values

    for sensor in sensors_in_rec:
        print(sensor)
        data_dict = {'x': [0], 'y': [0], "mode": "lines+markers", "name": sensor}
        fig_dict["data"].append(data_dict)

    print("Overview contains " + str(len(times)) + " frames")

    for t in times:

        frame = {"data": [], "name": t}
        frame["data"].append(self.get_ego_vehicle_shape_data_dict())

        for sensor in sensors_in_rec:

            x_values, y_values, id_values, markersize, hoverinfo = [], [], [], [], []

            relevant_row_in_df = df[(df.times == t) & (df.sensor == sensor)].sort_values(by=['unique_id'])
            for index, row in relevant_row_in_df.iterrows():

                if not row['VALID']: continue  # jump over invalid entries

                # if valid append put the data for the ref point
                x_values.append(round(row["pX"], 3))
                y_values.append(round(row["pY"], 3))
                hoverinfo.append('text')
                markersize.append(7)
                id_values.append(self.get_hover_info(row, column_names))  # information on hover

                # calculate points of vehicle
                x_values, y_values = self._calc_drawing_points(row, sensor, x_values, y_values)
                id_values.extend(7*[None])
                markersize.extend(7*[0])
                hoverinfo.extend(7*['none'])

            if not x_values and not y_values:
                x_values, y_values = [0], [0]  # make sure at least one value is ploted, otherwise the legend will vanish

            data_dict = {'x': x_values, 'y': y_values, "mode": "lines+markers", "name": sensor, "text": id_values, "connectgaps": False, "marker": {'size': markersize}, "hoverinfo": hoverinfo}
            frame["data"].append(data_dict)

        fig_dict["frames"].append(frame)
        slider_step = {"args": [[t], {"frame": {"duration": 20, "redraw": False}, "mode": "immediate", "transition": {"duration": 0}}], "label": t, "method": "animate"}
        sliders_dict["steps"].append(slider_step)

    fig_dict["layout"]["sliders"] = [sliders_dict]
    starttime2 = time.time()
    fig = go.Figure(fig_dict)