Source code for sofia_redux.scan.custom.sofia.info.extended_scanning
# Licensed under a 3-clause BSD style license - see LICENSE.rst
import numpy as np
from astropy import units
from sofia_redux.scan.custom.sofia.info.scanning import SofiaScanningInfo
from sofia_redux.scan.utilities.bracketed_values import BracketedValues
from sofia_redux.scan.utilities.utils import (
to_header_float, UNKNOWN_INT_VALUE, UNKNOWN_STRING_VALUE)
from sofia_redux.scan.coordinate_systems.coordinate_2d import Coordinate2D
from sofia_redux.scan.utilities.utils import insert_info_in_header
degree = units.Unit('degree')
arcsec = units.Unit('arcsec')
second = units.Unit('second')
__all__ = ['SofiaExtendedScanningInfo']
[docs]
class SofiaExtendedScanningInfo(SofiaScanningInfo):
def __init__(self):
"""
Initialize the SOFIA extended scanning information.
Contains information on additional scanning information that may be
required to describe SOFIA specific observations.
"""
super().__init__()
self.pattern = ''
self.coordinate_system = ''
self.amplitude = None # Coordinate2D (arcsec)
self.current_position_angle = np.nan * degree
self.duration = np.nan * second
self.rel_frequency = np.nan
self.rel_phase = np.nan * degree
self.t0 = np.nan * second
self.gyro_time_window = np.nan * second
self.iterations = UNKNOWN_INT_VALUE
self.subscans = UNKNOWN_INT_VALUE
self.raster_length = np.nan * arcsec
self.raster_step = np.nan * arcsec
self.is_cross_scanning = False
self.n_steps = UNKNOWN_INT_VALUE
self.tracking_enabled = UNKNOWN_INT_VALUE
self.position_angle = BracketedValues(np.nan, np.nan, unit='degree')
@property
def log_id(self):
"""
Return the string log ID for the info.
The log ID is used to extract certain information from table data.
Returns
-------
str
"""
return 'scan'
[docs]
def apply_configuration(self):
"""
Update scanning information with FITS header information.
Updates the scanning information by taking the following keywords from
the FITS header::
SCNPATT - The scanning pattern (str)
SCNCRSYS - The scanning coordinate system (str)
SCNAMPXL - The scanning x-elevation scanning amplitude (arcsec)
SCNAMPEL - The scanning elevation scanning amplitude (arcsec)
SCNANGLC - The current scanning angle (degree)
SCNANGLS - The initial scanning angle (degree)
SCNANGLF - The final scanning angle (degree)
SCNDUR - The scan duration (seconds)
SCNITERS - The number of scanning iterations (int)
SCNNSUBS - The number of sub-scans (int)
SCNLEN - The raster scan length (arcsec)
SCNSTEP - The raster scan step size (arcsec)
SCNSTEPS - The number of raster scan steps (int)
SCNCROSS - Whether the scan is cross-scanning (bool)
SCNFQRAT - The Lissajous y/x frequency ratio (float)
SCNPHASE - The Lissajous y/x relative phase (degree)
SCNTOFF - The Lissajous time offset (seconds)
SCNTWAIT - The track relock time window (seconds)
SCNTRKON - Whether tracking is on/off (0/1) (int)
Returns
-------
None
"""
super().apply_configuration()
options = self.options
if options is None:
return
self.pattern = options.get_string(
'SCNPATT', default=UNKNOWN_STRING_VALUE)
self.coordinate_system = options.get_string(
'SCNCRSYS', default=UNKNOWN_STRING_VALUE)
self.amplitude = Coordinate2D([options.get_float('SCNAMPXL'),
options.get_float('SCNAMPEL')],
unit='arcsec')
self.current_position_angle = options.get_float('SCNANGLC') * degree
self.position_angle = BracketedValues(options.get_float('SCNANGLS'),
options.get_float('SCNANGLF'),
unit='degree')
self.duration = options.get_float('SCNDUR') * second
self.iterations = options.get_int('SCNITERS',
default=UNKNOWN_INT_VALUE)
self.subscans = options.get_int('SCNNSUBS', default=UNKNOWN_INT_VALUE)
self.raster_length = options.get_float('SCNLEN') * arcsec
self.raster_step = options.get_float('SCNSTEP') * arcsec
self.n_steps = options.get_int('SCNSTEPS', default=UNKNOWN_INT_VALUE)
self.is_cross_scanning = options.get_bool('SCNCROSS')
self.rel_frequency = options.get_float('SCNFQRAT')
self.rel_phase = options.get_float('SCNPHASE') * degree
self.t0 = options.get_float('SCNTOFF') * second
self.gyro_time_window = options.get_float('SCNTWAIT') * second
self.tracking_enabled = options.get_int('SCNTRKON',
default=UNKNOWN_INT_VALUE)
[docs]
def get_table_entry(self, name):
"""
Return a parameter value for the given name.
Parameters
----------
name : str
The name of the parameter to retrieve.
Returns
-------
value
"""
if name == 'pattern':
return self.pattern
elif name == 'sys':
return self.coordinate_system
elif name == 'PA':
return self.current_position_angle.to('degree')
elif name == 'T':
return self.duration.to('second')
elif name == 'iters':
return self.iterations
elif name == 'nsub':
return self.subscans
elif name == 'trk':
if self.tracking_enabled == UNKNOWN_INT_VALUE:
return '?'
return self.tracking_enabled != 0
elif name == 'X':
return self.raster_length.to('arcsec')
elif name == 'dY':
return self.raster_step.to('arcsec')
elif name == 'strips':
return self.n_steps
elif name == 'cross?':
return self.is_cross_scanning
elif name == 'Ax':
return self.amplitude.x.to('arcsec')
elif name == 'Ay':
return self.amplitude.y.to('arcsec')
elif name == 'frel':
return self.rel_frequency
elif name == 'phi0':
return self.rel_phase.to('degree')
elif name == 't0':
return self.t0.to('second')
else:
return super().get_table_entry(name)