Skip to content

US station records with wrong coordinates or region (72273, PFNO0, 72540, KBKL0, KMJX0, KDVP0) #512

Description

@rajeee

Problem

The location or region of several US station records does not match the station named by the record's identifiers.

72273

  • Record: name "Fort Huachuca, Libby Aaf Ft Huachuca", region AZ, location 47.6333, -110.3333, elevation 1438, timezone America/Phoenix.
  • Identifiers: WMO 72273, ICAO KFHU, WBAN 03124, USAF 722730, GHCN USW00003124. All refer to Libby Army Airfield, Sierra Vista, AZ.
  • NCEI location for 722730-03124: 31.58833, -110.34417 (global-hourly/access/2023/72273003124.csv). api.weather.gov/stations/KFHU: [-110.33333, 31.58333].
  • The record location is in Chouteau County, Montana, 1,785 km from the station.
  • The location is unchanged since the first commit of this repository (dc56eb6).

PFNO0

  • Record: name "Noorvik / Andrewsville", region AK, location 38.8495, -75.6128, elevation 20, timezone America/New_York.
  • Identifiers: ICAO PFNO, WBAN 00113, USAF 704898 (Robert Curtis Memorial Airport, Noorvik, AK).
  • api.weather.gov/stations/PFNO: [-161.0223, 66.8175], elevation 17 m, timezone America/Anchorage. NCEI: 66.818, -161.022.
  • The record location is in Kent County, Delaware.

Name and region belong to a different station than the identifiers, coordinates and data

In these four records the name and region are consistent with each other but describe a different place than the ICAO/WBAN/USAF identifiers and the coordinates. The hourly data follows the identifiers: heating degree-days (base 65 °F) of the 2023 hourly series for each id are close to those of stations near the record coordinates and far from those of stations where the name points.

id name / region in record identifiers and coordinates (NCEI ISD) HDD65 2023, this id HDD65 2023 near the name HDD65 2023 near the coordinates
KBKL0 Brookville / Old Chinatown, PA Cleveland Burke Lakefront Airport, OH (KBKL, 725245-04853) 4,549 Jefferson County PA (Brookville): 5,299 Lorain County OH: 5,033
KDVP0 Davenport / Slayton, IA Slayton Municipal Airport, MN (KDVP, 720368-54924) 7,557 Scott County IA (Davenport): 5,320 Nobles County MN: 7,286
KMJX0 Toms River / Dover Forge, NH Ocean County Airport, NJ (KMJX, 720407-00462) 4,177 Rockingham County NH: 5,317 Monmouth County NJ: 4,120
72540 Spickard, MI Spickard, MO (GHCN USC00237963, USAF 725400) 4,890 Ingham County MI: 5,673 Livingston County MO: 4,535

NOAA's ISD station list has a separate historical station "BROOKVILLE FAA AP, PA" (WBAN 14741, 41.15, -79.10, no ICAO), so the KBKL0 name appears to come from a join between that station and Burke Lakefront. NWS and FAA tables list KDVP as Slayton, MN; Davenport, IA is KDVN. There is no Toms River in NH and no Spickard in MI.

Records with mixed identities

  • 72516: name "Bennington / Napoleon", region VT, location 46.4944, -99.7601 (Napoleon, ND), ICAO K5B5, GHCN USW00003761 (Avondale 2 N, PA). The hourly data for this id is consistent with Napoleon, ND.
  • 72555: name "Burwell / Engle", region NE, location 37.3874, -83.2616 (same as KCPF0, Hazard, KY), ICAO KK20, GHCN USW00013301 (Chillicothe 22 ENE, MO).

Effect

Stations().nearby() (1.x) and stations.nearby() (2.x) rank stations by the record location. For points in central Montana, 72273 is returned as the nearest station; for points in Kent County, DE and Caroline County, MD, PFNO0 is. The hourly data served for these ids is from Sierra Vista, AZ and Noorvik, AK. Checked against NCEI: for 2023-07-15, the 72273 series equals 72273003124.csv in 14 of 16 hours to 0.1 °C after the UTC-7 shift; for 2022-01-15, the PFNO0 series and 70489800113.csv are both between -12.2 and -13.3 °C in every hour.

Possible sources of the errors

