hera_sim.sigchain.MutualCoupling

class hera_sim.sigchain.MutualCoupling(uvbeam: UVBeam | str | Path | None = None, reflection: ndarray | Callable | None = None, omega_p: ndarray | Callable | None = None, ant_1_array: ndarray | None = None, ant_2_array: ndarray | None = None, pol_array: ndarray | None = None, array_layout: dict | None = None, coupling_matrix: ndarray | None = None, pixel_interp: str = 'az_za_simple', freq_interp: str = 'cubic', beam_kwargs: dict | None = None, use_numba: bool = True)[source]

Simulate mutual coupling according to Josaitis+ 2022.

This class simulates the “first-order coupling” between visibilities in an array. The model assumes that coupling is induced via re-radiation of incident astrophysical radiation due to an impedance mismatch at the antenna feed, and that the re-radiated signal is in the far-field of every other antenna in the array. Full details can be found here:

The essential equations from the paper are Equations 9 and 19. The implementation here effectively calculates Equation 19 for every visibility in the provided data. The original publication contains an error in Equation 9 (the effective height in transmission should have a complex conjugation applied), which we correct for in our implementation. In addition to this, we assume that every antenna feed has the same impedance, reflection coefficient, and effective height. Applying the correct conjugation, and enforcing these assumptions, the first-order correction to the visibility \({\bf V}_{ij}\) can be written as:

\[{\bf V}_{ij}^{\rm xt} = \sum_k \Bigl[ (1-\delta_{kj}) {\bf V}_{ik}^0 {\bf X}_{jk}^\dagger + (1-\delta_{ik}) {\bf X}_{ik} {\bf V}_{kj}^0 \Bigr],\]

where the “xt” superscript is shorthand for “crosstalk”, the “0” superscript refers to the “zeroth-order” visibilities, \(\delta_{ij}\) is the Kronecker delta, and \({\bf X}_{ij}\) is a “coupling matrix” that describes how radiation emitted from antenna \(j\) is received by antenna \(i\). The coupling matrix can be written as

\[{\bf X}_{jk} \equiv \frac{i\eta_0}{4\lambda} \frac{\Gamma_k}{R_k} \frac{e^{i2\pi\nu\tau_{jk}}}{b_{jk}} {\bf J}_j (\hat{\bf b}_{jk}) {\bf J}_k(\hat{\bf b}_{kj})^\dagger h_0^2,\]

where \(\Gamma\) is the reflection coefficient, \(R\) is the real part of the impedance, \(\eta_0\) is the impedance of free space, \(\lambda\) is the wavelength of the radiation, \(\nu\) is the frequency of the radiation, \(\tau=b/c\) is the delay of the baseline, \(b\) is the baseline length, \(\hat{\bf b}_{ij}\) is a unit vector pointing from antenna \(i\) to antenna \(j\), \({\bf J}\) is the Jones matrix describing the antenna’s peak-normalized far-field radiation pattern, and \(h_0\) is the amplitude of the antenna’s effective height.

The boldfaced variables without any overhead decorations indicate 2x2 matrices:

\[\begin{split}{\bf V} = \begin{pmatrix} V_{XX} & V_{XY} \\ V_{YX} & V_{YY} \end{pmatrix}, \quad {\bf J} = \frac{1}{h_0} \begin{pmatrix} h_{X\theta} & h_{X\phi} \\ h_{Y\theta} & h_{Y\phi} \end{pmatrix}\end{split}\]

The effective height can be rewritten as

\[h_0^2 = \frac{4\lambda^2 R}{\eta_0 \Omega_p}\]

where \(\Omega_p\) is the beam area (i.e. integral of the peak-normalized power beam). Substituting this in to the previous expression for the coupling coefficient and taking antennas to be identical gives

\[{\bf X}_{jk} = \frac{i\Gamma}{\Omega_p} \frac{e^{i2\pi\nu\tau_{jk}}} {b_{jk}/\lambda} {\bf J}(\hat{\bf b}_{jk}) {\bf J}(\hat{\bf b}_{kj})^\dagger.\]

In order to efficiently simulate the mutual coupling, the antenna and polarization axes of the visibilities and coupling matrix are combined into a single “antenna-polarization” axis, and the problem is recast as a simple matrix multiplication.

Parameters:
  • uvbeam – The beam (i.e. Jones matrix) to be used for calculating the coupling matrix. This may either be a pyuvdata.UVBeam object, a path to a file that may be read into a pyuvdata.UVBeam object, or a string identifying which pyuvsim.AnalyticBeam to use. Not required if providing a pre-calculated coupling matrix.

  • reflection – The reflection coefficient to use for calculating the coupling matrix. Should be either a np.ndarray or an interpolation object that gives the reflection coefficient as a function of frequency (in GHz). Not required if providing a pre-calculated coupling matrix.

  • omega_p – The integral of the peak-normalized power beam as a function of frequency (in GHz). Not required if providing a pre-calculated coupling matrix.

  • ant_1_array – Array of integers specifying the number of the first antenna in each visibility. Required for calculating the coupling matrix and the coupled visibilities.

  • ant_2_array – Array of integers specifying the number of the second antenna in each visibility.

  • pol_array – Array of integers representing polarization numbers, following the convention used for pyuvdata.UVData objects. Required for calculating the coupled visibilities.

  • array_layout – Dictionary mapping antenna numbers to their positions in local East- North-Up coordinates, expressed in meters. Not required if providing a pre-calculated coupling matrix.

  • coupling_matrix – Matrix describing how radiation is coupled between antennas in the array. Should have shape (1, n_freqs, 2*n_ants, 2*n_ants). The even elements along the “antenna-polarization” axes correspond to the “X” polarization; the odd elements correspond to the “Y” polarization.

  • pixel_interp – The name of the spatial interpolation method used for the beam. Not required if using an analytic beam or if providing a pre-computed coupling matrix.

  • freq_interp – The order of the spline to be used for interpolating the beam in frequency. Not required if using an analytic beam or if providing a pre-computed coupling matrix.

  • beam_kwargs – Additional keywords used for either reading in a beam or creating an analytic beam.

  • use_numba – Whether to use numba for accelerating the simulation. Default is to use numba if it is installed.

Methods

__call__(freqs, visibilities, **kwargs)

Calculate the first-order coupled visibilities.

build_coupling_matrix(freqs, array_layout, ...)

Calculate the coupling matrix used for mutual coupling simulation.

get_aliases()

Get all the aliases by which this model can be identified.

get_model(mdl)

Get a model with a particular name (including aliases).

get_models([with_aliases])

Get a dictionary of models associated with this component.

Attributes

attrs_to_pull

Mapping between parameter names and Simulator attributes

is_multiplicative

Whether this systematic multiplies existing visibilities

is_randomized

Whether this systematic contains a randomized component

return_type

Whether the returned value is per-antenna, per-baseline, or the full array