Esempio n. 1
0
    def test_get_bounding_corners_dask(self):
        """Test finding surrounding bounding corners."""
        import dask.array as da
        from pyresample.bilinear.xarr import (_get_input_xy_dask,
                                              _get_bounding_corners_dask)
        from pyresample._spatial_mp import Proj
        from pyresample import CHUNK_SIZE

        proj = Proj(self.target_def.proj_str)
        out_x, out_y = self.target_def.get_proj_coords(chunks=CHUNK_SIZE)
        out_x = da.ravel(out_x)
        out_y = da.ravel(out_y)
        in_x, in_y = _get_input_xy_dask(self.source_def, proj,
                                        da.from_array(self.valid_input_index),
                                        da.from_array(self.index_array))
        pt_1, pt_2, pt_3, pt_4, ia_ = _get_bounding_corners_dask(
            in_x, in_y, out_x, out_y, self.neighbours,
            da.from_array(self.index_array))

        self.assertTrue(pt_1.shape == pt_2.shape == pt_3.shape == pt_4.shape ==
                        (self.target_def.size, 2))
        self.assertTrue(ia_.shape == (self.target_def.size, 4))

        # Check which of the locations has four valid X/Y pairs by
        # finding where there are non-NaN values
        res = da.sum(pt_1 + pt_2 + pt_3 + pt_4, axis=1).compute()
        self.assertEqual(np.sum(~np.isnan(res)), 10)
Esempio n. 2
0
    def test_get_corner_dask(self):
        """Test finding the closest corners."""
        import dask.array as da
        from pyresample.bilinear.xarr import (_get_corner_dask,
                                              _get_input_xy_dask)
        from pyresample import CHUNK_SIZE
        from pyresample._spatial_mp import Proj

        proj = Proj(self.target_def.proj_str)
        in_x, in_y = _get_input_xy_dask(self.source_def, proj,
                                        da.from_array(self.valid_input_index),
                                        da.from_array(self.index_array))
        out_x, out_y = self.target_def.get_proj_coords(chunks=CHUNK_SIZE)
        out_x = da.ravel(out_x)
        out_y = da.ravel(out_y)

        # Some copy&paste from the code to get the input
        out_x_tile = np.reshape(np.tile(out_x, self.neighbours),
                                (self.neighbours, out_x.size)).T
        out_y_tile = np.reshape(np.tile(out_y, self.neighbours),
                                (self.neighbours, out_y.size)).T
        x_diff = out_x_tile - in_x
        y_diff = out_y_tile - in_y
        stride = np.arange(x_diff.shape[0])

        # Use lower left source pixels for testing
        valid = (x_diff > 0) & (y_diff > 0)
        x_3, y_3, idx_3 = _get_corner_dask(stride, valid, in_x, in_y,
                                           da.from_array(self.index_array))

        self.assertTrue(
            x_3.shape == y_3.shape == idx_3.shape == (self.target_def.size, ))
        # Four locations have no data to the lower left of them (the
        # bottom row of the area
        self.assertEqual(np.sum(np.isnan(x_3.compute())), 4)
Esempio n. 3
0
    def test_get_output_xy(self):
        """Test calculation of output xy-coordinates."""
        from pyresample.bilinear import _get_output_xy
        from pyresample._spatial_mp import Proj

        proj = Proj(self.target_def.proj_str)
        out_x, out_y = _get_output_xy(self.target_def, proj)
        self.assertTrue(out_x.all())
        self.assertTrue(out_y.all())
Esempio n. 4
0
 def __init__(self, target_area, source_lons, source_lats):
     self.target_area = target_area
     self.source_lons = source_lons
     self.source_lats = source_lats
     self.prj = Proj(self.target_area.proj_dict)
     self.x_idxs = None
     self.y_idxs = None
     self.idxs = None
     self._get_indices()
     self.counts = None
Esempio n. 5
0
    def test_get_input_xy(self):
        """Test calculation of input xy-coordinates."""
        from pyresample.bilinear import _get_input_xy
        from pyresample._spatial_mp import Proj

        proj = Proj(self.target_def.proj_str)
        in_x, in_y = _get_input_xy(self.swath_def, proj, self.input_idxs,
                                   self.idx_ref)
        self.assertTrue(in_x.all())
        self.assertTrue(in_y.all())
