Beispiel #1
0
def calculate_initial_values(eph, rundate):
    """Computing initial values for position and velocity in GCRS system

    This is for later use in orbit integration, from tables in the prediction files.  Use a lagrange polynomial in
    order to interpolate in the tables.

    Args:
        eph:  Dict containing ephemeris information

    Returns:
        eph:  Dict where the initial position and velocity is added
    """
    pos_gcrs = np.empty((3, 0))
    times = np.empty((0))
    table_of_positions = sorted(eph["positions"].items())
    mjd1, mjd2 = zip(*[t for t, d in table_of_positions])

    for pos_time, (_, data) in zip(time.Time(val=mjd1, val2=mjd2, fmt="mjd", scale="utc"), table_of_positions):
        diffsec = (pos_time.utc.datetime - rundate).total_seconds()
        # Only look at points close to rundate (start of integration)
        # if abs(diffsec) > 4000:
        #    continue
        # Table given in ITRF coordinate system. Convert to GCRS, where the integration of the satellite orbit will
        # be done

        pos_gcrs = np.hstack((pos_gcrs, np.transpose([rotation.trs2gcrs(pos_time) @ data["pos"]])))
        times = np.hstack((times, diffsec))

    log.info("Interpolating data from prediction file in order to get initial pos/vel")
    pos_gcrs_ip, vel_gcrs_ip = interpolation.interpolate_with_derivative(
        times, np.transpose(pos_gcrs), np.array([0.0]), kind="lagrange", window=10, bounds_error=False
    )
    eph["initial_pos"] = pos_gcrs_ip[0]
    eph["initial_vel"] = vel_gcrs_ip[0]
    return eph
Beispiel #2
0
def site_pos(dset):
    """Calculate the partial derivative of the site position for each station

    Args:
        data:     A Dataset containing model data.

    Returns:
        Tuple: Array of partial derivatives, list of their names, and their unit
    """
    # Remove stations that should be fixed
    stations = np.asarray(dset.unique("station"))
    fix_stations = config.tech[PARAMETER].fix_stations.list
    fix_idx = np.in1d(stations, fix_stations)
    if fix_idx.any():
        stations = stations[np.logical_not(fix_idx)]

    # Calculate partials
    all_partials = -dset.src_dir.unit_vector[:, None, :] @ rotation.trs2gcrs(dset.time)
    partials = np.zeros((dset.num_obs, len(stations) * 3))
    for idx, station in enumerate(stations):
        filter_1 = dset.filter(station_1=station)
        partials[filter_1, idx * 3 : idx * 3 + 3] = all_partials[filter_1][:, 0] * -1
        filter_2 = dset.filter(station_2=station)
        partials[filter_2, idx * 3 : idx * 3 + 3] = all_partials[filter_2][:, 0]

    column_names = [s + "_" + xyz for s in stations for xyz in "xyz"]

    return partials, column_names, "dimensionless"
Beispiel #3
0
def t2g_pos(trs: "TrsPosition", time: "Time" = None) -> "GcrsPosition":
    """Transforms input array from trs to gcrs coordinates"""
    if time is None:
        time = trs.time
        if time is None:
            raise mg_exceptions.InitializationError("Time is not defined")
    trs = np.asarray(trs)[:, :, None]
    return (rotation.trs2gcrs(time) @ trs)[:, :, 0]
Beispiel #4
0
def t2g_posvel(trs: "TrsPosVel", time: "Time" = None) -> "GcrsPosVel":
    """Transforms input array from trs to gcrs coordinates"""
    if time is None:
        time = trs.time
        if time is None:
            raise mg_exceptions.InitializationError("Time is not defined")
    trs = nputil.col(trs)
    t2g = rotation.trs2gcrs(time)
    dt2g = rotation.dtrs2gcrs_dt(time)

    transformation = np.block([[t2g, np.zeros(t2g.shape)], [dt2g, t2g]])
    return _matmul(transformation, trs)
Beispiel #5
0
def t2g_posvel(trs: "TrsPosVel", time: "Time" = None) -> "GcrsPosVel":
    """Transforms input array from trs to gcrs coordinates"""
    if time is None:
        time = trs.time
        if time is None:
            raise mg_exceptions.InitializationError("Time is not defined")
    trs = np.asarray(trs)[:, :, None]
    t2g = rotation.trs2gcrs(time)
    dt2g = rotation.dtrs2gcrs_dt(time)

    # Form block diagonal matrix with shape (num_obs, 6, 6)
    transformation = np.block([[t2g, np.zeros(t2g.shape)],
                               [np.zeros(dt2g.shape), dt2g]])
    return (transformation @ trs)[:, :, 0]
