rfgen.channels

Scientific validation

The channel pipeline transformations and their immutable parameter record have been scientifically validated against published references. See the per-component reports:

Each report covers construct validity, mathematical correctness against cited equations, empirical comparison to published reference numbers, literature grounding, experimental methodology, operating envelope, and documented limitations.

The rfgen.channels module ships the Layer 2 channel-transformation contract: the BaseChannel ABC, the per-call ChannelContext and ChannelRxParams value types, and the Transformation and Group enums. Concrete per-transformation ABCs and their built-in implementations live in three sibling Layer 3 modules:

TorchSig, the external RFML benchmark library, appears only in the opt-in adapter path; see TorchSig Interop.

Module

API page

What it ships

rfgen.tx_impairments

(per-transformation ABCs listed below)

TX-side concretes (DAC, PA, TX phase noise, TX IQ-imbalance, CFO)

rfgen.propagation

Propagation

AWGN and the Sionna-backed propagation skeletons

rfgen.rx_frontend

RX Frontend

RX-side concretes (mixer, IF filter, resampler, LNA noise, ADC, RX phase noise, RX IQ-imbalance, AGC) plus the opt-in TorchSig adapter

The per-device fingerprint store lives in rfgen.device_fingerprint; see the Device Fingerprint reference for FingerprintParams and DeviceRegistry.

This page documents the Layer 2 surface only. The 13 per-transformation ABCs (one per slot, except channel propagation which reuses :class:~rfgen.channels.protocols.BaseChannel indirectly through its propagation base) are listed in the class index with cross-references to their owning module page.

Pipeline model

The pipeline is a sequence of BaseChannel subclasses with one transformation per slot. Each concrete pins its slot via the Transformation class variable; the scene composer reads that variable to dispatch each emitter through the canonical pipeline order.

The 14 transformations split across a pre-sum and a post-sum boundary at the head of RX capture. Pre-sum stages run per-emitter (TX-side) and per-(emitter, RX) pair (propagation); at the combine point, the composer selects the emitter components whose realized_carrier_hz falls within [rx.center_freq_hz +/- rx.bandwidth_hz / 2], sums them, and forwards the result through the post-sum RX-capture and RX-hardware stages.

The emitter plugin’s baseband modulation is outside this pipeline; it is the emitter contract, not a channel transformation. Each emitter carries realized_carrier_hz as absolute Hz in its metadata. Each receiver carries center_freq_hz, bandwidth_hz, sample_rate_hz, and noise_figure_db on its ChannelRxParams instance.

Class index

Class

Kind

Group / Role

BaseChannel

abc

Layer 2 ABC; every concrete transformation inherits from this

ChannelContext

datatype

Per-call context passed to every apply() invocation

ChannelRxParams

datatype

Active receiver RF and hardware parameters

ChannelPipeline

dataclass

Layer 4 validated, ordered chain of BaseChannel transformations

ChannelChainConfig

alias

Alias of ChannelConfig; the config type accepted by ChannelPipeline.from_config

EmptyParams

sentinel

Pydantic model returned from schema() by parameterless transformations

TransformationLogEntry

TypedDict

Schema for one entry of SignalMetadata.transformation_log

FINGERPRINT_PARAM_KEYS

constant

Canonical key tuple consumed from emitter_meta.extras["fingerprint_params"]

Group

enum

IntEnum of the four pipeline groups

Transformation

enum

IntEnum of the 14 named transformations

BaseDACQuantization

abc

TX impairments: DAC quantization (lives in rfgen.tx_impairments)

BasePANonlinearity

abc

TX impairments: PA nonlinearity (lives in rfgen.tx_impairments); concretes RappPA, SalehPA

BaseTXPhaseNoise

abc

TX impairments: TX phase noise (lives in rfgen.tx_impairments); concrete LeesonTXPhaseNoise

BaseTXIQImbalance

abc

TX impairments: TX IQ imbalance (lives in rfgen.tx_impairments); concrete TorchSigTXIQImbalance

