Example #1
0
def _distribute_thickness_per_interp(glacier_mask,
                                     topo,
                                     cls,
                                     fls,
                                     grid,
                                     smooth=True,
                                     add_slope=True):
    """Where the job is actually done."""

    # Thick to interpolate
    dx = grid.dx
    thick = np.where(glacier_mask, np.NaN, 0)

    # Along the lines
    vs = []
    for cl, fl in zip(cls, fls):
        # TODO: here one should see if parabola is always the best choice
        vs.extend(cl['volume'])
        x, y = utils.tuple2int(fl.line.xy)
        thick[y, x] = cl['thick']
    vol = np.sum(vs)

    # Interpolate
    xx, yy = grid.ij_coordinates
    pnan = np.nonzero(~np.isfinite(thick))
    pok = np.nonzero(np.isfinite(thick))
    points = np.array((np.ravel(yy[pok]), np.ravel(xx[pok]))).T
    inter = np.array((np.ravel(yy[pnan]), np.ravel(xx[pnan]))).T
    thick[pnan] = griddata(points, np.ravel(thick[pok]), inter, method='cubic')

    # Smooth
    if smooth:
        gsize = np.rint(cfg.PARAMS['smooth_window'] / dx)
        thick = gaussian_blur(thick, np.int(gsize))
        thick = np.where(glacier_mask, thick, 0.)

    # Slope
    slope = 1.
    if add_slope:
        sy, sx = np.gradient(topo, dx, dx)
        slope = np.arctan(np.sqrt(sy**2 + sx**2))
        slope = np.clip(slope, np.deg2rad(6.), np.pi / 2.)
        slope = 1 / slope**(cfg.N / (cfg.N + 2))

    # Conserve volume
    tmp_vol = np.nansum(thick * slope * dx**2)
    final_t = thick * slope * vol / tmp_vol

    # Add to grids
    final_t = np.where(np.isfinite(final_t), final_t, 0.)
    assert np.allclose(np.sum(final_t * dx**2), vol)
    return final_t
Example #2
0
def _distribute_thickness_per_interp(glacier_mask, topo, cls, fls, grid,
                                     smooth=True, add_slope=True):
    """Where the job is actually done."""

    # Thick to interpolate
    dx = grid.dx
    thick = np.where(glacier_mask, np.NaN, 0)

    # Along the lines
    vs = []
    for cl, fl in zip(cls, fls):
        # TODO: here one should see if parabola is always the best choice
        vs.extend(cl['volume'])
        x, y = utils.tuple2int(fl.line.xy)
        thick[y, x] = cl['thick']
    vol = np.sum(vs)

    # Interpolate
    xx, yy = grid.ij_coordinates
    pnan = np.nonzero(~ np.isfinite(thick))
    pok = np.nonzero(np.isfinite(thick))
    points = np.array((np.ravel(yy[pok]), np.ravel(xx[pok]))).T
    inter = np.array((np.ravel(yy[pnan]), np.ravel(xx[pnan]))).T
    thick[pnan] = griddata(points, np.ravel(thick[pok]), inter, method='cubic')

    # Smooth
    if smooth:
        gsize = np.rint(cfg.PARAMS['smooth_window'] / dx)
        thick = gaussian_blur(thick, np.int(gsize))
        thick = np.where(glacier_mask, thick, 0.)

    # Slope
    slope = 1.
    if add_slope:
        sy, sx = np.gradient(topo, dx, dx)
        slope = np.arctan(np.sqrt(sy**2 + sx**2))
        slope = np.clip(slope, np.deg2rad(6.), np.pi/2.)
        slope = 1 / slope**(cfg.N / (cfg.N+2))

    # Conserve volume
    tmp_vol = np.nansum(thick * slope * dx**2)
    final_t = thick * slope * vol / tmp_vol

    # Add to grids
    final_t = np.where(np.isfinite(final_t), final_t, 0.)
    assert np.allclose(np.sum(final_t * dx**2), vol)
    return final_t
