Пример #1
0
def get_sp3_final_target(**kwargs):
    """ Final Orbit information in SP3 format from COD

      CODwwwwd.EPH.Z    CODE final GNSS orbits
      COXwwwwd.EPH.Z    CODE final GLONASS orbits (for GPS weeks
                        0990 to 1066)

      kwargs that matter:
      format='sp3' Optional but if given it must be sp3
      type='final' Optional but if given must be 'final'
      acid='cod' to get the GNSS solution, 'cox' to get GLONASS only solution.
        The latter (cox) are only available within the interval for GPS weeks
        0990 to 1066
      To provide a date, use either:
        * pydt=datetime.datetime(...) or 
        * year=... and doy=...

      Default values:
      kwargs['format'] = sp3
      kwargs['acid'] = cod
      kwargs['type'] = final

  """
    if 'format' in kwargs and kwargs['format'] not in ['sp3']:
        raise ArgumentError('[ERROR] code::get_sp3_final Invalid format',
                            'format', **kwargs)
    if 'acid' in kwargs and kwargs['acid'] not in ['cod', 'cox']:
        raise ArgumentError('[ERROR] code::get_sp3_final Invalid acid', 'acid',
                            **kwargs)
    if 'type' in kwargs and kwargs['type'] != 'final':
        raise ArgumentError('[ERROR] code::get_sp3_final Invalid type', 'type',
                            **kwargs)

    if 'format' not in kwargs:
        kwargs['format'] = 'sp3'
    if 'type' not in kwargs:
        kwargs['type'] = 'final'
    if 'acid' not in kwargs:
        kwargs['acid'] = 'cod'

    pydt = _date(**kwargs)  ## this may throw
    week, sow = pydt2gps(pydt)
    acn = 'COD' if kwargs['acid'] == 'cod' else 'COX'
    sdate = '{:04d}{:01d}'.format(week, sow2dow(sow))
    frmt = 'EPH'
    url_dir = '{:}'.format(pydt.strftime('%Y'))

    eph = '{:}{:}.{:}.Z'.format(acn, sdate, frmt)
    target = '{:}/CODE/{:}/{:}'.format(CODE_URL, url_dir, eph)
    return target
Пример #2
0
def get_euref_exclusion_list(dt):
    URL = 'ftp://epncb.oma.be/pub/station/general/excluded/exclude.'
    week, dow = pydt2gps(dt)
    target = '{:}{:}'.format(URL, week)
    try:
        status, target, saveas = web_retrieve(target)
    except:
        print('[DEBUG] Failed to download EUREF\'s exclusion list file',
              file=sys.stderr)
        return []

    exclusion_list = []
    with open(saveas, 'r') as fin:
        for line in fin.readlines():
            exclusion_list.append(line.split()[0])

    os.remove(saveas)

    return exclusion_list
Пример #3
0
def get_erp_final_target(**kwargs):
    """ Final Earth Rotation Parameters (ERP) files in from COD

      kwargs that matter:
      span='daily' for daily ERP's or 'weekly' for weekly ERP file
      code_dir='code' to download files from CODE_URL/CODE/yyyy or 'bswuser52' 
                to download from CODE_URL/BSWUSER52/ORB/yyyy
      acid='cod' Optional but if given must be cod
      type='final' Optional but if given must be 'final'
      format='bernese' Optional but if given must be 'bernese'
      To provide a date, use either:
        * pydt=datetime.datetime(...) or 
        * year=... and doy=...

      Default values:
      kwargs['span'] = daily

      CODwwww7.ERP.Z    Weekly CODE final ERP files as from week 0978 (*)
      CODyyddd.ERP.Z    Daily CODE final ERP files as from week 1706 (*)
      CODwwwwd.ERP.Z    CODE final ERPs belonging to the final orbits (+)
      CODwwww7.ERP.Z    Collection of the 7 daily COD-ERP solutions of the 
                        week (+)

      type=final
                        |span=daily                          | span=weekly                        |
      ------------------+------------------------------------+------------------------------------+
      code_dir=code     | /CODE/yyyy/CODwwwwd.ERP.Z          | /CODE/yyyy/CODwwww7.ERP.Z          |
      code_dir=bswuser52| /BSWUSER52/ORB/yyyy/CODyyddd.ERP.Z | /BSWUSER52/ORB/yyyy/CODwwww7.ERP.Z |


      (*) under /BSWUSER52/ORB/yyyy
      (+) under /CODE/yyyy

      I cannot find any difference between CODwwww7.ERP.Z Vs CODwwww7.ERP.Z,
      and CODyyddd.ERP.Z Vs CODwwwwd.ERP.Z. Hence, we add an optional argument
      'code_dir' which can take the values 'bswuser52' and 'code' and decides 
      which of the two options will be used (aka the remote ftp directory). By 
      default, the value defaults to code_dir=code

  """
    if 'format' in kwargs and kwargs['format'] not in ['bernese']:
        raise ArgumentError('[ERROR] code::get_erp_final Invalid format',
                            'format', **kwargs)
    if 'acid' in kwargs and kwargs['acid'] not in ['cod']:
        raise ArgumentError('[ERROR] code::get_erp_final Invalid acid', 'acid',
                            **kwargs)
    if 'type' in kwargs and kwargs['type'] != 'final':
        raise ArgumentError('[ERROR] code::get_erp_final Invalid type', 'type',
                            **kwargs)
    if 'span' in kwargs and kwargs['span'] not in ['daily', 'weekly']:
        raise ArgumentError('[ERROR] code::get_erp_final Invalid span', 'span',
                            **kwargs)
    if 'code_dir' in kwargs and kwargs['code_dir'] not in [
            'bswuser52', 'code'
    ]:
        raise ArgumentError('[ERROR] code::get_erp_final Invalid code_dir',
                            'code_dir', **kwargs)

    if 'span' not in kwargs:
        kwargs['span'] = 'daily'
    if 'code_dir' not in kwargs:
        kwargs['code_dir'] = 'code'

    pydt = _date(**kwargs)  ## this may throw
    yy, ddd = pydt2yydoy(pydt)
    week, sow = pydt2gps(pydt)

    if kwargs['code_dir'] == 'code':
        url_dir = '{:}/{:}'.format('CODE', pydt.strftime('%Y'))
    else:
        url_dir = '{:}/{:}/{:}'.format('BSWUSER52', 'ORB', pydt.strftime('%Y'))

    acn = 'COD'
    frmt = 'ERP'
    if kwargs['span'] == 'weekly':
        sdate = '{:04d}{:1d}'.format(week, 7)
    else:
        if kwargs['code_dir'] == 'code':
            sdate = '{:04d}{:01d}'.format(week, sow2dow(sow))
        else:
            sdate = '{:02d}{:03d}'.format(yy, ddd)

    erp = '{:}{:}.{:}.Z'.format(acn, sdate, frmt)
    target = '{:}/{:}/{:}'.format(CODE_URL, url_dir, erp)
    return target
