Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion geetools/ee_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from xee.ext import REQUEST_BYTE_LIMIT

from .accessors import register_class_accessor
from .utils import format_class_info, plot_data
from .utils import area_units_to_m2, format_class_info, plot_data


@register_class_accessor(ee.Image, "geetools")
Expand Down Expand Up @@ -2305,3 +2305,34 @@ def plot_hist(
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left")

return ax

@classmethod
def pixelArea(cls, area_unit: str = "m2", rename_to_units: bool = False) -> ee.Image:
"""Extend the :py:method:`ee.Image.pixelArea` method by setting the unit of the output.

Args:
area_unit: the unit of the output area. can be one of "m2", "ha", "kha", "km2" or "acres".
rename_to_units: if ``True``, the output image will be renamed to the given unit.

Returns:
the area ``ee.Image`` using the given unit.

Examples:
.. jupyter-execute::

import ee, geetools
from geetools.utils import initialize_documentation

initialize_documentation()

hectares = ee.Image.geetools.pixelArea("ha").rename("ha")
acres = ee.Image.geetools.pixelArea("acres").rename("acres")
total = hectares.addBands(acres)

buffer = ee.Geometry.Point(0,0).buffer(100)
values = total.reduceRegion(ee.Reducer.mean(), buffer, 1)
values.getInfo()
"""
name = area_unit if rename_to_units is True else "area"
divisor = area_units_to_m2(area_unit)
return ee.Image.pixelArea().divide(divisor).rename(name)
23 changes: 23 additions & 0 deletions geetools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,26 @@ def format_class_info(class_info: dict) -> dict:
# make sure class value is an int, but store as str
final[str(int(class_value))] = format_bandname(class_name)
return final


def area_units_to_m2(area_units: str) -> float:
"""Convert area units to m2.

Args:
area_units (str): Area units to convert to m2.

Returns:
float: The conversion factor.
"""
areas = {
"m2": 1,
"ha": 1e4,
"km2": 1e6,
"kha": 1e7,
"acres": 4046.86,
}

if area_units not in areas:
raise ValueError(f"Area units '{area_units}' not supported. Use one of {list(areas.keys())}")

return areas.get(area_units, 1)
31 changes: 31 additions & 0 deletions tests/test_Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -946,3 +946,34 @@ def image(self):
@property
def region(self):
return ee.Geometry.Rectangle([-112.60, 40.60, -111.18, 41.22])


class TestPixelArea:
"""Test the ``pixelArea`` method."""

def test_pixel_area_default(self):
surface = ee.Image.pixelArea().reduceRegion(ee.Reducer.mean(), self.buffer, 1)
ldcSurface = ee.Image.geetools.pixelArea().reduceRegion(ee.Reducer.mean(), self.buffer, 1)
isClose = ee.Number(surface.get("area")).subtract(ldcSurface.get("area")).abs().lte(1e-6)
assert bool(isClose.getInfo()) is True

def test_pixel_area(self, ee_dictionary_regression):
hectares = ee.Image.geetools.pixelArea("ha")
total = ee.Image.geetools.pixelArea("acres").addBands(hectares)
dict = total.reduceRegion(ee.Reducer.mean(), self.buffer, 1)
ee_dictionary_regression.check(dict)

def test_pixel_area_rename(self, ee_dictionary_regression):
hectares = ee.Image.geetools.pixelArea("ha", True)
acres = ee.Image.geetools.pixelArea("acres", True)
total = hectares.addBands(acres)
dict = total.reduceRegion(ee.Reducer.mean(), self.buffer, 1)
ee_dictionary_regression.check(dict)

def test_pixel_area_error(self):
with pytest.raises(ValueError):
ee.Image.geetools.pixelArea("not_a_unit")

@property
def buffer(self) -> ee.Geometry:
return ee.Geometry.Point(0, 0).buffer(100)
73 changes: 73 additions & 0 deletions tests/test_Image/serialized_test_pixel_area.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
result: '0'
values:
'0':
functionInvocationValue:
arguments:
geometry:
functionInvocationValue:
arguments:
distance:
constantValue: 100
geometry:
functionInvocationValue:
arguments:
coordinates:
constantValue:
- 0
- 0
functionName: GeometryConstructors.Point
functionName: Geometry.buffer
image:
functionInvocationValue:
arguments:
dstImg:
functionInvocationValue:
arguments:
input:
functionInvocationValue:
arguments:
image1:
valueReference: '1'
image2:
functionInvocationValue:
arguments:
value:
constantValue: 4046.86
functionName: Image.constant
functionName: Image.divide
names:
valueReference: '2'
functionName: Image.rename
srcImg:
functionInvocationValue:
arguments:
input:
functionInvocationValue:
arguments:
image1:
valueReference: '1'
image2:
functionInvocationValue:
arguments:
value:
constantValue: 10000.0
functionName: Image.constant
functionName: Image.divide
names:
valueReference: '2'
functionName: Image.rename
functionName: Image.addBands
reducer:
functionInvocationValue:
arguments: {}
functionName: Reducer.mean
scale:
constantValue: 1
functionName: Image.reduceRegion
'1':
functionInvocationValue:
arguments: {}
functionName: Image.pixelArea
'2':
constantValue:
- area
72 changes: 72 additions & 0 deletions tests/test_Image/serialized_test_pixel_area_rename.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
result: '0'
values:
'0':
functionInvocationValue:
arguments:
geometry:
functionInvocationValue:
arguments:
distance:
constantValue: 100
geometry:
functionInvocationValue:
arguments:
coordinates:
constantValue:
- 0
- 0
functionName: GeometryConstructors.Point
functionName: Geometry.buffer
image:
functionInvocationValue:
arguments:
dstImg:
functionInvocationValue:
arguments:
input:
functionInvocationValue:
arguments:
image1:
valueReference: '1'
image2:
functionInvocationValue:
arguments:
value:
constantValue: 10000.0
functionName: Image.constant
functionName: Image.divide
names:
constantValue:
- ha
functionName: Image.rename
srcImg:
functionInvocationValue:
arguments:
input:
functionInvocationValue:
arguments:
image1:
valueReference: '1'
image2:
functionInvocationValue:
arguments:
value:
constantValue: 4046.86
functionName: Image.constant
functionName: Image.divide
names:
constantValue:
- acres
functionName: Image.rename
functionName: Image.addBands
reducer:
functionInvocationValue:
arguments: {}
functionName: Reducer.mean
scale:
constantValue: 1
functionName: Image.reduceRegion
'1':
functionInvocationValue:
arguments: {}
functionName: Image.pixelArea
2 changes: 2 additions & 0 deletions tests/test_Image/test_pixel_area.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
area: 0.000245
area_1: 9.9e-05
2 changes: 2 additions & 0 deletions tests/test_Image/test_pixel_area_rename.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
acres: 0.000245
ha: 9.9e-05
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ values:
valueReference: '24'
functionName: String.cat
'4':
constantValue: 1ed13eebdf434fc6a0b5b90d4c5d2f6b
constantValue: aa357a2c1ed94d89ace8fd9df72a194b
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ values:
valueReference: '24'
functionName: String.cat
'4':
constantValue: 6d1778b0807247609992e68ea882c8b3
constantValue: 1929b220a31045588235d28322edfffc
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ values:
valueReference: '24'
functionName: String.cat
'4':
constantValue: 57a15b9dd7f3477fb4d7cfad1bd14ece
constantValue: 7fc0194a21ec4f159ce49a4944c01c2c
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ values:
valueReference: '24'
functionName: String.cat
'4':
constantValue: 08eeb603579441949b1ecbaf29a58065
constantValue: 61765dc2248c4c26be316aa2436828d4
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ values:
valueReference: '24'
functionName: String.cat
'4':
constantValue: 70c747284efa428d91f24b7bc7c3f4f2
constantValue: da1cbb74f3334b598c512e29451dd8e8
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ values:
valueReference: '24'
functionName: String.cat
'4':
constantValue: 4c9645642d9c46cc81c4ce3cfcb0cb0c
constantValue: 559148b2c5634e518fabdd8b816b1580
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ values:
valueReference: '12'
functionName: String.cat
'4':
constantValue: 97e61c7a29e54ea69d4962b4f1052dec
constantValue: 7e31ed9377544e4daae5de452a856eff
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ values:
valueReference: '23'
functionName: String.cat
'4':
constantValue: 6f17dfd5be2c4403849fcda8e0d23985
constantValue: ff481e85e8204b0a8bb4f29556fe496f
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ values:
valueReference: '12'
functionName: String.cat
'4':
constantValue: 03eefcd116f0442c8896b4c42df4dbfd
constantValue: e9ff3a6e43be4c1a826b403e980d152b
'5':
functionInvocationValue:
arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ values:
functionName: Date.format
functionName: Element.set
'16':
constantValue: c9280f1d888e4856b98fa47c8f00ed81
constantValue: 7611f16ad1be428298bd6bfc6501488a
'17':
constantValue: system:time_start
'18':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ values:
functionName: Date.format
functionName: Element.set
'16':
constantValue: 97d382d899cf4a8ba1fbc811cdb2ff2d
constantValue: 6b6455876d2f4a718a88089238522ec8
'17':
constantValue: system:time_start
'18':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ values:
functionName: Date.format
functionName: Element.set
'16':
constantValue: e4c444e0325147748bdf755b077e296d
constantValue: 259e4b9943d948a290d6e00844977ed9
'17':
constantValue: system:time_start
'18':
Expand Down