A module for reading/writing OIFITS (v1, v2) files
Project description
Python OIFITS module
This is a Python module for reading and writing OIFITS files. The only file you
need is oifits.py; everything else is supplementary.
Note, OIFITS2 support is currently in development, although already mostly working for both reading and writing OIFITS2 files. Please open an issue or contact me if you find any bugs.
The module was tested with Astropy 4.2 and numpy 1.19.2 under Python 3.8.5. Earlier versions will probably work, too.
For some example functions which make use of the module, see oitools.py in the
contrib directory. These are undocumented, messy examples only and may not work;
you should probably write your own.
Also included in the contrib directory is a sample array file for the VLTI.
This can be viewed using the plot_array function in oitools.py:
import matplotlib.pylab as plt
import oifits
from oitools import plot_array
oidata = oifits.open('VLTI-array.fits')
plot_array(oidata.array['VLTI'])
plt.show()
If you discover bugs, have issues with the code or suggestions, please feel free to open an issue on Github or contact me via email at pboley@gmail.com.
Installation
The module is available on PyPI and can be installed using pip:
pip install oifits
You can also just save oifits.py to the working directory of your project or
your
PYTHONPATH.
Usage
To open an existing OIFITS file, use the oifits.open(filename) function, where
filename can be either a filename or HDUList object. This will return an
oifits object with the following members (any of which can be empty
dictionaries or numpy arrays):
-
array: a dictionary of interferometric arrays, as defined by the OI_ARRAY tables. The dictionary key is the name of the array (ARRNAME). -
corr: a dictionary of correlation matrices, as defined by the OI_CORR table. The dictionary key is the name of the table (CORRNAME). -
header: the header from the primary HDU of the file. -
target: a numpy array of targets, as defined by the rows of the OI_TARGET table. -
wavelength: a dictionary of wavelength tables (OI_WAVELENGTH). The dictionary key is the name of the instrument/settings (INSNAME). -
vis,vis2,t3andflux: numpy arrays of objects containing all the measurement information. Each list member corresponds to a row in an OI_VIS/OI_VIS2/OI_T3/OI_FLUX table. -
inspol: a numpy array of objects containing the instrumental polarization information, as defined by the rows of the OI_INSPOL table.
A summary of the information in the oifits object can be obtained by using the info() method:
import oifits
oifitsobj = oifits.open('foo.fits')
oifitsobj.info()
The info() method can also be used from many of the objects contained within
the oifits object itself, e.g. oifitsobj.array['VLTI'].info() or
oifitsobj.vis[0].info().
Accessing the measurement data
The individual measurements can be referred to by accessing elements of the
vis, vis2, t3 and/or flux numpy arrays. These are themselves objects,
which contain the measurement data, as well as references to the corresponding
wavelength tables, intererometry stations, etc.
For example, if your OIFITS file contains OI_VIS measurements, the visibility
amplitude can be found in oifitsobj.vis[0].visamp, while the wavelengths
corresponding to the measurement can be found in
oifitsobj.vis[0].visamp.wavelength.eff_wave.
The OI_VIS/OI_VIS2/OI_T3/OI_FLUX classes use numpy masked arrays for
convenience, where the mask is defined via the flag member of these classes.
Beware of the following subtlety: the array data are accessed via (for
example) OI_VIS.visamp; however, OI_VIS.visamp itself is just a method which
constructs (on the fly) a masked array from OI_VIS._visamp, which is where the
data are actually stored. This is done transparently, and the data can be
accessed and modified transparently via the "visamp" hidden attribute. The same
goes for correlated fluxes, differential/closure phases, triple products, total
flux measurements, etc. See the notes on the individual classes for a list of
all the "hidden" attributes.
Combining OIFITS objects
The module provides a simple mechanism for combining multiple oifits objects,
achieved by using the + operator on two oifits objects: result = a + b.
This requires, however, that the information contained within all the support
tables (OI_ARRAY, OI_WAVELENGTH, OI_TARGET, etc.) is either identical,
or at least not mutually exclusive.
This behavior can be somewhat relaxed by setting the matchtargetbyname and/or
matchstationbyname in the top level of the module to True, in which cases
targets or interferometric stations with identical names will be considered as
identical (the values actually used in result = a + b are taken from a).
No mechanism is provided for the case where OI_WAVELENGTH tables have
identical names (INSNAME), but differing contents, as this requires
reinterpolating your data and is beyond the scope of this module.
Creating an OIFITS object from scratch
An example of creating an OIFITS file from scratch, which simulates using the
VLTI and MIDI (now decomissioned) for observations at random hour angles of the
calibrator star HD 148478, described as a uniform disk, can be found in
sample.py in the contrib directory.
Once you have assembled your OIFITS object, you can check if it is consistent
or valid by using the isconsistent() and isvalid() methods of the newly
created object, respectively. Consistency checks whether the new object is
entirely self-contained, and does not refer to any (sub)objects (e.g. wavelength
stations, array tables, telescopes or interferometric stations) which are not
contained in the object itself. Validity checks whether the information
contained within the oifits object actually conforms to the OIFITS standard. A
file can be consistent without being valid. An example of this is the
VLTI-array.fits file provided here, which does not conform to the OIFITS
standard in that it does not contain any measurements. However, because the
OI_ARRAY definition is somewhat complicated and the arrays themselves don't
really change much, it can be useful to save this information separately and
reuse it as needed.
If your OIFITS object is at least consistent, it can be written to a FITS file
using the save() method.
How to deal with non-conforming (broken) files
OIFITS files produced by the current version of the GRAVITY pipeline are known
to be broken: the OI_ARRAY tables are listed as conforming to OIFITS2
(OI_REVN=2), although they are missing the FOV and FOVTYPE columns.
Additionally, the OI_FLUX tables contain the flux measurements in the FLUX
column, instead of FLUXDATA. To fix the first problem, you can edit
the header of your file on-the-fly before trying to load it:
from astropy.io import fits
import oifits
hdulist = fits.open('foo.fits')
hdulist['OI_ARRAY'].header['OI_REVN'] = 1
oifitsobj = oifits.open(hdulist)
The problem with the FLUX/FLUXDATA error is a little more tricky, so the module handles it gracefully and warns you. Other errors in conforming to the OIFITS standards (e.g. DATE-OBS containing a date and time, instead of just a date; both MATISSE and GRAVITY make this mistake) are handled gracefully when possible, however if you see warnings I would encourage you to open a bug report with the software generating broken files.
Documentation
The API documentation is contained within the module itself in the form of
Python docstrings, which can be accessed using Python's help() function.
Besides this, you should also refer to the appropriate tables in the documents
defining the standard (see references), as the names of many
function arguments, tables, etc. are taken directly from there and not
documented explicitly.
Acknowledgements
Initial OIFITS2 capabilities were implemented with the financial support of grant 18-72-10132 of the Russian Science Foundation. That being said, the author is no longer affiliated with Russian institutions and condemns the Russian invasion of Ukraine.
References
-
A Data Exchange Standard for Optical (Visible/IR) Interferometry; Pauls et al., 2005
-
OIFITS 2: the 2nd version of the data exchange standard for optical interferometry; Duvet et al., 2017
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file oifits-0.6.1.tar.gz.
File metadata
- Download URL: oifits-0.6.1.tar.gz
- Upload date:
- Size: 36.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.32.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
813dbc184e38f8a3755e7ee4086b84cfc2669adf1df95a9cace9960d620c3cff
|
|
| MD5 |
07357dd3cbcf6080be79ff77bbbb83ac
|
|
| BLAKE2b-256 |
5158d71624b3633087d02cfc9582435c2a7ad421623ddfef3668a946f3964942
|
File details
Details for the file oifits-0.6.1-py3-none-any.whl.
File metadata
- Download URL: oifits-0.6.1-py3-none-any.whl
- Upload date:
- Size: 23.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.32.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c13615e8c8851cbc1c66f5d6cf1b0093269b2e23c7ede3576a8000f038df2b4
|
|
| MD5 |
d05b5ebbd3d0677a817e64d062bd287f
|
|
| BLAKE2b-256 |
90c46ab5c7073872a11637986d22a2ccfbb50c7e678cd747b547f5d89c7e05e3
|