Model Fitting
Parametric models
| Function | Description |
|---|---|
parse_model(dict, fit_params) | Compile a flat parameter dict into a FlatModel |
model_to_vis(model, x, uv) | Evaluate complex visibilities for a model (alias: eval_model) |
eval_model_grad(model, x, uv) | Evaluate visibilities + Jacobian |
display_model(dict, fit_params) | Pretty-print model parameters |
fit_model(dict, fit_params, data) | Fit model via gradient descent (NLopt) |
fit_model_lsqfit(dict, fit_params, data) | Fit model via Levenberg-Marquardt (LsqFit) |
fit_model_ultranest(dict, fit_params, data) | Fit model via nested sampling (UltraNest) |
model_to_obs(model, x, data) | Compute observables (V², T3amp, T3phi) from a model |
model_to_residuals(model, x, data) | Compute normalised residuals (model - data) / error |
model_to_chi2(model, x, data) | Compute weighted chi² (alias: chi2_flat) |
model_to_chi2_fg(model, x, data) | Compute chi² + gradient (alias: chi2_flat_fg) |
model_to_image(model, x; nx, pixsize) | Synthesize a model image via inverse FFT |
model_to_sed(model, x, wl_grid) | Compute spectral energy distribution |
resample_data(data) | Bootstrap resample data (add Gaussian noise from error bars) |
OITOOLS.FlatModel — Type
Top-level compiled model.
OITOOLS.parse_model — Function
parse_model(param_dict, fit_params; nB_workspace=100) -> FlatModelCompile a flat parameter dict into a FlatModel ready for evaluation.
Arguments
paramdict : Dict{String,Any} with "component,param" keys. Values may be Float64 (fixed or free) or String (expression). Special string key "component,profile" triggers the Hankel pathway. fitparams : Vector{String} of keys to optimize (must be numeric in paramdict). nBworkspace : Pre-allocated baseline grid size for HankelWorkspace buffers. Should be ≥ the number of baselines you will evaluate at.
Returns
A FlatModel whose evalmodel / evalmodel_grad methods can be called in a loop with zero Dict allocation.
Example
param = Dict(
"star,ud" => 0.8,
"star,f" => 0.6,
"ring,profile" => "exp(-(\$R / \$scale)^2 / 2)",
"ring,scale" => 1.5,
"ring,udout" => 12.0,
"ring,f" => "1 - \$star,f",
)
fit_params = ["star,ud", "star,f", "ring,scale"]
model = parse_model(param, fit_params)OITOOLS.model_to_vis — Function
model_to_vis(model, x, uv; wl=nothing, mjd=nothing, n=0)Alias for eval_model. Compute complex visibilities from a parametric model, for consistency with the model_to_obs / model_to_chi2 family.
OITOOLS.eval_model — Function
eval_model(model, x, uv; wl=nothing, mjd=nothing, n=0) -> Vector{ComplexF64}Evaluate the model visibility at the given parameter vector x and baselines uv.
Arguments
model : FlatModel from parsemodel x : current free-parameter values, length = length(model.fitparams) uv : 2×N matrix of (u,v) spatial frequencies in cycles/rad wl : wavelength per UV point (metres), length N — enables WL in expressions mjd : MJD per UV point, length N — enables MJD in expressions n : Bessel order for Hankel components (default 0)
Returns
V : complex visibility vector, length N
OITOOLS.eval_model_grad — Function
eval_model_grad(model, x, uv; wl=nothing, mjd=nothing, n=0) -> (V, J)Evaluate model visibility and its Jacobian w.r.t. x.
Returns
V : complex visibility vector (length nB) J : Jacobian, Matrix{ComplexF64} of shape (nB, length(x))
Uses ForwardDiff for the resolver and analytic components; for Hankel components uses the cached-K chain rule via hankelvisfwd! + pullback. This is more efficient than naive ForwardDiff through the full Hankel loop when nB is large, since Bessel evaluations are shared across parameters.
OITOOLS.display_model — Function
display_model(param_dict, fit_params; lb, ub)Print a human-readable summary of the model setup, grouped by component. Shows each parameter's value (or expression), whether it is free or fixed, and its bounds. Warns about common mistakes (value out of bounds, missing bounds, flux fractions that don't sum to 1).
Call this before fit_model / fit_model_ultranest to verify your setup.
OITOOLS.fit_model — Function
fit_model(param_dict, fit_params, data; kwargs...) -> FitResultFit a parametric model to interferometric data using NLopt.
Arguments
param_dict::Dict{String}— flat parameter dictionary (values are numbers or expression strings)fit_params::Vector{String}— names of the free parameters to optimizedata::OIdata— interferometric data
Keywords
lb,ub—Dict{String,Float64}of lower/upper bounds per parameter (default: ±Inf)weights— observable weights [V2, T3amp, T3phi, visamp, visphi, flux, diffphase]priors— Vector of(expr_str, target, sigma)tuples for Gaussian penaltiesmethod— NLopt algorithm (default:LD_LBFGS; use:LN_NELDERMEADfor gradient-free)maxeval— maximum function evaluations (default 2000)ftol_rel,xtol_rel— convergence tolerancesvonmises— use von Mises statistic for T3phinB_workspace— Hankel workspace size (default: nuv from data)verb— print per-evaluation chi2 breakdown
OITOOLS.fit_model_lsqfit — Function
fit_model_lsqfit(param_dict, fit_params, data; kwargs...) -> LsqFitResultFit a parametric model to interferometric data using Levenberg-Marquardt (LsqFit.jl). Returns parameter covariance and 1σ uncertainties.
Uses the analytic Jacobian from residuals_flat_jac (Wirtinger chain rule through the complex visibility Jacobian), so no finite-difference overhead.
Arguments
param_dict::Dict{String}— flat parameter dictionaryfit_params::Vector{String}— names of the free parameters to optimizedata::OIdata— interferometric data
Keywords
lb,ub—Dict{String,Float64}of lower/upper bounds per parameterweights— observable weights [V2, T3amp, T3phi, visamp, visphi, flux, diffphase]vonmises— use von Mises statistic for T3phinB_workspace— Hankel workspace sizemaxIter— maximum iterations (default 200)verb— print per-evaluation chi2 breakdown
OITOOLS.fit_model_ultranest — Function
fit_model_ultranest(param_dict, fit_params, data; kwargs...) -> UltraNestResultFit a parametric model to interferometric data using UltraNest nested sampling.
Requires PyCall and the Python ultranest package.
Arguments
param_dict::Dict{String}— flat parameter dictionaryfit_params::Vector{String}— names of the free parametersdata::OIdata— interferometric data
Keywords
lb,ub—Dict{String,Float64}of lower/upper bounds (REQUIRED for all fit_params)weights— observable weights [V2, T3amp, T3phi, visamp, visphi, flux, diffphase]vonmises— use von Mises statistic for T3phinB_workspace— Hankel workspace sizemin_num_live_points— minimum number of live points (default 400)cluster_num_live_points— live points for clustering (default 100)num_bootstraps— number of bootstraps for evidence (default 30)use_stepsampler— use RegionSliceSampler (default false)nsteps— steps per slice for stepsampler (default 400)frac_remain— termination fraction (default 0.001)log_interval— logging interval (default 100)verb— print progress (default true)cornerplot— show corner plot (default true)
OITOOLS.model_to_obs — Function
model_to_obs(model, x, data) -> (v2, t3amp, t3phi, visamp, visphi)Evaluate a FlatModel at parameter vector x and return the model observables matching the data structure.
Returns a NamedTuple with fields v2, t3amp, t3phi (degrees), visamp, visphi (degrees). Empty vectors are returned for observable types not present in data.
OITOOLS.model_to_residuals — Function
model_to_residuals(model, x, data)Compute normalised residuals (model - data) / error for each observable type. Returns a NamedTuple with fields v2, t3amp, t3phi, visamp, visphi. Phase residuals (t3phi, visphi) are wrapped to [-180, 180] before dividing by error.
OITOOLS.model_to_chi2 — Function
model_to_chi2(model, x, data; weights=[1,1,1,0,0,0,0], verb=false, vonmises=false)Alias for chi2_flat. Compute the weighted chi-squared of a parametric model against data, for consistency with the model_to_obs / model_to_vis family.
OITOOLS.model_to_chi2_fg — Function
model_to_chi2_fg(model, x, data; weights=[1,1,1,0,0,0,0], verb=false, vonmises=false)Alias for chi2_flat_fg. Compute chi-squared and its gradient w.r.t. x, for consistency with the model_to_obs / model_to_vis family.
OITOOLS.model_to_image — Function
model_to_image(model, x; nx=256, pixsize=0.1, oversample=1, normalize=true, wl=nothing)
-> Matrix{Float64}Synthesise an image from a FlatModel at parameter vector x.
The image is computed by evaluating the model visibility on the 2-D FFT frequency grid and applying an inverse real FFT (irfft), which exploits the Hermitian symmetry V(-u,-v) = conj(V(u,v)) to halve the number of visibility evaluations.
Arguments
model::FlatModel— compiled model fromparse_modelx::AbstractVector— current free-parameter values
Keywords
nx— image size in pixels (default 256)pixsize— pixel size in mas (default 0.1)oversample— oversampling factor (default 1)normalize— normalize image to unit sum (default true)wl— wavelength in microns (scalar); enables$WLin spectrum expressions
Returns
img — nx × nx Matrix{Float64}
OITOOLS.model_to_sed — Function
model_to_sed(model, x, wl_grid) -> (total, components)Evaluate the spectral energy distribution of a FlatModel by computing V(u=0, v=0) at each wavelength — the zero-baseline visibility equals the total flux.
Per-component fluxes are obtained by resolving the f / spectrum parameters at each wavelength.
Arguments
model::FlatModel— compiled model fromparse_modelx::AbstractVector— current free-parameter valueswl_grid— wavelength array in microns
Returns
total::Vector{Float64}— total flux at each wavelength (= V(0,0))components::Dict{String,Vector{Float64}}— per-component flux
OITOOLS.resample_data — Function
resample_data(data::OIdata)Create a bootstrapped copy of the data by adding Gaussian noise (drawn from the error bars) to the observables. Useful for bootstrap uncertainty estimation.
| Type | Description |
|---|---|
FitResult | Result from fit_model (fields: x_opt, chi2r, model, ...) |
LsqFitResult | Result from fit_model_lsqfit (adds stderror, covar, converged) |
UltraNestResult | Result from fit_model_ultranest (adds logz, logzerr, posterior) |
Visibility functions
Analytic visibility functions for standard source geometries. All take baseline spatial frequency arguments and return complex visibilities.
| Function | Model |
|---|---|
visibility_ud(b, diam) | Uniform disk |
visibility_ldlin(b, diam, u) | Linear limb-darkened disk |
visibility_ldquad(b, diam, u, w) | Quadratic limb-darkened disk |
visibility_ldquad_alt(b, diam, u, w) | Quadratic LD disk (alternative convention) |
visibility_ldpow(b, diam, alpha) | Power-law limb-darkened disk |
visibility_ldsquareroot(b, diam, u, w) | Square-root limb-darkened disk |
visibility_annulus(b, din, dout) | Uniform annulus |
visibility_ellipse_uniform(u, v, a, b, pa) | Uniform ellipse |
visibility_ellipse_quad(u, v, a, b, pa, c1, c2) | Quadratic LD ellipse |
visibility_thin_ring(b, diam) | Infinitely thin ring |
visibility_Gaussian_ring(b, diam, fwhm) | Gaussian ring |
visibility_Gaussian_ring_az(...) | Gaussian ring with azimuthal modulation |
visibility_Lorentzian_ring(b, diam, fwhm) | Lorentzian ring |
visibility_GaussianLorentzian_ring_az(...) | Gaussian-Lorentzian ring with azimuthal modulation |