chronaxis 0.1.0.dev0__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 (917) hide show
  1. chronaxis/__init__.py +72 -0
  2. chronaxis/__main__.py +12 -0
  3. chronaxis/analysis_cli.py +181 -0
  4. chronaxis/batch/__init__.py +14 -0
  5. chronaxis/batch/api.py +46 -0
  6. chronaxis/batch/cli.py +48 -0
  7. chronaxis/batch/config.py +37 -0
  8. chronaxis/batch/models.py +202 -0
  9. chronaxis/batch/process_transport.py +149 -0
  10. chronaxis/batch/process_tree.py +72 -0
  11. chronaxis/batch/publication.py +41 -0
  12. chronaxis/batch/runner.py +236 -0
  13. chronaxis/batch/templates.py +42 -0
  14. chronaxis/can_dependencies.py +42 -0
  15. chronaxis/cli.py +193 -0
  16. chronaxis/configuration/__init__.py +46 -0
  17. chronaxis/configuration/cli.py +41 -0
  18. chronaxis/configuration/diagnostics.py +107 -0
  19. chronaxis/configuration/explanation.py +233 -0
  20. chronaxis/configuration/file_tools.py +140 -0
  21. chronaxis/configuration/imports.py +144 -0
  22. chronaxis/configuration/initialization.py +36 -0
  23. chronaxis/configuration/json_parser.py +114 -0
  24. chronaxis/configuration/models.py +74 -0
  25. chronaxis/configuration/origins.py +90 -0
  26. chronaxis/configuration/overrides.py +55 -0
  27. chronaxis/configuration/resolution.py +150 -0
  28. chronaxis/configuration/template_catalog.py +68 -0
  29. chronaxis/configuration/templates/batch/analysis-annotated.yaml +18 -0
  30. chronaxis/configuration/templates/batch/analysis-minimal.yaml +18 -0
  31. chronaxis/configuration/templates/batch/annotated.yaml +6 -0
  32. chronaxis/configuration/templates/batch/minimal.yaml +6 -0
  33. chronaxis/configuration/templates/can-asc/annotated.yaml +18 -0
  34. chronaxis/configuration/templates/can-asc/minimal.yaml +18 -0
  35. chronaxis/configuration/templates/can-blf/annotated.yaml +18 -0
  36. chronaxis/configuration/templates/can-blf/minimal.yaml +18 -0
  37. chronaxis/configuration/templates/can-export/annotated.yaml +23 -0
  38. chronaxis/configuration/templates/can-export/minimal.yaml +23 -0
  39. chronaxis/configuration/templates/catalog.json +233 -0
  40. chronaxis/configuration/templates/charge-session/annotated.yaml +38 -0
  41. chronaxis/configuration/templates/charge-session/minimal.yaml +38 -0
  42. chronaxis/configuration/templates/command-response/annotated.yaml +32 -0
  43. chronaxis/configuration/templates/command-response/minimal.yaml +36 -0
  44. chronaxis/configuration/templates/fault-window/annotated.yaml +25 -0
  45. chronaxis/configuration/templates/fault-window/minimal.yaml +27 -0
  46. chronaxis/configuration/templates/ini-mapping/annotated.yaml +20 -0
  47. chronaxis/configuration/templates/ini-mapping/minimal.yaml +20 -0
  48. chronaxis/configuration/templates/raw-can-csv/annotated.yaml +34 -0
  49. chronaxis/configuration/templates/raw-can-csv/minimal.yaml +35 -0
  50. chronaxis/configuration/templates/shared/charge-session.asc +5 -0
  51. chronaxis/configuration/templates/shared/command-response.asc +8 -0
  52. chronaxis/configuration/templates/shared/fault-window.asc +5 -0
  53. chronaxis/configuration/templates/shared/power.asc +7 -0
  54. chronaxis/configuration/templates/shared/sample.asc +6 -0
  55. chronaxis/configuration/templates/shared/sample.blf +0 -0
  56. chronaxis/configuration/templates/shared/sample.csv +5 -0
  57. chronaxis/configuration/templates/shared/sample.dbc +11 -0
  58. chronaxis/configuration/templates/shared/signals.csv +6 -0
  59. chronaxis/configuration/templates/shared/source.ini +5 -0
  60. chronaxis/configuration/templates/shared/stability.asc +9 -0
  61. chronaxis/configuration/templates/shared/teaching.dbc +27 -0
  62. chronaxis/configuration/templates/shared/threshold.asc +7 -0
  63. chronaxis/configuration/templates/signal-csv/annotated.yaml +27 -0
  64. chronaxis/configuration/templates/signal-csv/minimal.yaml +27 -0
  65. chronaxis/configuration/templates/signal-export/annotated.yaml +27 -0
  66. chronaxis/configuration/templates/signal-export/minimal.yaml +29 -0
  67. chronaxis/configuration/templates/stability/annotated.yaml +35 -0
  68. chronaxis/configuration/templates/stability/minimal.yaml +35 -0
  69. chronaxis/configuration/templates/threshold/annotated.yaml +22 -0
  70. chronaxis/configuration/templates/threshold/minimal.yaml +22 -0
  71. chronaxis/configuration/yaml_parser.py +125 -0
  72. chronaxis/core/__init__.py +71 -0
  73. chronaxis/core/binding.py +449 -0
  74. chronaxis/core/calculation_series_join.py +106 -0
  75. chronaxis/core/calculations.py +435 -0
  76. chronaxis/core/calculations_memory_numpy.py +136 -0
  77. chronaxis/core/calculations_memory_reference.py +165 -0
  78. chronaxis/core/calculations_numpy.py +298 -0
  79. chronaxis/core/calculations_reference.py +294 -0
  80. chronaxis/core/condition_evidence.py +182 -0
  81. chronaxis/core/conditional_integral_result.py +43 -0
  82. chronaxis/core/conditional_integral_terms.py +146 -0
  83. chronaxis/core/conditional_integral_terms_numpy.py +148 -0
  84. chronaxis/core/conditional_integral_terms_reference.py +111 -0
  85. chronaxis/core/conditional_time_reduction.py +118 -0
  86. chronaxis/core/conditional_time_reduction_numpy.py +223 -0
  87. chronaxis/core/conditional_time_reduction_reference.py +213 -0
  88. chronaxis/core/declarations.py +192 -0
  89. chronaxis/core/decoded_binding.py +197 -0
  90. chronaxis/core/direct_message.py +387 -0
  91. chronaxis/core/export_interpolation.py +54 -0
  92. chronaxis/core/expression.py +642 -0
  93. chronaxis/core/expression_numpy.py +314 -0
  94. chronaxis/core/expression_reference.py +272 -0
  95. chronaxis/core/integral_result.py +53 -0
  96. chronaxis/core/integral_sum.py +77 -0
  97. chronaxis/core/integral_sum_numpy.py +224 -0
  98. chronaxis/core/integral_sum_reference.py +148 -0
  99. chronaxis/core/integral_terms.py +119 -0
  100. chronaxis/core/integral_terms_numpy.py +127 -0
  101. chronaxis/core/integral_terms_reference.py +91 -0
  102. chronaxis/core/mean_weights_numpy.py +29 -0
  103. chronaxis/core/mean_weights_reference.py +27 -0
  104. chronaxis/core/message_binding.py +305 -0
  105. chronaxis/core/models.py +485 -0
  106. chronaxis/core/normalize_numpy.py +396 -0
  107. chronaxis/core/numeric.py +472 -0
  108. chronaxis/core/numeric_numpy.py +440 -0
  109. chronaxis/core/record_intervals.py +115 -0
  110. chronaxis/core/sample_reduction.py +161 -0
  111. chronaxis/core/sample_reduction_numpy.py +160 -0
  112. chronaxis/core/sample_reduction_reference.py +154 -0
  113. chronaxis/core/selection.py +74 -0
  114. chronaxis/core/sequence.py +160 -0
  115. chronaxis/core/sequence_reference.py +248 -0
  116. chronaxis/core/stability.py +249 -0
  117. chronaxis/core/start_end.py +169 -0
  118. chronaxis/core/state.py +494 -0
  119. chronaxis/core/state_numpy.py +296 -0
  120. chronaxis/core/temporal.py +373 -0
  121. chronaxis/core/temporal_clock.py +25 -0
  122. chronaxis/core/temporal_memory_numpy.py +163 -0
  123. chronaxis/core/temporal_memory_reference.py +161 -0
  124. chronaxis/core/temporal_numpy.py +345 -0
  125. chronaxis/core/temporal_reference.py +304 -0
  126. chronaxis/core/time_reduction.py +190 -0
  127. chronaxis/core/time_reduction_numpy.py +205 -0
  128. chronaxis/core/time_reduction_reference.py +203 -0
  129. chronaxis/core/types.py +105 -0
  130. chronaxis/core/units.py +81 -0
  131. chronaxis/core/validation.py +94 -0
  132. chronaxis/core/window_delta.py +123 -0
  133. chronaxis/core/window_delta_numpy.py +78 -0
  134. chronaxis/core/window_delta_reference.py +69 -0
  135. chronaxis/core/windows.py +224 -0
  136. chronaxis/core/windows_numpy.py +78 -0
  137. chronaxis/core/windows_reference.py +61 -0
  138. chronaxis/execution/__init__.py +6 -0
  139. chronaxis/execution/batch_signal_groups.py +122 -0
  140. chronaxis/execution/bindings.py +296 -0
  141. chronaxis/execution/boundaries.py +568 -0
  142. chronaxis/execution/calculation_blocks.py +338 -0
  143. chronaxis/execution/calculation_values.py +55 -0
  144. chronaxis/execution/can_batch_reader.py +356 -0
  145. chronaxis/execution/can_reader.py +948 -0
  146. chronaxis/execution/can_reference_template.py +61 -0
  147. chronaxis/execution/condition_evidence.py +370 -0
  148. chronaxis/execution/conditional_integral_facts.py +310 -0
  149. chronaxis/execution/conditional_integral_reduction.py +216 -0
  150. chronaxis/execution/csv_observation.py +524 -0
  151. chronaxis/execution/csv_reader.py +662 -0
  152. chronaxis/execution/current_message_calculation.py +225 -0
  153. chronaxis/execution/driver_expression.py +274 -0
  154. chronaxis/execution/expressions.py +618 -0
  155. chronaxis/execution/frame_capture.py +245 -0
  156. chronaxis/execution/groups.py +236 -0
  157. chronaxis/execution/historical_conditional_blocks.py +264 -0
  158. chronaxis/execution/historical_conditional_integral.py +226 -0
  159. chronaxis/execution/historical_conditional_time_calculation.py +368 -0
  160. chronaxis/execution/historical_integral.py +219 -0
  161. chronaxis/execution/historical_observation.py +372 -0
  162. chronaxis/execution/historical_sample_calculation.py +338 -0
  163. chronaxis/execution/historical_selection_rows.py +300 -0
  164. chronaxis/execution/historical_time_calculation.py +341 -0
  165. chronaxis/execution/history.py +572 -0
  166. chronaxis/execution/history_records.py +225 -0
  167. chronaxis/execution/hold.py +448 -0
  168. chronaxis/execution/integral_facts.py +311 -0
  169. chronaxis/execution/integral_reduction.py +216 -0
  170. chronaxis/execution/legacy_frame_samples.py +94 -0
  171. chronaxis/execution/memory_reader.py +247 -0
  172. chronaxis/execution/message_bindings.py +293 -0
  173. chronaxis/execution/message_delivery.py +37 -0
  174. chronaxis/execution/observed_ingestion.py +551 -0
  175. chronaxis/execution/raw_signal_groups.py +192 -0
  176. chronaxis/execution/record_alarm_duration.py +114 -0
  177. chronaxis/execution/record_delta_condition.py +167 -0
  178. chronaxis/execution/record_diagnostics.py +87 -0
  179. chronaxis/execution/record_event_durations.py +143 -0
  180. chronaxis/execution/record_export_samples.py +94 -0
  181. chronaxis/execution/record_exports.py +155 -0
  182. chronaxis/execution/record_integral.py +196 -0
  183. chronaxis/execution/record_point_buffer.py +101 -0
  184. chronaxis/execution/record_rule_timeline.py +344 -0
  185. chronaxis/execution/record_sample.py +46 -0
  186. chronaxis/execution/record_sample_series.py +29 -0
  187. chronaxis/execution/record_scope_calculations.py +290 -0
  188. chronaxis/execution/record_selection.py +62 -0
  189. chronaxis/execution/record_sequences.py +199 -0
  190. chronaxis/execution/record_session_calculations.py +778 -0
  191. chronaxis/execution/record_signal_export.py +133 -0
  192. chronaxis/execution/record_source_cursor.py +295 -0
  193. chronaxis/execution/record_time_calculation.py +322 -0
  194. chronaxis/execution/record_time_indexes.py +143 -0
  195. chronaxis/execution/record_value_history.py +160 -0
  196. chronaxis/execution/record_windows.py +229 -0
  197. chronaxis/execution/required_expression.py +52 -0
  198. chronaxis/execution/retained_metadata.py +71 -0
  199. chronaxis/execution/run_session.py +402 -0
  200. chronaxis/execution/scanned_signal_proof.py +550 -0
  201. chronaxis/execution/signal_validity.py +40 -0
  202. chronaxis/execution/state.py +280 -0
  203. chronaxis/execution/temporal_buffer.py +508 -0
  204. chronaxis/execution/text_can_reader.py +359 -0
  205. chronaxis/execution/timeline.py +309 -0
  206. chronaxis/execution/timeline_multi.py +415 -0
  207. chronaxis/execution/window_delta_events.py +220 -0
  208. chronaxis/execution/window_replay.py +350 -0
  209. chronaxis/execution/windows.py +173 -0
  210. chronaxis/guide/README.md +70 -0
  211. chronaxis/guide/api/AnalysisError.md +14 -0
  212. chronaxis/guide/api/AnalysisPlan.md +96 -0
  213. chronaxis/guide/api/AnalysisResult.md +398 -0
  214. chronaxis/guide/api/AnalysisRunner.md +155 -0
  215. chronaxis/guide/api/BatchJob.md +19 -0
  216. chronaxis/guide/api/BatchJobResult.md +61 -0
  217. chronaxis/guide/api/BatchPlan.md +48 -0
  218. chronaxis/guide/api/BatchReport.md +108 -0
  219. chronaxis/guide/api/BatchRunner.md +84 -0
  220. chronaxis/guide/api/OutputManifest.md +23 -0
  221. chronaxis/guide/api/PlanFragment.md +47 -0
  222. chronaxis/guide/api/PlanValidationError.md +98 -0
  223. chronaxis/guide/api/PresetSpec.md +63 -0
  224. chronaxis/guide/api/ResultClosedError.md +14 -0
  225. chronaxis/guide/api/RunMetadata.md +100 -0
  226. chronaxis/guide/api/TimeConversion.md +29 -0
  227. chronaxis/guide/api/TimeOverflowError.md +17 -0
  228. chronaxis/guide/api/build_preset.md +36 -0
  229. chronaxis/guide/api/checked_add_ns.md +30 -0
  230. chronaxis/guide/api/convert_time.md +40 -0
  231. chronaxis/guide/api/explain_analysis_plan.md +38 -0
  232. chronaxis/guide/api/index.json +185 -0
  233. chronaxis/guide/api/load_analysis_plan.md +34 -0
  234. chronaxis/guide/api/load_batch_plan.md +36 -0
  235. chronaxis/guide/api/parse_datetime_ns.md +35 -0
  236. chronaxis/guide/api/parse_duration.md +30 -0
  237. chronaxis/guide/api/resolve_preset_roles.md +37 -0
  238. chronaxis/guide/api/run_batch.md +38 -0
  239. chronaxis/guide/api/shift_times_reference.md +33 -0
  240. chronaxis/guide/api/time_deltas_reference.md +37 -0
  241. chronaxis/guide/api/validate_analysis_plan.md +38 -0
  242. chronaxis/guide/en/README.md +74 -0
  243. chronaxis/guide/en/api/AnalysisError.md +14 -0
  244. chronaxis/guide/en/api/AnalysisPlan.md +93 -0
  245. chronaxis/guide/en/api/AnalysisResult.md +398 -0
  246. chronaxis/guide/en/api/AnalysisRunner.md +191 -0
  247. chronaxis/guide/en/api/BatchJob.md +17 -0
  248. chronaxis/guide/en/api/BatchJobResult.md +43 -0
  249. chronaxis/guide/en/api/BatchPlan.md +37 -0
  250. chronaxis/guide/en/api/BatchReport.md +52 -0
  251. chronaxis/guide/en/api/BatchRunner.md +51 -0
  252. chronaxis/guide/en/api/OutputManifest.md +23 -0
  253. chronaxis/guide/en/api/PlanFragment.md +33 -0
  254. chronaxis/guide/en/api/PlanValidationError.md +58 -0
  255. chronaxis/guide/en/api/PresetSpec.md +51 -0
  256. chronaxis/guide/en/api/ResultClosedError.md +14 -0
  257. chronaxis/guide/en/api/RunMetadata.md +100 -0
  258. chronaxis/guide/en/api/TimeConversion.md +23 -0
  259. chronaxis/guide/en/api/TimeOverflowError.md +14 -0
  260. chronaxis/guide/en/api/build_preset.md +23 -0
  261. chronaxis/guide/en/api/checked_add_ns.md +21 -0
  262. chronaxis/guide/en/api/convert_time.md +25 -0
  263. chronaxis/guide/en/api/explain_analysis_plan.md +30 -0
  264. chronaxis/guide/en/api/index.json +185 -0
  265. chronaxis/guide/en/api/load_analysis_plan.md +27 -0
  266. chronaxis/guide/en/api/load_batch_plan.md +28 -0
  267. chronaxis/guide/en/api/parse_datetime_ns.md +23 -0
  268. chronaxis/guide/en/api/parse_duration.md +20 -0
  269. chronaxis/guide/en/api/resolve_preset_roles.md +23 -0
  270. chronaxis/guide/en/api/run_batch.md +39 -0
  271. chronaxis/guide/en/api/shift_times_reference.md +21 -0
  272. chronaxis/guide/en/api/time_deltas_reference.md +22 -0
  273. chronaxis/guide/en/api/validate_analysis_plan.md +29 -0
  274. chronaxis/guide/en/fields/analysis/calculations-all-1.json +345 -0
  275. chronaxis/guide/en/fields/analysis/calculations-all-2.json +300 -0
  276. chronaxis/guide/en/fields/analysis/calculations-all-3.json +84 -0
  277. chronaxis/guide/en/fields/analysis/config_version-all-1.json +24 -0
  278. chronaxis/guide/en/fields/analysis/dataset-all-1.json +344 -0
  279. chronaxis/guide/en/fields/analysis/derived-all-1.json +147 -0
  280. chronaxis/guide/en/fields/analysis/diagnostics-all-1.json +69 -0
  281. chronaxis/guide/en/fields/analysis/execution-all-1.json +167 -0
  282. chronaxis/guide/en/fields/analysis/imports-all-1.json +39 -0
  283. chronaxis/guide/en/fields/analysis/intervals-all-1.json +173 -0
  284. chronaxis/guide/en/fields/analysis/message_calculations-all-1.json +345 -0
  285. chronaxis/guide/en/fields/analysis/message_calculations-all-2.json +270 -0
  286. chronaxis/guide/en/fields/analysis/metadata-all-1.json +24 -0
  287. chronaxis/guide/en/fields/analysis/outputs-all-1.json +332 -0
  288. chronaxis/guide/en/fields/analysis/outputs-all-2.json +319 -0
  289. chronaxis/guide/en/fields/analysis/outputs-all-3.json +321 -0
  290. chronaxis/guide/en/fields/analysis/outputs-all-4.json +236 -0
  291. chronaxis/guide/en/fields/analysis/outputs-all-5.json +246 -0
  292. chronaxis/guide/en/fields/analysis/outputs-all-6.json +214 -0
  293. chronaxis/guide/en/fields/analysis/overrides-all-1.json +104 -0
  294. chronaxis/guide/en/fields/analysis/presets-charge_session-1.json +398 -0
  295. chronaxis/guide/en/fields/analysis/presets-charge_session-2.json +114 -0
  296. chronaxis/guide/en/fields/analysis/presets-command_response-1.json +376 -0
  297. chronaxis/guide/en/fields/analysis/presets-fault_context-1.json +285 -0
  298. chronaxis/guide/en/fields/analysis/presets-threshold_excursion-1.json +317 -0
  299. chronaxis/guide/en/fields/analysis/rules-condition_duration-1.json +344 -0
  300. chronaxis/guide/en/fields/analysis/rules-condition_duration-2.json +27 -0
  301. chronaxis/guide/en/fields/analysis/rules-debounce-1.json +335 -0
  302. chronaxis/guide/en/fields/analysis/rules-falling_edge-1.json +317 -0
  303. chronaxis/guide/en/fields/analysis/rules-hysteresis-1.json +334 -0
  304. chronaxis/guide/en/fields/analysis/rules-hysteresis-2.json +27 -0
  305. chronaxis/guide/en/fields/analysis/rules-rising_edge-1.json +317 -0
  306. chronaxis/guide/en/fields/analysis/rules-start_end-1.json +333 -0
  307. chronaxis/guide/en/fields/analysis/rules-start_end-2.json +60 -0
  308. chronaxis/guide/en/fields/analysis/rules-start_only-1.json +334 -0
  309. chronaxis/guide/en/fields/analysis/rules-window_delta-1.json +338 -0
  310. chronaxis/guide/en/fields/analysis/rules-window_delta-2.json +96 -0
  311. chronaxis/guide/en/fields/analysis/sequences-all-1.json +378 -0
  312. chronaxis/guide/en/fields/analysis/sequences-all-2.json +70 -0
  313. chronaxis/guide/en/fields/analysis/signals-variant-1-1.json +349 -0
  314. chronaxis/guide/en/fields/analysis/signals-variant-1-2.json +297 -0
  315. chronaxis/guide/en/fields/analysis/signals-variant-1-3.json +323 -0
  316. chronaxis/guide/en/fields/analysis/signals-variant-1-4.json +192 -0
  317. chronaxis/guide/en/fields/analysis/signals-variant-2-1.json +327 -0
  318. chronaxis/guide/en/fields/analysis/signals-variant-2-2.json +312 -0
  319. chronaxis/guide/en/fields/analysis/signals-variant-2-3.json +294 -0
  320. chronaxis/guide/en/fields/analysis/signals-variant-2-4.json +253 -0
  321. chronaxis/guide/en/fields/analysis/signals-variant-2-5.json +44 -0
  322. chronaxis/guide/en/fields/analysis/sources-can_asc-1.json +318 -0
  323. chronaxis/guide/en/fields/analysis/sources-can_asc-2.json +310 -0
  324. chronaxis/guide/en/fields/analysis/sources-can_asc-3.json +311 -0
  325. chronaxis/guide/en/fields/analysis/sources-can_asc-4.json +69 -0
  326. chronaxis/guide/en/fields/analysis/sources-can_blf-1.json +317 -0
  327. chronaxis/guide/en/fields/analysis/sources-can_blf-2.json +310 -0
  328. chronaxis/guide/en/fields/analysis/sources-can_blf-3.json +317 -0
  329. chronaxis/guide/en/fields/analysis/sources-memory-1.json +332 -0
  330. chronaxis/guide/en/fields/analysis/sources-memory-2.json +125 -0
  331. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-1.json +330 -0
  332. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-10.json +233 -0
  333. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-11.json +225 -0
  334. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-12.json +228 -0
  335. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-13.json +226 -0
  336. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-14.json +230 -0
  337. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-15.json +227 -0
  338. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-16.json +230 -0
  339. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-17.json +238 -0
  340. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-18.json +239 -0
  341. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-19.json +233 -0
  342. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-2.json +310 -0
  343. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-20.json +242 -0
  344. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-21.json +230 -0
  345. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-22.json +228 -0
  346. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-23.json +230 -0
  347. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-24.json +223 -0
  348. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-25.json +290 -0
  349. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-26.json +131 -0
  350. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-3.json +297 -0
  351. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-4.json +226 -0
  352. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-5.json +230 -0
  353. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-6.json +227 -0
  354. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-7.json +230 -0
  355. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-8.json +238 -0
  356. chronaxis/guide/en/fields/analysis/sources-raw_can_csv-9.json +239 -0
  357. chronaxis/guide/en/fields/analysis/sources-signal_csv-1.json +331 -0
  358. chronaxis/guide/en/fields/analysis/sources-signal_csv-2.json +307 -0
  359. chronaxis/guide/en/fields/analysis/sources-signal_csv-3.json +315 -0
  360. chronaxis/guide/en/fields/analysis/sources-variant-6-1.json +319 -0
  361. chronaxis/guide/en/fields/analysis/sources-variant-6-2.json +307 -0
  362. chronaxis/guide/en/fields/analysis/sources-variant-6-3.json +312 -0
  363. chronaxis/guide/en/fields/analysis/sources-variant-6-4.json +113 -0
  364. chronaxis/guide/en/fields/analysis/windows-all-1.json +361 -0
  365. chronaxis/guide/en/fields/analysis/windows-all-2.json +187 -0
  366. chronaxis/guide/en/fields/batch/backend-all-1.json +26 -0
  367. chronaxis/guide/en/fields/batch/batch_version-all-1.json +22 -0
  368. chronaxis/guide/en/fields/batch/fail_fast-all-1.json +22 -0
  369. chronaxis/guide/en/fields/batch/inputs-all-1.json +161 -0
  370. chronaxis/guide/en/fields/batch/jobs-all-1.json +58 -0
  371. chronaxis/guide/en/fields/batch/process_count-all-1.json +23 -0
  372. chronaxis/guide/en/fields/batch/source-all-1.json +22 -0
  373. chronaxis/guide/en/fields/batch/template-all-1.json +22 -0
  374. chronaxis/guide/en/fields/definitions/derived-all-1.json +121 -0
  375. chronaxis/guide/en/fields/definitions/signals-all-1.json +336 -0
  376. chronaxis/guide/en/fields/definitions/signals-all-2.json +307 -0
  377. chronaxis/guide/en/fields/definitions/signals-all-3.json +290 -0
  378. chronaxis/guide/en/fields/definitions/signals-all-4.json +347 -0
  379. chronaxis/guide/en/fields/definitions/signals-all-5.json +297 -0
  380. chronaxis/guide/en/fields/definitions/signals-all-6.json +259 -0
  381. chronaxis/guide/en/fields/definitions/signals-all-7.json +117 -0
  382. chronaxis/guide/en/fields/definitions/sources-all-1.json +332 -0
  383. chronaxis/guide/en/fields/definitions/sources-all-10.json +306 -0
  384. chronaxis/guide/en/fields/definitions/sources-all-11.json +294 -0
  385. chronaxis/guide/en/fields/definitions/sources-all-12.json +212 -0
  386. chronaxis/guide/en/fields/definitions/sources-all-13.json +217 -0
  387. chronaxis/guide/en/fields/definitions/sources-all-14.json +213 -0
  388. chronaxis/guide/en/fields/definitions/sources-all-15.json +214 -0
  389. chronaxis/guide/en/fields/definitions/sources-all-16.json +215 -0
  390. chronaxis/guide/en/fields/definitions/sources-all-17.json +213 -0
  391. chronaxis/guide/en/fields/definitions/sources-all-18.json +214 -0
  392. chronaxis/guide/en/fields/definitions/sources-all-19.json +213 -0
  393. chronaxis/guide/en/fields/definitions/sources-all-2.json +323 -0
  394. chronaxis/guide/en/fields/definitions/sources-all-20.json +217 -0
  395. chronaxis/guide/en/fields/definitions/sources-all-21.json +210 -0
  396. chronaxis/guide/en/fields/definitions/sources-all-22.json +214 -0
  397. chronaxis/guide/en/fields/definitions/sources-all-23.json +218 -0
  398. chronaxis/guide/en/fields/definitions/sources-all-24.json +209 -0
  399. chronaxis/guide/en/fields/definitions/sources-all-25.json +215 -0
  400. chronaxis/guide/en/fields/definitions/sources-all-26.json +218 -0
  401. chronaxis/guide/en/fields/definitions/sources-all-27.json +224 -0
  402. chronaxis/guide/en/fields/definitions/sources-all-28.json +215 -0
  403. chronaxis/guide/en/fields/definitions/sources-all-29.json +205 -0
  404. chronaxis/guide/en/fields/definitions/sources-all-3.json +303 -0
  405. chronaxis/guide/en/fields/definitions/sources-all-30.json +298 -0
  406. chronaxis/guide/en/fields/definitions/sources-all-31.json +315 -0
  407. chronaxis/guide/en/fields/definitions/sources-all-32.json +306 -0
  408. chronaxis/guide/en/fields/definitions/sources-all-33.json +209 -0
  409. chronaxis/guide/en/fields/definitions/sources-all-4.json +336 -0
  410. chronaxis/guide/en/fields/definitions/sources-all-5.json +299 -0
  411. chronaxis/guide/en/fields/definitions/sources-all-6.json +307 -0
  412. chronaxis/guide/en/fields/definitions/sources-all-7.json +320 -0
  413. chronaxis/guide/en/fields/definitions/sources-all-8.json +303 -0
  414. chronaxis/guide/en/fields/definitions/sources-all-9.json +315 -0
  415. chronaxis/guide/en/fields/index.json +3450 -0
  416. chronaxis/guide/en/fields/mapping/aliases-all-1.json +91 -0
  417. chronaxis/guide/en/fields/mapping/analysis-all-1.json +382 -0
  418. chronaxis/guide/en/fields/mapping/analysis-all-10.json +301 -0
  419. chronaxis/guide/en/fields/mapping/analysis-all-11.json +312 -0
  420. chronaxis/guide/en/fields/mapping/analysis-all-12.json +311 -0
  421. chronaxis/guide/en/fields/mapping/analysis-all-13.json +314 -0
  422. chronaxis/guide/en/fields/mapping/analysis-all-14.json +310 -0
  423. chronaxis/guide/en/fields/mapping/analysis-all-15.json +297 -0
  424. chronaxis/guide/en/fields/mapping/analysis-all-16.json +226 -0
  425. chronaxis/guide/en/fields/mapping/analysis-all-17.json +230 -0
  426. chronaxis/guide/en/fields/mapping/analysis-all-18.json +227 -0
  427. chronaxis/guide/en/fields/mapping/analysis-all-19.json +230 -0
  428. chronaxis/guide/en/fields/mapping/analysis-all-2.json +323 -0
  429. chronaxis/guide/en/fields/mapping/analysis-all-20.json +221 -0
  430. chronaxis/guide/en/fields/mapping/analysis-all-21.json +237 -0
  431. chronaxis/guide/en/fields/mapping/analysis-all-22.json +233 -0
  432. chronaxis/guide/en/fields/mapping/analysis-all-23.json +222 -0
  433. chronaxis/guide/en/fields/mapping/analysis-all-24.json +231 -0
  434. chronaxis/guide/en/fields/mapping/analysis-all-25.json +225 -0
  435. chronaxis/guide/en/fields/mapping/analysis-all-26.json +230 -0
  436. chronaxis/guide/en/fields/mapping/analysis-all-27.json +228 -0
  437. chronaxis/guide/en/fields/mapping/analysis-all-28.json +230 -0
  438. chronaxis/guide/en/fields/mapping/analysis-all-29.json +223 -0
  439. chronaxis/guide/en/fields/mapping/analysis-all-3.json +318 -0
  440. chronaxis/guide/en/fields/mapping/analysis-all-30.json +233 -0
  441. chronaxis/guide/en/fields/mapping/analysis-all-31.json +218 -0
  442. chronaxis/guide/en/fields/mapping/analysis-all-32.json +239 -0
  443. chronaxis/guide/en/fields/mapping/analysis-all-33.json +233 -0
  444. chronaxis/guide/en/fields/mapping/analysis-all-34.json +225 -0
  445. chronaxis/guide/en/fields/mapping/analysis-all-35.json +228 -0
  446. chronaxis/guide/en/fields/mapping/analysis-all-36.json +226 -0
  447. chronaxis/guide/en/fields/mapping/analysis-all-37.json +244 -0
  448. chronaxis/guide/en/fields/mapping/analysis-all-38.json +326 -0
  449. chronaxis/guide/en/fields/mapping/analysis-all-39.json +299 -0
  450. chronaxis/guide/en/fields/mapping/analysis-all-4.json +297 -0
  451. chronaxis/guide/en/fields/mapping/analysis-all-40.json +311 -0
  452. chronaxis/guide/en/fields/mapping/analysis-all-41.json +310 -0
  453. chronaxis/guide/en/fields/mapping/analysis-all-42.json +346 -0
  454. chronaxis/guide/en/fields/mapping/analysis-all-43.json +267 -0
  455. chronaxis/guide/en/fields/mapping/analysis-all-44.json +327 -0
  456. chronaxis/guide/en/fields/mapping/analysis-all-45.json +279 -0
  457. chronaxis/guide/en/fields/mapping/analysis-all-46.json +327 -0
  458. chronaxis/guide/en/fields/mapping/analysis-all-47.json +312 -0
  459. chronaxis/guide/en/fields/mapping/analysis-all-48.json +294 -0
  460. chronaxis/guide/en/fields/mapping/analysis-all-49.json +253 -0
  461. chronaxis/guide/en/fields/mapping/analysis-all-5.json +312 -0
  462. chronaxis/guide/en/fields/mapping/analysis-all-50.json +346 -0
  463. chronaxis/guide/en/fields/mapping/analysis-all-51.json +324 -0
  464. chronaxis/guide/en/fields/mapping/analysis-all-52.json +335 -0
  465. chronaxis/guide/en/fields/mapping/analysis-all-53.json +317 -0
  466. chronaxis/guide/en/fields/mapping/analysis-all-54.json +316 -0
  467. chronaxis/guide/en/fields/mapping/analysis-all-55.json +302 -0
  468. chronaxis/guide/en/fields/mapping/analysis-all-56.json +319 -0
  469. chronaxis/guide/en/fields/mapping/analysis-all-57.json +334 -0
  470. chronaxis/guide/en/fields/mapping/analysis-all-58.json +333 -0
  471. chronaxis/guide/en/fields/mapping/analysis-all-59.json +359 -0
  472. chronaxis/guide/en/fields/mapping/analysis-all-6.json +327 -0
  473. chronaxis/guide/en/fields/mapping/analysis-all-60.json +303 -0
  474. chronaxis/guide/en/fields/mapping/analysis-all-61.json +326 -0
  475. chronaxis/guide/en/fields/mapping/analysis-all-62.json +301 -0
  476. chronaxis/guide/en/fields/mapping/analysis-all-63.json +326 -0
  477. chronaxis/guide/en/fields/mapping/analysis-all-64.json +367 -0
  478. chronaxis/guide/en/fields/mapping/analysis-all-65.json +334 -0
  479. chronaxis/guide/en/fields/mapping/analysis-all-66.json +358 -0
  480. chronaxis/guide/en/fields/mapping/analysis-all-67.json +349 -0
  481. chronaxis/guide/en/fields/mapping/analysis-all-68.json +331 -0
  482. chronaxis/guide/en/fields/mapping/analysis-all-69.json +304 -0
  483. chronaxis/guide/en/fields/mapping/analysis-all-7.json +303 -0
  484. chronaxis/guide/en/fields/mapping/analysis-all-70.json +349 -0
  485. chronaxis/guide/en/fields/mapping/analysis-all-71.json +288 -0
  486. chronaxis/guide/en/fields/mapping/analysis-all-72.json +316 -0
  487. chronaxis/guide/en/fields/mapping/analysis-all-73.json +266 -0
  488. chronaxis/guide/en/fields/mapping/analysis-all-74.json +227 -0
  489. chronaxis/guide/en/fields/mapping/analysis-all-75.json +239 -0
  490. chronaxis/guide/en/fields/mapping/analysis-all-76.json +274 -0
  491. chronaxis/guide/en/fields/mapping/analysis-all-77.json +380 -0
  492. chronaxis/guide/en/fields/mapping/analysis-all-78.json +313 -0
  493. chronaxis/guide/en/fields/mapping/analysis-all-79.json +338 -0
  494. chronaxis/guide/en/fields/mapping/analysis-all-8.json +292 -0
  495. chronaxis/guide/en/fields/mapping/analysis-all-80.json +304 -0
  496. chronaxis/guide/en/fields/mapping/analysis-all-81.json +140 -0
  497. chronaxis/guide/en/fields/mapping/analysis-all-9.json +332 -0
  498. chronaxis/guide/en/fields/mapping/io_policy-all-1.json +19 -0
  499. chronaxis/guide/en/fields/mapping/mapping_version-all-1.json +19 -0
  500. chronaxis/guide/en/fields/mapping/path_base-all-1.json +19 -0
  501. chronaxis/guide/en/fields/mapping/sections-all-1.json +402 -0
  502. chronaxis/guide/en/fields/mapping/sections-all-2.json +232 -0
  503. chronaxis/guide/en/semantics.md +70 -0
  504. chronaxis/guide/en/tasks.json +290 -0
  505. chronaxis/guide/en/workflow.md +41 -0
  506. chronaxis/guide/examples/analysis-imports.yaml +22 -0
  507. chronaxis/guide/examples/analysis.yaml +23 -0
  508. chronaxis/guide/examples/batch-minimal.yaml +3 -0
  509. chronaxis/guide/examples/conditional-energy.yaml +36 -0
  510. chronaxis/guide/examples/data/activity.csv +6 -0
  511. chronaxis/guide/examples/data/can/activity.asc +11 -0
  512. chronaxis/guide/examples/data/can/calculation-minimal.asc +6 -0
  513. chronaxis/guide/examples/data/can/conditional-energy/part-1.asc +92 -0
  514. chronaxis/guide/examples/data/can/conditional-energy/part-2.asc +36 -0
  515. chronaxis/guide/examples/data/can/conditional-energy/signals.dbc +10 -0
  516. chronaxis/guide/examples/data/can/execution-comparison.asc +12 -0
  517. chronaxis/guide/examples/data/can/execution-report.asc +4 -0
  518. chronaxis/guide/examples/data/can/expression-extended.asc +11 -0
  519. chronaxis/guide/examples/data/can/interval-actual.asc +6 -0
  520. chronaxis/guide/examples/data/can/preset-charge-energy.asc +15 -0
  521. chronaxis/guide/examples/data/can/preset-charge-minimal.asc +11 -0
  522. chronaxis/guide/examples/data/can/preset-command-automatic.asc +11 -0
  523. chronaxis/guide/examples/data/can/preset-fault-context.asc +7 -0
  524. chronaxis/guide/examples/data/can/preset-threshold-delay.asc +7 -0
  525. chronaxis/guide/examples/data/can/preset-threshold-partial.asc +7 -0
  526. chronaxis/guide/examples/data/can/quality.asc +6 -0
  527. chronaxis/guide/examples/data/can/quickstart-parts/part1.asc +4 -0
  528. chronaxis/guide/examples/data/can/quickstart-parts/part2.asc +3 -0
  529. chronaxis/guide/examples/data/can/quickstart.asc +6 -0
  530. chronaxis/guide/examples/data/can/rule-condition_duration-extended.asc +35 -0
  531. chronaxis/guide/examples/data/can/rule-condition_duration-minimal.asc +19 -0
  532. chronaxis/guide/examples/data/can/rule-debounce-extended.asc +19 -0
  533. chronaxis/guide/examples/data/can/rule-falling_edge-extended.asc +35 -0
  534. chronaxis/guide/examples/data/can/rule-hysteresis-extended.asc +19 -0
  535. chronaxis/guide/examples/data/can/rule-start_end-extended.asc +35 -0
  536. chronaxis/guide/examples/data/can/rule-start_only-extended.asc +19 -0
  537. chronaxis/guide/examples/data/can/rule-window_delta-extended.asc +19 -0
  538. chronaxis/guide/examples/data/can/sequence-outcomes.asc +19 -0
  539. chronaxis/guide/examples/data/can/signal-types.asc +13 -0
  540. chronaxis/guide/examples/data/can/start-end.asc +30 -0
  541. chronaxis/guide/examples/data/can/teaching-base.asc +58 -0
  542. chronaxis/guide/examples/data/can/teaching.dbc +53 -0
  543. chronaxis/guide/examples/data/joint-current.csv +5 -0
  544. chronaxis/guide/examples/data/joint.asc +5 -0
  545. chronaxis/guide/examples/data/joint.dbc +7 -0
  546. chronaxis/guide/examples/data/message-clean.asc +6 -0
  547. chronaxis/guide/examples/data/message-direction.asc +7 -0
  548. chronaxis/guide/examples/data/message-direction.dbc +7 -0
  549. chronaxis/guide/examples/data/power.blf +0 -0
  550. chronaxis/guide/examples/data/power.dbc +6 -0
  551. chronaxis/guide/examples/data/quality.csv +5 -0
  552. chronaxis/guide/examples/data/raw-can-example.csv +5 -0
  553. chronaxis/guide/examples/data/signal-types.csv +5 -0
  554. chronaxis/guide/examples/data/signals.csv +6 -0
  555. chronaxis/guide/examples/data/timing.asc +6 -0
  556. chronaxis/guide/examples/data/timing.dbc +11 -0
  557. chronaxis/guide/examples/export-can-minimal.yaml +24 -0
  558. chronaxis/guide/examples/input-csv-minimal.yaml +23 -0
  559. chronaxis/guide/examples/preset-charge-energy.yaml +41 -0
  560. chronaxis/guide/examples/preset-charge-minimal.yaml +31 -0
  561. chronaxis/guide/examples/preset-fault-context.yaml +27 -0
  562. chronaxis/guide/examples/quality.yaml +19 -0
  563. chronaxis/guide/examples/sequence-outcomes.yaml +39 -0
  564. chronaxis/guide/examples/shared/definitions.yaml +14 -0
  565. chronaxis/guide/examples/signal-enum-minimal.yaml +19 -0
  566. chronaxis/guide/examples/signal-number-conversion.yaml +24 -0
  567. chronaxis/guide/examples/window-merged.yaml +28 -0
  568. chronaxis/guide/fields/analysis/calculations-all-1.json +360 -0
  569. chronaxis/guide/fields/analysis/calculations-all-2.json +299 -0
  570. chronaxis/guide/fields/analysis/calculations-all-3.json +70 -0
  571. chronaxis/guide/fields/analysis/config_version-all-1.json +24 -0
  572. chronaxis/guide/fields/analysis/dataset-all-1.json +344 -0
  573. chronaxis/guide/fields/analysis/derived-all-1.json +147 -0
  574. chronaxis/guide/fields/analysis/diagnostics-all-1.json +69 -0
  575. chronaxis/guide/fields/analysis/execution-all-1.json +167 -0
  576. chronaxis/guide/fields/analysis/imports-all-1.json +39 -0
  577. chronaxis/guide/fields/analysis/intervals-all-1.json +173 -0
  578. chronaxis/guide/fields/analysis/message_calculations-all-1.json +360 -0
  579. chronaxis/guide/fields/analysis/message_calculations-all-2.json +255 -0
  580. chronaxis/guide/fields/analysis/metadata-all-1.json +24 -0
  581. chronaxis/guide/fields/analysis/outputs-all-1.json +349 -0
  582. chronaxis/guide/fields/analysis/outputs-all-2.json +302 -0
  583. chronaxis/guide/fields/analysis/outputs-all-3.json +321 -0
  584. chronaxis/guide/fields/analysis/outputs-all-4.json +253 -0
  585. chronaxis/guide/fields/analysis/outputs-all-5.json +244 -0
  586. chronaxis/guide/fields/analysis/outputs-all-6.json +199 -0
  587. chronaxis/guide/fields/analysis/overrides-all-1.json +104 -0
  588. chronaxis/guide/fields/analysis/presets-charge_session-1.json +398 -0
  589. chronaxis/guide/fields/analysis/presets-charge_session-2.json +114 -0
  590. chronaxis/guide/fields/analysis/presets-command_response-1.json +376 -0
  591. chronaxis/guide/fields/analysis/presets-fault_context-1.json +285 -0
  592. chronaxis/guide/fields/analysis/presets-threshold_excursion-1.json +317 -0
  593. chronaxis/guide/fields/analysis/rules-condition_duration-1.json +344 -0
  594. chronaxis/guide/fields/analysis/rules-condition_duration-2.json +27 -0
  595. chronaxis/guide/fields/analysis/rules-debounce-1.json +335 -0
  596. chronaxis/guide/fields/analysis/rules-falling_edge-1.json +317 -0
  597. chronaxis/guide/fields/analysis/rules-hysteresis-1.json +334 -0
  598. chronaxis/guide/fields/analysis/rules-hysteresis-2.json +27 -0
  599. chronaxis/guide/fields/analysis/rules-rising_edge-1.json +317 -0
  600. chronaxis/guide/fields/analysis/rules-start_end-1.json +349 -0
  601. chronaxis/guide/fields/analysis/rules-start_end-2.json +44 -0
  602. chronaxis/guide/fields/analysis/rules-start_only-1.json +334 -0
  603. chronaxis/guide/fields/analysis/rules-window_delta-1.json +356 -0
  604. chronaxis/guide/fields/analysis/rules-window_delta-2.json +78 -0
  605. chronaxis/guide/fields/analysis/sequences-all-1.json +394 -0
  606. chronaxis/guide/fields/analysis/sequences-all-2.json +54 -0
  607. chronaxis/guide/fields/analysis/signals-variant-1-1.json +349 -0
  608. chronaxis/guide/fields/analysis/signals-variant-1-2.json +297 -0
  609. chronaxis/guide/fields/analysis/signals-variant-1-3.json +340 -0
  610. chronaxis/guide/fields/analysis/signals-variant-1-4.json +175 -0
  611. chronaxis/guide/fields/analysis/signals-variant-2-1.json +327 -0
  612. chronaxis/guide/fields/analysis/signals-variant-2-2.json +335 -0
  613. chronaxis/guide/fields/analysis/signals-variant-2-3.json +289 -0
  614. chronaxis/guide/fields/analysis/signals-variant-2-4.json +270 -0
  615. chronaxis/guide/fields/analysis/sources-can_asc-1.json +318 -0
  616. chronaxis/guide/fields/analysis/sources-can_asc-2.json +310 -0
  617. chronaxis/guide/fields/analysis/sources-can_asc-3.json +311 -0
  618. chronaxis/guide/fields/analysis/sources-can_asc-4.json +69 -0
  619. chronaxis/guide/fields/analysis/sources-can_blf-1.json +317 -0
  620. chronaxis/guide/fields/analysis/sources-can_blf-2.json +310 -0
  621. chronaxis/guide/fields/analysis/sources-can_blf-3.json +317 -0
  622. chronaxis/guide/fields/analysis/sources-memory-1.json +347 -0
  623. chronaxis/guide/fields/analysis/sources-memory-2.json +110 -0
  624. chronaxis/guide/fields/analysis/sources-raw_can_csv-1.json +330 -0
  625. chronaxis/guide/fields/analysis/sources-raw_can_csv-10.json +233 -0
  626. chronaxis/guide/fields/analysis/sources-raw_can_csv-11.json +225 -0
  627. chronaxis/guide/fields/analysis/sources-raw_can_csv-12.json +228 -0
  628. chronaxis/guide/fields/analysis/sources-raw_can_csv-13.json +226 -0
  629. chronaxis/guide/fields/analysis/sources-raw_can_csv-14.json +230 -0
  630. chronaxis/guide/fields/analysis/sources-raw_can_csv-15.json +227 -0
  631. chronaxis/guide/fields/analysis/sources-raw_can_csv-16.json +230 -0
  632. chronaxis/guide/fields/analysis/sources-raw_can_csv-17.json +238 -0
  633. chronaxis/guide/fields/analysis/sources-raw_can_csv-18.json +239 -0
  634. chronaxis/guide/fields/analysis/sources-raw_can_csv-19.json +233 -0
  635. chronaxis/guide/fields/analysis/sources-raw_can_csv-2.json +310 -0
  636. chronaxis/guide/fields/analysis/sources-raw_can_csv-20.json +242 -0
  637. chronaxis/guide/fields/analysis/sources-raw_can_csv-21.json +230 -0
  638. chronaxis/guide/fields/analysis/sources-raw_can_csv-22.json +228 -0
  639. chronaxis/guide/fields/analysis/sources-raw_can_csv-23.json +230 -0
  640. chronaxis/guide/fields/analysis/sources-raw_can_csv-24.json +223 -0
  641. chronaxis/guide/fields/analysis/sources-raw_can_csv-25.json +290 -0
  642. chronaxis/guide/fields/analysis/sources-raw_can_csv-26.json +131 -0
  643. chronaxis/guide/fields/analysis/sources-raw_can_csv-3.json +297 -0
  644. chronaxis/guide/fields/analysis/sources-raw_can_csv-4.json +226 -0
  645. chronaxis/guide/fields/analysis/sources-raw_can_csv-5.json +230 -0
  646. chronaxis/guide/fields/analysis/sources-raw_can_csv-6.json +227 -0
  647. chronaxis/guide/fields/analysis/sources-raw_can_csv-7.json +230 -0
  648. chronaxis/guide/fields/analysis/sources-raw_can_csv-8.json +238 -0
  649. chronaxis/guide/fields/analysis/sources-raw_can_csv-9.json +239 -0
  650. chronaxis/guide/fields/analysis/sources-signal_csv-1.json +331 -0
  651. chronaxis/guide/fields/analysis/sources-signal_csv-2.json +327 -0
  652. chronaxis/guide/fields/analysis/sources-signal_csv-3.json +295 -0
  653. chronaxis/guide/fields/analysis/sources-variant-6-1.json +319 -0
  654. chronaxis/guide/fields/analysis/sources-variant-6-2.json +327 -0
  655. chronaxis/guide/fields/analysis/sources-variant-6-3.json +314 -0
  656. chronaxis/guide/fields/analysis/sources-variant-6-4.json +91 -0
  657. chronaxis/guide/fields/analysis/windows-all-1.json +361 -0
  658. chronaxis/guide/fields/analysis/windows-all-2.json +187 -0
  659. chronaxis/guide/fields/batch/backend-all-1.json +26 -0
  660. chronaxis/guide/fields/batch/batch_version-all-1.json +22 -0
  661. chronaxis/guide/fields/batch/fail_fast-all-1.json +22 -0
  662. chronaxis/guide/fields/batch/inputs-all-1.json +161 -0
  663. chronaxis/guide/fields/batch/jobs-all-1.json +58 -0
  664. chronaxis/guide/fields/batch/process_count-all-1.json +23 -0
  665. chronaxis/guide/fields/batch/source-all-1.json +22 -0
  666. chronaxis/guide/fields/batch/template-all-1.json +22 -0
  667. chronaxis/guide/fields/definitions/derived-all-1.json +121 -0
  668. chronaxis/guide/fields/definitions/signals-all-1.json +336 -0
  669. chronaxis/guide/fields/definitions/signals-all-2.json +307 -0
  670. chronaxis/guide/fields/definitions/signals-all-3.json +305 -0
  671. chronaxis/guide/fields/definitions/signals-all-4.json +352 -0
  672. chronaxis/guide/fields/definitions/signals-all-5.json +311 -0
  673. chronaxis/guide/fields/definitions/signals-all-6.json +254 -0
  674. chronaxis/guide/fields/definitions/signals-all-7.json +88 -0
  675. chronaxis/guide/fields/definitions/sources-all-1.json +332 -0
  676. chronaxis/guide/fields/definitions/sources-all-10.json +307 -0
  677. chronaxis/guide/fields/definitions/sources-all-11.json +280 -0
  678. chronaxis/guide/fields/definitions/sources-all-12.json +209 -0
  679. chronaxis/guide/fields/definitions/sources-all-13.json +219 -0
  680. chronaxis/guide/fields/definitions/sources-all-14.json +213 -0
  681. chronaxis/guide/fields/definitions/sources-all-15.json +212 -0
  682. chronaxis/guide/fields/definitions/sources-all-16.json +232 -0
  683. chronaxis/guide/fields/definitions/sources-all-17.json +213 -0
  684. chronaxis/guide/fields/definitions/sources-all-18.json +212 -0
  685. chronaxis/guide/fields/definitions/sources-all-19.json +217 -0
  686. chronaxis/guide/fields/definitions/sources-all-2.json +336 -0
  687. chronaxis/guide/fields/definitions/sources-all-20.json +228 -0
  688. chronaxis/guide/fields/definitions/sources-all-21.json +212 -0
  689. chronaxis/guide/fields/definitions/sources-all-22.json +232 -0
  690. chronaxis/guide/fields/definitions/sources-all-23.json +213 -0
  691. chronaxis/guide/fields/definitions/sources-all-24.json +212 -0
  692. chronaxis/guide/fields/definitions/sources-all-25.json +217 -0
  693. chronaxis/guide/fields/definitions/sources-all-26.json +228 -0
  694. chronaxis/guide/fields/definitions/sources-all-27.json +212 -0
  695. chronaxis/guide/fields/definitions/sources-all-28.json +217 -0
  696. chronaxis/guide/fields/definitions/sources-all-29.json +227 -0
  697. chronaxis/guide/fields/definitions/sources-all-3.json +306 -0
  698. chronaxis/guide/fields/definitions/sources-all-30.json +333 -0
  699. chronaxis/guide/fields/definitions/sources-all-31.json +302 -0
  700. chronaxis/guide/fields/definitions/sources-all-32.json +319 -0
  701. chronaxis/guide/fields/definitions/sources-all-33.json +89 -0
  702. chronaxis/guide/fields/definitions/sources-all-4.json +336 -0
  703. chronaxis/guide/fields/definitions/sources-all-5.json +313 -0
  704. chronaxis/guide/fields/definitions/sources-all-6.json +292 -0
  705. chronaxis/guide/fields/definitions/sources-all-7.json +319 -0
  706. chronaxis/guide/fields/definitions/sources-all-8.json +315 -0
  707. chronaxis/guide/fields/definitions/sources-all-9.json +318 -0
  708. chronaxis/guide/fields/index.json +3432 -0
  709. chronaxis/guide/fields/mapping/aliases-all-1.json +91 -0
  710. chronaxis/guide/fields/mapping/analysis-all-1.json +382 -0
  711. chronaxis/guide/fields/mapping/analysis-all-10.json +307 -0
  712. chronaxis/guide/fields/mapping/analysis-all-11.json +311 -0
  713. chronaxis/guide/fields/mapping/analysis-all-12.json +329 -0
  714. chronaxis/guide/fields/mapping/analysis-all-13.json +294 -0
  715. chronaxis/guide/fields/mapping/analysis-all-14.json +311 -0
  716. chronaxis/guide/fields/mapping/analysis-all-15.json +280 -0
  717. chronaxis/guide/fields/mapping/analysis-all-16.json +227 -0
  718. chronaxis/guide/fields/mapping/analysis-all-17.json +230 -0
  719. chronaxis/guide/fields/mapping/analysis-all-18.json +221 -0
  720. chronaxis/guide/fields/mapping/analysis-all-19.json +237 -0
  721. chronaxis/guide/fields/mapping/analysis-all-2.json +342 -0
  722. chronaxis/guide/fields/mapping/analysis-all-20.json +233 -0
  723. chronaxis/guide/fields/mapping/analysis-all-21.json +244 -0
  724. chronaxis/guide/fields/mapping/analysis-all-22.json +228 -0
  725. chronaxis/guide/fields/mapping/analysis-all-23.json +226 -0
  726. chronaxis/guide/fields/mapping/analysis-all-24.json +230 -0
  727. chronaxis/guide/fields/mapping/analysis-all-25.json +227 -0
  728. chronaxis/guide/fields/mapping/analysis-all-26.json +230 -0
  729. chronaxis/guide/fields/mapping/analysis-all-27.json +221 -0
  730. chronaxis/guide/fields/mapping/analysis-all-28.json +237 -0
  731. chronaxis/guide/fields/mapping/analysis-all-29.json +233 -0
  732. chronaxis/guide/fields/mapping/analysis-all-3.json +322 -0
  733. chronaxis/guide/fields/mapping/analysis-all-30.json +244 -0
  734. chronaxis/guide/fields/mapping/analysis-all-31.json +228 -0
  735. chronaxis/guide/fields/mapping/analysis-all-32.json +226 -0
  736. chronaxis/guide/fields/mapping/analysis-all-33.json +230 -0
  737. chronaxis/guide/fields/mapping/analysis-all-34.json +227 -0
  738. chronaxis/guide/fields/mapping/analysis-all-35.json +230 -0
  739. chronaxis/guide/fields/mapping/analysis-all-36.json +221 -0
  740. chronaxis/guide/fields/mapping/analysis-all-37.json +291 -0
  741. chronaxis/guide/fields/mapping/analysis-all-38.json +315 -0
  742. chronaxis/guide/fields/mapping/analysis-all-39.json +304 -0
  743. chronaxis/guide/fields/mapping/analysis-all-4.json +312 -0
  744. chronaxis/guide/fields/mapping/analysis-all-40.json +307 -0
  745. chronaxis/guide/fields/mapping/analysis-all-41.json +292 -0
  746. chronaxis/guide/fields/mapping/analysis-all-42.json +333 -0
  747. chronaxis/guide/fields/mapping/analysis-all-43.json +296 -0
  748. chronaxis/guide/fields/mapping/analysis-all-44.json +322 -0
  749. chronaxis/guide/fields/mapping/analysis-all-45.json +298 -0
  750. chronaxis/guide/fields/mapping/analysis-all-46.json +347 -0
  751. chronaxis/guide/fields/mapping/analysis-all-47.json +302 -0
  752. chronaxis/guide/fields/mapping/analysis-all-48.json +263 -0
  753. chronaxis/guide/fields/mapping/analysis-all-49.json +301 -0
  754. chronaxis/guide/fields/mapping/analysis-all-5.json +313 -0
  755. chronaxis/guide/fields/mapping/analysis-all-50.json +336 -0
  756. chronaxis/guide/fields/mapping/analysis-all-51.json +335 -0
  757. chronaxis/guide/fields/mapping/analysis-all-52.json +335 -0
  758. chronaxis/guide/fields/mapping/analysis-all-53.json +334 -0
  759. chronaxis/guide/fields/mapping/analysis-all-54.json +339 -0
  760. chronaxis/guide/fields/mapping/analysis-all-55.json +335 -0
  761. chronaxis/guide/fields/mapping/analysis-all-56.json +336 -0
  762. chronaxis/guide/fields/mapping/analysis-all-57.json +335 -0
  763. chronaxis/guide/fields/mapping/analysis-all-58.json +333 -0
  764. chronaxis/guide/fields/mapping/analysis-all-59.json +325 -0
  765. chronaxis/guide/fields/mapping/analysis-all-6.json +323 -0
  766. chronaxis/guide/fields/mapping/analysis-all-60.json +334 -0
  767. chronaxis/guide/fields/mapping/analysis-all-61.json +311 -0
  768. chronaxis/guide/fields/mapping/analysis-all-62.json +289 -0
  769. chronaxis/guide/fields/mapping/analysis-all-63.json +383 -0
  770. chronaxis/guide/fields/mapping/analysis-all-64.json +357 -0
  771. chronaxis/guide/fields/mapping/analysis-all-65.json +375 -0
  772. chronaxis/guide/fields/mapping/analysis-all-66.json +351 -0
  773. chronaxis/guide/fields/mapping/analysis-all-67.json +346 -0
  774. chronaxis/guide/fields/mapping/analysis-all-68.json +317 -0
  775. chronaxis/guide/fields/mapping/analysis-all-69.json +313 -0
  776. chronaxis/guide/fields/mapping/analysis-all-7.json +306 -0
  777. chronaxis/guide/fields/mapping/analysis-all-70.json +326 -0
  778. chronaxis/guide/fields/mapping/analysis-all-71.json +316 -0
  779. chronaxis/guide/fields/mapping/analysis-all-72.json +264 -0
  780. chronaxis/guide/fields/mapping/analysis-all-73.json +228 -0
  781. chronaxis/guide/fields/mapping/analysis-all-74.json +241 -0
  782. chronaxis/guide/fields/mapping/analysis-all-75.json +273 -0
  783. chronaxis/guide/fields/mapping/analysis-all-76.json +382 -0
  784. chronaxis/guide/fields/mapping/analysis-all-77.json +328 -0
  785. chronaxis/guide/fields/mapping/analysis-all-78.json +338 -0
  786. chronaxis/guide/fields/mapping/analysis-all-79.json +304 -0
  787. chronaxis/guide/fields/mapping/analysis-all-8.json +309 -0
  788. chronaxis/guide/fields/mapping/analysis-all-80.json +140 -0
  789. chronaxis/guide/fields/mapping/analysis-all-9.json +329 -0
  790. chronaxis/guide/fields/mapping/io_policy-all-1.json +19 -0
  791. chronaxis/guide/fields/mapping/mapping_version-all-1.json +19 -0
  792. chronaxis/guide/fields/mapping/path_base-all-1.json +19 -0
  793. chronaxis/guide/fields/mapping/sections-all-1.json +402 -0
  794. chronaxis/guide/fields/mapping/sections-all-2.json +232 -0
  795. chronaxis/guide/lookup.py +90 -0
  796. chronaxis/guide/manifest.json +614 -0
  797. chronaxis/guide/run_analysis.py +34 -0
  798. chronaxis/guide/schemas/analysis.schema.json +8451 -0
  799. chronaxis/guide/schemas/batch-v1.schema.json +172 -0
  800. chronaxis/guide/schemas/definitions.schema.json +29 -0
  801. chronaxis/guide/schemas/legacy-import-v1.schema.json +143 -0
  802. chronaxis/guide/semantics.md +62 -0
  803. chronaxis/guide/tasks.json +290 -0
  804. chronaxis/guide/workflow.md +38 -0
  805. chronaxis/legacy/__init__.py +46 -0
  806. chronaxis/legacy/batch_read.py +412 -0
  807. chronaxis/legacy/batch_validation.py +134 -0
  808. chronaxis/legacy/batch_wire.py +264 -0
  809. chronaxis/legacy/batch_worker.py +417 -0
  810. chronaxis/legacy/binding.py +154 -0
  811. chronaxis/legacy/dbc_cycles.py +47 -0
  812. chronaxis/legacy/decode_policy.py +28 -0
  813. chronaxis/legacy/disjunction.py +79 -0
  814. chronaxis/legacy/export_worker.py +147 -0
  815. chronaxis/legacy/export_write.py +378 -0
  816. chronaxis/legacy/message_store.py +562 -0
  817. chronaxis/legacy/process_read.py +526 -0
  818. chronaxis/legacy/raw_store.py +341 -0
  819. chronaxis/legacy/records.py +709 -0
  820. chronaxis/legacy/required_records.py +122 -0
  821. chronaxis/legacy/sum.py +403 -0
  822. chronaxis/legacy/sum_numpy.py +43 -0
  823. chronaxis/legacy/updates.py +277 -0
  824. chronaxis/legacy/vendor/sclicer_functions_v1/can_processor.py +138 -0
  825. chronaxis/legacy/vendor/sclicer_functions_v1/file_processor.py +218 -0
  826. chronaxis/legacy/vendor/sclicer_functions_v1/utils.py +447 -0
  827. chronaxis/legacy/worker.py +352 -0
  828. chronaxis/migration/__init__.py +11 -0
  829. chronaxis/migration/api.py +270 -0
  830. chronaxis/migration/ini.py +110 -0
  831. chronaxis/migration/legacy_sum.py +304 -0
  832. chronaxis/migration/models.py +83 -0
  833. chronaxis/migration/publication.py +230 -0
  834. chronaxis/migration/sclicer.py +241 -0
  835. chronaxis/migration/slope.py +78 -0
  836. chronaxis/migration/start_end.py +48 -0
  837. chronaxis/planning/__init__.py +19 -0
  838. chronaxis/planning/channels.py +30 -0
  839. chronaxis/planning/checks.py +447 -0
  840. chronaxis/planning/config_groups.py +215 -0
  841. chronaxis/planning/dbc_defaults.py +88 -0
  842. chronaxis/planning/export_options.py +247 -0
  843. chronaxis/planning/input_defaults.py +62 -0
  844. chronaxis/planning/input_paths.py +124 -0
  845. chronaxis/planning/input_requirements.py +250 -0
  846. chronaxis/planning/inputs.py +306 -0
  847. chronaxis/planning/intervals.py +242 -0
  848. chronaxis/planning/legacy_execution.py +38 -0
  849. chronaxis/planning/message_calculations.py +171 -0
  850. chronaxis/planning/models.py +369 -0
  851. chronaxis/planning/nodes.py +355 -0
  852. chronaxis/planning/plan.py +294 -0
  853. chronaxis/planning/preset_models.py +211 -0
  854. chronaxis/planning/record_execution.py +76 -0
  855. chronaxis/planning/reports.py +523 -0
  856. chronaxis/planning/sequences.py +91 -0
  857. chronaxis/planning/signal_groups.py +61 -0
  858. chronaxis/planning/signal_validity.py +46 -0
  859. chronaxis/planning/text_inputs.py +110 -0
  860. chronaxis/presets.py +270 -0
  861. chronaxis/results/__init__.py +34 -0
  862. chronaxis/results/analysis_outcome.py +67 -0
  863. chronaxis/results/artifact_exports.py +212 -0
  864. chronaxis/results/binding_metadata.py +54 -0
  865. chronaxis/results/budget.py +138 -0
  866. chronaxis/results/can_metadata.py +247 -0
  867. chronaxis/results/codec.py +246 -0
  868. chronaxis/results/errors.py +25 -0
  869. chronaxis/results/export_files.py +216 -0
  870. chronaxis/results/frame_exports.py +299 -0
  871. chronaxis/results/frame_patch.py +186 -0
  872. chronaxis/results/frame_rebuild.py +458 -0
  873. chronaxis/results/frame_sort.py +223 -0
  874. chronaxis/results/input_diagnostics.py +51 -0
  875. chronaxis/results/manifest.py +343 -0
  876. chronaxis/results/merge_runs.py +207 -0
  877. chronaxis/results/owned_directory.py +32 -0
  878. chronaxis/results/raw_exports.py +689 -0
  879. chronaxis/results/readable.py +355 -0
  880. chronaxis/results/readable_format.py +94 -0
  881. chronaxis/results/result.py +734 -0
  882. chronaxis/results/rows.py +57 -0
  883. chronaxis/results/signal_exports.py +209 -0
  884. chronaxis/results/signal_grid.py +219 -0
  885. chronaxis/results/spool.py +421 -0
  886. chronaxis/results/summary.py +350 -0
  887. chronaxis/results/text_can_metadata.py +64 -0
  888. chronaxis/results/threshold_metadata.py +105 -0
  889. chronaxis/runner.py +121 -0
  890. chronaxis/sources/__init__.py +23 -0
  891. chronaxis/sources/asc.py +412 -0
  892. chronaxis/sources/blf.py +101 -0
  893. chronaxis/sources/can_spec.py +179 -0
  894. chronaxis/sources/can_updates.py +160 -0
  895. chronaxis/sources/csv_spec.py +133 -0
  896. chronaxis/sources/descriptions.py +65 -0
  897. chronaxis/sources/memory.py +299 -0
  898. chronaxis/sources/models.py +497 -0
  899. chronaxis/sources/packing.py +170 -0
  900. chronaxis/sources/protocol.py +221 -0
  901. chronaxis/sources/raw_can.py +62 -0
  902. chronaxis/sources/raw_csv.py +470 -0
  903. chronaxis/sources/raw_csv_layout.py +310 -0
  904. chronaxis/sources/signal_csv.py +608 -0
  905. chronaxis/sources/text_can_decode.py +421 -0
  906. chronaxis/sources/text_can_ref.py +48 -0
  907. chronaxis/sources/text_can_spec.py +61 -0
  908. chronaxis/timebase/__init__.py +19 -0
  909. chronaxis/timebase/conversion.py +364 -0
  910. chronaxis/timebase/numpy_ops.py +104 -0
  911. chronaxis/user_guide.py +81 -0
  912. chronaxis-0.1.0.dev0.dist-info/METADATA +172 -0
  913. chronaxis-0.1.0.dev0.dist-info/RECORD +917 -0
  914. chronaxis-0.1.0.dev0.dist-info/WHEEL +5 -0
  915. chronaxis-0.1.0.dev0.dist-info/entry_points.txt +2 -0
  916. chronaxis-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
  917. chronaxis-0.1.0.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,223 @@