Example #3
0
def _distribute_thickness_per_altitude(glacier_mask, topo, cls, fls, grid,
                                       add_slope=True,
                                       smooth=True):
    """Where the job is actually done."""

    # Along the lines
    dx = grid.dx
    hs, ts, vs, xs, ys = [], [], [], [] ,[]
    for cl, fl in zip(cls, fls):
        # TODO: here one should see if parabola is always the best choice
        hs = np.append(hs, cl['hgt'])
        ts = np.append(ts, cl['thick'])
        vs = np.append(vs, cl['volume'])
        x, y = fl.line.xy
        xs = np.append(xs, x)
        ys = np.append(ys, y)
    vol = np.sum(vs)

    # very inefficient inverse distance stuff
    to_compute = np.nonzero(glacier_mask)
    thick = topo * np.NaN
    for (y, x) in np.asarray(to_compute).T:
        assert glacier_mask[y, x] == 1
        phgt = topo[y, x]
        # take the ones in a 100m range
        starth = 100.
        while True:
            starth += 10
            pok = np.nonzero(np.abs(phgt - hs) <= starth)[0]
            if len(pok) != 0:
                break
        dis_w = 1 / np.sqrt((xs[pok]-x)**2 + (ys[pok]-y)**2)
        thick[y, x] = np.average(ts[pok], weights=dis_w)

    # Smooth
    if smooth:
        thick = np.where(np.isfinite(thick), thick, 0.)
        gsize = np.rint(cfg.PARAMS['smooth_window'] / dx)
        thick = gaussian_blur(thick, np.int(gsize))
    thick = np.where(glacier_mask, thick, 0.)

    # Distance
    dis = distance_transform_edt(glacier_mask)
    dis = np.where(glacier_mask, dis, np.NaN)**0.5

    # Slope
    slope = 1.
    if add_slope:
        sy, sx = np.gradient(topo, dx, dx)
        slope = np.arctan(np.sqrt(sy**2 + sx**2))
        slope = np.clip(slope, np.deg2rad(6.), np.pi/2.)
        slope = 1 / slope**(cfg.N / (cfg.N+2))

    # Conserve volume
    tmp_vol = np.nansum(thick * dis * slope * dx**2)
    final_t = thick * dis * slope * vol / tmp_vol

    # Done
    final_t = np.where(np.isfinite(final_t), final_t, 0.)
    assert np.allclose(np.sum(final_t * dx**2), vol)
    return final_t
