mirror of
https://gitlab.science.ru.nl/mthesis-edeboone/m-thesis-introduction.git
synced 2024-11-13 18:13:31 +01:00
ZH: matrix: SNR plot compared to Rice and Gaussian
This commit is contained in:
parent
e06d3f13d0
commit
a58567728d
1 changed files with 217 additions and 0 deletions
217
simulations/airshower_beacon_simulation/matrix_base/bin/time_res_vs_snr.py
Executable file
217
simulations/airshower_beacon_simulation/matrix_base/bin/time_res_vs_snr.py
Executable file
|
@ -0,0 +1,217 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import json
|
||||||
|
|
||||||
|
from scipy import special
|
||||||
|
|
||||||
|
|
||||||
|
# Mimic import aa_generate_beacon as beacon
|
||||||
|
beacon = lambda: None
|
||||||
|
|
||||||
|
def read_snr_file(fname):
|
||||||
|
with open(fname, 'r') as fp:
|
||||||
|
return json.load(fp)
|
||||||
|
|
||||||
|
def read_tx_file(fname):
|
||||||
|
with open(fname, 'r') as fp:
|
||||||
|
data = json.load(fp)
|
||||||
|
|
||||||
|
f_beacon = data['f_beacon']
|
||||||
|
tx = data['tx']
|
||||||
|
|
||||||
|
del data['f_beacon']
|
||||||
|
del data['tx']
|
||||||
|
|
||||||
|
return tx, f_beacon, data
|
||||||
|
|
||||||
|
|
||||||
|
beacon.snr_fname = 'snr.json'
|
||||||
|
beacon.tx_fname = 'tx.json'
|
||||||
|
beacon.read_snr_file = read_snr_file
|
||||||
|
beacon.read_tx_file = read_tx_file
|
||||||
|
|
||||||
|
def read_snr_directories(data_directories, tx_fname=beacon.tx_fname, snr_fname=beacon.snr_fname, phase_res_fname='phase_time_residuals.json'):
|
||||||
|
# Read in snr
|
||||||
|
snrs = np.zeros(len(data_directories), dtype=float)
|
||||||
|
time_residuals = np.zeros( (len(snrs), 2), dtype=float)
|
||||||
|
|
||||||
|
|
||||||
|
tx, f_beacon, _ = beacon.read_tx_file(path.join(data_directories[0], tx_fname))
|
||||||
|
for i, data_dir in enumerate(data_directories):
|
||||||
|
# Read SNR file
|
||||||
|
snr_data = read_snr_file(path.join(data_dir, snr_fname))
|
||||||
|
|
||||||
|
# Open antennas file
|
||||||
|
with open(path.join(data_dir, phase_res_fname), 'r') as fp:
|
||||||
|
time_res_data = json.load(fp)
|
||||||
|
|
||||||
|
snrs[i] = snr_data['mean']
|
||||||
|
|
||||||
|
time_residuals[i] = time_res_data['mean'], time_res_data['std']
|
||||||
|
|
||||||
|
return f_beacon, snrs, time_residuals
|
||||||
|
|
||||||
|
|
||||||
|
## Math
|
||||||
|
def expectation(x, pdfx):
|
||||||
|
dx = x[1] - x[0]
|
||||||
|
return np.sum(x*pdfx*dx)
|
||||||
|
|
||||||
|
def variance(x, pdfx):
|
||||||
|
mu = expectation(x, pdfx)
|
||||||
|
dx = x[1] - x[0]
|
||||||
|
return np.sum(x**2 *pdfx*dx) - mu**2
|
||||||
|
|
||||||
|
def phase_distribution(theta, sigma, s):
|
||||||
|
k = s/sigma
|
||||||
|
ct = np.cos(theta)
|
||||||
|
st = np.sin(theta)
|
||||||
|
pipi = 2*np.pi
|
||||||
|
|
||||||
|
return (np.exp(-k**2/2)/pipi) \
|
||||||
|
+ (
|
||||||
|
(pipi**-0.5)*k*np.exp(-(k*st)**2/2)
|
||||||
|
* ((1.+special.erf(k*ct*2**-0.5))*ct/2)
|
||||||
|
)
|
||||||
|
|
||||||
|
def phase_distribution_gauss(theta, sigma, s):
|
||||||
|
k = s/sigma
|
||||||
|
return 1/np.sqrt(2*np.pi) * k *np.exp( -(k*theta)**2/2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from os import path
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import os
|
||||||
|
import matplotlib
|
||||||
|
if os.name == 'posix' and "DISPLAY" not in os.environ:
|
||||||
|
matplotlib.use('Agg')
|
||||||
|
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
parser = ArgumentParser()
|
||||||
|
|
||||||
|
figsize = (12,8)
|
||||||
|
|
||||||
|
# Multiple Data Directories
|
||||||
|
parser.add_argument("-d", dest='data_directories', default=[], nargs='*')
|
||||||
|
|
||||||
|
# Whether to show plots
|
||||||
|
group1 = parser.add_mutually_exclusive_group(required=False)
|
||||||
|
group1.add_argument('--show-plots', action='store_true', default=True, help='Default: %(default)s')
|
||||||
|
group1.add_argument('--no-show-plots', dest='show-plots', action='store_false')
|
||||||
|
|
||||||
|
# Figures directory
|
||||||
|
parser.add_argument('--fig-dir', type=str, default='./figures', help='Set None to disable saving figures. (Default: %(default)s)')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
show_plots = args.show_plots
|
||||||
|
|
||||||
|
if not args.data_directories:
|
||||||
|
parser.error("At least one data directory should be specified.")
|
||||||
|
|
||||||
|
f_beacon, snrs, time_residuals = read_snr_directories(args.data_directories)
|
||||||
|
|
||||||
|
phase2time = lambda x: x/(2*np.pi*f_beacon)
|
||||||
|
time2phase = lambda x: 2*np.pi*x*f_beacon
|
||||||
|
|
||||||
|
fig, ax = plt.subplots(figsize=(8,6))
|
||||||
|
ax.set_title("Beacon ({:.2f}MHz) Simulation".format(f_beacon*1e3))
|
||||||
|
ax.set_xlabel('Signal to Noise ratio')
|
||||||
|
ax.set_ylabel('Time Accuracy $\\sigma(t)$ [ns]')
|
||||||
|
|
||||||
|
# group per directories per N
|
||||||
|
if True:
|
||||||
|
import re
|
||||||
|
|
||||||
|
dirdict = {}
|
||||||
|
N_re = re.compile(r'_N(\d+)_')
|
||||||
|
|
||||||
|
for d in args.data_directories:
|
||||||
|
m = N_re.findall(d)[0]
|
||||||
|
|
||||||
|
if m not in dirdict:
|
||||||
|
dirdict[m] = []
|
||||||
|
|
||||||
|
dirdict[m].append(d)
|
||||||
|
|
||||||
|
|
||||||
|
dirlist = dirdict.values()
|
||||||
|
|
||||||
|
# plot data directories as one group
|
||||||
|
else:
|
||||||
|
dirlist = [args.data_directories]
|
||||||
|
|
||||||
|
for dirlist in dirlist:
|
||||||
|
f_beacon, snrs, time_residuals = read_snr_directories(dirlist)
|
||||||
|
|
||||||
|
# plot data
|
||||||
|
ax.plot(snrs*np.sqrt(np.pi/2), phase2time(time_residuals[:,1]), ls='none', marker='o')
|
||||||
|
|
||||||
|
# Add secondary axis
|
||||||
|
if True:
|
||||||
|
if False and secondary_axis == 'time':
|
||||||
|
functions = (phase2time, time2phase)
|
||||||
|
label = 'Time Accuracy $\\sigma_t\\varphi/(2\\pi f_{beac})$ [ns]'
|
||||||
|
else:
|
||||||
|
functions = (time2phase, phase2time)
|
||||||
|
label = 'Phase Accuracy $\\sigma_\\varphi$ [rad]'
|
||||||
|
|
||||||
|
secax = ax.secondary_yaxis('right', functions=functions)
|
||||||
|
secax.set_ylabel(label)
|
||||||
|
|
||||||
|
# logscales
|
||||||
|
if True:
|
||||||
|
ax.set_xscale('log')
|
||||||
|
ax.set_yscale('log')
|
||||||
|
|
||||||
|
# plot phasor snr
|
||||||
|
if True:
|
||||||
|
thetas = np.linspace(-np.pi, np.pi, 500)
|
||||||
|
sigma = 1
|
||||||
|
_snr_min = min(10, min(snrs))
|
||||||
|
_snr_max = min(100, max(snrs))
|
||||||
|
|
||||||
|
if ax.get_xscale() == 'log': #log
|
||||||
|
_snrs = np.logspace(np.log10(_snr_min), np.log10(_snr_max))
|
||||||
|
else: #linear
|
||||||
|
_snrs = np.linspace(_snr_min, _snr_max)
|
||||||
|
|
||||||
|
# Phasor Rice
|
||||||
|
phasor_pdfs = np.array([phase_distribution(thetas, sigma, s) for s in _snrs ])
|
||||||
|
phasor_sigma = np.sqrt(np.array([variance(thetas, pdf) for pdf in phasor_pdfs]))
|
||||||
|
|
||||||
|
ax.plot(_snrs, phase2time(phasor_sigma), label='Rice')
|
||||||
|
|
||||||
|
if True: # plot a pdf
|
||||||
|
fig2, ax2 = plt.subplots()
|
||||||
|
for idx in [0, len(_snrs)//4, len(_snrs)//2, -1]:
|
||||||
|
ax2.plot(thetas, phasor_pdfs[idx], label='s = {:.1f}'.format(_snrs[idx]))
|
||||||
|
ax2.set_xlabel('$\\theta$')
|
||||||
|
ax2.set_ylabel('$p(\\theta)$')
|
||||||
|
ax2.legend()
|
||||||
|
|
||||||
|
# Gauss Phasor
|
||||||
|
phasor_pdfs = np.array([phase_distribution_gauss(thetas, sigma, s) for s in _snrs ])
|
||||||
|
phasor_sigma = np.sqrt(np.array([variance(thetas, pdf) for pdf in phasor_pdfs]))
|
||||||
|
|
||||||
|
ax.plot(_snrs, phase2time(phasor_sigma), label='Gauss')
|
||||||
|
ax.legend()
|
||||||
|
|
||||||
|
# Set limit on x values
|
||||||
|
if not True or ax.get_xscale() != 'log':
|
||||||
|
ax.set_xlim(0, 100)
|
||||||
|
|
||||||
|
if args.fig_dir:
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(path.join(args.fig_dir, "time_res_vs_snr.pdf"))
|
||||||
|
|
||||||
|
if args.show_plots:
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue