Skip to content

Commit

Permalink
Merge pull request #730 from tmharty/recalculate_wyoming
Browse files Browse the repository at this point in the history
Recalculate Wyoming
  • Loading branch information
dopplershift authored Dec 12, 2024
2 parents 2200fb1 + 39deb66 commit 337f581
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 5 deletions.
22 changes: 17 additions & 5 deletions src/siphon/simplewebservice/wyoming.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __init__(self):
super().__init__('http://weather.uwyo.edu/cgi-bin/sounding')

@classmethod
def request_data(cls, time, site_id, **kwargs):
def request_data(cls, time, site_id, recalc=False, **kwargs):
r"""Retrieve upper air observations from the Wyoming archive.
Parameters
Expand All @@ -40,6 +40,11 @@ def request_data(cls, time, site_id, **kwargs):
The three letter ICAO identifier of the station for which data should be
downloaded.
recalc : bool
Whether to request the server recalculate the data (i.e. ignore its cache) before
returning it. Defaults to False. NOTE: This should be used sparingly because it
will increase the load on the service.
kwargs
Arbitrary keyword arguments to use to initialize source
Expand All @@ -50,10 +55,10 @@ def request_data(cls, time, site_id, **kwargs):
"""
endpoint = cls()
df = endpoint._get_data(time, site_id)
df = endpoint._get_data(time, site_id, recalc=recalc)
return df

def _get_data(self, time, site_id):
def _get_data(self, time, site_id, recalc=False):
r"""Download and parse upper air observations from an online archive.
Parameters
Expand All @@ -65,12 +70,15 @@ def _get_data(self, time, site_id):
The three letter ICAO identifier of the station for which data should be
downloaded.
recalc : bool
Returns recalculated data if True. Defaults to False.
Returns
-------
`pandas.DataFrame`
"""
raw_data = self._get_data_raw(time, site_id)
raw_data = self._get_data_raw(time, site_id, recalc=recalc)
soup = BeautifulSoup(raw_data, 'html.parser')
tabular_data = StringIO(soup.find_all('pre')[0].contents[0])
col_names = ['pressure', 'height', 'temperature', 'dewpoint', 'direction', 'speed']
Expand Down Expand Up @@ -129,7 +137,7 @@ def _get_data(self, time, site_id):

return df

def _get_data_raw(self, time, site_id):
def _get_data_raw(self, time, site_id, recalc=False):
"""Download data from the University of Wyoming's upper air archive.
Parameters
Expand All @@ -138,6 +146,8 @@ def _get_data_raw(self, time, site_id):
Date and time for which data should be downloaded
site_id : str
Site id for which data should be downloaded
recalc : bool
Returns recalculated data if True. Defaults to False.
Returns
-------
Expand All @@ -148,6 +158,8 @@ def _get_data_raw(self, time, site_id):
path = ('?region=naconf&TYPE=TEXT%3ALIST'
f'&YEAR={time:%Y}&MONTH={time:%m}&FROM={time:%d%H}&TO={time:%d%H}'
f'&STNM={site_id}')
if recalc:
path += '&REPLOT=1'

resp = self.get_path(path)
# See if the return is valid, but has no data
Expand Down
105 changes: 105 additions & 0 deletions tests/fixtures/wyoming_sounding_recalculate

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

39 changes: 39 additions & 0 deletions tests/test_wyoming.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,45 @@ def test_wyoming():
assert df.units['time'] is None


@recorder.use_cassette('wyoming_sounding_recalculate')
def test_wyoming_recalculate():
"""Test that recalculation request returns the same data."""
df = WyomingUpperAir.request_data(
datetime(1999, 5, 4, 0), 'OUN', recalc=True)

assert df['time'][0] == datetime(1999, 5, 4, 0)
assert df['station'][0] == 'OUN'
assert df['station_number'][0] == 72357
assert df['latitude'][0] == 35.18
assert df['longitude'][0] == -97.44
assert df['elevation'][0] == 345.0

assert_almost_equal(df['pressure'][5], 867.9, 2)
assert_almost_equal(df['height'][5], 1219., 2)
assert_almost_equal(df['height'][30], 10505., 2)
assert_almost_equal(df['temperature'][5], 17.4, 2)
assert_almost_equal(df['dewpoint'][5], 14.3, 2)
assert_almost_equal(df['u_wind'][5], 6.60, 2)
assert_almost_equal(df['v_wind'][5], 37.42, 2)
assert_almost_equal(df['speed'][5], 38.0, 1)
assert_almost_equal(df['direction'][5], 190.0, 1)

assert df.units['pressure'] == 'hPa'
assert df.units['height'] == 'meter'
assert df.units['temperature'] == 'degC'
assert df.units['dewpoint'] == 'degC'
assert df.units['u_wind'] == 'knot'
assert df.units['v_wind'] == 'knot'
assert df.units['speed'] == 'knot'
assert df.units['direction'] == 'degrees'
assert df.units['latitude'] == 'degrees'
assert df.units['longitude'] == 'degrees'
assert df.units['elevation'] == 'meter'
assert df.units['station'] is None
assert df.units['station_number'] is None
assert df.units['time'] is None


@recorder.use_cassette('wyoming_sounding_no_station')
def test_wyoming_no_station():
"""Test that we handle stations with no ID from the Wyoming archive."""
Expand Down

0 comments on commit 337f581

Please sign in to comment.