commkit 3.4.0__tar.gz → 3.5.0__tar.gz

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 (314) hide show
  1. commkit-3.5.0/.github/icon.svg +1 -0
  2. commkit-3.5.0/.github/logo.svg +1 -0
  3. {commkit-3.4.0 → commkit-3.5.0}/.github/workflows/ci.yml +1 -1
  4. {commkit-3.4.0 → commkit-3.5.0}/AGENTS.md +23 -65
  5. {commkit-3.4.0 → commkit-3.5.0}/CHANGELOG.md +33 -1
  6. {commkit-3.4.0 → commkit-3.5.0}/PKG-INFO +11 -11
  7. {commkit-3.4.0 → commkit-3.5.0}/README.md +12 -12
  8. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_signal_pipeline.py +1 -1
  9. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/workloads.py +4 -2
  10. {commkit-3.4.0 → commkit-3.5.0}/commkit/__init__.py +1 -1
  11. {commkit-3.4.0 → commkit-3.5.0}/commkit/_sequences.py +1 -1
  12. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/drift.py +3 -3
  13. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/fm_noise.py +6 -6
  14. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/linewidth/dsh.py +10 -10
  15. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/linewidth/phase.py +6 -6
  16. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/linewidth/result.py +16 -16
  17. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/trajectory.py +7 -7
  18. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/exit.py +9 -5
  19. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/performance.py +16 -14
  20. {commkit-3.4.0 → commkit-3.5.0}/commkit/core/__init__.py +5 -2
  21. {commkit-3.4.0 → commkit-3.5.0}/commkit/core/frame.py +5 -154
  22. {commkit-3.4.0 → commkit-3.5.0}/commkit/core/generation.py +2 -2
  23. commkit-3.5.0/commkit/core/preamble.py +170 -0
  24. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/__init__.py +2 -3
  25. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/_block/__init__.py +7 -4
  26. commkit-3.4.0/commkit/equalization/blind.py → commkit-3.5.0/commkit/equalization/_block/_blind.py +206 -11
  27. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/_block/_dd.py +13 -1
  28. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/_numba_loops.py +4 -2
  29. commkit-3.5.0/commkit/equalization/_sequential/__init__.py +21 -0
  30. {commkit-3.4.0/commkit/equalization/sequential → commkit-3.5.0/commkit/equalization/_sequential}/_blind.py +18 -1
  31. {commkit-3.4.0/commkit/equalization/sequential → commkit-3.5.0/commkit/equalization/_sequential}/_dd.py +30 -5
  32. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/linear.py +4 -4
  33. commkit-3.4.0/commkit/impairments/channel/linear.py → commkit-3.5.0/commkit/impairments/channel.py +186 -10
  34. {commkit-3.4.0 → commkit-3.5.0}/commkit/impairments/noise.py +1 -1
  35. {commkit-3.4.0 → commkit-3.5.0}/commkit/metrics/error_rates.py +22 -23
  36. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/__init__.py +12 -8
  37. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/analysis.py +116 -26
  38. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/coding.py +10 -4
  39. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/constellation.py +2 -0
  40. commkit-3.5.0/commkit/plotting/frequency.py +374 -0
  41. commkit-3.5.0/commkit/plotting/recovery.py +551 -0
  42. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/theme.py +15 -0
  43. commkit-3.5.0/commkit/plotting/timing.py +129 -0
  44. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/_common.py +5 -2
  45. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/pll.py +18 -13
  46. {commkit-3.4.0 → commkit-3.5.0}/examples/07-channel-coding.ipynb +5 -5
  47. {commkit-3.4.0 → commkit-3.5.0}/examples/08-probabilistic-shaping-and-coded-modulation.ipynb +5 -3
  48. {commkit-3.4.0 → commkit-3.5.0}/examples/23-carrier-phase-characterization.ipynb +3 -3
  49. {commkit-3.4.0 → commkit-3.5.0}/examples/25-laser-linewidth-short-delay-and-flicker.ipynb +2 -2
  50. {commkit-3.4.0 → commkit-3.5.0}/examples/26-laser-linewidth-self-homodyne-iq.ipynb +2 -2
  51. {commkit-3.4.0 → commkit-3.5.0}/examples/27-measurement-template-self-heterodyne.ipynb +3 -3
  52. {commkit-3.4.0 → commkit-3.5.0}/examples/28-measurement-template-self-homodyne-iq.ipynb +3 -3
  53. {commkit-3.4.0 → commkit-3.5.0}/pyproject.toml +2 -5
  54. {commkit-3.4.0 → commkit-3.5.0}/scripts/sanitize.sh +1 -1
  55. {commkit-3.4.0 → commkit-3.5.0}/tests/analysis/test_drift.py +2 -2
  56. {commkit-3.4.0 → commkit-3.5.0}/tests/analysis/test_linewidth.py +11 -11
  57. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_ldpc.py +3 -3
  58. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_polar.py +2 -4
  59. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_product.py +6 -1
  60. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_shaping.py +11 -7
  61. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_turbo.py +4 -4
  62. {commkit-3.4.0 → commkit-3.5.0}/tests/common/coding.py +1 -1
  63. {commkit-3.4.0 → commkit-3.5.0}/tests/common/signals.py +33 -5
  64. {commkit-3.4.0 → commkit-3.5.0}/tests/core/test_frame.py +1 -16
  65. {commkit-3.4.0 → commkit-3.5.0}/tests/core/test_generation.py +43 -27
  66. commkit-3.5.0/tests/core/test_preamble.py +26 -0
  67. {commkit-3.4.0 → commkit-3.5.0}/tests/core/test_psqam.py +21 -8
  68. {commkit-3.4.0 → commkit-3.5.0}/tests/core/test_signal.py +84 -23
  69. {commkit-3.4.0 → commkit-3.5.0}/tests/core/test_signal_mimo.py +1 -1
  70. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_blind.py +7 -1
  71. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_cpr.py +17 -7
  72. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_cs_kernel.py +1 -1
  73. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_equalizer_oracles.py +6 -1
  74. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_sequential.py +13 -6
  75. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_state.py +3 -1
  76. {commkit-3.4.0 → commkit-3.5.0}/tests/metrics/test_common.py +3 -3
  77. {commkit-3.4.0 → commkit-3.5.0}/tests/metrics/test_error_rates.py +26 -20
  78. {commkit-3.4.0 → commkit-3.5.0}/tests/metrics/test_information.py +4 -2
  79. {commkit-3.4.0 → commkit-3.5.0}/tests/metrics/test_quality.py +1 -1
  80. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_analysis.py +25 -3
  81. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_coding.py +6 -2
  82. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_constellation.py +9 -7
  83. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_equalizer.py +31 -7
  84. commkit-3.5.0/tests/plotting/test_plot_frequency.py +120 -0
  85. commkit-3.5.0/tests/plotting/test_plot_recovery.py +157 -0
  86. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_spectral.py +1 -1
  87. commkit-3.5.0/tests/plotting/test_plot_timing.py +75 -0
  88. {commkit-3.4.0 → commkit-3.5.0}/tests/plugins/precision_trace.py +25 -3
  89. {commkit-3.4.0 → commkit-3.5.0}/tests/plugins/transfer_trace.py +32 -6
  90. {commkit-3.4.0 → commkit-3.5.0}/tests/recovery/test_corrections.py +27 -7
  91. {commkit-3.4.0 → commkit-3.5.0}/tests/recovery/test_pilots.py +4 -4
  92. {commkit-3.4.0 → commkit-3.5.0}/tests/recovery/test_pll.py +30 -18
  93. {commkit-3.4.0 → commkit-3.5.0}/tests/recovery/test_recovery_oracles.py +3 -1
  94. {commkit-3.4.0 → commkit-3.5.0}/tests/test_api_contracts.py +23 -23
  95. {commkit-3.4.0 → commkit-3.5.0}/tests/test_fiber.py +1 -1
  96. {commkit-3.4.0 → commkit-3.5.0}/tests/test_frequency.py +5 -1
  97. {commkit-3.4.0 → commkit-3.5.0}/tests/test_io.py +15 -8
  98. {commkit-3.4.0 → commkit-3.5.0}/tests/test_pulse_shaping.py +22 -6
  99. {commkit-3.4.0 → commkit-3.5.0}/tests/test_receiver_chain.py +1 -1
  100. {commkit-3.4.0 → commkit-3.5.0}/tests/test_signal_pipeline.py +5 -1
  101. {commkit-3.4.0 → commkit-3.5.0}/tests/test_timing.py +8 -3
  102. {commkit-3.4.0 → commkit-3.5.0}/uv.lock +1 -1
  103. commkit-3.4.0/commkit/equalization/_block/_blind.py +0 -202
  104. commkit-3.4.0/commkit/equalization/_kernels_numba.py +0 -48
  105. commkit-3.4.0/commkit/equalization/sequential/__init__.py +0 -19
  106. commkit-3.4.0/commkit/impairments/channel/__init__.py +0 -24
  107. commkit-3.4.0/commkit/impairments/channel/nonlinear.py +0 -182
  108. commkit-3.4.0/commkit/plotting/sync.py +0 -1120
  109. commkit-3.4.0/tests/plotting/test_plot_sync.py +0 -341
  110. {commkit-3.4.0 → commkit-3.5.0}/.gitattributes +0 -0
  111. {commkit-3.4.0 → commkit-3.5.0}/.github/workflows/publish.yml +0 -0
  112. {commkit-3.4.0 → commkit-3.5.0}/.gitignore +0 -0
  113. {commkit-3.4.0 → commkit-3.5.0}/.python-version +0 -0
  114. {commkit-3.4.0 → commkit-3.5.0}/LICENSE +0 -0
  115. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0002_pre_v2.json +0 -0
  116. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0003_v2_0.json +0 -0
  117. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0004_fiber_dbp.json +0 -0
  118. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0005_gpu_decoder_path.json +0 -0
  119. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0006_perf_cleanup.json +0 -0
  120. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0007_v3_0.json +0 -0
  121. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0008_v3_1.json +0 -0
  122. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_block_blind.py +0 -0
  123. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_block_lms.py +0 -0
  124. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_bps.py +0 -0
  125. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_coding.py +0 -0
  126. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_equalizers.py +0 -0
  127. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_fiber.py +0 -0
  128. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_filters.py +0 -0
  129. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_import.py +0 -0
  130. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_llr.py +0 -0
  131. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_mapping.py +0 -0
  132. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/bench_sync_misc.py +0 -0
  133. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/benchutils.py +0 -0
  134. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/conftest.py +0 -0
  135. {commkit-3.4.0 → commkit-3.5.0}/benchmarks/record_baseline.py +0 -0
  136. {commkit-3.4.0 → commkit-3.5.0}/commkit/_array.py +0 -0
  137. {commkit-3.4.0 → commkit-3.5.0}/commkit/_circular.py +0 -0
  138. {commkit-3.4.0 → commkit-3.5.0}/commkit/_constants.py +0 -0
  139. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/__init__.py +0 -0
  140. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/compiler.py +0 -0
  141. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/graphs.py +0 -0
  142. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/src/algebraic.cu +0 -0
  143. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/src/bps_anchor.cu +0 -0
  144. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/src/bps_min_d2.cu +0 -0
  145. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/src/cs_block.cu +0 -0
  146. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/src/iir.cu +0 -0
  147. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/src/ldpc.cu +0 -0
  148. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/src/llr.cu +0 -0
  149. {commkit-3.4.0 → commkit-3.5.0}/commkit/_cuda/src/selftest.cu +0 -0
  150. {commkit-3.4.0 → commkit-3.5.0}/commkit/_dispersion.py +0 -0
  151. {commkit-3.4.0 → commkit-3.5.0}/commkit/_fft.py +0 -0
  152. {commkit-3.4.0 → commkit-3.5.0}/commkit/_fiber.py +0 -0
  153. {commkit-3.4.0 → commkit-3.5.0}/commkit/_overlap_save.py +0 -0
  154. {commkit-3.4.0 → commkit-3.5.0}/commkit/_random.py +0 -0
  155. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/__init__.py +0 -0
  156. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/_common.py +0 -0
  157. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/allan.py +0 -0
  158. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/interferometry.py +0 -0
  159. {commkit-3.4.0 → commkit-3.5.0}/commkit/analysis/linewidth/__init__.py +0 -0
  160. {commkit-3.4.0 → commkit-3.5.0}/commkit/backend.py +0 -0
  161. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/__init__.py +0 -0
  162. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/_galois.py +0 -0
  163. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/_gf2.py +0 -0
  164. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/_ldpc_tables.py +0 -0
  165. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/_numba_loops.py +0 -0
  166. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/algebraic.py +0 -0
  167. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/base.py +0 -0
  168. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/convolutional.py +0 -0
  169. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/crc.py +0 -0
  170. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/interleaving.py +0 -0
  171. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/ldpc.py +0 -0
  172. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/linear.py +0 -0
  173. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/polar.py +0 -0
  174. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/product.py +0 -0
  175. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/ratematch.py +0 -0
  176. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/shaping.py +0 -0
  177. {commkit-3.4.0 → commkit-3.5.0}/commkit/coding/turbo.py +0 -0
  178. {commkit-3.4.0 → commkit-3.5.0}/commkit/core/_signal_adapter.py +0 -0
  179. {commkit-3.4.0 → commkit-3.5.0}/commkit/core/signal.py +0 -0
  180. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/_block/_engine.py +0 -0
  181. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/_common.py +0 -0
  182. {commkit-3.4.0/commkit/equalization/sequential → commkit-3.5.0/commkit/equalization/_sequential}/_setup.py +0 -0
  183. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/pilots.py +0 -0
  184. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/polarization.py +0 -0
  185. {commkit-3.4.0 → commkit-3.5.0}/commkit/equalization/result.py +0 -0
  186. {commkit-3.4.0 → commkit-3.5.0}/commkit/filtering/__init__.py +0 -0
  187. {commkit-3.4.0 → commkit-3.5.0}/commkit/filtering/fiber.py +0 -0
  188. {commkit-3.4.0 → commkit-3.5.0}/commkit/filtering/linear.py +0 -0
  189. {commkit-3.4.0 → commkit-3.5.0}/commkit/filtering/pulses.py +0 -0
  190. {commkit-3.4.0 → commkit-3.5.0}/commkit/filtering/response.py +0 -0
  191. {commkit-3.4.0 → commkit-3.5.0}/commkit/frequency.py +0 -0
  192. {commkit-3.4.0 → commkit-3.5.0}/commkit/impairments/__init__.py +0 -0
  193. {commkit-3.4.0 → commkit-3.5.0}/commkit/impairments/frontend.py +0 -0
  194. {commkit-3.4.0 → commkit-3.5.0}/commkit/impairments/source.py +0 -0
  195. {commkit-3.4.0 → commkit-3.5.0}/commkit/io.py +0 -0
  196. {commkit-3.4.0 → commkit-3.5.0}/commkit/logger.py +0 -0
  197. {commkit-3.4.0 → commkit-3.5.0}/commkit/mapping/__init__.py +0 -0
  198. {commkit-3.4.0 → commkit-3.5.0}/commkit/mapping/_numba_llr.py +0 -0
  199. {commkit-3.4.0 → commkit-3.5.0}/commkit/mapping/bits.py +0 -0
  200. {commkit-3.4.0 → commkit-3.5.0}/commkit/mapping/constellation.py +0 -0
  201. {commkit-3.4.0 → commkit-3.5.0}/commkit/mapping/gray.py +0 -0
  202. {commkit-3.4.0 → commkit-3.5.0}/commkit/mapping/llr.py +0 -0
  203. {commkit-3.4.0 → commkit-3.5.0}/commkit/mapping/shaping.py +0 -0
  204. {commkit-3.4.0 → commkit-3.5.0}/commkit/math.py +0 -0
  205. {commkit-3.4.0 → commkit-3.5.0}/commkit/metrics/__init__.py +0 -0
  206. {commkit-3.4.0 → commkit-3.5.0}/commkit/metrics/_common.py +0 -0
  207. {commkit-3.4.0 → commkit-3.5.0}/commkit/metrics/information.py +0 -0
  208. {commkit-3.4.0 → commkit-3.5.0}/commkit/metrics/quality.py +0 -0
  209. {commkit-3.4.0 → commkit-3.5.0}/commkit/multirate.py +0 -0
  210. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/equalizer.py +0 -0
  211. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/eye.py +0 -0
  212. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/filter_response.py +0 -0
  213. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/spectral.py +0 -0
  214. {commkit-3.4.0 → commkit-3.5.0}/commkit/plotting/waveform.py +0 -0
  215. {commkit-3.4.0 → commkit-3.5.0}/commkit/py.typed +0 -0
  216. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/__init__.py +0 -0
  217. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/bps.py +0 -0
  218. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/carrier_phase.py +0 -0
  219. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/corrections.py +0 -0
  220. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/pilots.py +0 -0
  221. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/tikhonov.py +0 -0
  222. {commkit-3.4.0 → commkit-3.5.0}/commkit/recovery/viterbi_viterbi.py +0 -0
  223. {commkit-3.4.0 → commkit-3.5.0}/commkit/smoothing.py +0 -0
  224. {commkit-3.4.0 → commkit-3.5.0}/commkit/spectral.py +0 -0
  225. {commkit-3.4.0 → commkit-3.5.0}/commkit/timing.py +0 -0
  226. {commkit-3.4.0 → commkit-3.5.0}/examples/00-getting-started.ipynb +0 -0
  227. {commkit-3.4.0 → commkit-3.5.0}/examples/01-constellations-and-bit-mapping.ipynb +0 -0
  228. {commkit-3.4.0 → commkit-3.5.0}/examples/02-spectral-analysis.ipynb +0 -0
  229. {commkit-3.4.0 → commkit-3.5.0}/examples/03-digital-filters.ipynb +0 -0
  230. {commkit-3.4.0 → commkit-3.5.0}/examples/04-pulse-shaping-and-matched-filtering.ipynb +0 -0
  231. {commkit-3.4.0 → commkit-3.5.0}/examples/05-multirate-and-resampling.ipynb +0 -0
  232. {commkit-3.4.0 → commkit-3.5.0}/examples/06-awgn-and-performance-metrics.ipynb +0 -0
  233. {commkit-3.4.0 → commkit-3.5.0}/examples/09-laser-phase-noise.ipynb +0 -0
  234. {commkit-3.4.0 → commkit-3.5.0}/examples/10-front-end-impairments.ipynb +0 -0
  235. {commkit-3.4.0 → commkit-3.5.0}/examples/11-frame-synchronization-and-timing.ipynb +0 -0
  236. {commkit-3.4.0 → commkit-3.5.0}/examples/12-frequency-offset-estimation.ipynb +0 -0
  237. {commkit-3.4.0 → commkit-3.5.0}/examples/13-blind-carrier-phase-recovery.ipynb +0 -0
  238. {commkit-3.4.0 → commkit-3.5.0}/examples/14-pilot-aided-carrier-recovery.ipynb +0 -0
  239. {commkit-3.4.0 → commkit-3.5.0}/examples/15-linear-channel-equalization.ipynb +0 -0
  240. {commkit-3.4.0 → commkit-3.5.0}/examples/16-adaptive-equalization.ipynb +0 -0
  241. {commkit-3.4.0 → commkit-3.5.0}/examples/17-blind-equalization.ipynb +0 -0
  242. {commkit-3.4.0 → commkit-3.5.0}/examples/18-polarization-multiplexing.ipynb +0 -0
  243. {commkit-3.4.0 → commkit-3.5.0}/examples/19-chromatic-dispersion.ipynb +0 -0
  244. {commkit-3.4.0 → commkit-3.5.0}/examples/20-nonlinear-fiber-and-backpropagation.ipynb +0 -0
  245. {commkit-3.4.0 → commkit-3.5.0}/examples/21-fec-in-optical-standards.ipynb +0 -0
  246. {commkit-3.4.0 → commkit-3.5.0}/examples/22-coherent-transceiver-end-to-end.ipynb +0 -0
  247. {commkit-3.4.0 → commkit-3.5.0}/examples/24-laser-linewidth-self-heterodyne.ipynb +0 -0
  248. {commkit-3.4.0 → commkit-3.5.0}/examples/README.md +0 -0
  249. {commkit-3.4.0 → commkit-3.5.0}/tests/analysis/test_allan.py +0 -0
  250. {commkit-3.4.0 → commkit-3.5.0}/tests/analysis/test_fm_noise.py +0 -0
  251. {commkit-3.4.0 → commkit-3.5.0}/tests/analysis/test_interferometry.py +0 -0
  252. {commkit-3.4.0 → commkit-3.5.0}/tests/analysis/test_trajectory.py +0 -0
  253. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_algebraic.py +0 -0
  254. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_coding_base.py +0 -0
  255. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_convolutional.py +0 -0
  256. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_crc.py +0 -0
  257. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_exit.py +0 -0
  258. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_gf2.py +0 -0
  259. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_interleaving.py +0 -0
  260. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_ldpc_exit.py +0 -0
  261. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_ldpc_kernel.py +0 -0
  262. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_ldpc_tables.py +0 -0
  263. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_linear_codes.py +0 -0
  264. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_performance.py +0 -0
  265. {commkit-3.4.0 → commkit-3.5.0}/tests/coding/test_ratematch.py +0 -0
  266. {commkit-3.4.0 → commkit-3.5.0}/tests/common/__init__.py +0 -0
  267. {commkit-3.4.0 → commkit-3.5.0}/tests/common/conversions.py +0 -0
  268. {commkit-3.4.0 → commkit-3.5.0}/tests/common/kernel_utils.py +0 -0
  269. {commkit-3.4.0 → commkit-3.5.0}/tests/common/memory.py +0 -0
  270. {commkit-3.4.0 → commkit-3.5.0}/tests/common/metrics.py +0 -0
  271. {commkit-3.4.0 → commkit-3.5.0}/tests/common/periodic.py +0 -0
  272. {commkit-3.4.0 → commkit-3.5.0}/tests/common/reference_impl.py +0 -0
  273. {commkit-3.4.0 → commkit-3.5.0}/tests/common/scoring.py +0 -0
  274. {commkit-3.4.0 → commkit-3.5.0}/tests/common/theory.py +0 -0
  275. {commkit-3.4.0 → commkit-3.5.0}/tests/conftest.py +0 -0
  276. {commkit-3.4.0 → commkit-3.5.0}/tests/core/test_signal_adapter.py +0 -0
  277. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_block.py +0 -0
  278. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_bps_kernel.py +0 -0
  279. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_linear.py +0 -0
  280. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_mimo.py +0 -0
  281. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_polarization.py +0 -0
  282. {commkit-3.4.0 → commkit-3.5.0}/tests/equalization/test_winit.py +0 -0
  283. {commkit-3.4.0/tests/impairments/channel → commkit-3.5.0/tests/impairments}/test_channel_linear.py +0 -0
  284. {commkit-3.4.0/tests/impairments/channel → commkit-3.5.0/tests/impairments}/test_channel_nonlinear.py +0 -0
  285. {commkit-3.4.0 → commkit-3.5.0}/tests/impairments/test_frontend.py +0 -0
  286. {commkit-3.4.0 → commkit-3.5.0}/tests/impairments/test_noise.py +0 -0
  287. {commkit-3.4.0 → commkit-3.5.0}/tests/impairments/test_source.py +0 -0
  288. {commkit-3.4.0 → commkit-3.5.0}/tests/mapping/test_bits.py +0 -0
  289. {commkit-3.4.0 → commkit-3.5.0}/tests/mapping/test_constellation.py +0 -0
  290. {commkit-3.4.0 → commkit-3.5.0}/tests/mapping/test_gray.py +0 -0
  291. {commkit-3.4.0 → commkit-3.5.0}/tests/mapping/test_llr.py +0 -0
  292. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_eye.py +0 -0
  293. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_filter_response.py +0 -0
  294. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_theme.py +0 -0
  295. {commkit-3.4.0 → commkit-3.5.0}/tests/plotting/test_plot_waveform.py +0 -0
  296. {commkit-3.4.0 → commkit-3.5.0}/tests/plugins/__init__.py +0 -0
  297. {commkit-3.4.0 → commkit-3.5.0}/tests/recovery/test_bps.py +0 -0
  298. {commkit-3.4.0 → commkit-3.5.0}/tests/recovery/test_joint.py +0 -0
  299. {commkit-3.4.0 → commkit-3.5.0}/tests/recovery/test_tikhonov.py +0 -0
  300. {commkit-3.4.0 → commkit-3.5.0}/tests/recovery/test_viterbi_viterbi.py +0 -0
  301. {commkit-3.4.0 → commkit-3.5.0}/tests/test_array.py +0 -0
  302. {commkit-3.4.0 → commkit-3.5.0}/tests/test_backend.py +0 -0
  303. {commkit-3.4.0 → commkit-3.5.0}/tests/test_cuda_infra.py +0 -0
  304. {commkit-3.4.0 → commkit-3.5.0}/tests/test_dispersion.py +0 -0
  305. {commkit-3.4.0 → commkit-3.5.0}/tests/test_examples.py +0 -0
  306. {commkit-3.4.0 → commkit-3.5.0}/tests/test_filter_response.py +0 -0
  307. {commkit-3.4.0 → commkit-3.5.0}/tests/test_filtering.py +0 -0
  308. {commkit-3.4.0 → commkit-3.5.0}/tests/test_import_hygiene.py +0 -0
  309. {commkit-3.4.0 → commkit-3.5.0}/tests/test_logger.py +0 -0
  310. {commkit-3.4.0 → commkit-3.5.0}/tests/test_math.py +0 -0
  311. {commkit-3.4.0 → commkit-3.5.0}/tests/test_multirate.py +0 -0
  312. {commkit-3.4.0 → commkit-3.5.0}/tests/test_smoothing.py +0 -0
  313. {commkit-3.4.0 → commkit-3.5.0}/tests/test_spectral.py +0 -0
  314. {commkit-3.4.0 → commkit-3.5.0}/tests/test_working_memory.py +0 -0
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="17 25 256 256" role="img" aria-labelledby="title desc"><title id="title">CommKit symbol</title><desc id="desc">A hexagon containing equal-width rectangular and sine wave cycles. Transparent vector artwork.</desc><defs><linearGradient id="icon-ink" x1="35" y1="40" x2="250" y2="250" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fca50a" /><stop offset=".5" stop-color="#ed6925" /><stop offset="1" stop-color="#b53657" /></linearGradient><mask id="signal-cutout" maskUnits="userSpaceOnUse" x="20" y="20" width="260" height="260"><rect x="20" y="20" width="260" height="260" fill="white" /><path d="M20 193 H64 V113 H118 V193 H145 C154 193 163 173.944 172 153 C181 132.056 190 113 199 113 C208 113 217 132.056 226 153 C235 173.944 244 193 253 193 H275" fill="none" stroke="black" stroke-width="12" stroke-linejoin="round" stroke-linecap="round" /></mask></defs><g id="CommKit-symbol"><path d="M145 28 L253 90 V216 L145 278 L37 216 V90 Z" fill="url(#icon-ink)" mask="url(#signal-cutout)" /></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1365" height="306" viewBox="0 0 1365 306" role="img" aria-labelledby="title desc"><title id="title">CommKit — digital to waveform</title><desc id="desc">CommKit signal logo. Exactly half of the hexagon width contains one rectangular pulse cycle; the other half contains one smooth sinusoidal cycle of equal amplitude and width. Plain Roboto Black vector wordmark in Inferno amber-to-purple. Transparent background.</desc><defs><linearGradient id="ink" x1="0" y1="0" x2="1257" y2="0" gradientUnits="userSpaceOnUse"><stop offset="0.000" stop-color="#fb9b06" /><stop offset="0.050" stop-color="#fa9207" /><stop offset="0.100" stop-color="#f8890c" /><stop offset="0.150" stop-color="#f68013" /><stop offset="0.200" stop-color="#f37819" /><stop offset="0.250" stop-color="#f06f20" /><stop offset="0.300" stop-color="#eb6628" /><stop offset="0.350" stop-color="#e75e2e" /><stop offset="0.400" stop-color="#e25734" /><stop offset="0.450" stop-color="#dd513a" /><stop offset="0.500" stop-color="#d74b3f" /><stop offset="0.550" stop-color="#d04545" /><stop offset="0.600" stop-color="#ca404a" /><stop offset="0.650" stop-color="#c33b4f" /><stop offset="0.700" stop-color="#bc3754" /><stop offset="0.750" stop-color="#b3325a" /><stop offset="0.800" stop-color="#ab2f5e" /><stop offset="0.850" stop-color="#a32c61" /><stop offset="0.900" stop-color="#9b2964" /><stop offset="0.950" stop-color="#932667" /><stop offset="1.000" stop-color="#8c2369" /></linearGradient><linearGradient id="icon-ink" x1="35" y1="40" x2="250" y2="250" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fca50a" /><stop offset=".5" stop-color="#ed6925" /><stop offset="1" stop-color="#b53657" /></linearGradient><mask id="signal-cutout" maskUnits="userSpaceOnUse" x="20" y="20" width="260" height="260"><rect x="20" y="20" width="260" height="260" fill="white" /><path d="M20 193 H64 V113 H118 V193 H145 C154 193 163 173.944 172 153 C181 132.056 190 113 199 113 C208 113 217 132.056 226 153 C235 173.944 244 193 253 193 H275" fill="none" stroke="black" stroke-width="12" stroke-linejoin="round" stroke-linecap="round" /></mask></defs><g id="CommKit-symbol"><path d="M145 28 L253 90 V216 L145 278 L37 216 V90 Z" fill="url(#icon-ink)" mask="url(#signal-cutout)" /></g><g id="CommKit-wordmark" transform="translate(255 18) scale(.88)" fill="url(#ink)"><path d="M 120.79102 36.884766 C 107.14268 36.884766 94.7305 39.308148 83.554688 44.154297 C 72.378875 49.000446 62.81114 55.998142 54.849609 65.146484 C 46.888079 74.294827 40.755319 85.371472 36.453125 98.376953 C 32.150931 111.38243 30 125.99508 30 142.21484 L 30 153.93359 C 30 170.15336 32.051859 184.74123 36.15625 197.69727 C 40.260641 210.6533 46.244792 221.6804 54.107422 230.7793 C 61.970051 239.87819 71.562554 246.85112 82.886719 251.69727 C 94.210883 256.54341 107.09366 258.9668 121.5332 258.9668 C 139.33538 258.9668 154.7882 255.77755 167.89258 249.39844 C 180.99696 243.01932 191.25821 234.09361 198.67578 222.62109 C 206.09336 211.14858 210.14754 197.89623 210.83984 182.86328 L 158.91797 182.86328 C 158.72017 190.97316 157.13695 197.6241 154.16992 202.81641 C 151.20289 208.00871 147.0001 211.86474 141.56055 214.38672 C 136.12099 216.90869 129.44528 218.16992 121.5332 218.16992 C 114.41233 218.16992 108.40341 216.95823 103.50781 214.53516 C 98.612213 212.11208 94.632337 208.33035 91.566406 203.1875 C 88.500475 198.04465 86.275239 191.41848 84.890625 183.30859 C 83.506011 175.19871 82.8125 165.40611 82.8125 153.93359 L 82.8125 141.91797 C 82.8125 130.44545 83.580316 120.63004 85.113281 112.4707 C 86.646247 104.31137 88.995324 97.658477 92.160156 92.515625 C 95.324988 87.372773 99.280096 83.615812 104.02734 81.242188 C 108.77459 78.868563 114.36245 77.681641 120.79102 77.681641 C 129.98881 77.681641 137.35803 79.06671 142.89648 81.835938 C 148.43494 84.605166 152.48912 88.733651 155.06055 94.222656 C 157.63197 99.711662 159.01704 106.51121 159.21484 114.62109 L 211.13672 114.62109 C 209.85101 99.687043 205.64822 86.360394 198.52734 74.640625 C 191.40647 62.920857 181.36814 53.697924 168.41211 46.972656 C 155.45608 40.247388 139.58221 36.884766 120.79102 36.884766 z " /><path d="M 298.42773 92.515625 C 285.86731 92.515625 274.79066 94.569437 265.19727 98.673828 C 255.60387 102.77822 247.54309 108.48992 241.01562 115.80859 C 234.48816 123.12727 229.54427 131.75576 226.18164 141.69531 C 222.81901 151.63486 221.13672 162.48859 221.13672 174.25781 L 221.13672 177.37305 C 221.13672 189.04336 222.81901 199.84951 226.18164 209.78906 C 229.54427 219.72861 234.48816 228.38188 241.01562 235.75 C 247.54309 243.11812 255.65341 248.82982 265.3457 252.88477 C 275.038 256.93971 286.16418 258.9668 298.72461 258.9668 C 311.28504 258.9668 322.36168 256.93971 331.95508 252.88477 C 341.54848 248.82982 349.60925 243.11812 356.13672 235.75 C 362.66418 228.38188 367.61002 219.72861 370.97266 209.78906 C 374.33529 199.84951 376.01562 189.04336 376.01562 177.37305 L 376.01562 174.25781 C 376.01563 162.48859 374.33529 151.63486 370.97266 141.69531 C 367.61002 131.75576 362.66418 123.12727 356.13672 115.80859 C 349.60925 108.48992 341.52566 102.77822 331.88281 98.673828 C 322.23997 94.569437 311.08706 92.515625 298.42773 92.515625 z M 298.42773 131.08789 C 303.76839 131.08789 308.21886 132.22528 311.7793 134.5 C 315.33973 136.77472 318.15941 139.91443 320.23633 143.91992 C 322.31325 147.92541 323.79739 152.52449 324.6875 157.7168 C 325.57761 162.9091 326.02148 168.42265 326.02148 174.25781 L 326.02148 177.37305 C 326.02148 183.40601 325.57761 189.0434 324.6875 194.28516 C 323.79739 199.52691 322.31325 204.10122 320.23633 208.00781 C 318.15941 211.9144 315.3645 214.95699 311.85352 217.13281 C 308.34253 219.30863 303.96636 220.39648 298.72461 220.39648 C 293.38396 220.39648 288.93348 219.30863 285.37305 217.13281 C 281.81261 214.95699 278.99489 211.9144 276.91797 208.00781 C 274.84105 204.10122 273.35691 199.52691 272.4668 194.28516 C 271.57669 189.0434 271.13281 183.40601 271.13281 177.37305 L 271.13281 174.25781 C 271.13281 168.42265 271.57669 162.9091 272.4668 157.7168 C 273.35691 152.52449 274.84105 147.92541 276.91797 143.91992 C 278.99489 139.91443 281.78784 136.77472 285.29883 134.5 C 288.80981 132.22528 293.18598 131.08789 298.42773 131.08789 z " /><path d="M 480.36719 92.515625 C 470.27929 92.515625 461.40311 94.445595 453.73828 98.302734 C 446.18903 102.10171 439.82175 107.44341 434.62305 114.3125 L 432.89648 95.484375 L 386.01562 95.484375 L 386.01562 256 L 436.01172 256 L 436.01172 144.32031 C 436.41891 143.62939 436.82378 142.93778 437.27148 142.28906 C 439.69456 138.77808 442.63807 136.03271 446.09961 134.05469 C 449.56114 132.07667 453.46672 131.08789 457.81836 131.08789 C 461.9722 131.08789 465.48343 131.68038 468.35156 132.86719 C 471.21969 134.054 473.42016 136.37831 474.95312 139.83984 C 476.48609 143.30138 477.25195 148.44536 477.25195 155.26953 L 477.25195 256 L 527.24805 256 L 527.24805 148.89062 C 527.24805 147.33464 527.17118 145.87431 527.11719 144.38672 C 527.51571 143.67165 527.91582 142.95911 528.35938 142.28906 C 530.68355 138.77808 533.57753 136.03271 537.03906 134.05469 C 540.5006 132.07667 544.60431 131.08789 549.35156 131.08789 C 553.3076 131.08789 556.71976 131.70514 559.58789 132.94141 C 562.45602 134.17767 564.65649 136.50198 566.18945 139.91406 C 567.72242 143.32615 568.48828 148.34629 568.48828 154.97266 L 568.48828 256 L 618.63281 256 L 618.63281 154.97266 C 618.63281 143.30234 617.39635 133.48692 614.92383 125.52539 C 612.4513 117.56386 608.98961 111.15865 604.53906 106.3125 C 600.08852 101.46635 594.79592 97.955119 588.66406 95.779297 C 582.5322 93.603475 575.80696 92.515625 568.48828 92.515625 C 558.40038 92.515625 549.54897 94.445595 541.93359 98.302734 C 534.31822 102.15987 527.9645 107.59912 522.87109 114.62109 C 522.37627 115.30328 521.90415 116.00736 521.43359 116.71289 C 519.502 112.42475 517.16107 108.70282 514.33984 105.64648 C 510.186 101.14649 505.24212 97.83145 499.50586 95.705078 C 493.7696 93.578707 487.38916 92.515625 480.36719 92.515625 z " /><path d="M 722.98438 92.515625 C 712.89647 92.515625 704.01834 94.445595 696.35352 98.302734 C 688.80426 102.10171 682.43698 107.44341 677.23828 114.3125 L 675.51172 95.484375 L 628.63281 95.484375 L 628.63281 256 L 678.62695 256 L 678.62695 144.32031 C 679.03414 143.62939 679.43901 142.93778 679.88672 142.28906 C 682.30979 138.77808 685.25331 136.03271 688.71484 134.05469 C 692.17638 132.07667 696.08195 131.08789 700.43359 131.08789 C 704.58744 131.08789 708.09867 131.68038 710.9668 132.86719 C 713.83493 134.054 716.03539 136.37831 717.56836 139.83984 C 719.10132 143.30138 719.86719 148.44536 719.86719 155.26953 L 719.86719 256 L 769.86328 256 L 769.86328 148.89062 C 769.86328 147.33464 769.78642 145.87431 769.73242 144.38672 C 770.13095 143.67165 770.53106 142.95911 770.97461 142.28906 C 773.29878 138.77808 776.19276 136.03271 779.6543 134.05469 C 783.11583 132.07667 787.21955 131.08789 791.9668 131.08789 C 795.92284 131.08789 799.335 131.70514 802.20312 132.94141 C 805.07125 134.17767 807.27172 136.50198 808.80469 139.91406 C 810.33765 143.32615 811.10352 148.34629 811.10352 154.97266 L 811.10352 256 L 861.24805 256 L 861.24805 154.97266 C 861.24805 143.30234 860.01159 133.48692 857.53906 125.52539 C 855.06654 117.56386 851.60484 111.15865 847.1543 106.3125 C 842.70375 101.46635 837.41116 97.955119 831.2793 95.779297 C 825.14743 93.603475 818.42219 92.515625 811.10352 92.515625 C 801.01561 92.515625 792.16421 94.445595 784.54883 98.302734 C 776.93345 102.15987 770.57973 107.59912 765.48633 114.62109 C 764.9915 115.30328 764.51939 116.00736 764.04883 116.71289 C 762.11723 112.42475 759.77631 108.70282 756.95508 105.64648 C 752.80124 101.14649 747.85735 97.83145 742.12109 95.705078 C 736.38484 93.578707 730.00635 92.515625 722.98438 92.515625 z " /><path d="M 871.24805 40 L 871.24805 256 L 923.31836 256 L 923.31836 198.98242 L 944.62891 175.66992 L 990.66992 256 L 1052.2363 256 L 979.33594 135.39062 L 1052.2363 40 L 988 40 L 941.41797 107.79688 L 923.31836 135.24609 L 923.31836 40 L 871.24805 40 z " /><path d="M 1089.9785 29.763672 C 1081.7697 29.763672 1075.094 32.038445 1069.9512 36.587891 C 1064.8083 41.137337 1062.2363 46.972878 1062.2363 54.09375 C 1062.2363 61.214622 1064.8083 67.050163 1069.9512 71.599609 C 1075.094 76.149055 1081.7697 78.423828 1089.9785 78.423828 C 1098.1873 78.423828 1104.863 76.149055 1110.0059 71.599609 C 1115.1487 67.050163 1117.7207 61.214622 1117.7207 54.09375 C 1117.7207 46.972878 1115.1487 41.137337 1110.0059 36.587891 C 1104.863 32.038445 1098.1873 29.763672 1089.9785 29.763672 z M 1065.2031 95.484375 L 1065.2031 256 L 1115.3457 256 L 1115.3457 95.484375 L 1065.2031 95.484375 z " /><path d="M 1148.0449 55.576172 L 1148.0449 95.484375 L 1127.7207 95.484375 L 1127.7207 130.19727 L 1148.0449 130.19727 L 1148.0449 209.86328 C 1148.0449 221.4347 1150.0225 230.82906 1153.9785 238.04883 C 1157.9346 245.2686 1163.6958 250.56119 1171.2617 253.92383 C 1178.8276 257.28646 1187.9515 258.9668 1198.6328 258.9668 C 1203.8746 258.9668 1208.8184 258.59527 1213.4668 257.85352 C 1218.1151 257.11176 1222.5656 256.04868 1226.8184 254.66406 L 1226.8184 218.91211 C 1225.137 219.20881 1223.3576 219.43173 1221.4785 219.58008 C 1219.5994 219.72843 1217.2256 219.80273 1214.3574 219.80273 C 1210.3025 219.80273 1207.0637 219.33214 1204.6406 218.39258 C 1202.2176 217.45302 1200.5105 215.82222 1199.5215 213.49805 C 1198.5325 211.17387 1198.0391 207.88556 1198.0391 203.63281 L 1198.0391 130.19727 L 1224.4453 130.19727 L 1224.4453 95.484375 L 1198.0391 95.484375 L 1198.0391 55.576172 L 1148.0449 55.576172 z " /></g></svg>
@@ -126,7 +126,7 @@ jobs:
126
126
  - name: Kernel coverage report
