Generate one unified observation dataset¶
Use this workflow when communications and radar outputs must be synchronized
and consumed as one dataset sample. Each configured sample mints one
ScenePlan, runs an ordered set of projections, and publishes exactly one
Signal Dataset record.
This path is available in local and Dataproc Serverless execution. It is not a production-qualified Golden Path. The built-in active-radar projection is available, but its scientific claims retain the qualification limits in Radar Response, and each Dataproc image digest must pass the separate observation-runtime gate before it can be submitted.
Copy the complete checked configuration¶
Install both renderer integrations before validation or generation:
uv pip install 'rfgen[torchsig,sionna]'
On the hosted documentation page, download
unified-communications-radar.yaml
and save it as ./unified-rf/config.yaml. In a source checkout, copy the same
checked artifact:
mkdir -p ./unified-rf
cp docs/examples/unified-communications-radar.yaml ./unified-rf/config.yaml
rfgen validate --config-dir ./unified-rf --config-name config
It validates as one GenerationConfig, resolves two projection descriptors, and is refused without one. Success is a zero exit with no configuration error.
Keep exactly one plan block. That block owns the shared clock, systems,
scheduled events, scene geometry, and target sampling. Add both communication
and radar systems/events to this one plan; do not create one plan per domain.
The ScenePlan configuration contract
defines the complete authoring vocabulary.
All activity start_offset_s and stop_offset_s values are relative to
plan.clock.time_origin_s. The plan’s duration_s must contain every
activity. Both projections receive the same minted plan and bind their field
coordinates to the same content-derived time reference.
Generate and verify the one-record outcome¶
rfgen validate --config-dir ./unified-rf --config-name config
rfgen generate --config-dir ./unified-rf --config-name config
rfgen inspect ./rfgen-output
With the checked num_samples: 2, inspection must report two records—not four
records for two domains or a per-receiver fanout. Each record’s field catalog
contains both projections/communications_rx/... and
projections/radar_rx/... names.
Validation rejects duplicate projection IDs. Generation resolves every plugin, checks store capabilities, and preflights all relevant interactions before rendering. The built-in communications and radar projections currently record cross-domain coupling as explicitly excluded; they synchronize their separate outputs but do not simulate mutual communications/radar interference.
Inspect one record without assuming an iq field at the root:
from rfgen.observation import SDSObservationAdapter
from rfgen.storage import SignalDatasetStore
access = SignalDatasetStore().open("./rfgen-output")
metadata = access.metadata(0)
view = SDSObservationAdapter().metadata_view(metadata)
print(view.projection_ids)
print(view.field_names)
record = access[0]
observation = SDSObservationAdapter().decode(record)
print(observation.scene_plan.clock)
print(sorted(observation.fields))
Expect field paths such as
projections/communications_rx/receivers/rx0/iq and projection-owned radar
component paths. Exact radar components depend on the configured response
backend. Coordinate arrays may appear as auxiliary fields; consult
record.metadata["rfgen"]["primary_fields"] and auxiliary_fields instead of
classifying fields by suffix.
Run the same observation on Dataproc¶
Retain the same plan, projections, and observation blocks. Select the
Signal Dataset store and add the remote execution block:
storage:
backend: signal_dataset
path: gs://YOUR_BUCKET/YOUR_OUTPUT_ROOT
executor:
name: dataproc_serverless
dataproc:
project: YOUR_PROJECT
region: us-central1
staging_uri: gs://YOUR_BUCKET/rfgen-staging
service_account: YOUR_WORKER_SERVICE_ACCOUNT
observation_contract_version: 1
The submitting installation and the digest-pinned image must resolve the same projection descriptors. RFGen verifies the observation contract, image/runtime identity, staged configuration, plugin packages, store capabilities, and world asset boundary before creating cloud work. The qualified-image map is intentionally fail closed: a newly built image cannot run projection-enabled jobs until its exact digest passes the qualification workflow and is pinned in the map.
For an out-of-tree node, build a pure-Python wheel and list its local path
under executor.dataproc.extra_packages. RFGen verifies the local file
exists, is a valid zip archive, and declares an rfgen.* entry point before
staging it, and rejects a remote (gs:// or otherwise) package reference
outright; it does not inspect the archive for native extensions or compare it
against the locally installed distribution. Follow Dataproc Serverless /
Shipping plugin packages
for the full packaging contract.
What one record contains¶
A unified observation holds every projection’s fields for one ScenePlan in one
stored record. Multiple receivers do not split that record: each receiver is a
named subtree under projections/<projection_id>/receivers/rx<N>/, and the
segmentation raster carries a leading receiver axis. Older datasets that were
written one record per receiver remain readable as they were written; this
build does not produce that shape.
Update consumers to:
discover fields through the RFGen envelope instead of assuming root
iq;use each field’s semantic axes and coordinates instead of forcing one tensor rank;
use
field_owners,primary_fields, andauxiliary_fieldsto group fields;budget memory for a whole aggregate record; and
treat the projection and runtime identities as part of reproducibility.
The declared-evidence annotation path has not been migrated to aggregate observations. It continues to support the retained legacy metadata contract; do not send unified observations through it expecting projection-aware evidence or captions.