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,507 @@
1
+ """Automatic executive report generation.
2
+
3
+ This module provides one-click generation of comprehensive analysis reports
4
+ in multiple formats (PDF, HTML, Markdown).
5
+
6
+
7
+ Example:
8
+ >>> from oscura.reporting import generate_report
9
+ >>> trace = load("capture.wfm")
10
+ >>> report = generate_report(trace)
11
+ >>> report.save_pdf("analysis_report.pdf")
12
+
13
+ References:
14
+ TraceKit Auto-Discovery Specification
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from dataclasses import dataclass, field
20
+ from datetime import datetime
21
+ from pathlib import Path
22
+ from typing import TYPE_CHECKING, Any
23
+
24
+ import numpy as np
25
+
26
+ if TYPE_CHECKING:
27
+ from oscura.core.types import WaveformTrace
28
+
29
+
30
+ @dataclass
31
+ class ReportMetadata:
32
+ """Report metadata.
33
+
34
+ Attributes:
35
+ title: Report title.
36
+ author: Report author.
37
+ date: Report date.
38
+ project: Project name.
39
+ tags: List of tags.
40
+ """
41
+
42
+ title: str = "Signal Analysis Report"
43
+ author: str = "TraceKit"
44
+ date: str = field(default_factory=lambda: datetime.now().strftime("%Y-%m-%d"))
45
+ project: str | None = None
46
+ tags: list[str] = field(default_factory=list)
47
+
48
+
49
+ @dataclass
50
+ class Report:
51
+ """Executive analysis report.
52
+
53
+ Attributes:
54
+ sections: List of section names included.
55
+ plots: List of plot types included.
56
+ page_count: Estimated page count.
57
+ metadata: Report metadata.
58
+ content: Dictionary of section content.
59
+ output_path: Path to saved report.
60
+ file_size_mb: File size in MB (if saved).
61
+ """
62
+
63
+ sections: list[str] = field(default_factory=list)
64
+ plots: list[str] = field(default_factory=list)
65
+ page_count: int = 0
66
+ metadata: ReportMetadata = field(default_factory=ReportMetadata)
67
+ content: dict[str, str] = field(default_factory=dict)
68
+ output_path: str | None = None
69
+ file_size_mb: float = 0.0
70
+
71
+ def save_pdf(self, path: str) -> None:
72
+ """Save report as PDF.
73
+
74
+ Args:
75
+ path: Output file path.
76
+
77
+ Note:
78
+ This is a placeholder implementation. Full PDF generation
79
+ would require reportlab or similar library.
80
+ """
81
+ self.output_path = path
82
+ # Placeholder: would generate actual PDF here
83
+ with open(path, "w") as f:
84
+ f.write("PDF Report - Placeholder\n")
85
+ f.write(f"Title: {self.metadata.title}\n")
86
+ f.write(f"Date: {self.metadata.date}\n\n")
87
+
88
+ for section in self.sections:
89
+ if section in self.content:
90
+ f.write(f"\n{section.upper()}\n")
91
+ f.write("=" * 60 + "\n")
92
+ f.write(self.content[section] + "\n")
93
+
94
+ # Estimate file size
95
+ self.file_size_mb = Path(path).stat().st_size / (1024 * 1024)
96
+
97
+ def save_html(self, path: str) -> None:
98
+ """Save report as HTML.
99
+
100
+ Args:
101
+ path: Output file path.
102
+ """
103
+ self.output_path = path
104
+
105
+ html_content = f"""<!DOCTYPE html>
106
+ <html>
107
+ <head>
108
+ <meta charset="UTF-8">
109
+ <title>{self.metadata.title}</title>
110
+ <style>
111
+ body {{
112
+ font-family: Arial, sans-serif;
113
+ max-width: 900px;
114
+ margin: 0 auto;
115
+ padding: 20px;
116
+ line-height: 1.6;
117
+ }}
118
+ h1 {{
119
+ color: #2c3e50;
120
+ border-bottom: 3px solid #3498db;
121
+ padding-bottom: 10px;
122
+ }}
123
+ h2 {{
124
+ color: #34495e;
125
+ margin-top: 30px;
126
+ border-bottom: 2px solid #ecf0f1;
127
+ padding-bottom: 5px;
128
+ }}
129
+ .metadata {{
130
+ background-color: #ecf0f1;
131
+ padding: 15px;
132
+ border-radius: 5px;
133
+ margin-bottom: 20px;
134
+ }}
135
+ .section {{
136
+ margin-bottom: 30px;
137
+ }}
138
+ .critical {{
139
+ color: #e74c3c;
140
+ font-weight: bold;
141
+ }}
142
+ .warning {{
143
+ color: #f39c12;
144
+ font-weight: bold;
145
+ }}
146
+ .info {{
147
+ color: #3498db;
148
+ }}
149
+ </style>
150
+ </head>
151
+ <body>
152
+ <h1>{self.metadata.title}</h1>
153
+
154
+ <div class="metadata">
155
+ <p><strong>Date:</strong> {self.metadata.date}</p>
156
+ <p><strong>Author:</strong> {self.metadata.author}</p>
157
+ """
158
+ if self.metadata.project:
159
+ html_content += f" <p><strong>Project:</strong> {self.metadata.project}</p>\n"
160
+
161
+ if self.metadata.tags:
162
+ html_content += (
163
+ f" <p><strong>Tags:</strong> {', '.join(self.metadata.tags)}</p>\n"
164
+ )
165
+
166
+ html_content += " </div>\n\n"
167
+
168
+ for section in self.sections:
169
+ if section in self.content:
170
+ section_title = section.replace("_", " ").title()
171
+ html_content += f""" <div class="section">
172
+ <h2>{section_title}</h2>
173
+ <p>{self.content[section]}</p>
174
+ </div>
175
+ """
176
+ html_content += """</body>
177
+ </html>"""
178
+ with open(path, "w") as f:
179
+ f.write(html_content)
180
+
181
+ self.file_size_mb = Path(path).stat().st_size / (1024 * 1024)
182
+
183
+ def save_markdown(self, path: str) -> None:
184
+ """Save report as Markdown.
185
+
186
+ Args:
187
+ path: Output file path.
188
+ """
189
+ self.output_path = path
190
+
191
+ md_content = f"# {self.metadata.title}\n\n"
192
+ md_content += f"**Date:** {self.metadata.date} \n"
193
+ md_content += f"**Author:** {self.metadata.author} \n"
194
+
195
+ if self.metadata.project:
196
+ md_content += f"**Project:** {self.metadata.project} \n"
197
+
198
+ if self.metadata.tags:
199
+ md_content += f"**Tags:** {', '.join(self.metadata.tags)} \n"
200
+
201
+ md_content += "\n---\n\n"
202
+
203
+ for section in self.sections:
204
+ if section in self.content:
205
+ section_title = section.replace("_", " ").title()
206
+ md_content += f"## {section_title}\n\n"
207
+ md_content += self.content[section] + "\n\n"
208
+
209
+ with open(path, "w") as f:
210
+ f.write(md_content)
211
+
212
+ self.file_size_mb = Path(path).stat().st_size / (1024 * 1024)
213
+
214
+ def add_section(
215
+ self,
216
+ title: str,
217
+ content: str,
218
+ position: int | None = None,
219
+ ) -> None:
220
+ """Add custom section to report.
221
+
222
+ Args:
223
+ title: Section title.
224
+ content: Section content.
225
+ position: Insert position (None = append).
226
+ """
227
+ section_key = title.lower().replace(" ", "_")
228
+
229
+ if position is None:
230
+ self.sections.append(section_key)
231
+ else:
232
+ self.sections.insert(position, section_key)
233
+
234
+ self.content[section_key] = content
235
+
236
+ def include_plots(self, plot_types: list[str]) -> None:
237
+ """Select which plots to include in report.
238
+
239
+ Args:
240
+ plot_types: List of plot type names.
241
+ """
242
+ self.plots = plot_types
243
+
244
+ def set_metadata(
245
+ self,
246
+ title: str | None = None,
247
+ author: str | None = None,
248
+ date: str | None = None,
249
+ project: str | None = None,
250
+ tags: list[str] | None = None,
251
+ ) -> None:
252
+ """Set report metadata.
253
+
254
+ Args:
255
+ title: Report title.
256
+ author: Report author.
257
+ date: Report date.
258
+ project: Project name.
259
+ tags: List of tags.
260
+ """
261
+ if title:
262
+ self.metadata.title = title
263
+ if author:
264
+ self.metadata.author = author
265
+ if date:
266
+ self.metadata.date = date
267
+ if project:
268
+ self.metadata.project = project
269
+ if tags:
270
+ self.metadata.tags = tags
271
+
272
+
273
+ def _generate_executive_summary(trace: WaveformTrace, context: dict) -> str: # type: ignore[type-arg]
274
+ """Generate executive summary section.
275
+
276
+ Args:
277
+ trace: Waveform to analyze.
278
+ context: Analysis context.
279
+
280
+ Returns:
281
+ Executive summary text (≤200 words).
282
+ """
283
+ sample_rate = trace.metadata.sample_rate
284
+ duration_ms = len(trace.data) / sample_rate * 1000
285
+ v_min = float(np.min(trace.data))
286
+ v_max = float(np.max(trace.data))
287
+
288
+ summary = "This report presents analysis of a signal capture taken at "
289
+ summary += f"{sample_rate / 1e6:.1f} MS/s sample rate over {duration_ms:.2f} milliseconds. "
290
+ summary += f"The signal ranges from {v_min:.3f}V to {v_max:.3f}V. "
291
+
292
+ # Add context-specific information
293
+ if "characterization" in context:
294
+ char = context["characterization"]
295
+ if hasattr(char, "signal_type"):
296
+ summary += f"The signal was identified as {char.signal_type}. "
297
+
298
+ if "quality" in context:
299
+ quality = context["quality"]
300
+ if hasattr(quality, "status"):
301
+ summary += f"Data quality assessment: {quality.status}. "
302
+
303
+ summary += "Detailed findings and recommendations are provided in the sections below."
304
+
305
+ return summary
306
+
307
+
308
+ def _generate_key_findings(trace: WaveformTrace, context: dict) -> str: # type: ignore[type-arg]
309
+ """Generate key findings section.
310
+
311
+ Args:
312
+ trace: Waveform to analyze.
313
+ context: Analysis context.
314
+
315
+ Returns:
316
+ Key findings text.
317
+ """
318
+ findings = []
319
+
320
+ # Basic signal characteristics
321
+ v_range = np.ptp(trace.data)
322
+ findings.append(f"Signal swing: {v_range:.3f}V")
323
+
324
+ # Add context-specific findings
325
+ if "anomalies" in context:
326
+ anomalies = context["anomalies"]
327
+ if hasattr(anomalies, "__len__"):
328
+ findings.append(f"Detected {len(anomalies)} anomalies in signal")
329
+
330
+ if "decode" in context:
331
+ decode = context["decode"]
332
+ if hasattr(decode, "data") and hasattr(decode.data, "__len__"):
333
+ findings.append(f"Successfully decoded {len(decode.data)} bytes")
334
+
335
+ # Format findings
336
+ findings_text = "Key findings from signal analysis:\n\n"
337
+ for i, finding in enumerate(findings, 1):
338
+ findings_text += f"{i}. {finding}\n"
339
+
340
+ return findings_text
341
+
342
+
343
+ def _generate_methodology(trace: WaveformTrace, context: dict[str, Any]) -> str:
344
+ """Generate methodology section.
345
+
346
+ Args:
347
+ trace: Waveform to analyze.
348
+ context: Analysis context.
349
+
350
+ Returns:
351
+ Methodology description.
352
+ """
353
+ methodology = "Analysis methodology:\n\n"
354
+
355
+ methodology += "Signal characterization: Automated signal type detection using "
356
+ methodology += "statistical analysis and pattern recognition algorithms.\n\n"
357
+
358
+ methodology += "Quality assessment: Signal-to-noise ratio, clipping detection, "
359
+ methodology += "and sample rate validation.\n\n"
360
+
361
+ if "anomalies" in context:
362
+ methodology += "Anomaly detection: Automated detection of glitches, dropouts, "
363
+ methodology += "noise spikes, and timing violations.\n\n"
364
+
365
+ if "decode" in context:
366
+ methodology += "Protocol decode: Automatic parameter detection and "
367
+ methodology += "frame extraction with confidence scoring.\n\n"
368
+
369
+ return methodology
370
+
371
+
372
+ def _generate_detailed_results(trace: WaveformTrace, context: dict[str, Any]) -> str:
373
+ """Generate detailed results section.
374
+
375
+ Args:
376
+ trace: Waveform to analyze.
377
+ context: Analysis context.
378
+
379
+ Returns:
380
+ Detailed results text.
381
+ """
382
+ results = "Detailed measurement results:\n\n"
383
+
384
+ # Basic statistics
385
+ data = trace.data.astype(np.float64)
386
+ results += f"Minimum voltage: {np.min(data):.6f}V\n"
387
+ results += f"Maximum voltage: {np.max(data):.6f}V\n"
388
+ results += f"Mean voltage: {np.mean(data):.6f}V\n"
389
+ results += f"Standard deviation: {np.std(data):.6f}V\n"
390
+ results += f"Peak-to-peak: {np.ptp(data):.6f}V\n\n"
391
+
392
+ # Sample info
393
+ results += f"Sample count: {len(data):,}\n"
394
+ results += f"Sample rate: {trace.metadata.sample_rate / 1e6:.3f} MS/s\n"
395
+ results += f"Duration: {len(data) / trace.metadata.sample_rate * 1000:.3f} ms\n\n"
396
+
397
+ return results
398
+
399
+
400
+ def generate_report(
401
+ trace: WaveformTrace,
402
+ *,
403
+ format: str = "pdf",
404
+ template: str | None = None,
405
+ context: dict[str, Any] | None = None,
406
+ options: dict[str, Any] | None = None,
407
+ ) -> Report:
408
+ """Generate comprehensive executive analysis report.
409
+
410
+ Creates a professional report with executive summary, key findings,
411
+ methodology, and detailed results. Auto-includes relevant plots.
412
+
413
+ Args:
414
+ trace: Waveform to analyze.
415
+ format: Output format ("pdf", "html", "markdown").
416
+ template: Optional template file path.
417
+ context: Pre-computed analysis results (characterization, anomalies, etc.).
418
+ options: Report customization options:
419
+ - select_sections: List of sections to include
420
+ - custom_header: Custom header text
421
+ - custom_footer: Custom footer text
422
+ - page_orientation: "portrait" or "landscape"
423
+ - include_raw_data: Include raw data table
424
+ - plot_dpi: Plot resolution (default 300)
425
+
426
+ Returns:
427
+ Report object with content and save methods.
428
+
429
+ Example:
430
+ >>> report = generate_report(trace)
431
+ >>> report.save_pdf("analysis.pdf")
432
+ >>> print(f"Generated {report.page_count} page report")
433
+
434
+ References:
435
+ DISC-005: Automatic Executive Report
436
+ """
437
+ context = context or {}
438
+ options = options or {}
439
+
440
+ # Determine sections to include
441
+ default_sections = [
442
+ "executive_summary",
443
+ "key_findings",
444
+ "methodology",
445
+ "detailed_results",
446
+ ]
447
+
448
+ sections = options.get("select_sections", default_sections)
449
+
450
+ # Generate content for each section
451
+ content = {}
452
+
453
+ if "executive_summary" in sections or "summary" in sections:
454
+ content["executive_summary"] = _generate_executive_summary(trace, context)
455
+
456
+ if "key_findings" in sections or "findings" in sections:
457
+ content["key_findings"] = _generate_key_findings(trace, context)
458
+
459
+ if "methodology" in sections:
460
+ content["methodology"] = _generate_methodology(trace, context)
461
+
462
+ if "detailed_results" in sections or "results" in sections:
463
+ content["detailed_results"] = _generate_detailed_results(trace, context)
464
+
465
+ if "recommendations" in sections:
466
+ content["recommendations"] = (
467
+ "Recommendations based on analysis:\n\n"
468
+ "1. Signal quality is acceptable for analysis\n"
469
+ "2. Consider additional captures for verification\n"
470
+ "3. Review anomalies if present\n"
471
+ )
472
+
473
+ # Determine plot types to include
474
+ plot_types = options.get("plot_types", [])
475
+ if not plot_types:
476
+ # Auto-select based on signal characteristics
477
+ plot_types = ["time_domain_waveform"]
478
+
479
+ # Add spectral if signal looks periodic
480
+ if len(trace.data) > 100:
481
+ plot_types.append("fft_spectrum")
482
+
483
+ # Estimate page count (rough estimate)
484
+ page_count = 1 # Title page
485
+ page_count += len(sections) # One page per section
486
+ page_count += (len(plot_types) + 1) // 2 # 2 plots per page
487
+
488
+ # Create report object
489
+ report = Report(
490
+ sections=list(sections),
491
+ plots=plot_types,
492
+ page_count=page_count,
493
+ content=content,
494
+ )
495
+
496
+ # Set custom metadata if provided
497
+ if "custom_header" in options:
498
+ report.metadata.title = options["custom_header"]
499
+
500
+ return report
501
+
502
+
503
+ __all__ = [
504
+ "Report",
505
+ "ReportMetadata",
506
+ "generate_report",
507
+ ]