Пример #1
0
def get_dH_curve(DEM, dDEM, glacier_mask, bins=None, mode='mean'):
    valid = np.logical_and(np.isfinite(DEM), np.isfinite(dDEM))
    dem_data = DEM[valid]
    ddem_data = dDEM[valid]

    if bins is None:
        bins = get_bins(DEM, glacier_mask)
    mean_dH, bin_areas = bin_data(bins, ddem_data, dem_data, mode=mode, nbinned=True)

    return bins, mean_dH, bin_areas
Пример #2
0
def plot_dh_elevation(dDEM,
                      DEM,
                      glacier_mask=None,
                      binning=None,
                      bin_width=50,
                      polyorder=None):
    """

    :param dDEM:
    :param DEM:
    :param glacier_mask:
    :param binning:
    :param bin_width:
    :param polyorder:
    :return:
    """
    fig = plt.figure()
    plt.ion()

    if glacier_mask is not None:
        ddem_data = dDEM.img[np.logical_and(
            np.logical_and(np.isfinite(dDEM.img), np.isfinite(DEM.img)),
            glacier_mask)]
        dem_data = DEM.img[np.logical_and(
            np.logical_and(np.isfinite(dDEM.img), np.isfinite(DEM.img)),
            glacier_mask)]
    else:
        ddem_data = dDEM.img[np.logical_and(np.isfinite(dDEM.img),
                                            np.isfinite(DEM.img))]
        dem_data = DEM.img[np.logical_and(np.isfinite(dDEM.img),
                                          np.isfinite(DEM.img))]

    plt.plot(dem_data, ddem_data, '+')

    if binning is not None:
        if binning not in ['mean', 'median', 'poly']:
            raise ValueError('binning must be one of mean, median, polyfit')
        min_el = np.nanmin(dem_data) - (np.nanmin(dem_data) % bin_width)
        max_el = np.nanmax(dem_data) - (bin_width -
                                        (np.nanmax(dem_data) % bin_width))
        bins = np.arange(min_el, max_el, bin_width)
        if binning in ['mean', 'median']:
            binned_data = bin_data(bins, ddem_data, dem_data, mode=binning)
            plt.plot(bins, binned_data, 'r', linewidth=3)
        else:
            if polyorder is None:
                raise ValueError(
                    'polyorder must be defined to use polynomial fitting.')
            pfit = polyfit(dem_data, ddem_data, polyorder)
            interp_points = polyval(bins, pfit)
            plt.plot(bins, interp_points, 'r', linewidth=3)
    return fig
Пример #3
0
def parse_elev_func_args(func_name, dDEM, **kwargs):
    # first, make sure we use one of the right function names
    if func_name not in ['mean', 'median', 'poly']:
        raise ValueError('{} not one of mean, median, poly'.format(func_name))

    if 'DEM' not in kwargs:
        raise ValueError(
            'to use {}, you must supply a base DEM'.format(func_name))
    else:  # if we've been supplied a DEM, we have to check that it's the right size.
        DEM = kwargs['DEM']
        if type(DEM) is not GeoImg:
            raise TypeError('DEM must be a GeoImg')
        if DEM.img.shape != dDEM.img.shape:
            raise ValueError('dDEM and DEM must have the same shape')

    if 'glacier_mask' in kwargs:
        ddem_data = dDEM.img[np.logical_and(
            np.logical_and(np.isfinite(dDEM.img), np.isfinite(DEM.img)),
            kwargs['glacier_mask'])]
        dem_data = DEM.img[np.logical_and(
            np.logical_and(np.isfinite(dDEM.img), np.isfinite(DEM.img)),
            kwargs['glacier_mask'])]
    else:
        ddem_data = dDEM.img[np.logical_and(np.isfinite(dDEM.img),
                                            np.isfinite(DEM.img))]
        dem_data = DEM.img[np.logical_and(np.isfinite(dDEM.img),
                                          np.isfinite(DEM.img))]

    # now, figure out which of mean, median, polyfit we're using, and do it.
    if func_name == 'poly':
        if 'poly_order' not in kwargs:
            raise ValueError(
                'poly_order must be defined to use polynomial fitting')
        # now we fit a polynomial of order poly_order to the data:
        pfit = polyfit(dem_data, ddem_data, kwargs['poly_order'])

        # need a way to put hole values in the right place
        if 'glacier_mask' in kwargs:
            hole_inds = np.where(
                np.logical_and(
                    np.logical_and(np.isnan(dDEM.img), np.isfinite(DEM.img)),
                    kwargs['glacier_mask']))
        else:
            hole_inds = np.where(
                np.logical_and(np.isfinite(dDEM.img), np.isfinite(DEM.img)))

        hole_elevs = DEM.img[hole_inds]
        interp_points = polyval(hole_elevs, pfit)

        dDEM.img[hole_inds] = interp_points

        if 'valid_area' in kwargs:
            dDEM.img[np.logical_not(kwargs['valid_area'])] = np.nan

        return dDEM
    elif func_name == 'mean' or func_name == 'median':
        if 'bins' not in kwargs:
            # if we haven't been handed bins, we have to make our own.
            if 'bin_width' not in kwargs:
                bin_width = 50  # if we haven't been told what bin width to use, default to 50.
            else:
                bin_width = kwargs['bin_width']
            min_el = np.nanmin(dem_data) - (np.nanmin(dem_data) % bin_width)
            max_el = np.nanmax(dem_data) + (bin_width -
                                            (np.nanmax(dem_data) % bin_width))
            bins = np.arange(min_el, max_el + 1, bin_width)
        else:
            bins = kwargs['bins']
        binned_dH = bin_data(bins, ddem_data, dem_data, mode=func_name)
        # now, we interpolate the missing DH values to the binned values.
        f_elev = interp1d(bins, binned_dH, fill_value="extrapolate")
        # pull out missing values from dDEM
        if 'glacier_mask' in kwargs:
            hole_inds = np.where(
                np.logical_and(
                    np.logical_and(np.isnan(dDEM.img), np.isfinite(DEM.img)),
                    kwargs['glacier_mask']))
        else:
            hole_inds = np.where(
                np.logical_and(np.isfinite(dDEM.img), np.isfinite(DEM.img)))
        hole_elevs = DEM.img[hole_inds]

        filled = f_elev(hole_elevs)
        tmp_dDEM = dDEM.copy()
        tmp_dDEM.img[hole_inds] = filled

        if 'valid_area' in kwargs:
            tmp_dDEM.img[np.logical_not(kwargs['valid_area'])] = np.nan
        return tmp_dDEM
    else:
        raise ValueError(
            'Somehow we made it this far without naming a correct fitting function. Oops.'
        )
