Records, Receivers, and Assets¶
Warning
Pre-implementation. This page describes proposed contracts. Class signatures, parameter types, config field names, and behavior are subject to change before code lands. Once implementation exists, content here will be regenerated from docstrings or sourced from running tests.
A scene is the physical situation being generated. A record is the dataset unit consumed by training or evaluation. The relationship between them is shaped by two independent axes: how many transmitters the scene contains, and how many receivers observe it.
Minimal Example¶
Reading a 4-RX dataset in default (PER_RX) mode:
from rfgen.storage import open_store
with open_store("./out/tdoa_4rx") as store:
record = store.read(sample_id="sha256:9af2…")
# Standard single-RX shape (one record per receiver in PER_RX mode)
print(record.iq.shape) # torch.Size([2, 400_000])
print(record.scene.rx_index) # 0 (record.scene is SceneMetadata)
print(record.scene.scene_id) # "scene_0042"
print(record.scene.scene_geometry_hash) # "sha256:9af2…"
# Sibling records from the same scene share scene_id and geometry hash
siblings = store.read_siblings(record)
assert all(s.scene.scene_id == record.scene.scene_id
for s in siblings)
What It Covers¶
This page defines:
scene vs record,
multi-TX as the baseline (every scene is multi-emitter),
TX count vs record count (independent),
per-RX vs joint output,
content-addressed scene assets,
reconstruction of a Sionna RT environment from a record.
Scene vs Record¶
A scene describes emitters in time and frequency, optional physical geometry, materials, antenna patterns, and one or more receivers.
A record is one training example. It contains IQ, labels, metadata, optional text annotations, and references to any large assets needed to interpret or reproduce it.
The split matters most for multi-RX scenes and ray-traced scenes.
Multi-TX: the Baseline¶
This section assumes the semantic channel pipeline (TX impairments, channel propagation, RX capture, RX hardware) and the sum point at the head of RX capture. See Channels if those terms are new. “Pre-sum” means upstream of the per-receiver sum point (per-emitter), and “post-sum” means downstream of it (per-receiver).
Every scene is multi-emitter. There is no single-TX mode; the emitter count is sampled per scene from the configured density, and a count of one is just the lower end of that distribution. Multi-TX is not a special case.
N emitters produce N component signals. The scene composer calls each emitter’s generate() method per slot and tracks the results as component signals. The pre-sum chain (TX impairments, channel propagation) preserves those components while adding TX impairment values, propagation profile, realized SNR, and device identity metadata. After propagated components are summed at the head of RX capture, the scene-level Signal still carries component_signals[] so labels and annotations can read per-emitter ground truth directly.
One channel chain, scoped by group. The composer constructs a single ChannelPipeline. TX impairments and channel propagation run pre-sum, per-emitter. The sum point lives at the head of RX capture, and Sionna may vectorize many TX/RX paths into one channel-propagation invocation. RX capture and RX hardware run post-sum, per-receiver.
Compatibility or ablation modes that propagate an already-summed composite IQ must be explicit because they erase per-emitter propagation paths. Full mode semantics and the parameter surface are in Reference / Scene Composition Algorithm.
Source: Concepts / Channels defines the four channel groups and their cited subpages; Scenes § Composer Flow defines the pre-sum and post-sum composer flow; Reference / Scene Composition Algorithm records the implementation contract for emitter sampling, per-emitter routing, receiver summation, and multi-RX output.
TX count does not change record count. Record count is determined by receiver count and RecordAxis, not by emitter count. A scene with 5 transmitters and 1 receiver in default mode produces exactly one record.
Multi-RX: Per-RX vs Joint Records¶
Tasks that need the receiver array jointly should use RecordAxis.JOINT. Joint records emit one record per scene with a leading RX axis on IQ.
The default multi-RX layout is one record per receiver. A scene with N receivers emits N records, each with standard single-RX IQ shape (2, N_samples).
Each per-RX record carries:
its own IQ,
its own SNR and channel metadata,
its own bboxes derived from what that receiver heard,
its own annotation text,
shared
scene_id,distinct
rx_index.
This default matches single-RX training pipelines such as TorchSig, RadioML-style classifiers, and common SDR workflows.
Task |
Record axis |
|---|---|
Classification, modulation recognition, single-RX detection |
|
AoA, beamforming, MIMO decoding |
|
TDOA, distributed sensing, RX-array fingerprinting |
|
Multi-band device (e.g. 5G + Wi-Fi tuners on one chassis) |
RecordAxis is documented in Reference / API / Enums. The storage config field is documented in Reference / Config Schema.
Source: Reference / API / Enums defines RecordAxis.PER_RX and RecordAxis.JOINT; Reference / Config Schema defines the storage config field that selects the record axis. TorchSig’s single-receiver signal metadata shape is the compatibility anchor for the default per-RX path; see Reference / TorchSig Interop.
Multi-band Devices: Heterogeneous Receivers¶
Real customer devices often carry several receivers in one chassis, each tuned to a different band: a 5G NR receiver, a Wi-Fi receiver, a UHF radar tuner, and so on. The receivers share a position but capture different parts of the spectrum and run on different sample rates.
The framework expresses this with the heterogeneous-receivers path of MultiRXConfig. Set receivers to a list of ReceiverConfig entries; each carries its own position, optional center_freq_hz, bandwidth_hz, and sample_rate_hz. Per-emitter signals are merged at each receiver after band-filtering to that receiver’s capture window. Each receiver still produces its own record under RecordAxis.PER_RX.
Construct the config in Python:
from rfgen.config import MultiRXConfig, ReceiverConfig
multi_rx = MultiRXConfig(
receivers=[
ReceiverConfig(
rx_id="5g_nr",
position_m=(0.0, 0.0, 1.5),
center_freq_hz=3.5e9,
bandwidth_hz=100e6,
sample_rate_hz=122.88e6,
antenna_id="rugged_omni_v2",
),
ReceiverConfig(
rx_id="wifi",
position_m=(0.0, 0.0, 1.5),
center_freq_hz=2.4e9,
bandwidth_hz=80e6,
sample_rate_hz=80e6,
antenna_id="patch_2_4ghz",
),
],
)
The equivalent config that constructs the same objects:
# Two co-located receivers on one device: a 5G NR tuner and a Wi-Fi tuner.
scene:
multi_rx:
receivers:
- rx_id: "5g_nr"
position_m: [0.0, 0.0, 1.5]
center_freq_hz: 3.5e9
bandwidth_hz: 100e6
sample_rate_hz: 122.88e6
antenna_id: "rugged_omni_v2"
- rx_id: "wifi"
position_m: [0.0, 0.0, 1.5]
center_freq_hz: 2.4e9
bandwidth_hz: 80e6
sample_rate_hz: 80e6
antenna_id: "patch_2_4ghz"
storage:
record_axis: per_rx
Each scene produces two records, one per tuner, sharing the same scene_id but with distinct rx_index values. The stable receiver label begins at ReceiverConfig.rx_id; the scene composer copies that value into ChannelRxParams.tag for the active receiver on every channel call. In stored multi-RX scene metadata, the full receiver catalog is mirrored at record.scene.extras["receivers"][i]["rx_id"]; pair that list with record.scene.rx_index to recover which configured receiver produced a given per-RX record. The 5G record contains only emitters whose realized carrier overlaps [3.45, 3.55] GHz; the Wi-Fi record contains only emitters in [2.36, 2.44] GHz. An emitter outside both bands contributes to neither record’s IQ, and the current shipped path does not persist a drop-reason audit field in scene metadata.
This shape is distinct from the array path (MultiRXConfig.geometry = "ula" | "ura" | "arbitrary"), which assumes homogeneous receivers sharing the scene-level RF parameters. Use the array path for TDOA arrays and MIMO basestations; use the heterogeneous path for multi-band devices and distributed sensing networks where each node has its own front-end.
Source: Reference / Scene Composition Algorithm § Multi-RX defines the homogeneous receiver-array path and heterogeneous receiver-list path. Scene Geometry and Reference / Scene Geometry Assets ground the Sionna RT array, antenna, and receiver-position inputs used when the multi-RX scene is geometric.
Content-Addressed Assets¶
When Sionna RT is in use, a record must be enough to reconstruct the environment that produced it:
Mitsuba/Sionna scene geometry,
radio-material database,
antenna patterns,
TX/RX poses,
channel realization seed.
Embedding geometry in every record does not scale. Sionna RT, OpenStreetMap-derived, and CAD-derived scenes may include geometry, mesh, material, and antenna assets that are shared by many records. The framework stores large assets once by content hash.
Source: Reference / Scene Geometry Assets documents the Sionna RT and Mitsuba scene assets, radio materials, antenna arrays, and receiver positions that must be reconstructable. Sionna RT’s official documentation and Mitsuba’s scene-format documentation are the external sources for those asset types.
On disk, a dataset directory looks like:
dataset/
├── records/ # per-record blobs
└── assets/<sha256>/ # geometry, materials, antenna patterns
├── scene.xml
├── meshes/
├── materials.json
└── antenna_patterns/
Each record carries small references in scene metadata:
record.scene.scene_geometry_hash # record.scene is SceneMetadata
record.scene.material_db_hash
record.scene.antenna_pattern_hash
record.scene.geometry_asset_refs
record.scene.rx_index
record.scene.rx_pose
record.scene.rx_antenna_id
record.scene.channel_realization_seed
A stored record does not name a shipped dataset.resolve(...) helper today. The precise current contract is the metadata itself: record.scene.geometry_asset_refs carries the resolved typed asset references, while scene_geometry_hash, material_db_hash, and antenna_pattern_hash provide content-addressed audit keys. A storage-layer resolver may be added later, but current consumers should read the typed refs directly and use StorageConfig.assets_path to locate the corresponding blobs on disk. The exact channel realization is reproducible from those asset refs and hashes, record.scene.channel_realization_seed, the receiver pose, and the config.
Source: Reference / Determinism defines (global_seed, shard_id, sample_idx), shard content addressing, per-layer seed splitting, and backend-version recording. Reference / Scene Geometry Assets defines the loadable Sionna RT / Mitsuba asset bundle that scene_geometry_hash identifies.
Why This Fits Per-RX Records¶
In RecordAxis.PER_RX mode, all receiver records from one scene share the same geometry, material database, and antenna pattern hashes. Disk cost is:
1 x geometry assets + N x small record metadata
not:
N x geometry assets
Content addressing makes per-RX records compatible with large ray-traced scenes.
Inline Asset Export¶
Layer 7 does not implement inline_assets=True. Asset blobs stay content-addressed under the asset store, and callers should use StorageConfig.assets_path plus the typed refs in record.scene.geometry_asset_refs.
Determinism¶
A record is reproducible from (global_seed, shard_id, sample_idx) plus the asset store. The asset hash binds a record to the environment used to produce it.
Re-running with the same config, seeds, backend versions, and asset store should produce the same deterministic Phase 1 output. Full seed-flow rules live in Reference / Determinism.
Source: Reference / Determinism is the normative seed-flow contract. It defines the shard and sample seed hierarchy, layer-specific random-number-generator splits, and the acceptable backend nondeterminism caveat for Sionna and GPU reductions.
See Also¶
Scene Geometry for when geometry is required.
Scenes / Composition for how emitter count, placement, and multi-RX interact.
Channels for per-group scope and multi-RX channel realizations.
Reference / Scene Composition Algorithm for channel application modes and the full 10-step algorithm.
Reference / Scene Geometry Assets for Sionna RT and Mitsuba asset details.
Reference / Storage Layout for on-disk formats.
Background / Design Decisions § Channel pipeline for the rationale behind the per-RX axis and the post-sum chain that produce the per-receiver records.