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,948 @@
1
+ """把同次旧CAN逐帧输出接成预算信号批,保留原始帧与真实观测证明。
2
+
3
+ adapter构造/describe只检查声明并创建新工作目录,不读BLF/DBC、不启动进程。
4
+ 独立CANObservationRead首次next才启动CAN读取进程,先复制同次READY并核实际非空DBC单位,
5
+ 再逐原yield读取;显式all每帧调用一次原parse,仅retain_raw_frames时将全部原帧写入
6
+ RawFrameStore。所有原帧计读取数,时间按source/selected/none分别采集,
7
+ 本层收到的signals是运行实际需要的定义;requested只解码这些字段和消息指标所需ID,
8
+ 只传输所需值;auto跳过无用途字段与时间,full/source保原完整检查。显式all保留原全解码检查。
9
+ 当前原帧的匹配别名按全部列样本总和batch_rows拆批;其他报文
10
+ 不更新此信号,匹配定位但原dict缺key则None→MISSING,不延用旧值或猜DECODE_ERROR。
11
+
12
+ 时间仅原浮点秒convert_time(...,'s')加一次offset。当前ns-1才作为非EOF watermark,
13
+ 所以同刻后继不会被提前承诺;末次真实EOF交付独立空批,下一次StopIteration前须
14
+ 确认CAN读取进程退出、raw writer封口、validator结束和本次输入关闭成功,才开放CANObservation。
15
+ runtime_metadata保原READY冻结键形状,None/空unit原样表示未核实,不能假verified。
16
+ take_raw_store只在完成后一次移交原store;未移交则本read.close负责,不关已移交store。
17
+ 显式capture_message_updates=True时,同一record在raw追加后另存完整decoded仓,
18
+ 不在别名拆批处重复捕获。消息仓保同次READY.profile/read_identity和原量化事实,
19
+ 真EOF才封口;take_message_store同样先安装接收父,再撤本子责任。默认关闭时
20
+ 不创建消息目录或额外预约,原PULL/parse、字段投影与批次协议保持。
21
+
22
+ 来源/请求/同次元数据、当前原记录、装箱与validator动态去重状态分别先付费。
23
+ 未返回read及CAN读取进程/raw构造责任均真实安装后再推进,持续清理失败保最高恢复owner;
24
+ close可重试且不抵销借款。完成read脱离adapter活登记,事实可活到自身close。
25
+ 全部只用新分析层和已有pack_decoded两后端,不修改旧链、重复读DBC或声明RSS上限。
26
+ batch_read默认自动选择:requested由can_batch_reader接有限批,all保原逐条读取;
27
+ 显式bool仍覆盖自动选择。未保存raw由公开元数据None/None/0明确表达。
28
+ 直接累计且没有普通样本请求时,[home]另核两段真实输入字节的SHA256:全部原时间、
29
+ 所需记录的长度与JSON;selected/none的全时间SHA为None。只借用已严格解包的原包,不重编码或保存副本;真实EOF及
30
+ 进程关闭后才开放指纹。它不是普通信号样本摘要,read关闭后由接收方自付保留费用。
31
+ """
32
+
33
+ # 数值归一化复用既有pack;外层只处理实际来源身份、原行进度和资源责任。
34
+ from dataclasses import dataclass
35
+ import hashlib
36
+ from pathlib import Path
37
+ from uuid import uuid4
38
+ from ..core.binding import SignalDefinition
39
+ from ..core.validation import require_identifier, require_text
40
+ from ..legacy.process_read import LegacyCANProcessRead
41
+ from ..legacy.raw_store import RawFrameStore
42
+ from ..legacy.message_store import DecodedMessageStore, MAX_DECODED_MESSAGE_ROW_BYTES
43
+ from ..legacy.records import LegacyCANRequest, field_to_dict
44
+ from ..legacy.batch_wire import HEADER
45
+ from ..legacy.batch_worker import REQUESTED_VALUES_POLICY
46
+ from ..results.budget import ResourceBudget
47
+ from ..results.errors import ResultClosedError
48
+ from ..results.spool import _cleanup_owner, _reserve_owned_ram, _release_owned_ram
49
+ from ..sources.can_spec import LegacyCANSpec, CANSourceRef, can_field_from_key
50
+ from ..sources.descriptions import describe_fields, source_timebase_identity
51
+ from ..sources.models import (ReadRequest, SignalBatch, SourceDescription, SourceCapabilities, freeze_metadata)
52
+ from ..sources.packing import pack_decoded
53
+ from ..sources.protocol import BatchValidator, SourceClosedError, SourceReadError
54
+ from ..timebase.conversion import checked_add_ns, convert_time, require_int64_ns
55
+ from .history import _metadata_bytes, _pending_bytes
56
+
57
+
58
+ @dataclass(frozen=True)
59
+ class CANObservation:
60
+ """保存本read实际全部yield的完成事实,不接受请求范围作为原行首末。"""
61
+
62
+ source: str # 当前来源名。
63
+ session_id: str # 原会话。
64
+ request: ReadRequest # 创建本read的原对象,不按值重建。
65
+ read_identity: str # 每个read独立UUID。
66
+ first_ns: int | None # 全部原yield经一次映射的首端,全空为None。
67
+ last_ns: int | None # 全部原yield经一次映射的末端,全空为None。
68
+ row_count: int # 包含未知ID/空投影的原yield数,不是样本数。
69
+ source_eof: bool # 仅真实完整完成为True。
70
+ time_scope: str = 'source' # source为全来源;selected仅目标;none未采集。
71
+ retained_record_count: int = 0 # 本次实际保留记录数,不等于贡献数。
72
+ full_check_count: int = 0 # 按需策略下非原生输入的完整检查回退数。
73
+
74
+ def __post_init__(self):
75
+ """核完成事实结构。参数: 无。返回: None。异常: 类型/会话/端点或EOF矛盾。
76
+ """
77
+ require_identifier(self.source, 'can_observation.source')
78
+ require_identifier(self.session_id, 'can_observation.session_id')
79
+ require_text(self.read_identity, 'can_observation.read_identity')
80
+ if (not isinstance(self.request, ReadRequest) or self.request.session_id != self.session_id
81
+ or type(self.row_count) is not int or self.row_count < 0 or self.source_eof is not True):
82
+ raise ValueError('CAN观测需原请求、非负原行数及完整EOF')
83
+ if self.time_scope not in ('none', 'selected', 'source'):
84
+ raise ValueError('CAN观测时间范围非法')
85
+ if (type(self.retained_record_count) is not int or not 0 <= self.retained_record_count <= self.row_count
86
+ or type(self.full_check_count) is not int or not 0 <= self.full_check_count <= self.row_count):
87
+ raise ValueError('CAN观测保留/完整回退计数非法')
88
+ if self.time_scope == 'none':
89
+ if self.first_ns is not None or self.last_ns is not None:
90
+ raise ValueError('未采集时间不能声明首末')
91
+ return
92
+ if self.row_count == 0 or self.time_scope == 'selected' and not self.retained_record_count:
93
+ if self.first_ns is not None or self.last_ns is not None:
94
+ raise ValueError('空CAN输入没有可猜测首末')
95
+ else:
96
+ require_int64_ns(self.first_ns)
97
+ require_int64_ns(self.last_ns)
98
+ if self.first_ns > self.last_ns:
99
+ raise ValueError('CAN观测时间不能回退')
100
+
101
+
102
+ class BudgetedLegacyCANSourceAdapter:
103
+ """拥有静态来源描述和活read登记,完成read与已移交store由新父负责。"""
104
+
105
+ def __init__(self, budget, spec, session_id, signals, *, backend='numpy', work_dir,
106
+ capture_message_updates=False, batch_read=None, retain_raw_frames=True,
107
+ input_check='full', time_scope='source',
108
+ message_frame_ids=None,extra_fields=(), message_consumer=None, cycle_fields=(), metadata_fields=(), message_keys=(),
109
+ input_fingerprints=True, history_integrity=True, frame_observer=None):
110
+ """先付声明费用,建立显式新工作根但不访问原输入。
111
+
112
+ 参数: budget为共享ResourceBudget;spec为LegacyCANSpec;session_id为会话;
113
+ signals为SignalDefinition tuple;backend为numpy/reference;work_dir必须全新;
114
+ capture_message_updates为严格bool,默认False,仅显式开启才存同次decoded仓;
115
+ batch_read默认None自动选择:requested为True,all为False;显式bool保持选择,
116
+ requested不能显式False;retain_raw_frames决定是否保存原帧;
117
+ message_frame_ids为需要完整逐消息记录的ID,None保留所有实际返回记录。
118
+ extra_fields只为显式报文重建传递连续量/复用选择器,不生成普通信号别名。
119
+ message_keys为没有数值依赖也须触发的完整报文定位;
120
+ message_consumer可选同步接收共同消息模型;只传signals所需值,保留对象须由消费者另付费用。
121
+ cycle_fields独立请求初始化周期;metadata_fields仅请求字段候选,两者不添加解码值或普通样本。
122
+ frame_observer仅显式导出时接收原帧身份,不保存额外载荷或扫描文件。
123
+ input_fingerprints仅控制可选输入摘要,默认保持旧调用;必要值检查始终执行。
124
+ input_check/time_scope为计划固定的检查和时间范围;低层默认full/source保旧入口。
125
+ spec.decode_scope=requested使用批协议,将实际需要的字段及指标ID固定为解码集合;
126
+ 其他帧仍读取并检查原字段/时间,但不再生成或检查其解码值。
127
+ 返回: 静态adapter。异常: 原配置/目录/预算/取消;持续清理失败附can_source_cleanup_owner。
128
+ """
129
+ if batch_read is None and type(spec) is LegacyCANSpec:
130
+ batch_read = (spec.decode_scope == 'requested' or len(spec.input_paths) > 1
131
+ or spec.decode_policy != 'legacy' or bool(cycle_fields) or bool(metadata_fields))
132
+ if (not isinstance(budget, ResourceBudget) or type(spec) is not LegacyCANSpec
133
+ or type(signals) is not tuple or any(type(item) is not SignalDefinition for item in signals)
134
+ or backend not in ('numpy', 'reference') or not isinstance(work_dir, (str, Path))
135
+ or any(type(value) is not bool for value in (capture_message_updates, batch_read, retain_raw_frames, input_fingerprints, history_integrity))
136
+ or message_frame_ids is not None and (type(message_frame_ids) is not tuple
137
+ or any(type(value) is not int or not 0 <= value <= 0x1fffffff for value in message_frame_ids))):
138
+ raise TypeError('CAN来源需预算、静态spec、定义tuple、后端及新工作目录')
139
+ from ..sources.can_updates import require_message_keys
140
+ require_message_keys(message_keys, channel=spec.channel)
141
+ if message_keys and message_consumer is None:
142
+ raise ValueError('消息触发定位必须有实际消费者')
143
+ if message_keys:
144
+ message_frame_ids = tuple(sorted(set(message_frame_ids or ()) | {key[1] for key in message_keys}))
145
+ if message_consumer is not None and not callable(message_consumer):
146
+ raise TypeError('message_consumer需要同步可调用对象')
147
+ if not batch_read and (len(spec.input_paths) > 1 or spec.decode_policy != 'legacy' or cycle_fields or metadata_fields):
148
+ raise ValueError('连续文件和新解码政策需要批次读取')
149
+ from ..legacy.dbc_cycles import require_cycle_fields
150
+ require_cycle_fields(cycle_fields,spec.channel)
151
+ require_cycle_fields(metadata_fields,spec.channel)
152
+ self._metadata_fields = metadata_fields
153
+ self._cycle_fields = cycle_fields
154
+ self._input_fingerprints_requested = input_fingerprints
155
+ self._history_integrity=history_integrity
156
+ require_identifier(session_id, 'can.session_id')
157
+ from ..legacy.records import LegacyCANField
158
+ if type(extra_fields) is not tuple or len(extra_fields)>4096 or any(type(f) is not LegacyCANField or f.channel!=spec.channel for f in extra_fields):
159
+ raise ValueError('重建字段需要同通道有限LegacyCANField tuple')
160
+ if any(item.source != spec.name for item in signals) or len({item.name for item in signals}) != len(signals):
161
+ raise ValueError('CAN信号来源须匹配且别名唯一')
162
+ self.budget = self._budget = budget
163
+ self.spec, self.session_id, self.signals, self.backend = spec, session_id, signals, backend
164
+ self._capture_message_updates = capture_message_updates
165
+ if input_check not in ('auto', 'full') or time_scope not in ('none', 'selected', 'source'):
166
+ raise ValueError('CAN检查范围或时间范围非法')
167
+ if (input_check == 'full' or spec.decode_scope == 'all' or retain_raw_frames or capture_message_updates) and time_scope != 'source':
168
+ raise ValueError('完整诊断/原帧/消息历史必须保全来源时间')
169
+ self.input_check, self.time_scope = input_check, time_scope
170
+ self._batch_read, self._retain_raw_frames = batch_read, retain_raw_frames
171
+ self._message_frame_ids = message_frame_ids
172
+ # 策略与固定集合只在创建时决定;all不构造集合或增加声明费用。
173
+ self._decode_scope, self._decode_frame_ids = spec.decode_scope, ()
174
+ # 当前消息消费者只接收共同update,不借用read内部的临时原帧槽。
175
+ self._update_consumer = message_consumer
176
+ if frame_observer is not None and not callable(frame_observer):
177
+ raise TypeError('frame_observer需要可调用对象')
178
+ self._frame_observer = frame_observer
179
+ self._update_projection = None
180
+ self.work_dir = self._description = self._definitions = self._fields = None
181
+ self._requests = self._uninstalled_request = None
182
+ self._fixed_cost = self._held_cost = 0
183
+ self.closed = self._closing = False
184
+ try:
185
+ # 仅计静态有限树;解析field JSON/复制描述/创建登记前已覆盖所需空间。
186
+ cost = 65536 + 32 * _metadata_bytes((spec.name, str(spec.path) if len(spec.input_paths)==1 else tuple(str(p) for p in spec.input_paths), str(spec.dbc_path),
187
+ spec.channel, spec.timebase, spec.unit, spec.offset_ns, session_id, signals, str(work_dir)))
188
+ if cycle_fields or metadata_fields:
189
+ cost += 16384 + _metadata_bytes((cycle_fields,metadata_fields))*32
190
+ _reserve_owned_ram(self, cost, '_fixed_cost')
191
+ if extra_fields:
192
+ _reserve_owned_ram(self,65536+64*_metadata_bytes(extra_fields),'_fixed_cost')
193
+ if self._decode_scope == 'requested':
194
+ if not batch_read:
195
+ raise ValueError('requested来源需要批次读取,batch_read不能为False')
196
+ # 每输入ID覆盖tuple/set/排序及十进制诊断文本;每别名另覆盖scope定位副本。
197
+ # 先付保守上界再解析和创建集合,不按去重后的较小数额追补。
198
+ _reserve_owned_ram(self, 8192 + 256 * (len(signals) + len(message_frame_ids or ()))
199
+ + 512 * len(signals), '_fixed_cost')
200
+ if message_keys:
201
+ _reserve_owned_ram(self, 8192 + 2048 * len(message_keys), '_fixed_cost')
202
+ parsed = tuple((item, can_field_from_key(item.field)) for item in signals)
203
+ if any(field.channel != spec.channel for _, field in parsed):
204
+ raise ValueError('CAN字段通道必须等于单声明通道')
205
+ self._definitions = parsed
206
+ if message_consumer is not None:
207
+ from ..sources.can_updates import CANUpdateProjection
208
+ self._update_projection = CANUpdateProjection(spec.name, session_id, tuple(field for _, field in parsed), message_keys=message_keys,clock_fields=metadata_fields)
209
+ # 同一定位多别名只在声明元数据去重;默认全解码保持,requested固定集合
210
+ # 由下一分支建立。这里不建立DBC缓存,也不共享目标帧的解码调用。
211
+ self._fields = tuple(dict.fromkeys((*[field for _,field in parsed],*extra_fields)))
212
+ if self._decode_scope == 'requested':
213
+ self._decode_frame_ids = tuple(sorted({field.frame_id for field in self._fields}
214
+ | set(message_frame_ids or ())))
215
+ if len(self._decode_frame_ids) > 4096:
216
+ raise ValueError('requested最多声明4096个不同报文ID')
217
+ self._requests = set()
218
+ path = Path(work_dir).resolve()
219
+ if any(part.casefold() == 'refprojects' for part in path.parts):
220
+ raise ValueError('CAN工作目录禁止RefProjects')
221
+ path.mkdir(parents=True, exist_ok=False)
222
+ self.work_dir = path
223
+ locator = {'path': str(spec.path), 'dbc_path': str(spec.dbc_path), 'channel': spec.channel,
224
+ 'legacy_profile': spec.legacy_profile, 'time_unit': spec.unit, 'offset_ns': spec.offset_ns,
225
+ 'source_timebase_sha256': source_timebase_identity(spec.timebase, spec.offset_ns)}
226
+ if len(spec.input_paths) > 1:
227
+ locator.pop('path')
228
+ locator['paths'] = tuple(str(p) for p in spec.input_paths)
229
+ if spec.decode_policy != 'legacy':
230
+ locator['decode_policy'] = spec.decode_policy
231
+ diagnostics = (('原yield序号/完整原帧/原时间/同次DBC元数据' if retain_raw_frames else
232
+ '全部原yield观测/所需原序号与原时间/同次DBC元数据;未保存原帧副本'),)
233
+ if input_check == 'auto' and time_scope != 'source':
234
+ diagnostics = (('原yield计数/所需原序号与值;未采集时间' if time_scope == 'none' else
235
+ '原yield计数/所需原序号、值与时间;未采集非目标帧时间') + '/同次DBC元数据;未保存原帧副本',)
236
+ if self._decode_scope == 'requested':
237
+ locator['decode_scope'] = 'requested'
238
+ # 即使没有signal字段,来源级描述也必须绑定完整固定集合而非PULL子投影。
239
+ diagnostics += ('decode_scope=requested;decode_frame_ids='
240
+ + ','.join(str(value) for value in self._decode_frame_ids),)
241
+ if input_check == 'auto':
242
+ locator.update(input_check=input_check, time_scope=time_scope, check_policy_version='demand-check-v1')
243
+ diagnostics += ('按需检查:time_scope=' + time_scope + ';原生非目标帧仅保留本次要求的ID/时间处理;非原生输入完整检查回退',)
244
+ self._description = SourceDescription(spec.name, describe_fields(spec.name, signals, locator),
245
+ spec.timebase.timebase_id, None, None, SourceCapabilities(True, True, True, False,
246
+ diagnostics,
247
+ (('同格式原序BLF/单声明通道;原空dict不能区分解码失败原因' if len(spec.input_paths)>1
248
+ else '仅单BLF/单声明通道;原空dict不能区分解码失败原因'),
249
+ '缺DBC单位保持未核实;原始片段仅BLF且由run阶段写出;旧进程RSS未测')),
250
+ legacy_profile=spec.legacy_profile, metadata_status='declared')
251
+ except BaseException as exc:
252
+ _cleanup_owner(self, exc, 'can_source_cleanup_owner', 'CAN来源构造')
253
+ raise
254
+
255
+ @property
256
+ def capture_message_updates(self):
257
+ """读取原配置的消息捕获开关,不启动来源或开放完成证明。
258
+
259
+ 参数: 无。返回: 原生bool,关闭adapter后仍可核原开关。
260
+ 异常: 无;只读属性不允许调用方改写活read的捕获来源。
261
+ """
262
+ return self._capture_message_updates
263
+
264
+ @property
265
+ def batch_read(self):
266
+ """读取本adapter冻结的批协议选择。参数: 无。返回: bool。异常: 无。"""
267
+ return self._batch_read
268
+
269
+ @property
270
+ def retain_raw_frames(self):
271
+ """读取原始帧保存选择。参数: 无。返回: bool。异常: 无,不随关闭改变。"""
272
+ return self._retain_raw_frames
273
+
274
+ @property
275
+ def message_frame_ids(self):
276
+ """读取实际消息保留ID。参数: 无。返回: tuple或None。异常: 无。"""
277
+ return self._message_frame_ids
278
+
279
+ @property
280
+ def decode_scope(self):
281
+ """读取创建时的解码方式。参数: 无。返回: all/requested。异常: 无。"""
282
+ return self._decode_scope
283
+
284
+ @property
285
+ def decode_frame_ids(self):
286
+ """借用已付费的固定解码集合。参数: 无。返回: tuple,close后为空。异常: 无。"""
287
+ return self._decode_frame_ids
288
+
289
+ def _ensure_open(self):
290
+ """拒绝关闭中/已关闭。参数: 无。返回: None。异常: SourceClosedError。
291
+ """
292
+ if self.closed or self._closing:
293
+ raise SourceClosedError('CAN来源已关闭或正在清理')
294
+
295
+ def describe(self):
296
+ """返回已付费静态描述,不读BLF/DBC或spawn。参数: 无。返回: SourceDescription。
297
+ 异常: SourceClosedError为关闭中/已关闭。
298
+ """
299
+ self._ensure_open()
300
+ return self._description
301
+
302
+ def iter_batches(self, request):
303
+ """创建独立观测read,首次next才实际输入。参数: request为原ReadRequest。
304
+ 返回: CANObservationRead。异常: 原配置/预约/登记错误,持续失败保最高真实owner。
305
+ """
306
+ self._ensure_open()
307
+ if self._uninstalled_request is not None:
308
+ raise SourceClosedError('CAN来源有未返回read待清理')
309
+ try:
310
+ if self.batch_read:
311
+ from .can_batch_reader import CANBatchObservationRead
312
+ read = CANBatchObservationRead(self, request)
313
+ else:
314
+ read = CANObservationRead(self, request)
315
+ self._requests.add(read)
316
+ self._uninstalled_request = None
317
+ return read
318
+ except BaseException as exc:
319
+ read = self._uninstalled_request
320
+ if read is not None:
321
+ read._failed = True
322
+ _cleanup_owner(read, exc, 'can_observation_read_cleanup_owner', 'CAN请求登记')
323
+ if not read.closed:
324
+ exc.can_source_cleanup_owner = self
325
+ raise
326
+
327
+ def iter_batches_with_observation(self, request):
328
+ """使用同一独立read合同。参数: request为原请求。返回: CANObservationRead。
329
+ 异常: 与iter_batches相同;不复用adapter全局最后事实或request值map。
330
+ """
331
+ return self.iter_batches(request)
332
+
333
+ def close(self):
334
+ """关闭本来源活read及费用,不关闭已完成脱登记read或其新父raw store。
335
+
336
+ 参数: 无。返回: None,可重试。异常: 首个实际关闭/抵销错误,最高can_source_cleanup_owner。
337
+ """
338
+ if self.closed:
339
+ return
340
+ self._closing = True
341
+ failure = None
342
+ for read in (() if self._uninstalled_request is None else (self._uninstalled_request,)) + tuple(self._requests or ()):
343
+ try:
344
+ read.close()
345
+ except BaseException as exc:
346
+ if failure is None:
347
+ failure = exc
348
+ else:
349
+ failure.add_note('CAN其他read关闭附加失败: ' + type(exc).__name__)
350
+ if self._uninstalled_request is None and not self._requests:
351
+ self._description = self._definitions = self._fields = None
352
+ self._decode_frame_ids = ()
353
+ self._update_projection = self._update_consumer = None
354
+ self._frame_observer = None
355
+ self.spec, self.signals = None, ()
356
+ try:
357
+ _release_owned_ram(self, self._fixed_cost, '_fixed_cost')
358
+ except BaseException as exc:
359
+ if failure is None:
360
+ failure = exc
361
+ if self._held_cost == 0:
362
+ self.closed = True
363
+ if failure is not None:
364
+ failure.can_source_cleanup_owner = self
365
+ raise failure
366
+
367
+
368
+ class CANObservationRead:
369
+ """拥有同次CAN读取进程进程、原帧/可选消息仓及当前帧;事实活到自身close,移交仓归新父。"""
370
+
371
+ def __init__(self, owner, request):
372
+ """先安装未返回槽并预付固定树,不实际打开来源。
373
+
374
+ 参数: owner为预算CAN来源,request为同会话原ReadRequest。返回: 独立read。
375
+ 异常: 原请求/预算/取消;构造未返回资源由本read最高恢复owner负责。
376
+ """
377
+ if not isinstance(owner, BudgetedLegacyCANSourceAdapter) or not isinstance(request, ReadRequest):
378
+ raise TypeError('CAN read需要实际来源及ReadRequest')
379
+ owner._ensure_open()
380
+ if request.session_id != owner.session_id or any(name not in {item.name for item in owner.signals} for name in request.signal_names):
381
+ raise ValueError('CAN请求会话或投影不匹配')
382
+ self._owner, self._budget, self._request, self._spec = owner, owner.budget, request, owner.spec
383
+ self._process = self._raw_store = self._message_store = self._record = self._current = self._validator = None
384
+ self._capture_message_updates = owner.capture_message_updates
385
+ self._message_store_taken = False
386
+ self._selected = self._runtime_metadata = self._observation = self._identity = self._work_path = None
387
+ self._binding_projection = None
388
+ self._sample_pack_costs = ()
389
+ self._fixed_cost = self._metadata_cost = self._record_cost = self._pack_cost = 0
390
+ self._pending_cost = self._validation_cost = self._held_cost = self._update_cost = 0
391
+ self._first_ns = self._last_ns = self._conversion = self._mapped = None
392
+ self._row_count = self._alias_index = 0
393
+ self._retained_record_count = self._full_check_count = 0
394
+ self._started = self._eof_delivered = self._finished = self._taken = False
395
+ self._closed = self._closing = self._failed = False
396
+ # 只有requested直接累计且无普通样本时需要输入字节证明;all保原费用和扫描证据。
397
+ self._input_fingerprints_enabled = (owner._input_fingerprints_requested and owner.decode_scope == 'requested'
398
+ and owner._update_consumer is not None and not request.signal_names)
399
+ self._input_timestamp_sha = self._input_records_sha = self._input_fingerprints = None
400
+ self._input_frame_count = self._input_retained_count = 0
401
+ owner._uninstalled_request = self
402
+ try:
403
+ cost = 65536 + 16 * _metadata_bytes((request, owner._description, owner._definitions))
404
+ # 默认费用保持;开启时先覆盖本层新子路径及固定责任槽,仓本身另按原公式付款。
405
+ if self._capture_message_updates:
406
+ cost += 4096 + 32 * len(str(owner.work_dir))
407
+ if self._input_fingerprints_enabled:
408
+ cost += 8192 # 两个SHA状态、计数、memoryview与最终64字符摘要独立先付费。
409
+ _reserve_owned_ram(self, cost, '_fixed_cost')
410
+ if self._input_fingerprints_enabled:
411
+ if not owner.batch_read:
412
+ raise ValueError('CAN真实输入指纹需要批次读取')
413
+ self._input_timestamp_sha = hashlib.sha256()
414
+ self._input_records_sha = hashlib.sha256()
415
+ self._identity = uuid4().hex
416
+ self._work_path = owner.work_dir / self._identity
417
+ self._selected = tuple(pair for pair in owner._definitions if pair[0].name in request.signal_names)
418
+ self._validator = BatchValidator(owner._description, request)
419
+ except BaseException as exc:
420
+ self._failed = True
421
+ _cleanup_owner(self, exc, 'can_observation_read_cleanup_owner', 'CAN read构造')
422
+ raise
423
+
424
+ @property
425
+ def capture_message_updates(self):
426
+ """读取创建本read时的原捕获开关,不因adapter关闭而失去来源。
427
+
428
+ 参数: 无。返回: 原生bool快照。异常: 无;该标志本身不证明已经完成输入。
429
+ """
430
+ return self._capture_message_updates
431
+
432
+ @property
433
+ def identity(self):
434
+ """读取本次独立UUID。参数: 无。返回: str。异常: 无,不按request值复用。"""
435
+ return self._identity
436
+
437
+ @property
438
+ def request(self):
439
+ """读取创建时原请求。参数: 无。返回: 原ReadRequest。异常: 关闭时ResultClosedError。"""
440
+ self._require_open()
441
+ return self._request
442
+
443
+ @property
444
+ def closed(self):
445
+ """读取真实关闭事实。参数: 无。返回: bool。异常: 无。"""
446
+ return self._closed
447
+
448
+ @property
449
+ def failed(self):
450
+ """读取失败标记。参数: 无。返回: bool。异常: 无,不代表已清理。"""
451
+ return self._failed
452
+
453
+ @property
454
+ def finished(self):
455
+ """读取真实完整StopIteration事实。参数: 无。返回: bool。异常: 无。"""
456
+ return self._finished
457
+
458
+ @property
459
+ def exhausted(self):
460
+ """提供完成别名。参数: 无。返回: bool。异常: 无,EOF批交付仍为False。"""
461
+ return self._finished
462
+
463
+ def _require_open(self):
464
+ """拒绝已关闭/失败/半关闭。参数: 无。返回: None。异常: ResultClosedError。"""
465
+ if self._closed or self._closing or self._failed:
466
+ raise ResultClosedError('CAN read已关闭、失败或正在清理')
467
+
468
+ @property
469
+ def observation(self):
470
+ """仅完整完成后借读事实。参数: 无。返回: CANObservation。异常: ResultClosedError。"""
471
+ self._require_open()
472
+ if not self._finished:
473
+ raise ResultClosedError('CAN read尚未真正完整耗尽')
474
+ return self._observation
475
+
476
+ @property
477
+ def observed_bounds(self):
478
+ """读取已经看到的首末时间供在线规则定界,不表示输入已完整结束。
479
+
480
+ 参数: 无。返回: 两个必要整数或None;none时间范围不补造坐标。异常: 读取器已关闭/失败。
481
+ """
482
+ self._require_open()
483
+ return self._first_ns,self._last_ns
484
+
485
+ @property
486
+ def input_fingerprints(self):
487
+ """借读实际输入的两段字节指纹,不把它解释成普通信号样本摘要。
488
+
489
+ 参数: 无。返回: (时间SHA256,记录SHA256,全原帧数,保留记录数)的tuple。
490
+ 异常: ResultClosedError为未启用、未完成、失败或已关闭;不返回半成品hash。
491
+ 指纹只活到本read关闭,接收方要继续保留须在自己的预算下复制/持有。
492
+ """
493
+ self._require_open()
494
+ if not self._finished or self._input_fingerprints is None:
495
+ raise ResultClosedError('CAN真实输入指纹尚未完成或没有启用')
496
+ return self._input_fingerprints
497
+
498
+ def _observe_validated_packet(self, process, payload, batch):
499
+ """在严格批解包后借用原字节,按原顺序增量计算时间和所需记录指纹。
500
+
501
+ 参数: process必须是本read的实际子进程read;payload/batch为其刚核完的借用包。
502
+ 返回: None。异常: SourceReadError为归属/原序不符;原hash/取消错误保持且标记失败。
503
+ 时间区是头后每原帧8字节,记录区保每条长度及原JSON;不包含随分批改变的包头。
504
+ 任一更新中断后本read永久失败,不能重试同一批或发布部分指纹。
505
+ """
506
+ view = time_view = record_view = None
507
+ try:
508
+ self._require_open()
509
+ if (not self._input_fingerprints_enabled or self._input_timestamp_sha is None
510
+ or self._input_records_sha is None or self._input_fingerprints is not None
511
+ or process is not self._process or payload is not process._pending_reply
512
+ or batch.start_sequence != self._input_frame_count):
513
+ raise SourceReadError('CAN输入指纹须来自同次已核批且按全原帧序号连续')
514
+ view = memoryview(payload)
515
+ from ..legacy.batch_wire import record_payload_offset, FILE_HEADER
516
+ end = record_payload_offset(batch) + (FILE_HEADER.size if len(self._spec.input_paths)>1 else 0)
517
+ record_view = view[end:]
518
+ if self._owner.time_scope == 'source':
519
+ # 全来源模式才生成全部原时间SHA;新头长度由记录区与帧数确定。
520
+ time_view = view[end - 8 * batch.frame_count:end]
521
+ self._input_timestamp_sha.update(time_view)
522
+ self._input_records_sha.update(record_view)
523
+ self._input_frame_count += batch.frame_count
524
+ self._input_retained_count += len(batch.records)
525
+ except BaseException as exc:
526
+ self._failed = True
527
+ exc.can_observation_read_cleanup_owner = self
528
+ raise
529
+ finally:
530
+ # 即使调用方保存错误栈,也不由本层的视图继续保活整包;不复制任何原数据。
531
+ for borrowed in (time_view, record_view, view):
532
+ if borrowed is not None:
533
+ borrowed.release()
534
+ process = payload = batch = borrowed = view = time_view = record_view = None
535
+
536
+ @property
537
+ def runtime_metadata(self):
538
+ """借读同次READY原冻结映射,None/空unit仍未核实。
539
+
540
+ 参数: 无。返回: 保operation/version/profile等原键的映射。异常: 未READY/关闭ResultClosedError。
541
+ """
542
+ self._require_open()
543
+ if self._runtime_metadata is None:
544
+ raise ResultClosedError('CAN read尚未取得同次READY')
545
+ return self._runtime_metadata
546
+
547
+ def prepare_metadata(self):
548
+ """初始化同次DBC并返回周期/单位事实,不读取首帧。
549
+
550
+ 参数: 无。返回: 同一冻结READY。异常: 原启动错误,沿本read清理链处理。
551
+ 重复调用复用同次初始化;不把初始化成功当作输入EOF。
552
+ """
553
+ self._require_open()
554
+ try:
555
+ if self._runtime_metadata is None:
556
+ self._start()
557
+ return self._runtime_metadata
558
+ except BaseException as exc:
559
+ self._fail(exc)
560
+ raise
561
+
562
+ def _adopt(self, exc):
563
+ """接管未返回的实际CAN读取进程/raw/消息仓子owner。参数: exc为原错误。返回: None。异常: 无预期异常。"""
564
+ if self._process is None:
565
+ self._process = getattr(exc, 'can_process_read_cleanup_owner', None)
566
+ if self._raw_store is None and not self._taken:
567
+ self._raw_store = getattr(exc, 'raw_frame_store_cleanup_owner', None)
568
+ # 消息仓构造可能已经取得真实FD/费用却未返回;只接尚未移交的本层子责任。
569
+ if self._capture_message_updates and self._message_store is None and not self._message_store_taken:
570
+ self._message_store = getattr(exc, 'decoded_message_store_cleanup_owner', None)
571
+
572
+ def _fail(self, exc):
573
+ """保原错/取消并关闭同一最高read。参数: exc。返回: None。异常: 清理副错只note。"""
574
+ self._failed = True
575
+ self._adopt(exc)
576
+ exc.can_observation_read_cleanup_owner = self
577
+ _cleanup_owner(self, exc, 'can_observation_read_cleanup_owner', 'CAN观测read')
578
+
579
+ def _start(self):
580
+ """原start仅INIT,复制同次READY并核全部声明单位后才允许第一PULL。
581
+
582
+ 参数: 无。返回: None。异常: 原CAN读取进程/单位/预算/原始暂存错误;上层保真实子槽。
583
+ """
584
+ request = LegacyCANRequest(self._spec.path, self._spec.dbc_path, self._owner._fields)
585
+ if self._owner.batch_read:
586
+ from ..legacy.batch_read import LegacyCANBatchRead
587
+ ids = None if (self._owner.retain_raw_frames or self._capture_message_updates
588
+ and self._owner.message_frame_ids is None) else tuple(sorted(
589
+ {field.frame_id for _, field in self._owner._definitions}
590
+ | set(self._owner.message_frame_ids or ())))
591
+ # 传输预付不能吃光下一步装箱/验证/磁盘编码需要的空间;这里只留余量,
592
+ # 费用仍由实际消费owner在使用前逐笔入账,_record_cost已在PULL前支付。
593
+ # 同一次read的定位/路径/定义不可变;算一次每别名装箱费,后续样本
594
+ # 仍逐笔预付同一金额,不为相同的元数据反复遍历整个定义树。
595
+ self._sample_pack_costs = tuple(32768 + 32 * _metadata_bytes((definition, field,
596
+ max((str(p) for p in self._spec.input_paths),key=_metadata_bytes), self._spec.legacy_profile, self._request.session_id,
597
+ self._spec.name)) for definition, field in self._selected)
598
+ per_sample = 2 * max(self._sample_pack_costs, default=32768)
599
+ scratch = (65536 + 64 * MAX_DECODED_MESSAGE_ROW_BYTES
600
+ if self._capture_message_updates or self._owner.retain_raw_frames else 0)
601
+ sample_bound = self._request.batch_rows if self._selected else 0
602
+ headroom = 131072 + sample_bound * per_sample + scratch
603
+ # 当前批交给分析层前,只在上述消费空间之外预付并授权下一批。
604
+ # 当前处理失败/取消可能多读至多一批;预算不足时批read自动同步回退。
605
+ source_options = {'cycle_fields':self._owner._cycle_fields} if self._owner._cycle_fields else {}
606
+ if self._owner._metadata_fields:
607
+ source_options['metadata_fields'] = self._owner._metadata_fields
608
+ if len(self._spec.input_paths) > 1:
609
+ source_options['input_paths'] = self._spec.input_paths
610
+ if self._spec.decode_policy != 'legacy':
611
+ source_options['decode_policy'] = self._spec.decode_policy
612
+ if self._owner.decode_scope == 'requested':
613
+ self._process = LegacyCANBatchRead(request, self._budget, frame_ids=ids,
614
+ consumer_headroom_bytes=headroom, prefetch=True, decode_scope='requested',
615
+ input_check=self._owner.input_check, time_scope=self._owner.time_scope,
616
+ decode_frame_ids=self._owner.decode_frame_ids, **source_options)
617
+ else:
618
+ # 旧调用连新增默认关键字也不传,保原构造与故障注入入口。
619
+ self._process = LegacyCANBatchRead(request, self._budget, frame_ids=ids,
620
+ consumer_headroom_bytes=headroom, prefetch=True, **source_options)
621
+ else:
622
+ self._process = LegacyCANProcessRead(request, self._budget)
623
+ if self._input_fingerprints_enabled:
624
+ self._process._validated_packet_consumer = self._observe_validated_packet
625
+ self._process.start()
626
+ ready = self._process.metadata
627
+ _reserve_owned_ram(self, 4096 + 16 * _metadata_bytes(ready), '_metadata_cost')
628
+ self._runtime_metadata = freeze_metadata(ready)
629
+ from ..sources.can_updates import CANUpdateProjection
630
+ projection = self._owner._update_projection or CANUpdateProjection(self._spec.name,
631
+ self._request.session_id, tuple(field for _, field in self._owner._definitions))
632
+ self._binding_projection = projection.for_read(ready['fields'])
633
+ if len(self._spec.input_paths)>1 or self._spec.decode_policy != 'legacy' or self._owner._cycle_fields or self._owner._metadata_fields:
634
+ if (ready.get('version') != 5
635
+ or ready.get('input_paths') != tuple(str(p) for p in self._spec.input_paths)
636
+ or ready.get('decode_policy') != self._spec.decode_policy):
637
+ raise SourceReadError('同次CAN READY与连续文件/解码政策不符')
638
+ ready = dict(ready,version=ready['base_version'])
639
+ # 同次READY先与实际adapter交叉核;版本/集合不能从缺项猜成默认成功。
640
+ if self._owner.decode_scope == 'requested':
641
+ fixed = ready.get('decode_frame_ids')
642
+ expected_version = 4 if self._owner.input_check == 'auto' else 3
643
+ if (type(ready.get('version')) is not int or ready['version'] != expected_version
644
+ or type(ready.get('decode_scope')) is not str or ready['decode_scope'] != 'requested'
645
+ or type(fixed) is not tuple or any(type(value) is not int for value in fixed)
646
+ or fixed != self._owner.decode_frame_ids
647
+ or type(ready.get('decoded_values_policy')) is not str
648
+ or ready['decoded_values_policy'] != REQUESTED_VALUES_POLICY):
649
+ raise SourceReadError('同次CAN READY与来源固定requested策略不符')
650
+ if expected_version == 4 and (ready.get('input_check') != self._owner.input_check or ready.get('time_scope') != self._owner.time_scope):
651
+ raise SourceReadError('同次CAN READY检查/时间范围与来源不同')
652
+ elif (type(ready.get('version')) is not int or ready['version'] != 1
653
+ or 'decode_scope' in ready or 'decode_frame_ids' in ready
654
+ or 'decoded_values_policy' in ready):
655
+ raise SourceReadError('全解码来源必须保原v1 READY且不带按需策略')
656
+ for definition, field in self._owner._definitions:
657
+ unit = next(item['unit'] for item in ready['fields'] if item['locator'] == field_to_dict(field))
658
+ if unit not in (None, '') and unit != definition.input_unit:
659
+ raise SourceReadError('同次DBC非空单位不等于声明input_unit: ' + definition.name)
660
+ if self._owner.retain_raw_frames:
661
+ self._raw_store = RawFrameStore(self._budget, self._work_path, self._spec.name, integrity=self._owner._history_integrity)
662
+ # 原raw目录保持不变;可选子目录只在READY/单位核对完成后、首PULL之前创建。
663
+ if self._capture_message_updates:
664
+ self._message_store = DecodedMessageStore(self._budget, self._work_path / 'messages',
665
+ self._spec.name, self._request.session_id, decoder_profile=self._runtime_metadata['profile'],
666
+ read_identity=self._identity, sparse_sequences=self._owner.batch_read, integrity=self._owner._history_integrity)
667
+ self._started = True
668
+
669
+ def _accept(self, batch):
670
+ """先预约validator候选及同刻去重集合,再原子接收并留下实际保留费用。
671
+
672
+ 参数: batch为有限SignalBatch。返回: 原batch。异常: 原协议/预算/取消,由上层poison。
673
+ """
674
+ _reserve_owned_ram(self, 4096 + 2 * _pending_bytes(self._validator)
675
+ + 1024 * batch.sample_count, '_validation_cost')
676
+ self._validator.accept(batch)
677
+ retained = _pending_bytes(self._validator)
678
+ _release_owned_ram(self, self._pending_cost, '_pending_cost')
679
+ self._validation_cost -= retained
680
+ self._pending_cost += retained
681
+ _release_owned_ram(self, self._validation_cost, '_validation_cost')
682
+ self._current = batch
683
+ return batch
684
+
685
+ def _release_current(self):
686
+ """下一步前停止持有原batch再归还其装箱空间。参数: 无。返回: None。异常: 原抵销/取消。"""
687
+ self._current = None
688
+ _release_owned_ram(self, self._pack_cost, '_pack_cost')
689
+
690
+ def _new_record(self):
691
+ """原帧进入前先付本层记录/引用空间;全部yield先暂存再作分析层列选择。
692
+
693
+ 参数: 无。返回: True有新原帧,False为CAN读取进程真实EOF。异常: 原输入/时间/暂存错误。
694
+ """
695
+ self._record = None
696
+ _release_owned_ram(self, self._record_cost, '_record_cost')
697
+ _reserve_owned_ram(self, 4259840, '_record_cost')
698
+ record = conversion = None
699
+ try:
700
+ try:
701
+ record = next(self._process)
702
+ except StopIteration:
703
+ _release_owned_ram(self, self._record_cost, '_record_cost')
704
+ if not self._process.finished:
705
+ raise SourceReadError('CAN进程没有完整EOF')
706
+ if self._raw_store is not None:
707
+ self._raw_store.seal()
708
+ # 两仓仅在同一次真实CAN读取进程 EOF后封口;任一失败都不能开放finished或移交。
709
+ if self._capture_message_updates:
710
+ self._message_store.seal()
711
+ return False
712
+ conversion = convert_time(record.frame.timestamp, 's')
713
+ mapped = checked_add_ns(conversion.time_ns, self._spec.offset_ns)
714
+ if self._last_ns is not None and mapped < self._last_ns:
715
+ raise SourceReadError('CAN原yield时间回退,禁止重排')
716
+ if self._raw_store is not None:
717
+ self._raw_store.append(record, mapped)
718
+ # 同一个原decode对象恰追加一次,位于列选择之前,不因空投影或拆别名改变次数。
719
+ if self._capture_message_updates:
720
+ self._message_store.append(record, mapped, time_quantized=conversion.quantized)
721
+ self._binding_projection.fields_for(record.frame)
722
+ if self._owner._frame_observer is not None:
723
+ self._owner._frame_observer(record.frame)
724
+ if self._first_ns is None:
725
+ self._first_ns = mapped
726
+ self._last_ns, self._row_count = mapped, self._row_count + 1
727
+ self._record, self._conversion, self._mapped, self._alias_index = record, conversion, mapped, 0
728
+ self._deliver_message(record, mapped)
729
+ return True
730
+ finally:
731
+ # 原异常可被保留;只断本函数临时大record/转换,不清原输入或其他模块TB。
732
+ record = conversion = None
733
+
734
+ def _deliver_message(self, record, time_ns):
735
+ """仅有明确消费者时构造共同消息,默认读取不增加逐帧对象。
736
+
737
+ 参数: record为同次原解码帧;time_ns为已检查的时间或未采集None。
738
+ 返回: None。异常: 投影、预算或消费者错误由read统一标记失败并清理。
739
+ """
740
+ if self._owner._update_consumer is not None:
741
+ from .message_delivery import deliver_message
742
+ deliver_message(self, self._binding_projection, self._owner._update_consumer,
743
+ record.frame, record.sequence, record.values, time_ns)
744
+
745
+ def _batch(self):
746
+ """为当前原帧最多batch_rows个匹配别名装箱,缺key产生明确MISSING更新。
747
+
748
+ 参数: 无。返回: 已校验SignalBatch。异常: 原refs/归一化/预约/协议错误。
749
+ """
750
+ _reserve_owned_ram(self, 65536, '_pack_cost')
751
+ columns = {}
752
+ while self._alias_index < len(self._selected):
753
+ definition, field = self._selected[self._alias_index]
754
+ self._alias_index += 1
755
+ if field not in self._binding_projection.fields_for(self._record.frame):
756
+ continue
757
+ # 完整定位/定义及单样本数组均先付;不按原数值相同而合并独立别名。
758
+ _reserve_owned_ram(self, 16384 + 32 * _metadata_bytes((definition, field, str(self._spec.path),
759
+ self._spec.legacy_profile, self._request.session_id, self._spec.name)), '_pack_cost')
760
+ ref = CANSourceRef(self._request.session_id, self._spec.name, definition.field,
761
+ str(self._spec.path), self._spec.legacy_profile, field.channel, field.signal,
762
+ field.frame_id, self._record.frame.is_extended_id, self._record.frame.is_fd, self._record.sequence,
763
+ self._record.frame.timestamp, self._conversion.quantized)
764
+ value = self._record.values.get(field.signal)
765
+ columns[definition.name] = pack_decoded(definition,
766
+ ((self._mapped, self._record.sequence, value),), (ref,), self._owner.backend)
767
+ if len(columns) == self._request.batch_rows:
768
+ break
769
+ watermark = None if self._mapped == -(1 << 63) else self._mapped - 1
770
+ return self._accept(SignalBatch(self._spec.name, self._request.session_id, columns,
771
+ watermark, False, None))
772
+
773
+ def __iter__(self):
774
+ """保持本次原序位置。参数: 无。返回: self。异常: 无,不启动读取。"""
775
+ return self
776
+
777
+ def __next__(self):
778
+ """逐次交付当前原帧分片或独立空EOF批,真正下一次耗尽才开放完成事实。
779
+
780
+ 参数: 无。返回: SignalBatch。异常: 真StopIteration/原来源/预算/取消,最高read可恢复。
781
+ """
782
+ if self._finished:
783
+ raise StopIteration
784
+ self._require_open()
785
+ try:
786
+ self._release_current()
787
+ if not self._started:
788
+ self._start()
789
+ if self._eof_delivered:
790
+ self._finish()
791
+ elif self._record is not None and self._alias_index < len(self._selected):
792
+ return self._batch()
793
+ elif self._new_record():
794
+ return self._batch()
795
+ else:
796
+ _reserve_owned_ram(self, 65536, '_pack_cost')
797
+ batch = SignalBatch(self._spec.name, self._request.session_id, {}, self._last_ns,
798
+ True, self._last_ns)
799
+ self._accept(batch)
800
+ self._eof_delivered = True
801
+ return batch
802
+ except BaseException as exc:
803
+ self._fail(exc)
804
+ raise
805
+ raise StopIteration
806
+
807
+ def _close_child(self, slot):
808
+ """真实子owner完成关闭后才清槽。参数: slot为实际子槽。返回: None。异常: 原close错误。"""
809
+ child = getattr(self, slot)
810
+ if child is not None:
811
+ try:
812
+ child.close()
813
+ finally:
814
+ if child.closed:
815
+ setattr(self, slot, None)
816
+
817
+ def _finish(self):
818
+ """确认本read全部完成条件后开放事实,并解除adapter活登记。
819
+
820
+ 参数: 无。返回: None。异常: 原关闭/协议/登记错误,不能伪造完成。
821
+ """
822
+ if (not self._validator.ended or not self._process.finished
823
+ or self._owner.retain_raw_frames and (self._raw_store is None
824
+ or self._raw_store.state != 'sealed' or self._raw_store.closed)):
825
+ raise SourceReadError('CAN输入尚未满足真实完成条件')
826
+ if self._capture_message_updates:
827
+ # 完成事实必须同时属于本read的原消息仓,不能只凭原帧仓已封口推断。
828
+ store = self._message_store
829
+ if (store is None or store.closed or store.state != 'sealed'
830
+ or (store.count != self._row_count if not store.sparse_sequences else
831
+ store.count > self._row_count or store._last_sequence >= self._row_count)
832
+ or store.source_name != self._spec.name or store.session_id != self._request.session_id
833
+ or store.read_identity != self._identity
834
+ or store.decoder_profile != self._runtime_metadata['profile']):
835
+ raise SourceReadError('同次CAN消息仓尚未满足原对象及完整封口事实')
836
+ self._close_child('_process')
837
+ self._record = None
838
+ _release_owned_ram(self, self._record_cost, '_record_cost')
839
+ if self._input_fingerprints_enabled:
840
+ if (self._input_frame_count != self._row_count
841
+ or self._input_timestamp_sha is None or self._input_records_sha is None):
842
+ raise SourceReadError('CAN真实输入指纹的原帧数与完成观测不符')
843
+ self._input_fingerprints = (self._input_timestamp_sha.hexdigest() if self._owner.time_scope == 'source' else None,
844
+ self._input_records_sha.hexdigest(), self._input_frame_count, self._input_retained_count)
845
+ self._input_timestamp_sha = self._input_records_sha = None
846
+ self._observation = CANObservation(self._spec.name, self._request.session_id, self._request,
847
+ self._identity, self._first_ns, self._last_ns, self._row_count, True,
848
+ self._owner.time_scope, self._retained_record_count, self._full_check_count)
849
+ self._owner._requests.discard(self)
850
+ self._finished = True
851
+
852
+ def take_raw_store(self, receiver, slot='_raw_store'):
853
+ """仅完成后一次移交真实sealed store,本read后续不再关闭新父资源。
854
+
855
+ 参数: receiver为同一_budget的可信内部owner;slot为其已初始化为None的实际接收槽。
856
+ 返回: 原RawFrameStore,先装父槽再撤本子槽。异常: 状态/预算/槽错误或原安装取消;
857
+ 安装后取消仍由接收父实际槽可达,不在返回边界丢失真实费用。
858
+ """
859
+ self._require_open()
860
+ if not self._finished or self._taken or self._raw_store is None:
861
+ raise ResultClosedError('原始store未完成或已移交')
862
+ result = self._raw_store
863
+ if (getattr(receiver, '_budget', None) is not self._budget or type(slot) is not str
864
+ or not slot.startswith('_') or getattr(receiver, slot) is not None):
865
+ raise ValueError('原始store移交须同账本且接收实际槽为空')
866
+ try:
867
+ # 父赋值先发生;即使setter在真实安装后取消,也至少有最高父实际责任。
868
+ setattr(receiver, slot, result)
869
+ except BaseException as exc:
870
+ exc.can_observation_read_cleanup_owner = self
871
+ raise
872
+ finally:
873
+ if getattr(receiver, slot) is result:
874
+ self._raw_store, self._taken = None, True
875
+ return result
876
+
877
+ def take_message_store(self, receiver, slot='_message_store'):
878
+ """完成后一次移交同次消息仓,父实际安装成功才解除本read责任。
879
+
880
+ 参数: receiver为同一_budget的可信owner;slot为其已存在且为空的实际槽。
881
+ 返回: 原DecodedMessageStore对象,不重建文件或复制decoded记录。
882
+ 异常: ResultClosedError为未开启、未完成或已移交;ValueError为预算/槽不符;
883
+ 父安装前后取消保原异常和can_observation_read_cleanup_owner。
884
+ """
885
+ self._require_open()
886
+ if (not self._finished or not self._capture_message_updates or self._message_store_taken
887
+ or self._message_store is None):
888
+ raise ResultClosedError('消息store未开启、未完成或已移交')
889
+ store = self._message_store
890
+ if (getattr(receiver, '_budget', None) is not self._budget or type(slot) is not str
891
+ or not slot.startswith('_') or not hasattr(receiver, slot) or getattr(receiver, slot) is not None):
892
+ raise ValueError('消息store移交须同账本且接收实际槽为空')
893
+ try:
894
+ # setter可能在实际安装后取消;finally按真实父槽判断,不能先清子再return。
895
+ setattr(receiver, slot, store)
896
+ except BaseException as exc:
897
+ exc.can_observation_read_cleanup_owner = self
898
+ raise
899
+ finally:
900
+ if getattr(receiver, slot, None) is store:
901
+ self._message_store, self._message_store_taken = None, True
902
+ return store
903
+
904
+ def close(self):
905
+ """只关闭仍自有的输入/raw/消息store和所有实际费用,可持续重试。
906
+
907
+ 参数: 无。返回: None。异常: 首个子关闭/费用取消;can_observation_read_cleanup_owner保本对象。
908
+ """
909
+ if self._closed:
910
+ return
911
+ self._closing = True
912
+ failure = None
913
+ for slot in ('_process', '_raw_store', '_message_store'):
914
+ try:
915
+ self._close_child(slot)
916
+ except BaseException as exc:
917
+ if failure is None:
918
+ failure = exc
919
+ else:
920
+ failure.add_note('CAN其他子资源关闭附加失败: ' + type(exc).__name__)
921
+ if self._process is None and self._raw_store is None and self._message_store is None:
922
+ self._record = self._current = self._runtime_metadata = self._observation = None
923
+ self._validator = self._selected = None
924
+ self._binding_projection = None
925
+ self._sample_pack_costs = ()
926
+ self._input_timestamp_sha = self._input_records_sha = self._input_fingerprints = None
927
+ for slot in ('_update_cost', '_pack_cost', '_record_cost', '_validation_cost', '_pending_cost', '_metadata_cost', '_fixed_cost'):
928
+ try:
929
+ _release_owned_ram(self, getattr(self, slot), slot)
930
+ except BaseException as exc:
931
+ if failure is None:
932
+ failure = exc
933
+ else:
934
+ failure.add_note('CAN费用抵销附加失败: ' + type(exc).__name__)
935
+ if self._held_cost == 0:
936
+ try:
937
+ self._owner._requests.discard(self)
938
+ if self._owner._uninstalled_request is self:
939
+ self._owner._uninstalled_request = None
940
+ self._closed = True
941
+ except BaseException as exc:
942
+ if failure is None:
943
+ failure = exc
944
+ else:
945
+ failure.add_note('CAN解除read登记附加失败: ' + type(exc).__name__)
946
+ if failure is not None:
947
+ failure.can_observation_read_cleanup_owner = self
948
+ raise failure