BaseCFO

abc

TX impairments: CFO (lives in rfgen.tx_impairments); concrete LinearCFO

BaseChannelPropagation

abc

Channel propagation (lives in rfgen.propagation); concretes AWGNChannel, SionnaRT, SionnaUMa, SionnaUMi, SionnaRMa, SionnaTDL, SionnaCDL

BaseRXMixer

abc

RX capture: RX mixer (lives in rfgen.rx_frontend); concrete LinearRXMixer

BaseIFFilter

abc

RX capture: IF filter (lives in rfgen.rx_frontend); concrete ScipyFIRIFFilter

BaseResampler

abc

RX capture: resampler (lives in rfgen.rx_frontend); concrete ScipyPolyResampler

BaseLNANoise

abc

RX capture: LNA noise (lives in rfgen.rx_frontend); concrete LinearLNANoise

BaseADCQuantization

abc

RX hardware: ADC quantization (lives in rfgen.rx_frontend); concrete LinearADCQuantizer

BaseRXPhaseNoise

abc

RX hardware: RX phase noise (lives in rfgen.rx_frontend); concrete LeesonRXPhaseNoise

BaseRXIQImbalance

abc

RX hardware: RX IQ imbalance (lives in rfgen.rx_frontend); concrete TorchSigRXIQImbalance

BaseAGC

abc

RX hardware: AGC (lives in rfgen.rx_frontend); concrete LinearAGC

For per-class signatures of TX, propagation, and RX concretes, see the TX Impairments, Propagation, and RX Frontend pages.


class rfgen.channels.Group

class Group(IntEnum):
    TX          = 1   # per-emitter TX impairments
    CHANNEL     = 2   # per-(emitter, RX) pair propagation
    RX_CAPTURE  = 3   # per-RX mixing, filtering, resampling, LNA noise
    RX_HARDWARE = 4   # per-RX ADC, phase noise, IQ imbalance, AGC

Pipeline group tag. The leading digit of a Transformation integer is its group; the trailing digit is intra-group order. Group is distinct from Transformation: Group partitions the chain at the pre-sum / post-sum boundary; Transformation names individual operations within a group.

Transformation carries a .group property that returns the matching Group member.


class rfgen.channels.Transformation

class Transformation(IntEnum):
    # Group.TX (10s)
    DAC             = 11
    PA              = 12
    TX_PHASE_NOISE  = 13
    TX_IQ_IMB       = 14
    CFO             = 15

    # Group.CHANNEL (20s)
    PROPAGATION     = 21

    # Group.RX_CAPTURE (30s)
    RX_MIXER        = 31
    IF_FILTER       = 32
    RESAMPLER       = 33
    LNA_NOISE       = 34

    # Group.RX_HARDWARE (40s)
    ADC             = 41
    RX_PHASE_NOISE  = 42
    RX_IQ_IMB       = 43
    AGC             = 44

Integer tag pinned to every concrete channel implementation as a ClassVar[Transformation]. The integer value encodes ordering: value // 10 is the Group integer, value % 10 is the intra-group canonical order. The scene composer reads this tag to dispatch each emitter through the pipeline in monotonic order.

Notes

  • Multiple concrete implementations per transformation are allowed; only one transformation tag per class.

  • Do not define a new class with a Transformation value that does not appear in this enum. Renumbering existing members is a breaking change for the config validator.


class rfgen.channels.ChannelContext

@dataclass(frozen=True, slots=True)
class ChannelContext:
    """Per-call context handed to every BaseChannel.apply() invocation."""

    emitter_meta: SignalMetadata
    rx_params: ChannelRxParams
    scene_id: str
    sample_idx: int
    rng: torch.Generator

Kind. Frozen dataclass / value type.

Carries the per-transformation call context into BaseChannel.apply(). The scene driver constructs one ChannelContext per (emitter, RX, transformation) call; it is not shared across calls.

Fields

Field

Type

Description

emitter_meta

SignalMetadata

Ground-truth metadata for the emitter being transformed. TX-side transformations read device_id, realized_carrier_hz, sample_rate_hz; channel propagation reads realized_carrier_hz for Doppler and path-loss scaling; RX-side transformations read bandwidth_hz and sample_rate_hz.

rx_params

ChannelRxParams

The active receiver’s RF and hardware parameters. Carries center_freq_hz, bandwidth_hz, sample_rate_hz, and noise_figure_db.

scene_id

str

Stable scene identifier, used by transformations to derive deterministic per-scene seeds when needed.

sample_idx

int

Zero-based index of this sample within the current shard. Combined with scene_id for deterministic sub-scene seed derivation.

rng

torch.Generator

The per-call RNG. All randomness inside apply() MUST be drawn from this generator. Each call receives a fresh generator state so calls are independent.

Fingerprint fallback contract

When emitter_meta.extras does NOT contain the "fingerprint_params" slot, transformations that consume per-device priors MUST read defaults from FingerprintParams() (the device-fingerprint Pydantic model instantiated with declared default-prior values, which corresponds to the population-level prior mean). Such transformations MUST emit a transformation_log entry with fallback=True and fallback_reason="missing_fingerprint_params". The byte-for-byte equivalence test in tests/unit/test_channel_protocols.py ties Layer 3 channel implementations to this fallback shape.


class rfgen.channels.ChannelRxParams

@dataclass(frozen=True, slots=True)
class ChannelRxParams:
    """Active receiver RF and hardware parameters."""

    center_freq_hz: float
    bandwidth_hz: float
    sample_rate_hz: float
    noise_figure_db: float
    position_m: tuple[float, float, float] | None = None
    antenna_id: str | None = None
    tag: str | None = None

Kind. Frozen dataclass / value type.

The per-receiver RF and hardware parameters passed through ChannelContext.rx_params. Built by the scene driver from the active ReceiverConfig for each receiver in the scene.

Fields

Field

Type

Required

Default

Description

center_freq_hz

float

yes

Receiver LO frequency in Hz. Used by LinearRXMixer to compute f_lo = emitter.realized_carrier_hz - rx.center_freq_hz.

bandwidth_hz

float

yes

Receiver analog capture bandwidth in Hz. Used by ScipyFIRIFFilter (cutoff design) and LinearLNANoise (kTBF noise power).

sample_rate_hz

float

yes

Receiver ADC sample rate in Hz. Target output rate for ScipyPolyResampler.

noise_figure_db

float

yes

Receiver noise figure in dB, used by LinearLNANoise to compute additive noise power: P_n = k_B * T0 * bandwidth_hz * 10**(noise_figure_db/10).

position_m

tuple[float, float, float] | None

no

None

3D position in scene-frame meters. Consumed by Sionna RT and CDL backends for geometric calculations. None for statistical backends that do not use receiver position.

antenna_id

str | None

no

None

Antenna-pattern identifier. Consumed by Sionna RT and PHY backends for AoA-dependent gain.

tag

str | None

no

None

Human-readable receiver label. The scene composer sets this to ReceiverConfig.rx_id for the active receiver. It is the runtime receiver label threaded through channel calls; in stored multi-RX scene metadata the full receiver catalog is additionally mirrored under SceneMetadata.extras["receivers"].


class rfgen.channels.BaseChannel

class BaseChannel(ABC):
    transformation: ClassVar[Transformation]

    @abstractmethod
    def apply(self, signal: Signal, ctx: ChannelContext) -> Signal: ...

    @abstractmethod
    def schema(self) -> type[BaseModel]: ...

    @classmethod
    def schema_from_init(cls) -> type[BaseModel]: ...

Layer 2 ABC. Every concrete transformation inherits from a per-transformation ABC, which itself inherits from BaseChannel. BaseChannel is the type the scene composer dispatches against.

Class attributes

Attribute

Type

Description

transformation