Esempio n. 6
0
 def test_get_bounding_corners(self):
     proj = Proj(self.target_def.proj_str)
     out_x, out_y = bil._get_output_xy(self.target_def, proj)
     in_x, in_y = bil._get_input_xy(self.swath_def, proj,
                                    self.input_idxs, self.idx_ref)
     res = bil._get_bounding_corners(in_x, in_y, out_x, out_y,
                                     self.neighbours, self.idx_ref)
     for i in range(len(res) - 1):
         pt_ = res[i]
         for j in range(2):
             # Only the sixth output location has four valid corners
             self.assertTrue(np.isfinite(pt_[5, j]))
Esempio n. 7
0
    def test_get_input_xy(self):
        """Test computation of input X and Y coordinates in target proj."""
        from pyresample.bilinear.xarr import _get_input_xy
        from pyresample._spatial_mp import Proj

        proj = Proj(self.target_def.proj_str)
        in_x, in_y = _get_input_xy(self.source_def, proj,
                                   self._valid_input_index, self._index_array)

        self.assertTrue(in_x.shape, (self.target_def.size, 32))
        self.assertTrue(in_y.shape, (self.target_def.size, 32))
        self.assertTrue(in_x.all())
        self.assertTrue(in_y.all())
Esempio n. 8
0
def _convert_units(var, name, units, p, proj_dict, inverse=False, center=None):
    """Converts units from lon/lat to projection coordinates (meters).

    If `inverse` it True then the inverse calculation is done.

    """
    from pyproj import transform
    from pyresample._spatial_mp import Proj
    if var is None:
        return None
    if isinstance(var, DataArray):
        units = var.units
        var = tuple(var.data.tolist())
    if p.is_latlong() and not ('deg' == units or 'degrees' == units):
        raise ValueError(
            'latlon/latlong projection cannot take {0} as units: {1}'.format(
                units, name))
    # Check if units are an angle.
    is_angle = ('deg' == units or 'degrees' == units)
    if ('deg' in units) and not is_angle:
        logging.warning('units provided to {0} are incorrect: {1}'.format(
            name, units))
    # Convert from var projection units to projection units given by projection from user.
    if not is_angle:
        if units == 'meters' or units == 'metres':
            units = 'm'
        if proj_dict.get('units', 'm') != units:
            tmp_proj_dict = proj_dict.copy()
            tmp_proj_dict['units'] = units
            var = transform(Proj(tmp_proj_dict, preserve_units=True), p, *var)
    if name == 'center':
        var = _round_poles(var, units, p)
    # Return either degrees or meters depending on if the inverse is true or not.
    # Don't convert if inverse is True: Want degrees.
    # Converts list-like from degrees to meters.
    if is_angle and not inverse:
        if name in ('radius', 'resolution'):
            var = _distance_from_center_forward(var, center, p)
        else:
            var = p(*var, errcheck=True)
    # Don't convert if inverse is False: Want meters.
    elif not is_angle and inverse:
        # Converts list-like from meters to degrees.
        var = p(*var, inverse=True, errcheck=True)
    if name in ['radius', 'resolution']:
        var = (abs(var[0]), abs(var[1]))
    return var
Esempio n. 9
0
    def test_get_bounding_corners(self):
        """Test calculation of bounding corners."""
        from pyresample.bilinear import (_get_output_xy, _get_input_xy,
                                         _get_bounding_corners)
        from pyresample._spatial_mp import Proj

        proj = Proj(self.target_def.proj_str)
        out_x, out_y = _get_output_xy(self.target_def, proj)
        in_x, in_y = _get_input_xy(self.swath_def, proj, self.input_idxs,
                                   self.idx_ref)
        res = _get_bounding_corners(in_x, in_y, out_x, out_y, self.neighbours,
                                    self.idx_ref)
        for i in range(len(res) - 1):
            pt_ = res[i]
            for j in range(2):
                # Only the sixth output location has four valid corners
                self.assertTrue(np.isfinite(pt_[5, j]))
