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.
Files changed (465) hide show
  1. oscura/__init__.py +813 -8
  2. oscura/__main__.py +392 -0
  3. oscura/analyzers/__init__.py +37 -0
  4. oscura/analyzers/digital/__init__.py +177 -0
  5. oscura/analyzers/digital/bus.py +691 -0
  6. oscura/analyzers/digital/clock.py +805 -0
  7. oscura/analyzers/digital/correlation.py +720 -0
  8. oscura/analyzers/digital/edges.py +632 -0
  9. oscura/analyzers/digital/extraction.py +413 -0
  10. oscura/analyzers/digital/quality.py +878 -0
  11. oscura/analyzers/digital/signal_quality.py +877 -0
  12. oscura/analyzers/digital/thresholds.py +708 -0
  13. oscura/analyzers/digital/timing.py +1104 -0
  14. oscura/analyzers/eye/__init__.py +46 -0
  15. oscura/analyzers/eye/diagram.py +434 -0
  16. oscura/analyzers/eye/metrics.py +555 -0
  17. oscura/analyzers/jitter/__init__.py +83 -0
  18. oscura/analyzers/jitter/ber.py +333 -0
  19. oscura/analyzers/jitter/decomposition.py +759 -0
  20. oscura/analyzers/jitter/measurements.py +413 -0
  21. oscura/analyzers/jitter/spectrum.py +220 -0
  22. oscura/analyzers/measurements.py +40 -0
  23. oscura/analyzers/packet/__init__.py +171 -0
  24. oscura/analyzers/packet/daq.py +1077 -0
  25. oscura/analyzers/packet/metrics.py +437 -0
  26. oscura/analyzers/packet/parser.py +327 -0
  27. oscura/analyzers/packet/payload.py +2156 -0
  28. oscura/analyzers/packet/payload_analysis.py +1312 -0
  29. oscura/analyzers/packet/payload_extraction.py +236 -0
  30. oscura/analyzers/packet/payload_patterns.py +670 -0
  31. oscura/analyzers/packet/stream.py +359 -0
  32. oscura/analyzers/patterns/__init__.py +266 -0
  33. oscura/analyzers/patterns/clustering.py +1036 -0
  34. oscura/analyzers/patterns/discovery.py +539 -0
  35. oscura/analyzers/patterns/learning.py +797 -0
  36. oscura/analyzers/patterns/matching.py +1091 -0
  37. oscura/analyzers/patterns/periodic.py +650 -0
  38. oscura/analyzers/patterns/sequences.py +767 -0
  39. oscura/analyzers/power/__init__.py +116 -0
  40. oscura/analyzers/power/ac_power.py +391 -0
  41. oscura/analyzers/power/basic.py +383 -0
  42. oscura/analyzers/power/conduction.py +314 -0
  43. oscura/analyzers/power/efficiency.py +297 -0
  44. oscura/analyzers/power/ripple.py +356 -0
  45. oscura/analyzers/power/soa.py +372 -0
  46. oscura/analyzers/power/switching.py +479 -0
  47. oscura/analyzers/protocol/__init__.py +150 -0
  48. oscura/analyzers/protocols/__init__.py +150 -0
  49. oscura/analyzers/protocols/base.py +500 -0
  50. oscura/analyzers/protocols/can.py +620 -0
  51. oscura/analyzers/protocols/can_fd.py +448 -0
  52. oscura/analyzers/protocols/flexray.py +405 -0
  53. oscura/analyzers/protocols/hdlc.py +399 -0
  54. oscura/analyzers/protocols/i2c.py +368 -0
  55. oscura/analyzers/protocols/i2s.py +296 -0
  56. oscura/analyzers/protocols/jtag.py +393 -0
  57. oscura/analyzers/protocols/lin.py +445 -0
  58. oscura/analyzers/protocols/manchester.py +333 -0
  59. oscura/analyzers/protocols/onewire.py +501 -0
  60. oscura/analyzers/protocols/spi.py +334 -0
  61. oscura/analyzers/protocols/swd.py +325 -0
  62. oscura/analyzers/protocols/uart.py +393 -0
  63. oscura/analyzers/protocols/usb.py +495 -0
  64. oscura/analyzers/signal_integrity/__init__.py +63 -0
  65. oscura/analyzers/signal_integrity/embedding.py +294 -0
  66. oscura/analyzers/signal_integrity/equalization.py +370 -0
  67. oscura/analyzers/signal_integrity/sparams.py +484 -0
  68. oscura/analyzers/spectral/__init__.py +53 -0
  69. oscura/analyzers/spectral/chunked.py +273 -0
  70. oscura/analyzers/spectral/chunked_fft.py +571 -0
  71. oscura/analyzers/spectral/chunked_wavelet.py +391 -0
  72. oscura/analyzers/spectral/fft.py +92 -0
  73. oscura/analyzers/statistical/__init__.py +250 -0
  74. oscura/analyzers/statistical/checksum.py +923 -0
  75. oscura/analyzers/statistical/chunked_corr.py +228 -0
  76. oscura/analyzers/statistical/classification.py +778 -0
  77. oscura/analyzers/statistical/entropy.py +1113 -0
  78. oscura/analyzers/statistical/ngrams.py +614 -0
  79. oscura/analyzers/statistics/__init__.py +119 -0
  80. oscura/analyzers/statistics/advanced.py +885 -0
  81. oscura/analyzers/statistics/basic.py +263 -0
  82. oscura/analyzers/statistics/correlation.py +630 -0
  83. oscura/analyzers/statistics/distribution.py +298 -0
  84. oscura/analyzers/statistics/outliers.py +463 -0
  85. oscura/analyzers/statistics/streaming.py +93 -0
  86. oscura/analyzers/statistics/trend.py +520 -0
  87. oscura/analyzers/validation.py +598 -0
  88. oscura/analyzers/waveform/__init__.py +36 -0
  89. oscura/analyzers/waveform/measurements.py +943 -0
  90. oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
  91. oscura/analyzers/waveform/spectral.py +1689 -0
  92. oscura/analyzers/waveform/wavelets.py +298 -0
  93. oscura/api/__init__.py +62 -0
  94. oscura/api/dsl.py +538 -0
  95. oscura/api/fluent.py +571 -0
  96. oscura/api/operators.py +498 -0
  97. oscura/api/optimization.py +392 -0
  98. oscura/api/profiling.py +396 -0
  99. oscura/automotive/__init__.py +73 -0
  100. oscura/automotive/can/__init__.py +52 -0
  101. oscura/automotive/can/analysis.py +356 -0
  102. oscura/automotive/can/checksum.py +250 -0
  103. oscura/automotive/can/correlation.py +212 -0
  104. oscura/automotive/can/discovery.py +355 -0
  105. oscura/automotive/can/message_wrapper.py +375 -0
  106. oscura/automotive/can/models.py +385 -0
  107. oscura/automotive/can/patterns.py +381 -0
  108. oscura/automotive/can/session.py +452 -0
  109. oscura/automotive/can/state_machine.py +300 -0
  110. oscura/automotive/can/stimulus_response.py +461 -0
  111. oscura/automotive/dbc/__init__.py +15 -0
  112. oscura/automotive/dbc/generator.py +156 -0
  113. oscura/automotive/dbc/parser.py +146 -0
  114. oscura/automotive/dtc/__init__.py +30 -0
  115. oscura/automotive/dtc/database.py +3036 -0
  116. oscura/automotive/j1939/__init__.py +14 -0
  117. oscura/automotive/j1939/decoder.py +745 -0
  118. oscura/automotive/loaders/__init__.py +35 -0
  119. oscura/automotive/loaders/asc.py +98 -0
  120. oscura/automotive/loaders/blf.py +77 -0
  121. oscura/automotive/loaders/csv_can.py +136 -0
  122. oscura/automotive/loaders/dispatcher.py +136 -0
  123. oscura/automotive/loaders/mdf.py +331 -0
  124. oscura/automotive/loaders/pcap.py +132 -0
  125. oscura/automotive/obd/__init__.py +14 -0
  126. oscura/automotive/obd/decoder.py +707 -0
  127. oscura/automotive/uds/__init__.py +48 -0
  128. oscura/automotive/uds/decoder.py +265 -0
  129. oscura/automotive/uds/models.py +64 -0
  130. oscura/automotive/visualization.py +369 -0
  131. oscura/batch/__init__.py +55 -0
  132. oscura/batch/advanced.py +627 -0
  133. oscura/batch/aggregate.py +300 -0
  134. oscura/batch/analyze.py +139 -0
  135. oscura/batch/logging.py +487 -0
  136. oscura/batch/metrics.py +556 -0
  137. oscura/builders/__init__.py +41 -0
  138. oscura/builders/signal_builder.py +1131 -0
  139. oscura/cli/__init__.py +14 -0
  140. oscura/cli/batch.py +339 -0
  141. oscura/cli/characterize.py +273 -0
  142. oscura/cli/compare.py +775 -0
  143. oscura/cli/decode.py +551 -0
  144. oscura/cli/main.py +247 -0
  145. oscura/cli/shell.py +350 -0
  146. oscura/comparison/__init__.py +66 -0
  147. oscura/comparison/compare.py +397 -0
  148. oscura/comparison/golden.py +487 -0
  149. oscura/comparison/limits.py +391 -0
  150. oscura/comparison/mask.py +434 -0
  151. oscura/comparison/trace_diff.py +30 -0
  152. oscura/comparison/visualization.py +481 -0
  153. oscura/compliance/__init__.py +70 -0
  154. oscura/compliance/advanced.py +756 -0
  155. oscura/compliance/masks.py +363 -0
  156. oscura/compliance/reporting.py +483 -0
  157. oscura/compliance/testing.py +298 -0
  158. oscura/component/__init__.py +38 -0
  159. oscura/component/impedance.py +365 -0
  160. oscura/component/reactive.py +598 -0
  161. oscura/component/transmission_line.py +312 -0
  162. oscura/config/__init__.py +191 -0
  163. oscura/config/defaults.py +254 -0
  164. oscura/config/loader.py +348 -0
  165. oscura/config/memory.py +271 -0
  166. oscura/config/migration.py +458 -0
  167. oscura/config/pipeline.py +1077 -0
  168. oscura/config/preferences.py +530 -0
  169. oscura/config/protocol.py +875 -0
  170. oscura/config/schema.py +713 -0
  171. oscura/config/settings.py +420 -0
  172. oscura/config/thresholds.py +599 -0
  173. oscura/convenience.py +457 -0
  174. oscura/core/__init__.py +299 -0
  175. oscura/core/audit.py +457 -0
  176. oscura/core/backend_selector.py +405 -0
  177. oscura/core/cache.py +590 -0
  178. oscura/core/cancellation.py +439 -0
  179. oscura/core/confidence.py +225 -0
  180. oscura/core/config.py +506 -0
  181. oscura/core/correlation.py +216 -0
  182. oscura/core/cross_domain.py +422 -0
  183. oscura/core/debug.py +301 -0
  184. oscura/core/edge_cases.py +541 -0
  185. oscura/core/exceptions.py +535 -0
  186. oscura/core/gpu_backend.py +523 -0
  187. oscura/core/lazy.py +832 -0
  188. oscura/core/log_query.py +540 -0
  189. oscura/core/logging.py +931 -0
  190. oscura/core/logging_advanced.py +952 -0
  191. oscura/core/memoize.py +171 -0
  192. oscura/core/memory_check.py +274 -0
  193. oscura/core/memory_guard.py +290 -0
  194. oscura/core/memory_limits.py +336 -0
  195. oscura/core/memory_monitor.py +453 -0
  196. oscura/core/memory_progress.py +465 -0
  197. oscura/core/memory_warnings.py +315 -0
  198. oscura/core/numba_backend.py +362 -0
  199. oscura/core/performance.py +352 -0
  200. oscura/core/progress.py +524 -0
  201. oscura/core/provenance.py +358 -0
  202. oscura/core/results.py +331 -0
  203. oscura/core/types.py +504 -0
  204. oscura/core/uncertainty.py +383 -0
  205. oscura/discovery/__init__.py +52 -0
  206. oscura/discovery/anomaly_detector.py +672 -0
  207. oscura/discovery/auto_decoder.py +415 -0
  208. oscura/discovery/comparison.py +497 -0
  209. oscura/discovery/quality_validator.py +528 -0
  210. oscura/discovery/signal_detector.py +769 -0
  211. oscura/dsl/__init__.py +73 -0
  212. oscura/dsl/commands.py +246 -0
  213. oscura/dsl/interpreter.py +455 -0
  214. oscura/dsl/parser.py +689 -0
  215. oscura/dsl/repl.py +172 -0
  216. oscura/exceptions.py +59 -0
  217. oscura/exploratory/__init__.py +111 -0
  218. oscura/exploratory/error_recovery.py +642 -0
  219. oscura/exploratory/fuzzy.py +513 -0
  220. oscura/exploratory/fuzzy_advanced.py +786 -0
  221. oscura/exploratory/legacy.py +831 -0
  222. oscura/exploratory/parse.py +358 -0
  223. oscura/exploratory/recovery.py +275 -0
  224. oscura/exploratory/sync.py +382 -0
  225. oscura/exploratory/unknown.py +707 -0
  226. oscura/export/__init__.py +25 -0
  227. oscura/export/wireshark/README.md +265 -0
  228. oscura/export/wireshark/__init__.py +47 -0
  229. oscura/export/wireshark/generator.py +312 -0
  230. oscura/export/wireshark/lua_builder.py +159 -0
  231. oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
  232. oscura/export/wireshark/type_mapping.py +165 -0
  233. oscura/export/wireshark/validator.py +105 -0
  234. oscura/exporters/__init__.py +94 -0
  235. oscura/exporters/csv.py +303 -0
  236. oscura/exporters/exporters.py +44 -0
  237. oscura/exporters/hdf5.py +219 -0
  238. oscura/exporters/html_export.py +701 -0
  239. oscura/exporters/json_export.py +291 -0
  240. oscura/exporters/markdown_export.py +367 -0
  241. oscura/exporters/matlab_export.py +354 -0
  242. oscura/exporters/npz_export.py +219 -0
  243. oscura/exporters/spice_export.py +210 -0
  244. oscura/extensibility/__init__.py +131 -0
  245. oscura/extensibility/docs.py +752 -0
  246. oscura/extensibility/extensions.py +1125 -0
  247. oscura/extensibility/logging.py +259 -0
  248. oscura/extensibility/measurements.py +485 -0
  249. oscura/extensibility/plugins.py +414 -0
  250. oscura/extensibility/registry.py +346 -0
  251. oscura/extensibility/templates.py +913 -0
  252. oscura/extensibility/validation.py +651 -0
  253. oscura/filtering/__init__.py +89 -0
  254. oscura/filtering/base.py +563 -0
  255. oscura/filtering/convenience.py +564 -0
  256. oscura/filtering/design.py +725 -0
  257. oscura/filtering/filters.py +32 -0
  258. oscura/filtering/introspection.py +605 -0
  259. oscura/guidance/__init__.py +24 -0
  260. oscura/guidance/recommender.py +429 -0
  261. oscura/guidance/wizard.py +518 -0
  262. oscura/inference/__init__.py +251 -0
  263. oscura/inference/active_learning/README.md +153 -0
  264. oscura/inference/active_learning/__init__.py +38 -0
  265. oscura/inference/active_learning/lstar.py +257 -0
  266. oscura/inference/active_learning/observation_table.py +230 -0
  267. oscura/inference/active_learning/oracle.py +78 -0
  268. oscura/inference/active_learning/teachers/__init__.py +15 -0
  269. oscura/inference/active_learning/teachers/simulator.py +192 -0
  270. oscura/inference/adaptive_tuning.py +453 -0
  271. oscura/inference/alignment.py +653 -0
  272. oscura/inference/bayesian.py +943 -0
  273. oscura/inference/binary.py +1016 -0
  274. oscura/inference/crc_reverse.py +711 -0
  275. oscura/inference/logic.py +288 -0
  276. oscura/inference/message_format.py +1305 -0
  277. oscura/inference/protocol.py +417 -0
  278. oscura/inference/protocol_dsl.py +1084 -0
  279. oscura/inference/protocol_library.py +1230 -0
  280. oscura/inference/sequences.py +809 -0
  281. oscura/inference/signal_intelligence.py +1509 -0
  282. oscura/inference/spectral.py +215 -0
  283. oscura/inference/state_machine.py +634 -0
  284. oscura/inference/stream.py +918 -0
  285. oscura/integrations/__init__.py +59 -0
  286. oscura/integrations/llm.py +1827 -0
  287. oscura/jupyter/__init__.py +32 -0
  288. oscura/jupyter/display.py +268 -0
  289. oscura/jupyter/magic.py +334 -0
  290. oscura/loaders/__init__.py +526 -0
  291. oscura/loaders/binary.py +69 -0
  292. oscura/loaders/configurable.py +1255 -0
  293. oscura/loaders/csv.py +26 -0
  294. oscura/loaders/csv_loader.py +473 -0
  295. oscura/loaders/hdf5.py +9 -0
  296. oscura/loaders/hdf5_loader.py +510 -0
  297. oscura/loaders/lazy.py +370 -0
  298. oscura/loaders/mmap_loader.py +583 -0
  299. oscura/loaders/numpy_loader.py +436 -0
  300. oscura/loaders/pcap.py +432 -0
  301. oscura/loaders/preprocessing.py +368 -0
  302. oscura/loaders/rigol.py +287 -0
  303. oscura/loaders/sigrok.py +321 -0
  304. oscura/loaders/tdms.py +367 -0
  305. oscura/loaders/tektronix.py +711 -0
  306. oscura/loaders/validation.py +584 -0
  307. oscura/loaders/vcd.py +464 -0
  308. oscura/loaders/wav.py +233 -0
  309. oscura/math/__init__.py +45 -0
  310. oscura/math/arithmetic.py +824 -0
  311. oscura/math/interpolation.py +413 -0
  312. oscura/onboarding/__init__.py +39 -0
  313. oscura/onboarding/help.py +498 -0
  314. oscura/onboarding/tutorials.py +405 -0
  315. oscura/onboarding/wizard.py +466 -0
  316. oscura/optimization/__init__.py +19 -0
  317. oscura/optimization/parallel.py +440 -0
  318. oscura/optimization/search.py +532 -0
  319. oscura/pipeline/__init__.py +43 -0
  320. oscura/pipeline/base.py +338 -0
  321. oscura/pipeline/composition.py +242 -0
  322. oscura/pipeline/parallel.py +448 -0
  323. oscura/pipeline/pipeline.py +375 -0
  324. oscura/pipeline/reverse_engineering.py +1119 -0
  325. oscura/plugins/__init__.py +122 -0
  326. oscura/plugins/base.py +272 -0
  327. oscura/plugins/cli.py +497 -0
  328. oscura/plugins/discovery.py +411 -0
  329. oscura/plugins/isolation.py +418 -0
  330. oscura/plugins/lifecycle.py +959 -0
  331. oscura/plugins/manager.py +493 -0
  332. oscura/plugins/registry.py +421 -0
  333. oscura/plugins/versioning.py +372 -0
  334. oscura/py.typed +0 -0
  335. oscura/quality/__init__.py +65 -0
  336. oscura/quality/ensemble.py +740 -0
  337. oscura/quality/explainer.py +338 -0
  338. oscura/quality/scoring.py +616 -0
  339. oscura/quality/warnings.py +456 -0
  340. oscura/reporting/__init__.py +248 -0
  341. oscura/reporting/advanced.py +1234 -0
  342. oscura/reporting/analyze.py +448 -0
  343. oscura/reporting/argument_preparer.py +596 -0
  344. oscura/reporting/auto_report.py +507 -0
  345. oscura/reporting/batch.py +615 -0
  346. oscura/reporting/chart_selection.py +223 -0
  347. oscura/reporting/comparison.py +330 -0
  348. oscura/reporting/config.py +615 -0
  349. oscura/reporting/content/__init__.py +39 -0
  350. oscura/reporting/content/executive.py +127 -0
  351. oscura/reporting/content/filtering.py +191 -0
  352. oscura/reporting/content/minimal.py +257 -0
  353. oscura/reporting/content/verbosity.py +162 -0
  354. oscura/reporting/core.py +508 -0
  355. oscura/reporting/core_formats/__init__.py +17 -0
  356. oscura/reporting/core_formats/multi_format.py +210 -0
  357. oscura/reporting/engine.py +836 -0
  358. oscura/reporting/export.py +366 -0
  359. oscura/reporting/formatting/__init__.py +129 -0
  360. oscura/reporting/formatting/emphasis.py +81 -0
  361. oscura/reporting/formatting/numbers.py +403 -0
  362. oscura/reporting/formatting/standards.py +55 -0
  363. oscura/reporting/formatting.py +466 -0
  364. oscura/reporting/html.py +578 -0
  365. oscura/reporting/index.py +590 -0
  366. oscura/reporting/multichannel.py +296 -0
  367. oscura/reporting/output.py +379 -0
  368. oscura/reporting/pdf.py +373 -0
  369. oscura/reporting/plots.py +731 -0
  370. oscura/reporting/pptx_export.py +360 -0
  371. oscura/reporting/renderers/__init__.py +11 -0
  372. oscura/reporting/renderers/pdf.py +94 -0
  373. oscura/reporting/sections.py +471 -0
  374. oscura/reporting/standards.py +680 -0
  375. oscura/reporting/summary_generator.py +368 -0
  376. oscura/reporting/tables.py +397 -0
  377. oscura/reporting/template_system.py +724 -0
  378. oscura/reporting/templates/__init__.py +15 -0
  379. oscura/reporting/templates/definition.py +205 -0
  380. oscura/reporting/templates/index.html +649 -0
  381. oscura/reporting/templates/index.md +173 -0
  382. oscura/schemas/__init__.py +158 -0
  383. oscura/schemas/bus_configuration.json +322 -0
  384. oscura/schemas/device_mapping.json +182 -0
  385. oscura/schemas/packet_format.json +418 -0
  386. oscura/schemas/protocol_definition.json +363 -0
  387. oscura/search/__init__.py +16 -0
  388. oscura/search/anomaly.py +292 -0
  389. oscura/search/context.py +149 -0
  390. oscura/search/pattern.py +160 -0
  391. oscura/session/__init__.py +34 -0
  392. oscura/session/annotations.py +289 -0
  393. oscura/session/history.py +313 -0
  394. oscura/session/session.py +445 -0
  395. oscura/streaming/__init__.py +43 -0
  396. oscura/streaming/chunked.py +611 -0
  397. oscura/streaming/progressive.py +393 -0
  398. oscura/streaming/realtime.py +622 -0
  399. oscura/testing/__init__.py +54 -0
  400. oscura/testing/synthetic.py +808 -0
  401. oscura/triggering/__init__.py +68 -0
  402. oscura/triggering/base.py +229 -0
  403. oscura/triggering/edge.py +353 -0
  404. oscura/triggering/pattern.py +344 -0
  405. oscura/triggering/pulse.py +581 -0
  406. oscura/triggering/window.py +453 -0
  407. oscura/ui/__init__.py +48 -0
  408. oscura/ui/formatters.py +526 -0
  409. oscura/ui/progressive_display.py +340 -0
  410. oscura/utils/__init__.py +99 -0
  411. oscura/utils/autodetect.py +338 -0
  412. oscura/utils/buffer.py +389 -0
  413. oscura/utils/lazy.py +407 -0
  414. oscura/utils/lazy_imports.py +147 -0
  415. oscura/utils/memory.py +836 -0
  416. oscura/utils/memory_advanced.py +1326 -0
  417. oscura/utils/memory_extensions.py +465 -0
  418. oscura/utils/progressive.py +352 -0
  419. oscura/utils/windowing.py +362 -0
  420. oscura/visualization/__init__.py +321 -0
  421. oscura/visualization/accessibility.py +526 -0
  422. oscura/visualization/annotations.py +374 -0
  423. oscura/visualization/axis_scaling.py +305 -0
  424. oscura/visualization/colors.py +453 -0
  425. oscura/visualization/digital.py +337 -0
  426. oscura/visualization/eye.py +420 -0
  427. oscura/visualization/histogram.py +281 -0
  428. oscura/visualization/interactive.py +858 -0
  429. oscura/visualization/jitter.py +702 -0
  430. oscura/visualization/keyboard.py +394 -0
  431. oscura/visualization/layout.py +365 -0
  432. oscura/visualization/optimization.py +1028 -0
  433. oscura/visualization/palettes.py +446 -0
  434. oscura/visualization/plot.py +92 -0
  435. oscura/visualization/power.py +290 -0
  436. oscura/visualization/power_extended.py +626 -0
  437. oscura/visualization/presets.py +467 -0
  438. oscura/visualization/protocols.py +932 -0
  439. oscura/visualization/render.py +207 -0
  440. oscura/visualization/rendering.py +444 -0
  441. oscura/visualization/reverse_engineering.py +791 -0
  442. oscura/visualization/signal_integrity.py +808 -0
  443. oscura/visualization/specialized.py +553 -0
  444. oscura/visualization/spectral.py +811 -0
  445. oscura/visualization/styles.py +381 -0
  446. oscura/visualization/thumbnails.py +311 -0
  447. oscura/visualization/time_axis.py +351 -0
  448. oscura/visualization/waveform.py +367 -0
  449. oscura/workflow/__init__.py +13 -0
  450. oscura/workflow/dag.py +377 -0
  451. oscura/workflows/__init__.py +58 -0
  452. oscura/workflows/compliance.py +280 -0
  453. oscura/workflows/digital.py +272 -0
  454. oscura/workflows/multi_trace.py +502 -0
  455. oscura/workflows/power.py +178 -0
  456. oscura/workflows/protocol.py +492 -0
  457. oscura/workflows/reverse_engineering.py +639 -0
  458. oscura/workflows/signal_integrity.py +227 -0
  459. oscura-0.1.0.dist-info/METADATA +300 -0
  460. oscura-0.1.0.dist-info/RECORD +463 -0
  461. oscura-0.1.0.dist-info/entry_points.txt +2 -0
  462. {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/licenses/LICENSE +1 -1
  463. oscura-0.0.1.dist-info/METADATA +0 -63
  464. oscura-0.0.1.dist-info/RECORD +0 -5
  465. {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,371 @@
1
+ """Waveform measurements with uncertainty propagation.
2
+
3
+ This module extends the standard measurements module with uncertainty
4
+ estimation following GUM (Guide to the Expression of Uncertainty in Measurement)
5
+ principles.
6
+
7
+ All measurements return MeasurementResult objects that include both the
8
+ value and its associated uncertainty.
9
+
10
+ Example:
11
+ >>> from oscura.analyzers.waveform import measurements_with_uncertainty as meas_u
12
+ >>> result = meas_u.rise_time(trace)
13
+ >>> print(f"Rise time: {result.value*1e9:.2f} ± {result.uncertainty*1e9:.2f} ns")
14
+ Rise time: 2.34 ± 0.12 ns
15
+
16
+ References:
17
+ JCGM 100:2008 - Guide to the Expression of Uncertainty in Measurement (GUM)
18
+ IEEE 181-2011 - Standard for Transitional Waveform Definitions (Annex B: Uncertainty)
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from typing import TYPE_CHECKING
24
+
25
+ import numpy as np
26
+
27
+ from oscura.analyzers.waveform import measurements as meas
28
+ from oscura.core.uncertainty import MeasurementWithUncertainty, UncertaintyEstimator
29
+
30
+ if TYPE_CHECKING:
31
+ from oscura.core.types import WaveformTrace
32
+
33
+
34
+ def rise_time(
35
+ trace: WaveformTrace,
36
+ *,
37
+ ref_levels: tuple[float, float] = (0.1, 0.9),
38
+ include_uncertainty: bool = True,
39
+ ) -> MeasurementWithUncertainty:
40
+ """Measure rise time with uncertainty estimation.
41
+
42
+ Uncertainty sources:
43
+ - Time base accuracy (from calibration info if available)
44
+ - Sample interpolation error (sub-sample timing)
45
+ - Noise-induced edge jitter (from signal SNR)
46
+
47
+ Args:
48
+ trace: Input waveform trace.
49
+ ref_levels: Reference levels as fractions (0.0 to 1.0).
50
+ include_uncertainty: If False, only return value estimate (faster).
51
+
52
+ Returns:
53
+ MeasurementResult with value and uncertainty.
54
+
55
+ Example:
56
+ >>> result = rise_time(trace)
57
+ >>> print(f"t_rise = {result.value*1e9:.2f} ± {result.uncertainty*1e9:.2f} ns")
58
+
59
+ References:
60
+ IEEE 181-2011 Section 5.2 (rise time)
61
+ IEEE 181-2011 Annex B (measurement uncertainty)
62
+ """
63
+ # Get the measurement value
64
+ value = meas.rise_time(trace, ref_levels=ref_levels)
65
+
66
+ if not include_uncertainty or np.isnan(value):
67
+ return MeasurementWithUncertainty(value=float(value), uncertainty=float(np.nan), unit="s")
68
+
69
+ # Estimate uncertainty components
70
+ uncertainties = []
71
+
72
+ # 1. Time base uncertainty (Type B)
73
+ if trace.metadata.calibration_info is not None:
74
+ # Use calibration info if available
75
+ # Typical scope: 25-50 ppm timebase accuracy
76
+ timebase_ppm = 25.0 # Conservative estimate
77
+ u_timebase = UncertaintyEstimator.time_base_uncertainty(
78
+ trace.metadata.sample_rate, timebase_ppm
79
+ )
80
+ # Rise time involves 2 samples (start and stop), so uncertainty scales
81
+ u_timebase_rise = u_timebase * np.sqrt(2)
82
+ uncertainties.append(u_timebase_rise)
83
+ else:
84
+ # No calibration info - use conservative estimate
85
+ u_timebase_rise = (1.0 / trace.metadata.sample_rate) * 50e-6 # 50 ppm
86
+ uncertainties.append(u_timebase_rise)
87
+
88
+ # 2. Interpolation uncertainty (Type B - rectangular distribution)
89
+ # Linear interpolation error: typically ±0.5 samples worst case
90
+ sample_period = trace.metadata.time_base
91
+ u_interp = UncertaintyEstimator.type_b_rectangular(0.5 * sample_period)
92
+ uncertainties.append(u_interp)
93
+
94
+ # 3. Noise-induced uncertainty (Type A equivalent)
95
+ # Estimate from local signal noise
96
+ # Find the data region near the edge
97
+ data_slice = trace.data # Could refine to edge region
98
+ if len(data_slice) > 10:
99
+ noise_estimate = np.std(data_slice[:10]) if len(data_slice) >= 10 else 0.0
100
+ # Noise-to-slew-rate ratio gives time uncertainty
101
+ amplitude = np.ptp(trace.data)
102
+ if amplitude > 0:
103
+ # Approximate slew rate: amplitude / rise_time
104
+ slew_rate = amplitude / value if value > 0 else np.inf
105
+ u_noise = noise_estimate / slew_rate if slew_rate != np.inf else 0.0
106
+ uncertainties.append(u_noise)
107
+
108
+ # Combine all uncertainty sources (uncorrelated)
109
+ total_uncertainty = UncertaintyEstimator.combined_uncertainty(uncertainties)
110
+
111
+ return MeasurementWithUncertainty(
112
+ value=float(value),
113
+ uncertainty=total_uncertainty,
114
+ unit="s",
115
+ n_samples=len(trace.data),
116
+ )
117
+
118
+
119
+ def fall_time(
120
+ trace: WaveformTrace,
121
+ *,
122
+ ref_levels: tuple[float, float] = (0.9, 0.1),
123
+ include_uncertainty: bool = True,
124
+ ) -> MeasurementWithUncertainty:
125
+ """Measure fall time with uncertainty estimation.
126
+
127
+ Similar uncertainty sources as rise_time().
128
+
129
+ Args:
130
+ trace: Input waveform trace.
131
+ ref_levels: Reference levels as fractions (0.0 to 1.0).
132
+ include_uncertainty: If False, only return value estimate (faster).
133
+
134
+ Returns:
135
+ MeasurementResult with value and uncertainty.
136
+
137
+ References:
138
+ IEEE 181-2011 Section 5.2
139
+ """
140
+ value = meas.fall_time(trace, ref_levels=ref_levels)
141
+
142
+ if not include_uncertainty or np.isnan(value):
143
+ return MeasurementWithUncertainty(value=float(value), uncertainty=float(np.nan), unit="s")
144
+
145
+ # Similar uncertainty calculation as rise_time
146
+ uncertainties = []
147
+
148
+ # Time base uncertainty
149
+ timebase_ppm = 25.0
150
+ u_timebase = UncertaintyEstimator.time_base_uncertainty(
151
+ trace.metadata.sample_rate, timebase_ppm
152
+ )
153
+ uncertainties.append(u_timebase * np.sqrt(2))
154
+
155
+ # Interpolation uncertainty
156
+ sample_period = trace.metadata.time_base
157
+ u_interp = UncertaintyEstimator.type_b_rectangular(0.5 * sample_period)
158
+ uncertainties.append(u_interp)
159
+
160
+ total_uncertainty = UncertaintyEstimator.combined_uncertainty(uncertainties)
161
+
162
+ return MeasurementWithUncertainty(
163
+ value=float(value),
164
+ uncertainty=total_uncertainty,
165
+ unit="s",
166
+ n_samples=len(trace.data),
167
+ )
168
+
169
+
170
+ def frequency(
171
+ trace: WaveformTrace, *, include_uncertainty: bool = True
172
+ ) -> MeasurementWithUncertainty:
173
+ """Measure frequency with uncertainty estimation.
174
+
175
+ Uncertainty sources:
176
+ - Time base accuracy
177
+ - Period measurement uncertainty
178
+ - Allan variance (short-term stability)
179
+
180
+ Args:
181
+ trace: Input waveform trace.
182
+ include_uncertainty: If False, only return value estimate (faster).
183
+
184
+ Returns:
185
+ MeasurementResult with value and uncertainty in Hz.
186
+
187
+ Example:
188
+ >>> result = frequency(trace)
189
+ >>> print(f"f = {result.value/1e6:.6f} ± {result.relative_uncertainty*100:.2f}% MHz")
190
+
191
+ References:
192
+ IEEE 181-2011 Section 5.3
193
+ IEEE 1057-2017 Section 4.3
194
+ """
195
+ value = meas.frequency(trace)
196
+
197
+ if not include_uncertainty or np.isnan(value):
198
+ return MeasurementWithUncertainty(value=float(value), uncertainty=float(np.nan), unit="Hz")
199
+
200
+ # Frequency is 1/period, so uncertainty propagation:
201
+ # u(f) = f^2 * u(T) where T is period
202
+ period = 1.0 / value if value != 0 else np.nan
203
+
204
+ if np.isnan(period):
205
+ return MeasurementWithUncertainty(value=float(value), uncertainty=float(np.nan), unit="Hz")
206
+
207
+ # Estimate period uncertainty
208
+ uncertainties = []
209
+
210
+ # Time base uncertainty
211
+ timebase_ppm = 25.0
212
+ # Period measurement spans multiple cycles, typically more accurate
213
+ u_period_timebase = period * (timebase_ppm * 1e-6)
214
+ uncertainties.append(u_period_timebase)
215
+
216
+ # Interpolation uncertainty for edge detection
217
+ sample_period = trace.metadata.time_base
218
+ u_interp = UncertaintyEstimator.type_b_rectangular(0.5 * sample_period)
219
+ # Two edges per period
220
+ u_period_interp = u_interp * np.sqrt(2)
221
+ uncertainties.append(u_period_interp)
222
+
223
+ # Combine to get period uncertainty
224
+ u_period = UncertaintyEstimator.combined_uncertainty([float(u) for u in uncertainties])
225
+
226
+ # Propagate to frequency: u(f) = |df/dT| * u(T) = f^2 * u(T)
227
+ u_frequency = float((value**2) * u_period)
228
+
229
+ return MeasurementWithUncertainty(
230
+ value=float(value), uncertainty=u_frequency, unit="Hz", n_samples=len(trace.data)
231
+ )
232
+
233
+
234
+ def amplitude(
235
+ trace: WaveformTrace, *, include_uncertainty: bool = True
236
+ ) -> MeasurementWithUncertainty:
237
+ """Measure amplitude (Vpp) with uncertainty estimation.
238
+
239
+ Uncertainty sources:
240
+ - Vertical gain accuracy (from calibration info)
241
+ - Vertical offset error
242
+ - Quantization noise (ADC resolution)
243
+ - Signal noise (statistical)
244
+
245
+ Args:
246
+ trace: Input waveform trace.
247
+ include_uncertainty: If False, only return value estimate (faster).
248
+
249
+ Returns:
250
+ MeasurementResult with value and uncertainty in volts.
251
+
252
+ References:
253
+ IEEE 1057-2017 Section 4.2 (amplitude measurement)
254
+ IEEE 1057-2017 Section 4.4 (amplitude accuracy)
255
+ """
256
+ value = meas.amplitude(trace)
257
+
258
+ if not include_uncertainty or np.isnan(value):
259
+ return MeasurementWithUncertainty(value=float(value), uncertainty=float(np.nan), unit="V")
260
+
261
+ uncertainties = []
262
+
263
+ # 1. Vertical accuracy (Type B)
264
+ # Typical scope: ±2% of reading ± 0.1% of full scale
265
+ vertical_accuracy_pct = 2.0 # Conservative
266
+ if trace.metadata.vertical_scale is not None:
267
+ full_scale = trace.metadata.vertical_scale * 10 # 10 divisions typical
268
+ offset_error = full_scale * 0.001 # 0.1%
269
+ else:
270
+ offset_error = 0.001 # 1 mV default
271
+
272
+ u_vertical = UncertaintyEstimator.vertical_uncertainty(
273
+ float(value), vertical_accuracy_pct, offset_error
274
+ )
275
+ uncertainties.append(u_vertical)
276
+
277
+ # 2. Quantization uncertainty (Type B - rectangular)
278
+ if (
279
+ trace.metadata.calibration_info is not None
280
+ and trace.metadata.calibration_info.vertical_resolution is not None
281
+ ):
282
+ bits = trace.metadata.calibration_info.vertical_resolution
283
+ vertical_range = np.ptp(trace.data) # Simplification
284
+ lsb = vertical_range / (2**bits)
285
+ u_quant = UncertaintyEstimator.type_b_rectangular(0.5 * lsb)
286
+ uncertainties.append(u_quant)
287
+ else:
288
+ # Default: 8-bit ADC assumption
289
+ vertical_range = np.ptp(trace.data)
290
+ lsb = vertical_range / 256
291
+ u_quant = UncertaintyEstimator.type_b_rectangular(0.5 * lsb)
292
+ uncertainties.append(u_quant)
293
+
294
+ # 3. Signal noise (Type A)
295
+ # Estimate from flat regions (if available)
296
+ # Simplified: use standard deviation as proxy
297
+ if len(trace.data) > 100:
298
+ # Sample first and last 50 points (assume flat regions)
299
+ noise_start = np.std(trace.data[:50])
300
+ noise_end = np.std(trace.data[-50:])
301
+ u_noise = np.mean([noise_start, noise_end])
302
+ # Amplitude involves max and min, so sqrt(2) factor
303
+ uncertainties.append(u_noise * np.sqrt(2))
304
+
305
+ total_uncertainty = UncertaintyEstimator.combined_uncertainty(uncertainties)
306
+
307
+ return MeasurementWithUncertainty(
308
+ value=float(value),
309
+ uncertainty=total_uncertainty,
310
+ unit="V",
311
+ n_samples=len(trace.data),
312
+ )
313
+
314
+
315
+ def rms(
316
+ trace: WaveformTrace,
317
+ *,
318
+ ac_coupled: bool = False,
319
+ include_uncertainty: bool = True,
320
+ ) -> MeasurementWithUncertainty:
321
+ """Measure RMS voltage with uncertainty estimation.
322
+
323
+ Args:
324
+ trace: Input waveform trace.
325
+ ac_coupled: If True, remove DC component before calculating RMS.
326
+ include_uncertainty: If False, only return value estimate (faster).
327
+
328
+ Returns:
329
+ MeasurementResult with value and uncertainty in volts RMS.
330
+
331
+ References:
332
+ IEEE 1057-2017 Section 4.3
333
+ """
334
+ value = meas.rms(trace, ac_coupled=ac_coupled)
335
+
336
+ if not include_uncertainty or np.isnan(value):
337
+ return MeasurementWithUncertainty(value=float(value), uncertainty=float(np.nan), unit="V")
338
+
339
+ uncertainties = []
340
+
341
+ # Vertical accuracy
342
+ vertical_accuracy_pct = 2.0
343
+ offset_error = 0.001 # 1 mV
344
+ u_vertical = UncertaintyEstimator.vertical_uncertainty(
345
+ float(value), vertical_accuracy_pct, offset_error
346
+ )
347
+ uncertainties.append(u_vertical)
348
+
349
+ # Statistical uncertainty (Type A)
350
+ # RMS of N samples: u(RMS) ≈ RMS / sqrt(2N) for Gaussian noise
351
+ n = len(trace.data)
352
+ u_statistical = value / np.sqrt(2 * n) if n > 0 else 0.0
353
+ uncertainties.append(u_statistical)
354
+
355
+ total_uncertainty = UncertaintyEstimator.combined_uncertainty(uncertainties)
356
+
357
+ return MeasurementWithUncertainty(
358
+ value=float(value),
359
+ uncertainty=total_uncertainty,
360
+ unit="V",
361
+ n_samples=len(trace.data),
362
+ )
363
+
364
+
365
+ __all__ = [
366
+ "amplitude",
367
+ "fall_time",
368
+ "frequency",
369
+ "rise_time",
370
+ "rms",
371
+ ]