示例#1
0
def simulate_sin_bias(fn_dem_ref, fn_along_bias, along_angle, ampli, freq):

    ds_along = create_mem_raster_on_ref(fn_dem_ref)
    res = pixel_size(fn_dem_ref)
    bin_size = 3 * res

    dh_along = ds_along.GetRasterBand(1).ReadAsArray()
    nx, ny = np.shape(dh_along)
    xx, yy = np.meshgrid(np.arange(ny), np.arange(nx))
    altrack = -xx * np.sin(np.deg2rad(along_angle)) + yy * np.cos(
        np.deg2rad(along_angle))

    #correcting bias

    # filt = np.isfinite(dh_along)
    # xd = altrack[filt].flatten()
    # yd = dh_along[filt].flatten()
    # df = pd.DataFrame({'dh': yd, 'dist_altrack': xd})
    # df['dist_altrack'] = pd.cut(df['dist_altrack'], bins=np.arange(min(xd), max(xd) + bin_size, bin_size),
    #                             labels=np.arange(min(xd) + 50. / 2, max(xd) + bin_size / 2, bin_size))
    # df2 = df.groupby(['dist_altrack']).mean()
    # xtest = df2.index.values
    # ytest = df2['dh']

    #can occur when masking
    # filt_missing = np.logical_and(np.isfinite(xtest),np.isfinite(ytest))
    # keepxtest = xtest[filt_missing]
    # keepytest = ytest[filt_missing]

    # coeffs_al = np.polyfit(keepxtest, keepytest, 5)
    # poly_altrack = np.poly1d(coeffs_al)  # define a polynomial function
    # dh_corr = dh_along - poly_altrack(altrack)

    #simulating bias

    dh_simu = ampli * np.sin(altrack * res * 2 * np.pi / freq)

    write_nanarray(fn_along_bias, fn_dem_ref, dh_simu)
示例#2
0
def patches_method(fn_ddem,
                   fn_mask_stable,
                   perc_min_valid,
                   averaging_area,
                   method='circular',
                   nmax=1000.):
    def create_circular_mask(h, w, center=None, radius=None):

        if center is None:  # use the middle of the image
            center = [int(w / 2), int(h / 2)]
        if radius is None:  # use the smallest distance between the center and image walls
            radius = min(center[0], center[1], w - center[0], h - center[1])

        Y, X = np.ogrid[:h, :w]
        dist_from_center = np.sqrt((X - center[0])**2 + (Y - center[1])**2)

        mask = dist_from_center <= radius
        return mask

    ddem = read_nanarray(fn_ddem)
    res = pixel_size(fn_ddem)
    mask_stable = (read_nanarray(fn_mask_stable) > 0)

    valid_mask = np.logical_and(np.isfinite(ddem), mask_stable)

    ddem[~valid_mask] = np.nan
    nx, ny = np.shape(ddem)
    count = len(ddem[~np.isnan(ddem)])
    print('Number of valid pixels: ' + str(count))
    nb_cadrant = int(
        np.floor(np.sqrt((count * res * res) / averaging_area) + 1))
    #rectangular
    nx_sub = int(np.floor((nx - 1) / nb_cadrant))
    ny_sub = int(np.floor((ny - 1) / nb_cadrant))
    #radius size for a circular patch
    rad = int(np.floor(np.sqrt(averaging_area / res * res * np.pi)))

    tile = []
    mean_patch = []
    med_patch = []
    std_patch = []
    nb_patch = []

    list_cadrant = [[i, j] for i in range(nb_cadrant)
                    for j in range(nb_cadrant)]
    u = 0
    while len(list_cadrant) > 0 and u < nmax:

        check = 0
        while check == 0:
            rand_cadrant = random.randint(0, len(list_cadrant) - 1)

            i = list_cadrant[rand_cadrant][0]
            j = list_cadrant[rand_cadrant][1]

            check_x = int(np.floor(nx_sub * (i + 1 / 2)))
            check_y = int(np.floor(ny_sub * (j + 1 / 2)))
            if mask_stable[check_x, check_y]:
                check = 1

        list_cadrant.remove(list_cadrant[rand_cadrant])

        tile.append(int(str(i) + str(j)))
        if method == 'rectangular':
            patch = ddem[nx_sub * i:nx_sub * (i + 1),
                         ny_sub * j:ny_sub * (j + 1)].flatten()
        elif method == 'circular':
            center_x = np.floor(nx_sub * (i + 1 / 2))
            center_y = np.floor(ny_sub * (j + 1 / 2))
            mask = create_circular_mask(nx,
                                        ny,
                                        center=[center_x, center_y],
                                        radius=rad)
            # patch = ddem[center_x-rad:center_x+rad,center_y-rad:center_y+rad]
            patch = ddem[mask]
        else:
            print('Patch method must be rectangular or circular.')
            sys.exit()

        nb_pixel_total = len(patch)
        nb_pixel_valid = len(patch[np.isfinite(patch)])
        if nb_pixel_valid > np.ceil(perc_min_valid / 100. * nb_pixel_total):
            print('Here : ' + str(u))
            u = u + 1
            mean_patch.append(np.nanmean(patch))
            med_patch.append(np.nanmedian(patch))
            std_patch.append(np.nanstd(patch))
            nb_patch.append(nb_pixel_valid)

    tile = np.array(tile)
    mean_patch = np.array(mean_patch)
    med_patch = np.array(med_patch)
    std_patch = np.array(std_patch)
    nb_patch = np.array(nb_patch)

    return tile, mean_patch, med_patch, std_patch, nb_patch
