Skip to main content

Nearmap AI Python Library for extracting AI features from aerial imagery

Project description

nmaipy - Nearmap AI Python Library

Extract building footprints, vegetation, damage assessments, roof condition, and other AI features from Nearmap's aerial imagery using simple Python code.

Supported countries: au (Australia), us (United States), nz (New Zealand), ca (Canada)

Quick Start

1. Install

pip install nmaipy

Requires Python 3.12 or later.

2. Set your API key

export API_KEY=your_api_key_here

Contact your account administrator if you don't have one.

3. Run your first extraction

The repository ships with a 10-property smoke-test script (run_10_test.py) that extracts building features and roof age predictions for 10 US properties. It's the fastest way to verify your setup end-to-end:

python run_10_test.py

Output is written to data/outputs/quick_test/final/. Open rollup.csv, browse the rollup row per property, then have a look at README.md in the same directory — every export now ships an auto-generated, customer-readable data dictionary explaining every column.

The script itself is short — read it (run_10_test.py) to see the full call signature.

Common Use Cases

Population-scale analysis with mesh blocks / census blocks

nmaipy doesn't only consume parcel polygons. Mesh blocks (AU), census blocks (US/CA), suburbs, statistical areas — anything you can express as polygons can be passed in as AOIs. This gives you a contiguous map of AI features you can directly merge with demographic, economic, or other reference data on the same geographic units.

Pull a representative time-window (e.g. 12 months) for the latest snapshot:

from nmaipy.exporter import NearmapAIExporter

exporter = NearmapAIExporter(
    aoi_file='melbourne_mesh_blocks.geojson',  # or census blocks, suburbs, etc.
    output_dir='melbourne_2025',
    country='au',
    packs=['building', 'vegetation', 'surfaces', 'solar'],
    since='2025-01-01',
    until='2025-12-31',
    save_features=True,            # per-class GeoParquet with feature geometries
    include_parcel_geometry=True,  # keep block boundaries for GIS joins
    processes=8,
)
exporter.run()

For change detection, repeat the same call with a different since / until window and diff the resulting rollups. Each AOI gets a survey_date and system_version so you know exactly which capture / model version produced each row — useful when comparing vintages.

Tip: if your input has a since or until column (string-typed YYYY-MM-DD), it overrides the bulk values per row, so you can mix windows in a single export.

Disaster Response

Damage classification is a separate pack family. For a post-event sweep, request the buildings together with damage so you get the building footprint + the damage attributes on the same parcels:

exporter = NearmapAIExporter(
    aoi_file='affected_areas.geojson',
    output_dir='damage_assessment',
    country='us',
    packs=['building', 'damage_classifications', 'damage'],   # geometry + damage classes
    since='2024-07-08',             # date range of the event
    until='2024-07-11',
    rapid=True,                     # Permit use of rapid post-catastrophe imagery (e.g. during an event)
    include=['damage'],             # Adds the damage classification score (FEMA-style damage classification levels on a 5-point scale)
    save_features=True,
)
exporter.run()

rapid=True enables consideration of post-catastrophe rapid-response surveys (when available). The damage pack has variants (damage_postcat, damage_non_postcat) for damage-related feature classes; damage_classifications is the richer pack used here, exposing ten damage feature classes (Roof, Missing Roof Tile or Shingle, Vegetation Debris, Junk and Wreckage, Building Structural Loss, Roof with Temporary Repair, Structural Damage, Building Damage by Tree, Building with Structural Damage, Building lifecycle). The damage classification score is a separate quantity, retrieved by passing include=['damage'] — see the auto-generated README in your export's final/ directory for what each emitted column contains.

Roof Age Analysis (US Only)

Predict roof installation dates using AI analysis of historical imagery, combined with building permits and climate data. Recommended approach — unified with the Feature API in one export:

exporter = NearmapAIExporter(
    aoi_file='properties.geojson',
    output_dir='unified_results',
    country='us',
    packs=['building', 'building_structures'],
    roof_age=True,                # add Roof Age API predictions
    save_features=True,
)
exporter.run()

You can also use the standalone exporter if you only need roof age data (no Feature API calls):

