Пример #1
0
def gnss_total_group_delay(dset):
    """Correct for total group delay 

    Args:
        dset (Dataset):   Model data.

    Returns:
        numpy.ndarray:    GNSS total group delay correction for each observation in meter

    """
    if config.tech.apriori_orbit.str != "broadcast":
        log.warn(
            f"Total group delay can only be applied for '{config.tech.apriori_orbit}' orbits. Apriori orbit has "
            f"to be 'broadcast'.")
        return np.zeros(dset.num_obs)

    brdc = apriori.get(
        "orbit",
        rundate=dset.analysis["rundate"],
        system=tuple(dset.unique("system")),
        station=dset.vars["station"],
        apriori_orbit="broadcast",
    )

    return brdc.total_group_delay(dset)
Пример #2
0
def data_handling(dset):
    """Edits data based on SLR handling file

    Args:
        dset:     A Dataset containing model data.

    Returns:
        Array containing False for observations to throw away
    """
    handling = apriori.get("slr_handling_file", time=dset.time)

    remove_idx = np.zeros(dset.num_obs, dtype=bool)
    for station in dset.unique("station"):
        # TODO: To be implemented
        if "V" in handling.get(station, {}):
            log.dev(f"TODO: Station {station}, marked with a V, not sure what that means")

        # X is data to be deleted
        # N is a non reliable station, not to be used for operational analysis
        # Q is a station in quarantene
        for key in ["X", "N", "Q"]:
            intervals = handling.get(station, {}).get(key, [])
            for interval in intervals:
                start_x, end_x = interval[0]
                int_idx = dset.filter(station=station) & (dset.time >= start_x) & (dset.time <= end_x)
                if np.any(int_idx):
                    log.debug(f"Removed data for station {station} in interval {start_x}-{end_x}, marked with {key}")
                    remove_idx |= int_idx
    return ~remove_idx
Пример #3
0
def gnss_relativistic_clock(dset):
    """Determine relativistic clock correction due to orbit eccentricity

    The correction is caluclated for precise and broadcast orbits after Eq. 10.10 and 10.11 in :cite:`iers2010`.

    Args:
        dset (Dataset):   Model data.

    Returns:
        numpy.ndarray:    Relativistic clock correction due to orbit eccentricity corrections for each observation

    """
    if "delay.gnss_relativistic_clock" in dset.fields:
        return dset.delay.gnss_relativistic_clock
    else:
        orbit = apriori.get(
            "orbit",
            apriori_orbit=dset.vars["orbit"],
            rundate=dset.analysis["rundate"],
            system=tuple(dset.unique("system")),
            station=dset.vars["station"],
        )

        return -orbit.relativistic_clock_correction(
            dset.sat_posvel.trs.pos.val, dset.sat_posvel.trs.vel.val)
Пример #4
0
def term_2(dset, proj_Kb, _, _ve):
    r"""Part of the vacuum delay dependent on the gravitational potential

    The term :math:`\hat K \cdot \vec b \cdot \frac{(1 + \gamma) U}{c^2}` scaled by the denominator :math:`1 +
    \frac{\hat K \cdot (\vec V_\oplus + \vec w_2)}{c}`.

    The parameterized post-Newtonian (PPN) gamma, :math:`\gamma` is equal to 1 in general relativity theory.

    The gravitational potential at the geocenter, \f$ U \f$, neglecting the effects of the Earth's mass is
    calculated. Following table 11.1 in IERS Conventions [2], only the solar potential need to be included at the
    picosecond level. That is

    \f[ U = G M_\odot / | \vec R_{\oplus_\odot} | \f]

    where \f$ \vec R_{\oplus_\odot} \f$ is the vector from the Sun to the geocenter. We calculate the latter using the
    ephemerides.

    Args:
        dset:    Model input data.
        proj_Kb: Scaled projection of baseline in direction of source.

    Returns:
        Numpy array: Part of vacuum delay.
    """
    gamma = 1.0
    eph = apriori.get("ephemerides", time=dset.time)
    grav_potential = constant.GM_sun / np.linalg.norm(eph.pos_gcrs("sun"),
                                                      axis=1)
    return proj_Kb * (1 + gamma) * grav_potential / constant.c**2