Example #4
0
def glacier_masks_itmix(gdir):
    """Converts the glacier vector geometries to grids.

    Uses where possible the ITMIX DEM

    Parameters
    ----------
    gdir : oggm.GlacierDirectory
    """

    # open srtm tif-file:
    dem_ds = gdal.Open(gdir.get_filepath('dem'))
    dem = dem_ds.ReadAsArray().astype(float)

    # Correct the DEM (ASTER...)
    # Currently we just do a linear interp -- ASTER is totally shit anyway
    min_z = -999.
    if np.min(dem) <= min_z:
        xx, yy = gdir.grid.ij_coordinates
        pnan = np.nonzero(dem <= min_z)
        pok = np.nonzero(dem > min_z)
        if len(pok[0]) > 0:
            points = np.array((np.ravel(yy[pok]), np.ravel(xx[pok]))).T
            inter = np.array((np.ravel(yy[pnan]), np.ravel(xx[pnan]))).T
            dem[pnan] = griddata(points, np.ravel(dem[pok]), inter)
            msg = gdir.rgi_id + ': DEM needed interpolation'
            msg += '({:.1f}% missing).'.format(
                len(pnan[0]) / len(dem.flatten()) * 100)
            log.warning(msg)
        else:
            dem = dem * np.NaN

    # Replace DEM values with ITMIX ones where possible
    # Open DEM
    dem_f = None
    n_g = gdir.name.split(':')[-1]
    searchf = os.path.join(DATA_DIR, 'itmix', 'glaciers_sorted', '*')
    searchf = os.path.join(searchf, '02_surface_' + n_g + '_*.asc')
    for dem_f in glob.glob(searchf):
        pass

    if dem_f is None:
        # try synth
        n_g = gdir.rgi_id
        searchf = os.path.join(DATA_DIR, 'itmix', 'glaciers_synth', '*')
        searchf = os.path.join(searchf, '02_surface_' + n_g + '*.asc')
        for dem_f in glob.glob(searchf):
            pass

    if dem_f is not None:
        log.info('%s: ITMIX DEM file: %s', gdir.rgi_id, dem_f)
        it_dem_ds = EsriITMIX(dem_f)
        it_dem = it_dem_ds.get_vardata()
        it_dem = np.where(it_dem < -999., np.NaN, it_dem)

        # for some glaciers, trick
        if n_g in ['Academy', 'Devon']:
            it_dem = np.where(it_dem <= 0, np.NaN, it_dem)
            it_dem = np.where(np.isfinite(it_dem), it_dem, np.nanmin(it_dem))
        if n_g in ['Brewster', 'Austfonna']:
            it_dem = np.where(it_dem <= 0, np.NaN, it_dem)

        # Transform to local grid
        it_dem = gdir.grid.map_gridded_data(it_dem,
                                            it_dem_ds.grid,
                                            interp='linear')
        # And update values where possible
        if n_g in ['Synthetic2', 'Synthetic1']:
            dem = np.where(~it_dem.mask, it_dem, np.nanmin(it_dem))
        else:
            dem = np.where(~it_dem.mask, it_dem, dem)
    else:
        if 'Devon' in n_g:
            raise RuntimeError('Should have found DEM for Devon')

    # Disallow negative
    dem = dem.clip(0)

    # Grid
    nx = dem_ds.RasterXSize
    ny = dem_ds.RasterYSize
    assert nx == gdir.grid.nx
    assert ny == gdir.grid.ny

    # Proj
    geot = dem_ds.GetGeoTransform()
    x0 = geot[0]  # UL corner
    y0 = geot[3]  # UL corner
    dx = geot[1]
    dy = geot[5]  # Negative
    assert dx == -dy
    assert dx == gdir.grid.dx
    assert y0 == gdir.grid.corner_grid.y0
    assert x0 == gdir.grid.corner_grid.x0
    dem_ds = None  # to be sure...

    # Smooth SRTM?
    if cfg.PARAMS['smooth_window'] > 0.:
        gsize = np.rint(cfg.PARAMS['smooth_window'] / dx)
        smoothed_dem = gaussian_blur(dem, np.int(gsize))
    else:
        smoothed_dem = dem.copy()

    # Make entity masks
    log.debug('%s: glacier mask, divide %d', gdir.rgi_id, 0)
    _mask_per_divide(gdir, 0, dem, smoothed_dem)

    # Glacier divides
    nd = gdir.n_divides
    if nd == 1:
        # Optim: just make links
        linkname = gdir.get_filepath('gridded_data', div_id=1)
        sourcename = gdir.get_filepath('gridded_data')
        # overwrite as default
        if os.path.exists(linkname):
            os.remove(linkname)
        # TODO: temporary suboptimal solution
        try:
            # we are on UNIX
            os.link(sourcename, linkname)
        except AttributeError:
            # we are on windows
            copyfile(sourcename, linkname)
        linkname = gdir.get_filepath('geometries', div_id=1)
        sourcename = gdir.get_filepath('geometries')
        # overwrite as default
        if os.path.exists(linkname):
            os.remove(linkname)
        # TODO: temporary suboptimal solution
        try:
            # we are on UNIX
            os.link(sourcename, linkname)
        except AttributeError:
            # we are on windows
            copyfile(sourcename, linkname)
    else:
        # Loop over divides
        for i in gdir.divide_ids:
            log.debug('%s: glacier mask, divide %d', gdir.rgi_id, i)
            _mask_per_divide(gdir, i, dem, smoothed_dem)
