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
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)