Skip to content
80 changes: 80 additions & 0 deletions satpy/etc/readers/fci_l2_bufr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,34 @@ datasets:
- latitude

# ---- ASR products ------------
vza:
name: vza
long_name: Satellite Viewing Zenith Angle
standard_name: viewing_zenith_angle
resolution: 32000
file_type: fci_l2_bufr_asr
key: '#1#satelliteZenithAngle'
cell_method: area:mean
units: K
fill_value: -1.0e+100
coordinates:
- longitude
- latitude

sza:
name: sza
long_name: Solar Zenith Angle
standard_name: solar_zenith_angle
resolution: 32000
file_type: fci_l2_bufr_asr
key: '#1#solarZenithAngle'
cell_method: area:mean
units: K
fill_value: -1.0e+100
coordinates:
- longitude
- latitude

bt_mean_all_ir38:
name: bt_mean_all_ir38
long_name: TOA Brightness Temperature segment mean at 3.8um (all pixels)
Expand Down Expand Up @@ -1253,3 +1281,55 @@ datasets:
coordinates:
- longitude
- latitude

pixel_percentage_cloudy:
name: pixel_percentage_cloudy
long_name: Cloud Fraction in Segment
standard_name: pixels_used_fraction
resolution: 32000
file_type: fci_l2_bufr_asr
key: '#1#cloudAmountInSegment'
fill_value: -1.0e+100
units: '%'
coordinates:
- longitude
- latitude

pixel_percentage_cloudy_low:
name: pixel_percentage_cloudy_low
long_name: Low Cloud Fraction in Segment
standard_name: pixels_used_fraction
resolution: 32000
file_type: fci_l2_bufr_asr
key: '#2#cloudAmountInSegment'
fill_value: -1.0e+100
units: '%'
coordinates:
- longitude
- latitude

pixel_percentage_cloudy_mid:
name: pixel_percentage_cloudy_mid
long_name: Middle Cloud Fraction in Segment
standard_name: pixels_used_fraction
resolution: 32000
file_type: fci_l2_bufr_asr
key: '#3#cloudAmountInSegment'
fill_value: -1.0e+100
units: '%'
coordinates:
- longitude
- latitude

pixel_percentage_cloudy_high:
name: pixel_percentage_cloudy_high
long_name: High Cloud Fraction in Segment
standard_name: pixels_used_fraction
resolution: 32000
file_type: fci_l2_bufr_asr
key: '#4#cloudAmountInSegment'
fill_value: -1.0e+100
units: '%'
coordinates:
- longitude
- latitude
69 changes: 69 additions & 0 deletions satpy/etc/readers/fci_l2_nc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,14 @@ datasets:
file_type: nc_fci_crm
nc_key: mean_solar_zenith

mean_vza:
name: mean_vza
long_name: Satellite Viewing Zenith Angle (temporal average)
standard_name: viewing_zenith_angle
resolution: 1000
file_type: nc_fci_crm
nc_key: mean_satellite_zenith

mean_rel_azi:
name: mean_rel_azi
long_name: Relative Solar Satellite Azimuth Angle (temporal average)
Expand Down Expand Up @@ -1377,6 +1385,28 @@ datasets:
import_enum_information: True

# ASR - All-Sky Radiances
vza:
name: vza
long_name: Satellite Viewing Zenith Angle
standard_name: viewing_zenith_angle
resolution: 32000
file_type: nc_fci_asr
nc_key: satellite_zenith_angle
coordinates:
- longitude
- latitude

sza:
name: sza
long_name: Solar Zenith Angle
standard_name: solar_zenith_angle
resolution: 32000
file_type: nc_fci_asr
nc_key: solar_zenith_angle
coordinates:
- longitude
- latitude

bt_max:
name: bt_max
long_name: TOA Brightess Temperature Segment max
Expand Down Expand Up @@ -3147,3 +3177,42 @@ datasets:
coordinates:
- longitude
- latitude

pixel_percentage_cloudy_low:
name: pixel_percentage_cloudy_low
long_name: Percentage of FoR pixels used (cloudy pixels)
standard_name: pixels_used_fraction
resolution: 32000
file_type: nc_fci_asr
nc_key: pixel_percentage
category_id: 3
units: '%'
coordinates:
- longitude
- latitude

pixel_percentage_cloudy_mid:
name: pixel_percentage_cloudy_mid
long_name: Percentage of FoR pixels used (cloudy pixels)
standard_name: pixels_used_fraction
resolution: 32000
file_type: nc_fci_asr
nc_key: pixel_percentage
category_id: 4
units: '%'
coordinates:
- longitude
- latitude

pixel_percentage_cloudy_high:
name: pixel_percentage_cloudy_high
long_name: Percentage of FoR pixels used (cloudy pixels)
standard_name: pixels_used_fraction
resolution: 32000
file_type: nc_fci_asr
nc_key: pixel_percentage
category_id: 5
units: '%'
coordinates:
- longitude
- latitude
4 changes: 2 additions & 2 deletions satpy/readers/eum_l2_bufr.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from satpy.readers.core.eum import get_service_mode, recarray2dict
from satpy.readers.core.file_handlers import BaseFileHandler
from satpy.readers.core.seviri import mpef_product_header
from satpy.utils import get_legacy_chunk_size
from satpy.utils import get_chunk_size_limit

try:
import eccodes as ec
Expand All @@ -47,7 +47,7 @@

logger = logging.getLogger("EumetsatL2Bufr")

CHUNK_SIZE = get_legacy_chunk_size()
CHUNK_SIZE = get_chunk_size_limit()

SSP_DEFAULT = 0.0
BUFR_FILL_VALUE = -1.e+100
Expand Down
4 changes: 2 additions & 2 deletions satpy/readers/eum_l2_grib.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
from satpy.readers.core.seviri import REPEAT_CYCLE_DURATION as SEVIRI_REPEAT_CYCLE_DURATION
from satpy.readers.core.seviri import REPEAT_CYCLE_DURATION_RSS as SEVIRI_REPEAT_CYCLE_DURATION_RSS
from satpy.readers.core.seviri import calculate_area_extent as seviri_calculate_area_extent
from satpy.utils import get_legacy_chunk_size
from satpy.utils import get_chunk_size_limit

CHUNK_SIZE = get_legacy_chunk_size()
CHUNK_SIZE = get_chunk_size_limit()

try:
import eccodes as ec
Expand Down
42 changes: 27 additions & 15 deletions satpy/readers/fci_l2_nc.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
from satpy.readers.core.eum import get_service_mode
from satpy.readers.core.fci import platform_name_translate
from satpy.readers.core.file_handlers import BaseFileHandler
from satpy.utils import get_legacy_chunk_size
from satpy.utils import get_chunk_size_limit

logger = logging.getLogger(__name__)

CHUNK_SIZE = get_legacy_chunk_size()
CHUNK_SIZE = get_chunk_size_limit()

SSP_DEFAULT = 0.0

Expand All @@ -55,15 +55,22 @@ def sensor_name(self):

@property
def ssp_lon(self):
"""Return longitude at subsatellite point."""
"""Return central longitude of GEOS projection grid.

This is needed to compute the area definition for the gridded products (pixel-based and segmented).
For the AMV product it is not needed and therefore no warning is issued if missing.
"""
try:
return float(self.nc["mtg_geos_projection"].attrs["longitude_of_projection_origin"])
except (KeyError, AttributeError):
logger.warning(f"ssp_lon could not be obtained from file content, using default value "
f"of {SSP_DEFAULT} degrees east instead")
if self.product_type != "amv":
logger.warning(
f"ssp_lon could not be obtained from file content, "
f"using default value of {SSP_DEFAULT} degrees east instead"
)
return SSP_DEFAULT