示例#3
0
def get_geophys_var_hypso(fn_ddem, fn_dem, fn_shp, out_dir, path_to_r_geophys):

    pp = PdfPages(os.path.join(out_dir, 'hypsometric_fit_results.pdf'))

    ddem = read_nanarray(fn_ddem)
    ddem[np.absolute(ddem) > 60] = np.nan
    # ddem = ddem*12.
    dem = read_nanarray(fn_dem)
    mask = rasterize_shp(fn_shp, fn_dem)
    gsd = pixel_size(fn_ddem)
    fn_proxi = os.path.join(out_dir, 'proxi.tif')
    proxi = proximity_shp(fn_shp, fn_ddem, type_prox='interior')

    #first get residuals of poly fit
    res, res_stdized, elev, med, std, nmad, area_tot, area_meas, prox = ddem_med_hypso(
        ddem, dem, mask, gsd, pp=pp, proxi=proxi, get_elev_residual=True)
    plt.close('all')

    fn_mask = os.path.join(out_dir, 'mask.tif')
    write_nanarray(fn_mask, fn_ddem, mask)
    fn_res = os.path.join(out_dir, 'residual.tif')
    fn_res_stdized = os.path.join(out_dir, 'residual_standardized.tif')
    write_nanarray(fn_res, fn_ddem, res)
    write_nanarray(fn_res_stdized, fn_ddem, res_stdized)

    mask_geo = GeoImg(fn_mask)
    res_geo = GeoImg(fn_res)
    res_stdized_geo = GeoImg(fn_res_stdized)
    ddem_geo = GeoImg(fn_ddem)
    dem_geo = GeoImg(fn_dem)
    # res_geo.img[np.invert(mask)] = np.nan
    extent = extent_shp_ref(fn_shp, fn_dem)
    crop_res = res_geo.crop_to_extent(
        [extent[0], extent[2], extent[1], extent[3]])
    crop_res_stdized = res_stdized_geo.crop_to_extent(
        [extent[0], extent[2], extent[1], extent[3]])
    crop_ddem = ddem_geo.crop_to_extent(
        [extent[0], extent[2], extent[1], extent[3]])
    crop_mask = mask_geo.crop_to_extent(
        [extent[0], extent[2], extent[1], extent[3]])
    crop_dem = dem_geo.crop_to_extent(
        [extent[0], extent[2], extent[1], extent[3]])

    fn_crop_res_stdized = os.path.join(out_dir, 'res_stdized_cropped.tif')
    fn_crop_mask = os.path.join(out_dir, 'mask_cropped.tif')
    fn_crop_dem = os.path.join(out_dir, 'dem_cropped.tif')

    crop_res_stdized.img[crop_mask.img != 1] = np.nan
    crop_res_stdized.write(fn_crop_res_stdized)
    crop_mask.write(fn_crop_mask)
    crop_dem.write(fn_crop_dem)

    crop_res.img[crop_mask.img != 1] = np.nan
    crop_res_stdized.img[crop_mask.img != 1] = np.nan
    # crop_ddem.img = 12*crop_ddem.img

    clim_ddem_raw = np.nanmax(np.absolute(med))

    outline_gla = gpd.read_file(fn_shp)
    fig, _ = plot_polygon_df(outline_gla, edgecolor='k', lw=2, alpha=0.5)
    plt.title('Outline')
    pp.savefig(fig, dpi=300)

    fig = plot_ddem_results(crop_ddem,
                            clim=(-clim_ddem_raw, clim_ddem_raw),
                            colormap='Spectral')[0]
    plt.title('Elevation change [m] (Large scale)')
    pp.savefig(fig, dpi=300)

    fig = plot_ddem_results(crop_ddem, clim=(-3, 3), colormap='Spectral')[0]
    plt.title('Elevation change [m] (Thin scale)')
    pp.savefig(fig, dpi=300)

    clim_res = np.nanmean(np.absolute(nmad))

    fig = plot_ddem_results(crop_res,
                            clim=(-clim_res, clim_res),
                            colormap='Spectral')[0]
    plt.title(
        'Hypsometric residual of elevation change [m] \n (Elevation change minus hypsometric median)'
    )
    pp.savefig(fig, dpi=300)

    fig = plot_ddem_results(crop_res_stdized,
                            clim=(-1, 1),
                            colormap='Spectral')[0]
    plt.title(
        'Standardized hypsometric residual of elevation change [no unit] \n (Elevation change minus hypsometric median divided by hypsometric nmad)'
    )
    pp.savefig(fig, dpi=300)

    pp.close()
    plt.close('all')
    os.remove(fn_res)
    os.remove(fn_mask)
    os.remove(fn_res_stdized)

    #normalize elevation
    max_elev = np.nanmax(elev)
    min_elev = np.nanmin(elev)
    elev_n = (elev - min_elev) / (max_elev - min_elev)

    #normalize dh
    max_dh = np.nanmax(med)
    min_dh = np.nanmin(med)
    accu_elev = min_elev + 80 * (max_elev - min_elev) / 100
    tmp_max_dh = np.nanmean(
        med[elev > accu_elev])  #use mean of accumulation instead of max
    if np.abs((np.nanmax(med) - tmp_max_dh) / (max_dh - min_dh)) < 0.3:
        max_dh = tmp_max_dh
    med_n = (min_dh - med) / (max_dh - min_dh)
    std_n = std / (max_dh - min_dh)
    nmad_n = nmad / (max_dh - min_dh)

    #write normalized data
    elev_rs = np.arange(0, 1, 0.01)
    med_rs = np.interp(elev_rs, elev_n, med_n)
    std_rs = np.interp(elev_rs, elev_n, std_n)
    nmad_rs = np.interp(elev_rs, elev_n, nmad_n)
    area_rs = np.interp(elev_rs, elev_n, area_tot)
    df = pd.DataFrame()
    df = df.assign(norm_elev=elev_rs,
                   norm_med_dh=med_rs,
                   norm_std_dh=std_rs,
                   norm_nmad_rs=nmad_rs,
                   area_rs=area_rs)
    df_raw = pd.DataFrame()
    df_raw = df_raw.assign(elev=elev,
                           med_dh=med,
                           std_dh=std,
                           nmad_dh=nmad,
                           area_tot=area_tot,
                           area_meas=area_meas,
                           prox=prox)

    df.to_csv(os.path.join(out_dir, 'df_norm_dh_elev.csv'))
    df_raw.to_csv(os.path.join(out_dir, 'df_raw_dh_elev.csv'))

    ddem = dem = mask = res = res_stdized = crop_mask = crop_res_stdized = crop_res = crop_ddem = crop_dem = ddem_geo = dem_geo = res_geo = res_stdized_geo = None

    #get variogram with moving elevation window from R
    # cmd = 'Rscript '+path_to_r_geophys+' -d '+fn_crop_dem+' -r '+fn_crop_res_stdized+' -m '+fn_crop_mask+' -v Exp -o '+out_dir
    # fn_log = os.path.join(out_dir,'r_geophys.log')
    # log=open(fn_log,'w')
    # p=Popen(cmd,stdout=log,stderr=log,shell=True)
    # p.wait()
    # log.close()

    os.remove(fn_crop_dem)
    os.remove(fn_crop_res_stdized)
    os.remove(fn_crop_mask)