Пример #5
0
def gnss_relativistic_clock(dset):
    """Determine relativistic clock correction due to orbit eccentricity

    The correction is caluclated for precise and broadcast orbits after Eq. 10.10 and 10.11 in :cite:`iers2010`.

    TODO: 'gnss_relativistic_clock' could be saved in Dataset and used here to avoid calculation of relativistic clock
          correction twice.

    Args:
        dset (Dataset):   Model data.

    Returns:
        numpy.ndarray:    Relativistic clock correction due to orbit eccentricity corrections for each observation

    """
    # TODO: Is there a way that relativistic_clock_correction() could be called directly, without generating an orbit
    #       object? -> Should it be handled over dset.gnss_relativistic_clock ????
    orbit = apriori.get(
        "orbit",
        apriori_orbit=dset.vars["orbit"],
        rundate=dset.rundate,
        time=dset.sat_time,
        satellite=tuple(dset.satellite),
        system=tuple(dset.system),
        station=dset.vars["station"],
    )

    return -orbit.relativistic_clock_correction()
Пример #6
0
def nnr_crf(dset, param_names):
    # NNR to CRF

    celestial_reference_frame = config.tech.celestial_reference_frames.list[0]
    crf = apriori.get("crf",
                      celestial_reference_frames=celestial_reference_frame,
                      session=dset.dataset_name)
    n = len(param_names)
    H2 = np.zeros((3, n))
    for idx, column in enumerate(param_names):
        if "_src_dir-" not in column:
            continue
        source = column.split("-", maxsplit=1)[-1].split("_")[0]
        if source in crf:
            ra = crf[source].pos.crs[0]
            dec = crf[source].pos.crs[1]
            if column.endswith("_ra"):
                H2[0, idx] = -np.cos(ra) * np.sin(dec) * np.cos(dec)
                H2[1, idx] = -np.sin(ra) * np.sin(dec) * np.cos(dec)
                H2[2, idx] = np.cos(dec)**2
            if column.endswith("_dec"):
                H2[0, idx] = np.sin(ra)
                H2[1, idx] = -np.cos(ra)

    if H2.any():
        log.info("Applying NNR constraint to {}",
                 celestial_reference_frame.upper())
        # add NNR to CRF constraints
        sigma = np.array([1e-6] * 3)
        return H2, sigma
    else:
        return np.zeros((0, n)), np.zeros(0)
