"""Helper function(s) for power/gain calculations."""
from mpmath import mp
from ska_mid_cbf_fhs_common.helpers.math import FHS_MPMATH_PRECISION, FloatLike, MPFloat
[docs]
def calculate_gain_multiplier(p_max: FloatLike, measured_power: FloatLike, headroom: FloatLike) -> MPFloat:
"""
Calculate the gain multiplier required to apply to the signal
to achieve the optimal output power adhering to the provided headroom.
Args:
p_max (:obj:`FloatLike`): Maximum signal power, in decibels (dB).
measured_power (:obj:`FloatLike`): Average power measurement (is this in volts?). Must be within the interval (0, 1].
headroom (:obj:`FloatLike`): Requested RFI headroom, in decibels (dB).
Returns:
:obj:`MPFloat`: The gain multiplier to apply to the signal.
"""
if measured_power <= 0 or measured_power > 1:
raise ValueError(f"The measured power must be within the interval (0, 1]. Got: {measured_power}")
mp.dps = FHS_MPMATH_PRECISION
p_max = MPFloat(p_max)
measured_power = MPFloat(measured_power)
headroom = MPFloat(headroom)
p_measured = mp.fmul(10, mp.log10(measured_power)) # Measured power, in dB
gain = mp.fsub(mp.fsub(p_max, p_measured), headroom) # Required gain, in dB
return mp.power(10, mp.fdiv(gain, 20)) # Gain multiplier to apply to the signal
[docs]
def calculate_output_power(measured_power: FloatLike, multiplier: FloatLike) -> MPFloat:
"""
Calculate the power achieved after applying the specified gain multiplier.
Args:
measured_power (:obj:`FloatLike`): Average power measurement (is this in volts?). Must be within the interval (0, 1].
multiplier (:obj:`FloatLike`): Gain multiplier to apply to the measured power.
Returns:
:obj:`MPFloat`: The calculated output power.
"""
if measured_power <= 0 or measured_power > 1:
raise ValueError(f"The measured power must be within the interval (0, 1]. Got: {measured_power}")
if multiplier <= 0:
raise ValueError(f"The multiplier must be positive. Got: {multiplier}")
mp.dps = FHS_MPMATH_PRECISION
measured_power = MPFloat(measured_power)
multiplier = MPFloat(multiplier)
return mp.fmul(mp.power(multiplier, 2), measured_power)
[docs]
def calculate_expected_power(p_max: FloatLike, headroom: FloatLike) -> MPFloat:
"""
Calculate the expected optimal output power adhering to the provided headroom.
Args:
p_max (:obj:`FloatLike`): Maximum signal power, in decibels (dB).
headroom (:obj:`FloatLike`): Requested RFI headroom, in decibels (dB).
Returns:
:obj:`MPFloat`: The expected optimal output power.
"""
mp.dps = FHS_MPMATH_PRECISION
p_max = MPFloat(p_max)
headroom = MPFloat(headroom)
return mp.power(10, mp.fdiv(mp.fsub(p_max, headroom), 10))