oscura 0.5.1__py3-none-any.whl → 0.7.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 (497) 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/edges.py +325 -65
  5. oscura/analyzers/digital/quality.py +293 -166
  6. oscura/analyzers/digital/timing.py +260 -115
  7. oscura/analyzers/digital/timing_numba.py +334 -0
  8. oscura/analyzers/entropy.py +605 -0
  9. oscura/analyzers/eye/diagram.py +176 -109
  10. oscura/analyzers/eye/metrics.py +5 -5
  11. oscura/analyzers/jitter/__init__.py +6 -4
  12. oscura/analyzers/jitter/ber.py +52 -52
  13. oscura/analyzers/jitter/classification.py +156 -0
  14. oscura/analyzers/jitter/decomposition.py +163 -113
  15. oscura/analyzers/jitter/spectrum.py +80 -64
  16. oscura/analyzers/ml/__init__.py +39 -0
  17. oscura/analyzers/ml/features.py +600 -0
  18. oscura/analyzers/ml/signal_classifier.py +604 -0
  19. oscura/analyzers/packet/daq.py +246 -158
  20. oscura/analyzers/packet/parser.py +12 -1
  21. oscura/analyzers/packet/payload.py +50 -2110
  22. oscura/analyzers/packet/payload_analysis.py +361 -181
  23. oscura/analyzers/packet/payload_patterns.py +133 -70
  24. oscura/analyzers/packet/stream.py +84 -23
  25. oscura/analyzers/patterns/__init__.py +26 -5
  26. oscura/analyzers/patterns/anomaly_detection.py +908 -0
  27. oscura/analyzers/patterns/clustering.py +169 -108
  28. oscura/analyzers/patterns/clustering_optimized.py +227 -0
  29. oscura/analyzers/patterns/discovery.py +1 -1
  30. oscura/analyzers/patterns/matching.py +581 -197
  31. oscura/analyzers/patterns/pattern_mining.py +778 -0
  32. oscura/analyzers/patterns/periodic.py +121 -38
  33. oscura/analyzers/patterns/sequences.py +175 -78
  34. oscura/analyzers/power/conduction.py +1 -1
  35. oscura/analyzers/power/soa.py +6 -6
  36. oscura/analyzers/power/switching.py +250 -110
  37. oscura/analyzers/protocol/__init__.py +17 -1
  38. oscura/analyzers/protocols/base.py +6 -6
  39. oscura/analyzers/protocols/ble/__init__.py +38 -0
  40. oscura/analyzers/protocols/ble/analyzer.py +809 -0
  41. oscura/analyzers/protocols/ble/uuids.py +288 -0
  42. oscura/analyzers/protocols/can.py +257 -127
  43. oscura/analyzers/protocols/can_fd.py +107 -80
  44. oscura/analyzers/protocols/flexray.py +139 -80
  45. oscura/analyzers/protocols/hdlc.py +93 -58
  46. oscura/analyzers/protocols/i2c.py +247 -106
  47. oscura/analyzers/protocols/i2s.py +138 -86
  48. oscura/analyzers/protocols/industrial/__init__.py +40 -0
  49. oscura/analyzers/protocols/industrial/bacnet/__init__.py +33 -0
  50. oscura/analyzers/protocols/industrial/bacnet/analyzer.py +708 -0
  51. oscura/analyzers/protocols/industrial/bacnet/encoding.py +412 -0
  52. oscura/analyzers/protocols/industrial/bacnet/services.py +622 -0
  53. oscura/analyzers/protocols/industrial/ethercat/__init__.py +30 -0
  54. oscura/analyzers/protocols/industrial/ethercat/analyzer.py +474 -0
  55. oscura/analyzers/protocols/industrial/ethercat/mailbox.py +339 -0
  56. oscura/analyzers/protocols/industrial/ethercat/topology.py +166 -0
  57. oscura/analyzers/protocols/industrial/modbus/__init__.py +31 -0
  58. oscura/analyzers/protocols/industrial/modbus/analyzer.py +525 -0
  59. oscura/analyzers/protocols/industrial/modbus/crc.py +79 -0
  60. oscura/analyzers/protocols/industrial/modbus/functions.py +436 -0
  61. oscura/analyzers/protocols/industrial/opcua/__init__.py +21 -0
  62. oscura/analyzers/protocols/industrial/opcua/analyzer.py +552 -0
  63. oscura/analyzers/protocols/industrial/opcua/datatypes.py +446 -0
  64. oscura/analyzers/protocols/industrial/opcua/services.py +264 -0
  65. oscura/analyzers/protocols/industrial/profinet/__init__.py +23 -0
  66. oscura/analyzers/protocols/industrial/profinet/analyzer.py +441 -0
  67. oscura/analyzers/protocols/industrial/profinet/dcp.py +263 -0
  68. oscura/analyzers/protocols/industrial/profinet/ptcp.py +200 -0
  69. oscura/analyzers/protocols/jtag.py +180 -98
  70. oscura/analyzers/protocols/lin.py +219 -114
  71. oscura/analyzers/protocols/manchester.py +4 -4
  72. oscura/analyzers/protocols/onewire.py +253 -149
  73. oscura/analyzers/protocols/parallel_bus/__init__.py +20 -0
  74. oscura/analyzers/protocols/parallel_bus/centronics.py +92 -0
  75. oscura/analyzers/protocols/parallel_bus/gpib.py +137 -0
  76. oscura/analyzers/protocols/spi.py +192 -95
  77. oscura/analyzers/protocols/swd.py +321 -167
  78. oscura/analyzers/protocols/uart.py +267 -125
  79. oscura/analyzers/protocols/usb.py +235 -131
  80. oscura/analyzers/side_channel/power.py +17 -12
  81. oscura/analyzers/signal/__init__.py +15 -0
  82. oscura/analyzers/signal/timing_analysis.py +1086 -0
  83. oscura/analyzers/signal_integrity/__init__.py +4 -1
  84. oscura/analyzers/signal_integrity/sparams.py +2 -19
  85. oscura/analyzers/spectral/chunked.py +129 -60
  86. oscura/analyzers/spectral/chunked_fft.py +300 -94
  87. oscura/analyzers/spectral/chunked_wavelet.py +100 -80
  88. oscura/analyzers/statistical/checksum.py +376 -217
  89. oscura/analyzers/statistical/classification.py +229 -107
  90. oscura/analyzers/statistical/entropy.py +78 -53
  91. oscura/analyzers/statistics/correlation.py +407 -211
  92. oscura/analyzers/statistics/outliers.py +2 -2
  93. oscura/analyzers/statistics/streaming.py +30 -5
  94. oscura/analyzers/validation.py +216 -101
  95. oscura/analyzers/waveform/measurements.py +9 -0
  96. oscura/analyzers/waveform/measurements_with_uncertainty.py +31 -15
  97. oscura/analyzers/waveform/spectral.py +500 -228
  98. oscura/api/__init__.py +31 -5
  99. oscura/api/dsl/__init__.py +582 -0
  100. oscura/{dsl → api/dsl}/commands.py +43 -76
  101. oscura/{dsl → api/dsl}/interpreter.py +26 -51
  102. oscura/{dsl → api/dsl}/parser.py +107 -77
  103. oscura/{dsl → api/dsl}/repl.py +2 -2
  104. oscura/api/dsl.py +1 -1
  105. oscura/{integrations → api/integrations}/__init__.py +1 -1
  106. oscura/{integrations → api/integrations}/llm.py +201 -102
  107. oscura/api/operators.py +3 -3
  108. oscura/api/optimization.py +144 -30
  109. oscura/api/rest_server.py +921 -0
  110. oscura/api/server/__init__.py +17 -0
  111. oscura/api/server/dashboard.py +850 -0
  112. oscura/api/server/static/README.md +34 -0
  113. oscura/api/server/templates/base.html +181 -0
  114. oscura/api/server/templates/export.html +120 -0
  115. oscura/api/server/templates/home.html +284 -0
  116. oscura/api/server/templates/protocols.html +58 -0
  117. oscura/api/server/templates/reports.html +43 -0
  118. oscura/api/server/templates/session_detail.html +89 -0
  119. oscura/api/server/templates/sessions.html +83 -0
  120. oscura/api/server/templates/waveforms.html +73 -0
  121. oscura/automotive/__init__.py +8 -1
  122. oscura/automotive/can/__init__.py +10 -0
  123. oscura/automotive/can/checksum.py +3 -1
  124. oscura/automotive/can/dbc_generator.py +590 -0
  125. oscura/automotive/can/message_wrapper.py +121 -74
  126. oscura/automotive/can/patterns.py +98 -21
  127. oscura/automotive/can/session.py +292 -56
  128. oscura/automotive/can/state_machine.py +6 -3
  129. oscura/automotive/can/stimulus_response.py +97 -75
  130. oscura/automotive/dbc/__init__.py +10 -2
  131. oscura/automotive/dbc/generator.py +84 -56
  132. oscura/automotive/dbc/parser.py +6 -6
  133. oscura/automotive/dtc/data.json +17 -102
  134. oscura/automotive/dtc/database.py +2 -2
  135. oscura/automotive/flexray/__init__.py +31 -0
  136. oscura/automotive/flexray/analyzer.py +504 -0
  137. oscura/automotive/flexray/crc.py +185 -0
  138. oscura/automotive/flexray/fibex.py +449 -0
  139. oscura/automotive/j1939/__init__.py +45 -8
  140. oscura/automotive/j1939/analyzer.py +605 -0
  141. oscura/automotive/j1939/spns.py +326 -0
  142. oscura/automotive/j1939/transport.py +306 -0
  143. oscura/automotive/lin/__init__.py +47 -0
  144. oscura/automotive/lin/analyzer.py +612 -0
  145. oscura/automotive/loaders/blf.py +13 -2
  146. oscura/automotive/loaders/csv_can.py +143 -72
  147. oscura/automotive/loaders/dispatcher.py +50 -2
  148. oscura/automotive/loaders/mdf.py +86 -45
  149. oscura/automotive/loaders/pcap.py +111 -61
  150. oscura/automotive/uds/__init__.py +4 -0
  151. oscura/automotive/uds/analyzer.py +725 -0
  152. oscura/automotive/uds/decoder.py +140 -58
  153. oscura/automotive/uds/models.py +7 -1
  154. oscura/automotive/visualization.py +1 -1
  155. oscura/cli/analyze.py +348 -0
  156. oscura/cli/batch.py +142 -122
  157. oscura/cli/benchmark.py +275 -0
  158. oscura/cli/characterize.py +137 -82
  159. oscura/cli/compare.py +224 -131
  160. oscura/cli/completion.py +250 -0
  161. oscura/cli/config_cmd.py +361 -0
  162. oscura/cli/decode.py +164 -87
  163. oscura/cli/export.py +286 -0
  164. oscura/cli/main.py +115 -31
  165. oscura/{onboarding → cli/onboarding}/__init__.py +3 -3
  166. oscura/{onboarding → cli/onboarding}/help.py +80 -58
  167. oscura/{onboarding → cli/onboarding}/tutorials.py +97 -72
  168. oscura/{onboarding → cli/onboarding}/wizard.py +55 -36
  169. oscura/cli/progress.py +147 -0
  170. oscura/cli/shell.py +157 -135
  171. oscura/cli/validate_cmd.py +204 -0
  172. oscura/cli/visualize.py +158 -0
  173. oscura/convenience.py +125 -79
  174. oscura/core/__init__.py +4 -2
  175. oscura/core/backend_selector.py +3 -3
  176. oscura/core/cache.py +126 -15
  177. oscura/core/cancellation.py +1 -1
  178. oscura/{config → core/config}/__init__.py +20 -11
  179. oscura/{config → core/config}/defaults.py +1 -1
  180. oscura/{config → core/config}/loader.py +7 -5
  181. oscura/{config → core/config}/memory.py +5 -5
  182. oscura/{config → core/config}/migration.py +1 -1
  183. oscura/{config → core/config}/pipeline.py +99 -23
  184. oscura/{config → core/config}/preferences.py +1 -1
  185. oscura/{config → core/config}/protocol.py +3 -3
  186. oscura/{config → core/config}/schema.py +426 -272
  187. oscura/{config → core/config}/settings.py +1 -1
  188. oscura/{config → core/config}/thresholds.py +195 -153
  189. oscura/core/correlation.py +5 -6
  190. oscura/core/cross_domain.py +0 -2
  191. oscura/core/debug.py +9 -5
  192. oscura/{extensibility → core/extensibility}/docs.py +158 -70
  193. oscura/{extensibility → core/extensibility}/extensions.py +160 -76
  194. oscura/{extensibility → core/extensibility}/logging.py +1 -1
  195. oscura/{extensibility → core/extensibility}/measurements.py +1 -1
  196. oscura/{extensibility → core/extensibility}/plugins.py +1 -1
  197. oscura/{extensibility → core/extensibility}/templates.py +73 -3
  198. oscura/{extensibility → core/extensibility}/validation.py +1 -1
  199. oscura/core/gpu_backend.py +11 -7
  200. oscura/core/log_query.py +101 -11
  201. oscura/core/logging.py +126 -54
  202. oscura/core/logging_advanced.py +5 -5
  203. oscura/core/memory_limits.py +108 -70
  204. oscura/core/memory_monitor.py +2 -2
  205. oscura/core/memory_progress.py +7 -7
  206. oscura/core/memory_warnings.py +1 -1
  207. oscura/core/numba_backend.py +13 -13
  208. oscura/{plugins → core/plugins}/__init__.py +9 -9
  209. oscura/{plugins → core/plugins}/base.py +7 -7
  210. oscura/{plugins → core/plugins}/cli.py +3 -3
  211. oscura/{plugins → core/plugins}/discovery.py +186 -106
  212. oscura/{plugins → core/plugins}/lifecycle.py +1 -1
  213. oscura/{plugins → core/plugins}/manager.py +7 -7
  214. oscura/{plugins → core/plugins}/registry.py +3 -3
  215. oscura/{plugins → core/plugins}/versioning.py +1 -1
  216. oscura/core/progress.py +16 -1
  217. oscura/core/provenance.py +8 -2
  218. oscura/{schemas → core/schemas}/__init__.py +2 -2
  219. oscura/{schemas → core/schemas}/device_mapping.json +2 -8
  220. oscura/{schemas → core/schemas}/packet_format.json +4 -24
  221. oscura/{schemas → core/schemas}/protocol_definition.json +2 -12
  222. oscura/core/types.py +4 -0
  223. oscura/core/uncertainty.py +3 -3
  224. oscura/correlation/__init__.py +52 -0
  225. oscura/correlation/multi_protocol.py +811 -0
  226. oscura/discovery/auto_decoder.py +117 -35
  227. oscura/discovery/comparison.py +191 -86
  228. oscura/discovery/quality_validator.py +155 -68
  229. oscura/discovery/signal_detector.py +196 -79
  230. oscura/export/__init__.py +18 -8
  231. oscura/export/kaitai_struct.py +513 -0
  232. oscura/export/scapy_layer.py +801 -0
  233. oscura/export/wireshark/generator.py +1 -1
  234. oscura/export/wireshark/templates/dissector.lua.j2 +2 -2
  235. oscura/export/wireshark_dissector.py +746 -0
  236. oscura/guidance/wizard.py +207 -111
  237. oscura/hardware/__init__.py +19 -0
  238. oscura/{acquisition → hardware/acquisition}/__init__.py +4 -4
  239. oscura/{acquisition → hardware/acquisition}/file.py +2 -2
  240. oscura/{acquisition → hardware/acquisition}/hardware.py +7 -7
  241. oscura/{acquisition → hardware/acquisition}/saleae.py +15 -12
  242. oscura/{acquisition → hardware/acquisition}/socketcan.py +1 -1
  243. oscura/{acquisition → hardware/acquisition}/streaming.py +2 -2
  244. oscura/{acquisition → hardware/acquisition}/synthetic.py +3 -3
  245. oscura/{acquisition → hardware/acquisition}/visa.py +33 -11
  246. oscura/hardware/firmware/__init__.py +29 -0
  247. oscura/hardware/firmware/pattern_recognition.py +874 -0
  248. oscura/hardware/hal_detector.py +736 -0
  249. oscura/hardware/security/__init__.py +37 -0
  250. oscura/hardware/security/side_channel_detector.py +1126 -0
  251. oscura/inference/__init__.py +4 -0
  252. oscura/inference/active_learning/observation_table.py +4 -1
  253. oscura/inference/alignment.py +216 -123
  254. oscura/inference/bayesian.py +113 -33
  255. oscura/inference/crc_reverse.py +101 -55
  256. oscura/inference/logic.py +6 -2
  257. oscura/inference/message_format.py +342 -183
  258. oscura/inference/protocol.py +95 -44
  259. oscura/inference/protocol_dsl.py +180 -82
  260. oscura/inference/signal_intelligence.py +1439 -706
  261. oscura/inference/spectral.py +99 -57
  262. oscura/inference/state_machine.py +810 -158
  263. oscura/inference/stream.py +270 -110
  264. oscura/iot/__init__.py +34 -0
  265. oscura/iot/coap/__init__.py +32 -0
  266. oscura/iot/coap/analyzer.py +668 -0
  267. oscura/iot/coap/options.py +212 -0
  268. oscura/iot/lorawan/__init__.py +21 -0
  269. oscura/iot/lorawan/crypto.py +206 -0
  270. oscura/iot/lorawan/decoder.py +801 -0
  271. oscura/iot/lorawan/mac_commands.py +341 -0
  272. oscura/iot/mqtt/__init__.py +27 -0
  273. oscura/iot/mqtt/analyzer.py +999 -0
  274. oscura/iot/mqtt/properties.py +315 -0
  275. oscura/iot/zigbee/__init__.py +31 -0
  276. oscura/iot/zigbee/analyzer.py +615 -0
  277. oscura/iot/zigbee/security.py +153 -0
  278. oscura/iot/zigbee/zcl.py +349 -0
  279. oscura/jupyter/display.py +125 -45
  280. oscura/{exploratory → jupyter/exploratory}/__init__.py +8 -8
  281. oscura/{exploratory → jupyter/exploratory}/error_recovery.py +298 -141
  282. oscura/jupyter/exploratory/fuzzy.py +746 -0
  283. oscura/{exploratory → jupyter/exploratory}/fuzzy_advanced.py +258 -100
  284. oscura/{exploratory → jupyter/exploratory}/legacy.py +464 -242
  285. oscura/{exploratory → jupyter/exploratory}/parse.py +167 -145
  286. oscura/{exploratory → jupyter/exploratory}/recovery.py +119 -87
  287. oscura/jupyter/exploratory/sync.py +612 -0
  288. oscura/{exploratory → jupyter/exploratory}/unknown.py +299 -176
  289. oscura/jupyter/magic.py +4 -4
  290. oscura/{ui → jupyter/ui}/__init__.py +2 -2
  291. oscura/{ui → jupyter/ui}/formatters.py +3 -3
  292. oscura/{ui → jupyter/ui}/progressive_display.py +153 -82
  293. oscura/loaders/__init__.py +183 -67
  294. oscura/loaders/binary.py +88 -1
  295. oscura/loaders/chipwhisperer.py +153 -137
  296. oscura/loaders/configurable.py +208 -86
  297. oscura/loaders/csv_loader.py +458 -215
  298. oscura/loaders/hdf5_loader.py +278 -119
  299. oscura/loaders/lazy.py +87 -54
  300. oscura/loaders/mmap_loader.py +1 -1
  301. oscura/loaders/numpy_loader.py +253 -116
  302. oscura/loaders/pcap.py +226 -151
  303. oscura/loaders/rigol.py +110 -49
  304. oscura/loaders/sigrok.py +201 -78
  305. oscura/loaders/tdms.py +81 -58
  306. oscura/loaders/tektronix.py +291 -174
  307. oscura/loaders/touchstone.py +182 -87
  308. oscura/loaders/tss.py +456 -0
  309. oscura/loaders/vcd.py +215 -117
  310. oscura/loaders/wav.py +155 -68
  311. oscura/reporting/__init__.py +9 -0
  312. oscura/reporting/analyze.py +352 -146
  313. oscura/reporting/argument_preparer.py +69 -14
  314. oscura/reporting/auto_report.py +97 -61
  315. oscura/reporting/batch.py +131 -58
  316. oscura/reporting/chart_selection.py +57 -45
  317. oscura/reporting/comparison.py +63 -17
  318. oscura/reporting/content/executive.py +76 -24
  319. oscura/reporting/core_formats/multi_format.py +11 -8
  320. oscura/reporting/engine.py +312 -158
  321. oscura/reporting/enhanced_reports.py +949 -0
  322. oscura/reporting/export.py +86 -43
  323. oscura/reporting/formatting/numbers.py +69 -42
  324. oscura/reporting/html.py +139 -58
  325. oscura/reporting/index.py +137 -65
  326. oscura/reporting/output.py +158 -67
  327. oscura/reporting/pdf.py +67 -102
  328. oscura/reporting/plots.py +191 -112
  329. oscura/reporting/sections.py +88 -47
  330. oscura/reporting/standards.py +104 -61
  331. oscura/reporting/summary_generator.py +75 -55
  332. oscura/reporting/tables.py +138 -54
  333. oscura/reporting/templates/enhanced/protocol_re.html +525 -0
  334. oscura/sessions/__init__.py +14 -23
  335. oscura/sessions/base.py +3 -3
  336. oscura/sessions/blackbox.py +106 -10
  337. oscura/sessions/generic.py +2 -2
  338. oscura/sessions/legacy.py +783 -0
  339. oscura/side_channel/__init__.py +63 -0
  340. oscura/side_channel/dpa.py +1025 -0
  341. oscura/utils/__init__.py +15 -1
  342. oscura/utils/bitwise.py +118 -0
  343. oscura/{builders → utils/builders}/__init__.py +1 -1
  344. oscura/{comparison → utils/comparison}/__init__.py +6 -6
  345. oscura/{comparison → utils/comparison}/compare.py +202 -101
  346. oscura/{comparison → utils/comparison}/golden.py +83 -63
  347. oscura/{comparison → utils/comparison}/limits.py +313 -89
  348. oscura/{comparison → utils/comparison}/mask.py +151 -45
  349. oscura/{comparison → utils/comparison}/trace_diff.py +1 -1
  350. oscura/{comparison → utils/comparison}/visualization.py +147 -89
  351. oscura/{component → utils/component}/__init__.py +3 -3
  352. oscura/{component → utils/component}/impedance.py +122 -58
  353. oscura/{component → utils/component}/reactive.py +165 -168
  354. oscura/{component → utils/component}/transmission_line.py +3 -3
  355. oscura/{filtering → utils/filtering}/__init__.py +6 -6
  356. oscura/{filtering → utils/filtering}/base.py +1 -1
  357. oscura/{filtering → utils/filtering}/convenience.py +2 -2
  358. oscura/{filtering → utils/filtering}/design.py +169 -93
  359. oscura/{filtering → utils/filtering}/filters.py +2 -2
  360. oscura/{filtering → utils/filtering}/introspection.py +2 -2
  361. oscura/utils/geometry.py +31 -0
  362. oscura/utils/imports.py +184 -0
  363. oscura/utils/lazy.py +1 -1
  364. oscura/{math → utils/math}/__init__.py +2 -2
  365. oscura/{math → utils/math}/arithmetic.py +114 -48
  366. oscura/{math → utils/math}/interpolation.py +139 -106
  367. oscura/utils/memory.py +129 -66
  368. oscura/utils/memory_advanced.py +92 -9
  369. oscura/utils/memory_extensions.py +10 -8
  370. oscura/{optimization → utils/optimization}/__init__.py +1 -1
  371. oscura/{optimization → utils/optimization}/search.py +2 -2
  372. oscura/utils/performance/__init__.py +58 -0
  373. oscura/utils/performance/caching.py +889 -0
  374. oscura/utils/performance/lsh_clustering.py +333 -0
  375. oscura/utils/performance/memory_optimizer.py +699 -0
  376. oscura/utils/performance/optimizations.py +675 -0
  377. oscura/utils/performance/parallel.py +654 -0
  378. oscura/utils/performance/profiling.py +661 -0
  379. oscura/{pipeline → utils/pipeline}/base.py +1 -1
  380. oscura/{pipeline → utils/pipeline}/composition.py +1 -1
  381. oscura/{pipeline → utils/pipeline}/parallel.py +3 -2
  382. oscura/{pipeline → utils/pipeline}/pipeline.py +1 -1
  383. oscura/{pipeline → utils/pipeline}/reverse_engineering.py +412 -221
  384. oscura/{search → utils/search}/__init__.py +3 -3
  385. oscura/{search → utils/search}/anomaly.py +188 -58
  386. oscura/utils/search/context.py +294 -0
  387. oscura/{search → utils/search}/pattern.py +138 -10
  388. oscura/utils/serial.py +51 -0
  389. oscura/utils/storage/__init__.py +61 -0
  390. oscura/utils/storage/database.py +1166 -0
  391. oscura/{streaming → utils/streaming}/chunked.py +302 -143
  392. oscura/{streaming → utils/streaming}/progressive.py +1 -1
  393. oscura/{streaming → utils/streaming}/realtime.py +3 -2
  394. oscura/{triggering → utils/triggering}/__init__.py +6 -6
  395. oscura/{triggering → utils/triggering}/base.py +6 -6
  396. oscura/{triggering → utils/triggering}/edge.py +2 -2
  397. oscura/{triggering → utils/triggering}/pattern.py +2 -2
  398. oscura/{triggering → utils/triggering}/pulse.py +115 -74
  399. oscura/{triggering → utils/triggering}/window.py +2 -2
  400. oscura/utils/validation.py +32 -0
  401. oscura/validation/__init__.py +121 -0
  402. oscura/{compliance → validation/compliance}/__init__.py +5 -5
  403. oscura/{compliance → validation/compliance}/advanced.py +5 -5
  404. oscura/{compliance → validation/compliance}/masks.py +1 -1
  405. oscura/{compliance → validation/compliance}/reporting.py +127 -53
  406. oscura/{compliance → validation/compliance}/testing.py +114 -52
  407. oscura/validation/compliance_tests.py +915 -0
  408. oscura/validation/fuzzer.py +990 -0
  409. oscura/validation/grammar_tests.py +596 -0
  410. oscura/validation/grammar_validator.py +904 -0
  411. oscura/validation/hil_testing.py +977 -0
  412. oscura/{quality → validation/quality}/__init__.py +4 -4
  413. oscura/{quality → validation/quality}/ensemble.py +251 -171
  414. oscura/{quality → validation/quality}/explainer.py +3 -3
  415. oscura/{quality → validation/quality}/scoring.py +1 -1
  416. oscura/{quality → validation/quality}/warnings.py +4 -4
  417. oscura/validation/regression_suite.py +808 -0
  418. oscura/validation/replay.py +788 -0
  419. oscura/{testing → validation/testing}/__init__.py +2 -2
  420. oscura/{testing → validation/testing}/synthetic.py +5 -5
  421. oscura/visualization/__init__.py +9 -0
  422. oscura/visualization/accessibility.py +1 -1
  423. oscura/visualization/annotations.py +64 -67
  424. oscura/visualization/colors.py +7 -7
  425. oscura/visualization/digital.py +180 -81
  426. oscura/visualization/eye.py +236 -85
  427. oscura/visualization/interactive.py +320 -143
  428. oscura/visualization/jitter.py +587 -247
  429. oscura/visualization/layout.py +169 -134
  430. oscura/visualization/optimization.py +103 -52
  431. oscura/visualization/palettes.py +1 -1
  432. oscura/visualization/power.py +427 -211
  433. oscura/visualization/power_extended.py +626 -297
  434. oscura/visualization/presets.py +2 -0
  435. oscura/visualization/protocols.py +495 -181
  436. oscura/visualization/render.py +79 -63
  437. oscura/visualization/reverse_engineering.py +171 -124
  438. oscura/visualization/signal_integrity.py +460 -279
  439. oscura/visualization/specialized.py +190 -100
  440. oscura/visualization/spectral.py +670 -255
  441. oscura/visualization/thumbnails.py +166 -137
  442. oscura/visualization/waveform.py +150 -63
  443. oscura/workflows/__init__.py +3 -0
  444. oscura/{batch → workflows/batch}/__init__.py +5 -5
  445. oscura/{batch → workflows/batch}/advanced.py +150 -75
  446. oscura/workflows/batch/aggregate.py +531 -0
  447. oscura/workflows/batch/analyze.py +236 -0
  448. oscura/{batch → workflows/batch}/logging.py +2 -2
  449. oscura/{batch → workflows/batch}/metrics.py +1 -1
  450. oscura/workflows/complete_re.py +1144 -0
  451. oscura/workflows/compliance.py +44 -54
  452. oscura/workflows/digital.py +197 -51
  453. oscura/workflows/legacy/__init__.py +12 -0
  454. oscura/{workflow → workflows/legacy}/dag.py +4 -1
  455. oscura/workflows/multi_trace.py +9 -9
  456. oscura/workflows/power.py +42 -62
  457. oscura/workflows/protocol.py +82 -49
  458. oscura/workflows/reverse_engineering.py +351 -150
  459. oscura/workflows/signal_integrity.py +157 -82
  460. oscura-0.7.0.dist-info/METADATA +661 -0
  461. oscura-0.7.0.dist-info/RECORD +591 -0
  462. oscura/batch/aggregate.py +0 -300
  463. oscura/batch/analyze.py +0 -139
  464. oscura/dsl/__init__.py +0 -73
  465. oscura/exceptions.py +0 -59
  466. oscura/exploratory/fuzzy.py +0 -513
  467. oscura/exploratory/sync.py +0 -384
  468. oscura/exporters/__init__.py +0 -94
  469. oscura/exporters/csv.py +0 -303
  470. oscura/exporters/exporters.py +0 -44
  471. oscura/exporters/hdf5.py +0 -217
  472. oscura/exporters/html_export.py +0 -701
  473. oscura/exporters/json_export.py +0 -291
  474. oscura/exporters/markdown_export.py +0 -367
  475. oscura/exporters/matlab_export.py +0 -354
  476. oscura/exporters/npz_export.py +0 -219
  477. oscura/exporters/spice_export.py +0 -210
  478. oscura/search/context.py +0 -149
  479. oscura/session/__init__.py +0 -34
  480. oscura/session/annotations.py +0 -289
  481. oscura/session/history.py +0 -313
  482. oscura/session/session.py +0 -520
  483. oscura/workflow/__init__.py +0 -13
  484. oscura-0.5.1.dist-info/METADATA +0 -583
  485. oscura-0.5.1.dist-info/RECORD +0 -481
  486. /oscura/core/{config.py → config/legacy.py} +0 -0
  487. /oscura/{extensibility → core/extensibility}/__init__.py +0 -0
  488. /oscura/{extensibility → core/extensibility}/registry.py +0 -0
  489. /oscura/{plugins → core/plugins}/isolation.py +0 -0
  490. /oscura/{schemas → core/schemas}/bus_configuration.json +0 -0
  491. /oscura/{builders → utils/builders}/signal_builder.py +0 -0
  492. /oscura/{optimization → utils/optimization}/parallel.py +0 -0
  493. /oscura/{pipeline → utils/pipeline}/__init__.py +0 -0
  494. /oscura/{streaming → utils/streaming}/__init__.py +0 -0
  495. {oscura-0.5.1.dist-info → oscura-0.7.0.dist-info}/WHEEL +0 -0
  496. {oscura-0.5.1.dist-info → oscura-0.7.0.dist-info}/entry_points.txt +0 -0
  497. {oscura-0.5.1.dist-info → oscura-0.7.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}")