virgil.observables
Spectro-interferometric observables that follow the visibilities and phases
in an OIData data vector: OI_FLUX spectra (absolute
up to a grey scale, or normalized), correlated fluxes, |V| beside V², triple
amplitudes, and continuum-normalized differential phases. Read them with
read_oifits(..., extras=...) or OIData(path, extras=...); the guide is
Spectro-interferometric observables.
Spectro-interferometric observables beside V² and closure phase.
OIData keeps its visibilities (vis) and
phases (phi) as before. The observables here are further blocks of the
same data vector, in OIData.extras, read with
read_oifits(..., extras=...) (see
read_oifits). Each block predicts its data
from the model and whitens its own residuals, so the likelihood keeps one
whitened residual vector:
"flux":OI_FLUXas a spectrum known up to a grey scale,F(λ) = k Σ fᵢ(λ)fromtotal_spectrum(FluxSpectrum);"nflux":OI_FLUXnormalized to its continuum, F(λ)/F_c(λ), the same with the model normalized over the continuum channels;"corrflux": correlated fluxes (VISAMPwithAMPTYP = 'correlated flux'), k |Σ fᵢ(λ) Vᵢ|, up to a grey scale;"visamp": |V| (VISAMP,AMPTYP = 'absolute') beside V² (VisibilityAmplitude);"t3amp": triple amplitudes |V_ab V_bc V_ac| (TripleAmplitude);"visphi": differential phases, the exact arg V(λ) with the pipeline's continuum normalization applied as a linear operator (DifferentialPhase).
Grey scales are marginalized, not fitted. A spectrum's scale k (and an
optional polynomial in λ times the spectrum) enters linearly, so with a
Gaussian prior it integrates out in closed form (Luger, Foreman-Mackey &
Hogg 2017; virgil._linear): the data are Gaussian with covariance
D + A Λ Aᵀ about A μ, whitened by the same successive rank-one
steps as the 6d gains, with the log-determinant (which depends on the
model's spectral shape) kept in the effective errors. The conditional
posterior of k is
flux_scale_posterior.
The prior on k is stated, never taken from the data. Give it as
scale=(mean, sd) in the data's units (e.g. Jy), with
OIData.with_flux_scale. Normalized
spectra ("nflux") default to (1, 0.1). The Gaussian is a
proposal: k is a positive scale, whose Jeffreys prior is 1/k on stated
bounds. The two differ by about σ_k/k, which is negligible for a
well-measured spectrum. For the Jeffreys posterior, reweight samples of k
from the conditional posterior by 1 / (k N(k; mean, sd²)) within the
bounds, or sample log k under a log-uniform prior directly, as a model
parameter rather than marginalized. Make no evidence claims that depend
on the Gaussian's width.
Differential phases. A pipeline's differential phase is arg V minus a
fit of a + b/λ (an offset and a delay) over continuum channels, per
baseline and frame. That fit is a linear operator N = I − L on the phases
of one row (continuum_operator), so virgil applies the same N to the
exact model phase, never the photocentre approximation, which fails for
resolved structure. If our basis contains the pipeline's, N N_pipe = N, so
the data may be re-normalized safely. Their covariance is N D Nᵀ, which is
whitened as a dense block per frame. Projecting out a linear basis is the
flat-prior limit of marginalizing those nuisances: the likelihood of N d
with covariance N D Nᵀ is the same whichever projection with that null
space is used (restricted maximum likelihood).
Without double counting closure phases (the default of the design note, S §2.3): with closure phases in the data, each frame's baseline phases are also projected onto the telescope-differenced subspace φ_ab = a_a − a_b, orthogonal to every closure, and only channels in the line windows are kept. The closure phases (everywhere) and this closure-free part of the differential phase (in the lines) then measure different things. The cross-covariance between them is neglected as an approximation: it is exactly zero only when the baseline errors of a frame and channel are equal. For unequal errors it is nonzero, and the independent-block likelihood is not exact. The joint covariance is preferred when available.
FluxSpectrum
Bases: _Block
A spectrum known up to a grey scale: OI_FLUX or correlated fluxes.
The model of sample i (wavelength λᵢ, scale group gᵢ) is
mᵢ = Σ_j w_j tᵢ xᵢʲ, w ~ N((μ, 0, ...), diag(s, τ_1 μ, ...)²),
with t the model's template: the total spectrum Σ fᵢ(λ)
("flux"), the same divided by its continuum fit per row
("nflux"), or the total spectrum times |V| ("corrflux"),
normalized to a mean of 1 per scale group (except "nflux", which
is already normalized). x is λ scaled to [-1, 1] across the group, so
w_0 = k is the grey scale and w_j (j ≥ 1) an optional polynomial.
(μ, s) is the stated prior on k, in the data's units (the same for
every group; (1, 0.1) by default for "nflux"), and τ the
polynomial's widths relative to μ. The prior is a proposal for the
Jeffreys 1/k (see the module notes). The weights are marginalized
analytically.
Choice of prior. k is a scale parameter. Under rescaling of k the invariant (Jeffreys) prior is ∝ 1/k, uniform in log k, but that prior is improper, so an evidence computed with it is undefined. The broad Gaussian used here instead approximates a prior uniform in k. The only claim made is local: when k is sharply measured (σ_k/k ≪ 1, as for any useful OI_FLUX spectrum), the factor 1/k varies by only a fraction σ_k/k across the likelihood's width, so the posteriors of k and of the other parameters are insensitive to the choice. Evidence comparisons need a proper prior: finite positive bounds [k_min, k_max], with density 1 / (k ln(k_max/k_min)). With such bounds, that log-uniform prior is the Jeffreys choice under the rule for scale groups. Marginalizing in log k is not linear and is not done here (a follow-up).
Build with :meth:build; change the prior, groups and widths with
OIData.with_flux_scale.
wavel
instance-attribute
sample
instance-attribute
row
instance-attribute
frame
instance-attribute
station
instance-attribute
mjd
instance-attribute
group
instance-attribute
members
instance-attribute
count
instance-attribute
poly
instance-attribute
mu
instance-attribute
cont_rows
instance-attribute
cont_basis
instance-attribute
cont_fit
instance-attribute
kind = eqx.field(static=True)
class-attribute
instance-attribute
widths = eqx.field(static=True)
class-attribute
instance-attribute
scale = eqx.field(static=True)
class-attribute
instance-attribute
poly_width = eqx.field(static=True)
class-attribute
instance-attribute
per = eqx.field(static=True)
class-attribute
instance-attribute
continuum = eqx.field(static=True)
class-attribute
instance-attribute
continuum_order = eqx.field(static=True)
class-attribute
instance-attribute
model_dependent_covariance = True
class-attribute
instance-attribute
build(kind, values, errors, wavel, row, frame, station, sample=None, mjd=None, per='dataset', scale=None, poly_order=0, poly_width=0.1, continuum=None, continuum_order=0)
classmethod
Build from per-sample arrays (see the class notes).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
(flux, nflux, corrflux)
|
|
"flux"
|
values
|
array - like
|
The data and their uncertainties, one per sample. |
required |
errors
|
array - like
|
The data and their uncertainties, one per sample. |
required |
wavel
|
array - like
|
Each sample's wavelength (metres). |
required |
row
|
array - like
|
Each sample's row (one spectrum), frame (exposure) and station
(a telescope's |
required |
frame
|
array - like
|
Each sample's row (one spectrum), frame (exposure) and station
(a telescope's |
required |
station
|
array - like
|
Each sample's row (one spectrum), frame (exposure) and station
(a telescope's |
required |
sample
|
array-like of int
|
For |
None
|
mjd
|
array - like
|
Each sample's time (days), for splitting by epoch. |
None
|
per
|
(dataset, row, frame, station)
|
One grey scale for all the samples (default), or one per row, frame or station (telescope or baseline). |
"dataset"
|
scale
|
(float, float)
|
The prior |
None
|
poly_order
|
int
|
Also marginalize a polynomial in λ of this order times the template (default 0: a grey scale only). |
0
|
poly_width
|
float
|
Prior width of each polynomial coefficient, relative to the scale's prior mean. |
0.1
|
continuum
|
sequence of (lo, hi)
|
For |
None
|
continuum_order
|
int
|
For |
0
|
rebuild(values=None, errors=None, keep=None, **settings)
The same block with new settings, data, or only some samples.
subset(keep, new_index, flux_keep=None)
predict(model, cvis)
whiten(prediction, data, errors)
posterior(prediction, data, errors)
Conditional posterior of the weights w per group: mean and cov.
mean[g, 0] is the grey scale k of group g, multiplying the
template; mean[g, j] (j ≥ 1) the polynomial coefficients. The
Gaussian prior is a proposal for k's Jeffreys prior (see the
module notes).
simulated(prediction, cvis, noise, key=None)
VisibilityAmplitude
Bases: _Block
|V| at samples, e.g. VISAMP beside VIS2DATA ("visamp").
V² and |V| from the same measurement are not independent; reading both counts it twice unless the pipeline measured them separately.
sample
instance-attribute
kind = eqx.field(static=True, default='visamp')
class-attribute
instance-attribute
predict(model, cvis)
subset(keep, new_index, flux_keep=None)
TripleAmplitude
Bases: _Block
|V_ab V_bc V_ac| of closure triangles (T3AMP, "t3amp").
i1
instance-attribute
i2
instance-attribute
i3
instance-attribute
kind = eqx.field(static=True, default='t3amp')
class-attribute
instance-attribute
predict(model, cvis)
subset(keep, new_index, flux_keep=None)
DifferentialPhase
Bases: _Block
Continuum-normalized phases (VISPHI, "visphi").
values and errors are the per-sample phases (radians, in the
orientation of the visibility samples) and their uncertainties, as
read. Per frame, the phases of each baseline (a row of channels) are
unwrapped along wavelength and mapped by
Y = Qᵀ Φ Wᵀ,
where W holds the line-window rows of N = I − L (continuum_operator)
rotated onto independent combinations, and Q is an orthonormal basis of
the telescope-differenced phases (closure-free; with closure phases in
the data) or the identity. The data vector is Y of the data, the
covariance (Q ⊗ W) D (Q ⊗ W)ᵀ, whitened by its Cholesky factor per
frame. Build with :meth:build, or change the windows with
OIData.with_continuum.
With prior_width, the offset and slope of every baseline and frame
are instead marginalized under a finite Gaussian prior (the
projection is its flat limit): W keeps the channels of both windows
unchanged, each channel's closure-free combinations are whitened for
their covariance Qᵀ D Q, and the offsets and slopes are whitened out as
low-rank modes per frame, by the 6d gains' blocks
(virgil.gains). Their log-determinant does not depend
on the model.
Residuals are treated as linear (Gaussian), which holds while the differential phases are well below π, as they are after removing the continuum.
sample
instance-attribute
wavel
instance-attribute
frame
instance-attribute
stations
instance-attribute
row
instance-attribute
grid
instance-attribute
chan
instance-attribute
q
instance-attribute
w
instance-attribute
valid
instance-attribute
keep
instance-attribute
basis
instance-attribute
continuum = eqx.field(static=True)
class-attribute
instance-attribute
lines = eqx.field(static=True)
class-attribute
instance-attribute
order = eqx.field(static=True)
class-attribute
instance-attribute
closure_free = eqx.field(static=True)
class-attribute
instance-attribute
prior_width = eqx.field(static=True, default=None)
class-attribute
instance-attribute
kind = eqx.field(static=True, default='visphi')
class-attribute
instance-attribute
chol = None
class-attribute
instance-attribute
n_independent
property
build(values, errors, sample, wavel, frame, stations, row=None, continuum=None, lines=None, order=1, closure_free=True, prior_width=None)
classmethod
Build from per-sample phases (see the class notes).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
array - like
|
Phases (radians) and uncertainties, one per sample. |
required |
errors
|
array - like
|
Phases (radians) and uncertainties, one per sample. |
required |
sample
|
array-like of int
|
The visibility sample of each phase. |
required |
wavel
|
array - like
|
Each phase's wavelength (metres), frame, and station pair. |
required |
frame
|
array - like
|
Each phase's wavelength (metres), frame, and station pair. |
required |
stations
|
array - like
|
Each phase's wavelength (metres), frame, and station pair. |
required |
row
|
array-like of int
|
Which phases form one spectrum (one baseline of one frame); by default, those with the same frame and station pair. |
None
|
continuum
|
sequence of (lo, hi)
|
Wavelength ranges (metres). The continuum is fitted over the continuum channels and the line channels are kept. Either defaults to the complement of the other; with neither, every channel is both. |
None
|
lines
|
sequence of (lo, hi)
|
Wavelength ranges (metres). The continuum is fitted over the continuum channels and the line channels are kept. Either defaults to the complement of the other; with neither, every channel is both. |
None
|
order
|
int
|
1 (default): subtract a mean and a slope in wavenumber (an offset and a delay); 0: a mean. |
1
|
closure_free
|
bool
|
Keep only the telescope-differenced part of each frame's phases, orthogonal to the closure phases (default True; use it whenever the data have closure phases). |
True
|
prior_width
|
float or (float, float)
|
Marginalize the offset (and slope, per unit of the scaled
wavenumber, which spans 1 across the channels) of each
baseline and frame under Gaussian priors of these widths
(radians), over the channels of both windows, instead of
projecting them out ( |
None
|
rebuild(values=None, errors=None, keep=None, **settings)
The same block with new settings, data, or only some samples.
subset(keep, new_index, flux_keep=None)
data()
predict(model, cvis)
covariance(errors=None)
Per frame, the covariance of the outputs, (F, K R, K R).
Padded outputs get unit variance, so the matrices are invertible.
with_errors(errors)
data_errors()
whiten(prediction, data, errors)
simulated(prediction, cvis, noise, key=None)
continuum_operator(wavel, continuum, order=1)
The continuum fit of one spectrum, as a matrix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wavel
|
array - like
|
The channels' wavelengths (metres). |
required |
continuum
|
array-like of bool
|
Which channels are continuum. |
required |
order
|
int
|
0 fits a mean; 1 (the default) a mean and a slope in wavenumber 1/λ, which is an offset and a delay for a phase. |
1
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
in_ranges(wavel, ranges)
Whether each wavelength lies in one of ranges, [(lo, hi), ...].