ClassVar[Transformation]

Identifies which of the 14 named transformations this implementation performs. The ABC enforces at class-definition time via __init_subclass__ that every concrete (non-abstract) subclass sets this to a Transformation enum member; missing or incorrectly-typed values raise TypeError.

Method: apply

@abstractmethod
def apply(self, signal: Signal, ctx: ChannelContext) -> Signal

Applies the transformation to signal and returns a new Signal with updated IQ and metadata. ctx carries the per-call context.

Parameters

Name

Type

Description

signal

Signal

Input IQ plus metadata; shape conventions follow the emitter contract

ctx

ChannelContext

Per-call context: emitter_meta, rx_params, scene_id, sample_idx, rng

Returns

A new Signal with the same IQ shape (unless the transformation changes sample rate) and metadata updated to reflect the applied operation.

Method: schema

@abstractmethod
def schema(self) -> type[BaseModel]

Returns the Pydantic model describing this transformation’s parameters. Subclasses with no parameters return EmptyParams; subclasses with keyword-only __init__ parameters MAY delegate to cls.schema_from_init().

Method: schema_from_init (classmethod, cached)

@classmethod
@functools.cache
def schema_from_init(cls) -> type[BaseModel]

Builds a Pydantic model from the subclass’s __init__ signature. Each keyword argument (excluding self and ctx) becomes a field with the parameter annotation forwarded as the field type and the parameter default forwarded as the field default; parameters without a default become required. Subclasses with no keyword arguments return EmptyParams.

The result is cached per-class via functools.cache, so repeated calls in hot loops are O(1) after the first invocation.

Extension contract

Every subclass of BaseChannel (whether via a per-transformation ABC or directly) MUST satisfy these invariants:

  1. IQ shape. apply() MUST return a Signal whose iq has shape (2, N) where N == signal.iq.shape[-1], with the following exception: BaseResampler implementations MAY return a different N equal to int(round(signal.iq.shape[-1] * ctx.rx_params.sample_rate_hz / signal.metadata.sample_rate_hz)). No other transformation may change the sample count.

  2. No in-place mutation. apply() MUST NOT modify signal.iq or signal.metadata in place. Return a new Signal object; the input must be unchanged after the call.

  3. Metadata update. apply() MUST update the metadata fields that its transformation affects, and SHOULD append a TransformationLogEntry describing the realised parameters.

  4. Randomness source. All randomness MUST be drawn from ctx.rng. Subclasses MUST NOT use module-level random state, random.random(), or torch.rand() without a generator.

  5. transformation ClassVar. Must equal the Transformation enum member identifying this slot. The ABC enforces this at class definition; missing or incorrectly-typed values raise TypeError.

  6. No side effects. apply() MUST NOT perform I/O, network calls, or mutations of shared state. State that persists across calls (e.g., per-device filter kernels) must be stored as instance attributes, not module globals.

Extension points

Method

Status

Notes

apply()

Must override

Core transformation logic; the primary abstract method

schema()

Must override

Return a Pydantic model for config validation; return EmptyParams if no parameters

transformation

Must set as ClassVar

Set to the matching Transformation member at class definition; the ABC enforces this

Notes

  • Do not inherit directly from BaseChannel to add a new transformation implementation. Inherit from the per-transformation ABC for the relevant slot, such as BasePANonlinearity for PA nonlinearity.

  • Concrete-to-concrete inheritance is forbidden per project conventions.


class rfgen.channels.EmptyParams

class EmptyParams(BaseModel):
    model_config = ConfigDict(frozen=True, extra="forbid")

Sentinel Pydantic model returned from BaseChannel.schema() by transformations that take no parameters. The model has no fields, so EmptyParams.model_fields == {} and EmptyParams().model_dump() == {}.


class rfgen.channels.TransformationLogEntry

class TransformationLogEntry(TypedDict):
    name: str
    group: int
    transformation: int
    params: dict[str, object]
    applied_at_iso: str
    fallback: bool
    fallback_reason: str

