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,368 @@
1
+ """Natural language summary generation for signal analysis.
2
+
3
+ This module generates human-readable descriptions of measurements and analysis
4
+ results that avoid jargon and explain findings in accessible language.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.reporting import generate_summary
9
+ >>> trace = load("capture.wfm")
10
+ >>> summary = generate_summary(trace)
11
+ >>> print(summary.text)
12
+
13
+ References:
14
+ Oscura Auto-Discovery Specification
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from dataclasses import dataclass, field
20
+ from typing import TYPE_CHECKING, Any
21
+
22
+ import numpy as np
23
+
24
+ if TYPE_CHECKING:
25
+ from oscura.core.types import WaveformTrace
26
+
27
+
28
+ @dataclass
29
+ class Finding:
30
+ """Individual analysis finding.
31
+
32
+ Attributes:
33
+ title: Short title for the finding.
34
+ description: Plain language description.
35
+ confidence: Confidence score (0.0-1.0).
36
+ severity: Severity level (INFO, WARNING, CRITICAL).
37
+ """
38
+
39
+ title: str
40
+ description: str
41
+ confidence: float = 1.0
42
+ severity: str = "INFO"
43
+
44
+
45
+ @dataclass
46
+ class Summary:
47
+ """Natural language summary of signal analysis.
48
+
49
+ Attributes:
50
+ text: Complete summary text (2-3 sentences, 100-200 words).
51
+ overview: High-level overview sentence.
52
+ findings: List of key findings (minimum 3).
53
+ recommendations: Actionable insights and next steps.
54
+ word_count: Number of words in summary text.
55
+ grade_level: Flesch-Kincaid grade level.
56
+ """
57
+
58
+ text: str
59
+ overview: str
60
+ findings: list[Finding] = field(default_factory=list)
61
+ recommendations: list[str] = field(default_factory=list)
62
+ word_count: int = 0
63
+ grade_level: float = 0.0
64
+
65
+
66
+ def _estimate_grade_level(text: str) -> float:
67
+ """Estimate Flesch-Kincaid grade level.
68
+
69
+ Simple approximation based on sentence and word length.
70
+
71
+ Args:
72
+ text: Text to analyze.
73
+
74
+ Returns:
75
+ Estimated grade level.
76
+ """
77
+ # Split into sentences (simple split on period)
78
+ sentences = [s.strip() for s in text.split(".") if s.strip()]
79
+ if not sentences:
80
+ return 0.0
81
+
82
+ # Split into words
83
+ words = text.split()
84
+ if not words:
85
+ return 0.0
86
+
87
+ # Count syllables (approximation: count vowel groups)
88
+ total_syllables = 0
89
+ for word in words:
90
+ word_lower = word.lower()
91
+ syllable_count = 0
92
+ previous_was_vowel = False
93
+
94
+ for char in word_lower:
95
+ is_vowel = char in "aeiouy"
96
+ if is_vowel and not previous_was_vowel:
97
+ syllable_count += 1
98
+ previous_was_vowel = is_vowel
99
+
100
+ # Minimum 1 syllable per word
101
+ total_syllables += max(1, syllable_count)
102
+
103
+ # Flesch-Kincaid formula
104
+ avg_words_per_sentence = len(words) / len(sentences)
105
+ avg_syllables_per_word = total_syllables / len(words)
106
+
107
+ grade_level = 0.39 * avg_words_per_sentence + 11.8 * avg_syllables_per_word - 15.59
108
+
109
+ return max(0.0, grade_level)
110
+
111
+
112
+ def _characterize_signal_type(trace: WaveformTrace) -> tuple[str, float]:
113
+ """Characterize basic signal type.
114
+
115
+ Simple heuristic-based signal type detection.
116
+
117
+ Args:
118
+ trace: Waveform to analyze.
119
+
120
+ Returns:
121
+ Tuple of (signal_type, confidence).
122
+ """
123
+ data = trace.data.astype(np.float64)
124
+
125
+ # Check if digital (only 2-3 distinct levels)
126
+ unique_values = len(np.unique(np.round(data, decimals=2)))
127
+ value_range = np.ptp(data)
128
+
129
+ if unique_values <= 3 and value_range > 0.1:
130
+ # Likely digital
131
+ return "digital", 0.85
132
+ elif value_range < 0.01:
133
+ # Constant signal
134
+ return "DC level", 0.90
135
+ else:
136
+ # Analog
137
+ # Check for periodicity
138
+ if len(data) > 100:
139
+ autocorr = np.correlate(data - np.mean(data), data - np.mean(data), mode="full")
140
+ autocorr = autocorr[len(autocorr) // 2 :]
141
+ autocorr = autocorr / autocorr[0]
142
+
143
+ # Look for peaks in autocorrelation
144
+ if len(autocorr) > 10 and np.max(autocorr[10:]) > 0.5:
145
+ return "periodic analog", 0.75
146
+ return "analog", 0.70
147
+
148
+
149
+ def _assess_quality(trace: WaveformTrace) -> tuple[str, list[str]]:
150
+ """Assess signal quality.
151
+
152
+ Args:
153
+ trace: Waveform to analyze.
154
+
155
+ Returns:
156
+ Tuple of (quality_level, issues).
157
+ """
158
+ data = trace.data.astype(np.float64)
159
+ issues = []
160
+
161
+ # Check for sufficient data
162
+ if len(data) < 100:
163
+ issues.append("Very short capture (less than 100 samples)")
164
+
165
+ # Check noise level (standard deviation relative to range)
166
+ data_range = np.ptp(data)
167
+ if data_range > 0:
168
+ noise_ratio = np.std(data) / data_range
169
+ if noise_ratio > 0.2:
170
+ issues.append("High noise level detected")
171
+
172
+ # Check for clipping
173
+ if len(data) > 0:
174
+ data_min = np.min(data)
175
+ data_max = np.max(data)
176
+
177
+ # Check if many samples at min/max (possible clipping)
178
+ at_min = np.sum(data == data_min)
179
+ at_max = np.sum(data == data_max)
180
+
181
+ if at_min > len(data) * 0.05:
182
+ issues.append("Possible clipping at minimum level")
183
+ if at_max > len(data) * 0.05:
184
+ issues.append("Possible clipping at maximum level")
185
+
186
+ # Determine quality level
187
+ if not issues:
188
+ quality = "excellent"
189
+ elif len(issues) == 1:
190
+ quality = "good"
191
+ elif len(issues) == 2:
192
+ quality = "fair"
193
+ else:
194
+ quality = "poor"
195
+
196
+ return quality, issues
197
+
198
+
199
+ def _format_frequency(freq_hz: float) -> str:
200
+ """Format frequency in human-readable form.
201
+
202
+ Args:
203
+ freq_hz: Frequency in Hz.
204
+
205
+ Returns:
206
+ Formatted string.
207
+ """
208
+ if freq_hz >= 1e9:
209
+ return f"{freq_hz / 1e9:.1f} GHz"
210
+ elif freq_hz >= 1e6:
211
+ return f"{freq_hz / 1e6:.1f} MHz"
212
+ elif freq_hz >= 1e3:
213
+ return f"{freq_hz / 1e3:.1f} kHz"
214
+ else:
215
+ return f"{freq_hz:.1f} Hz"
216
+
217
+
218
+ def generate_summary(
219
+ trace: WaveformTrace,
220
+ *,
221
+ context: dict[str, Any] | None = None,
222
+ detail_level: str = "summary",
223
+ max_words: int = 200,
224
+ include_sections: list[str] | None = None,
225
+ ) -> Summary:
226
+ """Generate natural language summary of signal analysis.
227
+
228
+ Creates a plain-English description of the signal and analysis results,
229
+ avoiding technical jargon and explaining findings in accessible terms.
230
+
231
+ Args:
232
+ trace: Waveform to summarize.
233
+ context: Optional analysis context (characterization, anomalies, etc.).
234
+ detail_level: Summary detail level ("summary", "intermediate", "expert").
235
+ max_words: Maximum word count for summary text.
236
+ include_sections: Sections to include (default: all).
237
+
238
+ Returns:
239
+ Summary object with natural language description.
240
+
241
+ Example:
242
+ >>> trace = load("uart_signal.wfm")
243
+ >>> summary = generate_summary(trace)
244
+ >>> print(summary.text)
245
+ This is a digital signal with two voltage levels...
246
+
247
+ References:
248
+ DISC-003: Natural Language Summaries
249
+ """
250
+ context = context or {}
251
+ include_sections = include_sections or ["overview", "findings", "recommendations"]
252
+
253
+ # Characterize signal type
254
+ signal_type, type_confidence = _characterize_signal_type(trace)
255
+
256
+ # Assess quality
257
+ quality_level, quality_issues = _assess_quality(trace)
258
+
259
+ # Build overview
260
+ sample_rate = trace.metadata.sample_rate
261
+ duration_ms = len(trace.data) / sample_rate * 1000
262
+
263
+ overview = f"This is a {signal_type} signal captured at {_format_frequency(sample_rate)} sample rate for {duration_ms:.1f} milliseconds."
264
+
265
+ # Build findings
266
+ findings = []
267
+
268
+ # Signal type finding
269
+ findings.append(
270
+ Finding(
271
+ title="Signal Type",
272
+ description=f"Identified as {signal_type}",
273
+ confidence=type_confidence,
274
+ severity="INFO",
275
+ )
276
+ )
277
+
278
+ # Quality finding
279
+ quality_desc = f"Signal quality is {quality_level}"
280
+ if quality_issues:
281
+ quality_desc += f" with {len(quality_issues)} issue(s) noted"
282
+
283
+ findings.append(
284
+ Finding(
285
+ title="Signal Quality",
286
+ description=quality_desc,
287
+ confidence=0.85,
288
+ severity="WARNING" if quality_issues else "INFO",
289
+ )
290
+ )
291
+
292
+ # Voltage levels
293
+ v_min = float(np.min(trace.data))
294
+ v_max = float(np.max(trace.data))
295
+ v_range = v_max - v_min
296
+
297
+ findings.append(
298
+ Finding(
299
+ title="Voltage Range",
300
+ description=f"Signal ranges from {v_min:.3f}V to {v_max:.3f}V (swing: {v_range:.3f}V)",
301
+ confidence=1.0,
302
+ severity="INFO",
303
+ )
304
+ )
305
+
306
+ # Build recommendations
307
+ recommendations = []
308
+
309
+ if "very short" in str(quality_issues).lower():
310
+ recommendations.append("Capture a longer duration to enable more detailed analysis")
311
+
312
+ if "noise" in str(quality_issues).lower():
313
+ recommendations.append(
314
+ "Check signal integrity and consider using better probes or shielding"
315
+ )
316
+
317
+ if "clipping" in str(quality_issues).lower():
318
+ recommendations.append("Adjust voltage range to prevent signal clipping and data loss")
319
+
320
+ if signal_type == "digital" and not recommendations:
321
+ recommendations.append("Signal appears clean and suitable for digital protocol analysis")
322
+ elif signal_type in ["analog", "periodic analog"] and not recommendations:
323
+ recommendations.append("Consider spectral analysis to identify frequency components")
324
+
325
+ # Build complete summary text
326
+ summary_parts = []
327
+
328
+ if "overview" in include_sections:
329
+ summary_parts.append(overview)
330
+
331
+ if "findings" in include_sections and findings:
332
+ key_findings = findings[:3] # Top 3 findings
333
+ findings_text = " ".join(
334
+ [f"{finding.title}: {finding.description}." for finding in key_findings]
335
+ )
336
+ summary_parts.append(findings_text)
337
+
338
+ if "recommendations" in include_sections and recommendations:
339
+ rec_text = "Recommended next steps: " + "; ".join(recommendations[:2]) + "."
340
+ summary_parts.append(rec_text)
341
+
342
+ full_text = " ".join(summary_parts)
343
+
344
+ # Truncate to max_words if needed
345
+ words = full_text.split()
346
+ if len(words) > max_words:
347
+ words = words[:max_words]
348
+ full_text = " ".join(words) + "..."
349
+
350
+ # Calculate statistics
351
+ word_count = len(full_text.split())
352
+ grade_level = _estimate_grade_level(full_text)
353
+
354
+ return Summary(
355
+ text=full_text,
356
+ overview=overview,
357
+ findings=findings,
358
+ recommendations=recommendations,
359
+ word_count=word_count,
360
+ grade_level=grade_level,
361
+ )
362
+
363
+
364
+ __all__ = [
365
+ "Finding",
366
+ "Summary",
367
+ "generate_summary",
368
+ ]