def test_geo2XYZ(): X, Y, Z = COO.geo2xyz(-112.567, 43.36, 27.2, unit='dec_deg') # gamit convertc results -1782430.03490 -4288974.18902 4356684.78382 assert np.sqrt((X - -1782430.03490)**2) < 0.00002 assert np.sqrt((Y - -4288974.18902)**2) < 0.00002 assert np.sqrt((Z - 4356684.78382)**2) < 0.00002
def substract_pole(self,W=None,type='rot'): """ Substract the velocity predicted by an Euler pole or a rotation rate vector """ import numpy as np if isinstance(W,list):W=np.array(W) if len(W.shape)==1:W=W.reshape(3,1) import pyacs.lib.coordinates as Coordinates import pyacs.lib.euler as euler import numpy as np ltype=['euler','rot'] # type is either Euler pole (long. lat in dec. degrees and deg/Myr or cartesian rotation rate vector in rad/yr) if (type not in ltype): print("==> type should be either 'euler' or 'rot' ") if (type == 'euler'): # convert to rotation rate vector (lon, lat, omega)=(W[0,0],W[1,0],W[2,0]) (wx,wy,wz)=euler.euler2rot(lon, lat, omega) W=np.zeros([3,1]) W[0,0]=wx W[1,0]=wy W[2,0]=wz import math R=Coordinates.mat_rot_general_to_local(math.radians(self.lon),math.radians(self.lat),0.) (x,y,z)=Coordinates.geo2xyz(math.radians(self.lon),math.radians(self.lat),0.) # Observation equation in local frame Ai=np.zeros([3,3],float) Ai[0,1]= z Ai[0,2]=-y Ai[1,0]=-z Ai[1,2]= x Ai[2,0]= y Ai[2,1]=-x RAi=np.dot(R,Ai) # Predicted velocity Pi=np.dot(RAi,W) pve=Pi[0,0]*1.E3 pvn=Pi[1,0]*1.E3 import copy N=copy.deepcopy(self) N.Ve=self.Ve-pve N.Vn=self.Vn-pvn return(N)
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
def substract_pole(self, W=None, type_euler='rot'): ################################################################### """ substract the prediction of an Euler pole to the velocity field """ import pyacs.lib.coordinates as Coordinates import pyacs.lib.euler as euler import numpy as np W = np.array(W).reshape(3, 1) ltype = [ 'euler', 'rot' ] # type is either Euler pole (lon. lat in dec. degrees and deg/Myr or cartesian rotation rate vector in rad/yr) if (type_euler not in ltype): raise ValueError( "!!! type_euler should be either euler or rot. type_euler=%s", type_euler) if (type_euler == 'euler'): # convert to rotation rate vector (lon, lat, omega) = (W[0, 0], W[1, 0], W[2, 0]) (wx, wy, wz) = euler.euler2rot(lon, lat, omega) W = np.zeros([3, 1]) W[0, 0] = wx W[1, 0] = wy W[2, 0] = wz # create a new velocity field lGpoint = [] for M in self.sites: R = Coordinates.mat_rot_general_to_local(np.radians(M.lon), np.radians(M.lat)) (x, y, z) = Coordinates.geo2xyz(np.radians(M.lon), np.radians(M.lat), M.he) # Observation equation in local frame Ai = np.zeros([3, 3], float) Ai[0, 1] = z Ai[0, 2] = -y Ai[1, 0] = -z Ai[1, 2] = x Ai[2, 0] = y Ai[2, 1] = -x RAi = np.dot(R, Ai) # Predicted velocity Pi = np.dot(RAi, W) pve = Pi[0, 0] * 1.E3 pvn = Pi[1, 0] * 1.E3 N = M.copy() N.Ve = M.Ve - pve N.Vn = M.Vn - pvn lGpoint.append(N) res_vel = Velocity_Field(lgmt_points=lGpoint) return res_vel
def pole(self, lexclude=[], method='WLS', exp='pLate', log=None): ################################################################### """ Euler pole calculation; available optimization methods are WLS: weighted least squares, LS: least-squares, Dikin: L1 linear estimator """ import numpy as np import pyacs.lib.coordinates as Coordinates import numpy.linalg as nplinalg import pyacs.lib.euler as euler np.set_printoptions(precision=2, threshold=10000, linewidth=250) # Gets dimensions for the systems if lexclude: nsites = 0 for M in self.sites: if not (M.code in lexclude): nsites = nsites + 1 else: nsites = self.nsites() A = np.zeros([2 * nsites, 3], float) B = np.zeros([2 * nsites, 1], float) VCV_B = np.zeros([2 * nsites, 2 * nsites], float) # starts loop on sites to build the linear system index = 0 H_sites = {} for M in self.sites: if not (M.code in lexclude): # XYZ -> local frame rotation matrix H_sites[M.code] = M R = Coordinates.mat_rot_general_to_local( np.radians(M.lon), np.radians(M.lat)) (x, y, z) = Coordinates.geo2xyz(np.radians(M.lon), np.radians(M.lat), M.he) # Observation equation in local frame Ai = np.zeros([3, 3], float) Ai[0, 1] = z Ai[0, 2] = -y Ai[1, 0] = -z Ai[1, 2] = x Ai[2, 0] = y Ai[2, 1] = -x Ai = Ai / 1000.0 RAi = np.dot(R, Ai) # fill the observation i into the general design matrix A A[2 * index, 0] = RAi[0, 0] A[2 * index, 1] = RAi[0, 1] A[2 * index, 2] = RAi[0, 2] A[2 * index + 1, 0] = RAi[1, 0] A[2 * index + 1, 1] = RAi[1, 1] A[2 * index + 1, 2] = RAi[1, 2] B[2 * index, 0] = M.Ve B[2 * index + 1, 0] = M.Vn M.assign_index(index) VCV_B[2 * index, 2 * index] = M.SVe**2 VCV_B[2 * index + 1, 2 * index + 1] = M.SVn**2 cov = M.SVe * M.SVn * M.SVen VCV_B[2 * index + 1, 2 * index] = cov VCV_B[2 * index, 2 * index + 1] = cov index = index + 1 # solves linear system P = nplinalg.inv(VCV_B) ATP = np.dot((A.T), P) N = np.dot(ATP, A) M = np.dot(ATP, B) # Inversion Q = nplinalg.inv(N) X = np.dot(Q, M) # Model Prediction MP = np.dot(A, X) # Residuals RVen = (B - MP) VCV_POLE_X = Q * 1.E-12 chi2 = np.dot(np.dot(RVen.T, P), RVen) dof = 2 * nsites - 3 reduced_chi2 = np.sqrt(chi2 / float(dof)) (wx, wy, wz) = (X[0, 0] * 1.E-6, X[1, 0] * 1.E-6, X[2, 0] * 1.E-6) # Convert rotation rate in the geocentric cartesian frame to Euler pole in geopgraphical coordinates (llambda, phi, omega) = euler.rot2euler(wx, wy, wz) (max_sigma, min_sigma, azimuth, s_omega) = euler.euler_uncertainty([wx, wy, wz], VCV_POLE_X) # Write log if (not log): flog_name = exp + '.log' else: flog_name = log flog = open(flog_name, 'w') flog.write("\nROTATION RATE VECTOR\n") flog.write("Wx (rad/yr): %11.5G +- %10.5G\n" % (wx, np.sqrt(VCV_POLE_X[0, 0]))) flog.write("Wy (rad/yr): %11.5G +- %10.5G\n" % (wy, np.sqrt(VCV_POLE_X[1, 1]))) flog.write("Wz (rad/yr): %11.5G +- %10.5G\n" % (wz, np.sqrt(VCV_POLE_X[2, 2]))) # flog.write("Wx Wy Wz : %10.5G %10.5G %10.5G\n", % (wx,wy,wz)) flog.write("ASSOCIATED VARIANCE-COVARIANCE MATRIX (rad/yr)**2\n") flog.write(" Wx Wy Wz\n") flog.write("---------------------------------------\n") flog.write("Wx |%11.5G %11.5G %11.5G\n" % (VCV_POLE_X[0, 0], VCV_POLE_X[1, 0], VCV_POLE_X[2, 0])) flog.write("Wy | %11.5G %11.5G\n" % (VCV_POLE_X[1, 1], VCV_POLE_X[2, 1])) flog.write("Wz | %11.5G\n" % VCV_POLE_X[2, 2]) flog.write("---------------------------------------\n") flog.write("\nEULER POLE\n") flog.write("longitude (dec. degree) : %6.2lf\n" % llambda) flog.write("latitude (dec. degree) : %6.2lf\n" % phi) flog.write("angular velocity (deg/Myr ): %6.3lf\n" % omega) flog.write("ASSOCIATED ERROR ELLIPSE\n") flog.write("semi major axis : %5.2lf\n" % max_sigma) flog.write("semi minor axis : %5.2lf\n" % min_sigma) flog.write("azimuth of semi major axis : %5.1lf\n" % azimuth) flog.write("std(angular velocity) : %5.3lf\n" % s_omega) # Calculating a few statistics flog.write("\nSTATISTICS\n") flog.write("----------\n") flog.write("Number of sites = %10d\n" % nsites) flog.write("Chi**2 = %10.1lf\n" % chi2) flog.write("Reduced Chi**2 = %10.1lf\n" % reduced_chi2) flog.write("Deg. of. freedom = %10d\n" % dof) if (dof == 0): flog.write("A post. var. factor = No meaning (dof=0)\n") else: sigma_0 = np.sqrt(chi2 / dof) flog.write("A post. var. factor = %10.1lf\n" % sigma_0) # rms & wrms flog.write("\nRESIDUALS\n") flog.write("----------\n") flog.write( "site pred_e pred_n Ve Vn R_ve R_vn S_ve S_vn RN_ve RN_vn\n" ) flog.write( "------------------------------------------------------------------------------------------------------------------------------------\n" ) cpt_site = 0 rms = 0.0 wrms = 0.0 dwrms = 0.0 for site, M in sorted(H_sites.items()): M = H_sites[site] if not (M.code in lexclude): i = M.get_index() mpe = MP[2 * i, 0] mpn = MP[2 * i + 1, 0] oe = B[2 * i, 0] on = B[2 * i + 1, 0] rve = RVen[2 * i, 0] rvn = RVen[2 * i + 1, 0] sve = M.SVe svn = M.SVn flog.write("%-19s %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf %10.2lf\n" % \ (M.code, mpe,mpn,oe,on,rve, rvn, sve, svn, rve / sve, rvn / svn)) cpt_site = cpt_site + 1 rms = rms + rve**2 + rvn**2 wrms = wrms + (rve / sve)**2 + (rvn / svn)**2 dwrms = dwrms + 1.0 / sve**2 + 1.0 / svn**2 flog.write( "------------------------------------------------------------------------------------------------------------------------------------\n" ) rms = np.sqrt(rms / 2 / cpt_site) wrms = np.sqrt(wrms / dwrms) flog.write("rms = %10.2lf mm/yr wrms = %10.2lf mm/yr\n\n" % (rms, wrms)) flog.close() print("-- Rotation rate results logged in %s" % flog_name) return (X * 1.E-6, VCV_POLE_X)
def pole(self,W=None,SW=None,type_euler='rot',option='predict'): ################################################################### """Substract the prediction of a given Euler pole""" import pyacs.lib.coordinates as Coordinates import pyacs.lib.euler import numpy as np ltype=['euler','rot'] # type is either Euler pole (long. lat in dec. degrees and deg/Myr or cartesian rotation rate vector in rad/yr) if (type_euler not in ltype): raise ValueError( "!!! Error. type_euler should be either euler " + "or rot (Euler pole (long. lat in dec. degrees and deg/Myr)" + " or cartesian rotation rate vector in rad/yr. type_euler = %s )" , type_euler ) loption=['remove','predict','add'] # if (option not in loption): raise ValueError( "!!! Error. option should be either predict, remove or add. option = %s " , option ) if (type_euler == 'euler'): if (len(W.shape)!=2): W=W.reshape(3,1) # convert to rotation rate vector (lon, lat, omega)=(W[0,0],W[1,0],W[2,0]) (wx,wy,wz)=pyacs.lib.euler.euler2rot(lon, lat, omega) # W W=np.zeros((3,1)) W[0,0]=wx W[1,0]=wy W[2,0]=wz # get spherical coordinates (x,y,z)=Coordinates.geo2xyz(self.lon,self.lat,self.he,unit='dec_deg') (l,p,_)=Coordinates.xyz2geospheric(x,y,z,unit='radians') R=Coordinates.mat_rot_general_to_local(l,p) # Observation equation in local frame Ai=np.zeros([3,3],float) Ai[0,1]= z Ai[0,2]=-y Ai[1,0]=-z Ai[1,2]= x Ai[2,0]= y Ai[2,1]=-x RAi=np.dot(R,Ai) # Predicted velocity Pi=np.dot(RAi,W) pve=Pi[0,0]*1.E3 pvn=Pi[1,0]*1.E3 N=self.copy() if (option=='remove'): N.Ve=self.Ve-pve N.Vn=self.Vn-pvn if (option=='add'): N.Ve=self.Ve+pve N.Vn=self.Vn+pvn if (option=='predict'): N.Ve=pve N.Vn=pvn if SW != None: # uses pole variance-covariance matrix VCV=SW #print VCV.shape,Ai.shape # VCV=np.zeros((3,3)) # VCV[0,0]=SW[0] # VCV[1,1]=SW[1] # VCV[2,2]=SW[2] # VCV[1,2]=SW[3] # VCV[1,3]=SW[4] # VCV[2,3]=SW[5] # VCV_PREDICTION=np.dot(np.dot(Ai,VCV),Ai.T) VCV_PREDICTION_ENU=np.dot(np.dot(RAi,VCV),RAi.T) (N.SVe,N.SVn)=(np.sqrt(VCV_PREDICTION_ENU[0,0])*1000.0,np.sqrt(VCV_PREDICTION_ENU[1,1])*1000.0 ) return(N)