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,369 @@
1
+ """Automotive CAN bus visualization utilities.
2
+
3
+ This module provides visualization functions for CAN bus data, including
4
+ message timelines, signal plots, frequency analysis, and bus utilization.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections import Counter
10
+ from typing import TYPE_CHECKING, Any
11
+
12
+ import matplotlib.pyplot as plt
13
+ import numpy as np
14
+
15
+ if TYPE_CHECKING:
16
+ from oscura.automotive.can.models import CANMessage, CANMessageList
17
+
18
+ __all__ = [
19
+ "plot_bus_timeline",
20
+ "plot_bus_utilization",
21
+ "plot_message_distribution",
22
+ "plot_message_frequency",
23
+ "plot_signal_timeline",
24
+ ]
25
+
26
+
27
+ def plot_bus_timeline(
28
+ messages: CANMessageList,
29
+ *,
30
+ max_messages: int = 1000,
31
+ figsize: tuple[float, float] = (12, 6),
32
+ ) -> Any:
33
+ """Plot CAN bus message timeline.
34
+
35
+ Creates a scatter plot showing when each CAN ID appeared on the bus.
36
+ Useful for understanding bus activity patterns and message timing.
37
+
38
+ Args:
39
+ messages: List of CAN messages to plot.
40
+ max_messages: Maximum number of messages to plot (for performance).
41
+ figsize: Figure size (width, height) in inches.
42
+
43
+ Returns:
44
+ Matplotlib figure object.
45
+
46
+ Raises:
47
+ ValueError: If messages list is empty.
48
+
49
+ Example:
50
+ >>> from oscura.automotive.loaders import load_automotive_log
51
+ >>> messages = load_automotive_log("capture.blf")
52
+ >>> plot_bus_timeline(messages)
53
+ """
54
+ if len(messages) == 0:
55
+ raise ValueError("No messages to plot")
56
+
57
+ # Limit messages for performance
58
+ plot_messages = messages[:max_messages]
59
+
60
+ # Ensure plot_messages is a list for iteration
61
+ if isinstance(plot_messages, CANMessage):
62
+ # Single message returned from indexing
63
+ msg_list: list[CANMessage] = [plot_messages]
64
+ else:
65
+ # Must be list[CANMessage] from slice
66
+ msg_list = plot_messages # type: ignore[assignment]
67
+
68
+ # Extract timestamps and IDs
69
+ timestamps = [_get_timestamp(msg) for msg in msg_list]
70
+ arb_ids = [_get_arbitration_id(msg) for msg in msg_list]
71
+
72
+ # Create plot
73
+ fig, ax = plt.subplots(figsize=figsize)
74
+
75
+ ax.scatter(timestamps, arb_ids, alpha=0.5, s=2)
76
+ ax.set_xlabel("Time (s)")
77
+ ax.set_ylabel("CAN Arbitration ID")
78
+ ax.set_title(f"CAN Bus Timeline ({len(msg_list)} messages)")
79
+ ax.grid(True, alpha=0.3)
80
+
81
+ # Format y-axis as hex
82
+ ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f"0x{int(x):03X}"))
83
+
84
+ plt.tight_layout()
85
+ return fig
86
+
87
+
88
+ def plot_message_frequency(
89
+ messages: CANMessageList,
90
+ *,
91
+ top_n: int = 20,
92
+ figsize: tuple[float, float] = (10, 6),
93
+ ) -> Any:
94
+ """Plot CAN message frequency distribution.
95
+
96
+ Creates a bar chart showing the most frequent CAN IDs.
97
+
98
+ Args:
99
+ messages: List of CAN messages to analyze.
100
+ top_n: Number of top IDs to display.
101
+ figsize: Figure size (width, height) in inches.
102
+
103
+ Returns:
104
+ Matplotlib figure object.
105
+
106
+ Raises:
107
+ ValueError: If messages list is empty.
108
+
109
+ Example:
110
+ >>> plot_message_frequency(messages, top_n=15)
111
+ """
112
+ if len(messages) == 0:
113
+ raise ValueError("No messages to plot")
114
+
115
+ # Count message occurrences
116
+ id_counts = Counter(_get_arbitration_id(msg) for msg in messages)
117
+ most_common = id_counts.most_common(top_n)
118
+
119
+ ids = [f"0x{id_:03X}" for id_, _ in most_common]
120
+ counts = [count for _, count in most_common]
121
+
122
+ # Create plot
123
+ fig, ax = plt.subplots(figsize=figsize)
124
+
125
+ bars = ax.bar(range(len(ids)), counts)
126
+ ax.set_xlabel("CAN ID")
127
+ ax.set_ylabel("Message Count")
128
+ ax.set_title(f"Top {top_n} Most Frequent CAN IDs")
129
+ ax.set_xticks(range(len(ids)))
130
+ ax.set_xticklabels(ids, rotation=45, ha="right")
131
+ ax.grid(True, axis="y", alpha=0.3)
132
+
133
+ # Color bars by frequency
134
+ max_count = max(counts)
135
+ for bar, count in zip(bars, counts, strict=False):
136
+ bar.set_color(plt.cm.viridis(count / max_count))
137
+
138
+ plt.tight_layout()
139
+ return fig
140
+
141
+
142
+ def plot_signal_timeline(
143
+ messages: CANMessageList,
144
+ arb_id: int,
145
+ byte_index: int,
146
+ *,
147
+ figsize: tuple[float, float] = (12, 4),
148
+ ) -> Any:
149
+ """Plot timeline of a specific byte in CAN messages.
150
+
151
+ Useful for visualizing how a particular signal changes over time.
152
+
153
+ Args:
154
+ messages: List of CAN messages.
155
+ arb_id: CAN arbitration ID to filter.
156
+ byte_index: Index of byte to plot (0-7).
157
+ figsize: Figure size (width, height) in inches.
158
+
159
+ Returns:
160
+ Matplotlib figure object.
161
+
162
+ Raises:
163
+ ValueError: If no messages found with specified ID or byte index.
164
+
165
+ Example:
166
+ >>> # Plot byte 0 of CAN ID 0x123
167
+ >>> plot_signal_timeline(messages, 0x123, 0)
168
+ """
169
+ # Filter messages by ID
170
+ filtered = [msg for msg in messages if _get_arbitration_id(msg) == arb_id]
171
+
172
+ if len(filtered) == 0:
173
+ raise ValueError(f"No messages found with ID 0x{arb_id:03X}")
174
+
175
+ # Extract timestamps and byte values
176
+ timestamps = []
177
+ values = []
178
+
179
+ for msg in filtered:
180
+ msg_data = _get_data(msg)
181
+ if len(msg_data) > byte_index:
182
+ timestamps.append(_get_timestamp(msg))
183
+ values.append(msg_data[byte_index])
184
+
185
+ if len(values) == 0:
186
+ raise ValueError(f"No messages with ID 0x{arb_id:03X} have byte at index {byte_index}")
187
+
188
+ # Create plot
189
+ fig, ax = plt.subplots(figsize=figsize)
190
+
191
+ ax.plot(timestamps, values, linewidth=1, marker=".", markersize=3)
192
+ ax.set_xlabel("Time (s)")
193
+ ax.set_ylabel(f"Byte {byte_index} Value")
194
+ ax.set_title(f"CAN ID 0x{arb_id:03X} - Byte {byte_index} Timeline")
195
+ ax.grid(True, alpha=0.3)
196
+
197
+ plt.tight_layout()
198
+ return fig
199
+
200
+
201
+ def plot_bus_utilization(
202
+ messages: CANMessageList,
203
+ *,
204
+ window_size: float = 1.0,
205
+ figsize: tuple[float, float] = (12, 5),
206
+ ) -> Any:
207
+ """Plot CAN bus utilization over time.
208
+
209
+ Calculates and plots message rate in messages/second over time windows.
210
+
211
+ Args:
212
+ messages: List of CAN messages.
213
+ window_size: Time window size in seconds for calculating rate.
214
+ figsize: Figure size (width, height) in inches.
215
+
216
+ Returns:
217
+ Matplotlib figure object.
218
+
219
+ Raises:
220
+ ValueError: If messages list is empty or all messages have same timestamp.
221
+
222
+ Example:
223
+ >>> # Plot bus utilization with 0.5s windows
224
+ >>> plot_bus_utilization(messages, window_size=0.5)
225
+ """
226
+ if len(messages) == 0:
227
+ raise ValueError("No messages to plot")
228
+
229
+ # Get time range - use iteration to handle type union
230
+ first_msg: CANMessage = next(iter(messages))
231
+ last_msg: CANMessage = messages.messages[-1] # Access internal list directly
232
+ start_time = _get_timestamp(first_msg)
233
+ end_time = _get_timestamp(last_msg)
234
+ duration = end_time - start_time
235
+
236
+ if duration == 0:
237
+ raise ValueError("All messages have the same timestamp")
238
+
239
+ # Create time bins
240
+ num_bins = int(duration / window_size) + 1
241
+ bins = np.linspace(start_time, end_time, num_bins)
242
+ bin_centers = (bins[:-1] + bins[1:]) / 2
243
+
244
+ # Count messages per bin
245
+ timestamps = np.array([_get_timestamp(msg) for msg in messages])
246
+ counts, _ = np.histogram(timestamps, bins=bins)
247
+
248
+ # Convert to messages/second
249
+ rates = counts / window_size
250
+
251
+ # Create plot
252
+ fig, ax = plt.subplots(figsize=figsize)
253
+
254
+ ax.plot(bin_centers, rates, linewidth=1.5)
255
+ ax.fill_between(bin_centers, rates, alpha=0.3)
256
+ ax.set_xlabel("Time (s)")
257
+ ax.set_ylabel("Message Rate (msg/s)")
258
+ ax.set_title(f"CAN Bus Utilization (window={window_size}s)")
259
+ ax.grid(True, alpha=0.3)
260
+
261
+ # Add statistics
262
+ mean_rate = np.mean(rates)
263
+ ax.axhline(
264
+ mean_rate, color="r", linestyle="--", alpha=0.5, label=f"Mean: {mean_rate:.1f} msg/s"
265
+ )
266
+ ax.legend()
267
+
268
+ plt.tight_layout()
269
+ return fig
270
+
271
+
272
+ def plot_message_distribution(
273
+ messages: CANMessageList,
274
+ *,
275
+ figsize: tuple[float, float] = (10, 8),
276
+ ) -> Any:
277
+ """Plot distribution of CAN message properties.
278
+
279
+ Creates a multi-panel plot showing:
280
+ - DLC (data length) distribution
281
+ - Standard vs Extended ID ratio
282
+ - Message timing histogram
283
+
284
+ Args:
285
+ messages: List of CAN messages.
286
+ figsize: Figure size (width, height) in inches.
287
+
288
+ Returns:
289
+ Matplotlib figure object.
290
+
291
+ Raises:
292
+ ValueError: If messages list is empty.
293
+
294
+ Example:
295
+ >>> plot_message_distribution(messages)
296
+ """
297
+ if len(messages) == 0:
298
+ raise ValueError("No messages to plot")
299
+
300
+ # Create subplots
301
+ fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=figsize)
302
+
303
+ # 1. DLC distribution
304
+ dlcs = [_get_dlc(msg) for msg in messages]
305
+ dlc_counts = Counter(dlcs)
306
+ dlc_values = sorted(dlc_counts.keys())
307
+ dlc_counts_list = [dlc_counts[d] for d in dlc_values]
308
+
309
+ ax1.bar(dlc_values, dlc_counts_list, color="steelblue")
310
+ ax1.set_xlabel("Data Length Code (DLC)")
311
+ ax1.set_ylabel("Count")
312
+ ax1.set_title("Message DLC Distribution")
313
+ ax1.set_xticks(range(9))
314
+ ax1.grid(True, axis="y", alpha=0.3)
315
+
316
+ # 2. ID type distribution
317
+ std_count = sum(1 for msg in messages if not _is_extended(msg))
318
+ ext_count = sum(1 for msg in messages if _is_extended(msg))
319
+
320
+ ax2.bar(
321
+ ["Standard (11-bit)", "Extended (29-bit)"],
322
+ [std_count, ext_count],
323
+ color=["green", "orange"],
324
+ )
325
+ ax2.set_ylabel("Count")
326
+ ax2.set_title("ID Type Distribution")
327
+ ax2.grid(True, axis="y", alpha=0.3)
328
+
329
+ # 3. Inter-message timing histogram
330
+ if len(messages) > 1:
331
+ timestamps = [_get_timestamp(msg) for msg in messages]
332
+ intervals = np.diff(timestamps)
333
+ # Filter out very large gaps (likely recording breaks)
334
+ intervals = intervals[intervals < np.percentile(intervals, 99)]
335
+
336
+ ax3.hist(intervals * 1000, bins=50, color="purple", alpha=0.7) # Convert to ms
337
+ ax3.set_xlabel("Inter-message Time (ms)")
338
+ ax3.set_ylabel("Count")
339
+ ax3.set_title("Message Timing Distribution")
340
+ ax3.grid(True, axis="y", alpha=0.3)
341
+
342
+ plt.tight_layout()
343
+ return fig
344
+
345
+
346
+ # Helper functions to access CANMessage attributes safely
347
+ def _get_timestamp(msg: CANMessage) -> float:
348
+ """Get timestamp from CANMessage."""
349
+ return float(msg.timestamp)
350
+
351
+
352
+ def _get_arbitration_id(msg: CANMessage) -> int:
353
+ """Get arbitration_id from CANMessage."""
354
+ return int(msg.arbitration_id)
355
+
356
+
357
+ def _get_data(msg: CANMessage) -> bytes:
358
+ """Get data from CANMessage."""
359
+ return bytes(msg.data)
360
+
361
+
362
+ def _get_dlc(msg: CANMessage) -> int:
363
+ """Get DLC from CANMessage."""
364
+ return int(msg.dlc)
365
+
366
+
367
+ def _is_extended(msg: CANMessage) -> bool:
368
+ """Check if CANMessage has extended ID."""
369
+ return bool(msg.is_extended)
@@ -0,0 +1,55 @@
1
+ """Batch processing functionality for TraceKit.
2
+
3
+
4
+ This module enables efficient batch analysis of multiple signal files
5
+ with parallel execution support and comprehensive result aggregation.
6
+ """
7
+
8
+ from oscura.batch.advanced import (
9
+ AdvancedBatchProcessor,
10
+ BatchCheckpoint,
11
+ BatchConfig,
12
+ FileResult,
13
+ resume_batch,
14
+ )
15
+ from oscura.batch.aggregate import aggregate_results
16
+ from oscura.batch.analyze import batch_analyze
17
+ from oscura.batch.logging import (
18
+ BatchLogger,
19
+ BatchSummary,
20
+ FileLogEntry,
21
+ FileLogger,
22
+ aggregate_batch_logs,
23
+ )
24
+ from oscura.batch.metrics import (
25
+ BatchMetrics,
26
+ BatchMetricsSummary,
27
+ ErrorBreakdown,
28
+ FileMetrics,
29
+ ThroughputStats,
30
+ TimingStats,
31
+ get_batch_stats,
32
+ )
33
+
34
+ __all__ = [
35
+ # Advanced batch processing (API-012)
36
+ "AdvancedBatchProcessor",
37
+ "BatchCheckpoint",
38
+ "BatchConfig",
39
+ "BatchLogger",
40
+ "BatchMetrics",
41
+ "BatchMetricsSummary",
42
+ "BatchSummary",
43
+ "ErrorBreakdown",
44
+ "FileLogEntry",
45
+ "FileLogger",
46
+ "FileMetrics",
47
+ "FileResult",
48
+ "ThroughputStats",
49
+ "TimingStats",
50
+ "aggregate_batch_logs",
51
+ "aggregate_results",
52
+ "batch_analyze",
53
+ "get_batch_stats",
54
+ "resume_batch",
55
+ ]