Skip to content

Commit

Permalink
Merge branch 'release' into release-github
Browse files Browse the repository at this point in the history
# Conflicts:
#	pm4py/algo/conformance/alignments/process_tree/util/__init__.py
#	pm4py/algo/transformation/__init__.py
#	pm4py/meta.py
#	pm4py/objects/bpmn/__init__.py
#	pm4py/objects/bpmn/obj.py
#	pm4py/objects/bpmn/util/__init__.py
#	pm4py/objects/ocel/__init__.py
#	pm4py/objects/ocel/util/__init__.py
#	pm4py/objects/petri_net/utils/reduction.py
#	requirements_stable.txt
  • Loading branch information
fit-sebastiaan-van-zelst committed Jan 6, 2022
2 parents 7e90b62 + 95d6dc4 commit 79f5721
Show file tree
Hide file tree
Showing 122 changed files with 6,700 additions and 391 deletions.
48 changes: 46 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,57 @@
# PM4Py Changelog

## PM4Py 2.218

### Added
* c15c8897
* add utility function to convert SNA results to NetworkX
* 8b300dbb
* add several new statistics for OCEL logs
* 8da0f41a
* add frequency-based visualization (using alignments) for process trees
* 54261cbb
* add progress bar to token-based replay
* 225dcad7
* add OCEL schema validators
* da6a4787
* add reduction rules for R/I nets
* fefcd453
* additional support for BPMN functionalities: exceptions and markings
* 417274fd
* add support for feature extraction from OCEL logs
* 5f5ff573
* add filter that checks relative occurrence of a specified attribute

### Changed
* b82dd92e
* revised implementation of the business hours module, now supports input of work calendars (workalendar package)
* 434e66af
* allow arbitrary arc weights visualized (reported at https://github.com/pm4py/pm4py-core/issues/303)

### Deprecated

### Fixed
* 76563e4b
* fix bug in process tree alignment that generates NoneTypeError when multiple leaves have the same label
* 3b6800d0
* minor bugfix in process tree playout (reported at: https://github.com/pm4py/pm4py-core/issues/305)


### Removed

### Other



## PM4Py 2.2.17.1 (2021.12.18)

### Fixed
* 2eb36ce5
* Bug fix in OCEL importing (timestamp parsing)
* Bug fix in OCEL importing (timestamp parsing)
* 512c071e
* Resolved security issue in data Petri nets' PNML parsing
* Resolved security issue in data Petri nets' PNML parsing

---

## PM4Py 2.2.17 (2021.12.14)

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ RUN apt-get -y install libtool flex bison pkg-config g++ libssl-dev automake
RUN apt-get -y install libjemalloc-dev libboost-dev libboost-filesystem-dev libboost-system-dev libboost-regex-dev python3-dev autoconf flex bison cmake
RUN apt-get -y install libxml2-dev libxslt-dev libfreetype6-dev libsuitesparse-dev
RUN pip install -U wheel six pytest
RUN pip install backcall==0.2.0 colorama==0.4.4 cycler==0.11.0 decorator==5.1.0 deprecation==2.1.0 fonttools==4.28.3 graphviz==0.19 intervaltree==3.1.0 ipython==7.30.1 jedi==0.18.1 jinja2==3.0.3 joblib==1.1.0 jsonpickle==2.0.0 kiwisolver==1.3.2 lxml==4.6.4 MarkupSafe==2.0.1 matplotlib==3.5.0 matplotlib-inline==0.1.3 mpmath==1.2.1 networkx==2.6.3 numpy==1.21.4 packaging==21.3 pandas==1.3.4 parso==0.8.3 pickleshare==0.7.5 pillow==8.4.0 prompt-toolkit==3.0.23 pydotplus==2.0.2 pygments==2.10.0 pyparsing==3.0.6 python-dateutil==2.8.2 pytz==2021.3 pyvis==0.1.9 scikit-learn==1.0.1 scipy==1.7.3 setuptools==59.5.0 setuptools-scm==6.3.2 six==1.16.0 sortedcontainers==2.4.0 stringdist==1.0.9 sympy==1.9 threadpoolctl==3.0.0 tomli==1.2.2 tqdm==4.62.3 traitlets==5.1.1 wcwidth==0.2.5
RUN pip install backcall==0.2.0 colorama==0.4.4 cycler==0.11.0 decorator==5.1.0 deprecation==2.1.0 fonttools==4.28.5 graphviz==0.19.1 intervaltree==3.1.0 ipython==7.30.1 jedi==0.18.1 jinja2==3.0.3 joblib==1.1.0 jsonpickle==2.0.0 kiwisolver==1.3.2 lxml==4.7.1 MarkupSafe==2.0.1 matplotlib==3.5.1 matplotlib-inline==0.1.3 mpmath==1.2.1 networkx==2.6.3 numpy==1.22.0 packaging==21.3 pandas==1.3.5 parso==0.8.3 pickleshare==0.7.5 pillow==9.0.0 prompt-toolkit==3.0.24 pydotplus==2.0.2 pygments==2.11.1 pyparsing==3.0.6 python-dateutil==2.8.2 pytz==2021.3 pyvis==0.1.9 scikit-learn==1.0.2 scipy==1.7.3 setuptools==60.2.0 setuptools-scm==6.3.2 six==1.16.0 sortedcontainers==2.4.0 stringdist==1.0.9 sympy==1.9 threadpoolctl==3.0.0 tomli==2.0.0 tqdm==4.62.3 traitlets==5.1.1 wcwidth==0.2.5

COPY . /app
RUN cd /app && python setup.py install
24 changes: 12 additions & 12 deletions README.THIRD_PARTY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,44 @@ libraries are added/removed.
| cycler | https://pypi.org/project/cycler | BSD License (BSD) | 0.11.0 |
| decorator | https://pypi.org/project/decorator | BSD License (new BSD License) | 5.1.0 |
| deprecation | https://pypi.org/project/deprecation | Apache Software License (Apache 2) | 2.1.0 |
| fonttools | https://pypi.org/project/fonttools | MIT License (MIT) | 4.28.3 |
| graphviz | https://pypi.org/project/graphviz | MIT License (MIT) | 0.19 |
| fonttools | https://pypi.org/project/fonttools | MIT License (MIT) | 4.28.5 |
| graphviz | https://pypi.org/project/graphviz | MIT License (MIT) | 0.19.1 |
| intervaltree | https://pypi.org/project/intervaltree | Apache Software License (Apache License, Version 2.0) | 3.1.0 |
| ipython | https://pypi.org/project/ipython | BSD License (BSD) | 7.30.1 |
| jedi | https://pypi.org/project/jedi | MIT License (MIT) | 0.18.1 |
| jinja2 | https://pypi.org/project/jinja2 | BSD License (BSD-3-Clause) | 3.0.3 |
| joblib | https://pypi.org/project/joblib | BSD License (BSD) | 1.1.0 |
| jsonpickle | https://pypi.org/project/jsonpickle | BSD License | 2.0.0 |
| kiwisolver | https://pypi.org/project/kiwisolver | BSD License (BSD) | 1.3.2 |
| lxml | https://pypi.org/project/lxml | BSD License (BSD) | 4.6.4 |
| lxml | https://pypi.org/project/lxml | BSD License (BSD) | 4.7.1 |
| MarkupSafe | https://pypi.org/project/MarkupSafe | BSD License (BSD-3-Clause) | 2.0.1 |
| matplotlib | https://pypi.org/project/matplotlib | Python Software Foundation License (PSF) | 3.5.0 |
| matplotlib | https://pypi.org/project/matplotlib | Python Software Foundation License (PSF) | 3.5.1 |
| matplotlib-inline | https://pypi.org/project/matplotlib-inline | BSD 3-Clause | 0.1.3 |
| mpmath | https://pypi.org/project/mpmath | BSD License (BSD) | 1.2.1 |
| networkx | https://pypi.org/project/networkx | BSD License | 2.6.3 |
| numpy | https://pypi.org/project/numpy | BSD License (BSD) | 1.21.4 |
| numpy | https://pypi.org/project/numpy | BSD License (BSD) | 1.22.0 |
| packaging | https://pypi.org/project/packaging | Apache Software License, BSD License (BSD-2-Clause or Apache-2.0) | 21.3 |
| pandas | https://pypi.org/project/pandas | BSD License (BSD-3-Clause) | 1.3.4 |
| pandas | https://pypi.org/project/pandas | BSD License (BSD-3-Clause) | 1.3.5 |
| parso | https://pypi.org/project/parso | MIT License (MIT) | 0.8.3 |
| pickleshare | https://pypi.org/project/pickleshare | MIT License (MIT) | 0.7.5 |
| pillow | https://pypi.org/project/pillow | Historical Permission Notice and Disclaimer (HPND) (HPND) | 8.4.0 |
| prompt-toolkit | https://pypi.org/project/prompt-toolkit | BSD License | 3.0.23 |
| pillow | https://pypi.org/project/pillow | Historical Permission Notice and Disclaimer (HPND) (HPND) | 9.0.0 |
| prompt-toolkit | https://pypi.org/project/prompt-toolkit | BSD License | 3.0.24 |
| pydotplus | https://pypi.org/project/pydotplus | MIT License (UNKNOWN) | 2.0.2 |
| pygments | https://pypi.org/project/pygments | BSD License (BSD License) | 2.10.0 |
| pygments | https://pypi.org/project/pygments | BSD License (BSD License) | 2.11.1 |
| pyparsing | https://pypi.org/project/pyparsing | MIT License (MIT License) | 3.0.6 |
| python-dateutil | https://pypi.org/project/python-dateutil | Apache Software License, BSD License (Dual License) | 2.8.2 |
| pytz | https://pypi.org/project/pytz | MIT License (MIT) | 2021.3 |
| pyvis | https://pypi.org/project/pyvis | BSD | 0.1.9 |
| scikit-learn | https://pypi.org/project/scikit-learn | OSI Approved (new BSD) | 1.0.1 |
| scikit-learn | https://pypi.org/project/scikit-learn | OSI Approved (new BSD) | 1.0.2 |
| scipy | https://pypi.org/project/scipy | BSD License (BSD) | 1.7.3 |
| setuptools | https://pypi.org/project/setuptools | MIT License | 59.5.0 |
| setuptools | https://pypi.org/project/setuptools | MIT License | 60.2.0 |
| setuptools-scm | https://pypi.org/project/setuptools-scm | MIT License (MIT) | 6.3.2 |
| six | https://pypi.org/project/six | MIT License (MIT) | 1.16.0 |
| sortedcontainers | https://pypi.org/project/sortedcontainers | Apache Software License (Apache 2.0) | 2.4.0 |
| stringdist | https://pypi.org/project/stringdist | MIT License (MIT) | 1.0.9 |
| sympy | https://pypi.org/project/sympy | BSD License (BSD) | 1.9 |
| threadpoolctl | https://pypi.org/project/threadpoolctl | BSD License (BSD-3-Clause) | 3.0.0 |
| tomli | https://pypi.org/project/tomli | MIT License | 1.2.2 |
| tomli | https://pypi.org/project/tomli | MIT License | 2.0.0 |
| tqdm | https://pypi.org/project/tqdm | MIT License, Mozilla Public License 2.0 (MPL 2.0) (MPLv2.0, MIT Licences) | 4.62.3 |
| traitlets | https://pypi.org/project/traitlets | BSD License (BSD) | 5.1.1 |
| wcwidth | https://pypi.org/project/wcwidth | MIT License (MIT) | 0.2.5 |
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# The short X.Y version
version = '2.2'
# The full version, including alpha/beta/rc tags
release = '2.2.17.1'
release = '2.2.18'

# -- General configuration ---------------------------------------------------

Expand Down
7 changes: 7 additions & 0 deletions examples/execute_everything.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
import traceback


def merging_case_relations():
from examples import merging_case_relations
print("\n\nmerging_case_relations")
merging_case_relations.execute_script()


def activity_position():
from examples import activity_position
print("\n\nactivity_position")
Expand Down Expand Up @@ -519,6 +525,7 @@ def execute_script(f):
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))))

