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,392 @@
1
+ """Parameter optimization for signal analysis.
2
+
3
+ This module provides parameter optimization utilities including
4
+ grid search, parameter space definition, and optimization result tracking.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import itertools
10
+ import logging
11
+ import time
12
+ from dataclasses import dataclass, field
13
+ from typing import TYPE_CHECKING, Any
14
+
15
+ import numpy as np
16
+
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Callable, Iterator
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+ __all__ = [
23
+ "GridSearch",
24
+ "OptimizationResult",
25
+ "ParameterSpace",
26
+ "optimize_parameters",
27
+ ]
28
+
29
+
30
+ @dataclass
31
+ class ParameterSpace:
32
+ """Definition of parameter search space.
33
+
34
+ Attributes:
35
+ name: Parameter name
36
+ values: List of values to try
37
+ low: Low bound (for continuous params)
38
+ high: High bound (for continuous params)
39
+ log_scale: Use logarithmic scale
40
+ num_samples: Number of samples for continuous
41
+
42
+ Example:
43
+ >>> # Discrete parameter
44
+ >>> window = ParameterSpace("window", values=["hann", "hamming", "blackman"])
45
+ >>> # Continuous parameter
46
+ >>> cutoff = ParameterSpace("cutoff", low=1e3, high=1e6, num_samples=10)
47
+
48
+ References:
49
+ API-014: Parameter Optimization
50
+ """
51
+
52
+ name: str
53
+ values: list[Any] | None = None
54
+ low: float | None = None
55
+ high: float | None = None
56
+ log_scale: bool = False
57
+ num_samples: int = 10
58
+
59
+ def __post_init__(self) -> None:
60
+ """Generate values if continuous parameter."""
61
+ if self.values is None:
62
+ if self.low is not None and self.high is not None:
63
+ if self.log_scale:
64
+ self.values = list(
65
+ np.logspace(np.log10(self.low), np.log10(self.high), self.num_samples)
66
+ )
67
+ else:
68
+ self.values = list(np.linspace(self.low, self.high, self.num_samples))
69
+ else:
70
+ raise ValueError(
71
+ f"Parameter {self.name}: must specify either values or (low, high) bounds"
72
+ )
73
+
74
+ def __iter__(self) -> Iterator[Any]:
75
+ """Iterate over parameter values."""
76
+ return iter(self.values or [])
77
+
78
+ def __len__(self) -> int:
79
+ """Number of parameter values."""
80
+ return len(self.values or [])
81
+
82
+
83
+ @dataclass
84
+ class OptimizationResult:
85
+ """Result of parameter optimization.
86
+
87
+ Attributes:
88
+ best_params: Best parameter combination
89
+ best_score: Best objective score
90
+ all_results: All evaluated combinations
91
+ elapsed_time: Total optimization time
92
+ num_evaluations: Number of combinations evaluated
93
+
94
+ References:
95
+ API-014: Parameter Optimization
96
+ """
97
+
98
+ best_params: dict[str, Any]
99
+ best_score: float
100
+ all_results: list[tuple[dict[str, Any], float]] = field(default_factory=list)
101
+ elapsed_time: float = 0.0
102
+ num_evaluations: int = 0
103
+
104
+ def top_n(self, n: int = 5) -> list[tuple[dict[str, Any], float]]:
105
+ """Get top N parameter combinations.
106
+
107
+ Args:
108
+ n: Number of top results
109
+
110
+ Returns:
111
+ List of (params, score) tuples
112
+ """
113
+ sorted_results = sorted(self.all_results, key=lambda x: x[1], reverse=True)
114
+ return sorted_results[:n]
115
+
116
+ def to_dict(self) -> dict[str, Any]:
117
+ """Convert to dictionary."""
118
+ return {
119
+ "best_params": self.best_params,
120
+ "best_score": self.best_score,
121
+ "num_evaluations": self.num_evaluations,
122
+ "elapsed_time": self.elapsed_time,
123
+ }
124
+
125
+
126
+ class GridSearch:
127
+ """Grid search optimization for parameter tuning.
128
+
129
+ Exhaustively searches all combinations of parameters to find
130
+ the best combination based on an objective function.
131
+
132
+ Example:
133
+ >>> def objective(params, data):
134
+ ... result = analyze(data, **params)
135
+ ... return result.snr
136
+ >>>
137
+ >>> search = GridSearch([
138
+ ... ParameterSpace("nfft", values=[1024, 2048, 4096, 8192]),
139
+ ... ParameterSpace("window", values=["hann", "hamming"]),
140
+ ... ParameterSpace("overlap", low=0.25, high=0.75, num_samples=5)
141
+ ... ])
142
+ >>>
143
+ >>> result = search.fit(objective, data)
144
+ >>> print(f"Best params: {result.best_params}")
145
+
146
+ References:
147
+ API-014: Parameter Optimization
148
+ """
149
+
150
+ def __init__(self, param_spaces: list[ParameterSpace], verbose: bool = True):
151
+ """Initialize grid search.
152
+
153
+ Args:
154
+ param_spaces: List of parameter spaces
155
+ verbose: Print progress
156
+ """
157
+ self.param_spaces = param_spaces
158
+ self.verbose = verbose
159
+ self._progress_callback: Callable[[int, int], None] | None = None
160
+
161
+ @property
162
+ def num_combinations(self) -> int:
163
+ """Total number of parameter combinations."""
164
+ total = 1
165
+ for space in self.param_spaces:
166
+ total *= len(space)
167
+ return total
168
+
169
+ def on_progress(self, callback: Callable[[int, int], None]) -> GridSearch:
170
+ """Set progress callback.
171
+
172
+ Args:
173
+ callback: Function called with (current, total)
174
+
175
+ Returns:
176
+ Self (for chaining)
177
+ """
178
+ self._progress_callback = callback
179
+ return self
180
+
181
+ def fit(
182
+ self,
183
+ objective: Callable[[dict[str, Any], Any], float],
184
+ data: Any,
185
+ *,
186
+ maximize: bool = True,
187
+ early_stop: float | None = None,
188
+ ) -> OptimizationResult:
189
+ """Run grid search optimization.
190
+
191
+ Args:
192
+ objective: Objective function (params, data) -> score
193
+ data: Data to pass to objective
194
+ maximize: If True, maximize score; if False, minimize
195
+ early_stop: Stop if score reaches this threshold
196
+
197
+ Returns:
198
+ Optimization result
199
+ """
200
+ start_time = time.time()
201
+ all_results: list[tuple[dict[str, Any], float]] = []
202
+ best_params: dict[str, Any] = {}
203
+ best_score = float("-inf") if maximize else float("inf")
204
+
205
+ # Generate all combinations
206
+ param_names = [s.name for s in self.param_spaces]
207
+ param_values = [list(s) for s in self.param_spaces]
208
+
209
+ total = self.num_combinations
210
+ if self.verbose:
211
+ logger.info(f"Grid search: {total} combinations")
212
+
213
+ for i, values in enumerate(itertools.product(*param_values)):
214
+ params = dict(zip(param_names, values, strict=False))
215
+
216
+ try:
217
+ score = objective(params, data)
218
+ except Exception as e:
219
+ logger.warning(f"Objective failed for {params}: {e}")
220
+ score = float("-inf") if maximize else float("inf")
221
+
222
+ all_results.append((params, score))
223
+
224
+ # Update best
225
+ if maximize:
226
+ if score > best_score:
227
+ best_score = score
228
+ best_params = params.copy()
229
+ elif score < best_score:
230
+ best_score = score
231
+ best_params = params.copy()
232
+
233
+ # Progress
234
+ if self._progress_callback:
235
+ self._progress_callback(i + 1, total)
236
+
237
+ # Early stopping
238
+ if early_stop is not None and (
239
+ (maximize and score >= early_stop) or (not maximize and score <= early_stop)
240
+ ):
241
+ if self.verbose:
242
+ logger.info(f"Early stop at {i + 1}/{total}")
243
+ break
244
+
245
+ elapsed = time.time() - start_time
246
+
247
+ if self.verbose:
248
+ logger.info(f"Completed: best_score={best_score:.4f}, time={elapsed:.2f}s")
249
+
250
+ return OptimizationResult(
251
+ best_params=best_params,
252
+ best_score=best_score,
253
+ all_results=all_results,
254
+ elapsed_time=elapsed,
255
+ num_evaluations=len(all_results),
256
+ )
257
+
258
+
259
+ class RandomSearch:
260
+ """Random search optimization.
261
+
262
+ Samples random combinations from parameter space.
263
+
264
+ References:
265
+ API-014: Parameter Optimization
266
+ """
267
+
268
+ def __init__(
269
+ self,
270
+ param_spaces: list[ParameterSpace],
271
+ n_iterations: int = 100,
272
+ random_state: int | None = None,
273
+ ):
274
+ """Initialize random search.
275
+
276
+ Args:
277
+ param_spaces: Parameter spaces
278
+ n_iterations: Number of random samples
279
+ random_state: Random seed
280
+ """
281
+ self.param_spaces = param_spaces
282
+ self.n_iterations = n_iterations
283
+ self.random_state = random_state
284
+
285
+ def fit(
286
+ self,
287
+ objective: Callable[[dict[str, Any], Any], float],
288
+ data: Any,
289
+ *,
290
+ maximize: bool = True,
291
+ ) -> OptimizationResult:
292
+ """Run random search.
293
+
294
+ Args:
295
+ objective: Objective function
296
+ data: Data for objective
297
+ maximize: Maximize or minimize
298
+
299
+ Returns:
300
+ Optimization result
301
+ """
302
+ rng = np.random.default_rng(self.random_state)
303
+ start_time = time.time()
304
+ all_results: list[tuple[dict[str, Any], float]] = []
305
+ best_params: dict[str, Any] = {}
306
+ best_score = float("-inf") if maximize else float("inf")
307
+
308
+ for _ in range(self.n_iterations):
309
+ # Sample random parameters
310
+ params = {}
311
+ for space in self.param_spaces:
312
+ if space.values:
313
+ params[space.name] = rng.choice(space.values)
314
+
315
+ try:
316
+ score = objective(params, data)
317
+ except Exception:
318
+ score = float("-inf") if maximize else float("inf")
319
+
320
+ all_results.append((params, score))
321
+
322
+ if maximize:
323
+ if score > best_score:
324
+ best_score = score
325
+ best_params = params.copy()
326
+ elif score < best_score:
327
+ best_score = score
328
+ best_params = params.copy()
329
+
330
+ return OptimizationResult(
331
+ best_params=best_params,
332
+ best_score=best_score,
333
+ all_results=all_results,
334
+ elapsed_time=time.time() - start_time,
335
+ num_evaluations=len(all_results),
336
+ )
337
+
338
+
339
+ def optimize_parameters(
340
+ objective: Callable[[dict[str, Any], Any], float],
341
+ data: Any,
342
+ param_spaces: list[ParameterSpace] | dict[str, list[Any]],
343
+ *,
344
+ method: str = "grid",
345
+ maximize: bool = True,
346
+ **kwargs: Any,
347
+ ) -> OptimizationResult:
348
+ """Optimize parameters for objective function.
349
+
350
+ Convenience function for parameter optimization.
351
+
352
+ Args:
353
+ objective: Objective function (params, data) -> score
354
+ data: Data to pass to objective
355
+ param_spaces: Parameter spaces (list or dict)
356
+ method: Optimization method ("grid", "random")
357
+ maximize: Maximize or minimize
358
+ **kwargs: Additional arguments for optimizer
359
+
360
+ Returns:
361
+ Optimization result
362
+
363
+ Raises:
364
+ ValueError: If method is not one of the supported types.
365
+
366
+ Example:
367
+ >>> result = optimize_parameters(
368
+ ... objective=lambda p, d: analyze(d, **p).snr,
369
+ ... data=trace,
370
+ ... param_spaces={
371
+ ... "nfft": [1024, 2048, 4096],
372
+ ... "window": ["hann", "hamming"]
373
+ ... }
374
+ ... )
375
+
376
+ References:
377
+ API-014: Parameter Optimization
378
+ """
379
+ # Convert dict to ParameterSpace list
380
+ if isinstance(param_spaces, dict):
381
+ param_spaces = [
382
+ ParameterSpace(name, values=values) for name, values in param_spaces.items()
383
+ ]
384
+
385
+ if method == "grid":
386
+ optimizer = GridSearch(param_spaces, **kwargs)
387
+ elif method == "random":
388
+ optimizer = RandomSearch(param_spaces, **kwargs) # type: ignore[assignment]
389
+ else:
390
+ raise ValueError(f"Unknown optimization method: {method}")
391
+
392
+ return optimizer.fit(objective, data, maximize=maximize)