Esempio n. 10
0
    def test_get_four_closest_corners(self):
        """Test calculation of bounding corners."""
        from pyresample.bilinear import (_get_output_xy, _get_input_xy,
                                         _get_four_closest_corners)
        from pyresample._spatial_mp import Proj

        proj = Proj(self.target_def.proj_str)
        out_x, out_y = _get_output_xy(self.target_def)
        in_x, in_y = _get_input_xy(self.source_def, proj, self.input_idxs,
                                   self.idx_ref)
        (pt_1, pt_2, pt_3,
         pt_4), ia_ = _get_four_closest_corners(in_x, in_y, out_x, out_y,
                                                self._neighbours, self.idx_ref)

        self.assertTrue(pt_1.shape == pt_2.shape == pt_3.shape == pt_4.shape ==
                        (self.target_def.size, 2))
        self.assertTrue(ia_.shape == (self.target_def.size, 4))

        # Check which of the locations has four valid X/Y pairs by
        # finding where there are non-NaN values
        res = np.sum(pt_1 + pt_2 + pt_3 + pt_4, axis=1)
        self.assertEqual(np.sum(~np.isnan(res)), 10)
Esempio n. 11
0
def create_area_def(area_id,
                    projection,
                    width=None,
                    height=None,
                    area_extent=None,
                    shape=None,
                    upper_left_extent=None,
                    center=None,
                    resolution=None,
                    radius=None,
                    units=None,
                    **kwargs):
    """Takes data the user knows and tries to make an area definition from what can be found.

    Parameters
    ----------
    area_id : str
        ID of area
    projection : dict or str
        Projection parameters as a proj4_dict or proj4_string
    description : str, optional
        Description/name of area. Defaults to area_id
    proj_id : str, optional
        ID of projection (deprecated)
    units : str, optional
        Units that provided arguments should be interpreted as. This can be
        one of 'deg', 'degrees', 'meters', 'metres', and any
        parameter supported by the
        `cs2cs -lu <https://proj4.org/apps/cs2cs.html#cmdoption-cs2cs-lu>`_
        command. Units are determined in the following priority:

        1. units expressed with each variable through a DataArray's attrs attribute.
        2. units passed to ``units``
        3. units used in ``projection``
        4. meters

    width : str, optional
        Number of pixels in the x direction
    height : str, optional
        Number of pixels in the y direction
    area_extent : list, optional
        Area extent as a list (lower_left_x, lower_left_y, upper_right_x, upper_right_y)
    shape : list, optional
        Number of pixels in the y and x direction (height, width)
    upper_left_extent : list, optional
        Upper left corner of upper left pixel (x, y)
    center : list, optional
        Center of projection (x, y)
    resolution : list or float, optional
        Size of pixels: (dx, dy)
    radius : list or float, optional
        Length from the center to the edges of the projection (dx, dy)
    rotation: float, optional
        rotation in degrees(negative is cw)
    nprocs : int, optional
        Number of processor cores to be used
    lons : numpy array, optional
        Grid lons
    lats : numpy array, optional
        Grid lats
    optimize_projection:
        Whether the projection parameters have to be optimized for a DynamicAreaDefinition.

    Returns
    -------
    AreaDefinition or DynamicAreaDefinition : AreaDefinition or DynamicAreaDefinition
        If shape and area_extent are found, an AreaDefinition object is returned.
        If only shape or area_extent can be found, a DynamicAreaDefinition object is returned

    Raises
    ------
    ValueError:
        If neither shape nor area_extent could be found

    Notes
    -----
    * ``resolution`` and ``radius`` can be specified with one value if dx == dy
    * If ``resolution`` and ``radius`` are provided as angles, center must be given or findable. In such a case,
      they represent [projection x distance from center[0] to center[0]+dx, projection y distance from center[1] to
      center[1]+dy]
    """
    from pyresample._spatial_mp import Proj
    description = kwargs.pop('description', area_id)
    proj_id = kwargs.pop('proj_id', None)

    # Get a proj4_dict from either a proj4_dict or a proj4_string.
    proj_dict = _get_proj_data(projection)
    try:
        p = Proj(proj_dict, preserve_units=True)
    except RuntimeError:
        return _make_area(area_id, description, proj_id, proj_dict, shape,
                          area_extent, **kwargs)

    # If no units are provided, try to get units used in proj_dict. If still none are provided, use meters.
    if units is None:
        units = proj_dict.get('units',
                              'm' if not p.is_latlong() else 'degrees')

    # Allow height and width to be provided for more consistency across functions in pyresample.
    if height is not None or width is not None:
        shape = _validate_variable(shape, (height, width), 'shape',
                                   ['height', 'width'])

    # Makes sure list-like objects are list-like, have the right shape, and contain only numbers.
    center = _verify_list('center', center, 2)
    radius = _verify_list('radius', radius, 2)
    upper_left_extent = _verify_list('upper_left_extent', upper_left_extent, 2)
    resolution = _verify_list('resolution', resolution, 2)
    shape = _verify_list('shape', shape, 2)
    area_extent = _verify_list('area_extent', area_extent, 4)

    # Converts from lat/lon to projection coordinates (x,y) if not in projection coordinates. Returns tuples.
    center = _convert_units(center, 'center', units, p, proj_dict)
    upper_left_extent = _convert_units(upper_left_extent, 'upper_left_extent',
                                       units, p, proj_dict)
    if area_extent is not None:
        # convert area extent, pass as (X, Y)
        area_extent_ll = area_extent[:2]
        area_extent_ur = area_extent[2:]
        area_extent_ll = _convert_units(area_extent_ll, 'area_extent', units,
                                        p, proj_dict)
        area_extent_ur = _convert_units(area_extent_ur, 'area_extent', units,
                                        p, proj_dict)
        area_extent = area_extent_ll + area_extent_ur

    # Fills in missing information to attempt to create an area definition.
    if area_extent is None or shape is None:
        area_extent, shape = _extrapolate_information(area_extent, shape,
                                                      center, radius,
                                                      resolution,
                                                      upper_left_extent, units,
                                                      p, proj_dict)
    return _make_area(area_id, description, proj_id, proj_dict, shape,
                      area_extent, **kwargs)
