animation.generate_animation
animation.generate_animation(
full_entity_df_plus_pos,
event_position_df,
scenario=None,
time_col_name='time',
entity_col_name='entity_id',
event_col_name='event',
event_type_col_name='event_type',
resource_col_name='resource_id',
simulation_time_unit='minutes',
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,
hover_text_entity='default',
custom_hover_data=None,
resource_icon_size=24,
override_x_max=None,
override_y_max=None,
time_display_units=None,
start_date=None,
start_time=None,
resource_opacity=0.8,
custom_resource_icon=None,
wrap_resources_at=20,
gap_between_resources=10,
gap_between_resource_rows=30,
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,
setup_mode=False,
frame_duration=400,
frame_transition_duration=600,
debug_mode=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',
run_col_name='auto',
)Generate an animated visualization of patient flow through a system.
This function creates an interactive Plotly animation based on patient data and event positions.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| full_entity_df_plus_pos | pd.DataFrame | DataFrame containing entity data with position information. This will be the output of passing an event log through the reshape_for_animations() and generate_animation_df() functions. | required |
| event_position_df | pd.DataFrame | DataFrame specifying the positions of different events. | 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 (default is “time”). 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”) (default is “entity_id”). |
'entity_id' |
| event_col_name | str | Name of the column in event_log that specifies the actual event that occurred (default is “event”). |
'event' |
| event_type_col_name | str | Name of the column in event_log that specifies the category of the event (default is “event_type”). Supported event types include ‘arrival_departure’, ‘resource_use’, ‘resource_use_end’, and ‘queue’. |
'event_type' |
| resource_col_name | str | Name of the column for the resource identifier (default is “resource_id”). 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' |
| 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). | 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 |
| 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 “%{customdata[0]} some text” etc. See https://plotly.com/python/hover-text-and-formatting/#customizing-hover-text-with-a-hovertemplate for full details. It is recommended you pair this with custom_hover_data to have control over the order of column names present in the customdata list. | '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 |
| resource_icon_size | int | Size of resource icons in the animation (default is 24). | 24 |
| override_x_max | int | Override the maximum x-coordinate (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 (default is None). Same off-canvas UserWarning as override_x_max. |
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 |
| 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 |
| 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 |
| wrap_resources_at | int | Number of resources to show before wrapping to a new row (default is 20). If this has been set elsewhere, it is also important to set it in this function to ensure the visual indicators of the resources wrap in the same way the entities using those resources do. | 20 |
| gap_between_resources | int | Spacing between resources in pixels (default is 10). | 10 |
| gap_between_resource_rows | int | Vertical spacing between rows in pixels (default is 30). | 30 |
| queue_direction | (left, right) | Which way queues (and rows of resources) build out from their anchor. “left” is the historic behaviour - the anchor is the front of the queue and entities stack up to its left. “right” mirrors this, so the anchor becomes the bottom-left corner and the queue extends rightwards, which suits entity emojis that face right. Stage labels flip to the opposite side of a right-building queue. If set here it must also be set on generate_animation_df; overridden per event by a direction column on event_position_df. |
"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. Overridden per event by a flip_icons column on event_position_df (or EventPosition(..., flip_icons=...)). 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 - lets an icon be any glyph the font provides, and, because icon fonts are monochrome rather than colour fonts, is what makes entity_colour_by visible on the icon itself. One of vidigi.utils.ICON_FONT_PRESETS (currently "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 (or, for "material-symbols", ligature names like "directions_walk") instead of emoji. The overflow + N more / ASCII-gauge icon is always left on the default font, whatever this is set to - seeing tofu or a substituted glyph in place of ASCII art would be worse than the plain text. See vidigi.utils.entity_icon_font_css for what reaching the page involves and two Plotly quirks it works around; like flip_entity_icons, the CSS is injected automatically. Applies to entity icons only - resource glyphs have their own resource_icon_font. |
None |
| entity_icon_font_weight | int | Overrides a preset’s default weight (Font Awesome ships Solid at 900 and Regular at 400, say). Ignored for a raw custom family in entity_icon_font - most fonts have only one. |
None |
| resource_icon_font | str | Render glyph resource icons - a custom_resource_icon, and any per-event resource_icon that is a text glyph rather than an image - in an icon font instead of emoji. Independent of entity_icon_font: entities and resources can each be in their own font, or one in an icon font and the other left on emoji. Same accepted values (a vidigi.utils.ICON_FONT_PRESETS name or a raw CSS family), same automatic CSS injection. The codepoint or ligature goes straight into custom_resource_icon / resource_icon - there is no list argument like custom_entity_icon_list. Animation-wide, like entity_icon_font: every glyph resource stage shares it (the resource glyphs are a single trace), so there is no per-stage font. An image resource_icon is unaffected. Default None leaves glyph resource icons on the page default font. |
None |
| resource_icon_font_weight | int | Overrides a preset’s default weight for resource_icon_font, as entity_icon_font_weight does for entity_icon_font. |
None |
| entity_colour_by | str | Name of a column - typically one already on your event log, such as priority or pathway - to colour entity icons by by. Unlike emoji, which are colour fonts and ignore textfont.color entirely, this only has a visible effect together with entity_icon_font. Overflow rows keep overflow_text_color and are never coloured or added to the legend, whatever category they would otherwise fall into. |
None |
| entity_colour_map | dict | Maps values of entity_colour_by to specific colours, e.g. {"high": "crimson", "low": "steelblue"}. A value with no entry falls back to Plotly’s default qualitative palette. |
None |
| show_entity_legend | bool | Show a legend for entity_colour_by. Ignored when entity_colour_by is not set - there is nothing to key. |
True |
| entity_annotation_by | str | Name of a column to draw as a second line of text offset below each entity’s icon - e.g. a running length-of-stay figure or a delay flag. Express backend only (see backend). Appending extra text directly onto icon/icon_display is cheaper and is what vidigi has always drawn - prefer it whenever flip_entity_icons/entity_icon_font aren’t in play for this animation. It stops working once either of those is combined with baked-in text, though: Plotly gives a single SVG <text> node one font-family and one transform, so flipping or re-fonting the icon does the same to any text appended into the same string. entity_annotation_by draws the annotation as a genuinely separate scatter trace instead, so it is structurally untouched by either - at the cost of roughly doubling the per-frame point/text payload for every entity, for the whole animation. None (default) draws no second trace at all. Raises ValueError if the column isn’t found, matching entity_colour_by. |
None |
| entity_annotation_size | int | Font size (in points) of the entity_annotation_by text. Independent of entity_icon_size. |
14 |
| entity_annotation_color | str | Colour of the entity_annotation_by text. Independent of entity_colour_by/overflow_text_color. |
"black" |
| entity_annotation_offset_y | float | Vertical offset, in data units (the same units as event_position_df’s x/y), of entity_annotation_by text below (negative) or above (positive) each entity’s icon. Given its own literal default rather than derived from an unrelated spacing argument - check it against your entity_icon_size if icons and annotations start to overlap. |
-15 |
| resource_image_size | float | Size, in data units (the same units as event_position_df’s x/y), 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. Has no effect on a text glyph resource icon, which is sized by resource_icon_size as before. |
None |
| entity_resource_offset_y | float | Vertical offset, in data units (the same units as event_position_df’s x/y), of each resource icon relative to the entity using it - negative sits the icon below the entity (the historic default), positive above. Applies to all three resource-icon forms (the default dot, a glyph custom_resource_icon / resource_icon, and an image resource_icon). Use it to lift an entity clear of a large resource_image_size, or to sit it down onto the icon. |
-10 |
| setup_mode | bool | Whether to run in setup mode, showing grid and tick marks (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 | Whether to run in debug mode with additional output (default is False). | 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' |
| run_col_name | str or None | Name of the column identifying which simulation run (replication) each row belongs to, used to reject data 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' |
Returns
| Name | Type | Description |
|---|---|---|
| plotly.graph_objs._figure.Figure | An animated Plotly figure object representing the patient flow. |
Notes
- This function animates a single replication only. Data containing more than one run is rejected with a
ValueError, because the runs would otherwise be blended into an animation representing no run of your model. - The function uses Plotly Express to create an animated scatter plot.
- Time can be displayed as actual dates or as model time units.
- The animation supports customization of icon sizes, resource representation, and animation speed.
- A background image can be added to provide context for the patient flow.
- If
time_display_unitsis specified, the simulation time is converted into real-world datetimes using thesimulation_time_unitand optionallystart_dateandstart_time. - If
start_dateand/orstart_timeare not provided, a default offset from today’s date is used. - The
snapshot_timecolumn is transformed to datetime strings, and asnapshot_time_displaycolumn is created for visual display.