Tools & Packages
Open-source software is central to reproducible ecological research. Here are the tools I develop and maintain.
iLAND Workbench
π² iLAND Workbench β A QGIS Plugin for Forest Landscape Modeling
A dockable QGIS plugin that brings the iLAND individual-based forest landscape and disturbance model into a GIS workflow. It provides runtime management, module exploration, data-preparation pipelines for climate, soil, and stand-grid inputs, and reproducible analysis workflows β all from within QGIS.
iLAND Workbench bridges the gap between the iLAND simulation model and the QGIS ecosystem, making forest landscape modeling accessible without leaving your GIS environment. Key capabilities include:
- Runtime management with automatic download and verification of iLANDc across Windows, macOS, and Linux
- Module and submodule exploration directly from the iLAND source tree
- Complete climate workflows: future climate download, historical data, and conversion/validation pipelines
- Soil data acquisition from SSURGO and SoilGrids
- Stand-grid source workflows via LANDFIRE EVT and ESA WorldCover
- Landscape pre-flight validation before model creation
- Interactive SQLite plot browser for inspecting exported iLand output databases
- Full QGIS Processing provider integration
# Requires QGIS Desktop 3.28 or newer
# In QGIS: Plugins β Manage and Install Plugins β Install from ZIP
# Download iland_qgis_plugin.zip from the GitHub Releases pageThe plugin ships as a small, runtime-free package. The native iLAND console runtime (iLANDc) needed to run simulations is acquired automatically on first use.
@software{paudel2026iland,
author = {Paudel, Sushil},
title = {{iLAND Workbench: QGIS-based iLAND Workbench for
hassle-free installation and reproducible analysis
workflows}},
year = {2026},
version = {4.1.0},
publisher = {Zenodo},
doi = {10.5281/zenodo.19300115},
url = {https://doi.org/10.5281/zenodo.19300115}
}forestPulse
π¦ forestPulse β An R Package for Forest Structure, Disturbance & iLand Inputs
forestPulse turns forest field plots and drone or satellite imagery into analysis-ready summaries, and assembles the spatial and tabular inputs needed to drive the iLand forest landscape model. Current release v0.3.0, MIT licensed.
Together with iLAND Workbench, forestPulse completes the pipeline: it prepares the landscape, climate, and tree-initialisation inputs, and the plugin runs the simulation inside QGIS.
The package covers two connected areas, aimed at researchers, ecologists, and forest managers moving from field plots and imagery through to process-based modeling.
Field and remote-sensing analysis
- Index geotagged raster imagery into a spatial catalogue and match it to field plots
- Compute canopy height models (CHM), classify canopy gaps, and derive per-plot gap geometry
- Calculate 37 RGB-derived vegetation indices from drone orthomosaics
- Locate individual trees from compass bearings and distance measurements
- Summarise plot-level basal area, crown density, and species composition
- Standardise messy species names and audit what changed
iLand model inputs
- Impute field plots to pixels with modified random-forest imputation to build wall-to-wall tree lists, flagging poorly matched pixels
- Derive daily climate variables β vapour pressure deficit, radiation β from gridMET following the FAO-56 approach, and write a per-cluster SQLite climate database in iLandβs exact format
- Build the stand grid, resource-unit environment grid and file, and the tree-initialisation file, then cross-validate them β step by step or through a single
build_iland_landscape()call
# install.packages("remotes")
remotes::install_github("paudelsushil/forestPulse")Requires R 4.1.0 or newer. Some capabilities use optional packages declared in Suggests: install RSQLite for climate databases, yaImpute for plot-to-pixel imputation, and future/future.apply for parallel spatial sampling.
Field and remote-sensing analysis:
library(forestPulse)
# 1. Build a spatial catalogue of geotagged rasters and match it to field plots
catalog <- build_catalog(input = "path/to/imagery", output = "catalog.geojson")
plots <- sf::read_sf("plots.shp")
plot_imagery <- match_imagery(catalog, plots)
# 2. Canopy height model, then per-plot canopy gap metrics
chm <- compute_chm("dsm.tif", "dtm.tif", output = "chm.tif")
metrics <- extract_plot_metrics(chm = chm, plots = plots,
radius = 15.24, gap_threshold = 3)
# 3. An RGB vegetation index and a plot-level basal-area summary
vegetation_index("ExG", image_path = "orthomosaic.tif")
calculate_basal_area(tree_table, summary = "plot")Preparing inputs for the iLand model:
# Daily climate from a gridMET extraction -> per-cluster SQLite climate database
clim <- gridmet_preprocessing(
data = gridmet_daily, # one row per cluster-day
cluster_col = "cluster",
date_col = "date",
temp_unit = "K",
vpd_source = "compute" # derive VPD from temperature + humidity
)
write_iland_climate(clim, "database/climate.sqlite", split_col = "cluster")
# Stand grid + wall-to-wall tree initialisation via plot-to-pixel imputation
stand_grid <- create_stand_grid(stands, id_field = "stand_id",
filename = "gis/stand_grid.asc")
target <- make_target_from_rasters(predictor_stack, stand_grid)
pixel_plot <- impute_plots_to_pixels(reference, target, predictors, responses)
build_iland_init(pixel_plot, tree_lists, out_path = "init/init_trees.txt")| Topic | Functions |
|---|---|
| Raster catalogue | build_catalog(), read_catalog(), query_catalog(), match_imagery(), footprint() |
| Canopy height & gaps | compute_chm(), classify_gaps(), gap_metrics(), extract_plot_metrics() |
| Vegetation indices | vegetation_index() β 37 RGB indices |
| Tree location | locate_tree() |
| Basal area & summaries | calculate_basal_area(), calculate_species_basal_area(), calculate_plot_species_basal_area(), calculate_plot_summary() |
| Crown density | calculate_crownDensity(), show_calculation_details(), plot_summary() |
| Species standardisation | clean_species_names(), get_species_mapping(), check_unmapped_species(), compare_species_changes() |
| Climate (iLand) | gridmet_preprocessing(), calc_vpd(), calc_saturation_vapor_pressure(), convert_radiation(), write_iland_climate() |
| Landscape (iLand) | create_stand_grid(), create_environment_grid(), create_environment_file(), build_iland_landscape(), validate_landscape() |
| Imputation & init | impute_plots_to_pixels(), make_target_from_rasters(), flag_far_imputations(), build_iland_init(), create_init_file() |
Full documentation is available in the package help pages (?forestPulse) and the repository README.
@software{paudel2025forestpulse,
author = {Paudel, Sushil},
title = {{forestPulse: Analyse Forest Structure and Disturbance
from Field and Remote Sensing Data}},
year = {2025},
version = {0.3.0},
publisher = {Zenodo},
doi = {10.5281/zenodo.17887640},
url = {https://doi.org/10.5281/zenodo.17887640}
}Other Resources
GeoAI for Ecology (YouTube)
Video tutorials on remote sensing, GIS, R programming, and geospatial AI methods for ecological research.
Tutorials R GIS
Code & Data
Source code for both packages, plus reproducible code and datasets accompanying publications and tutorials.
Open Source Reproducible
Get notified about new releases
Tool releases, migration notes, and worked examples β by email once or twice a month, or by RSS.
You can also watch iLAND Workbench and forestPulse on GitHub for release notifications.