Esempio n. 12
0
 def test_get_output_xy(self):
     proj = Proj(self.target_def.proj_str)
     out_x, out_y = bil._get_output_xy(self.target_def, proj)
     self.assertTrue(out_x.all())
     self.assertTrue(out_y.all())
Esempio n. 13
0
 def _get_input_xy(self):
     return _get_input_xy(self._source_geo_def,
                          Proj(self._target_geo_def.proj_str),
                          self._valid_input_index, self._index_array)
Esempio n. 14
0
def get_bil_info(source_geo_def,
                 target_area_def,
                 radius=50e3,
                 neighbours=32,
                 nprocs=1,
                 masked=False,
                 reduce_data=True,
                 segments=None,
                 epsilon=0):
    """Calculate information needed for bilinear resampling.

    source_geo_def : object
        Geometry definition of source data
    target_area_def : object
        Geometry definition of target area
    radius : float, optional
        Cut-off distance in meters
    neighbours : int, optional
        Number of neighbours to consider for each grid point when
        searching the closest corner points
    nprocs : int, optional
        Number of processor cores to be used for getting neighbour info
    masked : bool, optional
        If true, return masked arrays, else return np.nan values for
        invalid points (default)
    reduce_data : bool, optional
        Perform initial coarse reduction of source dataset in order
        to reduce execution time
    segments : int or None
        Number of segments to use when resampling.
        If set to None an estimate will be calculated
    epsilon : float, optional
        Allowed uncertainty in meters. Increasing uncertainty
        reduces execution time

    Returns
    -------
    t__ : numpy array
        Vertical fractional distances from corner to the new points
    s__ : numpy array
        Horizontal fractional distances from corner to the new points
    input_idxs : numpy array
        Valid indices in the input data
    idx_arr : numpy array
        Mapping array from valid source points to target points
    """

    # Check source_geo_def
    # if isinstance(source_geo_def, tuple):
    #     from pyresample.geometry import SwathDefinition
    #     lons, lats = _mask_coordinates(source_geo_def[0], source_geo_def[1])
    #     source_geo_def = SwathDefinition(lons, lats)

    # Calculate neighbour information
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        (input_idxs, output_idxs, idx_ref, dists) = \
            kd_tree.get_neighbour_info(source_geo_def, target_area_def,
                                       radius, neighbours=neighbours,
                                       nprocs=nprocs, reduce_data=reduce_data,
                                       segments=segments, epsilon=epsilon)

    del output_idxs, dists

    # Reduce index reference
    input_size = input_idxs.sum()
    index_mask = (idx_ref == input_size)
    idx_ref = np.where(index_mask, 0, idx_ref)

    # Get output projection as pyproj object
    proj = Proj(target_area_def.proj_str)

    # Get output x/y coordinates
    out_x, out_y = _get_output_xy(target_area_def, proj)

    # Get input x/y coordinates
    in_x, in_y = _get_input_xy(source_geo_def, proj, input_idxs, idx_ref)

    # Get the four closest corner points around each output location
    pt_1, pt_2, pt_3, pt_4, idx_ref = \
        _get_bounding_corners(in_x, in_y, out_x, out_y, neighbours, idx_ref)

    # Calculate vertical and horizontal fractional distances t and s
    t__, s__ = _get_ts(pt_1, pt_2, pt_3, pt_4, out_x, out_y)

    # Mask NaN values
    if masked:
        mask = np.isnan(t__) | np.isnan(s__)
        t__ = np.ma.masked_where(mask, t__)
        s__ = np.ma.masked_where(mask, s__)

    return t__, s__, input_idxs, idx_ref
