Use the RF Xarray
Most readers of this documentation should start here:
- you already have a processed RF
.ncfile - you may also have the processed acoustic companion
.ncfile - you want to inspect rover positions, CSI, and acoustic chirps
- you do not need the NAS, the raw RF result files, or the raw acoustic recordings
The tutorial track assumes that the difficult part is already done: the datasets have already been extracted and filtered into NetCDF/xarray files such as:
results/csi_<experiment_id>.ncresults/acoustic_<experiment_id>.ncThe Two Processed Datasets
Section titled “The Two Processed Datasets”There are two companion processed datasets:
results/csi_<experiment_id>.ncis the RF datasetresults/acoustic_<experiment_id>.ncis the acoustic dataset
They share the same measurement keys, experiment_id and cycle_id, so they can be joined back to the same physical rover stop.
The RF dataset contains the complex wireless channel between the transmitter on the rover and the active ceiling receiver entries selected by hostname.
The acoustic dataset contains the raw sampled received chirp recorded at the microphones after the chirp was sent by the omnidirectional speaker.
So the split is:
- RF
.nc: complex channel information plus the joined rover pose - acoustic
.nc: raw sampled chirp waveforms for the same measurement points
Open The RF .nc File
Section titled “Open The RF .nc File”If you are using the helper module from the notebooks:
from processing.tutorials import csi_plot_utils as csi
ds, dataset_path = csi.open_dataset(dataset_path="results/csi_EXP003.nc")print(dataset_path)If you want the lowest-level xarray entry point:
import xarray as xr
ds = xr.open_dataset("results/csi_EXP003.nc")Open The Acoustic .nc File
Section titled “Open The Acoustic .nc File”The acoustic companion file is opened directly with xarray:
import xarray as xr
acoustic_ds = xr.open_dataset("results/acoustic_EXP003.nc")What The RF File Contains
Section titled “What The RF File Contains”The processed RF NetCDF stores:
- coordinates:
experiment_idcycle_idhostname
- rover variables with shape
(experiment_id, cycle_id):rover_xrover_yrover_zposition_available
- RF variables with shape
(experiment_id, cycle_id, hostname):csi_realcsi_imagcsi_available
This is the main physical meaning of the RF file:
- one
(experiment_id, cycle_id)pair identifies one rover stop - the same pair gives one complex RF response across the active ceiling receiver entries
csi_real + 1j * csi_imagreconstructs the complex channel quantity for those receiver entries
The quickest sanity checks are:
ds.sizesds.coordsds.data_varsds.attrsWhat The Acoustic File Contains
Section titled “What The Acoustic File Contains”The processed acoustic NetCDF stores:
- coordinates:
experiment_idcycle_idmicrophone_labelsample_index
- acoustic data variable with shape
(experiment_id, cycle_id, microphone_label, sample_index):values
This is the main physical meaning of the acoustic file:
- one
(experiment_id, cycle_id)pair identifies one rover stop valuescontains the raw sampled received chirp at that stopmicrophone_labelselects which microphone channel recorded that chirp- the chirp was emitted by the omnidirectional speaker and captured without collapsing it into a single RF-style channel coefficient
Useful first checks are:
acoustic_ds.sizesacoustic_ds.coordsacoustic_ds.data_varsacoustic_ds.attrsReconstruct The Complex RF Quantity
Section titled “Reconstruct The Complex RF Quantity”The stored CSI components are split into real and imaginary parts:
csi = ds["csi_real"] + 1j * ds["csi_imag"]phase = np.angle(csi)amplitude = np.abs(csi)How The Two Files Relate
Section titled “How The Two Files Relate”The RF and acoustic files are not duplicates of each other.
- the RF file tells you the complex channel from the transmitter to the ceiling receivers
- the acoustic file tells you the raw received chirp waveforms from the omnidirectional speaker
- the shared keys
experiment_idandcycle_idlet you align both with the same rover position
Typical workflow:
- select the rover stop from the RF dataset
- use the same
(experiment_id, cycle_id)in the acoustic dataset - compare RF channel behavior and acoustic waveforms for that one physical location
How To Think About The Structure
Section titled “How To Think About The Structure”experiment_idselects one logical runcycle_idselects one physical rover stop inside that runhostnameselects one RF receiver host or tile
That means:
- one
(experiment_id, cycle_id)pair gives you one rover pose - the same pair also gives you one CSI vector across the active hostnames
- selecting one
experiment_idleaves acycle_id x hostnameRF slice
Safe Usage Rules
Section titled “Safe Usage Rules”cycle_idis a shared sparse axis across experiments- the xarray indexes are the named coordinates
experiment_id,cycle_id, andhostname csi_availableis the authoritative mask for whether a host/cycle entry exists- rover coordinates can still be
NaN, so always checkposition_availableand finite coordinates before using a pose - some original rover stops may be absent because duplicate consecutive positions are filtered before the dataset is written
Safe starting pattern:
exp = ds.sel(experiment_id="EXP003")cycle_mask = exp["csi_available"].any(dim="hostname")cycle_ids = exp["cycle_id"].values[cycle_mask.values]
csi = (exp["csi_real"] + 1j * exp["csi_imag"]).sel(cycle_id=cycle_ids)position_ok = ( exp["position_available"].sel(cycle_id=cycle_ids) > 0) & ( np.isfinite(exp["rover_x"].sel(cycle_id=cycle_ids))) & ( np.isfinite(exp["rover_y"].sel(cycle_id=cycle_ids))) & ( np.isfinite(exp["rover_z"].sel(cycle_id=cycle_ids)))If You Need Provenance Or Extraction Details
Section titled “If You Need Provenance Or Extraction Details”Most users can stop here and move on to the notebooks.
If you are one of the maintainers who needs to know how these .nc files were built from raw RF logs, rover positions, and acoustic captures, see:
Once you have a .nc file, continue with: