openprocess 0.12.1__tar.gz → 0.12.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. {openprocess-0.12.1/openprocess.egg-info → openprocess-0.12.2}/PKG-INFO +1 -1
  2. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/__init__.py +1 -1
  3. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/measure.py +2 -3
  4. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/viewers.py +78 -10
  5. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/dotted.py +30 -4
  6. {openprocess-0.12.1 → openprocess-0.12.2/openprocess.egg-info}/PKG-INFO +1 -1
  7. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_flow_gui.py +9 -0
  8. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_measure.py +2 -0
  9. {openprocess-0.12.1 → openprocess-0.12.2}/LICENSE +0 -0
  10. {openprocess-0.12.1 → openprocess-0.12.2}/README.md +0 -0
  11. {openprocess-0.12.1 → openprocess-0.12.2}/cpnpy/__init__.py +0 -0
  12. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/analysis/__init__.py +0 -0
  13. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/analysis/state_space.py +0 -0
  14. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/analysis/state_space_process.py +0 -0
  15. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/citation.py +0 -0
  16. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/cli.py +0 -0
  17. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/1 Petri nets/Exercise 1.1 Order handling/answer.pnml +0 -0
  18. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/1 Petri nets/Exercise 1.1 Order handling/question.md +0 -0
  19. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/2 Soundness/Exercise 2.1 Spot the flaw/answer.pnml +0 -0
  20. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/2 Soundness/Exercise 2.1 Spot the flaw/net.pnml +0 -0
  21. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/2 Soundness/Exercise 2.1 Spot the flaw/question.md +0 -0
  22. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/3 Discovery/Exercise 3.1 The alpha-algorithm/log.txt +0 -0
  23. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/3 Discovery/Exercise 3.1 The alpha-algorithm/question.md +0 -0
  24. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/4 Regions/Exercise 4.1 Regions of a transition system/question.md +0 -0
  25. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/4 Regions/Exercise 4.1 Regions of a transition system/ts.txt +0 -0
  26. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/5 Markings/Exercise 5.1 Markings and matrices/net.pnml +0 -0
  27. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/5 Markings/Exercise 5.1 Markings and matrices/question.md +0 -0
  28. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/6 Inductive Miner/Exercise 6.1 Cuts and trees/log.txt +0 -0
  29. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/6 Inductive Miner/Exercise 6.1 Cuts and trees/question.md +0 -0
  30. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/log.txt +0 -0
  31. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/m1.pnml +0 -0
  32. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/m2.pnml +0 -0
  33. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/m3.pnml +0 -0
  34. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/net.pnml +0 -0
  35. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/question.md +0 -0
  36. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/exercises/pack.md +0 -0
  37. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/__init__.py +0 -0
  38. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/box.py +0 -0
  39. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/__init__.py +0 -0
  40. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/check.py +0 -0
  41. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/compare.py +0 -0
  42. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/cpn.py +0 -0
  43. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/discover.py +0 -0
  44. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/filter.py +0 -0
  45. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/input.py +0 -0
  46. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/output.py +0 -0
  47. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/predict.py +0 -0
  48. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/science.py +0 -0
  49. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/boxes/sweeps.py +0 -0
  50. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/convert.py +0 -0
  51. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/datasets.py +0 -0
  52. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/explain.py +0 -0
  53. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/figures.py +0 -0
  54. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/history.py +0 -0
  55. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/library.py +0 -0
  56. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/provenance.py +0 -0
  57. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/record.py +0 -0
  58. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/report.py +0 -0
  59. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/reproducibility.py +0 -0
  60. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/runner.py +0 -0
  61. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/script.py +0 -0
  62. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/snapshots.py +0 -0
  63. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/sweep.py +0 -0
  64. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/types.py +0 -0
  65. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/flow/workflow.py +0 -0
  66. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/__init__.py +0 -0
  67. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/app.py +0 -0
  68. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/arc_editing.py +0 -0
  69. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/canvas.py +0 -0
  70. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/__init__.py +0 -0
  71. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/canvas.py +0 -0
  72. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/page.py +0 -0
  73. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/picker.py +0 -0
  74. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/runs.py +0 -0
  75. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/stepper.py +0 -0
  76. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/summary.py +0 -0
  77. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/flow/templates.py +0 -0
  78. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/items.py +0 -0
  79. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/learn/answer_boxes.py +0 -0
  80. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/learn/concealment.py +0 -0
  81. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/learn/mode.py +0 -0
  82. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/panning.py +0 -0
  83. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/resources/openprocess-icon.png +0 -0
  84. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/__init__.py +0 -0
  85. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/__main__.py +0 -0
  86. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/alignment_view.py +0 -0
  87. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/app.py +0 -0
  88. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/charts.py +0 -0
  89. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/cite.py +0 -0
  90. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/command_palette.py +0 -0
  91. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/compare_page.py +0 -0
  92. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/connections.py +0 -0
  93. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/cpn_page.py +0 -0
  94. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/definition_view.py +0 -0
  95. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/derivation_view.py +0 -0
  96. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/documents.py +0 -0
  97. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/dotted_chart.py +0 -0
  98. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/file_dialogs.py +0 -0
  99. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/filter_dialog.py +0 -0
  100. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/graph_builders.py +0 -0
  101. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/graph_view.py +0 -0
  102. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/instances.py +0 -0
  103. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/loading.py +0 -0
  104. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/log_editor.py +0 -0
  105. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/log_page.py +0 -0
  106. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/markdown_view.py +0 -0
  107. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/mathtext.py +0 -0
  108. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/ml_highlighter.py +0 -0
  109. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/model_page.py +0 -0
  110. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/motion.py +0 -0
  111. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/net_comparison.py +0 -0
  112. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/notes_overlay.py +0 -0
  113. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/petri_page.py +0 -0
  114. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/provenance.py +0 -0
  115. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/regions_view.py +0 -0
  116. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/sidebar.py +0 -0
  117. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/spaces.py +0 -0
  118. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/style.py +0 -0
  119. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/tool_icons.py +0 -0
  120. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/updates.py +0 -0
  121. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/widgets.py +0 -0
  122. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/workers.py +0 -0
  123. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/studio/workspace.py +0 -0
  124. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/theme.py +0 -0
  125. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/gui/tidy.py +0 -0
  126. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/io/__init__.py +0 -0
  127. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/io/cpn_reader.py +0 -0
  128. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/io/cpn_writer.py +0 -0
  129. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/__init__.py +0 -0
  130. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/answers.py +0 -0
  131. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/checks.py +0 -0
  132. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/computed.py +0 -0
  133. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/context.py +0 -0
  134. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/exam.py +0 -0
  135. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/exercise-packs.md +0 -0
  136. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/importer.py +0 -0
  137. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/notation.py +0 -0
  138. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/pack.py +0 -0
  139. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/learn/sheet.py +0 -0
  140. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/__init__.py +0 -0
  141. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/analysis.py +0 -0
  142. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/cases.py +0 -0
  143. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/columns.py +0 -0
  144. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/compare_nets.py +0 -0
  145. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/conformance/__init__.py +0 -0
  146. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/conformance/alignments.py +0 -0
  147. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/conformance/quality.py +0 -0
  148. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/conformance/token_replay.py +0 -0
  149. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/csv_import.py +0 -0
  150. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/definitions.py +0 -0
  151. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/dfg.py +0 -0
  152. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/discovery/__init__.py +0 -0
  153. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/discovery/alpha.py +0 -0
  154. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/discovery/heuristics.py +0 -0
  155. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/discovery/inductive.py +0 -0
  156. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/discovery/state_regions.py +0 -0
  157. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/filtering.py +0 -0
  158. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/footprint.py +0 -0
  159. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/invariants.py +0 -0
  160. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/layout.py +0 -0
  161. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/log.py +0 -0
  162. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/ocel.py +0 -0
  163. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/petrinet.py +0 -0
  164. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/playout.py +0 -0
  165. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/pm4py_bridge.py +0 -0
  166. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/pnml.py +0 -0
  167. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/processtree.py +0 -0
  168. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/regions.py +0 -0
  169. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/stats.py +0 -0
  170. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/structure.py +0 -0
  171. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/transition_system.py +0 -0
  172. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/mining/xes.py +0 -0
  173. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/__init__.py +0 -0
  174. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/ast_nodes.py +0 -0
  175. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/builtins.py +0 -0
  176. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/colorsets.py +0 -0
  177. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/errors.py +0 -0
  178. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/evaluator.py +0 -0
  179. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/lexer.py +0 -0
  180. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/multiset.py +0 -0
  181. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/parser.py +0 -0
  182. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/ml/values.py +0 -0
  183. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/model/__init__.py +0 -0
  184. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/model/declarations.py +0 -0
  185. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/model/examples.py +0 -0
  186. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/model/net.py +0 -0
  187. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/model/plain.py +0 -0
  188. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/packages.py +0 -0
  189. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/palette.py +0 -0
  190. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/references.py +0 -0
  191. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/sim/__init__.py +0 -0
  192. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/sim/binding.py +0 -0
  193. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/sim/export.py +0 -0
  194. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/sim/simulator.py +0 -0
  195. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/teaching/__init__.py +0 -0
  196. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/teaching/answers.py +0 -0
  197. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/teaching/checks.py +0 -0
  198. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/teaching/pack.py +0 -0
  199. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess/teaching/sheet.py +0 -0
  200. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess.egg-info/SOURCES.txt +0 -0
  201. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess.egg-info/dependency_links.txt +0 -0
  202. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess.egg-info/entry_points.txt +0 -0
  203. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess.egg-info/requires.txt +0 -0
  204. {openprocess-0.12.1 → openprocess-0.12.2}/openprocess.egg-info/top_level.txt +0 -0
  205. {openprocess-0.12.1 → openprocess-0.12.2}/pyproject.toml +0 -0
  206. {openprocess-0.12.1 → openprocess-0.12.2}/setup.cfg +0 -0
  207. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_arc_editing.py +0 -0
  208. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_citation.py +0 -0
  209. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_colorsets.py +0 -0
  210. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_columns.py +0 -0
  211. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_cpn_course_model.py +0 -0
  212. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_definitions.py +0 -0
  213. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_docs.py +0 -0
  214. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_exercises_gui.py +0 -0
  215. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_flow.py +0 -0
  216. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_framework_contract.py +0 -0
  217. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_hierarchy.py +0 -0
  218. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_history.py +0 -0
  219. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_io.py +0 -0
  220. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_large_logs.py +0 -0
  221. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_learn.py +0 -0
  222. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_learn_gui.py +0 -0
  223. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_log_editing.py +0 -0
  224. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_mining.py +0 -0
  225. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_ml.py +0 -0
  226. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_multiset.py +0 -0
  227. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_ocel.py +0 -0
  228. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_packages.py +0 -0
  229. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_regions.py +0 -0
  230. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_rename.py +0 -0
  231. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_report.py +0 -0
  232. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_simulation.py +0 -0
  233. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_snapshots.py +0 -0
  234. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_state_space.py +0 -0
  235. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_studio_gui.py +0 -0
  236. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_teaching.py +0 -0
  237. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_tidy.py +0 -0
  238. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_updates.py +0 -0
  239. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_wf_structure.py +0 -0
  240. {openprocess-0.12.1 → openprocess-0.12.2}/tests/test_workspace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openprocess
3
- Version: 0.12.1
3
+ Version: 0.12.2
4
4
  Summary: Process mining, Petri nets and workflows in one open app: every algorithm visible, every result reproducible, every step teachable
5
5
  Author: Sam Struthers
6
6
  License: MIT
@@ -48,7 +48,7 @@ from .sim.simulator import Simulator
48
48
  #: The one place the version number is written (pyproject.toml, the update
49
49
  #: check and packaging/build.py read it from here). A release is tagged
50
50
  #: "v" + this, e.g. v0.2.0.
51
- __version__ = "0.12.1"
51
+ __version__ = "0.12.2"
52
52
 
53
53
  __all__ = [
54
54
  "Arc", "BindingElement", "CPNet", "Marking", "Multiset", "Page", "Place",
@@ -20,7 +20,7 @@ from typing import Literal
20
20
 
21
21
  from ... import flow
22
22
  from ...mining.cases import case_value, cases
23
- from ...mining.dotted import SORT_MODES, X_MODES, DotSettings, Dots, svg
23
+ from ...mining.dotted import SORT_MODES, X_MODES, DotSettings, Dots, how_to_read, svg
24
24
  from ...mining.log import EventLog
25
25
  from ...mining.petrinet import PetriNet
26
26
  from ..box import box
@@ -229,8 +229,7 @@ def dotted_chart(log: EventLog,
229
229
  f"{dots.origin + timedelta(seconds=dots.x_max - dots.x_min):%d %b %Y %H:%M}")
230
230
  title = f"{log.name}: {rows.lower()} by {X_MODES[dots.mode].lower()}, colour by {colour.lower()}"
231
231
  return Figure("Dotted chart", svg=svg(dots, title, unit),
232
- caption=f"Dotted chart: rows {rows}, x {X_MODES[dots.mode]}, colour {colour}, "
233
- f"sorted by {sort.lower()}.")
232
+ caption=f"{how_to_read(settings, dots.mode)} Colour: {colour}.")
234
233
 
