Beispiel #1
0
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)
Beispiel #4
0
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'
Beispiel #6
0
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
Beispiel #7
0
                    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)
Beispiel #11
0
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()
Beispiel #15
0
    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)