Skip to content

Commit c9c306c

Browse files
committed
plot S2_genie v S2_est, ability to add offset
1 parent 9481435 commit c9c306c

File tree

2 files changed

+75
-30
lines changed

2 files changed

+75
-30
lines changed

est_snr.py

Lines changed: 73 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,23 @@ def snr_est_test(model, snr_target, h, Nw, test_S1=False):
6262
# matrix of received pilots plus noise samples
6363
Pcn_hat = h*Pcn + n
6464

65+
Rcn_hat_genie = np.abs(h)*Pcn + n
66+
Ns = model.Ns + 1
67+
rx_sym_pilots = torch.zeros((1,1,Nw*Ns,Nc), dtype=torch.complex64)
68+
rx_sym_pilots[0,0,::Ns,:] = torch.tensor(Pcn_hat)
69+
rx_pilots = receiver.est_pilots(rx_sym_pilots, Nw-1, Nc, Ns)
70+
rx_pilots = rx_pilots.cpu().detach().numpy()
71+
rx_phase = np.angle(rx_pilots)
72+
Rcn_hat_est = Pcn_hat *np.exp(-1j*rx_phase)
73+
6574
# phase corrected received pilots
6675
genie_phase = not args.eq_ls
76+
6777
if genie_phase:
68-
Rcn_hat = np.abs(h)*Pcn + n
78+
Rcn_hat = Rcn_hat_genie
6979
else:
70-
Ns = model.Ns + 1
71-
rx_sym_pilots = torch.zeros((1,1,Nw*Ns,Nc), dtype=torch.complex64)
72-
rx_sym_pilots[0,0,::Ns,:] = torch.tensor(Pcn_hat)
73-
rx_pilots = receiver.est_pilots(rx_sym_pilots, Nw-1, Nc, Ns)
74-
rx_pilots = rx_pilots.cpu().detach().numpy()
75-
rx_phase = np.angle(rx_pilots)
76-
#print(rx_phase.shape)
77-
#print(rx_phase)
78-
Rcn_hat = Pcn_hat *np.exp(-1j*rx_phase)
79-
80+
Rcn_hat = Rcn_hat_est
81+
8082
if args.plots:
8183
plt.figure(1)
8284
plt.plot(Rcn_hat.real, Rcn_hat.imag,'b+')
@@ -96,17 +98,25 @@ def snr_est_test(model, snr_target, h, Nw, test_S1=False):
9698
print(f"S1: {S1:5.2f} S1_sum: {S1_sum:5.2f}")
9799

98100
# calculate S2 and SNR est
99-
S2 = np.sum(np.abs(Rcn_hat.imag)**2)
100-
snr_est = S1/(2*S2) - 1
101-
102-
# actual snr as check, for AWGN should be close to snr_target, for non untity h
103-
# it can be quite different
104-
101+
S2_genie = np.sum(np.abs(Rcn_hat_genie.imag)**2)
102+
S2_est = np.sum(np.abs(Rcn_hat_est.imag)**2)
103+
if genie_phase:
104+
snr_est = S1/(2*S2_genie) - 1
105+
else:
106+
snr_est = S1/(2*S2_est) - 1
107+
108+
# remove occasional illegal values
109+
if snr_est <= 0:
110+
snr_est = 0.1
111+
112+
# actual snr for this time window as check, for AWGN should be
113+
# close to snr_target, for non untity h it can be quite different
105114
snr_check = np.sum(np.abs(h*Pcn)**2)/np.sum(np.abs(n)**2)
106-
#print(f"S: {np.sum(np.abs(h*Pcn)**2):f} N: {np.sum(np.abs(n)**2)}")
107-
#print(f"snr:target {snr_target:5.2f} snr_check: {snr_check.real:5.2f} snr_est: {snr_est:5.2f}")
108115

109-
return snr_est,snr_check
116+
# user supplied correction factor
117+
snr_est *= 10 ** (args.offset/10)
118+
119+
return snr_est, snr_check, S2_genie, S2_est
110120

111121
# Bring up a RADAE model
112122
latent_dim = 80
@@ -122,47 +132,79 @@ def snr_est_test(model, snr_target, h, Nw, test_S1=False):
122132

123133
# single timestep test
124134
def single(snrdB, h, Nw, test_S1):
125-
snr_est, snr_check = snr_est_test(model, 10**(snrdB/10), h, Nw, test_S1)
135+
snr_est, snr_check, S2_genie, S2_est = snr_est_test(model, 10**(snrdB/10), h, Nw, test_S1)
126136
print(f"snrdB: {snrdB:5.2f} snrdB_check: {10*np.log10(snr_check):5.2f} snrdB_est: {10*np.log10(snr_est):5.2f}")
127137

128138
# run over a sequence of timesteps, and return lists of each each est
129139
def sequence(Ntimesteps, snrdB, h, Nw):
130140
snrdB_est_list = []
131141
snrdB_check_list = []
142+
NdB_genie_list = []
143+
NdB_est_list = []
132144

