2022-11-28 19:03:14 +01:00
#!/usr/bin/env python3
# vim: fdm=indent ts=4
"""
Find the best integer multiple to shift
2022-11-29 17:04:26 +01:00
antennas to be able to resolve
2022-11-28 19:03:14 +01:00
"""
import h5py
from itertools import combinations , zip_longest , product
import matplotlib . pyplot as plt
import numpy as np
2022-12-05 17:48:58 +01:00
from os import path
2023-01-11 02:18:36 +01:00
import os
2022-11-28 19:03:14 +01:00
from scipy . interpolate import interp1d
from earsim import REvent
from atmocal import AtmoCal
import aa_generate_beacon as beacon
import lib
from lib import rit
2023-05-01 18:19:37 +02:00
try :
from tqdm import tqdm
except :
tqdm = lambda x : x
2023-10-31 16:47:45 +01:00
try :
from joblib import Parallel , delayed
except :
Parallel = None
delayed = lambda x : x
def find_best_period_shifts_at_location ( * args , algo = None , * * kwargs ) :
"""
This is a placeholder function .
For args and kwargs see find_best_period_shifts_summing_at_location .
"""
if algo is None :
algo = ' sum '
return find_best_period_shifts_summing_at_location ( * args , * * kwargs , algo = algo )
def find_best_period_shifts_summing_at_location ( test_loc , antennas , allowed_ks , period = 1 , dt = None , period_shift_first_trace = 0 , plot_iteration_with_shifted_trace = None , fig_dir = None , fig_distinguish = None , snr_str = None , shower_plane_loc = None , algo = ' sum ' , verbose = False ) :
2022-11-28 19:03:14 +01:00
"""
Find the best sample_shift for each antenna by summing the antenna traces
and seeing how to get the best alignment .
"""
a_ = [ ]
t_ = [ ]
t_min = 1e9
t_max = - 1e9
2022-12-08 15:22:27 +01:00
a_maxima = [ ]
2022-12-23 11:17:10 +01:00
N_ant = len ( antennas )
2022-11-28 19:03:14 +01:00
2022-11-29 17:04:26 +01:00
if dt is None :
dt = antennas [ 0 ] . t_AxB [ 1 ] - antennas [ 0 ] . t_AxB [ 0 ]
2022-12-23 11:17:10 +01:00
if not hasattr ( plot_iteration_with_shifted_trace , ' __len__ ' ) :
if plot_iteration_with_shifted_trace :
plot_iteration_with_shifted_trace = [ plot_iteration_with_shifted_trace ]
else :
plot_iteration_with_shifted_trace = [ ]
2022-11-28 19:03:14 +01:00
# propagate to test location
for i , ant in enumerate ( antennas ) :
aloc = [ ant . x , ant . y , ant . z ]
delta , dist = atm . light_travel_time ( test_loc , aloc )
delta = delta * 1e9
t__ = np . subtract ( ant . t_AxB , delta )
t_ . append ( t__ )
a_ . append ( ant . E_AxB )
2022-12-08 15:22:27 +01:00
a_maxima . append ( max ( ant . E_AxB ) )
2022-11-28 19:03:14 +01:00
if t__ [ 0 ] < t_min :
t_min = t__ [ 0 ]
if t__ [ - 1 ] > t_max :
t_max = t__ [ - 1 ]
2022-12-08 15:22:27 +01:00
# sort traces with descending maxima
sort_idx = np . argsort ( a_maxima ) [ : : - 1 ]
t_ = [ t_ [ i ] for i in sort_idx ]
a_ = [ a_ [ i ] for i in sort_idx ]
2022-11-28 19:03:14 +01:00
# Interpolate and find best sample shift
2022-12-08 14:41:33 +01:00
max_neg_shift = 0 #np.min(allowed_sample_shifts) * dt
max_pos_shift = 0 #np.max(allowed_sample_shifts) * dt
2022-11-28 19:03:14 +01:00
2022-12-08 14:41:33 +01:00
t_sum = np . arange ( t_min + max_neg_shift , t_max + max_pos_shift , dt )
2022-11-28 19:03:14 +01:00
a_sum = np . zeros ( len ( t_sum ) )
2023-05-01 17:21:56 +02:00
a_first = np . zeros ( len ( t_sum ) )
2022-11-28 19:03:14 +01:00
2023-04-28 17:08:53 +02:00
best_period_shifts = np . zeros ( ( len ( antennas ) ) , dtype = int )
2022-11-28 19:03:14 +01:00
for i , ( t_r , E_ ) in enumerate ( zip ( t_ , a_ ) ) :
f = interp1d ( t_r , E_ , assume_sorted = True , bounds_error = False , fill_value = 0 )
if i == 0 :
2023-04-28 17:08:53 +02:00
best_period_shifts [ i ] = period_shift_first_trace
2023-10-31 16:47:45 +01:00
a_first = f ( t_sum - period_shift_first_trace * period )
a_sum + = a_first
2022-11-28 19:03:14 +01:00
continue
2022-12-05 17:48:58 +01:00
# init figure
2022-12-23 11:17:10 +01:00
if i in plot_iteration_with_shifted_trace :
2023-02-01 14:13:26 +01:00
fig , ax = plt . subplots ( figsize = figsize )
2023-04-28 18:02:27 +02:00
if shower_plane_loc is not None :
title_location = " s( {:.1g} , {:.1g} , {:.1g} ) " . format ( * shower_plane_loc )
else :
title_location = " ( { .1g}, {:.1g} , {:.1g} ) " . format ( * test_loc )
2023-10-31 16:47:45 +01:00
#ax.set_title("Traces at {}; i={i}/{tot}".format(title_location, i=i, tot=N_ant))
2022-12-02 19:09:33 +01:00
ax . set_xlabel ( " Time [ns] " )
ax . set_ylabel ( " Amplitude " )
2023-10-31 16:47:45 +01:00
#ax.plot(t_sum, a_sum)
2022-12-02 19:09:33 +01:00
2023-04-28 18:02:27 +02:00
fig2 , ax2 = plt . subplots ( figsize = figsize )
2023-10-31 16:47:45 +01:00
#ax2.set_title("Maxima at {}; i={i}/{tot}".format(title_location, i=i, tot=N_ant))
2023-04-28 18:02:27 +02:00
ax2 . set_xlabel ( " $k$th Period " )
ax2 . set_ylabel ( " Summed Amplitude " )
2023-10-31 16:47:45 +01:00
ax2 . plot ( 0 , np . max ( a_first ) , marker = ' * ' , label = ' first trace ' , ls = ' none ' , ms = 20 )
ax3 = ax2 . twinx ( )
ax3 . set_ylabel ( " Correlation " )
2023-04-28 18:02:27 +02:00
2023-04-28 17:08:53 +02:00
# find the maxima for each period shift k
shift_maxima = np . zeros ( len ( allowed_ks ) )
2023-10-31 16:47:45 +01:00
shift_corrs = np . zeros_like ( shift_maxima )
2023-04-28 17:08:53 +02:00
for j , k in enumerate ( allowed_ks ) :
2023-10-31 16:47:45 +01:00
augmented_a = f ( t_sum - k * period )
2022-11-28 19:03:14 +01:00
2023-05-01 17:21:56 +02:00
shift_maxima [ j ] = np . max ( augmented_a + a_first )
2023-10-31 16:47:45 +01:00
shift_corrs [ j ] = np . dot ( augmented_a , a_first )
2022-11-28 19:03:14 +01:00
2023-04-28 17:08:53 +02:00
if i in plot_iteration_with_shifted_trace and abs ( k ) < = 3 :
2023-10-31 16:47:45 +01:00
l = ax . plot ( t_sum , a_first + augmented_a , alpha = 0.7 , ls = ' dashed ' , label = f ' { k : g } ' )
ax . axhline ( shift_maxima [ j ] , ls = ' dashdot ' , color = l [ 0 ] . get_color ( ) , alpha = 0.7 )
2023-04-28 18:02:27 +02:00
ax2 . plot ( k , shift_maxima [ j ] , marker = ' o ' , ls = ' none ' , ms = 20 )
2023-10-31 16:47:45 +01:00
ax3 . plot ( k , shift_corrs [ j ] , marker = ' 3 ' , ls = ' none ' , ms = 20 )
2022-12-02 19:09:33 +01:00
2022-11-28 19:03:14 +01:00
# transform maximum into best_sample_shift
best_idx = np . argmax ( shift_maxima )
2023-10-31 16:47:45 +01:00
best_corr_idx = np . argmax ( shift_corrs )
2022-12-23 11:17:10 +01:00
2023-10-31 16:47:45 +01:00
if verbose and ( best_corr_idx != best_idx ) :
print ( " Correlation idx not equal to maximum idx " )
print ( best_corr_idx , best_idx )
if algo == ' sum ' :
best_period_shifts [ i ] = allowed_ks [ best_idx ]
elif algo == ' corr ' :
best_period_shifts [ i ] = allowed_ks [ best_corr_idx ]
k = best_period_shifts [ i ]
best_augmented_a = f ( t_sum - k * period )
2022-12-23 12:27:25 +01:00
a_sum + = best_augmented_a
2022-11-28 19:03:14 +01:00
2022-12-05 17:48:58 +01:00
# cleanup figure
2022-12-23 11:17:10 +01:00
if i in plot_iteration_with_shifted_trace :
2023-04-28 18:02:27 +02:00
# plot the traces
2022-12-23 12:27:25 +01:00
if True : # plot best k again
2023-10-31 16:47:45 +01:00
l = ax . plot ( t_sum , a_first + best_augmented_a , alpha = 0.8 , label = f ' best $k$= { best_period_shifts [ i ] : g } ' , lw = 2 )
ax . axhline ( shift_maxima [ j ] , ls = ' dashdot ' , color = l [ 0 ] . get_color ( ) , alpha = 0.7 )
2022-12-23 12:27:25 +01:00
2023-04-28 18:02:27 +02:00
if True : # plot best shift
ax2 . plot ( allowed_ks [ best_idx ] , shift_maxima [ best_idx ] , marker = ' * ' , ls = ' none ' , ms = 20 , label = f ' best $k$= { best_period_shifts [ i ] : g } ' )
2023-10-31 16:47:45 +01:00
ax3 . plot ( allowed_ks [ best_corr_idx ] , shift_maxima [ best_idx ] , marker = ' * ' , ls = ' none ' , ms = 20 , label = f ' best corr $k$= { allowed_ks [ best_corr_idx ] : g } ' )
2023-04-28 18:02:27 +02:00
2023-10-31 16:47:45 +01:00
ax . legend ( title = ' period shift $k$; ' + snr_str , ncol = 5 , loc = ' lower center ' )
2023-04-28 18:02:27 +02:00
ax2 . legend ( title = snr_str )
2023-10-31 16:47:45 +01:00
ax3 . legend ( )
2022-12-23 11:17:10 +01:00
if fig_dir :
2022-12-23 12:27:25 +01:00
fig . tight_layout ( )
2023-04-28 18:02:27 +02:00
fig2 . tight_layout ( )
if shower_plane_loc is not None :
fname_location = ' .sloc {:.1g} - {:.1g} - {:.1g} ' . format ( * shower_plane_loc )
else :
fname_location = ' .loc {:.1f} - {:.1f} - {:.1f} ' . format ( * test_loc )
fname = path . join ( fig_dir , path . basename ( __file__ ) + f ' . { fig_distinguish } i { i } ' + fname_location )
2022-12-23 11:17:10 +01:00
if True :
old_xlim = ax . get_xlim ( )
if True : # zoomed on part without peak of this trace
2023-10-31 16:47:45 +01:00
wx = 200
2022-12-23 11:17:10 +01:00
x = max ( t_r ) - wx
ax . set_xlim ( x - wx , x + wx )
fig . savefig ( fname + " .zoomed.beacon.pdf " )
if True : # zoomed on peak of this trace
2023-10-31 16:47:45 +01:00
x = t_sum [ np . argmax ( a_first ) ]
x = t_sum [ np . argmax ( f ( t_sum ) ) ]
wx = 50 + ( max ( best_period_shifts ) - min ( best_period_shifts ) ) * dt + 1 * period
2022-12-23 11:17:10 +01:00
ax . set_xlim ( x - wx , x + wx )
fig . savefig ( fname + " .zoomed.peak.pdf " )
ax . set_xlim ( * old_xlim )
fig . savefig ( fname + " .pdf " )
2023-04-28 18:02:27 +02:00
fig2 . savefig ( fname + " .maxima.pdf " )
2022-12-05 17:48:58 +01:00
plt . close ( fig )
2023-04-28 18:02:27 +02:00
plt . close ( fig2 )
2022-12-05 17:48:58 +01:00
2023-10-31 16:47:45 +01:00
if True : # final summed waveform
fig , ax = plt . subplots ( )
ax . set_title ( " Summed Traces with best k ' s at {} " . format ( title_location ) )
ax . set_xlabel ( " Time [ns] " )
ax . set_ylabel ( " Amplitude " )
ax . plot ( t_sum , a_sum )
if fig_dir :
fig . tight_layout ( )
fname = path . join ( fig_dir , path . basename ( __file__ ) + f ' . { fig_distinguish } i { i } ' + fname_location )
fig . savefig ( fname + " .sum.pdf " )
plt . close ( fig )
2022-12-08 15:22:27 +01:00
# sort by antenna (undo sorting by maximum)
undo_sort_idx = np . argsort ( sort_idx )
2023-04-28 17:08:53 +02:00
best_period_shifts = best_period_shifts [ undo_sort_idx ]
2022-12-08 15:22:27 +01:00
2022-11-28 19:03:14 +01:00
# Return ks
2023-10-31 16:47:45 +01:00
return best_period_shifts , np . max ( a_sum ) , sort_idx
2022-11-28 19:03:14 +01:00
if __name__ == " __main__ " :
import sys
2022-12-08 14:41:33 +01:00
import os
2022-12-05 17:48:58 +01:00
import matplotlib
2022-12-08 14:41:33 +01:00
if os . name == ' posix ' and " DISPLAY " not in os . environ :
matplotlib . use ( ' Agg ' )
2022-11-28 19:03:14 +01:00
2023-05-01 18:19:37 +02:00
plt . rcParams . update ( { ' figure.max_open_warning ' : 0 } )
2022-11-28 19:03:14 +01:00
atm = AtmoCal ( )
2023-01-12 14:31:21 +01:00
from scriptlib import MyArgumentParser
2023-01-12 14:49:54 +01:00
parser = MyArgumentParser ( default_fig_dir = " ./figures/periods_from_shower_figures/ " )
2023-02-02 19:27:01 +01:00
parser . add_argument ( ' --quick_run ' , action = ' store_true ' , help = ' Use a very coarse grid (6x6) ' )
2023-06-29 11:09:20 +02:00
parser . add_argument ( ' -X ' , type = int , default = 400 , help = ' Atmospheric depth to start the initial grid. ' )
2023-02-02 19:27:01 +01:00
2023-01-24 15:21:47 +01:00
parser . add_argument ( ' --max-k ' , type = float , default = 2 , help = ' Maximum abs(k) allowed to be shifted. (Default: %(default)d ) ' )
2023-02-02 19:27:01 +01:00
parser . add_argument ( ' -N ' , ' --N_runs ' , type = int , default = 5 , help = ' Maximum amount of iterations to grid search. (Default: %(default)d ) ' )
parser . add_argument ( ' -l ' , ' --passband-low ' , type = float , default = 30e-3 , help = ' Lower frequency [GHz] of the passband filter. (set -1 for np.inf) (Default: %(default)g ) ' )
parser . add_argument ( ' -u ' , ' --passband-high ' , type = float , default = 80e-3 , help = ' Upper frequency [GHz] of the passband filter. (set -1 for np.inf) (Default: %(default)g ) ' )
2023-02-02 17:55:37 +01:00
parser . add_argument ( ' --input-fname ' , type = str , default = None , help = ' Path to mysim.sry, either directory or path. If empty it takes DATA_DIR and appends mysim.sry. (Default: %(default)s ) ' )
2023-01-12 14:31:21 +01:00
args = parser . parse_args ( )
2023-02-02 17:55:37 +01:00
if not args . input_fname :
args . input_fname = args . data_dir
if path . isdir ( args . input_fname ) :
args . input_fname = path . join ( args . input_fname , " mysim.sry " )
2023-10-31 16:47:45 +01:00
figsize = ( 6 , 4 )
if True :
from matplotlib import rcParams
#rcParams["text.usetex"] = True
rcParams [ " font.family " ] = " serif "
rcParams [ " font.size " ] = " 14 "
rcParams [ " grid.linestyle " ] = ' dotted '
rcParams [ " figure.figsize " ] = figsize
figsize = rcParams [ ' figure.figsize ' ]
2022-11-28 19:03:14 +01:00
2023-01-12 14:49:54 +01:00
fig_dir = args . fig_dir
2022-12-05 17:48:58 +01:00
fig_subdir = path . join ( fig_dir , ' shifts/ ' )
2023-01-12 14:31:21 +01:00
show_plots = args . show_plots
2022-12-02 19:09:33 +01:00
2023-01-24 15:21:47 +01:00
max_k = int ( args . max_k )
allowed_ks = np . arange ( - max_k , max_k + 1 , dtype = int )
2023-06-29 11:09:20 +02:00
Xref = args . X
2022-11-29 17:04:26 +01:00
2023-02-02 19:27:01 +01:00
N_runs = args . N_runs
2023-01-10 14:45:28 +01:00
remove_beacon_from_trace = True
2023-01-30 10:18:16 +01:00
apply_signal_window_from_max = True
2022-12-02 19:09:33 +01:00
2023-02-02 19:27:01 +01:00
low_bp = args . passband_low if args . passband_low > = 0 else np . inf # GHz
high_bp = args . passband_high if args . passband_high > = 0 else np . inf # GHz
2022-11-28 19:03:14 +01:00
####
2023-02-02 17:55:37 +01:00
fname_dir = args . data_dir
2022-11-28 19:03:14 +01:00
antennas_fname = path . join ( fname_dir , beacon . antennas_fname )
time_diffs_fname = ' time_diffs.hdf5 ' if not True else antennas_fname
2023-02-03 15:13:44 +01:00
tx_fname = path . join ( fname_dir , beacon . tx_fname )
2023-04-13 15:04:45 +02:00
beacon_snr_fname = path . join ( fname_dir , beacon . beacon_snr_fname )
2022-11-28 19:03:14 +01:00
2023-01-11 02:18:36 +01:00
## This is a file indicating whether the k-finding algorithm was
## stopped early. This happens when the ks do not change between
## two consecutive iterations.
run_break_fname = path . join ( fname_dir , ' ca_breaked_run ' )
2022-12-23 11:13:53 +01:00
# create fig_dir
if fig_dir :
os . makedirs ( fig_dir , exist_ok = True )
if fig_subdir :
os . makedirs ( fig_subdir , exist_ok = True )
2022-11-28 19:03:14 +01:00
# Read in antennas from file
2022-12-23 12:28:33 +01:00
_ , tx , antennas = beacon . read_beacon_hdf5 ( antennas_fname )
2023-02-03 15:13:44 +01:00
_ , __ , txdata = beacon . read_tx_file ( tx_fname )
2022-11-28 19:03:14 +01:00
# Read original REvent
2023-02-02 17:55:37 +01:00
ev = REvent ( args . input_fname )
2022-11-28 19:03:14 +01:00
# .. patch in our antennas
ev . antennas = antennas
2023-04-12 22:42:59 +02:00
# read in snr information
2023-04-13 15:04:45 +02:00
beacon_snrs = beacon . read_snr_file ( beacon_snr_fname )
2023-10-31 16:47:45 +01:00
snr_str = f " $ \\ langle SNR \\ rangle$ = { beacon_snrs [ ' mean ' ] : .2g } "
2022-11-28 19:03:14 +01:00
# For now only implement using one freq_name
freq_names = antennas [ 0 ] . beacon_info . keys ( )
if len ( freq_names ) > 1 :
raise NotImplementedError
freq_name = next ( iter ( freq_names ) )
f_beacon = ev . antennas [ 0 ] . beacon_info [ freq_name ] [ ' freq ' ]
2023-01-30 10:18:16 +01:00
##
## Manipulate time and traces of each antenna
##
### Remove time due to true phase
### and optionally remove the beacon
2023-02-03 15:13:44 +01:00
### Note: there is no use in changing *_AxB variables here (except for plotting),
### they're recomputed by the upcoming rit.set_pol_and_bp call.
2023-01-16 19:42:21 +01:00
measured_repair_offsets = beacon . read_antenna_clock_repair_offsets ( ev . antennas , mode = ' phases ' , freq_name = freq_name )
2022-11-28 19:03:14 +01:00
for i , ant in enumerate ( ev . antennas ) :
2023-02-03 15:13:44 +01:00
ev . antennas [ i ] . orig_t = ev . antennas [ i ] . t
ev . antennas [ i ] . t + = measured_repair_offsets [ i ]
# t_AxB will be set by the rit.set_pol_and_bp function
2023-01-16 19:42:21 +01:00
ev . antennas [ i ] . t_AxB + = measured_repair_offsets [ i ]
2022-12-23 11:13:53 +01:00
2023-01-30 10:18:16 +01:00
if apply_signal_window_from_max :
2023-01-30 13:54:48 +01:00
N_pre , N_post = 250 , 250 # TODO: make this configurable
2023-01-30 10:18:16 +01:00
2023-02-03 15:13:44 +01:00
# Get max idx from all the traces
# and select the strongest
max_idx = [ ]
maxs = [ ]
2023-01-30 10:18:16 +01:00
2023-02-03 15:13:44 +01:00
for trace in [ ant . Ex , ant . Ey , ant . Ez ] :
idx = np . argmax ( np . abs ( trace ) )
max_idx . append ( idx )
maxs . append ( np . abs ( trace [ idx ] ) )
idx = np . argmax ( maxs )
max_idx = max_idx [ idx ]
# Create window around max_idx
2023-01-30 10:18:16 +01:00
low_idx = max ( 0 , max_idx - N_pre )
high_idx = min ( len ( ant . t ) , max_idx + N_post )
ev . antennas [ i ] . orig_t = ant . orig_t [ low_idx : high_idx ]
ev . antennas [ i ] . t = ant . t [ low_idx : high_idx ]
ev . antennas [ i ] . Ex = ant . Ex [ low_idx : high_idx ]
ev . antennas [ i ] . Ey = ant . Ey [ low_idx : high_idx ]
ev . antennas [ i ] . Ez = ant . Ez [ low_idx : high_idx ]
2023-02-03 15:13:44 +01:00
ev . antennas [ i ] . t_AxB = ant . t_AxB [ low_idx : high_idx ]
ev . antennas [ i ] . E_AxB = ant . E_AxB [ low_idx : high_idx ]
2023-01-30 10:18:16 +01:00
2023-02-03 15:13:44 +01:00
# .. and remove the beacon from the traces
# Note: ant.E_AxB is recalculated by rit.set_pol_and_bp
2023-01-09 16:55:34 +01:00
if remove_beacon_from_trace :
2023-01-16 19:42:21 +01:00
clock_phase = measured_repair_offsets [ i ] * 2 * np . pi * f_beacon
2023-01-17 18:17:12 +01:00
beacon_phase = ant . beacon_info [ freq_name ] [ ' beacon_phase ' ]
2022-12-23 11:13:53 +01:00
f = ant . beacon_info [ freq_name ] [ ' freq ' ]
ampl = ant . beacon_info [ freq_name ] [ ' amplitude ' ]
2023-02-03 15:13:44 +01:00
calc_beacon = lib . sine_beacon ( f , ev . antennas [ i ] . t , amplitude = ampl , phase = beacon_phase - clock_phase )
tx_amps = txdata [ ' amplitudes ' ]
tx_amps_sum = np . sum ( tx_amps )
# Split up contribution to the various polarisations
for j , amp in enumerate ( tx_amps ) :
if j == 0 :
ev . antennas [ i ] . Ex - = amp * ( 1 / tx_amps_sum ) * calc_beacon
elif j == 1 :
ev . antennas [ i ] . Ey - = amp * ( 1 / tx_amps_sum ) * calc_beacon
elif j == 2 :
ev . antennas [ i ] . Ez - = amp * ( 1 / tx_amps_sum ) * calc_beacon
# Subtract the beacon from E_AxB
2022-12-23 11:13:53 +01:00
ev . antennas [ i ] . E_AxB - = calc_beacon
# Make a figure of the manipulated traces
2023-02-03 15:13:44 +01:00
if i == 72 :
2022-12-23 11:13:53 +01:00
orig_beacon_amplifier = ampl / max ( ant . beacon )
2023-02-01 14:13:26 +01:00
fig , ax = plt . subplots ( figsize = figsize )
2023-02-03 15:13:44 +01:00
ax . set_title ( f " Signal and Beacon traces Antenna { ant . name } " )
2022-12-23 11:13:53 +01:00
ax . set_xlabel ( " Time [ns] " )
ax . set_ylabel ( " Amplitude [$ \\ mu V/m$] " )
ax . plot ( ant . t_AxB , ant . E_AxB + calc_beacon , alpha = 0.6 , ls = ' dashed ' , label = ' Signal ' ) # calc_beacon was already removed
ax . plot ( ant . t_AxB , calc_beacon , alpha = 0.6 , ls = ' dashed ' , label = ' Calc Beacon ' )
ax . plot ( ant . t_AxB , ant . E_AxB , alpha = 0.6 , label = " Signal - Calc Beacon " )
2023-04-12 22:42:59 +02:00
ax . legend ( title = snr_str )
2022-12-23 11:13:53 +01:00
# save
if fig_dir :
fig . tight_layout ( )
2023-01-16 18:40:59 +01:00
2022-12-23 11:13:53 +01:00
if True : # zoom
old_xlim = ax . get_xlim ( )
2023-10-31 16:47:45 +01:00
if not True : # zoomed on part without peak of this trace
wx , x = 100 , min ( ant . t_AxB )
2023-02-03 15:13:44 +01:00
ax . set_xlim ( x - 5 , x + wx )
2023-01-16 18:40:59 +01:00
2023-04-28 18:22:59 +02:00
fig . savefig ( path . join ( fig_dir , path . basename ( __file__ ) + f ' .traces.A { ant . name } .zoomed.beacon.pdf ' ) )
2022-12-23 11:13:53 +01:00
2023-01-16 18:40:59 +01:00
if True : # zoomed on peak of this trace
idx = np . argmax ( ev . antennas [ i ] . E_AxB )
x = ev . antennas [ i ] . t_AxB [ idx ]
2023-10-31 16:47:45 +01:00
wx = 150
2023-02-03 15:13:44 +01:00
ax . set_xlim ( x - wx / / 2 , x + wx / / 2 )
2023-04-28 18:22:59 +02:00
fig . savefig ( path . join ( fig_dir , path . basename ( __file__ ) + f " .traces.A { ant . name } .zoomed.peak.pdf " ) )
2022-12-23 11:13:53 +01:00
ax . set_xlim ( * old_xlim )
2023-04-28 18:22:59 +02:00
fig . savefig ( path . join ( fig_dir , path . basename ( __file__ ) + f ' .traces.A { ant . name } .pdf ' ) )
2022-12-23 11:13:53 +01:00
if show_plots :
plt . show ( )
2022-11-28 19:03:14 +01:00
2023-02-03 15:13:44 +01:00
# Prepare polarisation and passbands
rit . set_pol_and_bp ( ev , low = low_bp , high = high_bp )
2022-11-28 19:03:14 +01:00
2023-01-10 14:45:28 +01:00
# determine allowable ks per location
dt = ev . antennas [ 0 ] . t_AxB [ 1 ] - ev . antennas [ 0 ] . t_AxB [ 0 ]
2023-04-28 16:37:35 +02:00
print ( " Checking k: " , allowed_ks )
2023-01-10 14:45:28 +01:00
2023-01-09 16:09:17 +01:00
##
## Determine grid positions
##
2023-10-31 16:47:45 +01:00
zgr = 0 + ev . core [ 2 ]
dXref = atm . distance_to_slant_depth ( np . deg2rad ( ev . zenith ) , Xref , zgr )
2022-11-28 19:03:14 +01:00
scale2d = dXref * np . tan ( np . deg2rad ( 2. ) )
2023-01-09 16:09:17 +01:00
scale4d = dXref * np . tan ( np . deg2rad ( 4. ) )
2023-02-02 19:27:01 +01:00
if args . quick_run : #quicky
2023-10-31 16:47:45 +01:00
x_coarse = np . linspace ( - scale4d , scale4d , 16 )
y_coarse = np . linspace ( - scale4d , scale4d , 16 )
2023-01-09 16:09:17 +01:00
x_fine = x_coarse / 4
y_fine = y_coarse / 4
else : # long
2023-10-31 16:47:45 +01:00
x_coarse = np . linspace ( - scale4d , scale4d , 14 )
y_coarse = np . linspace ( - scale4d , scale4d , 14 )
2023-01-09 16:09:17 +01:00
2023-10-31 16:47:45 +01:00
x_fine = np . linspace ( - scale2d , scale2d , 18 )
y_fine = np . linspace ( - scale2d , scale2d , 18 )
2023-01-09 16:09:17 +01:00
2023-01-11 02:18:36 +01:00
## Remove run_break_fname if it exists
try :
os . remove ( run_break_fname )
except OSError :
pass
2023-01-09 16:09:17 +01:00
##
## Do calculations on the grid
##
2022-11-28 19:03:14 +01:00
2022-12-02 19:09:33 +01:00
for r in range ( N_runs ) :
2023-01-09 16:09:17 +01:00
# Setup Plane grid to test
2022-11-28 19:03:14 +01:00
if r == 0 :
2023-01-16 18:40:59 +01:00
xoff , yoff = 0 , 0
2022-11-28 19:03:14 +01:00
x = x_coarse
y = y_coarse
else :
2023-01-09 16:09:17 +01:00
# zooming in
2023-01-16 18:40:59 +01:00
# best_idx is defined at the end of the loop
2022-12-02 19:09:33 +01:00
old_ks_per_loc = ks_per_loc [ best_idx ]
2023-01-16 18:40:59 +01:00
xoff , yoff = locs [ best_idx ]
2022-11-29 17:04:26 +01:00
if r == 1 :
x = x_fine
y = y_fine
else :
x / = 4
y / = 4
2022-11-28 19:03:14 +01:00
2023-06-29 11:09:20 +02:00
print ( f " Testing grid run { r } centered on ( { xoff } , { yoff } ) at X= { Xref } . " )
2022-11-28 19:03:14 +01:00
2022-11-29 17:04:26 +01:00
ks_per_loc = np . zeros ( ( len ( x ) * len ( y ) , len ( ev . antennas ) ) , dtype = int )
2022-11-28 19:03:14 +01:00
maxima_per_loc = np . zeros ( ( len ( x ) * len ( y ) ) )
2022-11-29 17:04:26 +01:00
2022-11-28 19:03:14 +01:00
## Check each location on grid
xx = [ ]
yy = [ ]
N_loc = len ( maxima_per_loc )
2022-12-05 17:48:58 +01:00
2023-10-31 16:47:45 +01:00
# Make the grid a list of locations
xx = [ ]
yy = [ ]
for i , ( x_ , y_ ) in enumerate ( product ( x , y ) ) :
xx . append ( x_ + xoff )
yy . append ( y_ + yoff )
xx = np . array ( xx )
yy = np . array ( yy )
locs = list ( zip ( xx , yy ) )
# Shift the reference trace
if r == 0 :
first_trace_period_shift = 0
else :
first_trace_period_shift = 0 #first_trace_period_shift + np.rint(np.mean(old_ks_per_loc))
print ( " New first trace period: " , first_trace_period_shift )
# define loop func for joblib
def loop_func ( loc , dXref = dXref , i = 1 ) :
2022-12-05 17:48:58 +01:00
tmp_fig_subdir = None
2023-10-31 16:47:45 +01:00
if i == 0 :
2023-05-01 18:19:37 +02:00
if hasattr ( tqdm , ' __code__ ' ) and tqdm . __code__ . co - name == ' <lambda> ' :
print ( f " Testing location { i } out of { N_loc } " )
2022-12-05 17:48:58 +01:00
tmp_fig_subdir = fig_subdir
2023-06-29 11:09:20 +02:00
test_loc = loc [ 0 ] * ev . uAxB + loc [ 1 ] * ev . uAxAxB + dXref * ev . uA
2022-11-29 17:04:26 +01:00
2022-11-28 19:03:14 +01:00
# Find best k for each antenna
2023-10-31 16:47:45 +01:00
return find_best_period_shifts_at_location ( test_loc , ev . antennas , allowed_ks , period = 1 / f_beacon , dt = dt , period_shift_first_trace = first_trace_period_shift ,
plot_iteration_with_shifted_trace = [ 1 , 2 , 3 , 4 , 5 , len ( ev . antennas ) - 1 ] ,
fig_dir = tmp_fig_subdir , fig_distinguish = f " X { Xref } .run { r } . " ,
2023-06-29 11:09:20 +02:00
snr_str = snr_str , shower_plane_loc = ( loc [ 0 ] / 1e3 , loc [ 1 ] / 1e3 , dXref ) ,
)
2022-11-29 17:04:26 +01:00
2023-10-31 16:47:45 +01:00
res = ( delayed ( loop_func ) ( loc , i = i ) for i , loc in enumerate ( locs ) )
if Parallel :
res = Parallel ( n_jobs = None ) ( tqdm ( res , total = len ( locs ) ) )
else :
res = tqdm ( res , total = len ( locs ) )
# unpack loop results
ks_per_loc , maxima_per_loc , sort_idx = zip ( * res )
2022-12-02 19:09:33 +01:00
## Save maxima to file
2023-06-29 11:09:20 +02:00
np . savetxt ( path . join ( fig_dir , path . basename ( __file__ ) + f ' .maxima.X { Xref } .run { r } .txt ' ) , np . column_stack ( ( locs , maxima_per_loc , ks_per_loc ) ) )
2022-12-02 19:09:33 +01:00
2023-10-31 16:47:45 +01:00
scatter_kwargs = dict ( cmap = ' Spectral_r ' , s = 64 * 4 , alpha = 0.6 )
2022-11-28 19:03:14 +01:00
if True : #plot maximum at test locations
2023-02-01 14:13:26 +01:00
fig , axs = plt . subplots ( figsize = figsize )
2023-10-31 16:47:45 +01:00
#axs.set_title(f"Optimizing signal strength by varying $k$ per antenna,\n Grid Run {r}")
axs . set_ylabel ( " vxvxB [km] " )
axs . set_xlabel ( " -v x B [km] " )
2023-01-09 11:51:03 +01:00
axs . set_aspect ( ' equal ' , ' datalim ' )
2023-10-31 16:47:45 +01:00
sc = axs . scatter ( xx / 1e3 , yy / 1e3 , c = maxima_per_loc , * * scatter_kwargs )
2023-01-11 02:20:06 +01:00
fig . colorbar ( sc , ax = axs , label = ' Max Amplitude [$ \\ mu V/m$] ' )
2023-10-31 16:47:45 +01:00
#axs.legend(title=snr_str)
2023-04-12 22:42:59 +02:00
2023-01-11 02:20:06 +01:00
# indicate maximum value
idx = np . argmax ( maxima_per_loc )
2023-10-31 16:47:45 +01:00
axs . plot ( xx [ idx ] / 1e3 , yy [ idx ] / 1e3 , ' bx ' , ms = 30 ) # max value
axs . plot ( 0 , 0 , ' r+ ' , ms = 30 ) # true axis
2022-11-28 19:03:14 +01:00
2022-12-05 17:48:58 +01:00
if fig_dir :
2023-01-09 11:51:03 +01:00
old_xlims = axs . get_xlim ( )
old_ylims = axs . get_ylim ( )
2022-12-23 12:28:33 +01:00
fig . tight_layout ( )
2023-06-29 11:09:20 +02:00
fig . savefig ( path . join ( fig_dir , path . basename ( __file__ ) + f ' .maxima.X { Xref } .run { r } .pdf ' ) )
2023-01-11 02:20:06 +01:00
if False :
2022-12-23 12:28:33 +01:00
axs . plot ( tx . x / 1e3 , tx . y / 1e3 , marker = ' X ' , color = ' k ' )
fig . tight_layout ( )
2023-06-29 11:09:20 +02:00
fig . savefig ( path . join ( fig_dir , path . basename ( __file__ ) + f ' .maxima.X { Xref } .run { r } .with_tx.pdf ' ) )
2023-01-09 11:51:03 +01:00
axs . set_xlim ( * old_xlims )
axs . set_ylim ( * old_ylims )
fig . tight_layout ( )
2022-11-29 17:04:26 +01:00
2023-01-09 16:09:17 +01:00
##
2022-11-29 17:04:26 +01:00
best_idx = np . argmax ( maxima_per_loc )
2023-01-09 16:09:17 +01:00
best_k = ks_per_loc [ best_idx ]
2023-10-31 16:47:45 +01:00
print ( " Max at location: " , locs [ best_idx ] , " : " , maxima_per_loc [ best_idx ] )
print ( ' Best k: ' , best_k [ sort_idx [ best_idx ] ] ) # Sorted by DESC amplitude
print ( ' Mean best k: ' , np . rint ( np . mean ( best_k ) ) )
print ( ' first k: ' , first_trace_period_shift )
2023-01-09 16:09:17 +01:00
## Save best ks to file
2023-06-29 11:09:20 +02:00
np . savetxt ( path . join ( fig_dir , path . basename ( __file__ ) + f ' .bestk.X { Xref } .run { r } .txt ' ) , best_k )
2023-01-09 16:09:17 +01:00
## Do a small reconstruction of the shower for best ks
if True :
print ( " Reconstructing for best k " )
2023-01-11 02:20:06 +01:00
for j in range ( 2 ) :
power_reconstruction = j == 1
if power_reconstruction : # Do power reconstruction
# backup antenna times
backup_times = [ ant . t_AxB for ant in ev . antennas ]
# incorporate ks into timing
for i , ant in enumerate ( ev . antennas ) :
2023-10-31 16:47:45 +01:00
ev . antennas [ i ] . t_AxB = ant . t_AxB + best_k [ i ] * 1 / f_beacon
2023-01-11 02:20:06 +01:00
2023-10-31 16:47:45 +01:00
xx , yy , p , ___ = rit . shower_plane_slice ( ev , X = Xref , Nx = len ( x ) , Ny = len ( y ) , wx = ( x [ - 1 ] - x [ 0 ] ) / 2 , wy = ( y [ - 1 ] - y [ 0 ] ) / 2 , xoff = xoff , yoff = yoff , zgr = 0 )
2023-01-11 02:20:06 +01:00
# repair antenna times
for i , backup_t_AxB in enumerate ( backup_times ) :
ev . antennas [ i ] . t_AxB = backup_t_AxB
else : # get maximum amplitude at each location
maxima = np . empty ( len ( locs ) )
2023-10-31 16:47:45 +01:00
for i , loc in tqdm ( enumerate ( locs ) , total = len ( locs ) ) :
2023-01-11 02:20:06 +01:00
test_loc = loc [ 0 ] * ev . uAxB + loc [ 1 ] * ev . uAxAxB + dXref * ev . uA
P , t_ , a_ , a_sum , t_sum = rit . pow_and_time ( test_loc , ev , dt = dt )
maxima [ i ] = np . max ( a_sum )
2023-02-01 14:13:26 +01:00
fig , axs = plt . subplots ( figsize = figsize )
2023-10-31 16:47:45 +01:00
#axs.set_title(f"Shower slice for best k, Grid Run {r}")
axs . set_ylabel ( " vxvxB [km] " )
axs . set_xlabel ( " -v x B [km] " )
2023-01-11 02:20:06 +01:00
if power_reconstruction :
2023-10-31 16:47:45 +01:00
sc_c = p
sc_label = ' Power [$( \\ mu V/m)^2$] '
2023-01-11 02:20:06 +01:00
else :
2023-10-31 16:47:45 +01:00
sc_c = maxima
sc_label = ' Max Amplitude [$ \\ mu V/m$] '
sc = axs . scatter ( xx / 1e3 , yy / 1e3 , c = sc_c , * * scatter_kwargs )
fig . colorbar ( sc , ax = axs , label = sc_label )
# indicate maximum value
idx = np . argmax ( p if power_reconstruction else maxima )
axs . plot ( xx [ idx ] / 1e3 , yy [ idx ] / 1e3 , ' bx ' , ms = 30 ) # max value
axs . plot ( 0 , 0 , ' r+ ' , ms = 30 ) # true axis
# make square figure
axs . set_aspect ( ' equal ' , ' datalim ' )
2023-01-09 16:09:17 +01:00
2023-10-31 16:47:45 +01:00
#axs.legend(title=snr_str)
2023-01-11 02:20:06 +01:00
if fig_dir :
if power_reconstruction :
fname_extra = " power "
else :
fname_extra = " max_amp "
fig . tight_layout ( )
2023-06-29 11:09:20 +02:00
fig . savefig ( path . join ( fig_dir , path . basename ( __file__ ) + f ' .reconstruction.X { Xref } .run { r } . { fname_extra } .pdf ' ) )
2022-11-29 17:04:26 +01:00
# Abort if no improvement
2023-10-31 16:47:45 +01:00
if ( r != 0 and ( old_ks_per_loc == ks_per_loc [ best_idx ] - first_trace_period_shift ) . all ( ) ) :
2023-01-11 18:33:56 +01:00
print ( f " No changes from previous grid, breaking at iteration { r } out of { N_runs } " )
2023-01-11 02:18:36 +01:00
try :
with open ( run_break_fname , ' wt ' , encoding = ' utf-8 ' ) as fp :
fp . write ( f " Breaked at grid iteration { r } out of { N_runs } " )
except :
pass
2022-11-29 17:04:26 +01:00
break
2023-01-09 11:51:03 +01:00
old_ks_per_loc = ks_per_loc [ best_idx ]
2022-11-29 17:04:26 +01:00
# Save best ks to hdf5 antenna file
with h5py . File ( antennas_fname , ' a ' ) as fp :
group = fp . require_group ( ' antennas ' )
for i , ant in enumerate ( antennas ) :
h5ant = group [ ant . name ]
2023-01-09 11:51:03 +01:00
h5beacon_info = h5ant [ ' beacon_info ' ]
# find out freq_name
if freq_name is None :
freq_name = [ k for k in h5beacon_info . keys ( ) if np . isclose ( h5beacon_info [ k ] . attrs [ ' freq ' ] , f_beacon ) ] [ 0 ]
h5attrs = h5beacon_info [ freq_name ] . attrs
h5attrs [ ' best_k ' ] = old_ks_per_loc [ i ]
2023-01-24 15:21:47 +01:00
h5attrs [ ' best_k_time ' ] = old_ks_per_loc [ i ] / f_beacon
2022-11-29 17:04:26 +01:00
2023-01-09 16:09:17 +01:00
if show_plots :
plt . show ( )