diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f61e51d8..41ff4e594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,28 @@ # Changelog of pm4py +## pm4py 2.7.7 (2023.09.22) + +### Added +* 056d9e5714e2ad0a21fbcac0725ea4fb7aae260c + * encoding specification in pm4py.read and pm4py.write classes + +### Changed +* f81d62ad8dc8a76aabdf90763a8bd8b8e2ea2aa9 + * fixed compatibility with Python 3.12 (removed deprecation warnings) + +### Deprecated + +### Fixed + +### Removed + +### Other + + +--- + + ## pm4py 2.7.6 (2023.08.28) ### Added diff --git a/docs/source/conf.py b/docs/source/conf.py index c23b10cec..4cda3853e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,7 @@ # The short X.Y version version = '2.7' # The full version, including alpha/beta/rc tags -release = '2.7.6' +release = '2.7.7' # -- General configuration --------------------------------------------------- diff --git a/pm4py/meta.py b/pm4py/meta.py index 19e450f44..093761e57 100644 --- a/pm4py/meta.py +++ b/pm4py/meta.py @@ -16,10 +16,10 @@ ''' __name__ = 'pm4py' -VERSION = '2.7.6' +VERSION = '2.7.7' __version__ = VERSION __doc__ = 'Process mining for Python' -__author__ = 'Fraunhofer Institute for Applied Technology' +__author__ = 'Fraunhofer Institute for Applied Information Technology FIT' __author_email__ = 'pm4py@fit.fraunhofer.de' -__maintainer__ = 'Fraunhofer Institute for Applied Technology' +__maintainer__ = 'Fraunhofer Institute for Applied Information Technology FIT' __maintainer_email__ = "pm4py@fit.fraunhofer.de" diff --git a/pm4py/objects/dfg/exporter/variants/classic.py b/pm4py/objects/dfg/exporter/variants/classic.py index 6e42e2f88..e7bf5f0ca 100644 --- a/pm4py/objects/dfg/exporter/variants/classic.py +++ b/pm4py/objects/dfg/exporter/variants/classic.py @@ -18,12 +18,13 @@ from enum import Enum from collections import Counter from pm4py.objects.dfg.utils import dfg_utils -from pm4py.util.constants import DEFAULT_ENCODING +from pm4py.util import constants class Parameters(Enum): START_ACTIVITIES = "start_activities" END_ACTIVITIES = "end_activities" + ENCODING = "encoding" def export_line_by_line(dfg, parameters=None): @@ -91,13 +92,16 @@ def apply(dfg, output_path, parameters=None): Parameters of the algorithm, including: Parameters.START_ACTIVITIES => Start activities of the DFG Parameters.END_ACTIVITIES => End activities of the DFG + Parameters.ENCODING => The encoding to be used (default: utf-8) """ if parameters is None: parameters = {} + encoding = exec_utils.get_param_value(Parameters.ENCODING, parameters, constants.DEFAULT_ENCODING) + F = open(output_path, "wb") for row in export_line_by_line(dfg, parameters=parameters): - F.write(row.encode(DEFAULT_ENCODING)) + F.write(row.encode(encoding)) F.close() @@ -113,6 +117,7 @@ def export_as_string(dfg, parameters=None): Parameters of the algorithm, including: Parameters.START_ACTIVITIES => Start activities of the DFG Parameters.END_ACTIVITIES => End activities of the DFG + Parameters.ENCODING => The encoding to be used (default: utf-8) Returns -------------- @@ -122,10 +127,12 @@ def export_as_string(dfg, parameters=None): if parameters is None: parameters = {} + encoding = exec_utils.get_param_value(Parameters.ENCODING, parameters, constants.DEFAULT_ENCODING) + ret = [] for row in export_line_by_line(dfg, parameters=parameters): ret.append(row) ret = "".join(ret) - ret = ret.encode(DEFAULT_ENCODING) + ret = ret.encode(encoding) return ret diff --git a/pm4py/objects/dfg/importer/variants/classic.py b/pm4py/objects/dfg/importer/variants/classic.py index 7ca63fad0..d605673b3 100644 --- a/pm4py/objects/dfg/importer/variants/classic.py +++ b/pm4py/objects/dfg/importer/variants/classic.py @@ -1,21 +1,10 @@ -''' - 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 . -''' -from pm4py.util import constants +from pm4py.util import constants, exec_utils from io import StringIO +from enum import Enum + + +class Parameters(Enum): + ENCODING = "encoding" def import_dfg_from_rows(rows, parameters=None): @@ -111,7 +100,9 @@ def apply(file_path, parameters=None): if parameters is None: parameters = {} - F = open(file_path, "r") + encoding = exec_utils.get_param_value(Parameters.ENCODING, parameters, constants.DEFAULT_ENCODING) + + F = open(file_path, "r", encoding=encoding) content = F.readlines() F.close() @@ -141,7 +132,9 @@ def import_dfg_from_string(dfg_string, parameters=None): if parameters is None: parameters = {} + encoding = exec_utils.get_param_value(Parameters.ENCODING, parameters, constants.DEFAULT_ENCODING) + if type(dfg_string) is bytes: - dfg_string = dfg_string.decode(constants.DEFAULT_ENCODING) + dfg_string = dfg_string.decode(encoding) return import_dfg_from_rows(StringIO(dfg_string).readlines(), parameters=parameters) diff --git a/pm4py/read.py b/pm4py/read.py index 391c1b1ac..eb26f79d1 100644 --- a/pm4py/read.py +++ b/pm4py/read.py @@ -38,7 +38,7 @@ """ -def read_xes(file_path: str, variant: str = "lxml", return_legacy_log_object: bool = constants.DEFAULT_READ_XES_LEGACY_OBJECT, **kwargs) -> Union[DataFrame, EventLog]: +def read_xes(file_path: str, variant: str = "lxml", return_legacy_log_object: bool = constants.DEFAULT_READ_XES_LEGACY_OBJECT, encoding: str = constants.DEFAULT_ENCODING, **kwargs) -> Union[DataFrame, EventLog]: """ Reads an event log stored in XES format (see `xes-standard `_) Returns a table (``pandas.DataFrame``) view of the event log. @@ -46,6 +46,7 @@ def read_xes(file_path: str, variant: str = "lxml", return_legacy_log_object: bo :param file_path: file path of the event log (``.xes`` file) on disk :param variant: the variant of the importer to use. "iterparse" => traditional XML parser; "line_by_line" => text-based line-by-line importer ; "chunk_regex" => chunk-of-bytes importer (default); "iterparse20" => XES 2.0 importer :param return_legacy_log_object: boolean value enabling returning a log object (default: False) + :param encoding: the encoding to be used (default: utf-8) :rtype: ``DataFrame`` .. code-block:: python3 @@ -68,7 +69,12 @@ def read_xes(file_path: str, variant: str = "lxml", return_legacy_log_object: bo v = xes_importer.Variants.LINE_BY_LINE elif variant == "chunk_regex": v = xes_importer.Variants.CHUNK_REGEX - log = xes_importer.apply(file_path, variant=v, parameters=kwargs) + + from copy import copy + parameters = copy(kwargs) + parameters["encoding"] = encoding + + log = xes_importer.apply(file_path, variant=v, parameters=parameters) if return_legacy_log_object: return log log = log_converter.apply(log, variant=log_converter.Variants.TO_DATA_FRAME) @@ -76,7 +82,7 @@ def read_xes(file_path: str, variant: str = "lxml", return_legacy_log_object: bo return log -def read_pnml(file_path: str, auto_guess_final_marking: bool = False) -> Tuple[PetriNet, Marking, Marking]: +def read_pnml(file_path: str, auto_guess_final_marking: bool = False, encoding: str = constants.DEFAULT_ENCODING) -> Tuple[PetriNet, Marking, Marking]: """ Reads a Petri net object from a .pnml file. The Petri net object returned is a triple containing the following objects: @@ -87,6 +93,7 @@ def read_pnml(file_path: str, auto_guess_final_marking: bool = False) -> Tuple[P :rtype: ``Tuple[PetriNet, Marking, Marking]`` :param file_path: file path of the Petri net model (``.pnml`` file) on disk + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -97,15 +104,16 @@ def read_pnml(file_path: str, auto_guess_final_marking: bool = False) -> Tuple[P if not os.path.exists(file_path): raise Exception("File does not exist") from pm4py.objects.petri_net.importer import importer as pnml_importer - net, im, fm = pnml_importer.apply(file_path, parameters={"auto_guess_final_marking": auto_guess_final_marking}) + net, im, fm = pnml_importer.apply(file_path, parameters={"auto_guess_final_marking": auto_guess_final_marking, "encoding": encoding}) return net, im, fm -def read_ptml(file_path: str) -> ProcessTree: +def read_ptml(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> ProcessTree: """ Reads a process tree object from a .ptml file :param file_path: file path of the process tree object on disk + :param encoding: the encoding to be used (default: utf-8) :rtype: ``ProcessTree`` .. code-block:: python3 @@ -117,11 +125,11 @@ def read_ptml(file_path: str) -> ProcessTree: if not os.path.exists(file_path): raise Exception("File does not exist") from pm4py.objects.process_tree.importer import importer as tree_importer - tree = tree_importer.apply(file_path) + tree = tree_importer.apply(file_path, parameters={"encoding": encoding}) return tree -def read_dfg(file_path: str) -> Tuple[Dict[Tuple[str,str],int], Dict[str,int], Dict[str,int]]: +def read_dfg(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> Tuple[Dict[Tuple[str,str],int], Dict[str,int], Dict[str,int]]: """ Reads a DFG object from a .dfg file. The DFG object returned is a triple containing the following objects: @@ -132,7 +140,7 @@ def read_dfg(file_path: str) -> Tuple[Dict[Tuple[str,str],int], Dict[str,int], D :rtype: ``Tuple[Dict[Tuple[str,str],int], Dict[str,int], Dict[str,int]]`` :param file_path: file path of the dfg model on disk - + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -143,15 +151,16 @@ def read_dfg(file_path: str) -> Tuple[Dict[Tuple[str,str],int], Dict[str,int], D if not os.path.exists(file_path): raise Exception("File does not exist") from pm4py.objects.dfg.importer import importer as dfg_importer - dfg, start_activities, end_activities = dfg_importer.apply(file_path) + dfg, start_activities, end_activities = dfg_importer.apply(file_path, parameters={"encoding": encoding}) return dfg, start_activities, end_activities -def read_bpmn(file_path: str) -> BPMN: +def read_bpmn(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> BPMN: """ Reads a BPMN model from a .bpmn file :param file_path: file path of the bpmn model + :param encoding: the encoding to be used (default: utf-8) :rtype: ``BPMN`` .. code-block:: python3 @@ -164,17 +173,18 @@ def read_bpmn(file_path: str) -> BPMN: if not os.path.exists(file_path): raise Exception("File does not exist") from pm4py.objects.bpmn.importer import importer as bpmn_importer - bpmn_graph = bpmn_importer.apply(file_path) + bpmn_graph = bpmn_importer.apply(file_path, parameters={"encoding": encoding}) return bpmn_graph -def read_ocel(file_path: str, objects_path: Optional[str] = None) -> OCEL: +def read_ocel(file_path: str, objects_path: Optional[str] = None, encoding: str = constants.DEFAULT_ENCODING) -> OCEL: """ Reads an object-centric event log from a file (see: http://www.ocel-standard.org/). The ``OCEL`` object is returned by this method :param file_path: file path of the object-centric event log :param objects_path: [Optional] file path from which the objects dataframe should be read + :param encoding: the encoding to be used (default: utf-8) :rtype: ``OCEL`` .. code-block:: python3 @@ -186,23 +196,24 @@ def read_ocel(file_path: str, objects_path: Optional[str] = None) -> OCEL: if not os.path.exists(file_path): raise Exception("File does not exist") if file_path.lower().endswith("csv"): - return read_ocel_csv(file_path, objects_path) + return read_ocel_csv(file_path, objects_path, encoding=encoding) elif file_path.lower().endswith("jsonocel"): - return read_ocel_json(file_path) + return read_ocel_json(file_path, encoding=encoding) elif file_path.lower().endswith("xmlocel"): - return read_ocel_xml(file_path) + return read_ocel_xml(file_path, encoding=encoding) elif file_path.lower().endswith(".sqlite"): - return read_ocel_sqlite(file_path) + return read_ocel_sqlite(file_path, encoding=encoding) raise Exception("unsupported file format") -def read_ocel_csv(file_path: str, objects_path: Optional[str] = None) -> OCEL: +def read_ocel_csv(file_path: str, objects_path: Optional[str] = None, encoding: str = constants.DEFAULT_ENCODING) -> OCEL: """ Reads an object-centric event log from a CSV file (see: http://www.ocel-standard.org/). The ``OCEL`` object is returned by this method :param file_path: file path of the object-centric event log (.csv) :param objects_path: [Optional] file path from which the objects dataframe should be read + :param encoding: the encoding to be used (default: utf-8) :rtype: ``OCEL`` .. code-block:: python3 @@ -215,15 +226,16 @@ def read_ocel_csv(file_path: str, objects_path: Optional[str] = None) -> OCEL: raise Exception("File does not exist") from pm4py.objects.ocel.importer.csv import importer as csv_importer - return csv_importer.apply(file_path, objects_path=objects_path) + return csv_importer.apply(file_path, objects_path=objects_path, parameters={"encoding": encoding}) -def read_ocel_json(file_path: str) -> OCEL: +def read_ocel_json(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> OCEL: """ Reads an object-centric event log from a JSON-OCEL file (see: http://www.ocel-standard.org/). The ``OCEL`` object is returned by this method :param file_path: file path of the object-centric event log (.jsonocel) + :param encoding: the encoding to be used (default: utf-8) :rtype: ``OCEL`` .. code-block:: python3 @@ -236,15 +248,16 @@ def read_ocel_json(file_path: str) -> OCEL: raise Exception("File does not exist") from pm4py.objects.ocel.importer.jsonocel import importer as jsonocel_importer - return jsonocel_importer.apply(file_path, variant=jsonocel_importer.Variants.CLASSIC) + return jsonocel_importer.apply(file_path, variant=jsonocel_importer.Variants.CLASSIC, parameters={"encoding": encoding}) -def read_ocel_xml(file_path: str) -> OCEL: +def read_ocel_xml(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> OCEL: """ Reads an object-centric event log from a XML-OCEL file (see: http://www.ocel-standard.org/). The ``OCEL`` object is returned by this method :param file_path: file path of the object-centric event log (.xmlocel) + :param encoding: the encoding to be used (default: utf-8) :rtype: ``OCEL`` .. code-block:: python3 @@ -257,15 +270,16 @@ def read_ocel_xml(file_path: str) -> OCEL: raise Exception("File does not exist") from pm4py.objects.ocel.importer.xmlocel import importer as xmlocel_importer - return xmlocel_importer.apply(file_path, variant=xmlocel_importer.Variants.CLASSIC) + return xmlocel_importer.apply(file_path, variant=xmlocel_importer.Variants.CLASSIC, parameters={"encoding": encoding}) -def read_ocel_sqlite(file_path: str) -> OCEL: +def read_ocel_sqlite(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> OCEL: """ Reads an object-centric event log from a SQLite database (see: http://www.ocel-standard.org/). The ``OCEL`` object is returned by this method :param file_path: file path of the SQLite database (.sqlite) + :param encoding: the encoding to be used (default: utf-8) :rtype: ``OCEL`` .. code-block:: python3 @@ -278,14 +292,15 @@ def read_ocel_sqlite(file_path: str) -> OCEL: raise Exception("File does not exist") from pm4py.objects.ocel.importer.sqlite import importer as sqlite_importer - return sqlite_importer.apply(file_path, variant=sqlite_importer.Variants.PANDAS_IMPORTER) + return sqlite_importer.apply(file_path, variant=sqlite_importer.Variants.PANDAS_IMPORTER, parameters={"encoding": encoding}) -def read_ocel2(file_path: str) -> OCEL: +def read_ocel2(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> OCEL: """ Reads an OCEL2.0 event log :param file_path: path to the OCEL2.0 event log + :param encoding: the encoding to be used (default: utf-8) :rtype: ``OCEL`` .. code-block:: python3 @@ -297,18 +312,19 @@ def read_ocel2(file_path: str) -> OCEL: if not os.path.exists(file_path): raise Exception("File does not exist") if file_path.lower().endswith("sqlite"): - return read_ocel2_sqlite(file_path) + return read_ocel2_sqlite(file_path, encoding=encoding) elif file_path.lower().endswith("xml") or file_path.lower().endswith("xmlocel"): - return read_ocel2_xml(file_path) + return read_ocel2_xml(file_path, encoding=encoding) elif file_path.lower().endswith("jsonocel"): - return read_ocel_json(file_path) + return read_ocel_json(file_path, encoding=encoding) -def read_ocel2_sqlite(file_path: str) -> OCEL: +def read_ocel2_sqlite(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> OCEL: """ Reads an OCEL2.0 event log from a SQLite database :param file_path: path to the OCEL2.0 database + :param encoding: the encoding to be used (default: utf-8) :rtype: ``OCEL`` .. code-block:: python3 @@ -321,14 +337,15 @@ def read_ocel2_sqlite(file_path: str) -> OCEL: raise Exception("File does not exist") from pm4py.objects.ocel.importer.sqlite import importer as sqlite_importer - return sqlite_importer.apply(file_path, variant=sqlite_importer.Variants.OCEL20) + return sqlite_importer.apply(file_path, variant=sqlite_importer.Variants.OCEL20, parameters={"encoding": encoding}) -def read_ocel2_xml(file_path: str) -> OCEL: +def read_ocel2_xml(file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> OCEL: """ Reads an OCEL2.0 event log from an XML file :param file_path: path to the OCEL2.0 event log + :param encoding: the encoding to be used (default: utf-8) :rtype: ``OCEL`` .. code-block:: python3 @@ -341,4 +358,4 @@ def read_ocel2_xml(file_path: str) -> OCEL: raise Exception("File does not exist") from pm4py.objects.ocel.importer.xmlocel import importer as xml_importer - return xml_importer.apply(file_path, variant=xml_importer.Variants.OCEL20) + return xml_importer.apply(file_path, variant=xml_importer.Variants.OCEL20, parameters={"encoding": encoding}) diff --git a/pm4py/util/constants.py b/pm4py/util/constants.py index 51973de00..a311e27d5 100644 --- a/pm4py/util/constants.py +++ b/pm4py/util/constants.py @@ -75,6 +75,7 @@ def get_param_from_env(name, default): DEFAULT_BGCOLOR = get_param_from_env("PM4PY_DEFAULT_BGCOLOR", "white") DEFAULT_FORMAT_GVIZ_VIEW = get_param_from_env("PM4PY_DEFAULT_FORMAT_GVIZ_VIEW", "png") +DEFAULT_RANKDIR_GVIZ = get_param_from_env("PM4PY_DEFAULT_RANKDIR_GVIZ", "LR") ENABLE_MULTIPROCESSING_DEFAULT = True if get_param_from_env("PM4PY_ENABLE_MULTIPROCESSING_DEFAULT", "False").lower() == "true" else False DEFAULT_READ_XES_LEGACY_OBJECT = True if get_param_from_env("PM4PY_DEFAULT_READ_XES_LEGACY_OBJECT", "False").lower() == "true" else False diff --git a/pm4py/vis.py b/pm4py/vis.py index cc6de9433..0dc49df2d 100644 --- a/pm4py/vis.py +++ b/pm4py/vis.py @@ -43,7 +43,7 @@ def view_petri_net(petri_net: PetriNet, initial_marking: Optional[Marking] = None, final_marking: Optional[Marking] = None, format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", - decorations: Dict[Any, Any] = None, debug: bool = False, rankdir: str = "LR"): + decorations: Dict[Any, Any] = None, debug: bool = False, rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Views a (composite) Petri net @@ -71,7 +71,7 @@ def view_petri_net(petri_net: PetriNet, initial_marking: Optional[Marking] = Non def save_vis_petri_net(petri_net: PetriNet, initial_marking: Marking, final_marking: Marking, file_path: str, bgcolor: str = "white", - decorations: Dict[Any, Any] = None, debug: bool = False, rankdir: str = "LR"): + decorations: Dict[Any, Any] = None, debug: bool = False, rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Saves a Petri net visualization to a file @@ -100,7 +100,7 @@ def save_vis_petri_net(petri_net: PetriNet, initial_marking: Marking, final_mark def view_performance_dfg(dfg: dict, start_activities: dict, end_activities: dict, format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, - aggregation_measure="mean", bgcolor: str = "white", rankdir: str = "TB"): + aggregation_measure="mean", bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Views a performance DFG @@ -135,7 +135,7 @@ def view_performance_dfg(dfg: dict, start_activities: dict, end_activities: dict def save_vis_performance_dfg(dfg: dict, start_activities: dict, end_activities: dict, file_path: str, - aggregation_measure="mean", bgcolor: str = "white", rankdir: str = "TB"): + aggregation_measure="mean", bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Saves the visualization of a performance DFG @@ -170,7 +170,7 @@ def save_vis_performance_dfg(dfg: dict, start_activities: dict, end_activities: dfg_visualizer.save(gviz, file_path) -def view_dfg(dfg: dict, start_activities: dict, end_activities: dict, format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", max_num_edges: int = sys.maxsize, rankdir: str = "TB"): +def view_dfg(dfg: dict, start_activities: dict, end_activities: dict, format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", max_num_edges: int = sys.maxsize, rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Views a (composite) DFG @@ -204,7 +204,7 @@ def view_dfg(dfg: dict, start_activities: dict, end_activities: dict, format: st dfg_visualizer.view(gviz) -def save_vis_dfg(dfg: dict, start_activities: dict, end_activities: dict, file_path: str, bgcolor: str = "white", max_num_edges: int = sys.maxsize, rankdir: str = "TB"): +def save_vis_dfg(dfg: dict, start_activities: dict, end_activities: dict, file_path: str, bgcolor: str = "white", max_num_edges: int = sys.maxsize, rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Saves a DFG visualization to a file @@ -239,7 +239,7 @@ def save_vis_dfg(dfg: dict, start_activities: dict, end_activities: dict, file_p dfg_visualizer.save(gviz, file_path) -def view_process_tree(tree: ProcessTree, format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = "TB"): +def view_process_tree(tree: ProcessTree, format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Views a process tree @@ -262,7 +262,7 @@ def view_process_tree(tree: ProcessTree, format: str = constants.DEFAULT_FORMAT_ pt_visualizer.view(gviz) -def save_vis_process_tree(tree: ProcessTree, file_path: str, bgcolor: str = "white", rankdir: str = "TB"): +def save_vis_process_tree(tree: ProcessTree, file_path: str, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Saves the visualization of a process tree @@ -286,7 +286,7 @@ def save_vis_process_tree(tree: ProcessTree, file_path: str, bgcolor: str = "whi pt_visualizer.save(gviz, file_path) -def save_vis_bpmn(bpmn_graph: BPMN, file_path: str, bgcolor: str = "white", rankdir: str = "LR"): +def save_vis_bpmn(bpmn_graph: BPMN, file_path: str, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Saves the visualization of a BPMN graph @@ -310,7 +310,7 @@ def save_vis_bpmn(bpmn_graph: BPMN, file_path: str, bgcolor: str = "white", rank bpmn_visualizer.save(gviz, file_path) -def view_bpmn(bpmn_graph: BPMN, format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = "LR"): +def view_bpmn(bpmn_graph: BPMN, format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Views a BPMN graph @@ -893,7 +893,7 @@ def save_vis_events_distribution_graph(log: Union[EventLog, pd.DataFrame], file_ graphs_visualizer.save(gviz, file_path) -def view_ocdfg(ocdfg: Dict[str, Any], annotation: str = "frequency", act_metric: str = "events", edge_metric="event_couples", act_threshold: int = 0, edge_threshold: int = 0, performance_aggregation: str = "mean", format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = "LR"): +def view_ocdfg(ocdfg: Dict[str, Any], annotation: str = "frequency", act_metric: str = "events", edge_metric="event_couples", act_threshold: int = 0, edge_threshold: int = 0, performance_aggregation: str = "mean", format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Views an OC-DFG (object-centric directly-follows graph) with the provided configuration. @@ -935,7 +935,7 @@ def view_ocdfg(ocdfg: Dict[str, Any], annotation: str = "frequency", act_metric: visualizer.view(gviz) -def save_vis_ocdfg(ocdfg: Dict[str, Any], file_path: str, annotation: str = "frequency", act_metric: str = "events", edge_metric="event_couples", act_threshold: int = 0, edge_threshold: int = 0, performance_aggregation: str = "mean", bgcolor: str = "white", rankdir="LR"): +def save_vis_ocdfg(ocdfg: Dict[str, Any], file_path: str, annotation: str = "frequency", act_metric: str = "events", edge_metric="event_couples", act_threshold: int = 0, edge_threshold: int = 0, performance_aggregation: str = "mean", bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Saves the visualization of an OC-DFG (object-centric directly-follows graph) with the provided configuration. @@ -977,7 +977,7 @@ def save_vis_ocdfg(ocdfg: Dict[str, Any], file_path: str, annotation: str = "fre visualizer.save(gviz, file_path) -def view_ocpn(ocpn: Dict[str, Any], format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = "LR"): +def view_ocpn(ocpn: Dict[str, Any], format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Visualizes on the screen the object-centric Petri net @@ -1000,7 +1000,7 @@ def view_ocpn(ocpn: Dict[str, Any], format: str = constants.DEFAULT_FORMAT_GVIZ_ ocpn_visualizer.view(gviz) -def save_vis_ocpn(ocpn: Dict[str, Any], file_path: str, bgcolor: str = "white", rankdir: str = "LR"): +def save_vis_ocpn(ocpn: Dict[str, Any], file_path: str, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Saves the visualization of the object-centric Petri net into a file @@ -1267,7 +1267,7 @@ def save_vis_footprints(footprints: Union[Tuple[Dict[str, Any], Dict[str, Any]], fps_visualizer.save(gviz, file_path) -def view_object_graph(ocel: OCEL, graph: Set[Tuple[str, str]], format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = "LR"): +def view_object_graph(ocel: OCEL, graph: Set[Tuple[str, str]], format: str = constants.DEFAULT_FORMAT_GVIZ_VIEW, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Visualizes an object graph on the screen @@ -1292,7 +1292,7 @@ def view_object_graph(ocel: OCEL, graph: Set[Tuple[str, str]], format: str = con obj_graph_vis.view(gviz) -def save_vis_object_graph(ocel: OCEL, graph: Set[Tuple[str, str]], file_path: str, bgcolor: str = "white", rankdir: str = "LR"): +def save_vis_object_graph(ocel: OCEL, graph: Set[Tuple[str, str]], file_path: str, bgcolor: str = "white", rankdir: str = constants.DEFAULT_RANKDIR_GVIZ): """ Saves the visualization of an object graph diff --git a/pm4py/visualization/bpmn/variants/classic.py b/pm4py/visualization/bpmn/variants/classic.py index 8d45d0fd1..f278b0267 100644 --- a/pm4py/visualization/bpmn/variants/classic.py +++ b/pm4py/visualization/bpmn/variants/classic.py @@ -56,7 +56,7 @@ def apply(bpmn_graph: BPMN, parameters: Optional[Dict[Any, Any]] = None) -> grap from pm4py.objects.bpmn.util.sorting import get_sorted_nodes_edges image_format = exec_utils.get_param_value(Parameters.FORMAT, parameters, "png") - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "LR") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) font_size = exec_utils.get_param_value(Parameters.FONT_SIZE, parameters, 12) font_size = str(font_size) bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) diff --git a/pm4py/visualization/dfg/util/dfg_gviz.py b/pm4py/visualization/dfg/util/dfg_gviz.py index 409fd569c..63a747bdf 100644 --- a/pm4py/visualization/dfg/util/dfg_gviz.py +++ b/pm4py/visualization/dfg/util/dfg_gviz.py @@ -135,7 +135,7 @@ def assign_penwidth_edges(dfg): def graphviz_visualization(activities_count, dfg, image_format="png", measure="frequency", max_no_of_edges_in_diagram=100000, start_activities=None, end_activities=None, soj_time=None, - font_size="12", bgcolor=constants.DEFAULT_BGCOLOR, rankdir="TB"): + font_size="12", bgcolor=constants.DEFAULT_BGCOLOR, rankdir=constants.DEFAULT_RANKDIR_GVIZ): """ Do GraphViz visualization of a DFG graph diff --git a/pm4py/visualization/dfg/variants/cost.py b/pm4py/visualization/dfg/variants/cost.py index 1c8bf0692..1dcc43ea3 100644 --- a/pm4py/visualization/dfg/variants/cost.py +++ b/pm4py/visualization/dfg/variants/cost.py @@ -82,7 +82,7 @@ def apply(dfg: Dict[Tuple[str, str], int], log: EventLog = None, parameters: Opt activities = dfg_utils.get_activities_from_dfg(dfg) aggregation_measure = exec_utils.get_param_value(Parameters.AGGREGATION_MEASURE, parameters, "mean") - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "TB") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) # if all the aggregation measures are provided for a given key, diff --git a/pm4py/visualization/dfg/variants/frequency.py b/pm4py/visualization/dfg/variants/frequency.py index b8271b9c5..2dc667b71 100644 --- a/pm4py/visualization/dfg/variants/frequency.py +++ b/pm4py/visualization/dfg/variants/frequency.py @@ -82,7 +82,7 @@ def apply(dfg: Dict[Tuple[str, str], int], log: EventLog = None, parameters: Opt end_activities = dict() activities = sorted(list(set(dfg_utils.get_activities_from_dfg(dfg)).union(set(start_activities)).union(set(end_activities)))) - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "TB") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) stat_locale = exec_utils.get_param_value(Parameters.STAT_LOCALE, parameters, {}) diff --git a/pm4py/visualization/dfg/variants/performance.py b/pm4py/visualization/dfg/variants/performance.py index 61bf0635f..62d86c2ea 100644 --- a/pm4py/visualization/dfg/variants/performance.py +++ b/pm4py/visualization/dfg/variants/performance.py @@ -80,7 +80,7 @@ def apply(dfg: Dict[Tuple[str, str], int], log: EventLog = None, parameters: Opt activities = dfg_utils.get_activities_from_dfg(dfg) aggregation_measure = exec_utils.get_param_value(Parameters.AGGREGATION_MEASURE, parameters, "mean") - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "TB") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) stat_locale = exec_utils.get_param_value(Parameters.STAT_LOCALE, parameters, {}) diff --git a/pm4py/visualization/ocel/interleavings/variants/graphviz.py b/pm4py/visualization/ocel/interleavings/variants/graphviz.py index 71b2d2971..dd1aa2f59 100644 --- a/pm4py/visualization/ocel/interleavings/variants/graphviz.py +++ b/pm4py/visualization/ocel/interleavings/variants/graphviz.py @@ -103,7 +103,7 @@ def apply(dataframe1: pd.DataFrame, dataframe2: pd.DataFrame, interleavings: pd. image_format = exec_utils.get_param_value(Parameters.FORMAT, parameters, "png") bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "TB") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) annotation = exec_utils.get_param_value(Parameters.ANNOTATION, parameters, "frequency") aggregation_measure = exec_utils.get_param_value(Parameters.AGGREGATION_MEASURE, parameters, "mean") activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY) diff --git a/pm4py/visualization/ocel/object_graph/variants/graphviz.py b/pm4py/visualization/ocel/object_graph/variants/graphviz.py index 7dd9ae995..38bc46acf 100644 --- a/pm4py/visualization/ocel/object_graph/variants/graphviz.py +++ b/pm4py/visualization/ocel/object_graph/variants/graphviz.py @@ -20,7 +20,7 @@ from enum import Enum from pm4py.util import exec_utils import tempfile -from pm4py.util import vis_utils +from pm4py.util import vis_utils, constants from pm4py.objects.ocel.obj import OCEL @@ -68,7 +68,7 @@ def apply(ocel: OCEL, graph: Set[Tuple[str, str]], parameters: Optional[Dict[Any image_format = exec_utils.get_param_value(Parameters.FORMAT, parameters, "png") bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, "transparent") - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "LR") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) directed = exec_utils.get_param_value(Parameters.DIRECTED, parameters, True) filename = tempfile.NamedTemporaryFile(suffix='.gv') diff --git a/pm4py/visualization/ocel/ocdfg/variants/classic.py b/pm4py/visualization/ocel/ocdfg/variants/classic.py index a3f563b11..5f11164a0 100644 --- a/pm4py/visualization/ocel/ocdfg/variants/classic.py +++ b/pm4py/visualization/ocel/ocdfg/variants/classic.py @@ -175,7 +175,7 @@ def apply(ocdfg: Dict[str, Any], parameters: Optional[Dict[Any, Any]] = None) -> image_format = exec_utils.get_param_value(Parameters.FORMAT, parameters, "png") bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "TB") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) act_metric = exec_utils.get_param_value(Parameters.ACT_METRIC, parameters, "events") edge_metric = exec_utils.get_param_value(Parameters.EDGE_METRIC, parameters, "event_couples") act_threshold = exec_utils.get_param_value(Parameters.ACT_THRESHOLD, parameters, 0) diff --git a/pm4py/visualization/ocel/ocpn/variants/wo_decoration.py b/pm4py/visualization/ocel/ocpn/variants/wo_decoration.py index e15d0bb41..c989d1f5f 100644 --- a/pm4py/visualization/ocel/ocpn/variants/wo_decoration.py +++ b/pm4py/visualization/ocel/ocpn/variants/wo_decoration.py @@ -68,7 +68,7 @@ def apply(ocpn: Dict[str, Any], parameters: Optional[Dict[Any, Any]] = None) -> image_format = exec_utils.get_param_value(Parameters.FORMAT, parameters, "png") bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "LR") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) filename = tempfile.NamedTemporaryFile(suffix='.gv') viz = Digraph("ocdfg", filename=filename.name, engine='dot', graph_attr={'bgcolor': bgcolor}) diff --git a/pm4py/visualization/process_tree/variants/frequency_annotation.py b/pm4py/visualization/process_tree/variants/frequency_annotation.py index e612fde0c..dcf78c28a 100644 --- a/pm4py/visualization/process_tree/variants/frequency_annotation.py +++ b/pm4py/visualization/process_tree/variants/frequency_annotation.py @@ -103,7 +103,7 @@ def apply(tree: ProcessTree, parameters: Optional[Dict[Union[str, Parameters], A filename = tempfile.NamedTemporaryFile(suffix='.gv') bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "TB") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) viz = Graph("pt", filename=filename.name, engine='dot', graph_attr={'bgcolor': bgcolor, "rankdir": rankdir}) viz.attr('node', shape='ellipse', fixedsize='false') diff --git a/pm4py/visualization/process_tree/variants/symbolic.py b/pm4py/visualization/process_tree/variants/symbolic.py index 67bd977cf..83aa59013 100644 --- a/pm4py/visualization/process_tree/variants/symbolic.py +++ b/pm4py/visualization/process_tree/variants/symbolic.py @@ -99,7 +99,7 @@ def apply(tree: ProcessTree, parameters: Optional[Dict[Union[str, Parameters], A filename = tempfile.NamedTemporaryFile(suffix='.gv') bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "TB") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) viz = Graph("pt", filename=filename.name, engine='dot', graph_attr={'bgcolor': bgcolor, "rankdir": rankdir}) viz.attr('node', shape='ellipse', fixedsize='false') diff --git a/pm4py/visualization/process_tree/variants/wo_decoration.py b/pm4py/visualization/process_tree/variants/wo_decoration.py index 0faabc63f..a6ab86754 100644 --- a/pm4py/visualization/process_tree/variants/wo_decoration.py +++ b/pm4py/visualization/process_tree/variants/wo_decoration.py @@ -101,7 +101,7 @@ def apply(tree: ProcessTree, parameters: Optional[Dict[Union[str, Parameters], A filename = tempfile.NamedTemporaryFile(suffix='.gv') bgcolor = exec_utils.get_param_value(Parameters.BGCOLOR, parameters, constants.DEFAULT_BGCOLOR) - rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, "TB") + rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, constants.DEFAULT_RANKDIR_GVIZ) viz = Graph("pt", filename=filename.name, engine='dot', graph_attr={'bgcolor': bgcolor, 'rankdir': rankdir}) viz.attr('node', shape='ellipse', fixedsize='false') diff --git a/pm4py/write.py b/pm4py/write.py index a697f6eed..344aa197b 100644 --- a/pm4py/write.py +++ b/pm4py/write.py @@ -34,7 +34,7 @@ from pm4py.objects.log.obj import XESExtension -def write_xes(log: Union[EventLog, pd.DataFrame], file_path: str, case_id_key: str = "case:concept:name", extensions: Optional[Collection[XESExtension]] = None, **kwargs) -> None: +def write_xes(log: Union[EventLog, pd.DataFrame], file_path: str, case_id_key: str = "case:concept:name", extensions: Optional[Collection[XESExtension]] = None, encoding: str = constants.DEFAULT_ENCODING, **kwargs) -> None: """ Writes an event log to disk in the XES format (see `xes-standard `_) @@ -42,6 +42,7 @@ def write_xes(log: Union[EventLog, pd.DataFrame], file_path: str, case_id_key: s :param file_path: target file path of the event log (``.xes`` file) on disk :param case_id_key: column key that identifies the case identifier :param extensions: extensions defined for the event log + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -64,12 +65,13 @@ def write_xes(log: Union[EventLog, pd.DataFrame], file_path: str, case_id_key: s parameters[k] = v parameters[constants.PARAMETER_CONSTANT_CASEID_KEY] = case_id_key parameters["extensions"] = extensions + parameters["encoding"] = encoding from pm4py.objects.log.exporter.xes import exporter as xes_exporter xes_exporter.apply(log, file_path, parameters=parameters) -def write_pnml(petri_net: PetriNet, initial_marking: Marking, final_marking: Marking, file_path: str) -> None: +def write_pnml(petri_net: PetriNet, initial_marking: Marking, final_marking: Marking, file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> None: """ Writes a Petri net object to disk in the ``.pnml`` format (see `pnml-standard `_) @@ -77,6 +79,7 @@ def write_pnml(petri_net: PetriNet, initial_marking: Marking, final_marking: Mar :param initial_marking: initial marking of the Petri net :param final_marking: final marking of the Petri net :param file_path: target file path on disk of the ``.pnml`` file + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -89,15 +92,16 @@ def write_pnml(petri_net: PetriNet, initial_marking: Marking, final_marking: Mar file_path = file_path + ".pnml" from pm4py.objects.petri_net.exporter import exporter as petri_exporter - petri_exporter.apply(petri_net, initial_marking, file_path, final_marking=final_marking) + petri_exporter.apply(petri_net, initial_marking, file_path, final_marking=final_marking, parameters={"encoding": encoding}) -def write_ptml(tree: ProcessTree, file_path: str) -> None: +def write_ptml(tree: ProcessTree, file_path: str, encoding: str = constants.DEFAULT_ENCODING) -> None: """ Writes a process tree object to disk in the ``.ptml`` format. :param tree: ProcessTree object that needs to be written to disk :param file_path: target file path on disk of the ``.ptml`` file + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -110,10 +114,10 @@ def write_ptml(tree: ProcessTree, file_path: str) -> None: file_path = file_path + ".ptml" from pm4py.objects.process_tree.exporter import exporter as tree_exporter - tree_exporter.apply(tree, file_path) + tree_exporter.apply(tree, file_path, parameters={"encoding": encoding}) -def write_dfg(dfg: Dict[Tuple[str,str],int], start_activities: Dict[str,int], end_activities: Dict[str,int], file_path: str): +def write_dfg(dfg: Dict[Tuple[str,str],int], start_activities: Dict[str,int], end_activities: Dict[str,int], file_path: str, encoding: str = constants.DEFAULT_ENCODING): """ Writes a directly follows graph (DFG) object to disk in the ``.dfg`` format. @@ -121,6 +125,7 @@ def write_dfg(dfg: Dict[Tuple[str,str],int], start_activities: Dict[str,int], e :param start_activities: multiset tracking the number of occurrences of start activities :param end_activities: mulltiset tracking the number of occurrences of end activities :param file_path: target file path on disk to write the dfg object to + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -135,16 +140,18 @@ def write_dfg(dfg: Dict[Tuple[str,str],int], start_activities: Dict[str,int], e from pm4py.objects.dfg.exporter import exporter as dfg_exporter dfg_exporter.apply(dfg, file_path, parameters={dfg_exporter.Variants.CLASSIC.value.Parameters.START_ACTIVITIES: start_activities, - dfg_exporter.Variants.CLASSIC.value.Parameters.END_ACTIVITIES: end_activities}) + dfg_exporter.Variants.CLASSIC.value.Parameters.END_ACTIVITIES: end_activities, + "encoding": encoding}) -def write_bpmn(model: BPMN, file_path: str, auto_layout: bool = True): +def write_bpmn(model: BPMN, file_path: str, auto_layout: bool = True, encoding: str = constants.DEFAULT_ENCODING): """ Writes a BPMN model object to disk in the ``.bpmn`` format. :param model: BPMN model to export :param file_path: target file path on disk to write the BPMN object to :param auto_layout: boolean indicating whether the model should get an auto layout (which is written to disk) + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -160,10 +167,10 @@ def write_bpmn(model: BPMN, file_path: str, auto_layout: bool = True): from pm4py.objects.bpmn.layout import layouter model = layouter.apply(model) from pm4py.objects.bpmn.exporter import exporter - exporter.apply(model, file_path) + exporter.apply(model, file_path, parameters={"encoding": encoding}) -def write_ocel(ocel: OCEL, file_path: str, objects_path: str = None): +def write_ocel(ocel: OCEL, file_path: str, objects_path: str = None, encoding: str = constants.DEFAULT_ENCODING): """ Writes an OCEL object to disk in the ``.bpmn`` format. Different formats are supported, including CSV (flat table), JSON-OCEL, XML-OCEL and SQLite @@ -172,6 +179,7 @@ def write_ocel(ocel: OCEL, file_path: str, objects_path: str = None): :param ocel: OCEL object to write to disk :param file_path: target file path on disk to write the OCEL object to :param objects_path: location of the objects table (only applicable in case of .csv exporting) + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -182,17 +190,17 @@ def write_ocel(ocel: OCEL, file_path: str, objects_path: str = None): file_path = str(file_path) if file_path.lower().endswith("csv"): - return write_ocel_csv(ocel, file_path, objects_path) + return write_ocel_csv(ocel, file_path, objects_path, encoding=encoding) elif file_path.lower().endswith("jsonocel"): - return write_ocel_json(ocel, file_path) + return write_ocel_json(ocel, file_path, encoding=encoding) elif file_path.lower().endswith("xmlocel"): - return write_ocel_xml(ocel, file_path) + return write_ocel_xml(ocel, file_path, encoding=encoding) elif file_path.lower().endswith("sqlite"): - return write_ocel_sqlite(ocel, file_path) + return write_ocel_sqlite(ocel, file_path, encoding=encoding) raise Exception("unsupported file format") -def write_ocel_csv(ocel: OCEL, file_path: str, objects_path: str): +def write_ocel_csv(ocel: OCEL, file_path: str, objects_path: str, encoding: str = constants.DEFAULT_ENCODING): """ Writes an OCEL object to disk in the ``.csv`` file format. The OCEL object is exported into two separate files, i.e., one event table and one objects table. @@ -201,6 +209,7 @@ def write_ocel_csv(ocel: OCEL, file_path: str, objects_path: str): :param ocel: OCEL object :param file_path: target file path on disk to write the event table to :param objects_path: target file path on disk to write the objects table to + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -213,15 +222,16 @@ def write_ocel_csv(ocel: OCEL, file_path: str, objects_path: str): file_path = file_path + ".csv" from pm4py.objects.ocel.exporter.csv import exporter as csv_exporter - return csv_exporter.apply(ocel, file_path, objects_path=objects_path) + return csv_exporter.apply(ocel, file_path, objects_path=objects_path, parameters={"encoding": encoding}) -def write_ocel_json(ocel: OCEL, file_path: str): +def write_ocel_json(ocel: OCEL, file_path: str, encoding: str = constants.DEFAULT_ENCODING): """ Writes an OCEL object to disk in the ``.json`` file format (exported as ``.oceljson`` file). :param ocel: OCEL object :param file_path: target file path on disk to write the OCEL object to + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -238,15 +248,16 @@ def write_ocel_json(ocel: OCEL, file_path: str): is_ocel20 = ocel.is_ocel20() variant = jsonocel_exporter.Variants.OCEL20 if is_ocel20 else jsonocel_exporter.Variants.CLASSIC - return jsonocel_exporter.apply(ocel, file_path, variant=variant) + return jsonocel_exporter.apply(ocel, file_path, variant=variant, parameters={"encoding": encoding}) -def write_ocel_xml(ocel: OCEL, file_path: str): +def write_ocel_xml(ocel: OCEL, file_path: str, encoding: str = constants.DEFAULT_ENCODING): """ Writes an OCEL object to disk in the ``.xml`` file format (exported as ``.ocelxml`` file). :param ocel: OCEL object :param file_path: target file path on disk to write the OCEL object to + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -259,15 +270,16 @@ def write_ocel_xml(ocel: OCEL, file_path: str): file_path = file_path + ".xmlocel" from pm4py.objects.ocel.exporter.xmlocel import exporter as xmlocel_exporter - return xmlocel_exporter.apply(ocel, file_path, variant=xmlocel_exporter.Variants.CLASSIC) + return xmlocel_exporter.apply(ocel, file_path, variant=xmlocel_exporter.Variants.CLASSIC, parameters={"encoding": encoding}) -def write_ocel_sqlite(ocel: OCEL, file_path: str): +def write_ocel_sqlite(ocel: OCEL, file_path: str, encoding: str = constants.DEFAULT_ENCODING): """ Writes an OCEL object to disk to a ``SQLite`` database (exported as ``.sqlite`` file). :param ocel: OCEL object :param file_path: target file path to the SQLite datbaase + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -280,15 +292,16 @@ def write_ocel_sqlite(ocel: OCEL, file_path: str): file_path = file_path + ".sqlite" from pm4py.objects.ocel.exporter.sqlite import exporter as sqlite_exporter - return sqlite_exporter.apply(ocel, file_path, variant=sqlite_exporter.Variants.PANDAS_EXPORTER) + return sqlite_exporter.apply(ocel, file_path, variant=sqlite_exporter.Variants.PANDAS_EXPORTER, parameters={"encoding": encoding}) -def write_ocel2(ocel: OCEL, file_path: str): +def write_ocel2(ocel: OCEL, file_path: str, encoding: str = constants.DEFAULT_ENCODING): """ Writes an OCEL2.0 object to disk :param ocel: OCEL object :param file_path: target file path to the SQLite datbaase + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -299,19 +312,20 @@ def write_ocel2(ocel: OCEL, file_path: str): file_path = str(file_path) if file_path.lower().endswith("sqlite"): - return write_ocel2_sqlite(ocel, file_path) + return write_ocel2_sqlite(ocel, file_path, encoding=encoding) elif file_path.lower().endswith("xml") or file_path.lower().endswith("xmlocel"): - return write_ocel2_xml(ocel, file_path) + return write_ocel2_xml(ocel, file_path, encoding=encoding) elif file_path.lower().endswith("jsonocel"): - return write_ocel_json(ocel, file_path) + return write_ocel_json(ocel, file_path, encoding=encoding) -def write_ocel2_sqlite(ocel: OCEL, file_path: str): +def write_ocel2_sqlite(ocel: OCEL, file_path: str, encoding: str = constants.DEFAULT_ENCODING): """ Writes an OCEL2.0 object to disk to a ``SQLite`` database (exported as ``.sqlite`` file). :param ocel: OCEL object :param file_path: target file path to the SQLite datbaase + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -324,15 +338,16 @@ def write_ocel2_sqlite(ocel: OCEL, file_path: str): file_path = file_path + ".sqlite" from pm4py.objects.ocel.exporter.sqlite import exporter as sqlite_exporter - return sqlite_exporter.apply(ocel, file_path, variant=sqlite_exporter.Variants.OCEL20) + return sqlite_exporter.apply(ocel, file_path, variant=sqlite_exporter.Variants.OCEL20, parameters={"encoding": encoding}) -def write_ocel2_xml(ocel: OCEL, file_path: str): +def write_ocel2_xml(ocel: OCEL, file_path: str, encoding: str = constants.DEFAULT_ENCODING): """ Writes an OCEL2.0 object to disk to an ``XML`` file (exported as ``.xmlocel`` file). :param ocel: OCEL object :param file_path: target file path to the XML file + :param encoding: the encoding to be used (default: utf-8) .. code-block:: python3 @@ -345,4 +360,4 @@ def write_ocel2_xml(ocel: OCEL, file_path: str): file_path = file_path + ".xmlocel" from pm4py.objects.ocel.exporter.xmlocel import exporter as xml_exporter - return xml_exporter.apply(ocel, file_path, variant=xml_exporter.Variants.OCEL20) + return xml_exporter.apply(ocel, file_path, variant=xml_exporter.Variants.OCEL20, parameters={"encoding": encoding})