def upscale_field(lons, lats, field, x_scale=2, y_scale=2, is_degrees=True): ''' Takes a field defined on a sphere using lons/lats and returns an upscaled version, using cubic spline interpolation. ''' if is_degrees: lons = lons * np.pi / 180. lats = (lats + 90) * np.pi / 180. d_lon = lons[1] - lons[0] d_lat = lats[1] - lats[0] new_lon = np.linspace(lons[0], lons[-1], len(lons) * x_scale) new_lat = np.linspace(lats[0], lats[-1], len(lats) * x_scale) mesh_new_lat, mesh_new_lon = np.meshgrid(new_lat, new_lon) if True: lut = RectSphereBivariateSpline(lats[1:-1], lons[1:-1], field[1:-1, 1:-1]) interp_field = lut.ev(mesh_new_lat[1:-1, 1:-1].ravel(), mesh_new_lon[1:-1, 1:-1].ravel()).reshape( mesh_new_lon.shape[0] - 2, mesh_new_lon.shape[1] - 2).T else: pass if is_degrees: new_lon = new_lon * 180. / np.pi new_lat = (new_lat * 180. / np.pi) - 90 return new_lon[1:-1], new_lat[1:-1], interp_field
def apply_gia(sites_of_retain4, dir_file_gia): # read the rate of radial displacement (UP) on a 0.2x0.2 grid from ICE-6G_D(VM5a) data_ICE_6G_D = dir_file_gia # Open the dataset and print out metadeta ds = xr.open_dataset(data_ICE_6G_D) # convert lons and lats of sites in [d,m,s] to lons and colats in radian sites_of_retain4_lons = sites_of_retain4['Lon. °E'] * u.deg.to(u.rad) sites_of_retain4_lats = sites_of_retain4['Lat. °N'] * u.deg.to(u.rad) sites_of_retain4_colats = np.pi / 2 - sites_of_retain4_lats # colats and lons in radians lats, lons, up_rate = ds['Lat'], ds['Lon'], ds['Drad_250'] colats_rad = np.deg2rad(90 - lats) lons_rad = np.deg2rad(lons) lut = RectSphereBivariateSpline(colats_rad, lons_rad, up_rate) up_rate_sites = lut.ev(sites_of_retain4_colats, sites_of_retain4_lons) sites_of_retain5 = sites_of_retain4[up_rate_sites < 0.75] return sites_of_retain5
def ncepGFSmodel2swath(lats, lons, data, lats_2, lons_2): func = RectSphereBivariateSpline(lats, lons, data) data_2 = func.ev(lats_2.ravel(),\ lons_2.ravel())\ .reshape(lats_2.shape) return data_2
def resize_interpolate(ary_in, new_size): if hasattr(ary_in, 'dtype'): lons = sorted(list(set(ary_in['x']))) lats = sorted(list(set(ary_in['y']))) zs = ary_in['z'] else: lons, lats, zs = (numpy.array(sorted(list(set(x)))) for x in (zip(*ary_in))) #print('lls: ', lons, lats) zs = numpy.array([rw[2] for rw in ary_in]) # new_lons = numpy.linspace(min(lons), max(lons), new_size[0]) * numpy.pi / 180. new_lats = numpy.linspace(min(lats), max(lats), new_size[1]) * numpy.pi / 180. #return new_lons, new_lats new_lats, new_lons = numpy.meshgrid(new_lats, new_lons) # data = numpy.array(zs) data.shape = (numpy.size(lats), numpy.size(lons) ) # or is it len(lats), len(lons) (yes, i think it is) lut = RectSphereBivariateSpline(lats, lons, data) #data_interp = lut.ev(new_lats.ravel(), new_lons.ravel()) data_interp = lut.ev(new_lats.ravel(), new_lons.ravel()).reshape(new_size).T data_interp = data_interp.reshape((data_interp.size, )) #return data_interp # # return np.core.records.fromarrays( zip(*[[x * 180 / numpy.pi, y * 180 / numpy.pi, z] for (x, y), z in zip( itertools.product(new_lons.reshape(( new_lons.size, )), new_lats.reshape(( new_lats.size, ))), data_interp)]), dtype=[('x', '>f8'), ('y', '>f8'), ('z', '>f8')])
def upscale_field(lons, lats, field, x_scale=2, y_scale=2, is_degrees=True): ''' Takes a field defined on a sphere using lons/lats and returns an upscaled version, using cubic spline interpolation. ''' if is_degrees: lons = lons * np.pi / 180. lats = (lats + 90) * np.pi / 180. d_lon = lons[1] - lons[0] d_lat = lats[1] - lats[0] new_lon = np.linspace(lons[0], lons[-1], len(lons) * x_scale) new_lat = np.linspace(lats[0], lats[-1], len(lats) * x_scale) mesh_new_lat, mesh_new_lon = np.meshgrid(new_lat, new_lon) if True: lut = RectSphereBivariateSpline(lats[1:-1], lons[1:-1], field[1:-1, 1:-1]) interp_field = lut.ev(mesh_new_lat[1:-1, 1:-1].ravel(), mesh_new_lon[1:-1, 1:-1].ravel()).reshape(mesh_new_lon.shape[0] - 2, mesh_new_lon.shape[1] - 2).T else: pass if is_degrees: new_lon = new_lon * 180. / np.pi new_lat = (new_lat * 180. / np.pi) - 90 return new_lon[1:-1], new_lat[1:-1], interp_field
def create_model(file_name=None, tag=None): '''Takes .ffe model, converts into healpix and smooths the response''' ##Make an empty array for healpix projection beam_response = zeros(len_empty_healpix) * nan ##Load ffe model data in, which is stored in real and imaginary components ##of a phi/theta polaristaion representation of the beam ##apparently this is normal to beam engineers data = loadtxt(file_name) theta = data[:, 0] phi = data[:, 1] re_theta = data[:, 2] im_theta = data[:, 3] re_phi = data[:, 4] im_phi = data[:, 5] ##Convert to complex numbers X_theta = re_theta.astype(complex) X_theta.imag = im_theta X_phi = re_phi.astype(complex) X_phi.imag = im_phi ##make a coord grid for the data in the .ffe model theta_range = linspace(epsilon, 90, 91) phi_range = linspace(epsilon, 359.0, 360) theta_mesh, phi_mesh = meshgrid(theta_range, phi_range) ##Convert reference model into power from the complex values ##make an inf values super small power = 10 * log10(abs(X_theta)**2 + abs(X_phi)**2) power[where(power == -inf)] = -80 ##Had a problem with edge effects, leave off near horizon values power = power[:-91] ##Get things into correct shape and do an interpolation ##s is a paramater I had to play with to get by eye nice results power.shape = phi_mesh.shape lut = RectSphereBivariateSpline(theta_range * (pi / 180.0), phi_range * (pi / 180.0), power.T, s=0.1) ##Get the theta and phi of all healpixels ip = arange(len_empty_healpix) theta_rad, phi_rad = hp.pix2ang(nside, ip) ##Use spline to map beam into healpixels beam_response = lut.ev(theta_rad, phi_rad) return beam_response, theta_mesh, phi_mesh, power, theta
def regrid(phi_old, lambda_old, nphi_new, nlambda_new, data): Drc = data[1:-1, 1:-1, 0].copy() lut = RectSphereBivariateSpline(phi_old + pi / 2, lambda_old + pi, Drc.T) dlambda1 = 2 * pi / nlambda_new dphi1 = pi / nphi_new phi1 = np.array( [-((pi / 2) - dphi1 / 2) + (j) * dphi1 for j in range(nphi_new)]) + pi / 2 lambd1 = (np.array([-(pi) + (i) * dlambda1 for i in range(nlambda_new)])) + pi glambd, gphi = np.meshgrid(lambd1, phi1) interp = (lut.ev(gphi.ravel(), glambd.ravel())).reshape(nphi_new, nlambda_new).T return interp, phi1, lambd1, dphi1, dlambda1
def geointerp(lats, lons, data, grid_size_deg, mesh=False): '''We want to interpolate it to a global x-degree grid''' deg2rad = np.pi / 180. new_lats = np.linspace(grid_size_deg, 180, 180 / grid_size_deg) new_lons = np.linspace(grid_size_deg, 360, 360 / grid_size_deg) new_lats_mesh, new_lons_mesh = np.meshgrid(new_lats * deg2rad, new_lons * deg2rad) '''We need to set up the interpolator object''' # lats = [float(lat) for lat in lats] print lats * 2 #*deg2rad lut = RectSphereBivariateSpline(lats * deg2rad, lons * deg2rad, data) '''Finally we interpolate the data. The RectSphereBivariateSpline object only takes 1-D arrays as input, therefore we need to do some reshaping.''' new_lats = new_lats_mesh.ravel() new_lons = new_lons_mesh.ravel() data_interp = lut.ev(new_lats, new_lons) if mesh == True: data_interp = data_interp.reshape( (360 / grid_size_deg, 180 / grid_size_deg)).T return new_lats / deg2rad, new_lons / deg2rad, data_interp
def geointerp(lats,lons,data,grid_size_deg, mesh=False): '''We want to interpolate it to a global x-degree grid''' deg2rad = np.pi/180. new_lats = np.linspace(grid_size_deg, 180, 180/grid_size_deg) new_lons = np.linspace(grid_size_deg, 360, 360/grid_size_deg) new_lats_mesh, new_lons_mesh = np.meshgrid(new_lats*deg2rad, new_lons*deg2rad) '''We need to set up the interpolator object''' # lats = [float(lat) for lat in lats] print lats*2#*deg2rad lut = RectSphereBivariateSpline(lats*deg2rad, lons*deg2rad, data) '''Finally we interpolate the data. The RectSphereBivariateSpline object only takes 1-D arrays as input, therefore we need to do some reshaping.''' new_lats = new_lats_mesh.ravel() new_lons = new_lons_mesh.ravel() data_interp = lut.ev(new_lats,new_lons) if mesh == True: data_interp = data_interp.reshape((360/grid_size_deg, 180/grid_size_deg)).T return new_lats/deg2rad, new_lons/deg2rad, data_interp
def interpol(latitude,longitude,variable): ''' This thing interpolates ''' lut=RSBS(latitude,longitude,variable) interpolated_vairable=lut.ev(latai.ravel(),lonai.ravel()).reshape((361, 576)) return interpolated_vairable
# We want to interpolate it to a global one-degree grid new_lats = np.linspace(1, 180, 180) * np.pi / 180 new_lons = np.linspace(1, 360, 360) * np.pi / 180 new_lats, new_lons = np.meshgrid(new_lats, new_lons) # We need to set up the interpolator object from scipy.interpolate import RectSphereBivariateSpline lut = RectSphereBivariateSpline(lats, lons, data) # Finally we interpolate the data. The `RectSphereBivariateSpline` object # only takes 1-D arrays as input, therefore we need to do some reshaping. data_interp = lut.ev(new_lats.ravel(), new_lons.ravel()).reshape((360, 180)).T # Looking at the original and the interpolated data, one can see that the # interpolant reproduces the original data very well: import matplotlib.pyplot as plt fig = plt.figure() ax1 = fig.add_subplot(211) ax1.imshow(data, interpolation='nearest') ax2 = fig.add_subplot(212) ax2.imshow(data_interp, interpolation='nearest') plt.show() # Chosing the optimal value of ``s`` can be a delicate task. Recommended # values for ``s`` depend on the accuracy of the data values. If the user
def create_model(nside, file_name=None): """Takes feko .ffe reference model, converts into healpix and smooths the response :param nside: Healpix nside :param file_name: Path to :samp:`.ffe` feko model of reference tiles :returns: - :class:`tuple` of (beam_response, theta_mesh, phi_mesh, power, theta) """ # Make an empty array for healpix projection len_empty_healpix = hp.nside2npix(nside) beam_response = np.zeros(len_empty_healpix) * np.nan # Had problems with having coords = 0 when interpolating, so make a small number # and call it epsilon for some reason epsilon = 1.0e-12 # Load ffe model data in, which is stored in real and imaginary components # of a phi/theta polaristaion representation of the beam # apparently this is normal to beam engineers data = np.loadtxt(file_name) theta = data[:, 0] re_theta = data[:, 2] im_theta = data[:, 3] re_phi = data[:, 4] im_phi = data[:, 5] # Convert to complex numbers X_theta = re_theta.astype(complex) X_theta.imag = im_theta X_phi = re_phi.astype(complex) X_phi.imag = im_phi # make a coord grid for the data in the .ffe model theta_range = np.linspace(epsilon, 90, 91) phi_range = np.linspace(epsilon, 359.0, 360) theta_mesh, phi_mesh = np.meshgrid(theta_range, phi_range) # Convert reference model into power from the complex values power = 10 * np.log10(abs(X_theta)**2 + abs(X_phi)**2) # Make an inf values super small power[np.where(power == -np.inf)] = -80 # Had a problem with edge effects, leave off near horizon values # Basically remove the last 90 values of power list, where θ == 90 power = power[:-91] # Get things into correct shape and do an interpolation power.shape = phi_mesh.shape # Bivariate spline approximation over a rectangular mesh on a sphere # s is a paramater I had to play with to get by eye nice results # s: positive smoothing factor lut = RectSphereBivariateSpline(theta_range * (np.pi / 180.0), phi_range * (np.pi / 180.0), power.T, s=0.1) # Get the theta and phi of all healpixels i_pix = np.arange(hp.nside2npix(nside)) theta_rad, phi_rad = hp.pix2ang(nside, i_pix) # Evaluate the interpolated function at healpix gridpoints # Use spline to map beam into healpixels beam_response = lut.ev(theta_rad, phi_rad) # rescale beam response to have peak value of 0 dB beam_response = beam_response - np.nanmax(beam_response) return beam_response, theta_mesh, phi_mesh, power, theta
def main(): # Suppose we have global data on a coarse grid import numpy as np lats = np.linspace(10, 170, 9) * np.pi / 180. lons = np.linspace(0, 350, 18) * np.pi / 180. data = np.dot( np.atleast_2d(90. - np.linspace(-80., 80., 18)).T, np.atleast_2d(180. - np.abs(np.linspace(0., 350., 9)))).T # We want to interpolate it to a global one-degree grid new_lats = np.linspace(1, 180, 180) * np.pi / 180 new_lons = np.linspace(1, 360, 360) * np.pi / 180 new_lats, new_lons = np.meshgrid(new_lats, new_lons) # We need to set up the interpolator object from scipy.interpolate import RectSphereBivariateSpline lut = RectSphereBivariateSpline(lats, lons, data) # Finally we interpolate the data. The `RectSphereBivariateSpline` object # only takes 1-D arrays as input, therefore we need to do some reshaping. data_interp = lut.ev(new_lats.ravel(), new_lons.ravel()).reshape( (360, 180)).T # Looking at the original and the interpolated data, one can see that the # interpolant reproduces the original data very well: import matplotlib.pyplot as plt fig = plt.figure() ax1 = fig.add_subplot(211) ax1.imshow(data, interpolation='nearest') ax2 = fig.add_subplot(212) ax2.imshow(data_interp, interpolation='nearest') plt.show() # Chosing the optimal value of ``s`` can be a delicate task. Recommended # values for ``s`` depend on the accuracy of the data values. If the user # has an idea of the statistical errors on the data, she can also find a # proper estimate for ``s``. By assuming that, if she specifies the # right ``s``, the interpolator will use a spline ``f(u,v)`` which exactly # reproduces the function underlying the data, she can evaluate # ``sum((r(i,j)-s(u(i),v(j)))**2)`` to find a good estimate for this ``s``. # For example, if she knows that the statistical errors on her # ``r(i,j)``-values are not greater than 0.1, she may expect that a good # ``s`` should have a value not larger than ``u.size * v.size * (0.1)**2``. # If nothing is known about the statistical error in ``r(i,j)``, ``s`` must # be determined by trial and error. The best is then to start with a very # large value of ``s`` (to determine the least-squares polynomial and the # corresponding upper bound ``fp0`` for ``s``) and then to progressively # decrease the value of ``s`` (say by a factor 10 in the beginning, i.e. # ``s = fp0 / 10, fp0 / 100, ...`` and more carefully as the approximation # shows more detail) to obtain closer fits. # The interpolation results for different values of ``s`` give some insight # into this process: fig2 = plt.figure() s = [3e9, 2e9, 1e9, 1e8] for ii in range(len(s)): lut = RectSphereBivariateSpline(lats, lons, data, s=s[ii]) data_interp = lut.ev(new_lats.ravel(), new_lons.ravel()).reshape( (360, 180)).T ax = fig2.add_subplot(2, 2, ii + 1) ax.imshow(data_interp, interpolation='nearest') ax.set_title("s = %g" % s[ii]) plt.show()
def interpolate_RSBS(data, sz, lon1=None, lon2=None, lat1=None, lat2=None, fignum=None): # interpolate using scipy.interpolate.RectSphereBivariateSpline # # this needs some tuning, but it appears to be working and semi-functional # ... but tends to break for complex array. let's try scipy.interp2d(): #http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.interp2d.html # print('data: ', data[0:5]) # lons = sorted(list(set([x for x, y, z in data]))) lats = sorted(list(set([y for x, y, z in data]))) #print('lls: ', len(lats), len(lons)) data = numpy.reshape([rw[2] for rw in data], (len(lats), len(lons))) #print('sh: ', numpy.shape(data)) ##### plt.figure(fignum + 2) plt.clf() ax1 = plt.gca() ax1.imshow(data, interpolation='nearest') ##### # lon1 = (lon1 or min(lons)) lon2 = (lon2 or max(lons)) lat1 = (lat1 or min(lats)) lat2 = (lat2 or max(lats)) # #new_lats = np.linspace(1, 180, 180) * np.pi / 180 #new_lons = np.linspace(1, 360, 360) * np.pi / 180 new_lats = np.linspace(lat1, lat2, sz[0]) * np.pi / 180 new_lons = np.linspace(lon1, lon2, sz[1]) * np.pi / 180 new_lats, new_lons = np.meshgrid(new_lats, new_lons) # We need to set up the interpolator object #from scipy.interpolate import RectSphereBivariateSpline lut = RectSphereBivariateSpline(lats, lons, data) # #lut = RectBivariateSpline(lats, lons, data) print(len(new_lats), len(new_lons[0]), len(data), len(data[0]), new_lats.shape) # Finally we interpolate the data. The `RectSphereBivariateSpline` object # only takes 1-D arrays as input, therefore we need to do some reshaping. data_interp = lut.ev(new_lats.ravel(), new_lons.ravel()).reshape(new_lats.shape).T # Looking at the original and the interpolated data, one can see that the # interpolant reproduces the original data very well: # if fignum != None: fig = plt.figure(fignum + 0) ax1 = fig.add_subplot(211) ax1.imshow(data, interpolation='nearest') ax2 = fig.add_subplot(212) ax2.imshow(data_interp, interpolation='nearest') plt.show() # # Chosing the optimal value of ``s`` can be a delicate task. Recommended # values for ``s`` depend on the accuracy of the data values. If the user # has an idea of the statistical errors on the data, she can also find a # proper estimate for ``s``. By assuming that, if she specifies the # right ``s``, the interpolator will use a spline ``f(u,v)`` which exactly # reproduces the function underlying the data, she can evaluate # ``sum((r(i,j)-s(u(i),v(j)))**2)`` to find a good estimate for this ``s``. # For example, if she knows that the statistical errors on her # ``r(i,j)``-values are not greater than 0.1, she may expect that a good # ``s`` should have a value not larger than ``u.size * v.size * (0.1)**2``. # If nothing is known about the statistical error in ``r(i,j)``, ``s`` must # be determined by trial and error. The best is then to start with a very # large value of ``s`` (to determine the least-squares polynomial and the # corresponding upper bound ``fp0`` for ``s``) and then to progressively # decrease the value of ``s`` (say by a factor 10 in the beginning, i.e. # ``s = fp0 / 10, fp0 / 100, ...`` and more carefully as the approximation # shows more detail) to obtain closer fits. # The interpolation results for different values of ``s`` give some insight # into this process: fig2 = plt.figure(fignum + 1) s = [3e9, 2e9, 1e9, 1e8] for ii in range(len(s)): #lut = RectSphereBivariateSpline(lats, lons, data, s=s[ii]) RectBivariateSpline(lats, lons, data, s=s[ii]) data_interp = lut.ev(new_lats.ravel(), new_lons.ravel()).reshape(new_lons.shape).T ax = fig2.add_subplot(2, 2, ii + 1) ax.imshow(data_interp, interpolation='nearest') ax.set_title("s = %g" % s[ii]) plt.show()
PM2 = fn.variables['SSSMASS25_avg'][:]*1e9 PM3 = fn.variables['SO4SMASS_avg' ][:]*1e9*1.375 PM4 = fn.variables['OCSMASS_avg' ][:]*1e9 PM5 = fn.variables['BCSMASS_avg' ][:]*1e9 PM25 = PM1+PM2+PM3+PM4+PM5 # By Definition from MERRAero fn.close(); del fn clon=-98.5795 # central lat/lon for imaging. Dead-center of US. clat= 39.8282 # ---------------------------------------------------------------- # Interpolates coarse (144x288) 500 hPa data into finer (361x540) # surface grid. lut=RSBS(latp5,lonp5,u5) u5i=lut.ev(lat2.ravel(),lon2.ravel()).reshape((361, 540)) del lut lut=RSBS(latp5,lonp5,v5) v5i=lut.ev(lat2.ravel(),lon2.ravel()).reshape((361, 540)) del lut lut=RSBS(latp5,lonp5,hgt) hgti=lut.ev(lat2.ravel(),lon2.ravel()).reshape((361, 540)); del hgt, u5, v5, lonp5, latp5, lonp2, latp2, lon2, lat2, lon5, lat5 #fig = plt.figure() #ax1 = fig.add_subplot(211) #ax1.imshow(hgt, interpolation='nearest') #ax2 = fig.add_subplot(212) #ax2.imshow(hgti, interpolation='nearest') #plt.show()
""" This is an example test for scipy RectSphereBivariateSpline interpolator. It is meant to be used for approximation of a rectangular grid on a sphere, e.g., for lat/lon interpolation. """ import numpy as np from scipy.interpolate import RectSphereBivariateSpline import matplotlib.pyplot as plt lats = np.linspace(10, 170, 9) * np.pi / 180. lons = np.linspace(0, 350, 18) * np.pi / 180. data = np.dot(np.atleast_2d(90. - np.linspace(-80., 80., 18)).T, np.atleast_2d(180. - np.abs(np.linspace(0., 350., 9)))).T new_lats = np.linspace(1, 180, 180) * np.pi / 180 new_lons = np.linspace(1, 360, 360) * np.pi / 180 new_lats, new_lons = np.meshgrid(new_lats, new_lons) lut = RectSphereBivariateSpline(lats, lons, data) data_interp = lut.ev(new_lats.ravel(), new_lons.ravel()).reshape((360, 180)).T fig = plt.figure() ax1 = fig.add_subplot(211) ax1.imshow(data, interpolation='nearest') ax2 = fig.add_subplot(212) ax2.imshow(data_interp, interpolation='nearest') plt.show()
def apply_gsrm(sites_of_retain3_pv, ITRF_ID, dir_file_gsrm): # read the lons, lats, and heights width = (5, 3, 10, 25, 4, 3, 5, 4, 3, 5, 8) data_lonlat = np.genfromtxt(ITRF_ID, delimiter=width, dtype=np.str, skip_header=2, skip_footer=1, autostrip=True) n = len(data_lonlat) code_pt = np.core.defchararray.add(data_lonlat[:, 0], data_lonlat[:, 1]) CODE_PT = sites_of_retain3_pv['CODE'] + sites_of_retain3_pv['PT'] _, __, _index = np.intersect1d(CODE_PT, code_pt, return_indices=True) sites_of_retain3_lonlat = data_lonlat[_index] # convert lons and lats of sites in [d,m,s] to lons and colats in radian sites_of_retain3_lons = np.array(sites_of_retain3_lonlat[:, 4:7], dtype=np.float) sites_of_retain3_geod_lats = np.array(sites_of_retain3_lonlat[:, 7:10], dtype=np.float) sites_of_retain3_lons = [tuple(x) for x in sites_of_retain3_lons] sites_of_retain3_geod_lats = [tuple(x) for x in sites_of_retain3_geod_lats] sites_of_retain3_lons_deg = Angle(sites_of_retain3_lons, unit=u.deg) sites_of_retain3_lats_geod_deg = Angle(sites_of_retain3_geod_lats, unit=u.deg) sites_of_retain3_lats_deg = geode2geocen(sites_of_retain3_lats_geod_deg) sites_of_retain3_lons = sites_of_retain3_lons_deg.rad sites_of_retain3_lats = sites_of_retain3_lats_deg.to(u.rad).value df = pd.DataFrame(sites_of_retain3_lonlat[:, :4], columns=['CODE', 'PT', 'DOMES', 'STATION DESCRIPTION']) df['Geod. Lat. °N'] = sites_of_retain3_lats_geod_deg df['Lat. °N'] = sites_of_retain3_lats_deg df['Lon. °E'] = sites_of_retain3_lons_deg df['H'] = sites_of_retain3_lonlat[:, -1] sites_of_retain3_lonlat = df sites_of_retain3_colats = np.pi / 2 - sites_of_retain3_lats # read the GSRMv2.1 data_gsrmv21 = np.loadtxt(dir_file_gsrm) # calculate second invariant strain rate sisr = np.sqrt(data_gsrmv21[:, 8]**2 + data_gsrmv21[:, 9]**2).reshape( 1750, 3600) # flip the lons and lats sisr = np.flip(sisr, 0) sisr[:, :1800], sisr[:, 1800:] = sisr[:, 1800:].copy(), sisr[:, :1800].copy() # lons and lats after flipping lons = np.linspace(0.05, 359.95, 3600) lats = np.linspace(87.45, -87.45, 1750) # colats and lons in radians colats_rad = np.deg2rad(90 - lats) lons_rad = np.deg2rad(lons) lut = RectSphereBivariateSpline(colats_rad, lons_rad, sisr) sisr_sites = lut.ev(sites_of_retain3_colats, sites_of_retain3_lons) sites_of_retain4_lonlat = sites_of_retain3_lonlat[ sisr_sites < 0.1].reset_index(drop=True) CODE = sites_of_retain4_lonlat['CODE'] CODE_pv = sites_of_retain3_pv['CODE'] _, _index, __ = np.intersect1d(CODE_pv, CODE, return_indices=True) sites_of_retain4_pv = sites_of_retain3_pv.loc[_index].reset_index( drop=True) sites_of_retain4 = pd.merge(sites_of_retain4_lonlat, sites_of_retain4_pv, on=['CODE', 'PT'], validate="one_to_one") return sites_of_retain4
def regular_gldas(lats,lons,grids): ''' Normalize the GLDAS grid data to meet the requirements of spherical harmonic expansion with pyshtools based on the sampling theorem of Driscoll and Healy (1994). The normalized grid data has the following characteristics: (1) the first latitudinal band corresponds to 90 N, and the latitudinal band for 90 S is not included, and the latitudinal sampling interval is 180/n degrees. (2) the first longitudinal band is 0 E, and the longitude band for 360 E is not included, and the longitudinal sampling interval is 360/n for an equally spaced grid. Usage: gldas_new = regular_gldas(lats,lons,grids) Inputs: lats -> [float array] latitudes of gldas grid data lons -> [float array] longitudes of gldas grid data grids -> [float 2d array] gldas grids data Parameters: Outputs: gldas_new -> float 2d array] normalized grids data ''' # Extend the spatial extent of the GLDAS grid to a grid with a shape of n x 2n n = int(180/(lats[1] - lats[0])) lats_new = np.linspace(lats.max(),-lats.max(),n) lons_new = np.linspace(180-lons.max(),180+lons.max(),2*n) nlats,nlons = len(lats),len(lons) nlats_new,nlons_new = len(lats_new),len(lons_new) grids_new = [] for grid in grids: grid_new = np.zeros((nlats_new,nlons_new)) # Flip the grid data along latitude grid_new[:nlats,:] = np.flip(grid,0) # Swap the grid data along the longitude direction to make the longitude range from [-180W ~ 180E] to [0E ~ 360E] grid_new[:,:nlats_new],grid_new[:,nlats_new:] = grid_new[:,nlats_new:].copy(),grid_new[:,:nlats_new].copy() grids_new.append(grid_new) grids_new = np.array(grids_new) grids_new[np.isnan(grids_new)] = 0 trunc = np.abs(grids_new[grids_new != 0]).min()/2 lats_interp = lats_new + lons_new.min() lons_interp = lons_new - lons_new.min() grids_interp = [] # colatitude and longitude before interpolation colats_rad = np.deg2rad(90 - lats_new) lons_rad = np.deg2rad(lons_new) # colatitude and longitude after interpolation colats_rad_interp = np.deg2rad(90 - lats_interp) lons_rad_interp = np.deg2rad(lons_interp) lons_rad_interp, colats_rad_interp = np.meshgrid(lons_rad_interp, colats_rad_interp) # grid data after interpolation for grid_new in grids_new: lut = RectSphereBivariateSpline(colats_rad,lons_rad,grid_new) grid_interp = lut.ev(colats_rad_interp,lons_rad_interp).reshape(nlats_new,nlons_new) grids_interp.append(grid_interp) grids_interp = np.array(grids_interp) grids_interp[np.abs(grids_interp) < trunc] = 0 return lats_interp,lons_interp,grids_interp