The records look like joins of several NOAA, NWS and FAA station tables on station codes (ICAO code, FAA identifier, WMO/synop number), without a check that the joined fields describe the same place. What can be traced:

  • 72273: the NWS station table nsd_cccc.txt (tgftp.nws.noaa.gov/data/nsd_cccc.txt; 2015 copy here) contains:

    KFHU;72;273;Fort Huachuca, Libby AAF Ft Huachuca;AZ;United States;4;46-98N;110-20W;;;1438;;
    

    The latitude field "46-98N" has 98 minutes. 46 + 98/60 = 47.6333. The record name, elevation and longitude also match this row. Other projects that parsed this table carry the same value (GitHub code search for "Libby AAF Ft Huachuca"). The NWS API now returns 31.58333 for KFHU.

  • 72516: NWS/AWIPS station tables assign synop number 72516 to "K5B5 Bennington/Wm H Morse State, VT" (for example Unidata/awips2 metarStationInfo.txt: 0000072516|K5B5 | 42.89 | -73.25 | 252|Bennington/Wm H Morse State, VT). The FAA identifier 5B5 now belongs to Napoleon Municipal Airport, ND; Bennington is DDH. A record keyed on K5B5 combines the former holder of the identifier (name, region, synop number) with the current holder (coordinates, elevation, METAR data).

  • PFNO0: the record location 38.8495, -75.6128 is Chorman Airport, Farmington, DE (FAA identifier D74, 38.84955, -75.61278), an airfield without a weather station. How PFNO was joined to D74 is not identified. PFNO is not in the 2015 copy of nsd_cccc.txt.

  • KBKL0, KDVP0: the 2015 nsd_cccc.txt rows are correct (KBKL;--;---;CLEVELAND BURKE LAKEFRONT;OH;...;41-32N;81-40W, KDVP;--;---;Slayton, Slayton Municipal Airport;MN;...), so the names "Brookville" and "Davenport" and the regions PA and IA did not come from that table. The source of the substitution is not identified.

  • KMJX0, 72540, 72555: no source identified. KMJX is not in the 2015 copy of nsd_cccc.txt. The 72555 coordinates equal those of KCPF0 (Hazard, KY).

Import script behaviour

scripts/usa/import.py:

  • find_duplicate() matches an existing record by Meteostat id, then WMO, then ICAO, then proximity within 10 km.
  • If a duplicate is found within 1000 m and 25 m elevation, only the ICAO identifier is updated.
  • If a duplicate is found by identifier and the locations differ by more than 1000 m, nothing is updated and nothing is logged.
  • The loop body is wrapped in except BaseException: pass.

scripts/qa_check.py checks the id length and that latitude and longitude are within ±90 and ±180. It does not compare region with coordinates.

A record with a wrong location is therefore not corrected when the upstream source is corrected.

Possible corrections

  1. Values for the six records, if each record is meant to be the station that its identifiers and hourly data belong to:
file change
stations/72273.json location 31.5883, -110.3442; name "Sierra Vista / Libby Army Airfield"
stations/PFNO0.json location 66.8175, -161.0223; elevation 17; timezone America/Anchorage; name "Noorvik"
stations/72540.json region MO
stations/KBKL0.json region OH; name "Cleveland / Burke Lakefront Airport"
stations/KMJX0.json region NJ
stations/KDVP0.json region MN; name "Slayton"
  1. scripts/usa/import.py: when find_duplicate() matches by identifier and the distance exceeds 1000 m, log the conflict instead of skipping; replace except BaseException: pass with a handler that logs the station id.
duplicate = find_duplicate(data, stations)
if duplicate:
    d = get_distance(lat, lon, duplicate["latitude"], duplicate["longitude"])
    if d <= 1000 and abs(elevation - duplicate["elevation"]) <= 25:
        if data["identifiers"]["icao"]:
            update({"id": duplicate["id"], "identifiers": {"icao": data["identifiers"]["icao"]}})
    else:
        print(f"CONFLICT {duplicate['id']} <- {row['station_id']}: stored "
              f"{duplicate['latitude']},{duplicate['longitude']} vs NWS {lat},{lon} ({d/1000:.0f} km)")
else:
    data["id"] = generate_uid()
    create(data)
  1. scripts/qa_check.py: compare region with coordinates. A bounding box per ISO 3166-2 region is sufficient; over 2,181 US stations this test flags the eight records above and no others. I can help with this if useful.

Related: #469 (72314, fixed in #470), #484 (KLGA/KEWR, fixed in #505).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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