├── MATLAB ├── ESPRIT_doa.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp1A.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp1B.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp2.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp3.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp4.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp5A.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp5B.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp6.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp7A.m ├── GENER_Test_Data_DoA_JOURNAL_3D_Exp7B.m ├── GENER_Train_Data_DoA_JOURNAL_3D.m ├── GENER_Train_Data_DoA_JOURNAL_3D_multipleK.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp1A.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp1B.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp1C.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp2.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp3.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp4.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp5A.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp5B.m ├── MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp6.m ├── Q_mat.m ├── ang_spec.m ├── conv2matcom.m ├── conv_cov2vec.m ├── l1_SVD_DoA_est.m ├── optimize_threshold_l1SVD.m ├── plot_experiment1A.m ├── plot_experiment1B.m ├── plot_experiment1C_90deg.m ├── plot_experiment2.m ├── plot_experiment3.m ├── plot_experiment4.m ├── plot_experiment5.m ├── plot_experiment5A.m ├── plot_experiment5B.m ├── plot_experiment6.m ├── plot_experiment7B_SNR0dB.m ├── plot_experiment7B_SNRmin10dB.m ├── unit_ESPRIT.m └── unit_ESPRIT_fast.m ├── Python_CNN ├── CNN_testing_Exp1A_new_training.py ├── CNN_testing_Exp1B_new_training.py ├── CNN_testing_Exp1C_new_training_90deg.py ├── CNN_testing_Exp5A_new_training.py ├── CNN_testing_Exp5B_new_training.py ├── CNN_testing_Exp7A_allSNR_test_0dB.py ├── CNN_testing_Exp7A_allSNR_test_min10dB.py ├── CNN_testing_Exp7B_0dB_unknownK.py ├── CNN_testing_Exp7B_min10dB_unknownK.py ├── CNN_training_allSNR_multipleK_unknownK.py ├── CNN_training_lowSNR_new_training_RQ_test.py └── CNN_training_lowSNR_new_training_RQ_test_90deg.py ├── README.md └── Readme_experiments.txt /MATLAB/ESPRIT_doa.m: -------------------------------------------------------------------------------- 1 | % ESPRIT algorithm for DoA estimation 2 | % Author (implementation): Georgios K. Papageorgiou 3 | % Date: 24/3/2021 4 | 5 | function ang = ESPRIT_doa(R, ds, D, w) 6 | % Row weighting 7 | N = size(R,1); 8 | Ns = N-ds; %number of elements in a subarray 9 | 10 | % Row weighting 11 | weights = diag(sqrt([1:w-1 w*ones(1,Ns-2*(w-1)) w-1:-1:1])); % Eq 9.132 in [1] 12 | O = zeros(Ns,ds); 13 | 14 | % Selection Matrices 15 | Js1 = [weights O]; % Eq 9.134 in [1] 16 | Js2 = [O weights]; % Eq 9.135 in [1] 17 | 18 | % % Selection Matrices 19 | % Js1 = [eye(Ns) zeros(Ns, ds)]; % Eq 9.134 in [1] 20 | % Js2 = [zeros(Ns,ds) eye(Ns)]; % Eq 9.135 in [1] 21 | 22 | % Check for positive semi definite 23 | [eigenvects,sED] = eig((R+R')/2); % ensure Hermitian 24 | sED = diag(sED); 25 | diagEigenVals = sED; 26 | 27 | %Sort eigenvectors 28 | [~,indx] = sort(diagEigenVals,'descend'); 29 | eigenvects = eigenvects(:,indx); 30 | 31 | % Selecting subarray signal subspaces 32 | Us1 = Js1*eigenvects(:,1:D); 33 | Us2 = Js2*eigenvects(:,1:D); 34 | 35 | % TLS-ESPRIT 36 | C = [Us1';Us2']*[Us1 Us2]; % Eq. (9.123) in [1] 37 | [U,~,~] = svd(C); % C is 2*D x 2*D 38 | V12 = U(1:D,D+1:2*D); % D x D 39 | V22 = U(D+1:2*D,D+1:2*D); % D x D 40 | psi = -V12/V22; % Eq. (9.122) in [1] 41 | psieig = eig(psi); 42 | % Extract angle information estimated from two subarrays based on the 43 | % distance of the phase center between subarrays. 44 | doas = angle(psieig)/ds; 45 | 46 | %Convert estimated angle in sin-space to degrees. This method is valid for 47 | %ULA only. 48 | elSpacing = 0.5; % half-sapced ULAs 49 | u = doas/(2*pi*elSpacing); 50 | 51 | % check whether all elements of u are within [-1,1] 52 | idx = find(abs(u)<=1/ds); 53 | if length(idx) 1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 32 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 33 | w = min(ms,ULA.N-ds-ms+1); % Eq 9.133 in [1] 34 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 36 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 37 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 | SOURCE.power = ones(1,SOURCE.K).^2; 39 | noise_power = min(SOURCE.power)*10^(-SNR_dB/10); 40 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 41 | 42 | % l1-SVD threshold 43 | threshold = 550; 44 | l1_SVD_doa_est = zeros(SOURCE.K,Nsim); 45 | UnESPRIT_doa_est = zeros(SOURCE.K,Nsim); 46 | 47 | theta(1) = - SOURCE.interval; 48 | theta(2) = theta(1) + ang_sep; 49 | 50 | for i=1:Nsim 51 | %theta1 = sort(datasample(Reg,SOURCE.K,'Replace',false)); 52 | A_ula =zeros(ULA.N,SOURCE.K); 53 | %theta = zeros(1,SOURCE.K); 54 | for k=1:SOURCE.K 55 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA.N); 56 | end 57 | 58 | % The true covariance matrix 59 | Ry_the = A_ula*diag(ones(SOURCE.K,1))*A_ula' + noise_power*eye(ULA.N); 60 | % The signal plus noise 61 | S = (randn(SOURCE.K,T)+1j*randn(SOURCE.K,T))/sqrt(2); 62 | X = A_ula*S; 63 | Eta = sqrt(noise_power)*(randn(ULA.N,T)+1j*randn(ULA.N,T))/sqrt(2); 64 | Y = X + Eta; 65 | 66 | % Calculate the l1-SVD performance without storing the MMV data - Y 67 | [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA.N,threshold,SOURCE.K, THETA_angles); 68 | l1_SVD_doa_est(:,i) = sort(ang_est_l1svd)'; 69 | 70 | % Un-ESPRIT results 71 | doas_unit_ESPRIT_sam = unit_ESPRIT(Y, T, ds, SOURCE.K, w); 72 | UnESPRIT_doa_est(:,i) = sort(doas_unit_ESPRIT_sam); 73 | % The sample covariance matrix 74 | Ry_sam = Y*Y'/T; 75 | 76 | % Real and Imaginary part for the sample matrix 77 | r.sam(:,:,1,i) = real(Ry_sam); 78 | r.sam(:,:,2,i) = imag(Ry_sam); 79 | r.sam(:,:,3,i) = angle(Ry_sam); 80 | 81 | % Real and Imaginary part for the theor. covariance matrix R 82 | r.the(:,:,1,i) = real(Ry_the); 83 | r.the(:,:,2,i) = imag(Ry_the); 84 | r.the(:,:,3,i) = angle(Ry_the); 85 | 86 | % The angles - Ground Truth 87 | r.angles(:,i) = theta'; 88 | 89 | theta = theta+1; 90 | i 91 | end 92 | 93 | time_tot = toc/60; % in minutes 94 | 95 | % Save all variables 96 | h5create(filename,'/sam', size(r.sam)); 97 | h5write(filename, '/sam', r.sam); 98 | h5create(filename,'/theor',size(r.the)); 99 | h5write(filename, '/theor', r.the); 100 | h5create(filename,'/angles',size(r.angles)); 101 | h5write(filename, '/angles', r.angles); 102 | h5create(filename2,'/l1_SVD_ang',size(l1_SVD_doa_est)); 103 | h5write(filename2, '/l1_SVD_ang', l1_SVD_doa_est); 104 | h5create(filename3,'/UnESPRIT_ang',size(UnESPRIT_doa_est)); 105 | h5write(filename3, '/UnESPRIT_ang', UnESPRIT_doa_est); 106 | %h5disp(filename); 107 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp1B.m: -------------------------------------------------------------------------------- 1 | % DoA estimation via DNN: Training DATA 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 4/7/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | %clc; 9 | tic; 10 | rng(14); 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Location of the data 13 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 14 | 'TEST_DATA_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11.h5'); 15 | % Location of the l1-SVD results (without saving the y data-RMSE only) 16 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 17 | 'RMSE_l1SVD_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11.h5'); 18 | filename3 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 19 | 'RMSE_UnESPRIT_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11.h5'); 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21 | T = 200; % number of snapshots 22 | SNR_dB = 0; % SNR values 23 | SOURCE.K = 2; % number of sources/targets - Kmax 24 | ULA.N = 16; 25 | SOURCE.interval = 60; 26 | Nsim = 118; 27 | res = 1; 28 | ang_sep = 2.11; % in degrees 29 | % UnESPRIT pars 30 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 31 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 32 | w = min(ms,ULA.N-ds-ms+1); % Eq 9.133 in [1] 33 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 34 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 35 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 36 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37 | SOURCE.power = ones(1,SOURCE.K).^2; 38 | noise_power = min(SOURCE.power)*10^(-SNR_dB/10); 39 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 40 | 41 | % Threshold for the l1-SVD 42 | threshold = 60; 43 | l1_SVD_doa_est = zeros(SOURCE.K,Nsim); 44 | UnESPRIT_doa_est = zeros(SOURCE.K,Nsim); 45 | MSE_l1_svd = 0; 46 | 47 | theta(1) = - 59.5; 48 | theta(2) = theta(1) + ang_sep; 49 | 50 | for i=1:Nsim 51 | %theta1 = sort(datasample(Reg,SOURCE.K,'Replace',false)); 52 | A_ula =zeros(ULA.N,SOURCE.K); 53 | %theta = zeros(1,SOURCE.K); 54 | for k=1:SOURCE.K 55 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA.N); 56 | end 57 | 58 | % The true covariance matrix 59 | Ry_the = A_ula*diag(ones(SOURCE.K,1))*A_ula' + noise_power*eye(ULA.N); 60 | % The signal plus noise 61 | S = (randn(SOURCE.K,T)+1j*randn(SOURCE.K,T))/sqrt(2); 62 | X = A_ula*S; 63 | Eta = sqrt(noise_power)*(randn(ULA.N,T)+1j*randn(ULA.N,T))/sqrt(2); 64 | Y = X + Eta; 65 | 66 | % Calculate the l1-SVD performance without storing the MMV data - Y 67 | [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA.N,threshold,SOURCE.K, THETA_angles); 68 | l1_SVD_doa_est(:,i) = sort(ang_est_l1svd); 69 | 70 | % Un-ESPRIT results 71 | doas_unit_ESPRIT_sam = unit_ESPRIT(Y, T, ds, SOURCE.K, w); 72 | UnESPRIT_doa_est(:,i) = sort(doas_unit_ESPRIT_sam); 73 | 74 | % The sample covariance matrix 75 | Ry_sam = Y*Y'/T; 76 | 77 | % Real and Imaginary part for the sample matrix 78 | r.sam(:,:,1,i) = real(Ry_sam); 79 | r.sam(:,:,2,i) = imag(Ry_sam); 80 | r.sam(:,:,3,i) = angle(Ry_sam); 81 | 82 | % Real and Imaginary part for the theor. covariance matrix R 83 | r.the(:,:,1,i) = real(Ry_the); 84 | r.the(:,:,2,i) = imag(Ry_the); 85 | r.the(:,:,3,i) = angle(Ry_the); 86 | 87 | % The angles - Ground Truth 88 | r.angles(:,i) = theta'; 89 | 90 | MSE_l1_svd = MSE_l1_svd + norm(r.angles(:,i)-l1_SVD_doa_est(:,i))^2; 91 | 92 | theta = theta+1; 93 | i 94 | end 95 | 96 | RMSE_l1_svd = sqrt(MSE_l1_svd/Nsim/SOURCE.K); 97 | time_tot = toc/60; % in minutes 98 | 99 | % Save the variables in the specified locations 100 | h5create(filename,'/sam', size(r.sam)); 101 | h5write(filename, '/sam', r.sam); 102 | h5create(filename,'/theor',size(r.the)); 103 | h5write(filename, '/theor', r.the); 104 | h5create(filename,'/angles',size(r.angles)); 105 | h5write(filename, '/angles', r.angles); 106 | h5create(filename2,'/l1_SVD_ang',size(l1_SVD_doa_est)); 107 | h5write(filename2, '/l1_SVD_ang', l1_SVD_doa_est); 108 | h5create(filename3,'/UnESPRIT_ang',size(UnESPRIT_doa_est)); 109 | h5write(filename3, '/UnESPRIT_ang', UnESPRIT_doa_est); 110 | %h5disp(filename); 111 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp2.m: -------------------------------------------------------------------------------- 1 | % TESTING DATA Generator - Experiment 2 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 19/9/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | %clc; 9 | tic; 10 | rng(14); 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Save the data 13 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 14 | 'TEST_DATA1K_16ULA_K2_fixed_offgrid_ang_allSNR_T1000_3D.h5'); 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | T = 1000; % number of snapshots 17 | SNR_dB_vec = -20:5:30; % SNR values 18 | SOURCE_K = 2; % number of sources/targets - Kmax 19 | ULA_N = 16; 20 | SOURCE.interval = 60; 21 | Nsim = 1e+3; 22 | res = 1; 23 | % UnESPRIT pars 24 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 25 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 26 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 27 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 28 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 29 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 30 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 | SOURCE_power = ones(1,SOURCE_K).^2; 32 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 33 | 34 | % These are the angles with D\theta_min=1 degree 35 | theta(1) = 10.11; 36 | theta(2) = 13.3; 37 | 38 | A_ula =zeros(ULA_N,SOURCE_K); 39 | for k=1:SOURCE_K 40 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA_N); 41 | end 42 | 43 | R_sam = zeros(ULA_N,ULA_N,3,Nsim,length(SNR_dB_vec)); 44 | R_the = zeros(ULA_N,ULA_N,3,Nsim,length(SNR_dB_vec)); 45 | RMSE_l1SVD = zeros(1,length(SNR_dB_vec)); 46 | RMSE_UnESPRIT = zeros(1,length(SNR_dB_vec)); 47 | 48 | threshold_vec = [1260 700 400 230 140 100 70 70 60 60 60]; 49 | 50 | parfor ii=1:length(SNR_dB_vec) 51 | SNR_dB = SNR_dB_vec(ii); 52 | noise_power = min(SOURCE_power)*10^(-SNR_dB/10); 53 | 54 | r_sam = zeros(ULA_N,ULA_N,3,Nsim); 55 | r_the = zeros(ULA_N,ULA_N,3,Nsim); 56 | Y_dr = zeros(ULA_N,ULA_N,Nsim); 57 | mse_l1svd = 0; 58 | mse_unesp = 0; 59 | 60 | for i=1:Nsim 61 | 62 | % The true covariance matrix 63 | Ry_the = A_ula*diag(ones(SOURCE_K,1))*A_ula' + noise_power*eye(ULA_N); 64 | % The signal plus noise 65 | S = (randn(SOURCE_K,T)+1j*randn(SOURCE_K,T))/sqrt(2); 66 | X = A_ula*S; 67 | Eta = sqrt(noise_power)*(randn(ULA_N,T)+1j*randn(ULA_N,T))/sqrt(2); 68 | Y = X + Eta; 69 | % The sample covariance matrix 70 | Ry_sam = Y*Y'/T; 71 | 72 | % Real and Imaginary part for the sample matrix 73 | r_sam(:,:,1,i) = real(Ry_sam); 74 | r_sam(:,:,2,i) = imag(Ry_sam); 75 | r_sam(:,:,3,i) = angle(Ry_sam); 76 | 77 | r_the(:,:,1,i) = real(Ry_the); 78 | r_the(:,:,2,i) = imag(Ry_the); 79 | r_the(:,:,3,i) = angle(Ry_the); 80 | 81 | % l1_SVD exploiting group sparsity 82 | threshold = threshold_vec(ii); 83 | [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA_N,threshold,SOURCE_K, THETA_angles); 84 | mse_l1svd = mse_l1svd + norm(sort(ang_est_l1svd) - theta')^2; 85 | 86 | % Un-ESPRIT results 87 | doas_unit_ESPRIT_sam = unit_ESPRIT(Y, T, ds, SOURCE_K, w); 88 | mse_unesp = mse_unesp + norm(sort(doas_unit_ESPRIT_sam) - theta')^2; 89 | 90 | end 91 | R_sam(:,:,:,:,ii) = r_sam; 92 | R_the(:,:,:,:,ii) = r_the; 93 | RMSE_l1SVD(ii) = sqrt(mse_l1svd/SOURCE_K/Nsim); 94 | RMSE_UnESPRIT(ii) = sqrt(mse_unesp/SOURCE_K/Nsim); 95 | ii 96 | end 97 | angles = theta; 98 | 99 | time_tot = toc/60; % in minutes 100 | 101 | h5create(filename,'/sam', size(R_sam)); 102 | h5write(filename, '/sam', R_sam); 103 | h5create(filename,'/the', size(R_the)); 104 | h5write(filename, '/the', R_the); 105 | h5create(filename,'/angles',size(angles)); 106 | h5write(filename, '/angles', angles); 107 | h5create(filename,'/RMSE_l1SVD',size(RMSE_l1SVD)); 108 | h5write(filename, '/RMSE_l1SVD', RMSE_l1SVD); 109 | h5create(filename,'/RMSE_UnESPRIT',size(RMSE_UnESPRIT)); 110 | h5write(filename, '/RMSE_UnESPRIT', RMSE_UnESPRIT); 111 | %h5disp(filename); 112 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp3.m: -------------------------------------------------------------------------------- 1 | % TESTING DATA Generator 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 19/9/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | rng(2015); 9 | tic; 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | % Save the data 12 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 13 | 'TEST_DATA1K_16ULA_K2_min10dBSNR_3D_fixed_ang_sep3coma6_vsT.h5'); 14 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 15 | 'RMSE_l1_SVD_DATA1K_16ULA_K2_min10dBSNR_3D_fixed_ang_sep3coma6_vsT.h5'); 16 | filename3 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 17 | 'RMSE_UnESPRIT_DATA1K_16ULA_K2_min10dBSNR_3D_fixed_ang_sep3coma6_vsT.h5'); 18 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 19 | ang_sep = 3.6; 20 | SNR_dB = -10; 21 | T_vec = 1000*[0.1 0.2 0.5 1 2 5 10]; % SNR values 22 | SOURCE_K = 2; % number of sources/targets - Kmax 23 | ULA_N = 16; 24 | SOURCE.interval = 60; 25 | Nsim = 1000; 26 | % UnESPRIT pars 27 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 28 | reweight = 8; % if 1 the weights are equal if reweight>1 there are higher weights at the reweight center elements of each subarray 29 | w = min(reweight,ULA_N-ds-reweight+1); 30 | Ns = ULA_N-ds; 31 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 32 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 33 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 34 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 | SOURCE.power = ones(1,SOURCE_K).^2; 36 | noise_power = min(SOURCE.power)*10^(-SNR_dB/10); 37 | % grid 38 | res = 1; 39 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 40 | thresh_vec = [130 180 270 410 570 910 1280]; 41 | 42 | % These are the angles 43 | theta(1) = -13.18; 44 | theta(2) = theta(1) + ang_sep; 45 | 46 | A_ula =zeros(ULA_N,SOURCE_K); 47 | for k=1:SOURCE_K 48 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA_N); 49 | end 50 | 51 | % Initialization 52 | RMSE_l1SVD = zeros(1,length(T_vec)); 53 | RMSE_UnESPRIT = zeros(1,length(T_vec)); 54 | R_sam = zeros(ULA_N,ULA_N,3,Nsim,length(T_vec)); 55 | 56 | parfor ii=1:length(T_vec) 57 | T = T_vec(ii); 58 | threshold = thresh_vec(ii); 59 | 60 | mse_l1svd = 0; 61 | mse_unesp = 0; 62 | r_sam = zeros(ULA_N,ULA_N,3,Nsim); 63 | 64 | for i=1:Nsim 65 | 66 | % The true covariance matrix 67 | Ry_the = A_ula*diag(ones(SOURCE_K,1))*A_ula' + noise_power*eye(ULA_N); 68 | % The signal plus noise 69 | S = (randn(SOURCE_K,T)+1j*randn(SOURCE_K,T))/sqrt(2); 70 | X = A_ula*S; 71 | Eta = sqrt(noise_power)*(randn(ULA_N,T)+1j*randn(ULA_N,T))/sqrt(2); 72 | Y = X + Eta; 73 | % The sample covariance matrix 74 | Ry_sam = Y*Y'/T; 75 | 76 | % Real and Imaginary part for the sample matrix 77 | r_sam(:,:,1,i) = real(Ry_sam); 78 | r_sam(:,:,2,i) = imag(Ry_sam); 79 | r_sam(:,:,3,i) = angle(Ry_sam); 80 | 81 | % % l1_SVD exploiting group sparsity 82 | % [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA_N,threshold,SOURCE_K, THETA_angles); 83 | % mse_l1svd = mse_l1svd + norm(sort(ang_est_l1svd) - sort(theta)')^2; 84 | % 85 | % Un-ESPRIT results 86 | weights = diag(sqrt([1:w-1 w*ones(1,Ns-2*(w-1)) w-1:-1:1])); % Eq 9.132 in [1] 87 | O = zeros(Ns,ds); 88 | % Js1 = [weights O]; % don't really need that 89 | J2 = [O weights]; 90 | % Calculate the Q matrices 91 | QNs = Q_mat(Ns); 92 | QN = Q_mat(ULA_N); 93 | Q2T = Q_mat(2*T); 94 | 95 | % The real-valued data matrix 96 | TX = QN'*[Y flip(eye(ULA_N))*conj(Y)*flip(eye(T))]*Q2T; 97 | % Sample covariance of the real-valued data 98 | Rx_est = TX*TX'/(2*T); 99 | 100 | doas_unit_ESPRIT_sam = unit_ESPRIT_fast(Rx_est, ds, SOURCE_K, w); 101 | mse_unesp = mse_unesp + norm(sort(doas_unit_ESPRIT_sam) - sort(theta)')^2; 102 | 103 | end 104 | R_sam(:,:,:,:,ii) = r_sam; 105 | RMSE_l1SVD(ii) = sqrt(mse_l1svd/SOURCE_K/Nsim); 106 | RMSE_UnESPRIT(ii) = sqrt(mse_unesp/SOURCE_K/Nsim); 107 | ii 108 | end 109 | 110 | time_tot = toc/60; % in minutes 111 | 112 | % figure(1); 113 | % plot(T_vec,RMSE_l1SVD,'*--m'); 114 | % hold on; 115 | % plot(T_vec,RMSE_UnESPRIT,'s-.m'); 116 | % hold off; 117 | % grid on; 118 | % set(gca, 'YScale', 'log'); 119 | % ylabel('RMSE [degrees]', 'interpreter','latex'); 120 | % xlabel('T [snapshots] $\times 100$', 'interpreter','latex'); 121 | % xticks([1 2 5 10 20 50 100]*100); 122 | % xticklabels([1 2 5 10 20 50 100]); 123 | 124 | % Save the data 125 | % h5create(filename,'/sam', size(R_sam)); 126 | % h5write(filename, '/sam', R_sam); 127 | % h5create(filename,'/angles',size(theta)); 128 | % h5write(filename, '/angles', theta); 129 | % h5create(filename2,'/RMSE_l1_SVD',size(RMSE_l1SVD)); 130 | % h5write(filename2, '/RMSE_l1_SVD', RMSE_l1SVD); 131 | h5create(filename3,'/RMSE_UnESPRIT',size(RMSE_UnESPRIT)); 132 | h5write(filename3, '/RMSE_UnESPRIT', RMSE_UnESPRIT); 133 | % h5disp(filename3); 134 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp4.m: -------------------------------------------------------------------------------- 1 | % TESTING DATA Generator 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 19/9/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | clc; 9 | rng(14); % def 14 10 | tic; 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Location to save the data 13 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 14 | 'TEST_DATA1K_16ULA_K2_min10dBSNR_T500_3D_vs_ang_sep_v2.h5'); 15 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 16 | 'RMSE_l1_SVD_16ULA_K2_min10dBSNR_T500_3D_vs_ang_sep_v2.h5'); 17 | filename3 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 18 | 'RMSE_UnESPRIT_16ULA_K2_min10dBSNR_T500_3D_vs_ang_sep_v2.h5'); 19 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 20 | T = 500; % number of snapshots 21 | SNR_dB = -10; 22 | ang_sep_vec = [1 2 4 6 10 14]; % SNR values 23 | SOURCE_K = 2; % number of sources/targets - Kmax 24 | ULA_N = 16; 25 | SOURCE.interval = 60; 26 | Nsim = 10; 27 | res = 1; 28 | % UnESPRIT pars 29 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 30 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 31 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 32 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 33 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 34 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | SOURCE.power = ones(1,SOURCE_K).^2; 37 | noise_power = min(SOURCE.power)*10^(-SNR_dB/10); 38 | % grid 39 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 40 | 41 | % l1-SVD threshold parameter 42 | threshold = 290; 43 | % Angles 44 | % theta(1) = - 13.8; 45 | theta(1) = - 13.8; 46 | theta_all = [theta(1)*ones(1,length(ang_sep_vec)); theta(1) + ang_sep_vec]; 47 | 48 | % Initialization 49 | RMSE_l1SVD = zeros(1,length(ang_sep_vec)); 50 | RMSE_UnESPRIT = zeros(1,length(ang_sep_vec)); 51 | R_sam = zeros(ULA_N,ULA_N,3,Nsim,length(ang_sep_vec)); 52 | for ii=1:length(ang_sep_vec) 53 | 54 | A_ula =zeros(ULA_N,SOURCE_K); 55 | for k=1:SOURCE_K 56 | A_ula(:,k) = ULA_steer_vec(theta_all(k,ii),ULA_N); 57 | end 58 | mse_l1svd = 0; 59 | mse_unesp = 0; 60 | r_sam = zeros(ULA_N,ULA_N,3,Nsim); 61 | 62 | for i=1:Nsim 63 | 64 | % The signal plus noise 65 | S = (randn(SOURCE_K,T)+1j*randn(SOURCE_K,T))/sqrt(2); 66 | X = A_ula*S; 67 | Eta = sqrt(noise_power)*(randn(ULA_N,T)+1j*randn(ULA_N,T))/sqrt(2); 68 | Y = X + Eta; 69 | % The sample covariance matrix 70 | Ry_sam = Y*Y'/T; 71 | 72 | % Real and Imaginary part for the sample matrix 73 | r_sam(:,:,1,i) = real(Ry_sam); 74 | r_sam(:,:,2,i) = imag(Ry_sam); 75 | r_sam(:,:,3,i) = angle(Ry_sam); 76 | 77 | % l1_SVD exploiting group sparsity 78 | [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA_N,threshold,SOURCE_K, THETA_angles); 79 | mse_l1svd = mse_l1svd + norm(sort(ang_est_l1svd) - theta_all(:,ii))^2; 80 | 81 | % Un-ESPRIT results 82 | doas_unit_ESPRIT_sam = unit_ESPRIT(Y, T, ds, SOURCE_K, w); 83 | mse_unesp = mse_unesp + norm(sort(doas_unit_ESPRIT_sam) - theta_all(:,ii))^2; 84 | 85 | end 86 | R_sam(:,:,:,:,ii) = r_sam; 87 | RMSE_l1SVD(ii) = sqrt(mse_l1svd/SOURCE_K/Nsim); 88 | RMSE_UnESPRIT(ii) = sqrt(mse_unesp/SOURCE_K/Nsim); 89 | ii 90 | end 91 | 92 | time_tot = toc/60; % in minutes 93 | 94 | figure(1); 95 | plot(ang_sep_vec,RMSE_l1SVD,'--ob'); 96 | hold on; 97 | plot(ang_sep_vec,RMSE_UnESPRIT,'--or'); 98 | hold off; 99 | 100 | % 101 | h5create(filename,'/sam', size(R_sam)); 102 | h5write(filename, '/sam', R_sam); 103 | h5create(filename,'/angles',size(theta_all)); 104 | h5write(filename, '/angles', theta_all); 105 | h5create(filename2,'/RMSE_l1_SVD',size(RMSE_l1SVD)); 106 | h5write(filename2, '/RMSE_l1_SVD', RMSE_l1SVD); 107 | h5create(filename3,'/RMSE_UnESPRIT',size(RMSE_UnESPRIT)); 108 | h5write(filename3, '/RMSE_UnESPRIT', RMSE_UnESPRIT); 109 | h5disp(filename); 110 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp5A.m: -------------------------------------------------------------------------------- 1 | % DoA estimation via CNN: Exp. 5A 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 20/09/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | %clc; 9 | tic; 10 | rng(14); 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Location of the data 13 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 14 | 'TEST_DATA_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11_power_mismatch.h5'); 15 | % Location of the l1-SVD results (without saving the y data-RMSE only) 16 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 17 | 'RMSE_l1SVD_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11_power_mismatch.h5'); 18 | % Location for saving the UnESPRIT results (no y data saved-just processed) 19 | filename3 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 20 | 'RMSE_UnESPRIT_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11_power_mismatch.h5'); 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 | T = 200; % number of snapshots 23 | SNR_dB = 0; % SNR values 24 | SOURCE.K = 2; % number of sources/targets - Kmax 25 | ULA.N = 16; 26 | SOURCE.interval = 60; 27 | Nsim = 118; 28 | res = 1; 29 | ang_sep = 2.11; % in degrees 30 | % UnESPRIT pars 31 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 32 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 33 | w = min(ms,ULA.N-ds-ms+1); % Eq 9.133 in [1] 34 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 36 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 37 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 | SOURCE.power = ones(1,SOURCE.K).^2; 39 | noise_power = min(SOURCE.power)*10^(-SNR_dB/10); 40 | SOURCE.true_power = [0.7, 1.25]; 41 | true_SNR = 10*log10(min(SOURCE.true_power)/noise_power); 42 | 43 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 44 | 45 | % Threshold for the l1-SVD 46 | threshold = 60; 47 | l1_SVD_doa_est = zeros(SOURCE.K,Nsim); 48 | UnESPRIT_doa_est = zeros(SOURCE.K,Nsim); 49 | MSE_l1_svd = 0; 50 | MSE_unesp = 0; 51 | 52 | theta(1) = -59.5; 53 | theta(2) = theta(1) + ang_sep; 54 | 55 | for i=1:Nsim 56 | %theta1 = sort(datasample(Reg,SOURCE.K,'Replace',false)); 57 | A_ula =zeros(ULA.N,SOURCE.K); 58 | %theta = zeros(1,SOURCE.K); 59 | for k=1:SOURCE.K 60 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA.N); 61 | end 62 | 63 | % The true covariance matrix 64 | % Ry_the = A_ula*diag(SOURCE.true_power)*A_ula' + noise_power*eye(ULA.N); 65 | % The signal plus noise 66 | S = sqrt(SOURCE.true_power)'.*(randn(SOURCE.K,T)+1j*randn(SOURCE.K,T))/sqrt(2); 67 | X = A_ula*S; 68 | Eta = sqrt(noise_power)*(randn(ULA.N,T)+1j*randn(ULA.N,T))/sqrt(2); 69 | Y = X + Eta; 70 | 71 | % Calculate the l1-SVD performance without storing the MMV data - Y 72 | [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA.N,threshold,SOURCE.K, THETA_angles); 73 | l1_SVD_doa_est(:,i) = sort(ang_est_l1svd); 74 | 75 | % Un-ESPRIT results 76 | doas_unit_ESPRIT_sam = unit_ESPRIT(Y, T, ds, SOURCE.K, w); 77 | UnESPRIT_doa_est(:,i) = sort(doas_unit_ESPRIT_sam); 78 | 79 | % The sample covariance matrix 80 | Ry_sam = Y*Y'/T; 81 | 82 | % % Real and Imaginary part for the sample matrix 83 | r.sam(:,:,1,i) = real(Ry_sam); 84 | r.sam(:,:,2,i) = imag(Ry_sam); 85 | r.sam(:,:,3,i) = angle(Ry_sam); 86 | 87 | % The angles - Ground Truth 88 | r.angles(:,i) = theta'; 89 | 90 | MSE_l1_svd = MSE_l1_svd + norm(r.angles(:,i)-l1_SVD_doa_est(:,i))^2; 91 | 92 | MSE_unesp = MSE_unesp + norm(r.angles(:,i)-UnESPRIT_doa_est(:,i))^2; 93 | 94 | 95 | theta = theta+1; 96 | i 97 | end 98 | 99 | RMSE_l1_svd = sqrt(MSE_l1_svd/Nsim/SOURCE.K); 100 | RMSE_unesp = sqrt(MSE_unesp/Nsim/SOURCE.K); 101 | time_tot = toc/60; % in minutes 102 | 103 | % Save the variables in the specified locations 104 | h5create(filename,'/sam', size(r.sam)); 105 | h5write(filename, '/sam', r.sam); 106 | h5create(filename,'/angles',size(r.angles)); 107 | h5write(filename, '/angles', r.angles); 108 | h5create(filename2,'/l1_SVD_ang',size(l1_SVD_doa_est)); 109 | h5write(filename2, '/l1_SVD_ang', l1_SVD_doa_est); 110 | h5create(filename3,'/UnESPRIT_ang',size(UnESPRIT_doa_est)); 111 | h5write(filename3, '/UnESPRIT_ang', UnESPRIT_doa_est); 112 | h5disp(filename); 113 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp5B.m: -------------------------------------------------------------------------------- 1 | % DoA estimation via CNN: Exp. 5B 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 20/09/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | %clc; 9 | tic; 10 | rng(14); 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Location of the data 13 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 14 | 'TEST_DATA_16ULA_K2_min10dBSNR_T1000_3D_slideang_offgrid_sep4_power_mismatch.h5'); 15 | % Location of the l1-SVD results (without saving the y data-RMSE only) 16 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 17 | 'RMSE_l1SVD_16ULA_K2_min10dBSNR_T1000_3D_slideang_offgrid_sep4_power_mismatch.h5'); 18 | filename3 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 19 | 'RMSE_UnESPRIT_16ULA_K2_min10dBSNR_T1000_3D_slideang_offgrid_sep4_power_mismatch.h5'); 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21 | T = 1000; % number of snapshots 22 | SNR_dB = -10; % SNR values 23 | SOURCE.K = 2; % number of sources/targets - Kmax 24 | ULA.N = 16; 25 | SOURCE.interval = 60; 26 | Nsim = 116; 27 | res = 1; 28 | ang_sep = 4; % in degrees 29 | % UnESPRIT pars 30 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 31 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 32 | w = min(ms,ULA.N-ds-ms+1); % Eq 9.133 in [1] 33 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 34 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 35 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 36 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37 | SOURCE.power = ones(1,SOURCE.K).^2; 38 | noise_power = min(SOURCE.power)*10^(-SNR_dB/10); 39 | SOURCE.true_power = [0.7, 1.25]; 40 | true_SNR = 10*log10(min(SOURCE.true_power)/noise_power); 41 | 42 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 43 | 44 | % Threshold for the l1-SVD 45 | threshold = 400; 46 | l1_SVD_doa_est = zeros(SOURCE.K,Nsim); 47 | UnESPRIT_doa_est = zeros(SOURCE.K,Nsim); 48 | MSE_l1_svd = 0; 49 | MSE_unesp = 0; 50 | 51 | theta(1) = -59.43; 52 | theta(2) = theta(1) + ang_sep; 53 | 54 | for i=1:Nsim 55 | %theta1 = sort(datasample(Reg,SOURCE.K,'Replace',false)); 56 | A_ula =zeros(ULA.N,SOURCE.K); 57 | %theta = zeros(1,SOURCE.K); 58 | for k=1:SOURCE.K 59 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA.N); 60 | end 61 | 62 | % The true covariance matrix 63 | % Ry_the = A_ula*diag(SOURCE.true_power)*A_ula' + noise_power*eye(ULA.N); 64 | % The signal plus noise 65 | S = sqrt(SOURCE.true_power)'.*(randn(SOURCE.K,T)+1j*randn(SOURCE.K,T))/sqrt(2); 66 | X = A_ula*S; 67 | Eta = sqrt(noise_power)*(randn(ULA.N,T)+1j*randn(ULA.N,T))/sqrt(2); 68 | Y = X + Eta; 69 | 70 | % Calculate the l1-SVD performance without storing the MMV data - Y 71 | [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA.N,threshold,SOURCE.K, THETA_angles); 72 | l1_SVD_doa_est(:,i) = sort(ang_est_l1svd); 73 | 74 | % Un-ESPRIT results 75 | doas_unit_ESPRIT_sam = unit_ESPRIT(Y, T, ds, SOURCE.K, w); 76 | UnESPRIT_doa_est(:,i) = sort(doas_unit_ESPRIT_sam); 77 | 78 | % The sample covariance matrix 79 | Ry_sam = Y*Y'/T; 80 | 81 | % % Real and Imaginary part for the sample matrix 82 | r.sam(:,:,1,i) = real(Ry_sam); 83 | r.sam(:,:,2,i) = imag(Ry_sam); 84 | r.sam(:,:,3,i) = angle(Ry_sam); 85 | 86 | % The angles - Ground Truth 87 | r.angles(:,i) = theta'; 88 | 89 | MSE_l1_svd = MSE_l1_svd + norm(r.angles(:,i)-l1_SVD_doa_est(:,i))^2; 90 | MSE_unesp = MSE_unesp + norm(r.angles(:,i)-UnESPRIT_doa_est(:,i))^2; 91 | 92 | theta = theta+1; 93 | i 94 | end 95 | 96 | RMSE_l1_svd = sqrt(MSE_l1_svd/Nsim/SOURCE.K); 97 | RMSE_unesp = sqrt(MSE_unesp/Nsim/SOURCE.K); 98 | time_tot = toc/60; % in minutes 99 | 100 | % Save the variables in the specified locations 101 | h5create(filename,'/sam', size(r.sam)); 102 | h5write(filename, '/sam', r.sam); 103 | h5create(filename,'/angles',size(r.angles)); 104 | h5write(filename, '/angles', r.angles); 105 | h5create(filename2,'/l1_SVD_ang',size(l1_SVD_doa_est)); 106 | h5write(filename2, '/l1_SVD_ang', l1_SVD_doa_est); 107 | h5create(filename3,'/UnESPRIT_ang',size(UnESPRIT_doa_est)); 108 | h5write(filename3, '/UnESPRIT_ang', UnESPRIT_doa_est); 109 | h5disp(filename3); 110 | 111 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp6.m: -------------------------------------------------------------------------------- 1 | % TESTING DATA Generator - Experiment 2 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 19/9/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | %clc; 9 | tic; 10 | rng(14); 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Save the data 13 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 14 | 'TEST_DATA1K_3D_16ULA_K2_fixed_ang_sep3coma8_min10dBSNR_T1000_vsrho.h5'); 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | rho_vec = 0:0.1:1; % SNR values 17 | SNR_dB = -10; 18 | T = 1000; % number of snapshots 19 | SOURCE_K = 2; % number of sources/targets - Kmax 20 | SOURCE_power = ones(SOURCE_K,1); 21 | noise_power = min(SOURCE_power)*10^(-SNR_dB/10); 22 | ULA_N = 16; 23 | SOURCE.interval = 60; 24 | Nsim = 1e+3; 25 | res = 1; 26 | % UnESPRIT pars 27 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 28 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 29 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 30 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 32 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 33 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 34 | SOURCE_power = ones(1,SOURCE_K).^2; 35 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 36 | 37 | % These are the angles with D\theta_min=1 degree 38 | theta(1) = 10; 39 | theta(2) = 13.8; 40 | 41 | A_ula =zeros(ULA_N,SOURCE_K); 42 | for k=1:SOURCE_K 43 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA_N); 44 | end 45 | 46 | R_sam = zeros(ULA_N,ULA_N,3,Nsim,length(rho_vec)); 47 | R_the = zeros(ULA_N,ULA_N,3,Nsim,length(rho_vec)); 48 | RMSE_l1SVD = zeros(1,length(rho_vec)); 49 | RMSE_UnESPRIT = zeros(1,length(rho_vec)); 50 | 51 | eta = 400; 52 | 53 | for ii=1:length(rho_vec) 54 | rho = rho_vec(ii); 55 | 56 | P = diag(SOURCE_power); 57 | P(1,2)= rho; 58 | P(2,1)= rho; 59 | Pc = [1 0; rho sqrt(1-rho^2)]; 60 | 61 | r_sam = zeros(ULA_N,ULA_N,3,Nsim); 62 | r_the = zeros(ULA_N,ULA_N,3,Nsim); 63 | Y_dr = zeros(ULA_N,ULA_N,Nsim); 64 | mse_l1svd = 0; 65 | mse_unesp = 0; 66 | 67 | for i=1:Nsim 68 | 69 | % The true covariance matrix 70 | Ry_the = A_ula*P*A_ula' + noise_power*eye(ULA_N); 71 | % The signal plus noise 72 | S = (randn(SOURCE_K,T)+1j*randn(SOURCE_K,T))/sqrt(2); 73 | X = A_ula*Pc*S; 74 | Eta = sqrt(noise_power)*(randn(ULA_N,T)+1j*randn(ULA_N,T))/sqrt(2); 75 | Y = X + Eta; 76 | % The sample covariance matrix 77 | Ry_sam = Y*Y'/T; 78 | 79 | % Real and Imaginary part for the sample matrix 80 | r_sam(:,:,1,i) = real(Ry_sam); 81 | r_sam(:,:,2,i) = imag(Ry_sam); 82 | r_sam(:,:,3,i) = angle(Ry_sam); 83 | 84 | r_the(:,:,1,i) = real(Ry_the); 85 | r_the(:,:,2,i) = imag(Ry_the); 86 | r_the(:,:,3,i) = angle(Ry_the); 87 | 88 | % l1_SVD exploiting group sparsity 89 | [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA_N,eta,SOURCE_K, THETA_angles); 90 | mse_l1svd = mse_l1svd + norm(sort(ang_est_l1svd) - theta')^2; 91 | 92 | % Un-ESPRIT results 93 | doas_unit_ESPRIT_sam = unit_ESPRIT(Y, T, ds, SOURCE_K, w); 94 | mse_unesp = mse_unesp + norm(sort(doas_unit_ESPRIT_sam) - theta')^2; 95 | 96 | end 97 | R_sam(:,:,:,:,ii) = r_sam; 98 | R_the(:,:,:,:,ii) = r_the; 99 | RMSE_l1SVD(ii) = sqrt(mse_l1svd/SOURCE_K/Nsim); 100 | RMSE_UnESPRIT(ii) = sqrt(mse_unesp/SOURCE_K/Nsim); 101 | ii 102 | end 103 | angles = theta; 104 | 105 | time_tot = toc/60; % in minutes 106 | 107 | h5create(filename,'/sam', size(R_sam)); 108 | h5write(filename, '/sam', R_sam); 109 | h5create(filename,'/the', size(R_the)); 110 | h5write(filename, '/the', R_the); 111 | h5create(filename,'/angles',size(angles)); 112 | h5write(filename, '/angles', angles); 113 | h5create(filename,'/RMSE_l1SVD',size(RMSE_l1SVD)); 114 | h5write(filename, '/RMSE_l1SVD', RMSE_l1SVD); 115 | h5create(filename,'/RMSE_UnESPRIT',size(RMSE_UnESPRIT)); 116 | h5write(filename, '/RMSE_UnESPRIT', RMSE_UnESPRIT); 117 | h5disp(filename); 118 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp7A.m: -------------------------------------------------------------------------------- 1 | % DoA estimation via CNN - Exp. 6A 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 25/09/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | clc; 9 | tic; 10 | rng(14); 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Location of the data 13 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 14 | 'TEST_DATA_16ULA_K3_min10dBSNR_T3000_3D_fixedang_offgrid.h5'); 15 | % Location of the l1-SVD results (without saving the y data-RMSE only) 16 | % filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 17 | % 'RMSE_l1SVD_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11_power_mismatch.h5'); 18 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 19 | T = 3000; % number of snapshots 20 | SNR_dB = -10; % SNR values 21 | SOURCE.K = 3; % number of sources/targets - Kmax 22 | ULA.N = 16; 23 | SOURCE.interval = 60; 24 | Nsim = 10000; 25 | res = 1; 26 | ang_sep = 5.2; % in degrees 27 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 28 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 29 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 30 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 | SOURCE.power = ones(1,SOURCE.K).^2; 32 | noise_power = min(SOURCE.power)*10^(-SNR_dB/10); 33 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 34 | 35 | % % Threshold for the l1-SVD 36 | % threshold = 60; 37 | % l1_SVD_doa_est = zeros(SOURCE.K,Nsim); 38 | % MSE_l1_svd = 0; 39 | if SOURCE.K ==1 || SOURCE.K ==2 || SOURCE.K ==3 40 | theta(1) = -7.8; 41 | end 42 | if SOURCE.K ==2 || SOURCE.K ==3 43 | theta(2) = theta(1) + ang_sep; 44 | end 45 | if SOURCE.K ==3 46 | theta(3) = theta(2) + ang_sep; 47 | end 48 | 49 | for i=1:Nsim 50 | %theta1 = sort(datasample(Reg,SOURCE.K,'Replace',false)); 51 | A_ula =zeros(ULA.N,SOURCE.K); 52 | %theta = zeros(1,SOURCE.K); 53 | for k=1:SOURCE.K 54 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA.N); 55 | end 56 | 57 | % The true covariance matrix 58 | Ry_the = A_ula*diag(SOURCE.power)*A_ula' + noise_power*eye(ULA.N); 59 | [re_R, im_R] = conv_cov2vec(Ry_the); 60 | r = [re_R; im_R]; 61 | rn = normalize(r,'range'); 62 | Ry_the_sc = conv2matcom(rn); 63 | % The signal plus noise 64 | S = (randn(SOURCE.K,T)+1j*randn(SOURCE.K,T))/sqrt(2); 65 | X = A_ula*S; 66 | Eta = sqrt(noise_power)*(randn(ULA.N,T)+1j*randn(ULA.N,T))/sqrt(2); 67 | Y = X + Eta; 68 | 69 | % Calculate the l1-SVD performance without storing the MMV data - Y 70 | % [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA.N,threshold,SOURCE.K, THETA_angles); 71 | % l1_SVD_doa_est(:,i) = sort(ang_est_l1svd); 72 | 73 | % The sample covariance matrix 74 | Ry_sam = Y*Y'/T; 75 | 76 | % % Real and Imaginary part for the sample matrix 77 | r.sam(:,:,1,i) = real(Ry_sam); 78 | r.sam(:,:,2,i) = imag(Ry_sam); 79 | r.sam(:,:,3,i) = angle(Ry_sam); 80 | 81 | % % Real and Imaginary part for the sample matrix 82 | r.the(:,:,1,i) = real(Ry_the); 83 | r.the(:,:,2,i) = imag(Ry_the); 84 | r.the(:,:,3,i) = angle(Ry_the); 85 | 86 | % MSE_l1_svd = MSE_l1_svd + norm(r.angles(:,i)-l1_SVD_doa_est(:,i))^2; 87 | 88 | i 89 | end 90 | r.angles = theta'; 91 | % RMSE_l1_svd = sqrt(MSE_l1_svd/Nsim/SOURCE.K); 92 | time_tot = toc/60; % in minutes 93 | 94 | % Save the variables in the specified locations 95 | h5create(filename,'/sam', size(r.sam)); 96 | h5write(filename, '/sam', r.sam); 97 | h5create(filename,'/the', size(r.the)); 98 | h5write(filename, '/the', r.the); 99 | h5create(filename,'/angles',size(r.angles)); 100 | h5write(filename, '/angles', r.angles); 101 | % h5create(filename2,'/l1_SVD_ang',size(l1_SVD_doa_est)); 102 | % h5write(filename2, '/l1_SVD_ang', l1_SVD_doa_est); 103 | % h5disp(filename); 104 | -------------------------------------------------------------------------------- /MATLAB/GENER_Test_Data_DoA_JOURNAL_3D_Exp7B.m: -------------------------------------------------------------------------------- 1 | % DoA estimation via CNN - Exp. 6B 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 25/09/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | clc; 9 | tic; 10 | rng(100); % 100 is descent not for K=3 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Location of the data 13 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 14 | 'TEST_DATA_16ULA_K3_min10dBSNR_T3000_3D_slideang_offgrid_ang_sep10.h5'); 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | T = 3000; % number of snapshots 17 | SNR_dB = -10; % SNR values 18 | SOURCE.K = 3; % number of sources/targets - Kmax 19 | ULA.N = 16; 20 | SOURCE.interval = 60; 21 | res = 1; 22 | ang_sep = 10; % in degrees 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 25 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 26 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 27 | SOURCE.power = ones(1,SOURCE.K).^2; 28 | noise_power = min(SOURCE.power)*10^(-SNR_dB/10); 29 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 30 | 31 | % % Threshold for the l1-SVD 32 | % threshold = 60; 33 | % l1_SVD_doa_est = zeros(SOURCE.K,Nsim); 34 | % MSE_l1_svd = 0; 35 | 36 | if SOURCE.K == 1 || SOURCE.K == 2 || SOURCE.K == 3 37 | theta(1) = -59.8; 38 | Nsim = 120; 39 | end 40 | if SOURCE.K == 2 || SOURCE.K == 3 41 | theta(2) = theta(1) + ang_sep; 42 | Nsim = 110; 43 | end 44 | if SOURCE.K == 3 45 | theta(3) = theta(2) + ang_sep; 46 | Nsim = 100; 47 | end 48 | 49 | for i=1:Nsim 50 | %theta1 = sort(datasample(Reg,SOURCE.K,'Replace',false)); 51 | A_ula =zeros(ULA.N,SOURCE.K); 52 | %theta = zeros(1,SOURCE.K); 53 | for k=1:SOURCE.K 54 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA.N); 55 | end 56 | 57 | % The true covariance matrix 58 | Ry_the = A_ula*diag(SOURCE.power)*A_ula' + noise_power*eye(ULA.N); 59 | % The signal plus noise 60 | S = (randn(SOURCE.K,T)+1j*randn(SOURCE.K,T))/sqrt(2); 61 | X = A_ula*S; 62 | Eta = sqrt(noise_power)*(randn(ULA.N,T)+1j*randn(ULA.N,T))/sqrt(2); 63 | Y = X + Eta; 64 | 65 | % Calculate the l1-SVD performance without storing the MMV data - Y 66 | % [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA.N,threshold,SOURCE.K, THETA_angles); 67 | % l1_SVD_doa_est(:,i) = sort(ang_est_l1svd); 68 | 69 | % The sample covariance matrix 70 | Ry_sam = Y*Y'/T; 71 | 72 | % % Real and Imaginary part for the sample matrix 73 | r.sam(:,:,1,i) = real(Ry_sam); 74 | r.sam(:,:,2,i) = imag(Ry_sam); 75 | r.sam(:,:,3,i) = angle(Ry_sam); 76 | 77 | % % Real and Imaginary part for the sample matrix 78 | r.the(:,:,1,i) = real(Ry_the); 79 | r.the(:,:,2,i) = imag(Ry_the); 80 | r.the(:,:,3,i) = angle(Ry_the); 81 | 82 | % MSE_l1_svd = MSE_l1_svd + norm(r.angles(:,i)-l1_SVD_doa_est(:,i))^2; 83 | r.angles(:,i) = theta'; 84 | 85 | theta = theta +1; 86 | i 87 | end 88 | 89 | % RMSE_l1_svd = sqrt(MSE_l1_svd/Nsim/SOURCE.K); 90 | time_tot = toc/60; % in minutes 91 | 92 | % Save the variables in the specified locations 93 | h5create(filename,'/sam', size(r.sam)); 94 | h5write(filename, '/sam', r.sam); 95 | h5create(filename,'/the', size(r.the)); 96 | h5write(filename, '/the', r.the); 97 | h5create(filename,'/angles',size(r.angles)); 98 | h5write(filename, '/angles', r.angles); 99 | % h5create(filename2,'/l1_SVD_ang',size(l1_SVD_doa_est)); 100 | % h5write(filename2, '/l1_SVD_ang', l1_SVD_doa_est); 101 | % h5disp(filename); 102 | -------------------------------------------------------------------------------- /MATLAB/GENER_Train_Data_DoA_JOURNAL_3D.m: -------------------------------------------------------------------------------- 1 | % DoA estimation via CNN: Training DATA generation 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 18/9/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | clc; 9 | tic; 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | % Location to save the DATA 12 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 13 | 'TRAIN_DATA_16ULA_K2_low_SNR_res1_3D_90deg.h5'); 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | SNR_dB_vec = -20:5:0; % SNR values 16 | SOURCE_K = 2; % number of sources/targets - Kmax 17 | ULA_N = 16; 18 | SOURCE.interval = 90; 19 | G_res = 1; % degrees 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21 | % The steering/response vector of the N-element ULA 22 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | % The training sets of angles 25 | ang_d0 = -SOURCE.interval:G_res:SOURCE.interval; 26 | % ang_d1 = [ang_d0' NaN(length(ang_d0),1)]; 27 | ang_d2 = combnk(ang_d0,SOURCE_K); 28 | ang_d = ang_d2; 29 | S = length(SNR_dB_vec); 30 | % r_sam = zeros(ULA_N, ULA_N,3,size(ang_d,1)); 31 | % R_sam = zeros([size(r_sam) S]); 32 | L = size(ang_d,1); 33 | r_the = zeros(ULA_N, ULA_N,3,L); 34 | R_the = zeros([size(r_the) S]); 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | % % Progress bar - comment while debugging 37 | % pbar=waitbar(0,'Please wait...','Name','Progress'); 38 | 39 | parfor i=1:S 40 | SNR_dB = SNR_dB_vec(i); 41 | noise_power = 10^(-SNR_dB/10); 42 | % Angle selection 43 | % r_sam = zeros(ULA_N, ULA_N,3,size(ang_d,1)); 44 | r_the = zeros(ULA_N, ULA_N,3,L); 45 | for ii=1:L 46 | SOURCE_angles = ang_d(ii,:); 47 | A_ula = zeros(ULA_N,SOURCE_K); 48 | for k=1:SOURCE_K 49 | A_ula(:,k) = ULA_steer_vec(SOURCE_angles(k),ULA_N); 50 | end 51 | % The true covariance matrix 52 | Ry_the = A_ula*diag(ones(SOURCE_K,1))*A_ula' + noise_power*eye(ULA_N); 53 | 54 | % Real and Imaginary part for the theor. covariance matrix R 55 | r_the(:,:,1,ii) = real(Ry_the); 56 | r_the(:,:,2,ii) = imag(Ry_the); 57 | r_the(:,:,3,ii) = angle(Ry_the); 58 | 59 | end 60 | i 61 | 62 | R_the(:,:,:,:,i) = r_the; 63 | end 64 | 65 | % The angles - Ground Truth 66 | angles = ang_d; 67 | 68 | % close(pbar); 69 | time_tot = toc/60; % in minutes 70 | 71 | % Save the DATA 72 | h5create(filename,'/theor',size(R_the)); 73 | h5write(filename, '/theor', R_the); 74 | h5create(filename,'/angles',size(angles)); 75 | h5write(filename, '/angles', angles); 76 | h5disp(filename); 77 | -------------------------------------------------------------------------------- /MATLAB/GENER_Train_Data_DoA_JOURNAL_3D_multipleK.m: -------------------------------------------------------------------------------- 1 | % DoA estimation via CNN: Training DATA generation 6A 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 18/9/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | clc; 9 | tic; 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | % Location to save the DATA 12 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 13 | 'TRAIN_DATA_16ULA_K1to3_min15dBSNR_res1_3D.h5'); 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | SNR_dB_vec = -20:5:0; % SNR values 16 | SOURCE_K_max = 3; % number of sources/targets - Kmax 17 | ULA_N = 16; 18 | SOURCE.interval = 60; 19 | G_res = 1; % degrees 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21 | % The steering/response vector of the N-element ULA 22 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | % The training sets of angles 25 | grid = -SOURCE.interval:G_res:SOURCE.interval; 26 | D = []; 27 | for k=SOURCE_K_max:-1:1 28 | ang_d0 = combnk(grid,k); 29 | ang_d = [ang_d0 NaN(length(ang_d0),SOURCE_K_max-size(ang_d0,2))]; 30 | D = [D; ang_d]; 31 | end 32 | 33 | L = size(D,1); 34 | R_the = zeros(ULA_N, ULA_N,3,L,length(SNR_dB_vec)); 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | % % Progress bar - comment while debugging 37 | % pbar=waitbar(0,'Please wait...','Name','Progress'); 38 | for i =1:length(SNR_dB_vec) 39 | SNR_dB = SNR_dB_vec(i); 40 | noise_power = 10^(-SNR_dB/10); 41 | % Angle selection 42 | r_the = zeros(ULA_N, ULA_N,3,L); 43 | for ii=1:L 44 | SOURCE_angles = D(ii,:); 45 | SOURCE_angles = SOURCE_angles(~isnan(SOURCE_angles)); 46 | SOURCE_K = size(SOURCE_angles,2); 47 | A_ula = zeros(ULA_N,SOURCE_K); 48 | for k=1:SOURCE_K 49 | A_ula(:,k) = ULA_steer_vec(SOURCE_angles(k),ULA_N); 50 | end 51 | % The true covariance matrix 52 | Ry_the = A_ula*diag(ones(SOURCE_K,1))*A_ula' + noise_power*eye(ULA_N); 53 | 54 | % Real and Imaginary part for the theor. covariance matrix R 55 | r_the(:,:,1,ii) = real(Ry_the); 56 | r_the(:,:,2,ii) = imag(Ry_the); 57 | r_the(:,:,3,ii) = angle(Ry_the); 58 | end 59 | R_the(:,:,:,:,i) = r_the; 60 | i 61 | end 62 | % The angles - Ground Truth 63 | angles = D; 64 | 65 | % close(pbar); 66 | time_tot = toc/60; % in minutes 67 | 68 | % Save the DATA 69 | h5create(filename,'/theor',size(R_the)); 70 | h5write(filename, '/theor', R_the); 71 | h5create(filename,'/angles',size(angles)); 72 | h5write(filename, '/angles', angles); 73 | h5disp(filename); 74 | -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp1A.m: -------------------------------------------------------------------------------- 1 | % DAE Testing 2 | % Georgios K. Papageorgiou 03/02/2020 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | clear all; 5 | close all; 6 | % clc; 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 9 | 'TEST_DATA_16ULA_K2_min10dBSNR_T2000_3D_slideang_offgrid_sep4coma7.h5'); 10 | h5disp(filename); 11 | r_sam = h5read(filename, '/sam'); 12 | R_sam = squeeze(r_sam(:,:,1,:)+1j*r_sam(:,:,2,:)); 13 | r_the = h5read(filename, '/theor'); 14 | R_the = squeeze(r_the(:,:,1,:)+1j*r_the(:,:,2,:)); 15 | True_angles = h5read(filename, '/angles'); 16 | SOURCE_K = size(True_angles,1); 17 | [ULA_N,~, N_test] = size(R_sam); 18 | SOURCE.interval = 60; 19 | res = 1; 20 | T = 2000; 21 | % UnESPRIT pars 22 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 23 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 24 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 25 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 26 | 27 | % Initialization 28 | rmse_the = 0; 29 | rmse_sam = 0; 30 | rmse_the_rm = 0; 31 | rmse_sam_rm = 0; 32 | rmse_the_esp = 0; 33 | rmse_sam_esp = 0; 34 | 35 | ang_the = zeros(SOURCE_K,N_test); 36 | ang_sam = zeros(SOURCE_K,N_test); 37 | ang_the_rm = zeros(SOURCE_K,N_test); 38 | ang_sam_rm = zeros(SOURCE_K,N_test); 39 | ang_gt = zeros(SOURCE_K,N_test); 40 | ang_the_esp = zeros(SOURCE_K,N_test); 41 | ang_sam_esp = zeros(SOURCE_K,N_test); 42 | 43 | 44 | for nit=1:N_test 45 | 46 | % The true covariance matrix 47 | Rx = R_the(:,:,nit); 48 | 49 | % The smoothed sample covariance matrix 50 | Rx_sam = R_sam(:,:,nit); 51 | 52 | %% MUSIC estimator 53 | [doas_the, spec_the, specang_the] = musicdoa(Rx,SOURCE_K,'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 54 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 55 | 56 | ang_the(:,nit) = sort(doas_the)'; 57 | ang_sam(:,nit) = sort(doas_sam)'; 58 | ang_gt(:,nit) = sort(True_angles(:,nit)); 59 | 60 | % RMSE calculation 61 | rmse_the = rmse_the + norm(ang_the(:,nit) - ang_gt(:,nit))^2; 62 | rmse_sam = rmse_sam + norm(ang_sam(:,nit) - ang_gt(:,nit))^2; 63 | 64 | %% Root-MUSIC estimator 65 | doas_the_rm = sort(rootmusicdoa(Rx, SOURCE_K))'; 66 | doas_sam_rm = sort(rootmusicdoa(Rx_sam, SOURCE_K))'; 67 | 68 | ang_the_rm(:,nit) = sort(doas_the_rm); 69 | ang_sam_rm(:,nit) = sort(doas_sam_rm); 70 | 71 | % RMSE calculation - degrees 72 | rmse_the_rm = rmse_the_rm + norm(ang_the_rm(:,nit) - ang_gt(:,nit))^2; 73 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm(:,nit) - ang_gt(:,nit))^2; 74 | 75 | %% ESPRIT (with variable ds and reweighting technique) 76 | % EPSRIT 77 | doas_the_esp = ESPRIT_doa(Rx, ds, SOURCE_K, w); 78 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 79 | 80 | ang_the_esp(:,nit) = sort(doas_the_esp); 81 | ang_sam_esp(:,nit) = sort(doas_sam_esp); 82 | 83 | rmse_the_esp = rmse_the_esp + norm(ang_the_esp(:,nit) - ang_gt(:,nit))^2; 84 | rmse_sam_esp = rmse_sam_esp + norm( ang_sam_esp(:,nit)- ang_gt(:,nit))^2; 85 | 86 | nit 87 | end 88 | 89 | % MUSIC RMSE_deg 90 | RMSE_the = sqrt(rmse_the/SOURCE_K/N_test); 91 | RMSE_sam = sqrt(rmse_sam/SOURCE_K/N_test); 92 | MUSIC_deg = [ RMSE_the; RMSE_sam]; 93 | 94 | % R-MUSIC RMSE_deg 95 | RMSE_the_rm = sqrt(rmse_the_rm/SOURCE_K/N_test); 96 | RMSE_sam_rm = sqrt(rmse_sam_rm/SOURCE_K/N_test); 97 | R_MUSIC_deg = [ RMSE_the_rm; RMSE_sam_rm]; 98 | 99 | % ESPRIT_deg 100 | RMSE_the_esp = sqrt(rmse_the_esp/SOURCE_K/N_test); 101 | RMSE_sam_esp = sqrt(rmse_sam_esp/SOURCE_K/N_test); 102 | ESPRIT_deg = [ RMSE_the_esp; RMSE_sam_esp]; 103 | 104 | VarNames = {'Theoretical'; 'Sampled'}; 105 | Tab = table(VarNames, MUSIC_deg, R_MUSIC_deg,ESPRIT_deg) 106 | 107 | % % % Save the results 108 | save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 109 | save(fullfile(save_path,'Slide_angsep4coma7_K2_min10dB_T2000.mat'),'MUSIC_deg','R_MUSIC_deg','ESPRIT_deg','ang_the','ang_sam','ang_the_rm','ang_sam_rm','ang_the_esp','ang_sam_esp','ang_gt'); 110 | -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp1B.m: -------------------------------------------------------------------------------- 1 | % DAE Testing 2 | % Georgios K. Papageorgiou 03/02/2020 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | clear all; 5 | close all; 6 | % clc; 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 9 | 'TEST_DATA_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11.h5'); 10 | h5disp(filename); 11 | r_sam = h5read(filename, '/sam'); 12 | R_sam = squeeze(r_sam(:,:,1,:)+1j*r_sam(:,:,2,:)); 13 | r_the = h5read(filename, '/theor'); 14 | R_the = squeeze(r_the(:,:,1,:)+1j*r_the(:,:,2,:)); 15 | True_angles = h5read(filename, '/angles'); 16 | SOURCE_K = size(True_angles,1); 17 | [ULA_N,~, N_test] = size(R_sam); 18 | SOURCE.interval = 60; 19 | res = 1; 20 | % UnESPRIT pars 21 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 22 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 23 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | 26 | % Initialization 27 | rmse_the = 0; 28 | rmse_sam = 0; 29 | rmse_the_rm = 0; 30 | rmse_sam_rm = 0; 31 | rmse_the_esp = 0; 32 | rmse_sam_esp = 0; 33 | 34 | ang_the = zeros(SOURCE_K,N_test); 35 | ang_sam = zeros(SOURCE_K,N_test); 36 | ang_the_rm = zeros(SOURCE_K,N_test); 37 | ang_sam_rm = zeros(SOURCE_K,N_test); 38 | ang_gt = zeros(SOURCE_K,N_test); 39 | ang_the_esp = zeros(SOURCE_K,N_test); 40 | ang_sam_esp = zeros(SOURCE_K,N_test); 41 | 42 | for nit=1:N_test 43 | 44 | % The true covariance matrix 45 | Rx = R_the(:,:,nit); 46 | 47 | % The smoothed sample covariance matrix 48 | Rx_sam = R_sam(:,:,nit); 49 | 50 | % MUSIC estimator 51 | [doas_the, spec_the, specang_the] = musicdoa(Rx,SOURCE_K,'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 52 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 53 | 54 | ang_the(:,nit) = sort(doas_the)'; 55 | ang_sam(:,nit) = sort(doas_sam)'; 56 | ang_gt(:,nit) = sort(True_angles(:,nit)); 57 | 58 | % RMSE calculation 59 | rmse_the = rmse_the + norm(ang_the(:,nit) - ang_gt(:,nit))^2; 60 | rmse_sam = rmse_sam + norm(ang_sam(:,nit) - ang_gt(:,nit))^2; 61 | 62 | % Root-MUSIC estimator 63 | doas_the_rm = sort(rootmusicdoa(Rx, SOURCE_K))'; 64 | doas_sam_rm = sort(rootmusicdoa(Rx_sam, SOURCE_K))'; 65 | 66 | ang_the_rm(:,nit) = sort(doas_the_rm); 67 | ang_sam_rm(:,nit) = sort(doas_sam_rm); 68 | 69 | % RMSE calculation - degrees 70 | rmse_the_rm = rmse_the_rm + norm(ang_the_rm(:,nit) - ang_gt(:,nit))^2; 71 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm(:,nit) - ang_gt(:,nit))^2; 72 | %% ESPRIT (with variable ds and reweighting technique) 73 | % EPSRIT 74 | doas_the_esp = ESPRIT_doa(Rx, ds, SOURCE_K, w); 75 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 76 | 77 | ang_the_esp(:,nit) = sort(doas_the_esp); 78 | ang_sam_esp(:,nit) = sort(doas_sam_esp); 79 | 80 | rmse_the_esp = rmse_the_esp + norm(ang_the_esp(:,nit) - ang_gt(:,nit))^2; 81 | rmse_sam_esp = rmse_sam_esp + norm( ang_sam_esp(:,nit)- ang_gt(:,nit))^2; 82 | 83 | nit 84 | end 85 | 86 | % MUSIC RMSE_deg 87 | RMSE_the = sqrt(rmse_the/SOURCE_K/N_test); 88 | RMSE_sam = sqrt(rmse_sam/SOURCE_K/N_test); 89 | MUSIC_deg = [ RMSE_the; RMSE_sam]; 90 | 91 | % R-MUSIC RMSE_deg 92 | RMSE_the_rm = sqrt(rmse_the_rm/SOURCE_K/N_test); 93 | RMSE_sam_rm = sqrt(rmse_sam_rm/SOURCE_K/N_test); 94 | R_MUSIC_deg = [ RMSE_the_rm; RMSE_sam_rm]; 95 | 96 | % ESPRIT_deg 97 | RMSE_the_esp = sqrt(rmse_the_esp/SOURCE_K/N_test); 98 | RMSE_sam_esp = sqrt(rmse_sam_esp/SOURCE_K/N_test); 99 | ESPRIT_deg = [ RMSE_the_esp; RMSE_sam_esp]; 100 | 101 | VarNames = {'Theoretical'; 'Sampled'}; 102 | Tab = table(VarNames, MUSIC_deg, R_MUSIC_deg, ESPRIT_deg) 103 | 104 | % % Save the results 105 | save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 106 | save(fullfile(save_path,'Slide_angsep2coma11_K2_0dB_T200.mat'),'MUSIC_deg','R_MUSIC_deg','ESPRIT_deg','ang_the','ang_sam','ang_the_rm','ang_sam_rm','ang_the_esp','ang_sam_esp','ang_gt'); -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp1C.m: -------------------------------------------------------------------------------- 1 | % DAE Testing 2 | % Georgios K. Papageorgiou 03/02/2020 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | clear all; 5 | close all; 6 | % clc; 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 9 | 'TEST_DATA_16ULA_K2_min10dBSNR_T2000_3D_slideang_offgrid_sep4coma7_90deg.h5'); 10 | h5disp(filename); 11 | r_sam = h5read(filename, '/sam'); 12 | R_sam = squeeze(r_sam(:,:,1,:)+1j*r_sam(:,:,2,:)); 13 | r_the = h5read(filename, '/theor'); 14 | R_the = squeeze(r_the(:,:,1,:)+1j*r_the(:,:,2,:)); 15 | True_angles = h5read(filename, '/angles'); 16 | SOURCE_K = size(True_angles,1); 17 | [ULA_N,~, N_test] = size(R_sam); 18 | SOURCE.interval = 90; 19 | res = 1; 20 | T = 2000; 21 | % UnESPRIT pars 22 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 23 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 24 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 25 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 26 | 27 | % Initialization 28 | rmse_the = 0; 29 | rmse_sam = 0; 30 | rmse_the_rm = 0; 31 | rmse_sam_rm = 0; 32 | rmse_the_esp = 0; 33 | rmse_sam_esp = 0; 34 | rmse_the_unesp = 0; 35 | rmse_sam_unesp = 0; 36 | 37 | 38 | ang_the = zeros(SOURCE_K,N_test); 39 | ang_sam = zeros(SOURCE_K,N_test); 40 | ang_the_rm = zeros(SOURCE_K,N_test); 41 | ang_sam_rm = zeros(SOURCE_K,N_test); 42 | ang_gt = zeros(SOURCE_K,N_test); 43 | ang_the_esp = zeros(SOURCE_K,N_test); 44 | ang_sam_esp = zeros(SOURCE_K,N_test); 45 | ang_the_unesp = zeros(SOURCE_K,N_test); 46 | ang_sam_unesp = zeros(SOURCE_K,N_test); 47 | 48 | 49 | for nit=1:N_test 50 | 51 | % The true covariance matrix 52 | Rx = R_the(:,:,nit); 53 | 54 | % The smoothed sample covariance matrix 55 | Rx_sam = R_sam(:,:,nit); 56 | 57 | %% MUSIC estimator 58 | [doas_the, spec_the, specang_the] = musicdoa(Rx,SOURCE_K,'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 59 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 60 | 61 | ang_the(:,nit) = sort(doas_the)'; 62 | ang_sam(:,nit) = sort(doas_sam)'; 63 | ang_gt(:,nit) = sort(True_angles(:,nit)); 64 | 65 | % RMSE calculation 66 | rmse_the = rmse_the + norm(ang_the(:,nit) - ang_gt(:,nit))^2; 67 | rmse_sam = rmse_sam + norm(ang_sam(:,nit) - ang_gt(:,nit))^2; 68 | 69 | %% Root-MUSIC estimator 70 | doas_the_rm = sort(rootmusicdoa(Rx, SOURCE_K))'; 71 | doas_sam_rm = sort(rootmusicdoa(Rx_sam, SOURCE_K))'; 72 | 73 | ang_the_rm(:,nit) = sort(doas_the_rm); 74 | ang_sam_rm(:,nit) = sort(doas_sam_rm); 75 | 76 | % RMSE calculation - degrees 77 | rmse_the_rm = rmse_the_rm + norm(ang_the_rm(:,nit) - ang_gt(:,nit))^2; 78 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm(:,nit) - ang_gt(:,nit))^2; 79 | 80 | %% ESPRIT (with variable ds and reweighting technique) 81 | % EPSRIT 82 | 83 | doas_the_esp = ESPRIT_doa(Rx, ds, SOURCE_K, w); 84 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 85 | 86 | ang_the_esp(:,nit) = sort(doas_the_esp); 87 | ang_sam_esp(:,nit) = sort(doas_sam_esp); 88 | 89 | % ang = espritdoa(Rx_sam,SOURCE_K); 90 | rmse_the_esp = rmse_the_esp + norm(ang_the_esp(:,nit) - ang_gt(:,nit))^2; 91 | rmse_sam_esp = rmse_sam_esp + norm( ang_sam_esp(:,nit)- ang_gt(:,nit))^2; 92 | % %% Unitary ESPRIT (with variable ds and reweighting technique) 93 | % % Unitary ESPRIT 94 | % doas_unit_ESPRIT_the = unit_ESPRIT(X, T, ds, SOURCE_K, w); 95 | % doas_unit_ESPRIT_sam = unit_ESPRIT(Y, T, ds, SOURCE_K, w); 96 | % 97 | % ang_the_unesp(:,nit) = sort(doas_unit_ESPRIT_the); 98 | % ang_sam_unesp(:,nit) = sort(doas_unit_ESPRIT_sam); 99 | % 100 | % rmse_the_unit_esp = rmse_the_unit_esp + norm(ang_the_unesp(:,nit) - ang_gt(:,nit))^2; 101 | % rmse_sam_unit_esp = rmse_sam_unit_esp + norm(ang_sam_unesp(:,nit) - ang_gt(:,nit))^2; 102 | 103 | nit 104 | end 105 | 106 | % MUSIC RMSE_deg 107 | RMSE_the = sqrt(rmse_the/SOURCE_K/N_test); 108 | RMSE_sam = sqrt(rmse_sam/SOURCE_K/N_test); 109 | MUSIC_deg = [ RMSE_the; RMSE_sam]; 110 | 111 | % R-MUSIC RMSE_deg 112 | RMSE_the_rm = sqrt(rmse_the_rm/SOURCE_K/N_test); 113 | RMSE_sam_rm = sqrt(rmse_sam_rm/SOURCE_K/N_test); 114 | R_MUSIC_deg = [ RMSE_the_rm; RMSE_sam_rm]; 115 | 116 | % ESPRIT_deg 117 | RMSE_the_esp = sqrt(rmse_the_esp/SOURCE_K/N_test); 118 | RMSE_sam_esp = sqrt(rmse_sam_esp/SOURCE_K/N_test); 119 | ESPRIT_deg = [ RMSE_the_esp; RMSE_sam_esp]; 120 | 121 | % % UnESPRIT_deg 122 | % RMSE_the_unesp = sqrt(rmse_the_unit_esp/SOURCE_K/N_test); 123 | % RMSE_sam_unesp = sqrt(rmse_sam_unit_esp/SOURCE_K/N_test); 124 | % R_UnESPRIT_deg = [ RMSE_the_unesp; RMSE_sam_unesp]; 125 | 126 | VarNames = {'Theoretical'; 'Sampled'}; 127 | Tab = table(VarNames, MUSIC_deg, R_MUSIC_deg,ESPRIT_deg) 128 | 129 | % % Save the results 130 | save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 131 | save(fullfile(save_path,'Slide_angsep4coma7_K2_min10dB_T2000_90deg.mat'),'MUSIC_deg','R_MUSIC_deg','ESPRIT_deg','ang_the','ang_sam','ang_the_rm','ang_sam_rm','ang_the_esp','ang_sam_esp','ang_gt'); 132 | -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp2.m: -------------------------------------------------------------------------------- 1 | % CNN Testing - Experiment 2 2 | % Georgios K. Papageorgiou 19/09/2020 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | clear all; 5 | close all; 6 | clc; 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 9 | 'TEST_DATA1K_16ULA_K2_fixed_offgrid_ang_allSNR_T1000_3D.h5'); 10 | %h5disp(filename); 11 | r_sam = h5read(filename, '/sam'); 12 | R_sam = squeeze(r_sam(:,:,1,:,:)+1j*r_sam(:,:,2,:,:)); 13 | r_the = h5read(filename, '/the'); 14 | R_the = squeeze(r_the(:,:,1,:,:)+1j*r_the(:,:,2,:,:)); 15 | True_angles = h5read(filename, '/angles'); 16 | SOURCE_K = size(True_angles,2); 17 | [ULA_N,~, N_test,SNRs] = size(R_sam); 18 | SOURCE_power = ones(1, SOURCE_K); 19 | SOURCE.interval = 60; 20 | res = 1; 21 | SNR_vec = -20:5:30; 22 | % UnESPRIT pars 23 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 24 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 25 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 26 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 27 | % For the CRLB 28 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 29 | der_a = @(x,N) 1j*(pi^2/180)*cos(deg2rad(x))*ULA_steer_vec(x,N).*(0:1:N-1)'; 30 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 | 32 | A_ula = zeros(ULA_N,SOURCE_K); 33 | D = zeros(ULA_N,SOURCE_K); 34 | B = zeros(ULA_N^2,SOURCE_K); 35 | D_uncr = zeros(ULA_N^2,SOURCE_K); 36 | for k=1:SOURCE_K 37 | A_ula(:,k) = ULA_steer_vec(True_angles(k),ULA_N); 38 | D(:,k) = der_a(True_angles(k),ULA_N); 39 | B(:,k) = kron(conj(A_ula(:,k)), A_ula(:,k)); 40 | D_uncr(:,k) = kron(conj(D(:,k)), A_ula(:,k)) + kron(conj(A_ula(:,k)), D(:,k)); 41 | end 42 | H = D'*(eye(ULA_N)-A_ula*pinv(A_ula))*D; 43 | T = 1000; 44 | 45 | % These are used in the CRB for uncorrelated sources 46 | PI_A = A_ula*pinv(A_ula); 47 | G = null(B'); 48 | 49 | % Initialization 50 | RMSE_the = zeros(1,SNRs); 51 | RMSE_sam = zeros(1,SNRs); 52 | RMSE_the_rm = zeros(1,SNRs); 53 | RMSE_sam_rm = zeros(1,SNRs); 54 | RMSE_the_esp = zeros(1,SNRs); 55 | RMSE_sam_esp = zeros(1,SNRs); 56 | CRLB = zeros(1,SNRs); 57 | CRB_uncr = zeros(1,SNRs); 58 | 59 | parfor s=1:SNRs 60 | 61 | SNR_dB = SNR_vec(s); 62 | noise_power = 10^(-SNR_dB/10); 63 | 64 | R = A_ula*A_ula' + noise_power*eye(ULA_N); 65 | R_inv = inv(R); 66 | 67 | rmse_the = 0; 68 | rmse_sam = 0; 69 | rmse_the_rm = 0; 70 | rmse_sam_rm = 0; 71 | rmse_the_esp = 0; 72 | rmse_sam_esp = 0; 73 | 74 | 75 | for nit=1:N_test 76 | 77 | % The true covariance matrix 78 | Rx = R_the(:,:,nit,s); 79 | 80 | % The smoothed sample covariance matrix 81 | Rx_sam = R_sam(:,:,nit,s); 82 | 83 | % MUSIC estimator 84 | [doas_the, spec_the, specang_the] = musicdoa(Rx,SOURCE_K,'ScanAngles', -60:res:60); 85 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', -60:res:60); 86 | 87 | ang_the = sort(doas_the)'; 88 | ang_sam = sort(doas_sam)'; 89 | ang_gt = sort(True_angles)'; 90 | 91 | % RMSE calculation 92 | rmse_the = rmse_the + norm(ang_the - ang_gt)^2; 93 | rmse_sam = rmse_sam + norm(ang_sam- ang_gt)^2; 94 | 95 | % Root-MUSIC estimator 96 | doas_the_rm = sort(rootmusicdoa(Rx, SOURCE_K))'; 97 | doas_sam_rm = sort(rootmusicdoa(Rx_sam, SOURCE_K))'; 98 | 99 | ang_the_rm= sort(doas_the_rm); 100 | ang_sam_rm = sort(doas_sam_rm); 101 | 102 | % RMSE calculation - degrees 103 | rmse_the_rm = rmse_the_rm + norm(ang_the_rm - ang_gt)^2; 104 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm - ang_gt)^2; 105 | 106 | %% ESPRIT (with variable ds and reweighting technique) 107 | % EPSRIT 108 | doas_the_esp = ESPRIT_doa(Rx, ds, SOURCE_K, w); 109 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 110 | 111 | ang_the_esp = sort(doas_the_esp); 112 | ang_sam_esp = sort(doas_sam_esp); 113 | 114 | % ang = espritdoa(Rx_sam,SOURCE_K); 115 | rmse_the_esp = rmse_the_esp + norm(ang_the_esp - ang_gt)^2; 116 | rmse_sam_esp = rmse_sam_esp + norm( ang_sam_esp- ang_gt)^2; 117 | 118 | end 119 | 120 | % MUSIC RMSE_deg 121 | RMSE_the(s) = sqrt(rmse_the/SOURCE_K/N_test); 122 | RMSE_sam(s) = sqrt(rmse_sam/SOURCE_K/N_test); 123 | 124 | % R-MUSIC RMSE_deg 125 | RMSE_the_rm(s) = sqrt(rmse_the_rm/SOURCE_K/N_test); 126 | RMSE_sam_rm(s) = sqrt(rmse_sam_rm/SOURCE_K/N_test); 127 | 128 | % ESPRIT RMSE_deg 129 | RMSE_the_esp(s) = sqrt(rmse_the_esp/SOURCE_K/N_test); 130 | RMSE_sam_esp(s) = sqrt(rmse_sam_esp/SOURCE_K/N_test); 131 | 132 | % Cramer-Rao lower bound 133 | C_Cr = (noise_power/(2*T))*inv(real(H.*(A_ula'*R_inv*A_ula).')); 134 | CRLB(s) = sqrt(trace(C_Cr)/SOURCE_K); 135 | 136 | % CRB for uncorrelated sources 137 | C = kron(R.', R) + (noise_power^2/(ULA_N-SOURCE_K))*(PI_A(:)*(PI_A(:))'); 138 | CRB_mat = inv(diag(SOURCE_power)*D_uncr'*G*inv(G'*C*G)*G'*D_uncr*diag(SOURCE_power))/T; 139 | CRB_uncr(s) = sqrt(real(trace(CRB_mat))/SOURCE_K); 140 | s 141 | end 142 | %% 143 | figure(1); 144 | plot(SNR_vec,RMSE_sam,'s--'); 145 | hold on; 146 | plot(SNR_vec,RMSE_sam_rm,'d--'); 147 | plot(SNR_vec,RMSE_sam_esp,'+--') 148 | %plot(SNR_vec, CRLB,'*-'); 149 | plot(SNR_vec, CRB_uncr,'o-'); 150 | hold off; 151 | set(gca, 'YScale', 'log'); 152 | legend('MUSIC', 'R-MUSIC','ESPRIT','CRLB$_{uncr}$',... 153 | 'interpreter','latex'); 154 | title('DoA-estimation of K=2 sources', 'interpreter','latex'); 155 | ylabel('RMSE [degrees]', 'interpreter','latex'); 156 | xlabel('SNR [dB]', 'interpreter','latex'); 157 | grid on; 158 | 159 | % % %% Save the results 160 | save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 161 | save(fullfile(save_path,'RMSE_K2_offgrid_ang_fixed_allSNR_T1000.mat'),'SNR_vec','RMSE_sam','RMSE_sam_rm','RMSE_sam_esp','CRLB','CRB_uncr'); 162 | 163 | -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp3.m: -------------------------------------------------------------------------------- 1 | % TESTING DATA Generator - Experiment 3 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 19/9/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | % clc; 9 | SNR_dB = -10; 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 12 | 'TEST_DATA1K_16ULA_K2_min10dBSNR_3D_fixed_ang_sep3coma6_vsT.h5'); 13 | 14 | r_sam = h5read(filename, '/sam'); 15 | R_sam = squeeze(r_sam(:,:,1,:,:)+1j*r_sam(:,:,2,:,:)); 16 | True_angles = h5read(filename, '/angles'); 17 | SOURCE_K = size(True_angles,2); 18 | [ULA_N,~, N_test,T_vec_size] = size(R_sam); 19 | SOURCE.interval = 60; 20 | SOURCE_power = ones(1, SOURCE_K); 21 | res = 1; 22 | noise_power = 10^(-SNR_dB/10); 23 | T_vec = 1000*[0.1 0.2 0.5 1 2 5 10]; 24 | % ESPIRT pars 25 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 26 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 27 | w = min(ms,ULA_N-ds-ms+1); 28 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 29 | % For the CRLB 30 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 31 | der_a = @(x,N) 1j*(pi^2/180)*cos(deg2rad(x))*ULA_steer_vec(x,N).*(0:1:N-1)'; 32 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 33 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 34 | 35 | % Initialization 36 | RMSE_the = zeros(1,T_vec_size); 37 | RMSE_sam = zeros(1,T_vec_size); 38 | RMSE_the_rm = zeros(1,T_vec_size); 39 | RMSE_sam_rm = zeros(1,T_vec_size); 40 | RMSE_sam_esp = zeros(1,T_vec_size); 41 | CRLB = zeros(1,T_vec_size); 42 | CRB_uncr = zeros(1, T_vec_size); 43 | 44 | for s=1:T_vec_size 45 | 46 | rmse_the = 0; 47 | rmse_sam = 0; 48 | rmse_the_rm = 0; 49 | rmse_sam_rm = 0; 50 | rmse_sam_esp = 0; 51 | CRLBnit = 0; 52 | CRLBnit_uncr = 0; 53 | T = T_vec(s); 54 | for nit=1:N_test 55 | 56 | 57 | theta = True_angles'; 58 | 59 | A_ula = zeros(ULA_N,SOURCE_K); 60 | D = zeros(ULA_N,SOURCE_K); 61 | B = zeros(ULA_N^2,SOURCE_K); 62 | D_uncr = zeros(ULA_N^2,SOURCE_K); 63 | for k=1:SOURCE_K 64 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA_N); 65 | D(:,k) = der_a(theta(k),ULA_N); 66 | B(:,k) = kron(conj(A_ula(:,k)), A_ula(:,k)); 67 | D_uncr(:,k) = kron(conj(D(:,k)), A_ula(:,k)) + kron(conj(A_ula(:,k)), D(:,k)); 68 | end 69 | H = D'*(eye(ULA_N)-A_ula*pinv(A_ula))*D; 70 | 71 | R = A_ula*A_ula' + noise_power*eye(ULA_N); 72 | R_inv = inv(R); 73 | 74 | % These are used in the CRB for uncorrelated sources 75 | PI_A = A_ula*pinv(A_ula); 76 | G = null(B'); 77 | 78 | Rx_sam = R_sam(:,:,nit,s); 79 | 80 | % MUSIC estimator 81 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', THETA_angles); 82 | ang_sam = sort(doas_sam)'; 83 | ang_gt = sort(theta); 84 | % RMSE calculation 85 | rmse_sam = rmse_sam + norm(ang_sam- ang_gt)^2; 86 | 87 | % Root-MUSIC estimator 88 | doas_sam_rm = sort(rootmusicdoa(Rx_sam, SOURCE_K))'; 89 | ang_sam_rm = sort(doas_sam_rm); 90 | 91 | % RMSE calculation - degrees 92 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm - ang_gt)^2; 93 | 94 | % ESPRIT estimator 95 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 96 | ang_sam_esp = sort(doas_sam_esp); 97 | rmse_sam_esp = rmse_sam_esp + norm(ang_sam_esp- ang_gt)^2; 98 | 99 | % Cramer-Rao lower bound 100 | C_Cr = (noise_power/(2*T))*inv(real(H.*(A_ula'*R_inv*A_ula).')); 101 | CRLBnit = CRLBnit + trace(C_Cr); 102 | % CRB for uncorrelated sources 103 | C = kron(R.', R) + (noise_power^2/(ULA_N-SOURCE_K))*(PI_A(:)*(PI_A(:))'); 104 | CRB_mat = inv(diag(SOURCE_power)*D_uncr'*G*inv(G'*C*G)*G'*D_uncr*diag(SOURCE_power))/T; 105 | CRLBnit_uncr = CRLBnit_uncr + real(trace(CRB_mat)); 106 | 107 | end 108 | 109 | % MUSIC RMSE_deg 110 | RMSE_the(s) = sqrt(rmse_the/SOURCE_K/N_test); 111 | RMSE_sam(s) = sqrt(rmse_sam/SOURCE_K/N_test); 112 | 113 | % R-MUSIC RMSE_deg 114 | RMSE_the_rm(s) = sqrt(rmse_the_rm/SOURCE_K/N_test); 115 | RMSE_sam_rm(s) = sqrt(rmse_sam_rm/SOURCE_K/N_test); 116 | 117 | % ESPRIT RMSE_deg 118 | RMSE_sam_esp(s) = sqrt(rmse_sam_esp/SOURCE_K/N_test); 119 | 120 | CRLB(s) = sqrt(CRLBnit/SOURCE_K/N_test); 121 | CRB_uncr(s) = sqrt(CRLBnit_uncr/SOURCE_K/N_test); 122 | s 123 | end 124 | %% 125 | figure(1); 126 | plot(T_vec,RMSE_sam,'^--'); 127 | hold on; 128 | plot(T_vec,RMSE_sam_rm,'o--'); 129 | plot(T_vec,RMSE_sam_esp,'+--'); 130 | plot(T_vec, CRLB,'d-'); 131 | plot(T_vec, CRB_uncr,'.-'); 132 | hold off; 133 | set(gca, 'YScale', 'log'); 134 | legend('MUSIC', 'R-MUSIC','ESPRIT','CRLB','CRLB$_{uncr}$',... 135 | 'interpreter','latex'); 136 | title('DoA-estimation of K=2 sources', 'interpreter','latex'); 137 | ylabel('RMSE [degrees]', 'interpreter','latex'); 138 | xlabel('T (snapshots)', 'interpreter','latex'); 139 | grid on; 140 | 141 | % % %% Save the results 142 | save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 143 | save(fullfile(save_path,'RMSE_K2_min10dB_ang_sep3coma6_vsT.mat'),'T_vec','RMSE_sam','RMSE_sam_rm','RMSE_sam_esp','CRLB','CRB_uncr'); 144 | 145 | -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp4.m: -------------------------------------------------------------------------------- 1 | % MUSIC+R-MUSIC Testing 2 | % Georgios K. Papageorgiou 19/09/2020 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | clear all; 5 | close all; 6 | % clc; 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 9 | 'TEST_DATA1K_16ULA_K2_min10dBSNR_T500_3D_vs_ang_sep_v2.h5'); 10 | T = 500; 11 | % h5disp(filename); 12 | r_sam = h5read(filename, '/sam'); 13 | R_sam = squeeze(r_sam(:,:,1,:,:)+1j*r_sam(:,:,2,:,:)); 14 | % r_the = h5read(filename, '/the'); 15 | % R_the = squeeze(r_the(:,:,1,:,:)+1j*r_the(:,:,2,:,:)); 16 | True_angles = h5read(filename, '/angles'); 17 | SOURCE_K = size(True_angles,1); 18 | [ULA_N,~, N_test,ang_sep_vec_size] = size(R_sam); 19 | SOURCE.interval = 60; 20 | SOURCE_power = ones(1, SOURCE_K); 21 | res = 1; 22 | SNR_dB = -10; 23 | noise_power = 10^(-SNR_dB/10); 24 | ang_sep_vec = [1 2 4 6 10 14]; 25 | % ESPIRT pars 26 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 27 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 28 | w = min(ms,ULA_N-ds-ms+1); 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | % For the CRLB 31 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 32 | der_a = @(x,N) 1j*(pi^2/180)*cos(deg2rad(x))*ULA_steer_vec(x,N).*(0:1:N-1)'; 33 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 34 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 35 | 36 | % Initialization 37 | RMSE_the = zeros(1,ang_sep_vec_size); 38 | RMSE_sam = zeros(1,ang_sep_vec_size); 39 | RMSE_the_rm = zeros(1,ang_sep_vec_size); 40 | RMSE_sam_rm = zeros(1,ang_sep_vec_size); 41 | RMSE_sam_esp = zeros(1,ang_sep_vec_size); 42 | CRLB = zeros(1,ang_sep_vec_size); 43 | CRLB_uncr = zeros(1,ang_sep_vec_size); 44 | 45 | for s=1:ang_sep_vec_size 46 | 47 | rmse_the = 0; 48 | rmse_sam = 0; 49 | rmse_the_rm = 0; 50 | rmse_sam_rm = 0; 51 | rmse_sam_esp = 0; 52 | 53 | theta = True_angles(:,s); 54 | A_ula = zeros(ULA_N,SOURCE_K); 55 | D = zeros(ULA_N,SOURCE_K); 56 | B = zeros(ULA_N^2,SOURCE_K); 57 | D_uncr = zeros(ULA_N^2,SOURCE_K); 58 | for k=1:SOURCE_K 59 | A_ula(:,k) = ULA_steer_vec(theta(k),ULA_N); 60 | D(:,k) = der_a(theta(k),ULA_N); 61 | B(:,k) = kron(conj(A_ula(:,k)), A_ula(:,k)); 62 | D_uncr(:,k) = kron(conj(D(:,k)), A_ula(:,k)) + kron(conj(A_ula(:,k)), D(:,k)); 63 | end 64 | H = D'*(eye(ULA_N)-A_ula*pinv(A_ula))*D; 65 | R = A_ula*A_ula' + noise_power*eye(ULA_N); 66 | R_inv = inv(R); 67 | % These are used in the CRB for uncorrelated sources 68 | PI_A = A_ula*pinv(A_ula); 69 | G = null(B'); 70 | 71 | for nit=1:N_test 72 | 73 | Rx_sam = R_sam(:,:,nit,s); 74 | % MUSIC estimator 75 | % [doas_the, spec_the, specang_the] = musicdoa(Rx,SOURCE_K,'ScanAngles', THETA_angles); 76 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', THETA_angles); 77 | % ang_the = sort(doas_the)'; 78 | ang_sam = sort(doas_sam)'; 79 | ang_gt = sort(theta); 80 | 81 | % RMSE calculation 82 | % rmse_the = rmse_the + norm(ang_the - ang_gt)^2; 83 | rmse_sam = rmse_sam + norm(ang_sam- ang_gt)^2; 84 | % Root-MUSIC estimator 85 | % doas_the_rm = sort(rootmusicdoa(Rx, SOURCE_K))'; 86 | doas_sam_rm = rootmusicdoa(Rx_sam, SOURCE_K)'; 87 | % ang_the_rm= sort(doas_the_rm); 88 | ang_sam_rm = sort(doas_sam_rm); 89 | % RMSE calculation - degrees 90 | % rmse_the_rm = rmse_the_rm + norm(ang_the_rm - ang_gt)^2; 91 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm - ang_gt)^2; 92 | % EPSRIT 93 | % doas_the_esp = ESPRIT_doa(Rx, ds, SOURCE_K, w); 94 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 95 | % ang_the_esp = sort(doas_the_esp); 96 | ang_sam_esp = sort(doas_sam_esp); 97 | % ang = espritdoa(Rx_sam,SOURCE_K); 98 | % rmse_the_esp = rmse_the_esp + norm(ang_the_esp - ang_gt)^2; 99 | rmse_sam_esp = rmse_sam_esp + norm(ang_sam_esp- ang_gt)^2; 100 | 101 | end 102 | % CRB 103 | C_Cr = trace((noise_power/(2*T))*inv(real(H.*(A_ula'*R_inv*A_ula).'))); 104 | % CRB for uncorrelated sources 105 | C = kron(R.', R) + (noise_power^2/(ULA_N-SOURCE_K))*(PI_A(:)*(PI_A(:))'); 106 | CRB_mat = inv(diag(SOURCE_power)*D_uncr'*G*inv(G'*C*G)*G'*D_uncr*diag(SOURCE_power))/T; 107 | CRB_uncr = real(trace(CRB_mat)); 108 | 109 | % MUSIC RMSE_deg 110 | RMSE_the(s) = sqrt(rmse_the/SOURCE_K/N_test); 111 | RMSE_sam(s) = sqrt(rmse_sam/SOURCE_K/N_test); 112 | 113 | % R-MUSIC RMSE_deg 114 | RMSE_the_rm(s) = sqrt(rmse_the_rm/SOURCE_K/N_test); 115 | RMSE_sam_rm(s) = sqrt(rmse_sam_rm/SOURCE_K/N_test); 116 | 117 | % ESPRIT RMSE deg 118 | % RMSE_the_esp(s) = sqrt(rmse_the_esp/SOURCE_K/N_test); 119 | RMSE_sam_esp(s) = sqrt(rmse_sam_esp/SOURCE_K/N_test); 120 | 121 | % CRLB per Delta theta 122 | CRLB(s) = sqrt(C_Cr/SOURCE_K); 123 | CRLB_uncr(s) = sqrt(CRB_uncr/SOURCE_K); 124 | 125 | s 126 | end 127 | 128 | figure(1); 129 | plot(ang_sep_vec,RMSE_sam,'s--r'); 130 | hold on; 131 | plot(ang_sep_vec,RMSE_sam_rm,'o--g'); 132 | plot(ang_sep_vec,RMSE_sam_esp,'+--b'); 133 | plot(ang_sep_vec, CRLB,'*-k'); 134 | plot(ang_sep_vec, CRLB_uncr,'.-'); 135 | hold off; 136 | set(gca, 'YScale', 'log'); 137 | legend('MUSIC ', 'R-MUSIC ','ESPRIT','CRLB','CRLB$_{uncr}$',... 138 | 'interpreter','latex'); 139 | title('DoA-estimation of K=2 sources', 'interpreter','latex'); 140 | ylabel('RMSE [degrees]', 'interpreter','latex'); 141 | xlabel('Angle separation [degrees]', 'interpreter','latex'); 142 | grid on; 143 | 144 | % % % %% Save the results 145 | % save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 146 | % save(fullfile(save_path,'RMSE_K2_vs_ang_sep_T500_min10dBSNR_v2.mat'),'ang_sep_vec','RMSE_sam','RMSE_sam_rm','RMSE_sam_esp','CRLB','CRLB_uncr'); 147 | -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp5A.m: -------------------------------------------------------------------------------- 1 | % DAE Testing 2 | % Georgios K. Papageorgiou 03/02/2020 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | clear all; 5 | close all; 6 | % clc; 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 9 | 'TEST_DATA_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11_power_mismatch.h5'); 10 | % h5disp(filename); 11 | r_sam = h5read(filename, '/sam'); 12 | R_sam = squeeze(r_sam(:,:,1,:)+1j*r_sam(:,:,2,:)); 13 | True_angles = h5read(filename, '/angles'); 14 | SOURCE_K = size(True_angles,1); 15 | [ULA_N,~, N_test] = size(R_sam); 16 | SOURCE.interval = 60; 17 | res = 1; 18 | % UnESPRIT pars 19 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 20 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 21 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | 24 | % Initialization 25 | rmse_sam = 0; 26 | rmse_sam_rm = 0; 27 | rmse_sam_esp = 0; 28 | 29 | ang_sam = zeros(SOURCE_K,N_test); 30 | ang_sam_rm = zeros(SOURCE_K,N_test); 31 | ang_gt = zeros(SOURCE_K,N_test); 32 | ang_sam_esp = zeros(SOURCE_K,N_test); 33 | 34 | for nit=1:N_test 35 | 36 | 37 | % The smoothed sample covariance matrix 38 | Rx_sam = R_sam(:,:,nit); 39 | 40 | % MUSIC estimator 41 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 42 | 43 | ang_sam(:,nit) = sort(doas_sam)'; 44 | ang_gt(:,nit) = sort(True_angles(:,nit)); 45 | 46 | % RMSE calculation 47 | rmse_sam = rmse_sam + norm(ang_sam(:,nit) - ang_gt(:,nit))^2; 48 | 49 | % Root-MUSIC estimator 50 | doas_sam_rm = sort(rootmusicdoa(Rx_sam, SOURCE_K))'; 51 | ang_sam_rm(:,nit) = sort(doas_sam_rm); 52 | 53 | % RMSE calculation - degrees 54 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm(:,nit) - ang_gt(:,nit))^2; 55 | %% ESPRIT (with variable ds and reweighting technique) 56 | % EPSRIT 57 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 58 | ang_sam_esp(:,nit) = sort(doas_sam_esp); 59 | 60 | rmse_sam_esp = rmse_sam_esp + norm( ang_sam_esp(:,nit)- ang_gt(:,nit))^2; 61 | 62 | nit 63 | end 64 | 65 | % MUSIC RMSE_deg 66 | RMSE_sam = sqrt(rmse_sam/SOURCE_K/N_test); 67 | MUSIC_deg = RMSE_sam; 68 | 69 | % R-MUSIC RMSE_deg 70 | RMSE_sam_rm = sqrt(rmse_sam_rm/SOURCE_K/N_test); 71 | R_MUSIC_deg = RMSE_sam_rm; 72 | 73 | % ESPRIT_deg 74 | RMSE_sam_esp = sqrt(rmse_sam_esp/SOURCE_K/N_test); 75 | ESPRIT_deg = RMSE_sam_esp; 76 | 77 | VarNames = {'Sampled'}; 78 | Tab = table(VarNames, MUSIC_deg, R_MUSIC_deg, ESPRIT_deg) 79 | 80 | % % Save the results 81 | save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 82 | save(fullfile(save_path,'Slide_angsep2coma11_K2_0dB_T200_power_mismatch.mat'),'MUSIC_deg','R_MUSIC_deg','ESPRIT_deg','ang_sam','ang_sam_rm','ang_sam_esp','ang_gt'); -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp5B.m: -------------------------------------------------------------------------------- 1 | % DAE Testing 2 | % Georgios K. Papageorgiou 03/02/2020 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | clear all; 5 | close all; 6 | % clc; 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 9 | 'TEST_DATA_16ULA_K2_min10dBSNR_T1000_3D_slideang_offgrid_sep4_power_mismatch.h5'); 10 | % h5disp(filename); 11 | r_sam = h5read(filename, '/sam'); 12 | R_sam = squeeze(r_sam(:,:,1,:)+1j*r_sam(:,:,2,:)); 13 | True_angles = h5read(filename, '/angles'); 14 | SOURCE_K = size(True_angles,1); 15 | [ULA_N,~, N_test] = size(R_sam); 16 | SOURCE.interval = 60; 17 | res = 1; 18 | % UnESPRIT pars 19 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 20 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 21 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | 24 | % Initialization 25 | rmse_sam = 0; 26 | rmse_sam_rm = 0; 27 | rmse_sam_esp = 0; 28 | 29 | ang_sam = zeros(SOURCE_K,N_test); 30 | ang_sam_rm = zeros(SOURCE_K,N_test); 31 | ang_gt = zeros(SOURCE_K,N_test); 32 | ang_sam_esp = zeros(SOURCE_K,N_test); 33 | 34 | for nit=1:N_test 35 | 36 | 37 | % The smoothed sample covariance matrix 38 | Rx_sam = R_sam(:,:,nit); 39 | 40 | % MUSIC estimator 41 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 42 | 43 | ang_sam(:,nit) = sort(doas_sam)'; 44 | ang_gt(:,nit) = sort(True_angles(:,nit)); 45 | 46 | % RMSE calculation 47 | rmse_sam = rmse_sam + norm(ang_sam(:,nit) - ang_gt(:,nit))^2; 48 | 49 | % Root-MUSIC estimator 50 | doas_sam_rm = sort(rootmusicdoa(Rx_sam, SOURCE_K))'; 51 | ang_sam_rm(:,nit) = sort(doas_sam_rm); 52 | 53 | % RMSE calculation - degrees 54 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm(:,nit) - ang_gt(:,nit))^2; 55 | %% ESPRIT (with variable ds and reweighting technique) 56 | % EPSRIT 57 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 58 | ang_sam_esp(:,nit) = sort(doas_sam_esp); 59 | 60 | rmse_sam_esp = rmse_sam_esp + norm( ang_sam_esp(:,nit)- ang_gt(:,nit))^2; 61 | 62 | nit 63 | end 64 | 65 | % MUSIC RMSE_deg 66 | RMSE_sam = sqrt(rmse_sam/SOURCE_K/N_test); 67 | MUSIC_deg = RMSE_sam; 68 | 69 | % R-MUSIC RMSE_deg 70 | RMSE_sam_rm = sqrt(rmse_sam_rm/SOURCE_K/N_test); 71 | R_MUSIC_deg = RMSE_sam_rm; 72 | 73 | % ESPRIT_deg 74 | RMSE_sam_esp = sqrt(rmse_sam_esp/SOURCE_K/N_test); 75 | ESPRIT_deg = RMSE_sam_esp; 76 | 77 | VarNames = {'Sampled'}; 78 | Tab = table(VarNames, MUSIC_deg, R_MUSIC_deg, ESPRIT_deg) 79 | 80 | % % Save the results 81 | save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 82 | save(fullfile(save_path,'Slide_angsep4_K2_min10dB_T1000_power_mismatch.mat'),'MUSIC_deg','R_MUSIC_deg','ESPRIT_deg','ang_sam','ang_sam_rm','ang_sam_esp','ang_gt'); -------------------------------------------------------------------------------- /MATLAB/MUSIC_RMUSIC_ESPRIT_TESTING_3D_Exp6.m: -------------------------------------------------------------------------------- 1 | % CNN Testing - Experiment 2 2 | % Georgios K. Papageorgiou 19/09/2020 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | clear all; 5 | close all; 6 | clc; 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 9 | 'TEST_DATA1K_3D_16ULA_K2_fixed_ang_sep3coma8_min10dBSNR_T1000_vsrho.h5'); 10 | %h5disp(filename); 11 | r_sam = h5read(filename, '/sam'); 12 | R_sam = squeeze(r_sam(:,:,1,:,:)+1j*r_sam(:,:,2,:,:)); 13 | r_the = h5read(filename, '/the'); 14 | R_the = squeeze(r_the(:,:,1,:,:)+1j*r_the(:,:,2,:,:)); 15 | True_angles = h5read(filename, '/angles'); 16 | SOURCE_K = size(True_angles,2); 17 | [ULA_N,~, N_test,rhos] = size(R_sam); 18 | rho_vec = 0:0.1:1; 19 | SOURCE_power = ones(1, SOURCE_K); 20 | SOURCE.interval = 60; 21 | res = 1; 22 | SNR_dB = -10; 23 | T = 1000; 24 | noise_power = min(SOURCE_power)*10^(-SNR_dB/10); 25 | % UnESPRIT pars 26 | ds = 1; % if the angle search space is lower than [-30,30] ds>1 can be used, e.g., ds=2--> u=1/ds=0.5 --> [-30,30] degrees 27 | ms = 8; % if 1 the weights are equal if ms>1 there are higher weights at the center elements of each subarray 28 | w = min(ms,ULA_N-ds-ms+1); % Eq 9.133 in [1] 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | % For the CRLB 31 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 32 | der_a = @(x,N) 1j*(pi^2/180)*cos(deg2rad(x))*ULA_steer_vec(x,N).*(0:1:N-1)'; 33 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 34 | 35 | A_ula = zeros(ULA_N,SOURCE_K); 36 | D = zeros(ULA_N,SOURCE_K); 37 | for k=1:SOURCE_K 38 | A_ula(:,k) = ULA_steer_vec(True_angles(k),ULA_N); 39 | D(:,k) = der_a(True_angles(k),ULA_N); 40 | end 41 | H = D'*(eye(ULA_N)-A_ula*pinv(A_ula))*D; 42 | 43 | % Initialization 44 | RMSE_the = zeros(1,rhos); 45 | RMSE_sam = zeros(1,rhos); 46 | RMSE_the_rm = zeros(1,rhos); 47 | RMSE_sam_rm = zeros(1,rhos); 48 | RMSE_the_esp = zeros(1,rhos); 49 | RMSE_sam_esp = zeros(1,rhos); 50 | CRLB = zeros(1,rhos); 51 | 52 | for s=1:rhos 53 | 54 | rho = rho_vec(s); 55 | P = [1 rho; rho 1]; 56 | R = A_ula*P*A_ula' + noise_power*eye(ULA_N); 57 | R_inv = inv(R); 58 | 59 | 60 | rmse_the = 0; 61 | rmse_sam = 0; 62 | rmse_the_rm = 0; 63 | rmse_sam_rm = 0; 64 | rmse_the_esp = 0; 65 | rmse_sam_esp = 0; 66 | 67 | for nit=1:N_test 68 | 69 | % The true covariance matrix 70 | Rx = R_the(:,:,nit,s); 71 | 72 | % The smoothed sample covariance matrix 73 | Rx_sam = R_sam(:,:,nit,s); 74 | 75 | % MUSIC estimator 76 | [doas_the, spec_the, specang_the] = musicdoa(Rx,SOURCE_K,'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 77 | [doas_sam, spec_sam, specang_sam] = musicdoa(Rx_sam,SOURCE_K, 'ScanAngles', -SOURCE.interval:res:SOURCE.interval); 78 | 79 | ang_the = sort(doas_the)'; 80 | ang_sam = sort(doas_sam)'; 81 | ang_gt = sort(True_angles)'; 82 | 83 | % RMSE calculation 84 | rmse_the = rmse_the + norm(ang_the - ang_gt)^2; 85 | rmse_sam = rmse_sam + norm(ang_sam- ang_gt)^2; 86 | 87 | % Root-MUSIC estimator 88 | doas_the_rm = sort(rootmusicdoa(Rx, SOURCE_K))'; 89 | doas_sam_rm = sort(rootmusicdoa(Rx_sam, SOURCE_K))'; 90 | 91 | ang_the_rm= sort(doas_the_rm); 92 | ang_sam_rm = sort(doas_sam_rm); 93 | 94 | % RMSE calculation - degrees 95 | rmse_the_rm = rmse_the_rm + norm(ang_the_rm - ang_gt)^2; 96 | rmse_sam_rm = rmse_sam_rm + norm(ang_sam_rm - ang_gt)^2; 97 | 98 | %% ESPRIT (with variable ds and reweighting technique) 99 | % EPSRIT 100 | doas_the_esp = ESPRIT_doa(Rx, ds, SOURCE_K, w); 101 | doas_sam_esp = ESPRIT_doa(Rx_sam, ds, SOURCE_K, w); 102 | 103 | ang_the_esp = sort(doas_the_esp); 104 | ang_sam_esp = sort(doas_sam_esp); 105 | 106 | % ang = espritdoa(Rx_sam,SOURCE_K); 107 | rmse_the_esp = rmse_the_esp + norm(ang_the_esp - ang_gt)^2; 108 | rmse_sam_esp = rmse_sam_esp + norm( ang_sam_esp- ang_gt)^2; 109 | 110 | end 111 | 112 | % MUSIC RMSE_deg 113 | RMSE_the(s) = sqrt(rmse_the/SOURCE_K/N_test); 114 | RMSE_sam(s) = sqrt(rmse_sam/SOURCE_K/N_test); 115 | 116 | % R-MUSIC RMSE_deg 117 | RMSE_the_rm(s) = sqrt(rmse_the_rm/SOURCE_K/N_test); 118 | RMSE_sam_rm(s) = sqrt(rmse_sam_rm/SOURCE_K/N_test); 119 | 120 | % ESPRIT RMSE_deg 121 | RMSE_the_esp(s) = sqrt(rmse_the_esp/SOURCE_K/N_test); 122 | RMSE_sam_esp(s) = sqrt(rmse_sam_esp/SOURCE_K/N_test); 123 | 124 | % Cramer-Rao lower bound 125 | C_Cr = (noise_power/(2*T))*inv(real(H.*(P*A_ula'*R_inv*A_ula*P).')); 126 | CRLB(s) = sqrt(trace(C_Cr)/SOURCE_K); 127 | 128 | s 129 | end 130 | %% 131 | 132 | figure(1); 133 | plot(rho_vec,RMSE_sam,'^--g'); 134 | hold on; 135 | plot(rho_vec,RMSE_sam_rm,'o--c'); 136 | plot(rho_vec,RMSE_sam_esp,'+--r') 137 | plot(rho_vec, CRLB,'.-k'); 138 | hold off; 139 | set(gca, 'YScale', 'log'); 140 | legend('MUSIC', 'R-MUSIC','ESPRIT','CRLB',... 141 | 'interpreter','latex'); 142 | title('DoA-estimation of K=2 sources', 'interpreter','latex'); 143 | ylabel('RMSE [degrees]', 'interpreter','latex'); 144 | xlabel('Correlation coefficient', 'interpreter','latex'); 145 | grid on; 146 | 147 | % Save the results 148 | save_path = 'C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation\DoA_Estimation_underdetermined\ComparisonRESULTS'; 149 | save(fullfile(save_path,'RMSE_K2_offgrid_ang_fixed_min10dBSNR_T1000_vsrho.mat'),'rho_vec','RMSE_sam','RMSE_sam_rm','RMSE_sam_esp','CRLB'); 150 | -------------------------------------------------------------------------------- /MATLAB/Q_mat.m: -------------------------------------------------------------------------------- 1 | function Q = Q_mat(N) 2 | if rem(N,2)==0% N even 3 | Q = [eye(N/2) 1j*eye(N/2); flip(eye(N/2)) -1j*flip(eye(N/2))]/sqrt(2); 4 | else % N odd 5 | Q = [eye((N-1)/2) zeros((N-1)/2,1) 1j*eye((N-1)/2); ... 6 | zeros(1,(N-1)/2) sqrt(2) zeros(1,(N-1)/2); ... 7 | flip(eye((N-1)/2)) zeros((N-1)/2,1) -1j*flip(eye((N-1)/2))]/sqrt(2); 8 | end 9 | end -------------------------------------------------------------------------------- /MATLAB/ang_spec.m: -------------------------------------------------------------------------------- 1 | function SPEC = ang_spec(R, K, grid, N) 2 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 3 | % This is the noise subspace UN 4 | [U,D] = eig(R); 5 | eig_the = real(diag(D)); 6 | [~,Loc] = maxk(eig_the, K); 7 | Loc_noise = setdiff(1:length(eig_the), Loc); 8 | UN = U(:,Loc_noise); 9 | 10 | % Calculate the MUSIC spectra 11 | SPEC = zeros(1,numel(grid)); 12 | for kk=1:numel(grid) 13 | a = ULA_steer_vec(grid(kk), N); 14 | SPEC(kk) = 1/abs(a'*(UN*UN')*a); 15 | end 16 | end -------------------------------------------------------------------------------- /MATLAB/conv2matcom.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Author: Georgios K. Papageorgiou 3 | % Cite: [1]. G. K. Papageorgiou and M. Sellathurai, "Fast Direction-of-arrival 4 | % Estimation of Multiple Targets Using Deep Learning and Sparse Arrays," 5 | % IEEE International Conference on Acoustics, Speech and Signal Processing 6 | % (ICASSP), 2020. 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | % This function is the operator uvt() as described in [1]. 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | 11 | function Rx = conv2matcom(c) 12 | %%%%%%%%%%%%%%%%%%%%%%Input%%%%%%%%%%% 13 | % c: real-valued vector 14 | %%%%%%%%%%%%%%%%%%%%%Output%%%%%%%%%%% 15 | % R_x: a Hermitian matrix according to the reverse operator of vt() 16 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17 | Nd = sqrt(size(c,1)); 18 | Ndr = Nd*(Nd+1)/2; 19 | re_R = zeros(Nd); 20 | re_R(triu(ones(Nd),0)==1) = c(1:Ndr); 21 | re_R = re_R' + re_R - diag(diag(re_R)); 22 | im_R = zeros(Nd); %this is the upper triangular 23 | im_R(triu(ones(Nd),1)==1) = c(Ndr+1:end); 24 | im_R = im_R - im_R' ; 25 | Rx = re_R + 1j*im_R; 26 | end -------------------------------------------------------------------------------- /MATLAB/conv_cov2vec.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Author: Georgios K. Papageorgiou 3 | % Cite: [1]. G. K. Papageorgiou and M. Sellathurai, "Fast Direction-of-arrival 4 | % Estimation of Multiple Targets Using Deep Learning and Sparse Arrays," 5 | % IEEE International Conference on Acoustics, Speech and Signal Processing 6 | % (ICASSP), 2020. 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | % These are the operators vtr() and vti() as described in [1]. 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | 11 | function [re_R, im_R] = conv_cov2vec(R) 12 | %%%%%%%%%%%%%%%%%%%%%%Input%%%%%%%%%%% 13 | % R: complex-valued Hermitian matrix 14 | %%%%%%%%%%%%%%%%%%%%%Output%%%%%%%%%%% 15 | % re_R: a vector of the upper triangular's real part of R 16 | % im_R: a vector of the strict (+1 diagonal) upper triangular's imaginary part of R 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | re_R1 = real(R); 19 | re_R2 = triu(re_R1); 20 | re_R2_in = triu(true(size(re_R2))); 21 | re_R = re_R2(re_R2_in); 22 | 23 | im_R1 = imag(R); 24 | im_R2 = triu(im_R1,1); 25 | im_R2_in = triu(true(size(im_R2)),1); 26 | im_R = im_R2(im_R2_in); 27 | end 28 | 29 | -------------------------------------------------------------------------------- /MATLAB/l1_SVD_DoA_est.m: -------------------------------------------------------------------------------- 1 | function [ang_est, sp_val] = l1_SVD_DoA_est(Y,ULA_N,threshold,SOURCE_K, THETA_angles) 2 | % INPUTS: 3 | % Ry: the sample covariance estimate 4 | % ULA_N: the number of sensors in the array 5 | % noise_power: the variance of the noise 6 | % SOURCE_K: the number of sources 7 | % THETA_angles: the grid 8 | 9 | % OUTPUT: 10 | % ang_est: the DoA estimate 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 13 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 14 | % The grid and dictionary for the compressed sensing method 15 | NGrids = length(THETA_angles); 16 | A_dic = zeros(ULA_N,NGrids); 17 | for n=1:NGrids 18 | A_dic(:,n) = ULA_steer_vec(THETA_angles(n),ULA_N); 19 | end 20 | % Calculate the \ell_2,1 SVD 21 | [~,~,V] = svd(Y); 22 | Dr = [eye(rank(Y)) zeros(size(Y,1),size(Y,2) -rank(Y))]; 23 | Ydr = Y*V*Dr.'; 24 | 25 | % Solve SOCP using CVX 26 | cvx_begin quiet 27 | variable S_est_dr(NGrids,size(Y,1)) complex; 28 | minimize( sum(norms(S_est_dr.')) ); % this is the 2,1 norm of a matrix (mixed norm) % + 0.5*norm(y - A_dic*s_est,2) ); 29 | subject to 30 | norm(Ydr - A_dic*S_est_dr,'fro') <= threshold; 31 | cvx_end 32 | 33 | % % Solve SOCP using CVX 34 | % cvx_begin quiet 35 | % variable S_est_dr(NGrids,size(Y,1)) complex; 36 | % minimize ( threshold*sum(norms(S_est_dr.'))+0.5*square_pos(norm(Ydr - A_dic*S_est_dr,'fro')) );% this is the 2,1 norm of a matrix (mixed norm) % + 0.5*norm(y - A_dic*s_est,2) ); 37 | % cvx_end 38 | 39 | S_est = S_est_dr*Dr*V'; 40 | Ps = sum(abs(S_est).^2,2); 41 | % figure(1); 42 | % plot(Ps); 43 | [sp_val, spa_ind] = maxk(Ps,SOURCE_K); 44 | ang_est = sort(THETA_angles(spa_ind))'; 45 | 46 | end -------------------------------------------------------------------------------- /MATLAB/optimize_threshold_l1SVD.m: -------------------------------------------------------------------------------- 1 | 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % Author: Georgios K. Papageorgiou 4 | % Date: 7/9/2020 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | clear all; 7 | close all; 8 | tic; 9 | rng(14); 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | T = 1000; % number of snapshots 12 | threshold_vec = 350:10:450; 13 | SNR_dB = -10; % SNR values 14 | SOURCE_K = 2; % number of sources/targets - Kmax 15 | ULA_N = 16; 16 | SOURCE.interval = 60; 17 | Nsim = 20; 18 | res = 1; 19 | ang_sep = 3.8; 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21 | % The steering/response vector of the ULA, where theta=0.5*sin(deg2rad(x)); 22 | ULA_steer_vec = @(x,N) exp(1j*pi*sin(deg2rad(x))*(0:1:N-1)).'; 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | SOURCE_power = ones(1,SOURCE_K).^2; 25 | THETA_angles = -SOURCE.interval:res:SOURCE.interval; 26 | 27 | % These are the angles 28 | theta = 10; 29 | theta(2) = theta(1) + ang_sep; 30 | ang_gt = theta'; 31 | rho = 0.2; 32 | Pc = [1 0; rho sqrt(1-rho^2)]; 33 | 34 | A_ula =zeros(ULA_N,SOURCE_K); 35 | for k=1:SOURCE_K 36 | A_ula(:,k) = ULA_steer_vec(ang_gt(k),ULA_N); 37 | end 38 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 39 | 40 | RMSE_MUSIC = zeros(1,length(threshold_vec)); 41 | RMSE_RMUSIC = zeros(1,length(threshold_vec)); 42 | RMSE_l1SVD = zeros(1,length(threshold_vec)); 43 | 44 | noise_power = min(SOURCE_power)*10^(-SNR_dB/10); 45 | 46 | parfor ii=1:length(threshold_vec) 47 | threshold = threshold_vec(ii); 48 | 49 | r_sam = zeros(ULA_N,ULA_N,3,Nsim); 50 | r_the = zeros(ULA_N,ULA_N,3,Nsim); 51 | Y_dr = zeros(ULA_N,ULA_N,Nsim); 52 | 53 | mse_sam = 0; 54 | mse_sam_rm = 0; 55 | mse_l1svd = 0; 56 | 57 | for i=1:Nsim 58 | 59 | % The signal plus noise 60 | S = (randn(SOURCE_K,T)+1j*randn(SOURCE_K,T))/sqrt(2); 61 | X = A_ula*Pc*S; 62 | Eta = sqrt(noise_power)*(randn(ULA_N,T)+1j*randn(ULA_N,T))/sqrt(2); 63 | Y = X + Eta; 64 | % The sample covariance matrix 65 | Ry_sam = Y*Y'/T; 66 | 67 | % MUSIC estimate 68 | [doas_sam, spec_sam, specang_sam] = musicdoa(Ry_sam,SOURCE_K, 'ScanAngles', THETA_angles); 69 | ang_sam = sort(doas_sam)'; 70 | % RMSE calculation 71 | mse_sam = mse_sam + norm(ang_sam- ang_gt)^2; 72 | 73 | % Root-MUSIC estimator 74 | doas_sam_rm = sort(rootmusicdoa(Ry_sam, SOURCE_K))'; 75 | ang_sam_rm = sort(doas_sam_rm); 76 | % RMSE calculation - degrees 77 | mse_sam_rm = mse_sam_rm + norm(ang_sam_rm - ang_gt)^2; 78 | 79 | % l1_SVD 80 | [ang_est_l1svd, sp_val_l1svd] = l1_SVD_DoA_est(Y,ULA_N,threshold,SOURCE_K, THETA_angles); 81 | mse_l1svd = mse_l1svd + norm(sort(ang_est_l1svd) - ang_gt)^2; 82 | 83 | end 84 | 85 | RMSE_MUSIC(ii) = sqrt(mse_sam/SOURCE_K/Nsim); 86 | RMSE_RMUSIC(ii) = sqrt(mse_sam_rm/SOURCE_K/Nsim); 87 | RMSE_l1SVD(ii) = sqrt(mse_l1svd/SOURCE_K/Nsim); 88 | 89 | ii 90 | end 91 | 92 | time_tot = toc/60; % in minutes 93 | 94 | figure(1); 95 | plot(threshold_vec, RMSE_MUSIC); 96 | hold on; 97 | plot(threshold_vec, RMSE_RMUSIC); 98 | plot(threshold_vec, RMSE_l1SVD); 99 | hold off; 100 | legend('MUSIC','R-MUSIC','$\ell_1$-SVD', 'interpreter','latex'); 101 | 102 | 103 | [val,ind] = min(RMSE_l1SVD); 104 | best_thresh = threshold_vec(ind); 105 | disp(['The best threshold value is ',num2str(best_thresh)]); 106 | RMSE_l1SVD(ind) 107 | -------------------------------------------------------------------------------- /MATLAB/plot_experiment1B.m: -------------------------------------------------------------------------------- 1 | % Plot the results for Exp. 1B with Delta \theta =2.11 at 0 dB SNR T=200 2 | 3 | close all; 4 | 5 | % Load the MUSIC, R-MUSIC results 6 | File = fullfile(save_path,'Slide_angsep2coma11_K2_0dB_T200.mat'); 7 | load(File); 8 | 9 | % Load the CNN results 10 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 11 | 'DoA_Estimation_underdetermined\ComparisonRESULTS\Slide_ang_2coma11sep_K2_0dB_T200_CNN_RQ.h5'); 12 | gt_ang = h5read(filename, '/GT_angles'); 13 | CNN_pred = double(h5read(filename, '/CNN_pred_angles')); 14 | 15 | % Load the l1-SVD results 16 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 17 | 'RMSE_l1SVD_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11.h5'); 18 | l1_SVD_ang_est = double(h5read(filename2, '/l1_SVD_ang')); 19 | 20 | filename3 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 21 | 'RMSE_UnESPRIT_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11.h5'); 22 | UnESPRIT_ang_est = double(h5read(filename3, '/UnESPRIT_ang')); 23 | 24 | sam_ind = 1:length(ang_gt(1,:)); 25 | 26 | ang_MLP = [[-58.58102006 -58.58102006] 27 | [-57.61889195 -57.61889195] 28 | [-58.19135518 -54.9332847 ] 29 | [-55.57817099 -55.57817099] 30 | [-54.16059591 -54.16059591] 31 | [-52.98113591 -52.98113591] 32 | [-52.45154147 -52.45154147] 33 | [-51.71131289 -51.71131289] 34 | [-50.69628834 -50.69628834] 35 | [-50. -48. ] 36 | [-48.86888944 -48.86888944] 37 | [-47.43191255 -47.43191255] 38 | [-46.61173559 -46.61173559] 39 | [-47.1106154 -43.86046424] 40 | [-46. -43.11792146] 41 | [-45.0961141 -42.02897901] 42 | [-44. -41.63408055] 43 | [-42.79113952 -42.79113952] 44 | [-40.56349292 -40.56349292] 45 | [-38.20852076 -38.20852076] 46 | [-36.97515013 -36.97515013] 47 | [-40.22553301 -36. ] 48 | [-36.40675975 -36.40675975] 49 | [-35.63105605 -35.63105605] 50 | [-34.33382946 -34.33382946] 51 | [-33.53758696 -33.53758696] 52 | [-32.40128099 -32.40128099] 53 | [-31.12022665 -31.12022665] 54 | [-32.18764396 -28.00154305] 55 | [-29.13135302 -29.13135302] 56 | [-28.45969951 -28.45969951] 57 | [-27.68763118 -27.68763118] 58 | [-26.14548707 -26.14548707] 59 | [-26.66898992 -23.46531302] 60 | [-24.59492882 -24.59492882] 61 | [-23.67352982 -23.67352982] 62 | [-22.90366696 -22.90366696] 63 | [-21.66044068 -21.66044068] 64 | [-20.11869848 -20.11869848] 65 | [-20.15515174 -17.93250735] 66 | [-17.86481448 -17.86481448] 67 | [-17.43792935 -17.43792935] 68 | [-19.12055683 -15.7092554 ] 69 | [-15.43008091 -15.43008091] 70 | [-14.59758195 -14.59758195] 71 | [-13.10709348 -13.10709348] 72 | [-12.28534529 -12.28534529] 73 | [-10.93460963 -10.93460963] 74 | [-10.36298512 -10.36298512] 75 | [ -9.84996525 -9.84996525] 76 | [ -8.31301623 -8.31301623] 77 | [ -7.63883178 -7.63883178] 78 | [ -6.52650228 -6.52650228] 79 | [ -4.88421824 -4.88421824] 80 | [ -4.58288538 -4.58288538] 81 | [ -3.86404152 -3.86404152] 82 | [ -3.02936083 -3.02936083] 83 | [ -1.92266242 -1.92266242] 84 | [ -0.35529619 -0.35529619] 85 | [ 0.61346991 0.61346991] 86 | [ 1.82207768 1.82207768] 87 | [ 2.25822512 2.25822512] 88 | [ 2.9659342 2.9659342 ] 89 | [ 2.83869626 5.16075993] 90 | [ 5.27132226 5.27132226] 91 | [ 6.62322701 6.62322701] 92 | [ 7.57031548 7.57031548] 93 | [ 8.33383421 8.33383421] 94 | [ 9.52618255 9.52618255] 95 | [ 10.57415175 10.57415175] 96 | [ 11.55732867 11.55732867] 97 | [ 12.65932739 12.65932739] 98 | [ 13.55592154 13.55592154] 99 | [ 14.87624517 14.87624517] 100 | [ 15.38759913 15.38759913] 101 | [ 16.23465662 16.23465662] 102 | [ 17.16412041 17.16412041] 103 | [ 18.01867796 18.01867796] 104 | [ 19.80236106 19.80236106] 105 | [ 20.90744346 20.90744346] 106 | [ 22.24825617 22.24825617] 107 | [ 22.60875024 22.60875024] 108 | [ 23.27341151 23.27341151] 109 | [ 24.22615544 24.22615544] 110 | [ 25.14407527 25.14407527] 111 | [ 26.41995753 26.41995753] 112 | [ 27.53827824 27.53827824] 113 | [ 27.7902021 30. ] 114 | [ 30.35031397 30.35031397] 115 | [ 29.95545127 29.95545127] 116 | [ 31.60182599 31.60182599] 117 | [ 32.06828949 32.06828949] 118 | [ 32. 34.8760882 ] 119 | [ 34.71229432 34.71229432] 120 | [ 35.58081416 35.58081416] 121 | [ 36.36880139 36.36880139] 122 | [ 37.4873462 37.4873462 ] 123 | [ 38.17588795 38.17588795] 124 | [ 39.5320504 39.5320504 ] 125 | [ 39.02946058 42. ] 126 | [ 42.86866295 42.86866295] 127 | [ 42.56354069 42.56354069] 128 | [ 43.57557918 43.57557918] 129 | [ 44.2671976 44.2671976 ] 130 | [ 46.26550916 46.26550916] 131 | [ 46.5437715 46.5437715 ] 132 | [ 47.27503439 47.27503439] 133 | [ 48.10630679 48.10630679] 134 | [ 49.41960671 49.41960671] 135 | [ 50.37505687 50.37505687] 136 | [ 51.28303179 51.28303179] 137 | [ 45. 45. ] 138 | [ 53.46994853 53.46994853] 139 | [ 54.34671526 54.34671526] 140 | [ 55.61692839 55.61692839] 141 | [ 8.43923097 8.43923097] 142 | [ 51.6601211 51.6601211 ] 143 | [ 57. 57. ]]'; 144 | 145 | count = 0; 146 | for ii=1:size(sam_ind,2) 147 | if ang_MLP(1,ii)==ang_MLP(2,ii) 148 | ang_MLP(2,ii) = NaN; 149 | count = count + 1; 150 | end 151 | end 152 | 153 | % Plot the MUSIC results 154 | f_m(1)= figure(1); 155 | plot(sam_ind, ang_gt(1,:),'Color','r'); 156 | hold on; 157 | plot(sam_ind, ang_gt(2,:),'Color','b'); 158 | scatter(sam_ind, ang_sam(1,:),'Marker','^','MarkerEdgeColor',[1 0 0]); 159 | scatter(sam_ind, ang_sam(2,:),'Marker','^','MarkerEdgeColor',[0 0 1]); 160 | hold off; 161 | % xlim([0 sam_ind(end)+1]); ylim([-61 61]); 162 | grid on; 163 | legend('$\theta_1$','$\theta_2$','$\hat{\theta}_1$','$\hat{\theta}_2$','interpreter','latex'); 164 | title('MUSIC', 'interpreter','latex'); 165 | ylabel('DoA [degrees]', 'interpreter','latex'); 166 | xlabel('Sample index', 'interpreter','latex'); 167 | 168 | f_m(2) = figure(2); 169 | scatter(sam_ind, ang_gt(1,:)-ang_sam(1,:),'Marker','^','MarkerEdgeColor',[1 0 0]); 170 | hold on; 171 | scatter(sam_ind, ang_gt(2,:)-ang_sam(2,:),'Marker','^','MarkerEdgeColor',[0 0 1]); 172 | hold off; 173 | grid on; 174 | legend('$\Delta \theta_1=\theta_1 - \hat{\theta}_1$','$\Delta \theta_2=\theta_2 - \hat{\theta}_2$','interpreter','latex'); 175 | title('MUSIC errors', 'interpreter','latex'); 176 | ylabel('DoA [degrees]', 'interpreter','latex'); 177 | xlabel('Sample index', 'interpreter','latex'); 178 | 179 | sq_dif = abs(gt_ang - ang_sam).^2; 180 | RMSE_MUSIC = sqrt(sum(sq_dif(:))/length(sam_ind)/2); 181 | 182 | % Plot the R-MUSIC results 183 | f_rm(1) = figure(3); 184 | plot(sam_ind, ang_gt(1,:),'Color','r'); 185 | hold on; 186 | plot(sam_ind, ang_gt(2,:),'Color','b'); 187 | scatter(sam_ind, ang_sam_rm(1,:),'Marker','o','MarkerEdgeColor',[1 0 0]); 188 | scatter(sam_ind, ang_sam_rm(2,:),'Marker','o','MarkerEdgeColor',[0 0 1]); 189 | hold off; 190 | % xlim([0 sam_ind(end)+1]); ylim([-61 61]); 191 | grid on; 192 | legend('$\theta_1$','$\theta_2$','$\hat{\theta}_1$','$\hat{\theta}_2$','interpreter','latex'); 193 | title('R-MUSIC', 'interpreter','latex'); 194 | ylabel('DoA [degrees]', 'interpreter','latex'); 195 | xlabel('Sample index', 'interpreter','latex'); 196 | 197 | f_rm(2) = figure(4); 198 | scatter(sam_ind, ang_gt(1,:)-ang_sam_rm(1,:),'Marker','o','MarkerEdgeColor',[1 0 0]); 199 | hold on; 200 | scatter(sam_ind,ang_gt(2,:)-ang_sam_rm(2,:),'Marker','o','MarkerEdgeColor',[0 0 1]); 201 | grid on; 202 | legend('$\Delta \theta_1=\theta_1 - \hat{\theta}_1$','$\Delta \theta_2=\theta_2 - \hat{\theta}_2$','interpreter','latex'); 203 | title('R-MUSIC errors', 'interpreter','latex'); 204 | ylabel('DoA [degrees]', 'interpreter','latex'); 205 | xlabel('Sample index', 'interpreter','latex'); 206 | 207 | sq_dif = abs(gt_ang - ang_sam_rm).^2; 208 | RMSE_RMUSIC = sqrt(sum(sq_dif(:))/length(sam_ind)/2); 209 | 210 | % CNN 211 | f_cnn(1) = figure(5); 212 | plot(sam_ind, gt_ang(1,:),'Color','r'); 213 | hold on; 214 | plot(sam_ind, gt_ang(2,:),'Color','b'); 215 | scatter(sam_ind, CNN_pred(1,:),'Marker','d','MarkerEdgeColor',[1 0 0]); 216 | scatter(sam_ind, CNN_pred(2,:),'Marker','d','MarkerEdgeColor',[0 0 1]); 217 | hold off; 218 | % xlim([0 sam_ind(end)+1]); ylim([-61 61]); 219 | grid on; 220 | legend('$\theta_1$','$\theta_2$','$\hat{\theta}_1$','$\hat{\theta}_2$','interpreter','latex'); 221 | title('CNN', 'interpreter','latex'); 222 | ylabel('DoA [degrees]', 'interpreter','latex'); 223 | xlabel('Sample index', 'interpreter','latex'); 224 | 225 | f_cnn(2) = figure(6); 226 | scatter(sam_ind, gt_ang(1,:)-CNN_pred(1,:),'Marker','d','MarkerEdgeColor',[1 0 0]); 227 | hold on; 228 | scatter(sam_ind,gt_ang(2,:)-CNN_pred(2,:),'Marker','d','MarkerEdgeColor',[0 0 1]); 229 | grid on; 230 | ylim([-11 11]); 231 | legend('$\Delta \theta_1=\theta_1 - \hat{\theta}_1$','$\Delta \theta_2=\theta_2 - \hat{\theta}_2$','interpreter','latex'); 232 | title('CNN errors', 'interpreter','latex'); 233 | ylabel('DoA [degrees]', 'interpreter','latex'); 234 | xlabel('Sample index', 'interpreter','latex'); 235 | 236 | sq_dif = abs(gt_ang - CNN_pred).^2; 237 | RMSE_CNN = sqrt(sum(sq_dif(:))/length(sam_ind)/2); 238 | 239 | % Plot l1-SVD results 240 | f_gl1(1) = figure(7); 241 | plot(sam_ind, gt_ang(1,:),'Color','r'); 242 | hold on; 243 | plot(sam_ind, gt_ang(2,:),'Color','b'); 244 | scatter(sam_ind, l1_SVD_ang_est(1,:),'Marker','*','MarkerEdgeColor',[1 0 0]); 245 | scatter(sam_ind, l1_SVD_ang_est(2,:),'Marker','*','MarkerEdgeColor',[0 0 1]); 246 | hold off; 247 | %xlim([0 sam_ind(end)+1]); ylim([-61 61]); 248 | grid on; 249 | legend('$\theta_1$','$\theta_2$','$\hat{\theta}_1$','$\hat{\theta}_2$','interpreter','latex'); 250 | title('$\ell_{2,1}$-SVD', 'interpreter','latex'); 251 | ylabel('DoA [degrees]', 'interpreter','latex'); 252 | xlabel('Sample index', 'interpreter','latex'); 253 | 254 | f_gl1(2) = figure(8); 255 | scatter(sam_ind, gt_ang(1,:)-l1_SVD_ang_est(1,:),'Marker','*','MarkerEdgeColor',[1 0 0]); 256 | hold on; 257 | scatter(sam_ind,gt_ang(2,:)-l1_SVD_ang_est(2,:),'Marker','*','MarkerEdgeColor',[0 0 1]); 258 | grid on; 259 | ylim([-11 8]); 260 | legend('$\Delta \theta_1=\theta_1 - \hat{\theta}_1$','$\Delta \theta_2=\theta_2 - \hat{\theta}_2$','interpreter','latex'); 261 | title('$\ell_{2,1}$-SVD errors', 'interpreter','latex'); 262 | ylabel('DoA [degrees]', 'interpreter','latex'); 263 | xlabel('Sample index', 'interpreter','latex'); 264 | 265 | sq_dif = abs(gt_ang - l1_SVD_ang_est).^2; 266 | RMSE_l1_SVD = sqrt(sum(sq_dif(:))/length(sam_ind)/2); 267 | 268 | % Plot the proposed MLP results 269 | f_mlp(1) = figure(9); 270 | plot(sam_ind, gt_ang(1,:),'Color','r'); 271 | hold on; 272 | plot(sam_ind, gt_ang(2,:),'Color','b'); 273 | scatter(sam_ind, ang_MLP(1,:),'Marker','x','MarkerEdgeColor',[1 0 0]); 274 | scatter(sam_ind, ang_MLP(2,:),'Marker','x','MarkerEdgeColor',[0 0 1]); 275 | hold off; 276 | %xlim([0 sam_ind(end)+1]); ylim([-61 61]); 277 | grid on; 278 | legend('$\theta_1$','$\theta_2$','$\hat{\theta}_1$','$\hat{\theta}_2$','interpreter','latex'); 279 | title('MLP', 'interpreter','latex'); 280 | ylabel('DoA [degrees]', 'interpreter','latex'); 281 | xlabel('Sample index', 'interpreter','latex'); 282 | 283 | f_mlp(2) = figure(10); 284 | scatter(sam_ind, gt_ang(1,:)-ang_MLP(1,:),'Marker','x','MarkerEdgeColor',[1 0 0]); 285 | hold on; 286 | scatter(sam_ind,gt_ang(2,:)-ang_MLP(2,:),'Marker','x','MarkerEdgeColor',[0 0 1]); 287 | grid on; 288 | legend('$\Delta \theta_1=\theta_1 - \hat{\theta}_1$','$\Delta \theta_2=\theta_2 - \hat{\theta}_2$','interpreter','latex'); 289 | title('MLP errors', 'interpreter','latex'); 290 | ylabel('DoA [degrees]', 'interpreter','latex'); 291 | xlabel('Sample index', 'interpreter','latex'); 292 | 293 | sq_dif = abs(gt_ang - ang_MLP).^2; 294 | RMSE_MLP = sqrt(sum(sq_dif(:))/length(sam_ind)/2); 295 | 296 | % Plot the ESPRIT results 297 | f_esp(1) = figure(11); 298 | plot(sam_ind, ang_gt(1,:),'Color','r'); 299 | hold on; 300 | plot(sam_ind, ang_gt(2,:),'Color','b'); 301 | scatter(sam_ind, ang_sam_esp(1,:),'Marker','+','MarkerEdgeColor',[1 0 0]); 302 | scatter(sam_ind, ang_sam_esp(2,:),'Marker','+','MarkerEdgeColor',[0 0 1]); 303 | hold off; 304 | xlim([0 sam_ind(end)+1]); ylim([-70 70]); 305 | grid on; 306 | %axis('tight'); 307 | legend('$\theta_1$','$\theta_2$','$\hat{\theta}_1$','$\hat{\theta}_2$','interpreter','latex'); 308 | title('ESPRIT', 'interpreter','latex'); 309 | ylabel('DoA [degrees]', 'interpreter','latex'); 310 | xlabel('Sample index', 'interpreter','latex'); 311 | 312 | f_esp(2) = figure(12); 313 | scatter(sam_ind, ang_gt(1,:)-ang_sam_esp(1,:),'Marker','+','MarkerEdgeColor',[1 0 0]); 314 | hold on; 315 | scatter(sam_ind,ang_gt(2,:)-ang_sam_esp(2,:),'Marker','+','MarkerEdgeColor',[0 0 1]); 316 | grid on; 317 | ylim([-11 8]); 318 | legend('$\Delta \theta_1=\theta_1 - \hat{\theta}_1$','$\Delta \theta_2=\theta_2 - \hat{\theta}_2$','interpreter','latex'); 319 | title('ESPRIT Errors', 'interpreter','latex'); 320 | ylabel('DoA [degrees]', 'interpreter','latex'); 321 | xlabel('Sample index', 'interpreter','latex'); 322 | 323 | sq_dif = abs(gt_ang - ang_sam_esp).^2; 324 | RMSE_ESPRIT = sqrt(sum(sq_dif(:))/length(sam_ind)/2); 325 | 326 | % Plot UnESPRIT results 327 | f_unesp(1) = figure(13); 328 | plot(sam_ind, gt_ang(1,:),'Color','r'); 329 | hold on; 330 | plot(sam_ind, gt_ang(2,:),'Color','b'); 331 | scatter(sam_ind, UnESPRIT_ang_est(1,:),'Marker','s','MarkerEdgeColor',[1 0 0]); 332 | scatter(sam_ind, UnESPRIT_ang_est(2,:),'Marker','s','MarkerEdgeColor',[0 0 1]); 333 | hold off; 334 | xlim([0 sam_ind(end)+1]); ylim([-65 65]); 335 | grid on; 336 | legend('$\theta_1$','$\theta_2$','$\hat{\theta}_1$','$\hat{\theta}_2$','interpreter','latex'); 337 | title('UnESPRIT', 'interpreter','latex'); 338 | ylabel('DoA [degrees]', 'interpreter','latex'); 339 | xlabel('Sample index', 'interpreter','latex'); 340 | 341 | f_unesp(2) = figure(14); 342 | scatter(sam_ind, gt_ang(1,:)-UnESPRIT_ang_est(1,:),'Marker','s','MarkerEdgeColor',[1 0 0]); 343 | hold on; 344 | scatter(sam_ind,gt_ang(2,:)-UnESPRIT_ang_est(2,:),'Marker','s','MarkerEdgeColor',[0 0 1]); 345 | grid on; 346 | ylim([-11 8]); 347 | legend('$\Delta \theta_1=\theta_1 - \hat{\theta}_1$','$\Delta \theta_2=\theta_2 - \hat{\theta}_2$','interpreter','latex'); 348 | title('UnESPRIT Errors', 'interpreter','latex'); 349 | ylabel('DoA [degrees]', 'interpreter','latex'); 350 | xlabel('Sample index', 'interpreter','latex'); 351 | 352 | sq_dif = abs(gt_ang - UnESPRIT_ang_est).^2; 353 | RMSE_UnESPRIT = sqrt(sum(sq_dif(:))/length(sam_ind)/2); 354 | 355 | VarNames = {'RMSE'}; 356 | Tab = table(VarNames, RMSE_MUSIC, RMSE_RMUSIC, RMSE_CNN, RMSE_l1_SVD, RMSE_MLP, RMSE_ESPRIT, RMSE_UnESPRIT) 357 | 358 | 359 | -------------------------------------------------------------------------------- /MATLAB/plot_experiment2.m: -------------------------------------------------------------------------------- 1 | % Plot the RMSE results for Experiment 2 with Delta \theta =3.19 vs SNR 2 | % Author: Georgios K. Papageorgiou 3 | % Date: 19/09/2020 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | 6 | % clear all; 7 | close all; 8 | % Load the results 9 | T = 1000; 10 | 11 | % Load the MUSIC,R-MUSIC, CRLB results 12 | File = fullfile(save_path,'RMSE_K2_offgrid_ang_fixed_allSNR_T1000.mat'); 13 | load(File); 14 | 15 | % Load the CNN results 16 | % filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 17 | % 'DoA_Estimation_underdetermined\MUSIC_RESULTS\RMSE_CNN_K2_fixed_offgrid_ang_all_SNR_T1000_new_train_low.h5'); 18 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 19 | 'DoA_Estimation_underdetermined\ComparisonRESULTS\RMSE_CNN_K2_fixed_offgrid_ang_all_SNR_T1000_RQ.h5'); 20 | RMSE_CNN = double(h5read(filename, '/CNN_RMSE')); 21 | 22 | % Load the l1-SVD results 23 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 24 | 'TEST_DATA1K_16ULA_K2_fixed_offgrid_ang_allSNR_T1000_3D.h5'); 25 | RMSE_l1_SVD = double(h5read(filename2, '/RMSE_l1SVD')); 26 | RMSE_UnESPRIT = double(h5read(filename2, '/RMSE_UnESPRIT')); 27 | 28 | RMSE_MLP = [NaN NaN NaN 0.19 0.17 0.16 0.16 0.16 0.16 0.16 0.16]; 29 | 30 | %% 31 | % New Color Options 32 | orange = [0.8500, 0.3250, 0.0980]; 33 | gold_yellow = [0.9290, 0.6940, 0.1250]; 34 | new_green = [0.4660, 0.6740, 0.1880]; 35 | 36 | f=figure(1); 37 | plot(SNR_vec,RMSE_sam,'^--','Color',orange); 38 | hold on; 39 | plot(SNR_vec,RMSE_sam_rm,'o-.','Color', gold_yellow); 40 | plot(SNR_vec,RMSE_sam_esp,'+--','Color','r'); 41 | plot(SNR_vec,RMSE_UnESPRIT,'s-.','Color','g'); 42 | plot(SNR_vec,RMSE_l1_SVD,'*--','Color','m'); 43 | plot(SNR_vec,RMSE_MLP,'x--','Color','c'); 44 | plot(SNR_vec,RMSE_CNN,'d--','Color','b'); 45 | plot(SNR_vec, CRB_uncr,'.-','Color','k'); 46 | hold off; 47 | set(gca, 'YScale', 'log'); 48 | legend('MUSIC', 'R-MUSIC','ESPRIT','UnESPRIT','$\ell_{2,1}$-SVD','MLP','CNN','CRLB$_{uncr}$',... 49 | 'interpreter','latex'); 50 | title(['DoA-estimation of K=2 sources from $T=$',num2str(T), ' snapshots'], 'interpreter','latex'); 51 | ylabel('RMSE [degrees]', 'interpreter','latex'); 52 | xlabel('SNR [dB]', 'interpreter','latex'); 53 | grid on; 54 | -------------------------------------------------------------------------------- /MATLAB/plot_experiment3.m: -------------------------------------------------------------------------------- 1 | % Plot the RMSE results for Exp. 3 RMSE vs T 2 | % Author: Georgios K. Papageorgiou 3 | % Date: 19/09/2020 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | % clear all; 6 | 7 | % Load the results 8 | T_vec = 1000*[0.1 0.2 0.5 1 2 5 10]; 9 | SNR = -10; 10 | % Load the MUSIC,R-MUSIC, CRLB results 11 | File = fullfile(save_path,'RMSE_K2_min10dB_ang_sep3coma6_vsT.mat'); 12 | load(File); 13 | % Load the CNN results 14 | % filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 15 | % 'DoA_Estimation_underdetermined\MUSIC_RESULTS\RMSE_CNN_K2_min10dBSNR_vsT_ang_sep3coma6_new_train_low.h5'); 16 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 17 | 'DoA_Estimation_underdetermined\ComparisonRESULTS\RMSE_CNN_K2_min10dBSNR_vsT_ang_sep3coma6_new_train_low_vf.h5'); 18 | RMSE_CNN = double(h5read(filename, '/CNN_RMSE')); 19 | % Load the l1-SVD results 20 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 21 | 'RMSE_l1_SVD_DATA1K_16ULA_K2_min10dBSNR_3D_fixed_ang_sep3coma6_vsT.h5'); 22 | RMSE_l1SVD = double(h5read(filename2, '/RMSE_l1_SVD')); 23 | % UnESPRIT 24 | filename3 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 25 | 'RMSE_UnESPRIT_DATA1K_16ULA_K2_min10dBSNR_3D_fixed_ang_sep3coma6_vsT.h5'); 26 | RMSE_UnESPRIT = double(h5read(filename3, '/RMSE_UnESPRIT')); 27 | 28 | RMSE_MLP = [1.61, 1.48, 0.83, 0.57, 0.67, 0.18, 0.21]; 29 | %% 30 | % New Color Options 31 | orange = [0.8500, 0.3250, 0.0980]; 32 | gold_yellow = [0.9290, 0.6940, 0.1250]; 33 | new_green = [0.4660, 0.6740, 0.1880]; 34 | 35 | f=figure(1); 36 | plot(T_vec,RMSE_sam,'^--','Color',orange); 37 | hold on; 38 | plot(T_vec,RMSE_sam_rm,'o-.','Color',gold_yellow); 39 | plot(T_vec,RMSE_sam_esp,'+--','Color','r'); 40 | plot(T_vec,RMSE_UnESPRIT,'s-.','Color','g'); 41 | plot(T_vec,RMSE_l1SVD,'*--','Color','m'); 42 | % plot(T_vec,RMSE_MLP,'x--','Color','c'); 43 | plot(T_vec,RMSE_CNN,'d--','Color','b'); 44 | % plot(T_vec, CRLB,'.-','Color','k'); 45 | plot(T_vec, CRB_uncr,'.-','Color','k'); 46 | hold off; 47 | set(gca, 'YScale', 'log','XScale', 'log'); 48 | legend('MUSIC', 'R-MUSIC','ESPRIT','UnESPRIT','$\ell_{2,1}$-SVD','CNN','CRLB$_{uncr}$',... 49 | 'interpreter','latex'); 50 | title(['DoA-estimation of K=2 sources at ',num2str(SNR), ' dB SNR'], 'interpreter','latex'); 51 | ylabel('RMSE [degrees]', 'interpreter','latex'); 52 | xlabel('T [snapshots] $\times 100$', 'interpreter','latex'); 53 | xticks([1 2 5 10 20 50 100]*100); 54 | xticklabels([1 2 5 10 20 50 100]); 55 | grid on; 56 | 57 | % savefig(f,'RMSE_exp2_T100_cnn_res1_fixed_ang_offgrid.fig'); -------------------------------------------------------------------------------- /MATLAB/plot_experiment4.m: -------------------------------------------------------------------------------- 1 | % Plot the RMSE results for Exp. 4 RMSE vs \Delta \theta 2 | % Author: Georgios K. Papageorgiou 3 | % Date: 19/09/2020 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | % clear all; 6 | close all; 7 | 8 | % Load the results 9 | T = 500; % number of snapshots 10 | ang_sep_vec = [1 2 4 6 10 14]; % SNR values 11 | SNR = -10; 12 | % Load the MUSIC,R-MUSIC, CRLB results 13 | File = fullfile(save_path,'RMSE_K2_vs_ang_sep_T500_min10dBSNR_v2.mat'); 14 | load(File); 15 | % Load the CNN results 16 | % filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 17 | % 'DoA_Estimation_underdetermined\MUSIC_RESULTS\RMSE_CNN_K2_vs_ang_sep_T500_min10dBSNR.h5'); 18 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 19 | 'DoA_Estimation_underdetermined\ComparisonRESULTS\RMSE_CNN_K2_vs_ang_sep_T500_min10dBSNR_new_vf2.h5'); 20 | RMSE_CNN = double(h5read(filename, '/CNN_RMSE')); 21 | % Load the l1-SVD results 22 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 23 | 'RMSE_l1_SVD_16ULA_K2_min10dBSNR_T500_3D_vs_ang_sep_v2.h5'); 24 | RMSE_l1SVD = double(h5read(filename2, '/RMSE_l1_SVD')); 25 | % Load the ESPRIT results 26 | filename3 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 27 | 'RMSE_UnESPRIT_16ULA_K2_min10dBSNR_T500_3D_vs_ang_sep_v2.h5'); 28 | RMSE_UnESPRIT = double(h5read(filename3, '/RMSE_UnESPRIT')); 29 | 30 | % RMSE_MLP = [NaN, NaN, NaN, NaN, 0.39, 0.42]; % T=500 31 | RMSE_MLP = [NaN, NaN, NaN, NaN, 0.29, 0.36]; % T=1000 32 | 33 | %% 34 | % New Color Options 35 | orange = [0.8500, 0.3250, 0.0980]; 36 | gold_yellow = [0.9290, 0.6940, 0.1250]; 37 | new_green = [0.4660, 0.6740, 0.1880]; 38 | 39 | f=figure(1); 40 | plot(ang_sep_vec,RMSE_sam,'^--','Color',orange); 41 | hold on; 42 | plot(ang_sep_vec,RMSE_sam_rm,'o-.','Color',gold_yellow); 43 | plot(ang_sep_vec,RMSE_sam_esp,'+--','Color','r'); 44 | plot(ang_sep_vec,RMSE_UnESPRIT,'s-.','Color','g'); 45 | plot(ang_sep_vec,RMSE_l1SVD,'*--','Color','m'); 46 | plot(ang_sep_vec,RMSE_MLP,'x--','Color','c'); 47 | plot(ang_sep_vec,RMSE_CNN,'d--','Color','b'); 48 | % plot(ang_sep_vec, CRLB,'v-','Color','y'); 49 | plot(ang_sep_vec, CRLB_uncr,'.-','Color','k'); 50 | hold off; 51 | set(gca, 'YScale', 'log'); 52 | legend('MUSIC', 'R-MUSIC','ESPRIT','UnESPRIT','$\ell_{2,1}$-SVD','MLP','CNN','CRLB$_{uncr}$',... 53 | 'interpreter','latex'); 54 | xticks([0 1 2 4 6 8 10 12 14]); 55 | yticks([1 3 5:5:35]); 56 | title(['DoA-estimation of K=2 sources at ',num2str(SNR), ' dB SNR'], 'interpreter','latex'); 57 | ylabel('RMSE [degrees]', 'interpreter','latex'); 58 | xlabel('$\Delta \theta$ [degrees]', 'interpreter','latex'); 59 | grid on; 60 | 61 | % savefig(f,'RMSE_exp2_T100_cnn_res1_fixed_ang_offgrid.fig'); 62 | -------------------------------------------------------------------------------- /MATLAB/plot_experiment5.m: -------------------------------------------------------------------------------- 1 | % Plot the results for Exp. 1B with Delta \theta =2.11 at 0 dB SNR T=200 2 | 3 | clear all; 4 | close all; 5 | % Load the CNN results 6 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 7 | 'DoA_Estimation_underdetermined\MUSIC_RESULTS\Slide_ang_2coma11sep_K2_0dB_T200_CNN_new_v2_power_mismatch.h5'); 8 | gt_ang = h5read(filename, '/GT_angles'); 9 | CNN_pred = double(h5read(filename, '/CNN_pred_angles')); 10 | 11 | % Load the l1-SVD results 12 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 13 | 'RMSE_l1SVD_16ULA_K2_0dBSNR_T200_3D_slideang_offgrid_sep2coma11_power_mismatch.h5'); 14 | l1_SVD_ang_est = double(h5read(filename2, '/l1_SVD_ang')); 15 | 16 | sam_ind = 1:length(gt_ang(1,:)); 17 | 18 | f_cnn(1) = figure(1); 19 | plot(sam_ind, gt_ang(1,:),'Color','r'); 20 | hold on; 21 | plot(sam_ind, gt_ang(2,:),'Color','b'); 22 | s1 = scatter(sam_ind, CNN_pred(1,:),'Marker','d','MarkerEdgeColor',[1 0 0]); 23 | s2 = scatter(sam_ind, CNN_pred(2,:),'Marker','d','MarkerEdgeColor',[0 0 1]); 24 | hold off; 25 | xlim([0 sam_ind(end)+1]); ylim([-61 61]); 26 | grid on; 27 | title('CNN', 'interpreter','latex'); 28 | ylabel('DoA [degrees]', 'interpreter','latex'); 29 | xlabel('Sample index', 'interpreter','latex'); 30 | 31 | f_cnn(1) = figure(2); 32 | scatter(sam_ind, gt_ang(1,:)-CNN_pred(1,:),'Marker','d','MarkerEdgeColor',[1 0 0]); 33 | hold on; 34 | scatter(sam_ind,gt_ang(2,:)-CNN_pred(2,:),'Marker','d','MarkerEdgeColor',[0 0 1]); 35 | grid on; 36 | title('CNN errors', 'interpreter','latex'); 37 | ylabel('DoA [degrees]', 'interpreter','latex'); 38 | xlabel('Sample index', 'interpreter','latex'); 39 | 40 | c1 = gt_ang(1,:)-CNN_pred(1,:); 41 | c2 = gt_ang(2,:)-CNN_pred(2,:); 42 | 43 | % Plot l1-SVD results 44 | f_gl1(1) = figure(3); 45 | plot(sam_ind, gt_ang(1,:),'Color','r'); 46 | hold on; 47 | plot(sam_ind, gt_ang(2,:),'Color','b'); 48 | scatter(sam_ind, l1_SVD_ang_est(1,:),'Marker','*','MarkerEdgeColor',[1 0 0]); 49 | scatter(sam_ind, l1_SVD_ang_est(2,:),'Marker','*','MarkerEdgeColor',[0 0 1]); 50 | hold off; 51 | xlim([0 sam_ind(end)+1]); ylim([-61 61]); 52 | grid on; 53 | title('$\ell_{2,1}$-SVD', 'interpreter','latex'); 54 | ylabel('DoA [degrees]', 'interpreter','latex'); 55 | xlabel('Sample index', 'interpreter','latex'); 56 | 57 | f_gl1(1) = figure(4); 58 | scatter(sam_ind, gt_ang(1,:)-l1_SVD_ang_est(1,:),'Marker','*','MarkerEdgeColor',[1 0 0]); 59 | hold on; 60 | scatter(sam_ind,gt_ang(2,:)-l1_SVD_ang_est(2,:),'Marker','*','MarkerEdgeColor',[0 0 1]); 61 | grid on; 62 | title('$\ell_{2,1}$-SVD errors', 'interpreter','latex'); 63 | ylabel('DoA [degrees]', 'interpreter','latex'); 64 | xlabel('Sample index', 'interpreter','latex'); 65 | 66 | sq_dif = abs(gt_ang - l1_SVD_ang_est).^2; 67 | RMSE_l1_SVD = sqrt(sum(sq_dif(:))/length(sam_ind)/2) 68 | 69 | -------------------------------------------------------------------------------- /MATLAB/plot_experiment6.m: -------------------------------------------------------------------------------- 1 | % Plot the RMSE results for Experiment 6 2 | % Author: Georgios K. Papageorgiou 3 | % Date: 08/04/2021 - RQ 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | 6 | % clear all; 7 | close all; 8 | % Load the results 9 | T = 1000; 10 | rho_vec = 0:0.1:1; 11 | % Load the MUSIC,R-MUSIC, CRLB results 12 | File = fullfile(save_path,'RMSE_K2_offgrid_ang_fixed_min10dBSNR_T1000_vsrho.mat'); 13 | load(File); 14 | 15 | % Load the CNN results 16 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 17 | 'DoA_Estimation_underdetermined\ComparisonRESULTS\RMSE_CNN_K2_fixed_offgrid_ang3coma8_min10dBSNR_T1000_vsrho_lrRoP_0_7.h5'); 18 | RMSE_CNN = double(h5read(filename, '/CNN_RMSE')); 19 | 20 | % Load the l1-SVD results 21 | filename2 = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\DoA DATA\DoA_DATA_JOURNALS',... 22 | 'TEST_DATA1K_3D_16ULA_K2_fixed_ang_sep3coma8_min10dBSNR_T1000_vsrho.h5'); 23 | RMSE_l1_SVD = double(h5read(filename2, '/RMSE_l1SVD')); 24 | RMSE_UnESPRIT = double(h5read(filename2, '/RMSE_UnESPRIT')); 25 | 26 | %% 27 | % New Color Options 28 | orange = [0.8500, 0.3250, 0.0980]; 29 | gold_yellow = [0.9290, 0.6940, 0.1250]; 30 | new_green = [0.4660, 0.6740, 0.1880]; 31 | 32 | f=figure(1); 33 | plot(rho_vec,RMSE_sam,'^--','Color',orange); 34 | hold on; 35 | plot(rho_vec,RMSE_sam_rm,'o-.','Color', gold_yellow); 36 | plot(rho_vec,RMSE_sam_esp,'+--','Color','r'); 37 | plot(rho_vec,RMSE_UnESPRIT,'s-.','Color','g'); 38 | plot(rho_vec,RMSE_l1_SVD,'*--','Color','m'); 39 | % plot(SNR_vec,RMSE_MLP,'x--','Color','c'); 40 | plot(rho_vec,RMSE_CNN,'d--','Color','b'); 41 | plot(rho_vec, CRLB,'.-','Color','k'); 42 | hold off; 43 | set(gca, 'YScale', 'log'); 44 | legend('MUSIC', 'R-MUSIC','ESPRIT','UnESPRIT','$\ell_{2,1}$-SVD','CNN','CRLB',... 45 | 'interpreter','latex','location','northwest'); 46 | title(['DoA-estimation of K=2 sources from $T=$',num2str(T), ' snapshots'], 'interpreter','latex'); 47 | ylabel('RMSE [degrees]', 'interpreter','latex'); 48 | xlabel('Correlation coefficient $\rho$', 'interpreter','latex'); 49 | grid on; 50 | -------------------------------------------------------------------------------- /MATLAB/plot_experiment7B_SNR0dB.m: -------------------------------------------------------------------------------- 1 | % Plot the results for Exp. 5B with Delta \theta =4 at -10 dB SNR T=1000 2 | 3 | clear all; 4 | close all; 5 | % Load the CNN results 6 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 7 | 'DoA_Estimation_underdetermined\ComparisonRESULTS\Slide_ang_sep10_K1to3_0dB_T1000_CNN_RQ.h5'); 8 | gt_ang1 = h5read(filename, '/GT_angles1'); 9 | CNN_pred1 = double(h5read(filename, '/CNN_pred_angles1')); 10 | sam_ind1 = 1:length(gt_ang1); 11 | 12 | gt_ang2 = h5read(filename, '/GT_angles2'); 13 | CNN_pred2 = double(h5read(filename, '/CNN_pred_angles2')); 14 | sam_ind2 = 1:length(gt_ang2); 15 | 16 | gt_ang3 = h5read(filename, '/GT_angles3'); 17 | CNN_pred3 = double(h5read(filename, '/CNN_pred_angles3')); 18 | sam_ind3 = 1:length(gt_ang3); 19 | 20 | % Manually correcting these values for display purposes only 21 | % K=1 22 | FN_ind1 = gt_ang1(27); 23 | 24 | % K=2 25 | CNN_pred2(:,109) = flip(CNN_pred2(:,109)); 26 | FN_ind2 = [gt_ang2(2,105) gt_ang2(1,109)]; 27 | 28 | % K=3 29 | CNN_pred3(3,16) = CNN_pred3(2,16); 30 | CNN_pred3(2,16) = NaN; 31 | FN_ind3 = gt_ang3(2,16); 32 | 33 | figure(1); 34 | plot(sam_ind1, gt_ang1,'Color','#0d47a1'); 35 | hold on; 36 | scatter(sam_ind1, CNN_pred1(1,:),'Marker','d','MarkerEdgeColor','#9fa8da'); 37 | scatter(27, FN_ind1,'Marker','+','MarkerEdgeColor','#9c27b0'); 38 | scatter(36, CNN_pred1(2,36),'Marker','d','MarkerEdgeColor','k'); 39 | hold off; 40 | xlim([0 sam_ind1(end)+1]); 41 | ylim([-61 61]); 42 | legend('$\theta_1$', '$\hat{\theta}_1$','FN','FP',... 43 | 'interpreter','latex','location','northwest') 44 | grid on; 45 | ylabel('DoA [degrees]', 'interpreter','latex'); 46 | xlabel('Sample index', 'interpreter','latex'); 47 | 48 | figure(2); 49 | plot(sam_ind2, gt_ang2(1,:),'Color','#0d47a1'); 50 | hold on; 51 | plot(sam_ind2, gt_ang2(2,:),'Color','#c62828'); 52 | scatter(sam_ind2, CNN_pred2(1,:),'Marker','d','MarkerEdgeColor','#9fa8da'); 53 | scatter(sam_ind2, CNN_pred2(2,:),'Marker','d','MarkerEdgeColor','#ef9a9a'); 54 | scatter(105, FN_ind2(1),'Marker','+','MarkerEdgeColor','#9c27b0'); 55 | scatter(109, FN_ind2(2),'Marker','+','MarkerEdgeColor','#9c27b0'); 56 | hold off; 57 | xlim([0 sam_ind2(end)+1]); 58 | ylim([-61 61]); 59 | legend('$\theta_1$', '$\theta_2$',... 60 | '$\hat{\theta}_1$', '$\hat{\theta}_2$','FN',... 61 | 'interpreter','latex','location','northwest'); 62 | grid on; 63 | ylabel('DoA [degrees]', 'interpreter','latex'); 64 | xlabel('Sample index', 'interpreter','latex'); 65 | 66 | figure(3); 67 | plot(sam_ind3, gt_ang3(1,:),'Color','#0d47a1'); 68 | hold on; 69 | plot(sam_ind3, gt_ang3(2,:),'Color','#c62828'); 70 | plot(sam_ind3, gt_ang3(3,:),'Color','#689f38'); 71 | scatter(sam_ind3, CNN_pred3(1,:),'Marker','d','MarkerEdgeColor','#9fa8da'); 72 | scatter(sam_ind3, CNN_pred3(2,:),'Marker','d','MarkerEdgeColor','#ef9a9a'); 73 | scatter(sam_ind3, CNN_pred3(3,:),'Marker','d','MarkerEdgeColor','#c5e1a5'); 74 | scatter(16, FN_ind3,'Marker','+','MarkerEdgeColor','#9c27b0'); 75 | hold off; 76 | xlim([0 sam_ind3(end)+1]); 77 | ylim([-61 61]); 78 | legend('$\theta_1$', '$\theta_2$','$\theta_3$',... 79 | '$\hat{\theta}_1$', '$\hat{\theta}_2$','$\hat{\theta}_3$','FN',... 80 | 'interpreter','latex','location','northwest'); 81 | grid on; 82 | ylabel('DoA [degrees]', 'interpreter','latex'); 83 | xlabel('Sample index', 'interpreter','latex'); 84 | -------------------------------------------------------------------------------- /MATLAB/plot_experiment7B_SNRmin10dB.m: -------------------------------------------------------------------------------- 1 | % Plot the results for Exp. 5B with Delta \theta =4 at -10 dB SNR T=1000 2 | 3 | clear all; 4 | close all; 5 | % Load the CNN results 6 | filename = fullfile('C:\Users\geo_p\OneDrive - Heriot-Watt University\HWU2\Code\Python\DoA Estimation',... 7 | 'DoA_Estimation_underdetermined\ComparisonRESULTS\Slide_ang_sep10_K1to3_min10dB_T3000_CNN_RQ.h5'); 8 | gt_ang1 = h5read(filename, '/GT_angles1'); 9 | CNN_pred1 = double(h5read(filename, '/CNN_pred_angles1')); 10 | sam_ind1 = 1:length(gt_ang1); 11 | 12 | gt_ang2 = h5read(filename, '/GT_angles2'); 13 | CNN_pred2 = double(h5read(filename, '/CNN_pred_angles2')); 14 | sam_ind2 = 1:length(gt_ang2); 15 | % Visual correction and marking of FP and FN 16 | CNN_pred2(2,110) = CNN_pred2(1,110); 17 | CNN_pred2(1,110) = NaN; 18 | FN_ind1 = gt_ang2(1,110); 19 | 20 | gt_ang3 = h5read(filename, '/GT_angles3'); 21 | CNN_pred3 = double(h5read(filename, '/CNN_pred_angles3')); 22 | sam_ind3 = 1:length(gt_ang3); 23 | 24 | FN_ind3 = [15, 46, 99]; 25 | CNN_pred3(3,FN_ind3(2)) = CNN_pred3(2,FN_ind3(2)); 26 | CNN_pred3(2,FN_ind3(2)) = NaN; 27 | CNN_pred3(3,FN_ind3(3)) = CNN_pred3(2,FN_ind3(3)); 28 | CNN_pred3(2,FN_ind3(3)) = CNN_pred3(1,FN_ind3(3)); 29 | CNN_pred3(1,FN_ind3(3)) = NaN; 30 | 31 | figure(1); 32 | plot(sam_ind1, gt_ang1,'Color','#0d47a1'); 33 | hold on; 34 | scatter(sam_ind1, CNN_pred1,'Marker','d','MarkerEdgeColor','#9fa8da'); 35 | hold off; 36 | xlim([0 sam_ind1(end)+1]); 37 | ylim([-61 61]); 38 | legend('$\theta_1$', '$\hat{\theta}_1$', 'interpreter','latex','location','northwest') 39 | grid on; 40 | ylabel('DoA [degrees]', 'interpreter','latex'); 41 | xlabel('Sample index', 'interpreter','latex'); 42 | 43 | figure(2); 44 | plot(sam_ind2, gt_ang2(1,:),'Color','#0d47a1'); 45 | hold on; 46 | plot(sam_ind2, gt_ang2(2,:),'Color','#c62828'); 47 | scatter(sam_ind2, CNN_pred2(1,:),'Marker','d','MarkerEdgeColor','#9fa8da'); 48 | scatter(sam_ind2, CNN_pred2(2,:),'Marker','d','MarkerEdgeColor','#ef9a9a'); 49 | scatter(110, FN_ind1,'Marker','+','MarkerEdgeColor','#9c27b0'); % 1 FN error 50 | hold off; 51 | xlim([0 sam_ind2(end)+1]); 52 | ylim([-61 61]); 53 | legend('$\theta_1$', '$\theta_2$',... 54 | '$\hat{\theta}_1$', '$\hat{\theta}_2$','FN',... 55 | 'interpreter','latex','location','northwest'); 56 | grid on; 57 | ylabel('DoA [degrees]', 'interpreter','latex'); 58 | xlabel('Sample index', 'interpreter','latex'); 59 | 60 | figure(3); 61 | plot(sam_ind3, gt_ang3(1,:),'Color','#0d47a1'); 62 | hold on; 63 | plot(sam_ind3, gt_ang3(2,:),'Color','#c62828'); 64 | plot(sam_ind3, gt_ang3(3,:),'Color','#689f38'); 65 | scatter(sam_ind3, CNN_pred3(1,:),'Marker','d','MarkerEdgeColor','#9fa8da'); 66 | scatter(sam_ind3, CNN_pred3(2,:),'Marker','d','MarkerEdgeColor','#ef9a9a'); 67 | scatter(sam_ind3, CNN_pred3(3,:),'Marker','d','MarkerEdgeColor','#c5e1a5'); 68 | scatter(FN_ind3(1), gt_ang3(3,FN_ind3(1)),'Marker','+','MarkerEdgeColor','#9c27b0'); 69 | scatter(FN_ind3(2), gt_ang3(2,FN_ind3(2)),'Marker','+','MarkerEdgeColor','#9c27b0'); 70 | scatter(FN_ind3(3), gt_ang3(1,FN_ind3(3)),'Marker','+','MarkerEdgeColor','#9c27b0'); 71 | hold off; 72 | xlim([0 sam_ind3(end)+1]); 73 | ylim([-61 61]); 74 | legend('$\theta_1$', '$\theta_2$','$\theta_3$',... 75 | '$\hat{\theta}_1$', '$\hat{\theta}_2$','$\hat{\theta}_3$','FN',... 76 | 'interpreter','latex','location','northwest'); 77 | grid on; 78 | ylabel('DoA [degrees]', 'interpreter','latex'); 79 | xlabel('Sample index', 'interpreter','latex'); 80 | -------------------------------------------------------------------------------- /MATLAB/unit_ESPRIT.m: -------------------------------------------------------------------------------- 1 | % Unitary ESPRIT for DoA estimation (TLS implementation) 2 | function ang = unit_ESPRIT(X,T, ds, K, w) 3 | % ds: missing elements of each sub-array for overlapping arrays 4 | % K: number of sources 5 | N = size(X,1); % number of sensors 6 | Ns = N-ds; 7 | 8 | weights = diag(sqrt([1:w-1 w*ones(1,Ns-2*(w-1)) w-1:-1:1])); % Eq 9.132 in [1] 9 | O = zeros(Ns,ds); 10 | 11 | % Js1 = [weights O]; % don't really need that 12 | J2 = [O weights]; 13 | 14 | % Calculate the Q matrices 15 | QNs = Q_mat(Ns); 16 | QN = Q_mat(N); 17 | Q2T = Q_mat(2*T); 18 | 19 | % The real-valued data matrix 20 | TX = QN'*[X flip(eye(N))*conj(X)*flip(eye(T))]*Q2T; 21 | 22 | % Sample covariance of the real-valued data 23 | Rx_est = TX*TX'/(2*T); 24 | 25 | % Perform the eigendecomposition of Rx_est 26 | % Check for positive semi definite 27 | [eigenvects,sED] = eig((Rx_est+Rx_est')/2); % ensure Hermitian 28 | sED = diag(sED); 29 | [~, ind_max_eig] = maxk(sED,K); 30 | ES = eigenvects(:,ind_max_eig); 31 | 32 | % Calculate the K1, K2 matrices 33 | K_mat = QNs'*J2*QN; 34 | K1 = 2*real(K_mat); 35 | K2 = 2*imag(K_mat); 36 | 37 | TLS1 = K1*ES; % size Ns*K 38 | TLS2 = K2*ES; % size Ns*K 39 | 40 | C = [TLS1';TLS2']*[TLS1 TLS2]; 41 | [U,~,~] = svd(C); % C is 2*D x 2*D 42 | V12 = U(1:K,K+1:2*K); % D x D 43 | V22 = U(K+1:2*K,K+1:2*K); % D x D 44 | psi = -V12/V22; % Eq. (9.122) in [1] 45 | psieig = real(eig(psi)); 46 | % Extract angle information estimated from two subarrays based on the 47 | % distance of the phase center between subarrays. 48 | psi = 2*atan(psieig)/pi/ds; 49 | ang = sort(asind(psi)); 50 | % 51 | % doas = 1/ds*angle(psieig); 52 | % 53 | % %Convert estimated angle in sin-space to degrees. This method is valid for 54 | % %ULA only. 55 | % 56 | % u = doas/(pi); 57 | % % check whether all elements of u are within [-1,1] 58 | % idx = find(abs(u)<=1); 59 | % if length(idx) prob).astype(int) 126 | Dsz = log.shape[0] 127 | KMat = log.sum(axis=1) 128 | Kmax = max(KMat) 129 | Corp = sum(KMat==K)*100/Dsz 130 | Fap = sum(KMat>K)*100/Dsz 131 | Mdp = sum(KMat= prob).astype(int) 185 | Dsz = log.shape[0] 186 | KMat = log.sum(axis=1) 187 | Kmax = max(KMat) 188 | # probability *% 189 | Corp = sum(KMat==K)*100/Dsz 190 | Fap = sum(KMat>K)*100/Dsz 191 | Mdp = sum(KMath: 343 | h=short 344 | return h 345 | 346 | def Hausdorffdist_1D(A,B): 347 | d = max(Hausdorffdirectdist_1D(A,B), Hausdorffdirectdist_1D(B,A)) 348 | return d 349 | 350 | def Hausdorffdist_1D_set(A,B): 351 | dim = A.shape[0] 352 | dis = 0 353 | h = 0 354 | for i in range(dim): 355 | d = Hausdorffdist_1D(A[i],B[i]) 356 | dis = dis + d 357 | if d>h: 358 | h = d 359 | mean_H = dis/dim 360 | return mean_H, h 361 | 362 | # Function that removes NaNs in the angles (due to single source - GT) 363 | def remove_nans(y): 364 | data_size = y.shape[0] 365 | y_NOnans =[] 366 | for n in range(data_size): 367 | log = np.isnan(y[n]) 368 | val = y[n][np.logical_not(log)] 369 | y_NOnans.append(val) 370 | return y_NOnans 371 | 372 | 373 | # In[26]: 374 | 375 | 376 | A_sam_thresh1_noNans = np.array(remove_nans(A_sam_thresh1)) 377 | A_sam_thresh2_noNans = np.array(remove_nans(A_sam_thresh2)) 378 | A_sam_thresh3_noNans = np.array(remove_nans(A_sam_thresh3)) 379 | 380 | 381 | # In[27]: 382 | 383 | 384 | mean_H1, max_H1 = Hausdorffdist_1D_set(A_sam_thresh1_noNans,B1) 385 | mean_H1 = round(mean_H1,2) 386 | print(mean_H1) 387 | print(max_H1) 388 | 389 | 390 | # In[28]: 391 | 392 | 393 | mean_H2, max_H2 = Hausdorffdist_1D_set(A_sam_thresh2_noNans,B2) 394 | mean_H2 = round(mean_H2,2) 395 | print(mean_H2) 396 | print(max_H2) 397 | 398 | 399 | # In[29]: 400 | 401 | 402 | mean_H3, max_H3 = Hausdorffdist_1D_set(A_sam_thresh3_noNans,B3) 403 | mean_H3 = round(mean_H3,2) 404 | print(mean_H3) 405 | print(max_H3) 406 | 407 | 408 | # In[30]: 409 | 410 | 411 | KMat12 = np.append(KMat1,KMat2) 412 | KMat = np.append(KMat12,KMat3) 413 | GT12 = np.append(K1*np.ones((n_test,1)), K2*np.ones((n_test,1))) 414 | GT = np.append(GT12, K3*np.ones((n_test,1))) 415 | 416 | 417 | # In[31]: 418 | 419 | 420 | CM = confusion_matrix(GT,KMat,normalize='true') 421 | print(CM) 422 | 423 | 424 | # In[34]: 425 | 426 | 427 | Table_conf_lev = [prob1, prob2, prob3] 428 | print(Table_conf_lev) 429 | 430 | 431 | # In[35]: 432 | 433 | 434 | df_cm = pd.DataFrame(CM*100, range(min(KMat),max(KMat)+1), range(min(KMat),max(KMat)+1)) 435 | f = plt.figure(figsize=(7,4)) 436 | sn.set(font_scale=1.4) # for label size 437 | sn.heatmap(df_cm, annot=True, annot_kws={"size": 16}, fmt=".2f", cmap='Blues') # font size 438 | plt.xlabel('Predicted K') 439 | plt.ylabel('True K') 440 | plt.show() 441 | f.savefig("Exper6_conf_mat_0dB_RQ.eps", dpi=1200, bbox_inches='tight') 442 | 443 | 444 | # In[ ]: 445 | 446 | 447 | 448 | 449 | -------------------------------------------------------------------------------- /Python_CNN/CNN_testing_Exp7A_allSNR_test_min10dB.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # In[1]: 5 | 6 | 7 | import h5py 8 | from sklearn.model_selection import train_test_split 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from keras import optimizers 12 | from keras.models import Sequential 13 | from keras.layers import Dense, Conv2D, MaxPooling2D, Flatten, Dropout, BatchNormalization, ReLU, Softmax 14 | from keras.regularizers import l2, l1 15 | from keras.initializers import glorot_normal 16 | from sklearn.preprocessing import MultiLabelBinarizer 17 | from keras.models import load_model 18 | from sklearn.metrics import mean_squared_error, confusion_matrix 19 | import pandas as pd 20 | import math 21 | import tensorflow as tf 22 | from tensorflow import keras 23 | import seaborn as sn 24 | 25 | 26 | # In[2]: 27 | 28 | 29 | # New model trained in the low-SNR regime - 25/09/2020 30 | # model_CNN = load_model('Model_CNN_DoA_N16_K1to3_res1_min15to0dBSNR_Kunknown_bs128_adam_lr0_002.h5') 31 | # model_CNN = load_model('Model_CNN_DoA_N16_K1to3_res1_min15to0dBSNR_Kunknown_adam_bs64_lr1emin3.h5') # best result so far 32 | model_CNN = load_model('Model_CNN_DoA_N16_K1to3_res1_min15to0dBSNR_Kunknown_adam_bs32_lr1emin3.h5') 33 | 34 | 35 | # In[3]: 36 | 37 | 38 | res = 1 39 | An_max = 60 40 | An_min = -60 41 | v = np.arange(An_min, An_max+res,res) 42 | 43 | 44 | # In[4]: 45 | 46 | 47 | # Load the Test Data for Experiment 1A 48 | filename1 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TEST_DATA_16ULA_K1_min10dBSNR_T3000_3D_fixedang_offgrid.h5' 49 | f1 = h5py.File(filename1, 'r') 50 | GT_angles1 = np.array(f1['angles']) 51 | Ry_sam_test1 = np.array(f1['sam']) 52 | Ry_the_test1 = np.array(f1['the']) 53 | K1 = 1 54 | [n_test,chan,N,M]=Ry_sam_test1.shape 55 | X_test_data_sam1 = Ry_sam_test1.swapaxes(1,3) 56 | X_test_data_the1 = Ry_the_test1.swapaxes(1,3) 57 | 58 | 59 | # In[5]: 60 | 61 | 62 | X_test_data_sam1.shape 63 | 64 | 65 | # In[6]: 66 | 67 | 68 | # Load the Test Data for Experiment 1A 69 | filename2 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TEST_DATA_16ULA_K2_min10dBSNR_T3000_3D_fixedang_offgrid.h5' 70 | f2 = h5py.File(filename2, 'r') 71 | GT_angles2 = np.array(f2['angles']) 72 | Ry_sam_test2 = np.array(f2['sam']) 73 | Ry_the_test2 = np.array(f2['the']) 74 | K2 = 2 75 | X_test_data_sam2 = Ry_sam_test2.swapaxes(1,3) 76 | X_test_data_the2 = Ry_the_test2.swapaxes(1,3) 77 | 78 | 79 | # In[7]: 80 | 81 | 82 | # Load the Test Data for Experiment 1A 83 | filename3 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TEST_DATA_16ULA_K3_min10dBSNR_T3000_3D_fixedang_offgrid.h5' 84 | f3 = h5py.File(filename3, 'r') 85 | GT_angles3 = np.array(f3['angles']) 86 | Ry_sam_test3 = np.array(f3['sam']) 87 | Ry_the_test3 = np.array(f3['the']) 88 | K3 = 3 89 | X_test_data_sam3 = Ry_sam_test3.swapaxes(1,3) 90 | X_test_data_the3 = Ry_the_test3.swapaxes(1,3) 91 | 92 | 93 | # In[8]: 94 | 95 | 96 | # The true set 97 | B1 = np.tile(GT_angles1,(n_test,1)) 98 | B2 = np.tile(GT_angles2,(n_test,1)) 99 | B3 = np.tile(GT_angles3,(n_test,1)) 100 | 101 | 102 | # In[9]: 103 | 104 | 105 | # Estimation with the sample covariance matrix K=1 106 | with tf.device('/cpu:0'): 107 | x_pred_sam1 = model_CNN.predict(X_test_data_sam1) 108 | x_ind_K_sam1 = np.argpartition(x_pred_sam1, -K1, axis=1)[:, -K1:] 109 | A_sam1 = np.sort(v[x_ind_K_sam1]) 110 | 111 | # Estimation with the true covariance matrix K=1 112 | with tf.device('/cpu:0'): 113 | x_pred_the1 = model_CNN.predict(X_test_data_the1) 114 | x_ind_K_the1 = np.argpartition(x_pred_the1, -K1, axis=1)[:, -K1:] 115 | A_the1 = np.sort(v[x_ind_K_the1]) 116 | 117 | 118 | # In[10]: 119 | 120 | 121 | # Calculate the RMSE [in degrees] 122 | RMSE_sam1 = round(np.sqrt(mean_squared_error(np.sort(A_sam1), np.sort(B1))),4) 123 | # Calculate the RMSE [in degrees] 124 | RMSE_the1 = round(np.sqrt(mean_squared_error(np.sort(A_the1), np.sort(B1))),4) 125 | print('The RMSE with the true cov. mat. is ',RMSE_the1,' and with the sample is ',RMSE_sam1, 'for K=1') 126 | 127 | 128 | # In[11]: 129 | 130 | 131 | # Estimation with the sample covariance matrix K=2 132 | with tf.device('/cpu:0'): 133 | x_pred_sam2 = model_CNN.predict(X_test_data_sam2) 134 | x_ind_K_sam2 = np.argpartition(x_pred_sam2, -K2, axis=1)[:, -K2:] 135 | A_sam2 = np.sort(v[x_ind_K_sam2]) 136 | 137 | # Estimation with the true covariance matrix K=1 138 | with tf.device('/cpu:0'): 139 | x_pred_the2 = model_CNN.predict(X_test_data_the2) 140 | x_ind_K_the2 = np.argpartition(x_pred_the2, -K2, axis=1)[:, -K2:] 141 | A_the2 = np.sort(v[x_ind_K_the2]) 142 | 143 | 144 | # In[12]: 145 | 146 | 147 | # Calculate the RMSE [in degrees] 148 | RMSE_sam2 = round(np.sqrt(mean_squared_error(np.sort(A_sam2), np.sort(B2))),4) 149 | # Calculate the RMSE [in degrees] 150 | RMSE_the2 = round(np.sqrt(mean_squared_error(np.sort(A_the2), np.sort(B2))),4) 151 | print('The RMSE with the true cov. mat. is ',RMSE_the2,' and with the sample is ',RMSE_sam2, 'for K=2') 152 | 153 | 154 | # In[13]: 155 | 156 | 157 | # Estimation with the sample covariance matrix K=2 158 | with tf.device('/cpu:0'): 159 | x_pred_sam3 = model_CNN.predict(X_test_data_sam3) 160 | x_ind_K_sam3 = np.argpartition(x_pred_sam3, -K3, axis=1)[:, -K3:] 161 | A_sam3 = np.sort(v[x_ind_K_sam3]) 162 | 163 | # Estimation with the true covariance matrix K=1 164 | with tf.device('/cpu:0'): 165 | x_pred_the3 = model_CNN.predict(X_test_data_the3) 166 | x_ind_K_the3 = np.argpartition(x_pred_the3, -K3, axis=1)[:, -K3:] 167 | A_the3 = np.sort(v[x_ind_K_the3]) 168 | 169 | 170 | # In[14]: 171 | 172 | 173 | # Calculate the RMSE [in degrees] 174 | RMSE_sam3 = round(np.sqrt(mean_squared_error(np.sort(A_sam3), np.sort(B3))),4) 175 | # Calculate the RMSE [in degrees] 176 | RMSE_the3 = round(np.sqrt(mean_squared_error(np.sort(A_the3), np.sort(B3))),4) 177 | print('The RMSE with the true cov. mat. is ',RMSE_the3,' and with the sample is ',RMSE_sam3, 'for K=3') 178 | 179 | 180 | # In[15]: 181 | 182 | 183 | # Check here the threshold prediction without assuming knowledge of K, which is here used only for the rate calculation 184 | def noK_prediction_slide(x_pred_sam, prob, K, GT_angles): 185 | log = (x_pred_sam >= prob).astype(int) 186 | Dsz = log.shape[0] 187 | KMat = log.sum(axis=1) 188 | Kmax = max(KMat) 189 | # probability *% 190 | Corp = sum(KMat==K)*100/Dsz 191 | Fap = sum(KMat>K)*100/Dsz 192 | Mdp = sum(KMath: 344 | h=short 345 | return h 346 | 347 | def Hausdorffdist_1D(A,B): 348 | d = max(Hausdorffdirectdist_1D(A,B), Hausdorffdirectdist_1D(B,A)) 349 | return d 350 | 351 | def Hausdorffdist_1D_set(A,B): 352 | dim = A.shape[0] 353 | dis = 0 354 | h = 0 355 | for i in range(dim): 356 | d = Hausdorffdist_1D(A[i],B[i]) 357 | dis = dis + d 358 | if d>h: 359 | h = d 360 | mean_H = dis/dim 361 | return mean_H, h 362 | 363 | # Function that removes NaNs in the angles (due to single source - GT) 364 | def remove_nans(y): 365 | data_size = y.shape[0] 366 | y_NOnans =[] 367 | for n in range(data_size): 368 | log = np.isnan(y[n]) 369 | val = y[n][np.logical_not(log)] 370 | y_NOnans.append(val) 371 | return y_NOnans 372 | 373 | 374 | # In[59]: 375 | 376 | 377 | A_sam_thresh1_noNans = np.array(remove_nans(A_sam_thresh1)) 378 | A_sam_thresh2_noNans = np.array(remove_nans(A_sam_thresh2)) 379 | A_sam_thresh3_noNans = np.array(remove_nans(A_sam_thresh3)) 380 | 381 | 382 | # In[60]: 383 | 384 | 385 | mean_H1, max_H1 = Hausdorffdist_1D_set(A_sam_thresh1_noNans,B1) 386 | mean_H1 = round(mean_H1,2) 387 | print(mean_H1) 388 | print(max_H1) 389 | 390 | 391 | # In[61]: 392 | 393 | 394 | mean_H2, max_H2 = Hausdorffdist_1D_set(A_sam_thresh2_noNans,B2) 395 | mean_H2 = round(mean_H2,2) 396 | print(mean_H2) 397 | print(max_H2) 398 | 399 | 400 | # In[62]: 401 | 402 | 403 | mean_H3, max_H3 = Hausdorffdist_1D_set(A_sam_thresh3_noNans,B3) 404 | mean_H3 = round(mean_H3,2) 405 | print(mean_H3) 406 | print(max_H3) 407 | 408 | 409 | # In[63]: 410 | 411 | 412 | KMat12 = np.append(KMat1,KMat2) 413 | KMat = np.append(KMat12,KMat3) 414 | GT12 = np.append(K1*np.ones((n_test,1)), K2*np.ones((n_test,1))) 415 | GT = np.append(GT12, K3*np.ones((n_test,1))) 416 | 417 | 418 | # In[64]: 419 | 420 | 421 | CM = confusion_matrix(GT,KMat,normalize='true') 422 | print(CM) 423 | 424 | 425 | # In[67]: 426 | 427 | 428 | p_conf_lev = [prob1, prob2, prob3] 429 | print(p_conf_lev) 430 | 431 | 432 | # In[68]: 433 | 434 | 435 | df_cm = pd.DataFrame(CM*100, range(min(KMat),max(KMat)+1), range(min(KMat),max(KMat)+1)) 436 | f = plt.figure(figsize=(7,4)) 437 | sn.set(font_scale=1.4) # for label size 438 | sn.heatmap(df_cm, annot=True, annot_kws={"size": 16}, fmt=".2f", cmap='Blues') # font size 439 | plt.xlabel('Predicted K') 440 | plt.ylabel('True K') 441 | plt.show() 442 | f.savefig("Exper6_conf_mat_min10dB_RQ.eps", dpi=1200, bbox_inches='tight') 443 | 444 | 445 | # In[ ]: 446 | 447 | 448 | 449 | 450 | -------------------------------------------------------------------------------- /Python_CNN/CNN_testing_Exp7B_0dB_unknownK.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # In[1]: 5 | 6 | 7 | import h5py 8 | from sklearn.model_selection import train_test_split 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from keras import optimizers 12 | from keras.models import Sequential 13 | from keras.layers import Dense, Conv2D, MaxPooling2D, Flatten, Dropout, BatchNormalization, ReLU, Softmax 14 | from keras.regularizers import l2, l1 15 | from keras.initializers import glorot_normal 16 | from sklearn.preprocessing import MultiLabelBinarizer 17 | from keras.models import load_model 18 | from sklearn.metrics import mean_squared_error 19 | import pandas as pd 20 | import math 21 | import tensorflow as tf 22 | from tensorflow import keras 23 | 24 | 25 | # In[2]: 26 | 27 | 28 | # New model with low-SNR training - 25/09/2020 29 | model_CNN = load_model('Model_CNN_DoA_class_Data_N16_K1to3_res1_0dBSNR_v2.h5') 30 | # model_CNN = load_model('Model_CNN_DoA_N16_K1to3_res1_min15to0dBSNR_Kunknown_adam_bs64_lr1emin3.h5') 31 | 32 | 33 | # In[3]: 34 | 35 | 36 | res = 1 37 | An_max = 60 38 | An_min = -60 39 | v = np.arange(An_min, An_max+res,res) 40 | 41 | 42 | # In[4]: 43 | 44 | 45 | # Load the Test Data for the Experiment 46 | # K=1 - 120 examples 47 | filename1 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TEST_DATA_16ULA_K1_0dBSNR_T1000_3D_slideang_offgrid_ang_sep10.h5' 48 | f1 = h5py.File(filename1, 'r') 49 | GT_angles1 = np.array(f1['angles']) 50 | Ry_the_test1 = np.array(f1['the']) 51 | Ry_sam_test1 = np.array(f1['sam']) 52 | Nsim1 = GT_angles1.shape[0] 53 | # K=2 - 110 examples 54 | filename2 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TEST_DATA_16ULA_K2_0dBSNR_T1000_3D_slideang_offgrid_ang_sep10.h5' 55 | f2 = h5py.File(filename2, 'r') 56 | GT_angles2 = np.array(f2['angles']) 57 | Ry_the_test2 = np.array(f2['the']) 58 | Ry_sam_test2 = np.array(f2['sam']) 59 | Nsim2 = GT_angles2.shape[0] 60 | # K=3 - 110 examples 61 | filename3 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TEST_DATA_16ULA_K3_0dBSNR_T1000_3D_slideang_offgrid_ang_sep10.h5' 62 | f3 = h5py.File(filename3, 'r') 63 | GT_angles3 = np.array(f3['angles']) 64 | Ry_the_test3 = np.array(f3['the']) 65 | Ry_sam_test3 = np.array(f3['sam']) 66 | Nsim3 = GT_angles3.shape[0] 67 | 68 | 69 | # In[5]: 70 | 71 | 72 | Ry_sam_test1.shape 73 | 74 | 75 | # In[6]: 76 | 77 | 78 | # First permute the tensor and then predict 79 | [n_test,dim,N,M]=Ry_sam_test1.shape 80 | X_test_data_sam1 = Ry_sam_test1.swapaxes(1,3) 81 | X_test_data_sam2 = Ry_sam_test2.swapaxes(1,3) 82 | X_test_data_sam3 = Ry_sam_test3.swapaxes(1,3) 83 | 84 | X_test_data_the1 = Ry_the_test1.swapaxes(1,3) 85 | X_test_data_the2 = Ry_the_test2.swapaxes(1,3) 86 | X_test_data_the3 = Ry_the_test3.swapaxes(1,3) 87 | 88 | X_test_data_sam1.shape 89 | 90 | 91 | # In[7]: 92 | 93 | 94 | # K =1 with Sample Covariance Estimate 95 | B1 = GT_angles1 96 | K = 1 97 | # Run inference on CPU 98 | with tf.device('/cpu:0'): 99 | # Estimation with the covariance matrix 100 | x_pred_sam1 = model_CNN.predict(X_test_data_sam1) 101 | # Classify K sources with maximum probability - Scenario 1 102 | x_ind_K_sam1 = np.argpartition(x_pred_sam1, -K, axis=1)[:, -K:] 103 | A_sam1 = np.sort(v[x_ind_K_sam1]) 104 | # Calculate the RMSE [in degrees] 105 | RMSE_sam1 = round(np.sqrt(mean_squared_error(np.sort(A_sam1), np.sort(B1))),4) 106 | print(RMSE_sam1) 107 | 108 | 109 | # In[8]: 110 | 111 | 112 | # K =1 with True Covariance Matrix 113 | K = 1 114 | # Run inference on CPU 115 | with tf.device('/cpu:0'): 116 | # Estimation with the covariance matrix 117 | x_pred_the1 = model_CNN.predict(X_test_data_the1) 118 | # Classify K sources with maximum probability - Scenario 1 119 | x_ind_K_the1 = np.argpartition(x_pred_the1, -K, axis=1)[:, -K:] 120 | A_the1 = np.sort(v[x_ind_K_the1]) 121 | # Calculate the RMSE [in degrees] 122 | RMSE_the1 = round(np.sqrt(mean_squared_error(np.sort(A_the1), np.sort(B1))),4) 123 | print(RMSE_the1) 124 | 125 | 126 | # In[9]: 127 | 128 | 129 | # K =2 130 | B2 = GT_angles2 131 | K = 2 132 | # Run inference on CPU 133 | with tf.device('/cpu:0'): 134 | # Estimation with the covariance matrix 135 | x_pred_sam2 = model_CNN.predict(X_test_data_sam2) 136 | # Classify K sources with maximum probability - Scenario 1 137 | x_ind_K_sam2 = np.argpartition(x_pred_sam2, -K, axis=1)[:, -K:] 138 | A_sam2 = np.sort(v[x_ind_K_sam2]) 139 | # Calculate the RMSE [in degrees] 140 | RMSE_sam2 = round(np.sqrt(mean_squared_error(np.sort(A_sam2), np.sort(B2))),4) 141 | print(RMSE_sam2) 142 | 143 | 144 | # In[10]: 145 | 146 | 147 | # K =2 148 | K = 2 149 | # Run inference on CPU 150 | with tf.device('/cpu:0'): 151 | # Estimation with the covariance matrix 152 | x_pred_the2 = model_CNN.predict(X_test_data_the2) 153 | # Classify K sources with maximum probability - Scenario 1 154 | x_ind_K_the2 = np.argpartition(x_pred_the2, -K, axis=1)[:, -K:] 155 | A_the2 = np.sort(v[x_ind_K_the2]) 156 | # Calculate the RMSE [in degrees] 157 | RMSE_the2 = round(np.sqrt(mean_squared_error(np.sort(A_the2), np.sort(B2))),4) 158 | print(RMSE_the2) 159 | 160 | 161 | # In[11]: 162 | 163 | 164 | # K =1 165 | B3 = GT_angles3 166 | K = 3 167 | # Run inference on CPU 168 | with tf.device('/cpu:0'): 169 | # Estimation with the covariance matrix 170 | x_pred_sam3 = model_CNN.predict(X_test_data_sam3) 171 | # Classify K sources with maximum probability - Scenario 1 172 | x_ind_K_sam3 = np.argpartition(x_pred_sam3, -K, axis=1)[:, -K:] 173 | A_sam3 = np.sort(v[x_ind_K_sam3]) 174 | # Calculate the RMSE [in degrees] 175 | RMSE_sam3 = round(np.sqrt(mean_squared_error(np.sort(A_sam3), np.sort(B3))),4) 176 | print(RMSE_sam3) 177 | 178 | 179 | # In[12]: 180 | 181 | 182 | # K =3 183 | K = 3 184 | # Run inference on CPU 185 | with tf.device('/cpu:0'): 186 | # Estimation with the covariance matrix 187 | x_pred_the3 = model_CNN.predict(X_test_data_the3) 188 | # Classify K sources with maximum probability - Scenario 1 189 | x_ind_K_the3 = np.argpartition(x_pred_the3, -K, axis=1)[:, -K:] 190 | A_the3 = np.sort(v[x_ind_K_the3]) 191 | # Calculate the RMSE [in degrees] 192 | RMSE_the3 = round(np.sqrt(mean_squared_error(np.sort(A_the3), np.sort(B3))),4) 193 | print(RMSE_the3) 194 | 195 | 196 | # In[13]: 197 | 198 | 199 | # Check here the threshold prediction without assuming knowledge of K, which is here used only for the rate calculation 200 | def noK_prediction_slide(x_pred_sam, prob, K, GT_angles): 201 | log = (x_pred_sam >= prob).astype(int) 202 | Dsz = log.shape[0] 203 | KMat = log.sum(axis=1) 204 | Kmax = max(KMat) 205 | # probability *% 206 | Corp = sum(KMat==K)*100/Dsz 207 | Fap = sum(KMat>K)*100/Dsz 208 | Mdp = sum(KMath: 357 | h=short 358 | return h 359 | 360 | def Hausdorffdist_1D(A,B): 361 | d = max(Hausdorffdirectdist_1D(A,B), Hausdorffdirectdist_1D(B,A)) 362 | return d 363 | 364 | def Hausdorffdist_1D_set(A,B): 365 | dim = A.shape[0] 366 | dis = 0 367 | h = 0 368 | for i in range(dim): 369 | d = Hausdorffdist_1D(A[i],B[i]) 370 | dis = dis + d 371 | if d>h: 372 | h = d 373 | mean_H = dis/dim 374 | return mean_H, h 375 | 376 | # Function that removes NaNs in the angles (due to single source - GT) 377 | def remove_nans(y): 378 | data_size = y.shape[0] 379 | y_NOnans =[] 380 | for n in range(data_size): 381 | log = np.isnan(y[n]) 382 | val = y[n][np.logical_not(log)] 383 | y_NOnans.append(val) 384 | return y_NOnans 385 | 386 | 387 | # In[25]: 388 | 389 | 390 | A_sam_thresh1_noNans = np.array(remove_nans(A_sam_thresh1)) 391 | A_sam_thresh2_noNans = np.array(remove_nans(A_sam_thresh2)) 392 | A_sam_thresh3_noNans = np.array(remove_nans(A_sam_thresh3)) 393 | 394 | 395 | # In[26]: 396 | 397 | 398 | mean_H1, max_H1 = Hausdorffdist_1D_set(A_sam_thresh1_noNans,B1) 399 | mean_H1 = round(mean_H1,2) 400 | print(mean_H1) 401 | print(max_H1) 402 | 403 | 404 | # In[27]: 405 | 406 | 407 | mean_H2, max_H2 = Hausdorffdist_1D_set(A_sam_thresh2_noNans,B2) 408 | mean_H2 = round(mean_H2,2) 409 | print(mean_H2) 410 | print(max_H2) 411 | 412 | 413 | # In[28]: 414 | 415 | 416 | mean_H3, max_H3 = Hausdorffdist_1D_set(A_sam_thresh3_noNans,B3) 417 | mean_H3 = round(mean_H3,2) 418 | print(mean_H3) 419 | print(max_H3) 420 | 421 | 422 | # In[29]: 423 | 424 | 425 | # Save the results and plot them in MATLAB 426 | filename_s = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/HWU2/Code/Python/DoA Estimation/DoA_Estimation_underdetermined/ComparisonRESULTS/Slide_ang_sep10_K1to3_0dB_T1000_CNN_RQ.h5' 427 | hfs = h5py.File(filename_s, 'w') 428 | hfs.create_dataset('GT_angles1', data=B1) 429 | hfs.create_dataset('GT_angles2', data=B2) 430 | hfs.create_dataset('GT_angles3', data=B3) 431 | hfs.create_dataset('Conf_level1', data=prob1) 432 | hfs.create_dataset('Conf_level2', data=prob2) 433 | hfs.create_dataset('Conf_level3', data=prob3) 434 | hfs.create_dataset('Mean_Hausdorff1', data=mean_H1) 435 | hfs.create_dataset('Mean_Hausdorff2', data=mean_H2) 436 | hfs.create_dataset('Mean_Hausdorff3', data=mean_H3) 437 | hfs.create_dataset('Max_Hausdorff1', data=max_H1) 438 | hfs.create_dataset('Max_Hausdorff2', data=max_H2) 439 | hfs.create_dataset('Max_Hausdorff3', data=max_H3) 440 | hfs.create_dataset('CNN_pred_angles1', data=A_sam_thresh1) 441 | hfs.create_dataset('CNN_pred_angles2', data=A_sam_thresh2) 442 | hfs.create_dataset('CNN_pred_angles3', data=A_sam_thresh3) 443 | hfs.close() 444 | 445 | 446 | # In[40]: 447 | 448 | 449 | B1[0] 450 | 451 | -------------------------------------------------------------------------------- /Python_CNN/CNN_training_allSNR_multipleK_unknownK.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # In[1]: 5 | 6 | 7 | import h5py 8 | from sklearn.model_selection import train_test_split 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from keras import optimizers 12 | from keras.models import Sequential 13 | from keras.layers import Dense, Conv2D, MaxPooling2D, Flatten, Dropout, BatchNormalization, ReLU, Softmax, LeakyReLU 14 | from keras.regularizers import l2, l1 15 | from keras.initializers import glorot_normal 16 | from sklearn.preprocessing import MultiLabelBinarizer, MinMaxScaler 17 | from keras.models import load_model 18 | from sklearn.metrics import mean_squared_error 19 | import pandas as pd 20 | import math 21 | import tensorflow as tf 22 | from tensorflow import keras 23 | #from tensorflow.keras.optimizers import Adam 24 | from keras.callbacks import LearningRateScheduler, ReduceLROnPlateau 25 | 26 | 27 | # In[2]: 28 | 29 | 30 | # Fix K=1-3 detection of sources - Experiment Part A: 1) 31 | filename1 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TRAIN_DATA_16ULA_K1to3_min15to0dBSNR_res1_3D.h5' 32 | f1 = h5py.File(filename1, 'r') 33 | angles = np.transpose(np.array(f1['angles'])) 34 | Ry_the = np.array(f1['theor']) 35 | res = 1 36 | 37 | 38 | # In[3]: 39 | 40 | 41 | An_max = 60 42 | An_min = -60 43 | v = np.arange(An_min, An_max+res,res) 44 | print(v) 45 | 46 | 47 | # In[4]: 48 | 49 | 50 | DNN_outp = v.size 51 | print(DNN_outp) 52 | 53 | 54 | # In[5]: 55 | 56 | 57 | angles.shape 58 | 59 | 60 | # In[6]: 61 | 62 | 63 | Ry_the.shape 64 | 65 | 66 | # In[7]: 67 | 68 | 69 | [SNRs, n, chan, M, N] = Ry_the.shape 70 | X_data0=Ry_the.swapaxes(2,4) 71 | X_data0.shape 72 | 73 | 74 | # In[8]: 75 | 76 | 77 | X_data = X_data0.reshape([SNRs*n,N,M,chan]) 78 | X_data.shape 79 | 80 | 81 | # In[9]: 82 | 83 | 84 | # this function performs min-max scaling after fitting to 3D data by reshaping 85 | def min_max_sc_3D(X_data, scaler): 86 | [tr_samp, N, M, chan] = X_data.shape 87 | Data = X_data.reshape([tr_samp,M*N*chan]) 88 | scaler.fit(Data) 89 | X_ = scaler.transform(Data) 90 | X = X_.reshape([tr_samp, N, M, chan]) 91 | return X 92 | 93 | 94 | # In[10]: 95 | 96 | 97 | scaler = MinMaxScaler() 98 | X_data_sc = min_max_sc_3D(X_data, scaler) 99 | X_data_sc.shape 100 | 101 | 102 | # In[9]: 103 | 104 | 105 | # Function that removes NaNs in the angles (due to single source - GT) 106 | def remove_nans(y): 107 | data_size = y.shape[0] 108 | y_NOnans =[] 109 | for n in range(data_size): 110 | log = np.isnan(y[n]) 111 | val = y[n][np.logical_not(log)] 112 | y_NOnans.append(val) 113 | return y_NOnans 114 | 115 | 116 | # In[10]: 117 | 118 | 119 | # Create the multiple labels 120 | Y_Labels0 = remove_nans(angles) 121 | mlb = MultiLabelBinarizer() 122 | yTrain_encoded = mlb.fit_transform(Y_Labels0) 123 | yTrain_encoded.shape 124 | 125 | 126 | # In[11]: 127 | 128 | 129 | Y_Labels = np.tile(yTrain_encoded, reps=(SNRs,1)) 130 | Y_Labels.shape 131 | 132 | 133 | # In[12]: 134 | 135 | 136 | # Split the dataset into training and validation sets 137 | xTrain, xVal, yTrain, yVal = train_test_split(X_data, Y_Labels, test_size=0.1, random_state=42) # checked 138 | 139 | 140 | # In[13]: 141 | 142 | 143 | # Define the model (CNN) for single source localization 144 | input_shape = xTrain.shape[1:] 145 | kern_size1 = 3 146 | kern_size2 = 2 147 | 148 | model = Sequential() # kernel_regularizer=l1(0.00001), 149 | model.add(Conv2D(256, kernel_size=(kern_size1,kern_size1), activation=None, input_shape=input_shape, name="Conv2D_1",padding="valid", strides=(2,2))) 150 | model.add(BatchNormalization(trainable=True)) 151 | model.add(ReLU()) 152 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_2", padding="valid")) 153 | model.add(BatchNormalization(trainable=True)) 154 | model.add(ReLU()) 155 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_3", padding="valid")) 156 | model.add(BatchNormalization(trainable=True)) 157 | model.add(ReLU()) 158 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_4", padding="valid")) 159 | model.add(BatchNormalization(trainable=True)) 160 | model.add(ReLU()) 161 | model.add(Flatten()) 162 | model.add(Dense(4096, activation="relu",name="Dense_Layer1")) 163 | model.add(Dropout(0.3,name="Dropout1")) 164 | model.add(Dense(2048, activation="relu",name="Dense_Layer2")) 165 | model.add(Dropout(0.3,name="Dropout2")) 166 | model.add(Dense(1024, activation="relu",name="Dense_Layer3")) 167 | model.add(Dropout(0.3,name="Dropout3")) 168 | model.add(Dense(DNN_outp, activation="sigmoid", kernel_initializer=glorot_normal(seed=None),name="Classif_Layer")) 169 | model.summary() 170 | 171 | 172 | # In[14]: 173 | 174 | 175 | # Train the model with Adam and Reduce lr on Plateau 176 | # Last best pars is bs=128, rlr 0.7, pat=10, lr=2e-3 16/4/21 19:00 177 | rlr = ReduceLROnPlateau(monitor='val_loss', factor=0.7, patience=10, verbose=1) 178 | cbks = [rlr] 179 | opt = tf.keras.optimizers.Adam(learning_rate=0.001) 180 | model.compile(optimizer=opt, loss='binary_crossentropy', metrics=[tf.keras.metrics.BinaryAccuracy(name="acc")]) 181 | train_history = model.fit(xTrain, yTrain, epochs=200, batch_size=32, shuffle=True, validation_data=(xVal, yVal), callbacks=cbks) 182 | 183 | 184 | # In[15]: 185 | 186 | 187 | model.save('Model_CNN_DoA_N16_K1to3_res1_min15to0dBSNR_Kunknown_adam_bs32_lr1emin3.h5') 188 | 189 | 190 | # In[16]: 191 | 192 | 193 | # summarize history for accuracy 194 | f1 = plt.figure(1) 195 | plt.plot(train_history.history['acc'], label='Training accuracy') 196 | plt.plot(train_history.history['val_acc'], label='Validation accuracy') 197 | #plt.title('model accuracy') 198 | plt.ylabel('Accuracy') 199 | plt.xlabel('Epoch') 200 | plt.legend(['Train', 'Val.'], loc='lower right') 201 | plt.grid() 202 | plt.show() 203 | 204 | # summarize history for loss 205 | f2 = plt.figure(2) 206 | plt.plot(train_history.history['loss'], label='Training loss') 207 | plt.plot(train_history.history['val_loss'], label='Validation loss') 208 | #plt.title('model loss') 209 | plt.ylabel('Loss') 210 | plt.xlabel('Epoch') 211 | plt.legend(['Train', 'Val.'], loc='upper left') 212 | plt.grid() 213 | plt.show() 214 | 215 | 216 | # In[17]: 217 | 218 | 219 | # Save the figures to include them in the paper 220 | f1.savefig("training_acc_mixK_mixSNR_min15to0dB_bs32_lr1emin3.eps", dpi=1200, bbox_inches='tight') 221 | f2.savefig("training_loss_mixK_mixSNR_min15to0dB_bs32_lr1emin3.eps", dpi=1200, bbox_inches='tight') 222 | 223 | 224 | # In[18]: 225 | 226 | 227 | # save the training performance for reporting 228 | f3 = plt.figure(1) 229 | plt.subplot(2,1,1) 230 | plt.plot(train_history.history['acc'], label='Training accuracy') 231 | plt.plot(train_history.history['val_acc'], label='Validation accuracy') 232 | plt.ylabel('Accuracy') 233 | plt.legend(['Train', 'Val.'], loc='lower right') 234 | plt.grid() 235 | plt.subplot(2,1,2) 236 | plt.plot(train_history.history['loss'], label='Training loss') 237 | plt.plot(train_history.history['val_loss'], label='Validation loss') 238 | plt.ylabel('Loss') 239 | plt.xlabel('Epoch') 240 | plt.legend(['Train', 'Val.'], loc='upper right') 241 | plt.grid() 242 | plt.show() 243 | 244 | 245 | # In[19]: 246 | 247 | 248 | # Save the figures to include them in the paper 249 | f3.savefig("training_perf_mixK_mixSNR_min15to0dB_bs32_lr1emin3.eps", dpi=1200, bbox_inches='tight') 250 | 251 | 252 | # In[ ]: 253 | 254 | 255 | 256 | 257 | -------------------------------------------------------------------------------- /Python_CNN/CNN_training_lowSNR_new_training_RQ_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # In[1]: 5 | 6 | 7 | import h5py 8 | from sklearn.model_selection import train_test_split 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from keras import optimizers 12 | from keras.models import Sequential 13 | from keras.layers import Dense, Conv2D, MaxPooling2D, Flatten, Dropout, BatchNormalization, ReLU, Softmax 14 | from keras.regularizers import l2, l1 15 | from keras.initializers import glorot_normal 16 | from sklearn.preprocessing import MultiLabelBinarizer 17 | from keras.models import load_model 18 | from sklearn.metrics import mean_squared_error 19 | import pandas as pd 20 | import math 21 | import tensorflow as tf 22 | from tensorflow import keras 23 | #from tensorflow.keras.optimizers import Adam 24 | from keras.callbacks import LearningRateScheduler, ReduceLROnPlateau 25 | 26 | 27 | # In[2]: 28 | 29 | 30 | # Fix K detection of sources - Experiment Part A: 1) 31 | filename1 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TRAIN_DATA_16ULA_K2_low_SNR_res1_3D.h5' 32 | f1 = h5py.File(filename1, 'r') 33 | angles = np.transpose(np.array(f1['angles'])) 34 | Ry_the = np.array(f1['theor']) 35 | res = 1 36 | K=2 37 | 38 | 39 | # In[3]: 40 | 41 | 42 | An_max = np.max(angles) 43 | An_min = np.min(angles) 44 | v = np.arange(An_min, An_max+res,res) 45 | print(v) 46 | 47 | 48 | # In[4]: 49 | 50 | 51 | DNN_outp = v.size 52 | print(DNN_outp) 53 | 54 | 55 | # In[5]: 56 | 57 | 58 | angles.shape 59 | 60 | 61 | # In[6]: 62 | 63 | 64 | Ry_the.shape 65 | 66 | 67 | # In[7]: 68 | 69 | 70 | [ SNRs, n, chan, M, N] = Ry_the.shape 71 | 72 | 73 | # In[8]: 74 | 75 | 76 | X_data0=Ry_the.swapaxes(2,4) 77 | X_data0.shape 78 | 79 | 80 | # In[9]: 81 | 82 | 83 | X_data = X_data0.reshape([SNRs*n,N,M,chan]) 84 | X_data.shape 85 | 86 | 87 | # In[10]: 88 | 89 | 90 | mlb = MultiLabelBinarizer() 91 | yTrain_encoded = mlb.fit_transform(angles) 92 | 93 | 94 | # In[11]: 95 | 96 | 97 | yTrain_encoded[1] 98 | 99 | 100 | # In[12]: 101 | 102 | 103 | Y_Labels = np.tile(yTrain_encoded, reps=(SNRs,1)) 104 | #Y_Labels = yTrain_encoded 105 | Y_Labels.shape 106 | 107 | 108 | # In[13]: 109 | 110 | 111 | # Split the dataset into training and validation sets 112 | xTrain, xVal, yTrain, yVal = train_test_split(X_data, Y_Labels, test_size=0.1, random_state=42) # checked 113 | 114 | 115 | # In[14]: 116 | 117 | 118 | # Define the model (CNN) for single source localization 119 | input_shape = xTrain.shape[1:] 120 | kern_size1 = 3 121 | kern_size2 = 2 122 | 123 | model = Sequential() # kernel_regularizer=l1(0.00001), 124 | model.add(Conv2D(256, kernel_size=(kern_size1,kern_size1), activation=None, input_shape=input_shape, name="Conv2D_1",padding="valid", strides=(2,2))) 125 | model.add(BatchNormalization(trainable=True)) 126 | model.add(ReLU()) 127 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_2", padding="valid")) 128 | model.add(BatchNormalization(trainable=True)) 129 | model.add(ReLU()) 130 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_3", padding="valid")) 131 | model.add(BatchNormalization(trainable=True)) 132 | model.add(ReLU()) 133 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_4", padding="valid")) 134 | model.add(BatchNormalization(trainable=True)) 135 | model.add(ReLU()) 136 | model.add(Flatten()) 137 | model.add(Dense(4096, activation="relu",name="Dense_Layer1")) 138 | model.add(Dropout(0.3,name="Dropout1")) 139 | model.add(Dense(2048, activation="relu",name="Dense_Layer2")) 140 | model.add(Dropout(0.3,name="Dropout2")) 141 | model.add(Dense(1024, activation="relu",name="Dense_Layer3")) 142 | model.add(Dropout(0.3,name="Dropout3")) 143 | model.add(Dense(DNN_outp, activation="sigmoid", kernel_initializer=glorot_normal(seed=None),name="Classif_Layer")) 144 | model.summary() 145 | 146 | 147 | # In[15]: 148 | 149 | 150 | # Train the model with decaying learn rate 151 | # OPTION 1 152 | def schedule(epoch,lr): # use this function to gradually reduce the lr 153 | if epoch<1: 154 | return lr 155 | else: 156 | return float(lr*tf.math.exp(-0.1)) 157 | # OPTION 2 158 | def step_decay(epoch, lr): # or use this function to reduce every epochs_drop by a desired factor 159 | initial_lr = 0.001 160 | drop = 0.5 161 | epochs_drop = 10 162 | lrate = initial_lr* math.pow(drop, math.floor((1+epoch)/epochs_drop)) 163 | return lrate 164 | #dlr = LearningRateScheduler(step_decay,verbose=1) 165 | rlr = ReduceLROnPlateau(monitor='val_loss', factor=0.7, patience=10, verbose=1) 166 | #es = EarlyStopping(monitor='val_acc', mode='max', verbose=1, patience=20) 167 | #mc = ModelCheckpoint('best_model.h5', monitor='val_acc', mode='max', verbose=1, save_best_only=True) 168 | cbks = [rlr] #, es, mc] # no early stopping here due to the different stats between trainign and validation data 169 | #opt = tf.keras.optimizers.SGD(learning_rate=0.1,momentum=0.9,nesterov=True) 170 | opt = tf.keras.optimizers.Adam(learning_rate=0.001) 171 | model.compile(optimizer=opt , loss='binary_crossentropy', metrics=[tf.keras.metrics.BinaryAccuracy(name="acc")]) 172 | train_history = model.fit(xTrain, yTrain, epochs=200, batch_size=32, shuffle=True, validation_data=(xVal, yVal), callbacks=cbks) 173 | 174 | 175 | # In[16]: 176 | 177 | 178 | # summarize history for accuracy 179 | f1 = plt.figure(1) 180 | plt.plot(train_history.history['acc'], label='Training accuracy') 181 | plt.plot(train_history.history['val_acc'], label='Validation accuracy') 182 | #plt.title('model accuracy') 183 | plt.ylabel('Accuracy') 184 | plt.xlabel('Epoch') 185 | plt.legend(['Train', 'Val.'], loc='lower right') 186 | plt.grid() 187 | plt.show() 188 | 189 | # summarize history for loss 190 | f2 = plt.figure(2) 191 | plt.plot(train_history.history['loss'], label='Training loss') 192 | plt.plot(train_history.history['val_loss'], label='Validation loss') 193 | #plt.title('model loss') 194 | plt.ylabel('Loss') 195 | plt.xlabel('Epoch') 196 | plt.legend(['Train', 'Val.'], loc='upper left') 197 | plt.grid() 198 | plt.show() 199 | 200 | 201 | # In[17]: 202 | 203 | 204 | # save the training performance for reporting 205 | f3 = plt.figure(1) 206 | plt.subplot(2,1,1) 207 | plt.plot(train_history.history['acc'], label='Training accuracy') 208 | plt.plot(train_history.history['val_acc'], label='Validation accuracy') 209 | plt.ylabel('Accuracy') 210 | plt.legend(['Train', 'Val.'], loc='lower right') 211 | plt.grid() 212 | plt.subplot(2,1,2) 213 | plt.plot(train_history.history['loss'], label='Training loss') 214 | plt.plot(train_history.history['val_loss'], label='Validation loss') 215 | plt.ylabel('Loss') 216 | plt.xlabel('Epoch') 217 | plt.legend(['Train', 'Val.'], loc='upper right') 218 | plt.grid() 219 | plt.show() 220 | 221 | 222 | # In[18]: 223 | 224 | 225 | f1.savefig("binary_acc_Adam_lr_def_RoP_0_7.eps", dpi=1200, bbox_inches='tight') 226 | f2.savefig("loss_Adam_lr_def_RoP_0_7.eps", dpi=1200, bbox_inches='tight') 227 | 228 | 229 | # In[20]: 230 | 231 | 232 | # Save the figures to include them in the paper 233 | f3.savefig("training_perf_Adam_lr_def_RoP_0_7.eps", dpi=1200, bbox_inches='tight') 234 | 235 | 236 | # In[19]: 237 | 238 | 239 | model.save('Model_CNN_DoA_class_Data_N16_K2_res1_lowSNR_new_training_RQ_Adam_dropRoP_0_7.h5') 240 | 241 | -------------------------------------------------------------------------------- /Python_CNN/CNN_training_lowSNR_new_training_RQ_test_90deg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # In[1]: 5 | 6 | 7 | import h5py 8 | from sklearn.model_selection import train_test_split 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from keras import optimizers 12 | from keras.models import Sequential 13 | from keras.layers import Dense, Conv2D, MaxPooling2D, Flatten, Dropout, BatchNormalization, ReLU, Softmax 14 | from keras.regularizers import l2, l1 15 | from keras.initializers import glorot_normal 16 | from sklearn.preprocessing import MultiLabelBinarizer 17 | from keras.models import load_model 18 | from sklearn.metrics import mean_squared_error 19 | import pandas as pd 20 | import math 21 | import tensorflow as tf 22 | from tensorflow import keras 23 | #from tensorflow.keras.optimizers import Adam 24 | from keras.callbacks import LearningRateScheduler, ReduceLROnPlateau 25 | 26 | 27 | # In[2]: 28 | 29 | 30 | # Fix K detection of sources - Experiment Part A: 1) 31 | filename1 = 'C:/Users/geo_p/OneDrive - Heriot-Watt University/DoA DATA/DoA_DATA_JOURNALS/TRAIN_DATA_16ULA_K2_low_SNR_res1_3D_90deg.h5' 32 | f1 = h5py.File(filename1, 'r') 33 | angles = np.transpose(np.array(f1['angles'])) 34 | Ry_the = np.array(f1['theor']) 35 | res = 1 36 | K=2 37 | 38 | 39 | # In[3]: 40 | 41 | 42 | An_max = np.max(angles) 43 | An_min = np.min(angles) 44 | v = np.arange(An_min, An_max+res,res) 45 | print(v) 46 | 47 | 48 | # In[4]: 49 | 50 | 51 | DNN_outp = v.size 52 | print(DNN_outp) 53 | 54 | 55 | # In[5]: 56 | 57 | 58 | angles.shape 59 | 60 | 61 | # In[6]: 62 | 63 | 64 | Ry_the.shape 65 | 66 | 67 | # In[7]: 68 | 69 | 70 | [SNRs, n, chan, M, N] = Ry_the.shape 71 | 72 | 73 | # In[8]: 74 | 75 | 76 | X_data0=Ry_the.swapaxes(2,4) 77 | X_data0.shape 78 | 79 | 80 | # In[9]: 81 | 82 | 83 | X_data = X_data0.reshape([SNRs*n,N,M,chan]) 84 | X_data.shape 85 | 86 | 87 | # In[10]: 88 | 89 | 90 | mlb = MultiLabelBinarizer() 91 | yTrain_encoded = mlb.fit_transform(angles) 92 | 93 | 94 | # In[11]: 95 | 96 | 97 | yTrain_encoded[1] 98 | 99 | 100 | # In[12]: 101 | 102 | 103 | Y_Labels = np.tile(yTrain_encoded, reps=(SNRs,1)) 104 | #Y_Labels = yTrain_encoded 105 | Y_Labels.shape 106 | 107 | 108 | # In[13]: 109 | 110 | 111 | # Split the dataset into training and validation sets 112 | xTrain, xVal, yTrain, yVal = train_test_split(X_data, Y_Labels, test_size=0.1, random_state=42) # checked 113 | 114 | 115 | # In[16]: 116 | 117 | 118 | # Define the model (CNN) for single source localization 119 | input_shape = xTrain.shape[1:] 120 | kern_size1 = 3 121 | kern_size2 = 2 122 | 123 | model = Sequential() 124 | model.add(Conv2D(256, kernel_size=(kern_size1,kern_size1), activation=None, input_shape=input_shape, name="Conv2D_1",padding="valid", strides=(2,2))) 125 | model.add(BatchNormalization(trainable=True)) 126 | model.add(ReLU()) 127 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_2", padding="valid")) 128 | model.add(BatchNormalization(trainable=True)) 129 | model.add(ReLU()) 130 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_3", padding="valid")) 131 | model.add(BatchNormalization(trainable=True)) 132 | model.add(ReLU()) 133 | model.add(Conv2D(256, kernel_size=(kern_size2,kern_size2), activation=None,name="Conv2D_4", padding="valid")) 134 | model.add(BatchNormalization(trainable=True)) 135 | model.add(ReLU()) 136 | model.add(Flatten()) 137 | model.add(Dense(4096, activation="relu",name="Dense_Layer1")) 138 | model.add(Dropout(0.3,name="Dropout1")) 139 | model.add(Dense(2048, activation="relu",name="Dense_Layer2")) 140 | model.add(Dropout(0.3,name="Dropout2")) 141 | model.add(Dense(1024, activation="relu",name="Dense_Layer3")) 142 | model.add(Dropout(0.3,name="Dropout3")) 143 | model.add(Dense(DNN_outp, activation="sigmoid", kernel_initializer=glorot_normal(seed=None),name="Classif_Layer")) 144 | model.summary() 145 | 146 | 147 | # In[17]: 148 | 149 | 150 | # Train the model with Adam 151 | # Train the model with decaying learn rate 152 | # OPTION 1 153 | def schedule(epoch,lr): # use this function to gradually reduce the lr 154 | if epoch<1: 155 | return lr 156 | else: 157 | return float(lr*tf.math.exp(-0.1)) 158 | # OPTION 2 159 | def step_decay(epoch, lr): # or use this function to reduce every epochs_drop by a desired factor 160 | initial_lr = 0.001 161 | drop = 0.5 162 | epochs_drop = 20 163 | lrate = initial_lr* math.pow(drop, math.floor((1+epoch)/epochs_drop)) 164 | return lrate 165 | #dlr = LearningRateScheduler(step_decay,verbose=1) 166 | rlr = ReduceLROnPlateau(monitor='val_loss', factor=0.7, patience=10, verbose=1) 167 | cbks = [rlr] 168 | #opt = tf.keras.optimizers.SGD(learning_rate=0.1,momentum=0.9,nesterov=True) 169 | opt = tf.keras.optimizers.Adam(learning_rate=0.001) 170 | model.compile(optimizer=opt , loss='binary_crossentropy', metrics=[tf.keras.metrics.BinaryAccuracy(name="acc")]) 171 | train_history = model.fit(xTrain, yTrain, epochs=200, batch_size=32, shuffle=True, validation_data=(xVal, yVal), callbacks=cbks) 172 | 173 | 174 | # In[18]: 175 | 176 | 177 | # summarize history for accuracy 178 | f1 = plt.figure(1) 179 | plt.plot(train_history.history['acc'], label='Training accuracy') 180 | plt.plot(train_history.history['val_acc'], label='Validation accuracy') 181 | #plt.title('model accuracy') 182 | plt.ylabel('Accuracy') 183 | plt.xlabel('Epoch') 184 | plt.legend(['Train', 'Val.'], loc='lower right') 185 | plt.grid() 186 | plt.show() 187 | 188 | # summarize history for loss 189 | f2 = plt.figure(2) 190 | plt.plot(train_history.history['loss'], label='Training loss') 191 | plt.plot(train_history.history['val_loss'], label='Validation loss') 192 | #plt.title('model loss') 193 | plt.ylabel('Loss') 194 | plt.xlabel('Epoch') 195 | plt.legend(['Train', 'Val.'], loc='upper left') 196 | plt.grid() 197 | plt.show() 198 | 199 | 200 | # In[19]: 201 | 202 | 203 | # save the training performance for reporting 204 | f3 = plt.figure(1) 205 | plt.subplot(2,1,1) 206 | plt.plot(train_history.history['acc'], label='Training accuracy') 207 | plt.plot(train_history.history['val_acc'], label='Validation accuracy') 208 | plt.ylabel('Accuracy') 209 | plt.legend(['Train', 'Val.'], loc='lower right') 210 | plt.grid() 211 | plt.subplot(2,1,2) 212 | plt.plot(train_history.history['loss'], label='Training loss') 213 | plt.plot(train_history.history['val_loss'], label='Validation loss') 214 | plt.ylabel('Loss') 215 | plt.xlabel('Epoch') 216 | plt.legend(['Train', 'Val.'], loc='upper right') 217 | plt.grid() 218 | plt.show() 219 | 220 | 221 | # In[20]: 222 | 223 | 224 | f1.savefig("binary_acc_Adam_LRdef_90deg_v6c.eps", dpi=1200, bbox_inches='tight') 225 | f2.savefig("loss_Adam_LRdef_90deg_v6c.eps", dpi=1200, bbox_inches='tight') 226 | 227 | 228 | # In[21]: 229 | 230 | 231 | # Save the figures to include them in the paper 232 | f3.savefig("training_perf_Adam_LRdef_90deg_v6c.eps", dpi=1200, bbox_inches='tight') 233 | 234 | 235 | # In[22]: 236 | 237 | 238 | model.save('Model_CNN_DoA_class_Data_N16_K2_res1_lowSNR_new_training_RQ_90deg_v6c.h5') 239 | 240 | 241 | # In[ ]: 242 | 243 | 244 | 245 | 246 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeepNetworks-for-DoA-estimation-in-low-SNR 2 | 3 | The code was written in jupyter notebook and the files stored in .py format when finalized. 4 | 5 | Python 3.7 was used as interpreter and the CNN was trained using GPU computing (TITAN RTX used) using Tensorflow 2.3 as backend. 6 | --------------------------------------------------------------------------------