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,333 @@
1
+ """BER-related jitter analysis functions.
2
+
3
+ This module provides total jitter at BER calculations, bathtub curve
4
+ generation, and eye opening measurements using the dual-Dirac model.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.analyzers.jitter.ber import tj_at_ber, bathtub_curve
9
+ >>> tj = tj_at_ber(rj_rms=1e-12, dj_pp=10e-12, ber=1e-12)
10
+ >>> positions, ber_values = bathtub_curve(tie_data, unit_interval=1e-9)
11
+
12
+ References:
13
+ IEEE 2414-2020: Standard for Jitter and Phase Noise
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from dataclasses import dataclass
19
+ from typing import TYPE_CHECKING
20
+
21
+ import numpy as np
22
+ from scipy import special
23
+
24
+ if TYPE_CHECKING:
25
+ from numpy.typing import NDArray
26
+
27
+
28
+ @dataclass
29
+ class BathtubCurveResult:
30
+ """Result of bathtub curve generation.
31
+
32
+ Attributes:
33
+ positions: Sampling positions in UI (0.0 to 1.0).
34
+ ber_left: BER values for left side of eye.
35
+ ber_right: BER values for right side of eye.
36
+ ber_total: Combined BER (left + right).
37
+ eye_opening: Eye opening in UI at specified target BER.
38
+ target_ber: Target BER for eye opening calculation.
39
+ unit_interval: Unit interval in seconds.
40
+ """
41
+
42
+ positions: NDArray[np.float64]
43
+ ber_left: NDArray[np.float64]
44
+ ber_right: NDArray[np.float64]
45
+ ber_total: NDArray[np.float64]
46
+ eye_opening: float
47
+ target_ber: float
48
+ unit_interval: float
49
+
50
+
51
+ def q_factor_from_ber(ber: float) -> float:
52
+ """Calculate Q-factor from target BER.
53
+
54
+ The Q-factor is the number of standard deviations from the mean
55
+ for a Gaussian distribution to achieve the target BER.
56
+
57
+ Args:
58
+ ber: Bit error rate (e.g., 1e-12).
59
+
60
+ Returns:
61
+ Q-factor value.
62
+
63
+ Example:
64
+ >>> q = q_factor_from_ber(1e-12)
65
+ >>> print(f"Q(1e-12) = {q:.3f}") # ~7.034
66
+
67
+ References:
68
+ IEEE 2414-2020: Q = sqrt(2) * erfc_inv(2 * BER)
69
+ """
70
+ if ber <= 0 or ber >= 0.5:
71
+ return np.nan # type: ignore[no-any-return]
72
+
73
+ # BER = 0.5 * erfc(Q / sqrt(2))
74
+ # erfc(Q / sqrt(2)) = 2 * BER
75
+ # Q / sqrt(2) = erfc_inv(2 * BER)
76
+ # Q = sqrt(2) * erfc_inv(2 * BER)
77
+
78
+ q = np.sqrt(2) * special.erfcinv(2 * ber)
79
+ return float(q)
80
+
81
+
82
+ def ber_from_q_factor(q: float) -> float:
83
+ """Calculate BER from Q-factor.
84
+
85
+ Args:
86
+ q: Q-factor value.
87
+
88
+ Returns:
89
+ Bit error rate.
90
+
91
+ Example:
92
+ >>> ber = ber_from_q_factor(7.034)
93
+ >>> print(f"BER = {ber:.2e}") # ~1e-12
94
+ """
95
+ if q <= 0:
96
+ return 0.5
97
+
98
+ # BER = 0.5 * erfc(Q / sqrt(2))
99
+ ber = 0.5 * special.erfc(q / np.sqrt(2))
100
+ return float(ber)
101
+
102
+
103
+ def tj_at_ber(
104
+ rj_rms: float,
105
+ dj_pp: float,
106
+ ber: float = 1e-12,
107
+ ) -> float:
108
+ """Calculate total jitter at specified BER using dual-Dirac model.
109
+
110
+ The dual-Dirac model combines random and deterministic jitter:
111
+ TJ(BER) = 2 * Q(BER) * RJ_rms + DJ_pp
112
+
113
+ Common Q values:
114
+ - Q(1e-12) = 7.034
115
+ - Q(1e-15) = 7.941
116
+
117
+ Args:
118
+ rj_rms: Random jitter RMS in seconds.
119
+ dj_pp: Deterministic jitter peak-to-peak in seconds.
120
+ ber: Target bit error rate (default 1e-12).
121
+
122
+ Returns:
123
+ Total jitter in seconds at specified BER.
124
+
125
+ Raises:
126
+ ValueError: If rj_rms is negative.
127
+
128
+ Example:
129
+ >>> tj = tj_at_ber(rj_rms=1e-12, dj_pp=10e-12, ber=1e-12)
130
+ >>> print(f"TJ@1e-12: {tj * 1e12:.2f} ps")
131
+
132
+ References:
133
+ IEEE 2414-2020 Section 6.6
134
+ """
135
+ if rj_rms < 0:
136
+ raise ValueError("RJ must be non-negative")
137
+
138
+ if dj_pp < 0:
139
+ raise ValueError("DJ must be non-negative")
140
+
141
+ q = q_factor_from_ber(ber)
142
+
143
+ if np.isnan(q):
144
+ return np.nan # type: ignore[no-any-return]
145
+
146
+ # TJ = 2 * Q * RJ_rms + DJ_pp
147
+ tj = 2 * q * rj_rms + dj_pp
148
+
149
+ return tj
150
+
151
+
152
+ def bathtub_curve(
153
+ tie_data: NDArray[np.float64],
154
+ unit_interval: float,
155
+ *,
156
+ n_points: int = 100,
157
+ target_ber: float = 1e-12,
158
+ rj_rms: float | None = None,
159
+ dj_delta: float | None = None,
160
+ ) -> BathtubCurveResult:
161
+ """Generate bathtub curve showing BER vs. sampling position.
162
+
163
+ The bathtub curve shows how bit error rate varies across the
164
+ unit interval, with low BER in the center (eye opening) and
165
+ high BER near the edges.
166
+
167
+ Args:
168
+ tie_data: Time Interval Error data in seconds.
169
+ unit_interval: Unit interval (bit period) in seconds.
170
+ n_points: Number of points in the curve.
171
+ target_ber: Target BER for eye opening calculation.
172
+ rj_rms: Pre-computed RJ (extracted from data if None).
173
+ dj_delta: Pre-computed DJ delta (extracted from data if None).
174
+
175
+ Returns:
176
+ BathtubCurveResult with position and BER arrays.
177
+
178
+ Example:
179
+ >>> result = bathtub_curve(tie_data, unit_interval=1e-9)
180
+ >>> print(f"Eye opening: {result.eye_opening:.3f} UI at BER=1e-12")
181
+
182
+ References:
183
+ IEEE 2414-2020 Section 6.7
184
+ """
185
+ from oscura.analyzers.jitter.decomposition import extract_dj, extract_rj
186
+
187
+ valid_data = tie_data[~np.isnan(tie_data)]
188
+
189
+ # Normalize TIE to UI
190
+ valid_data / unit_interval
191
+
192
+ # Extract jitter components if not provided
193
+ if rj_rms is None or dj_delta is None:
194
+ try:
195
+ rj_result = extract_rj(valid_data, min_samples=100)
196
+ rj_rms = rj_result.rj_rms
197
+ except Exception:
198
+ rj_rms = np.std(valid_data)
199
+
200
+ try:
201
+ dj_result = extract_dj(valid_data, min_samples=100)
202
+ dj_delta = dj_result.dj_delta
203
+ except Exception:
204
+ dj_delta = 0.0
205
+
206
+ # Convert to UI
207
+ sigma_ui = rj_rms / unit_interval
208
+ delta_ui = dj_delta / unit_interval
209
+
210
+ # Generate sampling positions (0 to 1 UI)
211
+ positions = np.linspace(0, 1, n_points)
212
+
213
+ # Calculate BER at each position using dual-Dirac model
214
+ # Left side: probability of sampling a '1' when '0' is sent
215
+ # Right side: probability of sampling a '0' when '1' is sent
216
+
217
+ # For a dual-Dirac distribution centered at 0.5 UI:
218
+ # Left Dirac at 0.5 - delta, Right Dirac at 0.5 + delta
219
+
220
+ ber_left = np.zeros(n_points)
221
+ ber_right = np.zeros(n_points)
222
+
223
+ for i, pos in enumerate(positions):
224
+ # Left BER: Q-function from left edge
225
+ if sigma_ui > 0:
226
+ # Distance from left edge to sampling point
227
+ q_left = (pos - delta_ui) / sigma_ui
228
+ ber_left[i] = 0.5 * special.erfc(q_left / np.sqrt(2))
229
+
230
+ # Distance from right edge to sampling point
231
+ q_right = (1 - pos - delta_ui) / sigma_ui
232
+ ber_right[i] = 0.5 * special.erfc(q_right / np.sqrt(2))
233
+ else:
234
+ # No random jitter - step function
235
+ ber_left[i] = 0.5 if pos <= delta_ui else 0
236
+ ber_right[i] = 0.5 if pos >= (1 - delta_ui) else 0
237
+
238
+ # Total BER is sum of left and right
239
+ ber_total = ber_left + ber_right
240
+
241
+ # Clip to valid range
242
+ ber_total = np.clip(ber_total, 1e-18, 0.5)
243
+ ber_left = np.clip(ber_left, 1e-18, 0.5)
244
+ ber_right = np.clip(ber_right, 1e-18, 0.5)
245
+
246
+ # Calculate eye opening at target BER
247
+ eye_opening = _calculate_eye_opening(positions, ber_total, target_ber)
248
+
249
+ return BathtubCurveResult(
250
+ positions=positions,
251
+ ber_left=ber_left,
252
+ ber_right=ber_right,
253
+ ber_total=ber_total,
254
+ eye_opening=eye_opening,
255
+ target_ber=target_ber,
256
+ unit_interval=unit_interval,
257
+ )
258
+
259
+
260
+ def _calculate_eye_opening(
261
+ positions: NDArray[np.float64],
262
+ ber: NDArray[np.float64],
263
+ target_ber: float,
264
+ ) -> float:
265
+ """Calculate eye opening at target BER.
266
+
267
+ Args:
268
+ positions: Sampling positions in UI.
269
+ ber: BER values at each position.
270
+ target_ber: Target BER for eye opening.
271
+
272
+ Returns:
273
+ Eye opening in UI.
274
+ """
275
+ # Find positions where BER <= target_ber
276
+ valid_positions = positions[ber <= target_ber]
277
+
278
+ if len(valid_positions) == 0:
279
+ return 0.0
280
+
281
+ # Eye opening is the range of valid positions
282
+ eye_opening = float(np.max(valid_positions) - np.min(valid_positions))
283
+
284
+ return eye_opening
285
+
286
+
287
+ def eye_opening_at_ber(
288
+ rj_rms: float,
289
+ dj_pp: float,
290
+ unit_interval: float,
291
+ target_ber: float = 1e-12,
292
+ ) -> float:
293
+ """Calculate horizontal eye opening at target BER.
294
+
295
+ Uses the dual-Dirac model to calculate the eye opening width
296
+ at a specified BER level.
297
+
298
+ Args:
299
+ rj_rms: Random jitter RMS in seconds.
300
+ dj_pp: Deterministic jitter peak-to-peak in seconds.
301
+ unit_interval: Unit interval in seconds.
302
+ target_ber: Target BER level.
303
+
304
+ Returns:
305
+ Eye opening in UI (0.0 to 1.0).
306
+
307
+ Example:
308
+ >>> opening = eye_opening_at_ber(1e-12, 10e-12, 100e-12, 1e-12)
309
+ >>> print(f"Eye opening: {opening:.3f} UI")
310
+ """
311
+ # Total jitter at BER
312
+ tj = tj_at_ber(rj_rms, dj_pp, target_ber)
313
+
314
+ # Eye opening = UI - TJ
315
+ opening_seconds = unit_interval - tj
316
+
317
+ if opening_seconds <= 0:
318
+ return 0.0
319
+
320
+ # Convert to UI
321
+ opening_ui = opening_seconds / unit_interval
322
+
323
+ return max(0.0, min(1.0, opening_ui))
324
+
325
+
326
+ __all__ = [
327
+ "BathtubCurveResult",
328
+ "bathtub_curve",
329
+ "ber_from_q_factor",
330
+ "eye_opening_at_ber",
331
+ "q_factor_from_ber",
332
+ "tj_at_ber",
333
+ ]