diff --git a/satpy/etc/readers/fci_l2_bufr.yaml b/satpy/etc/readers/fci_l2_bufr.yaml index 1754093fcd..33dbbb587f 100644 --- a/satpy/etc/readers/fci_l2_bufr.yaml +++ b/satpy/etc/readers/fci_l2_bufr.yaml @@ -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) @@ -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 diff --git a/satpy/etc/readers/fci_l2_nc.yaml b/satpy/etc/readers/fci_l2_nc.yaml index 04962740b7..80bf68ad87 100644 --- a/satpy/etc/readers/fci_l2_nc.yaml +++ b/satpy/etc/readers/fci_l2_nc.yaml @@ -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) @@ -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 @@ -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 diff --git a/satpy/readers/eum_l2_bufr.py b/satpy/readers/eum_l2_bufr.py index 95f378378a..06a66e6deb 100644 --- a/satpy/readers/eum_l2_bufr.py +++ b/satpy/readers/eum_l2_bufr.py @@ -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 @@ -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 diff --git a/satpy/readers/eum_l2_grib.py b/satpy/readers/eum_l2_grib.py index d4d581052b..1d26b24417 100644 --- a/satpy/readers/eum_l2_grib.py +++ b/satpy/readers/eum_l2_grib.py @@ -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 diff --git a/satpy/readers/fci_l2_nc.py b/satpy/readers/fci_l2_nc.py index 730d1ae7ae..6830623975 100644 --- a/satpy/readers/fci_l2_nc.py +++ b/satpy/readers/fci_l2_nc.py @@ -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 @@ -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: @@ -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", @@ -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: @@ -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, @@ -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, @@ -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 @@ -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): @@ -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 diff --git a/satpy/tests/reader_tests/test_eum_l2_grib.py b/satpy/tests/reader_tests/test_eum_l2_grib.py index 4172cf0ea0..3f8a647d1e 100644 --- a/satpy/tests/reader_tests/test_eum_l2_grib.py +++ b/satpy/tests/reader_tests/test_eum_l2_grib.py @@ -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_): @@ -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_): diff --git a/satpy/tests/reader_tests/test_fci_l2_nc.py b/satpy/tests/reader_tests/test_fci_l2_nc.py index 2761e92c60..4908fa6e98 100644 --- a/satpy/tests/reader_tests/test_fci_l2_nc.py +++ b/satpy/tests/reader_tests/test_fci_l2_nc.py @@ -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", @@ -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):