133145
for i in range(Ntimesteps):
134-
snr_est, snr_check = snr_est_test(model, 10**(snrdB/10), h[i*Nw:(i+1)*Nw,:], Nw)
146+
snr_est, snr_check, S2_genie, S2_est = snr_est_test(model, 10**(snrdB/10), h[i*Nw:(i+1)*Nw,:], Nw)
135147
snrdB_check = 10*np.log10(snr_check)
136148
snrdB_est = 10*np.log10(snr_est)
137-
print(f"snrdB: {snrdB:5.2f} snrdB_check: {snrdB_check:5.2f} snrdB_est: {snrdB_est:5.2f}")
149+
NdB_genie = 10*np.log10(2*S2_genie)
150+
NdB_est = 10*np.log10(2*S2_est)
151+
152+
print(f"snrdB: {snrdB:5.2f} snrdB_check: {snrdB_check:5.2f} snrdB_est: {snrdB_est:5.2f} NdB: {NdB_genie:5.2f} {NdB_est:5.2f}")
153+
138154
snrdB_est_list = np.append(snrdB_est_list, snrdB_est)
139155
snrdB_check_list = np.append(snrdB_check_list, snrdB_check)
156+
NdB_genie_list = np.append(NdB_genie_list, NdB_genie)
157+
NdB_est_list = np.append(NdB_est_list, NdB_est)
140158

141-
return snrdB_est_list, snrdB_check_list
159+
return snrdB_est_list, snrdB_check_list, NdB_genie,NdB_est
142160

143161
# sweep across SNRs
144162
def sweep(Ntimesteps, h, Nw):
145163

146164
EsNodB_check = []
147165
EsNodB_est = []
166+
NdB_genie = []
167+
NdB_est = []
168+
148169
r = range(-5,20)
149170
for aEsNodB in r:
150-
aEsNodB_check, aEsNodB_est = sequence(Ntimesteps, aEsNodB, h, Nw)
171+
aEsNodB_check, aEsNodB_est, aNdB_genie, aNdB_est = sequence(Ntimesteps, aEsNodB, h, Nw)
151172
EsNodB_check = np.append(EsNodB_check, aEsNodB_check)
152173
EsNodB_est = np.append(EsNodB_est, aEsNodB_est)
174+
NdB_genie = np.append(NdB_genie, aNdB_genie)
175+
NdB_est = np.append(NdB_est, aNdB_est)
153176

177+
z = np.polyfit(EsNodB_check, EsNodB_est, 1)
178+
print(z)
179+
EsNodB_est_fit = z[0]*EsNodB_check + z[1]
180+
154181
plt.figure(1)
155182
plt.plot(EsNodB_check, EsNodB_est,'b+')
183+
plt.plot(EsNodB_check, EsNodB_est_fit,'r')
156184
plt.plot(r,r)
157185
plt.axis([-5, 20, -5, 20])
158186
plt.grid()
159187
plt.xlabel('SNR (dB)')
160188
plt.ylabel('SNR est (dB)')
189+
190+
z = np.polyfit(NdB_genie, NdB_est, 1)
191+
print(z)
192+
NdB_est_fit = z[0]*NdB_genie + z[1]
193+
print(len(NdB_est))
194+
plt.figure(2)
195+
plt.plot(NdB_genie, NdB_est,'b+')
196+
plt.plot(NdB_genie,NdB_genie)
197+
plt.plot(NdB_genie, NdB_est_fit,'r')
198+
plt.grid()
199+
plt.xlabel('N_genie (dB)')
200+
plt.ylabel('N_est (dB)')
201+
161202
plt.show()
162203

163-
# save test file of test points for Latex plotting in Octave radae_plots.m:est_snr_plot()
164-
test_points = np.transpose(np.array((EsNodB_check,EsNodB_est)))
165-
np.savetxt('est_snr.txt',test_points,delimiter='\t')
204+
if args.save_text:
205+
# save test file of test points for Latex plotting in Octave radae_plots.m:est_snr_plot()
206+
test_points = np.transpose(np.array((EsNodB_check,EsNodB_est)))
207+
np.savetxt(args.save_text,test_points,delimiter='\t')
166208

167209
parser = argparse.ArgumentParser()
168210
parser.add_argument('--snrdB', type=float, default=10.0, help='snrdB set point')
@@ -172,8 +214,10 @@ def sweep(Ntimesteps, h, Nw):
172214
parser.add_argument('-T', type=float, default=1.0, help='length of time window for estimate (default 1.0 sec)')
173215
parser.add_argument('--Nt', type=int, default=1, help='number of analysis time windows to test across (default 1)')
174216
parser.add_argument('--test_S1', action='store_true', help='calculate S1 two ways to check S1 expression')
175-
parser.add_argument('--eq_ls', action='store_true', help='est phase from received pilots usin least square (default genie phase)')
217+
parser.add_argument('--eq_ls', action='store_true', help='est phase from received pilots using least square (default genie phase)')
176218
parser.add_argument('--plots', action='store_true', help='debug plots (default off)')
219+
parser.add_argument('--save_text', type=str, default="", help='path to text file to save test points')
220+
parser.add_argument('--offset', type=float, default=0.0, help='y offset correction in dB (default 0)')
177221
args = parser.parse_args()
178222

179223
Nw = int(args.T // model.Tmf)

multipath_samples.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ function multipath_samples(ch, Fs, Rs, Nc, Nseconds, H_fn, G_fn="",H_complex=0)
6767
else
6868
bytes_per_sample = 4
6969
end
70-
printf("H file size is Nseconds*Rs*Nc*(%d bytes/sample) = %d*%d*%d*%d = %d bytes\n", bytes_per_sample, Nseconds,Rs,Nc,Nseconds*Rs*Nc*bytes_per_sample)
70+
printf("H file size is Nseconds*Rs*Nc*(%d bytes/sample) = %d*%d*%d*%d = %d bytes\n", bytes_per_sample,
71+
Nseconds,Rs,Nc,bytes_per_sample, Nseconds*Rs*Nc*bytes_per_sample)
7172
f=fopen(H_fn,"wb");
7273
[r c] = size(H);
7374
Hflat = reshape(H', 1, r*c);

0 commit comments

Comments
 (0)