rfgen.rt_assets

rfgen.rt_assets is the sealed boundary between versioned electromagnetic material or antenna-pattern assets and Sionna RT. It validates immutable asset data, applies only declared interpolation, binds through public Sionna APIs, and records a deterministic assignment receipt. Sionna RT remains responsible for ray tracing and electromagnetic propagation.

The module is not a plugin interface. Applications instantiate RTAssetLibrary, load immutable Pydantic v2 assets, and pass the resulting bindings to a Sionna scene. They do not subclass the library or replace its validation policy.

Public surface

Group

Symbols

Contract

Policies

InterpolationPolicy, ExtrapolationPolicy, MissingMaterialPolicy

Closed StrEnum values: LINEAR, ERROR, and either ERROR or USE_NAMED_DEFAULT.

Material asset

RTMaterialAssetV1

Frozen, extra-forbidden material samples on a strictly increasing frequency grid.

Pattern asset

AntennaPatternAssetV1

Frozen, extra-forbidden complex co-polar and cross-polar angular samples.

Bindings

SionnaMaterialBinding, SionnaPatternBinding

Frozen asset plus the opaque public Sionna object returned at registration.

Assignment receipt

RTAssignmentReportV1

Frozen ordered assignment list and solve provenance.

Service

RTAssetLibrary

Loads assets, preflights material frequency, and performs all-or-nothing scene assignment.

Errors

RTAssetValidationError, BackendUnavailableError

Respectively malformed or unrepresentable asset input, and an absent or incompatible optional Sionna RT API.

Policy enums

InterpolationPolicy.LINEAR is the only supported frequency interpolation. ExtrapolationPolicy.ERROR is the only supported extrapolation behavior. MissingMaterialPolicy.ERROR rejects any scene object without an explicit assignment. MissingMaterialPolicy.USE_NAMED_DEFAULT assigns the registered default_id to every omitted object.

There is no clamp, nearest-neighbor, or implicit-default mode. A caller that needs a solve at a frequency outside an asset grid receives RTAssetValidationError before a scene object changes.

RTMaterialAssetV1

RTMaterialAssetV1 has this constructor contract:

class RTMaterialAssetV1(BaseModel):
    material_id: str
    frequency_hz: tuple[float, ...]
    relative_permittivity: tuple[float, ...]
    conductivity_s_per_m: tuple[float, ...]
    magnetic_permeability: tuple[tuple[float, float], ...] | None = None
    permittivity_std: tuple[float, ...] | None = None
    conductivity_std_s_per_m: tuple[float, ...] | None = None
    correlation_id: str | None = None
    interpolation_policy: InterpolationPolicy = InterpolationPolicy.LINEAR
    extrapolation_policy: ExtrapolationPolicy = ExtrapolationPolicy.ERROR
    source_uri: str
    license_spdx: str
    content_sha256: str
    object_ids: tuple[str, ...] = ()

frequency_hz is a nonempty strictly increasing tuple of finite positive Hz values. The permittivity and conductivity tuples have shape [frequency]; relative permittivity is finite and at least 1, and conductivity is finite and nonnegative in S/m. Optional standard-deviation tuples have the same shape and are finite and nonnegative. content_sha256 is exactly sha256:<64 lowercase hexadecimal characters> and license_spdx must parse as an SPDX expression.

magnetic_permeability, when supplied, has shape [frequency, 2] with [real, imag] values. Every row must be exactly [1.0, 0.0]: public Sionna RadioMaterial represents relative permittivity and conductivity, but not non-unity relative magnetic permeability. Rejecting the unrepresentable input prevents loss of a physical field at the backend boundary.

object_ids is an optional UTF-8-byte-sorted, duplicate-free list of scene object identifiers. It is provenance metadata, not an assignment operation.

at_frequency

def at_frequency(self, frequency_hz: float) -> dict[str, float | complex | None]: ...

Returns linearly interpolated permittivity and conductivity plus optional standard deviations and permeability. Standard deviations interpolate their variance and then take the nonnegative square root. The requested finite Hz value must lie in the closed declared grid interval; otherwise the method raises RTAssetValidationError and returns no partial result.

AntennaPatternAssetV1

class AntennaPatternAssetV1(BaseModel):
    pattern_id: str
    frequency_hz: tuple[float, ...]
    theta_rad: tuple[float, ...]
    phi_rad: tuple[float, ...]
    co_polar: tuple[tuple[tuple[tuple[float, float], ...], ...], ...]
    cross_polar: tuple[tuple[tuple[tuple[float, float], ...], ...], ...]
    gain_std_db: tuple[tuple[tuple[tuple[float, float], ...], ...], ...] | None = None
    phase_std_rad: tuple[tuple[tuple[tuple[float, float], ...], ...], ...] | None = None
    basis: str = "THETA_PHI"
    normalization: str = "REALIZED_GAIN"
    source_uri: str
    license_spdx: str
    content_sha256: str

