Simulating observations

OITOOLS can generate synthetic OIFITS datasets from a parametric model or image, either by copying the UV coverage of an existing file or by building observations from scratch using array geometry and observation times.

From an existing OIFITS file

The simplest approach reuses the UV coverage and noise properties of a real dataset:

using OITOOLS
simulate_from_oifits("data/2004-data1.oifits", "data/sim.oifits";
                     image="data/2004true.fits", pixsize=0.101)

A flat-dict parametric model can be used instead of an image:

params = Dict("star,ud" => 3.0, "star,f" => 1.0)
model = dict_to_model(params, String[])

simulate_from_oifits("data/2004-data1.oifits", "data/sim.oifits";
                     flat_model=model, flat_params=Float64[])

See example_simulate_observations_from_OIFITS.jl.

From observation times and array geometry

To simulate a full night of observations at a specific interferometer, you need four configuration objects: facility, target, combiner, and wavelength setup. These are read from TOML files shipped with OITOOLS in src/configs/.

Configuration files

The .toml extension is optional — OITOOLS resolves built-in config names automatically.

Facility — array layout, telescope positions, atmospheric conditions:

facility = read_facility_file("CHARA_new")
Config nameInterferometerTelescopes
CHARACHARA array6×1 m
CHARA_newCHARA array (updated)6×1 m
VLTI_UTVLTI Unit Telescopes4×8.2 m
VLTI_AT_smallVLTI ATs — small config4×1.8 m
VLTI_AT_mediumVLTI ATs — medium config4×1.8 m
VLTI_AT_largeVLTI ATs — large config4×1.8 m

Target — celestial coordinates and proper motion:

target = read_obs_file("default_obs")

You can also query SIMBAD directly:

ra, dec = ra_dec_from_simbad("Vega")
target = TargetConfig(target="Vega", raep0=ra, decep0=dec)

Combiner — beam combiner properties (throughput, read noise, calibration errors):

combiner = read_comb_file("MIRCX")
Config nameInstrumentArrayBand
GRAVITYGRAVITYVLTIK
MATISSE_LMMATISSEVLTIL+M
MATISSE_NMATISSEVLTIN
MIRCXMIRC-XCHARAH
MYSTICMYSTICCHARAK
MIRCMIRC (legacy)CHARAH
SPICASPICACHARAV

Wavelength — spectral setup for a given combiner mode:

wave = read_wave_file("MIRCX_LOWH")
Config nameCombinerModeBand
GRAVITY_LOWKGRAVITYLow spectral resolutionK
MATISSE_LOWLMATISSE_LMLow spectral resolutionL
MATISSE_LOWNMATISSE_NLow spectral resolutionN
MIRCX_LOWHMIRCXLow spectral resolutionH
MIRCX_LOWJMIRCXLow spectral resolutionJ
MYSTIC_LOWKMYSTICLow spectral resolutionK
MIRC_LOWHMIRCH-band prismH
SPICA_LRSPICALow resolutionV

Simulating from an image

using Dates

# Observation times: every 15 minutes over a 5.5-hour window
dates = collect(DateTime(2024,8,13,3,0,0):Minute(15):DateTime(2024,8,13,8,30,0))

facility = read_facility_file("CHARA_new")
target   = read_obs_file("default_obs")
combiner = read_comb_file("MIRCX")
wave     = read_wave_file("MIRCX")

simulate(facility, target, combiner, wave, dates, "sim_image.oifits";
         image="data/2004true.fits", pixsize=0.101)

Simulating from a parametric model

params = Dict(
    "star,ud"    => 3.0,
    "star,f"     => 0.7,
    "disk,f"     => "1 - \$star,f",
    "disk,diamout" => 10.0,
    "disk,profile" => "exp(-(\$R/3.0)^2)",
)
model = dict_to_model(params, String[])

simulate(facility, target, combiner, wave, dates, "sim_model.oifits";
         flat_model=model, flat_params=Float64[])

See example_simulate_observations_from_model.jl and example_simulate_observations_from_image.jl.

Polychromatic simulation

example_simulate_polychromatic_disk.jl demonstrates simulating a chromatic, time-variable disk with an off-axis companion. The companion introduces wavelength-dependent differential phases, producing non-zero OIVIS signals. The example writes OIVIS2, OIVIS (with differential phases), OIT3, and OI_FLUX tables.

Observation planning

OITOOLS provides tools for checking delay-line feasibility and producing Gantt charts for a given target and night:

gantt_onenight(facility, target, date)

Additional planning utilities:

# Sunrise/sunset times
rise, set = sunrise_sunset(facility, date)

# Hour angle and altitude for observability
ha = jd_to_hour_angle(jd, target.raep0, facility.lon)
altitude, azimuth = alt_az(ha, target.decep0, facility.lat)

# Delay-line limits
opd_min, opd_max = opd_limits(facility, target, ha)

See example_chara_plan.jl.