feature.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #!/usr/bin/env python
  2. """An object representing EE Features."""
  3. # Using lowercase function naming to match the JavaScript names.
  4. # pylint: disable=g-bad-name
  5. from . import apifunction
  6. from . import computedobject
  7. from . import ee_exception
  8. from . import element
  9. from . import geometry
  10. class Feature(element.Element):
  11. """An object representing EE Features."""
  12. _initialized = False
  13. # Tell pytype to not complain about dynamic attributes.
  14. _HAS_DYNAMIC_ATTRIBUTES = True
  15. def __init__(self, geom, opt_properties=None):
  16. """Creates a feature a geometry or computed object.
  17. Features can be constructed from one of the following arguments plus an
  18. optional dictionary of properties:
  19. 1) An ee.Geometry.
  20. 2) A GeoJSON Geometry.
  21. 3) A GeoJSON Feature.
  22. 4) A computed object - reinterpreted as a geometry if properties
  23. are specified, and as a feature if they aren't.
  24. Args:
  25. geom: A geometry or feature.
  26. opt_properties: A dictionary of metadata properties. If the first
  27. parameter is a Feature (instead of a geometry), this is unused.
  28. Raises:
  29. EEException: if the given geometry isn't valid.
  30. """
  31. if isinstance(geom, Feature):
  32. if opt_properties is not None:
  33. raise ee_exception.EEException(
  34. 'Can\'t create Feature out of a Feature and properties.')
  35. # A pre-constructed Feature. Copy.
  36. super(Feature, self).__init__(geom.func, geom.args)
  37. return
  38. self.initialize()
  39. feature_constructor = apifunction.ApiFunction.lookup('Feature')
  40. if geom is None or isinstance(geom, geometry.Geometry):
  41. # A geometry object.
  42. super(Feature, self).__init__(feature_constructor, {
  43. 'geometry': geom,
  44. 'metadata': opt_properties or None
  45. })
  46. elif isinstance(geom, computedobject.ComputedObject):
  47. # A custom object to reinterpret as a Feature.
  48. super(Feature, self).__init__(geom.func, geom.args, geom.varName)
  49. elif isinstance(geom, dict) and geom.get('type') == 'Feature':
  50. properties = geom.get('properties', {})
  51. if 'id' in geom:
  52. if 'system:index' in properties:
  53. raise ee_exception.EEException(
  54. 'Can\'t specify both "id" and "system:index".')
  55. properties = properties.copy()
  56. properties['system:index'] = geom['id']
  57. # Try to convert a GeoJSON Feature.
  58. super(Feature, self).__init__(feature_constructor, {
  59. 'geometry': geometry.Geometry(geom.get('geometry', None)),
  60. 'metadata': properties
  61. })
  62. else:
  63. # Try to convert the geometry arg to a Geometry, in the hopes of it
  64. # turning out to be GeoJSON.
  65. super(Feature, self).__init__(feature_constructor, {
  66. 'geometry': geometry.Geometry(geom),
  67. 'metadata': opt_properties or None
  68. })
  69. @classmethod
  70. def initialize(cls):
  71. """Imports API functions to this class."""
  72. if not cls._initialized:
  73. apifunction.ApiFunction.importApi(cls, 'Feature', 'Feature')
  74. cls._initialized = True
  75. @classmethod
  76. def reset(cls):
  77. """Removes imported API functions from this class."""
  78. apifunction.ApiFunction.clearApi(cls)
  79. cls._initialized = False
  80. def getMapId(self, vis_params=None):
  81. """Fetch and return a map id and token, suitable for use in a Map overlay.
  82. Args:
  83. vis_params: The visualization parameters. Currently only one parameter,
  84. 'color', containing a hex RGB color string is allowed.
  85. Returns:
  86. A map ID dictionary as described in ee.data.getMapId, including an
  87. additional 'image' field containing Collection.draw image wrapping a
  88. FeatureCollection containing this feature.
  89. """
  90. # Create a collection containing this one feature and render it.
  91. collection = apifunction.ApiFunction.call_('Collection', [self])
  92. return collection.getMapId(vis_params)
  93. @staticmethod
  94. def name():
  95. return 'Feature'