The ascent package implements the
ASC-CFD (Assemblage Shift Characterization — Community
Functional Dynamics) framework. Communities can exhibit identical levels
of functional turnover while following fundamentally different
ecological trajectories. One community may experience a directional
shift in its functional equilibrium, another may simply reorganize
biomass internally, and a third may expand into previously unoccupied
regions of trait space. Traditional metrics often collapse these
distinct processes into a single value. ascent instead uses
a multi-layer topological approach to decompose community restructuring
into three orthogonal geometric components:
Table 1. Functional diversity metrics used in ASC-CFD frameworks.
| Layer | Metric | Ecological Question |
|---|---|---|
| Position | ΔC | Where is the community moving? |
| Dispersion | ΔFDis | How is biomass being redistributed? |
| Boundary | ΔFRic | Are functional boundaries expanding or collapsing? |
To isolate deterministic environmental filtering from stochastic
noise, ascent triggers a hierarchical triad of null models:
Structural (Incidence), Quantitative
(Demographic), and Identity (Trait Shuffle).
We simulate a bird community experiencing habitat degradation.
Functional matrices often contain mixed data types. Here, we combine
quantitative traits (body mass, beak length) and binary traits (diet,
habitat specialization). Binary traits MUST be encoded as
factor to correctly apply the Gower
distance metric.
library(ascent)
# 1. Functional Trait Space
set.seed(42)
aves_traits <- data.frame(
Body_Mass = c(15, 20, 30, 45, 60, 90, 150, 250, 400, 600),
Beak_Length = c(10, 12, 15, 22, 28, 35, 45, 60, 85, 120),
Frugivore = factor(c(0, 0, 1, 1, 1, 0, 1, 1, 1, 0)),
Forest_Dep = factor(c(0, 0, 0, 0, 1, 1, 1, 1, 1, 1))
)
rownames(aves_traits) <- paste0("Av_sp", 1:10)
# 2a. Temporal Matrix (Deforestation)
abund_time <- rbind(
Site1_Ref = c( 0, 0, 10, 15, 25, 20, 10, 8, 4, 2), # Mature forest
Site1_Imp = c(40, 35, 15, 5, 0, 0, 0, 0, 0, 0) # Logged area
)
# 2b. Spatial Matrix (Landscape Gradient)
abund_space <- rbind(
Primary = c( 0, 0, 5, 10, 20, 25, 15, 10, 5, 2),
Secondary = c( 0, 5, 10, 20, 35, 20, 10, 0, 0, 0),
Agri = c( 0, 0, 0, 5, 45, 45, 5, 0, 0, 0)
)We start with the core engine: evaluating the functional
restructuring driven by deforestation in Site 1 using
asc_paired(). We simultaneously trigger the triad of null
models using asc_null(). (Note:
n_perm = 99 is used for CRAN vignette compilation speed.
Use 999 or 9999 for research).
res_paired <- asc_paired(
traits = aves_traits, abund = abund_time,
sites = c("Site1", "Site1"), time = c("Reference", "Impacted"),
ref_time = "Reference", dist_method = "gower"
)
res_paired <- asc_null(res_paired, n_perm = 99, seed = 123)
summary(res_paired)
#> ==================================================
#> ASC-CFD: Multidimensional Functional Restructuring
#> ==================================================
#>
#> Number of Contrasts: 1
#> Functional Dimensionality (k): 2 (Explaining 96.4% of variance)
#> PCoA Quality: 83.8%
#>
#> --- Functional Shift Overview ---
#> Contrast Layer1_rDeltaC Layer2_DeltaFDis Layer3_DeltaFRic
#> Site1 42.42 -0.093 -0.2415
#>
#> --- Multi-Level Null Model Evaluation ---
#> Struct: Incidence Filter | Quant: Demographic Filter | Identity: Trait Filter
#> Note: FRic under Quantitative filter is NA (incidence fixed -> hull invariant)
#>
#> Contrast Filter Metric Observed SES P_value
#> Site1 Structural Position (Delta C) 0.4186 2.66 0.07
#> Site1 Quantitative Position (Delta C) 0.4186 -0.28 0.60
#> Site1 Identity Position (Delta C) 0.4186 1.64 0.03
#> Site1 Structural Dispersion (Delta FDis) -0.0930 -0.55 0.49
#> Site1 Quantitative Dispersion (Delta FDis) -0.0930 -0.07 0.48
#> Site1 Identity Dispersion (Delta FDis) -0.0930 -0.41 0.47
#> Site1 Structural Volume (Delta FRic) -0.2415 -0.09 0.63
#> Site1 Quantitative Volume (Delta FRic) -0.2415 NA NA
#> Site1 Identity Volume (Delta FRic) -0.2415 -0.37 0.48
#>
#> --- Top Functional Drivers (Leverage Preview) ---
#> Contrast
#> Site1
#> Top_5_Drivers
#> Av_sp1 (+0.20), Av_sp2 (+0.18), Av_sp6 (-0.03), Av_sp5 (+0.02), Av_sp8 (+0.02)Ecological Interpretation: The community experienced a displacement of the functional centroid (42.42% of the regional functional diameter), while changes in dispersion and volume were small and consistent with random expectations. The only component that exceeded the null models was position under the identity filter, indicating that the observed restructuring was associated with a non-random selection of combinations of functional traits. Consequently, the results suggest a directional functional filtering process without evidence of significant contraction of the functional niche or internal reorganization of biomass.
To dissect the biological drivers behind this geometric shift, we extract the Functional Leverage. This algorithm projects the multidimensional demographic shift (\(\Delta p_i\)) of each species onto the unit directional vector of the ecosystem.
# Extract the specific topological drivers
drivers_time <- asc_transitions(res_paired)
head(drivers_time$Site1$species_leverage, 4)
#> Species Delta_p Projection Leverage
#> 1 Av_sp1 0.4210526 0.48262845 0.20321198
#> 2 Av_sp2 0.3684211 0.47589125 0.17532836
#> 3 Av_sp6 -0.2127660 0.12159546 -0.02587137
#> 4 Av_sp5 -0.2659574 -0.07792306 0.02072422
# Plot the PCoA trajectory and the leverage divergence
plot(res_paired, contrast = "Site1", type = "both", n_sp = 5)Ecological Interpretation: Species Av_sp1 (small, open-area generalist) exhibited the highest positive leverage, indicating that its demographic expansion strongly pulled the community centroid toward the degraded state. In contrast, Av_sp6 showed negative leverage because it declined despite occupying a position aligned with the direction of change, partially opposing the overall displacement. Conversely, the decline of Av_sp5 generated a small positive leverage effect by removing biomass from a region of trait space located opposite to the observed trajectory, thereby facilitating the centroid shift.
For landscape ecology or beta-diversity studies, ascent
computes the bidirectional spatial divergence between all possible
community pairs using asc_pairwise().
res_pw <- asc_pairwise(traits = aves_traits, abund = abund_space, dist_method = "gower")
res_pw <- asc_null(res_pw, n_perm = 99, seed = 42)
summary(res_pw)
#> ==================================================
#> ASC-CFD: Pairwise Spatial Functional Network
#> ==================================================
#>
#> Communities Analyzed: 3 | Spatial Contrasts: 3
#> Functional Dimensionality (k): 2 (Explaining 96.4% of variance)
#> PCoA Quality: 83.8%
#>
#> --- Global Divergence Summary ---
#> Mean Position Shift (rDelta_C): 10.87%
#> Mean Dispersion Shift (Delta_FDis): -0.0225
#> Mean Volume Shift (Delta_FRic): -0.1108
#>
#> --- Multi-Level Null Model Evaluation (Head) ---
#> Struct: Incidence Filter | Quant: Demographic Filter | Identity: Trait Filter
#> Note: FRic under Quantitative filter is NA (incidence fixed -> hull invariant)
#>
#> Contrast Filter Metric Observed SES
#> Primary_vs_Secondary Structural Position (Delta C) 0.1223 -0.12
#> Primary_vs_Secondary Quantitative Position (Delta C) 0.1223 -1.29
#> Primary_vs_Secondary Identity Position (Delta C) 0.1223 0.71
#> Primary_vs_Secondary Structural Dispersion (Delta FDis) -0.0021 1.22
#> Primary_vs_Secondary Quantitative Dispersion (Delta FDis) -0.0021 0.59
#> Primary_vs_Secondary Identity Dispersion (Delta FDis) -0.0021 0.15
#> Primary_vs_Secondary Structural Volume (Delta FRic) -0.0687 1.05
#> Primary_vs_Secondary Quantitative Volume (Delta FRic) -0.0687 NA
#> Primary_vs_Secondary Identity Volume (Delta FRic) -0.0687 0.04
#> Primary_vs_Agri Structural Position (Delta C) 0.0641 0.91
#> P_value
#> 0.45
#> 0.89
#> 0.24
#> 1.00
#> 1.00
#> 0.96
#> 0.92
#> NA
#> 0.59
#> 0.30
#>
#> --- Top Functional Drivers (Leverage Preview - Head) ---
#> Contrast
#> Primary_vs_Secondary
#> Primary_vs_Agri
#> Secondary_vs_Agri
#> Top_5_Drivers
#> Av_sp4 (+0.03), Av_sp3 (+0.02), Av_sp2 (+0.02), Av_sp8 (+0.02), Av_sp9 (+0.02)
#> Av_sp6 (+0.05), Av_sp5 (-0.02), Av_sp8 (+0.02), Av_sp7 (+0.01), Av_sp9 (+0.01)
#> Av_sp6 (+0.07), Av_sp4 (+0.04), Av_sp3 (+0.03), Av_sp7 (-0.01), Av_sp5 (+0.00)
# Visualize the functional gap between Primary and Secondary Forest
plot(res_pw, contrast = "Primary_vs_Secondary", type = "both", n_sp = 5)
# Visualize the severe functional gap between Secondary Forest and Agriculture
plot(res_pw, contrast = "Secondary_vs_Agri", type = "both", n_sp = 5)Ecological Interpretation: The spatial analysis revealed relatively small functional differences among communities. None of the observed shifts exceeded the expectations generated by the hierarchical null models, suggesting that the apparent variation among habitats can be explained by stochastic fluctuations in species composition and abundance. In this simulated example, agricultural intensification produced only modest changes in community topology, resulting in limited displacement of the functional centroid and minor reductions in functional volume. This example illustrates how ASC-CFD can distinguish between apparent community differences and statistically supported functional restructuring. Although the communities differ in composition, none of the observed topological shifts were stronger than expected under the null models, indicating weak evidence for deterministic functional filtering.
Sometimes, a researcher only needs to report the absolute structural
metrics of isolated communities without computing directional networks.
asc_baseline() calculates the absolute functional topology
of isolated communities.
base_topo <- asc_baseline(traits = aves_traits, abund = abund_space, dist_method = "gower")
summary(base_topo)
#> ==================================================
#> ASC-CFD: Baseline Functional Topology
#> ==================================================
#>
#> Entities Analyzed: 3
#> Functional Dimensionality (k): 2 (Explaining 96.4% of variance)
#> PCoA Quality: 83.8%
#>
#> --- Absolute Entity Metrics ---
#> Entity CWM_Axis_1 CWM_Axis_2 FDis FRic
#> Primary 0.0524 -0.0604 0.2377 0.2491
#> Secondary -0.0686 -0.0784 0.2356 0.1804
#> Agri 0.0401 0.0025 0.2040 0.0829The baseline metrics reveal a gradual reduction in both functional
richness and functional dispersion from Primary forest to
Agri habitat, indicating that agricultural communities
occupy a somewhat smaller and less dispersed region of the functional
space.
As a supplementary utility, the package provides
asc_entities(), an algorithm that clusters the regional
species pool into discrete functional entities based on morphological
and ecological trait distances, regardless of spatial abundance.
# Cluster the species into 3 functional entities using Gower distance
func_ent <- asc_entities(traits = aves_traits, dist_method = "gower", k = 3)
summary(func_ent)
#> ==================================================
#> ASC-CFD: Functional Entities Classification
#> ==================================================
#>
#> Total Species: 10
#> Functional Entities Identified: 3
#> Distance Metric: Gower | Clustering Method: ward.D2
#>
#> --- Species Distribution per Entity ---
#>
#> Entity_1 Entity_2 Entity_3
#> 5 4 1
#>
#> --- Classification Preview (Head) ---
#> Species Entity_ID Body_Mass Beak_Length Frugivore Forest_Dep
#> Av_sp1 Entity_1 15 10 0 0
#> Av_sp2 Entity_1 20 12 0 0
#> Av_sp3 Entity_1 30 15 1 0
#> Av_sp4 Entity_1 45 22 1 0
#> Av_sp5 Entity_2 60 28 1 1
# Visualize the functional dendrogram
plot(func_ent)This classification helps researchers map continuous traits into discrete ecological guilds prior to mapping community-level dynamics.
Choosing the Appropriate Function
Table 2. Functions included in ascent
package and its purposes.
| Objective | Function |
|---|---|
| Temporal restructuring | asc_paired() |
| Spatial divergence | asc_pairwise() |
| Species drivers | asc_transitions() |
| Baseline topology | asc_baseline() |
| Functional entities | asc_entities() |
| Null model inference | asc_null() |
FRic is computed as the volume of the convex hull in the retained PCoA axes. It captures the outer boundary of the functional space and has the following properties:
FRic = NA rather
than FRic = 0, because a zero-volume hull is a meaningful
geometric statement (collinear species), while NA signals
that the metric cannot be computed.Recommendation: Interpret \(\Delta FRic\) as a topological descriptor of the functional boundary, complementary to (but not substituting for) the abundance-weighted \(\Delta FDis\).
asc_null() operates on the full stacked community matrix
and assumes a shared regional species pool. The
curveball algorithm permutes species across all rows simultaneously. For
biogeographically independent sites, run asc_null() on each
contrast separately.
Model A assigns uniform relative abundances (\(1/S_{local}\)) to all species present after the curveball permutation. This means the null distribution for FDis under Model A tests whether the shift is extreme given random species composition with equitable abundances, not with the observed SAD.
The Functional Leverage satisfies a strict mathematical identity:
\[\sum_{i=1}^{S} \text{Leverage}_i = \|\Delta C\|\]
Each species’ leverage is the product of its demographic change and its alignment with the centroid trajectory:
\[\text{Leverage}_i = \Delta p_i \cdot \text{proj}(\mathbf{f}_i, \hat{v})\]
where \(\Delta p_i = p_{i,\text{comp}} - p_{i,\text{ref}}\) is the change in relative abundance, and \(\text{proj}(\mathbf{f}_i, \hat{v})\) is the scalar projection of the species’ PCoA coordinates onto the unit directional vector \(\hat{v}\) of the centroid shift. Species with positive leverage drive the shift; species with negative leverage resist it.