Example 4: A ciw Model

Note that this example is written using ciw 2.x

It will not run with 3.x - but could theoretically be adapted to do so

The ‘logs’ object is the result of running

sim_engine.get_all_records()

However, note that while we run multiple replications, we only pass the records for a single replication to the event_log_from_ciw_recs function.


The underlying model code is from Monks, T., Harper, A., & Heather, A. (2023). Towards Sharing Tools, Artefacts, and Reproducible Simulation: a ciw model example (v1.0.1). Zenodo. https://doi.org/10.5281/zenodo.10051494

See here for the adaptation embedded within that repo: https://github.com/Bergam0t/ciw-example-animation/tree/main


import pandas as pd
# Import the wrapper objects for model interaction.
from examples.example_4_ciw.ex_4_ciw_model import Experiment, multiple_replications
from vidigi.utils import event_log_from_ciw_recs
from vidigi.animation import animate_activity_log
N_OPERATORS = 13
N_NURSES = 9
RESULTS_COLLECTION_PERIOD = 1000

user_experiment = Experiment(n_operators=N_OPERATORS,
                             n_nurses=N_NURSES,
                             chance_callback=0.4)

# run multiple replications
results, logs = multiple_replications(user_experiment, n_reps=10)

# the 'logs' object contains a list, where each entry is the recs object for that run
logs_run_1 = logs[0]

print(len(logs_run_1))
2266
# let's print all of the outputs for a single individual
[print(log) for log in logs_run_1 if log.id_number==500]

# let's now try turning this into an event log
event_log_test = event_log_from_ciw_recs(logs_run_1, node_name_list=["operator", "nurse"])

event_log_test.head(25)
Record(id_number=500, customer_class=0, original_customer_class=0, node=1, arrival_date=269.6165843237451, waiting_time=14.514495676004913, service_start_date=284.13107999975, service_time=8.289105946048721, service_end_date=292.4201859457987, time_blocked=0.0, exit_date=292.4201859457987, destination=-1, queue_size_at_arrival=37, queue_size_at_departure=43, server_id=1, record_type='service')
patient pathway event_type event time resource_id
0 1 Model arrival_departure arrival 0.503707 NaN
1 1 Model queue operator_wait_begins 0.503707 NaN
2 1 Model resource_use operator_begins 0.503707 1.0
3 1 Model resource_use operator_ends 6.136387 1.0
4 1 Model queue nurse_wait_begins 6.136387 NaN
5 1 Model resource_use nurse_begins 6.136387 1.0
6 1 Model resource_use nurse_ends 23.061561 1.0
7 1 Model arrival_departure depart 23.061561 NaN
8 2 Model arrival_departure arrival 1.048958 NaN
9 2 Model queue operator_wait_begins 1.048958 NaN
10 2 Model resource_use operator_begins 1.048958 2.0
11 2 Model resource_use operator_ends 8.075635 2.0
12 2 Model arrival_departure depart 8.075635 NaN
13 3 Model arrival_departure arrival 1.392097 NaN
14 3 Model queue operator_wait_begins 1.392097 NaN
15 3 Model resource_use operator_begins 1.392097 3.0
16 3 Model resource_use operator_ends 8.482409 3.0
17 3 Model queue nurse_wait_begins 8.482409 NaN
18 3 Model resource_use nurse_begins 8.482409 2.0
19 3 Model resource_use nurse_ends 19.488025 2.0
20 3 Model arrival_departure depart 19.488025 NaN
21 4 Model arrival_departure arrival 2.280472 NaN
22 4 Model queue operator_wait_begins 2.280472 NaN
23 4 Model resource_use operator_begins 2.280472 4.0
24 4 Model resource_use operator_ends 10.076369 4.0
# Create required event_position_df for vidigi animation
event_position_df = pd.DataFrame([
                    {'event': 'arrival',
                     'x':  30, 'y': 350,
                     'label': "Arrival"},

                    {'event': 'operator_wait_begins',
                     'x':  205, 'y': 270,
                     'label': "Waiting for Operator"},

                    {'event': 'operator_begins',
                     'x':  210, 'y': 210,
                     'resource':'n_operators',
                     'label': "Speaking to operator"},

                    {'event': 'nurse_wait_begins',
                     'x':  205, 'y': 110,
                     'label': "Waiting for Nurse"},

                    {'event': 'nurse_begins',
                     'x':  210, 'y': 50,
                     'resource':'n_nurses',
                     'label': "Speaking to Nurse"},

                    {'event': 'exit',
                     'x':  270, 'y': 10,
                     'label': "Exit"}

                ])
# Create a suitable class to pass in the resource numbers
class model_params():
    n_operators = N_OPERATORS
    n_nurses = N_NURSES
# Create animation
animate_activity_log(
        event_log=event_log_test,
        event_position_df= event_position_df,
        scenario=model_params(),
        debug_mode=True,
        setup_mode=False,
        every_x_time_units=1,
        include_play_button=True,
        icon_and_text_size=20,
        gap_between_entities=8,
        gap_between_rows=25,
        plotly_height=700,
        frame_duration=200,
        plotly_width=1200,
        override_x_max=300,
        override_y_max=300,
        limit_duration=RESULTS_COLLECTION_PERIOD,
        wrap_queues_at=25,
        step_snapshot_max=75,
        time_display_units="dhm",
        display_stage_labels=True,
    )
Animation function called at 18:07:36
Iteration through minute-by-minute logs complete 18:07:40
Snapshot df concatenation complete at 18:07:40
Reshaped animation dataframe finished construction at 18:07:40
Placement dataframe finished construction at 18:07:40
Output animation generation complete at 18:07:44
Total Time Elapsed: 7.97 seconds
Unable to display output for mime type(s): application/vnd.plotly.v1+json