ska_sdp_instrumental_calibration.xarray_processors.ionosphere_solvers module

class ska_sdp_instrumental_calibration.xarray_processors.ionosphere_solvers.IonosphericSolver(vis, modelvis, cluster_indexes=None, block_diagonal=False, niter=15, tol=1e-06, zernike_limit=None)[source]

Bases: object

Solves for ionospheric phase screens using a linearized approach.

This class sets up and solves a system of linear equations to determine the parameters of a phase screen model (e.g., Zernike polynomials) that best fits the observed visibility data. It supports antenna clustering and iterative refinement of the solution.

NOTE: This solver assumes that input visibilities have linear polarisation, with all 4 polarisations (XX, XY, YX, YY) present.

Parameters:
  • vis (xarray.Dataset) -- Input visibility dataset.

  • modelvis (xarray.Dataset) -- Model visibility dataset corresponding to vis.

  • cluster_indexes (numpy.ndarray, optional) -- Array of integers assigning each antenna to a cluster. If None, all antennas are treated as a single cluster (default: None).

  • block_diagonal (bool, optional) -- If True, solve for all clusters simultaneously assuming a block-diagonal system. If False, solve for each cluster sequentially (default: False).

  • niter (int, optional) -- Maximum number of iterations for the solver (default: 15).

  • tol (float, optional) -- Tolerance for the fractional change in parameters to determine convergence (default: 1e-6).

  • zernike_limit (list[int], optional) -- list of Zernike index limits: Generate all Zernikes with n + |m| <= zernike_limit[cluster_id]. If None, a default is used by the solver.

xyz

Cartesian coordinates of the antennas.

Type:

numpy.ndarray

antenna1

Array of first antenna indices for each baseline.

Type:

numpy.ndarray

antenna2

Array of second antenna indices for each baseline.

Type:

numpy.ndarray

change

The maximum fractional change in parameters from the last iteration.

Type:

float

niter

Maximum number of iterations.

Type:

int

tol

Convergence tolerance.

Type:

float

vis

Observed visibilities for the first time step.

Type:

xarray.DataArray

weight

Visibility weights for the first time step.

Type:

xarray.DataArray

flags

Visibility flags for the first time step.

Type:

xarray.DataArray

modelvis

Model visibilities for the first time step.

Type:

xarray.DataArray

pols

List of polarization indices to be used in the solve.

Type:

list

param

List of parameter arrays, one for each cluster.

Type:

list of numpy.ndarray

coeff

List of coefficient arrays, one for each antenna.

Type:

list of numpy.ndarray

solve_function

The method used to solve the normal equations, chosen based on block_diagonal.

Type:

callable

Raises:

ValueError -- If model visibilities are all zero or if polarisations are unsupported.

static solve(vis, modelvis, gaintable, cluster_indexes=None, block_diagonal=False, niter=15, tol=1e-06, zernike_limit=None)[source]
get_updated_params()[source]

Iteratively update the screen parameters until convergence.

In each iteration, this method calls the selected solver function to get a parameter update, adds the update to the current parameters, and applies the resulting phase distortion to the model visibilities for the next iteration.

Parameters:
  • n_cluster (int) -- The number of antenna clusters.

  • n_param (int) -- The total number of parameters to solve for.

Returns:

The final, converged screen parameters.

Return type:

dask.array.Array

build_normal_equation(modelvis, param, cid=None)[source]

Construct the normal equation matrices AA and Ab.

This function builds the linear system AA . x = Ab, where AA = Real(A^H W A) and Ab = Imag(A^H W dV).

Parameters:
  • modelvis (numpy.ndarray) -- The model visibilities.

  • param (numpy.ndarray) -- The current screen parameters.

  • cid (int, optional) -- The cluster ID. If specified, the equation is built only for this cluster. Otherwise, it's built for all clusters (default: None).

Returns:

A tuple containing the matrices AA and Ab.

Return type:

tuple[numpy.ndarray, numpy.ndarray]

build_cluster_design_matrix(modelvis, param, cid=None)[source]

Build the design matrix A for the linear system.

The design matrix A relates the visibility phases to the screen parameters. This method constructs A for either a single specified cluster or for all clusters combined.

Parameters:
  • modelvis (numpy.ndarray) -- The model visibilities.

  • param (numpy.ndarray) -- The current screen parameters.

  • cid (int, optional) -- Cluster ID. If given, the matrix is built only for this cluster. Otherwise, the matrix for all clusters is returned (default: None).

Returns:

The complex-valued design matrix A of shape (n_param, n_baselines, n_freq, n_pol).

Return type:

numpy.ndarray

cluster_design_matrix(modelvis, stn2cid, n_param, cid)[source]

Calculate the design matrix for a single, specified cluster.

This is a helper method that computes the components of the design matrix A for a specific cluster.

Parameters:
  • modelvis (numpy.ndarray) -- The model visibilities.

  • stn2cid (list of list) -- Mapping from station ID to cluster ID.

  • n_param (int) -- The number of parameters for this cluster.

  • cid (int) -- The ID of the cluster for which to build the matrix.

Returns:

The design matrix A for the specified cluster.

Return type:

numpy.ndarray

updated_gain_table(param, gain_data)[source]

Construct the final gain table from the solved parameters.

This method uses the final screen parameters to compute the complex gains for each antenna and frequency.

Parameters:
  • param (numpy.ndarray) -- The final, converged screen parameters for all clusters.

  • gain_data (numpy.ndarray) -- An empty or template gain data array to be filled.

Returns:

The populated gain table data array.

Return type:

numpy.ndarray