Пример #4
0
def get_erp_rapid_target(**kwargs):
    """ Rapid , Ultra-Rapid and Predicted Final Earth Rotation Parameters (ERP) 
      files in from COD
        
      kwargs that matter:
      acid='cod' Optional but if given must be cod
      format='bernese' Optional but if given must be 'bernese'
      span='daily' Optional but if given must be 'daily'
      type=[...] If not given, default value is 'frapid'
      To provide a date, use either:
        * pydt=datetime.datetime(...) or 
        * year=... and doy=...
      A datetime is only optional if type=='current'

      CODwwwwd.ERP_M.Z  CODE final rapid ERPs belonging to the final rapid 
                          orbits (-)
      COD.ERP_U         CODE ultra-rapid ERPs belonging to the ultra-rapid 
                          orbit product
      CODwwwwd.ERP_U    CODE ultra-rapid ERPs belonging to the ultra-rapid 
                          orbits
      CODwwwwd.ERP_M    CODE final rapid ERPs belonging to the final rapid 
                          orbits
      CODwwwwd.ERP_R    CODE early rapid ERPs belonging to the early rapid 
                          orbits
      CODwwwwd.ERP_P    CODE predicted ERPs belonging to the predicted
                          24-hour orbits
      CODwwwwd.ERP_P2   CODE predicted ERPs belonging to the predicted
                          48-hour orbits
      CODwwwwd.ERP_5D   CODE predicted ERPs belonging to the predicted
                          5-day orbits

      (-) under /CODE/yyyy_M

      type=current               | COD.ERP_U
      type=urapid or ultra-rapid | CODwwwwd.ERP_U
      type=frapid or final-rapid | CODwwwwd.ERP_M [or CODwwwwd.ERP_M.Z]
      type=erapid or early-rapid | CODwwwwd.ERP_R
      type=prediction            | CODwwwwd.ERP_P
      type=p2                    | CODwwwwd.ERP_P2
      type=p5                    | CODwwwwd.ERP_5D

      files in brackets not available!
  """
    if 'format' in kwargs and kwargs['format'] not in ['bernese']:
        raise ArgumentError('[ERROR] code::get_erp_rapid Invalid format',
                            'format', **kwargs)
    if 'span' in kwargs and kwargs['span'] not in ['daily']:
        raise ArgumentError('[ERROR] code::get_erp_rapid Invalid span', 'span',
                            **kwargs)
    if 'acid' in kwargs and kwargs['acid'] not in ['cod']:
        raise ArgumentError('[ERROR] code::get_erp_rapid Invalid acid', 'acid',
                            **kwargs)
    if 'type' in kwargs and kwargs['type'] not in [
            'urapid', 'ultra-rapid', 'frapid', 'final-rapid', 'erapid',
            'early-rapid', 'prediction', 'p2', 'p5', 'current'
    ]:
        raise ArgumentError('[ERROR] code::get_erp_rapid Invalid type', 'type',
                            **kwargs)

    if 'type' not in kwargs:
        kwargs['type'] = 'frapid'

    if kwargs['type'] != 'frapid':
        pydt = _date(**kwargs)  ## this may throw
        week, sow = pydt2gps(pydt)
        sdate = '{:04d}{:01d}'.format(week, sow2dow(sow))
    acn = 'COD'
    url_dir = 'CODE'

    if kwargs['type'] in ['urapid', 'ultra-rapid']:
        frmt = 'ERP_U'
    elif kwargs['type'] in ['frapid', 'final-rapid']:
        frmt = 'ERP_M'
    elif kwargs['type'] in ['erapid', 'early-rapid']:
        frmt = 'ERP_R'
    elif kwargs['type'] in ['prediction']:
        frmt = 'ERP_P'
    elif kwargs['type'] in ['p2']:
        frmt = 'ERP_P2'
    elif kwargs['type'] in ['p5']:
        frmt = 'ERP_5D'
    elif kwargs['type'] in ['current']:
        sdate = ''
        frmt = 'ERP_U'

    erp = '{:}{:}.{:}'.format(acn, sdate, frmt)
    target = '{:}/{:}/{:}'.format(CODE_URL, url_dir, erp)
    return target
