diff --git a/satpy/etc/readers/fci_l2_bufr.yaml b/satpy/etc/readers/fci_l2_bufr.yaml
new file mode 100644
index 0000000000..ef515d0471
--- /dev/null
+++ b/satpy/etc/readers/fci_l2_bufr.yaml
@@ -0,0 +1,1256 @@
+reader:
+ name: fci_l2_bufr
+ short_name: FCI l2 BUFR
+ long_name: MTGi Level 2 products in BUFR format
+ description: FCI L2 BUFR Product Reader
+ status: Alpha
+ supports_fsspec: false
+ sensors: [fci]
+ default_channels: []
+ reader: !!python/name:satpy.readers.yaml_reader.GEOFlippableFileYAMLReader
+
+file_types:
+ fci_l2_bufr_asr:
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
+ file_patterns:
+ - '{pflag}_{location_indicator},{data_designator},MTI{spacecraft_id:1d}+FCI-2-ASR-{subtype}-{coverage}-{subsetting}-{component1}-{component2}-{component3}-{purpose}-BUFR_{oflag}_{originator}_{processing_time:%Y%m%d%H%M%S}_{facility_or_tool}_{environment}_{start_time:%Y%m%d%H%M%S}_{end_time:%Y%m%d%H%M%S}_{processing_mode}_{special_compression}_{disposition_mode}_{repeat_cycle_in_day:>04d}_{count_in_repeat_cycle:>04d}.bin'
+ fci_l2_bufr_amv:
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
+ file_patterns:
+ - '{pflag}_{location_indicator},{data_designator},MTI{spacecraft_id:1d}+FCI-2-AMV-{subtype}-{coverage}-{subsetting}-{component1}-{component2}-{component3}-{purpose}-BUFR_{oflag}_{originator}_{processing_time:%Y%m%d%H%M%S}_{facility_or_tool}_{environment}_{start_time:%Y%m%d%H%M%S}_{end_time:%Y%m%d%H%M%S}_{processing_mode}_{special_compression}_{disposition_mode}_{repeat_cycle_in_day:>04d}_{count_in_repeat_cycle:>04d}.bin'
+
+datasets:
+ #----- COMMON ------------------
+ latitude:
+ name: latitude
+ key: '#1#latitude'
+ resolution: [32000, -1]
+ file_type: [fci_l2_bufr_asr,fci_l2_bufr_amv]
+ standard_name: latitude
+ units: degree_north
+ fill_value: -1.e+100
+
+ longitude:
+ name: longitude
+ key: '#1#longitude'
+ resolution: [32000, -1]
+ file_type: [fci_l2_bufr_asr,fci_l2_bufr_amv]
+ standard_name: longitude
+ units: degree_east
+ fill_value: -1.e+100
+
+
+ # ---- AMV products ------------
+ pressure:
+ name: pressure
+ long_name: Pressure of AMV feature
+ standard_name: air_pressure_at_wind_level
+ file_type: fci_l2_bufr_amv
+ key: '#1#pressure'
+ units: Pa
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ temperature:
+ name: temperature
+ long_name: Temperature of AMV feature
+ standard_name: air_temperature_at_wind_level
+ file_type: fci_l2_bufr_amv
+ key: '#1#airTemperature'
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ height:
+ name: height
+ long_name: Height of AMV feature
+ standard_name: height_at_wind_level
+ file_type: fci_l2_bufr_amv
+ key: '#1#heightOfTopOfCloud'
+ units: m
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ direction:
+ name: direction
+ long_name: Direction of AMV
+ standard_name: wind_to_direction
+ file_type: fci_l2_bufr_amv
+ key: '#1#windDirection'
+ units: degree_north
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ speed:
+ name: speed
+ long_name: Speed of AMV
+ standard_name: wind_speed
+ file_type: fci_l2_bufr_amv
+ key: '#1#windSpeed'
+ units: m/s
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ speed_u_component:
+ name: speed_u_component
+ long_name: Speed U component of AMV
+ standard_name: wind_speed_horizontal_component
+ file_type: fci_l2_bufr_amv
+ key: '#1#u'
+ units: m/s
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ speed_v_component:
+ name: speed_v_component
+ long_name: Speed V component of AMV
+ standard_name: wind_speed_vertival_component
+ file_type: fci_l2_bufr_amv
+ key: '#1#v'
+ units: m/s
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ target_type:
+ name: target_type
+ long_name: Target type (cloud or clearsky)
+ standard_name: wind_target_type
+ file_type: fci_l2_bufr_amv
+ key: '#1#extendedHeightAssignmentMethod'
+ units: ""
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ wind_method:
+ name: wind_method
+ long_name: Wind derivation method
+ standard_name: wind_wind_method
+ file_type: fci_l2_bufr_amv
+ key: 'satelliteDerivedWindComputationMethod'
+ units: ""
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ qi:
+ name: qi
+ long_name: Overall Reliability of AMV
+ standard_name: wind_overall_reliability
+ file_type: fci_l2_bufr_amv
+ key: '#1#percentConfidence'
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ qi_excl_fcst:
+ name: qi_excl_fcst
+ long_name: Overall Reliability (excluding forecast) of AMV
+ standard_name: wind_overall_reliability_exc_forecast
+ file_type: fci_l2_bufr_amv
+ key: '#2#percentConfidence'
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ channel_id:
+ name: channel_id
+ long_name: Channel Id
+ standard_name: channel_id
+ file_type: fci_l2_bufr_amv
+ key: '#1#channelNumber'
+ units: ""
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ # ---- ASR products ------------
+ bt_mean_all_ir38:
+ name: bt_mean_all_ir38
+ long_name: TOA Brightness Temperature segment mean at 3.8um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#19#brightnessTemperature'
+ wavelength: [3.4, 3.8, 4.2]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_clear_ir38:
+ name: bt_mean_clear_ir38
+ long_name: TOA Brightness Temperature segment mean at 3.8um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#20#brightnessTemperature'
+ wavelength: [3.4, 3.8, 4.2]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_cloudy_ir38:
+ name: bt_mean_cloudy_ir38
+ long_name: TOA Brightness Temperature segment mean at 3.8um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#21#brightnessTemperature'
+ wavelength: [3.4, 3.8, 4.2]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_all_wv63:
+ name: bt_mean_all_wv63
+ long_name: TOA Brightness Temperature segment mean at 6.3um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#25#brightnessTemperature'
+ wavelength: [5.3, 6.3, 7.3]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_clear_wv63:
+ name: bt_mean_clear_wv63
+ long_name: TOA Brightness Temperature segment mean at 6.3um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#26#brightnessTemperature'
+ wavelength: [5.3, 6.3, 7.3]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_cloudy_wv63:
+ name: bt_mean_cloudy_wv63
+ long_name: TOA Brightness Temperature segment mean at 6.3um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#27#brightnessTemperature'
+ wavelength: [5.3, 6.3, 7.3]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_all_wv73:
+ name: bt_mean_all_wv73
+ long_name: TOA Brightness Temperature segment mean at 7.3um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#31#brightnessTemperature'
+ wavelength: [6.85, 7.35, 7.85]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_clear_wv73:
+ name: bt_mean_clear_wv73
+ long_name: TOA Brightness Temperature segment mean at 7.3um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#32#brightnessTemperature'
+ wavelength: [6.85, 7.35, 7.85]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_cloudy_wv73:
+ name: bt_mean_cloudy_wv73
+ long_name: TOA Brightness Temperature segment mean at 7.3um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#33#brightnessTemperature'
+ wavelength: [6.85, 7.35, 7.85]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_all_ir87:
+ name: bt_mean_all_ir87
+ long_name: TOA Brightness Temperature segment mean at 8.7um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#37#brightnessTemperature'
+ wavelength: [8.3, 8.7, 9.1]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_clear_ir87:
+ name: bt_mean_clear_ir87
+ long_name: TOA Brightness Temperature segment mean at 8.7um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#38#brightnessTemperature'
+ wavelength: [8.3, 8.7, 9.1]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_cloudy_ir87:
+ name: bt_mean_cloudy_ir87
+ long_name: TOA Brightness Temperature segment mean at 8.7um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#39#brightnessTemperature'
+ wavelength: [8.3, 8.7, 9.1]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_all_ir97:
+ name: bt_mean_all_ir97
+ long_name: TOA Brightness Temperature segment mean at 9.7um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#43#brightnessTemperature'
+ wavelength: [9.36, 9.66, 9.96]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_clear_ir97:
+ name: bt_mean_clear_ir97
+ long_name: TOA Brightness Temperature segment mean at 9.7um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#44#brightnessTemperature'
+ wavelength: [9.36, 9.66, 9.96]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_cloudy_ir97:
+ name: bt_mean_cloudy_ir97
+ long_name: TOA Brightness Temperature segment mean at 9.7um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#45#brightnessTemperature'
+ wavelength: [9.36, 9.66, 9.96]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_all_ir105:
+ name: bt_mean_all_ir105
+ long_name: TOA Brightness Temperature segment mean at 10.5um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#49#brightnessTemperature'
+ wavelength: [9.8, 10.5, 11.2]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_clear_ir105:
+ name: bt_mean_clear_ir105
+ long_name: TOA Brightness Temperature segment mean at 10.5um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#50#brightnessTemperature'
+ wavelength: [9.8, 10.5, 11.2]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_cloudy_ir105:
+ name: bt_mean_cloudy_ir105
+ long_name: TOA Brightness Temperature segment mean at 10.5um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#51#brightnessTemperature'
+ wavelength: [9.8, 10.5, 11.2]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_all_ir123:
+ name: bt_mean_all_ir123
+ long_name: TOA Brightness Temperature segment mean at 12.3um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#55#brightnessTemperature'
+ wavelength: [11.8, 12.3, 12.8]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_clear_ir123:
+ name: bt_mean_clear_ir123
+ long_name: TOA Brightness Temperature segment mean at 12.3um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#56#brightnessTemperature'
+ wavelength: [11.8, 12.3, 12.8]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_cloudy_ir123:
+ name: bt_mean_cloudy_ir123
+ long_name: TOA Brightness Temperature segment mean at 12.3um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#57#brightnessTemperature'
+ wavelength: [11.8, 12.3, 12.8]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_all_ir133:
+ name: bt_mean_all_ir133
+ long_name: TOA Brightness Temperature segment mean at 13.3um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#61#brightnessTemperature'
+ wavelength: [12.7, 13.3, 13.9]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_clear_ir133:
+ name: bt_mean_clear_ir133
+ long_name: TOA Brightness Temperature segment mean at 13.3um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#62#brightnessTemperature'
+ wavelength: [12.7, 13.3, 13.9]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ bt_mean_cloudy_ir133:
+ name: bt_mean_cloudy_ir133
+ long_name: TOA Brightness Temperature segment mean at 13.3um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#63#brightnessTemperature'
+ wavelength: [12.7, 13.3, 13.9]
+ cell_method: area:mean
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_all_ir38:
+ name: quality_bt_all_ir38
+ long_name: TOA Brightness Temperature % confidence at 3.8um (all pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#19#brightnessTemperature->percentConfidence'
+ wavelength: [3.4, 3.8, 4.2]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_clear_ir38:
+ name: quality_bt_clear_ir38
+ long_name: TOA Brightness Temperature % confidence at 3.8um (clear pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#20#brightnessTemperature->percentConfidence'
+ wavelength: [3.4, 3.8, 4.2]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_cloudy_ir38:
+ name: quality_bt_cloudy_ir38
+ long_name: TOA Brightness Temperature % confidence at 3.8um (cloudy pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#21#brightnessTemperature->percentConfidence'
+ wavelength: [3.4, 3.8, 4.2]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_all_wv63:
+ name: quality_bt_all_wv63
+ long_name: TOA Brightness Temperature % confidence at 6.3um (all pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#25#brightnessTemperature->percentConfidence'
+ wavelength: [5.3, 6.3, 7.3]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_clear_wv63:
+ name: quality_bt_clear_wv63
+ long_name: TOA Brightness Temperature % confidence at 6.3um (clear pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#26#brightnessTemperature->percentConfidence'
+ wavelength: [5.3, 6.3, 7.3]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_cloudy_wv63:
+ name: quality_bt_cloudy_wv63
+ long_name: TOA Brightness Temperature % confidence at 6.3um (cloudy pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#27#brightnessTemperature->percentConfidence'
+ wavelength: [5.3, 6.3, 7.3]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_all_wv73:
+ name: quality_bt_all_wv73
+ long_name: TOA Brightness Temperature % confidence at 7.3um (all pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#31#brightnessTemperature->percentConfidence'
+ wavelength: [6.85, 7.35, 7.85]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_clear_wv73:
+ name: quality_bt_clear_wv73
+ long_name: TOA Brightness Temperature % confidence at 7.3um (clear pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#32#brightnessTemperature->percentConfidence'
+ wavelength: [6.85, 7.35, 7.85]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_cloudy_wv73:
+ name: quality_bt_cloudy_wv73
+ long_name: TOA Brightness Temperature % confidence at 7.3um (cloudy pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#33#brightnessTemperature->percentConfidence'
+ wavelength: [6.85, 7.35, 7.85]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_all_ir87:
+ name: quality_bt_all_ir87
+ long_name: TOA Brightness Temperature % confidence at 8.7um (all pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#37#brightnessTemperature->percentConfidence'
+ wavelength: [8.3, 8.7, 9.1]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_clear_ir87:
+ name: quality_bt_clear_ir87
+ long_name: TOA Brightness Temperature % confidence at 8.7um (clear pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#38#brightnessTemperature->percentConfidence'
+ wavelength: [8.3, 8.7, 9.1]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_cloudy_ir87:
+ name: quality_bt_cloudy_ir87
+ long_name: TOA Brightness Temperature % confidence at 8.7um (cloudy pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#39#brightnessTemperature->percentConfidence'
+ wavelength: [8.3, 8.7, 9.1]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_all_ir97:
+ name: quality_bt_all_ir97
+ long_name: TOA Brightness Temperature % confidence at 9.7um (all pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#43#brightnessTemperature->percentConfidence'
+ wavelength: [9.36, 9.66, 9.96]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_clear_ir97:
+ name: quality_bt_clear_ir97
+ long_name: TOA Brightness Temperature % confidence at 9.7um (clear pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#44#brightnessTemperature->percentConfidence'
+ wavelength: [9.36, 9.66, 9.96]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_cloudy_ir97:
+ name: quality_bt_cloudy_ir97
+ long_name: TOA Brightness Temperature % confidence at 9.7um (cloudy pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#45#brightnessTemperature->percentConfidence'
+ wavelength: [9.36, 9.66, 9.96]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_all_ir105:
+ name: quality_bt_all_ir105
+ long_name: TOA Brightness Temperature % confidence at 10.5um (all pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#49#brightnessTemperature->percentConfidence'
+ wavelength: [9.8, 10.5, 11.2]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_clear_ir105:
+ name: quality_bt_clear_ir105
+ long_name: TOA Brightness Temperature % confidence at 10.5um (clear pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#50#brightnessTemperature->percentConfidence'
+ wavelength: [9.8, 10.5, 11.2]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_cloudy_ir105:
+ name: quality_bt_cloudy_ir105
+ long_name: TOA Brightness Temperature % confidence at 10.5um (cloudy pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#51#brightnessTemperature->percentConfidence'
+ wavelength: [9.8, 10.5, 11.2]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_all_ir123:
+ name: quality_bt_all_ir123
+ long_name: TOA Brightness Temperature % confidence at 12.3um (all pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#55#brightnessTemperature->percentConfidence'
+ wavelength: [11.8, 12.3, 12.8]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_clear_ir123:
+ name: quality_bt_clear_ir123
+ long_name: TOA Brightness Temperature % confidence at 12.3um (clear pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#56#brightnessTemperature->percentConfidence'
+ wavelength: [11.8, 12.3, 12.8]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_cloudy_ir123:
+ name: quality_bt_cloudy_ir123
+ long_name: TOA Brightness Temperature % confidence at 12.3um (cloudy pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#57#brightnessTemperature->percentConfidence'
+ wavelength: [11.8, 12.3, 12.8]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_all_ir133:
+ name: quality_bt_all_ir133
+ long_name: TOA Brightness Temperature % confidence at 13.3um (all pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#61#brightnessTemperature->percentConfidence'
+ wavelength: [12.7, 13.3, 13.9]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_clear_ir133:
+ name: quality_bt_clear_ir133
+ long_name: TOA Brightness Temperature % confidence at 13.3um (clear pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#62#brightnessTemperature->percentConfidence'
+ wavelength: [12.7, 13.3, 13.9]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ quality_bt_cloudy_ir133:
+ name: quality_bt_cloudy_ir133
+ long_name: TOA Brightness Temperature % confidence at 13.3um (cloudy pixels)
+ standard_name: quality
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#63#brightnessTemperature->percentConfidence'
+ wavelength: [12.7, 13.3, 13.9]
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_all_ir38:
+ name: std_bt_all_ir38
+ long_name: TOA Brightness Temperature standard deviation at 3.8um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#19#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [3.4, 3.8, 4.2]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_clear_ir38:
+ name: std_bt_clear_ir38
+ long_name: TOA Brightness Temperature standard deviation at 3.8um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#20#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [3.4, 3.8, 4.2]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_cloudy_ir38:
+ name: std_bt_cloudy_ir38
+ long_name: TOA Brightness Temperature standard deviation at 3.8um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#21#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [3.4, 3.8, 4.2]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_all_wv63:
+ name: std_bt_all_wv63
+ long_name: TOA Brightness Temperature standard deviation at 6.3um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#25#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [5.3, 6.3, 7.3]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_clear_wv63:
+ name: std_bt_clear_wv63
+ long_name: TOA Brightness Temperature standard deviation at 6.3um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#26#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [5.3, 6.3, 7.3]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_cloudy_wv63:
+ name: std_bt_cloudy_wv63
+ long_name: TOA Brightness Temperature standard deviation at 6.3um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#27#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [5.3, 6.3, 7.3]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_all_wv73:
+ name: std_bt_all_wv73
+ long_name: TOA Brightness Temperature standard deviation at 7.3um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#31#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [6.85, 7.35, 7.85]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_clear_wv73:
+ name: std_bt_clear_wv73
+ long_name: TOA Brightness Temperature standard deviation at 7.3um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#32#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [6.85, 7.35, 7.85]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_cloudy_wv73:
+ name: std_bt_cloudy_wv73
+ long_name: TOA Brightness Temperature standard deviation at 7.3um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#33#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [6.85, 7.35, 7.85]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_all_ir87:
+ name: std_bt_all_ir87
+ long_name: TOA Brightness Temperature standard deviation at 8.7um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#37#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [8.3, 8.7, 9.1]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_clear_ir87:
+ name: std_bt_clear_ir87
+ long_name: TOA Brightness Temperature standard deviation at 8.7um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#38#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [8.3, 8.7, 9.1]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_cloudy_ir87:
+ name: std_bt_cloudy_ir87
+ long_name: TOA Brightness Temperature standard deviation at 8.7um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#39#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [8.3, 8.7, 9.1]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_all_ir97:
+ name: std_bt_all_ir97
+ long_name: TOA Brightness Temperature standard deviation at 9.7um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#43#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [9.36, 9.66, 9.96]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_clear_ir97:
+ name: std_bt_clear_ir97
+ long_name: TOA Brightness Temperature standard deviation at 9.7um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#44#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [9.36, 9.66, 9.96]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_cloudy_ir97:
+ name: std_bt_cloudy_ir97
+ long_name: TOA Brightness Temperature standard deviation at 9.7um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#45#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [9.36, 9.66, 9.96]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_all_ir105:
+ name: std_bt_all_ir105
+ long_name: TOA Brightness Temperature standard deviation at 10.5um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#49#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [9.8, 10.5, 11.2]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_clear_ir105:
+ name: std_bt_clear_ir105
+ long_name: TOA Brightness Temperature standard deviation at 10.5um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#50#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [9.8, 10.5, 11.2]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_cloudy_ir105:
+ name: std_bt_cloudy_ir105
+ long_name: TOA Brightness Temperature standard deviation at 10.5um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#51#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [9.8, 10.5, 11.2]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_all_ir123:
+ name: std_bt_all_ir123
+ long_name: TOA Brightness Temperature standard deviation at 12.3um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#55#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [11.8, 12.3, 12.8]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_clear_ir123:
+ name: std_bt_clear_ir123
+ long_name: TOA Brightness Temperature standard deviation at 12.3um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#56#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [11.8, 12.3, 12.8]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_cloudy_ir123:
+ name: std_bt_cloudy_ir123
+ long_name: TOA Brightness Temperature standard deviation at 12.3um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#57#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [11.8, 12.3, 12.8]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_all_ir133:
+ name: std_bt_all_ir133
+ long_name: TOA Brightness Temperature standard deviation at 13.3um (all pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#61#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [12.7, 13.3, 13.9]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_clear_ir133:
+ name: std_bt_clear_ir133
+ long_name: TOA Brightness Temperature standard deviation at 13.3um (clear pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#62#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [12.7, 13.3, 13.9]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ std_bt_cloudy_ir133:
+ name: std_bt_cloudy_ir133
+ long_name: TOA Brightness Temperature standard deviation at 13.3um (cloudy pixels)
+ standard_name: toa_brightess_temperature
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#63#brightnessTemperature->firstOrderStatisticalValue'
+ wavelength: [12.7, 13.3, 13.9]
+ cell_method: area:standard_deviation
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ pixel_percentage_clear:
+ name: pixel_percentage_clear
+ long_name: Clear Sky Fraction in Segment
+ standard_name: pixels_used_fraction
+ resolution: 32000
+ file_type: fci_l2_bufr_asr
+ key: '#1#amountSegmentCloudFree'
+ 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 ab91e592b5..6a465f3f7a 100644
--- a/satpy/etc/readers/fci_l2_nc.yaml
+++ b/satpy/etc/readers/fci_l2_nc.yaml
@@ -183,7 +183,7 @@ datasets:
intm_pressure:
name: intm_pressure
- standard_name: wind_pressure
+ standard_name: air_pressure_at_wind_level
file_type: nc_fci_amvi
nc_key: intm_pressure
coordinates:
@@ -192,7 +192,7 @@ datasets:
intm_temperature:
name: intm_temperature
- standard_name: wind_temperature
+ standard_name: air_temperature_at_wind_level
file_type: nc_fci_amvi
nc_key: intm_temperature
coordinates:
@@ -275,7 +275,7 @@ datasets:
pressure:
name: pressure
- standard_name: wind_pressure
+ standard_name: air_pressure_at_wind_level
file_type: nc_fci_amv
nc_key: pressure
coordinates:
@@ -284,7 +284,7 @@ datasets:
temperature:
name: temperature
- standard_name: wind_temperature
+ standard_name: air_temperature_at_wind_level
file_type: nc_fci_amv
nc_key: temperature
coordinates:
diff --git a/satpy/etc/readers/seviri_l2_bufr.yaml b/satpy/etc/readers/seviri_l2_bufr.yaml
index e0c51c4370..d998afd8d9 100644
--- a/satpy/etc/readers/seviri_l2_bufr.yaml
+++ b/satpy/etc/readers/seviri_l2_bufr.yaml
@@ -11,48 +11,48 @@ reader:
file_types:
seviri_l2_bufr_asr:
- file_reader: !!python/name:satpy.readers.seviri_l2_bufr.SeviriL2BufrFileHandler
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
file_patterns:
- 'ASRBUFRProd_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}'
- '{spacecraft:s}-SEVI-MSGASRE-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}.bfr'
- '{spacecraft:s}-SEVI-MSGASRE-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}'
seviri_l2_bufr_cla:
- file_reader: !!python/name:satpy.readers.seviri_l2_bufr.SeviriL2BufrFileHandler
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
file_patterns:
- 'CLABUFRProd_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}'
- '{spacecraft:s}-SEVI-MSGCLAP-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}.bfr'
- '{spacecraft:s}-SEVI-MSGCLAP-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}'
seviri_l2_bufr_csr:
- file_reader: !!python/name:satpy.readers.seviri_l2_bufr.SeviriL2BufrFileHandler
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
file_patterns:
- 'CSRBUFRProd_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}'
- '{spacecraft:s}-SEVI-MSGCSKR-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}.bfr'
- '{spacecraft:s}-SEVI-MSGCSKR-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}'
seviri_l2_bufr_gii:
- file_reader: !!python/name:satpy.readers.seviri_l2_bufr.SeviriL2BufrFileHandler
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
file_patterns:
- 'GIIBUFRProduct_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}'
- '{spacecraft:s}-SEVI-MSGGIIN-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}.bfr'
- '{spacecraft:s}-SEVI-MSGGIIN-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}'
seviri_l2_bufr_thu:
- file_reader: !!python/name:satpy.readers.seviri_l2_bufr.SeviriL2BufrFileHandler
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
file_patterns:
- 'THBUFRProd_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}'
- '{spacecraft:s}-SEVI-MSGTPHU-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}.bfr'
- '{spacecraft:s}-SEVI-MSGTPHU-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}'
seviri_l2_bufr_toz:
- file_reader: !!python/name:satpy.readers.seviri_l2_bufr.SeviriL2BufrFileHandler
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
file_patterns:
- 'TOZBUFRProd_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}'
- '{spacecraft:s}-SEVI-MSGTOZN-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}.bfr'
- '{spacecraft:s}-SEVI-MSGTOZN-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}'
seviri_l2_bufr_amv:
- file_reader: !!python/name:satpy.readers.seviri_l2_bufr.SeviriL2BufrFileHandler
+ file_reader: !!python/name:satpy.readers.eum_l2_bufr.EumetsatL2BufrFileHandler
file_patterns:
- 'AMVBUFRProd_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}'
- '{spacecraft:s}-SEVI-MSGAMVE-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}.bfr'
@@ -65,7 +65,7 @@ datasets:
key: '#1#latitude'
long_name: Latitude
standard_name: latitude
- resolution: [48006.450653072,9001.209497451,72009.675979608]
+ resolution: [48006.450653072,48006.450653072,48006.450653072,9001.209497451,48006.450653072,9001.209497451,-1]
file_type: [seviri_l2_bufr_asr,seviri_l2_bufr_cla,seviri_l2_bufr_csr,seviri_l2_bufr_gii,seviri_l2_bufr_thu,seviri_l2_bufr_toz,seviri_l2_bufr_amv]
units: degree_north
fill_value: -1.e+100
@@ -73,7 +73,7 @@ datasets:
longitude:
name: longitude
key: '#1#longitude'
- resolution: [48006.450653072,9001.209497451,72009.675979608]
+ resolution: [48006.450653072,48006.450653072,48006.450653072,9001.209497451,48006.450653072,9001.209497451,-1]
file_type: [seviri_l2_bufr_asr,seviri_l2_bufr_cla,seviri_l2_bufr_csr,seviri_l2_bufr_gii,seviri_l2_bufr_thu,seviri_l2_bufr_toz,seviri_l2_bufr_amv]
long_name: Longitude
standard_name: longitude
@@ -1081,7 +1081,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: ""
+ units: "°C"
file_type: seviri_l2_bufr_gii
fill_value: -1.e+100
@@ -1094,7 +1094,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: ""
+ units: "°C"
file_type: seviri_l2_bufr_gii
fill_value: -1.e+100
@@ -1107,7 +1107,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: ""
+ units: "°C"
file_type: seviri_l2_bufr_gii
fill_value: -1.e+100
@@ -1120,7 +1120,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: mm
+ units: kg/m2
file_type: seviri_l2_bufr_gii
fill_value: -1.e+100
@@ -1133,7 +1133,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: mm
+ units: kg/m2
file_type: seviri_l2_bufr_gii
fill_value: -1.e+100
@@ -1146,7 +1146,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: mm
+ units: kg/m2
file_type: seviri_l2_bufr_gii
fill_value: -1.e+100
@@ -1159,7 +1159,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: ""
+ units: "°C"
file_type: seviri_l2_bufr_gii
fill_value: -1.e+100
@@ -1172,7 +1172,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: degrees
+ units: degrees_north
file_type: seviri_l2_bufr_gii
fill_value: 0
@@ -1185,7 +1185,7 @@ datasets:
coordinates:
- longitude
- latitude
- units: mm
+ units: kg/m2
file_type: seviri_l2_bufr_gii
fill_value: -1.e+100
@@ -1246,41 +1246,170 @@ datasets:
flag_meanings: ['not processed', 'first guess', 'high cloud (not processed)', 'successful retrieval', 'bad retrieval']
# ---- AMV products ------------
- speed:
- name: speed
- long_name: Wind Speed
- standard_name: wind_speed
- key: '#1#windSpeed'
- resolution: 72009.675979608
+ pressure:
+ name: pressure
+ long_name: Air Pressure at Wind Level
+ standard_name: air_pressure
file_type: seviri_l2_bufr_amv
- units: m s-1
+ key: '#1#pressure'
+ units: Pa
fill_value: -1.e+100
coordinates:
- longitude
- latitude
+ oca_pressure:
+ name: oca_pressure
+ long_name: Air Pressure at Wind Level feature from OCA hight assignment
+ standard_name: air_pressure_at_wind_level
+ file_type: fci_l2_bufr_amv
+ key: '#3#pressure'
+ units: Pa
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ temperature:
+ name: temperature
+ long_name: Temperature of AMV feature
+ standard_name: air_temperature_at_wind_level
+ file_type: seviri_l2_bufr_amv
+ key: '#1#airTemperature'
+ units: K
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ height:
+ name: height
+ file_type: seviri_l2_bufr_amv
+ key: '#1#heightOfTopOfCloud'
+ long_name: Height of AMV feature
+ standard_name: height_at_wind_level
+ units: m
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
direction:
name: direction
long_name: Wind Direction
standard_name: wind_to_direction
- key: '#1#windDirection'
- resolution: 72009.675979608
file_type: seviri_l2_bufr_amv
- units: deg
+ key: '#1#windDirection'
+ units: degrees_north
fill_value: -1.e+100
coordinates:
- longitude
- latitude
- pressure:
- name: pressure
- long_name: Air Pressure at Wind Level
- standard_name: air_pressure
- key: '#1#pressure'
- resolution: 72009.675979608
+ speed:
+ name: speed
+ long_name: Wind Speed
+ standard_name: wind_speed
file_type: seviri_l2_bufr_amv
- units: Pa
+ key: '#1#windSpeed'
+ units: m/s
fill_value: -1.e+100
coordinates:
- longitude
- latitude
+
+ speed_u_component:
+ name: speed_u_component
+ long_name: Speed U component of AMV
+ standard_name: wind_speed_horizontal_component
+ file_type: seviri_l2_bufr_amv
+ key: '#1#u'
+ units: m/s
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ speed_v_component:
+ name: speed_v_component
+ long_name: Speed V component of AMV
+ standard_name: wind_speed_vertival_component
+ file_type: seviri_l2_bufr_amv
+ key: '#1#v'
+ units: m/s
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ target_type:
+ name: target_type
+ long_name: Target type (cloud or clearsky)
+ standard_name: wind_target_type
+ file_type: seviri_l2_bufr_amv
+ key: '#1#extendedHeightAssignmentMethod'
+ units: ""
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ wind_method:
+ name: wind_method
+ long_name: Wind derivation method
+ standard_name: wind_wind_method
+ file_type: seviri_l2_bufr_amv
+ key: 'satelliteDerivedWindComputationMethod'
+ units: ""
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ qi:
+ name: qi
+ long_name: Overall Reliability of AMV
+ standard_name: wind_overall_reliability
+ file_type: seviri_l2_bufr_amv
+ key: '#1#percentConfidence'
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ qi_excl_fcst:
+ name: qi_excl_fcst
+ long_name: Overall Reliability (excluding forecast) of AMV
+ standard_name: wind_overall_reliability_exc_forecast
+ file_type: seviri_l2_bufr_amv
+ key: '#2#percentConfidence'
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ qi_excl_fcst_oca:
+ name: qi_excl_fcst_oca
+ long_name: Overall Reliability (excluding forecast and OCA) of AMV
+ standard_name: wind_overall_reliability_exc_forecast_and_oca
+ file_type: seviri_l2_bufr_amv
+ key: '#4#percentConfidence'
+ units: '%'
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
+
+ channel_id:
+ name: channel_id
+ long_name: Channel Id
+ standard_name: channel_id
+ file_type: seviri_l2_bufr_amv
+ key: '#1#channelNumber'
+ units: ""
+ fill_value: -1.0e+100
+ coordinates:
+ - longitude
+ - latitude
diff --git a/satpy/readers/seviri_l2_bufr.py b/satpy/readers/eum_l2_bufr.py
similarity index 58%
rename from satpy/readers/seviri_l2_bufr.py
rename to satpy/readers/eum_l2_bufr.py
index a48a7e00d6..15c594bf73 100644
--- a/satpy/readers/seviri_l2_bufr.py
+++ b/satpy/readers/eum_l2_bufr.py
@@ -26,6 +26,7 @@
import datetime as dt
import logging
+import os
import dask.array as da
import numpy as np
@@ -44,20 +45,26 @@
raise ImportError(
"Missing eccodes-python and/or eccodes C-library installation. Use conda to install eccodes")
+logger = logging.getLogger("EumetsatL2Bufr")
+
CHUNK_SIZE = get_legacy_chunk_size()
-logger = logging.getLogger("SeviriL2Bufr")
-data_center_dict = {55: {"ssp": "E0415", "name": "08"}, 56: {"ssp": "E0455", "name": "09"},
- 57: {"ssp": "E0095", "name": "10"}, 70: {"ssp": "E0000", "name": "11"}}
+SSP_DEFAULT = 0.0
+BUFR_FILL_VALUE = -1.e+100
+
+data_center_dict = {55: {"ssp": "E0415", "name": "MSG1"}, 56: {"ssp": "E0455", "name": "MSG2"},
+ 57: {"ssp": "E0095", "name": "MSG3"}, 70: {"ssp": "E0000", "name": "MSG4"},
+ 71: {"ssp": "E0000", "name": "MTGi1"}}
+
+# Sensor resolution (pixel size in m) used to deermine product segment sizes
+resolution_dict = {"fci": 2000, "seviri": 3000}
-seg_size_dict = {"seviri_l2_bufr_asr": 16, "seviri_l2_bufr_cla": 16,
- "seviri_l2_bufr_csr": 16, "seviri_l2_bufr_gii": 3,
- "seviri_l2_bufr_thu": 16, "seviri_l2_bufr_toz": 3,
- "seviri_l2_bufr_amv": 24}
+# List of variables that are now returned by eccodes as array, but that we want as single value
+deprecate_to_single_value = ["satelliteIdentifier"]
-class SeviriL2BufrFileHandler(BaseFileHandler):
- """File handler for SEVIRI L2 BUFR products.
+class EumetsatL2BufrFileHandler(BaseFileHandler):
+ """File handler for EUMETSAT Central Facility SEVIRI and FCI L2 BUFR products.
**Loading data with AreaDefinition**
@@ -66,8 +73,8 @@ class SeviriL2BufrFileHandler(BaseFileHandler):
be loaded with a SwathDefinition, i.e. similar to how the data are stored in the BUFR file:
scene = satpy.Scene(filenames,
- reader='seviri_l2_bufr',
- reader_kwargs={'with_area_definition': False})
+ reader="seviri_l2_bufr",
+ reader_kwargs={"with_area_definition": False})
**Defining dataset recticifation longitude**
@@ -77,62 +84,78 @@ class SeviriL2BufrFileHandler(BaseFileHandler):
rectification longitude can be defined by the user by providing `rectification_longitude` in the `reader_kwargs`:
scene = satpy.Scene(filenames,
- reader='seviri_l2_bufr',
- reader_kwargs={'rectification_longitude': 0.0})
+ reader="seviri_l2_bufr",
+ reader_kwargs={"rectification_longitude": 0.0})
If not done, default values applicable to the operational grids of the respective SEVIRI instruments will be used.
"""
def __init__(self, filename, filename_info, filetype_info, with_area_definition=False,
rectification_longitude="default", **kwargs):
- """Initialise the file handler for SEVIRI L2 BUFR data."""
- super(SeviriL2BufrFileHandler, self).__init__(filename,
- filename_info,
- filetype_info)
+ """Initialise the file handler for EUMETSAT SEVIRI and FCI L2 BUFR data."""
+ super(EumetsatL2BufrFileHandler, self).__init__(filename,
+ filename_info,
+ filetype_info)
+
+ # Set this environment variable to get consistent array sizes from eccodes. This fixes the cases
+ # where all values in the expected array are the same (in particular fill values) which causes
+ # eccodes to encode them and return them as a single value
+ os.environ["ECCODES_BUFR_MULTI_ELEMENT_CONSTANT_ARRAYS"] = "1"
if ("server" in filename_info):
# EUMETSAT Offline Bufr product
- self.mpef_header = self._read_mpef_header()
+ self.bufr_header = self._read_mpef_header()
else:
# Product was retrieved from the EUMETSAT Data Center
- timeStr = self.get_attribute("typicalDate")+self.get_attribute("typicalTime")
- buf_start_time = dt.datetime.strptime(timeStr, "%Y%m%d%H%M%S")
- sc_id = self.get_attribute("satelliteIdentifier")
- self.mpef_header = {}
- self.mpef_header["NominalTime"] = buf_start_time
- self.mpef_header["SpacecraftName"] = data_center_dict[sc_id]["name"]
- self.mpef_header["RectificationLongitude"] = data_center_dict[sc_id]["ssp"]
+ attr = self.get_attributes(["typicalDate", "typicalTime", "satelliteIdentifier"])
+ timeStr = attr["typicalDate"]+attr["typicalTime"]
+ sc_id = int(attr["satelliteIdentifier"])
+
+ self.bufr_header = {}
+ self.bufr_header["NominalTime"] = dt.datetime.strptime(timeStr, "%Y%m%d%H%M%S")
+ self.bufr_header["SpacecraftName"] = data_center_dict[sc_id]["name"]
+ self.bufr_header["RectificationLongitude"] = data_center_dict[sc_id]["ssp"]
if rectification_longitude != "default":
- self.mpef_header["RectificationLongitude"] = f"E{int(rectification_longitude * 10):04d}"
+ self.bufr_header["RectificationLongitude"] = f"E{int(rectification_longitude * 10):04d}"
+ self.filetype = filetype_info["file_type"]
self.with_adef = with_area_definition
- if self.with_adef and filetype_info["file_type"] == "seviri_l2_bufr_amv":
- logging.warning("AMV BUFR data cannot be loaded with an area definition. Setting self.with_def = False.")
- self.with_adef = False
- self.seg_size = seg_size_dict[filetype_info["file_type"]]
+ def __del__(self):
+ """Delete the instance and environment variable."""
+ try:
+ del os.environ["ECCODES_BUFR_MULTI_ELEMENT_CONSTANT_ARRAYS"]
+ except KeyError:
+ pass
@property
def start_time(self):
"""Return the repeat cycle start time."""
- return self.mpef_header["NominalTime"]
-
- @property
- def end_time(self):
- """Return the repeat cycle end time."""
- return self.start_time + dt.timedelta(minutes=15)
+ return self.bufr_header["NominalTime"]
@property
def platform_name(self):
"""Return spacecraft name."""
- return "MET{}".format(self.mpef_header["SpacecraftName"])
+ if self.bufr_header["SpacecraftName"].isdigit():
+ # self._read_mpef_header will return the SpacecraftName as a string with an integer, representing the
+ # Meteosat series number (1-11). This is cnverted to the corresponding MSG ID.
+ return f'MSG{int(self.bufr_header["SpacecraftName"])-7}'
+ else:
+ return self.bufr_header["SpacecraftName"]
+
+ @property
+ def sensor_name(self):
+ """Return instrument name."""
+ if self.platform_name.startswith("MSG"):
+ return "seviri"
+ elif self.platform_name.startswith("MTG"):
+ return "fci"
@property
def ssp_lon(self):
"""Return subsatellite point longitude."""
- # e.g. E0415
- ssp_lon = self.mpef_header["RectificationLongitude"]
+ ssp_lon = self.bufr_header["RectificationLongitude"]
return float(ssp_lon[1:])/10.
def get_area_def(self, key):
@@ -147,23 +170,40 @@ def _read_mpef_header(self):
hdr = np.fromfile(self.filename, mpef_product_header, 1)
return recarray2dict(hdr)
- def get_attribute(self, key):
+ def get_attributes(self, keys):
"""Get BUFR attributes."""
# This function is inefficient as it is looping through the entire
- # file to get 1 attribute. It causes a problem though if you break
- # from the file early - dont know why but investigating - fix later
+ # file to get a list of attributes. It causes a problem though if you break
+ # from the file early - dont know why but investigating - fix later.
fh = open(self.filename, "rb")
+
+ # Initialize output
+ attrs = dict()
+
while True:
- # get handle for message
+ # Get handle for message
bufr = ec.codes_bufr_new_from_file(fh)
if bufr is None:
break
ec.codes_set(bufr, "unpack", 1)
- attr = ec.codes_get(bufr, key)
+ for k in keys:
+ try:
+ if k in deprecate_to_single_value:
+ # With ECCODES_BUFR_MULTI_ELEMENT_CONSTANT_ARRAYS set to 1 all values, including scalars, are
+ # returned as arrays. Hence, we extract the single value here.
+ value = ec.codes_get_array(bufr, k)[0]
+ else:
+ value = ec.codes_get(bufr, k)
+ attrs[k] = value
+
+ except BaseException:
+ attrs[k] = None
+ logging.warning(f"Failed to read key {k} from message")
+
ec.codes_release(bufr)
fh.close()
- return attr
+ return attrs
def get_array(self, key):
"""Get all data from file for the given BUFR key."""
@@ -176,13 +216,16 @@ def get_array(self, key):
ec.codes_set(bufr, "unpack", 1)
+ if not ec.codes_is_defined(bufr, key):
+ logging.warning(f"Key: {key} does not exist in BUFR file")
+ return None
+
# if is the first message initialise our final array
if (msgCount == 0):
- arr = da.from_array(ec.codes_get_array(
- bufr, key, float), chunks=CHUNK_SIZE)
+ arr = da.from_array(ec.codes_get_array(bufr, key, float), chunks=CHUNK_SIZE)
+
else:
- tmpArr = da.from_array(ec.codes_get_array(
- bufr, key, float), chunks=CHUNK_SIZE)
+ tmpArr = da.from_array(ec.codes_get_array(bufr, key, float), chunks=CHUNK_SIZE)
arr = da.concatenate((arr, tmpArr))
msgCount = msgCount+1
@@ -202,19 +245,21 @@ def get_dataset(self, dataset_id, dataset_info):
"""
arr = self.get_array(dataset_info["key"])
- if self.with_adef:
+ if self.with_adef and "resolution" in dataset_id:
xarr = self.get_dataset_with_area_def(arr, dataset_id)
- # coordinates are not relevant when returning data with an AreaDefinition
+ # Coordinates are not relevant when returning data with an AreaDefinition
if "coordinates" in dataset_info.keys():
del dataset_info["coordinates"]
else:
+ if self.with_adef:
+ logging.warning("Trying to use `with_area_definition=True` for a dataset without resolution. "
+ "This is not supported and the keyword will be ignored.")
xarr = xr.DataArray(arr, dims=["y"])
if "fill_value" in dataset_info:
xarr = xarr.where(xarr != dataset_info["fill_value"])
self._add_attributes(xarr, dataset_info)
-
return xarr
def get_dataset_with_area_def(self, arr, dataset_id):
@@ -224,7 +269,6 @@ def get_dataset_with_area_def(self, arr, dataset_id):
xarr = xr.DataArray(arr, dims=["y"])
else:
lons_1d, lats_1d, data_1d = da.compute(self.longitude, self.latitude, arr)
-
self._area_def = self._construct_area_def(dataset_id)
icol, irow = self._area_def.get_array_indices_from_lonlat(lons_1d, lats_1d)
@@ -249,19 +293,17 @@ def _construct_area_def(self, dataset_id):
AreaDefinition: A pyresample AreaDefinition object containing the area definition.
"""
- res = dataset_id["resolution"]
-
- area_naming_input_dict = {"platform_name": "msg",
- "instrument_name": "seviri",
- "resolution": res,
+ area_naming_input_dict = {"platform_name": self.platform_name[:3].lower(),
+ "instrument_name": self.sensor_name,
+ "resolution": dataset_id["resolution"],
}
area_naming = get_geos_area_naming({**area_naming_input_dict,
- **get_service_mode("seviri", self.ssp_lon)})
+ **get_service_mode(self.sensor_name, self.ssp_lon)})
# Datasets with a segment size of 3 pixels extend outside the original SEVIRI 3km grid (with 1238 x 1238
# segments a 3 pixels). Hence, we need to use corresponding area defintions in areas.yaml
- if self.seg_size == 3:
+ if self.sensor_name=="seviri" and round(dataset_id["resolution"])==9001:
area_naming["area_id"] += "_ext"
area_naming["description"] += " (extended outside original 3km grid)"
@@ -272,8 +314,13 @@ def _construct_area_def(self, dataset_id):
def _add_attributes(self, xarr, dataset_info):
"""Add dataset attributes to xarray."""
- xarr.attrs["sensor"] = "SEVIRI"
+ xarr.attrs["sensor"] = self.sensor_name.upper()
xarr.attrs["platform_name"] = self.platform_name
xarr.attrs["ssp_lon"] = self.ssp_lon
- xarr.attrs["seg_size"] = self.seg_size
+ if ("resolution" not in dataset_info) or (dataset_info["resolution"] is None):
+ xarr.attrs["seg_size"] = None
+ xarr.attrs["resolution"] = None
+ else:
+ xarr.attrs["seg_size"] = round(dataset_info["resolution"]/resolution_dict[self.sensor_name])
+
xarr.attrs.update(dataset_info)
diff --git a/satpy/tests/reader_tests/test_eum_l2_bufr.py b/satpy/tests/reader_tests/test_eum_l2_bufr.py
new file mode 100644
index 0000000000..274dbdab8b
--- /dev/null
+++ b/satpy/tests/reader_tests/test_eum_l2_bufr.py
@@ -0,0 +1,379 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017-2019 Satpy developers
+#
+# 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 .
+"""Unittesting the EUMETSAT L2 BUFR reader."""
+
+import sys
+import unittest
+from datetime import datetime
+from unittest import mock
+
+import dask.array as da
+import numpy as np
+import pytest
+from pyresample import geometry
+
+from satpy.tests.utils import make_dataid
+
+AREA_DEF_MSG_IODC = geometry.AreaDefinition(
+ "msg_seviri_iodc_48km",
+ "MSG SEVIRI Indian Ocean Data Coverage service area definition with 48 km resolution",
+ "",
+ {"a": 6378169., "b": 6356583.8, "lon_0": 45.5,
+ "h": 35785831., "proj": "geos", "units": "m"},
+ 232,
+ 232,
+ (-5570248.686685662, -5567248.28340708, 5567248.28340708, 5570248.686685662)
+)
+
+AREA_DEF_MSG_FES = geometry.AreaDefinition(
+
+ "msg_seviri_fes_48km",
+ "MSG SEVIRI Full Earth Scanning service area definition with 48 km resolution",
+ "",
+ {"a": 6378169., "b": 6356583.8, "lon_0": 0.0,
+ "h": 35785831., "proj": "geos", "units": "m"},
+ 232,
+ 232,
+ (-5570248.6867, -5567248.2834, 5567248.2834, 5570248.6867)
+)
+
+AREA_DEF_MSG_IODC_EXT = geometry.AreaDefinition(
+ "msg_seviri_iodc_9km_ext",
+ "MSG SEVIRI Indian Ocean Data Coverage service area definition with 9 km resolution "
+ "(extended outside original 3km grid)",
+ "",
+ {"a": 6378169., "b": 6356583.8, "lon_0": 45.5,
+ "h": 35785831., "proj": "geos", "units": "m"},
+ 1238,
+ 1238,
+ (-5571748.8883, -5571748.8882, 5571748.8882, 5571748.8883)
+)
+
+AREA_DEF_FCI_FES = geometry.AreaDefinition(
+ "mtg_fci_fdss_32km",
+ "MTG FCI Full Disk Scanning Service area definition with 32 km SSP resolution",
+ "",
+ {"x_0": 0, "y_0": 0, "ellps": "WGS84", "lon_0": 0.0,
+ "h": 35786400., "proj": "geos", "units": "m"},
+ 348,
+ 348,
+ (-5567999.998550739, -5567999.998550739, 5567999.994203017, 5567999.994203017)
+)
+
+AREA_DEF_MSG_FES_3km_ext = geometry.AreaDefinition(
+ "msg_seviri_fes_9km_ext",
+ "MSG SEVIRI Full Earth Scanning service area definition with 9 km resolution",
+ "",
+ {"a": 6378169., "b": 6356583.8, "lon_0": 0.0,
+ "h": 35785831., "proj": "geos", "units": "m"},
+ 1238,
+ 1238,
+ (-5571748.888268564, -5571748.888155806, 5571748.888155806, 5571748.888268564)
+)
+
+# Test data for mock file
+DATA = np.random.default_rng().uniform(low=250, high=350, size=(128,))
+LAT = np.random.default_rng().uniform(low=-80, high=80, size=(128,))
+LON = np.random.default_rng().uniform(low=-38.5, high=121.5, size=(128,))
+
+# Test cases dictionaries
+TEST_DATA = {"GIIBUFRProduct_20231027140000Z_00_OMPEFS03_MET10_FES_E0000": {
+ "platform_name": "MSG3",
+ "spacecraft_number": "10",
+ "RectificationLongitude": "E0000",
+ "ssp_lon": 0.0,
+ "area": AREA_DEF_MSG_FES_3km_ext,
+ "seg_size": 3,
+ "file_type": "seviri_l2_bufr_gii",
+ "key": "#1#brightnessTemperature",
+ "resolution": 9001,
+ "data": DATA},
+ "ASRBUFRProd_20231022224500Z_00_OMPEFS03_MET10_FES_E0000": {
+ "platform_name": "MSG3",
+ "spacecraft_number": "10",
+ "RectificationLongitude": "E0000",
+ "ssp_lon": 0.0,
+ "area": AREA_DEF_MSG_FES,
+ "seg_size": 16,
+ "file_type": "seviri_l2_bufr_asr",
+ "key": "#1#brightnessTemperature",
+ "resolution": 48006,
+ "data": DATA},
+ "AMVBUFRProd_20231023044500Z_00_OMPEFS02_MET09_FES_E0455": {
+ "platform_name": "MSG2",
+ "spacecraft_number": "9",
+ "RectificationLongitude": "E0455",
+ "area": AREA_DEF_MSG_IODC,
+ "ssp_lon": 45.5,
+ "seg_size": None,
+ "file_type": "seviri_l2_bufr_amv",
+ "key": "#1#brightnessTemperature",
+ "resolution": None,
+ "data": DATA},
+ "MSG2-SEVI-MSGASRE-0101-0101-20191106130000.000000000Z-20191106131702-1362128.bfr": {
+ "platform_name": "MSG2",
+ "spacecraft_number": "9",
+ "RectificationLongitude": "E0455",
+ "area": AREA_DEF_MSG_IODC,
+ "ssp_lon": 45.5,
+ "seg_size": 16,
+ "file_type": "seviri_l2_bufr_asr",
+ "key": "#1#brightnessTemperature",
+ "resolution": 48006,
+ "data": DATA},
+ """W_XX-EUMETSAT-Darmstadt,IMG+SAT,MTI1+FCI-2-ASR--FD------BUFR_C_EUMT_
+ 20230623092246_L2PF_IV_20170410170000_20170410171000_V__C_0103_0000.bin""": {
+ "platform_name": "MTGi1",
+ "spacecraft_number": "24",
+ "RectificationLongitude": "E0000",
+ "area": AREA_DEF_FCI_FES,
+ "ssp_lon": 0.0,
+ "seg_size": 16,
+ "file_type": "fci_l2_bufr_asr",
+ "key": "#1#brightnessTemperature",
+ "resolution": 32000,
+ "data": DATA},
+ """W_XX-EUMETSAT-Darmstadt,IMG+SAT,MTI1+FCI-2-AMV--FD------BUFR_C_EUMT_
+20230623092246_L2PF_IV_20170410170000_20170410171000_V__C_0103_0000.bin""": {
+ "platform_name": "MTGi1",
+ "spacecraft_number": "24",
+ "RectificationLongitude": "E0000",
+ "area": AREA_DEF_FCI_FES,
+ "ssp_lon": 0.0,
+ "seg_size": None,
+ "file_type": "fci_l2_bufr_amv",
+ "key": "#1#brightnessTemperature",
+ "resolution": None,
+ "data": DATA}}
+
+TEST_FILES = list(TEST_DATA.keys())
+
+
+class L2BufrData:
+ """Mock L2 BUFR data."""
+
+ @unittest.skipIf(sys.platform.startswith("win"), "'eccodes' not supported on Windows")
+ def __init__(self, filename, test_data, with_adef=False, rect_lon="default"):
+ """Initialize by mocking test data for testing the L2 BUFR reader."""
+ import eccodes as ec
+
+ from satpy.readers.eum_l2_bufr import EumetsatL2BufrFileHandler
+
+ self.buf1 = ec.codes_bufr_new_from_samples("BUFR4_local_satellite")
+ ec.codes_set(self.buf1, "unpack", 1)
+ # write the bufr test data twice as we want to read in and then concatenate the data in the reader
+ # 55 id corresponds to METEOSAT 8
+ ec.codes_set(self.buf1, "satelliteIdentifier", 47 + int(test_data["spacecraft_number"]))
+ ec.codes_set_array(self.buf1, "#1#latitude", LAT)
+ ec.codes_set_array(self.buf1, "#1#longitude", LON)
+ ec.codes_set_array(self.buf1, test_data["key"], test_data["data"])
+
+ self.m = mock.mock_open()
+
+ FILETYPE_INFO = {"file_type": test_data["file_type"]}
+
+ # only our offline product contain MPEF product headers so we get the metadata from there
+ if ("BUFRProd" in filename):
+ with mock.patch("satpy.readers.eum_l2_bufr.np.fromfile") as fromfile:
+
+ MPEF_PRODUCT_HEADER = {
+ "NominalTime": datetime(2019, 11, 6, 18, 0),
+ "SpacecraftName": test_data["spacecraft_number"],
+ "RectificationLongitude": test_data["RectificationLongitude"]
+ }
+ fromfile.return_value = MPEF_PRODUCT_HEADER
+ with mock.patch("satpy.readers.eum_l2_bufr.recarray2dict") as recarray2dict:
+ recarray2dict.side_effect = (lambda x: x)
+
+ FILENAME_INFO = {"start_time": "20231022224500", "spacecraft": test_data["platform_name"],
+ "server": "TESTSERVER"}
+ self.fh = EumetsatL2BufrFileHandler(
+ filename, FILENAME_INFO, FILETYPE_INFO,
+ with_area_definition=with_adef,
+ rectification_longitude=int(test_data["RectificationLongitude"][1:]) / 10)
+ self.fh.mpef_header = MPEF_PRODUCT_HEADER
+
+ else:
+ # No Mpef Header so we get the metadata from the BUFR messages
+ with mock.patch("satpy.readers.eum_l2_bufr.open", self.m, create=True):
+ with mock.patch("eccodes.codes_bufr_new_from_file",
+ side_effect=[self.buf1, None, self.buf1, None, self.buf1, None]) as ec1:
+ ec1.return_value = ec1.side_effect
+ with mock.patch("eccodes.codes_set") as ec2:
+ ec2.return_value = 1
+ with mock.patch("eccodes.codes_release") as ec5:
+ ec5.return_value = 1
+
+ FILENAME_INFO = {"start_time": "20191112000000",
+ "spacecraft": test_data["platform_name"]}
+ self.fh = EumetsatL2BufrFileHandler(
+ filename, FILENAME_INFO, FILETYPE_INFO,
+ with_area_definition=with_adef,
+ rectification_longitude=int(test_data["RectificationLongitude"][1:]) / 10)
+
+ self.resolution = test_data["resolution"]
+
+ def get_data(self, dataset_name, key, coordinates):
+ """Read data from mock file."""
+ DATASET_INFO = {
+ "name": dataset_name,
+ "key": key,
+ "fill_value": -1.e+100,
+ "resolution": self.resolution
+ }
+ if coordinates:
+ DATASET_INFO.update({"coordinates": ("longitude", "latitude")})
+
+ with mock.patch("satpy.readers.eum_l2_bufr.open", self.m, create=True):
+ with mock.patch("eccodes.codes_bufr_new_from_file",
+ side_effect=[self.buf1, self.buf1, None]) as ec1:
+ ec1.return_value = ec1.side_effect
+ with mock.patch("eccodes.codes_set") as ec2:
+ ec2.return_value = 1
+ with mock.patch("eccodes.codes_release") as ec5:
+ ec5.return_value = 1
+ z = self.fh.get_dataset(make_dataid(name=dataset_name, resolution=self.resolution),
+ DATASET_INFO)
+
+ return z
+
+
+@pytest.mark.parametrize("input_file", TEST_FILES)
+class TestL2BufrReader:
+ """Test EUMETSAT L2 BUFR Reader."""
+
+ @staticmethod
+ def test_lonslats(input_file):
+ """Test reading of longitude and latitude data with EUMETSAT L2 BUFR reader."""
+ test_data = TEST_DATA[input_file]
+ bufr_obj = L2BufrData(input_file, test_data)
+ zlat = bufr_obj.get_data("latitude", "#1#latitude", coordinates=False)
+ zlon = bufr_obj.get_data("longitude", "#1#longitude", coordinates=False)
+ np.testing.assert_array_equal(zlat.values, np.concatenate((LAT, LAT), axis=0))
+ np.testing.assert_array_equal(zlon.values, np.concatenate((LON, LON), axis=0))
+
+ @staticmethod
+ def test_attributes_with_swath_definition(input_file):
+ """Test correctness of dataset attributes with data loaded with a SwathDefinition (default behaviour)."""
+ test_data = TEST_DATA[input_file]
+ bufr_obj = L2BufrData(input_file, test_data)
+ z = bufr_obj.get_data(dataset_name="TestData", key=test_data["key"], coordinates=True)
+ assert z.attrs["platform_name"] == test_data["platform_name"]
+ assert z.attrs["ssp_lon"] == test_data["ssp_lon"]
+ assert z.attrs["seg_size"] == test_data["seg_size"]
+
+ @staticmethod
+ def test_attributes_with_area_definition(input_file):
+ """Test correctness of dataset attributes with data loaded with a AreaDefinition."""
+ test_data = TEST_DATA[input_file]
+ bufr_obj = L2BufrData(input_file, test_data, with_adef=True)
+ _ = bufr_obj.get_data("latitude", "#1#latitude", coordinates=False)
+ _ = bufr_obj.get_data("longitude", "#1#longitude", coordinates=False)
+
+ z = bufr_obj.get_data(dataset_name="TestData", key=test_data["key"], coordinates=True)
+ assert z.attrs["platform_name"] == test_data["platform_name"]
+ assert z.attrs["ssp_lon"] == test_data["ssp_lon"]
+ assert z.attrs["seg_size"] == test_data["seg_size"]
+
+ @staticmethod
+ def test_data_with_swath_definition(input_file):
+ """Test data loaded with SwathDefinition (default behaviour)."""
+ test_data = TEST_DATA[input_file]
+ bufr_obj = L2BufrData(input_file, test_data)
+ with pytest.raises(NotImplementedError):
+ bufr_obj.fh.get_area_def(None)
+
+ # concatenate original test arrays as get_dataset will have read and concatented the data
+ x1 = np.concatenate((DATA, DATA), axis=0)
+ z = bufr_obj.get_data(dataset_name="TestData", key=test_data["key"], coordinates=True)
+ np.testing.assert_array_equal(z.values, x1)
+
+ def test_data_with_area_definition(self, input_file):
+ """Test data loaded with an area definition."""
+ test_data = TEST_DATA[input_file]
+ if test_data["seg_size"] is None:
+ # Skip this test
+ return
+
+ bufr_obj = L2BufrData(input_file, test_data, with_adef=True)
+ _ = bufr_obj.get_data("latitude", "#1#latitude", coordinates=False)
+ _ = bufr_obj.get_data("longitude", "#1#longitude", coordinates=False)
+
+ z = bufr_obj.get_data(dataset_name="TestData", key=test_data["key"], coordinates=True)
+
+ ad = bufr_obj.fh.get_area_def(None)
+
+ assert ad == test_data["area"]
+ data_1d = np.concatenate((DATA, DATA), axis=0)
+
+ # Put BUFR data on 2D grid that the 2D array returned by get_dataset should correspond to
+ lons_1d, lats_1d = da.compute(bufr_obj.fh.longitude, bufr_obj.fh.latitude)
+ icol, irow = ad.get_array_indices_from_lonlat(lons_1d, lats_1d)
+
+ data_2d = np.empty(ad.shape)
+ data_2d[:] = np.nan
+ data_2d[irow.compressed(), icol.compressed()] = data_1d[~irow.mask]
+ np.testing.assert_array_equal(z.values, data_2d)
+
+ # Removed assert dedicated to products with seg_size=3 (covered by GII test case)
+
+ def test_data_with_rect_lon(self, input_file):
+ """Test data loaded with an area definition and a rectification longitude."""
+ test_data = TEST_DATA[input_file]
+ if test_data["seg_size"] is None:
+ # Skip this test
+ return
+
+ bufr_obj = L2BufrData(input_file, test_data, with_adef=True)
+ np.testing.assert_equal(bufr_obj.fh.ssp_lon,
+ int(test_data["RectificationLongitude"][1:]) / 10)
+ _ = bufr_obj.get_data("latitude", "#1#latitude", coordinates=False)
+ _ = bufr_obj.get_data("longitude", "#1#longitude", coordinates=False)
+ _ = bufr_obj.get_data(dataset_name="TestData", key=test_data["key"], coordinates=True)
+ # We need to lead the data in order to create the AreaDefinition
+
+ ad = bufr_obj.fh.get_area_def(None)
+ assert ad == test_data["area"]
+
+ def test_resolution(self, input_file):
+ """Test data loaded with the correct resolution attribute ."""
+ test_data = TEST_DATA[input_file]
+ bufr_obj = L2BufrData(input_file, test_data, with_adef=True)
+ _ = bufr_obj.get_data("latitude", "#1#latitude", coordinates=False)
+ _ = bufr_obj.get_data("longitude", "#1#longitude", coordinates=False)
+
+ z = bufr_obj.get_data(dataset_name="TestData", key=test_data["key"], coordinates=True)
+
+ assert z.attrs["resolution"] == bufr_obj.resolution
+
+ def test_amv_with_area_def(self, input_file):
+ """Test that AMV data can not be loaded with an area definition.
+
+ The way to test this is to try load a variable with with_adef=True. The reader shall ignore this flag
+ and return a 1D array, not a 2D.
+ """
+ test_data = TEST_DATA[input_file]
+ if test_data["file_type"] not in ["seviri_l2_bufr_amv", "fci_l2_bufr_amv"]:
+ return # Skip this test for non AMV datasets
+
+ bufr_obj = L2BufrData(input_file, test_data, with_adef=True)
+ _ = bufr_obj.get_data("latitude", "#1#latitude", coordinates=False)
+ _ = bufr_obj.get_data("longitude", "#1#longitude", coordinates=False)
+ z = bufr_obj.get_data(dataset_name="TestData", key=test_data["key"], coordinates=True)
+
+ assert len(z.dims) == 1
diff --git a/satpy/tests/reader_tests/test_seviri_l2_bufr.py b/satpy/tests/reader_tests/test_seviri_l2_bufr.py
deleted file mode 100644
index 5696cbbef0..0000000000
--- a/satpy/tests/reader_tests/test_seviri_l2_bufr.py
+++ /dev/null
@@ -1,281 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (c) 2017-2019 Satpy developers
-#
-# 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 .
-"""Unittesting the SEVIRI L2 BUFR reader."""
-
-import datetime as dt
-import sys
-import unittest
-from unittest import mock
-
-import dask.array as da
-import numpy as np
-import pytest
-from pyresample import geometry
-
-from satpy.tests.utils import RANDOM_GEN, make_dataid
-
-FILETYPE_INFO = {"file_type": "seviri_l2_bufr_asr"}
-
-FILENAME_INFO = {"start_time": "20191112000000",
- "spacecraft": "MSG2"}
-FILENAME_INFO2 = {"start_time": "20191112000000",
- "spacecraft": "MSG2",
- "server": "TESTSERVER"}
-MPEF_PRODUCT_HEADER = {
- "NominalTime": dt.datetime(2019, 11, 6, 18, 0),
- "SpacecraftName": "09",
- "RectificationLongitude": "E0455"
-}
-
-DATASET_INFO = {
- "name": "testdata",
- "key": "#1#brightnessTemperature",
- "coordinates": ("longitude", "latitude"),
- "fill_value": 0
-}
-
-DATASET_INFO_LAT = {
- "name": "latitude",
- "key": "#1#latitude",
- "fill_value": -1.e+100
-}
-
-DATASET_INFO_LON = {
- "name": "longitude",
- "key": "#1#longitude",
- "fill_value": -1.e+100
-}
-
-
-DATASET_ATTRS = {
- "platform_name": "MET09",
- "ssp_lon": 45.5,
- "seg_size": 16
-}
-
-AREA_DEF = geometry.AreaDefinition(
- "msg_seviri_iodc_48km",
- "MSG SEVIRI Indian Ocean Data Coverage service area definition with 48 km resolution",
- "",
- {"a": 6378169., "b": 6356583.8, "lon_0": DATASET_ATTRS["ssp_lon"],
- "h": 35785831., "proj": "geos", "units": "m"},
- 232,
- 232,
- (-5570248.6867, -5567248.2834, 5567248.2834, 5570248.6867)
-)
-
-AREA_DEF_FES = geometry.AreaDefinition(
- "msg_seviri_res_48km",
- "MSG SEVIRI Full Earth Scanning service area definition with 48 km resolution",
- "",
- {"a": 6378169., "b": 6356583.8, "lon_0": 0.0,
- "h": 35785831., "proj": "geos", "units": "m"},
- 232,
- 232,
- (-5570248.6867, -5567248.2834, 5567248.2834, 5570248.6867)
-)
-
-AREA_DEF_EXT = geometry.AreaDefinition(
- "msg_seviri_iodc_9km_ext",
- "MSG SEVIRI Indian Ocean Data Coverage service area definition with 9 km resolution "
- "(extended outside original 3km grid)",
- "",
- {"a": 6378169., "b": 6356583.8, "lon_0": DATASET_ATTRS["ssp_lon"],
- "h": 35785831., "proj": "geos", "units": "m"},
- 1238,
- 1238,
- (-5571748.8883, -5571748.8882, 5571748.8882, 5571748.8883)
-)
-
-TEST_FILES = [
- "ASRBUFRProd_20191106130000Z_00_OMPEFS02_MET09_FES_E0000",
- "MSG2-SEVI-MSGASRE-0101-0101-20191106130000.000000000Z-20191106131702-1362128.bfr",
- "MSG2-SEVI-MSGASRE-0101-0101-20191106101500.000000000Z-20191106103218-1362148"
-]
-
-# Test data
-DATA = RANDOM_GEN.uniform(low=250, high=350, size=(128,))
-LAT = RANDOM_GEN.uniform(low=-80, high=80, size=(128,))
-LON = RANDOM_GEN.uniform(low=-38.5, high=121.5, size=(128,))
-
-
-class SeviriL2BufrData:
- """Mock SEVIRI L2 BUFR data."""
-
- @unittest.skipIf(sys.platform.startswith("win"), "'eccodes' not supported on Windows")
- def __init__(self, filename, with_adef=False, rect_lon="default"):
- """Initialize by mocking test data for testing the SEVIRI L2 BUFR reader."""
- import eccodes as ec
-
- from satpy.readers.seviri_l2_bufr import SeviriL2BufrFileHandler
- self.buf1 = ec.codes_bufr_new_from_samples("BUFR4_local_satellite")
- ec.codes_set(self.buf1, "unpack", 1)
- # write the bufr test data twice as we want to read in and then concatenate the data in the reader
- # 55 id corresponds to METEOSAT 8`
- ec.codes_set(self.buf1, "satelliteIdentifier", 56)
- ec.codes_set_array(self.buf1, "#1#latitude", LAT)
- ec.codes_set_array(self.buf1, "#1#latitude", LAT)
- ec.codes_set_array(self.buf1, "#1#longitude", LON)
- ec.codes_set_array(self.buf1, "#1#longitude", LON)
- ec.codes_set_array(self.buf1, "#1#brightnessTemperature", DATA)
- ec.codes_set_array(self.buf1, "#1#brightnessTemperature", DATA)
-
- self.m = mock.mock_open()
- # only our offline product contain MPEF product headers so we get the metadata from there
- if ("BUFRProd" in filename):
- with mock.patch("satpy.readers.seviri_l2_bufr.np.fromfile") as fromfile:
- fromfile.return_value = MPEF_PRODUCT_HEADER
- with mock.patch("satpy.readers.seviri_l2_bufr.recarray2dict") as recarray2dict:
- recarray2dict.side_effect = (lambda x: x)
- self.fh = SeviriL2BufrFileHandler(filename, FILENAME_INFO2, FILETYPE_INFO,
- with_area_definition=with_adef, rectification_longitude=rect_lon)
- self.fh.mpef_header = MPEF_PRODUCT_HEADER
-
- else:
- # No Mpef Header so we get the metadata from the BUFR messages
- with mock.patch("satpy.readers.seviri_l2_bufr.open", self.m, create=True):
- with mock.patch("eccodes.codes_bufr_new_from_file",
- side_effect=[self.buf1, None, self.buf1, None, self.buf1, None]) as ec1:
- ec1.return_value = ec1.side_effect
- with mock.patch("eccodes.codes_set") as ec2:
- ec2.return_value = 1
- with mock.patch("eccodes.codes_release") as ec5:
- ec5.return_value = 1
- self.fh = SeviriL2BufrFileHandler(filename, FILENAME_INFO, FILETYPE_INFO,
- with_area_definition=with_adef,
- rectification_longitude=rect_lon)
-
- def get_data(self, dataset_info):
- """Read data from mock file."""
- with mock.patch("satpy.readers.seviri_l2_bufr.open", self.m, create=True):
- with mock.patch("eccodes.codes_bufr_new_from_file",
- side_effect=[self.buf1, self.buf1, None]) as ec1:
- ec1.return_value = ec1.side_effect
- with mock.patch("eccodes.codes_set") as ec2:
- ec2.return_value = 1
- with mock.patch("eccodes.codes_release") as ec5:
- ec5.return_value = 1
- z = self.fh.get_dataset(make_dataid(name=dataset_info["name"], resolution=48000), dataset_info)
-
- return z
-
-
-@pytest.mark.parametrize("input_file", TEST_FILES)
-class TestSeviriL2BufrReader:
- """Test SEVIRI L2 BUFR Reader."""
-
- @staticmethod
- def test_lonslats(input_file):
- """Test reading of longitude and latitude data with SEVIRI L2 BUFR reader."""
- bufr_obj = SeviriL2BufrData(input_file)
- zlat = bufr_obj.get_data(DATASET_INFO_LAT)
- zlon = bufr_obj.get_data(DATASET_INFO_LON)
- np.testing.assert_array_equal(zlat.values, np.concatenate((LAT, LAT), axis=0))
- np.testing.assert_array_equal(zlon.values, np.concatenate((LON, LON), axis=0))
-
- @staticmethod
- def test_attributes_with_swath_definition(input_file):
- """Test correctness of dataset attributes with data loaded with a SwathDefinition (default behaviour)."""
- bufr_obj = SeviriL2BufrData(input_file)
- z = bufr_obj.get_data(DATASET_INFO)
- assert z.attrs["platform_name"] == DATASET_ATTRS["platform_name"]
- assert z.attrs["ssp_lon"] == DATASET_ATTRS["ssp_lon"]
- assert z.attrs["seg_size"] == DATASET_ATTRS["seg_size"]
-
- @staticmethod
- def test_attributes_with_area_definition(input_file):
- """Test correctness of dataset attributes with data loaded with a AreaDefinition."""
- bufr_obj = SeviriL2BufrData(input_file, with_adef=True)
- _ = bufr_obj.get_data(DATASET_INFO_LAT) # We need to load the lat/lon data in order to
- _ = bufr_obj.get_data(DATASET_INFO_LON) # populate the file handler with these data
- z = bufr_obj.get_data(DATASET_INFO)
- assert z.attrs["platform_name"] == DATASET_ATTRS["platform_name"]
- assert z.attrs["ssp_lon"] == DATASET_ATTRS["ssp_lon"]
- assert z.attrs["seg_size"] == DATASET_ATTRS["seg_size"]
-
- @staticmethod
- def test_data_with_swath_definition(input_file):
- """Test data loaded with SwathDefinition (default behaviour)."""
- bufr_obj = SeviriL2BufrData(input_file)
- with pytest.raises(NotImplementedError):
- bufr_obj.fh.get_area_def(None)
-
- # concatenate original test arrays as get_dataset will have read and concatented the data
- x1 = np.concatenate((DATA, DATA), axis=0)
- z = bufr_obj.get_data(DATASET_INFO)
- np.testing.assert_array_equal(z.values, x1)
-
- def test_data_with_area_definition(self, input_file):
- """Test data loaded with AreaDefinition."""
- bufr_obj = SeviriL2BufrData(input_file, with_adef=True)
- _ = bufr_obj.get_data(DATASET_INFO_LAT) # We need to load the lat/lon data in order to
- _ = bufr_obj.get_data(DATASET_INFO_LON) # populate the file handler with these data
- z = bufr_obj.get_data(DATASET_INFO)
-
- ad = bufr_obj.fh.get_area_def(None)
- assert ad == AREA_DEF
- data_1d = np.concatenate((DATA, DATA), axis=0)
-
- # Put BUFR data on 2D grid that the 2D array returned by get_dataset should correspond to
- lons_1d, lats_1d = da.compute(bufr_obj.fh.longitude, bufr_obj.fh.latitude)
- icol, irow = ad.get_array_indices_from_lonlat(lons_1d, lats_1d)
-
- data_2d = np.empty(ad.shape)
- data_2d[:] = np.nan
- data_2d[irow.compressed(), icol.compressed()] = data_1d[~irow.mask]
- np.testing.assert_array_equal(z.values, data_2d)
-
- # Test that the correct AreaDefinition is identified for products with 3 pixel segements
- bufr_obj.fh.seg_size = 3
- ad_ext = bufr_obj.fh._construct_area_def(make_dataid(name="dummmy", resolution=9000))
- assert ad_ext == AREA_DEF_EXT
-
- def test_data_with_rect_lon(self, input_file):
- """Test data loaded with AreaDefinition and user defined rectification longitude."""
- bufr_obj = SeviriL2BufrData(input_file, with_adef=True, rect_lon=0.0)
- np.testing.assert_equal(bufr_obj.fh.ssp_lon, 0.0)
- _ = bufr_obj.get_data(DATASET_INFO_LAT) # We need to load the lat/lon data in order to
- _ = bufr_obj.get_data(DATASET_INFO_LON) # populate the file handler with these data
- _ = bufr_obj.get_data(DATASET_INFO) # We need to lead the data in order to create the AreaDefinition
-
- ad = bufr_obj.fh.get_area_def(None)
- assert ad == AREA_DEF_FES
-
-
-class SeviriL2AMVBufrData:
- """Mock SEVIRI L2 AMV BUFR data."""
-
- @unittest.skipIf(sys.platform.startswith("win"), "'eccodes' not supported on Windows")
- def __init__(self, filename):
- """Initialize by mocking test data for testing the SEVIRI L2 BUFR reader."""
- from satpy.readers.seviri_l2_bufr import SeviriL2BufrFileHandler
-
- with mock.patch("satpy.readers.seviri_l2_bufr.np.fromfile"):
- self.fh = SeviriL2BufrFileHandler(filename, FILENAME_INFO2,
- filetype_info={"file_type": "seviri_l2_bufr_amv"},
- with_area_definition=True)
-
-
-class TestSeviriL2AMVBufrReader:
- """Test SEVIRI L2 BUFR Reader for AMV data."""
-
- @staticmethod
- def test_amv_with_area_def():
- """Test that AMV data can not be loaded with an area definition."""
- bufr_obj = SeviriL2AMVBufrData("AMVBUFRProd_20201110124500Z_00_OMPEFS04_MET11_FES_E0000")
- assert bufr_obj.fh.with_adef is False