oscura 0.0.1__py3-none-any.whl → 0.1.1__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.1.dist-info/METADATA +300 -0
- oscura-0.1.1.dist-info/RECORD +463 -0
- oscura-0.1.1.dist-info/entry_points.txt +2 -0
- {oscura-0.0.1.dist-info → oscura-0.1.1.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.1.dist-info}/WHEEL +0 -0
oscura/cli/main.py
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""Oscura Core CLI Framework implementing CLI-001.
|
|
2
|
+
|
|
3
|
+
Provides the main entry point for the oscura command-line interface with
|
|
4
|
+
support for multiple output formats and verbose logging.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
$ oscura --help
|
|
9
|
+
$ oscura characterize signal.wfm --output json
|
|
10
|
+
$ oscura decode uart.wfm -vv
|
|
11
|
+
$ oscura shell # Interactive REPL
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import logging
|
|
18
|
+
import sys
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
import click
|
|
22
|
+
|
|
23
|
+
# Configure logging
|
|
24
|
+
logging.basicConfig(
|
|
25
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
26
|
+
level=logging.WARNING,
|
|
27
|
+
)
|
|
28
|
+
logger = logging.getLogger("oscura")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class OutputFormat:
|
|
32
|
+
"""Output format handler for CLI results.
|
|
33
|
+
|
|
34
|
+
Supports JSON, CSV, HTML, and table (default) output formats.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def json(data: dict[str, Any]) -> str:
|
|
39
|
+
"""Format as JSON."""
|
|
40
|
+
return json.dumps(data, indent=2, default=str)
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def csv(data: dict[str, Any]) -> str:
|
|
44
|
+
"""Format as CSV (simplified)."""
|
|
45
|
+
lines = ["key,value"]
|
|
46
|
+
for key, value in data.items():
|
|
47
|
+
if isinstance(value, dict):
|
|
48
|
+
# Nested dict - flatten
|
|
49
|
+
for subkey, subvalue in value.items():
|
|
50
|
+
lines.append(f"{key}.{subkey},{subvalue}")
|
|
51
|
+
elif isinstance(value, list):
|
|
52
|
+
lines.append(f'{key},"{",".join(map(str, value))}"')
|
|
53
|
+
else:
|
|
54
|
+
lines.append(f"{key},{value}")
|
|
55
|
+
return "\n".join(lines)
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def html(data: dict[str, Any]) -> str:
|
|
59
|
+
"""Format as HTML."""
|
|
60
|
+
html_parts = [
|
|
61
|
+
"<!DOCTYPE html>",
|
|
62
|
+
"<html>",
|
|
63
|
+
"<head>",
|
|
64
|
+
"<meta charset='utf-8'>",
|
|
65
|
+
"<title>Oscura Analysis Results</title>",
|
|
66
|
+
"<style>",
|
|
67
|
+
"body { font-family: Arial, sans-serif; margin: 20px; }",
|
|
68
|
+
"table { border-collapse: collapse; width: 100%; }",
|
|
69
|
+
"th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }",
|
|
70
|
+
"th { background-color: #4CAF50; color: white; }",
|
|
71
|
+
"tr:nth-child(even) { background-color: #f2f2f2; }",
|
|
72
|
+
"</style>",
|
|
73
|
+
"</head>",
|
|
74
|
+
"<body>",
|
|
75
|
+
"<h1>Oscura Analysis Results</h1>",
|
|
76
|
+
"<table>",
|
|
77
|
+
"<tr><th>Parameter</th><th>Value</th></tr>",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
for key, value in data.items():
|
|
81
|
+
html_parts.append(f"<tr><td>{key}</td><td>{value}</td></tr>")
|
|
82
|
+
|
|
83
|
+
html_parts.extend(
|
|
84
|
+
[
|
|
85
|
+
"</table>",
|
|
86
|
+
"</body>",
|
|
87
|
+
"</html>",
|
|
88
|
+
]
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return "\n".join(html_parts)
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def table(data: dict[str, Any]) -> str:
|
|
95
|
+
"""Format as ASCII table."""
|
|
96
|
+
if not data:
|
|
97
|
+
return "No data"
|
|
98
|
+
|
|
99
|
+
# Calculate column widths
|
|
100
|
+
max_key = max(len(str(k)) for k in data)
|
|
101
|
+
max_val = max(len(str(v)) for v in data.values())
|
|
102
|
+
|
|
103
|
+
# Build table
|
|
104
|
+
lines = []
|
|
105
|
+
lines.append("=" * (max_key + max_val + 7))
|
|
106
|
+
lines.append(f"{'Parameter':{max_key}} | Value")
|
|
107
|
+
lines.append("-" * (max_key + max_val + 7))
|
|
108
|
+
|
|
109
|
+
for key, value in data.items():
|
|
110
|
+
lines.append(f"{key!s:{max_key}} | {value}")
|
|
111
|
+
|
|
112
|
+
lines.append("=" * (max_key + max_val + 7))
|
|
113
|
+
|
|
114
|
+
return "\n".join(lines)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def format_output(data: dict[str, Any], format_type: str) -> str:
|
|
118
|
+
"""Format output data according to specified format.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
data: Dictionary of results to format.
|
|
122
|
+
format_type: Output format ('json', 'csv', 'html', 'table').
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Formatted string.
|
|
126
|
+
"""
|
|
127
|
+
formatter = getattr(OutputFormat, format_type, OutputFormat.table)
|
|
128
|
+
return formatter(data)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@click.group() # type: ignore[misc]
|
|
132
|
+
@click.option( # type: ignore[misc]
|
|
133
|
+
"-v",
|
|
134
|
+
"--verbose",
|
|
135
|
+
count=True,
|
|
136
|
+
help="Increase verbosity (-v for INFO, -vv for DEBUG).",
|
|
137
|
+
)
|
|
138
|
+
@click.version_option(version="0.1.0", prog_name="oscura") # type: ignore[misc]
|
|
139
|
+
@click.pass_context # type: ignore[misc]
|
|
140
|
+
def cli(ctx: click.Context, verbose: int) -> None:
|
|
141
|
+
"""Oscura - Signal Analysis Framework for Oscilloscope Data.
|
|
142
|
+
|
|
143
|
+
Command-line tools for characterizing buffers, decoding protocols,
|
|
144
|
+
analyzing spectra, and comparing signals.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
ctx: Click context object.
|
|
148
|
+
verbose: Verbosity level (0=WARNING, 1=INFO, 2+=DEBUG).
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
oscura characterize signal.wfm
|
|
152
|
+
oscura decode uart.wfm --protocol auto
|
|
153
|
+
oscura batch '*.wfm' --analysis characterize
|
|
154
|
+
oscura compare before.wfm after.wfm
|
|
155
|
+
oscura shell # Interactive REPL
|
|
156
|
+
"""
|
|
157
|
+
# Ensure ctx.obj exists
|
|
158
|
+
ctx.ensure_object(dict)
|
|
159
|
+
|
|
160
|
+
# Set logging level based on verbosity
|
|
161
|
+
if verbose == 0:
|
|
162
|
+
logger.setLevel(logging.WARNING)
|
|
163
|
+
elif verbose == 1:
|
|
164
|
+
logger.setLevel(logging.INFO)
|
|
165
|
+
logger.info("Verbose mode enabled")
|
|
166
|
+
else: # verbose >= 2
|
|
167
|
+
logger.setLevel(logging.DEBUG)
|
|
168
|
+
logger.debug("Debug mode enabled")
|
|
169
|
+
|
|
170
|
+
ctx.obj["verbose"] = verbose
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@click.command() # type: ignore[misc]
|
|
174
|
+
def shell() -> None:
|
|
175
|
+
"""Start an interactive Oscura shell.
|
|
176
|
+
|
|
177
|
+
Opens a Python REPL with Oscura pre-imported and ready to use.
|
|
178
|
+
Features tab completion, persistent history, and helpful shortcuts.
|
|
179
|
+
|
|
180
|
+
Example:
|
|
181
|
+
$ oscura shell
|
|
182
|
+
Oscura Shell v0.1.0
|
|
183
|
+
>>> trace = load("signal.wfm")
|
|
184
|
+
>>> rise_time(trace)
|
|
185
|
+
"""
|
|
186
|
+
from oscura.cli.shell import start_shell
|
|
187
|
+
|
|
188
|
+
start_shell()
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
@click.command() # type: ignore[misc]
|
|
192
|
+
@click.argument("tutorial_id", required=False, default=None) # type: ignore[misc]
|
|
193
|
+
@click.option("--list", "list_tutorials", is_flag=True, help="List available tutorials") # type: ignore[misc]
|
|
194
|
+
def tutorial(tutorial_id: str | None, list_tutorials: bool) -> None:
|
|
195
|
+
"""Run an interactive tutorial.
|
|
196
|
+
|
|
197
|
+
Provides step-by-step guidance for learning Oscura.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
tutorial_id: ID of the tutorial to run (or None to list).
|
|
201
|
+
list_tutorials: If True, list available tutorials.
|
|
202
|
+
|
|
203
|
+
Examples:
|
|
204
|
+
oscura tutorial --list # List available tutorials
|
|
205
|
+
oscura tutorial getting_started # Run the getting started tutorial
|
|
206
|
+
"""
|
|
207
|
+
from oscura.onboarding import list_tutorials as list_tut
|
|
208
|
+
from oscura.onboarding import run_tutorial
|
|
209
|
+
|
|
210
|
+
if list_tutorials or tutorial_id is None:
|
|
211
|
+
tutorials = list_tut()
|
|
212
|
+
click.echo("Available tutorials:")
|
|
213
|
+
for t in tutorials:
|
|
214
|
+
click.echo(f" {t['id']}: {t['title']} ({t['difficulty']}, {t['steps']} steps)")
|
|
215
|
+
if tutorial_id is None:
|
|
216
|
+
click.echo("\nRun with: oscura tutorial <tutorial_id>")
|
|
217
|
+
return
|
|
218
|
+
|
|
219
|
+
run_tutorial(tutorial_id, interactive=True)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# Import subcommands
|
|
223
|
+
from oscura.cli.batch import batch # noqa: E402
|
|
224
|
+
from oscura.cli.characterize import characterize # noqa: E402
|
|
225
|
+
from oscura.cli.compare import compare # noqa: E402
|
|
226
|
+
from oscura.cli.decode import decode # noqa: E402
|
|
227
|
+
|
|
228
|
+
# Register subcommands
|
|
229
|
+
cli.add_command(characterize) # type: ignore[has-type]
|
|
230
|
+
cli.add_command(decode) # type: ignore[has-type]
|
|
231
|
+
cli.add_command(batch) # type: ignore[has-type]
|
|
232
|
+
cli.add_command(compare) # type: ignore[has-type]
|
|
233
|
+
cli.add_command(shell)
|
|
234
|
+
cli.add_command(tutorial)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def main() -> None:
|
|
238
|
+
"""Entry point for the oscura CLI."""
|
|
239
|
+
try:
|
|
240
|
+
cli(obj={})
|
|
241
|
+
except Exception as e:
|
|
242
|
+
logger.error(f"Fatal error: {e}")
|
|
243
|
+
sys.exit(1)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
if __name__ == "__main__":
|
|
247
|
+
main()
|
oscura/cli/shell.py
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
"""Interactive REPL shell for Oscura exploration.
|
|
2
|
+
|
|
3
|
+
This module provides an interactive Python shell with Oscura auto-imports,
|
|
4
|
+
tab completion, and persistent history for exploratory data analysis.
|
|
5
|
+
|
|
6
|
+
- Auto-imports Oscura modules
|
|
7
|
+
- Tab completion for methods and attributes
|
|
8
|
+
- Persistent command history
|
|
9
|
+
- Customized prompt with context info
|
|
10
|
+
|
|
11
|
+
Example:
|
|
12
|
+
$ oscura shell
|
|
13
|
+
Oscura Shell v0.1.0
|
|
14
|
+
Type 'help()' for Oscura help, 'exit()' to quit.
|
|
15
|
+
|
|
16
|
+
In [1]: trace = load("capture.wfm")
|
|
17
|
+
In [2]: rise_time(trace)
|
|
18
|
+
Out[2]: 2.5e-9
|
|
19
|
+
In [3]: freq, mag = fft(trace)
|
|
20
|
+
|
|
21
|
+
References:
|
|
22
|
+
- Python readline module
|
|
23
|
+
- IPython-style interaction patterns
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import atexit
|
|
29
|
+
import code
|
|
30
|
+
import contextlib
|
|
31
|
+
import readline
|
|
32
|
+
import rlcompleter
|
|
33
|
+
import sys
|
|
34
|
+
from pathlib import Path
|
|
35
|
+
from typing import Any
|
|
36
|
+
|
|
37
|
+
# History file location
|
|
38
|
+
HISTORY_FILE = Path.home() / ".oscura_history"
|
|
39
|
+
HISTORY_LENGTH = 1000
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_oscura_namespace() -> dict[str, Any]:
|
|
43
|
+
"""Build namespace with Oscura auto-imports.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Dictionary with all commonly-used Oscura functions and classes.
|
|
47
|
+
"""
|
|
48
|
+
namespace: dict[str, Any] = {}
|
|
49
|
+
|
|
50
|
+
# Core imports
|
|
51
|
+
try:
|
|
52
|
+
import oscura as osc
|
|
53
|
+
|
|
54
|
+
namespace["osc"] = osc
|
|
55
|
+
|
|
56
|
+
# Auto-import commonly used functions at top level
|
|
57
|
+
from oscura import (
|
|
58
|
+
DigitalTrace,
|
|
59
|
+
ProtocolPacket,
|
|
60
|
+
TraceMetadata,
|
|
61
|
+
# Core types
|
|
62
|
+
WaveformTrace,
|
|
63
|
+
# Math
|
|
64
|
+
add,
|
|
65
|
+
amplitude,
|
|
66
|
+
band_pass,
|
|
67
|
+
band_stop,
|
|
68
|
+
# Statistics
|
|
69
|
+
basic_stats,
|
|
70
|
+
detect_edges,
|
|
71
|
+
differentiate,
|
|
72
|
+
divide,
|
|
73
|
+
duty_cycle,
|
|
74
|
+
enob,
|
|
75
|
+
fall_time,
|
|
76
|
+
# Spectral
|
|
77
|
+
fft,
|
|
78
|
+
frequency,
|
|
79
|
+
get_supported_formats,
|
|
80
|
+
high_pass,
|
|
81
|
+
histogram,
|
|
82
|
+
integrate,
|
|
83
|
+
# Loaders
|
|
84
|
+
load,
|
|
85
|
+
# Filtering
|
|
86
|
+
low_pass,
|
|
87
|
+
mean,
|
|
88
|
+
measure,
|
|
89
|
+
multiply,
|
|
90
|
+
overshoot,
|
|
91
|
+
percentiles,
|
|
92
|
+
period,
|
|
93
|
+
psd,
|
|
94
|
+
pulse_width,
|
|
95
|
+
# Measurements
|
|
96
|
+
rise_time,
|
|
97
|
+
rms,
|
|
98
|
+
sfdr,
|
|
99
|
+
sinad,
|
|
100
|
+
snr,
|
|
101
|
+
spectrogram,
|
|
102
|
+
subtract,
|
|
103
|
+
thd,
|
|
104
|
+
# Digital
|
|
105
|
+
to_digital,
|
|
106
|
+
undershoot,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
namespace.update(
|
|
110
|
+
{
|
|
111
|
+
"WaveformTrace": WaveformTrace,
|
|
112
|
+
"DigitalTrace": DigitalTrace,
|
|
113
|
+
"TraceMetadata": TraceMetadata,
|
|
114
|
+
"ProtocolPacket": ProtocolPacket,
|
|
115
|
+
"load": load,
|
|
116
|
+
"get_supported_formats": get_supported_formats,
|
|
117
|
+
"rise_time": rise_time,
|
|
118
|
+
"fall_time": fall_time,
|
|
119
|
+
"frequency": frequency,
|
|
120
|
+
"period": period,
|
|
121
|
+
"amplitude": amplitude,
|
|
122
|
+
"rms": rms,
|
|
123
|
+
"mean": mean,
|
|
124
|
+
"overshoot": overshoot,
|
|
125
|
+
"undershoot": undershoot,
|
|
126
|
+
"duty_cycle": duty_cycle,
|
|
127
|
+
"pulse_width": pulse_width,
|
|
128
|
+
"measure": measure,
|
|
129
|
+
"fft": fft,
|
|
130
|
+
"psd": psd,
|
|
131
|
+
"thd": thd,
|
|
132
|
+
"snr": snr,
|
|
133
|
+
"sinad": sinad,
|
|
134
|
+
"enob": enob,
|
|
135
|
+
"sfdr": sfdr,
|
|
136
|
+
"spectrogram": spectrogram,
|
|
137
|
+
"to_digital": to_digital,
|
|
138
|
+
"detect_edges": detect_edges,
|
|
139
|
+
"low_pass": low_pass,
|
|
140
|
+
"high_pass": high_pass,
|
|
141
|
+
"band_pass": band_pass,
|
|
142
|
+
"band_stop": band_stop,
|
|
143
|
+
"add": add,
|
|
144
|
+
"subtract": subtract,
|
|
145
|
+
"multiply": multiply,
|
|
146
|
+
"divide": divide,
|
|
147
|
+
"differentiate": differentiate,
|
|
148
|
+
"integrate": integrate,
|
|
149
|
+
"basic_stats": basic_stats,
|
|
150
|
+
"histogram": histogram,
|
|
151
|
+
"percentiles": percentiles,
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Protocol decoders
|
|
156
|
+
try:
|
|
157
|
+
from oscura.analyzers.protocols import (
|
|
158
|
+
decode_can,
|
|
159
|
+
decode_i2c,
|
|
160
|
+
decode_spi,
|
|
161
|
+
decode_uart,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
namespace.update(
|
|
165
|
+
{
|
|
166
|
+
"decode_uart": decode_uart,
|
|
167
|
+
"decode_spi": decode_spi,
|
|
168
|
+
"decode_i2c": decode_i2c,
|
|
169
|
+
"decode_can": decode_can,
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
except ImportError:
|
|
173
|
+
pass
|
|
174
|
+
|
|
175
|
+
# Discovery
|
|
176
|
+
try:
|
|
177
|
+
from oscura.discovery import (
|
|
178
|
+
characterize_signal,
|
|
179
|
+
decode_protocol,
|
|
180
|
+
find_anomalies,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
namespace.update(
|
|
184
|
+
{
|
|
185
|
+
"characterize_signal": characterize_signal,
|
|
186
|
+
"find_anomalies": find_anomalies,
|
|
187
|
+
"decode_protocol": decode_protocol,
|
|
188
|
+
}
|
|
189
|
+
)
|
|
190
|
+
except ImportError:
|
|
191
|
+
pass
|
|
192
|
+
|
|
193
|
+
except ImportError as e:
|
|
194
|
+
print(f"Warning: Could not import Oscura: {e}")
|
|
195
|
+
|
|
196
|
+
# Common utilities
|
|
197
|
+
try:
|
|
198
|
+
import matplotlib.pyplot as plt
|
|
199
|
+
|
|
200
|
+
namespace["plt"] = plt
|
|
201
|
+
except ImportError:
|
|
202
|
+
pass
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
import numpy as np
|
|
206
|
+
|
|
207
|
+
namespace["np"] = np
|
|
208
|
+
except ImportError:
|
|
209
|
+
pass
|
|
210
|
+
|
|
211
|
+
return namespace
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def setup_history() -> None:
|
|
215
|
+
"""Set up readline history with persistence."""
|
|
216
|
+
# Enable tab completion
|
|
217
|
+
readline.parse_and_bind("tab: complete")
|
|
218
|
+
|
|
219
|
+
# Load history if exists
|
|
220
|
+
if HISTORY_FILE.exists():
|
|
221
|
+
with contextlib.suppress(Exception):
|
|
222
|
+
readline.read_history_file(HISTORY_FILE)
|
|
223
|
+
|
|
224
|
+
# Set history length
|
|
225
|
+
readline.set_history_length(HISTORY_LENGTH)
|
|
226
|
+
|
|
227
|
+
# Save history on exit
|
|
228
|
+
atexit.register(lambda: readline.write_history_file(HISTORY_FILE))
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def oscura_help() -> None:
|
|
232
|
+
"""Display Oscura help in the REPL."""
|
|
233
|
+
help_text = """
|
|
234
|
+
Oscura Interactive Shell - Quick Reference
|
|
235
|
+
=============================================
|
|
236
|
+
|
|
237
|
+
Loading Data:
|
|
238
|
+
trace = load("file.wfm") # Auto-detect format
|
|
239
|
+
trace = load("file.csv") # CSV file
|
|
240
|
+
formats = get_supported_formats() # List supported formats
|
|
241
|
+
|
|
242
|
+
Waveform Measurements:
|
|
243
|
+
rise_time(trace) # 10-90% rise time
|
|
244
|
+
fall_time(trace) # 90-10% fall time
|
|
245
|
+
frequency(trace) # Fundamental frequency
|
|
246
|
+
amplitude(trace) # Peak-to-peak amplitude
|
|
247
|
+
measure(trace) # All measurements
|
|
248
|
+
|
|
249
|
+
Spectral Analysis:
|
|
250
|
+
freq, mag = fft(trace) # FFT
|
|
251
|
+
freq, pwr = psd(trace) # Power Spectral Density
|
|
252
|
+
thd(trace) # Total Harmonic Distortion
|
|
253
|
+
snr(trace) # Signal-to-Noise Ratio
|
|
254
|
+
|
|
255
|
+
Digital Analysis:
|
|
256
|
+
digital = to_digital(trace) # Extract digital signal
|
|
257
|
+
edges = detect_edges(trace) # Find edges
|
|
258
|
+
|
|
259
|
+
Filtering:
|
|
260
|
+
filtered = low_pass(trace, 1e6) # Low-pass filter
|
|
261
|
+
filtered = high_pass(trace, 1e3) # High-pass filter
|
|
262
|
+
|
|
263
|
+
Protocol Decoding:
|
|
264
|
+
packets = decode_uart(trace) # UART decode
|
|
265
|
+
packets = decode_spi(clk, mosi) # SPI decode
|
|
266
|
+
packets = decode_i2c(scl, sda) # I2C decode
|
|
267
|
+
|
|
268
|
+
Discovery (Auto-Analysis):
|
|
269
|
+
result = characterize_signal(trace) # Auto-characterize
|
|
270
|
+
anomalies = find_anomalies(trace) # Find anomalies
|
|
271
|
+
|
|
272
|
+
For detailed help on any function:
|
|
273
|
+
help(function_name)
|
|
274
|
+
|
|
275
|
+
Full documentation: https://github.com/lair-click-bats/oscura
|
|
276
|
+
"""
|
|
277
|
+
print(help_text)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class OscuraConsole(code.InteractiveConsole):
|
|
281
|
+
"""Custom interactive console for Oscura.
|
|
282
|
+
|
|
283
|
+
Provides IPython-style prompts and enhanced error handling.
|
|
284
|
+
"""
|
|
285
|
+
|
|
286
|
+
def __init__(self, locals: dict[str, Any] | None = None) -> None:
|
|
287
|
+
"""Initialize the console with Oscura namespace."""
|
|
288
|
+
super().__init__(locals=locals, filename="<oscura>")
|
|
289
|
+
self.prompt_counter = 1
|
|
290
|
+
|
|
291
|
+
def interact(self, banner: str | None = None, exitmsg: str | None = None) -> None:
|
|
292
|
+
"""Start the interactive session."""
|
|
293
|
+
if banner is None:
|
|
294
|
+
import oscura
|
|
295
|
+
|
|
296
|
+
banner = f"""
|
|
297
|
+
Oscura Shell v{oscura.__version__}
|
|
298
|
+
Python {sys.version.split()[0]} on {sys.platform}
|
|
299
|
+
Type 'oscura_help()' for quick reference, 'exit()' to quit.
|
|
300
|
+
|
|
301
|
+
Auto-imported: tk (oscura), np (numpy), plt (matplotlib.pyplot)
|
|
302
|
+
Common functions: load, measure, fft, psd, thd, low_pass, high_pass
|
|
303
|
+
"""
|
|
304
|
+
if exitmsg is None:
|
|
305
|
+
exitmsg = "Goodbye!"
|
|
306
|
+
|
|
307
|
+
super().interact(banner=banner, exitmsg=exitmsg)
|
|
308
|
+
|
|
309
|
+
def raw_input(self, prompt: str = "") -> str:
|
|
310
|
+
"""Override prompt with counter."""
|
|
311
|
+
custom_prompt = f"In [{self.prompt_counter}]: "
|
|
312
|
+
result = super().raw_input(custom_prompt)
|
|
313
|
+
self.prompt_counter += 1
|
|
314
|
+
return result
|
|
315
|
+
|
|
316
|
+
def showtraceback(self) -> None:
|
|
317
|
+
"""Show traceback with helpful hints."""
|
|
318
|
+
super().showtraceback()
|
|
319
|
+
# Could add context-sensitive hints here
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def start_shell() -> None:
|
|
323
|
+
"""Start the Oscura interactive shell.
|
|
324
|
+
|
|
325
|
+
This is the main entry point for the REPL, providing:
|
|
326
|
+
- Auto-imported Oscura functions and modules
|
|
327
|
+
- Tab completion
|
|
328
|
+
- Persistent command history
|
|
329
|
+
- Customized prompts
|
|
330
|
+
"""
|
|
331
|
+
# Set up history
|
|
332
|
+
setup_history()
|
|
333
|
+
|
|
334
|
+
# Build namespace
|
|
335
|
+
namespace = get_oscura_namespace()
|
|
336
|
+
|
|
337
|
+
# Add help function
|
|
338
|
+
namespace["oscura_help"] = oscura_help
|
|
339
|
+
|
|
340
|
+
# Set up completer
|
|
341
|
+
completer = rlcompleter.Completer(namespace)
|
|
342
|
+
readline.set_completer(completer.complete)
|
|
343
|
+
|
|
344
|
+
# Start console
|
|
345
|
+
console = OscuraConsole(locals=namespace)
|
|
346
|
+
console.interact()
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
if __name__ == "__main__":
|
|
350
|
+
start_shell()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Comparison and limit testing module for Oscura.
|
|
2
|
+
|
|
3
|
+
This module provides waveform comparison, limit testing, mask testing,
|
|
4
|
+
and golden waveform comparison functionality.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from oscura.comparison.compare import (
|
|
8
|
+
compare_traces,
|
|
9
|
+
correlation,
|
|
10
|
+
difference,
|
|
11
|
+
similarity_score,
|
|
12
|
+
)
|
|
13
|
+
from oscura.comparison.golden import (
|
|
14
|
+
GoldenReference,
|
|
15
|
+
compare_to_golden,
|
|
16
|
+
create_golden,
|
|
17
|
+
tolerance_envelope,
|
|
18
|
+
)
|
|
19
|
+
from oscura.comparison.limits import (
|
|
20
|
+
LimitSpec,
|
|
21
|
+
check_limits,
|
|
22
|
+
create_limit_spec,
|
|
23
|
+
margin_analysis,
|
|
24
|
+
)
|
|
25
|
+
from oscura.comparison.mask import (
|
|
26
|
+
Mask,
|
|
27
|
+
create_mask,
|
|
28
|
+
eye_mask,
|
|
29
|
+
mask_test,
|
|
30
|
+
)
|
|
31
|
+
from oscura.comparison.trace_diff import (
|
|
32
|
+
Difference,
|
|
33
|
+
TraceDiff,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Note: compare_traces is imported from both compare.py and trace_diff.py
|
|
37
|
+
# The trace_diff version is from discovery.comparison (intelligent comparison)
|
|
38
|
+
# Import as compare_traces_intelligent to avoid conflict
|
|
39
|
+
from oscura.comparison.trace_diff import compare_traces as compare_traces_intelligent
|
|
40
|
+
|
|
41
|
+
__all__ = [
|
|
42
|
+
# Intelligent trace diff (DISC-004)
|
|
43
|
+
"Difference",
|
|
44
|
+
# Golden reference
|
|
45
|
+
"GoldenReference",
|
|
46
|
+
# Limits
|
|
47
|
+
"LimitSpec",
|
|
48
|
+
# Mask testing
|
|
49
|
+
"Mask",
|
|
50
|
+
"TraceDiff",
|
|
51
|
+
"check_limits",
|
|
52
|
+
"compare_to_golden",
|
|
53
|
+
# Comparison
|
|
54
|
+
"compare_traces",
|
|
55
|
+
"compare_traces_intelligent",
|
|
56
|
+
"correlation",
|
|
57
|
+
"create_golden",
|
|
58
|
+
"create_limit_spec",
|
|
59
|
+
"create_mask",
|
|
60
|
+
"difference",
|
|
61
|
+
"eye_mask",
|
|
62
|
+
"margin_analysis",
|
|
63
|
+
"mask_test",
|
|
64
|
+
"similarity_score",
|
|
65
|
+
"tolerance_envelope",
|
|
66
|
+
]
|