#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Nov 21 10:59:47 2017

@author: Neo

Retrieve the result from .eop and .eob file which is generated by
the program getpar.

.eop and .eob files contain estimates of X pole coordinate, Y pole coordinate,
UT1-TAI angle, UT1 rate and UT1 acceleration as well as their formal
uncertainties. Estimates are obtained using all observations of the specific
session. Database names and time-tags are also included.

   File contains lines of two types:
1) Comment.
The first character is #. Header comment contain the full name of the spool
file.
The first two symbols are blank. Header lines contain titles of the columns.

2) Format.
2.1).eop
   Field   Format Units     Meaning
   1-8     A8     --        record type identifier: EOP_LOC:
   11-20   A10    --        database name with leading dollar sign
   23-25   I3     --        database version number
   34-49   A16    calend    EOP time tag in Solve format: YYYY.MM.DD-hh:mm
                            Time scale is not defined. Adjustments are at TDB
                            time scale, a priori EOP are at unknown time scale.
   58-63   I6     --        number of observation used for getting these EOP
                            estimates.
   69-79   F11.4  mas       estimate of X-pole coordinate
   84-93   F10.2  muas      formal uncertainty of X-pole coordinate
   99-109  F11.4  mas       estimate of Y-pole coordinate
   114-123 F10.2  muas      formal uncertainty of Y-pole coordinate
   129-139 F11.4  msec      estimates of UT1-TAI
   144-153 F10.2  musec     formal uncertainty of UT1-TAI
   159-169 F11.4  mas/day   estimates of X pole rate
   174-183 F10.2  muas/day  formal uncertainties of X pole rate
   189-199 F11.4  msec/day  estimates of Y pole rate
   204-213 F10.2  msec/day  formal uncertainties of Y pole rate
   219-229 F11.4  msec/day  estimates of UT1-TAI rate
   234-243 F10.2  musec/day formal uncertainties of UT1-TAI rate
   249-259 F11.4  ms/day**2 estimates of UT1-TAI acceleration
   264-273 F10.2  ms/day**2 formal uncertainties of UT1-TAI acceleration

2.2).eob
  1    1-1    A1     ---     Usage flag
  2    3-14   F12.6  days    Modified Julian date of the TDT time tag for
                             pole coordinates and UT1
  3   16-25   A10    ---     Database name
  4   27-32   A6     ---     IVS session code (if available)
  5   34-41   F8.6   arcsec  The estimate of X pole coordinate
  6   43-50   F8.6   arcsec  The estimate of Y pole coordinate
  7   52-62   F11.7  sec     The UT1-TAI function
  8   64-71   F8.3   mas     Adjustment of the nutation in longitude angle with
                                        respect to IAU 1980 nutation expansion
  9   73-80   F8.3   mas     Adjustment of the nutation in obliquity angle with
                                        respect to IAU 1980 theory
 10   82-90   F9.6   asc/day The estimate of X pole rate
 11   92-100  F9.6   asc/day The estimate of Y pole rate
 12  102-108  F7.4   ms/day  The estimate of UT1 rate
 13  110-117  F8.6   arcsec  Formal uncertainty of X pole coordinate
 14  119-126  F8.6   arcsec  Formal uncertainty of Y pole coordinate
 15  128-136  F9.7   sec     Formal uncertainty of UT1-UTC function
 16  138-144  F7.3   mas     Formal uncertainty of nutation in longitude angle
 17  146-152  F7.3   mas     Formal uncertainty of nutation in obliquity angle
 18  154-162  F9.6   asc/day Formal uncertainty of X pole rate
 19  164-172  F9.6   asc/day Formal uncertainty of Y pole rate
 20  174-180  F7.4   asc/day Formal uncertainty of UT1 rate
 21  182-187  F6.4   --      Correlation between the estimates of X-pole
                                          positions and Y-pole position
 22  189-194  F6.4   --      Correlation between the estimates of X-pole
                                         positions and UT1-TAI angle
 23  196-201  F6.4   --      Correlation between the estimates of Y-pole
                                         positions and UT1-TAI angle
 24  203-208  F6.4   --      Correlation between the estimates of nutation in
                                         longitude and nutation in obliquity
 25  210-215  F6.4   --      Correlation between the estimates of X-pole
                                          positions and UT1 rate
 26  217-222  F6.4   --      Correlation between the estimates of Y-pole
                                         positions and UT1-TAI date
 27  224-229  F6.4   --      Correlation between the estimates of
                                         UT1-TAI angle UT1 rate
 28  231-235  F5.2   hours   Session duration
 29  237-243  F7.2   psec    Weighted root mean square of postfit residuals
 30  245-250  I6     --      Number of used observations in the session
 31  252-263  F12.6  days    Modified Julian date for nutation at TDT time
                             scale
 32  265-328  A64    --      The network configuration line. Consists of
                             two characters IVS station codes listed
                             in alphabetic order for stations that participated
                             in the experiment and supplied the data that have
                             been used in processing this experiment.

    If the specific parameter was not estimated in this experiment, the field
