Example #1
0
def create_classifier(x, z, toe, window=40, min_buffer=40, max_buffer=200):
    """
    Create dune toe classifier.

    ...

    Parameters
    ----------
    x : ndarray
        Array of cross-shore locations of size (m,).
    z : ndarray
        Array of elevations matching x. May be of size (m,) or (m,n).
    toe : ndarray
        Array of dune toe locations of size (n,).
    window : int, default 40
        Size of the window for training data.
    min_buffer : int, default 40
        Minimum buffer around the real dune toe.
    max_buffer : int, default 200
        Maximum buffer range.

    Returns
    -------
    clf : scikit-learn classifier
        Created random forest classifier.
    """

    # Pre-processing
    z = ds.interp_nan(x, z)  # interp nan
    xx = np.arange(np.min(x), np.max(x) + 0.5, 0.5)
    z = ds.interp_to_grid(x, xx, z)  # interp to grid
    toe = ds.interp_toe_to_grid(x, xx, toe)
    z = ds.moving_average(z, 5)  # apply moving average to smooth
    z = ds.diff_data(z, 1)  # differentiate

    # Create data
    features, labels = create_training_data(xx, z, toe, window, min_buffer,
                                            max_buffer)

    # Build classifier
    clf = RandomForestClassifier(n_estimators=100,
                                 criterion="gini",
                                 random_state=123).fit(features,
                                                       labels.ravel())
    return clf
Example #2
0
    def predict_dunecrest(self,
                          method="max",
                          window_size=21,
                          threshold=0.8,
                          water_level=0):
        """
        Find location of dune crest.

        ...

        Parameters
        ----------
        method : {'max', 'rr'}, default 'max'
            Method to identify the dune crest location. The region of the beach profile
            that the dune toe location is searched for is constrained to the region
            seaward of the dune crest.
            max: the maximum elevation of the cross-shore profile.
            rr: dune crest calculated based on relative relief.
        window_size : int, default 21
            Only valid for method "rr". Size of window for calculating relative relief.
            May be int or list of ints. If a list is passed, relative relief is
            calculated for each window size and averaged.
        threshold : float, default 0.8
            Only valid for method "rr". Threshold of relative relief that identifies the
            dune toe. Between 0 and 1.
        water_level : number, default 0
            Only valid for method "rr". Elevation of mean water level, profile elevations
            at or below mean water level elevation are set to NaN to ensure stability of
            relative relief calculations.

        Returns
        -------
        dt_index : array of ints
            dune toe location.

        """
        if method == "max":
            dc_index = np.array([np.argmax(row) for row in self.z_interp])
        elif method == "rr":
            if isinstance(window_size, int):
                assert isinstance(window_size, int) & \
                       (window_size > 0) & \
                       (window_size < self.z_interp.shape[1]), f'window_size must be int between 0 and {self.z_interp.shape[1]}.'
            elif isinstance(window_size, list):
                assert all(
                    isinstance(_, int) & (_ > 0) & (_ < self.z_interp.shape[1])
                    for _ in window_size
                ), f'window_size must be int between 0 and {self.z_interp.shape[1]}.'
            else:
                raise ValueError(f'window_size must be of type int or list.')
            assert isinstance(threshold, (int, float)) & \
                   (0 < threshold < 1), f'threshold should be number between 0 and 1, but {threshold} was passed.'
            assert isinstance(
                water_level, (int, float)
            ), f'water_level should be a number, but {water_level} was passed.'
            window_size = np.atleast_1d(window_size)
            dc_index = np.full((self.z_interp.shape[0], ), np.nan)
            for i, row in enumerate(self.z_interp):
                rr = ds.relative_relief(row, window_size, water_level)
                try:
                    # suppress warnings for use of < with nan values
                    with np.errstate(invalid='ignore'):
                        dc_index[i] = np.where(rr > threshold)[0][-1]
                except:
                    dc_index[i] = np.nanargmin(rr)
                    print(
                        f'Threshold not found for index {i}, setting dune toe to maximum relief.'
                    )
        else:
            raise ValueError(f'method should be "max" or "rr", not {method}.')

        # Interp back to original x coordinates
        dc_index = ds.interp_toe_to_grid(self.x_interp, self.x,
                                         dc_index.astype(int))
        return dc_index
