#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2023
#
# 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/>.
"""GERB L2 HR HDF5 reader.
Introduction
------------
A reader for the Top of Atmosphere outgoing fluxes from the Geostationary Earth Radiation
Budget instrument aboard the Meteosat Second Generation satellites.
Reader Arguments
----------------
Some arguments can be provided to the reader to change its behaviour. These are
provided through the `Scene` instantiation, eg::
scn = Scene(filenames=filenames, reader="gerb_l2_hr_h5", reader_kwargs={"area": "msg_seviri_fes_9km"})
"""
import datetime as dt
import logging
from satpy.area import get_area_def
from satpy.readers.core.hdf5 import HDF5FileHandler
LOG = logging.getLogger(__name__)
[docs]
def gerb_get_dataset(ds, ds_info):
"""Load a GERB dataset in memory from a HDF5 file or HDF5FileHandler.
The routine takes into account the quantisation factor and fill values.
"""
ds_attrs = ds.attrs
ds_fill = ds_info["fill_value"]
fill_mask = ds != ds_fill
if "Quantisation Factor" in ds_attrs and "Unit" in ds_attrs:
ds = ds*ds_attrs["Quantisation Factor"]
else:
ds = ds*1.
ds = ds.where(fill_mask)
return ds
[docs]
class GERB_HR_FileHandler(HDF5FileHandler):
"""File handler for GERB L2 High Resolution H5 files.
**Overriding the ``area``**
By default, the GERB HR reader looks at the attribute "Geolocation/attr/Nominal
Satellite Longitude (degrees)" for selecting the area definition. This data is not
available for the GERB-like products however, so you may need to override it with the
``area`` argument::
scene = satpy.Scene(filenames, reader="gerb_l2_hr_h5",
area="msg_seviri_fes_9km")
"""
[docs]
def __init__(self, filename, filename_info, filetype_info, area=None):
"""Initialize the reader."""
super(GERB_HR_FileHandler, self).__init__(filename, filename_info, filetype_info)
self.user_area = None
if area is not None:
self.user_area = area
@property
def end_time(self):
"""Get end time."""
return self.start_time + dt.timedelta(minutes=15)
@property
def start_time(self):
"""Get start time."""
return self.filename_info["sensing_time"]
[docs]
def get_dataset(self, ds_id, ds_info):
"""Read a HDF5 file into an xarray DataArray."""
ds_name = ds_id["name"]
if ds_name not in ["Solar Flux", "Thermal Flux", "Solar Radiance", "Thermal Radiance"]:
raise KeyError(f"{ds_name} is an unknown dataset for this reader.")
ds = gerb_get_dataset(self[f"Radiometry/{ds_name}"], ds_info)
ds.attrs.update({"start_time": self.start_time, "data_time": self.start_time, "end_time": self.end_time})
return ds
[docs]
def get_area_def(self, dsid):
"""Area definition for the GERB product."""
if self.user_area is not None:
return get_area_def(self.user_area)
ssp_lon = self.file_content["Geolocation/attr/Nominal Satellite Longitude (degrees)"]
if abs(ssp_lon) < 1e-6:
return get_area_def("msg_seviri_fes_9km")
elif abs(ssp_lon - 9.5) < 1e-6:
return get_area_def("msg_seviri_fes_9km")
elif abs(ssp_lon - 45.5) < 1e-6:
return get_area_def("msg_seviri_iodc_9km")
else:
raise ValueError(f"There is no matching grid for SSP longitude {self.ssp_lon}")