Skip to content

Commit c4f31cb

Browse files
Merge pull request #158 from aodn/fix_velocity_time_scrambing
Fix time scrambing issue in velocity hourly product
2 parents 238f3ce + 99c92fc commit c4f31cb

4 files changed

Lines changed: 93 additions & 15 deletions

File tree

aodntools/timeseries_products/velocity_hourly_timeseries.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,12 @@ def append_resampled_values(nc_cell, ds, slice_start, binning_functions):
5757
df_cell = nc_cell.squeeze().to_dataframe()
5858
# shift the index forward 30min to centre the bins on the hour
5959
df_cell.index = df_cell.index + pd.Timedelta(minutes=30)
60-
# TODO: shift timestamps to centre of sampling interval
6160

6261
df_cell_1H = df_cell.resample('1H')
6362
slice_end = len(df_cell_1H) + slice_start
6463

6564
# set binned timestamps
66-
time_slice = (np.fromiter(df_cell_1H.groups.keys(), dtype='M8[ns]') - TIME_EPOCH) / ONE_DAY
65+
time_slice = (np.fromiter(df_cell_1H.min().index, dtype='M8[ns]') - TIME_EPOCH) / ONE_DAY
6766
ds['TIME'][slice_start:slice_end] = time_slice
6867

6968
# take the mean of the variables

test_aodntools/timeseries_products/test_velocity_aggregated_timeseries.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@
2222
TEST_ROOT, 'IMOS_ANMN-NRS_VZ_20180816_NRSROT_FV01_velocity-aggregated-timeseries_END-20191018_C-20200623.nc'
2323
)
2424

25+
OBS_VARS = {'TIME', 'DEPTH', 'DEPTH_quality_control', 'UCUR', 'UCUR_quality_control',
26+
'VCUR', 'VCUR_quality_control', 'WCUR', 'WCUR_quality_control', 'instrument_index', 'CELL_INDEX'}
27+
INST_VARS = {'LATITUDE', 'LONGITUDE', 'NOMINAL_DEPTH', 'SECONDS_TO_MIDDLE'}
28+
STR_VARS = {'source_file', 'instrument_id'}
29+
30+
2531
class TestVelocityAggregatedTimeseries(BaseTestCase):
26-
def test_main_aggregator(self):
32+
def test_velocity_aggregated(self):
2733
output_file, bad_files = velocity_aggregated(INPUT_FILES, 'NRSROT', input_dir=TEST_ROOT, output_dir='/tmp')
2834

2935
self.assertEqual(1, len(bad_files))
@@ -34,19 +40,13 @@ def test_main_aggregator(self):
3440

3541
# check dimensions and variables
3642
self.assertSetEqual(set(dataset.dimensions), {'OBSERVATION', 'INSTRUMENT', 'strlen'})
43+
self.assertSetEqual(set(dataset.variables.keys()), OBS_VARS | INST_VARS | STR_VARS)
3744

38-
obs_vars = {'TIME', 'DEPTH', 'DEPTH_quality_control', 'UCUR', 'UCUR_quality_control',
39-
'VCUR', 'VCUR_quality_control', 'WCUR', 'WCUR_quality_control', 'instrument_index', 'CELL_INDEX'}
40-
inst_vars = {'LATITUDE', 'LONGITUDE', 'NOMINAL_DEPTH', 'SECONDS_TO_MIDDLE'}
41-
string_vars = {'source_file', 'instrument_id'}
42-
43-
self.assertSetEqual(set(dataset.variables.keys()), obs_vars | inst_vars | string_vars)
44-
45-
for var in obs_vars:
45+
for var in OBS_VARS:
4646
self.assertEqual(dataset.variables[var].dimensions, ('OBSERVATION',))
47-
for var in inst_vars:
47+
for var in INST_VARS:
4848
self.assertEqual(dataset.variables[var].dimensions, ('INSTRUMENT',))
49-
for var in string_vars:
49+
for var in STR_VARS:
5050
self.assertEqual(dataset.variables[var].dimensions, ('INSTRUMENT', 'strlen'))
5151

5252
for f in chartostring(dataset['source_file'][:]):
@@ -58,8 +58,7 @@ def test_main_aggregator(self):
5858

