Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved formatting of notes section of METAR parser #1908

Merged
merged 3 commits into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/api/references.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,9 @@ References
.. [WMO8] WMO, 2018: Guide to Meteorological Instruments and Methods of Observation.
`WMO No.8 <https://library.wmo.int/doc_num.php?explnum_id=10616>`_.

.. [WMO306] WMO, 2011: Manual on Codes - International Codes, Volume I.1, Annex II to the WMO
Technical Regulations: Part A - Alphanumeric Codes. `WMO No.306
<https://library.wmo.int/index.php?lvl=notice_display&id=13617>`_.

.. [WMO1966] WMO, 1966: International Meteorological Tables, `WMO-No. 188.TP.94
<https://library.wmo.int/doc_num.php?explnum_id=7997>`_.
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ per-file-ignores = examples/*.py: D MPY001 T003 T001
src/metpy/deprecation.py: C801
src/metpy/calc/*.py: RST306
src/metpy/interpolate/*.py: RST306
src/metpy/io/*.py: RST306
src/metpy/future.py: RST307
src/metpy/constants.py: RST306
docs/doc-server.py: T001
Expand Down
188 changes: 101 additions & 87 deletions src/metpy/io/metar.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@
'dew_point_temperature': 'degC',
'altimeter': 'inHg',
'air_pressure_at_sea_level': 'hPa',
'present_weather': None,
'past_weather': None,
'past_weather2': None}
'current_wx1_symbol': None,
'current_wx2_symbol': None,
'current_wx3_symbol': None}


@exporter.export
Expand Down Expand Up @@ -87,33 +87,39 @@ def parse_metar_to_dataframe(metar_text, *, year=None, month=None):
Notes
-----
The output has the following columns:
'station_id': Station Identifier (ex. KLOT)
'latitude': Latitude of the observation, measured in degrees
'longitude': Longitude of the observation, measured in degrees
'elevation': Elevation of the observation above sea level, measured in meters
'date_time': Date and time of the observation, datetime object
'wind_direction': Direction the wind is coming from, measured in degrees
'wind_spd': Wind speed, measured in knots
'current_wx1': Current weather (1 of 3)
'current_wx2': Current weather (2 of 3)
'current_wx3': Current weather (3 of 3)
'skyc1': Sky cover (ex. FEW)
'skylev1': Height of sky cover 1, measured in feet
'skyc2': Sky cover (ex. OVC)
'skylev2': Height of sky cover 2, measured in feet
'skyc3': Sky cover (ex. FEW)
'skylev3': Height of sky cover 3, measured in feet
'skyc4': Sky cover (ex. CLR)
'skylev4:': Height of sky cover 4, measured in feet
'cloudcover': Cloud coverage measured in oktas, taken from maximum of sky cover values
'temperature': Temperature, measured in degrees Celsius
'dewpoint': Dew point, measured in degrees Celsius
'altimeter': Altimeter value, measured in inches of mercury, float
'current_wx1_symbol': Current weather symbol (1 of 3), integer
'current_wx2_symbol': Current weather symbol (2 of 3), integer
'current_wx3_symbol': Current weather symbol (3 of 3), integer
'sea_level_pressure': Sea level pressure, derived from temperature, elevation
and altimeter value, float

* 'station_id': Station Identifier (ex. KLOT)
* 'latitude': Latitude of the observation, measured in degrees
* 'longitude': Longitude of the observation, measured in degrees
* 'elevation': Elevation of the observation above sea level, measured in meters
* '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
* 'current_wx1': Current weather (1 of 3)
* 'current_wx2': Current weather (2 of 3)
* 'current_wx3': Current weather (3 of 3)
* 'low_cloud_type': Low-level sky cover (ex. FEW)
* 'low_cloud_level': Height of low-level sky cover, measured in feet
* 'medium_cloud_type': Medium-level sky cover (ex. OVC)
* 'medium_cloud_level': Height of medium-level sky cover, measured in feet
* 'high_cloud_type': High-level sky cover (ex. FEW)
* 'high_cloud_level': Height of high-level sky cover, measured in feet
* 'highest_cloud_type': Highest-level Sky cover (ex. CLR)
* 'highest_cloud_level:': Height of highest-level sky cover, measured in feet
* 'cloud_coverage': Cloud cover measured in oktas, taken from maximum of sky cover values
* 'air_temperature': Temperature, measured in degrees Celsius
* 'dew_point_temperature': Dew point, measured in degrees Celsius
* 'altimeter': Altimeter value, measured in inches of mercury
* 'current_wx1_symbol': Current weather symbol (1 of 3), WMO integer code from [WMO306]_
Attachment IV
* 'current_wx2_symbol': Current weather symbol (2 of 3), WMO integer code from [WMO306]_
Attachment IV
* 'current_wx3_symbol': Current weather symbol (3 of 3), WMO integer code from [WMO306]_
Attachment IV
* 'air_pressure_at_sea_level': Sea level pressure, derived from temperature, elevation
and altimeter value
* 'eastward_wind': Eastward component (u-compoment) of the wind vector, measured in knots
* 'northward_wind': Northward component (v-compoment) of the wind vector, measured in knots

"""
# Defaults year and/or month to present reported date if not provided
Expand Down Expand Up @@ -149,9 +155,9 @@ def parse_metar_to_dataframe(metar_text, *, year=None, month=None):
'air_temperature': metar_vars.temperature,
'dew_point_temperature': metar_vars.dewpoint,
'altimeter': metar_vars.altimeter,
'present_weather': metar_vars.current_wx1_symbol,
'past_weather': metar_vars.current_wx2_symbol,
'past_weather2': metar_vars.current_wx3_symbol},
'current_wx1_symbol': metar_vars.current_wx1_symbol,
'current_wx2_symbol': metar_vars.current_wx2_symbol,
'current_wx3_symbol': metar_vars.current_wx3_symbol},
index=[metar_vars.station_id])

# Convert to sea level pressure using calculation in metpy.calc
Expand Down Expand Up @@ -203,33 +209,35 @@ def parse_metar_to_named_tuple(metar_text, station_metadata, year, month):
Notes
-----
Returned data has named tuples with the following attributes:
'station_id': Station Identifier (ex. KLOT)
'latitude': Latitude of the observation, measured in degrees
'longitude': Longitude of the observation, measured in degrees
'elevation': Elevation of the observation above sea level, measured in meters
'date_time': Date and time of the observation, datetime object
'wind_direction': Direction the wind is coming from, measured in degrees
'wind_spd': Wind speed, measured in knots
'current_wx1': Current weather (1 of 3)
'current_wx2': Current weather (2 of 3)
'current_wx3': Current weather (3 of 3)
'skyc1': Sky cover (ex. FEW)
'skylev1': Height of sky cover 1, measured in feet
'skyc2': Sky cover (ex. OVC)
'skylev2': Height of sky cover 2, measured in feet
'skyc3': Sky cover (ex. FEW)
'skylev3': Height of sky cover 3, measured in feet
'skyc4': Sky cover (ex. CLR)
'skylev4:': Height of sky cover 4, measured in feet
'cloudcover': Cloud coverage measured in oktas, taken from maximum of sky cover values
'temperature': Temperature, measured in degrees Celsius
'dewpoint': Dewpoint, measured in degrees Celsius
'altimeter': Altimeter value, measured in inches of mercury, float
'current_wx1_symbol': Current weather symbol (1 of 3), integer
'current_wx2_symbol': Current weather symbol (2 of 3), integer
'current_wx3_symbol': Current weather symbol (3 of 3), integer
'sea_level_pressure': Sea level pressure, derived from temperature, elevation
and altimeter value, float

* 'station_id': Station Identifier (ex. KLOT)
* 'latitude': Latitude of the observation, measured in degrees
* 'longitude': Longitude of the observation, measured in degrees
* 'elevation': Elevation of the observation above sea level, measured in meters
* '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
* 'current_wx1': Current weather (1 of 3)
* 'current_wx2': Current weather (2 of 3)
* 'current_wx3': Current weather (3 of 3)
* 'skyc1': Sky cover (ex. FEW)
* 'skylev1': Height of sky cover 1, measured in feet
* 'skyc2': Sky cover (ex. OVC)
* 'skylev2': Height of sky cover 2, measured in feet
* 'skyc3': Sky cover (ex. FEW)
* 'skylev3': Height of sky cover 3, measured in feet
* 'skyc4': Sky cover (ex. CLR)
* 'skylev4:': Height of sky cover 4, measured in feet
* 'cloudcover': Cloud coverage measured in oktas, taken from maximum of sky cover values
* 'temperature': Temperature, measured in degrees Celsius
* 'dewpoint': Dewpoint, measured in degrees Celsius
* 'altimeter': Altimeter value, measured in inches of mercury
* 'current_wx1_symbol': Current weather symbol (1 of 3), WMO integer code from [WMO306]_
Attachment IV
* 'current_wx2_symbol': Current weather symbol (2 of 3), WMO integer code from [WMO306]_
Attachment IV
* 'current_wx3_symbol': Current weather symbol (3 of 3), WMO integer code from [WMO306]_
Attachment IV

"""
# Decode the data using the parser (built using Canopy) the parser utilizes a grammar
Expand Down Expand Up @@ -453,33 +461,39 @@ def parse_metar_file(filename, *, year=None, month=None):
Notes
-----
The returned `pandas.DataFrame` has the following columns:
'station_id': Station Identifier (ex. KLOT)
'latitude': Latitude of the observation, measured in degrees
'longitude': Longitude of the observation, measured in degrees
'elevation': Elevation of the observation above sea level, measured in meters
'date_time': Date and time of the observation, datetime object
'wind_direction': Direction the wind is coming from, measured in degrees
'wind_spd': Wind speed, measured in knots
'current_wx1': Current weather (1 of 3)
'current_wx2': Current weather (2 of 3)
'current_wx3': Current weather (3 of 3)
'skyc1': Sky cover (ex. FEW)
'skylev1': Height of sky cover 1, measured in feet
'skyc2': Sky cover (ex. OVC)
'skylev2': Height of sky cover 2, measured in feet
'skyc3': Sky cover (ex. FEW)
'skylev3': Height of sky cover 3, measured in feet
'skyc4': Sky cover (ex. CLR)
'skylev4:': Height of sky cover 4, measured in feet
'cloudcover': Cloud coverage measured in oktas, taken from maximum of sky cover values
'temperature': Temperature, measured in degrees Celsius
'dewpoint': Dew point, measured in degrees Celsius
'altimeter': Altimeter value, measured in inches of mercury, float
'current_wx1_symbol': Current weather symbol (1 of 3), integer
'current_wx2_symbol': Current weather symbol (2 of 3), integer
'current_wx3_symbol': Current weather symbol (3 of 3), integer
'sea_level_pressure': Sea level pressure, derived from temperature, elevation
and altimeter value, float

* 'station_id': Station Identifier (ex. KLOT)
* 'latitude': Latitude of the observation, measured in degrees
* 'longitude': Longitude of the observation, measured in degrees
* 'elevation': Elevation of the observation above sea level, measured in meters
* '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
* 'current_wx1': Current weather (1 of 3)
* 'current_wx2': Current weather (2 of 3)
* 'current_wx3': Current weather (3 of 3)
* 'low_cloud_type': Low-level sky cover (ex. FEW)
* 'low_cloud_level': Height of low-level sky cover, measured in feet
* 'medium_cloud_type': Medium-level sky cover (ex. OVC)
* 'medium_cloud_level': Height of medium-level sky cover, measured in feet
* 'high_cloud_type': High-level sky cover (ex. FEW)
* 'high_cloud_level': Height of high-level sky cover, measured in feet
* 'highest_cloud_type': Highest-level Sky cover (ex. CLR)
* 'highest_cloud_level:': Height of highest-level sky cover, measured in feet
* 'cloud_coverage': Cloud cover measured in oktas, taken from maximum of sky cover values
* 'air_temperature': Temperature, measured in degrees Celsius
* 'dew_point_temperature': Dew point, measured in degrees Celsius
* 'altimeter': Altimeter value, measured in inches of mercury
* 'current_wx1_symbol': Current weather symbol (1 of 3), WMO integer code from [WMO306]_
Attachment IV
* 'current_wx2_symbol': Current weather symbol (2 of 3), WMO integer code from [WMO306]_
Attachment IV
* 'current_wx3_symbol': Current weather symbol (3 of 3), WMO integer code from [WMO306]_
Attachment IV
* 'air_pressure_at_sea_level': Sea level pressure, derived from temperature, elevation
and altimeter value
* 'eastward_wind': Eastward component (u-compoment) of the wind vector, measured in knots
* 'northward_wind': Northward component (v-compoment) of the wind vector, measured in knots

"""
# Defaults year and/or month to present reported date if not provided
Expand Down
7 changes: 3 additions & 4 deletions src/metpy/plots/wx_symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: BSD-3-Clause
"""Simplify using the weather symbol font.

See WMO manual 485 Vol 1 for more info on the symbols.
See WMO No.306 Attachment IV for more info on the symbols.
"""

try:
Expand Down Expand Up @@ -185,9 +185,8 @@ def alt_char(self, code, alt):
#####################################################################
# This dictionary is for mapping METAR present weather text codes
# to WMO codes for plotting wx symbols along with the station plots.
# Pages II-4-3 and II-4-4 of this document describes the difference between
# manned and automated stations:
# https://github.com/Unidata/MetPy/files/1151142/485_Vol_I_en.pdf
# See Attachment IV of WMO No.306 for more information:
# https://library.wmo.int/index.php?lvl=notice_display&id=13617
# It may become necessary to add automated station wx_codes in the future,
# but that will also require knowing the status of all stations.

Expand Down
6 changes: 3 additions & 3 deletions tests/io/test_metar.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ def test_missing_values():
assert_almost_equal(df.current_wx1.values, np.nan)
assert_almost_equal(df.current_wx2.values, np.nan)
assert_almost_equal(df.current_wx3.values, np.nan)
assert_almost_equal(df.present_weather.values, 0)
assert_almost_equal(df.past_weather.values, 0)
assert_almost_equal(df.past_weather2.values, 0)
assert_almost_equal(df.current_wx1_symbol.values, 0)
assert_almost_equal(df.current_wx2_symbol.values, 0)
assert_almost_equal(df.current_wx3_symbol.values, 0)
assert_almost_equal(df.low_cloud_type.values, np.nan)
assert_almost_equal(df.medium_cloud_type.values, np.nan)
assert_almost_equal(df.high_cloud_type.values, np.nan)
Expand Down