From 34c1176a725475e01da1822659b64b94fc74adf8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 17:44:49 +0000 Subject: [PATCH 1/2] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v5.0.0...v6.0.0) - [github.com/astral-sh/ruff-pre-commit: v0.9.6 → v0.15.20](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.6...v0.15.20) - [github.com/snakemake/snakefmt: v0.11.4 → v2.0.3](https://github.com/snakemake/snakefmt/compare/v0.11.4...v2.0.3) - [github.com/codespell-project/codespell: v2.4.1 → v2.4.2](https://github.com/codespell-project/codespell/compare/v2.4.1...v2.4.2) --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6483ee3..ed7fb02 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ default_language_version: repos: # Generic 'file quality' testing - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: # Machine-friendliness - id: trailing-whitespace @@ -25,7 +25,7 @@ repos: # Python file formatting - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.6 + rev: v0.15.20 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] @@ -33,13 +33,13 @@ repos: # Snakemake file formatting - repo: https://github.com/snakemake/snakefmt - rev: v0.11.4 + rev: v2.0.3 hooks: - id: snakefmt # Spelling - repo: https://github.com/codespell-project/codespell - rev: v2.4.1 + rev: v2.4.2 hooks: - id: codespell files: .*\.(py|smk|md)$|^Snakefile$ From d1c1cb0d14333fef29293e6e3d39f24b116fb5d5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 17:45:07 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/integration/Snakefile | 26 ++++----- workflow/Snakefile | 4 +- workflow/rules/automatic.smk | 106 +++++++++++++++++------------------ workflow/rules/process.smk | 60 ++++++++++---------- 4 files changed, 98 insertions(+), 98 deletions(-) diff --git a/tests/integration/Snakefile b/tests/integration/Snakefile index 9d66eb5..c28d2e0 100644 --- a/tests/integration/Snakefile +++ b/tests/integration/Snakefile @@ -3,14 +3,14 @@ configfile: workflow.source_path("./test_config.yaml") rule download_netherlands_shapes: - message: - "Download and unzip the Netherlands shapes." output: "resources/inputs/shapes/NLD.parquet", log: "logs/download_netherlands_shapes.log", conda: "../../workflow/envs/shell.yaml" + message: + "Download and unzip the Netherlands shapes." shell: """ curl -sSLo {output:q} "https://zenodo.org/records/16684683/files/NLD.parquet" @@ -18,14 +18,14 @@ rule download_netherlands_shapes: rule download_netherlands_protected_areas: - message: - "Download a dummy drop-in dataset for Netherlands protected areas (not based on WDPA)." output: "resources/inputs/wdpa.gdb.zip", log: "logs/download_netherlands_protected_areas.log", conda: "../../workflow/envs/shell.yaml" + message: + "Download a dummy drop-in dataset for Netherlands protected areas (not based on WDPA)." shell: """ curl -sSLo {output:q} "https://zenodo.org/records/16684513/files/wdpa-nl-dropin.gdb.zip" @@ -33,8 +33,6 @@ rule download_netherlands_protected_areas: rule unzip_netherlands_protected_areas: - message: - "Download protected areas data." input: script=workflow.source_path("../../workflow/scripts/unzip_like.py"), zipfile=rules.download_netherlands_protected_areas.output, @@ -44,9 +42,11 @@ rule unzip_netherlands_protected_areas: "logs/unzip_netherlands_protected_areas.log", conda: "../../workflow/envs/shell.yaml" + message: + "Download protected areas data." shell: """ - python {input.script:q} {input.zipfile:q} -t "resources/inputs/" 2> {log:q} + python {input.script:q} {input.zipfile:q} -t "resources/inputs/" 2>{log:q} """ @@ -55,10 +55,6 @@ rule unzip_netherlands_protected_areas: # `config`: specifies the module configuration. # `pathvars:` helps you re-wire where the module places files. module module_area_potentials: - snakefile: - "../../workflow/Snakefile" - config: - config["module_area_potentials"] pathvars: # Redirect specific user resources (inputs) shapes="resources/inputs/shapes/{shape}.parquet", @@ -69,6 +65,10 @@ module module_area_potentials: logs="resources/module/logs", resources="resources/module/resources", results="resources/module/results", + snakefile: + "../../workflow/Snakefile" + config: + config["module_area_potentials"] # rename all module rules with a prefix, to avoid naming conflicts. @@ -77,9 +77,9 @@ use rule * from module_area_potentials as module_area_potentials_* # Request something from the module rule all: - message: - "Run the module for the Netherlands shapes." default_target: True input: # The report file requires all area potential output files "resources/module/results/NLD/area_potential_report.html", + message: + "Run the module for the Netherlands shapes." diff --git a/workflow/Snakefile b/workflow/Snakefile index 90ac733..1105c0c 100644 --- a/workflow/Snakefile +++ b/workflow/Snakefile @@ -46,8 +46,6 @@ include: "rules/process.smk" rule all: - message: - "ERROR: Invalid `rule all:` call" default_target: True output: "INVALID", @@ -55,5 +53,7 @@ rule all: stderr="/all.stderr", conda: "envs/shell.yaml" + message: + "ERROR: Invalid `rule all:` call" shell: 'echo "This workflow must be called as a snakemake module." > {log.stderr}' diff --git a/workflow/rules/automatic.smk b/workflow/rules/automatic.smk index bdb6890..8ae4890 100644 --- a/workflow/rules/automatic.smk +++ b/workflow/rules/automatic.smk @@ -7,10 +7,6 @@ if config.get("tiny_files", False): ## rule clip_slope: - message: - "Download slope data covering the bounds of the input shapefile." - params: - cog_url=internal["resources"]["automatic"]["slope"], input: vector="", output: @@ -18,14 +14,14 @@ if config.get("tiny_files", False): log: "/{shape}/clip_slope.log", localrule: True + params: + cog_url=internal["resources"]["automatic"]["slope"], + message: + "Download slope data covering the bounds of the input shapefile." wrapper: "v7.2.0/geo/rasterio/clip-geotiff" rule clip_bathymetry: - message: - "Download bathymetry data covering the bounds of the input shapefile." - params: - cog_url=internal["resources"]["automatic"]["bathymetry"], input: vector="", output: @@ -33,6 +29,10 @@ if config.get("tiny_files", False): log: "/{shape}/clip_bathymetry.log", localrule: True + params: + cog_url=internal["resources"]["automatic"]["bathymetry"], + message: + "Download bathymetry data covering the bounds of the input shapefile." wrapper: "v7.2.0/geo/rasterio/clip-geotiff" @@ -43,42 +43,40 @@ else: ## rule download_slope: - message: - "Download global slope data." - params: - url=internal["resources"]["automatic"]["slope"], output: path="/automatic/global/slope.tif", log: "/download_slope.log", + localrule: True conda: "../envs/shell.yaml" - localrule: True + params: + url=internal["resources"]["automatic"]["slope"], + message: + "Download global slope data." shell: """ curl -sSLo {output:q} {params.url:q} """ rule download_bathymetry: - message: - "Download global bathymetry data." - params: - url=internal["resources"]["automatic"]["bathymetry"], output: path="/automatic/global/bathymetry.tif", log: "/download_bathymetry.log", + localrule: True conda: "../envs/shell.yaml" - localrule: True + params: + url=internal["resources"]["automatic"]["bathymetry"], + message: + "Download global bathymetry data." shell: """ curl -sSLo {output:q} {params.url:q} """ rule clip_slope: - message: - "Cut slope data to the bounds of the input shapefile." input: script=workflow.source_path("../scripts/clip_raster.py"), shapes="", @@ -89,14 +87,14 @@ else: "/{shape}/clip_slope.log", conda: "../envs/default.yaml" + message: + "Cut slope data to the bounds of the input shapefile." shell: """ - python {input.script:q} {input.slope:q} {input.shapes:q} {output:q} 2> {log:q} + python {input.script:q} {input.slope:q} {input.shapes:q} {output:q} 2>{log:q} """ rule clip_bathymetry: - message: - "Cut bathymetry data to the bounds of the input shapefile." input: script=workflow.source_path("../scripts/clip_raster.py"), shapes="", @@ -107,9 +105,11 @@ else: "/{shape}/clip_bathymetry.log", conda: "../envs/default.yaml" + message: + "Cut bathymetry data to the bounds of the input shapefile." shell: """ - python {input.script:q} {input.bathymetry:q} {input.shapes:q} {output:q} 2> {log:q} + python {input.script:q} {input.bathymetry:q} {input.shapes:q} {output:q} 2>{log:q} """ @@ -119,17 +119,17 @@ else: rule download_globcover: - message: - "Download the GlobCover land cover data (~380 MB)." - params: - url=internal["resources"]["automatic"]["globcover"], output: "/automatic/global/globcover.zip", log: "/download_globcover.log", + localrule: True conda: "../envs/shell.yaml" - localrule: True + params: + url=internal["resources"]["automatic"]["globcover"], + message: + "Download the GlobCover land cover data (~380 MB)." shell: """ curl -sSLo {output:q} {params.url:q} @@ -137,10 +137,6 @@ rule download_globcover: rule unzip_globcover: - message: - "Unzip the relevant TIF files from the GlobCover zip file." - params: - target_file=internal["resources"]["automatic"]["globcover_landcover_tif"], input: script=workflow.source_path("../scripts/unzip_like.py"), zipfile=rules.download_globcover.output, @@ -150,15 +146,17 @@ rule unzip_globcover: "/unzip_globcover.log", conda: "../envs/shell.yaml" + params: + target_file=internal["resources"]["automatic"]["globcover_landcover_tif"], + message: + "Unzip the relevant TIF files from the GlobCover zip file." shell: """ - python {input.script:q} {input.zipfile:q} -f {params.target_file:q} -o {output:q} 2> {log:q} + python {input.script:q} {input.zipfile:q} -f {params.target_file:q} -o {output:q} 2>{log:q} """ rule clip_landcover: - message: - "Cut land cover data to the bounds of the input shapefile." input: script=workflow.source_path("../scripts/clip_raster.py"), shapes="", @@ -169,9 +167,11 @@ rule clip_landcover: "/{shape}/clip_landcover.log", conda: "../envs/default.yaml" + message: + "Cut land cover data to the bounds of the input shapefile." shell: """ - python {input.script:q} {input.landcover:q} {input.shapes:q} {output:q} 2> {log:q} + python {input.script:q} {input.landcover:q} {input.shapes:q} {output:q} 2>{log:q} """ @@ -181,17 +181,17 @@ rule clip_landcover: rule download_ghsl: - message: - "Download the GHSL (Global Human Settlement Layer) built-up surface data." - params: - url=internal["resources"]["automatic"]["ghsl"], output: "/automatic/global/ghsl_built_s.zip", log: "/download_ghsl.log", + localrule: True conda: "../envs/shell.yaml" - localrule: True + params: + url=internal["resources"]["automatic"]["ghsl"], + message: + "Download the GHSL (Global Human Settlement Layer) built-up surface data." shell: """ curl -sSLo {output:q} {params.url:q} @@ -199,10 +199,6 @@ rule download_ghsl: rule unzip_ghsl: - message: - "Unzip the relevant TIF file from the GHSL data." - params: - target_file=internal["resources"]["automatic"]["ghsl_tif"], input: script=workflow.source_path("../scripts/unzip_like.py"), zipfile=rules.download_ghsl.output, @@ -212,15 +208,17 @@ rule unzip_ghsl: "/unzip_ghsl.log", conda: "../envs/shell.yaml" + params: + target_file=internal["resources"]["automatic"]["ghsl_tif"], + message: + "Unzip the relevant TIF file from the GHSL data." shell: """ - python {input.script:q} {input.zipfile:q} -f {params.target_file:q} -o {output:q} 2> {log:q} + python {input.script:q} {input.zipfile:q} -f {params.target_file:q} -o {output:q} 2>{log:q} """ rule clip_settlement: - message: - "Cut settlement data to the bounds of the input shapefile." input: script=workflow.source_path("../scripts/clip_raster.py"), shapes="", @@ -231,9 +229,11 @@ rule clip_settlement: "/{shape}/clip_settlement.log", conda: "../envs/default.yaml" + message: + "Cut settlement data to the bounds of the input shapefile." shell: """ - python {input.script:q} {input.settlement:q} {input.shapes:q} {output:q} 2> {log:q} + python {input.script:q} {input.settlement:q} {input.shapes:q} {output:q} 2>{log:q} """ @@ -243,8 +243,6 @@ rule clip_settlement: rule rasterise_clip_wdpa: - message: - "Rasterise and cut WDPA data to the bounds of the input shapefile, using the landcover raster as reference for the rasterisation." input: script=workflow.source_path("../scripts/clip_and_rasterise_polys.py"), shapes="", @@ -256,7 +254,9 @@ rule rasterise_clip_wdpa: "/{shape}/clip_wdpa.log", conda: "../envs/default.yaml" + message: + "Rasterise and cut WDPA data to the bounds of the input shapefile, using the landcover raster as reference for the rasterisation." shell: """ - python {input.script:q} {input.shapes:q} {input.reference_raster:q} {input.protected_areas:q} {output:q} 2> {log:q} + python {input.script:q} {input.shapes:q} {input.reference_raster:q} {input.protected_areas:q} {output:q} 2>{log:q} """ diff --git a/workflow/rules/process.smk b/workflow/rules/process.smk index 64053b1..7da7a8a 100644 --- a/workflow/rules/process.smk +++ b/workflow/rules/process.smk @@ -1,8 +1,4 @@ checkpoint breakup_shape: - message: - "Break up {wildcards.shape} into the configured subunits." - params: - split_by=config["split_by"], input: script=workflow.source_path("../scripts/breakup_shape.py"), shapes="", @@ -12,19 +8,17 @@ checkpoint breakup_shape: "/{shape}/breakup_shape.log", conda: "../envs/default.yaml" + params: + split_by=config["split_by"], + message: + "Break up {wildcards.shape} into the configured subunits." shell: """ - python {input.script:q} {input.shapes:q} {params.split_by:q} {output:q} 2> {log:q} + python {input.script:q} {input.shapes:q} {params.split_by:q} {output:q} 2>{log:q} """ rule prepare_resampled_inputs: - message: - "Resample inputs for {wildcards.subunit} in {wildcards.shape} to the projection and resolution of the land cover data, while aggregating land cover types." - params: - # Use internal defaults if not overridden - land_cover_types_yaml_string=internal["land_cover_types"] - | config.get("land_cover_types", {}), input: script=workflow.source_path("../scripts/resample.py"), shapes=rules.breakup_shape.output, @@ -43,25 +37,23 @@ rule prepare_resampled_inputs: "/{shape}/{subunit}/prepare_resampled_inputs.log", conda: "../envs/default.yaml" + params: + # Use internal defaults if not overridden + land_cover_types_yaml_string=internal["land_cover_types"] + | config.get("land_cover_types", {}), + message: + "Resample inputs for {wildcards.subunit} in {wildcards.shape} to the projection and resolution of the land cover data, while aggregating land cover types." shell: """ python {input.script:q} \ - "{input.shapes}/{wildcards.subunit}.parquet" \ - {input.land_cover_path:q} {input.slope_path:q} {input.settlement_path:q} {input.bathymetry_path:q} {input.protected_area_path:q} \ - {params.land_cover_types_yaml_string:q} \ - {output.resampled_input:q} {output.plot:q} 2> {log:q} + "{input.shapes}/{wildcards.subunit}.parquet" \ + {input.land_cover_path:q} {input.slope_path:q} {input.settlement_path:q} {input.bathymetry_path:q} {input.protected_area_path:q} \ + {params.land_cover_types_yaml_string:q} \ + {output.resampled_input:q} {output.plot:q} 2>{log:q} """ rule area_potential: - message: - "Compute area potential for the tech {wildcards.tech} and {wildcards.subunit} in {wildcards.shape}." - params: - config=lambda wildcards: config["techs"][f"{wildcards.tech}"], - subunit_override_config=lambda wildcards: config.get("overrides", {}) - .get(wildcards.subunit, {}) - .get(wildcards.tech, {}), - buffer_crs=lambda wildcards: config["buffer_crs"], input: script=workflow.source_path("../scripts/area_potential.py"), shapes=rules.breakup_shape.output, @@ -76,15 +68,21 @@ rule area_potential: "/{shape}/{subunit}/area_potential_{tech}.log", conda: "../envs/default.yaml" + params: + config=lambda wildcards: config["techs"][f"{wildcards.tech}"], + subunit_override_config=lambda wildcards: config.get("overrides", {}) + .get(wildcards.subunit, {}) + .get(wildcards.tech, {}), + buffer_crs=lambda wildcards: config["buffer_crs"], + message: + "Compute area potential for the tech {wildcards.tech} and {wildcards.subunit} in {wildcards.shape}." shell: """ - python {input.script:q} "{input.shapes}/{wildcards.subunit}.parquet" {input.resampled_path:q} {params.config:q} {params.buffer_crs:q} {output.area_potential:q} {output.plot:q} --override_config={params.subunit_override_config:q} 2> {log:q} + python {input.script:q} "{input.shapes}/{wildcards.subunit}.parquet" {input.resampled_path:q} {params.config:q} {params.buffer_crs:q} {output.area_potential:q} {output.plot:q} --override_config={params.subunit_override_config:q} 2>{log:q} """ rule aggregate_area_potential: - message: - "Aggregate area potential for the tech {wildcards.tech} in {wildcards.shape}." input: get_subunits, output: @@ -93,6 +91,8 @@ rule aggregate_area_potential: "/{shape}/aggregate_area_potential_{tech}.log", conda: "../envs/default.yaml" + message: + "Aggregate area potential for the tech {wildcards.tech} in {wildcards.shape}." shell: """ gdalwarp --config GDAL_CACHEMAX 3000 -wm 3000 -of GTiff -co COMPRESS=LZW {input} {output.aggregated_area_potential:q} @@ -100,8 +100,6 @@ rule aggregate_area_potential: rule plot_aggregated_area_potential: - message: - "Plot aggregated area potential for the tech {wildcards.tech} in {wildcards.shape}." input: rules.aggregate_area_potential.output.aggregated_area_potential, output: @@ -113,13 +111,13 @@ rule plot_aggregated_area_potential: "/{shape}/plot_aggregated_area_potential_{tech}.log", conda: "../envs/default.yaml" + message: + "Plot aggregated area potential for the tech {wildcards.tech} in {wildcards.shape}." script: "../scripts/tif_to_png.py" rule area_potential_report: - message: - "Generate an overview report of the area potential for all techs in shapes {wildcards.shape}." input: shapes="", area_potentials=expand( @@ -141,5 +139,7 @@ rule area_potential_report: "/{shape}/area_potential_report.log", conda: "../envs/default.yaml" + message: + "Generate an overview report of the area potential for all techs in shapes {wildcards.shape}." script: "../scripts/report.py"