127
127
  run: >-
128
128
  uv run coverage report --show-missing --fail-under=85
129
- --include="commkit/equalization/_kernels_numba.py,commkit/equalization/_numba_loops.py,commkit/equalization/sequential/*,commkit/frequency.py,commkit/recovery/*,commkit/coding/ldpc.py,commkit/coding/shaping.py,commkit/coding/polar.py,commkit/coding/convolutional.py,commkit/coding/turbo.py"
129
+ --include="commkit/equalization/_numba_loops.py,commkit/equalization/_sequential/*,commkit/frequency.py,commkit/recovery/*,commkit/coding/ldpc.py,commkit/coding/shaping.py,commkit/coding/polar.py,commkit/coding/convolutional.py,commkit/coding/turbo.py"
130
130
 
131
131
  # GPU legs (--device=gpu / --device=all) require CuPy + CUDA and are run
132
132
  # manually or on a self-hosted runner; they are intentionally not part of
@@ -37,10 +37,10 @@ uv run pytest --run-slow # also the long statistical validation
37
37
  uv run pytest tests/equalization/ -k lms # subset
38
38
  uv run pytest --cov=commkit # coverage
39
39
  uv run pytest --device=cpu -p tests.plugins.precision_trace \
40
- --ignore=tests/test_examples.py # precision audit (§5); the suite passes under it
40
+ --ignore=tests/test_examples.py # precision audit (see Numerics); the suite passes under it
41
41
  uv run pytest --device=gpu -p tests.plugins.transfer_trace \
42
- --ignore=tests/test_examples.py # transfer audit (§6); fails on an undocumented transfer
43
- scripts/sanitize.sh # kernels under compute-sanitizer (§6); setup in the script
42
+ --ignore=tests/test_examples.py # transfer audit (see Performance); fails on an undocumented transfer
43
+ scripts/sanitize.sh # kernels under compute-sanitizer (see Performance); setup in the script
44
44
  ```
45
45
 
46
46
  Numba kernel coverage runs the kernel tests with `NUMBA_DISABLE_JIT=1` and reports only the kernel modules; the test selection and the `--include` list are in the `kernel-coverage` job of `.github/workflows/ci.yml`.
@@ -61,7 +61,7 @@ uv run pytest benchmarks/ --benchmark-disable --device=all
61
61
  uv run pytest benchmarks/bench_bps.py --benchmark-only --device=all # timed
62
62
  uv run pytest benchmarks/ --benchmark-only --device=all \
63
63
  --benchmark-compare=0008 --benchmark-storage=file://benchmarks/baselines
64
- uv run python benchmarks/record_baseline.py NAME # record a new baseline (§8)
64
+ uv run python benchmarks/record_baseline.py NAME # record a new baseline (see Benchmarks)
65
65
  ```
66
66
 
67
67
  ---
@@ -150,6 +150,8 @@ Dependencies point downward only:
150
150
  - A size names its unit: `num_symbols`, `num_blocks` (codewords of a FEC code), `info_bits` (a code's information length where it is a parameter), `blocks_per_frame`, `num_variables`, `num_segments`. In `coding`, `length` and `n` mean the codeword length in bits and `k` the information length, nothing else.
151
151
  - A seeded part of a factory takes `<part>_rng` (`payload_rng`), with the semantics of `rng`.
152
152
  - `method=` strings name only a numerical flavor of one algorithm (`method="maxlog" | "exact"`); algorithms are objects.
153
+ - Output scaling has three names: `normalize` (bool) measures the power and rescales to the library's convention; `correct_power` (bool) applies the exact, known gain of a rate change without measuring; `<thing>_normalization` (a string) chooses how coefficients are scaled (`taps_normalization="unit_energy" | "unity_gain"`).
154
+ - A search window is `search_range`, a `(start, stop)` pair in the axis's unit, or `search_band`, a half-width in Hz around a nominal frequency.
153
155
  - Values are in SI units without a suffix (`linewidth` in Hz, `drift_rate` in rad/s, `taus` in s). A result holding one quantity in two units suffixes the SI one (`lags` in samples, `lag_s`). A conventional non-SI unit goes into the name: `_db`, `_dbm`, `_deg`, `_nm`, `_km`, `_ps_nm_km`. Normalized quantities say so (`normalized_bandwidth`). No second name for one quantity in another unit (no `center_frequency_ghz`); `center_wavelength_nm` is a different, derived quantity.
154
156
 
155
157
  ### Docstrings
@@ -158,6 +160,7 @@ Docstrings describe the code as it is; a change in behavior updates them in the
158
160
 
159
161
  - **Summary line** on the line of the opening quotes, one line, ending with a period. Functions: imperative mood (`Apply ...`), or a noun phrase for a function named after what it returns (`evm`, `welch_psd`). Classes and modules: a noun phrase.
160
162
  - **Module docstrings** name what the module holds (`:func:`, `:class:`), then the conventions particular to it (a sign convention, a scaling, a file layout). No marketing adjectives, no history of earlier layouts, no restatement of this file. A private module's summary ends with "(private)" and the body names its users.
163
+ - **Sections by role:** functions and the objects users configure (algorithm objects, codes, pulses, `Constellation`, frames, `Signal`) list their arguments under Parameters. Result classes, the frozen dataclasses a function returns (`*Estimate`, `*Result`, `*Curve`, `FilterResponse`, ...), list their fields under Attributes with the stored types, even when users may build one themselves; the summary then says the constructor takes the same fields.
161
164
  - **Types:** inputs are `array_like`, or `array_like or Signal` where Signal-aware; returned arrays and fields are `ndarray` (on the input's device), `ndarray or Signal` for transforms, `numpy.ndarray` where always on the host. Shapes go in the description in double backticks: ``(C, N)``.
162
165
  - **Plots** return `(fig, ax) or None`, multi-panel plots `(fig, axes) or None` (`None` with `show=True`).
163
166
  - **Defaults:** `name : type, default value`; `name : type, optional` when the default is `None`, with the description saying what `None` does.
@@ -166,10 +169,10 @@ Docstrings describe the code as it is; a change in behavior updates them in the
166
169
  ### Errors and logging
167
170
 
168
171
  - Wrong input raises, with a message naming the argument.
169
- - **No fallbacks for a broken environment.** Code never catches a failure of CuPy, a CUDA kernel (compile, load, launch), a graph capture or another dependency to run a different implementation; the failure raises to the caller. A path kept "just in case" is code no test or user runs. (Dispatch on the *input* is allowed; see §6 Kernel policy.)
172
+ - **No fallbacks for a broken environment.** Code never catches a failure of CuPy, a CUDA kernel (compile, load, launch), a graph capture or another dependency to run a different implementation; the failure raises to the caller. A path kept "just in case" is code no test or user runs. (Dispatch on the *input* is allowed; see the kernel policy in [Performance](#6-performance).)
170
173
  - `logger` is for diagnostics only. Per-channel logging that needs a device-to-host transfer is wrapped in `if logger.isEnabledFor(logging.INFO):`.
171
174
  - **Levels:** `DEBUG` traces what a call is about to do (method, parameters, sizes). `INFO` is one summary per public call of what a user would print next (the values found, the parameters applied, an equalizer's exit MSE, a decoder's failed checks, what `generate` or `io` produced). `WARNING` flags a returned but suspect result (no convergence, a fit outside its valid range, near-zero power, a code with 4-cycles). Value objects and pure helpers do not log.
172
- - `warnings.warn` is used only for `PrecisionWarning` (§5). The library never configures handlers, Matplotlib or warning filters at import time.
175
+ - `warnings.warn` is used only for `PrecisionWarning` (see [Numerics](#5-numerics)). The library never configures handlers, Matplotlib or warning filters at import time.
173
176
 
174
177
  ---
175
178
 
@@ -185,7 +188,7 @@ Docstrings describe the code as it is; a change in behavior updates them in the
185
188
  - RLS keeps `P`, the gain `k` and the regressor buffers in complex128 (in single precision `P` loses positive definiteness and the filter diverges);
186
189
  - LMS/CMA/RDE accumulate dot products and gradient updates in complex128 around complex64 inputs and weights; the block equalizers stay complex64, as their tap sums run inside the FFTs;
187
190
  - sums: metrics compute per element in the input's precision and accumulate in float64.
188
- - complex128 pays only where single-precision rounding accumulates over many FFT passes, as in the fiber solver (6e-4 after 10^4 steps in complex64, 1e-12 in complex128); there the GPU runs its plain CuPy stages, not the fused complex64 kernels.
191
+ - complex128 pays only where single-precision rounding accumulates over many FFT passes, as in the fiber solver; there the GPU runs its plain CuPy stages, not the fused complex64 kernels.
189
192
  - **The NEP 50 trap:** under NumPy 2 a NumPy scalar is not weak, so `np.float64(a) * x64` (any `np.sqrt`, `np.pi * ...` result, or a float64 array such as `xp.fft.fftfreq`) promotes complex64 to complex128. Combine single-precision data only with Python scalars or arrays cast to its precision. Frequency responses (dispersion, delays, Jones matrices) are computed at float64 phase accuracy and cast to the spectrum's precision before the multiply; rotate with `math._derotate`.
190
193
  - **Audit with `tests/plugins/precision_trace.py`** after touching numerics. It lists every float64/complex128 array of sample-rate size that a NumPy path creates from single-precision, integer or bool data or from scratch, with its source line; output dtypes alone hide a compute-in-double-and-cast-back. Every reported site must be one of the deliberate uses above.
191
194
  - **Normalization invariant:** at `sps` samples per symbol, `E[|x|²] = 1/sps`; at symbol rate, `E[|x|²] = 1`. Any rate-changing block applies the exact gain correction.
@@ -201,14 +204,14 @@ Docstrings describe the code as it is; a change in behavior updates them in the
201
204
  | Sequential recursions: LMS/RLS/CMA/RDE, PLL, Tikhonov, cycle slips, the Mengali-Morelli bootstrap, per-codeword decoders on trellises and trees (CCDM, polar SC/SCL, Viterbi, BCJR, turbo, recursive systematic encoding) | Numba `@njit(cache=True, fastmath=True, nogil=True)`, independent rows in `prange`. The equalizers' kernel with inline carrier recovery compiles strict (unwrap, running sums) and calls fast-math tap and distance loops as separate functions (an `inline="always"` helper takes its caller's flags) | CPU; GPU input does one round trip |
202
205
  | Linear recursions: IIR filtering | CPU: Numba without `fastmath`, so double input matches SciPy bit for bit. GPU: `iir` kernel: each block's state from a zero start in parallel, states carried across blocks in two levels (groups, then across groups), blocks filtered again, in double precision | follows the input |
203
206
  | Binary linear algebra of codes: encoding, syndromes, ML-decoding correlations on the GPU, Chase's test patterns | one float32 GEMM per chunk (`coding._gf2.matmul_mod2`), exact below an inner dimension of 2^24, parity in place (CPU) or by one elementwise kernel writing int8 (GPU); small tables cached per code and device (`backend._device_tables`) | follows the input |
204
- | Algebraic decoding (BCH, Reed-Solomon): Berlekamp-Massey, Chien search to the locator's degree, Forney | CPU: Numba `parallel=True` over codewords. GPU: `algebraic_correct`, one thread per codeword in integer table arithmetic, so both agree exactly (a lockstep CuPy version was 12x slower) | follows the input |
205
- | Layered LDPC belief propagation (min-sum, sum-product) | CPU: Numba `parallel=True` over codewords, all iterations inside, no fast-math. GPU: `ldpc_layered`, one block per codeword, rows of a layer in parallel, early stop per codeword; same row order, so min-sum agrees bit for bit (a CuPy version was 7-23x slower) | follows the input |
206
- | Maximum-likelihood decoding: the correlation with all `2^k` codewords, the decision and the per-bit maxima of the max-log soft output | CPU: one Numba pass, `parallel=True` over rows, branch-free selects under fast-math without the no-NaN and no-Inf flags (a GEMM then a separate pass ran 3x slower, its threads competing with BLAS's). GPU: the GEMM per chunk, the per-bit maxima by a CuPy `ReductionKernel` that broadcasts over the codewords instead of building `(rows, codewords, n)`. `soft=False` skips the maxima on both | follows the input |
207
+ | Algebraic decoding (BCH, Reed-Solomon): Berlekamp-Massey, Chien search to the locator's degree, Forney | CPU: Numba `parallel=True` over codewords. GPU: `algebraic_correct`, one thread per codeword in integer table arithmetic, so both agree exactly | follows the input |
208
+ | Layered LDPC belief propagation (min-sum, sum-product) | CPU: Numba `parallel=True` over codewords, all iterations inside, no fast-math. GPU: `ldpc_layered`, one block per codeword, rows of a layer in parallel, early stop per codeword; same row order, so min-sum agrees bit for bit | follows the input |
209
+ | Maximum-likelihood decoding: the correlation with all `2^k` codewords, the decision and the per-bit maxima of the max-log soft output | CPU: one Numba pass, `parallel=True` over rows, branch-free selects under fast-math without the no-NaN and no-Inf flags (not a GEMM then a pass: its threads compete with BLAS's). GPU: the GEMM per chunk, the per-bit maxima by a CuPy `ReductionKernel` that broadcasts over the codewords instead of building `(rows, codewords, n)`. `soft=False` skips the maxima on both | follows the input |
207
210
  | Monte Carlo analysis (EXIT curves, error-rate curves) | the existing encoders, decoders and demapper and vectorized NumPy/CuPy, through the private block functions (no INFO line per batch); closed-form parts are host NumPy on small grids. No kernel of its own | follows `device` |
208
- | Elementwise chains between multi-core FFTs (fiber solver's Kerr and PMD stages) | NumPy: a Numba `parallel=True` pass competes with `scipy.fft`'s threads and measured slower end to end; adopt one only on a paired end-to-end A/B | CPU |
211
+ | Elementwise chains between multi-core FFTs (fiber solver's Kerr and PMD stages) | NumPy: a Numba `parallel=True` pass competes with `scipy.fft`'s threads; adopt one only on a paired end-to-end A/B | CPU |
209
212
  | Other hot spots limited by intermediates, launches or round trips | CUDA C++ via CuPy `RawModule` (`commkit/_cuda/src`) | GPU |
210
213
 
211
- **Numba kernels live at module level** in a private module that a getter imports on first use (`equalization/_numba_loops.py`, `coding/_numba_loops.py`, `mapping/_numba_llr.py`), so `import commkit` does not load Numba and `cache=True` works across processes. A kernel defined inside a function that calls another kernel defined there recompiles in every process (Numba's cache key misses the captured dispatcher); a getter may build a closure that captures only constants (`_get_numba_sos`).
214
+ **Numba kernels live at module level** in a private module (`equalization/_numba_loops.py`, `coding/_numba_loops.py`, `mapping/_numba_llr.py`) that a getter `_get_numba_<name>()`, defined in the module that calls the kernel, imports on first use, so `import commkit` does not load Numba and `cache=True` works across processes. A kernel defined inside a function that calls another kernel defined there recompiles in every process (Numba's cache key misses the captured dispatcher); a getter may build a closure that captures only constants (`_get_numba_sos`).
212
215
 
213
216
  **Host-sync hygiene:**
214
217
 
@@ -237,7 +240,7 @@ Docstrings describe the code as it is; a change in behavior updates them in the
237
240
 
238
241
  - **Fixtures:** use `backend_device`, `xp` and `xpt` from `tests/conftest.py`. Assert with `xpt.assert_allclose(...)` (`numpy.testing` raises on CuPy arrays); cast expectations with `xp.asarray` and reductions with `float(...)`.
239
242
  - **No configuration skips.** The GPU legs skip only when CuPy is not installed, and fail instead under an explicit `--device=gpu`; a broken CuPy fails under any setting. Tests outside the selected run are deselected at collection (`gpu_only`, `cpu_only`, `slow` without `--run-slow`), so a run with CuPy reports no skips. A new test never calls `pytest.skip` for a configuration.
240
- - **Layout mirrors the source:** `tests/<subpackage>/test_<module>.py`, `tests/test_<module>.py` for flat modules. Basenames are globally unique (prepend import mode), hence `channel/test_channel_linear.py`. Split a large file by concern. Shared builders live in `tests/common/` and use the public API.
243
+ - **Layout mirrors the source:** `tests/<subpackage>/test_<module>.py`, `tests/test_<module>.py` for flat modules. Basenames are globally unique (prepend import mode). Split a large file by concern, each part named after its module (`impairments/test_channel_linear.py`, `test_channel_nonlinear.py`). Shared builders live in `tests/common/` and use the public API.
241
244
  - **Contract registry** (`tests/test_api_contracts.py`): every public function has a row, checked generically for array and Signal in/out, device preserved, input not mutated, keyword-only parameters, `TypeError` on unsupported arrays, fact conflicts and return rules. Do not repeat these checks per module.
242
245
  - **Oracles:** sequential kernels are tested against plain-Python references in `tests/common/reference_impl.py`, CUDA kernels against their CPU reference. Kernel tests skip only on the CPU parametrization (`skip_unless_gpu`), so a kernel that fails to compile fails its tests.
243
246
  - **Mathematical meaning:** test documented definitions (a pulse width, a dispersion sign, noise-variance scaling) against independently derived expectations, not only shapes and energies.
@@ -248,83 +251,38 @@ Docstrings describe the code as it is; a change in behavior updates them in the
248
251
  - **Tolerances are derived** (AWGN theory, a Cramér–Rao bound, a Wiener or loop-noise prediction, a binomial interval), and the docstring states the derivation and the measured value. `tests/common/theory.py` holds the closed forms, in NumPy and SciPy only.
249
252
  - **Real channels**: convergence tests use `make_channel_signal` (RRC pulses, ISI, fractional delay, polarization rotation, DGD, AWGN). The repeat-upsampled builders serve plumbing tests only.
250
253
  - **Break the code to check the test**: monkeypatch a plausible wrong result (zeros, a factor of two, the feature off) and confirm the test fails.
251
- - A strengthened test that exposes a library fault is marked `pytest.mark.xfail(strict=True, reason=...)` with the measured numbers and listed in §10; the fix lands in its own commit, which removes the mark.
254
+ - A strengthened test that exposes a library fault is marked `pytest.mark.xfail(strict=True, reason=...)` with the measured numbers; the fix lands in its own commit, which removes the mark.
252
255
  - **Monte Carlo tests** state what their sample bounds (0 failures in 12 frames bounds the FER below 0.22 at 95 %) and check the operating point (the pre-FEC BER against theory). The default run uses a smoke size; a `slow` parametrization repeats it with enough trials to mean something.
253
256
  - **End-to-end chains** in `tests/test_receiver_chain.py` run several impairments and their receiver, scored against the source bits or AWGN theory, each with one correction left out as a failing baseline.
254
257
  - **Warnings are failures**: a WARNING from the `commkit` logger fails the test unless it is marked `allow_warnings` (it provokes a suspect result on purpose) or asserts the log through `caplog`. A WARNING that reports what the caller asked for is a log-level bug, fixed in the library.
255
258
  - **API changes never change expected values.** A signature change only changes how tests call the code; numerical changes land in their own commit with independent validation.
256
- - **Examples** are Jupyter notebooks in `examples/`, committed without outputs (the `nbstripout` filter, §2). `tests/test_examples.py` executes each one, so an API change updates the notebooks in the same commit.
259
+ - **Examples** are Jupyter notebooks in `examples/`, committed without outputs (the `nbstripout` filter, see [Commands](#2-commands)). `tests/test_examples.py` executes each one, so an API change updates the notebooks in the same commit.
257
260
  - They form a course: one topic per notebook, `NN-lowercase-words.ipynb`, in teaching order (signals and DSP, channel and metrics, coding, receiver algorithms, fiber systems, characterization). Each opens with what it covers and links the notebooks it builds on, and ends with a link to the next. A new notebook takes its place in the order and updates `examples/README.md` and its neighbors' links.
258
261
  - Every claim in the text matches what the cells print: run the notebook and read its numbers before committing. Keep each under about 20 s on the CPU.
259
262
  - Plots of hand-computed arrays go through `to_device(x, "cpu")`, so the notebooks run unchanged on the GPU.
260
- - **Coverage** must not drop below the CI floors: 78 % for the package, 85 % for the Numba kernel modules (the `NUMBA_DISABLE_JIT=1` job, §2).
263
+ - **Coverage** must not drop below the CI floors: 78 % for the package, 85 % for the Numba kernel modules (the `NUMBA_DISABLE_JIT=1` job, see [Commands](#2-commands)).
261
264
 
262
265
  ---
263
266
 
264
267
  ## 8. Benchmarks
265
268
 
266
- `benchmarks/` tracks the GPU-relevant hot paths. Baselines are committed under `benchmarks/baselines/`. The reference is `0008` (`v3_1`, the 3.1 state) on the reference machine: RTX 4070 Ti, Ryzen 7 7800X3D, WSL2. Earlier baselines lack later benchmark files; `0002` ran the CPR equalizer and Viterbi-Viterbi benchmarks on workloads that did not converge, so compare those only from `0003` on.
269
+ `benchmarks/` tracks the GPU-relevant hot paths. Baselines are committed under `benchmarks/baselines/`. The reference is `0008` (`v3_1`) on the reference machine: RTX 4070 Ti, Ryzen 7 7800X3D, WSL2.
267
270
 
268
271
  - **Workloads must converge**, or the benchmark times a failure mode (slip storms, divergence). Every equalizer benchmark asserts its symbol error rate with `benchutils.assert_converged`.
269
272
  - **Workloads** come from `benchmarks/workloads.py` with fixed seeds; never generate data inline.
270
- - **Baselines** are recorded with `benchmarks/record_baseline.py`: each file in its own process, best of `--passes` (default three; raise it when small benchmarks keep outliers, as `0008` did with ten). Never record from a single `pytest benchmarks/` run: small GPU benchmarks after the large equalizer workloads ran several times slower than alone.
273
+ - **Baselines** are recorded with `benchmarks/record_baseline.py`: each file in its own process, best of `--passes` (default three; raise it when small benchmarks keep outliers). Never record from a single `pytest benchmarks/` run: small GPU benchmarks run after the large equalizer workloads are slowed by them.
271
274
  - **IDs** are `[cpu]` or `[gpu]`, meaning the input device.
272
275
  - **Timing:** timed bodies end with the `sync` fixture, or GPU timings measure launches. Each benchmark has one warmup round (compilation, pool growth), and a session fixture warms Numba's thread pool before the first.
273
276
  - **Tools:** `benchmarks/benchutils.py` provides `CudaEventTimer` and `nvtx_range` for `nsys`. Logging is set to WARNING in `benchmarks/conftest.py`.
274
- - **Trust deltas, not single runs.** Swings of ±20-40 % have been seen under load. Re-run a suspected regression in isolation, or do a paired A/B of at least 7 repetitions, alternating old and new. When even unchanged benchmarks move, time the changed part with `CudaEventTimer` and quote it against the step it sits in.
277
+ - **Trust deltas, not single runs.** Timings swing widely under load. Re-run a suspected regression in isolation, or do a paired A/B of at least 7 repetitions, alternating old and new. When even unchanged benchmarks move, time the changed part with `CudaEventTimer` and quote it against the step it sits in.
275
278
  - A commit touching a hot path quotes its delta against `0008`. Tolerance is 5 % on CPU and 10 % on GPU.
276
279
 
277
280
  ---
278
281
 
279
282
  ## 9. Release
280
283
 
281
- 1. On `main`: the CPU and GPU suites pass with no failures or skips, slow validation included (`uv run pytest -rs --run-slow`; strict xfails, if any, are listed in §10); `scripts/sanitize.sh` is clean if a kernel changed; `uv build` succeeds and `uv run --with twine twine check dist/*` passes.
284
+ 1. On `main`: the CPU and GPU suites pass with no failures or skips, slow validation included (`uv run pytest -rs --run-slow`; the only expected failures are strict xfails whose reason names a known fault); `scripts/sanitize.sh` is clean if a kernel changed; `uv build` succeeds and `uv run --with twine twine check dist/*` passes.
282
285
  2. `CHANGELOG.md`: a `## [X.Y.Z] - YYYY-MM-DD` section written for users. Changes that may need code updates come first, with how to migrate, then Added, Performance (measured, as a ratio of new to old time), Fixed and Development. Add its compare link at the bottom and commit.
283
286
  3. `uv run bump-my-version bump {patch|minor|major}` commits the new version and tags `vX.Y.Z`.
284
287
  4. `git push origin main --tags`. The ruleset on `main` requires pull requests; repository admins bypass it for these two commits.
285
288
  5. `gh release create vX.Y.Z --title vX.Y.Z --notes-file notes.md` with the changelog section as notes. Publishing the release runs `.github/workflows/publish.yml`, which uploads to PyPI through Trusted Publishing; a pushed tag alone publishes nothing.
286
-
287
- ---
288
-
289
- ## 10. Roadmap and open items
290
-
291
- What is not done yet, in suggested order. Unlike the sections above, this is a to-do list: remove an item in the commit that resolves it, and add one when a known gap is left open.
292
-
293
- ### Switch to Python 3.15 (blocked)
294
-
295
- Goal: require Python 3.15 only, mainly for explicit lazy imports (PEP 810). State checked on 2026-10-23 (uv 0.13.5, CPython 3.15.1):
296
-
297
- - **Blocker: CuPy has no 3.15 wheels.** `cupy-cuda13x` 14.2.0 ships cp310-cp314 only; support is tracked in cupy/cupy#10259, milestone v14.3.0.
298
- - **Blocker: `jupyter_client` fails to import on 3.15**: `jsonutil.py` calls `strptime` with a day and no year, which 3.15 rejects (cpython#70647), so `tests/test_examples.py` fails at collection. Wait for a fixed release; do not work around it in commkit.
299
- - **Ready:** wheels on 3.15 exist for NumPy 2.5.4, SciPy 1.18.1, Numba 0.68.0, Matplotlib 3.11.2, mypy 2.4.0 and the dev tools. The CPU suite has not been run on 3.15.
300
-
301
- Steps, each its own commit (the version switch first, then each refactor):
302
-
303
- 1. **Validate unchanged code** in a 3.15 venv: full CPU+GPU suite with notebooks (`-rs`), benchmark smoke run, kernel-coverage job, precision audit.
304
- 2. **Switch the floor:** `requires-python = ">=3.15"`, classifiers, ruff `target-version`, dependency minimums to the first 3.15 wheels (`cupy-cuda13x[ctk]>=14.3`, `numba>=0.68`, `numpy>=2.5`, `scipy>=1.18`; recheck each); `ci.yml` matrix and jobs and `publish.yml` on 3.15 (keep `locked` and `lowest-direct`); `uv lock`; README and §2. Record a 3.15 baseline, compare it with `0008` by a paired A/B on unchanged code, and make it the reference.
305
- 3. **Lazy imports.** `lazy` is module-level only (not in functions, classes or `try`, not with `*`); confirm on the interpreter.
306
- - Move the function-local imports (`import cupy as cp`, `import numba`, `from . import compiler` in `_cuda`, cycle-breaking imports of `Constellation`, `Signal`, `normalize`) to `lazy import` / `lazy from`; find them with `grep -rnE '^\s{4,}(import|from) ' commkit`.
307
- - CuPy stays optional: every use stays behind `is_cupy_available` / `dispatch`; decide per site whether `backend.py`'s probes stay eager inside `try`.
308
- - Check that a lazy `numba` does not move the import cost to an odd first call, and turn `TYPE_CHECKING` blocks into `lazy from` where the name is useful at run time.
309
- - Measure with `benchmarks/bench_import.py`; keep `tests/test_import_hygiene.py` passing and extend it to assert that `import commkit` loads neither CuPy nor Matplotlib, if that becomes true.
310
- 4. **Other cleanups** (verify each against What's New in 3.14 and 3.15): drop `from __future__ import annotations` (PEP 649/749; check nothing reads `__annotations__` as strings); check `open()` without `encoding=` under default UTF-8 mode (PEP 686); grep for `strptime` with a day and no year; try the sampling profiler (PEP 799) on the CPU hot paths and mention it in §8 if useful.
311
-
312
- ### Channel coding
313
-
314
- 1. **oFEC** (OpenROADM, ITU-T G.709.3) is not implemented: its block structure is specified in OpenROADM MSA documents that were not available in a form to implement from. It would build on `BCHCode` (extended BCH(256, 239)), soft-output `Chase` and the staircase decoder's windowed iteration.
315
- 2. **NR rate matching for polar codes** (sub-block interleaving, circular buffer, puncturing and shortening with their frozen-set rules, parity-check bits) and **LTE rate matching for turbo codes** are not included: `PolarCode` and `TurboCode` are the mother codes; `Punctured` and `Shortened` cover generic rate matching.
316
-
317
- ### Test suite
318
-
319
- - **Standard tables against the standards.** The NR polar reliability sequence (TS 38.212 Table 5.3.1.2-1), the LTE QPP interleaver parameters (TS 36.212 Table 5.1.3-3) and the DVB-S2 and PON parity-check address tables are tested against commkit's own tables. They should be compared in full with fixtures under `tests/data/standards/` transcribed from the specifications, each with a provenance header (document, version, table). ETSI's download pages refuse scripted access; the documents have to be supplied.
320
-
321
- ### Nonlinear fiber channel
322
-
323
- Each is an addition that leaves the current API unchanged.
324
-
325
- - **Batched realizations**: a leading axis `(B, 2, N)` (launch-power sweeps, Monte Carlo over seeds) so cuFFT batches them and short records fill the GPU.
326
- - **Adaptive step rules**: a `step_rule=` object (maximum nonlinear phase per step, local-error method) next to the equal `steps_per_span`, which measured 3x more accurate than logarithmic steps on a 32 GBd, 80 km span.
327
- - **WDM helpers**: combining frequency-shifted channels into one wideband field and selecting one after propagation; the solver already handles the wide field (with `dispersion_slope_ps_nm2_km` set).
328
- - **Distributed (Raman) amplification and per-span fiber types** in one call (chaining calls already works: every call speaks launch-relative units).
329
- - **cuFFT callbacks** fusing the linear stage into the transforms (CuPy's support is experimental and compiles with nvcc at run time).
330
- - **Self-steepening and Raman scattering** for ultra-wideband fields.
@@ -4,6 +4,37 @@ Notable changes to CommKit, newest first. Performance figures are from the refer
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [3.5.0] - 2026-11-05
8
+
9
+ One name per concept, finished. A review of the API and the module layout renamed the arguments and result fields that broke the library's naming rules, split or merged the modules that broke its size rules, and fixed the two audit tools that could pass without checking anything. Numerical results do not change.
10
+
11
+ ### Changes that may need code updates
12
+
13
+ Every rename fails loudly with `TypeError` (or `AttributeError` for a field); none changes a result.
14
+
15
+ - `generate` takes `num_symbols` by keyword only, like every other parameter after the constellation: write `generate(c, num_symbols=N, ...)` instead of `generate(c, N, ...)`.
16
+ - `metrics.fer(info_bits=)` replaces `block_length=`, the code's information length as everywhere else in the coding API.
17
+ - Result fields of the laser analyses have descriptive names:
18
+ - `LinewidthEstimate`: `frequencies`, `fm_psd`, `fm_psd_model`, `increment_var`, `delta_phi_var` and `peak_frequency` replace `f`, `S_f`, `S_f_model`, `var`, `dphi_var` and `f_peak`;
19
+ - `DshFmNoisePsd`: `frequencies` and `fm_psd` replace `f` and `S_f`;
20
+ - `FrequencyDrift`: `peak_to_peak` replaces `pp`.
21
+ - `analysis.carrier_phase_trajectory(symbols, ...)` and `equalization.estimate_transfer_function(samples, ...)` rename their first argument (was `y_eq` and `received`); positional calls are unaffected.
22
+ - `recovery.PLL(proportional_gain=, integral_gain=)` replaces `mu=` and `beta=`, the raw loop gains. `normalized_bandwidth` is unchanged.
23
+ - `plotting.plot_error_rate(x_axis="ebn0")` replaces `ebn0=True`, as `plot_psd(x_axis=)` chooses its axis; another value raises `ValueError`.
24
+ - `plot_frequency_drift(reference_amplitude=)` and `plot_carrier_phase_characterization(reference_amplitude=)` replace `amp_ref=`.
25
+ - `plot_constellation` draws no grid.
26
+ - Modules moved; import from the packages as documented and nothing changes. `commkit.impairments.channel` is one module (it was the subpackage `channel.linear` / `channel.nonlinear`); `commkit.plotting.sync` is split into `plotting.timing`, `plotting.frequency` and `plotting.recovery`, and `plot_carrier_phase_decomposition` lives in `plotting.analysis`; `Preamble` is defined in `commkit.core.preamble`; `commkit.equalization.sequential` and `commkit.equalization.blind` are private (`_sequential`, `_block`).
27
+
28
+ ### Fixed
29
+
30
+ - `ErrorRateCurve` and `ExitCurve` document their fields under Attributes, as every other result class does.
31
+
32
+ ### Development
33
+
34
+ - The transfer audit (`tests/plugins/transfer_trace.py`) failed on 3.4.0 for three legitimate copies it did not list (`SingleCarrierFrame.to_signal`, `extract_payload`, `save_npz`); they are documented now. Both audit plugins found commkit by the path fragment `commkit/commkit/`, so in a checkout of another name (a git worktree) they recorded nothing and passed; they now match the installed package's directory.
35
+ - The Numba kernel getters of the equalizers sit in the modules that call them, as in `coding` and `mapping`, and `_kernels_numba.py` is gone.
36
+ - AGENTS.md holds only the rules for changing the code; it gains glossary entries for output scaling (`normalize`, `correct_power`, `*_normalization`) and search windows (`search_range`, `search_band`), and the rule that result classes document their fields under Attributes. The README carries the new logo.
37
+
7
38
  ## [3.4.0] - 2026-11-03
8
39
 
9
40
  Error-rate curves for every code, decoders that say what they checked, and one noise convention for real and complex samples.
@@ -395,7 +426,8 @@ See the [GitHub release](https://github.com/lokgar/commkit/releases/tag/v1.1.0)
395
426
 
396
427
  First release. See the [GitHub release](https://github.com/lokgar/commkit/releases/tag/v1.0.0).
397
428
 
398
- [Unreleased]: https://github.com/lokgar/commkit/compare/v3.4.0...HEAD
429
+ [Unreleased]: https://github.com/lokgar/commkit/compare/v3.5.0...HEAD
430
+ [3.5.0]: https://github.com/lokgar/commkit/compare/v3.4.0...v3.5.0
399
431
  [3.4.0]: https://github.com/lokgar/commkit/compare/v3.3.0...v3.4.0
400
432
  [3.3.0]: https://github.com/lokgar/commkit/compare/v3.2.1...v3.3.0
401
433
  [3.2.1]: https://github.com/lokgar/commkit/compare/v3.2.0...v3.2.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: commkit
3
- Version: 3.4.0
3
+ Version: 3.5.0
4
4
  Summary: A Python library for high-performance digital communications research.
5
5
  Project-URL: Homepage, https://github.com/lokgar/commkit
6
6
  Project-URL: Repository, https://github.com/lokgar/commkit
@@ -34,18 +34,18 @@ Provides-Extra: notebook
34
34
  Requires-Dist: jupyter>=1.1.1; extra == 'notebook'
35
35
  Description-Content-Type: text/markdown
36
36
 
37
- # CommKit
37
+ <p align="center">
38
+ <img src="https://raw.githubusercontent.com/lokgar/commkit/main/.github/logo.svg" alt="CommKit" width="520">
39
+ </p>
38
40
 
39
- **Digital-communications research kit for Python, on CPU and GPU.**
41
+ <p align="center">Digital communications research kit for Python with CUDA acceleration.</p>
40
42
 
41
- ![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)
42
- ![Backends](https://img.shields.io/badge/backend-NumPy%20%7C%20CuPy-orange)
43
- ![License](https://img.shields.io/badge/license-MIT-green)
44
- ![CUDA](https://img.shields.io/badge/CUDA-13.x-76B900?logo=nvidia)
45
-
46
- CommKit covers the receiver chain of coherent and IM/DD links (waveform generation, channel impairments, synchronization, carrier recovery, adaptive equalization, metrics, laser characterization and plotting) on NumPy or CuPy arrays. Computation runs on the device the data lives on.
47
-
48
- ---
43
+ <p align="center">
44
+ <img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="Python 3.12+">
45
+ <img src="https://img.shields.io/badge/backend-NumPy%20%7C%20CuPy-orange" alt="Backends">
46
+ <img src="https://img.shields.io/badge/license-MIT-green" alt="License">
47
+ <img src="https://img.shields.io/badge/CUDA-13.x-76B900?logo=nvidia" alt="CUDA">
48
+ </p>
49
49
 
50
50
  ## The model
51
51
 
@@ -1,15 +1,15 @@
1
- # CommKit
2
-
3
- **Digital-communications research kit for Python, on CPU and GPU.**
4
-
5
- ![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)
6
- ![Backends](https://img.shields.io/badge/backend-NumPy%20%7C%20CuPy-orange)
7
- ![License](https://img.shields.io/badge/license-MIT-green)
8
- ![CUDA](https://img.shields.io/badge/CUDA-13.x-76B900?logo=nvidia)
9
-
10
- CommKit covers the receiver chain of coherent and IM/DD links (waveform generation, channel impairments, synchronization, carrier recovery, adaptive equalization, metrics, laser characterization and plotting) on NumPy or CuPy arrays. Computation runs on the device the data lives on.
11
-
12
- ---
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/lokgar/commkit/main/.github/logo.svg" alt="CommKit" width="520">
3
+ </p>
4
+
5
+ <p align="center">Digital communications research kit for Python with CUDA acceleration.</p>
6
+
7
+ <p align="center">
8
+ <img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="Python 3.12+">
9
+ <img src="https://img.shields.io/badge/backend-NumPy%20%7C%20CuPy-orange" alt="Backends">
10
+ <img src="https://img.shields.io/badge/license-MIT-green" alt="License">
11
+ <img src="https://img.shields.io/badge/CUDA-13.x-76B900?logo=nvidia" alt="CUDA">
12
+ </p>
13
13
 
14
14
  ## The model
15
15
 
@@ -19,7 +19,7 @@ ROUNDS = dict(rounds=3, warmup_rounds=1, iterations=1)
19
19
  def _plain_signal():
20
20
  return generate(
21
21
  Constellation.qam(16),
22
- 32_768,
22
+ num_symbols=32_768,
23
23
  symbol_rate=1e6,
24
24
  sps=4,
25
25
  pulse=RRC(0.35, span=8),
@@ -126,7 +126,7 @@ def fiber_workload(n_samples: int, seed: int = 0) -> np.ndarray:
126
126
 
127
127
  sig = generate(
128
128
  Constellation.qam(16),
129
- n_samples // 2,
129
+ num_symbols=n_samples // 2,
130
130
  symbol_rate=32e9,
131
131
  sps=2,
132
132
  pulse=RRC(0.1),
@@ -162,7 +162,9 @@ def coded_workload(code, num_codewords: int, esn0_db: float, seed: int = 0):
162
162
  from commkit.mapping import compute_llr
163
163
 
164
164
  c = Constellation.qam(4)
165
- sig = generate(c, num_codewords * code.n // 2, symbol_rate=FS, code=code, rng=seed)
165
+ sig = generate(
166
+ c, num_symbols=num_codewords * code.n // 2, symbol_rate=FS, code=code, rng=seed
167
+ )
166
168
  rx = apply_awgn(sig, esn0_db=esn0_db, rng=seed + 1)
167
169
  llrs = compute_llr(rx, noise_var=10 ** (-esn0_db / 10))
168
170
  return np.asarray(llrs, dtype=np.float32), sig.reference.info_bits
@@ -31,7 +31,7 @@ Matplotlib, change warning filters, or touch the GPU.
31
31
  import importlib
32
32
  from typing import Any
33
33
 
34
- __version__ = "3.4.0"
34
+ __version__ = "3.5.0"
35
35
 
36
36
  from .backend import PrecisionWarning
37
37
  from .core import (
@@ -1,7 +1,7 @@
1
1
  """Synchronization sequences (private).
2
2
 
3
3
  Barker and Zadoff-Chu generators and the per-stream ZC root assignment.
4
- They live below ``core`` so that ``core.frame`` can build preambles without
4
+ They live below ``core`` so that ``core.preamble`` can build preambles without
5
5
  importing a DSP module; ``commkit.timing`` exposes the generators publicly.
6
6
  """
7
7
 
@@ -25,14 +25,14 @@ class FrequencyDrift:
25
25
  ----------
26
26
  df : ndarray
27
27
  Per-sample residual frequency in Hz, on the input's device.
28
- std, pp, max_abs : float or numpy.ndarray
28
+ std, peak_to_peak, max_abs : float or numpy.ndarray
29
29
  Standard deviation, peak-to-peak and largest magnitude of ``df``:
30
30
  floats (SISO) or ``(C,)`` arrays (MIMO).
31
31
  """
32
32
 
33
33
  df: Any
34
34
  std: float | np.ndarray
35
- pp: float | np.ndarray
35
+ peak_to_peak: float | np.ndarray
36
36
  max_abs: float | np.ndarray
37
37
 
38
38
 
@@ -187,6 +187,6 @@ def frequency_drift(
187
187
  return FrequencyDrift(
188
188
  df=df_out,
189
189
  std=to_report_scalar(std, was_1d=was_1d),
190
- pp=to_report_scalar(pp, was_1d=was_1d),
190
+ peak_to_peak=to_report_scalar(pp, was_1d=was_1d),
191
191
  max_abs=to_report_scalar(max_abs, was_1d=was_1d),
192
192
  )
@@ -29,18 +29,18 @@ class DshFmNoisePsd:
29
29
 
30
30
  Attributes
31
31
  ----------
32
- f : ndarray
32
+ frequencies : ndarray
33
33
  One-sided frequency axis in Hz.
34
- S_f : ndarray
35
- Laser FM-noise PSD in Hz²/Hz (NaN at masked bins), ``(nfreq,)`` or
34
+ fm_psd : ndarray
35
+ Laser FM-noise PSD :math:`S_f` in Hz²/Hz (NaN at masked bins), ``(nfreq,)`` or
36
36
  ``(C, nfreq)``.
37
37
  valid : ndarray
38
38
  Boolean mask ``(nfreq,)`` of trustworthy bins (away from the
39
39
  interferometer's transfer-function notches).
40
40
  """
41
41
 
42
- f: Any
43
- S_f: Any
42
+ frequencies: Any
43
+ fm_psd: Any
44
44
  valid: Any
45
45
 
46
46
 
@@ -321,4 +321,4 @@ def dsh_fm_noise_psd(
321
321
  valid = response >= 4.0 * float(notch_guard)
322
322
  S_laser = xp.where(valid, S_beat / xp.maximum(response, 1e-300), xp.nan)
323
323
 
324
- return DshFmNoisePsd(f=f, S_f=S_laser, valid=valid)
324
+ return DshFmNoisePsd(frequencies=f, fm_psd=S_laser, valid=valid)
@@ -72,7 +72,7 @@ class DshFmPsd:
72
72
  (single-photodiode) capture at its FM detection bandwidth
73
73
  ``min(f_shift, f_s/2 - f_shift)``.
74
74
  notch_guard : float, default 0.1
75
- Masks the bins near the notches of the reported ``S_f`` when the
75
+ Masks the bins near the notches of the reported ``fm_psd`` when the
76
76
  segments resolve the fringes (see :func:`dsh_fm_noise_psd`); the fit
77
77
  uses every bin either way.
78
78
  combine_polarizations : bool, default False
@@ -137,8 +137,8 @@ class DshFmPsd:
137
137
  * The model covers white FM, flicker FM and white detection noise.
138
138
  Other structure in the band (random-walk FM ``∝ 1/f²`` at the lowest
139
139
  bins, fiber acoustic lines, a colored receiver noise) biases the fit;
140
- fence it out with ``f_min`` and ``f_max``, and compare ``S_f`` with
141
- ``S_f_model`` on :func:`commkit.plotting.plot_frequency_noise_psd`.
140
+ fence it out with ``f_min`` and ``f_max``, and compare ``fm_psd`` with
141
+ ``fm_psd_model`` on :func:`commkit.plotting.plot_frequency_noise_psd`.
142
142
  * The detection-noise term assumes additive Gaussian angle noise, that is a
143
143
  beat SNR well above the unwrap threshold (≳ 10 dB in the record's
144
144
  bandwidth). Below it phase slips add a white-FM-like floor.
@@ -468,9 +468,9 @@ def _dsh_fm_psd(samples: ArrayType, method: DshFmPsd, fs: float) -> LinewidthEst
468
468
  value=to_report_scalar(np.pi * theta[:, 0], was_1d=was_1d),
469
469
  method=method,
470
470
  f_shift=f_hat,
471
- f=f_cpu,
472
- S_f=per_channel(S_laser),
473
- S_f_model=per_channel(model),
471
+ frequencies=f_cpu,
472
+ fm_psd=per_channel(S_laser),
473
+ fm_psd_model=per_channel(model),
474
474
  valid=valid,
475
475
  used=per_channel(used2),
476
476
  band=(float(f_used[0]), float(f_used[-1])),
@@ -535,10 +535,10 @@ def _dsh_increment(
535
535
  method=method,
536
536
  f_shift=f_hat,
537
537
  angle_noise_var=to_report_scalar(intercept, was_1d=was_1d),
538
- dphi_var=to_report_scalar(to_device(dphi_var, "cpu"), was_1d=was_1d),
538
+ delta_phi_var=to_report_scalar(to_device(dphi_var, "cpu"), was_1d=was_1d),
539
539
  lags=ls,
540
540
  lag_s=a_sec,
541
- var=var_cpu.T,
541
+ increment_var=var_cpu.T,
542
542
  slope=slope,
543
543
  intercept=intercept,
544
544
  )
@@ -618,7 +618,7 @@ def _dsh_lorentzian(
618
618
  linewidth_3db=to_report_scalar(dnu_3db, was_1d=was_1d),
619
619
  lineshape_ratio=to_report_scalar(ratio, was_1d=was_1d),
620
620
  coherence_factor=to_report_scalar(coh, was_1d=was_1d),
621
- f=f_cpu,
621
+ frequencies=f_cpu,
622
622
  psd=restore_1d(was_1d, P2),
623
- f_peak=to_report_scalar(f_peak, was_1d=was_1d),
623
+ peak_frequency=to_report_scalar(f_peak, was_1d=was_1d),
624
624
  )
@@ -246,10 +246,10 @@ def _increment_slope(
246
246
  return LinewidthEstimate(
247
247
  value=to_report_scalar(np.maximum(slope, 0.0) / (2.0 * np.pi), was_1d=was_1d),
248
248
  method=method,
249
- dphi_var=to_report_scalar(to_device(var1, "cpu"), was_1d=was_1d),
249
+ delta_phi_var=to_report_scalar(to_device(var1, "cpu"), was_1d=was_1d),
250
250
  angle_noise_var=to_report_scalar(intercept, was_1d=was_1d),
251
251
  lag_s=lag_sec,
252
- var=var_k_cpu.T,
252
+ increment_var=var_k_cpu.T,
253
253
  slope=slope,
254
254
  intercept=intercept,
255
255
  )
@@ -295,12 +295,12 @@ def _increment_subtract(
295
295
  return LinewidthEstimate(
296
296
  value=to_report_scalar(to_device(linewidth, "cpu"), was_1d=was_1d),
297
297
  method=method,
298
- dphi_var=to_report_scalar(var1_cpu, was_1d=was_1d),
298
+ delta_phi_var=to_report_scalar(var1_cpu, was_1d=was_1d),
299
299
  angle_noise_var=to_report_scalar(
300
300
  to_device(angle_noise_var, "cpu"), was_1d=was_1d
301
301
  ),
302
302
  lag_s=np.array([t_sym]),
303
- var=np.atleast_1d(var1_cpu)[:, None],
303
+ increment_var=np.atleast_1d(var1_cpu)[:, None],
304
304
  )
305
305
 
306
306
 
@@ -374,8 +374,8 @@ def _beta_separation(
374
374
  linewidth_floor=to_report_scalar(lw_floor_cpu, was_1d=was_1d),
375
375
  num_segments=k_seg,
376
376
  area_hz2=to_report_scalar(area_cpu, was_1d=was_1d),
377
- f=f_cpu,
378
- S_f=S_cpu,
377
+ frequencies=f_cpu,
378
+ fm_psd=S_cpu,
379
379
  beta_line=beta_cpu,
380
380
  above=above_cpu,
381
381
  used=used_cpu,