images module
restee.images
img_to_geotiff(session, domain, image, outfile, bands=None)
Function to save requested ee.Image to a file in a GeoTIFF format
Parameters:
Name | Type | Description | Default |
---|---|---|---|
session |
EESession |
Earth Engine cloud session used to manage REST API requests |
required |
domain |
Domain |
Domain object defining the spatial region to request image |
required |
image |
Image |
computed ee.Image object to request |
required |
outfile |
str |
path to write requested data to |
required |
bands |
Iterable |
list or tuple or band names to request from image, if None then all bands will be requested. default = None |
None |
Examples:
>>> img = (
ee.ImageCollection('MODIS/006/MOD13Q1')
.select("NDVI")
.first()
)
>>> states = ee.FeatureCollection('TIGER/2018/States')
>>> maine = states.filter(ee.Filter.eq('NAME', 'Maine'))
>>> domain = restee.Domain.from_ee_geometry(session,maine,0.01)
>>> ree.img_to_geotiff(session,domain,img,"maine_ndvi.tiff")
Source code in restee/images.py
def img_to_geotiff(
session: EESession,
domain: Domain,
image: ee.Image,
outfile: str,
bands: Iterable = None,
):
"""Function to save requested ee.Image to a file in a GeoTIFF format
args:
session (EESession): Earth Engine cloud session used to manage REST API requests
domain (Domain): Domain object defining the spatial region to request image
image (ee.Image): computed ee.Image object to request
outfile (str): path to write requested data to
bands (Iterable[str]): list or tuple or band names to request from image, if None then
all bands will be requested. default = None
example:
>>> img = (
ee.ImageCollection('MODIS/006/MOD13Q1')
.select("NDVI")
.first()
)
>>> states = ee.FeatureCollection('TIGER/2018/States')
>>> maine = states.filter(ee.Filter.eq('NAME', 'Maine'))
>>> domain = restee.Domain.from_ee_geometry(session,maine,0.01)
>>> ree.img_to_geotiff(session,domain,img,"maine_ndvi.tiff")
"""
outfile = Path(outfile)
if bands is None:
bands = get_value(session, image.bandNames())
pixels = _get_image(session, domain, image, bands, dataformat="GEO_TIFF")
outfile.write_bytes(pixels)
return
img_to_ndarray(session, domain, image, bands=None)
Function to request ee.Image as a numpy.ndarray
Parameters:
Name | Type | Description | Default |
---|---|---|---|
session |
EESession |
Earth Engine cloud session used to manage REST API requests |
required |
domain |
Domain |
Domain object defining the spatial region to request image |
required |
image |
Image |
computed ee.Image object to request |
required |
bands |
Iterable |
list or tuple or band names to request from image, if None then all bands will be requested. default = None |
None |
Returns:
Type | Description |
---|---|
numpy.ndarray |
structured numpy array where each band from image is a named field |
Examples:
>>> img = (
ee.ImageCollection('MODIS/006/MOD13Q1')
.select("NDVI")
.first()
)
>>> states = ee.FeatureCollection('TIGER/2018/States')
>>> maine = states.filter(ee.Filter.eq('NAME', 'Maine'))
>>> domain = restee.Domain.from_ee_geometry(session,maine,0.01)
>>> ndvi_arr = ree.img_to_ndarray(session,domain,img)
Source code in restee/images.py
def img_to_ndarray(
session: EESession,
domain: Domain,
image: ee.Image,
bands: Iterable = None,
):
"""Function to request ee.Image as a numpy.ndarray
args:
session (EESession): Earth Engine cloud session used to manage REST API requests
domain (Domain): Domain object defining the spatial region to request image
image (ee.Image): computed ee.Image object to request
bands (Iterable[str]): list or tuple or band names to request from image, if None then
all bands will be requested. default = None
returns:
numpy.ndarray: structured numpy array where each band from image is a named field
example:
>>> img = (
ee.ImageCollection('MODIS/006/MOD13Q1')
.select("NDVI")
.first()
)
>>> states = ee.FeatureCollection('TIGER/2018/States')
>>> maine = states.filter(ee.Filter.eq('NAME', 'Maine'))
>>> domain = restee.Domain.from_ee_geometry(session,maine,0.01)
>>> ndvi_arr = ree.img_to_ndarray(session,domain,img)
"""
if bands is None:
bands = get_value(session, image.bandNames())
pixels = _get_image(session, domain, image, bands, dataformat="NPY")
return np.load(BytesIO(pixels))
img_to_xarray(session, domain, image, bands=None, apply_mask=True, no_data_value=None)
Function to request ee.Image as a xarray Dataset. This function wraps img_to_ndarray.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
session |
EESession |
Earth Engine cloud session used to manage REST API requests |
required |
domain |
Domain |
Domain object defining the spatial region to request image |
required |
image |
Image |
computed ee.Image object to request |
required |
bands |
Iterable |
list or tuple or band names to request from image, if None then all bands will be requested. default = None |
None |
apply_mask |
bool |
mask pixels based on domain mask. default = True |
True |
no_data_value |
float |
no data value to mask in returned dataset, typically 0. if None, then no data will be masked by value. default = None |
None |
Returns:
Type | Description |
---|---|
xarray.Dataset |
dataset with geocoordinates and each band as a variable |
Examples:
>>> img = (
ee.ImageCollection('MODIS/006/MOD13Q1')
.first()
)
>>> states = ee.FeatureCollection('TIGER/2018/States')
>>> maine = states.filter(ee.Filter.eq('NAME', 'Maine'))
>>> domain = restee.Domain.from_ee_geometry(session,maine,0.01)
>>> ds_ndvi = ree.img_to_xarray(session,domain,img,no_data_value=0)
Source code in restee/images.py
def img_to_xarray(
session: EESession,
domain: Domain,
image: ee.Image,
bands: Iterable = None,
apply_mask: bool = True,
no_data_value: float = None,
):
"""Function to request ee.Image as a xarray Dataset. This function
wraps img_to_ndarray.
args:
session (EESession): Earth Engine cloud session used to manage REST API requests
domain (Domain): Domain object defining the spatial region to request image
image (ee.Image): computed ee.Image object to request
bands (Iterable[str]): list or tuple or band names to request from image, if None then
all bands will be requested. default = None
apply_mask (bool): mask pixels based on domain mask. default = True
no_data_value (float): no data value to mask in returned dataset, typically 0. if None,
then no data will be masked by value. default = None
returns:
xarray.Dataset: dataset with geocoordinates and each band as a variable
example:
>>> img = (
ee.ImageCollection('MODIS/006/MOD13Q1')
.first()
)
>>> states = ee.FeatureCollection('TIGER/2018/States')
>>> maine = states.filter(ee.Filter.eq('NAME', 'Maine'))
>>> domain = restee.Domain.from_ee_geometry(session,maine,0.01)
>>> ds_ndvi = ree.img_to_xarray(session,domain,img,no_data_value=0)
"""
if bands is None:
bands = get_value(session, image.bandNames())
pixels = img_to_ndarray(session, domain, image, bands=bands)
bandnames = pixels.dtype.names
if CRS.from_string(domain.crs).is_geographic:
x_name, y_name = "lon", "lat"
x_long, y_long = "Longitude", "Latitude"
x_units, y_units = "degrees_east", "degrees_north"
else:
x_name, y_name = (
"x",
"y",
)
x_long, y_long = "Eastings", "Northings"
# assumes all non-geographic projections have m units...
x_units, y_units = "meters", "meters"
# CF conventions are coordinates for center pixels
# assign domain coordinates and shift to center
coords = {
x_name: (
[x_name],
domain.x_coords + (domain.resolution / 2),
{"units": x_units, "long_name": x_long},
),
y_name: (
[y_name],
domain.y_coords - (domain.resolution / 2),
{"units": y_units, "long_name": y_long},
),
}
data_dict = {band: ([y_name, x_name], pixels[band]) for band in bandnames}
ds = xr.Dataset(data_dict, coords=coords)
if no_data_value is not None:
ds = ds.where(ds != no_data_value)
if apply_mask:
ds = ds.where(domain.mask == 1)
return ds
imgcollection_to_xarray(session, domain, imagecollection, bands=None, max_workers=5, verbose=False, apply_mask=True, no_data_value=None)
Function to request ee.ImageCollection as a xarray Dataset. This function assumes the image collection is distinguished by time (i.e. 'system:time_start' property). Sends multiple concurrent requests to speed up data transfer. This function wraps img_to_ndarray.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
session |
EESession |
Earth Engine cloud session used to manage REST API requests |
required |
domain |
Domain |
Domain object defining the spatial region to request image |
required |
imagecollection |
ImageCollection |
computed ee.ImageCollection object to request,
images must have |
required |
bands |
Iterable |
list or tuple or band names to request from image, if None then all bands will be requested. default = None |
None |
max_workers |
int |
number of concurrent requests to send. default = 5, |
5 |
verbose |
bool |
flag to determine if a request progress bar should be shown. default = False |
False |
apply_mask |
bool |
mask pixels based on domain mask. default = True |
True |
no_data_value |
float |
no data value to mask in returned dataset, typically 0. if None, then no data will be masked by value. default = None |
None |
Returns:
Type | Description |
---|---|
xarray.Dataset |
dataset with multiple images along time dimesions, each band is a variable |
Examples:
>>> ic = (
ee.ImageCollection('MODIS/006/MOD13Q1')
.limit(10,"system:time_start")
)
>>> states = ee.FeatureCollection('TIGER/2018/States')
>>> maine = states.filter(ee.Filter.eq('NAME', 'Maine'))
>>> domain = restee.Domain.from_ee_geometry(session,maine,0.01)
>>> ds_ndvi = ree.imgcollection_to_xarray(session,domain,img,no_data_value=0,verbose=True)
Source code in restee/images.py
def imgcollection_to_xarray(
session,
domain: Domain,
imagecollection: ee.ImageCollection,
bands: Iterable = None,
max_workers: int = 5,
verbose: bool = False,
apply_mask: bool = True,
no_data_value: float = None,
):
"""Function to request ee.ImageCollection as a xarray Dataset. This function assumes
the image collection is distinguished by time (i.e. 'system:time_start' property).
Sends multiple concurrent requests to speed up data transfer. This function wraps
img_to_ndarray.
args:
session (EESession): Earth Engine cloud session used to manage REST API requests
domain (Domain): Domain object defining the spatial region to request image
imagecollection (ee.ImageCollection): computed ee.ImageCollection object to request,
images must have `system:time_start` property
bands (Iterable[str]): list or tuple or band names to request from image, if None then
all bands will be requested. default = None
max_workers (int): number of concurrent requests to send. default = 5,
verbose (bool): flag to determine if a request progress bar should be shown. default = False
apply_mask (bool): mask pixels based on domain mask. default = True
no_data_value (float): no data value to mask in returned dataset, typically 0. if None,
then no data will be masked by value. default = None
returns:
xarray.Dataset: dataset with multiple images along time dimesions, each band is a variable
example:
>>> ic = (
ee.ImageCollection('MODIS/006/MOD13Q1')
.limit(10,"system:time_start")
)
>>> states = ee.FeatureCollection('TIGER/2018/States')
>>> maine = states.filter(ee.Filter.eq('NAME', 'Maine'))
>>> domain = restee.Domain.from_ee_geometry(session,maine,0.01)
>>> ds_ndvi = ree.imgcollection_to_xarray(session,domain,img,no_data_value=0,verbose=True)
"""
#TODO: write functionality to allow the definition of ImageCollections by other properties than time
dates = get_value(session, imagecollection.aggregate_array("system:time_start"))
dates = pd.to_datetime(list(map(lambda x: x / 1e-6, dates)))
coll_id = get_value(session, imagecollection.get("system:id"))
n_imgs = get_value(session, imagecollection.size())
if bands is None:
bands = get_value(session, ee.Image(imagecollection.first()).bandNames())
imgseq = range(n_imgs)
imglist = imagecollection.toList(n_imgs)
def request_func(x):
return img_to_ndarray(session, domain, ee.Image(imglist.get(x)), bands=bands)
if n_imgs < max_workers:
gen = map(request_func, imgseq)
if verbose:
series = tuple(tqdm(gen, total=n_imgs, desc=f"{coll_id} progress"))
else:
series = tuple(gen)
else:
with ThreadPoolExecutor(max_workers) as executor:
gen = executor.map(request_func, imgseq)
if verbose:
series = tuple(tqdm(gen, total=n_imgs, desc=f"{coll_id} progress"))
else:
series = tuple(gen)
if CRS.from_string(domain.crs).is_geographic:
x_name, y_name = "lon", "lat"
x_long, y_long = "Longitude", "Latitude"
x_units, y_units = "degrees_east", "degrees_north"
else:
x_name, y_name = (
"x",
"y",
)
x_long, y_long = "Eastings", "Northings"
# assumes all non-geographic projections have m units...
x_units, y_units = "meters", "meters"
# CF conventions are coordinates for center pixels
# assign domain coordinates and shift to center
data_dict = {
"time": {"dims": ("time"), "data": dates},
x_name: {
"dims": (x_name),
"data": domain.x_coords + (domain.resolution / 2),
"attrs": {"long_name": x_long, "units": x_units},
},
y_name: {
"dims": (y_name),
"data": domain.y_coords - (domain.resolution / 2),
"attrs": {"long_name": y_long, "units": y_units},
},
}
bandnames = series[0].dtype.names
series_shp = (n_imgs, domain.y_size, domain.x_size)
for i in range(n_imgs):
for band in bandnames:
if i == 0:
data_dict[band] = {
"dims": ("time", y_name, x_name),
"data": np.zeros(series_shp),
}
data_dict[band]["data"][i, :, :] = series[i][band][:, :]
ds = xr.Dataset.from_dict(data_dict)
if no_data_value is not None:
ds = ds.where(ds != no_data_value)
if apply_mask:
ds = ds.where(domain.mask == 1)
return ds