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,465 @@
1
+ """Memory usage logging and progress tracking for Oscura operations.
2
+
3
+ This module provides detailed memory profiling logs for debugging and monitoring
4
+ memory usage during long-running operations.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.core.memory_progress import MemoryLogger
9
+ >>> logger = MemoryLogger("analysis.log", format="csv")
10
+ >>> with logger:
11
+ ... for i in range(1000):
12
+ ... # Perform work
13
+ ... logger.log_operation("fft", iteration=i)
14
+ >>> stats = logger.get_summary()
15
+
16
+ References:
17
+ psutil documentation for memory monitoring
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import csv
23
+ import json
24
+ import os
25
+ import time
26
+ from contextlib import contextmanager
27
+ from dataclasses import asdict, dataclass
28
+ from pathlib import Path
29
+ from typing import TYPE_CHECKING, Any, Literal, TextIO
30
+
31
+ from oscura.utils.memory import get_available_memory, get_memory_pressure
32
+
33
+ if TYPE_CHECKING:
34
+ from collections.abc import Iterator
35
+
36
+
37
+ @dataclass
38
+ class MemoryLogEntry:
39
+ """Single memory log entry.
40
+
41
+
42
+ Attributes:
43
+ timestamp: Time of log entry (seconds since epoch).
44
+ operation: Name of operation being performed.
45
+ iteration: Iteration number (if applicable).
46
+ memory_used: Process memory usage (bytes).
47
+ memory_peak: Peak memory since start (bytes).
48
+ memory_available: System available memory (bytes).
49
+ memory_pressure: Memory pressure (0.0-1.0).
50
+ eta_seconds: Estimated time to completion (seconds).
51
+ message: Optional descriptive message.
52
+ """
53
+
54
+ timestamp: float
55
+ operation: str
56
+ iteration: int | None
57
+ memory_used: int
58
+ memory_peak: int
59
+ memory_available: int
60
+ memory_pressure: float
61
+ eta_seconds: float
62
+ message: str
63
+
64
+
65
+ class MemoryLogger:
66
+ """Logger for detailed memory profiling during operations.
67
+
68
+
69
+ Logs memory usage at each operation with timestamps and metadata.
70
+ Supports CSV and JSON output formats.
71
+
72
+ Args:
73
+ log_file: Path to output log file.
74
+ format: Output format ('csv' or 'json').
75
+ auto_flush: Flush after each write (default: True).
76
+ enable_console: Also print to console (default: False).
77
+
78
+ Example:
79
+ >>> logger = MemoryLogger("memory.csv", format="csv")
80
+ >>> with logger:
81
+ ... for i in range(100):
82
+ ... # Do work
83
+ ... logger.log_operation("processing", iteration=i)
84
+ >>> print(logger.get_summary())
85
+
86
+ References:
87
+ MEM-025: Memory Usage Logging
88
+ """
89
+
90
+ def __init__(
91
+ self,
92
+ log_file: str | Path,
93
+ *,
94
+ format: Literal["csv", "json"] = "csv",
95
+ auto_flush: bool = True,
96
+ enable_console: bool = False,
97
+ ):
98
+ """Initialize memory logger.
99
+
100
+ Args:
101
+ log_file: Path to log file.
102
+ format: Output format ('csv' or 'json').
103
+ auto_flush: Flush after each entry.
104
+ enable_console: Print to console as well.
105
+ """
106
+ self.log_file = Path(log_file)
107
+ self.format = format
108
+ self.auto_flush = auto_flush
109
+ self.enable_console = enable_console
110
+
111
+ # State
112
+ self._entries: list[MemoryLogEntry] = []
113
+ self._file_handle: TextIO | None = None
114
+ self._csv_writer: Any = None
115
+ self._start_time = 0.0
116
+ self._start_memory = 0
117
+ self._peak_memory = 0
118
+
119
+ # Create directory if needed
120
+ self.log_file.parent.mkdir(parents=True, exist_ok=True)
121
+
122
+ def __enter__(self) -> MemoryLogger:
123
+ """Enter context and initialize logging."""
124
+ self._start_time = time.time()
125
+ self._start_memory = self._get_process_memory()
126
+ self._peak_memory = self._start_memory
127
+
128
+ # Open log file
129
+ self._file_handle = open(self.log_file, "w", newline="")
130
+
131
+ # Initialize CSV writer if needed
132
+ if self.format == "csv":
133
+ self._csv_writer = csv.DictWriter(
134
+ self._file_handle, # type: ignore[arg-type]
135
+ fieldnames=[
136
+ "timestamp",
137
+ "operation",
138
+ "iteration",
139
+ "memory_used",
140
+ "memory_peak",
141
+ "memory_available",
142
+ "memory_pressure",
143
+ "eta_seconds",
144
+ "message",
145
+ ],
146
+ )
147
+ self._csv_writer.writeheader() # type: ignore[attr-defined]
148
+ if self.auto_flush:
149
+ self._file_handle.flush() # type: ignore[attr-defined]
150
+
151
+ return self
152
+
153
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None: # type: ignore[no-untyped-def]
154
+ """Exit context and finalize logging."""
155
+ # Note: exc_val and exc_tb intentionally unused but required for Python 3.11+ compatibility
156
+ # Write summary for JSON format
157
+ if self.format == "json" and self._file_handle:
158
+ summary = { # type: ignore[unreachable]
159
+ "entries": [asdict(entry) for entry in self._entries],
160
+ "summary": self._get_summary_dict(),
161
+ }
162
+ json.dump(summary, self._file_handle, indent=2)
163
+
164
+ # Close file
165
+ if self._file_handle:
166
+ self._file_handle.close() # type: ignore[unreachable]
167
+ self._file_handle = None
168
+
169
+ def log_operation(
170
+ self,
171
+ operation: str,
172
+ *,
173
+ iteration: int | None = None,
174
+ eta_seconds: float = 0.0,
175
+ message: str = "",
176
+ ) -> None:
177
+ """Log memory usage for an operation.
178
+
179
+
180
+ Args:
181
+ operation: Name of operation.
182
+ iteration: Iteration number (optional).
183
+ eta_seconds: Estimated time to completion.
184
+ message: Optional descriptive message.
185
+
186
+ Example:
187
+ >>> logger.log_operation("fft", iteration=100, eta_seconds=5.2)
188
+
189
+ References:
190
+ MEM-025: Memory Usage Logging
191
+ """
192
+ # Get memory metrics
193
+ memory_used = self._get_process_memory()
194
+ memory_available = get_available_memory()
195
+ memory_pressure = get_memory_pressure()
196
+
197
+ # Update peak
198
+ self._peak_memory = max(self._peak_memory, memory_used)
199
+
200
+ # Create entry
201
+ entry = MemoryLogEntry(
202
+ timestamp=time.time(),
203
+ operation=operation,
204
+ iteration=iteration,
205
+ memory_used=memory_used,
206
+ memory_peak=self._peak_memory,
207
+ memory_available=memory_available,
208
+ memory_pressure=memory_pressure,
209
+ eta_seconds=eta_seconds,
210
+ message=message,
211
+ )
212
+
213
+ self._entries.append(entry)
214
+
215
+ # Write to file
216
+ if self._file_handle and self.format == "csv": # type: ignore[unreachable]
217
+ self._csv_writer.writerow(asdict(entry)) # type: ignore[unreachable]
218
+ if self.auto_flush:
219
+ self._file_handle.flush()
220
+
221
+ # Console output
222
+ if self.enable_console:
223
+ print(self._format_entry(entry))
224
+
225
+ def log_progress(
226
+ self,
227
+ operation: str,
228
+ current: int,
229
+ total: int,
230
+ *,
231
+ message: str = "",
232
+ ) -> None:
233
+ """Log memory usage with progress information.
234
+
235
+
236
+ Convenience method that calculates ETA from progress.
237
+
238
+ Args:
239
+ operation: Name of operation.
240
+ current: Current progress value.
241
+ total: Total progress value.
242
+ message: Optional message.
243
+
244
+ Example:
245
+ >>> for i in range(1000):
246
+ ... logger.log_progress("analysis", i + 1, 1000)
247
+
248
+ References:
249
+ MEM-024: Memory-Aware Progress Callback
250
+ MEM-025: Memory Usage Logging
251
+ """
252
+ # Calculate ETA
253
+ elapsed = time.time() - self._start_time
254
+ eta = elapsed / current * (total - current) if current > 0 else 0.0
255
+
256
+ self.log_operation(
257
+ operation,
258
+ iteration=current,
259
+ eta_seconds=eta,
260
+ message=message,
261
+ )
262
+
263
+ def get_summary(self) -> str:
264
+ """Get human-readable summary of memory usage.
265
+
266
+ Returns:
267
+ Formatted summary string.
268
+
269
+ Example:
270
+ >>> logger = MemoryLogger("test.log")
271
+ >>> with logger:
272
+ ... logger.log_operation("test")
273
+ >>> print(logger.get_summary())
274
+
275
+ References:
276
+ MEM-025: Memory Usage Logging
277
+ """
278
+ summary = self._get_summary_dict()
279
+
280
+ return (
281
+ f"Memory Usage Summary:\n"
282
+ f" Entries: {summary['entry_count']}\n"
283
+ f" Duration: {summary['duration']:.2f}s\n"
284
+ f" Start Memory: {summary['start_memory'] / 1e9:.2f} GB\n"
285
+ f" Peak Memory: {summary['peak_memory'] / 1e9:.2f} GB\n"
286
+ f" Delta: {summary['memory_delta'] / 1e9:.2f} GB\n"
287
+ f" Min Available: {summary['min_available'] / 1e9:.2f} GB\n"
288
+ f" Max Pressure: {summary['max_pressure'] * 100:.1f}%\n"
289
+ )
290
+
291
+ def get_entries(self) -> list[MemoryLogEntry]:
292
+ """Get all logged entries.
293
+
294
+ Returns:
295
+ List of memory log entries.
296
+
297
+ References:
298
+ MEM-025: Memory Usage Logging
299
+ """
300
+ return self._entries.copy()
301
+
302
+ def _get_summary_dict(self) -> dict: # type: ignore[type-arg]
303
+ """Get summary statistics as dictionary."""
304
+ if not self._entries:
305
+ return {
306
+ "entry_count": 0,
307
+ "duration": 0.0,
308
+ "start_memory": self._start_memory,
309
+ "peak_memory": self._peak_memory,
310
+ "memory_delta": 0,
311
+ "min_available": 0,
312
+ "max_pressure": 0.0,
313
+ }
314
+
315
+ duration = self._entries[-1].timestamp - self._entries[0].timestamp
316
+ min_available = min(e.memory_available for e in self._entries)
317
+ max_pressure = max(e.memory_pressure for e in self._entries)
318
+
319
+ return {
320
+ "entry_count": len(self._entries),
321
+ "duration": duration,
322
+ "start_memory": self._start_memory,
323
+ "peak_memory": self._peak_memory,
324
+ "memory_delta": self._peak_memory - self._start_memory,
325
+ "min_available": min_available,
326
+ "max_pressure": max_pressure,
327
+ }
328
+
329
+ def _format_entry(self, entry: MemoryLogEntry) -> str:
330
+ """Format entry for console output."""
331
+ elapsed = entry.timestamp - self._start_time
332
+ return (
333
+ f"[{elapsed:7.2f}s] {entry.operation:20s} | "
334
+ f"Used: {entry.memory_used / 1e9:6.2f} GB | "
335
+ f"Peak: {entry.memory_peak / 1e9:6.2f} GB | "
336
+ f"Avail: {entry.memory_available / 1e9:6.2f} GB | "
337
+ f"Pressure: {entry.memory_pressure * 100:5.1f}%"
338
+ + (f" | {entry.message}" if entry.message else "")
339
+ )
340
+
341
+ def _get_process_memory(self) -> int:
342
+ """Get current process memory usage in bytes."""
343
+ try:
344
+ import psutil
345
+
346
+ process = psutil.Process()
347
+ return process.memory_info().rss # type: ignore[no-any-return]
348
+ except ImportError:
349
+ # Fallback: estimate from system memory
350
+ from oscura.utils.memory import get_total_memory
351
+
352
+ return get_total_memory() - get_available_memory()
353
+
354
+
355
+ @contextmanager
356
+ def log_memory(
357
+ log_file: str | Path,
358
+ *,
359
+ format: Literal["csv", "json"] = "csv",
360
+ enable_console: bool = False,
361
+ ) -> Iterator[MemoryLogger]:
362
+ """Context manager for memory logging.
363
+
364
+
365
+ Convenience function that wraps MemoryLogger.
366
+
367
+ Args:
368
+ log_file: Path to log file.
369
+ format: Output format ('csv' or 'json').
370
+ enable_console: Print to console.
371
+
372
+ Yields:
373
+ MemoryLogger instance.
374
+
375
+ Example:
376
+ >>> with log_memory("analysis.csv") as logger:
377
+ ... for i in range(1000):
378
+ ... # Do work
379
+ ... logger.log_progress("processing", i + 1, 1000)
380
+
381
+ References:
382
+ MEM-025: Memory Usage Logging
383
+ """
384
+ logger = MemoryLogger(log_file, format=format, enable_console=enable_console)
385
+ with logger:
386
+ yield logger
387
+
388
+
389
+ def create_progress_callback_with_logging(
390
+ logger: MemoryLogger,
391
+ operation: str,
392
+ ) -> callable: # type: ignore[valid-type]
393
+ """Create progress callback that logs to MemoryLogger.
394
+
395
+
396
+ Returns a callback function compatible with progress tracking APIs
397
+ that automatically logs memory usage.
398
+
399
+ Args:
400
+ logger: MemoryLogger instance to log to.
401
+ operation: Name of operation.
402
+
403
+ Returns:
404
+ Progress callback function.
405
+
406
+ Example:
407
+ >>> logger = MemoryLogger("test.log")
408
+ >>> callback = create_progress_callback_with_logging(logger, "fft")
409
+ >>> callback(50, 100, "Processing")
410
+
411
+ References:
412
+ MEM-024: Memory-Aware Progress Callback
413
+ MEM-025: Memory Usage Logging
414
+ """
415
+
416
+ def callback(current: int, total: int, message: str) -> None:
417
+ """Progress callback with memory logging."""
418
+ logger.log_progress(operation, current, total, message=message)
419
+
420
+ return callback
421
+
422
+
423
+ def enable_memory_logging_from_cli(
424
+ log_file: str | Path | None = None,
425
+ ) -> MemoryLogger | None:
426
+ """Enable memory logging from CLI flag.
427
+
428
+
429
+ Checks for --log-memory CLI flag and returns logger if enabled.
430
+
431
+ Args:
432
+ log_file: Override log file path (default: auto-generate).
433
+
434
+ Returns:
435
+ MemoryLogger if enabled, None otherwise.
436
+
437
+ Example:
438
+ >>> logger = enable_memory_logging_from_cli()
439
+ >>> if logger:
440
+ ... with logger:
441
+ ... # Operations are logged
442
+ ... logger.log_operation("test")
443
+
444
+ References:
445
+ MEM-025: Memory Usage Logging
446
+ """
447
+ # Check environment variable
448
+ if os.environ.get("TK_LOG_MEMORY", "").lower() not in ("1", "true", "yes"):
449
+ return None
450
+
451
+ # Generate log file name if not provided
452
+ if log_file is None:
453
+ timestamp = time.strftime("%Y%m%d_%H%M%S")
454
+ log_file = Path(f"oscura_memory_{timestamp}.csv")
455
+
456
+ return MemoryLogger(log_file, format="csv", enable_console=False)
457
+
458
+
459
+ __all__ = [
460
+ "MemoryLogEntry",
461
+ "MemoryLogger",
462
+ "create_progress_callback_with_logging",
463
+ "enable_memory_logging_from_cli",
464
+ "log_memory",
465
+ ]