Example #3
0
    def predict_shoreline(self, water_level=0, dune_crest='max', **kwargs):
        """
        Find location of the shoreline.

        ...

        Parameters
        ----------
        water_level : number or None, default 0
            Elevation of mean water level, profile elevations at or below mean water
            level elevation are set to NaN to ensure stability of relative relief
            calculations.  See Wernette et al. (2016) for further details.
        dune_crest : {'max', 'rr', int, None}, default 'max'
            Method to identify the dune crest location. The region of the beach profile
            that the dune toe location is searched for is constrained to the region
            seaward of the dune crest.
            max: the maximum elevation of the cross-shore profile.
            rr: dune crest calculated based on relative relief.
            int: integer specifying the location of the dune crest. Of size 1 or
                 self.z.shape[0].
            None: do not calculate a dune crest location. Search the whole profile for
                  the dune toe.
        **kwargs : arguments
            Additional arguments to pass to `predict_dunecrest()`. Keywords include
            window_size, threshold, water_level.

        Returns
        -------
        numpy.ndarray
            1-D array containing the index of the shoreline location for each profile.

        """
        assert isinstance(
            water_level, (int, float)
        ), f'water_level should be a number, but {water_level} was passed.'
        if dune_crest in ['max', 'rr']:
            for k in kwargs.keys():
                if k not in ["window", "threshold", "water_level"]:
                    raise Warning(
                        f'{k} not a valid argument for predict_dunecrest() or predict_shoreline()'
                    )
            kwargs = {
                k: v
                for k, v in kwargs.items()
                if k in ["window", "threshold", "water_level"]
            }
            dune_crest_loc = self.predict_dunecrest(method=dune_crest,
                                                    **kwargs)
        elif isinstance(dune_crest, int):
            dune_crest_loc = np.full((self.z_interp.shape[0], ), dune_crest)
        elif dune_crest is None:
            dune_crest_loc = np.full((self.z_interp.shape[0], ), 0)
        elif len(dune_crest) == self.z_interp.shape[0] & \
             isinstance(dune_crest, np.ndarray) & \
             all(isinstance(_, np.int64) for _ in dune_crest):
            dune_crest_loc = dune_crest
        else:
            raise ValueError(
                f'dune_crest should be "max", "rr", int (of size 1 or {self.z_interp.shape[0]}), or None'
            )

        sl_index = np.array([
            len(row) - np.argmin(np.flipud(row) <= water_level) - 1
            for row in self.z_interp
        ])
        # Interp back to original x coordinates
        sl_index = ds.interp_toe_to_grid(self.x_interp, self.x, sl_index)
        mask = ((dune_crest_loc - sl_index) > 0)
        sl_index[mask] = -1

        return sl_index
