Skip to content

Commit

Permalink
DEP: deprecate NOAA's RUC sounding model
Browse files Browse the repository at this point in the history
  • Loading branch information
Gui-FernandesBR committed Oct 9, 2024
1 parent 9d34c7e commit fbb8983
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 136 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ RocketPy is the next-generation trajectory simulation solution for High-Power Ro

2. **Accurate Weather Modeling**
- Supports International Standard Atmosphere (1976)
- Custom atmospheric profiles and Soundings (Wyoming, NOAARuc)
- Custom atmospheric profiles and Soundings (Wyoming)
- Weather forecasts, reanalysis, and ensembles for realistic scenarios

3. **Aerodynamic Models**
Expand Down
11 changes: 11 additions & 0 deletions docs/user/environment/1-atm-models/soundings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ Initialize a new Environment instance:
NOAA's Ruc Soundings
--------------------

.. important::

From September 30th, 2024, this model is no longer available since NOAA has \
discontinued the Ruc Soundings public service. The following message is \
displayed on the website: \
"On Monday, September 30, a number of legacy websites were permanently removed. \
These sites were no longer being maintained and did not meet security and \
design requirements mandated by NOAA. They were intended for research \
purposes and are not designed for operational use, such as for commercial \
purposes or the safety of life and property."

Another option for upper air soundings is `NOAA's Ruc Soundings <https://rucsoundings.noaa.gov/>`_.
This service allows users to download virtual soundings from numerical weather
prediction models such as GFS, RAP, and NAM, and also real soundings from the
Expand Down
124 changes: 7 additions & 117 deletions rocketpy/environment/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,11 @@ class Environment:
Environment.atmospheric_model_type : string
Describes the atmospheric model which is being used. Can only assume the
following values: ``standard_atmosphere``, ``custom_atmosphere``,
``wyoming_sounding``, ``NOAARucSounding``, ``Forecast``, ``Reanalysis``,
``wyoming_sounding``, ``Forecast``, ``Reanalysis``,
``Ensemble``.
Environment.atmospheric_model_file : string
Address of the file used for the atmospheric model being used. Only
defined for ``wyoming_sounding``, ``NOAARucSounding``, ``Forecast``,
defined for ``wyoming_sounding``, ``Forecast``,
``Reanalysis``, ``Ensemble``
Environment.atmospheric_model_dict : dictionary
Dictionary used to properly interpret ``netCDF`` and ``OPeNDAP`` files.
Expand Down Expand Up @@ -1053,24 +1053,6 @@ def set_atmospheric_model( # pylint: disable=too-many-statements
.. _weather.uwyo: http://weather.uwyo.edu/upperair/sounding.html
- ``NOAARucSounding``: sets pressure, temperature, wind-u
and wind-v profiles and surface elevation obtained from
an upper air sounding given by the file parameter through
an URL. This URL should point to a data webpage obtained
through NOAA's Ruc Sounding servers, which can be accessed
in `rucsoundings`_. Selecting ROABs as the
initial data source, specifying the station through it's
WMO-ID and opting for the ASCII (GSD format) button, the
following example URL opens up:
https://rucsoundings.noaa.gov/get_raobs.cgi?data_source=RAOB&latest=latest&start_year=2019&start_month_name=Feb&start_mday=5&start_hour=12&start_min=0&n_hrs=1.0&fcst_len=shortest&airport=83779&text=Ascii%20text%20%28GSD%20format%29&hydrometeors=false&start=latest
Any ASCII GSD format page from this server can be read,
so information from virtual soundings such as GFS and NAM
can also be imported.
.. _rucsoundings: https://rucsoundings.noaa.gov/
- ``windy_atmosphere``: sets pressure, temperature, wind-u and
wind-v profiles and surface elevation obtained from the Windy API.
See file argument to specify the model as either ``ECMWF``,
Expand Down Expand Up @@ -1279,8 +1261,6 @@ def set_atmospheric_model( # pylint: disable=too-many-statements
self.process_standard_atmosphere()
elif type == "wyoming_sounding":
self.process_wyoming_sounding(file)
elif type == "noaarucsounding":
self.process_noaaruc_sounding(file)
elif type == "custom_atmosphere":
self.process_custom_atmosphere(pressure, temperature, wind_u, wind_v)
elif type == "windy":
Expand Down Expand Up @@ -1689,108 +1669,18 @@ def process_noaaruc_sounding(self, file): # pylint: disable=too-many-statements
See also
--------
More details can be found at: https://rucsoundings.noaa.gov/.
This method is deprecated and will be fully deleted in version 1.8.0.
Returns
-------
None
"""
# Request NOAA Ruc Sounding from file url
response = fetch_noaaruc_sounding(file)

# Split response into lines
lines = response.text.split("\n")

# Process GSD format (https://rucsoundings.noaa.gov/raob_format.html)

# Extract elevation data
for line in lines:
# Split line into columns
columns = re.split(" +", line)[1:]
if len(columns) > 0:
if columns[0] == "1" and columns[5] != "99999":
# Save elevation
self.elevation = float(columns[5])
else:
# No elevation data available
pass

pressure_array = []
barometric_height_array = []
temperature_array = []
wind_speed_array = []
wind_direction_array = []

for line in lines:
# Split line into columns
columns = re.split(" +", line)[1:]
if len(columns) < 6:
# skip lines with less than 6 columns
continue
if columns[0] in ["4", "5", "6", "7", "8", "9"]:
# Convert columns to floats
columns = np.array(columns, dtype=float)
# Select relevant columns
altitude, pressure, temperature, wind_direction, wind_speed = columns[
[2, 1, 3, 5, 6]
]
# Check for missing values
if altitude == 99999:
continue
# Save values only if they are not missing
if pressure != 99999:
pressure_array.append([altitude, pressure])
barometric_height_array.append([pressure, altitude])
if temperature != 99999:
temperature_array.append([altitude, temperature])
if wind_direction != 99999:
wind_direction_array.append([altitude, wind_direction])
if wind_speed != 99999:
wind_speed_array.append([altitude, wind_speed])

# Convert lists to arrays
pressure_array = np.array(pressure_array)
barometric_height_array = np.array(barometric_height_array)
temperature_array = np.array(temperature_array)
wind_speed_array = np.array(wind_speed_array)
wind_direction_array = np.array(wind_direction_array)

# Converts 10*hPa to Pa and save values
pressure_array[:, 1] = 10 * pressure_array[:, 1]
self.__set_pressure_function(pressure_array)
# Converts 10*hPa to Pa and save values
barometric_height_array[:, 0] = 10 * barometric_height_array[:, 0]
self.__set_barometric_height_function(barometric_height_array)

# Convert C to K and save values
temperature_array[:, 1] = temperature_array[:, 1] / 10 + 273.15
self.__set_temperature_function(temperature_array)

# Process wind-u and wind-v
# Converts Knots to m/s
wind_speed_array[:, 1] = wind_speed_array[:, 1] * 1.852 / 3.6
wind_heading_array = wind_direction_array[:, :] * 1
# Convert wind direction to wind heading
wind_heading_array[:, 1] = (wind_direction_array[:, 1] + 180) % 360
wind_u = wind_speed_array[:, :] * 1
wind_v = wind_speed_array[:, :] * 1
wind_u[:, 1] = wind_speed_array[:, 1] * np.sin(
np.deg2rad(wind_heading_array[:, 1])
)
wind_v[:, 1] = wind_speed_array[:, 1] * np.cos(
np.deg2rad(wind_heading_array[:, 1])
warnings.warn(
"NOAA RUC models are no longer available. "
"This method is deprecated and will be fully deleted in version 1.8.0.",
DeprecationWarning,
)

# Save wind data
self.__set_wind_direction_function(wind_direction_array)
self.__set_wind_heading_function(wind_heading_array)
self.__set_wind_speed_function(wind_speed_array)
self.__set_wind_velocity_x_function(wind_u)
self.__set_wind_velocity_y_function(wind_v)

# Save maximum expected height
self.max_expected_height = pressure_array[-1, 0]

def process_forecast_reanalysis(
self, file, dictionary
): # pylint: disable=too-many-locals,too-many-statements
Expand Down
10 changes: 6 additions & 4 deletions rocketpy/environment/fetchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import re
import time
import warnings
from datetime import datetime, timedelta, timezone

import netCDF4
Expand Down Expand Up @@ -347,10 +348,11 @@ def fetch_noaaruc_sounding(file):
ImportError
If unable to load the specified file or the file content is too short.
"""
response = requests.get(file)
if response.status_code != 200 or len(response.text) < 10:
raise ImportError("Unable to load " + file + ".")
return response
warnings.warn(
"The NOAA RUC soundings are deprecated since September 30th, 2024. "
"This method will be removed in version 1.8.0.",
DeprecationWarning,
)


@exponential_backoff(max_attempts=5, base_delay=2, max_delay=60)
Expand Down
14 changes: 0 additions & 14 deletions tests/integration/test_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,6 @@ def test_standard_atmosphere(
assert example_plain_env.prints.print_earth_details() is None


@patch("matplotlib.pyplot.show")
def test_noaaruc_atmosphere(
mock_show, example_spaceport_env
): # pylint: disable=unused-argument
url = (
r"https://rucsoundings.noaa.gov/get_raobs.cgi?data_source=RAOB&latest="
r"latest&start_year=2019&start_month_name=Feb&start_mday=5&start_hour=12"
r"&start_min=0&n_hrs=1.0&fcst_len=shortest&airport=83779&text=Ascii"
r"%20text%20%28GSD%20format%29&hydrometeors=false&start=latest"
)
example_spaceport_env.set_atmospheric_model(type="NOAARucSounding", file=url)
assert example_spaceport_env.all_info() is None


@pytest.mark.parametrize(
"model_name",
[
Expand Down

0 comments on commit fbb8983

Please sign in to comment.