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,363 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://oscura.io/schemas/protocol_definition.json",
4
+ "title": "Protocol Definition Schema",
5
+ "description": "Schema for validating protocol DSL definitions for automatic decoder/encoder generation (CFG-001).",
6
+ "type": "object",
7
+ "required": ["name", "settings", "framing", "fields"],
8
+ "additionalProperties": true,
9
+ "properties": {
10
+ "name": {
11
+ "type": "string",
12
+ "description": "Protocol identifier",
13
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$",
14
+ "minLength": 1
15
+ },
16
+ "version": {
17
+ "type": "string",
18
+ "description": "Protocol version",
19
+ "pattern": "^\\d+\\.\\d+$"
20
+ },
21
+ "description": {
22
+ "type": "string",
23
+ "description": "Human-readable description"
24
+ },
25
+ "settings": {
26
+ "type": "object",
27
+ "description": "Global protocol settings",
28
+ "properties": {
29
+ "endian": {
30
+ "type": "string",
31
+ "enum": ["big", "little", "native"],
32
+ "description": "Default byte order"
33
+ },
34
+ "alignment": {
35
+ "type": "integer",
36
+ "minimum": 1,
37
+ "description": "Byte alignment (1 = no padding)"
38
+ },
39
+ "strict": {
40
+ "type": "boolean",
41
+ "description": "Fail on unknown fields or extra data"
42
+ }
43
+ },
44
+ "additionalProperties": false
45
+ },
46
+ "framing": {
47
+ "type": "object",
48
+ "description": "Message framing and boundary detection",
49
+ "required": ["type"],
50
+ "properties": {
51
+ "type": {
52
+ "type": "string",
53
+ "enum": ["delimiter", "length_prefix", "fixed"],
54
+ "description": "Framing method"
55
+ },
56
+ "sync": {
57
+ "type": "object",
58
+ "description": "Synchronization pattern",
59
+ "properties": {
60
+ "pattern": {
61
+ "type": "array",
62
+ "description": "Sync byte pattern",
63
+ "items": { "type": "integer", "minimum": 0, "maximum": 255 }
64
+ },
65
+ "required": {
66
+ "type": "boolean",
67
+ "description": "Whether sync pattern is mandatory"
68
+ }
69
+ },
70
+ "additionalProperties": false
71
+ },
72
+ "length_field": {
73
+ "type": "object",
74
+ "description": "Length field specification (for length_prefix framing)",
75
+ "properties": {
76
+ "offset": {
77
+ "type": "integer",
78
+ "minimum": 0,
79
+ "description": "Offset from start of message"
80
+ },
81
+ "size": {
82
+ "type": "integer",
83
+ "minimum": 1,
84
+ "maximum": 8,
85
+ "description": "Length field size in bytes"
86
+ },
87
+ "endian": {
88
+ "type": "string",
89
+ "enum": ["big", "little", "native"],
90
+ "description": "Byte order for length field"
91
+ },
92
+ "includes_header": {
93
+ "type": "boolean",
94
+ "description": "Whether length includes header bytes"
95
+ }
96
+ },
97
+ "additionalProperties": false
98
+ },
99
+ "delimiter": {
100
+ "type": "object",
101
+ "description": "Delimiter specification (for delimiter framing)",
102
+ "properties": {
103
+ "pattern": {
104
+ "type": "array",
105
+ "description": "Delimiter byte pattern",
106
+ "items": { "type": "integer", "minimum": 0, "maximum": 255 }
107
+ },
108
+ "escape": {
109
+ "type": "integer",
110
+ "minimum": 0,
111
+ "maximum": 255,
112
+ "description": "Escape byte for escaped delimiters"
113
+ }
114
+ },
115
+ "additionalProperties": false
116
+ },
117
+ "fixed_size": {
118
+ "type": "integer",
119
+ "minimum": 1,
120
+ "description": "Fixed message size (for fixed framing)"
121
+ }
122
+ },
123
+ "additionalProperties": false
124
+ },
125
+ "fields": {
126
+ "type": "array",
127
+ "description": "Field definitions in order",
128
+ "minItems": 1,
129
+ "items": {
130
+ "allOf": [{ "$ref": "#/definitions/field" }, { "required": ["name"] }]
131
+ }
132
+ },
133
+ "computed_fields": {
134
+ "type": "array",
135
+ "description": "Computed/virtual fields derived from other fields",
136
+ "items": {
137
+ "type": "object",
138
+ "required": ["name", "expression"],
139
+ "properties": {
140
+ "name": {
141
+ "type": "string",
142
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$"
143
+ },
144
+ "expression": {
145
+ "type": "string",
146
+ "description": "Expression to compute value"
147
+ },
148
+ "description": {
149
+ "type": "string"
150
+ }
151
+ },
152
+ "additionalProperties": false
153
+ }
154
+ },
155
+ "decoding": {
156
+ "type": "object",
157
+ "description": "Decoding hints and configuration",
158
+ "properties": {
159
+ "min_header_size": {
160
+ "type": "integer",
161
+ "minimum": 1,
162
+ "description": "Minimum bytes to determine message length"
163
+ },
164
+ "max_message_size": {
165
+ "type": "integer",
166
+ "minimum": 1,
167
+ "description": "Maximum allowed message size"
168
+ },
169
+ "resync_on_error": {
170
+ "type": "boolean",
171
+ "description": "Attempt to resynchronize on errors"
172
+ },
173
+ "max_resync_distance": {
174
+ "type": "integer",
175
+ "minimum": 1,
176
+ "description": "Maximum bytes to search for resync"
177
+ }
178
+ },
179
+ "additionalProperties": false
180
+ },
181
+ "encoding": {
182
+ "type": "object",
183
+ "description": "Encoding rules for encoder generation",
184
+ "properties": {
185
+ "auto_fill": {
186
+ "type": "object",
187
+ "description": "Fields to auto-fill when encoding",
188
+ "additionalProperties": { "type": "boolean" }
189
+ },
190
+ "validate_required_fields": {
191
+ "type": "boolean",
192
+ "description": "Validate all required fields present"
193
+ },
194
+ "validate_field_ranges": {
195
+ "type": "boolean",
196
+ "description": "Validate field values in valid ranges"
197
+ }
198
+ },
199
+ "additionalProperties": false
200
+ }
201
+ },
202
+ "definitions": {
203
+ "field": {
204
+ "type": "object",
205
+ "required": ["type"],
206
+ "properties": {
207
+ "name": {
208
+ "type": "string",
209
+ "description": "Field name (optional for array elements)",
210
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$"
211
+ },
212
+ "type": {
213
+ "type": "string",
214
+ "enum": [
215
+ "uint8",
216
+ "uint16",
217
+ "uint32",
218
+ "uint64",
219
+ "int8",
220
+ "int16",
221
+ "int32",
222
+ "int64",
223
+ "float32",
224
+ "float64",
225
+ "bytes",
226
+ "string",
227
+ "array",
228
+ "struct",
229
+ "bitfield"
230
+ ],
231
+ "description": "Field data type"
232
+ },
233
+ "size": {
234
+ "description": "Field size (bytes for bytes type, can be expression)",
235
+ "oneOf": [{ "type": "integer", "minimum": 1 }, { "type": "string" }]
236
+ },
237
+ "endian": {
238
+ "type": "string",
239
+ "enum": ["big", "little", "native"],
240
+ "description": "Byte order override"
241
+ },
242
+ "value": {
243
+ "description": "Expected constant value for validation",
244
+ "oneOf": [
245
+ { "type": "integer" },
246
+ { "type": "number" },
247
+ { "type": "string" },
248
+ { "type": "array" }
249
+ ]
250
+ },
251
+ "condition": {
252
+ "type": "string",
253
+ "description": "Conditional expression - field only present if true"
254
+ },
255
+ "description": {
256
+ "type": "string",
257
+ "description": "Field description"
258
+ },
259
+ "enum": {
260
+ "type": "object",
261
+ "description": "Enumeration value to name mappings (keys can be integers or hex strings)",
262
+ "additionalProperties": {
263
+ "type": "object",
264
+ "required": ["name"],
265
+ "properties": {
266
+ "name": { "type": "string" },
267
+ "description": { "type": "string" }
268
+ },
269
+ "additionalProperties": false
270
+ }
271
+ },
272
+ "fields": {
273
+ "description": "Nested fields (for bitfield or struct types)",
274
+ "oneOf": [
275
+ {
276
+ "type": "object",
277
+ "description": "Bitfield extraction",
278
+ "patternProperties": {
279
+ "^[a-zA-Z][a-zA-Z0-9_]*$": {
280
+ "type": "object",
281
+ "properties": {
282
+ "bit": {
283
+ "type": "integer",
284
+ "minimum": 0,
285
+ "description": "Single bit position"
286
+ },
287
+ "bits": {
288
+ "type": "array",
289
+ "items": { "type": "integer", "minimum": 0 },
290
+ "minItems": 2,
291
+ "maxItems": 2,
292
+ "description": "Bit range [start, end]"
293
+ },
294
+ "description": { "type": "string" }
295
+ },
296
+ "oneOf": [{ "required": ["bit"] }, { "required": ["bits"] }]
297
+ }
298
+ }
299
+ },
300
+ {
301
+ "type": "array",
302
+ "description": "Struct fields",
303
+ "items": { "$ref": "#/definitions/field" }
304
+ }
305
+ ]
306
+ },
307
+ "count_field": {
308
+ "type": ["string", "null"],
309
+ "description": "Field name containing array count (for array type)"
310
+ },
311
+ "element": {
312
+ "description": "Array element definition (for array type)",
313
+ "$ref": "#/definitions/field"
314
+ },
315
+ "encoding": {
316
+ "type": "string",
317
+ "description": "Character encoding (for string type)",
318
+ "enum": ["utf-8", "ascii", "latin-1", "utf-16", "utf-32"]
319
+ },
320
+ "validation": {
321
+ "type": "object",
322
+ "description": "Field validation rules",
323
+ "properties": {
324
+ "min": {
325
+ "type": "number",
326
+ "description": "Minimum value"
327
+ },
328
+ "max": {
329
+ "type": "number",
330
+ "description": "Maximum value"
331
+ },
332
+ "expected": {
333
+ "description": "Expected value",
334
+ "oneOf": [
335
+ { "type": "integer" },
336
+ { "type": "number" },
337
+ { "type": "string" },
338
+ { "type": "array" }
339
+ ]
340
+ },
341
+ "on_mismatch": {
342
+ "type": "string",
343
+ "enum": ["error", "warn", "ignore"],
344
+ "description": "Action on validation failure"
345
+ },
346
+ "algorithm": {
347
+ "type": "string",
348
+ "enum": ["crc16_ccitt", "crc32", "md5", "sha1"],
349
+ "description": "Checksum algorithm"
350
+ },
351
+ "scope": {
352
+ "type": "string",
353
+ "enum": ["all_prior", "message", "payload"],
354
+ "description": "Scope for checksum calculation"
355
+ }
356
+ },
357
+ "additionalProperties": false
358
+ }
359
+ },
360
+ "additionalProperties": false
361
+ }
362
+ }
363
+ }
@@ -0,0 +1,16 @@
1
+ """Pattern search and anomaly detection for Oscura.
2
+
3
+
4
+ This module enables efficient pattern matching, anomaly detection, and
5
+ context extraction for debugging and analysis workflows.
6
+ """
7
+
8
+ from oscura.search.anomaly import find_anomalies
9
+ from oscura.search.context import extract_context
10
+ from oscura.search.pattern import find_pattern
11
+
12
+ __all__ = [
13
+ "extract_context",
14
+ "find_anomalies",
15
+ "find_pattern",
16
+ ]
@@ -0,0 +1,292 @@
1
+ """Anomaly detection in signal traces.
2
+
3
+ This module provides automated detection of glitches, timing violations,
4
+ and protocol errors with context extraction for debugging.
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ import numpy as np
10
+ from numpy.typing import NDArray
11
+
12
+
13
+ def find_anomalies(
14
+ trace: NDArray[np.float64],
15
+ anomaly_type: str = "glitch",
16
+ *,
17
+ threshold: float | None = None,
18
+ min_width: float | None = None,
19
+ max_width: float | None = None,
20
+ sample_rate: float | None = None,
21
+ context_samples: int = 100,
22
+ **kwargs: Any,
23
+ ) -> list[dict[str, Any]]:
24
+ """Find glitches, timing violations, or protocol errors in traces.
25
+
26
+ Anomaly detection with context extraction.
27
+ Integrates with QUAL-005 glitch detection for signal quality analysis.
28
+
29
+ Args:
30
+ trace: Input signal trace
31
+ anomaly_type: Type of anomaly to detect:
32
+ - 'glitch': Short-duration voltage spikes/dips
33
+ - 'timing': Edge timing violations (requires sample_rate)
34
+ - 'protocol': Protocol-level errors (requires decoded data)
35
+ threshold: Detection threshold. Meaning depends on anomaly_type:
36
+ - glitch: Voltage deviation from expected level
37
+ - timing: Timing violation threshold in seconds
38
+ min_width: Minimum anomaly width in seconds (requires sample_rate)
39
+ max_width: Maximum anomaly width in seconds (requires sample_rate)
40
+ sample_rate: Sample rate in Hz (required for timing analysis)
41
+ context_samples: Number of samples to include before/after anomaly
42
+ for context extraction (default: 100)
43
+ **kwargs: Additional type-specific parameters
44
+
45
+ Returns:
46
+ List of anomaly dictionaries, each containing:
47
+ - index: Sample index where anomaly occurs
48
+ - type: Anomaly type
49
+ - severity: Severity score (0-1, higher is worse)
50
+ - duration: Duration in samples
51
+ - amplitude: Amplitude deviation (for glitches)
52
+ - context: ±context_samples around anomaly
53
+ - description: Human-readable description
54
+
55
+ Raises:
56
+ ValueError: If invalid anomaly_type or missing required parameters
57
+
58
+ Examples:
59
+ >>> # Detect voltage glitches
60
+ >>> trace = np.array([0, 0, 0, 0.8, 0, 0, 0]) # Spike at index 3
61
+ >>> anomalies = find_anomalies(
62
+ ... trace,
63
+ ... anomaly_type='glitch',
64
+ ... threshold=0.5,
65
+ ... sample_rate=1e6
66
+ ... )
67
+ >>> print(f"Found {len(anomalies)} glitches")
68
+
69
+ >>> # Detect timing violations
70
+ >>> anomalies = find_anomalies(
71
+ ... trace,
72
+ ... anomaly_type='timing',
73
+ ... min_width=10e-9, # 10 ns minimum
74
+ ... max_width=100e-9, # 100 ns maximum
75
+ ... sample_rate=1e9
76
+ ... )
77
+
78
+ Notes:
79
+ - Glitch detection uses derivative and threshold methods
80
+ - Timing detection requires sample_rate for width calculations
81
+ - Context extraction handles edge cases at trace boundaries
82
+ - Integrates with QUAL-005 for comprehensive signal quality analysis
83
+
84
+ References:
85
+ SRCH-002: Anomaly Search
86
+ QUAL-005: Glitch Detection
87
+ """
88
+ if trace.size == 0:
89
+ return []
90
+
91
+ valid_types = {"glitch", "timing", "protocol"}
92
+ if anomaly_type not in valid_types:
93
+ raise ValueError(f"Invalid anomaly_type '{anomaly_type}'. Must be one of: {valid_types}")
94
+
95
+ anomalies: list[dict[str, Any]] = []
96
+
97
+ if anomaly_type == "glitch":
98
+ anomalies = _detect_glitches(
99
+ trace,
100
+ threshold=threshold,
101
+ min_width=min_width,
102
+ max_width=max_width,
103
+ sample_rate=sample_rate,
104
+ context_samples=context_samples,
105
+ )
106
+
107
+ elif anomaly_type == "timing":
108
+ if sample_rate is None:
109
+ raise ValueError("sample_rate required for timing anomaly detection")
110
+
111
+ anomalies = _detect_timing_violations(
112
+ trace,
113
+ sample_rate=sample_rate,
114
+ min_width=min_width,
115
+ max_width=max_width,
116
+ context_samples=context_samples,
117
+ )
118
+
119
+ elif anomaly_type == "protocol":
120
+ # Protocol error detection would integrate with protocol decoders
121
+ # For now, return empty list with note
122
+ anomalies = []
123
+
124
+ return anomalies
125
+
126
+
127
+ def _detect_glitches(
128
+ trace: NDArray[np.float64],
129
+ threshold: float | None,
130
+ min_width: float | None,
131
+ max_width: float | None,
132
+ sample_rate: float | None,
133
+ context_samples: int,
134
+ ) -> list[dict[str, Any]]:
135
+ """Detect voltage glitches using derivative method."""
136
+ glitches: list[dict[str, Any]] = []
137
+
138
+ # Auto-threshold if not provided
139
+ threshold_value: float
140
+ if threshold is None:
141
+ # Use 3 sigma as default threshold
142
+ threshold_value = float(3 * np.std(trace))
143
+ else:
144
+ threshold_value = threshold
145
+
146
+ # Compute derivative to find rapid changes
147
+ derivative = np.diff(trace)
148
+ abs_derivative = np.abs(derivative)
149
+
150
+ # Find points where derivative exceeds threshold
151
+ glitch_candidates = np.where(abs_derivative > threshold_value)[0]
152
+
153
+ if len(glitch_candidates) == 0:
154
+ return glitches
155
+
156
+ # Group consecutive points into glitch events
157
+ glitch_groups = []
158
+ current_group = [glitch_candidates[0]]
159
+
160
+ for idx in glitch_candidates[1:]:
161
+ if idx == current_group[-1] + 1:
162
+ current_group.append(idx)
163
+ else:
164
+ glitch_groups.append(current_group)
165
+ current_group = [idx]
166
+
167
+ if current_group:
168
+ glitch_groups.append(current_group)
169
+
170
+ # Compute baseline once for all glitches (performance optimization)
171
+ # For very large arrays (>1M samples), use percentile approximation
172
+ if len(trace) > 1_000_000:
173
+ # Fast approximation: 50th percentile with linear interpolation
174
+ baseline = float(np.percentile(trace, 50, method="linear"))
175
+ else:
176
+ baseline = float(np.median(trace))
177
+
178
+ # Filter by width if specified
179
+ for group in glitch_groups:
180
+ start_idx = group[0]
181
+ end_idx = group[-1] + 1
182
+ duration_samples = end_idx - start_idx
183
+
184
+ # Check width constraints
185
+ if sample_rate is not None:
186
+ duration_seconds = duration_samples / sample_rate
187
+
188
+ if min_width is not None and duration_seconds < min_width:
189
+ continue
190
+ if max_width is not None and duration_seconds > max_width:
191
+ continue
192
+
193
+ # Extract context
194
+ ctx_start = max(0, start_idx - context_samples)
195
+ ctx_end = min(len(trace), end_idx + context_samples)
196
+ context = trace[ctx_start:ctx_end].copy()
197
+
198
+ # Compute amplitude deviation (baseline computed once above)
199
+ amplitude = np.max(np.abs(trace[start_idx:end_idx] - baseline))
200
+
201
+ # Severity: normalized amplitude
202
+ severity = min(1.0, amplitude / (threshold_value * 3))
203
+
204
+ glitches.append(
205
+ {
206
+ "index": start_idx,
207
+ "type": "glitch",
208
+ "severity": float(severity),
209
+ "duration": duration_samples,
210
+ "amplitude": float(amplitude),
211
+ "context": context,
212
+ "description": f"Glitch at sample {start_idx}, amplitude {amplitude:.3g}",
213
+ }
214
+ )
215
+
216
+ return glitches
217
+
218
+
219
+ def _detect_timing_violations(
220
+ trace: NDArray[np.float64],
221
+ sample_rate: float,
222
+ min_width: float | None,
223
+ max_width: float | None,
224
+ context_samples: int,
225
+ ) -> list[dict[str, Any]]:
226
+ """Detect timing violations (pulse width violations)."""
227
+ violations = []
228
+
229
+ # Simple threshold for digital signal
230
+ threshold = (np.max(trace) + np.min(trace)) / 2
231
+ digital = (trace >= threshold).astype(int)
232
+
233
+ # Find edges
234
+ edges = np.diff(digital)
235
+ rising_edges = np.where(edges == 1)[0]
236
+ falling_edges = np.where(edges == -1)[0]
237
+
238
+ # Measure pulse widths
239
+ for rise in rising_edges:
240
+ # Find next falling edge
241
+ next_fall = falling_edges[falling_edges > rise]
242
+ if len(next_fall) == 0:
243
+ continue
244
+
245
+ fall = next_fall[0]
246
+ pulse_width_samples = fall - rise
247
+ pulse_width_seconds = pulse_width_samples / sample_rate
248
+
249
+ # Check violations
250
+ violated = False
251
+ violation_type = ""
252
+
253
+ if min_width is not None and pulse_width_seconds < min_width:
254
+ violated = True
255
+ violation_type = "too_short"
256
+
257
+ if max_width is not None and pulse_width_seconds > max_width:
258
+ violated = True
259
+ violation_type = "too_long"
260
+
261
+ if violated:
262
+ # Extract context
263
+ ctx_start = max(0, rise - context_samples)
264
+ ctx_end = min(len(trace), fall + context_samples)
265
+ context = trace[ctx_start:ctx_end].copy()
266
+
267
+ # Severity based on deviation
268
+ if min_width is not None:
269
+ deviation = abs(pulse_width_seconds - min_width) / min_width
270
+ elif max_width is not None:
271
+ deviation = abs(pulse_width_seconds - max_width) / max_width
272
+ else:
273
+ deviation = 0.0
274
+
275
+ severity = min(1.0, deviation)
276
+
277
+ violations.append(
278
+ {
279
+ "index": rise,
280
+ "type": f"timing_{violation_type}",
281
+ "severity": float(severity),
282
+ "duration": pulse_width_samples,
283
+ "amplitude": float(pulse_width_seconds),
284
+ "context": context,
285
+ "description": (
286
+ f"Timing violation at sample {rise}: "
287
+ f"pulse width {pulse_width_seconds * 1e9:.1f} ns ({violation_type})"
288
+ ),
289
+ }
290
+ )
291
+
292
+ return violations