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.
Files changed (217) hide show
  1. package/AGENT_CONTEXT.md +191 -0
  2. package/CATALOG.md +329 -0
  3. package/LICENSE +692 -0
  4. package/README.md +347 -0
  5. package/bin/install.mjs +168 -0
  6. package/docs/comparison-with-alternatives.md +38 -0
  7. package/docs/global-examples-index.md +103 -0
  8. package/docs/repository-statistics.md +101 -0
  9. package/docs/theoretical-foundations.md +188 -0
  10. package/environment.yaml +106 -0
  11. package/examples/community/arctic_tundra_vegetation_example.md +247 -0
  12. package/examples/community/bird_landuse_example.md +63 -0
  13. package/examples/community/phytoplankton_reservoir_example.md +60 -0
  14. package/examples/community/reef_fish_indopacific_example.md +221 -0
  15. package/examples/impact/baci_road_example.md +57 -0
  16. package/examples/impact/ecosystem_services_atlantic_forest.md +83 -0
  17. package/examples/impact/forest_loss_borneo_timeseries_example.md +225 -0
  18. package/examples/occupancy/puma_camera_example.md +61 -0
  19. package/examples/occupancy/snow_leopard_himalayas_example.md +204 -0
  20. package/examples/reproducible/whittaker_biome_sdm_example.md +406 -0
  21. package/examples/sdm/anteater_cerrado_example.md +69 -0
  22. package/examples/sdm/jaguar_amazon_example.md +80 -0
  23. package/examples/sdm/koala_climate_change_example.md +170 -0
  24. package/examples/sdm/wolf_recolonization_europe_example.md +193 -0
  25. package/package.json +43 -0
  26. package/renv.lock +194 -0
  27. package/skills/SKILL_INDEX.json +1020 -0
  28. package/skills/acoustic-monitoring/SKILL.md +163 -0
  29. package/skills/acoustic-monitoring/examples/example-prompts.md +100 -0
  30. package/skills/acoustic-monitoring/examples/temperate_forest_birds_example.md +285 -0
  31. package/skills/acoustic-monitoring/resources/acoustic-indices-reference.md +93 -0
  32. package/skills/acoustic-monitoring/resources/soundscape-ecology-guide.md +90 -0
  33. package/skills/acoustic-monitoring/resources/species-id-tools-comparison.md +89 -0
  34. package/skills/acoustic-monitoring/scripts/batch_species_detection.py +360 -0
  35. package/skills/acoustic-monitoring/scripts/compute_acoustic_indices.R +235 -0
  36. package/skills/acoustic-monitoring/scripts/compute_acoustic_indices.py +374 -0
  37. package/skills/biostatistics-workbench/SKILL.md +140 -0
  38. package/skills/biostatistics-workbench/examples/example-prompts.md +39 -0
  39. package/skills/biostatistics-workbench/resources/effect-size-reference.md +81 -0
  40. package/skills/biostatistics-workbench/resources/glm-family-link-reference.md +47 -0
  41. package/skills/biostatistics-workbench/resources/test-selection-guide.md +93 -0
  42. package/skills/biostatistics-workbench/scripts/glm_pipeline.R +78 -0
  43. package/skills/biostatistics-workbench/scripts/glm_pipeline.py +210 -0
  44. package/skills/camera-trap-processing/SKILL.md +159 -0
  45. package/skills/camera-trap-processing/examples/example-prompts.md +103 -0
  46. package/skills/camera-trap-processing/examples/leopard_serengeti_example.md +231 -0
  47. package/skills/camera-trap-processing/resources/activity-patterns-reference.md +113 -0
  48. package/skills/camera-trap-processing/resources/camtrapR-workflow-guide.md +130 -0
  49. package/skills/camera-trap-processing/resources/detection-event-definition-guide.md +89 -0
  50. package/skills/camera-trap-processing/scripts/estimate_activity.R +169 -0
  51. package/skills/camera-trap-processing/scripts/process_camtrap_data.R +179 -0
  52. package/skills/camera-trap-processing/scripts/process_camtrap_data.py +192 -0
  53. package/skills/community-ecology-ordination/SKILL.md +133 -0
  54. package/skills/community-ecology-ordination/examples/example-prompts.md +35 -0
  55. package/skills/community-ecology-ordination/resources/dissimilarity-metric-guide.md +53 -0
  56. package/skills/community-ecology-ordination/resources/nmds-interpretation-guide.md +104 -0
  57. package/skills/community-ecology-ordination/scripts/__pycache__/community_analysis.cpython-311.pyc +0 -0
  58. package/skills/community-ecology-ordination/scripts/community_analysis.R +143 -0
  59. package/skills/community-ecology-ordination/scripts/community_analysis.py +231 -0
  60. package/skills/ecological-data-foundation/SKILL.md +129 -0
  61. package/skills/ecological-data-foundation/examples/example-prompts.md +40 -0
  62. package/skills/ecological-data-foundation/resources/coordinate-cleaning-flags.md +66 -0
  63. package/skills/ecological-data-foundation/resources/darwin-core-glossary.md +91 -0
  64. package/skills/ecological-data-foundation/resources/data-citation-guide.md +265 -0
  65. package/skills/ecological-data-foundation/resources/gbif-data-citation-guide.md +193 -0
  66. package/skills/ecological-data-foundation/resources/qa-checklist.md +83 -0
  67. package/skills/ecological-data-foundation/scripts/__pycache__/clean_occurrences.cpython-311.pyc +0 -0
  68. package/skills/ecological-data-foundation/scripts/__pycache__/download_from_ebird.cpython-311.pyc +0 -0
  69. package/skills/ecological-data-foundation/scripts/__pycache__/download_from_inat.cpython-311.pyc +0 -0
  70. package/skills/ecological-data-foundation/scripts/__pycache__/download_from_iucn.cpython-311.pyc +0 -0
  71. package/skills/ecological-data-foundation/scripts/__pycache__/download_from_obis.cpython-311.pyc +0 -0
  72. package/skills/ecological-data-foundation/scripts/clean_occurrences.R +230 -0
  73. package/skills/ecological-data-foundation/scripts/clean_occurrences.py +268 -0
  74. package/skills/ecological-data-foundation/scripts/download_from_ebird.R +251 -0
  75. package/skills/ecological-data-foundation/scripts/download_from_ebird.py +364 -0
  76. package/skills/ecological-data-foundation/scripts/download_from_gbif.R +315 -0
  77. package/skills/ecological-data-foundation/scripts/download_from_gbif.py +407 -0
  78. package/skills/ecological-data-foundation/scripts/download_from_inat.R +238 -0
  79. package/skills/ecological-data-foundation/scripts/download_from_inat.py +304 -0
  80. package/skills/ecological-data-foundation/scripts/download_from_iucn.R +273 -0
  81. package/skills/ecological-data-foundation/scripts/download_from_iucn.py +344 -0
  82. package/skills/ecological-data-foundation/scripts/download_from_obis.R +248 -0
  83. package/skills/ecological-data-foundation/scripts/download_from_obis.py +318 -0
  84. package/skills/ecological-impact-assessment/SKILL.md +123 -0
  85. package/skills/ecological-impact-assessment/examples/example-prompts.md +32 -0
  86. package/skills/ecological-impact-assessment/resources/baci-design-guide.md +55 -0
  87. package/skills/ecological-impact-assessment/resources/fragmentation-metrics-reference.md +86 -0
  88. package/skills/ecological-impact-assessment/resources/pressure-index-template.md +78 -0
  89. package/skills/ecological-impact-assessment/resources/study-design-guide.md +168 -0
  90. package/skills/ecological-impact-assessment/scripts/baci_analysis.R +161 -0
  91. package/skills/ecological-impact-assessment/scripts/fragmentation_analysis.py +141 -0
  92. package/skills/ecological-impact-assessment/scripts/power_analysis_baci.R +274 -0
  93. package/skills/ecosystem-services-assessment/SKILL.md +125 -0
  94. package/skills/ecosystem-services-assessment/examples/example-prompts.md +24 -0
  95. package/skills/ecosystem-services-assessment/resources/es-indicator-reference.md +45 -0
  96. package/skills/ecosystem-services-assessment/resources/invest-parameter-guide.md +86 -0
  97. package/skills/ecosystem-services-assessment/resources/rusle-coefficients.md +88 -0
  98. package/skills/ecosystem-services-assessment/scripts/__pycache__/compute_es.cpython-311.pyc +0 -0
  99. package/skills/ecosystem-services-assessment/scripts/compute_es.py +189 -0
  100. package/skills/ecosystem-services-assessment/scripts/tradeoff_analysis.R +161 -0
  101. package/skills/environmental-time-series/SKILL.md +125 -0
  102. package/skills/environmental-time-series/examples/example-prompts.md +33 -0
  103. package/skills/environmental-time-series/resources/anomaly-indices-reference.md +88 -0
  104. package/skills/environmental-time-series/resources/bfast-parameter-guide.md +69 -0
  105. package/skills/environmental-time-series/scripts/__pycache__/recovery_trajectory.cpython-311.pyc +0 -0
  106. package/skills/environmental-time-series/scripts/__pycache__/trend_analysis.cpython-311.pyc +0 -0
  107. package/skills/environmental-time-series/scripts/recovery_trajectory.R +305 -0
  108. package/skills/environmental-time-series/scripts/recovery_trajectory.py +178 -0
  109. package/skills/environmental-time-series/scripts/trend_analysis.R +192 -0
  110. package/skills/environmental-time-series/scripts/trend_analysis.py +184 -0
  111. package/skills/geoprocessing-for-ecology/SKILL.md +123 -0
  112. package/skills/geoprocessing-for-ecology/examples/example-prompts.md +32 -0
  113. package/skills/geoprocessing-for-ecology/resources/crs-reference.md +62 -0
  114. package/skills/geoprocessing-for-ecology/resources/global-predictor-sources.md +331 -0
  115. package/skills/geoprocessing-for-ecology/resources/resampling-methods.md +57 -0
  116. package/skills/geoprocessing-for-ecology/scripts/__pycache__/download_predictors.cpython-311.pyc +0 -0
  117. package/skills/geoprocessing-for-ecology/scripts/download_predictors.R +239 -0
  118. package/skills/geoprocessing-for-ecology/scripts/download_predictors.py +379 -0
  119. package/skills/geoprocessing-for-ecology/scripts/stack_and_extract.R +224 -0
  120. package/skills/geoprocessing-for-ecology/scripts/stack_and_extract.py +172 -0
  121. package/skills/landscape-connectivity/SKILL.md +170 -0
  122. package/skills/landscape-connectivity/examples/example-prompts.md +96 -0
  123. package/skills/landscape-connectivity/examples/jaguar_mesoamerica_corridor_example.md +271 -0
  124. package/skills/landscape-connectivity/resources/circuitscape-parameter-guide.md +155 -0
  125. package/skills/landscape-connectivity/resources/graph-theory-for-ecology.md +134 -0
  126. package/skills/landscape-connectivity/resources/resistance-surface-guide.md +141 -0
  127. package/skills/landscape-connectivity/scripts/connectivity_analysis.py +387 -0
  128. package/skills/landscape-connectivity/scripts/connectivity_metrics.R +274 -0
  129. package/skills/landscape-connectivity/scripts/resistance_surface.R +239 -0
  130. package/skills/model-validation-and-uncertainty/SKILL.md +131 -0
  131. package/skills/model-validation-and-uncertainty/examples/example-prompts.md +30 -0
  132. package/skills/model-validation-and-uncertainty/resources/extrapolation-risk-guide.md +236 -0
  133. package/skills/model-validation-and-uncertainty/resources/metric-selection-guide.md +52 -0
  134. package/skills/model-validation-and-uncertainty/resources/threshold-selection-guide.md +64 -0
  135. package/skills/model-validation-and-uncertainty/scripts/__pycache__/validate_model.cpython-311.pyc +0 -0
  136. package/skills/model-validation-and-uncertainty/scripts/extrapolation_risk.R +315 -0
  137. package/skills/model-validation-and-uncertainty/scripts/validate_model.py +226 -0
  138. package/skills/model-validation-and-uncertainty/scripts/validate_sdm.R +162 -0
  139. package/skills/occupancy-and-detection/SKILL.md +126 -0
  140. package/skills/occupancy-and-detection/examples/example-prompts.md +33 -0
  141. package/skills/occupancy-and-detection/resources/detection-history-format.md +100 -0
  142. package/skills/occupancy-and-detection/resources/occupancy-study-design.md +47 -0
  143. package/skills/occupancy-and-detection/scripts/__pycache__/occupancy_analysis.cpython-311.pyc +0 -0
  144. package/skills/occupancy-and-detection/scripts/occupancy_analysis.R +160 -0
  145. package/skills/occupancy-and-detection/scripts/occupancy_analysis.py +159 -0
  146. package/skills/population-viability-analysis/SKILL.md +161 -0
  147. package/skills/population-viability-analysis/examples/african_elephant_pva_example.md +266 -0
  148. package/skills/population-viability-analysis/examples/example-prompts.md +95 -0
  149. package/skills/population-viability-analysis/resources/extinction-risk-thresholds.md +128 -0
  150. package/skills/population-viability-analysis/resources/matrix-model-guide.md +139 -0
  151. package/skills/population-viability-analysis/resources/sensitivity-elasticity-reference.md +182 -0
  152. package/skills/population-viability-analysis/scripts/matrix_pva.R +258 -0
  153. package/skills/population-viability-analysis/scripts/pva_analysis.py +442 -0
  154. package/skills/population-viability-analysis/scripts/stochastic_pva.R +353 -0
  155. package/skills/predictive-modeling-best-practices/SKILL.md +136 -0
  156. package/skills/predictive-modeling-best-practices/examples/example-prompts.md +58 -0
  157. package/skills/predictive-modeling-best-practices/resources/collinearity-decision-tree.md +65 -0
  158. package/skills/predictive-modeling-best-practices/resources/sampling-bias-correction.md +267 -0
  159. package/skills/predictive-modeling-best-practices/resources/spatial-cv-guide.md +73 -0
  160. package/skills/predictive-modeling-best-practices/scripts/__pycache__/spatial_cv.cpython-311.pyc +0 -0
  161. package/skills/predictive-modeling-best-practices/scripts/collinearity_check.R +112 -0
  162. package/skills/predictive-modeling-best-practices/scripts/spatial_cv.py +182 -0
  163. package/skills/reproducible-ecology-pipeline/SKILL.md +139 -0
  164. package/skills/reproducible-ecology-pipeline/examples/example-prompts.md +35 -0
  165. package/skills/reproducible-ecology-pipeline/resources/directory-structure-template.md +94 -0
  166. package/skills/reproducible-ecology-pipeline/resources/params-yaml-template.yaml +84 -0
  167. package/skills/reproducible-ecology-pipeline/resources/reproducibility-checklist-template.md +66 -0
  168. package/skills/reproducible-ecology-pipeline/scripts/generate_file_manifest.py +110 -0
  169. package/skills/reproducible-ecology-pipeline/scripts/init_project.sh +53 -0
  170. package/skills/spatial-prioritization/SKILL.md +162 -0
  171. package/skills/spatial-prioritization/examples/biodiversity_hotspot_prioritization_example.md +289 -0
  172. package/skills/spatial-prioritization/examples/example-prompts.md +93 -0
  173. package/skills/spatial-prioritization/resources/cost-surface-reference.md +130 -0
  174. package/skills/spatial-prioritization/resources/marxan-vs-prioritizr-comparison.md +125 -0
  175. package/skills/spatial-prioritization/resources/prioritizr-formulation-guide.md +188 -0
  176. package/skills/spatial-prioritization/resources/representation-targets-guide.md +186 -0
  177. package/skills/spatial-prioritization/scripts/prioritization_sensitivity.R +320 -0
  178. package/skills/spatial-prioritization/scripts/run_prioritization.R +336 -0
  179. package/skills/species-distribution-modeling/SKILL.md +139 -0
  180. package/skills/species-distribution-modeling/examples/example-prompts.md +36 -0
  181. package/skills/species-distribution-modeling/resources/algorithm-comparison.md +25 -0
  182. package/skills/species-distribution-modeling/resources/calibration-area-guide.md +71 -0
  183. package/skills/species-distribution-modeling/resources/climate-scenario-preparation.md +170 -0
  184. package/skills/species-distribution-modeling/resources/maxent-calibration-guide.md +211 -0
  185. package/skills/species-distribution-modeling/resources/sdm-checklist.md +37 -0
  186. package/skills/species-distribution-modeling/scripts/predict_distribution.R +236 -0
  187. package/skills/species-distribution-modeling/scripts/predict_distribution.py +286 -0
  188. package/skills/species-distribution-modeling/scripts/prepare_future_layers.R +351 -0
  189. package/skills/species-distribution-modeling/scripts/project_scenarios.R +220 -0
  190. package/skills/species-distribution-modeling/scripts/run_ensemble_sdm.R +99 -0
  191. package/skills/species-distribution-modeling/scripts/sdm_pipeline.py +318 -0
  192. package/skills/species-distribution-modeling/scripts/tune_maxnet.R +344 -0
  193. package/templates/SKILL_TEMPLATE.md +225 -0
  194. package/templates/checklists/data-submission-checklist.md +38 -0
  195. package/templates/checklists/post-analysis-checklist.md +55 -0
  196. package/templates/checklists/pre-analysis-checklist.md +31 -0
  197. package/templates/prompts/debug-skill.md +47 -0
  198. package/templates/prompts/invoke-skill.md +34 -0
  199. package/templates/prompts/invoke-workflow.md +45 -0
  200. package/templates/reports/technical-report-template.md +80 -0
  201. package/templates/scripts/logger_setup.R +79 -0
  202. package/templates/scripts/logger_setup.py +119 -0
  203. package/templates/scripts/params_loader.R +28 -0
  204. package/templates/scripts/params_loader.py +38 -0
  205. package/workflows/analyze-community-structure/WORKFLOW.md +72 -0
  206. package/workflows/analyze-environmental-change/WORKFLOW.md +73 -0
  207. package/workflows/assess-ecological-impact/WORKFLOW.md +75 -0
  208. package/workflows/assess-ecosystem-services/WORKFLOW.md +68 -0
  209. package/workflows/assess-landscape-connectivity/WORKFLOW.md +84 -0
  210. package/workflows/build-fire-risk-map/WORKFLOW.md +79 -0
  211. package/workflows/produce-technical-report/WORKFLOW.md +113 -0
  212. package/workflows/run-camera-trap-occupancy/WORKFLOW.md +87 -0
  213. package/workflows/run-conservation-prioritization/WORKFLOW.md +89 -0
  214. package/workflows/run-multispecies-screening/WORKFLOW.md +197 -0
  215. package/workflows/run-occupancy-analysis/WORKFLOW.md +74 -0
  216. package/workflows/run-population-viability/WORKFLOW.md +90 -0
  217. 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.