virgil.oifits
Read and write OIFITS files with astropy.io.fits alone. This is the
maintained OIFITS path; OIData uses read_oifits whenever it
is given a file path or an opened HDUList (including pyoifits objects).
The reader supports:
- several wavelength channels (every baseline × channel becomes one sample);
- several
OI_VIS2/OI_VIS/OI_T3tables and epochs, matched byARRNAME,INSNAME(or anotherINSNAMEof the same array with identical wavelengths), station indices andMJD; FLAGcolumns and non-finite values, which are left out of the observables;- several targets, chosen with
target=; - absolute phases from
OI_VISVISPHIwhen there is noOI_T3.
Closure-phase triangles (a, b, c) find their baselines (a, b), (b, c)
and (a, c) in the visibility table with the same ARRNAME and INSNAME, or
else in one of the same array with identical wavelengths (the standard does
not require T3 and V² tables to share an INSNAME; station numbers belong to
an array, so another ARRNAME is never used). A baseline stored reversed is used as the conjugate. A
baseline stored in neither orientation (some MIRC-X and ESO phase-3 files omit
a baseline's V²) is placed at the OI_T3 row's own (u, v) as a flagged
sample, with one warning per file giving the number of such legs.
Functions
Read and write OIFITS files using only astropy.io.fits.
This is the maintained OIFITS path of virgil.
read_oifitsturns an OIFITS file into the record thatvirgil.oidata.OIDatais built from. It accepts a file path or any astropyHDUList, includingpyoifitsobjects (which subclass it). It handles several wavelength channels, several OIFITS tables, several epochs, andFLAGcolumns.write_oifitswrites a dictionary of OIFITS tables (the layout used by the legacyvirgil.legacy.oifits_implaneiawriter) to an OIFITS2 file.
Each (baseline, wavelength) sample becomes one element of the flat u,
v and wavel arrays of the record. Samples are ordered by table, then
row, then wavelength channel. Closure phases index into these samples, so a
multi-wavelength closure phase is formed from visibilities at its own
wavelength.
read_oifits(source, target=None, insname=None, frame_mjd='mean', extras=())
Read an OIFITS file into a record for OIData.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str, os.PathLike, astropy.io.fits.HDUList, or a list of them
|
File path, or an opened file (e.g. from |
required |
target
|
str or int
|
Target to keep, by |
None
|
insname
|
str or sequence of str
|
Keep only the tables ( |
None
|
frame_mjd
|
(mean, row)
|
The time given to each sample. |
"mean"
|
extras
|
sequence of str
|
Further observables to read beside the visibilities and phases
(none by default, so existing analyses are unchanged); see
|
()
|
Returns:
| Type | Description |
|---|---|
dict
|
Record with flat per-sample arrays |
Notes
Squared visibilities (OI_VIS2) are preferred over amplitudes
(OI_VIS), and closure phases (OI_T3) over absolute phases
(OI_VIS VISPHI). VISAMP is read only when its table's
AMPTYP is 'absolute', and VISPHI only when its
PHITYP is 'absolute'; a missing keyword counts as
'absolute', as in OIFITS1. Differential amplitudes and phases,
and correlated fluxes, raise a ValueError. Nothing in the
standard marks OI_VIS2 VIS2DATA that holds squared correlated
flux rather than squared visibility, as in MATISSE products reduced
with corrFlux=TRUE; such data are read as visibilities, so
calibrate them (e.g. with virgil-vlti) before fitting. A file with
only OI_T3 gives closure phases alone: its baselines come from the
triangle coordinates, and vis is empty. A file with neither
OI_T3 nor VISPHI gives visibilities alone: phi is empty, and
files with and without phases cannot be read together. Samples are
flagged when their FLAG is set or their value or uncertainty is
not finite.
Each closure-phase triangle (a, b, c) is matched to the visibility
baselines (a, b), (b, c) and (a, c) with the same INSNAME
(or, failing that, any INSNAME with identical wavelengths) and nearest
MJD and TIME, within its own file. The MJDs (and TIMEs) must agree to within
twice the longest INT_TIME in the visibility table (or about 9
seconds if there is none), since pipelines such as GRAVITY's average different
frames of one exposure for each table. A leg with no such visibility row,
or stored only reversed as (b, a), gets an extra flagged sample at
its own (u, v) from the OI_T3 row (U1COORD...V2COORD),
as the standard makes OI_T3 self-contained; for a reversed leg the
model's visibility there is the conjugate of the stored one. A file
with legs that have no visibility row in either orientation (V²
coverage incomplete, as in some MIRC-X and ESO phase-3 files) gives one
warning with their number.
A frame is one exposure of one instrument: the baselines that closure
phases tie together, together with any rows of the same INSNAME at
the same MJD and TIME (each within about 9 seconds). Both are
compared because some OIFITS v1 writers (e.g. OYSTER) give a night one
MJD and put each snapshot in TIME; closure phases are correlated
only within a snapshot. Frames are numbered within the record, so
different files never share one.
All files in a list must hold the same kinds of observable (squared visibilities or amplitudes; closure or absolute phases; the same extras).
With extras, a VISPHI or VISAMP row is matched to the
visibility sample of its baseline and time as closure-phase legs are
(a reversed baseline negates the phase). VISPHI is then never read
as an absolute phase: without OI_T3 the phase block is empty. A
file whose OI_VIS holds correlated fluxes and no OI_VIS2 gives
flagged visibility samples, with the amplitudes in "visamp".
write_oifits(tables, filename, overwrite=True)
Write a dictionary of OIFITS tables to an OIFITS2 file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tables
|
dict
|
Mapping of table name to a dict of columns, in the layout used by
|
required |
filename
|
str or PathLike
|
Output path. Missing parent directories are created. |
required |
overwrite
|
bool
|
Replace an existing file (default True). |
True
|
Returns:
| Type | Description |
|---|---|
Path
|
The path written. |
Notes
Unlike the legacy writer, this does not query SIMBAD: target coordinates
are taken from tables["OI_TARGET"] or info (RA/DEC in
degrees) and are zero otherwise.
build_hdulist(tables)
Build the OIFITS2 HDUList that :func:write_oifits writes.
Useful for adding non-standard columns or keywords before writing.