Skip to content

Commit

Permalink
Add common base class for initialization
Browse files Browse the repository at this point in the history
This is also a good place for the common documentation.
  • Loading branch information
sfinkens committed Dec 15, 2020
1 parent 916b297 commit dfb9d73
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 112 deletions.
81 changes: 81 additions & 0 deletions satpy/readers/seviri_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,87 @@ def images_used(self):
mpef_product_header = MpefProductHeader().get()


class SEVIRIBaseFileHandler:
"""Base class for SEVIRI L1.5 file handlers.
**Calibration to radiance**
The SEVIRI L1.5 file handlers allow for choosing between two file-internal
calibration coefficients to convert counts to radiances:
- Nominal for all channels (default)
- GSICS where available (IR currently) and nominal for the remaining
channels (VIS & HRV currently)
In order to change the default behaviour, use the ``reader_kwargs`` keyword
argument upon Scene creation::
import satpy
scene = satpy.Scene(filenames,
reader='seviri_l1b_...',
reader_kwargs={'calib_mode': 'GSICS'})
scene.load(['VIS006', 'IR_108'])
Furthermore, it is possible to specify external calibration coefficients
for the conversion from counts to radiances. External coefficients take
precedence over internal coefficients, but you can also mix internal and
external coefficients: If external calibration coefficients are specified
for only a subset of channels, the remaining channels will be calibrated
using the chosen file-internal coefficients (nominal or GSICS).
Calibration coefficients must be specified in [mW m-2 sr-1 (cm-1)-1].
In the following example we use external calibration coefficients for the
``VIS006`` & ``IR_108`` channels, and nominal coefficients for the
remaining channels::
coefs = {'VIS006': {'gain': 0.0236, 'offset': -1.20},
'IR_108': {'gain': 0.2156, 'offset': -10.4}}
scene = satpy.Scene(filenames,
reader='seviri_l1b_...',
reader_kwargs={'ext_calib_coefs': coefs})
scene.load(['VIS006', 'VIS008', 'IR_108', 'IR_120'])
In the next example we use we use external calibration coefficients for the
``VIS006`` & ``IR_108`` channels, GSICS coefficients where available
(other IR channels) and nominal coefficients for the rest::
coefs = {'VIS006': {'gain': 0.0236, 'offset': -1.20},
'IR_108': {'gain': 0.2156, 'offset': -10.4}}
scene = satpy.Scene(filenames,
reader='seviri_l1b_...',
reader_kwargs={'calib_mode': 'GSICS',
'ext_calib_coefs': coefs})
scene.load(['VIS006', 'VIS008', 'IR_108', 'IR_120'])
**Calibration to reflectance**
When loading solar channels, the SEVIRI L1.5 readers apply a correction for
the Sun-Earth distance variation throughout the year - as recommended by
the EUMETSAT document `Conversion from radiances to reflectances for SEVIRI warm channels`_.
In the unlikely situation that this correction is not required, it can be
removed on a per-channel basis using
:func:`satpy.readers.utils.remove_earthsun_distance_correction`.
.. _Conversion from radiances to reflectances for SEVIRI warm channels:
https://www.eumetsat.int/website/wcm/idc/idcplg?IdcService=GET_FILE&dDocName=PDF_MSG_SEVIRI_RAD2REFL&
RevisionSelectionMethod=LatestReleased&Rendition=Web
"""

def __init__(self, calib_mode='nominal', ext_calib_coefs=None):
"""Initialize the file handler.
Args:
calib_mode: Calibration mode for converting counts to radiances.
Either "nominal" or "GSICS". Default is "nominal".
ext_calib_coefs: External calibration coefficients.
"""
self.calib_mode = calib_mode
self.ext_calib_coefs = ext_calib_coefs or {}


class SEVIRICalibrationAlgorithm:
"""SEVIRI calibration algorithms."""

