Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
^\.vscode$
^LICENSE\.md$
^src/Makevars$
^\.claude$
25 changes: 19 additions & 6 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
Package: ClassicHCAS
Type: Package
Title: The Classic Habitat Condition Assessment System (HCAS)
Version: 1.1.0
Date: 2026-03-18
Author: Roozbeh Valavi, Eric Lehmann, Kristen Williams, Mike Birchall, Simon Collings, Simon Ferrier, and Tom Harwood
Maintainer: <roozbeh.valavi@csiro.au>
Version: 2.0.0
Date: 2026-07-02
Authors@R: c(
person(given = "Roozbeh", family = "Valavi",
email = "roozbeh.valavi@csiro.au", role = c("aut", "cre")),
person(given = "Kristen", family = "Williams", role = "aut"),
person(given = "Eric", family = "Lehmann", role = "aut"),
person(given = "Simon", family = "Collings", role = "aut"),
person(given = "Tom", family = "Harwood", role = "aut"),
person(given = "Mike", family = "Birchall", role = "aut"),
person(given = "Simon", family = "Ferrier", role = "aut"))
URL: https://github.com/csiro/ClassicHCAS
BugReports: https://github.com/csiro/ClassicHCAS/issues
Maintainer: Roozbeh Valavi <roozbeh.valavi@csiro.au>
Description: The HCAS evaluates habitat condition by comparing observed and
predicted remote sensing variables using reference ecosystem samples (Valavi et al. 2026).
predicted remote sensing variables using reference ecosystem samples.
License: GPL (>= 3)
Encoding: UTF-8
LazyData: true
Expand All @@ -19,12 +27,17 @@ Imports:
scales,
terra (>= 1.7.71)
Suggests:
ggplot2,
leafem,
leaflet,
methods,
knitr,
rmarkdown,
shiny,
shinyWidgets,
tinytest,
testthat (>= 3.0.0)
RoxygenNote: 7.3.2
RoxygenNote: 7.3.3
VignetteBuilder: knitr
Config/testthat/edition: 3
LinkingTo:
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

S3method(plot,reference_density)
S3method(print,reference_density)
export(aggregate_importance)
export(benchmark)
export(calibrate)
export(hcas_inspection)
export(normalise)
export(palettes)
export(radial_count)
export(ref_density)
export(reference_use)
export(tiling)
export(variable_importance)
import(Rcpp)
importFrom(Rcpp,sourceCpp)
useDynLib(ClassicHCAS, .registration = TRUE)
92 changes: 56 additions & 36 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,75 @@
# Version 2.0.0

