Ejemplo n.º 1
0
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'}
Ejemplo n.º 2
0
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'}
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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