import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation, rc
rc('animation', html='html5')
from matplotlib.colors import LogNorm
T1 = (0, 0)
T2 = (0.07, 0)
T3 = (1, .5)
Fc = 2_450_000_000. # Downscale to 2.45GHz
c = 299792458. # m/s
t_off = 0.2 / Fc
scale = 0.025 # size in cm covered by single pixel
resolution = 200 # number of on plot
# we have central point at size/scale
# one point on grid represents scale*d_scale meters
def m_to_point(T):
return resolution+T[1]/scale, resolution+T[0]/scale
m_to_point(T2)
(200.0, 202.8)
len(np.arange(0, grid[0].shape[0], scale/9))
144000
# grid has positions in meters
grid = np.mgrid[-resolution*scale:resolution*scale:scale,-resolution*scale:resolution*scale:scale]
dT_f = lambda T1: np.clip(np.sqrt( (grid[0]-T1[0])**2 + (grid[1]-T1[1])**2), 0.07, 1000)
dT1 = dT_f(T1)
dT2 = dT_f(T2)
dT3 = dT_f(T3)
def label_plot(*nodes):
plt.xticks(np.linspace(0, grid[0].shape[0]-1, 9), np.linspace(-resolution*scale, resolution*scale, 9))
plt.yticks(np.linspace(0, grid[0].shape[0]-1, 9), np.linspace(-resolution*scale, resolution*scale, 9))
for T in nodes:
plt.plot(*m_to_point(T), 'ro', markersize=1)
plt.colorbar()
plt.imshow(1/dT1**2, vmax=5, vmin=0)
label_plot(T1)
plt.title('1/distance to node')
plt.show()
phase_f = lambda dT, t_off: np.sin(2*np.pi*Fc*(-dT/c+t_off))
phase = phase_f(dT1, t_off)
plt.imshow(phase)
label_plot(T1)
plt.title('Phase at a given point in time')
Text(0.5, 1.0, 'Phase at a given point in time')
fig = plt.figure(figsize=(6, 6))
ampl_f = lambda dT1, t_off: phase_f(dT1, t_off)/(dT1**2)
ampl = ampl_f(dT1, t_off)
plt.imshow(ampl, vmax=5, vmin=0)
label_plot(T1)
plt.title('Amplitude of waveform at a given point in time')
Text(0.5, 1.0, 'Amplitude of waveform at a given point in time')
fig = plt.figure(figsize=(6, 6))
phase = phase_f(dT1, t_off)
im = plt.imshow(phase)
label_plot(T1)
plt.title("Wave propagation animation")
def animate(i):
im.set_data(phase_f(dT1, 0.01*i/Fc))
return (im,)
anim = animation.FuncAnimation(fig, animate,
frames=100, interval=20, blit=True)
anim
fig = plt.figure(figsize=(10, 10))
ampl = np.abs(ampl_f(dT1, t_off))
im = plt.imshow(ampl, vmax=5, vmin=0)
label_plot(T1)
plt.title('Waveform amplitude propagation')
def animate(i):
im.set_data(np.abs(ampl_f(dT1, 0.01*i/Fc)))
return (im,)
anim = animation.FuncAnimation(fig, animate,
frames=100, interval=20, blit=True)
anim
fig = plt.figure(figsize=(6, 6))
plt.imshow(phase_f(dT1, t_off) + phase_f(dT2, 0))
label_plot(T1, T2)
plt.title('Interference between two nodes half-wavelenght\n apart withot power attenuation (20%phi offset)')
Text(0.5, 1.0, 'Interference between two nodes half-wavelenght\n apart withot power attenuation (20%phi offset)')
fig = plt.figure(figsize=(6, 6))
ampl = np.abs(ampl_f(dT1, t_off) + ampl_f(dT2, 0))
im = plt.imshow(ampl, vmax=5, vmin=0)
label_plot(T1, T2)
plt.title('Interference between two nodes half-wavelenght\n (20%phi offset)')
Text(0.5, 1.0, 'Interference between two nodes half-wavelenght\n (20%phi offset)')
def animate(i):
dt = 0.01*i/Fc
im.set_data(np.abs(ampl_f(dT1, t_off+dt) + ampl_f(dT2, dt)))
return (im,)
anim = animation.FuncAnimation(fig, animate,
frames=100, interval=20, blit=True)
anim
fig = plt.figure(figsize=(6, 6))
ampl = np.abs(ampl_f(dT1, 0) + ampl_f(dT2, 0))
im = plt.imshow(ampl, vmax=5, vmin=0)
label_plot(T1, T2)
plt.title("Beamforming with 0 offset")
Text(0.5, 1.0, 'Beamforming with 0 offset')
def animate(i):
dt = 0.01*(i%100)/Fc
t_off = 0.1*(i//100)/Fc
im.set_data(np.abs(ampl_f(dT1, t_off+dt) + ampl_f(dT2, dt)))
return (im,)
anim = animation.FuncAnimation(fig, animate,
frames=10_00, interval=20, blit=True)
anim
t = np.linspace(0., 1., 200)/Fc
ampls = np.array([ampl_f(dT1, ti) for ti in t])
ampl_agg_baseline = np.mean(np.abs(ampls), axis=0)
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(ampl_agg_baseline, vmax=5, vmin=0)
label_plot(T1)
plt.title('Single node signal amplitude')
Text(0.5, 1.0, 'Single node signal amplitude')
import pandas as pd
pd.Series(ampl_agg.ravel()).describe()
count 160000.000000 mean 0.348738 std 23.813855 min 0.000408 25% 0.011352 50% 0.028389 75% 0.070958 max 6247.967411 dtype: float64
%%time
ampls2 = np.array([ampl_f(dT2, ti+0) for ti in t])
ampl_agg_baseline2 = np.mean(np.abs(ampls2), axis=0)
Wall time: 1.34 s
ampl_agg = np.mean(np.abs(ampls+ampls2), axis=0)+1e-9
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(ampl_agg, vmax=5, vmin=0)
label_plot(T1, T2)
plt.title('Two node signal amplitude')
Text(0.5, 1.0, 'Two node signal amplitude')
import tqdm
import tqdm.notebook as tqdm
frames = 100
pbar = tqdm.tqdm(total=frames)
def animate(i):
t_off = i / frames/Fc
ampls2 = np.array([ampl_f(dT2, ti+t_off) for ti in t])
ampl_agg = np.mean(np.abs(ampls+ampls2), axis=0)
im.set_data(ampl_agg)
pbar.update(1)
return (im,)
anim = animation.FuncAnimation(fig, animate,
frames=frames, interval=100, blit=True)
anim
def gain_max(ampl_agg, *baselines):
return ampl_agg/np.max(np.dstack([*baselines]), axis=-1)
gain_kwargs = dict( vmax=2, vmin=0, cmap='coolwarm')
fig = plt.figure(figsize=(6, 6))
plt.title("Standard MIMO gain – 2 antennas separated by\nhalf wavelenght with 0 phase offset")
im = plt.imshow(gain_max(ampl_agg, ampl_agg_baseline, ampl_agg_baseline2), **gain_kwargs)
label_plot(T1, T2)
# Why? Let's take a point (0.5, 0.5) and see
x, y = 100, 100
plt.plot(ampls[:,x, y], label='from T1')
plt.plot(ampls2[:,x, y], label='from T2')
plt.plot(ampls[:,x, y]+ampls2[:,x, y], label='sum')
plt.legend()
plt.title('Why? Offset in phase due to wavelenght propagation time')
Text(0.5, 1.0, 'Why? Offset in phase due to wavelenght propagation time')
ampls3 = np.array([ampl_f(dT3, ti+0) for ti in t])
ampl_agg_baseline3 = np.mean(np.abs(ampls3), axis=0)
ampl_agg = np.mean(np.abs(ampls+ampls3), axis=0)
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(ampl_agg, vmax=5, vmin=0)
label_plot(T1, T3)
plt.title('Two nodes with perfectly synchronized nodes (sig power)')
Text(0.5, 1.0, 'Two nodes with perfectly synchronized nodes (sig power)')
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(gain_max(ampl_agg, ampl_agg_baseline, ampl_agg_baseline3), **gain_kwargs)
label_plot(T1, T3)
plt.title('Two nodes with perfectly synchronized clocks\nGain over best of 2 signals')
Text(0.5, 1.0, 'Two nodes with perfectly synchronized clocks\nGain over best of 2 signals')
import tqdm.notebook as tqdm
frames = 100
pbar = tqdm.tqdm(total=frames)
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(ampl_agg, vmax=5, vmin=0)
plt.title('Two nodes with drifting clocks\n(sig power, time not to scale)')
def animate(i):
t_off = i / frames/Fc
ampls2 = np.array([ampl_f(dT3, ti+t_off) for ti in t])
ampl_agg = np.mean(np.abs(ampls+ampls2), axis=0)
im.set_data(ampl_agg)
pbar.update(1)
return (im,)
anim = animation.FuncAnimation(fig, animate,
frames=frames, interval=100, blit=True)
anim
T4 = (-3, 1.5)
dT4 = dT_f(T4)
ampls4 = np.array([ampl_f(dT4, ti+0.45/Fc) for ti in t])
ampl_agg_baseline4 = np.mean(np.abs(ampls4), axis=0)
ampl_agg = np.mean(np.abs(ampls+ampls4), axis=0)
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(ampl_agg, vmax=5, vmin=0)
label_plot(T1, T4)
plt.title('Two distant nodes with perfectly synchronized cloks\n with 45%ph offset (sig power)')
Text(0.5, 1.0, 'Two distant nodes with perfectly synchronized cloks\n with 45%ph offset (sig power)')
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(gain_max(ampl_agg, ampl_agg_baseline, ampl_agg_baseline4), **gain_kwargs)
label_plot(T1, T4)
plt.title('Two distant nodes with perfectly synchronized clocks\nwith 45%ph offset Gain over best of 2 signals')
Text(0.5, 1.0, 'Two distant nodes with perfectly synchronized clocks\nwith 45%ph offset Gain over best of 2 signals')
ampl_agg = np.mean(np.abs(ampls+ampls4+ampls3), axis=0)
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(ampl_agg, vmax=5, vmin=0)
label_plot(T1, T3, T4)
plt.title('Three nodes with perfectly synchronized clocks up to phase.')
Text(0.5, 1.0, 'Three nodes with perfectly synchronized clocks up to phase.')
fig = plt.figure(figsize=(6, 6))
gain = gain_max(ampl_agg, ampl_agg_baseline,ampl_agg_baseline4,ampl_agg_baseline3)
im = plt.imshow(gain, **gain_kwargs)
label_plot(T1, T3, T4)
plt.title('Gain of using 3 nodes over the best of 3 signals.\nPerfect clocks.')
Text(0.5, 1.0, 'Gain of using 3 nodes over the best of 3 signals.\nPerfect clocks.')
import tqdm.notebook as tqdm
frames = 50
pbar = tqdm.tqdm(total=frames)
fig = plt.figure(figsize=(10, 10))
gain = gain_max(ampl_agg, ampl_agg_baseline,ampl_agg_baseline4,ampl_agg_baseline3)
im = plt.imshow(gain, **gain_kwargs)
label_plot(T1, T3, T4)
plt.xlabel('Meters')
plt.ylabel('Meters')
plt.title('Gain of using 3 nodes over the best signal sequentially')
plt.suptitle('Nodes have some clock drift (imagine 5sec is .5us)')
def animate(i):
perc = i / frames
t3_off = 0.4/Fc + perc*(1.2/Fc)
t4_off = 0.1/Fc + perc*(3/Fc)
ampls3 = np.array([ampl_f(dT3, ti+t3_off) for ti in t])
ampls4 = np.array([ampl_f(dT4, ti+t4_off) for ti in t])
ampl_agg = np.mean(np.abs(ampls+ampls3+ampls4), axis=0)
gain = gain_max(ampl_agg, ampl_agg_baseline,ampl_agg_baseline4,ampl_agg_baseline3)
im.set_data(gain)
pbar.update(1)
return (im,)
anim = animation.FuncAnimation(fig, animate,
frames=frames, interval=200, blit=True)
anim