235
234
 
236
235
  @box(name="Who does what", group="Measure")
@@ -398,17 +398,10 @@ def result_widget(value, page=None, node=None) -> QWidget:
398
398
  if value.note:
399
399
  add(label(value.note, "muted", wrap=True))
400
400
  elif isinstance(value, Figure):
401
- shown = False
401
+ shown, svg = False, None
402
402
  if value.svg:
403
403
  try:
404
- from PySide6.QtSvgWidgets import QSvgWidget
405
- svg = QSvgWidget()
406
- svg.load(value.svg.encode("utf-8"))
407
- svg.setMinimumHeight(260)
408
- svg.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
409
- size = svg.renderer().defaultSize()
410
- if size.width() > 0:
411
- svg.setMaximumHeight(int(min(600, max(260, size.height() * 1.4))))
404
+ svg = SvgFigure(value.svg)
412
405
  add(svg)
413
406
  shown = True
414
407
  except ImportError:
@@ -425,8 +418,11 @@ def result_widget(value, page=None, node=None) -> QWidget:
425
418
  add(label("The figure has no SVG or PNG form.", "muted"))
426
419
  if value.caption:
427
420
  add(label(value.caption, "muted", wrap=True))
421
+ buttons = [button("Open larger", lambda: open_figure(value, svg))] if value.svg and shown else []
428
422
  if page is not None:
429
- add(hbox(button("Save as SVG…", lambda: page.save_figure(value)), None))
423
+ buttons.append(button("Save as SVG…", lambda: page.save_figure(value)))
424
+ if buttons:
425
+ add(hbox(*buttons, None))
430
426
  elif isinstance(value, Text):
431
427
  text = QPlainTextEdit(value.text)
432
428
  text.setReadOnly(True)
@@ -1047,3 +1043,75 @@ def status_text(result: Result | None) -> tuple[str, str]:
1047
1043
  if result.status == "blocked":
1048
1044
  return result.message or "Not allowed to run yet", "warning"
1049
1045
  return result.message or "Waiting", "muted"
1046
+
1047
+
1048
+ class SvgFigure(QWidget):
1049
+ """An SVG figure drawn at the width it is given and in its own
1050
+ proportions, never stretched: text stays readable and nothing is cut
1051
+ off. Click it to see it at full size."""
1052
+
1053
+ def __init__(self, svg: str, parent=None) -> None:
1054
+ from PySide6.QtSvg import QSvgRenderer
1055
+ super().__init__(parent)
1056
+ self.renderer = QSvgRenderer(svg.encode("utf-8"), self)
1057
+ size = self.renderer.defaultSize()
1058
+ self.ratio = size.height() / size.width() if size.width() > 0 else 0.6
1059
+ self.svg = svg
1060
+ policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
1061
+ policy.setHeightForWidth(True)
1062
+ self.setSizePolicy(policy)
1063
+ self.setMinimumWidth(200)
1064
+ self.setCursor(Qt.PointingHandCursor)
1065
+ self.setToolTip("Click to see the figure at full size")
1066
+
1067
+ def hasHeightForWidth(self) -> bool:
1068
+ return True
1069
+
1070
+ def heightForWidth(self, width: int) -> int:
1071
+ return max(1, round(width * self.ratio))
1072
+
1073
+ def sizeHint(self):
1074
+ from PySide6.QtCore import QSize
1075
+ size = self.renderer.defaultSize()
1076
+ return QSize(size.width(), size.height()) if size.width() > 0 else QSize(560, 336)
1077
+
1078
+ def paintEvent(self, event) -> None:
1079
+ from PySide6.QtCore import QRectF
1080
+ from PySide6.QtGui import QPainter
1081
+ painter = QPainter(self)
1082
+ painter.setRenderHint(QPainter.Antialiasing)
1083
+ width = min(self.width(), round(self.height() / self.ratio)) if self.ratio else self.width()
1084
+ height = round(width * self.ratio)
1085
+ self.renderer.render(painter, QRectF((self.width() - width) / 2, 0, width, height))
1086
+ painter.end()
1087
+
1088
+ def mouseReleaseEvent(self, event) -> None:
1089
+ if event.button() == Qt.LeftButton:
1090
+ open_figure(None, self)
1091
+ super().mouseReleaseEvent(event)
1092
+
1093
+
1094
+ def open_figure(figure, widget: "SvgFigure | None") -> None:
1095
+ """The figure in a window of its own, as large as the screen allows;
1096
+ resizing the window resizes the figure, in proportion."""
1097
+ if widget is None:
1098
+ return
1099
+ window = QDialog(widget.window())
1100
+ window.setWindowTitle(getattr(figure, "name", None) or "Figure")
1101
+ full = SvgFigure(widget.svg)
1102
+ full.setCursor(Qt.ArrowCursor)
1103
+ full.setToolTip("")
1104
+ full.mouseReleaseEvent = lambda event: None
1105
+ full.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
1106
+ layout = QVBoxLayout(window)
1107
+ layout.setContentsMargins(12, 12, 12, 12)
1108
+ layout.addWidget(full)
1109
+ size = full.sizeHint()
1110
+ width, height = size.width() + 24, size.height() + 24
1111
+ screen = widget.screen().availableGeometry() if widget.screen() else None
1112
+ if screen is not None:
1113
+ scale = min(1.0, (screen.width() - 80) / width, (screen.height() - 80) / height)
1114
+ width, height = round(width * scale), round(height * scale)
1115
+ window.resize(width, height)
1116
+ window.setAttribute(Qt.WA_DeleteOnClose)
1117
+ window.show()
@@ -365,7 +365,7 @@ def svg(dots: Dots, title: str = "", unit: str = "Auto", width: int = 900) -> st
365
365
  legend_rows = (min(len(dots.colour_values), 9) + 2) // 3
