11"""Tests the regridding service module."""
22
3+ import logging
34from pathlib import Path
45from unittest .mock import MagicMock , patch
56
89from harmony_service_lib .message import Message as HarmonyMessage
910from harmony_service_lib .message import Source as HarmonySource
1011
12+ from harmony_regridding_service .exceptions import InvalidVariableRequest
1113from harmony_regridding_service .regridding_service import regrid
1214
1315test_scale_extent = {
@@ -36,7 +38,7 @@ def test_regrid_projected_data_end_to_end(
3638 """Test the full regrid process for projected input data."""
3739 input_filename = str (smap_projected_netcdf_file )
3840 output_filename = str (tmp_path / 'regridded_output.nc' )
39- logger_mock = MagicMock ()
41+ logger = logging . getLogger ()
4042
4143 # Define a target CRS [and optionally grid parameters]
4244 params = {
@@ -57,7 +59,7 @@ def test_regrid_projected_data_end_to_end(
5759 'harmony_regridding_service.regridding_service.generate_output_filename' ,
5860 return_value = output_filename ,
5961 ):
60- result_filename = regrid (message , input_filename , source , logger_mock )
62+ result_filename = regrid (message , input_filename , source , logger )
6163
6264 assert result_filename == output_filename
6365 assert Path (output_filename ).exists ()
@@ -82,14 +84,14 @@ def test_regrid_projected_data_end_to_end(
8284 ), description
8385
8486
85- def test_regrid_smap_data_end_to_end (
87+ def test_regrid_smap_file (
8688 test_spl3ftp_ncfile ,
8789 tmp_path ,
8890):
8991 """Test the full regrid process for projected input data."""
9092 input_filename = str (test_spl3ftp_ncfile )
9193 output_filename = str (tmp_path / 'regridded_output.nc' )
92- logger_mock = MagicMock ()
94+ logger = logging . getLogger ()
9395
9496 # Define a target CRS [and optionally grid parameters]
9597 params = {
@@ -107,7 +109,7 @@ def test_regrid_smap_data_end_to_end(
107109 'harmony_regridding_service.regridding_service.generate_output_filename' ,
108110 return_value = output_filename ,
109111 ):
110- result_filename = regrid (message , input_filename , source , logger_mock )
112+ result_filename = regrid (message , input_filename , source , logger )
111113
112114 assert result_filename == output_filename
113115 assert Path (output_filename ).exists ()
@@ -139,3 +141,146 @@ def test_regrid_smap_data_end_to_end(
139141 assert 'longitude' in dt [group ], f'failed: { group } '
140142 assert 'latitude' in dt [group ], f'failed: { group } '
141143 assert 'altitude_dem' in dt [group ], f'failed: { group } '
144+
145+
146+ def test_regrid_smap_excluded_variable_file (
147+ test_spl3ftp_ncfile ,
148+ tmp_path ,
149+ ):
150+ """Test the full regrid process with excluded variables.
151+
152+ This test adds a test varinfo config that excludes science variables:
153+ "/.*altitude_dem.*"
154+
155+ Is it the same as the previous test, but the last assertion is that the
156+ variable is not in the output.
157+
158+ """
159+ input_filename = str (test_spl3ftp_ncfile )
160+ output_filename = str (tmp_path / 'regridded_output.nc' )
161+ logger = logging .getLogger ()
162+
163+ # Define a target CRS [and optionally grid parameters]
164+ params = {
165+ 'format' : {
166+ 'mime' : 'application/x-netcdf' ,
167+ 'crs' : 'EPSG:4326' ,
168+ },
169+ 'sources' : [{'collection' : 'C123-test' , 'shortName' : 'SPL3FTP' }],
170+ }
171+ message = HarmonyMessage (params )
172+ source = HarmonySource ({'collection' : 'C123-TEST' , 'shortName' : 'SPL3FTP' })
173+
174+ # Mock generate_output_filename to control the output path
175+ with (
176+ patch (
177+ 'harmony_regridding_service.regridding_service.generate_output_filename' ,
178+ return_value = output_filename ,
179+ ),
180+ patch (
181+ 'harmony_regridding_service.regridding_service.varinfo_config_filename' ,
182+ return_value = str (
183+ Path (Path (__file__ ).parent / 'fixtures/test_HRS_varinfo_config.json' )
184+ ),
185+ ),
186+ ):
187+ result_filename = regrid (message , input_filename , source , logger )
188+
189+ assert result_filename == output_filename
190+ assert Path (output_filename ).exists ()
191+
192+ expected_groups = [
193+ '/Freeze_Thaw_Retrieval_Data_Polar' ,
194+ '/Freeze_Thaw_Retrieval_Data_Global' ,
195+ ]
196+ expected = {
197+ '/Freeze_Thaw_Retrieval_Data_Polar' : {
198+ 'width' : 263 ,
199+ 'height' : 122 ,
200+ },
201+ '/Freeze_Thaw_Retrieval_Data_Global' : {
202+ 'width' : 186 ,
203+ 'height' : 73 ,
204+ },
205+ }
206+
207+ with xr .open_datatree (output_filename ) as dt :
208+ for group in expected_groups :
209+ expects = expected [group ]
210+
211+ assert 'crs' in dt [group ], f'failed: { group } '
212+
213+ assert dt [group ].dims ['y' ] == expects ['height' ], f'failed: { group } '
214+ assert dt [group ].dims ['x' ] == expects ['width' ], f'failed: { group } '
215+
216+ assert 'longitude' in dt [group ], f'failed: { group } '
217+ assert 'latitude' in dt [group ], f'failed: { group } '
218+ ### This is the change from the previous test. altitude_dem is
219+ ### configured to be an excluded science variable
220+
221+ assert 'altitude_dem' not in dt [group ], f'failed: { group } '
222+
223+
224+ def test_regrid_smap_bad_user_requested_variable_data_end_to_end (
225+ test_spl3ftp_ncfile ,
226+ tmp_path ,
227+ ):
228+ """Test a Request that specifies an explicitly excluded variable.
229+
230+ This test repeats the previous test but a new test config is used that
231+ explicitly excludes that user's variable. we expect this request to fail.
232+
233+ """
234+ input_filename = str (test_spl3ftp_ncfile )
235+ output_filename = str (tmp_path / 'regridded_output.nc' )
236+ logger = MagicMock ()
237+
238+ # Define a user selected variable
239+ user_var = {
240+ 'id' : 'V12345789-EEDTEST' ,
241+ 'name' : 'Freeze_Thaw_Retrieval_Data_Global/altitude_dem' ,
242+ }
243+
244+ # Define a target CRS [and optionally grid parameters]
245+ params = {
246+ 'format' : {
247+ 'mime' : 'application/x-netcdf' ,
248+ 'crs' : 'EPSG:4326' ,
249+ },
250+ 'sources' : [
251+ {'collection' : 'C123-test' , 'shortName' : 'SPL3FTP' , 'variables' : [user_var ]}
252+ ],
253+ }
254+ message = HarmonyMessage (params )
255+ source = HarmonySource (message ['sources' ][0 ])
256+
257+ # Mock generate_output_filename to control the output path
258+ with (
259+ patch (
260+ 'harmony_regridding_service.regridding_service.generate_output_filename' ,
261+ return_value = output_filename ,
262+ ),
263+ patch (
264+ 'harmony_regridding_service.regridding_service.varinfo_config_filename' ,
265+ return_value = str (
266+ Path (Path (__file__ ).parent / 'fixtures/test_HRS_varinfo_config.json' )
267+ ),
268+ ),
269+ ):
270+ # when harmony-service-lib is updated use this.
271+ # expected_message = re.escape(
272+ # r"Request for unprocessable variable(s): "
273+ # "{'/Freeze_Thaw_Retrieval_Data_Global/altitude_dem'}."
274+ # )
275+ # with pytest.raises(InvalidVariableRequest, match=expected_message):
276+ # regrid(message, input_filename, source, logger)
277+
278+ expected_message = (
279+ 'Request for unprocessable variable(s): '
280+ "{'/Freeze_Thaw_Retrieval_Data_Global/altitude_dem'}."
281+ )
282+
283+ with pytest .raises (InvalidVariableRequest ) as exception_info :
284+ regrid (message , input_filename , source , logger )
285+
286+ assert exception_info .value .message == expected_message
0 commit comments