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,437 @@
1
+ """Packet metrics for stream analysis.
2
+
3
+ This module provides throughput, jitter, and loss rate metrics
4
+ for packet stream analysis.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.analyzers.packet.metrics import throughput, jitter, loss_rate
9
+ >>> rate = throughput(packets)
10
+ >>> jitter_stats = jitter(packets)
11
+
12
+ References:
13
+ RFC 3550 for jitter calculation
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from dataclasses import dataclass
19
+ from typing import TYPE_CHECKING, Any
20
+
21
+ import numpy as np
22
+
23
+ if TYPE_CHECKING:
24
+ from collections.abc import Iterator, Sequence
25
+
26
+ from numpy.typing import NDArray
27
+
28
+
29
+ @dataclass
30
+ class PacketInfo:
31
+ """Packet information for metrics calculation.
32
+
33
+ Attributes:
34
+ timestamp: Packet arrival timestamp in seconds.
35
+ size: Packet size in bytes.
36
+ sequence: Optional sequence number for loss detection.
37
+ """
38
+
39
+ timestamp: float
40
+ size: int
41
+ sequence: int | None = None
42
+
43
+
44
+ @dataclass
45
+ class ThroughputResult:
46
+ """Throughput measurement result.
47
+
48
+ Attributes:
49
+ bytes_per_second: Data rate in bytes/second.
50
+ bits_per_second: Data rate in bits/second.
51
+ packets_per_second: Packet rate.
52
+ total_bytes: Total bytes in measurement period.
53
+ total_packets: Total packets in measurement period.
54
+ duration: Measurement duration in seconds.
55
+ """
56
+
57
+ bytes_per_second: float
58
+ bits_per_second: float
59
+ packets_per_second: float
60
+ total_bytes: int
61
+ total_packets: int
62
+ duration: float
63
+
64
+
65
+ @dataclass
66
+ class JitterResult:
67
+ """Jitter measurement result.
68
+
69
+ Attributes:
70
+ mean: Mean inter-arrival time.
71
+ std: Standard deviation of inter-arrival time.
72
+ min: Minimum inter-arrival time.
73
+ max: Maximum inter-arrival time.
74
+ jitter_rfc3550: RFC 3550 jitter estimate.
75
+ """
76
+
77
+ mean: float
78
+ std: float
79
+ min: float
80
+ max: float
81
+ jitter_rfc3550: float
82
+
83
+
84
+ @dataclass
85
+ class LossResult:
86
+ """Packet loss measurement result.
87
+
88
+ Attributes:
89
+ loss_rate: Loss rate as fraction (0-1).
90
+ loss_percentage: Loss rate as percentage.
91
+ packets_lost: Estimated number of lost packets.
92
+ packets_received: Number of received packets.
93
+ gaps: List of (start_seq, end_seq) gap ranges.
94
+ """
95
+
96
+ loss_rate: float
97
+ loss_percentage: float
98
+ packets_lost: int
99
+ packets_received: int
100
+ gaps: list[tuple[int, int]]
101
+
102
+
103
+ @dataclass
104
+ class LatencyResult:
105
+ """Request-response latency result.
106
+
107
+ Attributes:
108
+ mean: Mean latency in seconds.
109
+ std: Standard deviation.
110
+ min: Minimum latency.
111
+ max: Maximum latency.
112
+ p50: Median latency.
113
+ p95: 95th percentile latency.
114
+ p99: 99th percentile latency.
115
+ samples: Number of samples.
116
+ """
117
+
118
+ mean: float
119
+ std: float
120
+ min: float
121
+ max: float
122
+ p50: float
123
+ p95: float
124
+ p99: float
125
+ samples: int
126
+
127
+
128
+ def throughput(
129
+ packets: Sequence[PacketInfo] | Iterator[PacketInfo],
130
+ *,
131
+ window_size: float | None = None,
132
+ ) -> ThroughputResult:
133
+ """Calculate throughput and packet rate.
134
+
135
+ Args:
136
+ packets: Sequence or iterator of packets.
137
+ window_size: If provided, use sliding window of this duration.
138
+ If None, calculate over entire sequence.
139
+
140
+ Returns:
141
+ ThroughputResult with throughput metrics.
142
+
143
+ Example:
144
+ >>> packets = [PacketInfo(t, sz) for t, sz in data]
145
+ >>> result = throughput(packets)
146
+ >>> print(f"Throughput: {result.bits_per_second / 1e6:.2f} Mbps")
147
+ """
148
+ packet_list = list(packets)
149
+
150
+ if len(packet_list) < 2:
151
+ return ThroughputResult(
152
+ bytes_per_second=0.0,
153
+ bits_per_second=0.0,
154
+ packets_per_second=0.0,
155
+ total_bytes=sum(p.size for p in packet_list),
156
+ total_packets=len(packet_list),
157
+ duration=0.0,
158
+ )
159
+
160
+ total_bytes = sum(p.size for p in packet_list)
161
+ total_packets = len(packet_list)
162
+
163
+ # Sort by timestamp
164
+ sorted_packets = sorted(packet_list, key=lambda p: p.timestamp)
165
+ duration = sorted_packets[-1].timestamp - sorted_packets[0].timestamp
166
+
167
+ if duration <= 0:
168
+ duration = 1e-9 # Avoid division by zero
169
+
170
+ bytes_per_second = total_bytes / duration
171
+ packets_per_second = total_packets / duration
172
+
173
+ return ThroughputResult(
174
+ bytes_per_second=bytes_per_second,
175
+ bits_per_second=bytes_per_second * 8,
176
+ packets_per_second=packets_per_second,
177
+ total_bytes=total_bytes,
178
+ total_packets=total_packets,
179
+ duration=duration,
180
+ )
181
+
182
+
183
+ def jitter(
184
+ packets: Sequence[PacketInfo] | Iterator[PacketInfo],
185
+ ) -> JitterResult:
186
+ """Calculate inter-arrival time jitter.
187
+
188
+ Computes jitter statistics including RFC 3550 jitter estimate.
189
+
190
+ Args:
191
+ packets: Sequence or iterator of packets with timestamps.
192
+
193
+ Returns:
194
+ JitterResult with jitter metrics.
195
+
196
+ Example:
197
+ >>> result = jitter(packets)
198
+ >>> print(f"Jitter: {result.std * 1000:.3f} ms")
199
+
200
+ References:
201
+ RFC 3550 Section A.8 for jitter calculation
202
+ """
203
+ packet_list = list(packets)
204
+
205
+ if len(packet_list) < 2:
206
+ return JitterResult(
207
+ mean=0.0,
208
+ std=0.0,
209
+ min=0.0,
210
+ max=0.0,
211
+ jitter_rfc3550=0.0,
212
+ )
213
+
214
+ # Sort by timestamp
215
+ sorted_packets = sorted(packet_list, key=lambda p: p.timestamp)
216
+
217
+ # Calculate inter-arrival times
218
+ timestamps = np.array([p.timestamp for p in sorted_packets])
219
+ iat = np.diff(timestamps)
220
+
221
+ # RFC 3550 jitter estimate (smoothed absolute deviation)
222
+ # J(i) = J(i-1) + (|D(i-1,i)| - J(i-1))/16
223
+ # where D(i-1,i) is the difference in inter-arrival times
224
+ if len(iat) > 1:
225
+ d = np.diff(iat) # Deviation from expected IAT
226
+ jitter_rfc = 0.0
227
+ for deviation in np.abs(d):
228
+ jitter_rfc = jitter_rfc + (deviation - jitter_rfc) / 16
229
+ else:
230
+ jitter_rfc = 0.0
231
+
232
+ return JitterResult(
233
+ mean=float(np.mean(iat)),
234
+ std=float(np.std(iat)),
235
+ min=float(np.min(iat)),
236
+ max=float(np.max(iat)),
237
+ jitter_rfc3550=float(jitter_rfc),
238
+ )
239
+
240
+
241
+ def loss_rate(
242
+ packets: Sequence[PacketInfo] | Iterator[PacketInfo],
243
+ ) -> LossResult:
244
+ """Detect and report packet loss from sequence numbers.
245
+
246
+ Args:
247
+ packets: Sequence or iterator of packets with sequence numbers.
248
+
249
+ Returns:
250
+ LossResult with loss metrics.
251
+
252
+ Example:
253
+ >>> result = loss_rate(packets)
254
+ >>> print(f"Loss rate: {result.loss_percentage:.2f}%")
255
+ >>> for start, end in result.gaps:
256
+ ... print(f"Gap: {start} to {end}")
257
+ """
258
+ packet_list = list(packets)
259
+
260
+ # Filter packets with sequence numbers
261
+ with_seq = [(p.sequence, p.timestamp) for p in packet_list if p.sequence is not None]
262
+
263
+ if len(with_seq) < 2:
264
+ return LossResult(
265
+ loss_rate=0.0,
266
+ loss_percentage=0.0,
267
+ packets_lost=0,
268
+ packets_received=len(packet_list),
269
+ gaps=[],
270
+ )
271
+
272
+ # Sort by sequence number
273
+ sorted_seqs = sorted(with_seq, key=lambda x: x[0])
274
+ sequences = [s[0] for s in sorted_seqs]
275
+
276
+ # Find gaps in sequence
277
+ gaps: list[tuple[int, int]] = []
278
+ packets_lost = 0
279
+
280
+ for i in range(1, len(sequences)):
281
+ expected = sequences[i - 1] + 1
282
+ actual = sequences[i]
283
+
284
+ if actual > expected:
285
+ # Gap detected
286
+ gaps.append((expected, actual - 1))
287
+ packets_lost += actual - expected
288
+
289
+ # Calculate loss rate
290
+ total_expected = sequences[-1] - sequences[0] + 1
291
+ packets_received = len(sequences)
292
+
293
+ loss_frac = packets_lost / total_expected if total_expected > 0 else 0.0
294
+
295
+ return LossResult(
296
+ loss_rate=loss_frac,
297
+ loss_percentage=loss_frac * 100,
298
+ packets_lost=packets_lost,
299
+ packets_received=packets_received,
300
+ gaps=gaps,
301
+ )
302
+
303
+
304
+ def latency(
305
+ request_times: Sequence[float] | NDArray[np.floating[Any]],
306
+ response_times: Sequence[float] | NDArray[np.floating[Any]],
307
+ ) -> LatencyResult:
308
+ """Calculate request-response latency statistics.
309
+
310
+ Args:
311
+ request_times: Array of request timestamps.
312
+ response_times: Array of corresponding response timestamps.
313
+
314
+ Returns:
315
+ LatencyResult with latency statistics.
316
+
317
+ Raises:
318
+ ValueError: If request and response arrays have different lengths.
319
+
320
+ Example:
321
+ >>> result = latency(request_times, response_times)
322
+ >>> print(f"Mean latency: {result.mean * 1000:.2f} ms")
323
+ >>> print(f"P99 latency: {result.p99 * 1000:.2f} ms")
324
+ """
325
+ req = np.asarray(request_times)
326
+ resp = np.asarray(response_times)
327
+
328
+ if len(req) != len(resp):
329
+ raise ValueError("Request and response arrays must have same length")
330
+
331
+ if len(req) == 0:
332
+ return LatencyResult(
333
+ mean=0.0,
334
+ std=0.0,
335
+ min=0.0,
336
+ max=0.0,
337
+ p50=0.0,
338
+ p95=0.0,
339
+ p99=0.0,
340
+ samples=0,
341
+ )
342
+
343
+ latencies = resp - req
344
+
345
+ # Filter out negative latencies (invalid pairings)
346
+ valid = latencies >= 0
347
+ latencies = latencies[valid]
348
+
349
+ if len(latencies) == 0:
350
+ return LatencyResult(
351
+ mean=0.0,
352
+ std=0.0,
353
+ min=0.0,
354
+ max=0.0,
355
+ p50=0.0,
356
+ p95=0.0,
357
+ p99=0.0,
358
+ samples=0,
359
+ )
360
+
361
+ return LatencyResult(
362
+ mean=float(np.mean(latencies)),
363
+ std=float(np.std(latencies)),
364
+ min=float(np.min(latencies)),
365
+ max=float(np.max(latencies)),
366
+ p50=float(np.percentile(latencies, 50)),
367
+ p95=float(np.percentile(latencies, 95)),
368
+ p99=float(np.percentile(latencies, 99)),
369
+ samples=len(latencies),
370
+ )
371
+
372
+
373
+ def windowed_throughput(
374
+ packets: Sequence[PacketInfo],
375
+ window_size: float,
376
+ step_size: float | None = None,
377
+ ) -> tuple[NDArray[np.float64], NDArray[np.float64]]:
378
+ """Calculate throughput over sliding windows.
379
+
380
+ Args:
381
+ packets: Sequence of packets.
382
+ window_size: Window size in seconds.
383
+ step_size: Step size in seconds (default: window_size / 2).
384
+
385
+ Returns:
386
+ (times, throughputs) - Center times and throughput values.
387
+
388
+ Example:
389
+ >>> times, rates = windowed_throughput(packets, window_size=1.0)
390
+ >>> plt.plot(times, rates / 1e6)
391
+ >>> plt.ylabel("Throughput (Mbps)")
392
+ """
393
+ if step_size is None:
394
+ step_size = window_size / 2
395
+
396
+ packet_list = sorted(packets, key=lambda p: p.timestamp)
397
+
398
+ if len(packet_list) < 2:
399
+ return np.array([]), np.array([])
400
+
401
+ start_time = packet_list[0].timestamp
402
+ end_time = packet_list[-1].timestamp
403
+
404
+ times = []
405
+ throughputs = []
406
+
407
+ window_start = start_time
408
+
409
+ while window_start + window_size <= end_time:
410
+ window_end = window_start + window_size
411
+
412
+ # Count bytes in window
413
+ window_bytes = sum(p.size for p in packet_list if window_start <= p.timestamp < window_end)
414
+
415
+ center_time = window_start + window_size / 2
416
+ rate = window_bytes / window_size * 8 # bits/second
417
+
418
+ times.append(center_time)
419
+ throughputs.append(rate)
420
+
421
+ window_start += step_size
422
+
423
+ return np.array(times), np.array(throughputs)
424
+
425
+
426
+ __all__ = [
427
+ "JitterResult",
428
+ "LatencyResult",
429
+ "LossResult",
430
+ "PacketInfo",
431
+ "ThroughputResult",
432
+ "jitter",
433
+ "latency",
434
+ "loss_rate",
435
+ "throughput",
436
+ "windowed_throughput",
437
+ ]