plots.plot_warm_up_diagnostic
plots.plot_warm_up_diagnostic(
event_log,
*,
series='queue',
event=None,
first_event=None,
second_event=None,
method='welch',
windows=(5, 10, 20),
every_x_time_units=1,
limit_duration=None,
show_ensemble=True,
show_runs=False,
**col_kwargs,
)Plot a Welch (or cumulative-mean) diagnostic for choosing warm_up=.
Ensemble-averages a per-run series across replications, then smooths it (see vidigi.analysis.welch_moving_average) so the point at which the curve stops drifting - the visual signal a modeller reads off to pick warm_up= for the other analysis functions in this module - is legible.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| event_log | pandas.DataFrame | Long-format event log spanning one or more runs. | required |
| series | (queue, occupancy, duration) | What per-run series to diagnose: - "queue": queue length at regular snapshots, from vidigi.analysis.queue_size_over_time. Requires event= naming the queue’s event. - "occupancy": resource occupancy at regular snapshots, from vidigi.analysis.resource_occupancy_over_time. Requires event= naming the resource step. - "duration": per-entity durations in arrival order, from vidigi.analysis.event_durations. Requires first_event= and second_event=. There is no time axis for this series - the x-axis is the entity’s position in arrival order, not simulated time, so a cutoff read off this plot is an entity count, not a time. Apply it via event_durations’s own warm_up= (a pairing is excluded by when it started, i.e. first_time) - note this is a genuinely different truncation rule from warm_up= on the other two series, which censor/clip a bout rather than exclude an atomic observation by its start time. See vidigi.analysis.event_durations’s warm_up parameter. |
"queue" |
| event | str | The queue’s or resource step’s event name. Required, and only used, for series="queue"/"occupancy". |
None |
| first_event | str | The two events to pair. Required, and only used, for series="duration". |
None |
| second_event | str | The two events to pair. Required, and only used, for series="duration". |
None |
| method | (welch, cumulative, none) | Smoothing procedure - see vidigi.analysis.welch_moving_average. "welch" overlays one curve per entry in windows; "cumulative" and "none" each draw a single curve and ignore windows. "cumulative" is the “time series inspection” technique the DES RAP book demonstrates (Heather et al., 2026 - https://pythonhealthdatascience.github.io/des_rap_book/pages/guide/output_analysis/length_warmup.html); "none" is the raw ensemble average with no smoothing at all - a further step beyond that, not itself what the DES RAP book shows. "none" is drawn the same way show_ensemble’s reference line would be, so show_ensemble is a no-op under it to avoid drawing the identical line twice. |
"welch" |
| windows | sequence of int | Window half-widths to overlay when method="welch". More smoothing (a larger window) gives a shorter usable curve - see vidigi.analysis.welch_moving_average. |
(5, 10, 20) |
| every_x_time_units | float | Snapshot granularity. Only used for series="queue"/"occupancy". |
1 |
| limit_duration | float | End of the window snapshots are taken over. None (default) uses the latest time seen anywhere in the trial. Only used for series="queue"/"occupancy". |
None |
| show_ensemble | bool | If True, also draws the raw (unsmoothed) ensemble-average series as a thin dotted line, for comparison against the smoothed curve(s). Ignored when method="none" - see method above. |
True |
| show_runs | bool | If True, also draws every individual replication’s own raw series - the same idea as the DES RAP book’s own per-replication traces (though those plot each run’s cumulative mean, matching method="cumulative" above, rather than the fully raw series drawn here), and useful with any method for seeing how much cross-replication spread the smoothing/pooling is hiding. Drawn at opacity=0.2 under one shared legend entry (“individual runs”) rather than one entry per run, since with a realistic replication count a full per-run legend would swamp the windows=/ method entries that are the actual point of this plot - unlike plot_queue_size/plot_resource_utilisation_over_time, which plot one series at a time and so can afford to label each run. Drawn at each run’s own full length, not truncated to the shortest run the way the summary trace(s) are. |
False |
| **col_kwargs | dict | Column-name keyword arguments forwarded to whichever underlying vidigi.analysis function series selects (queue_size_over_time/resource_occupancy_over_time/ event_durations) - e.g. run_col_name=, or match= for series="duration". |
{} |
Returns
| Name | Type | Description |
|---|---|---|
| plotly.graph_objects.Figure |
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | If series is not one of the three supported values; if the event= (for series="queue"/"occupancy") or first_event=/second_event= (for series="duration") the chosen series requires is missing, or an argument for a different series is given; or (series="occupancy") if event names a step that never occurred. |
Notes
There is deliberately no automatic warm-up-length selector - see vidigi.analysis.welch_moving_average.
See Also
vidigi.analysis.welch_moving_average : The underlying smoothing procedure.
Examples
>>> plot_warm_up_diagnostic(trial.to_dataframe(), series="queue", event="waiting")
<plotly.graph_objs._figure.Figure>