TypedDict schema for one entry of SignalMetadata.transformation_log. Layer 3 channel implementations append one TransformationLogEntry per applied transformation; audit and replay tooling consumes the log key-by-key.

Keys

Key

Type

Description

name

str

Human-readable transformation name (e.g. "PA", "LinearCFO").

group

int

Group integer (1…4).

transformation

int

Transformation integer.

params

dict[str, object]

Pydantic model_dump() of the realised parameter values for this call.

applied_at_iso

str

ISO-8601 UTC timestamp when the transformation ran.

fallback

bool

True iff the transformation read default fingerprint values because emitter_meta.extras did not carry a "fingerprint_params" slot.

fallback_reason

str

Free-form reason string when fallback is True; empty string otherwise.


ChannelChainConfig

ChannelChainConfig = ChannelConfig

Kind. Module-level alias (not a new class).

ChannelChainConfig is an alias of ChannelConfig, the Layer 2 Pydantic config model that already carries the chain field and its cross-entry invariants. The alias exists so the Layer 4 API surface (ChannelPipeline.from_config(ChannelChainConfig)) has a distinct name without duplicating the config model.

Construct via ChannelConfig directly:

from rfgen.config.channel import ChannelConfig
from rfgen.channel_pipeline import ChannelChainConfig  # same object

assert ChannelChainConfig is ChannelConfig  # True

See ChannelConfig on the Config page for the full field list.


class rfgen.channel_pipeline.ChannelPipeline

@dataclass(frozen=True, slots=True)
class ChannelPipeline:
    chain: tuple[BaseChannel, ...] = ()

    def __init__(self, transformations: Sequence[BaseChannel] = ()) -> None: ...

    @classmethod
    def from_config(cls, config: ChannelChainConfig) -> ChannelPipeline: ...

Kind. Frozen dataclass. Lives in rfgen.channel_pipeline, exported from rfgen.channel_pipeline.__all__.

A validated, ordered chain of BaseChannel transformations. The pipeline carries no DSP code: it holds the BaseChannel instances in canonical pipeline order and exposes the four group-aligned partition properties consumed by the scene composer. Two mutation paths are blocked by the frozen-dataclass contract:

  1. pipeline.chain[i] = other raises TypeError (tuple is immutable).

  2. pipeline.chain = (...) raises dataclasses.FrozenInstanceError (frozen dataclass).

Attributes

Attribute

Type

Description

chain

tuple[BaseChannel, ...]

Validated transformation chain, in canonical pipeline order. Read-only; set once at construction.

Constructor

ChannelPipeline(transformations: Sequence[BaseChannel] = ())

Validates and freezes the transformation chain.

Parameters

Name

Type

Default

Description

transformations

Sequence[BaseChannel]

()

Ordered sequence of BaseChannel instances. An empty sequence is allowed; the scene composer documents which groups it requires.

Raises

ChannelError when any of the following invariants is violated:

Invariant

Trigger

All entries are BaseChannel instances

Any entry fails isinstance(entry, BaseChannel)

Group order is monotonic non-decreasing

An entry’s transformation.group integer is less than the preceding entry’s

Intra-group ordinals are monotonic non-decreasing

Within the same Group, an entry’s transformation.value % 10 is less than the preceding entry’s

At most one Group.CHANNEL entry

More than one propagation transformation appears in the chain

The error message names the offending pair so the configuration author can correct the chain without reading the validator source.

Partition properties

The four properties split chain by Group using the value // 10 rule. Their concatenation reconstructs list(chain):

tx_transforms + ([propagation] if propagation else []) + list(rx_capture) + list(rx_hardware) == list(chain)

Property

Type

Description

tx_transforms

tuple[BaseChannel, ...]

Entries whose transformation.group is Group.TX.

propagation

BaseChannel | None

The single Group.CHANNEL entry, or None if absent.

rx_capture

tuple[BaseChannel, ...]

