mirror of
https://github.com/google/earthengine-api.git
synced 2025-12-08 19:26:12 +00:00
400 lines
13 KiB
Python
400 lines
13 KiB
Python
#!/usr/bin/env python3
|
|
"""Test for the ee.featurecollection module."""
|
|
|
|
import json
|
|
from typing import Any, Dict
|
|
from unittest import mock
|
|
|
|
import unittest
|
|
import ee
|
|
from ee import _cloud_api_utils
|
|
from ee import apitestcase
|
|
|
|
|
|
def make_expression_graph(
|
|
function_invocation_value: Dict[str, Any],
|
|
) -> Dict[str, Any]:
|
|
return {
|
|
'result': '0',
|
|
'values': {'0': {'functionInvocationValue': function_invocation_value}},
|
|
}
|
|
|
|
|
|
# ee.FeatureCollection(ee.Feature(None))
|
|
FEATURES_ONE = {
|
|
'functionInvocationValue': {
|
|
'functionName': 'Collection',
|
|
'arguments': {
|
|
'features': {
|
|
'arrayValue': {
|
|
'values': [{
|
|
'functionInvocationValue': {
|
|
'functionName': 'Feature',
|
|
'arguments': {},
|
|
}
|
|
}]
|
|
}
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
FEATURES_A = {
|
|
'functionInvocationValue': {
|
|
'functionName': 'Collection.loadTable',
|
|
'arguments': {'tableId': {'constantValue': 'a'}},
|
|
}
|
|
}
|
|
|
|
FEATURES_B = {
|
|
'functionInvocationValue': {
|
|
'functionName': 'Collection.loadTable',
|
|
'arguments': {'tableId': {'constantValue': 'b'}},
|
|
}
|
|
}
|
|
|
|
class FeatureCollectionTestCase(apitestcase.ApiTestCase):
|
|
|
|
def test_constructors(self):
|
|
"""Verifies that constructors understand valid parameters."""
|
|
from_id = ee.FeatureCollection('abcd')
|
|
self.assertEqual(
|
|
ee.ApiFunction.lookup('Collection.loadTable'), from_id.func)
|
|
self.assertEqual({'tableId': 'abcd'}, from_id.args)
|
|
|
|
from_id_and_geom_column = ee.FeatureCollection('abcd', 'xyz')
|
|
self.assertEqual(
|
|
ee.ApiFunction.lookup('Collection.loadTable'),
|
|
from_id_and_geom_column.func)
|
|
self.assertEqual({
|
|
'tableId': 'abcd',
|
|
'geometryColumn': 'xyz'
|
|
}, from_id_and_geom_column.args)
|
|
|
|
geometry = ee.Geometry.Point(1, 2)
|
|
feature = ee.Feature(geometry)
|
|
geo_json = {'type': 'FeatureCollection', 'features': [geometry.toGeoJSON()]}
|
|
from_geometries = ee.FeatureCollection([geometry])
|
|
from_single_geometry = ee.FeatureCollection(geometry)
|
|
from_features = ee.FeatureCollection([feature])
|
|
from_single_feature = ee.FeatureCollection(feature)
|
|
from_geo_json = ee.FeatureCollection(geo_json)
|
|
self.assertEqual(from_geometries, from_single_geometry)
|
|
self.assertEqual(from_geometries, from_features)
|
|
self.assertEqual(from_geometries, from_single_feature)
|
|
self.assertEqual(from_geometries, from_geo_json)
|
|
self.assertEqual(ee.ApiFunction.lookup('Collection'), from_geometries.func)
|
|
self.assertEqual({'features': [feature]}, from_geometries.args)
|
|
|
|
# Test a computed list object.
|
|
l = ee.List([feature]).slice(0)
|
|
from_list = ee.FeatureCollection(l)
|
|
self.assertEqual({'features': l}, from_list.args)
|
|
|
|
from_computed_object = ee.FeatureCollection(
|
|
ee.ComputedObject(None, {'x': 'y'}))
|
|
self.assertEqual({'x': 'y'}, from_computed_object.args)
|
|
|
|
def test_get_map_id(self):
|
|
"""Verifies that getMap() uses Collection.draw to draw."""
|
|
collection = ee.FeatureCollection('test5')
|
|
mapid = collection.getMapId({'color': 'ABCDEF'})
|
|
manual = ee.ApiFunction.call_('Collection.draw', collection, 'ABCDEF')
|
|
|
|
self.assertEqual('fakeMapId', mapid['mapid'])
|
|
self.assertEqual(manual, mapid['image'])
|
|
|
|
def test_download(self):
|
|
"""Verifies that Download ID and URL generation."""
|
|
ee.FeatureCollection('test7').getDownloadURL()
|
|
|
|
self.assertEqual('/table', self.last_table_call['url'])
|
|
self.assertEqual(ee.FeatureCollection('test7').serialize(),
|
|
self.last_table_call['data']['table'].serialize())
|
|
|
|
ee.FeatureCollection('test8').getDownloadURL(
|
|
'json', 'bar, baz', 'qux')
|
|
self.assertEqual(
|
|
ee.FeatureCollection('test8').serialize(),
|
|
self.last_table_call['data']['table'].serialize())
|
|
self.assertEqual('JSON', self.last_table_call['data']['format'])
|
|
self.assertEqual('bar, baz', self.last_table_call['data']['selectors'])
|
|
self.assertEqual('qux', self.last_table_call['data']['filename'])
|
|
|
|
self.assertEqual(
|
|
ee.FeatureCollection('test7').getDownloadUrl('csv'),
|
|
ee.FeatureCollection('test7').getDownloadURL('csv'))
|
|
|
|
def test_download_table_with_cloud_api(self):
|
|
cloud_api_resource = mock.MagicMock()
|
|
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
create_table_response = {'name': 'table_name'}
|
|
cloud_api_resource.projects().tables().create().execute.return_value = (
|
|
create_table_response)
|
|
fc = ee.FeatureCollection([ee.Feature(None, {'foo': 'bar'})])
|
|
result = ee.data.getTableDownloadId({
|
|
'table': fc, 'selectors': 'foo', 'format': 'CSV',
|
|
})
|
|
url = ee.data.makeTableDownloadUrl(result)
|
|
|
|
self.assertDictEqual(result, {'docid': '5', 'token': '6'})
|
|
self.assertEqual(url, f'/{_cloud_api_utils.VERSION}/5:getFeatures')
|
|
|
|
def test_select(self):
|
|
def equals(c1, c2):
|
|
self.assertEqual(c1.serialize(), c2.serialize())
|
|
|
|
fc = ee.FeatureCollection(ee.Feature(ee.Geometry.Point(0, 0), {'a': 5}))
|
|
equals(fc.select('a'), fc.select(['a']))
|
|
equals(fc.select('a', 'b'), fc.select(['a', 'b']))
|
|
equals(fc.select('a', 'b', 'c'), fc.select(['a', 'b', 'c']))
|
|
equals(fc.select('a', 'b', 'c', 'd'), fc.select(['a', 'b', 'c', 'd']))
|
|
|
|
equals(fc.select(['a']), fc.select(['a'], None, True))
|
|
equals(fc.select(['a'], None, False),
|
|
fc.select(propertySelectors=['a'], retainGeometry=False))
|
|
|
|
def test_init_opt_column(self):
|
|
result = ee.FeatureCollection(
|
|
args='[{}]', opt_column='a-column'
|
|
).serialize()
|
|
self.assertIn('"geometryColumn": {"constantValue": "a-column"}', result)
|
|
|
|
def test_classify(self):
|
|
output_name = 'output name'
|
|
expect = make_expression_graph({
|
|
'arguments': {
|
|
'features': FEATURES_ONE,
|
|
'classifier': {
|
|
'functionInvocationValue': {
|
|
'arguments': {},
|
|
'functionName': 'Classifier.smileNaiveBayes',
|
|
}
|
|
},
|
|
'outputName': {'constantValue': output_name},
|
|
},
|
|
'functionName': 'FeatureCollection.classify',
|
|
})
|
|
classifier = ee.Classifier.smileNaiveBayes()
|
|
expression = ee.FeatureCollection(ee.Feature(None)).classify(
|
|
classifier, output_name
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
expression = ee.FeatureCollection(ee.Feature(None)).classify(
|
|
classifier=classifier, outputName=output_name
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
def test_cluster(self):
|
|
output_name = 'output name'
|
|
expect = make_expression_graph({
|
|
'arguments': {
|
|
'features': FEATURES_ONE,
|
|
'clusterer': {
|
|
'functionInvocationValue': {
|
|
'functionName': 'Clusterer.wekaCobweb',
|
|
'arguments': {},
|
|
}
|
|
},
|
|
'outputName': {'constantValue': output_name},
|
|
},
|
|
'functionName': 'FeatureCollection.cluster',
|
|
})
|
|
clusterer = ee.Clusterer.wekaCobweb()
|
|
expression = ee.FeatureCollection(ee.Feature(None)).cluster(
|
|
clusterer, output_name
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
expression = ee.FeatureCollection(ee.Feature(None)).cluster(
|
|
clusterer=clusterer, outputName=output_name
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
def test_copy_properties(self):
|
|
source = ee.FeatureCollection('b')
|
|
properties = ['c', 'd']
|
|
exclude = ['e', 'f']
|
|
expect = make_expression_graph({
|
|
'arguments': {
|
|
'destination': FEATURES_A,
|
|
'source': FEATURES_B,
|
|
'properties': {'constantValue': properties},
|
|
'exclude': {'constantValue': exclude},
|
|
},
|
|
# Note this is Element rather than FeatureCollection
|
|
'functionName': 'Element.copyProperties',
|
|
})
|
|
expression = ee.FeatureCollection('a').copyProperties(
|
|
source, properties, exclude
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
expression = ee.FeatureCollection('a').copyProperties(
|
|
source=source, properties=properties, exclude=exclude
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
def test_inverse_distance(self):
|
|
a_range = 2
|
|
property_name = 'property name'
|
|
mean = 3
|
|
std_dev = 4
|
|
gamma = 5
|
|
reducer = ee.Reducer.max()
|
|
expect = make_expression_graph({
|
|
'arguments': {
|
|
'collection': FEATURES_ONE,
|
|
'range': {'constantValue': a_range},
|
|
'propertyName': {'constantValue': property_name},
|
|
'mean': {'constantValue': mean},
|
|
'stdDev': {'constantValue': std_dev},
|
|
'gamma': {'constantValue': gamma},
|
|
'reducer': {
|
|
'functionInvocationValue': {
|
|
'functionName': 'Reducer.max',
|
|
'arguments': {},
|
|
}
|
|
},
|
|
},
|
|
'functionName': 'FeatureCollection.inverseDistance',
|
|
})
|
|
expression = ee.FeatureCollection(ee.Feature(None)).inverseDistance(
|
|
a_range, property_name, mean, std_dev, gamma, reducer
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
expression = ee.FeatureCollection(ee.Feature(None)).inverseDistance(
|
|
range=a_range,
|
|
propertyName=property_name,
|
|
mean=mean,
|
|
stdDev=std_dev,
|
|
gamma=gamma,
|
|
reducer=reducer,
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
def test_kriging(self):
|
|
property_name = 'property name'
|
|
shape = 'exponential'
|
|
range = 1
|
|
sill = 2
|
|
nugget = 3
|
|
max_distance = 4
|
|
reducer = ee.Reducer.max()
|
|
expect = make_expression_graph({
|
|
'arguments': {
|
|
'collection': FEATURES_ONE,
|
|
'propertyName': {'constantValue': property_name},
|
|
'shape': {'constantValue': shape},
|
|
'range': {'constantValue': range},
|
|
'sill': {'constantValue': sill},
|
|
'nugget': {'constantValue': nugget},
|
|
'maxDistance': {'constantValue': max_distance},
|
|
'reducer': {
|
|
'functionInvocationValue': {
|
|
'functionName': 'Reducer.max',
|
|
'arguments': {},
|
|
}
|
|
},
|
|
},
|
|
'functionName': 'FeatureCollection.kriging',
|
|
})
|
|
expression = ee.FeatureCollection(ee.Feature(None)).kriging(
|
|
property_name, shape, range, sill, nugget, max_distance, reducer
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
expression = ee.FeatureCollection(ee.Feature(None)).kriging(
|
|
propertyName=property_name,
|
|
shape=shape,
|
|
range=range,
|
|
sill=sill,
|
|
nugget=nugget,
|
|
maxDistance=max_distance,
|
|
reducer=reducer,
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
def test_make_array(self):
|
|
properties = ['a', 'b']
|
|
name = 'name string'
|
|
expect = make_expression_graph({
|
|
'arguments': {
|
|
'collection': FEATURES_ONE,
|
|
'properties': {'constantValue': properties},
|
|
'name': {'constantValue': name},
|
|
},
|
|
'functionName': 'FeatureCollection.makeArray',
|
|
})
|
|
expression = ee.FeatureCollection(ee.Feature(None)).makeArray(
|
|
properties, name
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
expression = ee.FeatureCollection(ee.Feature(None)).makeArray(
|
|
properties=properties, name=name
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
def test_random_points(self):
|
|
region = ee.Geometry.Point([1, 2])
|
|
points = 1
|
|
seed = 2
|
|
max_error_num = 3
|
|
max_error = ee.ErrorMargin(max_error_num)
|
|
expect = make_expression_graph({
|
|
'arguments': {
|
|
'region': {
|
|
'functionInvocationValue': {
|
|
'functionName': 'GeometryConstructors.Point',
|
|
'arguments': {'coordinates': {'constantValue': [1, 2]}},
|
|
}
|
|
},
|
|
'points': {'constantValue': points},
|
|
'seed': {'constantValue': seed},
|
|
'maxError': {
|
|
'functionInvocationValue': {
|
|
'functionName': 'ErrorMargin',
|
|
'arguments': {'value': {'constantValue': max_error_num}},
|
|
}
|
|
},
|
|
},
|
|
'functionName': 'FeatureCollection.randomPoints',
|
|
})
|
|
|
|
expression = ee.FeatureCollection.randomPoints(
|
|
region, points, seed, max_error_num
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
expression = ee.FeatureCollection.randomPoints(
|
|
region, points, seed, max_error
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
expression = ee.FeatureCollection(ee.Feature(None)).randomPoints(
|
|
region=region, points=points, seed=seed, maxError=max_error
|
|
)
|
|
result = json.loads(expression.serialize())
|
|
self.assertEqual(expect, result)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|