Expand Down
82 changes: 14 additions & 68 deletions satpy/readers/seviri_l1b_hrit.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,10 @@
scn['IR_108']['y'] = mi
scn['IR_108'].sel(time=np.datetime64('2019-03-01T12:06:13.052000000'))
Notes:
When loading solar channels, this reader applies a correction for the
Sun-Earth distance variation throughout the year - as recommended by
the EUMETSAT document:
'Conversion from radiances to reflectances for SEVIRI warm channels'
In the unlikely situation that this correction is not required, it can be
removed on a per-channel basis using the
satpy.readers.utils.remove_earthsun_distance_correction(channel, utc_time)
function.
References:
- `MSG Level 1.5 Image Format Description`_
- `Radiometric Calibration of MSG SEVIRI Level 1.5 Image Data in Equivalent Spectral Blackbody Radiance`_
- `Conversion from radiances to reflectances for SEVIRI warm channels`_
.. _MSG Level 1.5 Image Format Description: http://www.eumetsat.int/website/wcm/idc/idcplg?IdcService=GET_FILE&dDocName=
Expand All @@ -143,10 +132,6 @@
https://www.eumetsat.int/website/wcm/idc/idcplg?IdcService=GET_FILE&dDocName=PDF_TEN_MSG_SEVIRI_RAD_CALIB&
RevisionSelectionMethod=LatestReleased&Rendition=Web
.. _Conversion from radiances to reflectances for SEVIRI warm channels:
https://www.eumetsat.int/website/wcm/idc/idcplg?IdcService=GET_FILE&dDocName=PDF_MSG_SEVIRI_RAD2REFL&
RevisionSelectionMethod=LatestReleased&Rendition=Web
"""

from __future__ import division
Expand All @@ -171,7 +156,8 @@
from satpy.readers.seviri_base import (CHANNEL_NAMES, SATNUM,
SEVIRICalibrationHandler,
chebyshev, get_cds_time, HRV_NUM_COLUMNS,
pad_data_horizontally, create_coef_dict)
pad_data_horizontally, create_coef_dict,
SEVIRIBaseFileHandler)
from satpy.readers.seviri_l1b_native_hdr import (hrit_epilogue, hrit_prologue,
impf_configuration)
from satpy.readers._geos_area import get_area_extent, get_area_definition
Expand Down Expand Up @@ -435,55 +421,12 @@ def reduce(self, max_size):
return self._reduce(self.epilogue, max_size=max_size)


class HRITMSGFileHandler(HRITFileHandler):
class HRITMSGFileHandler(HRITFileHandler, SEVIRIBaseFileHandler):
"""SEVIRI HRIT format reader.
**Calibration**
It is possible to choose between two file-internal calibration coefficients for the conversion
from counts to radiances:
- Nominal for all channels (default)
- GSICS for IR channels and nominal for VIS channels
In order to change the default behaviour, use the ``reader_kwargs`` upon Scene creation::
import satpy
import glob
filenames = glob.glob('H-000-MSG3*')
scene = satpy.Scene(filenames,
reader='seviri_l1b_hrit',
reader_kwargs={'calib_mode': 'GSICS'})
scene.load(['VIS006', 'IR_108'])
Furthermore, it is possible to specify external calibration coefficients for the conversion from
counts to radiances. They must be specified in [mW m-2 sr-1 (cm-1)-1]. External coefficients
take precedence over internal coefficients. If external calibration coefficients are specified
for only a subset of channels, the remaining channels will be calibrated using the chosen
file-internal coefficients (nominal or GSICS).
In the following example we use external calibration coefficients for the ``VIS006`` &
``IR_108`` channels, and nominal coefficients for the remaining channels::
coefs = {'VIS006': {'gain': 0.0236, 'offset': -1.20},
'IR_108': {'gain': 0.2156, 'offset': -10.4}}
scene = satpy.Scene(filenames,
reader='seviri_l1b_hrit',
reader_kwargs={'ext_calib_coefs': coefs})
scene.load(['VIS006', 'VIS008', 'IR_108', 'IR_120'])
In the next example we use we use external calibration coefficients for the ``VIS006`` &
``IR_108`` channels, nominal coefficients for the remaining VIS channels and GSICS coefficients
for the remaining IR channels::
coefs = {'VIS006': {'gain': 0.0236, 'offset': -1.20},
'IR_108': {'gain': 0.2156, 'offset': -10.4}}
scene = satpy.Scene(filenames,
reader='seviri_l1b_hrit',
reader_kwargs={'calib_mode': 'GSICS',
'ext_calib_coefs': coefs})
scene.load(['VIS006', 'VIS008', 'IR_108', 'IR_120'])
See :class:`satpy.readers.seviri_base.SEVIRIBaseFileHandler`.
**Raw Metadata**
Expand Down Expand Up @@ -511,11 +454,16 @@ def __init__(self, filename, filename_info, filetype_info,
prologue, epilogue, calib_mode='nominal',
ext_calib_coefs=None, mda_max_array_size=100, fill_hrv=True):
"""Initialize the reader."""
super(HRITMSGFileHandler, self).__init__(filename, filename_info,
filetype_info,
(msg_hdr_map,
msg_variable_length_headers,
msg_text_headers))
HRITFileHandler.__init__(
self,
filename,
filename_info,
filetype_info,
(msg_hdr_map,
msg_variable_length_headers,
msg_text_headers)
)
SEVIRIBaseFileHandler.__init__(self, calib_mode, ext_calib_coefs)