示例#4
0
def kernel_tvol_outline_adjust(fn_ddem,
                               fn_dem,
                               fn_outline_in,
                               fn_outline_out,
                               fn_mask_stable,
                               fn_mask_gla,
                               tolerance_factor=5.,
                               kernel_size=9,
                               only_thinning=True):
    def gkern(kernlen=21):

        #source: https://stackoverflow.com/questions/29731726/how-to-calculate-a-gaussian-kernel-matrix-efficiently-in-numpy
        """Returns a 2D Gaussian kernel."""

        lim = kernlen // 2 + (kernlen % 2) / 2
        x = np.linspace(-lim, lim, kernlen + 1)
        kern1d = np.diff(st.norm.cdf(x))
        kern2d = np.outer(kern1d, kern1d)
        return kern2d / kern2d.sum()

    #inside parameters based on prior knowledge:
    tmp_dir = create_tmp_dir_for_outfile(fn_outline_out)

    #read
    ddem = read_nanarray(fn_ddem)
    ddem[np.absolute(ddem) > 60] = np.nan
    dem = read_nanarray(fn_dem)
    mask_other_gla = (read_nanarray(fn_mask_stable) == 1)
    mask_gla = (read_nanarray(fn_mask_gla) == 1)
    mask_stable = np.invert(np.logical_or(mask_gla, mask_other_gla))
    res = pixel_size(fn_dem)

    elev, med, std, nmad = ddem_discrete_hypso(ddem,
                                               dem,
                                               mask_gla,
                                               gsd=res,
                                               bin_val=10)[1:5]

    #first, keep stable terrain
    keep_stable = np.logical_and(mask_stable, np.isfinite(ddem))
    ddem_on_stable = ddem[keep_stable]

    #get nmad as representative statistic of stable terrain
    median_stable = np.nanmedian(ddem_on_stable)
    mad_stable = np.nanmedian(
        np.absolute(ddem_on_stable[~np.isnan(ddem_on_stable)] - median_stable))
    nmad_stable = 1.4826 * mad_stable

    # #filter heavy outliers to get a fair representation of overall stable terrain (without unmapped glaciers, landslides, etc...)
    # ddem_on_stable[np.array(np.absolute(ddem_on_stable - median_stable) > 3 * nmad_stable)] = np.nan

    #rasterize outline
    # mask_outline = rasterize_shp(fn_outline_in,fn_ddem)

    #get an idea of thinning rate and amplitude of adjustment
    # dh_on_outline = ddem_poly_elev(ddem,dem,5,mask_outline)

    outline_timelapse = 10
    ddem_timelapse = 10
    # detect elev above which thinning is not significant anymore so we don't care
    critic_elev = np.nanmax(
        elev[np.absolute(med) + 3 * np.absolute(nmad) > tolerance_factor *
             nmad_stable])
    filt_elev = (elev <= critic_elev)
    # remove decreasing dh signal around the end of ablation area to assess effective dh with elevation
    filt_diff_dh = (np.diff(med) > 0)
    filt_diff_dh = np.append(filt_diff_dh, True)
    filt = np.logical_and(filt_elev, filt_diff_dh)
    new_elev = elev[filt]
    new_med = med[filt]
    #range of proximity value to search in as a function of elevation
    critic_proximity = np.absolute(
        new_med
    ) * outline_timelapse * ddem_timelapse  #TODO: ideally, multiply that by a timelapse between outline and first DEM, make sure ddem is in m and not m.y-1, and then apply a factor with slope convolution in the proximity area
    interp_critic_proximity = np.reshape(
        np.interp(dem.flatten(),
                  new_elev,
                  critic_proximity,
                  right=0,
                  left=np.nanmax(critic_proximity)), np.shape(dem)
    )  #TODO: could extrapolate linearly with elevation to assess lower dh?

    #define mask of areas for possible outline adjustment
    # mask_surround_elev = (dem>min_elev-mvp_elev_value) & (dem<=critic_elev)
    proximity_rast = proximity_shp(fn_outline_in, fn_ddem)
    mask_proximity = proximity_rast < interp_critic_proximity

    #define mask for neighboring glaciers
    tmp_rast_othergla = os.path.join(tmp_dir, 'tmp_rast_othergla.tif')
    tmp_prox_othergla = os.path.join(tmp_dir, 'tmp_prox_othergla.tif')
    rast_othergla = np.ones(np.shape(mask_other_gla))
    rast_othergla[~mask_other_gla] = 0
    write_nanarray(tmp_rast_othergla, fn_dem, rast_othergla)
    proximity_rast_fn(tmp_rast_othergla, tmp_prox_othergla)
    prox_othergla = read_nanarray(tmp_prox_othergla)

    max_prox_othergla = 4 * kernel_size * res
    mask_max_prox_othergla = prox_othergla > max_prox_othergla

    mask_maybe = np.logical_and(mask_proximity, mask_max_prox_othergla)

    #get upper elevation/center of glacier by using intersect with original outline with buffer/polygonize excluding proximity mask
    tmp_buffered = os.path.join(tmp_dir, 'tmp_buff.shp')
    buffer_shp_fn(fn_outline_in, tmp_buffered, 3 * res)
    buff_rast = rasterize_shp(tmp_buffered, fn_ddem)
    buff_rast[mask_maybe] = 0
    buff_mask = np.ones(np.shape(buff_rast))
    buff_mask[~buff_rast] = -9999
    tmp_buffered_rast = os.path.join(tmp_dir, 'tmp_buff_mask.tif')
    tmp_upper_outline = os.path.join(tmp_dir, 'tmp_upper.shp')
    write_nanarray(tmp_buffered_rast, fn_ddem, buff_mask)
    #if there is an area untouched that is kept to union with adjusted polygon at the end
    nb_pixel_kept = len(buff_mask[buff_mask == 1])
    if nb_pixel_kept > 0:
        polygonize_fn(tmp_buffered_rast, tmp_upper_outline)
        tmp_inters = os.path.join(tmp_dir, 'tmp_inters.shp')
        # inters_shp_fn(fn_outline_in,tmp_upper_outline,tmp_inters)

        #get a common area to merge with final polygon by buffering previous outline
        tmp_upper_buff = os.path.join(tmp_dir, 'tmp_buff_upper.shp')
        tmp_upper_buff_inters = os.path.join(tmp_dir,
                                             'tmp_buff_upper_inters.shp')
        buffer_shp_fn(tmp_upper_outline, tmp_upper_buff, 2 * kernel_size * res)
        inters_shp_fn(fn_outline_in, tmp_upper_buff, tmp_upper_buff_inters)
        mask_upper_buff = rasterize_shp(tmp_upper_buff_inters, fn_dem)
    #if there is no area untouched, find pole of inaccessibility
    else:
        tmp_poi = os.path.join(tmp_dir, 'poi.shp')
        poi_polygon(fn_outline_in, tmp_poi, res)
        mask_upper_buff = rasterize_shp(tmp_poi, fn_dem, all_touched=True)

    ddem_maybe = ddem
    ddem_maybe[~mask_maybe] = np.nan
    if only_thinning:
        ddem_maybe[ddem_maybe > 5 * nmad_stable] = np.nan

    #use kernel to ensure volume change at a given pixel is significant
    conv = convolve(ddem_maybe, gkern(kernel_size), mode='nearest')
    if only_thinning:
        mask_tvol = (conv < -tolerance_factor * nmad_stable)
    else:
        mask_tvol = (np.absolute(conv) > tolerance_factor * nmad_stable)

    #use filling algorithm from common mask to get only spatially continuous adjusted area with interior of glacier
    mask_common = np.logical_and(mask_upper_buff, mask_tvol)
    mask_flood = floodfill_discontinuous(mask_tvol, mask_start=mask_common)
    mask_flood = mask_flood.astype('float')
    mask_flood[mask_flood == 0] = -9999

    fn_mask_flood = os.path.join(tmp_dir, 'mask_flood.tif')
    fn_shp_flood = os.path.join(tmp_dir, 'shp_flood.shp')
    fn_smooth_flood = os.path.join(tmp_dir, 'shp_flood_smooth.shp')

    write_nanarray(fn_mask_flood, fn_ddem, mask_flood)

    #polygonize final mask
    polygonize_fn(fn_mask_flood, fn_shp_flood)

    #smooth polygon
    simplify_shp_fn(fn_shp_flood, fn_smooth_flood, tolerance=res)

    #union with inside
    if nb_pixel_kept > 0 and not isempty_firstfeat(fn_smooth_flood):
        union_shp_fn(fn_smooth_flood, tmp_upper_buff_inters, fn_outline_out)
    elif not isempty_firstfeat(fn_smooth_flood):
        copy_shp_fn(fn_smooth_flood, fn_outline_out)
    else:
        #TODO: actually need to change projection in this step or it stays that of the input shapefile
        copy_shp_fn(fn_outline_in, fn_outline_out)
