Skip to content

virgil.plotting

Plotting functions for virgil models, data and grid results.

  • plot_grid_map draws any grid result (log likelihood, best-fit flux, uncertainty, S/N, contrast limit) with defaults chosen by kind=, and plot_contrast_curve draws radial contrast curves.
  • plot_null_distribution, plot_roc and plot_completeness draw the simulated searches of a DetectionMC: false-alarm probabilities, ROC curves and completeness maps.
  • Contrasts can be shown as flux ratios (companion/primary), as contrasts (primary/companion, e.g. 100) or in magnitudes (e.g. 5 mag), with units="flux" | "contrast" | "delta_mag".

Sky images follow the package convention: East (positive dra) to the left and North (positive ddec) up. Importing this module does not change matplotlib's global settings; call set_style to opt in to the virgil look for every figure.

set_style()

Apply the virgil matplotlib style globally.

The plotting functions in this module already use this style for the figures they create, without touching global settings. Call this to use it for your own figures too.

plot_grid_map(values, grid, kind='loglike', *, units='flux', sigma=None, percentile=None, truth=None, best=None, star=True, flux_param=None, ax=None, cmap=None, log=None, label=None, title=None, figsize=(7, 6))

Plot a grid result as a sky map (or a 1D profile).

Parameters:

Name Type Description Default
values array - like

Grid result with one axis per coordinate key of grid (every key except the flux), in key order, as returned by virgil.grid_fit and virgil.limits. A full likelihood_grid (with the flux axis) is reduced to its maximum over flux. One coordinate gives a line plot.

required
grid dict[str, array - like]

The grid axes used to compute values.

required
kind (loglike, flux, sigma, snr, limit)

What values holds, which sets the default colour map, scale and labels: a log likelihood, a best-fit flux, a flux uncertainty, a signal-to-noise ratio, or a flux upper limit.

"loglike"
units (flux, contrast, delta_mag)

For kind="flux" and "limit", show the values as flux ratios (companion/primary, default), contrasts (primary/companion, e.g. 100), or magnitude differences (e.g. 5 mag).

"flux"
sigma float

Confidence of a kind="limit" map, for its title (e.g. sigma=5 gives "5σ limit").

None
percentile float

Confidence of a kind="limit" map, for its title (e.g. sigma=5 gives "5σ limit").

None
truth dict or sequence

Coordinates to mark with a cross (truth) or circle (best fit). A dict is looked up by key; a sequence is read in coordinate-key order.

None
best dict or sequence

Coordinates to mark with a cross (truth) or circle (best fit). A dict is looked up by key; a sequence is read in coordinate-key order.

None
star bool

Mark the primary at the origin of sky maps (default True).

True
flux_param str

Key of the flux axis, if it is not the one key ending in flux.

None
ax Axes

Axes to draw on; a new figure is made if omitted.

None
cmap optional

Override the defaults for kind: colour map, logarithmic colour scale, colour-bar label and title.

None
log optional

Override the defaults for kind: colour map, logarithmic colour scale, colour-bar label and title.

None
label optional

Override the defaults for kind: colour map, logarithmic colour scale, colour-bar label and title.

None
title optional

Override the defaults for kind: colour map, logarithmic colour scale, colour-bar label and title.

None
figsize tuple

Size of a new figure.

(7, 6)

Returns:

Type Description
tuple

(fig, ax).

Notes

When the coordinates include dra and ddec (also as paths such as "comp.dra") they are drawn as x and y, East-left and North-up, whatever their order in grid; pixels are centred on the samples.

Examples:

>>> fig, (a, b) = plt.subplots(1, 2)
>>> plot_grid_map(flux, grid, kind="flux", ax=a)
>>> plot_grid_map(flux / sigma, grid, kind="snr", ax=b)
>>> plot_grid_map(limits, grid, kind="limit", units="delta_mag", sigma=5)

plot_contrast_curve(values, grid=None, *, units='delta_mag', sigma=None, percentile=None, label=None, band=True, truth=None, center=(0.0, 0.0), r_max=None, bins=20, ax=None, color=None, figsize=(8, 4))

Plot a radial contrast curve: the median limit against separation.

Parameters:

Name Type Description Default
values array - like or dict

A limit map (companion/primary flux ratios, with one axis per coordinate key of grid in key order, as from absil_limits or ruffio_upperlimit), or a radial_profile of one.