The strictly increasing theta_rad grid is in [0, pi]; the strictly increasing phi_rad grid is in [-pi, pi). Co-polar and cross-polar samples have shape [frequency, theta, phi, 2]; the final pair stores the real and imaginary components. Optional uncertainty tensors have the same leading three dimensions and a final two-polarization axis, with finite nonnegative values. The only admitted basis and normalization are THETA_PHI and REALIZED_GAIN.

at_frequency(frequency_hz) returns the declared angular grids and complex field tables at one in-grid finite Hz value. Its uncertainty values use the same variance interpolation rule as material assets. It raises RTAssetValidationError outside the declared grid.

Public Sionna pattern boundary

Sionna’s public register_antenna_pattern factory callback receives theta and phi, not a solve frequency. RTAssetLibrary.load_pattern therefore accepts exactly one frequency sample for a bindable table. It performs bilinear angular interpolation, clamps theta to the measured boundary, and uses periodic phi seam interpolation. A multi-frequency table raises BackendUnavailableError; selecting a slice or discarding frequency metadata would be ambiguous.

RTAssetLibrary lifecycle

library = RTAssetLibrary()
material = library.load_material(material_asset)
pattern = library.load_pattern(single_frequency_pattern_asset)
report = library.assign(
    scene,
    {"wall": material.asset.material_id},
    frequency_hz=1_500_000_000.0,
    scene_hash="sha256:" + "b" * 64,
)

RTAssetLibrary(*, rt_module: Any | None = None) optionally accepts an injected Sionna RT module for controlled tests. Without it, the constructor imports sionna.rt lazily only when a binding is requested.

Method

Input

Result and failures

load_material(asset)

RTMaterialAssetV1 or mapping

Parses a strict asset, registers one public RadioMaterial, and returns SionnaMaterialBinding. Duplicate IDs and invalid values raise RTAssetValidationError; missing or incompatible public Sionna APIs raise BackendUnavailableError.

load_pattern(asset)

AntennaPatternAssetV1 or mapping

Registers one singleton-frequency public pattern and returns SionnaPatternBinding. Duplicate IDs, malformed data, or a multi-frequency asset fail closed as described above.

validate_material_frequency(material_id, frequency_hz)

loaded material ID and finite Hz value

Preflights the scalar material grid without mutating a scene. An unloaded ID or out-of-grid frequency raises RTAssetValidationError. Call it before a direct PathSolver use that bypasses assign.

assign(scene, assignments, policy=MissingMaterialPolicy.ERROR, *, frequency_hz, default_id=None, scene_hash, device="cpu", backend="sionna-rt")

mapping from scene object ID to loaded material ID

Validates every input and every requested material frequency before assigning any scene.objects[object_id].radio_material; returns RTAssignmentReportV1.

assign requires a mapping-like public scene.objects map and a sha256:<64 lowercase hexadecimal characters> scene_hash. frequency_hz is required and finite. device and backend are nonempty provenance strings. Object identifiers sort by UTF-8 bytes; the report preserves that order. Unknown scene objects, missing assignments, unloaded material IDs, invalid defaults, and incompatible public radio_material objects fail before the first mutation. The operation is therefore all-or-nothing for validation failures.

Binding and receipt models

SionnaMaterialBinding contains asset: RTMaterialAssetV1 and opaque backend_material: Any. SionnaPatternBinding contains asset: AntennaPatternAssetV1 and opaque backend_pattern: Any. The backend values are intentionally not serialized by rfgen.

RTAssignmentReportV1 contains:

Field

Type

Meaning

assignments

tuple[tuple[str, str], ...]

UTF-8-byte-sorted (object_id, material_id) pairs that were applied.

mapping_sha256

sha256:<hex>

SHA-256 of the compact canonical assignment-pair JSON bytes.

scene_hash

sha256:<hex>

Caller-provided digest of the solved scene bytes.

sionna_version, mitsuba_version

str

Backend versions observed during binding.

device, backend

str

Caller-declared execution provenance.

The receipt proves input-to-backend binding for one solve. It is not a hardware calibration certificate or an assertion of sim-to-real agreement.

Validation boundary

The executable Layer 28 evidence tests strict schema rejection, interpolation, ordering, all-or-nothing assignment, public material binding, singleton pattern registration, free-space loss, PEC reflection, dielectric two-ray reflection, and CPU repeatability. The measurement setup, thresholds, citations, and exclusions live in RT material asset validation.

See Also