''' 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 . ''' import pm4py import sys import os import itertools from pathlib import Path import traceback import pandas as pd from pm4py.util import constants, pandas_utils methods = { "ConvertToXES": {"inputs": [".csv"], "output_extension": ".xes", "method": lambda x: pm4py.write_xes( pm4py.convert_to_event_log(pm4py.format_dataframe(pandas_utils.read_csv(x[0]))), x[1])}, "ConvertToCSV": {"inputs": [".xes"], "output_extension": ".csv", "method": lambda x: pm4py.convert_to_dataframe(pm4py.read_xes(x[0])).to_csv(x[1], index=False)}, "ConvertPNMLtoBPMN": {"inputs": [".pnml"], "output_extension": ".bpmn", "method": lambda x: pm4py.write_bpmn(pm4py.convert_to_bpmn(*pm4py.read_pnml(x[0])), x[1])}, "ConvertPNMLtoPTML": {"inputs": [".pnml"], "output_extension": ".ptml", "method": lambda x: pm4py.write_ptml(pm4py.convert_to_process_tree(*pm4py.read_pnml(x[0])), x[1])}, "ConvertPTMLtoPNML": {"inputs": [".ptml"], "output_extension": ".pnml", "method": lambda x: pm4py.write_pnml(*pm4py.convert_to_petri_net(pm4py.read_ptml(x[0])), x[1])}, "ConvertPTMLtoBPMN": {"inputs": [".ptml"], "output_extension": ".bpmn", "method": lambda x: pm4py.write_bpmn(pm4py.convert_to_bpmn(pm4py.read_ptml(x[0])), x[1])}, "ConvertBPMNtoPNML": {"inputs": [".bpmn"], "output_extension": ".pnml", "method": lambda x: pm4py.write_pnml(*pm4py.convert_to_petri_net(pm4py.read_bpmn(x[0])), x[1])}, "ConvertDFGtoPNML": {"inputs": [".dfg"], "output_extension": ".pnml", "method": lambda x: pm4py.write_pnml(*pm4py.convert_to_petri_net(*pm4py.read_dfg(x[0])), x[1])}, "DiscoverPetriNetAlpha": {"inputs": [".xes"], "output_extension": ".pnml", "method": lambda x: pm4py.write_pnml(*pm4py.discover_petri_net_alpha(__read_log(x[0])), x[1])}, "DiscoverPetriNetInductive": {"inputs": [".xes"], "output_extension": ".pnml", "method": lambda x: pm4py.write_pnml( *pm4py.discover_petri_net_inductive(__read_log(x[0])), x[1])}, "DiscoverPetriNetHeuristics": {"inputs": [".xes"], "output_extension": ".pnml", "method": lambda x: pm4py.write_pnml( *pm4py.discover_petri_net_heuristics(__read_log(x[0])), x[1])}, "DiscoverBPMNInductive": {"inputs": [".xes"], "output_extension": ".bpmn", "method": lambda x: pm4py.write_bpmn( pm4py.discover_bpmn_inductive(__read_log(x[0])), x[1])}, "DiscoverProcessTreeInductive": {"inputs": [".xes"], "output_extension": ".ptml", "method": lambda x: pm4py.write_ptml( pm4py.discover_process_tree_inductive(__read_log(x[0])), x[1])}, "DiscoverDFG": {"inputs": [".xes"], "output_extension": ".dfg", "method": lambda x: pm4py.write_dfg(*pm4py.discover_dfg(__read_log(x[0])), x[1])}, "ConformanceDiagnosticsTBR": {"inputs": [".xes", ".pnml"], "output_extension": ".txt", "method": lambda x: open(x[2], "w").write(str( pm4py.conformance_diagnostics_token_based_replay(__read_log(x[0]), *pm4py.read_pnml(x[1]), return_diagnostics_dataframe=False)))}, "ConformanceDiagnosticsAlignments": {"inputs": [".xes", ".pnml"], "output_extension": ".txt", "method": lambda x: open(x[2], "w").write(str( pm4py.conformance_diagnostics_alignments(__read_log(x[0]), *pm4py.read_pnml(x[1]), return_diagnostics_dataframe=False)))}, "FitnessTBR": {"inputs": [".xes", ".pnml"], "output_extension": ".txt", "method": lambda x: open(x[2], "w").write(str( pm4py.fitness_token_based_replay(__read_log(x[0]), *pm4py.read_pnml(x[1]))))}, "FitnessAlignments": {"inputs": [".xes", ".pnml"], "output_extension": ".txt", "method": lambda x: open(x[2], "w").write(str( pm4py.fitness_alignments(__read_log(x[0]), *pm4py.read_pnml(x[1]))))}, "PrecisionTBR": {"inputs": [".xes", ".pnml"], "output_extension": ".txt", "method": lambda x: open(x[2], "w").write(str( pm4py.precision_token_based_replay(__read_log(x[0]), *pm4py.read_pnml(x[1]))))}, "PrecisionAlignments": {"inputs": [".xes", ".pnml"], "output_extension": ".txt", "method": lambda x: open(x[2], "w").write(str( pm4py.precision_alignments(__read_log(x[0]), *pm4py.read_pnml(x[1]))))}, "SaveVisDFG": {"inputs": [".dfg"], "output_extension": ".png", "method": lambda x: pm4py.save_vis_dfg(*pm4py.read_dfg(x[0]), x[1])}, "SaveVisPNML": {"inputs": [".pnml"], "output_extension": ".png", "method": lambda x: pm4py.save_vis_petri_net(*pm4py.read_pnml(x[0]), x[1])}, "SaveVisBPMN": {"inputs": [".bpmn"], "output_extension": ".png", "method": lambda x: pm4py.save_vis_bpmn(pm4py.read_bpmn(x[0]), x[1])}, "SaveVisPTML": {"inputs": [".ptml"], "output_extension": ".png", "method": lambda x: pm4py.save_vis_process_tree(pm4py.read_ptml(x[0]), x[1])}, "SaveVisDottedChart": {"inputs": [".xes", None, None, None], "output_extension": ".png", "method": lambda x: pm4py.save_vis_dotted_chart(__read_log(x[0]), x[4], attributes=[x[1], x[2], x[3]])}, "SaveVisTransitionSystem": {"inputs": [".xes"], "output_extension": ".png", "method": lambda x: pm4py.save_vis_transition_system( pm4py.discover_transition_system(__read_log(x[0])), x[1])}, "SaveVisTrie": {"inputs": [".xes"], "output_extension": ".png", "method": lambda x: pm4py.save_vis_prefix_tree(pm4py.discover_prefix_tree(__read_log(x[0])), x[1])}, "SaveVisEventsDistribution": {"inputs": [".xes", None], "output_extension": ".png", "method": lambda x: pm4py.save_vis_events_distribution_graph(__read_log(x[0]), x[2], distr_type=x[1])}, "SaveVisEventsPerTime": {"inputs": [".xes"], "output_extension": ".png", "method": lambda x: pm4py.save_vis_events_per_time_graph(__read_log(x[0]), x[1])}, "GenerateProcessTree": {"inputs": [None], "output_extension": ".ptml", "method": lambda x: pm4py.write_ptml( pm4py.generate_process_tree(parameters={"min": int(x[0]), "max": int(x[0]), "mode": int(x[0])}), x[1])}, "PNMLplayout": {"inputs": [".pnml"], "output_extension": ".xes", "method": lambda x: pm4py.write_xes(pm4py.play_out(*pm4py.read_pnml(x[0])), x[1])}, "PTMLplayout": {"inputs": [".ptml"], "output_extension": ".xes", "method": lambda x: pm4py.write_xes(pm4py.play_out(pm4py.read_ptml(x[0])), x[1])}, "DFGplayout": {"inputs": [".dfg"], "output_extension": ".dfg", "method": lambda x: pm4py.write_xes(pm4py.play_out(*pm4py.read_dfg(x[0])), x[1])}, "SaveVisSNA": {"inputs": [".xes", None], "output_extension": ".png", "method": lambda x: pm4py.save_vis_sna(__apply_sna(__read_log(x[0]), x[1]), x[2])}, "SaveVisCaseDuration": {"inputs": [".xes"], "output_extension": ".png", "method": lambda x: pm4py.save_vis_case_duration_graph(__read_log(x[0]), x[1])}, "FilterVariantsTopK": {"inputs": [".xes", None], "output_extension": ".xes", "method": lambda x: pm4py.write_xes(pm4py.filter_variants_top_k(__read_log(x[0]), int(x[1])), x[2])}, "FilterVariantsCoverage": {"inputs": [".xes", None], "output_extension": ".xes", "method": lambda x: pm4py.write_xes( pm4py.filter_variants_by_coverage_percentage(__read_log(x[0]), float(x[1])), x[2])}, "FilterCasePerformance": {"inputs": [".xes", None, None], "output_extension": ".xes", "method": lambda x: pm4py.write_xes( pm4py.filter_case_performance(__read_log(x[0]), min_performance=float(x[1]), max_performance=float(x[2])), x[3])}, "FilterTimeRange": {"inputs": [".xes", None, None], "output_extension": ".xes", "method": lambda x: pm4py.write_xes( pm4py.filter_time_range(__read_log(x[0]), x[1] + " 00:00:00", x[2] + " 23:59:59"), x[3])} } def __read_log(log_path): if "xes" in log_path.lower(): return pm4py.read_xes(log_path) elif "csv" in log_path.lower(): dataframe = pandas_utils.read_csv(log_path) dataframe = pm4py.format_dataframe(dataframe) return dataframe def __apply_sna(log, method, **kwargs): if method == "handover": return pm4py.discover_handover_of_work_network(log, **kwargs) elif method == "working_together": return pm4py.discover_working_together_network(log, **kwargs) elif method == "similar_activities": return pm4py.discover_activity_based_resource_similarity(log, **kwargs) elif method == "subcontracting": return pm4py.discover_subcontracting_network(log, **kwargs) def __get_output_name(inp_list, idx, method_name, extension): ret = [] for inp in inp_list: ret.append(str(Path(inp).stem)) return "_".join(ret) + "_" + method_name + extension def cli_interface(): method_name = sys.argv[1] if method_name in methods: method = methods[method_name] inputs = [] for i in range(len(method["inputs"])): ci = sys.argv[2 + i] if os.path.isdir(ci): if not os.path.exists(ci): raise Exception("the provided path (" + ci + ") does not exist.") files = os.listdir(ci) inputs.append([os.path.join(ci, f) for f in files if os.path.isfile(os.path.join(ci, f)) and f.endswith(method["inputs"][i])]) else: inputs.append([ci]) j = 2 + len(method["inputs"]) inputs = list(itertools.product(*inputs)) if len(inputs) == 1: outputs = [[sys.argv[j]]] else: if not os.path.exists(sys.argv[j]): os.mkdir(sys.argv[j]) outputs = [ [os.path.join(sys.argv[j], __get_output_name(inputs[z], z, method_name, method["output_extension"]))] for z in range(len(inputs))] method_tuples = [(*inputs[i], *outputs[i]) for i in range(len(inputs))] for i in range(len(method_tuples)): try: if not os.path.exists(method_tuples[i][-1]): print(method_name, method_tuples[i]) method["method"](method_tuples[i]) except: traceback.print_exc() else: raise Exception("the provided method (" + method_name + ") does not exist in the CLI.") if __name__ == "__main__": cli_interface()