def create_map_widgets(self, title_list, map, inventory_df): """Create and add map widgets into map. Args: title_list (list): A list of the file names in the folder. """ map_dropdown = ipywgt.Dropdown(description='Outputfile - 1', options=title_list, width=500) file_control1 = ipylft.WidgetControl(widget=map_dropdown, position='bottomleft') # use the following line when it needs to have another dropdown # dropdown2 = ipywgt.Dropdown(description = 'Outputfile - 2', options = title_list2, width=500) # file_control2 = ipylft.WidgetControl(widget=dropdown2, position='bottomleft') button = ipywgt.Button(description='Generate Map', button_style='info') button.on_click(self.on_button_clicked) map_control = ipylft.WidgetControl(widget=button, position='bottomleft') map.add_control(ipylft.LayersControl(position='topright', style='info')) map.add_control(ipylft.FullScreenControl(position='topright')) map.add_control(map_control) # map.add_control(file_control2) # use the line when it needs to have extra dropdown map.add_control(file_control1) # set global for button click self.map_dropdown = map_dropdown self.inventory_df = inventory_df self.inventory_json = json.loads(inventory_df.to_json()) return map
def _add_controls(self): ibc = ipyl.WidgetControl(widget=self.img_button, position='topleft') self.map.add_control(ibc) ipc = ipyl.WidgetControl(widget=self.img_pane, position='topleft') self.map.add_control(ipc)
def _add_controls(self): vbc = ipyl.WidgetControl( widget=self.viz_button, position='topleft' ) self.map.add_control(vbc) vpc = ipyl.WidgetControl( widget=self.viz_pane, position='topleft' ) self.map.add_control(vpc)
def _add_controls(self): lbc = ipyl.WidgetControl( widget=self.layer_button, position='bottomright' ) self.map.add_control(lbc)
def build_us_cntymap(dataframe, colname): global geojson_cnty, this_cnty_colname, cnty_overlay, county_data_dict global cnty_layer, cnty_legend, cnty_control global MapsVDict, geojson_cnty, mapcenter, mapzoom, loc_dict # This function builds a US Choropleth Map (but doesn't display it) for the county-level # data provided. # Load data needed to build either kind of map build_us_genericmap() # Build location dictionary if doesn't yet exist try: loc_dict except NameError: loc_dict = BuildLocationDict(dataframe) # ipyleaflet requires a dictionary for the choro_data field/the variable to be visualized, # so convert the Pandas data series into the appropriate dictionary setting keys to postal # codes used in geojson_states county_data_dict = get_cnty_dict(dataframe, colname) # Determine range of values for colormap, then define colormap (need to also pass # max/min values to Choropleth builder or they are ignored). Set up legend dictionary # to show this range. (minval, maxval) = set_cm_limits(county_data_dict) cmap = BuildColormap(minval, maxval) legendDict = BuildLegendDict(minval, maxval, cmap) # Creating the map cnty_map = lf.Map(center=mapcenter, zoom=mapzoom) # Draw a functional counties layer cnty_layer = lf.Choropleth( geo_data=geojson_cnty, choro_data=scrub(county_data_dict), key_on='id', # Below here is some formatting/coloring from the documentation colormap=cmap, value_min=minval, value_max=maxval, border_color=map_border_color, hover_style=map_hover_style, style=map_style) cnty_map.add_layer(cnty_layer) # Display a legend cnty_legend = lf.LegendControl(legendDict, name="Legend", position="bottomleft") cnty_map.add_control(cnty_legend) # Display data in overlay this_cnty_colname = colname cnty_overlay = widgets.HTML("Hover over Location for Details") cnty_control = lf.WidgetControl(widget=cnty_overlay, position='topright') cnty_map.add_control(cnty_control) cnty_layer.on_hover(update_cnty_overlay) return (cnty_map, cnty_legend, cnty_overlay)
def create_legend(self): legend = linear.YlOrRd_04.scale(0, self.vmax_val) self.m.colormap = legend out = ipywgt.Output(layout={'border': '1px solid black'}) with out: display(legend) widget_control = ipylft.WidgetControl(widget=out, position='topright') m.add_control(widget_control) display(m)
def yearSlider(self, minYear, maxYear, value): """ Generate year slider for map use given available years """ yearSlider = IntSlider(description='Year:', min=minYear, max=maxYear, value=value) yearWidget = ipyleaflet.WidgetControl( widget=yearSlider, position='topright') return yearSlider, yearWidget
def dataBox(self): """ generate data box for map use """ data_box = HTML( value="click to show data" ) data_widget = ipyleaflet.WidgetControl( widget=data_box, position='topright') return data_box, data_widget
def create_map_widgets(self, m, outfiles): self.dropdown1 = ipywgt.Dropdown(description='Outputfile - 1', options=outfiles, width=500) file_control1 = ipylft.WidgetControl(widget=self.dropdown1, position='bottomleft') # self.dropdown2 = ipywgt.Dropdown(description = 'Outputfile - 2', options = outfiles, width=500) # file_control2 = ipylft.WidgetControl(widget=self.dropdown2, position='bottomleft') button = ipywgt.Button(description='Generate Map', button_style='info') button.on_click(self.on_button_clicked) generatemap_control = ipylft.WidgetControl(widget=button, position='bottomleft') m.add_control(ipylft.LayersControl(position='topright', style='info')) m.add_control(ipylft.FullScreenControl(position='topright')) m.add_control(generatemap_control) # m.add_control(file_control2) m.add_control(file_control1)
def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) drop_Agg = widg.Dropdown(description="Aggregation method",options={"Compas":"******", "Compas asymétrique":"compas_asym", 'AGAT':"agat", 'AGAT asymétrique':"agat_asym"}) drop_Agg.value = self.distance_choice drop_Agg.observe(self.change_aggregate,"value") self.m.add_control(ipyl.WidgetControl(widget = drop_Agg, position="topright"))
def attrDropdown(self): """ Generate attribute dropdown for map use """ dropdown = Dropdown( options=set(self.choro_data.keys()), value=self.selectedAttr, description='Attribute:', disabled=False, ) dropdown_wgt = ipyleaflet.WidgetControl( widget=dropdown, position='topright') return dropdown, dropdown_wgt
def __init__(self, distance_choice="agat"): self.m = ipyl.Map(center=(45, 0), zoom=7, layout={"height": "500px"}) # Date date_picker = widg.DatePicker(value=dt.datetime(2020, 1, 26)) self._date = date_picker.value date_picker.observe(self.change_date, "value") self.step = 0 self.distance_choice = distance_choice variable_picker = widg.Dropdown( value="WWMF", options=["WWMF", "WME", "W1", "PRECIP", "T"]) variable_picker.observe(self.variable_change, "value") dept_picker = widg.Dropdown(value="41", options={ "Finistère": "29", "Isère": "38", "Hérault": "34", "Loire-et-cher": "41" }) dept_picker.observe(self.change_dept, "value") self.dept = dept_picker.value self._variable = variable_picker.value # Open dataset and mask self.open_file() # Add other widgets self.legend = widg.Image(layout=widg.Layout(height="430px")) self.html1 = HTML(''' <h4>Type de temps</h4> Hover over a pixel ''') self.html1.layout.margin = '0px 20px 20px 20px' # Add controls control1 = WidgetControl(widget=self.html1, position='bottomright') self.m.add_control(control1) self.m.add_control(ipyl.LayersControl()) slider = widg.IntSlider(min=0, max=len(self.da.step) - 1, step=1, value=0, description="step") slider.observe(self.change_step, 'value') self.m.add_control( ipyl.WidgetControl(widget=widg.VBox( [date_picker, slider, variable_picker, dept_picker]), position="topright")) self.m.add_control(ipyl.FullScreenControl()) self.render() super().__init__([self.m, self.legend])
def _interact_layer_button(self, b): ''' toggle layers pane ''' if self.layer_button.button_style == '': self.layer_button.button_style = 'success' self.layer_control = ipyl.WidgetControl( widget=self.layer_window, position='bottomright' ) self.map.add_control(self.layer_control) else: self.layer_button.button_style = '' self.map.remove_control(self.layer_control)
def _interact_layer_remove(self, b): ''' remove selected layer ''' self.remove(self.get_selected()) self.map.remove_control(self.layer_control) self._build_layer_window() self.layer_control = ipyl.WidgetControl( widget=self.layer_window, position='bottomright' ) self.map.add_control(self.layer_control) self._update_selected()
def _interact_layer_add(self, b): ''' add a new layer ''' name = 'layer {}'.format(self.ctr) self.add(name, Sentinel2()) self.map.remove_control(self.layer_control) self._build_layer_window() self.layer_control = ipyl.WidgetControl( widget=self.layer_window, position='bottomright' ) self.map.add_control(self.layer_control) self._update_selected()
def add_layer(self, l): layer, legend, profile = l.get() # add layer to map self.map.add_layer(layer) # add legend to map if necessary if "Colormap" in profile["task"]["options"]: t = profile["task"]["options"]["Colormap"] if t not in self.legend_list and legend is not None: legend_ctrl = ill.WidgetControl( widget=legend, position="topright" ) self.map.add_control(legend_ctrl) self.legend_list.append(t)
def __init__(self, map, position="topright", layout=None): """ Construct a PixelInspector and attach it to a map. Parameters ---------- map: ipyleaflet.Map, workflows.interactive.MapApp The map to attach to position: str, optional, default "topright" Where on the map to display the values table layout: ipywidgets.Layout, optional Layout for the values table. Defaults to ``Layout(max_height="350px", overflow="scroll", padding="4px")`` """ if layout is None: layout = ipywidgets.Layout(max_height="350px", overflow="scroll", padding="4px") super().__init__([], layout=layout) self.layout.grid_template_columns = "min-content " * (1 + self.n_bands) # awkwardly handle MapApp without circularly importing it for an isinstance check try: sub_map = map.map except AttributeError: pass else: if isinstance(sub_map, ipyleaflet.Map): map = sub_map self._map = map self.marker.map = map self._inspector_rows_by_layer_id = weakref.WeakValueDictionary() self._layers_changed({"old": [], "new": map.layers}) # initialize with the current layers on the map, if any self._control = ipyleaflet.WidgetControl(widget=self, position=position) map.add_control(self._control) map.observe(self._layers_changed, names=["layers"], type="change") map.on_interaction(self._handle_click) self._orig_cursor = map.default_style.cursor map.default_style.cursor = "crosshair"
def dropdown_shapefile(self, *args): if self.control_selectDownload.value == 'Watershed': self.control_shapefileText = ipywidgets.Text( placeholder='Insert Shapefile PATH HERE') hbox_shape = ipywidgets.HBox( [self.control_shapefileText, self.control_shapefileButtom]) widget_control04 = ipyleaflet.WidgetControl(widget=hbox_shape, position='bottomright') self.m01.add_control(widget_control04) else: try: self.control_shapefileText.close() self.control_shapefileButtom.close() self.m01.remove_control(widget_control04) self.m01.remove_layer(self.geo_data) except: pass
def _interact_hist_button(self, b): ''' compute a histogram and show result when pressed ''' if self.hist_button.button_style == '': self.hist_button.button_style = 'warning' self._build_hist_pane() # add hist pane control directly to map # TODO: this is kind of ugly self.hist_control = ipyl.WidgetControl(widget=self.hist_pane, position='topleft') self.map.add_control(self.hist_control) self.hist_button.button_style = 'success' else: self.hist_button.button_style = '' [l.unlink() for l in self.hist_links] self.map.remove_control(self.hist_control)
city_widget = widgets.Text( #value='', placeholder='e.g. Jacksonville', description='City:', disabled=False) severity_widget = widgets.BoundedIntText(value=1, min=1, max=4, step=1, description='Severity', disabled=False) # Create widget control state_widget_control = leaflet.WidgetControl(widget=state_widget, position='topright') city_widget_control = leaflet.WidgetControl(widget=city_widget, position='topright') severity_widget_control = leaflet.WidgetControl(widget=severity_widget, position='topright') # Input Param print('Setting Input Parameters') state = 'FL' city = 'Jacksonville' severity = 2 color_by_severity = {1: 'green', 2: 'blue', 3: 'yellow', 4: 'red'} color = color_by_severity[severity] # Filter data by input param print('Filtering Input Data')
def __init__(self, projection, **kwargs): # set default keyword arguments kwargs.setdefault('zoom', False) kwargs.setdefault('scale', True) kwargs.setdefault('cursor', True) kwargs.setdefault('center', (39, -108)) kwargs.setdefault('color', 'green') # create basemap in projection if (projection == 'Global'): self.map = ipyleaflet.Map( center=kwargs['center'], zoom=9, max_zoom=15, basemap=ipyleaflet.basemaps.Esri.WorldTopoMap) self.map.add_layer(basemaps.GLIMS.glaciers) elif (projection == 'North'): self.map = ipyleaflet.Map(center=(90, 0), zoom=5, max_zoom=24, basemap=basemaps.Esri.ArcticOceanBase, crs=projections.EPSG5936) self.map.add_layer(basemaps.Esri.ArcticOceanReference) elif (projection == 'South'): self.map = ipyleaflet.Map(center=(-90, 0), zoom=2, max_zoom=9, basemap=basemaps.Esri.AntarcticBasemap, crs=projections.EPSG3031) # add control for zoom if kwargs['zoom']: zoom_slider = ipywidgets.IntSlider(description='Zoom level:', min=self.map.min_zoom, max=self.map.max_zoom, value=self.map.zoom) ipywidgets.jslink((zoom_slider, 'value'), (self.map, 'zoom')) zoom_control = ipyleaflet.WidgetControl(widget=zoom_slider, position='topright') self.map.add_control(zoom_control) # add scale bar if kwargs['scale']: scale_control = ipyleaflet.ScaleControl(position='topright') self.map.add_control(scale_control) # add label for cursor position if kwargs['cursor']: self.cursor = ipywidgets.Label() label_control = ipyleaflet.WidgetControl(widget=self.cursor, position='bottomright') self.map.add_control(label_control) # keep track of cursor position self.map.on_interaction(self.handle_interaction) # add control for drawing polygons or bounding boxes draw_control = ipyleaflet.DrawControl(polyline={}, circlemarker={}, edit=False) shapeOptions = { 'color': kwargs['color'], 'fill_color': kwargs['color'] } draw_control.rectangle = dict(shapeOptions=shapeOptions, metric=['km', 'm']) draw_control.polygon = dict(shapeOptions=shapeOptions, allowIntersection=False, showArea=True, metric=['km', 'm']) # create regions self.regions = [] draw_control.on_draw(self.handle_draw) self.map.add_control(draw_control)
def controls_on_Map(self): control_layer = ipyleaflet.LayersControl(position='topright') self.m01.add_control(control_layer) control_fullscreen = ipyleaflet.FullScreenControl() self.m01.add_control(control_fullscreen) self.control_draw = ipyleaflet.DrawControl() self.m01.add_control(self.control_draw) control_scale = ipyleaflet.ScaleControl(position='bottomleft') self.m01.add_control(control_scale) slider_heatmap_radius = ipywidgets.IntSlider(description='Radius', min=1, max=50, value=15) ipywidgets.jslink((slider_heatmap_radius, 'value'), (self.heatmap_all, 'radius')) widget_control01 = ipyleaflet.WidgetControl( widget=slider_heatmap_radius, position='bottomright') self.m01.add_control(widget_control01) self.date_slider = ipywidgets.SelectionSlider(options=pd.date_range( start='2000-01-01', end='2020-01-01', freq='M').to_numpy()) self.date_slider.observe(self.date_location, names='value') ipywidgets.jslink((slider_heatmap_radius, 'value'), (self.heatmap_byLast, 'radius')) widget_control02 = ipyleaflet.WidgetControl(widget=self.date_slider, position='topright') self.m01.add_control(widget_control02) self.control_selectDownload = ipywidgets.Dropdown( options=['Watershed', 'All', 'byDate'], value=None, description='Select type:') self.control_selectDownload.observe(self.dropdown_shapefile, names='value') self.control_selectDownload.observe(self.shapefile_buttom, names='value') box_layout = ipywidgets.Layout(display='flex', flex_flow='column', align_items='stretch', width='100%') self.control_pathDownload = ipywidgets.Text( placeholder='Write your PATH to Download HERE.') vbox01 = ipywidgets.VBox( [self.control_selectDownload, self.control_pathDownload]) self.control_buttonDownload = ipywidgets.Button(description='Download') self.control_loadingDownload = ipywidgets.FloatProgress(min=0, max=1, value=0) self.control_choiceDownload = ipywidgets.RadioButtons( options=['Rain', 'Flow']) hbox01 = ipywidgets.HBox( [self.control_choiceDownload, self.control_buttonDownload], layout=box_layout) vbox02 = ipywidgets.VBox( [vbox01, hbox01, self.control_loadingDownload], layout=box_layout) widget_control03 = ipyleaflet.WidgetControl(widget=vbox02, position='bottomright') self.m01.add_control(widget_control03) # control_progressDownload = ipywidgets.FloatProgress() self.control_shapefileButtom = ipywidgets.Button( description='Visualizar')
def add_widget(widget, pos, margin='0px 0px 0px 0px'): widget.layout.margin = margin widget_control = ipyleaflet.WidgetControl(widget=widget, position=pos) m.add_control(widget_control)
def plot_geo_data_cluster(data, geom_column, title_columns): def date_filter(df, date_range, timestamp_column: str): dates = pd.to_datetime(df[timestamp_column]).apply(pd.Timestamp.date) return df[(date_range[0] <= dates) & (dates <= date_range[1])] def toggle_tweets_table_visibility(change): app_state['is_in_bounds'] = None if change['old'] and not change['new']: tweets_table.value, app_state['is_in_bounds'] = '', None else: update_range() def update_range(*_): def in_bounds(loc): return all(bounds[0] < loc) and all(loc < bounds[1]) if len(m.bounds) == 0: return bounds = np.array(m.bounds) locs = app_state['filtered_data'][geom_column].apply(_wkb_hex_to_point) is_in_bounds = locs.apply(in_bounds) if app_state['is_in_bounds'] is None or not np.array_equal( is_in_bounds, app_state['is_in_bounds']): if is_in_bounds.sum() > 0: ts_plot = _get_ts_count_plot( app_state['full_data'], app_state['filtered_data'][is_in_bounds], app_state['timestamp_column']) time_slider_box.children = [ ts_plot, *time_slider_box.children[1:] ] if tweets_table_cb.value: tweets_table.value = app_state['filtered_data'].loc[ is_in_bounds, title_columns].reset_index(drop=True).to_html( formatters={'media': _to_html}, escape=False, na_rep='', index=False) else: tweets_table.value = '' tweets_table_cb.description = 'Show {} Tweets'.format( is_in_bounds.sum()) app_state['is_in_bounds'] = is_in_bounds def change_date_range(change): def filter_markers(marker_cluster: ipyleaflet.MarkerCluster, min_date, max_date): marker_cluster.markers = [ m for m in app_state['markers'] if min_date <= m.timestamp.date() <= max_date ] filtered_data = date_filter( app_state['full_data'], change['new'], timestamp_column=app_state['timestamp_column']) app_state['filtered_data'] = filtered_data heatmap.locations = list( filtered_data[geom_column].apply(_wkb_hex_to_point).values) filter_markers(marker_clusters, *change['new']) update_range() m = ipyleaflet.Map(center=(51, 10), zoom=4, scroll_wheel_zoom=True, zoom_control=False) m.layout.height = '900px' app_state = dict(is_in_bounds=None, full_data=data.dropna(subset=[geom_column]), filtered_data=data.dropna(subset=[geom_column]), timestamp_column=_get_timestap_column(data)) info_box_default_text = 'Hover over a marker' info_box = widgets.HTML(info_box_default_text, layout=Layout(margin='10px', overflow='scroll_hidden')) m.add_control( ipyleaflet.WidgetControl(widget=widgets.HBox( [info_box], layout=Layout(max_height='300px')), position='topright')) loading_wrapper = _loading_wrapper_factory(info_box, info_box_default_text) tweets_table = widgets.HTML(layout=widgets.Layout( overflow='scroll_hidden')) tweets_table_box = widgets.HBox([tweets_table], layout=Layout(max_height='500px', overflow_y='auto', max_width='900px')) tweets_table_cb = widgets.Checkbox(value=False) tweets_table_cb.observe(toggle_tweets_table_visibility, type='change', names=('value', )) tweets_box = widgets.VBox([tweets_table_cb, tweets_table_box]) m.add_control( ipyleaflet.WidgetControl(widget=tweets_box, position='bottomleft')) time_slider = get_time_slider(app_state['full_data']) time_slider.observe(loading_wrapper(change_date_range), type='change', names=('value', )) time_slider.layout.margin, time_slider.description = '0px 5px 0px 5px', '' ts_plot = _get_ts_count_plot(data, app_state['filtered_data'], app_state['timestamp_column']) time_slider_box = widgets.VBox([ts_plot, time_slider]) m.add_control( ipyleaflet.WidgetControl(widget=time_slider_box, position='topleft')) marker_clusters = get_marker_cluster( app_state['filtered_data'], geom_column, title_columns=title_columns, info_box=info_box, timestamp_column=app_state['timestamp_column']) app_state['markers'] = marker_clusters.markers heatmap_locations = list(app_state['filtered_data'][geom_column].apply( _wkb_hex_to_point).values) heatmap = ipyleaflet.Heatmap(name='Heatmap', min_opacity=.1, blur=20, radius=20, max_zoom=12, locations=heatmap_locations) m.add_layer(heatmap) m.add_layer(marker_clusters) change_date_range(dict(new=time_slider.value)) m.add_control(ipyleaflet.LayersControl()) m.add_control(ipyleaflet.FullScreenControl()) m.observe(update_range) display(m)
def __init__(self, projection='Global', **kwargs): # set default keyword arguments kwargs.setdefault('attribution', True) kwargs.setdefault('zoom', 1) kwargs.setdefault('zoom_control', False) kwargs.setdefault('scale_control', False) kwargs.setdefault('cursor_control', True) kwargs.setdefault('layer_control', True) kwargs.setdefault('center', (39, -108)) # create basemap in projection if (projection == 'Global'): self.map = ipyleaflet.Map( center=kwargs['center'], zoom=kwargs['zoom'], max_zoom=15, attribution_control=kwargs['attribution'], basemap=ipyleaflet.basemaps.Esri.WorldTopoMap) self.crs = 'EPSG:3857' elif (projection == 'North'): self.map = ipyleaflet.Map( center=kwargs['center'], zoom=kwargs['zoom'], max_zoom=24, attribution_control=kwargs['attribution'], basemap=ipyleaflet.basemaps.Esri.ArcticOceanBase, crs=projections.EPSG5936.Basemap) self.map.add_layer(ipyleaflet.basemaps.Esri.ArcticOceanReference) self.crs = 'EPSG:5936' elif (projection == 'South'): self.map = ipyleaflet.Map( center=kwargs['center'], zoom=kwargs['zoom'], max_zoom=9, attribution_control=kwargs['attribution'], basemap=ipyleaflet.basemaps.Esri.AntarcticBasemap, crs=projections.EPSG3031.Basemap) self.crs = 'EPSG:3031' # add control for layers if kwargs['layer_control']: self.layer_control = ipyleaflet.LayersControl(position='topleft') self.map.add_control(self.layer_control) self.layers = self.map.layers # add control for zoom if kwargs['zoom_control']: zoom_slider = ipywidgets.IntSlider(description='Zoom level:', min=self.map.min_zoom, max=self.map.max_zoom, value=self.map.zoom) ipywidgets.jslink((zoom_slider, 'value'), (self.map, 'zoom')) zoom_control = ipyleaflet.WidgetControl(widget=zoom_slider, position='topright') self.map.add_control(zoom_control) # add control for spatial scale bar if kwargs['scale_control']: scale_control = ipyleaflet.ScaleControl(position='topright') self.map.add_control(scale_control) # add control for cursor position if kwargs['cursor_control']: self.cursor = ipywidgets.Label() cursor_control = ipyleaflet.WidgetControl(widget=self.cursor, position='bottomleft') self.map.add_control(cursor_control) # keep track of cursor position self.map.on_interaction(self.handle_interaction) # add control for marker if kwargs['marker_control']: # add marker with default location self.marker = ipyleaflet.Marker(location=kwargs['center'], draggable=True) self.map.add_layer(self.marker) # add text with marker location self.marker_text = ipywidgets.Text( value='{0:0.8f},{1:0.8f}'.format(*kwargs['center']), description='Lat/Lon:', disabled=False) # watch marker widgets for changes self.marker.observe(self.set_marker_text) self.marker_text.observe(self.set_marker_location) self.map.observe(self.set_map_center) # add control for marker location marker_control = ipyleaflet.WidgetControl(widget=self.marker_text, position='bottomright') self.map.add_control(marker_control)
def add_current_to_map(self): """ Add the currently-selected `~.Workflow` to ``wf.map`` or ``self.map``, if possible. The `~.Workflow` must be one of these types: * `~.geospatial.Image` * `~.ImageCollection`, in which case it's mosaicked * `~.Function`, in which case it must return an `~.geospatial.Image` or `~.ImageCollection`, and only take `~.Int`, `~.Float`, `~.Str`, `~.Bool`, or `~.Datetime` as parameters. A widget will be added to the map to control the function arguments interactively. These `~.VersionedGraft.labels` set on the version will customize the map: * ``default_bands``: space-separated string, like ``"red green blue"``. These bands will be picked from the `~.geospatial.Image` before displaying. * ``colormap``: str, like ``"viridis"``. This colormap will be applied to the layer. * ``scales``: JSON-encoded list, like ``"[[0, 0.5], [0, 0.5], [0, 0.5]]"``. This will be JSON-decoded, and used as the ``scales=`` argument to `~.Image.visualize`. If ``self.map`` is None, the layer will be added to ``wf.map``, otherwise to ``self.map``. Returns ------- lyr: WorkflowsLayer The layer added to the map Raises ------ ValueError If a Workflow and version are not currently selected. TypeError If the selected version is not one of the supported types. """ flow = self.current_flow vg = self.current_vg if not (flow and vg): raise ValueError("No Workflow and version currently selected") obj = vg.object parameters = {} if isinstance(obj, types.Function): param_names = [f"arg_{i}" for i in range(len(obj.arg_types))] graft_params = [ types.parameter(name, type_) for name, type_ in zip(param_names, obj.arg_types) ] try: parameters = { name: proxytype_to_widget[type_]() for name, type_ in zip(param_names, obj.arg_types) } except KeyError as e: raise TypeError( f"Cannot create interactive control for type {e}") obj = obj(*graft_params) if isinstance(obj, types.ImageCollection): obj = obj.mosaic() if isinstance(obj, types.Image): # NOTE(gabe): we LBYL for all these because accessing a missing key on the # fake proto dict object inserts it (like `setdefault`, not `get`), mutating `vg.labels` :( if "default_bands" in vg.labels: obj = obj.pick_bands(vg.labels["default_bands"]) colormap = vg.labels[ "colormap"] if "colormap" in vg.labels else None scales = json.loads( vg.labels["scales"]) if "scales" in vg.labels else None map_ = self.map if isinstance(map_, MapApp): map_ = map_.map lyr = obj.visualize( flow.name + ":" + vg.version, colormap=colormap, scales=scales, map=map_, **parameters, ) if len(parameters) > 0: # hack to display layer params on map ctrl = ipyleaflet.WidgetControl(widget=lyr.parameters.widget, position="bottomleft") map_.add_control(ctrl) def remove_ctrl_obs(layers_change): if lyr not in layers_change["new"]: map_.remove_control(ctrl) map_.unobserve(remove_ctrl_obs, names="layers") map_.observe(remove_ctrl_obs, names="layers") return lyr raise TypeError( f"Can only visualize Image, ImageCollection, and Functions that return those, not {vg.type.__name__}" )
def _add_controls(self): hbc = ipyl.WidgetControl(widget=self.hist_button, position='topleft') self.map.add_control(hbc)
def renderMap(self): '''creates ipyleaflet map''' self.m = ipyleaflet.Map(center=(33.66832279243364, 135.8861750364304), zoom=10) # self.grid options = [] options.extend(list(self.all_style_dict.keys())) option = options[0] dates = sorted([date for date in self.all_style_dict[option].keys()]) self.layer = ipyleaflet.Choropleth( geo_data=self.grid, choro_data=self.all_style_dict[option][str(dates[0])], colormap=linear.YlOrRd_04, style={ "fillOpacity": 0.8, "dashArray": "5, 5" }, ) self.m.add_layer(self.layer) self.time_slider = widgets.SelectionSlider( options=dates, value=dates[0], description="TimeStamp", disabled=False, continuous_update=False, orientation="horizontal", readout=True, ) self.time_slider.observe(self.on_slide, "value") widget_control_slider = ipyleaflet.WidgetControl( widget=self.time_slider, position="bottomright") self.m.add_control(widget_control_slider) # widgets.interact(update_map_time, timeStamp = self.time_slider) self.dropdown = widgets.Dropdown(options=options, value=option, description="Select layer") self.dropdown.observe(self.on_click, "value") widget_control = ipyleaflet.WidgetControl(widget=self.dropdown, position="topright") self.m.add_control(widget_control) self.color_range = widgets.IntRangeSlider( value=[self.layer.value_min, self.layer.value_max], min=self.layer.value_min, max=self.layer.value_max, step=1, description="ColorBar:", disabled=False, continuous_update=False, orientation="horizontal", readout=True, readout_format="d", ) self.zoom_to_location({"new": list(self.BBOXes.keys())[0]}) self.color_range.observe(self.on_selection, "value") widget_control = ipyleaflet.WidgetControl(widget=self.color_range, position="bottomright") self.m.add_control(widget_control) locations = widgets.Dropdown( options=self.BBOXes.keys(), value=list(self.BBOXes.keys())[0], description="Location:", ) locations.observe(self.zoom_to_location, "value") widget_control = ipyleaflet.WidgetControl(widget=locations, position="topright") self.m.add_control(widget_control) self.m.observe(self.zoom_out_to_target_bounds, "bounds") def compute_style(feature, colormap, choro_data): return { "fillColor": colormap(choro_data), "color": "white", "weight": random.randint(1, 3), } self.layer.style_callback = compute_style
def plotLeaflet(geoJson: dict, idToValue: dict, worldMap: lf.Map = None, includeEmpty: bool = True, labelFormat: str = "Id={0} - Value={1}", mapArgs: dict = {}, heatmapArgs: dict = {}) -> lf.Map: ''' Plot the choropleth on the map using the ipyleaflet library @idToValue: a dictionary containing mappings of ids to their associated values @worldMap: ipyleaflet Map object. If this is specified, the new heatmap will be addded to this object. Else a new Map object will be created @includeEmpty: true if we want to display the regions that have value 0. False otherwise @labelFormat: the string format of the text that is displayed when the mouse hovers over a polygon. The format must contain exactly 2 placeholders. Returns: map object ''' updatedIdToValue = __syncIdToValueDict(geoJson, idToValue) # If we don't display empty regions, we need to # create a new geo JSON that does NOT contain the # ids that have 0 value if (not includeEmpty): origGeoJson = geoJson geoJson = {"type": "FeatureCollection", "features": []} for idValue, value in updatedIdToValue.items(): if (value > 0): feature = getFeatureById(origGeoJson, idValue) geoJson["features"].append(feature) # Create the world map object if not specified if (worldMap is None): #basemap=lf.basemaps.CartoDB.DarkMatter, center=center, zoom=10 worldMap = lf.Map(**mapArgs) worldMap.add_control(lf.FullScreenControl()) worldMap.add_control(lf.LayersControl(position="topright")) # Default heatmap arguments minVal, maxVal = min(updatedIdToValue.values()), max( updatedIdToValue.values()) defaultHeatmapArgs = { "key_on": "id", "border_color": "black", "value_min": minVal, "value_max": maxVal, "style": { 'fillOpacity': 0.8, 'dashArray': '5, 5' }, "hover_style": { 'fillColor': 'purple', 'dashArray': '0', 'fillOpacity': 0.5 }, "name": "Choropleth", "colormap": linear.OrRd_06 } # Make a copy of the heatmapArgs, because we would add the default arguments # to this dict if the default arguments are not specified by the caller. Making # a copy prevents modifying the passed in dict object heatmapArgs = dict(heatmapArgs) for k, v in defaultHeatmapArgs.items(): if (k not in heatmapArgs): heatmapArgs[k] = v # Create the choropleth layer choroplethLayer = lf.Choropleth(geo_data=geoJson, choro_data=updatedIdToValue, **heatmapArgs) # Create a label widget to display the currently hovered polygon id & # the value associated with that id labelWidget = widgets.Label(value="") widgetControl = lf.WidgetControl(widget=labelWidget, position="bottomright") worldMap.add_control(widgetControl) def mouseout(*args, **kwargs): ''' Set the label value to empty string when the mouse exits a region ''' labelWidget.value = "" def hover(*args, **kwargs): ''' Set the label to the id & its associated value ''' idValue = kwargs["id"] labelWidget.value = labelFormat.format(idValue, updatedIdToValue[idValue]) # Register callbacks choroplethLayer.on_mouseout(mouseout) choroplethLayer.on_hover(hover) # Remove existing choropleth layer that has the same name choroplethName = heatmapArgs["name"] if ("name" in heatmapArgs) else "" removeLayerByType(worldMap, choroplethName, lf.Choropleth) worldMap.add_layer(choroplethLayer) return worldMap
def add_current_to_map(self): """ Add the currently-selected `~.Workflow` to ``wf.map`` or ``self.map``, if possible. The `~.Workflow` must be one of these types: * `~.geospatial.Image` * `~.ImageCollection` * `~.Function`, in which case it must return an `~.geospatial.Image` or `~.ImageCollection`, and only take `~.Int`, `~.Float`, `~.Str`, `~.Bool`, or `~.Datetime` as parameters. A widget will be added to the map to control the function arguments interactively. If the version has `~.VersionedGraft.viz_options`, the first `.VizOption` will be used to style the layer on the map. If ``self.map`` is None, the layer will be added to ``wf.map``, otherwise to ``self.map``. Returns ------- lyr: WorkflowsLayer The layer added to the map Raises ------ ValueError If a Workflow and version are not currently selected. If the currently-selected Workflow and version is incompatible with this client version. TypeError If the selected version is not one of the supported types. """ flow = self.current_flow vg = self.current_vg if not (flow and vg): raise ValueError("No Workflow and version currently selected") params = vg._make_params() # ^ NOTE(gabe): use `._make_params()` instead of `.params` so we get new params objects every time, # meaning new widget instances. otherwise, if the object was added to the map multiple times, # the widgets for every layer would seem to be linked (because they'd actually be the same objects). try: param_overrides = { p._name: proxytype_to_widget[type(p)]( name=p._name, **( # omg this is terrible. find a better way. dict(hide_deps_of=p) if isinstance( p, (types.Image, types.ImageCollection)) else {}), ) for p in params if not hasattr(p, "widget") } except KeyError as e: raise TypeError(f"Cannot create interactive control for type {e}") obj = vg.object if isinstance(obj, types.Function): obj = obj(*params) if isinstance(obj, (types.Image, types.ImageCollection)): if vg.viz_options: viz_option = vg.viz_options[0] if viz_option.bands: obj = obj.pick_bands(viz_option.bands) visualize_kwargs = { "checkerboard": viz_option.checkerboard, "colormap": viz_option.colormap, "scales": viz_option.scales, } if isinstance(obj, types.ImageCollection): visualize_kwargs["reduction"] = viz_option.reduction else: visualize_kwargs = {} map_ = self.map if isinstance(map_, MapApp): map_ = map_.map # if layer name already exists, don't overwrite it layer_name = f"{flow.name}:{vg.version}" i = 2 while any(layer.name == layer_name for layer in map_.layers): layer_name = f"{flow.name}:{vg.version} ({i})" i += 1 lyr = obj.visualize( layer_name, map=map_, **visualize_kwargs, **param_overrides, ) if len(params) > 0: # hack to display layer params on map labels = ipywidgets.VBox(children=[ ipywidgets.Label(getattr(p, "_label", "") or p._name) for p in params ]) widgets = ipywidgets.VBox(children=[ param_overrides.get(p._name, None) or p.widget for p in params ]) content = ipywidgets.HBox(children=[labels, widgets]) widget = ipywidgets.VBox( children=[ipywidgets.HTML(f"<b>{lyr.name}<b>"), content]) ctrl = ipyleaflet.WidgetControl(widget=widget, position="bottomleft") map_.add_control(ctrl) def remove_ctrl_obs(layers_change): if lyr not in layers_change["new"]: map_.remove_control(ctrl) map_.unobserve(remove_ctrl_obs, names="layers") map_.observe(remove_ctrl_obs, names="layers") return lyr raise TypeError( f"Can only visualize Image, ImageCollection, and Functions that return those, not {vg.type.__name__}" )