1
+ """为离线报文导出进行有界磁盘排序,不把整段报文留在内存。
2
+
3
+ 输入为有限标量排序键和新导出自己的JSON记录,输出按键稳定排列的记录流。
4
+ 每批最多64行,归并只开两路输入;旧run留作诊断且累计计入spool。旧调用默认用摘要绑定每行与结束标记;新版仅显式完整性诊断时启用。
5
+ 不启用摘要时仍校验行结构、行长和结束计数,拒绝截断,不提供防篡改证明。
6
+ 所有句柄在owner上登记,持续关闭失败仍可重试;本模块不读原日志或加载DBC。
7
+ """
8
+
9
+ from hashlib import blake2b
10
+ from hmac import compare_digest
11
+ import json
12
+ from pathlib import Path
13
+ from secrets import token_bytes
14
+
15
+ from .budget import _reserve_owned_ram, _release_owned_ram, _cleanup_owner
16
+ from .errors import ResultClosedError, ResultFormatError
17
+
18
+
19
+ class FrameSort:
20
+ """拥有一个新目录、最多64行缓冲和三个实际文件,封口后只允许顺序回读。"""
21
+
22
+ def __init__(self,path,budget,*,check_cancel=None,buffer_rows=64,integrity=True):
23
+ """预约并创建暂存。参数: path新目录、budget、取消回调及批行数。返回: owner。异常: 配置/预算/I/O错。
24
+ """
25
+ if type(buffer_rows) is not int or not 1<=buffer_rows<=64:
26
+ raise ValueError('报文排序缓冲需要1至64行')
27
+ if type(integrity) is not bool: raise TypeError("integrity需要bool")
28
+ self.integrity=integrity
29
+ self.path=Path(path); self._budget=budget; self.check_cancel=check_cancel
30
+ self._held_cost=self._fixed_cost=self._buffer_cost=0
31
+ self.buffer_rows=buffer_rows; self.buffer=[]; self.handles=[]
32
+ self._closed=False; self.state='building'; self.count=self.runs=0
33
+ self.level=0; self.secret=None; self.cursor=None; self.pending_file=None
34
+ try:
35
+ # 两路解码树/编码/缓冲及句柄均有固定工作空间,实际行缓冲另计。
36
+ _reserve_owned_ram(self,6*1048576,'_fixed_cost')
37
+ if any(p.casefold()=='refprojects' for p in (*self.path.parts,*self.path.resolve().parts)):
38
+ raise ValueError('报文排序不能写RefProjects')
39
+ self.path.mkdir(parents=True,exist_ok=False); self.secret=token_bytes(32) if integrity else None
40
+ except BaseException as error:
41
+ _cleanup_owner(self,error,'frame_sort_cleanup_owner','报文排序构造')
42
+ raise
43
+
44
+ def _check(self):
45
+ """在有界I/O间检查取消。参数: 无。返回: None。异常: 关闭或取消。
46
+ """
47
+ if self._closed:
48
+ raise ResultClosedError('报文排序已关闭')
49
+ if self.check_cancel is not None:
50
+ self.check_cancel()
51
+
52
+ def _open(self,path,mode):
53
+ """登记真实句柄后交付。参数: path、模式。返回: 文件。异常: 打开或登记失败。
54
+ """
55
+ self.pending_file=path.open(mode,buffering=65536)
56
+ stream=self.pending_file
57
+ self.handles.append(stream); self.pending_file=None
58
+ return stream
59
+
60
+ def _close_file(self,stream):
61
+ """关闭成功才撤销登记。参数: stream实际流。返回: None。异常: 关闭错保责任。
62
+ """
63
+ stream.close(); self.handles.remove(stream)
64
+
65
+ def _mac(self,path,index,body):
66
+ """把完整行绑定当前run及顺序。参数: path/index/body。返回: 64字节摘要。异常: 原类型错。
67
+ """
68
+ digest=blake2b(key=self.secret,digest_size=32)
69
+ digest.update(path.name.encode('ascii')); digest.update(str(index).encode('ascii'))
70
+ digest.update(b'\0'); digest.update(body)
71
+ return digest.hexdigest().encode('ascii')
72
+
73
+ def _write(self,stream,index,packet):
74
+ """有界编码并实写一行。参数: stream/index/packet。返回: None。异常: 配额/超行/写入错。
75
+ """
76
+ self._check()
77
+ body=json.dumps(packet,ensure_ascii=False,allow_nan=False,separators=(',',':')).encode('utf-8')
78
+ if len(body)>65536:
79
+ raise ResultFormatError('报文排序单行超过64KiB')
80
+ payload=(self._mac(Path(stream.name),index,body)+b' ' if self.integrity else b'')+body+b'\n'
81
+ self._budget.reserve_spool(len(payload))
82
+ position=0
83
+ while position<len(payload):
84
+ written=stream.write(payload[position:])
85
+ if type(written) is not int or not 0<written<=len(payload)-position:
86
+ raise OSError('报文排序写入无进展')
87
+ position+=written
88
+
89
+ def _read(self,path):
90
+ """逐行核完整性,必须读到合法结束记录。参数: path本次run。返回: 记录生成器。异常: 改写/截断/关闭错。
91
+ """
92
+ stream=self._open(path,'rb'); index=0; primary=None
93
+ try:
94
+ while True:
95
+ self._check(); raw=stream.readline(65604)
96
+ if not raw.endswith(b'\n') or len(raw)>(65602 if self.integrity else 65537) or self.integrity and raw[64:65]!=b' ':
97
+ raise ResultFormatError('报文排序行截断或超限')
98
+ body=raw[65:-1] if self.integrity else raw[:-1]
99
+ if self.integrity and not compare_digest(raw[:64],self._mac(path,index,body)):
100
+ raise ResultFormatError('报文排序行内容或顺序被修改')
101
+ packet=json.loads(body)
102
+ if type(packet) is dict:
103
+ if packet!={'end':index} or stream.read(1):
104
+ raise ResultFormatError('报文排序结束记录不一致')
105
+ return
106
+ if type(packet) is not list or len(packet)!=3 or type(packet[0]) is not list:
107
+ raise ResultFormatError('报文排序行结构非法')
108
+ index+=1
109
+ yield (tuple(packet[0]),packet[1],packet[2])
110
+ except BaseException as error:
111
+ primary=error
112
+ raise
113
+ finally:
114
+ # 校验/取消是主错误;关闭错误只能附注,真实句柄保owner供再次close。
115
+ try:
116
+ self._close_file(stream)
117
+ except BaseException as cleanup:
118
+ if primary is None:
119
+ raise
120
+ primary.add_note('报文排序回读关闭待恢复: '+repr(cleanup))
121
+
122
+ def append(self,key,packet):
123
+ """预约后缓冲一条。参数: key有限同类型标量tuple、packet有限JSON对象。返回: None。异常: 结构/预算/I/O错。
124
+ """
125
+ self._check()
126
+ if self.state!='building' or type(key) is not tuple or len(key)>32 or any(type(v) not in (int,str) for v in key):
127
+ raise ValueError('报文排序需要building及有限标量键')
128
+ encoded=json.dumps(packet,ensure_ascii=False,allow_nan=False,separators=(',',':')).encode('utf-8')
129
+ if len(encoded)>65000:
130
+ raise ResultFormatError('报文记录超过排序行能力')
131
+ # JSON往返冻结调用者数据,避免追加后修改改变尚未写盘的结果。
132
+ _reserve_owned_ram(self,4096+len(encoded)*32,'_buffer_cost')
133
+ self.buffer.append((key,self.count,json.loads(encoded))); self.count+=1
134
+ if len(self.buffer)>=self.buffer_rows:
135
+ self._flush()
136
+
137
+ def _flush(self):
138
+ """稳定排序有限缓冲并保存一个run。参数: 无。返回: None。异常: 排序/I/O/配额错。
139
+ """
140
+ if not self.buffer:
141
+ return
142
+ self.buffer.sort(key=lambda item:(item[0],item[1]))
143
+ stream=self._open(self.path/f'0-{self.runs}.jsonl','xb')
144
+ for index,packet in enumerate(self.buffer):
145
+ self._write(stream,index,packet)
146
+ self._write(stream,len(self.buffer),{'end':len(self.buffer)})
147
+ self._close_file(stream); self.runs+=1; self.buffer.clear()
148
+ _release_owned_ram(self,self._buffer_cost,'_buffer_cost')
149
+
150
+ def _merge(self,left,right,target):
151
+ """只保两路当前行进行稳定归并。参数: 两个run及新目标。返回: None。异常: 输入校验/写入/关闭错。
152
+ """
153
+ first=self._read(left); second=self._read(right) if right is not None else iter(())
154
+ stream=self._open(target,'xb'); count=0; primary=None
155
+ try:
156
+ a=next(first,None); b=next(second,None)
157
+ while a is not None or b is not None:
158
+ choose_first=b is None or a is not None and (a[0],a[1])<=(b[0],b[1])
159
+ row=a if choose_first else b
160
+ self._write(stream,count,row); count+=1
161
+ if choose_first:
162
+ a=next(first,None)
163
+ else:
164
+ b=next(second,None)
165
+ self._write(stream,count,{'end':count}); self._close_file(stream)
166
+ except BaseException as error:
167
+ primary=error
168
+ raise
169
+ finally:
170
+ cleanup_error=None
171
+ for reader in (first,second):
172
+ close=getattr(reader,'close',None)
173
+ if close is not None:
174
+ try:
175
+ close()
176
+ except BaseException as cleanup:
177
+ cleanup_error=cleanup_error or cleanup
178
+ if cleanup_error is not None:
179
+ if primary is None:
180
+ raise cleanup_error
181
+ primary.add_note('报文归并游标关闭待恢复: '+repr(cleanup_error))
182
+
183
+ def seal(self):
184
+ """完成所有有界归并,空输入也有完整结束记录。参数: 无。返回: None。异常: 输入/预算/取消/I/O错。
185
+ """
186
+ self._check()
187
+ if self.state!='building':
188
+ raise ResultClosedError('报文排序不能重复封口')
189
+ self._flush()
190
+ if not self.runs:
191
+ stream=self._open(self.path/'0-0.jsonl','xb')
192
+ self._write(stream,0,{'end':0}); self._close_file(stream); self.runs=1
193
+ while self.runs>1:
194
+ for index in range(0,self.runs,2):
195
+ self._merge(self.path/f'{self.level}-{index}.jsonl',
196
+ self.path/f'{self.level}-{index+1}.jsonl' if index+1<self.runs else None,
197
+ self.path/f'{self.level+1}-{index//2}.jsonl')
198
+ self.level+=1; self.runs=(self.runs+1)//2
199
+ self.state='sealed'
200
+
201
+ def rows(self):
202
+ """交付单一可关闭回读游标。参数: 无。返回: (key,序号,记录)生成器。异常: 非sealed或已有游标。
203
+ """
204
+ self._check()
205
+ if self.state!='sealed' or self.cursor is not None:
206
+ raise ResultClosedError('报文排序未封口或已交付游标')
207
+ self.cursor=self._read(self.path/f'{self.level}-0.jsonl')
208
+ return self.cursor
209
+
210
+ def close(self):
211
+ """关闭全部实际文件后释放自有预算;保暂存供诊断。参数: 无。返回: None。异常: 原关闭/释放错可重试。
212
+ """
213
+ if self._closed:
214
+ return
215
+ if self.cursor is not None:
216
+ self.cursor.close(); self.cursor=None
217
+ if self.pending_file is not None:
218
+ self.pending_file.close(); self.pending_file=None
219
+ while self.handles:
220
+ self._close_file(self.handles[-1])
221
+ self.buffer.clear(); self.secret=None
222
+ _release_owned_ram(self,self._buffer_cost,'_buffer_cost')
223
+ _release_owned_ram(self,self._fixed_cost,'_fixed_cost'); self._closed=True
@@ -0,0 +1,51 @@
1
+ """保存明确请求的输入检查范围;摘要只覆盖实际交给分析层的记录。
2
+
3
+ 一份来源说明关联必要路径、所需别名、检查范围及可选摘要,不复制输入文件。
4
+ 本模型不读取数据;EOF和摘要由同次运行提供,不能当成全文件内容证明。
5
+ """
6
+ from dataclasses import dataclass
7
+ from ..core.validation import require_identifier,require_text
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class InputDiagnostic:
12
+ """一个实际来源的有限诊断;记录数与摘要均指同一所需记录流。"""
13
+ source: str
14
+ source_type: str
15
+ paths: tuple[str,...]
16
+ aliases: tuple[str,...]
17
+ bindings: tuple[tuple[str,str],...]
18
+ input_check: str
19
+ time_scope: str
20
+ record_count: int
21
+ source_eof: bool
22
+ sha256: str | None = None
23
+ digest_scope: str = 'required-decoded-records-v1'
24
+
25
+ def __post_init__(self):
26
+ """核有限范围声明。参数: 无。返回: None。异常: 类型/值错误。"""
27
+ require_identifier(self.source,'diagnostic.source')
28
+ if self.source_type not in ('can_blf','can_asc','asc_or_blf','raw_can_csv','memory','signal_csv'):
29
+ raise ValueError('诊断来源类型无效')
30
+ for values in (self.paths,self.aliases):
31
+ if type(values) is not tuple:raise TypeError('诊断路径/别名需要tuple')
32
+ for value in values:require_text(value,'diagnostic.locator')
33
+ if type(self.bindings) is not tuple or any(type(pair) is not tuple or len(pair)!=2
34
+ or pair[0] not in self.aliases or type(pair[1]) is not str or not pair[1] for pair in self.bindings):
35
+ raise ValueError('诊断绑定需要别名及实际原字段')
36
+ if self.input_check not in ('auto','full') or self.time_scope not in ('none','selected','source'):
37
+ raise ValueError('诊断检查范围无效')
38
+ if type(self.record_count) is not int or self.record_count<0 or self.source_eof is not True:
39
+ raise ValueError('诊断需要真实EOF与非负记录数')
40
+ if self.sha256 is not None and (type(self.sha256) is not str or len(self.sha256)!=64
41
+ or any(c not in '0123456789abcdef' for c in self.sha256)):
42
+ raise ValueError('诊断摘要必须是SHA256或None')
43
+ if self.digest_scope!='required-decoded-records-v1':
44
+ raise ValueError('不能把所需记录流摘要声明为全文件证明')
45
+
46
+ def to_dict(self):
47
+ """输出一份来源/绑定范围,未请求摘要时不写空摘要栏。参数: 无。返回: dict。异常: 无。"""
48
+ result={name:getattr(self,name) for name in ('source','source_type','paths','bindings','input_check','time_scope','record_count','source_eof')}
49
+ result['record_scope']=self.digest_scope
50
+ if self.sha256 is not None:result['sha256']=self.sha256
51
+ return result
@@ -0,0 +1,343 @@
1
+ """定义结果清单中的运行事实和已发布输出身份。
2
+
3
+ 输入为执行侧明确提供的时间/身份/后端,输出为冻结元数据模型。
4
+ 不会推断CAN、DBC或同步关系;软件/Python版本、资源统计和输出由结果层补齐。
5
+ 调用者须提供真实信息,模型校验不能证明真实日志已经验收。
6
+ """
7
+
8
+ # 清单字段冻结;带时区时间及int64会话边界与核心协议一致。
9
+ from dataclasses import dataclass, asdict, fields
10
+ from datetime import datetime
11
+ from math import isfinite, isnan
12
+ from pathlib import Path
13
+ from sys import getsizeof
14
+ from ..core.validation import require_text, require_identifier
15
+ from ..core.models import Interval
16
+ from ..core.binding import SignalDefinition
17
+ from ..core.types import QualityFlag
18
+ from .binding_metadata import PresetBindingMetadata, PresetRoleMetadata
19
+ from .can_metadata import CANSourceMetadata, CANUnitCheck, CANFrameFormatNotice
20
+ from .text_can_metadata import TextCANSourceMetadata
21
+ from .threshold_metadata import ThresholdDurationMetadata,SummaryThresholdDuration
22
+ from .input_diagnostics import InputDiagnostic
23
+ from .analysis_outcome import AnalysisOutcome, RuleOutcome
24
+ from ..legacy.records import LegacyCANField
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class RunMetadata:
29
+ """保存运行身份、实际后端、时间解释、会话边界与兼容限制。
30
+
31
+ started_at须含时区;session_boundaries为(session_id,start_ns,end_ns)tuple。
32
+ 映射/DBC/依赖事实未涉及时使用空tuple,不能把空值当成验证通过。
33
+ 字段只保存明确输入;新层资源/输出/结束时间由实际执行结果补充。
34
+ signal_bindings保本次实际定义,preset_bindings保最终角色;可选语义仍是声明,
35
+ 角色契约通过也不表示物理事实已测量。can_sources保存同次真实CAN读取/暂存/
36
+ 单位核对的结构化事实;text_can_sources保存新文本解析/DBC/观测事实。
37
+ 未提供的详细事实不作为当前运行的验证证明。
38
+ """
39
+
40
+ run_id: str
41
+ input_identity: str | None
42
+ plan_hash: str
43
+ backend: str
44
+ config_version: int
45
+ source_time_interpretation: str
46
+ session_boundaries: tuple[tuple[str, int, int], ...]
47
+ started_at: str
48
+ mapping_hashes: tuple[str, ...] = ()
49
+ dbc_hashes: tuple[str, ...] = ()
50
+ parsing_policy: str = 'decoded-results'
51
+ worker_config: str = 'single-thread'
52
+ dependency_versions: tuple[tuple[str, str], ...] = ()
53
+ limitations: tuple[str, ...] = ()
54
+ software_version: str = '0.1.0.dev0'
55
+ device_label: str = 'pending'
56
+ signal_bindings: tuple[SignalDefinition, ...] = () # 本次实际完整定义,不含样本或输入行。
57
+ preset_bindings: tuple[PresetBindingMetadata, ...] = () # 原预设版本及最终角色。
58
+ can_sources: tuple[CANSourceMetadata, ...] = () # 同次实际CAN read事实,不含样本或伪造DBC哈希。
59
+ session_ids: tuple[str, ...] = () # 无时间请求仍明确会话身份,绝不伪造边界。
60
+ text_can_sources: tuple[TextCANSourceMetadata,...] = () # 新文本入口同次DBC/解析/观测事实。
61
+ threshold_durations: tuple[SummaryThresholdDuration, ...] = () # 仅显式阈值预设的同次状态累计。
62
+ detailed_diagnostics: bool = False # 按显式请求输出额外质量明细和摘要。
63
+ retain_work: bool = False # 显式现场留存请求,不默认保留工作文件。
64
+ input_diagnostics: tuple[InputDiagnostic,...] = () # 仅按请求记录同次所需输入范围。
65
+ trace_requested: bool = False # input_trace表独立于贡献和哈希。
66
+ integrity_diagnostics: bool = False # 摘要独立于逐条追溯。
67
+ frame_format_notices: tuple[tuple[str, CANFrameFormatNotice], ...] = () # 同次已核差异始终提示,独立于可选诊断。
68
+
69
+ analysis_outcome: AnalysisOutcome | None = None # 同次推进的轻量业务结果概况,非逐条追溯。
70
+
71
+ def __post_init__(self) -> None:
72
+ """验证清单文本与明确会话范围,不访问外部输入。
73
+
74
+ 参数: 无。返回: None。异常: TypeError/ValueError为结构或事实格式错误。
75
+ """
76
+ if self.analysis_outcome is not None and type(self.analysis_outcome) is not AnalysisOutcome:
77
+ raise TypeError('分析结果概况需要AnalysisOutcome或None')
78
+ # 必填文本不能用空字符串表示已经取得的运行身份。
79
+ for name in ('run_id', 'plan_hash', 'source_time_interpretation',
80
+ 'parsing_policy', 'worker_config', 'software_version', 'device_label'):
81
+ require_text(getattr(self, name), name)
82
+ if self.backend not in ('reference', 'numpy') or type(self.config_version) is not int or self.config_version != 3:
83
+ raise ValueError('结果清单需实际reference/numpy及配置版本3')
84
+ if (self.input_identity is not None):
85
+ require_text(self.input_identity, 'input_identity')
86
+ if type(self.detailed_diagnostics) is not bool or type(self.retain_work) is not bool:
87
+ raise TypeError('诊断/现场保留需要bool')
88
+ if type(self.trace_requested) is not bool or type(self.integrity_diagnostics) is not bool:
89
+ raise TypeError('输入诊断开关需要bool')
90
+ if (type(self.input_diagnostics) is not tuple
91
+ or any(type(item) is not InputDiagnostic for item in self.input_diagnostics)):
92
+ raise TypeError('输入诊断需InputDiagnostic tuple')
93
+ if self.input_diagnostics and not (self.trace_requested or self.integrity_diagnostics):
94
+ raise ValueError('未请求不能附输入诊断')
95
+ if (type(self.frame_format_notices) is not tuple or any(type(pair) is not tuple or len(pair) != 2
96
+ or type(pair[1]) is not CANFrameFormatNotice for pair in self.frame_format_notices)):
97
+ raise TypeError('帧型提示需要来源与CANFrameFormatNotice的tuple')
98
+ for source, notice in self.frame_format_notices:
99
+ require_identifier(source, 'frame_format.source')
100
+ if len({(source, notice.alias) for source, notice in self.frame_format_notices}) != len(self.frame_format_notices):
101
+ raise ValueError('同来源信号的帧型提示不能重复')
102
+ require_text(self.started_at, 'started_at')
103
+ if datetime.fromisoformat(self.started_at).utcoffset() is None:
104
+ raise ValueError('started_at必须带时区')
105
+ # 会话边界只验证半开范围,空会话允许start=end;不自动联合或平移。
106
+ if type(self.session_boundaries) is not tuple:
107
+ raise TypeError('session_boundaries需tuple')
108
+ for boundary in self.session_boundaries:
109
+ if type(boundary) is not tuple or len(boundary) != 3:
110
+ raise TypeError('会话边界需(session_id,start,end)')
111
+ require_identifier(boundary[0], 'session_id')
112
+ # 清单直接JSON序列化,固定原生整数,bool及NumPy容器不能偷偷换类型。
113
+ if type(boundary[1]) is not int or type(boundary[2]) is not int:
114
+ raise TypeError('清单会话边界需原生int纳秒')
115
+ Interval(boundary[1], boundary[2])
116
+ for values in (self.mapping_hashes, self.dbc_hashes, self.limitations):
117
+ if type(values) is not tuple or any(type(value) is not str or not value for value in values):
118
+ raise TypeError('清单映射/限制需要非空文本tuple')
119
+ if type(self.dependency_versions) is not tuple or any(type(item) is not tuple or len(item) != 2
120
+ or any(type(value) is not str or not value for value in item) for item in self.dependency_versions):
121
+ raise TypeError('依赖版本需(name,version)tuple')
122
+
123
+ # 新快照只接不可变定义和有限角色记录,拒绝自由字典或原样本模型。
124
+ if (type(self.signal_bindings) is not tuple
125
+ or any(type(item) is not SignalDefinition for item in self.signal_bindings)
126
+ or type(self.preset_bindings) is not tuple
127
+ or any(type(item) is not PresetBindingMetadata for item in self.preset_bindings)):
128
+ raise TypeError('运行绑定清单需SignalDefinition及PresetBindingMetadata tuple')
129
+ names = {item.name for item in self.signal_bindings}
130
+ if len(names) != len(self.signal_bindings):
131
+ raise ValueError('运行绑定清单不能重复别名')
132
+ if len({item.preset_id for item in self.preset_bindings}) != len(self.preset_bindings):
133
+ raise ValueError('运行绑定清单不能重复预设ID')
134
+ if any(role.alias not in names for preset in self.preset_bindings for role in preset.roles):
135
+ raise ValueError('预设最终角色必须引用本清单实际信号别名')
136
+ if (type(self.threshold_durations) is not tuple
137
+ or any(type(item) is not (SummaryThresholdDuration)
138
+ for item in self.threshold_durations)):
139
+ raise TypeError('阈值汇总需ThresholdDurationMetadata tuple')
140
+ preset_ids = {item.preset_id for item in self.preset_bindings if item.preset_type == 'threshold_excursion'}
141
+ if (len({item.preset_id for item in self.threshold_durations}) != len(self.threshold_durations)
142
+ or any((item.rule_id != item.preset_id + '_activity')
143
+ for item in self.threshold_durations)):
144
+ raise ValueError('阈值汇总必须对应本次预设及生成规则,不能重复')
145
+ if type(self.session_ids) is not tuple or len(set(self.session_ids)) != len(self.session_ids):
146
+ raise TypeError('独立会话身份需要无重复tuple')
147
+ for session_id in self.session_ids:
148
+ require_identifier(session_id, 'session_id')
149
+ # CAN仅接受登记冻结模型;会话、来源和单位事实必须关联本次原绑定,不能借旧任务别名。
150
+ if type(self.text_can_sources) is not tuple or any(type(item) is not TextCANSourceMetadata for item in self.text_can_sources):
151
+ raise TypeError('文本CAN清单需要TextCANSourceMetadata tuple')
152
+ if len({item.source for item in self.text_can_sources})!=len(self.text_can_sources):
153
+ raise ValueError('文本CAN清单来源重复')
154
+ for source in self.text_can_sources:
155
+ if source.session_id not in ({b[0] for b in self.session_boundaries}|set(self.session_ids)):
156
+ raise ValueError('文本CAN清单会话错误')
157
+ expected={s.name:s.input_unit for s in self.signal_bindings if s.source==source.source}
158
+ if {c.alias:c.input_unit for c in source.unit_checks}!=expected or len(source.unit_checks)!=len(expected):
159
+ raise ValueError('文本CAN单位清单必须覆盖实际绑定')
160
+ if type(self.can_sources) is not tuple or any(type(item) is not CANSourceMetadata for item in self.can_sources):
161
+ raise TypeError('CAN运行清单需要CANSourceMetadata tuple')
162
+ if len({item.source for item in self.can_sources}) != len(self.can_sources):
163
+ raise ValueError('CAN运行清单来源重复')
164
+ # 空默认不为旧运行再构造来源/单位索引,实际CAN存在时才核本次对应关系。
165
+ if self.can_sources:
166
+ sessions = {boundary[0] for boundary in self.session_boundaries} | set(self.session_ids)
167
+ definitions = {item.name: item for item in self.signal_bindings}
168
+ for source in self.can_sources:
169
+ if source.session_id not in sessions:
170
+ raise ValueError('CAN运行清单会话不属于本次session_boundaries')
171
+ expected = {name for name, definition in definitions.items() if definition.source == source.source}
172
+ if {check.alias for check in source.unit_checks} != expected:
173
+ raise ValueError('CAN单位清单必须恰好覆盖同来源本次实际绑定别名')
174
+ for check in source.unit_checks:
175
+ definition = definitions.get(check.alias)
176
+ if (definition is None or definition.source != source.source
177
+ or definition.input_unit != check.input_unit):
178
+ raise ValueError('CAN单位核对别名/来源/input_unit与本次原声明不同')
179
+ if source.decode_scope == 'requested':
180
+ # requested可服务普通/混合/导出计划;只核实际需求,不由结果模式猜范围。
181
+ # 仍要求原完整CAN定位和通道吻合,固定ID必须覆盖每个实际所需字段。
182
+ # 实际需要CAN字段才导入来源包,保持纯预算/旧默认元数据的轻量导入。
183
+ from ..sources.can_spec import can_field_from_key
184
+ selected_field = can_field_from_key(definition.field)
185
+ if (selected_field.channel != source.channel
186
+ or selected_field.frame_id not in source.decode_frame_ids):
187
+ raise ValueError('requested固定解码集合须覆盖本次实际绑定字段及同来源通道')
188
+ for notice in source.frame_format_notices:
189
+ # 提示必须满足本次信号定位;省略的帧型允许由同次实际读取补齐。
190
+ from ..sources.can_spec import can_field_from_key
191
+ definition = definitions.get(notice.alias)
192
+ field = None if definition is None else can_field_from_key(definition.field)
193
+ if (definition is None or definition.source != source.source
194
+ or (field.channel,field.frame_id,field.signal)!=(notice.channel,notice.frame_id,notice.signal)
195
+ or field.is_extended is not None and field.is_extended!=notice.is_extended
196
+ or field.is_fd is not None and field.is_fd!=notice.requested_is_fd):
197
+ raise ValueError('CAN帧型提示必须对应本次原信号完整定位')
198
+
199
+ def estimated_bytes(self) -> int:
200
+ """在asdict/JSON复制前估算元数据与其临时对象开销。
201
+
202
+ 参数: 无。返回: 保守bytes估算。异常: 无,类型已经校验。
203
+ """
204
+ # 文本/tuple结构只读遍历,转换副本成本以16倍和固定余量保守覆盖。
205
+ # 空默认新字段不增加旧金额;非空定义/角色/CAN事实在asdict复制前递归覆盖。
206
+ return 8192 + 16 * sum(_metadata_size(getattr(self, field.name)) + 256 for field in fields(self)
207
+ if field.name not in ('signal_bindings', 'preset_bindings', 'can_sources', 'session_ids','text_can_sources','threshold_durations','detailed_diagnostics','retain_work','input_diagnostics','trace_requested','integrity_diagnostics','frame_format_notices','analysis_outcome')
208
+ or getattr(self, field.name))
209
+
210
+ def to_dict(self) -> dict:
211
+ """返回独立JSON兼容元数据,调用侧必须先预留estimated_bytes。
212
+
213
+ 参数: 无。
214
+ 返回: 独立JSON兼容dict。detailed_diagnostics=False时仅输出运行身份、
215
+ 后端、配置版本、时间解释、运行设置及适用的边界/限制/请求诊断;
216
+ signal_bindings、preset_bindings、can_sources等即使非空也不输出。
217
+ detailed_diagnostics=True才展开详细模型;空的可选明细继续按分支省略。
218
+ 模型持有字段不等于默认序列化一定包含该键。
219
+ 异常: 无预期异常;调用方须在复制前承担estimated_bytes预算。
220
+ """
221
+ if (not self.detailed_diagnostics):
222
+ # 从生成处只复制必要运行信息,不先展开完整绑定/来源后再隐藏。
223
+ result = {name: getattr(self, name) for name in ('run_id', 'plan_hash', 'backend',
224
+ 'config_version', 'started_at', 'device_label', 'software_version',
225
+ 'source_time_interpretation', 'parsing_policy', 'worker_config', 'retain_work', 'detailed_diagnostics')}
226
+ for name in ('input_identity', 'session_boundaries', 'session_ids', 'limitations', 'dependency_versions'):
227
+ if getattr(self, name):
228
+ result[name] = getattr(self, name)
229
+ if self.threshold_durations:
230
+ result['threshold_durations']=tuple(item.to_dict() for item in self.threshold_durations)
231
+ if self.trace_requested or self.integrity_diagnostics:
232
+ result['diagnostics']={'trace':self.trace_requested,'integrity':self.integrity_diagnostics}
233
+ result['input_diagnostics']=[item.to_dict() for item in self.input_diagnostics]
234
+ if self.frame_format_notices:
235
+ result['frame_format_notices']=[dict(source=source, **asdict(notice)) for source, notice in self.frame_format_notices]
236
+ if self.analysis_outcome is not None:
237
+ result['analysis_outcome']=self.analysis_outcome.to_dict()
238
+ return result
239
+ result = asdict(self)
240
+ if self.analysis_outcome is None:
241
+ result.pop('analysis_outcome')
242
+ else:
243
+ result['analysis_outcome']=self.analysis_outcome.to_dict()
244
+ if self.frame_format_notices:
245
+ result['frame_format_notices']=[dict(source=source, **asdict(notice)) for source, notice in self.frame_format_notices]
246
+ else:
247
+ result.pop('frame_format_notices')
248
+ if self.input_identity is None:
249
+ result.pop('input_identity') # 未计算的全量输入摘要不以占位文字冒充。
250
+ if self.threshold_durations:
251
+ result['threshold_durations'] = tuple(item.to_dict() for item in self.threshold_durations)
252
+ else:
253
+ result.pop('threshold_durations')
254
+ if not self.text_can_sources:
255
+ result.pop('text_can_sources')
256
+ if not self.session_ids:
257
+ result.pop('session_ids')
258
+ # 只有实际存在的详细事实才展开对应字段。
259
+ if self.signal_bindings:
260
+ for row, definition in zip(result['signal_bindings'], self.signal_bindings):
261
+ # dtype转明确文本;无效值里的非有限诊断用既有显式标签,不输出裸NaN。
262
+ row['dtype'] = definition.dtype.value
263
+ row['invalid_values'] = tuple({'diagnostic_float': 'nan' if isnan(value) else
264
+ 'inf' if value > 0 else '-inf'} if type(value) is float and not isfinite(value) else value
265
+ for value in definition.invalid_values)
266
+ row['semantic_status'] = 'not_provided' if definition.semantic_id is None else 'declared'
267
+ # 原基础策略拒绝全部非零质量位;声明名称不代表物理语义已核实。
268
+ row['quality_policy'] = {'mode': 'reject_nonzero',
269
+ 'forbidden_flags': tuple(flag.name for flag in QualityFlag),
270
+ 'forbidden_mask': sum(int(flag) for flag in QualityFlag)}
271
+ else:
272
+ result.pop('signal_bindings')
273
+ if not self.preset_bindings:
274
+ result.pop('preset_bindings')
275
+ if not self.can_sources:
276
+ result.pop('can_sources')
277
+ else:
278
+ # 仅实际差异增加提示;原无差异CAN清单的键和值完全保持。
279
+ for row, source in zip(result['can_sources'], self.can_sources):
280
+ if not source.frame_format_notices:
281
+ row.pop('frame_format_notices')
282
+ if source.input_check == 'full' and source.check_policy_version is None:
283
+ for key in ('input_check', 'time_scope', 'check_policy_version', 'retained_record_count',
284
+ 'full_check_count', 'selected_first_ns', 'selected_last_ns'):
285
+ row.pop(key)
286
+ if source.decode_scope == 'all':
287
+ # 新默认字段既不改变旧JSON,也不增加旧估算费用。
288
+ row.pop('decode_scope')
289
+ row.pop('decode_frame_ids')
290
+ if source.decoded_values_policy == 'all_values-v1':
291
+ # 兼容旧all与旧requested全字段事实,默认值不改变清单键或费用。
292
+ row.pop('decoded_values_policy')
293
+ return result
294
+
295
+
296
+ def _metadata_size(value) -> int:
297
+ """统计已校验元数据树的基础对象大小,不产生转换树。
298
+
299
+ 参数: value为元数据字段。返回: 基础bytes估算。异常: 无。
300
+ """
301
+ # 仅遍历已验证的有限模型,不泛化为raw_config或任意dataclass序列化。
302
+ if type(value) in (SignalDefinition, PresetBindingMetadata, PresetRoleMetadata,
303
+ CANSourceMetadata, CANUnitCheck, CANFrameFormatNotice,TextCANSourceMetadata,InputDiagnostic,
304
+ AnalysisOutcome, RuleOutcome):
305
+ return getsizeof(value) + sum(_metadata_size(getattr(value, field.name)) + 32 for field in fields(value)
306
+ if type(value) is not CANSourceMetadata or (
307
+ (field.name != 'frame_format_notices' or value.frame_format_notices)
308
+ and (field.name not in ('decode_scope', 'decode_frame_ids') or value.decode_scope != 'all')
309
+ and (field.name != 'decoded_values_policy' or value.decoded_values_policy != 'all_values-v1')
310
+ and (field.name not in ('input_check', 'time_scope', 'check_policy_version',
311
+ 'retained_record_count', 'full_check_count', 'selected_first_ns', 'selected_last_ns')
312
+ or value.check_policy_version is not None or value.input_check != 'full')))
313
+
314
+ if type(value) is tuple:
315
+ return getsizeof(value) + sum(_metadata_size(item) + 32 for item in value)
316
+ return getsizeof(value)
317
+
318
+
319
+ @dataclass(frozen=True)
320
+ class OutputManifest:
321
+ """保存成功发布目录、清单和固定白名单表行数;legacy只在启用时出现。"""
322
+
323
+ run_id: str
324
+ output_dir: Path
325
+ manifest_path: Path
326
+ output_files: tuple[Path, ...]
327
+ row_counts: tuple[tuple[str, int], ...]
328
+ status: str = 'completed'
329
+
330
+ def __post_init__(self) -> None:
331
+ """校验返回清单身份,不凭构造调用证明目录已发布。
332
+
333
+ 参数: 无。返回: None。异常: TypeError/ValueError为字段错误。
334
+ """
335
+ require_text(self.run_id, 'run_id')
336
+ if self.status != 'completed' or not isinstance(self.output_dir, Path) or not isinstance(self.manifest_path, Path):
337
+ raise ValueError('OutputManifest需completed和Path')
338
+ if type(self.output_files) is not tuple or any(not isinstance(path, Path) for path in self.output_files):
339
+ raise TypeError('输出路径需tuple Path')
340
+ if type(self.row_counts) is not tuple or any(type(item) is not tuple or len(item) != 2
341
+ or item[0] not in ('events', 'segments', 'calculations', 'message_calculations', 'legacy_contributions', 'sequences','contributions','input_trace','selections')
342
+ or type(item[1]) is not int or item[1] < 0 for item in self.row_counts):
343
+ raise ValueError('输出行数需固定表及非负原生int')