diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml index e9736f1..0072f90 100644 --- a/.github/workflows/test-coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -1,12 +1,12 @@ # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: + # workflow_dispatch: push: branches: [main, master] pull_request: - branches: [main, master] -name: test-coverage +name: test-coverage.yaml permissions: read-all @@ -15,8 +15,6 @@ jobs: runs-on: ubuntu-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - R_KEEP_PKG_SOURCE: yes - _R_CHECK_CRAN_INCOMING_: false steps: - uses: actions/checkout@v4 @@ -27,20 +25,31 @@ jobs: - uses: r-lib/actions/setup-r-dependencies@v2 with: - pak-version: devel - upgrade: 'TRUE' - cache-version: 2 - extra-packages: | - any::covr - local::. + extra-packages: any::covr, any::xml2 needs: coverage - name: Test coverage run: | - options(crayon.enabled = TRUE) - covr::codecov( + cov <- covr::package_coverage( quiet = FALSE, clean = FALSE, - token = "${{secrets.CODECOV_TOKEN}}" + install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") ) - shell: Rscript {0} \ No newline at end of file + covr::to_cobertura(cov) + shell: Rscript {0} + + - uses: codecov/codecov-action@v4 + with: + # Fail if error if not on PR, or if on PR and token is given + fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }} + file: ./cobertura.xml + plugin: noop + disable_search: true + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Upload test results + if: failure() + uses: actions/upload-artifact@v4 + with: + name: coverage-test-failures + path: ${{ runner.temp }}/package \ No newline at end of file diff --git a/NAMESPACE b/NAMESPACE index 0d089ee..ca8b103 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -18,7 +18,6 @@ export(as_matrix) export(as_rast) export(as_vector) export(as_wbw_raster) -export(expect_snapshot) export(num_cells) export(print_geotiff_tags) export(stdev) @@ -40,19 +39,27 @@ export(wbw_install) export(wbw_is_float) export(wbw_is_int) export(wbw_is_rgb) +export(wbw_majority_filter) export(wbw_max_procs) +export(wbw_maximum_filter) export(wbw_mean_filter) export(wbw_median_filter) +export(wbw_minimum_filter) export(wbw_multidirectional_hillshade) +export(wbw_olympic_filter) +export(wbw_percentile_filter) export(wbw_random_sample) +export(wbw_range_filter) export(wbw_read_raster) export(wbw_read_vector) export(wbw_res) export(wbw_rows) export(wbw_ruggedness_index) export(wbw_slope) +export(wbw_standard_deviation_filter) export(wbw_to_degrees) export(wbw_to_radians) +export(wbw_total_filter) export(wbw_version) export(wbw_write_raster) export(wbw_xres) diff --git a/R/filters.R b/R/filters.R index 5391975..2955761 100644 --- a/R/filters.R +++ b/R/filters.R @@ -13,8 +13,8 @@ #' assigned the mean value. Otherwise, it retains its original value. #' #' Neighbourhood size, or filter size, is specified in the x and y dimensions -#' using `filter_size_x` and `filter_size_y` These dimensions should be odd, -#' positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). #' #' @eval rd_input_raster("x") #' @param filter_size_x \code{integer}, X dimension of the neighbourhood size @@ -168,8 +168,8 @@ S7::method(wbw_bilateral_filter, WhiteboxRaster) <- #' [wbw_bilateral_filter] or [wbw_gaussian_filter]. #' #' Neighbourhood size, or filter size, is specified in the x and y dimensions -#' using `filter_size_x` and `filter_size_y` These dimensions should be odd, -#' positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). #' #' @eval rd_input_raster("x") #' @param filter_size_x \code{integer}, X dimension of the neighbourhood size @@ -311,8 +311,8 @@ S7::method(wbw_gaussian_filter, WhiteboxRaster) <- #' minimum value. #' #' Neighbourhood size, or filter size, is specified in the x and y dimensions -#' using `filter_size_x` and `filter_size_y` These dimensions should be odd, -#' positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). #' #' @eval rd_input_raster("x") #' @param filter_size_x \code{integer}, X dimension of the neighbourhood size @@ -386,8 +386,8 @@ S7::method(wbw_conservative_smoothing_filter, WhiteboxRaster) <- #' #' @details #' Neighbourhood size, or filter size, is specified in the x and y dimensions -#' using `filter_size_x` and `filter_size_y` These dimensions should be odd, -#' positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). #' #' @eval rd_input_raster("x") #' @param filter_size_x \code{integer}, X dimension of the neighbourhood size @@ -447,8 +447,6 @@ S7::method(wbw_high_pass_filter, WhiteboxRaster) <- ) } - - #' High Pass Median Filter #' @keywords image_processing #' @@ -461,13 +459,14 @@ S7::method(wbw_high_pass_filter, WhiteboxRaster) <- #' #' @details #' Neighbourhood size, or filter size, is specified in the x and y dimensions -#' using `filter_size_x` and `filter_size_y` These dimensions should be odd, -#' positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). #' #' @eval rd_input_raster("x") #' @param filter_size_x \code{integer}, X dimension of the neighbourhood size #' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size -#' @param sig_digits \code{integer} +#' @param sig_digits \code{integer}, default 2. Required for rounding of +#' floating points inputs. #' #' @return [WhiteboxRaster] object containing filtered values #' @@ -532,34 +531,33 @@ S7::method(wbw_high_pass_median_filter, WhiteboxRaster) <- ) } - - #' Median Filter #' @keywords image_processing #' #' @description -#' This tool performs a median filter on a raster image. Median filters, a -#' type of low-pass filter, can be used to emphasize the longer-range -#' variability in an image, effectively acting to smooth the image. This +#' This tool performs a median filter on a raster image. Median filters, a +#' type of low-pass filter, can be used to emphasize the longer-range +#' variability in an image, effectively acting to smooth the image. This #' can be useful for reducing the noise in an image. #' #' @details -#' The algorithm operates by calculating the median value (middle value in +#' The algorithm operates by calculating the median value (middle value in #' a sorted list) in a moving window centred on each grid cell. Specifically, #' this tool uses the efficient running-median filtering algorithm of -#' Huang et al. (1979). The median value is not influenced by -#' anomolously high or low values in the distribution to the extent -#' that the average is. As such, the median filter is far less sensitive +#' Huang et al. (1979). The median value is not influenced by +#' anomolously high or low values in the distribution to the extent +#' that the average is. As such, the median filter is far less sensitive #' to shot noise in an image than the mean filter. -#' +#' #' Neighbourhood size, or filter size, is specified in the x and y dimensions -#' using `filter_size_x` and `filter_size_y` These dimensions should be odd, -#' positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). #' #' @eval rd_input_raster("x") #' @param filter_size_x \code{integer}, X dimension of the neighbourhood size #' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size -#' @param sig_digits \code{integer} +#' @param sig_digits \code{integer}, default 2. Required for rounding of +#' floating points inputs. #' #' @return [WhiteboxRaster] object containing filtered values #' @@ -567,10 +565,10 @@ S7::method(wbw_high_pass_median_filter, WhiteboxRaster) <- #' [wbw_high_pass_median_filter()] #' #' @references -#' Huang, T., Yang, G.J.T.G.Y. and Tang, G., 1979. A fast two-dimensional +#' Huang, T., Yang, G.J.T.G.Y. and Tang, G., 1979. A fast two-dimensional #' median filtering algorithm. IEEE Transactions on Acoustics, Speech, and #' Signal Processing, 27(1), pp.13-18. -#' +#' #' @eval rd_wbw_link("median_filter") #' @eval rd_example("wbw_median_filter", #' c("filter_size_x = 3L", "filter_size_y = 3L")) @@ -629,3 +627,618 @@ S7::method(wbw_median_filter, WhiteboxRaster) <- source = out ) } + +#' Majority Filter +#' @keywords image_processing +#' +#' @description +#' Assigns each cell in the output grid the most frequently occurring value +#' (mode) in a moving window centred on each grid cell in the input raster. +#' +#' @details +#' Neighbourhood size, or filter size, is specified in the x and y dimensions +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' +#' @eval rd_input_raster("x") +#' @param filter_size_x \code{integer}, X dimension of the neighbourhood size +#' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size +#' +#' @return [WhiteboxRaster] object containing filtered values +#' +#' @seealso [wbw_mean_filter()], [wbw_high_pass_filter()], +#' [wbw_high_pass_median_filter()] +#' +#' @eval rd_wbw_link("majority_filter") +#' @eval rd_example("wbw_majority_filter", +#' c("filter_size_x = 3L", "filter_size_y = 3L")) +#' +#' @export +wbw_majority_filter <- + S7::new_generic( + name = "wbw_majority_filter", + dispatch_args = "x", + fun = function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + S7::S7_dispatch() + } + ) + +S7::method(wbw_majority_filter, WhiteboxRaster) <- + function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + # Checks + check_env(wbe) + filter_size_x <- + checkmate::asInteger( + filter_size_x, + lower = 0L, + len = 1L + ) + filter_size_y <- + checkmate::asInteger( + filter_size_y, + lower = 0L, + len = 1L + ) + checkmate::assert_true(filter_size_x %% 2 == 1) + checkmate::assert_true(filter_size_y %% 2 == 1) + + # Filter + out <- + wbe$majority_filter( + raster = x@source, + filter_size_x = filter_size_x, + filter_size_y = filter_size_y + ) + # Return Raster + WhiteboxRaster( + name = x@name, + source = out + ) + } + + +#' Maximum Filter +#' @keywords image_processing +#' +#' @description +#' Assigns each cell in the output grid the maximum value in a moving window +#' centred on each grid cell in the input raster. +#' +#' @details +#' Neighbourhood size, or filter size, is specified in the x and y dimensions +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' +#' @eval rd_input_raster("x") +#' @param filter_size_x \code{integer}, X dimension of the neighbourhood size +#' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size +#' +#' @return [WhiteboxRaster] object containing filtered values +#' +#' @seealso [wbw_mean_filter()], [wbw_high_pass_filter()], +#' [wbw_high_pass_median_filter()] +#' +#' @eval rd_wbw_link("maximum_filter") +#' @eval rd_example("wbw_maximum_filter", +#' c("filter_size_x = 3L", "filter_size_y = 3L")) +#' +#' @export +wbw_maximum_filter <- + S7::new_generic( + name = "wbw_maximum_filter", + dispatch_args = "x", + fun = function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + S7::S7_dispatch() + } + ) + +S7::method(wbw_maximum_filter, WhiteboxRaster) <- + function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + # Checks + check_env(wbe) + filter_size_x <- + checkmate::asInteger( + filter_size_x, + lower = 0L, + len = 1L + ) + filter_size_y <- + checkmate::asInteger( + filter_size_y, + lower = 0L, + len = 1L + ) + checkmate::assert_true(filter_size_x %% 2 == 1) + checkmate::assert_true(filter_size_y %% 2 == 1) + + # Filter + out <- + wbe$maximum_filter( + raster = x@source, + filter_size_x = filter_size_x, + filter_size_y = filter_size_y + ) + # Return Raster + WhiteboxRaster( + name = x@name, + source = out + ) + } + + +#' Minimum Filter +#' @keywords image_processing +#' +#' @description +#' Assigns each cell in the output grid the minimum value in a moving window +#' centred on each grid cell in the input raster. +#' +#' @details +#' Neighbourhood size, or filter size, is specified in the x and y dimensions +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' +#' @eval rd_input_raster("x") +#' @param filter_size_x \code{integer}, X dimension of the neighbourhood size +#' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size +#' +#' @return [WhiteboxRaster] object containing filtered values +#' +#' @seealso [wbw_mean_filter()], [wbw_high_pass_filter()], +#' [wbw_high_pass_median_filter()] +#' +#' @eval rd_wbw_link("minimum_filter") +#' @eval rd_example("wbw_minimum_filter", +#' c("filter_size_x = 3L", "filter_size_y = 3L")) +#' +#' @export +wbw_minimum_filter <- + S7::new_generic( + name = "wbw_minimum_filter", + dispatch_args = "x", + fun = function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + S7::S7_dispatch() + } + ) + +S7::method(wbw_minimum_filter, WhiteboxRaster) <- + function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + # Checks + check_env(wbe) + filter_size_x <- + checkmate::asInteger( + filter_size_x, + lower = 0L, + len = 1L + ) + filter_size_y <- + checkmate::asInteger( + filter_size_y, + lower = 0L, + len = 1L + ) + checkmate::assert_true(filter_size_x %% 2 == 1) + checkmate::assert_true(filter_size_y %% 2 == 1) + + # Filter + out <- + wbe$minimum_filter( + raster = x@source, + filter_size_x = filter_size_x, + filter_size_y = filter_size_y + ) + # Return Raster + WhiteboxRaster( + name = x@name, + source = out + ) + } + +#' Olympic Filter +#' @keywords image_processing +#' +#' @description +#' This filter is a modification of the [wbw_mean_filter], whereby +#' the highest and lowest values in the kernel are dropped, and the remaining +#' values are averaged to replace the central pixel. The result is a +#' low-pass smoothing filter that is more robust than the [wbw_mean_filter], +#' which is more strongly impacted by the presence of outlier values. +#' It is named after a system of scoring Olympic events. +#' +#' @details +#' Neighbourhood size, or filter size, is specified in the x and y dimensions +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' +#' @eval rd_input_raster("x") +#' @param filter_size_x \code{integer}, X dimension of the neighbourhood size +#' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size +#' +#' @return [WhiteboxRaster] object containing filtered values +#' +#' @seealso [wbw_mean_filter()] +#' +#' @eval rd_wbw_link("olympic_filter") +#' @eval rd_example("wbw_olympic_filter", +#' c("filter_size_x = 3L", "filter_size_y = 3L")) +#' +#' @export +wbw_olympic_filter <- + S7::new_generic( + name = "wbw_olympic_filter", + dispatch_args = "x", + fun = function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + S7::S7_dispatch() + } + ) + +S7::method(wbw_olympic_filter, WhiteboxRaster) <- + function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + # Checks + check_env(wbe) + filter_size_x <- + checkmate::asInteger( + filter_size_x, + lower = 0L, + len = 1L + ) + filter_size_y <- + checkmate::asInteger( + filter_size_y, + lower = 0L, + len = 1L + ) + checkmate::assert_true(filter_size_x %% 2 == 1) + checkmate::assert_true(filter_size_y %% 2 == 1) + + # Filter + out <- + wbe$olympic_filter( + raster = x@source, + filter_size_x = filter_size_x, + filter_size_y = filter_size_y + ) + # Return Raster + WhiteboxRaster( + name = x@name, + source = out + ) + } + + +#' Percentile Filter +#' @keywords image_processing +#' +#' @description +#' This tool calculates the percentile of the center cell in a moving filter +#' window applied to an input image (\code{x}). This indicates the value +#' below which a given percentage of the neighbouring values in within the +#' filter fall. For example, the 35th percentile is the value below which 35% +#' of the neighbouring values in the filter window may be found. As such, +#' the percentile of a pixel value is indicative of the relative location +#' of the site within the statistical distribution of values contained +#' within a filter window. +#' +#' When applied to input digital elevation models, percentile is a measure of +#' local topographic position, or elevation residual. +#' +#' +#' @details +#' Neighbourhood size, or filter size, is specified in the x and y dimensions +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' +#' This tool takes advantage of the redundancy between overlapping, +#' neighbouring filters to enhance computationally efficiency, using a +#' method similar to Huang et al. (1979). This efficient method of +#' calculating percentiles requires rounding of floating-point inputs, +#' and therefore the user must specify the number of significant +#' digits (\code{sig_digits}) to be used during the processing. +#' +#' @eval rd_input_raster("x") +#' @param filter_size_x \code{integer}, X dimension of the neighbourhood size +#' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size +#' @param sig_digits \code{integer}, default 2. Required for rounding of +#' floating points inputs. +#' +#' @return [WhiteboxRaster] object containing filtered values +#' +#' @seealso [wbw_median_filter()] +#' +#' @references +#' Huang, T., Yang, G.J.T.G.Y. and Tang, G., 1979. A fast two-dimensional +#' median filtering algorithm. IEEE Transactions on Acoustics, Speech, and +#' Signal Processing, 27(1), pp.13-18. +#' +#' @eval rd_wbw_link("percentile_filter") +#' @eval rd_example("wbw_percentile_filter", +#' c("filter_size_x = 3L", "filter_size_y = 3L")) +#' +#' @export +wbw_percentile_filter <- + S7::new_generic( + name = "wbw_percentile_filter", + dispatch_args = "x", + fun = function(x, + filter_size_x = 11L, + filter_size_y = 11L, + sig_digits = 2L) { + S7::S7_dispatch() + } + ) + +S7::method(wbw_percentile_filter, WhiteboxRaster) <- + function(x, + filter_size_x = 11L, + filter_size_y = 11L, + sig_digits = 2L) { + # Checks + check_env(wbe) + filter_size_x <- + checkmate::asInteger( + filter_size_x, + lower = 0L, + len = 1L + ) + filter_size_y <- + checkmate::asInteger( + filter_size_y, + lower = 0L, + len = 1L + ) + checkmate::assert_true(filter_size_x %% 2 == 1) + checkmate::assert_true(filter_size_y %% 2 == 1) + sig_digits <- + checkmate::asInteger( + sig_digits, + lower = 0L, + len = 1L + ) + # Filter + out <- + wbe$percentile_filter( + raster = x@source, + filter_size_x = filter_size_x, + filter_size_y = filter_size_y, + sig_digits = sig_digits + ) + # Return Raster + WhiteboxRaster( + name = x@name, + source = out + ) + } + + +#' Range Filter +#' @keywords image_processing +#' +#' @description +#' A range filter assigns to each cell in the output grid the range +#' (maximum - minimum) of the values contained within a moving window +#' centred on each grid cell. +#' +#' @details +#' Neighbourhood size, or filter size, is specified in the x and y dimensions +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' +#' @eval rd_input_raster("x") +#' @param filter_size_x \code{integer}, X dimension of the neighbourhood size +#' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size +#' +#' @return [WhiteboxRaster] object containing filtered values +#' +#' @seealso [wbw_minimum_filter()], [wbw_maximum_filter()] +#' +#' @eval rd_wbw_link("range_filter") +#' @eval rd_example("wbw_range_filter", +#' c("filter_size_x = 3L", "filter_size_y = 3L")) +#' +#' @export +wbw_range_filter <- + S7::new_generic( + name = "wbw_range_filter", + dispatch_args = "x", + fun = function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + S7::S7_dispatch() + } + ) + +S7::method(wbw_range_filter, WhiteboxRaster) <- + function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + # Checks + check_env(wbe) + filter_size_x <- + checkmate::asInteger( + filter_size_x, + lower = 0L, + len = 1L + ) + filter_size_y <- + checkmate::asInteger( + filter_size_y, + lower = 0L, + len = 1L + ) + checkmate::assert_true(filter_size_x %% 2 == 1) + checkmate::assert_true(filter_size_y %% 2 == 1) + + # Filter + out <- + wbe$range_filter( + raster = x@source, + filter_size_x = filter_size_x, + filter_size_y = filter_size_y + ) + # Return Raster + WhiteboxRaster( + name = x@name, + source = out + ) + } + +#' Total Filter +#' @keywords image_processing +#' +#' @description +#' A total filter assigns to each cell in the output grid the total (sum) +#' of all values in a moving window centred on each grid cell. +#' +#' @details +#' Neighbourhood size, or filter size, is specified in the x and y dimensions +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' +#' @eval rd_input_raster("x") +#' @param filter_size_x \code{integer}, X dimension of the neighbourhood size +#' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size +#' +#' @return [WhiteboxRaster] object containing filtered values +#' +#' @seealso [wbw_minimum_filter()], [wbw_maximum_filter()], +#' [wbw_range_filter()], [wbw_majority_filter()] +#' +#' @eval rd_wbw_link("total_filter") +#' @eval rd_example("wbw_total_filter", +#' c("filter_size_x = 3L", "filter_size_y = 3L")) +#' +#' @export +wbw_total_filter <- + S7::new_generic( + name = "wbw_total_filter", + dispatch_args = "x", + fun = function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + S7::S7_dispatch() + } + ) + +S7::method(wbw_total_filter, WhiteboxRaster) <- + function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + # Checks + check_env(wbe) + filter_size_x <- + checkmate::asInteger( + filter_size_x, + lower = 0L, + len = 1L + ) + filter_size_y <- + checkmate::asInteger( + filter_size_y, + lower = 0L, + len = 1L + ) + checkmate::assert_true(filter_size_x %% 2 == 1) + checkmate::assert_true(filter_size_y %% 2 == 1) + + # Filter + out <- + wbe$total_filter( + raster = x@source, + filter_size_x = filter_size_x, + filter_size_y = filter_size_y + ) + # Return Raster + WhiteboxRaster( + name = x@name, + source = out + ) + } + +#' Standard Deviation Filter +#' @keywords image_processing +#' +#' @description +#' A standard deviation filter assigns to each cell in the output grid the +#' standard deviation, a measure of dispersion, of the values contained within +#' a moving window centred on each grid cell. +#' +#' @details +#' Neighbourhood size, or filter size, is specified in the x and y dimensions +#' using \code{filter_size_x} and \code{filter_size_y} These dimensions should +#' be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +#' +#' @eval rd_input_raster("x") +#' @param filter_size_x \code{integer}, X dimension of the neighbourhood size +#' @param filter_size_y \code{integer}, Y dimension of the neighbourhood size +#' +#' @return [WhiteboxRaster] object containing filtered values +#' +#' @seealso [wbw_minimum_filter()], [wbw_maximum_filter()], +#' [wbw_range_filter()], [wbw_majority_filter()], [wbw_total_filter()] +#' +#' @eval rd_wbw_link("standard_deviation_filter") +#' @eval rd_example("wbw_standard_deviation_filter", +#' c("filter_size_x = 3L", "filter_size_y = 3L")) +#' +#' @export +wbw_standard_deviation_filter <- + S7::new_generic( + name = "wbw_standard_deviation_filter", + dispatch_args = "x", + fun = function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + S7::S7_dispatch() + } + ) + +S7::method(wbw_standard_deviation_filter, WhiteboxRaster) <- + function(x, + filter_size_x = 11L, + filter_size_y = 11L) { + # Checks + check_env(wbe) + filter_size_x <- + checkmate::asInteger( + filter_size_x, + lower = 0L, + len = 1L + ) + filter_size_y <- + checkmate::asInteger( + filter_size_y, + lower = 0L, + len = 1L + ) + checkmate::assert_true(filter_size_x %% 2 == 1) + checkmate::assert_true(filter_size_y %% 2 == 1) + + # Filter + out <- + wbe$standard_deviation_filter( + raster = x@source, + filter_size_x = filter_size_x, + filter_size_y = filter_size_y + ) + # Return Raster + WhiteboxRaster( + name = x@name, + source = out + ) + } diff --git a/R/utils_documentation.R b/R/utils_documentation.R index bf6e600..a9e327f 100644 --- a/R/utils_documentation.R +++ b/R/utils_documentation.R @@ -55,30 +55,4 @@ rd_example <- # "}", sep = "\n" ) - } - -#' Tinytest Snapshot -#' https://github.com/etiennebacher/astgrepr/ -#' blob/ea91137bdb10d22c7a988a8cb1b0bc896935fb0d/R/tinytest.R -#' -#' @keywords internal -#' @export -expect_snapshot <- function(label, current) { - snapshot_file <- file.path("_snapshots", paste0(label, ".txt")) - current2 <- paste(utils::capture.output(print(current)), collapse = "\n") - - if (!dir.exists(dirname(snapshot_file))) { - dir.create(dirname(snapshot_file), showWarnings = FALSE, recursive = TRUE) - } - if (!file.exists(snapshot_file)) { - cat(current2, file = snapshot_file, sep = "\n") - message("Creating file ", snapshot_file) - return(invisible()) - } - target <- paste(readLines(snapshot_file, warn = FALSE), collapse = "\n") - tinytest::tinytest( - result = identical(current2, target), - call = sys.call(sys.parent(1)), - diff = paste0("Check content of ", snapshot_file) - ) -} + } \ No newline at end of file diff --git a/man/expect_snapshot.Rd b/man/expect_snapshot.Rd deleted file mode 100644 index 3ffd422..0000000 --- a/man/expect_snapshot.Rd +++ /dev/null @@ -1,16 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils_documentation.R -\name{expect_snapshot} -\alias{expect_snapshot} -\title{Tinytest Snapshot -https://github.com/etiennebacher/astgrepr/ -blob/ea91137bdb10d22c7a988a8cb1b0bc896935fb0d/R/tinytest.R} -\usage{ -expect_snapshot(label, current) -} -\description{ -Tinytest Snapshot -https://github.com/etiennebacher/astgrepr/ -blob/ea91137bdb10d22c7a988a8cb1b0bc896935fb0d/R/tinytest.R -} -\keyword{internal} diff --git a/man/wbw_adaptive_filter.Rd b/man/wbw_adaptive_filter.Rd index a613a26..ec052f6 100644 --- a/man/wbw_adaptive_filter.Rd +++ b/man/wbw_adaptive_filter.Rd @@ -30,8 +30,8 @@ center cell value exceeds the user-defined threshold, the output cell is assigned the mean value. Otherwise, it retains its original value. Neighbourhood size, or filter size, is specified in the x and y dimensions -using \code{filter_size_x} and \code{filter_size_y} These dimensions should be odd, -positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). } \examples{ f <- system.file("extdata/dem.tif", package = "wbw") diff --git a/man/wbw_conservative_smoothing_filter.Rd b/man/wbw_conservative_smoothing_filter.Rd index 3fc9a7a..817e6f2 100644 --- a/man/wbw_conservative_smoothing_filter.Rd +++ b/man/wbw_conservative_smoothing_filter.Rd @@ -33,8 +33,8 @@ the corresponding grid cell in the output image is replaced with the minimum value. Neighbourhood size, or filter size, is specified in the x and y dimensions -using \code{filter_size_x} and \code{filter_size_y} These dimensions should be odd, -positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). } \examples{ f <- system.file("extdata/dem.tif", package = "wbw") diff --git a/man/wbw_high_pass_filter.Rd b/man/wbw_high_pass_filter.Rd index 07bfff9..177ac49 100644 --- a/man/wbw_high_pass_filter.Rd +++ b/man/wbw_high_pass_filter.Rd @@ -25,8 +25,8 @@ neighbourhood (i.e. window.) } \details{ Neighbourhood size, or filter size, is specified in the x and y dimensions -using \code{filter_size_x} and \code{filter_size_y} These dimensions should be odd, -positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). } \examples{ f <- system.file("extdata/dem.tif", package = "wbw") diff --git a/man/wbw_high_pass_median_filter.Rd b/man/wbw_high_pass_median_filter.Rd index 628e5cd..52c361c 100644 --- a/man/wbw_high_pass_median_filter.Rd +++ b/man/wbw_high_pass_median_filter.Rd @@ -18,7 +18,8 @@ wbw_high_pass_median_filter( \item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} -\item{sig_digits}{\code{integer}} +\item{sig_digits}{\code{integer}, default 2. Required for rounding of +floating points inputs.} } \value{ \link{WhiteboxRaster} object containing filtered values @@ -32,8 +33,8 @@ surrounding neighbourhood (i.e. window.) } \details{ Neighbourhood size, or filter size, is specified in the x and y dimensions -using \code{filter_size_x} and \code{filter_size_y} These dimensions should be odd, -positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). } \examples{ f <- system.file("extdata/dem.tif", package = "wbw") diff --git a/man/wbw_majority_filter.Rd b/man/wbw_majority_filter.Rd new file mode 100644 index 0000000..c705590 --- /dev/null +++ b/man/wbw_majority_filter.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filters.R +\name{wbw_majority_filter} +\alias{wbw_majority_filter} +\title{Majority Filter} +\usage{ +wbw_majority_filter(x, filter_size_x = 11L, filter_size_y = 11L) +} +\arguments{ +\item{x}{Raster object of class \link{WhiteboxRaster}. See \code{\link[=wbw_read_raster]{wbw_read_raster()}} for more details.} + +\item{filter_size_x}{\code{integer}, X dimension of the neighbourhood size} + +\item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} +} +\value{ +\link{WhiteboxRaster} object containing filtered values +} +\description{ +Assigns each cell in the output grid the most frequently occurring value +(mode) in a moving window centred on each grid cell in the input raster. +} +\details{ +Neighbourhood size, or filter size, is specified in the x and y dimensions +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +} +\examples{ +f <- system.file("extdata/dem.tif", package = "wbw") +wbw_read_raster(f) |> + wbw_majority_filter(filter_size_x = 3L, filter_size_y = 3L) +} +\references{ +For more information, see \url{https://www.whiteboxgeo.com/manual/wbw-user-manual/book/tool_help.html#majority_filter} +} +\seealso{ +\code{\link[=wbw_mean_filter]{wbw_mean_filter()}}, \code{\link[=wbw_high_pass_filter]{wbw_high_pass_filter()}}, +\code{\link[=wbw_high_pass_median_filter]{wbw_high_pass_median_filter()}} +} +\keyword{image_processing} diff --git a/man/wbw_maximum_filter.Rd b/man/wbw_maximum_filter.Rd new file mode 100644 index 0000000..b0a3a7b --- /dev/null +++ b/man/wbw_maximum_filter.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filters.R +\name{wbw_maximum_filter} +\alias{wbw_maximum_filter} +\title{Maximum Filter} +\usage{ +wbw_maximum_filter(x, filter_size_x = 11L, filter_size_y = 11L) +} +\arguments{ +\item{x}{Raster object of class \link{WhiteboxRaster}. See \code{\link[=wbw_read_raster]{wbw_read_raster()}} for more details.} + +\item{filter_size_x}{\code{integer}, X dimension of the neighbourhood size} + +\item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} +} +\value{ +\link{WhiteboxRaster} object containing filtered values +} +\description{ +Assigns each cell in the output grid the maximum value in a moving window +centred on each grid cell in the input raster. +} +\details{ +Neighbourhood size, or filter size, is specified in the x and y dimensions +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +} +\examples{ +f <- system.file("extdata/dem.tif", package = "wbw") +wbw_read_raster(f) |> + wbw_maximum_filter(filter_size_x = 3L, filter_size_y = 3L) +} +\references{ +For more information, see \url{https://www.whiteboxgeo.com/manual/wbw-user-manual/book/tool_help.html#maximum_filter} +} +\seealso{ +\code{\link[=wbw_mean_filter]{wbw_mean_filter()}}, \code{\link[=wbw_high_pass_filter]{wbw_high_pass_filter()}}, +\code{\link[=wbw_high_pass_median_filter]{wbw_high_pass_median_filter()}} +} +\keyword{image_processing} diff --git a/man/wbw_mean_filter.Rd b/man/wbw_mean_filter.Rd index cea106d..d7f7e5f 100644 --- a/man/wbw_mean_filter.Rd +++ b/man/wbw_mean_filter.Rd @@ -27,8 +27,8 @@ their smoothing compared to edge-preserving alternatives like the \link{wbw_bilateral_filter} or \link{wbw_gaussian_filter}. Neighbourhood size, or filter size, is specified in the x and y dimensions -using \code{filter_size_x} and \code{filter_size_y} These dimensions should be odd, -positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). } \examples{ f <- system.file("extdata/dem.tif", package = "wbw") diff --git a/man/wbw_median_filter.Rd b/man/wbw_median_filter.Rd index 0361e09..7ca31d9 100644 --- a/man/wbw_median_filter.Rd +++ b/man/wbw_median_filter.Rd @@ -13,7 +13,8 @@ wbw_median_filter(x, filter_size_x = 11L, filter_size_y = 11L, sig_digits = 2L) \item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} -\item{sig_digits}{\code{integer}} +\item{sig_digits}{\code{integer}, default 2. Required for rounding of +floating points inputs.} } \value{ \link{WhiteboxRaster} object containing filtered values @@ -34,8 +35,8 @@ that the average is. As such, the median filter is far less sensitive to shot noise in an image than the mean filter. Neighbourhood size, or filter size, is specified in the x and y dimensions -using \code{filter_size_x} and \code{filter_size_y} These dimensions should be odd, -positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). } \examples{ f <- system.file("extdata/dem.tif", package = "wbw") diff --git a/man/wbw_minimum_filter.Rd b/man/wbw_minimum_filter.Rd new file mode 100644 index 0000000..6cb034f --- /dev/null +++ b/man/wbw_minimum_filter.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filters.R +\name{wbw_minimum_filter} +\alias{wbw_minimum_filter} +\title{Minimum Filter} +\usage{ +wbw_minimum_filter(x, filter_size_x = 11L, filter_size_y = 11L) +} +\arguments{ +\item{x}{Raster object of class \link{WhiteboxRaster}. See \code{\link[=wbw_read_raster]{wbw_read_raster()}} for more details.} + +\item{filter_size_x}{\code{integer}, X dimension of the neighbourhood size} + +\item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} +} +\value{ +\link{WhiteboxRaster} object containing filtered values +} +\description{ +Assigns each cell in the output grid the minimum value in a moving window +centred on each grid cell in the input raster. +} +\details{ +Neighbourhood size, or filter size, is specified in the x and y dimensions +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +} +\examples{ +f <- system.file("extdata/dem.tif", package = "wbw") +wbw_read_raster(f) |> + wbw_minimum_filter(filter_size_x = 3L, filter_size_y = 3L) +} +\references{ +For more information, see \url{https://www.whiteboxgeo.com/manual/wbw-user-manual/book/tool_help.html#minimum_filter} +} +\seealso{ +\code{\link[=wbw_mean_filter]{wbw_mean_filter()}}, \code{\link[=wbw_high_pass_filter]{wbw_high_pass_filter()}}, +\code{\link[=wbw_high_pass_median_filter]{wbw_high_pass_median_filter()}} +} +\keyword{image_processing} diff --git a/man/wbw_olympic_filter.Rd b/man/wbw_olympic_filter.Rd new file mode 100644 index 0000000..61c85f7 --- /dev/null +++ b/man/wbw_olympic_filter.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filters.R +\name{wbw_olympic_filter} +\alias{wbw_olympic_filter} +\title{Olympic Filter} +\usage{ +wbw_olympic_filter(x, filter_size_x = 11L, filter_size_y = 11L) +} +\arguments{ +\item{x}{Raster object of class \link{WhiteboxRaster}. See \code{\link[=wbw_read_raster]{wbw_read_raster()}} for more details.} + +\item{filter_size_x}{\code{integer}, X dimension of the neighbourhood size} + +\item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} +} +\value{ +\link{WhiteboxRaster} object containing filtered values +} +\description{ +This filter is a modification of the \link{wbw_mean_filter}, whereby +the highest and lowest values in the kernel are dropped, and the remaining +values are averaged to replace the central pixel. The result is a +low-pass smoothing filter that is more robust than the \link{wbw_mean_filter}, +which is more strongly impacted by the presence of outlier values. +It is named after a system of scoring Olympic events. +} +\details{ +Neighbourhood size, or filter size, is specified in the x and y dimensions +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +} +\examples{ +f <- system.file("extdata/dem.tif", package = "wbw") +wbw_read_raster(f) |> + wbw_olympic_filter(filter_size_x = 3L, filter_size_y = 3L) +} +\references{ +For more information, see \url{https://www.whiteboxgeo.com/manual/wbw-user-manual/book/tool_help.html#olympic_filter} +} +\seealso{ +\code{\link[=wbw_mean_filter]{wbw_mean_filter()}} +} +\keyword{image_processing} diff --git a/man/wbw_percentile_filter.Rd b/man/wbw_percentile_filter.Rd new file mode 100644 index 0000000..cbf8f1c --- /dev/null +++ b/man/wbw_percentile_filter.Rd @@ -0,0 +1,67 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filters.R +\name{wbw_percentile_filter} +\alias{wbw_percentile_filter} +\title{Percentile Filter} +\usage{ +wbw_percentile_filter( + x, + filter_size_x = 11L, + filter_size_y = 11L, + sig_digits = 2L +) +} +\arguments{ +\item{x}{Raster object of class \link{WhiteboxRaster}. See \code{\link[=wbw_read_raster]{wbw_read_raster()}} for more details.} + +\item{filter_size_x}{\code{integer}, X dimension of the neighbourhood size} + +\item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} + +\item{sig_digits}{\code{integer}, default 2. Required for rounding of +floating points inputs.} +} +\value{ +\link{WhiteboxRaster} object containing filtered values +} +\description{ +This tool calculates the percentile of the center cell in a moving filter +window applied to an input image (\code{x}). This indicates the value +below which a given percentage of the neighbouring values in within the +filter fall. For example, the 35th percentile is the value below which 35\% +of the neighbouring values in the filter window may be found. As such, +the percentile of a pixel value is indicative of the relative location +of the site within the statistical distribution of values contained +within a filter window. + +When applied to input digital elevation models, percentile is a measure of +local topographic position, or elevation residual. +} +\details{ +Neighbourhood size, or filter size, is specified in the x and y dimensions +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). + +This tool takes advantage of the redundancy between overlapping, +neighbouring filters to enhance computationally efficiency, using a +method similar to Huang et al. (1979). This efficient method of +calculating percentiles requires rounding of floating-point inputs, +and therefore the user must specify the number of significant +digits (\code{sig_digits}) to be used during the processing. +} +\examples{ +f <- system.file("extdata/dem.tif", package = "wbw") +wbw_read_raster(f) |> + wbw_percentile_filter(filter_size_x = 3L, filter_size_y = 3L) +} +\references{ +Huang, T., Yang, G.J.T.G.Y. and Tang, G., 1979. A fast two-dimensional +median filtering algorithm. IEEE Transactions on Acoustics, Speech, and +Signal Processing, 27(1), pp.13-18. + +For more information, see \url{https://www.whiteboxgeo.com/manual/wbw-user-manual/book/tool_help.html#percentile_filter} +} +\seealso{ +\code{\link[=wbw_median_filter]{wbw_median_filter()}} +} +\keyword{image_processing} diff --git a/man/wbw_range_filter.Rd b/man/wbw_range_filter.Rd new file mode 100644 index 0000000..24637f9 --- /dev/null +++ b/man/wbw_range_filter.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filters.R +\name{wbw_range_filter} +\alias{wbw_range_filter} +\title{Range Filter} +\usage{ +wbw_range_filter(x, filter_size_x = 11L, filter_size_y = 11L) +} +\arguments{ +\item{x}{Raster object of class \link{WhiteboxRaster}. See \code{\link[=wbw_read_raster]{wbw_read_raster()}} for more details.} + +\item{filter_size_x}{\code{integer}, X dimension of the neighbourhood size} + +\item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} +} +\value{ +\link{WhiteboxRaster} object containing filtered values +} +\description{ +A range filter assigns to each cell in the output grid the range +(maximum - minimum) of the values contained within a moving window +centred on each grid cell. +} +\details{ +Neighbourhood size, or filter size, is specified in the x and y dimensions +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +} +\examples{ +f <- system.file("extdata/dem.tif", package = "wbw") +wbw_read_raster(f) |> + wbw_range_filter(filter_size_x = 3L, filter_size_y = 3L) +} +\references{ +For more information, see \url{https://www.whiteboxgeo.com/manual/wbw-user-manual/book/tool_help.html#range_filter} +} +\seealso{ +\code{\link[=wbw_minimum_filter]{wbw_minimum_filter()}}, \code{\link[=wbw_maximum_filter]{wbw_maximum_filter()}} +} +\keyword{image_processing} diff --git a/man/wbw_standard_deviation_filter.Rd b/man/wbw_standard_deviation_filter.Rd new file mode 100644 index 0000000..dd72e69 --- /dev/null +++ b/man/wbw_standard_deviation_filter.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filters.R +\name{wbw_standard_deviation_filter} +\alias{wbw_standard_deviation_filter} +\title{Standard Deviation Filter} +\usage{ +wbw_standard_deviation_filter(x, filter_size_x = 11L, filter_size_y = 11L) +} +\arguments{ +\item{x}{Raster object of class \link{WhiteboxRaster}. See \code{\link[=wbw_read_raster]{wbw_read_raster()}} for more details.} + +\item{filter_size_x}{\code{integer}, X dimension of the neighbourhood size} + +\item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} +} +\value{ +\link{WhiteboxRaster} object containing filtered values +} +\description{ +A standard deviation filter assigns to each cell in the output grid the +standard deviation, a measure of dispersion, of the values contained within +a moving window centred on each grid cell. +} +\details{ +Neighbourhood size, or filter size, is specified in the x and y dimensions +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +} +\examples{ +f <- system.file("extdata/dem.tif", package = "wbw") +wbw_read_raster(f) |> + wbw_standard_deviation_filter(filter_size_x = 3L, filter_size_y = 3L) +} +\references{ +For more information, see \url{https://www.whiteboxgeo.com/manual/wbw-user-manual/book/tool_help.html#standard_deviation_filter} +} +\seealso{ +\code{\link[=wbw_minimum_filter]{wbw_minimum_filter()}}, \code{\link[=wbw_maximum_filter]{wbw_maximum_filter()}}, +\code{\link[=wbw_range_filter]{wbw_range_filter()}}, \code{\link[=wbw_majority_filter]{wbw_majority_filter()}}, \code{\link[=wbw_total_filter]{wbw_total_filter()}} +} +\keyword{image_processing} diff --git a/man/wbw_total_filter.Rd b/man/wbw_total_filter.Rd new file mode 100644 index 0000000..0f6ba11 --- /dev/null +++ b/man/wbw_total_filter.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filters.R +\name{wbw_total_filter} +\alias{wbw_total_filter} +\title{Total Filter} +\usage{ +wbw_total_filter(x, filter_size_x = 11L, filter_size_y = 11L) +} +\arguments{ +\item{x}{Raster object of class \link{WhiteboxRaster}. See \code{\link[=wbw_read_raster]{wbw_read_raster()}} for more details.} + +\item{filter_size_x}{\code{integer}, X dimension of the neighbourhood size} + +\item{filter_size_y}{\code{integer}, Y dimension of the neighbourhood size} +} +\value{ +\link{WhiteboxRaster} object containing filtered values +} +\description{ +A total filter assigns to each cell in the output grid the total (sum) +of all values in a moving window centred on each grid cell. +} +\details{ +Neighbourhood size, or filter size, is specified in the x and y dimensions +using \code{filter_size_x} and \code{filter_size_y} These dimensions should +be odd, positive integer values (e.g. 3L, 5L, 7L, 9L, etc.). +} +\examples{ +f <- system.file("extdata/dem.tif", package = "wbw") +wbw_read_raster(f) |> + wbw_total_filter(filter_size_x = 3L, filter_size_y = 3L) +} +\references{ +For more information, see \url{https://www.whiteboxgeo.com/manual/wbw-user-manual/book/tool_help.html#total_filter} +} +\seealso{ +\code{\link[=wbw_minimum_filter]{wbw_minimum_filter()}}, \code{\link[=wbw_maximum_filter]{wbw_maximum_filter()}}, +\code{\link[=wbw_range_filter]{wbw_range_filter()}}, \code{\link[=wbw_majority_filter]{wbw_majority_filter()}} +} +\keyword{image_processing} diff --git a/tests/tinytest/setup.R b/tests/tinytest/setup.R index 336d115..bfb5f99 100644 --- a/tests/tinytest/setup.R +++ b/tests/tinytest/setup.R @@ -17,8 +17,3 @@ skip_if_not_installed <- function(pkg) { exit_file("Package", pkg, "not available") } } - -register_tinytest_extension( - "wbw", - "expect_snapshot" -) \ No newline at end of file diff --git a/tests/tinytest/test_filter.R b/tests/tinytest/test_filter.R index 6c452aa..c307c91 100644 --- a/tests/tinytest/test_filter.R +++ b/tests/tinytest/test_filter.R @@ -1,92 +1,162 @@ source("setup.R") -# Test adaptive filter failures -expect_error(wbw_adaptive_filter(x, filter_size_x = 10L)) -expect_error(wbw_adaptive_filter(x, filter_size_y = 2)) -expect_error(wbw_adaptive_filter(x, filter_size_y = c(1:2))) -expect_error(wbw_adaptive_filter(x, filter_size_y = 1.5)) -expect_error(wbw_adaptive_filter(x, threshold = "a")) -expect_error(wbw_adaptive_filter("x", threshold = "a")) - -# Test bilateral filter failures -expect_error(wbw_bilateral_filter(x, sigma_dist = 10L)) -expect_error(wbw_bilateral_filter(x, sigma_int = -2)) -expect_error(wbw_bilateral_filter(x, sigma_dist = c(1:2))) -expect_error(wbw_bilateral_filter(x, sigma_dist = 20.1)) -expect_error(wbw_bilateral_filter(x, sigma_dist = "a")) -expect_error(wbw_bilateral_filter("x", sigma_int = "a")) - -# Test mean filter failures -expect_error(wbw_mean_filter(x, filter_size_x = 10L)) -expect_error(wbw_mean_filter(x, filter_size_y = 2)) -expect_error(wbw_mean_filter(x, filter_size_y = c(1:2))) -expect_error(wbw_mean_filter(x, filter_size_y = 1.5)) -expect_error(wbw_mean_filter(x, filter_size_y = "a")) -expect_error(wbw_mean_filter("x", filter_size_y = "a")) - -# Test conservative smoothing filter failures -expect_error(wbw_conservative_smoothing_filter(x, filter_size_x = 10L)) -expect_error(wbw_conservative_smoothing_filter(x, filter_size_y = 2)) -expect_error(wbw_conservative_smoothing_filter(x, filter_size_y = c(1:2))) -expect_error(wbw_conservative_smoothing_filter(x, filter_size_y = 1.5)) -expect_error(wbw_conservative_smoothing_filter(x, filter_size_y = "a")) -expect_error(wbw_conservative_smoothing_filter("x", filter_size_y = "a")) - -# Test high pass filter failures -expect_error(wbw_high_pass_filter(x, filter_size_x = 10, filter_size_y = 11)) -expect_error(wbw_high_pass_filter(x, filter_size_x = 11, filter_size_y = 10)) -expect_error(wbw_high_pass_filter(x, filter_size_x = 11.1, filter_size_y = 11)) -expect_error(wbw_high_pass_filter("x", filter_size_x = 11, filter_size_y = 11)) - # Test successful filter returns -expect_inherits(wbw_adaptive_filter(x), c("wbw::WhiteboxRaster", "S7_object")) -expect_inherits(wbw_bilateral_filter(x), c("wbw::WhiteboxRaster", "S7_object")) -expect_inherits(wbw_mean_filter(x), c("wbw::WhiteboxRaster", "S7_object")) -expect_inherits(wbw_conservative_smoothing_filter(x), c("wbw::WhiteboxRaster", "S7_object")) -expect_inherits(wbw_high_pass_filter(x), c("wbw::WhiteboxRaster", "S7_object")) -expect_inherits(wbw_gaussian_filter(x), c("wbw::WhiteboxRaster", "S7_object")) - -# Snapshots -expect_snapshot( - label = "wbw_adaptive_filter", - wbw_adaptive_filter(x) +expect_inherits( + wbw_adaptive_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_bilateral_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_conservative_smoothing_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_gaussian_filter(x), c("wbw::WhiteboxRaster", "S7_object") ) -expect_snapshot( - label = "wbw_bilateral_filter", - wbw_bilateral_filter(x) +expect_inherits( + wbw_high_pass_filter(x), c("wbw::WhiteboxRaster", "S7_object") ) -expect_snapshot( - label = "wbw_mean_filter", - wbw_mean_filter(x) +expect_inherits( + wbw_high_pass_median_filter(x), c("wbw::WhiteboxRaster", "S7_object") ) -expect_snapshot( - label = "wbw_conservative_smoothing_filter", - wbw_conservative_smoothing_filter(x) +expect_inherits( + wbw_majority_filter(x), c("wbw::WhiteboxRaster", "S7_object") ) -expect_snapshot( - label = "wbw_high_pass_filter", - wbw_high_pass_filter(x) +expect_inherits( + wbw_maximum_filter(x), c("wbw::WhiteboxRaster", "S7_object") ) -expect_snapshot( - label = "wbw_gaussian_filter", - wbw_gaussian_filter(x) +expect_inherits( + wbw_mean_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_median_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_minimum_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_olympic_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_percentile_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_range_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_total_filter(x), c("wbw::WhiteboxRaster", "S7_object") +) +expect_inherits( + wbw_standard_deviation_filter(x), c("wbw::WhiteboxRaster", "S7_object") ) # Test filter alterations +# Here is near-equality check is happening. If two values are close to +# be equal, i.e. 2.222222226 and 2.222222225, then all.equal() returns TRUE +# In other cases the function will return the mean relative difference as +# a character vector true_median <- median(x) -# Test adaptive filter -filtered <- wbw_adaptive_filter(x, filter_size_x = 51, filter_size_y = 51) -expect_true(median(filtered) != true_median) - -# Test bilateral filter -filtered <- wbw_bilateral_filter(x, sigma_dist = 5, sigma_int = 5) -expect_true(median(filtered) != true_median) - -# Test mean filter -filtered <- wbw_mean_filter(x, filter_size_x = 51, filter_size_y = 51) -expect_true(median(filtered) != true_median) - -# Test gaussian filter -filtered <- wbw_gaussian_filter(x, sigma = 5) -expect_true(median(filtered) != true_median) +expect_true( + wbw_adaptive_filter( + x, + filter_size_x = 51, + filter_size_y = 51 + ) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_bilateral_filter( + x, + sigma_dist = 3 + ) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_conservative_smoothing_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_gaussian_filter(x, sigma = 1.5) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_high_pass_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_high_pass_median_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_majority_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_maximum_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_mean_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_median_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_minimum_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_olympic_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_percentile_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_range_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_total_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +) +expect_true( + wbw_standard_deviation_filter(x) |> + median() |> + all.equal(true_median) |> + is.character() +)