def info(self): """ Basic informations about time series included in the Gts instance. """ import pyacs.message.message as MESSAGE import pyacs.lib.astrotime as at import numpy as np # number of ts MESSAGE("Number of time series: %d" % self.n()) # date min_decyear = 3000. max_decyear = -1 l1000days = [] l25days = [] lduration = [] llon = [] llat = [] for code in self.lcode(): lduration.append(self.__dict__[code].data[-1, 0] - self.__dict__[code].data[0, 0]) llon.append(self.__dict__[code].lon) llat.append(self.__dict__[code].lat) if self.__dict__[code].data[0, 0] < min_decyear: min_decyear = self.__dict__[code].data[0, 0] if self.__dict__[code].data[-1, 0] > max_decyear: max_decyear = self.__dict__[code].data[-1, 0] if self.__dict__[code].data.shape[0] > 1000: l1000days.append(code) if self.__dict__[code].data[-1, 0] - self.__dict__[code].data[0, 0] > 2.5: l25days.append(code) MESSAGE("Start/End Duration in decimal year: %10.4lf %10.4lf %8.4lf" % ( min_decyear, max_decyear, max_decyear - min_decyear)) ndays = int(at.decyear2mjd(max_decyear) - at.decyear2mjd(min_decyear)) MESSAGE("Start/End Duration doy: %04d-%03d %04d-%03d %d days" % ( int(min_decyear), at.decyear2dayno(min_decyear)[0], int(max_decyear), at.decyear2dayno(max_decyear)[0], ndays)) str_sdate = at.decyear2datetime(min_decyear).isoformat(" ", "minutes") str_edate = at.decyear2datetime(max_decyear).isoformat(" ", "minutes") MESSAGE("Start/End : %s %s " % (str_sdate, str_edate)) MESSAGE("Number of sites with more than 1000 observations: %d" % len(l1000days)) MESSAGE("Number of sites with more than 2.5 years of observations: %d" % len(l25days)) MESSAGE("Mean time series duration %.1lf years. Median time series duration %.1lf years" % ( np.mean(np.array(lduration)), np.median(np.array(lduration)))) MESSAGE("Network mean location: (%.1lf,%.1lf). Network median location: (%.1lf,%.1lf)" % ( np.mean(np.array(llon)), np.mean(np.array(llat)), np.median(np.array(llon)), np.median(np.array(llat)))) return self
def np_decyear_2_days(data, ref_date): """ converts a 1-D numpy array including decimal year to a 1-D numpy array of days after a reference date ref_date is read by guess_date returns a 1-D numpy array """ from pyacs.lib import astrotime as AT lmjd = np.array(list(map(AT.decyear2mjd, data))) ref_mjd = AT.decyear2mjd(guess_date(ref_date)) return (lmjd - ref_mjd)
def __get_offset_date_and_value(x, y, threshold): # for dates data_mjd = at.decyear2mjd(x) new_data_mjd = (data_mjd[0:-1] + data_mjd[1:]) / 2. x_diff = at.mjd2decyear(new_data_mjd) # for y diff_y = np.diff(y) abs_diff_y = np.fabs(diff_y) np_idx = np.where(abs_diff_y > threshold) # get dates np_dates = x_diff[np_idx] # get values np_values = diff_y[np_idx] return np_dates, np_values
def trajectory(self, model_type, offset_dates=[], eq_dates=[], H_fix={}, H_constraints={}, H_bounds={}, component='NEU', verbose=False): ############################################################################### """ Calculates the parameters of a (non-linear) trajectory model for a Geodetic Time Series. The trajectory model is: y(t) = trend : trend_cst + trend * ( t - t0 ) + annual: a_annual * cos( 2*pi + phi_annual ) + semi-annual: a_semi_annual * cos( 2*pi + phi_semi_annual ) + offset : Heaviside( t - t_offset_i ) * offset_i + post-seismic_deformation as decaying log (psd_log): psd_eq_i * np.log( 1 + Heaviside( t - eq_i )/tau_i ) :param model_type: string made of the key-word the parameters to be estimated. Key-word parameters are 'trend','annual','semi-annual','seasonal','offset','psd_log'. 'trend-seasonal-offset-psd_log' will do the full trajectory model. :param offset_dates: a list of offset_dates in decimal year :param eq_dates: a list of earthquake dates for which post-seismic deformation (psd_log) will be estimated :param H_fix: a dictionary including the name of the parameter to be hold fixed and the value. For instance to impose the co-seismic offset (North-East-Up) and relaxation time of 100 days for the first earthquake use: H_fix = { 'psd_log_offset_00':[10., 15., 0.] , 'psd_log_tau_00':[100., 100., 100.]} :param H_constraints: a dictionary including the name of the parameter to be constrained. For instance to impose a 50 days constraints around 500 days on the relaxation time of the second earthquake for all NEU components use: H_fix = { 'psd_log_tau_01':[[500.,50], [500.,50] , [500.,50]]} :param H_bounds: a dictionary including the bounds. For instance to impose a relaxation time for the third earthquake to be in the range of 2 to 3 years, for all NEU components use: H_bounds = { 'psd_log_tau_02':[[2*365.,3*365.], [[2*365.,3*365.] , [[2*365.,3*365.]]} :param component: string , component for which the trajectory model will be estimated. :param verbose: verbose mode :note: Unlike most pyacs.gts functions, trajectory returns 4 elements: the results as a dictionary, the model Gts, the residual Gts and a Gts with model predictions at every day. """ # import import numpy as np import pyacs.lib.astrotime as at # after this method .data and .data_xyz are not consistent so .data_xyz is set to None self.data_xyz = None # fills the H_fix, H_constraints & H_bounds for the components if 'N' in component: i = 0 # H_fix H_fix_N = {} for k, v in H_fix.items(): if isinstance(v, list): H_fix_N[k] = v[i] else: H_fix_N[k] = v # H_constraints H_constraints_N = {} for k, v in H_constraints.items(): if isinstance(v[0], list): H_constraints_N[k] = v[i] else: H_constraints_N[k] = v # H_bounds H_bounds_N = {} for k, v in H_bounds.items(): if isinstance(v[0], list): H_bounds_N[k] = v[i] else: H_bounds_N[k] = v if 'E' in component: i = 1 # H_fix H_fix_E = {} for k, v in H_fix.items(): if isinstance(v, list): H_fix_E[k] = v[i] else: H_fix_E[k] = v # H_constraints H_constraints_E = {} for k, v in H_constraints.items(): if isinstance(v[0], list): H_constraints_E[k] = v[i] else: H_constraints_E[k] = v # H_bounds H_bounds_E = {} for k, v in H_bounds.items(): if isinstance(v[0], list): H_bounds_E[k] = v[i] else: H_bounds_E[k] = v if 'U' in component: i = 2 # H_fix H_fix_U = {} for k, v in H_fix.items(): if isinstance(v, list): H_fix_U[k] = v[i] else: H_fix_U[k] = v # H_constraints H_constraints_U = {} for k, v in H_constraints.items(): if isinstance(v[0], list): H_constraints_U[k] = v[i] else: H_constraints_U[k] = v # H_bounds H_bounds_U = {} for k, v in H_bounds.items(): if isinstance(v[0], list): H_bounds_U[k] = v[i] else: H_bounds_U[k] = v # Run the estimation from pyacs.gts.lib.model.non_linear_gts_model import nl_gts_fit t_mjd = at.decyear2mjd(self.data[:, 0]) t_mjd_ed = np.arange(t_mjd[0], t_mjd[-1]) t_ed = at.mjd2decyear(t_mjd_ed) # North if 'N' in component: if verbose: print("-- Running trajectory model for site %s component North" % self.code) i = 1 (H_res_N, model_N, residuals_N, model_ed_N) = nl_gts_fit(self.data[:, 0], self.data[:, i], self.data[:, i + 3], \ model_type, offset_dates=offset_dates, eq_dates=eq_dates, \ H_fix=H_fix_N, H_constraints=H_constraints_N, H_bounds=H_bounds_N, verbose=verbose) else: model_N = np.vstack((self.data[:, 0], self.data[:, 0] * 0.)) residuals_N = np.vstack((self.data[:, 0], self.data[:, 0] * 0.)) model_ed_N = np.vstack((t_ed, t_ed * 0.)) # East if 'E' in component: if verbose: print("-- Running trajectory model for site %s component East" % self.code) i = 2 (H_res_E, model_E, residuals_E, model_ed_E) = nl_gts_fit(self.data[:, 0], self.data[:, i], self.data[:, i + 3], \ model_type, offset_dates=offset_dates, eq_dates=eq_dates, \ H_fix=H_fix_E, H_constraints=H_constraints_E, H_bounds=H_bounds_E, verbose=verbose) else: model_E = np.vstack((self.data[:, 0], self.data[:, 0] * 0.)) residuals_E = np.vstack((self.data[:, 0], self.data[:, 0] * 0.)) model_ed_E = np.vstack((t_ed, t_ed * 0.)) # Up if 'U' in component: if verbose: print("-- Running trajectory model for site %s component Up" % self.code) i = 3 (H_res_U, model_U, residuals_U, model_ed_U) = nl_gts_fit(self.data[:, 0], self.data[:, i], self.data[:, i + 3], \ model_type, offset_dates=offset_dates, eq_dates=eq_dates, \ H_fix=H_fix_U, H_constraints=H_constraints_U, H_bounds=H_bounds_U, verbose=verbose) else: model_U = np.vstack((self.data[:, 0], self.data[:, 0] * 0.)) residuals_U = np.vstack((self.data[:, 0], self.data[:, 0] * 0.)) model_ed_U = np.vstack((t_ed, t_ed * 0.)) # prepare return output H_res = [H_res_N, H_res_E, H_res_U] model_gts = self.copy(data_xyz=False) model_gts.data[:, 1] = model_N[:, -1] model_gts.data[:, 2] = model_E[:, -1] model_gts.data[:, 3] = model_U[:, -1] residual_gts = self.copy(data_xyz=False) residual_gts.data[:, 1] = residuals_N[:, -1] residual_gts.data[:, 2] = residuals_E[:, -1] residual_gts.data[:, 3] = residuals_U[:, -1] model_ed_gts = self.copy(data_xyz=False) model_ed_gts.data = np.zeros((t_ed.shape[0], 10)) model_ed_gts.data[:, 0] = t_ed model_ed_gts.data[:, 1] = model_ed_N[:, -1] model_ed_gts.data[:, 2] = model_ed_E[:, -1] model_ed_gts.data[:, 3] = model_ed_U[:, -1] return H_res, model_gts, residual_gts, model_ed_gts
def substract_ts_daily(self,ts,verbose=True): ################################################################### """ substract the ts provided as argument to the current time series :param ts: time series to be substracted as a Gts instance :param verbose: verbose mode :return : new Gts :note: this method assumes daily time series """ # import import inspect import numpy as np import pyacs.lib.astrotime as at # check data is not None from pyacs.gts.lib.errors import GtsInputDataNone try: if self.data is None: # raise exception raise GtsInputDataNone(inspect.stack()[0][3],__name__,self) except GtsInputDataNone as error: # print PYACS WARNING print( error ) return( self ) # check data is not None try: if ts.data is None: # raise exception raise GtsInputDataNone(inspect.stack()[0][3],__name__,ts) except GtsInputDataNone as error: # print PYACS WARNING print( error ) return( self ) # find common dates np_mjd_1 = at.decyear2mjd( self.data[:,0] ).astype( int ) np_mjd_2 = at.decyear2mjd( ts.data[:,0] ).astype( int ) np_mjd_common_dates = np.intersect1d( np_mjd_1 , np_mjd_2 ) if verbose: print('-- ', np_mjd_common_dates.shape[0] , ' common dates found.') # test whether there are common dates if np_mjd_common_dates.shape[0] == 0: print('! WARNING No common dates between ',self.code,' from ',self.ifile) print('!!! and ',ts.code, ' from ',ts.ifile) new_data = None else: # extract mask1 = np.isin( np_mjd_1, np_mjd_common_dates ) data1 = self.data[ mask1 ] mask2 = np.isin( np_mjd_2, np_mjd_common_dates ) data2 = ts.data[ mask2 ] if data1.shape != data2.shape: print("!!! ERROR. Extracted data have different shapes") new_data = None # ENU new_data = data1 - data2 # dates new_data[:,0] = data1[:,0] # uncertainties new_data[:,4:8] = np.sqrt( data1[:,4:8]**2 + data2[:,4:8]**2 ) new_data[:,8:] = 0. new_code=self.code+'_'+ts.code new_Gts=self.copy(data=new_data) new_Gts.code=new_code # .data_xyz set to None new_Gts.data_xyz = None return(new_Gts)
def nl_gts_fit(ty, ym, sym, model_type, offset_dates=[], eq_dates=[], H_fix={}, H_constraints={}, H_bounds={}, verbose=False): ############################################################################### """ Fits a single 1D time series with a (non-linear) trajectory model. See documentation of gts.fit_trajectory for explanation on the options. """ import numpy as np ############################################################################### def fwd_model(m): ############################################################################### # index of parameter i = 0 # trend y_trend = np.copy(t) * 0.0 if 'trend' in model_type: y_trend = m[i] + m[i + 1] * t i = i + 2 # seasonal terms y_annual = np.copy(t) * .0 y_semi_annual = np.copy(t) * .0 if ('seasonal' in model_type) or ('annual' in model_type): y_annual = np.cos(2. * np.pi * (t - 0.) / 365.25) * m[i] - np.sin( 2. * np.pi * (t - 0.) / 365.25) * m[i + 1] i = i + 2 if ('seasonal' in model_type) or ('semi-annual' in model_type): y_semi_annual = np.cos(4. * np.pi * (t - 0.) / 365.25) * m[i] - np.sin( 4. * np.pi * (t - 0.) / 365.25) * m[i + 1] i = i + 2 # offsets y_offset = np.copy(t) * .0 if ('offset' in model_type): for date in offset_dates: h = t * 0. + 1. h[np.where(t < date)] = 0. y_offset = y_offset + h * m[i] i = i + 1 # psd y_psd = np.copy(t) * .0 if ('psd_log' in model_type): for date in eq_dates: h = t * 0. + 1. h[np.where(t <= date)] = 0. y_offset = y_offset + h * m[i] h = t * 0. lindex = np.where(t > date) y_psd[lindex] = y_psd[lindex] + m[i + 1] * np.log( 1 + (t[lindex] - date) / np.sqrt(m[i + 2]**2)) i = i + 3 # sum everything y_model = y_trend + y_annual + y_semi_annual + y_offset + y_psd return y_model ############################################################################### def cost(m): ############################################################################### y_model = fwd_model(m) # chi2_obs red_chi2_obs = np.sum(((y - y_model) / sy)**2) / y.shape[0] # chi2_reg chi2_reg = 0. if H_constraints != {}: for k, v in H_c_prior_sigma.items(): chi2_reg = chi2_reg + ((m[k] - v[0]) / v[1])**2 # chi2 chi2 = red_chi2_obs + chi2_reg return chi2 ############################################################################### def rms(m): ############################################################################### y_model = fwd_model(m) return np.sqrt(np.sum(((y - y_model) / 1.)**2) / y.shape[0]) ############################################################################### def wrms(m): ############################################################################### y_model = fwd_model(m) return np.sqrt(np.sum(((y - y_model) / 1.)**2) / np.sum(1. / sy**2)) ############################################################################### def red_chi_square(m): ############################################################################### y_model = fwd_model(m) return np.sqrt(np.sum(((y - y_model) / sy)**2) / y.shape[0]) ############################################################################### # prepare: log parameters index ############################################################################### H_param = {} n_param = 0 if 'trend' in model_type: H_param['trend_cst'] = n_param H_param['trend_slope'] = n_param + 1 n_param = n_param + 2 if 'seasonal' in model_type: H_param['annual_a'] = n_param H_param['annual_b'] = n_param + 1 H_param['semi_annual_a'] = n_param + 2 H_param['semi_annual_b'] = n_param + 3 n_param = n_param + 4 if 'annual' in model_type: H_param['annual_a'] = n_param H_param['annual_b'] = n_param + 1 n_param = n_param + 2 if 'semi-annual' in model_type: H_param['semi_annual_a'] = n_param H_param['semi_annual_b'] = n_param + 1 n_param = n_param + 2 if 'offset' in model_type: for i in np.arange(len(offset_dates)): H_param['offset' + ("_%02d" % i)] = n_param + i n_param = n_param + len(offset_dates) if 'psd_log' in model_type: for i in np.arange(len(eq_dates)): H_param['psd_log_offset' + ("_%02d" % i)] = n_param + 3 * i H_param['psd_log_amp' + ("_%02d" % i)] = n_param + 3 * i + 1 H_param['psd_log_tau' + ("_%02d" % i)] = n_param + 3 * i + 2 n_param = n_param + 3 * len(eq_dates) if verbose: print('-- number of parameters for trajectory model: ', n_param) print('-- index of parameters for trajectory model: ') for k, v in H_param.items(): print("-- m[%02d]: %s " % (v, k)) ############################################################################### # dealing with constraints ############################################################################### import scipy.optimize from pyacs.lib import astrotime as at # work with days rather than dec.year t = at.decyear2mjd(ty) offset_dates = at.decyear2mjd(offset_dates) eq_dates = at.decyear2mjd(eq_dates) # work with mm rather than m y = ym * 1.E3 sy = sym * 1.E3 bounds = None m0 = np.zeros(n_param) + 1. # bounds either as fixed or bounded parameters if H_fix != {} or H_bounds != {}: lb = [-np.inf] * n_param ub = [np.inf] * n_param bounds = scipy.optimize.Bounds(lb, ub, keep_feasible=False) # case of fixed parameters if H_fix != {}: if verbose: print('-- dealing with parameters hold fixed') for k, v in H_fix.items(): lb[H_param[k]] = v ub[H_param[k]] = v m0[H_param[k]] = v bounds = scipy.optimize.Bounds(lb, ub, keep_feasible=False) if verbose: print('-- bounds accounting for fixed parameters') for j in np.arange(len(lb)): print("-- m[%02d]: %.3lf %.3lf " % (j, lb[j], ub[j])) # case of bounded parameters if H_bounds != {}: if verbose: print('-- dealing with bounded parameters') for k, v in H_bounds.items(): lb[H_param[k]] = v[0] ub[H_param[k]] = v[1] bounds = scipy.optimize.Bounds(lb, ub, keep_feasible=False) if verbose: print('-- bounds accounting for bounded parameters') for j in np.arange(len(lb)): print("-- m[%02d]: %.3lf %.3lf " % (j, lb[j], ub[j])) # constraints if H_constraints != {}: if verbose: print('-- dealing with parameter constraints') H_c_prior_sigma = {} for k, v in H_constraints.items(): H_c_prior_sigma[H_param[k]] = [v[0], v[1]] m0[H_param[k]] = v[0] if verbose: print("-- m[%02d]: prior: %.3lf sigma: %.3lf " % (H_param[k], v[0], v[1])) fwd_model(m0) res = scipy.optimize.minimize(cost, m0, method='SLSQP', tol=1e-6, bounds=bounds) if verbose: print('-- minimization finished') print('-- scipy.optimize.minimize message: ', res.message) # print results H_res = {} for k, v in H_param.items(): H_res[k] = res.x[v] if verbose: print("-- %-18s m[%02d]: %+15.3lf " % (k, v, res.x[v])) if verbose: # print rms print('--rms (mm): %.2lf ' % rms(res.x)) # print rms print('--wrms (mm): %.2lf ' % wrms(res.x)) # print reduced chi2 print('--reduced chi-square : %.2lf ' % red_chi_square(res.x)) # return estimated parameters , model at t, residuals at t , model at every day # parameters were already stored in H_res y_model = fwd_model(res.x) model = np.vstack((at.mjd2decyear(t), y_model * 1.E-3)).T residuals = np.vstack((at.mjd2decyear(t), (y - y_model) * 1.E-3)).T t_every_day = np.arange(t[0], t[-1]) t = t_every_day y_model_every_day = fwd_model(res.x) model_every_day = np.vstack( (at.mjd2decyear(t_every_day), (y_model_every_day) * 1.E-3)).T return H_res, model, residuals, model_every_day
def decimate(self,time_step=30.,dates=[],method='median',verbose=False): ################################################################### """ decimate a time series :param time_step: time step in days :param dates: list of dates where point are forced to be written regardless time_step :param method: method used to be used to calculated the position. choose among ['median','mean','exact'] :param verbose: verbose mode :return : new Gts """ # import import inspect import numpy as np import pyacs.lib.astrotime as at # check data is not None from pyacs.gts.lib.errors import GtsInputDataNone try: if self.data is None: # raise exception raise GtsInputDataNone(inspect.stack()[0][3],__name__,self) except GtsInputDataNone as error: # print PYACS WARNING print( error ) return( self ) # start and end date start_decyear = self.data[0,0] end_decyear = self.data[-1,0] start_mjd = at.decyear2mjd(start_decyear) end_mjd = at.decyear2mjd(end_decyear) # new_gts to be filled new_gts=self.copy() new_gts.data=np.zeros((1,self.data.shape[1])) # loop on dates by time_step for date in np.arange(start_mjd ,end_mjd + time_step / 2. , time_step ): sub_ts=self.\ extract_periods( [at.mjd2decyear(date-time_step/2.),at.mjd2decyear(date+time_step/2.)] ,\ verbose = verbose) if sub_ts.data is None: continue if method == 'median': new_obs = np.median(sub_ts.data,axis=0) if method == 'mean': new_obs = np.mean(sub_ts.data,axis=0) if method == 'exact': new_obs = sub_ts.data[int(sub_ts.data.shape[0])-1,:] new_gts.data = np.vstack( ( new_gts.data, new_obs.reshape(1,-1) ) ) # case dates are provided for date in dates: sub_ts=self.extract_periods( [date,end_decyear] , verbose = verbose) if sub_ts.data is not None: new_obs = sub_ts.data[0,:] if verbose: print("-- adding observation at user requested date: %lf = %s = doy %d" % ( date, '-'.join(map(str, at.decyear2cal(date))), at.decyear2dayno(date))) if new_gts.data is not None: new_gts.data = np.vstack( ( new_gts.data, new_obs.reshape(1,-1) ) ) else: new_gts.data = new_obs.new_obs.reshape(1,-1) # remove first obs if new_gts.data.shape[0] == 1: if verbose: print('!!! decimated Gts has no date') new_gts.data = None new_gts.data_xyz = None return(new_gts) else: new_gts.data = np.delete(new_gts.data,0,axis=0) new_gts.neu2xyz() # reorder new_gts.reorder(verbose=verbose) if verbose: print('-- decimated Gts has ',new_gts.data.shape[0],' entries') return(new_gts)
def spline(self, smoothing=1, degree=5, date=None): """ :param smoothing: Positive smoothing factor used to choose the number of knots. Number of knots will be increased until the smoothing condition is satisfied: sum((w[i] * (y[i]-spl(x[i])))**2, axis=0) <= s :param degree: Degree of the smoothing spline. Must be <= 5. Default is k=3, a cubic spline. :param date: 1D array of interpolation dates in decimal year, or 'day' for every day. defualt None will interpolate at data date only. :return: new gts instance """ import numpy as np from pyacs.gts.Gts import Gts import inspect ########################################################################### # check data is not None from pyacs.gts.lib.errors import GtsInputDataNone try: if self.data is None: # raise exception raise GtsInputDataNone(inspect.stack()[0][3], __name__, self) except GtsInputDataNone as error: # print PYACS WARNING print(error) return (self) ########################################################################### # import from scipy.interpolate import UnivariateSpline import numpy as np Spline_ts = self.copy() s_e = UnivariateSpline(self.data[:, 0], self.data[:, 1], s=smoothing * 1E-3, k=degree) s_n = UnivariateSpline(self.data[:, 0], self.data[:, 2], s=smoothing * 1E-3, k=degree) s_u = UnivariateSpline(self.data[:, 0], self.data[:, 3], s=smoothing * 1E-3, k=degree) if date is None: Spline_ts.data[:, 1] = s_e(self.data[:, 0]) Spline_ts.data[:, 2] = s_n(self.data[:, 0]) Spline_ts.data[:, 3] = s_u(self.data[:, 0]) if isinstance(date, np.ndarray): Spline_ts.data[:, 1] = s_e(date) Spline_ts.data[:, 2] = s_n(date) Spline_ts.data[:, 3] = s_u(date) if date == 'day': import pyacs.lib.astrotime as at np_date = at.mjd2decyear( np.arange(at.decyear2mjd(self.data[0, 0]), at.decyear2mjd(self.data[-1, 0]))) Spline_ts.data = np.zeros((np_date.shape[0], 10)) Spline_ts.data[:, 0] = np_date Spline_ts.data[:, 1] = s_e(np_date) Spline_ts.data[:, 2] = s_n(np_date) Spline_ts.data[:, 3] = s_u(np_date) return (Spline_ts)
plt.show() ######################################################################################## # MAIN ######################################################################################## from pyacs.lib import astrotime as at from pyacs.gts.Gts import Gts raw_ts = Gts() my_ts = raw_ts.read_pos( tsfile= '/Users/nocquet/projets/2018/soam_proc/test_pyacs_061_snx/pos/IBEC.pos') t = at.decyear2mjd(my_ts.data[:, 0]) y = my_ts.data[:, 2] * 1.E3 sy = my_ts.data[:, 5] * 1.E3 offset_dates = [at.decyear2mjd(2012.524590164)] #offset_dates=[] eq_dates = [at.decyear2mjd(2016.292349727)] #eq_dates=[] H_constraints = {} bounds = {} nl_gts_fit(t, y, sy, 'trend-psd-seasonal', offset_dates=offset_dates,
def __handle_round_date(decyear): mjd = np.round(at.decyear2mjd(decyear), decimals=2) (mday, month, iyear, _ut) = at.mjd2cal(mjd) return (mday, month, iyear)
def find_offsets_edge_filter( self, threshold=0.6, search_lbda=[ 3,5,7,10,20,50,100,200,300] , delta_day=100, \ in_place=False, lcomponent='NE' , \ verbose=True, debug=True, log=False, eq_file=None): ############################################################################### # import from pyacs.gts.lib.filters.total_variation import edge import numpy as np import pyacs.lib.astrotime as at import pyacs.lib.units import datetime # handle delta_day if isinstance(delta_day, int): ldelta_day = [delta_day] else: if not isinstance(delta_day, list): print( "!!! ERROR: delta_day should be a list of integer or an integer" ) else: ldelta_day = delta_day # eq list a gcmt file if eq_file is not None: EQ = np.genfromtxt(eq_file, dtype=None) np_eq_lon = EQ['f0'] np_eq_lat = EQ['f1'] np_moment_scalar = EQ['f8'] np_moment_exponent = EQ['f9'] np_str_date = EQ['f10'] # handle magnitude np_eq_magnitude = np.copy(np_moment_scalar) * 0.0 i = 0 for scalar, exponent in zip(np_moment_scalar, np_moment_exponent): moment = scalar * 10.**(exponent - 7) np_eq_magnitude[i] = pyacs.lib.units.moment_to_magnitude(moment) i = i + 1 # handle dates np_eq_mjd = np.copy(np_moment_scalar) * 0. i = 0 for str_date in np_str_date: dyear = int(str_date[:4]) dmonth = int(str_date[4:6]) dmday = int(str_date[6:8]) dhour = int(str_date[8:10]) dminute = int(str_date[10:12]) date = datetime.datetime(dyear, dmonth, dmday, dhour, dminute) np_eq_mjd[i] = at.datetime2mjd(date) i = i + 1 # initialize the components l_idx_component = [] if 'N' in lcomponent: l_idx_component.append(1) if 'E' in lcomponent: l_idx_component.append(2) if 'U' in lcomponent: l_idx_component.append(3) H_idx_component = {1: 'N', 2: 'E', 3: 'U'} # working Gts new_gts = self.copy() ############## def __get_offset_date_and_value(x, y, threshold): # for dates data_mjd = at.decyear2mjd(x) new_data_mjd = (data_mjd[0:-1] + data_mjd[1:]) / 2. x_diff = at.mjd2decyear(new_data_mjd) # for y diff_y = np.diff(y) abs_diff_y = np.fabs(diff_y) np_idx = np.where(abs_diff_y > threshold) # get dates np_dates = x_diff[np_idx] # get values np_values = diff_y[np_idx] return np_dates, np_values ############## ############## def __handle_round_date(decyear): mjd = np.round(at.decyear2mjd(decyear), decimals=2) (mday, month, iyear, _ut) = at.mjd2cal(mjd) return (mday, month, iyear) ############## # detrend H_offset = {} for delta_day in ldelta_day: if verbose: print("-- detrend_median with delta_day=%d" % delta_day) gts_dtm = self.detrend_median(delta_day=delta_day) if gts_dtm is None: gts_dtm = self.detrend() median_neu = np.median(np.fabs(gts_dtm.differentiate().data[:, 1:4]), axis=0) if verbose: print("-- median daily scattering NEU (mm): ", median_neu * 1.E3) for lbda in search_lbda: edge_ts = gts_dtm.edge_filter(lbda, verbose=verbose) for idx in l_idx_component: np_dates, np_values = __get_offset_date_and_value( edge_ts.data[:, 0], edge_ts.data[:, idx], median_neu[idx - 1] * threshold) new_gts.offsets_dates = np_dates if verbose or log: if verbose: print( "-- suspected offsets for component %s and lbda = %d" % (H_idx_component[idx], lbda)) for date, value in zip(np_dates, np_values): (mday, month, iyear) = __handle_round_date(date) mjd = at.decyear2mjd(date) sstr_date = ("%4d_%02d_%02d" % (iyear, month, mday)) no_EQ = True if eq_file is not None: i = 0 for mjd_eq in np_eq_mjd: if np.fabs(mjd_eq - mjd) <= 1.: if verbose: print("%.6lf %10.3lf (%4d-%02d-%02d) EQ Mw %.1lf %6.2lf %6.2lf " % \ (date,value*1.E3,iyear,month,mday, np_eq_magnitude[i],np_eq_lon[i],np_eq_lat[i])) if sstr_date in H_offset.keys(): H_offset[sstr_date].append([ idx, value, lbda, np_eq_magnitude[i], delta_day ]) else: H_offset[sstr_date] = [[ idx, value, lbda, np_eq_magnitude[i], delta_day ]] no_EQ = False i = i + 1 if no_EQ and verbose: print("%.6lf %10.3lf (%4d-%02d-%02d)" % (date, value * 1.E3, iyear, month, mday)) if no_EQ: if sstr_date in H_offset.keys(): H_offset[sstr_date].append( [idx, value, lbda, 0, delta_day]) else: H_offset[sstr_date] = [[ idx, value, lbda, 0, delta_day ]] if log: for sstr_date in H_offset.keys(): # open log file log_filename = ("%s_Mw%02d.dat" % (sstr_date, H_offset[sstr_date][0][-2] * 10)) try: flog = open(log_filename, 'a+') except: from colors import red return_str = red("[PYACS WARNING] Could not create file: %s" % (log)) print(return_str) print(H_offset[sstr_date]) np_offset = np.array(H_offset[sstr_date]).reshape(-1, 5) # list lbda l_lbda = list(set(np_offset[:, 2].tolist())) # list dalta_day l_delta_day = list(set(np_offset[:, 4].tolist())) # loop lbda for lbda in sorted(l_lbda): # loop delta_day for delta_day in l_delta_day: # empty line to write as a list lw = [ self.lon, self.lat, 0., 0., 1., 1., 0., ("%s_%03d" % (self.code, lbda)), 0 ] # get results given ldba lindex = np.where( (np.fabs(np_offset[:, 2] - lbda) < 1.E-3) & (np.fabs(np_offset[:, 4] - delta_day) < 1.E-3)) offset = np_offset[lindex].reshape(-1, 5) for i in np.arange(offset.shape[0]): if offset[i, 0] == 1.: lw[3] = offset[i, 1] * 1.E3 if offset[i, 0] == 2.: lw[2] = offset[i, 1] * 1.E3 if offset[i, 0] == 3.: lw[7] = ("%s %6.2lf " % (lw[7]), offset[i, 1] * 1.E3) lw[8] = offset[i, 4] flog.write( "%10.4lf %10.4lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %s %03d\n" % tuple(lw)) flog.close() return new_gts