Пример #5
0
def get_trp_rapid_target(**kwargs):
    """ Rapid or Ultra-rapid tropospheric information in SINEX or Bernese format 
      from COD
  
        COD.TRO_U         CODE ultra-rapid troposphere product in SINEX
                          format
        COD_TRO.SNX_U.Z   CODE ultra-rapid solution, as above but with 
                          troposphere parameters for selected sites, SINEX 
                          format
        CODwwwwd.TRO_R    CODE troposphere product from the early rapid
                          solution, SINEX format
        ________Unused________________________________________________________
        COD_TRO.SNX_U.Z   CODE ultra-rapid solution, as above but with 
                          troposphere parameters for selected sites, SINEX 
                          format
        CODwwwwd_TRO.SNX_R.Z  CODE early rapid solution, as above but with 
                          troposphere parameters for selected sites, SINEX 
                          format

      Default Values
      kwargs['format'] = 'sinex'
      kwargs['type'] = 'rapid'
      To provide a date, use either:
        * pydt=datetime.datetime(...) or 
        * year=... and doy=...

      aka:
      kwargs           |format=sinex        | format=bernese      |
      -----------------+--------------------+---------------------+
      type=rapid       | CODwwwwd.TRO_R     |                     |
      type=urapid      | COD.TRO_U          |                     |
      type=urapid-sites| COD_TRO.SNX_U.Z    |                     |

  """
    if 'format' in kwargs and kwargs['format'] not in ['sinex', 'tro']:
        raise ArgumentError('[ERROR] code::get_trp_rapid Invalid format',
                            'format', **kwargs)
    if 'type' in kwargs and kwargs['type'] not in [
            'rapid', 'urapid', 'urapid-sites'
    ]:
        raise ArgumentError('[ERROR] code::get_trp_rapid Invalid type', 'type',
                            **kwargs)

    if 'format' not in kwargs:
        kwargs['format'] = 'sinex'
    if 'type' not in kwargs:
        kwargs['type'] = 'rapid'

    if kwargs['type'] == 'rapid':
        yy, ddd = _pydt2yydoy(pydt)

    if kwargs['format'] in ['sinex', 'tro']:
        acn = 'COD'
        if kwargs['type'] == 'rapid':
            week, sow = pydt2gps(pydt)
            sdate = '{:04d}{:1d}'.format(week, sow2dow(sow))
            frmt = 'TRO_R'
        elif kwargs['type'] == 'urapid':
            sdate = ''
            frmt = 'TRO_U'
        elif kwargs['type'] == 'urapid-sites':
            sdate = '_TRO'
            frmt = 'SNX_U.Z'
        else:
            raise RuntimeError(
                '[ERROR] code::get_trp_rapid invalid request (#1)')
    else:
        raise RuntimeError('[ERROR] code::get_ion_rapid invalid request (#2)')

    tro = '{:}{:}.{:}'.format(acn, sdate, frmt)
    target = '{:}/CODE/{:}'.format(CODE_URL, tro)
    return target
Пример #6
0
def get_trp_final_target(**kwargs):
    """ Final tropospheric information in SINEX or Bernese format from COD

      CODwwwwd.TRO.Z  CODE final troposphere product, SINEX format
      CODyyddd.TRP.Z  Troposphere path delays of final solution
      COEyyddd.TRP.Z  Troposphere path delays of EUREF solution

      kwargs that matter:
      format='sinex' or format='tro' to get the Tropospheric SINEX format.
      format='trp' or format='bernese' to get the Bernese format.
      acid='coe' to get the EUREF solution.
      type='final' Optional but if given must be 'final'
      To provide a date, use either:
        * pydt=datetime.datetime(...) or 
        * year=... and doy=...

      Default values:
      kwargs['format'] = bernese
      kwargs['acid'] = cod

      kwargs  | format=bernese                   | format=sinex
      --------+----------------------------------+----------------------------
      acid=coe|BSWUSER52/ATM/yyyy/COEyyddd.TRP.Z |
      acid=cod|BSWUSER52/ATM/yyyy/CODyyddd.TRP.Z |CODE/yyyy/CODwwwwd.TRO.Z
  """
    if 'format' in kwargs and kwargs['format'] not in [
            'sinex', 'tro', 'trp', 'bernese'
    ]:
        raise ArgumentError('[ERROR] code::get_trp_final Invalid format',
                            'format', **kwargs)
    if 'acid' in kwargs and kwargs['acid'] not in ['cod', 'coe']:
        raise ArgumentError('[ERROR] code::get_trp_final Invalid acid', 'acid',
                            **kwargs)
    if 'type' in kwargs and kwargs['type'] != 'final':
        raise ArgumentError('[ERROR] code::get_trp_final Invalid type', 'type',
                            **kwargs)

    if 'format' not in kwargs:
        kwargs['format'] = 'bernese'
    if 'acid' not in kwargs:
        kwargs['acid'] = 'cod'

    frmt = 'TRP' if kwargs['format'] in ['bernese', 'trp'] else 'TRO'

    pydt = _date(**kwargs)  ## this may throw
    yy, ddd = _pydt2yydoy(pydt)
    if kwargs['acid'] == 'coe':
        if kwargs['format'] in ['sinex', 'tro']:
            msg = '[ERROR] code::get_trp_final No product in SINEX format for EUREF solution'
            raise RuntimeError(msg)
        url_dir = 'BSWUSER52/ATM/{:}'.format(pydt.strftime("%Y"))
        acn = 'COE'
        sdate = '{:02d}{:03d}'.format(yy, ddd)
    else:
        acn = 'COD'
        if kwargs['format'] in ['bernese', 'ion']:
            url_dir = 'BSWUSER52/ATM/{:}'.format(pydt.strftime("%Y"))
            sdate = '{:02d}{:03d}'.format(yy, ddd)
        else:
            url_dir = 'CODE/{:}'.format(pydt.strftime("%Y"))
            week, sow = pydt2gps(pydt)
            sdate = '{:04d}{:1d}'.format(week, sow2dow(sow))

    tro = '{:}{:}.{:}.Z'.format(acn, sdate, frmt)
    target = '{:}/{:}/{:}'.format(CODE_URL, url_dir, tro)
    return target