self.prologue_ = prologue
self.epilogue_ = epilogue
Expand All @@ -524,8 +472,6 @@ def __init__(self, filename, filename_info, filetype_info,
self._filename_info = filename_info
self.mda_max_array_size = mda_max_array_size
self.fill_hrv = fill_hrv
self.calib_mode = calib_mode
self.ext_calib_coefs = ext_calib_coefs or {}

self._get_header()

Expand Down
34 changes: 9 additions & 25 deletions satpy/readers/seviri_l1b_native.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,14 @@
# satpy. If not, see <http://www.gnu.org/licenses/>.
"""SEVIRI native format reader.
Notes:
When loading solar channels, this reader applies a correction for the
Sun-Earth distance variation throughout the year - as recommended by
the EUMETSAT document:
'Conversion from radiances to reflectances for SEVIRI warm channels'
In the unlikely situation that this correction is not required, it can be
removed on a per-channel basis using the
satpy.readers.utils.remove_earthsun_distance_correction(channel, utc_time)
function.
References:
- `MSG Level 1.5 Native Format File Definition`_
- `MSG Level 1.5 Image Data Format Description`_
- `Conversion from radiances to reflectances for SEVIRI warm channels`_
.. _MSG Level 1.5 Native Format File Definition
.. _MSG Level 1.5 Native Format File Definition:
https://www-cdn.eumetsat.int/files/2020-04/pdf_fg15_msg-native-format-15.pdf
.. _MSG Level 1.5 Image Data Format Description
.. _MSG Level 1.5 Image Data Format Description:
https://www-cdn.eumetsat.int/files/2020-05/pdf_ten_05105_msg_img_data.pdf
.. _Conversion from radiances to reflectances for SEVIRI warm channels:
https://www-cdn.eumetsat.int/files/2020-04/pdf_msg_seviri_rad2refl.pdf
"""

Expand All @@ -58,7 +45,7 @@
SEVIRICalibrationHandler, CHANNEL_NAMES, SATNUM, dec10216,
VISIR_NUM_COLUMNS, VISIR_NUM_LINES, HRV_NUM_COLUMNS, HRV_NUM_LINES,
create_coef_dict, get_service_mode, pad_data_horizontally,
pad_data_vertically
pad_data_vertically, SEVIRIBaseFileHandler
)
from satpy.readers.seviri_l1b_native_hdr import (GSDTRecords, native_header,
native_trailer)
Expand All @@ -67,12 +54,12 @@
logger = logging.getLogger('native_msg')


