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