mirror of
https://gitlab.science.ru.nl/mthesis-edeboone/m.internship-documentation.git
synced 2024-11-22 15:03:35 +01:00
Figure: new Beacon Sync figure
This commit is contained in:
parent
307c3189ca
commit
9ff75c5629
2 changed files with 222 additions and 0 deletions
|
@ -20,6 +20,12 @@ dist-clean:
|
|||
beacon_spatial_time_difference_setup.pdf: src/beacon_spatial_time_difference_setup.py
|
||||
$< $@
|
||||
|
||||
beacon_sync: \
|
||||
src/beacon_sync.py
|
||||
#beacon_sync.pdf beacon_sync.png \
|
||||
# beacon_sync_period.pdf beacon_sync_period.png
|
||||
$< .
|
||||
|
||||
single_beacon: \
|
||||
sine_beacon.pdf sine_beacon.png \
|
||||
ttl_beacon.pdf ttl_beacon.png
|
||||
|
|
216
figures/beacon/src/beacon_sync.py
Executable file
216
figures/beacon/src/beacon_sync.py
Executable file
|
@ -0,0 +1,216 @@
|
|||
#!/usr/bin/env python3
|
||||
# vim: fdm=marker fmr=<<<,>>>
|
||||
|
||||
__doc__ = \
|
||||
"""
|
||||
Two figures showing synchronising on a sine beacon and a pulse.
|
||||
"""
|
||||
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.gridspec as gridspec
|
||||
import scipy.fft as ft
|
||||
|
||||
rng = np.random.default_rng()
|
||||
|
||||
def _annotate_width(
|
||||
ax, name,
|
||||
x1, x2, y1=None, y2=None,
|
||||
text_dx=(0,0),
|
||||
text_kw={}, arrow_kw={}
|
||||
):
|
||||
"""
|
||||
Annotate a width between two points, with both an arrow between
|
||||
the points, and a text between them.
|
||||
|
||||
Parameters:
|
||||
-----------
|
||||
ax: Axes
|
||||
the Axes to plot on
|
||||
name: str
|
||||
text to put on top of the arrow
|
||||
x1: float or tuple
|
||||
(horizontal) location of the first point
|
||||
x2: float or tuple
|
||||
(horizontal) location of the first point
|
||||
y1: float
|
||||
vertical location of the first point
|
||||
y2: float
|
||||
vertical location of the first point
|
||||
|
||||
"""
|
||||
if hasattr(x1, '__len__'):
|
||||
if y1 is None:
|
||||
y1 = x1[1]
|
||||
x1 = x1[0]
|
||||
|
||||
if hasattr(x2, '__len__'):
|
||||
if y2 is None:
|
||||
y2 = x2[1]
|
||||
x2 = x2[0]
|
||||
|
||||
y1 = 0 if y1 is None else y1
|
||||
y2 = y1 if y2 is None else y2
|
||||
|
||||
default_arrow_kw = dict(
|
||||
xy = (x1, y1),
|
||||
xytext = (x2,y2),
|
||||
arrowprops = dict(
|
||||
arrowstyle="<->",
|
||||
shrinkA=False,
|
||||
shrinkB=False,
|
||||
),
|
||||
)
|
||||
|
||||
default_text_kw = dict(
|
||||
va='bottom',
|
||||
ha='center',
|
||||
xy=((x1+x2)/2 + text_dx[0], (y1+y2)/2 + text_dx[1])
|
||||
)
|
||||
|
||||
an1 = ax.annotate("", **{**default_arrow_kw, **arrow_kw})
|
||||
an2 = ax.annotate(name, **{**default_text_kw, **text_kw})
|
||||
|
||||
return [an1, an2]
|
||||
|
||||
def main(
|
||||
f_sine = 0.05153, # GHz
|
||||
timelength = 80, # ns
|
||||
samplerate = 1, # GHz
|
||||
phase_diff = 1.2*np.pi, # rad
|
||||
t_beacon_offset = 4.4, # ns
|
||||
):
|
||||
|
||||
t_sampled = np.arange(0, timelength, 1/samplerate)
|
||||
t_impulse = np.arange(0, timelength, 1/4 * 1/samplerate)
|
||||
|
||||
beacons = [0.1 * np.cos(2*np.pi*f_sine*(t_sampled - t_beacon_offset) + phase_diff*i) for i in range(2)]
|
||||
|
||||
t_beacon_delay = phase_diff/(2*np.pi*f_sine)
|
||||
beacon_ticks = np.array([ n/f_sine for n in range(1+int((t_sampled[-1] - t_sampled[0])*f_sine)) ])
|
||||
t_beacon_ticks = [ beacon_ticks + t_beacon_offset - i*t_beacon_delay for i in range(2) ]
|
||||
|
||||
def gaussian(x, mu=0, sigma=1 ):
|
||||
return 1/(sigma*np.sqrt(2*np.pi)) * np.exp(- (x-mu)**2 / sigma**2 )
|
||||
|
||||
impulse_time_diff = 2.1/f_sine + (1/f_sine - t_beacon_delay)
|
||||
impulse_func = lambda x, mu=0: gaussian(x, mu, 2)
|
||||
|
||||
impulse_timing = t_beacon_offset + .5/f_sine + np.array([0, impulse_time_diff])
|
||||
impulses = [ impulse_func(t_impulse, impulse_time) for impulse_time in impulse_timing ]
|
||||
|
||||
figs = []
|
||||
fig_kwargs = {}
|
||||
tick_kwargs = dict(color='k', alpha=0.2, ls=(0, (3,2)))
|
||||
arrow_kwargs = dict(arrowprops=dict(arrowstyle="->" ))
|
||||
arrow_text_kwargs = dict()
|
||||
arrow_y = 0.12
|
||||
|
||||
if True:
|
||||
fig, axes = plt.subplots(2, 1, **{**dict(sharex=True, gridspec_kw=dict(hspace=0)), **fig_kwargs})
|
||||
text_dx = (1, 0.005)
|
||||
|
||||
if False:
|
||||
for _ax in axes:
|
||||
_ax.spines[:].set_visible(False)
|
||||
|
||||
axes[-1].set_xlabel("Time")
|
||||
axes[-1].set_xticks([], [])
|
||||
|
||||
axes[0].set_ylabel("Reference")
|
||||
axes[1].set_ylabel("Antenna")
|
||||
|
||||
for i in range(0, 2):
|
||||
axes[i].set_yticks([], [])
|
||||
axes[i].plot(t_impulse, impulses[i])
|
||||
axes[i].plot(t_sampled, beacons[i], marker='.')
|
||||
|
||||
# indicate timing of ticks
|
||||
[axes[i].axvline(tick, **tick_kwargs) for tick in t_beacon_ticks[i] if tick > t_sampled[0] and tick < t_sampled[-1] ]
|
||||
|
||||
# get the first ticks
|
||||
first_ticks = [ min(ticks) for ticks in t_beacon_ticks ]
|
||||
first_ticks = [ tick if tick > 0 else tick + 1/f_sine for tick in first_ticks ]
|
||||
_annotate_width(axes[1], '$t_\\varphi$', first_ticks[0], first_ticks[1], text_dx=text_dx, y1=arrow_y, text_kw=arrow_text_kwargs, arrow_kw=arrow_kwargs)
|
||||
|
||||
figs.append(fig)
|
||||
|
||||
if True:
|
||||
fig, axes = plt.subplots(2, 1, **{**dict(sharex=True, gridspec_kw=dict(hspace=0)), **fig_kwargs})
|
||||
text_dx = (0, 0.005)
|
||||
|
||||
if False:
|
||||
for _ax in axes:
|
||||
_ax.spines[:].set_visible(False)
|
||||
|
||||
axes[-1].set_xlabel("Time")
|
||||
axes[-1].set_xticks([], [])
|
||||
|
||||
if not True:
|
||||
axes[0].set_ylabel("Reference")
|
||||
axes[1].set_ylabel("Antenna")
|
||||
|
||||
for i in range(0, 2):
|
||||
t_delta = (i == 1) * ( t_beacon_delay - 1/f_sine )
|
||||
axes[i].set_yticks([], [])
|
||||
axes[i].plot(t_impulse + t_delta , impulses[i])
|
||||
axes[i].plot(t_sampled + t_delta , beacons[i], marker='.')
|
||||
|
||||
# indicate timing of ticks
|
||||
t_delta = (i == 1) * ( t_beacon_delay - 1/f_sine )
|
||||
[axes[i].axvline(tick+t_delta, **tick_kwargs) for tick in t_beacon_ticks[i] if tick > t_sampled[0] and tick < t_sampled[-1] ]
|
||||
|
||||
# get the tick before the impulse
|
||||
_diffs = np.array([ impulse_timing[i] - t_beacon_ticks[i] for i in range(0,2) ])
|
||||
_diffs[_diffs < 0 ] = np.inf # only early ticks
|
||||
impulse_ticks_idx = np.argmin(abs(_diffs), axis=1)
|
||||
impulse_ticks = [ t_beacon_ticks[i][idx] + (i==1)*t_delta for i, idx in enumerate(impulse_ticks_idx) ]
|
||||
|
||||
_annotate_width(axes[1], '$kT$', impulse_ticks[0], impulse_ticks[1], text_dx=text_dx, y1=arrow_y, text_kw=arrow_text_kwargs, arrow_kw=arrow_kwargs)
|
||||
|
||||
|
||||
figs.append(fig)
|
||||
|
||||
return figs
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from argparse import ArgumentParser
|
||||
import os.path as path
|
||||
|
||||
import os
|
||||
import sys
|
||||
# Append parent directory to import path so pyfiglib can be found
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
import pyfiglib as pfl
|
||||
|
||||
|
||||
parser = ArgumentParser(description=__doc__)
|
||||
parser.add_argument("fname", metavar="path/to/figure[/]", nargs="*", help="Location for generated figure, will append __file__ if a directory. If not supplied, figure is shown.", default=None)
|
||||
|
||||
args = parser.parse_args()
|
||||
default_extensions = ['pdf', 'png']
|
||||
default_names = ['beacon_sync', 'beacon_sync_period']
|
||||
|
||||
if args.fname == 'none':
|
||||
args.fname = None
|
||||
|
||||
pfl.rcParams['font.size'] = 20
|
||||
pfl.rcParams['figure.figsize'] = (6,4)
|
||||
pfl.rcParams['figure.constrained_layout.use'] = True
|
||||
|
||||
###
|
||||
figs = main()
|
||||
|
||||
### Save or show figures
|
||||
if not args.fname:
|
||||
# empty list, False, None
|
||||
plt.show()
|
||||
else:
|
||||
for i, f in enumerate(figs):
|
||||
if len(args.fname) == 1 and len(figs) != 1:
|
||||
for ext in default_extensions:
|
||||
f.savefig(path.join(args.fname[0], default_names[i]) + "." + ext, transparent=True)
|
||||
else:
|
||||
f.savefig(args.fname[i], transparent=True)
|
Loading…
Reference in a new issue