Пример #7
0
def get_ion_rapid_target(**kwargs):
    """ Rapid or Ultra-rapid ionosphere information in IONEX or Bernese format 
      from COD

      CORGddd0.yyI.Z    CODE rapid ionosphere product, IONEX format
      COPGddd0.yyI.Z    CODE 1-day or 2-day ionosphere predictions,
                        in IONEX format
      CODwwwwd.ION_R    CODE rapid ionosphere product, Bernese format
      CODwwwwd.ION_P    CODE 1-day ionosphere predictions, Bernese format
      CODwwwwd.ION_P2   CODE 2-day ionosphere predictions, Bernese format
      CODwwwwd.ION_P5   CODE 5-day ionosphere predictions, Bernese format
      COD.ION_U         Last update of CODE rapid ionosphere product
                        (1 day) complemented with ionosphere predictions 
                        (2 days)

      kwargs that matter:
      format='ionex' or format='inx' to get the IONEX format.
      format='ion' or format='bernese' to get the Bernese format.
      acid='coe' to get the EUREF solution.
      To provide a date, use either:
        * pydt=datetime.datetime(...) or 
        * year=... and doy=...
  
      Default Values
      kwargs['format'] = 'bernese'
      kwargs['type'] = 'rapid'

      aka:
      kwargs         |format=ionex        | format=bernese      |
      ---------------+--------------------+---------------------+
      type=rapid     |CODE/CORGddd0.yyI.Z | CODE/CODwwwwd.ION_R |
      type=prediction|CODE/COPGddd0.yyI.Z | CODE/CODwwwwd.ION_P |
      type=current or|                    | CODE/COD.ION_U      |
      urapid or      |                    |
      ultra-rapid    |                    |
      type=p2        |                    | CODE/CODwwwwd.ION_P2|
      type=p5        |                    | CODE/CODwwwwd.ION_P5|

      TODO current should be an alias for urapid or ultra-rapid
  """
    if 'format' in kwargs and kwargs['format'] not in [
            'ionex', 'inx', 'ion', 'bernese'
    ]:
        raise ArgumentError('[ERROR] code::get_ion_rapid Invalid format',
                            'format', **kwargs)
    if 'type' in kwargs and kwargs['type'] not in [
            'rapid', 'prediction', 'current', 'p2', 'p5', 'urapid',
            'ultra-rapid'
    ]:
        raise ArgumentError('[ERROR] code::get_ion_rapid Invalid type', 'type',
                            **kwargs)

    if 'format' not in kwargs:
        kwargs['format'] = 'bernese'
    if 'type' in kwargs and kwargs['type'] in ['urapid', 'ultra-rapid']:
        kwargs['type'] = 'current'
    if 'type' not in kwargs:
        kwargs['type'] = 'rapid'

    if kwargs['type'] != 'current':
        pydt = _date(**kwargs)  ## this may throw
        yy, ddd = pydt2yydoy(pydt)

    if kwargs['format'] in ['ionex', 'inx']:
        sdate = '{:03d}0'.format(ddd)
        frmt = '{:}I.Z'.format(pydt.strftime("%y"))
        if 'type' in kwargs and kwargs['type'] == 'rapid':
            acn = 'CORG'
        elif 'type' in kwargs and kwargs['type'] == 'prediction':
            acn = 'COPG'
        else:
            raise RuntimeError(
                '[ERROR] code::get_ion_rapid invalid request (#1)')

    if kwargs['format'] in ['bernese', 'ion']:
        acn = 'COD'
        if kwargs['type'] == 'current':
            frmt = 'ION_U'
            sdate = ''
        else:
            week, sow = pydt2gps(pydt)
            sdate = '{:04d}{:1d}'.format(week, sow2dow(sow))
            if kwargs['type'] == 'rapid':
                frmt = 'ION_R'
            elif kwargs['type'] == 'prediction':
                frmt = 'ION_P'
            elif kwargs['type'] == 'p2':
                frmt = 'ION_P2'
            elif kwargs['type'] == 'p5':
                frmt = 'ION_P5'
            else:
                raise RuntimeError(
                    '[ERROR] code::get_ion_rapid invalid request (#2)')

    ion = '{:}{:}.{:}'.format(acn, sdate, frmt)
    target = '{:}/CODE/{:}'.format(CODE_URL, ion)
    return target