- Added a boosted condition estimator to `benchmark()`, `reference_use()`, `variable_importance()`, and `hcas_inspection()`. The default is now `boost = k2`, with `k1 = 70` and `k2 = 10`: the highest-probability retained site's kernel weight is multiplied by the boost factor before computing condition, condition attribution, or variable-importance weights. Set `boost = NULL` or `boost = NA` to use the previous unboosted LDC/ordinary-kernel behaviour.
- Renamed the public `k_pred` and `k_obs` arguments to `k1` and `k2`, respectively, to identify them as the first- and second-stage reference filters rather than imply that each filter is tied exclusively to an environmental or observed-RS definition.
- Added an experimental expanded temporal reference mode to `benchmark()`. It is off by default; supply `temporal_sigma` to enable it. `temporal_sigma` controls the bandwidth of the Gaussian temporal weighting used to select and weight the most relevant reference year for each site. Reference samples can be supplied as a named list of yearly matrices. This expands the temporal representation of reference sites rather than applying a post-hoc correction to the target condition score.
- Added selectable retained-reference distance kernels. `kernel = "Gaussian"` remains the default and uses `exp(-(distance / lambda)^2)`; `kernel = "Cauchy"` uses the standard Cauchy shape `1 / (1 + (distance / lambda)^2)`. Lower-case `gaussian` and `cauchy` are also accepted. The same option is used by `benchmark()`, `reference_use()`, `hcas_inspection()`, and `variable_importance()`.
- Added raster target support to `hcas_inspection()`. Raster inputs use x/y target coordinates, can extract reference-sample values from xy-only `samples`, and support Leaflet map clicks that snap the clicked location to the containing raster cell centre.
- Added `reference_use()` to assess how reference sites are used during benchmarking. A single run returns each site's `predicted` selection count among `k1`, `density` retention count among `k2`, and `condition` attribution. Its attribution uses the selected distance kernel and `boost` setting. Expanded temporal references are not yet supported by `reference_use()`.
- Added `variable_importance()` to attribute the observed target-to-reference departure to each RS variable. The `output` argument selects per-variable layers of `"importance"` (default; signal-to-noise ratio: the weighted mean absolute departure of the target from its references, standardised by the weighted spread among the references themselves), `"signal"` (the raw weighted departure contribution, which sums per cell to the total observed departure), or `"share"` (the per-cell departure partition, where a cell's variables sum to one — a direct percent attribution). `aggregate_importance()` summarises the per-cell scores across the landscape into a median ranking and a mean relative-share attribution. Its retained-reference weighting uses the same selected distance kernel and `boost` setting as `benchmark()`. Expanded temporal references are not yet supported.

# Version 1.1.0
* Consolidated package colour helpers into a single `palettes()` function and removed `hcas_color()` and `ref_density_color()`.
* Changed `drop_features` so excluded RS variables are removed from the active feature set before C++ distance calculations, instead of being zeroed in place.

- Consolidated package colour helpers into a single `palettes()` function and removed `hcas_color()` and `ref_density_color()`.
- Changed `drop_features` so excluded RS variables are removed from the active feature set before C++ distance calculations, instead of being zeroed in place.

# Version 1.0.0
* Renamed the reference density function to `ref_density()`, renamed the radial counting function (from `proximity()`) to `radial_count()`, and changed the reference density object class to `reference_density`.
* The order of input data has completely changed and both `ref_density()` and `benchmark()` functions require data with **x**, **y**, **predicted**, and **observed** remote sensing variable order.
* Complete re-write of the main C++ functions (for `ref_density()`, `benchmark()`, and `radial_count()`) using vectorised operations, including changing feature space distance calculations from `double` to `float32`, resulting in significant speed improvement (~10x) with no loss of accuracy.
* The Eigen C++ library is adapted as the main matrix engine.
* The dependency on KDtrees is dropped while keeping or even improving the speed.
* The reference density now performs only one-way pairwise distance calculations. As a result, the raw reference density values are exactly halved compared to before. This has no impact on the normalised reference density or the final output.
* The "corner value" in the reference density (previously calculated as the count of values) is no longer computed, since it is simply equal to the number of samples.
* The `calibrate()` function no longer performs interpolation. The output is now fully fitted using a monotonic spline.
* A fast spatial distance calculation is implemented (no difference for projected CRS with 0.01 meters accuracy).
* The geographic distance for lat/long is now corrected for the latitude of the source cell, not just the radius transformation to degrees.
* A new function (`tiling()`) is added for making raster tiles using raster or matrix data.
* The `NaN` pixels are now directly handled within C++ code.
* Expanded the test suite with additional C++-focused coverage, including edge cases and thread-consistency checks for core workflows.

- Renamed the reference density function to `ref_density()`, renamed the radial counting function (from `proximity()`) to `radial_count()`, and changed the reference density object class to `reference_density`.
- The order of input data has completely changed and both `ref_density()` and `benchmark()` functions require data with **x**, **y**, **predicted**, and **observed** remote sensing variable order.
- Complete re-write of the main C++ functions (for `ref_density()`, `benchmark()`, and `radial_count()`) using vectorised operations, including changing feature space distance calculations from `double` to `float32`, resulting in significant speed improvement (\~10x) with no loss of accuracy.
- The Eigen C++ library is adapted as the main matrix engine.
- The dependency on KDtrees is dropped while keeping or even improving the speed.
- The reference density now performs only one-way pairwise distance calculations. As a result, the raw reference density values are exactly halved compared to before. This has no impact on the normalised reference density or the final output.
- The "corner value" in the reference density (previously calculated as the count of values) is no longer computed, since it is simply equal to the number of samples.
- The `calibrate()` function no longer performs interpolation. The output is now fully fitted using a monotonic spline.
- A fast spatial distance calculation is implemented (no difference for projected CRS with 0.01 meters accuracy).
- The geographic distance for lat/long is now corrected for the latitude of the source cell, not just the radius transformation to degrees.
- A new function (`tiling()`) is added for making raster tiles using raster or matrix data.
- The `NaN` pixels are now directly handled within C++ code.
- Expanded the test suite with additional C++-focused coverage, including edge cases and thread-consistency checks for core workflows.

# Version 0.2.0
* Added `drop_features` parameter to fully exclude specific remote sensing variables from both the `ref_density` and `benchmark` functions.
* Added a condition to ensure that `k_obs` is less than or equal to `k_pred`.
* A new reference density normalisation method has been implemented in R using the `legacy = FALSE` argument to mitigate edge effects.
* The zero-zero point (reference self-count) in the raw reference density is now excluded prior to normalisation.
* The `ref_density` function arguments have changed to `data` and `samples`.

- Added `drop_features` parameter to fully exclude specific remote sensing variables from both the `ref_density` and `benchmark` functions.
- Added a condition to ensure that `k_obs` is less than or equal to `k_pred`.
- A new reference density normalisation method has been implemented in R using the `legacy = FALSE` argument to mitigate edge effects.
- The zero-zero point (reference self-count) in the raw reference density is now excluded prior to normalisation.
- The `ref_density` function arguments have changed to `data` and `samples`.

# Version 0.1.6
* Added a `scale_factor` parameter to allow user-defined correction of geographic CRS distance calculations, enhancing flexibility in handling distance conversions (previously set to a default value only).
* Enhanced C++ code for improved efficiency in point class creation.

- Added a `scale_factor` parameter to allow user-defined correction of geographic CRS distance calculations, enhancing flexibility in handling distance conversions (previously set to a default value only).
- Enhanced C++ code for improved efficiency in point class creation.

# Version 0.1.5
* Replaced the natural spline in the `calibrate` function with a monotonically increasing spline function.

- Replaced the natural spline in the `calibrate` function with a monotonically increasing spline function.

# Version 0.1.4
* Deprecated the linear (piece-wise) calibration method, superseded with the spline method.
* The arguments of `calibrate` are updated with `x_values` and `y_values`.
* Fixed the benchmarking `self_exclude` floating point error.

- Deprecated the linear (piece-wise) calibration method, superseded with the spline method.
- The arguments of `calibrate` are updated with `x_values` and `y_values`.
- Fixed the benchmarking `self_exclude` floating point error.

# Version 0.1.3
* Added the `proximity` function to count the number of samples within a specified radius.
* Removed the requirement for `add_xy` in the `benchmark()` function.
* Removed `filename` and `wopt` parameters from all functions and replaced them with additional arguments `...` for more flexibility.
* Internal `terra` functions have been improved by eliminating the need for explicit creation of x and y coordinates.

- Added the `proximity` function to count the number of samples within a specified radius.
- Removed the requirement for `add_xy` in the `benchmark()` function.
- Removed `filename` and `wopt` parameters from all functions and replaced them with additional arguments `...` for more flexibility.
- Internal `terra` functions have been improved by eliminating the need for explicit creation of x and y coordinates.

# Version 0.1.2
* Check for availability of the `terra` package is added when input is a raster
* improved documentation and imports
* a bug fix in benchmarking

- Check for availability of the `terra` package is added when input is a raster
- improved documentation and imports
- a bug fix in benchmarking

# Version 0.1.1
* Added the geographic distance penalty for selecting the nearest predicted neighbours (`xy_penalty` and `xy_stats` parameters)
* Added an option for excluding self-assessment for benchmark sample sites (default).

- Added the geographic distance penalty for selecting the nearest predicted neighbours (`xy_penalty` and `xy_stats` parameters)
- Added an option for excluding self-assessment for benchmark sample sites (default).

# Version 0.1.0
* Translated all legacy HCAS codes to R and Rcpp

- Translated all legacy HCAS codes to R and Rcpp
59 changes: 49 additions & 10 deletions R/ClassicHCAS.R
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
#' ClassicHCAS: The Classic Habitat Condition Assessment System (HCAS)
#'
#' The HCAS evaluates habitat condition by comparing observed and predicted
#' remote sensing (RS) variables using reference ecosystem samples.
#' It integrates multiple RS data layers to provide a comprehensive assessment of
#' habitat quality.
#'
#' @seealso \code{\link{benchmark}} and \code{\link{ref_density}}.
#' ClassicHCAS: The Classic Habitat Condition Assessment System (HCAS)
#'
#' @references The Habitat Condition Assessment System (HCAS)...
#' ClassicHCAS implements the core Habitat Condition Assessment System workflow
#' for estimating habitat condition from Earth observation and environmental
#' data. HCAS compares observed remote-sensing (RS) variables with predicted
#' reference-condition RS variables. Locations whose observed signal is close to
#' the expected reference signal, relative to high-integrity reference samples,
#' receive higher condition scores.
#'
#' @details
#' The package is data-agnostic: users supply their own observed RS variables,
#' predicted reference-condition RS variables, and reference or benchmark samples.
#' The expected RS variables are usually produced outside this package by
#' modelling high-integrity reference ecosystems as a function of abiotic
#' environmental covariates such as climate, soils, water availability, and
#' landform.
#'
#' The main ClassicHCAS workflow is:
#' \enumerate{
#' \item Use \code{\link{ref_density}} to build a reference density surface
#' from pairwise predicted and observed RS distances among reference samples.
#' \item Use \code{\link{normalise}} to trim and normalise that surface so it
#' can be used as a probability surface during benchmarking.
#' \item Use \code{\link{benchmark}} to estimate unscaled condition for target
#' locations or rasters by comparing them with nearby, environmentally similar
#' reference samples.
#' \item Use \code{\link{calibrate}} to transform unscaled condition values to
#' an interpretable 0-1 condition scale.
#' }
#'
#' Operational helpers include \code{\link{radial_count}}, for mapping local
#' reference-sample support, \code{\link{tiling}}, for splitting large raster
#' jobs into balanced processing tiles, and \code{\link{palettes}}, for package
#' plotting colours.
#'
#' @seealso \code{\link{ref_density}}, \code{\link{normalise}},
#' \code{\link{benchmark}}, and \code{\link{calibrate}}.
#'
#' @references
#' Harwood, T. D., Donohue, R. J., Williams, K. J., Ferrier, S.,
#' McVicar, T. R., Newell, G., and White, M. (2016). Habitat Condition
#' Assessment System: A new way to assess the condition of natural habitats for
#' terrestrial biodiversity across whole regions using remote sensing data.
#' \emph{Methods in Ecology and Evolution}, 7(9), 1050-1059.
#'
#' Williams, K. J., Harwood, T. D., Lehmann, E. A., Ware, C., Lyon, P.,
#' Bakar, S., Schmidt, R. K., Mokany, K., Van Niel, T. G., Richards, A. E.,
#' Dickson, F., McVicar, R., and Ferrier, S. (2021). Habitat Condition
#' Assessment System (HCAS version 2.1). CSIRO Publishing.
#'
#' @name ClassicHCAS
#' @author Roozbeh Valavi, Chris Ware, Eric Lehmann, Kristen Williams, Mike Birchall, Simon Collings, Simon Ferrier, and Tom Harwood
#' @author Roozbeh Valavi, Kristen Williams, Eric Lehmann, Simon Collings, Tom Harwood, Mike Birchall, and Simon Ferrier
#' @import Rcpp
NULL
12 changes: 10 additions & 2 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

bench_cpp <- function(raster_vals, sample_vals, ref_density, xy_stats, xy_penalty = 0.0, geographic = FALSE, radius_km = 200, k_env = 50L, k_rs = 20L, bin_width = 0.05, bin_num = 400L, offset = 0L, confidence = 0.5, lambda = 2.0, exclude_slef = TRUE, make_su = FALSE, num_threads = -1L) {
.Call(`_ClassicHCAS_bench_cpp`, raster_vals, sample_vals, ref_density, xy_stats, xy_penalty, geographic, radius_km, k_env, k_rs, bin_width, bin_num, offset, confidence, lambda, exclude_slef, make_su, num_threads)
bench_cpp <- function(raster_vals, sample_vals, ref_density, xy_stats, xy_penalty = 0.0, geographic = FALSE, radius_km = 200, k_env = 70L, k_rs = 10L, bin_width = 0.05, bin_num = 400L, offset = 0L, confidence = 0.5, lambda = 1.0, exclude_slef = TRUE, temporal_weights = NULL, make_su = FALSE, num_threads = -1L, kernel = "gaussian", boost = NULL) {
.Call(`_ClassicHCAS_bench_cpp`, raster_vals, sample_vals, ref_density, xy_stats, xy_penalty, geographic, radius_km, k_env, k_rs, bin_width, bin_num, offset, confidence, lambda, exclude_slef, temporal_weights, make_su, num_threads, kernel, boost)
}

norm_cpp <- function(x, trim_size = 400L, offset = 0L) {
Expand All @@ -17,7 +17,15 @@ ref_density_cpp <- function(rs_vals, pr_vals, xy_vals, radius_km = 1000.0, bin_w
.Call(`_ClassicHCAS_ref_density_cpp`, rs_vals, pr_vals, xy_vals, radius_km, bin_width, bin_num, geographic, num_threads)
}

reference_use_cpp <- function(target_vals, sample_vals, ref_density, xy_stats, xy_penalty = 0.0, geographic = FALSE, radius_km = 200, k_env = 70L, k_rs = 10L, bin_width = 0.05, bin_num = 400L, offset = 0L, confidence = 0.5, lambda = 1.0, exclude_slef = TRUE, num_threads = -1L, weighted_max = FALSE, kernel = "gaussian", boost = NULL) {
.Call(`_ClassicHCAS_reference_use_cpp`, target_vals, sample_vals, ref_density, xy_stats, xy_penalty, geographic, radius_km, k_env, k_rs, bin_width, bin_num, offset, confidence, lambda, exclude_slef, num_threads, weighted_max, kernel, boost)
}

tiling_cpp <- function(x, n_tiles, method = "best", exact = TRUE) {
.Call(`_ClassicHCAS_tiling_cpp`, x, n_tiles, method, exact)
}

variable_importance_cpp <- function(target_vals, sample_vals, ref_density, xy_stats, xy_penalty = 0.0, geographic = FALSE, radius_km = 200, k_env = 70L, k_rs = 10L, bin_width = 0.05, bin_num = 400L, offset = 0L, lambda = 1.0, epsilon = 1e-6, output = "importance", exclude_slef = TRUE, num_threads = -1L, kernel = "gaussian", boost = NULL) {
.Call(`_ClassicHCAS_variable_importance_cpp`, target_vals, sample_vals, ref_density, xy_stats, xy_penalty, geographic, radius_km, k_env, k_rs, bin_width, bin_num, offset, lambda, epsilon, output, exclude_slef, num_threads, kernel, boost)
}

Loading
Loading