diff --git a/pm4py/__init__.py b/pm4py/__init__.py index ec6d52f5e..a12382579 100644 --- a/pm4py/__init__.py +++ b/pm4py/__init__.py @@ -28,7 +28,7 @@ conformance_log_skeleton from pm4py.ocel import ocel_objects_interactions_summary, ocel_temporal_summary, ocel_objects_summary, ocel_get_object_types, ocel_get_attribute_names, ocel_flattening, ocel_object_type_activities, ocel_objects_ot_count, \ discover_ocdfg, discover_oc_petri_net, discover_objects_graph, sample_ocel_objects, ocel_drop_duplicates, ocel_merge_duplicates, ocel_sort_by_additional_column, \ - ocel_add_index_based_timedelta, sample_ocel_connected_components, ocel_o2o_enrichment + ocel_add_index_based_timedelta, sample_ocel_connected_components, ocel_o2o_enrichment, ocel_e2o_lifecycle_enrichment from pm4py.vis import view_petri_net, save_vis_petri_net, view_dfg, save_vis_dfg, view_process_tree, \ save_vis_process_tree, \ view_ocdfg, save_vis_ocdfg, view_heuristics_net, save_vis_heuristics_net, view_bpmn, save_vis_bpmn, view_sna, save_vis_sna,\ diff --git a/pm4py/objects/ocel/util/e2o_qualification.py b/pm4py/objects/ocel/util/e2o_qualification.py new file mode 100644 index 000000000..06b90e936 --- /dev/null +++ b/pm4py/objects/ocel/util/e2o_qualification.py @@ -0,0 +1,45 @@ +from pm4py.objects.ocel.obj import OCEL +from typing import Optional, Dict, Any +from enum import Enum +from pm4py.util import exec_utils +from copy import copy + +class Parameters(Enum): + CONCATENER = "concatener" + CONCAT_COLUMN = "concat_column" + + +def apply(ocel: OCEL, qualifier_type: str, parameters: Optional[Dict[Any, Any]] = None) -> OCEL: + if parameters is None: + parameters = {} + + concatener = exec_utils.get_param_value(Parameters.CONCATENER, parameters, "@@") + concat_column = exec_utils.get_param_value(Parameters.CONCAT_COLUMN, parameters, "@@concat") + + ocel = copy(ocel) + ocel.relations[concat_column] = ocel.relations[ocel.event_id_column] + concatener + ocel.relations[ocel.object_id_column] + relations = ocel.relations.groupby(ocel.object_id_column)[ocel.event_id_column] + + if qualifier_type == "creation": + relations = relations.first().to_dict() + relations = {y + concatener + x: qualifier_type for x, y in relations.items()} + elif qualifier_type == "termination": + relations = relations.last().to_dict() + relations = {y + concatener + x: qualifier_type for x, y in relations.items()} + elif qualifier_type == "other": + relations0 = relations.agg(list).to_dict() + relations0 = {x: y[1:-1] for x, y in relations0.items()} + relations0 = {x: y for x, y in relations0.items() if y} + relations = {} + for x, y in relations0.items(): + for y1 in y: + relations[y1 + concatener + x] = qualifier_type + + ocel.relations[ocel.qualifier+"_2"] = ocel.relations[concat_column].map(relations) + ocel.relations[ocel.qualifier+"_2"] = ocel.relations[ocel.qualifier+"_2"].fillna(ocel.relations[ocel.qualifier]) + ocel.relations[ocel.qualifier] = ocel.relations[ocel.qualifier+"_2"] + + del ocel.relations[ocel.qualifier+"_2"] + del ocel.relations[concat_column] + + return ocel diff --git a/pm4py/ocel.py b/pm4py/ocel.py index 4af2afae8..2a78d1671 100644 --- a/pm4py/ocel.py +++ b/pm4py/ocel.py @@ -291,6 +291,29 @@ def ocel_o2o_enrichment(ocel: OCEL, included_graphs: Optional[Collection[str]] = return ocel20_computation.apply(ocel, parameters={"included_graphs": included_graphs}) +def ocel_e2o_lifecycle_enrichment(ocel: OCEL) -> OCEL: + """ + Inserts lifecycle-based information (when an object is created/terminated or other types of relations) + in the list of E2O relations of the OCEL + + :param ocel: object-centric event log + :rtype: ``OCEL`` + + .. code-block:: python3 + + import pm4py + + ocel = pm4py.read_ocel('trial.ocel') + ocel = pm4py.ocel_e2o_lifecycle_enrichment(ocel) + print(ocel.relations) + """ + from pm4py.objects.ocel.util import e2o_qualification + ocel = e2o_qualification.apply(ocel, "termination") + ocel = e2o_qualification.apply(ocel, "creation") + ocel = e2o_qualification.apply(ocel, "other") + return ocel + + def sample_ocel_objects(ocel: OCEL, num_objects: int) -> OCEL: """ Given an object-centric event log, returns a sampled event log with a subset of the objects