Synthetic channel profiles

Use rfgen.core.profiles.ChannelProfileCatalog when a generation job needs a named, reproducible synthetic channel chain. A profile fixes the order of existing transformations; a sweep resolution records the exact selected synthetic parameters before the job generates scenes. Start with the channel pipeline, then use this page when you need a controlled profile for an ablation or a reproducible generation job.

This API does not create a waveform or a dataset by itself. It resolves and validates a named profile, then writes a durable description of that manual resolution. It is not a SceneConfig selector and does not automatically attach a profile to scene composition. A generation job continues to own its editable channel.chain (or its explicitly constructed ChannelPipeline) under the ordinary scene-composition contract; callers who choose to map a resolved profile into that job own that explicit integration and should retain the profile manifest alongside the job’s normal provenance. It also does not compare generated data with a physical capture or make a sim-to-real claim.

Profiles

The source-tree YAML files live at src/rfgen/data/channel_profiles/<profile>.yaml. Those same files are packaged with rfgen, so resolve() works from an installed wheel without a checkout; pass config_root only to use a deliberate alternate directory.

Profile

Chain

Availability

awgn-baseline

AWGNChannel

Always available; active sweep stage is SNR.

tdl-fading

SionnaTDL

Requires pip install 'rfgen[sionna]'; active sweep stages are TDL model and speed. TDL is a link-level model and needs no deployment topology. No fallback is substituted.

full-chain

RappPALinearCFOAWGNChannelLinearRXMixerLinearADCQuantizer

Always available; active sweep stages are PA, CFO, and SNR.

rayleigh-baseline

RayleighBlockFading

Requires pip install 'rfgen[sionna]'; no sweep dimension is consumed. RayleighBlockFading has a zero-argument constructor: the fading tap has no configurable parameter.

flat-fading-correlated

SionnaFlatFading

Requires pip install 'rfgen[sionna]'; no sweep dimension is consumed. num_fading_blocks (default 16) and correlation (default 0.7, -1.0 < correlation < 1.0) are fixed in the profile’s own chain parameters, not swept.

custom-pdp-baseline

DeclaredPowerDelayProfilePDPRayleighFadingApplyCIR

Requires pip install 'rfgen[sionna]' for the discrete-time CIR conversion; no sweep dimension is consumed. The declared profile (one of "custom_pdp_short_office" or "custom_pdp_long_urban_macro") is fixed in the profile’s own chain parameters, not swept.

Profiles preserve the established TX → propagation → RX order for the stages they include. awgn-baseline, tdl-fading, rayleigh-baseline, flat-fading-correlated, and custom-pdp-baseline are deliberately minimal, propagation-only profiles. full-chain includes TX PA and CFO, AWGN propagation, RX mixing, and ADC quantization in that order. The catalog delegates construction to the registered transformations and ChannelPipeline; it does not reimplement their DSP.

Quick start

from rfgen.core.profiles import ChannelProfileCatalog

resolution = ChannelProfileCatalog.resolve(
    "full-chain",
    dimensions={"snr_db": 10.0, "cfo_hz": 250.0, "pa_p": 2.0, "pa_a": 1.0},
    sample_id="train-000017",
    seed=1337,
)
pipeline = resolution.pipeline
manifest_path = ChannelProfileCatalog.write_manifest(resolution, root="output")

The resulting manifest is written to artifacts/channel-sweeps/<profile>/<shard_id>.json. The write is exclusive: writing that partition again raises FileExistsError rather than overwriting its provenance.

Dimensions and determinism

resolve accepts only these synthetic sweep dimensions. Values outside the listed bounds raise rfgen.core.errors.ValidationError with {code: "channel_sweep_invalid", dimension, value}.

Dimension

Unit

Allowed values

snr_db

dB

−20 through 30 in 2 dB steps

cfo_hz

Hz

−1000 through 1000

pa_p

unitless

strictly positive Rapp smoothness

pa_a

unitless

strictly positive Rapp saturation scale

tdl_model

3GPP profile letter

A, B, C, D, or E

tdl_speed_kmh

km/h

0 through 300

Every manifest records the six bounded dimension values, even where a profile does not consume a value, so that the complete declared sweep coordinate is auditable. The artifact partition key is (profile, dimensions, sample_id, seed). Reusing that complete key yields byte-identical resolved configuration JSON, the same shard_id, and the same resolved_config_sha256; changing the seed gives a distinct artifact identity. The manifest also records the ordered concrete chain names.

tdl-fading resolves through the installed SionnaTDL backend. If that extra is absent, resolution fails before generation with {code: "channel_profile_backend_unavailable", profile: "tdl-fading", missing_extra: "sionna"}. The catalog never replaces TDL with AWGN or a hand-written approximation.

resolution.context_for(context) is a low-level helper for an application that already owns a ChannelContext and directly invokes the established propagation API. It returns a copy whose rt_solver_params carries the resolved StatisticalSolverConfig. The catalog does not add a public scene-composer or pipeline selector for this helper, and it does not make a profile automatically runnable in a generation job.

API

class ChannelProfileCatalog:
    @staticmethod
    def profile_path(profile: str, *, config_root: str | Path | None = None) -> Path: ...

    @classmethod
    def resolve(
        cls,
        profile: str,
        *,
        dimensions: Mapping[str, object] | None = None,
        sample_id: str | int = 0,
        seed: int = 0,
        config_root: str | Path | None = None,
    ) -> ChannelProfileResolution: ...

    @classmethod
    def write_manifest(cls, resolution: ChannelProfileResolution, *, root: str | Path = ".") -> Path: ...

ChannelProfileResolution contains immutable config (the JSON-ready resolved configuration), pipeline (the validated ChannelPipeline), manifest, and an optional typed statistical_solver. It is populated for tdl-fading, rayleigh-baseline, flat-fading-correlated, and custom-pdp-baseline, and None for awgn-baseline and full-chain. Only tdl-fading derives its statistical_solver from swept dimensions (tdl_model, tdl_speed_kmh); the other three populate it from their own fixed profile defaults. Its context_for(context) method is only the explicit low-level context binding described above; it is not a generation-pipeline attachment API. ChannelProfileManifest has exactly profile, seed, chain, dimensions, shard_id, and resolved_config_sha256.

Limits

These profiles are reproducible synthetic scenario settings, not transmitter fingerprints or calibrated receiver measurements. Use the Sionna-backed profiles (tdl-fading, rayleigh-baseline, flat-fading-correlated, custom-pdp-baseline) only with the installed optional dependency and typed statistical-solver context documented for channel propagation. SionnaTDL, RayleighBlockFading, SionnaFlatFading, and the declared-PDP/Rayleigh chain are all geometry-free, link-level statistical models: none requires a 3D site asset or deployment topology. A Sionna-backed profile supplies a link-level fading selection; it does not by itself establish deployment path loss, shadowing, or real-capture fidelity. Site-specific geometry is a separate requirement of ray-traced propagation such as SionnaRT.