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
@@ -0,0 +1,405 @@
1
+ """Automatic backend selection for optimal performance.
2
+
3
+ This module provides intelligent backend selection based on data characteristics,
4
+ available hardware, and performance requirements. Automatically chooses between
5
+ NumPy, Numba, GPU (CuPy), and distributed (Dask) backends.
6
+
7
+ Usage:
8
+ from oscura.core.backend_selector import BackendSelector, select_backend
9
+
10
+ selector = BackendSelector()
11
+ backend = selector.select_for_fft(signal_size=10_000_000)
12
+ # Returns 'gpu' if available, else 'scipy'
13
+
14
+ Performance decision tree:
15
+ - Small data (<100K): NumPy/SciPy
16
+ - Medium data (100K-10M): Numba JIT
17
+ - Large data (>10M): GPU if available, else Numba
18
+ - Huge data (>1GB): Dask distributed
19
+
20
+ Example:
21
+ >>> from oscura.core.backend_selector import select_backend
22
+ >>> import numpy as np
23
+ >>>
24
+ >>> data = np.random.randn(50_000_000)
25
+ >>> backend = select_backend('fft', data_size=len(data))
26
+ >>> print(f"Selected backend: {backend}") # 'gpu' or 'scipy'
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ from dataclasses import dataclass
32
+ from typing import Literal
33
+
34
+ import numpy as np
35
+ import psutil
36
+
37
+ # Check available backends
38
+ try:
39
+ from oscura.core.gpu_backend import gpu
40
+
41
+ HAS_GPU = gpu.gpu_available
42
+ except (ImportError, AttributeError):
43
+ HAS_GPU = False
44
+
45
+ try:
46
+ import numba # type: ignore[import-untyped]
47
+
48
+ HAS_NUMBA = True
49
+ del numba
50
+ except ImportError:
51
+ HAS_NUMBA = False
52
+
53
+ try:
54
+ import dask.array # type: ignore[import-not-found, import-untyped]
55
+
56
+ HAS_DASK = True
57
+ del dask # type: ignore[name-defined]
58
+ except ImportError:
59
+ HAS_DASK = False
60
+
61
+ try:
62
+ import scipy.fft
63
+
64
+ HAS_SCIPY = True
65
+ del scipy
66
+ except ImportError:
67
+ HAS_SCIPY = False
68
+
69
+
70
+ BackendType = Literal["numpy", "scipy", "numba", "gpu", "dask"]
71
+
72
+
73
+ @dataclass
74
+ class BackendCapabilities:
75
+ """Available backend capabilities on this system.
76
+
77
+ Attributes:
78
+ has_gpu: Whether GPU (CuPy) is available.
79
+ has_numba: Whether Numba JIT is available.
80
+ has_dask: Whether Dask distributed is available.
81
+ has_scipy: Whether SciPy is available.
82
+ cpu_count: Number of CPU cores.
83
+ total_memory_gb: Total system RAM in GB.
84
+ gpu_memory_gb: GPU memory in GB (0 if no GPU).
85
+ """
86
+
87
+ has_gpu: bool
88
+ has_numba: bool
89
+ has_dask: bool
90
+ has_scipy: bool
91
+ cpu_count: int
92
+ total_memory_gb: float
93
+ gpu_memory_gb: float
94
+
95
+
96
+ def get_system_capabilities() -> BackendCapabilities:
97
+ """Detect available backends and system resources.
98
+
99
+ Returns:
100
+ BackendCapabilities object with system information.
101
+
102
+ Example:
103
+ >>> caps = get_system_capabilities()
104
+ >>> if caps.has_gpu:
105
+ ... print(f"GPU available with {caps.gpu_memory_gb:.1f} GB memory")
106
+ """
107
+ # CPU and memory info
108
+ cpu_count = psutil.cpu_count(logical=False) or 1
109
+ total_memory = psutil.virtual_memory().total
110
+ total_memory_gb = total_memory / (1024**3)
111
+
112
+ # GPU memory
113
+ gpu_memory_gb = 0.0
114
+ if HAS_GPU:
115
+ try:
116
+ from oscura.core.gpu_backend import gpu
117
+
118
+ # Get GPU memory in bytes, convert to GB
119
+ gpu_memory_gb = gpu.get_memory_info()[1] / (1024**3) # type: ignore[attr-defined]
120
+ except Exception:
121
+ gpu_memory_gb = 0.0
122
+
123
+ return BackendCapabilities(
124
+ has_gpu=HAS_GPU,
125
+ has_numba=HAS_NUMBA,
126
+ has_dask=HAS_DASK,
127
+ has_scipy=HAS_SCIPY,
128
+ cpu_count=cpu_count,
129
+ total_memory_gb=total_memory_gb,
130
+ gpu_memory_gb=gpu_memory_gb,
131
+ )
132
+
133
+
134
+ class BackendSelector:
135
+ """Intelligent backend selector for optimal performance.
136
+
137
+ This class analyzes data characteristics and system capabilities to
138
+ automatically select the best backend for each operation.
139
+
140
+ Example:
141
+ >>> selector = BackendSelector()
142
+ >>> # For FFT on 50M samples
143
+ >>> backend = selector.select_for_fft(50_000_000)
144
+ >>> # For edge detection with hysteresis
145
+ >>> backend = selector.select_for_edge_detection(1_000_000, has_hysteresis=True)
146
+ """
147
+
148
+ def __init__(self) -> None:
149
+ """Initialize backend selector with system capabilities."""
150
+ self.capabilities = get_system_capabilities()
151
+
152
+ def select_for_fft(
153
+ self,
154
+ data_size: int,
155
+ dtype: type = np.float64,
156
+ ) -> BackendType:
157
+ """Select optimal backend for FFT operations.
158
+
159
+ Args:
160
+ data_size: Number of samples in signal.
161
+ dtype: Data type (affects memory usage).
162
+
163
+ Returns:
164
+ BackendType: 'numpy', 'scipy', 'gpu', or 'dask'.
165
+
166
+ Example:
167
+ >>> selector = BackendSelector()
168
+ >>> backend = selector.select_for_fft(10_000_000)
169
+ """
170
+ # Decision tree based on data size
171
+ if data_size > 100_000_000 and self.capabilities.has_dask:
172
+ # Huge data: use distributed
173
+ return "dask"
174
+ elif data_size > 10_000_000 and self.capabilities.has_gpu:
175
+ # Large data + GPU: use GPU
176
+ return "gpu"
177
+ elif self.capabilities.has_scipy:
178
+ # Use scipy.fft with workers (faster than numpy.fft)
179
+ return "scipy"
180
+ else:
181
+ # Fallback to numpy
182
+ return "numpy"
183
+
184
+ def select_for_edge_detection(
185
+ self,
186
+ data_size: int,
187
+ has_hysteresis: bool = False,
188
+ ) -> BackendType:
189
+ """Select optimal backend for edge detection.
190
+
191
+ Args:
192
+ data_size: Number of samples in signal.
193
+ has_hysteresis: Whether hysteresis is used (affects vectorization).
194
+
195
+ Returns:
196
+ BackendType: 'numpy', 'numba', or 'gpu'.
197
+
198
+ Example:
199
+ >>> selector = BackendSelector()
200
+ >>> backend = selector.select_for_edge_detection(5_000_000, has_hysteresis=True)
201
+ """
202
+ if data_size > 10_000_000 and self.capabilities.has_gpu:
203
+ return "gpu"
204
+ elif has_hysteresis and self.capabilities.has_numba and data_size > 100_000:
205
+ return "numba"
206
+ elif has_hysteresis:
207
+ return "numpy" # Actually uses Python for hysteresis state machine
208
+ else:
209
+ return "numpy" # Vectorized without hysteresis
210
+
211
+ def select_for_correlation(
212
+ self,
213
+ signal1_size: int,
214
+ signal2_size: int,
215
+ mode: Literal["full", "valid", "same"] = "full",
216
+ ) -> BackendType:
217
+ """Select optimal backend for correlation.
218
+
219
+ Args:
220
+ signal1_size: Size of first signal.
221
+ signal2_size: Size of second signal.
222
+ mode: Correlation mode.
223
+
224
+ Returns:
225
+ Backend name.
226
+
227
+ Example:
228
+ >>> selector = BackendSelector()
229
+ >>> backend = selector.select_for_correlation(1_000_000, 10_000)
230
+ """
231
+ total_size = signal1_size + signal2_size
232
+ output_size = self._estimate_correlation_output(signal1_size, signal2_size, mode)
233
+
234
+ # Estimate memory
235
+ total_memory_mb = (total_size + output_size) * 8 / (1024**2)
236
+
237
+ if total_memory_mb > self.capabilities.total_memory_gb * 1024 * 0.5:
238
+ # Would use >50% RAM: use chunked/streaming
239
+ return "dask" if self.capabilities.has_dask else "numpy"
240
+ elif signal1_size > 10_000_000 and self.capabilities.has_gpu:
241
+ return "gpu"
242
+ elif self.capabilities.has_scipy:
243
+ return "scipy"
244
+ else:
245
+ return "numpy"
246
+
247
+ def select_for_protocol_decode(
248
+ self,
249
+ data_size: int,
250
+ protocol: str,
251
+ ) -> BackendType:
252
+ """Select optimal backend for protocol decoding.
253
+
254
+ Args:
255
+ data_size: Number of samples in signal.
256
+ protocol: Protocol name (e.g., 'uart', 'spi', 'i2c').
257
+
258
+ Returns:
259
+ Backend name.
260
+
261
+ Example:
262
+ >>> selector = BackendSelector()
263
+ >>> backend = selector.select_for_protocol_decode(5_000_000, 'uart')
264
+ """
265
+ # Protocol decoders use edge detection + state machines
266
+ # Large signals benefit from Numba-compiled state machines
267
+ if data_size > 1_000_000 and self.capabilities.has_numba:
268
+ return "numba"
269
+ else:
270
+ return "numpy"
271
+
272
+ def select_for_pattern_matching(
273
+ self,
274
+ data_size: int,
275
+ pattern_count: int,
276
+ approximate: bool = False,
277
+ ) -> BackendType:
278
+ """Select optimal backend for pattern matching.
279
+
280
+ Args:
281
+ data_size: Size of data to search.
282
+ pattern_count: Number of patterns.
283
+ approximate: Whether approximate matching is acceptable.
284
+
285
+ Returns:
286
+ Backend name.
287
+
288
+ Example:
289
+ >>> selector = BackendSelector()
290
+ >>> backend = selector.select_for_pattern_matching(1_000_000, 100, approximate=True)
291
+ """
292
+ # For approximate matching with many patterns, LSH is best
293
+ # Otherwise use standard string matching
294
+ if approximate and pattern_count > 10:
295
+ return "numpy" # LSH implementation in NumPy
296
+ elif data_size > 10_000_000:
297
+ return "numba"
298
+ else:
299
+ return "numpy"
300
+
301
+ def _estimate_correlation_output(
302
+ self,
303
+ size1: int,
304
+ size2: int,
305
+ mode: Literal["full", "valid", "same"],
306
+ ) -> int:
307
+ """Estimate output size of correlation.
308
+
309
+ Args:
310
+ size1: Size of first signal.
311
+ size2: Size of second signal.
312
+ mode: Correlation mode.
313
+
314
+ Returns:
315
+ Estimated output size in samples.
316
+ """
317
+ if mode == "full":
318
+ return size1 + size2 - 1
319
+ elif mode == "valid":
320
+ return max(size1, size2) - min(size1, size2) + 1
321
+ else: # same
322
+ return max(size1, size2)
323
+
324
+
325
+ # Global selector instance
326
+ _global_selector: BackendSelector | None = None
327
+
328
+
329
+ def get_global_selector() -> BackendSelector:
330
+ """Get global backend selector instance (singleton).
331
+
332
+ Returns:
333
+ Global BackendSelector instance.
334
+
335
+ Example:
336
+ >>> selector = get_global_selector()
337
+ >>> backend = selector.select_for_fft(1_000_000)
338
+ """
339
+ global _global_selector
340
+ if _global_selector is None:
341
+ _global_selector = BackendSelector()
342
+ return _global_selector
343
+
344
+
345
+ def select_backend(
346
+ operation: Literal[
347
+ "fft", "edge_detection", "correlation", "protocol_decode", "pattern_matching"
348
+ ],
349
+ **kwargs: int | str | bool,
350
+ ) -> BackendType:
351
+ """Convenience function to select backend for an operation.
352
+
353
+ Args:
354
+ operation: Type of operation.
355
+ **kwargs: Operation-specific parameters.
356
+
357
+ Returns:
358
+ Selected backend name.
359
+
360
+ Example:
361
+ >>> backend = select_backend('fft', data_size=10_000_000)
362
+ >>> backend = select_backend('edge_detection', data_size=5_000_000, has_hysteresis=True)
363
+ >>> backend = select_backend('correlation', signal1_size=1_000_000, signal2_size=10_000)
364
+ """
365
+ selector = get_global_selector()
366
+
367
+ if operation == "fft":
368
+ return selector.select_for_fft(
369
+ data_size=int(kwargs.get("data_size", 0)),
370
+ dtype=kwargs.get("dtype", np.float64), # type: ignore[arg-type]
371
+ )
372
+ elif operation == "edge_detection":
373
+ return selector.select_for_edge_detection(
374
+ data_size=int(kwargs.get("data_size", 0)),
375
+ has_hysteresis=bool(kwargs.get("has_hysteresis", False)),
376
+ )
377
+ elif operation == "correlation":
378
+ return selector.select_for_correlation(
379
+ signal1_size=int(kwargs.get("signal1_size", 0)),
380
+ signal2_size=int(kwargs.get("signal2_size", 0)),
381
+ mode=kwargs.get("mode", "full"), # type: ignore[arg-type]
382
+ )
383
+ elif operation == "protocol_decode":
384
+ return selector.select_for_protocol_decode(
385
+ data_size=int(kwargs.get("data_size", 0)),
386
+ protocol=str(kwargs.get("protocol", "")),
387
+ )
388
+ elif operation == "pattern_matching":
389
+ return selector.select_for_pattern_matching(
390
+ data_size=int(kwargs.get("data_size", 0)),
391
+ pattern_count=int(kwargs.get("pattern_count", 0)),
392
+ approximate=bool(kwargs.get("approximate", False)),
393
+ )
394
+ else:
395
+ return "numpy" # type: ignore[unreachable]
396
+
397
+
398
+ __all__ = [
399
+ "BackendCapabilities",
400
+ "BackendSelector",
401
+ "BackendType",
402
+ "get_global_selector",
403
+ "get_system_capabilities",
404
+ "select_backend",
405
+ ]