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 0000000..0244e1d Binary files /dev/null and b/tests/data/multi_date.grd differ 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