Exemplo n.º 1
0
    def get_area_def(self, dataset_id):
        """Get the area definition of the band.

        In general, image data from one window/area is available. For the HRV channel in FES mode, however,
        data from two windows ('Lower' and 'Upper') are available. Hence, we collect lists of area-extents
        and corresponding number of image lines/columns. In case of FES HRV data, two area definitions are
        computed, stacked and squeezed. For other cases, the lists will only have one entry each, from which
        a single area definition is computed.

        Note that the AreaDefinition area extents returned by this function for Native data will be slightly
        different compared to the area extents returned by the SEVIRI HRIT reader.
        This is due to slightly different pixel size values when calculated using the data available in the files. E.g.
        for the 3 km grid:

        ``Native: data15hd['ImageDescription']['ReferenceGridVIS_IR']['ColumnDirGridStep'] == 3000.4031658172607``
        ``HRIT:                            np.deg2rad(2.**16 / pdict['lfac']) * pdict['h'] == 3000.4032785810186``

        This results in the Native 3 km full-disk area extents being approx. 20 cm shorter in each direction.

        The method for calculating the area extents used by the HRIT reader (CFAC/LFAC mechanism) keeps the
        highest level of numeric precision and is used as reference by EUM. For this reason, the standard area
        definitions defined in the `areas.yaml` file correspond to the HRIT ones.

        """
        pdict = {}
        pdict['a'] = self.mda['projection_parameters']['a']
        pdict['b'] = self.mda['projection_parameters']['b']
        pdict['h'] = self.mda['projection_parameters']['h']
        pdict['ssp_lon'] = self.mda['projection_parameters']['ssp_longitude']

        area_naming_input_dict = {
            'platform_name': 'msg',
            'instrument_name': 'seviri',
            'resolution': int(dataset_id['resolution'])
        }
        area_naming = get_geos_area_naming({
            **area_naming_input_dict,
            **get_service_mode('seviri', pdict['ssp_lon'])
        })

        pdict['a_name'] = area_naming['area_id']
        pdict['a_desc'] = area_naming['description']
        pdict['p_id'] = ""

        area_extent = self.get_area_extent(dataset_id)
        areas = list()
        for aex, nlines, ncolumns in zip(area_extent['area_extent'],
                                         area_extent['nlines'],
                                         area_extent['ncolumns']):
            pdict['nlines'] = nlines
            pdict['ncols'] = ncolumns
            areas.append(get_area_definition(pdict, aex))

        if len(areas) == 2:
            area = geometry.StackedAreaDefinition(areas[0], areas[1])
            area = area.squeeze()
        else:
            area = areas[0]

        return area
