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
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Power analysis module for Oscura.
|
|
2
|
+
|
|
3
|
+
Provides comprehensive power analysis capabilities including:
|
|
4
|
+
- Basic power measurements (instantaneous, average, RMS, peak)
|
|
5
|
+
- AC power analysis (reactive, apparent, power factor)
|
|
6
|
+
- Switching loss analysis for power electronics
|
|
7
|
+
- Safe Operating Area (SOA) analysis
|
|
8
|
+
- Ripple measurement
|
|
9
|
+
- Efficiency calculations
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
>>> from oscura.analyzers.power import instantaneous_power, power_statistics
|
|
14
|
+
>>> power_trace = instantaneous_power(voltage_trace, current_trace)
|
|
15
|
+
>>> stats = power_statistics(power_trace)
|
|
16
|
+
>>> print(f"Average power: {stats['average']:.2f} W")
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from oscura.analyzers.power.ac_power import (
|
|
20
|
+
apparent_power,
|
|
21
|
+
displacement_power_factor,
|
|
22
|
+
distortion_power_factor,
|
|
23
|
+
phase_angle,
|
|
24
|
+
power_factor,
|
|
25
|
+
reactive_power,
|
|
26
|
+
total_harmonic_distortion_power,
|
|
27
|
+
)
|
|
28
|
+
from oscura.analyzers.power.basic import (
|
|
29
|
+
average_power,
|
|
30
|
+
energy,
|
|
31
|
+
instantaneous_power,
|
|
32
|
+
peak_power,
|
|
33
|
+
power_statistics,
|
|
34
|
+
rms_power,
|
|
35
|
+
)
|
|
36
|
+
from oscura.analyzers.power.conduction import (
|
|
37
|
+
conduction_loss,
|
|
38
|
+
duty_cycle_weighted_loss,
|
|
39
|
+
forward_voltage,
|
|
40
|
+
mosfet_conduction_loss,
|
|
41
|
+
on_resistance,
|
|
42
|
+
)
|
|
43
|
+
from oscura.analyzers.power.efficiency import (
|
|
44
|
+
efficiency,
|
|
45
|
+
multi_output_efficiency,
|
|
46
|
+
power_conversion_efficiency,
|
|
47
|
+
)
|
|
48
|
+
from oscura.analyzers.power.ripple import (
|
|
49
|
+
extract_ripple,
|
|
50
|
+
ripple,
|
|
51
|
+
ripple_frequency,
|
|
52
|
+
ripple_percentage,
|
|
53
|
+
ripple_statistics,
|
|
54
|
+
)
|
|
55
|
+
from oscura.analyzers.power.soa import (
|
|
56
|
+
SOALimit,
|
|
57
|
+
check_soa_violations,
|
|
58
|
+
create_mosfet_soa,
|
|
59
|
+
plot_soa,
|
|
60
|
+
soa_analysis,
|
|
61
|
+
)
|
|
62
|
+
from oscura.analyzers.power.switching import (
|
|
63
|
+
switching_energy,
|
|
64
|
+
switching_frequency,
|
|
65
|
+
switching_loss,
|
|
66
|
+
total_switching_loss,
|
|
67
|
+
turn_off_loss,
|
|
68
|
+
turn_on_loss,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
__all__ = [
|
|
72
|
+
"SOALimit",
|
|
73
|
+
"apparent_power",
|
|
74
|
+
"average_power",
|
|
75
|
+
"check_soa_violations",
|
|
76
|
+
# Conduction
|
|
77
|
+
"conduction_loss",
|
|
78
|
+
"create_mosfet_soa",
|
|
79
|
+
"displacement_power_factor",
|
|
80
|
+
"distortion_power_factor",
|
|
81
|
+
"duty_cycle_weighted_loss",
|
|
82
|
+
# Efficiency
|
|
83
|
+
"efficiency",
|
|
84
|
+
"energy",
|
|
85
|
+
"extract_ripple",
|
|
86
|
+
"forward_voltage",
|
|
87
|
+
# Basic power
|
|
88
|
+
"instantaneous_power",
|
|
89
|
+
"mosfet_conduction_loss",
|
|
90
|
+
"multi_output_efficiency",
|
|
91
|
+
"on_resistance",
|
|
92
|
+
"peak_power",
|
|
93
|
+
"phase_angle",
|
|
94
|
+
"plot_soa",
|
|
95
|
+
"power_conversion_efficiency",
|
|
96
|
+
"power_factor",
|
|
97
|
+
"power_statistics",
|
|
98
|
+
# AC power
|
|
99
|
+
"reactive_power",
|
|
100
|
+
# Ripple
|
|
101
|
+
"ripple",
|
|
102
|
+
"ripple_frequency",
|
|
103
|
+
"ripple_percentage",
|
|
104
|
+
"ripple_statistics",
|
|
105
|
+
"rms_power",
|
|
106
|
+
# SOA
|
|
107
|
+
"soa_analysis",
|
|
108
|
+
"switching_energy",
|
|
109
|
+
"switching_frequency",
|
|
110
|
+
# Switching
|
|
111
|
+
"switching_loss",
|
|
112
|
+
"total_harmonic_distortion_power",
|
|
113
|
+
"total_switching_loss",
|
|
114
|
+
"turn_off_loss",
|
|
115
|
+
"turn_on_loss",
|
|
116
|
+
]
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
"""AC power analysis for Oscura.
|
|
2
|
+
|
|
3
|
+
Provides AC power calculations including reactive power, apparent power,
|
|
4
|
+
power factor, and harmonic analysis.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
>>> from oscura.analyzers.power.ac_power import power_factor, reactive_power
|
|
9
|
+
>>> pf = power_factor(voltage_trace, current_trace)
|
|
10
|
+
>>> q = reactive_power(voltage_trace, current_trace)
|
|
11
|
+
>>> print(f"Power factor: {pf:.3f}, Reactive power: {q:.2f} VAR")
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
from oscura.analyzers.power.basic import average_power
|
|
19
|
+
from oscura.core.types import WaveformTrace
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def phase_angle(
|
|
23
|
+
voltage: WaveformTrace,
|
|
24
|
+
current: WaveformTrace,
|
|
25
|
+
) -> float:
|
|
26
|
+
"""Calculate phase angle between voltage and current.
|
|
27
|
+
|
|
28
|
+
Uses cross-correlation to determine the phase shift.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
voltage: Voltage waveform trace.
|
|
32
|
+
current: Current waveform trace.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Phase angle in radians (positive = current lags voltage).
|
|
36
|
+
|
|
37
|
+
Example:
|
|
38
|
+
>>> phi = phase_angle(v_trace, i_trace)
|
|
39
|
+
>>> print(f"Phase angle: {np.degrees(phi):.1f} degrees")
|
|
40
|
+
"""
|
|
41
|
+
v_data = voltage.data
|
|
42
|
+
i_data = current.data
|
|
43
|
+
|
|
44
|
+
# Ensure same length
|
|
45
|
+
min_len = min(len(v_data), len(i_data))
|
|
46
|
+
v_data = v_data[:min_len]
|
|
47
|
+
i_data = i_data[:min_len]
|
|
48
|
+
|
|
49
|
+
# Remove DC offset
|
|
50
|
+
v_ac = v_data - np.mean(v_data)
|
|
51
|
+
i_ac = i_data - np.mean(i_data)
|
|
52
|
+
|
|
53
|
+
# Cross-correlation to find phase shift
|
|
54
|
+
# correlate(v, i) tells us how much to shift i to align with v
|
|
55
|
+
# A positive lag means i needs to be shifted right (i lags v)
|
|
56
|
+
correlation = np.correlate(v_ac, i_ac, mode="full")
|
|
57
|
+
lags = np.arange(-len(i_ac) + 1, len(v_ac))
|
|
58
|
+
|
|
59
|
+
# Find peak correlation
|
|
60
|
+
peak_idx = np.argmax(np.abs(correlation))
|
|
61
|
+
lag_samples = lags[peak_idx]
|
|
62
|
+
|
|
63
|
+
# Convert lag to phase angle
|
|
64
|
+
# Estimate frequency using zero crossings
|
|
65
|
+
v_crossings = np.where(np.diff(np.signbit(v_ac)))[0]
|
|
66
|
+
if len(v_crossings) >= 2:
|
|
67
|
+
period_samples = 2 * np.mean(np.diff(v_crossings))
|
|
68
|
+
# Negative lag because correlation gives us how much to shift i to align with v
|
|
69
|
+
# If lag is negative, i is ahead of v (capacitive), phase should be negative
|
|
70
|
+
# If lag is positive, i is behind v (inductive), phase should be positive
|
|
71
|
+
phase = -2 * np.pi * lag_samples / period_samples
|
|
72
|
+
else:
|
|
73
|
+
# Fallback: use FFT to find fundamental frequency
|
|
74
|
+
fft_v = np.fft.rfft(v_ac)
|
|
75
|
+
freq_idx = np.argmax(np.abs(fft_v[1:])) + 1
|
|
76
|
+
period_samples = len(v_ac) / freq_idx
|
|
77
|
+
phase = -2 * np.pi * lag_samples / period_samples
|
|
78
|
+
|
|
79
|
+
return float(phase)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def reactive_power(
|
|
83
|
+
voltage: WaveformTrace,
|
|
84
|
+
current: WaveformTrace,
|
|
85
|
+
*,
|
|
86
|
+
frequency: float | None = None,
|
|
87
|
+
) -> float:
|
|
88
|
+
"""Calculate reactive power (Q) in VAR.
|
|
89
|
+
|
|
90
|
+
Q = V_rms * I_rms * sin(phi)
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
voltage: Voltage waveform trace.
|
|
94
|
+
current: Current waveform trace.
|
|
95
|
+
frequency: Fundamental frequency in Hz. If None, auto-detect.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Reactive power in VAR (positive = inductive, negative = capacitive).
|
|
99
|
+
|
|
100
|
+
Example:
|
|
101
|
+
>>> q = reactive_power(v_trace, i_trace)
|
|
102
|
+
>>> print(f"Reactive power: {q:.2f} VAR")
|
|
103
|
+
|
|
104
|
+
References:
|
|
105
|
+
IEEE 1459-2010 (Power quality definitions)
|
|
106
|
+
"""
|
|
107
|
+
v_data = voltage.data
|
|
108
|
+
i_data = current.data
|
|
109
|
+
|
|
110
|
+
# Ensure same length
|
|
111
|
+
min_len = min(len(v_data), len(i_data))
|
|
112
|
+
v_data = v_data[:min_len]
|
|
113
|
+
i_data = i_data[:min_len]
|
|
114
|
+
|
|
115
|
+
# Calculate RMS values
|
|
116
|
+
v_rms = float(np.sqrt(np.mean(v_data**2)))
|
|
117
|
+
i_rms = float(np.sqrt(np.mean(i_data**2)))
|
|
118
|
+
|
|
119
|
+
# Calculate phase angle
|
|
120
|
+
phi = phase_angle(voltage, current)
|
|
121
|
+
|
|
122
|
+
return v_rms * i_rms * np.sin(phi) # type: ignore[no-any-return]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def apparent_power(
|
|
126
|
+
voltage: WaveformTrace,
|
|
127
|
+
current: WaveformTrace,
|
|
128
|
+
) -> float:
|
|
129
|
+
"""Calculate apparent power (S) in VA.
|
|
130
|
+
|
|
131
|
+
S = V_rms * I_rms
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
voltage: Voltage waveform trace.
|
|
135
|
+
current: Current waveform trace.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Apparent power in VA.
|
|
139
|
+
|
|
140
|
+
Example:
|
|
141
|
+
>>> s = apparent_power(v_trace, i_trace)
|
|
142
|
+
>>> print(f"Apparent power: {s:.2f} VA")
|
|
143
|
+
|
|
144
|
+
References:
|
|
145
|
+
IEEE 1459-2010 (Power quality definitions)
|
|
146
|
+
"""
|
|
147
|
+
v_data = voltage.data
|
|
148
|
+
i_data = current.data
|
|
149
|
+
|
|
150
|
+
# Ensure same length
|
|
151
|
+
min_len = min(len(v_data), len(i_data))
|
|
152
|
+
v_data = v_data[:min_len]
|
|
153
|
+
i_data = i_data[:min_len]
|
|
154
|
+
|
|
155
|
+
v_rms = float(np.sqrt(np.mean(v_data**2)))
|
|
156
|
+
i_rms = float(np.sqrt(np.mean(i_data**2)))
|
|
157
|
+
|
|
158
|
+
return v_rms * i_rms
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def power_factor(
|
|
162
|
+
voltage: WaveformTrace,
|
|
163
|
+
current: WaveformTrace,
|
|
164
|
+
) -> float:
|
|
165
|
+
"""Calculate power factor (PF = P / S).
|
|
166
|
+
|
|
167
|
+
For sinusoidal waveforms, PF = cos(phi).
|
|
168
|
+
For non-sinusoidal waveforms, includes distortion effects.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
voltage: Voltage waveform trace.
|
|
172
|
+
current: Current waveform trace.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Power factor (0 to 1, can be negative for regeneration).
|
|
176
|
+
|
|
177
|
+
Example:
|
|
178
|
+
>>> pf = power_factor(v_trace, i_trace)
|
|
179
|
+
>>> print(f"Power factor: {pf:.3f}")
|
|
180
|
+
|
|
181
|
+
References:
|
|
182
|
+
IEEE 1459-2010
|
|
183
|
+
"""
|
|
184
|
+
p = average_power(voltage=voltage, current=current)
|
|
185
|
+
s = apparent_power(voltage, current)
|
|
186
|
+
|
|
187
|
+
if s == 0:
|
|
188
|
+
return 0.0
|
|
189
|
+
|
|
190
|
+
return p / s
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def displacement_power_factor(
|
|
194
|
+
voltage: WaveformTrace,
|
|
195
|
+
current: WaveformTrace,
|
|
196
|
+
) -> float:
|
|
197
|
+
"""Calculate displacement power factor (DPF).
|
|
198
|
+
|
|
199
|
+
DPF = cos(phi) where phi is the phase angle between fundamental
|
|
200
|
+
components of voltage and current.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
voltage: Voltage waveform trace.
|
|
204
|
+
current: Current waveform trace.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Displacement power factor.
|
|
208
|
+
|
|
209
|
+
Example:
|
|
210
|
+
>>> dpf = displacement_power_factor(v_trace, i_trace)
|
|
211
|
+
"""
|
|
212
|
+
# Extract fundamental components
|
|
213
|
+
v_fund = _extract_fundamental(voltage)
|
|
214
|
+
i_fund = _extract_fundamental(current)
|
|
215
|
+
|
|
216
|
+
# Calculate phase angle of fundamentals
|
|
217
|
+
phi = phase_angle(v_fund, i_fund)
|
|
218
|
+
|
|
219
|
+
return float(np.cos(phi))
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def distortion_power_factor(
|
|
223
|
+
voltage: WaveformTrace,
|
|
224
|
+
current: WaveformTrace,
|
|
225
|
+
) -> float:
|
|
226
|
+
"""Calculate distortion power factor.
|
|
227
|
+
|
|
228
|
+
Distortion PF = True PF / Displacement PF
|
|
229
|
+
= sqrt(1 / (1 + THD_i^2)) (for sinusoidal voltage)
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
voltage: Voltage waveform trace.
|
|
233
|
+
current: Current waveform trace.
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Distortion power factor.
|
|
237
|
+
|
|
238
|
+
Example:
|
|
239
|
+
>>> dist_pf = distortion_power_factor(v_trace, i_trace)
|
|
240
|
+
"""
|
|
241
|
+
pf = power_factor(voltage, current)
|
|
242
|
+
dpf = displacement_power_factor(voltage, current)
|
|
243
|
+
|
|
244
|
+
if dpf == 0:
|
|
245
|
+
return 0.0
|
|
246
|
+
|
|
247
|
+
return pf / dpf
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def total_harmonic_distortion_power(
|
|
251
|
+
trace: WaveformTrace,
|
|
252
|
+
fundamental_freq: float | None = None,
|
|
253
|
+
max_harmonic: int = 50,
|
|
254
|
+
) -> float:
|
|
255
|
+
"""Calculate Total Harmonic Distortion for power analysis.
|
|
256
|
+
|
|
257
|
+
THD = sqrt(sum(V_h^2 for h=2..N)) / V_1
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
trace: Voltage or current waveform.
|
|
261
|
+
fundamental_freq: Fundamental frequency. If None, auto-detect.
|
|
262
|
+
max_harmonic: Maximum harmonic order to include.
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
THD as a ratio (not percentage).
|
|
266
|
+
|
|
267
|
+
Example:
|
|
268
|
+
>>> thd = total_harmonic_distortion_power(current_trace)
|
|
269
|
+
>>> print(f"Current THD: {thd*100:.1f}%")
|
|
270
|
+
"""
|
|
271
|
+
data = trace.data
|
|
272
|
+
sample_rate = trace.metadata.sample_rate
|
|
273
|
+
|
|
274
|
+
# FFT
|
|
275
|
+
n = len(data)
|
|
276
|
+
fft_result = np.fft.rfft(data)
|
|
277
|
+
freqs = np.fft.rfftfreq(n, 1 / sample_rate)
|
|
278
|
+
|
|
279
|
+
# Find fundamental
|
|
280
|
+
if fundamental_freq is None:
|
|
281
|
+
# Auto-detect: find largest peak above DC
|
|
282
|
+
magnitudes = np.abs(fft_result[1:])
|
|
283
|
+
fund_idx = int(np.argmax(magnitudes)) + 1
|
|
284
|
+
fundamental_freq = freqs[fund_idx]
|
|
285
|
+
else:
|
|
286
|
+
fund_idx = int(np.round(fundamental_freq * n / sample_rate))
|
|
287
|
+
|
|
288
|
+
# Get fundamental magnitude
|
|
289
|
+
v1 = np.abs(fft_result[fund_idx])
|
|
290
|
+
if v1 == 0:
|
|
291
|
+
return 0.0
|
|
292
|
+
|
|
293
|
+
# Sum harmonic magnitudes
|
|
294
|
+
harmonic_sum_sq = 0.0
|
|
295
|
+
for h in range(2, max_harmonic + 1):
|
|
296
|
+
h_idx = h * fund_idx
|
|
297
|
+
if h_idx < len(fft_result):
|
|
298
|
+
harmonic_sum_sq += np.abs(fft_result[h_idx]) ** 2
|
|
299
|
+
|
|
300
|
+
return float(np.sqrt(harmonic_sum_sq) / v1)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _extract_fundamental(trace: WaveformTrace) -> WaveformTrace:
|
|
304
|
+
"""Extract fundamental component of a waveform."""
|
|
305
|
+
data = trace.data
|
|
306
|
+
n = len(data)
|
|
307
|
+
|
|
308
|
+
# FFT
|
|
309
|
+
fft_result = np.fft.rfft(data)
|
|
310
|
+
|
|
311
|
+
# Find fundamental peak
|
|
312
|
+
magnitudes = np.abs(fft_result[1:])
|
|
313
|
+
fund_idx = np.argmax(magnitudes) + 1
|
|
314
|
+
|
|
315
|
+
# Zero out all but fundamental
|
|
316
|
+
filtered_fft = np.zeros_like(fft_result)
|
|
317
|
+
filtered_fft[fund_idx] = fft_result[fund_idx]
|
|
318
|
+
|
|
319
|
+
# Inverse FFT
|
|
320
|
+
fundamental = np.fft.irfft(filtered_fft, n=n)
|
|
321
|
+
|
|
322
|
+
return WaveformTrace(
|
|
323
|
+
data=fundamental.astype(np.float64),
|
|
324
|
+
metadata=trace.metadata,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def three_phase_power(
|
|
329
|
+
v_a: WaveformTrace,
|
|
330
|
+
v_b: WaveformTrace,
|
|
331
|
+
v_c: WaveformTrace,
|
|
332
|
+
i_a: WaveformTrace,
|
|
333
|
+
i_b: WaveformTrace,
|
|
334
|
+
i_c: WaveformTrace,
|
|
335
|
+
) -> dict[str, float]:
|
|
336
|
+
"""Calculate three-phase power quantities.
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
v_a: Phase A voltage trace.
|
|
340
|
+
v_b: Phase B voltage trace.
|
|
341
|
+
v_c: Phase C voltage trace.
|
|
342
|
+
i_a: Phase A current trace.
|
|
343
|
+
i_b: Phase B current trace.
|
|
344
|
+
i_c: Phase C current trace.
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
Dictionary with:
|
|
348
|
+
- total_active: Total active power (W)
|
|
349
|
+
- total_reactive: Total reactive power (VAR)
|
|
350
|
+
- total_apparent: Total apparent power (VA)
|
|
351
|
+
- power_factor: Three-phase power factor
|
|
352
|
+
- phase_a_power: Phase A active power
|
|
353
|
+
- phase_b_power: Phase B active power
|
|
354
|
+
- phase_c_power: Phase C active power
|
|
355
|
+
"""
|
|
356
|
+
# Calculate per-phase powers
|
|
357
|
+
p_a = average_power(voltage=v_a, current=i_a)
|
|
358
|
+
p_b = average_power(voltage=v_b, current=i_b)
|
|
359
|
+
p_c = average_power(voltage=v_c, current=i_c)
|
|
360
|
+
|
|
361
|
+
q_a = reactive_power(v_a, i_a)
|
|
362
|
+
q_b = reactive_power(v_b, i_b)
|
|
363
|
+
q_c = reactive_power(v_c, i_c)
|
|
364
|
+
|
|
365
|
+
total_p = p_a + p_b + p_c
|
|
366
|
+
total_q = q_a + q_b + q_c
|
|
367
|
+
total_s = np.sqrt(total_p**2 + total_q**2)
|
|
368
|
+
|
|
369
|
+
pf = total_p / total_s if total_s != 0 else 0.0
|
|
370
|
+
|
|
371
|
+
return {
|
|
372
|
+
"total_active": total_p,
|
|
373
|
+
"total_reactive": total_q,
|
|
374
|
+
"total_apparent": total_s,
|
|
375
|
+
"power_factor": pf,
|
|
376
|
+
"phase_a_power": p_a,
|
|
377
|
+
"phase_b_power": p_b,
|
|
378
|
+
"phase_c_power": p_c,
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
__all__ = [
|
|
383
|
+
"apparent_power",
|
|
384
|
+
"displacement_power_factor",
|
|
385
|
+
"distortion_power_factor",
|
|
386
|
+
"phase_angle",
|
|
387
|
+
"power_factor",
|
|
388
|
+
"reactive_power",
|
|
389
|
+
"three_phase_power",
|
|
390
|
+
"total_harmonic_distortion_power",
|
|
391
|
+
]
|