示例#1
0
文件: __init__.py 项目: yxw027/where
def add(config_key, dset):
    delta_pos = list()

    for _ in dset.for_each_suffix("station"):
        if position.is_position(dset.site_pos):
            sta_delta = position.PositionDelta(np.zeros((dset.num_obs, 3)),
                                               system="gcrs",
                                               ref_pos=dset.site_pos)
        elif position.is_posvel(dset.site_pos):
            sta_delta = position.PosVelDelta(np.zeros((dset.num_obs, 6)),
                                             system="gcrs",
                                             ref_pos=dset.site_pos)

        if config_key not in dset.fields:
            return list(sta_delta)

        pos_fields = [
            f for f in dset[config_key]._fields
            if f.endswith(dset.default_field_suffix)
        ]

        for field in pos_fields:
            sta_delta += dset[config_key][field]
        delta_pos.append(sta_delta)
    return delta_pos
示例#2
0
def ocean_pole_tides_station(dset, opt):
    """Calculate the ocean pole tide corrections for a station

    Ocean pole tide corrections are returned in meters in the Geocentric Celestial Reference System for each
    observation.

    Args:
        dset:        A Dataset containing model data.
        version:     Version number of conventional mean pole model
        opt:         Apriori ocean pole tide coefficients

    Returns:
        Numpy array with ocean tide corrections in meters.
    """
    eop = apriori.get("eop", time=dset.time)

    # Constants in IERS Conventions equation 7.29
    H_p = np.sqrt(8 * np.pi / 15) * constant.omega ** 2 * constant.a ** 4 / constant.GM
    K = 4 * np.pi * constant.G * constant.a * constant.rho_w * H_p / (3 * constant.g_E)
    # @todo make these global? related to love numbers somehow
    gamma_2_R = 0.6870
    gamma_2_I = 0.0036

    # Equation (7.24) IERS Conventions 2010
    m_1 = (eop.x - eop.x_pole) * Unit.arcsec2rad
    m_2 = (eop.y_pole - eop.y) * Unit.arcsec2rad

    lat, lon, _ = dset.site_pos.pos.llh.T

    u_enu_R = np.array(
        [opt["u_e_R"](lon, lat, grid=False), opt["u_n_R"](lon, lat, grid=False), opt["u_r_R"](lon, lat, grid=False)]
    )
    u_enu_I = np.array(
        [opt["u_e_I"](lon, lat, grid=False), opt["u_n_I"](lon, lat, grid=False), opt["u_r_I"](lon, lat, grid=False)]
    )

    # Equation (7.29) IERS Conventions 2010
    denu = (K * ((m_1 * gamma_2_R + m_2 * gamma_2_I) * u_enu_R + (m_1 * gamma_2_R - m_2 * gamma_2_I) * u_enu_I)).T

    if position.is_position(dset.site_pos):
        pos_correction = position.PositionDelta(denu, system="enu", ref_pos=dset.site_pos, time=dset.time)
    elif position.is_posvel(dset.site_pos):
        # set velocity to zero
        denu = np.concatenate((denu, np.zeros(denu.shape)), axis=1)
        pos_correction = position.PosVelDelta(denu, system="enu", ref_pos=dset.site_pos, time=dset.time)
    else:
        log.fatal(f"dset.site_pos{dset.default_field_suffix} is not a PositionArray or PosVelArray.")

    return pos_correction.gcrs
示例#3
0
def solid_pole_tides_station(dset):
    """Calculate the solid pole tide corrections for a station

    Solid pole tide corrections are returned in meters in the Geocentric Celestial Reference System for each
    observation.

    Args:
        dset:        A Dataset containing model data.
        version:     Version number of conventional mean pole model

    Returns:
        Numpy array with ocean tide corrections in meters.
    """
    eop = apriori.get("eop", time=dset.time)

    # Equation (7.24) IERS Conventions 2010
    m_1 = eop.x - eop.x_pole
    m_2 = eop.y_pole - eop.y

    lat, lon, _ = dset.site_pos.pos.llh.T
    theta = np.pi / 2 - lat
    coslon, sinlon = np.cos(lon), np.sin(lon)

    # Equation (7.26) IERS Conventions 2010
    dup = -33 * np.sin(2 * theta) * (m_1 * coslon + m_2 * sinlon) * Unit.mm2m
    dsouth = -9 * np.cos(2 * theta) * (m_1 * coslon + m_2 * sinlon) * Unit.mm2m
    deast = 9 * np.cos(theta) * (m_1 * sinlon + m_2 * coslon) * Unit.mm2m

    # Correction in topocentric (east, north, up) coordinates
    denu = np.vstack((deast, -dsouth, dup)).T
    if position.is_position(dset.site_pos):
        pos_correction = position.PositionDelta(denu,
                                                system="enu",
                                                ref_pos=dset.site_pos,
                                                time=dset.time)
    elif position.is_posvel(dset.site_pos):
        # set velocity to zero
        denu = np.concatenate((denu, np.zeros(denu.shape)), axis=1)
        pos_correction = position.PosVelDelta(denu,
                                              system="enu",
                                              ref_pos=dset.site_pos,
                                              time=dset.time)
    else:
        log.fatal(
            f"dset.site_pos{dset.default_field_suffix} is not a PositionArray or PosVelArray."
        )

    return pos_correction.gcrs
示例#4
0
def solid_tides_station(dset, correction_cache):
    """Calculate the solid tide corrections for a station

    Solid tide corrections are returned in meters in the Geocentric Celestial Reference System for each observation.

    Args:
        dset:        A Dataset containing model data.

    Returns:
        Numpy array with solid tide corrections in meters.
    """
    eph = apriori.get("ephemerides", time=dset.time)
    dxyz = np.zeros((dset.num_obs, 3))
    obs_dt = dset.time.utc.datetime
    hour_of_day = dset.time.utc.jd_frac * 24

    sun_itrs = eph.pos_itrs("sun")
    moon_itrs = eph.pos_itrs("moon")

    # Calculate correction
    for obs in range(dset.num_obs):
        cache_key = (dset.station[obs], obs_dt[obs])
        if cache_key in correction_cache:
            dxyz[obs] = correction_cache[cache_key]
        else:
            dxyz[obs] = iers.dehanttideinel(
                dset.site_pos.pos[obs],
                obs_dt[obs].year,
                obs_dt[obs].month,
                obs_dt[obs].day,
                hour_of_day[obs],
                sun_itrs[obs],
                moon_itrs[obs],
            )
            correction_cache[cache_key] = dxyz[obs]

    if position.is_position(dset.site_pos):
        pos_correction = position.PositionDelta(dxyz, system="trs", ref_pos=dset.site_pos, time=dset.time)
    elif position.is_posvel(dset.site_pos):
        # set velocity to zero
        dxyz = np.concatenate((dxyz, np.zeros(dxyz.shape)), axis=1)
        pos_correction = position.PosVelDelta(dxyz, system="trs", ref_pos=dset.site_pos, time=dset.time)
    else:
        log.fatal(f"dset.site_pos{dset.default_field_suffix} is not a PositionArray or PosVelArray.")

    return pos_correction.gcrs
示例#5
0
def non_tidal_atmospheric_loading_station(ntapl, dset):
    """Apply non tidal atmospheric loading displacements for a station field.

    Corrections are returned in meters in the Geocentric
    Celestial Reference System for each observation.

    Args:
        dset:        A Dataset containing model data

    Returns:
        Numpy array: GCRS corrections in meters.
    """
    lat, lon, _ = dset.site_pos.pos.llh.T
    try:
        dup = ntapl["up"](dset.time, lon, lat)
        deast = ntapl["east"](dset.time, lon, lat)
        dnorth = ntapl["north"](dset.time, lon, lat)
    except KeyError:
        log.warn(
            f"No non-tidal atmospheric loading available for {dset.rundate}")
        dup = np.zeros(len(dset.time))
        deast = np.zeros(len(dset.time))
        dnorth = np.zeros(len(dset.time))

    denu = np.stack((deast, dnorth, dup), axis=1)
    if position.is_position(dset.site_pos):
        pos_correction = position.PositionDelta(denu,
                                                system="enu",
                                                ref_pos=dset.site_pos,
                                                time=dset.time)
    elif position.is_posvel(dset.site_pos):
        # set velocity to zero
        denu = np.concatenate((denu, np.zeros(denu.shape)), axis=1)
        pos_correction = position.PosVelDelta(denu,
                                              system="enu",
                                              ref_pos=dset.site_pos,
                                              time=dset.time)
    else:
        log.fatal(
            f"dset.site_pos{dset.default_field_suffix} is not a PositionArray or PosVelArray."
        )

    return pos_correction.gcrs
示例#6
0
文件: atm_tides.py 项目: yxw027/where
def atmospheric_tides_station(dset):
    """Calculate the atmospheric tides corrections for a station

    Atmospheric tides corrections are returned in meters in the Geocentric Celestial Reference System for each
    observation.

    Args:
        dset:        A Dataset containing model data

    Returns:
        Numpy array with atmospheric tide corrections in meters.

    """
    coeff = apriori.get("atmospheric_tides")
    use_cmc = config.tech.atmospheric_tides_cmc.bool

    # S1 has a period of 1 cycle/day, S2 has a period of 2 cycle/day
    omega_1 = 2 * np.pi
    omega_2 = 4 * np.pi

    # Time argument is fraction of UT1 day, see [2].
    t = dset.time.ut1.jd_frac
    lat, lon, _ = dset.site_pos.pos.llh.T

    # Equation 7.19a and 7.19b from IERS Conventions 2010
    de = (
        coeff["A_d1_e"](lon, lat, grid=False) * np.cos(omega_1 * t)
        + coeff["B_d1_e"](lon, lat, grid=False) * np.sin(omega_1 * t)
        + coeff["A_d2_e"](lon, lat, grid=False) * np.cos(omega_2 * t)
        + coeff["B_d2_e"](lon, lat, grid=False) * np.sin(omega_2 * t)
    )
    dn = (
        coeff["A_d1_n"](lon, lat, grid=False) * np.cos(omega_1 * t)
        + coeff["B_d1_n"](lon, lat, grid=False) * np.sin(omega_1 * t)
        + coeff["A_d2_n"](lon, lat, grid=False) * np.cos(omega_2 * t)
        + coeff["B_d2_n"](lon, lat, grid=False) * np.sin(omega_2 * t)
    )
    du = (
        coeff["A_d1_u"](lon, lat, grid=False) * np.cos(omega_1 * t)
        + coeff["B_d1_u"](lon, lat, grid=False) * np.sin(omega_1 * t)
        + coeff["A_d2_u"](lon, lat, grid=False) * np.cos(omega_2 * t)
        + coeff["B_d2_u"](lon, lat, grid=False) * np.sin(omega_2 * t)
    )
    denu = np.vstack([de, dn, du]).T * Unit.mm2m

    if position.is_position(dset.site_pos):
        pos_correction = position.PositionDelta(denu, system="enu", ref_pos=dset.site_pos, time=dset.time)
    elif position.is_posvel(dset.site_pos):
        # set velocity to zero
        denu = np.concatenate((denu, np.zeros(denu.shape)), axis=1)
        pos_correction = position.PosVelDelta(denu, system="enu", ref_pos=dset.site_pos, time=dset.time)
    else:
        log.fatal(f"dset.site_pos{dset.default_field_suffix} is not a PositionArray or PosVelArray.")

    # Add center of mass corrections
    if use_cmc:
        # Equation (7.20) in [1]
        coeff_cmc = apriori.get("atmospheric_tides_cmc")
        cmc = (
            coeff_cmc["A1"][None, :] * np.cos(omega_1 * t)[:, None]
            + coeff_cmc["B1"][None, :] * np.sin(omega_1 * t)[:, None]
            + coeff_cmc["A2"][None, :] * np.cos(omega_2 * t)[:, None]
            + coeff_cmc["B2"][None, :] * np.sin(omega_2 * t)[:, None]
        )
        if position.is_position(dset.site_pos):
            cmc_correction = position.PositionDelta(cmc, system="trs", ref_pos=dset.site_pos, time=dset.time)
        elif position.is_posvel(dset.site_pos):
            # set velocity to zero
            cmc = np.concatenate((cmc, np.zeros(cmc.shape)), axis=1)
            cmc_correction = position.PosVelDelta(cmc, system="trs", ref_pos=dset.site_pos, time=dset.time)
        pos_correction = pos_correction.trs + cmc_correction.trs

    return pos_correction.gcrs
示例#7
0
def ocean_tides_station(dset, amplitudes, phases, correction_cache):
    """Calculate the ocean tide corrections for a station

    Ocean tide corrections are returned in meters in the Geocentric Celestial Reference System for each observation.

    Args:
        dset:        A Dataset containing model data.

    Returns:
        Numpy array with ocean tide corrections in meters.
    """
    denu = np.zeros((dset.num_obs, 3))
    use_cmc = config.tech.ocean_tides_cmc.bool

    # Calculate correction
    for obs, site_id in enumerate(dset.site_id):
        if site_id not in amplitudes:
            # Warn about missing Ocean Tides Coefficients
            if site_id in _WARNED_MISSING:
                continue
            station = dset.unique("station", site_id=site_id)[0]
            log.error(
                f"Missing ocean loading coefficients for site id {site_id!r} ({station}). Correction set to zero."
            )
            _WARNED_MISSING.add(site_id)
            continue

        cache_key = (dset.station[obs], dset.time.utc.datetime[obs])
        if cache_key in correction_cache:
            denu[obs] = correction_cache[cache_key]
        else:
            epoch = [float(t) for t in dset.time.utc[obs].yday.split(":")]
            dup, dsouth, dwest = iers.hardisp(epoch, amplitudes[site_id],
                                              phases[site_id], 1, 1.0)

            # Correction in topocentric (east, north, up) coordinates
            denu[obs] = np.array([-dwest[0], -dsouth[0], dup[0]])
            correction_cache[cache_key] = denu[obs]

    if position.is_position(dset.site_pos):
        pos_correction = position.PositionDelta(denu,
                                                system="enu",
                                                ref_pos=dset.site_pos,
                                                time=dset.time)
    elif position.is_posvel(dset.site_pos):
        # set velocity to zero
        denu = np.concatenate((denu, np.zeros(denu.shape)), axis=1)
        pos_correction = position.PosVelDelta(denu,
                                              system="enu",
                                              ref_pos=dset.site_pos,
                                              time=dset.time)
    else:
        log.fatal(
            f"dset.site_pos{dset.default_field_suffix} is not a PositionArray or PosVelArray."
        )

    # Center of mass corrections
    if use_cmc:
        coeff_cmc = apriori.get("ocean_tides_cmc")
        in_phase = coeff_cmc["in_phase"]
        cross_phase = coeff_cmc["cross_phase"]
        cmc = np.zeros((dset.num_obs, 3))
        for obs, time in enumerate(dset.time.utc):
            year, doy = time.datetime.year, float(
                time.datetime.strftime("%j")) + time.mjd_frac
            angle = iers.arg2(year, doy)[:, None]
            cmc[obs] += np.sum(in_phase * np.cos(angle) +
                               cross_phase * np.sin(angle),
                               axis=0)

        if position.is_position(dset.site_pos):
            cmc_correction = position.PositionDelta(cmc,
                                                    system="trs",
                                                    ref_pos=dset.site_pos,
                                                    time=dset.time)
        elif position.is_posvel(dset.site_pos):
            # set velocity to zero
            cmc = np.concatenate((cmc, np.zeros(cmc.shape)), axis=1)
            cmc_correction = position.PosVelDelta(cmc,
                                                  system="trs",
                                                  ref_pos=dset.site_pos,
                                                  time=dset.time)
        pos_correction = pos_correction.trs + cmc_correction

    return pos_correction.gcrs
示例#8
0
def eccentricity_vector_station(ecc, dset):
    """Calculate the eccentricity vector for a station.

    Corrections are returned in meters in the Geocentric
    Celestial Reference System for each observation.

    Args:
        dset:        A Dataset containing model data

    Returns:
        Numpy array: GCRS corrections in meters.
    """
    if position.is_position(dset.site_pos):
        ecc_vector = position.PositionDelta(np.zeros((dset.num_obs, 3)),
                                            system="enu",
                                            ref_pos=dset.site_pos,
                                            time=dset.time)
    elif position.is_posvel(dset.site_pos):
        ecc_vector = position.PosVelDelta(np.zeros((dset.num_obs, 6)),
                                          system="enu",
                                          ref_pos=dset.site_pos,
                                          time=dset.time)
    else:
        log.fatal(
            f"dset.site_pos{dset.default_field_suffix} is not a PositionArray or PosVelArray."
        )

    fieldnames = config.tech.eccentricity.identifier.list
    fielddata = [dset[field] for field in fieldnames]
    if len(fieldnames) > 1:
        keys = set(tuple(zip(*fielddata)))
    else:
        keys = fielddata[0].tolist()

    for key in keys:
        if len(fieldnames) > 1:
            filters = dict(zip(fieldnames, key))
        else:
            filters = dict(zip(fieldnames, [key]))

        if key not in ecc:
            ecc_vector[dset.filter(**filters), 0:3] = np.zeros(3)
            if key in _WARNED_MISSING:
                continue
            log.warn(
                f"Missing eccentricity data for {key}. Vector set to zero.")
            _WARNED_MISSING.add(key)
            continue

        if ecc[key]["coord_type"] == "ENU":
            ecc_vector[dset.filter(**filters), 0:3] = ecc[key]["vector"]

    ecc_vector = ecc_vector.trs
    for key in keys:
        if len(fieldnames) > 1:
            filters = dict(zip(fieldnames, key))
        else:
            filters = dict(zip(fieldnames, [key]))

        if key not in ecc:
            ecc_vector[dset.filter(**filters), 0:3] = np.zeros(3)
            continue

        if ecc[key]["coord_type"] == "XYZ":
            ecc_vector[dset.filter(**filters), 0:3] = ecc[key]["vector"]

    return ecc_vector.gcrs