def __interp2_thread(rx, ry, data, zx, zy, pmap, weight, nx, ny, mask): """ internal routine: 2D interpolation thread for parallel interpolation """ data = np.ma.fix_invalid(data, copy=False) # Convolve the water over the land ksize = 2 * np.round( np.sqrt((nx / np.ma.median(np.ma.diff(rx)))**2 + (ny / np.ma.median(np.ma.diff(ry.T)))**2)) + 1 if ksize < _ksize_range[0]: warn("nx or ny values are too small for stable OA, {:f}".format(ksize)) ksize = _ksize_range[0] elif ksize > _ksize_range[1]: warn("nx or ny values are too large for stable OA, {:f}".format(ksize)) ksize = _ksize_range[1] data = seapy.convolve_mask(data, ksize=ksize, copy=False) # Interpolate the field and return the result with timeout(minutes=30): res, pm = seapy.oasurf(rx, ry, data, zx, zy, pmap, weight, nx, ny) return np.ma.masked_where(np.logical_or(mask == 0, np.abs(res) > 9e4), res, copy=False)
def v2rho(v, fill=False): """ Put the v field onto the rho field for the c-grid Parameters ---------- v : masked array like Input v field fill : bool, optional Fill the masked data before moving grids Returns ------- rho : masked array """ v = np.ma.array(v, copy=False) if fill: v = seapy.convolve_mask(v, copy=True) shp = np.array(v.shape) nshp = shp.copy() nshp[-2] = nshp[-2] + 1 fore = np.product([shp[i] for i in np.arange(0, v.ndim - 2)]).astype(int) nfld = np.ones([fore, nshp[-2], nshp[-1]]) nfld[:, 1:-1, :] = 0.5 * \ (v.reshape([fore, shp[-2], shp[-1]])[:, 0:-1, :].filled(np.nan) + v.reshape([fore, shp[-2], shp[-1]])[:, 1:, :].filled(np.nan)) nfld[:, 0, :] = nfld[:, 1, :] + (nfld[:, 2, :] - nfld[:, 3, :]) nfld[:, -1, :] = nfld[:, -2, :] + (nfld[:, -2, :] - nfld[:, -3, :]) return np.ma.fix_invalid(nfld.reshape(nshp), copy=False, fill_value=1e+37)
def v2rho(v, fill=False): """ Put the v field onto the rho field for the c-grid Parameters ---------- v : masked array like Input v field fill : bool, optional Fill the masked data before moving grids Returns ------- rho : masked array """ v = np.ma.array(v, copy=False) if fill: v = seapy.convolve_mask(v, copy=True) shp = np.array(v.shape) nshp = shp.copy() nshp[-2] = nshp[-2] + 1 fore = np.product([shp[i] for i in np.arange(0, v.ndim - 2)]).astype(int) nfld = np.ones([fore, nshp[-2], nshp[-1]]) nfld[:, 1:-1, :] = 0.5 * \ (v.reshape([fore, shp[-2], shp[-1]])[:, 0:-1, :].filled(np.nan) + v.reshape([fore, shp[-2], shp[-1]])[:, 1:, :].filled(np.nan)) nfld[:, 0, :] = nfld[:, 1, :] + (nfld[:, 2, :] - nfld[:, 3, :]) nfld[:, -1, :] = nfld[:, -2, :] + (nfld[:, -2, :] - nfld[:, -3, :]) return np.ma.fix_invalid(nfld.reshape(nshp), copy=False, fill_value=1e+37)
def u2rho(u, fill=False): """ Put the u field onto the rho field for the c-grid Parameters ---------- u : masked array like Input u field fill : bool, optional Fill the masked data before moving grids Returns ------- rho : masked array """ u = np.ma.array(u, copy=False) if fill: u = seapy.convolve_mask(u, copy=True) shp = np.array(u.shape) nshp = shp.copy() nshp[-1] = nshp[-1] + 1 fore = np.product([shp[i] for i in np.arange(0, u.ndim - 1)]).astype(int) nfld = np.ones([fore, nshp[-1]]) nfld[:, 1:-1] = 0.5 * \ (u.reshape([fore, shp[-1]])[:, 0:-1].filled(np.nan) + u.reshape([fore, shp[-1]])[:, 1:].filled(np.nan)) nfld[:, 0] = nfld[:, 1] + (nfld[:, 2] - nfld[:, 3]) nfld[:, -1] = nfld[:, -2] + (nfld[:, -2] - nfld[:, -3]) return np.ma.fix_invalid(nfld.reshape(nshp), copy=False, fill_value=1e+37)
def u2rho(u, fill=False): """ Put the u field onto the rho field for the c-grid Parameters ---------- u : masked array like Input u field fill : bool, optional Fill the masked data before moving grids Returns ------- rho : masked array """ u = np.ma.array(u, copy=False) if fill: u = seapy.convolve_mask(u, copy=True) shp = np.array(u.shape) nshp = shp.copy() nshp[-1] = nshp[-1] + 1 fore = np.product([shp[i] for i in np.arange(0, u.ndim - 1)]).astype(int) nfld = np.ones([fore, nshp[-1]]) nfld[:, 1:-1] = 0.5 * \ (u.reshape([fore, shp[-1]])[:, 0:-1].filled(np.nan) + u.reshape([fore, shp[-1]])[:, 1:].filled(np.nan)) nfld[:, 0] = nfld[:, 1] + (nfld[:, 2] - nfld[:, 3]) nfld[:, -1] = nfld[:, -2] + (nfld[:, -2] - nfld[:, -3]) return np.ma.fix_invalid(nfld.reshape(nshp), copy=False, fill_value=1e+37)
def __init__(self, grid, dt, reftime=seapy.default_epoch, ssh_mean=None, ssh_error=0.05): if ssh_mean is not None: self.ssh_mean = seapy.convolve_mask(ssh_mean, ksize=5, copy=True) else: self.ssh_mean = None self.ssh_error = ssh_error super().__init__(grid, dt, reftime)
def __init__(self, grid, dt, reftime=seapy.default_epoch, ssh_mean=None, ssh_error=0.05): if ssh_mean is not None: self.ssh_mean = seapy.convolve_mask(ssh_mean, ksize=5, copy=True) else: self.ssh_mean = None self.ssh_error = ssh_error super().__init__(grid, dt, reftime)
def __init__(self, grid, dt, reftime=seapy.default_epoch, ssh_mean=None, ssh_error=None, repeat=3, provenance="SSH"): self.provenance = provenance.upper() self.repeat = repeat self.ssh_error = ssh_error if ssh_error else _aviso_sla_errors if ssh_mean is not None: self.ssh_mean = seapy.convolve_mask(ssh_mean, ksize=5, copy=True) else: self.ssh_mean = None super().__init__(grid, dt, reftime)
def __init__(self, grid, dt, reftime=seapy.default_epoch, ssh_mean=None, ssh_error=None, repeat=3, provenance="SSH"): self.provenance = provenance.upper() self.repeat = repeat self.ssh_error = ssh_error if ssh_error else _aviso_sla_errors if ssh_mean is not None: self.ssh_mean = seapy.convolve_mask(ssh_mean, ksize=5, copy=True) else: self.ssh_mean = None super().__init__(grid, dt, reftime)
def gen_direct_forcing(his_file, frc_file): """ Generate a direct forcing file from a history (or other ROMS output) file. It requires that sustr, svstr, shflux, and ssflux (or swflux) with salt be available. This will generate a forcing file that contains: sustr, svstr, swflux, and ssflux. Parameters ---------- his_file: string, The ROMS history (or other) file(s) (can use wildcards) that contains the fields to make forcing from frc_file: string, The output forcing file Returns ------- None: Generates an output file of bulk forcings """ import os infile = seapy.netcdf(his_file) ref, _ = seapy.roms.get_reftime(infile) # Create the output file nc = seapy.roms.ncgen.create_frc_direct(frc_file, eta_rho=infile.dimensions[ 'eta_rho'].size, xi_rho=infile.dimensions[ 'xi_rho'].size, reftime=ref, clobber=True, title="Forcing from " + os.path.basename(his_file)) # Copy the data over nc.variables['SSS'][:] = infile.variables['salt'][:, -1, :, :] if 'EminusP' in infile.variables: nc.variables['swflux'][:] = infile.variables['EminusP'][:] elif 'swflux' in infile.variables: nc.variables['swflux'][:] = infile.variables['swflux'][:] else: nc.variables['swflux'][:] = infile.variables['ssflux'][:] \ / nc.variables['SSS'][:] nc.variables['frc_time'][:] = netCDF4.date2num(netCDF4.num2date( infile.variables['ocean_time'][:], infile.variables['ocean_time'].units), nc.variables['frc_time'].units) for f in seapy.progressbar.progress(("sustr", "svstr", "shflux", "swrad", "lat_rho", "lat_u", "lat_v", "lon_rho", "lon_u", "lon_v")): if f in infile.variables: nc.variables[f][:] = seapy.convolve_mask( infile.variables[f][:], copy=False) nc.close()
def _cgrid_rho_vel(rho, dim, fill): """ Private Method: Compute the u- or v-grid velocity from a rho-field for a c-grid """ rho = np.ma.array(rho, copy=False) if fill: rho = seapy.convolve_mask(rho, copy=True) shp = np.array(rho.shape) fore = np.product([shp[i] for i in np.arange(0, dim)]) aft = np.product([shp[i] for i in np.arange(dim + 1, rho.ndim)]) nfld = 0.5 * (rho.reshape([fore, shp[dim], aft])[:, 0:-1, :].filled(np.nan) + rho.reshape([fore, shp[dim], aft])[:, 1:, :].filled(np.nan)) shp[dim] = shp[dim] - 1 return np.ma.fix_invalid(nfld.reshape(shp), copy=False, fill_value=1e+37)
def _cgrid_rho_vel(rho, dim, fill): """ Private Method: Compute the u- or v-grid velocity from a rho-field for a c-grid """ rho = np.ma.array(rho, copy=False) if fill: rho = seapy.convolve_mask(rho, copy=True) shp = np.array(rho.shape) fore = np.product([shp[i] for i in np.arange(0, dim)]).astype(int) aft = np.product([shp[i] for i in np.arange(dim + 1, rho.ndim)]).astype(int) nfld = 0.5 * (rho.reshape([fore, shp[dim], aft])[:, 0:-1, :].filled( np.nan) + rho.reshape([fore, shp[dim], aft])[:, 1:, :].filled(np.nan)) shp[dim] = shp[dim] - 1 return np.ma.fix_invalid(nfld.reshape(shp), copy=False, fill_value=1e+37)
def __interp2_thread(rx, ry, data, zx, zy, pmap, weight, nx, ny, mask): """ internal routine: 2D interpolation thread for parallel interpolation """ data = np.ma.fix_invalid(data, copy=False) # Convolve the water over the land ksize = 2 * np.round(np.sqrt((nx / np.median(np.diff(rx)))**2 + (ny / np.median(np.diff(ry.T)))**2)) + 1 if ksize < _ksize_range[0]: warn("nx or ny values are too small for stable OA, {:f}".format(ksize)) ksize = _ksize_range[0] elif ksize > _ksize_range[1]: warn("nx or ny values are too large for stable OA, {:f}".format(ksize)) ksize = _ksize_range[1] data = seapy.convolve_mask(data, ksize=ksize, copy=False) # Interpolate the field and return the result with timeout(minutes=30): res, pm = seapy.oasurf(rx, ry, data, zx, zy, pmap, weight, nx, ny) return np.ma.masked_where(np.logical_or(mask == 0, np.abs(res) > 9e4), res, copy=False)
def __interp3_thread(rx, ry, rz, data, zx, zy, zz, pmap, weight, nx, ny, mask, up_factor=1.0, down_factor=1.0): """ internal routine: 3D interpolation thread for parallel interpolation """ # Make the mask 3D mask = seapy.adddim(mask, zz.shape[0]) data = np.ma.fix_invalid(data, copy=False) # To avoid extrapolation, we are going to convolve ocean over the land # and add a new top and bottom layer that replicates the data of the # existing current and top. 1) iteratively convolve until we have # filled most of the points, 2) Determine which way the # depth goes and add/subtract new layers, and 3) fill in masked values # from the layer above/below. gradsrc = (rz[0, 1, 1] - rz[-1, 1, 1]) > 0 # Convolve the water over the land ksize = 2 * np.round(np.sqrt((nx / np.median(np.diff(rx)))**2 + (ny / np.median(np.diff(ry.T)))**2)) + 1 if ksize < _ksize_range[0]: warn("nx or ny values are too small for stable OA, {:f}".format(ksize)) ksize = _ksize_range[0] elif ksize > _ksize_range[1]: warn("nx or ny values are too large for stable OA, {:f}".format(ksize)) ksize = _ksize_range[1] # Iterate at most 5 times, but we will hopefully break out before that by # checking if we have filled at least 40% of the bottom to be like # the surface bot = -1 if gradsrc else 0 top = 0 if gradsrc else -1 topmask = np.maximum(1, np.ma.count_masked(data[top, :, :])) if np.ma.count_masked(data[bot, :, :]) > 0: for iter in range(5): # Check if we have most everything by checking the bottom data = seapy.convolve_mask(data, ksize=ksize + iter, copy=False) if topmask / np.maximum(1, np.ma.count_masked(data[bot, :, :])) > 0.4: break # Now fill vertically nrz = np.zeros((data.shape[0] + 2, data.shape[1], data.shape[2])) nrz[1:-1, :, :] = rz nrz[bot, :, :] = rz[bot, :, :] - 5000 nrz[top, :, :] = 1 if not gradsrc: # The first level is the bottom # factor = down_factor levs = np.arange(data.shape[0], 0, -1) - 1 else: # The first level is the top # factor = up_factor levs = np.arange(0, data.shape[0]) # Fill in missing values where we have them from the shallower layer for k in levs[1:]: if np.ma.count_masked(data[k, :, :]) == 0: continue idx = np.nonzero(np.logical_xor(data.mask[k, :, :], data.mask[k - 1, :, :])) data.mask[k, idx[0], idx[1]] = data.mask[k - 1, idx[0], idx[1]] data[k, idx[0], idx[1]] = data[k - 1, idx[0], idx[1]] * down_factor # Add upper and lower boundaries ndat = np.zeros((data.shape[0] + 2, data.shape[1], data.shape[2])) ndat[bot, :, :] = data[bot, :, :].filled(np.nan) * down_factor ndat[1:-1, :, :] = data.filled(np.nan) ndat[top, :, :] = data[top, :, :].filled(np.nan) * up_factor # Interpolate the field and return the result with timeout(minutes=30): if gradsrc: res, pm = seapy.oavol(rx, ry, nrz[::-1, :, :], ndat[::-1, :, :], zx, zy, zz, pmap, weight, nx, ny) else: res, pm = seapy.oavol(rx, ry, nrz, ndat, zx, zy, zz, pmap, weight, nx, ny) return np.ma.masked_where(np.logical_or(mask == 0, np.abs(res) > 9e4), res, copy=False)
def __interp3_thread(rx, ry, rz, data, zx, zy, zz, pmap, weight, nx, ny, mask, up_factor=1.0, down_factor=1.0): """ internal routine: 3D interpolation thread for parallel interpolation """ # Make the mask 3D mask = seapy.adddim(mask, zz.shape[0]) data = np.ma.fix_invalid(data, copy=False) # To avoid extrapolation, we are going to convolve ocean over the land # and add a new top and bottom layer that replicates the data of the # existing current and top. 1) iteratively convolve until we have # filled most of the points, 2) Determine which way the # depth goes and add/subtract new layers, and 3) fill in masked values # from the layer above/below. gradsrc = (rz[0, 1, 1] - rz[-1, 1, 1]) > 0 # Convolve the water over the land ksize = 2 * np.round(np.sqrt((nx / np.median(np.diff(rx)))**2 + (ny / np.median(np.diff(ry.T)))**2)) + 1 if ksize < _ksize_range[0]: warn("nx or ny values are too small for stable OA, {:f}".format(ksize)) ksize = _ksize_range[0] elif ksize > _ksize_range[1]: warn("nx or ny values are too large for stable OA, {:f}".format(ksize)) ksize = _ksize_range[1] # Iterate at most 5 times, but we will hopefully break out before that by # checking if we have filled at least 40% of the bottom to be like # the surface bot = -1 if gradsrc else 0 top = 0 if gradsrc else -1 topmask = np.maximum(1, np.ma.count_masked(data[top, :, :])) if np.ma.count_masked(data[bot, :, :]) > 0: for iter in range(5): # Check if we have most everything by checking the bottom data = seapy.convolve_mask(data, ksize=ksize + iter, copy=False) if topmask / np.maximum(1, np.ma.count_masked(data[bot, :, :])) > 0.4: break # Now fill vertically nrz = np.zeros((data.shape[0] + 2, data.shape[1], data.shape[2])) nrz[1:-1, :, :] = rz nrz[bot, :, :] = rz[bot, :, :] - 5000 nrz[top, :, :] = 1 if not gradsrc: # The first level is the bottom # factor = down_factor levs = np.arange(data.shape[0], 0, -1) - 1 else: # The first level is the top # factor = up_factor levs = np.arange(0, data.shape[0]) # Fill in missing values where we have them from the shallower layer for k in levs[1:]: if np.ma.count_masked(data[k, :, :]) == 0: continue idx = np.nonzero(np.logical_xor(data.mask[k, :, :], data.mask[k - 1, :, :])) data.mask[k, idx[0], idx[1]] = data.mask[k - 1, idx[0], idx[1]] data[k, idx[0], idx[1]] = data[k - 1, idx[0], idx[1]] * down_factor # Add upper and lower boundaries ndat = np.zeros((data.shape[0] + 2, data.shape[1], data.shape[2])) ndat[bot, :, :] = data[bot, :, :].filled(np.nan) * down_factor ndat[1:-1, :, :] = data.filled(np.nan) ndat[top, :, :] = data[top, :, :].filled(np.nan) * up_factor # Interpolate the field and return the result with timeout(minutes=30): if gradsrc: res, pm = seapy.oavol(rx, ry, nrz[::-1, :, :], ndat[::-1, :, :], zx, zy, zz, pmap, weight, nx, ny) else: res, pm = seapy.oavol(rx, ry, nrz, ndat, zx, zy, zz, pmap, weight, nx, ny) return np.ma.masked_where(np.logical_or(mask == 0, np.abs(res) > 9e4), res, copy=False)
def gen_direct_forcing(his_file, frc_file, cdl=None): """ Generate a direct forcing file from a history (or other ROMS output) file. It requires that sustr, svstr, shflux, and ssflux (or swflux) with salt be available. This will generate a forcing file that contains: sustr, svstr, swflux, and ssflux. Parameters ---------- his_file: string, The ROMS history (or other) file(s) (can use wildcards) that contains the fields to make forcing from frc_file: string, The output forcing file cdl: string, optional, Use the specified CDL file as the definition for the new netCDF file. Returns ------- None: Generates an output file of bulk forcings """ import os infile = seapy.netcdf(his_file) ref, _ = seapy.roms.get_reftime(infile) # Create the output file nc = seapy.roms.ncgen.create_frc_direct( frc_file, eta_rho=infile.dimensions['eta_rho'].size, xi_rho=infile.dimensions['xi_rho'].size, reftime=ref, clobber=True, title="Forcing from " + os.path.basename(his_file), cdl=cdl) # Copy the data over time = seapy.roms.num2date(infile, 'ocean_time') nc.variables['frc_time'][:] = seapy.roms.date2num(time, nc, 'frc_time') for x in seapy.progressbar.progress(seapy.chunker(range(len(time)), 1000)): nc.variables['SSS'][x, :, :] = seapy.convolve_mask( infile.variables['salt'][x, -1, :, :], copy=False) if 'EminusP' in infile.variables: nc.variables['swflux'][x, :, :] = seapy.convolve_mask( infile.variables['EminusP'][x, :, :], copy=False) * 86400 elif 'swflux' in infile.variables: nc.variables['swflux'][x, :, :] = seapy.convolve_mask( infile.variables['swflux'][x, :, :], copy=False) else: nc.variables['swflux'][x, :, :] = seapy.convolve_mask( infile.variables['ssflux'][x, :, :] / nc.variables['SSS'][x, :, :], copy=False) nc.sync() for f in ("sustr", "svstr", "shflux", "swrad"): if f in infile.variables: nc.variables[f][x, :, :] = seapy.convolve_mask( infile.variables[f][x, :, :], copy=False) nc.sync() for f in ("lat_rho", "lat_u", "lat_v", "lon_rho", "lon_u", "lon_v"): if f in infile.variables: nc.variables[f][:] = infile.variables[f][:] nc.close()
def gen_direct_forcing(his_file, frc_file, cdl=None): """ Generate a direct forcing file from a history (or other ROMS output) file. It requires that sustr, svstr, shflux, and ssflux (or swflux) with salt be available. This will generate a forcing file that contains: sustr, svstr, swflux, and ssflux. Parameters ---------- his_file: string, The ROMS history (or other) file(s) (can use wildcards) that contains the fields to make forcing from frc_file: string, The output forcing file cdl: string, optional, Use the specified CDL file as the definition for the new netCDF file. Returns ------- None: Generates an output file of bulk forcings """ import os infile = seapy.netcdf(his_file) ref, _ = seapy.roms.get_reftime(infile) # Create the output file nc = seapy.roms.ncgen.create_frc_direct(frc_file, eta_rho=infile.dimensions[ 'eta_rho'].size, xi_rho=infile.dimensions[ 'xi_rho'].size, reftime=ref, clobber=True, title="Forcing from " + os.path.basename(his_file), cdl=cdl) # Copy the data over time = seapy.roms.num2date(infile, 'ocean_time') nc.variables['frc_time'][:] = seapy.roms.date2num(time, nc, 'frc_time') for x in seapy.progressbar.progress(seapy.chunker(range(len(time)), 1000)): nc.variables['SSS'][x, :, :] = seapy.convolve_mask( infile.variables['salt'][x, -1, :, :], copy=False) if 'EminusP' in infile.variables: nc.variables['swflux'][x, :, :] = seapy.convolve_mask( infile.variables['EminusP'][x, :, :], copy=False) * 86400 elif 'swflux' in infile.variables: nc.variables['swflux'][x, :, :] = seapy.convolve_mask( infile.variables['swflux'][x, :, :], copy=False) else: nc.variables['swflux'][x, :, :] = seapy.convolve_mask( infile.variables['ssflux'][x, :, :] / nc.variables['SSS'][x, :, :], copy=False) nc.sync() for f in ("sustr", "svstr", "shflux", "swrad"): if f in infile.variables: nc.variables[f][x, :, :] = seapy.convolve_mask( infile.variables[f][x, :, :], copy=False) nc.sync() for f in ("lat_rho", "lat_u", "lat_v", "lon_rho", "lon_u", "lon_v"): if f in infile.variables: nc.variables[f][:] = infile.variables[f][:] nc.close()