Skip to content

Commit

Permalink
Merge branch 'ft-1216-log-to-interval-tree' into 'integration'
Browse files Browse the repository at this point in the history
FT 1216 Log to interval tree (retrieving open paths at a given point in time)

See merge request pm4py/pm4py-core!469
  • Loading branch information
fit-sebastiaan-van-zelst committed Oct 1, 2021
2 parents 0eeda19 + 7a44bef commit 03ee6b8
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 1 deletion.
16 changes: 16 additions & 0 deletions examples/log_to_int_tree_open_paths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pm4py
import os
from pm4py.algo.transformation.log_to_interval_tree import algorithm as log_to_interval_tree


def execute_script():
log = pm4py.read_xes(os.path.join("..", "tests", "input_data", "receipt.xes"))
tree = log_to_interval_tree.apply(log, variant=log_to_interval_tree.Variants.OPEN_PATHS)
# see how many paths are open at the timestamp 1319616410
print(len(tree[1319616410]))
# read the detailed information about the source and target event of each path
print(tree[1319616410])


if __name__ == "__main__":
execute_script()
2 changes: 1 addition & 1 deletion pm4py/algo/transformation/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from pm4py.algo.transformation import log_to_trie, log_to_features
from pm4py.algo.transformation import log_to_trie, log_to_features, log_to_interval_tree
1 change: 1 addition & 0 deletions pm4py/algo/transformation/log_to_interval_tree/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from pm4py.algo.transformation.log_to_interval_tree import algorithm, variants
35 changes: 35 additions & 0 deletions pm4py/algo/transformation/log_to_interval_tree/algorithm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from enum import Enum
from typing import Optional, Dict, Any

from intervaltree import IntervalTree

from pm4py.algo.transformation.log_to_interval_tree.variants import open_paths
from pm4py.objects.log.obj import EventLog
from pm4py.util import exec_utils


class Variants(Enum):
OPEN_PATHS = open_paths


def apply(log: EventLog, variant=Variants.OPEN_PATHS, parameters: Optional[Dict[Any, Any]] = None) -> IntervalTree:
"""
Transforms the event log to an interval tree using one of the available variants
Parameters
-----------------
log
Event log
variant
Variant of the algorithm to be used:
- Variants.OPEN_PATHS: transforms the event log to an interval tree in which the intervals are the
directly-follows paths in the log (open at the complete timestamp of the source event,
and closed at the start timestamp of the target event),
and having as associated data the source and the target event.
Returns
-----------------
tree
Interval tree object (which can be queried at a given timestamp, or range of timestamps)
"""
return exec_utils.get_variant(variant).apply(log, parameters=parameters)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from pm4py.algo.transformation.log_to_interval_tree.variants import open_paths
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from enum import Enum
from typing import Optional, Dict, Any

from intervaltree import IntervalTree, Interval

from pm4py.objects.log.obj import EventLog
from pm4py.util import exec_utils, constants, xes_constants


class Parameters(Enum):
START_TIMESTAMP_KEY = constants.PARAMETER_CONSTANT_START_TIMESTAMP_KEY
TIMESTAMP_KEY = constants.PARAMETER_CONSTANT_TIMESTAMP_KEY
EPSILON = "epsilon"


def apply(log: EventLog, parameters: Optional[Dict[Any, Any]] = None) -> IntervalTree:
"""
Transforms the event log to an interval tree in which the intervals are the
directly-follows paths in the log (open at the complete timestamp of the source event,
and closed at the start timestamp of the target event), and having as associated data the source and the target
event.
Parameters
-----------------
log
Event log
parameters
Parameters of the algorithm, including:
- Parameters.START_TIMESTAMP_KEY => the attribute to be used as start timestamp (default: xes_constants.DEFAULT_TIMESTAMP_KEY)
- Parameters.TIMESTAMP_KEY => the attribute to be used as completion timestamp (default: xes_constants.DEFAULT_TIMESTAMP_KEY)
- Parameters.EPSILON => the small gap that is removed from the timestamp of the source event and added to the
timestamp of the target event to make interval querying possible
Returns
-----------------
tree
Interval tree object (which can be queried at a given timestamp, or range of timestamps)
"""
if parameters is None:
parameters = {}

start_timestamp_key = exec_utils.get_param_value(Parameters.START_TIMESTAMP_KEY, parameters,
xes_constants.DEFAULT_TIMESTAMP_KEY)
timestamp_key = exec_utils.get_param_value(Parameters.TIMESTAMP_KEY, parameters,
xes_constants.DEFAULT_TIMESTAMP_KEY)
epsilon = exec_utils.get_param_value(Parameters.EPSILON, parameters, 0.00001)

tree = IntervalTree()

for trace in log:
for i in range(len(trace) - 1):
time_i = trace[i][timestamp_key].timestamp()
for j in range(i + 1, len(trace)):
time_j = trace[j][start_timestamp_key].timestamp()
if time_j >= time_i:
#print(time_i, time_j, (time_i + time_j)/2.0)
tree.add(Interval(time_i - epsilon, time_j + epsilon,
data={"source_event": trace[i], "target_event": trace[j]}))
break

return tree

0 comments on commit 03ee6b8

Please sign in to comment.