5959
# check aggregated variable values
6060
expected = Dataset(EXPECTED_OUTPUT_FILE)
61-
compare_vars = ('TIME', 'UCUR', 'UCUR_quality_control', 'VCUR', 'VCUR_quality_control', 'NOMINAL_DEPTH',
62-
'CELL_INDEX', 'instrument_index', 'DEPTH', 'DEPTH_quality_control')
61+
compare_vars = set(expected.variables.keys()) - STR_VARS
6362
non_match_vars = [var for var in compare_vars
6463
if not all(dataset[var][:] == expected[var][:])
6564
]
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import unittest
5+
6+
import numpy as np
7+
from netCDF4 import Dataset, chartostring
8+
9+
from aodntools import __version__
10+
from aodntools.timeseries_products.common import NoInputFilesError
11+
from aodntools.timeseries_products.velocity_hourly_timeseries import velocity_hourly_aggregated
12+
from test_aodntools.base_test import BaseTestCase
13+
14+
TEST_ROOT = os.path.dirname(__file__)
15+
BAD_FILE = 'IMOS_ANMN-NRS_BAD_VELOCITY_FILE.nc'
16+
INPUT_FILES = [
17+
'IMOS_ANMN-NRS_AETVZ_20181213T080000Z_NRSROT-ADCP_FV01_NRSROT-ADCP-1812-Sentinel-or-Monitor-Workhorse-ADCP-44_END-20181215T100000Z_C-20200430T000000Z.nc',
18+
'IMOS_ANMN-NRS_AETVZ_20180816T080000Z_NRSROT-ADCP_FV01_NRSROT-ADCP-1808-Sentinel-or-Monitor-Workhorse-ADCP-44_END-20180822T053000Z_C-20200623T000000Z.nc',
19+
'IMOS_ANMN-NRS_AETVZ_20191016T080000Z_NRSROT-ADCP_FV01_NRSROT-ADCP-1910-Sentinel-or-Monitor-Workhorse-ADCP-44_END-20191018T100000Z_C-20200430T000000Z.nc',
20+
BAD_FILE
21+
]
22+
EXPECTED_OUTPUT_FILE = os.path.join(
23+
TEST_ROOT, 'IMOS_ANMN-NRS_VZ_20180816_NRSROT_FV02_velocity-hourly-timeseries_END-20191018_C-20220502.nc'
24+
)
25+
26+
OBS_VARS = {'TIME', 'instrument_index', 'CELL_INDEX'}
27+
INST_VARS = {'LATITUDE', 'LONGITUDE', 'NOMINAL_DEPTH', 'SECONDS_TO_MIDDLE'}
28+
STR_VARS = {'source_file', 'instrument_id'}
29+
for v in ['DEPTH', 'UCUR', 'VCUR', 'WCUR']:
30+
OBS_VARS.add(v)
31+
for s in ['_min', '_max', '_std', '_count']:
32+
OBS_VARS.add(v + s)
33+
34+
35+
class TestVelocityHourlyTimeseries(BaseTestCase):
36+
def test_velocity_hourly(self):
37+
output_file, bad_files = velocity_hourly_aggregated(INPUT_FILES, 'NRSROT',
38+
input_dir=TEST_ROOT, output_dir='/tmp')
39+
40+
self.assertEqual(1, len(bad_files))
41+
for file, errors in bad_files.items():
42+
self.assertEqual(BAD_FILE, file)
43+
44+
dataset = Dataset(output_file)
45+
46+
# check dimensions and variables
47+
self.assertSetEqual(set(dataset.dimensions), {'OBSERVATION', 'INSTRUMENT', 'strlen'})
48+
self.assertSetEqual(set(dataset.variables.keys()), OBS_VARS | INST_VARS | STR_VARS)
49+
50+
for var in OBS_VARS:
51+
self.assertEqual(dataset.variables[var].dimensions, ('OBSERVATION',))
52+
for var in INST_VARS:
53+
self.assertEqual(dataset.variables[var].dimensions, ('INSTRUMENT',))
54+
for var in STR_VARS:
55+
self.assertEqual(dataset.variables[var].dimensions, ('INSTRUMENT', 'strlen'))
56+
57+
for f in chartostring(dataset['source_file'][:]):
58+
self.assertIn(f, INPUT_FILES)
59+
60+
# check attributes
61+
self.assertEqual(__version__, dataset.generating_code_version)
62+
self.assertIn(__version__, dataset.lineage)
63+
64+
# check aggregated variable values
65+
expected = Dataset(EXPECTED_OUTPUT_FILE)
66+
self.assertEqual(len(expected['TIME']), len(dataset['TIME']))
67+
68+
non_match_vars = []
69+
for var in set(expected.variables.keys()) - STR_VARS:
70+
if not all(np.isclose(dataset[var], expected[var], equal_nan=True)):
71+
non_match_vars.append(var)
72+
self.assertEqual(non_match_vars, [])
73+
74+
def test_all_rejected(self):
75+
self.assertRaises(NoInputFilesError, velocity_hourly_aggregated, [BAD_FILE], 'NRSROT',
76+
input_dir=TEST_ROOT, output_dir='/tmp')
77+
78+
79+
if __name__ == '__main__':
80+
unittest.main()

0 commit comments

Comments
 (0)