animation.animate_activity_log

animation.animate_activity_log(
    event_log,
    event_position_df,
    scenario=None,
    time_col_name='time',
    entity_col_name='entity_id',
    event_type_col_name='event_type',
    event_col_name='event',
    pathway_col_name=None,
    resource_col_name='resource_id',
    simulation_time_unit='minutes',
    every_x_time_units=10,
    wrap_queues_at=20,
    wrap_resources_at=20,
    step_snapshot_max=60,
    step_snapshot_max_overrides=None,
    limit_duration=None,
    plotly_height=900,
    plotly_width=None,
    include_play_button=True,
    add_background_image=None,
    display_stage_labels=True,
    entity_icon_size=24,
    text_size=24,
    resource_icon_size=24,
    hover_text_entity='default',
    custom_hover_data=None,
    gap_between_entities=10,
    gap_between_queue_rows=30,
    gap_between_resource_rows=30,
    gap_between_resources=10,
    queue_direction='left',
    flip_entity_icons=False,
    entity_icon_font=None,
    entity_icon_font_weight=None,
    resource_icon_font=None,
    resource_icon_font_weight=None,
    entity_colour_by=None,
    entity_colour_map=None,
    show_entity_legend=True,
    entity_annotation_by=None,
    entity_annotation_size=14,
    entity_annotation_color='black',
    entity_annotation_offset_y=-15,
    resource_image_size=None,
    entity_resource_offset_y=-10,
    resource_opacity=0.8,
    custom_resource_icon=None,
    override_x_max=None,
    override_y_max=None,
    start_date=None,
    start_time=None,
    time_display_units=None,
    setup_mode=False,
    frame_duration=400,
    frame_transition_duration=600,
    debug_mode=False,
    custom_entity_icon_list=None,
    debug_write_intermediate_objects=False,
    background_image_opacity=0.5,
    overflow_text_color='black',
    stage_label_text_colour='black',
    stage_label_offset=10,
    plot_bgcolor=None,
    paper_bgcolor=None,
    backend='express',
    step_snapshot_limit_gauges=False,
    gauge_segments=10,
    gauge_max_override=None,
    step_snapshot_reveal_pop_in=False,
    spawn_in_from_arrival=True,
    run_number=None,
    run_col_name='auto',
    warm_up=0,
    snapshot_alignment='warm_up',
)

Generate an animated visualization of patient flow through a system.

This function processes event log data, adds positional information, and creates an interactive Plotly animation representing patient movement through various stages.

Parameters

