Predictions Module

The pred module provides access to hourly weather forecasts from AEMet, covering a 3-day horizon. It includes a station registry of ~8,000 Spanish municipalities with nearest-neighbour lookup by coordinates and case-insensitive name search.

Station registry

The module ships with a JSON registry of prediction stations. Data is loaded lazily on first access and cached in memory.

get_predicted_stations returns the full registry:

from aemetxfb.pred import get_predicted_stations

stations = get_predicted_stations()
print(len(stations))  # ~8000
print(stations["id28079"]["name"])  # "Madrid"

Each entry maps a station ID to {"name": ..., "lat": ..., "lon": ...}.

Nearest-station lookup

find_nearest_location() finds the closest station to a pair of coordinates using vectorised numpy operations:

from aemetxfb.pred import find_nearest_location

station_id = find_nearest_location(40.4168, -3.7038)
print(station_id)  # "id28079"

Hourly forecasts

get_forecast() fetches and parses the AEMet hourly forecast XML for a municipality. It accepts either a name (string) or coordinates (lat/lon as floats):

from aemetxfb.pred import get_forecast

# By name
forecast = get_forecast("Madrid")

# By coordinates
forecast = get_forecast(40.4168, -3.7038)

The function returns a Forecast object.

Forecast object

The Forecast class exposes typed getter methods for metadata, sunrise/sunset, hourly variables, and probability blocks.

Metadata

forecast.get_metadata()               # full dict
forecast.get_metadata("name")         # "Madrid"
forecast.get_metadata("province")     # "Madrid"
forecast.get_metadata("id")           # "50130"
forecast.get_metadata("link")         # AEMet web URL

Sunrise and sunset

df = forecast.get_sunrise_sunset()
#    date       sunrise    sunset
# 0 2026-06-24  06:33:00  21:45:00
# 1 2026-06-25  06:33:00  21:45:00
# 2 2026-06-26  06:33:00  21:45:00

Hourly data

# All variables
df = forecast.get_hourly()

# Single variable (aliases accepted)
df = forecast.get_hourly("temperature")
df = forecast.get_hourly("rain")          # alias for precipitation
df = forecast.get_hourly("gust")          # alias for gust_speed
df = forecast.get_hourly("sky")           # alias for sky_description

Available variables:

Column

Aliases

Description

temperature

Air temperature (°C, integer)

apparent_temperature

heat_index

Apparent / perceived temperature (°C, integer)

relative_humidity

humidity

Relative humidity (%)

precipitation

rain

Accumulated precipitation (mm)

snow

Snow depth (cm)

wind_direction

Wind direction (cardinal, e.g. “N”, “SE”)

wind_speed

Wind speed (km/h, integer)

gust_speed

gust

Maximum gust speed (km/h, integer)

sky_code

Sky condition code (e.g. “11”, “12n”)

sky_description

sky, weather

Human-readable sky description

Probability blocks

# All types (wide format)
df = forecast.get_probability()
#    date       period  precipitation  storm  snow
# 0 2026-06-24   0814              0      0     0

# Single type
df = forecast.get_probability("precipitation")
df = forecast.get_probability("storm")       # alias: thunderstorm
df = forecast.get_probability("snow")

Probabilities are given for 6-hour blocks:

Period

Hours

Description

0208

02:00–08:00

Early morning

0814

08:00–14:00

Late morning / early afternoon

1420

14:00–20:00

Afternoon / evening

2002

20:00–02:00

Night

Error handling

  • Name not foundValueError with a clear message.

  • Ambiguous nameValueError listing all matching stations with coordinates (e.g. "Mieres" matches 2 entries).

  • Incomplete coordinatesValueError when only latitude or longitude is provided.

  • Network / parse errorsRuntimeError wrapping the underlying exception.

API reference

See aemetxfb.pred for the full API reference.