diff --git a/satpy/readers/fci_l1c_nc.py b/satpy/readers/fci_l1c_nc.py index fc40916699..69ded90dd5 100644 --- a/satpy/readers/fci_l1c_nc.py +++ b/satpy/readers/fci_l1c_nc.py @@ -182,6 +182,18 @@ def _get_channel_name_from_dsname(dsname): return channel_name +# Platform names according to the MTG FCI L1 Product User Guide, +# EUM/MTG/USR/13/719113 from 2019-06-27, pages 32 and 124, are MTI1, MTI2, +# MTI3, and MTI4, but we want to use names such as described in WMO OSCAR +# MTG-I1, MTG-I2, MTG-I3, and MTG-I4. +# +# Not sure how the numbering will be considering MTG-S1 and MTG-S2 will be launched +# in-between. +_platform_name_translate = { + "MTI1": "Meteosat-12", + "MTI2": "MTG-I2", + "MTI3": "MTG-I3", + "MTI4": "MTG-I4"} class FCIL1cNCFileHandler(NetCDF4FsspecFileHandler): """Class implementing the MTG FCI L1c Filehandler. @@ -193,21 +205,6 @@ class using the :mod:`~satpy.Scene.load` method with the reader ``"fci_l1c_nc"``. """ - - # Platform names according to the MTG FCI L1 Product User Guide, - # EUM/MTG/USR/13/719113 from 2019-06-27, pages 32 and 124, are MTI1, MTI2, - # MTI3, and MTI4, but we want to use names such as described in WMO OSCAR - # MTG-I1, MTG-I2, MTG-I3, and MTG-I4. - # - # After launch: translate to METEOSAT-xx instead? Not sure how the - # numbering will be considering MTG-S1 and MTG-S2 will be launched - # in-between. - _platform_name_translate = { - "MTI1": "MTG-I1", - "MTI2": "MTG-I2", - "MTI3": "MTG-I3", - "MTI4": "MTG-I4"} - def __init__(self, filename, filename_info, filetype_info): """Initialize file handler.""" super().__init__(filename, filename_info, @@ -391,7 +388,7 @@ def _get_dataset_measurand(self, key, info=None): res.attrs.update(info) res.attrs.update(attrs) - res.attrs["platform_name"] = self._platform_name_translate.get( + res.attrs["platform_name"] = _platform_name_translate.get( self["attr/platform"], self["attr/platform"]) # remove unpacking parameters for calibrated data diff --git a/satpy/readers/li_base_nc.py b/satpy/readers/li_base_nc.py index a65129c904..6b753e0a44 100644 --- a/satpy/readers/li_base_nc.py +++ b/satpy/readers/li_base_nc.py @@ -191,6 +191,7 @@ import xarray as xr from pyproj import Proj +from satpy.readers.fci_l1c_nc import _platform_name_translate from satpy.readers.netcdf_utils import NetCDF4FsspecFileHandler logger = logging.getLogger(__name__) @@ -516,10 +517,13 @@ def register_dataset(self, var_name, oc_name=None): ds_name = var_name if oc_name is None else f"{var_name}_{oc_name}_sector" + platform = self.filename_info["mission_prefix"] + "I" + self.filename_info["spacecraft_id"] + ds_info = { "name": ds_name, "variable_name": var_name, "sensor": "li", + "platform_name": _platform_name_translate[platform], "file_type": self.filetype_info["file_type"] } diff --git a/satpy/tests/reader_tests/test_fci_l1c_nc.py b/satpy/tests/reader_tests/test_fci_l1c_nc.py index aa98990df3..92f64bfb59 100644 --- a/satpy/tests/reader_tests/test_fci_l1c_nc.py +++ b/satpy/tests/reader_tests/test_fci_l1c_nc.py @@ -1027,7 +1027,7 @@ def test_platform_name(self, reader_configs, fh_param): """ reader = _get_reader_with_filehandlers(fh_param["filenames"], reader_configs) res = reader.load(["vis_06"], pad_data=False) - assert res["vis_06"].attrs["platform_name"] == "MTG-I1" + assert res["vis_06"].attrs["platform_name"] == "Meteosat-12" @pytest.mark.parametrize(("fh_param", "compare_tuples"), [(lazy_fixture("FakeFCIFileHandlerFDHSI_fixture"), (67, 10, diff --git a/satpy/tests/reader_tests/test_li_l2_nc.py b/satpy/tests/reader_tests/test_li_l2_nc.py index 13981a37f4..c83ebe3aa0 100644 --- a/satpy/tests/reader_tests/test_li_l2_nc.py +++ b/satpy/tests/reader_tests/test_li_l2_nc.py @@ -175,7 +175,9 @@ def test_dataset_loading(self, filetype_infos): ftype = pinfo["ftype"] filename_info = { "start_time": "0000", - "end_time": "1000" + "end_time": "1000", + "mission_prefix": "MT", + "spacecraft_id": "1" } handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, ftype), @@ -195,9 +197,15 @@ def test_dataset_loading(self, filetype_infos): def test_unregistered_dataset_loading(self, filetype_infos): """Test loading of an unregistered dataset.""" + filename_info = { + "start_time": "0000", + "end_time": "1000", + "mission_prefix": "MT", + "spacecraft_id": "1" + } # Iterate on all the available product types: - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc")) + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc")) dataset_id = make_dataid(name="test_dataset") with pytest.raises(KeyError): @@ -205,11 +213,17 @@ def test_unregistered_dataset_loading(self, filetype_infos): def test_dataset_not_in_provided_dataset(self, filetype_infos): """Test loading of a dataset that is not provided.""" + filename_info = { + "start_time": "0000", + "end_time": "1000", + "mission_prefix": "MT", + "spacecraft_id": "1" + } # Iterate on all the available product types: dataset_dict = {"name": "test_dataset"} - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc")) + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc")) dataset_id = make_dataid(name="test_dataset") @@ -219,7 +233,10 @@ def test_filename_infos(self, filetype_infos): """Test settings retrieved from filename.""" filename_info = { "start_time": "20101112131415", - "end_time": "20101112131416" + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc")) @@ -246,11 +263,29 @@ def test_filename_infos(self, filetype_infos): # check product type: assert handler.product_type == "2-AF" + def test_platform_name_and_sensor(self, filetype_infos): + """Test that plaform name and sensor attributes are set.""" + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + + } + + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lfl_nc")) + dsid = make_dataid(name="flash_duration") + dset = handler.get_dataset(dsid) + assert dset.attrs["platform_name"] == "Meteosat-12" + assert dset.attrs["sensor"] == "li" + def test_var_path_exists(self, filetype_infos): """Test variable_path_exists from li reader.""" filename_info = { "start_time": "20101112131415", "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" } handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lef_nc")) @@ -272,6 +307,8 @@ def test_get_first_valid_variable(self, filetype_infos): filename_info = { "start_time": "20101112131415", "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" } handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lef_nc")) @@ -324,6 +361,8 @@ def test_get_first_valid_variable_not_found(self, filetype_infos): filename_info = { "start_time": "20101112131415", "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" } handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lef_nc")) @@ -333,7 +372,13 @@ def test_get_first_valid_variable_not_found(self, filetype_infos): def test_available_datasets(self, filetype_infos): """Test available_datasets from li reader.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_lef_nc")) + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lef_nc")) # get current ds_infos. These should all be returned by the available_datasets ds_infos_to_compare = handler.dataset_infos.copy() @@ -349,7 +394,9 @@ def test_variable_scaling(self, filetype_infos): """Test automatic rescaling with offset and scale attributes.""" filename_info = { "start_time": "20101112131415", - "end_time": "20101112131416" + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" } handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lfl_nc")) @@ -379,7 +426,13 @@ def test_variable_scaling(self, filetype_infos): def test_swath_coordinates(self, filetype_infos): """Test that swath coordinates are used correctly to assign coordinates to some datasets.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_lfl_nc")) + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lfl_nc")) # Check latitude: dsid = make_dataid(name="latitude") @@ -402,7 +455,13 @@ def test_swath_coordinates(self, filetype_infos): def test_report_datetimes(self, filetype_infos): """Should report time variables as numpy datetime64 type and time durations as timedelta64.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_le_nc")) + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_le_nc")) # Check epoch_time: dsid = make_dataid(name="epoch_time_north_sector") @@ -432,7 +491,13 @@ def test_report_datetimes(self, filetype_infos): def test_milliseconds_to_timedelta(self, filetype_infos): """Should covert milliseconds to timedelta.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_lfl_nc")) + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lfl_nc")) # Check flash_duration: dsid = make_dataid(name="flash_duration") @@ -447,7 +512,13 @@ def test_milliseconds_to_timedelta(self, filetype_infos): def test_apply_accumulate_index_offset(self, filetype_infos): """Should accumulate index offsets.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_le_nc")) + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_le_nc")) # Check time offset: dsid = make_dataid(name="l1b_chunk_offsets_north_sector") @@ -467,7 +538,13 @@ def test_apply_accumulate_index_offset(self, filetype_infos): def test_combine_info(self, filetype_infos): """Test overridden combine_info.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_le_nc")) + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_le_nc")) # get a dataset including the index_offset in the ds_info dsid = make_dataid(name="l1b_chunk_offsets_north_sector") @@ -485,7 +562,13 @@ def test_combine_info(self, filetype_infos): def test_coordinates_projection(self, filetype_infos): """Should automatically generate lat/lon coords from projection data.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc"), + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc"), with_area_definition=False) dsid = make_dataid(name="flash_accumulation") @@ -498,7 +581,7 @@ def test_coordinates_projection(self, filetype_infos): with pytest.raises(NotImplementedError): handler.get_area_def(dsid) - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_afr_nc"), + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_afr_nc"), with_area_definition=False) dsid = make_dataid(name="flash_radiance") @@ -508,7 +591,7 @@ def test_coordinates_projection(self, filetype_infos): assert dset.attrs["coordinates"][0] == "longitude" assert dset.attrs["coordinates"][1] == "latitude" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_afa_nc"), + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_afa_nc"), with_area_definition=False) dsid = make_dataid(name="accumulated_flash_area") @@ -522,10 +605,17 @@ def test_generate_coords_on_accumulated_prods(self, filetype_infos): """Test daskified generation of coords.""" accumulated_products = ["li_l2_af_nc", "li_l2_afr_nc", "li_l2_afa_nc"] coordinate_datasets = ["longitude", "latitude"] + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } for accum_prod in accumulated_products: for ds_name in coordinate_datasets: - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, accum_prod)) + handler = LIL2NCFileHandler("filename", filename_info, + extract_filetype_info(filetype_infos, accum_prod)) dsid = make_dataid(name=ds_name) dset = handler.get_dataset(dsid) # Check dataset type @@ -537,10 +627,17 @@ def test_generate_coords_on_lon_lat(self, filetype_infos): """Test getting lon/lat dataset on accumulated product.""" accumulated_products = ["li_l2_af_nc", "li_l2_afr_nc", "li_l2_afa_nc"] coordinate_datasets = ["longitude", "latitude"] + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } for accum_prod in accumulated_products: for ds_name in coordinate_datasets: - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, accum_prod)) + handler = LIL2NCFileHandler("filename", filename_info, + extract_filetype_info(filetype_infos, accum_prod)) dsid = make_dataid(name=ds_name) handler.generate_coords_from_scan_angles = mock.MagicMock( side_effect=handler.generate_coords_from_scan_angles) @@ -551,10 +648,17 @@ def test_generate_coords_inverse_proj(self, filetype_infos): """Test inverse_projection execution delayed until .values is called on the dataset.""" accumulated_products = ["li_l2_af_nc", "li_l2_afr_nc", "li_l2_afa_nc"] coordinate_datasets = ["longitude", "latitude"] + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } for accum_prod in accumulated_products: for ds_name in coordinate_datasets: - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, accum_prod)) + handler = LIL2NCFileHandler("filename", filename_info, + extract_filetype_info(filetype_infos, accum_prod)) dsid = make_dataid(name=ds_name) handler.inverse_projection = mock.MagicMock(side_effect=handler.inverse_projection) dset = handler.get_dataset(dsid) @@ -575,7 +679,13 @@ def test_generate_coords_not_called_on_non_accum_dataset(self, filetype_infos): def generate_coords(self, filetype_infos, file_type_name, variable_name): """Generate file handler and mimic coordinate generator call.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, file_type_name)) + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, file_type_name)) dsid = make_dataid(name=variable_name) handler.generate_coords_from_scan_angles = mock.MagicMock( side_effect=handler.generate_coords_from_scan_angles) @@ -584,7 +694,13 @@ def generate_coords(self, filetype_infos, file_type_name, variable_name): def test_generate_coords_called_once(Self, filetype_infos): """Test that the method is called only once.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc")) + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc")) # check internal variable is empty assert len(handler.internal_variables) == 0 coordinate_datasets = ["longitude", "latitude"] @@ -604,8 +720,14 @@ def test_coords_generation(self, filetype_infos): "li_l2_afr_nc", "li_l2_afa_nc"] + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } for prod in products: - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, prod)) + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, prod)) # Get azimuth/elevation arrays from handler azimuth = handler.get_measured_variable(handler.swath_coordinates["azimuth"]) @@ -650,7 +772,13 @@ def test_coords_generation(self, filetype_infos): def test_coords_and_grid_consistency(self, filetype_infos): """Compare computed latlon coords for 1-d version with latlon from areadef as for the gridded version.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc"), + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc"), with_area_definition=True) # Get cols/rows arrays from handler @@ -674,7 +802,13 @@ def test_coords_and_grid_consistency(self, filetype_infos): def test_get_area_def_acc_products(self, filetype_infos): """Test retrieval of area def for accumulated products.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc"), + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc"), with_area_definition=True) dsid = make_dataid(name="flash_accumulation") @@ -688,7 +822,13 @@ def test_get_area_def_acc_products(self, filetype_infos): def test_get_area_def_non_acc_products(self, filetype_infos): """Test retrieval of area def for non-accumulated products.""" - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_lgr_nc"), + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_lgr_nc"), with_area_definition=True) # Should throw for non-accum products: with pytest.raises(NotImplementedError): @@ -713,8 +853,14 @@ def write_flash_accum(_vname, _ocname, _settings): def test_without_area_def(self, filetype_infos): """Test accumulated products data array without area definition.""" # without area definition + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } handler_without_area_def = LIL2NCFileHandler( - "filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc"), with_area_definition=False) + "filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc"), with_area_definition=False) dsid = make_dataid(name="flash_accumulation") @@ -763,19 +909,31 @@ def test_with_area_def_vars_with_no_pattern(self, filetype_infos): def handler_with_area(self, filetype_infos, product_name): """Create handler with area definition.""" + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } # Note: we need a test param provider here to ensure we write the same values for both handlers below: FakeLIFileHandlerBase.schema_parameters = TestLIL2.param_provider # with area definition - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, product_name), + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, product_name), with_area_definition=True) return handler def test_with_area_def_pixel_placement(self, filetype_infos): """Test the placements of pixel value with area definition.""" + filename_info = { + "start_time": "20101112131415", + "end_time": "20101112131416", + "mission_prefix": "MT", + "spacecraft_id": "1" + } # with area definition FakeLIFileHandlerBase.schema_parameters = TestLIL2.param_provider - handler = LIL2NCFileHandler("filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc"), + handler = LIL2NCFileHandler("filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc"), with_area_definition=True) dsid = make_dataid(name="flash_accumulation") @@ -787,7 +945,7 @@ def test_with_area_def_pixel_placement(self, filetype_infos): yarr = handler.get_measured_variable("y").values.astype(int) handler_without_area_def = LIL2NCFileHandler( - "filename", {}, extract_filetype_info(filetype_infos, "li_l2_af_nc"), with_area_definition=False) + "filename", filename_info, extract_filetype_info(filetype_infos, "li_l2_af_nc"), with_area_definition=False) FakeLIFileHandlerBase.schema_parameters = None