Пример #4
0
def get_elev_curve(DEM,
                   dDEM,
                   glacier_mask=None,
                   bins=None,
                   mode='mean',
                   outlier=False,
                   fill=False,
                   poly_order=3):
    """
    Get a dh(z) curve for a glacier/region of interest, given a DEM and a difference DEM (dDEM). Available modes are
        'mean'/'median', calculating the mean(median) of each elevation bin, or poly, fitting a polynomial (default
        third-order) to the means of each elevation bin.

    :param DEM: DEM to determine z in dh(z)
    :param dDEM: difference DEM to determine dh in dh(z)
    :param glacier_mask: mask representing glacier outline
    :param bins: values representing the lower edge of elevation bins
    :param mode: how to determine the dh(z) relationship
    :param outlier: filter outliers using an iterative 3-sigma filter
    :param fill: fill missing bins using a polynomial fit (default third order)
    :param poly_order: order for any polynomial fitting

    :type DEM: array-like
    :type dDEM: array-like
    :type glacier_mask: array-like
    :type bins: array-like
    :type mode: str
    :type outlier: bool
    :type fill: bool
    :type poly_order: int

    :returns bins, curve, bin_areas: elevation bins, dh(z) curve, and number of pixels per elevation bin.
    """
    assert mode in ['mean', 'median',
                    'poly'], "mode not recognized: {}".format(mode)
    if glacier_mask is None:
        valid = np.logical_and(np.isfinite(DEM), np.isfinite(dDEM))
    else:
        valid = np.logical_and(
            glacier_mask, np.logical_and(np.isfinite(DEM), np.isfinite(dDEM)))

    dem_data = DEM[valid]
    ddem_data = dDEM[valid]

    if bins is None:
        bins = get_bins(DEM, glacier_mask)

    if outlier:
        # ddem_data = outlier_removal(bins, dem_data, ddem_data)
        ddem_data = nmad_outlier_removal(bins, dem_data, ddem_data)

    if mode in ['mean', 'median']:
        curve, bin_areas = bin_data(bins,
                                    ddem_data,
                                    dem_data,
                                    mode=mode,
                                    nbinned=True)
        if fill:
            _bins = bins[np.isfinite(curve)]
            _curve = bins[np.isfinite(curve)]
            p = polyfit(bins, curve, poly_order)
            fill_ = polyval(bins, p)
            curve[np.isnan(curve)] = fill_[np.isnan(curve)]

    else:
        _mean, bin_areas = bin_data(bins,
                                    ddem_data,
                                    dem_data,
                                    mode='mean',
                                    nbinned=True)
        p = polyfit(bins, _mean, poly_order)
        curve = polyval(bins, p)

    return bins, curve, bin_areas