B
    îq\IY  ã            	   @   s"  d dl Z d dlZd dlmZmZ d dlZddlmZm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ d dlmZ e  d¡Ze  d¡Zdddddddddg	ZdZdZd  d !e¡¡Z"dd„ Z#dddd œZ$d!d"„ Z%d#d$„ Z&d%d&„ Z'd'd(„ Z(d)d*„ Z)d+d,„ Z*d-d.„ Z+dS )/é    N)ÚdefaultdictÚOrderedDicté   )ÚHeaderÚCard)Úunits)ÚEarthLocation)ÚColumn)ÚTimeÚ	TimeDelta)ÚBARYCENTRIC_SCALES)ÚFITS_DEPRECATED_SCALES)ÚAstropyUserWarningz(?P<type>[A-Z]+)[-]+z(?P<algo>[A-Z]+)\s*ÚsÚdÚaZcyÚminÚhZyrZtaZBa)ÚTIMESYSÚMJDREFÚJDREFÚDATEREFÚTREFPOSZTREFDIRZTIMEUNITZTIMEOFFSzOBSGEO-XzOBSGEO-YzOBSGEO-ZzOBSGEO-LzOBSGEO-BzOBSGEO-HÚDATEzDATE-OBSzDATE-AVGzDATE-BEGzDATE-ENDzMJD-OBSzMJD-AVGzMJD-BEGzMJD-END)ÚTCTYPÚTCUNIÚTRPOSz({0})[0-9]+ú|c             C   s   t  t| ¡dk	S )z”
    Check if the FITS header keyword is a time column-specific keyword.

    Parameters
    ----------
    keyword : str
        FITS keyword.
    N)ÚreÚmatchÚCOLUMN_TIME_KEYWORD_REGEXP)Úkeyword© r"   ú7lib/python3.7/site-packages/astropy/io/fits/fitstime.pyÚis_time_column_keyword3   s    	r$   )ÚUTCzDefault time scale)g        zTime columns are jd = jd1 + jd2)Ú
TOPOCENTERzTime reference position)r   r   r   c                sx  t  ˆ d ˆ d  ¡ ¡ˆ d< ˆ d tjkrˆ d dkrRt dt¡ dˆ d< dˆ d< ˆ d dkr|t dt¡ d	ˆ d< d
ˆ d< q˜td 	ˆ d ¡ƒ‚nd
ˆ d< ‡ fdd„dD ƒ}t
|ƒdkrÎtj|dtjiŽˆ d< nf|rät d 	|¡t¡ ‡ fdd„dD ƒ}t
|ƒdkrtj|Ž ˆ d< n |r,t d 	|¡t¡ d
ˆ d< x>dD ](\}}|ˆ kr:ˆ | |dœˆ d< P q:W dddœˆ d< d
S )zö
    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.
    r   ÚscaleÚgpszã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.ÚtaiÚformatZlocala+  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".ÚutcNzÀ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.c                s   g | ]}|ˆ krˆ | ‘qS r"   r"   )Ú.0Úattr)Úglobal_infor"   r#   ú
<listcomp>{   s    z'_verify_global_info.<locals>.<listcomp>)zOBSGEO-XzOBSGEO-YzOBSGEO-Zé   ÚunitÚlocationzaThe geocentric observatory location {} is not completely specified (X, Y, Z) and will be ignored.c                s   g | ]}|ˆ krˆ | ‘qS r"   r"   )r,   r-   )r.   r"   r#   r/   Œ   s    )zOBSGEO-LzOBSGEO-BzOBSGEO-HzeThe geodetic observatory location {} is not completely specified (lon, lat, alt) and will be ignored.))r   Úmjd)r   Újd)r   Úfits)Úvalr*   Úref_timer   r3   )r   ÚgetÚlowerr
   ÚSCALESÚwarningsÚwarnr   ÚAssertionErrorr*   Úlenr   Zfrom_geocentricÚuÚmZfrom_geodetic)r.   Zobs_geoÚkeyZformat_r"   )r.   r#   Ú_verify_global_infoE   sR    