required
grid dict[str, array - like]

The grid axes of a limit map; it must contain dra and ddec axes (also as paths such as "comp.dra").

None
units (delta_mag, contrast, flux)

Show limits as magnitude differences (default), contrasts (primary/companion) or flux ratios (companion/primary). Deeper limits are always drawn lower down.

"delta_mag"
sigma optional

Legend label; by default built from sigma or percentile (e.g. "5σ limit"), or "Median limit".

None
percentile optional

Legend label; by default built from sigma or percentile (e.g. "5σ limit"), or "Median limit".

None
label optional

Legend label; by default built from sigma or percentile (e.g. "5σ limit"), or "Median limit".

None
band bool

Shade the 16–84 percentile range of each annulus (default True).

True
truth tuple

(dra, ddec, flux) of a detected companion to mark.

None
center optional

Annuli, passed to radial_profile.

(0.0, 0.0)
r_max optional

Annuli, passed to radial_profile.

(0.0, 0.0)
bins optional

Annuli, passed to radial_profile.

(0.0, 0.0)
ax Axes

Axes to draw on, e.g. to overlay several curves.

None
color optional

Line and band colour.

None
figsize tuple

Size of a new figure.

(8, 4)

Returns:

Type Description
tuple

(fig, ax).

plot_null_distribution(mc, stat='delta_chi2', *, observed=None, fap=None, reference=True, ax=None, title=None, figsize=(7, 4.5))

Plot how often companion-free searches exceed each threshold.

The curve is the empirical exceedance (survival) function of the statistic over the null simulations: at each threshold, the fraction of companion-free searches at or above it, that is the threshold's false-alarm probability. It is drawn on a log scale, so the tail that sets detection thresholds is visible.

Parameters:

Name Type Description Default
mc DetectionMC

Simulated searches, from injection_recovery.

required
stat str

"delta_chi2" (default), "log_bayes_factor" or "max_snr".

'delta_chi2'
observed float

The statistic of the real data. It is drawn as a vertical line, with its empirical false-alarm probability (DetectionMC.false_alarm_probability) and the 95% interval of that probability as a point with error bars.

None
fap float

A false-alarm probability to draw as a horizontal line, with the empirical threshold that reaches it (DetectionMC.threshold) as a vertical line.

None
reference bool

