This repository contains the MATLAB artifact for the paper:
Xin Liu, Wei-Han Chen, and Kannan Srinivasan. 0cal: Zero-Cost Calibration for mmWave Networks. SenSys 2026. DOI:
10.1145/3774906.3802748.
The paper PDF is included as 26sensys-0cal.pdf.
This artifact is split across GitHub and Zenodo. GitHub is the code and lightweight-artifact repository. Zenodo is the canonical source for the raw LoS and NLoS probe measurements.
This GitHub repository contains:
- MATLAB scripts for simulation, measured-data processing, and plotting.
- Plotting utilities used by
main.m. - The paper PDF.
- Lightweight saved
.matfiles and.pngoutputs for several paper-style plots. - LoS and NLoS processing scripts under
los/andnlos/.
This checkout does not contain the full raw probe traces for the LoS and NLoS experiments.
The raw probe measurements are hosted on Zenodo:
- Record: https://zenodo.org/records/19897158
- DOI:
10.5281/zenodo.19897158 - Title:
0cal Artifact Dataset: Raw Probe Measurements for mmWave Calibration in Line-of-Sight and Non-Line-of-Sight Environments - Files:
Line-Of-Sight_instance_probe.tar.gzNone-Line-Of-Sight_instance_probe.tar.gz
These archives contain the fundamental raw instance_probe/data*.mat measurements collected in Line-of-Sight (LoS) and Non-Line-of-Sight (NLoS) / persistent-distortion settings. Treat these Zenodo files as the primary non-derivable experimental inputs.
The raw Zenodo data are the source data. The MATLAB code in this repository is used to process those probe measurements into steering-vector summaries, selected uniform/non-uniform subsets, phase-deviation summaries, and figures.
Some saved intermediate .mat files remain in GitHub for convenience, especially the root-level files consumed by main.m. Those files are lightweight processed artifacts, not replacements for the raw probe dataset.
The code supports three distinct kinds of evidence from the paper:
- Fully synthetic simulation, such as the array-size study for Figure 11.
- Hybrid simulation using a real measured calibration phase vector, such as Figures 4 and 5.
- Real-measurement processing and saved real-result plots, such as Figures 7, 8, 9, 10, and 12.
The distinction matters. "Simulation" in this artifact does not always mean synthetic from scratch. simulation/main_correlation_shift.m and simulation/main_non_uniform.m use the measured 32-element calibration vector in simulation/cal32_new_taoffice.mat. simulation/main_array_size.m is fully synthetic.
The current repository contains the following top-level components:
| Path | Role |
|---|---|
26sensys-0cal.pdf |
Paper associated with this artifact. |
README.md |
This artifact guide. |
main.m |
Top-level plotting script for the saved root-level .mat files. Every plotting block is disabled by default with if 1 == 0. |
plot_scripts/ |
Plotting helpers used by main.m, including CDF, bar, line, and interval plotting utilities. |
simulation/ |
Simulation and hybrid-simulation scripts for Figures 4, 5, and 11, plus shared array/phase helpers. |
simulation/cal32_new_taoffice.mat |
Measured 32-element calibration phase vector used by the hybrid Figure 4 and Figure 5 workflows. |
los/ |
MATLAB scripts for the LoS raw-probe processing pipeline. The raw instance_probe/ data directory is not included in GitHub. |
nlos/ |
MATLAB scripts for the NLoS / persistent-distortion raw-probe processing pipeline. The raw instance_probe/ data directory is not included in GitHub. |
d1_correlation_shift.mat |
Saved data for the Figure 4 correlation plots. Also regenerable from simulation/main_correlation_shift.m. |
d2_non_uniform.mat |
Saved data for the Figure 5 AoD-distribution plot. Also regenerable from simulation/main_non_uniform.m. |
d4_instance_increase.mat |
Saved real-result summary for Figure 8. |
d5_beamforming.mat |
Saved real-result summary for Figure 9. |
d6_compressive_sensing.mat |
Saved real-result summary for Figure 10. |
d7_array_size.mat |
Saved data for Figure 11. Also regenerable from simulation/main_array_size.m. |
withoutDeviation.png, withDeviation.png, aodDistribution.png, instanceSize.png, uncalibrated.png, beamforming.png, arraySize.png |
Pre-generated plot images from the saved data. |
Historical path note: older artifact text referred to Line-Of-Sight/ and None-Line-Of-Sight/ directories inside GitHub. Those complete local measurement trees are not present in this checkout. The Zenodo raw archives use those descriptive names, while the current GitHub processing scripts live in los/ and nlos/.
Generated directories such as the following are not part of the current checkout unless you create them by running the data pipeline:
los/instance_probe/andnlos/instance_probe/los/instance_sv/andnlos/instance_sv/los/instance_phase_deviation/andnlos/instance_phase_deviation/los/phase_plot_data/andnlos/phase_plot_data/los/phase_plot_figures/andnlos/phase_plot_figures/
The artifact was inspected with MATLAB R2024b. The scripts use MATLAB functionality from:
- Phased Array System Toolbox or equivalent functions for
phased.ConformalArray,steervec,pattern,getElementPosition, andphysconst. - Statistics and Machine Learning Toolbox for functions such as
randomandcdfplot. - Signal Processing Toolbox or equivalent functions for
xcorr,rms,db2mag, and related signal-processing operations.
The full hardware-acquisition path also depends on M-Cube/USRP support code that is not fully included in this repository.
To replay the LoS/NLoS raw-data pipeline, download the two raw archives from Zenodo and arrange the extracted probe directories so that the scripts see:
los/instance_probe/data*.mat
nlos/instance_probe/data*.mat
If an archive extracts into a wrapper directory such as Line-Of-Sight/instance_probe/, move or copy that instance_probe/ directory under los/. Do the analogous step for None-Line-Of-Sight/instance_probe/ and nlos/.
The scripts use fullfile(pwd, 'instance_probe'), so the important requirement is to run each pipeline from a directory that contains the corresponding instance_probe/ folder.
This path regenerates the plots supported by the root-level saved .mat files without downloading the large raw probe archives.
- Open MATLAB at the repository root.
- Run:
addpath('./plot_scripts')- Open
main.m. - For the figure block you want, change
if 1 == 0toif 1 == 1. - Run
main.m.
This supports the saved-data versions of Figures 4, 5, 8, 9, 10, and 11. It does not regenerate Figures 7 or 12 in the current checkout because the corresponding LoS/NLoS raw data and generated phase_plot_data/ directories are not stored in GitHub and must be regenerated locally from Zenodo data.
Run these scripts from simulation/:
cd simulation
main_correlation_shift % Figure 4 data: synthetic steering vectors + measured calibration phase
main_non_uniform % Figure 5 data: synthetic AoD distribution + measured calibration phase
main_array_size % Figure 11 data: fully synthetic array-size simulation
cd ..These scripts save local copies under simulation/ and parent copies at the repository root.
After placing the Zenodo raw data as described above, the intended pipeline is:
cd los % or cd nlos
addpath('../simulation')
A_Reading_Instance_Generating_SV
B_Handle_Non_Uniform_Distribution
C_Compute_Phase_Deviation
D_plot_phase_deviation % use D_Plot_phase_deviation in nlos
cd ..The pipeline stages are:
| Stage | Input | Output |
|---|---|---|
A_Reading_Instance_Generating_SV.m |
instance_probe/data*.mat |
instance_sv/instance_sv.mat |
B_Handle_Non_Uniform_Distribution.m |
instance_sv/instance_sv.mat |
instance_sv/instance_sv_non_uniform_*.mat, instance_sv/instance_sv_uniform_*.mat, az_instance_map.json |
C_Compute_Phase_Deviation.m |
selected instance_sv/*.mat subsets |
instance_phase_deviation/*.mat |
D_plot_phase_deviation.m or D_Plot_phase_deviation.m |
instance_phase_deviation/*.mat summaries |
phase_plot_data/phase_deviation.mat, phase_plot_figures/Element_*.png, phase_plot_figures/Element_*.pdf |
Important limitation: the first stage currently calls extract_beam_metrics_and_paths, which is not present in this repository. The scripts also add a local lib/ path, but no los/lib/ or nlos/lib/ directory is included. If those helper functions are available from an external M-Cube support checkout or local MATLAB path, the raw replay path can be completed; otherwise, the raw-to-instance_sv step is not one-click reproducible from this GitHub repository alone.
These are paper diagrams or platform illustrations and are not directly regenerated by scripts in this repository.
- Figure 1 compares lab-grade OTA calibration with 0cal.
- Figure 2 illustrates relative complex gain between antenna elements.
- Figure 3 shows antenna layout and adjacency-selection logic. Related hard-coded adjacency arrays appear in
los/C_Compute_Phase_Deviation.mandnlos/C_Compute_Phase_Deviation.m. - Figure 6 shows the M-Cube-based prototype and office deployment environment.
- Type: hybrid simulation-style evaluation.
- Real component: measured calibration phase vector from
simulation/cal32_new_taoffice.mat. - Simulation component: steering vectors over scan angles from -60 to 60 degrees.
- Generation script:
simulation/main_correlation_shift.m. - Saved data:
simulation/d1_correlation_shift.matand rootd1_correlation_shift.mat. - Plotting script: first block of
main.m. - Output images:
withoutDeviation.pngandwithDeviation.png.
- Type: hybrid simulation-style evaluation.
- Real component:
simulation/main_non_uniform.mloadssimulation/cal32_new_taoffice.matand savesdata.gnd_truth. - Simulation component: the AoD histogram is synthetically generated from clustered and uniform angle samples.
- Generation script:
simulation/main_non_uniform.m. - Saved data:
simulation/d2_non_uniform.matand rootd2_non_uniform.mat. - Plotting script: first block of
main.m, after the Figure 4 plots. - Output image:
aodDistribution.png.
- Type: real-data based.
- Canonical raw data:
Line-Of-Sight_instance_probe.tar.gzon Zenodo. - Current GitHub scripts:
los/A_*.m,los/B_*.m,los/C_*.m,los/D_plot_phase_deviation.m. - Expected local raw-data path after download:
los/instance_probe/data*.mat. - Generated compact data:
los/phase_plot_data/phase_deviation.mat. - Generated per-element plots:
los/phase_plot_figures/Element_*.pngand.pdf. - Paper-selected elements: #26, #27, #19, and #13.
The current GitHub checkout does not include the raw instance_probe/ directory or the generated phase_plot_data/ and phase_plot_figures/ outputs for this figure. They should be regenerated from the Zenodo raw data once the required helper functions are available.
- Type: real-data based saved result.
- Saved data:
d4_instance_increase.mat. - Data fields:
data.legcontainsControlled,w/ 100 samples,w/ 300 samples,w/ 500 samples, andw/ 700 samples;data.dpstores the SNR samples used to build the CDF curves. - Plotting script: the
d4_instance_increase.matblock inmain.m. - Output image:
instanceSize.png.
The current plotting block drops the controlled row and plots the 100, 300, 500, and 700 instance cases.
- Type: real-data based saved result.
- Saved data:
d5_beamforming.mat. - Data fields:
data.legcontains controlled calibration, uncalibrated, and uncontrolled/0cal calibration. - Plotting script: the
d5_beamforming.matblock inmain.m. - Output image:
uncalibrated.png.
The plotting block reorders rows to show uncalibrated, traditionally calibrated, and 0cal with 700 instances.
- Type: real-data based saved result.
- Saved data:
d6_compressive_sensing.mat. - Data fields:
data.legcontainsACO,11ad,SWIFT, andOurs. - Plotting script: the
d6_compressive_sensing.matblock inmain.m. - Output image:
beamforming.png.
The current plotting block uses 11ad, ACO, and Ours labeled as 0cal + Compressive Sensing. The saved SWIFT row is present but not plotted by main.m.
- Type: fully synthetic simulation.
- Generation script:
simulation/main_array_size.m. - Saved data:
simulation/d7_array_size.matand rootd7_array_size.mat. - Plotting script: the
d7_array_size.matblock inmain.m. - Output image:
arraySize.png.
Important caveat: the paper discusses four array sizes, 36, 64, 256, and 1024 elements. The current simulation/main_array_size.m and saved d7_array_size.mat include an additional 128-element case. The main.m legend still lists four labels. For exact paper-style reproduction, either remove the 128-element column before plotting or deliberately update the plotting code and legend.
- Type: real-data based.
- Canonical raw data:
Line-Of-Sight_instance_probe.tar.gzon Zenodo.None-Line-Of-Sight_instance_probe.tar.gzon Zenodo.
- Current GitHub scripts:
los/for the dominant-LoS baseline.nlos/for the persistent distorted / NLoS condition.
- Generated compact data:
los/phase_plot_data/phase_deviation.matnlos/phase_plot_data/phase_deviation.mat
- Paper elements: #19 and #13.
The final Figure 12 is not generated by a single included top-level script. It combines selected-uniform curves from both LoS and NLoS processed outputs. After generating both phase_deviation.mat files, a minimal combine step is:
los_data = load(fullfile('los', 'phase_plot_data', 'phase_deviation.mat'));
nlos_data = load(fullfile('nlos', 'phase_plot_data', 'phase_deviation.mat'));
x = los_data.data.x(1:10); % 100, 200, ..., 1000
elems = [19 13];
figure;
for k = 1:numel(elems)
subplot(1, 2, k);
e = elems(k);
plot(x, nlos_data.data.dp_uniform(1:10, e), 'o-', ...
'DisplayName', 'Persistent Distorted');
hold on;
plot(x, los_data.data.dp_uniform(1:10, e), 's-', ...
'DisplayName', 'LoS-Dominant');
ylim([-pi pi]);
yticks([-pi -pi/2 0 pi/2 pi]);
yticklabels({'-pi','-pi/2','0','pi/2','pi'});
xlabel('Num of Comm Instances');
ylabel('Phase Deviation');
title(sprintf('Element #%d', e));
legend('Location', 'northwest');
grid on;
endThis reflects the paper interpretation: persistent blockage/reflection can shift the converged phase relative to the dominant-LoS baseline.
- The raw LoS/NLoS probe measurements are not stored in GitHub. Download them from Zenodo before running the real-data pipeline.
- The current checkout contains
los/andnlos/script directories, not completeLine-Of-Sight/andNone-Line-Of-Sight/data trees. los/instance_probe/,nlos/instance_probe/,instance_sv/,instance_phase_deviation/,phase_plot_data/, andphase_plot_figures/are generated or externally supplied directories, not tracked source directories in this checkout.- The raw replay step
A_Reading_Instance_Generating_SV.mcallsextract_beam_metrics_and_paths, which is not included. A related helper namedsimulation/debug_peaks.mexists, but the scripts do not call it directly. - Both raw replay scripts call
addpath(pwd, 'lib')andsavepath, but nolib/directory is present underlos/ornlos/. simulation/run_exp_calibration.mreferences hardware/acquisition helpers such ascreate_csi_codebookandmeasure_cs_multipath_codebook, which are not included. Treat it as a hardware-acquisition sketch, not a self-contained reproduction script.- Some MATLAB function names and filenames do not match exactly. For example,
C_Compute_Phase_Deviation.mdeclaresfunction Compute_Phase_Deviation(...), and the plot files declarefunction plot_phase_deviation(). If MATLAB path resolution fails, run from a clean working directory and adjust the function/file naming locally. - Figures 8, 9, and 10 can be replotted from saved root-level real-result
.matsummaries. This repository does not include a complete script chain from raw probes tod4_instance_increase.mat,d5_beamforming.mat, ord6_compressive_sensing.mat. - Figure 12 requires combining outputs from both
los/andnlos/. The ingredients can be generated, but no dedicated final Figure 12 assembly script is included. main.mis a plotting notebook with disabled blocks, not a one-click driver.
| Paper figure | Type | Script(s) | Input data | Output in repository or generated output | Notes |
|---|---|---|---|---|---|
| Figure 1 | Diagram | Not included | N/A | N/A | Conceptual comparison of lab OTA calibration and 0cal. |
| Figure 2 | Diagram | Not included | N/A | N/A | Relative-gain schematic. |
| Figure 3 | Diagram with code-related constants | No standalone plot script | N/A | N/A | Adjacency arrays appear in los/C_Compute_Phase_Deviation.m and nlos/C_Compute_Phase_Deviation.m. |
| Figure 4 | Hybrid simulation | simulation/main_correlation_shift.m, main.m |
simulation/cal32_new_taoffice.mat |
d1_correlation_shift.mat, withoutDeviation.png, withDeviation.png |
Uses measured phase deviation to perturb synthetic steering vectors. |
| Figure 5 | Hybrid simulation | simulation/main_non_uniform.m, main.m |
simulation/cal32_new_taoffice.mat |
d2_non_uniform.mat, aodDistribution.png |
AoD histogram is synthetic; calibration ground truth comes from measured phase. |
| Figure 6 | Platform/photo figure | Not included | N/A | N/A | Prototype and deployment photos are not regenerated. |
| Figure 7 | Real data | los/A_*.m, B_*.m, C_*.m, D_plot_phase_deviation.m |
Zenodo LoS raw probes | Generated los/phase_plot_figures/Element_*.png |
Requires Zenodo data and missing helper availability. |
| Figure 8 | Real saved result | main.m |
d4_instance_increase.mat |
instanceSize.png |
Plots 100, 300, 500, and 700 instance CDFs. |
| Figure 9 | Real saved result | main.m |
d5_beamforming.mat |
uncalibrated.png |
Compares uncalibrated, traditional calibration, and 0cal with 700 instances. |
| Figure 10 | Real saved result | main.m |
d6_compressive_sensing.mat |
beamforming.png |
Plots 11ad, ACO, and 0cal + compressive sensing. |
| Figure 11 | Fully synthetic simulation | simulation/main_array_size.m, main.m |
Random path angles generated by script | d7_array_size.mat, arraySize.png |
Current data includes an extra 128-element case. |
| Figure 12 | Real data, combined LoS/NLoS | los/ and nlos/ pipelines plus manual combine |
Zenodo LoS and NLoS raw probes | Generated phase_plot_data/phase_deviation.mat files |
Requires combining element #19 and #13 selected-uniform curves from both folders. |
If you use this artifact, cite the paper and the Zenodo dataset:
Xin Liu, Wei-Han Chen, and Kannan Srinivasan.
0cal: Zero-Cost Calibration for mmWave Networks.
SenSys 2026.
DOI: 10.1145/3774906.3802748
0cal Artifact Dataset: Raw Probe Measurements for mmWave Calibration
in Line-of-Sight and Non-Line-of-Sight Environments.
Zenodo. DOI: 10.5281/zenodo.19897158