rB   c             C   sö  |   dd¡}|   dd¡}|   dd¡}|dk	r&t |dd… ¡rVt |dd… ¡rVdS | ¡ tjkrz| ¡ | d< d| d< nª|t ¡ krœt| | d< d| d< nˆ|d	kr¾|d | d< |d | d< nf|d
krêt	 
d | ¡t¡ d| d< d| d< n:|dkr t	 
d | ¡t¡ |d | d< |d | d< ndS n<|dk	r:|tksD|dk	r^|d | d< |d | d< ndS |dk	r¨|dkrž|d | d< | d dkr¦t	 
dt¡ nd| d< n>|d dkrÞ|d | d< | d dkræt	 
dt¡ nd| d< |d | d< dS )a   
    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.
    r   Nr   r   é   Fr'   r*   ÚTIMEZGPSzÞ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.r)   r(   ZLOCALa  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.r&   r2   zÑ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.r   z´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.r7   T)r8   ÚTCTYP_RE_TYPEr   ÚTCTYP_RE_ALGOr9   r
   r:   r   Úkeysr;   r<   r*   r   ÚFITS_TIME_UNIT)Úcolumn_infor.   r'   r1   r2   r"   r"   r#   Ú_verify_column_info¨   sf    
$






rJ   c             C   sx   | j j ¡ dkrt| j jtkrt|d |d |d ddœ}|d dkrp|d	 |d	< |d	 dkrpt d
 | j j¡t¡ |S dS )a/  
    Check if a column without corresponding time column keywords in the
    FITS header represents time or not. If yes, return the time column
    information needed for its conversion to Time.
    This is only applicable to the special-case where a column has the
    name 'TIME' and a time unit.
    rD   r'   r*   r7   N)r'   r*   r7   r2   r   r&   r2   z\Time column "{}" reference position will be ignored due to unspecified observatory position.)	ÚinfoÚnameÚupperr1   rH   r;   r<   r*   r   )Úcolr.   rI   r"   r"   r#   Ú_get_info_if_time_column  s    rO   c          	   C   sà   xÚ|  ¡ D ]Î\}}| d¡rŽ|| jkrØ|dkr2dn|d }y2d|krVt| d¡d ƒnd}t|d||d}W n tk
r€   Y nX || j|< q
| d	¡r
|| jkr
yt|d
|d d}W n tk
rÌ   Y nX || j|< q
W dS )a  
    Convert the table metadata for time informational keywords
    to astropy Time.

    Parameters
    ----------
    table : `~astropy.table.Table`
        The table whose time metadata is to be converted.
    global_info : dict
        Global time reference frame information.
    r   r+   r'   Ú.éÿÿÿÿr   r5   )r*   r'   Ú	precisionzMJD-r3   )r*   r'   N)ÚitemsÚ
startswithÚmetar>   Úsplitr
   Ú
ValueError)Útabler.   rA   Úvaluer'   rR   r"   r"   r#   Ú_convert_global_time4  s&    



rZ   c          
   C   s”  yP| j jjdkrLtt| j jjdd… ƒd dƒ}t| d|d ||d d	S |d
 dkrjt| d|d dS |d d dkrì|d d
 dkrì| jd dkrÌ| jdkrÌt| d | d |d |d d
 |d dS t| |d |d d
 |d dS t|d d |d |d d
 |d d}| jd dkrD| jdkrDt	| d | d ƒ}nt	| ƒ}|| S  t
k
rŽ } zt d || j j¡t¡ | S d}~X Y nX dS )a  
    Convert time columns to astropy Time columns.

    Parameters
    ----------
    col : `~astropy.table.Column`
        The time coordinate column to be converted to Time.
    column_info : dict
        Column-specific time reference frame override information.
    )ÚSÚUé   Né   r   r5   r'   r2   )r*   r'   rR   r2   r*   r(   )r*   r2   r7   r6   )r4   r3   rQ   r   ).r   ).r   )r'   r*   r2   z`The exception "{}" was encountered while trying to convert the time column "{}" to Astropy Time.)rK   ZdtypeZkindÚmaxÚintÚstrr
   ÚshapeÚndimr   Ú	Exceptionr;   r<   r*   rL   r   )rN   rI   rR   r7   Z
delta_timeÚerrr"   r"   r#   Ú_convert_time_columnZ  s<     




