rm_lite.utils.synthesis

RM-synthesis utils

Attributes

Classes

FDFOptions

Options for RM-synthesis, shared by the 1D and 3D tools

FWHM

FaradayMoments

Moments of the polarised intensity Faraday depth spectrum.

FractionalSpectra

RMSFParams

RM spread function parameters

RMSFResults

Results of the RMSF calculation

RMSynthParams

Parameters for RM-synthesis calculation

RMsynthResults

Results of the RM-synthesis calculation

SigmaAdd

Sigma_add complexity metrics

SigmaAddArrays

StokesData

Stokes parameters and errors

StokesSigmaAdd

Stokes Sigma_add complexity metrics

TheoreticalNoise

Theoretical noise of the FDF

Functions

_debias_fdf_block(→ numpy.typing.NDArray[numpy.float64])

_fractional_with_error(...)

Elementwise num/den with independent-error propagation.

_lambda_sq_density(→ numpy.typing.NDArray[numpy.float64])

Local lambda^2 sampling density on a virtual grid of cells width cell_m2:

_require_single_chunk_on_axis(→ None)

Raise if arr is a dask array with more than one chunk along axis.

briggs_weight(→ numpy.typing.NDArray[numpy.float64])

Briggs robust weights interpolating natural (robust -> +inf) and

calc_faraday_moments(→ FaradayMoments)

Compute the zeroth, first, and second moments of a Faraday depth spectrum.

calc_mom2_fdf(→ float)

Calculate the 2nd moment of the polarised intensity FDF. Can be applied to

calculate_sigma_add(→ SigmaAdd)

Calculate the most likely value of additional scatter, assuming the

calculate_sigma_add_arr(→ SigmaAddArrays)

cdf_percentile(→ float)

Return the value at a given percentile of a cumulative distribution function

compute_rmsf_params(→ RMSFParams)

compute_rmsynth_params(→ RMSynthParams)

Calculate the parameters for RM-synthesis.

compute_theoretical_noise(→ TheoreticalNoise)

create_fractional_spectra(→ FractionalSpectra | None)

debias_fdf(→ numpy.typing.NDArray[numpy.float64])

Compute debiased polarised intensity amplitudes from a complex FDF cube.

freq_to_lambda2(→ T)

Convert frequency to lambda^2.

get_fdf_parameters(→ polars.DataFrame)

Measure standard parameters from a complex Faraday Dispersion Function.

get_fwhm_rmsf(→ FWHM)

Calculate the FWHM of the RMSF.

get_mask_index(→ numpy.typing.NDArray[numpy.bool_])

get_rmsf_nufft(→ RMSFResults)

Compute the RMSF for a given set of lambda^2 values.

inverse_rmsynth_nufft(...)

Inverse RM-synthesis - FDF to Stokes Q and U in wavelength^2 space.

lambda2_to_freq(→ T)

Convert lambda^2 to frequency.

make_double_phi_arr(→ numpy.typing.NDArray[numpy.float64])

make_phi_arr(→ numpy.typing.NDArray[numpy.float64])

Construct a Faraday depth array.

measure_fdf_complexity(→ float)

measure_qu_complexity(→ StokesSigmaAdd)

natural_weight(→ numpy.typing.NDArray[numpy.float64])

Natural (inverse-variance) weights; all ones if no noise is given.

rmsynth_nufft(→ numpy.typing.NDArray[numpy.complex128])

Run RM-synthesis on a cube of Stokes Q and U data using the NUFFT method.

uniform_lsq_weight(→ numpy.typing.NDArray[numpy.float64])

Uniform-in-lambda^2 weights: natural weights divided by the virtual-grid

Module Contents

class rm_lite.utils.synthesis.FDFOptions

Options for RM-synthesis, shared by the 1D and 3D tools

__post_init__() None
d_phi_radm2: float | None = None

Faraday depth resolution

do_fit_rmsf: bool = False

