2022-12-02 19:07:46 +01:00
#!/usr/bin/env python3
# vim: fdm=indent ts=4
import h5py
2022-12-22 12:07:51 +01:00
from itertools import combinations , product
2022-12-02 19:07:46 +01:00
import matplotlib . pyplot as plt
import numpy as np
import aa_generate_beacon as beacon
import lib
2023-02-07 17:58:45 +01:00
from lib import figlib
2022-12-02 19:07:46 +01:00
if __name__ == " __main__ " :
from os import path
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-12-05 17:48:58 +01:00
2023-01-12 14:31:21 +01:00
from scriptlib import MyArgumentParser
parser = MyArgumentParser ( )
2023-02-02 14:57:55 +01:00
parser . add_argument ( ' ref_ant_idx ' , default = None , nargs = ' * ' , type = int , help = ' Reference Antenna Indices for Baselines(ref_ant_idx, *). Leave empty to use all available antennas. (Default: %(default)s ) ' )
2023-01-12 14:31:21 +01:00
args = parser . parse_args ( )
2023-02-02 08:57:03 +01:00
figsize = ( 12 , 8 )
2022-12-02 19:07:46 +01:00
c_light = 3e8 * 1e-9
2023-01-12 14:31:21 +01:00
show_plots = args . show_plots
2023-02-02 14:57:55 +01:00
ref_ant_id = args . ref_ant_idx # leave None for all baselines
2022-12-02 19:07:46 +01:00
####
2023-02-02 17:55:37 +01:00
fname_dir = args . data_dir
2022-12-02 19:07:46 +01:00
antennas_fname = path . join ( fname_dir , beacon . antennas_fname )
2022-12-21 17:24:44 +01:00
time_diffs_fname = ' time_diffs.hdf5 ' if False else antennas_fname
2023-04-13 15:04:45 +02:00
beacon_snr_fname = path . join ( fname_dir , beacon . beacon_snr_fname )
2022-12-02 19:07:46 +01:00
2023-01-12 14:49:54 +01:00
fig_dir = args . fig_dir # set None to disable saving
2022-12-05 17:48:58 +01:00
2022-12-02 19:07:46 +01:00
if not path . isfile ( antennas_fname ) :
print ( " Antenna file cannot be found, did you try generating a beacon? " )
sys . exit ( 1 )
# Read in antennas from file
f_beacon , tx , antennas = beacon . read_beacon_hdf5 ( antennas_fname )
# run over all baselines
2023-02-02 14:57:55 +01:00
if not ref_ant_id :
2022-12-02 19:07:46 +01:00
print ( " Doing all baselines " )
2023-02-02 14:57:55 +01:00
baselines = combinations ( antennas , 2 )
2022-12-02 19:07:46 +01:00
# use ref_ant
else :
2022-12-22 12:07:51 +01:00
ref_ants = [ antennas [ i ] for i in ref_ant_id ]
print ( " Doing all baselines with {} " . format ( [ int ( a . name ) for a in ref_ants ] ) )
2023-02-02 14:57:55 +01:00
baselines = product ( ref_ants , antennas )
2022-12-02 19:07:46 +01:00
# For now, only one beacon_frequency is supported
freq_names = antennas [ 0 ] . beacon_info . keys ( )
if len ( freq_names ) > 1 :
raise NotImplementedError
freq_name = next ( iter ( freq_names ) )
2023-02-02 14:57:55 +01:00
# Collect baselines from optional generators
baselines = list ( baselines )
2022-12-02 19:07:46 +01:00
# Get phase difference per baseline
2023-02-02 14:57:55 +01:00
2022-12-02 19:07:46 +01:00
phase_diffs = np . empty ( ( len ( baselines ) , 2 ) )
for i , base in enumerate ( baselines ) :
2022-12-05 17:57:23 +01:00
if i % 1000 == 0 :
2022-12-02 19:07:46 +01:00
print ( i , " out of " , len ( baselines ) )
# read f_beacon from the first antenna
f_beacon = base [ 0 ] . beacon_info [ freq_name ] [ ' freq ' ]
# Get true phase diffs
try :
2023-01-19 16:24:05 +01:00
clock_phases = np . array ( [ ant . beacon_info [ freq_name ] [ ' clock_phase ' ] for ant in base ] )
clock_phases_diff = lib . phase_mod ( lib . phase_mod ( clock_phases [ 1 ] ) - lib . phase_mod ( clock_phases [ 0 ] ) )
2022-12-02 19:07:46 +01:00
except IndexError :
2023-01-19 16:24:05 +01:00
# clock_phase not determined yet
print ( f " Missing clock_phases for { freq_name } in baseline { base [ 0 ] . name } , { base [ 1 ] . name } " )
clock_phases_diff = np . nan
2022-12-02 19:07:46 +01:00
# save phase difference with antenna names
2023-01-19 16:24:05 +01:00
phase_diffs [ i ] = [ f_beacon , clock_phases_diff ]
2022-12-02 19:07:46 +01:00
2022-12-08 11:22:33 +01:00
beacon . write_baseline_time_diffs_hdf5 ( time_diffs_fname , baselines , phase_diffs [ : , 1 ] , [ 0 ] * len ( phase_diffs ) , phase_diffs [ : , 0 ] )
2022-12-02 19:07:46 +01:00
2022-12-19 21:34:49 +01:00
##############################
# Compare actual time shifts #
##############################
2023-04-13 15:04:45 +02:00
beacon_snrs = beacon . read_snr_file ( beacon_snr_fname )
2023-04-28 17:14:49 +02:00
snr_str = f " $ \\ langle SNR \\ rangle$ = { beacon_snrs [ ' mean ' ] : .1g } "
2023-04-12 22:42:59 +02:00
2023-01-19 16:24:05 +01:00
actual_antenna_clock_phases = { a . name : - 2 * np . pi * a . attrs [ ' clock_offset ' ] * f_beacon for a in sorted ( antennas , key = lambda a : int ( a . name ) ) }
2022-12-02 19:07:46 +01:00
# Compare actual time shifts
my_phase_diffs = [ ]
for i , b in enumerate ( baselines ) :
2023-01-19 16:24:05 +01:00
actual_clock_phase_diff = lib . phase_mod ( lib . phase_mod ( actual_antenna_clock_phases [ b [ 1 ] . name ] ) - lib . phase_mod ( actual_antenna_clock_phases [ b [ 0 ] . name ] ) )
2022-12-02 19:07:46 +01:00
2023-01-19 16:24:05 +01:00
this_actual_clock_phase_diff = lib . phase_mod ( actual_clock_phase_diff )
my_phase_diffs . append ( this_actual_clock_phase_diff )
2022-12-02 19:07:46 +01:00
# Make a plot
if True :
N_base = len ( baselines )
N_ant = len ( antennas )
2022-12-19 21:34:49 +01:00
for i in range ( 2 ) :
plot_residuals = i == 1
2023-02-07 17:58:45 +01:00
true_phases = my_phase_diffs
measured_phases = phase_diffs [ : , 1 ]
2022-12-19 21:34:49 +01:00
2023-02-07 17:58:45 +01:00
hist_kwargs = { }
2022-12-19 21:34:49 +01:00
if plot_residuals :
2023-02-07 17:58:45 +01:00
measured_phases = lib . phase_mod ( measured_phases - true_phases )
hist_kwargs [ ' histtype ' ] = ' stepfilled '
fig = figlib . phase_comparison_figure (
measured_phases ,
true_phases ,
plot_residuals = plot_residuals ,
f_beacon = f_beacon ,
figsize = figsize ,
hist_kwargs = hist_kwargs ,
2023-02-13 10:40:26 +01:00
fit_gaussian = plot_residuals ,
2023-02-07 17:58:45 +01:00
)
axs = fig . get_axes ( )
2022-12-19 21:34:49 +01:00
2023-04-12 22:42:59 +02:00
axs [ 0 ] . legend ( title = snr_str )
2023-02-07 17:58:45 +01:00
if plot_residuals :
2023-04-13 12:28:04 +02:00
axs [ 0 ] . set_title ( " Difference between Measured and Actual phase difference \n for Baselines (i,j " + ( ' ) ' if not ref_ant_id else ' = ' + str ( [ int ( a . name ) for a in ref_ants ] ) + ' ) ' ) )
2022-12-22 16:51:39 +01:00
axs [ - 1 ] . set_xlabel ( " Baseline Phase Residual $ \\ Delta \\ varphi_ { ij_ {meas} } - \\ Delta \\ varphi_ { ij_ {true} }$ [rad] " )
2022-12-19 21:34:49 +01:00
else :
2023-04-13 12:28:04 +02:00
axs [ 0 ] . set_title ( " Comparison Measured and Actual phase difference \n for Baselines (i,j " + ( ' ) ' if not ref_ant_id else ' = ' + str ( [ int ( a . name ) for a in ref_ants ] ) + ' ) ' ) )
2022-12-22 16:51:39 +01:00
axs [ - 1 ] . set_xlabel ( " Baseline Phase $ \\ Delta \\ varphi_ {ij} $ [rad] " )
2022-12-22 12:07:51 +01:00
2023-02-07 17:58:45 +01:00
#
2022-12-19 21:34:49 +01:00
i = 0
2023-02-07 17:58:45 +01:00
secax = axs [ i ] . child_axes [ 0 ]
secax . set_xlabel ( ' Time $ \\ Delta \\ varphi/(2 \\ pi f_ {beac} )$ [ns] ' )
2022-12-22 12:07:51 +01:00
2023-02-07 17:58:45 +01:00
#
2022-12-19 21:34:49 +01:00
i = 1
axs [ i ] . set_ylabel ( " Baseline no. " )
2023-04-13 12:28:04 +02:00
fig . tight_layout ( )
2022-12-19 21:34:49 +01:00
if fig_dir :
extra_name = " measured "
if plot_residuals :
2022-12-21 17:24:44 +01:00
extra_name = " residuals "
2023-01-04 11:05:20 +01:00
fig . savefig ( path . join ( fig_dir , path . basename ( __file__ ) + f " . { extra_name } .F { freq_name } .pdf " ) )
2022-12-05 17:48:58 +01:00
if show_plots :
2022-12-02 19:07:46 +01:00
plt . show ( )