def directional_response(self, theta, phi, polarization): """ Generate the (complex) frequency-dependent directional response. For given angles and polarization direction, use the model of the directional and polarization gains of the antenna to generate a function for the interpolated response of the antenna with respect to frequency. Used with the `frequency_response` method to calculate effective heights. Parameters ---------- theta : float Polar angle (radians) from which a signal is arriving. phi : float Azimuthal angle (radians) from which a signal is arriving. polarization : array_like Normalized polarization vector in the antenna coordinate system. Returns ------- function A function which returns complex-valued voltage gains for given frequencies, using the values of incoming angle and polarization. See Also -------- ARAAntenna.frequency_response : Calculate the (complex) frequency response of the antenna. """ e_theta = [ np.cos(theta) * np.cos(phi), np.cos(theta) * np.sin(phi), -np.sin(theta) ] e_phi = [-np.sin(phi), np.cos(phi), 0] theta_factor = np.dot(polarization, e_theta) phi_factor = np.dot(polarization, e_phi) theta_gains = complex_bilinear_interp(x=np.degrees(theta), y=np.degrees(phi), xp=self._response_zens, yp=self._response_azis, fp=self._theta_response, method='cartesian') phi_gains = complex_bilinear_interp(x=np.degrees(theta), y=np.degrees(phi), xp=self._response_zens, yp=self._response_azis, fp=self._phi_response, method='cartesian') freq_interpolator = lambda frequencies: complex_interp( x=frequencies, xp=self._response_freqs, fp=theta_factor * theta_gains + phi_factor * phi_gains, method='euler', outer=0) return freq_interpolator
def test_euler_extrapolation(self): """Test euler complex extrapolation""" steps = np.arange(5) extrap_steps = [steps[0] - 1, steps[-1] + 1] gain = np.array([1, 2, 3, 2, 1]) phase = np.radians([45, 90, 180, 90, 45]) extrap = complex_interp(extrap_steps, steps, gain * np.exp(1j * phase), method='euler', outer=None) assert np.allclose(np.abs(extrap), [gain[0], gain[-1]]) assert np.allclose(np.angle(extrap), [phase[0], phase[-1]]) extrap2 = complex_interp(extrap_steps, steps, gain * np.exp(1j * phase), method='euler', outer=0) assert np.array_equal(extrap2, [0, 0])
def test_cartesian_extrapolation(self): """Test cartesian complex extrapolation""" steps = np.arange(5) extrap_steps = [steps[0] - 1, steps[-1] + 1] real = np.array([1, 2, 3, 2, 1]) imag = np.array([3, 2, 1, 2, 3]) extrap = complex_interp(extrap_steps, steps, real + 1j * imag, method='cartesian', outer=None) assert np.array_equal(np.real(extrap), [real[0], real[-1]]) assert np.array_equal(np.imag(extrap), [imag[0], imag[-1]]) extrap2 = complex_interp(extrap_steps, steps, real + imag, method='cartesian', outer=0) assert np.array_equal(extrap2, [0, 0])
def test_euler_phase_unwrapping(self): """Test phase unwrapping in euler complex interpolation""" steps = np.arange(5) interp_steps = steps[:-1] + 0.5 gain = np.array([1, 2, 3, 2, 1]) phase = np.radians([45, 90, 180, -90, -45]) interp = complex_interp(interp_steps, steps, gain * np.exp(1j * phase), method='euler') phase_interp = np.interp(interp_steps, steps, np.unwrap(phase)) phase_interp = phase_interp % (2 * np.pi) phase_interp[phase_interp > np.pi] -= 2 * np.pi assert np.allclose(np.angle(interp), phase_interp)
def test_euler_interpolation(self): """Test euler complex interpolation""" steps = np.arange(5) interp_steps = steps[:-1] + 0.5 gain = np.array([1, 2, 3, 2, 1]) phase = np.radians([45, 90, 180, 90, 45]) interp = complex_interp(interp_steps, steps, gain * np.exp(1j * phase), method='euler') gain_interp = np.interp(interp_steps, steps, gain) phase_interp = np.interp(interp_steps, steps, phase) assert np.allclose(np.abs(interp), gain_interp) assert np.array_equal(np.angle(interp), phase_interp)
def test_cartesian_interpolation(self): """Test cartesian complex interpolation""" steps = np.arange(5) interp_steps = steps[:-1] + 0.5 real = np.array([1, 2, 3, 2, 1]) imag = np.array([3, 2, 1, 2, 3]) interp = complex_interp(interp_steps, steps, real + 1j * imag, method='cartesian') real_interp = np.interp(interp_steps, steps, real) imag_interp = np.interp(interp_steps, steps, imag) assert np.array_equal(np.real(interp), real_interp) assert np.array_equal(np.imag(interp), imag_interp)
def interpolate_filter(self, frequencies): """ Generate interpolated filter values for given frequencies. Calculate the interpolated values of the antenna's filter gain data for some frequencies. Parameters ---------- frequencies : array_like 1D array of frequencies (Hz) at which to calculate gains. Returns ------- array_like Complex filter gain in voltage for the given `frequencies`. """ return complex_interp(x=frequencies, xp=self._filter_freqs, fp=self._filter_response, method='euler', outer=0)