Пример #8
0
def get_ion_final_target(**kwargs):
    """ Final ionosphere information in IONEX or Bernese format from COD

      kwargs that matter:
      format='ionex' or format='inx' to get the IONEX format.
      format='ion' or format='bernese' to get the Bernese format.
      acid='coe' to get the EUREF solution.
      type='final' Optional but if given must be 'final'
      To provide a date, use either:
        * pydt=datetime.datetime(...) or 
        * year=... and doy=...

      Default values:
      kwargs['format'] = bernese
      kwargs['acid'] = cod

      kwargs  |format=ionex                 | format=bernese               |
      --------+-----------------------------+------------------------------+
      acid=coe|BSWUSER52/ATM/yyyy/COEyyddd.INX.Z| BSWUSER52/ATM/yyyy/COEyyddd.ION.Z|
      acid=cod|CODE/yyyy/CODGddd0.yyI.Z     | CODE/yyyy/CODwwwwd.ION.Z     |
  """
    if 'format' in kwargs and kwargs['format'] not in [
            'ionex', 'inx', 'ion', 'bernese'
    ]:
        raise ArgumentError('[ERROR] code::get_ion_final Invalid format',
                            'format', **kwargs)
    if 'acid' in kwargs and kwargs['acid'] not in ['cod', 'coe']:
        raise ArgumentError('[ERROR] code::get_ion_final Invalid acid', 'acid',
                            **kwargs)
    if 'type' in kwargs and kwargs['type'] != 'final':
        raise ArgumentError('[ERROR] code::get_ion_final Invalid type', 'type',
                            **kwargs)

    if 'format' not in kwargs:
        kwargs['format'] = 'bernese'
    if 'acid' not in kwargs:
        kwargs['acid'] = 'cod'

    pydt = _date(**kwargs)  ## this may throw
    yy, ddd = pydt2yydoy(pydt)
    if kwargs['format'] in ['bernese', 'ion']:
        frmt = 'ION'
    else:
        if kwargs['acid'] == 'coe':
            frmt = 'INX'
        else:
            frmt = '{:02d}I'.format(yy)

    if kwargs['acid'] == 'coe':
        url_dir = 'BSWUSER52/ATM/{:}'.format(pydt.strftime("%Y"))
        acn = 'COE'
        sdate = '{:02d}{:03d}'.format(yy, ddd)
    else:
        url_dir = 'CODE/{:}'.format(pydt.strftime("%Y"))
        if kwargs['format'] in ['bernese', 'ion']:
            acn = 'COD'
            week, sow = pydt2gps(pydt)
            sdate = '{:04d}{:01d}'.format(week, sow2dow(sow))
        else:
            acn = 'CODG'
            sdate = '{:03d}0'.format(ddd)

    ion = '{:}{:}.{:}.Z'.format(acn, sdate, frmt)
    target = '{:}/{:}/{:}'.format(CODE_URL, url_dir, ion)
    return target
