Calculate path propagation/attenuation according to ITU-R P.452 (16).
Copyright (C) 2015+ Benjamin Winkel (bwinkel@mpifr.de)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from astropy import units as u
from pycraf import pathprof
from pycraf import conversions as cnv
rc('animation', html='html5')
FRAMES = 120
The propagation losses depend on a lot of different parameters, such as frequency, distance, weather etc. Here, we try to visualize some of the effects. The generic (flat-Earth) case is used (without loss of generality).
distance = 100 * u.km
hprof_step = 50 * u.m
lon_t, lat_t = 0 * u.deg, 50 * u.deg
hprof_data = pathprof.height_path_data_generic(
distance, hprof_step, lon_t, lat_t,
)
def plot_helper(freq, temp, press, h_tg, h_rg, time_percent, titles):
plt.close()
fig = plt.figure(figsize=(14, 10))
ax = fig.add_axes((0.1, 0.1, 0.8, 0.8))
lines_dict = {}
for key, name, style in zip(
['L_b0p', 'L_bd', 'L_bs', 'L_ba', 'L_b'],
['LOS', 'Diffraction', 'Troposcatter', 'Ducting', 'Total'],
['b-', 'r-', 'c-', 'g-', 'k--']
):
results = pathprof.atten_path_fast(
freq[0], temp[0], press[0],
h_tg[0], h_rg[0], time_percent[0],
hprof_data,
)
lines_dict[key] = ax.plot(
hprof_data['distances'][5:],
results[key][5:],
style, label=name
)[0]
ax.legend(
*ax.get_legend_handles_labels(),
loc='lower right', fontsize=8, handlelength=3
)
title = ax.set_title(titles[0], loc='center', fontsize=20)
ax.set_xlim((0, 100))
ax.set_ylim((80, 260))
ax.set_xlabel('Distance [km]')
ax.set_ylabel('Path attenuation [dB]')
ax.grid()
def animate_freq(i):
results = pathprof.atten_path_fast(
freq[i], temp[i], press[i],
h_tg[i], h_rg[i], time_percent[i],
hprof_data,
)
title.set_text(titles[i])
for key in ['L_b0p', 'L_bd', 'L_bs', 'L_ba', 'L_b']:
lines_dict[key].set_ydata(results[key][5:])
return list(lines_dict.values())
def init():
return animate_freq(0)
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(
fig, animate_freq, init_func=init, frames=FRAMES, interval=50, blit=True
)
# this takes a while!
plt.close(anim._fig)
return anim
h_tg, h_rg = np.full(FRAMES, 30) * u.m, np.full(FRAMES, 30) * u.m
freq = np.logspace(np.log10(0.1), np.log10(50), FRAMES) * u.GHz
temp = np.full(FRAMES, 293.15) * u.K
press = np.full(FRAMES, 1013.) * u.hPa
time_percent = np.full(FRAMES, 2) * u.percent
titles = ['Frequency: {:5.2f}'.format(f) for f in freq]
plot_helper(freq, temp, press, h_tg, h_rg, time_percent, titles)
h_tg, h_rg = np.full(FRAMES, 30) * u.m, np.full(FRAMES, 30) * u.m
freq = np.full(FRAMES, 10.) * u.GHz
temp = np.linspace(250., 330, FRAMES) * u.K
press = np.full(FRAMES, 1013.) * u.hPa
time_percent = np.full(FRAMES, 2) * u.percent
titles = ['Temperature: {:5.2f}'.format(t) for t in temp]
plot_helper(freq, temp, press, h_tg, h_rg, time_percent, titles)
h_tg, h_rg = np.full(FRAMES, 30) * u.m, np.full(FRAMES, 30) * u.m
freq = np.full(FRAMES, 10.) * u.GHz
temp = np.full(FRAMES, 293.15) * u.K
press = np.full(FRAMES, 1013.) * u.hPa
time_percent = np.logspace(np.log10(0.1), np.log10(50), FRAMES) * u.percent
titles = ['Time percent: {:5.2f}'.format(p) for p in time_percent]
plot_helper(freq, temp, press, h_tg, h_rg, time_percent, titles)