def _verify_global_info(global_info): """ Given the global time reference frame information, verify that each global time coordinate attribute will be given a valid value. Parameters ---------- global_info : dict Global time reference frame information. """ # Translate FITS deprecated scale into astropy scale, or else just convert # to lower case for further checks. global_info['scale'] = FITS_DEPRECATED_SCALES.get( global_info['TIMESYS'], global_info['TIMESYS'].lower()) # Verify global time scale if global_info['scale'] not in Time.SCALES: # 'GPS' and 'LOCAL' are FITS recognized time scale values # but are not supported by astropy. if global_info['scale'] == 'gps': warnings.warn( 'Global time scale (TIMESYS) has a FITS recognized time scale ' 'value "GPS". In Astropy, "GPS" is a time from epoch format ' 'which runs synchronously with TAI; GPS is approximately 19 s ' 'ahead of TAI. Hence, this format will be used.', AstropyUserWarning) # Assume that the values are in GPS format global_info['scale'] = 'tai' global_info['format'] = 'gps' if global_info['scale'] == 'local': warnings.warn( 'Global time scale (TIMESYS) has a FITS recognized time scale ' 'value "LOCAL". However, the standard states that "LOCAL" should be ' 'tied to one of the existing scales because it is intrinsically ' 'unreliable and/or ill-defined. Astropy will thus use the default ' 'global time scale "UTC" instead of "LOCAL".', AstropyUserWarning) # Default scale 'UTC' global_info['scale'] = 'utc' global_info['format'] = None else: raise AssertionError( 'Global time scale (TIMESYS) should have a FITS recognized ' 'time scale value (got {!r}). The FITS standard states that ' 'the use of local time scales should be restricted to alternate ' 'coordinates.'.format(global_info['TIMESYS'])) else: # Scale is already set global_info['format'] = None # Check if geocentric global location is specified obs_geo = [ global_info[attr] for attr in ('OBSGEO-X', 'OBSGEO-Y', 'OBSGEO-Z') if attr in global_info ] # Location full specification is (X, Y, Z) if len(obs_geo) == 3: global_info['location'] = EarthLocation.from_geocentric(*obs_geo, unit=u.m) else: # Check if geodetic global location is specified (since geocentric failed) # First warn the user if geocentric location is partially specified if obs_geo: warnings.warn( 'The geocentric observatory location {} is not completely ' 'specified (X, Y, Z) and will be ignored.'.format(obs_geo), AstropyUserWarning) # Check geodetic location obs_geo = [ global_info[attr] for attr in ('OBSGEO-L', 'OBSGEO-B', 'OBSGEO-H') if attr in global_info ] if len(obs_geo) == 3: global_info['location'] = EarthLocation.from_geodetic(*obs_geo) else: # Since both geocentric and geodetic locations are not specified, # location will be None. # Warn the user if geodetic location is partially specified if obs_geo: warnings.warn( 'The geodetic observatory location {} is not completely ' 'specified (lon, lat, alt) and will be ignored.'.format( obs_geo), AstropyUserWarning) global_info['location'] = None # Get global time reference # Keywords are listed in order of precedence, as stated by the standard for key, format_ in (('MJDREF', 'mjd'), ('JDREF', 'jd'), ('DATEREF', 'fits')): if key in global_info: global_info['ref_time'] = { 'val': global_info[key], 'format': format_ } break else: # If none of the three keywords is present, MJDREF = 0.0 must be assumed global_info['ref_time'] = {'val': 0, 'format': 'mjd'}
def _verify_global_info(global_info): """ Given the global time reference frame information, verify that each global time coordinate attribute will be given a valid value. Parameters ---------- global_info : dict Global time reference frame information. """ # Translate FITS deprecated scale into astropy scale, or else just convert # to lower case for further checks. global_info['scale'] = FITS_DEPRECATED_SCALES.get(global_info['TIMESYS'], global_info['TIMESYS'].lower()) # Verify global time scale if global_info['scale'] not in Time.SCALES: # 'GPS' and 'LOCAL' are FITS recognized time scale values # but are not supported by astropy. if global_info['scale'] == 'gps': warnings.warn( 'Global time scale (TIMESYS) has a FITS recognized time scale ' 'value "GPS". In Astropy, "GPS" is a time from epoch format ' 'which runs synchronously with TAI; GPS is approximately 19 s ' 'ahead of TAI. Hence, this format will be used.', AstropyUserWarning) # Assume that the values are in GPS format global_info['scale'] = 'tai' global_info['format'] = 'gps' if global_info['scale'] == 'local': warnings.warn( 'Global time scale (TIMESYS) has a FITS recognized time scale ' 'value "LOCAL". However, the standard states that "LOCAL" should be ' 'tied to one of the existing scales because it is intrinsically ' 'unreliable and/or ill-defined. Astropy will thus use the default ' 'global time scale "UTC" instead of "LOCAL".', AstropyUserWarning) # Default scale 'UTC' global_info['scale'] = 'utc' global_info['format'] = None else: raise AssertionError( 'Global time scale (TIMESYS) should have a FITS recognized ' 'time scale value (got {!r}). The FITS standard states that ' 'the use of local time scales should be restricted to alternate ' 'coordinates.'.format(global_info['TIMESYS'])) else: # Scale is already set global_info['format'] = None # Check if geocentric global location is specified obs_geo = [global_info[attr] for attr in ('OBSGEO-X', 'OBSGEO-Y', 'OBSGEO-Z') if attr in global_info] # Location full specification is (X, Y, Z) if len(obs_geo) == 3: global_info['location'] = EarthLocation.from_geocentric(*obs_geo, unit=u.m) else: # Check if geodetic global location is specified (since geocentric failed) # First warn the user if geocentric location is partially specified if obs_geo: warnings.warn( 'The geocentric observatory location {} is not completely ' 'specified (X, Y, Z) and will be ignored.'.format(obs_geo), AstropyUserWarning) # Check geodetic location obs_geo = [global_info[attr] for attr in ('OBSGEO-L', 'OBSGEO-B', 'OBSGEO-H') if attr in global_info] if len(obs_geo) == 3: global_info['location'] = EarthLocation.from_geodetic(*obs_geo) else: # Since both geocentric and geodetic locations are not specified, # location will be None. # Warn the user if geodetic location is partially specified if obs_geo: warnings.warn( 'The geodetic observatory location {} is not completely ' 'specified (lon, lat, alt) and will be ignored.'.format(obs_geo), AstropyUserWarning) global_info['location'] = None # Get global time reference # Keywords are listed in order of precedence, as stated by the standard for key, format_ in (('MJDREF', 'mjd'), ('JDREF', 'jd'), ('DATEREF', 'fits')): if key in global_info: global_info['ref_time'] = {'val': global_info[key], 'format': format_} break else: # If none of the three keywords is present, MJDREF = 0.0 must be assumed global_info['ref_time'] = {'val': 0, 'format': 'mjd'}
def _verify_column_info(column_info, global_info): """ Given the column-specific time reference frame information, verify that each column-specific time coordinate attribute has a valid value. Return True if the coordinate column is time, or else return False. Parameters ---------- global_info : dict Global time reference frame information. column_info : dict Column-specific time reference frame override information. """ scale = column_info.get('TCTYP', None) unit = column_info.get('TCUNI', None) location = column_info.get('TRPOS', None) if scale is not None: # Non-linear coordinate types have "4-3" form and are not time coordinates if TCTYP_RE_TYPE.match(scale[:5]) and TCTYP_RE_ALGO.match(scale[5:]): return False elif scale.lower() in Time.SCALES: column_info['scale'] = scale.lower() column_info['format'] = None elif scale in FITS_DEPRECATED_SCALES.keys(): column_info['scale'] = FITS_DEPRECATED_SCALES[scale] column_info['format'] = None # TCTYPn (scale) = 'TIME' indicates that the column scale is # controlled by the global scale. elif scale == 'TIME': column_info['scale'] = global_info['scale'] column_info['format'] = global_info['format'] elif scale == 'GPS': warnings.warn( 'Table column "{}" has a FITS recognized time scale value "GPS". ' 'In Astropy, "GPS" is a time from epoch format which runs ' 'synchronously with TAI; GPS runs ahead of TAI approximately ' 'by 19 s. Hence, this format will be used.'.format( column_info), AstropyUserWarning) column_info['scale'] = 'tai' column_info['format'] = 'gps' elif scale == 'LOCAL': warnings.warn( 'Table column "{}" has a FITS recognized time scale value "LOCAL". ' 'However, the standard states that "LOCAL" should be tied to one ' 'of the existing scales because it is intrinsically unreliable ' 'and/or ill-defined. Astropy will thus use the global time scale ' '(TIMESYS) as the default.'.format(column_info), AstropyUserWarning) column_info['scale'] = global_info['scale'] column_info['format'] = global_info['format'] else: # Coordinate type is either an unrecognized local time scale # or a linear coordinate type return False # If TCUNIn is a time unit or TRPOSn is specified, the column is a time # coordinate. This has to be tested since TCTYP (scale) is not specified. elif (unit is not None and unit in FITS_TIME_UNIT) or location is not None: column_info['scale'] = global_info['scale'] column_info['format'] = global_info['format'] # None of the conditions for time coordinate columns is satisfied else: return False # Check if column-specific reference position TRPOSn is specified if location is not None: # Observatory position (location) needs to be specified only # for 'TOPOCENTER'. if location == 'TOPOCENTER': column_info['location'] = global_info['location'] if column_info['location'] is None: warnings.warn( 'Time column reference position "TRPOSn" value is "TOPOCENTER". ' 'However, the observatory position is not properly specified. ' 'The FITS standard does not support this and hence reference ' 'position will be ignored.', AstropyUserWarning) else: column_info['location'] = None # Warn user about ignoring global reference position when TRPOSn is # not specified elif global_info['TREFPOS'] == 'TOPOCENTER': if global_info['location'] is not None: warnings.warn( 'Time column reference position "TRPOSn" is not specified. The ' 'default value for it is "TOPOCENTER", and the observatory position ' 'has been specified. However, for supporting column-specific location, ' 'reference position will be ignored for this column.', AstropyUserWarning) column_info['location'] = None else: column_info['location'] = None # Get reference time column_info['ref_time'] = global_info['ref_time'] return True
def _verify_column_info(column_info, global_info): """ Given the column-specific time reference frame information, verify that each column-specific time coordinate attribute has a valid value. Return True if the coordinate column is time, or else return False. Parameters ---------- global_info : dict Global time reference frame information. column_info : dict Column-specific time reference frame override information. """ scale = column_info.get('TCTYP', None) unit = column_info.get('TCUNI', None) location = column_info.get('TRPOS', None) if scale is not None: # Non-linear coordinate types have "4-3" form and are not time coordinates if TCTYP_RE_TYPE.match(scale[:5]) and TCTYP_RE_ALGO.match(scale[5:]): return False elif scale.lower() in Time.SCALES: column_info['scale'] = scale.lower() column_info['format'] = None elif scale in FITS_DEPRECATED_SCALES.keys(): column_info['scale'] = FITS_DEPRECATED_SCALES[scale] column_info['format'] = None # TCTYPn (scale) = 'TIME' indicates that the column scale is # controlled by the global scale. elif scale == 'TIME': column_info['scale'] = global_info['scale'] column_info['format'] = global_info['format'] elif scale == 'GPS': warnings.warn( 'Table column "{}" has a FITS recognized time scale value "GPS". ' 'In Astropy, "GPS" is a time from epoch format which runs ' 'synchronously with TAI; GPS runs ahead of TAI approximately ' 'by 19 s. Hence, this format will be used.'.format(column_info), AstropyUserWarning) column_info['scale'] = 'tai' column_info['format'] = 'gps' elif scale == 'LOCAL': warnings.warn( 'Table column "{}" has a FITS recognized time scale value "LOCAL". ' 'However, the standard states that "LOCAL" should be tied to one ' 'of the existing scales because it is intrinsically unreliable ' 'and/or ill-defined. Astropy will thus use the global time scale ' '(TIMESYS) as the default.'. format(column_info), AstropyUserWarning) column_info['scale'] = global_info['scale'] column_info['format'] = global_info['format'] else: # Coordinate type is either an unrecognized local time scale # or a linear coordinate type return False # If TCUNIn is a time unit or TRPOSn is specified, the column is a time # coordinate. This has to be tested since TCTYP (scale) is not specified. elif (unit is not None and unit in FITS_TIME_UNIT) or location is not None: column_info['scale'] = global_info['scale'] column_info['format'] = global_info['format'] # None of the conditions for time coordinate columns is satisfied else: return False # Check if column-specific reference position TRPOSn is specified if location is not None: # Observatory position (location) needs to be specified only # for 'TOPOCENTER'. if location == 'TOPOCENTER': column_info['location'] = global_info['location'] if column_info['location'] is None: warnings.warn( 'Time column reference position "TRPOSn" value is "TOPOCENTER". ' 'However, the observatory position is not properly specified. ' 'The FITS standard does not support this and hence reference ' 'position will be ignored.', AstropyUserWarning) else: column_info['location'] = None # Since TRPOSn is not specified, global reference position is # considered. elif global_info['TREFPOS'] == 'TOPOCENTER': column_info['location'] = global_info['location'] if column_info['location'] is None: warnings.warn( 'Time column reference position "TRPOSn" is not specified. The ' 'default value for it is "TOPOCENTER", but due to unspecified ' 'observatory position, reference position will be ignored.', AstropyUserWarning) else: column_info['location'] = None # Get reference time column_info['ref_time'] = global_info['ref_time'] return True