Пример #9
0
def get_sp3_rapid_target(**kwargs):
    """ Rapid or Ultra-rapid orbit information in SP3 format from COD

      kwargs that matter:
      format='sp3' Optional but if given it must be sp3
      type='frapid' Cn be any of current, current-5d, .... (see Table below)
      acid='cod' Optional but if given it must be 'cod'
      To provide a date, use either:
        * pydt=datetime.datetime(...) or 
        * year=... and doy=...

      Default values:
      kwargs['format'] = sp3
      kwargs['acid'] = cod
      kwargs['type'] = frapid

      COD.EPH_U         CODE ultra-rapid GNSS orbits
      COD.EPH_5D        Last update of CODE 5-day orbit predictions, from
                        rapid analysis, including all active GLONASS and
                        Galileo satellites
      CODwwwwd.EPH_U    CODE ultra-rapid GNSS orbits from the 24UT solution
                        available until the corresponding early rapid orbit
                        is available (to ensure a complete coverage of orbits
                        even if the early rapid solution is delayed after the
                        first ultra-rapid solutions of the day)
      CODwwwwd.EPH_M    CODE final rapid GNSS orbits
                        (middle day of a long-arc solution where the rapid
                        observations were completed by a subsequent
                        ultra-rapid dataset)
      CODwwwwd.EPH_R    CODE early rapid GNSS orbits
                        (third day of a 72-hour solution)
      CODwwwwd.EPH_P    CODE 24-hour GNSS orbit predictions
      CODwwwwd.EPH_P2   CODE 48-hour GNSS orbit predictions
      CODwwwwd.EPH_5D   CODE 5-day GNSS orbit predictions
      
      type=current               | COD.EPH_U
      type=current-5d            | COD.EPH_5D
      type=urapid or ultra-rapid | CODwwwwd.EPH_U
      type=frapid or final-rapid | CODwwwwd.EPH_M
      type=erapid or early-rapid | CODwwwwd.EPH_R
      type=prediction            | CODwwwwd.EPH_P
      type=p2                    | CODwwwwd.EPH_P2
      type=p5                    | CODwwwwd.EPH_5D
    """
    if 'format' in kwargs and kwargs['format'] not in ['sp3']:
        raise RuntimeError('[ERROR] code::get_sp3_rapid Invalid format.')
    if 'acid' in kwargs and kwargs['acid'] not in ['cod']:
        raise RuntimeError('[ERROR] code::get_sp3_rapid Invalid acid.')
    if 'type' in kwargs and kwargs['type'] not in [
            'current', 'current-5d', 'urapid', 'ultra-rapid', 'frapid',
            'final-rapid', 'erapid', 'early-rapid', 'prediction', 'p2', 'p5'
    ]:
        raise RuntimeError('[ERROR] code::get_sp3_rapid Invalid type.')

    if 'format' not in kwargs:
        kwargs['format'] = 'sp3'
    if 'type' not in kwargs:
        kwargs['type'] = 'frapid'
    if 'acid' not in kwargs:
        kwargs['acid'] = 'cod'

    acn = 'COD'
    url_dir = 'CODE'
    if kwargs['type'] not in ['current', 'current-5d']:
        pydt = _date(**kwargs)  ## this may throw
        week, sow = pydt2gps(pydt)
        sdate = '{:04d}{:01d}'.format(week, sow2dow(sow))

    if kwargs['type'] == 'current':
        sdate = ''
        frmt = 'EPH_U'
    elif kwargs['type'] == 'current-5d':
        sdate = ''
        frmt = 'EPH_5D'
    elif kwargs['type'] in ['urapid', 'ultra-rapid']:
        frmt = 'EPH_U'
    elif kwargs['type'] in ['frapid', 'final-rapid']:
        frmt = 'EPH_M'
    elif kwargs['type'] in ['erapid', 'early-rapid']:
        frmt = 'EPH_R'
    elif kwargs['type'] == 'prediction':
        frmt = 'EPH_P'
    elif kwargs['type'] == 'p2':
        frmt = 'EPH_P2'
    elif kwargs['type'] == 'p5':
        frmt = 'EPH_5D'
    else:
        raise RuntimeError('[ERROR] code::get_sp3_rapid Invalid type.')

    eph = '{:}{:}.{:}'.format(acn, sdate, frmt)
    target = '{:}/{:}/{:}'.format(CODE_URL, url_dir, eph)
    return target