oscura 0.0.1__py3-none-any.whl → 0.1.0__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.
- oscura/__init__.py +813 -8
- oscura/__main__.py +392 -0
- oscura/analyzers/__init__.py +37 -0
- oscura/analyzers/digital/__init__.py +177 -0
- oscura/analyzers/digital/bus.py +691 -0
- oscura/analyzers/digital/clock.py +805 -0
- oscura/analyzers/digital/correlation.py +720 -0
- oscura/analyzers/digital/edges.py +632 -0
- oscura/analyzers/digital/extraction.py +413 -0
- oscura/analyzers/digital/quality.py +878 -0
- oscura/analyzers/digital/signal_quality.py +877 -0
- oscura/analyzers/digital/thresholds.py +708 -0
- oscura/analyzers/digital/timing.py +1104 -0
- oscura/analyzers/eye/__init__.py +46 -0
- oscura/analyzers/eye/diagram.py +434 -0
- oscura/analyzers/eye/metrics.py +555 -0
- oscura/analyzers/jitter/__init__.py +83 -0
- oscura/analyzers/jitter/ber.py +333 -0
- oscura/analyzers/jitter/decomposition.py +759 -0
- oscura/analyzers/jitter/measurements.py +413 -0
- oscura/analyzers/jitter/spectrum.py +220 -0
- oscura/analyzers/measurements.py +40 -0
- oscura/analyzers/packet/__init__.py +171 -0
- oscura/analyzers/packet/daq.py +1077 -0
- oscura/analyzers/packet/metrics.py +437 -0
- oscura/analyzers/packet/parser.py +327 -0
- oscura/analyzers/packet/payload.py +2156 -0
- oscura/analyzers/packet/payload_analysis.py +1312 -0
- oscura/analyzers/packet/payload_extraction.py +236 -0
- oscura/analyzers/packet/payload_patterns.py +670 -0
- oscura/analyzers/packet/stream.py +359 -0
- oscura/analyzers/patterns/__init__.py +266 -0
- oscura/analyzers/patterns/clustering.py +1036 -0
- oscura/analyzers/patterns/discovery.py +539 -0
- oscura/analyzers/patterns/learning.py +797 -0
- oscura/analyzers/patterns/matching.py +1091 -0
- oscura/analyzers/patterns/periodic.py +650 -0
- oscura/analyzers/patterns/sequences.py +767 -0
- oscura/analyzers/power/__init__.py +116 -0
- oscura/analyzers/power/ac_power.py +391 -0
- oscura/analyzers/power/basic.py +383 -0
- oscura/analyzers/power/conduction.py +314 -0
- oscura/analyzers/power/efficiency.py +297 -0
- oscura/analyzers/power/ripple.py +356 -0
- oscura/analyzers/power/soa.py +372 -0
- oscura/analyzers/power/switching.py +479 -0
- oscura/analyzers/protocol/__init__.py +150 -0
- oscura/analyzers/protocols/__init__.py +150 -0
- oscura/analyzers/protocols/base.py +500 -0
- oscura/analyzers/protocols/can.py +620 -0
- oscura/analyzers/protocols/can_fd.py +448 -0
- oscura/analyzers/protocols/flexray.py +405 -0
- oscura/analyzers/protocols/hdlc.py +399 -0
- oscura/analyzers/protocols/i2c.py +368 -0
- oscura/analyzers/protocols/i2s.py +296 -0
- oscura/analyzers/protocols/jtag.py +393 -0
- oscura/analyzers/protocols/lin.py +445 -0
- oscura/analyzers/protocols/manchester.py +333 -0
- oscura/analyzers/protocols/onewire.py +501 -0
- oscura/analyzers/protocols/spi.py +334 -0
- oscura/analyzers/protocols/swd.py +325 -0
- oscura/analyzers/protocols/uart.py +393 -0
- oscura/analyzers/protocols/usb.py +495 -0
- oscura/analyzers/signal_integrity/__init__.py +63 -0
- oscura/analyzers/signal_integrity/embedding.py +294 -0
- oscura/analyzers/signal_integrity/equalization.py +370 -0
- oscura/analyzers/signal_integrity/sparams.py +484 -0
- oscura/analyzers/spectral/__init__.py +53 -0
- oscura/analyzers/spectral/chunked.py +273 -0
- oscura/analyzers/spectral/chunked_fft.py +571 -0
- oscura/analyzers/spectral/chunked_wavelet.py +391 -0
- oscura/analyzers/spectral/fft.py +92 -0
- oscura/analyzers/statistical/__init__.py +250 -0
- oscura/analyzers/statistical/checksum.py +923 -0
- oscura/analyzers/statistical/chunked_corr.py +228 -0
- oscura/analyzers/statistical/classification.py +778 -0
- oscura/analyzers/statistical/entropy.py +1113 -0
- oscura/analyzers/statistical/ngrams.py +614 -0
- oscura/analyzers/statistics/__init__.py +119 -0
- oscura/analyzers/statistics/advanced.py +885 -0
- oscura/analyzers/statistics/basic.py +263 -0
- oscura/analyzers/statistics/correlation.py +630 -0
- oscura/analyzers/statistics/distribution.py +298 -0
- oscura/analyzers/statistics/outliers.py +463 -0
- oscura/analyzers/statistics/streaming.py +93 -0
- oscura/analyzers/statistics/trend.py +520 -0
- oscura/analyzers/validation.py +598 -0
- oscura/analyzers/waveform/__init__.py +36 -0
- oscura/analyzers/waveform/measurements.py +943 -0
- oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
- oscura/analyzers/waveform/spectral.py +1689 -0
- oscura/analyzers/waveform/wavelets.py +298 -0
- oscura/api/__init__.py +62 -0
- oscura/api/dsl.py +538 -0
- oscura/api/fluent.py +571 -0
- oscura/api/operators.py +498 -0
- oscura/api/optimization.py +392 -0
- oscura/api/profiling.py +396 -0
- oscura/automotive/__init__.py +73 -0
- oscura/automotive/can/__init__.py +52 -0
- oscura/automotive/can/analysis.py +356 -0
- oscura/automotive/can/checksum.py +250 -0
- oscura/automotive/can/correlation.py +212 -0
- oscura/automotive/can/discovery.py +355 -0
- oscura/automotive/can/message_wrapper.py +375 -0
- oscura/automotive/can/models.py +385 -0
- oscura/automotive/can/patterns.py +381 -0
- oscura/automotive/can/session.py +452 -0
- oscura/automotive/can/state_machine.py +300 -0
- oscura/automotive/can/stimulus_response.py +461 -0
- oscura/automotive/dbc/__init__.py +15 -0
- oscura/automotive/dbc/generator.py +156 -0
- oscura/automotive/dbc/parser.py +146 -0
- oscura/automotive/dtc/__init__.py +30 -0
- oscura/automotive/dtc/database.py +3036 -0
- oscura/automotive/j1939/__init__.py +14 -0
- oscura/automotive/j1939/decoder.py +745 -0
- oscura/automotive/loaders/__init__.py +35 -0
- oscura/automotive/loaders/asc.py +98 -0
- oscura/automotive/loaders/blf.py +77 -0
- oscura/automotive/loaders/csv_can.py +136 -0
- oscura/automotive/loaders/dispatcher.py +136 -0
- oscura/automotive/loaders/mdf.py +331 -0
- oscura/automotive/loaders/pcap.py +132 -0
- oscura/automotive/obd/__init__.py +14 -0
- oscura/automotive/obd/decoder.py +707 -0
- oscura/automotive/uds/__init__.py +48 -0
- oscura/automotive/uds/decoder.py +265 -0
- oscura/automotive/uds/models.py +64 -0
- oscura/automotive/visualization.py +369 -0
- oscura/batch/__init__.py +55 -0
- oscura/batch/advanced.py +627 -0
- oscura/batch/aggregate.py +300 -0
- oscura/batch/analyze.py +139 -0
- oscura/batch/logging.py +487 -0
- oscura/batch/metrics.py +556 -0
- oscura/builders/__init__.py +41 -0
- oscura/builders/signal_builder.py +1131 -0
- oscura/cli/__init__.py +14 -0
- oscura/cli/batch.py +339 -0
- oscura/cli/characterize.py +273 -0
- oscura/cli/compare.py +775 -0
- oscura/cli/decode.py +551 -0
- oscura/cli/main.py +247 -0
- oscura/cli/shell.py +350 -0
- oscura/comparison/__init__.py +66 -0
- oscura/comparison/compare.py +397 -0
- oscura/comparison/golden.py +487 -0
- oscura/comparison/limits.py +391 -0
- oscura/comparison/mask.py +434 -0
- oscura/comparison/trace_diff.py +30 -0
- oscura/comparison/visualization.py +481 -0
- oscura/compliance/__init__.py +70 -0
- oscura/compliance/advanced.py +756 -0
- oscura/compliance/masks.py +363 -0
- oscura/compliance/reporting.py +483 -0
- oscura/compliance/testing.py +298 -0
- oscura/component/__init__.py +38 -0
- oscura/component/impedance.py +365 -0
- oscura/component/reactive.py +598 -0
- oscura/component/transmission_line.py +312 -0
- oscura/config/__init__.py +191 -0
- oscura/config/defaults.py +254 -0
- oscura/config/loader.py +348 -0
- oscura/config/memory.py +271 -0
- oscura/config/migration.py +458 -0
- oscura/config/pipeline.py +1077 -0
- oscura/config/preferences.py +530 -0
- oscura/config/protocol.py +875 -0
- oscura/config/schema.py +713 -0
- oscura/config/settings.py +420 -0
- oscura/config/thresholds.py +599 -0
- oscura/convenience.py +457 -0
- oscura/core/__init__.py +299 -0
- oscura/core/audit.py +457 -0
- oscura/core/backend_selector.py +405 -0
- oscura/core/cache.py +590 -0
- oscura/core/cancellation.py +439 -0
- oscura/core/confidence.py +225 -0
- oscura/core/config.py +506 -0
- oscura/core/correlation.py +216 -0
- oscura/core/cross_domain.py +422 -0
- oscura/core/debug.py +301 -0
- oscura/core/edge_cases.py +541 -0
- oscura/core/exceptions.py +535 -0
- oscura/core/gpu_backend.py +523 -0
- oscura/core/lazy.py +832 -0
- oscura/core/log_query.py +540 -0
- oscura/core/logging.py +931 -0
- oscura/core/logging_advanced.py +952 -0
- oscura/core/memoize.py +171 -0
- oscura/core/memory_check.py +274 -0
- oscura/core/memory_guard.py +290 -0
- oscura/core/memory_limits.py +336 -0
- oscura/core/memory_monitor.py +453 -0
- oscura/core/memory_progress.py +465 -0
- oscura/core/memory_warnings.py +315 -0
- oscura/core/numba_backend.py +362 -0
- oscura/core/performance.py +352 -0
- oscura/core/progress.py +524 -0
- oscura/core/provenance.py +358 -0
- oscura/core/results.py +331 -0
- oscura/core/types.py +504 -0
- oscura/core/uncertainty.py +383 -0
- oscura/discovery/__init__.py +52 -0
- oscura/discovery/anomaly_detector.py +672 -0
- oscura/discovery/auto_decoder.py +415 -0
- oscura/discovery/comparison.py +497 -0
- oscura/discovery/quality_validator.py +528 -0
- oscura/discovery/signal_detector.py +769 -0
- oscura/dsl/__init__.py +73 -0
- oscura/dsl/commands.py +246 -0
- oscura/dsl/interpreter.py +455 -0
- oscura/dsl/parser.py +689 -0
- oscura/dsl/repl.py +172 -0
- oscura/exceptions.py +59 -0
- oscura/exploratory/__init__.py +111 -0
- oscura/exploratory/error_recovery.py +642 -0
- oscura/exploratory/fuzzy.py +513 -0
- oscura/exploratory/fuzzy_advanced.py +786 -0
- oscura/exploratory/legacy.py +831 -0
- oscura/exploratory/parse.py +358 -0
- oscura/exploratory/recovery.py +275 -0
- oscura/exploratory/sync.py +382 -0
- oscura/exploratory/unknown.py +707 -0
- oscura/export/__init__.py +25 -0
- oscura/export/wireshark/README.md +265 -0
- oscura/export/wireshark/__init__.py +47 -0
- oscura/export/wireshark/generator.py +312 -0
- oscura/export/wireshark/lua_builder.py +159 -0
- oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
- oscura/export/wireshark/type_mapping.py +165 -0
- oscura/export/wireshark/validator.py +105 -0
- oscura/exporters/__init__.py +94 -0
- oscura/exporters/csv.py +303 -0
- oscura/exporters/exporters.py +44 -0
- oscura/exporters/hdf5.py +219 -0
- oscura/exporters/html_export.py +701 -0
- oscura/exporters/json_export.py +291 -0
- oscura/exporters/markdown_export.py +367 -0
- oscura/exporters/matlab_export.py +354 -0
- oscura/exporters/npz_export.py +219 -0
- oscura/exporters/spice_export.py +210 -0
- oscura/extensibility/__init__.py +131 -0
- oscura/extensibility/docs.py +752 -0
- oscura/extensibility/extensions.py +1125 -0
- oscura/extensibility/logging.py +259 -0
- oscura/extensibility/measurements.py +485 -0
- oscura/extensibility/plugins.py +414 -0
- oscura/extensibility/registry.py +346 -0
- oscura/extensibility/templates.py +913 -0
- oscura/extensibility/validation.py +651 -0
- oscura/filtering/__init__.py +89 -0
- oscura/filtering/base.py +563 -0
- oscura/filtering/convenience.py +564 -0
- oscura/filtering/design.py +725 -0
- oscura/filtering/filters.py +32 -0
- oscura/filtering/introspection.py +605 -0
- oscura/guidance/__init__.py +24 -0
- oscura/guidance/recommender.py +429 -0
- oscura/guidance/wizard.py +518 -0
- oscura/inference/__init__.py +251 -0
- oscura/inference/active_learning/README.md +153 -0
- oscura/inference/active_learning/__init__.py +38 -0
- oscura/inference/active_learning/lstar.py +257 -0
- oscura/inference/active_learning/observation_table.py +230 -0
- oscura/inference/active_learning/oracle.py +78 -0
- oscura/inference/active_learning/teachers/__init__.py +15 -0
- oscura/inference/active_learning/teachers/simulator.py +192 -0
- oscura/inference/adaptive_tuning.py +453 -0
- oscura/inference/alignment.py +653 -0
- oscura/inference/bayesian.py +943 -0
- oscura/inference/binary.py +1016 -0
- oscura/inference/crc_reverse.py +711 -0
- oscura/inference/logic.py +288 -0
- oscura/inference/message_format.py +1305 -0
- oscura/inference/protocol.py +417 -0
- oscura/inference/protocol_dsl.py +1084 -0
- oscura/inference/protocol_library.py +1230 -0
- oscura/inference/sequences.py +809 -0
- oscura/inference/signal_intelligence.py +1509 -0
- oscura/inference/spectral.py +215 -0
- oscura/inference/state_machine.py +634 -0
- oscura/inference/stream.py +918 -0
- oscura/integrations/__init__.py +59 -0
- oscura/integrations/llm.py +1827 -0
- oscura/jupyter/__init__.py +32 -0
- oscura/jupyter/display.py +268 -0
- oscura/jupyter/magic.py +334 -0
- oscura/loaders/__init__.py +526 -0
- oscura/loaders/binary.py +69 -0
- oscura/loaders/configurable.py +1255 -0
- oscura/loaders/csv.py +26 -0
- oscura/loaders/csv_loader.py +473 -0
- oscura/loaders/hdf5.py +9 -0
- oscura/loaders/hdf5_loader.py +510 -0
- oscura/loaders/lazy.py +370 -0
- oscura/loaders/mmap_loader.py +583 -0
- oscura/loaders/numpy_loader.py +436 -0
- oscura/loaders/pcap.py +432 -0
- oscura/loaders/preprocessing.py +368 -0
- oscura/loaders/rigol.py +287 -0
- oscura/loaders/sigrok.py +321 -0
- oscura/loaders/tdms.py +367 -0
- oscura/loaders/tektronix.py +711 -0
- oscura/loaders/validation.py +584 -0
- oscura/loaders/vcd.py +464 -0
- oscura/loaders/wav.py +233 -0
- oscura/math/__init__.py +45 -0
- oscura/math/arithmetic.py +824 -0
- oscura/math/interpolation.py +413 -0
- oscura/onboarding/__init__.py +39 -0
- oscura/onboarding/help.py +498 -0
- oscura/onboarding/tutorials.py +405 -0
- oscura/onboarding/wizard.py +466 -0
- oscura/optimization/__init__.py +19 -0
- oscura/optimization/parallel.py +440 -0
- oscura/optimization/search.py +532 -0
- oscura/pipeline/__init__.py +43 -0
- oscura/pipeline/base.py +338 -0
- oscura/pipeline/composition.py +242 -0
- oscura/pipeline/parallel.py +448 -0
- oscura/pipeline/pipeline.py +375 -0
- oscura/pipeline/reverse_engineering.py +1119 -0
- oscura/plugins/__init__.py +122 -0
- oscura/plugins/base.py +272 -0
- oscura/plugins/cli.py +497 -0
- oscura/plugins/discovery.py +411 -0
- oscura/plugins/isolation.py +418 -0
- oscura/plugins/lifecycle.py +959 -0
- oscura/plugins/manager.py +493 -0
- oscura/plugins/registry.py +421 -0
- oscura/plugins/versioning.py +372 -0
- oscura/py.typed +0 -0
- oscura/quality/__init__.py +65 -0
- oscura/quality/ensemble.py +740 -0
- oscura/quality/explainer.py +338 -0
- oscura/quality/scoring.py +616 -0
- oscura/quality/warnings.py +456 -0
- oscura/reporting/__init__.py +248 -0
- oscura/reporting/advanced.py +1234 -0
- oscura/reporting/analyze.py +448 -0
- oscura/reporting/argument_preparer.py +596 -0
- oscura/reporting/auto_report.py +507 -0
- oscura/reporting/batch.py +615 -0
- oscura/reporting/chart_selection.py +223 -0
- oscura/reporting/comparison.py +330 -0
- oscura/reporting/config.py +615 -0
- oscura/reporting/content/__init__.py +39 -0
- oscura/reporting/content/executive.py +127 -0
- oscura/reporting/content/filtering.py +191 -0
- oscura/reporting/content/minimal.py +257 -0
- oscura/reporting/content/verbosity.py +162 -0
- oscura/reporting/core.py +508 -0
- oscura/reporting/core_formats/__init__.py +17 -0
- oscura/reporting/core_formats/multi_format.py +210 -0
- oscura/reporting/engine.py +836 -0
- oscura/reporting/export.py +366 -0
- oscura/reporting/formatting/__init__.py +129 -0
- oscura/reporting/formatting/emphasis.py +81 -0
- oscura/reporting/formatting/numbers.py +403 -0
- oscura/reporting/formatting/standards.py +55 -0
- oscura/reporting/formatting.py +466 -0
- oscura/reporting/html.py +578 -0
- oscura/reporting/index.py +590 -0
- oscura/reporting/multichannel.py +296 -0
- oscura/reporting/output.py +379 -0
- oscura/reporting/pdf.py +373 -0
- oscura/reporting/plots.py +731 -0
- oscura/reporting/pptx_export.py +360 -0
- oscura/reporting/renderers/__init__.py +11 -0
- oscura/reporting/renderers/pdf.py +94 -0
- oscura/reporting/sections.py +471 -0
- oscura/reporting/standards.py +680 -0
- oscura/reporting/summary_generator.py +368 -0
- oscura/reporting/tables.py +397 -0
- oscura/reporting/template_system.py +724 -0
- oscura/reporting/templates/__init__.py +15 -0
- oscura/reporting/templates/definition.py +205 -0
- oscura/reporting/templates/index.html +649 -0
- oscura/reporting/templates/index.md +173 -0
- oscura/schemas/__init__.py +158 -0
- oscura/schemas/bus_configuration.json +322 -0
- oscura/schemas/device_mapping.json +182 -0
- oscura/schemas/packet_format.json +418 -0
- oscura/schemas/protocol_definition.json +363 -0
- oscura/search/__init__.py +16 -0
- oscura/search/anomaly.py +292 -0
- oscura/search/context.py +149 -0
- oscura/search/pattern.py +160 -0
- oscura/session/__init__.py +34 -0
- oscura/session/annotations.py +289 -0
- oscura/session/history.py +313 -0
- oscura/session/session.py +445 -0
- oscura/streaming/__init__.py +43 -0
- oscura/streaming/chunked.py +611 -0
- oscura/streaming/progressive.py +393 -0
- oscura/streaming/realtime.py +622 -0
- oscura/testing/__init__.py +54 -0
- oscura/testing/synthetic.py +808 -0
- oscura/triggering/__init__.py +68 -0
- oscura/triggering/base.py +229 -0
- oscura/triggering/edge.py +353 -0
- oscura/triggering/pattern.py +344 -0
- oscura/triggering/pulse.py +581 -0
- oscura/triggering/window.py +453 -0
- oscura/ui/__init__.py +48 -0
- oscura/ui/formatters.py +526 -0
- oscura/ui/progressive_display.py +340 -0
- oscura/utils/__init__.py +99 -0
- oscura/utils/autodetect.py +338 -0
- oscura/utils/buffer.py +389 -0
- oscura/utils/lazy.py +407 -0
- oscura/utils/lazy_imports.py +147 -0
- oscura/utils/memory.py +836 -0
- oscura/utils/memory_advanced.py +1326 -0
- oscura/utils/memory_extensions.py +465 -0
- oscura/utils/progressive.py +352 -0
- oscura/utils/windowing.py +362 -0
- oscura/visualization/__init__.py +321 -0
- oscura/visualization/accessibility.py +526 -0
- oscura/visualization/annotations.py +374 -0
- oscura/visualization/axis_scaling.py +305 -0
- oscura/visualization/colors.py +453 -0
- oscura/visualization/digital.py +337 -0
- oscura/visualization/eye.py +420 -0
- oscura/visualization/histogram.py +281 -0
- oscura/visualization/interactive.py +858 -0
- oscura/visualization/jitter.py +702 -0
- oscura/visualization/keyboard.py +394 -0
- oscura/visualization/layout.py +365 -0
- oscura/visualization/optimization.py +1028 -0
- oscura/visualization/palettes.py +446 -0
- oscura/visualization/plot.py +92 -0
- oscura/visualization/power.py +290 -0
- oscura/visualization/power_extended.py +626 -0
- oscura/visualization/presets.py +467 -0
- oscura/visualization/protocols.py +932 -0
- oscura/visualization/render.py +207 -0
- oscura/visualization/rendering.py +444 -0
- oscura/visualization/reverse_engineering.py +791 -0
- oscura/visualization/signal_integrity.py +808 -0
- oscura/visualization/specialized.py +553 -0
- oscura/visualization/spectral.py +811 -0
- oscura/visualization/styles.py +381 -0
- oscura/visualization/thumbnails.py +311 -0
- oscura/visualization/time_axis.py +351 -0
- oscura/visualization/waveform.py +367 -0
- oscura/workflow/__init__.py +13 -0
- oscura/workflow/dag.py +377 -0
- oscura/workflows/__init__.py +58 -0
- oscura/workflows/compliance.py +280 -0
- oscura/workflows/digital.py +272 -0
- oscura/workflows/multi_trace.py +502 -0
- oscura/workflows/power.py +178 -0
- oscura/workflows/protocol.py +492 -0
- oscura/workflows/reverse_engineering.py +639 -0
- oscura/workflows/signal_integrity.py +227 -0
- oscura-0.1.0.dist-info/METADATA +300 -0
- oscura-0.1.0.dist-info/RECORD +463 -0
- oscura-0.1.0.dist-info/entry_points.txt +2 -0
- {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/licenses/LICENSE +1 -1
- oscura-0.0.1.dist-info/METADATA +0 -63
- oscura-0.0.1.dist-info/RECORD +0 -5
- {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
"""Report section generation for TraceKit.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for creating standardized report sections
|
|
4
|
+
including title, summary, measurements, plots, and conclusions.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
>>> from oscura.reporting.sections import create_title_section
|
|
9
|
+
>>> section = create_title_section("Signal Analysis Report", author="Engineer")
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from oscura.reporting.core import Section
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def create_title_section(
|
|
21
|
+
title: str,
|
|
22
|
+
*,
|
|
23
|
+
author: str | None = None,
|
|
24
|
+
date: datetime | None = None,
|
|
25
|
+
subtitle: str | None = None,
|
|
26
|
+
) -> Section:
|
|
27
|
+
"""Create title section for report.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
title: Report title.
|
|
31
|
+
author: Report author.
|
|
32
|
+
date: Report date (defaults to now).
|
|
33
|
+
subtitle: Optional subtitle.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Title Section object.
|
|
37
|
+
|
|
38
|
+
References:
|
|
39
|
+
REPORT-006
|
|
40
|
+
"""
|
|
41
|
+
content_parts = []
|
|
42
|
+
|
|
43
|
+
if subtitle:
|
|
44
|
+
content_parts.append(subtitle)
|
|
45
|
+
|
|
46
|
+
if author:
|
|
47
|
+
content_parts.append(f"Author: {author}")
|
|
48
|
+
|
|
49
|
+
if date is None:
|
|
50
|
+
date = datetime.now()
|
|
51
|
+
content_parts.append(f"Date: {date.strftime('%Y-%m-%d %H:%M')}")
|
|
52
|
+
|
|
53
|
+
content = "\n".join(content_parts)
|
|
54
|
+
|
|
55
|
+
return Section(
|
|
56
|
+
title=title,
|
|
57
|
+
content=content,
|
|
58
|
+
level=0, # Top level
|
|
59
|
+
visible=True,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def create_executive_summary_section(
|
|
64
|
+
results: dict[str, Any],
|
|
65
|
+
*,
|
|
66
|
+
key_findings: list[str] | None = None,
|
|
67
|
+
length: str = "summary",
|
|
68
|
+
) -> Section:
|
|
69
|
+
"""Create executive summary section.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
results: Analysis results dictionary.
|
|
73
|
+
key_findings: List of key findings to highlight.
|
|
74
|
+
length: Summary length (short, summary, detailed).
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Executive Summary Section object.
|
|
78
|
+
|
|
79
|
+
References:
|
|
80
|
+
REPORT-004, REPORT-006
|
|
81
|
+
"""
|
|
82
|
+
content_parts = []
|
|
83
|
+
|
|
84
|
+
# Overall status
|
|
85
|
+
if "pass_count" in results and "total_count" in results:
|
|
86
|
+
pass_count = results["pass_count"]
|
|
87
|
+
total = results["total_count"]
|
|
88
|
+
|
|
89
|
+
if pass_count == total:
|
|
90
|
+
content_parts.append(f"All {total} tests passed with satisfactory margins.")
|
|
91
|
+
else:
|
|
92
|
+
fail_count = total - pass_count
|
|
93
|
+
content_parts.append(
|
|
94
|
+
f"{fail_count} of {total} tests failed ({fail_count / total * 100:.0f}% failure rate)."
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Key findings
|
|
98
|
+
if key_findings:
|
|
99
|
+
content_parts.append("\n**Key Findings:**")
|
|
100
|
+
for finding in key_findings[:5]: # Top 5
|
|
101
|
+
content_parts.append(f"- {finding}")
|
|
102
|
+
|
|
103
|
+
# Margin analysis
|
|
104
|
+
if "min_margin" in results:
|
|
105
|
+
margin = results["min_margin"]
|
|
106
|
+
content_parts.append("\n**Margin Analysis:**")
|
|
107
|
+
if margin < 0:
|
|
108
|
+
content_parts.append(f"Critical: Minimum margin is {margin:.1f}% (violation).")
|
|
109
|
+
elif margin < 10:
|
|
110
|
+
content_parts.append(
|
|
111
|
+
f"Warning: Minimum margin is {margin:.1f}% (below recommended 10%)."
|
|
112
|
+
)
|
|
113
|
+
elif margin < 20:
|
|
114
|
+
content_parts.append(f"Acceptable: Minimum margin is {margin:.1f}% (below target 20%).")
|
|
115
|
+
else:
|
|
116
|
+
content_parts.append(f"Good: Minimum margin is {margin:.1f}% (exceeds target 20%).")
|
|
117
|
+
|
|
118
|
+
# Recommendations (for detailed summary)
|
|
119
|
+
if length == "detailed" and "violations" in results:
|
|
120
|
+
violations = results["violations"]
|
|
121
|
+
if violations:
|
|
122
|
+
content_parts.append("\n**Recommendations:**")
|
|
123
|
+
for violation in violations[:3]:
|
|
124
|
+
content_parts.append(
|
|
125
|
+
f"- Address {violation.get('parameter', 'measurement')} violation"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
content = "\n".join(content_parts)
|
|
129
|
+
|
|
130
|
+
return Section(
|
|
131
|
+
title="Executive Summary",
|
|
132
|
+
content=content,
|
|
133
|
+
level=1,
|
|
134
|
+
visible=True,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def create_measurement_results_section(
|
|
139
|
+
measurements: dict[str, Any],
|
|
140
|
+
*,
|
|
141
|
+
include_plots: bool = False,
|
|
142
|
+
) -> Section:
|
|
143
|
+
"""Create measurement results section.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
measurements: Dictionary of measurement results.
|
|
147
|
+
include_plots: Include measurement plots.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Measurement Results Section object.
|
|
151
|
+
|
|
152
|
+
References:
|
|
153
|
+
REPORT-006
|
|
154
|
+
"""
|
|
155
|
+
from oscura.reporting.tables import create_measurement_table
|
|
156
|
+
|
|
157
|
+
# Create measurement table
|
|
158
|
+
table = create_measurement_table(measurements, format="dict")
|
|
159
|
+
|
|
160
|
+
content = [table]
|
|
161
|
+
|
|
162
|
+
# Add interpretation if any failures
|
|
163
|
+
failed_count = sum(1 for m in measurements.values() if not m.get("passed", True))
|
|
164
|
+
if failed_count > 0:
|
|
165
|
+
interpretation = f"\n{failed_count} measurement(s) failed specification limits."
|
|
166
|
+
content.insert(0, interpretation)
|
|
167
|
+
|
|
168
|
+
return Section(
|
|
169
|
+
title="Measurement Results",
|
|
170
|
+
content=content,
|
|
171
|
+
level=1,
|
|
172
|
+
visible=True,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def create_plots_section(
|
|
177
|
+
figures: list[dict[str, Any]],
|
|
178
|
+
) -> Section:
|
|
179
|
+
"""Create plots section.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
figures: List of figure dictionaries.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Plots Section object.
|
|
186
|
+
|
|
187
|
+
References:
|
|
188
|
+
REPORT-006
|
|
189
|
+
"""
|
|
190
|
+
content = []
|
|
191
|
+
|
|
192
|
+
for fig in figures:
|
|
193
|
+
content.append(fig)
|
|
194
|
+
|
|
195
|
+
return Section(
|
|
196
|
+
title="Waveform Plots",
|
|
197
|
+
content=content,
|
|
198
|
+
level=1,
|
|
199
|
+
visible=True,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def create_methodology_section(
|
|
204
|
+
analysis_params: dict[str, Any],
|
|
205
|
+
*,
|
|
206
|
+
verbosity: str = "standard",
|
|
207
|
+
) -> Section:
|
|
208
|
+
"""Create methodology section.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
analysis_params: Analysis parameters and settings.
|
|
212
|
+
verbosity: Detail level (summary, standard, detailed).
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Methodology Section object.
|
|
216
|
+
|
|
217
|
+
References:
|
|
218
|
+
REPORT-006
|
|
219
|
+
"""
|
|
220
|
+
content_parts = []
|
|
221
|
+
|
|
222
|
+
# Test setup
|
|
223
|
+
if "sample_rate" in analysis_params:
|
|
224
|
+
content_parts.append(f"Sample rate: {analysis_params['sample_rate']:.3g} Hz")
|
|
225
|
+
if "num_samples" in analysis_params:
|
|
226
|
+
content_parts.append(f"Number of samples: {analysis_params['num_samples']:,}")
|
|
227
|
+
if "duration" in analysis_params:
|
|
228
|
+
content_parts.append(f"Capture duration: {analysis_params['duration']:.6g} s")
|
|
229
|
+
|
|
230
|
+
# Analysis methods
|
|
231
|
+
if verbosity in ("standard", "detailed"):
|
|
232
|
+
content_parts.append("\n**Analysis Methods:**")
|
|
233
|
+
methods = analysis_params.get("methods", [])
|
|
234
|
+
if methods:
|
|
235
|
+
for method in methods:
|
|
236
|
+
content_parts.append(f"- {method}")
|
|
237
|
+
else:
|
|
238
|
+
content_parts.append("- Standard signal analysis algorithms")
|
|
239
|
+
|
|
240
|
+
# Standards compliance
|
|
241
|
+
if "standards" in analysis_params:
|
|
242
|
+
content_parts.append("\n**Standards:**")
|
|
243
|
+
for standard in analysis_params["standards"]:
|
|
244
|
+
content_parts.append(f"- {standard}")
|
|
245
|
+
|
|
246
|
+
# Detailed parameters
|
|
247
|
+
if verbosity == "detailed":
|
|
248
|
+
content_parts.append("\n**Detailed Parameters:**")
|
|
249
|
+
for key, value in analysis_params.items():
|
|
250
|
+
if key not in (
|
|
251
|
+
"sample_rate",
|
|
252
|
+
"num_samples",
|
|
253
|
+
"duration",
|
|
254
|
+
"methods",
|
|
255
|
+
"standards",
|
|
256
|
+
):
|
|
257
|
+
content_parts.append(f"- {key}: {value}")
|
|
258
|
+
|
|
259
|
+
content = "\n".join(content_parts)
|
|
260
|
+
|
|
261
|
+
return Section(
|
|
262
|
+
title="Methodology",
|
|
263
|
+
content=content,
|
|
264
|
+
level=1,
|
|
265
|
+
visible=True,
|
|
266
|
+
collapsible=True,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def create_conclusions_section(
|
|
271
|
+
results: dict[str, Any],
|
|
272
|
+
*,
|
|
273
|
+
recommendations: list[str] | None = None,
|
|
274
|
+
) -> Section:
|
|
275
|
+
"""Create conclusions section.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
results: Analysis results.
|
|
279
|
+
recommendations: List of recommendations.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
Conclusions Section object.
|
|
283
|
+
|
|
284
|
+
References:
|
|
285
|
+
REPORT-006
|
|
286
|
+
"""
|
|
287
|
+
content_parts = []
|
|
288
|
+
|
|
289
|
+
# Overall conclusion
|
|
290
|
+
if "pass_count" in results and "total_count" in results:
|
|
291
|
+
pass_count = results["pass_count"]
|
|
292
|
+
total = results["total_count"]
|
|
293
|
+
|
|
294
|
+
if pass_count == total:
|
|
295
|
+
content_parts.append(
|
|
296
|
+
"The device under test meets all specifications and is ready for deployment."
|
|
297
|
+
)
|
|
298
|
+
else:
|
|
299
|
+
fail_count = total - pass_count
|
|
300
|
+
content_parts.append(
|
|
301
|
+
f"The device under test has {fail_count} specification violation(s) "
|
|
302
|
+
"that must be addressed before deployment."
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# Risk assessment
|
|
306
|
+
if "min_margin" in results:
|
|
307
|
+
margin = results["min_margin"]
|
|
308
|
+
content_parts.append("\n**Risk Assessment:**")
|
|
309
|
+
if margin < 0:
|
|
310
|
+
content_parts.append("HIGH RISK: Specification violations detected.")
|
|
311
|
+
elif margin < 10:
|
|
312
|
+
content_parts.append("MEDIUM RISK: Insufficient design margin.")
|
|
313
|
+
elif margin < 20:
|
|
314
|
+
content_parts.append("LOW RISK: Adequate margin but below target.")
|
|
315
|
+
else:
|
|
316
|
+
content_parts.append("ACCEPTABLE: Sufficient design margin.")
|
|
317
|
+
|
|
318
|
+
# Recommendations
|
|
319
|
+
if recommendations:
|
|
320
|
+
content_parts.append("\n**Recommendations:**")
|
|
321
|
+
for rec in recommendations:
|
|
322
|
+
content_parts.append(f"- {rec}")
|
|
323
|
+
|
|
324
|
+
content = "\n".join(content_parts)
|
|
325
|
+
|
|
326
|
+
return Section(
|
|
327
|
+
title="Conclusions",
|
|
328
|
+
content=content,
|
|
329
|
+
level=1,
|
|
330
|
+
visible=True,
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def create_appendix_section(
|
|
335
|
+
raw_data: dict[str, Any],
|
|
336
|
+
*,
|
|
337
|
+
include_provenance: bool = True,
|
|
338
|
+
) -> Section:
|
|
339
|
+
"""Create appendix section with raw data and provenance.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
raw_data: Raw data to include.
|
|
343
|
+
include_provenance: Include data provenance information.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
Appendix Section object.
|
|
347
|
+
|
|
348
|
+
References:
|
|
349
|
+
REPORT-006
|
|
350
|
+
"""
|
|
351
|
+
content_parts = []
|
|
352
|
+
|
|
353
|
+
# Provenance
|
|
354
|
+
if include_provenance:
|
|
355
|
+
content_parts.append("**Data Provenance:**")
|
|
356
|
+
if "source_file" in raw_data:
|
|
357
|
+
content_parts.append(f"Source: {raw_data['source_file']}")
|
|
358
|
+
if "timestamp" in raw_data:
|
|
359
|
+
content_parts.append(f"Timestamp: {raw_data['timestamp']}")
|
|
360
|
+
if "tool_version" in raw_data:
|
|
361
|
+
content_parts.append(f"Tool Version: {raw_data['tool_version']}")
|
|
362
|
+
|
|
363
|
+
# Raw data (truncated)
|
|
364
|
+
content_parts.append("\n**Raw Data:** (See detailed output for full data)")
|
|
365
|
+
|
|
366
|
+
content = "\n".join(content_parts)
|
|
367
|
+
|
|
368
|
+
return Section(
|
|
369
|
+
title="Appendix",
|
|
370
|
+
content=content,
|
|
371
|
+
level=1,
|
|
372
|
+
visible=True,
|
|
373
|
+
collapsible=True,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def create_violations_section(
|
|
378
|
+
violations: list[dict[str, Any]],
|
|
379
|
+
) -> Section:
|
|
380
|
+
"""Create violations section highlighting failures.
|
|
381
|
+
|
|
382
|
+
Args:
|
|
383
|
+
violations: List of violation dictionaries.
|
|
384
|
+
|
|
385
|
+
Returns:
|
|
386
|
+
Violations Section object.
|
|
387
|
+
|
|
388
|
+
References:
|
|
389
|
+
REPORT-005 (Smart Content Filtering)
|
|
390
|
+
"""
|
|
391
|
+
if not violations:
|
|
392
|
+
return Section(
|
|
393
|
+
title="Violations",
|
|
394
|
+
content="No specification violations detected.",
|
|
395
|
+
level=1,
|
|
396
|
+
visible=False, # Hide if no violations
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
content_parts = [f"**{len(violations)} specification violation(s) detected:**\n"]
|
|
400
|
+
|
|
401
|
+
for v in violations:
|
|
402
|
+
param = v.get("parameter", "Unknown")
|
|
403
|
+
value = v.get("value", "N/A")
|
|
404
|
+
spec = v.get("specification", "N/A")
|
|
405
|
+
severity = v.get("severity", "WARNING")
|
|
406
|
+
|
|
407
|
+
content_parts.append(f"- **{param}**: {value} (spec: {spec}) [{severity}]")
|
|
408
|
+
|
|
409
|
+
content = "\n".join(content_parts)
|
|
410
|
+
|
|
411
|
+
return Section(
|
|
412
|
+
title="Violations",
|
|
413
|
+
content=content,
|
|
414
|
+
level=1,
|
|
415
|
+
visible=True,
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def create_standard_report_sections(
|
|
420
|
+
results: dict[str, Any],
|
|
421
|
+
*,
|
|
422
|
+
verbosity: str = "standard",
|
|
423
|
+
) -> list[Section]:
|
|
424
|
+
"""Create standard set of report sections.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
results: Complete analysis results.
|
|
428
|
+
verbosity: Report verbosity level.
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
List of Section objects for a complete report.
|
|
432
|
+
|
|
433
|
+
References:
|
|
434
|
+
REPORT-006
|
|
435
|
+
"""
|
|
436
|
+
sections = []
|
|
437
|
+
|
|
438
|
+
# Executive summary (all verbosity levels)
|
|
439
|
+
if "summary" in results or "pass_count" in results:
|
|
440
|
+
sections.append(create_executive_summary_section(results))
|
|
441
|
+
|
|
442
|
+
# Violations (if any)
|
|
443
|
+
if results.get("violations"):
|
|
444
|
+
sections.append(create_violations_section(results["violations"]))
|
|
445
|
+
|
|
446
|
+
# Measurement results
|
|
447
|
+
if "measurements" in results:
|
|
448
|
+
sections.append(create_measurement_results_section(results["measurements"]))
|
|
449
|
+
|
|
450
|
+
# Plots (if available)
|
|
451
|
+
if results.get("figures"):
|
|
452
|
+
sections.append(create_plots_section(results["figures"]))
|
|
453
|
+
|
|
454
|
+
# Methodology (standard and above)
|
|
455
|
+
if verbosity in ("standard", "detailed", "debug") and "analysis_params" in results:
|
|
456
|
+
sections.append(create_methodology_section(results["analysis_params"], verbosity=verbosity))
|
|
457
|
+
|
|
458
|
+
# Conclusions
|
|
459
|
+
if "conclusions" in results or "recommendations" in results:
|
|
460
|
+
sections.append(
|
|
461
|
+
create_conclusions_section(
|
|
462
|
+
results,
|
|
463
|
+
recommendations=results.get("recommendations"),
|
|
464
|
+
)
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
# Appendix (detailed and debug only)
|
|
468
|
+
if verbosity in ("detailed", "debug"):
|
|
469
|
+
sections.append(create_appendix_section(results))
|
|
470
|
+
|
|
471
|
+
return sections
|