From e8cd380caac085f3bcfbec6d8bdd3c4dc2b077e5 Mon Sep 17 00:00:00 2001 From: Nathan Wendt Date: Thu, 27 Oct 2022 12:26:23 -0500 Subject: [PATCH] Minor bug fixes and new tests --- gempakio/decode/gempak.py | 25 +++++++++++++++++-------- setup.py | 2 +- tests/data/multi_date.grd | Bin 0 -> 30208 bytes tests/test_grids.py | 17 +++++++++++++++++ tests/test_soundings.py | 19 ++++++++++++++++++- tests/test_surface.py | 14 ++++++++++++++ 6 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 tests/data/multi_date.grd diff --git a/gempakio/decode/gempak.py b/gempakio/decode/gempak.py index e78b21d..745d08e 100644 --- a/gempakio/decode/gempak.py +++ b/gempakio/decode/gempak.py @@ -900,7 +900,9 @@ def gdxarray(self, parameter=None, date_time=None, coordinate=None, date_time2 : datetime or array-like of datetime Secondary valid datetime of the grid. Alternatively - can be a string with the format YYYYmmddHHMM. + a string with the format YYYYmmddHHMM or first|FIRST + or last|LAST which function to retrieve the latest + and oldest time within the file, respectively. level2: float or array_like of float Secondary vertical level. Typically used for layers. @@ -947,11 +949,13 @@ def gdxarray(self, parameter=None, date_time=None, coordinate=None, if date_time2 is not None: if (not isinstance(date_time2, Iterable) - or isinstance(date_time2, str)): + or (isinstance(date_time2, str) + and date_time2 not in ['first', 'FIRST', 'last', 'LAST'])): date_time2 = [date_time2] - for i, dt in enumerate(date_time2): - if isinstance(dt, str): - date_time2[i] = datetime.strptime(dt, '%Y%m%d%H%M') + if date_time2 not in ['first', 'FIRST', 'last', 'LAST']: + for i, dt in enumerate(date_time2): + if isinstance(dt, str): + date_time2[i] = datetime.strptime(dt, '%Y%m%d%H%M') if level2 is not None and not isinstance(level2, Iterable): level2 = [level2] @@ -962,9 +966,14 @@ def gdxarray(self, parameter=None, date_time=None, coordinate=None, # Do this now or the matched filter iterator will be consumed # prematurely. if date_time in ['last', 'LAST']: - date_time = [max((d.DATTIM for d in matched))] + date_time = [max((d.DATTIM1 for d in matched))] elif date_time in ['first', 'FIRST']: - date_time = [min((d.DATTIM for d in matched))] + date_time = [min((d.DATTIM1 for d in matched))] + + if date_time2 in ['last', 'LAST']: + date_time2 = [max((d.DATTIM2 for d in matched))] + elif date_time2 in ['first', 'FIRST']: + date_time2 = [min((d.DATTIM2 for d in matched))] if parameter is not None: matched = filter( @@ -2052,7 +2061,7 @@ def snxarray(self, station_id=None, station_number=None, if 'TXPB' in snd: wmo_text['txpb'] = snd.pop('TXPB') if wmo_text: - attrs['WMO_CODES'] = wmo_text + attrs['wmo_codes'] = wmo_text dt = datetime.combine(snd.pop('DATE'), snd.pop('TIME')) if vcoord == 'pres': diff --git a/setup.py b/setup.py index a74b8ba..8f9db9e 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages, setup NAME = 'gempakio' -VERSION = '0.8.0' +VERSION = '0.8.1' DESCR = 'Read GEMPAK data with pure Python.' URL = 'https://github.com/nawendt/gempakio' REQUIRES = ['pyproj', 'xarray'] diff --git a/tests/data/multi_date.grd b/tests/data/multi_date.grd new file mode 100644 index 0000000000000000000000000000000000000000..0244e1de7d4a4fc7d9ab07cdf84097a6a796485e GIT binary patch literal 30208 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 Z`TcVS&KdaiV8C@1X+FyN;s1<*{{rv8YcK!+ literal 0 HcmV?d00001 diff --git a/tests/test_grids.py b/tests/test_grids.py index 5091ca0..c9c5e66 100644 --- a/tests/test_grids.py +++ b/tests/test_grids.py @@ -4,6 +4,7 @@ """Tests for decoding GEMPAK grid files.""" +from datetime import datetime, timedelta from pathlib import Path import numpy as np @@ -24,3 +25,19 @@ def test_grid_loading(grid_name): gempak = np.load(d)['values'] np.testing.assert_allclose(gio, gempak, rtol=1e-6, atol=0) + + +@pytest.mark.parametrize('keyword,date_time', [ + ('FIRST', '201204141200'), ('LAST', '201204150000') +]) +def test_time_keywords(keyword, date_time): + """Test time keywords FIRST and LAST.""" + g = Path(__file__).parent / 'data' / 'multi_date.grd' + + grid = GempakGrid(g).gdxarray(date_time=keyword)[0] + dt64 = grid.time.values[0] + epoch_seconds = int(dt64) / 1e9 + grid_dt = datetime(1970, 1, 1) + timedelta(seconds=epoch_seconds) + expected = datetime.strptime(date_time, '%Y%m%d%H%M') + + assert grid_dt == expected diff --git a/tests/test_soundings.py b/tests/test_soundings.py index 46bea51..0a12d7b 100644 --- a/tests/test_soundings.py +++ b/tests/test_soundings.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: BSD-3-Clause """Tests for decoding GEMPAK grid files.""" +from datetime import datetime, timedelta from pathlib import Path import numpy as np @@ -84,7 +85,7 @@ def test_sounding_text(text_type): gso = GempakSounding(g).snxarray(station_id='OUN')[0] gempak = pd.read_csv(d) - text = gso.attrs['WMO_CODES'][text_type] + text = gso.attrs['wmo_codes'][text_type] gem_text = gempak.loc[:, text_type.upper()][0] assert text == gem_text @@ -157,3 +158,19 @@ def test_unmerged_sigw_pressure_sounding(): np.testing.assert_allclose(gdrct, ddrct, rtol=1e-10, atol=1e-2) np.testing.assert_allclose(gsped, dsped, rtol=1e-10, atol=1e-2) np.testing.assert_allclose(ghght, dhght, rtol=1e-10, atol=1e-1) + + +@pytest.mark.parametrize('keyword,date_time', [ + ('FIRST', '202011070000'), ('LAST', '202011070100') +]) +def test_time_keywords(keyword, date_time): + """Test time keywords FIRST and LAST.""" + g = Path(__file__).parent / 'data' / 'unmerged_with_text.snd' + + gso = GempakSounding(g).snxarray(date_time=keyword)[0] + expected = datetime.strptime(date_time, '%Y%m%d%H%M') + dt64 = gso.time.values[0] + epoch_seconds = int(dt64) / 1e9 + sounding_dt = datetime(1970, 1, 1) + timedelta(seconds=epoch_seconds) + + assert sounding_dt == expected diff --git a/tests/test_surface.py b/tests/test_surface.py index 85a2ad6..07a385e 100644 --- a/tests/test_surface.py +++ b/tests/test_surface.py @@ -111,3 +111,17 @@ def test_multiple_special_observations(): assert date_time == datetime(2021, 9, 7, 16, 4) assert text == gem_text + + +@pytest.mark.parametrize('keyword,date_time', [ + ('FIRST', '202109062353'), ('LAST', '202109071604') +]) +def test_time_keywords(keyword, date_time): + """Test time keywords FIRST and LAST.""" + g = Path(__file__).parent / 'data' / 'msn_std_sfc.sfc' + + gsf = GempakSurface(g).sfjson(date_time=keyword)[-1] + expected = datetime.strptime(date_time, '%Y%m%d%H%M') + surface_dt = gsf['properties']['date_time'] + + assert surface_dt == expected