ecological-agent-skills 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_CONTEXT.md +191 -0
- package/CATALOG.md +329 -0
- package/LICENSE +692 -0
- package/README.md +347 -0
- package/bin/install.mjs +168 -0
- package/docs/comparison-with-alternatives.md +38 -0
- package/docs/global-examples-index.md +103 -0
- package/docs/repository-statistics.md +101 -0
- package/docs/theoretical-foundations.md +188 -0
- package/environment.yaml +106 -0
- package/examples/community/arctic_tundra_vegetation_example.md +247 -0
- package/examples/community/bird_landuse_example.md +63 -0
- package/examples/community/phytoplankton_reservoir_example.md +60 -0
- package/examples/community/reef_fish_indopacific_example.md +221 -0
- package/examples/impact/baci_road_example.md +57 -0
- package/examples/impact/ecosystem_services_atlantic_forest.md +83 -0
- package/examples/impact/forest_loss_borneo_timeseries_example.md +225 -0
- package/examples/occupancy/puma_camera_example.md +61 -0
- package/examples/occupancy/snow_leopard_himalayas_example.md +204 -0
- package/examples/reproducible/whittaker_biome_sdm_example.md +406 -0
- package/examples/sdm/anteater_cerrado_example.md +69 -0
- package/examples/sdm/jaguar_amazon_example.md +80 -0
- package/examples/sdm/koala_climate_change_example.md +170 -0
- package/examples/sdm/wolf_recolonization_europe_example.md +193 -0
- package/package.json +43 -0
- package/renv.lock +194 -0
- package/skills/SKILL_INDEX.json +1020 -0
- package/skills/acoustic-monitoring/SKILL.md +163 -0
- package/skills/acoustic-monitoring/examples/example-prompts.md +100 -0
- package/skills/acoustic-monitoring/examples/temperate_forest_birds_example.md +285 -0
- package/skills/acoustic-monitoring/resources/acoustic-indices-reference.md +93 -0
- package/skills/acoustic-monitoring/resources/soundscape-ecology-guide.md +90 -0
- package/skills/acoustic-monitoring/resources/species-id-tools-comparison.md +89 -0
- package/skills/acoustic-monitoring/scripts/batch_species_detection.py +360 -0
- package/skills/acoustic-monitoring/scripts/compute_acoustic_indices.R +235 -0
- package/skills/acoustic-monitoring/scripts/compute_acoustic_indices.py +374 -0
- package/skills/biostatistics-workbench/SKILL.md +140 -0
- package/skills/biostatistics-workbench/examples/example-prompts.md +39 -0
- package/skills/biostatistics-workbench/resources/effect-size-reference.md +81 -0
- package/skills/biostatistics-workbench/resources/glm-family-link-reference.md +47 -0
- package/skills/biostatistics-workbench/resources/test-selection-guide.md +93 -0
- package/skills/biostatistics-workbench/scripts/glm_pipeline.R +78 -0
- package/skills/biostatistics-workbench/scripts/glm_pipeline.py +210 -0
- package/skills/camera-trap-processing/SKILL.md +159 -0
- package/skills/camera-trap-processing/examples/example-prompts.md +103 -0
- package/skills/camera-trap-processing/examples/leopard_serengeti_example.md +231 -0
- package/skills/camera-trap-processing/resources/activity-patterns-reference.md +113 -0
- package/skills/camera-trap-processing/resources/camtrapR-workflow-guide.md +130 -0
- package/skills/camera-trap-processing/resources/detection-event-definition-guide.md +89 -0
- package/skills/camera-trap-processing/scripts/estimate_activity.R +169 -0
- package/skills/camera-trap-processing/scripts/process_camtrap_data.R +179 -0
- package/skills/camera-trap-processing/scripts/process_camtrap_data.py +192 -0
- package/skills/community-ecology-ordination/SKILL.md +133 -0
- package/skills/community-ecology-ordination/examples/example-prompts.md +35 -0
- package/skills/community-ecology-ordination/resources/dissimilarity-metric-guide.md +53 -0
- package/skills/community-ecology-ordination/resources/nmds-interpretation-guide.md +104 -0
- package/skills/community-ecology-ordination/scripts/__pycache__/community_analysis.cpython-311.pyc +0 -0
- package/skills/community-ecology-ordination/scripts/community_analysis.R +143 -0
- package/skills/community-ecology-ordination/scripts/community_analysis.py +231 -0
- package/skills/ecological-data-foundation/SKILL.md +129 -0
- package/skills/ecological-data-foundation/examples/example-prompts.md +40 -0
- package/skills/ecological-data-foundation/resources/coordinate-cleaning-flags.md +66 -0
- package/skills/ecological-data-foundation/resources/darwin-core-glossary.md +91 -0
- package/skills/ecological-data-foundation/resources/data-citation-guide.md +265 -0
- package/skills/ecological-data-foundation/resources/gbif-data-citation-guide.md +193 -0
- package/skills/ecological-data-foundation/resources/qa-checklist.md +83 -0
- package/skills/ecological-data-foundation/scripts/__pycache__/clean_occurrences.cpython-311.pyc +0 -0
- package/skills/ecological-data-foundation/scripts/__pycache__/download_from_ebird.cpython-311.pyc +0 -0
- package/skills/ecological-data-foundation/scripts/__pycache__/download_from_inat.cpython-311.pyc +0 -0
- package/skills/ecological-data-foundation/scripts/__pycache__/download_from_iucn.cpython-311.pyc +0 -0
- package/skills/ecological-data-foundation/scripts/__pycache__/download_from_obis.cpython-311.pyc +0 -0
- package/skills/ecological-data-foundation/scripts/clean_occurrences.R +230 -0
- package/skills/ecological-data-foundation/scripts/clean_occurrences.py +268 -0
- package/skills/ecological-data-foundation/scripts/download_from_ebird.R +251 -0
- package/skills/ecological-data-foundation/scripts/download_from_ebird.py +364 -0
- package/skills/ecological-data-foundation/scripts/download_from_gbif.R +315 -0
- package/skills/ecological-data-foundation/scripts/download_from_gbif.py +407 -0
- package/skills/ecological-data-foundation/scripts/download_from_inat.R +238 -0
- package/skills/ecological-data-foundation/scripts/download_from_inat.py +304 -0
- package/skills/ecological-data-foundation/scripts/download_from_iucn.R +273 -0
- package/skills/ecological-data-foundation/scripts/download_from_iucn.py +344 -0
- package/skills/ecological-data-foundation/scripts/download_from_obis.R +248 -0
- package/skills/ecological-data-foundation/scripts/download_from_obis.py +318 -0
- package/skills/ecological-impact-assessment/SKILL.md +123 -0
- package/skills/ecological-impact-assessment/examples/example-prompts.md +32 -0
- package/skills/ecological-impact-assessment/resources/baci-design-guide.md +55 -0
- package/skills/ecological-impact-assessment/resources/fragmentation-metrics-reference.md +86 -0
- package/skills/ecological-impact-assessment/resources/pressure-index-template.md +78 -0
- package/skills/ecological-impact-assessment/resources/study-design-guide.md +168 -0
- package/skills/ecological-impact-assessment/scripts/baci_analysis.R +161 -0
- package/skills/ecological-impact-assessment/scripts/fragmentation_analysis.py +141 -0
- package/skills/ecological-impact-assessment/scripts/power_analysis_baci.R +274 -0
- package/skills/ecosystem-services-assessment/SKILL.md +125 -0
- package/skills/ecosystem-services-assessment/examples/example-prompts.md +24 -0
- package/skills/ecosystem-services-assessment/resources/es-indicator-reference.md +45 -0
- package/skills/ecosystem-services-assessment/resources/invest-parameter-guide.md +86 -0
- package/skills/ecosystem-services-assessment/resources/rusle-coefficients.md +88 -0
- package/skills/ecosystem-services-assessment/scripts/__pycache__/compute_es.cpython-311.pyc +0 -0
- package/skills/ecosystem-services-assessment/scripts/compute_es.py +189 -0
- package/skills/ecosystem-services-assessment/scripts/tradeoff_analysis.R +161 -0
- package/skills/environmental-time-series/SKILL.md +125 -0
- package/skills/environmental-time-series/examples/example-prompts.md +33 -0
- package/skills/environmental-time-series/resources/anomaly-indices-reference.md +88 -0
- package/skills/environmental-time-series/resources/bfast-parameter-guide.md +69 -0
- package/skills/environmental-time-series/scripts/__pycache__/recovery_trajectory.cpython-311.pyc +0 -0
- package/skills/environmental-time-series/scripts/__pycache__/trend_analysis.cpython-311.pyc +0 -0
- package/skills/environmental-time-series/scripts/recovery_trajectory.R +305 -0
- package/skills/environmental-time-series/scripts/recovery_trajectory.py +178 -0
- package/skills/environmental-time-series/scripts/trend_analysis.R +192 -0
- package/skills/environmental-time-series/scripts/trend_analysis.py +184 -0
- package/skills/geoprocessing-for-ecology/SKILL.md +123 -0
- package/skills/geoprocessing-for-ecology/examples/example-prompts.md +32 -0
- package/skills/geoprocessing-for-ecology/resources/crs-reference.md +62 -0
- package/skills/geoprocessing-for-ecology/resources/global-predictor-sources.md +331 -0
- package/skills/geoprocessing-for-ecology/resources/resampling-methods.md +57 -0
- package/skills/geoprocessing-for-ecology/scripts/__pycache__/download_predictors.cpython-311.pyc +0 -0
- package/skills/geoprocessing-for-ecology/scripts/download_predictors.R +239 -0
- package/skills/geoprocessing-for-ecology/scripts/download_predictors.py +379 -0
- package/skills/geoprocessing-for-ecology/scripts/stack_and_extract.R +224 -0
- package/skills/geoprocessing-for-ecology/scripts/stack_and_extract.py +172 -0
- package/skills/landscape-connectivity/SKILL.md +170 -0
- package/skills/landscape-connectivity/examples/example-prompts.md +96 -0
- package/skills/landscape-connectivity/examples/jaguar_mesoamerica_corridor_example.md +271 -0
- package/skills/landscape-connectivity/resources/circuitscape-parameter-guide.md +155 -0
- package/skills/landscape-connectivity/resources/graph-theory-for-ecology.md +134 -0
- package/skills/landscape-connectivity/resources/resistance-surface-guide.md +141 -0
- package/skills/landscape-connectivity/scripts/connectivity_analysis.py +387 -0
- package/skills/landscape-connectivity/scripts/connectivity_metrics.R +274 -0
- package/skills/landscape-connectivity/scripts/resistance_surface.R +239 -0
- package/skills/model-validation-and-uncertainty/SKILL.md +131 -0
- package/skills/model-validation-and-uncertainty/examples/example-prompts.md +30 -0
- package/skills/model-validation-and-uncertainty/resources/extrapolation-risk-guide.md +236 -0
- package/skills/model-validation-and-uncertainty/resources/metric-selection-guide.md +52 -0
- package/skills/model-validation-and-uncertainty/resources/threshold-selection-guide.md +64 -0
- package/skills/model-validation-and-uncertainty/scripts/__pycache__/validate_model.cpython-311.pyc +0 -0
- package/skills/model-validation-and-uncertainty/scripts/extrapolation_risk.R +315 -0
- package/skills/model-validation-and-uncertainty/scripts/validate_model.py +226 -0
- package/skills/model-validation-and-uncertainty/scripts/validate_sdm.R +162 -0
- package/skills/occupancy-and-detection/SKILL.md +126 -0
- package/skills/occupancy-and-detection/examples/example-prompts.md +33 -0
- package/skills/occupancy-and-detection/resources/detection-history-format.md +100 -0
- package/skills/occupancy-and-detection/resources/occupancy-study-design.md +47 -0
- package/skills/occupancy-and-detection/scripts/__pycache__/occupancy_analysis.cpython-311.pyc +0 -0
- package/skills/occupancy-and-detection/scripts/occupancy_analysis.R +160 -0
- package/skills/occupancy-and-detection/scripts/occupancy_analysis.py +159 -0
- package/skills/population-viability-analysis/SKILL.md +161 -0
- package/skills/population-viability-analysis/examples/african_elephant_pva_example.md +266 -0
- package/skills/population-viability-analysis/examples/example-prompts.md +95 -0
- package/skills/population-viability-analysis/resources/extinction-risk-thresholds.md +128 -0
- package/skills/population-viability-analysis/resources/matrix-model-guide.md +139 -0
- package/skills/population-viability-analysis/resources/sensitivity-elasticity-reference.md +182 -0
- package/skills/population-viability-analysis/scripts/matrix_pva.R +258 -0
- package/skills/population-viability-analysis/scripts/pva_analysis.py +442 -0
- package/skills/population-viability-analysis/scripts/stochastic_pva.R +353 -0
- package/skills/predictive-modeling-best-practices/SKILL.md +136 -0
- package/skills/predictive-modeling-best-practices/examples/example-prompts.md +58 -0
- package/skills/predictive-modeling-best-practices/resources/collinearity-decision-tree.md +65 -0
- package/skills/predictive-modeling-best-practices/resources/sampling-bias-correction.md +267 -0
- package/skills/predictive-modeling-best-practices/resources/spatial-cv-guide.md +73 -0
- package/skills/predictive-modeling-best-practices/scripts/__pycache__/spatial_cv.cpython-311.pyc +0 -0
- package/skills/predictive-modeling-best-practices/scripts/collinearity_check.R +112 -0
- package/skills/predictive-modeling-best-practices/scripts/spatial_cv.py +182 -0
- package/skills/reproducible-ecology-pipeline/SKILL.md +139 -0
- package/skills/reproducible-ecology-pipeline/examples/example-prompts.md +35 -0
- package/skills/reproducible-ecology-pipeline/resources/directory-structure-template.md +94 -0
- package/skills/reproducible-ecology-pipeline/resources/params-yaml-template.yaml +84 -0
- package/skills/reproducible-ecology-pipeline/resources/reproducibility-checklist-template.md +66 -0
- package/skills/reproducible-ecology-pipeline/scripts/generate_file_manifest.py +110 -0
- package/skills/reproducible-ecology-pipeline/scripts/init_project.sh +53 -0
- package/skills/spatial-prioritization/SKILL.md +162 -0
- package/skills/spatial-prioritization/examples/biodiversity_hotspot_prioritization_example.md +289 -0
- package/skills/spatial-prioritization/examples/example-prompts.md +93 -0
- package/skills/spatial-prioritization/resources/cost-surface-reference.md +130 -0
- package/skills/spatial-prioritization/resources/marxan-vs-prioritizr-comparison.md +125 -0
- package/skills/spatial-prioritization/resources/prioritizr-formulation-guide.md +188 -0
- package/skills/spatial-prioritization/resources/representation-targets-guide.md +186 -0
- package/skills/spatial-prioritization/scripts/prioritization_sensitivity.R +320 -0
- package/skills/spatial-prioritization/scripts/run_prioritization.R +336 -0
- package/skills/species-distribution-modeling/SKILL.md +139 -0
- package/skills/species-distribution-modeling/examples/example-prompts.md +36 -0
- package/skills/species-distribution-modeling/resources/algorithm-comparison.md +25 -0
- package/skills/species-distribution-modeling/resources/calibration-area-guide.md +71 -0
- package/skills/species-distribution-modeling/resources/climate-scenario-preparation.md +170 -0
- package/skills/species-distribution-modeling/resources/maxent-calibration-guide.md +211 -0
- package/skills/species-distribution-modeling/resources/sdm-checklist.md +37 -0
- package/skills/species-distribution-modeling/scripts/predict_distribution.R +236 -0
- package/skills/species-distribution-modeling/scripts/predict_distribution.py +286 -0
- package/skills/species-distribution-modeling/scripts/prepare_future_layers.R +351 -0
- package/skills/species-distribution-modeling/scripts/project_scenarios.R +220 -0
- package/skills/species-distribution-modeling/scripts/run_ensemble_sdm.R +99 -0
- package/skills/species-distribution-modeling/scripts/sdm_pipeline.py +318 -0
- package/skills/species-distribution-modeling/scripts/tune_maxnet.R +344 -0
- package/templates/SKILL_TEMPLATE.md +225 -0
- package/templates/checklists/data-submission-checklist.md +38 -0
- package/templates/checklists/post-analysis-checklist.md +55 -0
- package/templates/checklists/pre-analysis-checklist.md +31 -0
- package/templates/prompts/debug-skill.md +47 -0
- package/templates/prompts/invoke-skill.md +34 -0
- package/templates/prompts/invoke-workflow.md +45 -0
- package/templates/reports/technical-report-template.md +80 -0
- package/templates/scripts/logger_setup.R +79 -0
- package/templates/scripts/logger_setup.py +119 -0
- package/templates/scripts/params_loader.R +28 -0
- package/templates/scripts/params_loader.py +38 -0
- package/workflows/analyze-community-structure/WORKFLOW.md +72 -0
- package/workflows/analyze-environmental-change/WORKFLOW.md +73 -0
- package/workflows/assess-ecological-impact/WORKFLOW.md +75 -0
- package/workflows/assess-ecosystem-services/WORKFLOW.md +68 -0
- package/workflows/assess-landscape-connectivity/WORKFLOW.md +84 -0
- package/workflows/build-fire-risk-map/WORKFLOW.md +79 -0
- package/workflows/produce-technical-report/WORKFLOW.md +113 -0
- package/workflows/run-camera-trap-occupancy/WORKFLOW.md +87 -0
- package/workflows/run-conservation-prioritization/WORKFLOW.md +89 -0
- package/workflows/run-multispecies-screening/WORKFLOW.md +197 -0
- package/workflows/run-occupancy-analysis/WORKFLOW.md +74 -0
- package/workflows/run-population-viability/WORKFLOW.md +90 -0
- package/workflows/run-sdm-study/WORKFLOW.md +99 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
resource_id: marxan-vs-prioritizr-comparison
|
|
3
|
+
skill_id: spatial-prioritization
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Marxan vs prioritizr vs Zonation: Tool Comparison
|
|
7
|
+
|
|
8
|
+
## Core Comparison
|
|
9
|
+
|
|
10
|
+
| Feature | Marxan | prioritizr | Zonation |
|
|
11
|
+
|---------|--------|-----------|---------|
|
|
12
|
+
| **Algorithm** | Simulated annealing (heuristic) | Integer Linear Programming (exact) | Iterative removal (hierarchical) |
|
|
13
|
+
| **Solution type** | Multiple near-optimal solutions | Single optimal (or near-optimal with gap) | Continuous priority rank surface |
|
|
14
|
+
| **Objective** | Minimum set / maximum coverage | Minimum set / maximum coverage / others | Hierarchical feature retention |
|
|
15
|
+
| **Targets** | Required | Required | Optional (uses curves) |
|
|
16
|
+
| **Spatial compactness** | BLM penalty | BLM penalty | Integrated via edge weights |
|
|
17
|
+
| **Speed on large problems** | Fast (heuristic) | Slower (exact, ILP overhead) | Fast (greedy removal) |
|
|
18
|
+
| **Repeatability** | Stochastic (multiple runs) | Deterministic (exact) | Deterministic |
|
|
19
|
+
| **R integration** | marxan R package | Native R (prioritizr) | ZonationR (wrapper) |
|
|
20
|
+
| **License** | Free (registration) | Open source (MIT) | Free (registration) |
|
|
21
|
+
| **Best for** | Exploratory planning, large PU counts | Exact solution, auditability | Landscape-wide ranking without targets |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to Use Each Tool
|
|
26
|
+
|
|
27
|
+
### Use Marxan when:
|
|
28
|
+
- Very large landscapes (> 100,000 planning units) where ILP is computationally infeasible
|
|
29
|
+
- Exploring multiple near-optimal solutions to present to stakeholders
|
|
30
|
+
- Legacy workflow compatibility required
|
|
31
|
+
|
|
32
|
+
### Use prioritizr when:
|
|
33
|
+
- Provably optimal or near-optimal solution required (legal/policy context)
|
|
34
|
+
- Multiple constraints (locked in, locked out, budget constraints) must be handled exactly
|
|
35
|
+
- Reproducibility and auditability are paramount
|
|
36
|
+
- Gap to optimality must be certified (gap < 1%)
|
|
37
|
+
|
|
38
|
+
### Use Zonation when:
|
|
39
|
+
- No hard targets — want to rank all areas from most to least irreplaceable
|
|
40
|
+
- Connectivity features (dispersal kernels, landscape complementarity) are central
|
|
41
|
+
- Creating a continuous priority surface for broad-scale land-use planning
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Equivalence of Marxan BLM and prioritizr BLM
|
|
46
|
+
|
|
47
|
+
Both tools use a Boundary Length Modifier to penalise fragmentation, but implementation differs:
|
|
48
|
+
|
|
49
|
+
```r
|
|
50
|
+
# prioritizr: BLM is applied as a penalty per unit of boundary
|
|
51
|
+
p_prioritizr <- p %>%
|
|
52
|
+
add_boundary_penalties(penalty = 0.01, data = NULL)
|
|
53
|
+
|
|
54
|
+
# Marxan BLM equivalent (approximate)
|
|
55
|
+
# Marxan BLM ≈ prioritizr penalty × mean PU perimeter
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Calibration:** The same BLM value will produce different results in Marxan vs prioritizr because Marxan's objective function scaling differs. Calibrate each tool's BLM independently.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Zonation Priority Surface in R (Concept)
|
|
63
|
+
|
|
64
|
+
Zonation iteratively removes the planning unit with the least conservation value, preserving the most irreplaceable areas until all PUs are removed. The order of removal = priority rank (last removed = highest priority).
|
|
65
|
+
|
|
66
|
+
```r
|
|
67
|
+
# Simplified Zonation-like ranking in R (for conceptual illustration)
|
|
68
|
+
# Full Zonation requires the standalone software
|
|
69
|
+
zonation_rank <- function(features, weights = NULL) {
|
|
70
|
+
if (is.null(weights)) weights <- rep(1, nlyr(features))
|
|
71
|
+
feature_vals <- as.data.frame(features, xy = FALSE, na.rm = FALSE)
|
|
72
|
+
# Weighted rarity-normalised score per cell
|
|
73
|
+
totals <- colSums(feature_vals, na.rm = TRUE)
|
|
74
|
+
totals[totals == 0] <- 1
|
|
75
|
+
norm_vals <- sweep(feature_vals, 2, totals, "/")
|
|
76
|
+
cell_scores <- rowSums(norm_vals * rep(weights, each = nrow(norm_vals)),
|
|
77
|
+
na.rm = TRUE)
|
|
78
|
+
# Rank cells: higher score = higher priority
|
|
79
|
+
rank(-cell_scores, ties.method = "first")
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Irreplaceability Comparison
|
|
86
|
+
|
|
87
|
+
Both Marxan and prioritizr can compute irreplaceability scores:
|
|
88
|
+
|
|
89
|
+
| Method | Implementation | Interpretation |
|
|
90
|
+
|--------|---------------|----------------|
|
|
91
|
+
| Marxan summed solution frequency | Run 100 solutions; irreplaceability = frequency of selection | 1.0 = selected in all solutions = irreplaceable |
|
|
92
|
+
| prioritizr rarity-weighted richness | `eval_rare_richness_importance()` | Higher = rarer features concentrated in that PU |
|
|
93
|
+
| Zonation rank | Priority rank from removal order | Rank 1 = last removed = most irreplaceable |
|
|
94
|
+
|
|
95
|
+
```r
|
|
96
|
+
# prioritizr irreplaceability
|
|
97
|
+
irr_map <- eval_rare_richness_importance(p, s)
|
|
98
|
+
|
|
99
|
+
# Marxan portfolio approach via prioritizr
|
|
100
|
+
# Run 100 solutions with varying budgets/targets
|
|
101
|
+
solutions <- lapply(1:100, function(i) {
|
|
102
|
+
solve(p %>% add_highs_solver(gap = 0.05)) # relaxed gap for diversity
|
|
103
|
+
})
|
|
104
|
+
# Frequency map
|
|
105
|
+
freq_map <- Reduce("+", solutions) / 100
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Output Format Comparison
|
|
111
|
+
|
|
112
|
+
| Output | Marxan | prioritizr | Zonation |
|
|
113
|
+
|--------|--------|-----------|---------|
|
|
114
|
+
| Solution raster | `.dat` grid or spatial join | `SpatRaster` (binary) | `.rank.compressed.tif` |
|
|
115
|
+
| Feature representation | `_mvbest.txt` | `eval_feature_representation_summary()` | `curves.txt` |
|
|
116
|
+
| Cost summary | `_summary.txt` | `eval_cost_summary()` | — |
|
|
117
|
+
| Boundary | `_boundcalc.txt` | `eval_boundary_summary()` | edge weight output |
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## References
|
|
122
|
+
|
|
123
|
+
- Ball, I.R., Possingham, H.P. & Watts, M.E. (2009). Marxan and relatives: software for spatial conservation prioritisation. In: *Spatial Conservation Prioritisation* (pp. 185–195). Oxford University Press.
|
|
124
|
+
- Hanson, J.O. et al. (2024). prioritizr: Systematic conservation prioritization in R. *Methods in Ecology and Evolution*, 15(8), 1337–1344. DOI: 10.1111/2041-210X.14376
|
|
125
|
+
- Moilanen, A. et al. (2022). Zonation spatial conservation planning framework, Version 5. University of Helsinki.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
resource_id: prioritizr-formulation-guide
|
|
3
|
+
skill_id: spatial-prioritization
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# prioritizr Problem Formulation Guide
|
|
7
|
+
|
|
8
|
+
## Problem Types
|
|
9
|
+
|
|
10
|
+
| Problem type | Objective | When to use |
|
|
11
|
+
|-------------|-----------|-------------|
|
|
12
|
+
| **Minimum set** | Minimise total cost subject to meeting targets | Tight budgets; known targets (30×30) |
|
|
13
|
+
| **Maximum coverage** | Maximise features protected subject to budget | Fixed budget; want to maximise benefit |
|
|
14
|
+
| **Maximum utility** | Maximise weighted feature benefit | Prioritising high-value features |
|
|
15
|
+
| **Phylogenetic diversity** | Maximise phylogenetic diversity protected | Biodiversity triage |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Minimum Set Problem — Core Structure
|
|
20
|
+
|
|
21
|
+
```r
|
|
22
|
+
# Usage: source this block or call from run_prioritization.R
|
|
23
|
+
suppressPackageStartupMessages(library(prioritizr))
|
|
24
|
+
suppressPackageStartupMessages(library(terra))
|
|
25
|
+
suppressPackageStartupMessages(library(sf))
|
|
26
|
+
|
|
27
|
+
# Inputs:
|
|
28
|
+
# pu_raster — SpatRaster, planning units (cell = one PU)
|
|
29
|
+
# Values = cost; NA = excluded from analysis
|
|
30
|
+
# features — SpatRaster, one layer per biodiversity feature
|
|
31
|
+
# Values = amount of feature in each PU (0–1 suitability or area)
|
|
32
|
+
# targets — numeric vector, length = n_features, proportion to protect
|
|
33
|
+
# locked_in — SpatRaster, 1 = must be selected (existing PAs)
|
|
34
|
+
# locked_out — SpatRaster, 1 = must not be selected (developed areas)
|
|
35
|
+
|
|
36
|
+
build_problem <- function(pu_raster, features, targets,
|
|
37
|
+
locked_in = NULL, locked_out = NULL,
|
|
38
|
+
blm = 0) {
|
|
39
|
+
p <- problem(pu_raster, features) %>%
|
|
40
|
+
add_min_set_objective() %>%
|
|
41
|
+
add_relative_targets(targets) %>%
|
|
42
|
+
add_binary_decisions() %>%
|
|
43
|
+
add_default_solver(gap = 0.01, time_limit = 600, verbose = FALSE)
|
|
44
|
+
|
|
45
|
+
if (!is.null(locked_in)) {
|
|
46
|
+
p <- p %>% add_locked_in_constraints(locked_in)
|
|
47
|
+
}
|
|
48
|
+
if (!is.null(locked_out)) {
|
|
49
|
+
p <- p %>% add_locked_out_constraints(locked_out)
|
|
50
|
+
}
|
|
51
|
+
if (blm > 0) {
|
|
52
|
+
p <- p %>% add_boundary_penalties(penalty = blm, data = NULL)
|
|
53
|
+
}
|
|
54
|
+
p
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Setting Representation Targets
|
|
61
|
+
|
|
62
|
+
| Target basis | Example value | Recommended for |
|
|
63
|
+
|-------------|-------------|-----------------|
|
|
64
|
+
| Fixed proportion | 0.30 (30% of range) | 30×30 policy, simple analyses |
|
|
65
|
+
| IUCN-based rule | Declining spp → 0.50; stable → 0.25 | Threat-based targets |
|
|
66
|
+
| Gap analysis | 1 − (current protected / total range) | Sites already partially protected |
|
|
67
|
+
| Area-based | Minimum area to maintain MVP | Species with known minimum area |
|
|
68
|
+
|
|
69
|
+
```r
|
|
70
|
+
# IUCN-based target function
|
|
71
|
+
set_iucn_targets <- function(species_df) {
|
|
72
|
+
# species_df: columns 'species', 'iucn_category', 'protected_fraction'
|
|
73
|
+
targets <- ifelse(species_df$iucn_category %in% c("CR", "EN"), 0.60,
|
|
74
|
+
ifelse(species_df$iucn_category == "VU", 0.50,
|
|
75
|
+
ifelse(species_df$iucn_category == "NT", 0.35,
|
|
76
|
+
0.25)))
|
|
77
|
+
# Reduce by already protected fraction (gap analysis)
|
|
78
|
+
gap_targets <- pmax(0, targets - species_df$protected_fraction)
|
|
79
|
+
gap_targets
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Boundary Length Modifier (BLM) Calibration
|
|
86
|
+
|
|
87
|
+
BLM controls the compactness of the selected solution:
|
|
88
|
+
- BLM = 0: ignores spatial compactness (fragmented solution)
|
|
89
|
+
- Large BLM: highly compact, may sacrifice feature representation
|
|
90
|
+
|
|
91
|
+
```r
|
|
92
|
+
# BLM calibration: evaluate cost-compactness tradeoff
|
|
93
|
+
blm_values <- c(0, 0.001, 0.01, 0.1, 1, 10)
|
|
94
|
+
|
|
95
|
+
blm_results <- lapply(blm_values, function(blm) {
|
|
96
|
+
p <- build_problem(pu, features, targets, locked_in, blm = blm)
|
|
97
|
+
s <- solve(p)
|
|
98
|
+
list(
|
|
99
|
+
blm = blm,
|
|
100
|
+
total_cost = eval_cost_summary(p, s)$cost,
|
|
101
|
+
total_boundary = eval_boundary_summary(p, s)$boundary,
|
|
102
|
+
n_pu_selected = sum(values(s), na.rm = TRUE)
|
|
103
|
+
)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
blm_df <- dplyr::bind_rows(blm_results)
|
|
107
|
+
# Plot: total cost vs boundary length — choose elbow point
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Rule:** Select BLM at the elbow of the cost–boundary tradeoff curve. Above the elbow, additional boundary reduction costs disproportionately more.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Solvers
|
|
115
|
+
|
|
116
|
+
| Solver | R package | License | Recommended for |
|
|
117
|
+
|--------|----------|---------|----------------|
|
|
118
|
+
| **HiGHS** | `highs` | MIT (free) | Default for new analyses |
|
|
119
|
+
| Gurobi | `gurobi` | Commercial | Large problems, fastest |
|
|
120
|
+
| CPLEX | — | Commercial | Enterprise use |
|
|
121
|
+
| lpsymphony | `lpsymphony` | Free | Fallback if HiGHS unavailable |
|
|
122
|
+
| Rsymphony | `Rsymphony` | Free | Small problems |
|
|
123
|
+
|
|
124
|
+
```r
|
|
125
|
+
# Use HiGHS (free, recommended)
|
|
126
|
+
p <- p %>%
|
|
127
|
+
add_highs_solver(gap = 0.01, time_limit = 600, verbose = FALSE)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Evaluating Solution Performance
|
|
133
|
+
|
|
134
|
+
```r
|
|
135
|
+
# After solving
|
|
136
|
+
s <- solve(p)
|
|
137
|
+
|
|
138
|
+
# Feature representation
|
|
139
|
+
rep_summary <- eval_feature_representation_summary(p, s)
|
|
140
|
+
print(rep_summary)
|
|
141
|
+
# Columns: feature, total_amount, absolute_held, relative_held
|
|
142
|
+
|
|
143
|
+
# Targets met?
|
|
144
|
+
targets_met <- rep_summary$relative_held >= targets
|
|
145
|
+
cat(sprintf("Targets met: %d / %d features\n",
|
|
146
|
+
sum(targets_met), length(targets_met)))
|
|
147
|
+
|
|
148
|
+
# Cost summary
|
|
149
|
+
cost_df <- eval_cost_summary(p, s)
|
|
150
|
+
cat(sprintf("Total cost: %g\n", cost_df$cost))
|
|
151
|
+
|
|
152
|
+
# Number of PUs selected
|
|
153
|
+
n_pu <- sum(values(s), na.rm = TRUE)
|
|
154
|
+
cat(sprintf("PUs selected: %d / %d\n", n_pu, ncell(s[!is.na(s)])))
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Irreplaceability (Rarity-Weighted Richness)
|
|
160
|
+
|
|
161
|
+
```r
|
|
162
|
+
# Compute portfolio irreplaceability via feature rarity weighting
|
|
163
|
+
irr <- eval_rare_richness_importance(p, s)
|
|
164
|
+
writeRaster(irr, "outputs/prioritization/irreplaceability.tif", overwrite = TRUE)
|
|
165
|
+
|
|
166
|
+
# High-irreplaceability PUs not in solution = overlooked priorities
|
|
167
|
+
high_irr <- irr >= quantile(values(irr), 0.80, na.rm = TRUE)
|
|
168
|
+
high_irr_not_selected <- high_irr & (s == 0)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Pitfalls
|
|
174
|
+
|
|
175
|
+
- **Feature layers with different spatial extents:** All feature and cost rasters must have identical extent, resolution, and CRS. Reproject and resample to a common grid before analysis.
|
|
176
|
+
- **Targets set to 1.0 (100%):** A target of 1.0 requires protecting all PUs with any amount of the feature — often infeasible. Use 0.9 maximum unless justified.
|
|
177
|
+
- **Ignoring existing PAs:** Not locking in existing protected areas means the solver may exclude them and replace with cheaper PUs. Always lock in existing PAs.
|
|
178
|
+
- **Cost = area:** Equal-area PUs with cost = 1 creates minimum-set problems but maximises area, not biodiversity per cost unit. Use real cost data (land value, opportunity cost) where available.
|
|
179
|
+
- **BLM = 0 in fragmented landscapes:** Without boundary penalty, solutions are often highly fragmented and impractical. Always test with at least one non-zero BLM value.
|
|
180
|
+
- **Ignoring connectivity in feature layers:** Using species presence/absence rather than SDM suitability as features may overrepresent common, widespread species.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## References
|
|
185
|
+
|
|
186
|
+
- Hanson, J.O. et al. (2024). prioritizr: Systematic conservation prioritization in R. *Methods in Ecology and Evolution*, 15(8), 1337–1344. DOI: 10.1111/2041-210X.14376
|
|
187
|
+
- Marxan Conservation Solutions (2020). Marxan User Manual v2.43.
|
|
188
|
+
- Wilson, K.A. et al. (2009). Conserving biodiversity efficiently: what to do, where, and when. *PLOS Biology*, 7(9), e1000175. DOI: 10.1371/journal.pbio.1000175
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
resource_id: representation-targets-guide
|
|
3
|
+
skill_id: spatial-prioritization
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Representation Targets Guide
|
|
7
|
+
|
|
8
|
+
## What Are Representation Targets?
|
|
9
|
+
|
|
10
|
+
Representation targets define the minimum amount of each biodiversity feature that must be included in the conservation solution. They operationalise policy commitments (30×30) and species-level conservation requirements into quantitative thresholds for ILP formulation.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Target Types in prioritizr
|
|
15
|
+
|
|
16
|
+
| Target type | Function | Input format | Example |
|
|
17
|
+
|-------------|---------|--------------|---------|
|
|
18
|
+
| Relative | `add_relative_targets()` | Proportion of total feature amount | 0.30 = protect 30% of each feature |
|
|
19
|
+
| Absolute | `add_absolute_targets()` | Raw units (km², individuals, occurrences) | 500 km² of suitable habitat |
|
|
20
|
+
| Loglinear | `add_loglinear_targets()` | Curve from lower to upper bound | Small-range spp → higher targets |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 30×30 Target Implementation
|
|
25
|
+
|
|
26
|
+
```r
|
|
27
|
+
suppressPackageStartupMessages(library(prioritizr))
|
|
28
|
+
|
|
29
|
+
# Simple: 30% of each feature
|
|
30
|
+
p_30x30 <- p %>%
|
|
31
|
+
add_relative_targets(0.30)
|
|
32
|
+
|
|
33
|
+
# Refined: 30% of terrestrial features, 30% of marine features
|
|
34
|
+
# Apply different targets per feature group
|
|
35
|
+
n_terrestrial <- 45
|
|
36
|
+
n_marine <- 20
|
|
37
|
+
targets_vec <- c(rep(0.30, n_terrestrial), rep(0.30, n_marine))
|
|
38
|
+
p_30x30_v2 <- p %>%
|
|
39
|
+
add_relative_targets(targets_vec)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Note:** 30×30 refers to 30% of area protected by 2030. The ILP target of 0.30 for each feature is not equivalent to 30% of area — the solution may protect more or less than 30% of area depending on feature distribution.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## IUCN-Based Targets (Gap Analysis)
|
|
47
|
+
|
|
48
|
+
```r
|
|
49
|
+
compute_iucn_targets <- function(species_df, features, existing_pa_raster) {
|
|
50
|
+
# species_df: columns species, iucn_category, total_range_km2
|
|
51
|
+
# features: SpatRaster with one layer per species
|
|
52
|
+
# existing_pa_raster: 1 = protected, 0 = not
|
|
53
|
+
|
|
54
|
+
n <- nrow(species_df)
|
|
55
|
+
targets <- numeric(n)
|
|
56
|
+
|
|
57
|
+
for (i in seq_len(n)) {
|
|
58
|
+
cat_i <- species_df$iucn_category[i]
|
|
59
|
+
# Raw targets by IUCN category (based on Jenkins et al. 2015)
|
|
60
|
+
raw_target <- switch(cat_i,
|
|
61
|
+
CR = 0.60,
|
|
62
|
+
EN = 0.50,
|
|
63
|
+
VU = 0.40,
|
|
64
|
+
NT = 0.30,
|
|
65
|
+
0.17 # LC default (Aichi Target 11)
|
|
66
|
+
)
|
|
67
|
+
# Gap analysis: subtract already protected fraction
|
|
68
|
+
feat_layer <- features[[i]]
|
|
69
|
+
total_amt <- global(feat_layer, "sum", na.rm = TRUE)[[1]]
|
|
70
|
+
pa_amt <- global(feat_layer * existing_pa_raster, "sum", na.rm = TRUE)[[1]]
|
|
71
|
+
pct_protected <- pa_amt / max(total_amt, 1e-9)
|
|
72
|
+
gap_target <- max(0, raw_target - pct_protected)
|
|
73
|
+
targets[i] <- gap_target
|
|
74
|
+
}
|
|
75
|
+
targets
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Log-Linear Targets for Range-Size-Based Scaling
|
|
82
|
+
|
|
83
|
+
Large-range species require smaller proportional targets than small-range species (Rodrigues et al. 2004):
|
|
84
|
+
|
|
85
|
+
```r
|
|
86
|
+
# Log-linear target function
|
|
87
|
+
# Lower target for widespread, upper target for rare species
|
|
88
|
+
loglinear_targets <- function(range_km2,
|
|
89
|
+
lower_threshold_km2 = 1000,
|
|
90
|
+
upper_threshold_km2 = 250000,
|
|
91
|
+
lower_target = 0.10,
|
|
92
|
+
upper_target = 1.00) {
|
|
93
|
+
targets <- ifelse(range_km2 < lower_threshold_km2,
|
|
94
|
+
upper_target,
|
|
95
|
+
ifelse(range_km2 > upper_threshold_km2,
|
|
96
|
+
lower_target,
|
|
97
|
+
upper_target + (lower_target - upper_target) *
|
|
98
|
+
(log(range_km2) - log(lower_threshold_km2)) /
|
|
99
|
+
(log(upper_threshold_km2) - log(lower_threshold_km2))
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
targets
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# Example
|
|
106
|
+
species_ranges <- c(100, 1000, 50000, 500000) # km²
|
|
107
|
+
targets <- loglinear_targets(species_ranges)
|
|
108
|
+
cat(data.frame(range_km2 = species_ranges, target = round(targets, 2)))
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
| Range (km²) | Target |
|
|
112
|
+
|-------------|--------|
|
|
113
|
+
| 100 | 1.00 (100%) |
|
|
114
|
+
| 1,000 | 1.00 (threshold) |
|
|
115
|
+
| 50,000 | 0.62 |
|
|
116
|
+
| 500,000 | 0.10 |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Feature Weights (Prioritising Threatened Species)
|
|
121
|
+
|
|
122
|
+
When not all features are equally important, apply weights:
|
|
123
|
+
|
|
124
|
+
```r
|
|
125
|
+
# Weight by IUCN category
|
|
126
|
+
weights_vec <- case_when(
|
|
127
|
+
species_df$iucn_category == "CR" ~ 4,
|
|
128
|
+
species_df$iucn_category == "EN" ~ 3,
|
|
129
|
+
species_df$iucn_category == "VU" ~ 2,
|
|
130
|
+
species_df$iucn_category == "NT" ~ 1.5,
|
|
131
|
+
TRUE ~ 1
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Apply in maximum coverage problem
|
|
135
|
+
p_weighted <- problem(pu, features) %>%
|
|
136
|
+
add_max_features_objective(budget = total_budget) %>%
|
|
137
|
+
add_absolute_targets(1e-6) %>% # minimum feasibility
|
|
138
|
+
add_feature_weights(weights_vec) %>%
|
|
139
|
+
add_binary_decisions() %>%
|
|
140
|
+
add_highs_solver(gap = 0.01)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Target Shortfalls and Cost-Benefit Curves
|
|
146
|
+
|
|
147
|
+
When targets cannot be fully met within budget:
|
|
148
|
+
|
|
149
|
+
```r
|
|
150
|
+
# Evaluate target shortfalls after solving
|
|
151
|
+
rep_summary <- eval_feature_representation_summary(p, s)
|
|
152
|
+
shortfall_df <- rep_summary %>%
|
|
153
|
+
mutate(target = targets_vec,
|
|
154
|
+
shortfall = pmax(0, target - relative_held),
|
|
155
|
+
pct_shortfall = shortfall / target * 100) %>%
|
|
156
|
+
arrange(desc(shortfall))
|
|
157
|
+
|
|
158
|
+
# Cost-effectiveness curve: cost vs % of targets met
|
|
159
|
+
budgets <- seq(0.2, 1.0, by = 0.1) * total_budget
|
|
160
|
+
ce_results <- lapply(budgets, function(b) {
|
|
161
|
+
p_b <- p %>% add_max_features_objective(budget = b)
|
|
162
|
+
s_b <- solve(p_b)
|
|
163
|
+
rep_b <- eval_feature_representation_summary(p_b, s_b)
|
|
164
|
+
data.frame(budget = b,
|
|
165
|
+
pct_targets_met = mean(rep_b$relative_held >= targets_vec) * 100)
|
|
166
|
+
})
|
|
167
|
+
ce_df <- dplyr::bind_rows(ce_results)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Pitfalls
|
|
173
|
+
|
|
174
|
+
- **Relative targets applied to features with zero total:** If a feature has total_amount = 0 (no occurrence in study area), any relative target is infeasible. Filter out zero-occurrence features before analysis.
|
|
175
|
+
- **Targets exceeding currently achievable area:** If 80% of a species' range is already developed, a target of 0.60 may be infeasible. Check feasibility before optimisation.
|
|
176
|
+
- **Equal targets for all species regardless of area or threat:** This treats a critically endangered microendemic the same as a common widespread species. Always use IUCN or range-based targets.
|
|
177
|
+
- **Forgetting to account for feature detectability:** SDM-based features represent potential habitat, not confirmed presence. Over-targeting poorly surveyed species inflates solution cost without confirmed benefit.
|
|
178
|
+
- **Targets ignore quality:** A target of 30% met by degraded habitat may not achieve conservation objectives. Consider weighting feature layers by habitat quality before setting targets.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## References
|
|
183
|
+
|
|
184
|
+
- Rodrigues, A.S.L. et al. (2004). Effectiveness of the global protected area network in representing species diversity. *Nature*, 428, 640–643. DOI: 10.1038/nature02422
|
|
185
|
+
- Jenkins, C.N. et al. (2015). Global patterns of terrestrial vertebrate diversity and conservation. *PNAS*, 112(18), 5667–5672. DOI: 10.1073/pnas.1302251112
|
|
186
|
+
- CBD (2022). *Kunming-Montreal Global Biodiversity Framework*. Convention on Biological Diversity, COP15.
|