def variant_to_trace(variant, parameters=None): if parameters is None: parameters = {} activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY) variant_delimiter = exec_utils.get_param_value( Parameters.PARAMETER_VARIANT_DELIMITER, parameters, constants.DEFAULT_VARIANT_SEP) from pm4py.objects.log.log import Trace, Event trace = Trace() if type(variant) is tuple or type(variant) is list: for act in variant: event = Event({activity_key: act}) trace.append(event) elif type(variant) is str: var_act = variant.split(variant_delimiter) for act in var_act: event = Event({activity_key: act}) trace.append(event) return trace
def create_log(G, conn_comp, timestamps, max_comp_len=50, include_loops=False): log = EventLog() for i in range(len(conn_comp)): if len(conn_comp[i]) <= max_comp_len: trace = Trace() trace.attributes["concept:name"] = str(i) SG = G.subgraph(conn_comp[i]) SGG = networkx.DiGraph(SG) edges = list(SGG.edges) for e in edges: if e[0] == e[1]: SGG.remove_edge(e[0], e[1]) sorted_nodes = list(networkx.topological_sort(SGG)) for n in sorted_nodes: selfloop = 1 if (n, n) in SG.edges else 0 trace.append( Event({ 'time:timestamp': timestamps[n.split("=")[1]], 'concept:name': n.split("=")[0], 'value': n.split("=")[1], 'typevalue': n, 'selfloop': selfloop })) if include_loops and selfloop: trace.append( Event({ 'time:timestamp': timestamps[n.split("=")[1]], 'concept:name': n.split("=")[0], 'value': n.split("=")[1], 'typevalue': n, 'selfloop': selfloop })) log.append(trace) log = sorting.sort_timestamp_log(log, "time:timestamp") return log
def apply(tree, no, prob, has_empty_trace=False): """ Returns non-fitting EventLog with fixed traces randomly created by the process tree. Parameters ----------- tree Process Tree no Number of traces that will be in the event log prob Randomness of the traces has_empty_trace True, when the event log has empty trace Returns ------------ EventLog Non-fitting event log """ log, non_fit_traces = generate_log(tree, no), list() label_num = pt_mani_utils.non_none_leaves_number(tree) traces = list(map(lambda t: t, log)) while len(traces) > 0: trace = traces.pop() non_fit_t = Trace(attributes=log.attributes) for event in trace: if random.random() < prob: index = random.randint(0, 2) if index == 1: # add a new event non_fit_t.append(event) new_event = Event() new_event[ xes.DEFAULT_NAME_KEY] = pt_gene_utils.get_cur_label( label_num + 1) non_fit_t.append(new_event) elif index == 2: # replace with other event new_event = Event() new_event[ xes.DEFAULT_NAME_KEY] = pt_gene_utils.get_cur_label( random.randint(1, label_num)) non_fit_t.append(new_event) else: non_fit_t.append(event) if not has_empty_trace and len(non_fit_t) == 0: traces.append(generate_log(tree, 1)[0]) else: non_fit_traces.append(non_fit_t) return EventLog(non_fit_traces, attributes=log.attributes, classifiers=log.classifiers, omni_present=log.omni_present, extensions=log.extensions)
def form_log_from_dictio_couple(first_cases_repr, second_cases_repr, enable_multiplier=False): """ Form a log from a couple of dictionary, to use for root cause analysis Parameters ------------- first_cases_repr First cases representation second_cases_repr Second cases representation enable_multiplier Enable balancing of classes Returns ------------ log Trace log object """ log = EventLog() if enable_multiplier: multiplier_first = int( max( float(len(second_cases_repr)) / float(len(first_cases_repr)), 1)) multiplier_second = int( max( float(len(first_cases_repr)) / float(len(second_cases_repr)), 1)) else: multiplier_first = 1 multiplier_second = 1 for j in range(multiplier_first): for i in range(len(first_cases_repr)): trace = Trace() event = Event(first_cases_repr[i]) trace.append(event) log.append(trace) for j in range(multiplier_second): for i in range(len(second_cases_repr)): trace = Trace() event = Event(second_cases_repr[i]) trace.append(event) log.append(trace) return log
def insert_missing_events(trace): obj_ids = set(x["obj_id"] for x in trace) for o in obj_ids: if o in Shared.associated_events: for ev in Shared.associated_events[o]: trace.append(Event(dict(ev))) return trace
def list_of_str_to_trace(activities: List[str]) -> Trace: t = Trace() for a in activities: e = Event() e["concept:name"] = a t.append(e) return t
def apply(df, parameters=None): """ Convert a dataframe into a log containing 1 case per variant (only control-flow perspective is considered) Parameters ------------- df Dataframe parameters Parameters of the algorithm Returns ------------- log Event log """ from pm4py.statistics.traces.pandas import case_statistics if parameters is None: parameters = {} variant_stats = case_statistics.get_variant_statistics(df, parameters=parameters) activity_key = parameters[ pm4_constants.PARAMETER_CONSTANT_ACTIVITY_KEY] if pm4_constants.PARAMETER_CONSTANT_ACTIVITY_KEY in parameters else xes.DEFAULT_NAME_KEY log = EventLog() for vd in variant_stats: variant = vd['variant'].split(",") trace = Trace() for activity in variant: event = Event() event[activity_key] = activity trace.append(event) log.append(trace) return log
def apply_tree_variants(variants, parameters=None): """ Apply the IM algorithm to a dictionary of variants obtaining a process tree Parameters ---------- variants Variants parameters Parameters of the algorithm, including: Parameters.ACTIVITY_KEY -> attribute of the log_skeleton to use as activity name (default concept:name) Returns ---------- process_tree Process tree """ log = EventLog() activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY) var_keys = list(variants.keys()) for var in var_keys: trace = Trace() activities = var.split(constants.DEFAULT_VARIANT_SEP) for act in activities: trace.append(Event({activity_key: act})) log.append(trace) return apply_tree(log, parameters=parameters)
def create_trace(labels: List[str]) -> Trace: trace = Trace() for label in labels: e = Event() e["concept:name"] = label trace.append(e) return trace
def generate_log(pt, no_traces=100): """ Generate a log out of a process tree Parameters ------------ pt Process tree no_traces Number of traces contained in the process tree Returns ------------ log Trace log object """ log = TraceLog() for i in range(no_traces): ex_seq = execute(pt) ex_seq_labels = pt_util.project_execution_sequence_to_labels(ex_seq) trace = Trace() trace.attributes[xes.DEFAULT_NAME_KEY] = str(i) for label in ex_seq_labels: event = Event() event[xes.DEFAULT_NAME_KEY] = label trace.append(event) log.append(trace) return log
def apply(df, parameters=None): """ Convert a dataframe into a log containing 1 case per variant (only control-flow perspective is considered) Parameters ------------- df Dataframe parameters Parameters of the algorithm Returns ------------- log Event log """ if parameters is None: parameters = {} variant_stats = case_statistics.get_variant_statistics( df, parameters=parameters) log = EventLog() for vd in variant_stats: variant = vd['variant'].split(",") trace = Trace() for activity in variant: event = Event() event[xes.DEFAULT_NAME_KEY] = activity trace.append(event) log.append(trace) return log
def apply(bytes, parameters=None): """ Apply the deserialization to the bytes produced by Pyarrow serialization Parameters -------------- bytes Bytes parameters Parameters of the algorithm Returns -------------- deser Deserialized object """ if parameters is None: parameters = {} buffer = pyarrow.py_buffer(bytes) list_objs = pyarrow.deserialize(buffer) log = EventLog(attributes=list_objs[0], extensions=list_objs[1], omni_present=list_objs[2], classifiers=list_objs[3]) for i in range(len(list_objs[4])): trace = Trace(attributes=list_objs[4][i]) for j in range(len(list_objs[5][i])): trace.append(Event(list_objs[5][i][j])) log.append(trace) return log
def apply_from_variants_list(var_list, parameters=None): """ Discovers the log skeleton from the variants list Parameters --------------- var_list Variants list parameters Parameters Returns --------------- model Log skeleton model """ if parameters is None: parameters = {} activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes.DEFAULT_NAME_KEY) variant_delimiter = exec_utils.get_param_value( Parameters.PARAMETER_VARIANT_DELIMITER, parameters, constants.DEFAULT_VARIANT_SEP) log = EventLog() for cv in var_list: v = cv[0] tr = v.split(variant_delimiter) trace = Trace() for act in tr: trace.append(Event({activity_key: act})) log.append(trace) return apply(log, parameters=parameters)
def apply(log, parameters=None): """ Converts the event log to an event stream Parameters ---------- log: :class:`pm4py.log.log.EventLog` An Event log include_case_attributes: Default is True case_attribute_prefix: Default is 'case:' enable_deepcopy Enables deepcopy (avoid references between input and output objects) Returns ------- log : :class:`pm4py.log.log.EventLog` An Event stream """ if parameters is None: parameters = {} stream_post_processing = exec_utils.get_param_value( Parameters.STREAM_POST_PROCESSING, parameters, False) case_pref = exec_utils.get_param_value(Parameters.CASE_ATTRIBUTE_PREFIX, parameters, 'case:') enable_deepcopy = exec_utils.get_param_value(Parameters.DEEP_COPY, parameters, True) include_case_attributes = exec_utils.get_param_value( Parameters.INCLUDE_CASE_ATTRIBUTES, parameters, True) compress = exec_utils.get_param_value(Parameters.COMPRESS, parameters, True) if pkgutil.find_loader("pandas"): import pandas if isinstance(log, pandas.DataFrame): extensions = __detect_extensions(log) list_events = pandas_utils.to_dict_records(log) if stream_post_processing: list_events = __postprocess_stream(list_events) if compress: list_events = __compress(list_events) for i in range(len(list_events)): list_events[i] = Event(list_events[i]) log = log_instance.EventStream(list_events, attributes={'origin': 'csv'}) for ex in extensions: log.extensions[ex.name] = { xes_constants.KEY_PREFIX: ex.prefix, xes_constants.KEY_URI: ex.uri } if isinstance(log, EventLog): return __transform_event_log_to_event_stream( log, include_case_attributes=include_case_attributes, case_attribute_prefix=case_pref, enable_deepcopy=enable_deepcopy) return log
def execute_script(): L = EventLog() e1 = Event() e1["concept:name"] = "A" e2 = Event() e2["concept:name"] = "B" e3 = Event() e3["concept:name"] = "C" e4 = Event() e4["concept:name"] = "D" t = Trace() t.append(e1) t.append(e2) t.append(e3) t.append(e4) for i in range(10000): L.append(deepcopy(t)) print(len(L))
def list_to_xes(log): traces = list() for t in log: trace = Trace() for e in t.split(", "): event = Event() event["concept:name"] = e trace.append(event) traces.append(trace) return EventLog(traces)
def create_event_log(log): traces = list() for events in log.split(", "): trace = Trace() for e in list(events): event = Event() event["concept:name"] = e trace.append(event) traces.append(trace) return EventLog(traces)
def apply(tree, parameters=None): """ Performs an extensive playout of the process tree Parameters ------------- tree Process tree parameters Possible parameters, including: - Parameters.MAX_TRACE_LENGTH => maximum length of a trace (default: min_allowed_trace_length) - Parameters.MAX_LOOP_OCC => maximum number of occurrences for a loop (default: MAX_TRACE_LENGTH) - Parameters.ACTIVITY_KEY => activity key - Parameters.MAX_LIMIT_NUM_TRACES => maximum number to the limit of traces; the playout shall stop when the number is reached (default: sys.maxsize) Returns ------------- log_skeleton Event log_skeleton """ if parameters is None: parameters = {} activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY) # to save memory in the returned log_skeleton, allocate each activity once. to know the list of activities of the # process tree, use the footprints module fp_tree = fp_discovery.apply(tree, parameters=parameters) activities = fp_tree["activities"] activities = {act: Event({activity_key: act}) for act in activities} min_allowed_trace_length = bottomup_discovery.get_min_trace_length(tree, parameters=parameters) max_trace_length = exec_utils.get_param_value(Parameters.MAX_TRACE_LENGTH, parameters, min_allowed_trace_length) max_loop_occ = exec_utils.get_param_value(Parameters.MAX_LOOP_OCC, parameters, int(max_trace_length/2)) max_limit_num_traces = exec_utils.get_param_value(Parameters.MAX_LIMIT_NUM_TRACES, parameters, 100000) return_set_strings = exec_utils.get_param_value(Parameters.RETURN_SET_STRINGS, parameters, False) bottomup = bottomup_discovery.get_bottomup_nodes(tree, parameters=parameters) min_rem_dict = bottomup_discovery.get_min_rem_dict(tree, parameters=parameters) playout_dictio = {} for i in range(len(bottomup)): get_playout(bottomup[i], playout_dictio, max_trace_length, max_loop_occ, min_rem_dict, max_limit_num_traces) tree_playout_traces = playout_dictio[tree][TRACES] if return_set_strings: return tree_playout_traces log = EventLog() for tr0 in tree_playout_traces: trace = Trace() for act in tr0: trace.append(activities[act]) log.append(trace) return log
def apply(df, parameters=None): """ Convert a dataframe into a log containing N case per variant (only control-flow perspective is considered) Parameters ------------- df Dataframe parameters Parameters of the algorithm Returns ------------- log Event log """ from pm4py.statistics.traces.pandas import case_statistics if parameters is None: parameters = {} return_variants = parameters[ RETURN_VARIANTS] if RETURN_VARIANTS in parameters else False case_glue = parameters[ pm4_constants. PARAMETER_CONSTANT_CASEID_KEY] if pm4_constants.PARAMETER_CONSTANT_CASEID_KEY in parameters else pm4_constants.CASE_CONCEPT_NAME activity_key = parameters[ pm4_constants. PARAMETER_CONSTANT_ACTIVITY_KEY] if pm4_constants.PARAMETER_CONSTANT_ACTIVITY_KEY in parameters else xes.DEFAULT_NAME_KEY variant_stats = case_statistics.get_variant_statistics( df, parameters=parameters) log = EventLog() all_variants_log = {} for vd in variant_stats: variant = vd['variant'].split(",") variant_count = vd[case_glue] trace = Trace() for activity in variant: event = Event() event[activity_key] = activity trace.append(event) all_variants_log[vd['variant']] = [] for i in range(variant_count): log.append(trace) all_variants_log[vd['variant']].append(len(log) - 1) if return_variants: return log, all_variants_log return log
def acyclic_net_variants(net, initial_marking, final_marking, activity_key=xes_util.DEFAULT_NAME_KEY): """ Given an acyclic accepting Petri net, initial and final marking extracts a set of variants (in form of traces) replayable on the net. Warning: this function is based on a marking exploration. If the accepting Petri net contains loops, the method will not work properly as it stops the search if a specific marking has already been encountered. Parameters ---------- :param net: An acyclic workflow net :param initial_marking: The initial marking of the net. :param final_marking: The final marking of the net. :param activity_key: activity key to use Returns ------- :return: variants: :class:`list` Set of variants - in the form of Trace objects - obtainable executing the net """ active = {(initial_marking, ())} visited = set() variants = set() while active: curr_marking, curr_partial_trace = active.pop() curr_pair = (curr_marking, curr_partial_trace) enabled_transitions = petri.semantics.enabled_transitions( net, curr_marking) for transition in enabled_transitions: if transition.label is not None: next_partial_trace = curr_partial_trace + (transition.label, ) else: next_partial_trace = curr_partial_trace next_marking = petri.semantics.execute(transition, net, curr_marking) next_pair = (next_marking, next_partial_trace) if next_marking == final_marking: variants.add(next_partial_trace) else: # If the next marking is not in visited, if the next marking+partial trace is different from the current one+partial trace if next_pair not in visited and curr_pair != next_pair: active.add(next_pair) visited.add(curr_pair) trace_variants = [] for variant in variants: trace = Trace() for activity_label in variant: trace.append(Event({activity_key: activity_label})) trace_variants.append(trace) return trace_variants
def preprocess_log(log, activities=None, parameters=None): """ Preprocess a log to enable correlation mining Parameters -------------- log Log object activities (if provided) list of activities of the log parameters Parameters of the algorithm Returns -------------- transf_stream Transformed stream activities_grouped Grouped activities activities List of activities of the log """ if parameters is None: parameters = {} activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY) timestamp_key = exec_utils.get_param_value(Parameters.TIMESTAMP_KEY, parameters, xes_constants.DEFAULT_TIMESTAMP_KEY) start_timestamp_key = exec_utils.get_param_value(Parameters.START_TIMESTAMP_KEY, parameters, xes_constants.DEFAULT_TIMESTAMP_KEY) index_key = exec_utils.get_param_value(Parameters.INDEX_KEY, parameters, DEFAULT_INDEX_KEY) if type(log) is pd.DataFrame: # keep only the two columns before conversion log = log[list(set([activity_key, timestamp_key, start_timestamp_key]))] log = converter.apply(log, variant=converter.TO_EVENT_STREAM, parameters=parameters) transf_stream = EventStream() for idx, ev in enumerate(log): transf_stream.append( Event({activity_key: ev[activity_key], timestamp_key: ev[timestamp_key].timestamp(), start_timestamp_key: ev[start_timestamp_key].timestamp(), index_key: idx})) transf_stream = sorted(transf_stream, key=lambda x: (x[start_timestamp_key], x[timestamp_key], x[index_key])) if activities is None: activities = sorted(list(set(x[activity_key] for x in transf_stream))) activities_grouped = {x: [y for y in transf_stream if y[activity_key] == x] for x in activities} return transf_stream, activities_grouped, activities
def generate_log(pt0, actdict, no_traces=100): """ Generate a log out of a process tree Parameters ------------ pt Process tree no_traces Number of traces contained in the process tree Returns ------------ log Trace log object """ pt = deepcopy(pt0) #for ele in pt: #print(ele,'here is line 50') # different taus must give different ID in log generation!!!! # so we cannot use the default process tree class # we use this different one! pt = GenerationTree(pt) log = EventLog() #print(pt,'line 56') # assigns to each event an increased timestamp from 1970 curr_timestamp = 10000000 for i in range(no_traces): ex_seq = execute(pt, actdict) #print(ex_seq,'ex_seq') ex_seq_labels = pt_util.project_execution_sequence_to_labels(ex_seq) #print(ex_seq_labels,'ex_seq_labels') trace = Trace() trace.attributes[xes.DEFAULT_NAME_KEY] = str(i) #print('line 67') for label in ex_seq_labels: event = Event() event[xes.DEFAULT_NAME_KEY] = label event[xes.DEFAULT_TIMESTAMP_KEY] = datetime.datetime.fromtimestamp( curr_timestamp) trace.append(event) #print(event,'line 73') curr_timestamp = curr_timestamp + 1 log.append(trace) return log
def apply_from_variant(variant, dfg, sa, ea, parameters=None): if parameters is None: parameters = {} activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY) variant_delimiter = exec_utils.get_param_value( Parameters.PARAMETER_VARIANT_DELIMITER, parameters, constants.DEFAULT_VARIANT_SEP) variant_split = variant.split( variant_delimiter) if type(variant) is str else variant trace = Trace() for act in variant_split: trace.append(Event({activity_key: act})) return apply_trace(trace, dfg, sa, ea, parameters=parameters)
def apply(log, parameters=None): """ Converts the event log to an event stream Parameters ---------- log: :class:`pm4py.log.log.EventLog` An Event log include_case_attributes: Default is True case_attribute_prefix: Default is 'case:' enable_deepcopy Enables deepcopy (avoid references between input and output objects) Returns ------- log : :class:`pm4py.log.log.EventLog` An Event stream """ if parameters is None: parameters = {} stream_post_processing = exec_utils.get_param_value( Parameters.STREAM_POST_PROCESSING, parameters, False) case_pref = exec_utils.get_param_value(Parameters.CASE_ATTRIBUTE_PREFIX, parameters, 'case:') enable_deepcopy = exec_utils.get_param_value(Parameters.DEEP_COPY, parameters, False) if isinstance(log, pandas.core.frame.DataFrame): list_events = log.to_dict('records') if stream_post_processing: list_events = __postprocess_stream(list_events) for i in range(len(list_events)): list_events[i] = Event(list_events[i]) log = log_instance.EventStream(list_events, attributes={'origin': 'csv'}) if isinstance(log, EventLog): return __transform_event_log_to_event_stream( log, include_case_attributes=True, case_attribute_prefix=case_pref, enable_deepcopy=enable_deepcopy) return log
def acyclic_net_variants(net, initial_marking, final_marking): """ Given an acyclic accepting Petri net, initial and final marking extracts a set of variants (in form of traces) replayable on the net. Warning: this function is based on a marking exploration. If the accepting Petri net contains loops, the method will not work properly as it stops the search if a specific marking has already been encountered. Parameters ---------- net: An acyclic workflow net initial_marking: The initial marking of the net. final_marking: The final marking of the net. Returns ------- variants: :class:`list` List of variants - in the form of Trace objects - obtainable executing the net """ active = [(initial_marking, Trace())] visited = [] variants = [] while active: curr_couple = active.pop(0) en_tr = petri.semantics.enabled_transitions(net, curr_couple[0]) for t in en_tr: next_activitylist = deepcopy(curr_couple[1]) if t.label is not None: next_activitylist.append(Event({'concept:name': repr(t)})) next_couple = (petri.semantics.execute(t, net, curr_couple[0]), next_activitylist) if hash(next_couple[0]) == hash(final_marking): variants.append(next_couple[1]) else: # If the next marking hash is not in visited, if the next marking+partial trace itself is # not already in active and if the next marking+partial trace is different from the # current one+partial trace if hash(next_couple[0]) not in visited and next( (mark for mark in active if hash(mark[0]) == hash( next_couple[0] and mark[1] == next_couple[1])), None) is None and ( hash(curr_couple[0]) != hash(next_couple[0]) or curr_couple[1] != next_couple[1]): active.append(next_couple) visited.append(hash(curr_couple[0])) return variants
def apply_from_variants_list(var_list, model, parameters=None): """ Performs conformance checking using the log skeleton, applying it from a list of variants Parameters -------------- var_list List of variants model Log skeleton model parameters Parameters Returns -------------- conformance_dictio Dictionary containing, for each variant, the result of log skeleton checking """ if parameters is None: parameters = {} activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes.DEFAULT_NAME_KEY) variant_delimiter = exec_utils.get_param_value( Parameters.PARAMETER_VARIANT_DELIMITER, parameters, constants.DEFAULT_VARIANT_SEP) conformance_output = {} for cv in var_list: v = cv[0] tr = v.split(variant_delimiter) trace = Trace() for act in tr: trace.append(Event({activity_key: act})) conformance_output[v] = apply_trace(trace, model, parameters=parameters) return conformance_output
def keep_only_one_attribute_per_event(log, attribute_key): """ Keeps only one attribute per event Parameters --------------- log Event log attribute_key Attribute key """ new_log = EventLog() if log is not None: for trace in log: new_trace = Trace() for ev in trace: new_trace.append(Event({attribute_key: ev[attribute_key]})) new_log.append(new_trace) return new_log
def __introduce_deviations_in_log(log: EventLog, probability_alter_trace=.5, probability_delete_event=.2, probability_change_activity_label=.2, probability_insert_events=.2): altered_log = EventLog() for t in log: if random.random() < probability_alter_trace: altered_trace = Trace() for e in t: action = random.choice([1, 2, 3]) if action == 1 and not random.random() < probability_delete_event: altered_trace.append(e) elif action == 2 and random.random() < probability_change_activity_label: e["concept:name"] = random.choice(string.ascii_letters) altered_trace.append(e) elif action == 3 and random.random() < probability_insert_events: e = Event() e["concept:name"] = random.choice(string.ascii_letters) altered_trace.append(e) altered_log.append(altered_trace) else: altered_log.append(t) return altered_log
def form_fake_log(prefixes_keys, activity_key=xes_util.DEFAULT_NAME_KEY): """ Form fake log for replay (putting each prefix as separate trace to align) Parameters ---------- prefixes_keys Keys of the prefixes (to form a log with a given order) activity_key Activity key (must be provided if different from concept:name) """ fake_log = EventLog() for prefix in prefixes_keys: trace = Trace() prefix_activities = prefix.split(",") for activity in prefix_activities: event = Event() event[activity_key] = activity trace.append(event) fake_log.append(trace) return fake_log
def generate_log(pt0, no_traces=100): """ Generate a log out of a process tree Parameters ------------ pt Process tree no_traces Number of traces contained in the process tree Returns ------------ log Trace log object """ pt = deepcopy(pt0) log = EventLog() # assigns to each event an increased timestamp from 1970 curr_timestamp = 10000000 for i in range(no_traces): ex_seq = execute(pt) ex_seq_labels = pt_util.project_execution_sequence_to_labels(ex_seq) trace = Trace() trace.attributes[xes.DEFAULT_NAME_KEY] = str(i) for label in ex_seq_labels: event = Event() event[xes.DEFAULT_NAME_KEY] = label event[xes.DEFAULT_TIMESTAMP_KEY] = datetime.datetime.fromtimestamp( curr_timestamp) trace.append(event) curr_timestamp = curr_timestamp + 1 log.append(trace) return log