Select Git revision
eventlog.py 7.86 KiB
import pandas as pd
import simplesimmodel as model
import numpy as np
from collections import OrderedDict
import simpy
from pm4py.objects.log.exporter.xes import exporter as xes_exporter
from pm4py.objects.log.importer.xes import importer as xes_importer
from pm4py.objects.log.obj import EventLog
from pm4py.objects.log.obj import Trace
from pm4py.objects.log.obj import Event
import os
"""
Event log generator for our simulation model:
- generate an event log
- update an event log (adding new events)
- export event log
- get current state of an event log
"""
def add_start_event(process, event_id, case_id, activity, start_timestamp):
process.event_log.append(event_id)
process.event_log[event_id] = {
'CaseID': case_id,
'Activity': activity,
'StartTimestamp': float(start_timestamp),
'EndTimestamp': None
}
process.event_counter += 1
def add_end_event(process, event_id, end_timestamp):
event = process.event_log[event_id]
event['EndTimestamp'] = end_timestamp
def export_to_csv(process, file_path):
event_log_df = pd.DataFrame.from_dict(process.event_log)
event_log_df.to_csv(file_path, index=False)
def export_to_xes(process, file_path):
event_log = process.event_log
# Create an empty event log object
event_log_obj = EventLog()
# Iterate over each event in the event log
for event_data in event_log:
# Create a new trace
trace = Trace()
# Create a new event
event = Event()
# Set the attributes of the event based on the dictionary values
event['Activity'] = event_data['Activity']
event['StartTimestamp'] = event_data['StartTimestamp']
event['EndTimestamp'] = event_data['EndTimestamp']
event['CaseID'] = event_data['CaseID']
# Add the event to the trace
trace.append(event)
# Add the trace to the event log
event_log_obj.append(trace)
# Export the event log to XES format
xes_exporter.apply(event_log_obj, file_path)
def convert_to_dataframe(name):
file_path = r"Frontend/upload/" + name
# print(path)
file_extension = os.path.splitext(file_path)[1].lower()
if file_extension == '.csv':
event_log_df = pd.read_csv(file_path)
elif file_extension == '.xes':
# Read the XES file
event_log = xes_importer.apply(file_path)
# Extract the event attributes and create a list of dictionaries
event_data = []
for trace in event_log:
for event in trace:
event_data.append(event)
# Create a pandas DataFrame from the event data
event_log_df = pd.DataFrame(event_data)
else:
print(f"Unsupported file type: {file_extension}")
# print(event_log_df)
return event_log_df
def get_active_cases(name):
event_log_df = convert_to_dataframe(name)
active_cases = event_log_df.groupby('CaseID').filter(lambda x: 'order completed' not in x['Activity'].values)['CaseID'].unique().tolist()
print(active_cases)
return active_cases
def get_state(case_id,name):
process = np.zeros(13, dtype=int)
num_s = 1
process[0] = num_s
num_ot = 4
process[1] = num_ot
num_sh_a = 2
process[2] = num_sh_a
num_sh_b = 2
process[3] = num_sh_b
num_sh_c = 2
process[4] = num_sh_c
num_m_a = 4
process[5] = num_m_a
num_m_b = 10
process[6] = num_m_b
num_p_a = 2
process[7] = num_p_a
num_p_b = 3
process[8] = num_p_b
num_p_c = 3
process[9] = num_p_c
num_ds_a = 25
process[10] = num_ds_a
num_ds_b = 40
process[11] = num_ds_b
num_ds_c = 45
process[12] = num_ds_c
case = np.zeros(15, dtype=int)
activity_mapping = {
'place order': 1,
'arrange standard order': 2,
'arrange custom order': 3,
'pick from stock A': 4,
'pick from stock B': 5,
'pick from stock C': 6,
'manufacture A': 7,
'manufacture B': 8,
'pack A': 9,
'pack B': 10,
'pack C': 11,
'attempt delivery A': 12,
'attempt delivery B': 13,
'attempt delivery C': 14,
'order completed': 15,
}
event_log = convert_to_dataframe(name)
# Sort the event log by case ID and start timestamp
event_log.sort_values(by=['CaseID', 'StartTimestamp'], inplace=True)
# Group the event log by case ID and get the last activity for each case
last_activities = event_log.groupby('CaseID').tail(1).reset_index()
# Remap the activity names to numbers using the mapping dictionary
last_activities['Activity'] = last_activities['Activity'].map(activity_mapping)
# Filter the cases where the end timestamp of the last activity is None or empty
unfinished_cases = last_activities[last_activities['EndTimestamp'].isnull()]['CaseID'].tolist()
# Update the state of the ressources given all unfinished cases
for i in unfinished_cases:
activity = last_activities[last_activities['CaseID'] == i]['Activity'].values[0]
if activity == 1 or activity == 15:
process[0] -= 1
elif activity == 2 or activity == 3:
process[1] -= 1
else:
process[activity-2] -= 1
# Get the state of the case for the given Case ID
filtered_log = event_log[event_log['CaseID'] == case_id]
activities = filtered_log['Activity'].map(activity_mapping).tolist()
for i in activities:
case[i-1] += 1
# Get the last event for the given Case ID
event = last_activities[last_activities['CaseID'] == case_id]['Activity'].values[0]
"""
state = {
'process': process,
'case': case,
'event': event
}
"""
state = OrderedDict()
state['case'] = case
state['event'] = event
state['process'] = process
# print(state)
return state
# connect with frontend!!!
def generate_event_log(time):
ressources = []
num_s = 1
ressources.append(num_s+1)
num_ot = 4
ressources.append(num_ot+1)
num_sh_a = 2
ressources.append(num_sh_a+1)
num_sh_b = 2
ressources.append(num_sh_b+1)
num_sh_c = 2
ressources.append(num_sh_c+1)
num_m_a = 4
ressources.append(num_m_a+1)
num_m_b = 10
ressources.append(num_m_b+1)
num_p_a = 2
ressources.append(num_p_a+1)
num_p_b = 3
ressources.append(num_p_b+1)
num_p_c = 3
ressources.append(num_p_c+1)
num_ds_a = 25
ressources.append(num_ds_a+1)
num_ds_b = 40
ressources.append(num_ds_b+1)
num_ds_c = 45
ressources.append(num_ds_c+1)
# generate event log
env = simpy.Environment()
business_process = model.BusinessProcess(env, ressources)
business_process.event_log_flag = True
env.process(model.run_process(env, business_process))
env.run(until = time)
export_to_csv(business_process, r'Frontend/export/eventlog.csv')
export_to_xes(business_process, r'Frontend/export/eventlog.xes')
def show_active_cases(name):
activity_mapping = {
1: 'place order',
2: 'arrange standard order',
3: 'arrange custom order',
4: 'pick from stock A',
5: 'pick from stock B',
6: 'pick from stock C',
7: 'manufacture A',
8: 'manufacture B',
9: 'pack A',
10: 'pack B',
11: 'pack C',
12: 'attempt delivery A',
13: 'attempt delivery B',
14: 'attempt delivery C',
15: 'order completed',
}
caselist = get_active_cases(name)
reslist = []
for case in caselist:
state = get_state(case, name)
trace = []
events = state['case']
for i in range(len(events)):
if events[i] == 1:
trace.append(activity_mapping[i+1])
tup = (case, trace)
reslist.append(tup)
return reslist
def main():
# generate_event_log(10000)
print(get_state(5, "eventlog.csv"))
if __name__ == "__main__":
main()