oscura 0.5.0__py3-none-any.whl → 0.6.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 (513) hide show
  1. oscura/__init__.py +169 -167
  2. oscura/analyzers/__init__.py +3 -0
  3. oscura/analyzers/classification.py +659 -0
  4. oscura/analyzers/digital/__init__.py +0 -48
  5. oscura/analyzers/digital/edges.py +325 -65
  6. oscura/analyzers/digital/extraction.py +0 -195
  7. oscura/analyzers/digital/quality.py +293 -166
  8. oscura/analyzers/digital/timing.py +260 -115
  9. oscura/analyzers/digital/timing_numba.py +334 -0
  10. oscura/analyzers/entropy.py +605 -0
  11. oscura/analyzers/eye/diagram.py +176 -109
  12. oscura/analyzers/eye/metrics.py +5 -5
  13. oscura/analyzers/jitter/__init__.py +6 -4
  14. oscura/analyzers/jitter/ber.py +52 -52
  15. oscura/analyzers/jitter/classification.py +156 -0
  16. oscura/analyzers/jitter/decomposition.py +163 -113
  17. oscura/analyzers/jitter/spectrum.py +80 -64
  18. oscura/analyzers/ml/__init__.py +39 -0
  19. oscura/analyzers/ml/features.py +600 -0
  20. oscura/analyzers/ml/signal_classifier.py +604 -0
  21. oscura/analyzers/packet/daq.py +246 -158
  22. oscura/analyzers/packet/parser.py +12 -1
  23. oscura/analyzers/packet/payload.py +50 -2110
  24. oscura/analyzers/packet/payload_analysis.py +361 -181
  25. oscura/analyzers/packet/payload_patterns.py +133 -70
  26. oscura/analyzers/packet/stream.py +84 -23
  27. oscura/analyzers/patterns/__init__.py +26 -5
  28. oscura/analyzers/patterns/anomaly_detection.py +908 -0
  29. oscura/analyzers/patterns/clustering.py +169 -108
  30. oscura/analyzers/patterns/clustering_optimized.py +227 -0
  31. oscura/analyzers/patterns/discovery.py +1 -1
  32. oscura/analyzers/patterns/matching.py +581 -197
  33. oscura/analyzers/patterns/pattern_mining.py +778 -0
  34. oscura/analyzers/patterns/periodic.py +121 -38
  35. oscura/analyzers/patterns/sequences.py +175 -78
  36. oscura/analyzers/power/conduction.py +1 -1
  37. oscura/analyzers/power/soa.py +6 -6
  38. oscura/analyzers/power/switching.py +250 -110
  39. oscura/analyzers/protocol/__init__.py +17 -1
  40. oscura/analyzers/protocols/__init__.py +1 -22
  41. oscura/analyzers/protocols/base.py +6 -6
  42. oscura/analyzers/protocols/ble/__init__.py +38 -0
  43. oscura/analyzers/protocols/ble/analyzer.py +809 -0
  44. oscura/analyzers/protocols/ble/uuids.py +288 -0
  45. oscura/analyzers/protocols/can.py +257 -127
  46. oscura/analyzers/protocols/can_fd.py +107 -80
  47. oscura/analyzers/protocols/flexray.py +139 -80
  48. oscura/analyzers/protocols/hdlc.py +93 -58
  49. oscura/analyzers/protocols/i2c.py +247 -106
  50. oscura/analyzers/protocols/i2s.py +138 -86
  51. oscura/analyzers/protocols/industrial/__init__.py +40 -0
  52. oscura/analyzers/protocols/industrial/bacnet/__init__.py +33 -0
  53. oscura/analyzers/protocols/industrial/bacnet/analyzer.py +708 -0
  54. oscura/analyzers/protocols/industrial/bacnet/encoding.py +412 -0
  55. oscura/analyzers/protocols/industrial/bacnet/services.py +622 -0
  56. oscura/analyzers/protocols/industrial/ethercat/__init__.py +30 -0
  57. oscura/analyzers/protocols/industrial/ethercat/analyzer.py +474 -0
  58. oscura/analyzers/protocols/industrial/ethercat/mailbox.py +339 -0
  59. oscura/analyzers/protocols/industrial/ethercat/topology.py +166 -0
  60. oscura/analyzers/protocols/industrial/modbus/__init__.py +31 -0
  61. oscura/analyzers/protocols/industrial/modbus/analyzer.py +525 -0
  62. oscura/analyzers/protocols/industrial/modbus/crc.py +79 -0
  63. oscura/analyzers/protocols/industrial/modbus/functions.py +436 -0
  64. oscura/analyzers/protocols/industrial/opcua/__init__.py +21 -0
  65. oscura/analyzers/protocols/industrial/opcua/analyzer.py +552 -0
  66. oscura/analyzers/protocols/industrial/opcua/datatypes.py +446 -0
  67. oscura/analyzers/protocols/industrial/opcua/services.py +264 -0
  68. oscura/analyzers/protocols/industrial/profinet/__init__.py +23 -0
  69. oscura/analyzers/protocols/industrial/profinet/analyzer.py +441 -0
  70. oscura/analyzers/protocols/industrial/profinet/dcp.py +263 -0
  71. oscura/analyzers/protocols/industrial/profinet/ptcp.py +200 -0
  72. oscura/analyzers/protocols/jtag.py +180 -98
  73. oscura/analyzers/protocols/lin.py +219 -114
  74. oscura/analyzers/protocols/manchester.py +4 -4
  75. oscura/analyzers/protocols/onewire.py +253 -149
  76. oscura/analyzers/protocols/parallel_bus/__init__.py +20 -0
  77. oscura/analyzers/protocols/parallel_bus/centronics.py +92 -0
  78. oscura/analyzers/protocols/parallel_bus/gpib.py +137 -0
  79. oscura/analyzers/protocols/spi.py +192 -95
  80. oscura/analyzers/protocols/swd.py +321 -167
  81. oscura/analyzers/protocols/uart.py +267 -125
  82. oscura/analyzers/protocols/usb.py +235 -131
  83. oscura/analyzers/side_channel/power.py +17 -12
  84. oscura/analyzers/signal/__init__.py +15 -0
  85. oscura/analyzers/signal/timing_analysis.py +1086 -0
  86. oscura/analyzers/signal_integrity/__init__.py +4 -1
  87. oscura/analyzers/signal_integrity/sparams.py +2 -19
  88. oscura/analyzers/spectral/chunked.py +129 -60
  89. oscura/analyzers/spectral/chunked_fft.py +300 -94
  90. oscura/analyzers/spectral/chunked_wavelet.py +100 -80
  91. oscura/analyzers/statistical/checksum.py +376 -217
  92. oscura/analyzers/statistical/classification.py +229 -107
  93. oscura/analyzers/statistical/entropy.py +78 -53
  94. oscura/analyzers/statistics/correlation.py +407 -211
  95. oscura/analyzers/statistics/outliers.py +2 -2
  96. oscura/analyzers/statistics/streaming.py +30 -5
  97. oscura/analyzers/validation.py +216 -101
  98. oscura/analyzers/waveform/measurements.py +9 -0
  99. oscura/analyzers/waveform/measurements_with_uncertainty.py +31 -15
  100. oscura/analyzers/waveform/spectral.py +500 -228
  101. oscura/api/__init__.py +31 -5
  102. oscura/api/dsl/__init__.py +582 -0
  103. oscura/{dsl → api/dsl}/commands.py +43 -76
  104. oscura/{dsl → api/dsl}/interpreter.py +26 -51
  105. oscura/{dsl → api/dsl}/parser.py +107 -77
  106. oscura/{dsl → api/dsl}/repl.py +2 -2
  107. oscura/api/dsl.py +1 -1
  108. oscura/{integrations → api/integrations}/__init__.py +1 -1
  109. oscura/{integrations → api/integrations}/llm.py +201 -102
  110. oscura/api/operators.py +3 -3
  111. oscura/api/optimization.py +144 -30
  112. oscura/api/rest_server.py +921 -0
  113. oscura/api/server/__init__.py +17 -0
  114. oscura/api/server/dashboard.py +850 -0
  115. oscura/api/server/static/README.md +34 -0
  116. oscura/api/server/templates/base.html +181 -0
  117. oscura/api/server/templates/export.html +120 -0
  118. oscura/api/server/templates/home.html +284 -0
  119. oscura/api/server/templates/protocols.html +58 -0
  120. oscura/api/server/templates/reports.html +43 -0
  121. oscura/api/server/templates/session_detail.html +89 -0
  122. oscura/api/server/templates/sessions.html +83 -0
  123. oscura/api/server/templates/waveforms.html +73 -0
  124. oscura/automotive/__init__.py +8 -1
  125. oscura/automotive/can/__init__.py +10 -0
  126. oscura/automotive/can/checksum.py +3 -1
  127. oscura/automotive/can/dbc_generator.py +590 -0
  128. oscura/automotive/can/message_wrapper.py +121 -74
  129. oscura/automotive/can/patterns.py +98 -21
  130. oscura/automotive/can/session.py +292 -56
  131. oscura/automotive/can/state_machine.py +6 -3
  132. oscura/automotive/can/stimulus_response.py +97 -75
  133. oscura/automotive/dbc/__init__.py +10 -2
  134. oscura/automotive/dbc/generator.py +84 -56
  135. oscura/automotive/dbc/parser.py +6 -6
  136. oscura/automotive/dtc/data.json +2763 -0
  137. oscura/automotive/dtc/database.py +2 -2
  138. oscura/automotive/flexray/__init__.py +31 -0
  139. oscura/automotive/flexray/analyzer.py +504 -0
  140. oscura/automotive/flexray/crc.py +185 -0
  141. oscura/automotive/flexray/fibex.py +449 -0
  142. oscura/automotive/j1939/__init__.py +45 -8
  143. oscura/automotive/j1939/analyzer.py +605 -0
  144. oscura/automotive/j1939/spns.py +326 -0
  145. oscura/automotive/j1939/transport.py +306 -0
  146. oscura/automotive/lin/__init__.py +47 -0
  147. oscura/automotive/lin/analyzer.py +612 -0
  148. oscura/automotive/loaders/blf.py +13 -2
  149. oscura/automotive/loaders/csv_can.py +143 -72
  150. oscura/automotive/loaders/dispatcher.py +50 -2
  151. oscura/automotive/loaders/mdf.py +86 -45
  152. oscura/automotive/loaders/pcap.py +111 -61
  153. oscura/automotive/uds/__init__.py +4 -0
  154. oscura/automotive/uds/analyzer.py +725 -0
  155. oscura/automotive/uds/decoder.py +140 -58
  156. oscura/automotive/uds/models.py +7 -1
  157. oscura/automotive/visualization.py +1 -1
  158. oscura/cli/analyze.py +348 -0
  159. oscura/cli/batch.py +142 -122
  160. oscura/cli/benchmark.py +275 -0
  161. oscura/cli/characterize.py +137 -82
  162. oscura/cli/compare.py +224 -131
  163. oscura/cli/completion.py +250 -0
  164. oscura/cli/config_cmd.py +361 -0
  165. oscura/cli/decode.py +164 -87
  166. oscura/cli/export.py +286 -0
  167. oscura/cli/main.py +115 -31
  168. oscura/{onboarding → cli/onboarding}/__init__.py +3 -3
  169. oscura/{onboarding → cli/onboarding}/help.py +80 -58
  170. oscura/{onboarding → cli/onboarding}/tutorials.py +97 -72
  171. oscura/{onboarding → cli/onboarding}/wizard.py +55 -36
  172. oscura/cli/progress.py +147 -0
  173. oscura/cli/shell.py +157 -135
  174. oscura/cli/validate_cmd.py +204 -0
  175. oscura/cli/visualize.py +158 -0
  176. oscura/convenience.py +125 -79
  177. oscura/core/__init__.py +4 -2
  178. oscura/core/backend_selector.py +3 -3
  179. oscura/core/cache.py +126 -15
  180. oscura/core/cancellation.py +1 -1
  181. oscura/{config → core/config}/__init__.py +20 -11
  182. oscura/{config → core/config}/defaults.py +1 -1
  183. oscura/{config → core/config}/loader.py +7 -5
  184. oscura/{config → core/config}/memory.py +5 -5
  185. oscura/{config → core/config}/migration.py +1 -1
  186. oscura/{config → core/config}/pipeline.py +99 -23
  187. oscura/{config → core/config}/preferences.py +1 -1
  188. oscura/{config → core/config}/protocol.py +3 -3
  189. oscura/{config → core/config}/schema.py +426 -272
  190. oscura/{config → core/config}/settings.py +1 -1
  191. oscura/{config → core/config}/thresholds.py +195 -153
  192. oscura/core/correlation.py +5 -6
  193. oscura/core/cross_domain.py +0 -2
  194. oscura/core/debug.py +9 -5
  195. oscura/{extensibility → core/extensibility}/docs.py +158 -70
  196. oscura/{extensibility → core/extensibility}/extensions.py +160 -76
  197. oscura/{extensibility → core/extensibility}/logging.py +1 -1
  198. oscura/{extensibility → core/extensibility}/measurements.py +1 -1
  199. oscura/{extensibility → core/extensibility}/plugins.py +1 -1
  200. oscura/{extensibility → core/extensibility}/templates.py +73 -3
  201. oscura/{extensibility → core/extensibility}/validation.py +1 -1
  202. oscura/core/gpu_backend.py +11 -7
  203. oscura/core/log_query.py +101 -11
  204. oscura/core/logging.py +126 -54
  205. oscura/core/logging_advanced.py +5 -5
  206. oscura/core/memory_limits.py +108 -70
  207. oscura/core/memory_monitor.py +2 -2
  208. oscura/core/memory_progress.py +7 -7
  209. oscura/core/memory_warnings.py +1 -1
  210. oscura/core/numba_backend.py +13 -13
  211. oscura/{plugins → core/plugins}/__init__.py +9 -9
  212. oscura/{plugins → core/plugins}/base.py +7 -7
  213. oscura/{plugins → core/plugins}/cli.py +3 -3
  214. oscura/{plugins → core/plugins}/discovery.py +186 -106
  215. oscura/{plugins → core/plugins}/lifecycle.py +1 -1
  216. oscura/{plugins → core/plugins}/manager.py +7 -7
  217. oscura/{plugins → core/plugins}/registry.py +3 -3
  218. oscura/{plugins → core/plugins}/versioning.py +1 -1
  219. oscura/core/progress.py +16 -1
  220. oscura/core/provenance.py +8 -2
  221. oscura/{schemas → core/schemas}/__init__.py +2 -2
  222. oscura/core/schemas/bus_configuration.json +322 -0
  223. oscura/core/schemas/device_mapping.json +182 -0
  224. oscura/core/schemas/packet_format.json +418 -0
  225. oscura/core/schemas/protocol_definition.json +363 -0
  226. oscura/core/types.py +4 -0
  227. oscura/core/uncertainty.py +3 -3
  228. oscura/correlation/__init__.py +52 -0
  229. oscura/correlation/multi_protocol.py +811 -0
  230. oscura/discovery/auto_decoder.py +117 -35
  231. oscura/discovery/comparison.py +191 -86
  232. oscura/discovery/quality_validator.py +155 -68
  233. oscura/discovery/signal_detector.py +196 -79
  234. oscura/export/__init__.py +18 -20
  235. oscura/export/kaitai_struct.py +513 -0
  236. oscura/export/scapy_layer.py +801 -0
  237. oscura/export/wireshark/README.md +15 -15
  238. oscura/export/wireshark/generator.py +1 -1
  239. oscura/export/wireshark/templates/dissector.lua.j2 +2 -2
  240. oscura/export/wireshark_dissector.py +746 -0
  241. oscura/guidance/wizard.py +207 -111
  242. oscura/hardware/__init__.py +19 -0
  243. oscura/{acquisition → hardware/acquisition}/__init__.py +4 -4
  244. oscura/{acquisition → hardware/acquisition}/file.py +2 -2
  245. oscura/{acquisition → hardware/acquisition}/hardware.py +7 -7
  246. oscura/{acquisition → hardware/acquisition}/saleae.py +15 -12
  247. oscura/{acquisition → hardware/acquisition}/socketcan.py +1 -1
  248. oscura/{acquisition → hardware/acquisition}/streaming.py +2 -2
  249. oscura/{acquisition → hardware/acquisition}/synthetic.py +3 -3
  250. oscura/{acquisition → hardware/acquisition}/visa.py +33 -11
  251. oscura/hardware/firmware/__init__.py +29 -0
  252. oscura/hardware/firmware/pattern_recognition.py +874 -0
  253. oscura/hardware/hal_detector.py +736 -0
  254. oscura/hardware/security/__init__.py +37 -0
  255. oscura/hardware/security/side_channel_detector.py +1126 -0
  256. oscura/inference/__init__.py +4 -0
  257. oscura/inference/active_learning/README.md +7 -7
  258. oscura/inference/active_learning/observation_table.py +4 -1
  259. oscura/inference/alignment.py +216 -123
  260. oscura/inference/bayesian.py +113 -33
  261. oscura/inference/crc_reverse.py +101 -55
  262. oscura/inference/logic.py +6 -2
  263. oscura/inference/message_format.py +342 -183
  264. oscura/inference/protocol.py +95 -44
  265. oscura/inference/protocol_dsl.py +180 -82
  266. oscura/inference/signal_intelligence.py +1439 -706
  267. oscura/inference/spectral.py +99 -57
  268. oscura/inference/state_machine.py +810 -158
  269. oscura/inference/stream.py +270 -110
  270. oscura/iot/__init__.py +34 -0
  271. oscura/iot/coap/__init__.py +32 -0
  272. oscura/iot/coap/analyzer.py +668 -0
  273. oscura/iot/coap/options.py +212 -0
  274. oscura/iot/lorawan/__init__.py +21 -0
  275. oscura/iot/lorawan/crypto.py +206 -0
  276. oscura/iot/lorawan/decoder.py +801 -0
  277. oscura/iot/lorawan/mac_commands.py +341 -0
  278. oscura/iot/mqtt/__init__.py +27 -0
  279. oscura/iot/mqtt/analyzer.py +999 -0
  280. oscura/iot/mqtt/properties.py +315 -0
  281. oscura/iot/zigbee/__init__.py +31 -0
  282. oscura/iot/zigbee/analyzer.py +615 -0
  283. oscura/iot/zigbee/security.py +153 -0
  284. oscura/iot/zigbee/zcl.py +349 -0
  285. oscura/jupyter/display.py +125 -45
  286. oscura/{exploratory → jupyter/exploratory}/__init__.py +8 -8
  287. oscura/{exploratory → jupyter/exploratory}/error_recovery.py +298 -141
  288. oscura/jupyter/exploratory/fuzzy.py +746 -0
  289. oscura/{exploratory → jupyter/exploratory}/fuzzy_advanced.py +258 -100
  290. oscura/{exploratory → jupyter/exploratory}/legacy.py +464 -242
  291. oscura/{exploratory → jupyter/exploratory}/parse.py +167 -145
  292. oscura/{exploratory → jupyter/exploratory}/recovery.py +119 -87
  293. oscura/jupyter/exploratory/sync.py +612 -0
  294. oscura/{exploratory → jupyter/exploratory}/unknown.py +299 -176
  295. oscura/jupyter/magic.py +4 -4
  296. oscura/{ui → jupyter/ui}/__init__.py +2 -2
  297. oscura/{ui → jupyter/ui}/formatters.py +3 -3
  298. oscura/{ui → jupyter/ui}/progressive_display.py +153 -82
  299. oscura/loaders/__init__.py +171 -63
  300. oscura/loaders/binary.py +88 -1
  301. oscura/loaders/chipwhisperer.py +153 -137
  302. oscura/loaders/configurable.py +208 -86
  303. oscura/loaders/csv_loader.py +458 -215
  304. oscura/loaders/hdf5_loader.py +278 -119
  305. oscura/loaders/lazy.py +87 -54
  306. oscura/loaders/mmap_loader.py +1 -1
  307. oscura/loaders/numpy_loader.py +253 -116
  308. oscura/loaders/pcap.py +226 -151
  309. oscura/loaders/rigol.py +110 -49
  310. oscura/loaders/sigrok.py +201 -78
  311. oscura/loaders/tdms.py +81 -58
  312. oscura/loaders/tektronix.py +291 -174
  313. oscura/loaders/touchstone.py +182 -87
  314. oscura/loaders/vcd.py +215 -117
  315. oscura/loaders/wav.py +155 -68
  316. oscura/reporting/__init__.py +9 -7
  317. oscura/reporting/analyze.py +352 -146
  318. oscura/reporting/argument_preparer.py +69 -14
  319. oscura/reporting/auto_report.py +97 -61
  320. oscura/reporting/batch.py +131 -58
  321. oscura/reporting/chart_selection.py +57 -45
  322. oscura/reporting/comparison.py +63 -17
  323. oscura/reporting/content/executive.py +76 -24
  324. oscura/reporting/core_formats/multi_format.py +11 -8
  325. oscura/reporting/engine.py +312 -158
  326. oscura/reporting/enhanced_reports.py +949 -0
  327. oscura/reporting/export.py +86 -43
  328. oscura/reporting/formatting/numbers.py +69 -42
  329. oscura/reporting/html.py +139 -58
  330. oscura/reporting/index.py +137 -65
  331. oscura/reporting/output.py +158 -67
  332. oscura/reporting/pdf.py +67 -102
  333. oscura/reporting/plots.py +191 -112
  334. oscura/reporting/sections.py +88 -47
  335. oscura/reporting/standards.py +104 -61
  336. oscura/reporting/summary_generator.py +75 -55
  337. oscura/reporting/tables.py +138 -54
  338. oscura/reporting/templates/enhanced/protocol_re.html +525 -0
  339. oscura/reporting/templates/index.md +13 -13
  340. oscura/sessions/__init__.py +14 -23
  341. oscura/sessions/base.py +3 -3
  342. oscura/sessions/blackbox.py +106 -10
  343. oscura/sessions/generic.py +2 -2
  344. oscura/sessions/legacy.py +783 -0
  345. oscura/side_channel/__init__.py +63 -0
  346. oscura/side_channel/dpa.py +1025 -0
  347. oscura/utils/__init__.py +15 -1
  348. oscura/utils/autodetect.py +1 -5
  349. oscura/utils/bitwise.py +118 -0
  350. oscura/{builders → utils/builders}/__init__.py +1 -1
  351. oscura/{comparison → utils/comparison}/__init__.py +6 -6
  352. oscura/{comparison → utils/comparison}/compare.py +202 -101
  353. oscura/{comparison → utils/comparison}/golden.py +83 -63
  354. oscura/{comparison → utils/comparison}/limits.py +313 -89
  355. oscura/{comparison → utils/comparison}/mask.py +151 -45
  356. oscura/{comparison → utils/comparison}/trace_diff.py +1 -1
  357. oscura/{comparison → utils/comparison}/visualization.py +147 -89
  358. oscura/{component → utils/component}/__init__.py +3 -3
  359. oscura/{component → utils/component}/impedance.py +122 -58
  360. oscura/{component → utils/component}/reactive.py +165 -168
  361. oscura/{component → utils/component}/transmission_line.py +3 -3
  362. oscura/{filtering → utils/filtering}/__init__.py +6 -6
  363. oscura/{filtering → utils/filtering}/base.py +1 -1
  364. oscura/{filtering → utils/filtering}/convenience.py +2 -2
  365. oscura/{filtering → utils/filtering}/design.py +169 -93
  366. oscura/{filtering → utils/filtering}/filters.py +2 -2
  367. oscura/{filtering → utils/filtering}/introspection.py +2 -2
  368. oscura/utils/geometry.py +31 -0
  369. oscura/utils/imports.py +184 -0
  370. oscura/utils/lazy.py +1 -1
  371. oscura/{math → utils/math}/__init__.py +2 -2
  372. oscura/{math → utils/math}/arithmetic.py +114 -48
  373. oscura/{math → utils/math}/interpolation.py +139 -106
  374. oscura/utils/memory.py +129 -66
  375. oscura/utils/memory_advanced.py +92 -9
  376. oscura/utils/memory_extensions.py +10 -8
  377. oscura/{optimization → utils/optimization}/__init__.py +1 -1
  378. oscura/{optimization → utils/optimization}/search.py +2 -2
  379. oscura/utils/performance/__init__.py +58 -0
  380. oscura/utils/performance/caching.py +889 -0
  381. oscura/utils/performance/lsh_clustering.py +333 -0
  382. oscura/utils/performance/memory_optimizer.py +699 -0
  383. oscura/utils/performance/optimizations.py +675 -0
  384. oscura/utils/performance/parallel.py +654 -0
  385. oscura/utils/performance/profiling.py +661 -0
  386. oscura/{pipeline → utils/pipeline}/base.py +1 -1
  387. oscura/{pipeline → utils/pipeline}/composition.py +11 -3
  388. oscura/{pipeline → utils/pipeline}/parallel.py +3 -2
  389. oscura/{pipeline → utils/pipeline}/pipeline.py +1 -1
  390. oscura/{pipeline → utils/pipeline}/reverse_engineering.py +412 -221
  391. oscura/{search → utils/search}/__init__.py +3 -3
  392. oscura/{search → utils/search}/anomaly.py +188 -58
  393. oscura/utils/search/context.py +294 -0
  394. oscura/{search → utils/search}/pattern.py +138 -10
  395. oscura/utils/serial.py +51 -0
  396. oscura/utils/storage/__init__.py +61 -0
  397. oscura/utils/storage/database.py +1166 -0
  398. oscura/{streaming → utils/streaming}/chunked.py +302 -143
  399. oscura/{streaming → utils/streaming}/progressive.py +1 -1
  400. oscura/{streaming → utils/streaming}/realtime.py +3 -2
  401. oscura/{triggering → utils/triggering}/__init__.py +6 -6
  402. oscura/{triggering → utils/triggering}/base.py +6 -6
  403. oscura/{triggering → utils/triggering}/edge.py +2 -2
  404. oscura/{triggering → utils/triggering}/pattern.py +2 -2
  405. oscura/{triggering → utils/triggering}/pulse.py +115 -74
  406. oscura/{triggering → utils/triggering}/window.py +2 -2
  407. oscura/utils/validation.py +32 -0
  408. oscura/validation/__init__.py +121 -0
  409. oscura/{compliance → validation/compliance}/__init__.py +5 -5
  410. oscura/{compliance → validation/compliance}/advanced.py +5 -5
  411. oscura/{compliance → validation/compliance}/masks.py +1 -1
  412. oscura/{compliance → validation/compliance}/reporting.py +127 -53
  413. oscura/{compliance → validation/compliance}/testing.py +114 -52
  414. oscura/validation/compliance_tests.py +915 -0
  415. oscura/validation/fuzzer.py +990 -0
  416. oscura/validation/grammar_tests.py +596 -0
  417. oscura/validation/grammar_validator.py +904 -0
  418. oscura/validation/hil_testing.py +977 -0
  419. oscura/{quality → validation/quality}/__init__.py +4 -4
  420. oscura/{quality → validation/quality}/ensemble.py +251 -171
  421. oscura/{quality → validation/quality}/explainer.py +3 -3
  422. oscura/{quality → validation/quality}/scoring.py +1 -1
  423. oscura/{quality → validation/quality}/warnings.py +4 -4
  424. oscura/validation/regression_suite.py +808 -0
  425. oscura/validation/replay.py +788 -0
  426. oscura/{testing → validation/testing}/__init__.py +2 -2
  427. oscura/{testing → validation/testing}/synthetic.py +5 -5
  428. oscura/visualization/__init__.py +9 -0
  429. oscura/visualization/accessibility.py +1 -1
  430. oscura/visualization/annotations.py +64 -67
  431. oscura/visualization/colors.py +7 -7
  432. oscura/visualization/digital.py +180 -81
  433. oscura/visualization/eye.py +236 -85
  434. oscura/visualization/interactive.py +320 -143
  435. oscura/visualization/jitter.py +587 -247
  436. oscura/visualization/layout.py +169 -134
  437. oscura/visualization/optimization.py +103 -52
  438. oscura/visualization/palettes.py +1 -1
  439. oscura/visualization/power.py +427 -211
  440. oscura/visualization/power_extended.py +626 -297
  441. oscura/visualization/presets.py +2 -0
  442. oscura/visualization/protocols.py +495 -181
  443. oscura/visualization/render.py +79 -63
  444. oscura/visualization/reverse_engineering.py +171 -124
  445. oscura/visualization/signal_integrity.py +460 -279
  446. oscura/visualization/specialized.py +190 -100
  447. oscura/visualization/spectral.py +670 -255
  448. oscura/visualization/thumbnails.py +166 -137
  449. oscura/visualization/waveform.py +150 -63
  450. oscura/workflows/__init__.py +3 -0
  451. oscura/{batch → workflows/batch}/__init__.py +5 -5
  452. oscura/{batch → workflows/batch}/advanced.py +150 -75
  453. oscura/workflows/batch/aggregate.py +531 -0
  454. oscura/workflows/batch/analyze.py +236 -0
  455. oscura/{batch → workflows/batch}/logging.py +2 -2
  456. oscura/{batch → workflows/batch}/metrics.py +1 -1
  457. oscura/workflows/complete_re.py +1144 -0
  458. oscura/workflows/compliance.py +44 -54
  459. oscura/workflows/digital.py +197 -51
  460. oscura/workflows/legacy/__init__.py +12 -0
  461. oscura/{workflow → workflows/legacy}/dag.py +4 -1
  462. oscura/workflows/multi_trace.py +9 -9
  463. oscura/workflows/power.py +42 -62
  464. oscura/workflows/protocol.py +82 -49
  465. oscura/workflows/reverse_engineering.py +351 -150
  466. oscura/workflows/signal_integrity.py +157 -82
  467. oscura-0.6.0.dist-info/METADATA +643 -0
  468. oscura-0.6.0.dist-info/RECORD +590 -0
  469. oscura/analyzers/digital/ic_database.py +0 -498
  470. oscura/analyzers/digital/timing_paths.py +0 -339
  471. oscura/analyzers/digital/vintage.py +0 -377
  472. oscura/analyzers/digital/vintage_result.py +0 -148
  473. oscura/analyzers/protocols/parallel_bus.py +0 -449
  474. oscura/batch/aggregate.py +0 -300
  475. oscura/batch/analyze.py +0 -139
  476. oscura/dsl/__init__.py +0 -73
  477. oscura/exceptions.py +0 -59
  478. oscura/exploratory/fuzzy.py +0 -513
  479. oscura/exploratory/sync.py +0 -384
  480. oscura/export/wavedrom.py +0 -430
  481. oscura/exporters/__init__.py +0 -94
  482. oscura/exporters/csv.py +0 -303
  483. oscura/exporters/exporters.py +0 -44
  484. oscura/exporters/hdf5.py +0 -217
  485. oscura/exporters/html_export.py +0 -701
  486. oscura/exporters/json_export.py +0 -338
  487. oscura/exporters/markdown_export.py +0 -367
  488. oscura/exporters/matlab_export.py +0 -354
  489. oscura/exporters/npz_export.py +0 -219
  490. oscura/exporters/spice_export.py +0 -210
  491. oscura/exporters/vintage_logic_csv.py +0 -247
  492. oscura/reporting/vintage_logic_report.py +0 -523
  493. oscura/search/context.py +0 -149
  494. oscura/session/__init__.py +0 -34
  495. oscura/session/annotations.py +0 -289
  496. oscura/session/history.py +0 -313
  497. oscura/session/session.py +0 -520
  498. oscura/visualization/digital_advanced.py +0 -718
  499. oscura/visualization/figure_manager.py +0 -156
  500. oscura/workflow/__init__.py +0 -13
  501. oscura-0.5.0.dist-info/METADATA +0 -407
  502. oscura-0.5.0.dist-info/RECORD +0 -486
  503. /oscura/core/{config.py → config/legacy.py} +0 -0
  504. /oscura/{extensibility → core/extensibility}/__init__.py +0 -0
  505. /oscura/{extensibility → core/extensibility}/registry.py +0 -0
  506. /oscura/{plugins → core/plugins}/isolation.py +0 -0
  507. /oscura/{builders → utils/builders}/signal_builder.py +0 -0
  508. /oscura/{optimization → utils/optimization}/parallel.py +0 -0
  509. /oscura/{pipeline → utils/pipeline}/__init__.py +0 -0
  510. /oscura/{streaming → utils/streaming}/__init__.py +0 -0
  511. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/WHEEL +0 -0
  512. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/entry_points.txt +0 -0
  513. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -4,7 +4,7 @@ Provides digital pattern matching for multi-channel logic signals.
