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,127 @@
1
+ """Executive summary auto-generation.
2
+
3
+ Automatically generates concise executive summaries with key findings,
4
+ pass/fail status, and critical violations highlighted.
5
+
6
+
7
+ References:
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from dataclasses import dataclass, field
13
+ from typing import Any, Literal
14
+
15
+
16
+ @dataclass
17
+ class ExecutiveSummary:
18
+ """Executive summary of analysis results.
19
+
20
+ Attributes:
21
+ overall_status: Overall pass/fail status.
22
+ pass_count: Number of passing tests.
23
+ total_count: Total number of tests.
24
+ key_findings: List of 3-5 key findings.
25
+ critical_violations: List of critical violations.
26
+ min_margin_pct: Minimum margin percentage.
27
+ summary_text: Natural language summary.
28
+
29
+ References:
30
+ REPORT-004: Executive Summary Auto-Generation
31
+ """
32
+
33
+ overall_status: bool
34
+ pass_count: int
35
+ total_count: int
36
+ key_findings: list[str] = field(default_factory=list)
37
+ critical_violations: list[str] = field(default_factory=list)
38
+ min_margin_pct: float | None = None
39
+ summary_text: str = ""
40
+
41
+
42
+ def generate_executive_summary(
43
+ results: dict[str, Any],
44
+ *,
45
+ max_findings: int = 5,
46
+ length: Literal["short", "detailed"] = "short",
47
+ ) -> ExecutiveSummary:
48
+ """Generate executive summary from analysis results.
49
+
50
+ Automatically extracts top 3-5 key findings, pass/fail status in first
51
+ sentence, and critical violations in bullet list.
52
+
53
+ Args:
54
+ results: Analysis results dictionary.
55
+ max_findings: Maximum number of key findings (default 5).
56
+ length: Summary length (short=1 paragraph, detailed=1 page).
57
+
58
+ Returns:
59
+ ExecutiveSummary with generated content.
60
+
61
+ Example:
62
+ >>> results = {"pass_count": 10, "total_count": 12}
63
+ >>> summary = generate_executive_summary(results)
64
+ >>> print(summary.summary_text)
65
+ 'All 10 tests passed with >25% margin. No violations.'
66
+
67
+ References:
68
+ REPORT-004: Executive Summary Auto-Generation
69
+ """
70
+ # Extract basic counts
71
+ pass_count = results.get("pass_count", 0)
72
+ total_count = results.get("total_count", 0)
73
+ fail_count = total_count - pass_count if total_count else 0
74
+ overall_status = fail_count == 0
75
+
76
+ # Extract violations
77
+ violations = results.get("violations", [])
78
+ critical_violations = [v for v in violations if v.get("severity", "").lower() == "critical"]
79
+
80
+ # Extract key findings
81
+ key_findings: list[str] = []
82
+ if critical_violations:
83
+ key_findings.append(
84
+ f"{len(critical_violations)} critical violation(s) require immediate attention"
85
+ )
86
+ elif violations:
87
+ key_findings.append(f"{len(violations)} violation(s) detected")
88
+
89
+ # Add margin information
90
+ min_margin = results.get("min_margin")
91
+ if min_margin is not None and min_margin < 20:
92
+ status = "critical" if min_margin < 10 else "marginal"
93
+ key_findings.append(f"Minimum margin is {min_margin:.1f}% ({status})")
94
+
95
+ # Build summary text in natural language
96
+ if overall_status and total_count > 0:
97
+ summary_text = f"All {pass_count} tests passed."
98
+ if min_margin is not None and min_margin > 20:
99
+ summary_text += f" Minimum margin: {min_margin:.1f}%."
100
+ elif total_count > 0:
101
+ pct = fail_count / total_count * 100
102
+ summary_text = f"{fail_count} of {total_count} tests failed ({pct:.0f}% failure rate)."
103
+ else:
104
+ summary_text = "Analysis completed successfully."
105
+
106
+ if critical_violations:
107
+ summary_text += (
108
+ f" Critical: {len(critical_violations)} violation(s) require immediate action."
109
+ )
110
+
111
+ # Add detailed findings for detailed mode
112
+ if length == "detailed" and key_findings:
113
+ summary_text += "\n\nKey Findings:\n"
114
+ summary_text += "\n".join(f" - {finding}" for finding in key_findings[:max_findings])
115
+
116
+ return ExecutiveSummary(
117
+ overall_status=overall_status,
118
+ pass_count=pass_count,
119
+ total_count=total_count,
120
+ key_findings=key_findings[:max_findings],
121
+ critical_violations=[str(v) for v in critical_violations],
122
+ min_margin_pct=min_margin,
123
+ summary_text=summary_text,
124
+ )
125
+
126
+
127
+ __all__ = ["ExecutiveSummary", "generate_executive_summary"]
@@ -0,0 +1,191 @@
1
+ """Smart content filtering for reports.
2
+
3
+ Shows only relevant information based on context, severity, and audience
4
+ with conditional sections and violation-only modes.
5
+
6
+
7
+ References:
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from dataclasses import dataclass
13
+ from enum import Enum
14
+ from typing import Any, Literal
15
+
16
+ from oscura.reporting.formatting.standards import Severity
17
+
18
+
19
+ class AudienceType(Enum):
20
+ """Audience types for content filtering."""
21
+
22
+ EXECUTIVE = "executive"
23
+ ENGINEERING = "engineering"
24
+ DEBUG = "debug"
25
+ REGULATORY = "regulatory"
26
+ PRODUCTION = "production"
27
+
28
+
29
+ @dataclass
30
+ class ContentFilter:
31
+ """Smart content filtering configuration.
32
+
33
+ Attributes:
34
+ severity_threshold: Minimum severity to show (critical/warning/info).
35
+ audience: Target audience type.
36
+ show_only: Show only specific content (violations, changes, all).
37
+ hide_empty_sections: Hide sections with no data.
38
+ relevance_threshold: Minimum relevance score (0.0-1.0).
39
+
40
+ References:
41
+ REPORT-005: Smart Content Filtering
42
+ """
43
+
44
+ severity_threshold: Severity = Severity.INFO
45
+ audience: AudienceType = AudienceType.ENGINEERING
46
+ show_only: Literal["all", "violations", "changes"] = "all"
47
+ hide_empty_sections: bool = True
48
+ relevance_threshold: float = 0.5
49
+
50
+
51
+ def filter_by_severity(
52
+ items: list[dict[str, Any]],
53
+ min_severity: Severity | str,
54
+ ) -> list[dict[str, Any]]:
55
+ """Filter items by severity level.
56
+
57
+ Args:
58
+ items: List of items with 'severity' field.
59
+ min_severity: Minimum severity to include.
60
+
61
+ Returns:
62
+ Filtered list of items.
63
+
64
+ Example:
65
+ >>> items = [{"name": "test1", "severity": "critical"},
66
+ ... {"name": "test2", "severity": "info"}]
67
+ >>> filtered = filter_by_severity(items, "warning")
68
+ >>> len(filtered) # Only critical items
69
+ 1
70
+
71
+ References:
72
+ REPORT-005: Smart Content Filtering
73
+ """
74
+ if isinstance(min_severity, str):
75
+ min_severity = Severity(min_severity.lower())
76
+
77
+ severity_order = {
78
+ Severity.INFO: 0,
79
+ Severity.WARNING: 1,
80
+ Severity.ERROR: 2,
81
+ Severity.CRITICAL: 3,
82
+ }
83
+
84
+ min_level = severity_order.get(min_severity, 0)
85
+
86
+ filtered = []
87
+ for item in items:
88
+ item_severity_str = item.get("severity", "info").lower()
89
+ try:
90
+ item_severity = Severity(item_severity_str)
91
+ item_level = severity_order.get(item_severity, 0)
92
+ if item_level >= min_level:
93
+ filtered.append(item)
94
+ except (ValueError, KeyError):
95
+ continue
96
+
97
+ return filtered
98
+
99
+
100
+ def filter_by_audience(
101
+ content: dict[str, Any],
102
+ audience: AudienceType | str,
103
+ ) -> dict[str, Any]:
104
+ """Filter content for specific audience.
105
+
106
+ Args:
107
+ content: Content dictionary with various sections.
108
+ audience: Target audience type.
109
+
110
+ Returns:
111
+ Filtered content dictionary.
112
+
113
+ Example:
114
+ >>> content = {"methodology": "...", "results": "...", "raw_data": "..."}
115
+ >>> filtered = filter_by_audience(content, "executive")
116
+ >>> "raw_data" in filtered # False - executives don't need raw data
117
+ False
118
+
119
+ References:
120
+ REPORT-005: Smart Content Filtering
121
+ """
122
+ if isinstance(audience, str):
123
+ audience = AudienceType(audience.lower())
124
+
125
+ # Define what each audience sees
126
+ audience_sections = {
127
+ AudienceType.EXECUTIVE: ["executive_summary", "key_findings", "recommendations"],
128
+ AudienceType.ENGINEERING: ["summary", "results", "methodology", "plots"],
129
+ AudienceType.DEBUG: ["summary", "results", "methodology", "plots", "raw_data", "logs"],
130
+ AudienceType.REGULATORY: ["summary", "compliance", "test_procedures", "standards"],
131
+ AudienceType.PRODUCTION: ["summary", "pass_fail", "margin", "yield"],
132
+ }
133
+
134
+ allowed_sections = audience_sections.get(audience, list(content.keys()))
135
+
136
+ filtered = {}
137
+ for key, value in content.items():
138
+ if key in allowed_sections:
139
+ filtered[key] = value
140
+
141
+ return filtered
142
+
143
+
144
+ def calculate_relevance_score(
145
+ item: dict[str, Any],
146
+ context: dict[str, Any] | None = None,
147
+ ) -> float:
148
+ """Calculate relevance score for content item.
149
+
150
+ Args:
151
+ item: Content item.
152
+ context: Optional context for relevance scoring.
153
+
154
+ Returns:
155
+ Relevance score 0.0-1.0.
156
+
157
+ References:
158
+ REPORT-005: Smart Content Filtering
159
+ """
160
+ score = 0.5 # Base score
161
+
162
+ # Increase score for violations
163
+ if item.get("status") == "fail":
164
+ score += 0.3
165
+
166
+ # Increase score for critical severity
167
+ severity = item.get("severity", "").lower()
168
+ if severity == "critical":
169
+ score += 0.3
170
+ elif severity == "warning":
171
+ score += 0.1
172
+
173
+ # Increase score for outliers
174
+ if item.get("is_outlier"):
175
+ score += 0.2
176
+
177
+ # Increase score for low margins
178
+ margin = item.get("margin_pct")
179
+ if margin is not None and margin < 20:
180
+ score += 0.2
181
+
182
+ return min(1.0, score)
183
+
184
+
185
+ __all__ = [
186
+ "AudienceType",
187
+ "ContentFilter",
188
+ "calculate_relevance_score",
189
+ "filter_by_audience",
190
+ "filter_by_severity",
191
+ ]
@@ -0,0 +1,257 @@
1
+ """Minimal boilerplate content generation.
2
+
3
+ This module eliminates unnecessary static text and focuses on data-driven
4
+ narrative with compact formatting and automated captions.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.reporting.content import generate_compact_text
9
+ >>> compact = generate_compact_text(value=2.3e-9, spec=5e-9, unit="s")
10
+ >>> print(compact) # "Rise time: 2.3ns (spec <5ns, ✓ 54% margin)"
11
+
12
+ References:
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from dataclasses import dataclass
18
+ from typing import Any, Literal
19
+
20
+
21
+ @dataclass
22
+ class MinimalContent:
23
+ """Minimal boilerplate content generator.
24
+
25
+ Focuses on data-driven content with minimal filler text.
26
+
27
+ Attributes:
28
+ auto_units: Auto-scale units (2300ns → 2.3μs).
29
+ data_first: Show results before methodology.
30
+ show_passing: Include passing tests or violations only.
31
+ auto_captions: Generate captions from data, not static templates.
32
+
33
+ References:
34
+ REPORT-003: Minimal Boilerplate Content
35
+ """
36
+
37
+ auto_units: bool = True
38
+ data_first: bool = True
39
+ show_passing: bool = True
40
+ auto_captions: bool = True
41
+
42
+
43
+ def generate_compact_text(
44
+ value: float,
45
+ spec: float | None = None,
46
+ unit: str = "",
47
+ *,
48
+ spec_type: Literal["max", "min"] = "max",
49
+ name: str = "",
50
+ ) -> str:
51
+ """Generate compact, data-driven text.
52
+
53
+ Avoids filler text like "The measurement was performed and the result was...".
54
+ Instead produces compact format: "Rise time: 2.3ns (spec <5ns, ✓ 54% margin)".
55
+
56
+ Args:
57
+ value: Measured value.
58
+ spec: Specification limit (optional).
59
+ unit: Unit string.
60
+ spec_type: Type of specification (max or min).
61
+ name: Measurement name (optional).
62
+
63
+ Returns:
64
+ Compact formatted string.
65
+
66
+ Example:
67
+ >>> generate_compact_text(2.3e-9, 5e-9, "s", name="Rise time")
68
+ 'Rise time: 2.3ns (spec <5ns, ✓ 54% margin)'
69
+
70
+ References:
71
+ REPORT-003: Minimal Boilerplate Content
72
+ """
73
+ from oscura.reporting.formatting.numbers import format_with_units
74
+
75
+ # Format value with auto-scaled units
76
+ value_str = format_with_units(value, unit)
77
+
78
+ # Build compact text
79
+ parts = []
80
+ if name:
81
+ parts.append(f"{name}:")
82
+
83
+ parts.append(value_str)
84
+
85
+ # Add spec context if provided
86
+ if spec is not None:
87
+ spec_str = format_with_units(spec, unit)
88
+ spec_symbol = "<" if spec_type == "max" else ">"
89
+
90
+ # Calculate pass/fail and margin
91
+ if spec_type == "max":
92
+ passed = value <= spec
93
+ margin = (spec - value) / spec * 100 if spec != 0 else 0
94
+ else:
95
+ passed = value >= spec
96
+ margin = (value - spec) / spec * 100 if spec != 0 else 0
97
+
98
+ status_symbol = "\u2713" if passed else "\u2717" # ✓ or ✗
99
+ spec_part = f"(spec {spec_symbol}{spec_str}, {status_symbol} {margin:.0f}% margin)"
100
+ parts.append(spec_part)
101
+
102
+ return " ".join(parts)
103
+
104
+
105
+ def auto_caption(
106
+ data_type: str,
107
+ data: dict[str, Any],
108
+ *,
109
+ include_stats: bool = True,
110
+ ) -> str:
111
+ """Generate automated captions from data.
112
+
113
+ Instead of static templates, generates captions based on actual data content.
114
+
115
+ Args:
116
+ data_type: Type of data (measurement, plot, table).
117
+ data: Data dictionary.
118
+ include_stats: Include statistics in caption.
119
+
120
+ Returns:
121
+ Generated caption string.
122
+
123
+ Example:
124
+ >>> data = {"name": "Rise time", "count": 100, "mean": 2.3e-9}
125
+ >>> auto_caption("measurement", data)
126
+ 'Rise time measurement (n=100, mean=2.3ns)'
127
+
128
+ References:
129
+ REPORT-003: Minimal Boilerplate Content
130
+ """
131
+ parts = []
132
+
133
+ # Extract key information
134
+ name = data.get("name", data_type.title())
135
+ parts.append(name)
136
+
137
+ # Add data-specific information
138
+ if data_type == "measurement" and include_stats:
139
+ count = data.get("count")
140
+ if count:
141
+ parts.append(f"(n={count}")
142
+
143
+ mean = data.get("mean")
144
+ if mean is not None:
145
+ from oscura.reporting.formatting.numbers import format_with_units
146
+
147
+ unit = data.get("unit", "")
148
+ mean_str = format_with_units(mean, unit)
149
+ parts[-1] += f", mean={mean_str}"
150
+
151
+ parts[-1] += ")"
152
+
153
+ elif data_type == "plot":
154
+ plot_type = data.get("type", "plot")
155
+ if plot_type != "plot":
156
+ parts.append(f"- {plot_type}")
157
+
158
+ elif data_type == "table":
159
+ rows = data.get("rows")
160
+ cols = data.get("cols")
161
+ if rows and cols:
162
+ parts.append(f"({rows}x{cols})")
163
+
164
+ return " ".join(parts)
165
+
166
+
167
+ def remove_filler_text(text: str) -> str:
168
+ """Remove common filler phrases from text.
169
+
170
+ Args:
171
+ text: Input text.
172
+
173
+ Returns:
174
+ Text with filler removed.
175
+
176
+ Example:
177
+ >>> text = "The measurement was performed and the result was 2.3ns."
178
+ >>> remove_filler_text(text)
179
+ 'Result: 2.3ns.'
180
+
181
+ References:
182
+ REPORT-003: Minimal Boilerplate Content
183
+ """
184
+ # Common filler phrases to remove
185
+ filler_phrases = [
186
+ "The measurement was performed and",
187
+ "The result was",
188
+ "It was found that",
189
+ "The analysis shows that",
190
+ "It can be seen that",
191
+ "As can be observed",
192
+ "The data indicates",
193
+ "It should be noted that",
194
+ ]
195
+
196
+ result = text
197
+ for phrase in filler_phrases:
198
+ result = result.replace(phrase, "").strip()
199
+
200
+ # Clean up extra spaces
201
+ while " " in result:
202
+ result = result.replace(" ", " ")
203
+
204
+ # Capitalize first letter after removal
205
+ if result and not result[0].isupper():
206
+ result = result[0].upper() + result[1:]
207
+
208
+ return result
209
+
210
+
211
+ def conditional_section(
212
+ data: list[Any] | dict[str, Any],
213
+ section_title: str,
214
+ ) -> tuple[bool, str]:
215
+ """Determine if section should be shown.
216
+
217
+ Only show sections if data exists (no empty sections).
218
+
219
+ Args:
220
+ data: Section data.
221
+ section_title: Section title.
222
+
223
+ Returns:
224
+ Tuple of (should_show, reason).
225
+
226
+ Example:
227
+ >>> should_show, reason = conditional_section([], "Violations")
228
+ >>> print(should_show) # False
229
+ >>> print(reason) # "No violations found"
230
+
231
+ References:
232
+ REPORT-003: Minimal Boilerplate Content
233
+ """
234
+ if isinstance(data, list):
235
+ if not data:
236
+ return False, f"No {section_title.lower()} found"
237
+ return True, f"{len(data)} {section_title.lower()}"
238
+
239
+ elif isinstance(data, dict):
240
+ if not data or all(not v for v in data.values()):
241
+ return False, f"No {section_title.lower()} found"
242
+ return True, ""
243
+
244
+ else:
245
+ # For other types, check if truthy
246
+ if not data: # type: ignore[unreachable]
247
+ return False, f"No {section_title.lower()} found"
248
+ return True, ""
249
+
250
+
251
+ __all__ = [
252
+ "MinimalContent",
253
+ "auto_caption",
254
+ "conditional_section",
255
+ "generate_compact_text",
256
+ "remove_filler_text",
257
+ ]