Repository: Unidata/MetPy

Issue:
METAR Parser Documentation Improvement
The notes section for the METAR parser could be improved in getting a better listing of the parameters that come out of the parser.

https://unidata.github.io/MetPy/latest/api/generated/metpy.io.parse_metar_file.html

Currently, the documentation comes out in one continuous paragraph, making it very difficult to decipher the variables and what data they represent.


Discussion:
23ccozad: Docs should now be all lined up for `parse_metar_to_dataframe()`, `parse_metar_to_named_tuple()`, `parse_metar_file()`. But another set of eyes is always helpful, so please let me know if I missed anything.

Patch:
diff --git a/docs/api/references.rst b/docs/api/references.rst
index 3021de45c7..e990023d55 100644
--- a/docs/api/references.rst
+++ b/docs/api/references.rst
@@ -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>`_.
diff --git a/setup.cfg b/setup.cfg
index 2d6eb26eb0..642a869c1b 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -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
diff --git a/src/metpy/io/metar.py b/src/metpy/io/metar.py
index 8274de52b6..23bb8f54b1 100644
--- a/src/metpy/io/metar.py
+++ b/src/metpy/io/metar.py
@@ -55,9 +55,9 @@ col_units = {'station_id': None,
              '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
@@ -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
@@ -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
@@ -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
@@ -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
diff --git a/src/metpy/plots/wx_symbols.py b/src/metpy/plots/wx_symbols.py
index 99f9e98104..c91a621309 100644
--- a/src/metpy/plots/wx_symbols.py
+++ b/src/metpy/plots/wx_symbols.py
@@ -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:
@@ -185,9 +185,8 @@ with exporter:
     #####################################################################
     # 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.
 


Test patch:
diff --git a/tests/io/test_metar.py b/tests/io/test_metar.py
index e29a0f8c3a..870e32b1d6 100644
--- a/tests/io/test_metar.py
+++ b/tests/io/test_metar.py
@@ -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)