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,572 @@
1
+ """将已解码批次写入有限历史并单行重放,不重读旧输入。
2
+
3
+ 输入为来源描述、读取请求和typed SignalBatch;输出为样本/进度迭代器。
4
+ 每来源一个JSONL,列内有序数组以有限堆按时间/序号合并,保留所有同刻更新。
5
+ 共享ResourceBudget覆盖现有批次数组nbytes、Python容器、协议pending和行副本;
6
+ 预算在新增结构/写入前申请,累计spool包含失败部分,不承诺全进程RSS。
7
+ 来源在生成批次前的预算接线尚未在本组件实现,不能据此声称完整AnalysisRunner有限。
8
+ 失败保留诊断文件和原异常,关闭活动句柄;RefProjects与既有工作目录不修改。
9
+ """
10
+
11
+ # 标准库文件、摘要和有限堆;只读取解码后的数组,不依赖旧CAN模块。
12
+ from collections.abc import Iterator, Mapping
13
+ from contextlib import contextmanager
14
+ from dataclasses import fields, is_dataclass
15
+ from enum import Enum
16
+ from hashlib import sha256
17
+ import heapq
18
+ from pathlib import Path
19
+ from sys import getsizeof
20
+ from types import MappingProxyType
21
+ from ..core.numeric import ScalarValue
22
+ from ..core.types import QualityFlag, SignalDType
23
+ from ..results.budget import ResourceBudget
24
+ from ..results.codec import _estimate
25
+ from ..results.errors import AnalysisError, ResultClosedError, ResultFormatError
26
+ from ..results.spool import _cleanup_owner, _reserve_owned_ram, _release_owned_ram
27
+ from ..sources.models import SignalBatch, SourceDescription, ReadRequest
28
+ from ..sources.protocol import BatchValidator
29
+ from .history_records import (HistorySample, HistoryProgress, HistoryRecord,
30
+ estimate_record_bytes, encode_record, decode_record)
31
+ from .groups import DecodedTimeGroup, _TimeGroupIterator
32
+
33
+
34
+ def _metadata_bytes(value, depth: int = 0) -> int:
35
+ """估算已校验来源/请求的冻结元数据,不改变结果层封闭类型注册。
36
+
37
+ 参数: value为typed描述树,depth为递归深度。返回: 基础bytes。
38
+ 异常: ResultFormatError为深度或未支持元数据。
39
+ """
40
+ # 仅计数,不执行序列化或调用任意对象方法;所有描述先经typed模型检查。
41
+ if depth > 32:
42
+ raise ResultFormatError('历史元数据超过32层')
43
+ if is_dataclass(value) and not isinstance(value, type):
44
+ return getsizeof(value) + sum(256 + _metadata_bytes(getattr(value, field.name), depth + 1) for field in fields(value))
45
+ if isinstance(value, Mapping):
46
+ return getsizeof(value) + sum(128 + _metadata_bytes(key, depth + 1) + _metadata_bytes(item, depth + 1) for key, item in value.items())
47
+ if type(value) is tuple:
48
+ return getsizeof(value) + sum(32 + _metadata_bytes(item, depth + 1) for item in value)
49
+ if isinstance(value, Enum):
50
+ return 512
51
+ if value is None or type(value) in (str, int, bool, float):
52
+ return getsizeof(value) + 64
53
+ raise ResultFormatError('历史元数据类型无法估算')
54
+
55
+
56
+ def _pending_bytes(validator: BatchValidator) -> int:
57
+ """估算当前组去重状态,不保留历史所有sequence。
58
+
59
+ 参数: validator为一个来源协议状态。返回: 保守bytes。
60
+ 异常: 已校验状态不主动抛错。
61
+ """
62
+ # set每身份计256bytes,覆盖槽位、整数与局部复制;列固定项单独计。
63
+ return sum(512 + len(sequences) * 256 for _, sequences in validator.pending.values())
64
+
65
+
66
+ def _batch_bytes(batch: SignalBatch) -> int:
67
+ """核算调用方已提供批次数组和引用/原诊断容器。
68
+
69
+ 参数: batch为typed批次。返回: 数组精确nbytes加容器保守bytes。
70
+ 异常: 深度/类型估算错误传播,不省略长字段开销。
71
+ """
72
+ # 数组形状(N,)、整数ns和固定值dtype已经由SignalSeries检查。
73
+ # 定位可含CSVSourceRef子类,完整字段用描述估算;结果编码注册保持封闭。
74
+ return 4096 + sum(column.nbytes + 2048 + 16 * (_estimate((column.name, column.unit,
75
+ column.labels, column.original_values)) + _metadata_bytes(column.source_ref)) for column in batch.series.values())
76
+
77
+
78
+ class DecodedHistoryStore:
79
+ """维护一次任务的分源历史、协议状态和独立读取句柄。
80
+
81
+ building仅能追加,sealed要求所有来源EOF;failed/cancelled禁止重放。
82
+ close幂等关闭读取句柄并释放状态RAM,磁盘文件留作恢复证据,不递归删除。
83
+ 源数/字段数来自固定声明,样本数增长只体现在磁盘和整数计数中。
84
+ """
85
+
86
+ def __init__(self, budget: ResourceBudget, work_dir: str | Path,
87
+ descriptions: tuple[SourceDescription, ...], requests: Mapping[str, ReadRequest]):
88
+ """为新目录建立历史,检查来源/请求并先申请固定元数据预算。
89
+
90
+ 参数: budget为共享账本;work_dir必须不存在;descriptions/requests按来源对应。
91
+ 返回: building存储。异常: ValueError/TypeError/预算或实际目录创建原错;持续
92
+ 清理失败附history_cleanup_owner,已有目录不写失败标记也不抵销借用费用。
93
+ """
94
+ # 先检查固定配置,不能将同名来源后值覆盖前值或混用会话。
95
+ if not isinstance(budget, ResourceBudget) or type(descriptions) is not tuple or not descriptions or any(not isinstance(item, SourceDescription) for item in descriptions):
96
+ raise TypeError('历史需要账本和非空typed来源tuple')
97
+ names = tuple(item.name for item in descriptions)
98
+ if len(set(names)) != len(names) or not isinstance(requests, Mapping) or set(requests) != set(names) or any(not isinstance(item, ReadRequest) for item in requests.values()):
99
+ raise ValueError('历史来源和请求必须唯一对应')
100
+ if len({item.session_id for item in requests.values()}) != 1:
101
+ raise ValueError('一个历史任务只支持一个明确session')
102
+ path = Path(work_dir)
103
+ # 首次预算与文件检查前安装所有实际责任槽;None表示尚未分配对应容器。
104
+ self.budget = self._budget = budget
105
+ self.work_dir = path
106
+ self._state_cost = self._pending_cost = self._append_cost = 0
107
+ self._record_cost = self._diagnostic_cost = self._held_cost = 0
108
+ self.validators = self.paths = self.counts = self.hashes = self.line_limits = None
109
+ self._completions = self._iterators = self._groups = None
110
+ self._write_handle = self._diagnostic_handle = None
111
+ # 固定状态预算覆盖一个无缓冲写FD及路径借引用;来源再多也不同时持有多个写FD。
112
+ self._write_path = None
113
+ self.closed = self._closing = False
114
+ self.state = 'building'
115
+ try:
116
+ if path.exists():
117
+ raise FileExistsError(path)
118
+ # 保留原费用公式;reserve成功返回途中取消也由实际state槽接住。
119
+ state_cost = 8192 + len(names) * 4096 + 16 * _metadata_bytes(descriptions) + 16 * _metadata_bytes(tuple(requests.values()))
120
+ _reserve_owned_ram(self, state_cost, '_state_cost')
121
+ # 固定结构的所有分配都纳入释放边界,全部成功后才创建外部目录。
122
+ self.validators = {item.name: BatchValidator(item, requests[item.name]) for item in descriptions}
123
+ self.paths = {name: path / f'{name}.jsonl' for name in names}
124
+ self.counts = {name: [0, 0] for name in names}
125
+ self.hashes = {name: sha256() for name in names}
126
+ self.line_limits = {name: 1 for name in names}
127
+ self._completions: dict[str, HistoryProgress] = {}
128
+ self.max_line_bytes = max(1, budget.memory_budget_bytes // 256)
129
+ self.reader_cost = self.max_line_bytes * 64 + 8192
130
+ self._iterators: set[_HistoryIterator] = set()
131
+ self._groups: set[_TimeGroupIterator] = set()
132
+ path.mkdir(parents=True, exist_ok=False)
133
+ except BaseException as exc:
134
+ # mkdir原错不被释放失败覆盖;不再对半构造对象猜费用或重复释放state。
135
+ self.state = 'cancelled' if isinstance(exc, (KeyboardInterrupt, SystemExit)) else 'failed'
136
+ _cleanup_owner(self, exc, 'history_cleanup_owner', '解码历史构造')
137
+ raise
138
+
139
+ def _check(self, state: str) -> None:
140
+ """检查生命周期,不让关闭或失败历史继续使用。
141
+
142
+ 参数: state为所需状态。返回: None。
143
+ 异常: ResultClosedError或AnalysisError为状态不允许。
144
+ """
145
+ # closed先判断,避免关闭后又读损坏文件。
146
+ if self.closed or self._closing:
147
+ raise ResultClosedError('解码历史已关闭或正在清理')
148
+ if self.state != state:
149
+ raise AnalysisError(f'历史状态{self.state},需要{state}')
150
+
151
+ def _write_bytes(self, handle, payload: bytes) -> None:
152
+ """先申请累计磁盘额度,循环完成合法短写。
153
+
154
+ 参数: handle为二进制文件,payload为单行bytes。返回: None。
155
+ 异常: 超限/OSError/零写立即失败,原部分文件保留。
156
+ """
157
+ self.budget.reserve_spool(len(payload))
158
+ offset = 0
159
+ while offset < len(payload):
160
+ # memoryview避免每次短写复制剩余整行。
161
+ written = handle.write(memoryview(payload)[offset:])
162
+ if written is None or written <= 0 or written > len(payload) - offset:
163
+ raise OSError('历史文件写入无进展或返回非法长度')
164
+ offset += written
165
+
166
+ @contextmanager
167
+ def _writer(self, slot, path, mode):
168
+ """复用当前来源的无缓冲写FD,切换来源或失败时关闭,诊断仍逐次关闭。
169
+
170
+ 参数: slot为写入或诊断句柄槽;path/mode为原路径和原打开方式。
171
+ 返回: 上下文内借用实际FileIO。异常: 打开或写入原错;已有主错时关闭
172
+ 副错只加note,失败FD留父close重试。成功数据批不关闭,EOF或seal/close收尾。
173
+ """
174
+ persistent = slot == '_write_handle'
175
+ if persistent and self._write_handle is not None and self._write_path != path:
176
+ # 先关旧来源再打开新来源,关闭失败立即传播,禁止覆盖原FD的恢复责任。
177
+ self._close_handle(slot)
178
+ if getattr(self, slot) is None:
179
+ setattr(self, slot, path.open(mode, buffering=0))
180
+ if persistent:
181
+ self._write_path = path
182
+ elif not persistent:
183
+ raise AnalysisError('历史仍有未关闭诊断FD,不能覆盖恢复责任')
184
+ failure = None
185
+ try:
186
+ yield getattr(self, slot)
187
+ except BaseException as exc:
188
+ failure = exc
189
+ raise
190
+ finally:
191
+ # failure明确来自本次with主体,不用调用方外层except状态猜真正主异常。
192
+ if not persistent or failure is not None:
193
+ self._close_handle(slot, failure)
194
+
195
+ def _close_handle(self, slot, primary=None):
196
+ """按实际FD状态关闭一个父持有句柄,实际未关时保留原对象。
197
+
198
+ 参数: slot为本父句柄字段;primary为本次已传播主错误或None。
199
+ 返回: None。异常: 无主错时原close错误传播;有主错时只加note,最高
200
+ history仍持失败句柄。释放后取消也以真实closed完成最小解除。
201
+ """
202
+ handle = getattr(self, slot)
203
+ if handle is None:
204
+ return
205
+ try:
206
+ handle.close()
207
+ if not handle.closed:
208
+ raise AnalysisError('历史写FD close返回但实际尚未关闭')
209
+ except BaseException as cleanup:
210
+ if primary is None:
211
+ raise
212
+ primary.add_note(f'历史{slot}关闭附加失败: {type(cleanup).__name__}')
213
+ finally:
214
+ if handle.closed:
215
+ setattr(self, slot, None)
216
+ if slot == '_write_handle':
217
+ self._write_path = None
218
+
219
+ def _write_record(self, handle, name: str, record: HistoryRecord) -> None:
220
+ """申请单行编码临时RAM,写入成功后更新摘要。
221
+
222
+ 参数: handle/name为当前来源文件,record为typed记录。返回: None。
223
+ 异常: 格式/预算/文件错误传播,finally释放临时RAM。
224
+ """
225
+ cost = estimate_record_bytes(record)
226
+ failure = None
227
+ try:
228
+ _reserve_owned_ram(self, cost, '_record_cost')
229
+ payload = encode_record(record, self.max_line_bytes)
230
+ self._write_bytes(handle, payload)
231
+ self.hashes[name].update(payload)
232
+ # 实际成功写入最大行是读预算的可靠上限,避免源数>4永远无法同时开游标。
233
+ self.line_limits[name] = max(self.line_limits[name], len(payload))
234
+ except BaseException as exc:
235
+ failure = exc
236
+ raise
237
+ finally:
238
+ # 编码/写入原错优先;释放取消保留单行槽给最高history重试,不丢账或盖根因。
239
+ try:
240
+ _release_owned_ram(self, self._record_cost, '_record_cost')
241
+ except BaseException as cleanup:
242
+ if failure is None:
243
+ raise
244
+ failure.add_note(f'历史编码槽清理附加失败: {type(cleanup).__name__}')
245
+
246
+ def append(self, batch: SignalBatch) -> None:
247
+ """保存一批的全部异步样本和最终进度,空批仍写一条记录。
248
+
249
+ 参数: batch为已经归一化的typed批次。返回: None。
250
+ 异常: AnalysisError保留格式/协议/预算/磁盘异常链;取消原样传播。
251
+ 边界: 接收到的数组已经分配,本方法计入其占用但不能追溯控制该分配。
252
+ """
253
+ self._check('building')
254
+ try:
255
+ if not isinstance(batch, SignalBatch) or batch.source not in self.validators:
256
+ raise ValueError('历史批次不属于声明来源')
257
+ validator = self.validators[batch.source]
258
+ batch_index, total = self.counts[batch.source]
259
+ if batch_index >= 2 ** 63 - 1 or total + batch.sample_count >= 2 ** 63:
260
+ raise OverflowError('历史批次/样本计数超过int64')
261
+ # 验证器会复制pending,并可能为本批所有sequence建set,提前覆盖最坏瞬时开销。
262
+ growth = batch.sample_count * 256 + len(batch.series) * 512
263
+ requested = _batch_bytes(batch) + _pending_bytes(validator) + growth + 4096 + len(batch.series) * 512
264
+ _reserve_owned_ram(self, requested, '_append_cost')
265
+ validator.accept(batch)
266
+ # 把新增协议状态的预留从临时lease转为持久账目,不在分配后再申请。
267
+ new_pending = sum(_pending_bytes(item) for item in self.validators.values())
268
+ retained = max(0, new_pending - self._pending_cost)
269
+ if new_pending < self._pending_cost:
270
+ _release_owned_ram(self, self._pending_cost - new_pending, '_pending_cost')
271
+ else:
272
+ # 同一owner内部把本批已付金额交给协议pending,不再申请或借余额补账。
273
+ self._append_cost -= retained
274
+ self._pending_cost += retained
275
+ # 每列仅持一个索引,有限堆按(time,sequence,列顺序)合并,不拼接全批列表。
276
+ columns = tuple(batch.series.values())
277
+ heap = [(int(column.time_ns[0]), int(column.sequence[0]), order, 0)
278
+ for order, column in enumerate(columns) if len(column.time_ns)]
279
+ heapq.heapify(heap)
280
+ with self._writer('_write_handle', self.paths[batch.source], 'ab') as handle:
281
+ while heap:
282
+ time, sequence, order, index = heapq.heappop(heap)
283
+ column = columns[order]
284
+ physical = column.values[index].item()
285
+ original_present = column.original_values is not None
286
+ original = column.original_values[index] if original_present else None
287
+ valid = bool(column.valid[index])
288
+ logical = column.labels[physical] if valid and column.dtype is SignalDType.ENUM else physical
289
+ # 无效原诊断仅作诊断,不参与计算;数组占位仍独立保留。
290
+ if not valid and original_present:
291
+ logical = original
292
+ value = ScalarValue(logical, column.dtype, valid, QualityFlag(int(column.quality[index])), column.labels)
293
+ record = HistorySample(batch_index, column.name, time, sequence, physical, value,
294
+ column.unit, column.source_ref[index], original_present, original)
295
+ self._write_record(handle, batch.source, record)
296
+ next_index = index + 1
297
+ if next_index < len(column.time_ns):
298
+ heapq.heappush(heap, (int(column.time_ns[next_index]), int(column.sequence[next_index]), order, next_index))
299
+ # 进度必须在全部样本之后写;部分批次故障不会形成完成历史。
300
+ progress = HistoryProgress(batch_index, batch.source, batch.session_id,
301
+ batch.sample_count, batch.watermark_ns, batch.source_eof, batch.observed_end_ns)
302
+ self._write_record(handle, batch.source, progress)
303
+ if batch.source_eof:
304
+ # 成功EOF必须先真实关闭写FD,随后才登记该来源完成;失败仍走原poison/清理路径。
305
+ self._close_handle('_write_handle')
306
+ self.counts[batch.source] = [batch_index + 1, total + batch.sample_count]
307
+ if batch.source_eof:
308
+ # 固定每来源一条完成事实,不收集所有历史进度;状态预估覆盖这些冻结对象。
309
+ self._completions[batch.source] = progress
310
+ # 正常金额和释放时刻保持;交接取消同样会进入失败路径而不能伪报完成。
311
+ _release_owned_ram(self, self._append_cost, '_append_cost')
312
+ except BaseException as exc:
313
+ self.state = 'cancelled' if isinstance(exc, (KeyboardInterrupt, SystemExit)) else 'failed'
314
+ # 最小失败标记尽力写入;额度/物理磁盘不足时不覆盖真正失败原因。
315
+ self._record_failure(exc)
316
+ _cleanup_owner(self, exc, 'history_cleanup_owner', '解码历史写入')
317
+ if isinstance(exc, (KeyboardInterrupt, SystemExit)):
318
+ raise
319
+ error = AnalysisError('已解码历史写入失败')
320
+ recovery = getattr(exc, 'history_cleanup_owner', None)
321
+ if recovery is not None:
322
+ error.history_cleanup_owner = recovery
323
+ for note in getattr(exc, '__notes__', ()):
324
+ error.add_note(note)
325
+ raise error from exc
326
+
327
+ def _record_failure(self, exc: BaseException) -> None:
328
+ """尽力保存有界失败标记,不将可能巨大的异常文本装入内存。
329
+
330
+ 参数: exc为原失败。返回: None。异常: 写标记失败被记录为原异常附注。
331
+ """
332
+ try:
333
+ _reserve_owned_ram(self, 8192, '_diagnostic_cost')
334
+ payload = f'state={self.state}\nexception={type(exc).__name__}\n'.encode('utf-8')
335
+ with self._writer('_diagnostic_handle', self.work_dir / 'failure.txt', 'xb') as handle:
336
+ self._write_bytes(handle, payload)
337
+ except BaseException as diagnostic:
338
+ # 系统取消原因仍在原异常链;这里仅作最小诊断收尾。
339
+ exc.add_note(f'历史失败标记未写完: {type(diagnostic).__name__}')
340
+ finally:
341
+ # 诊断自身也可能在reserve/release返回途中取消,未抵销金额仍归history。
342
+ try:
343
+ # 诊断FD持续未关时仍保留原8192描述费,只有父close能完成这笔责任。
344
+ if self._diagnostic_handle is None:
345
+ _release_owned_ram(self, self._diagnostic_cost, '_diagnostic_cost')
346
+ except BaseException as cleanup:
347
+ exc.add_note(f'历史失败标记槽清理附加失败: {type(cleanup).__name__}')
348
+
349
+ def seal(self) -> None:
350
+ """所有配置来源EOF后封存,禁止用单文件EOF代替来源终点。
351
+
352
+ 参数: 无。返回: None。异常: AnalysisError为未结束来源或错误状态。
353
+ """
354
+ self._check('building')
355
+ if any(not validator.ended for validator in self.validators.values()):
356
+ raise AnalysisError('全部来源EOF前不能封存解码历史')
357
+ # 正常EOF追加已经关闭写FD;封存再次收尾,不能把未关写FD交给重放阶段。
358
+ self._close_handle('_write_handle')
359
+ self.state = 'sealed'
360
+
361
+ def iter_records(self, source: str) -> Iterator[HistoryRecord]:
362
+ """建立一个有独立文件位置的有限重放迭代器。
363
+
364
+ 参数: source为声明来源名。返回: typed记录Iterator。
365
+ 异常: 关闭/未封存/未知来源/预算/打开错误。
366
+ """
367
+ self._check('sealed')
368
+ if source not in self.validators:
369
+ raise ValueError('未知历史来源')
370
+ iterator = _HistoryIterator(self, source)
371
+ try:
372
+ self._iterators.add(iterator)
373
+ except BaseException as exc:
374
+ # 注册未成功时对象还未返回;保留注册原错并由正式属性交出持续清理失败的实际reader。
375
+ _cleanup_owner(iterator, exc, 'history_iterator_cleanup_owner', '历史游标注册')
376
+ raise
377
+ return iterator
378
+
379
+ @property
380
+ def source_completions(self) -> Mapping[str, HistoryProgress]:
381
+ """读取已封存来源EOF/终点原事实,不推断未知终点或有效期。
382
+
383
+ 参数: 无。返回: 只读Mapping;仅owner仍打开时可用。
384
+ 异常: 关闭或未封存的历史状态错误。
385
+ """
386
+ self._check('sealed')
387
+ return MappingProxyType(self._completions)
388
+
389
+ def iter_groups(self, *, sources=None) -> Iterator[DecodedTimeGroup]:
390
+ """按完整同时间组重放已封存历史,注册关闭所有权。
391
+
392
+ 参数: sources为来源名tuple或None;None保留全部来源,空tuple不打开源游标。
393
+ 返回: 独立组Iterator;组只包含所选来源,返回后须及时消费。
394
+ 异常: 生命周期/来源子集类型、重复、未知名称/源游标/预算/历史读取错误。
395
+ 边界: 子集EOF只证明所选来源;全历史摘要验证须另行遍历全部来源。
396
+ """
397
+ self._check('sealed')
398
+ # 默认参数沿用原构造调用及费用;显式子集的校验和预约由同一真实游标负责。
399
+ iterator = _TimeGroupIterator(self) if sources is None else _TimeGroupIterator(self, sources=sources)
400
+ try:
401
+ self._groups.add(iterator)
402
+ except BaseException as exc:
403
+ # 未登记的实际group仍拥有子reader;清理失败不能替换注册原错或丢失顶层恢复责任。
404
+ _cleanup_owner(iterator, exc, 'time_group_iterator_cleanup_owner', '时间组游标注册')
405
+ raise
406
+ return iterator
407
+
408
+ def close(self) -> None:
409
+ """幂等关闭所有活动迭代器并释放协议/固定状态RAM,保留历史文件。
410
+
411
+ 参数: 无。返回: None。异常: 原句柄/预算/取消错误附history_cleanup_owner;
412
+ 子reader或任一费用未完成时保留父合同和实际责任,恢复后同一close重试。
413
+ """
414
+ if self.closed:
415
+ return
416
+ self._closing = True
417
+ try:
418
+ cleanup_error = None
419
+ for slot in ('_write_handle', '_diagnostic_handle'):
420
+ try:
421
+ self._close_handle(slot)
422
+ except BaseException as exc:
423
+ if cleanup_error is None:
424
+ cleanup_error = exc
425
+ else:
426
+ cleanup_error.add_note(f'其他历史写FD关闭失败: {type(exc).__name__}')
427
+ for iterator in tuple(self._groups or ()) + tuple(self._iterators or ()):
428
+ try:
429
+ iterator.close()
430
+ except BaseException as exc:
431
+ # 一个句柄关闭出错仍尝试其余句柄,最后报告首个错误。
432
+ if cleanup_error is None:
433
+ cleanup_error = exc
434
+ else:
435
+ cleanup_error.add_note(f'其他历史游标关闭失败: {type(exc).__name__}')
436
+ if cleanup_error is not None:
437
+ raise cleanup_error
438
+ # 全部实际子游标成功关闭后才清元数据,失败的FD仍能用原owner重试。
439
+ for slot in ('validators', 'paths', 'counts', 'hashes', 'line_limits', '_completions'):
440
+ value = getattr(self, slot)
441
+ if value is not None:
442
+ value.clear()
443
+ for slot in ('_record_cost', '_diagnostic_cost', '_append_cost', '_pending_cost', '_state_cost'):
444
+ _release_owned_ram(self, getattr(self, slot), slot)
445
+ if self._held_cost == 0:
446
+ self.closed = True
447
+ except BaseException as exc:
448
+ exc.history_cleanup_owner = self
449
+ raise
450
+
451
+
452
+ class _HistoryIterator:
453
+ """单行读取、核对批次计数与SHA256,不装入完整历史。
454
+
455
+ cost与_held_cost记录同一笔自有reader费用;未返回构造或注册失败通过原异常恢复。
456
+ handle与登记只在真实FD关闭、费用抵销后解除,不归还调用方history的费用。
457
+ """
458
+
459
+ def __init__(self, owner: DecodedHistoryStore, source: str):
460
+ """先预留解析/句柄RAM再打开单个来源文件。
461
+
462
+ 参数: owner为封存历史,source为来源名。返回: 新独立迭代器。
463
+ 异常: 预算/打开/取消原错,持续清理失败时从history_iterator_cleanup_owner恢复close。
464
+ """
465
+ # 行上限来自封存前实际成功写入的数据,读取先限长再解析,篡改长行不能越过预算。
466
+ self.max_line_bytes = owner.line_limits[source]
467
+ # 8192字节buffer只用于新history有限预读;额外16384先覆盖其存储与对象,再open。
468
+ # 原逻辑行限长、真实空读EOF/摘要/计数不变,底层调用次数及取消时机不保证相同。
469
+ cost = self.max_line_bytes * 64 + 8192 + 16384
470
+ # 最小关闭字段先建立,固定申请/摘要/打开都纳入同一所有权保护区。
471
+ self.owner, self.source, self.handle, self.cost = owner, source, None, 0
472
+ self._budget, self._held_cost = owner.budget, 0
473
+ self.closed = self._closing = self._verified_eof = False
474
+ try:
475
+ # finally只围绕本次直接预约登记,成功后取消也保留实际自有费用。
476
+ _reserve_owned_ram(self, cost, 'cost')
477
+ # 摘要/固定结构先建好,文件最后打开,后段初始化失败不会泄漏句柄或预留。
478
+ self.batch_index = self.samples = self.total = 0
479
+ self.ended = False
480
+ # 只有真实读到文件EOF并完成摘要/计数核对才能提供此证明,提前close不算。
481
+ self._verified_eof = False
482
+ self.digest = sha256()
483
+ self.handle = owner.paths[source].open('rb', buffering=8192)
484
+ except BaseException as exc:
485
+ # 未返回的self仍有真实费用/句柄,瞬时清理重试一次,持续失败挂原错供调用方恢复。
486
+ _cleanup_owner(self, exc, 'history_iterator_cleanup_owner', '历史游标构造')
487
+ raise
488
+
489
+ def __iter__(self) -> '_HistoryIterator':
490
+ """返回本次独立游标。
491
+
492
+ 参数: 无。返回: self。异常: 无。
493
+ """
494
+ return self
495
+
496
+ @property
497
+ def verified_eof(self) -> bool:
498
+ """读取实际文件EOF核对事实。参数: 无。返回: bool。异常: 无;提前close为False。"""
499
+ return self._verified_eof
500
+
501
+ def __next__(self) -> HistoryRecord:
502
+ """读取一行并检查身份、批次结构及终点完整性。
503
+
504
+ 参数: 无。返回: 一条HistoryRecord。
505
+ 异常: StopIteration为已校验完整EOF;损坏/关闭/实际读错误传播并关闭句柄。
506
+ """
507
+ if self.owner.closed or self.owner._closing:
508
+ raise ResultClosedError('解码历史已关闭或正在清理')
509
+ if self.closed:
510
+ raise StopIteration
511
+ # 文件已关闭但预算交接尚未完成时只允许重试close,不从半关闭游标读取。
512
+ if self._closing:
513
+ raise ResultClosedError('解码历史游标正在关闭')
514
+ try:
515
+ payload = self.handle.readline(self.max_line_bytes + 1)
516
+ if not payload:
517
+ # 提前迭代终止不算全部通过;只有实际EOF才核对完整摘要与计数。
518
+ if not self.ended or self.samples or [self.batch_index, self.total] != self.owner.counts[self.source] or self.digest.digest() != self.owner.hashes[self.source].digest():
519
+ raise ResultFormatError('解码历史EOF、计数或摘要不完整')
520
+ self._verified_eof = True
521
+ self.close()
522
+ raise StopIteration
523
+ if self.ended:
524
+ raise ResultFormatError('历史来源EOF之后仍有记录')
525
+ record = decode_record(payload, self.max_line_bytes)
526
+ if record.batch_index != self.batch_index:
527
+ raise ResultFormatError('历史批次号不连续')
528
+ validator = self.owner.validators[self.source]
529
+ if isinstance(record, HistorySample):
530
+ if record.source_ref.source_name != self.source or record.source_ref.session_id != validator.request.session_id or record.name not in validator.request.signal_names:
531
+ raise ResultFormatError('历史样本身份/投影冲突')
532
+ self.samples += 1
533
+ if self.samples > validator.request.batch_rows:
534
+ raise ResultFormatError('历史批次样本超限')
535
+ else:
536
+ if record.source != self.source or record.session_id != validator.request.session_id or record.sample_count != self.samples:
537
+ raise ResultFormatError('历史进度身份/样本计数冲突')
538
+ self.total += self.samples
539
+ self.samples = 0
540
+ self.batch_index += 1
541
+ self.ended = record.source_eof
542
+ self.digest.update(payload)
543
+ return record
544
+ except BaseException as exc:
545
+ # EOF/解析/IO原错保持;清理失败只附notes与恢复入口,不改读取、摘要或计数算法。
546
+ _cleanup_owner(self, exc, 'history_iterator_cleanup_owner', '历史游标读取')
547
+ raise
548
+
549
+ def close(self) -> None:
550
+ """关闭单个游标并抵销一次预留,重复关闭安全。
551
+
552
+ 参数: 无。返回: None,幂等。
553
+ 异常: 文件/预算/取消传播,真实文件未关闭或预算未抵销时保留登记供重试。
554
+ """
555
+ if self.closed:
556
+ # 已抵销但脱链返回取消的孤儿,重试只清登记,不再次扣账。
557
+ self.owner._iterators.discard(self)
558
+ return
559
+ self._closing = True
560
+ try:
561
+ if self.handle is not None:
562
+ self.handle.close()
563
+ finally:
564
+ # 以真实FD.closed判断关闭返回取消;文件未关闭不释放其预留或丢重试权。
565
+ if self.handle is None or self.handle.closed:
566
+ try:
567
+ _release_owned_ram(self, self.cost, 'cost')
568
+ finally:
569
+ if self.cost == 0:
570
+ # 运行绑定在实际EOF关闭之后还需读取最终SHA,保留固定大小摘要对象。
571
+ self.closed, self.cost = True, 0
572
+ self.owner._iterators.discard(self)