Name Type Description Default
event_log pd.DataFrame, EventLogger, or TrialLogger The log of events to be animated, containing patient activities. A vidigi.logging.EventLogger or TrialLogger may be passed directly, in which case its .to_dataframe() is called for you. required
event_position_df pd.DataFrame DataFrame specifying the positions of different events, with columns ‘event’, ‘x’, and ‘y’ (plus optional ‘label’, ‘resource’, ‘direction’ - see queue_direction - ‘flip_icons’ - see flip_entity_icons - and ‘resource_icon’, which overrides custom_resource_icon per event and can name an image instead of a text glyph - see EventPosition). required
scenario object or dict Object whose attributes - or dict whose keys - give the number of each resource available at a step, e.g. scenario.n_nurses or scenario={"n_nurses": 2} (default is None). Used for two independent things: - Drawing the resource-availability icons at each stage. This also needs a resource column on event_position_df naming the attribute or key to read for that step (e.g. resource="n_nurses"). If an event declares a resource but no scenario is passed, a warning is raised and those icons are skipped. - Appending the resource identifier column (resource_col_name, “resource_id” by default) to the hover customdata, so a custom hover_text_entity template can display it. This happens only when the event log actually contains that column, i.e. the model logged resource use via log_resource_use_start / log_resource_use_end. The built-in default template does not reference it, and a scenario passed for a model with no resource-use logging is harmless - the column is simply not appended. None
time_col_name str Name of the column in event_log that contains the timestamp of each event. Timestamps should represent the number of time units since the simulation began. "time"
entity_col_name str Name of the column in event_log that contains the unique identifier for each entity (e.g., “entity_id”, “entity”, “patient”, “patient_id”, “customer”, “ID”). "entity_id"
event_type_col_name str Name of the column in event_log that specifies the category of the event. Supported event types include ‘arrival_departure’, ‘resource_use’, ‘resource_use_end’, and ‘queue’. "event_type"
event_col_name str Name of the column in event_log that specifies the actual event that occurred. "event"
pathway_col_name str Name of the column in event_log that identifies the specific pathway or process flow the entity is following. If None, it is assumed that pathway information is not present. None
resource_col_name str Name of the column for the resource identifier. Used for ‘resource_use’ events. "resource_id"
simulation_time_unit SimulationTimeUnit Time unit used within the simulation (default is minutes). Possible values are ‘seconds’, ‘minutes’, ‘hours’, ‘days’, ‘weeks’, ‘years’ 'minutes'
every_x_time_units int Time interval between animation frames in minutes (default is 10). 10
wrap_queues_at int Maximum number of entities to display in a queue before wrapping to a new row (default is 20). 20
wrap_resources_at int Number of resources to show before wrapping to a new row (default is 20). 20
step_snapshot_max int Maximum number of patients to show in each snapshot per event (default is 60). Any entities beyond this are collapsed into a + n more label (or a gauge, see step_snapshot_limit_gauges). Acts as the fallback for any event not named in step_snapshot_max_overrides. 60
step_snapshot_max_overrides dict A mapping of event name to a per-event step_snapshot_max, e.g. {"waiting_for_bed": 250} to show a long bottleneck queue in full while keeping every other step capped at step_snapshot_max. Any event not listed uses the scalar step_snapshot_max. Default None. A key that matches no event in the log raises a warning. None
limit_duration int The time at which the animation stops (default is None, which auto-adjusts to the maximum time in the provided event log). Together with warm_up this bounds the animation window. None
plotly_height int Height of the Plotly figure in pixels (default is 900). 900
plotly_width int Width of the Plotly figure in pixels (default is None, which auto-adjusts). None
include_play_button bool Whether to include a play button in the animation (default is True). True
add_background_image str Path to a background image file to add to the animation (default is None). None
display_stage_labels bool Whether to display labels for each stage (default is True). True
entity_icon_size int Size of entity icons in the animation (default is 24). 24
text_size int Size of text labels in the animation (default is 24). 24
resource_icon_size int Size of resource icons in the animation (default is 24). 24
hover_text_entity str | None String to define the hover text. If None, hover on entity icons will be disabled. Default will display the entity ID, their current time in the system, etc. Must be provided in the format “%{some_column_name} some text” etc. See https://plotly.com/python/hover-text-and-formatting/#customizing-hover-text-with-a-hovertemplate for full details. All columns present in the initial dataframe are available to access by referencing their name in the format “%{some_column_name}” 'default'
custom_hover_data list[str] | None A list of column names, which must be defined as strings. If provided, becomes a list of additional columns that can be accessed as part of the string defined within hover_text_entity. customdata[0] is the first column specified, customdata[1] is the second, etc. So e.g. if you pass in [“widgets_created_cumulative”] as your custom_hover_data, your hover_text_entity may be “Widgets created so far: %{customdata[0]}”. When scenario is set and the event log has a resource_col_name column, that column is appended to the list automatically, landing at customdata[len(custom_hover_data)]. Because custom_hover_data replaces the fixed column list the default hover_text_entity template indexes, you must also pass your own hover_text_entity string - supplying custom_hover_data while leaving hover_text_entity at its default raises ValueError. None
gap_between_entities int Horizontal spacing between entities in pixels (default is 10). 10
gap_between_queue_rows int Vertical spacing between rows in pixels (default is 30). 30
gap_between_resource_rows int Vertical spacing between rows in pixels (default is 30). 30
gap_between_resources int Horizontal spacing between resources in pixels (default is 10). 10
queue_direction (left, right) Which way queues (and rows of resources) build out from their anchor. “left” (the default, and byte-identical to previous versions) makes the anchor the front of the queue, with entities stacking up to its left. “right” mirrors this - the anchor becomes the bottom-left corner and the queue extends rightwards, which reads better with entity emojis that face right. Stage labels move to the opposite side of a right-building queue. Set this per event instead with a direction column on event_position_df (or EventPosition(..., direction=...)), which overrides the animation-wide value. "left"
flip_entity_icons bool Mirror entity icons (and a custom_resource_icon) horizontally - useful when an emoji faces the wrong way for a particular layout, independently of queue_direction. Set this per event instead with a flip_icons column on event_position_df (or EventPosition(..., flip_icons=...)), which overrides the animation-wide value. Requires CSS to reach the page - this is injected automatically (see vidigi.utils.inject_icon_flip_css) whenever any icon actually resolves to flipped; embedding the figure a different way may need vidigi.utils.entity_icon_flip_css() added explicitly. Does not affect a static export via fig.write_image(). False
entity_icon_font str Render entity icons in an icon font instead of emoji, so an icon can be any glyph the font provides - one of vidigi.utils.ICON_FONT_PRESETS ("font-awesome", "bootstrap-icons", "material-symbols"), or any CSS font-family name already available on the page. custom_entity_icon_list then supplies that font’s codepoints instead of emoji. Resource glyphs have their own resource_icon_font. See generate_animation’s docstring for the overflow-icon exemption and vidigi.utils.entity_icon_font_css for what reaching the page involves; the CSS is injected automatically, as for flip_entity_icons. None
entity_icon_font_weight int Overrides a preset’s default weight. Ignored for a raw custom family. None
resource_icon_font str Render glyph resource icons (custom_resource_icon, and any text-glyph resource_icon) in an icon font, independently of entity_icon_font - each side can be in its own font, or one left on emoji. Same accepted values and automatic CSS injection; the codepoint goes straight into custom_resource_icon / resource_icon. Animation-wide. See generate_animation’s docstring for detail. None
resource_icon_font_weight int Overrides a preset’s default weight for resource_icon_font. None
entity_colour_by str Name of a column - typically one already on your event log - to colour entity icons by. Only visible together with entity_icon_font, since emoji are colour fonts and ignore textfont.color entirely. None
entity_colour_map dict Maps values of entity_colour_by to specific colours; an uncovered value falls back to Plotly’s default qualitative palette. None
show_entity_legend bool Show a legend for entity_colour_by. Ignored when it is not set. True
entity_annotation_by str Name of a column to draw as offset text below each entity’s icon - e.g. a running length-of-stay figure. Express backend only. See generate_animation’s docstring for the full trade-off against appending text directly onto icon yourself: prefer appending when flip_entity_icons/entity_icon_font aren’t in play, and reach for this only once they are. None
entity_annotation_size int Font size (in points) of the entity_annotation_by text. 14
entity_annotation_color str Colour of the entity_annotation_by text. "black"
entity_annotation_offset_y float Vertical offset, in data units, of entity_annotation_by text below (negative) or above (positive) each entity’s icon. -15
resource_image_size float Size, in data units, of an image resource_icon (see EventPosition.resource_icon). Defaults to resource_icon_size, kept independent of gap_between_resources so changing the spacing between resources doesn’t also change their size. None
entity_resource_offset_y float Vertical offset, in data units, of each resource icon relative to the entity using it - negative below (the historic default), positive above. Applies to the default dot, a glyph custom_resource_icon / resource_icon, and an image resource_icon alike. -10
resource_opacity float Opacity of resource icons (default is 0.8). 0.8
custom_resource_icon str Custom icon to use for resources (default is None). None
override_x_max int Override the maximum x-coordinate of the plot (default is None). The figure margin already auto-expands to fit auto-generated stage labels, so this is only needed to reframe a layout the auto-sizing gets wrong. The axis then runs exactly [0, override_x_max]; a UserWarning is raised if any event anchor falls outside that, as its queue / resources would be drawn off-canvas. None
override_y_max int Override the maximum y-coordinate of the plot (default is None). Same off-canvas UserWarning as override_x_max. None
start_date str Start date for the animation in ‘YYYY-MM-DD’ format. Only used when time_display_units is ‘d’ or ‘dhm’ (default is None). None
start_time str Start time for the animation in ‘HH:MM:SS’ format. Only used when time_display_units is ‘d’ or ‘dhm’ (default is None). None
time_display_units str Format for displaying time on the animation timeline. This affects how simulation time is converted into human-readable dates or clock formats. If None (default), the raw simulation time is used. Predefined options: - ‘dhms’ : Day Month Year + HH:MM:SS (e.g., “06 June 2025 14:23:45”) - ‘dhms_ampm’ : Same as ‘dhms’, but in 12-hour format with AM/PM (e.g., “06 June 2025 02:23:45 PM”) - ‘dhm’ : Day Month Year + HH:MM (e.g., “06 June 2025 14:23”) - ‘dhm_ampm’ : 12-hour format with AM/PM - (e.g., “06 June 2025 02:23 PM”) - ‘dh’ : Day Month Year + HH (e.g., “06 June 2025 14”) - ‘dh_ampm’ : 12-hour format with AM/PM (e.g., “06 June 2025 02 PM”) - ‘d’ : Full weekday and date (e.g., “Friday 06 June 2025”) - ‘m’ : Month and year (e.g., “June 2025”) - ‘y’ : Year only (e.g., “2025”) - ‘day_clock’ or ‘simulation_day_clock’ : Show simulation-relative day and time (e.g., “Simulation Day 3 14:15”) - ‘day_clock_ampm’ or ‘simulation_day_clock_ampm’ : Same as above, but time is shown in 12-hour clock with AM/PM (e.g., “Simulation Day 3 02:15 PM”) Alternatively, you can supply a custom strftime (https://strftime.org/) format string (e.g., ‘%Y-%m-%d %H’) to control the display manually. None
setup_mode bool If True, display grid and tick marks for initial setup (default is False). False
frame_duration int Duration of each frame in milliseconds (default is 400). 400
frame_transition_duration int Duration of transition between frames in milliseconds (default is 600). 600
debug_mode bool If True, print debug information during processing (default is False). False
custom_entity_icon_list list[str] | None If given, overrides the default list of emojis used to represent entities None
debug_write_intermediate_objects bool If True, writes intermediate data objects (for example, the reshaped event log and positional dataframe) to CSV files in the current working directory. False
background_image_opacity float Opacity (0 is transparent, to 1, completely opaque) of the provided background image 0.5
overflow_text_color str Color of the text displayed on top of entity icons in the animation (default is black). 'black'
stage_label_text_colour str Color of the stage label text added next to each event position when display_stage_labels is True (default is black). 'black'
stage_label_offset float Gap, in data units, between a stage label and the front of its queue/resources (the event anchor point) when display_stage_labels is True (default is 10). Increase this for larger icon sizes so labels don’t crowd the icons. 10
plot_bgcolor str Background colour of the plotting area (inside the axes), passed straight to fig.update_layout(plot_bgcolor=...). Accepts any CSS colour string, e.g. “white” or “#f5f5f5”. If None (default), Plotly’s template default is left untouched. None
paper_bgcolor str Background colour of the area surrounding the plotting area (behind the title, play button and timeline), passed straight to fig.update_layout(paper_bgcolor=...). Accepts any CSS colour string. If None (default), Plotly’s template default is left untouched. None
backend AnimationBackend EXPERIMENTAL. Whether to use the plotly express backend for the initial plot (default), or the experimental plotly go backend. The go approach is currently unstable and much slower. Use at your own risk. 'express'
step_snapshot_limit_gauges bool If True, replaces the text ‘+ x more’ with a gauge. The upper limit of the gauge is set by the maximum queue length observed across the simulation. False
gauge_segments int Number of discrete segments used when rendering queue length gauges in the animation. Higher values give a finer-grained visual indication of queue length, while lower values produce chunkier segments. 10
gauge_max_override int | float Manually specified maximum value for queue length gauges. If None, the upper limit is determined from the maximum queue length observed in the simulation when step_snapshot_limit_gauges is True. None
step_snapshot_reveal_pop_in bool If True, an entity that re-appears as an individually-drawn icon after being hidden by step_snapshot_max “pops in” at its queue position instead of visibly flying in from the top-left of the plot. See generate_animation_df’s docstring for the full mechanism and cost. The default False is a verified no-op; planned to change to True at the next major version (3.0). False
spawn_in_from_arrival bool When True (the default), a genuinely new entity glides into the animation from the event_position_df anchor named "arrival" instead of flying in from the plot’s top-left corner - the arrival-side mirror of how the synthetic depart step makes an exit land at a chosen anchor. Only affects entities that arrive at least two snapshots after the animation window opens; an entity already present when it opens keeps the top-left fly-in, as does a layout with no "arrival" row in event_position_df. Pass False to restore the pre-2.0.0 top-left fly-in. Independent of step_snapshot_reveal_pop_in. See generate_animation_df’s docstring for the full mechanism. True
run_number int Selects a single replication from a TrialLogger passed as event_log. Only valid with a TrialLogger: passing it alongside a DataFrame or an EventLogger raises ValueError, as does passing a multi-run TrialLogger without it. None
run_col_name str or None Name of the column identifying which simulation run (replication) each row belongs to, used to reject event logs containing more than one replication. Default is “auto”, which looks for a column named (case-insensitively) one of ‘run’, ‘run_number’, ‘replication’, ‘rep’ or ‘run_id’. Pass an explicit column name to override the search, or None to disable the check. 'auto'
warm_up int The time at which the animation starts, in simulation time units (default is 0, the beginning of the run). Not to be confused with start_time above, which is a time of day used only for labelling frames as clock times. This is how to discard a warm-up period. Pass the whole event log and set warm_up to the end of your warm-up; do not filter the log by time first. Filtering removes the ‘arrival’ rows of every entity that arrived during the warm-up, and since presence is worked out from arrival and departure rows, those entities then vanish from every frame - including ones still queuing, which is exactly what a steady-state animation is meant to show. warm_up trims the window while leaving that history intact. 0
snapshot_alignment (warm_up, run_start) Which point the snapshot grid counts from when warm_up is non-zero. Ignored when warm_up is 0. - “warm_up” (default): the first frame lands exactly on the boundary, showing the state of the system as the warm-up ends. - “run_start”: frame times stay on the grid running from time 0 and the early ones are dropped, so they remain the same times you would get with no warm-up at all. The two are identical whenever warm_up is a multiple of every_x_time_units. "warm_up"

Returns

Name Type Description
plotly.graph_objs._figure.Figure An animated Plotly figure object representing the patient flow.

Notes

  • Pass a single replication only. An event log containing more than one run is rejected with a ValueError. Passing several runs does not raise on its own - it silently blends them into an animation that represents no run of your model - so this is checked before any work is done. Filter first, e.g. event_log[event_log["run"] == 1].
  • This function uses helper functions: reshape_for_animations, generate_animation_df, and generate_animation.
  • The animation supports customization of icon sizes, resource representation, and animation speed.
  • Time can be displayed as actual dates or as model time units.
  • A background image can be added to provide context for the patient flow.
  • The function handles both queuing and resource use events.
Back to top