for its value and formal uncertainty is replaced by filler: $$$$$$. The filler
takes entire field.

3) .eops
 Columns  Units   Meaning
    1     days    Modified Julian date
    2     arcsec  X pole coordinate
    3     arcsec  Y pole coordinate
    4     sec     UT1-TAI
    5     mas     Celestial pole offset dX wrt IAU 2006
    6     mas     Celestial pole offset dY wrt IAU 2006
    7     arcsec  Formal uncertainty of X pole coordinate
    8     arcsec  Formal uncertainty of Y pole coordinate
    9     sec     Formal uncertainty of UT1-TAI
   10     mas     Formal uncertainty of celestial pole offset dX
   11     mas     Formal uncertainty of celestial pole offset dY
   12     --      10-character database identifier
   13     --      Correlation between X and Y
   14     --      Correlation between X and UT1-TAI
   15     --      Correlation between Y and UT1-TAI
   16     --      Correlation between dX and dY
   17     --      Number of used observations in the session
   18     --      6-character session identifier
   19     hours   Session duration
   20     asc/day X pole coordinate rate
   21     asc/day Y pole coordinate rate
   22     ms      Excess of length of day
   23             Field not used
   24             Field not used
   25     asc/day Formal uncertainty of X pole coordinate rate
   26     asc/day Formal uncertainty of Y pole coordinate rate
   27     ms      Formal uncertainty of excess of length of day
   28             Field not used
   29             Field not used
   30     ps      Postfit rms delay
   31     --      Array structure

