def main(): # Get the domain XML file from the command line arguments if len(sys.argv) < 2: print 'Usage: detect_flood_modis.py domain.xml' sys.exit(0) cmt.ee_authenticate.initialize() # Fetch data set information domain = cmt.domain.Domain() domain.load_xml(sys.argv[1]) # Display the Landsat and MODIS data for the data set cmt.util.gui_util.visualizeDomain(domain) # # import cmt.modis.adaboost # cmt.modis.adaboost.adaboost_learn() # Adaboost training # #cmt.modis.adaboost.adaboost_dem_learn(None) # Adaboost DEM stats collection # raise Exception('DEBUG') waterMask = ee.Image("MODIS/MOD44W/MOD44W_005_2000_02_24").select( ['water_mask'], ['b1']) addToMap(waterMask.mask(waterMask), { 'min': 0, 'max': 1 }, 'Permanent Water Mask', False) # For each of the algorithms for a in range(len(ALGORITHMS)): # Run the algorithm on the data and get the results try: (alg, result) = detect_flood(domain, ALGORITHMS[a]) if result is None: continue # These lines are needed for certain data sets which EE is not properly masking!!! # result = result.mask(domain.skybox_nir.image.reduce(ee.Reducer.allNonZero())) # result = result.mask(domain.skybox.image.reduce(ee.Reducer.allNonZero())) # Get a color pre-associated with the algorithm, then draw it on the map color = get_algorithm_color(ALGORITHMS[a]) addToMap(result.mask(result), { 'min': 0, 'max': 1, 'opacity': 0.5, 'palette': '000000, ' + color }, alg, False) # Compare the algorithm output to the ground truth and print the results if domain.ground_truth: cmt.util.evaluation.evaluate_approach_thread( functools.partial(evaluation_function, alg=ALGORITHMS[a]), result, domain.ground_truth, domain.bounds, is_algorithm_fractional(ALGORITHMS[a])) except Exception, e: print('Caught exception running algorithm: ' + get_algorithm_name(ALGORITHMS[a]) + '\n' + str(e) + '\n')
def grow_regions(sensor, thresholded, thresholds): """???????""" REGION_GROWTH_RANGE = 20 neighborhood_kernel = ee.Kernel.square(1, "pixels", False) loose_thresholded = sensor.image.select([sensor.band_names[0]]).lte(thresholds[0]) for i in range(1, len(sensor.band_names)): loose_thresholded = loose_thresholded.And(sensor.image.select([sensor.band_names[i]]).lte(thresholds[i])) addToMap(loose_thresholded, {"min": 0, "max": 1}, "Loose", False) for i in range(REGION_GROWTH_RANGE): thresholded = thresholded.convolve(neighborhood_kernel).And(loose_thresholded) return thresholded
def main(): # Get the domain XML file from the command line arguments if len(sys.argv) < 2: print 'Usage: detect_flood_radar.py domain.xml' sys.exit(0) cmt.ee_authenticate.initialize() # Fetch data set information domain = cmt.domain.Domain() domain.load_xml(sys.argv[1]) # Display radar and ground truth cmt.util.gui_util.visualizeDomain(domain) waterMask = ee.Image("MODIS/MOD44W/MOD44W_005_2000_02_24").select( ['water_mask'], ['b1']) addToMap(waterMask.mask(waterMask), { 'min': 0, 'max': 1 }, 'Permanent Water Mask', False) # print im.image.getDownloadUrl({'name' : 'sar', 'region':ee.Geometry.Rectangle(-91.23, 32.88, -91.02, 33.166).toGeoJSONString(), 'scale': 6.174}) # For each of the algorithms for a in range(len(ALGORITHMS)): try: # Run the algorithm on the data and get the results alg = ALGORITHMS[a] result = detect_flood(domain, alg) # Needed for certain images which did not mask properly from maps engine # result = result.mask(domain.get_radar().image.reduce(ee.Reducer.allNonZero())) # Get a color pre-associated with the algorithm, then draw it on the map color = get_algorithm_color(alg) addToMap(result.mask(result), { 'min': 0, 'max': 1, 'opacity': 0.5, 'palette': '000000, ' + color }, get_algorithm_name(alg), False) # Compare the algorithm output to the ground truth and print the results if domain.ground_truth is not None: cmt.util.evaluation.evaluate_approach_thread( functools.partial(evaluation_function, alg=alg), result, domain.ground_truth, domain.bounds) except Exception, e: print('Caught exception running algorithm: ' + get_algorithm_name(ALGORITHMS[a]) + '\n' + str(e) + '\n')
def grow_regions(sensor, thresholded, thresholds): '''???????''' REGION_GROWTH_RANGE = 20 neighborhood_kernel = ee.Kernel.square(1, 'pixels', False) loose_thresholded = sensor.image.select([sensor.band_names[0] ]).lte(thresholds[0]) for i in range(1, len(sensor.band_names)): loose_thresholded = loose_thresholded.And( sensor.image.select([sensor.band_names[i]]).lte(thresholds[i])) addToMap(loose_thresholded, {'min': 0, 'max': 1}, 'Loose', False) for i in range(REGION_GROWTH_RANGE): thresholded = thresholded.convolve(neighborhood_kernel).And( loose_thresholded) return thresholded
def main(): # Get the domain XML file from the command line arguments if len(sys.argv) < 2: print 'Usage: detect_flood_modis.py domain.xml' sys.exit(0) cmt.ee_authenticate.initialize() # Fetch data set information domain = cmt.domain.Domain() domain.load_xml(sys.argv[1]) # Display the Landsat and MODIS data for the data set cmt.util.gui_util.visualizeDomain(domain) # # import cmt.modis.adaboost # cmt.modis.adaboost.adaboost_learn() # Adaboost training # #cmt.modis.adaboost.adaboost_dem_learn(None) # Adaboost DEM stats collection # raise Exception('DEBUG') waterMask = ee.Image("MODIS/MOD44W/MOD44W_005_2000_02_24").select(['water_mask'], ['b1']) addToMap(waterMask.mask(waterMask), {'min': 0, 'max': 1}, 'Permanent Water Mask', False) # For each of the algorithms for a in range(len(ALGORITHMS)): # Run the algorithm on the data and get the results try: (alg, result) = detect_flood(domain, ALGORITHMS[a]) if result is None: continue # These lines are needed for certain data sets which EE is not properly masking!!! # result = result.mask(domain.skybox_nir.image.reduce(ee.Reducer.allNonZero())) # result = result.mask(domain.skybox.image.reduce(ee.Reducer.allNonZero())) # Get a color pre-associated with the algorithm, then draw it on the map color = get_algorithm_color(ALGORITHMS[a]) addToMap(result.mask(result), {'min': 0, 'max': 1, 'opacity': 0.5, 'palette': '000000, ' + color}, alg, False) # Compare the algorithm output to the ground truth and print the results if domain.ground_truth: cmt.util.evaluation.evaluate_approach_thread(functools.partial( evaluation_function, alg=ALGORITHMS[a]), result, domain.ground_truth, domain.bounds, is_algorithm_fractional(ALGORITHMS[a])) except Exception, e: print('Caught exception running algorithm: ' + get_algorithm_name(ALGORITHMS[a]) + '\n' + str(e) + '\n')
def threshold(domain, historical_domain=None): '''An implementation of the paper: Matgen, Hostache, Schumann, et. al. "Towards an automated SAR-based flood monitoring system: Lessons learned from two case studies." Physics and Chemistry of the Earth, 2011. TODO: ???? ''' sensor = domain.get_radar() # Get the first radar sensor available hist = RadarHistogram(domain, sensor) thresholds = hist.get_thresholds() # Get thresholds for each band # For each band, get pixels less than a threshold results = [] for c in range(len(thresholds)): ch = sensor.band_names[c] results.append(sensor.image.select([ch], [ch]).lte(thresholds[c])) #????? result_image = results[0] for c in range(1, len(results)): result_image = result_image.addBands(results[c], [sensor.band_names[c]]) addToMap(result_image, {'min': 0, 'max': 1}, 'Color Image', False) # TODO: Compare water pixels to expected distribution # take difference of two image, remove pixels that aren't below # original non region-growing threshold and don't change by at # least fixed amount #????? result_image = results[0].select([sensor.band_names[0]], ['b1']) for c in range(1, len(results)): result_image = result_image.And(results[c]) #???? growing_thresholds = hist.find_loose_thresholds() result_image = grow_regions(sensor, result_image, growing_thresholds) #hist.show_histogram() # This is useful for debugging return result_image
def main(): # Get the domain XML file from the command line arguments if len(sys.argv) < 2: print 'Usage: detect_flood_radar.py domain.xml' sys.exit(0) cmt.ee_authenticate.initialize() # Fetch data set information domain = cmt.domain.Domain() domain.load_xml(sys.argv[1]) # Display radar and ground truth cmt.util.gui_util.visualizeDomain(domain) waterMask = ee.Image("MODIS/MOD44W/MOD44W_005_2000_02_24").select(['water_mask'], ['b1']) addToMap(waterMask.mask(waterMask), {'min': 0, 'max': 1}, 'Permanent Water Mask', False) # print im.image.getDownloadUrl({'name' : 'sar', 'region':ee.Geometry.Rectangle(-91.23, 32.88, -91.02, 33.166).toGeoJSONString(), 'scale': 6.174}) # For each of the algorithms for a in range(len(ALGORITHMS)): try: # Run the algorithm on the data and get the results alg = ALGORITHMS[a] result = detect_flood(domain, alg) # Needed for certain images which did not mask properly from maps engine # result = result.mask(domain.get_radar().image.reduce(ee.Reducer.allNonZero())) # Get a color pre-associated with the algorithm, then draw it on the map color = get_algorithm_color(alg) addToMap(result.mask(result), {'min': 0, 'max': 1, 'opacity': 0.5, 'palette': '000000, ' + color}, get_algorithm_name(alg), False) # Compare the algorithm output to the ground truth and print the results if domain.ground_truth is not None: cmt.util.evaluation.evaluate_approach_thread(functools.partial( evaluation_function, alg=alg), result, domain.ground_truth, domain.bounds) except Exception, e: print('Caught exception running algorithm: ' + get_algorithm_name(ALGORITHMS[a]) + '\n' + str(e) + '\n')
def threshold(domain, historical_domain=None): """An implementation of the paper: Matgen, Hostache, Schumann, et. al. "Towards an automated SAR-based flood monitoring system: Lessons learned from two case studies." Physics and Chemistry of the Earth, 2011. TODO: ???? """ sensor = domain.get_radar() # Get the first radar sensor available hist = RadarHistogram(domain, sensor) thresholds = hist.get_thresholds() # Get thresholds for each band # For each band, get pixels less than a threshold results = [] for c in range(len(thresholds)): ch = sensor.band_names[c] results.append(sensor.image.select([ch], [ch]).lte(thresholds[c])) # ????? result_image = results[0] for c in range(1, len(results)): result_image = result_image.addBands(results[c], [sensor.band_names[c]]) addToMap(result_image, {"min": 0, "max": 1}, "Color Image", False) # TODO: Compare water pixels to expected distribution # take difference of two image, remove pixels that aren't below # original non region-growing threshold and don't change by at # least fixed amount # ????? result_image = results[0].select([sensor.band_names[0]], ["b1"]) for c in range(1, len(results)): result_image = result_image.And(results[c]) # ???? growing_thresholds = hist.find_loose_thresholds() result_image = grow_regions(sensor, result_image, growing_thresholds) # hist.show_histogram() # This is useful for debugging return result_image
def sar_martinis(domain, cr_method=False): '''Compute a global threshold via histogram splitting on selected subregions''' sensor = domain.get_radar() radarImage = sensor.image # Many papers reccomend a median type filter to remove speckle noise. # 1: Divide up the image into a grid of tiles, X # Divide up the region into a grid of subregions MAX_BOXES_PER_SIDE = 12 # Cap the number of boxes at 144 DESIRED_BOX_SIZE_METERS = 3000 boxList, boxSizeMeters = divideUpBounds(domain.bounds, DESIRED_BOX_SIZE_METERS, MAX_BOXES_PER_SIDE) # Extract the center point from each box centersList = map(getBoundsCenter, boxList) # SENTINEL = 12m/pixel KERNEL_SIZE = 13 # Each box will be covered by a 13x13 pixel kernel metersPerPixel = boxSizeMeters / KERNEL_SIZE print 'Using metersPerPixel: ' + str(metersPerPixel) avgKernel = ee.Kernel.square(KERNEL_SIZE, 'pixels', True); # <-- EE fails if this is in meters! # Select the radar layer we want to work in if 'water_detect_radar_channel' in domain.algorithm_params: channelName = domain.algorithm_params['water_detect_radar_channel'] else: # Just use the first radar channel channelName = sensor.band_names[0] # Rescale the input data so the statistics are not dominated by very bright pixels GRAY_MAX = 255 grayLayer = applyCutlerLinearLogScale(radarImage.select([channelName]), domain.bounds) #addToMap(grayLayer, {'min': 0, 'max': GRAY_MAX, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'grayLayer', False) # Compute the global mean, then make a constant image out of it. globalMean = grayLayer.reduceRegion(ee.Reducer.mean(), domain.bounds, metersPerPixel) globalMeanImage = ee.Image.constant(globalMean.getInfo()[channelName]) print 'global mean = ' + str(globalMean.getInfo()[channelName]) # Compute mean and standard deviation across the entire image meanImage = grayLayer.convolve(avgKernel) graysSquared = grayLayer.pow(ee.Image(2)) meansSquared = meanImage.pow(ee.Image(2)) meanOfSquaredImage = graysSquared.convolve(avgKernel) meansDiff = meanOfSquaredImage.subtract(meansSquared) stdImage = meansDiff.sqrt() # Debug plots #addToMap(meanImage, {'min': 3000, 'max': 70000, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'Mean', False) #addToMap(stdImage, {'min': 3000, 'max': 200000, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'StdDev', False) #addToMap(meanImage, {'min': 0, 'max': GRAY_MAX, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'Mean', False) #addToMap(stdImage, {'min': 0, 'max': 40, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'StdDev', False) # Compute these two statistics across the entire image CV = meanImage.divide(stdImage).reproject( "EPSG:4326", None, metersPerPixel) R = meanImage.divide(globalMeanImage).reproject("EPSG:4326", None, metersPerPixel) # 2: Prune to a reduced set of tiles X' # Parameters which control which sub-regions will have their histograms analyzed # - These are strongly influenced by the smoothing kernel size!!! MIN_CV = 0.7 MAX_CV = 1.3 MAX_R = 1.1 MIN_R = 0.5 # Debug plots addToMap(CV, {'min': 0, 'max': 4.0, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'CV', False) addToMap(R, {'min': 0, 'max': 4.0, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'R', False) if cr_method: MIN_CR = 0.10 # sar_griefeneder reccomends replacing CV with CR = (std / gray value range), min value 0.05 imageMin = grayLayer.reduceRegion(ee.Reducer.min(), domain.bounds, metersPerPixel).getInfo()[channelName] imageMax = grayLayer.reduceRegion(ee.Reducer.max(), domain.bounds, metersPerPixel).getInfo()[channelName] grayRange = imageMax - imageMin CR = stdImage.divide(grayRange) #addToMap(CR, {'min': 0, 'max': 0.3, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'CR', False) # Filter out pixels based on computed statistics t1 = CV.gte(MIN_CV) t2 = CV.lte(MAX_CV) t3 = R.gte(MIN_R) t4 = R.lte(MAX_R) if cr_method: temp = CR.gte(MIN_CR).And(t3).And(t4) else: temp = t1.And(t2).And(t3).And(t4) X_prime = temp.reproject("EPSG:4326", None, metersPerPixel) addToMap(X_prime.mask(X_prime), {'min': 0, 'max': 1, 'opacity': 1.0, 'palette': TEAL_PALETTE}, 'X_prime', False) # 3: Prune again to a final set of tiles X'' # Further pruning happens here but for now we are skipping it and using # everything that got by the filter. This would speed local computation. # - This is equivalent to using a large number for N'' in the original paper # (which does not suggest a value for N'') X_doublePrime = X_prime # 4: For each tile, compute the optimal threshold # Assemble all local gray values at each point ? localPixelLists = grayLayer.neighborhoodToBands(avgKernel) maskWrapper = ee.ImageCollection([X_doublePrime]); collection = ee.ImageCollection([localPixelLists]); # Extract the point data at from each sub-region! localThresholdList = [] usedPointList = [] rejectedPointList = [] for loc in centersList: try: thisLoc = ee.Geometry.Point(loc[1], loc[0]) # If the mask for this location is invalid, skip this location maskValue = maskWrapper.getRegion(thisLoc, metersPerPixel); maskValue = maskValue.getInfo()[1][4] # TODO: Not the best way to grab the value! if not maskValue: rejectedPointList.append(thisLoc) continue # Otherwise pull down all the pixel values surrounding this center point pointData = collection.getRegion(thisLoc, metersPerPixel) pixelVals = pointData.getInfo()[1][4:] # TODO: Not the best way to grab the value! # TODO: Can EE handle making a histogram around this region or do we need to do this ourselves? #pointData = localPixelLists.reduceRegion(thisRegion, ee.Reducer.histogram(), SAMPLING_SCALE); #print pointData.getInfo() #print pixelVals #__show_histogram(pixelVals) #plt.bar(range(len(pixelVals)), pixelVals) # Compute a histogram from the pixels (TODO: Do this with EE!) NUM_BINS = 256 hist, binEdges = numpy.histogram(pixelVals, NUM_BINS) binCenters = numpy.divide(numpy.add(binEdges[:NUM_BINS], binEdges[1:]), 2.0) # Compute a split on the histogram splitVal = histogram.splitHistogramKittlerIllingworth(hist, binCenters) print "Computed local threshold = " + str(splitVal) localThresholdList.append(splitVal) usedPointList.append(thisLoc) #plt.bar(binCenters, hist) #plt.show() except Exception,e: print 'Failed to compute a location:' print str(e)
#plt.show() except Exception,e: print 'Failed to compute a location:' print str(e) numUsedPoints = len(usedPointList) numUnusedPoints = len(rejectedPointList) if (numUsedPoints > 0): usedPointListEE = ee.FeatureCollection(ee.Feature(usedPointList[0])) for i in range(1,numUsedPoints): temp = ee.FeatureCollection(ee.Feature(usedPointList[i])) usedPointListEE = usedPointListEE.merge(temp) usedPointsDraw = usedPointListEE.draw('00FF00', 8) addToMap(usedPointsDraw, {}, 'Used PTs', False) if (numUnusedPoints > 0): unusedPointListEE = ee.FeatureCollection(ee.Feature(rejectedPointList[0])) for i in range(1,numUnusedPoints): temp = ee.FeatureCollection(ee.Feature(rejectedPointList[i])) unusedPointListEE = unusedPointListEE.merge(temp) unusedPointsDraw = unusedPointListEE.draw('FF0000', 8) addToMap(unusedPointsDraw, {}, 'Unused PTs', False) # 5: Use the individual thresholds to compute a global threshold computedThreshold = numpy.median(localThresholdList) # Nothing fancy going on here!
def Lake_Level_Run(lake, date = None, enddate = None, results_dir = None, fai=False, ndti=False, \ update_function = None, complete_function = None): if date is None: start_date = ee.Date('1984-01-01') end_date = ee.Date('2030-01-01') elif enddate != None and date != None: start_date = ee.Date(date) end_date = ee.Date(enddate) if dt.strptime(date, '%Y-%m-%d') > dt.strptime(enddate, '%Y-%m-%d'): print "Date range invalid: Start date is after end date. Please adjust date range and retry." return elif dt.strptime(date, '%Y-%m-%d') == dt.strptime(enddate, '%Y-%m-%d'): print "Date range invalid: Start date is same as end date. Please adjust date range and retry." return else: start_date = ee.Date(date) end_date = start_date.advance(1.0, 'month') # start_date = ee.Date('2011-06-01') # lake high # start_date = ee.Date('1993-07-01') # lake low # start_date = ee.Date('1993-06-01') # lake low but some jet streams # --- This is the database containing all the lake locations! # all_lakes = ee.FeatureCollection('ft:13s-6qZDKWXsLOWyN7Dap5o6Xuh2sehkirzze29o3', "geometry").toList(1000000) if lake is not None: all_lakes = ee.FeatureCollection( 'ft:1igNpJRGtsq2RtJuieuV0DwMg5b7nU8ZHGgLbC7iq', "geometry").filterMetadata(u'LAKE_NAME', u'equals', lake).toList(1000000) if all_lakes.size() == 0: print 'Lake not found in database. Ending process...' else: # bounds = ee.Geometry.Rectangle(-125.29, 32.55, -114.04, 42.02) # all_lakes = ee.FeatureCollection('ft:13s-6qZDKWXsLOWyN7Dap5o6Xuh2sehkirzze29o3', "geometry").filterBounds(bounds).toList(1000000) all_lakes = ee.FeatureCollection( 'ft:1igNpJRGtsq2RtJuieuV0DwMg5b7nU8ZHGgLbC7iq', "geometry").toList(1000000) # .filterMetadata(u'AREA_SKM', u'less_than', 300.0).toList(100000)#.filterMetadata( # u'LAT_DEG', u'less_than', 42.02).filterMetadata( u'LAT_DEG', u'greater_than', 32.55).filterMetadata( # u'LONG_DEG', u'less_than', -114.04).filterMetadata(u'LONG_DEG', u'greater_than', -125.29).toList(1000000) # pprint(ee.Feature(all_lakes.get(0)).getInfo()) # display individual image from a date if enddate != None and date != None: # Create output directory if not os.path.exists(results_dir): os.makedirs(results_dir) # Fetch ee information for all of the lakes we loaded from the database all_lakes_local = all_lakes.getInfo() for i in range(len(all_lakes_local)): # For each lake... ee_lake = ee.Feature(all_lakes.get(i)) # Get this one lake # Spawn a processing thread for this lake LakeThread((all_lakes_local[i], ee_lake, start_date, end_date, results_dir, fai, ndti, \ functools.partial(update_function, i, len(all_lakes_local)))) # Wait in this loop until all of the LakeThreads have stopped while True: thread_lock.acquire() if total_threads == 0: thread_lock.release() break thread_lock.release() time.sleep(0.1) elif date: from cmt.mapclient_qt import centerMap, addToMap lake = all_lakes.get(0).getInfo() ee_lake = ee.Feature(all_lakes.get(0)) ee_bounds = ee_lake.geometry().buffer(1000) collection = get_image_collection(ee_bounds, start_date, end_date) landsat = ee.Image(collection.first()) #pprint(landsat.getInfo()) center = ee_bounds.centroid().getInfo()['coordinates'] centerMap(center[0], center[1], 11) addToMap(landsat, {'bands': ['B3', 'B2', 'B1']}, 'Landsat 3,2,1 RGB') addToMap(landsat, {'bands': ['B7', 'B5', 'B4']}, 'Landsat 7,5,4 RGB', False) addToMap(landsat, {'bands': ['B6']}, 'Landsat 6', False) clouds = detect_clouds(landsat) water = detect_water(landsat, clouds) addToMap(clouds.mask(clouds), {'opacity': 0.5}, 'Cloud Mask') addToMap(water.mask(water), { 'opacity': 0.5, 'palette': '00FFFF' }, 'Water Mask') addToMap(ee.Feature(ee_bounds)) # print count_water_and_clouds(ee_bounds, landsat).getInfo() # compute water levels in all images of area else: # Create output directory if not os.path.exists(results_dir): os.makedirs(results_dir) # Fetch ee information for all of the lakes we loaded from the database all_lakes_local = all_lakes.getInfo() for i in range(len(all_lakes_local)): # For each lake... ee_lake = ee.Feature(all_lakes.get(i)) # Get this one lake # Spawn a processing thread for this lake LakeThread((all_lakes_local[i], ee_lake, start_date, end_date, results_dir, \ functools.partial(update_function, i, len(all_lakes_local)))) # Wait in this loop until all of the LakeThreads have stopped while True: thread_lock.acquire() if total_threads == 0: thread_lock.release() break thread_lock.release() time.sleep(0.1) if complete_function != None: complete_function() print "Operation completed."
def sar_martinis(domain, cr_method=False): '''Compute a global threshold via histogram splitting on selected subregions''' sensor = domain.get_radar() radarImage = sensor.image # Many papers reccomend a median type filter to remove speckle noise. # 1: Divide up the image into a grid of tiles, X # Divide up the region into a grid of subregions MAX_BOXES_PER_SIDE = 12 # Cap the number of boxes at 144 DESIRED_BOX_SIZE_METERS = 3000 boxList, boxSizeMeters = divideUpBounds(domain.bounds, DESIRED_BOX_SIZE_METERS, MAX_BOXES_PER_SIDE) # Extract the center point from each box centersList = map(getBoundsCenter, boxList) # SENTINEL = 12m/pixel KERNEL_SIZE = 13 # Each box will be covered by a 13x13 pixel kernel metersPerPixel = boxSizeMeters / KERNEL_SIZE print 'Using metersPerPixel: ' + str(metersPerPixel) avgKernel = ee.Kernel.square(KERNEL_SIZE, 'pixels', True) # <-- EE fails if this is in meters! # Select the radar layer we want to work in if 'water_detect_radar_channel' in domain.algorithm_params: channelName = domain.algorithm_params['water_detect_radar_channel'] else: # Just use the first radar channel channelName = sensor.band_names[0] # Rescale the input data so the statistics are not dominated by very bright pixels GRAY_MAX = 255 grayLayer = applyCutlerLinearLogScale(radarImage.select([channelName]), domain.bounds) #addToMap(grayLayer, {'min': 0, 'max': GRAY_MAX, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'grayLayer', False) # Compute the global mean, then make a constant image out of it. globalMean = grayLayer.reduceRegion(ee.Reducer.mean(), domain.bounds, metersPerPixel) globalMeanImage = ee.Image.constant(globalMean.getInfo()[channelName]) print 'global mean = ' + str(globalMean.getInfo()[channelName]) # Compute mean and standard deviation across the entire image meanImage = grayLayer.convolve(avgKernel) graysSquared = grayLayer.pow(ee.Image(2)) meansSquared = meanImage.pow(ee.Image(2)) meanOfSquaredImage = graysSquared.convolve(avgKernel) meansDiff = meanOfSquaredImage.subtract(meansSquared) stdImage = meansDiff.sqrt() # Debug plots #addToMap(meanImage, {'min': 3000, 'max': 70000, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'Mean', False) #addToMap(stdImage, {'min': 3000, 'max': 200000, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'StdDev', False) #addToMap(meanImage, {'min': 0, 'max': GRAY_MAX, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'Mean', False) #addToMap(stdImage, {'min': 0, 'max': 40, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'StdDev', False) # Compute these two statistics across the entire image CV = meanImage.divide(stdImage).reproject("EPSG:4326", None, metersPerPixel) R = meanImage.divide(globalMeanImage).reproject("EPSG:4326", None, metersPerPixel) # 2: Prune to a reduced set of tiles X' # Parameters which control which sub-regions will have their histograms analyzed # - These are strongly influenced by the smoothing kernel size!!! MIN_CV = 0.7 MAX_CV = 1.3 MAX_R = 1.1 MIN_R = 0.5 # Debug plots addToMap(CV, { 'min': 0, 'max': 4.0, 'opacity': 1.0, 'palette': GRAY_PALETTE }, 'CV', False) addToMap(R, { 'min': 0, 'max': 4.0, 'opacity': 1.0, 'palette': GRAY_PALETTE }, 'R', False) if cr_method: MIN_CR = 0.10 # sar_griefeneder reccomends replacing CV with CR = (std / gray value range), min value 0.05 imageMin = grayLayer.reduceRegion( ee.Reducer.min(), domain.bounds, metersPerPixel).getInfo()[channelName] imageMax = grayLayer.reduceRegion( ee.Reducer.max(), domain.bounds, metersPerPixel).getInfo()[channelName] grayRange = imageMax - imageMin CR = stdImage.divide(grayRange) #addToMap(CR, {'min': 0, 'max': 0.3, 'opacity': 1.0, 'palette': GRAY_PALETTE}, 'CR', False) # Filter out pixels based on computed statistics t1 = CV.gte(MIN_CV) t2 = CV.lte(MAX_CV) t3 = R.gte(MIN_R) t4 = R.lte(MAX_R) if cr_method: temp = CR.gte(MIN_CR).And(t3).And(t4) else: temp = t1.And(t2).And(t3).And(t4) X_prime = temp.reproject("EPSG:4326", None, metersPerPixel) addToMap(X_prime.mask(X_prime), { 'min': 0, 'max': 1, 'opacity': 1.0, 'palette': TEAL_PALETTE }, 'X_prime', False) # 3: Prune again to a final set of tiles X'' # Further pruning happens here but for now we are skipping it and using # everything that got by the filter. This would speed local computation. # - This is equivalent to using a large number for N'' in the original paper # (which does not suggest a value for N'') X_doublePrime = X_prime # 4: For each tile, compute the optimal threshold # Assemble all local gray values at each point ? localPixelLists = grayLayer.neighborhoodToBands(avgKernel) maskWrapper = ee.ImageCollection([X_doublePrime]) collection = ee.ImageCollection([localPixelLists]) # Extract the point data at from each sub-region! localThresholdList = [] usedPointList = [] rejectedPointList = [] for loc in centersList: try: thisLoc = ee.Geometry.Point(loc[1], loc[0]) # If the mask for this location is invalid, skip this location maskValue = maskWrapper.getRegion(thisLoc, metersPerPixel) maskValue = maskValue.getInfo()[1][ 4] # TODO: Not the best way to grab the value! if not maskValue: rejectedPointList.append(thisLoc) continue # Otherwise pull down all the pixel values surrounding this center point pointData = collection.getRegion(thisLoc, metersPerPixel) pixelVals = pointData.getInfo()[1][ 4:] # TODO: Not the best way to grab the value! # TODO: Can EE handle making a histogram around this region or do we need to do this ourselves? #pointData = localPixelLists.reduceRegion(thisRegion, ee.Reducer.histogram(), SAMPLING_SCALE); #print pointData.getInfo() #print pixelVals #__show_histogram(pixelVals) #plt.bar(range(len(pixelVals)), pixelVals) # Compute a histogram from the pixels (TODO: Do this with EE!) NUM_BINS = 256 hist, binEdges = numpy.histogram(pixelVals, NUM_BINS) binCenters = numpy.divide( numpy.add(binEdges[:NUM_BINS], binEdges[1:]), 2.0) # Compute a split on the histogram splitVal = histogram.splitHistogramKittlerIllingworth( hist, binCenters) print "Computed local threshold = " + str(splitVal) localThresholdList.append(splitVal) usedPointList.append(thisLoc) #plt.bar(binCenters, hist) #plt.show() except Exception, e: print 'Failed to compute a location:' print str(e)
#plt.show() except Exception, e: print 'Failed to compute a location:' print str(e) numUsedPoints = len(usedPointList) numUnusedPoints = len(rejectedPointList) if (numUsedPoints > 0): usedPointListEE = ee.FeatureCollection(ee.Feature(usedPointList[0])) for i in range(1, numUsedPoints): temp = ee.FeatureCollection(ee.Feature(usedPointList[i])) usedPointListEE = usedPointListEE.merge(temp) usedPointsDraw = usedPointListEE.draw('00FF00', 8) addToMap(usedPointsDraw, {}, 'Used PTs', False) if (numUnusedPoints > 0): unusedPointListEE = ee.FeatureCollection( ee.Feature(rejectedPointList[0])) for i in range(1, numUnusedPoints): temp = ee.FeatureCollection(ee.Feature(rejectedPointList[i])) unusedPointListEE = unusedPointListEE.merge(temp) unusedPointsDraw = unusedPointListEE.draw('FF0000', 8) addToMap(unusedPointsDraw, {}, 'Unused PTs', False) # 5: Use the individual thresholds to compute a global threshold computedThreshold = numpy.median( localThresholdList) # Nothing fancy going on here!
# Fetch data set information domain = cmt.domain.Domain() domain.load_xml(sys.argv[1]) # Display the Landsat and MODIS data for the data set cmt.util.gui_util.visualizeDomain(domain) # # import cmt.modis.adaboost # cmt.modis.adaboost.adaboost_learn() # Adaboost training # #cmt.modis.adaboost.adaboost_dem_learn(None) # Adaboost DEM stats collection # raise Exception('DEBUG') waterMask = ee.Image("MODIS/MOD44W/MOD44W_005_2000_02_24").select(['water_mask'], ['b1']) addToMap(waterMask.mask(waterMask), {'min': 0, 'max': 1}, 'Permanent Water Mask', False) # For each of the algorithms for a in range(len(ALGORITHMS)): # Run the algorithm on the data and get the results try: (alg, result) = detect_flood(domain, ALGORITHMS[a]) if result is None: continue # These lines are needed for certain data sets which EE is not properly masking!!! # result = result.mask(domain.skybox_nir.image.reduce(ee.Reducer.allNonZero())) # result = result.mask(domain.skybox.image.reduce(ee.Reducer.allNonZero())) # Get a color pre-associated with the algorithm, then draw it on the map color = get_algorithm_color(ALGORITHMS[a])
#u'LAT_DEG', u'less_than', 42.02).filterMetadata( u'LAT_DEG', u'greater_than', 32.55).filterMetadata( #u'LONG_DEG', u'less_than', -114.04).filterMetadata(u'LONG_DEG', u'greater_than', -125.29).toList(1000000) #pprint(ee.Feature(all_lakes.get(0)).getInfo()) # display individual image from a date if args.date: from cmt.mapclient_qt import centerMap, addToMap lake = all_lakes.get(0).getInfo() ee_lake = ee.Feature(all_lakes.get(0)) ee_bounds = ee_lake.geometry().buffer(1000) collection = get_image_collection(ee_bounds, start_date, end_date) landsat = ee.Image(collection.first()) #pprint(landsat.getInfo()) center = ee_bounds.centroid().getInfo()['coordinates'] centerMap(center[0], center[1], 11) addToMap(landsat, {'bands': ['B3', 'B2', 'B1']}, 'Landsat 3,2,1 RGB') addToMap(landsat, {'bands': ['B7', 'B5', 'B4']}, 'Landsat 7,5,4 RGB', False) addToMap(landsat, {'bands': ['B6' ]}, 'Landsat 6', False) clouds = detect_clouds(landsat) water = detect_water(landsat, clouds) addToMap(clouds.mask(clouds), {'opacity' : 0.5}, 'Cloud Mask') addToMap(water.mask(water), {'opacity' : 0.5, 'palette' : '00FFFF'}, 'Water Mask') addToMap(ee.Feature(ee_bounds)) #print count_water_and_clouds(ee_bounds, landsat).getInfo() # compute water levels in all images of area else: # Create output directory if not os.path.exists(args.results_dir): os.makedirs(args.results_dir)
# plt.show() except Exception, e: print "Failed to compute a location:" print str(e) numUsedPoints = len(usedPointList) numUnusedPoints = len(rejectedPointList) if numUsedPoints > 0: usedPointListEE = ee.FeatureCollection(ee.Feature(usedPointList[0])) for i in range(1, numUsedPoints): temp = ee.FeatureCollection(ee.Feature(usedPointList[i])) usedPointListEE = usedPointListEE.merge(temp) usedPointsDraw = usedPointListEE.draw("00FF00", 8) addToMap(usedPointsDraw, {}, "Used PTs", False) if numUnusedPoints > 0: unusedPointListEE = ee.FeatureCollection(ee.Feature(rejectedPointList[0])) for i in range(1, numUnusedPoints): temp = ee.FeatureCollection(ee.Feature(rejectedPointList[i])) unusedPointListEE = unusedPointListEE.merge(temp) unusedPointsDraw = unusedPointListEE.draw("FF0000", 8) addToMap(unusedPointsDraw, {}, "Unused PTs", False) # 5: Use the individual thresholds to compute a global threshold computedThreshold = numpy.median(localThresholdList) # Nothing fancy going on here! print "Computed global threshold = " + str(computedThreshold)
def Lake_Level_Run(lake, date = None, enddate = None, results_dir = None, fai=False, ndti=False, \ update_function = None, complete_function = None): if date is None: start_date = ee.Date('1984-01-01') end_date = ee.Date('2030-01-01') elif enddate != None and date != None: start_date = ee.Date(date) end_date = ee.Date(enddate) if dt.strptime(date,'%Y-%m-%d') > dt.strptime(enddate,'%Y-%m-%d'): print "Date range invalid: Start date is after end date. Please adjust date range and retry." return elif dt.strptime(date,'%Y-%m-%d') == dt.strptime(enddate,'%Y-%m-%d'): print "Date range invalid: Start date is same as end date. Please adjust date range and retry." return else: start_date = ee.Date(date) end_date = start_date.advance(1.0, 'month') # start_date = ee.Date('2011-06-01') # lake high # start_date = ee.Date('1993-07-01') # lake low # start_date = ee.Date('1993-06-01') # lake low but some jet streams # --- This is the database containing all the lake locations! # all_lakes = ee.FeatureCollection('ft:13s-6qZDKWXsLOWyN7Dap5o6Xuh2sehkirzze29o3', "geometry").toList(1000000) if lake is not None: all_lakes = ee.FeatureCollection('ft:1igNpJRGtsq2RtJuieuV0DwMg5b7nU8ZHGgLbC7iq', "geometry").filterMetadata(u'LAKE_NAME', u'equals', lake).toList(1000000) if all_lakes.size() == 0: print 'Lake not found in database. Ending process...' else: # bounds = ee.Geometry.Rectangle(-125.29, 32.55, -114.04, 42.02) # all_lakes = ee.FeatureCollection('ft:13s-6qZDKWXsLOWyN7Dap5o6Xuh2sehkirzze29o3', "geometry").filterBounds(bounds).toList(1000000) all_lakes = ee.FeatureCollection('ft:1igNpJRGtsq2RtJuieuV0DwMg5b7nU8ZHGgLbC7iq', "geometry").toList(1000000) # .filterMetadata(u'AREA_SKM', u'less_than', 300.0).toList(100000)#.filterMetadata( # u'LAT_DEG', u'less_than', 42.02).filterMetadata( u'LAT_DEG', u'greater_than', 32.55).filterMetadata( # u'LONG_DEG', u'less_than', -114.04).filterMetadata(u'LONG_DEG', u'greater_than', -125.29).toList(1000000) # pprint(ee.Feature(all_lakes.get(0)).getInfo()) # display individual image from a date if enddate != None and date != None: # Create output directory if not os.path.exists(results_dir): os.makedirs(results_dir) # Fetch ee information for all of the lakes we loaded from the database all_lakes_local = all_lakes.getInfo() for i in range(len(all_lakes_local)): # For each lake... ee_lake = ee.Feature(all_lakes.get(i)) # Get this one lake # Spawn a processing thread for this lake LakeThread((all_lakes_local[i], ee_lake, start_date, end_date, results_dir, fai, ndti, \ functools.partial(update_function, i, len(all_lakes_local)))) # Wait in this loop until all of the LakeThreads have stopped while True: thread_lock.acquire() if total_threads == 0: thread_lock.release() break thread_lock.release() time.sleep(0.1) elif date: from cmt.mapclient_qt import centerMap, addToMap lake = all_lakes.get(0).getInfo() ee_lake = ee.Feature(all_lakes.get(0)) ee_bounds = ee_lake.geometry().buffer(1000) collection = get_image_collection(ee_bounds, start_date, end_date) landsat = ee.Image(collection.first()) #pprint(landsat.getInfo()) center = ee_bounds.centroid().getInfo()['coordinates'] centerMap(center[0], center[1], 11) addToMap(landsat, {'bands': ['B3', 'B2', 'B1']}, 'Landsat 3,2,1 RGB') addToMap(landsat, {'bands': ['B7', 'B5', 'B4']}, 'Landsat 7,5,4 RGB', False) addToMap(landsat, {'bands': ['B6' ]}, 'Landsat 6', False) clouds = detect_clouds(landsat) water = detect_water(landsat, clouds) addToMap(clouds.mask(clouds), {'opacity' : 0.5}, 'Cloud Mask') addToMap(water.mask(water), {'opacity' : 0.5, 'palette' : '00FFFF'}, 'Water Mask') addToMap(ee.Feature(ee_bounds)) # print count_water_and_clouds(ee_bounds, landsat).getInfo() # compute water levels in all images of area else: # Create output directory if not os.path.exists(results_dir): os.makedirs(results_dir) # Fetch ee information for all of the lakes we loaded from the database all_lakes_local = all_lakes.getInfo() for i in range(len(all_lakes_local)): # For each lake... ee_lake = ee.Feature(all_lakes.get(i)) # Get this one lake # Spawn a processing thread for this lake LakeThread((all_lakes_local[i], ee_lake, start_date, end_date, results_dir, \ functools.partial(update_function, i, len(all_lakes_local)))) # Wait in this loop until all of the LakeThreads have stopped while True: thread_lock.acquire() if total_threads == 0: thread_lock.release() break thread_lock.release() time.sleep(0.1) if complete_function != None: complete_function() print "Operation completed."
def dnns_revised(domain, b): '''Dynamic Nearest Neighbor Search with revisions to improve performance on our test data''' # One issue with this algorithm is that its large search range slows down even Earth Engine! # - With a tiny kernel size, everything is relative to the region average which seems to work pretty well. # Another problem is that we don't have a good way of identifying 'Definately land' pixels like we do for water. # Parameters KERNEL_SIZE = 1 # The original paper used a 100x100 pixel box = 25,000 meters! PURELAND_THRESHOLD = 3500 # TODO: Vary by domain? PURE_WATER_THRESHOLD_RATIO = 0.1 # Set up two square kernels of the same size # - These kernels define the search range for nearby pure water and land pixels kernel = ee.Kernel.square(KERNEL_SIZE, 'pixels', False) kernel_normalized = ee.Kernel.square(KERNEL_SIZE, 'pixels', True) composite_image = b['b1'].addBands(b['b2']).addBands(b['b6']) # Compute (b2 - b1) < threshold, a simple water detection algorithm. Treat the result as "pure water" pixels. pureWaterThreshold = float(domain.algorithm_params['modis_diff_threshold']) * PURE_WATER_THRESHOLD_RATIO pureWater = modis_diff(domain, b, pureWaterThreshold) # Compute the mean value of pure water pixels across the entire region, then store in a constant value image. AVERAGE_SCALE_METERS = 30 # This value seems to have no effect on the results averageWater = safe_get_info(pureWater.mask(pureWater).multiply(composite_image).reduceRegion(ee.Reducer.mean(), domain.bounds, AVERAGE_SCALE_METERS)) averageWaterImage = ee.Image([averageWater['sur_refl_b01'], averageWater['sur_refl_b02'], averageWater['sur_refl_b06']]) # For each pixel, compute the number of nearby pure water pixels pureWaterCount = pureWater.convolve(kernel) # Get mean of nearby pure water (b1,b2,b6) values for each pixel with enough pure water nearby MIN_PURE_NEARBY = 10 averageWaterLocal = pureWater.multiply(composite_image).convolve(kernel).multiply(pureWaterCount.gte(MIN_PURE_NEARBY)).divide(pureWaterCount) # For pixels that did not have enough pure water nearby, just use the global average water value averageWaterLocal = averageWaterLocal.add(averageWaterImage.multiply(averageWaterLocal.Not())) # Use simple diff method to select pure land pixels #LAND_THRESHOLD = 2000 # TODO: Move to domain selector pureLand = b['b2'].subtract(b['b1']).gte(PURELAND_THRESHOLD).select(['sur_refl_b02'], ['b1']) # Rename sur_refl_b02 to b1 averagePureLand = safe_get_info(pureLand.mask(pureLand).multiply(composite_image).reduceRegion(ee.Reducer.mean(), domain.bounds, AVERAGE_SCALE_METERS)) averagePureLandImage = ee.Image([averagePureLand['sur_refl_b01'], averagePureLand['sur_refl_b02'], averagePureLand['sur_refl_b06']]) pureLandCount = pureLand.convolve(kernel) # Get nearby pure land count for each pixel averagePureLandLocal = pureLand.multiply(composite_image).convolve(kernel).multiply(pureLandCount.gte(MIN_PURE_NEARBY)).divide(pureLandCount) averagePureLandLocal = averagePureLandLocal.add(averagePureLandImage.multiply(averagePureLandLocal.Not())) # For pixels that did not have any pure land nearby, use mean # Implement equations 10 and 11 from the paper oneOverSix = b['b1'].divide(b['b6']) twoOverSix = b['b2'].divide(b['b6']) eqTenLeft = oneOverSix.subtract( averageWaterLocal.select('sur_refl_b01').divide(b['b6']) ) eqElevenLeft = twoOverSix.subtract( averageWaterLocal.select('sur_refl_b02').divide(b['b6']) ) # For each pixel, grab all the ratios from nearby pixels nearbyPixelsOneOverSix = oneOverSix.neighborhoodToBands(kernel) # Each of these images has one band per nearby pixel nearbyPixelsTwoOverSix = twoOverSix.neighborhoodToBands(kernel) nearbyPixelsOne = b['b1'].neighborhoodToBands(kernel) nearbyPixelsTwo = b['b2'].neighborhoodToBands(kernel) nearbyPixelsSix = b['b6'].neighborhoodToBands(kernel) # Find which nearby pixels meet the EQ 10 and 11 criteria eqTenMatches = ( nearbyPixelsOneOverSix.gt(eqTenLeft ) ).And( nearbyPixelsOneOverSix.lt(oneOverSix) ) eqElevenMatches = ( nearbyPixelsTwoOverSix.gt(eqElevenLeft) ).And( nearbyPixelsTwoOverSix.lt(twoOverSix) ) nearbyLandPixels = eqTenMatches.And(eqElevenMatches) # Find the average of the nearby matching pixels numNearbyLandPixels = nearbyLandPixels.reduce(ee.Reducer.sum()) meanNearbyBandOne = nearbyPixelsOne.multiply(nearbyLandPixels).reduce(ee.Reducer.sum()).divide(numNearbyLandPixels) meanNearbyBandTwo = nearbyPixelsTwo.multiply(nearbyLandPixels).reduce(ee.Reducer.sum()).divide(numNearbyLandPixels) meanNearbyBandSix = nearbyPixelsSix.multiply(nearbyLandPixels).reduce(ee.Reducer.sum()).divide(numNearbyLandPixels) # Pack the results into a three channel image for the whole region meanNearbyLand = meanNearbyBandOne.addBands(meanNearbyBandTwo).addBands(meanNearbyBandSix) meanNearbyLand = meanNearbyLand.multiply(numNearbyLandPixels.gte(MIN_PURE_NEARBY)).add( averagePureLandImage.multiply(numNearbyLandPixels.lt(MIN_PURE_NEARBY)) ) addToMap(numNearbyLandPixels, {'min': 0, 'max': 400, }, 'numNearbyLandPixels', False) addToMap(meanNearbyLand, {'min': 0, 'max': 3000, 'bands': ['sum', 'sum_1', 'sum_2']}, 'meanNearbyLand', False) # Compute the water fraction: (land - b) / (land - water) landDiff = averagePureLandLocal.subtract(composite_image) waterDiff = averageWaterLocal.subtract(composite_image) typeDiff = averagePureLandLocal.subtract(averageWaterLocal) #water_vector = (averageLandLocal.subtract(b)).divide(averageLandLocal.subtract(averageWaterLocal)) landDist = landDiff.expression("b('sur_refl_b01')*b('sur_refl_b01') + b('sur_refl_b02') *b('sur_refl_b02') + b('sur_refl_b06')*b('sur_refl_b06')").sqrt(); waterDist = waterDiff.expression("b('sur_refl_b01')*b('sur_refl_b01') + b('sur_refl_b02') *b('sur_refl_b02') + b('sur_refl_b06')*b('sur_refl_b06')").sqrt(); typeDist = typeDiff.expression("b('sur_refl_b01')*b('sur_refl_b01') + b('sur_refl_b02') *b('sur_refl_b02') + b('sur_refl_b06')*b('sur_refl_b06')").sqrt(); #waterOff = landDist.divide(waterDist.add(landDist)) waterOff = landDist.divide(typeDist) # TODO: Improve this math, maybe full matrix treatment? # Set pure water to 1, pure land to 0 waterOff = waterOff.subtract(pureLand.multiply(waterOff)) waterOff = waterOff.add(pureWater.multiply(ee.Image(1.0).subtract(waterOff))) # TODO: Better way of filtering out low fraction pixels. waterOff = waterOff.multiply(waterOff) waterOff = waterOff.gt(0.6) #addToMap(fraction, {'min': 0, 'max': 1}, 'fraction', False) addToMap(pureWater, {'min': 0, 'max': 1}, 'pure water', False) addToMap(pureLand, {'min': 0, 'max': 1}, 'pure land', False) addToMap(pureWaterCount, {'min': 0, 'max': 100}, 'pure water count', False) addToMap(pureLandCount, {'min': 0, 'max': 100}, 'pure land count', False) #addToMap(numNearbyLandPixels, {'min': 0, 'max': 400, }, 'numNearbyLandPixels', False) #addToMap(meanNearbyLand, {'min': 0, 'max': 3000, 'bands': ['sum', 'sum_1', 'sum_2']}, 'meanNearbyLand', False) addToMap(averageWaterImage, {'min': 0, 'max': 3000, 'bands': ['constant', 'constant_1', 'constant_2']}, 'average water', False) addToMap(averagePureLandImage, {'min': 0, 'max': 3000, 'bands': ['constant', 'constant_1', 'constant_2']}, 'average pure land', False) addToMap(averageWaterLocal, {'min': 0, 'max': 3000, 'bands': ['sur_refl_b01', 'sur_refl_b02', 'sur_refl_b06']}, 'local water ref', False) addToMap(averagePureLandLocal, {'min': 0, 'max': 3000, 'bands': ['sur_refl_b01', 'sur_refl_b02', 'sur_refl_b06']}, 'local pure land ref', False) return waterOff.select(['sur_refl_b01'], ['b1']) # Rename sur_refl_b02 to b1