Example #5
0
def glacier_masks_itmix(gdir):
    """Converts the glacier vector geometries to grids.

    Uses where possible the ITMIX DEM

    Parameters
    ----------
    gdir : oggm.GlacierDirectory
    """

    # open srtm tif-file:
    dem_ds = gdal.Open(gdir.get_filepath('dem'))
    dem = dem_ds.ReadAsArray().astype(float)

    # Correct the DEM (ASTER...)
    # Currently we just do a linear interp -- ASTER is totally shit anyway
    min_z = -999.
    if np.min(dem) <= min_z:
        xx, yy = gdir.grid.ij_coordinates
        pnan = np.nonzero(dem <= min_z)
        pok = np.nonzero(dem > min_z)
        if len(pok[0]) > 0:
            points = np.array((np.ravel(yy[pok]), np.ravel(xx[pok]))).T
            inter = np.array((np.ravel(yy[pnan]), np.ravel(xx[pnan]))).T
            dem[pnan] = griddata(points, np.ravel(dem[pok]), inter)
            msg = gdir.rgi_id + ': DEM needed interpolation'
            msg += '({:.1f}% missing).'.format(len(pnan[0])/len(dem.flatten())*100)
            log.warning(msg)
        else:
            dem = dem*np.NaN

    # Replace DEM values with ITMIX ones where possible
    # Open DEM
    dem_f = None
    n_g = gdir.name.split(':')[-1]
    searchf = os.path.join(DATA_DIR, 'itmix', 'glaciers_sorted', '*')
    searchf = os.path.join(searchf, '02_surface_' + n_g + '_*.asc')
    for dem_f in glob.glob(searchf):
        pass

    if dem_f is None:
        # try synth
        n_g = gdir.rgi_id
        searchf = os.path.join(DATA_DIR, 'itmix', 'glaciers_synth', '*')
        searchf = os.path.join(searchf, '02_surface_' + n_g + '*.asc')
        for dem_f in glob.glob(searchf):
            pass

    if dem_f is not None:
        log.info('%s: ITMIX DEM file: %s', gdir.rgi_id, dem_f)
        it_dem_ds = EsriITMIX(dem_f)
        it_dem = it_dem_ds.get_vardata()
        it_dem = np.where(it_dem < -999., np.NaN, it_dem)

        # for some glaciers, trick
        if n_g in ['Academy', 'Devon']:
            it_dem = np.where(it_dem <= 0, np.NaN, it_dem)
            it_dem = np.where(np.isfinite(it_dem), it_dem, np.nanmin(it_dem))
        if n_g in ['Brewster', 'Austfonna']:
            it_dem = np.where(it_dem <= 0, np.NaN, it_dem)

        # Transform to local grid
        it_dem = gdir.grid.map_gridded_data(it_dem, it_dem_ds.grid,
                                            interp='linear')
        # And update values where possible
        if  n_g in ['Synthetic2', 'Synthetic1']:
            dem = np.where(~ it_dem.mask, it_dem, np.nanmin(it_dem))
        else:
            dem = np.where(~ it_dem.mask, it_dem, dem)
    else:
        if 'Devon' in n_g:
            raise RuntimeError('Should have found DEM for Devon')
    
    # Disallow negative
    dem = dem.clip(0)

    # Grid
    nx = dem_ds.RasterXSize
    ny = dem_ds.RasterYSize
    assert nx == gdir.grid.nx
    assert ny == gdir.grid.ny

    # Proj
    geot = dem_ds.GetGeoTransform()
    x0 = geot[0]  # UL corner
    y0 = geot[3]  # UL corner
    dx = geot[1]
    dy = geot[5]  # Negative
    assert dx == -dy
    assert dx == gdir.grid.dx
    assert y0 == gdir.grid.corner_grid.y0
    assert x0 == gdir.grid.corner_grid.x0
    dem_ds = None  # to be sure...

    # Smooth SRTM?
    if cfg.PARAMS['smooth_window'] > 0.:
        gsize = np.rint(cfg.PARAMS['smooth_window'] / dx)
        smoothed_dem = gaussian_blur(dem, np.int(gsize))
    else:
        smoothed_dem = dem.copy()

    # Make entity masks
    log.debug('%s: glacier mask, divide %d', gdir.rgi_id, 0)
    _mask_per_divide(gdir, 0, dem, smoothed_dem)

    # Glacier divides
    nd = gdir.n_divides
    if nd == 1:
        # Optim: just make links
        linkname = gdir.get_filepath('gridded_data', div_id=1)
        sourcename = gdir.get_filepath('gridded_data')
        # overwrite as default
        if os.path.exists(linkname):
            os.remove(linkname)
        # TODO: temporary suboptimal solution
        try:
            # we are on UNIX
            os.link(sourcename, linkname)
        except AttributeError:
            # we are on windows
            copyfile(sourcename, linkname)
        linkname = gdir.get_filepath('geometries', div_id=1)
        sourcename = gdir.get_filepath('geometries')
        # overwrite as default
        if os.path.exists(linkname):
            os.remove(linkname)
        # TODO: temporary suboptimal solution
        try:
            # we are on UNIX
            os.link(sourcename, linkname)
        except AttributeError:
            # we are on windows
            copyfile(sourcename, linkname)
    else:
        # Loop over divides
        for i in gdir.divide_ids:
            log.debug('%s: glacier mask, divide %d', gdir.rgi_id, i)
            _mask_per_divide(gdir, i, dem, smoothed_dem)
