GIS project assembly and digital field form management. Pull provincial datasets from the BC Data Catalogue, Freshwater Atlas, and cloud-hosted layers, clip to any set of watershed groups, and assemble a fully styled QGIS project with digital field forms — ready to deploy to mobile devices for collaborative offline field collection.
We build and maintain forms for fish passage assessment, habitat confirmation, effectiveness monitoring, restoration site investigation, eDNA sampling, and benthic invertebrate collection — with more added as programs evolve. Data collected in some forms is structured for direct submission to provincial database systems (FISS, PSCIS, CABIN), while other data lands within central database systems we maintain and share with partners. Photos are automatically renamed and organized into site directories. Multiple team members contribute within the same shared project, with changes syncing between field and office.
Installation
pak::pkg_install("NewGraphEnvironment/rfp")System dependencies
rfp shell scripts require GDAL and several Python CLI tools. Install with:
# GDAL (also needed by R's sf package)
brew install gdal # macOS
# apt install gdal-bin # Linux
# Python CLI tools (bcdata, fio, rio, mergin)
pip install uv
uv sync --project "$(Rscript -e 'cat(system.file("python", package = "rfp"))')"Verify everything is available:
rfp::rfp_check_deps()Quick start
library(rfp)
# Create a field-ready QGIS project
rfp_project_create(
name = "elk_river_2026",
watershed_groups = c("ELKR"),
template = "bcfishpass_mobile",
forms = c("pscis", "fiss_site")
)
# Apply cartographic styles from the gq registry
rfp_styles_apply("~/Projects/gis/elk_river_2026/background_layers.gpkg")
# Push to Mergin Maps for mobile field collection
rfp_mergin_create("newgraph/elk_river_2026", "~/Projects/gis/elk_river_2026")
rfp_mergin_share("newgraph/elk_river_2026", "field_tech_1", "writer")
# Audit who changed what, when
rfp_mergin_collaborators("newgraph/elk_river_2026")
rfp_mergin_history("newgraph/elk_river_2026", since = "2026-01-01")
# Which rows in a layer changed between two points in time?
# e.g. watershed groups added to the Fraser project since 2025-03-31
rfp_mergin_diff(
project = "newgraph/sern_fraser_2024",
path = "background_layers.gpkg",
layer = "whse_basemapping.fwa_watershed_groups_poly",
from = "2025-03-31",
key = "watershed_group_code"
)See the package documentation for vignettes and function reference.
How the pieces fit together
rfp is built around a layered workflow — each layer is independently usable, and they compose into a field-and-web pipeline. The same QGIS project is the unit of work for mobile field collection (Mergin Maps) and for web map deployment (QWC2):
| Layer | Functions / artefacts | Role |
|---|---|---|
| Layer sources |
rfp_source(), rfp_source_bcdata(), rfp_source_csv(), rfp_source_url()
|
Pluggable abstraction for where a layer comes from: BC Data Catalogue, CSVs on disk, cloud URLs, test fixtures. Project assembly reads the registry. |
| Project assembly |
rfp_project_create(), rfp_project_layers(), rfp_project_subset(), rfp_project_templates(); inst/templates/{bcfishpass_mobile,bcrestoration_mobile}.qgs
|
Stitch a styled QGIS project together from background layers + forms + templates + methods PDFs. rfp_project_subset() derives a focused child project from a heavy parent (e.g. a one-watershed mobile deploy or a browser-renderable subset from a multi-region parent). |
| Forms |
rfp_form_types(), rfp_form_create(); inst/lookups/rfp_form_types.csv
|
Package-internal registry of field-form GeoPackages (PSCIS, FISS, eDNA, habitat confirmation, restoration, CABIN). Add a form to a project, deploy with the project, sync back as data. |
| QGIS authoring |
rfp_qgs_rename(), rfp_qgs_themes(), rfp_qgs_theme_apply(), rfp_qgs_theme_export()
|
xml2-based transformations on .qgs files: WMS-safe layer naming, inspect map themes (visibility presets) in a project, and transfer themes between projects so a styling change made in one project propagates to others. |
| Cartography (via gq) |
rfp_styles_apply(); inst/pyqgis/apply_styles.py, render_map.py
|
Apply cartographic styles maintained centrally in gq — QGIS, tmap, leaflet, and web all share the same registry. PyQGIS scripts drive the headless application + map rendering. |
| Field deployment (Mergin Maps) |
rfp_mergin_create/share/pull/push/sync/diff/history/... (12 fns) |
Deploy projects to Mergin, share with collaborators by role, sync changes between field and office, audit history with row-level diffs. |
| Web deployment (QWC2) |
rfp_qgs_themes_config() → qwc_config.csv; consumed by rtj’s qwc_project-add.sh
|
Generate the QWC2 themesConfig + visibility-preset entry for a project. Theme keep-list, initial theme, locked layers, bbox override, project title, URL suffix — all driven from the .qgs map themes. WMS-spec name compliance is handled by rfp_qgs_rename() so QWC2’s flattened group hierarchy doesn’t collide. |
| Field artefacts |
rfp_photo_metadata_rm(), rfp_gpx_import(), rfp_gpkg_to_geojson()
|
Photo metadata scrubbing, GPS track import, format conversion. |
| Provincial metadata |
rfp_meta_bcd_xref(), rfp_meta_bcd_xref_col_comments()
|
Cross-reference layers to BC Data Catalogue records for documentation + lineage; surfaces WMS endpoints for downstream consumption. |
The mobile-and-web dual deployment is the design intent: one QGIS project, two delivery surfaces. rfp_project_subset() is the data-thinning primitive that makes the same project legible in a browser (full provincial layers won’t render in QWC2).
Roadmap
- Form lifecycle deepening — registry expansion (more form types, partner-defined types) and tighter coupling to downstream database submission for FISS / PSCIS / CABIN. A CSV-driven form-builder (QML generation from tabular definitions) is in design (#24).
-
Style-registry tightening — connect QGIS
layer_stylestables to the central gq style registry so a style edit propagates to every project that references it (#15, #17). -
QGIS version support — bump templates to QGIS 4.0 once stable (#68); multi-version schema fixtures for
qgs/subsettests (#69). -
Layer-source plugins — extend
rfp_source_*()to additional cloud-hosted sources beyond BC Data Catalogue, direct URLs, and CSV.
Issues and feature requests live in GitHub Issues.
