From 2f3cd35addbbf72b9194d3a3775be216106af0be Mon Sep 17 00:00:00 2001 From: Mads Christian Lund Date: Fri, 21 Jun 2024 11:31:46 +0200 Subject: [PATCH] Updated get_bufr to support static GPS heights. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bedrock stations shouldn’t depend on the noisy GPS signal for elevation. * Added station dimension values for WEG_B * Added corresponding unittest --- src/pypromice/postprocess/get_bufr.py | 13 +++- .../postprocess/station_configurations.toml | 6 ++ tests/unit/bufr_export/test_get_bufr.py | 62 +++++++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/pypromice/postprocess/get_bufr.py b/src/pypromice/postprocess/get_bufr.py index e199b597..765a319a 100644 --- a/src/pypromice/postprocess/get_bufr.py +++ b/src/pypromice/postprocess/get_bufr.py @@ -144,6 +144,7 @@ class StationConfiguration: temperature_from_sonic_ranger: Optional[float] = None height_of_gps_from_station_ground: Optional[float] = None sonic_ranger_from_gps: Optional[float] = None + static_height_of_gps_from_mean_sea_level: Optional[float] = None # The station data will be exported to BUFR if True. Otherwise, it will only export latest position export_bufr: bool = False @@ -558,14 +559,22 @@ def get_bufr_variables( if station_configuration.barometer_from_gps is None: raise AttributeError("barometer_from_gps is required for BUFR export") + if station_configuration.static_height_of_gps_from_mean_sea_level is None: + height_of_gps_above_mean_sea_level = data["gps_alt_fit"] + else: + height_of_gps_above_mean_sea_level = ( + station_configuration.static_height_of_gps_from_mean_sea_level + ) + heightOfStationGroundAboveMeanSeaLevel = ( - data["gps_alt_fit"] - station_configuration.height_of_gps_from_station_ground + height_of_gps_above_mean_sea_level - station_configuration.height_of_gps_from_station_ground ) heightOfBarometerAboveMeanSeaLevel = ( - data["gps_alt_fit"] + station_configuration.barometer_from_gps + height_of_gps_above_mean_sea_level + station_configuration.barometer_from_gps ) + heightOfSensorAboveLocalGroundOrDeckOfMarinePlatformTempRH = ( station_configuration.temperature_from_station_ground ) diff --git a/src/pypromice/postprocess/station_configurations.toml b/src/pypromice/postprocess/station_configurations.toml index 99bca21e..b6897327 100644 --- a/src/pypromice/postprocess/station_configurations.toml +++ b/src/pypromice/postprocess/station_configurations.toml @@ -514,6 +514,12 @@ station_site = "NUK_U" project = "Wegener" station_type = "land" wmo_id = "460" +barometer_from_gps = 1.3 +anemometer_from_sonic_ranger = 0.4 +temperature_from_sonic_ranger = 0.0 +height_of_gps_from_station_ground = 0.9 +sonic_ranger_from_gps = 1.3 +static_height_of_gps_from_mean_sea_level = 17.5 export_bufr = true skipped_variables = [] positions_update_timestamp_only = false diff --git a/tests/unit/bufr_export/test_get_bufr.py b/tests/unit/bufr_export/test_get_bufr.py index 4683561f..19ace941 100644 --- a/tests/unit/bufr_export/test_get_bufr.py +++ b/tests/unit/bufr_export/test_get_bufr.py @@ -199,6 +199,68 @@ def test_bufr_variables_promice_v3(self): heightOfBarometerAboveMeanSeaLevel=2126, ) + def test_bufr_variables_static_gps_elevation(self): + timestamp = datetime.datetime.now() + data = pd.Series( + data=dict( + rh_i=0.93, + t_i=-21, + name="", + p_i=993, + wdir_i=32.1, + wspd_i=5.3, + gps_lon_fit=-46.0, + gps_lat_fit=66.0, + # This is a erroneous value that should be overridden by the static value + gps_alt_fit=142.1, + z_boom_u_smooth=2.1, + ), + name=timestamp, + ) + station_config = StationConfiguration( + stid="A_STID", + station_type="land", + wmo_id="4201", + export_bufr=True, + barometer_from_gps=1.3, + height_of_gps_from_station_ground=0.9, + static_height_of_gps_from_mean_sea_level=17.5, + anemometer_from_sonic_ranger=None, + temperature_from_sonic_ranger=None, + sonic_ranger_from_gps=None, + ) + # The elevations should be determined from the static variable + expected_station_ground_elevation = 17.5 - 0.9 + expected_barometer_elevation = 17.5 + 1.3 + + expected_bufr_variables = BUFRVariables( + wmo_id=station_config.wmo_id, + station_type=station_config.station_type, + timestamp=timestamp, + relativeHumidity=1.0, + airTemperature=252.2, # Converted to kelvin + pressure=199300.0, + windDirection=32.0, + windSpeed=5.3, + latitude=66.0, + longitude=-46.0, + heightOfStationGroundAboveMeanSeaLevel=expected_station_ground_elevation, + heightOfBarometerAboveMeanSeaLevel=expected_barometer_elevation, + # The sensor heights are ignored since the necessary dimension values are missing + heightOfSensorAboveLocalGroundOrDeckOfMarinePlatformTempRH=np.nan, + heightOfSensorAboveLocalGroundOrDeckOfMarinePlatformWSPD=np.nan, + ) + + output = get_bufr_variables( + data, + station_configuration=station_config, + ) + + self.assertEqual( + expected_bufr_variables, + output, + ) + def test_fails_on_missing_dimension_values(self): """ Test that get_bufr_variables raises an AttributeError if the data is missing