Example #6
0
def _distribute_thickness_per_altitude(glacier_mask, topo, cls, fls, grid,
                                       add_slope=True,
                                       smooth=True):
    """Where the job is actually done."""

    # Along the lines
    dx = grid.dx
    hs, ts, vs, xs, ys = [], [], [], [] ,[]
    for cl, fl in zip(cls, fls):
        # TODO: here one should see if parabola is always the best choice
        hs = np.append(hs, fl.surface_h)
        ts = np.append(ts, cl['thick'])
        vs = np.append(vs, cl['volume'])
        x, y = fl.line.xy
        xs = np.append(xs, x)
        ys = np.append(ys, y)
    vol = np.sum(vs)

    # very inefficient inverse distance stuff
    to_compute = np.nonzero(glacier_mask)
    thick = topo * np.NaN
    for (y, x) in np.asarray(to_compute).T:
        assert glacier_mask[y, x] == 1
        phgt = topo[y, x]
        # take the ones in a 100m range
        starth = 100.
        while True:
            starth += 10
            pok = np.nonzero(np.abs(phgt - hs) <= starth)[0]
            if len(pok) != 0:
                break
        sqr = np.sqrt((xs[pok]-x)**2 + (ys[pok]-y)**2)
        pzero = np.where(sqr == 0)
        if len(pzero[0]) == 0:
            thick[y, x] = np.average(ts[pok], weights=1 / sqr)
        elif len(pzero[0]) == 1:
            thick[y, x] = ts[pzero]
        else:
            raise RuntimeError('We should not be there')

    # Smooth
    if smooth:
        thick = np.where(np.isfinite(thick), thick, 0.)
        gsize = np.rint(cfg.PARAMS['smooth_window'] / dx)
        thick = gaussian_blur(thick, np.int(gsize))
    thick = np.where(glacier_mask, thick, 0.)

    # Distance
    dis = distance_transform_edt(glacier_mask)
    dis = np.where(glacier_mask, dis, np.NaN)**0.5

    # Slope
    slope = 1.
    if add_slope:
        sy, sx = np.gradient(topo, dx, dx)
        slope = np.arctan(np.sqrt(sy**2 + sx**2))
        slope = np.clip(slope, np.deg2rad(6.), np.pi/2.)
        slope = 1 / slope**(cfg.N / (cfg.N+2))

    # Conserve volume
    tmp_vol = np.nansum(thick * dis * slope * dx**2)
    final_t = thick * dis * slope * vol / tmp_vol

    # Done
    final_t = np.where(np.isfinite(final_t), final_t, 0.)
    assert np.allclose(np.sum(final_t * dx**2), vol)
    return final_t