Esempio n. 15
0
 def test_get_input_xy(self):
     proj = Proj(self.target_def.proj_str)
     in_x, in_y = bil._get_output_xy(self.swath_def, proj)
     self.assertTrue(in_x.all())
     self.assertTrue(in_y.all())
Esempio n. 16
0
    def get_bil_info(self):
        """Return neighbour info.

        Returns
        -------
        t__ : numpy array
            Vertical fractional distances from corner to the new points
        s__ : numpy array
            Horizontal fractional distances from corner to the new points
        input_idxs : numpy array
            Valid indices in the input data
        idx_arr : numpy array
            Mapping array from valid source points to target points

        """
        if self.source_geo_def.size < self.neighbours:
            warnings.warn('Searching for %s neighbours in %s data points' %
                          (self.neighbours, self.source_geo_def.size))

        # Create kd-tree
        valid_input_idx, resample_kdtree = self._create_resample_kdtree()
        # This is a numpy array
        self.valid_input_index = valid_input_idx

        if resample_kdtree.n == 0:
            # Handle if all input data is reduced away
            bilinear_t, bilinear_s, valid_input_index, index_array = \
                _create_empty_bil_info(self.source_geo_def,
                                       self.target_geo_def)
            self.bilinear_t = bilinear_t
            self.bilinear_s = bilinear_s
            self.valid_input_index = valid_input_idx
            self.index_array = index_array

            return bilinear_t, bilinear_s, valid_input_index, index_array

        target_lons, target_lats = self.target_geo_def.get_lonlats()
        valid_output_idx = ((target_lons >= -180) & (target_lons <= 180) &
                            (target_lats <= 90) & (target_lats >= -90))

        index_array, distance_array = self._query_resample_kdtree(
            resample_kdtree, target_lons, target_lats, valid_output_idx)

        # Reduce index reference
        input_size = da.sum(self.valid_input_index)
        index_mask = index_array == input_size
        index_array = da.where(index_mask, 0, index_array)

        # Get output projection as pyproj object
        proj = Proj(self.target_geo_def.proj_str)

        # Get output x/y coordinates
        out_x, out_y = _get_output_xy_dask(self.target_geo_def, proj)

        # Get input x/y coordinates
        in_x, in_y = _get_input_xy_dask(self.source_geo_def, proj,
                                        self.valid_input_index, index_array)

        # Get the four closest corner points around each output location
        pt_1, pt_2, pt_3, pt_4, index_array = \
            _get_bounding_corners_dask(in_x, in_y, out_x, out_y,
                                       self.neighbours, index_array)

        # Calculate vertical and horizontal fractional distances t and s
        t__, s__ = _get_ts_dask(pt_1, pt_2, pt_3, pt_4, out_x, out_y)
        self.bilinear_t, self.bilinear_s = t__, s__

        self.valid_output_index = valid_output_idx
        self.index_array = index_array
        self.distance_array = distance_array

        return (self.bilinear_t, self.bilinear_s, self.valid_input_index,
                self.index_array)
