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,456 @@
1
+ """Signal quality warnings for Oscura.
2
+
3
+ This module provides automated detection and warning of signal quality issues
4
+ including clipping, noise, saturation, and undersampling.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.quality.warnings import SignalQualityAnalyzer
9
+ >>> analyzer = SignalQualityAnalyzer()
10
+ >>> warnings = analyzer.analyze(trace)
11
+ >>> for warning in warnings:
12
+ ... print(warning)
13
+
14
+ References:
15
+ - IEEE 1057: Standard for Digitizing Waveform Recorders
16
+ - Nyquist sampling theorem
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from dataclasses import dataclass
22
+ from typing import TYPE_CHECKING, Literal
23
+
24
+ import numpy as np
25
+
26
+ if TYPE_CHECKING:
27
+ from numpy.typing import NDArray
28
+
29
+ from oscura.core.types import WaveformTrace
30
+
31
+
32
+ @dataclass
33
+ class QualityWarning:
34
+ """Signal quality warning.
35
+
36
+ Attributes:
37
+ severity: Warning severity (error, warning, info)
38
+ category: Warning category (clipping, noise, saturation, undersampling)
39
+ message: Human-readable warning message
40
+ value: Numeric value associated with warning
41
+ threshold: Threshold that triggered warning
42
+ suggestion: Suggested action to fix issue
43
+
44
+ Example:
45
+ >>> warning = QualityWarning(
46
+ ... severity="warning",
47
+ ... category="clipping",
48
+ ... message="Signal clipping detected",
49
+ ... value=5.2,
50
+ ... threshold=5.0,
51
+ ... suggestion="Reduce input amplitude or increase ADC range"
52
+ ... )
53
+ >>> print(warning)
54
+
55
+ References:
56
+ EDGE-001: Signal Quality Warnings
57
+ """
58
+
59
+ severity: Literal["error", "warning", "info"]
60
+ category: Literal["clipping", "noise", "saturation", "undersampling", "dc_offset"]
61
+ message: str
62
+ value: float
63
+ threshold: float
64
+ suggestion: str = ""
65
+
66
+ def __str__(self) -> str:
67
+ """Format warning as string.
68
+
69
+ Returns:
70
+ Formatted warning message
71
+ """
72
+ prefix = {"error": "ERROR", "warning": "WARNING", "info": "INFO"}[self.severity]
73
+ msg = f"[{prefix}] {self.message}"
74
+ if self.value is not None:
75
+ msg += f" (value: {self.value:.3f}, threshold: {self.threshold:.3f})"
76
+ if self.suggestion:
77
+ msg += f"\n Suggestion: {self.suggestion}"
78
+ return msg
79
+
80
+
81
+ class SignalQualityAnalyzer:
82
+ """Analyzer for signal quality issues.
83
+
84
+ : Detect clipping, undersampling, noise, and saturation.
85
+ Performs comprehensive signal quality checks and generates warnings.
86
+
87
+ Args:
88
+ clip_threshold: Clipping detection threshold (fraction of range, default: 0.99)
89
+ noise_threshold_db: Noise floor threshold in dB (default: -40)
90
+ saturation_threshold: ADC saturation threshold (default: 0.98)
91
+ nyquist_factor: Factor for Nyquist frequency check (default: 2.0)
92
+
93
+ Example:
94
+ >>> from oscura.quality.warnings import SignalQualityAnalyzer
95
+ >>> analyzer = SignalQualityAnalyzer(clip_threshold=0.95)
96
+ >>> warnings = analyzer.analyze(trace)
97
+ >>> if warnings:
98
+ ... for w in warnings:
99
+ ... print(w)
100
+
101
+ References:
102
+ EDGE-001: Signal Quality Warnings
103
+ """
104
+
105
+ def __init__(
106
+ self,
107
+ *,
108
+ clip_threshold: float = 0.99,
109
+ noise_threshold_db: float = -40.0,
110
+ saturation_threshold: float = 0.98,
111
+ nyquist_factor: float = 2.0,
112
+ ) -> None:
113
+ """Initialize signal quality analyzer.
114
+
115
+ Args:
116
+ clip_threshold: Clipping detection threshold
117
+ noise_threshold_db: Noise floor threshold in dB
118
+ saturation_threshold: ADC saturation threshold
119
+ nyquist_factor: Nyquist frequency factor
120
+ """
121
+ self.clip_threshold = clip_threshold
122
+ self.noise_threshold_db = noise_threshold_db
123
+ self.saturation_threshold = saturation_threshold
124
+ self.nyquist_factor = nyquist_factor
125
+
126
+ def analyze(
127
+ self,
128
+ trace: WaveformTrace | NDArray[np.float64],
129
+ *,
130
+ sample_rate: float | None = None,
131
+ adc_range: tuple[float, float] | None = None,
132
+ ) -> list[QualityWarning]:
133
+ """Analyze signal quality and generate warnings.
134
+
135
+ : Comprehensive signal quality detection.
136
+
137
+ Args:
138
+ trace: Input trace or signal array
139
+ sample_rate: Sample rate in Hz (required for undersampling check)
140
+ adc_range: ADC range as (min, max) tuple
141
+
142
+ Returns:
143
+ List of QualityWarning objects
144
+
145
+ Example:
146
+ >>> warnings = analyzer.analyze(trace, sample_rate=1e9)
147
+ >>> for warning in warnings:
148
+ ... print(warning)
149
+
150
+ References:
151
+ EDGE-001: Signal Quality Warnings
152
+ """
153
+ # Extract data and sample rate
154
+ if hasattr(trace, "data"):
155
+ data = trace.data # type: ignore[ignore-without-code]
156
+ if sample_rate is None and hasattr(trace, "metadata"):
157
+ sample_rate = trace.metadata.sample_rate # type: ignore[ignore-without-code]
158
+ else:
159
+ data = trace # type: ignore[assignment]
160
+
161
+ # Ensure data is NDArray[np.float64]
162
+ data_array: NDArray[np.float64] = np.asarray(data, dtype=np.float64)
163
+
164
+ warnings: list[QualityWarning] = []
165
+
166
+ # Check clipping
167
+ warnings.extend(
168
+ check_clipping(
169
+ data_array,
170
+ threshold=self.clip_threshold,
171
+ adc_range=adc_range,
172
+ )
173
+ )
174
+
175
+ # Check saturation
176
+ warnings.extend(
177
+ check_saturation(
178
+ data_array,
179
+ threshold=self.saturation_threshold,
180
+ adc_range=adc_range,
181
+ )
182
+ )
183
+
184
+ # Check noise
185
+ warnings.extend(
186
+ check_noise(
187
+ data_array,
188
+ threshold_db=self.noise_threshold_db,
189
+ )
190
+ )
191
+
192
+ # Check undersampling (requires sample rate)
193
+ if sample_rate is not None:
194
+ warnings.extend(
195
+ check_undersampling(
196
+ data_array,
197
+ sample_rate=sample_rate,
198
+ nyquist_factor=self.nyquist_factor,
199
+ )
200
+ )
201
+
202
+ return warnings
203
+
204
+
205
+ def check_clipping(
206
+ signal: NDArray[np.float64],
207
+ *,
208
+ threshold: float = 0.99,
209
+ adc_range: tuple[float, float] | None = None,
210
+ ) -> list[QualityWarning]:
211
+ """Detect signal clipping.
212
+
213
+ : Detect clipping (signal hits rail).
214
+
215
+ Args:
216
+ signal: Input signal array
217
+ threshold: Fraction of range for clipping detection (default: 0.99)
218
+ adc_range: ADC range as (min, max) tuple
219
+
220
+ Returns:
221
+ List of clipping warnings
222
+
223
+ Example:
224
+ >>> import numpy as np
225
+ >>> signal = np.clip(np.random.randn(1000), -1, 1)
226
+ >>> warnings = check_clipping(signal)
227
+ >>> if warnings:
228
+ ... print("Clipping detected!")
229
+
230
+ References:
231
+ EDGE-001: Detect clipping
232
+ """
233
+ warnings: list[QualityWarning] = []
234
+
235
+ # Determine signal range
236
+ if adc_range is not None:
237
+ min_val, max_val = adc_range
238
+ else:
239
+ min_val = float(np.min(signal))
240
+ max_val = float(np.max(signal))
241
+
242
+ signal_range = max_val - min_val
243
+ if signal_range == 0:
244
+ return warnings
245
+
246
+ # Count samples near limits
247
+ upper_limit = min_val + signal_range * threshold
248
+ lower_limit = min_val + signal_range * (1 - threshold)
249
+
250
+ n_upper: int = int(np.sum(signal >= upper_limit))
251
+ n_lower: int = int(np.sum(signal <= lower_limit))
252
+ n_clipped = n_upper + n_lower
253
+ clip_percent = float(100.0 * n_clipped / len(signal))
254
+
255
+ if clip_percent > 1.0: # More than 1% clipped
256
+ severity: Literal["error", "warning"] = "error" if clip_percent > 5.0 else "warning"
257
+ warnings.append(
258
+ QualityWarning(
259
+ severity=severity,
260
+ category="clipping",
261
+ message=f"Signal clipping detected at {clip_percent:.1f}% of samples",
262
+ value=clip_percent,
263
+ threshold=1.0,
264
+ suggestion="Reduce input amplitude or increase ADC range",
265
+ )
266
+ )
267
+
268
+ return warnings
269
+
270
+
271
+ def check_saturation(
272
+ signal: NDArray[np.float64],
273
+ *,
274
+ threshold: float = 0.98,
275
+ adc_range: tuple[float, float] | None = None,
276
+ ) -> list[QualityWarning]:
277
+ """Detect ADC saturation.
278
+
279
+ : Detect saturation (ADC range utilization).
280
+
281
+ Args:
282
+ signal: Input signal array
283
+ threshold: Saturation threshold as fraction of range (default: 0.98)
284
+ adc_range: ADC range as (min, max) tuple
285
+
286
+ Returns:
287
+ List of saturation warnings
288
+
289
+ Example:
290
+ >>> warnings = check_saturation(signal, threshold=0.95)
291
+
292
+ References:
293
+ EDGE-001: Detect saturation
294
+ """
295
+ warnings: list[QualityWarning] = []
296
+
297
+ # Determine signal range
298
+ if adc_range is not None:
299
+ adc_min, adc_max = adc_range
300
+ adc_span = adc_max - adc_min
301
+ else:
302
+ # Assume signal uses full observed range as ADC range
303
+ adc_min = float(np.min(signal))
304
+ adc_max = float(np.max(signal))
305
+ adc_span = adc_max - adc_min
306
+
307
+ if adc_span == 0:
308
+ return warnings
309
+
310
+ # Calculate range utilization
311
+ signal_min = float(np.min(signal))
312
+ signal_max = float(np.max(signal))
313
+ signal_span = signal_max - signal_min
314
+ utilization = signal_span / adc_span
315
+
316
+ if utilization > threshold:
317
+ warnings.append(
318
+ QualityWarning(
319
+ severity="warning",
320
+ category="saturation",
321
+ message=f"High ADC range utilization: {utilization * 100:.1f}%",
322
+ value=utilization * 100,
323
+ threshold=threshold * 100,
324
+ suggestion="Consider increasing ADC range or reducing signal amplitude",
325
+ )
326
+ )
327
+
328
+ return warnings
329
+
330
+
331
+ def check_noise(
332
+ signal: NDArray[np.float64],
333
+ *,
334
+ threshold_db: float = -40.0,
335
+ ) -> list[QualityWarning]:
336
+ """Detect excessive noise.
337
+
338
+ : Detect noise (SNR below threshold warning).
339
+
340
+ Args:
341
+ signal: Input signal array
342
+ threshold_db: Noise threshold in dB (default: -40)
343
+
344
+ Returns:
345
+ List of noise warnings
346
+
347
+ Example:
348
+ >>> warnings = check_noise(signal, threshold_db=-50)
349
+
350
+ References:
351
+ EDGE-001: Detect noise
352
+ """
353
+ warnings: list[QualityWarning] = []
354
+
355
+ # Estimate SNR
356
+ signal_power = float(np.mean(signal**2))
357
+ if signal_power == 0:
358
+ return warnings
359
+
360
+ # Estimate noise from high-frequency components
361
+ # Simple approach: use standard deviation as noise estimate
362
+ noise_power = float(np.var(signal))
363
+ if noise_power == 0:
364
+ return warnings
365
+
366
+ snr_linear = signal_power / noise_power
367
+ snr_db = 10 * np.log10(snr_linear) if snr_linear > 0 else -np.inf
368
+
369
+ if snr_db < threshold_db:
370
+ warnings.append(
371
+ QualityWarning(
372
+ severity="warning",
373
+ category="noise",
374
+ message=f"High noise level detected: SNR = {snr_db:.1f} dB",
375
+ value=snr_db,
376
+ threshold=threshold_db,
377
+ suggestion="Check signal source, grounding, and shielding",
378
+ )
379
+ )
380
+
381
+ return warnings
382
+
383
+
384
+ def check_undersampling(
385
+ signal: NDArray[np.float64],
386
+ *,
387
+ sample_rate: float,
388
+ nyquist_factor: float = 2.0,
389
+ ) -> list[QualityWarning]:
390
+ """Detect undersampling (Nyquist violation).
391
+
392
+ : Detect undersampling (Nyquist violation warning).
393
+
394
+ Args:
395
+ signal: Input signal array
396
+ sample_rate: Sample rate in Hz
397
+ nyquist_factor: Required factor above Nyquist (default: 2.0)
398
+
399
+ Returns:
400
+ List of undersampling warnings
401
+
402
+ Example:
403
+ >>> warnings = check_undersampling(signal, sample_rate=1e9)
404
+
405
+ References:
406
+ EDGE-001: Detect undersampling
407
+ Nyquist-Shannon sampling theorem
408
+ """
409
+ warnings: list[QualityWarning] = []
410
+
411
+ # Estimate highest frequency component using FFT
412
+ fft = np.fft.rfft(signal)
413
+ freqs = np.fft.rfftfreq(len(signal), d=1 / sample_rate)
414
+ power = np.abs(fft) ** 2
415
+
416
+ # Find frequency where power drops to 1% of peak
417
+ peak_power: float = float(np.max(power))
418
+ threshold_power = peak_power * 0.01
419
+
420
+ # Find highest significant frequency
421
+ significant_freqs = freqs[power > threshold_power]
422
+ if len(significant_freqs) > 0:
423
+ max_freq = float(np.max(significant_freqs))
424
+ nyquist_freq = sample_rate / 2.0
425
+ required_nyquist = max_freq * nyquist_factor
426
+
427
+ if required_nyquist > nyquist_freq:
428
+ warnings.append(
429
+ QualityWarning(
430
+ severity="error",
431
+ category="undersampling",
432
+ message=(
433
+ f"Undersampling detected: signal contains "
434
+ f"{max_freq / 1e6:.1f} MHz, but Nyquist frequency is "
435
+ f"{nyquist_freq / 1e6:.1f} MHz"
436
+ ),
437
+ value=max_freq,
438
+ threshold=nyquist_freq / nyquist_factor,
439
+ suggestion=(
440
+ f"Increase sample rate to at least "
441
+ f"{required_nyquist * 2 / 1e6:.1f} MS/s or apply anti-aliasing filter"
442
+ ),
443
+ )
444
+ )
445
+
446
+ return warnings
447
+
448
+
449
+ __all__ = [
450
+ "QualityWarning",
451
+ "SignalQualityAnalyzer",
452
+ "check_clipping",
453
+ "check_noise",
454
+ "check_saturation",
455
+ "check_undersampling",
456
+ ]
@@ -0,0 +1,248 @@
1
+ """Report generation module for Oscura.
2
+
3
+ This module provides professional report generation including PDF/HTML
4
+ output, templates, formatting, and multi-format export.
5
+ """
6
+
7
+ # Comprehensive Analysis Report API (CAR-001 through CAR-007)
8
+ from oscura.reporting.analyze import (
9
+ UnsupportedFormatError,
10
+ analyze,
11
+ )
12
+ from oscura.reporting.auto_report import (
13
+ Report as AutoReport,
14
+ )
15
+ from oscura.reporting.auto_report import (
16
+ ReportMetadata,
17
+ )
18
+ from oscura.reporting.auto_report import (
19
+ generate_report as generate_auto_report,
20
+ )
21
+ from oscura.reporting.batch import (
22
+ BatchReportResult,
23
+ aggregate_batch_measurements,
24
+ batch_report,
25
+ generate_batch_report,
26
+ )
27
+ from oscura.reporting.chart_selection import (
28
+ ChartType,
29
+ auto_select_chart,
30
+ get_axis_scaling,
31
+ recommend_chart_with_reasoning,
32
+ )
33
+ from oscura.reporting.comparison import (
34
+ compare_waveforms,
35
+ generate_comparison_report,
36
+ )
37
+ from oscura.reporting.config import (
38
+ ANALYSIS_CAPABILITIES,
39
+ AnalysisConfig,
40
+ AnalysisDomain,
41
+ AnalysisError,
42
+ AnalysisResult,
43
+ DataOutputConfig,
44
+ DomainConfig,
45
+ InputType,
46
+ ProgressCallback,
47
+ ProgressInfo,
48
+ get_available_analyses,
49
+ )
50
+ from oscura.reporting.core import ( # core.py module
51
+ Report,
52
+ ReportConfig,
53
+ Section,
54
+ generate_report,
55
+ )
56
+ from oscura.reporting.core_formats import ( # core_formats/ directory
57
+ MultiFormatRenderer,
58
+ detect_format_from_extension,
59
+ render_all_formats,
60
+ )
61
+ from oscura.reporting.engine import (
62
+ AnalysisEngine,
63
+ )
64
+ from oscura.reporting.export import (
65
+ batch_export_formats,
66
+ export_multiple_reports,
67
+ export_report,
68
+ )
69
+ from oscura.reporting.formatting import (
70
+ NumberFormatter,
71
+ format_margin,
72
+ format_pass_fail,
73
+ format_value,
74
+ format_with_context,
75
+ format_with_locale,
76
+ format_with_units,
77
+ )
78
+ from oscura.reporting.html import (
79
+ generate_html_report,
80
+ save_html_report,
81
+ )
82
+ from oscura.reporting.index import (
83
+ IndexGenerator,
84
+ TemplateEngine,
85
+ )
86
+ from oscura.reporting.multichannel import (
87
+ generate_multichannel_report,
88
+ )
89
+ from oscura.reporting.output import OutputManager
90
+ from oscura.reporting.pdf import (
91
+ generate_pdf_report,
92
+ save_pdf_report,
93
+ )
94
+ from oscura.reporting.plots import (
95
+ PLOT_REGISTRY,
96
+ PlotGenerator,
97
+ register_plot,
98
+ )
99
+ from oscura.reporting.pptx_export import (
100
+ PPTXPresentation,
101
+ PPTXSlide,
102
+ export_pptx,
103
+ generate_presentation_from_report,
104
+ )
105
+ from oscura.reporting.sections import (
106
+ create_conclusions_section,
107
+ create_executive_summary_section,
108
+ create_measurement_results_section,
109
+ create_methodology_section,
110
+ create_plots_section,
111
+ create_standard_report_sections,
112
+ create_title_section,
113
+ create_violations_section,
114
+ )
115
+ from oscura.reporting.standards import (
116
+ ColorScheme,
117
+ ExecutiveSummary,
118
+ FormatStandards,
119
+ Severity,
120
+ VisualEmphasis,
121
+ format_executive_summary_html,
122
+ generate_executive_summary,
123
+ )
124
+ from oscura.reporting.summary_generator import (
125
+ Finding,
126
+ Summary,
127
+ generate_summary,
128
+ )
129
+ from oscura.reporting.tables import (
130
+ create_comparison_table,
131
+ create_measurement_table,
132
+ create_statistics_table,
133
+ format_batch_summary_table,
134
+ )
135
+ from oscura.reporting.template_system import (
136
+ ReportTemplate,
137
+ TemplateSection,
138
+ list_templates,
139
+ load_template,
140
+ )
141
+
142
+ __all__ = [
143
+ # Comprehensive Analysis Report API (CAR-001 through CAR-007)
144
+ "ANALYSIS_CAPABILITIES",
145
+ "PLOT_REGISTRY",
146
+ "AnalysisConfig",
147
+ "AnalysisDomain",
148
+ "AnalysisEngine",
149
+ "AnalysisError",
150
+ "AnalysisResult",
151
+ # Auto Report
152
+ "AutoReport",
153
+ # Batch (REPORT-009, RPT-003)
154
+ "BatchReportResult",
155
+ # Chart Selection (REPORT-028)
156
+ "ChartType",
157
+ # Standards (REPORT-001, REPORT-002, REPORT-004)
158
+ "ColorScheme",
159
+ "DataOutputConfig",
160
+ "DomainConfig",
161
+ "ExecutiveSummary",
162
+ # Summary Generation
163
+ "Finding",
164
+ "FormatStandards",
165
+ "IndexGenerator",
166
+ "InputType",
167
+ # Multi-format (REPORT-010)
168
+ "MultiFormatRenderer",
169
+ # Formatting (REPORT-026)
170
+ "NumberFormatter",
171
+ "OutputManager",
172
+ # PPTX Export (REPORT-023)
173
+ "PPTXPresentation",
174
+ "PPTXSlide",
175
+ "PlotGenerator",
176
+ "ProgressCallback",
177
+ "ProgressInfo",
178
+ # Core
179
+ "Report",
180
+ "ReportConfig",
181
+ "ReportMetadata",
182
+ # Templates (RPT-002)
183
+ "ReportTemplate",
184
+ "Section",
185
+ "Severity",
186
+ "Summary",
187
+ "TemplateEngine",
188
+ "TemplateSection",
189
+ "UnsupportedFormatError",
190
+ "VisualEmphasis",
191
+ "aggregate_batch_measurements",
192
+ "analyze",
193
+ "auto_select_chart",
194
+ # Export
195
+ "batch_export_formats",
196
+ "batch_report",
197
+ # Comparison
198
+ "compare_waveforms",
199
+ # Tables
200
+ "create_comparison_table",
201
+ # Sections
202
+ "create_conclusions_section",
203
+ "create_executive_summary_section",
204
+ "create_measurement_results_section",
205
+ "create_measurement_table",
206
+ "create_methodology_section",
207
+ "create_plots_section",
208
+ "create_standard_report_sections",
209
+ "create_statistics_table",
210
+ "create_title_section",
211
+ "create_violations_section",
212
+ # Multi-format (REPORT-010)
213
+ "detect_format_from_extension",
214
+ "export_multiple_reports",
215
+ "export_pptx",
216
+ "export_report",
217
+ "format_batch_summary_table",
218
+ "format_executive_summary_html",
219
+ "format_margin",
220
+ "format_pass_fail",
221
+ "format_value",
222
+ "format_with_context",
223
+ "format_with_locale",
224
+ "format_with_units",
225
+ "generate_auto_report",
226
+ "generate_batch_report",
227
+ "generate_comparison_report",
228
+ "generate_executive_summary",
229
+ # HTML Generation
230
+ "generate_html_report",
231
+ # Multi-Channel
232
+ "generate_multichannel_report",
233
+ # PDF Generation
234
+ "generate_pdf_report",
235
+ "generate_presentation_from_report",
236
+ "generate_report",
237
+ "generate_summary",
238
+ "get_available_analyses",
239
+ "get_axis_scaling",
240
+ "list_templates",
241
+ "load_template",
242
+ "recommend_chart_with_reasoning",
243
+ "register_plot",
244
+ # Multi-format (REPORT-010)
245
+ "render_all_formats",
246
+ "save_html_report",
247
+ "save_pdf_report",
248
+ ]