virgil.metrics
Image-recovery scores for comparing a reconstruction with a known truth, following the interferometric imaging contests: resampling, alignment, the normalized cross-correlation, the L1 score, the beam-convolved rms and the 2004 σ/peak.
Scores for comparing a reconstructed image with a known truth.
The image-recovery figures of merit used by the interferometric imaging contests, written from their published definitions:
- the 2004 Beauty Contest, Lawson et al. (2004, Proc. SPIE 5491, 886),
Eq. 2: the flux-weighted rms of the normalized difference, over the
peak (
lawson_sigma_over_peak); - the 2008-2012 contests (Cotton et al. 2008, Proc. SPIE 7013; Malbet et
al. 2010, Proc. SPIE 7734; Baron et al. 2012, Proc. SPIE 8445): the rms
difference after convolving both images with a Gaussian beam
(
rms_convolved); - the 2024 contest's
ImageMetricsL1 score (l1_score); - the normalized cross-correlation (
ncc).
score resamples, aligns and evaluates all of them.
Images are in the virgil orientation (row 0 North, column 0 East, centre at
the middle of the pixel grid, as in
Image); each function takes an
Image or an array with its pixel_scale_mas.
Comparing two images pixel by pixel needs them on the same grid and, because
interferometric data do not fix the absolute position, usually aligned
first.
resample(image, pixel_scale_mas, npix, new_pixel_scale_mas)
Resample an image onto a new grid, conserving flux.
The pixel fluxes are integrated exactly over the new pixels, treating
each old pixel as uniform, by linearly interpolating the cumulative flux
at the new pixel edges with
jax.scipy.ndimage.map_coordinates and differencing.
That is flux-conserving, and area-averages rather than aliases when the
new pixels are coarser. Both grids are centred on the same sky position
(the middle of the array, as in
pixel_offsets); flux outside the old
field is zero, and old flux outside the new field is dropped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
(Image or array - like, shape(ny, nx))
|
The image, with row 0 North and column 0 East. |
required |
pixel_scale_mas
|
float or None
|
Pixel size of |
required |
npix
|
int or (int, int)
|
Number of pixels of the new grid, |
required |
new_pixel_scale_mas
|
float
|
Pixel size of the new grid in milliarcseconds. |
required |
Returns:
| Type | Description |
|---|---|
(Array, shape(ny_new, nx_new))
|
The resampled pixel fluxes. |
ncc(image, truth)
Normalized cross-correlation of two images at zero shift.
The zero-mean form, Σ (e - ē)(r - r̄) / sqrt(Σ (e - ē)² Σ (r - r̄)²)
for the image e and truth r: 1 for identical images up to a
positive scale and offset, and independent of the flux scale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
(array - like, shape(ny, nx))
|
Images on the same grid. |
required |
truth
|
(array - like, shape(ny, nx))
|
Images on the same grid. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
The correlation coefficient, in [-1, 1]. |
l1_score(image, truth)
The L1 score of the 2024 imaging contest's ImageMetrics.
1 - min_{a >= 0} Σ|a e - r| / Σ r for the image e and truth
r: 1 for a perfect reconstruction up to flux scale, 0 for an image
no better than none. Since Σ|a e - r| = Σ e |a - r/e|, the optimal
scale a is the median of r/e with weights e, found by
sorting. Pixels of the image must be non-negative; negative values are
set to zero. The score does not depend on the flux scale of either image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
(array - like, shape(ny, nx))
|
Images on the same grid. |
required |
truth
|
(array - like, shape(ny, nx))
|
Images on the same grid. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
The score, in [0, 1]. |
rms_convolved(image, truth, pixel_scale_mas=None, beam=None, relative=False)
The rms difference of two images, after convolving with a beam.
The metric of the 2008-2012 contests: both images are normalized to unit flux, convolved with a Gaussian beam (the data's resolution, so that structure the data cannot resolve does not count against the reconstruction), and the rms of their difference is taken. With no beam the images are compared as they are.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
(Image or array - like, shape(ny, nx))
|
Images on the same grid. |
required |
truth
|
(Image or array - like, shape(ny, nx))
|
Images on the same grid. |
required |
pixel_scale_mas
|
float
|
Pixel size in milliarcseconds; needed only with a |
None
|
beam
|
Beam
|
The beam, usually |
None
|
relative
|
bool
|
Divide by the peak of the convolved truth, so the result is a fraction of the peak rather than of the total flux per pixel. |
False
|
Returns:
| Type | Description |
|---|---|
Array
|
The rms difference. |
lawson_sigma_over_peak(image, truth)
The 2004 Beauty Contest figure of merit, σ over the peak.
Lawson et al. (2004), Eq. 2: with both images normalized to unit flux,
σ is the root of the mean squared difference weighted by the true flux,
σ² = Σ r (e - r)² / Σ r, and the score is σ divided by the peak of
the truth. Smaller is better; 0 is a perfect reconstruction.
Both images are normalized to unit sum over the whole array, and only then is the rms weighted by the truth. The weighting means pixels where the truth is zero are not scored directly, but flux the reconstruction puts in empty sky changes its flux on the source (the sum is fixed), so it still affects σ indirectly. It can raise or lower σ: taking flux off a source pixel that was too bright lowers it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
(array - like, shape(ny, nx))
|
Images on the same grid. |
required |
truth
|
(array - like, shape(ny, nx))
|
Images on the same grid. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
σ / peak. |
align(image, truth, max_shift_mas, pixel_scale_mas=None)
Shift an image to best match the truth, by maximizing the NCC.
Interferometric data do not fix the absolute position, so a
reconstruction can sit anywhere in the field. The shift is found by an
exhaustive integer-pixel search of up to max_shift_mas along each
axis, refined to a fraction of a pixel by a parabola through the NCC
along each axis around the best integer shift. The shift itself is done
by bilinear interpolation, with zeros brought in at the edge.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
(Image or array - like, shape(ny, nx))
|
The image to shift. |
required |
truth
|
(Image or array - like, shape(ny, nx))
|
The reference, on the same grid. |
required |
max_shift_mas
|
float
|
Largest shift to search, in mas, along each axis. |
required |
pixel_scale_mas
|
float
|
Pixel size in milliarcseconds, if not given by an
|
None
|
Returns:
| Name | Type | Description |
|---|---|---|
shifted |
(Array, shape(ny, nx))
|
The shifted image. |
shift_mas |
tuple of float
|
The shift applied, |
score(image, truth, *, pixel_scale_mas=None, truth_pixel_scale_mas=None, beam=None, v2_only=False, max_shift_mas=None)
Every image-recovery metric of a reconstruction against a truth.
The image is resampled onto the truth's grid if the grids differ
(resample), aligned to the truth
(align) and normalized to unit flux, then
scored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
Image or array - like
|
The reconstruction and the true image, each an
|
required |
truth
|
Image or array - like
|
The reconstruction and the true image, each an
|
required |
pixel_scale_mas
|
float
|
Pixel sizes in mas, for arrays. The truth's defaults to the image's. |
None
|
truth_pixel_scale_mas
|
float
|
Pixel sizes in mas, for arrays. The truth's defaults to the image's. |
None
|
beam
|
Beam
|
If given, also report the rms difference after convolving with it. |
None
|
v2_only
|
bool
|
For data without phase information (squared visibilities only) an image and its 180° rotation fit equally well. With this set the rotated image is scored as well and the better of the two, by NCC, is kept. |
False
|
max_shift_mas
|
float
|
Search range of the alignment, in mas. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
|