Skip to content

virgil.radio_toeplitz

Provisional

May change in any 0.4.x release without a deprecation cycle.

The radio χ² of a one-Image fit through precomputed dirty beams and images. See Toeplitz χ².

Radio χ² through the dirty beam (Toeplitz embedding), for one-Image scenes.

When the scene is a single Image I (unit sum), the χ² of ComplexVisData.term is, for each ddid d of observation e,

χ²_d = (C_d − 2 G_e Iᵀ D_d(δ_e) + G_e² Iᵀ B_d I) / s_d²

with G_e = flux · gain_e, C_d = Σ w|V|², the dirty image D_d at the observation's offset δ_e and the dirty beam B_d (a Toeplitz matrix, applied by FFT on a 2N × 2N grid). Precompute them once with ComplexVisData.toeplitz; an evaluation then costs a few FFTs of the image grid, whatever the number of visibilities. See Radio interferometry.

Fitted offsets (offsets="spread") are an opt-in extension. The offset ramp cancels in |M|², so B_d is offset-free, and with the stored spread grid b the dirty image is D(x + δ) = Σ_l b_l e^{2πil(x+δ)/n_f} / ψ̂(x + δ): a phase ramp on b and the kernel transform at non-integer x + δ (a type-3 evaluation), exact while no point's kernel wraps. It builds on type-3 NUFFT evaluation; we know of no prior use of this combination.

Provisional

May change in any 0.4.x release without a deprecation cycle.

Source: Fessler et al. (2005), nufftax, Barnett et al. (2019), Lee & Greengard (2005).

ToeplitzVisData

Bases: Module

Precomputed dirty beams and images of a ComplexVisData (provisional).

Build it with ComplexVisData.toeplitz; its term has the χ², log- normalization, gradient and profiled ŝ of ComplexVisData.term for a scene that is one fixed-layout Image.

Attributes:

Name Type Description
data ComplexVisData
mask (N,) bool

Points used.

npix, pixel_scale_mas, rotation_deg, smooth_fwhm_mas

The Image layout the precompute is for.

image_offset_mas (float, float)

The template's fixed (dra, ddec), folded into the visibilities.

free_offsets bool

Whether D_d can be shifted (offsets="spread").

max_shift_pix float

Largest image-frame offset allowed, in pixels.

nyquist_fraction float

max |t| / π of the used points (t = 2π u × pixel, rad).

margin float or None

The largest nyquist_fraction that free offsets allow, 1 − w/n_f.

arrays dict

bhat, cross, c_sum (Σ w|V|² per ddid), logw, count (points per ddid).

plan = dict(idx=np.asarray(used[idx]), valid=np.asarray(valid), group=np.asarray(chunk_group), last=np.asarray(last), tx=chunked(tx), ty=chunked(ty), h=chunked(h), rot=chunked(rot)) instance-attribute

data = data instance-attribute

mask = mask instance-attribute

npix = npix class-attribute instance-attribute

pixel_scale_mas = float(pix) class-attribute instance-attribute

rotation_deg = float(image.rotation_deg) class-attribute instance-attribute

smooth_fwhm_mas = image.smooth_fwhm_mas class-attribute instance-attribute

image_offset_mas = (dra, ddec) class-attribute instance-attribute

free_offsets = free class-attribute instance-attribute

max_shift_pix = float(bound) class-attribute instance-attribute

nyquist_fraction = tau class-attribute instance-attribute

margin = margin class-attribute instance-attribute

signature = _signature(nuisance) class-attribute instance-attribute

kp = kp class-attribute instance-attribute

sizes = (n_groups, nf_b, nf_d) class-attribute instance-attribute

arrays = dict(self._compute(data.vis, data.weight), count=np.asarray(count)) instance-attribute

layout property

(shape, pixel_scale_mas, rotation_deg, smooth_fwhm_mas).

__init__(data, image, nuisance, mask=None, offsets='none', eps=1e-14, max_offset_mas=None, chunk_size=65536)

rebuild(vis, weight)

The same precompute for new full-length vis and weight (jitted: no recompilation).

term(scene, nuisance, sigma=None)

A likelihood term for fit's likelihoods.

As ComplexVisData.term (same loss, gradient and derived), but with no residual vector: fit with method="lbfgs" or "adam". scene(values) must be one Image of this layout (alone, or the only part of a System) at the template's fixed dra, ddec; the observations' offsets are cal.offset.

direct_term(scene, nuisance, **kwargs)

ComplexVisData.term of the same points, for checks.

chi2_by_ddid(scene, values, nuisance)

(chi2, n) per ddid, as ComplexVisData.chi2_by_ddid.

crosscheck(scene, values, nuisance, chunk_size=10000000)

The χ² per ddid and the loss both ways, and their largest relative difference.

Returns a dict: chi2 and chi2_direct per ddid, loss and loss_direct (½χ² + log_norm), max_rel. chunk_size is the direct term's.