4
4
  Supports exact matches, wildcards, and edge conditions.
5
5
 
6
6
  Example:
7
- >>> from oscura.triggering.pattern import PatternTrigger, find_pattern
7
+ >>> from oscura.utils.triggering.pattern import PatternTrigger, find_pattern
8
8
  >>> # Find pattern 1010 on 4 channels
9
9
  >>> trigger = PatternTrigger(pattern=[1, 0, 1, 0])
10
10
  >>> events = trigger.find_events(trace)
@@ -18,7 +18,7 @@ import numpy as np
18
18
 
19
19
  from oscura.core.exceptions import AnalysisError
20
20
  from oscura.core.types import DigitalTrace, WaveformTrace
21
- from oscura.triggering.base import (
21
+ from oscura.utils.triggering.base import (
22
22
  Trigger,
23
23
  TriggerEvent,
24
24
  TriggerType,
@@ -4,7 +4,7 @@ Provides pulse width triggering, glitch detection, and runt pulse
4
4
  detection for signal integrity analysis.
5
5
 
6
6
  Example:
7
- >>> from oscura.triggering.pulse import PulseWidthTrigger, find_glitches
7
+ >>> from oscura.utils.triggering.pulse import PulseWidthTrigger, find_glitches
8
8
  >>> # Find pulses between 100ns and 200ns
9
9
  >>> trigger = PulseWidthTrigger(level=1.5, min_width=100e-9, max_width=200e-9)
10
10
  >>> events = trigger.find_events(trace)
@@ -18,10 +18,11 @@ from dataclasses import dataclass
18
18
  from typing import Literal
19
19
 
20
20
  import numpy as np
21
+ from numpy.typing import NDArray
21
22
 
22
23
  from oscura.core.exceptions import AnalysisError
23
24
  from oscura.core.types import DigitalTrace, WaveformTrace
24
- from oscura.triggering.base import (
25
+ from oscura.utils.triggering.base import (
25
26
  Trigger,
26
27
  TriggerEvent,
27
28
  TriggerType,
@@ -307,6 +308,101 @@ class RuntTrigger(Trigger):
307
308
  self.high_threshold = high_threshold
308
309
  self.polarity = polarity
309
310
 
311
+ def _get_zone(self, value: float) -> int:
312
+ """Get zone for a signal value.
313
+
314
+ Args:
315
+ value: Signal value
316
+
317
+ Returns:
318
+ Zone index (0=low, 1=middle, 2=high)
319
+ """
320
+ if value < self.low_threshold:
321
+ return 0
322
+ if value > self.high_threshold:
323
+ return 2
324
+ return 1
325
+
326
+ def _find_positive_runt(
327
+ self,
328
+ zones: NDArray[np.int_],
329
+ data: NDArray[np.float64],
330
+ start_idx: int,
331
+ sample_period: float,
332
+ ) -> tuple[TriggerEvent | None, int]:
333
+ """Find positive runt pulse starting at index.
334
+
335
+ Args:
336
+ zones: Zone classification array
337
+ data: Signal data
338
+ start_idx: Starting index
339
+ sample_period: Sample period
340
+
341
+ Returns:
342
+ Tuple of (event or None, next index)
343
+ """
344
+ j = start_idx + 1
345
+ while j < len(zones) and zones[j] == 1:
346
+ j += 1
347
+
348
+ if j < len(zones) and zones[j] == 0:
349
+ peak = float(np.max(data[start_idx : j + 1]))
350
+ event = TriggerEvent(
351
+ timestamp=start_idx * sample_period,
352
+ sample_index=start_idx,
353
+ event_type=TriggerType.RUNT,
354
+ level=peak,
355
+ duration=(j - start_idx) * sample_period,
356
+ data={
357
+ "polarity": "positive",
358
+ "expected_high": self.high_threshold,
359
+ "actual_peak": peak,
360
+ },
361
+ )
362
+ return event, j
363
+
364
+ return None, j
365
+
366
+ def _find_negative_runt(
367
+ self,
368
+ zones: NDArray[np.int_],
369
+ data: NDArray[np.float64],
370
+ start_idx: int,
371
+ sample_period: float,
372
+ ) -> tuple[TriggerEvent | None, int]:
373
+ """Find negative runt pulse starting at index.
374
+
375
+ Args:
376
+ zones: Zone classification array
377
+ data: Signal data
378
+ start_idx: Starting index
379
+ sample_period: Sample period
380
+
381
+ Returns:
382
+ Tuple of (event or None, next index)
383
+ """
384
+ j = start_idx + 1
385
+ while j < len(zones) and zones[j] == 1:
386
+ j += 1
387
+
388
+ if j < len(zones) and zones[j] == 2:
389
+ trough = float(np.min(data[start_idx : j + 1]))
390
+ event = TriggerEvent(
391
+ timestamp=start_idx * sample_period,
392
+ sample_index=start_idx,
393
+ event_type=TriggerType.RUNT,
394
+ level=trough,
395
+ duration=(j - start_idx) * sample_period,
396
+ data={
397
+ "polarity": "negative",
398
+ "expected_low": self.low_threshold,
399
+ "actual_trough": trough,
400
+ },
401
+ )
402
+ return event, j
403
+
404
+ return None, j
405
+
310
406
  def find_events(
311
407
  self,
312
408
  trace: WaveformTrace | DigitalTrace,
@@ -320,88 +416,33 @@ class RuntTrigger(Trigger):
320
416
  List of trigger events for each runt pulse.
321
417
  """
322
418
  if isinstance(trace, DigitalTrace):
323
- # Digital traces don't have runts
324
419
  return []
325
420
 
326
421
  data = trace.data
327
422
  sample_period = trace.metadata.time_base
328
423
  events: list[TriggerEvent] = []
329
424
 
330
- # Track signal zones
331
- # Zone 0: below low_threshold
332
- # Zone 1: between thresholds
333
- # Zone 2: above high_threshold
334
- def get_zone(value: float) -> int:
335
- if value < self.low_threshold:
336
- return 0
337
- elif value > self.high_threshold:
338
- return 2
339
- else:
340
- return 1
341
-
342
- zones = np.array([get_zone(v) for v in data])
343
-
344
- # Find runt pulses: transitions that enter zone 1 but don't reach the other side
425
+ zones = np.array([self._get_zone(v) for v in data])
426
+
345
427
  i = 0
346
428
  while i < len(zones) - 1:
347
429
  curr_zone = zones[i]
348
430
 
349
- if curr_zone == 0:
350
- # Starting low - look for positive runt
351
- if self.polarity in ("positive", "either"):
352
- # Find transition to zone 1
353
- if zones[i + 1] == 1:
354
- start_idx = i
355
- # Track through zone 1
356
- j = i + 1
357
- while j < len(zones) and zones[j] == 1:
358
- j += 1
359
- if j < len(zones) and zones[j] == 0:
360
- # Returned to low without reaching high - RUNT
361
- peak = float(np.max(data[start_idx : j + 1]))
362
- events.append(
363
- TriggerEvent(
364
- timestamp=start_idx * sample_period,
365
- sample_index=start_idx,
366
- event_type=TriggerType.RUNT,
367
- level=peak,
368
- duration=(j - start_idx) * sample_period,
369
- data={
370
- "polarity": "positive",
371
- "expected_high": self.high_threshold,
372
- "actual_peak": peak,
373
- },
374
- )
375
- )
376
- i = j
377
- continue
378
-
379
- elif curr_zone == 2:
380
- # Starting high - look for negative runt
381
- if self.polarity in ("negative", "either") and zones[i + 1] == 1:
382
- start_idx = i
383
- j = i + 1
384
- while j < len(zones) and zones[j] == 1:
385
- j += 1
386
- if j < len(zones) and zones[j] == 2:
387
- # Returned to high without reaching low - RUNT
388
- trough = float(np.min(data[start_idx : j + 1]))
389
- events.append(
390
- TriggerEvent(
391
- timestamp=start_idx * sample_period,
392
- sample_index=start_idx,
393
- event_type=TriggerType.RUNT,
394
- level=trough,
395
- duration=(j - start_idx) * sample_period,
396
- data={
397
- "polarity": "negative",
398
- "expected_low": self.low_threshold,
399
- "actual_trough": trough,
400
- },
401
- )
402
- )
403
- i = j
404
- continue
431
+ # Check for positive runt (starting from zone 0)
432
+ if curr_zone == 0 and self.polarity in ("positive", "either") and zones[i + 1] == 1:
433
+ event, next_i = self._find_positive_runt(zones, data, i, sample_period)
434
+ if event:
435
+ events.append(event)
436
+ i = next_i
437
+ continue
438
+
439
+ # Check for negative runt (starting from zone 2)
440
+ if curr_zone == 2 and self.polarity in ("negative", "either") and zones[i + 1] == 1:
441
+ event, next_i = self._find_negative_runt(zones, data, i, sample_period)
442
+ if event:
443
+ events.append(event)
444
+ i = next_i
445
+ continue
405
446
 
406
447
  i += 1
407
448
 
@@ -4,7 +4,7 @@ Provides window triggering (signal inside/outside voltage window) and
4
4
  zone triggering (signal enters/exits defined zones) for limit testing.
5
5
 
6
6
  Example:
7
- >>> from oscura.triggering.window import WindowTrigger, find_window_violations
7
+ >>> from oscura.utils.triggering.window import WindowTrigger, find_window_violations
8
8
  >>> # Trigger when signal exits 0-3.3V window
9
9
  >>> trigger = WindowTrigger(low_threshold=0, high_threshold=3.3, trigger_on="exit")
10
10
  >>> violations = trigger.find_events(trace)
@@ -18,7 +18,7 @@ from typing import TYPE_CHECKING, Literal
18
18
  import numpy as np
19
19
 
20
20
  from oscura.core.exceptions import AnalysisError
21
- from oscura.triggering.base import (
21
+ from oscura.utils.triggering.base import (
22
22
  Trigger,
23
23
  TriggerEvent,
24
24
  TriggerType,
@@ -0,0 +1,32 @@
1
+ """Validation utility functions.
2
+
3
+ This module provides validation helpers used across export and other modules.
4
+ """
5
+
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from oscura.workflows.reverse_engineering import ProtocolSpec
10
+
11
+
12
+ def validate_protocol_spec(spec: "ProtocolSpec") -> None:
13
+ """Validate protocol specification.
14
+
15
+ Ensures protocol specification has required fields and is well-formed.
16
+
17
+ Args:
18
+ spec: Protocol specification to validate
19
+
20
+ Raises:
21
+ ValueError: If spec is invalid (missing name or fields)
22
+
23
+ Example:
24
+ >>> from oscura.analyzers.protocols.base import ProtocolSpec
25
+ >>> spec = ProtocolSpec(name="MyProtocol", fields=[...])
26
+ >>> validate_protocol_spec(spec) # No error if valid
27
+ """
28
+ if not spec.name:
29
+ raise ValueError("Protocol name is required")
30
+
31
+ if not spec.fields:
32
+ raise ValueError("Protocol must have at least one field")
@@ -0,0 +1,121 @@
1
+ """Validation and test generation for protocol specifications.
2
+
3
+ This module provides tools for generating test vectors, validating protocol
4
+ implementations, fuzzing protocol parsers, and replaying messages to verify
5
+ reverse-engineered protocols.
6
+
7
+ Example:
8
+ >>> from oscura.validation import GrammarTestGenerator, TestGenerationConfig
9
+ >>> from oscura.sessions import ProtocolSpec
10
+ >>>
11
+ >>> config = TestGenerationConfig(strategy="coverage", num_tests=100)
12
+ >>> generator = GrammarTestGenerator(config)
13
+ >>> tests = generator.generate_tests(protocol_spec)
14
+ >>> print(f"Generated {len(tests.valid_messages)} valid messages")
15
+ >>>
16
+ >>> # Replay validation
17
+ >>> from oscura.validation import ReplayConfig, ReplayValidator
18
+ >>> replay_config = ReplayConfig(interface="serial", port="/dev/ttyUSB0")
19
+ >>> validator = ReplayValidator(replay_config)
20
+ >>> result = validator.validate_protocol(protocol_spec, test_messages)
21
+ >>>
22
+ >>> # Fuzzing
23
+ >>> from oscura.validation import ProtocolFuzzer, FuzzingConfig
24
+ >>> fuzzer_config = FuzzingConfig(strategy="coverage_guided", max_iterations=1000)
25
+ >>> fuzzer = ProtocolFuzzer(fuzzer_config)
26
+ >>> report = fuzzer.fuzz_protocol(protocol_spec, seed_corpus)
27
+ >>> print(f"Found {report.total_crashes} crashes")
28
+
29
+ Modules:
30
+ grammar_tests: Grammar-based test vector generation and fuzzing
31
+ replay: Protocol replay validation framework
32
+ fuzzer: Advanced protocol fuzzing with coverage-guided mutation
33
+ """
34
+
35
+ from oscura.validation.compliance_tests import (
36
+ ComplianceConfig,
37
+ ComplianceTestGenerator,
38
+ ComplianceTestSuite,
39
+ StandardType,
40
+ TestCase,
41
+ TestType,
42
+ )
43
+ from oscura.validation.fuzzer import (
44
+ FuzzingConfig,
45
+ FuzzingReport,
46
+ FuzzingResult,
47
+ FuzzingStrategy,
48
+ MutationOperator,
49
+ ProtocolFuzzer,
50
+ TestResult,
51
+ )
52
+ from oscura.validation.grammar_tests import (
53
+ GeneratedTests,
54
+ GrammarTestGenerator,
55
+ TestGenerationConfig,
56
+ )
57
+ from oscura.validation.grammar_validator import (
58
+ ErrorSeverity,
59
+ ErrorType,
60
+ ProtocolGrammarValidator,
61
+ ValidationError,
62
+ ValidationReport,
63
+ )
64
+ from oscura.validation.hil_testing import (
65
+ HILConfig,
66
+ HILTester,
67
+ HILTestReport,
68
+ HILTestResult,
69
+ InterfaceType,
70
+ TestStatus,
71
+ )
72
+ from oscura.validation.regression_suite import (
73
+ ComparisonMode,
74
+ RegressionReport,
75
+ RegressionTestResult,
76
+ RegressionTestSuite,
77
+ )
78
+ from oscura.validation.replay import (
79
+ ProtocolSpec,
80
+ ReplayConfig,
81
+ ReplayValidator,
82
+ ValidationResult,
83
+ )
84
+
85
+ __all__ = [
86
+ "ComparisonMode",
87
+ "ComplianceConfig",
88
+ "ComplianceTestGenerator",
89
+ "ComplianceTestSuite",
90
+ "ErrorSeverity",
91
+ "ErrorType",
92
+ "FuzzingConfig",
93
+ "FuzzingReport",
94
+ "FuzzingResult",
95
+ "FuzzingStrategy",
96
+ "GeneratedTests",
97
+ "GrammarTestGenerator",
98
+ "HILConfig",
99
+ "HILTestReport",
100
+ "HILTestResult",
101
+ "HILTester",
102
+ "InterfaceType",
103
+ "MutationOperator",
104
+ "ProtocolFuzzer",
105
+ "ProtocolGrammarValidator",
106
+ "ProtocolSpec",
107
+ "RegressionReport",
108
+ "RegressionTestResult",
109
+ "RegressionTestSuite",
110
+ "ReplayConfig",
111
+ "ReplayValidator",
112
+ "StandardType",
113
+ "TestCase",
114
+ "TestGenerationConfig",
115
+ "TestResult",
116
+ "TestStatus",
117
+ "TestType",
118
+ "ValidationError",
119
+ "ValidationReport",
120
+ "ValidationResult",
121
+ ]
@@ -7,7 +7,7 @@ and MIL-STD standards.
7
7
 
8
8
  Example:
9
9
  >>> import oscura as osc
10
- >>> from oscura.compliance import load_limit_mask, check_compliance, generate_compliance_report
10
+ >>> from oscura.validation.compliance import load_limit_mask, check_compliance, generate_compliance_report
11
11
  >>>
12
12
  >>> trace = osc.load('emissions.wfm')
13
13
  >>> mask = load_limit_mask('FCC_Part15_ClassB')
@@ -15,7 +15,7 @@ Example:
15
15
  >>> generate_compliance_report(result, 'compliance_report.html')
16
16
  """
17
17
 
18
- from oscura.compliance.advanced import (
18
+ from oscura.validation.compliance.advanced import (
19
19
  ComplianceTestConfig,
20
20
  ComplianceTestRunner,
21
21
  ComplianceTestSuite,
@@ -26,17 +26,17 @@ from oscura.compliance.advanced import (
26
26
  QuasiPeakDetector,
27
27
  interpolate_limit,
28
28
  )
29
- from oscura.compliance.masks import (
29
+ from oscura.validation.compliance.masks import (
30
30
  AVAILABLE_MASKS,
31
31
  LimitMask,
32
32
  create_custom_mask,
33
33
  load_limit_mask,
34
34
  )
35
- from oscura.compliance.reporting import (
35
+ from oscura.validation.compliance.reporting import (
36
36
  ComplianceReportFormat,
37
37
  generate_compliance_report,
38
38
  )
39
- from oscura.compliance.testing import (
39
+ from oscura.validation.compliance.testing import (
40
40
  ComplianceResult,
41
41
  ComplianceViolation,
42
42
  DetectorType,
@@ -22,7 +22,7 @@ import numpy as np
22
22
  if TYPE_CHECKING:
23
23
  from numpy.typing import NDArray
24
24
 
25
- from oscura.compliance.masks import LimitMask
25
+ from oscura.validation.compliance.masks import LimitMask
26
26
 
27
27
  logger = logging.getLogger(__name__)
28
28
 
@@ -63,7 +63,7 @@ class LimitInterpolator:
63
63
  defined frequency points.
64
64
 
65
65
  Example:
66
- >>> from oscura.compliance import load_limit_mask
66
+ >>> from oscura.validation.compliance import load_limit_mask
67
67
  >>> mask = load_limit_mask('FCC_Part15_ClassB')
68
68
  >>> interp = LimitInterpolator(mask)
69
69
  >>> limit_at_100mhz = interp.interpolate(100e6)
@@ -339,7 +339,7 @@ class ComplianceTestRunner:
339
339
  Returns:
340
340
  Self for chaining
341
341
  """
342
- from oscura.compliance.masks import load_limit_mask
342
+ from oscura.validation.compliance.masks import load_limit_mask
343
343
 
344
344
  mask = load_limit_mask(mask_name)
345
345
  self._masks.append((mask_name, mask))
@@ -573,7 +573,7 @@ class QuasiPeakDetector:
573
573
  """
574
574
 
575
575
  # CISPR 16-1-1 detector parameters by band
576
- BAND_PARAMS = { # noqa: RUF012
576
+ BAND_PARAMS = {
577
577
  QPDetectorBand.BAND_A: QPDetectorParams(
578
578
  bandwidth=200, # 200 Hz
579
579
  charge_time=45, # ms
@@ -601,7 +601,7 @@ class QuasiPeakDetector:
601
601
  }
602
602
 
603
603
  # Frequency ranges for bands (Hz)
604
- BAND_RANGES = { # noqa: RUF012
604
+ BAND_RANGES = {
605
605
  QPDetectorBand.BAND_A: (9e3, 150e3),
606
606
  QPDetectorBand.BAND_B: (150e3, 30e6),
607
607
  QPDetectorBand.BAND_C: (30e6, 300e6),
@@ -4,7 +4,7 @@ This module provides limit mask loading and management for EMC compliance testin
4
4
 
5
5
 
6
6
  Example:
7
- >>> from oscura.compliance.masks import load_limit_mask, AVAILABLE_MASKS
7
+ >>> from oscura.validation.compliance.masks import load_limit_mask, AVAILABLE_MASKS
8
8
  >>> print(AVAILABLE_MASKS)
9
9
  >>> mask = load_limit_mask('FCC_Part15_ClassB')
10
10
  >>> print(f"Frequency range: {mask.frequency_range}")