earthengine-api/python/ee/featurecollection.py
Google Earth Engine Authors 8fee1d9e26 v0.1.386
PiperOrigin-RevId: 597577360
2024-01-18 18:09:09 +00:00

220 lines
7.0 KiB
Python

"""Representation of an Earth Engine FeatureCollection."""
# Using lowercase function naming to match the JavaScript names.
# pylint: disable=g-bad-name
from __future__ import annotations
from typing import Any, Dict, List, Optional, Type, Union
from ee import _utils
from ee import apifunction
from ee import collection
from ee import computedobject
from ee import data
from ee import deprecation
from ee import ee_exception
from ee import ee_list
from ee import ee_types
from ee import feature
from ee import geometry
class FeatureCollection(collection.Collection):
"""A representation of a FeatureCollection."""
_initialized = False
# Tell pytype to not complain about dynamic attributes.
_HAS_DYNAMIC_ATTRIBUTES = True
@_utils.accept_opt_prefix('opt_column')
def __init__(
self,
args: Optional[
Union[
Dict[str, Any],
List[Any],
str,
feature.Feature,
geometry.Geometry,
computedobject.ComputedObject,
]
],
column: Optional[Any] = None,
):
"""Constructs a collection features.
Args:
args: constructor argument. One of: 1) A string - assumed to be the name
of a collection. 2) A geometry. 3) A feature. 4) An array of features.
5) A GeoJSON FeatureCollection. 6) A computed object - reinterpreted as
a collection.
column: The name of the geometry column to use. Only useful with the
string constructor.
Raises:
EEException: if passed something other than the above.
"""
self.initialize()
# Wrap geometries with features.
if isinstance(args, geometry.Geometry):
args = feature.Feature(args)
# Wrap single features in an array.
if isinstance(args, feature.Feature):
args = [args]
if ee_types.isString(args):
# An ID.
actual_args = {'tableId': args}
if column:
actual_args['geometryColumn'] = column
super().__init__(
apifunction.ApiFunction.lookup('Collection.loadTable'), actual_args)
elif isinstance(args, (list, tuple)):
# A list of features.
super().__init__(
apifunction.ApiFunction.lookup('Collection'), {
'features': [feature.Feature(i) for i in args]
})
elif isinstance(args, ee_list.List):
# A computed list of features.
super().__init__(
apifunction.ApiFunction.lookup('Collection'), {
'features': args
})
elif isinstance(args, dict) and args.get('type') == self.name():
# A GeoJSON FeatureCollection
super().__init__(
apifunction.ApiFunction.lookup('Collection'),
{'features': [feature.Feature(i) for i in args.get('features', [])]})
elif isinstance(args, computedobject.ComputedObject):
# A custom object to reinterpret as a FeatureCollection.
super().__init__(args.func, args.args, args.varName)
else:
raise ee_exception.EEException(
'Unrecognized argument type to convert to a FeatureCollection: %s' %
args)
@classmethod
def initialize(cls) -> None:
"""Imports API functions to this class."""
if not cls._initialized:
super().initialize()
apifunction.ApiFunction.importApi(cls, cls.name(), cls.name())
cls._initialized = True
@classmethod
def reset(cls) -> None:
"""Removes imported API functions from this class."""
apifunction.ApiFunction.clearApi(cls)
cls._initialized = False
def getMapId(
self, vis_params: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
"""Fetch and return a map id and token, suitable for use in a Map overlay.
Args:
vis_params: The visualization parameters. Currently only one parameter,
'color', containing a hex RGB color string is allowed.
Returns:
A map ID dictionary as described in ee.data.getMapId, including an
additional 'image' field containing Collection.draw image wrapping a
FeatureCollection containing this feature.
"""
painted = apifunction.ApiFunction.apply_('Collection.draw', {
'collection': self,
'color': (vis_params or {}).get('color', '000000')
})
return painted.getMapId({})
def getDownloadURL(
self,
filetype: Optional[str] = None,
selectors: Optional[Any] = None,
filename: Optional[str] = None,
) -> str:
"""Gets a download URL.
When the URL is accessed, the FeatureCollection is downloaded in one of
several formats.
Args:
filetype: The format of download, one of: "csv", "json", "geojson", "kml",
"kmz" ("json" outputs GeoJSON). If unspecified, defaults to "csv".
selectors: Feature property names used to select the attributes to be
downloaded. If unspecified, all properties are included.
filename: Name of the file to be downloaded; extension is appended by
default. If unspecified, defaults to "table".
Returns:
A URL to download this FeatureCollection.
"""
request = {}
request['table'] = self
if filetype is not None:
request['format'] = filetype.upper()
if filename is not None:
request['filename'] = filename
if selectors is not None:
if isinstance(selectors, (list, tuple)):
selectors = ','.join(selectors)
request['selectors'] = selectors
return data.makeTableDownloadUrl(data.getTableDownloadId(request))
# Deprecated spelling to match the JS library.
getDownloadUrl = deprecation.Deprecated('Use getDownloadURL().')(
getDownloadURL)
# TODO(user): How to handle type annotations for
# feature_collection.select('a', 'b', 'c')?
# pylint: disable-next=keyword-arg-before-vararg
def select(
self,
propertySelectors: Any,
newProperties: Optional[Any] = None,
retainGeometry: Union[bool, str] = True,
*args,
) -> FeatureCollection:
"""Select properties from each feature in a collection.
Args:
propertySelectors: An array of names or regexes specifying the properties
to select.
newProperties: An array of strings specifying the new names for the
selected properties. If supplied, the length must match the number
of properties selected.
retainGeometry: A boolean. When false, the result will have no geometry.
*args: Selector elements as varargs.
Returns:
The feature collection with selected properties.
"""
if len(args) or ee_types.isString(propertySelectors):
args = list(args)
if not isinstance(retainGeometry, bool):
args.insert(0, retainGeometry)
if newProperties is not None:
args.insert(0, newProperties)
args.insert(0, propertySelectors)
return self.map(lambda feat: feat.select(args, None, True))
else:
return self.map(
# pylint: disable-next=g-long-lambda
lambda feat: feat.select(
propertySelectors, newProperties, retainGeometry
)
)
@staticmethod
def name() -> str:
return 'FeatureCollection'
@staticmethod
def elementType() -> Type[feature.Feature]:
return feature.Feature