def bheatflx_artm_bamber(args, nc_seaRise, nc_base, base): """Get bheatflx and artm from the sea rise data. This function pulls in the `bheatflx` and `presartm` variables from the Sea Rise dataset and writes them to the base dataset as `bheatflx` and `artm`. NetCDF attributes are preserved. Parameters ---------- args : Namespace() object holding parsed command line arguments. nc_seaRise : An opened netCDF Dataset containing the Sea Rise data. nc_base : The created netCDF Dataset that will contain the base data. base : A DataGrid() class instance that holds the base data grid information. """ seaRise_y = nc_seaRise.variables['y'] seaRise_ny = seaRise_y[:].shape[0] seaRise_x = nc_seaRise.variables['x'] seaRise_nx = seaRise_x[:].shape[0] # to convert to Bamber 1km grid seaRise_data = np.ndarray((base.ny, base.nx)) seaRise_y_equal_base = 100 seaRise_x_equal_base = 500 # get basal heat flux #-------------------- seaRise_data[:, :] = 0. seaRise_bheatflx = nc_seaRise.variables['bheatflx'] seaRise_data[seaRise_y_equal_base:seaRise_y_equal_base + seaRise_ny, seaRise_x_equal_base:seaRise_x_equal_base + seaRise_nx] = -seaRise_bheatflx[0, :, :] # invert sign! speak.verbose(args, " Writing bheatflx to base.") base_bheatflx = nc_base.createVariable('bheatflx', 'f4', ( 'y', 'x', )) base_bheatflx[:, :] = seaRise_data[:, :] copy_atts(seaRise_bheatflx, base_bheatflx) # get annual mean air temperature (2m) #------------------------------------- seaRise_data[:, :] = 0. seaRise_presartm = nc_seaRise.variables['presartm'] seaRise_data[seaRise_y_equal_base:seaRise_y_equal_base + seaRise_ny, seaRise_x_equal_base:seaRise_x_equal_base + seaRise_nx] = seaRise_presartm[0, :, :] speak.verbose(args, " Writing artm to base.") base_artm = nc_base.createVariable('artm', 'f4', ( 'y', 'x', )) base_artm[:, :] = seaRise_data[:, :] copy_atts(seaRise_presartm, base_artm)
def apply_mask(args, nc_mask, nc_base ): """Apply Zurich mask to thk and make usrf. This function pulls in the Zurich mask, applies it to the variable `thk` and then creates the variable `usrf.` Parameters ---------- args : Namespace() object holding parsed command line arguments. nc_mask : An opened netCDF Dataset containing the Zurich mask. nc_base : The created netCDF Dataset that contains the base data. """ base_thk = nc_base.variables['thk'] thk_data = base_thk[:,:] base_topg = nc_base.variables['topg'] topg_data = base_topg[:,:] mask = nc_mask.variables['IceSheetMask'] speak.verbose(args," Applying mask to thk.") thk_data = thk_data * mask[:,:] base_thk[:,:] = thk_data speak.verbose(args," Creating usrf.") base_usrf = nc_base.createVariable('usrf', 'f4',('y','x',)) base_usrf[:,:] = thk_data + topg_data
def velocity_bamber(args, nc_insar, nc_base, trans): """Get the velocities from the insar data. This function pulls in the `vx`, `vy`, `ex` and `ey` variables from the InSAR dataset and writes them to the base dataset. NetCDF attributes are preserved. Parameters ---------- args : Namespace() object holding parsed command line arguments. nc_insar : An opened netCDF Dataset containing the InSAR data. nc_base : The created netCDF Dataset that will contain the base data. trans : A DataGrid() class instance that holds the base data grid transformed to the EPSG:3413 projection. """ insar_y = nc_insar.variables['y'] insar_ny = insar_y[:].shape[0] insar_x = nc_insar.variables['x'] insar_nx = insar_x[:].shape[0] base_data = np.ndarray((trans.ny, trans.nx)) for vv in ['vy', 'vx', 'ey', 'ex']: insar_data[:, :] = 0. base_data[:, :] = 0. insar_var = nc_insar.variables[vv] insar_data = np.ma.masked_values( nc_bamber.variables[var_list[1]][:, :], -2.e9) data_min = insar_data.min() data_max = insar_data.max() speak.verbose(args, " Interpolating " + vv + ".") insar_to_base = scipy.interpolate.RectBivariateSpline( insar_y[:], insar_x[:], insar_data, kx=1, ky=1, s=0) # regular 2d linear interp. but faster for ii in range(0, trans.nx): base_data[:, ii] = insar_to_base.ev(trans.y_grid[:, ii], trans.x_grid[:, ii]) base_data[base_data < data_min] = -2.e9 base_data[base_data > data_max] = -2.e9 speak.verbose(args, " Writing " + vv + " to base.") base_var = nc_base.createVariable(vv, 'f4', ( 'y', 'x', )) base_var[:, :] = base_data[:, :] copy_atts(insar_var, base_var)
def acab_epsg3413(args, nc_racmo, nc_bamber, nc_base, base, proj_epsg3413, proj_eigen_gl04c): bamber = projections.DataGrid() bamber.y = nc_bamber.variables['projection_y_coordinate'] bamber.x = nc_bamber.variables['projection_x_coordinate'] bamber.ny = bamber.y[:].shape[0] bamber.nx = bamber.x[:].shape[0] bamber.make_grid() speak.verbose(args, ' Interpolating smb to acab in base grid.') sys.stdout.write(" [%-60s] %d%%" % ('=' * 0, 0.)) sys.stdout.flush() racmo_data = nc_racmo.variables['smb'][:, ::-1].transpose() / 910. racmo_data = np.ma.masked_invalid( racmo_data) # find invalid data and create a mask racmo_data = racmo_data.filled(0.) # fill invalid data with zeros base2bamber = projections.transform(base, proj_epsg3413, proj_eigen_gl04c) racmo_interp = scipy.interpolate.RectBivariateSpline( bamber.y[:], bamber.x[:], racmo_data, kx=1, ky=1, s=0) # regular 2d linear interp. but faster base_bamber = np.zeros(base.dims) for ii in range(0, base.nx): ctr = (ii * 60) / base.nx sys.stdout.write("\r [%-60s] %d%%" % ('=' * ctr, ctr / 60. * 100.)) sys.stdout.flush() base_bamber[:, ii] = racmo_interp.ev(base2bamber.y_grid[:, ii], base2bamber.x_grid[:, ii]) sys.stdout.write("\r [%-60s] %d%%\n" % ('=' * 60, 100.)) sys.stdout.flush() #NOTE: RectBivariateSpline extrapolates data outside the convex hull # (constant value), so, we need to create a mask for values outisde # the IceBridge convex hull... base_y_mask = np.ma.masked_outside(base2bamber.y_grid, bamber.y[0], bamber.y[-1]) base_x_mask = np.ma.masked_outside(base2bamber.x_grid, bamber.x[0], bamber.x[-1]) base_masked = np.ma.masked_array(base_bamber, mask=np.logical_or( base_y_mask.mask, base_x_mask.mask)) base.var = nc_base.createVariable('acab', 'f4', ( 'y', 'x', )) base.var[:] = base_masked.filled(0.) base.var.long_name = 'Water Equivalent Surface Mass Balance' base.var.standard_name = 'land_ice_lwe_surface_specific_mass_balance' base.var.units = 'mm/year' base.var.grid_mapping = 'epsg_3413' base.var.coordinates = 'lon lat' base.var.source = 'Ian Howat' base.var.comments = '1961--1990 mean surface mass balance from RACMO 2.0 '
def velocity_epsg3413(args, nc_insar, nc_base, base): insar = projections.DataGrid() insar.y = nc_insar.variables['y'] insar.x = nc_insar.variables['x'] insar.ny = insar.y[:].shape[0] insar.nx = insar.x[:].shape[0] insar.make_grid() for var in ['vy', 'vx', 'ey', 'ex']: speak.verbose(args, ' Interpolating ' + var + ' and writing to base.') sys.stdout.write(" [%-60s] %d%%" % ('=' * 0, 0.)) sys.stdout.flush() insar_data = np.ma.masked_values(nc_insar.variables[var][:, :], -2.e9) data_min = insar_data.min() data_max = insar_data.max() insar_to_base = scipy.interpolate.RectBivariateSpline( insar.y[:], insar.x[:], insar_data, kx=1, ky=1, s=0) # regular 2d linear interp. but faster base_data = np.zeros(base.dims) for ii in range(0, base.nx): ctr = (ii * 60) / base.nx sys.stdout.write("\r [%-60s] %d%%" % ('=' * ctr, ctr / 60. * 100.)) sys.stdout.flush() base_data[:, ii] = insar_to_base.ev(base.y_grid[:, ii], base.x_grid[:, ii]) sys.stdout.write("\r [%-60s] %d%%\n" % ('=' * 60, 100.)) sys.stdout.flush() base_data[base_data < data_min] = -2.e9 base_data[base_data > data_max] = -2.e9 base.var = nc_base.createVariable(var, 'f4', ( 'y', 'x', )) base.var[:] = base_data[:] copy_atts(nc_insar.variables[var], base.var) base.var.grid_mapping = 'epsg_3413' base.var.coordinates = 'lon lat'
def acab_bamber(args, nc_racmo2p0, nc_base, base): """Get acab from the RACMO 2.0 data. This function pulls in the `smb` variable from the RACMO 2.0 dataset and writes it to the base dataset as `acab`. NetCDF attributes are preserved. Parameters ---------- args : Namespace() object holding parsed command line arguments. nc_racmo2p0 : An opened netCDF Dataset containing the RACMO 2.0 data. nc_base : The created netCDF Dataset that will contain the base data. base : A DataGrid() class instance that holds the base data grid information. """ racmo2p0_data = np.ndarray((base.ny, base.nx)) racmo2p0_data[:, :] = 0. racmo2p0_smb = nc_racmo2p0.variables['smb'] racmo2p0_data[:, :] = racmo2p0_smb[:, ::-1].transpose() / 910. racmo2p0_data = np.ma.masked_invalid( racmo2p0_data) # find invalid data and create a mask racmo2p0_data = racmo2p0_data.filled(0.) # fill invalid data with zeros speak.verbose(args, " Writing acab to base.") base_acab = nc_base.createVariable('acab', 'f4', ( 'y', 'x', )) base_acab[:, :] = racmo2p0_data[:, :] copy_atts( racmo2p0_smb, base_acab) #FIXME: check atribute units -- divided by 910 earlier
action="store_true") volume.add_argument("-q", "--quiet", help="Run silently", action="store_true") args = parser.parse_args() speak.notquiet(args, "\nBuilding the Greenland datasets in the Bamber projection.") speak.notquiet(args, "=========================================================\n") # load in datasets speak.notquiet(args, "Loading the datasets.") from data import bamberdem nc_bamber = get_nc_file(lc_bamber, 'r') speak.verbose(args, " Found Bamber DEM") from data import searise nc_seaRise = get_nc_file(lc_seaRise, 'r') speak.verbose(args, " Found Sea Rise data") from data import racmo2p0 nc_racmo2p0 = get_nc_file(lc_racmo2p0, 'r') speak.verbose(args, " Found RACMO 2.0 data") from data import insar try: nc_insar = get_nc_file(lc_InSAR, 'r') except Exception: speak.verbose(args, "\n Building InSAR velocity dataset...\n") subprocess.call("python util/convert_velocities.py " +
args = parser.parse_args() f_1km = os.path.join(args.out_dir, f_1km) speak.notquiet( args, '\nBuilding the Greenland datasets in the EPSG:3413 projection.') speak.notquiet( args, '============================================================\n') # load in datasets speak.notquiet(args, 'Loading the datasets.') from data import epsg3413 f_epsg = abs_existing_file(lc_epsg) speak.verbose(args, ' Found EPSG:3413 grid specs') f_epsg_shr = args.shrink speak.verbose(args, ' Found shrunken EPSG:3413 grid specs') from data import bamberdem nc_bamber = get_nc_file(lc_bamber, 'r') speak.verbose(args, ' Found Bamber DEM') if not args.use_template: from data import searise nc_seaRise = get_nc_file(lc_seaRise, 'r') speak.verbose(args, ' Found Sea Rise data') from data import racmo2p0 nc_racmo2p0 = get_nc_file(lc_racmo2p0, 'r') speak.verbose(args, ' Found RACMO 2.0 data')
def add_time(args, f_base, f_1km, f_template): """Add the time dimension to a Bamber 1km DEM dataset and write config files. This function opens the base dataset, creates a new 1km dataset with the time dimension that has been shrunken to just around the ice sheet, and creates a CISM config file. NetCDF attributes are preserved. Parameters ---------- args : Namespace() object holding parsed command line arguments. f_base : Filename for the created netCDF Dataset that contains the base data. f_1km : Filename for the created netCDF Dataset that will contain the 1 km dataset. f_template : Filename for the template used to create the CISM config file. """ # shrink dataset to the ice sheet nc_base = Dataset(f_base, 'r') y_shrink = [100, 2900 + 1] #NOTE: python stop exclusive, nco stop inclusive! x_shrink = [500, 2000 + 1] #NOTE: python stop exclusive, nco stop inclusive! base = DataGrid() base.y = nc_base.variables['y'] base.x = nc_base.variables['x'] base.ny = base.y[y_shrink[0]:y_shrink[1]].shape[0] base.nx = base.x[x_shrink[0]:x_shrink[1]].shape[0] speak.verbose(args, " Writing " + f_1km) nc_1km = Dataset(f_1km, 'w', format='NETCDF4') nc_1km.createDimension('time', None) nc_1km.createDimension('y1', base.ny) nc_1km.createDimension('x1', base.nx) time = nc_1km.createVariable('time', 'f4', ('time', )) y1 = nc_1km.createVariable('y1', 'f4', ('y1', )) x1 = nc_1km.createVariable('x1', 'f4', ('x1', )) copy_atts(base.y, y1) copy_atts(base.x, x1) y1[:] = base.y[y_shrink[0]:y_shrink[1]] x1[:] = base.x[x_shrink[0]:x_shrink[1]] time[0] = 0. for var_name, var_data in nc_base.variables.iteritems(): if var_name not in ['x', 'y', 'lat', 'lon']: var_1km = nc_1km.createVariable(var_name, 'f4', ( 'time', 'y1', 'x1', )) var_1km[0, :, :] = var_data[y_shrink[0]:y_shrink[1], x_shrink[0]:x_shrink[1]] copy_atts(var_data, var_1km) elif var_name not in ['x', 'y']: var_1km = nc_1km.createVariable(var_name, 'f4', ( 'y1', 'x1', )) copy_atts(var_data, var_1km) var_1km[:, :] = var_data[y_shrink[0]:y_shrink[1], x_shrink[0]:x_shrink[1]] nc_base.close() nc_1km.close() os.chmod(f_1km, 0o644) # uses an octal number! speak.verbose(args, " Writing the 1km config file.") config.write(f_1km, f_template, base, 1)
def coarsen(args, f_base, f_template, coarse_list): """Coarsen an base dataset. This function opens the 1 km dataset and creates coarser resolution datasets. All NetCDF data attributes are preserved. Parameters ---------- args : Namespace() object holding parsed command line arguments. f_base : Filename for the base dataset to coarsen. f_template : Filename for the template used to create the CISM config files. coarse_list : List of resolutions to coarsen to. """ nc_base = Dataset(f_base, 'r') base = DataGrid() base.y = nc_base.variables['y1'] base.ny = base.y[:].shape[0] base.x = nc_base.variables['x1'] base.nx = base.x[:].shape[0] base.proj = nc_base.variables['epsg_3413'] coarse_names = [] for skip in coarse_list: coarse = DataGrid() coarse.ny = base.y[::skip].shape[0] coarse.nx = base.x[::skip].shape[0] idx = f_base.find('km') f_coarse = f_base[:idx - 1] + str(skip) + f_base[idx:] speak.verbose(args, " Writing " + f_coarse) nc_coarse = Dataset(f_coarse, 'w', format='NETCDF4') nc_coarse.createDimension('time', None) nc_coarse.createDimension('y1', coarse.ny) nc_coarse.createDimension('x1', coarse.nx) coarse.time = nc_coarse.createVariable('time', 'f4', ('time', )) coarse.y = nc_coarse.createVariable('y1', 'f4', ('y1', )) coarse.x = nc_coarse.createVariable('x1', 'f4', ('x1', )) copy_atts(base.y, coarse.y) copy_atts(base.x, coarse.x) coarse.y[:] = base.y[::skip] coarse.x[:] = base.x[::skip] coarse.time[0] = 0. coarse.proj = nc_coarse.createVariable('epsg_3413', 'b') copy_atts(base.proj, coarse.proj) for var_name, var_data in nc_base.variables.iteritems(): if var_name not in ['time', 'x1', 'y1', 'lat', 'lon', 'epsg_3413']: var_coarse = nc_coarse.createVariable(var_name, 'f4', ( 'time', 'y1', 'x1', )) var_coarse[0, :, :] = var_data[0, ::skip, ::skip] copy_atts(var_data, var_coarse) elif var_name not in ['time', 'x1', 'y1', 'epsg_3413']: var_coarse = nc_coarse.createVariable(var_name, 'f4', ( 'y1', 'x1', )) var_coarse[:, :] = var_data[::skip, ::skip] copy_atts(var_data, var_coarse) nc_coarse.close() # set file permissions os.chmod(f_coarse, 0o644) # uses an Octal number! # write config files speak.verbose(args, " Writing the " + str(skip) + " km config file.") config.write(f_coarse, f_template, coarse, skip)
def bheatflx_artm_epsg3413(args, nc_seaRise, nc_base, base, proj_epsg3413, proj_eigen_gl04c): seaRise = projections.DataGrid() seaRise.y = nc_seaRise.variables['y'] seaRise.x = nc_seaRise.variables['x'] seaRise.ny = seaRise.y[:].shape[0] seaRise.nx = seaRise.x[:].shape[0] seaRise.make_grid() base_vars = {'bheatflx': 'bheatflx', 'artm': 'presartm'} for base_var, sea_var in base_vars.iteritems(): speak.verbose( args, ' Interpolating ' + sea_var + ' to ' + base_var + ' in base grid.') sys.stdout.write(" [%-60s] %d%%" % ('=' * 0, 0.)) sys.stdout.flush() sea_data = nc_seaRise.variables[sea_var][0, :, :] base2bamber = projections.transform(base, proj_epsg3413, proj_eigen_gl04c) seaRise_interp = scipy.interpolate.RectBivariateSpline( seaRise.y[:], seaRise.x[:], sea_data, kx=1, ky=1, s=0) # regular 2d linear interp. but faster base_bamber = np.zeros(base.dims) for ii in range(0, base.nx): ctr = (ii * 60) / base.nx sys.stdout.write("\r [%-60s] %d%%" % ('=' * ctr, ctr / 60. * 100.)) sys.stdout.flush() base_bamber[:, ii] = seaRise_interp.ev(base2bamber.y_grid[:, ii], base2bamber.x_grid[:, ii]) sys.stdout.write("\r [%-60s] %d%%\n" % ('=' * 60, 100.)) sys.stdout.flush() #NOTE: RectBivariateSpline extrapolates data outside the convex hull # (constant value), so, we need to create a mask for values outisde # the IceBridge convex hull... base_y_mask = np.ma.masked_outside(base2bamber.y_grid, seaRise.y[0], seaRise.y[-1]) base_x_mask = np.ma.masked_outside(base2bamber.x_grid, seaRise.x[0], seaRise.x[-1]) base_masked = np.ma.masked_array(base_bamber, mask=np.logical_or( base_y_mask.mask, base_x_mask.mask)) if base_var != 'bheatflx': base_bamber[base_masked.mask] = -9999. base.var = nc_base.createVariable(base_var, 'f4', ( 'y', 'x', )) if base_var == 'bheatflx': base.var[:] = -base_bamber[:] # invert sign! else: base.var[:] = base_bamber[:] copy_atts_add_fill(nc_seaRise.variables[sea_var], base.var, -9999.) base.var.grid_mapping = 'epsg_3413' base.var.coordinates = 'lon lat'
def mcb_epsg3413(args, nc_massCon, nc_bamber, nc_base, base, proj_epsg3413, proj_eigen_gl04c): """The mass conserving bed data on CISM's ESPG:3413 grid. This function pulls in the `thickness` variable from the mass conserving bed dataset, interpolates it to CISM's EPSG:3413 grid, and writes it to the base dataset as `thk`. NetCDF attributes are mostly preserved, but the data is changed from type short to type float. """ massCon = projections.DataGrid() massCon.y = nc_massCon.variables['y'] massCon.x = nc_massCon.variables['x'] massCon.ny = massCon.y[:].shape[0] massCon.nx = massCon.x[:].shape[0] massCon.make_grid_flip_y() massCon.thickness = nc_massCon.variables['thickness'] massCon.thk = np.ndarray(massCon.dims) massCon.thk[:, :] = massCon.thickness[::-1, :] # y fliped bamber = projections.DataGrid() bamber.y = nc_bamber.variables['projection_y_coordinate'] bamber.x = nc_bamber.variables['projection_x_coordinate'] bamber.ny = bamber.y[:].shape[0] bamber.nx = bamber.x[:].shape[0] bamber.make_grid() speak.verbose(args, " Interpolating thickness and writing to base.") sys.stdout.write(" [%-60s] %d%%" % ('=' * 0, 0.)) sys.stdout.flush() massCon_to_base = scipy.interpolate.RectBivariateSpline( massCon.y[::-1], massCon.x[:], massCon.thk, kx=1, ky=1, s=0) # regular 2d linear interp. but faster base.thk = nc_base.createVariable('thk', 'f4', ( 'y', 'x', )) base.thk[:] = np.zeros(base.dims) for ii in range(0, base.nx): ctr = (ii * 60) / base.nx sys.stdout.write("\r [%-60s] %d%%" % ('=' * ctr, ctr / 60. * 100.)) sys.stdout.flush() base.thk[:, ii] = massCon_to_base.ev(base.y_grid[:, ii], base.x_grid[:, ii]) sys.stdout.write("\r [%-60s] %d%%\n" % ('=' * 60, 100.)) sys.stdout.flush() copy_atts_bad_fill(massCon.thickness, base.thk, -9999.) base.thk.grid_mapping = 'epsg_3413' base.thk.coordinates = 'lon lat' base.thk.reference = 'M. Morlighem, E. Rignot, J. Mouginot, H. Seroussi and E. Larour, Deeply incised submarine glacial valleys beneath the Greenland Ice Sheet, Nat. Geosci., 7, 418-422, 2014, doi:10.1038/ngeo2167, http://www.nature.com/ngeo/journal/vaop/ncurrent/full/ngeo2167.html' speak.verbose(args, " Interpolating, with priority, topg and topgerr.") speak.verbose(args, " Primary Data [IceBridge]: bed and errbed.") speak.verbose( args, " Secondary Data [BamberDEM]: BedrockElevation and BedrockError." ) #base_vars = {'topg':['bed','BedrockElevation']} #NOTE: topgerr accounts for ~10 min. of the runtime. base_vars = { 'topg': ['bed', 'BedrockElevation'], 'topgerr': ['errbed', 'BedrockError'] } for var, var_list in base_vars.iteritems(): speak.verbose(args, '\n Begin ' + var + ':') pri_data = np.ma.masked_equal( nc_massCon.variables[var_list[0]][::-1, :], -9999) sec_data = np.ma.masked_values(nc_bamber.variables[var_list[1]][:, :], -9999.) pri_range = [pri_data.min(), pri_data.max()] rng = [sec_data.min(), sec_data.max()] if pri_range[0] < rng[0]: rng[0] = pri_range[0] if pri_range[1] > rng[1]: rng[1] = pri_range[1] # fill in missing data values in the IceBridge data with the Bamber DEM speak.verbose(args, " Combining IceBridge and Bamber DEMs.") sys.stdout.write(" [%-60s] %d%%" % ('=' * 0, 0.)) sys.stdout.flush() massCon2bamber = projections.transform(massCon, proj_epsg3413, proj_eigen_gl04c) sec_interp = scipy.interpolate.RectBivariateSpline( bamber.y[::], bamber.x[:], sec_data, kx=1, ky=1, s=0) # regular 2d linear interp. but faster massCon_bamber = np.zeros(massCon.dims) for ii in range(0, massCon.nx): ctr = (ii * 60) / massCon.nx sys.stdout.write("\r [%-60s] %d%%" % ('=' * ctr, ctr / 60. * 100.)) sys.stdout.flush() massCon_bamber[:, ii] = sec_interp.ev(massCon2bamber.y_grid[:, ii], massCon2bamber.x_grid[:, ii]) sys.stdout.write("\r [%-60s] %d%%\n" % ('=' * 60, 100.)) sys.stdout.flush() pri_data.unshare_mask() pri_data[pri_data.mask] = massCon_bamber[pri_data.mask] # interpolate the Bamber DEM data to the base grid speak.verbose( args, " Interpolating extended Bamber DEM to base grid.") sys.stdout.write(" [%-60s] %d%%" % ('=' * 0, 0.)) sys.stdout.flush() base2bamber = projections.transform(base, proj_epsg3413, proj_eigen_gl04c) base_bamber = np.zeros(base.dims) for ii in range(0, base.nx): ctr = (ii * 60) / base.nx sys.stdout.write("\r [%-60s] %d%%" % ('=' * ctr, ctr / 60. * 100.)) sys.stdout.flush() base_bamber[:, ii] = sec_interp.ev(base2bamber.y_grid[:, ii], base2bamber.x_grid[:, ii]) sys.stdout.write("\r [%-60s] %d%%\n" % ('=' * 60, 100.)) sys.stdout.flush() # interpolate the filled IceBridge data to the base grid speak.verbose(args, " Interpolating combined dataset to base grid.") sys.stdout.write(" [%-60s] %d%%" % ('=' * 0, 0.)) sys.stdout.flush() pri_interp = scipy.interpolate.RectBivariateSpline( massCon.y[::-1], massCon.x[:], pri_data, kx=1, ky=1, s=0) # regular 2d linear interp. but faster base_mcb = np.zeros(base.dims) for ii in range(0, base.nx): ctr = (ii * 60) / base.nx sys.stdout.write("\r [%-60s] %d%%" % ('=' * ctr, ctr / 60. * 100.)) sys.stdout.flush() base_mcb[:, ii] = pri_interp.ev(base.y_grid[:, ii], base.x_grid[:, ii]) sys.stdout.write("\r [%-60s] %d%%\n" % ('=' * 60, 100.)) sys.stdout.flush() #NOTE: RectBivariateSpline extrapolates data outside the convex hull # (constant value), so, we need to create a mask for values outisde # the IceBridge convex hull... base_y_mask = np.ma.masked_outside(base.y_grid, massCon.y[0], massCon.y[-1]) base_x_mask = np.ma.masked_outside(base.x_grid, massCon.x[0], massCon.x[-1]) base_mcb_masked = np.ma.masked_array(base_mcb, mask=np.logical_or( base_y_mask.mask, base_x_mask.mask)) base_bamber[~base_mcb_masked.mask] = base_mcb_masked[~base_mcb_masked. mask] bamx = [ bamber.x[0], bamber.x[-1], bamber.x[-1], bamber.x[0], bamber.x[0] ] bamy = [ bamber.y[0], bamber.y[0], bamber.y[-1], bamber.y[-1], bamber.y[0] ] bam_shape = shape({ 'type': 'polygon', 'coordinates': [zip(bamx, bamy)] }) base_pts_in_bamber = zip(base2bamber.x_grid.flatten(), base2bamber.y_grid.flatten()) msk = np.ones(base2bamber.x_grid.size, dtype=bool) for ii in range(msk.size): msk[ii] = Point(base_pts_in_bamber[ii]).within(bam_shape) msk.shape = base2bamber.x_grid.shape #from pprint import pprint as pp #print(msk.size) #pp(msk) base_bamber[~msk] = -9999. #NOTE: Make sure all values fall within a reasonable range as # RectBivariateSpine interps using the missing values base_bamber[base_bamber < rng[0]] = -9999. base_bamber[base_bamber > rng[1]] = -9999. base.var = nc_base.createVariable(var, 'f4', ( 'y', 'x', )) base.var[:] = base_bamber[:] copy_atts_bad_fill(nc_massCon.variables[var_list[0]], base.var, -9999.) base.var.grid_mapping = 'epsg_3413' base.var.coordinates = 'lon lat' base.var.reference = 'M. Morlighem, E. Rignot, J. Mouginot, H. Seroussi and E. Larour, Deeply incised submarine glacial valleys beneath the Greenland Ice Sheet, Nat. Geosci., 7, 418-422, 2014, doi:10.1038/ngeo2167, http://www.nature.com/ngeo/journal/vaop/ncurrent/full/ngeo2167.html'
def mcb_bamber(args, nc_massCon, nc_bamber, nc_base, base, trans, proj_eigen_gl04c, proj_epsg3413): """The mass conserving bed data in the bamber projection. This function pulls in the `thickness` variable from the mass conserving bed dataset, interpolates it to the Bamber DEM, and writes it to the base dataset as `thk`. NetCDF attributes are mostly preserved, but the data is changed from type short to type float. This function then pulls in the `bed` and `errbed` variables from the mass conserving bed dataset, and the `bedrockElevation` and `bedrockError` variables from the Bamber dataset. Prioritizing the mass conserving bed data, the bedrock elevation and error is interpolated to the Bamber DEM and written as `topg` and `topgerr` respectively. Data attributes are taken from the mass conserving bed data, and the data is written as a float. Parameters ---------- args : Namespace() object holding parsed command line arguments. nc_massCon : An opened netCDF Dataset containing the Sea Rise data. nc_bamber : An opened netCDF Dataset containing the Sea Rise data. nc_base : The created netCDF Dataset that will contain the base data. base : A DataGrid() class instance that holds the base data grid information. trans : A DataGrid() class instance that holds the base data grid transformed to EPSG:3413. proj_eigen_gl04c : A proj class instance that holds the Bamber DEM projection. proj_epsg3413 : A proj class instance that holds the EPSG:3413 projection. """ massCon = projections.DataGrid() massCon.y = nc_massCon.variables['y'] massCon.x = nc_massCon.variables['x'] massCon.ny = massCon.y[:].shape[0] massCon.nx = massCon.x[:].shape[0] massCon.make_grid_flip_y() massCon.yx = np.ndarray((len(massCon.y_grid.ravel()), 2)) massCon.yx[:, 0] = massCon.y_grid.ravel() massCon.yx[:, 1] = massCon.x_grid.ravel() massCon.tree = scipy.spatial.cKDTree(massCon.yx) trans.yx = np.ndarray((len(trans.y_grid.ravel()), 2)) trans.yx[:, 0] = trans.y_grid.ravel() trans.yx[:, 1] = trans.x_grid.ravel() trans.qd, trans.qi = massCon.tree.query( trans.yx, k=1) # nearest neighbor in massCon for transformed base grid massCon.thickness = nc_massCon.variables['thickness'] massCon.thk = np.ndarray(massCon.dims) massCon.thk[:, :] = massCon.thickness[:: -1, :] # y fliped when compaired to Bamber speak.verbose(args, " Interpolating thickness.") massCon_to_base = scipy.interpolate.RectBivariateSpline( massCon.y[::-1], massCon.x[:], massCon.thk, kx=1, ky=1, s=0) # regular 2d linear interp. but faster trans.thk = np.zeros(trans.dims) for ii in range(0, base.nx): trans.thk[:, ii] = massCon_to_base.ev(trans.y_grid[:, ii], trans.x_grid[:, ii]) speak.verbose(args, " Writing thk to base.") base.thk = nc_base.createVariable('thk', 'f4', ( 'y', 'x', )) base.thk[:, :] = trans.thk[:, :] copy_atts_bad_fill(massCon.thickness, base.thk, -9999.) speak.verbose(args, " Interpolating, with priority, topg and topgerr.") speak.verbose(args, " Primary Data [IceBridge]: bed and errbed.") speak.verbose( args, " Secondary Data [BamberDEM]: BedrockElevation and BedrockError." ) pri_data = np.ma.masked_equal(nc_massCon.variables['bed'][::-1, :], -9999) sec_data = np.ma.masked_values( nc_bamber.variables['BedrockElevation'][:, :], -9999.) new_data = np.ma.array(np.zeros(base.dims), mask=np.zeros(base.dims)) pri_err = np.ma.masked_equal(nc_massCon.variables['errbed'][::-1, :], -9999) sec_err = np.ma.masked_values(nc_bamber.variables['BedrockError'][:, :], -9999.) new_err = np.ma.array(np.zeros(base.dims), mask=np.zeros(base.dims)) for ii in range(0, base.ny): for jj in range(0, base.nx): # make sure inside priority grid (massCon) if (trans.y_grid[ii, jj] < massCon.y_grid[0, 0] or trans.y_grid[ii, jj] > massCon.y_grid[-1, 0]): # outside y range if sec_data.mask[ii, jj]: new_data.mask[ii, jj] = True new_err.mask[ii, jj] = True continue else: tx, ty, td = pyproj.transform(proj_eigen_gl04c, proj_epsg3413, base.x_grid[ii, jj], base.y_grid[ii, jj], sec_data[ii, jj]) new_data[ii, jj] = td new_err[ii, jj] = sec_err[ii, jj] continue if (trans.x_grid[ii, jj] < massCon.x_grid[0, 0] or trans.x_grid[ii, jj] > massCon.x_grid[0, -1]): # outside x range if sec_data.mask[ii, jj]: new_data.mask[ii, jj] = True new_err.mask[ii, jj] = True continue else: tx, ty, td = pyproj.transform(proj_eigen_gl04c, proj_epsg3413, base.x_grid[ii, jj], base.y_grid[ii, jj], sec_data[ii, jj]) new_data[ii, jj] = td new_err[ii, jj] = sec_err[ii, jj] continue indx = np.ravel_multi_index((ii, jj), base.dims) # nearest neighbor indices nn_ii, nn_jj = np.unravel_index(trans.qi[indx], massCon.dims) # to find nearest neighbors quadrent i_s = -1 j_s = -1 # find quadrent point lies in if trans.y_grid[ii, jj] >= massCon.y_grid[nn_ii, nn_jj]: i_s = +1 if trans.x_grid[ii, jj] >= massCon.x_grid[nn_ii, nn_jj]: j_s = +1 # check for missing priority data! # NOTE: points are ordered as such: # # 0: (ii , jj ) # 1: (ii , jj+j_s) # 2: (ii+i_s, jj+j_s) # 3: (ii+i_s, jj ) # # Which, for an upper-right quadrent looks like: # # 3 ---- 2 # | | # | | # 0 ---- 1 # # Numbering in other quadrents is the reflection through the axis or axes # with negitive skip values (i_s or j_s). missing_points, interp_dict = interp.check_missing( pri_data, (nn_ii, nn_jj), i_s, j_s) missing_err_pts, err_dict = interp.check_missing( pri_err, (nn_ii, nn_jj), i_s, j_s) # get secondary data! if not missing_points: pass elif not sec_data.mask[ii, jj]: tx, ty, td = pyproj.transform(proj_eigen_gl04c, proj_epsg3413, base.x_grid[ii, jj], base.y_grid[ii, jj], sec_data[ii, jj]) if len(missing_points) <= 3: for point in missing_points: # use secondary data at (ii,jj) for missing points, but keep same interp weight! interp_dict[point] = td err_dict[point] = sec_err[ii, jj] else: new_data[ii, jj] = td new_err[ii, jj] = sec_err[ii, jj] continue else: new_data.mask[ii, jj] = True new_err.mask[ii, jj] = True continue # interpolate! alpha = (trans.y_grid[ii, jj] - massCon.y_grid[nn_ii, nn_jj]) / (massCon.dy * i_s) beta = (trans.x_grid[ii, jj] - massCon.x_grid[nn_ii, nn_jj]) / (massCon.dx * j_s) w = interp.linear_weights(alpha, beta) new_data[ii,jj] = interp_dict[ (nn_ii, nn_jj ) ]*w[0] \ +interp_dict[ (nn_ii, nn_jj+j_s) ]*w[1] \ +interp_dict[ (nn_ii+i_s,nn_jj+j_s) ]*w[2] \ +interp_dict[ (nn_ii+i_s,nn_jj ) ]*w[3] new_err[ii,jj] = err_dict[ (nn_ii, nn_jj ) ]*w[0] \ +err_dict[ (nn_ii, nn_jj+j_s) ]*w[1] \ +err_dict[ (nn_ii+i_s,nn_jj+j_s) ]*w[2] \ +err_dict[ (nn_ii+i_s,nn_jj ) ]*w[3] missing_points = None interp_dict = None err_dict = None # now transform new data back to bamber grid. temp_x_grid, temp_y_grid, temp_data = pyproj.transform( proj_epsg3413, proj_eigen_gl04c, trans.x_grid.flatten(), trans.y_grid.flatten(), new_data.flatten()) new_data[:, :] = temp_data.reshape(base.dims)[:, :] speak.verbose(args, " Writing topg topgerr to base.") base.topg = nc_base.createVariable('topg', 'f4', ( 'y', 'x', )) base.topg[:, :] = new_data.filled(-9999.)[:, :] copy_atts_bad_fill(nc_massCon.variables['bed'], base.topg, -9999.) base.topgerr = nc_base.createVariable('topgerr', 'f4', ( 'y', 'x', )) base.topgerr[:, :] = new_err.filled(-9999.)[:, :] copy_atts_bad_fill(nc_massCon.variables['errbed'], base.topgerr, -9999.)
def main(args): if args.write: nc_base = get_nc_file(args.input,'r+') else: nc_base = get_nc_file(args.input,'r') base = projections.DataGrid() base.y = nc_base.variables['y'] base.x = nc_base.variables['x'] base.ny = base.y[:].shape[0] base.nx = base.x[:].shape[0] base.make_grid() base.topg = nc_base.variables['topg'] base.thk = nc_base.variables['thk'] topg = base.topg[::-1,:].filled() ice = base.thk[::-1,:] islands = np.greater(topg, args.altitude) segments, ids = ndimage.label(islands) #sgmt = ndimage.measurements.find_objects(segments) speak.verbose(args, ' Number of distinct shallow regions found: {}'.format(ids)) mask = np.array(segments * -1.) # Set ocean mask[np.equal(mask,0)] = 1 labeled = np.copy(mask) # For viewing #NOTE: nx = 2480, ny = 2975; -1 for index gl_x = [1200, 1990, 1990, 1625, 1320, 720, 440, 440, 359, 540, 586, 618, 710, 774, 819, 878, 969, 1200] gl_y = [ 60, 344, 1680, 2225, 2940, 2940, 1995, 1168, 767, 523, 507, 493, 416, 391, 346, 305, 273, 60] shape_gl = shape({'type':'polygon', 'coordinates':[zip(gl_y, gl_x)]}) ei_x = [960, 773, 140, 140, 158, 122, 144, 115, 84, 65, 45, 34, 44, 60, 76, 183, 207, 359, 540, 586, 618, 710, 774, 819, 878, 969, 960] ei_y = [ 84, 24, 24, 200, 290, 377, 431, 503, 505, 495, 501, 536, 558, 594, 652, 737, 855, 767, 523, 507, 493, 416, 391, 346, 305, 273, 84] shape_ei = shape({'type':'polygon', 'coordinates':[zip(ei_y, ei_x)]}) for ii in range(mask.shape[0]): speak.progress(args, ii, mask.shape[0], width=60, char='=', indent=4) for jj in range(mask.shape[1]): if topg[ii,jj] == -9999.: mask[ii,jj] = 0 elif Point((ii,jj)).within(shape_gl): if ice[ii,jj] > 0: if ice[ii,jj] >= -1*topg[ii,jj]/R_RHO: mask[ii,jj] = 3 else: mask[ii,jj] = 4 elif topg[ii,jj] > 0: mask[ii,jj] = 2 else: mask[ii,jj] = 1 elif mask[ii,jj] == 1: continue elif Point((ii,jj)).within(shape_ei): if topg[ii,jj] > 0: mask[ii,jj] = -2 else: mask[ii,jj] = -1 else: mask[ii,jj] = -3 speak.progress(args, mask.shape[0], mask.shape[0], width=60, char='=', indent=4) if args.write: base.mask = nc_base.createVariable('mask', 'i4', ('y','x',) ) base.mask[:,:] = mask[::-1,:] base.mask.long_name = 'location type mask' base.mask.grid_mapping = 'epsg_3413' base.mask.coordinates = 'lon lat' base.source = 'Joseph H. Kennedy, ORNL' base.comment = 'Mask values: -3, shallow ocean or land outside paleo domain; '+ \ '-2, bare paleo land; '+ \ '-1, shallow paleo ocean; '+ \ '0, missing topg data; '+ \ '1, ocean; '+ \ '2, bare land; '+ \ '3, grounded ice; '+ \ '4, floating ice.' fig, ((ax1, ax2, ax3), (ax4, ax5, ax6)) = plt.subplots(2,3, figsize=(12,10), dpi=150) plt.rc('text', usetex=True) plt.rc('font', family='serif') ax1.imshow(topg, cmap='spectral', interpolation='nearest') ax1.set_title('Topography') ax2.imshow(islands, cmap='spectral', interpolation='nearest') ax2.set_title('Shallow regions') ax3.imshow(labeled, cmap='spectral', interpolation='nearest') ax3.set_title('Labeled regions') ax4.imshow(ice, cmap='spectral', interpolation='nearest') ax4.set_title('Ice thickness') ax5.imshow(mask, cmap='spectral', interpolation='nearest') ax5.set_title('Mask') ax6.imshow(mask, cmap='spectral', interpolation='nearest') ax6.autoscale(False) ax6.plot(gl_x, gl_y, '-ro') ax6.plot(ei_x, ei_y, '-bx') ax6.set_title('Mask with shapes') plt.tight_layout() plt.savefig('segments.png', bbox_inches='tight') if args.show: plt.show() nc_base.close()
args, "\nPlotting the representation of the Bamber grid in the EPSG:3413 projection" ) speak.notquiet( args, "==========================================================================\n" ) #================== # load in datasets #================== speak.notquiet(args, "Loading the datasets.") nc_template = get_nc_file(lc_template, 'r') nc_base = get_nc_file(lc_base, 'r') speak.verbose(args, " Found Bamber DEM") speak.verbose(args, "\n All data files found!") #===== Bamber DEM ====== # this is a 1km dataset #======================= speak.notquiet(args, "\nCreating the 1 km Bamber template grid."), template = projections.DataGrid() template.y = nc_template.variables['projection_y_coordinate'] template.x = nc_template.variables['projection_x_coordinate'] template.ny = template.y[:].shape[0] template.nx = template.x[:].shape[0] template.make_grid()
def add_time(args, f_base, f_1km, f_template, f_epsg_shrunk): """Add the time dimension to a EPSG:3413 1km dataset and write config files. This function opens the base dataset, creates a new 1km dataset with the time dimension that has been shrunken to just around the ice sheet, and creates a CISM config file. NetCDF attributes are preserved. Parameters ---------- args : Namespace() object holding parsed command line arguments. f_base : Filename for the created netCDF Dataset that contains the base data. f_1km : Filename for the created netCDF Dataset that will contain the 1 km dataset. f_template : Filename for the template used to create the CISM config file. """ # shrink dataset to the ice sheet nc_base = Dataset(f_base, 'r') base = DataGrid() base.y = nc_base.variables['y'] base.x = nc_base.variables['x'] with open(f_epsg_shrunk, 'r') as f: epsg = json.load(f) idx_left = (np.abs(base.x[:] - epsg['ll'][0])).argmin() idx_right = (np.abs(base.x[:] - epsg['ur'][0])).argmin() idx_lower = (np.abs(base.y[:] - epsg['ll'][1])).argmin() idx_upper = (np.abs(base.y[:] - epsg['ur'][1])).argmin() y_shrink = [idx_lower, idx_upper + 1 ] #NOTE: python stop exclusive, nco stop inclusive! x_shrink = [idx_left, idx_right + 1 ] #NOTE: python stop exclusive, nco stop inclusive! base.ny = base.y[y_shrink[0]:y_shrink[1]].shape[0] base.nx = base.x[x_shrink[0]:x_shrink[1]].shape[0] speak.verbose(args, " Writing " + f_1km) nc_1km = Dataset(f_1km, 'w', format='NETCDF4') nc_1km.createDimension('time', None) nc_1km.createDimension('y1', base.ny) nc_1km.createDimension('x1', base.nx) time = nc_1km.createVariable('time', 'f4', ('time', )) time.long_name = 'time' time.units = 'common_years since 2009-01-01 00:00:00' time.calendar = '365_day' time.comment = "The initial time here is an estimate of the nominal date for Joughin's 2015 "+ \ "InSAR data. Because this is a synthesis of datasets across many time periods, "+ \ "the inital date is inherently fuzzy and should be changed to suit your purposes." y1 = nc_1km.createVariable('y1', 'f4', ('y1', )) x1 = nc_1km.createVariable('x1', 'f4', ('x1', )) copy_atts(base.y, y1) copy_atts(base.x, x1) y1[:] = base.y[y_shrink[0]:y_shrink[1]] x1[:] = base.x[x_shrink[0]:x_shrink[1]] time[0] = 0. base.proj = nc_base.variables['epsg_3413'] proj = nc_1km.createVariable('epsg_3413', 'b') copy_atts(base.proj, proj) for var_name, var_data in nc_base.variables.iteritems(): if var_name not in ['x', 'y', 'lat', 'lon', 'epsg_3413']: var_1km = nc_1km.createVariable(var_name, 'f4', ( 'time', 'y1', 'x1', )) copy_atts(var_data, var_1km) var_1km[0, :, :] = var_data[y_shrink[0]:y_shrink[1], x_shrink[0]:x_shrink[1]] elif var_name not in ['x', 'y', 'epsg_3413']: var_1km = nc_1km.createVariable(var_name, 'f4', ( 'y1', 'x1', )) copy_atts(var_data, var_1km) var_1km[:, :] = var_data[y_shrink[0]:y_shrink[1], x_shrink[0]:x_shrink[1]] nc_base.close() nc_1km.close() os.chmod(f_1km, 0o644) # uses an octal number! speak.verbose(args, " Writing the 1km config file.") config.write(f_1km, f_template, base, 1)