riverarchitect.mapping

Map production built on QGIS print layouts.

Replaces the former ArcGIS Pro implementation (arcpy.mp.ArcGISProject / .aprx projects, .lyrx layer files, PDFDocumentCreate page stitching). Nothing here needs an Esri licence.

What changed conceptually

  • Project file: .aprx -> .qgz (QgsProject, readable and editable in QGIS)

  • Layer style: .lyrx -> .qml (QgsRasterLayer.loadNamedStyle)

  • Page series: PDFDocumentCreate + appendPages -> QGIS Atlas The old code exported one temporary PDF per map centre point and stitched them together. QGIS drives a multi-page series natively: a coverage layer holds one rectangle per page and QgsLayoutExporter.exportToPdf(atlas, …) writes a single multi-page PDF in one call.

  • Layout: a layout stored inside the proprietary template -> composed in code The layout (map frame, legend, scale bar, north arrow, title, footer) is built programmatically, so no binary template is required. An existing .qgz template is used instead when one is present in 02_Maps/templates/.

The public API – Mapper(condition, map_type, ...), prepare_layout(), make_pdf_maps() and .error – is unchanged from the ArcGIS implementation, so existing callers keep working without modification.

Running headless requires QT_QPA_PLATFORM=offscreen, which this module sets itself.

riverarchitect.mapping.QGIS_BINDINGS_PATH = None

The directory the bindings were found in, when they were not already importable.

riverarchitect.mapping.QGIS_PREFIX = None

The QGIS prefix that goes to QgsApplication.setPrefixPath. None means the environment’s QGIS_PREFIX_PATH, or the platform default, is used.

riverarchitect.mapping.QGIS_LAYOUTS = {'darwin': (('/Applications/QGIS*.app/Contents/Resources/python', '{b}/../../MacOS', ()), ('/home/docs/Applications/QGIS*.app/Contents/Resources/python', '{b}/../../MacOS', ()), ('/opt/homebrew/opt/qgis/QGIS.app/Contents/Resources/python', '{b}/../../MacOS', ())), 'linux': (('/usr/lib/python3/dist-packages', '/usr', ()), ('/usr/lib/python3*/dist-packages', '/usr', ()), ('/usr/lib/python3*/site-packages', '/usr', ()), ('/usr/share/qgis/python', '/usr', ()), ('/usr/local/share/qgis/python', '/usr/local', ()), ('/opt/qgis*/share/qgis/python', '{b}/../../..', ())), 'win32': (('C:/OSGeo4W*/apps/qgis*/python', '{b}/..', ('{b}/../bin', '{b}/../../../bin')), ('C:/Program Files/QGIS */apps/qgis*/python', '{b}/..', ('{b}/../bin', '{b}/../../../bin')), ('C:/Program Files*/QGIS*/apps/qgis*/python', '{b}/..', ('{b}/../bin', '{b}/../../../bin')))}

Where a QGIS installation keeps its Python bindings, per platform, as (bindings glob, prefix template, DLL directory globs). A distribution installs the bindings for the system interpreter, so a conda environment does not see them even though QGIS is installed and working - which is the case this exists to handle. {b} in a prefix template is replaced by the matched bindings directory.

Globs matter on Windows, where the standalone installer puts the version in the folder name (C:\\Program Files\\QGIS 3.34.5), and on macOS, where the bundle may be QGIS.app or QGIS-LTR.app.

riverarchitect.mapping.qgis_candidates()[source]

Yield (bindings, prefix, dll_dirs) triples to try, most specific first.

RIVERARCHITECT_QGIS_PATH (a directory containing the qgis package) and QGIS_PREFIX_PATH come first, so a non-standard installation can be pointed at explicitly and nothing needs guessing.

riverarchitect.mapping.qgis_status()[source]

Whether mapping can run here, and what to do about it if it cannot.

One implementation for both front ends, so the Qt and the tkinter tab cannot give different advice.

Returns:

(available, message).

Return type:

tuple

class riverarchitect.mapping.QgisSession[source]

Bases: object

Process-wide QgsApplication. QGIS may only be initialised once per process.

classmethod start()[source]
classmethod stop()[source]
class riverarchitect.mapping.Mapper(condition, map_type, *args)[source]

Bases: object

project_path()[source]
open_project()[source]

Create (or reopen) the QGIS project that carries this condition’s maps.

Replaces copy_template_project(), which duplicated river_template.aprx. If a QGIS template exists at 02_Maps/templates/river_template.qgz it is used as the starting point; otherwise an empty project is created and the layout is composed in code.

save_project()[source]
choose_ref_layer(raster_type)[source]
choose_ref_layout(map_lyr_name='')[source]
choose_map_layer(map_name='')[source]
style_file(style_name)[source]

Full path of a .qml style, or an empty string when it does not exist.

apply_style(layer, style_name)[source]
get_input_ras_dir(map_type)[source]
get_raster_extent(path2raster)[source]
add_background_layers()[source]

Add any background layers shipped with the template directory.

add_map_raster(raster_path, layer_name, style_name)[source]
add_shapefiles()[source]

Add MaxLifespan shapefiles (map_type ‘mlf’) alongside the rasters.

build_layout(layout_name, title_text)[source]

Compose a print layout: map frame, legend, scale bar, north arrow, title, footer.

Replaces the layouts that used to live inside river_template.aprx.

make_xy_centerpoints(new_extents)[source]
coverage_layer()[source]

One rectangle per map page, driving the QGIS atlas.

This is the structural replacement for the old loop that zoomed the map frame to each centre point, exported a temporary PDF and appended it to a growing document.

make_pdf_maps(map_name, *args, **kwargs)[source]
prepare_layout(*args, **kwargs)[source]
zoom2map(xy)[source]

Kept for API compatibility. Page extents are now driven by the atlas coverage layer.