def __call__(self,suntanspath,depthmax=0.0,scalefac=-1.0, interpnodes=True): self.suntanspath=suntanspath # Initialise the interpolation points print 'Loading suntans grid points...' self.grd = sunpy.Grid(self.suntanspath) if interpnodes: print 'Interpolating depths onto nodes and taking min...' self.xy = np.column_stack((self.grd.xp,self.grd.yp)) else: print 'Interpolating depths straight to cell centres...' self.xy = np.column_stack((self.grd.xv,self.grd.yv)) # Initialise the Interpolation class print 'Building interpolant class...' self.F = interpXYZ(self.indata.XY,self.xy,method=self.interpmethod,NNear=self.NNear,\ p=self.p,varmodel=self.varmodel,nugget=self.nugget,sill=self.sill,vrange=self.vrange) # Interpolate the data print 'Interpolating data...' dv = self.F(self.indata.Zin)*scalefac if interpnodes: self.grd.dv = np.zeros_like(self.grd.xv) for nn in range(self.grd.Nc): self.grd.dv[nn] = np.max(dv[self.grd.cells[nn,0:self.grd.nfaces[nn] ] ]) #self.grd.dv[nn] = np.mean(dv[self.grd.cells[nn,0:self.grd.nfaces[nn] ] ]) else: self.grd.dv = dv # Smooth if self.smooth: self.smoothDepths() # Cap the maximum depth ind = self.grd.dv<=depthmax self.grd.dv[ind]=depthmax # Write the depths to file print 'Writing depths.dat...' self.grd.saveBathy(suntanspath+'/depths.dat-voro') print 'Data saved to %s.'%suntanspath+'/depths.dat-voro' # Plot if self.plottype=='mpl': self.plot() elif self.plottype=='vtk2': self.plotvtk() elif self.plottype=='vtk3': self.plotvtk3D() print 'Finished depth interpolation.'
def smoothDepths(self): """ Smooth the data by running an interpolant over the model grid points """ print 'Smoothing the data...' Fsmooth =interpXYZ(self.xy,self.xy,method=self.smoothmethod,NNear=self.smoothnear,vrange=self.vrange) self.grd.dv = Fsmooth(self.grd.dv)
def interp(self): """ interp the data to SUNTANS 16 wind stations """ xw = np.zeros_like(self.lat) yw = np.zeros_like(self.lon) if self.lon.ndim == 2: for i in range(self.lon.shape[0]): for j in range(self.lon.shape[1]): (xw[i, j], yw[i, j]) = utm.from_latlon(self.lat[i, j], self.lon[i, j])[0:2] else: for i in range(self.lon.shape[0]): (xw[i], yw[i]) = utm.from_latlon(self.lat[i], self.lon[i])[0:2] xy_narr = np.vstack((xw.ravel(), yw.ravel())).T xy_sun = np.vstack((self.xsun.ravel(), self.ysun.ravel())).T F = interpXYZ(xy_narr, xy_sun, method='idw') Nt = len(self.t[:]) self.air_u_new = np.zeros([Nt, self.xsun.shape[0]]) self.air_v_new = np.zeros([Nt, self.xsun.shape[0]]) self.tair_new = np.zeros([Nt, self.xsun.shape[0]]) self.cloud_new = np.zeros([Nt, self.xsun.shape[0]]) self.rh_new = np.zeros([Nt, self.xsun.shape[0]]) self.pair_new = np.zeros([Nt, self.xsun.shape[0]]) self.rain_new = np.zeros([Nt, self.xsun.shape[0]]) for tstep in range(Nt): utem = F(self.air_u[tstep, :].ravel()) vtem = F(self.air_v[tstep, :].ravel()) tair_tem = F(self.tair[tstep, :].ravel()) cloud_tem = F(self.cloud[tstep, :].ravel()) rh_tem = F(self.rh[tstep, :].ravel()) pair_tem = F(self.pair[tstep, :].ravel()) rain_tem = F(self.rain[tstep, :].ravel()) self.air_u_new[tstep, :] = utem self.air_v_new[tstep, :] = vtem self.tair_new[tstep, :] = tair_tem self.cloud_new[tstep, :] = cloud_tem self.rh_new[tstep, :] = rh_tem self.pair_new[tstep, :] = pair_tem self.rain_new[tstep, :] = rain_tem self.cloud_new[self.cloud_new > 1] = 1.0
def writeGNOME(self, outfile): """ Save the data to the file that GNOME can read """ ## Step One: intepolate wind to a regular grid Num = 20 lon = np.linspace(self.bbox[0], self.bbox[1], Num) lat = np.linspace(self.bbox[2], self.bbox[3], Num) lon_new, lat_new = np.meshgrid(lon, lat) x = np.zeros_like(lat_new) y = np.zeros_like(lon_new) for i in range(Num): for j in range(Num): (x[i, j], y[i, j]) = utm.from_latlon(lat_new[i, j], lon_new[i, j])[0:2] xncep = np.zeros_like(self.lat) yncep = np.zeros_like(self.lon) for i in range(len(self.lat)): (xncep[i], yncep[i]) = utm.from_latlon(self.lat[i], self.lon[i])[0:2] xy = np.vstack((x.ravel(), y.ravel())).T xy_ncep = np.vstack((xncep.ravel(), yncep.ravel())).T F = interpXYZ(xy_ncep, xy, method='idw') Nt = len(self.timei) air_u_new = np.zeros([Nt, Num, Num]) air_v_new = np.zeros([Nt, Num, Num]) for tstep in range(Nt): utem = F(self.air_u[tstep, :].ravel()) vtem = F(self.air_v[tstep, :].ravel()) air_u_new[tstep, :, :] = utem.reshape(Num, Num) air_v_new[tstep, :, :] = vtem.reshape(Num, Num) ## Step Two: write the data to GNOME file GNOME_wind(outfile, self.timei, lat_new, lon_new, air_u_new, air_v_new)
def interp_h(self, new_lon, new_lat): """ funtion that interpolates the water depth onto the new rectilinear grid Input: lon, lat of the new grid Output: interpolated h """ new_SW=(new_lat.min(), new_lon.min()) ###(lat, lon) new_NE=(new_lat.max(), new_lon.max()) xnew, ynew = self.convert_utm(new_lon, new_lat) xy_new = np.vstack((xnew.ravel(),ynew.ravel())).T ## new grid lon_rho = self.data_roms['lon_rho'][1:-2,1:-2] lat_rho = self.data_roms['lat_rho'][1:-2,1:-2] mask_rho = self.data_roms['mask'][1:-2,1:-2] h = self.data_roms['h'][1:-2,1:-2] ind = self.findNearset(new_SW[1], new_SW[0], lon_rho, lat_rho) J0=ind[0][0] I0=ind[0][1] ind = self.findNearset(new_NE[1], new_NE[0], lon_rho, lat_rho) J1=ind[0][0] I1=ind[0][1] x_rho, y_rho = self.convert_utm(lon_rho, lat_rho) #### convert to utm for interpolation y_rho_ss = y_rho[J0:J1,I0:I1] ##subset x,y x_rho_ss = x_rho[J0:J1,I0:I1] mask_rho_ss = mask_rho[J0:J1,I0:I1] h_ss = h[J0:J1,I0:I1] xy_rho = np.vstack((x_rho_ss[mask_rho_ss==1],y_rho_ss[mask_rho_ss==1])).T Fh = interpXYZ(xy_rho, xy_new) hout = np.zeros((xnew.shape[0], xnew.shape[1])) print "interpolating ROMS depth h onto the new rectilinear grid!!! \n" #### Loop through time to do the interpolation #### htem = Fh(h_ss[:,:][mask_rho_ss==1].flatten()) hout[:,:] = htem.reshape(xnew.shape[0], xnew.shape[1]) return hout
def extract_HC(modfile,lon,lat,z=None,conlist=None): """ Extract harmonic constituents from OTIS binary output and interpolate onto points in lon,lat set "z" to specifiy depth for transport to velocity conversion set "constituents" in conlist Returns: u_re, u_im, v_re, v_im, h_re, h_im, omega, conlist """ ### # Make sure the longitude is between 0 and 360 lon = np.mod(lon,360.0) ### # Read the filenames from the model file pathfile = os.path.split(modfile) path = pathfile[0] f = open(modfile,'r') hfile = path+'/' + f.readline().strip() uvfile = path+'/' + f.readline().strip() grdfile = path+'/' + f.readline().strip() f.close() ### # Read the grid file X,Y,depth, mask = read_OTPS_grd(grdfile) #X[X>180.0] = 180.0 - X[X>180.0] mask = mask == 1 # Create an interpolation object sz = lon.shape lon = lon.ravel() lat = lat.ravel() nx = lon.size F= interpXYZ(np.vstack((X[mask],Y[mask])).T,np.vstack((lon,lat)).T,method='idw',NNear=3,p=1.0) # Interpolate the model depths onto the points if z is none if z == None: z = F(depth[mask]) else: z = np.abs(z) # make sure they are positive ### # Check that the constituents are in the file conOTIS = get_OTPS_constits(hfile) if conlist == None: conlist = conOTIS for vv in conlist: if not vv in conOTIS: print 'Warning: constituent name: %s not present in OTIS file.'%vv conlist.remove(vv) ### # Now go through and read the data for each # Initialse the arrays ncon = len(conlist) u_re = np.zeros((ncon,nx)) u_im = np.zeros((ncon,nx)) v_re = np.zeros((ncon,nx)) v_im = np.zeros((ncon,nx)) h_re = np.zeros((ncon,nx)) h_im = np.zeros((ncon,nx)) omega = np.zeros((ncon,)) for ii, vv in enumerate(conlist): idx = otis_constits[vv]['index'] omega[ii] = otis_constits[vv]['omega'] print 'Interpolating consituent: %s...'%vv # Read and interpolate h X ,Y, tmp_h_re, tmp_h_im = read_OTPS_h(hfile,idx) h_re[ii,:] = F(tmp_h_re[mask]) h_im[ii,:] = F(tmp_h_im[mask]) # Read and interpolate u and v - Note the conversion from transport to velocity X ,Y, tmp_u_re, tmp_u_im, tmp_v_re, tmp_v_im = read_OTPS_UV(uvfile,idx) u_re[ii,:] = F(tmp_u_re[mask]) / z u_im[ii,:] = F(tmp_u_im[mask]) / z v_re[ii,:] = F(tmp_v_re[mask]) / z v_im[ii,:] = F(tmp_v_im[mask]) / z # Return the arrays in their original shape szout = (ncon,) + sz return u_re.reshape(szout), u_im.reshape(szout), v_re.reshape(szout), \ v_im.reshape(szout), h_re.reshape(szout), h_im.reshape(szout), omega, conlist
def avg_stress(self, tau_x, tau_y): """ funtion that does the average and interpolation of the stress """ vor_sun = vor_suntans(self.start, self.end) vor_sun.readFile(self.sunfile) xv = vor_sun.xv yv = vor_sun.yv Nt = vor_sun.Nt lon = self.data_roms['lon_psi'] lat = self.data_roms['lat_psi'] mask = self.data_roms['mask_psi'] #### Step 1) Prepare x, y coordinate to do the interpolation #### xroms = np.zeros_like(lon) yroms = np.zeros_like(lat) (y,x) = lon.shape for i in range(y): for j in range(x): (yroms[i,j],xroms[i,j])=utm.from_latlon(lat[i,j],lon[i,j])[0:2] #### Step 2) subset ROMS grid for interpolation #### SW=utm.to_latlon(xv.min(),yv.min(),15,'R') ###(lat, lon) NE=utm.to_latlon(xv.max(),yv.max(),15,'R') ind = self.findNearset(SW[1], SW[0], lon, lat) J0=ind[0][0] - 15 I0=ind[0][1] + 5 ind = self.findNearset(NE[1], NE[0], lon, lat) J1=ind[0][0] + 5 I1=ind[0][1] - 6 yss = yroms[J0:J1,I0:I1] ##subset x,y xss = xroms[J0:J1,I0:I1] maskss = mask[J0:J1,I0:I1] #### Step 3) Prepare the grid variables for the interpolation class #### xy_sun = np.vstack((yv.ravel(),xv.ravel())).T ## SUNTANS grid, xi: latitude, yi: longitude xy_new = np.vstack((xss[maskss==1],yss[maskss==1])).T ## subset ROMS grid Fs = interpXYZ(xy_sun,xy_new, method='idw') (Y, X) = xss.shape #### Initialize the output array @ subset roms grid #### tau_out_x = np.zeros((Nt, Y, X)) tau_out_y = np.zeros((Nt, Y, X)) #### Step 4) Loop througth time to do the interpolation #### for tstep in range(Nt): tau_tem_x = Fs(tau_x[tstep,:]) tau_tem_y = Fs(tau_y[tstep,:]) tau_out_x[tstep, maskss==1] = tau_tem_x tau_out_y[tstep, maskss==1] = tau_tem_y #### Step 5) do the 2D spatial average for stress #### lonss = lon[J0:J1,I0:I1] ## subset lon, lat latss = lat[J0:J1,I0:I1] tau_avg_x, lon_avg, lat_avg = vor_sun.average(tau_out_x, lonss, latss, maskss) tau_avg_y, lon_avg, lat_avg = vor_sun.average(tau_out_y, lonss, latss, maskss) #### Step 6) interpolate the averaged value to the original roms grid #### x_avg, y_avg = self.convert_utm(lon_avg, lat_avg) xy_avg = np.vstack((x_avg.flatten(), y_avg.flatten())).T Favg = interpXYZ(xy_avg, xy_new, method='idw') tau_avg_x2 = np.zeros((Nt, Y, X)) tau_avg_y2 = np.zeros((Nt, Y, X)) for tstep in range(Nt): tau_tem_x2 = Favg(tau_avg_x[tstep,:,:].flatten()) tau_tem_y2 = Favg(tau_avg_y[tstep,:,:].flatten()) tau_avg_x2[tstep,:,:][maskss==1] = tau_tem_x2 tau_avg_y2[tstep,:,:][maskss==1] = tau_tem_y2 maskss = vor_sun.obc_mask(lonss, latss, maskss) tau_avg_x2[:,maskss==0] = 0. tau_avg_y2[:,maskss==0] = 0. #### Step 7) interpolate the averaged value from ROMS grid to the new rectilinear grid #### new_lon, new_lat, dx, dy = self.rectilinear(self.nx,self.ny) new_SW=(new_lat.min(), new_lon.min()) ###(lat, lon) new_NE=(new_lat.max(), new_lon.max()) ind = self.findNearset(new_SW[1], new_SW[0], lonss, latss) J0=ind[0][0] I0=ind[0][1] ind = self.findNearset(new_NE[1], new_NE[0], lonss, latss) J1=ind[0][0] I1=ind[0][1] new_yss = yss[J0:J1,I0:I1] ##subset x,y from the subsetted ROMS grid to new grid new_xss = xss[J0:J1,I0:I1] new_maskss = maskss[J0:J1,I0:I1] tau_x_ss = tau_avg_x2[:,J0:J1,I0:I1] tau_y_ss = tau_avg_y2[:,J0:J1,I0:I1] xy_roms_ss = np.vstack((new_xss[new_maskss==1],new_yss[new_maskss==1])).T xnew, ynew = self.convert_utm(new_lon, new_lat) xy_new = np.vstack((xnew.ravel(),ynew.ravel())).T Fnew = interpXYZ(xy_roms_ss, xy_new) tau_x_new = np.zeros((Nt, xnew.shape[0], xnew.shape[1])) tau_y_new = np.zeros((Nt, xnew.shape[0], xnew.shape[1])) print "interpolating averaged stress onto the new rectilinear grid!!! \n" #### Loop through time to do the interpolation #### for tstep in range(Nt): tau_tem_x3 = Fnew(tau_x_ss[tstep,:,:][new_maskss==1].flatten()) tau_tem_y3 = Fnew(tau_y_ss[tstep,:,:][new_maskss==1].flatten()) tau_x_new[tstep,:,:] = tau_tem_x3.reshape(xnew.shape[0],xnew.shape[1]) tau_y_new[tstep,:,:] = tau_tem_y3.reshape(xnew.shape[0],xnew.shape[1]) # ###################################################################### # #### These are just for testing if the interpolation is correct #### # #### commented if not using #### # west=-95.42; east=-93.94 # south=28.39; north=29.90 # fig = plt.figure(figsize=(10,8)) # basemap = Basemap(projection='merc',llcrnrlat=south,urcrnrlat=north,\ # llcrnrlon=west,urcrnrlon=east, resolution='h') # # basemap.drawcoastlines() # basemap.fillcontinents(color='coral',lake_color='aqua') # basemap.drawcountries() # basemap.drawstates() # # llons, llats=basemap(lonss,latss) # con = basemap.pcolormesh(llons,llats,tau_avg_x2[-1,:,:]) # #con.set_clim(vmin=-0.08, vmax=0.03) # cbar = plt.colorbar(con, orientation='vertical') # cbar.set_label("stress") # plt.show() # ###################################################################### hout = self.interp_h(new_lon, new_lat) return tau_x_new, tau_y_new, hout
def vorticity_filtered(self, new_lon, new_lat): """ This function calls the vorticity class that calculates the filtered vorticity interpolate the filtered vorticity into the original ROMS grid interpolate the filtered vorticity into the new rectilinear grid Input: new grid Output: interpolated filtered vorticity """ #### Step 1) call vorticity class #### vor = vor_filter(self.start, self.end) w_filter, lon_avg, lat_avg, mask_avg = vor.vorticity_filter() ##Note: the mask_avg is not the same shape as other variables #### Step 2) interpolate the filtered vorticity into the original ROMS grid #### time = self.data_roms['time'] ## Note the lon, lat and mask should be the subsetted variables vor_sun = vor_suntans(self.start, self.end) vor_sun.readFile(self.sunfile) w_sun, lonss, latss, maskss = vor.vorticity_sun() #lon = self.data_roms['lon_rho'][1:-2,1:-2] #lat = self.data_roms['lat_rho'][1:-2,1:-2] #mask = self.data_roms['mask'][1:-2,1:-2] xroms, yroms = self.convert_utm(lonss, latss) xy_roms = np.vstack((xroms[maskss==1], yroms[maskss==1])).T x_avg, y_avg = self.convert_utm(lon_avg, lat_avg) xy_avg = np.vstack((x_avg.flatten(), y_avg.flatten())).T Favg = interpXYZ(xy_avg, xy_roms, method='idw') w_out = np.zeros((len(time), lonss.shape[0], lonss.shape[1])) for tstep in range(len(time)): w_tem = Favg(w_filter[tstep,:,:].flatten()) w_out[tstep,:,:][maskss==1] = w_tem w_out[np.isnan(w_out)] = 0. ## some nan value comes from interpolation #### mask the unuseful part of vorticity #### maskss = vor_sun.obc_mask(lonss, latss, maskss) w_out[:,maskss==0] = 0. #### Step 3) interpolate the filtered vorticity into the new rectilinear grid #### SW=(new_lat.min(), new_lon.min()) ###(lat, lon) NE=(new_lat.max(), new_lon.max()) ind = self.findNearset(SW[1], SW[0], lonss, latss) J0=ind[0][0] I0=ind[0][1] ind = self.findNearset(NE[1], NE[0], lonss, latss) J1=ind[0][0] I1=ind[0][1] yss = yroms[J0:J1,I0:I1] ##subset x,y xss = xroms[J0:J1,I0:I1] maskss = maskss[J0:J1,I0:I1] wss = w_out[:,J0:J1,I0:I1] xy_roms = np.vstack((xss[maskss==1],yss[maskss==1])).T xnew, ynew = self.convert_utm(new_lon, new_lat) xy_new = np.vstack((xnew.ravel(),ynew.ravel())).T Fw = interpXYZ(xy_roms, xy_new) X, Y = xnew.shape wnew = np.zeros((len(time), X, Y)) print "interpolating filtered vorticity onto the new rectilinear grid!!! \n" #### Loop through time to do the interpolation #### for tstep in range(len(time)): wtem = Fw(wss[tstep,:,:][maskss==1].flatten()) wnew[tstep,:,:] = wtem.reshape(X,Y) return wnew
def interp_roms_uv(self, new_lon, new_lat): """ function that interpolate the ROMS velocity Input: new grid Output: interpolated velocity field """ #### subset ROMS grid for interpolation #### #### Step 1) Prepare x, y coordinate and velocity to do the interpolation #### time = self.data_roms['time'] lon = self.data_roms['lon_rho'][1:-2,1:-2] lat = self.data_roms['lat_rho'][1:-2,1:-2] mask = self.data_roms['mask'][1:-2,1:-2] u = self.data_roms['u'] v = self.data_roms['v'] ang = self.data_roms['angle'][1:-2,1:-2] Nk = u.shape[1] # average u,v to central rho points uroms = np.zeros((len(time), Nk, mask.shape[0], mask.shape[1])) vroms = np.zeros((len(time), Nk, mask.shape[0], mask.shape[1])) for t in range(len(time)): for k in range(Nk): uroms[t,k,:,:] = self.shrink(u[t,k,:,:], mask.shape) vroms[t,k,:,:] = self.shrink(v[t,k,:,:], mask.shape) #### adjust velocity direction #### uroms, vroms = self.rot2d(uroms, vroms, ang) #### Step 2) subset ROMS grid for interpolation #### SW=(new_lat.min(), new_lon.min()) ###(lat, lon) NE=(new_lat.max(), new_lon.max()) ind = self.findNearset(SW[1], SW[0], lon, lat) J0=ind[0][0] I0=ind[0][1] ind = self.findNearset(NE[1], NE[0], lon, lat) J1=ind[0][0] I1=ind[0][1] xroms, yroms = self.convert_utm(lon, lat) #### convert to utm for interpolation yss = yroms[J0:J1,I0:I1] ##subset x,y xss = xroms[J0:J1,I0:I1] maskss = mask[J0:J1,I0:I1] u = uroms[:,:,J0:J1,I0:I1] v = vroms[:,:,J0:J1,I0:I1] #### Step 3) Prepare the grid variables for the interpolation class #### xy_roms = np.vstack((xss[maskss==1],yss[maskss==1])).T xnew, ynew = self.convert_utm(new_lon, new_lat) xy_new = np.vstack((xnew.ravel(),ynew.ravel())).T Fuv = interpXYZ(xy_roms, xy_new) X, Y = xnew.shape uout = np.zeros((len(time),Nk, X, Y)) vout = np.zeros((len(time),Nk, X, Y)) print "interpolating ROMS U, V velocity onto the new rectilinear grid!!! \n" #### Loop through time to do the interpolation #### for tstep in range(len(time)): for k in range(Nk): utem = Fuv(u[tstep,k,:,:][maskss==1].flatten()) vtem = Fuv(v[tstep,k,:,:][maskss==1].flatten()) uout[tstep,k,:,:] = utem.reshape(X,Y) vout[tstep,k,:,:] = vtem.reshape(X,Y) #pdb.set_trace() return uout[:,:,:,:], vout[:,:,:,:]