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,360 @@
1
+ """PowerPoint presentation export for TraceKit reports.
2
+
3
+ This module provides PPTX generation for stakeholder presentations
4
+ with automated slide layouts, embedded plots, and speaker notes.
5
+
6
+
7
+ Note:
8
+ This is a stub implementation. For full functionality, install python-pptx:
9
+ pip install python-pptx
10
+
11
+ Example:
12
+ >>> from oscura.reporting import export_pptx
13
+ >>> data = {"title": "Analysis Report", "findings": [...]}
14
+ >>> export_pptx(data, "presentation.pptx")
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import logging
20
+ from dataclasses import dataclass, field
21
+ from pathlib import Path
22
+ from typing import Any
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+ # Check if python-pptx is available
27
+ try:
28
+ from pptx import Presentation
29
+ from pptx.util import Inches
30
+
31
+ PPTX_AVAILABLE = True
32
+ except ImportError:
33
+ PPTX_AVAILABLE = False
34
+ logger.warning("python-pptx not available. Install with: pip install python-pptx")
35
+
36
+
37
+ @dataclass
38
+ class PPTXSlide:
39
+ """PowerPoint slide configuration.
40
+
41
+ Attributes:
42
+ title: Slide title
43
+ content: Slide content (text, bullet points, or image path)
44
+ layout: Slide layout type
45
+ notes: Speaker notes
46
+ chart_data: Optional chart data to embed
47
+ """
48
+
49
+ title: str
50
+ content: str | list[str] | Path = ""
51
+ layout: str = "title_content" # title, title_content, content, blank
52
+ notes: str = ""
53
+ chart_data: dict[str, Any] | None = None
54
+
55
+
56
+ @dataclass
57
+ class PPTXPresentation:
58
+ """PowerPoint presentation configuration.
59
+
60
+ Attributes:
61
+ title: Presentation title
62
+ subtitle: Presentation subtitle
63
+ author: Author name
64
+ slides: List of slides
65
+ template: Optional template file path
66
+
67
+ References:
68
+ REPORT-023: PowerPoint/PPTX Export
69
+ """
70
+
71
+ title: str
72
+ subtitle: str = ""
73
+ author: str = ""
74
+ slides: list[PPTXSlide] = field(default_factory=list)
75
+ template: Path | None = None
76
+
77
+ def add_slide(
78
+ self,
79
+ title: str,
80
+ content: str | list[str] | Path = "",
81
+ *,
82
+ layout: str = "title_content",
83
+ notes: str = "",
84
+ ) -> PPTXSlide:
85
+ """Add slide to presentation.
86
+
87
+ Args:
88
+ title: Slide title
89
+ content: Slide content
90
+ layout: Layout type
91
+ notes: Speaker notes
92
+
93
+ Returns:
94
+ Created slide object
95
+ """
96
+ slide = PPTXSlide(title=title, content=content, layout=layout, notes=notes)
97
+ self.slides.append(slide)
98
+ return slide
99
+
100
+
101
+ def export_pptx(
102
+ report_data: dict[str, Any],
103
+ output_path: str | Path,
104
+ *,
105
+ title: str = "Analysis Report",
106
+ subtitle: str = "",
107
+ author: str = "",
108
+ template: Path | None = None,
109
+ ) -> Path:
110
+ """Export report data to PowerPoint presentation.
111
+
112
+ Args:
113
+ report_data: Report data dictionary containing:
114
+ - 'summary': Executive summary text
115
+ - 'findings': List of key findings
116
+ - 'measurements': Measurement results
117
+ - 'plots': List of plot image paths
118
+ output_path: Output PPTX file path
119
+ title: Presentation title
120
+ subtitle: Presentation subtitle
121
+ author: Author name
122
+ template: Optional template PPTX file
123
+
124
+ Returns:
125
+ Path to generated PPTX file
126
+
127
+ Example:
128
+ >>> data = {
129
+ ... 'summary': 'All tests passed',
130
+ ... 'findings': ['Rise time: 2.3ns', 'Fall time: 2.1ns'],
131
+ ... 'plots': [Path('plot1.png'), Path('plot2.png')]
132
+ ... }
133
+ >>> export_pptx(data, 'report.pptx', title='Signal Analysis')
134
+
135
+ References:
136
+ REPORT-023: PowerPoint/PPTX Export
137
+ """
138
+ output_path = Path(output_path)
139
+
140
+ if not PPTX_AVAILABLE:
141
+ # Create stub file
142
+ logger.warning("Creating stub PPTX file (python-pptx not installed)")
143
+ _create_stub_pptx(output_path, title, report_data)
144
+ return output_path
145
+
146
+ # Create presentation
147
+ prs = Presentation(str(template)) if template else Presentation()
148
+
149
+ # Title slide
150
+ _add_title_slide(prs, title, subtitle, author)
151
+
152
+ # Summary slide
153
+ summary = report_data.get("summary", "")
154
+ if summary:
155
+ _add_summary_slide(prs, summary)
156
+
157
+ # Key findings slides
158
+ findings = report_data.get("findings", [])
159
+ if findings:
160
+ _add_findings_slide(prs, findings)
161
+
162
+ # Measurement results slides
163
+ measurements = report_data.get("measurements", [])
164
+ if measurements:
165
+ _add_measurement_slides(prs, measurements)
166
+
167
+ # Plot slides
168
+ plots = report_data.get("plots", [])
169
+ for i, plot_path in enumerate(plots, 1):
170
+ _add_plot_slide(prs, plot_path, f"Figure {i}")
171
+
172
+ # Save presentation
173
+ prs.save(str(output_path))
174
+ logger.info("Exported PPTX presentation to %s", output_path)
175
+
176
+ return output_path
177
+
178
+
179
+ def _add_title_slide(
180
+ prs: Any,
181
+ title: str,
182
+ subtitle: str,
183
+ author: str,
184
+ ) -> None:
185
+ """Add title slide to presentation."""
186
+ if not PPTX_AVAILABLE:
187
+ return
188
+
189
+ slide = prs.slides.add_slide(prs.slide_layouts[0]) # Title slide layout
190
+
191
+ # Set title
192
+ if slide.shapes.title:
193
+ slide.shapes.title.text = title
194
+
195
+ # Set subtitle (placeholder 1)
196
+ if len(slide.placeholders) > 1:
197
+ subtitle_text = subtitle
198
+ if author:
199
+ subtitle_text += f"\n{author}"
200
+ slide.placeholders[1].text = subtitle_text
201
+
202
+
203
+ def _add_summary_slide(prs: Any, summary: str) -> None:
204
+ """Add executive summary slide."""
205
+ if not PPTX_AVAILABLE:
206
+ return
207
+
208
+ slide = prs.slides.add_slide(prs.slide_layouts[1]) # Title and content layout
209
+
210
+ if slide.shapes.title:
211
+ slide.shapes.title.text = "Executive Summary"
212
+
213
+ # Add summary text
214
+ if len(slide.placeholders) > 1:
215
+ text_frame = slide.placeholders[1].text_frame
216
+ text_frame.text = summary
217
+
218
+
219
+ def _add_findings_slide(prs: Any, findings: list[str]) -> None:
220
+ """Add key findings slide with bullet points."""
221
+ if not PPTX_AVAILABLE:
222
+ return
223
+
224
+ slide = prs.slides.add_slide(prs.slide_layouts[1]) # Title and content layout
225
+
226
+ if slide.shapes.title:
227
+ slide.shapes.title.text = "Key Findings"
228
+
229
+ # Add bullet points
230
+ if len(slide.placeholders) > 1:
231
+ text_frame = slide.placeholders[1].text_frame
232
+ text_frame.clear()
233
+
234
+ for finding in findings:
235
+ p = text_frame.add_paragraph()
236
+ p.text = finding
237
+ p.level = 0
238
+
239
+
240
+ def _add_measurement_slides(prs: Any, measurements: list[dict[str, Any]]) -> None:
241
+ """Add measurement results slides."""
242
+ if not PPTX_AVAILABLE:
243
+ return
244
+
245
+ # Group measurements into slides (5 per slide)
246
+ chunk_size = 5
247
+ for i in range(0, len(measurements), chunk_size):
248
+ chunk = measurements[i : i + chunk_size]
249
+
250
+ slide = prs.slides.add_slide(prs.slide_layouts[1])
251
+
252
+ if slide.shapes.title:
253
+ slide.shapes.title.text = f"Measurement Results ({i + 1}-{i + len(chunk)})"
254
+
255
+ # Add measurements as bullet points
256
+ if len(slide.placeholders) > 1:
257
+ text_frame = slide.placeholders[1].text_frame
258
+ text_frame.clear()
259
+
260
+ for meas in chunk:
261
+ p = text_frame.add_paragraph()
262
+ name = meas.get("name", "Unknown")
263
+ value = meas.get("value", "")
264
+ unit = meas.get("unit", "")
265
+ status = meas.get("status", "")
266
+
267
+ p.text = f"{name}: {value} {unit} {status}"
268
+ p.level = 0
269
+
270
+
271
+ def _add_plot_slide(prs: Any, plot_path: Path, caption: str) -> None:
272
+ """Add slide with embedded plot image."""
273
+ if not PPTX_AVAILABLE:
274
+ return
275
+
276
+ slide = prs.slides.add_slide(prs.slide_layouts[5]) # Blank layout
277
+
278
+ # Add title
279
+ if slide.shapes.title:
280
+ slide.shapes.title.text = caption
281
+
282
+ # Add image (centered)
283
+ if plot_path.exists():
284
+ left = Inches(1.5)
285
+ top = Inches(2)
286
+ width = Inches(7)
287
+
288
+ slide.shapes.add_picture(str(plot_path), left, top, width=width)
289
+
290
+
291
+ def _create_stub_pptx(
292
+ output_path: Path,
293
+ title: str,
294
+ report_data: dict[str, Any],
295
+ ) -> None:
296
+ """Create stub PPTX file when python-pptx not available."""
297
+ # Write text file with .pptx extension as placeholder
298
+ with output_path.open("w") as f:
299
+ f.write("PowerPoint Export Stub\n")
300
+ f.write("======================\n\n")
301
+ f.write(f"Title: {title}\n\n")
302
+ f.write("Install python-pptx for full PPTX export:\n")
303
+ f.write(" pip install python-pptx\n\n")
304
+ f.write("Report Data Summary:\n")
305
+ f.write(f" - Summary: {report_data.get('summary', 'N/A')}\n")
306
+ f.write(f" - Findings: {len(report_data.get('findings', []))} items\n")
307
+ f.write(f" - Measurements: {len(report_data.get('measurements', []))} items\n")
308
+ f.write(f" - Plots: {len(report_data.get('plots', []))} items\n")
309
+
310
+
311
+ def generate_presentation_from_report(
312
+ report: dict[str, Any],
313
+ output_path: str | Path,
314
+ *,
315
+ presentation_config: PPTXPresentation | None = None,
316
+ ) -> Path:
317
+ """Generate PowerPoint presentation from report structure.
318
+
319
+ Args:
320
+ report: Report dictionary with standard structure
321
+ output_path: Output file path
322
+ presentation_config: Optional presentation configuration
323
+
324
+ Returns:
325
+ Path to generated presentation
326
+
327
+ References:
328
+ REPORT-023: PowerPoint/PPTX Export
329
+ """
330
+ if presentation_config is None:
331
+ presentation_config = PPTXPresentation(
332
+ title=report.get("title", "Analysis Report"),
333
+ subtitle=report.get("subtitle", ""),
334
+ author=report.get("author", ""),
335
+ )
336
+
337
+ # Extract data from report
338
+ report_data = {
339
+ "summary": report.get("executive_summary", ""),
340
+ "findings": report.get("key_findings", []),
341
+ "measurements": report.get("measurements", []),
342
+ "plots": report.get("plot_paths", []),
343
+ }
344
+
345
+ return export_pptx(
346
+ report_data,
347
+ output_path,
348
+ title=presentation_config.title,
349
+ subtitle=presentation_config.subtitle,
350
+ author=presentation_config.author,
351
+ template=presentation_config.template,
352
+ )
353
+
354
+
355
+ __all__ = [
356
+ "PPTXPresentation",
357
+ "PPTXSlide",
358
+ "export_pptx",
359
+ "generate_presentation_from_report",
360
+ ]
@@ -0,0 +1,11 @@
1
+ """Renderers for different output formats."""
2
+
3
+ from oscura.reporting.renderers.pdf import (
4
+ PDFRenderer,
5
+ render_to_pdf,
6
+ )
7
+
8
+ __all__ = [
9
+ "PDFRenderer",
10
+ "render_to_pdf",
11
+ ]
@@ -0,0 +1,94 @@
1
+ """Enhanced PDF report generation.
2
+
3
+ High-quality PDF report generation with embedded plots, metadata,
4
+ and PDF/A compliance for archival (enhancements to existing PDF module).
5
+
6
+
7
+ References:
8
+ - REPORT-008: PDF Report Generation
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import dataclass
14
+ from typing import TYPE_CHECKING, Any
15
+
16
+ if TYPE_CHECKING:
17
+ from oscura.reporting.core import Report
18
+
19
+
20
+ @dataclass
21
+ class PDFRenderer:
22
+ """PDF report renderer.
23
+
24
+ Attributes:
25
+ dpi: Plot rendering DPI (default 300 for print quality).
26
+ embed_fonts: Embed fonts for consistency (default True).
27
+ vector_graphics: Use vector graphics for plots (default True).
28
+ table_of_contents: Include TOC (default True).
29
+ pdfa_compliance: Generate PDF/A-1b output (default False).
30
+ page_numbering: Include page numbers (default True).
31
+
32
+ References:
33
+ REPORT-008: PDF Report Generation Engine
34
+ """
35
+
36
+ dpi: int = 300
37
+ embed_fonts: bool = True
38
+ vector_graphics: bool = True
39
+ table_of_contents: bool = True
40
+ pdfa_compliance: bool = False
41
+ page_numbering: bool = True
42
+
43
+
44
+ def render_to_pdf(
45
+ report: Report,
46
+ output_path: str | None = None,
47
+ **kwargs: Any,
48
+ ) -> bytes:
49
+ """Render report to PDF.
50
+
51
+ Args:
52
+ report: Report object to render.
53
+ output_path: Optional output path (if None, returns bytes).
54
+ **kwargs: Additional PDF rendering options.
55
+
56
+ Returns:
57
+ PDF data as bytes (if output_path is None).
58
+
59
+ Example:
60
+ >>> from oscura.reporting.core import Report, ReportConfig
61
+ >>> report = Report(config=ReportConfig(title="Test Report"))
62
+ >>> pdf_bytes = render_to_pdf(report)
63
+
64
+ References:
65
+ REPORT-008: PDF Report Generation Engine
66
+ """
67
+ # Import existing PDF module
68
+ from oscura.reporting.pdf import generate_pdf_report
69
+
70
+ # Merge kwargs with defaults
71
+ renderer = PDFRenderer(**kwargs)
72
+
73
+ # Generate PDF
74
+ pdf_bytes = generate_pdf_report(
75
+ report,
76
+ dpi=renderer.dpi,
77
+ embed_fonts=renderer.embed_fonts,
78
+ vector_graphics=renderer.vector_graphics,
79
+ table_of_contents=renderer.table_of_contents,
80
+ pdfa_compliance=renderer.pdfa_compliance,
81
+ )
82
+
83
+ # Save if path provided
84
+ if output_path:
85
+ with open(output_path, "wb") as f:
86
+ f.write(pdf_bytes)
87
+
88
+ return pdf_bytes
89
+
90
+
91
+ __all__ = [
92
+ "PDFRenderer",
93
+ "render_to_pdf",
94
+ ]