def remove_pole(self, pole, pole_type='euler', in_place=False, verbose=True): """ remove velocity predicted by an Euler pole or a rotation rate vector from a time series pole is a 1D array with 3 values requires self.lon & self.lat attributes to have been filled before if in_place = True then replace the current time series """ import numpy as np from pyacs.gts.Gts import Gts import inspect # after this method .data and .data_xyz are not consistent so .data_xyz is set to None self.data_xyz = None ########################################################################### # 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) ########################################################################### if (self.lon is None) or (self.lat is None): print( "!!! ERROR: lon & lat needs to be properly filled to use this method." ) return () from pyacs.lib.gmtpoint import GMT_Point M = GMT_Point(code=self.code, lon=self.lon, lat=self.lat, Ve=0., Vn=0., SVe=0., SVn=0.) # N=M.substract_pole(pole,pole_type) N = M.pole(W=pole, SW=None, type_euler='euler', option='predict') vel_neu = np.array([N.Vn, N.Ve, 0.]) * 1E-3 if verbose: print("-- Removing velocity (NEU)", vel_neu * 1.E3) new_Gts = self.remove_velocity(vel_neu) if in_place: self.data = new_Gts.data.copy() return (new_Gts)
def save_velocity(self, gmt_file, verbose=True, comment=None, up=False): ################################################################### """ Appends velocity estimates (with uncertainties) to a gmt psvelo file :param gmt_file: output gmt psvelo file (will append if gmt_file already exists) :param verbose: verbose mode (boolean) :param comment: comment as a string. '# ' is pre-prended to comment if not provided :param up: boolean. If True, then Ve, SVe and SVen are set to 0 and Vu and Vu are written as 4-th and 6-th fields :return: the current Gts instance """ # comment if comment is not None: if comment[0] != '#': comment = '# ' + comment else: comment = '' # import from pyacs.lib.vel_field import Velocity_Field from pyacs.lib.gmtpoint import GMT_Point import os.path # init Velocity_Field() instance vel_field = Velocity_Field() if os.path.isfile(gmt_file): vel_field.read(gmt_file, verbose=False) [vn, ve, vu, svn, sve, svu] = self.velocity * 1000.0 if not up: M = GMT_Point(code=self.code + ' ' + comment, lon=self.lon, lat=self.lat, Ve=ve, Vn=vn, SVe=sve, SVn=svn, SVen=0.0) else: M = GMT_Point(code=self.code + ' ' + comment, lon=self.lon, lat=self.lat, Ve=0.0, Vn=vu, SVe=0.0, SVn=svu, SVen=0.0) vel_field.add_point(M) vel_field.write(gmt_file, verbose=False) return (self)
def sel_radius(self, center, range, verbose=True): ################################################################### """ selects the time series for sites within a radius within range around center :param center: [lon, lat] in decimal degree. center for selection :param range: [min_radius, max_radius] in km. Can also be a site code or simply max_radius :pram verbose: verbose mode :return: a new Sgts instance """ # import import pyacs.message.message as MESSAGE import pyacs.message.verbose_message as VERBOSE import pyacs.message.error as ERROR import pyacs.message.warning as WARNING import pyacs.message.debug_message as DEBUG from pyacs.lib.gmtpoint import GMT_Point # decipher center if isinstance(center, str): [lon_center, lat_center] = [self.__dict__[center].lon, self.__dict__[center].lat] # decipher range if isinstance(range, float): range = [0, range] # start loop CNTR = GMT_Point(code='XXXX', lon=lon_center, lat=lat_center, he=0.) lsel = [] for code in self.lcode(): XXXX = GMT_Point(code='XXXX', lon=self.__dict__[code].lon, lat=self.__dict__[code].lat, he=0.) sdistance = CNTR.spherical_distance(XXXX) / 1.E3 if sdistance >= range[0] and sdistance < range[1]: # print("%s %s : %10.1lf " % (EQ__.code,code,EQ__.spherical_distance(XXXX)/1.E3)) lsel.append(code) # ensure the provided site is included if range[0] == 0 if int(range[0]) == 0 and not (center in lsel): lsel.append(center) return self.sub(linclude=lsel)
def spherical_baseline_length_rate(slon, slat, sve, svn, elon, elat, eve, evn, sigma=None, verbose=False): ################################################################### """ calculates the baseline (great circle) length rate of change between two points :param slon,slat: coordinates of profile start point (decimal degrees) :param sve,svn: east and north components of start point (mm/yr) :param elon,elat: coordinates of profile end point (decimal degrees) :param eve,evn: east and north components of end point (mm/yr) :param sigma: list of velocities uncertainties: [sig_sve, sig_svn, corr_sven, sig_eve, sig_evn, corr_even] :return : length, rate, 1D strain rate """ # Rt in meters Rt = 6371.0E3 # #print('slon, slat, sve, svn, elon, elat, eve, evn',slon, slat, sve, svn, elon, elat, eve, evn) #print('sigma ', sigma ) # import import numpy as np from pyacs.lib import vectors from pyacs.lib.gmtpoint import GMT_Point from pyacs.lib import glinalg from pyacs.lib import euler (xi, yi, zi) = geo2xyz(np.radians(slon), np.radians(slat), 0.0 , unit='radians') Xi = np.array([xi, yi, zi]) #print('Xi' , Xi) (xs, ys, zs) = geo2xyz(np.radians(elon), np.radians(elat), 0.0 , unit='radians') Xs = np.array([xs, ys, zs]) #print('Xs' , Xs) POLE = vectors.vector_product(Xi, Xs) #print( euler.rot2euler(POLE[0], POLE[1], POLE[2]) ) POLE = vectors.normalize(POLE) # along / transverse great circle component start point R = mat_rot_general_to_local(np.radians(slon), np.radians(slat), unit='radians') OM = np.array([xi, yi, zi]) OM = vectors.normalize(OM) unit_parallele_xyz = vectors.vector_product(POLE, OM) unit_parallele_enu = np.dot(R, unit_parallele_xyz) #print('unit_parallele_enu' , unit_parallele_enu*10. ) sv_parallele = sve * unit_parallele_enu[0] + svn * unit_parallele_enu[1] sv_perpendicular = sve * unit_parallele_enu[1] - svn * unit_parallele_enu[0] # covariance if sigma is not None: sig = np.array([ sigma[0] , sigma[1] ]) corr = np.eye(2) corr[0,1] = sigma[2] corr[1,0] = sigma[2] cov = glinalg.corr_to_cov(corr, sig ) # rotation angle_rad = np.arctan2( unit_parallele_enu[1] , unit_parallele_enu[2] ) #print('angle_rad in deg ' , np.degrees( angle_rad )) rot = np.zeros((2,2)) rot[0,0] = np.cos( angle_rad ) rot[0,0] = np.cos( angle_rad ) rot[1,1] = np.cos( angle_rad ) rot[0,1] = -np.sin( angle_rad ) rot[1,0] = np.sin( angle_rad ) # apply rotation vcv_en = np.dot( rot , np.dot( cov , rot.T) ) s_sv_parallel = np.sqrt( vcv_en[0,0] ) # along / transverse great circle component end point R = mat_rot_general_to_local(np.radians(elon), np.radians(elat), unit='radians') OM = np.array([xs, ys, zs]) OM = vectors.normalize(OM) unit_parallele_xyz = vectors.vector_product(POLE, OM) unit_parallele_enu = np.dot(R, unit_parallele_xyz) #print('unit_parallele_enu' , unit_parallele_enu*10. ) ev_parallele = eve * unit_parallele_enu[0] + evn * unit_parallele_enu[1] ev_perpendicular = eve * unit_parallele_enu[1] - evn * unit_parallele_enu[0] # covariance if sigma is not None: sig = np.array([ sigma[3] , sigma[4] ]) corr = np.eye(2) corr[0,1] = sigma[5] corr[1,0] = sigma[5] cov = glinalg.corr_to_cov(corr, sig ) # rotation angle_rad = np.arctan2( unit_parallele_enu[1] , unit_parallele_enu[2] ) #print('angle_rad in deg ' , np.degrees( angle_rad )) rot = np.zeros((2,2)) rot[0,0] = np.cos( angle_rad ) rot[0,0] = np.cos( angle_rad ) rot[1,1] = np.cos( angle_rad ) rot[0,1] = -np.sin( angle_rad ) rot[1,0] = np.sin( angle_rad ) # apply rotation vcv_en = np.dot( rot , np.dot( cov , rot.T) ) s_ev_parallel = np.sqrt( vcv_en[0,0] ) # great circle arc length MS = GMT_Point(lon=slon, lat=slat) ME = GMT_Point(lon=elon, lat=elat) length_arc = MS.spherical_distance(ME) # lengthening in mm/yr length_rate = ev_parallele - sv_parallele # 1D strain rate in 1/yr strain_rate = length_rate * 1E-3 / length_arc # case covariance if sigma is None: return length_arc , length_rate , strain_rate else: sig_v = np.sqrt( s_sv_parallel**2 + s_ev_parallel**2 ) sig_strain_rate = sig_v * 1.E-3 / length_arc return length_arc , length_rate , strain_rate, sig_v, sig_strain_rate
def read(cls, file_name=None, lexclude=[], lonly=[], verbose=False): ################################################################### """ Reads a GMT psvelo file """ # import import numpy as np # init vf = Velocity_Field() # fake 4-letters code generation using hexadecimal def __gen_fake_code__(n): FAKE = [] for i in np.arange(n): fake_code = ("%4s" % hex(i).split('x')[-1].replace('L', '')).replace( ' ', '0') FAKE.append(fake_code.upper()) return (np.array(FAKE)) # reads psvelo file if verbose: print("-- Reading GMT psvelo file: %s " % file_name) try: np_vel = np.array(np.mat(np.genfromtxt(file_name, comments='#'))) except: raise IOError("!!! Could not read file: %s" % file_name) # empty psvelo file if np_vel.size == 0: return (vf) if (np_vel.shape[1] == 8): if verbose: print("-- file %s has 8 columns" % file_name) np_vel = np.delete(np_vel, -1, axis=1) np_code = np.array( np.mat( np.genfromtxt(file_name, comments='#', usecols=(7), dtype=str))).flatten() elif (np_vel.shape[1] == 3): if verbose: print("-- file %s has 3 columns" % file_name) np_vel = np.delete(np_vel, -1, axis=1) np_code = np.array( np.mat(np.genfromtxt(file_name, comments='#', usecols=(2)))).flatten() elif (np_vel.shape[1] not in [3, 8]): np_code = __gen_fake_code__(np_vel.shape[0]) else: raise IOError("!!! Could not decipher file content: %s", file_name) # populates velocity field from pyacs.lib.gmtpoint import GMT_Point lgmt_points = [] for i in np.arange(np_vel.shape[0]): code = np_code[i] if np_vel.shape[1] >= 7: lon, lat, Ve, Vn, SVe, SVn, SVen = np_vel[i, :] M = GMT_Point(lon=lon, lat=lat, Ve=Ve, Vn=Vn, SVe=SVe, SVn=SVn, SVen=SVen, code=code) else: lon, lat = np_vel[i, :] M = GMT_Point(lon=lon, lat=lat, code=code) if verbose: M.get_info(display=True) # tests whether site will be added if lonly != []: if M.code in lonly: lgmt_points.append(M) else: if lexclude != []: if M.code not in lexclude: lgmt_points.append(M) else: lgmt_points.append(M) vf.file_name = file_name vf.sites = lgmt_points return vf
def proj_profile(self, slon, slat, elon, elat, d, save=None, verbose=False): ################################################################### """ project velocity components along a great circle defined by initial/stop points (slon,slat,elon,elat) :param slon,slat: coordinates of profile start point (decimal degrees) :param elon,elat: coordinates of profile end point (decimal degrees) :param d : maximum distance for a point to be considered :param save : output file name (optional) :return : numpy 1D array with np_code, np_distance_along_profile, np_distance_to_profile , \ np_Ve , np_Vn , np_SVe , np_SVn , \ np_v_parallele , np_v_perpendicular , \ np_sigma_v_parallele , np_sigma_v_perpendicular , np_lazimuth """ lcode = [] ldistance_along_profile = [] ldistance_to_profile = [] lVe = [] lVn = [] lSVe = [] lSVn = [] lv_parallele = [] lv_perpendicular = [] lsigma_v_parallele = [] lsigma_v_perpendicular = [] lazimuth = [] # Rt in meters Rt = 6371.0E3 # import import numpy as np from pyacs.lib import coordinates as Coordinates from pyacs.lib import vectors from pyacs.lib.gmtpoint import GMT_Point (xi, yi, zi) = Coordinates.geo2xyz(np.radians(slon), np.radians(slat), 0.0) Xi = np.array([xi, yi, zi]) MS = GMT_Point(lon=slon, lat=slat) (xs, ys, zs) = Coordinates.geo2xyz(np.radians(elon), np.radians(elat), 0.0) Xs = np.array([xs, ys, zs]) ME = GMT_Point(lon=elon, lat=elat) length_arc = MS.spherical_distance(ME) / 1000.0 POLE = vectors.vector_product(Xi, Xs) POLE = vectors.normalize(POLE) # LOOP ON SITES H_distance = {} for M in self.sites: if verbose: print('-- projecting ', M.code) (x, y, z) = Coordinates.geo2xyz(np.radians(M.lon), np.radians(M.lat), 0.0) R = Coordinates.mat_rot_general_to_local(np.radians(M.lon), np.radians(M.lat), unit='radians') OM = np.array([x, y, z]) OM = vectors.normalize(OM) unit_parallele_xyz = vectors.vector_product(POLE, OM) unit_parallele_enu = np.dot(R, unit_parallele_xyz) v_parallele = M.Ve * unit_parallele_enu[ 0] + M.Vn * unit_parallele_enu[1] v_perpendicular = M.Ve * unit_parallele_enu[ 1] - M.Vn * unit_parallele_enu[0] azimuth = np.arctan2(unit_parallele_enu[0], unit_parallele_enu[1]) # longitude of M in the system having AOB as equator and P as north pole # to do that, we write the XYZ coordinates of M in the POLE/EQUATOR frame # x_m = vectors.scal_prod(OM, vectors.normalize(Xi)) y_m = vectors.scal_prod( OM, vectors.normalize(vectors.vector_product(Xi, -POLE))) longitud_m = np.arctan2(y_m, x_m) distance_along_profile = longitud_m * Rt # distance to profile is obtained from the latitude in POLE/EQUATOR frame z_m = vectors.scal_prod(OM, POLE) latitud_m = np.arcsin(z_m) # distance_to_profile= np.fabs(latitud_m) * Rt distance_to_profile = latitud_m * Rt # now propagates the vcv go get the uncertainty in each direction # we use the value of local azimuth of profile and the law of variance propagation local_R = np.array([[np.cos(azimuth + np.pi / 2.), np.sin(azimuth + np.pi / 2.)], \ [-np.sin(azimuth + np.pi / 2.), np.cos(azimuth + np.pi / 2.)]]) cov = M.SVe * M.SVn * M.SVen vcv_en = np.array([[M.SVe**2, cov], [cov, M.SVn**2]]) vcv_profile = np.dot(np.dot(local_R, vcv_en), local_R.T) sigma_v_parallele = np.sqrt(vcv_profile[0, 0]) sigma_v_perpendicular = np.sqrt(vcv_profile[1, 1]) if (np.fabs(distance_to_profile / 1000.0) < d) and (distance_along_profile / 1000.0 >= 0.0) and ( distance_along_profile / 1000.0 <= length_arc): lcode.append(M.code) ldistance_along_profile.append(distance_along_profile / 1000.0) ldistance_to_profile.append(distance_to_profile / 1000.0) lVe.append(M.Ve) lVn.append(M.Vn) lSVe.append(M.SVe) lSVn.append(M.SVn) lv_parallele.append(v_parallele) lv_perpendicular.append(v_perpendicular) lsigma_v_parallele.append(sigma_v_parallele) lsigma_v_perpendicular.append(sigma_v_perpendicular) lazimuth.append(np.degrees(azimuth)) H_distance[distance_along_profile] = \ ("%4s %10.3lf %10.3lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.1lf\n" \ % (M.code, distance_along_profile / 1000.0, distance_to_profile / 1000.0, M.Ve, M.Vn , M.SVe, M.SVn, v_parallele, v_perpendicular, sigma_v_parallele, sigma_v_perpendicular, np.degrees(azimuth))) if save is not None: print("-- writing results to ", save) fs = open(save, 'w') fs.write( "#site profile_distance_to_A (km) distance_to_profile (km) Ve Vn SVe SVn V_parallele V_perpendicular SV_parallele SV_perpendicular azimuth \n" ) fs.write( "#-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n" ) for distance in sorted(H_distance.keys()): fs.write("%s" % H_distance[distance]) fs.close() np_distance_along_profile = np.array(ldistance_along_profile) lindex = np.argsort(np_distance_along_profile) np_code = np.array(lcode, dtype=str)[lindex] np_distance_along_profile = np_distance_along_profile[lindex] np_distance_to_profile = np.array(ldistance_to_profile)[lindex] np_Ve = np.array(lVe)[lindex] np_Vn = np.array(lVn)[lindex] np_SVe = np.array(lSVe)[lindex] np_SVn = np.array(lSVn)[lindex] np_v_parallele = np.array(lv_parallele)[lindex] np_v_perpendicular = np.array(lv_perpendicular)[lindex] np_sigma_v_parallele = np.array(lsigma_v_parallele)[lindex] np_sigma_v_perpendicular = np.array(lsigma_v_perpendicular)[lindex] np_lazimuth = np.array(lazimuth)[lindex] return np_code, np_distance_along_profile, np_distance_to_profile , \ np_Ve , np_Vn , np_SVe , np_SVn , \ np_v_parallele , np_v_perpendicular , \ np_sigma_v_parallele , np_sigma_v_perpendicular , np_lazimuth
################################################################### # CASE PLL ################################################################### if args.pll is not None: from pyacs.lib.gmtpoint import GMT_Point W[2,0] = -W[2,0] vel = VF() # decipher pll option i=1 for pll in args.pll: [lon,lat] = list( map(float, pll.split('/')[-2:]) ) M=GMT_Point(code=("X%03d" % i), lon=lon,lat=lat,Ve=0.,Vn=0.,SVe=0.,SVn=0.,SVen=0.) vel.add_point(M) i = i + 1 # prediction new_vel = vel.substract_pole(W, type_euler='euler') # print results if args.ovel is not None: my_comment = ("# Euler pole (%8.4lf %8.4lf %8.4lf) prediction" % tuple(W.flatten().tolist()) ) new_vel.write(args.ovel , comment='# ') else: for code in new_vel.lcode(): new_vel.print_info_site(code, verbose=False)