Skip to content

feat(backend): clip DEM to buffered AOI before upload to reduce QFiel… - #864

Open
s4h1r wants to merge 3 commits into
hotosm:devfrom
s4h1r:dev
Open

feat(backend): clip DEM to buffered AOI before upload to reduce QFiel…#864
s4h1r wants to merge 3 commits into
hotosm:devfrom
s4h1r:dev

Conversation

@s4h1r

@s4h1r s4h1r commented Aug 8, 2026

Copy link
Copy Markdown

What type of PR is this? (check all applicable)

  • 🍕 Feature
  • 🐛 Bug Fix
  • 📝 Documentation
  • 🧑‍💻 Refactor
  • ✅ Test
  • 🤖 Build or CI
  • ❓ Other (please specify)

Related Issue

Fixes #790

Describe this PR

This PR clips downloaded DEMs to the project AOI with a 50 m buffer before uploading them to S3. This reduces unnecessary DEM coverage in QField packages.

The clipping uses GDAL with a PostGIS-derived cutline and is integrated into the existing DEM download/upload workflow. If clipping cannot be performed, the original DEM is uploaded as a fallback.

Tests cover successful clipping, fallback paths, invalid geometry, temporary-file cleanup, and error handling.

AI Tool Usage

  • No AI tools were used
  • AI tools were used (complete below)

If AI-assisted:

  • Tool(s) used: Hermes Agent
  • What was generated: Used to navigate and understand the codebase, repository architecture, conventions, and relevant documentation to make informed implementation decisions.
  • What you reviewed and changed: All implementation decisions and changes were reviewed and made by me.

Review follow-up

I had a small hiccup while applying the Copilot review suggestions and initially accepted the wrong suggested fix, but I caught it, corrected the implementation, and pushed the final version. The PR is now up to date and ready for review.

Screenshots

N/A — backend-only change.

Review Guide

  • just lint — passed
  • pre-commit run --hook-stage pre-push --all-files — all 16 hooks passed
  • just test backend — 231/231 tests passed

…d package size

Signed-off-by: Sahir <sahir22@proton.me>
Copilot AI lite review requested due to automatic review settings August 8, 2026 19:21
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@github-actions github-actions Bot added the backend Related to backend code label Aug 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements Issue #790 by clipping downloaded DEM rasters to a project’s buffered AOI (50m) before uploading to S3, reducing QField package size while keeping a safe fallback to the original DEM when clipping cannot be performed.

Changes:

  • Added clip_dem_to_aoi() GDAL-based clipping helper and integrated it into the download_and_upload_dem() workflow using a PostGIS-derived buffered outline.
  • Added ARQ-worker-side fallback behavior for missing AOI / missing DB pool / clipping errors (uploads unclipped DEM).
  • Added a new test suite covering clipping invocation, fallback paths, and basic clipping behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/backend/app/jaxa/upload_dem.py Adds GDAL clipping helper and clips DEM to a 50m-buffered AOI from PostGIS before upload, with fallback behavior on failure.
src/backend/tests/test_upload_dem.py Adds tests for the new clipping + fallback workflow and direct helper behavior.
Suppressed comments (3)

src/backend/tests/test_upload_dem.py:154

  • This test writes a dummy merged.tif to tmp_path/merged.tif, but download_and_upload_dem() reads/writes tmp_path/tif_processing/<project_id>/merged.tif (based on tempfile.gettempdir()). Creating the file at the actual expected path makes the test setup match production behavior and avoids false confidence if future code starts checking for file existence before clipping/uploading.
    merged = tmp_path / "merged.tif"
    merged.write_bytes(b"fake-tif")
    monkeypatch.setattr(upload_dem.tempfile, "gettempdir", lambda: str(tmp_path))

src/backend/tests/test_upload_dem.py:196

  • This test writes a dummy merged.tif to tmp_path/merged.tif, but download_and_upload_dem() reads/writes tmp_path/tif_processing/<project_id>/merged.tif (based on tempfile.gettempdir()). Creating the file at the actual expected path makes the test setup match production behavior and avoids false confidence if future code starts checking for file existence before clipping/uploading.
    merged = tmp_path / "merged.tif"
    merged.write_bytes(b"fake-tif")
    monkeypatch.setattr(upload_dem.tempfile, "gettempdir", lambda: str(tmp_path))

src/backend/tests/test_upload_dem.py:238

  • This test writes a dummy merged.tif to tmp_path/merged.tif, but download_and_upload_dem() reads/writes tmp_path/tif_processing/<project_id>/merged.tif (based on tempfile.gettempdir()). Creating the file at the actual expected path makes the test setup match production behavior and avoids false confidence if future code starts checking for file existence before clipping/uploading.
    merged = tmp_path / "merged.tif"
    merged.write_bytes(b"fake-tif")
    monkeypatch.setattr(upload_dem.tempfile, "gettempdir", lambda: str(tmp_path))

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/backend/app/jaxa/upload_dem.py Outdated
Comment on lines +146 to +148
fd, cutline_path = tempfile.mkstemp(suffix=".geojson", prefix="cutline_")
os.close(fd)
clipped_path = dem_path + ".clipped.tif"
Comment thread src/backend/tests/test_upload_dem.py Outdated
@s4h1r

s4h1r commented Aug 8, 2026

Copy link
Copy Markdown
Author

I have read the CONTRIBUTING.md document and I hereby sign and agree with the guidelines

github-actions Bot added a commit that referenced this pull request Aug 8, 2026
@s4h1r s4h1r closed this Aug 8, 2026
@s4h1r s4h1r reopened this Aug 8, 2026
s4h1r and others added 2 commits August 9, 2026 01:55
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@spwoodcock

Copy link
Copy Markdown
Member

Thanks! I'll review asap 🙏

@s4h1r

s4h1r commented Aug 26, 2026

Copy link
Copy Markdown
Author

Thanks! I'll review asap 🙏

It's been quite some time. A response would be highly appreciated. Thanks

@spwoodcock

Copy link
Copy Markdown
Member

Thanks for the prompt!

It hasn't been that long though 😉 Open source maintainers can take a while to reply - you'll get used to it - due to overwhelming demand on their attention. Especially a problem with LLM-assisted contributions, which take a maintainer orders of magnitude longer to validate and review PRs than it does for devs to produce them.
https://responsibleai.guide

That all said, thanks again, I'll review this today or tomorrow!

In the meantime, did you manage to test this code on an actual example, other than automated tests? 🙏

A good way to do that:

  1. Start a local dev server
  2. Create a project
  3. Wait for the DEM
  4. Download the generated DEM from local RustFS S3 to inspect in a tool like QGIS.

To fully confirm, you could do the pre and post this PR, so compare clipped and not clipped DEMs 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Related to backend code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scraped DEM should be clipped to a buffered AOI, reducing file size

3 participants