Ejemplo n.º 1
0
def extrapolate_sp3_DataFrame(DFsp3,
                              step=900,
                              n_step=9,
                              backward=True,
                              forward=True,
                              until_backward=None,
                              until_forward=None,
                              return_all=True):
    """
    Extrapolate the positions in a SP3 based on the first/last
    epochs' position

    Parameters
    ----------
    DFsp3 : DataFrame
        Input Orbit DataFrame (i.e. generated by files_rw.read_sp3).
    step : int, optional
        step between two epochs. The default is 900.
    n_step : int, optional
        number of epochs to interpolate. The default is 9.
    backward and forward : bool, optional
        extrapolate for the day before/after. The default is True.
    return_all : bool, optional
        if True, returns the input DF enhanced with the extrapolated values
        if False, returns only the extrapolated values.
        The default is True.
    until_backward & until_backward : datetime, optional
        epoch until then the extrapolation has to be done.
        Override n_step
        
    Returns
    -------
    DForb_out : DataFrame
        Orbit DataFrame with extrapolated values
        (see return_all).

    """
    NewEpoch_stk = []

    for sat in DFsp3["sat"].unique():
        print("INFO:extrapolate_sp3_DataFrame: extrapolate: ", sat)
        DFsat = DFsp3[(DFsp3["sat"] == sat) & (DFsp3["type"] == "P")].copy()
        DFsat.sort_values("epoch", inplace=True)

        DFline_dummy = DFsat.iloc[0].copy()
        DFline_dummy["clk"] = 999999.999999

        XYZ = DFsat[["x", "y", "z"]].values * 1000
        Tgps = conv.numpy_dt2dt(DFsat["epoch"].values)
        Tutc = conv.dt_gpstime2dt_utc(Tgps)
        Tsec = [e.total_seconds() for e in (Tutc - Tutc[0])]

        P = conv.ECEF2ECI(XYZ, Tutc)
        V = np.gradient(P, Tsec, axis=0)

        def extrapo_intern_fct(i_ref, coef, until):
            ##
            ## backward :
            ## i_ref , coef = 0,-1
            ##
            ## forward :
            ## i_ref , coef = -1,1
            ##
            ## CORRDS ARE GIVEN IN ECI HERE !!!
            ##
            orbit_back = TwoBodyOrbit("orbit",
                                      mu=3.9860044188e14)  # create an instance
            orbit_back.setOrbCart(Tsec[i_ref], P[i_ref],
                                  V[i_ref])  # define the orbit

            if until:
                t_rang_strt, t_rang_end = list(sorted([Tutc[i_ref], until]))
                Range = conv.dt_range(t_rang_strt, t_rang_end, 0, step)
                n_step_intern = len(Range) - 1
            else:
                n_step_intern = n_step

            for t in np.arange(step, n_step_intern * step + 1, step):
                Pout, Vout = orbit_back.posvelatt(coef * t)
                epoc = Tgps[i_ref] + coef * dt.timedelta(seconds=int(t))
                DFline_new = DFline_dummy.copy()
                DFline_new[["x", "y", "z"]] = Pout
                DFline_new["epoch"] = pd.Timestamp(epoc)

                NewEpoch_stk.append(DFline_new)

            return Pout, Vout

        ### backward
        if backward:
            extrapo_intern_fct(0, -1, until_backward)

        ### forward
        if forward:
            extrapo_intern_fct(-1, 1, until_forward)

    DFNewEpoch = pd.DataFrame(NewEpoch_stk)

    Tutc_NewEpoch = conv.dt_gpstime2dt_utc(
        conv.numpy_dt2dt(DFNewEpoch["epoch"].values))
    DFNewEpoch[["x", "y",
                "z"]] = conv.ECI2ECEF(DFNewEpoch[["x", "y", "z"]].values,
                                      Tutc_NewEpoch)
    DFNewEpoch[["x", "y", "z"]] = DFNewEpoch[["x", "y", "z"]] * 10**-3

    if return_all:
        DForb_out = pd.concat((DFsp3, DFNewEpoch))
    else:
        DForb_out = DFNewEpoch

    DForb_out.reset_index(drop=True, inplace=True)
    DForb_out.sort_values(["sat", "epoch"], inplace=True)
    DForb_out.reset_index(drop=True, inplace=True)

    return DForb_out