Example #4
0
    def predict_dunetoe_rr(self,
                           toe_window_size=21,
                           toe_threshold=0.2,
                           water_level=0,
                           dune_crest=None,
                           shoreline=None,
                           verbose=True,
                           **kwargs):
        """
        Predict dune toe location based on relative relief (rr). Based on
        Wernette et al. (2016):

        Wernette, P., Houser, C., & Bishop, M. P. (2016). An automated approach for
        extracting Barrier Island morphology from digital elevation models.
        Geomorphology, 262, 1-7.

        ...

        Parameters
        ----------
        toe_window_size : int, default 21
            Size of window for calculating relative relief. May be int or list of ints.
            If a list is passed, relative relief is calculated for each window size and
            averaged. See Wernette et al. (2016) for further details.
        toe_threshold : float, default 0.2
            Threshold of relative relief that identifies the dune toe. Between 0 and 1.
            See Wernette et al. (2016) for further details.
        water_level : number, default 0
            Elevation of mean water level, profile elevations at or below mean water
            level elevation are set to NaN to ensure stability of relative relief
            calculations.  See Wernette et al. (2016) for further details.
        dune_crest : {'max', 'rr', int, None}, default 'max'
            Method to identify the dune crest location. The region of the beach profile
            that the dune toe location is searched for is constrained to the region
            seaward of the dune crest.
            max: the maximum elevation of the cross-shore profile.
            rr: dune crest calculated based on relative relief.
            int: integer specifying the location of the dune crest. Of size 1 or
                 self.z.shape[0].
            None: do not calculate a dune crest location. Search the whole profile for
                  the dune toe.
        shoreline : int or bool, default True
            Location of shoreline. The region of the beach profile that the dune toe
            location is searched for is constrained to the region landward of the
            shoreline.
            True: use `predict_shoreline()` to calculate shoreline location.
            False: do not use or find a shoreline location.
            int: integer specifying the location of the shoreline. Of size 1 or
                 self.z.shape[0].
        verbose : bool, default True
            If True, will output notifications for when no relative relief value lies
            below toe_threshold, in which case the minimum relative relief is selected
            as the toe location.
        **kwargs : arguments
            Additional arguments to pass to `predict_dunecrest()` and/or
            `predict_shoreline()`. Keywords include window_size, threshold, water_level.

        Returns
        -------
        dt_index : array of ints
            dune toe location.

        """
        if isinstance(toe_window_size, int):
            assert isinstance(toe_window_size, int) & \
                   (toe_window_size > 0) & \
                   (toe_window_size < self.z_interp.shape[
                       1]), f'window_size must be int between 0 and {self.z_interp.shape[1]}.'
        elif isinstance(toe_window_size, list):
            assert all(
                isinstance(_, int) & (_ > 0) & (_ < self.z_interp.shape[1])
                for _ in toe_window_size
            ), f'window_size must be int between 0 and {self.z_interp.shape[1]}.'
        else:
            raise ValueError(f'window_size must bt of type int or list.')
        assert isinstance(toe_threshold, (int, float)) & \
               (toe_threshold > 0 and toe_threshold < 1), f'threshold should be number between 0 and 1, but {toe_threshold} was passed.'
        assert isinstance(
            water_level, (int, float)
        ), f'water_level should be a number, but {water_level} was passed.'

        if dune_crest in ['max', 'rr']:
            for k in kwargs.keys():
                if k not in ["window_size", "threshold", "water_level"]:
                    raise Warning(
                        f'{k} not a valid argument for predict_dunecrest() or predict_shoreline()'
                    )
            kwargs = {
                k: v
                for k, v in kwargs.items()
                if k in ["window_size", "threshold", "water_level"]
            }
            dune_crest_loc = self.predict_dunecrest(method=dune_crest,
                                                    **kwargs)
            dune_crest_loc = ds.interp_toe_to_grid(self.x, self.x_interp,
                                                   dune_crest_loc)
        elif isinstance(dune_crest, int):
            dune_crest_loc = np.full((self.z_interp.shape[0], ),
                                     dune_crest).astype(int)
        elif dune_crest is None:
            dune_crest_loc = np.full((self.z_interp.shape[0], ), 0)
        elif len(dune_crest) == self.z_interp.shape[0] & \
             isinstance(dune_crest, np.ndarray) & \
             all(isinstance(_, np.int64) for _ in dune_crest):
            dune_crest_loc = dune_crest.astype(int)
            dune_crest_loc = ds.interp_toe_to_grid(self.x, self.x_interp,
                                                   dune_crest_loc)
        else:
            raise ValueError(
                f'dune_crest should be "max", "rr", int (of size 1 or {self.z_interp.shape[0]}), or None'
            )

        if shoreline == True:
            for k in kwargs.keys():
                if k not in ["window_size", "threshold", "water_level"]:
                    raise Warning(
                        f'{k} not a valid argument for predict_dunecrest() or predict_shoreline()'
                    )
            kwargs = {
                k: v
                for k, v in kwargs.items()
                if k in ["water_level", "window_size", "threshold"]
            }
            shoreline_loc = self.predict_shoreline(water_level, dune_crest,
                                                   **kwargs)
            shoreline_loc = ds.interp_toe_to_grid(self.x, self.x_interp,
                                                  shoreline_loc)
        elif shoreline is False or shoreline is None:
            shoreline_loc = np.full((self.z_interp.shape[0], ), -1).astype(int)
        elif isinstance(shoreline, int):
            shoreline_loc = np.full((self.z_interp.shape[0], ),
                                    shoreline).astype(int)
        elif len(shoreline) == self.z_interp.shape[0] & \
             isinstance(shoreline, np.ndarray) & \
             all(isinstance(_, np.int64) for _ in shoreline):
            shoreline_loc = shoreline
            shoreline_loc = ds.interp_toe_to_grid(self.x, self.x_interp,
                                                  shoreline_loc)
        else:
            raise ValueError(
                f'shoreline should be bool, or int (of size 1 or {self.z_interp.shape[0]})'
            )

        window = np.atleast_1d(toe_window_size)
        dt_index = np.full((self.z_interp.shape[0], ), np.nan)
        for i, row in enumerate(self.z_interp):
            rr = ds.relative_relief(row, window, water_level)
            try:
                # suppress warnings for use of < with nan values
                with np.errstate(invalid='ignore'):
                    dt_index[i] = np.where(
                        rr[dune_crest_loc[i]:shoreline_loc[i]] < toe_threshold
                    )[0][-1] + dune_crest_loc[i]
            except:
                dt_index[i] = np.nanargmin(
                    rr[dune_crest_loc[i]:shoreline_loc[i]]) + dune_crest_loc[i]
                if verbose:
                    print(
                        f'Threshold not exceeded for profile {i}, setting dune toe to minimum relief.'
                    )
        dt_index = ds.interp_toe_to_grid(self.x_interp, self.x,
                                         dt_index.astype(int))
        return dt_index