mirror of
https://github.com/google/earthengine-api.git
synced 2025-12-08 19:26:12 +00:00
179 lines
6.2 KiB
Python
179 lines
6.2 KiB
Python
#!/usr/bin/env python
|
|
"""Test for the ee.collection module."""
|
|
|
|
|
|
|
|
import datetime
|
|
import re
|
|
|
|
import unittest
|
|
|
|
import ee
|
|
from ee import apitestcase
|
|
|
|
|
|
class CollectionTestCase(apitestcase.ApiTestCase):
|
|
|
|
def testSortAndLimit(self):
|
|
"""Verifies the behavior of the sort() and limit() methods."""
|
|
collection = ee.Collection(ee.Function(), {})
|
|
|
|
limited = collection.limit(10)
|
|
self.assertEqual(ee.ApiFunction.lookup('Collection.limit'), limited.func)
|
|
self.assertEqual({
|
|
'collection': collection,
|
|
'limit': ee.Number(10)
|
|
}, limited.args)
|
|
|
|
sorted_collection = collection.sort('bar', True)
|
|
self.assertEqual(
|
|
ee.ApiFunction.lookup('Collection.limit'), sorted_collection.func)
|
|
self.assertEqual({
|
|
'collection': collection,
|
|
'key': ee.String('bar'),
|
|
'ascending': True
|
|
}, sorted_collection.args)
|
|
|
|
reverse_sorted_collection = collection.sort('bar', False)
|
|
self.assertEqual(
|
|
ee.ApiFunction.lookup('Collection.limit'),
|
|
reverse_sorted_collection.func)
|
|
self.assertEqual({
|
|
'collection': collection,
|
|
'key': ee.String('bar'),
|
|
'ascending': False
|
|
}, reverse_sorted_collection.args)
|
|
|
|
def testFilter(self):
|
|
"""Verifies the behavior of filter() method."""
|
|
collection = ee.Collection(ee.Function(), {})
|
|
|
|
# We don't allow empty filters.
|
|
self.assertRaises(Exception, collection.filter)
|
|
|
|
filtered = collection.filter(ee.Filter.eq('foo', 1))
|
|
self.assertEqual(ee.ApiFunction.lookup('Collection.filter'), filtered.func)
|
|
self.assertEqual({
|
|
'collection': collection,
|
|
'filter': ee.Filter.eq('foo', 1)
|
|
}, filtered.args)
|
|
self.assertIsInstance(filtered, ee.Collection)
|
|
|
|
def testFilterShortcuts(self):
|
|
"""Verifies the behavior of the various filtering shortcut methods."""
|
|
collection = ee.Collection(ee.Function(), {})
|
|
geom = {'type': 'Polygon', 'coordinates': [[[1, 2], [3, 4]]]}
|
|
d1 = datetime.datetime.strptime('1/1/2000', '%m/%d/%Y')
|
|
d2 = datetime.datetime.strptime('1/1/2001', '%m/%d/%Y')
|
|
|
|
self.assertEqual(
|
|
collection.filter(ee.Filter.geometry(geom)),
|
|
collection.filterBounds(geom))
|
|
self.assertEqual(
|
|
collection.filter(ee.Filter.date(d1)), collection.filterDate(d1))
|
|
self.assertEqual(
|
|
collection.filter(ee.Filter.date(d1, d2)), collection.filterDate(
|
|
d1, d2))
|
|
self.assertEqual(
|
|
collection.filter(ee.Filter.eq('foo', 13)),
|
|
collection.filterMetadata('foo', 'equals', 13))
|
|
|
|
def testMapping(self):
|
|
"""Verifies the behavior of the map() method."""
|
|
collection = ee.ImageCollection('foo')
|
|
algorithm = lambda img: img.select('bar')
|
|
mapped = collection.map(algorithm)
|
|
|
|
self.assertIsInstance(mapped, ee.ImageCollection)
|
|
self.assertEqual(ee.ApiFunction.lookup('Collection.map'), mapped.func)
|
|
self.assertEqual(collection, mapped.args['collection'])
|
|
|
|
# Need to do a serialized comparison for the function body because
|
|
# variables returned from CustomFunction.variable() do not implement
|
|
# __eq__.
|
|
sig = {
|
|
'returns': 'Image',
|
|
'args': [{'name': '_MAPPING_VAR_0_0', 'type': 'Image'}]
|
|
}
|
|
expected_function = ee.CustomFunction(sig, algorithm)
|
|
self.assertEqual(expected_function.serialize(),
|
|
mapped.args['baseAlgorithm'].serialize())
|
|
|
|
def testNestedMapping(self):
|
|
"""Verifies that nested map() calls produce distinct variables."""
|
|
collection = ee.FeatureCollection('foo')
|
|
result = collection.map(lambda x: collection.map(lambda y: [x, y]))
|
|
|
|
# Verify the signatures.
|
|
self.assertEqual('_MAPPING_VAR_1_0',
|
|
result.args['baseAlgorithm']._signature['args'][0]['name'])
|
|
inner_result = result.args['baseAlgorithm']._body
|
|
self.assertEqual(
|
|
'_MAPPING_VAR_0_0',
|
|
inner_result.args['baseAlgorithm']._signature['args'][0]['name'])
|
|
|
|
# Verify the references.
|
|
self.assertEqual('_MAPPING_VAR_1_0',
|
|
inner_result.args['baseAlgorithm']._body[0].varName)
|
|
self.assertEqual('_MAPPING_VAR_0_0',
|
|
inner_result.args['baseAlgorithm']._body[1].varName)
|
|
|
|
def testIteration(self):
|
|
"""Verifies the behavior of the iterate() method."""
|
|
collection = ee.ImageCollection('foo')
|
|
first = ee.Image(0)
|
|
algorithm = lambda img, prev: img.addBands(ee.Image(prev))
|
|
result = collection.iterate(algorithm, first)
|
|
|
|
self.assertEqual(ee.ApiFunction.lookup('Collection.iterate'), result.func)
|
|
self.assertEqual(collection, result.args['collection'])
|
|
self.assertEqual(first, result.args['first'])
|
|
|
|
# Need to do a serialized comparison for the function body because
|
|
# variables returned from CustomFunction.variable() do not implement
|
|
# __eq__.
|
|
sig = {
|
|
'returns': 'Object',
|
|
'args': [
|
|
{'name': '_MAPPING_VAR_0_0', 'type': 'Image'},
|
|
{'name': '_MAPPING_VAR_0_1', 'type': 'Object'}
|
|
]
|
|
}
|
|
expected_function = ee.CustomFunction(sig, algorithm)
|
|
self.assertEqual(expected_function.serialize(),
|
|
result.args['function'].serialize())
|
|
|
|
def testNestedFunctions(self):
|
|
"""Verifies that nested function calls produce distinct variables."""
|
|
fc = ee.FeatureCollection('fc')
|
|
def f0(feat):
|
|
return ee.Dictionary(feat.get('get')).map(f1)
|
|
def f1(k1, v1):
|
|
def f2(k2, v2):
|
|
def f3(k3, v3):
|
|
def f4(k4):
|
|
return (ee.Number(1).add(ee.Number(k1)).add(ee.Number(k2))
|
|
.add(ee.Number(k3)).add(ee.Number(k4)))
|
|
return ee.Dictionary(v3).map(f4)
|
|
return ee.Dictionary(v2).map(f3)
|
|
return ee.Dictionary(v1).map(f2)
|
|
mapped_vars = re.findall(r'\d_\d', fc.map(f0).serialize())
|
|
self.assertEqual(
|
|
'0_0, 1_0, 1_1, 2_0, 2_1, 3_0, 3_1, 4_0',
|
|
', '.join(sorted(set(mapped_vars))))
|
|
|
|
def testUnboundArguments(self):
|
|
fc = ee.FeatureCollection('fc')
|
|
with self.assertRaisesRegex(
|
|
Exception, 'User-defined methods must return a value'):
|
|
fc.map(lambda x: None)
|
|
|
|
with self.assertRaisesRegex(
|
|
Exception,
|
|
'A mapped function\'s arguments cannot be used in client-side operations'
|
|
):
|
|
fc.map(lambda x: x.serialize())
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|