rf   c             C   sP  dddœ}t tƒ}| jdd}xˆ| jD ]~\}}}|tkrL|||< | |¡ q&t|ƒr„t d|¡ 	¡ \}}	||t
|	ƒ |< | |¡ q&|dkr&t d|¡r&|| ||< q&W t|ƒ t||ƒ |rþx>| ¡ D ]2\}	}
t|
|ƒrÈ|j|	d	  }t|| |
ƒ||< qÈW xLt|jƒD ]>\}	}|	d	 |kr
t|| |ƒ}
|
r
t|| |
ƒ||< q
W |S )
as  
    Read FITS binary table time columns as `~astropy.time.Time`.

    This method reads the metadata associated with time coordinates, as
    stored in a FITS binary table header, converts time columns into
    `~astropy.time.Time` columns and reads global reference times as
    `~astropy.time.Time` instances.

    Parameters
    ----------
    hdr : `~astropy.io.fits.header.Header`
        FITS Header
    table : `~astropy.table.Table`
        The table whose time columns are to be read as Time

    Returns
    -------
    hdr : `~astropy.io.fits.header.Header`
        Modified FITS Header (time metadata removed)
    r%   r&   )r   r   T)Ústripz([A-Z]+)([0-9]+))zOBSGEO-XzOBSGEO-YzOBSGEO-ZzTTYPE[0-9]+r   )r   r   ÚcopyZcardsÚTIME_KEYWORDSÚremover$   r   r   Úgroupsr`   rB   rZ   rS   rJ   Úcolnamesrf   Ú	enumeraterO   )ÚhdrrX   r.   Ztime_columnsZhcopyrA   rY   ÚcommentÚbaseÚidxrI   Zcolnamer"   r"   r#   Úfits_to_time—  s:    

rr   c       	         sú  | j dd}tdd„ t ¡ D ƒƒ}ttƒ|jd< |jd }| j t	¡}d‰ x¤|D ]š}|j
jd dkr€| |j
jt|jƒ¡ qRt |j|jg¡}t |d	|j¡}| |j
jt|d
d¡ | j |j
j¡d }|j ¡ ||j
j d< d
||j
j d< t|dƒdkr&ˆ dk	rît d |j
j¡t¡ qRd||j
j d< |jtkr`t d |j
j|j ¡ ¡t¡ ˆ dkrÒ|j ‰ ˆ j!dkr¸xRdD ]0}|j"ttˆ |ƒ #t$j%¡ƒd | ¡ ¡d q‚W n| &‡ fdd„dD ƒ¡ qRˆ |j krRt'd ˆ |j ¡ƒ‚qRW ||fS )as  
    Replace Time columns in a Table with non-mixin columns containing
    each element as a vector of two doubles (jd1, jd2) and return a FITS
    header with appropriate time coordinate keywords.
    jd = jd1 + jd2 represents time in the Julian Date format with
    high-precision.

    Parameters
    ----------
    table : `~astropy.table.Table`
        The table whose Time columns are to be replaced.

    Returns
    -------
    table : `~astropy.table.Table`
        The table with replaced Time columns
    hdr : `~astropy.io.fits.header.Header`
        Header containing global time reference frame FITS keywords
    F)Z	copy_datac             S   s&   g | ]\}}t ||d  |d d‘qS )r   r   )r!   rY   ro   )r   )r,   rA   r6   r"   r"   r#   r/   û  s   z time_to_fits.<locals>.<listcomp>Z__coordinate_columns__Nr5   Zformatted_valuer   r   )r1   r   Z
coord_typeZ
coord_unitr2   z‘Time Column "{}" has no specified location, but global Time Position is present, which will be the default for this column in FITS specification.r&   Ztime_ref_poszREarth Location "TOPOCENTER" for Time Column "{}" is incompatabile with scale "{}".)ÚxÚyÚzz	OBSGEO-{})rL   c                s0   g | ](}t d  | ¡ ¡tˆ |ƒ tj¡d‘qS )z	OBSGEO-{})r!   rY   )r   r*   rM   ÚgetattrÚto_valuer?   r@   )r,   Údim)r2   r"   r#   r/   7  s   z†Multiple Time Columns with different geocentric observatory locations ({}, {}) encountered.This is not supported by the FITS standard.)(rh   r   ÚGLOBAL_TIME_INFOrS   r   r   rU   ÚcolumnsÚ
isinstancer
   rK   Zserialize_methodZreplace_columnrL   r	   rY   ÚnpZarrayZjd1Zjd2Zrollaxisrc   rl   Úindexr'   rM   rv   r;   r<   r*   r   r   r2   ÚsizeZ
add_columnrw   r?   r@   ÚextendrW   )	rX   Znewtablern   Z
coord_metaZ	time_colsrN   Zjd12Únrx   r"   )r2   r#   Útime_to_fitsâ  sR    




r   ),r   r;   Úcollectionsr   r   Znumpyr|   Ú r   r   Zastropyr   r?   Zastropy.coordinatesr   Zastropy.tabler	   Zastropy.timer
   r   Zastropy.time.corer   Zastropy.time.formatsr   Zastropy.utils.exceptionsr   ÚcompilerE   rF   rH   ri   ZCOLUMN_TIME_KEYWORDSr*   Újoinr    r$   ry   rB   rJ   rO   rZ   rf   rr   r   r"   r"   r"   r#   Ú<module>   s:   

	cn&=K