oscura 0.0.1__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. oscura/__init__.py +813 -8
  2. oscura/__main__.py +392 -0
  3. oscura/analyzers/__init__.py +37 -0
  4. oscura/analyzers/digital/__init__.py +177 -0
  5. oscura/analyzers/digital/bus.py +691 -0
  6. oscura/analyzers/digital/clock.py +805 -0
  7. oscura/analyzers/digital/correlation.py +720 -0
  8. oscura/analyzers/digital/edges.py +632 -0
  9. oscura/analyzers/digital/extraction.py +413 -0
  10. oscura/analyzers/digital/quality.py +878 -0
  11. oscura/analyzers/digital/signal_quality.py +877 -0
  12. oscura/analyzers/digital/thresholds.py +708 -0
  13. oscura/analyzers/digital/timing.py +1104 -0
  14. oscura/analyzers/eye/__init__.py +46 -0
  15. oscura/analyzers/eye/diagram.py +434 -0
  16. oscura/analyzers/eye/metrics.py +555 -0
  17. oscura/analyzers/jitter/__init__.py +83 -0
  18. oscura/analyzers/jitter/ber.py +333 -0
  19. oscura/analyzers/jitter/decomposition.py +759 -0
  20. oscura/analyzers/jitter/measurements.py +413 -0
  21. oscura/analyzers/jitter/spectrum.py +220 -0
  22. oscura/analyzers/measurements.py +40 -0
  23. oscura/analyzers/packet/__init__.py +171 -0
  24. oscura/analyzers/packet/daq.py +1077 -0
  25. oscura/analyzers/packet/metrics.py +437 -0
  26. oscura/analyzers/packet/parser.py +327 -0
  27. oscura/analyzers/packet/payload.py +2156 -0
  28. oscura/analyzers/packet/payload_analysis.py +1312 -0
  29. oscura/analyzers/packet/payload_extraction.py +236 -0
  30. oscura/analyzers/packet/payload_patterns.py +670 -0
  31. oscura/analyzers/packet/stream.py +359 -0
  32. oscura/analyzers/patterns/__init__.py +266 -0
  33. oscura/analyzers/patterns/clustering.py +1036 -0
  34. oscura/analyzers/patterns/discovery.py +539 -0
  35. oscura/analyzers/patterns/learning.py +797 -0
  36. oscura/analyzers/patterns/matching.py +1091 -0
  37. oscura/analyzers/patterns/periodic.py +650 -0
  38. oscura/analyzers/patterns/sequences.py +767 -0
  39. oscura/analyzers/power/__init__.py +116 -0
  40. oscura/analyzers/power/ac_power.py +391 -0
  41. oscura/analyzers/power/basic.py +383 -0
  42. oscura/analyzers/power/conduction.py +314 -0
  43. oscura/analyzers/power/efficiency.py +297 -0
  44. oscura/analyzers/power/ripple.py +356 -0
  45. oscura/analyzers/power/soa.py +372 -0
  46. oscura/analyzers/power/switching.py +479 -0
  47. oscura/analyzers/protocol/__init__.py +150 -0
  48. oscura/analyzers/protocols/__init__.py +150 -0
  49. oscura/analyzers/protocols/base.py +500 -0
  50. oscura/analyzers/protocols/can.py +620 -0
  51. oscura/analyzers/protocols/can_fd.py +448 -0
  52. oscura/analyzers/protocols/flexray.py +405 -0
  53. oscura/analyzers/protocols/hdlc.py +399 -0
  54. oscura/analyzers/protocols/i2c.py +368 -0
  55. oscura/analyzers/protocols/i2s.py +296 -0
  56. oscura/analyzers/protocols/jtag.py +393 -0
  57. oscura/analyzers/protocols/lin.py +445 -0
  58. oscura/analyzers/protocols/manchester.py +333 -0
  59. oscura/analyzers/protocols/onewire.py +501 -0
  60. oscura/analyzers/protocols/spi.py +334 -0
  61. oscura/analyzers/protocols/swd.py +325 -0
  62. oscura/analyzers/protocols/uart.py +393 -0
  63. oscura/analyzers/protocols/usb.py +495 -0
  64. oscura/analyzers/signal_integrity/__init__.py +63 -0
  65. oscura/analyzers/signal_integrity/embedding.py +294 -0
  66. oscura/analyzers/signal_integrity/equalization.py +370 -0
  67. oscura/analyzers/signal_integrity/sparams.py +484 -0
  68. oscura/analyzers/spectral/__init__.py +53 -0
  69. oscura/analyzers/spectral/chunked.py +273 -0
  70. oscura/analyzers/spectral/chunked_fft.py +571 -0
  71. oscura/analyzers/spectral/chunked_wavelet.py +391 -0
  72. oscura/analyzers/spectral/fft.py +92 -0
  73. oscura/analyzers/statistical/__init__.py +250 -0
  74. oscura/analyzers/statistical/checksum.py +923 -0
  75. oscura/analyzers/statistical/chunked_corr.py +228 -0
  76. oscura/analyzers/statistical/classification.py +778 -0
  77. oscura/analyzers/statistical/entropy.py +1113 -0
  78. oscura/analyzers/statistical/ngrams.py +614 -0
  79. oscura/analyzers/statistics/__init__.py +119 -0
  80. oscura/analyzers/statistics/advanced.py +885 -0
  81. oscura/analyzers/statistics/basic.py +263 -0
  82. oscura/analyzers/statistics/correlation.py +630 -0
  83. oscura/analyzers/statistics/distribution.py +298 -0
  84. oscura/analyzers/statistics/outliers.py +463 -0
  85. oscura/analyzers/statistics/streaming.py +93 -0
  86. oscura/analyzers/statistics/trend.py +520 -0
  87. oscura/analyzers/validation.py +598 -0
  88. oscura/analyzers/waveform/__init__.py +36 -0
  89. oscura/analyzers/waveform/measurements.py +943 -0
  90. oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
  91. oscura/analyzers/waveform/spectral.py +1689 -0
  92. oscura/analyzers/waveform/wavelets.py +298 -0
  93. oscura/api/__init__.py +62 -0
  94. oscura/api/dsl.py +538 -0
  95. oscura/api/fluent.py +571 -0
  96. oscura/api/operators.py +498 -0
  97. oscura/api/optimization.py +392 -0
  98. oscura/api/profiling.py +396 -0
  99. oscura/automotive/__init__.py +73 -0
  100. oscura/automotive/can/__init__.py +52 -0
  101. oscura/automotive/can/analysis.py +356 -0
  102. oscura/automotive/can/checksum.py +250 -0
  103. oscura/automotive/can/correlation.py +212 -0
  104. oscura/automotive/can/discovery.py +355 -0
  105. oscura/automotive/can/message_wrapper.py +375 -0
  106. oscura/automotive/can/models.py +385 -0
  107. oscura/automotive/can/patterns.py +381 -0
  108. oscura/automotive/can/session.py +452 -0
  109. oscura/automotive/can/state_machine.py +300 -0
  110. oscura/automotive/can/stimulus_response.py +461 -0
  111. oscura/automotive/dbc/__init__.py +15 -0
  112. oscura/automotive/dbc/generator.py +156 -0
  113. oscura/automotive/dbc/parser.py +146 -0
  114. oscura/automotive/dtc/__init__.py +30 -0
  115. oscura/automotive/dtc/database.py +3036 -0
  116. oscura/automotive/j1939/__init__.py +14 -0
  117. oscura/automotive/j1939/decoder.py +745 -0
  118. oscura/automotive/loaders/__init__.py +35 -0
  119. oscura/automotive/loaders/asc.py +98 -0
  120. oscura/automotive/loaders/blf.py +77 -0
  121. oscura/automotive/loaders/csv_can.py +136 -0
  122. oscura/automotive/loaders/dispatcher.py +136 -0
  123. oscura/automotive/loaders/mdf.py +331 -0
  124. oscura/automotive/loaders/pcap.py +132 -0
  125. oscura/automotive/obd/__init__.py +14 -0
  126. oscura/automotive/obd/decoder.py +707 -0
  127. oscura/automotive/uds/__init__.py +48 -0
  128. oscura/automotive/uds/decoder.py +265 -0
  129. oscura/automotive/uds/models.py +64 -0
  130. oscura/automotive/visualization.py +369 -0
  131. oscura/batch/__init__.py +55 -0
  132. oscura/batch/advanced.py +627 -0
  133. oscura/batch/aggregate.py +300 -0
  134. oscura/batch/analyze.py +139 -0
  135. oscura/batch/logging.py +487 -0
  136. oscura/batch/metrics.py +556 -0
  137. oscura/builders/__init__.py +41 -0
  138. oscura/builders/signal_builder.py +1131 -0
  139. oscura/cli/__init__.py +14 -0
  140. oscura/cli/batch.py +339 -0
  141. oscura/cli/characterize.py +273 -0
  142. oscura/cli/compare.py +775 -0
  143. oscura/cli/decode.py +551 -0
  144. oscura/cli/main.py +247 -0
  145. oscura/cli/shell.py +350 -0
  146. oscura/comparison/__init__.py +66 -0
  147. oscura/comparison/compare.py +397 -0
  148. oscura/comparison/golden.py +487 -0
  149. oscura/comparison/limits.py +391 -0
  150. oscura/comparison/mask.py +434 -0
  151. oscura/comparison/trace_diff.py +30 -0
  152. oscura/comparison/visualization.py +481 -0
  153. oscura/compliance/__init__.py +70 -0
  154. oscura/compliance/advanced.py +756 -0
  155. oscura/compliance/masks.py +363 -0
  156. oscura/compliance/reporting.py +483 -0
  157. oscura/compliance/testing.py +298 -0
  158. oscura/component/__init__.py +38 -0
  159. oscura/component/impedance.py +365 -0
  160. oscura/component/reactive.py +598 -0
  161. oscura/component/transmission_line.py +312 -0
  162. oscura/config/__init__.py +191 -0
  163. oscura/config/defaults.py +254 -0
  164. oscura/config/loader.py +348 -0
  165. oscura/config/memory.py +271 -0
  166. oscura/config/migration.py +458 -0
  167. oscura/config/pipeline.py +1077 -0
  168. oscura/config/preferences.py +530 -0
  169. oscura/config/protocol.py +875 -0
  170. oscura/config/schema.py +713 -0
  171. oscura/config/settings.py +420 -0
  172. oscura/config/thresholds.py +599 -0
  173. oscura/convenience.py +457 -0
  174. oscura/core/__init__.py +299 -0
  175. oscura/core/audit.py +457 -0
  176. oscura/core/backend_selector.py +405 -0
  177. oscura/core/cache.py +590 -0
  178. oscura/core/cancellation.py +439 -0
  179. oscura/core/confidence.py +225 -0
  180. oscura/core/config.py +506 -0
  181. oscura/core/correlation.py +216 -0
  182. oscura/core/cross_domain.py +422 -0
  183. oscura/core/debug.py +301 -0
  184. oscura/core/edge_cases.py +541 -0
  185. oscura/core/exceptions.py +535 -0
  186. oscura/core/gpu_backend.py +523 -0
  187. oscura/core/lazy.py +832 -0
  188. oscura/core/log_query.py +540 -0
  189. oscura/core/logging.py +931 -0
  190. oscura/core/logging_advanced.py +952 -0
  191. oscura/core/memoize.py +171 -0
  192. oscura/core/memory_check.py +274 -0
  193. oscura/core/memory_guard.py +290 -0
  194. oscura/core/memory_limits.py +336 -0
  195. oscura/core/memory_monitor.py +453 -0
  196. oscura/core/memory_progress.py +465 -0
  197. oscura/core/memory_warnings.py +315 -0
  198. oscura/core/numba_backend.py +362 -0
  199. oscura/core/performance.py +352 -0
  200. oscura/core/progress.py +524 -0
  201. oscura/core/provenance.py +358 -0
  202. oscura/core/results.py +331 -0
  203. oscura/core/types.py +504 -0
  204. oscura/core/uncertainty.py +383 -0
  205. oscura/discovery/__init__.py +52 -0
  206. oscura/discovery/anomaly_detector.py +672 -0
  207. oscura/discovery/auto_decoder.py +415 -0
  208. oscura/discovery/comparison.py +497 -0
  209. oscura/discovery/quality_validator.py +528 -0
  210. oscura/discovery/signal_detector.py +769 -0
  211. oscura/dsl/__init__.py +73 -0
  212. oscura/dsl/commands.py +246 -0
  213. oscura/dsl/interpreter.py +455 -0
  214. oscura/dsl/parser.py +689 -0
  215. oscura/dsl/repl.py +172 -0
  216. oscura/exceptions.py +59 -0
  217. oscura/exploratory/__init__.py +111 -0
  218. oscura/exploratory/error_recovery.py +642 -0
  219. oscura/exploratory/fuzzy.py +513 -0
  220. oscura/exploratory/fuzzy_advanced.py +786 -0
  221. oscura/exploratory/legacy.py +831 -0
  222. oscura/exploratory/parse.py +358 -0
  223. oscura/exploratory/recovery.py +275 -0
  224. oscura/exploratory/sync.py +382 -0
  225. oscura/exploratory/unknown.py +707 -0
  226. oscura/export/__init__.py +25 -0
  227. oscura/export/wireshark/README.md +265 -0
  228. oscura/export/wireshark/__init__.py +47 -0
  229. oscura/export/wireshark/generator.py +312 -0
  230. oscura/export/wireshark/lua_builder.py +159 -0
  231. oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
  232. oscura/export/wireshark/type_mapping.py +165 -0
  233. oscura/export/wireshark/validator.py +105 -0
  234. oscura/exporters/__init__.py +94 -0
  235. oscura/exporters/csv.py +303 -0
  236. oscura/exporters/exporters.py +44 -0
  237. oscura/exporters/hdf5.py +219 -0
  238. oscura/exporters/html_export.py +701 -0
  239. oscura/exporters/json_export.py +291 -0
  240. oscura/exporters/markdown_export.py +367 -0
  241. oscura/exporters/matlab_export.py +354 -0
  242. oscura/exporters/npz_export.py +219 -0
  243. oscura/exporters/spice_export.py +210 -0
  244. oscura/extensibility/__init__.py +131 -0
  245. oscura/extensibility/docs.py +752 -0
  246. oscura/extensibility/extensions.py +1125 -0
  247. oscura/extensibility/logging.py +259 -0
  248. oscura/extensibility/measurements.py +485 -0
  249. oscura/extensibility/plugins.py +414 -0
  250. oscura/extensibility/registry.py +346 -0
  251. oscura/extensibility/templates.py +913 -0
  252. oscura/extensibility/validation.py +651 -0
  253. oscura/filtering/__init__.py +89 -0
  254. oscura/filtering/base.py +563 -0
  255. oscura/filtering/convenience.py +564 -0
  256. oscura/filtering/design.py +725 -0
  257. oscura/filtering/filters.py +32 -0
  258. oscura/filtering/introspection.py +605 -0
  259. oscura/guidance/__init__.py +24 -0
  260. oscura/guidance/recommender.py +429 -0
  261. oscura/guidance/wizard.py +518 -0
  262. oscura/inference/__init__.py +251 -0
  263. oscura/inference/active_learning/README.md +153 -0
  264. oscura/inference/active_learning/__init__.py +38 -0
  265. oscura/inference/active_learning/lstar.py +257 -0
  266. oscura/inference/active_learning/observation_table.py +230 -0
  267. oscura/inference/active_learning/oracle.py +78 -0
  268. oscura/inference/active_learning/teachers/__init__.py +15 -0
  269. oscura/inference/active_learning/teachers/simulator.py +192 -0
  270. oscura/inference/adaptive_tuning.py +453 -0
  271. oscura/inference/alignment.py +653 -0
  272. oscura/inference/bayesian.py +943 -0
  273. oscura/inference/binary.py +1016 -0
  274. oscura/inference/crc_reverse.py +711 -0
  275. oscura/inference/logic.py +288 -0
  276. oscura/inference/message_format.py +1305 -0
  277. oscura/inference/protocol.py +417 -0
  278. oscura/inference/protocol_dsl.py +1084 -0
  279. oscura/inference/protocol_library.py +1230 -0
  280. oscura/inference/sequences.py +809 -0
  281. oscura/inference/signal_intelligence.py +1509 -0
  282. oscura/inference/spectral.py +215 -0
  283. oscura/inference/state_machine.py +634 -0
  284. oscura/inference/stream.py +918 -0
  285. oscura/integrations/__init__.py +59 -0
  286. oscura/integrations/llm.py +1827 -0
  287. oscura/jupyter/__init__.py +32 -0
  288. oscura/jupyter/display.py +268 -0
  289. oscura/jupyter/magic.py +334 -0
  290. oscura/loaders/__init__.py +526 -0
  291. oscura/loaders/binary.py +69 -0
  292. oscura/loaders/configurable.py +1255 -0
  293. oscura/loaders/csv.py +26 -0
  294. oscura/loaders/csv_loader.py +473 -0
  295. oscura/loaders/hdf5.py +9 -0
  296. oscura/loaders/hdf5_loader.py +510 -0
  297. oscura/loaders/lazy.py +370 -0
  298. oscura/loaders/mmap_loader.py +583 -0
  299. oscura/loaders/numpy_loader.py +436 -0
  300. oscura/loaders/pcap.py +432 -0
  301. oscura/loaders/preprocessing.py +368 -0
  302. oscura/loaders/rigol.py +287 -0
  303. oscura/loaders/sigrok.py +321 -0
  304. oscura/loaders/tdms.py +367 -0
  305. oscura/loaders/tektronix.py +711 -0
  306. oscura/loaders/validation.py +584 -0
  307. oscura/loaders/vcd.py +464 -0
  308. oscura/loaders/wav.py +233 -0
  309. oscura/math/__init__.py +45 -0
  310. oscura/math/arithmetic.py +824 -0
  311. oscura/math/interpolation.py +413 -0
  312. oscura/onboarding/__init__.py +39 -0
  313. oscura/onboarding/help.py +498 -0
  314. oscura/onboarding/tutorials.py +405 -0
  315. oscura/onboarding/wizard.py +466 -0
  316. oscura/optimization/__init__.py +19 -0
  317. oscura/optimization/parallel.py +440 -0
  318. oscura/optimization/search.py +532 -0
  319. oscura/pipeline/__init__.py +43 -0
  320. oscura/pipeline/base.py +338 -0
  321. oscura/pipeline/composition.py +242 -0
  322. oscura/pipeline/parallel.py +448 -0
  323. oscura/pipeline/pipeline.py +375 -0
  324. oscura/pipeline/reverse_engineering.py +1119 -0
  325. oscura/plugins/__init__.py +122 -0
  326. oscura/plugins/base.py +272 -0
  327. oscura/plugins/cli.py +497 -0
  328. oscura/plugins/discovery.py +411 -0
  329. oscura/plugins/isolation.py +418 -0
  330. oscura/plugins/lifecycle.py +959 -0
  331. oscura/plugins/manager.py +493 -0
  332. oscura/plugins/registry.py +421 -0
  333. oscura/plugins/versioning.py +372 -0
  334. oscura/py.typed +0 -0
  335. oscura/quality/__init__.py +65 -0
  336. oscura/quality/ensemble.py +740 -0
  337. oscura/quality/explainer.py +338 -0
  338. oscura/quality/scoring.py +616 -0
  339. oscura/quality/warnings.py +456 -0
  340. oscura/reporting/__init__.py +248 -0
  341. oscura/reporting/advanced.py +1234 -0
  342. oscura/reporting/analyze.py +448 -0
  343. oscura/reporting/argument_preparer.py +596 -0
  344. oscura/reporting/auto_report.py +507 -0
  345. oscura/reporting/batch.py +615 -0
  346. oscura/reporting/chart_selection.py +223 -0
  347. oscura/reporting/comparison.py +330 -0
  348. oscura/reporting/config.py +615 -0
  349. oscura/reporting/content/__init__.py +39 -0
  350. oscura/reporting/content/executive.py +127 -0
  351. oscura/reporting/content/filtering.py +191 -0
  352. oscura/reporting/content/minimal.py +257 -0
  353. oscura/reporting/content/verbosity.py +162 -0
  354. oscura/reporting/core.py +508 -0
  355. oscura/reporting/core_formats/__init__.py +17 -0
  356. oscura/reporting/core_formats/multi_format.py +210 -0
  357. oscura/reporting/engine.py +836 -0
  358. oscura/reporting/export.py +366 -0
  359. oscura/reporting/formatting/__init__.py +129 -0
  360. oscura/reporting/formatting/emphasis.py +81 -0
  361. oscura/reporting/formatting/numbers.py +403 -0
  362. oscura/reporting/formatting/standards.py +55 -0
  363. oscura/reporting/formatting.py +466 -0
  364. oscura/reporting/html.py +578 -0
  365. oscura/reporting/index.py +590 -0
  366. oscura/reporting/multichannel.py +296 -0
  367. oscura/reporting/output.py +379 -0
  368. oscura/reporting/pdf.py +373 -0
  369. oscura/reporting/plots.py +731 -0
  370. oscura/reporting/pptx_export.py +360 -0
  371. oscura/reporting/renderers/__init__.py +11 -0
  372. oscura/reporting/renderers/pdf.py +94 -0
  373. oscura/reporting/sections.py +471 -0
  374. oscura/reporting/standards.py +680 -0
  375. oscura/reporting/summary_generator.py +368 -0
  376. oscura/reporting/tables.py +397 -0
  377. oscura/reporting/template_system.py +724 -0
  378. oscura/reporting/templates/__init__.py +15 -0
  379. oscura/reporting/templates/definition.py +205 -0
  380. oscura/reporting/templates/index.html +649 -0
  381. oscura/reporting/templates/index.md +173 -0
  382. oscura/schemas/__init__.py +158 -0
  383. oscura/schemas/bus_configuration.json +322 -0
  384. oscura/schemas/device_mapping.json +182 -0
  385. oscura/schemas/packet_format.json +418 -0
  386. oscura/schemas/protocol_definition.json +363 -0
  387. oscura/search/__init__.py +16 -0
  388. oscura/search/anomaly.py +292 -0
  389. oscura/search/context.py +149 -0
  390. oscura/search/pattern.py +160 -0
  391. oscura/session/__init__.py +34 -0
  392. oscura/session/annotations.py +289 -0
  393. oscura/session/history.py +313 -0
  394. oscura/session/session.py +445 -0
  395. oscura/streaming/__init__.py +43 -0
  396. oscura/streaming/chunked.py +611 -0
  397. oscura/streaming/progressive.py +393 -0
  398. oscura/streaming/realtime.py +622 -0
  399. oscura/testing/__init__.py +54 -0
  400. oscura/testing/synthetic.py +808 -0
  401. oscura/triggering/__init__.py +68 -0
  402. oscura/triggering/base.py +229 -0
  403. oscura/triggering/edge.py +353 -0
  404. oscura/triggering/pattern.py +344 -0
  405. oscura/triggering/pulse.py +581 -0
  406. oscura/triggering/window.py +453 -0
  407. oscura/ui/__init__.py +48 -0
  408. oscura/ui/formatters.py +526 -0
  409. oscura/ui/progressive_display.py +340 -0
  410. oscura/utils/__init__.py +99 -0
  411. oscura/utils/autodetect.py +338 -0
  412. oscura/utils/buffer.py +389 -0
  413. oscura/utils/lazy.py +407 -0
  414. oscura/utils/lazy_imports.py +147 -0
  415. oscura/utils/memory.py +836 -0
  416. oscura/utils/memory_advanced.py +1326 -0
  417. oscura/utils/memory_extensions.py +465 -0
  418. oscura/utils/progressive.py +352 -0
  419. oscura/utils/windowing.py +362 -0
  420. oscura/visualization/__init__.py +321 -0
  421. oscura/visualization/accessibility.py +526 -0
  422. oscura/visualization/annotations.py +374 -0
  423. oscura/visualization/axis_scaling.py +305 -0
  424. oscura/visualization/colors.py +453 -0
  425. oscura/visualization/digital.py +337 -0
  426. oscura/visualization/eye.py +420 -0
  427. oscura/visualization/histogram.py +281 -0
  428. oscura/visualization/interactive.py +858 -0
  429. oscura/visualization/jitter.py +702 -0
  430. oscura/visualization/keyboard.py +394 -0
  431. oscura/visualization/layout.py +365 -0
  432. oscura/visualization/optimization.py +1028 -0
  433. oscura/visualization/palettes.py +446 -0
  434. oscura/visualization/plot.py +92 -0
  435. oscura/visualization/power.py +290 -0
  436. oscura/visualization/power_extended.py +626 -0
  437. oscura/visualization/presets.py +467 -0
  438. oscura/visualization/protocols.py +932 -0
  439. oscura/visualization/render.py +207 -0
  440. oscura/visualization/rendering.py +444 -0
  441. oscura/visualization/reverse_engineering.py +791 -0
  442. oscura/visualization/signal_integrity.py +808 -0
  443. oscura/visualization/specialized.py +553 -0
  444. oscura/visualization/spectral.py +811 -0
  445. oscura/visualization/styles.py +381 -0
  446. oscura/visualization/thumbnails.py +311 -0
  447. oscura/visualization/time_axis.py +351 -0
  448. oscura/visualization/waveform.py +367 -0
  449. oscura/workflow/__init__.py +13 -0
  450. oscura/workflow/dag.py +377 -0
  451. oscura/workflows/__init__.py +58 -0
  452. oscura/workflows/compliance.py +280 -0
  453. oscura/workflows/digital.py +272 -0
  454. oscura/workflows/multi_trace.py +502 -0
  455. oscura/workflows/power.py +178 -0
  456. oscura/workflows/protocol.py +492 -0
  457. oscura/workflows/reverse_engineering.py +639 -0
  458. oscura/workflows/signal_integrity.py +227 -0
  459. oscura-0.1.0.dist-info/METADATA +300 -0
  460. oscura-0.1.0.dist-info/RECORD +463 -0
  461. oscura-0.1.0.dist-info/entry_points.txt +2 -0
  462. {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/licenses/LICENSE +1 -1
  463. oscura-0.0.1.dist-info/METADATA +0 -63
  464. oscura-0.0.1.dist-info/RECORD +0 -5
  465. {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,440 @@
1
+ """Parallel processing utilities for optimization and analysis.
2
+
3
+ This module provides utilities for efficient parallel execution of analysis tasks
4
+ using both thread and process-based parallelism.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import logging
10
+ from collections.abc import Callable
11
+ from concurrent.futures import (
12
+ ProcessPoolExecutor,
13
+ ThreadPoolExecutor,
14
+ as_completed,
15
+ )
16
+ from dataclasses import dataclass
17
+ from typing import TYPE_CHECKING, Any
18
+
19
+ import numpy as np
20
+
21
+ from oscura.core.exceptions import AnalysisError
22
+
23
+ if TYPE_CHECKING:
24
+ from collections.abc import Iterable
25
+
26
+ from numpy.typing import NDArray
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ @dataclass
32
+ class ParallelResult[R]:
33
+ """Result from parallel execution.
34
+
35
+ Attributes:
36
+ results: List of results from all tasks.
37
+ execution_time: Total execution time in seconds.
38
+ success_count: Number of successfully completed tasks.
39
+ error_count: Number of failed tasks.
40
+ errors: List of exceptions encountered.
41
+
42
+ Example:
43
+ >>> result = parallel_map(fn, items)
44
+ >>> print(f"Completed {result.success_count}/{len(items)}")
45
+ """
46
+
47
+ results: list[R]
48
+ execution_time: float
49
+ success_count: int
50
+ error_count: int
51
+ errors: list[Exception] | None = None
52
+
53
+
54
+ @dataclass
55
+ class WorkerPool:
56
+ """Configuration for worker pool management.
57
+
58
+ Attributes:
59
+ max_workers: Maximum number of workers.
60
+ use_threads: Use threads (True) or processes (False).
61
+ timeout: Timeout per task in seconds.
62
+ chunk_size: Number of items per worker chunk.
63
+
64
+ Example:
65
+ >>> pool = WorkerPool(max_workers=4, use_threads=True, timeout=30)
66
+ """
67
+
68
+ max_workers: int = 4
69
+ use_threads: bool = True
70
+ timeout: float | None = None
71
+ chunk_size: int = 1
72
+
73
+
74
+ def get_optimal_workers(max_workers: int | None = None) -> int:
75
+ """Get optimal number of workers for current system.
76
+
77
+ Uses CPU count by default, respecting max_workers limit.
78
+
79
+ Args:
80
+ max_workers: Maximum workers to use. None for all CPUs.
81
+
82
+ Returns:
83
+ Optimal number of workers.
84
+
85
+ Example:
86
+ >>> workers = get_optimal_workers(max_workers=8)
87
+ """
88
+ import os
89
+
90
+ cpu_count = os.cpu_count() or 1
91
+ if max_workers is None:
92
+ return cpu_count
93
+ return min(max_workers, cpu_count)
94
+
95
+
96
+ def parallel_map[T, R](
97
+ func: Callable[[T], R],
98
+ iterable: Iterable[T],
99
+ *,
100
+ max_workers: int | None = None,
101
+ use_threads: bool = True,
102
+ timeout: float | None = None,
103
+ collect_errors: bool = True,
104
+ ) -> ParallelResult[R]:
105
+ """Apply function to items in parallel.
106
+
107
+ Maps a function over an iterable using either threads or processes.
108
+
109
+ Args:
110
+ func: Function to apply to each item.
111
+ iterable: Items to process.
112
+ max_workers: Maximum concurrent workers.
113
+ use_threads: Use threads (True) or processes (False).
114
+ timeout: Timeout per task in seconds.
115
+ collect_errors: Collect errors instead of raising.
116
+
117
+ Returns:
118
+ ParallelResult with results and execution stats.
119
+
120
+ Raises:
121
+ AnalysisError: If collect_errors=False and a task fails.
122
+
123
+ Example:
124
+ >>> def process_item(x):
125
+ ... return x * 2
126
+ >>> result = parallel_map(process_item, range(100))
127
+ >>> print(f"Completed: {result.success_count}")
128
+
129
+ References:
130
+ OPT-001: Parallel Execution Framework
131
+ """
132
+ import time
133
+
134
+ items = list(iterable)
135
+ if not items:
136
+ return ParallelResult(results=[], execution_time=0.0, success_count=0, error_count=0)
137
+
138
+ executor_class = ThreadPoolExecutor if use_threads else ProcessPoolExecutor
139
+ max_workers = get_optimal_workers(max_workers)
140
+
141
+ start_time = time.time()
142
+ results: list[R] = [None] * len(items) # type: ignore[list-item]
143
+ errors: list[Exception] = []
144
+ success_count = 0
145
+ error_count = 0
146
+
147
+ with executor_class(max_workers=max_workers) as executor:
148
+ futures = {executor.submit(func, item): i for i, item in enumerate(items)}
149
+
150
+ for future in as_completed(futures, timeout=timeout):
151
+ idx = futures[future]
152
+ try:
153
+ results[idx] = future.result()
154
+ success_count += 1
155
+ except Exception as e:
156
+ error_count += 1
157
+ errors.append(e)
158
+
159
+ if not collect_errors:
160
+ execution_time = time.time() - start_time
161
+ raise AnalysisError(f"Task {idx} failed: {e!s}") from e
162
+
163
+ execution_time = time.time() - start_time
164
+
165
+ return ParallelResult(
166
+ results=results,
167
+ execution_time=execution_time,
168
+ success_count=success_count,
169
+ error_count=error_count,
170
+ errors=errors if errors else None,
171
+ )
172
+
173
+
174
+ def parallel_reduce[T, R](
175
+ func: Callable[[T], R],
176
+ iterable: Iterable[T],
177
+ reducer: Callable[[list[R]], Any],
178
+ *,
179
+ max_workers: int | None = None,
180
+ use_threads: bool = True,
181
+ timeout: float | None = None,
182
+ ) -> Any:
183
+ """Map and reduce results in parallel.
184
+
185
+ Applies function to items in parallel, then reduces results.
186
+
187
+ Args:
188
+ func: Function to apply to each item.
189
+ iterable: Items to process.
190
+ reducer: Function to reduce list of results.
191
+ max_workers: Maximum concurrent workers.
192
+ use_threads: Use threads (True) or processes (False).
193
+ timeout: Timeout per task in seconds.
194
+
195
+ Returns:
196
+ Reduced result.
197
+
198
+ Example:
199
+ >>> def compute(x):
200
+ ... return x * 2
201
+ >>> result = parallel_reduce(
202
+ ... compute,
203
+ ... range(100),
204
+ ... reducer=lambda x: sum(x)
205
+ ... )
206
+
207
+ References:
208
+ OPT-001: Parallel Execution Framework
209
+ """
210
+ result = parallel_map(
211
+ func,
212
+ iterable,
213
+ max_workers=max_workers,
214
+ use_threads=use_threads,
215
+ timeout=timeout,
216
+ collect_errors=False,
217
+ )
218
+
219
+ return reducer(result.results)
220
+
221
+
222
+ def batch_parallel_map[T, R](
223
+ func: Callable[[list[T]], list[R]],
224
+ iterable: Iterable[T],
225
+ *,
226
+ batch_size: int = 100,
227
+ max_workers: int | None = None,
228
+ use_threads: bool = True,
229
+ timeout: float | None = None,
230
+ ) -> ParallelResult[R]:
231
+ """Apply function to batches of items in parallel.
232
+
233
+ Processes items in batches, useful when function benefits from
234
+ batch processing.
235
+
236
+ Args:
237
+ func: Function accepting list of items.
238
+ iterable: Items to process.
239
+ batch_size: Number of items per batch.
240
+ max_workers: Maximum concurrent workers.
241
+ use_threads: Use threads (True) or processes (False).
242
+ timeout: Timeout per batch in seconds.
243
+
244
+ Returns:
245
+ ParallelResult with flattened results.
246
+
247
+ Example:
248
+ >>> def process_batch(items):
249
+ ... return [x * 2 for x in items]
250
+ >>> result = batch_parallel_map(
251
+ ... process_batch,
252
+ ... range(1000),
253
+ ... batch_size=100
254
+ ... )
255
+
256
+ References:
257
+ OPT-001: Parallel Execution Framework
258
+ """
259
+ import time
260
+
261
+ items = list(iterable)
262
+ if not items:
263
+ return ParallelResult(results=[], execution_time=0.0, success_count=0, error_count=0)
264
+
265
+ # Create batches
266
+ batches = [items[i : i + batch_size] for i in range(0, len(items), batch_size)]
267
+
268
+ start_time = time.time()
269
+ executor_class = ThreadPoolExecutor if use_threads else ProcessPoolExecutor
270
+ max_workers = get_optimal_workers(max_workers)
271
+
272
+ all_results: list[R] = []
273
+ errors: list[Exception] = []
274
+ success_count = 0
275
+ error_count = 0
276
+
277
+ with executor_class(max_workers=max_workers) as executor:
278
+ futures = {executor.submit(func, batch): i for i, batch in enumerate(batches)}
279
+
280
+ for future in as_completed(futures, timeout=timeout):
281
+ try:
282
+ batch_results = future.result()
283
+ all_results.extend(batch_results)
284
+ success_count += 1
285
+ except Exception as e:
286
+ error_count += 1
287
+ errors.append(e)
288
+
289
+ execution_time = time.time() - start_time
290
+
291
+ return ParallelResult(
292
+ results=all_results,
293
+ execution_time=execution_time,
294
+ success_count=success_count,
295
+ error_count=error_count,
296
+ errors=errors if errors else None,
297
+ )
298
+
299
+
300
+ def parallel_filter[T](
301
+ func: Callable[[T], bool],
302
+ iterable: Iterable[T],
303
+ *,
304
+ max_workers: int | None = None,
305
+ use_threads: bool = True,
306
+ timeout: float | None = None,
307
+ ) -> ParallelResult[T]:
308
+ """Filter items in parallel.
309
+
310
+ Applies predicate to items in parallel, filtering results.
311
+
312
+ Args:
313
+ func: Predicate function returning True to keep item.
314
+ iterable: Items to filter.
315
+ max_workers: Maximum concurrent workers.
316
+ use_threads: Use threads (True) or processes (False).
317
+ timeout: Timeout per task in seconds.
318
+
319
+ Returns:
320
+ ParallelResult with filtered items.
321
+
322
+ Example:
323
+ >>> def is_even(x):
324
+ ... return x % 2 == 0
325
+ >>> result = parallel_filter(is_even, range(100))
326
+
327
+ References:
328
+ OPT-001: Parallel Execution Framework
329
+ """
330
+ import time
331
+
332
+ items = list(iterable)
333
+ if not items:
334
+ return ParallelResult(results=[], execution_time=0.0, success_count=0, error_count=0)
335
+
336
+ executor_class = ThreadPoolExecutor if use_threads else ProcessPoolExecutor
337
+ max_workers = get_optimal_workers(max_workers)
338
+
339
+ start_time = time.time()
340
+ results: list[T] = []
341
+ errors: list[Exception] = []
342
+ success_count = 0
343
+ error_count = 0
344
+
345
+ with executor_class(max_workers=max_workers) as executor:
346
+ futures = {executor.submit(func, item): item for item in items}
347
+
348
+ for future in as_completed(futures, timeout=timeout):
349
+ item = futures[future]
350
+ try:
351
+ if future.result():
352
+ results.append(item)
353
+ success_count += 1
354
+ except Exception as e:
355
+ error_count += 1
356
+ errors.append(e)
357
+
358
+ execution_time = time.time() - start_time
359
+
360
+ return ParallelResult(
361
+ results=results,
362
+ execution_time=execution_time,
363
+ success_count=success_count,
364
+ error_count=error_count,
365
+ errors=errors if errors else None,
366
+ )
367
+
368
+
369
+ def chunked_parallel_map(
370
+ func: Callable[[NDArray[np.float64]], NDArray[np.float64]],
371
+ data: NDArray[np.float64],
372
+ *,
373
+ chunk_size: int = 10000,
374
+ max_workers: int | None = None,
375
+ use_threads: bool = True,
376
+ timeout: float | None = None,
377
+ ) -> NDArray[np.float64]:
378
+ """Apply function to chunks of array data in parallel.
379
+
380
+ Useful for processing large arrays where parallelization overhead
381
+ is justified.
382
+
383
+ Args:
384
+ func: Function accepting 1D array chunk.
385
+ data: Array to process.
386
+ chunk_size: Number of samples per chunk.
387
+ max_workers: Maximum concurrent workers.
388
+ use_threads: Use threads (True) or processes (False).
389
+ timeout: Timeout per chunk in seconds.
390
+
391
+ Returns:
392
+ Processed array (concatenated chunks).
393
+
394
+ Raises:
395
+ AnalysisError: If processing fails.
396
+
397
+ Example:
398
+ >>> def process_chunk(chunk):
399
+ ... return np.fft.fft(chunk)
400
+ >>> result = chunked_parallel_map(process_chunk, data, chunk_size=1000)
401
+
402
+ References:
403
+ OPT-001: Parallel Execution Framework
404
+ """
405
+ if len(data) == 0:
406
+ return np.array([])
407
+
408
+ if len(data) <= chunk_size:
409
+ return func(data)
410
+
411
+ # Create chunks
412
+ chunks = [data[i : i + chunk_size] for i in range(0, len(data), chunk_size)]
413
+
414
+ executor_class = ThreadPoolExecutor if use_threads else ProcessPoolExecutor
415
+ max_workers = get_optimal_workers(max_workers)
416
+
417
+ results: list[NDArray[np.float64]] = []
418
+
419
+ with executor_class(max_workers=max_workers) as executor:
420
+ futures = {executor.submit(func, chunk): i for i, chunk in enumerate(chunks)}
421
+
422
+ for future in as_completed(futures, timeout=timeout):
423
+ try:
424
+ results.append(future.result())
425
+ except Exception as e:
426
+ raise AnalysisError(f"Chunk processing failed: {e!s}") from e
427
+
428
+ return np.concatenate(results)
429
+
430
+
431
+ __all__ = [
432
+ "ParallelResult",
433
+ "WorkerPool",
434
+ "batch_parallel_map",
435
+ "chunked_parallel_map",
436
+ "get_optimal_workers",
437
+ "parallel_filter",
438
+ "parallel_map",
439
+ "parallel_reduce",
440
+ ]