Пример #7
0
def solid_tides_station(dset):
    """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 enumerate(dset.values()):
        dxyz[obs] = iers.dehanttideinel(
            dset.site_pos.itrs_pos[obs],
            obs_dt[obs].year,
            obs_dt[obs].month,
            obs_dt[obs].day,
            hour_of_day[obs],
            sun_itrs[obs],
            moon_itrs[obs],
        )

    # Transform from terrestial to celestial
    return dset.site_pos.convert_itrs_to_gcrs(dxyz)
Пример #8
0
def ocean_tides(dset):
    """Calculate ocean tide corrections at both stations

    Ocean tide corrections are returned in meters in the Geocentric Celestial Reference System for each observation. A
    Numpy array with 6 columns is returned, the first three columns are \f$ x, y, z \f$ for station 1, while the last
    three columns are \f$ x, y, z \f$ for station 2.

    Args:
        rundate:  The model run date.
        tech:     The technique.
        dset:     A Dataset containing model data.

    Returns:
        Numpy array with ocean tide corrections in meters.
    """
    # Ocean Tides Coefficients
    otc = apriori.get("ocean_tides")

    amplitudes = {s: otc[s]["amplitudes"] for s in dset.unique("site_id") if s in otc}
    phases = {s: otc[s]["phases"] for s in dset.unique("site_id") if s in otc}
    # Warn about missing Ocean Tides Coefficients
    for site_id in set(dset.unique("site_id")) - set(amplitudes.keys()):
        log.error("Missing ocean loading coefficients for site id '{}'. Correction set to zero.", site_id)

    data_out = list()
    for _ in dset.for_each("station"):
        data_out.append(ocean_tides_station(dset, amplitudes, phases))

    return np.hstack(data_out)
Пример #9
0
    def site_eccentricity(self):
        """Mandatory
        """
        ecc = apriori.get("eccentricity",
                          rundate=self.dset.analysis["rundate"])
        self.fid.write("+SITE/ECCENTRICITY\n")
        self.fid.write(
            "*Code PT SBIN T Data_Start__ Data_End____ typ Apr --> Benchmark (m)_____\n"
        )
        for sta in self.dset.unique("station"):
            site_id = self.dset.meta[sta]["site_id"]

            self.fid.write(
                " {:4} {:>2} {:>4} {:1} {:12} {:12} {:3} {: 8.4f} {: 8.4f} {: 8.4f}\n"
                "".format(
                    site_id,
                    "A",
                    1,
                    _TECH[self.dset.meta["tech"]],
                    self.dset.time.yydddsssss[0],
                    self.dset.time.yydddsssss[-1],
                    ecc[site_id]["coord_type"],
                    ecc[site_id]["vector"][0],
                    ecc[site_id]["vector"][1],
                    ecc[site_id]["vector"][2],
                ))
        self.fid.write("-SITE/ECCENTRICITY\n")
Пример #10
0
def gnss_relativistic_clock_rate(dset):
    """Determine relativistic clock rate correction due to orbit eccentricity

    The correction is caluclated for precise and broadcast orbits after Eq. 6-19 in :cite:`zhang2007`.

    Args:
        dset (Dataset):   Model data.

    Returns:
        numpy.ndarray:    Relativistic clock rate correction due to orbit eccentricity corrections for each observation

    """

    gm = constant.get("GM", source="iers_2010")

    orbit = apriori.get(
        "orbit",
        apriori_orbit=dset.vars["orbit"],
        rundate=dset.analysis["rundate"],
        system=tuple(dset.unique("system")),
        station=dset.vars["station"],
    )

    a = np.power(orbit.get_ephemeris_field("sqrt_a", dset), 2)

    correction = 2 * gm / constant.c * (1 / a -
                                        1 / dset.sat_posvel.trs.pos.length)

    return correction
Пример #11
0
def _write_line(sta_1, sta_2, dset, idx):
    """Write one line of information about a station or baseline.

    At the moment, we also print the line to the screen for convenience, this might need to be
    changed when we run operationally?

    Args:
        sta_1:  String, name of Station 1.
        sta_2:  String, name of Station 2.
        dset:   Dataset, data from the model run.
        idx:    Bool-array, True for observations that should be included.
        fid:    File-pointer, file to write to.

    """
    rms = dset.rms("residual", idx=idx) if any(idx) else 0
    bias = dset.mean("residual", idx=idx) if any(idx) else 0
    stars = "" if rms < STAR_THRESHOLD else "*" * min(MAX_NUM_STARS, math.ceil(math.log2(rms / STAR_THRESHOLD)))

    if sta_2 and any(idx):
        trf = apriori.get("trf", time=dset.time.utc.mean)
        site_id_1 = dset.meta[sta_1]["site_id"]
        site_id_2 = dset.meta[sta_2]["site_id"]
        pos_1 = trf[site_id_1].pos.trs
        pos_2 = trf[site_id_2].pos.trs
        bl_len = (pos_2 - pos_1).length
    else:
        bl_len = 0

    return f"{sta_1:<9s} {sta_2:<9s} {np.sum(idx):>5d} {bl_len:>11.1f} {bias:>11.6f} {rms:>11.6f} {stars}"
Пример #12
0
def get_satellite_sun_vector(time, sat_pos):
    """Determine unit vector pointing from satellite to Sun in ITRS

    The determination of the vector pointing from satellite to Sun is based on Eq. 5.77 in :cite:`subirana2013`.

    Args:
        time (where.lib.time.Time):     Where Time object.
        sat_pos (numpy.ndarray):        Satellite position in ITRS.

    Returns:
        numpy.ndarray:  unit vectors pointing from satellite to Sun in ITRS and in unit of meters
    """

    num_obs = len(time)
    unit_sat_sun_pos = np.zeros((num_obs, 3))

    # Get Sun position vector in ITRS
    eph = apriori.get("ephemerides", time=time)

    # TODO:
    # Actually the JPL ephemeris are given in the BCRS with Solar System barycenter as origin and not Earth mass
    # center.  So in principle the sun position vector has to be transformed from the BCRS to the GCRS. What are the
    # consequences, if we do not consider these corrections?
    sun_pos_itrs = eph.pos_itrs("sun")

    # Determination of vector between satellite and Sun
    sat_sun_pos = sun_pos_itrs - sat_pos
    sat_sun_pos_norm = np.linalg.norm(sat_sun_pos, axis=1)
    unit_sat_sun_pos = sat_sun_pos / sat_sun_pos_norm[:, None]

    return unit_sat_sun_pos
Пример #13
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_mean
    m_2 = -(eop.y - eop.y_mean)

    lat, lon, _ = dset.site_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
    return dset.site_pos.convert_enu_to_gcrs(denu)
Пример #14
0
    def itrs_pos_sun(self):
        """Determine unit vector pointing from given position to Sun in ITRS

        The determination of the vector pointing from given position to Sun is based on Eq. 5.77 in
        :cite:`subirana2013`.

        Returns:
            numpy.ndarray:  unit vectors pointing from given position to Sun in ITRS and in unit of meters
        """
        # Get Sun position vector in ITRS

        eph = apriori.get(
            "ephemerides",
            time=self._time.tdb)  # TODO: is self._time.tdb correct

        # TODO:
        # Actually the JPL ephemeris are given in the BCRS with Solar System barycenter as origin and not Earth mass
        # center. So in principle the sun position vector has to be transformed from the BCRS to the GCRS. What are
        # the consequences, if we do not consider these corrections?
        earth_sun = eph.itrs(
            "earth", "sun")  # vector pointing from Earth to Sun mass center

        # Determination of vector between given position and Sun
        pos_sun = earth_sun - self.itrs_pos
        pos_sun_unit = mathp.unit_vector(pos_sun)

        # +DEBUG: Use same model as gLAB for determination of sun-earth vector
        # glab_sun_earth = gnss.findsun(self._time.tdb)
        # glab_pos_sun = glab_sun_earth - self.itrs_pos
        # pos_sun_unit = mathp.unit_vector(glab_pos_sun)
        # -DEBUG

        return pos_sun_unit
Пример #15
0
def validate_args(rundate, session=None, **kwargs):
    """Validate a session for the given rundate

    If session is not a valid VLBI session for the given rundate, an InvalidSessionError is raised.

    Args:
        rundate (date):    The model run date.
        session (String):  Name of session.

    Return:
        String:  Name of validated session.
    """
    if session is None:
        raise exceptions.InvalidArgsError(
            "You must specify '--session=<...>' to run a VLBI analysis")

    master_schedule = apriori.get("vlbi_master_schedule", rundate=rundate)
    master_sessions = master_schedule.list_sessions(rundate)
    if session not in master_sessions:
        log.warn(
            f"Session '{session}' is not listed in master file for {rundate:{config.FMT_date}}. "
            f"Available sessions are {', '.join(master_sessions)}.")
    else:
        if not master_schedule.ready(rundate, session):
            status = master_schedule.status(rundate, session)
            log.warn(
                f"Session '{session}' is not ready for processing. Master file status: '{status}'"
            )
Пример #16
0
    def write_to_dataset(self, dset):
        """Store DORIS data in a dataset

        Args:
            dset: The Dataset where data are stored.
        """
        dset.num_obs = len(self.data["obs"]["time"])
        dset.add_time("time", val=self.data["obs"].pop("time"), scale="utc", format="isot")
        dset.add_text("station", val=self.data["obs"].pop("station"))

        for field, value in self.data["obs"].items():
            dset.add_float(field, val=np.array(value))

        # Station data
        sta_fields = set().union(*[v.keys() for v in self.meta["station_info"].values()])
        for field in sta_fields:
            dset.add_text(field, val=[self.meta["station_info"][s][field] for s in dset.station])

        # Station positions
        site_pos = np.zeros((dset.num_obs, 3))
        trf = apriori.get("trf", time=dset.time)
        for site in dset.unique("station"):
            idx = dset.filter(station=site)
            site_pos[idx, :] = trf[site].pos.trs[idx, :]
            log.debug(f"Using position {np.mean(site_pos[idx, :], axis=0)} for {site!r}")
        dset.add_position("site_pos", time="time", itrs=site_pos)

        # Satellite
        dset.add_text("satellite", val=[self.vars["sat_name"]] * dset.num_obs)
def gnss_ignore_unhealthy_satellite(dset):
    """Remove observations epochs for satellites, which are related to unhealthy GNSS broadcast ephemeris

    If a satellite is set to unhealthy in one of the given broadcast ephemeris blocks, then the related satellite 
    observation epochs are removed. 

    The definition of the satellite vehicle health flags depends on GNSS:
        - GPS: see section 20.3.3.3.1.4 in :cite:`is-gps-200h`
        - Galileo: see section 5.1.9.3 in :cite:`galileo-os-sis-icd`
        - BeiDou: see section 5.2.4.6 in :cite:`bds-sis-icd`
        - QZSS: see section 4.1.2.3 in :cite:`is-qzss-pnt-001`
        - IRNSS: see section 6.2.1.6 in :cite:`irnss-icd-sps`

    Args:
        dset (Dataset):   A Dataset containing model data.

    Returns:
        numpy.ndarray:    Array containing False for observations to throw away
    """
    # Get signal health status information from GNSS broadcast orbits
    brdc = apriori.get(
        "orbit",
        rundate=dset.analysis["rundate"],
        station=dset.vars["station"],
        system=tuple(dset.unique("system")),
        apriori_orbit="broadcast",
    )
    remove_idx = brdc.signal_health_status(dset) > 0

    unhealthy_satellites = sorted(set(dset.satellite[remove_idx]))
    log.info(f"Discarding observations for unhealthy satellites: {', '.join(unhealthy_satellites)}")

    return ~remove_idx
Пример #18
0
def spv_doppler(stage, dset):
    """Calculate model parameters and estimate

    Args:
        stage (str):          Name of current stage.
        dset (Dataset):       A dataset containing the data.
    """

    # to have access to orbit data, you have make a new call
    # to orbit
    # orbit = apriori.get("orbit", rundate=dset.analysis["rundate"], system=tuple(dset.unique('system')), station=dset.vars["station"],)

    station = dset.vars["station"]
    orbit = apriori.get("orbit",
                        rundate=dset.analysis["rundate"],
                        system=tuple(dset.unique("system")),
                        station=station)
    orbit.dset_raw.write_as(stage=stage, session=station, dataset_name="raw")
    orbit.dset_edit.write_as(stage=stage, session=station, dataset_name="edit")

    import IPython

    IPython.embed()

    #  get the observed time
    MJD = sorted(set(dset.time.gps.mjd))
    for epoch in MJD:
        idx = dset.time.gps.mjd == epoch
        valid_sats = dset.satellite[idx]
        dop_obs = dset.D1X[idx]
        AZ = dset.sat_posvel.azimuth[idx]
        EL = dset.sat_posvel.elevation[idx]
        SAT_ENU = dset.sat_posvel.enu_up[idx]
        SAT_POS = dset.sat_posvel.itrs_pos[idx]
        SAT_VEL = dset.sat_posvel.itrs_vel[idx]
Пример #19
0
def _ignore_satellites(dset: "Dataset", orbit_flag: str) -> None:
    """Remove GNSS observations with unavailable apriori satellite orbits from Dataset

    The remover can be used for precise and broadcast ephemeris and also for the GNSS and SISRE technique/analysis.

    - GNSS: The apriori orbit is chosen via the configuration. The available satellites of the apriori orbits are
            compared against the satellites given in the GNSS observation files.

    - SISRE: Both apriori orbits, broadcast and precise, has to be checked against a set of satellites defined in
             the configuration file.

    Args:
        dset:        A Dataset containing model data, which is decimated by unavailable satellite observations.
        orbit_flag:  Specification of which apriori orbit is used ("broadcast" or "precise")
    """
    orbit = apriori.get(
        "orbit",
        apriori_orbit=orbit_flag,
        rundate=dset.analysis["rundate"],
        station=dset.vars["station"],
        system=tuple(dset.unique("system")),
        day_offset=
        0,  # check satellite availability only for current rundate and not for the days before/after
        # rundate in addition. TODO: This does not work for broadcast ephemeris at the moment.
    )
    not_available_sat = set(dset.satellite) - set(orbit.dset_raw.satellite)
    file_paths = orbit.dset_raw.meta["parser"]["file_path"]

    if not_available_sat:
        log.warn(
            f"The following satellites are not given in apriori {orbit_flag} orbit file {', '.join(file_paths)}: "
            f"{', '.join(sorted(not_available_sat))}")
        cleaners.apply_remover("ignore_satellite",
                               dset,
                               satellites=not_available_sat)
Пример #20
0
def data_quality(dset):
    """Edits data based on data quality

    Args:
        dset:     A Dataset containing model data.

    Returns:
        Array containing False for observations to throw away
    """
    session = dset.dataset_name
    handling_str = config.session[
        session].slr_handling.str  # TODO: this is not used ...
    handling = apriori.get("slr_handling_file", time=dset.time)

    remove_idx = np.zeros(dset.num_obs, dtype=bool)
    for station in dset.unique("station"):
        intervals = handling.get(station, {}).get("X", [])
        for interval in intervals:
            start_x = interval[0][0]
            end_x = interval[0][1]
            int_idx = np.logical_and(
                dset.filter(station=station),
                np.logical_and(dset.date_list >= start_x,
                               dset.date_list <= end_x))
            if np.any(int_idx):
                log.warn("Removed data for station {} in interval {}-{}",
                         station, start_x, end_x)
                remove_idx = np.logical_or(remove_idx, int_idx)
    return np.logical_not(remove_idx)
Пример #21
0
def eclipse_satellites(fid, dsets):
    """Write overview over satellites in eclipse

    Args:
       fid:
       dsets:
    """
    stations = sorted(dsets["orbit"].keys())
    if not stations:
        return 0

    fid.write("\n# Overview over satellites in eclipse\n\n")
    fid.write("| Satellites                                      |\n")
    # fid.write('| Sat. | From    | To                             |\n') #TODO: time period of eclipting satellites needed
    fid.write("|------------------------------------------------:|\n")

    dset = dsets["orbit"][stations[0]]
    brdc = apriori.get(
        "orbit",
        rundate=dset.rundate,
        time=dset.time,
        satellite=tuple(dset.satellite),
        system=tuple(dset.system),
        station=dset.dataset_name.upper(),
        apriori_orbit="broadcast",
    )
    fid.write(
        "| {sats:47s} |\n"
        "".format(sats=" ".join(gnss.check_satellite_eclipse(brdc.dset))))
Пример #22
0
def vmf1_gridded_pressure(dset):
    """Calulates VMF1 gridded atmospheric pressure

    Equation (9.11) in IERS conventions 2010 :cite:`iers2010` is converted to 'pressure' and the VMF1 gridded
    atmospheric pressure can be determined with help of the gridded zenith hydrostatic delays from VMF1. The gridded
    VMF1 pressure values needs to be rescaled to actual station height. The method is described with Eq. (4) in Kouba
    :cite:`kouba2007`.

    Args:
        dset (Dataset):    Model data.

    Returns:
        numpy.ndarray:  Atmospheric pressure for each observation in [hPa].
    """
    # Get gridded VMF1 data
    vmf1 = apriori.get("vmf1", time=dset.time)

    lat, lon, height = dset.site_pos.llh.T
    grid_zhd = vmf1["zh"](dset.time, lon,
                          lat)  # Interpolation in time and space in VMF1 grid
    grid_height = vmf1["ell"](lon, lat, grid=False)
    grid_pressure = pressure_zhd(grid_zhd, lat, grid_height)

    # Rescale gridded pressure to station pressure
    pressure = pressure_height_correction(grid_pressure, grid_height, height)

    return pressure
Пример #23
0
def unhealthy_satellites(fid, dsets):
    """Write overview over unhealthy satellites

    Args:
       fid:
       dsets:
    """
    stations = sorted(dsets["orbit"].keys())
    if not stations:
        return 0

    fid.write("\n# Overview over unhealthy satellites\n\n")
    fid.write("| Sta.  |   Satellites                             |\n")
    fid.write("|-------|-----------------------------------------:|\n")

    for station in stations:
        dset = dsets["orbit"][station]

        brdc = apriori.get(
            "orbit",
            rundate=dset.rundate,
            time=dset.time,
            satellite=tuple(dset.satellite),
            system=tuple(dset.system),
            station=dset.dataset_name.upper(),
            apriori_orbit="broadcast",
        )
        fid.write("| {sta:5s} | {sats:40s} |\n"
                  "".format(sta=station,
                            sats=" ".join(brdc.unhealthy_satellites())))
Пример #24
0
def validate_session(rundate, session):
    """Validate a session for the given rundate

    If session is not a valid VLBI session for the given rundate, an InvalidSessionError is raised.

    Args:
        rundate (date):    The model run date.
        session (String):  Name of session.

    Return:
        String:  Name of validated session.
    """
    if not session:
        if util.check_options("--session"):
            return session  # Explicitly specified blank session, typically to open timeseries interactively
        raise exceptions.InvalidSessionError(
            "You must specify '--session=<...>' to run a VLBI analysis")

    # TODO: Can we use master files to validate sessions? What about intensives?
    master_schedule = apriori.get("vlbi_master_schedule", rundate=rundate)
    master_sessions = master_schedule.list_sessions(rundate)
    if session not in master_sessions:
        log.warn(
            f"Session '{session}' is not listed in master file for {rundate:{config.FMT_date}}. "
            f"Available sessions are {', '.join(master_sessions)}.")
    return session
Пример #25
0
def Y(time):
    """Total Y coordinate of CIP

    Returns:
        model + celestial pole offset
    """
    eop = apriori.get("eop", time=time)
    return sofa.Y_model(time) + eop.dy * Unit.arcsec2rad
Пример #26
0
def X(time):
    """Total X coordinate of CIP

    Returns:
        model + celestial pole offset
    """
    eop = apriori.get("eop", time=time)
    return X_model(time) + eop.dx * unit.arcsec2rad
Пример #27
0
 def initial_posvel(self, initial_dt):
     """Calculate initial position and velocity for GPS satellites
     """
     orb = apriori.get("gnss_orbit", rundate=initial_dt)[self.name]["pos"]
     pos = orb.gcrs[0]
     vel = (orb.gcrs[1] - orb.gcrs[0]) / (orb.utc_dt[1] -
                                          orb.utc_dt[0]).total_seconds()
     return np.hstack((pos, vel))
Пример #28
0
def delta_ut1_utc(time: "TimeArray", models=None) -> "np_float":

    if time.scale == "ut1":
        # pretend that ut1 is utc to get an approximate delta value
        eop = apriori.get("eop",
                          time=Time(time.mjd, fmt="mjd", scale="utc"),
                          models=models)
        tmp_utc_mjd = time.mjd - eop.ut1_utc * Unit.second2day

        # get a better delta value with a new computed utc value
        eop = apriori.get("eop",
                          time=Time(tmp_utc_mjd, fmt="mjd", scale="utc"),
                          models=models)
        return -eop.ut1_utc * Unit.second2day
    else:
        # time scale is utc
        eop = apriori.get("eop", time=time, models=models)
        return eop.ut1_utc * Unit.second2day
Пример #29
0
def calculate_temperature_functions(dset):
    """Estimates a temperature sine function based on the air temperature recorded at each site

    If the number of data points is too small to estimate a sine function a simple constant function based on the mean
    value of the datapoints is used instead.

    Args:
        dset (Dataset):  Model data.

    Returns:
        Dict: One temperature function for each station.
    """
    temperature_funcs = dict()
    for ivsname in dset.unique("ivsname"):
        try:
            site_id = dset.meta[ivsname]["site_id"]
        except KeyError:
            site_id = ""

        idx_1 = dset.filter(ivsname_1=ivsname)
        time_1 = dset.time.utc[idx_1].mjd
        temp_1 = dset.temperature_1[idx_1]

        idx_2 = dset.filter(ivsname_2=ivsname)
        time_2 = dset.time.utc[idx_2].mjd
        temp_2 = dset.temperature_2[idx_2]

        time = np.append(time_1, time_2)
        temp = np.append(temp_1, temp_2)

        if any(np.isnan(temp)):
            vmf1_sta = apriori.get("vmf1_station", time=dset.time)
            try:
                temperature_funcs[ivsname] = vmf1_sta[ivsname]["temp"]
                log.warn(
                    f"Missing temperature data for {ivsname} ({site_id}). Getting temperature from VMF1 station files"
                )
                continue
            except KeyError:
                log.warn(
                    f"Missing temperature data for {ivsname} ({site_id}). No backup data source available"
                )

        # Amplitude, phase, offset, trend
        guess = [3 * np.std(temp) / (2**0.5), 0, np.mean(temp), 0]
        optimize_func = lambda x: (x[0] * np.sin(2 * np.pi * time + x[1]) + x[
            2] + x[3] * time - temp)

        if len(temp) >= 4:
            coeff = optimize.leastsq(optimize_func, guess)[0]
        else:
            log.warn(
                f"Few datapoints, applying constant temperature for {ivsname} ({site_id})."
            )
            coeff = [0, 0, np.mean(temp), 0]
        temperature_funcs[ivsname] = _get_temperature_func(*coeff)
    return temperature_funcs
Пример #30
0
 def aberrated_src_dir(site_pos):
     """See IERS2010 Conventions, equation 11.15"""
     site_vel_gcrs = site_pos.gcrs.vel.val
     eph = apriori.get("ephemerides", time=dset.time)
     vel = eph.vel_bcrs("earth") + site_vel_gcrs
     return (
         dset.src_dir.unit_vector + vel / constant.c -
         dset.src_dir.unit_vector *
         (dset.src_dir.unit_vector[:, None, :] @ vel[:, :, None])[:, :, 0] /
         constant.c)