class NativeMSGFileHandler(BaseFileHandler):
class NativeMSGFileHandler(BaseFileHandler, SEVIRIBaseFileHandler):
"""SEVIRI native format reader.
The Level1.5 Image data calibration method can be changed by adding the
required mode to the Scene object instantiation kwargs eg
kwargs = {"calib_mode": "gsics",}
**Calibration**
See :class:`satpy.readers.seviri_base.SEVIRIBaseFileHandler`.
**Padding channel data to full disk**
Expand All @@ -89,12 +76,9 @@ class NativeMSGFileHandler(BaseFileHandler):
def __init__(self, filename, filename_info, filetype_info,
calib_mode='nominal', fill_disk=False, ext_calib_coefs=None):
"""Initialize the reader."""
super(NativeMSGFileHandler, self).__init__(filename,
filename_info,
filetype_info)
BaseFileHandler.__init__(self, filename, filename_info, filetype_info)
SEVIRIBaseFileHandler.__init__(self, calib_mode, ext_calib_coefs)
self.platform_name = None
self.calib_mode = calib_mode
self.ext_calib_coefs = ext_calib_coefs or {}
self.fill_disk = fill_disk

# Declare required variables.
Expand Down
33 changes: 14 additions & 19 deletions satpy/readers/seviri_l1b_nc.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,19 @@
# satpy. If not, see <http://www.gnu.org/licenses/>.
"""SEVIRI netcdf format reader.
Notes:
When loading solar channels, this reader applies a correction for the
Sun-Earth distance variation throughout the year - as recommended by
the EUMETSAT document:
'Conversion from radiances to reflectances for SEVIRI warm channels'
In the unlikely situation that this correction is not required, it can be
removed on a per-channel basis using the
satpy.readers.utils.remove_earthsun_distance_correction(channel, utc_time)
function.
References:
- `MSG Level 1.5 Image Data Format Description`_
- `Conversion from radiances to reflectances for SEVIRI warm channels`_
.. _MSG Level 1.5 Image Data Format Description:
https://www.eumetsat.int/website/wcm/idc/idcplg?IdcService=GET_FILE&dDocName=PDF_TEN_05105_MSG_IMG_DATA&
RevisionSelectionMethod=LatestReleased&Rendition=Web
.. _Conversion from radiances to reflectances for SEVIRI warm channels:
https://www.eumetsat.int/website/wcm/idc/idcplg?IdcService=GET_FILE&dDocName=PDF_MSG_SEVIRI_RAD2REFL&
RevisionSelectionMethod=LatestReleased&Rendition=Web
"""

from satpy.readers.file_handlers import BaseFileHandler
from satpy.readers.seviri_base import (SEVIRICalibrationHandler,
CHANNEL_NAMES, SATNUM)
CHANNEL_NAMES, SATNUM,
SEVIRIBaseFileHandler)
import xarray as xr

from satpy.readers._geos_area import get_area_definition
Expand All @@ -51,14 +38,22 @@
import datetime


class NCSEVIRIFileHandler(BaseFileHandler):
"""File handler for NC seviri files."""
class NCSEVIRIFileHandler(BaseFileHandler, SEVIRIBaseFileHandler):
"""File handler for NC seviri files.
**Calibration**
See :class:`satpy.readers.seviri_base.SEVIRIBaseFileHandler`. Note that
there is only one set of calibration coefficients (GSICS) available in the
netCDF files and therefore there is no `calib_mode` argument.
"""

def __init__(self, filename, filename_info, filetype_info,
ext_calib_coefs=None):
"""Init the file handler."""
super(NCSEVIRIFileHandler, self).__init__(filename, filename_info, filetype_info)
self.ext_calib_coefs = ext_calib_coefs or {}
BaseFileHandler.__init__(self, filename, filename_info,
filetype_info)
SEVIRIBaseFileHandler.__init__(self, ext_calib_coefs=ext_calib_coefs)
self.nc = None
self.mda = {}
self.reference = datetime.datetime(1958, 1, 1)
Expand Down

0 comments on commit dfb9d73

Please sign in to comment.