def _get_global_attributes(self, product_type="pixel"):
def _get_global_attributes(self):
"""Create a dictionary of global attributes to be added to all datasets.

Returns:
Expand All @@ -86,18 +93,19 @@ def _get_global_attributes(self, product_type="pixel"):
"platform_name": platform_name_translate.get(self.spacecraft_name, self.spacecraft_name)
}

if product_type=="amv":
if self.product_type == "amv":
attributes["channel"] = self.filename_info["channel"]
attributes["time_parameters"] = {}
attributes["time_parameters"]["wind_time"] = self.wind_time

return attributes

def _set_attributes(self, variable, dataset_info, product_type="pixel"):
def _set_attributes(self, variable, dataset_info):
"""Set dataset attributes."""
if product_type in ["pixel", "segmented"]:
if product_type == "pixel":
if self.product_type in ["pixel", "segmented"]:
if self.product_type == "pixel":
xdim, ydim = "number_of_columns", "number_of_rows"
elif product_type == "segmented":
elif self.product_type == "segmented":
xdim, ydim = "number_of_FoR_cols", "number_of_FoR_rows"

if dataset_info["nc_key"] not in ["product_quality",
Expand All @@ -112,7 +120,7 @@ def _set_attributes(self, variable, dataset_info, product_type="pixel"):
del variable.attrs["unit"]

variable.attrs.update(dataset_info)
variable.attrs.update(self._get_global_attributes(product_type=product_type))
variable.attrs.update(self._get_global_attributes())

import_enum_information = dataset_info.get("import_enum_information", False)
if import_enum_information:
Expand Down Expand Up @@ -180,8 +188,9 @@ class FciL2NCFileHandler(FciL2CommonFunctions, BaseFileHandler):
def __init__(self, filename, filename_info, filetype_info, with_area_definition=True):
"""Open the NetCDF file with xarray and prepare for dataset reading."""
super().__init__(filename, filename_info, filetype_info)
self.product_type = "pixel"

# Use xarray's default netcdf4 engine to open the fileq
# Use xarray's default netcdf4 engine to open the file
self.nc = xr.open_dataset(
self.filename,
decode_cf=True,
Expand Down Expand Up @@ -343,6 +352,8 @@ class FciL2NCSegmentFileHandler(FciL2CommonFunctions, BaseFileHandler):
def __init__(self, filename, filename_info, filetype_info, with_area_definition=False):
"""Open the NetCDF file with xarray and prepare for dataset reading."""
super().__init__(filename, filename_info, filetype_info)
self.product_type = "segmented"

# Use xarray's default netcdf4 engine to open the file
self.nc = xr.open_dataset(
self.filename,
Expand Down Expand Up @@ -396,7 +407,7 @@ def get_dataset(self, dataset_id, dataset_info):
if "fill_value" in dataset_info:
variable = self._mask_data(variable, dataset_info["fill_value"])

variable = self._set_attributes(variable, dataset_info, product_type="segmented")
variable = self._set_attributes(variable, dataset_info)

return variable

Expand Down Expand Up @@ -457,6 +468,7 @@ class FciL2NCAMVFileHandler(FciL2CommonFunctions, BaseFileHandler):
def __init__(self, filename, filename_info, filetype_info):
"""Open the NetCDF file with xarray and prepare for dataset reading."""
super().__init__(filename, filename_info, filetype_info)
self.product_type = "amv"

@cached_property
def nc(self):
Expand Down Expand Up @@ -499,6 +511,6 @@ def get_dataset(self, dataset_id, dataset_info):
return None

# Manage the attributes of the dataset
variable = self._set_attributes(variable, dataset_info, product_type="amv")
variable = self._set_attributes(variable, dataset_info)

return variable
8 changes: 4 additions & 4 deletions satpy/tests/reader_tests/test_eum_l2_grib.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ def common_checks(ec_, reader, mock_file, dataset_id):
def test_seviri_data_reading(da_, xr_, setup_reader):
"""Test the reading of data from the product."""
from satpy.readers.eum_l2_grib import EUML2GribFileHandler
from satpy.utils import get_legacy_chunk_size
from satpy.utils import get_chunk_size_limit
ec_ = setup_reader
chunk_size = get_legacy_chunk_size()
chunk_size = get_chunk_size_limit()

with mock.patch("builtins.open", mock.mock_open()) as mock_file:
with mock.patch("satpy.readers.eum_l2_grib.ec", ec_):
Expand Down Expand Up @@ -214,9 +214,9 @@ def test_seviri_data_reading(da_, xr_, setup_reader):
def test_fci_data_reading(da_, xr_, setup_reader):
"""Test the reading of fci data from the product."""
from satpy.readers.eum_l2_grib import EUML2GribFileHandler
from satpy.utils import get_legacy_chunk_size
from satpy.utils import get_chunk_size_limit
ec_ = setup_reader
chunk_size = get_legacy_chunk_size()
chunk_size = get_chunk_size_limit()

with mock.patch("builtins.open", mock.mock_open()) as mock_file:
with mock.patch("satpy.readers.eum_l2_grib.ec", ec_):
Expand Down
6 changes: 3 additions & 3 deletions satpy/tests/reader_tests/test_fci_l2_nc.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ def test_all_basic(self, amv_filehandler, amv_file):
assert amv_filehandler.sensor_name == "test_data_source"
assert amv_filehandler.ssp_lon == 0.0

global_attributes = amv_filehandler._get_global_attributes(product_type="amv")
global_attributes = amv_filehandler._get_global_attributes()
expected_global_attributes = {
"filename": amv_file,
"spacecraft_name": "TEST_PLATFORM",
Expand All @@ -637,8 +637,8 @@ def test_all_basic(self, amv_filehandler, amv_file):

# Drop wind_time dataset and check that wind_time attribute becomes None
amv_filehandler.nc = amv_filehandler.nc.drop_vars("wind_time")
expected_global_attributes["time_parameters"] = {"wind_time":None}
global_attributes = amv_filehandler._get_global_attributes(product_type="amv")
expected_global_attributes["time_parameters"] = {"wind_time": None}
global_attributes = amv_filehandler._get_global_attributes()
assert global_attributes == expected_global_attributes

def test_dataset(self, amv_filehandler):
Expand Down
Loading