Exemplo n.º 2
0
    def _construct_area_def(self, dataset_id):
        """Construct a standardized AreaDefinition based on satellite, instrument, resolution and sub-satellite point.

        Returns:
            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 = get_geos_area_naming({
            **area_naming_input_dict,
            **get_service_mode('seviri', 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:
            area_naming['area_id'] += '_ext'
            area_naming[
                'description'] += ' (extended outside original 3km grid)'

        # Construct AreaDefinition from standardized area definition in areas.yaml.
        stand_area_def = get_area_def(area_naming['area_id'])

        return stand_area_def
Exemplo n.º 3
0
    def _construct_area_def(self, dataset_id):
        """Construct the area definition.

        Returns:
            AreaDefinition: A pyresample AreaDefinition object containing the area definition.

        """
        res = dataset_id.resolution

        area_naming_input_dict = {'platform_name': 'mtg',
                                  'instrument_name': 'fci',
                                  'resolution': res,
                                  }

        area_naming = get_geos_area_naming({**area_naming_input_dict,
                                            **get_service_mode('fci', self.ssp_lon)})

        # Construct area definition from standardized area definition.
        stand_area_def = get_area_def(area_naming['area_id'])

        if (stand_area_def.x_size != self.ncols) | (stand_area_def.y_size != self.nlines):
            raise NotImplementedError('Unrecognised AreaDefinition.')

        mod_area_extent = self._modify_area_extent(stand_area_def.area_extent)

        area_def = geometry.AreaDefinition(
            stand_area_def.area_id,
            stand_area_def.description,
            "",
            stand_area_def.proj_dict,
            stand_area_def.x_size,
            stand_area_def.y_size,
            mod_area_extent)

        return area_def
Exemplo n.º 4
0
    def _get_proj_area(self, dataset_id):
        """Extract projection and area information."""
        # Read the projection data from the mtg_geos_projection variable
        a = float(self._projection.attrs['semi_major_axis'])
        h = float(self._projection.attrs['perspective_point_height'])

        # Some L2PF test data files have a typo in the keyname for the inverse flattening parameter. Use a default value
        # as fallback until all L2PF test files are correctly formatted.
        rf = float(self._projection.attrs.get('inverse_flattening', 298.257223563))

        res = dataset_id.resolution

        area_naming_input_dict = {'platform_name': 'mtg',
                                  'instrument_name': 'fci',
                                  'resolution': res,
                                  }

        area_naming = get_geos_area_naming({**area_naming_input_dict,
                                            **get_service_mode('fci', self.ssp_lon)})

        proj_dict = {'a': a,
                     'lon_0': self.ssp_lon,
                     'h': h,
                     "rf": rf,
                     'proj': 'geos',
                     'units': 'm',
                     "sweep": 'y'}

        return area_naming, proj_dict
Exemplo n.º 5
0
 def test_get_unknown_instrument_service_mode(self):
     """Test fetching of service mode information for unknown input instrument."""
     ssp_lon = 0
     name = 'unknown'
     desc = 'unknown'
     res = get_service_mode('test', ssp_lon)
     self.assertEqual(res['service_name'], name)
     self.assertEqual(res['service_desc'], desc)
Exemplo n.º 6
0
 def test_get_unknown_lon_service_mode(self):
     """Test fetching of service mode information for unknown input longitude."""
     ssp_lon = 13
     name = 'unknown'
     desc = 'unknown'
     res = get_service_mode('fci', ssp_lon)
     self.assertEqual(res['service_name'], name)
     self.assertEqual(res['service_desc'], desc)
Exemplo n.º 7
0
 def test_get_fci_service_mode_rss(self):
     """Test fetching of FCI service mode information for RSS."""
     ssp_lon = 9.5
     name = 'rss'
     desc = 'Rapid Scanning Service'
     res = get_service_mode('fci', ssp_lon)
     self.assertEqual(res['service_name'], name)
     self.assertEqual(res['service_desc'], desc)
Exemplo n.º 8
0
 def test_get_fci_service_mode_fdss(self):
     """Test fetching of FCI service mode information for FDSS."""
     ssp_lon = 0.0
     name = 'fdss'
     desc = 'Full Disk Scanning Service'
     res = get_service_mode('fci', ssp_lon)
     self.assertEqual(res['service_name'], name)
     self.assertEqual(res['service_desc'], desc)
Exemplo n.º 9
0
 def test_get_seviri_service_mode_iodc(self):
     """Test fetching of SEVIRI service mode information for IODC."""
     ssp_lon = 41.5
     name = 'iodc'
     desc = 'Indian Ocean Data Coverage service'
     res = get_service_mode('seviri', ssp_lon)
     self.assertEqual(res['service_name'], name)
     self.assertEqual(res['service_desc'], desc)
Exemplo n.º 10
0
 def test_get_seviri_service_mode_fes(self):
     """Test fetching of SEVIRI service mode information for FES."""
     ssp_lon = 0.0
     name = 'fes'
     desc = 'Full Earth Scanning service'
     res = get_service_mode('seviri', ssp_lon)
     self.assertEqual(res['service_name'], name)
     self.assertEqual(res['service_desc'], desc)
Exemplo n.º 11
0
    def get_area_def(self, dataset_id):
        """Get the area def.

        Note that the AreaDefinition area extents returned by this function for NetCDF data will be slightly
        different compared to the area extents returned by the SEVIRI HRIT reader.
        This is due to slightly different pixel size values when calculated using the data available in the files. E.g.
        for the 3 km grid:

        ``NetCDF:  self.nc.attrs['vis_ir_column_dir_grid_step'] == 3000.4031658172607``
        ``HRIT: np.deg2rad(2.**16 / pdict['lfac']) * pdict['h'] == 3000.4032785810186``

        This results in the Native 3 km full-disk area extents being approx. 20 cm shorter in each direction.

        The method for calculating the area extents used by the HRIT reader (CFAC/LFAC mechanism) keeps the
        highest level of numeric precision and is used as reference by EUM. For this reason, the standard area
        definitions defined in the `areas.yaml` file correspond to the HRIT ones.

        """
        pdict = {}
        pdict['a'] = self.mda['projection_parameters']['a']
        pdict['b'] = self.mda['projection_parameters']['b']
        pdict['h'] = self.mda['projection_parameters']['h']
        pdict['ssp_lon'] = self.mda['projection_parameters']['ssp_longitude']

        area_naming_input_dict = {
            'platform_name': 'msg',
            'instrument_name': 'seviri',
            'resolution': int(dataset_id['resolution'])
        }
        area_naming = get_geos_area_naming({
            **area_naming_input_dict,
            **get_service_mode('seviri', pdict['ssp_lon'])
        })

        if dataset_id['name'] == 'HRV':
            pdict['nlines'] = self.mda['hrv_number_of_lines']
            pdict['ncols'] = self.mda['hrv_number_of_columns']
            pdict['a_name'] = area_naming['area_id']
            pdict['a_desc'] = area_naming['description']
            pdict['p_id'] = ""
        else:
            pdict['nlines'] = self.mda['number_of_lines']
            pdict['ncols'] = self.mda['number_of_columns']
            pdict['a_name'] = area_naming['area_id']
            pdict['a_desc'] = area_naming['description']
            pdict['p_id'] = ""

        area = get_area_definition(pdict, self.get_area_extent(dataset_id))

        return area
Exemplo n.º 12
0
    def get_area_def(self, key):
        """Calculate on-fly area definition for a dataset in geos-projection."""
        # assumption: channels with same resolution should have same area
        # cache results to improve performance
        if key['resolution'] in self._cache:
            return self._cache[key['resolution']]

        a = float(self["data/mtg_geos_projection/attr/semi_major_axis"])
        h = float(
            self["data/mtg_geos_projection/attr/perspective_point_height"])
        rf = float(self["data/mtg_geos_projection/attr/inverse_flattening"])
        lon_0 = float(self[
            "data/mtg_geos_projection/attr/longitude_of_projection_origin"])
        sweep = str(self["data/mtg_geos_projection"].sweep_angle_axis)

        area_extent, nlines, ncols = self.calc_area_extent(key)
        logger.debug('Calculated area extent: {}'.format(''.join(
            str(area_extent))))

        # use a (semi-major axis) and rf (reverse flattening) to define ellipsoid as recommended by EUM (see PUG)
        proj_dict = {
            'a': a,
            'lon_0': lon_0,
            'h': h,
            "rf": rf,
            'proj': 'geos',
            'units': 'm',
            "sweep": sweep
        }

        area_naming_input_dict = {
            'platform_name': 'mtg',
            'instrument_name': 'fci',
            'resolution': int(key['resolution'])
        }
        area_naming = get_geos_area_naming({
            **area_naming_input_dict,
            **get_service_mode('fci', lon_0)
        })

        area = geometry.AreaDefinition(area_naming['area_id'],
                                       area_naming['description'], "",
                                       proj_dict, ncols, nlines, area_extent)

        self._cache[key['resolution']] = area
        return area
Exemplo n.º 13
0
    def get_area_def(self, dsid):
        """Get the area definition of the band."""
        # Common parameters for both HRV and other channels
        nlines = int(self.mda['number_of_lines'])
        loff = np.float32(self.mda['loff'])
        pdict = {}
        pdict['cfac'] = np.int32(self.mda['cfac'])
        pdict['lfac'] = np.int32(self.mda['lfac'])
        pdict['coff'] = np.float32(self.mda['coff'])

        pdict['a'] = self.mda['projection_parameters']['a']
        pdict['b'] = self.mda['projection_parameters']['b']
        pdict['h'] = self.mda['projection_parameters']['h']
        pdict['ssp_lon'] = self.mda['projection_parameters']['SSP_longitude']

        pdict['nlines'] = nlines
        pdict['ncols'] = int(self.mda['number_of_columns'])
        if (self.prologue['ImageDescription']['Level15ImageProduction']
            ['ImageProcDirection'] == 0):
            pdict['scandir'] = 'N2S'
        else:
            pdict['scandir'] = 'S2N'

        area_naming_input_dict = {
            'platform_name': 'msg',
            'instrument_name': 'seviri',
            'resolution': int(dsid['resolution'])
        }
        area_naming = get_geos_area_naming({
            **area_naming_input_dict,
            **get_service_mode('seviri', pdict['ssp_lon'])
        })

        # Compute area definition for non-HRV channels:
        if dsid['name'] != 'HRV':
            pdict['loff'] = loff - nlines
            aex = self._get_area_extent(pdict)
            pdict['a_name'] = area_naming['area_id']
            pdict['a_desc'] = area_naming['description']
            pdict['p_id'] = ""
            area = get_area_definition(pdict, aex)
            self.area = area
            return self.area

        segment_number = self.mda['segment_sequence_number']

        current_first_line = (
            (segment_number - self.mda['planned_start_segment_number']) *
            pdict['nlines'])

        # Or, if we are processing HRV:
        pdict['a_name'] = area_naming['area_id']
        pdict['p_id'] = ""
        bounds = self.epilogue['ImageProductionStats'][
            'ActualL15CoverageHRV'].copy()
        if self.fill_hrv:
            bounds['UpperEastColumnActual'] = 1
            bounds['UpperWestColumnActual'] = HRV_NUM_COLUMNS
            bounds['LowerEastColumnActual'] = 1
            bounds['LowerWestColumnActual'] = HRV_NUM_COLUMNS
            pdict['ncols'] = HRV_NUM_COLUMNS

        upper_south_line = bounds[
            'LowerNorthLineActual'] - current_first_line - 1
        upper_south_line = min(max(upper_south_line, 0), pdict['nlines'])
        lower_coff = (5566 - bounds['LowerEastColumnActual'] + 1)
        upper_coff = (5566 - bounds['UpperEastColumnActual'] + 1)

        # First we look at the lower window
        pdict['nlines'] = upper_south_line
        pdict['loff'] = loff - upper_south_line
        pdict['coff'] = lower_coff
        pdict['a_desc'] = area_naming['description']
        lower_area_extent = self._get_area_extent(pdict)
        lower_area = get_area_definition(pdict, lower_area_extent)

        # Now the upper window
        pdict['nlines'] = nlines - upper_south_line
        pdict['loff'] = loff - pdict['nlines'] - upper_south_line
        pdict['coff'] = upper_coff
        pdict['a_desc'] = area_naming['description']
        upper_area_extent = self._get_area_extent(pdict)
        upper_area = get_area_definition(pdict, upper_area_extent)

        area = geometry.StackedAreaDefinition(lower_area, upper_area)

        self.area = area.squeeze()
        return self.area
Exemplo n.º 14
0
    def _get_proj_area(self, gid):
        """Compute the dictionary with the projection and area definition from a GRIB message.

        Args:
            gid: The ID of the GRIB message.
        Returns:
            tuple: A tuple of two dictionaries for the projection and the area definition.
                pdict:
                    a: Earth major axis [m]
                    b: Earth minor axis [m]
                    h: Height over surface [m]
                    ssp_lon: longitude of subsatellite point [deg]
                    nlines: number of lines
                    ncols: number of columns
                    a_name: name of the area
                    a_desc: description of the area
                    p_id: id of the projection
                area_dict:
                    center_point: coordinate of the center point
                    north: coodinate of the north limit
                    east: coodinate of the east limit
                    west: coodinate of the west limit
                    south: coodinate of the south limit
        """
        # Get name of area definition
        area_naming_input_dict = {
            'platform_name': 'msg',
            'instrument_name': 'seviri',
            'resolution': self._res,
        }

        area_naming = get_geos_area_naming({
            **area_naming_input_dict,
            **get_service_mode('seviri', self._ssp_lon)
        })

        # Read all projection and area parameters from the message
        earth_major_axis_in_meters = self._get_from_msg(
            gid, 'earthMajorAxis') * 1000.0  # [m]
        earth_minor_axis_in_meters = self._get_from_msg(
            gid, 'earthMinorAxis') * 1000.0  # [m]

        earth_major_axis_in_meters = self._scale_earth_axis(
            earth_major_axis_in_meters)
        earth_minor_axis_in_meters = self._scale_earth_axis(
            earth_minor_axis_in_meters)

        nr_in_radius_of_earth = self._get_from_msg(gid, 'NrInRadiusOfEarth')
        xp_in_grid_lengths = self._get_from_msg(gid, 'XpInGridLengths')
        h_in_meters = earth_major_axis_in_meters * (nr_in_radius_of_earth - 1.0
                                                    )  # [m]

        # Create the dictionary with the projection data
        pdict = {
            'a': earth_major_axis_in_meters,
            'b': earth_minor_axis_in_meters,
            'h': h_in_meters,
            'ssp_lon': self._ssp_lon,
            'nlines': self._ncols,
            'ncols': self._nrows,
            'a_name': area_naming['area_id'],
            'a_desc': area_naming['description'],
            'p_id': "",
        }

        # Compute the dictionary with the area extension
        area_dict = {
            'center_point': xp_in_grid_lengths,
            'north': self._nrows,
            'east': 1,
            'west': self._ncols,
            'south': 1,
        }

        return pdict, area_dict