Entries whose transformation.group is Group.RX_CAPTURE.

rx_hardware

tuple[BaseChannel, ...]

Entries whose transformation.group is Group.RX_HARDWARE.

Dunder methods

Method

Signature

Behavior

__len__

() -> int

Returns len(self.chain).

__iter__

() -> Iterator[BaseChannel]

Yields each BaseChannel in chain order.

__eq__

(other: object) -> bool

Compares pipelines by (transformation, params) per-entry. Two pipelines are equal when they have the same length and each position pairs entries with identical Transformation identifiers and identical schema().model_dump() payloads. Instance identity is not required. Returns NotImplemented when other is not a ChannelPipeline.

__repr__

() -> str

Returns "ChannelPipeline(<n> transformations: <names>)" where <n> is len(chain) and <names> is a comma-separated list of the concrete class names in chain order. An empty chain renders as "ChannelPipeline(0 transformations: )". The contract test asserts that every transformation’s class name appears in the repr.

Method: from_config (classmethod)

@classmethod
def from_config(cls, config: ChannelChainConfig) -> ChannelPipeline

Builds a pipeline by resolving each chain entry through the plugin registry.

Each ChannelChainEntry in config.chain is resolved through an EntryPointRegistry over the rfgen.channels entry-point group. The discovered class is instantiated with the entry’s params mapping as keyword arguments. The resulting instances are then passed through the standard ChannelPipeline validator, so config-time and code-time construction enforce identical invariants.

Parameters

Name

Type

Description

config

ChannelChainConfig

A validated ChannelConfig instance.

Returns

A new ChannelPipeline whose chain contains one BaseChannel instance per config.chain entry.

Raises

Exception

Trigger

ChannelError

Chain-level validation fails after plugin instantiation.

PluginNotFoundError

An entry’s Transformation does not correspond to a registered rfgen.channels plugin.

Validation invariants summary

Invariant

Error type

Error details

All entries are BaseChannel

ChannelError

Names the offending entry index and its actual type.

Group order is monotonic non-decreasing

ChannelError

Names the offending pair and their group labels.

Intra-group ordinals are monotonic non-decreasing

ChannelError

Names the offending pair, transformation names, and values.

At most one Group.CHANNEL entry

ChannelError

Lists all Group.CHANNEL class names found in the chain.

Minimal example

from rfgen.channel_pipeline import ChannelPipeline
from rfgen.tx_impairments import LinearDACQuantizer, LinearCFO
from rfgen.propagation import AWGNChannel
from rfgen.rx_frontend import LinearRXMixer, ScipyFIRIFFilter, LinearADCQuantizer

pipeline = ChannelPipeline(
    transformations=[
        LinearDACQuantizer(),
        LinearCFO(f_offset_hz=100.0),
        AWGNChannel(snr_db=20.0),
        LinearRXMixer(),
        ScipyFIRIFFilter(),
        LinearADCQuantizer(),
    ]
)

print(len(pipeline))           # 6
print(pipeline.tx_transforms)  # (LinearDACQuantizer, LinearCFO)
print(pipeline.propagation)    # AWGNChannel instance
print(repr(pipeline))
# ChannelPipeline(6 transformations: LinearDACQuantizer, LinearCFO, AWGNChannel, LinearRXMixer, ScipyFIRIFFilter, LinearADCQuantizer)

From config:

from rfgen.channel_pipeline import ChannelPipeline, ChannelChainConfig
from rfgen.config.channel import ChannelConfig

cfg = ChannelConfig.model_validate({
    "chain": [
        {"transformation": "DAC", "params": {}},
        {"transformation": "PROPAGATION", "params": {"snr_db": 20.0}},
        {"transformation": "ADC", "params": {}},
    ]
})
pipeline = ChannelPipeline.from_config(cfg)

Per-transformation ABCs

The 13 per-transformation ABCs live alongside their concretes in the three Layer 3 modules listed at the top of this page. Each ABC sets its transformation ClassVar to the matching Transformation member and leaves apply and schema abstract for concrete subclasses to override.