示例#5
0
def neff(mask, fn_ref, crange, model='Sph', psill=1., kappa=1 / 2, nugget=0):
    def hcov(h,
             crange=crange,
             model=model,
             psill=psill,
             kappa=kappa,
             nugget=nugget):

        return h * cov(
            h, crange, model=model, psill=psill, kappa=kappa, nugget=nugget)

    # fn_ref = '/home/atom/ongoing/std_err/data_vhr/etienne_mb/mask_mdg.tif'
    # mask = (read_nanarray(fn_ref) == 1)

    #get inside proximity of mask
    ds = create_mem_raster_on_ref(fn_ref)
    ds.GetRasterBand(1).WriteArray(mask)
    ds_prox = proximity_rast_ds(ds, val=0)
    prox = ds_prox.GetRasterBand(1).ReadAsArray()

    #pole of innacessibility
    poi_tup = np.where(prox == np.nanmax(prox))
    poi_x = poi_tup[0][0]
    poi_y = poi_tup[1][0]

    #get proximity from the pole
    mask_poi = np.zeros(np.shape(mask), dtype=bool)
    mask_poi[poi_x, poi_y] = 1
    ds.GetRasterBand(1).WriteArray(mask_poi)
    ds_prox_poi = proximity_rast_ds(ds, val=1)
    prox_poi = ds_prox_poi.GetRasterBand(1).ReadAsArray()

    #maximum distance in the mast from the poi
    max_prox = np.nanmax(prox_poi[mask])
    res = pixel_size(fn_ref)
    bin_size = 3 * res

    #bin with circular area
    bins_area = np.arange(0, max_prox, bin_size)
    tot_area = np.zeros(len(bins_area))
    obs_area = np.zeros(len(bins_area))

    for i in np.arange(len(bins_area)):

        tot_area[i] = np.count_nonzero((prox_poi >= bins_area[i])
                                       & (prox_poi < bins_area[i] + bin_size))
        obs_area[i] = np.count_nonzero((prox_poi[mask] >= bins_area[i]) & (
            prox_poi[mask] < bins_area[i] + bin_size))

    frac_area = obs_area / tot_area

    #integrate piecewise:
    full_int = 0
    for i in np.arange(len(bins_area)):
        low = bins_area[i]
        upp = bins_area[i] + bin_size
        piec_int = integrate_fun(hcov, low, upp)[0]
        print(piec_int)
        full_int += piec_int * frac_area[i]

    area_tot = np.count_nonzero(mask) * res**2

    gamma_unity = full_int / area_tot

    return 1. / (1 - gamma_unity)