Ejemplo n.º 2
0
def write_sp3(SP3_DF_in,
              outpath,
              outname=None,
              prefix='orb',
              skip_null_epoch=True,
              force_format_c=False):
    """
    Write a SP3 file from an Orbit DataFrame

    Parameters
    ----------
    SP3_DF_in : DataFrame
        Input Orbit DataFrame.
    outpath : str
        The output path of the file (see also outname).
    outname : None or str, optional
        None = outpath is the full path (directory + filename) of the output.
        A string = a manual name for the file.
        'auto_old_cnv' = automatically generate the filename (old convention)
        'auto_new_cnv' = automatically generate the filename (new convention)
        The default is None.
    prefix : str, optional
        the output 3-char. name of the AC. The default is 'orb'.
    skip_null_epoch : bool, optional
        Do not write an epoch if all sats are null (filtering). 
        The default is True.
    force_format_c : bool, optional
        DESCRIPTION. The default is False.

    Returns
    -------
    The string containing the formatted SP3 data.
    """

    ################## MAIN DATA
    LinesStk = []

    SP3_DF_wrk = SP3_DF_in.sort_values(["epoch", "sat"])

    EpochRawList = SP3_DF_wrk["epoch"].unique()
    SatList = sorted(SP3_DF_wrk["sat"].unique())
    SatList = list(reversed(SatList))
    SatListSet = set(SatList)
    EpochUsedList = []

    if not "clk" in SP3_DF_wrk.columns:
        SP3_DF_wrk["clk"] = 999999.999999

    for epoc in EpochRawList:
        SP3epoc = pd.DataFrame(SP3_DF_wrk[SP3_DF_wrk["epoch"] == epoc])
        ## manage missing Sats for the current epoc
        MissingSats = SatListSet.difference(set(SP3epoc["sat"]))

        for miss_sat in MissingSats:
            miss_line = SP3epoc.iloc[0].copy()
            miss_line["sat"] = miss_sat
            miss_line["const"] = miss_sat[0]
            miss_line["x"] = 0.000000
            miss_line["y"] = 0.000000
            miss_line["z"] = 0.000000
            miss_line["clk"] = 999999.999999

            SP3epoc = SP3epoc.append(miss_line)
        #### end of missing sat bloc

        SP3epoc.sort_values("sat", inplace=True, ascending=False)
        timestamp = conv.dt2sp3_timestamp(conv.numpy_dt2dt(epoc)) + "\n"

        linefmt = "P{:}{:14.6f}{:14.6f}{:14.6f}{:14.6f}\n"

        LinesStkEpoch = []
        sum_val_epoch = 0
        for ilin, lin in SP3epoc.iterrows():
            if not "clk" in lin.index:  # manage case if no clk in columns
                lin["clk"] = 999999.999999
            line_out = linefmt.format(lin["sat"], lin["x"], lin["y"], lin["z"],
                                      lin["clk"])

            sum_val_epoch += lin["x"] + lin["y"] + lin["z"]

            LinesStkEpoch.append(line_out)

        ### if skip_null_epoch activated, print only if valid epoch
        if not (np.isclose(sum_val_epoch, 0) and skip_null_epoch):
            LinesStk.append(timestamp)  # stack the timestamp
            LinesStk = LinesStk + LinesStkEpoch  # stack the values
            EpochUsedList.append(epoc)  # stack the epoc as dt

    ################## HEADER
    ######### SATELLITE LIST

    Satline_stk = []
    Sigmaline_stk = []

    if force_format_c:
        nlines = 5
    else:
        div, mod = np.divmod(len(SatList), 17)

        if div < 5:
            nlines = 5
        else:
            nlines = div

            if mod != 0:
                nlines += 1

    for i in range(nlines):
        SatLine = SatList[17 * i:17 * (i + 1)]
        SatLineSigma = len(SatLine) * " 01"

        if len(SatLine) < 17:
            complem = " 00" * (17 - len(SatLine))
        else:
            complem = ""

        if i == 0:
            nbsat4line = len(SatList)
        else:
            nbsat4line = ''

        satline = "+  {:3}   ".format(nbsat4line) + "".join(
            SatLine) + complem + "\n"
        sigmaline = "++         0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0\n"
        sigmaline = "++       " + SatLineSigma + complem + "\n"

        Satline_stk.append(satline)
        Sigmaline_stk.append(sigmaline)

    ######### 2 First LINES
    start_dt = conv.numpy_dt2dt(np.min(EpochUsedList))

    header_line1 = "#cP" + conv.dt2sp3_timestamp(
        start_dt, False) + "     {:3}".format(
            len(EpochUsedList)) + "   u+U IGSXX FIT  XXX\n"

    delta_epoch = int(utils.most_common(np.diff(EpochUsedList) * 10**-9))
    MJD = conv.dt2MJD(start_dt)
    MJD_int = int(np.floor(MJD))
    MJD_dec = MJD - MJD_int
    gps_wwww, gps_sec = conv.dt2gpstime(start_dt, False, "gps")

    header_line2 = "## {:4} {:15.8f} {:14.8f} {:5} {:15.13f}\n".format(
        gps_wwww, gps_sec, delta_epoch, MJD_int, MJD_dec)

    ######### HEADER BOTTOM
    header_bottom = """%c M  cc GPS ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc
%c cc cc ccc ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc
%f  1.2500000  1.025000000  0.00000000000  0.000000000000000
%f  0.0000000  0.000000000  0.00000000000  0.000000000000000
%i    0    0    0    0      0      0      0      0         0
%i    0    0    0    0      0      0      0      0         0
/* PCV:IGSXX_XXXX OL/AL:FESXXXX  NONE     YN CLK:CoN ORB:CoN
/*     GeodeZYX Toolbox Output
/*
/*
"""

    ################## FINAL STACK

    FinalLinesStk = []

    FinalLinesStk.append(header_line1)
    FinalLinesStk.append(header_line2)
    FinalLinesStk = FinalLinesStk + Satline_stk + Sigmaline_stk
    FinalLinesStk.append(header_bottom)
    FinalLinesStk = FinalLinesStk + LinesStk + ["EOF"]

    FinalStr = "".join(FinalLinesStk)

    ### Manage the file path
    prefix_opera = prefix

    if not outname:
        outpath_opera = outpath
    elif outname == 'auto_old_cnv':
        week, dow = conv.dt2gpstime(start_dt)
        filename = prefix_opera + str(week) + str(dow) + '.sp3'
        outpath_opera = os.path.join(outpath, filename)

    elif outname == 'auto_new_cnv':
        print("ERR: not implemented yet !!!!!")
        raise Exception

    F = open(outpath_opera, "w+")
    F.write(FinalStr)