Source code for sofia_redux.instruments.exes.get_resolution
# Licensed under a 3-clause BSD style license - see LICENSE.rst
import os
from astropy import log
from astropy.io import fits
import pandas
from sofia_redux.instruments import exes
from sofia_redux.toolkit.utilities import goodfile, hdinsert
__all__ = ['get_resolution']
[docs]
def get_resolution(header):
"""
Retrieve expected spectral resolving power.
Requires spectral resolution files in exes/data/resolution for
overriding cross-dispersed resolutions:
- short_wave_resolution.txt
- medium_wave_resolution.txt
- long_wave_resolution.txt
These files must have 2 columns: slit width (arcsec) and
spectral resolving power (lambda / dlambda). The file chosen is
based on the central wavelength for the observation.
The procedure is:
1. Read resolution data from the configuration file matching
the central wavelength of the observation (WAVECENT).
2. Use SLITWID to find the closest resolution value.
3. If no appropriate data is found, or the mode is not cross-dispersed,
the value of the RP (if present) or RESOLUN keyword is returned.
Otherwise, the best matching resolving power is returned.
Parameters
----------
header : fits.Header
Returns
-------
float
Expected resolving power.
"""
if not isinstance(header, fits.Header):
msg = 'Invalid header.'
log.error(msg)
raise ValueError(msg)
required_keywords = ['WAVECENT', 'SLITWID', 'RESOLUN', 'INSTCFG']
for key in required_keywords:
if key not in header:
msg = f'Header missing {key} keyword.'
log.error(msg)
raise ValueError(msg)
instcfg = header['INSTCFG']
slitwid = header['SLITWID']
resolun = header['RESOLUN']
wavecent = header['WAVECENT']
# check for valid RP value: if present and reasonable,
# use instead of resolun
rp = header.get('RP', -9999)
if rp > 500:
resolun = rp
if 'HIGH' not in str(instcfg).strip().upper():
log.debug(f'Mode {instcfg}: returning header value.')
return resolun
if wavecent < 10.5:
rfile = 'short_wave_resolution.txt'
elif wavecent < 15.5:
rfile = 'medium_wave_resolution.txt'
else:
rfile = 'long_wave_resolution.txt'
resfile = os.path.join(os.path.dirname(exes.__file__), 'data',
'resolution', rfile)
hdinsert(header, 'RESFILE', resfile)
log.debug(f'Using resolution file: {resfile}')
if not goodfile(resfile, verbose=True):
msg = f'Cannot read resolution file: {resfile}'
log.error(msg)
raise ValueError(msg)
# Find appropriate resolution
log.debug(f"Loading resolution file: {resfile}")
names = ['slitwid', 'res']
df = pandas.read_csv(resfile, comment='#', names=names,
sep=r'\s+')
if df.empty:
log.debug('No resolution data; returning header value.')
return resolun
resolution = float(df.loc[
(df.slitwid - slitwid).abs().idxmin()]['res'])
log.debug(f'Found resolution: {resolution}')
return resolution