366
366
  top = 34 + 18 * legend_rows
367
367
  bottom, right = 44, 16
368
- plot_h = min(max(n_rows * (16 if labelled else 0.5), 220), 620)
368
+ plot_h = min(max(n_rows * (16 if labelled else 0.5), 220), 440) # landscape: it fits a side panel
369
369
  plot_w = width - left - right
370
370
  height = top + plot_h + bottom
371
371
  x0, x1 = dots.x_min, dots.x_max
@@ -442,14 +442,40 @@ def svg(dots: Dots, title: str = "", unit: str = "Auto", width: int = 900) -> st
442
442
  # Legend: what each colour means, with how many events.
443
443
  items = [(CATEGORICAL_LIGHT[i], v, dots.colour_counts[v]) for i, v in enumerate(dots.colour_values[:8])]
444
444
  rest = dots.colour_values[8:]
445
- if rest:
446
- items.append((OTHER_LIGHT, f"Other ({len(rest)})", sum(dots.colour_counts[v] for v in rest)))
445
+ if rest: # name the grey values when there are few, so none is hidden
446
+ name = "Other: " + ", ".join(rest) if len(rest) <= 3 else f"Other ({len(rest)} values)"
447
+ items.append((OTHER_LIGHT, name, sum(dots.colour_counts[v] for v in rest)))
447
448
  column = (width - left - right) / 3
448
449
  for i, (fill, value, count) in enumerate(items):
