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
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
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
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