I am trying to write a simulation code to estimate AOA's from channel state informations(CSI) using MUSIC algorithm. I am using OFDM with 64 subcarriers. Is there any material on how to estimate AOAs directly from CSIs using MUSIC?
I have linear antenna array. The number of antenna is a variable that I can play around with. Minimum is 4.
import os, time, sys
import numpy as np
import matplotlib.pyplot as plt
def get_chans_from_params(params, K, sep, lambs):
'''
given the params/4-tuples for the physical paths, compute the channel
across K antenna for given wavelengths.
Based on Equation 3 of paper
'''
d_ns, a_ns, phi_ns, psi_ns = params
N = len(d_ns)
I = len(lambs)
H = np.zeros(([I, K]),dtype=complex)
for i_wl in range(len(lambs)):
wl = lambs[i_wl]
### based on eq 3
for i_K in range(K): ###for each antenna
t = 0
for i_N in range(N): ###for each path
c1 = np.exp(-2j * np.pi * (i_K) * sep[i_wl] * psi_ns[i_N] / wl)
H[i_wl, i_K] += c1
return H
def get_lambsWifi(cf, bw, nfft):
c = 3e8
f = np.fft.fftfreq(nfft)
f = np.fft.fftshift(f)
f = f * bw
cf = f + cf
cf_wifi = np.concatenate((cf[6:32], cf[33:59]))
l1 = []
for f in cf_wifi:
l1.append(c / f)
return np.array(l1)
sep = 0.06 ## antenna separation, no effect when K=1
nfft = 64 ## nfft for channel
K = 4 ## num antennas
cf = 2.412e9 ## center freq
bw = 20e6 ## bandwidth over which channel is observed
l1 = get_lambsWifi(cf, bw, nfft) ## wavelengths, lambda for subcarriers in channel
sep = l1/2
params = [ [5], [0.8], [0.001], [np.cos(np.pi/4)]]
K = 4
lambs = l1
print(l1)
X = get_chans_from_params(params,K,sep,lambs)
print(X[0,:])
X1 = X[0,:].reshape(K,1)
theta = np.linspace(0,np.pi,314)
Pmusic=np.zeros((1,len(theta)),dtype=complex)
l=l1[0]
X_h = X1.conj().T
eigenValues, eigenVectors = np.linalg.eig(X1*X_h)
idx = eigenValues.argsort()[::-1]
eigenValues = eigenValues[idx]
eigenVectors = eigenVectors[:,idx]
idx = eigenValues.argsort()[::-1]
eigenValues = eigenValues[idx]# soriting the eigenvectors and eigenvalues from greatest to least eigenvalue
eigenVectors = eigenVectors[:,idx]
signal_eigen = eigenVectors[0:1]#these vectors make up the signal subspace, by using the number of principal compoenets, 2 to split the eigenvectors
noise_eigen = eigenVectors[1:len(eigenVectors)]# noise subspace
U_N = np.transpose(noise_eigen)
# noisy_eigenvalues = eig_val[1:]
# thresholded_indices = np.where(noisy_eigenvalues > 0.5)[0]
# U_N = eig_vect[:, thresholded_indices]
for i in range(len(theta)):
psi_ns = np.cos(theta[i])
SS = np.zeros((K,1),dtype=complex);
### based on eq 3
for i_K in range(K): ###for each antenna
SS[i_K] = np.exp(-2j * np.pi * (i_K)* sep[0]*psi_ns/l)
PP = np.dot(np.dot(np.transpose(SS),np.dot(U_N,np.transpose(U_N))),SS)
print('print',PP)
Pmusic[0,i]=(1/PP);
Pmusic[0,:] = np.real(10*np.log10(Pmusic[0,:]))
print(Pmusic)
plt.plot(theta,Pmusic[0,:])
plt.show()