def __init__(self, args=None, version=None): """Constructs an Earth Engine image. Args: args: This constructor accepts a variety of arguments: - A string - an EarthEngine asset id, - A string and a number - an EarthEngine asset id and version, - A number - creates a constant image, - An EEArray - creates a constant array image, - A list - creates an image out of each element of the array and combines them into a single image, - An ee.Image - returns the argument, - Nothing - results in an empty transparent image. version: An optional asset version. Raises: EEException: if passed something other than the above. """ self.initialize() if version is not None: if ee_types.isString(args) and ee_types.isNumber(version): # An ID and version. super(Image, self).__init__( apifunction.ApiFunction.lookup('Image.load'), {'id': args, 'version': version}) else: raise ee_exception.EEException( 'If version is specified, the arg to Image() must be a string. ' 'Received: %s' % (args,)) return if ee_types.isNumber(args): # A constant image. super(Image, self).__init__( apifunction.ApiFunction.lookup('Image.constant'), {'value': args}) elif ee_types.isString(args): # An ID. super(Image, self).__init__( apifunction.ApiFunction.lookup('Image.load'), {'id': args}) elif isinstance(args, (list, tuple)): # Make an image out of each element. image = Image.combine_([Image(i) for i in args]) super(Image, self).__init__(image.func, image.args) elif isinstance(args, computedobject.ComputedObject): if args.name() == 'Array': # A constant array image. super(Image, self).__init__( apifunction.ApiFunction.lookup('Image.constant'), {'value': args}) else: # A custom object to reinterpret as an Image. super(Image, self).__init__(args.func, args.args, args.varName) elif args is None: super(Image, self).__init__( apifunction.ApiFunction.lookup('Image.mask'), {'image': Image(0), 'mask': Image(0)}) else: raise ee_exception.EEException( 'Unrecognized argument type to convert to an Image: %s' % args)
def select(self, opt_selectors=None, opt_names=None, *args): """Selects bands from an image. Can be called in one of two ways: - Passed any number of non-list arguments. All of these will be interpreted as band selectors. These can be band names, regexes, or numeric indices. E.g. selected = image.select('a', 'b', 3, 'd'); - Passed two lists. The first will be used as band selectors and the second as new names for the selected bands. The number of new names must match the number of selected bands. E.g. selected = image.select(['a', 4], ['newA', 'newB']); Args: opt_selectors: An array of names, regexes or numeric indices specifying the bands to select. opt_names: An array of strings specifying the new names for the selected bands. *args: Selector elements as varargs. Returns: An image with the selected bands. """ if opt_selectors is not None: args = list(args) if opt_names is not None: args.insert(0, opt_names) args.insert(0, opt_selectors) algorithm_args = { 'input': self, 'bandSelectors': args[0] if args else [], } if args: # If the user didn't pass an array as the first argument, assume # that everything in the arguments array is actually a selector. if (len(args) > 2 or ee_types.isString(args[0]) or ee_types.isNumber(args[0])): # Varargs inputs. selectors = args # Verify we didn't get anything unexpected. for selector in selectors: if (not ee_types.isString(selector) and not ee_types.isNumber(selector) and not isinstance(selector, computedobject.ComputedObject)): raise ee_exception.EEException( 'Illegal argument to select(): ' + selector) algorithm_args['bandSelectors'] = selectors elif len(args) > 1: algorithm_args['newNames'] = args[1] return apifunction.ApiFunction.apply_('Image.select', algorithm_args)
def select(self, selectors, opt_names=None, *args): """Select bands from an image. This is an override to the normal Image.select function to allow varargs specification of selectors. Args: selectors: An array of names, regexes or numeric indices specifying the bands to select. opt_names: An array of strings specifying the new names for the selected bands. If supplied, the length must match the number of bands selected. *args: Selector elements as varargs. Returns: An image with the selected bands. """ arguments = { 'input': self, 'bandSelectors': selectors, } if (isinstance(selectors, (basestring, int, long)) or ee_types.isString(selectors) or ee_types.isNumber(selectors)): # Varargs inputs. selectors = [selectors] if opt_names is not None: selectors.append(opt_names) opt_names = None selectors.extend(args) arguments['bandSelectors'] = selectors if opt_names: arguments['newNames'] = opt_names return apifunction.ApiFunction.apply_('Image.select', arguments)
def __init__(self, args, opt_column=None): """Constructs a collection features. Args: args: constructor argument. One of: 1) A string - assumed to be the name of a collection. 2) A number - assumed to be the ID of a Fusion Table. 3) A geometry. 4) A feature. 5) An array of features. 6) A computed object - reinterpreted as a collection. opt_column: The name of the geometry column to use. Only useful with the string or number constructor arguments. 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.isNumber(args) or ee_types.isString(args): # An ID. actual_args = {'tableId': args} if opt_column: actual_args['geometryColumn'] = opt_column super(FeatureCollection, self).__init__( apifunction.ApiFunction.lookup('Collection.loadTable'), actual_args) elif isinstance(args, (list, tuple)): # A list of features. super(FeatureCollection, self).__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(FeatureCollection, self).__init__( apifunction.ApiFunction.lookup('Collection'), { 'features': args }) elif isinstance(args, computedobject.ComputedObject): # A custom object to reinterpret as a FeatureCollection. super(FeatureCollection, self).__init__( args.func, args.args, args.varName) else: raise ee_exception.EEException( 'Unrecognized argument type to convert to a FeatureCollection: %s' % args)
def __init__(self, args, opt_column=None): """Constructs a collection features. Args: args: constructor argument. One of: 1) A string - assumed to be the name of a collection. 2) A number - assumed to be the ID of a Fusion Table. 3) A geometry. 4) A feature. 5) An array of features. 6) A computed object - reinterpreted as a collection. opt_column: The name of the geometry column to use. Only useful with the string or number constructor arguments. 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.isNumber(args) or ee_types.isString(args): # An ID. actual_args = {'tableId': args} if opt_column: actual_args['geometryColumn'] = opt_column super(FeatureCollection, self).__init__( apifunction.ApiFunction.lookup('Collection.loadTable'), actual_args) elif isinstance(args, (list, tuple)): # A list of features. super(FeatureCollection, self).__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(FeatureCollection, self).__init__(apifunction.ApiFunction.lookup('Collection'), {'features': args}) elif isinstance(args, computedobject.ComputedObject): # A custom object to reinterpret as a FeatureCollection. super(FeatureCollection, self).__init__(args.func, args.args, args.varName) else: raise ee_exception.EEException( 'Unrecognized argument type to convert to a FeatureCollection: %s' % args)
def __init__(self, date, opt_tz=None): """Construct a date. This sends all inputs (except another Date) through the Date function. This constuctor accepts the following args: 1) A bare date. 2) An ISO string 3) A integer number of milliseconds since the epoch. 4) A ComputedObject. Args: date: The date to wrap. opt_tz: An optional timezone, only useable with a string date. """ self.initialize() func = apifunction.ApiFunction('Date') args = None varName = None if isinstance(date, datetime.datetime): args = { 'value': math.floor(serializer.DatetimeToMicroseconds(date) / 1000) } elif types.isNumber(date): args = {'value': date} elif isinstance(date, basestring): args = {'value': date} if opt_tz: if isinstance(opt_tz, basestring): args['timeZone'] = opt_tz else: raise ee_exception.EEException( 'Invalid argument specified for ee.Date(..., opt_tz): %s' % date) elif isinstance(date, computedobject.ComputedObject): if date.func and date.func.getSignature()['returns'] == 'Date': # If it's a call that's already returning a Date, just cast. func = date.func args = date.args varName = date.varName else: args = {'value': date} else: raise ee_exception.EEException( 'Invalid argument specified for ee.Date(): %s' % date) super(Date, self).__init__(func, args, varName)
def _parseArgs(ctor_name, depth, args): """Parses arguments into a GeoJSON dictionary or a ComputedObject. Args: ctor_name: The name of the constructor to use. depth: The nesting depth at which points are found. args: The array of values to test. Returns: If the arguments are simple, a GeoJSON object describing the geometry. Otherwise a ComputedObject calling the appropriate constructor. """ result = {} keys = ['coordinates', 'crs', 'geodesic', 'maxError', 'evenOdd'] if all(ee_types.isNumber(i) for i in args): # All numbers, so convert them to a true array. result['coordinates'] = args else: # Parse parameters by position. if len(args) > len(keys): raise ee_exception.EEException( 'Geometry constructor given extra arguments.') for key, arg in zip(keys, args): if arg is not None: result[key] = arg # Standardize the coordinates and test if they are simple enough for # client-side initialization. if (Geometry._hasServerValue(result['coordinates']) or result.get('crs') is not None or result.get('geodesic') is not None or result.get('maxError') is not None): # Some arguments cannot be handled in the client, so make a server call. # Note we don't declare a default evenOdd value, so the server can infer # a default based on the projection. server_name = 'GeometryConstructors.' + ctor_name return apifunction.ApiFunction.lookup(server_name).apply(result) else: # Everything can be handled here, so check the depth and init this object. result['type'] = ctor_name result['coordinates'] = Geometry._fixDepth(depth, result['coordinates']) # Enable evenOdd by default for any kind of polygon. if ('evenOdd' not in result and ctor_name in ['Polygon', 'Rectangle', 'MultiPolygon']): result['evenOdd'] = True return result
def _parseArgs(ctor_name, depth, args): """Parses arguments into a GeoJSON dictionary or a ComputedObject. Args: ctor_name: The name of the constructor to use. depth: The nesting depth at which points are found. args: The array of values to test. Returns: If the arguments are simple, a GeoJSON object describing the geometry. Otherwise a ComputedObject calling the appropriate constructor. """ result = {} keys = ["coordinates", "crs", "geodesic", "maxError", "evenOdd"] if all(ee_types.isNumber(i) for i in args): # All numbers, so convert them to a true array. result["coordinates"] = args else: # Parse parameters by position. if len(args) > len(keys): raise ee_exception.EEException("Geometry constructor given extra arguments.") for key, arg in zip(keys, args): if arg is not None: result[key] = arg # Standardize the coordinates and test if they are simple enough for # client-side initialization. if ( Geometry._hasServerValue(result["coordinates"]) or result.get("crs") is not None or result.get("geodesic") is not None or result.get("maxError") is not None ): # Some arguments cannot be handled in the client, so make a server call. # Note we don't declare a default evenOdd value, so the server can infer # a default based on the projection. server_name = "GeometryConstructors." + ctor_name return apifunction.ApiFunction.lookup(server_name).apply(result) else: # Everything can be handled here, so check the depth and init this object. result["type"] = ctor_name result["coordinates"] = Geometry._fixDepth(depth, result["coordinates"]) # Enable evenOdd by default for any kind of polygon. if "evenOdd" not in result and ctor_name in ["Polygon", "Rectangle", "MultiPolygon"]: result["evenOdd"] = True return result
def __init__(self, date, opt_tz=None): """Construct a date. This sends all inputs (except another Date) through the Date function. This constuctor accepts the following args: 1) A bare date. 2) An ISO string 3) A integer number of milliseconds since the epoch. 4) A ComputedObject. Args: date: The date to wrap. opt_tz: An optional timezone, only useable with a string date. """ self.initialize() func = apifunction.ApiFunction('Date') args = None varName = None if isinstance(date, datetime.datetime): args = {'value': math.floor(serializer.DatetimeToMicroseconds(date) / 1000)} elif types.isNumber(date): args = {'value': date} elif isinstance(date, basestring): args = {'value': date} if opt_tz: if isinstance(opt_tz, basestring): args['timeZone'] = opt_tz else: raise ee_exception.EEException( 'Invalid argument specified for ee.Date(..., opt_tz): %s' % date) elif isinstance(date, computedobject.ComputedObject): if date.func != func: args = {'value': date} else: func = date.func args = date.args varName = date.varName else: raise ee_exception.EEException( 'Invalid argument specified for ee.Date(): %s' % date) super(Date, self).__init__(func, args, varName) self._date = None
def _parseArgs(ctor_name, depth, args): """Parses arguments into a GeoJSON dictionary or a ComputedObject. Args: ctor_name: The name of the constructor to use. depth: The nesting depth at which points are found. args: The array of values to test. Returns: If the arguments are simple, a GeoJSON object describing the geometry. Otherwise a ComputedObject calling the appropriate constructor. """ result = {} keys = ['coordinates', 'crs', 'geodesic', 'maxError'] if all(ee_types.isNumber(i) for i in args): # All numbers, so convert them to a true array. result['coordinates'] = args else: # Parse parameters by position. if len(args) > len(keys): raise ee_exception.EEException( 'Geometry constructor given extra arguments.') for key, arg in zip(keys, args): if arg is not None: result[key] = arg # Standardize the coordinates and test if they are simple enough for # client-side initialization. if (Geometry._hasServerValue(result['coordinates']) or result.get('crs') is not None or result.get('geodesic') is not None or result.get('maxError') is not None): # Some arguments cannot be handled in the client, so make a server call. server_name = 'GeometryConstructors.' + ctor_name return apifunction.ApiFunction.lookup(server_name).apply(result) else: # Everything can be handled here, so check the depth and init this object. result['type'] = ctor_name result['coordinates'] = Geometry._fixDepth(depth, result['coordinates']) return result