Fit RMSF

do_fit_rmsf_real: bool = False

Fit real part of the RMSF

n_samples: float | None = 10.0

Number of samples

phi_max_radm2: float | None = None

Maximum Faraday depth

robust: float | None = None

Briggs robust parameter (required for weight_type=’briggs’)

weight_type: WeightType = 'variance'

Weight type

class rm_lite.utils.synthesis.FWHM

Bases: NamedTuple

d_lambda_sq_max_m2: float

The maximum difference in lambda^2 values

fwhm_rmsf_radm2: float

The FWHM of the RMSF main lobe

lambda_sq_range_m2: float

The range of lambda^2 values

class rm_lite.utils.synthesis.FaradayMoments

Bases: NamedTuple

Moments of the polarised intensity Faraday depth spectrum.

mom0: numpy.typing.NDArray[numpy.float64]

total polarised intensity, in the input FDF amplitude units

Type:

Zeroth moment

mom1: numpy.typing.NDArray[numpy.float64]

intensity-weighted mean Faraday depth in rad/m^2

Type:

First moment

mom2: numpy.typing.NDArray[numpy.float64]

intensity-weighted Faraday depth dispersion in rad/m^2

Type:

Second moment

class rm_lite.utils.synthesis.FractionalSpectra

Bases: NamedTuple

fit_result: rm_lite.utils.fitting.FitResult | None
no_nan_idx: numpy.typing.NDArray[numpy.bool_]
stokes_data: StokesData
class rm_lite.utils.synthesis.RMSFParams

Bases: NamedTuple

RM spread function parameters

phi_max: float

Maximum Faraday depth

phi_max_scale: float

Maximum Faraday depth scale

rmsf_fwhm_meas: float

Measured FWHM of the RMSF

rmsf_fwhm_theory: float

Theoretical FWHM of the RMSF

rmsf_results: RMSFResults

Empirical RMSF

class rm_lite.utils.synthesis.RMSFResults

Bases: NamedTuple

Results of the RMSF calculation

fit_status_arr: numpy.typing.NDArray[numpy.float64]

The status of the RMSF fit

fwhm_rmsf_arr: numpy.typing.NDArray[numpy.float64]

The FWHM of the RMSF main lobe

phi_double_arr_radm2: numpy.typing.NDArray[numpy.float64]

The (double length) Faraday depth array

rmsf_cube: numpy.typing.NDArray[numpy.float64]

The RMSF cube

class rm_lite.utils.synthesis.RMSynthParams

Bases: NamedTuple

Parameters for RM-synthesis calculation

lam_sq_0_m2: float

Reference wavelength^2 value

lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64]

Wavelength^2 values in m^2

phi_arr_radm2: numpy.typing.NDArray[numpy.float64]

Faraday depth values in rad/m^2

weight_arr: numpy.typing.NDArray[numpy.float64]

Weight array

class rm_lite.utils.synthesis.RMsynthResults

Bases: NamedTuple

Results of the RM-synthesis calculation

fdf_dirty_cube: numpy.typing.NDArray[numpy.float64]

The Faraday dispersion function cube

lam_sq_0_m2: float

The reference lambda^2 value

class rm_lite.utils.synthesis.SigmaAdd

Bases: NamedTuple

Sigma_add complexity metrics

sigma_add: float

Sigma_add median value

sigma_add_arrays: SigmaAddArrays

Sigma_add arrays

sigma_add_minus: float

Sigma_add lower quartile

sigma_add_plus: float

Sigma_add upper quartile

class rm_lite.utils.synthesis.SigmaAddArrays

Bases: NamedTuple

cdf: numpy.typing.NDArray[numpy.float64]

CDF array of the additional noise term

pdf: numpy.typing.NDArray[numpy.float64]

PDF array of the additional noise term

sigma_add_arr: numpy.typing.NDArray[numpy.float64]

Array of additional noise values