from nmaipy.roof_age_exporter import RoofAgeExporter

exporter = RoofAgeExporter(
    aoi_file='properties.geojson',
    output_dir='roof_age_results',
    country='us',
    threads=10,
    output_format='both',         # GeoParquet and CSV
)
exporter.run()

Dataset selection: pass roof_age_dataset='latest' (default — pointer maintained by the Nearmap team), 'A.0', 'A.1', or any raw resource UUID. Historical "as-of" queries: combine with since / until to ask "what was this roof like in the past?" — these drive the API's sinceAsOfDate / untilAsOfDate body parameters. Note: --until / --since are not supported on the A.0 dataset and are rejected client-side with a clear error.

Each roof carries:

  • Predicted installation date
  • Confidence score (trust signal)
  • Evidence type and number of imagery captures analysed
  • Timeline of all imagery used

Useful for insurance underwriting, property valuation, maintenance planning, and real-estate due diligence.

Wildfire Risk & Defensible Space

Assess wildfire vulnerability with defensible space analysis around structures — per-zone metrics and per-class risk object breakdowns (vegetation, neighbouring roofs, yard debris) across three concentric zones (0-indexed, matching the CalFire convention):

exporter = NearmapAIExporter(
    aoi_file='properties.geojson',
    output_dir='wildfire_risk',
    country='us',
    packs=['building'],
    include=['defensibleSpace', 'wildfireScore'],
    save_features=True,
)
exporter.run()

Output includes per-zone metrics (zone area, defensible-space area, coverage ratio) and per-class risk-object breakdowns for both the primary roof and the aggregate parcel.

Roof Condition (RSI) with Structural Damage Fallback

Extract Roof Spotlight Index scores that automatically resolve the best RSI per roof — using the roof's own score when available, or falling back to the Building Lifecycle score when structural damage is present:

exporter = NearmapAIExporter(
    aoi_file='properties.geojson',
    output_dir='rsi_results',
    country='us',
    packs=['building', 'building_structures'],
    include=['roofSpotlightIndex'],
    save_features=True,
)
exporter.run()

The building_structures pack provides the Building Lifecycle features needed for the fallback. Without it, RSI is only available from roofs that have no structural damage.

3D-first exports with 2D fallback (prefer3d)

When you want maximum 3D attribute coverage in a single unified export — without losing AOIs that only have 2D coverage in your date window — use prefer3d=True. The exporter runs the bulk request as if only3d=True, then transparently retries each AOI that returned no 3D survey with only3d=False:

exporter = NearmapAIExporter(
    aoi_file='properties.geojson',
    output_dir='unified_3d_results',
    country='us',
    packs=['building', 'building_char', 'roof_char'],
    prefer3d=True,
    save_features=True,
)
exporter.run()

The output rollup carries a mesh_date column — non-empty when the row used a 3D survey, empty when it fell back to 2D. Mutually exclusive with only3d. No-op for AOIs pinned to a survey_resource_id (the survey is already chosen).

Discovering available AI Features

Packs and feature classes are not hard-coded — your account's available packs (and their classes) are returned by the API. List them programmatically:

from nmaipy.feature_api import FeatureApi

api = FeatureApi()  # uses API_KEY env var

# Dict of pack code -> list of feature class UUIDs your account can query
packs = api.get_packs()
print(sorted(packs.keys()))

# DataFrame of feature classes (rich metadata: description, type, perspective, etc.)
classes = api.get_feature_classes()
print(classes[["description", "type"]].head())

# Filter to a specific pack
building_classes = api.get_feature_classes(packs=["building"])

Commonly available packs (this list is not exhaustive):

Pack Description
building Building footprints and heights
building_char Detailed building characteristics
roof_char Detailed roof characteristics (material, shape, etc.)
vegetation Trees and vegetation coverage
surfaces Ground surface materials
pools Swimming pool detection
solar Solar panel detection
damage / damage_postcat / damage_non_postcat Damage classification (post-catastrophe and lifecycle)

For the full catalog and access details, use the snippet above or check the Nearmap help site.

Input Data Formats

