Skip to content

core module

restee.core

Domain

Domain class to define spatial region for image requests

Examples:

Defines a psuedo-global domain at 1 degree resolution

>>> coords =  [-180,-60,180,85]
>>> domain = restee.Domain(coords,resolution=1)
>>> domain.shape
    (145, 360)

pixelgrid property readonly

Property for json/dict represenstion of pixel grid info for requesting EE rasters. Used to define the spatial domain and shape of imagery for requests

Returns:

Type Description
dict

dictionary representation of pixel grid (https://developers.google.com/earth-engine/reference/rest/v1beta/PixelGrid)

__init__(self, bbox, resolution=0.25, crs='EPSG:4326') special

Initialize Domain class

Parameters:

Name Type Description Default
bbox Iterable

bounding box to create domain as [W,S,E,N]

required
resolution float

resolution to make domain. default = 0.25

0.25
crs str

string name of coordinate reference system of domain. resolution units must match the crs units. default = "EPSG:4326"

'EPSG:4326'
Source code in restee/core.py
def __init__(
    self, bbox: Iterable, resolution: float = 0.25, crs: str = "EPSG:4326"
):
    """Initialize Domain class

    args:
        bbox (Iterable): bounding box to create domain as [W,S,E,N]
        resolution (float): resolution to make domain. default = 0.25
        crs (str): string name of coordinate reference system of domain.
            resolution units must match the crs units. default = "EPSG:4326"
    """
    # set crs
    self._crs = crs

    # set resolution info
    self.resolution = resolution

    # set the bounding box
    if np.any((np.array(bbox) % self.resolution)) != 0:
        self.bbox = Domain._round_out(bbox, self.resolution)
    else:
        self.bbox = bbox

    minx, miny, maxx, maxy = self.bbox
    y_coords = np.arange(miny+self.resolution, maxy+self.resolution, self.resolution)[::-1]
    x_coords = np.arange(minx, maxx, self.resolution)

    self.x_size = x_coords.size
    self.y_size = y_coords.size

    self.x_coords = x_coords
    self.y_coords = y_coords

    self._construct_grid()

    self._mask = np.ones(self.shape)

    return

from_ee_geometry(session, geom, resolution=0.25) staticmethod

Domain contructor function that takes a ee.Geometry, ee.Feature, or ee.FeatureCollection and returns a domain object with the geometry as a mask. Useful for using ee to process a region and use as domain for requsting imagery.

Parameters:

Name Type Description Default
session EESession

restee session autheticated to make requests

required
geom ee.Geometry|ee.Feature|ee.FeatureCollection

ee object to create the domain from

required
resolution float

resolution to make domain, must match units of vector crs. default = 0.25

0.25

Returns:

Type Description
restee.Domain

domain object with mask from vector

Source code in restee/core.py
@staticmethod
def from_ee_geometry(session, geom, resolution: float = 0.25):
    """Domain contructor function that takes a ee.Geometry, ee.Feature, or ee.FeatureCollection
    and returns a domain object with the geometry as a mask. Useful for using ee to process
    a region and use as domain for requsting imagery.

    args:
        session (EESession): restee session autheticated to make requests
        geom (ee.Geometry|ee.Feature|ee.FeatureCollection): ee object to create the domain from
        resolution (float): resolution to make domain, must match units of vector crs.
            default = 0.25

    returns:
        restee.Domain: domain object with mask from vector
    """
    if isinstance(geom, ee.Geometry):
        fc = ee.FeatureCollection([ee.Feature(geom)])
    elif isinstance(geom, ee.Feature):
        fc = ee.FeatureCollection([geom])
    else:
        fc = geom

    project = session.cloud_project
    url = f"https://earthengine.googleapis.com/v1beta/projects/{project}/table:computeFeatures"
    serialized = ee.serializer.encode(fc, for_cloud_api=True)
    payload = dict(expression=serialized)

    response = session.send_request(url, payload)

    gdf = gpd.read_file(StringIO(response.content.decode()))

    return Domain.from_geopandas(gdf, resolution=resolution)

from_geopandas(gdf, resolution=0.25) staticmethod

Domain constructor function that takes a GeoDataFrame and returns a domain object with the vector as a mask.

Parameters:

Name Type Description Default
gdf geopandas.GeoDataFrame

GeoDataFrame to create the domain from

required
resolution float

resolution to make domain, must match units of vector crs. default = 0.25

0.25

Returns:

Type Description
restee.Domain

domain object with mask from vector

Source code in restee/core.py
@staticmethod
def from_geopandas(gdf, resolution: float = 0.25):
    """Domain constructor function that takes a GeoDataFrame and returns a domain
    object with the vector as a mask.

    args:
        gdf (geopandas.GeoDataFrame): GeoDataFrame to create the domain from
        resolution (float): resolution to make domain, must match units of vector crs.
            default = 0.25

    returns:
        restee.Domain: domain object with mask from vector
    """
    bbox = Domain._round_out(gdf.total_bounds, res=resolution)
    crs = gdf.crs.srs
    d = Domain(bbox, resolution, crs)
    d.mask = features.geometry_mask(
        gdf.geometry, d.shape, transform=d.transform, all_touched=True, invert=True
    )
    return d

from_rasterio(ds, mask_val=None) staticmethod

Domain contructor function that takes a rasterio object and returns a domain with the same geotransform and crs

Parameters:

Name Type Description Default
ds rasterio

rasterio object to model domain from

required

Returns:

Type Description
restee.Domain

domain object with same geotransform and crs as the input

Source code in restee/core.py
@staticmethod
def from_rasterio(ds, mask_val=None):
    """Domain contructor function that takes a rasterio object and returns a domain
    with the same geotransform and crs

    args:
        ds (rasterio): rasterio object to model domain from

    returns:
        restee.Domain: domain object with same geotransform and crs as the input
    """
    resolution = np.mean(ds.res)
    crs = ds.crs.data["init"]
    bbox = tuple(ds.bounds)
    d = Domain(bbox, resolution, crs)
    # TODO: add code to automatically mask no data values
    return d

resample(self, factor)

Function to resample domain shape and coordinates to a new resolution. Useful for requesting imagery over the same domain but at different spatial resolutions

Parameters:

Name Type Description Default
factor float

factor to scale the shape and coordinates. For example, if factor = 2, then the resolution will half and shape doubles.

required

Returns:

Type Description
restee.Domain

domain object with new resolution/coordinates

Source code in restee/core.py
def resample(self, factor: float):
    """Function to resample domain shape and coordinates to a new resolution.
    Useful for requesting imagery over the same domain but at different spatial
    resolutions

    args:
        factor (float): factor to scale the shape and coordinates. For example,
            if factor = 2, then the resolution will half and shape doubles.

    returns:
        restee.Domain: domain object with new resolution/coordinates
    """
    new = copy.deepcopy(self)
    new.resolution = float(new.resolution / factor)
    # interpolate the x coordinates
    old_x = np.arange(self.x_size) * factor
    new_x = np.arange(self.x_size * factor)
    f_x = interpolate.interp1d(
        old_x, self.x_coords, bounds_error=False, fill_value="extrapolate"
    )
    new.x_coords = f_x(new_x)

    old_x = np.arange(self.y_size) * factor
    new_x = np.arange(self.y_size * factor)
    f_y = interpolate.interp1d(
        old_x, self.y_coords, bounds_error=False, fill_value="extrapolate"
    )
    new.y_coords = f_y(new_x)

    new.x_size = new.x_coords.size
    new.y_size = new.y_coords.size

    new._construct_grid()

    interp_mask = ndimage.zoom(self.mask, factor, order=0, mode="nearest")
    new.mask = interp_mask.astype(np.bool)

    return new

to_ee_bbox(self)

Converts the domain bounding box to and ee.Geometry

Returns:

Type Description
ee.Geometry

bounding box of domain

Source code in restee/core.py
def to_ee_bbox(self):
    """Converts the domain bounding box to and ee.Geometry

    returns:
        ee.Geometry: bounding box of domain
    """
    return ee.Geometry.Rectangle(self.bbox)

EESession

EESession class that handles GCP/EE REST API info to make authenticated requests to Google Cloud. Users provides credentials that are used to create an authorized session to make HTTP requests

__init__(self, project, key) special

Initialization function for the EESession class

Parameters:

Name Type Description Default
project str

Google Cloud project name with service account whitelisted to use Earth Engine

required
key str

path to private key file for your whitelisted service account

required
Source code in restee/core.py
def __init__(self, project: str, key: str):
    """Initialization function for the EESession class

    args:
        project (str): Google Cloud project name with service account whitelisted to use Earth Engine
        key (str): path to private key file for your whitelisted service account
    """
    self._PROJECT = project
    self._SESSION = self._get_session(key)

send_request(self, url, data)

Method to send authenticated requests to google cloud. This is wrapped with a backoff decorator that will try multiple requests if the initial ones fail.

Parameters:

Name Type Description Default
url str

EE REST API endpoint to send request. See https://developers.google.com/earth-engine/reference/rest for more info

required
data dict

Dictionary object to send in the body of the Request.

required

Returns:

Type Description
response

Reponse object with information on status and content

Source code in restee/core.py
@backoff.on_exception(
    backoff.expo,
    requests.exceptions.RequestException,
    max_tries=5,
    max_time=300,
    giveup=_fatal_code,
)
def send_request(self, url, data):
    """Method to send authenticated requests to google cloud.
    This is wrapped with a backoff decorator that will try multiple requests
    if the initial ones fail.

    args:
        url (str): EE REST API endpoint to send request.
            See https://developers.google.com/earth-engine/reference/rest for more info
        data (dict): Dictionary object to send in the body of the Request.

    returns:
        response: Reponse object with information on status and content
    """
    return self.session.post(url=url, data=json.dumps(data))