def feature_byProperty(features, xProperties, seriesProperty, **kwargs): """Generates a Chart from a set of features. Plots property values of one or more features. Reference: https://developers.google.com/earth-engine/guides/charts_feature#uichartfeaturebyproperty Args: features (ee.FeatureCollection): The features to include in the chart. xProperties (list | dict): One of (1) a list of properties to be plotted on the x-axis; or (2) a (property, label) dictionary specifying labels for properties to be used as values on the x-axis. seriesProperty (str): The name of the property used to label each feature in the legend. Raises: Exception: If the provided xProperties is not a list or dict. Exception: If the chart fails to create. """ try: df = ee_to_df(features) if isinstance(xProperties, list): x_data = xProperties y_data = df[xProperties].values elif isinstance(xProperties, dict): x_data = list(xProperties.values()) y_data = df[list(xProperties.keys())].values else: raise Exception("xProperties must be a list or dictionary.") labels = list(df[seriesProperty]) if "ylim" in kwargs: min_value = kwargs["ylim"][0] max_value = kwargs["ylim"][1] else: min_value = y_data.min() max_value = y_data.max() max_value = max_value + 0.2 * (max_value - min_value) if "title" not in kwargs: title = "" else: title = kwargs["title"] if "legend_location" not in kwargs: legend_location = "top-left" else: legend_location = kwargs["legend_location"] if "display_legend" not in kwargs: display_legend = True else: display_legend = kwargs["display_legend"] fig = plt.figure( title=title, legend_location=legend_location, ) if "width" in kwargs: fig.layout.width = kwargs["width"] if "height" in kwargs: fig.layout.height = kwargs["height"] bar_chart = plt.bar(x=x_data, y=y_data, labels=labels, display_legend=display_legend) bar_chart.type = "grouped" if "colors" in kwargs: bar_chart.colors = kwargs["colors"] if "xlabel" in kwargs: plt.xlabel(kwargs["xlabel"]) if "ylabel" in kwargs: plt.ylabel(kwargs["ylabel"]) plt.ylim(min_value, max_value) if "xlabel" in kwargs and ("ylabel" in kwargs): bar_chart.tooltip = Tooltip( fields=["x", "y"], labels=[kwargs["xlabel"], kwargs["ylabel"]]) else: bar_chart.tooltip = Tooltip(fields=["x", "y"]) plt.show() except Exception as e: raise Exception(e)
def feature_groups(features, xProperty, yProperty, seriesProperty, **kwargs): """Generates a Chart from a set of features. Plots the value of one property for each feature. Reference: https://developers.google.com/earth-engine/guides/charts_feature#uichartfeaturegroups Args: features (ee.FeatureCollection): The feature collection to make a chart from. xProperty (str): Features labeled by xProperty. yProperty (str): Features labeled by yProperty. seriesProperty (str): The property used to label each feature in the legend. Raises: Exception: Errors when creating the chart. """ try: df = ee_to_df(features) df[yProperty] = pd.to_numeric(df[yProperty]) unique_series_values = df[seriesProperty].unique().tolist() new_column_names = [] for value in unique_series_values: sample_filter = (df[seriesProperty] == value).map({ True: 1, False: 0 }) column_name = str(yProperty) + "_" + str(value) df[column_name] = df[yProperty] * sample_filter new_column_names.append(column_name) if "labels" in kwargs: labels = kwargs["labels"] else: labels = [str(x) for x in unique_series_values] if "ylim" in kwargs: min_value = kwargs["ylim"][0] max_value = kwargs["ylim"][1] else: min_value = df[yProperty].to_numpy().min() max_value = df[yProperty].to_numpy().max() max_value = max_value + 0.2 * (max_value - min_value) if "title" not in kwargs: title = "" else: title = kwargs["title"] if "legend_location" not in kwargs: legend_location = "top-left" else: legend_location = kwargs["legend_location"] x_data = list(df[xProperty]) y_data = [df[x] for x in new_column_names] plt.bar(x_data, y_data) fig = plt.figure( title=title, legend_location=legend_location, ) if "width" in kwargs: fig.layout.width = kwargs["width"] if "height" in kwargs: fig.layout.height = kwargs["height"] if "display_legend" not in kwargs: display_legend = True else: display_legend = kwargs["display_legend"] bar_chart = plt.bar(x_data, y_data, labels=labels, display_legend=display_legend) if "colors" in kwargs: bar_chart.colors = kwargs["colors"] if "xlabel" in kwargs: plt.xlabel(kwargs["xlabel"]) if "ylabel" in kwargs: plt.ylabel(kwargs["ylabel"]) plt.ylim(min_value, max_value) if "xlabel" in kwargs and ("ylabel" in kwargs): bar_chart.tooltip = Tooltip( fields=["x", "y"], labels=[kwargs["xlabel"], kwargs["ylabel"]]) else: bar_chart.tooltip = Tooltip(fields=["x", "y"]) plt.show() except Exception as e: raise Exception(e)
def feature_histogram(features, property, maxBuckets=None, minBucketWidth=None, **kwargs): """ Generates a Chart from a set of features. Computes and plots a histogram of the given property. - X-axis = Histogram buckets (of property value). - Y-axis = Frequency Reference: https://developers.google.com/earth-engine/guides/charts_feature#uichartfeaturehistogram Args: features (ee.FeatureCollection): The features to include in the chart. property (str): The name of the property to generate the histogram for. maxBuckets (int, optional): The maximum number of buckets (bins) to use when building a histogram; will be rounded up to a power of 2. minBucketWidth (float, optional): The minimum histogram bucket width, or null to allow any power of 2. Raises: Exception: If the provided xProperties is not a list or dict. Exception: If the chart fails to create. """ import math if not isinstance(features, ee.FeatureCollection): raise Exception("features must be an ee.FeatureCollection") first = features.first() props = first.propertyNames().getInfo() if property not in props: raise Exception( f"property {property} not found. Available properties: {', '.join(props)}" ) def nextPowerOf2(n): return pow(2, math.ceil(math.log2(n))) def grow_bin(bin_size, ref): while bin_size < ref: bin_size *= 2 return bin_size try: raw_data = pd.to_numeric( pd.Series(features.aggregate_array(property).getInfo())) y_data = raw_data.tolist() if "ylim" in kwargs: min_value = kwargs["ylim"][0] max_value = kwargs["ylim"][1] else: min_value = raw_data.min() max_value = raw_data.max() data_range = max_value - min_value if not maxBuckets: initial_bin_size = nextPowerOf2(data_range / pow(2, 8)) if minBucketWidth: if minBucketWidth < initial_bin_size: bin_size = grow_bin(minBucketWidth, initial_bin_size) else: bin_size = minBucketWidth else: bin_size = initial_bin_size else: initial_bin_size = math.ceil(data_range / nextPowerOf2(maxBuckets)) if minBucketWidth: if minBucketWidth < initial_bin_size: bin_size = grow_bin(minBucketWidth, initial_bin_size) else: bin_size = minBucketWidth else: bin_size = initial_bin_size start_bins = (math.floor(min_value / bin_size) * bin_size) - (bin_size / 2) end_bins = (math.ceil(max_value / bin_size) * bin_size) + (bin_size / 2) if start_bins < min_value: y_data.append(start_bins) else: y_data[y_data.index(min_value)] = start_bins if end_bins > max_value: y_data.append(end_bins) else: y_data[y_data.index(max_value)] = end_bins num_bins = math.floor((end_bins - start_bins) / bin_size) if "title" not in kwargs: title = "" else: title = kwargs["title"] fig = plt.figure(title=title) if "width" in kwargs: fig.layout.width = kwargs["width"] if "height" in kwargs: fig.layout.height = kwargs["height"] if "xlabel" not in kwargs: xlabel = "" else: xlabel = kwargs["xlabel"] if "ylabel" not in kwargs: ylabel = "" else: ylabel = kwargs["ylabel"] histogram = plt.hist( sample=y_data, bins=num_bins, axes_options={ "count": { "label": ylabel }, "sample": { "label": xlabel } }, ) if "colors" in kwargs: histogram.colors = kwargs["colors"] if "stroke" in kwargs: histogram.stroke = kwargs["stroke"] else: histogram.stroke = "#ffffff00" if "stroke_width" in kwargs: histogram.stroke_width = kwargs["stroke_width"] else: histogram.stroke_width = 0 if ("xlabel" in kwargs) and ("ylabel" in kwargs): histogram.tooltip = Tooltip( fields=["midpoint", "count"], labels=[kwargs["xlabel"], kwargs["ylabel"]], ) else: histogram.tooltip = Tooltip(fields=["midpoint", "count"]) plt.show() except Exception as e: raise Exception(e)
import numpy as np import bqplot.pyplot as plt size = 100 plt.figure(title='Scatter plot with colors') plt.scatter(np.random.randn(size), np.random.randn(size), color=np.random.randn(size)) plt.show()
def feature_byFeature(features, xProperty, yProperties, **kwargs): """Generates a Chart from a set of features. Plots the value of one or more properties for each feature. Reference: https://developers.google.com/earth-engine/guides/charts_feature#uichartfeaturebyfeature Args: features (ee.FeatureCollection): The feature collection to generate a chart from. xProperty (str): Features labeled by xProperty. yProperties (list): Values of yProperties. Raises: Exception: Errors when creating the chart. """ try: df = ee_to_df(features) if "ylim" in kwargs: min_value = kwargs["ylim"][0] max_value = kwargs["ylim"][1] else: min_value = df[yProperties].to_numpy().min() max_value = df[yProperties].to_numpy().max() max_value = max_value + 0.2 * (max_value - min_value) if "title" not in kwargs: title = "" else: title = kwargs["title"] if "legend_location" not in kwargs: legend_location = "top-left" else: legend_location = kwargs["legend_location"] x_data = list(df[xProperty]) y_data = df[yProperties].values.T.tolist() plt.bar(x_data, y_data) fig = plt.figure( title=title, legend_location=legend_location, ) if "width" in kwargs: fig.layout.width = kwargs["width"] if "height" in kwargs: fig.layout.height = kwargs["height"] if "labels" in kwargs: labels = kwargs["labels"] else: labels = yProperties if "display_legend" not in kwargs: display_legend = True else: display_legend = kwargs["display_legend"] bar_chart = plt.bar(x_data, y_data, labels=labels, display_legend=display_legend) bar_chart.type = "grouped" if "colors" in kwargs: bar_chart.colors = kwargs["colors"] if "xlabel" in kwargs: plt.xlabel(kwargs["xlabel"]) if "ylabel" in kwargs: plt.ylabel(kwargs["ylabel"]) plt.ylim(min_value, max_value) if "xlabel" in kwargs and ("ylabel" in kwargs): bar_chart.tooltip = Tooltip( fields=["x", "y"], labels=[kwargs["xlabel"], kwargs["ylabel"]]) else: bar_chart.tooltip = Tooltip(fields=["x", "y"]) plt.show() except Exception as e: raise Exception(e)
def create_output_widgets(self): # create the output widgets self.tasks_done_bar = widgets.IntProgress( value=0, min=0, max=self.ending_task - self.starting_task, description='Percent of tasks complete:', style={'description_width': 'initial'}, orientation='horizontal') self.tasks_idling = widgets.IntProgress( value=0, min=0, max=self.max_workers, description='Percent of workers idle', style={'description_width': 'initial'}, orientation='horizontal') self.workers_connected = widgets.IntProgress( value=0, min=0, max=self.max_workers, description='Percent of max workers connected', style={'description_width': 'initial'}, orientation='horizontal') self.status_message = widgets.Text( value='Initializing workers', description='Workqueue Status', disabled=True, style={'description_width': 'initial'}, orientation='horizontal') self.worker_time = widgets.Text( description='Time spent by workers (Seconds)', disabled=True, style={'description_width': 'initial'}, orientation='horizontal') self.tasks_per_second = widgets.FloatText( value=0, description='Average tasks complete per second', style={'description_width': 'initial'}, disabled=True) self.task_output_storage = [] # clear output from previous runs # display output display( widgets.HBox( [self.status_message, self.tasks_per_second, self.worker_time])) display( widgets.HBox([ self.tasks_done_bar, self.workers_connected, self.tasks_idling ])) # initialize real time task display output for i in range(self.starting_task, self.ending_task + self.max_workers + 10): self.task_output_storage.append( widgets.ToggleButton( value=False, description=str(i - 2), disabled=False, button_style= '', # 'success', 'info', 'warning', 'danger' or '' layout=widgets.Layout(width='20%', height='20px'))) horizontal_boxes = 15 vertical_boxes = (self.ending_task - self.starting_task) // horizontal_boxes + 1 vertical_temp = [] # actually place the real time display output on screen for j in range(vertical_boxes): horizontal_temp = [] for i in range(horizontal_boxes): if (i + j * horizontal_boxes + 2) > (self.ending_task): break horizontal_temp.append( self.task_output_storage[i + j * horizontal_boxes + 2]) vertical_temp.append(widgets.HBox(horizontal_temp)) display(widgets.VBox(vertical_temp)) self.starting_time = time.perf_counter() # reset starting time # below are just properties of the worker time pie chart fig = plt.figure(title="Work Queue Time Distribution (Milliseconds)") self.pie = plt.pie(sizes=[0, 0, 0], labels=[ 'Work Queue internal', 'Waiting for workers', 'Application' ], display_values=True, values_format=".1f", display_labels='outside') self.pie.stroke = "black" self.pie.colors = ["tomato", "lawngreen", "gray"] self.pie.radius = 150 self.pie.inner_radius = 60 self.pie.label_color = 'orangered' self.pie.font_size = '20px' self.pie.font_weight = 'bold' plt.show()
def submit_clicked(b): with output_widget: output_widget.clear_output() print('Computing...') Map.default_style = {'cursor': 'wait'} try: admin1_id = admin1_widget.value admin2_id = admin2_widget.value band1 = first_band.value band2 = second_band.value selected_year = year_widget.value threshold = nd_threshold.value bands = band_combo.value.split('/') apply_fmask = fmask_widget.value palette = nd_color.value use_aoi = aoi_widget.value download = download_widget.value if use_aoi: if Map.user_roi is not None: roi = Map.user_roi layer_name = 'User drawn AOI' geom = roi else: output_widget.clear_output() print('No user AOI could be found.') return else: statefp = ee.Feature(states.filter(ee.Filter.eq('NAME', admin1_id)).first()).get('STATEFP') roi = fc.filter(ee.Filter.And(ee.Filter.eq('NAME', admin2_id), ee.Filter.eq('STATEFP', statefp))) layer_name = admin1_id + '-' + admin2_id geom = roi.geometry() Map.layers = Map.layers[:4] Map.addLayer(ee.Image().paint(geom, 0, 2), {'palette': 'red'}, layer_name) images = geemap.landsat_timeseries(roi=roi, start_year=1984, end_year=2020, start_date='01-01', end_date='12-31', apply_fmask=apply_fmask) nd_images = images.map(lambda img: img.normalizedDifference([band1, band2])) result_images = nd_images.map(lambda img: img.gt(threshold)) selected_image = ee.Image(images.toList(images.size()).get(selected_year - 1984)) selected_result_image = ee.Image(result_images.toList(result_images.size()).get(selected_year - 1984)).selfMask() vis_params = { 'bands': bands, 'min': 0, 'max': 3000 } Map.addLayer(selected_image, vis_params, 'Landsat ' + str(selected_year)) Map.addLayer(selected_result_image, {'palette': palette}, 'Result ' + str(selected_year)) def cal_area(img): pixel_area = img.multiply(ee.Image.pixelArea()).divide(1e4) img_area = pixel_area.reduceRegion(**{ 'geometry': geom, 'reducer': ee.Reducer.sum(), 'scale': 1000, 'maxPixels': 1e12, 'bestEffort': True }) return img.set({'area': img_area}) areas = result_images.map(cal_area) stats = areas.aggregate_array('area').getInfo() x = list(range(1984, 2021)) y = [item.get('nd') for item in stats] fig = plt.figure(1) fig.layout.height = '270px' plt.clear() plt.plot(x, y) plt.title('Temporal trend (1984-2020)') plt.xlabel('Year') plt.ylabel('Area (ha)') output_widget.clear_output() plt.show() if download: out_dir = os.path.join(os.path.expanduser('~'), 'Downloads') out_name = 'chart_' + geemap.random_string() + '.csv' out_csv = os.path.join(out_dir, out_name) if not os.path.exists(out_dir): os.makedirs(out_dir) with open(out_csv, 'w') as f: f.write('year, area (ha)\n') for index, item in enumerate(x): line = '{},{:.2f}\n'.format(item, y[index]) f.write(line) link = geemap.create_download_link( out_csv, title="Click here to download the chart data: ") display(link) except Exception as e: print(e) print('An error occurred during computation.') Map.default_style = {'cursor': 'default'}
import numpy as np import bqplot.pyplot as plt size = 100 plt.figure(title="Scatter plot with colors") plt.scatter(np.random.randn(size), np.random.randn(size), color=np.random.randn(size)) plt.show()
b = b * 30 x_sc = bqplot.LinearScale() y_sc = bqplot.LinearScale() ax_x = bqplot.Axis(scale=x_sc, label="X-value") ax_y = bqplot.Axis(scale=y_sc, label="Y-value", orientation='vertical') scatters1 = bqplot.Scatter(x=a[:, 0], y=a[:, 1], scales={ 'x': x_sc, 'y': y_sc }, default_size=5, colors=["navy"], sizes=[10]) scatters2 = bqplot.Scatter(x=b[:, 0], y=b[:, 1], scales={ 'x': x_sc, 'y': y_sc }, default_size=2, colors=['orange'], sizes=[5]) fig = bqplot.Figure(marks=[scatters1, scatters2], axes=[ax_x, ax_y]) plt.show(fig)
def plot(self, x, y, plot_type=None, overlay=False, position='bottomright', min_width=None, max_width=None, min_height=None, max_height=None, **kwargs): """Creates a plot based on x-array and y-array data. Args: x (numpy.ndarray or list): The x-coordinates of the plotted line. y (numpy.ndarray or list): The y-coordinates of the plotted line. plot_type (str, optional): The plot type can be one of "None", "bar", "scatter" or "hist". Defaults to None. overlay (bool, optional): Whether to overlay plotted lines on the figure. Defaults to False. position (str, optional): Position of the control, can be ‘bottomleft’, ‘bottomright’, ‘topleft’, or ‘topright’. Defaults to 'bottomright'. min_width (int, optional): Min width of the widget (in pixels), if None it will respect the content size. Defaults to None. max_width (int, optional): Max width of the widget (in pixels), if None it will respect the content size. Defaults to None. min_height (int, optional): Min height of the widget (in pixels), if None it will respect the content size. Defaults to None. max_height (int, optional): Max height of the widget (in pixels), if None it will respect the content size. Defaults to None. """ if self.plot_widget is not None: plot_widget = self.plot_widget else: plot_widget = widgets.Output(layout={'border': '1px solid black'}) plot_control = WidgetControl(widget=plot_widget, position=position, min_width=min_width, max_width=max_width, min_height=min_height, max_height=max_height) self.plot_widget = plot_widget self.plot_control = plot_control self.add_control(plot_control) if max_width is None: max_width = 500 if max_height is None: max_height = 300 if (plot_type is None) and ('markers' not in kwargs.keys()): kwargs['markers'] = 'circle' with plot_widget: try: fig = plt.figure(1, **kwargs) if max_width is not None: fig.layout.width = str(max_width) + 'px' if max_height is not None: fig.layout.height = str(max_height) + 'px' plot_widget.clear_output(wait=True) if not overlay: plt.clear() if plot_type is None: if 'marker' not in kwargs.keys(): kwargs['marker'] = 'circle' plt.plot(x, y, **kwargs) elif plot_type == 'bar': plt.bar(x, y, **kwargs) elif plot_type == 'scatter': plt.scatter(x, y, **kwargs) elif plot_type == 'hist': plt.hist(y, **kwargs) plt.show() except Exception as e: print(e) print("Failed to create plot.")