Source code for cbadc.analog_signal.quadrature

"""Sinusoidal signals."""
from typing import Union, List
from ._analog_signal import _AnalogSignal
from .constant_signal import ConstantSignal
from sympy import cos
from mpmath import mp
import numpy as np


def _rotation_matrix(angle):
    """Get a rotation matrix.

    Parameters
    ----------
    angle : `float`
        the angle of rotation

    Returns
    -------
    `numpy.ndarray`
        a 2x2 rotation matrix
    """
    return np.array([[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]])


[docs]def get_quadrature_signal_pair( amplitude: float, angular_frequency: float, in_phase: _AnalogSignal = ConstantSignal(1.0), quadrature: _AnalogSignal = ConstantSignal(0.0), phase: float = 0.0, offset: float = 0.0, ): """Get a quadrature pair of sinusoidal signals. Parameters ---------- amplitude_modulation: :py:class:`cbadc.analog_signal._AnalogSignal` the amplitude modulation phase_modulation: :py:class:`cbadc.analog_signal._AnalogSignal` the phase modulation angular_frequency: `float` the angular frequency of the sinusoidal signal phase: `float` the phase of the sinusoidal signal offset: `float` the offset of the sinusoidal signal Returns ------- `tuple` of :py:class:`cbadc.analog_signal._AnalogSignal` a quadrature pair of sinusoidal signals """ return [ QuadratureSignal(amplitude, angular_frequency, True, [in_phase, quadrature]), QuadratureSignal(amplitude, angular_frequency, False, [in_phase, quadrature]), ]
[docs]class SineWaveModulator(_AnalogSignal): def __init__( self, in_phase: _AnalogSignal, quadrature: _AnalogSignal, carrier_frequency: float, ): super().__init__() self._in_phase = in_phase self._quadrature = quadrature self._carrier_radial_frequency = 2.0 * np.pi * carrier_frequency self._amplitude = 1.0 / np.sqrt(2.0)
[docs] def evaluate(self, t: float) -> float: """Evaluate the signal at time :math:`t`. Parameters ---------- t : `float` the time instance for evaluation. Returns ------- float The analog signal value """ return self._amplitude * ( np.cos(self._carrier_radial_frequency * t) * self._in_phase.evaluate(t) + np.sin(self._carrier_radial_frequency * t) * self._quadrature.evaluate(t) )
[docs]class QuadratureSignal(_AnalogSignal): """An analog continuous-time sinusoidal signal. Parameters ---------- amplitude_modulation : :py:class`cbadc.analog_signal.AnalogSignal` the amplitude modulation signal phase_modulations: :py:class`cbadc.analog_signal.AnalogSignal` the phase modulation signal angular_frequency: `float` the angular frequency of the sinusoidal signal phase: `float` the phase of the sinusoidal signal offset: `float` the offset of the sinusoidal signal """ amplitude: float angular_frequency: float phase: float offset: float def __init__( self, amplitude: float, angular_frequency: float, in_phase: bool, i_q: List[_AnalogSignal], ): super().__init__() self.amplitude = amplitude self.angular_frequency = angular_frequency if in_phase: self.phase = np.array([1.0, 0.0]) else: self.phase = np.array([0.0, 1.0]) if len(i_q) != 2: raise ValueError("i_q must be a list of length 2.") self._iq = i_q
[docs] def evaluate(self, t: float) -> float: """Evaluate the signal at time :math:`t`. Parameters ---------- t : `float` the time instance for evaluation. Returns ------- float The analog signal value """ iq = np.array([iq.evaluate(t) for iq in self._iq]) return self.amplitude * np.dot( self.phase, np.dot(_rotation_matrix(self.angular_frequency * t), iq), )