0

Currently I have this code:

fig= go.Figure()
for idx in range(len(reference)):
    df = reference.loc[idx]
    if df.ObjClass != 0:
        x,y = df.Polygon.exterior.xy
        fig.add_trace(go.Scatter(x=np.array(x), y=np.array(y)))
return fig

The the plot is for boudning boxes using polygons. Moste likely not the most efficient, open for improvements there as well.

My question is how to add an animation to and existing Plotly figure? In my df I have a time column that would be suitable for that (df.Time). When the animation is added in, I only want to plot the polygons for that timestamp.

Current plot without animation

EDIT: Adding Data struct

So this does not work when plotting, as I explain in my comment below. However if I change to sorting by ObjID instead of Time, it does work but the animation frame is not sorted. I want the lowest time to be first and highest at the end.

ObjClass    Time    ObjID   Corner  Lat Long
0   3.0 5.9 54.0    RR  21.549906   129.418088
563 3.0 5.9 54.0    LR  23.569243   129.523022
1126    3.0 5.9 54.0    LF  23.569243   136.523022
1689    3.0 5.9 54.0    RF  21.549906   136.418088
1   3.0 5.95    54.0    RR  17.946687   114.856340
564 3.0 5.95    54.0    LR  19.726662   114.919184
1127    3.0 5.95    54.0    LF  19.726662   121.919184
1690    3.0 5.95    54.0    RF  17.946687   121.856340
2   3.0 6.0 54.0    RR  17.685873   121.115523
565 3.0 6.0 54.0    LR  19.556310   121.182149
1128    3.0 6.0 54.0    LF  19.556310   128.182149
1691    3.0 6.0 54.0    RF  17.685873   128.115523
3   3.0 6.05    54.0    RR  17.685873   121.115523
566 3.0 6.05    54.0    LR  19.556310   121.182149
1129    3.0 6.05    54.0    LF  19.556310   128.182149
1692    3.0 6.05    54.0    RF  17.685873   128.115523
4   3.0 6.1 54.0    RR  17.375609   127.925362
567 3.0 6.1 54.0    LR  19.322351   127.848100
1130    3.0 6.1 54.0    LF  19.322351   134.848100
1693    3.0 6.1 54.0    RF  17.375609   134.925362

1 Answer 1

1

You have not provided sample data. Implicitly you are defined a data frame

Polygon ObjectId ObjClass time
POLYGON ((58 91, 58 77, 0 73, -0 87, 58 91)) 0 1 00:00
POLYGON ((51 102, 58 90, 7 62, 0 74, 51 102)) 0 1 01:00
POLYGON ((40 110, 52 101, 18 54, 6 63, 40 110)) 0 1 02:00

This has assumed an additional column ObjectId that is the same polygon which has different coordinates for each time

Simplest way to create a plotly animated figure is use Plotly Express. Hence restructure data to be x and y sequences in a long dataframe

import io
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
import shapely.wkt


df_p = pd.read_csv(io.StringIO("""Polygon,ObjectId,ObjClass,time
"POLYGON ((58 91, 58 77, 0 73, -0 87, 58 91))",0,1,00:00
"POLYGON ((51 102, 58 90, 7 62, 0 74, 51 102))",0,1,01:00
"POLYGON ((40 110, 52 101, 18 54, 6 63, 40 110))",0,1,02:00
"POLYGON ((28 112, 41 109, 30 52, 17 55, 28 112))",0,1,03:00
"POLYGON ((32 29, 20 33, 38 93, 50 89, 32 29))",1,1,00:00
"POLYGON ((45 31, 34 29, 25 91, 36 93, 45 31))",1,1,01:00
"POLYGON ((57 38, 47 32, 13 84, 23 90, 57 38))",1,1,02:00
"POLYGON ((65 50, 58 39, 5 72, 12 83, 65 50))",1,1,03:00
"POLYGON ((1 90, 7 90, 12 48, 6 48, 1 90))",2,1,00:00
"POLYGON ((-7 85, -2 89, 20 53, 15 49, -7 85))",2,1,01:00
"POLYGON ((-13 78, -10 83, 26 60, 23 55, -13 78))",2,1,02:00
"POLYGON ((-15 69, -14 75, 28 69, 27 63, -15 69))",2,1,03:00
"POLYGON ((59 12, 49 18, 84 92, 94 86, 59 12))",3,1,00:00
"POLYGON ((77 11, 65 11, 66 93, 78 93, 77 11))",3,1,01:00
"POLYGON ((94 17, 83 12, 49 87, 60 92, 94 17))",3,1,02:00
"POLYGON ((107 30, 99 21, 36 74, 44 83, 107 30))",3,1,03:00
"POLYGON ((9 29, 3 37, 13 43, 19 35, 9 29))",4,1,00:00
"POLYGON ((12 28, 4 34, 10 44, 18 38, 12 28))",4,1,01:00
"POLYGON ((15 29, 5 31, 7 43, 17 41, 15 29))",4,1,02:00
"POLYGON ((17 32, 8 29, 5 40, 14 43, 17 32))",4,1,03:00"""))

