mirror of
https://gitlab.science.ru.nl/mthesis-edeboone/m-thesis-introduction.git
synced 2024-11-14 02:23:32 +01:00
198 lines
5.8 KiB
Python
198 lines
5.8 KiB
Python
|
#!/usr/bin/env python3
|
||
|
# vim: fdm=indent ts=4
|
||
|
|
||
|
import numpy as np
|
||
|
import h5py
|
||
|
|
||
|
import lib
|
||
|
|
||
|
import aa_generate_beacon as beacon
|
||
|
|
||
|
from lib import direct_fourier_transform
|
||
|
|
||
|
from numpy.polynomial import Polynomial
|
||
|
|
||
|
def find_beacon_in_traces(
|
||
|
traces,
|
||
|
t_trace,
|
||
|
f_beacon_estimate = 50e6,
|
||
|
frequency_fit = False,
|
||
|
N_test_freqs = 5e2,
|
||
|
f_beacon_estimate_band = 0.01,
|
||
|
amp_cut = 0.8
|
||
|
):
|
||
|
"""
|
||
|
f_beacon_band is inclusive
|
||
|
|
||
|
traces is [trace, trace, trace, .. ]
|
||
|
"""
|
||
|
|
||
|
amplitudes = np.zeros(len(traces))
|
||
|
phases = np.zeros(len(traces))
|
||
|
frequencies = np.zeros(len(traces))
|
||
|
|
||
|
if frequency_fit: # fit frequency
|
||
|
test_freqs = f_beacon_estimate + f_beacon_estimate_band * np.linspace(-1, 1, int(N_test_freqs)+1)
|
||
|
ft_amp_gen = direct_fourier_transform(test_freqs, t_trace, (x for x in traces))
|
||
|
|
||
|
n_samples = len(t_trace)
|
||
|
|
||
|
for i, ft_amp in enumerate(ft_amp_gen):
|
||
|
real, imag = ft_amp
|
||
|
amps = 1/n_samples * ( real**2 + imag**2)**0.5
|
||
|
|
||
|
# find frequency peak and surrounding
|
||
|
# bins valid for parabola fitting
|
||
|
max_amp_idx = np.argmax(amps)
|
||
|
max_amp = amps[max_amp_idx]
|
||
|
|
||
|
if True:
|
||
|
frequencies[i] = test_freqs[max_amp_idx]
|
||
|
continue
|
||
|
|
||
|
valid_mask = amps >= amp_cut*max_amp
|
||
|
|
||
|
if True: # make sure not to use other peaks
|
||
|
lower_mask = valid_mask[0:max_amp_idx]
|
||
|
upper_mask = valid_mask[max_amp_idx:]
|
||
|
|
||
|
if any(lower_mask):
|
||
|
lower_end = np.argmin(lower_mask[::-1])
|
||
|
else:
|
||
|
lower_end = max_amp_idx
|
||
|
|
||
|
if any(upper_mask):
|
||
|
upper_end = np.argmin(upper_mask)
|
||
|
else:
|
||
|
upper_end = 0
|
||
|
|
||
|
|
||
|
valid_mask[0:(max_amp_idx - lower_end)] = False
|
||
|
valid_mask[(max_amp_idx + upper_end):] = False
|
||
|
|
||
|
if all(~valid_mask):
|
||
|
frequencies[i] = np.nan
|
||
|
continue
|
||
|
|
||
|
# fit Parabola
|
||
|
parafit = Polynomial.fit(test_freqs[valid_mask], amps[valid_mask], 2)
|
||
|
func = parafit.convert()
|
||
|
|
||
|
# find frequency where derivative is 0
|
||
|
deriv = func.deriv(1)
|
||
|
freq = deriv.roots()[0]
|
||
|
|
||
|
frequencies[i] = freq
|
||
|
else:
|
||
|
frequencies[:] = f_beacon_estimate
|
||
|
|
||
|
# evaluate fourier transform at freq for each trace
|
||
|
for i, freq in enumerate(frequencies):
|
||
|
if freq is np.nan:
|
||
|
phases[i] = np.nan
|
||
|
amplitudes[i] = np.nan
|
||
|
continue
|
||
|
|
||
|
real, imag = direct_fourier_transform(freq, t_trace, traces[i])
|
||
|
|
||
|
phases[i] = np.arctan2(real, imag)
|
||
|
amplitudes[i] = 1/len(t_trace) * (real**2 + imag**2)**0.5
|
||
|
|
||
|
return frequencies, phases, amplitudes
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
from os import path
|
||
|
import sys
|
||
|
|
||
|
|
||
|
f_beacon_band = (49e-3,55e-3) #GHz
|
||
|
allow_frequency_fitting = True
|
||
|
read_frequency_from_file = True
|
||
|
|
||
|
fname = "ZH_airshower/mysim.sry"
|
||
|
|
||
|
####
|
||
|
fname_dir = path.dirname(fname)
|
||
|
antennas_fname = path.join(fname_dir, beacon.antennas_fname)
|
||
|
|
||
|
if not path.isfile(antennas_fname):
|
||
|
print("Antenna file cannot be found, did you try generating a beacon?")
|
||
|
sys.exit(1)
|
||
|
|
||
|
# read in antennas
|
||
|
with h5py.File(antennas_fname, 'a') as fp:
|
||
|
if 'antennas' not in fp.keys():
|
||
|
print("Antenna file corrupted? no antennas")
|
||
|
sys.exit(1)
|
||
|
|
||
|
group = fp['antennas']
|
||
|
|
||
|
f_beacon = None
|
||
|
if read_frequency_from_file and 'tx' in fp:
|
||
|
tx = fp['tx']
|
||
|
if 'f_beacon' in tx.attrs:
|
||
|
f_beacon = tx.attrs['f_beacon']
|
||
|
else:
|
||
|
print("No frequency found in file.")
|
||
|
sys.exit(2)
|
||
|
f_beacon_estimate_band = 0.01*f_beacon
|
||
|
|
||
|
elif allow_frequency_fitting:
|
||
|
f_beacon_estimate_band = (f_beacon_band[1] - f_beacon_band[0])/2
|
||
|
f_beacon = f_beacon_band[1] - f_beacon_estimate_band
|
||
|
else:
|
||
|
print("Not allowed to fit frequency and no tx group found in file.")
|
||
|
sys.exit(2)
|
||
|
|
||
|
N_antennas = len(group.keys())
|
||
|
# just for funzies
|
||
|
found_data = np.zeros((N_antennas, 3))
|
||
|
|
||
|
# Determine frequency and phase
|
||
|
for i, name in enumerate(group.keys()):
|
||
|
ant_group = group[name]
|
||
|
|
||
|
if 'traces' not in ant_group.keys():
|
||
|
print(f"Antenna file corrupted? no 'traces' in {name}")
|
||
|
sys.exit(1)
|
||
|
|
||
|
traces = ant_group['traces']
|
||
|
|
||
|
freqs, phases, amps = find_beacon_in_traces(
|
||
|
traces[1:-1], traces[0],
|
||
|
f_beacon_estimate=f_beacon,
|
||
|
frequency_fit=allow_frequency_fitting,
|
||
|
f_beacon_estimate_band=f_beacon_estimate_band
|
||
|
)
|
||
|
|
||
|
# only take Ex for now
|
||
|
frequency = freqs[-1]
|
||
|
phase = phases[-1]
|
||
|
amplitude = amps[-1]
|
||
|
|
||
|
print(frequency, phase, amplitude)
|
||
|
|
||
|
ant_group.attrs['beacon_freq'] = frequency
|
||
|
ant_group.attrs['beacon_phase'] = phase
|
||
|
ant_group.attrs['beacon_amplitude'] = amplitude
|
||
|
ant_group.attrs['beacon_orientation'] = 'Ex'
|
||
|
|
||
|
found_data[i] = frequency, phase, amplitude
|
||
|
|
||
|
# show histogram of found frequencies
|
||
|
if True:
|
||
|
import matplotlib.pyplot as plt
|
||
|
if True or allow_frequency_fitting:
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.set_xlabel("Frequency")
|
||
|
ax.set_ylabel("Counts")
|
||
|
ax.hist(found_data[:,0], bins='auto', density=False)
|
||
|
|
||
|
if True:
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.set_xlabel("Amplitudes")
|
||
|
ax.set_ylabel("Counts")
|
||
|
ax.hist(found_data[:,2], bins='auto', density=False)
|
||
|
|
||
|
plt.show()
|