Source code for satpy.tests.reader_tests.test_vii_l1b_nc

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2020 Satpy developers
#
# satpy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# satpy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with satpy.  If not, see <http://www.gnu.org/licenses/>.
"""The vii_l1b_nc reader tests package.

This version tests the readers for VII test data V2 as per PFS V4A.

"""


import datetime
import os
import unittest
import uuid

import dask.array as da
import numpy as np
import pytest
import xarray as xr
from netCDF4 import Dataset

from satpy.readers.vii_l1b_nc import ViiL1bNCFileHandler
from satpy.readers.vii_utils import MEAN_EARTH_RADIUS

TEST_FILE = "test_file_vii_l1b_nc.nc"


[docs] class TestViiL1bNCFileHandler(unittest.TestCase): """Test the ViiL1bNCFileHandler reader."""
[docs] def setUp(self): """Set up the test.""" # Easiest way to test the reader is to create a test netCDF file on the fly # uses a UUID to avoid permission conflicts during execution of tests in parallel self.test_file_name = TEST_FILE + str(uuid.uuid1()) + ".nc" with Dataset(self.test_file_name, "w") as nc: # Create data group g1 = nc.createGroup("data") # Add dimensions to data group g1.createDimension("num_chan_solar", 11) g1.createDimension("num_chan_thermal", 9) g1.createDimension("num_pixels", 72) g1.createDimension("num_lines", 600) # Create calibration_data group g1_1 = g1.createGroup("calibration_data") # Add variables to data/calibration_data group bt_a = g1_1.createVariable("bt_conversion_a", np.float32, dimensions=("num_chan_thermal",)) bt_a[:] = np.arange(9) bt_b = g1_1.createVariable("bt_conversion_b", np.float32, dimensions=("num_chan_thermal",)) bt_b[:] = np.arange(9) cw = g1_1.createVariable("channel_cw_thermal", np.float32, dimensions=("num_chan_thermal",)) cw[:] = np.arange(9) isi = g1_1.createVariable("Band_averaged_solar_irradiance", np.float32, dimensions=("num_chan_solar",)) isi[:] = np.arange(11) # Create measurement_data group g1_2 = g1.createGroup("measurement_data") # Add dimensions to data/measurement_data group g1_2.createDimension("num_tie_points_act", 10) g1_2.createDimension("num_tie_points_alt", 100) # Add variables to data/measurement_data group sza = g1_2.createVariable("solar_zenith", np.float32, dimensions=("num_tie_points_alt", "num_tie_points_act")) sza[:] = 25.0 delta_lat = g1_2.createVariable("delta_lat", np.float32, dimensions=("num_lines", "num_pixels")) delta_lat[:] = 1.0 self.reader = ViiL1bNCFileHandler( filename=self.test_file_name, filename_info={ "creation_time": datetime.datetime(year=2017, month=9, day=22, hour=22, minute=40, second=10), "sensing_start_time": datetime.datetime(year=2017, month=9, day=20, hour=12, minute=30, second=30), "sensing_end_time": datetime.datetime(year=2017, month=9, day=20, hour=18, minute=30, second=50) }, filetype_info={} )
[docs] def tearDown(self): """Remove the previously created test file.""" # Catch Windows PermissionError for removing the created test file. try: os.remove(self.test_file_name) except OSError: pass
[docs] def test_calibration_functions(self): """Test the calibration functions.""" radiance = np.array([[1.0, 2.0, 5.0], [7.0, 10.0, 20.0]]) cw = 13.0 a = 3.0 b = 100.0 bt = self.reader._calibrate_bt(radiance, cw, a, b) expected_bt = np.array([[675.04993213, 753.10301462, 894.93149648], [963.20401882, 1048.95086402, 1270.95546218]]) assert np.allclose(bt, expected_bt) angle_factor = 0.4 isi = 2.0 refl = self.reader._calibrate_refl(radiance, angle_factor, isi) expected_refl = np.array([[62.8318531, 125.6637061, 314.1592654], [439.8229715, 628.3185307, 1256.637061]]) assert np.allclose(refl, expected_refl)
[docs] def test_functions(self): """Test the functions.""" # Checks that the _perform_orthorectification function is correctly executed variable = xr.DataArray( dims=("num_lines", "num_pixels"), name="test_name", attrs={ "key_1": "value_1", "key_2": "value_2" }, data=da.from_array(np.ones((600, 72))) ) orthorect_variable = self.reader._perform_orthorectification(variable, "data/measurement_data/delta_lat") expected_values = np.degrees(np.ones((600, 72)) / MEAN_EARTH_RADIUS) + np.ones((600, 72)) assert np.allclose(orthorect_variable.values, expected_values) # Checks that the _perform_calibration function is correctly executed in all cases # radiance calibration: return value is simply a copy of the variable return_variable = self.reader._perform_calibration(variable, {"calibration": "radiance"}) assert np.all(return_variable == variable) # invalid calibration: raises a ValueError with pytest.raises(ValueError, match="Unknown calibration invalid for dataset test"): self.reader._perform_calibration(variable, {"calibration": "invalid", "name": "test"}) # brightness_temperature calibration: checks that the return value is correct calibrated_variable = self.reader._perform_calibration(variable, {"calibration": "brightness_temperature", "chan_thermal_index": 3}) expected_values = np.full((600, 72), 1101.10413712) assert np.allclose(calibrated_variable.values, expected_values) # reflectance calibration: checks that the return value is correct calibrated_variable = self.reader._perform_calibration(variable, {"calibration": "reflectance", "wavelength": [0.658, 0.668, 0.678], "chan_solar_index": 2}) expected_values = np.full((600, 72), 173.3181982) assert np.allclose(calibrated_variable.values, expected_values)