Skip to content

Station Search

The StationIndex provides fast searching and filtering of 55,000+ weather station entries from climate.onebuilding.org.

Loading the Index

from idfkit.weather import StationIndex

# Instant load from bundled data (no network needed)
index = StationIndex.load()

print(f"Stations: {len(index)}")
print(f"Countries: {len(index.countries)}")

Search by Name

Fuzzy text search across station names, cities, and WMO numbers:

# Search by name
results = index.search("chicago ohare")

for r in results[:5]:
    print(f"{r.station.display_name} (score={r.score:.2f})")

SearchResult Attributes

Attribute Type Description
station WeatherStation The matching station
score float Match score (0.0 to 1.0)

Search Tips

# City name
results = index.search("New York")

# Airport code pattern
results = index.search("JFK")

# WMO number
results = index.search("725300")

# Country + city
results = index.search("London UK")

Search by Coordinates

Find stations nearest to a location using great-circle distance:

# Nearest to downtown Chicago
results = index.nearest(41.88, -87.63)

for r in results[:5]:
    print(f"{r.station.display_name}: {r.distance_km:.1f} km")

Function Signature

def nearest(
    self,
    latitude: float,
    longitude: float,
    *,
    limit: int = 5,
    max_distance_km: float | None = None,
    country: str | None = None,
) -> list[SpatialResult]:

SpatialResult Attributes

Attribute Type Description
station WeatherStation The nearby station
distance_km float Distance in kilometers

Search by Address

Combine geocode() with nearest() for address-based search:

from idfkit.weather import StationIndex, geocode

index = StationIndex.load()

# One-liner using splat operator
results = index.nearest(*geocode("Willis Tower, Chicago, IL"))

# Or step by step
lat, lon = geocode("350 Fifth Avenue, New York, NY")
results = index.nearest(lat, lon)

Filter by Country

# Get all stations in a country
us_stations = index.filter(country="USA")
print(f"US stations: {len(us_stations)}")

# Get all stations in a state/region
california = [s for s in us_stations if s.state == "CA"]

Filter by Coordinates

Use nearest() with max_distance_km to find stations within a geographic area:

# Find all stations within 100 km of a point
stations = index.nearest(
    41.0,
    -88.5,
    max_distance_km=100.0,
    limit=50,
)

Get by WMO Number

# Get specific station by WMO
results = index.get_by_wmo("725300")

for station in results:
    print(f"{station.display_name}: {station.source}")

Note: WMO numbers are not unique — multiple entries can share a WMO (different year ranges, data sources).

WeatherStation Attributes

Attribute Type Description
city str City/station name
state str State/province/region
country str Country name
wmo str WMO station number
source str Data source identifier (e.g., "SRC-TMYx")
latitude float Station latitude
longitude float Station longitude
timezone float UTC offset (hours from GMT)
elevation float Elevation in meters
url str Download URL for weather files
display_name str Formatted name (city, state, country)

Listing Countries

# Get all available countries
countries = index.countries

for country in sorted(countries)[:10]:
    count = len(index.filter(country=country))
    print(f"{country}: {count} stations")

Refreshing the Index

The bundled index works without network access. To get the latest data:

# Check if upstream has updates
if index.check_for_updates():
    print("Updates available")

    # Refresh from climate.onebuilding.org (requires openpyxl)
    index = StationIndex.refresh()

Refresh requires: pip install idfkit[weather]

Performance

The index uses efficient data structures for fast searching:

Operation Typical Time
load() ~100ms
search(query) ~10ms
nearest(lat, lon) ~50ms
filter(country=...) ~5ms

Best Practices

  1. Load once — Keep the index in memory for multiple searches
  2. Use spatial search — More accurate than name matching for locations
  3. Check multiple results — First result isn't always the best match
  4. Verify WMO — Same physical station may have multiple entries

See Also