Skip to content

Feature: add synchronous download_naip_from_polygon() wrapper to download.py #1355

@abhayrajjais01

Description

@abhayrajjais01

Problem

Downloading NAIP imagery via download_ArcGIS_REST() currently requires the caller to manually set up an asyncio.Semaphore, AsyncLimiter, and wrap everything in asyncio.run():

import asyncio
from asyncio import Semaphore
from aiolimiter import AsyncLimiter
from deepforest import download

async def main():
    semaphore = Semaphore(10)
    limiter = AsyncLimiter(1, 0.5)
    await download.download_web_server(
        semaphore, limiter, url,
        xmin, ymin, xmax, ymax,
        bbox_crs, savedir=savedir, image_name="tile.tiff"
    )

asyncio.run(main())

For the common use case of "I have a region and want the NAIP tile," this async boilerplate adds unnecessary friction — especially in notebooks and simple scripts.

Proposed Solution

Add a synchronous download_naip_from_polygon() function:

from deepforest import download

path = download.download_naip_from_polygon(
    gdf=my_geodataframe,
    savedir=".",
    year=2022,
    buffer_meters=100
)

Internally it would:

  • Compute the buffered bounding box from the input GeoDataFrame (any CRS)
  • Reproject to WGS84 for the API call
  • Set up Semaphore and AsyncLimiter with sensible defaults
  • Call the existing download_ArcGIS_REST() via asyncio.run()
  • Return the output file path

Scope

  • Fully additive — no changes to existing functions
  • Tests added to test_download.py reusing the existing mock pattern
  • No new dependencies

If this feature looks good, i would like to open a PR for this

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions