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,584 @@
1
+ """Packet validation and integrity checking.
2
+
3
+ This module provides comprehensive packet validation including sync markers,
4
+ sequence numbers, checksums, and structural integrity verification.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.loaders.validation import PacketValidator
9
+ >>> validator = PacketValidator(sync_marker=0xFA, checksum_type="crc16")
10
+ >>> result = validator.validate_packet(packet_data)
11
+ >>> if result.is_valid:
12
+ ... print("Packet valid")
13
+ >>> stats = validator.get_statistics()
14
+ >>> print(f"Pass rate: {stats.pass_rate:.1%}")
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import logging
20
+ from dataclasses import dataclass, field
21
+ from typing import Any
22
+
23
+ # Logger for debug output
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ @dataclass
28
+ class SequenceGap:
29
+ """Sequence gap information.
30
+
31
+
32
+
33
+ Attributes:
34
+ position: Packet position where gap was detected.
35
+ expected: Expected sequence number.
36
+ got: Actual sequence number received.
37
+ gap_size: Size of the gap (number of missing packets).
38
+ """
39
+
40
+ position: int
41
+ expected: int
42
+ got: int
43
+ gap_size: int
44
+
45
+
46
+ @dataclass
47
+ class SequenceValidation:
48
+ """Sequence validation results.
49
+
50
+
51
+
52
+ Attributes:
53
+ total_packets: Total number of packets validated.
54
+ sequence_gaps: List of detected sequence gaps.
55
+ duplicates: Number of duplicate sequence numbers.
56
+ valid: Whether sequence validation passed overall.
57
+ """
58
+
59
+ total_packets: int = 0
60
+ sequence_gaps: list[SequenceGap] = field(default_factory=list)
61
+ duplicates: int = 0
62
+ valid: bool = True
63
+
64
+ @property
65
+ def gap_count(self) -> int:
66
+ """Number of sequence gaps detected.
67
+
68
+ Returns:
69
+ Number of gaps.
70
+ """
71
+ return len(self.sequence_gaps)
72
+
73
+ @property
74
+ def total_missing_packets(self) -> int:
75
+ """Total number of missing packets across all gaps.
76
+
77
+ Returns:
78
+ Sum of all gap sizes.
79
+ """
80
+ return sum(gap.gap_size for gap in self.sequence_gaps)
81
+
82
+
83
+ @dataclass
84
+ class ValidationResult:
85
+ """Result of packet validation.
86
+
87
+
88
+
89
+ Attributes:
90
+ is_valid: Whether packet passed all validation checks.
91
+ sync_valid: Sync marker validation result.
92
+ sequence_valid: Sequence number validation result.
93
+ checksum_valid: Checksum validation result.
94
+ errors: List of validation error messages.
95
+ warnings: List of validation warnings.
96
+ packet_index: Index of validated packet.
97
+ """
98
+
99
+ is_valid: bool = True
100
+ sync_valid: bool = True
101
+ sequence_valid: bool = True
102
+ checksum_valid: bool = True
103
+ errors: list[str] = field(default_factory=list)
104
+ warnings: list[str] = field(default_factory=list)
105
+ packet_index: int = 0
106
+
107
+ def add_error(self, message: str) -> None:
108
+ """Add validation error.
109
+
110
+ Args:
111
+ message: Error message.
112
+ """
113
+ self.errors.append(message)
114
+ self.is_valid = False
115
+
116
+ def add_warning(self, message: str) -> None:
117
+ """Add validation warning.
118
+
119
+ Args:
120
+ message: Warning message.
121
+ """
122
+ self.warnings.append(message)
123
+
124
+
125
+ @dataclass
126
+ class ValidationStats:
127
+ """Aggregate validation statistics.
128
+
129
+
130
+
131
+ Attributes:
132
+ total_packets: Total number of packets validated.
133
+ valid_packets: Number of packets that passed all checks.
134
+ sync_failures: Number of sync marker failures.
135
+ sequence_gaps: Number of sequence gaps detected.
136
+ sequence_duplicates: Number of duplicate sequences detected.
137
+ checksum_failures: Number of checksum failures.
138
+ error_types: Dictionary of error type counts.
139
+ """
140
+
141
+ total_packets: int = 0
142
+ valid_packets: int = 0
143
+ sync_failures: int = 0
144
+ sequence_gaps: int = 0
145
+ sequence_duplicates: int = 0
146
+ checksum_failures: int = 0
147
+ error_types: dict[str, int] = field(default_factory=dict)
148
+
149
+ @property
150
+ def pass_rate(self) -> float:
151
+ """Calculate validation pass rate.
152
+
153
+ Returns:
154
+ Fraction of packets that passed validation (0.0 to 1.0).
155
+ """
156
+ if self.total_packets == 0:
157
+ return 0.0
158
+ return self.valid_packets / self.total_packets
159
+
160
+ @property
161
+ def fail_rate(self) -> float:
162
+ """Calculate validation fail rate.
163
+
164
+ Returns:
165
+ Fraction of packets that failed validation (0.0 to 1.0).
166
+ """
167
+ return 1.0 - self.pass_rate
168
+
169
+ def add_error_type(self, error_type: str) -> None:
170
+ """Increment error type counter.
171
+
172
+ Args:
173
+ error_type: Type of error (e.g., "sync_mismatch", "checksum_fail").
174
+ """
175
+ self.error_types[error_type] = self.error_types.get(error_type, 0) + 1
176
+
177
+
178
+ class PacketValidator:
179
+ """Validate packet integrity and structure.
180
+
181
+
182
+
183
+ Performs comprehensive validation including:
184
+ - Sync/magic byte verification
185
+ - Sequence number gap/duplicate detection
186
+ - Checksum verification (CRC-8/16/32, sum, XOR)
187
+ - Field value range validation
188
+
189
+ Attributes:
190
+ sync_marker: Expected sync marker value (optional).
191
+ sync_field: Name of sync field in packet header (optional).
192
+ sequence_field: Name of sequence field in packet header (optional).
193
+ checksum_type: Checksum algorithm ("crc8", "crc16", "crc32", "sum", "xor", optional).
194
+ checksum_field: Name of checksum field in packet header (optional).
195
+ strictness: Validation strictness level ("strict", "normal", "lenient").
196
+ stats: Validation statistics.
197
+ """
198
+
199
+ def __init__(
200
+ self,
201
+ *,
202
+ sync_marker: int | bytes | None = None,
203
+ sync_field: str = "sync_marker",
204
+ sequence_field: str = "sequence",
205
+ checksum_type: str | None = None,
206
+ checksum_field: str = "checksum",
207
+ strictness: str = "normal",
208
+ ) -> None:
209
+ """Initialize packet validator.
210
+
211
+ Args:
212
+ sync_marker: Expected sync marker value (optional).
213
+ sync_field: Name of sync field in packet header (default: "sync_marker").
214
+ sequence_field: Name of sequence field in packet header (default: "sequence").
215
+ checksum_type: Checksum algorithm (optional).
216
+ checksum_field: Name of checksum field in packet header (default: "checksum").
217
+ strictness: Validation strictness ("strict", "normal", "lenient").
218
+ """
219
+ self.sync_marker = sync_marker
220
+ self.sync_field = sync_field
221
+ self.sequence_field = sequence_field
222
+ self.checksum_type = checksum_type
223
+ self.checksum_field = checksum_field
224
+ self.strictness = strictness
225
+
226
+ self.stats = ValidationStats()
227
+ self._last_sequence: int | None = None
228
+
229
+ def validate_packet(
230
+ self, packet: dict[str, Any], packet_data: bytes | None = None
231
+ ) -> ValidationResult:
232
+ """Validate a single packet.
233
+
234
+
235
+
236
+ Args:
237
+ packet: Parsed packet dictionary.
238
+ packet_data: Raw packet bytes (required for checksum validation).
239
+
240
+ Returns:
241
+ ValidationResult with validation outcome.
242
+
243
+ Example:
244
+ >>> validator = PacketValidator(sync_marker=0xFA)
245
+ >>> result = validator.validate_packet(packet)
246
+ >>> if not result.is_valid:
247
+ ... print(f"Errors: {result.errors}")
248
+ """
249
+ result = ValidationResult(packet_index=packet.get("index", 0))
250
+
251
+ header = packet.get("header", {})
252
+
253
+ # Validate sync marker
254
+ if self.sync_marker is not None:
255
+ result.sync_valid = self._validate_sync(header, result)
256
+
257
+ # Validate sequence number
258
+ if self.sequence_field in header:
259
+ result.sequence_valid = self._validate_sequence(header, result)
260
+
261
+ # Validate checksum
262
+ if self.checksum_type is not None and packet_data is not None:
263
+ result.checksum_valid = self._validate_checksum(header, packet_data, result)
264
+
265
+ # Update statistics
266
+ self.stats.total_packets += 1
267
+ if result.is_valid:
268
+ self.stats.valid_packets += 1
269
+
270
+ return result
271
+
272
+ def _validate_sync(self, header: dict[str, Any], result: ValidationResult) -> bool:
273
+ """Validate sync marker.
274
+
275
+ Args:
276
+ header: Packet header dictionary.
277
+ result: Validation result to update.
278
+
279
+ Returns:
280
+ True if sync is valid.
281
+ """
282
+ if self.sync_field not in header:
283
+ if self.strictness == "strict":
284
+ result.add_error(f"Missing sync field: {self.sync_field}")
285
+ self.stats.sync_failures += 1
286
+ self.stats.add_error_type("sync_missing")
287
+ return False
288
+ else:
289
+ result.add_warning(f"Missing sync field: {self.sync_field}")
290
+ return True
291
+
292
+ sync_value = header[self.sync_field]
293
+
294
+ if sync_value != self.sync_marker:
295
+ # Convert bytes to int if needed for formatting
296
+ if isinstance(sync_value, int):
297
+ sync_val_hex = sync_value
298
+ elif isinstance(sync_value, bytes):
299
+ sync_val_hex = int.from_bytes(sync_value, "big")
300
+ else:
301
+ sync_val_hex = int.from_bytes(bytes([sync_value]), "big")
302
+
303
+ # Convert sync_marker to int if needed for formatting
304
+ if isinstance(self.sync_marker, int):
305
+ expected_hex = self.sync_marker
306
+ elif isinstance(self.sync_marker, bytes):
307
+ expected_hex = int.from_bytes(self.sync_marker, "big")
308
+ else:
309
+ expected_hex = 0
310
+
311
+ msg = f"Sync marker mismatch: expected {expected_hex:#x}, got {sync_val_hex:#x}"
312
+ if self.strictness == "strict":
313
+ result.add_error(msg)
314
+ else:
315
+ result.add_warning(msg)
316
+
317
+ self.stats.sync_failures += 1
318
+ self.stats.add_error_type("sync_mismatch")
319
+ return False
320
+
321
+ return True
322
+
323
+ def _validate_sequence(self, header: dict[str, Any], result: ValidationResult) -> bool:
324
+ """Validate sequence number.
325
+
326
+ Args:
327
+ header: Packet header dictionary.
328
+ result: Validation result to update.
329
+
330
+ Returns:
331
+ True if sequence is valid.
332
+ """
333
+ sequence = header.get(self.sequence_field)
334
+ if sequence is None:
335
+ return True # No sequence to validate
336
+
337
+ if self._last_sequence is not None:
338
+ expected = (self._last_sequence + 1) & 0xFFFFFFFF # Handle rollover
339
+
340
+ if sequence == self._last_sequence:
341
+ # Duplicate sequence
342
+ msg = f"Duplicate sequence number: {sequence}"
343
+ result.add_warning(msg)
344
+ self.stats.sequence_duplicates += 1
345
+ self.stats.add_error_type("sequence_duplicate")
346
+ return False
347
+
348
+ elif sequence != expected:
349
+ # Sequence gap
350
+ gap = (sequence - expected) & 0xFFFFFFFF
351
+ msg = f"Sequence gap detected: expected {expected}, got {sequence} (gap: {gap})"
352
+
353
+ if self.strictness == "strict":
354
+ result.add_error(msg)
355
+ else:
356
+ result.add_warning(msg)
357
+
358
+ self.stats.sequence_gaps += 1
359
+ self.stats.add_error_type("sequence_gap")
360
+
361
+ if self.strictness == "strict":
362
+ self._last_sequence = sequence
363
+ return False
364
+
365
+ self._last_sequence = sequence
366
+ return True
367
+
368
+ def _validate_checksum(
369
+ self, header: dict[str, Any], packet_data: bytes, result: ValidationResult
370
+ ) -> bool:
371
+ """Validate packet checksum.
372
+
373
+ Args:
374
+ header: Packet header dictionary.
375
+ packet_data: Raw packet bytes.
376
+ result: Validation result to update.
377
+
378
+ Returns:
379
+ True if checksum is valid.
380
+ """
381
+ if self.checksum_field not in header:
382
+ if self.strictness == "strict":
383
+ result.add_error(f"Missing checksum field: {self.checksum_field}")
384
+ self.stats.checksum_failures += 1
385
+ self.stats.add_error_type("checksum_missing")
386
+ return False
387
+ return True
388
+
389
+ expected_checksum = header[self.checksum_field]
390
+ computed_checksum = self._compute_checksum(packet_data)
391
+
392
+ if computed_checksum != expected_checksum:
393
+ msg = f"Checksum mismatch: expected {expected_checksum:#x}, got {computed_checksum:#x}"
394
+
395
+ if self.strictness == "strict":
396
+ result.add_error(msg)
397
+ else:
398
+ result.add_warning(msg)
399
+
400
+ self.stats.checksum_failures += 1
401
+ self.stats.add_error_type("checksum_fail")
402
+ return False
403
+
404
+ return True
405
+
406
+ def _compute_checksum(self, data: bytes) -> int:
407
+ """Compute checksum using configured algorithm.
408
+
409
+ Args:
410
+ data: Data to checksum.
411
+
412
+ Returns:
413
+ Computed checksum value.
414
+ """
415
+ if self.checksum_type == "crc8":
416
+ return self._crc8(data)
417
+ elif self.checksum_type == "crc16":
418
+ return self._crc16(data)
419
+ elif self.checksum_type == "crc32":
420
+ return self._crc32(data)
421
+ elif self.checksum_type == "sum":
422
+ return sum(data) & 0xFF
423
+ elif self.checksum_type == "xor":
424
+ result = 0
425
+ for byte in data:
426
+ result ^= byte
427
+ return result
428
+ else:
429
+ logger.warning("Unknown checksum type: %s", self.checksum_type)
430
+ return 0
431
+
432
+ @staticmethod
433
+ def _crc8(data: bytes, poly: int = 0x07) -> int:
434
+ """Compute CRC-8 checksum.
435
+
436
+ Args:
437
+ data: Data to checksum.
438
+ poly: CRC polynomial (default: 0x07).
439
+
440
+ Returns:
441
+ CRC-8 value.
442
+ """
443
+ crc = 0
444
+ for byte in data:
445
+ crc ^= byte
446
+ for _ in range(8):
447
+ if crc & 0x80:
448
+ crc = (crc << 1) ^ poly
449
+ else:
450
+ crc <<= 1
451
+ crc &= 0xFF
452
+ return crc
453
+
454
+ @staticmethod
455
+ def _crc16(data: bytes, poly: int = 0x1021) -> int:
456
+ """Compute CRC-16 checksum.
457
+
458
+ Args:
459
+ data: Data to checksum.
460
+ poly: CRC polynomial (default: 0x1021 for CRC-16-CCITT).
461
+
462
+ Returns:
463
+ CRC-16 value.
464
+ """
465
+ crc = 0xFFFF
466
+ for byte in data:
467
+ crc ^= byte << 8
468
+ for _ in range(8):
469
+ if crc & 0x8000:
470
+ crc = (crc << 1) ^ poly
471
+ else:
472
+ crc <<= 1
473
+ crc &= 0xFFFF
474
+ return crc
475
+
476
+ @staticmethod
477
+ def _crc32(data: bytes, poly: int = 0xEDB88320) -> int:
478
+ """Compute CRC-32 checksum.
479
+
480
+ Args:
481
+ data: Data to checksum.
482
+ poly: CRC polynomial (default: 0xEDB88320 for CRC-32).
483
+
484
+ Returns:
485
+ CRC-32 value.
486
+ """
487
+ crc = 0xFFFFFFFF
488
+ for byte in data:
489
+ crc ^= byte
490
+ for _ in range(8):
491
+ if crc & 1:
492
+ crc = (crc >> 1) ^ poly
493
+ else:
494
+ crc >>= 1
495
+ return crc ^ 0xFFFFFFFF
496
+
497
+ def get_statistics(self) -> ValidationStats:
498
+ """Get aggregate validation statistics.
499
+
500
+
501
+
502
+ Returns:
503
+ ValidationStats with cumulative validation results.
504
+
505
+ Example:
506
+ >>> validator = PacketValidator()
507
+ >>> # ... validate packets ...
508
+ >>> stats = validator.get_statistics()
509
+ >>> print(f"Pass rate: {stats.pass_rate:.1%}")
510
+ >>> print(f"Sync failures: {stats.sync_failures}")
511
+ """
512
+ return self.stats
513
+
514
+ def validate_sequence(self, packets: list[dict[str, Any]]) -> SequenceValidation:
515
+ """Validate sequence numbers across multiple packets.
516
+
517
+
518
+
519
+ Args:
520
+ packets: List of parsed packets with headers.
521
+
522
+ Returns:
523
+ SequenceValidation with gap and duplicate detection results.
524
+
525
+ Example:
526
+ >>> validator = PacketValidator(sequence_field="sequence")
527
+ >>> seq_validation = validator.validate_sequence(packets)
528
+ >>> if seq_validation.gap_count > 0:
529
+ ... print(f"Found {seq_validation.gap_count} sequence gaps")
530
+ """
531
+ result = SequenceValidation(total_packets=len(packets))
532
+
533
+ if not packets:
534
+ return result
535
+
536
+ last_seq: int | None = None
537
+
538
+ for i, packet in enumerate(packets):
539
+ header = packet.get("header", {})
540
+ seq = header.get(self.sequence_field)
541
+
542
+ if seq is None:
543
+ continue
544
+
545
+ if last_seq is not None:
546
+ expected = (last_seq + 1) & 0xFFFFFFFF
547
+
548
+ if seq == last_seq:
549
+ # Duplicate
550
+ result.duplicates += 1
551
+ result.valid = False
552
+
553
+ elif seq != expected:
554
+ # Gap detected
555
+ gap_size = (seq - expected) & 0xFFFFFFFF
556
+ gap = SequenceGap(
557
+ position=i,
558
+ expected=expected,
559
+ got=seq,
560
+ gap_size=gap_size,
561
+ )
562
+ result.sequence_gaps.append(gap)
563
+ result.valid = False
564
+
565
+ last_seq = seq
566
+
567
+ return result
568
+
569
+ def reset_statistics(self) -> None:
570
+ """Reset validation statistics.
571
+
572
+ Useful for validating multiple files or resetting state.
573
+ """
574
+ self.stats = ValidationStats()
575
+ self._last_sequence = None
576
+
577
+
578
+ __all__ = [
579
+ "PacketValidator",
580
+ "SequenceGap",
581
+ "SequenceValidation",
582
+ "ValidationResult",
583
+ "ValidationStats",
584
+ ]