commkit 3.1.2__tar.gz → 3.2.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.
- {commkit-3.1.2 → commkit-3.2.0}/AGENTS.md +3 -1
- {commkit-3.1.2 → commkit-3.2.0}/CHANGELOG.md +41 -1
- {commkit-3.1.2 → commkit-3.2.0}/PKG-INFO +4 -4
- {commkit-3.1.2 → commkit-3.2.0}/README.md +3 -3
- {commkit-3.1.2 → commkit-3.2.0}/commkit/__init__.py +1 -1
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/__init__.py +21 -1
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/base.py +23 -1
- commkit-3.2.0/commkit/coding/exit.py +946 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/ldpc.py +3 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/core/frame.py +14 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/impairments/__init__.py +4 -2
- {commkit-3.1.2 → commkit-3.2.0}/commkit/impairments/frontend.py +8 -2
- commkit-3.2.0/commkit/impairments/noise.py +283 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/io.py +3 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/__init__.py +6 -0
- commkit-3.2.0/commkit/plotting/coding.py +362 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/00-getting-started.ipynb +18 -4
- {commkit-3.1.2 → commkit-3.2.0}/examples/06-awgn-and-performance-metrics.ipynb +98 -34
- {commkit-3.1.2 → commkit-3.2.0}/examples/07-channel-coding.ipynb +133 -6
- {commkit-3.1.2 → commkit-3.2.0}/examples/11-frame-synchronization-and-timing.ipynb +5 -5
- {commkit-3.1.2 → commkit-3.2.0}/examples/15-linear-channel-equalization.ipynb +3 -2
- {commkit-3.1.2 → commkit-3.2.0}/examples/16-adaptive-equalization.ipynb +8 -4
- {commkit-3.1.2 → commkit-3.2.0}/examples/22-coherent-transceiver-end-to-end.ipynb +3 -3
- {commkit-3.1.2 → commkit-3.2.0}/examples/26-laser-linewidth-self-homodyne-iq.ipynb +3 -5
- {commkit-3.1.2 → commkit-3.2.0}/examples/README.md +2 -2
- {commkit-3.1.2 → commkit-3.2.0}/pyproject.toml +2 -2
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_coding_base.py +27 -0
- commkit-3.2.0/tests/coding/test_exit.py +258 -0
- commkit-3.2.0/tests/coding/test_ldpc_exit.py +172 -0
- commkit-3.2.0/tests/impairments/test_noise.py +299 -0
- commkit-3.2.0/tests/plotting/test_plot_coding.py +182 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_api_contracts.py +12 -0
- {commkit-3.1.2 → commkit-3.2.0}/uv.lock +1 -1
- commkit-3.1.2/commkit/impairments/noise.py +0 -229
- commkit-3.1.2/tests/impairments/test_noise.py +0 -244
- {commkit-3.1.2 → commkit-3.2.0}/.gitattributes +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/.github/workflows/ci.yml +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/.github/workflows/publish.yml +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/.gitignore +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/.python-version +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/LICENSE +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0002_pre_v2.json +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0003_v2_0.json +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0004_fiber_dbp.json +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0005_gpu_decoder_path.json +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0006_perf_cleanup.json +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0007_v3_0.json +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/baselines/Linux-CPython-3.14-64bit/0008_v3_1.json +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_block_blind.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_block_lms.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_bps.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_coding.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_equalizers.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_fiber.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_filters.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_import.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_llr.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_mapping.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_signal_pipeline.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/bench_sync_misc.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/benchutils.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/conftest.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/record_baseline.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/benchmarks/workloads.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_array.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_circular.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_constants.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/compiler.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/graphs.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/src/algebraic.cu +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/src/bps_anchor.cu +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/src/bps_min_d2.cu +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/src/cs_block.cu +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/src/iir.cu +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/src/ldpc.cu +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/src/llr.cu +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_cuda/src/selftest.cu +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_dispersion.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_fft.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_fiber.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_overlap_save.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_random.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/_sequences.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/_common.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/allan.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/drift.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/fm_noise.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/interferometry.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/linewidth/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/linewidth/dsh.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/linewidth/phase.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/linewidth/result.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/analysis/trajectory.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/backend.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/_galois.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/_gf2.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/_ldpc_tables.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/_numba_loops.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/algebraic.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/convolutional.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/crc.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/interleaving.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/linear.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/polar.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/product.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/ratematch.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/shaping.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/coding/turbo.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/core/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/core/_signal_adapter.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/core/generation.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/core/signal.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/_block/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/_block/_blind.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/_block/_dd.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/_block/_engine.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/_common.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/_kernels_numba.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/_numba_loops.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/blind.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/linear.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/pilots.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/polarization.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/result.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/sequential/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/sequential/_blind.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/sequential/_dd.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/equalization/sequential/_setup.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/filtering/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/filtering/fiber.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/filtering/linear.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/filtering/pulses.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/frequency.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/impairments/channel/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/impairments/channel/linear.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/impairments/channel/nonlinear.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/impairments/source.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/logger.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/mapping/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/mapping/_numba_llr.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/mapping/bits.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/mapping/constellation.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/mapping/gray.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/mapping/llr.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/mapping/shaping.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/math.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/metrics.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/multirate.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/analysis.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/constellation.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/equalizer.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/eye.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/filter_response.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/spectral.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/sync.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/theme.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/plotting/waveform.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/py.typed +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/_common.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/bps.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/carrier_phase.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/corrections.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/pilots.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/pll.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/tikhonov.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/recovery/viterbi_viterbi.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/smoothing.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/spectral.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/commkit/timing.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/01-constellations-and-bit-mapping.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/02-spectral-analysis.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/03-digital-filters.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/04-pulse-shaping-and-matched-filtering.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/05-multirate-and-resampling.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/08-probabilistic-shaping-and-coded-modulation.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/09-laser-phase-noise.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/10-front-end-impairments.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/12-frequency-offset-estimation.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/13-blind-carrier-phase-recovery.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/14-pilot-aided-carrier-recovery.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/17-blind-equalization.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/18-polarization-multiplexing.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/19-chromatic-dispersion.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/20-nonlinear-fiber-and-backpropagation.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/21-fec-in-optical-standards.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/23-carrier-phase-characterization.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/24-laser-linewidth-self-heterodyne.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/25-laser-linewidth-short-delay-and-flicker.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/27-measurement-template-self-heterodyne.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/examples/28-measurement-template-self-homodyne-iq.ipynb +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/analysis/test_allan.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/analysis/test_drift.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/analysis/test_fm_noise.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/analysis/test_interferometry.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/analysis/test_linewidth.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/analysis/test_trajectory.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_algebraic.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_convolutional.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_crc.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_gf2.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_interleaving.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_ldpc.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_ldpc_kernel.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_ldpc_tables.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_linear_codes.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_polar.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_product.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_ratematch.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_shaping.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/coding/test_turbo.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/coding.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/conversions.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/kernel_utils.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/memory.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/metrics.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/periodic.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/reference_impl.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/common/signals.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/conftest.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/core/test_frame.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/core/test_generation.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/core/test_psqam.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/core/test_signal.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/core/test_signal_adapter.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/core/test_signal_mimo.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_blind.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_block.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_bps_kernel.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_cpr.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_cs_kernel.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_equalizer_oracles.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_linear.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_mimo.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_polarization.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_sequential.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_state.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/equalization/test_winit.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/impairments/channel/test_channel_linear.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/impairments/channel/test_channel_nonlinear.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/impairments/test_frontend.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/impairments/test_source.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/mapping/test_bits.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/mapping/test_constellation.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/mapping/test_gray.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/mapping/test_llr.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_analysis.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_constellation.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_equalizer.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_eye.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_filter_response.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_spectral.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_sync.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_theme.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plotting/test_plot_waveform.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plugins/__init__.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plugins/precision_trace.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/plugins/transfer_trace.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/recovery/test_bps.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/recovery/test_corrections.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/recovery/test_joint.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/recovery/test_pilots.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/recovery/test_pll.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/recovery/test_recovery_oracles.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/recovery/test_tikhonov.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/recovery/test_viterbi_viterbi.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_array.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_backend.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_cuda_infra.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_dispersion.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_examples.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_fiber.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_filtering.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_frequency.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_import_hygiene.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_io.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_logger.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_math.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_metrics.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_multirate.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_pulse_shaping.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_signal_pipeline.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_smoothing.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_spectral.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_timing.py +0 -0
- {commkit-3.1.2 → commkit-3.2.0}/tests/test_working_memory.py +0 -0
|
@@ -175,7 +175,7 @@ Dependencies point downward only:
|
|
|
175
175
|
- Never use a global RNG.
|
|
176
176
|
- **Types:** a transform is written `def f(samples: S, ...) -> S` with the TypeVar `S` from `core/_signal_adapter.py` (bound to `np.ndarray | Signal`), so a Signal gives a Signal and an array an array. Do not reassign the `samples` parameter; name the unwrapped array `x`.
|
|
177
177
|
- **Device follows the data.** There are no `backend=` arguments and no global switches. Unsupported array types (JAX, PyTorch) raise `TypeError`.
|
|
178
|
-
- Only factories with no input data to follow (`generate`, `generate_phase_noise`, `Preamble`/`SingleCarrierFrame.to_signal`, `load_npz`) take `device: str = "cpu"`, validated with `require_device()
|
|
178
|
+
- Only factories with no input data to follow (`generate`, `generate_phase_noise`, `Preamble`/`SingleCarrierFrame.to_signal`, `load_npz`, and the Monte Carlo EXIT curves `decoder_exit_curve` and `demapper_exit_curve`) take `device: str = "cpu"`, validated with `require_device()` (in `coding`, which cannot import `core`, by the same check in `coding.exit`). They draw randomness as the rule above says and do the vectorized work (mapping, shaping) on `device`. The default is never "GPU if available".
|
|
179
179
|
- **No `debug_plot`.** Numerical code never imports plotting. Plot functions consume results or recompute through public compute functions.
|
|
180
180
|
- **Design and apply are separate functions**, for example `RRC(...).taps(sps)` and `fir_filter`, or `butterworth_sos` and `iir_filter`.
|
|
181
181
|
|
|
@@ -227,6 +227,7 @@ Docstrings describe the code as it is; a change in behavior updates them in the
|
|
|
227
227
|
- Wrong input raises, with a message naming the argument.
|
|
228
228
|
- **No fallbacks for a broken environment.** Code never catches a failure of CuPy, a CUDA kernel (compile, load, launch), a CUDA-graph capture or any other dependency in order to run a slower or different implementation; the failure raises to the caller. The kernels and graphs are tested on a GPU before every release (§2), a broken CuPy already fails when data moves to the GPU, and a path kept "just in case" is code that no test or user runs. Dispatch on the *input* is different and allowed: a kernel's documented limits (dtype, number of points, phases or channels) may route to the general implementation where that implementation exists anyway (the CPU's), and the dispatch says so where it happens. A GPU-only path that would serve only inputs beyond a kernel's limit is not written; such input raises (`compute_llr` above 16 bits per symbol).
|
|
229
229
|
- `logger` is for diagnostics only. Per-channel logging that needs a device-to-host transfer is wrapped in `if logger.isEnabledFor(logging.INFO):`.
|
|
230
|
+
- **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 a metric or estimator found, the parameters an impairment applied, an equalizer's exit MSE, a decoder's failed checks and iterations, what `generate`, a frame or `io` produced. `WARNING` flags a result that is returned but suspect (no convergence, a fit outside its valid range, a near-zero power, a code with 4-cycles). Value objects and pure helpers (taps, tables, code construction) do not log. `warnings.warn` is used only for `PrecisionWarning`, which callers filter.
|
|
230
231
|
- The library never configures handlers, Matplotlib or warning filters at import time.
|
|
231
232
|
|
|
232
233
|
---
|
|
@@ -263,6 +264,7 @@ Docstrings describe the code as it is; a change in behavior updates them in the
|
|
|
263
264
|
| Binary linear algebra of codes: encoding, syndromes, the correlations of maximum-likelihood decoding, the syndromes of algebraic decoding, Chase's test patterns through a hard decoder | one float32 GEMM per chunk (`coding._gf2.matmul_mod2`: BLAS, cuBLAS), exact below an inner dimension of 2^24, its parity taken in place on the CPU and by one elementwise kernel writing int8 on the GPU; small tables (generators, coset leaders) cached per code object and device (`backend._device_tables`) | follows the input |
|
|
264
265
|
| Algebraic decoding from the syndromes (BCH, Reed-Solomon): Berlekamp-Massey, a Chien search that stops at the locator's degree, Forney at the roots | CPU: Numba `parallel=True` over codewords. GPU: CUDA kernel (`algebraic_correct`), one thread per codeword, the same steps in integer table arithmetic, so both agree exactly (a CuPy version running Berlekamp-Massey in lockstep over the codewords, about 450 launches per decode, was 12x slower on KP4) | follows the input |
|
|
265
266
|
| Iterative decoding of many codewords: layered LDPC belief propagation (min-sum, sum-product) | CPU: Numba `parallel=True` over codewords, all layers and iterations inside, without fast-math. GPU: CUDA kernel (`ldpc_layered`), one thread block per codeword, the rows of a layer in parallel, early stop per codeword inside the kernel; the same rows in the same order on both, so min-sum agrees bit for bit (a CuPy version, about 12 launches per layer, was 7-23x slower) | follows the input |
|
|
267
|
+
| Analysis by Monte Carlo (EXIT curves) | the work is the existing compiled decoders and vectorized NumPy/CuPy (the demapper's distance table in chunks, histograms on the device); the closed-form parts (the `J` table, LDPC node curves, the chart's trajectory) are host NumPy on grids of a few thousand points, about 0.1 s. No kernel of its own: a whole curve takes 0.05-0.3 s on the GPU | follows `device` |
|
|
266
268
|
| Elementwise chains between multi-core FFTs (the fiber solver's Kerr and PMD stages) | NumPy: a Numba `parallel=True` pass there competes with `scipy.fft`'s threads (the solver's Numba passes measured 1.1-1.8x slower end to end, 2^14-2^20); adopt one only on a paired end-to-end A/B | CPU |
|
|
267
269
|
|
|
268
270
|
**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 the disk cache (`cache=True`) keeps them across processes. A kernel defined inside a function that calls another kernel defined there captures that dispatcher in its closure, which Numba's cache key does not reproduce in a new process: it compiled again in every process (3 s for `compute_llr`, 6 s for polar list decoding). A getter may build a kernel in a closure that captures only constants (`_get_numba_sos`).
|
|
@@ -4,6 +4,42 @@ Notable changes to CommKit, newest first. Performance figures are from the refer
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [3.2.0] - 2026-10-30
|
|
8
|
+
|
|
9
|
+
EXIT analysis and coding diagnostics. EXIT charts for any soft-in soft-out component, measured through the existing decoders or the demapper, or in closed form for LDPC codes with their threshold; plots of LLR distributions, parity-check matrices and EXIT charts; and INFO logging in the modules where it was missing. Nothing changes for existing code.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **EXIT analysis** in `commkit.coding.exit`. `ExitCurve` is the transfer curve of one soft-in soft-out component and `exit_chart(first, second)` the `ExitChart` of two, with the decoding trajectory, whether the tunnel is open and where it closes. Curves come from `decoder_exit_curve` (measured through `decode` for any code whose decoder returns a-posteriori LLRs: LDPC, BCJR, Chase), `demapper_exit_curve` (measured, for iterative demapping on AWGN) and `ldpc_exit_curves` (the variable and check nodes of an LDPC code in closed form), with `ldpc_threshold`, the belief-propagation threshold in the Gaussian approximation (0.498 for the DVB-S2 rate-1/2 short code, the NGMI at which simulated QPSK frames start to decode). Measured curves run on the chosen device; the docstrings list the limitations (Gaussian a-priori LLRs, long interleavers, no curve for decoders without soft output such as turbo and polar, early stopping).
|
|
14
|
+
- **Coding plots**: `plot_llr_distribution(llrs, bits)` draws the LLR densities given the transmitted bit and their consistency, `log p(L | 0) / p(L | 1)` against `L`, which shows LLRs from a wrong `noise_var` or demapper model; `plot_parity_check(code)` draws the nonzero entries and node degrees of a parity-check matrix; `plot_exit_chart(chart)` draws an `ExitChart` and marks where a closed tunnel stalls.
|
|
15
|
+
- INFO logging where it was missing: `decode` reports the blocks whose own check failed and the iterations used, `estimate_iq_imbalance` its estimate, and `SingleCarrierFrame.to_signal`, `save_npz` and `load_npz` what they built, saved or loaded. Notebook 00 shows how to turn it on.
|
|
16
|
+
- Notebook 06 checks LLR consistency; notebook 07 predicts the LDPC threshold with an EXIT chart and charts iterative demapping with Gray and natural labels.
|
|
17
|
+
|
|
18
|
+
### Development
|
|
19
|
+
|
|
20
|
+
- AGENTS.md states the logging levels: DEBUG for what a call is about to do, INFO for one summary per public call, WARNING for a returned but suspect result; value objects do not log, and `warnings.warn` is kept for `PrecisionWarning`.
|
|
21
|
+
|
|
22
|
+
## [3.1.3] - 2026-10-30
|
|
23
|
+
|
|
24
|
+
Additive noise without a scaling knob. `apply_awgn` either measures the signal or takes an absolute noise variance, and the OSNR moves to its own function, `apply_ase`.
|
|
25
|
+
|
|
26
|
+
### Changes that may need code updates
|
|
27
|
+
|
|
28
|
+
- **`apply_awgn(signal_power=)` is removed.** Its uses each have a direct replacement:
|
|
29
|
+
- silence or zero padding around the signal: nothing to pass, as Es is now measured as energy per symbol (below);
|
|
30
|
+
- a fixed noise floor, noise referenced to the transmitter, or noise on a dark capture: `noise_var=`, the absolute noise variance per sample. For unit-energy symbols, `noise_var = 10 ** (-esn0_db / 10)` at any `sps`.
|
|
31
|
+
- **`apply_awgn(osnr_db=, reference_bandwidth=, noise_modes=)` is `apply_ase(osnr_db=, reference_bandwidth=, noise_modes=)`.** Same arguments and noise.
|
|
32
|
+
|
|
33
|
+
### Changes that alter results
|
|
34
|
+
|
|
35
|
+
- **`apply_awgn(esn0_db=)` measures Es as energy per symbol**: each channel's energy over the number of symbols the record carries (a Signal's frame length without a zero guard, else its reference's symbol count, else `N / sps`). Zero padding and silence around a frame no longer lower the noise level; without silence the noise is as before. `apply_ase` measures the signal power the same way.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- `apply_awgn(noise_var=)`, an absolute noise variance per sample, scalar or `(C,)`; exactly one of `esn0_db` and `noise_var` is given.
|
|
40
|
+
- `apply_awgn(per_channel=False)` gives every channel one noise level, from the mean symbol energy over channels, as identical receivers with one noise floor; the default gives each channel the requested Es/N0.
|
|
41
|
+
- Notebook 06 shows relative (`esn0_db`) against absolute (`noise_var`) noise.
|
|
42
|
+
|
|
7
43
|
## [3.1.2] - 2026-10-29
|
|
8
44
|
|
|
9
45
|
`apply_awgn` without hidden assumptions about what a channel is: Es/N0 holds per channel, and the OSNR counts the ASE of the modes the medium guides instead of assuming the two polarizations of a single-mode fiber.
|
|
@@ -282,7 +318,11 @@ See the [GitHub release](https://github.com/lokgar/commkit/releases/tag/v1.1.0)
|
|
|
282
318
|
|
|
283
319
|
First release. See the [GitHub release](https://github.com/lokgar/commkit/releases/tag/v1.0.0).
|
|
284
320
|
|
|
285
|
-
[Unreleased]: https://github.com/lokgar/commkit/compare/v3.
|
|
321
|
+
[Unreleased]: https://github.com/lokgar/commkit/compare/v3.2.0...HEAD
|
|
322
|
+
[3.2.0]: https://github.com/lokgar/commkit/compare/v3.1.3...v3.2.0
|
|
323
|
+
[3.1.3]: https://github.com/lokgar/commkit/compare/v3.1.2...v3.1.3
|
|
324
|
+
[3.1.2]: https://github.com/lokgar/commkit/compare/v3.1.1...v3.1.2
|
|
325
|
+
[3.1.1]: https://github.com/lokgar/commkit/compare/v3.1.0...v3.1.1
|
|
286
326
|
[3.1.0]: https://github.com/lokgar/commkit/compare/v3.0.0...v3.1.0
|
|
287
327
|
[3.0.0]: https://github.com/lokgar/commkit/compare/v2.3.0...v3.0.0
|
|
288
328
|
[2.3.0]: https://github.com/lokgar/commkit/compare/v2.2.0...v2.3.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: commkit
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.2.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
|
|
@@ -119,7 +119,7 @@ CommKit never picks a device for you: data stays where you put it, and each func
|
|
|
119
119
|
| [`commkit.filtering`](https://github.com/lokgar/commkit/tree/main/commkit/filtering) | Pulses (`RRC`, `RC`, `Gaussian`, `Rect`, `SmoothRect`), FIR and IIR design (Butterworth, Chebyshev I/II, elliptic, Bessel), `fir_filter`, `iir_filter`, `matched_filter`, overlap-save, chromatic-dispersion compensation and digital backpropagation (`correct_fiber_propagation`). |
|
|
120
120
|
| [`commkit.multirate`](https://github.com/lokgar/commkit/blob/main/commkit/multirate.py) | `resample` (fractional), `decimate`, `upsample`, `decimate_to_symbol_rate`. |
|
|
121
121
|
| [`commkit.spectral`](https://github.com/lokgar/commkit/blob/main/commkit/spectral.py) | Welch PSD, spectrograms, frequency shifting, pilot tones. |
|
|
122
|
-
| [`commkit.impairments`](https://github.com/lokgar/commkit/tree/main/commkit/impairments) | AWGN at an Es/N0 or an OSNR, phase noise, IQ imbalance (blind estimate; Löwdin and Gram-Schmidt correction), chromatic dispersion, PMD and polarization mixing, and nonlinear fiber propagation over amplified spans (split-step Kerr effect with dispersion, loss, PMD and ASE) of a `Fiber`. |
|
|
122
|
+
| [`commkit.impairments`](https://github.com/lokgar/commkit/tree/main/commkit/impairments) | AWGN at an Es/N0 (measured as energy per symbol) or of an absolute variance, ASE at an OSNR (`apply_ase`), phase noise, IQ imbalance (blind estimate; Löwdin and Gram-Schmidt correction), chromatic dispersion, PMD and polarization mixing, and nonlinear fiber propagation over amplified spans (split-step Kerr effect with dispersion, loss, PMD and ASE) of a `Fiber`. |
|
|
123
123
|
| [`commkit.timing`](https://github.com/lokgar/commkit/blob/main/commkit/timing.py) | Barker and Zadoff-Chu sequences, `estimate_timing` / `correct_timing`, fractional delay estimation and correction. |
|
|
124
124
|
| [`commkit.frequency`](https://github.com/lokgar/commkit/blob/main/commkit/frequency.py) | `estimate_frequency_offset` / `correct_frequency_offset` with `MthPower`, `MengaliMorelli`, `PilotSymbols` and `BiasTone`; static and blockwise. |
|
|
125
125
|
| [`commkit.recovery`](https://github.com/lokgar/commkit/tree/main/commkit/recovery) | `estimate_carrier_phase` / `correct_carrier_phase` with `ViterbiViterbi`, `BPS`, `PLL`, `Tikhonov`, `DataAided`, `PilotAided`, `PilotTone(s)`; cycle-slip correction; `resolve_phase_ambiguity` and `resolve_channel_permutation`. |
|
|
@@ -129,8 +129,8 @@ CommKit never picks a device for you: data stays where you put it, and each func
|
|
|
129
129
|
| [`commkit.math`](https://github.com/lokgar/commkit/blob/main/commkit/math.py) | `rms`, `normalize`, dB conversions. |
|
|
130
130
|
| [`commkit.smoothing`](https://github.com/lokgar/commkit/blob/main/commkit/smoothing.py) | Display and estimation smoothers (moving average, Savitzky-Golay, 2-D density). Signal-chain filters are in `filtering`. |
|
|
131
131
|
| [`commkit.io`](https://github.com/lokgar/commkit/blob/main/commkit/io.py) | `save_npz` / `load_npz` for Signals. |
|
|
132
|
-
| [`commkit.plotting`](https://github.com/lokgar/commkit/tree/main/commkit/plotting) | Constellations, eye diagrams, spectra, filter responses, equalizer convergence,
|
|
133
|
-
| [`commkit.coding`](https://github.com/lokgar/commkit/tree/main/commkit/coding) | Channel coding: `encode` / `decode` dispatched on a code object, `LinearBlockCode` (Hamming, extended and shortened), syndrome and maximum-likelihood decoding; `LDPCCode` (DVB-S2, the 802.3ca / 50G-PON code, any parity-check or quasi-cyclic matrix) with layered min-sum and sum-product decoding on the CPU (Numba) and GPU (CUDA); `ReedSolomonCode` (G.709, KR4, KP4, 10G-EPON, XGS-PON) and `BCHCode` with Berlekamp-Massey decoding; Chase-Pyndiah soft decoding; the G.709.2 `StaircaseCode` and `Concatenated` codes (400ZR C-FEC with its exact Hamming(128,119), 802.3dj); `PolarCode` (5G NR information set) with SC and CRC-aided SCL decoding; `ConvolutionalCode` (K = 7, terminated or tail-biting) with Viterbi and BCJR, `TurboCode` (LTE); `CRC` (NR, LTE, Ethernet), `Interleaver`, `Punctured` and `Shortened`; distribution matching (`CCDM`) and probabilistic amplitude shaping (`PAS`). Coded payloads through `generate(..., code=)`. |
|
|
132
|
+
| [`commkit.plotting`](https://github.com/lokgar/commkit/tree/main/commkit/plotting) | Constellations, eye diagrams, spectra, filter responses, equalizer convergence, synchronization and laser diagnostics that draw the estimates, and coding diagnostics: LLR distributions and their consistency, parity-check matrices, EXIT charts. Imported on first use. |
|
|
133
|
+
| [`commkit.coding`](https://github.com/lokgar/commkit/tree/main/commkit/coding) | Channel coding: `encode` / `decode` dispatched on a code object, `LinearBlockCode` (Hamming, extended and shortened), syndrome and maximum-likelihood decoding; `LDPCCode` (DVB-S2, the 802.3ca / 50G-PON code, any parity-check or quasi-cyclic matrix) with layered min-sum and sum-product decoding on the CPU (Numba) and GPU (CUDA); `ReedSolomonCode` (G.709, KR4, KP4, 10G-EPON, XGS-PON) and `BCHCode` with Berlekamp-Massey decoding; Chase-Pyndiah soft decoding; the G.709.2 `StaircaseCode` and `Concatenated` codes (400ZR C-FEC with its exact Hamming(128,119), 802.3dj); `PolarCode` (5G NR information set) with SC and CRC-aided SCL decoding; `ConvolutionalCode` (K = 7, terminated or tail-biting) with Viterbi and BCJR, `TurboCode` (LTE); `CRC` (NR, LTE, Ethernet), `Interleaver`, `Punctured` and `Shortened`; distribution matching (`CCDM`) and probabilistic amplitude shaping (`PAS`); EXIT charts of measured decoder and demapper curves, and of LDPC codes in closed form with their threshold. Coded payloads through `generate(..., code=)`. |
|
|
134
134
|
|
|
135
135
|
Importing `commkit` has no side effects: it configures no logging, Matplotlib or warning filters, and does not touch the GPU.
|
|
136
136
|
|
|
@@ -83,7 +83,7 @@ CommKit never picks a device for you: data stays where you put it, and each func
|
|
|
83
83
|
| [`commkit.filtering`](https://github.com/lokgar/commkit/tree/main/commkit/filtering) | Pulses (`RRC`, `RC`, `Gaussian`, `Rect`, `SmoothRect`), FIR and IIR design (Butterworth, Chebyshev I/II, elliptic, Bessel), `fir_filter`, `iir_filter`, `matched_filter`, overlap-save, chromatic-dispersion compensation and digital backpropagation (`correct_fiber_propagation`). |
|
|
84
84
|
| [`commkit.multirate`](https://github.com/lokgar/commkit/blob/main/commkit/multirate.py) | `resample` (fractional), `decimate`, `upsample`, `decimate_to_symbol_rate`. |
|
|
85
85
|
| [`commkit.spectral`](https://github.com/lokgar/commkit/blob/main/commkit/spectral.py) | Welch PSD, spectrograms, frequency shifting, pilot tones. |
|
|
86
|
-
| [`commkit.impairments`](https://github.com/lokgar/commkit/tree/main/commkit/impairments) | AWGN at an Es/N0 or an OSNR, phase noise, IQ imbalance (blind estimate; Löwdin and Gram-Schmidt correction), chromatic dispersion, PMD and polarization mixing, and nonlinear fiber propagation over amplified spans (split-step Kerr effect with dispersion, loss, PMD and ASE) of a `Fiber`. |
|
|
86
|
+
| [`commkit.impairments`](https://github.com/lokgar/commkit/tree/main/commkit/impairments) | AWGN at an Es/N0 (measured as energy per symbol) or of an absolute variance, ASE at an OSNR (`apply_ase`), phase noise, IQ imbalance (blind estimate; Löwdin and Gram-Schmidt correction), chromatic dispersion, PMD and polarization mixing, and nonlinear fiber propagation over amplified spans (split-step Kerr effect with dispersion, loss, PMD and ASE) of a `Fiber`. |
|
|
87
87
|
| [`commkit.timing`](https://github.com/lokgar/commkit/blob/main/commkit/timing.py) | Barker and Zadoff-Chu sequences, `estimate_timing` / `correct_timing`, fractional delay estimation and correction. |
|
|
88
88
|
| [`commkit.frequency`](https://github.com/lokgar/commkit/blob/main/commkit/frequency.py) | `estimate_frequency_offset` / `correct_frequency_offset` with `MthPower`, `MengaliMorelli`, `PilotSymbols` and `BiasTone`; static and blockwise. |
|
|
89
89
|
| [`commkit.recovery`](https://github.com/lokgar/commkit/tree/main/commkit/recovery) | `estimate_carrier_phase` / `correct_carrier_phase` with `ViterbiViterbi`, `BPS`, `PLL`, `Tikhonov`, `DataAided`, `PilotAided`, `PilotTone(s)`; cycle-slip correction; `resolve_phase_ambiguity` and `resolve_channel_permutation`. |
|
|
@@ -93,8 +93,8 @@ CommKit never picks a device for you: data stays where you put it, and each func
|
|
|
93
93
|
| [`commkit.math`](https://github.com/lokgar/commkit/blob/main/commkit/math.py) | `rms`, `normalize`, dB conversions. |
|
|
94
94
|
| [`commkit.smoothing`](https://github.com/lokgar/commkit/blob/main/commkit/smoothing.py) | Display and estimation smoothers (moving average, Savitzky-Golay, 2-D density). Signal-chain filters are in `filtering`. |
|
|
95
95
|
| [`commkit.io`](https://github.com/lokgar/commkit/blob/main/commkit/io.py) | `save_npz` / `load_npz` for Signals. |
|
|
96
|
-
| [`commkit.plotting`](https://github.com/lokgar/commkit/tree/main/commkit/plotting) | Constellations, eye diagrams, spectra, filter responses, equalizer convergence,
|
|
97
|
-
| [`commkit.coding`](https://github.com/lokgar/commkit/tree/main/commkit/coding) | Channel coding: `encode` / `decode` dispatched on a code object, `LinearBlockCode` (Hamming, extended and shortened), syndrome and maximum-likelihood decoding; `LDPCCode` (DVB-S2, the 802.3ca / 50G-PON code, any parity-check or quasi-cyclic matrix) with layered min-sum and sum-product decoding on the CPU (Numba) and GPU (CUDA); `ReedSolomonCode` (G.709, KR4, KP4, 10G-EPON, XGS-PON) and `BCHCode` with Berlekamp-Massey decoding; Chase-Pyndiah soft decoding; the G.709.2 `StaircaseCode` and `Concatenated` codes (400ZR C-FEC with its exact Hamming(128,119), 802.3dj); `PolarCode` (5G NR information set) with SC and CRC-aided SCL decoding; `ConvolutionalCode` (K = 7, terminated or tail-biting) with Viterbi and BCJR, `TurboCode` (LTE); `CRC` (NR, LTE, Ethernet), `Interleaver`, `Punctured` and `Shortened`; distribution matching (`CCDM`) and probabilistic amplitude shaping (`PAS`). Coded payloads through `generate(..., code=)`. |
|
|
96
|
+
| [`commkit.plotting`](https://github.com/lokgar/commkit/tree/main/commkit/plotting) | Constellations, eye diagrams, spectra, filter responses, equalizer convergence, synchronization and laser diagnostics that draw the estimates, and coding diagnostics: LLR distributions and their consistency, parity-check matrices, EXIT charts. Imported on first use. |
|
|
97
|
+
| [`commkit.coding`](https://github.com/lokgar/commkit/tree/main/commkit/coding) | Channel coding: `encode` / `decode` dispatched on a code object, `LinearBlockCode` (Hamming, extended and shortened), syndrome and maximum-likelihood decoding; `LDPCCode` (DVB-S2, the 802.3ca / 50G-PON code, any parity-check or quasi-cyclic matrix) with layered min-sum and sum-product decoding on the CPU (Numba) and GPU (CUDA); `ReedSolomonCode` (G.709, KR4, KP4, 10G-EPON, XGS-PON) and `BCHCode` with Berlekamp-Massey decoding; Chase-Pyndiah soft decoding; the G.709.2 `StaircaseCode` and `Concatenated` codes (400ZR C-FEC with its exact Hamming(128,119), 802.3dj); `PolarCode` (5G NR information set) with SC and CRC-aided SCL decoding; `ConvolutionalCode` (K = 7, terminated or tail-biting) with Viterbi and BCJR, `TurboCode` (LTE); `CRC` (NR, LTE, Ethernet), `Interleaver`, `Punctured` and `Shortened`; distribution matching (`CCDM`) and probabilistic amplitude shaping (`PAS`); EXIT charts of measured decoder and demapper curves, and of LDPC codes in closed form with their threshold. Coded payloads through `generate(..., code=)`. |
|
|
98
98
|
|
|
99
99
|
Importing `commkit` has no side effects: it configures no logging, Matplotlib or warning filters, and does not touch the GPU.
|
|
100
100
|
|
|
@@ -23,13 +23,26 @@ Codes: :class:`LinearBlockCode` (Hamming), :class:`LDPCCode` (DVB-S2, PON),
|
|
|
23
23
|
:class:`Stages`, :class:`SC`, :class:`SCL`, :class:`Viterbi`, :class:`BCJR`,
|
|
24
24
|
:class:`TurboIterations`. Bit
|
|
25
25
|
permutations: :func:`interleave` and :func:`deinterleave` with an
|
|
26
|
-
:class:`Interleaver`.
|
|
26
|
+
:class:`Interleaver`. EXIT analysis: :func:`exit_chart` of two
|
|
27
|
+
:class:`ExitCurve` objects, from :func:`decoder_exit_curve` (any soft-output
|
|
28
|
+
decoder), :func:`demapper_exit_curve` (iterative demapping) or
|
|
29
|
+
:func:`ldpc_exit_curves` (LDPC nodes, closed form, with
|
|
30
|
+
:func:`ldpc_threshold`).
|
|
27
31
|
"""
|
|
28
32
|
|
|
29
33
|
from .algebraic import BCHCode, BerlekampMassey, ReedSolomonCode
|
|
30
34
|
from .base import DecodeResult, decode, encode
|
|
31
35
|
from .convolutional import BCJR, ConvolutionalCode, Viterbi
|
|
32
36
|
from .crc import CRC
|
|
37
|
+
from .exit import (
|
|
38
|
+
ExitChart,
|
|
39
|
+
ExitCurve,
|
|
40
|
+
decoder_exit_curve,
|
|
41
|
+
demapper_exit_curve,
|
|
42
|
+
exit_chart,
|
|
43
|
+
ldpc_exit_curves,
|
|
44
|
+
ldpc_threshold,
|
|
45
|
+
)
|
|
33
46
|
from .interleaving import Interleaver, deinterleave, interleave
|
|
34
47
|
from .ldpc import LDPCCode, MinSum, SumProduct
|
|
35
48
|
from .linear import Chase, LinearBlockCode, MaximumLikelihood, Syndrome
|
|
@@ -49,6 +62,8 @@ __all__ = [
|
|
|
49
62
|
"Concatenated",
|
|
50
63
|
"ConvolutionalCode",
|
|
51
64
|
"DecodeResult",
|
|
65
|
+
"ExitChart",
|
|
66
|
+
"ExitCurve",
|
|
52
67
|
"HardIterations",
|
|
53
68
|
"Interleaver",
|
|
54
69
|
"LDPCCode",
|
|
@@ -72,5 +87,10 @@ __all__ = [
|
|
|
72
87
|
"decode",
|
|
73
88
|
"deinterleave",
|
|
74
89
|
"encode",
|
|
90
|
+
"decoder_exit_curve",
|
|
91
|
+
"demapper_exit_curve",
|
|
92
|
+
"exit_chart",
|
|
75
93
|
"interleave",
|
|
94
|
+
"ldpc_exit_curves",
|
|
95
|
+
"ldpc_threshold",
|
|
76
96
|
]
|
|
@@ -17,6 +17,7 @@ along the last axis; a block never spans channels.
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import dataclasses
|
|
20
|
+
import logging
|
|
20
21
|
from collections.abc import Callable
|
|
21
22
|
from dataclasses import dataclass
|
|
22
23
|
from typing import Any, NamedTuple
|
|
@@ -24,7 +25,7 @@ from typing import Any, NamedTuple
|
|
|
24
25
|
import numpy as np
|
|
25
26
|
|
|
26
27
|
from .._array import as_2d, restore_1d, validate_array, warn_if_double
|
|
27
|
-
from ..backend import ArrayType, get_array_module
|
|
28
|
+
from ..backend import ArrayType, get_array_module, to_device
|
|
28
29
|
from ..logger import logger
|
|
29
30
|
|
|
30
31
|
__all__ = ["DecodeResult", "decode", "encode"]
|
|
@@ -272,6 +273,26 @@ def encode(bits: ArrayType, *, code: Any) -> ArrayType:
|
|
|
272
273
|
return restore_1d(was_1d, out.reshape(x2.shape[0], num_blocks * code.n))
|
|
273
274
|
|
|
274
275
|
|
|
276
|
+
def _log_decode(res: _Decoded, code: Any, method: Any) -> None:
|
|
277
|
+
"""Log the decoder's own success check and iterations (INFO level)."""
|
|
278
|
+
# Two (R,) transfers, made only when INFO is enabled.
|
|
279
|
+
if not logger.isEnabledFor(logging.INFO) or res.valid.size == 0:
|
|
280
|
+
return
|
|
281
|
+
valid = to_device(res.valid, "cpu")
|
|
282
|
+
iterations = to_device(res.iterations, "cpu")
|
|
283
|
+
failed = int(valid.size - np.count_nonzero(valid))
|
|
284
|
+
most = int(iterations.max())
|
|
285
|
+
used = f", iterations mean {float(iterations.mean()):.1f}, max {most}"
|
|
286
|
+
logger.info(
|
|
287
|
+
"Decoded %d block(s) of %r with %r: %d failed the decoder's check%s.",
|
|
288
|
+
valid.size,
|
|
289
|
+
code,
|
|
290
|
+
method,
|
|
291
|
+
failed,
|
|
292
|
+
used if most > 1 else "",
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
|
|
275
296
|
def decode(llrs: ArrayType, *, code: Any, method: Any = None) -> DecodeResult:
|
|
276
297
|
"""Decode LLRs (or hard decisions) of a code's transmitted bits.
|
|
277
298
|
|
|
@@ -325,6 +346,7 @@ def decode(llrs: ArrayType, *, code: Any, method: Any = None) -> DecodeResult:
|
|
|
325
346
|
return None
|
|
326
347
|
return restore_1d(was_1d, a.reshape(x2.shape[0], num_blocks * size))
|
|
327
348
|
|
|
349
|
+
_log_decode(res, code, method)
|
|
328
350
|
return DecodeResult(
|
|
329
351
|
bits=shaped(res.bits, code.k),
|
|
330
352
|
llrs=shaped(res.llrs, code.n),
|