In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import xarray as xr
In [2]:
path = 'fmt.all'
starting_day = '2018-11-06'
frequency = 27e6
In [3]:
def load_data(path, starting_day, frequency):
with open(path) as f:
data = [(s.split()[0], float(s.split()[5])) for s in f.readlines()]
timestamps = np.array([np.datetime64(starting_day + 'T' + d[0]) for d in data])
# correct rollover
timestamps += np.concatenate(([0], np.cumsum(np.diff(np.array(timestamps)) < np.timedelta64(0)))) * np.timedelta64(3600*24)
ppb = [-d[1]/frequency*1e9 for d in data]
data = xr.DataArray(ppb, coords = {'time':timestamps}, dims = ('time'))
data.attrs['units'] = 'ppb'
data.name = 'Frequency offset'
return data
In [4]:
ppb = load_data(path, starting_day, frequency)
ppb = ppb[ppb > -720][:-1] # filter some invalid measurements
In [5]:
plt.figure(figsize=(14,8))
ppb.plot()
plt.gca().xaxis.set_major_locator(mdates.DayLocator())
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
plt.grid()
plt.title('Frequency offset')
plt.xlabel('UTC time')
plt.ylabel('Frequency offset (ppb)');
In [6]:
plt.figure(figsize=(14,8))
for g in ppb.groupby('time.day'):
plt.plot(np.datetime64('2000-01-01') + (g[1].coords['time'] - g[1].coords['time'].astype('datetime64[D]')), g[1],\
label = f'Day {g[0]}', alpha = 0.75)
plt.gca().xaxis.set_major_locator(mdates.HourLocator())
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
plt.xticks(rotation=45)
plt.xlim(['2000-01-01T00:00', '2000-01-02T00:00'])
plt.legend()
plt.grid()
plt.title('Frequency offset (by day)')
plt.xlabel('Hour of day (UTC)')
plt.ylabel('Frequency offset (ppb)');
In [7]:
plt.figure(figsize=(14,8))
for g in ppb.groupby('time.day'):
plt.plot(np.datetime64('2000-01-01') + (g[1].coords['time'] - g[1].coords['time'].astype('datetime64[D]')), g[1] - g[1].mean(),\
label = f'Day {g[0]}', alpha = 0.5)
plt.gca().xaxis.set_major_locator(mdates.HourLocator())
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
plt.xticks(rotation=45)
plt.xlim(['2000-01-01T00:00', '2000-01-02T00:00'])
plt.legend()
plt.grid()
plt.title('Frequency offset with average removed (by day)')
plt.xlabel('Hour of day (UTC)')
plt.ylabel('Deviation from average (ppb)');
In [8]:
def avar(x, tau):
return 1e-9*np.sqrt(0.5*(x.resample(time=f'{int(round(tau))}S').mean().diff('time')**2).mean())
In [9]:
taus = np.logspace(1,5)
avars = [avar(ppb, tau) for tau in taus]
In [10]:
plt.figure(figsize=(14,8))
plt.loglog(taus, avars)
plt.grid()
plt.title('Allan deviation')
plt.xlabel('$\\tau$ (s)')
plt.ylabel('$\\sigma(\\tau)$');
plt.ylim([1e-10,1e-8]);