SkillAgentSearch skills...

OIFITS.jl

Support for OI-FITS (optical interferometry data format) in Julia.

Install / Use

/learn @emmt/OIFITS.jl
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

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] Aqua QA

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_TARGET data-block stores a list of observed targets;
  • each OI_ARRAY data-block describes a given array of telescope stations;
  • each OI_WAVELENGTH data-block describes a given instrument notably the effective wavelengths and bandwidths of its spectral channels;
  • OI_CORR data-blocks store correlation data;
  • OI_VIS data-blocks store complex visibility data;
  • OI_VIS2 data-blocks store squared visibility (powerspectrum) data;
  • OI_T3 data-blocks store triple product (bispectrum) data;
  • OI_FLUX data-blocks store spectral flux data;
  • OI_INSPOL data-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.target is the OI_TARGET data-block of the OI-FITS structure.

  • ds.instr is a list of OI_WAVELENGTH data-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 insname
    

    Matching 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 get method can be used to provide a default value, for example:

    get(ds.instr, insname, nothing)
    

    would yield nothing if insname is not found in ds.instr instead of throwing an exception.

  • ds.array is a list of OI_ARRAY data-blocks indexed like ds.instr except that interferometric array names are assumed.

  • ds.correl is a list of OI_CORR data-blocks indexed like ds.instr except that correlation data array names are assumed.

  • ds.vis is a vector of OI_VIS data-blocks.

  • ds.vis2 is a vector of OI_VIS2 data-blocks.

  • ds.t3 is a vector of OI_T3 data-blocks.

  • ds.flux is a vector of OI_FLUX data-blocks.

  • ds.inspol is a vector of OI_INSPOL data-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.extname yields the OI-FITS name of the extension corresponding to the data-block db (for all data-block types);

  • db.array yields the OI_ARRAY data-block associated with data-block db (only for OI_VIS, OI_VIS2, OI_T3, OI_FLUX, and OI_INSPOL data-block). Beware that the association with an OI_ARRAY is optional, so db.array may be actually undefined; this can be checked by isdefined(db,:array).

  • db.instr yields the OI_WAVELENGTH data-block associated with data-block db (only for OI_VIS, OI_VIS2, OI_T3, and OI_FLUX data-block).

  • db.correl yields the OI_CORR data-block associated with data-block db (only for OI_VIS, OI_VIS2, OI_T3, and OI_FLUX data-block).

  • db.name is an alias for db.arrname for OI_ARRAY instances, for db.insname for OI_WAVELENGTH instances, and for db.corrname for OI_CORR instances.

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.revn of the data-block;

  • the field (for example db.instr for an OI_VIS data-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

View on GitHub
GitHub Stars8
CategoryCustomer
Updated2mo ago
Forks7

Languages

Julia

Security Score

70/100

Audited on Jan 28, 2026

No findings