MATLAB Code
%% Multipath PCA Simulator GUI
function multipath_pca_gui
close all; clear; clc;
% Parameters
N = 200; % Number of samples
t = linspace(0,1,N); % Time vector
% Create Figure
fig = figure('Name','Multipath PCA Simulator','Position',[100 50 1200 700]);
% Axes
ax1 = subplot(3,2,1); title(ax1,'Transmitted Signal'); xlabel(ax1,'Sample Index'); ylabel(ax1,'Amplitude');
ax2 = subplot(3,2,2); title(ax2,'Received Multipath Signals'); xlabel(ax2,'Sample Index'); ylabel(ax2,'Amplitude');
ax3 = subplot(3,2,3); title(ax3,'Eigenvalue Spectrum'); xlabel(ax3,'Principal Component'); ylabel(ax3,'Variance');
ax4 = subplot(3,2,4); title(ax4,'Top Principal Components (PCA)'); xlabel(ax4,'Sample Index'); ylabel(ax4,'PC Value');
ax5 = subplot(3,2,[5,6]); title(ax5,'Reconstructed Signals from Selected PCs'); xlabel(ax5,'Sample Index'); ylabel(ax5,'Amplitude');
% Signal Type Dropdown
uicontrol(fig,'Style','text','Position',[20 660 100 20],'String','Signal Type:');
sigDropdown = uicontrol(fig,'Style','popupmenu','Position',[120 660 120 25],...
'String',{'Sine','Noisy Sine','Random'});
% Number of Paths Slider
uicontrol(fig,'Style','text','Position',[260 660 80 20],'String','Number of Paths:');
pathSlider = uicontrol(fig,'Style','slider','Position',[340 660 150 25],'Min',1,'Max',5,'Value',3,...
'SliderStep',[1/4 1/4]);
pathText = uicontrol(fig,'Style','text','Position',[500 660 30 20],'String','3');
% SNR Slider
uicontrol(fig,'Style','text','Position',[540 660 60 20],'String','SNR(dB):');
snrSlider = uicontrol(fig,'Style','slider','Position',[600 660 150 25],'Min',0,'Max',40,'Value',20,...
'SliderStep',[1/40 5/40]);
snrText = uicontrol(fig,'Style','text','Position',[760 660 30 20],'String','20');
% PC Slider
uicontrol(fig,'Style','text','Position',[800 660 140 20],'String','Principal Components:');
pcSlider = uicontrol(fig,'Style','slider','Position',[950 660 150 25],'Min',1,'Max',3,'Value',1,...
'SliderStep',[1/2 1/2]);
pcText = uicontrol(fig,'Style','text','Position',[1110 660 30 20],'String','1');
% Run Button
runButton = uicontrol(fig,'Style','pushbutton','Position',[20 620 100 30],'String','Run Simulation');
% Shared data
data.N = N; data.t = t; data.ax1=ax1; data.ax2=ax2; data.ax3=ax3;
data.ax4=ax4; data.ax5=ax5; data.V=[]; data.X_rx=[]; data.P=3;
% Assign callbacks
set(runButton,'Callback',@(src,evt) runSimulation());
set(pathSlider,'Callback',@(src,evt) updateSimulation());
set(snrSlider,'Callback',@(src,evt) updateSimulation());
set(sigDropdown,'Callback',@(src,evt) updateSimulation());
set(pcSlider,'Callback',@(src,evt) updateReconstruction());
%% --- Nested functions ---
function runSimulation()
updateSimulation();
end
function updateSimulation()
% Get UI values
P = round(get(pathSlider,'Value')); set(pathText,'String',num2str(P));
snr_db = round(get(snrSlider,'Value')); set(snrText,'String',num2str(snr_db));
signalTypeOptions = {'sine','noisySine','random'};
signalType = signalTypeOptions{get(sigDropdown,'Value')};
data.P = P;
% Generate transmitted signal
switch signalType
case 'sine'
X_tx = sin(2*pi*5*t);
case 'noisySine'
X_tx = sin(2*pi*5*t) + 0.3*(rand(1,N)-0.5);
case 'random'
X_tx = 2*(rand(1,N)-0.5);
end
data.X_tx = X_tx;
% Simulate multipath
X_rx = zeros(P,N);
for p=1:P
fade = 0.2 + 0.8*rand;
delay = randi([0,10]);
pathSig = zeros(1,N);
for n=1:N
if n-delay > 0
pathSig(n) = X_tx(n-delay)*fade;
end
end
pathSig = awgn(pathSig,snr_db,'measured');
X_rx(p,:) = pathSig;
end
data.X_rx = X_rx;
% Plot transmitted
plot(ax1,t,X_tx,'LineWidth',1.5); grid(ax1,'on');
title(ax1,'Transmitted Signal'); xlabel(ax1,'Sample Index'); ylabel(ax1,'Amplitude');
% Plot received
plot(ax2,t,X_rx','LineWidth',1.5); grid(ax2,'on');
title(ax2,'Received Multipath Signals'); xlabel(ax2,'Sample Index'); ylabel(ax2,'Amplitude');
legend(ax2,arrayfun(@(p) sprintf('Path %d',p),1:P,'UniformOutput',false));
% PCA
Xc = X_rx - mean(X_rx,2);
C = (Xc*Xc.')/(N-1);
[V,D] = eig(C);
[eigvals,idx] = sort(diag(D),'descend');
V = V(:,idx);
data.V = V;
% Eigenvalue spectrum
bar(ax3,eigvals); grid(ax3,'on');
title(ax3,'Eigenvalue Spectrum of Covariance Matrix'); xlabel(ax3,'Principal Component'); ylabel(ax3,'Variance');
% Top PCs
Y = V.'*Xc;
plot(ax4,t,Y(1:min(P,2),:),'LineWidth',1.5); grid(ax4,'on');
title(ax4,'Top Principal Components (PCA)'); xlabel(ax4,'Sample Index'); ylabel(ax4,'PC Value');
legend(ax4,arrayfun(@(k) sprintf('PC %d',k),1:min(P,2),'UniformOutput',false));
% Update PC slider max
set(pcSlider,'Max',P,'Value',min(get(pcSlider,'Value'),P));
set(pcText,'String',num2str(round(get(pcSlider,'Value'))));
% Reconstruct
updateReconstruction();
end
function updateReconstruction()
k = round(get(pcSlider,'Value')); set(pcText,'String',num2str(k));
X_rx = data.X_rx; V = data.V; P = data.P;
% Mean-center per path
Xc = X_rx - mean(X_rx,2);
% Project and reconstruct using top k PCs
V_k = V(:,1:k);
Y_k = V_k.'*Xc;
X_recon = V_k*Y_k + mean(X_rx,2);
% Plot reconstructed signals
plot(ax5,t,X_recon','LineWidth',1.5); grid(ax5,'on');
title(ax5,sprintf('Reconstructed Signals using Top %d PCs',k));
xlabel(ax5,'Sample Index'); ylabel(ax5,'Amplitude');
legend(ax5,arrayfun(@(p) sprintf('Path %d',p),1:P,'UniformOutput',false));
% Optional: show combined transmitted estimate
hold(ax5,'on');
combined_estimate = mean(X_recon,1);
plot(ax5,t,combined_estimate,'k--','LineWidth',2);
legend(ax5,[arrayfun(@(p) sprintf('Path %d',p),1:P,'UniformOutput',false), {'Estimated Signal'}]);
hold(ax5,'off');
end
end
Output