oscura 0.0.1__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. oscura/__init__.py +813 -8
  2. oscura/__main__.py +392 -0
  3. oscura/analyzers/__init__.py +37 -0
  4. oscura/analyzers/digital/__init__.py +177 -0
  5. oscura/analyzers/digital/bus.py +691 -0
  6. oscura/analyzers/digital/clock.py +805 -0
  7. oscura/analyzers/digital/correlation.py +720 -0
  8. oscura/analyzers/digital/edges.py +632 -0
  9. oscura/analyzers/digital/extraction.py +413 -0
  10. oscura/analyzers/digital/quality.py +878 -0
  11. oscura/analyzers/digital/signal_quality.py +877 -0
  12. oscura/analyzers/digital/thresholds.py +708 -0
  13. oscura/analyzers/digital/timing.py +1104 -0
  14. oscura/analyzers/eye/__init__.py +46 -0
  15. oscura/analyzers/eye/diagram.py +434 -0
  16. oscura/analyzers/eye/metrics.py +555 -0
  17. oscura/analyzers/jitter/__init__.py +83 -0
  18. oscura/analyzers/jitter/ber.py +333 -0
  19. oscura/analyzers/jitter/decomposition.py +759 -0
  20. oscura/analyzers/jitter/measurements.py +413 -0
  21. oscura/analyzers/jitter/spectrum.py +220 -0
  22. oscura/analyzers/measurements.py +40 -0
  23. oscura/analyzers/packet/__init__.py +171 -0
  24. oscura/analyzers/packet/daq.py +1077 -0
  25. oscura/analyzers/packet/metrics.py +437 -0
  26. oscura/analyzers/packet/parser.py +327 -0
  27. oscura/analyzers/packet/payload.py +2156 -0
  28. oscura/analyzers/packet/payload_analysis.py +1312 -0
  29. oscura/analyzers/packet/payload_extraction.py +236 -0
  30. oscura/analyzers/packet/payload_patterns.py +670 -0
  31. oscura/analyzers/packet/stream.py +359 -0
  32. oscura/analyzers/patterns/__init__.py +266 -0
  33. oscura/analyzers/patterns/clustering.py +1036 -0
  34. oscura/analyzers/patterns/discovery.py +539 -0
  35. oscura/analyzers/patterns/learning.py +797 -0
  36. oscura/analyzers/patterns/matching.py +1091 -0
  37. oscura/analyzers/patterns/periodic.py +650 -0
  38. oscura/analyzers/patterns/sequences.py +767 -0
  39. oscura/analyzers/power/__init__.py +116 -0
  40. oscura/analyzers/power/ac_power.py +391 -0
  41. oscura/analyzers/power/basic.py +383 -0
  42. oscura/analyzers/power/conduction.py +314 -0
  43. oscura/analyzers/power/efficiency.py +297 -0
  44. oscura/analyzers/power/ripple.py +356 -0
  45. oscura/analyzers/power/soa.py +372 -0
  46. oscura/analyzers/power/switching.py +479 -0
  47. oscura/analyzers/protocol/__init__.py +150 -0
  48. oscura/analyzers/protocols/__init__.py +150 -0
  49. oscura/analyzers/protocols/base.py +500 -0
  50. oscura/analyzers/protocols/can.py +620 -0
  51. oscura/analyzers/protocols/can_fd.py +448 -0
  52. oscura/analyzers/protocols/flexray.py +405 -0
  53. oscura/analyzers/protocols/hdlc.py +399 -0
  54. oscura/analyzers/protocols/i2c.py +368 -0
  55. oscura/analyzers/protocols/i2s.py +296 -0
  56. oscura/analyzers/protocols/jtag.py +393 -0
  57. oscura/analyzers/protocols/lin.py +445 -0
  58. oscura/analyzers/protocols/manchester.py +333 -0
  59. oscura/analyzers/protocols/onewire.py +501 -0
  60. oscura/analyzers/protocols/spi.py +334 -0
  61. oscura/analyzers/protocols/swd.py +325 -0
  62. oscura/analyzers/protocols/uart.py +393 -0
  63. oscura/analyzers/protocols/usb.py +495 -0
  64. oscura/analyzers/signal_integrity/__init__.py +63 -0
  65. oscura/analyzers/signal_integrity/embedding.py +294 -0
  66. oscura/analyzers/signal_integrity/equalization.py +370 -0
  67. oscura/analyzers/signal_integrity/sparams.py +484 -0
  68. oscura/analyzers/spectral/__init__.py +53 -0
  69. oscura/analyzers/spectral/chunked.py +273 -0
  70. oscura/analyzers/spectral/chunked_fft.py +571 -0
  71. oscura/analyzers/spectral/chunked_wavelet.py +391 -0
  72. oscura/analyzers/spectral/fft.py +92 -0
  73. oscura/analyzers/statistical/__init__.py +250 -0
  74. oscura/analyzers/statistical/checksum.py +923 -0
  75. oscura/analyzers/statistical/chunked_corr.py +228 -0
  76. oscura/analyzers/statistical/classification.py +778 -0
  77. oscura/analyzers/statistical/entropy.py +1113 -0
  78. oscura/analyzers/statistical/ngrams.py +614 -0
  79. oscura/analyzers/statistics/__init__.py +119 -0
  80. oscura/analyzers/statistics/advanced.py +885 -0
  81. oscura/analyzers/statistics/basic.py +263 -0
  82. oscura/analyzers/statistics/correlation.py +630 -0
  83. oscura/analyzers/statistics/distribution.py +298 -0
  84. oscura/analyzers/statistics/outliers.py +463 -0
  85. oscura/analyzers/statistics/streaming.py +93 -0
  86. oscura/analyzers/statistics/trend.py +520 -0
  87. oscura/analyzers/validation.py +598 -0
  88. oscura/analyzers/waveform/__init__.py +36 -0
  89. oscura/analyzers/waveform/measurements.py +943 -0
  90. oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
  91. oscura/analyzers/waveform/spectral.py +1689 -0
  92. oscura/analyzers/waveform/wavelets.py +298 -0
  93. oscura/api/__init__.py +62 -0
  94. oscura/api/dsl.py +538 -0
  95. oscura/api/fluent.py +571 -0
  96. oscura/api/operators.py +498 -0
  97. oscura/api/optimization.py +392 -0
  98. oscura/api/profiling.py +396 -0
  99. oscura/automotive/__init__.py +73 -0
  100. oscura/automotive/can/__init__.py +52 -0
  101. oscura/automotive/can/analysis.py +356 -0
  102. oscura/automotive/can/checksum.py +250 -0
  103. oscura/automotive/can/correlation.py +212 -0
  104. oscura/automotive/can/discovery.py +355 -0
  105. oscura/automotive/can/message_wrapper.py +375 -0
  106. oscura/automotive/can/models.py +385 -0
  107. oscura/automotive/can/patterns.py +381 -0
  108. oscura/automotive/can/session.py +452 -0
  109. oscura/automotive/can/state_machine.py +300 -0
  110. oscura/automotive/can/stimulus_response.py +461 -0
  111. oscura/automotive/dbc/__init__.py +15 -0
  112. oscura/automotive/dbc/generator.py +156 -0
  113. oscura/automotive/dbc/parser.py +146 -0
  114. oscura/automotive/dtc/__init__.py +30 -0
  115. oscura/automotive/dtc/database.py +3036 -0
  116. oscura/automotive/j1939/__init__.py +14 -0
  117. oscura/automotive/j1939/decoder.py +745 -0
  118. oscura/automotive/loaders/__init__.py +35 -0
  119. oscura/automotive/loaders/asc.py +98 -0
  120. oscura/automotive/loaders/blf.py +77 -0
  121. oscura/automotive/loaders/csv_can.py +136 -0
  122. oscura/automotive/loaders/dispatcher.py +136 -0
  123. oscura/automotive/loaders/mdf.py +331 -0
  124. oscura/automotive/loaders/pcap.py +132 -0
  125. oscura/automotive/obd/__init__.py +14 -0
  126. oscura/automotive/obd/decoder.py +707 -0
  127. oscura/automotive/uds/__init__.py +48 -0
  128. oscura/automotive/uds/decoder.py +265 -0
  129. oscura/automotive/uds/models.py +64 -0
  130. oscura/automotive/visualization.py +369 -0
  131. oscura/batch/__init__.py +55 -0
  132. oscura/batch/advanced.py +627 -0
  133. oscura/batch/aggregate.py +300 -0
  134. oscura/batch/analyze.py +139 -0
  135. oscura/batch/logging.py +487 -0
  136. oscura/batch/metrics.py +556 -0
  137. oscura/builders/__init__.py +41 -0
  138. oscura/builders/signal_builder.py +1131 -0
  139. oscura/cli/__init__.py +14 -0
  140. oscura/cli/batch.py +339 -0
  141. oscura/cli/characterize.py +273 -0
  142. oscura/cli/compare.py +775 -0
  143. oscura/cli/decode.py +551 -0
  144. oscura/cli/main.py +247 -0
  145. oscura/cli/shell.py +350 -0
  146. oscura/comparison/__init__.py +66 -0
  147. oscura/comparison/compare.py +397 -0
  148. oscura/comparison/golden.py +487 -0
  149. oscura/comparison/limits.py +391 -0
  150. oscura/comparison/mask.py +434 -0
  151. oscura/comparison/trace_diff.py +30 -0
  152. oscura/comparison/visualization.py +481 -0
  153. oscura/compliance/__init__.py +70 -0
  154. oscura/compliance/advanced.py +756 -0
  155. oscura/compliance/masks.py +363 -0
  156. oscura/compliance/reporting.py +483 -0
  157. oscura/compliance/testing.py +298 -0
  158. oscura/component/__init__.py +38 -0
  159. oscura/component/impedance.py +365 -0
  160. oscura/component/reactive.py +598 -0
  161. oscura/component/transmission_line.py +312 -0
  162. oscura/config/__init__.py +191 -0
  163. oscura/config/defaults.py +254 -0
  164. oscura/config/loader.py +348 -0
  165. oscura/config/memory.py +271 -0
  166. oscura/config/migration.py +458 -0
  167. oscura/config/pipeline.py +1077 -0
  168. oscura/config/preferences.py +530 -0
  169. oscura/config/protocol.py +875 -0
  170. oscura/config/schema.py +713 -0
  171. oscura/config/settings.py +420 -0
  172. oscura/config/thresholds.py +599 -0
  173. oscura/convenience.py +457 -0
  174. oscura/core/__init__.py +299 -0
  175. oscura/core/audit.py +457 -0
  176. oscura/core/backend_selector.py +405 -0
  177. oscura/core/cache.py +590 -0
  178. oscura/core/cancellation.py +439 -0
  179. oscura/core/confidence.py +225 -0
  180. oscura/core/config.py +506 -0
  181. oscura/core/correlation.py +216 -0
  182. oscura/core/cross_domain.py +422 -0
  183. oscura/core/debug.py +301 -0
  184. oscura/core/edge_cases.py +541 -0
  185. oscura/core/exceptions.py +535 -0
  186. oscura/core/gpu_backend.py +523 -0
  187. oscura/core/lazy.py +832 -0
  188. oscura/core/log_query.py +540 -0
  189. oscura/core/logging.py +931 -0
  190. oscura/core/logging_advanced.py +952 -0
  191. oscura/core/memoize.py +171 -0
  192. oscura/core/memory_check.py +274 -0
  193. oscura/core/memory_guard.py +290 -0
  194. oscura/core/memory_limits.py +336 -0
  195. oscura/core/memory_monitor.py +453 -0
  196. oscura/core/memory_progress.py +465 -0
  197. oscura/core/memory_warnings.py +315 -0
  198. oscura/core/numba_backend.py +362 -0
  199. oscura/core/performance.py +352 -0
  200. oscura/core/progress.py +524 -0
  201. oscura/core/provenance.py +358 -0
  202. oscura/core/results.py +331 -0
  203. oscura/core/types.py +504 -0
  204. oscura/core/uncertainty.py +383 -0
  205. oscura/discovery/__init__.py +52 -0
  206. oscura/discovery/anomaly_detector.py +672 -0
  207. oscura/discovery/auto_decoder.py +415 -0
  208. oscura/discovery/comparison.py +497 -0
  209. oscura/discovery/quality_validator.py +528 -0
  210. oscura/discovery/signal_detector.py +769 -0
  211. oscura/dsl/__init__.py +73 -0
  212. oscura/dsl/commands.py +246 -0
  213. oscura/dsl/interpreter.py +455 -0
  214. oscura/dsl/parser.py +689 -0
  215. oscura/dsl/repl.py +172 -0
  216. oscura/exceptions.py +59 -0
  217. oscura/exploratory/__init__.py +111 -0
  218. oscura/exploratory/error_recovery.py +642 -0
  219. oscura/exploratory/fuzzy.py +513 -0
  220. oscura/exploratory/fuzzy_advanced.py +786 -0
  221. oscura/exploratory/legacy.py +831 -0
  222. oscura/exploratory/parse.py +358 -0
  223. oscura/exploratory/recovery.py +275 -0
  224. oscura/exploratory/sync.py +382 -0
  225. oscura/exploratory/unknown.py +707 -0
  226. oscura/export/__init__.py +25 -0
  227. oscura/export/wireshark/README.md +265 -0
  228. oscura/export/wireshark/__init__.py +47 -0
  229. oscura/export/wireshark/generator.py +312 -0
  230. oscura/export/wireshark/lua_builder.py +159 -0
  231. oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
  232. oscura/export/wireshark/type_mapping.py +165 -0
  233. oscura/export/wireshark/validator.py +105 -0
  234. oscura/exporters/__init__.py +94 -0
  235. oscura/exporters/csv.py +303 -0
  236. oscura/exporters/exporters.py +44 -0
  237. oscura/exporters/hdf5.py +219 -0
  238. oscura/exporters/html_export.py +701 -0
  239. oscura/exporters/json_export.py +291 -0
  240. oscura/exporters/markdown_export.py +367 -0
  241. oscura/exporters/matlab_export.py +354 -0
  242. oscura/exporters/npz_export.py +219 -0
  243. oscura/exporters/spice_export.py +210 -0
  244. oscura/extensibility/__init__.py +131 -0
  245. oscura/extensibility/docs.py +752 -0
  246. oscura/extensibility/extensions.py +1125 -0
  247. oscura/extensibility/logging.py +259 -0
  248. oscura/extensibility/measurements.py +485 -0
  249. oscura/extensibility/plugins.py +414 -0
  250. oscura/extensibility/registry.py +346 -0
  251. oscura/extensibility/templates.py +913 -0
  252. oscura/extensibility/validation.py +651 -0
  253. oscura/filtering/__init__.py +89 -0
  254. oscura/filtering/base.py +563 -0
  255. oscura/filtering/convenience.py +564 -0
  256. oscura/filtering/design.py +725 -0
  257. oscura/filtering/filters.py +32 -0
  258. oscura/filtering/introspection.py +605 -0
  259. oscura/guidance/__init__.py +24 -0
  260. oscura/guidance/recommender.py +429 -0
  261. oscura/guidance/wizard.py +518 -0
  262. oscura/inference/__init__.py +251 -0
  263. oscura/inference/active_learning/README.md +153 -0
  264. oscura/inference/active_learning/__init__.py +38 -0
  265. oscura/inference/active_learning/lstar.py +257 -0
  266. oscura/inference/active_learning/observation_table.py +230 -0
  267. oscura/inference/active_learning/oracle.py +78 -0
  268. oscura/inference/active_learning/teachers/__init__.py +15 -0
  269. oscura/inference/active_learning/teachers/simulator.py +192 -0
  270. oscura/inference/adaptive_tuning.py +453 -0
  271. oscura/inference/alignment.py +653 -0
  272. oscura/inference/bayesian.py +943 -0
  273. oscura/inference/binary.py +1016 -0
  274. oscura/inference/crc_reverse.py +711 -0
  275. oscura/inference/logic.py +288 -0
  276. oscura/inference/message_format.py +1305 -0
  277. oscura/inference/protocol.py +417 -0
  278. oscura/inference/protocol_dsl.py +1084 -0
  279. oscura/inference/protocol_library.py +1230 -0
  280. oscura/inference/sequences.py +809 -0
  281. oscura/inference/signal_intelligence.py +1509 -0
  282. oscura/inference/spectral.py +215 -0
  283. oscura/inference/state_machine.py +634 -0
  284. oscura/inference/stream.py +918 -0
  285. oscura/integrations/__init__.py +59 -0
  286. oscura/integrations/llm.py +1827 -0
  287. oscura/jupyter/__init__.py +32 -0
  288. oscura/jupyter/display.py +268 -0
  289. oscura/jupyter/magic.py +334 -0
  290. oscura/loaders/__init__.py +526 -0
  291. oscura/loaders/binary.py +69 -0
  292. oscura/loaders/configurable.py +1255 -0
  293. oscura/loaders/csv.py +26 -0
  294. oscura/loaders/csv_loader.py +473 -0
  295. oscura/loaders/hdf5.py +9 -0
  296. oscura/loaders/hdf5_loader.py +510 -0
  297. oscura/loaders/lazy.py +370 -0
  298. oscura/loaders/mmap_loader.py +583 -0
  299. oscura/loaders/numpy_loader.py +436 -0
  300. oscura/loaders/pcap.py +432 -0
  301. oscura/loaders/preprocessing.py +368 -0
  302. oscura/loaders/rigol.py +287 -0
  303. oscura/loaders/sigrok.py +321 -0
  304. oscura/loaders/tdms.py +367 -0
  305. oscura/loaders/tektronix.py +711 -0
  306. oscura/loaders/validation.py +584 -0
  307. oscura/loaders/vcd.py +464 -0
  308. oscura/loaders/wav.py +233 -0
  309. oscura/math/__init__.py +45 -0
  310. oscura/math/arithmetic.py +824 -0
  311. oscura/math/interpolation.py +413 -0
  312. oscura/onboarding/__init__.py +39 -0
  313. oscura/onboarding/help.py +498 -0
  314. oscura/onboarding/tutorials.py +405 -0
  315. oscura/onboarding/wizard.py +466 -0
  316. oscura/optimization/__init__.py +19 -0
  317. oscura/optimization/parallel.py +440 -0
  318. oscura/optimization/search.py +532 -0
  319. oscura/pipeline/__init__.py +43 -0
  320. oscura/pipeline/base.py +338 -0
  321. oscura/pipeline/composition.py +242 -0
  322. oscura/pipeline/parallel.py +448 -0
  323. oscura/pipeline/pipeline.py +375 -0
  324. oscura/pipeline/reverse_engineering.py +1119 -0
  325. oscura/plugins/__init__.py +122 -0
  326. oscura/plugins/base.py +272 -0
  327. oscura/plugins/cli.py +497 -0
  328. oscura/plugins/discovery.py +411 -0
  329. oscura/plugins/isolation.py +418 -0
  330. oscura/plugins/lifecycle.py +959 -0
  331. oscura/plugins/manager.py +493 -0
  332. oscura/plugins/registry.py +421 -0
  333. oscura/plugins/versioning.py +372 -0
  334. oscura/py.typed +0 -0
  335. oscura/quality/__init__.py +65 -0
  336. oscura/quality/ensemble.py +740 -0
  337. oscura/quality/explainer.py +338 -0
  338. oscura/quality/scoring.py +616 -0
  339. oscura/quality/warnings.py +456 -0
  340. oscura/reporting/__init__.py +248 -0
  341. oscura/reporting/advanced.py +1234 -0
  342. oscura/reporting/analyze.py +448 -0
  343. oscura/reporting/argument_preparer.py +596 -0
  344. oscura/reporting/auto_report.py +507 -0
  345. oscura/reporting/batch.py +615 -0
  346. oscura/reporting/chart_selection.py +223 -0
  347. oscura/reporting/comparison.py +330 -0
  348. oscura/reporting/config.py +615 -0
  349. oscura/reporting/content/__init__.py +39 -0
  350. oscura/reporting/content/executive.py +127 -0
  351. oscura/reporting/content/filtering.py +191 -0
  352. oscura/reporting/content/minimal.py +257 -0
  353. oscura/reporting/content/verbosity.py +162 -0
  354. oscura/reporting/core.py +508 -0
  355. oscura/reporting/core_formats/__init__.py +17 -0
  356. oscura/reporting/core_formats/multi_format.py +210 -0
  357. oscura/reporting/engine.py +836 -0
  358. oscura/reporting/export.py +366 -0
  359. oscura/reporting/formatting/__init__.py +129 -0
  360. oscura/reporting/formatting/emphasis.py +81 -0
  361. oscura/reporting/formatting/numbers.py +403 -0
  362. oscura/reporting/formatting/standards.py +55 -0
  363. oscura/reporting/formatting.py +466 -0
  364. oscura/reporting/html.py +578 -0
  365. oscura/reporting/index.py +590 -0
  366. oscura/reporting/multichannel.py +296 -0
  367. oscura/reporting/output.py +379 -0
  368. oscura/reporting/pdf.py +373 -0
  369. oscura/reporting/plots.py +731 -0
  370. oscura/reporting/pptx_export.py +360 -0
  371. oscura/reporting/renderers/__init__.py +11 -0
  372. oscura/reporting/renderers/pdf.py +94 -0
  373. oscura/reporting/sections.py +471 -0
  374. oscura/reporting/standards.py +680 -0
  375. oscura/reporting/summary_generator.py +368 -0
  376. oscura/reporting/tables.py +397 -0
  377. oscura/reporting/template_system.py +724 -0
  378. oscura/reporting/templates/__init__.py +15 -0
  379. oscura/reporting/templates/definition.py +205 -0
  380. oscura/reporting/templates/index.html +649 -0
  381. oscura/reporting/templates/index.md +173 -0
  382. oscura/schemas/__init__.py +158 -0
  383. oscura/schemas/bus_configuration.json +322 -0
  384. oscura/schemas/device_mapping.json +182 -0
  385. oscura/schemas/packet_format.json +418 -0
  386. oscura/schemas/protocol_definition.json +363 -0
  387. oscura/search/__init__.py +16 -0
  388. oscura/search/anomaly.py +292 -0
  389. oscura/search/context.py +149 -0
  390. oscura/search/pattern.py +160 -0
  391. oscura/session/__init__.py +34 -0
  392. oscura/session/annotations.py +289 -0
  393. oscura/session/history.py +313 -0
  394. oscura/session/session.py +445 -0
  395. oscura/streaming/__init__.py +43 -0
  396. oscura/streaming/chunked.py +611 -0
  397. oscura/streaming/progressive.py +393 -0
  398. oscura/streaming/realtime.py +622 -0
  399. oscura/testing/__init__.py +54 -0
  400. oscura/testing/synthetic.py +808 -0
  401. oscura/triggering/__init__.py +68 -0
  402. oscura/triggering/base.py +229 -0
  403. oscura/triggering/edge.py +353 -0
  404. oscura/triggering/pattern.py +344 -0
  405. oscura/triggering/pulse.py +581 -0
  406. oscura/triggering/window.py +453 -0
  407. oscura/ui/__init__.py +48 -0
  408. oscura/ui/formatters.py +526 -0
  409. oscura/ui/progressive_display.py +340 -0
  410. oscura/utils/__init__.py +99 -0
  411. oscura/utils/autodetect.py +338 -0
  412. oscura/utils/buffer.py +389 -0
  413. oscura/utils/lazy.py +407 -0
  414. oscura/utils/lazy_imports.py +147 -0
  415. oscura/utils/memory.py +836 -0
  416. oscura/utils/memory_advanced.py +1326 -0
  417. oscura/utils/memory_extensions.py +465 -0
  418. oscura/utils/progressive.py +352 -0
  419. oscura/utils/windowing.py +362 -0
  420. oscura/visualization/__init__.py +321 -0
  421. oscura/visualization/accessibility.py +526 -0
  422. oscura/visualization/annotations.py +374 -0
  423. oscura/visualization/axis_scaling.py +305 -0
  424. oscura/visualization/colors.py +453 -0
  425. oscura/visualization/digital.py +337 -0
  426. oscura/visualization/eye.py +420 -0
  427. oscura/visualization/histogram.py +281 -0
  428. oscura/visualization/interactive.py +858 -0
  429. oscura/visualization/jitter.py +702 -0
  430. oscura/visualization/keyboard.py +394 -0
  431. oscura/visualization/layout.py +365 -0
  432. oscura/visualization/optimization.py +1028 -0
  433. oscura/visualization/palettes.py +446 -0
  434. oscura/visualization/plot.py +92 -0
  435. oscura/visualization/power.py +290 -0
  436. oscura/visualization/power_extended.py +626 -0
  437. oscura/visualization/presets.py +467 -0
  438. oscura/visualization/protocols.py +932 -0
  439. oscura/visualization/render.py +207 -0
  440. oscura/visualization/rendering.py +444 -0
  441. oscura/visualization/reverse_engineering.py +791 -0
  442. oscura/visualization/signal_integrity.py +808 -0
  443. oscura/visualization/specialized.py +553 -0
  444. oscura/visualization/spectral.py +811 -0
  445. oscura/visualization/styles.py +381 -0
  446. oscura/visualization/thumbnails.py +311 -0
  447. oscura/visualization/time_axis.py +351 -0
  448. oscura/visualization/waveform.py +367 -0
  449. oscura/workflow/__init__.py +13 -0
  450. oscura/workflow/dag.py +377 -0
  451. oscura/workflows/__init__.py +58 -0
  452. oscura/workflows/compliance.py +280 -0
  453. oscura/workflows/digital.py +272 -0
  454. oscura/workflows/multi_trace.py +502 -0
  455. oscura/workflows/power.py +178 -0
  456. oscura/workflows/protocol.py +492 -0
  457. oscura/workflows/reverse_engineering.py +639 -0
  458. oscura/workflows/signal_integrity.py +227 -0
  459. oscura-0.1.0.dist-info/METADATA +300 -0
  460. oscura-0.1.0.dist-info/RECORD +463 -0
  461. oscura-0.1.0.dist-info/entry_points.txt +2 -0
  462. {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/licenses/LICENSE +1 -1
  463. oscura-0.0.1.dist-info/METADATA +0 -63
  464. oscura-0.0.1.dist-info/RECORD +0 -5
  465. {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,393 @@
1
+ """Progressive streaming analysis with incremental confidence.
2
+
3
+ Enables real-time analysis with confidence that increases as more data
4
+ is processed, allowing early stopping when confidence is sufficient.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import logging
10
+ from collections import deque
11
+ from collections.abc import Callable
12
+ from dataclasses import dataclass
13
+ from typing import TYPE_CHECKING, Any
14
+
15
+ import numpy as np
16
+
17
+ from ..quality.scoring import assess_data_quality
18
+
19
+ if TYPE_CHECKING:
20
+ from numpy.typing import NDArray
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ @dataclass
26
+ class StreamingProgress:
27
+ """Progress update from streaming analysis.
28
+
29
+ Attributes:
30
+ samples_processed: Number of samples processed so far
31
+ total_samples: Total samples expected (None if unknown)
32
+ confidence: Current confidence level (0-1)
33
+ preliminary_results: Current analysis results
34
+ is_complete: Whether analysis is complete
35
+ can_stop_early: Whether confidence is sufficient for early stopping
36
+ message: Human-readable status message
37
+ """
38
+
39
+ samples_processed: int
40
+ total_samples: int | None
41
+ confidence: float
42
+ preliminary_results: dict[str, Any]
43
+ is_complete: bool = False
44
+ can_stop_early: bool = False
45
+ message: str = ""
46
+
47
+ @property
48
+ def progress_percent(self) -> float | None:
49
+ """Get progress as percentage if total is known.
50
+
51
+ Returns:
52
+ Progress percentage (0-100) or None if total unknown
53
+ """
54
+ if self.total_samples:
55
+ return 100.0 * self.samples_processed / self.total_samples
56
+ return None
57
+
58
+
59
+ @dataclass
60
+ class StreamingConfig:
61
+ """Configuration for streaming analysis.
62
+
63
+ Attributes:
64
+ chunk_size: Samples per processing chunk
65
+ overlap: Overlap ratio between chunks (0-1)
66
+ min_samples_for_result: Minimum samples before generating results
67
+ early_stop_confidence: Confidence threshold for early stopping
68
+ max_buffer_size: Maximum buffer size to maintain
69
+ update_interval_samples: Samples between progress updates
70
+ """
71
+
72
+ chunk_size: int = 1024
73
+ overlap: float = 0.25
74
+ min_samples_for_result: int = 100
75
+ early_stop_confidence: float = 0.9
76
+ max_buffer_size: int = 100000
77
+ update_interval_samples: int = 512
78
+
79
+
80
+ class ProgressiveAnalyzer:
81
+ """Streaming analyzer with progressive confidence updates.
82
+
83
+ Processes data in chunks and provides incremental updates with
84
+ increasing confidence as more data is analyzed. Enables early
85
+ stopping when confidence threshold is met.
86
+
87
+ API-004: Real-time streaming analysis
88
+ QUAL-001: Quality scoring with progressive confidence
89
+
90
+ Example:
91
+ >>> analyzer = ProgressiveAnalyzer(sample_rate=1000.0)
92
+ >>> analyzer.subscribe(lambda p: print(f"Confidence: {p.confidence:.0%}"))
93
+ >>> progress = analyzer.process_chunk(data_chunk)
94
+ >>> if progress.can_stop_early:
95
+ ... final = analyzer.finalize()
96
+ """
97
+
98
+ def __init__(
99
+ self,
100
+ sample_rate: float = 1.0,
101
+ config: StreamingConfig | None = None,
102
+ ):
103
+ """Initialize progressive analyzer.
104
+
105
+ Args:
106
+ sample_rate: Sample rate in Hz
107
+ config: Streaming configuration
108
+ """
109
+ self.sample_rate = sample_rate
110
+ self.config = config or StreamingConfig()
111
+
112
+ # Internal state
113
+ self._buffer: deque[float] = deque(maxlen=self.config.max_buffer_size)
114
+ self._samples_processed = 0
115
+ self._current_results: dict[str, Any] = {}
116
+ self._confidence = 0.0
117
+ self._callbacks: list[Callable[[StreamingProgress], None]] = []
118
+
119
+ # Running statistics (incremental calculation)
120
+ self._sum = 0.0
121
+ self._sum_sq = 0.0
122
+ self._min_val = float("inf")
123
+ self._max_val = float("-inf")
124
+
125
+ # Frequency estimation state
126
+ self._zero_crossings: list[int] = []
127
+ self._last_sign = 0
128
+
129
+ def reset(self) -> None:
130
+ """Reset analyzer state to initial conditions."""
131
+ self._buffer.clear()
132
+ self._samples_processed = 0
133
+ self._current_results = {}
134
+ self._confidence = 0.0
135
+ self._sum = 0.0
136
+ self._sum_sq = 0.0
137
+ self._min_val = float("inf")
138
+ self._max_val = float("-inf")
139
+ self._zero_crossings = []
140
+ self._last_sign = 0
141
+
142
+ def subscribe(self, callback: Callable[[StreamingProgress], None]) -> None:
143
+ """Subscribe to progress updates.
144
+
145
+ Args:
146
+ callback: Function called with StreamingProgress updates
147
+ """
148
+ self._callbacks.append(callback)
149
+
150
+ def process_chunk(self, chunk: NDArray[np.float64]) -> StreamingProgress:
151
+ """Process a chunk of data.
152
+
153
+ Args:
154
+ chunk: Data chunk to process
155
+
156
+ Returns:
157
+ StreamingProgress with current state
158
+ """
159
+ chunk_arr = np.asarray(chunk).flatten()
160
+
161
+ # Handle empty chunks
162
+ if len(chunk_arr) == 0:
163
+ return StreamingProgress(
164
+ samples_processed=self._samples_processed,
165
+ total_samples=None,
166
+ confidence=self._confidence,
167
+ preliminary_results=self._current_results.copy(),
168
+ is_complete=False,
169
+ can_stop_early=self._confidence >= self.config.early_stop_confidence,
170
+ message=self._get_status_message(),
171
+ )
172
+
173
+ # Add to buffer
174
+ for val in chunk_arr:
175
+ self._buffer.append(val)
176
+
177
+ # Update running statistics
178
+ self._update_statistics(chunk_arr)
179
+
180
+ # Update frequency estimation
181
+ self._update_frequency_estimation(chunk_arr)
182
+
183
+ self._samples_processed += len(chunk_arr)
184
+
185
+ # Calculate current confidence
186
+ self._update_confidence()
187
+
188
+ # Generate preliminary results
189
+ self._update_results()
190
+
191
+ # Create progress update
192
+ progress = StreamingProgress(
193
+ samples_processed=self._samples_processed,
194
+ total_samples=None,
195
+ confidence=self._confidence,
196
+ preliminary_results=self._current_results.copy(),
197
+ is_complete=False,
198
+ can_stop_early=self._confidence >= self.config.early_stop_confidence,
199
+ message=self._get_status_message(),
200
+ )
201
+
202
+ # Notify subscribers
203
+ if self._samples_processed % self.config.update_interval_samples < len(chunk_arr):
204
+ self._notify(progress)
205
+
206
+ return progress
207
+
208
+ def finalize(self) -> StreamingProgress:
209
+ """Finalize analysis and return final results.
210
+
211
+ Returns:
212
+ Final StreamingProgress with complete results
213
+ """
214
+ # Do final calculations with all buffered data
215
+ if self._buffer:
216
+ buffer_array = np.array(list(self._buffer))
217
+
218
+ # Enhanced frequency detection with full buffer
219
+ self._current_results["frequency_final"] = self._detect_frequency_fft(buffer_array)
220
+
221
+ # Final quality assessment
222
+ data_quality = assess_data_quality(buffer_array, self.sample_rate)
223
+ self._current_results["data_quality"] = {
224
+ "snr_db": data_quality.snr_db,
225
+ "sample_count": data_quality.sample_count,
226
+ "completeness": data_quality.completeness,
227
+ }
228
+
229
+ self._confidence = min(1.0, self._confidence * 1.1) # Boost for finalization
230
+
231
+ progress = StreamingProgress(
232
+ samples_processed=self._samples_processed,
233
+ total_samples=self._samples_processed,
234
+ confidence=self._confidence,
235
+ preliminary_results=self._current_results.copy(),
236
+ is_complete=True,
237
+ can_stop_early=False,
238
+ message="Analysis complete",
239
+ )
240
+
241
+ self._notify(progress)
242
+ return progress
243
+
244
+ def _update_statistics(self, chunk: NDArray[np.float64]) -> None:
245
+ """Update running statistics with new chunk."""
246
+ self._sum += float(np.sum(chunk))
247
+ self._sum_sq += float(np.sum(chunk**2))
248
+ self._min_val = min(self._min_val, float(np.min(chunk)))
249
+ self._max_val = max(self._max_val, float(np.max(chunk)))
250
+
251
+ def _update_frequency_estimation(self, chunk: NDArray[np.float64]) -> None:
252
+ """Update frequency estimation from zero crossings."""
253
+ # Track zero crossings
254
+ mean_val = self._sum / max(1, self._samples_processed)
255
+
256
+ for i, val in enumerate(chunk):
257
+ current_sign = 1 if val > mean_val else -1
258
+ if self._last_sign != 0 and current_sign != self._last_sign:
259
+ self._zero_crossings.append(self._samples_processed - len(chunk) + i)
260
+ self._last_sign = current_sign
261
+
262
+ def _update_confidence(self) -> None:
263
+ """Update confidence based on data processed."""
264
+ # Base confidence from sample count (logarithmic)
265
+ sample_factor = min(1.0, np.log10(max(1, self._samples_processed)) / 4.0)
266
+
267
+ # Frequency confidence from consistent zero crossings
268
+ freq_factor = 0.5
269
+ if len(self._zero_crossings) > 10:
270
+ intervals = np.diff(self._zero_crossings)
271
+ if len(intervals) > 5:
272
+ cv = np.std(intervals) / (np.mean(intervals) + 1e-10)
273
+ freq_factor = min(1.0, 1.0 - cv)
274
+
275
+ # Combine factors - ensure monotonic increase by taking max with previous
276
+ new_confidence = 0.4 * sample_factor + 0.4 * freq_factor + 0.2
277
+ self._confidence = max(self._confidence, new_confidence)
278
+
279
+ def _update_results(self) -> None:
280
+ """Update preliminary results."""
281
+ n = self._samples_processed
282
+ if n < self.config.min_samples_for_result:
283
+ return
284
+
285
+ # Running mean and std
286
+ mean = self._sum / n
287
+ variance = (self._sum_sq / n) - (mean**2)
288
+ std = np.sqrt(max(0, variance))
289
+
290
+ self._current_results.update(
291
+ {
292
+ "mean": mean,
293
+ "std": std,
294
+ "min": self._min_val,
295
+ "max": self._max_val,
296
+ "amplitude": self._max_val - self._min_val,
297
+ "sample_count": n,
298
+ }
299
+ )
300
+
301
+ # Frequency from zero crossings
302
+ if len(self._zero_crossings) > 4:
303
+ intervals = np.diff(self._zero_crossings)
304
+ avg_half_period = np.mean(intervals) / self.sample_rate
305
+ if avg_half_period > 0:
306
+ self._current_results["frequency_estimate"] = 0.5 / avg_half_period
307
+
308
+ def _detect_frequency_fft(self, data: NDArray[np.float64]) -> float | None:
309
+ """Detect frequency using FFT on full buffer.
310
+
311
+ Args:
312
+ data: Signal data
313
+
314
+ Returns:
315
+ Dominant frequency in Hz or None if detection failed
316
+ """
317
+ try:
318
+ data_ac = data - np.mean(data)
319
+ fft_result = np.fft.rfft(data_ac)
320
+ freqs = np.fft.rfftfreq(len(data_ac), d=1.0 / self.sample_rate)
321
+ magnitude = np.abs(fft_result[1:])
322
+
323
+ if len(magnitude) > 0:
324
+ peak_idx = np.argmax(magnitude)
325
+ return float(freqs[1:][peak_idx])
326
+ except Exception:
327
+ pass
328
+ return None
329
+
330
+ def _get_status_message(self) -> str:
331
+ """Generate status message.
332
+
333
+ Returns:
334
+ Human-readable status string
335
+ """
336
+ if self._samples_processed < self.config.min_samples_for_result:
337
+ return f"Collecting data... ({self._samples_processed} samples)"
338
+
339
+ if self._confidence < 0.5:
340
+ return f"Low confidence ({self._confidence:.0%}), collecting more data..."
341
+ elif self._confidence < 0.8:
342
+ return f"Medium confidence ({self._confidence:.0%}), analysis in progress"
343
+ else:
344
+ return f"High confidence ({self._confidence:.0%}), results reliable"
345
+
346
+ def _notify(self, progress: StreamingProgress) -> None:
347
+ """Notify all subscribers.
348
+
349
+ Args:
350
+ progress: Progress update to send
351
+ """
352
+ for callback in self._callbacks:
353
+ try:
354
+ callback(progress)
355
+ except Exception as e:
356
+ logger.debug(f"Callback error: {e}")
357
+
358
+
359
+ def create_progressive_analyzer(
360
+ sample_rate: float = 1.0,
361
+ chunk_size: int = 1024,
362
+ early_stop_confidence: float = 0.9,
363
+ ) -> ProgressiveAnalyzer:
364
+ """Create a progressive analyzer with common settings.
365
+
366
+ Args:
367
+ sample_rate: Sample rate in Hz
368
+ chunk_size: Samples per chunk
369
+ early_stop_confidence: Confidence threshold for early stopping
370
+
371
+ Returns:
372
+ Configured ProgressiveAnalyzer
373
+
374
+ Example:
375
+ >>> analyzer = create_progressive_analyzer(
376
+ ... sample_rate=1000.0,
377
+ ... chunk_size=512,
378
+ ... early_stop_confidence=0.85
379
+ ... )
380
+ """
381
+ config = StreamingConfig(
382
+ chunk_size=chunk_size,
383
+ early_stop_confidence=early_stop_confidence,
384
+ )
385
+ return ProgressiveAnalyzer(sample_rate, config)
386
+
387
+
388
+ __all__ = [
389
+ "ProgressiveAnalyzer",
390
+ "StreamingConfig",
391
+ "StreamingProgress",
392
+ "create_progressive_analyzer",
393
+ ]