@@ -243,8 +243,9 @@ def test_dimensions_mapping_output_merra(self, mock_dataset):
243
243
244
244
* Continuous granules (e.g., all output dimension values map to an
245
245
input value).
246
- * Discontinous granules (e.g., there is intervening space in the
247
- output temporal dimension).
246
+ * Discontinuous granules (e.g., there is intervening space in the
247
+ output temporal dimension). This will have gaps in the output
248
+ temporal dimension.
248
249
249
250
"""
250
251
merra_time_values = np .linspace (0 , 1380 , 24 )
@@ -358,8 +359,13 @@ def test_dimensions_mapping_output_merra(self, mock_dataset):
358
359
# Check the output time has correct values and units.
359
360
self .assertEqual (merra_mapping .output_dimensions ['/time' ].units ,
360
361
'minutes since 2020-01-03T00:30:00' )
362
+
363
+ # Expected time values are 24 consecutive hours, then a gap of 24
364
+ # hours, before another 24 consecutive hourly values.
365
+ expected_time_values = np .append (np .linspace (0 , 23 * 60 , 24 ),
366
+ np .linspace (48 * 60 , 71 * 60 , 24 ))
361
367
assert_array_equal (merra_mapping .output_dimensions ['/time' ].values ,
362
- np . linspace ( 0 , 4260 , 72 )) # 72 values of consecutive hours
368
+ expected_time_values )
363
369
364
370
# Check none of the output dimensions have bounds information, as
365
371
# none of the inputs did.
@@ -385,21 +391,23 @@ def test_dimensions_mapping_output_gpm(self, mock_dataset):
385
391
* Continuous granules (e.g., all output dimension values map to an
386
392
input value).
387
393
* Discontinous granules (e.g., there is intervening space in the
388
- output temporal dimension).
394
+ output temporal dimension). This test will now assume those gaps
395
+ are persisted as the service will no longer attempt to create a
396
+ regular grid.
389
397
390
398
"""
391
- expected_output_time_values = np .linspace (0 , 432000 , 6 ) # Daily data
399
+ continuous_time_values = np .linspace (0 , 432000 , 6 ) # Daily data
392
400
dataset_one = self .generate_netcdf_input (
393
401
'gpm_one.nc4' , self .lat_data , self .lon_data ,
394
- np .array ([expected_output_time_values [0 ]]), self .temporal_units
402
+ np .array ([continuous_time_values [0 ]]), self .temporal_units
395
403
)
396
404
dataset_two = self .generate_netcdf_input (
397
405
'gpm_two.nc4' , self .lat_data , self .lon_data ,
398
- np .array ([expected_output_time_values [2 ]]), self .temporal_units
406
+ np .array ([continuous_time_values [2 ]]), self .temporal_units
399
407
)
400
408
dataset_three = self .generate_netcdf_input (
401
409
'gpm_three.nc4' , self .lat_data , self .lon_data ,
402
- np .array ([expected_output_time_values [5 ]]), self .temporal_units
410
+ np .array ([continuous_time_values [5 ]]), self .temporal_units
403
411
)
404
412
405
413
mock_dataset .side_effect = [dataset_one , dataset_two , dataset_three ]
@@ -438,10 +446,15 @@ def test_dimensions_mapping_output_gpm(self, mock_dataset):
438
446
"""
439
447
440
448
# Check the output time has correct values and units.
449
+ expected_discontinuous_time_values = np .array ([
450
+ continuous_time_values [0 ],
451
+ continuous_time_values [2 ],
452
+ continuous_time_values [5 ]
453
+ ])
441
454
self .assertEqual (gpm_mapping .output_dimensions ['/time' ].units ,
442
455
self .temporal_units )
443
456
assert_array_equal (gpm_mapping .output_dimensions ['/time' ].values ,
444
- expected_output_time_values )
457
+ expected_discontinuous_time_values )
445
458
446
459
# Check none of the output dimensions have bounds information, as
447
460
# none of the inputs did.
@@ -454,6 +467,55 @@ def test_dimensions_mapping_output_gpm(self, mock_dataset):
454
467
self .assertIsNone (gpm_mapping .output_dimensions ['/time' ].bounds_values )
455
468
self .assertIsNone (gpm_mapping .output_dimensions ['/time' ].bounds_path )
456
469
470
+ @patch ('harmony_netcdf_to_zarr.mosaic_utilities.Dataset' )
471
+ def test_dimensions_mapping_unordered_granules (self , mock_dataset ):
472
+ """ Test that the `DimensionsMapping.output_dimensions` mapping is
473
+ correctly instantiated from known input data. This specific test
474
+ targets data like GPM/IMERG, where the spatial dimensions are the
475
+ same in each granule, the temporal dimension epochs are the same,
476
+ but the temporal dimension values vary between granules.
477
+
478
+ This specific test ensures that the output temporal dimension will
479
+ be correctly ordered, even if the input granules are not. This is
480
+ achieved by the behaviour of `numpy.unique`.
481
+
482
+ """
483
+ expected_output_time_values = np .linspace (0 , 172800 , 3 ) # Daily data
484
+ dataset_one = self .generate_netcdf_input (
485
+ 'gpm_one.nc4' , self .lat_data , self .lon_data ,
486
+ np .array ([expected_output_time_values [0 ]]), self .temporal_units
487
+ )
488
+ dataset_two = self .generate_netcdf_input (
489
+ 'gpm_two.nc4' , self .lat_data , self .lon_data ,
490
+ np .array ([expected_output_time_values [1 ]]), self .temporal_units
491
+ )
492
+ dataset_three = self .generate_netcdf_input (
493
+ 'gpm_three.nc4' , self .lat_data , self .lon_data ,
494
+ np .array ([expected_output_time_values [2 ]]), self .temporal_units
495
+ )
496
+
497
+ mock_dataset .side_effect = [dataset_one , dataset_two , dataset_three ]
498
+ gpm_mapping = DimensionsMapping (['gpm_three.nc4' , 'gpm_one.nc4' ,
499
+ 'gpm_two.nc4' ])
500
+
501
+ # Check the expected dimensions are in the output mapping.
502
+ # Note: aggregation of non-temporal dimensions has been disabled
503
+ # as the Swath Projector can have values with slight rounding
504
+ # errors in their output grid dimensions.
505
+ self .assertSetEqual (set (gpm_mapping .output_dimensions .keys ()),
506
+ {'/time' })
507
+
508
+ # Check the output time has correct values and units.
509
+ self .assertEqual (gpm_mapping .output_dimensions ['/time' ].units ,
510
+ self .temporal_units )
511
+ assert_array_equal (gpm_mapping .output_dimensions ['/time' ].values ,
512
+ expected_output_time_values )
513
+
514
+ # Check none of the output dimensions have bounds information, as
515
+ # none of the inputs did.
516
+ self .assertIsNone (gpm_mapping .output_dimensions ['/time' ].bounds_values )
517
+ self .assertIsNone (gpm_mapping .output_dimensions ['/time' ].bounds_path )
518
+
457
519
@patch ('harmony_netcdf_to_zarr.mosaic_utilities.Dataset' )
458
520
def test_dimensions_mapping_output_spatial (self , mock_dataset ):
459
521
""" Test that the `DimensionsMapping.output_dimensions` mapping is
@@ -538,9 +600,9 @@ def test_dimensions_mapping_bounds(self, mock_dataset):
538
600
* All output dimension values map to an input dimension value
539
601
and therefore all output bounds values can be copied from the
540
602
input data
541
- * There are output dimension values that do not map to input
542
- dimension values (due to gaps in coverage) and the corresponding
543
- bounds values for those gaps must be calculated.
603
+ * The inputs are discontinuous, and so the outputs will also be
604
+ discontinuous. (Note, previously, the gaps would be filled to
605
+ form a regularly sampled dimension)
544
606
545
607
"""
546
608
dimension_data_one = np .linspace (0 , 2 , 3 )
@@ -591,7 +653,7 @@ def test_dimensions_mapping_bounds(self, mock_dataset):
591
653
if dataset .isopen ():
592
654
dataset .close ()
593
655
594
- with self .subTest ('Some output dimension values are in coverage gaps ' ):
656
+ with self .subTest ('Discontinuous input granules ' ):
595
657
dataset_one = self .generate_netcdf_with_bounds ('bounds_three.nc4' ,
596
658
'dim' ,
597
659
dimension_data_one ,
@@ -617,15 +679,12 @@ def test_dimensions_mapping_bounds(self, mock_dataset):
617
679
[2.5 , 3.5 ],
618
680
[3.5 , 4.5 ],
619
681
[4.5 , 5.5 ],
620
- [5.5 , 6.5 ],
621
- [6.5 , 7.5 ],
622
- [7.5 , 8.5 ],
623
682
[8.5 , 9.5 ],
624
683
[9.5 , 10.5 ],
625
684
[10.5 , 11.5 ]])
626
685
627
686
assert_array_equal (mapping .output_dimensions ['/dim' ].values ,
628
- np .array ([0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ]))
687
+ np .array ([0 , 1 , 2 , 3 , 4 , 5 , 9 , 10 , 11 ]))
629
688
self .assertEqual (mapping .output_dimensions ['/dim' ].bounds_path ,
630
689
'/dim_bnds' )
631
690
assert_array_equal (mapping .output_dimensions ['/dim' ].bounds_values ,
0 commit comments