Skip to content

Commit

Permalink
ENH: Add wind gusts to parsed METAR output (Fixes #2075)
Browse files Browse the repository at this point in the history
  • Loading branch information
dopplershift committed Sep 1, 2021
1 parent 5ab290b commit da313d9
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 86 deletions.
4 changes: 2 additions & 2 deletions src/metpy/io/_metar_parser/metar_parser.peg
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ sep <- " "+
siteid <- sep? [0-9A-Z] [0-9A-Z] [0-9A-Z] [0-9A-Z]
datetime <- sep [\d]+ "Z"
auto <- ((sep ("AUTO" / "COR"))+)?
wind <- ((sep? wind_dir wind_spd (gust)? ("KT" / "MPS") varwind?))?
wind <- ((sep? wind_dir wind_spd gust ("KT" / "MPS") varwind?))?
wind_dir <- (([\d] [\d] [\d]) / 'VAR' / 'VRB' / "///")?
wind_spd <- (([\d] [\d] [\d]?) / "//")?
gust <- "G" [\d]+
gust <- ("G" [\d]+)?
varwind <- sep [\d] [\d] [\d] "V" [\d] [\d] [\d]
vis <- ((sep ( ([\d] [\d] [\d] [\d] ("NDV")?) / ([\d] ([\d] / ((" " [\d])? "/" [\d]))? "SM") / ("M" [\d] "/" [\d] "SM") / "CAVOK" / "////") varvis?))?
varvis <- sep [\d] [\d] [\d] [\d] [NSEW]? [NSEW]?
Expand Down
33 changes: 17 additions & 16 deletions src/metpy/io/_metar_parser/metar_parser.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 23 additions & 10 deletions src/metpy/io/metar.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@

# Configure the named tuple used for storing METAR data
Metar = namedtuple('metar', ['station_id', 'latitude', 'longitude', 'elevation', 'date_time',
'wind_direction', 'wind_speed', 'visibility', 'current_wx1',
'current_wx2', 'current_wx3', 'skyc1', 'skylev1', 'skyc2',
'skylev2', 'skyc3', 'skylev3', 'skyc4', 'skylev4', 'cloudcover',
'temperature', 'dewpoint', 'altimeter', 'current_wx1_symbol',
'current_wx2_symbol', 'current_wx3_symbol', 'remarks'])
'wind_direction', 'wind_speed', 'wind_gust', 'visibility',
'current_wx1', 'current_wx2', 'current_wx3', 'skyc1', 'skylev1',
'skyc2', 'skylev2', 'skyc3', 'skylev3', 'skyc4', 'skylev4',
'cloudcover', 'temperature', 'dewpoint', 'altimeter',
'current_wx1_symbol', 'current_wx2_symbol', 'current_wx3_symbol',
'remarks'])

# Create a dictionary for attaching units to the different variables
col_units = {'station_id': None,
Expand All @@ -35,6 +36,7 @@
'date_time': None,
'wind_direction': 'degrees',
'wind_speed': 'kts',
'wind_gust': 'kts',
'visibility': 'meters',
'eastward_wind': 'kts',
'northward_wind': 'kts',
Expand Down Expand Up @@ -117,6 +119,7 @@ def parse_metar(metar_text, year, month, station_metadata=station_info):
* 'date_time': Date and time of the observation, datetime object
* 'wind_direction': Direction the wind is coming from, measured in degrees
* 'wind_speed': Wind speed, measured in knots
* 'wind_gust': Wind gusts, measured in knots
* 'current_wx1': Current weather (1 of 3)
* 'current_wx2': Current weather (2 of 3)
* 'current_wx3': Current weather (3 of 3)
Expand Down Expand Up @@ -175,6 +178,7 @@ def parse_metar(metar_text, year, month, station_metadata=station_info):
date_time = np.nan

# Set the wind values
wind_units = 'kts'
try:
# If there are missing wind values, set wind speed and wind direction to nan
if ('/' in tree.wind.text) or (tree.wind.text == 'KT') or (tree.wind.text == ''):
Expand All @@ -184,7 +188,8 @@ def parse_metar(metar_text, year, month, station_metadata=station_info):
else:
wind_spd = float(tree.wind.wind_spd.text)
if 'MPS' in tree.wind.text:
wind_spd = units.Quantity(wind_spd, 'm/s').m_as('knots')
wind_units = 'm/s'
wind_spd = units.Quantity(wind_spd, wind_units).m_as('knots')
if (tree.wind.wind_dir.text == 'VRB') or (tree.wind.wind_dir.text == 'VAR'):
wind_dir = np.nan
else:
Expand All @@ -194,6 +199,13 @@ def parse_metar(metar_text, year, month, station_metadata=station_info):
wind_dir = np.nan
wind_spd = np.nan

# Parse out the wind gust field
if 'G' in tree.wind.text:
wind_gust = units.Quantity(float(tree.wind.gust.text.strip()[1:]),
wind_units).m_as('knots')
else:
wind_gust = np.nan

# Handle visibility
try:
if tree.vis.text.endswith('SM'):
Expand Down Expand Up @@ -302,10 +314,10 @@ def parse_metar(metar_text, year, month, station_metadata=station_info):
remarks = remarks[3:].strip()

# Returns a named tuple with all the relevant variables
return Metar(station_id, lat, lon, elev, date_time, wind_dir, wind_spd, visibility,
current_wx[0], current_wx[1], current_wx[2], skyc[0], skylev[0], skyc[1],
skylev[1], skyc[2], skylev[2], skyc[3], skylev[3], cloudcover, temp, dewp,
altim, current_wx_symbol[0], current_wx_symbol[1], current_wx_symbol[2],
return Metar(station_id, lat, lon, elev, date_time, wind_dir, wind_spd, wind_gust,
visibility, current_wx[0], current_wx[1], current_wx[2], skyc[0], skylev[0],
skyc[1], skylev[1], skyc[2], skylev[2], skyc[3], skylev[3], cloudcover, temp,
dewp, altim, current_wx_symbol[0], current_wx_symbol[1], current_wx_symbol[2],
remarks)


Expand Down Expand Up @@ -367,6 +379,7 @@ def _metars_to_dataframe(metar_iter, *, year=None, month=None):
* 'date_time': Date and time of the observation, datetime object
* 'wind_direction': Direction the wind is coming from, measured in degrees
* 'wind_speed': Wind speed, measured in knots
* 'wind_gust': Wind gust, measured in knots
* 'visibility': Visibility distance, measured in meters
* 'current_wx1': Current weather (1 of 3)
* 'current_wx2': Current weather (2 of 3)
Expand Down
Loading

0 comments on commit da313d9

Please sign in to comment.