TX impairments (rfgen.tx_impairments)

ABC

Transformation

Concretes shipped

BaseDACQuantization

DAC = 11

LinearDACQuantizer (inline mid-tread uniform quantizer)

BasePANonlinearity

PA = 12

RappPA, SalehPA; helper select_pa_nonlinearity() routes by PAModel

BaseTXPhaseNoise

TX_PHASE_NOISE = 13

LeesonTXPhaseNoise (shared rfgen._leeson synthesizer)

BaseTXIQImbalance

TX_IQ_IMB = 14

TorchSigTXIQImbalance (inline differential I/Q model; see class docstring for Library-First override rationale)

BaseCFO

CFO = 15

LinearCFO (signal * exp(j*2*pi*f0*t))

Channel propagation (rfgen.propagation)

ABC

Transformation

Concretes shipped

BaseChannelPropagation

PROPAGATION = 21

AWGNChannel (default, pure-torch); SionnaRT, SionnaUMa, SionnaUMi, SionnaRMa, SionnaTDL, SionnaCDL (lazy-import skeletons gated behind the rfgen[sionna] extra)

See Propagation for per-class signatures.

RX capture and RX hardware (rfgen.rx_frontend)

ABC

Transformation

Concretes shipped

BaseRXMixer

RX_MIXER = 31

LinearRXMixer

BaseIFFilter

IF_FILTER = 32

ScipyFIRIFFilter

BaseResampler

RESAMPLER = 33

ScipyPolyResampler

BaseLNANoise

LNA_NOISE = 34

LinearLNANoise (pure-torch, no Friis cascade)

BaseADCQuantization

ADC = 41

LinearADCQuantizer (inline mid-tread uniform quantizer)

BaseRXPhaseNoise

RX_PHASE_NOISE = 42

LeesonRXPhaseNoise (shared rfgen._leeson synthesizer)

BaseRXIQImbalance

RX_IQ_IMB = 43

TorchSigRXIQImbalance (inline differential I/Q model)

BaseAGC

AGC = 44

LinearAGC (custom torch loop; documented Library-First gap)

The opt-in TorchSigImpairments adapter applies TorchSig’s bundled impairment chain in one call and registers under Transformation.ADC for book-keeping. See RX Frontend for per-class signatures.


See Also


Anchor aliases (cross-reference compatibility)

The anchors below preserve cross-reference targets from earlier design drafts so existing concept pages resolve without modification. They each resolve to the per-transformation ABC index above or the relevant Layer 3 page.

The old Stage enum is replaced by Group and Transformation. The old per-stage ABCs (BasePropagation, BaseDeviceFingerprint, BaseFrequencyShift, BaseRxFrontend, BaseAwgn, BaseTorchSigTransform) are replaced by the 13 per-transformation ABCs listed in the Class index.

Old concrete class names (AWGN, DeviceFingerprint, FrequencyShift, Impairments, TorchSigImpairments, AnalyticReceiverFrontend, RappPA, SalehPA) belong to the previous 5-stage design. Equivalent functionality ships through the per-transformation concretes documented in TX Impairments, Propagation, and RX Frontend.

Earlier drafts described a ChannelPipeline with a ChainKind flag spanning pre-sum and post-sum partitions. The shipped ChannelPipeline (see above) is a frozen dataclass in rfgen.channel_pipeline with no ChainKind. The ChannelChainConfig alias resolves to ChannelConfig; no ChainKind class exists.

Old Sionna class names with the ...Channel suffix (SionnaUMaChannel, SionnaUMiChannel, SionnaRMaChannel, SionnaTDLChannel, SionnaCDLChannel, SionnaRTChannel) belong to earlier drafts. The shipped names drop the suffix: SionnaRT, SionnaUMa, SionnaUMi, SionnaRMa, SionnaTDL, SionnaCDL. See Propagation for the per-class signatures.