Source code for AllSkyCam4OLEODL.link_budget

"""This modules manages the creation and display of the link budget."""

# C:\Users\alda_ik\Documents\04_PROGRAMMING\03_SCRIPTS\05_LINK_BUDGET\link_budget.py

from typing import Union, Tuple
from scipy.special import erfinv

import numpy as np
import mplcursors
import matplotlib.pyplot as plt

import math

from . import constants as const


[docs] def printer_lb( el: Union[np.ndarray, int], elevation_mode, sat, a_tx: int, p_tx: int, ppb: int, teta_tx: float, a_rx: int, leng: Union[np.ndarray, float], g_tx: float, a_fsl: Union[np.ndarray, float], i_axial: Union[np.ndarray, float], area_rx: float, a_atm: Union[np.ndarray, float], a_bw: int, g_rx: float, p_rx: Union[np.ndarray, float], int_ogs_lin: Union[np.ndarray, float], int_ogs_lin_loss: Union[np.ndarray, float], p_ogs_mean: Union[np.ndarray, float], p_ogs_mean_loss: Union[np.ndarray, float], p_rx_lin: Union[np.ndarray, float], wl: float, p_rfe_lin: float, a_sci: int, ) -> Tuple[Union[np.ndarray, int], Union[np.ndarray, float]]: """Prints the graph or the results and summary of the link budget. 1. If the elevation mode is "Full" it will just print the graph, if not it will print the result of the link budget. Args: el (np.ndarray | int): Elevation of the satellite elevation_mode (tk.StringVar): Container of the elevation mode. sat (tk.StringVar): Container of the payload used. a_tx (int): Transmitter optical loss. p_tx (int): Transmitter power. ppb (int): Photons/bit. teta_tx (float): Transmitter divergence. a_rx (int): Receiver optical loss onto RFE. leng (np.ndarray | float): Length of the link. g_tx (float): Transmitter antenna gain. a_fsl (np.ndarray | float): Free-space loss. i_axial (np.ndarray | float): Axial intensity at OGS-distance. area_rx (float): Receiver antenna area. a_atm (np.ndarray | float): Atmospheric attenuation loss. a_bw (int): Mean BeamWander loss. g_rx (float): Reveiver antenna gain. p_rx (np.ndarray | float): Received power. int_ogs_lin (np.ndarray | float): Intensity onto OGS-apertue exc. losses. int_ogs_lin_loss (np.ndarray | float): Intensity onto OGS-apertue inc. losses. p_ogs_mean (np.ndarray | float): Power into the OGS-apertue - no additional RX-losses. p_ogs_mean_loss (np.ndarray | float): Power into the OGS-apertue including RX-losses. p_rx_lin (np.ndarray | float): RxPower onto RFE-detector incl all losses. wl (float): Wavelength. p_rfe_lin (float): RFE-sensitivity for an specific Photons/bit. a_sci (int): Scintillation loss. """ if elevation_mode.get() == "Full": print(int_ogs_lin_loss) el = np.arange(5, 90) print(el) plt.figure() plt.plot(el, int_ogs_lin_loss * 1e6, "-", color="r", linewidth=2) plt.ylabel("Intensity onto Camera-apertue / µW/m²") plt.xlabel("Elevation / 1°") plt.subplots_adjust(left=0.17, right=0.95, top=0.92, bottom=0.13) plt.title(f"{sat.get()} intensity Link Budget") plt.grid(True) fig_manager = plt.get_current_fig_manager() # Dimensions and position of the link budget window (WidthxHeight+X+Y) fig_manager.window.wm_geometry("355x372+545+290") mplcursors.cursor() plt.show(block=False) else: print("///////////////////////////////////////////////////") print() print(f"Transmit-power = {p_tx} dBm") print(f"Divergence = {((teta_tx*1E6*10)/10)} µrad") print(f"Optical loss Tx = {a_tx} dB") print( f"Optical loss onto RFE (incl. splitting) = {a_rx} dB - We are not " f"taking into account optical loss as the receiver is a camera" ) # if sat == "OsirisV1": # print( # f"Optical loss onto RFE (incl. splitting) = {a_rx} dB - in OSIRISv1 from FLP -7,5dB were measured in 30cm telescope towards PowerSensor" # ) # print(f"Optical loss Rx (incl. splitting) = {a_rx} dB - in KIODO only 4% of Rx-light was on RFE-APD") print() print(f"Link-distance = {(leng/100)*.1} km") print(f"Tx-antenna gain = + {g_tx} dB") print(f"Freespace Loss = {a_fsl} dB") print( f" # axial Intensity a OGS-distance = {i_axial*1E6} µW/m^2, after " f"only distance and Tx-internal losses" ) print(f" # Area of Rx-antenna = {area_rx} m^2") print( f" # power into Rx-aperture [no a_atmo nor a_pointing, only a_Tx, " f"a_fsl, g_Rx] = {1E6*i_axial * area_rx} µW" ) print() print(f"atmosph. atten. = {a_atm} dB") print( f"mean BeamWander loss = {a_bw} dB - Being the receiver a camera, we are " f"not taking into acount BeamWander losses" ) print( f"scinti-loss = {a_sci} dB - Once again we suppose Scintillation loss as cero" ) print() print(f"Rx-antenna gain = + {g_rx} dB") print(f"optical loss Rx = {a_rx} dB, includes splitting for Tracking") print(f"RxPower on RFE with all losses = {p_rx} dBm") print( f" # intensity onto OGS-apertue incl atmosphere but excl. " f"Rx-losses = {int_ogs_lin *1E6} µW/m^2" ) print( f" # intensity onto OGS-apertue incl atmosphere including " f"Rx-losses = {int_ogs_lin_loss *1E6} µW/m^2" ) print( f" # power into the OGS-apertue - no additional RX-losses" f"= {(10**(p_ogs_mean/10)/1000)*1E6} µW" ) print( f" # power into the OGS-apertue including RX-losses = " f"{(10**(p_ogs_mean_loss/10)/1000)*1E6} µW" ) print( f"RxPower onto RFE-detector incl all losses = {p_rx_lin*1E9} nW, " f"sufficient for {(p_rx_lin/ppb/(const.H*const.C/wl))/1E9} Gbps at {ppb} Photons/bit" ) print( f"RFE-sensitivity for {ppb} Ppb = {p_rfe_lin*1E9} nW or " f"{math.log10(p_rfe_lin*1000)*10} dBm" ) print() print(f"Link Margin: {p_rx - math.log10(p_rfe_lin*1000)*10 } dBm") print() print("///////////////////// Summary /////////////////////") if elevation_mode.get() == "Individual": print(f"mean source power +{p_tx} dBm") print(f"Tx-internal losses {a_tx} dBm") print(f"Tx-antenna gain +{g_tx} dB") print(f"pointing loss {a_bw} dB") print(f"Distance {leng/1000} km") print(f"freespace loss {a_fsl} dB") print(f"Atmospheric loss {a_atm} dB") print(f"scintillation loss {a_sci} dB") print(f"Rx-antenna gain +{g_rx} dB") print(f"Power into Rx-Aper {p_ogs_mean} dBm") print(f"Rx-internal losses {a_rx} dB") p_rx_ = ( p_tx + a_tx + g_tx + a_bw + a_fsl + a_atm + a_sci + g_rx + a_rx ) print(f"Power onto detectr {p_rx_} dBm") print( f"Sensitivity of RFE {10*math.log10(p_rfe_lin*1000)} dBm / {p_rfe_lin*1E9} nW" ) print( f"Link Margin {p_rx_ - 10*math.log10(p_rfe_lin*1000)} dB" ) print() print("//////////////////// Intensity ////////////////////") print( f"Axial Intensity at OGS-distance = {i_axial*1E6} µW/m^2, after only " f"distance and Tx-internal losses" ) print( f"Intensity onto OGS-apertue incl atmosphere but excl. Rx-losses = " f"{int_ogs_lin *1E6} µW/m^2" ) print( f"Intensity onto OGS-apertue incl atmosphere including Rx-losses = " f"{int_ogs_lin_loss *1E6} µW/m^2" ) print() print("////////////////////// Power //////////////////////") print( f"Power into Rx-aperture [no a_atmo nor a_pointing, only a_Tx, a_fsl, " f"g_Rx] = {1E6*i_axial * area_rx} µW" ) print( f"Power into the OGS-apertue - no additional RX-losses = " f"{(10**(p_ogs_mean/10)/1000)*1E6} µW" ) print( f"Power into the OGS-apertue including RX-losses = " f"{(10**(p_ogs_mean_loss/10)/1000)*1E6} µW" )