449
450
  lx, ly = left + (i % 3) * column, 32 + (i // 3) * 18
450
- name = (value or "–") if len(value) <= 34 else value[:33] + "…"
451
+ name = (value or "–") if len(value) <= 48 else value[:47] + "…"
451
452
  out.append(f'<circle cx="{lx + 5:.1f}" cy="{ly - 4}" r="4.5" fill="{fill}"/>')
452
453
  out.append(f'<text x="{lx + 14:.1f}" y="{ly}" fill="#333">{_escape(name)} '
453
454
  f'<tspan fill="#888">{count:,}</tspan></text>')
454
455
  out.append("</svg>")
455
456
  return "\n".join(out)
457
+
458
+
459
+ def how_to_read(settings: DotSettings, mode: int) -> str:
460
+ """What the chart's axes mean and which patterns to look for, for the
461
+ x mode it was drawn in and its rows."""
462
+ by_case = settings.rows == "Case"
463
+ rows = ("Each row is a case and each dot one of its events" if by_case else
464
+ f"Each row is one value of {settings.rows} and each dot an event of it")
465
+ order = f"; rows are sorted by {SORT_MODES[settings.sort].lower()}" if by_case else ""
466
+ x = {
467
+ 0: ", at the time it happened. "
468
+ + ("The slope of the first dots is the arrival rate, vertical lines are events handled "
469
+ "together (batches), and horizontal gaps are cases waiting."
470
+ if by_case else
471
+ "Gaps are times it was not active (nights, weekends, days off), and vertical lines "
472
+ "are batches."),
473
+ 1: ", at the time since its case began, so every case starts at 0. Compare how long each "
474
+ "step takes after the start; long horizontal gaps are waiting.",
475
+ 2: ", at its share of the case's duration (0 % the first event, 100 % the last), so cases "
476
+ "of different lengths line up: a column shows where in a case something usually happens.",
477
+ 3: ", at its place among all events of the log ordered by time: actual time without the gaps.",
478
+ 4: ", at its position in the case (0 is the first event): which step comes where, whatever "
479
+ "the time.",
480
+ }[mode]
481
+ return f"{rows}{order}{x}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openprocess
3
- Version: 0.12.1
3
+ Version: 0.12.2
4
4
  Summary: Process mining, Petri nets and workflows in one open app: every algorithm visible, every result reproducible, every step teachable
5
5
  Author: Sam Struthers
6
6
  License: MIT
@@ -1442,3 +1442,12 @@ def test_alignments_show_as_chevrons_and_on_the_model(app):
1442
1442
  assert len(lists) == 1 and lists[0].model().rowCount() == 3
1443
1443
  widget.resize(900, 900)
1444
1444
  widget.grab()
1445
+
1446
+
1447
+ def test_a_figure_keeps_its_proportions_at_any_width(app):
1448
+ """A figure in the Result panel is never stretched: its height follows its width."""
1449
+ from openprocess.gui.flow.viewers import SvgFigure
1450
+ figure = SvgFigure('<svg xmlns="http://www.w3.org/2000/svg" width="900" height="450" viewBox="0 0 900 450">'
1451
+ '<rect width="900" height="450" fill="white"/></svg>')
1452
+ assert figure.hasHeightForWidth()
1453
+ assert figure.heightForWidth(380) == 190 and figure.heightForWidth(900) == 450
@@ -86,6 +86,8 @@ def test_dotted_chart_draws_one_dot_per_event():
86
86
  # Dots on the same spot in the same colour are drawn once: u1 creates all four orders on day 0.
87
87
  by_user = dotted_chart(purchase_log(), rows="User", colour="Activity")
88
88
  assert by_user.svg.count('r="3.0"') == 13 and ">u2</text>" in by_user.svg
89
+ # Five activities fit the palette; the caption says how to read the chart.
90
+ assert "Other" not in figure.svg and "arrival rate" in figure.caption
89
91
  # Without timestamps the chart falls back to the position in the case.
90
92
  untimed = dotted_chart(EventLog.from_simple_log(parse_simple_log("[<a,b,c>^2, <a,c>]")), x="Actual time")
91
93
  assert "Event position in the case" in untimed.svg and untimed.svg.count('r="3.0"') == 8
File without changes
File without changes