#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2019 Satpy developers
#
# This file is part of satpy.
#
# 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 HRIT electrol reader tests package."""
import datetime
import unittest
from unittest import mock
import dask.array as da
import numpy as np
from xarray import DataArray
from satpy.readers.electrol_hrit import (
HRITGOMSEpilogueFileHandler,
HRITGOMSFileHandler,
HRITGOMSPrologueFileHandler,
epilogue,
image_acquisition,
prologue,
recarray2dict,
satellite_status,
)
from satpy.tests.utils import make_dataid
# Simplify some type selections
f64_t = np.float64
i32_t = np.int32
u32_t = np.uint32
[docs]
class Testrecarray2dict(unittest.TestCase):
"""Test the function that converts numpy record arrays into dicts for use within SatPy."""
[docs]
def test_fun(self):
"""Test record array."""
inner_st = np.dtype([('test_str', '<S20'), ('test_int', 'i4')])
outer_st = np.dtype([('test_sec', inner_st), ('test_flt', 'f4')])
inner_da = np.array([('Testing', 10)], dtype=inner_st)
outer_da = np.array([(inner_da, 1.45)], dtype=outer_st)
expected = {'test_sec': {'test_str': np.array([b'Testing'], dtype='<S20'),
'test_int': np.array([10], dtype=np.int32)},
'test_flt': np.array([1.45], dtype=np.float32)}
self.assertEqual(expected, recarray2dict(outer_da))
[docs]
class TestHRITGOMSProFileHandler(unittest.TestCase):
"""Test the HRIT Prologue FileHandler."""
# Below are variable definitions used in testing the prologue reader.
# These values are taken from a typical ELECTRO-L HRIT scene
test_sat_status = {'TagType': 2,
'TagLength': 292,
'SatelliteID': 19002,
'SatelliteName': b'ELECTRO',
'NominalLongitude': 1.3264,
'SatelliteCondition': 1,
'TimeOffset': 0.}
test_img_acq = {'TagType': np.repeat(3, 10).astype(u32_t),
'TagLength': np.repeat(24, 10).astype(u32_t),
'Status': np.repeat(2, 10).astype(u32_t),
'StartDelay': np.repeat(9119019, 10).astype(np.int32),
'Cel': np.repeat(0., 10)}
test_calib = np.full((10, 1024), 50, dtype=np.int32)
test_pro = {'SatelliteStatus': test_sat_status,
'ImageAcquisition': test_img_acq,
'ImageCalibration': test_calib}
[docs]
@mock.patch('satpy.readers.electrol_hrit.np.fromfile')
@mock.patch('satpy.readers.electrol_hrit.HRITFileHandler.__init__')
def test_init(self, new_fh_init, fromfile):
"""Set up the hrit file handler for testing."""
new_fh_init.return_value.filename = 'filename'
HRITGOMSPrologueFileHandler.filename = 'filename'
HRITGOMSPrologueFileHandler.mda = {'total_header_length': 1}
# Set up the test data to use within the prologue reader
tss = np.array([(2, 292, 19002, 'ELECTRO', 1.3264, 1, 0.)],
dtype=satellite_status)
tia = np.tile(np.array([(3, 24, 2, 9119019, 0.)],
dtype=image_acquisition), (1, 10))
tc = np.full((10, 1024), 50)
rtv = np.array([(tss, tia, tc)], dtype=prologue)
# Pretend to return this when reading a fake prologue
fromfile.return_value = rtv
m = mock.mock_open()
with mock.patch('satpy.readers.electrol_hrit.open',
m, create=True) as newopen:
newopen.return_value.__enter__.return_value.seek.return_value = 1
test_t = datetime.datetime(2018, 1, 1, 0, 0)
self.reader = HRITGOMSPrologueFileHandler(
'filename', {'platform_shortname': 'GOMS2',
'start_time': test_t,
'service': 'test_service'},
{'filetype': 'info'})
# assertDictEqual doesn't seem to work for dicts containing dicts,
# so we must compare some items individually
self.assertDictEqual(self.test_pro['SatelliteStatus'],
self.reader.prologue['SatelliteStatus'])
prop = 'ImageAcquisition'
for key in self.reader.prologue[prop]:
np.testing.assert_array_equal(self.test_pro[prop][key],
self.reader.prologue[prop][key])
np.testing.assert_array_equal(self.test_pro['ImageCalibration'],
self.reader.prologue['ImageCalibration'])
[docs]
class TestHRITGOMSEpiFileHandler(unittest.TestCase):
"""Test the HRIT Epilogue FileHandler."""
[docs]
@mock.patch('satpy.readers.electrol_hrit.np.fromfile')
@mock.patch('satpy.readers.electrol_hrit.HRITFileHandler.__init__')
def test_init(self, new_fh_init, fromfile):
"""Set up the hrit file handler for testing."""
new_fh_init.return_value.filename = 'filename'
HRITGOMSEpilogueFileHandler.filename = 'filename'
HRITGOMSEpilogueFileHandler.mda = {'total_header_length': 1}
# Set up the test data to use within the epilogue reader
rtv = np.ones((1,), dtype=epilogue)
# Pretend to return this when reading a fake epilogue
fromfile.return_value = rtv
m = mock.mock_open()
with mock.patch('satpy.readers.electrol_hrit.open',
m, create=True) as newopen:
newopen.return_value.__enter__.return_value.seek.return_value = 1
test_t = datetime.datetime(2018, 1, 1, 0, 0)
self.reader = HRITGOMSEpilogueFileHandler(
'filename', {'platform_shortname': 'GOMS2',
'start_time': test_t,
'service': 'test_service'},
{'filetype': 'info'})
epi = self.reader.epilogue
# We don't check everything in the epilogue (too many nested dicts)
# but rather check the epilogue is returned as a dict and that two
# representative data fields are as we expect.
self.assertIsInstance(epi, dict)
np.testing.assert_array_equal(
epi['RadiometricProcessing']['RPSummary']['IsOptic'], np.ones(10))
np.testing.assert_array_equal(
epi['GeometricProcessing']['TimeProcessing'], np.ones(10))
[docs]
@mock.patch('satpy.readers.electrol_hrit.HRITGOMSFileHandler.__init__', return_value=None)
@mock.patch('satpy.readers.electrol_hrit.HRITFileHandler.get_dataset', return_value={})
class TestHRITGOMSFileHandler(unittest.TestCase):
"""A test of the ELECTRO-L main file handler functions."""
[docs]
@mock.patch('satpy.readers.electrol_hrit.HRITGOMSFileHandler.calibrate')
def test_get_dataset(self, calibrate_mock, *mocks):
"""Test get dataset."""
key = make_dataid(name='CH1', calibration='counts')
fake_array = mock.MagicMock()
fake_array.attrs = dict()
calibrate_mock.return_value = fake_array
fh = HRITGOMSFileHandler()
fh.platform_name = 'Electro'
fh.mda = {'projection_parameters': {'SSP_longitude': 0.0},
'orbital_parameters': {'satellite_nominal_longitude': 0.5}}
info = {'units': 'm', 'standard_name': 'electro', 'wavelength': 5.0}
output = fh.get_dataset(key, info)
# Check that 'calibrate' is called
calibrate_mock.assert_called()
# Check that the correct attributes are returned
attrs_exp = info.copy()
attrs_exp.update({'orbital_parameters': {'satellite_nominal_longitude': 0.5,
'satellite_nominal_latitude': 0.0,
'projection_longitude': 0.0,
'projection_latitude': 0.0,
'projection_altitude': 35785831.00},
'platform_name': 'Electro',
'sensor': 'msu-gs'})
assert dict(output.attrs, **attrs_exp) == output.attrs
[docs]
def test_calibrate(self, *mocks):
"""Test calibrate."""
lut = np.linspace(1e6, 1.6e6, num=1024).astype(np.int32)
lut = np.tile(lut, (10, 1))
fh = HRITGOMSFileHandler()
fh.prologue = {'ImageCalibration': lut}
fh.chid = 1
# Set up test input data
counts = DataArray(da.linspace(1, 1023, 25, chunks=5,
dtype=np.uint16).reshape(5, 5))
# Test that calibration fails if given a silly mode
self.assertRaises(NotImplementedError, fh.calibrate, counts,
'nonsense')
# Test that 'counts' calibration returns identical values to input
out = fh.calibrate(counts, 'counts')
self.assertTrue(np.all(out.values == counts.values))
# Test that 'radiance' calibrates successfully
out = fh.calibrate(counts, 'radiance')
self.assertTrue(np.allclose(out.values, lut[0, counts]/1000.))
# Test that 'brightness_temperature' calibrates successfully
out = fh.calibrate(counts, 'brightness_temperature')
self.assertTrue(np.allclose(out.values, lut[0, counts]/1000.))
[docs]
def test_get_area_def(self, *mocks):
"""Test get_area_def."""
example_area_ext = (-5566748.0802, -1854249.1809,
5570748.6178, 2000.2688)
fh = HRITGOMSFileHandler()
fh.mda = {'cfac': 10231753, 'lfac': 10231753,
'coff': 1392.0, 'loff': 0.0, 'number_of_lines': 464,
'number_of_columns': 2784,
'projection_parameters': {'SSP_longitude': 0.0}}
area = fh.get_area_def(True)
self.assertTrue(np.allclose(np.array(area.area_extent),
np.array(example_area_ext)))