
mappingAS — Mapping Area of Species. Geographic range metrics (EOO / AOO), land-cover conversion and fire, and protected-area overlap for extinction-risk screening — from raw occurrence points to an interactive app and a written assessment report.
mappingAS is an R package, with an accompanying
Shiny application, for screening species against
Criterion B of the IUCN Red List. Starting from a set
of occurrence points, it estimates each species’ geographic range (EOO /
AOO), measures how much of that range has been converted to anthropic
land cover and how much has burned, quantifies the overlap with
protected areas (global WDPA), and packages everything for mapping,
inspection, export and reporting. Land-cover conversion is driven by
MapBiomas across South America and by the global
Esri / Impact Observatory (Sentinel-2) 10 m land cover
elsewhere, so a species anywhere on Earth can be screened with the same
workflow — no Google Earth Engine account required.
Screening only. The categories produced are provisional — they rest solely on the EOO/AOO size thresholds of Criterion B. They do not replace a formal IUCN assessment, which also requires the sub-conditions of fragmentation/few locations, continuing decline and extreme fluctuation.
| Module | What you get | Key functions |
|---|---|---|
| Occurrence import | Read points from spreadsheets or spatial files, auto-detecting the species/lon/lat columns | read_occurrences() |
| Range metrics | Extent of Occurrence (EOO, convex hull) and Area of Occupancy (AOO, 2 km grid) on an equal-area projection, with provisional Criterion B categories | assess_species(), calc_eoo(),
calc_aoo(), iucn_category_B() |
| Subpopulations & locations | Estimate of the number of subpopulations (circular-buffer method) and number of locations (10 km occupied-grid-cell method), following the ConR spatial rationale | assess_species(), calc_subpop(),
calc_locations() |
| Habitat conversion | % converted (anthropic) vs. natural within the EOO/AOO, plus the full per-class land-cover breakdown | assess_species(), class_table(),
plot_conversion() |
| Land-cover time series | Composition (% × year) as a stacked-area chart (EOO and AOO together), plus a per-class regression trendline with equation, R² and p-value | timeseries_for_species(),
cover_timeseries(), plot_timeseries(),
plot_class_trendline() |
| Fire | % of the range burned at least once and burned-area time series, from MapBiomas Fire (Brazil) | assess_species(fire = TRUE),
fire_timeseries_for_species(),
plot_fire_timeseries() |
| Protected areas | Overlap of occurrences/EOO/AOO with protected areas (global WDPA), incl. the natural-and-protected share | assess_species(protected = TRUE),
pa_table(), plot_protection(),
protected_areas() |
| Maps | Interactive Leaflet map and a publication-ready static map (points + EOO + AOO + land cover/fire) | map_species(), map_static() |
| Interactive charts | Every chart as an interactive plotly widget (hover, zoom) | mas_plotly() |
| Reporting | A written, referenced assessment report (HTML / text / Word .docx) | assessment_report() |
| Factsheet | A self-contained HTML factsheet merging the computed metrics/charts with user-supplied taxonomy, supporting information, land use, conservation units, vouchers, references and up to 4 watermarked photos | factsheet_html() |
| Export | EOO/AOO polygons as shapefile/GeoPackage and land-cover rasters (GeoTIFF) | export_ranges() |
| Interactive app | A Shiny GUI that runs the whole workflow with no code | run_app() |
# install.packages("remotes")
remotes::install_github("lucasbarreirageo/mappingAS")The core dependencies (sf, terra,
leaflet, DT, shiny,
bslib, ggplot2, plotly,
officer, readxl) are installed automatically —
including officer, so the Word report works out of the
box.
The local land-cover backend uses GDAL with
/vsicurl/ (shipped with
terra/sf), so no Google Earth Engine
account and no full-mosaic download are needed — only the
window covering each species’ range is read (and cached on disk). This
applies to both MapBiomas and the global Sentinel-2/Esri layer.
The optional Earth Engine backend needs a configured
rgee:
install.packages("rgee")
rgee::ee_install() # creates the Python environment
rgee::ee_Initialize() # authenticates with your Earth Engine accountlibrary(mappingAS)
# 1. Read points (csv / xlsx / shp) — columns are auto-detected
occ <- read_occurrences("my_occurrences.xlsx")
# 2. Run the assessment. `initiative = "auto"` picks MapBiomas for occurrences
# in South America and the global Sentinel-2/Esri layer elsewhere.
res <- assess_species(occ,
initiative = "auto", backend = "local",
mapbiomas = TRUE, # habitat conversion (default)
fire = TRUE, # burned-area metrics (Brazil)
protected = TRUE) # overlap with protected areas (WDPA)
# 3. Inspect the summary table (one row per species)
res$summary
# 4. Map and charts
map_species(res) # leaflet: points + EOO + AOO + land cover (+ fire, protected areas)
plot_conversion(res) # natural vs. converted, EOO and AOO
mas_plotly(plot_conversion(res)) # same chart, interactive
# 5. A written assessment report
cat(assessment_report(res, output = "text"))
assessment_report(res, output = "docx", file = "assessment.docx")
# 6. Export the ranges as spatial data
export_ranges(res) # mappingAS_EOO.shp + mappingAS_AOO.shp
export_ranges(res, format = "gpkg") # one GeoPackage with eoo and aoo layers
export_ranges(res, zip = TRUE) # bundled into a single .zipex <- system.file("extdata", "example_occurrences.csv", package = "mappingAS")
res <- assess_species(read_occurrences(ex), backend = "local")
reslibrary(mappingAS)
run_app()Upload a file
(.xlsx/.csv/.gpkg/.geojson
or a shapefile in a .zip), map the columns if needed,
choose the land-cover product (default
Auto), the year, the AOO cell
size, the source (local / GEE) and which
optional modules to run (fire, protected
areas), then click Assess. The app is
organised as tabs:
factsheet_html()): fill in the
taxonomy, supporting information, land use, conservation units, vouchers
and reference, add up to four (watermarked) photos, and it embeds those
alongside the computed metrics, a top anthropic activities
chart and the standard charts — a single portable .html you
can open offline or publish (e.g. on GitHub Pages).A light/dark theme toggle is available in the header.
export_ranges() writes the EOO and
AOO polygons (one feature per species by default) with
area, conversion and provisional-category attributes attached:
export_ranges(res,
dir = "output", # output directory
format = "shapefile", # or "gpkg"
what = "both", # "eoo", "aoo" or "both"
crs = 4326, # output CRS (WGS84 by default)
aoo_as = "union", # "union" (1 feature/species) or "cells"
zip = FALSE) # TRUE = bundle everything into a .zipBecause the ESRI Shapefile format limits field names
to 10 characters, the attribute table uses compact names
(species, eoo_km2/aoo_km2,
n_cells, conv_pct, nat_pct,
cat_B1/cat_B2, prov_cat,
mb_year, mb_coll). The
GeoPackage (format = "gpkg") stores both
layers (eoo, aoo) in a single file with no
field-name limit — the easiest option for QGIS/ArcGIS. By default, a
mappingAS_classes.csv with the per-class composition is
written too (class_csv = FALSE to skip).
The Shiny Map tab additionally exports the
underlying land-cover and fire GeoTIFF rasters, clipped
to the selected species’ EOO or AOO, as a .zip.
# Area and % of each land-cover class within the EOO and AOO
ct <- class_table(res) # species x range (EOO/AOO) x class
# Land-cover composition over time (stacked-area chart, official class colours)
ts <- timeseries_for_species(res, species = "sp1", range = "eoo", by = "class")
plot_timeseries(ts)
mas_plotly(plot_timeseries(ts)) # interactive
# Directly on any geometry
ts2 <- cover_timeseries(my_geometry, years = c(1990, 2000, 2010, 2020), by = "class")Each year is read separately (one GeoTIFF window per year), so an annual series across the whole record can take a while; increase the year step to speed it up. (The time series uses whichever product the species was assessed with — MapBiomas back to 1985, or Sentinel-2/Esri for 2017–2023.)
# Fire: enable during assessment, then chart the burned-area series
res <- assess_species(occ, fire = TRUE)
fts <- fire_timeseries_for_species(res, species = "sp1", range = "eoo")
plot_fire_timeseries(fts)
# Protected areas (global WDPA)
res <- assess_species(occ, protected = TRUE)
pa_table(res) # per-protected-area overlap table
plot_protection(res) # share of the range inside vs. outside protected areasWith protected = TRUE and
mapbiomas = TRUE, the summary also reports the habitat that
is both natural and inside protected areas
(effectively protected natural habitat).
Key columns (res$summary, also shown with a glossary in
the app’s Results tab):
| Column | Meaning |
|---|---|
species, n_records,
n_unique |
Species; number of records and unique coordinates |
eoo_km2 |
EOO in km² (NA if fewer than 3 unique points) |
aoo_km2, aoo_cells |
AOO in km² and number of occupied cells |
eoo_converted_pct / eoo_natural_pct |
% converted / natural within the EOO |
aoo_converted_pct / aoo_natural_pct |
% converted / natural within the AOO |
eoo_cat_B1, aoo_cat_B2,
provisional_cat |
Provisional categories (size only) |
mapbiomas_initiative, mapbiomas_year,
mapbiomas_collection |
Land-cover source used per species (a MapBiomas product, or
sentinel2 when the range fell back to the global
Esri/Sentinel-2 layer) |
eoo_burned_pct, aoo_burned_pct |
% of the EOO/AOO burned at least once (fire = TRUE) |
occ_in_uc_pct, eoo_uc_pct,
aoo_uc_pct, n_uc |
Overlap with protected areas (protected = TRUE) |
eoo_nat_uc_pct, aoo_nat_uc_pct |
Share of the range that is natural and protected |
NA), edges
densified along great circles and measured on the WGS84 ellipsoid.cell_km), taken as the minimum over several
translated grids.subpop_resol_km (default 1/10 of the
maximum inter-point distance, Rivers et
al. 2010) is drawn around each occurrence, the circles are
dissolved, and the disjoint polygons are counted.loc_km, or a sliding-scale fraction of the max
inter-point distance via loc_scale), minimum over
translated grids. When protected = TRUE, occurrences inside
protected areas are decoupled from those outside (ConR
method_protected: "no_more_than_one" counts
each protected area with occurrences as one location;
"other" grids inside/outside separately). A grid-based
screening proxy, not a formal count of locations under a specific
threat.converted_pct = anthropic / (anthropic + natural) × 100
(terrestrial denominator; water and not-observed excluded by default —
set water_in_denominator = TRUE to include water)."local" (default) — reads, over the
network, only the window of the source GeoTIFF via GDAL
/vsicurl/ (MapBiomas national mosaics, or the
Sentinel-2/Esri MGRS tiles). No Earth Engine account, no full-mosaic
download. The windowed crop is cached on disk and reused for mapping and
re-runs; map overlays use a fast decimated read."gee" — computes per-class areas
server-side on Google Earth Engine (recommended for very large,
e.g. continental, ranges). Requires rgee::ee_Initialize().
Wired for initiative = "brazil" only.assess_species() (and the whole pipeline) takes an
initiative argument so a species outside
Brazil can be screened with the same workflow — without Google
Earth Engine and without a Google Drive download. Every product
is streamed year-by-year as Cloud-Optimized GeoTIFFs from the public
MapBiomas bucket via GDAL /vsicurl/, exactly like the
Brazil backend:
initiative |
Product | Default collection | Years |
|---|---|---|---|
"brazil" (default) |
MapBiomas Brazil | 10 | 1985–2024 |
"amazonia" |
MapBiomas Amazonia / Pan-Amazon (RAISG) | 6 | 1986–2023 |
"colombia" |
MapBiomas Colombia | 3 | 1985–2024 |
"argentina" |
MapBiomas Argentina | 2 | 1985–2024 |
"bolivia" |
MapBiomas Bolivia | 3 | 1985–2024 |
"chile" |
MapBiomas Chile | 1 | 2000–2022 |
"ecuador" |
MapBiomas Ecuador | 3 | 1985–2024 |
"peru" |
MapBiomas Peru | 3 | 1985–2024 |
"venezuela" |
MapBiomas Venezuela | 2 | 1985–2023 |
"paraguay" |
MapBiomas Paraguay | 2 | 1985–2023 |
"uruguay" |
MapBiomas Uruguay | 1 | 1985–2022 |
# A species in the Peruvian Amazon, no GEE:
res_pe <- assess_species(occ, initiative = "peru")
# Anywhere in the Amazon basin (Pan-Amazon collection):
res_az <- assess_species(occ, initiative = "amazonia")year and collection default to each
initiative’s latest year and native collection.
mb_initiatives() lists the products;
mb_source_url(), mb_raster_local(),
mb_years(), mb_legend(),
summarise_conversion() and cover_timeseries()
all accept initiative.
One standardised legend. MapBiomas harmonises its
pixel codes across initiatives, so mb_legend() returns a
single standardised table (same class names, colours and
conservation groups) that labels every country’s raster consistently —
this is what lets a range spanning more than one country be assessed
coherently. The country-specific classes (Andinean formations, Glacier,
primary/secondary/dwarf forest, scrubland/steppe/fog oasis/peatlands,
Pinus/Eucalyptus plantations, salt flat, …) are included; a code absent
from a given product simply contributes zero area. MapBiomas
Fire is published for Brazil only and is skipped (with
a warning) for the other initiatives.
For a species whose range falls outside every MapBiomas
country, assess_species() can fall back to the
global Esri / Impact Observatory 10 m Annual Land Use Land
Cover product — the Sentinel-2-derived data behind the ArcGIS Living
Atlas Land Cover Explorer. It is streamed the same way as MapBiomas
(public Cloud-Optimized GeoTIFFs via GDAL /vsicurl/,
no Google Earth Engine and no account), tiled by MGRS
grid zone and read only over each range.
# Automatic: try MapBiomas, fall back to Sentinel-2 where it has no data
res <- assess_species(occ, initiative = "auto")
# Force the global Sentinel-2/Esri layer everywhere
res <- assess_species(occ, initiative = "sentinel2")
# Turn the automatic fallback off (out-of-coverage ranges return NA, as before)
res <- assess_species(occ, initiative = "brazil", fallback = "none")The automatic fallback is on by default
(fallback = "sentinel2"). The 9 Sentinel-2 classes are
mapped to the same conservation groups as MapBiomas — Trees / Rangeland
/ Flooded vegetation → natural; Crops / Built area →
anthropic (converted); Water excluded; Bare ground and Snow/Ice
excluded as ambiguous; Clouds → not observed — so the
conversion percentages, per-class tables, donut charts, maps and report
all work unchanged. The product actually used is recorded per species in
the mapbiomas_initiative column. Years available: 2017–2023
(s2_years()). Helpers: esri_legend(),
s2_source_url(), s2_raster_local().
Protected-area overlap
(assess_species(protected = TRUE)) reads the global
World Database on Protected Areas (WDPA) from its
public ArcGIS FeatureServer (bounding-box query, cached), standardised
to pa_name / pa_category /
pa_group columns with IUCN categories mapped to
strict-protection (Ia–III) vs sustainable-use (IV–VI). It works anywhere
in the world. A local pa_src file
(.shp/.gpkg/.geojson) overrides
it for offline use. See wdpa_areas().
backend = "gee".mappingAS complements other R packages for preliminary,
area-based conservation assessment — among them ConR,
red
and rCAT,
as well as the GeoCAT web
tool. Its distinguishing focus is coupling the EOO/AOO range metrics
with habitat-conversion, fire and protected-area layers
(MapBiomas, global Sentinel-2/Esri land cover, and WDPA) in a single
reproducible workflow and Shiny app.
When using this package, please also cite the underlying data and methods:
MIT © Antônio Lucas Barreira. See the LICENSE file.