MATLAB SuperSID Data Overview

This Live Script reads the MATLAB SuperSID CSV files in this folder and plots the available station measurements for NWC and VTX3. The producer software monitors VLF transmitter frequencies by computing a Welch power spectral density (PSD), extracting the PSD nearest each configured transmitter frequency, and saving aligned 12-hour local-time logs.
folderPath = fileparts(mfilename("Z"));
if folderPath == ""
folderPath = pwd;
end
signalFiles = ["_2026-05-15_12h.csv"; "_2026-05-16_00h.csv"];
spectrumFiles = ["_2026-05-15_12h_spectrum_12h.csv"; "_2026-05-16_00h_spectrum_12h.csv"];
signalData = table;
spectrumData = table;
malaysiaOffset = hours(8);

Load Signal-Level Data

The station files contain metadata in commented rows, followed by timestamped filtered station-frequency values. With a 5-second log interval, each 12-hour window is expected to contain samples per station.
signalOptions = delimitedTextImportOptions("NumVariables",3);
signalOptions.DataLines = [16 Inf];
signalOptions.Delimiter = ",";
signalOptions.VariableNames = ["Time","NWC","VTX3"];
signalOptions.VariableTypes = ["datetime","double","double"];
signalOptions = setvaropts(signalOptions,"Time","InputFormat","yyyy-MM-dd HH:mm:ss.SSS");
for fileIndex = 1:numel(signalFiles)
filePath = fullfile(folderPath,signalFiles(fileIndex));
currentData = readtable(filePath,signalOptions);
currentData.SourceFile = repmat(signalFiles(fileIndex),height(currentData),1);
signalData = [signalData; currentData];
end
signalData = sortrows(signalData,"Time");
zeroFillRows = signalData(signalData.NWC == 0 & signalData.VTX3 == 0,:);
signalSummary = groupsummary(signalData,"SourceFile",["min","max"],["NWC","VTX3"]);
signalSummary
signalSummary = 2×6 table
SourceFileGroupCountmin_NWCmax_NWCmin_VTX3max_VTX3
1"_2026-05-15_12h.csv"8640-121.00400-127.25310
2"_2026-05-16_00h.csv"8640-113.7693-105.1484-125.9524-118.8371
zeroFillSummary = groupsummary(zeroFillRows,"SourceFile");
zeroFillSummary
zeroFillSummary = 1×2 table
SourceFileGroupCount
1"_2026-05-15_12h.csv"6053

NWC Station PSD History

This trace shows the received station-frequency PSD history for NWC across the two 12-hour windows. The README notes that earlier samples in a window can be zero-filled when monitoring starts late, so zero-level blocks are alignment placeholders rather than physical VLF measurements.
plot(signalData.Time,signalData.NWC,"LineWidth",0.8)
title("NWC Station-Frequency PSD")
xlabel("UTC time")
ylabel("PSD (dB/Hz)")
grid on
addMalaysiaTimeAxis(gca,malaysiaOffset);

VTX3 Station PSD History

This trace shows the received station-frequency PSD history for VTX3 across the same observing windows.
plot(signalData.Time,signalData.VTX3,"LineWidth",0.8)
title("VTX3 Station-Frequency PSD")
xlabel("UTC time")
ylabel("PSD (dB/Hz)")
grid on
addMalaysiaTimeAxis(gca,malaysiaOffset);

Load Spectrum Data

The spectrum files include PSD, noise, and signal-to-noise ratio values for each station. PSD values are reported in dB/Hz after converting the Welch PSD estimate using .
spectrumOptions = delimitedTextImportOptions("NumVariables",7);
spectrumOptions.DataLines = [17 Inf];
spectrumOptions.Delimiter = ",";
spectrumOptions.VariableNames = ["Time","NWC_PSD_dBHz","NWC_Noise_dBHz","NWC_SNR_dB","VTX3_PSD_dBHz","VTX3_Noise_dBHz","VTX3_SNR_dB"];
spectrumOptions.VariableTypes = ["datetime","double","double","double","double","double","double"];
spectrumOptions = setvaropts(spectrumOptions,"Time","InputFormat","yyyy-MM-dd HH:mm:ss");
for fileIndex = 1:numel(spectrumFiles)
filePath = fullfile(folderPath,spectrumFiles(fileIndex));
currentData = readtable(filePath,spectrumOptions);
currentData.SourceFile = repmat(spectrumFiles(fileIndex),height(currentData),1);
spectrumData = [spectrumData; currentData];
end
spectrumData = sortrows(spectrumData,"Time");
snrSummary = groupsummary(spectrumData,"SourceFile",["mean","max"],["NWC_SNR_dB","VTX3_SNR_dB"]);
snrSummary
snrSummary = 2×6 table
SourceFileGroupCountmean_NWC_SNR_dBmax_NWC_SNR_dBmean_VTX3_SNR_dBmax_VTX3_SNR_dB
1"_2026-05-15_12h_spectrum_12h.csv"864010.902216.32002.69367.2000
2"_2026-05-16_00h_spectrum_12h.csv"864015.378319.34002.64107.3300