if __name__ == "__main__":
execute_script(merging_case_relations)
execute_script(activity_position)
execute_script(link_analysis_vbfa)
execute_script(ocel_streaming)
Expand Down
21 changes: 21 additions & 0 deletions examples/feature_extraction_ocel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import os
import pm4py
import pandas as pd
from pm4py.algo.transformation.ocel.features.objects import algorithm as objects_feature_extraction
from pm4py.algo.transformation.ocel.features.events import algorithm as events_feature_extraction


def execute_script():
ocel = pm4py.read_ocel(os.path.join("..", "tests", "input_data", "ocel", "example_log.jsonocel"))
# extracts some features on the objects and embed them in a Pandas dataframe
data_objects, feature_names_objects = objects_feature_extraction.apply(ocel)
objects_features_df = pd.DataFrame(data_objects, columns=feature_names_objects)
print(objects_features_df)
# extracts some features on the events and embed them in a Pandas dataframe
data_events, feature_names_events = events_feature_extraction.apply(ocel)
events_features_df = pd.DataFrame(data_events, columns=feature_names_events)
print(events_features_df)


if __name__ == "__main__":
execute_script()
15 changes: 15 additions & 0 deletions examples/ocel_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from pm4py.objects.ocel.validation import jsonocel, xmlocel
import os


def execute_script():
# validate a JSONOCEL file against the corresponding schema
validation_result = jsonocel.apply(os.path.join("..", "tests", "input_data", "ocel", "example_log.jsonocel"), os.path.join("..", "tests", "input_data", "ocel", "validation", "schema.json"))
print(validation_result)
# validate an XMLOCEL file against the corresponding schema
validation_result = xmlocel.apply(os.path.join("..", "tests", "input_data", "ocel", "example_log.xmlocel"), os.path.join("..", "tests", "input_data", "ocel", "validation", "schema.xml"))
print(validation_result)


if __name__ == "__main__":
execute_script()
17 changes: 17 additions & 0 deletions examples/process_tree_frequency_annotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pm4py
import os
from pm4py.algo.conformance.alignments.process_tree.util import search_graph_pt_frequency_annotation
from pm4py.visualization.process_tree import visualizer as pt_visualizer


def execute_script():
log = pm4py.read_xes(os.path.join("..", "tests", "input_data", "receipt.xes"))
tree = pm4py.discover_process_tree_inductive(log)
aligned_traces = pm4py.conformance_diagnostics_alignments(log, tree)
tree = search_graph_pt_frequency_annotation.apply(tree, aligned_traces)
gviz = pt_visualizer.apply(tree, parameters={"format": "svg"}, variant=pt_visualizer.Variants.FREQUENCY_ANNOTATION)
pt_visualizer.view(gviz)


if __name__ == "__main__":
execute_script()
43 changes: 43 additions & 0 deletions examples/tree_manual_generation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pm4py
from pm4py.objects.process_tree.obj import ProcessTree, Operator


def execute_script():
root = ProcessTree(operator=Operator.SEQUENCE)

choice = ProcessTree(operator=Operator.XOR, parent=root)
parallel = ProcessTree(operator=Operator.PARALLEL, parent=root)

root.children.append(choice)
root.children.append(parallel)

leaf_A = ProcessTree(label="A", parent=choice)
leaf_B = ProcessTree(label="B", parent=choice)
leaf_C = ProcessTree(label="C", parent=choice)

choice.children.append(leaf_A)
choice.children.append(leaf_B)
choice.children.append(leaf_C)

leaf_D = ProcessTree(label="D", parent=parallel)
leaf_E = ProcessTree(label="E", parent=parallel)
leaf_F = ProcessTree(label="F", parent=parallel)

parallel.children.append(leaf_D)
parallel.children.append(leaf_E)
parallel.children.append(leaf_F)

pm4py.view_process_tree(root, format="svg")

# remove leaf_C from choice
choice.children.remove(leaf_C)

# remove the leaf with label "E" from parallel
parallel.children.remove(
[parallel.children[i] for i in range(len(parallel.children)) if parallel.children[i].label == "E"][0])

pm4py.view_process_tree(root, format="svg")


if __name__ == "__main__":
execute_script()
21 changes: 21 additions & 0 deletions examples/workalendar_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pm4py.util.business_hours import BusinessHours
import datetime
from workalendar.europe import Italy


def execute_script():
ts1 = 100000000
ts2 = 110000000
d1 = datetime.datetime.fromtimestamp(ts1)
d2 = datetime.datetime.fromtimestamp(ts2)
print(ts2-ts1)
# default business hours: all the days of the week except Saturday and Sunday are working days.
bh1 = BusinessHours(d1, d2, worktiming=[[7, 12.5], [13, 17]])
print(bh1.getseconds())
# let's calculate the business hours using a proper work calendar.
bh2 = BusinessHours(d1, d2, worktiming=[[7, 12.25], [13.25, 17]], workcalendar=Italy())
print(bh2.getseconds())


