def _calculate_pos_trs(self, site): """Calculate positions for the given time epochs The positions are calculated as simple linear offsets based on the reference epoch. Makes sure to pick out the correct time interval to use. Args: key: Key saying which site to calculate position for, type might depend on the Trf. Returns: Array: Positions, one 3-vector for each time epoch. """ station_info = self.data[site] ref_epoch = Time(float(station_info["ref_epoch"]), fmt="decimalyear", scale="utc") pos = np.full((self.time.size, 3), fill_value=np.nan) ref_pos = np.array(station_info["pos"]) ref_vel = np.array(station_info["vel"]) interval_years = (self.time - ref_epoch).jd * Unit.day2julian_years pos[:, :] = ref_pos + interval_years[:, None] * ref_vel[None, :] ell = ellipsoid.get("GRS80") pos_trs = Position(pos, system="trs", ellipsoid=ell, time=self.time) return np.squeeze(pos_trs)
def _calculate_pos_trs(self, site): """Calculate positions for the given time epochs The positions are calculated as simple linear offsets based on the reference epoch. Args: site (String): Key saying which site to calculate position for. Returns: Array: Positions, one 3-vector for each time epoch. """ station_info = self.data[site] ref_epoch = Time(station_info["ref_epoch"], scale="utc", fmt="datetime") pos = np.zeros((self.time.size, 3)) for pv in station_info["pos_vel"].values(): idx = np.logical_and(self.time.utc.datetime >= pv["start"], self.time.utc.datetime < pv["end"]) if idx.size == 1: idx = np.array([idx]) if not any(idx): continue ref_pos = np.array([pv["STAX"], pv["STAY"], pv["STAZ"]]) ref_vel = np.array([pv["VELX"], pv["VELY"], pv["VELZ"]]) interval_years = (self.time - ref_epoch).jd * Unit.day2julian_years if isinstance(interval_years, float): interval_years = np.array([interval_years]) pos[idx, :] = ref_pos + interval_years[idx, None] * ref_vel[None, :] ell = ellipsoid.get(config.tech.reference_ellipsoid.str.upper()) pos_trs = Position(pos, system="trs", ellipsoid=ell, time=self.time) return np.squeeze(pos_trs)
def _calculate_pos_trs(self, site): """Calculate positions for the given time epochs There are no velocities available, so same position is returned for all time epochs Args: site (String): Key specifying which site to calculate position for, must be key in self.data. Returns: Array: Positions, one 3-vector for each time epoch. """ pos = self.data[site].pop("pos")[None, :].repeat(self.time.size, axis=0) ell = ellipsoid.get(config.tech.reference_ellipsoid.str.upper()) pos_trs = Position(pos, system="trs", ellipsoid=ell, time=self.time) return np.squeeze(pos_trs)
def _calculate_pos_trs(self, site): """Calculate positions for the given time epochs There are no velocities available, so same position is returned for all time epochs Args: site (String): Key specifying which site to calculate position for, must be key in self.data. Returns: Array: Positions, one 3-vector for each time epoch. """ site_data = self.data[site] if self.time.isscalar: pos = np.full(3, np.nan) if "pos" not in site_data: return pos epoch = self.time.datetime try: ep_idx = np.where((site_data["time_start"] <= epoch) & (epoch < site_data["time_end"]))[0][0] pos[:] = site_data["pos"][ep_idx] except IndexError: pass else: pos = np.full((len(self.time), 3), np.nan) if "pos" not in site_data: return pos for idx, epoch in enumerate(self.time.datetime): try: ep_idx = np.where((site_data["time_start"] <= epoch) & (epoch < site_data["time_end"]))[0][0] except IndexError: continue pos[idx] = site_data["pos"][ep_idx] ell = ellipsoid.get(config.tech.reference_ellipsoid.str.upper()) pos_trs = Position(pos, system="trs", ellipsoid=ell, time=self.time) return np.squeeze(pos_trs)
def _calculate_pos_trs(self, site): """Calculate positions for the given time epochs The positions are calculated as simple linear offsets based on the reference epoch. If there is a post-seismic deformations model for a station the motion due to that model is added to the linear velocity model. Makes sure to pick out the correct time interval to use. Args: site (String): Key saying which site to calculate position for. Returns: Array: Positions, one 3-vector for each time epoch. """ station_info = self.data[site] ref_epoch = Time(station_info["ref_epoch"], scale="utc", fmt="datetime") pos = np.zeros((self.time.size, 3)) for pv in station_info["pos_vel"].values(): idx = np.logical_and(self.time.utc.datetime >= pv["start"], self.time.utc.datetime < pv["end"]) if idx.ndim == 0: idx = np.array([idx]) if not any(idx): continue ref_pos = np.array([pv["STAX"], pv["STAY"], pv["STAZ"]]) ref_vel = np.array([pv["VELX"], pv["VELY"], pv["VELZ"]]) interval_years = (self.time - ref_epoch).jd * Unit.day2julian_years if isinstance(interval_years, float): interval_years = np.array([interval_years]) pos[idx, :] = ref_pos + interval_years[idx, None] * ref_vel[None, :] ell = ellipsoid.get(config.tech.reference_ellipsoid.str.upper()) pos_trs = Position(np.squeeze(pos), system="trs", ellipsoid=ell, time=self.time) # Post-seismic deformations, see Appendix C in :cite:'itrf2014' if "psd" in station_info: psd = station_info["psd"] denu = dict(H=np.zeros(self.time.size), E=np.zeros(self.time.size), N=np.zeros(self.time.size)) for param in psd.values(): t_0 = Time(param["epoch"], fmt="datetime", scale="utc") delta_t = (self.time - t_0).jd * Unit.day2julian_years if isinstance(delta_t, float): delta_t = np.array([delta_t]) idx = delta_t > 0 for L in "ENH": aexp = np.array(param.get("AEXP_" + L, list())) texp = np.array(param.get("TEXP_" + L, list())) for a, t in zip(aexp, texp): denu[L][idx] += a * (1 - np.exp(-delta_t[idx] / t)) alog = np.array(param.get("ALOG_" + L, list())) tlog = np.array(param.get("TLOG_" + L, list())) for a, t in zip(alog, tlog): denu[L][idx] += a * np.log(1 + delta_t[idx] / t) denu = np.vstack((denu["E"], denu["N"], denu["H"])).T pos_delta = PositionDelta(np.squeeze(denu), system="enu", ellipsoid=ell, ref_pos=pos_trs, time=self.time) pos_trs += pos_delta.trs return np.squeeze(pos_trs)