nmaipy accepts AOIs in:

  • GeoJSON — standard geospatial polygons
  • GeoPackage (.gpkg) — OGC standard
  • Parquet / GeoParquet — efficient columnar format for large datasets
  • CSV / TSV / PSV — text format with a geometry column containing WKT polygons

Your file should contain polygons representing the areas you want to analyse — parcels, mesh blocks, census blocks, suburbs, statistical areas, custom regions, etc. An aoi_id column identifies each row; if absent, sequential IDs are generated. Optional per-row since / until (string-typed) and survey_resource_id columns override bulk values per-AOI.

Output Data

The exporter writes results to {output_dir}/final/:

File Description
rollup.csv or .parquet One row per AOI with summary statistics (counts, areas, primary-feature attributes, scores, metadata)
rollup_data_dictionary.csv Customer-readable data dictionary for every column in rollup
{class}.csv Per-class attribute tables (e.g. roof.csv, building.csv, swimming_pool.csv, solar_panel.csv, roof_instance.csv, building_lifecycle.csv)
{class}_data_dictionary.csv Data dictionary for each per-class file
{class}_features.parquet Per-class GeoParquet with feature geometries (when save_features=True)
features.parquet All features combined as GeoParquet (when save_features=True)
feature_api_errors.csv AOIs where the Feature API returned errors (with status code and message)
roof_age_errors.csv AOIs where the Roof Age API returned errors (US only)
classes_availability.json Per-class availability metadata for the resolved system version
latency_stats.csv API latency diagnostics (P50, P90, P95, P99)
export_config.json Full record of export parameters and nmaipy version, used by the fast-path re-invocation detector
README.md Auto-generated, customer-readable README — column tables grouped by section, class hierarchy diagram, primary-feature selection explainer, full data dictionary for the export

A {output_dir}/chunks/ directory holds intermediate per-chunk results during processing and enables resume after interruption.

For column-level documentation, open final/README.md from your export — it always reflects exactly what's in the files (including any 3D / prefer3d / pack-specific columns).

S3 Output Support

Pass an s3:// URI as output_dir to write directly to Amazon S3:

exporter = NearmapAIExporter(
    aoi_file='properties.geojson',
    output_dir='s3://my-bucket/nmaipy-results/',
    country='us',
    packs=['building'],
)
exporter.run()

AWS credentials are resolved from environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) or ~/.aws/credentials. The cache_dir parameter also accepts S3 URIs, though local caching is faster for iterative development.

Working with Large Areas

Any AOI larger than 1 km² is automatically gridded — split into ~200 m cells, processed in parallel, then recombined and deduplicated. No configuration needed for the common case:

exporter = NearmapAIExporter(
    aoi_file='large_region.geojson',
    output_dir='large_area_results',
    country='us',
    packs=['building'],
    processes=16,
)
exporter.run()

By default, gridded AOIs require every cell to succeed (aoi_grid_min_pct=100). Use a lower value to allow partial coverage at the cost of mixing survey dates within an AOI; set aoi_grid_inexact=True to silence the multi-date warning.

Performance Tips

  1. Parallel processing: set processes to roughly the number of CPU cores available.
  2. Tune chunk size: chunk_size (default 500) groups AOIs per parallel work unit. Smaller = finer parallelism and cheaper resume; larger = lower overhead.
  3. Cache API responses: cache_dir persists API responses to a directory. Re-runs with the same parameters reuse the cache. Defaults to {output_dir}/cache/.
  4. Filter by date: since / until restrict to specific time periods and reduce data volume.
  5. Fast-path re-invocation: if final/README.md and export_config.json already exist and the config matches the current call, the exporter returns in ~1s instead of rebuilding. Pure perf knobs (processes, threads, chunk_size, cache_dir) are ignored when comparing configs.

Command Line Interface

Every Python API option has a CLI equivalent. See python nmaipy/exporter.py --help for the full list. Highlights:

python nmaipy/exporter.py \
    --aoi-file "parcels.geojson" \
    --output-dir "results" \
    --country us \
    --packs building vegetation \
    --save-features \
    --roof-age

Key options:

