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.
- chronaxis/__init__.py +72 -0
- chronaxis/__main__.py +12 -0
- chronaxis/analysis_cli.py +181 -0
- chronaxis/batch/__init__.py +14 -0
- chronaxis/batch/api.py +46 -0
- chronaxis/batch/cli.py +48 -0
- chronaxis/batch/config.py +37 -0
- chronaxis/batch/models.py +202 -0
- chronaxis/batch/process_transport.py +149 -0
- chronaxis/batch/process_tree.py +72 -0
- chronaxis/batch/publication.py +41 -0
- chronaxis/batch/runner.py +236 -0
- chronaxis/batch/templates.py +42 -0
- chronaxis/can_dependencies.py +42 -0
- chronaxis/cli.py +193 -0
- chronaxis/configuration/__init__.py +46 -0
- chronaxis/configuration/cli.py +41 -0
- chronaxis/configuration/diagnostics.py +107 -0
- chronaxis/configuration/explanation.py +233 -0
- chronaxis/configuration/file_tools.py +140 -0
- chronaxis/configuration/imports.py +144 -0
- chronaxis/configuration/initialization.py +36 -0
- chronaxis/configuration/json_parser.py +114 -0
- chronaxis/configuration/models.py +74 -0
- chronaxis/configuration/origins.py +90 -0
- chronaxis/configuration/overrides.py +55 -0
- chronaxis/configuration/resolution.py +150 -0
- chronaxis/configuration/template_catalog.py +68 -0
- chronaxis/configuration/templates/batch/analysis-annotated.yaml +18 -0
- chronaxis/configuration/templates/batch/analysis-minimal.yaml +18 -0
- chronaxis/configuration/templates/batch/annotated.yaml +6 -0
- chronaxis/configuration/templates/batch/minimal.yaml +6 -0
- chronaxis/configuration/templates/can-asc/annotated.yaml +18 -0
- chronaxis/configuration/templates/can-asc/minimal.yaml +18 -0
- chronaxis/configuration/templates/can-blf/annotated.yaml +18 -0
- chronaxis/configuration/templates/can-blf/minimal.yaml +18 -0
- chronaxis/configuration/templates/can-export/annotated.yaml +23 -0
- chronaxis/configuration/templates/can-export/minimal.yaml +23 -0
- chronaxis/configuration/templates/catalog.json +233 -0
- chronaxis/configuration/templates/charge-session/annotated.yaml +38 -0
- chronaxis/configuration/templates/charge-session/minimal.yaml +38 -0
- chronaxis/configuration/templates/command-response/annotated.yaml +32 -0
- chronaxis/configuration/templates/command-response/minimal.yaml +36 -0
- chronaxis/configuration/templates/fault-window/annotated.yaml +25 -0
- chronaxis/configuration/templates/fault-window/minimal.yaml +27 -0
- chronaxis/configuration/templates/ini-mapping/annotated.yaml +20 -0
- chronaxis/configuration/templates/ini-mapping/minimal.yaml +20 -0
- chronaxis/configuration/templates/raw-can-csv/annotated.yaml +34 -0
- chronaxis/configuration/templates/raw-can-csv/minimal.yaml +35 -0
- chronaxis/configuration/templates/shared/charge-session.asc +5 -0
- chronaxis/configuration/templates/shared/command-response.asc +8 -0
- chronaxis/configuration/templates/shared/fault-window.asc +5 -0
- chronaxis/configuration/templates/shared/power.asc +7 -0
- chronaxis/configuration/templates/shared/sample.asc +6 -0
- chronaxis/configuration/templates/shared/sample.blf +0 -0
- chronaxis/configuration/templates/shared/sample.csv +5 -0
- chronaxis/configuration/templates/shared/sample.dbc +11 -0
- chronaxis/configuration/templates/shared/signals.csv +6 -0
- chronaxis/configuration/templates/shared/source.ini +5 -0
- chronaxis/configuration/templates/shared/stability.asc +9 -0
- chronaxis/configuration/templates/shared/teaching.dbc +27 -0
- chronaxis/configuration/templates/shared/threshold.asc +7 -0
- chronaxis/configuration/templates/signal-csv/annotated.yaml +27 -0
- chronaxis/configuration/templates/signal-csv/minimal.yaml +27 -0
- chronaxis/configuration/templates/signal-export/annotated.yaml +27 -0
- chronaxis/configuration/templates/signal-export/minimal.yaml +29 -0
- chronaxis/configuration/templates/stability/annotated.yaml +35 -0
- chronaxis/configuration/templates/stability/minimal.yaml +35 -0
- chronaxis/configuration/templates/threshold/annotated.yaml +22 -0
- chronaxis/configuration/templates/threshold/minimal.yaml +22 -0
- chronaxis/configuration/yaml_parser.py +125 -0
- chronaxis/core/__init__.py +71 -0
- chronaxis/core/binding.py +449 -0
- chronaxis/core/calculation_series_join.py +106 -0
- chronaxis/core/calculations.py +435 -0
- chronaxis/core/calculations_memory_numpy.py +136 -0
- chronaxis/core/calculations_memory_reference.py +165 -0
- chronaxis/core/calculations_numpy.py +298 -0
- chronaxis/core/calculations_reference.py +294 -0
- chronaxis/core/condition_evidence.py +182 -0
- chronaxis/core/conditional_integral_result.py +43 -0
- chronaxis/core/conditional_integral_terms.py +146 -0
- chronaxis/core/conditional_integral_terms_numpy.py +148 -0
- chronaxis/core/conditional_integral_terms_reference.py +111 -0
- chronaxis/core/conditional_time_reduction.py +118 -0
- chronaxis/core/conditional_time_reduction_numpy.py +223 -0
- chronaxis/core/conditional_time_reduction_reference.py +213 -0
- chronaxis/core/declarations.py +192 -0
- chronaxis/core/decoded_binding.py +197 -0
- chronaxis/core/direct_message.py +387 -0
- chronaxis/core/export_interpolation.py +54 -0
- chronaxis/core/expression.py +642 -0
- chronaxis/core/expression_numpy.py +314 -0
- chronaxis/core/expression_reference.py +272 -0
- chronaxis/core/integral_result.py +53 -0
- chronaxis/core/integral_sum.py +77 -0
- chronaxis/core/integral_sum_numpy.py +224 -0
- chronaxis/core/integral_sum_reference.py +148 -0
- chronaxis/core/integral_terms.py +119 -0
- chronaxis/core/integral_terms_numpy.py +127 -0
- chronaxis/core/integral_terms_reference.py +91 -0
- chronaxis/core/mean_weights_numpy.py +29 -0
- chronaxis/core/mean_weights_reference.py +27 -0
- chronaxis/core/message_binding.py +305 -0
- chronaxis/core/models.py +485 -0
- chronaxis/core/normalize_numpy.py +396 -0
- chronaxis/core/numeric.py +472 -0
- chronaxis/core/numeric_numpy.py +440 -0
- chronaxis/core/record_intervals.py +115 -0
- chronaxis/core/sample_reduction.py +161 -0
- chronaxis/core/sample_reduction_numpy.py +160 -0
- chronaxis/core/sample_reduction_reference.py +154 -0
- chronaxis/core/selection.py +74 -0
- chronaxis/core/sequence.py +160 -0
- chronaxis/core/sequence_reference.py +248 -0
- chronaxis/core/stability.py +249 -0
- chronaxis/core/start_end.py +169 -0
- chronaxis/core/state.py +494 -0
- chronaxis/core/state_numpy.py +296 -0
- chronaxis/core/temporal.py +373 -0
- chronaxis/core/temporal_clock.py +25 -0
- chronaxis/core/temporal_memory_numpy.py +163 -0
- chronaxis/core/temporal_memory_reference.py +161 -0
- chronaxis/core/temporal_numpy.py +345 -0
- chronaxis/core/temporal_reference.py +304 -0
- chronaxis/core/time_reduction.py +190 -0
- chronaxis/core/time_reduction_numpy.py +205 -0
- chronaxis/core/time_reduction_reference.py +203 -0
- chronaxis/core/types.py +105 -0
- chronaxis/core/units.py +81 -0
- chronaxis/core/validation.py +94 -0
- chronaxis/core/window_delta.py +123 -0
- chronaxis/core/window_delta_numpy.py +78 -0
- chronaxis/core/window_delta_reference.py +69 -0
- chronaxis/core/windows.py +224 -0
- chronaxis/core/windows_numpy.py +78 -0
- chronaxis/core/windows_reference.py +61 -0
- chronaxis/execution/__init__.py +6 -0
- chronaxis/execution/batch_signal_groups.py +122 -0
- chronaxis/execution/bindings.py +296 -0
- chronaxis/execution/boundaries.py +568 -0
- chronaxis/execution/calculation_blocks.py +338 -0
- chronaxis/execution/calculation_values.py +55 -0
- chronaxis/execution/can_batch_reader.py +356 -0
- chronaxis/execution/can_reader.py +948 -0
- chronaxis/execution/can_reference_template.py +61 -0
- chronaxis/execution/condition_evidence.py +370 -0
- chronaxis/execution/conditional_integral_facts.py +310 -0
- chronaxis/execution/conditional_integral_reduction.py +216 -0
- chronaxis/execution/csv_observation.py +524 -0
- chronaxis/execution/csv_reader.py +662 -0
- chronaxis/execution/current_message_calculation.py +225 -0
- chronaxis/execution/driver_expression.py +274 -0
- chronaxis/execution/expressions.py +618 -0
- chronaxis/execution/frame_capture.py +245 -0
- chronaxis/execution/groups.py +236 -0
- chronaxis/execution/historical_conditional_blocks.py +264 -0
- chronaxis/execution/historical_conditional_integral.py +226 -0
- chronaxis/execution/historical_conditional_time_calculation.py +368 -0
- chronaxis/execution/historical_integral.py +219 -0
- chronaxis/execution/historical_observation.py +372 -0
- chronaxis/execution/historical_sample_calculation.py +338 -0
- chronaxis/execution/historical_selection_rows.py +300 -0
- chronaxis/execution/historical_time_calculation.py +341 -0
- chronaxis/execution/history.py +572 -0
- chronaxis/execution/history_records.py +225 -0
- chronaxis/execution/hold.py +448 -0
- chronaxis/execution/integral_facts.py +311 -0
- chronaxis/execution/integral_reduction.py +216 -0
- chronaxis/execution/legacy_frame_samples.py +94 -0
- chronaxis/execution/memory_reader.py +247 -0
- chronaxis/execution/message_bindings.py +293 -0
- chronaxis/execution/message_delivery.py +37 -0
- chronaxis/execution/observed_ingestion.py +551 -0
- chronaxis/execution/raw_signal_groups.py +192 -0
- chronaxis/execution/record_alarm_duration.py +114 -0
- chronaxis/execution/record_delta_condition.py +167 -0
- chronaxis/execution/record_diagnostics.py +87 -0
- chronaxis/execution/record_event_durations.py +143 -0
- chronaxis/execution/record_export_samples.py +94 -0
- chronaxis/execution/record_exports.py +155 -0
- chronaxis/execution/record_integral.py +196 -0
- chronaxis/execution/record_point_buffer.py +101 -0
- chronaxis/execution/record_rule_timeline.py +344 -0
- chronaxis/execution/record_sample.py +46 -0
- chronaxis/execution/record_sample_series.py +29 -0
- chronaxis/execution/record_scope_calculations.py +290 -0
- chronaxis/execution/record_selection.py +62 -0
- chronaxis/execution/record_sequences.py +199 -0
- chronaxis/execution/record_session_calculations.py +778 -0
- chronaxis/execution/record_signal_export.py +133 -0
- chronaxis/execution/record_source_cursor.py +295 -0
- chronaxis/execution/record_time_calculation.py +322 -0
- chronaxis/execution/record_time_indexes.py +143 -0
- chronaxis/execution/record_value_history.py +160 -0
- chronaxis/execution/record_windows.py +229 -0
- chronaxis/execution/required_expression.py +52 -0
- chronaxis/execution/retained_metadata.py +71 -0
- chronaxis/execution/run_session.py +402 -0
- chronaxis/execution/scanned_signal_proof.py +550 -0
- chronaxis/execution/signal_validity.py +40 -0
- chronaxis/execution/state.py +280 -0
- chronaxis/execution/temporal_buffer.py +508 -0
- chronaxis/execution/text_can_reader.py +359 -0
- chronaxis/execution/timeline.py +309 -0
- chronaxis/execution/timeline_multi.py +415 -0
- chronaxis/execution/window_delta_events.py +220 -0
- chronaxis/execution/window_replay.py +350 -0
- chronaxis/execution/windows.py +173 -0
- chronaxis/guide/README.md +70 -0
- chronaxis/guide/api/AnalysisError.md +14 -0
- chronaxis/guide/api/AnalysisPlan.md +96 -0
- chronaxis/guide/api/AnalysisResult.md +398 -0
- chronaxis/guide/api/AnalysisRunner.md +155 -0
- chronaxis/guide/api/BatchJob.md +19 -0
- chronaxis/guide/api/BatchJobResult.md +61 -0
- chronaxis/guide/api/BatchPlan.md +48 -0
- chronaxis/guide/api/BatchReport.md +108 -0
- chronaxis/guide/api/BatchRunner.md +84 -0
- chronaxis/guide/api/OutputManifest.md +23 -0
- chronaxis/guide/api/PlanFragment.md +47 -0
- chronaxis/guide/api/PlanValidationError.md +98 -0
- chronaxis/guide/api/PresetSpec.md +63 -0
- chronaxis/guide/api/ResultClosedError.md +14 -0
- chronaxis/guide/api/RunMetadata.md +100 -0
- chronaxis/guide/api/TimeConversion.md +29 -0
- chronaxis/guide/api/TimeOverflowError.md +17 -0
- chronaxis/guide/api/build_preset.md +36 -0
- chronaxis/guide/api/checked_add_ns.md +30 -0
- chronaxis/guide/api/convert_time.md +40 -0
- chronaxis/guide/api/explain_analysis_plan.md +38 -0
- chronaxis/guide/api/index.json +185 -0
- chronaxis/guide/api/load_analysis_plan.md +34 -0
- chronaxis/guide/api/load_batch_plan.md +36 -0
- chronaxis/guide/api/parse_datetime_ns.md +35 -0
- chronaxis/guide/api/parse_duration.md +30 -0
- chronaxis/guide/api/resolve_preset_roles.md +37 -0
- chronaxis/guide/api/run_batch.md +38 -0
- chronaxis/guide/api/shift_times_reference.md +33 -0
- chronaxis/guide/api/time_deltas_reference.md +37 -0
- chronaxis/guide/api/validate_analysis_plan.md +38 -0
- chronaxis/guide/en/README.md +74 -0
- chronaxis/guide/en/api/AnalysisError.md +14 -0
- chronaxis/guide/en/api/AnalysisPlan.md +93 -0
- chronaxis/guide/en/api/AnalysisResult.md +398 -0
- chronaxis/guide/en/api/AnalysisRunner.md +191 -0
- chronaxis/guide/en/api/BatchJob.md +17 -0
- chronaxis/guide/en/api/BatchJobResult.md +43 -0
- chronaxis/guide/en/api/BatchPlan.md +37 -0
- chronaxis/guide/en/api/BatchReport.md +52 -0
- chronaxis/guide/en/api/BatchRunner.md +51 -0
- chronaxis/guide/en/api/OutputManifest.md +23 -0
- chronaxis/guide/en/api/PlanFragment.md +33 -0
- chronaxis/guide/en/api/PlanValidationError.md +58 -0
- chronaxis/guide/en/api/PresetSpec.md +51 -0
- chronaxis/guide/en/api/ResultClosedError.md +14 -0
- chronaxis/guide/en/api/RunMetadata.md +100 -0
- chronaxis/guide/en/api/TimeConversion.md +23 -0
- chronaxis/guide/en/api/TimeOverflowError.md +14 -0
- chronaxis/guide/en/api/build_preset.md +23 -0
- chronaxis/guide/en/api/checked_add_ns.md +21 -0
- chronaxis/guide/en/api/convert_time.md +25 -0
- chronaxis/guide/en/api/explain_analysis_plan.md +30 -0
- chronaxis/guide/en/api/index.json +185 -0
- chronaxis/guide/en/api/load_analysis_plan.md +27 -0
- chronaxis/guide/en/api/load_batch_plan.md +28 -0
- chronaxis/guide/en/api/parse_datetime_ns.md +23 -0
- chronaxis/guide/en/api/parse_duration.md +20 -0
- chronaxis/guide/en/api/resolve_preset_roles.md +23 -0
- chronaxis/guide/en/api/run_batch.md +39 -0
- chronaxis/guide/en/api/shift_times_reference.md +21 -0
- chronaxis/guide/en/api/time_deltas_reference.md +22 -0
- chronaxis/guide/en/api/validate_analysis_plan.md +29 -0
- chronaxis/guide/en/fields/analysis/calculations-all-1.json +345 -0
- chronaxis/guide/en/fields/analysis/calculations-all-2.json +300 -0
- chronaxis/guide/en/fields/analysis/calculations-all-3.json +84 -0
- chronaxis/guide/en/fields/analysis/config_version-all-1.json +24 -0
- chronaxis/guide/en/fields/analysis/dataset-all-1.json +344 -0
- chronaxis/guide/en/fields/analysis/derived-all-1.json +147 -0
- chronaxis/guide/en/fields/analysis/diagnostics-all-1.json +69 -0
- chronaxis/guide/en/fields/analysis/execution-all-1.json +167 -0
- chronaxis/guide/en/fields/analysis/imports-all-1.json +39 -0
- chronaxis/guide/en/fields/analysis/intervals-all-1.json +173 -0
- chronaxis/guide/en/fields/analysis/message_calculations-all-1.json +345 -0
- chronaxis/guide/en/fields/analysis/message_calculations-all-2.json +270 -0
- chronaxis/guide/en/fields/analysis/metadata-all-1.json +24 -0
- chronaxis/guide/en/fields/analysis/outputs-all-1.json +332 -0
- chronaxis/guide/en/fields/analysis/outputs-all-2.json +319 -0
- chronaxis/guide/en/fields/analysis/outputs-all-3.json +321 -0
- chronaxis/guide/en/fields/analysis/outputs-all-4.json +236 -0
- chronaxis/guide/en/fields/analysis/outputs-all-5.json +246 -0
- chronaxis/guide/en/fields/analysis/outputs-all-6.json +214 -0
- chronaxis/guide/en/fields/analysis/overrides-all-1.json +104 -0
- chronaxis/guide/en/fields/analysis/presets-charge_session-1.json +398 -0
- chronaxis/guide/en/fields/analysis/presets-charge_session-2.json +114 -0
- chronaxis/guide/en/fields/analysis/presets-command_response-1.json +376 -0
- chronaxis/guide/en/fields/analysis/presets-fault_context-1.json +285 -0
- chronaxis/guide/en/fields/analysis/presets-threshold_excursion-1.json +317 -0
- chronaxis/guide/en/fields/analysis/rules-condition_duration-1.json +344 -0
- chronaxis/guide/en/fields/analysis/rules-condition_duration-2.json +27 -0
- chronaxis/guide/en/fields/analysis/rules-debounce-1.json +335 -0
- chronaxis/guide/en/fields/analysis/rules-falling_edge-1.json +317 -0
- chronaxis/guide/en/fields/analysis/rules-hysteresis-1.json +334 -0
- chronaxis/guide/en/fields/analysis/rules-hysteresis-2.json +27 -0
- chronaxis/guide/en/fields/analysis/rules-rising_edge-1.json +317 -0
- chronaxis/guide/en/fields/analysis/rules-start_end-1.json +333 -0
- chronaxis/guide/en/fields/analysis/rules-start_end-2.json +60 -0
- chronaxis/guide/en/fields/analysis/rules-start_only-1.json +334 -0
- chronaxis/guide/en/fields/analysis/rules-window_delta-1.json +338 -0
- chronaxis/guide/en/fields/analysis/rules-window_delta-2.json +96 -0
- chronaxis/guide/en/fields/analysis/sequences-all-1.json +378 -0
- chronaxis/guide/en/fields/analysis/sequences-all-2.json +70 -0
- chronaxis/guide/en/fields/analysis/signals-variant-1-1.json +349 -0
- chronaxis/guide/en/fields/analysis/signals-variant-1-2.json +297 -0
- chronaxis/guide/en/fields/analysis/signals-variant-1-3.json +323 -0
- chronaxis/guide/en/fields/analysis/signals-variant-1-4.json +192 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-1.json +327 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-2.json +312 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-3.json +294 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-4.json +253 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-5.json +44 -0
- chronaxis/guide/en/fields/analysis/sources-can_asc-1.json +318 -0
- chronaxis/guide/en/fields/analysis/sources-can_asc-2.json +310 -0
- chronaxis/guide/en/fields/analysis/sources-can_asc-3.json +311 -0
- chronaxis/guide/en/fields/analysis/sources-can_asc-4.json +69 -0
- chronaxis/guide/en/fields/analysis/sources-can_blf-1.json +317 -0
- chronaxis/guide/en/fields/analysis/sources-can_blf-2.json +310 -0
- chronaxis/guide/en/fields/analysis/sources-can_blf-3.json +317 -0
- chronaxis/guide/en/fields/analysis/sources-memory-1.json +332 -0
- chronaxis/guide/en/fields/analysis/sources-memory-2.json +125 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-1.json +330 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-10.json +233 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-11.json +225 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-12.json +228 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-13.json +226 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-14.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-15.json +227 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-16.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-17.json +238 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-18.json +239 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-19.json +233 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-2.json +310 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-20.json +242 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-21.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-22.json +228 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-23.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-24.json +223 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-25.json +290 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-26.json +131 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-3.json +297 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-4.json +226 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-5.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-6.json +227 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-7.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-8.json +238 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-9.json +239 -0
- chronaxis/guide/en/fields/analysis/sources-signal_csv-1.json +331 -0
- chronaxis/guide/en/fields/analysis/sources-signal_csv-2.json +307 -0
- chronaxis/guide/en/fields/analysis/sources-signal_csv-3.json +315 -0
- chronaxis/guide/en/fields/analysis/sources-variant-6-1.json +319 -0
- chronaxis/guide/en/fields/analysis/sources-variant-6-2.json +307 -0
- chronaxis/guide/en/fields/analysis/sources-variant-6-3.json +312 -0
- chronaxis/guide/en/fields/analysis/sources-variant-6-4.json +113 -0
- chronaxis/guide/en/fields/analysis/windows-all-1.json +361 -0
- chronaxis/guide/en/fields/analysis/windows-all-2.json +187 -0
- chronaxis/guide/en/fields/batch/backend-all-1.json +26 -0
- chronaxis/guide/en/fields/batch/batch_version-all-1.json +22 -0
- chronaxis/guide/en/fields/batch/fail_fast-all-1.json +22 -0
- chronaxis/guide/en/fields/batch/inputs-all-1.json +161 -0
- chronaxis/guide/en/fields/batch/jobs-all-1.json +58 -0
- chronaxis/guide/en/fields/batch/process_count-all-1.json +23 -0
- chronaxis/guide/en/fields/batch/source-all-1.json +22 -0
- chronaxis/guide/en/fields/batch/template-all-1.json +22 -0
- chronaxis/guide/en/fields/definitions/derived-all-1.json +121 -0
- chronaxis/guide/en/fields/definitions/signals-all-1.json +336 -0
- chronaxis/guide/en/fields/definitions/signals-all-2.json +307 -0
- chronaxis/guide/en/fields/definitions/signals-all-3.json +290 -0
- chronaxis/guide/en/fields/definitions/signals-all-4.json +347 -0
- chronaxis/guide/en/fields/definitions/signals-all-5.json +297 -0
- chronaxis/guide/en/fields/definitions/signals-all-6.json +259 -0
- chronaxis/guide/en/fields/definitions/signals-all-7.json +117 -0
- chronaxis/guide/en/fields/definitions/sources-all-1.json +332 -0
- chronaxis/guide/en/fields/definitions/sources-all-10.json +306 -0
- chronaxis/guide/en/fields/definitions/sources-all-11.json +294 -0
- chronaxis/guide/en/fields/definitions/sources-all-12.json +212 -0
- chronaxis/guide/en/fields/definitions/sources-all-13.json +217 -0
- chronaxis/guide/en/fields/definitions/sources-all-14.json +213 -0
- chronaxis/guide/en/fields/definitions/sources-all-15.json +214 -0
- chronaxis/guide/en/fields/definitions/sources-all-16.json +215 -0
- chronaxis/guide/en/fields/definitions/sources-all-17.json +213 -0
- chronaxis/guide/en/fields/definitions/sources-all-18.json +214 -0
- chronaxis/guide/en/fields/definitions/sources-all-19.json +213 -0
- chronaxis/guide/en/fields/definitions/sources-all-2.json +323 -0
- chronaxis/guide/en/fields/definitions/sources-all-20.json +217 -0
- chronaxis/guide/en/fields/definitions/sources-all-21.json +210 -0
- chronaxis/guide/en/fields/definitions/sources-all-22.json +214 -0
- chronaxis/guide/en/fields/definitions/sources-all-23.json +218 -0
- chronaxis/guide/en/fields/definitions/sources-all-24.json +209 -0
- chronaxis/guide/en/fields/definitions/sources-all-25.json +215 -0
- chronaxis/guide/en/fields/definitions/sources-all-26.json +218 -0
- chronaxis/guide/en/fields/definitions/sources-all-27.json +224 -0
- chronaxis/guide/en/fields/definitions/sources-all-28.json +215 -0
- chronaxis/guide/en/fields/definitions/sources-all-29.json +205 -0
- chronaxis/guide/en/fields/definitions/sources-all-3.json +303 -0
- chronaxis/guide/en/fields/definitions/sources-all-30.json +298 -0
- chronaxis/guide/en/fields/definitions/sources-all-31.json +315 -0
- chronaxis/guide/en/fields/definitions/sources-all-32.json +306 -0
- chronaxis/guide/en/fields/definitions/sources-all-33.json +209 -0
- chronaxis/guide/en/fields/definitions/sources-all-4.json +336 -0
- chronaxis/guide/en/fields/definitions/sources-all-5.json +299 -0
- chronaxis/guide/en/fields/definitions/sources-all-6.json +307 -0
- chronaxis/guide/en/fields/definitions/sources-all-7.json +320 -0
- chronaxis/guide/en/fields/definitions/sources-all-8.json +303 -0
- chronaxis/guide/en/fields/definitions/sources-all-9.json +315 -0
- chronaxis/guide/en/fields/index.json +3450 -0
- chronaxis/guide/en/fields/mapping/aliases-all-1.json +91 -0
- chronaxis/guide/en/fields/mapping/analysis-all-1.json +382 -0
- chronaxis/guide/en/fields/mapping/analysis-all-10.json +301 -0
- chronaxis/guide/en/fields/mapping/analysis-all-11.json +312 -0
- chronaxis/guide/en/fields/mapping/analysis-all-12.json +311 -0
- chronaxis/guide/en/fields/mapping/analysis-all-13.json +314 -0
- chronaxis/guide/en/fields/mapping/analysis-all-14.json +310 -0
- chronaxis/guide/en/fields/mapping/analysis-all-15.json +297 -0
- chronaxis/guide/en/fields/mapping/analysis-all-16.json +226 -0
- chronaxis/guide/en/fields/mapping/analysis-all-17.json +230 -0
- chronaxis/guide/en/fields/mapping/analysis-all-18.json +227 -0
- chronaxis/guide/en/fields/mapping/analysis-all-19.json +230 -0
- chronaxis/guide/en/fields/mapping/analysis-all-2.json +323 -0
- chronaxis/guide/en/fields/mapping/analysis-all-20.json +221 -0
- chronaxis/guide/en/fields/mapping/analysis-all-21.json +237 -0
- chronaxis/guide/en/fields/mapping/analysis-all-22.json +233 -0
- chronaxis/guide/en/fields/mapping/analysis-all-23.json +222 -0
- chronaxis/guide/en/fields/mapping/analysis-all-24.json +231 -0
- chronaxis/guide/en/fields/mapping/analysis-all-25.json +225 -0
- chronaxis/guide/en/fields/mapping/analysis-all-26.json +230 -0
- chronaxis/guide/en/fields/mapping/analysis-all-27.json +228 -0
- chronaxis/guide/en/fields/mapping/analysis-all-28.json +230 -0
- chronaxis/guide/en/fields/mapping/analysis-all-29.json +223 -0
- chronaxis/guide/en/fields/mapping/analysis-all-3.json +318 -0
- chronaxis/guide/en/fields/mapping/analysis-all-30.json +233 -0
- chronaxis/guide/en/fields/mapping/analysis-all-31.json +218 -0
- chronaxis/guide/en/fields/mapping/analysis-all-32.json +239 -0
- chronaxis/guide/en/fields/mapping/analysis-all-33.json +233 -0
- chronaxis/guide/en/fields/mapping/analysis-all-34.json +225 -0
- chronaxis/guide/en/fields/mapping/analysis-all-35.json +228 -0
- chronaxis/guide/en/fields/mapping/analysis-all-36.json +226 -0
- chronaxis/guide/en/fields/mapping/analysis-all-37.json +244 -0
- chronaxis/guide/en/fields/mapping/analysis-all-38.json +326 -0
- chronaxis/guide/en/fields/mapping/analysis-all-39.json +299 -0
- chronaxis/guide/en/fields/mapping/analysis-all-4.json +297 -0
- chronaxis/guide/en/fields/mapping/analysis-all-40.json +311 -0
- chronaxis/guide/en/fields/mapping/analysis-all-41.json +310 -0
- chronaxis/guide/en/fields/mapping/analysis-all-42.json +346 -0
- chronaxis/guide/en/fields/mapping/analysis-all-43.json +267 -0
- chronaxis/guide/en/fields/mapping/analysis-all-44.json +327 -0
- chronaxis/guide/en/fields/mapping/analysis-all-45.json +279 -0
- chronaxis/guide/en/fields/mapping/analysis-all-46.json +327 -0
- chronaxis/guide/en/fields/mapping/analysis-all-47.json +312 -0
- chronaxis/guide/en/fields/mapping/analysis-all-48.json +294 -0
- chronaxis/guide/en/fields/mapping/analysis-all-49.json +253 -0
- chronaxis/guide/en/fields/mapping/analysis-all-5.json +312 -0
- chronaxis/guide/en/fields/mapping/analysis-all-50.json +346 -0
- chronaxis/guide/en/fields/mapping/analysis-all-51.json +324 -0
- chronaxis/guide/en/fields/mapping/analysis-all-52.json +335 -0
- chronaxis/guide/en/fields/mapping/analysis-all-53.json +317 -0
- chronaxis/guide/en/fields/mapping/analysis-all-54.json +316 -0
- chronaxis/guide/en/fields/mapping/analysis-all-55.json +302 -0
- chronaxis/guide/en/fields/mapping/analysis-all-56.json +319 -0
- chronaxis/guide/en/fields/mapping/analysis-all-57.json +334 -0
- chronaxis/guide/en/fields/mapping/analysis-all-58.json +333 -0
- chronaxis/guide/en/fields/mapping/analysis-all-59.json +359 -0
- chronaxis/guide/en/fields/mapping/analysis-all-6.json +327 -0
- chronaxis/guide/en/fields/mapping/analysis-all-60.json +303 -0
- chronaxis/guide/en/fields/mapping/analysis-all-61.json +326 -0
- chronaxis/guide/en/fields/mapping/analysis-all-62.json +301 -0
- chronaxis/guide/en/fields/mapping/analysis-all-63.json +326 -0
- chronaxis/guide/en/fields/mapping/analysis-all-64.json +367 -0
- chronaxis/guide/en/fields/mapping/analysis-all-65.json +334 -0
- chronaxis/guide/en/fields/mapping/analysis-all-66.json +358 -0
- chronaxis/guide/en/fields/mapping/analysis-all-67.json +349 -0
- chronaxis/guide/en/fields/mapping/analysis-all-68.json +331 -0
- chronaxis/guide/en/fields/mapping/analysis-all-69.json +304 -0
- chronaxis/guide/en/fields/mapping/analysis-all-7.json +303 -0
- chronaxis/guide/en/fields/mapping/analysis-all-70.json +349 -0
- chronaxis/guide/en/fields/mapping/analysis-all-71.json +288 -0
- chronaxis/guide/en/fields/mapping/analysis-all-72.json +316 -0
- chronaxis/guide/en/fields/mapping/analysis-all-73.json +266 -0
- chronaxis/guide/en/fields/mapping/analysis-all-74.json +227 -0
- chronaxis/guide/en/fields/mapping/analysis-all-75.json +239 -0
- chronaxis/guide/en/fields/mapping/analysis-all-76.json +274 -0
- chronaxis/guide/en/fields/mapping/analysis-all-77.json +380 -0
- chronaxis/guide/en/fields/mapping/analysis-all-78.json +313 -0
- chronaxis/guide/en/fields/mapping/analysis-all-79.json +338 -0
- chronaxis/guide/en/fields/mapping/analysis-all-8.json +292 -0
- chronaxis/guide/en/fields/mapping/analysis-all-80.json +304 -0
- chronaxis/guide/en/fields/mapping/analysis-all-81.json +140 -0
- chronaxis/guide/en/fields/mapping/analysis-all-9.json +332 -0
- chronaxis/guide/en/fields/mapping/io_policy-all-1.json +19 -0
- chronaxis/guide/en/fields/mapping/mapping_version-all-1.json +19 -0
- chronaxis/guide/en/fields/mapping/path_base-all-1.json +19 -0
- chronaxis/guide/en/fields/mapping/sections-all-1.json +402 -0
- chronaxis/guide/en/fields/mapping/sections-all-2.json +232 -0
- chronaxis/guide/en/semantics.md +70 -0
- chronaxis/guide/en/tasks.json +290 -0
- chronaxis/guide/en/workflow.md +41 -0
- chronaxis/guide/examples/analysis-imports.yaml +22 -0
- chronaxis/guide/examples/analysis.yaml +23 -0
- chronaxis/guide/examples/batch-minimal.yaml +3 -0
- chronaxis/guide/examples/conditional-energy.yaml +36 -0
- chronaxis/guide/examples/data/activity.csv +6 -0
- chronaxis/guide/examples/data/can/activity.asc +11 -0
- chronaxis/guide/examples/data/can/calculation-minimal.asc +6 -0
- chronaxis/guide/examples/data/can/conditional-energy/part-1.asc +92 -0
- chronaxis/guide/examples/data/can/conditional-energy/part-2.asc +36 -0
- chronaxis/guide/examples/data/can/conditional-energy/signals.dbc +10 -0
- chronaxis/guide/examples/data/can/execution-comparison.asc +12 -0
- chronaxis/guide/examples/data/can/execution-report.asc +4 -0
- chronaxis/guide/examples/data/can/expression-extended.asc +11 -0
- chronaxis/guide/examples/data/can/interval-actual.asc +6 -0
- chronaxis/guide/examples/data/can/preset-charge-energy.asc +15 -0
- chronaxis/guide/examples/data/can/preset-charge-minimal.asc +11 -0
- chronaxis/guide/examples/data/can/preset-command-automatic.asc +11 -0
- chronaxis/guide/examples/data/can/preset-fault-context.asc +7 -0
- chronaxis/guide/examples/data/can/preset-threshold-delay.asc +7 -0
- chronaxis/guide/examples/data/can/preset-threshold-partial.asc +7 -0
- chronaxis/guide/examples/data/can/quality.asc +6 -0
- chronaxis/guide/examples/data/can/quickstart-parts/part1.asc +4 -0
- chronaxis/guide/examples/data/can/quickstart-parts/part2.asc +3 -0
- chronaxis/guide/examples/data/can/quickstart.asc +6 -0
- chronaxis/guide/examples/data/can/rule-condition_duration-extended.asc +35 -0
- chronaxis/guide/examples/data/can/rule-condition_duration-minimal.asc +19 -0
- chronaxis/guide/examples/data/can/rule-debounce-extended.asc +19 -0
- chronaxis/guide/examples/data/can/rule-falling_edge-extended.asc +35 -0
- chronaxis/guide/examples/data/can/rule-hysteresis-extended.asc +19 -0
- chronaxis/guide/examples/data/can/rule-start_end-extended.asc +35 -0
- chronaxis/guide/examples/data/can/rule-start_only-extended.asc +19 -0
- chronaxis/guide/examples/data/can/rule-window_delta-extended.asc +19 -0
- chronaxis/guide/examples/data/can/sequence-outcomes.asc +19 -0
- chronaxis/guide/examples/data/can/signal-types.asc +13 -0
- chronaxis/guide/examples/data/can/start-end.asc +30 -0
- chronaxis/guide/examples/data/can/teaching-base.asc +58 -0
- chronaxis/guide/examples/data/can/teaching.dbc +53 -0
- chronaxis/guide/examples/data/joint-current.csv +5 -0
- chronaxis/guide/examples/data/joint.asc +5 -0
- chronaxis/guide/examples/data/joint.dbc +7 -0
- chronaxis/guide/examples/data/message-clean.asc +6 -0
- chronaxis/guide/examples/data/message-direction.asc +7 -0
- chronaxis/guide/examples/data/message-direction.dbc +7 -0
- chronaxis/guide/examples/data/power.blf +0 -0
- chronaxis/guide/examples/data/power.dbc +6 -0
- chronaxis/guide/examples/data/quality.csv +5 -0
- chronaxis/guide/examples/data/raw-can-example.csv +5 -0
- chronaxis/guide/examples/data/signal-types.csv +5 -0
- chronaxis/guide/examples/data/signals.csv +6 -0
- chronaxis/guide/examples/data/timing.asc +6 -0
- chronaxis/guide/examples/data/timing.dbc +11 -0
- chronaxis/guide/examples/export-can-minimal.yaml +24 -0
- chronaxis/guide/examples/input-csv-minimal.yaml +23 -0
- chronaxis/guide/examples/preset-charge-energy.yaml +41 -0
- chronaxis/guide/examples/preset-charge-minimal.yaml +31 -0
- chronaxis/guide/examples/preset-fault-context.yaml +27 -0
- chronaxis/guide/examples/quality.yaml +19 -0
- chronaxis/guide/examples/sequence-outcomes.yaml +39 -0
- chronaxis/guide/examples/shared/definitions.yaml +14 -0
- chronaxis/guide/examples/signal-enum-minimal.yaml +19 -0
- chronaxis/guide/examples/signal-number-conversion.yaml +24 -0
- chronaxis/guide/examples/window-merged.yaml +28 -0
- chronaxis/guide/fields/analysis/calculations-all-1.json +360 -0
- chronaxis/guide/fields/analysis/calculations-all-2.json +299 -0
- chronaxis/guide/fields/analysis/calculations-all-3.json +70 -0
- chronaxis/guide/fields/analysis/config_version-all-1.json +24 -0
- chronaxis/guide/fields/analysis/dataset-all-1.json +344 -0
- chronaxis/guide/fields/analysis/derived-all-1.json +147 -0
- chronaxis/guide/fields/analysis/diagnostics-all-1.json +69 -0
- chronaxis/guide/fields/analysis/execution-all-1.json +167 -0
- chronaxis/guide/fields/analysis/imports-all-1.json +39 -0
- chronaxis/guide/fields/analysis/intervals-all-1.json +173 -0
- chronaxis/guide/fields/analysis/message_calculations-all-1.json +360 -0
- chronaxis/guide/fields/analysis/message_calculations-all-2.json +255 -0
- chronaxis/guide/fields/analysis/metadata-all-1.json +24 -0
- chronaxis/guide/fields/analysis/outputs-all-1.json +349 -0
- chronaxis/guide/fields/analysis/outputs-all-2.json +302 -0
- chronaxis/guide/fields/analysis/outputs-all-3.json +321 -0
- chronaxis/guide/fields/analysis/outputs-all-4.json +253 -0
- chronaxis/guide/fields/analysis/outputs-all-5.json +244 -0
- chronaxis/guide/fields/analysis/outputs-all-6.json +199 -0
- chronaxis/guide/fields/analysis/overrides-all-1.json +104 -0
- chronaxis/guide/fields/analysis/presets-charge_session-1.json +398 -0
- chronaxis/guide/fields/analysis/presets-charge_session-2.json +114 -0
- chronaxis/guide/fields/analysis/presets-command_response-1.json +376 -0
- chronaxis/guide/fields/analysis/presets-fault_context-1.json +285 -0
- chronaxis/guide/fields/analysis/presets-threshold_excursion-1.json +317 -0
- chronaxis/guide/fields/analysis/rules-condition_duration-1.json +344 -0
- chronaxis/guide/fields/analysis/rules-condition_duration-2.json +27 -0
- chronaxis/guide/fields/analysis/rules-debounce-1.json +335 -0
- chronaxis/guide/fields/analysis/rules-falling_edge-1.json +317 -0
- chronaxis/guide/fields/analysis/rules-hysteresis-1.json +334 -0
- chronaxis/guide/fields/analysis/rules-hysteresis-2.json +27 -0
- chronaxis/guide/fields/analysis/rules-rising_edge-1.json +317 -0
- chronaxis/guide/fields/analysis/rules-start_end-1.json +349 -0
- chronaxis/guide/fields/analysis/rules-start_end-2.json +44 -0
- chronaxis/guide/fields/analysis/rules-start_only-1.json +334 -0
- chronaxis/guide/fields/analysis/rules-window_delta-1.json +356 -0
- chronaxis/guide/fields/analysis/rules-window_delta-2.json +78 -0
- chronaxis/guide/fields/analysis/sequences-all-1.json +394 -0
- chronaxis/guide/fields/analysis/sequences-all-2.json +54 -0
- chronaxis/guide/fields/analysis/signals-variant-1-1.json +349 -0
- chronaxis/guide/fields/analysis/signals-variant-1-2.json +297 -0
- chronaxis/guide/fields/analysis/signals-variant-1-3.json +340 -0
- chronaxis/guide/fields/analysis/signals-variant-1-4.json +175 -0
- chronaxis/guide/fields/analysis/signals-variant-2-1.json +327 -0
- chronaxis/guide/fields/analysis/signals-variant-2-2.json +335 -0
- chronaxis/guide/fields/analysis/signals-variant-2-3.json +289 -0
- chronaxis/guide/fields/analysis/signals-variant-2-4.json +270 -0
- chronaxis/guide/fields/analysis/sources-can_asc-1.json +318 -0
- chronaxis/guide/fields/analysis/sources-can_asc-2.json +310 -0
- chronaxis/guide/fields/analysis/sources-can_asc-3.json +311 -0
- chronaxis/guide/fields/analysis/sources-can_asc-4.json +69 -0
- chronaxis/guide/fields/analysis/sources-can_blf-1.json +317 -0
- chronaxis/guide/fields/analysis/sources-can_blf-2.json +310 -0
- chronaxis/guide/fields/analysis/sources-can_blf-3.json +317 -0
- chronaxis/guide/fields/analysis/sources-memory-1.json +347 -0
- chronaxis/guide/fields/analysis/sources-memory-2.json +110 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-1.json +330 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-10.json +233 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-11.json +225 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-12.json +228 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-13.json +226 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-14.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-15.json +227 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-16.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-17.json +238 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-18.json +239 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-19.json +233 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-2.json +310 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-20.json +242 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-21.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-22.json +228 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-23.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-24.json +223 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-25.json +290 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-26.json +131 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-3.json +297 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-4.json +226 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-5.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-6.json +227 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-7.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-8.json +238 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-9.json +239 -0
- chronaxis/guide/fields/analysis/sources-signal_csv-1.json +331 -0
- chronaxis/guide/fields/analysis/sources-signal_csv-2.json +327 -0
- chronaxis/guide/fields/analysis/sources-signal_csv-3.json +295 -0
- chronaxis/guide/fields/analysis/sources-variant-6-1.json +319 -0
- chronaxis/guide/fields/analysis/sources-variant-6-2.json +327 -0
- chronaxis/guide/fields/analysis/sources-variant-6-3.json +314 -0
- chronaxis/guide/fields/analysis/sources-variant-6-4.json +91 -0
- chronaxis/guide/fields/analysis/windows-all-1.json +361 -0
- chronaxis/guide/fields/analysis/windows-all-2.json +187 -0
- chronaxis/guide/fields/batch/backend-all-1.json +26 -0
- chronaxis/guide/fields/batch/batch_version-all-1.json +22 -0
- chronaxis/guide/fields/batch/fail_fast-all-1.json +22 -0
- chronaxis/guide/fields/batch/inputs-all-1.json +161 -0
- chronaxis/guide/fields/batch/jobs-all-1.json +58 -0
- chronaxis/guide/fields/batch/process_count-all-1.json +23 -0
- chronaxis/guide/fields/batch/source-all-1.json +22 -0
- chronaxis/guide/fields/batch/template-all-1.json +22 -0
- chronaxis/guide/fields/definitions/derived-all-1.json +121 -0
- chronaxis/guide/fields/definitions/signals-all-1.json +336 -0
- chronaxis/guide/fields/definitions/signals-all-2.json +307 -0
- chronaxis/guide/fields/definitions/signals-all-3.json +305 -0
- chronaxis/guide/fields/definitions/signals-all-4.json +352 -0
- chronaxis/guide/fields/definitions/signals-all-5.json +311 -0
- chronaxis/guide/fields/definitions/signals-all-6.json +254 -0
- chronaxis/guide/fields/definitions/signals-all-7.json +88 -0
- chronaxis/guide/fields/definitions/sources-all-1.json +332 -0
- chronaxis/guide/fields/definitions/sources-all-10.json +307 -0
- chronaxis/guide/fields/definitions/sources-all-11.json +280 -0
- chronaxis/guide/fields/definitions/sources-all-12.json +209 -0
- chronaxis/guide/fields/definitions/sources-all-13.json +219 -0
- chronaxis/guide/fields/definitions/sources-all-14.json +213 -0
- chronaxis/guide/fields/definitions/sources-all-15.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-16.json +232 -0
- chronaxis/guide/fields/definitions/sources-all-17.json +213 -0
- chronaxis/guide/fields/definitions/sources-all-18.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-19.json +217 -0
- chronaxis/guide/fields/definitions/sources-all-2.json +336 -0
- chronaxis/guide/fields/definitions/sources-all-20.json +228 -0
- chronaxis/guide/fields/definitions/sources-all-21.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-22.json +232 -0
- chronaxis/guide/fields/definitions/sources-all-23.json +213 -0
- chronaxis/guide/fields/definitions/sources-all-24.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-25.json +217 -0
- chronaxis/guide/fields/definitions/sources-all-26.json +228 -0
- chronaxis/guide/fields/definitions/sources-all-27.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-28.json +217 -0
- chronaxis/guide/fields/definitions/sources-all-29.json +227 -0
- chronaxis/guide/fields/definitions/sources-all-3.json +306 -0
- chronaxis/guide/fields/definitions/sources-all-30.json +333 -0
- chronaxis/guide/fields/definitions/sources-all-31.json +302 -0
- chronaxis/guide/fields/definitions/sources-all-32.json +319 -0
- chronaxis/guide/fields/definitions/sources-all-33.json +89 -0
- chronaxis/guide/fields/definitions/sources-all-4.json +336 -0
- chronaxis/guide/fields/definitions/sources-all-5.json +313 -0
- chronaxis/guide/fields/definitions/sources-all-6.json +292 -0
- chronaxis/guide/fields/definitions/sources-all-7.json +319 -0
- chronaxis/guide/fields/definitions/sources-all-8.json +315 -0
- chronaxis/guide/fields/definitions/sources-all-9.json +318 -0
- chronaxis/guide/fields/index.json +3432 -0
- chronaxis/guide/fields/mapping/aliases-all-1.json +91 -0
- chronaxis/guide/fields/mapping/analysis-all-1.json +382 -0
- chronaxis/guide/fields/mapping/analysis-all-10.json +307 -0
- chronaxis/guide/fields/mapping/analysis-all-11.json +311 -0
- chronaxis/guide/fields/mapping/analysis-all-12.json +329 -0
- chronaxis/guide/fields/mapping/analysis-all-13.json +294 -0
- chronaxis/guide/fields/mapping/analysis-all-14.json +311 -0
- chronaxis/guide/fields/mapping/analysis-all-15.json +280 -0
- chronaxis/guide/fields/mapping/analysis-all-16.json +227 -0
- chronaxis/guide/fields/mapping/analysis-all-17.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-18.json +221 -0
- chronaxis/guide/fields/mapping/analysis-all-19.json +237 -0
- chronaxis/guide/fields/mapping/analysis-all-2.json +342 -0
- chronaxis/guide/fields/mapping/analysis-all-20.json +233 -0
- chronaxis/guide/fields/mapping/analysis-all-21.json +244 -0
- chronaxis/guide/fields/mapping/analysis-all-22.json +228 -0
- chronaxis/guide/fields/mapping/analysis-all-23.json +226 -0
- chronaxis/guide/fields/mapping/analysis-all-24.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-25.json +227 -0
- chronaxis/guide/fields/mapping/analysis-all-26.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-27.json +221 -0
- chronaxis/guide/fields/mapping/analysis-all-28.json +237 -0
- chronaxis/guide/fields/mapping/analysis-all-29.json +233 -0
- chronaxis/guide/fields/mapping/analysis-all-3.json +322 -0
- chronaxis/guide/fields/mapping/analysis-all-30.json +244 -0
- chronaxis/guide/fields/mapping/analysis-all-31.json +228 -0
- chronaxis/guide/fields/mapping/analysis-all-32.json +226 -0
- chronaxis/guide/fields/mapping/analysis-all-33.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-34.json +227 -0
- chronaxis/guide/fields/mapping/analysis-all-35.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-36.json +221 -0
- chronaxis/guide/fields/mapping/analysis-all-37.json +291 -0
- chronaxis/guide/fields/mapping/analysis-all-38.json +315 -0
- chronaxis/guide/fields/mapping/analysis-all-39.json +304 -0
- chronaxis/guide/fields/mapping/analysis-all-4.json +312 -0
- chronaxis/guide/fields/mapping/analysis-all-40.json +307 -0
- chronaxis/guide/fields/mapping/analysis-all-41.json +292 -0
- chronaxis/guide/fields/mapping/analysis-all-42.json +333 -0
- chronaxis/guide/fields/mapping/analysis-all-43.json +296 -0
- chronaxis/guide/fields/mapping/analysis-all-44.json +322 -0
- chronaxis/guide/fields/mapping/analysis-all-45.json +298 -0
- chronaxis/guide/fields/mapping/analysis-all-46.json +347 -0
- chronaxis/guide/fields/mapping/analysis-all-47.json +302 -0
- chronaxis/guide/fields/mapping/analysis-all-48.json +263 -0
- chronaxis/guide/fields/mapping/analysis-all-49.json +301 -0
- chronaxis/guide/fields/mapping/analysis-all-5.json +313 -0
- chronaxis/guide/fields/mapping/analysis-all-50.json +336 -0
- chronaxis/guide/fields/mapping/analysis-all-51.json +335 -0
- chronaxis/guide/fields/mapping/analysis-all-52.json +335 -0
- chronaxis/guide/fields/mapping/analysis-all-53.json +334 -0
- chronaxis/guide/fields/mapping/analysis-all-54.json +339 -0
- chronaxis/guide/fields/mapping/analysis-all-55.json +335 -0
- chronaxis/guide/fields/mapping/analysis-all-56.json +336 -0
- chronaxis/guide/fields/mapping/analysis-all-57.json +335 -0
- chronaxis/guide/fields/mapping/analysis-all-58.json +333 -0
- chronaxis/guide/fields/mapping/analysis-all-59.json +325 -0
- chronaxis/guide/fields/mapping/analysis-all-6.json +323 -0
- chronaxis/guide/fields/mapping/analysis-all-60.json +334 -0
- chronaxis/guide/fields/mapping/analysis-all-61.json +311 -0
- chronaxis/guide/fields/mapping/analysis-all-62.json +289 -0
- chronaxis/guide/fields/mapping/analysis-all-63.json +383 -0
- chronaxis/guide/fields/mapping/analysis-all-64.json +357 -0
- chronaxis/guide/fields/mapping/analysis-all-65.json +375 -0
- chronaxis/guide/fields/mapping/analysis-all-66.json +351 -0
- chronaxis/guide/fields/mapping/analysis-all-67.json +346 -0
- chronaxis/guide/fields/mapping/analysis-all-68.json +317 -0
- chronaxis/guide/fields/mapping/analysis-all-69.json +313 -0
- chronaxis/guide/fields/mapping/analysis-all-7.json +306 -0
- chronaxis/guide/fields/mapping/analysis-all-70.json +326 -0
- chronaxis/guide/fields/mapping/analysis-all-71.json +316 -0
- chronaxis/guide/fields/mapping/analysis-all-72.json +264 -0
- chronaxis/guide/fields/mapping/analysis-all-73.json +228 -0
- chronaxis/guide/fields/mapping/analysis-all-74.json +241 -0
- chronaxis/guide/fields/mapping/analysis-all-75.json +273 -0
- chronaxis/guide/fields/mapping/analysis-all-76.json +382 -0
- chronaxis/guide/fields/mapping/analysis-all-77.json +328 -0
- chronaxis/guide/fields/mapping/analysis-all-78.json +338 -0
- chronaxis/guide/fields/mapping/analysis-all-79.json +304 -0
- chronaxis/guide/fields/mapping/analysis-all-8.json +309 -0
- chronaxis/guide/fields/mapping/analysis-all-80.json +140 -0
- chronaxis/guide/fields/mapping/analysis-all-9.json +329 -0
- chronaxis/guide/fields/mapping/io_policy-all-1.json +19 -0
- chronaxis/guide/fields/mapping/mapping_version-all-1.json +19 -0
- chronaxis/guide/fields/mapping/path_base-all-1.json +19 -0
- chronaxis/guide/fields/mapping/sections-all-1.json +402 -0
- chronaxis/guide/fields/mapping/sections-all-2.json +232 -0
- chronaxis/guide/lookup.py +90 -0
- chronaxis/guide/manifest.json +614 -0
- chronaxis/guide/run_analysis.py +34 -0
- chronaxis/guide/schemas/analysis.schema.json +8451 -0
- chronaxis/guide/schemas/batch-v1.schema.json +172 -0
- chronaxis/guide/schemas/definitions.schema.json +29 -0
- chronaxis/guide/schemas/legacy-import-v1.schema.json +143 -0
- chronaxis/guide/semantics.md +62 -0
- chronaxis/guide/tasks.json +290 -0
- chronaxis/guide/workflow.md +38 -0
- chronaxis/legacy/__init__.py +46 -0
- chronaxis/legacy/batch_read.py +412 -0
- chronaxis/legacy/batch_validation.py +134 -0
- chronaxis/legacy/batch_wire.py +264 -0
- chronaxis/legacy/batch_worker.py +417 -0
- chronaxis/legacy/binding.py +154 -0
- chronaxis/legacy/dbc_cycles.py +47 -0
- chronaxis/legacy/decode_policy.py +28 -0
- chronaxis/legacy/disjunction.py +79 -0
- chronaxis/legacy/export_worker.py +147 -0
- chronaxis/legacy/export_write.py +378 -0
- chronaxis/legacy/message_store.py +562 -0
- chronaxis/legacy/process_read.py +526 -0
- chronaxis/legacy/raw_store.py +341 -0
- chronaxis/legacy/records.py +709 -0
- chronaxis/legacy/required_records.py +122 -0
- chronaxis/legacy/sum.py +403 -0
- chronaxis/legacy/sum_numpy.py +43 -0
- chronaxis/legacy/updates.py +277 -0
- chronaxis/legacy/vendor/sclicer_functions_v1/can_processor.py +138 -0
- chronaxis/legacy/vendor/sclicer_functions_v1/file_processor.py +218 -0
- chronaxis/legacy/vendor/sclicer_functions_v1/utils.py +447 -0
- chronaxis/legacy/worker.py +352 -0
- chronaxis/migration/__init__.py +11 -0
- chronaxis/migration/api.py +270 -0
- chronaxis/migration/ini.py +110 -0
- chronaxis/migration/legacy_sum.py +304 -0
- chronaxis/migration/models.py +83 -0
- chronaxis/migration/publication.py +230 -0
- chronaxis/migration/sclicer.py +241 -0
- chronaxis/migration/slope.py +78 -0
- chronaxis/migration/start_end.py +48 -0
- chronaxis/planning/__init__.py +19 -0
- chronaxis/planning/channels.py +30 -0
- chronaxis/planning/checks.py +447 -0
- chronaxis/planning/config_groups.py +215 -0
- chronaxis/planning/dbc_defaults.py +88 -0
- chronaxis/planning/export_options.py +247 -0
- chronaxis/planning/input_defaults.py +62 -0
- chronaxis/planning/input_paths.py +124 -0
- chronaxis/planning/input_requirements.py +250 -0
- chronaxis/planning/inputs.py +306 -0
- chronaxis/planning/intervals.py +242 -0
- chronaxis/planning/legacy_execution.py +38 -0
- chronaxis/planning/message_calculations.py +171 -0
- chronaxis/planning/models.py +369 -0
- chronaxis/planning/nodes.py +355 -0
- chronaxis/planning/plan.py +294 -0
- chronaxis/planning/preset_models.py +211 -0
- chronaxis/planning/record_execution.py +76 -0
- chronaxis/planning/reports.py +523 -0
- chronaxis/planning/sequences.py +91 -0
- chronaxis/planning/signal_groups.py +61 -0
- chronaxis/planning/signal_validity.py +46 -0
- chronaxis/planning/text_inputs.py +110 -0
- chronaxis/presets.py +270 -0
- chronaxis/results/__init__.py +34 -0
- chronaxis/results/analysis_outcome.py +67 -0
- chronaxis/results/artifact_exports.py +212 -0
- chronaxis/results/binding_metadata.py +54 -0
- chronaxis/results/budget.py +138 -0
- chronaxis/results/can_metadata.py +247 -0
- chronaxis/results/codec.py +246 -0
- chronaxis/results/errors.py +25 -0
- chronaxis/results/export_files.py +216 -0
- chronaxis/results/frame_exports.py +299 -0
- chronaxis/results/frame_patch.py +186 -0
- chronaxis/results/frame_rebuild.py +458 -0
- chronaxis/results/frame_sort.py +223 -0
- chronaxis/results/input_diagnostics.py +51 -0
- chronaxis/results/manifest.py +343 -0
- chronaxis/results/merge_runs.py +207 -0
- chronaxis/results/owned_directory.py +32 -0
- chronaxis/results/raw_exports.py +689 -0
- chronaxis/results/readable.py +355 -0
- chronaxis/results/readable_format.py +94 -0
- chronaxis/results/result.py +734 -0
- chronaxis/results/rows.py +57 -0
- chronaxis/results/signal_exports.py +209 -0
- chronaxis/results/signal_grid.py +219 -0
- chronaxis/results/spool.py +421 -0
- chronaxis/results/summary.py +350 -0
- chronaxis/results/text_can_metadata.py +64 -0
- chronaxis/results/threshold_metadata.py +105 -0
- chronaxis/runner.py +121 -0
- chronaxis/sources/__init__.py +23 -0
- chronaxis/sources/asc.py +412 -0
- chronaxis/sources/blf.py +101 -0
- chronaxis/sources/can_spec.py +179 -0
- chronaxis/sources/can_updates.py +160 -0
- chronaxis/sources/csv_spec.py +133 -0
- chronaxis/sources/descriptions.py +65 -0
- chronaxis/sources/memory.py +299 -0
- chronaxis/sources/models.py +497 -0
- chronaxis/sources/packing.py +170 -0
- chronaxis/sources/protocol.py +221 -0
- chronaxis/sources/raw_can.py +62 -0
- chronaxis/sources/raw_csv.py +470 -0
- chronaxis/sources/raw_csv_layout.py +310 -0
- chronaxis/sources/signal_csv.py +608 -0
- chronaxis/sources/text_can_decode.py +421 -0
- chronaxis/sources/text_can_ref.py +48 -0
- chronaxis/sources/text_can_spec.py +61 -0
- chronaxis/timebase/__init__.py +19 -0
- chronaxis/timebase/conversion.py +364 -0
- chronaxis/timebase/numpy_ops.py +104 -0
- chronaxis/user_guide.py +81 -0
- chronaxis-0.1.0.dev0.dist-info/METADATA +172 -0
- chronaxis-0.1.0.dev0.dist-info/RECORD +917 -0
- chronaxis-0.1.0.dev0.dist-info/WHEEL +5 -0
- chronaxis-0.1.0.dev0.dist-info/entry_points.txt +2 -0
- chronaxis-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
- chronaxis-0.1.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
"""检查JSON/YAML解析后的配置值,并在错误中保存具体字段位置。
|
|
2
|
+
|
|
3
|
+
输入为原生字典、列表、标量及JSON路径,输出合法原值、冻结元数据、
|
|
4
|
+
时间坐标或模型实例;错误统一关联为PlanValidationError。
|
|
5
|
+
字段和类型严格检查,不把True当整数,不忽略未知键或自动纠正数值。
|
|
6
|
+
时间必须声明单位或时区,路径只转为绝对定位,不检查文件内容或存在性。
|
|
7
|
+
本模块不读日志或DBC;地区时区解析可能读取系统时区数据库。
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# 精确配置时间与确定身份只依赖标准库。
|
|
11
|
+
import json
|
|
12
|
+
import re
|
|
13
|
+
from datetime import timedelta, timezone
|
|
14
|
+
from math import isfinite
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from collections.abc import Mapping
|
|
17
|
+
from zoneinfo import ZoneInfo
|
|
18
|
+
from difflib import get_close_matches
|
|
19
|
+
from ..configuration.diagnostics import child_path, value_preview
|
|
20
|
+
# 单位和安全名称校验沿用已验核心。
|
|
21
|
+
from ..core.validation import require_identifier, require_text
|
|
22
|
+
from ..sources.models import freeze_metadata
|
|
23
|
+
from ..timebase import convert_time, parse_duration, parse_datetime_ns
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class PlanValidationError(ValueError):
|
|
27
|
+
"""保存配置字段路径、原因、机器错误码及可选的原文定位和修正建议。
|
|
28
|
+
|
|
29
|
+
不吞执行异常或数据读取失败;code区分无效配置与未接线能力。
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, path: str, message: str, code: str = 'invalid_config', *, hint=None,
|
|
33
|
+
source=None, location=None, object_name=None, value=None):
|
|
34
|
+
"""建立明确路径错误,保留原异常链供load_analysis_plan诊断。
|
|
35
|
+
|
|
36
|
+
参数: path为原始字段路径;message为违反的约束;code默认invalid_config。
|
|
37
|
+
hint为修正说明,source/location为文件及行列,object_name为所属声明名称,
|
|
38
|
+
value为有长度限制的显示文本;均可省略,不保存整个原始配置。
|
|
39
|
+
返回: None;异常文本含路径和原因。
|
|
40
|
+
异常: 无;参数由校验器内部构造。
|
|
41
|
+
"""
|
|
42
|
+
# 文件路径独立保存在source;path始终指配置字段。
|
|
43
|
+
self.path = path
|
|
44
|
+
# 机器码不以错误文本模糊匹配。
|
|
45
|
+
self.code = code
|
|
46
|
+
# 字段路径与文件分开;只保存有限诊断,不持有加载文档。
|
|
47
|
+
self.message = message
|
|
48
|
+
self.hint=hint
|
|
49
|
+
self.source=source
|
|
50
|
+
self.location=location
|
|
51
|
+
self.object_name=object_name
|
|
52
|
+
self.value_preview=value
|
|
53
|
+
super().__init__()
|
|
54
|
+
self.refresh_text()
|
|
55
|
+
|
|
56
|
+
def refresh_text(self):
|
|
57
|
+
"""重建人读消息。参数: 无。返回: None。异常: 无;附加定位后调用。"""
|
|
58
|
+
place=self.source or ''
|
|
59
|
+
if self.location is not None:
|
|
60
|
+
place+=f':{self.location.line}:{self.location.column}(第{self.location.line}行,第{self.location.column}列)'
|
|
61
|
+
text=(place+' ' if place else '')+self.path+f' [{self.code}] '+self.message
|
|
62
|
+
if self.object_name is not None:
|
|
63
|
+
text+=';对象:'+self.object_name
|
|
64
|
+
if self.value_preview is not None:
|
|
65
|
+
text+=';当前值:'+self.value_preview
|
|
66
|
+
if self.hint is not None:
|
|
67
|
+
text+=';修正:'+self.hint
|
|
68
|
+
self.args=(text,)
|
|
69
|
+
|
|
70
|
+
def to_dict(self):
|
|
71
|
+
"""返回稳定机器诊断。参数: 无。返回: 原生dict。异常: 无。"""
|
|
72
|
+
return dict(code=self.code,source=self.source,path=self.path,message=self.message,
|
|
73
|
+
line=None if self.location is None else self.location.line,
|
|
74
|
+
column=None if self.location is None else self.location.column,
|
|
75
|
+
object_name=self.object_name,value=self.value_preview,hint=self.hint)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def configuration_error(error):
|
|
79
|
+
"""把共享语法错误交给计划API的异常类型。参数: ConfigurationError。返回: PlanValidationError。
|
|
80
|
+
|
|
81
|
+
维持文件路径与具体语法代码,文本补实际字段和可靠行列;不读取或重解析配置。
|
|
82
|
+
"""
|
|
83
|
+
from ..configuration import field_path_text
|
|
84
|
+
hints={'duplicate_key':'每个对象内的字段名只能声明一次;删除或重命名重复项',
|
|
85
|
+
'unsupported_yaml_feature':'使用普通映射、列表和标量;将公共值明确写入对应字段',
|
|
86
|
+
'nonfinite_number':'使用有限数值,不能用NaN或Infinity代表缺失数据',
|
|
87
|
+
'unsupported_format':'使用 .yaml、.yml 或 .json 文件',
|
|
88
|
+
'invalid_json':'检查引号、逗号和括号;JSON字符串和键必须用双引号',
|
|
89
|
+
'invalid_yaml':'检查缩进和冒号;缩进使用空格'}
|
|
90
|
+
return PlanValidationError(field_path_text(error.field_path),error.message,error.code,
|
|
91
|
+
source=error.source,location=error.location,hint=hints.get(error.code))
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def object_at(value, path: str, required=(), optional=()) -> dict:
|
|
95
|
+
"""检查JSON对象的类型、必填项和允许字段。
|
|
96
|
+
|
|
97
|
+
参数:
|
|
98
|
+
value: 待检查原值,必须是原生dict且全部键为字符串。
|
|
99
|
+
path (str): 当前配置位置。
|
|
100
|
+
required (tuple): 必填键,默认空元组。
|
|
101
|
+
optional (tuple): 可选键,默认空元组。
|
|
102
|
+
返回:
|
|
103
|
+
dict。原字典只在解析中读取,独立快照由计划入口另行创建。
|
|
104
|
+
异常:
|
|
105
|
+
PlanValidationError: 对象类型错误、缺少必填项或含未知键。
|
|
106
|
+
"""
|
|
107
|
+
# 不执行任意Mapping用户方法。
|
|
108
|
+
if type(value) is not dict or any(type(key) is not str for key in value):
|
|
109
|
+
# JSON对象键只能文本。
|
|
110
|
+
raise PlanValidationError(path, '必须为字符串键对象','invalid_type',hint='使用字段名: 值组成的对象')
|
|
111
|
+
# 未知键不静默忽略工程参数。
|
|
112
|
+
unknown = sorted(set(value) - set(required) - set(optional))
|
|
113
|
+
# 缺项不能用None隐式补齐。
|
|
114
|
+
missing = sorted(set(required) - set(value))
|
|
115
|
+
# 指向真实错误字段;仅提示候选名称,不改写用户输入。
|
|
116
|
+
if unknown:
|
|
117
|
+
key=unknown[0]
|
|
118
|
+
choices=get_close_matches(key,sorted(set(required)|set(optional)),n=1,cutoff=0.65)
|
|
119
|
+
hint=f'是否要写 {choices[0]}?请核对后修改字段名' if choices else '移除该字段;允许字段:'+', '.join((*required,*optional))
|
|
120
|
+
raise PlanValidationError(child_path(path,key),f'未知字段{unknown};缺少字段{missing}',
|
|
121
|
+
'unknown_field',hint=hint)
|
|
122
|
+
if missing:
|
|
123
|
+
key=missing[0]
|
|
124
|
+
raise PlanValidationError(child_path(path,key),f'缺少必填字段{missing}',
|
|
125
|
+
'missing_field',hint=f'在所属对象中补充 {key},值应来自实际输入或分析要求')
|
|
126
|
+
# 深复制由AnalysisPlan入口统一负责。
|
|
127
|
+
return value
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def array_at(value, path: str) -> list:
|
|
131
|
+
"""要求明确JSON数组,不把文本或tuple当自由迭代器。
|
|
132
|
+
|
|
133
|
+
参数: value原值;path位置。
|
|
134
|
+
返回: 原list,仅解析期间读取。
|
|
135
|
+
异常: PlanValidationError为类型错误。
|
|
136
|
+
"""
|
|
137
|
+
# from_dict也遵守JSON结构,与load_analysis_plan一致。
|
|
138
|
+
if type(value) is not list:
|
|
139
|
+
# 不接受集合的非确定顺序。
|
|
140
|
+
raise PlanValidationError(path, '必须为数组','invalid_type',hint='使用列表,例如 []')
|
|
141
|
+
# 顺序在后续tuple中保留。
|
|
142
|
+
return value
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def text_at(value, path: str, *, identifier=False) -> str:
|
|
146
|
+
"""检查非空文本或统一简单名称,保留原大小写。
|
|
147
|
+
|
|
148
|
+
参数: value原值;path位置;identifier是否安全标识符。
|
|
149
|
+
返回: 原str,不改点号字段或semantic字符串。
|
|
150
|
+
异常: PlanValidationError为类型/名称错误。
|
|
151
|
+
"""
|
|
152
|
+
# 核心校验不需要任何输入I/O。
|
|
153
|
+
try:
|
|
154
|
+
# 字段和标识符采用不同规则。
|
|
155
|
+
return require_identifier(value, path) if identifier else require_text(value, path)
|
|
156
|
+
# 核心异常只在配置边界增加位置。
|
|
157
|
+
except (TypeError, ValueError) as error:
|
|
158
|
+
# 保留原校验原因,不吞异常。
|
|
159
|
+
raise PlanValidationError(path, str(error)) from error
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def choice_at(value, choices: tuple, path: str):
|
|
163
|
+
"""要求显式支持的原生类型值,禁止bool等价整数。
|
|
164
|
+
|
|
165
|
+
参数: value原值;choices允许值tuple;path位置。
|
|
166
|
+
返回: 原值。
|
|
167
|
+
异常: PlanValidationError为未知值/类型。
|
|
168
|
+
"""
|
|
169
|
+
# True不能因==1成为config_version合法输入。
|
|
170
|
+
if not any(type(value) is type(item) and value == item for item in choices):
|
|
171
|
+
# 清楚列出真实支持版本/kind。
|
|
172
|
+
raise PlanValidationError(path, f'必须为{choices}','invalid_choice',
|
|
173
|
+
hint='使用允许值之一,例如 '+value_preview(choices[0]))
|
|
174
|
+
# 不自动升级版本或猜别名。
|
|
175
|
+
return value
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def number_at(value, path: str, *, integer=False, minimum=None, maximum=None):
|
|
179
|
+
"""检查有限原生数值及包含端点的范围,保留整数精度。
|
|
180
|
+
|
|
181
|
+
参数:
|
|
182
|
+
value: 原int或float数值,bool不被接受。
|
|
183
|
+
path (str): 当前配置位置。
|
|
184
|
+
integer (bool): 默认False;True时只接受原生int。
|
|
185
|
+
minimum: 可选包含式下限,默认None,不限制下端。
|
|
186
|
+
maximum: 可选包含式上限,默认None,不限制上端。
|
|
187
|
+
返回:
|
|
188
|
+
int或float。保持原类型和位值,不截断或转成浮点。
|
|
189
|
+
异常:
|
|
190
|
+
PlanValidationError: 类型错误、非有限浮点或超出范围。
|
|
191
|
+
"""
|
|
192
|
+
# bool不属于数值工程参数。
|
|
193
|
+
if type(value) not in ((int,) if integer else (int, float)) or type(value) is float and not isfinite(value):
|
|
194
|
+
# JSON非有限扩展不进入产品配置。
|
|
195
|
+
raise PlanValidationError(path, '必须为有限整数' if integer else '必须为有限数值','invalid_type')
|
|
196
|
+
# 明确边界不执行隐式截断。
|
|
197
|
+
if minimum is not None and value < minimum or maximum is not None and value > maximum:
|
|
198
|
+
# 覆盖率与资源限额不能默默纠正。
|
|
199
|
+
raise PlanValidationError(path, f'数值必须位于[{minimum}, {maximum}]','out_of_range')
|
|
200
|
+
# 保留整数精度与原生类型。
|
|
201
|
+
return value
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def duration_at(value, path: str, *, positive=False) -> int:
|
|
205
|
+
"""把带单位的非负持续时间转为整数纳秒。
|
|
206
|
+
|
|
207
|
+
参数:
|
|
208
|
+
value (str): 明确带时间单位的持续文本,不接受裸数。
|
|
209
|
+
path (str): 当前配置位置。
|
|
210
|
+
positive (bool): 默认False;True时要求纳秒量化后仍大于0。
|
|
211
|
+
返回:
|
|
212
|
+
int。符合int64范围的纳秒时长,允许零时长时返回0。
|
|
213
|
+
异常:
|
|
214
|
+
PlanValidationError: 语法、单位、范围错误,或正时长量化后为0。
|
|
215
|
+
"""
|
|
216
|
+
# 原负值在核心入口量化前拒绝。
|
|
217
|
+
try:
|
|
218
|
+
# 不允许裸数或隐式秒。
|
|
219
|
+
result = parse_duration(value).time_ns
|
|
220
|
+
# 将精确转换异常关联配置位置。
|
|
221
|
+
except (TypeError, ValueError, OverflowError) as error:
|
|
222
|
+
# 不修改语义以允许错误参数。
|
|
223
|
+
raise PlanValidationError(path, str(error),'invalid_duration',hint='使用带单位的非负时长,例如 "1s" 或 "500ms";按实际要求选择') from error
|
|
224
|
+
# 0.1ns舍入0不能冒充正TTL。
|
|
225
|
+
if positive and result <= 0:
|
|
226
|
+
# TTL和抑制窗口必须有正时长。
|
|
227
|
+
raise PlanValidationError(path, '持续量化后必须大于0ns','invalid_duration',hint='设置正时长,例如 "1s";按实际采样有效期选择')
|
|
228
|
+
# 全部后续时间计算保持整数。
|
|
229
|
+
return result
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def coordinate_at(value, path: str, *, absolute=False, tz=None) -> int:
|
|
233
|
+
"""解释带单位相对坐标或完整绝对日期,返回整数纳秒。
|
|
234
|
+
|
|
235
|
+
参数:
|
|
236
|
+
value (str): 相对数值加s、ms、us或ns单位,或完整绝对日期文本。
|
|
237
|
+
path (str): 当前配置位置。
|
|
238
|
+
absolute (bool): 默认False;True时按绝对日期解析。
|
|
239
|
+
tz (tzinfo | None): 默认None;绝对日期没有自身时区时使用此声明。
|
|
240
|
+
返回:
|
|
241
|
+
int。int64纳秒坐标;相对坐标允许负数,区别于非负持续时间。
|
|
242
|
+
异常:
|
|
243
|
+
PlanValidationError: 文本、单位、时区、日期或数值范围错误。
|
|
244
|
+
"""
|
|
245
|
+
# 完整文本保留精确十进制表达。
|
|
246
|
+
text_at(value, path)
|
|
247
|
+
# 核心日期不采用机器默认时区。
|
|
248
|
+
try:
|
|
249
|
+
# 绝对坐标明确完整日期,不猜文件名。
|
|
250
|
+
if absolute:
|
|
251
|
+
# 显式offset日期优先于配置tz。
|
|
252
|
+
return parse_datetime_ns(value, tz).time_ns
|
|
253
|
+
# 相对坐标语法允许负号,显式四种单位。
|
|
254
|
+
match = re.fullmatch(r'\s*([+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)\s*(ns|us|ms|s)\s*', value)
|
|
255
|
+
# 不接受单位缺失或尾部任意文本。
|
|
256
|
+
if match is None:
|
|
257
|
+
# 负坐标不同于持续参数的非负门槛。
|
|
258
|
+
raise ValueError('坐标须为数值+s/ms/us/ns')
|
|
259
|
+
# 精确转换不先经float。
|
|
260
|
+
return convert_time(match[1], match[2]).time_ns
|
|
261
|
+
# 配置边界保留原转换异常。
|
|
262
|
+
except (TypeError, ValueError, OverflowError) as error:
|
|
263
|
+
# 错误具体关联当前坐标键。
|
|
264
|
+
raise PlanValidationError(path, str(error)) from error
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def timezone_at(value, path: str):
|
|
268
|
+
"""解析显式UTC、固定offset或IANA名称,拒绝机器时区推断。
|
|
269
|
+
|
|
270
|
+
参数: value为None或非空文本;path位置。
|
|
271
|
+
返回: tzinfo或None,仅IANA可能读取系统时区数据库,不读数据输入。
|
|
272
|
+
异常: PlanValidationError为非法offset/未知时区或依赖缺失。
|
|
273
|
+
"""
|
|
274
|
+
# 无声明保留None,naive日期稍后必须报错。
|
|
275
|
+
if value is None:
|
|
276
|
+
# 不填机器当前地区。
|
|
277
|
+
return None
|
|
278
|
+
# 时区名称保留用户原文。
|
|
279
|
+
text_at(value, path)
|
|
280
|
+
# UTC常用表示不需外部时区文件。
|
|
281
|
+
if value in ('UTC', 'Z'):
|
|
282
|
+
# 固定零偏移明确UTC。
|
|
283
|
+
return timezone.utc
|
|
284
|
+
# 固定offset只接标准时分格式。
|
|
285
|
+
match = re.fullmatch(r'([+-])(\d{2}):(\d{2})', value)
|
|
286
|
+
# 验证分量,禁止datetime将+00:60自动归一化。
|
|
287
|
+
if match is not None:
|
|
288
|
+
# 各分量界限明确。
|
|
289
|
+
hours, minutes = int(match[2]), int(match[3])
|
|
290
|
+
# 偏移绝对值须小于24小时。
|
|
291
|
+
if hours > 23 or minutes > 59:
|
|
292
|
+
# 不接受非法offset自动变换。
|
|
293
|
+
raise PlanValidationError(path, '固定时区须小于24小时且分钟<60')
|
|
294
|
+
# 正负号只用于声明的固定偏移。
|
|
295
|
+
return timezone(timedelta(minutes=(hours * 60 + minutes) * (1 if match[1] == '+' else -1)))
|
|
296
|
+
# IANA解析可能缺本机tzdata,明确报告而非换机器默认。
|
|
297
|
+
try:
|
|
298
|
+
# 不读取日志/DBC,不凭地理位置猜时区。
|
|
299
|
+
return ZoneInfo(value)
|
|
300
|
+
# 环境缺项与未知名称都是配置可定位错误。
|
|
301
|
+
except (KeyError, ValueError) as error:
|
|
302
|
+
# 保留原依赖/名称异常供调用者修正。
|
|
303
|
+
raise PlanValidationError(path, f'时区不可用:{value}') from error
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def metadata_at(value, path: str):
|
|
307
|
+
"""深冻结唯一允许自由键的JSON元数据对象。
|
|
308
|
+
|
|
309
|
+
参数: value元数据dict;path位置。
|
|
310
|
+
返回: 深复制的只读Mapping/tuple,不影响调用者输入。
|
|
311
|
+
异常: PlanValidationError为非JSON/非有限/键类型错误。
|
|
312
|
+
"""
|
|
313
|
+
# 自由键也必须属于JSON对象。
|
|
314
|
+
if type(value) is not dict:
|
|
315
|
+
# 不把数组当metadata根。
|
|
316
|
+
raise PlanValidationError(path, 'metadata必须为对象')
|
|
317
|
+
# 模型递归校验JSON类型且不保留调用者引用。
|
|
318
|
+
try:
|
|
319
|
+
# 自定义键不改变产品执行语义。
|
|
320
|
+
return freeze_metadata(value)
|
|
321
|
+
# 只在配置边界增加当前位置。
|
|
322
|
+
except (TypeError, ValueError) as error:
|
|
323
|
+
# 元数据也不允许未知Python对象进入计划。
|
|
324
|
+
raise PlanValidationError(path, str(error)) from error
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def require_json_value(value, path: str, active=None) -> None:
|
|
328
|
+
"""在冻结之前检查原生JSON结构,并定位当前递归路径上的循环。
|
|
329
|
+
|
|
330
|
+
参数:
|
|
331
|
+
value: dict/list或原生str/int/float/bool/None,浮点必须有限。
|
|
332
|
+
path (str): 当前配置位置,递归时补字段名或数组下标。
|
|
333
|
+
active (set[int] | None): 当前祖先容器身份;根调用省略。
|
|
334
|
+
返回:
|
|
335
|
+
None,结构合法;不复制、转换或修改输入。
|
|
336
|
+
异常:
|
|
337
|
+
PlanValidationError: 非JSON对象、非文本对象键、非有限浮点或循环容器。
|
|
338
|
+
处理流程:
|
|
339
|
+
先区分原生容器与标量,逐层检查后由调用者冻结;共享但不循环的
|
|
340
|
+
容器允许重复出现。此检查不打开文件或执行任意Mapping方法。
|
|
341
|
+
"""
|
|
342
|
+
# 只允许JSON原生容器,避免tuple或自定义Mapping被通用冻结器归一化。
|
|
343
|
+
if type(value) not in (dict, list):
|
|
344
|
+
# bool与int都是合法JSON标量;未知对象不调用其转换方法。
|
|
345
|
+
if type(value) not in (str, int, float, bool, type(None)):
|
|
346
|
+
raise PlanValidationError(path, '必须为原生JSON对象、数组或标量')
|
|
347
|
+
# NaN/Infinity不能成为预算、配置元数据或正常数值声明。
|
|
348
|
+
if type(value) is float and not isfinite(value):
|
|
349
|
+
raise PlanValidationError(path, 'JSON浮点必须有限')
|
|
350
|
+
return
|
|
351
|
+
# 当前祖先集合区别于全局访问集合,共享容器不等同于循环。
|
|
352
|
+
ancestors = set() if active is None else active
|
|
353
|
+
identity = id(value)
|
|
354
|
+
if identity in ancestors:
|
|
355
|
+
# 自引用定位在引用发生处,不能泄漏通用冻结器的RecursionError。
|
|
356
|
+
raise PlanValidationError(path, 'JSON配置不能包含循环容器')
|
|
357
|
+
ancestors.add(identity)
|
|
358
|
+
try:
|
|
359
|
+
# 对象只接受字符串键;数组严格保持原顺序和下标。
|
|
360
|
+
if type(value) is dict:
|
|
361
|
+
for key, item in value.items():
|
|
362
|
+
if type(key) is not str:
|
|
363
|
+
raise PlanValidationError(path, 'JSON对象键必须为字符串')
|
|
364
|
+
require_json_value(item, child_path(path,key), ancestors)
|
|
365
|
+
else:
|
|
366
|
+
for index, item in enumerate(value):
|
|
367
|
+
require_json_value(item, f'{path}[{index}]', ancestors)
|
|
368
|
+
finally:
|
|
369
|
+
# 无论成功或失败都退出当前祖先路径,不污染其他分支的循环判定。
|
|
370
|
+
ancestors.remove(identity)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def json_value(value):
|
|
374
|
+
"""将已深冻结JSON快照转回可序列化新结构。
|
|
375
|
+
|
|
376
|
+
参数: value来自freeze_metadata的typed结构。
|
|
377
|
+
返回: 新dict/list或原不可变标量。
|
|
378
|
+
异常: 无;调用者保证已校验JSON类型。
|
|
379
|
+
"""
|
|
380
|
+
# 只读映射不能直接交给json.dumps。
|
|
381
|
+
if isinstance(value, Mapping):
|
|
382
|
+
# 重建新dict,保持原计划不可变。
|
|
383
|
+
return {key: json_value(item) for key, item in value.items()}
|
|
384
|
+
# tuple表示原JSON数组,顺序必须保留。
|
|
385
|
+
if type(value) is tuple:
|
|
386
|
+
# 不将路径顺序排序。
|
|
387
|
+
return [json_value(item) for item in value]
|
|
388
|
+
# 原生标量不可变,可直接复用。
|
|
389
|
+
return value
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def canonical(value) -> str:
|
|
393
|
+
"""生成JSON配置的确定身份文本,不读取文件内容。
|
|
394
|
+
|
|
395
|
+
参数: value已校验JSON结构或其深冻结快照。
|
|
396
|
+
返回: 规范JSON文本,字典排序、数组原序、整数精度保持。
|
|
397
|
+
异常: TypeError/ValueError为内部非JSON结构。
|
|
398
|
+
"""
|
|
399
|
+
# allow_nan=False拒绝非标准JSON,不以NaN身份混入配置。
|
|
400
|
+
return json.dumps(json_value(value), sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def absolute_path(value, base: Path, path: str) -> Path:
|
|
404
|
+
"""相对于明确基准解释路径,不打开目标或核实存在性。
|
|
405
|
+
|
|
406
|
+
参数:
|
|
407
|
+
value (str): 非空路径文本,不得含NUL字符。
|
|
408
|
+
base (Path): 相对路径的解释基准。
|
|
409
|
+
path (str): 此字段在配置中的错误定位。
|
|
410
|
+
返回:
|
|
411
|
+
Path。绝对定位路径,不解析实际符号链接或读取文件内容。
|
|
412
|
+
异常:
|
|
413
|
+
PlanValidationError: 路径文本非法或含NUL。
|
|
414
|
+
OSError: 获取当前目录或系统路径转换发生错误时可传播。
|
|
415
|
+
"""
|
|
416
|
+
# 路径不采用字符串对象隐式repr。
|
|
417
|
+
text_at(value, path)
|
|
418
|
+
# NUL会让未来文件读取不可用,提前具体拒绝。
|
|
419
|
+
if '\x00' in value:
|
|
420
|
+
# 保持配置错误与读文件失败分别诊断。
|
|
421
|
+
raise PlanValidationError(path, '路径含NUL')
|
|
422
|
+
# absolute只调用词法路径操作,不解析符号链接或读取输入。
|
|
423
|
+
return (base / value).absolute()
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def model_at(factory, path: str, *args, **kwargs):
|
|
427
|
+
"""用内部指定构造器创建模型,将校验错误关联到配置位置。
|
|
428
|
+
|
|
429
|
+
参数:
|
|
430
|
+
factory: 程序内部固定的模型构造器或校验函数,不来自配置反射。
|
|
431
|
+
path (str): 当前配置位置。
|
|
432
|
+
args: 已解析的位置参数。
|
|
433
|
+
kwargs: 已解析的关键字参数。
|
|
434
|
+
返回:
|
|
435
|
+
构造器的实际返回值,通常是已检查的模型实例。
|
|
436
|
+
异常:
|
|
437
|
+
PlanValidationError: 包装TypeError、ValueError、OverflowError或LookupError,
|
|
438
|
+
保留原异常链;其他异常原样传播。
|
|
439
|
+
"""
|
|
440
|
+
# 构造器来自内部代码,不执行配置指定对象或反射。
|
|
441
|
+
try:
|
|
442
|
+
# 原模型契约直接生效,不隐式修正参数。
|
|
443
|
+
return factory(*args, **kwargs)
|
|
444
|
+
# 只有配置模型校验错误转换为计划异常。
|
|
445
|
+
except (TypeError, ValueError, OverflowError, LookupError) as error:
|
|
446
|
+
# 原单位/时间/字段原因保持可查。
|
|
447
|
+
raise PlanValidationError(path, str(error)) from error
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""把当前配置的就地分组送入既有解析器,不改变时间或数值规则。
|
|
2
|
+
|
|
3
|
+
输入为JSON配置副本,输出独立副本。reader集中读取参数,conversion集中换算,
|
|
4
|
+
interval跟随实际消费者,scope对象明确引用规则或窗口。仅复制配置,不读输入、
|
|
5
|
+
不推断设备同步、不生成逐帧追溯。反向函数用于配置工具输出当前唯一公共形式。
|
|
6
|
+
"""
|
|
7
|
+
from copy import deepcopy
|
|
8
|
+
from functools import wraps
|
|
9
|
+
import re
|
|
10
|
+
from .checks import object_at, array_at, text_at, timezone_at, PlanValidationError
|
|
11
|
+
|
|
12
|
+
CONVERSION = ('input_unit', 'scale', 'offset')
|
|
13
|
+
READER_FLAT = ('encoding', 'delimiter', 'missing_values', 'decode_scope', 'input_check')
|
|
14
|
+
NODES = ('rules', 'windows', 'calculations', 'sequences')
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def public_errors(function):
|
|
18
|
+
"""将内部字段错误还原到用户声明位置。参数: 计划构建方法。返回: 包装方法。异常: 原PlanValidationError。
|
|
19
|
+
|
|
20
|
+
不改变错误代码和原因,不读取或保存输入;结构阶段对旧名的拒绝保留旧名位置。
|
|
21
|
+
"""
|
|
22
|
+
@wraps(function)
|
|
23
|
+
def checked(cls, config, *args, **kwargs):
|
|
24
|
+
"""调用原解析器,仅在错误退出时修正已归组字段的路径。"""
|
|
25
|
+
try:
|
|
26
|
+
return function(cls, config, *args, **kwargs)
|
|
27
|
+
except PlanValidationError as error:
|
|
28
|
+
if error.code == 'unknown_field' or type(config) is not dict:
|
|
29
|
+
raise
|
|
30
|
+
path = error.path
|
|
31
|
+
path = re.sub(r'(\$\.sources\[\d+\])\.(?:parser|reader_options)(?=\.|$)', r'\1.reader', path)
|
|
32
|
+
path = re.sub(r'(\$\.sources\[\d+\])\.(encoding|delimiter|missing_values|decode_scope|input_check)(?=\.|$)', r'\1.reader.\2', path)
|
|
33
|
+
path = re.sub(r'(\$\.signals\[\d+\](?:\.signals\[\d+\])?)\.(input_unit|scale|offset)(?=\.|$)', r'\1.conversion.\2', path)
|
|
34
|
+
path = re.sub(r'(\.time)\.origin(?=\.|$)', r'\1.clock', path)
|
|
35
|
+
path = re.sub(r'(\.resampling)\.origin(?=\.|$)', r'\1.start', path)
|
|
36
|
+
path = path.replace('$.outputs.can_frames.timezone_offset_minutes', '$.outputs.can_frames.timezone')
|
|
37
|
+
path = re.sub(r'(\$\.outputs\.(?:can_frames|signal_csv))\.window(?=\.|$)', r'\1.scope.window', path)
|
|
38
|
+
match = re.match(r'^\$\.intervals\.overrides\.([^\.]+)(.*)$', path)
|
|
39
|
+
if match:
|
|
40
|
+
for section in NODES:
|
|
41
|
+
nodes = config.get(section, [])
|
|
42
|
+
if type(nodes) is not list: continue
|
|
43
|
+
for index, node in enumerate(nodes):
|
|
44
|
+
if type(node) is dict and node.get('name') == match[1] and 'interval' in node:
|
|
45
|
+
path = f'$.{section}[{index}].interval' + match[2]
|
|
46
|
+
error.path = path
|
|
47
|
+
error.refresh_text()
|
|
48
|
+
raise
|
|
49
|
+
return checked
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _leaves(signals, path='$.signals'):
|
|
53
|
+
"""遍历叶信号及声明路径。参数: 数组。返回: (dict,path)。异常: 错误数组/对象。"""
|
|
54
|
+
for index, item in enumerate(array_at(signals, path)):
|
|
55
|
+
child_path = f'{path}[{index}]'
|
|
56
|
+
if type(item) is not dict:
|
|
57
|
+
raise PlanValidationError(child_path, '信号声明必须为对象')
|
|
58
|
+
if 'signals' in item:
|
|
59
|
+
yield from _leaves(item['signals'], child_path + '.signals')
|
|
60
|
+
else:
|
|
61
|
+
yield item, child_path
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def normalize_configuration(config):
|
|
65
|
+
"""解析当前公共分组。参数: 已验证JSON字典。返回: 独立内部字典。异常: 公共结构错误。
|
|
66
|
+
|
|
67
|
+
只接受当前拼写,旧扁平参数明确拒绝;内部parser/reader_options等仅供既有
|
|
68
|
+
解析器消费,不作为第二套用户配置入口。调用应在预设展开之前。
|
|
69
|
+
"""
|
|
70
|
+
root = deepcopy(config)
|
|
71
|
+
for index, source in enumerate(array_at(root['sources'], '$.sources')):
|
|
72
|
+
path = f'$.sources[{index}]'
|
|
73
|
+
if type(source) is not dict:
|
|
74
|
+
raise PlanValidationError(path, '来源必须为对象')
|
|
75
|
+
for key in ('parser', 'reader_options', *READER_FLAT):
|
|
76
|
+
if key in source:
|
|
77
|
+
raise PlanValidationError(path + '.' + key, '读取参数请放在reader对象内', 'unknown_field')
|
|
78
|
+
if 'reader' in source:
|
|
79
|
+
reader = dict(object_at(source.pop('reader'), path + '.reader', (),
|
|
80
|
+
(*READER_FLAT, 'decode_policy', 'version', 'layout', 'time_format', 'id_base',
|
|
81
|
+
'length_base', 'channel_origin', 'payload_style', 'rollover_min_drop')))
|
|
82
|
+
# 信号表读取参数和CAN解码参数分别交给各自的原校验器。
|
|
83
|
+
for key in ('decode_scope', 'input_check'):
|
|
84
|
+
if key in reader: source[key] = reader.pop(key)
|
|
85
|
+
if 'decode_policy' in reader:
|
|
86
|
+
source['reader_options'] = {'decode_policy': reader.pop('decode_policy')}
|
|
87
|
+
if source.get('source_type') == 'signal_csv':
|
|
88
|
+
source.update(reader)
|
|
89
|
+
elif reader:
|
|
90
|
+
source['parser'] = reader
|
|
91
|
+
clock = source.get('time')
|
|
92
|
+
if type(clock) is dict and 'origin' in clock:
|
|
93
|
+
raise PlanValidationError(path + '.time.origin', '来源时间基准名称请使用clock', 'unknown_field')
|
|
94
|
+
if type(clock) is dict and 'clock' in clock:
|
|
95
|
+
clock['origin'] = clock.pop('clock')
|
|
96
|
+
if type(clock) is dict and 'timezone_offset_minutes' in clock:
|
|
97
|
+
raise PlanValidationError(path + '.time.timezone_offset_minutes',
|
|
98
|
+
'时区统一使用timezone,例如+08:00', 'unknown_field')
|
|
99
|
+
for signal, path in _leaves(root['signals']):
|
|
100
|
+
for key in CONVERSION:
|
|
101
|
+
if key in signal:
|
|
102
|
+
raise PlanValidationError(path + '.' + key, '信号换算请放在conversion对象内', 'unknown_field')
|
|
103
|
+
if 'conversion' in signal:
|
|
104
|
+
signal.update(object_at(signal.pop('conversion'), path + '.conversion', (), CONVERSION))
|
|
105
|
+
intervals = dict(object_at(root.get('intervals', {}), '$.intervals', (), ('default',)))
|
|
106
|
+
overrides = {}
|
|
107
|
+
for section in NODES:
|
|
108
|
+
for index, node in enumerate(array_at(root.get(section, []), '$.' + section)):
|
|
109
|
+
path = f'$.{section}[{index}]'
|
|
110
|
+
if type(node) is not dict:
|
|
111
|
+
raise PlanValidationError(path, '节点必须为对象')
|
|
112
|
+
if 'interval' in node:
|
|
113
|
+
name = text_at(node.get('name'), path + '.name', identifier=True)
|
|
114
|
+
if name in overrides:
|
|
115
|
+
raise PlanValidationError(path + '.name', '间隔消费者名称重复')
|
|
116
|
+
# 原间隔解析器随后检查模式、驱动、正周期和消费者是否适用。
|
|
117
|
+
overrides[name] = node.pop('interval')
|
|
118
|
+
if section == 'calculations' and 'scope' in node:
|
|
119
|
+
scope = node['scope']
|
|
120
|
+
if scope == 'session':
|
|
121
|
+
continue
|
|
122
|
+
scope = object_at(scope, path + '.scope', (), ('rule', 'window'))
|
|
123
|
+
if len(scope) != 1:
|
|
124
|
+
raise PlanValidationError(path + '.scope', 'scope需要且只能引用一个rule或window')
|
|
125
|
+
key = next(iter(scope))
|
|
126
|
+
target = text_at(scope[key], path + '.scope.' + key, identifier=True)
|
|
127
|
+
node['scope'] = ('event:' if key == 'rule' else 'segment:') + target
|
|
128
|
+
if overrides: intervals['overrides'] = overrides
|
|
129
|
+
if intervals or 'intervals' in root: root['intervals'] = intervals
|
|
130
|
+
for kind in ('signal_csv', 'can_frames'):
|
|
131
|
+
outputs = root.get('outputs', {})
|
|
132
|
+
output = outputs.get(kind) if type(outputs) is dict else None
|
|
133
|
+
if type(output) is not dict: continue
|
|
134
|
+
path = '$.outputs.' + kind
|
|
135
|
+
if kind == 'can_frames':
|
|
136
|
+
if 'timezone_offset_minutes' in output:
|
|
137
|
+
raise PlanValidationError(path + '.timezone_offset_minutes', '时区请使用timezone,例如+08:00', 'unknown_field')
|
|
138
|
+
if 'timezone' in output:
|
|
139
|
+
zone = timezone_at(output.pop('timezone'), path + '.timezone')
|
|
140
|
+
offset = None if zone is None else zone.utcoffset(None)
|
|
141
|
+
if zone is not None and offset is None:
|
|
142
|
+
raise PlanValidationError(path + '.timezone', '原帧导出需要UTC或固定时区,例如+08:00')
|
|
143
|
+
output['timezone_offset_minutes'] = None if offset is None else int(offset.total_seconds() // 60)
|
|
144
|
+
grid = output.get('resampling')
|
|
145
|
+
if type(grid) is dict:
|
|
146
|
+
if 'origin' in grid:
|
|
147
|
+
raise PlanValidationError(path + '.resampling.origin', '采样网格起点请使用start', 'unknown_field')
|
|
148
|
+
if 'start' in grid: grid['origin'] = grid.pop('start')
|
|
149
|
+
if 'window' in output:
|
|
150
|
+
raise PlanValidationError(path + '.window', '窗口引用请写scope: {window: 名称}', 'unknown_field')
|
|
151
|
+
scope = output.get('scope', 'session')
|
|
152
|
+
if scope == 'session': continue
|
|
153
|
+
scope = object_at(scope, path + '.scope', (), ('window', 'windows'))
|
|
154
|
+
if len(scope) != 1:
|
|
155
|
+
raise PlanValidationError(path + '.scope', '导出scope需要一个window引用或windows: all')
|
|
156
|
+
output['scope'] = 'segments'
|
|
157
|
+
if 'window' in scope:
|
|
158
|
+
output['window'] = text_at(scope['window'], path + '.scope.window', identifier=True)
|
|
159
|
+
elif kind != 'can_frames' or scope['windows'] != 'all':
|
|
160
|
+
raise PlanValidationError(path + '.scope.windows', '仅原帧导出支持windows: all')
|
|
161
|
+
return root
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def public_configuration(config):
|
|
165
|
+
"""把生成器内部结构转成当前公共配置。参数: 配置字典。返回: 独立字典。异常: 结构错误。
|
|
166
|
+
|
|
167
|
+
不读取文件,不改变自由metadata或业务值;已使用新分组的内容原样保留。
|
|
168
|
+
用于预设展开、INI导入和resolve,不能用作接受旧用户配置的兼容入口。
|
|
169
|
+
"""
|
|
170
|
+
root = deepcopy(config)
|
|
171
|
+
for source in root.get('sources', []):
|
|
172
|
+
reader = dict(source.get('reader', {}))
|
|
173
|
+
for key in ('parser', 'reader_options'):
|
|
174
|
+
reader.update(source.pop(key, {}))
|
|
175
|
+
for key in READER_FLAT:
|
|
176
|
+
if key in source: reader[key] = source.pop(key)
|
|
177
|
+
if reader: source['reader'] = reader
|
|
178
|
+
clock = source.get('time', {})
|
|
179
|
+
if 'origin' in clock: clock['clock'] = clock.pop('origin')
|
|
180
|
+
if 'timezone_offset_minutes' in clock:
|
|
181
|
+
minutes = clock.pop('timezone_offset_minutes')
|
|
182
|
+
if type(minutes) is not int or not -1439 <= minutes <= 1439:
|
|
183
|
+
raise PlanValidationError('$.sources.time.timezone', '固定时区分钟数无效')
|
|
184
|
+
clock['timezone'] = ('+' if minutes >= 0 else '-') + f'{abs(minutes)//60:02}:{abs(minutes)%60:02}'
|
|
185
|
+
for signal, _ in _leaves(root.get('signals', [])):
|
|
186
|
+
conversion = dict(signal.get('conversion', {}))
|
|
187
|
+
for key in CONVERSION:
|
|
188
|
+
if key in signal: conversion[key] = signal.pop(key)
|
|
189
|
+
if conversion: signal['conversion'] = conversion
|
|
190
|
+
intervals = root.get('intervals', {})
|
|
191
|
+
overrides = intervals.pop('overrides', {}) if type(intervals) is dict else {}
|
|
192
|
+
for section in NODES:
|
|
193
|
+
for node in root.get(section, []):
|
|
194
|
+
if node.get('name') in overrides:
|
|
195
|
+
node['interval'] = overrides.pop(node['name'])
|
|
196
|
+
scope = node.get('scope')
|
|
197
|
+
if section == 'calculations' and type(scope) is str and ':' in scope:
|
|
198
|
+
kind, target = scope.split(':', 1)
|
|
199
|
+
if kind in ('event', 'segment'):
|
|
200
|
+
node['scope'] = {'rule' if kind == 'event' else 'window': target}
|
|
201
|
+
# 无对应节点不能丢弃声明,让原错误继续可见而不是静默删配置。
|
|
202
|
+
if overrides: intervals['overrides'] = overrides
|
|
203
|
+
for kind in ('signal_csv', 'can_frames'):
|
|
204
|
+
outputs = root.get('outputs', {})
|
|
205
|
+
output = outputs.get(kind) if type(outputs) is dict else None
|
|
206
|
+
if type(output) is not dict: continue
|
|
207
|
+
if kind == 'can_frames' and 'timezone_offset_minutes' in output:
|
|
208
|
+
minutes = output.pop('timezone_offset_minutes')
|
|
209
|
+
output['timezone'] = None if minutes is None else ('+' if minutes >= 0 else '-') + f'{abs(minutes)//60:02}:{abs(minutes)%60:02}'
|
|
210
|
+
grid = output.get('resampling')
|
|
211
|
+
if type(grid) is dict and 'origin' in grid: grid['start'] = grid.pop('origin')
|
|
212
|
+
if output.get('scope') != 'segments': continue
|
|
213
|
+
window = output.pop('window', None)
|
|
214
|
+
output['scope'] = {'windows': 'all'} if window is None else {'window': window}
|
|
215
|
+
return root
|