class rm_lite.utils.synthesis.StokesData

Bases: NamedTuple

Stokes parameters and errors

complex_pol_arr: numpy.typing.NDArray[numpy.complex128]

Stokes Q and U array

complex_pol_error: numpy.typing.NDArray[numpy.complex128]

Stokes Q and U error array

freq_arr_hz: numpy.typing.NDArray[numpy.float64]

Frequency array in Hz

stokes_i_arr: numpy.typing.NDArray[numpy.float64] | None = None

Stokes I array

stokes_i_error_arr: numpy.typing.NDArray[numpy.float64] | None = None

Stokes I error array

stokes_i_model_arr: numpy.typing.NDArray[numpy.float64] | None = None

Stokes I model array

stokes_i_model_error: numpy.typing.NDArray[numpy.float64] | None = None

Stokes I model error array

class rm_lite.utils.synthesis.StokesSigmaAdd

Bases: NamedTuple

Stokes Sigma_add complexity metrics

sigma_add_p: SigmaAdd

Sigma_add for polarised intensity

sigma_add_q: SigmaAdd

Sigma_add for Stokes Q

sigma_add_u: SigmaAdd

Sigma_add for Stokes U

class rm_lite.utils.synthesis.TheoreticalNoise

Bases: NamedTuple

Theoretical noise of the FDF

fdf_error_noise: float

Theoretical noise of the FDF

fdf_q_noise: float

Theoretical noise of the real FDF

fdf_u_noise: float

Theoretical noise of the imaginary FDF

rm_lite.utils.synthesis._debias_fdf_block(complex_fdf_arr: numpy.typing.NDArray[numpy.complex128], phi_arr_radm2: numpy.typing.NDArray[numpy.float64], lam_sq_0_m2: float, axis: int, filter_size: int) numpy.typing.NDArray[numpy.float64]
rm_lite.utils.synthesis._fractional_with_error(num: numpy.typing.NDArray[numpy.float64], num_err: numpy.typing.NDArray[numpy.float64], den: numpy.typing.NDArray[numpy.float64], den_err: numpy.typing.NDArray[numpy.float64]) tuple[numpy.typing.NDArray[numpy.float64], numpy.typing.NDArray[numpy.float64]]

Elementwise num/den with independent-error propagation.

Same closed form uncertainties uses, but in numpy so a degenerate model (near-zero denominator, huge covariance) overflows to inf/nan instead of raising OverflowError the way python floats do.

rm_lite.utils.synthesis._lambda_sq_density(lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64], natural_weight_arr: numpy.typing.NDArray[numpy.float64], cell_m2: float) numpy.typing.NDArray[numpy.float64]

Local lambda^2 sampling density on a virtual grid of cells width cell_m2: the total natural weight in each channel’s cell, over the cell width. Channels sharing a cell share one density, so uniform_lsq (natural/density) gives them equal weight and no single channel jumps within a cell; each occupied cell then contributes equally (interferometric uniform weighting). briggs blends it with the natural weight via robust. The density steps where the true sampling density changes (gaps, channelisation changes); this is correct inverse-density weighting, not aliasing. Flagged channels (zero natural weight) get zero density.

rm_lite.utils.synthesis._require_single_chunk_on_axis(arr: Any, axis: int, reason: str) None

Raise if arr is a dask array with more than one chunk along axis.

A median reduction across the Faraday depth axis is not supported by dask.

rm_lite.utils.synthesis.briggs_weight(lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64], natural_weight_arr: numpy.typing.NDArray[numpy.float64], robust: float, cell_m2: float) numpy.typing.NDArray[numpy.float64]

Briggs robust weights interpolating natural (robust -> +inf) and uniform-in-lambda^2 (robust -> -inf). The f^2 factor is normalised by the natural-weighted mean sampling density (CASA convention) so robust is comparable across datasets with different channel counts.

rm_lite.utils.synthesis.calc_faraday_moments(complex_fdf_arr: numpy.typing.NDArray[numpy.complex128] | numpy.typing.NDArray[numpy.float64], phi_arr_radm2: numpy.typing.NDArray[numpy.float64], fwhm_rmsf_radm2: float | numpy.typing.NDArray[numpy.float64], axis: int = 0, threshold: float | None = None, auto_threshold_sigma: float | None = None, debias: bool = False, lam_sq_0_m2: float | None = None, debias_filter_size: int = 5, min_weight_fraction: float | None = None) FaradayMoments

Compute the zeroth, first, and second moments of a Faraday depth spectrum.

The FDF amplitude is in units per RMSF (the native RM-synthesis scale). mom0 is converted to integrated units by dividing the Faraday-depth sum by the RMSF area (a Gaussian of FWHM fwhm_rmsf_radm2), so an unresolved component of peak amplitude P gives mom0 = P.

Complex input is reduced with np.abs; real input is used as-is, so the signed debiased amplitudes from debias_fdf integrate without folding noise into a positive floor. debias=True applies that debiasing internally (needs lam_sq_0_m2 and a spatial axis), giving unbiased moments with no threshold.

Works on numpy or dask arrays of any dimensionality: the Faraday depth axis is reduced away, the rest preserved. auto_threshold_sigma and debias=True reduce over the Faraday depth axis, so for dask that axis must be one chunk.

Parameters:
  • complex_fdf_arr (NDArray[np.complex128]) – Complex (or real) FDF.

  • phi_arr_radm2 (NDArray[np.float64]) – Uniformly spaced Faraday depth array in rad/m^2.

  • fwhm_rmsf_radm2 (float | NDArray[np.float64]) – FWHM of the RMSF main lobe in rad/m^2. An array must broadcast against the FDF shape with the Faraday depth axis removed.

  • axis (int, optional) – Faraday depth axis of complex_fdf_arr. Defaults to 0.

  • threshold (float | None, optional) – Exclude amplitudes below this value (in FDF amplitude units). Not supported with debias=True. Defaults to None.

  • auto_threshold_sigma (float | None, optional) – Exclude amplitudes below this multiple of the per-spectrum noise (a robust mad_std of the real and imaginary parts). Mutually exclusive with threshold, and not supported with debias=True. Defaults to None.

  • debias (bool, optional) – Debias the FDF amplitudes with debias_fdf before computing the moments. Requires complex input with a spatial axis, and lam_sq_0_m2. Defaults to False.

  • lam_sq_0_m2 (float | None, optional) – Reference wavelength^2 of the RM-synthesis derotation, passed to debias_fdf. Required when debias=True. Defaults to None.

  • debias_filter_size (int, optional) – Spatial median filter size passed to debias_fdf. Defaults to 5.

  • min_weight_fraction (float | None, optional) – Opt-in guard for signed input. When set, mom1/mom2 are NaN wherever the net weight |sum(amplitude)| is below this fraction of the total absolute weight sum(|amplitude|), so near-cancelling noise spectra do not yield spurious finite Faraday depths. mom0 is unaffected. Off by default (irreversible masking); a mom0 detection cut is the alternative. Defaults to None.

Returns:

mom0 (FDF amplitude units), mom1 (rad/m^2), and mom2

(dispersion, rad/m^2). Spectra with no valid amplitude have mom0 = 0 and mom1 = mom2 = NaN.

Return type:

FaradayMoments

rm_lite.utils.synthesis.calc_mom2_fdf(complex_fdf_arr: numpy.typing.NDArray[numpy.complex128], phi_arr_radm2: numpy.typing.NDArray[numpy.float64]) float

Calculate the 2nd moment of the polarised intensity FDF. Can be applied to a clean component spectrum or a standard FDF

rm_lite.utils.synthesis.calculate_sigma_add(y_arr: numpy.typing.NDArray[numpy.float64], dy_arr: numpy.typing.NDArray[numpy.float64], median: float | None = None, noise: float | None = None, n_samples: int = 1000) SigmaAdd

Calculate the most likely value of additional scatter, assuming the input data is drawn from a normal distribution. The total uncertainty on each data point Y_i is modelled as dYtot_i**2 = dY_i**2 + dYadd**2.

rm_lite.utils.synthesis.calculate_sigma_add_arr(y_arr: numpy.typing.NDArray[numpy.float64], dy_arr: numpy.typing.NDArray[numpy.float64], median: float | None = None, noise: float | None = None, n_samples: int = 1000) SigmaAddArrays
rm_lite.utils.synthesis.cdf_percentile(values: numpy.typing.NDArray[numpy.float64], cdf: numpy.typing.NDArray[numpy.float64], q: float = 50.0) float

Return the value at a given percentile of a cumulative distribution function

Parameters:
  • values (NDArray[np.float64]) – Array of values

  • cdf (NDArray[np.float64]) – Cumulative distribution function

  • q (float, optional) – Percentile. Defaults to 50.0.

Returns:

Interpolated value at the given percentile

Return type:

float

rm_lite.utils.synthesis.compute_rmsf_params(freq_arr_hz: numpy.typing.NDArray[numpy.float64], weight_arr: numpy.typing.NDArray[numpy.float64]) RMSFParams
rm_lite.utils.synthesis.compute_rmsynth_params(freq_arr_hz: numpy.typing.NDArray[numpy.float64], complex_pol_arr: numpy.typing.NDArray[numpy.complex128], complex_pol_error: numpy.typing.NDArray[numpy.complex128], fdf_options: FDFOptions) RMSynthParams

Calculate the parameters for RM-synthesis.

Parameters:
  • freq_arr_hz (NDArray[np.float64]) – Frequency array in Hz

  • pol_arr (NDArray[np.complex128]) – Complex polarisation array

  • real_qu_error (NDArray[np.float64 | np.float32]) – Error in Stokes Q and U (real)

  • fdf_options (FDFOptions) – Options for RM-synthesis

Raises:

ValueError – If d_phi_radm2 is not provided and n_samples is None.

Returns:

Wavelength^2 values, reference wavelength^2, Faraday depth values, weight array

Return type:

RMSynthParams

rm_lite.utils.synthesis.compute_theoretical_noise(complex_pol_error: numpy.typing.NDArray[numpy.complex128], weight_arr: numpy.typing.NDArray[numpy.float64]) TheoreticalNoise
rm_lite.utils.synthesis.create_fractional_spectra(stokes_data: StokesData, ref_freq_hz: float, fit_options: rm_lite.utils.fitting.StokesIFitOptions) FractionalSpectra | None
rm_lite.utils.synthesis.debias_fdf(complex_fdf_arr: numpy.typing.NDArray[numpy.complex128], phi_arr_radm2: numpy.typing.NDArray[numpy.float64], lam_sq_0_m2: float, axis: int = 0, filter_size: int = 5) numpy.typing.NDArray[numpy.float64]

Compute debiased polarised intensity amplitudes from a complex FDF cube.

Implements the polarisation de-biasing of Mueller, Beck & Krause (2017, A&A 600, A63), adapted to Faraday depth cubes: the polarisation angle in each Faraday depth plane is median-filtered over the spatial axes (via its cos/sin components, dodging the angle wrap), and the observed Q + iU is projected onto the filtered-angle direction, P* = U sin(theta_m) + Q cos(theta_m). Unlike abs(fdf), the result is noise-like (zero-mean Gaussian) in signal-free regions, at the cost of allowing negative values. Summed over Faraday depth (e.g. by calc_faraday_moments) the noise cancels instead of accumulating a positive floor.

The Mueller et al. method assumes the angle is smooth across the filter box, which an FDF plane violates wherever RM varies: its angle is 2 psi0 + 2 lam_sq_0 (RM - phi). That deterministic ramp is removed first, by derotating each spectrum with a per-pixel peak Faraday depth estimate (the amplitude-weighted centroid of the half-max region about the peak), so only the intrinsic angle 2 psi0, assumed spatially smooth, is filtered. Sightlines with multiple components at very different Faraday depths are only derotated for the dominant peak; secondary components lose cos(2 lam_sq_0 dRM) of amplitude in the projection.

Works on numpy or dask arrays (dask via map_overlap with a filter_size // 2 spatial halo; the Faraday depth axis must be a single chunk, as produced by rm_lite.tools_3d).

Parameters:
  • complex_fdf_arr (NDArray[np.complex128]) – Complex FDF with at least one spatial axis (2D or 3D).

  • phi_arr_radm2 (NDArray[np.float64]) – Uniformly spaced Faraday depth array in rad/m^2.

  • lam_sq_0_m2 (float) – Reference wavelength^2 of the RM-synthesis derotation (e.g. RMSynth3DResults.lam_sq_0_m2). Pass 0 to skip the RM derotation (the original Mueller et al. method, valid only for spatially smooth RM).

  • axis (int, optional) – Faraday depth axis, excluded from the spatial median filter (each Faraday depth plane is filtered independently). Defaults to 0.

  • filter_size (int, optional) – Odd spatial median filter box size in pixels. Defaults to 5.

Returns:

Debiased polarised intensity, same shape as the input.

Return type:

NDArray[np.float64]

rm_lite.utils.synthesis.freq_to_lambda2(freq_hz: T) T

Convert frequency to lambda^2.

Parameters:

freq_hz (float) – Frequency in Hz

Returns:

Wavelength^2 in m^2

Return type:

float

rm_lite.utils.synthesis.get_fdf_parameters(fdf_arr: numpy.typing.NDArray[numpy.complex128], phi_arr_radm2: numpy.typing.NDArray[numpy.float64], fwhm_rmsf_radm2: float, freq_arr_hz: numpy.typing.NDArray[numpy.float64], complex_pol_arr: numpy.typing.NDArray[numpy.complex128], complex_pol_error: numpy.typing.NDArray[numpy.complex128], lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64], lam_sq_0_m2: float, stokes_i_reference_flux: float, theoretical_noise: TheoreticalNoise, fit_function: Literal['log', 'linear'], bias_correction_snr: float = 5.0, moment_threshold_snr: float = 5.0) polars.DataFrame

Measure standard parameters from a complex Faraday Dispersion Function. Currently this function assumes that the noise levels in the Stokes Q and U spectra are the same. Returns a dictionary containing measured parameters.

Faraday moments (see calc_faraday_moments) are computed with amplitudes below moment_threshold_snr times the theoretical FDF noise excluded. mom0_debias additionally corrects each amplitude for polarisation bias (the same 2.3 sigma^2 correction applied to the fitted peak) before integrating.

rm_lite.utils.synthesis.get_fwhm_rmsf(lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64]) FWHM

Calculate the FWHM of the RMSF.

Parameters:
  • lambda_sq_arr_m2 (NDArray[np.float64]) – Wavelength^2 values in m^2

  • super_resolution (bool, optional) – Use Cotton+Rudnick superresolution. Defaults to False.

Returns:

FWHM of the RMSF main lobe, maximum difference in lambda^2 values, range of lambda^2 values

Return type:

fwhm_rmsf_arr

rm_lite.utils.synthesis.get_mask_index(stokes_data: StokesData) numpy.typing.NDArray[numpy.bool_]
rm_lite.utils.synthesis.get_rmsf_nufft(lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64], phi_arr_radm2: numpy.typing.NDArray[numpy.float64], weight_arr: numpy.typing.NDArray[numpy.float64], lam_sq_0_m2: float, mask_arr: numpy.typing.NDArray[numpy.bool_] | None = None, do_fit_rmsf: bool = False, do_fit_rmsf_real: bool = False, eps: float = 1e-06, nthreads: int = 0) RMSFResults

Compute the RMSF for a given set of lambda^2 values.

Parameters:
  • lambda_sq_arr_m2 (NDArray[np.float64]) – Wavelength^2 values in m^2

  • phi_arr_radm2 (NDArray[np.float64]) – Faraday depth values in rad/m^2

  • weight_arr (NDArray[np.float64]) – Weight array

  • lam_sq_0_m2 (float) – Reference wavelength^2 value

  • super_resolution (bool, optional) – Use superresolution. Defaults to False.

  • mask_arr (Optional[NDArray[np.float64]], optional) – Mask array. Defaults to None.

  • do_fit_rmsf (bool, optional) – Fit the RMSF with a Gaussian. Defaults to False.

  • do_fit_rmsf_real (bool, optional) – Fit the real part of the. Defaults to False.

  • eps (float, optional) – NUFFT tolerance. Defaults to 1e-6.

  • nthreads (int, optional) – finufft OpenMP threads. 0 uses finufft’s default (all cores). Set to 1 when parallelising across chunks with dask, to avoid oversubscription. Defaults to 0.

Raises:
  • ValueError – If the wavelength^2 and weight arrays are not the same shape.

  • ValueError – If the mask dimensions are > 3.

  • ValueError – If the mask depth does not match the lambda^2 vector.

Returns:

rmsf_cube, phi_double_arr_radm2, fwhm_rmsf_arr, fit_status_arr

Return type:

RMSFResults

rm_lite.utils.synthesis.inverse_rmsynth_nufft(complex_fdf_arr: numpy.typing.NDArray[numpy.complex128], lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64], phi_arr_radm2: numpy.typing.NDArray[numpy.float64], lam_sq_0_m2: float, eps: float = 1e-06, nthreads: int = 0) numpy.typing.NDArray[numpy.complex128]

Inverse RM-synthesis - FDF to Stokes Q and U in wavelength^2 space.

Parameters:
  • complex_fdf_arr (NDArray[np.complex128]) – Complex polarisation array in Faraday depth space

  • lambda_sq_arr_m2 (NDArray[np.float64]) – Wavelength^2 values in m^2

  • phi_arr_radm2 (NDArray[np.float64]) – Faraday depth values in rad/m^2

  • lam_sq_0_m2 (float) – Reference wavelength^2 value

  • eps (float, optional) – NUFFT tolerance. Defaults to 1e-6.

  • nthreads (int, optional) – finufft OpenMP threads. 0 uses finufft’s default (all cores). Defaults to 0.

Raises:
  • ValueError – If the Stokes Q and U data arrays are not the same shape.

  • ValueError – If the data dimensions are > 3.

  • ValueError – If the data depth does not match the lambda^2 vector.

Returns:

Complex polarisation array in wavelength^2 space

Return type:

NDArray[np.float64]

rm_lite.utils.synthesis.lambda2_to_freq(lambda_sq_m2: T) T

Convert lambda^2 to frequency.

Parameters:

lambda_sq_m2 (NDArray[np.float64]) – Wavelength^2 in m^2

Returns:

Frequency in Hz

Return type:

NDArray[np.float64]

rm_lite.utils.synthesis.make_double_phi_arr(phi_arr_radm2: numpy.typing.NDArray[numpy.float64]) numpy.typing.NDArray[numpy.float64]
rm_lite.utils.synthesis.make_phi_arr(phi_max_radm2: float, d_phi_radm2: float) numpy.typing.NDArray[numpy.float64]

Construct a Faraday depth array.

Parameters:
  • phi_max_radm2 (float) – Maximum Faraday depth in rad/m^2

  • d_phi_radm2 (float) – Spacing in Faraday depth in rad/m^2

Returns:

Faraday depth array in rad/m^2

Return type:

NDArray[np.float64]

rm_lite.utils.synthesis.measure_fdf_complexity(phi_arr_radm2: numpy.typing.NDArray[numpy.float64], complex_fdf_arr: numpy.typing.NDArray[numpy.complex128]) float
rm_lite.utils.synthesis.measure_qu_complexity(freq_arr_hz: numpy.typing.NDArray[numpy.float64], complex_pol_arr: numpy.typing.NDArray[numpy.complex128], complex_pol_error: numpy.typing.NDArray[numpy.complex128], frac_pol: float, psi0_deg: float, rm_radm2: float) StokesSigmaAdd
rm_lite.utils.synthesis.natural_weight(real_qu_error: numpy.typing.NDArray[numpy.float64]) numpy.typing.NDArray[numpy.float64]

Natural (inverse-variance) weights; all ones if no noise is given.

rm_lite.utils.synthesis.rmsynth_nufft(complex_pol_arr: numpy.typing.NDArray[numpy.complex128], lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64], phi_arr_radm2: numpy.typing.NDArray[numpy.float64], weight_arr: numpy.typing.NDArray[numpy.float64], lam_sq_0_m2: float, eps: float = 1e-06, nthreads: int = 0) numpy.typing.NDArray[numpy.complex128]

Run RM-synthesis on a cube of Stokes Q and U data using the NUFFT method.

Parameters:
  • complex_pol_arr (NDArray[np.complex128]) – Complex polarisation values (Q + iU)

  • lambda_sq_arr_m2 (NDArray[np.float64]) – Wavelength^2 values in m^2

  • phi_arr_radm2 (NDArray[np.float64]) – Faraday depth values in rad/m^2

  • weight_arr (NDArray[np.float64]) – Weight array

  • lam_sq_0_m2 (Optional[float], optional) – Reference wavelength^2 in m^2. Defaults to None.

  • eps (float, optional) – NUFFT tolerance. Defaults to 1e-6.

  • nthreads (int, optional) – finufft OpenMP threads. 0 uses finufft’s default (all cores). Set to 1 when parallelising across chunks with dask, to avoid oversubscription. Defaults to 0.

Raises:
  • ValueError – If the weight and lambda^2 arrays are not the same shape.

  • ValueError – If the Stokes Q and U data arrays are not the same shape.

  • ValueError – If the data dimensions are > 3.

  • ValueError – If the data depth does not match the lambda^2 vector.

Returns:

Dirty Faraday dispersion function cube

Return type:

NDArray[np.float64]

rm_lite.utils.synthesis.uniform_lsq_weight(lambda_sq_arr_m2: numpy.typing.NDArray[numpy.float64], natural_weight_arr: numpy.typing.NDArray[numpy.float64], cell_m2: float) numpy.typing.NDArray[numpy.float64]

Uniform-in-lambda^2 weights: natural weights divided by the virtual-grid lambda^2 sampling density, so each occupied cell contributes equally regardless of how densely it is sampled, and channels sharing a cell get equal weight. This is interferometric uniform weighting on the lambda^2 grid; it narrows the RMSF main lobe. The density (and hence the weight) steps where the true sampling density changes (gaps, channelisation).

rm_lite.utils.synthesis.POLARISATION_BIAS_FACTOR = 2.3
rm_lite.utils.synthesis.T
rm_lite.utils.synthesis.WEIGHT_TYPES: tuple[str, Ellipsis] = ('variance', 'natural', 'uniform', 'uniform_lsq', 'briggs')
rm_lite.utils.synthesis.WeightType

variance/natural (1/sigma^2, equivalent), uniform (equal per channel), uniform_lsq (equal per lambda^2 interval, narrows the RMSF), briggs (robust interpolation between natural and uniform_lsq, needs robust).

Type:

RM-synthesis weighting

rm_lite.utils.synthesis.fdf_params_schema
rm_lite.utils.synthesis.fdf_params_schema_df