Flag What it does
--packs AI packs to extract (building, vegetation, surfaces, pools, solar, damage, etc.)
--include Additional calculated includes (roofSpotlightIndex, defensibleSpace, hurricaneScore, windScore, hailScore, wildfireScore, windHailRisk)
--roof-age Include Roof Age API data (US only)
--roof-age-dataset latest (default), A.0, A.1, or any raw resource UUID
--prefer3d Prefer 3D surveys, fall back to 2D per AOI when no 3D coverage exists in the window. Mutually exclusive with --only3d
--only3d Restrict every query to 3D surveys (no fallback)
--system-version-prefix Restrict to a specific AI generation (e.g. gen6-)
--system-version Pin to an exact version (e.g. gen6-glowing_grove-1.0)
--rapid Consider rapid post-catastrophe surveys (damage workflows)
--since / --until Filter by survey date range (YYYY-MM-DD). Per-AOI columns override per-row. With --roof-age, drives sinceAsOfDate / untilAsOfDate for historical roof state
--save-features Save per-class GeoParquet files with feature geometries
--tabular-file-format csv (default) or parquet for rollup and per-class attribute files
--primary-decision Feature selection method: largest_intersection, nearest, or optimal
--cache-dir / --no-cache Persist API responses to a directory / disable caching
--max-retries Maximum API retry attempts (default 10)
--api-key Override the API_KEY env var

Standalone Roof Age Export (US Only)

If you only need roof age data with no Feature API calls:

python -m nmaipy.roof_age_exporter \
    --aoi-file "us_properties.geojson" \
    --output-dir "roof_age_results" \
    --country us \
    --processes 4 \
    --output-format both

Accepts the same --roof-age-dataset, --until, --since flags as the unified exporter (with the same A.0-dataset rejection rule). See python -m nmaipy.roof_age_exporter --help for all options.

Examples

  • run_10_test.py — the 10-property smoke test described in Quick Start.
  • examples.py — working examples covering building / vegetation extraction, damage assessment, multi-pack urban planning, vegetation analysis, pool detection, large-area gridding, time-series, and unified roof age.
  • data/examples/ — sample AOI files:
    • sydney_parcels.geojson — Sydney CBD, AU
    • us_parcels.geojson — Austin, TX
    • large_area.geojson — 2 km × 2 km Melbourne (triggers auto-gridding)
  • notebooks/Coverage_Checker.ipynb — Jupyter notebook for coverage checking.

Requirements

  • Python 3.12+
  • Nearmap API key (contact Nearmap for access)
  • Memory: assume ~1 GB per process for large exports. The default processes=N (CPU count) on a 16-core box with chunk_size=500 typically uses 10–20 GB.
  • AWS credentials (only if writing to S3)

Getting Help

  • Issues / feature requests: GitHub
  • API key & access: contact Nearmap
  • Column-level documentation: open final/README.md inside your export's output directory

License

See LICENSE for details.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nmaipy-5.0.11.tar.gz (233.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nmaipy-5.0.11-py3-none-any.whl (235.9 kB view details)

Uploaded Python 3

File details

Details for the file nmaipy-5.0.11.tar.gz.

File metadata

  • Download URL: nmaipy-5.0.11.tar.gz
  • Upload date:
  • Size: 233.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for nmaipy-5.0.11.tar.gz
Algorithm Hash digest
SHA256 c5304b3341256034cf29ed7dd6e0cf17c45a74962e60eab352cdcfd0aa7585b2
MD5 67519b6db43d60e991cadca43f1029aa
BLAKE2b-256 8d2c1bb07e830bc32f56503dd48c76e2ae3a7b80ec2ee012803f00b210103967

See more details on using hashes here.

File details

Details for the file nmaipy-5.0.11-py3-none-any.whl.

File metadata

  • Download URL: nmaipy-5.0.11-py3-none-any.whl
  • Upload date:
  • Size: 235.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for nmaipy-5.0.11-py3-none-any.whl
Algorithm Hash digest
SHA256 a455a2edc6df2a861c412068f77ac938615074152bdeaec6f5dd444e77ea1d29
MD5 0ef685dce4045720767b65cbba31f75b
BLAKE2b-256 28174fd0f0490e1c7b4a197e01a0b3d93939ea5d1ca119e6f2d1b28a76399ffe

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page