def gts(self, method, *args, **kwargs): ################################################################### """ apply a gts method to all Gts instance of the current Sgts object :param method: Gts method to be applied as string :param *arg: arguments for the Gts method to be applied :param **kwarg: keyword arguments for the Gts method to be applied :example : ts.gts('detrend',periods=[2010.0,2013.0]) """ from pyacs.gts.Sgts import Sgts verbose = kwargs.get('verbose', False) new_ts = Sgts(read=False) lsite = self.lcode() for site in sorted(lsite): if verbose: print('-- processing ', site) try: func = getattr(self.__dict__[site], method) new_ts.append(func(*args, **kwargs)) except: print( '!!!WARNING: problem with method %s on gts %s. Removed from output' % (method, site)) return (new_ts)
def add_offsets_dates(self,dates,verbose=False): ################################################################### """ add_offsets_dates to every Gts in current Sgts """ # import from pyacs.gts.Sgts import Sgts from pyacs.gts.Gts import Gts New_Sgts=Sgts(read=False) for gts in self.lGts(): if verbose:print("-- Processing ",gts.code) try: new_gts=gts new_gts.offsets_dates=dates except (RuntimeError, TypeError, NameError): print("!!! Error processing ",gts.code) continue if isinstance(new_gts,Gts): New_Sgts.append(new_gts) else: print("!!! Error processing ",gts.code, "!!! No time series created.") return( New_Sgts )
def sel_rectangle(self, bounds, verbose=True): ################################################################### """ selects the time series for sites within a rectangles :param bounds: [lon_min,lon_max,lat_min,lat_max] :pram verbose: verbose mode :return: a new Sgts instance """ # import from pyacs.gts.Sgts import Sgts [lon_min, lon_max, lat_min, lat_max] = bounds new_Sgts = Sgts(read=False) for gts in self.lGts(): current_lon = gts.lon current_lat = gts.lat if current_lon >= lon_min and current_lon <= lon_max <= lon_max and current_lat >= lat_min and current_lat <= lat_max: if verbose: print("-- ", gts.code, " selected") new_Sgts.append(gts) return (new_Sgts)
def get_unr(self, lcode): """ :param lcode: list of GNSS site codes to be downloaded from UNR web site :return: new Sgts instance """ # import from pyacs.gts.Gts import Gts from pyacs.gts.Sgts import Sgts # initialize Sgts ts = Sgts(read=False) # loop on sites for code in lcode: print("-- downloading %s from UNR" % code) try: ts.append(Gts().get_unr(code)) except: print("!!!ERROR downloading %s from UNR" % code) # return return ts
def obs_tensor2sgts(T_OBS_RAW, np_names_t_obs, np_obs_date_s, verbose=True): """ Converts a obs_tensor object into a Sgts """ # import import numpy as np from pyacs.gts.Gts import Gts from pyacs.gts.Sgts import Sgts import pyacs.lib.astrotime as at # import pyeq.message.message as MESSAGE # import pyeq.message.verbose_message as VERBOSE # import pyeq.message.error as ERROR # import pyeq.message.debug_message as DEBUG # initialize Sgts sgts = Sgts(read=False) # loop on sites for i in np.arange(np_names_t_obs.shape[0]): code = np_names_t_obs[i] #DEBUG('converting %s ' % code) # get the index of valid dates lindex = np.where(np.isfinite(T_OBS_RAW[:, i, 0]))[0] data = np.zeros((lindex.shape[0], 10)) # obs_tensor is ENU and Gts are NEU data[:, 2] = T_OBS_RAW[lindex, i, 0] * 1E-3 data[:, 1] = T_OBS_RAW[lindex, i, 1] * 1E-3 data[:, 3] = T_OBS_RAW[lindex, i, 2] * 1E-3 data[:, 5] = T_OBS_RAW[lindex, i, 3] * 1E-3 data[:, 4] = T_OBS_RAW[lindex, i, 4] * 1E-3 data[:, 6] = T_OBS_RAW[lindex, i, 5] * 1E-3 data[:, 0] = at.datetime2decyear( at.seconds2datetime(np_obs_date_s[lindex])) sgts.append(Gts(code=code, data=data)) #VERBOSE("converted %d time series " % ( len( sgts.lcode() )) ) return sgts
def sub(self, lexclude=[], linclude=[]): ################################################################### """ Returns a new Sgts instance excluding Gts with code in lexclude and keeping Gts with code in include :param lexclude: list of sites to be excluded :param linclude: list of sites to be included, excluding all other. """ from pyacs.gts.Sgts import Sgts if linclude != []: sub_Sgts = Sgts(read=False) for code in linclude: if (code not in lexclude) and (self.has_ts(code)): sub_Sgts.append(self.__dict__[code].copy()) else: sub_Sgts = self.copy() for code in lexclude: if self.has_ts(code): sub_Sgts.delts(code) return (sub_Sgts)
# USING P. REBISCHUNG SINEX LIBRARY MESSAGE("Reading IGS psd file using P. Rebischung sinex library: %s" % args.psd) psd = sinex.read(args.psd) else: psd = None ################################################################### # STARTS LOOP FOR EACH SINEX FILES ################################################################### # H_res_helmert H_res_helmert = {} # Sgts instance for reference sites residual time series l_res_ts = Sgts(read=False) # initialize sts sts = Sgts(read=False) ########################################################################## MESSAGE("START OF PROCESSING - LOOP ON SINEX FILES", level=2) ########################################################################## index_sinex = 0 for sinex_name in lsinex: # Helmert and sites covariance initialization T = None H_COV = None
#!/usr/bin/env python import pyacs.message.message as MESSAGE import logging logging.getLogger("my_logger").setLevel(logging.WARNING) MESSAGE("Welcome to pyacs interactive environment") import sys, os MESSAGE("Importing pyacs core module") import pyacs MESSAGE("pyacs veriosn: %s" % pyacs.__version__) MESSAGE("Importing pyacs.gts module") from pyacs.gts.Sgts import Sgts from pyacs.gts.Gts import Gts MESSAGE("Importing class Velocity_Field from pyacs.lib.vel_field module as vf") from pyacs.lib.vel_field import Velocity_Field as vf MESSAGE("Importing numpy as np") import numpy as np MESSAGE("Importing matplotlib.pyplot as plt") import matplotlib.pyplot as plt MESSAGE("Importing pyacs.lib.astrotime as at") import pyacs.lib.astrotime as at MESSAGE("Importing pyacs.lib.coordinates as coo") import pyacs.lib.coordinates as coo MESSAGE('Trying to read time series files') ts = Sgts()
#!/usr/bin/env python # pos files to be analyzed pos_dir = '/Users/nocquet/projets/2018/soam_proc/run_pjarrin_12_12_2018/pos' # outdir outdir = '/Users/nocquet/projets/2018/soam_proc/pyacs_analysis_velocity_field' # outfiles cgps_file = 'vel_cgps.dat' sgps_file = 'vel_sgps.dat' ssgps_file = 'vel_ssgps.dat' from pyacs.gts.Sgts import Sgts ts = Sgts(ts_dir=pos_dir) # select sites impacted by the 2016/04/16 EQ bounds_eq_2016 = [-83, -74, -3.5, 2.5] period = [1990., 2016.29] ts_eq_2016 = ts.sel_rectangle(bounds_eq_2016, verbose=True) # loop on sites for gts in ts.lGts(): print("-- Processing ", gts.code) # remove post EQ data if it is in the selected area
def same_site(self, dc=10, in_place=True, verbose=False): ################################################################### """ Check that all gts in the current Sgts are actually the same site. If a given time series is found to be of two separate sites, then a new gts is added to the return Sgts instance. param dc: critical distance to decide to split the time series param in_place: if True modify current Sgts, False retuen a new Sgts param verbose: verbose mode return: a new Sgts instance """ # import import numpy as np from pyacs.gts.Sgts import Sgts from pyacs.gts.Gts import Gts if not in_place: new_Sgts = Sgts(read=False) # start loop on sites lcode = self.lcode() for site in lcode: if verbose: print('-- Processing ', site) my_ts = self.__dict__[site].copy() if my_ts.data_xyz is not None: data = my_ts.data_xyz[:, 1:4] ddata = np.copy(my_ts.data_xyz[:, 1:4]) else: # if no data_xyz go to next gts print( "!!! WARNING: data_xyz attribute required for method same_site and not found gts %s" % (site)) # ensure median calculation if np.mod(data.shape[0], 2) == 0: # duplicates the last date ddata = np.vstack((ddata, ddata[-1, :])) median = np.median(ddata, axis=0) dist_data = np.sqrt(np.sum((data - median)**2, axis=1)) lindex = np.where(dist_data > dc * 1.E3) # case gts needs to be split if len(lindex[0]) > 0: # create a new code new_code = my_ts.code[:3] + '_' if new_code in self.lcode(): print( "!!! ERROR: try to create a new gts with code %s and it already exists." % (new_code)) new_code = my_ts.code[:2] + '__' if verbose: print( "-- time series for site %s appears to include different sites because there are coordinates at %d dates %.1lf km from the median position" % (site, len(lindex), np.max(ddata) * 1.E-3)) print( "-- %s time series will be split into code %s and code %s" % (site, site, new_code)) # create a new gts new_gts = Gts(code=new_code, data_xyz=np.copy(my_ts.data_xyz[lindex])) new_gts.xyz2neu(corr=True) # remove the line from my_ts my_ts.data_xyz = np.delete(my_ts.data_xyz, lindex, axis=0) my_ts.xyz2neu(corr=True) # update the ouput if in_place: self.append(new_gts) else: new_Sgts.append(new_gts) if in_place: self.__dict__[site] = my_ts else: new_Sgts.append(my_ts) if in_place: return self else: return new_Sgts
def medvel(self, outdir=None, verbose=False): ################################################################### """ Automatic velocity estimates using median estimator. The code is adapted from the MIDAS approach (Blewitt et al., 2016). medvel fills the velocity attribute of every Gts from the current Sgts instance. returns the modified Sgts instance Optionally, if outdir option is provided, writes the results in outdir :param: outdir: output directory, default None :param: verbose: boolean, verbose mode :param: warning: output warning file :reference: Blewitt, G., Kreemer, C., Hammond, W. C., & Gazeaux, J. (2016). MIDAS robust trend estimator for accurate GPS station velocities without step detection. Journal of Geophysical Research: Solid Earth, 121(3), 2054-2068. """ # import from pyacs.gts.Sgts import Sgts import sys, os # initialize new Sgts new_sgts = Sgts(read=False) # create output directory if outdir is not None: if os.path.isdir(outdir): print('!!! ', outdir, ' directory already exists') sys.exit() elif os.path.isfile(outdir): print('!!! ', outdir, ' file already exists') sys.exit() else: if verbose: print('-- creating ', outdir) os.mkdir(outdir) # output file names out_cgps = outdir + '/vel_cgps.dat' out_sgps = outdir + '/vel_sgps.dat' out_cgps_up = outdir + '/vel_cgps_up.dat' out_sgps_up = outdir + '/vel_sgps_up.dat' # open warning file fwarning = open(outdir + '/warning.dat', 'w+') # start loop on sites lcode = self.lcode() for site in lcode: if verbose: print('-- Processing ', site) # check whether there is at least one year of data if (self.__dict__[site].data[-1, 0] - self.__dict__[site].data[0, 0]) < 1.0: if verbose: print("-- Less than one year of data for site: %s" % site) if outdir is not None: fwarning.write("-- Less than one year of data for site: %s\n" % site) continue # check whether there are at least three data if (self.__dict__[site].data.shape[0]) < 3: if verbose: print("-- Less than 3 data for site: %s" % site) if outdir is not None: fwarning.write("-- Less than 3 data for site: %s\n" % site) # continue # detrended = self.__dict__[site].detrend_median(auto=True) if (detrended.velocity is None): print("-- Problem in detrend_median for site : %s " % site) continue if (outdir is not None): detrended.save_velocity(out_cgps, verbose=verbose) detrended.save_velocity(out_cgps_up, verbose=verbose, up=True) new_sgts.append(detrended) return (new_sgts)
# TESTS FOR gts subpackage from pyacs.gts.Sgts import Sgts as Sgts import numpy as np from pyacs.gts.lib.outliers import find_outliers_sliding_window dir_test = 'data/ts' dir_output = 'output' # Reading ts files ts = Sgts(dir_test) # select site code = ts.lcode()[0] # test plot basic ts.__dict__[code].plot(save=dir_output + '/' + code + '_01.png', verbose=True, title='ex_01: raw time series') # test outliers percentage ts.__dict__[code]\ .find_outliers_percentage()\ .plot(save=dir_output+'/'+code+'_02.png',verbose=True, title='ex_02: outliers (percentage method)') # test outliers smoothing time windows ts.__dict__[code]\ .find_outliers_sliding_window()\ .plot(save=dir_output+'/'+code+'_03.png',verbose=True, title='ex_03: outliers (sliding window method)')
def frame(self, frame=None, euler=None, w=None, verbose=False): ################################################################### """ Rotates the time series according to an Euler pole. User must provide either frame, euler or w. :param frame: str, implemented values are 'soam','nas','nazca','inca','nas_wrt_soam','inca_wrt_soam'. :param euler: Euler values provided either as a \ string 'euler_lon/euler_lat/euler_w', a list [euler_lon,euler_lat,euler_w] or \ a 1D numpy array np.array([euler_lon,euler_lat,euler_w]) :param w: rotation rate vector in rad/yr, provided either as a \ string 'wx/wy/wz', a list [wx,wy,wz] or \ a 1D numpy array np.array([wx,wy,wz]) :return: the new Sgts instance in new frame :ref: All values for frames are from Nocquet et al., Nat Geosc., 2014. """ # import import numpy as np import pyacs.lib.euler from pyacs.gts.Sgts import Sgts from pyacs.gts.Gts import Gts # check arguments are OK if [frame, euler, w].count(None) != 2: print('!!! ERROR: define either argument frame, euler or w ') return (None) # Euler poles taken from pygvel_pole_info.py lEuler = {} # from Jarrin et al., 2022 lEuler['soam'] = [-133.29, -18.41, 0.121] lEuler['nas'] = [-133.999, 12.404, 0.158] # from Nocquet et al., 2021 lEuler['soam_nocquet_2014'] = [-132.21, -18.83, 0.121] lEuler['nas_nocquet_2014'] = [-97.52, 6.48, 0.359] lEuler['nazca_nocquet_2014'] = [-94.4, 61.0, 0.57] lEuler['inca_nocquet_2014'] = [-103.729, -1.344, 0.1659] lEuler['nas_wrt_soam_nocquet_2014'] = [-83.40, 15.21, 0.287] lEuler['inca_wrt_soam_nocquet_2014'] = [-63.76, 22.47, 0.092] # check frame case is OK if (frame not in list(lEuler.keys())) and (frame is not None): print("!!! ERROR: requested frame ", frame, " not known") print("!!! ERROR: available frames are: ", list(lEuler.keys())) return (None) # initialize new gts New_Sgts = Sgts(read=False) # convert to Euler vector whatever the provided argument # case frame if frame is not None: euler_vector = np.array(lEuler[frame]) # case w as rotation rate vector if w != None: if (isinstance(w, str)) and '/' in w: w = np.array(list(map(float, w.split('/')))) if isinstance(w, list): w = np.array(w) if not isinstance(w, np.ndarray): print('!!! ERROR: argument w not understood: ', w) return (None) euler_vector = np.array(pyacs.lib.euler.rot2euler([w[0], w[1], w[2]])) # case euler vector if euler is not None: if (isinstance(euler, str)) and '/' in euler: euler = np.array(list(map(float, euler.split('/')))) if isinstance(euler, list): euler = np.array(euler) if not isinstance(euler, np.ndarray): print('!!! ERROR: argument euler not understood: ', euler) return (None) euler_vector = np.array(euler) # converts the gts for gts in self.lGts(): if verbose: print("-- Processing ", gts.code) try: new_gts = gts.remove_pole(euler_vector, pole_type='euler', in_place=False, verbose=verbose) except (RuntimeError, TypeError, NameError): print("!!! Error processing ", gts.code) continue if isinstance(new_gts, Gts): New_Sgts.append(new_gts) else: print("!!! Error processing ", gts.code, "!!! No time series created.") return (New_Sgts)