Beispiel #6
0
def site_pos(dset):
    """Calculate the partial derivative of the site position for each station

    Args:
        data:     A Dataset containing model data.

    Returns:
        Tuple:    Array of partial derivatives, list of their names, and their unit
    """
    # Remove stations that should be fixed
    stations = np.asarray(dset.unique("station"))
    fix_stations = config.tech[PARAMETER].fix_stations.list
    if fix_stations:
        log.info(f"Not estimating stations {fix_stations}")

    # Remove stations with less than 10 observations
    stations_few_obs = []
    for station in stations:
        number_of_observations = np.sum(dset.filter(station=station))
        if number_of_observations < 10:
            stations_few_obs.append(station)

    fix_stations += stations_few_obs
    if stations_few_obs:
        log.info(
            f"Not estimating stations {stations_few_obs}, less than 10 observations"
        )

    fix_idx = np.in1d(stations, fix_stations)
    if fix_idx.any():
        stations = stations[np.logical_not(fix_idx)]

    reflect_time = dset.time + TimeDelta(
        dset.time_bias + dset.up_leg, fmt="seconds", scale="utc")
    i2g = rotation.trs2gcrs(reflect_time)
    site_pos_reflect_time = (i2g @ dset.site_pos.val[:, :, None])[:, :, 0]

    unit_vector = dset.sat_pos.pos.val[:] - site_pos_reflect_time[:]
    unit_vector = unit_vector / np.linalg.norm(unit_vector)
    # Calculate partials
    all_partials = -unit_vector[:, None, :] @ i2g
    partials = np.zeros((dset.num_obs, len(stations) * 3))
    for idx, station in enumerate(stations):
        filter_1 = dset.filter(station=station)
        partials[filter_1, idx * 3:idx * 3 + 3] = all_partials[filter_1][:, 0]

    column_names = [s + "_" + xyz for s in stations for xyz in "xyz"]

    return partials, column_names, "dimensionless"
Beispiel #7
0
def calculate_initial_values(eph, rundate):
    """Computing initial values for position and velocity in GCRS system

    This is for later use in orbit integration, from tables in the prediction files.  Use a lagrange polynomial in
    order to interpolate in the tables.

    Args:
        eph:  Dict containing ephemeris information

    Returns:
        eph:  Dict where the initial position and velocity is added
    """
    data = sorted(eph["positions"].items())
    pos_itrs = np.zeros((len(data), 3))
    mjd1, mjd2 = zip(*[t for t, d in data])
    rotation_mat = rotation.trs2gcrs(
        time.Time(val=mjd1, val2=mjd2, fmt="mjd", scale="utc"))
    tbl = time.Time(val=mjd1, val2=mjd2, fmt="mjd", scale="utc")

    for i in range(0, len(data)):
        pos_itrs[i] = data[i][1]["pos"]

    diffsec = np.array([(t - rundate).total_seconds()
                        for t in tbl.utc.datetime])

    # Table given in ITRF coordinate system. Convert to GCRS, where the integration of the satellite orbit will
    # be done

    pos_gcrs = np.sum(rotation_mat @ pos_itrs[:, :, None], axis=2)
    log.info(
        "Interpolating data from prediction file in order to get initial pos/vel"
    )
    pos_gcrs_ip, vel_gcrs_ip = interpolation.interpolate_with_derivative(
        diffsec,
        pos_gcrs,
        np.array([0.0]),
        kind="lagrange",
        window=10,
        bounds_error=False)
    eph["initial_pos"] = pos_gcrs_ip[0]
    eph["initial_vel"] = vel_gcrs_ip[0]

    return eph
