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.
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.1.dist-info/METADATA +300 -0
  460. oscura-0.1.1.dist-info/RECORD +463 -0
  461. oscura-0.1.1.dist-info/entry_points.txt +2 -0
  462. {oscura-0.0.1.dist-info → oscura-0.1.1.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.1.dist-info}/WHEEL +0 -0
oscura/__main__.py ADDED
@@ -0,0 +1,392 @@
1
+ """Oscura command-line interface.
2
+
3
+ This module provides the main entry point for Oscura CLI operations,
4
+ including sample data download.
5
+
6
+
7
+ Example:
8
+ python -m oscura download_samples
9
+ python -m oscura --help
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import argparse
15
+ import hashlib
16
+ import sys
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+
21
+ def get_samples_dir() -> Path:
22
+ """Get the samples directory path (~/.oscura/samples/).
23
+
24
+ Returns:
25
+ Path to the samples directory.
26
+ """
27
+ return Path.home() / ".oscura" / "samples"
28
+
29
+
30
+ def get_sample_files() -> dict[str, dict[str, Any]]:
31
+ """Get the list of sample files to download.
32
+
33
+ Returns:
34
+ Dictionary mapping filename to file metadata.
35
+ """
36
+ # Sample files configuration
37
+ # In production, these would be hosted on a public CDN or GitHub releases
38
+ return {
39
+ "sine_1khz.csv": {
40
+ "description": "1 kHz sine wave, 100 kS/s, CSV format",
41
+ "format": "csv",
42
+ "size": 1024 * 50, # ~50 KB
43
+ "checksum": None, # Would be populated with actual checksum
44
+ "url": "https://raw.githubusercontent.com/oscura/sample-data/main/sine_1khz.csv",
45
+ },
46
+ "square_wave.csv": {
47
+ "description": "10 kHz square wave with ringing, CSV format",
48
+ "format": "csv",
49
+ "size": 1024 * 100, # ~100 KB
50
+ "checksum": None,
51
+ "url": "https://raw.githubusercontent.com/oscura/sample-data/main/square_wave.csv",
52
+ },
53
+ "uart_9600.bin": {
54
+ "description": "UART signal at 9600 baud, binary format",
55
+ "format": "binary",
56
+ "size": 1024 * 20, # ~20 KB
57
+ "checksum": None,
58
+ "url": "https://raw.githubusercontent.com/oscura/sample-data/main/uart_9600.bin",
59
+ },
60
+ "i2c_capture.bin": {
61
+ "description": "I2C bus capture with multiple devices",
62
+ "format": "binary",
63
+ "size": 1024 * 50, # ~50 KB
64
+ "checksum": None,
65
+ "url": "https://raw.githubusercontent.com/oscura/sample-data/main/i2c_capture.bin",
66
+ },
67
+ "spi_flash.bin": {
68
+ "description": "SPI flash read operation",
69
+ "format": "binary",
70
+ "size": 1024 * 30, # ~30 KB
71
+ "checksum": None,
72
+ "url": "https://raw.githubusercontent.com/oscura/sample-data/main/spi_flash.bin",
73
+ },
74
+ "noisy_signal.csv": {
75
+ "description": "Noisy analog signal for filtering examples",
76
+ "format": "csv",
77
+ "size": 1024 * 80, # ~80 KB
78
+ "checksum": None,
79
+ "url": "https://raw.githubusercontent.com/oscura/sample-data/main/noisy_signal.csv",
80
+ },
81
+ "eye_diagram.npz": {
82
+ "description": "High-speed serial data for eye diagram",
83
+ "format": "npz",
84
+ "size": 1024 * 200, # ~200 KB
85
+ "checksum": None,
86
+ "url": "https://raw.githubusercontent.com/oscura/sample-data/main/eye_diagram.npz",
87
+ },
88
+ }
89
+
90
+
91
+ def download_file(url: str, dest: Path, checksum: str | None = None) -> bool:
92
+ """Download a file from URL to destination.
93
+
94
+ Args:
95
+ url: URL to download from.
96
+ dest: Destination file path.
97
+ checksum: Optional SHA256 checksum to verify.
98
+
99
+ Returns:
100
+ True if download successful, False otherwise.
101
+ """
102
+ try:
103
+ import ssl
104
+ import urllib.request
105
+
106
+ # Create SSL context that works in most environments
107
+ context = ssl.create_default_context()
108
+
109
+ print(f" Downloading: {url}")
110
+
111
+ with urllib.request.urlopen(url, context=context, timeout=30) as response:
112
+ data = response.read()
113
+
114
+ # Verify checksum if provided
115
+ if checksum:
116
+ computed = hashlib.sha256(data).hexdigest()
117
+ if computed != checksum:
118
+ print(f" ERROR: Checksum mismatch for {dest.name}")
119
+ print(f" Expected: {checksum}")
120
+ print(f" Got: {computed}")
121
+ return False
122
+
123
+ # Write to destination
124
+ dest.parent.mkdir(parents=True, exist_ok=True)
125
+ dest.write_bytes(data)
126
+
127
+ print(f" Saved: {dest}")
128
+ return True
129
+
130
+ except Exception as e:
131
+ print(f" ERROR: Failed to download {url}: {e}")
132
+ return False
133
+
134
+
135
+ def generate_sample_file(filename: str, dest: Path) -> bool:
136
+ """Generate a sample file locally when download is not available.
137
+
138
+ This is a fallback when the remote repository is not available.
139
+
140
+ Args:
141
+ filename: Name of the sample file to generate.
142
+ dest: Destination file path.
143
+
144
+ Returns:
145
+ True if generation successful, False otherwise.
146
+ """
147
+ try:
148
+ import numpy as np
149
+
150
+ dest.parent.mkdir(parents=True, exist_ok=True)
151
+
152
+ if filename == "sine_1khz.csv":
153
+ # Generate 1 kHz sine wave at 100 kS/s, 1000 samples
154
+ sample_rate = 100_000
155
+ duration = 0.01 # 10 ms
156
+ t = np.arange(0, duration, 1 / sample_rate)
157
+ signal = 0.5 * np.sin(2 * np.pi * 1000 * t)
158
+ np.savetxt(
159
+ dest,
160
+ np.column_stack([t, signal]),
161
+ delimiter=",",
162
+ header="time,voltage",
163
+ comments="",
164
+ )
165
+ return True
166
+
167
+ elif filename == "square_wave.csv":
168
+ # Generate 10 kHz square wave with some ringing
169
+ sample_rate = 1_000_000
170
+ duration = 0.001 # 1 ms
171
+ t = np.arange(0, duration, 1 / sample_rate)
172
+ signal = 0.5 * np.sign(np.sin(2 * np.pi * 10000 * t))
173
+ # Add some ringing/noise
174
+ signal += 0.05 * np.random.randn(len(signal))
175
+ np.savetxt(
176
+ dest,
177
+ np.column_stack([t, signal]),
178
+ delimiter=",",
179
+ header="time,voltage",
180
+ comments="",
181
+ )
182
+ return True
183
+
184
+ elif filename == "noisy_signal.csv":
185
+ # Generate noisy sine wave
186
+ sample_rate = 10_000
187
+ duration = 0.1 # 100 ms
188
+ t = np.arange(0, duration, 1 / sample_rate)
189
+ signal = 0.5 * np.sin(2 * np.pi * 100 * t)
190
+ signal += 0.1 * np.random.randn(len(signal))
191
+ np.savetxt(
192
+ dest,
193
+ np.column_stack([t, signal]),
194
+ delimiter=",",
195
+ header="time,voltage",
196
+ comments="",
197
+ )
198
+ return True
199
+
200
+ elif filename.endswith(".bin"):
201
+ # Generate placeholder binary data
202
+ data = np.random.randint(0, 256, 1000, dtype=np.uint8)
203
+ data.tofile(dest)
204
+ return True
205
+
206
+ elif filename.endswith(".npz"):
207
+ # Generate high-speed signal for eye diagram
208
+ sample_rate = 10_000_000 # 10 MS/s
209
+ samples_per_ui = 100
210
+ num_ui = 100
211
+ t = np.arange(samples_per_ui * num_ui) / sample_rate
212
+ # Generate random bit pattern
213
+ bits = np.random.randint(0, 2, num_ui)
214
+ signal = np.repeat(bits.astype(float), samples_per_ui)
215
+ # Add some jitter and noise
216
+ signal += 0.1 * np.random.randn(len(signal))
217
+ np.savez(dest, time=t, signal=signal, sample_rate=sample_rate)
218
+ return True
219
+
220
+ else:
221
+ print(f" WARNING: Unknown file type: {filename}")
222
+ return False
223
+
224
+ except Exception as e:
225
+ print(f" ERROR: Failed to generate {filename}: {e}")
226
+ return False
227
+
228
+
229
+ def download_samples(force: bool = False, generate: bool = True) -> int:
230
+ """Download sample waveform files for testing and tutorials.
231
+
232
+ Args:
233
+ force: Force re-download even if files exist.
234
+ generate: Generate files locally if download fails.
235
+
236
+ Returns:
237
+ Exit code (0 for success, 1 for failure).
238
+ """
239
+ samples_dir = get_samples_dir()
240
+ sample_files = get_sample_files()
241
+
242
+ print("Oscura Sample Data Download")
243
+ print("==============================")
244
+ print(f"Destination: {samples_dir}")
245
+ print()
246
+
247
+ success_count = 0
248
+ fail_count = 0
249
+
250
+ for filename, info in sample_files.items():
251
+ dest = samples_dir / filename
252
+
253
+ if dest.exists() and not force:
254
+ print(f"[SKIP] {filename} (already exists)")
255
+ success_count += 1
256
+ continue
257
+
258
+ print(f"[DOWNLOAD] {filename}")
259
+ print(f" Description: {info['description']}")
260
+
261
+ # Try to download first
262
+ url = info.get("url")
263
+ checksum = info.get("checksum")
264
+
265
+ if url and download_file(url, dest, checksum):
266
+ success_count += 1
267
+ continue
268
+
269
+ # Fall back to local generation
270
+ if generate:
271
+ print(" Falling back to local generation...")
272
+ if generate_sample_file(filename, dest):
273
+ print(f" Generated: {dest}")
274
+ success_count += 1
275
+ continue
276
+
277
+ fail_count += 1
278
+ print(f" FAILED: {filename}")
279
+
280
+ print()
281
+ print(f"Summary: {success_count} succeeded, {fail_count} failed")
282
+
283
+ if fail_count > 0:
284
+ print()
285
+ print("Some downloads failed. Sample files are optional and used for")
286
+ print("tutorials and testing. You can proceed without them.")
287
+ return 1
288
+
289
+ print()
290
+ print("Sample files downloaded successfully!")
291
+ print()
292
+ print("Example usage:")
293
+ print(" >>> import oscura as osc")
294
+ print(f" >>> trace = osc.load('{samples_dir / 'sine_1khz.csv'}')")
295
+ print(" >>> trace.plot()")
296
+
297
+ return 0
298
+
299
+
300
+ def list_samples() -> int:
301
+ """List available sample files.
302
+
303
+ Returns:
304
+ Exit code.
305
+ """
306
+ samples_dir = get_samples_dir()
307
+ sample_files = get_sample_files()
308
+
309
+ print("Available sample files:")
310
+ print()
311
+
312
+ for filename, info in sample_files.items():
313
+ dest = samples_dir / filename
314
+ status = "[EXISTS]" if dest.exists() else "[NOT DOWNLOADED]"
315
+ print(f" {status} {filename}")
316
+ print(f" {info['description']}")
317
+ print()
318
+
319
+ return 0
320
+
321
+
322
+ def main() -> int:
323
+ """Main entry point for Oscura CLI.
324
+
325
+ Returns:
326
+ Exit code.
327
+ """
328
+ parser = argparse.ArgumentParser(
329
+ prog="oscura",
330
+ description="Oscura signal analysis toolkit",
331
+ )
332
+
333
+ subparsers = parser.add_subparsers(dest="command", help="Available commands")
334
+
335
+ # download_samples command
336
+ download_parser = subparsers.add_parser(
337
+ "download_samples",
338
+ aliases=["download"],
339
+ help="Download sample waveform files",
340
+ )
341
+ download_parser.add_argument(
342
+ "--force",
343
+ "-f",
344
+ action="store_true",
345
+ help="Force re-download even if files exist",
346
+ )
347
+ download_parser.add_argument(
348
+ "--no-generate",
349
+ action="store_true",
350
+ help="Do not generate files locally if download fails",
351
+ )
352
+
353
+ # list_samples command
354
+ subparsers.add_parser(
355
+ "list_samples",
356
+ aliases=["list"],
357
+ help="List available sample files",
358
+ )
359
+
360
+ # version command
361
+ subparsers.add_parser(
362
+ "version",
363
+ help="Show version information",
364
+ )
365
+
366
+ args = parser.parse_args()
367
+
368
+ if args.command in ("download_samples", "download"):
369
+ return download_samples(
370
+ force=args.force,
371
+ generate=not args.no_generate,
372
+ )
373
+
374
+ elif args.command in ("list_samples", "list"):
375
+ return list_samples()
376
+
377
+ elif args.command == "version":
378
+ try:
379
+ from oscura import __version__
380
+
381
+ print(f"Oscura version {__version__}")
382
+ except ImportError:
383
+ print("Oscura version unknown")
384
+ return 0
385
+
386
+ else:
387
+ parser.print_help()
388
+ return 0
389
+
390
+
391
+ if __name__ == "__main__":
392
+ sys.exit(main())
@@ -0,0 +1,37 @@
1
+ """Oscura analyzers module.
2
+
3
+ Provides signal analysis functionality including:
4
+ - Waveform measurements (timing, amplitude)
5
+ - Digital signal analysis (edge detection, thresholding, timing, quality)
6
+ - Spectral analysis (FFT, PSD, quality metrics)
7
+ - Statistical analysis (outliers, correlation, trends)
8
+ - Protocol decoding (UART, SPI, I2C, CAN)
9
+ - Jitter analysis (RJ, DJ, PJ, DDJ, bathtub curves)
10
+ - Eye diagram analysis (height, width, Q-factor)
11
+ - Signal integrity (S-parameters, equalization)
12
+ """
13
+
14
+ # Import measurements module as namespace for DSL compatibility
15
+ from oscura.analyzers import (
16
+ digital,
17
+ eye,
18
+ jitter,
19
+ measurements,
20
+ protocols,
21
+ signal_integrity,
22
+ statistics,
23
+ validation,
24
+ waveform,
25
+ )
26
+
27
+ __all__ = [
28
+ "digital",
29
+ "eye",
30
+ "jitter",
31
+ "measurements",
32
+ "protocols",
33
+ "signal_integrity",
34
+ "statistics",
35
+ "validation",
36
+ "waveform",
37
+ ]
@@ -0,0 +1,177 @@
1
+ """Digital signal analysis module.
2
+
3
+ Provides digital signal extraction, edge detection, timing analysis,
4
+ signal quality metrics, multi-channel correlation, clock recovery,
5
+ bus decoding, edge timing analysis, and signal quality metrics.
6
+
7
+ - RE-THR-001: Time-Varying Threshold Support
8
+ - RE-THR-002: Multi-Level Logic Support
9
+ """
10
+
11
+ from oscura.analyzers.digital.bus import (
12
+ BusConfig,
13
+ BusDecoder,
14
+ BusTransaction,
15
+ ParallelBusConfig,
16
+ decode_bus,
17
+ sample_at_clock,
18
+ )
19
+ from oscura.analyzers.digital.clock import (
20
+ BaudRateResult,
21
+ ClockMetrics,
22
+ ClockRecovery,
23
+ detect_baud_rate,
24
+ detect_clock_frequency,
25
+ measure_clock_jitter,
26
+ recover_clock,
27
+ )
28
+ from oscura.analyzers.digital.correlation import (
29
+ ChannelCorrelator,
30
+ CorrelatedChannels,
31
+ CorrelationResult,
32
+ align_by_trigger,
33
+ correlate_channels,
34
+ resample_to_common_rate,
35
+ )
36
+ from oscura.analyzers.digital.edges import (
37
+ Edge,
38
+ EdgeDetector,
39
+ EdgeTiming,
40
+ TimingConstraint,
41
+ check_timing_constraints,
42
+ classify_edge_quality,
43
+ interpolate_edge_time,
44
+ measure_edge_timing,
45
+ )
46
+ from oscura.analyzers.digital.edges import (
47
+ TimingViolation as EdgeTimingViolation,
48
+ )
49
+ from oscura.analyzers.digital.edges import (
50
+ detect_edges as detect_edges_advanced,
51
+ )
52
+ from oscura.analyzers.digital.extraction import (
53
+ LOGIC_FAMILIES,
54
+ detect_edges,
55
+ get_logic_threshold,
56
+ to_digital,
57
+ )
58
+ from oscura.analyzers.digital.quality import (
59
+ Glitch,
60
+ NoiseMarginResult,
61
+ Violation,
62
+ detect_glitches,
63
+ detect_violations,
64
+ noise_margin,
65
+ signal_quality_summary,
66
+ )
67
+ from oscura.analyzers.digital.signal_quality import (
68
+ NoiseMargins,
69
+ SignalIntegrityReport,
70
+ SignalQualityAnalyzer,
71
+ SimpleQualityMetrics,
72
+ TransitionMetrics,
73
+ analyze_signal_integrity,
74
+ measure_noise_margins,
75
+ )
76
+
77
+ # RE-THR-001, RE-THR-002: Adaptive Thresholding and Multi-Level Logic
78
+ from oscura.analyzers.digital.thresholds import (
79
+ AdaptiveThresholder,
80
+ AdaptiveThresholdResult,
81
+ MultiLevelDetector,
82
+ MultiLevelResult,
83
+ ThresholdConfig,
84
+ apply_adaptive_threshold,
85
+ calculate_threshold_snr,
86
+ detect_multi_level,
87
+ )
88
+ from oscura.analyzers.digital.timing import (
89
+ ClockRecoveryResult,
90
+ TimingViolation,
91
+ hold_time,
92
+ phase,
93
+ propagation_delay,
94
+ recover_clock_edge,
95
+ recover_clock_fft,
96
+ setup_time,
97
+ skew,
98
+ slew_rate,
99
+ )
100
+
101
+ __all__ = [
102
+ # Extraction
103
+ "LOGIC_FAMILIES",
104
+ "AdaptiveThresholdResult",
105
+ # Adaptive Thresholds (RE-THR-001)
106
+ "AdaptiveThresholder",
107
+ # Clock Recovery (DSP-002)
108
+ "BaudRateResult",
109
+ # Bus Decoding (DSP-003)
110
+ "BusConfig",
111
+ "BusDecoder",
112
+ "BusTransaction",
113
+ # Correlation (DSP-001)
114
+ "ChannelCorrelator",
115
+ "ClockMetrics",
116
+ "ClockRecovery",
117
+ # Timing
118
+ "ClockRecoveryResult",
119
+ "CorrelatedChannels",
120
+ "CorrelationResult",
121
+ # Edge Analysis (DSP-004)
122
+ "Edge",
123
+ "EdgeDetector",
124
+ "EdgeTiming",
125
+ "EdgeTimingViolation",
126
+ # Quality
127
+ "Glitch",
128
+ # Multi-Level Logic (RE-THR-002)
129
+ "MultiLevelDetector",
130
+ "MultiLevelResult",
131
+ "NoiseMarginResult",
132
+ # Signal Quality (DSP-005)
133
+ "NoiseMargins",
134
+ "ParallelBusConfig",
135
+ "SignalIntegrityReport",
136
+ "SignalQualityAnalyzer",
137
+ "SimpleQualityMetrics",
138
+ "ThresholdConfig",
139
+ "TimingConstraint",
140
+ "TimingViolation",
141
+ "TransitionMetrics",
142
+ "Violation",
143
+ "align_by_trigger",
144
+ "analyze_signal_integrity",
145
+ "apply_adaptive_threshold",
146
+ "calculate_threshold_snr",
147
+ "check_timing_constraints",
148
+ "classify_edge_quality",
149
+ "correlate_channels",
150
+ "decode_bus",
151
+ "detect_baud_rate",
152
+ "detect_clock_frequency",
153
+ "detect_edges",
154
+ "detect_edges_advanced",
155
+ "detect_glitches",
156
+ "detect_multi_level",
157
+ "detect_violations",
158
+ "get_logic_threshold",
159
+ "hold_time",
160
+ "interpolate_edge_time",
161
+ "measure_clock_jitter",
162
+ "measure_edge_timing",
163
+ "measure_noise_margins",
164
+ "noise_margin",
165
+ "phase",
166
+ "propagation_delay",
167
+ "recover_clock",
168
+ "recover_clock_edge",
169
+ "recover_clock_fft",
170
+ "resample_to_common_rate",
171
+ "sample_at_clock",
172
+ "setup_time",
173
+ "signal_quality_summary",
174
+ "skew",
175
+ "slew_rate",
176
+ "to_digital",
177
+ ]