dynamic-systems-testing-framework 1.0.1__py3-none-any.whl

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 (185) hide show
  1. dstf/__init__.py +41 -0
  2. dstf/__main__.py +10 -0
  3. dstf/authoring/__init__.py +13 -0
  4. dstf/authoring/builtin/__init__.py +32 -0
  5. dstf/authoring/builtin/accept.py +205 -0
  6. dstf/authoring/builtin/edit_criteria.py +479 -0
  7. dstf/authoring/builtin/edit_family.py +228 -0
  8. dstf/authoring/builtin/edit_on_plot.py +1354 -0
  9. dstf/authoring/builtin/edit_tree.py +1399 -0
  10. dstf/authoring/builtin/enqueue.py +144 -0
  11. dstf/authoring/capabilities.py +463 -0
  12. dstf/authoring/errors.py +49 -0
  13. dstf/authoring/family_rows.py +526 -0
  14. dstf/authoring/forms.py +631 -0
  15. dstf/authoring/layout.py +104 -0
  16. dstf/authoring/live_rows.py +337 -0
  17. dstf/authoring/live_runs.py +385 -0
  18. dstf/authoring/needle.py +127 -0
  19. dstf/authoring/picker_rows.py +92 -0
  20. dstf/authoring/queue_rows.py +354 -0
  21. dstf/authoring/session.py +3016 -0
  22. dstf/authoring/shell/__init__.py +9 -0
  23. dstf/authoring/shell/actions.py +702 -0
  24. dstf/authoring/shell/app.py +53 -0
  25. dstf/authoring/shell/drawer_controls.py +190 -0
  26. dstf/authoring/shell/family_fold.py +468 -0
  27. dstf/authoring/shell/figure_hook.py +249 -0
  28. dstf/authoring/shell/grips.js +1000 -0
  29. dstf/authoring/shell/header.py +783 -0
  30. dstf/authoring/shell/live_view.py +93 -0
  31. dstf/authoring/shell/picker.py +267 -0
  32. dstf/authoring/shell/placing.py +122 -0
  33. dstf/authoring/shell/plot_card.py +1171 -0
  34. dstf/authoring/shell/queue_panel.py +433 -0
  35. dstf/authoring/shell/rail.py +593 -0
  36. dstf/authoring/shell/shell.py +528 -0
  37. dstf/authoring/shell/stats_card.py +501 -0
  38. dstf/authoring/shell/strip.py +204 -0
  39. dstf/authoring/shell/style.py +721 -0
  40. dstf/authoring/shell/suite.py +277 -0
  41. dstf/authoring/shell/suite_grid.js +414 -0
  42. dstf/authoring/shell/suite_grid.py +373 -0
  43. dstf/authoring/shell/tab_theme.py +110 -0
  44. dstf/authoring/shell/tabstate.py +146 -0
  45. dstf/authoring/shell/test_list.py +179 -0
  46. dstf/authoring/shell/test_page.py +1404 -0
  47. dstf/authoring/shell/tree_card.py +1171 -0
  48. dstf/authoring/shell/variables_drawer.py +589 -0
  49. dstf/authoring/shell/widgets.py +188 -0
  50. dstf/authoring/situation.py +287 -0
  51. dstf/authoring/spec_document.py +215 -0
  52. dstf/authoring/spec_preview.py +83 -0
  53. dstf/authoring/suite_rows.py +99 -0
  54. dstf/authoring/tree_move.py +516 -0
  55. dstf/authoring/tree_pointer.py +33 -0
  56. dstf/authoring/tree_text.py +61 -0
  57. dstf/authoring/typed_number.js +64 -0
  58. dstf/authoring/typed_number.py +76 -0
  59. dstf/authoring/unscorable.py +141 -0
  60. dstf/authoring/variable_rows.py +216 -0
  61. dstf/backends/__init__.py +283 -0
  62. dstf/backends/base.py +1117 -0
  63. dstf/backends/common/__init__.py +1 -0
  64. dstf/backends/common/json_driver.py +484 -0
  65. dstf/backends/common/live_mat.py +369 -0
  66. dstf/backends/common/mat_reader.py +632 -0
  67. dstf/backends/common/proc_kill.py +238 -0
  68. dstf/backends/common/proc_output.py +20 -0
  69. dstf/backends/common/result_files.py +109 -0
  70. dstf/backends/common/result_variables.py +329 -0
  71. dstf/backends/common/statistics.py +39 -0
  72. dstf/backends/cross_backend.py +193 -0
  73. dstf/backends/dymola/__init__.py +5 -0
  74. dstf/backends/dymola/backend.py +776 -0
  75. dstf/backends/dymola/interface_loader.py +241 -0
  76. dstf/backends/dymola/log_parser.py +396 -0
  77. dstf/backends/dymola/persistent_backend.py +949 -0
  78. dstf/backends/fmpy/__init__.py +11 -0
  79. dstf/backends/fmpy/backend.py +443 -0
  80. dstf/backends/julia/__init__.py +27 -0
  81. dstf/backends/julia/backend.py +156 -0
  82. dstf/backends/julia/persistent_backend.py +541 -0
  83. dstf/backends/julia/run_persistent.jl +167 -0
  84. dstf/backends/julia/run_test.jl +146 -0
  85. dstf/backends/openmodelica/__init__.py +21 -0
  86. dstf/backends/openmodelica/backend.py +368 -0
  87. dstf/backends/openmodelica/init_xml.py +76 -0
  88. dstf/backends/openmodelica/log_parser.py +119 -0
  89. dstf/backends/openmodelica/mos_generator.py +228 -0
  90. dstf/backends/openmodelica/persistent_backend.py +1045 -0
  91. dstf/backends/openmodelica/session_loader.py +63 -0
  92. dstf/backends/persistent.py +1811 -0
  93. dstf/backends/pool.py +602 -0
  94. dstf/backends/progress.py +395 -0
  95. dstf/backends/python/__init__.py +11 -0
  96. dstf/backends/python/backend.py +141 -0
  97. dstf/backends/python/run_test.py +141 -0
  98. dstf/backends/run_metadata.py +103 -0
  99. dstf/backends/types.py +310 -0
  100. dstf/cli/__init__.py +12 -0
  101. dstf/cli/author_cmd.py +61 -0
  102. dstf/cli/baseline_cmds.py +341 -0
  103. dstf/cli/common.py +231 -0
  104. dstf/cli/diag_cmds.py +350 -0
  105. dstf/cli/main.py +561 -0
  106. dstf/cli/review.py +398 -0
  107. dstf/cli/run_cmds.py +589 -0
  108. dstf/cli/spec_cmds.py +123 -0
  109. dstf/comparison/__init__.py +13 -0
  110. dstf/comparison/algorithms.py +2127 -0
  111. dstf/comparison/builtins.py +291 -0
  112. dstf/comparison/comparator.py +1189 -0
  113. dstf/comparison/geometry.py +164 -0
  114. dstf/comparison/handles.py +1194 -0
  115. dstf/comparison/metric_tree.py +332 -0
  116. dstf/comparison/mode_schema.py +176 -0
  117. dstf/comparison/modes.py +788 -0
  118. dstf/comparison/registry.py +230 -0
  119. dstf/comparison/seeds.py +281 -0
  120. dstf/comparison/sides.py +158 -0
  121. dstf/comparison/snap.py +62 -0
  122. dstf/comparison/strict_keys.py +246 -0
  123. dstf/comparison/summaries.py +354 -0
  124. dstf/comparison/tree_eval.py +868 -0
  125. dstf/comparison/tree_spec.py +678 -0
  126. dstf/comparison/types.py +194 -0
  127. dstf/comparison/validator.py +232 -0
  128. dstf/config.py +815 -0
  129. dstf/discovery/__init__.py +0 -0
  130. dstf/discovery/json_recognizer.py +702 -0
  131. dstf/discovery/library_state.py +248 -0
  132. dstf/discovery/mo_parser.py +794 -0
  133. dstf/discovery/patch_apply.py +308 -0
  134. dstf/discovery/patch_envelope.py +63 -0
  135. dstf/discovery/plots.py +318 -0
  136. dstf/discovery/recognizer.py +103 -0
  137. dstf/discovery/scan_cache.py +154 -0
  138. dstf/discovery/spec_parser.py +538 -0
  139. dstf/discovery/spec_shape.py +122 -0
  140. dstf/discovery/spec_update.py +493 -0
  141. dstf/discovery/test_registry.py +488 -0
  142. dstf/discovery/unit_tests.py +95 -0
  143. dstf/figures/__init__.py +14 -0
  144. dstf/figures/assemble.py +48 -0
  145. dstf/figures/decimate.py +150 -0
  146. dstf/figures/families.py +289 -0
  147. dstf/figures/palette.py +170 -0
  148. dstf/figures/plotly.py +1413 -0
  149. dstf/figures/view.py +233 -0
  150. dstf/pipeline.py +435 -0
  151. dstf/plugins.py +104 -0
  152. dstf/reporting/__init__.py +0 -0
  153. dstf/reporting/console_report.py +187 -0
  154. dstf/reporting/context_builder.py +979 -0
  155. dstf/reporting/dashboard_render.py +534 -0
  156. dstf/reporting/junit_report.py +192 -0
  157. dstf/reporting/overlay_loader.py +708 -0
  158. dstf/reporting/report_suite.py +1059 -0
  159. dstf/reporting/rows.py +458 -0
  160. dstf/reporting/schema_export.py +413 -0
  161. dstf/reporting/stats_rows.py +321 -0
  162. dstf/reporting/status.py +388 -0
  163. dstf/reporting/templates/axes.js +61 -0
  164. dstf/reporting/templates/dashboard.html +284 -0
  165. dstf/reporting/templates/dashboard.js +604 -0
  166. dstf/reporting/templates/filters.js +100 -0
  167. dstf/reporting/templates/interactive.html +420 -0
  168. dstf/reporting/templates/report.js +116 -0
  169. dstf/reporting/templates/vendor/plotly.min.js +8 -0
  170. dstf/reporting/theme.py +324 -0
  171. dstf/reporting/tree_rows.py +73 -0
  172. dstf/reporting/verdicts.py +124 -0
  173. dstf/storage/__init__.py +0 -0
  174. dstf/storage/accept.py +216 -0
  175. dstf/storage/baseline.py +43 -0
  176. dstf/storage/batch_manifest.py +204 -0
  177. dstf/storage/ref_index.py +295 -0
  178. dstf/storage/reference_store.py +661 -0
  179. dstf/storage/roles.py +576 -0
  180. dstf/storage/run_stats.py +85 -0
  181. dynamic_systems_testing_framework-1.0.1.dist-info/METADATA +266 -0
  182. dynamic_systems_testing_framework-1.0.1.dist-info/RECORD +185 -0
  183. dynamic_systems_testing_framework-1.0.1.dist-info/WHEEL +4 -0
  184. dynamic_systems_testing_framework-1.0.1.dist-info/entry_points.txt +2 -0
  185. dynamic_systems_testing_framework-1.0.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,164 @@
