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/core/memoize.py ADDED
@@ -0,0 +1,171 @@
1
+ """Memory-safe memoization decorators for Oscura analyzer functions.
2
+
3
+ This module provides lightweight memoization decorators optimized for analyzer
4
+ functions that process numpy arrays. Unlike the full OscuraCache, these
5
+ decorators provide simple in-memory caching with bounded size.
6
+
7
+
8
+ Example:
9
+ >>> from oscura.core.memoize import memoize_analysis
10
+ >>> @memoize_analysis(maxsize=32)
11
+ ... def expensive_fft(signal, nperseg):
12
+ ... return scipy.fft.fft(signal, n=nperseg)
13
+ >>> result = expensive_fft(signal_array, 1024) # Computed
14
+ >>> result = expensive_fft(signal_array, 1024) # Cached
15
+
16
+ References:
17
+ functools.lru_cache for standard Python memoization
18
+ hashlib for stable array hashing
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import hashlib
24
+ from functools import wraps
25
+ from typing import TYPE_CHECKING, Any, TypeVar
26
+
27
+ import numpy as np
28
+ from numpy.typing import NDArray
29
+
30
+ if TYPE_CHECKING:
31
+ from collections.abc import Callable
32
+
33
+ T = TypeVar("T")
34
+
35
+
36
+ def array_hash(arr: NDArray[Any], sample_size: int = 10000) -> str:
37
+ """Create stable hash for numpy array.
38
+
39
+ Uses first `sample_size` bytes of array data to create a hash key.
40
+ This is faster than hashing the entire array while maintaining
41
+ good cache hit rates for typical analysis workflows.
42
+
43
+ Args:
44
+ arr: Numpy array to hash.
45
+ sample_size: Number of bytes to sample for hashing (default: 10KB).
46
+
47
+ Returns:
48
+ 16-character hex hash string.
49
+
50
+ Example:
51
+ >>> arr = np.arange(1000000, dtype=np.float32)
52
+ >>> hash1 = array_hash(arr)
53
+ >>> hash2 = array_hash(arr)
54
+ >>> assert hash1 == hash2
55
+ """
56
+ # Use shape, dtype, and sample of data for hash
57
+ hash_obj = hashlib.sha256()
58
+
59
+ # Include shape and dtype
60
+ hash_obj.update(str(arr.shape).encode())
61
+ hash_obj.update(str(arr.dtype).encode())
62
+
63
+ # Sample first N bytes of data
64
+ data_bytes = arr.tobytes()[:sample_size]
65
+ hash_obj.update(data_bytes)
66
+
67
+ return hash_obj.hexdigest()[:16]
68
+
69
+
70
+ def memoize_analysis(maxsize: int = 32) -> Callable[[Callable[..., T]], Callable[..., T]]:
71
+ """Decorator for memoizing analysis functions with numpy arrays.
72
+
73
+ Automatically hashes numpy array arguments for cache keys.
74
+ Memory-safe with bounded cache size using LRU eviction.
75
+
76
+
77
+ Args:
78
+ maxsize: Maximum number of cached results (default: 32).
79
+
80
+ Returns:
81
+ Decorator function.
82
+
83
+ Example:
84
+ >>> @memoize_analysis(maxsize=16)
85
+ ... def detect_edges(signal, threshold):
86
+ ... # Expensive edge detection...
87
+ ... return edges
88
+ >>> # First call computes
89
+ >>> edges1 = detect_edges(signal_array, 0.5)
90
+ >>> # Second call uses cache
91
+ >>> edges2 = detect_edges(signal_array, 0.5)
92
+ >>> assert edges1 is edges2
93
+
94
+ Note:
95
+ Cache is stored per-function. Use OscuraCache from core.cache
96
+ for persistent cross-function caching.
97
+
98
+ References:
99
+ PERF-001: Performance optimization requirements
100
+ """
101
+
102
+ def decorator(func: Callable[..., T]) -> Callable[..., T]:
103
+ cache: dict[str, T] = {}
104
+ cache_order: list[str] = [] # Track insertion order for LRU
105
+
106
+ @wraps(func)
107
+ def wrapper(*args: Any, **kwargs: Any) -> T:
108
+ # Build cache key from args
109
+ key_parts: list[str] = []
110
+
111
+ for arg in args:
112
+ if isinstance(arg, np.ndarray):
113
+ key_parts.append(f"arr_{len(arg)}_{array_hash(arg)}")
114
+ else:
115
+ key_parts.append(str(arg))
116
+
117
+ for k, v in sorted(kwargs.items()):
118
+ if isinstance(v, np.ndarray):
119
+ key_parts.append(f"{k}=arr_{len(v)}_{array_hash(v)}")
120
+ else:
121
+ key_parts.append(f"{k}={v}")
122
+
123
+ cache_key = ":".join(key_parts)
124
+
125
+ # Check cache
126
+ if cache_key in cache:
127
+ # Move to end (most recently used)
128
+ cache_order.remove(cache_key)
129
+ cache_order.append(cache_key)
130
+ return cache[cache_key]
131
+
132
+ # Compute result
133
+ result = func(*args, **kwargs)
134
+
135
+ # Evict oldest if at capacity
136
+ if len(cache) >= maxsize:
137
+ oldest = cache_order.pop(0)
138
+ del cache[oldest]
139
+
140
+ # Store result
141
+ cache[cache_key] = result
142
+ cache_order.append(cache_key)
143
+
144
+ return result
145
+
146
+ def cache_clear() -> None:
147
+ """Clear all cached results."""
148
+ cache.clear()
149
+ cache_order.clear()
150
+
151
+ def cache_info() -> dict[str, Any]:
152
+ """Get cache statistics.
153
+
154
+ Returns:
155
+ Dictionary with cache size and maxsize.
156
+ """
157
+ return {"size": len(cache), "maxsize": maxsize}
158
+
159
+ # Attach utility methods
160
+ wrapper.cache_clear = cache_clear # type: ignore[attr-defined]
161
+ wrapper.cache_info = cache_info # type: ignore[attr-defined]
162
+
163
+ return wrapper
164
+
165
+ return decorator
166
+
167
+
168
+ __all__ = [
169
+ "array_hash",
170
+ "memoize_analysis",
171
+ ]
@@ -0,0 +1,274 @@
1
+ """Pre-flight memory checking for Oscura operations.
2
+
3
+ This module provides automatic memory verification before executing
4
+ memory-intensive operations to prevent OOM crashes.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.core.memory_check import check_operation_memory, require_memory
9
+ >>> check = check_operation_memory('spectrogram', samples=1e9, nperseg=4096)
10
+ >>> if not check.sufficient:
11
+ ... print(check.recommendation)
12
+
13
+ References:
14
+ See oscura.utils.memory for memory estimation functions.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from typing import TYPE_CHECKING, Any
20
+
21
+ from oscura.utils.memory import (
22
+ MemoryCheck,
23
+ MemoryCheckError,
24
+ check_memory_available,
25
+ require_memory,
26
+ )
27
+
28
+ if TYPE_CHECKING:
29
+ from collections.abc import Callable
30
+
31
+
32
+ # Operations that automatically perform memory checks
33
+ _AUTO_CHECK_OPERATIONS = {
34
+ "fft",
35
+ "psd",
36
+ "spectrogram",
37
+ "eye_diagram",
38
+ "correlate",
39
+ "filter",
40
+ "stft",
41
+ "cwt",
42
+ "dwt",
43
+ }
44
+
45
+ # Global flag to bypass memory checks (use with caution)
46
+ _force_memory = False
47
+
48
+
49
+ def set_force_memory(enabled: bool) -> None:
50
+ """Enable or disable forced memory bypass.
51
+
52
+
53
+ Args:
54
+ enabled: If True, bypass memory checks (dangerous).
55
+
56
+ Warning:
57
+ Bypassing memory checks can lead to system crashes.
58
+ Only use when you are certain the operation will succeed.
59
+
60
+ Example:
61
+ >>> set_force_memory(True) # Bypass all memory checks
62
+ >>> # ... perform operation ...
63
+ >>> set_force_memory(False) # Re-enable checks
64
+ """
65
+ global _force_memory
66
+ _force_memory = enabled
67
+
68
+
69
+ def is_force_memory() -> bool:
70
+ """Check if memory checks are bypassed.
71
+
72
+ Returns:
73
+ True if memory checks are disabled.
74
+ """
75
+ return _force_memory
76
+
77
+
78
+ def check_operation_memory(
79
+ operation: str,
80
+ samples: int | float | None = None,
81
+ **kwargs: Any,
82
+ ) -> MemoryCheck:
83
+ """Check if sufficient memory is available for an operation.
84
+
85
+
86
+ This is a convenience wrapper around utils.memory.check_memory_available
87
+ with automatic bypass support.
88
+
89
+ Args:
90
+ operation: Operation name (fft, psd, spectrogram, etc.).
91
+ samples: Number of samples to process.
92
+ **kwargs: Additional operation-specific parameters.
93
+
94
+ Returns:
95
+ MemoryCheck with sufficiency status and recommendations.
96
+
97
+ Example:
98
+ >>> check = check_operation_memory('fft', samples=1e9, nfft=8192)
99
+ >>> if not check.sufficient:
100
+ ... print(f"Insufficient memory: {check.recommendation}")
101
+ """
102
+ # Bypass check if forced
103
+ if _force_memory:
104
+ return MemoryCheck(
105
+ sufficient=True,
106
+ available=0,
107
+ required=0,
108
+ recommendation="Memory check bypassed (--force-memory enabled)",
109
+ )
110
+
111
+ return check_memory_available(operation, samples, **kwargs)
112
+
113
+
114
+ def auto_check_memory(
115
+ operation: str,
116
+ samples: int | float | None = None,
117
+ **kwargs: Any,
118
+ ) -> None:
119
+ """Automatically check memory and raise error if insufficient.
120
+
121
+
122
+ This function is called automatically by operations that support
123
+ memory checking (fft, psd, spectrogram, etc.).
124
+
125
+ Args:
126
+ operation: Operation name.
127
+ samples: Number of samples.
128
+ **kwargs: Additional parameters.
129
+
130
+ Example:
131
+ >>> try:
132
+ ... auto_check_memory('spectrogram', samples=1e9, nperseg=4096)
133
+ ... except MemoryCheckError as e:
134
+ ... print(f"Memory check failed: {e}")
135
+ ... print(f"Suggestion: {e.recommendation}")
136
+
137
+ Note:
138
+ May raise MemoryCheckError if insufficient memory and not forced.
139
+ """
140
+ # Skip check if operation doesn't require it
141
+ if operation not in _AUTO_CHECK_OPERATIONS:
142
+ return
143
+
144
+ # Bypass if forced
145
+ if _force_memory:
146
+ return
147
+
148
+ # Perform check
149
+ require_memory(operation, samples, **kwargs)
150
+
151
+
152
+ def with_memory_check(func: Callable) -> Callable: # type: ignore[type-arg]
153
+ """Decorator to add automatic memory checking to a function.
154
+
155
+
156
+ The decorated function must accept 'samples' as a keyword argument
157
+ and should have an 'operation' attribute or name that matches
158
+ a supported operation type.
159
+
160
+ Args:
161
+ func: Function to decorate.
162
+
163
+ Returns:
164
+ Decorated function with memory checking.
165
+
166
+ Example:
167
+ >>> @with_memory_check
168
+ ... def my_fft(signal, samples=None, **kwargs):
169
+ ... # ... FFT implementation ...
170
+ ... pass
171
+ >>> my_fft.operation = 'fft' # Specify operation type
172
+ """
173
+
174
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
175
+ # Extract operation name
176
+ operation = getattr(func, "operation", func.__name__)
177
+
178
+ # Extract samples if available
179
+ samples = kwargs.get("samples")
180
+ if samples is None and len(args) > 0:
181
+ # Try to infer from first argument
182
+ try:
183
+ import numpy as np
184
+
185
+ if isinstance(args[0], np.ndarray):
186
+ samples = len(args[0])
187
+ except (ImportError, TypeError):
188
+ pass
189
+
190
+ # Perform check
191
+ if operation in _AUTO_CHECK_OPERATIONS and not _force_memory:
192
+ auto_check_memory(operation, samples, **kwargs)
193
+
194
+ # Call original function
195
+ return func(*args, **kwargs)
196
+
197
+ # Preserve function metadata
198
+ wrapper.__name__ = func.__name__
199
+ wrapper.__doc__ = func.__doc__
200
+ wrapper.__module__ = func.__module__
201
+
202
+ return wrapper
203
+
204
+
205
+ def register_auto_check_operation(operation: str) -> None:
206
+ """Register an operation for automatic memory checking.
207
+
208
+ Args:
209
+ operation: Operation name to register.
210
+
211
+ Example:
212
+ >>> register_auto_check_operation('custom_transform')
213
+ >>> # Now custom_transform will automatically check memory
214
+ """
215
+ _AUTO_CHECK_OPERATIONS.add(operation)
216
+
217
+
218
+ def unregister_auto_check_operation(operation: str) -> None:
219
+ """Unregister an operation from automatic memory checking.
220
+
221
+ Args:
222
+ operation: Operation name to unregister.
223
+
224
+ Example:
225
+ >>> unregister_auto_check_operation('custom_transform')
226
+ >>> # Now custom_transform will not automatically check memory
227
+ """
228
+ _AUTO_CHECK_OPERATIONS.discard(operation)
229
+
230
+
231
+ def _reset_auto_check_operations() -> None:
232
+ """Reset AUTO_CHECK_OPERATIONS to default state.
233
+
234
+ WARNING: This is for testing only. It resets the global state to defaults.
235
+ """
236
+ global _AUTO_CHECK_OPERATIONS
237
+ _AUTO_CHECK_OPERATIONS = {
238
+ "fft",
239
+ "psd",
240
+ "spectrogram",
241
+ "eye_diagram",
242
+ "correlate",
243
+ "filter",
244
+ "stft",
245
+ "cwt",
246
+ "dwt",
247
+ }
248
+
249
+
250
+ def get_auto_check_operations() -> set[str]:
251
+ """Get set of operations that automatically check memory.
252
+
253
+ Returns:
254
+ Set of operation names.
255
+
256
+ Example:
257
+ >>> ops = get_auto_check_operations()
258
+ >>> print(f"Auto-checked operations: {', '.join(sorted(ops))}")
259
+ """
260
+ return _AUTO_CHECK_OPERATIONS.copy()
261
+
262
+
263
+ __all__ = [
264
+ "MemoryCheck",
265
+ "MemoryCheckError",
266
+ "auto_check_memory",
267
+ "check_operation_memory",
268
+ "get_auto_check_operations",
269
+ "is_force_memory",
270
+ "register_auto_check_operation",
271
+ "set_force_memory",
272
+ "unregister_auto_check_operation",
273
+ "with_memory_check",
274
+ ]