df_p["Polygon"] = df_p["Polygon"].apply(shapely.wkt.loads)

# explode out ploygons to x & y for plotly express
df_plot = (
    df_p["Polygon"]
    .apply(
        lambda p: [{"x": x, "y": y} for x, y in zip(p.exterior.xy[0], p.exterior.xy[1])]
    )
    .explode()
    .apply(pd.Series)
    .join(df_p)
)


px.line(df_plot, x="x", y="y", color="ObjectId", animation_frame="time")

enter image description here

using sample data

import pandas as pd
import io
import plotly.express as px

df = pd.read_csv(
    io.StringIO(
        """ObjClass    Time    ObjID   Corner  Lat Long
0   3.0 5.9 54.0    RR  21.549906   129.418088
563 3.0 5.9 54.0    LR  23.569243   129.523022
1126    3.0 5.9 54.0    LF  23.569243   136.523022
1689    3.0 5.9 54.0    RF  21.549906   136.418088
1   3.0 5.95    54.0    RR  17.946687   114.856340
564 3.0 5.95    54.0    LR  19.726662   114.919184
1127    3.0 5.95    54.0    LF  19.726662   121.919184
1690    3.0 5.95    54.0    RF  17.946687   121.856340
2   3.0 6.0 54.0    RR  17.685873   121.115523
565 3.0 6.0 54.0    LR  19.556310   121.182149
1128    3.0 6.0 54.0    LF  19.556310   128.182149
1691    3.0 6.0 54.0    RF  17.685873   128.115523
3   3.0 6.05    54.0    RR  17.685873   121.115523
566 3.0 6.05    54.0    LR  19.556310   121.182149
1129    3.0 6.05    54.0    LF  19.556310   128.182149
1692    3.0 6.05    54.0    RF  17.685873   128.115523
4   3.0 6.1 54.0    RR  17.375609   127.925362
567 3.0 6.1 54.0    LR  19.322351   127.848100
1130    3.0 6.1 54.0    LF  19.322351   134.848100
1693    3.0 6.1 54.0    RF  17.375609   134.925362"""
    ),
    sep="\s+",
    engine="python",
)

# if polygon is a quadrangle, need five points to define it. 4 is just a linestring
# duplicate first corner
df = pd.concat([df, df.loc[df["Corner"].eq("RR")].assign(Corner="RR2")])

# need to sort by Corner, hence make it a categorical
df["Corner"] = pd.Categorical(
    df["Corner"], ["RR", "RF", "LF", "LR", "RR2"], ordered=True
)

px.line(
    df.sort_values(["ObjID", "Time", "Corner"]),
    x="Long",
    y="Lat",
    color="ObjID",
    animation_frame="Time",
).update_layout(
    xaxis={"range": [df["Long"].min(), df["Long"].max()]},
    yaxis={"range": [df["Lat"].min(), df["Lat"].max()]},
)
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you so much for your answer! Help med out a lot! However now I have a new problem. Using your example I restructured my dataframe to a long format with "Lat" and "Long" columns. However it seems very picky on how I sort my data. If I sort by "ObjID" it work but the timeline is all messed up. If I sort by "Time" instead, the timeline is OK but then it only plots one of the objects per time value, even though there are multiple.
you have not shared your data structure so I had to infer it. It looks like you have a data frame with polygons where each polygon has an ObjId that is constant through time / transformations. hence that's how I structured sample data. update your question with head(10) of your dataframe and I'll update. This is why all SO guidelines on asking questions stress need to share sample data. Don't do the horrible thing of sharing your data as an image forcing any answerer to use unreliable OCR to use it
Added my data structure above. Looks a bit horrible but I hopefully you can copy it without too much hassle.
updated answer - you completely threw me with sample code using shapely. It appears your sample code and sample data are unrelated
Hehe that is because I changed up my Shapely Polygon approach to closer match your answer. The original data does include Polygon objects, but I dropped those when trying to adapt my df to your example.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.