if __name__ == "__main__":
execute_script()
2 changes: 1 addition & 1 deletion pm4py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
discover_petri_net_inductive, discover_tree_inductive, discover_process_tree_inductive, discover_heuristics_net, \
discover_dfg, discover_footprints, discover_eventually_follows_graph, discover_directly_follows_graph, discover_bpmn_inductive, \
discover_performance_dfg, discover_ocdfg, discover_oc_petri_net
from pm4py.filtering import filter_start_activities, filter_end_activities, filter_attribute_values, filter_variants, \
from pm4py.filtering import filter_log_relative_occurrence_event_attribute, filter_start_activities, filter_end_activities, filter_attribute_values, filter_variants, \
filter_variants_percentage, filter_directly_follows_relation, filter_time_range, filter_trace_attribute, \
filter_eventually_follows_relation, filter_event_attribute_values, filter_trace_attribute_values, \
filter_between, filter_case_size, filter_case_performance, filter_activities_rework, filter_paths_performance, \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
You should have received a copy of the GNU General Public License
along with PM4Py. If not, see <https://www.gnu.org/licenses/>.
'''
from pm4py.algo.conformance.alignments.process_tree.util import search_graph_pt_replay_semantics
from pm4py.algo.conformance.alignments.process_tree.util import search_graph_pt_replay_semantics, search_graph_pt_frequency_annotation
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'''
This file is part of PM4Py (More Info: https://pm4py.fit.fraunhofer.de).
PM4Py is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PM4Py is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PM4Py. If not, see <https://www.gnu.org/licenses/>.
'''
from pm4py.objects.process_tree.obj import ProcessTree
from typing import Optional, Dict, Any, Union
from pm4py.util import typing, exec_utils
from enum import Enum
from collections import Counter
from pm4py.objects.process_tree.utils import bottomup


class Parameters(Enum):
NUM_EVENTS_PROPERTY = "num_events_property"
NUM_CASES_PROPERTY = "num_cases_property"


def apply(pt: ProcessTree, align_result: Union[typing.AlignmentResult, typing.ListAlignments],
parameters: Optional[Dict[Any, Any]] = None) -> ProcessTree:
"""
Annotate a process tree with frequency information (number of events / number of cases),
given the results of an alignment performed on the process tree.
Parameters
----------------
pt
Process tree
parameters
Parameters of the algorithm, including:
- Parameters.NUM_EVENTS_PROPERTY => number of events
- Parameters.NUM_CASES_PROPERTY => number of cases
Returns
----------------
pt
Annotated process tree
"""
if parameters is None:
parameters = {}

num_events_property = exec_utils.get_param_value(Parameters.NUM_EVENTS_PROPERTY, parameters, "num_events")
num_cases_property = exec_utils.get_param_value(Parameters.NUM_CASES_PROPERTY, parameters, "num_cases")
bottomup_nodes = bottomup.get_bottomup_nodes(pt, parameters=parameters)

all_paths_open_enabled_events = []
all_paths_open_enabled_cases = []
for trace in align_result:
state = trace["state"]
paths = []
while state.parent is not None:
if state.path:
paths.append(state.path)
state = state.parent
paths.reverse()
paths_enabled = [y[0] for x in paths for y in x if y[1] is ProcessTree.OperatorState.ENABLED]
paths_open = [y[0] for x in paths for y in x if y[1] is ProcessTree.OperatorState.OPEN if
y[0] not in paths_enabled]
all_paths_open_enabled_events = all_paths_open_enabled_events + paths_enabled + paths_open
all_paths_open_enabled_cases = all_paths_open_enabled_cases + list(set(paths_enabled + paths_open))
all_paths_open_enabled_events_counter = Counter(all_paths_open_enabled_events)
all_paths_open_enabled_cases_counter = Counter(all_paths_open_enabled_cases)

for node in bottomup_nodes:
node._properties[num_events_property] = all_paths_open_enabled_events_counter[node]
node._properties[num_cases_property] = all_paths_open_enabled_cases_counter[node]

return pt
Loading

0 comments on commit 79f5721

Please sign in to comment.