|
15 | 15 | import pandas as pd |
16 | 16 | import pedpy |
17 | 17 | import plotly.graph_objects as go |
| 18 | +from matplotlib.patches import Circle |
| 19 | +from matplotlib.figure import Figure as MatplotlibFigure |
18 | 20 | from plotly.graph_objs import Figure, Scatter |
19 | 21 | from plotly.graph_objs.layout import Shape |
20 | 22 | from shapely import Polygon |
@@ -141,8 +143,6 @@ def _get_colormap( |
141 | 143 | ) |
142 | 144 |
|
143 | 145 | return [scatter_trace] |
144 | | - |
145 | | - |
146 | 146 | def _get_shapes_for_frame( |
147 | 147 | frame_data: pd.DataFrame, |
148 | 148 | min_value: float, |
@@ -444,3 +444,54 @@ def animate( |
444 | 444 | height=height, |
445 | 445 | title_note=title_note, |
446 | 446 | ) |
| 447 | +def plot_frame_fast( |
| 448 | + data_df: pd.DataFrame, |
| 449 | + area: pedpy.WalkableArea, |
| 450 | + frame_num: int, |
| 451 | + *, |
| 452 | + radius: float = 0.1, |
| 453 | + xlim: Tuple[float, float] | None = None, |
| 454 | + ylim: Tuple[float, float] | None = None, |
| 455 | +) -> MatplotlibFigure: |
| 456 | + """Render a single frame with matplotlib for fast inspection.""" |
| 457 | + frame_data = data_df[data_df["frame"] == frame_num].copy() |
| 458 | + frame_data["radius"] = radius |
| 459 | + min_value = float(data_df["motivation"].min()) |
| 460 | + max_value = float(data_df["motivation"].max()) |
| 461 | + |
| 462 | + fig, ax = plt.subplots(figsize=(7, 9), constrained_layout=True) |
| 463 | + x, y = area.polygon.exterior.xy |
| 464 | + ax.plot(np.array(x), np.array(y), color="black", linewidth=1.0) |
| 465 | + for inner in area.polygon.interiors: |
| 466 | + xi, yi = zip(*inner.coords[:]) |
| 467 | + ax.plot(np.array(xi), np.array(yi), color="black", linewidth=1.0) |
| 468 | + |
| 469 | + cmap = plt.cm.jet_r |
| 470 | + norm = plt.Normalize(vmin=min_value, vmax=max_value if max_value > min_value else min_value + 1.0) |
| 471 | + for row in frame_data.itertuples(): |
| 472 | + circle = Circle( |
| 473 | + (row.x, row.y), |
| 474 | + radius=row.radius, |
| 475 | + facecolor=cmap(norm(row.motivation)), |
| 476 | + edgecolor="none", |
| 477 | + ) |
| 478 | + ax.add_patch(circle) |
| 479 | + |
| 480 | + sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm) |
| 481 | + sm.set_array([]) |
| 482 | + fig.colorbar(sm, ax=ax, label="Motivation") |
| 483 | + minx, miny, maxx, maxy = area.bounds |
| 484 | + if xlim is None: |
| 485 | + xlim = (minx - 0.5, maxx + 0.5) |
| 486 | + if ylim is None: |
| 487 | + ylim = (miny - 0.5, maxy + 0.5) |
| 488 | + ax.set_xlim(*xlim) |
| 489 | + ax.set_ylim(*ylim) |
| 490 | + ax.set_aspect("equal") |
| 491 | + ax.set_xticks([]) |
| 492 | + ax.set_yticks([]) |
| 493 | + for spine in ax.spines.values(): |
| 494 | + spine.set_visible(False) |
| 495 | + ax.set_xlabel("") |
| 496 | + ax.set_ylabel("") |
| 497 | + return fig |
0 commit comments