"""

from astropy.table import Table, Column
import numpy as np
from time import strptime, mktime
import sys
import os

__all__ = {"read_eop", "read_eob", "read_eops"}


# ------------------------------  FUNCTIONS  ---------------------------
def time_trans(timestr):
    '''Transform the time from string to nvalue(JD year).

    The time string is formated as YYYY.MM.DD-hh:mm.
    '''

    ts = mktime(strptime(str(timestr, 'utf-8'),
                         "%Y.%m.%d-%H:%M"))
    return ts / 365.25 / 86400 + 1970.0


def read_eop(eop_file):
    '''Retrieve the result from .eop file.

    Parameters
    ----------
    eop_file : string
        name of .eop file

    Returns
    ----------
    dbname : array, string
       database name with leading dollar sign
    tag : array, float
        EOP time flag, year
    obsnum : array, int
        number of observations used
    X : array, float
        X-pole coordinate, mas
    X_err : array, float
        formal uncertainty of X, mas
    Y : array, float
        Y-pole coordinate, mas
    Y_err : array, float
        formal uncertainty of Y, mas
    U : array, float
        UT1 - TAI, msec
    U_err : array, float
        formal uncertainty of U, msec
    XR : array, float
        X-pole coordinate rate, mas/day
    XR_err : array. float
        formal uncertainty of XR, mas/day
    YR : array, float, mas/day
        Y-pole coordinate rate, mas/day
    YR_err : array. float
        formal uncertainty of YR, mas/day
    UR : array, float
        UT1 - TAI rate, msec/day
    UR_err : array. float
        formal uncertainty of UR, msec/day
    '''

    if not os.path.isfile(eop_file):
        print("Couldn't find the file", eop_file)
        sys.exit()

    dbname = np.genfromtxt(eop_file, dtype=str, usecols=(1,))
    tag = np.genfromtxt(eop_file, usecols=(4,), converters={4: time_trans})
    obsnum = np.genfromtxt(eop_file, dtype=int, usecols=(6,))
    X, X_err, Y, Y_err, U, U_err = np.genfromtxt(eop_file,
                                                 usecols=np.arange(8, 20, 2),
                                                 missing_values='*'*8,
                                                 filling_values=0.,
                                                 unpack=True)
    XR, XR_err, YR, YR_err, UR, UR_err = np.genfromtxt(
        eop_file, usecols=np.arange(20, 32, 2), unpack=True)

    # uas -> mas or usec -> msec
    X_err, Y_err, U_err = X_err / 1000.0, Y_err / 1000.0, U_err / 1000.0

    # uas/day -> mas/day or usec/day -> msec/day
    XR_err, YR_err, UR_err = XR_err / 1000, YR_err / 1000, UR_err / 1000

    return [dbname, tag, obsnum, X, X_err, Y, Y_err, U, U_err,
            XR, XR_err, YR, YR_err, UR, UR_err]


def zero_err(err):
    '''set zero-error to 0.999999
    '''

    return np.where(err == 0, 0.999999, err)


def read_eob(eob_file):
    '''Retrieve the result from .eob file.

    Parameters
    ----------
    eob_file : string
        name of .eob file

    Returns
    ----------
    dbname : array, string
       database name with leading dollar sign
    tag_eop : array, float
        EOP time flag, modified Julian data
    tag_nut : array, float
        Nutation time flag, modified Julian data
    obsnum : array, int
        number of observations used
    X : array, float
        X-pole coordinate, mas
    X_err : array, float
        formal uncertainty of X, mas
    Y : array, float
        Y-pole coordinate, mas
    Y_err : array, float
        formal uncertainty of Y, mas
    U : array, float
        UT1 - TAI, msec
    U_err : array, float
        formal uncertainty of U, msec
    XR : array, float
        X-pole coordinate rate, mas/day
    XR_err : array, float
        formal uncertainty of XR, mas/day
    YR : array, float, mas/day
        Y-pole coordinate rate, mas/day
    YR_err : array, float
        formal uncertainty of YR, mas/day
    UR : array, float
        UT1 - TAI rate, msec/day
    UR_err : array, float
        formal uncertainty of UR, msec/day
    P : array, float
        nutation in longitude, mas
    P_err : array, float
        formal uncertainty of P, mas
    E : array, float
        nutation on obliquity, mas
    E_err : array, float
        formal uncertainty of E, mas
    corXY : array, float
        correlation between X and Y
    corXU : array, float
        correlation between X and U
    corYU : array, float
        correlation between Y and U
    corPE : array, float
        correlation between X and Y
    corXUR : array, float
        correlation between X and UR
    corYUR : array, float
        correlation between Y and UR
    corUUR : array, float
        correlation between U and UR
    '''

    if not os.path.isfile(eob_file):
        print("Couldn't find the file", eob_file)
        sys.exit()

    dbname = np.genfromtxt(eob_file, dtype=str, usecols=(1,))

    tag_eop, tag_nut = np.genfromtxt(eob_file, usecols=(0, 28), unpack=True)

    obsnum = np.genfromtxt(eob_file, dtype=int, usecols=(27,))

    X, Y, U, P, E, XR, YR, UR = np.genfromtxt(eob_file,
                                              usecols=np.arange(2, 10),
                                              missing_values='*'*7,
                                              filling_values=0.0,
                                              unpack=True)

    [X_err, Y_err, U_err,
     P_err, E_err,
     XR_err, YR_err, UR_err] = np.genfromtxt(eob_file,
                                             usecols=np.arange(10, 18),
                                             missing_values='*'*7,
                                             filling_values=1.0e6,
                                             unpack=True)

    # Avoid zero-error, 0.0 -> 0.999999
    X_err = zero_err(X_err)
    Y_err = zero_err(Y_err)
    U_err = zero_err(U_err)
    P_err = zero_err(P_err)
    E_err = zero_err(E_err)
    XR_err = zero_err(XR_err)
    YR_err = zero_err(XR_err)
    UR_err = zero_err(UR_err)

    [corXY, corXU, corYU, corPE, corUUR, corXUR, corYUR
     ] = np.genfromtxt(eob_file, usecols=np.arange(18, 25), unpack=True)

    # as -> mas or sec -> msec
    X, Y, U = X * 1000.0, Y * 1000.0, U * 1000.0
    X_err, Y_err, U_err = X_err * 1000.0, Y_err * 1000.0, U_err * 1000.0

    # as/day -> mas/day or sec/day -> msec/day
    XR, YR = XR * 1000, YR * 1000
    XR_err, YR_err, UR_err = XR_err * 1000, YR_err * 1000, UR_err * 1000

    return [dbname, obsnum, tag_eop, X, X_err, Y, Y_err, U, U_err,
            XR, XR_err, YR, YR_err, UR, UR_err,
            corXY, corXU, corYU, corXUR, corYUR, corUUR,
            tag_nut, P, P_err, E, E_err, corPE]


def read_eops(eops_file):
    '''Retrieve from the result from .eops data.

    Data columns are listed as follow:

      Columns  Units   Meaning
         1     days    Modified Julian date
         2     arcsec  X pole coordinate
         3     arcsec  Y pole coordinate
         4     sec     UT1-TAI
         5     mas     Celestial pole offset dX wrt IAU 2006
         6     mas     Celestial pole offset dY wrt IAU 2006
         7     arcsec  Formal uncertainty of X pole coordinate
         8     arcsec  Formal uncertainty of Y pole coordinate
         9     sec     Formal uncertainty of UT1-TAI
        10     mas     Formal uncertainty of celestial pole offset dX
        11     mas     Formal uncertainty of celestial pole offset dY
        12     --      10-character database identifier
        13     --      Correlation between X and Y
        14     --      Correlation between X and UT1-TAI
        15     --      Correlation between Y and UT1-TAI
        16     --      Correlation between dX and dY
        17     --      Number of used observations in the session
        18     --      6-character session identifier
        19     hours   Session duration
        20     asc/day X pole coordinate rate
        21     asc/day Y pole coordinate rate
        22     ms      Excess of length of day
        23             Field not used
        24             Field not used
        25     asc/day Formal uncertainty of X pole coordinate rate
        26     asc/day Formal uncertainty of Y pole coordinate rate
        27     ms      Formal uncertainty of excess of length of day
        28             Field not used
        29             Field not used
        30     ps      Postfit rms delay
        31     --      Array structure

    Parameters
    ----------
    eops_file : string
        name of .eops file

    Returns
    ----------
    eops_table : astropy.table.Table object
        |__
            mjd : array, float
                time lag, modified Julian date
            Xp : array, float
                X-pole coordinate, mas
            Xperr : array, float
                formal uncertainty of X, mas
            Yp : array, float
                Y-pole coordinate, mas
            Yperr : array, float
                formal uncertainty of Y, mas
            U : array, float
                UT1 - TAI, msec
            Uerr : array, float
                formal uncertainty of U, msec
            dX : array, float
                X coordinate of nutation offset, mas
            dXerr : array. float
                formal uncertainty of XR, mas
            dY : array, float, mas
                Y coordinate of Nutation offset, mas
            dYerr : array. float
                formal uncertainty of dY, mas
    '''

    if not os.path.isfile(eops_file):
        print("Couldn't find the file", eops_file)
        sys.exit()

    mjd, Xp, Yp, U, dX, dY = np.genfromtxt(eops_file,
                                           usecols=range(6),
                                           unpack=True)

    Xperr, Yperr, Uerr, dXerr, dYerr = np.genfromtxt(eops_file,
                                                     usecols=range(6, 11, 1),
                                                     unpack=True)
    # as -> mas or sec -> msec
    Xp, Yp, Up = Xp * 1000.0, Yp * 1000.0, Up * 1000.0
    Xperr, Yperr, Uerr = Xperr * 1000.0, Yperr * 1000.0, Uerr * 1000.0

    Xperr = np.where(Xperr == 0, 1.e6, Xperr)
    Yperr = np.where(Yperr == 0, 1.e6, Yperr)
    Uerr = np.where(Uerr == 0, 1.e6, Uerr)
    dXerr = np.where(perr == 0, 1.e6, dXerr)
    dYerr = np.where(dYerr == 0, 1.e6, dYperr)

    return [mjd, Xp, Xperr, Yp, Yperr, U, Uerr,
            dX, dXerr, dY, dYerr]


# ------------------------------  MAIN BODY  ---------------------------
if __name__ == '__main__':
    read_eob(sys.argv[1])
# ------------------------------ END -----------------------------------
