Getting Started

Imports

GeoDataAccess.jl does not export symbols by default. Import what you need explicitly:

using GeoDataAccess
using GeoDataAccess: DataAccessPlan, fetch, MetaData
using Dates

Discovering Sources

GeoDataAccess ships with several data sources. Use all_sources and available_sources to see what’s registered:

all_sources()
13-element Vector{GeoDataAccess.AbstractDataSource}:
 OpenMeteoArchive()
 OpenMeteoForecast()
 NOAANCEI("daily-summaries")
 NASAPower()
 TomorrowIO()
 VisualCrossing()
 GeoDataAccess.USGSEarthquake()
 USGSWaterServices("dv")
 GeoDataAccess.OpenAQ()
 GeoDataAccess.NASAFIRMS()
 GeoDataAccess.EPAAQS()
 GeoDataAccess.NOAAGFS()
 GeoDataAccess.ERA5()
# Only sources you can use right now (API key set or not required)
available_sources()
7-element Vector{GeoDataAccess.AbstractDataSource}:
 OpenMeteoArchive()
 OpenMeteoForecast()
 NOAANCEI("daily-summaries")
 NASAPower()
 GeoDataAccess.USGSEarthquake()
 USGSWaterServices("dv")
 GeoDataAccess.NOAAGFS()

Every source carries a MetaData record describing its coverage, resolution, variables, and access requirements:

MetaData(NASAPower())
MetaData("", "No published rate limit", :weather, Dict(:WD2M => "Wind direction at 2m (°)", :PRECTOTCORR => "Precipitation corrected (mm/day)", :CLOUD_AMT => "Cloud amount (%)", :CLRSKY_SFC_SW_DWN => "Clear-sky surface shortwave downward irradiance (MJ/m²/day)", :ALLSKY_SFC_SW_DWN => "All-sky surface shortwave downward irradiance (MJ/m²/day)", :RH2M => "Relative humidity at 2m (%)", :WS10M => "Wind speed at 10m (m/s)", :ALLSKY_SFC_LW_DWN => "All-sky surface longwave downward irradiance (W/m²)", :WD10M => "Wind direction at 10m (°)", :WS2M => "Wind speed at 2m (m/s)"…), :raster, "55 km", "Global", :timeseries, Day(1), "1981-present", "Open Data (NASA)", "https://power.larc.nasa.gov/docs/services/api/", Dict("DataFrames" => "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"))
MetaData(OpenMeteoArchive())
MetaData("", "10,000 calls/day (non-commercial)", :weather, Dict(:temperature_2m_mean => "Daily mean temperature at 2m (°C)", :wind_direction_10m_dominant => "Daily dominant wind direction (°)", :apparent_temperature_max => "Daily maximum apparent temperature (°C)", :surface_pressure => "Surface pressure (hPa)", :precipitation_sum => "Daily total precipitation (mm)", :wind_gusts_10m_max => "Daily maximum wind gusts at 10m (km/h)", :precipitation_hours => "Daily hours with precipitation", :temperature_2m => "Air temperature at 2m (°C)", :rain_sum => "Daily total rain (mm)", :wind_direction_10m => "Wind direction at 10m (°)"…), :raster, "25 km", "Global", :timeseries, Hour(1), "1940-present", "CC BY 4.0", "https://open-meteo.com/en/docs/historical-weather-api", Dict("DataFrames" => "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"))

Plan / Fetch Workflow

Every data request follows two steps:

  1. PlanDataAccessPlan(source, extent, start_date, stop_date; kw...) builds a plan describing the API calls that will be made, without executing them.
  2. Fetchfetch(plan) executes the plan, downloads data, and returns file paths to cached JSON files.

The interface is the same regardless of which source you choose.

Step 1: Create a Plan

Pass a data source, a location (longitude, latitude), a date range, and the variables you want. Each source has its own variable names — check its MetaData or documentation page for the list.

# NASA POWER — daily temperature and precipitation
plan = DataAccessPlan(NASAPower(), (-74.0, 40.7),
    Date(2024, 7, 1), Date(2024, 7, 14);
    variables = [:T2M, :PRECTOTCORR])
DataAccessPlan for nasapower
  Extent:    Point(40.7, -74.0)
  Time:      2024-07-01 to 2024-07-14 (14 days)
  Variables: T2M, PRECTOTCORR
  community: AG
  query_type: point
  API calls: 1
  Est. size: 224 bytes

  Request 1: GET Point(40.7, -74.0), 14 days → nasapower/f4aeeed25010a44.json

The plan shows you exactly what will be fetched — number of API calls, estimated size, time range, and variables — before any network requests are made.

Step 2: Fetch the Data

files = fetch(plan)
1-element Vector{String}:
 "/home/runner/.julia/scratchspac" ⋯ 60 bytes ⋯ "nasapower/f4aeeed25010a44.json"

fetch returns a vector of file paths to cached JSON files. Read them with JSON.jl:

using JSON

data = JSON.parsefile(files[1])
collect(keys(data))
7-element Vector{String}:
 "type"
 "geometry"
 "properties"
 "header"
 "messages"
 "parameters"
 "times"

Shortcut: fetch Directly

You can also skip the plan and call fetch directly on a source:

files = fetch(NASAPower(), (-74.0, 40.7),
    Date(2024, 7, 1), Date(2024, 7, 14);
    variables = [:T2M, :PRECTOTCORR])
1-element Vector{String}:
 "/home/runner/.julia/scratchspac" ⋯ 60 bytes ⋯ "nasapower/f4aeeed25010a44.json"

Same Workflow, Any Source

The plan/fetch pattern works identically across all sources. Only the source constructor and variable names change:

# Open-Meteo Archive — hourly data with different variable names
plan = DataAccessPlan(OpenMeteoArchive(), (-74.0, 40.7),
    Date(2024, 7, 1), Date(2024, 7, 14);
    variables = [:temperature_2m, :precipitation],
    frequency = :hourly)
DataAccessPlan for openmeteoarchive
  Extent:    Point(40.7, -74.0)
  Time:      2024-07-01 to 2024-07-14 (14 days)
  Variables: temperature_2m, precipitation
  frequency: hourly
  timezone: GMT
  API calls: 1
  Est. size: 5.250 KiB

  Request 1: GET 1 point(s), hourly 14 days → openmeteoarchive/d24c1282ace1ab86.json
# NOAA NCEI — station-based, requires station IDs
plan = DataAccessPlan(NOAANCEI(), (-74.0, 40.7),
    Date(2024, 7, 1), Date(2024, 7, 14);
    stations = ["USW00094728"],
    variables = [:TMAX, :TMIN, :PRCP])
DataAccessPlan for noaancei
  Extent:    1 station(s): USW00094728
  Time:      2024-07-01 to 2024-07-14 (14 days)
  Variables: TMAX, TMIN, PRCP
  stations: ["USW00094728"]
  API calls: 1
  Est. size: 336 bytes

  Request 1: GET 1 station(s), 14 days → noaancei/a0665c46cb739385.json

See the Data Sources section in the sidebar for source-specific details, examples, and variable listings.

Example: Comparing Sources

Fetch daily temperature from two independent sources for the same location and overlay them:

using CairoMakie

# NASA POWER
files_power = fetch(NASAPower(), (-74.0, 40.7),
    Date(2024, 7, 1), Date(2024, 7, 14);
    variables = [:T2M])
power = JSON.parsefile(files_power[1])
power_temps = collect(values(power["properties"]["parameter"]["T2M"]))
power_dates = Date.(collect(keys(power["properties"]["parameter"]["T2M"])), "yyyymmdd")

# Open-Meteo Archive
files_meteo = fetch(OpenMeteoArchive(), (-74.0, 40.7),
    Date(2024, 7, 1), Date(2024, 7, 14);
    variables = [:temperature_2m_mean], frequency = :daily)
meteo = JSON.parsefile(files_meteo[1])
meteo_temps = meteo["daily"]["temperature_2m_mean"]
meteo_dates = Date.(meteo["daily"]["time"])

fig = Figure(size=(700, 350))
ax = Axis(fig[1, 1];
    xlabel="Date", ylabel="Temperature (°C)",
    title="Daily Mean Temperature — NYC, July 2024",
    xticklabelrotation=pi/4)
lines!(ax, power_dates, power_temps; label="NASA POWER", linewidth=2)
lines!(ax, meteo_dates, meteo_temps; label="Open-Meteo (ERA5)", linewidth=2)
axislegend(ax; position=:lb, framevisible=false)
fig

GeoInterface Integration

DataAccessPlan accepts any GeoInterface.jl-compatible geometry as the spatial extent. The geometry type determines how coordinates are sent to the API:

Geometry Behavior
Point / Tuple Single coordinate query
MultiPoint One query per point
LineString One query per vertex
Polygon Bounding box / corner point queries
Extent Bounding box / corner point queries

Multi-Point Query

import GeoInterface as GI

mp = GI.MultiPoint([(-74.0, 40.7), (-87.6, 41.9)])

plan = DataAccessPlan(NASAPower(), mp,
    Date(2024, 1, 1), Date(2024, 1, 7);
    variables = [:T2M])
plan
DataAccessPlan for nasapower
  Extent:    2 points
  Time:      2024-01-01 to 2024-01-07 (7 days)
  Variables: T2M
  community: AG
  query_type: multi_point
  API calls: 2
  Est. size: 112 bytes

  Request 1: GET Point(40.7, -74.0), 7 days → nasapower/c378f65586265649.json
  Request 2: GET Point(41.9, -87.6), 7 days → nasapower/ce8f13f38b3cb8e.json

Extent Query

using GeoInterface.Extents: Extent

ext = Extent(X=(-76.0, -72.0), Y=(39.0, 42.0))

plan = DataAccessPlan(NASAPower(), ext,
    Date(2024, 1, 1), Date(2024, 1, 7);
    variables = [:T2M])
plan
DataAccessPlan for nasapower
  Extent:    Extent(X=(-76.0, -72.0), Y=(39.0, 42.0))
  Time:      2024-01-01 to 2024-01-07 (7 days)
  Variables: T2M
  community: AG
  query_type: regional
  API calls: 1
  Est. size: 56 bytes

  Request 1: GET Regional bbox, 7 days → nasapower/4ec2c52b8c5be1bf.json