OIFITS.jl
Support for OI-FITS (optical interferometry data format) in Julia.
Install / Use
/learn @emmt/OIFITS.jlREADME
Support for OI-FITS data in Julia
[![License][license-img]][license-url]
[![Build Status][github-ci-img]][github-ci-url]
[![Coverage][codecov-img]][codecov-url]
The OIFITS.jl package provides support for OI-FITS data in Julia language.
OI-FITS types
OI-FITS is a standard to store optical interferometry data as a collection of data-blocks. In the second revision of the standard (see Ref. 1 and Ref. 2), an OI-FITS file may contain the following data-blocks:
- an
OI_TARGETdata-block stores a list of observed targets; - each
OI_ARRAYdata-block describes a given array of telescope stations; - each
OI_WAVELENGTHdata-block describes a given instrument notably the effective wavelengths and bandwidths of its spectral channels; OI_CORRdata-blocks store correlation data;OI_VISdata-blocks store complex visibility data;OI_VIS2data-blocks store squared visibility (powerspectrum) data;OI_T3data-blocks store triple product (bispectrum) data;OI_FLUXdata-blocks store spectral flux data;OI_INSPOLdata-blocks store instrumental polarization data.
These data-blocks are stored as binary tables in a FITS data file. The support for FITS
files is provided by AstroFITS and
FITSHeaders.
The Julia type of an OI-FITS data-block corresponds to the OI-FITS extension (see above
list). In addition to these types for individual OI-FITS data-blocks, objects of exported
type OIDataSet contain several OI-FITS data-blocks and are efficient representation of the
content of a compliant OI-FITS file.
Other exported types are OIDataBlock, the super-type of all data-block types, and
OITargetEntry, the type of entries in OI_TARGET data-blocks.
Reading and writing OI-FITS files
Reading and writing OI-FITS data-sets
Reading an OI-FITS data file in Julia yields a data-set and is done by:
using OIFITS
ds = read(OIDataSet, input)
where input it the name of the OI-FITS file or an instance of AstroFITS.FitsFile which
represents an open FITS file. The above read call is equivalent to the shortcut:
ds = OIDataSet(input)
It is possible to merge the contents of several OI-FITS file, say inp1, inp2, etc., by
one of:
ds = read(OIDataSet, inp1, inp2, ...)
ds = OIDataSet(inp1, inp2, ...)
or to merge them into an existing data-set ds:
read!(ds, inp1, inp2, ...)
Creating an OI-FITS file is as simple as writing the data-set ds:
write(filename, ds)
Overwriting is forbidden by default, but the keyword overwrite=true may be specified to
allow for silently overwriting an existing file.
Reading and writing individual OI-FITS data-blocks
It may be useful to read individual OI-FITS data-blocks, to debug or to fix the contents of a non-compliant OI-FITS file. To that end, you must open the FITS file and can then read a given HDU as an OI-FITS data-block:
using AstroFITS, OIFITS
f = FitsFile(filename, "r") # open FITS file for reading
tgt = OI_TARGET(f[i]) # read OI_TARGET extension in i-th HDU
tgt = read(OI_TARGET, f[i]) # idem
db = OI_VIS2(f[j]) # read OI_VIS2 extension in j-th HDU
db = read(OI_VIS2, f[j]) # idem
...
any OI-FITS data-block type can be read in that way. If the type of the i-th extension is
not known, OIDataBlock can be used instead but the result is not type-stable:
db = OIDataBlock(f[i]) # read any OI-FITS extension in i-th HDU
db = read(OIDataBlock, f[i]) # idem
Writing individual OI-FITS data-blocks is also possible:
using AstroFITS, OIFITS
f = FitsFile(filename, "w") # open FITS file for writing
write(f, db) # write db in the next HDU of f
To fix a non-compliant OI-FITS file (usually duplicate target or instrument names), you can
read all the data-blocks, fix those which are wrong and push them in order in an
OIDataSet to have a consistent data-set which you can then directly use or write in an
OI-FITS file for later. Thanks to the automatic rewriting of target identifiers and of the
fact that targets (and other dependencies) are identified by their name and consistently
merged, it is possible to push an OI_TARGET with multiply defined identical targets (apart
maybe their identifiers).
Accessing the contents of data-blocks and data-sets
The contents of OI-FITS data-blocks and data-sets may be accessed by the dot notation but also by indexation.
Contents of data-sets
The dot notation can be used on a data-set object, say ds, storing a consistent set of
OI-FITS data-blocks. The following properties are available:
-
ds.targetis theOI_TARGETdata-block of the OI-FITS structure. -
ds.instris a list ofOI_WAVELENGTHdata-blocks indexed by a regular integer index or by the instrument name:ds.instr[i] # yields the i-th OI_WAVELENGTH data-block ds.instr[insname] # yields the OI_WAVELENGTH data-block whose name matches insnameMatching of names follows FITS conventions that case of letters and trailing spaces are ignored. An exception is thrown if the index (integer or name) is not valid. The
getmethod can be used to provide a default value, for example:get(ds.instr, insname, nothing)would yield
nothingifinsnameis not found inds.instrinstead of throwing an exception. -
ds.arrayis a list ofOI_ARRAYdata-blocks indexed likeds.instrexcept that interferometric array names are assumed. -
ds.correlis a list ofOI_CORRdata-blocks indexed likeds.instrexcept that correlation data array names are assumed. -
ds.visis a vector ofOI_VISdata-blocks. -
ds.vis2is a vector ofOI_VIS2data-blocks. -
ds.t3is a vector ofOI_T3data-blocks. -
ds.fluxis a vector ofOI_FLUXdata-blocks. -
ds.inspolis a vector ofOI_INSPOLdata-blocks.
Other fields of data-sets shall be considered as private and not accessed directly.
Using the dot notation, it is easy to access the different data-blocks containing measurements. For instance:
for db in ds.vis2
...
end
is convenient to loop over all OI_VIS2 instances stored by ds.
Content of data-blocks
The content of a data-block, say db, may also be accessed by the dot notation. As a
general rule, db.key or db.col yield the value of the keyword key or the content of
the column col of the OI-FITS table corresponding to the data-block db. In order to
follow Julia conventions and to accommodate for a number of restrictions, key or col are
the FITS keyword or column name converted to lower case letters and with non-alphanumeric
letters replaced by underscores. For instance db.date_obs yields the value of the keyword
DATE-OBS, that is the UTC start date of observations. The revision number corresponding to
the keyword OI_REVN is however accessed as db.revn, this is the only exception. Other
properties are also accessible via this syntax:
-
db.extnameyields the OI-FITS name of the extension corresponding to the data-blockdb(for all data-block types); -
db.arrayyields theOI_ARRAYdata-block associated with data-blockdb(only forOI_VIS,OI_VIS2,OI_T3,OI_FLUX, andOI_INSPOLdata-block). Beware that the association with anOI_ARRAYis optional, sodb.arraymay be actually undefined; this can be checked byisdefined(db,:array). -
db.instryields theOI_WAVELENGTHdata-block associated with data-blockdb(only forOI_VIS,OI_VIS2,OI_T3, andOI_FLUXdata-block). -
db.correlyields theOI_CORRdata-block associated with data-blockdb(only forOI_VIS,OI_VIS2,OI_T3, andOI_FLUXdata-block). -
db.nameis an alias fordb.arrnameforOI_ARRAYinstances, fordb.insnameforOI_WAVELENGTHinstances, and fordb.corrnameforOI_CORRinstances.
Of course, getting a given property must make sense. For example, db.sta_name is only
possible for an OI_ARRAY data-block but not for an OI_WAVELENGTH data-block. The dot
notation can be however be chained and:
db.instr.eff_wave
can be used to access the effective wavelengths of the measurements in db via the
instrument associated to db. Shortcuts are provided:
λ = db.eff_wave # get effective wavelength
Δλ = db.eff_band # get effective bandwidth
for OI_WAVELENGTH data-blocks but also for OI_VIS, OI_VIS2, OI_T3, and OI_FLUX
data-blocks.
Some fields of a data-block db may however be undefined because:
-
the field is not yet defined (the data-block is being constructed);
-
the field is optional in the revision
db.revnof the data-block; -
the field (for example
db.instrfor anOI_VISdata-block) involves links with other data-blocks (the dependencies) and these links are only defined when a data-block is part of a data-set (see Building of data-sets below).
OI_TARGET data-blocks
For efficiency, instances of OI_TARGET data-blocks do not follow the same rules as other
types of OI-FITS data-blocks whose properties are the columns of the corresponding OI-FITS
table: in an OI_TARGET instance, all parameters describing a target are represented by an
OITargetEntry structure and all targets are stored as a vector of OITargetEntry. An
OI_TARGET instance, say db, has the 3 following properties:
db.extname # yields "OI_TARGET"
db.list # yields a vector of OITargetEntry instances
db.revn # yields the revision number
The list of targets db.list can be indexed by an integer (as any Julia vector) or by the
target name (case of letters and trailing spaces are irrelevant).
As an OI_TARGET dat
Related Skills
openhue
348.2kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
348.2kElevenLabs text-to-speech with mac-style say UX.
weather
348.2kGet current weather and forecasts via wttr.in or Open-Meteo
tweakcc
1.6kCustomize Claude Code's system prompts, create custom toolsets, input pattern highlighters, themes/thinking verbs/spinners, customize input box & user message styling, support AGENTS.md, unlock private/unreleased features, and much more. Supports both native/npm installs on all platforms.
