Python ee.Feature() Examples
The following are 30
code examples of ee.Feature().
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
You may also want to check out all available functions/classes of the module
ee
, or try the search function
.
Example #1
Source File: maptools.py From ipygee with MIT License | 6 votes |
def featurePropertiesOutput(feat): """ generates a string for features properties """ info = feat.getInfo() properties = info['properties'] theid = info.get('id') if theid: stdout = '<h3>ID {}</h3></br>'.format(theid) else: stdout = '<h3>Feature has no ID</h3></br>' if properties: for prop, value in properties.items(): stdout += '<b>{}</b>: {}</br>'.format(prop, value) else: stdout += '<b>Feature has no properties</b>' return stdout
Example #2
Source File: ee_test.py From aqua-monitor with GNU Lesser General Public License v3.0 | 6 votes |
def testPromotion(self): """Verifies object promotion rules.""" self.InitializeApi() # Features and Images are both already Elements. self.assertTrue(isinstance(ee._Promote(ee.Feature(None), 'Element'), ee.Feature)) self.assertTrue(isinstance(ee._Promote(ee.Image(0), 'Element'), ee.Image)) # Promote an untyped object to an Element. untyped = ee.ComputedObject('foo', {}) self.assertTrue(isinstance(ee._Promote(untyped, 'Element'), ee.Element)) # Promote an untyped variable to an Element. untyped = ee.ComputedObject(None, None, 'foo') self.assertTrue(isinstance(ee._Promote(untyped, 'Element'), ee.Element)) self.assertEquals('foo', ee._Promote(untyped, 'Element').varName)
Example #3
Source File: dictionary_test.py From aqua-monitor with GNU Lesser General Public License v3.0 | 6 votes |
def testDictionary(self): """Verifies basic behavior of ee.Dictionary.""" src = {'a': 1, 'b': 2, 'c': 'three'} dictionary = ee.Dictionary(src) self.assertEquals({'type': 'Dictionary', 'value': src}, ee.Serializer(False)._encode(dictionary)) f = ee.Feature(None, {'properties': src}) computed = ee.Dictionary(f.get('properties')) self.assertTrue(isinstance(computed, ee.Dictionary)) # The 4 types of arguments we expect cons = (ee.Dictionary(src), ee.Dictionary(f.get('properties')), ee.Dictionary(), ee.Dictionary(('one', 1))) for d in cons: self.assertTrue(isinstance(d, ee.ComputedObject))
Example #4
Source File: server.py From aqua-monitor with GNU Lesser General Public License v3.0 | 6 votes |
def GetImageInfoTimeSeries(aoi): def GetImageInfo(img): return ee.Feature(None, { 'id': img.get('system:id'), 'time': img.get('system:time_start'), 'cloud_cover': img.get('CLOUD_COVER') }) def ToFeatureCollection(imageCollectionName): return ee.FeatureCollection(ee.ImageCollection(imageCollectionName).filterBounds(aoi).map(GetImageInfo)) collectionNames = [ 'LANDSAT/LT4_L1T_TOA', 'LANDSAT/LT5_L1T_TOA', 'LANDSAT/LE7_L1T_TOA', 'LANDSAT/LC8_L1T_TOA' ] fc = ee.FeatureCollection([]) for n in collectionNames: fc = fc.merge(ToFeatureCollection(n)) info = fc.sort('time').getInfo() return [i['properties'] for i in info['features']]
Example #5
Source File: scores.py From geebap with GNU General Public License v3.0 | 6 votes |
def map(self, collection, **kwargs): """ Map the score over a collection :param col: collection :type col: satcol.Collection :param geom: boundaries geometry :type geom: ee.Geometry or ee.Feature """ col = kwargs.get('col') geom = kwargs.get('geom') minscale = min([band.scale for band in col.bands]) def wrap(img): score = self.compute(img, geometry=geom, scale=minscale, count_zeros=self.count_zeros) prop = score.get(self.name) return img.addBands(score).set(self.name, prop) return collection.map(wrap)
Example #6
Source File: ee_test.py From earthengine with MIT License | 6 votes |
def testPromotion(self): """Verifies object promotion rules.""" self.InitializeApi() # Features and Images are both already Elements. self.assertTrue(isinstance(ee._Promote(ee.Feature(None), 'Element'), ee.Feature)) self.assertTrue(isinstance(ee._Promote(ee.Image(0), 'Element'), ee.Image)) # Promote an untyped object to an Element. untyped = ee.ComputedObject('foo', {}) self.assertTrue(isinstance(ee._Promote(untyped, 'Element'), ee.Element)) # Promote an untyped variable to an Element. untyped = ee.ComputedObject(None, None, 'foo') self.assertTrue(isinstance(ee._Promote(untyped, 'Element'), ee.Element)) self.assertEquals('foo', ee._Promote(untyped, 'Element').varName)
Example #7
Source File: dictionary_test.py From earthengine with MIT License | 6 votes |
def testDictionary(self): """Verifies basic behavior of ee.Dictionary.""" src = {'a': 1, 'b': 2, 'c': 'three'} dictionary = ee.Dictionary(src) self.assertEquals({'type': 'Dictionary', 'value': src}, ee.Serializer(False)._encode(dictionary)) f = ee.Feature(None, {'properties': src}) computed = ee.Dictionary(f.get('properties')) self.assertTrue(isinstance(computed, ee.Dictionary)) # The 4 types of arguments we expect cons = (ee.Dictionary(src), ee.Dictionary(f.get('properties')), ee.Dictionary(), ee.Dictionary(('one', 1))) for d in cons: self.assertTrue(isinstance(d, ee.ComputedObject))
Example #8
Source File: feature_test.py From aqua-monitor with GNU Lesser General Public License v3.0 | 5 votes |
def testConstructors(self): """Verifies that constructors understand valid parameters.""" point = ee.Geometry.Point(1, 2) from_geometry = ee.Feature(point) self.assertEquals(ee.ApiFunction('Feature'), from_geometry.func) self.assertEquals({'geometry': point, 'metadata': None}, from_geometry.args) from_null_geometry = ee.Feature(None, {'x': 2}) self.assertEquals(ee.ApiFunction('Feature'), from_null_geometry.func) self.assertEquals({'geometry': None, 'metadata': {'x': 2}}, from_null_geometry.args) computed_geometry = ee.Geometry(ee.ComputedObject(ee.Function(), {'a': 1})) computed_properties = ee.ComputedObject(ee.Function(), {'b': 2}) from_computed_one = ee.Feature(computed_geometry) from_computed_both = ee.Feature(computed_geometry, computed_properties) self.assertEquals(ee.ApiFunction('Feature'), from_computed_one.func) self.assertEquals({'geometry': computed_geometry, 'metadata': None}, from_computed_one.args) self.assertEquals(ee.ApiFunction('Feature'), from_computed_both.func) self.assertEquals({'geometry': computed_geometry, 'metadata': computed_properties}, from_computed_both.args) from_variable = ee.Feature(ee.CustomFunction.variable(None, 'foo')) self.assertTrue(isinstance(from_variable, ee.Feature)) self.assertEquals({'type': 'ArgumentRef', 'value': 'foo'}, from_variable.encode(None)) from_geo_json_feature = ee.Feature({ 'type': 'Feature', 'id': 'bar', 'geometry': point.toGeoJSON(), 'properties': {'foo': 42} }) self.assertEquals(ee.ApiFunction('Feature'), from_geo_json_feature.func) self.assertEquals(point, from_geo_json_feature.args['geometry']) self.assertEquals({'foo': 42, 'system:index': 'bar'}, from_geo_json_feature.args['metadata'])
Example #9
Source File: test_geometry.py From gee_tools with MIT License | 5 votes |
def test_getRegion(): expected = [[0.0,0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]] pol = ee.Geometry.Polygon(expected) feat = ee.Feature(pol) region_geom = getRegion(pol) region_feat = getRegion(feat) assert region_geom == [expected] assert region_feat == [expected]
Example #10
Source File: featurecollection.py From gee_tools with MIT License | 5 votes |
def enumerateSimple(collection, name='ENUM'): """ Simple enumeration of features inside a collection. Each feature stores its enumeration, so if the order of features changes over time, the numbers will not be in order """ size = collection.size() collist = collection.toList(size) seq = ee.List.sequence(0, size.subtract(1)) def wrap(n): n = ee.Number(n).toInt() feat = collist.get(n) return ee.Feature(feat).set(name, n) fc = ee.FeatureCollection(seq.map(wrap)) return ee.FeatureCollection(fc.copyProperties(source=collection))
Example #11
Source File: featurecollection.py From gee_tools with MIT License | 5 votes |
def addId(collection, name='id', start=1): """ Add a unique numeric identifier, from parameter 'start' to collection.size() stored in a property called with parameter 'name' :param collection: the collection :type collection: ee.FeatureCollection :param name: the name of the resulting property :type name: str :param start: the number to start from :type start: int :return: the parsed collection with a new property :rtype: ee.FeatureCollection """ start = ee.Number(start) collist = collection.toList(collection.size()) first = ee.Feature(collist.get(0)) rest = collist.slice(1) # Set first id first = ee.List([first.set(name, start)]) # Set rest def over_col(feat, last): last = ee.List(last) last_feat = ee.Feature(last.get(-1)) feat = ee.Feature(feat) last_id = ee.Number(last_feat.get('id')) return last.add(feat.set('id', last_id.add(1))) return ee.FeatureCollection(ee.List(rest.iterate(over_col, first)))
Example #12
Source File: featurecollection.py From gee_tools with MIT License | 5 votes |
def fromKML(filename=None, data=None, crs=None, encoding=None): """ Create a list of Features from a KML file. Return a python tuple with ee.Feature inside. This is due to failing when attempting to create a FeatureCollection (Broken Pipe ERROR) out of the list. You can try creating it yourself casting the result of this function to a ee.List or using it directly as a FeatureCollection argument. :param filename: the name of the file to load :type filename: str :param crs: a coordinate reference system in EPSG format. If not specified it will try to get it from the geoJSON, and if not there it will rise an error :type: crs: str :return: a tuple of features. """ geojsondict = utils.kmlToGeoJsonDict(filename, data, encoding) features = geojsondict['features'] for feat in features: # remove styleUrl prop = feat['properties'] if 'styleUrl' in prop: prop.pop('styleUrl') # remove Z value if needed geom = feat['geometry'] ty = geom['type'] if ty == 'GeometryCollection': geometries = geom['geometries'] for g in geometries: c = g['coordinates'] utils.removeZ(c) else: coords = geom['coordinates'] utils.removeZ(coords) return fromGeoJSON(data=geojsondict, crs=crs)
Example #13
Source File: utils.py From gee_tools with MIT License | 5 votes |
def reduceRegionsPandas(data, index='system:index', add_coordinates=False, duplicate_index=False): """ Transform data coming from Image.reduceRegions to a pandas dataframe :param data: data coming from Image.reduceRegions :type data: ee.Dictionary or dict :param index: the index of the dataframe :param add_coordinates: if True adds the coordinates to the dataframe :param duplicate_index: if True adds the index data to the dataframe too :return: a pandas dataframe :rtype: pd.DataFrame """ if not isinstance(data, dict): if add_coordinates: def addCentroid(feat): feat = ee.Feature(feat) centroid = feat.centroid().geometry() coords = ee.List(centroid.coordinates()) return feat.set('longitude', ee.Number(coords.get(0)), 'latitude', ee.Number(coords.get(1))) data = data.map(addCentroid) data = data.getInfo() features = data['features'] d, indexes = [], [] for feature in features: nf = deepcopy(feature) props = nf['properties'] if not duplicate_index: props.pop(index) if index in props else props d.append(props) if index == 'system:index': indexes.append(feature['id']) else: indexes.append(feature['properties'][index]) return pd.DataFrame(d, indexes)
Example #14
Source File: Map.py From qgis-earthengine-plugin with MIT License | 5 votes |
def setZoom(zoom): """ Sets the zoom level of the map. https://developers.google.com/earth-engine/api_docs#map.setzoom Uses: >>> from ee_plugin import Map >>> Map.setZoom(15) """ center = getCenter() centerObject(ee.Feature(center), zoom)
Example #15
Source File: Map.py From qgis-earthengine-plugin with MIT License | 5 votes |
def centerObject(feature, zoom=None): """ Centers the map view on a given object. https://developers.google.com/earth-engine/api_docs#map.centerobject Uses: >>> from ee_plugin import Map >>> Map.centerObject(feature) """ feature = ee.Feature(feature) if not zoom: # make sure our geometry is in geo rect = feature.geometry().transform(ee.Projection('EPSG:4326'), 1) # get coordinates coords = rect.bounds().getInfo()['coordinates'][0] xmin = coords[0][0] ymin = coords[0][1] xmax = coords[2][0] ymax = coords[2][1] # construct QGIS geometry rect = QgsRectangle(xmin, ymin, xmax, ymax) # transform rect to a crs used by current project crs_src = QgsCoordinateReferenceSystem(4326) crs_dst = QgsCoordinateReferenceSystem(QgsProject.instance().crs()) geo2proj = QgsCoordinateTransform(crs_src, crs_dst, QgsProject.instance()) rect_proj = geo2proj.transform(rect) # center geometry iface.mapCanvas().zoomToFeatureExtent(rect_proj) else: # set map center to feature centroid at a specified zoom center = feature.geometry().centroid().coordinates().getInfo() setCenter(center[0], center[1], zoom)
Example #16
Source File: miscUtilities.py From CrisisMappingToolkit with Apache License 2.0 | 5 votes |
def regionIsInUnitedStates(region): '''Returns true if the current region is inside the US.''' # Extract the geographic boundary of the US. nationList = ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw') nation = ee.Feature(nationList.filter(ee.Filter.eq('Country', 'United States')).first()) nationGeo = ee.Geometry(nation.geometry()) result = nationGeo.contains(region, 10) return (str(result.getInfo()) == 'True')
Example #17
Source File: domain.py From CrisisMappingToolkit with Apache License 2.0 | 5 votes |
def _load_training_json(self, sensor_domain_folder, json_file_name): '''Load in a JSON file containing training features for an EE classifier''' # Load the input file json_file_path = os.path.join(sensor_domain_folder, json_file_name.text + '.json') print('Loading JSON training data: ' + json_file_path) with open(json_file_path, 'r') as f: feature_dict = json.load(f) if not feature_dict: raise Exception('Failed to read JSON file ' + json_file_path) # Convert the data into the desired training format # - The input data is N entries, each containing a polygon of points. # - The output data is ee formatted and classified as either 0 (land) or 1 (water) feature_list = [] for key in feature_dict: # Assign as land unless water is in the key name! terrain_code = 0 if 'water' in key.lower(): terrain_code = 1 #this_geometry = ee.Geometry.LinearRing(feature_dict[key]) this_geometry = ee.Geometry.Polygon(feature_dict[key]) this_feature = ee.Feature(this_geometry, {'classification': terrain_code}) feature_list.append(this_feature) self.training_features = ee.FeatureCollection(feature_list)
Example #18
Source File: lake_measure.py From CrisisMappingToolkit with Apache License 2.0 | 5 votes |
def count_water_and_clouds(ee_bounds, image, sun_elevation): '''Calls the water and cloud detection algorithms on an image and packages the results''' image = ee.Image(image) clouds = detect_clouds(image).gt(cloudThresh) # snow = detect_snow(image).gt(snowThresh) # Function to scale water detection sensitivity based on time of year. def scale_waterThresh(sun_angle): waterThresh = ((.6 / 54) * (62 - sun_angle)) + .05 return waterThresh waterThresh = scale_waterThresh(sun_elevation) water = detect_water(image).gt(waterThresh).And(clouds.Not()) # .And(snow.Not()) cloud_count = clouds.mask(clouds).reduceRegion( reducer = ee.Reducer.count(), geometry = ee_bounds, scale = 30, maxPixels = 1000000, bestEffort = True ) water_count = water.mask(water).reduceRegion( reducer = ee.Reducer.count(), geometry = ee_bounds, scale = 30, maxPixels = 1000000, bestEffort = True ) # addToMap(ee.Algorithms.ConnectedComponentLabeler(water, ee.Kernel.square(1), 256)) return ee.Feature(None, {'date': image.get('DATE_ACQUIRED'), 'spacecraft': image.get('SPACECRAFT_ID'), 'water': water_count.get('constant'), 'cloud': cloud_count.get('constant')}) # Function to add FAI (Algal) index to image and print download URL for raster.
Example #19
Source File: ee_test.py From aqua-monitor with GNU Lesser General Public License v3.0 | 5 votes |
def testDatePromtion(self): # Make a feature, put a time in it, and get it out as a date. self.InitializeApi() point = ee.Geometry.Point(1, 2) feature = ee.Feature(point, {'x': 1, 'y': 2}) date_range = ee.call('DateRange', feature.get('x'), feature.get('y')) # Check that the start and end args are wrapped in a call to Date. self.assertEquals(date_range.args['start'].func._signature['name'], 'Date') self.assertEquals(date_range.args['end'].func._signature['name'], 'Date')
Example #20
Source File: dispatcher.py From ipygee with MIT License | 5 votes |
def feature(info): """ Dispatch a ee.Feature """ geom = info.get('geometry') geomtype = geom.get('type') props = info.get('properties') # Contruct an accordion with the geometries acc = geometry(geom) children = list(acc.children) # Properties if props: # dispatch properties prop_acc = dispatch(props) else: prop_acc = dispatch('Feature has no properties') # Append properties as a child children.append(prop_acc.widget) acc.set_title(1, 'properties') acc.children = children acc.selected_index = None # Geometry Type typewid = dispatch(geomtype) return acc
Example #21
Source File: maptools.py From ipygee with MIT License | 5 votes |
def getGeojsonTile(geometry, name=None, inspect={'data':None, 'reducer':None, 'scale':None}): ''' Get a GeoJson giving a ee.Geometry or ee.Feature ''' if isinstance(geometry, ee.Feature): feat = geometry geometry = feat.geometry() else: feat = None info = geometry.getInfo() type = info['type'] gjson_types = ['Polygon', 'LineString', 'MultiPolygon', 'LinearRing', 'MultiLineString', 'MultiPoint', 'Point', 'Polygon', 'Rectangle', 'GeometryCollection'] # newname = name if name else "{} {}".format(type, map.added_geometries) if type in gjson_types: data = inspect['data'] if feat: default_popup = featurePropertiesOutput(feat) else: default_popup = type red = inspect.get('reducer','first') sca = inspect.get('scale', None) popval = getData(geometry, data, red, sca, name) if data else default_popup geojson = geometry.getInfo() return {'geojson':geojson, 'pop': popval} # 'name': newname} else: print('unrecognized object type to add to map')
Example #22
Source File: server.py From aqua-monitor with GNU Lesser General Public License v3.0 | 5 votes |
def get_image_list(bounds, collection='LANDSAT/LC8_L1T_TOA'): images = ee.ImageCollection(collection).filterBounds(bounds) features = ee.FeatureCollection(images) image_info = features.map(lambda img: ee.Feature(None, { 'id': img.get('system:id'), 'time': img.get('system:time_start'), 'cloud_cover': img.get('CLOUD_COVER') })) info = image_info.getInfo() return [i['properties'] for i in info['features']]
Example #23
Source File: feature_test.py From earthengine with MIT License | 5 votes |
def testConstructors(self): """Verifies that constructors understand valid parameters.""" point = ee.Geometry.Point(1, 2) from_geometry = ee.Feature(point) self.assertEquals(ee.ApiFunction('Feature'), from_geometry.func) self.assertEquals({'geometry': point, 'metadata': None}, from_geometry.args) from_null_geometry = ee.Feature(None, {'x': 2}) self.assertEquals(ee.ApiFunction('Feature'), from_null_geometry.func) self.assertEquals({'geometry': None, 'metadata': {'x': 2}}, from_null_geometry.args) computed_geometry = ee.Geometry(ee.ComputedObject(ee.Function(), {'a': 1})) computed_properties = ee.ComputedObject(ee.Function(), {'b': 2}) from_computed_one = ee.Feature(computed_geometry) from_computed_both = ee.Feature(computed_geometry, computed_properties) self.assertEquals(ee.ApiFunction('Feature'), from_computed_one.func) self.assertEquals({'geometry': computed_geometry, 'metadata': None}, from_computed_one.args) self.assertEquals(ee.ApiFunction('Feature'), from_computed_both.func) self.assertEquals({'geometry': computed_geometry, 'metadata': computed_properties}, from_computed_both.args) from_variable = ee.Feature(ee.CustomFunction.variable(None, 'foo')) self.assertTrue(isinstance(from_variable, ee.Feature)) self.assertEquals({'type': 'ArgumentRef', 'value': 'foo'}, from_variable.encode(None)) from_geo_json_feature = ee.Feature({ 'type': 'Feature', 'id': 'bar', 'geometry': point.toGeoJSON(), 'properties': {'foo': 42} }) self.assertEquals(ee.ApiFunction('Feature'), from_geo_json_feature.func) self.assertEquals(point, from_geo_json_feature.args['geometry']) self.assertEquals({'foo': 42, 'system:index': 'bar'}, from_geo_json_feature.args['metadata'])
Example #24
Source File: idw_interpolation.py From qgis-earthengine-examples with MIT License | 5 votes |
def sampling(sample): lat = sample.get('latitude') lon = sample.get('longitude') ch4 = sample.get('ch4') return ee.Feature(ee.Geometry.Point([lon, lat]), {'ch4': ch4}) # Import two weeks of S5P methane and composite by mean.
Example #25
Source File: extract_image_by_polygon.py From qgis-earthengine-examples with MIT License | 5 votes |
def extract_landsat(feature): geom = ee.Feature(feature).geometry() image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR') \ .filterDate('2019-01-01', '2019-12-31') \ .filterBounds(geom) \ .median() \ .clip(geom) return image # Select the first five U.S. counties
Example #26
Source File: get_image_centroid.py From qgis-earthengine-examples with MIT License | 5 votes |
def getGeom(image): return ee.Feature(image.geometry().centroid(), {'foo': 1}) # Load a Landsat 8 collection.
Example #27
Source File: 3_water_class_transition.py From qgis-earthengine-examples with MIT License | 5 votes |
def createFeature(transition_class_stats): transition_class_stats = ee.Dictionary(transition_class_stats) class_number = transition_class_stats.get('transition_class_value') result = { 'transition_class_number': class_number, 'transition_class_''name': lookup_names.get(class_number), 'transition_class_''palette': lookup_palette.get(class_number), 'area_m2': transition_class_stats.get('sum') } return ee.Feature({}, result) # Creates a feature without a geometry. # Create a JSON dictionary that defines piechart colors based on the # transition class palette. # https:#developers.google.com/chart/interactive/docs/gallery/piechart
Example #28
Source File: app.py From earthengine with MIT License | 5 votes |
def makefeature(data): ''' for exporting as CSV to Drive ''' return ee.Feature(None, {'data': data})
Example #29
Source File: maptools.py From ipygee with MIT License | 5 votes |
def getData(geometry, obj, reducer='first', scale=None, name=None): ''' Get data from an ee.ComputedObject using a giving ee.Geometry ''' accepted = (ee.Image, ee.ImageCollection, ee.Feature, ee.FeatureCollection) reducers = {'first': ee.Reducer.first(), 'mean': ee.Reducer.mean(), 'median': ee.Reducer.median(), 'sum':ee.Reducer.sum()} if not isinstance(obj, accepted): return "Can't get data from that Object" elif isinstance(obj, ee.Image): t = geometry.type().getInfo() # Try to get the image scale scale = obj.select([0]).projection().nominalScale().getInfo() \ if not scale else scale # Reduce if computed scale is too big scale = 1 if scale > 500 else scale if t == 'Point': values = tools.image.getValue(obj, geometry, scale, 'client') val_str = '<h3>Data from {}'.format(name) for key, val in values.items(): val_str += '<b>{}:</b> {}</br>'.format(key, val) return val_str elif t == 'Polygon': red = reducer if reducer in reducers.keys() else 'first' values = obj.reduceRegion(reducers[red], geometry, scale, maxPixels=1e13).getInfo() val_str = '<h3>{}:</h3>\n'.format(red) for key, val in values.items(): val_str += '<b>{}:</b> {}</br>'.format(key, val) return val_str
Example #30
Source File: feature_test.py From earthengine with MIT License | 5 votes |
def testGetMap(self): """Verifies that getMap() uses Collection.draw to rasterize Features.""" feature = ee.Feature(None) mapid = feature.getMapId({'color': 'ABCDEF'}) manual = ee.ApiFunction.apply_('Collection.draw', { 'collection': ee.FeatureCollection([feature]), 'color': 'ABCDEF'}) self.assertEquals('fakeMapId', mapid['mapid']) self.assertEquals(manual.serialize(), mapid['image'].serialize())