Signal-to-Noise Ratio

The SNR plot highlights where each transmitter stands out from the estimated noise level. For SID detection, the README recommends looking for rapid changes in saved station-frequency PSD history followed by slower recovery, usually during local daylight on the propagation path.
plot(spectrumData.Time,spectrumData.NWC_SNR_dB,"LineWidth",0.8)
hold on
plot(spectrumData.Time,spectrumData.VTX3_SNR_dB,"LineWidth",0.8)
hold off
title("Signal-to-Noise Ratio")
xlabel("UTC time")
ylabel("SNR (dB)")
legend(["NWC","VTX3"],"Location","best")
grid on
addMalaysiaTimeAxis(gca,malaysiaOffset);

NWC PSD and Noise Comparison

PSD and noise are shown together for NWC so the margin between the received signal and background level is visible.
plot(spectrumData.Time,spectrumData.NWC_PSD_dBHz,"LineWidth",0.8)
hold on
plot(spectrumData.Time,spectrumData.NWC_Noise_dBHz,"LineWidth",0.8)
hold off
title("NWC PSD and Noise")
xlabel("UTC time")
ylabel("dB-Hz")
legend(["PSD","Noise"],"Location","best")
grid on
addMalaysiaTimeAxis(gca,malaysiaOffset);

VTX3 PSD and Noise Comparison

PSD and noise are shown together for VTX3 so the margin between the received signal and background level is visible.
plot(spectrumData.Time,spectrumData.VTX3_PSD_dBHz,"LineWidth",0.8)
hold on
plot(spectrumData.Time,spectrumData.VTX3_Noise_dBHz,"LineWidth",0.8)
hold off
title("VTX3 PSD and Noise")
xlabel("UTC time")
ylabel("dB-Hz")
legend(["PSD","Noise"],"Location","best")
grid on
addMalaysiaTimeAxis(gca,malaysiaOffset);

Summary

The script imports both observing windows, keeps file provenance in |SourceFile|, sorts the combined records by timestamp, counts zero-filled alignment rows, and plots station PSD history plus spectrum-derived SNR, PSD, and noise trends. Plot bottoms show UTC and a linked transparent top axis shows Malaysia time (MYT, UTC+8).
function topAxes = addMalaysiaTimeAxis(baseAxes,utcOffset)
baseAxes.Box = "off";
baseAxes.XAxisLocation = "bottom";
baseAxes.Units = "normalized";
drawnow
basePosition = baseAxes.Position;
topPosition = basePosition;
topPosition(2) = min(basePosition(2) + basePosition(4) + 0.075,0.92);
topPosition(4) = 0.001;
topAxes = axes("Units","normalized","Position",topPosition,"Color","none","YAxisLocation","right","XAxisLocation","top","YTick",[],"Box","off");
plot(topAxes,baseAxes.XLim,[NaN NaN])
topAxes.XLim = baseAxes.XLim;
topAxes.XTick = baseAxes.XTick;
topAxes.XTickLabel = string(baseAxes.XTick + utcOffset,"dd-MMM HH:mm");
topAxes.YLim = [0 1];
topAxes.YTick = [];
topAxes.YTickLabel = {};
topAxes.YColor = "none";
topAxes.Color = "none";
topAxes.PickableParts = "none";
topAxes.HitTest = "off";
title(topAxes,"Malaysia time (MYT, UTC+8)","FontWeight","normal")
linkaxes([baseAxes topAxes],"x")
end