Draw what the statistic would do at one position fixed in advance (default True): ½ P(χ²₁ ≥ x) for delta_chi2 (Wilks's theorem with the flux on its boundary at zero), the Gaussian tail for max_snr. The gap between this curve and the empirical one is the look-elsewhere effect. log_bayes_factor has no reference.

True
ax Axes

Axes to draw on; a new figure is made if omitted.

None
title str

Title; by default it names the statistic and the number of draws.

None
figsize tuple

Size of a new figure. The legend is drawn outside the axes; a tight bounding box (as Jupyter uses) includes it.

(7, 4.5)

Returns:

Type Description
tuple

(fig, ax).

Notes

The legend sits outside the axes, to their right, so that it never covers the tail of the distribution. When drawing on axes in a grid of subplots, leave room for it or move it with ax.legend(...).

Examples:

>>> plot_null_distribution(mc, "delta_chi2", observed=21.3,
...                        fap=1.35e-3)

plot_roc(mc, stat, *, flux=None, sep_bin=None, ax=None, log_fpr=True, mark_wilks=(3.0, 5.0), title=None, figsize=(7, 4.5))

Plot ROC curves: completeness against false-alarm probability.

Each curve follows a detection threshold from high to low: its false-positive rate (the fraction of companion-free simulations above the threshold, i.e. its false-alarm probability) on the x-axis and its true-positive rate (the fraction of injected companions recovered, the completeness) on the y-axis. A statistic that cannot tell companions from noise lies on the chance curve TPR = FPR; a better one lies above it.

Parameters:

Name Type Description Default
mc DetectionMC

Simulated searches, from injection_recovery.

required
stat str or sequence of str

"delta_chi2", "log_bayes_factor" or "max_snr", or several of them to compare.

required
flux (float, (float, float) or list)

Only the injections of this flux, or in this range (lo, hi), as for DetectionMC.roc. A list gives one curve per entry. By default, every injection.

None
sep_bin (float, float) or list of them

Only the injections with separations in [lo, hi) (mas); a list gives one curve per bin.

None
ax Axes

Axes to draw on; a new figure is made if omitted.

None
log_fpr bool

Logarithmic false-positive axis (default), from half a null draw's worth (0.5 / n_null) to 1, since detections are claimed at small false-alarm probabilities. On it the chance curve TPR = FPR is a curve, not a straight line.

True
mark_wilks sequence of float

Local significances (default 3σ and 5σ) to mark. A vertical line shows the false-alarm probability that Wilks's theorem gives them at one position fixed in advance, the one-sided Gaussian tail (0.135% at 3σ, 2.9×10⁻⁷ at 5σ), when it lies on the axis. A circle on every delta_chi2 or max_snr curve shows where the threshold equals that local significance (delta_chi2 = 9 or max_snr = 3 at 3σ): its horizontal distance from the line is the look-elsewhere effect of searching a grid. None or () marks nothing.

(3.0, 5.0)
title str

Title; by default it names what all the curves share (one statistic, one flux or separation selection), and the legend names what differs.

None
figsize tuple

Size of a new figure. The legend is drawn outside the axes; a tight bounding box (as Jupyter uses) includes it.

(7, 4.5)

Returns:

Type Description
tuple

(fig, ax).

Notes

With several statistics, the line style tells the statistics apart and the colour the flux or separation selections; with one statistic, both change from curve to curve. The legend sits outside the axes, to their right, as in plot_null_distribution.

Examples:

Three statistics at one injected flux, then one statistic at several:

>>> plot_roc(mc, ["delta_chi2", "log_bayes_factor", "max_snr"],
...          flux=4e-3)
>>> plot_roc(mc, "delta_chi2", flux=[2e-3, 4e-3, 8e-3])

plot_completeness(mc, stat, fap, *, units='delta_mag', contours=(0.5, 0.9), sep_bins=None, flux_bins=None, ax=None, cmap='viridis', colorbar=True, title=None, figsize=(8, 4.5))

Plot a completeness map against separation and companion brightness.

Each cell is the fraction of injected companions of that separation and flux that a search detects at the false-alarm probability fap (DetectionMC.completeness). Lines mark where the completeness reaches each level in contours, the empirical contrast curves of DetectionMC.contrast_curve.

Parameters:

Name Type Description Default
mc DetectionMC

Simulated searches with injections, from injection_recovery.

required
stat str

The detection statistic, e.g. "delta_chi2".

required
fap float

False-alarm probability of the detection threshold, e.g. 1.35e-3 (the one-sided Gaussian tail at 3σ).

required
units (delta_mag, contrast, flux)

The y-axis, as in plot_contrast_curve: magnitude difference (default, linear), contrast (primary/companion, log) or flux ratio (companion/primary, log). Fainter companions are always drawn lower down, so limit curves from plot_contrast_curve can be drawn on the same axes.

"delta_mag"
contours sequence of float

Completeness levels to draw as lines (default 50% and 90%); () draws none.

(0.5, 0.9)
sep_bins array - like

Bin edges (mas, and flux), as for DetectionMC.completeness. By default every distinct injected separation and flux is a cell.

None
flux_bins array - like

Bin edges (mas, and flux), as for DetectionMC.completeness. By default every distinct injected separation and flux is a cell.

None
ax Axes

Axes to draw on; a new figure is made if omitted.

None
cmap str or Colormap

Colour map of the completeness, from 0 to 1.

'viridis'
colorbar bool

Add a colour bar (default True).

True
title str

Title; by default it gives the statistic and the FAP.

None
figsize tuple

Size of a new figure.

(8, 4.5)

Returns:

Type Description
tuple

(fig, ax).

Notes

Cells span halfway to their neighbours, in separation and in log flux. Injections of zero flux have no Δmag or contrast and are left out. The contour lines are contrast_curve's: in each separation bin the completeness is made non-decreasing in flux and interpolated linearly in log flux (linearly in Δmag), so they are exactly the curves that method returns, and they are absent where the injected fluxes do not bracket the level. The map sets the axis limits to its cells, so curves drawn afterwards do not widen them.

Examples:

A completeness map with Absil limits of companion-free data overplotted (plot_contrast_curve redraws the legend, so place it again at the end):

>>> fig, ax = plot_completeness(mc, "delta_chi2", 1.35e-3)
>>> plot_contrast_curve(absil_map, grid, sigma=3, band=False,
...                     ax=ax)
>>> ax.legend(loc="lower left", fontsize="small")

plot_orbit_ensemble(orbits, positions=None, truth=None, *, n_points=400, n_sigma=1.0, color='#3c6e9f', alpha=None, truth_color='#d1495b', cmap='viridis', ax=None, figsize=(6.5, 6))

Draw orbits on the sky, e.g. draws from a posterior, with the data.

East is to the left and North up, and the primary sits at the origin. Each orbit is drawn over one full period as a thin line; the measured positions are coloured by time, with their error ellipses.

Parameters:

Name Type Description Default
orbits KeplerOrbit

One orbit, or many as a single KeplerOrbit whose elements are 1-D arrays of equal length (e.g. built from posterior samples).

required
positions PositionData

Measured positions to overlay, with n_sigma error ellipses.

None
truth KeplerOrbit

A reference orbit (e.g. the truth of a simulation), drawn as a thicker contrasting line.

None
n_points int

Points along each orbit.

400
n_sigma float

Size of the error ellipses, in standard deviations.

1.0
color optional

Colours of the ensemble and of the reference orbit.

'#3c6e9f'
truth_color optional

Colours of the ensemble and of the reference orbit.

'#3c6e9f'
alpha float

Opacity of each ensemble line; by default it falls with the number of orbits, so that the density of lines reads as probability.

None
cmap str

Colour map for the epochs' times.

'viridis'
ax Axes

Axes to draw on.

None
figsize tuple

Size of a new figure.

(6.5, 6)

Returns:

Type Description
tuple

(fig, ax).

plot_model(model, fov_mas, npix=256, ax=None, title=None, saturate=None, cmap='magma', beam=None, convolve=False)

Show a source model's rendered image with sky axes.

East is to the left and North is up, matching the orientation of render.

Parameters:

Name Type Description Default
model SourceModel

Model to render.

required
fov_mas float

Width of the field of view in milliarcseconds.

required
npix int

Number of pixels on a side.

256
ax Axes

Axes to draw on; a new figure is made if omitted.

None
title str

Axes title.

None
saturate float

Quantile (e.g. 0.99) at which to saturate the colour scale, so that faint structure next to a bright star is visible.

None
cmap str

Matplotlib colour map.

'magma'
beam Beam

The data's resolution, from imaging.beam, drawn as a shaded FWHM ellipse in the lower-left corner, as is usual on reconstructed images.

None
convolve bool

If True, show the image convolved with beam (see imaging.convolve_beam): what the data resolve, rather than the super-resolved image.

False

Returns:

Type Description
Axes

The axes drawn on.

plot_residual_map(residual, fov_mas, sigma=None, ax=None, title=None, cmap='RdBu_r')

Show a signed residual image on a symmetric, diverging colour scale.

Use it next to an image and its reconstruction (or data and a model) to see where they agree. Without sigma the map is the plain signed residual, as for a maximum a posteriori image with no uncertainty. With sigma it is the z-score residual / sigma. The colour scale is centred on zero in either case, with East to the left and North up.

Parameters:

Name Type Description Default
residual (array - like, shape(npix, npix))

E.g. reconstruction.render(npix, fov) - truth.render(npix, fov), in the orientation of render.

required
fov_mas float

Width of the field of view in milliarcseconds.

required
sigma array - like or float

Uncertainty of the residual, per pixel or overall; if given, the map shows z-scores.

None
ax Axes

Axes to draw on; a new figure is made if omitted.

None
title str

Axes title.

None
cmap str

A diverging Matplotlib colour map.

'RdBu_r'

Returns:

Type Description
Axes

The axes drawn on (with a colour bar).

plot_uv_coverage(data, ax=None, cmap='viridis', figsize=(6, 5.5))

Plot the uv coverage of data, coloured by wavelength.

Each sample is drawn at (u, v) and at its mirror (-u, -v) (the visibility there is the conjugate), in units of millions of wavelengths, with East (positive u) to the left as on the sky.

Parameters:

Name Type Description Default
data OIData

Data to show. Flagged samples are drawn too: the coverage is that of the observation.

required
ax Axes

Axes to draw on; a new figure is made if omitted.

None
cmap str

Colour map of the wavelength, used when the data have more than one wavelength (one colour otherwise).

'viridis'
figsize tuple

Size of a new figure.

(6, 5.5)

Returns:

Type Description
tuple

(fig, ax).

plot_oidata_overview(oidata, figsize=(15, 4.5))

Plot uv coverage, visibilities and phases of an OIData object.

Parameters:

Name Type Description Default
oidata OIData

Data to show. Flagged samples are left out. Projected observables (vis_mat/phi_mat) have no baseline and are not shown against it.

required
figsize tuple

Figure size.

(15, 4.5)

Returns:

Type Description
tuple

(fig, (ax_uv, ax_vis, ax_phi)).

plot_data_model_correlation(oidata, predictions_by_label, colors=None, figsize=(10, 5), phase_title='Phase correlation', square_axes=True, vis_label=None)

Plot data-vs-model correlation panels for visibility and phase observables.

Parameters:

Name Type Description Default
oidata OIData

Observed data container.

required
predictions_by_label dict

Mapping label -> prediction summary where each summary contains vis_mean, vis_std, phi_mean, phi_std arrays.

required
colors list

Matplotlib color list. If omitted, cycle C0, C1, ...

None
figsize tuple

Figure size.

(10, 5)
phase_title str

Title for the phase panel.

'Phase correlation'
square_axes bool

If True, enforce square panel boxes for both subplots.

True
vis_label str

Axis label for the visibility observable. By default it follows oidata.vis_mode: V² and amplitudes are shown in percent, log-amplitudes and projected (e.g. DISCO) observables as plain values.

None

Returns:

Type Description
tuple

(fig, (ax1, ax2)) for visibility and phase axes. Data with no phase observables (e.g. AMIGO DISCOs, which hold every observable in vis) leave the phase axis hidden and give the visibility panel the whole figure.

plot_chainconsumer_diagnostics(chains_by_label, columns, truth=None, colors=None, walk_columns=None)

Plot comparison diagnostics using ChainConsumer for multiple posterior chains.

Parameters:

Name Type Description Default
chains_by_label dict

Mapping label -> pandas.DataFrame containing chain samples.

required
columns list[str]

Columns used for contour/corner plotting.

required
truth dict

Truth mapping for columns displayed. When omitted, no truth overlay is drawn.

None
colors list[str]

Per-chain colors.

None
walk_columns list[str]

Columns to show in walk plots. Defaults to columns.

None

Returns:

Type Description
tuple

(consumer, corner_fig, walks_fig): the configured ChainConsumer instance and the two figures it drew.

plot_hmc_fisher_chainconsumer(hmc_table, fisher_table, truth_cartesian, colors=('#1f77b4', '#ff7f0e'))

Plot paired Cartesian and polar ChainConsumer diagnostics for HMC and Fisher-HMC.

Parameters:

Name Type Description Default
hmc_table DataFrame

Posterior table for vanilla HMC.

required
fisher_table DataFrame

Posterior table for Fisher-reparameterized HMC.

required
truth_cartesian dict

Truth mapping in Cartesian coordinates.

required
colors tuple[str, str]

Colors used for HMC and Fisher-HMC chains.

('#1f77b4', '#ff7f0e')

Returns:

Type Description
dict

Mapping with the ChainConsumer objects ("cartesian", "polar"), their figures ("cartesian_figures", "polar_figures", each (corner, walks)) and the truth mappings.

diagnostics_table_from_samples(samples, dra_key='dra', ddec_key='ddec', flux_key='flux', log10_flux=False)

Build a standardized diagnostics table from posterior sample arrays.

Parameters:

Name Type Description Default
samples dict - like

Mapping of sample arrays.

required
dra_key str

Key for right-ascension offsets.

'dra'
ddec_key str

Key for declination offsets.

'ddec'
flux_key str

Key for flux or log10-flux samples.

'flux'
log10_flux bool

If True, exponentiate flux_key values as base-10.

False

Returns:

Type Description
DataFrame

Table with dra, ddec, flux, sep, and pa columns.

truth_cartesian_and_polar(truth)

Return truth mappings for shared ChainConsumer Cartesian and polar interfaces.

Parameters:

Name Type Description Default
truth dict

Mapping with dra, ddec, and flux values.

required

Returns:

Type Description
tuple[dict, dict]

Cartesian and polar truth dictionaries.