1
+ """Geometry primitives: what a comparison mode scored against, as data.
2
+
3
+ Each :class:`~.types.VariableComparison` carries the primitives its mode
4
+ built while scoring — the tube band on the grid it was enforced on, the
5
+ checkpoint boxes, the declared bounds, the detected events, the spectra.
6
+ They are the single source every figure draws from (``dstf.figures``), so a
7
+ mode cannot draw one envelope and score another.
8
+
9
+ The vocabulary is deliberately small. A new kind of drawing is a new class
10
+ here plus one builder in ``dstf.figures.plotly``; that is cheaper than
11
+ smuggling a shape into :class:`Series`, which is the failure this file's
12
+ size guards against.
13
+
14
+ Ids are addresses. A mode emits LOCAL ids (``tube/band``, ``tube/upper/3``,
15
+ ``points/target/0``) — it does not know its leaf — and the evaluator
16
+ prefixes each with the leaf's RFC 6902 path (``/metrics/children/2``)
17
+ through :meth:`Primitive.prefixed`, so a figure handle and a patch op share
18
+ one name. ``kind`` is a free label the figure builder styles on:
19
+ ``"result"`` (what was computed), ``"handle"`` (the resolved position of an
20
+ authored parameter — a control point, a bound, a declared peak), ``"grip"``
21
+ (the resolved position of one SIDE of a tolerance; drawn only for the open
22
+ criterion in the tool, never as a trace and never in the report — four more
23
+ dots per checkpoint would sit on every report page), ``"ref"`` / ``"act"``
24
+ (which curve an event or spectrum belongs to), ``"matched"`` / ``"detected"``
25
+ (peak roles), ``"error"`` (the view's error series).
26
+
27
+ A grip's local id is ``<family>/<edge>/<key>`` — ``points/upper/3``,
28
+ ``events/late/0``, ``tube/lower/const`` — beside the handle it belongs to
29
+ (``points/target/3``): the edge says which side it is, and
30
+ :func:`grip_axis` / :func:`grip_outward` which way it moves.
31
+ """
32
+
33
+ from __future__ import annotations
34
+
35
+ from dataclasses import dataclass, replace
36
+ from typing import Literal
37
+
38
+ import numpy as np
39
+
40
+ Panel = Literal["time", "spectrum"]
41
+
42
+
43
+ @dataclass(frozen=True, kw_only=True, eq=False)
44
+ class Primitive:
45
+ id: str
46
+ kind: str = "result"
47
+ panel: Panel = "time"
48
+
49
+ def prefixed(self, prefix: str) -> Primitive:
50
+ """A copy whose id is ``<prefix>/<id>`` — the evaluator's stamp."""
51
+ return replace(self, id=f"{prefix}/{self.id}")
52
+
53
+
54
+ @dataclass(frozen=True, kw_only=True, eq=False)
55
+ class Band(Primitive):
56
+ """An envelope: ``lower[i] <= y <= upper[i]`` at ``time[i]``."""
57
+
58
+ time: np.ndarray
59
+ lower: np.ndarray
60
+ upper: np.ndarray
61
+
62
+
63
+ @dataclass(frozen=True, kw_only=True, eq=False)
64
+ class Box(Primitive):
65
+ """A rectangle ``[t0, t1] × [y0, y1]``. ``y0``/``y1`` of ``None`` span the panel."""
66
+
67
+ t0: float
68
+ t1: float
69
+ y0: float | None
70
+ y1: float | None
71
+ passed: bool | None = None
72
+
73
+
74
+ @dataclass(frozen=True, kw_only=True, eq=False)
75
+ class Marker(Primitive):
76
+ x: float
77
+ y: float
78
+ passed: bool | None = None
79
+
80
+
81
+ @dataclass(frozen=True, kw_only=True, eq=False)
82
+ class HLine(Primitive):
83
+ value: float
84
+ passed: bool | None = None
85
+
86
+
87
+ @dataclass(frozen=True, kw_only=True, eq=False)
88
+ class VLine(Primitive):
89
+ time: float
90
+
91
+
92
+ #: A grip's edge and the direction along its axis that is OUTWARD from the
93
+ #: target: ``+1`` towards larger values (or later times), ``-1`` the other
94
+ #: way. A lookup, not a default: an edge that is not here raises.
95
+ _GRIP_OUTWARD = {
96
+ "upper": 1,
97
+ "after": 1,
98
+ "late": 1,
99
+ "lower": -1,
100
+ "before": -1,
101
+ "early": -1,
102
+ }
103
+
104
+
105
+ def grip_edge(grip: Primitive) -> str:
106
+ """A grip's edge: the segment of its id before the last — ``upper`` of
107
+ ``…/points/upper/3``."""
108
+ return grip.id.split("/")[-2]
109
+
110
+
111
+ def grip_group(prim: Primitive) -> str:
112
+ """The grips that show together — a checkpoint's four, a window's two:
113
+ the id without its edge, ``…/points/3`` of ``…/points/upper/3``. The
114
+ handle they stand around reads the same way (``…/points/target/3``), so
115
+ a ring names the group of its own grips."""
116
+ parts = prim.id.split("/")
117
+ return "/".join(parts[:-2] + parts[-1:])
118
+
119
+
120
+ #: What a grip's arrow says of itself — its tooltip in the tool — by its
121
+ #: edge, in the side names the editor's fields use (a tolerance's − / +
122
+ #: read as lower / upper). A lookup, not a default, like `_GRIP_OUTWARD`.
123
+ _GRIP_LABELS = {
124
+ "upper": "Drag to set the upper tolerance",
125
+ "lower": "Drag to set the lower tolerance",
126
+ "before": "Drag to set how much before",
127
+ "after": "Drag to set how much after",
128
+ "early": "Drag to set how much earlier",
129
+ "late": "Drag to set how much later",
130
+ }
131
+
132
+
133
+ def grip_label(grip: Primitive) -> str:
134
+ """The one line a grip's arrow says of what dragging it sets."""
135
+ return _GRIP_LABELS[grip_edge(grip)]
136
+
137
+
138
+ def grip_outward(grip: Primitive) -> int:
139
+ """``+1`` or ``-1``: which way along :func:`grip_axis` leads AWAY from
140
+ the target — where the grip is drawn, just outside its edge."""
141
+ return _GRIP_OUTWARD[grip_edge(grip)]
142
+
143
+
144
+ def grip_axis(grip: Marker | VLine) -> Literal["x", "y"]:
145
+ """The ONE axis a grip moves on. A line stands at a time or a frequency:
146
+ x. A marker's ``upper`` and ``lower`` are the edges of a value: y; its
147
+ ``before`` and ``after`` those of a time: x."""
148
+ if isinstance(grip, VLine):
149
+ return "x"
150
+ return "y" if grip_edge(grip) in ("upper", "lower") else "x"
151
+
152
+
153
+ @dataclass(frozen=True, kw_only=True, eq=False)
154
+ class Series(Primitive):
155
+ x: np.ndarray
156
+ y: np.ndarray
157
+
158
+
159
+ @dataclass(frozen=True, kw_only=True, eq=False)
160
+ class Window(Primitive):
161
+ """The leaf's time window; either end ``None`` means open on that side."""
162
+
163
+ start: float | None
164
+ end: float | None