Esempio n. 17
0
def create_area_def(area_id, projection, width=None, height=None, area_extent=None, shape=None, upper_left_extent=None,
                    center=None, resolution=None, radius=None, units=None, **kwargs):
    """Takes data the user knows and tries to make an area definition from what can be found.

    Parameters
    ----------
    area_id : str
        ID of area
    projection : dict or str
        Projection parameters as a proj4_dict or proj4_string
    description : str, optional
        Description/name of area. Defaults to area_id
    proj_id : str, optional
        ID of projection (deprecated)
    units : str, optional
        Units that provided arguments should be interpreted as. This can be
        one of 'deg', 'degrees', 'meters', 'metres', and any
        parameter supported by the
        `cs2cs -lu <https://proj4.org/apps/cs2cs.html#cmdoption-cs2cs-lu>`_
        command. Units are determined in the following priority:

        1. units expressed with each variable through a DataArray's attrs attribute.
        2. units passed to ``units``
        3. units used in ``projection``
        4. meters

    width : str, optional
        Number of pixels in the x direction
    height : str, optional
        Number of pixels in the y direction
    area_extent : list, optional
        Area extent as a list (lower_left_x, lower_left_y, upper_right_x, upper_right_y)
    shape : list, optional
        Number of pixels in the y and x direction (height, width)
    upper_left_extent : list, optional
        Upper left corner of upper left pixel (x, y)
    center : list, optional
        Center of projection (x, y)
    resolution : list or float, optional
        Size of pixels: (dx, dy)
    radius : list or float, optional
        Length from the center to the edges of the projection (dx, dy)
    rotation: float, optional
        rotation in degrees(negative is cw)
    nprocs : int, optional
        Number of processor cores to be used
    lons : numpy array, optional
        Grid lons
    lats : numpy array, optional
        Grid lats
    optimize_projection:
        Whether the projection parameters have to be optimized for a DynamicAreaDefinition.

    Returns
    -------
    AreaDefinition or DynamicAreaDefinition : AreaDefinition or DynamicAreaDefinition
        If shape and area_extent are found, an AreaDefinition object is returned.
        If only shape or area_extent can be found, a DynamicAreaDefinition object is returned

    Raises
    ------
    ValueError:
        If neither shape nor area_extent could be found

    Notes
    -----
    * ``resolution`` and ``radius`` can be specified with one value if dx == dy
    * If ``resolution`` and ``radius`` are provided as angles, center must be given or findable. In such a case,
      they represent [projection x distance from center[0] to center[0]+dx, projection y distance from center[1] to
      center[1]+dy]
    """
    from pyresample._spatial_mp import Proj
    description = kwargs.pop('description', area_id)
    proj_id = kwargs.pop('proj_id', None)

    # Get a proj4_dict from either a proj4_dict or a proj4_string.
    proj_dict = _get_proj_data(projection)
    try:
        p = Proj(proj_dict, preserve_units=True)
    except RuntimeError:
        return _make_area(area_id, description, proj_id, proj_dict, shape, area_extent, **kwargs)

    # If no units are provided, try to get units used in proj_dict. If still none are provided, use meters.
    if units is None:
        units = proj_dict.get('units', 'm' if not p.is_latlong() else 'degrees')

    # Allow height and width to be provided for more consistency across functions in pyresample.
    if height is not None or width is not None:
        shape = _validate_variable(shape, (height, width), 'shape', ['height', 'width'])

    # Makes sure list-like objects are list-like, have the right shape, and contain only numbers.
    center = _verify_list('center', center, 2)
    radius = _verify_list('radius', radius, 2)
    upper_left_extent = _verify_list('upper_left_extent', upper_left_extent, 2)
    resolution = _verify_list('resolution', resolution, 2)
    shape = _verify_list('shape', shape, 2)
    area_extent = _verify_list('area_extent', area_extent, 4)

    # Converts from lat/lon to projection coordinates (x,y) if not in projection coordinates. Returns tuples.
    center = _convert_units(center, 'center', units, p, proj_dict)
    upper_left_extent = _convert_units(upper_left_extent, 'upper_left_extent', units, p, proj_dict)
    if area_extent is not None:
        # convert area extent, pass as (X, Y)
        area_extent_ll = area_extent[:2]
        area_extent_ur = area_extent[2:]
        area_extent_ll = _convert_units(area_extent_ll, 'area_extent', units, p, proj_dict)
        area_extent_ur = _convert_units(area_extent_ur, 'area_extent', units, p, proj_dict)
        area_extent = area_extent_ll + area_extent_ur

    # Fills in missing information to attempt to create an area definition.
    if area_extent is None or shape is None:
        area_extent, shape = _extrapolate_information(area_extent, shape, center, radius, resolution,
                                                      upper_left_extent, units, p, proj_dict)
    return _make_area(area_id, description, proj_id, proj_dict, shape, area_extent, **kwargs)