Step 2. Set up simulation parameters

A very simple example with one server - avoiding the vidigi logger class

If you would prefer to implement your own approach to logging, you can avoid the use of the EventLogger class, and instead manually build your event logs, as shown in this example.

Step 1. Import required libraries

  • vidigi
  • simpy - for simulation model (or see the Ciw functions and examples elsewhere in this documentation)
  • random - for generating random arrivals
  • pandas - for managing dataframes
import simpy
import pandas as pd
import random
from vidigi.animation import animate_activity_log
from vidigi.utils import EventPosition, create_event_position_df
# Simple simulation parameters
SIM_DURATION = 50
NUM_SERVERS = 1
ARRIVAL_RATE = 1.0
SERVICE_TIME = 3.0

Step 3. Write model code with event logs

Create a simple simulation model using simpy.

On the left is a basic simpy model. If not familiar check out simpy documentation for intro to simpy.

On the right is how we incorporate vidigi. Information for vidigi collected in a list of dictionaries which we will convert into a dataframe. You need a arrival_departure event.

Simple SimPy Model
def patient_generator(env, server, event_log):
    """Generate patients arriving at the shop"""
    patient_id = 0

    while True:
        patient_id += 1

        # Start the patient process
        env.process(patient_process(env, patient_id, server, event_log))

        # Wait for next arrival
        yield env.timeout(random.expovariate(ARRIVAL_RATE))

def patient_process(env, patient_id, server, event_log):
    """Process a single patient through the system"""

    # Request server
    with server.request() as request:
        yield request

        # Service time
        service_duration = random.expovariate(1.0/SERVICE_TIME)
        yield env.timeout(service_duration)

# Run the simulation
def run_simulation():
    env = simpy.Environment()
    server = simpy.Resource(env, capacity=NUM_SERVERS)
    event_log = []

    # Start patient generator
    env.process(patient_generator(env, server, event_log))

    # Run simulation
    env.run(until=SIM_DURATION)
With Vidigi Modifications
def patient_generator(env, server, event_log):
    """Generate patients arriving at the shop"""
    patient_id = 0

    while True:
        patient_id += 1

        # Log arrival
        event_log.append({ 
            'patient': patient_id, 
            'event': 'arrival', 
            'event_type': 'arrival_departure',  
            'time': env.now 
        }) 

        # Start the patient process
        env.process(patient_process(env, patient_id, server, event_log))

        # Wait for next arrival
        yield env.timeout(random.expovariate(ARRIVAL_RATE))

def patient_process(env, patient_id, server, event_log):
    """Process a single patient through the system"""

    # Log start of queue wait 
    event_log.append({ 
        'patient': patient_id, 
        'event': 'queue_wait_begins', 
        'event_type': 'queue', 
        'time': env.now 
    }) 

    # Request server
    with server.request() as request:
        yield request

        # Log service start
        event_log.append({ 
            'patient': patient_id, 
            'event': 'service_begins', 
            'event_type': 'resource_use', 
            'time': env.now, 
            'resource_id': 1 
        }) 

        # Service time
        service_duration = random.expovariate(1.0/SERVICE_TIME)
        yield env.timeout(service_duration)

        # Log service end 
        event_log.append({ 
            'patient': patient_id, 
            'event': 'service_complete', 
            'event_type': 'resource_use_end', 
            'time': env.now, 
            'resource_id': 1 
        }) 

    # Log departure 
    event_log.append({ 
        'patient': patient_id, 
        'event': 'depart', 
        'event_type': 'arrival_departure', 
        'time': env.now 
    }) 

# Run the simulation
def run_simulation():
    env = simpy.Environment()
    server = simpy.Resource(env, capacity=NUM_SERVERS)
    event_log = []

    # Start patient generator
    env.process(patient_generator(env, server, event_log))

    # Run simulation
    env.run(until=SIM_DURATION)

    return pd.DataFrame(event_log) 

Step 4. Run simulation

# Run simulation and get event log
event_log_df = run_simulation()
print(f"Generated {len(event_log_df)} events")
Generated 125 events

Step 5. Create event positions dataframe

# Define positions for animation
event_positions = create_event_position_df([
    EventPosition(event='arrival', x=0, y=350, label="Entrance"),
    EventPosition(event='queue_wait_begins', x=250, y=250, label="Queue"),
    EventPosition(event='service_begins', x=250, y=150, resource='server', label="Being Served"),
    EventPosition(event='depart', x=250, y=50, label="Exit")
])

Step 6. Create animation

Explaining:

  • plotly_height and plotly_width
  • override_x_max and override_y_max
  • setup_mode
  • every_x_time_units
# Create animation
animate_activity_log(
    event_log=event_log_df,
    event_position_df=event_positions,
    entity_col_name="patient",
    every_x_time_units=1,
    plotly_height=600,
    override_x_max=360,
    limit_duration=SIM_DURATION
)