Beispiel #8
0
def calculate(stage, dset):
    """
    Integrate differential equation of motion of the satellite

    Args:
        stage:  Name of current stage
        dset:   Dataset containing the data
    """

    iterations = config.tech.iterations.int

    # Run models adjusting station positions
    site.calculate_site("site", dset)
    delta_pos = site.add("site", dset)
    dset.site_pos[:] = (dset.site_pos.gcrs + delta_pos[0].gcrs).trs

    dset.add_float("obs",
                   val=dset.time_of_flight * constant.c / 2,
                   unit="meter")
    dset.add_float("calc", np.zeros(dset.num_obs), unit="meter")
    dset.add_float("residual", np.zeros(dset.num_obs), unit="meter")
    dset.add_float("up_leg", np.zeros(dset.num_obs), unit="second")
    dset.add_posvel("sat_pos",
                    np.zeros((dset.num_obs, 6)),
                    system="gcrs",
                    time=dset.time)
    arc_length = config.tech.arc_length.float

    dset.site_pos.other = dset.sat_pos

    # First guess for up_leg:
    dset.up_leg[:] = dset.time_of_flight / 2

    for iter_num in itertools.count(start=1):
        log.blank()
        log.info(f"Calculating model corrections for iteration {iter_num}")

        sat_time_list = dset.obs_time + dset.time_bias + dset.up_leg
        apriori_orbit_provider = config.tech.apriori_orbit.str
        sat_name = dset.vars["sat_name"]

        rundate = dset.analysis["rundate"]

        if apriori_orbit_provider:
            version = config.tech.apriori_orbit_version.str
            log.info(
                f"Using external orbits from {apriori_orbit_provider}, version {version}"
            )
            apriori_orbit = apriori.get(
                "orbit",
                rundate=rundate + timedelta(days=arc_length),
                time=None,
                day_offset=6,
                satellite=sat_name,
                apriori_orbit="slr",
                file_key="slr_external_orbits",
            )
            dset_external = apriori_orbit._read(dset, apriori_orbit_provider,
                                                version)

            sat_pos = dset_external.sat_pos.gcrs_pos
            t_sec = TimeDelta(
                dset_external.time -
                Time(datetime(rundate.year, rundate.month, rundate.day),
                     scale="utc",
                     fmt="datetime"),
                fmt="seconds",
            )
            t_sec = t_sec.value
        else:
            sat_pos, sat_vel, t_sec = orbit.calculate_orbit(
                datetime(rundate.year, rundate.month, rundate.day),
                sat_name,
                sat_time_list,
                return_full_table=True)

        sat_pos_ip, sat_vel_ip = interpolation.interpolate_with_derivative(
            np.array(t_sec),
            sat_pos,
            sat_time_list,
            kind="interpolated_univariate_spline")
        dset.sat_pos.gcrs[:] = np.concatenate((sat_pos_ip, sat_vel_ip), axis=1)
        delay.calculate_delay("kinematic_models", dset)

        # We observe the time when an observation is done, and the time of flight of the laser pulse. We estimate
        # the up-leg time with Newton's method applied to the equation (8.84) of :cite:'beutler2005' Gerhard Beutler:
        # Methods of Celestial Mechanics, Vol I., 2005.
        for j in range(0, 4):
            reflect_time = dset.time + TimeDelta(
                dset.time_bias + dset.up_leg, fmt="seconds", scale="utc")
            site_pos_reflect_time = (rotation.trs2gcrs(reflect_time)
                                     @ dset.site_pos.trs.val[:, :, None])[:, :,
                                                                          0]
            sta_sat_vector = dset.sat_pos.gcrs.pos.val - site_pos_reflect_time
            unit_vector = sta_sat_vector / np.linalg.norm(sta_sat_vector,
                                                          axis=1)[:, None]

            rho12 = (np.linalg.norm(sta_sat_vector, axis=1) +
                     delay.add("kinematic_models", dset)) / constant.c
            correction = (-dset.up_leg + rho12) / (
                np.ones(dset.num_obs) - np.sum(
                    unit_vector / constant.c * dset.sat_pos.vel.val, axis=1))
            dset.up_leg[:] += correction
            sat_time_list = dset.obs_time + dset.time_bias + dset.up_leg
            sat_pos_ip, sat_vel_ip = interpolation.interpolate_with_derivative(
                np.array(t_sec),
                sat_pos,
                sat_time_list,
                kind="interpolated_univariate_spline")

            dset.sat_pos.gcrs[:] = np.concatenate((sat_pos_ip, sat_vel_ip),
                                                  axis=1)

        delay.calculate_delay("satellite_models", dset)
        dset.calc[:] = delay.add("satellite_models", dset)
        dset.residual[:] = dset.obs - dset.calc
        log.info(
            f"{dset.num_obs} observations, residual = {dset.rms('residual'):.4f}"
        )
        if not apriori_orbit_provider:
            orbit.update_orbit(sat_name, dset.site_pos.gcrs, dset.sat_pos.pos,
                               dset.sat_pos.vel, dset.residual, dset.bin_rms)

        dset.write_as(stage=stage, label=iter_num, sat_name=sat_name)
        if iter_num >= iterations:
            break