def display_composite_ipyleaflet(self, zoom=10): image = self.image.clip(ee.Geometry(self.polygon)) mapid = image.getMapId() tiles_url = self.ee_tiles.format(**mapid) tile_layer = ipyl.TileLayer(url=tiles_url, layers='collection', format='image/png', name=self.collection, opacity=1) polygon = ipyl.Polygon(locations=self.locations, color=self.color, fill_opacity=0., name='AoI') m = ipyl.Map(center=tuple(self.centroid), zoom=zoom) m.add_layer(tile_layer) m.add_layer(polygon) control = ipyl.LayersControl(position='topright') m.add_control(control) m.add_control(ipyl.FullScreenControl()) return m
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 plotHeatmap(locations: [tuple], heatmapName: str, worldMap: lf.Map = None, center: tuple = (0, 0), **kwargs) -> lf.Map: ''' Plot the given lat lon locations as a heatmap layer on a world map object @center: the center coordinate when creating the world map object @locations: list of latitude & longitude pair @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 @heatmapName: name of the heatmap layer Returns: a newly created Map object or the passed in worldMap object. ''' # Create map if it's not passed in to the function if (worldMap is None): baseMap = lf.basemaps.CartoDB.DarkMatter # lf.basemaps.Esri.WorldTopoMap worldMap = lf.Map(basemap=baseMap, center=center, zoom=10) worldMap.add_control(lf.FullScreenControl()) worldMap.add_control(lf.LayersControl(position='topright')) # Remove existing heatmap layer that has the same name removeLayerByType(worldMap, heatmapName, lf.Heatmap) # Add the heatmap layer to the world map object heatmap = lf.Heatmap(locations=locations, radius=20, name=heatmapName, **kwargs) worldMap.add_layer(heatmap) return worldMap
def demo_basemaps(location, base_demo): strava = ipl.basemap_to_tiles(ipl.basemaps.Strava.Winter) carto_dark = ipl.basemap_to_tiles(ipl.basemaps.CartoDB.DarkMatter) mapnik = ipl.basemap_to_tiles(ipl.basemaps.OpenStreetMap.Mapnik) black_white = ipl.basemap_to_tiles( ipl.basemaps.OpenStreetMap.BlackAndWhite) osm_hot = ipl.basemap_to_tiles(ipl.basemaps.OpenStreetMap.HOT) esri_image = ipl.basemap_to_tiles(ipl.basemaps.Esri.WorldImagery) esri_topo = ipl.basemap_to_tiles(ipl.basemaps.Esri.WorldTopoMap) esri_world = ipl.basemap_to_tiles(ipl.basemaps.Esri.NatGeoWorldMap) water_color = ipl.basemap_to_tiles(ipl.basemaps.Stamen.Watercolor) layer_demo = [ strava, carto_dark, mapnik, black_white, osm_hot, esri_image, esri_topo, esri_world, water_color ] for show_layer in layer_demo: base_demo.add_layer(show_layer) time.sleep(.95) base_demo.remove_layer(base_demo.layers[0]) time.sleep(1.2) base_demo.add_layer(mapnik) base_demo.add_control(ipl.LayersControl())
def get_gdf_map(datasets: list): """Get ipyleaflet map with list of datasets with geopandas . Args: datasets (list): a list of pyincore Dataset objects Returns: ipyleaflet.Map: ipyleaflet Map object """ # TODO: how to add a style for each dataset # TODO: performance issue. If there are a lot of data, the browser will crash geo_data_list = [] # (min_lat, min_lon, max_lat, max_lon) bbox_all = [9999, 9999, -9999, -9999] for dataset in datasets: # maybe this part should be moved to Dataset Class gdf = gpd.read_file(dataset.local_file_path) geo_data = ipylft.GeoData(geo_dataframe=gdf, name=dataset.metadata['title']) geo_data_list.append(geo_data) bbox = gdf.total_bounds bbox_all = GeoUtil.merge_bbox(bbox_all, bbox) m = GeoUtil.get_ipyleaflet_map(bbox_all) for entry in geo_data_list: m.add_layer(entry) m.add_control(ipylft.LayersControl()) return m
def show(self, tabs=True, layer_control=True, draw_control=False, fullscreen=True): """ Show the Map on the Notebook """ if not self.is_shown: if layer_control: # Layers Control lc = ipyleaflet.LayersControl() self.add_control(lc) if draw_control: # Draw Control dc = ipyleaflet.DrawControl(edit=False) dc.on_draw(self.handle_draw) self.add_control(dc) if fullscreen: # Control full_control = ipyleaflet.FullScreenControl() self.add_control(full_control) if tabs: display(self, self.tab_widget) else: display(self) else: if tabs: display(self, self.tab_widget) else: display(self) self.is_shown = True # Start with crosshair cursor self.default_style = {'cursor': 'crosshair'}
def get_gdf_wms_map(datasets, wms_datasets, wms_url=globals.INCORE_GEOSERVER_WMS_URL): """Get a map with WMS layers from list of datasets for geopandas and list of datasets for WMS Args: datasets (list): list of pyincore Dataset objects wms_datasets (list): list of pyincore Dataset objects for wms layers wms_url (str): URL of WMS server Returns: obj: A ipylfealet Map object """ # TODO: how to add a style for each WMS layers (pre-defined styules on WMS server) and gdf layers # (min_lat, min_lon, max_lat, max_lon) bbox_all = [9999, 9999, -9999, -9999] geo_data_list = [] for dataset in datasets: # maybe this part should be moved to Dataset Class gdf = gpd.read_file(dataset.local_file_path) geo_data = ipylft.GeoData(geo_dataframe=gdf, name=dataset.metadata['title']) geo_data_list.append(geo_data) bbox = gdf.total_bounds bbox_all = GeoUtil.merge_bbox(bbox_all, bbox) wms_layers = [] for dataset in wms_datasets: wms_layer_name = 'incore:' + dataset.id wms_layer = ipylft.WMSLayer(url=wms_url, layers=wms_layer_name, format='image/png', transparent=True, name=dataset.metadata['title'] + '-WMS') wms_layers.append(wms_layer) bbox = dataset.metadata['boundingBox'] bbox_all = GeoUtil.merge_bbox(bbox_all, bbox) m = GeoUtil.get_ipyleaflet_map(bbox_all) for layer in wms_layers: m.add_layer(layer) for g in geo_data_list: m.add_layer(g) m.add_control(ipylft.LayersControl()) return m
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 plot_network_dataset(network_dataset: NetworkDataset): """Creates map window with Network Dataset visualized Args: network_dataset (NetworkDataset): pyincore Network Dataset object Returns: m (ipyleaflet.Map): ipyleaflet Map object """ # get node file name path link_path = network_dataset.link.file_path link_file_name = os.path.basename(link_path) # get node file name path node_path = network_dataset.node.file_path node_file_name = os.path.basename(node_path) # read file using geopandas node_gdf = gpd.read_file(node_path) link_gdf = gpd.read_file(link_path) geo_data_list = [] # (min_lat, min_lon, max_lat, max_lon) bbox_all = [9999, 9999, -9999, -9999] # add node data to list node_geo_data = ipylft.GeoData(geo_dataframe=node_gdf, name=node_file_name) geo_data_list.append(node_geo_data) # add link data to list link_geo_data = ipylft.GeoData(geo_dataframe=link_gdf, name=link_file_name) geo_data_list.append(link_geo_data) bbox = link_gdf.total_bounds bbox_all = GeoUtil.merge_bbox(bbox_all, bbox) m = GeoUtil.get_ipyleaflet_map(bbox_all) for entry in geo_data_list: m.add_layer(entry) m.add_control(ipylft.LayersControl()) return m
def show(self, inspector=True): """ Show the Map on the Notebook """ if not self.is_shown: # Layers Control lc = ipyleaflet.LayersControl() self.add_control(lc) self.is_shown = True if inspector: # Create Assets Tab self.create_assets_tab() # Display display(self, self.tabs) else: display(self) elif inspector: display(self, self.tabs) else: display(self)
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 plot_isochrones(coordinates, isochrones, zoom_level=8): '''Initiate map and plot isochrones centered on coordinates.''' center = coord_to_tuple(coordinates) layer_color = 'brown' fill_color = 'orange' m = ipl.Map(center=center, zoom=zoom_level) for key in isochrones.keys(): item = ipl.Polygon(locations=isochrones[key], color=layer_color, weight=1, fill_color=fill_color, fill_opacity=0.2, name=key) m.add_layer(item) m.add_control(ipl.LayersControl()) return m
def __init__( self, data_url_prefix='https://raw.githubusercontent.com/yyu/GeoJSON-US/master' ): self.zipcodes = WebDict( url_maker=lambda z: f'{data_url_prefix}/perZIPgeojson/{z[0]}/{z[1]}/{z[2]}/{z}.json', response_processor=json.loads) self.gazetteer = WebTSV(f'{data_url_prefix}/ZIPCodesGazetteer.tsv') self.zipcode_set = set(self.gazetteer.keys()) self.center = [47.621795, -122.334958] self.zoom = 8 self.height = '500px' self.progress_bar_width = '500px' self.area_style = { 'color': '#0000ff', 'weight': .5, 'fillColor': '#000077', 'fillOpacity': 0.2 } self.progress_bar = widgets.IntProgress( bar_style='info', layout=widgets.Layout(width=self.progress_bar_width)) self.label = widgets.Label() self.progress_label = widgets.Label() self.info_box = widgets.HBox([self.progress_label, self.progress_bar]) self.basemap = leaflet.basemaps.OpenMapSurfer.Roads self.basemap['name'] = 'basemap' self.heatmap_data = leaflet.basemaps.Strava.All self.heatmap_data['name'] = 'heatmap' self.heatmap = leaflet.basemap_to_tiles(self.heatmap_data) self.layers_control = leaflet.LayersControl() self.map_layout = widgets.Layout(height=self.height) self.map = None
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
class measures(object): def __init__(self): measures.sheet = None measures.sheet2 = None measures.band_index1 = 4 measures.band_index2 = 4 measures.pyccd_flag = False measures.pyccd_flag2 = False measures.table = None conn = sqlite3.connect(measures.dbPath) measures.current_id = measures.current_id measures.c = conn.cursor() measures.minv = 0 measures.maxv = 6000 measures.b1 = 'SWIR1' measures.b2 = 'NIR' measures.b3 = 'RED' # Starting variables pyccd_flag = False pyccd_flag2 = False current_band = '' band_index1 = 4 band_index2 = 4 click_col = '' point_color = ['#43a2ca'] click_df = pd.DataFrame() sample_col = '' sample_df = pd.DataFrame() PyCCDdf = pd.DataFrame() table = pd.DataFrame() band_list = [ 'BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2', 'BRIGHTNESS', 'GREENNESS', 'WETNESS' ] year_range = [1986, 2018] doy_range = [1, 365] step = 1 #in years current_id = 0 # Set up database dbPath = os.getcwd() + '/measures_database' command = '''CREATE TABLE measures (id text, lat text, lon text, year1 text, year2 text, direction text, coverType text, condition text, change text, chaOther text, confCA text, class text, water text, bare text, albedo text, use text, height text, transport text, impervious text, density text, vegType1 text, herbaceous text, shrub text, forestPhenology text, leafType text, location text, confidence real, notes text, byear text, brange1 text, brange2 text)''' conn = sql.make_db(dbPath, command) # Widgets # Sliders years = plots.make_range_slider([1990, 1991], 1990, 2018, 1, 'Years:') break_years = plots.make_range_slider([1990, 1991], 1990, 2018, 1, 'Years:') break_year = plots.make_slider(1990, 1991, 2018, 1, 'Years:') confidence = plots.make_slider(0, 0, 3, 1, 'Confidence:') ca_confidence = plots.make_slider(0, 0, 3, 1, '') ylim = plots.make_range_slider([0, 4000], -10000, 10000, 500, 'YLim:') xlim = plots.make_range_slider([2000, 2018], 1984, 2019, 1, 'XLim:') ylim2 = plots.make_range_slider([0, 4000], -10000, 10000, 500, 'YLim:') xlim2 = plots.make_range_slider([2000, 2018], 1984, 2019, 1, 'XLim:') # Dropdown boxes drop1 = plots.make_drop('Persistant Ice?', ['Persistant Ice?', 'Yes', 'No'], 'Decision 2') drop2 = plots.make_drop('Decision 3', ['Decision 3'], 'Decision 3') drop3 = plots.make_drop('Decision 4', ['Decision 4'], 'Decision 4') drop4 = plots.make_drop('Decision 5', ['Decision 5'], 'Decision 5') drop5 = plots.make_drop('Decision 6', ['Decision 6'], 'Decision 6') drop6 = plots.make_drop('Decision 7', ['Decision 7'], 'Decision 7') drop7 = plots.make_drop('Decision 8', ['Decision 8'], 'Decision 8') drop8 = plots.make_drop('Decision 9', ['Decision 9'], 'Decision 9') drop9 = plots.make_drop('Stable', ['Stable', 'Transitional', 'Break'], 'Label Type:') drop0 = plots.make_drop( 'Dominant or Secondary?', ['Dominant or Secondary?', 'Dominant', 'Secondary'], 'Decision 1') band_selector1 = plots.make_drop('SWIR1', band_list, 'Select band') band_selector2 = plots.make_drop('SWIR1', band_list, 'Select band') image_band_1 = plots.make_drop('RED', band_list, 'Red:') image_band_2 = plots.make_drop('GREEN', band_list, 'Green:') image_band_3 = plots.make_drop('BLUE', band_list, 'Blue:') # Checkbox color_check = plots.make_checkbox(False, 'Color DOY', False) # Select multiple veg_selector = plots.make_selector(['Veg Type'], [ 'Veg Type', 'Cropland', 'Plantation', 'Wetland', 'Riparian/Flood', 'Mangrove' ], 'Veg Type:', disabled=True) change_selector = plots.make_selector(['None'], [ 'None', 'Deforestation/Logging', 'Fire', 'Insect damage', 'Urban Dev.', 'Flooding', 'Decline/Degradation', 'Regrowth', 'Riparian/Water shift', 'Other (Specify)' ], 'Change Agent:') direction = plots.make_selector(['None'], [ 'None', 'Veg Increase', 'Veg Decrease', 'Water Increase', 'Water Decrease', 'Bare Increase', 'Bare Decrease', 'Urban Increase', 'Urban Decrease', 'Albedo Increase', 'Albedo Decrease' ], 'Directional Change:') # Text boxes change_other = plots.make_text('Specify other', 'Specify other', 'Other:') notes = plots.make_text_large( 'Enter any useful or interesting information about the land cover of this sample', '', 'Notes', layout=widgets.Layout()) #,layout=widgets.Layout(width='70%')) spreadsheet = plots.make_text('Google Spreadsheet Credential JSON', 'Google Spreadsheet Credential JSON', 'Credentials:') spreadName = plots.make_text('Google Spreadsheet Name', 'Google Spreadsheet Name', 'SS Name:') sampleWidget = plots.make_text('Path to sample feature collection', 'Path to sample feature collection', 'Path:') stretch_min = plots.make_text_float(0, 0, 'Min:') stretch_max = plots.make_text_float(1450, 1450, 'Max:') zoom_box = plots.make_text_float(12, 12, 'Zoom:') idBox = plots.make_text('0', '0', 'ID:') # Buttons validate = plots.make_button(False, 'Validate', icon='check') save_button = plots.make_button(False, 'Save', icon='') load_button = plots.make_button(False, 'Load', icon='') toggle_pyccd_button = plots.make_button(False, 'Clear Pyccd 1', icon='') toggle_pyccd_button2 = plots.make_button(False, 'Clear Pyccd 2', icon='') return_button = plots.make_button(False, 'Return to Sample', icon='') next_pt = plots.make_button(False, 'Next point', icon='') previous_pt = plots.make_button(False, 'Previous point', icon='') pyccd_button = plots.make_button(False, 'Run PyCCD 1', icon='') pyccd_button2 = plots.make_button(False, 'Run PyCCD 2', icon='') clear_layers = plots.make_button(False, 'Clear Map', icon='') delete_rows = plots.make_button(False, 'Delete Last', icon='') # Validate valid = plots.make_valid(False, 'Not Saved', '') valid_load = plots.make_valid(False, 'Not Loaded', '') # HTML pt_message = plots.make_html('Current ID: ') time_label = plots.make_html('') coord_message = plots.make_html('Lat, Lon: ') selected_label = plots.make_html('ID of selected point') hover_label = plots.make_html('Test Value') text_brush = plots.make_html('Selected year range:') kml_link = plots.make_html('KML:') error_label = plots.make_html('Load a point') # Table table_widget = qgrid.show_grid(table, show_toolbar=False) # Plots # Scales # Dates lc1_x = plots.make_bq_scale('date', datetime.date(xlim.value[0], 2, 1), datetime.date(xlim.value[1], 1, 1)) lc1_x2 = plots.make_bq_scale('date', datetime.date(xlim.value[0], 2, 1), datetime.date(xlim.value[1], 1, 1)) # DOY lc1_x3 = plots.make_bq_scale('linear', 0, 365) # Reflectance lc2_y = plots.make_bq_scale('linear', ylim.value[0], ylim.value[1]) lc2_y2 = plots.make_bq_scale('linear', ylim.value[0], ylim.value[1]) # plots lc2 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x, 'y': lc2_y }, [1, 1], { 'click': 'select', 'hover': 'tooltip' }, { 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, {'opacity': 0.5}, display_legend=True, labels=['Sample point']) lc3 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x2, 'y': lc2_y2 }, [1, 1], { 'click': 'select', 'hover': 'tooltip' }, { 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, {'opacity': 0.5}, display_legend=True, labels=['Clicked point']) lc4 = plots.make_bq_plot('lines', [], [], { 'x': lc1_x, 'y': lc2_y }, [1, 1], {}, {}, {}, colors=['black'], stroke_width=3) lc5 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x, 'y': lc2_y }, [1, 1], {}, {}, {}, labels=['Model Endpoint'], colors=['red'], marker='triangle-up') lc6 = plots.make_bq_plot('lines', [], [], { 'x': lc1_x2, 'y': lc2_y2 }, [1, 1], {}, {}, {}, colors=['black'], stroke_width=3) lc7 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x2, 'y': lc2_y2 }, [1, 1], {}, {}, {}, labels=['Model Endpoint'], colors=['red'], marker='triangle-up') lc8 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x3, 'y': lc2_y }, [1, 1], { 'click': 'select', 'hover': 'tooltip' }, { 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, {'opacity': 0.5}, display_legend=True, labels=['Sample point']) # Axis x_ax1 = plots.make_bq_axis('Date', lc1_x, num_ticks=6, tick_format='%Y', orientation='horizontal') x_ax2 = plots.make_bq_axis('Date', lc1_x2, num_ticks=6, tick_format='%Y', orientation='horizontal') x_ax3 = plots.make_bq_axis('DOY', lc1_x3, num_ticks=6, orientation='horizontal') y_ay1 = plots.make_bq_axis('SWIR1', lc2_y, orientation='vertical') y_ay2 = plots.make_bq_axis('SWIR1', lc2_y2, orientation='vertical') # Figures fig = plots.make_bq_figure([lc2, lc4, lc5], [x_ax1, y_ay1], { 'height': '300px', 'width': '100%' }, 'Sample TS') fig2 = plots.make_bq_figure([lc3, lc6, lc7], [x_ax2, y_ay2], { 'height': '300px', 'width': '100%' }, 'Clicked TS') fig3 = plots.make_bq_figure([lc8], [x_ax3, y_ay1], { 'height': '300px', 'width': '100%' }, 'Clicked TS') # Functions # Delete data highlighted in rows def delete_data_rows(a): measures.c.execute( "DELETE FROM measures WHERE id = (SELECT MAX(id) FROM measures)") measures.change_table(0) condition = measures.drop9.value if condition == 'Break': measures.sheet2.delete_row(2) else: measures.sheet.delete_row(2) # Reset dropdowns def reset_drops(): measures.drop4.set_trait('options', ['Decision 4']) measures.drop5.set_trait('options', ['Decision 5']) measures.drop6.set_trait('options', ['Decision 6']) measures.drop7.set_trait('options', ['Decision 7']) measures.drop8.set_trait('options', ['Decision 8']) measures.veg_selector.disabled = True # Change dropdowns based on drop1 selection def drop1_clicked(selection): if selection.new == 'No': measures.drop2.set_trait('options', ['>30% Vegetated?', 'Yes', 'No']) elif selection.new == 'Yes': measures.drop2.set_trait('options', ['Ice/Snow']) measures.drop3.set_trait('options', ['No other information needed']) measures.reset_drops() # Change dropdowns based on drop2 selection def drop2_clicked(selection): if '>30% Vegetated?' in measures.drop2.options: if selection.new == 'Yes': measures.drop3.set_trait('options', [ 'Density', 'Closed (60-70%)', 'Open (30-60%)', 'Sparse (<30%)' ]) measures.veg_selector.disabled = False measures.drop4.set_trait('options', ['Trees?', 'Yes', 'No']) elif selection.new == 'No': measures.drop3.set_trait( 'options', ['Dominant Cover?', 'Water', 'Bare', 'Developed']) measures.drop4.set_trait('options', ['Decision 4']) measures.drop5.set_trait('options', ['Decision 5']) measures.drop6.set_trait('options', ['Decision 6']) measures.drop7.set_trait('options', ['Decision 7']) measures.drop8.set_trait('options', ['Decision 8']) measures.veg_selector.disabled = True else: measures.drop3.set_trait('options', ['No Other Information Needed']) # Change dropdowns based on drop3 selection def drop3_clicked(selection): if 'Dominant Cover?' in measures.drop3.options: measures.veg_selector.disabled = True if selection.new == 'Water': measures.drop4.set_trait('options', [ 'Water Type', 'Shore/Inter tidal', 'Shallows', 'River', 'Lake/Reservoir', 'Ocean' ]) elif selection.new == 'Bare': measures.drop4.set_trait('options', [ 'Bare Type', 'Soil', 'Rock', 'Quarry (Active)', 'Beach/Sand' ]) elif selection.new == 'Developed': measures.drop4.set_trait( 'options', ['Surface Albedo', 'High', 'Low', 'Mixed']) measures.drop5.set_trait( 'options', ['Use', 'Residential', 'Commercial/Industrial']) measures.drop6.set_trait('options', [ 'Building Height', 'No Buildings', '1-2 Stories', '3-5 Stories', '5+ Stories' ]) measures.drop7.set_trait( 'options', ['Transport', 'Road', 'Not Applicable']) measures.drop8.set_trait('options', [ '% Impervious', 'High (60-100)', 'Medium (30-60)', 'Low (<30)' ]) # Change dropdowns based on drop4 selection def drop4_clicked(selection): if 'Trees?' in measures.drop4.options: if selection.new == 'Yes': measures.drop5.set_trait( 'options', ['Height >5m & Canopy >30%', 'Yes', 'No']) elif selection.new == 'No': measures.drop5.set_trait('options', [ 'Herbaceous Type', 'Grassland', 'Pasture', 'Lawn/Urban Grass', 'Moss/Lichen' ]) # Change dropdowns based on drop5 selection def drop5_clicked(selection): if 'Height >5m & Canopy >30%' in measures.drop5.options: if selection.new == 'Yes': measures.drop6.set_trait( 'options', ['Forest Type', 'Evergreen', 'Deciduous', 'Mixed']) measures.drop7.set_trait( 'options', ['Leaf Type', 'Broad', 'Needle', 'Unsure']) measures.drop8.set_trait('options', ['Location', 'Interior', 'Edge']) elif selection.new == 'No': measures.drop6.set_trait( 'options', ['Shrub Type', 'Evergreen', 'Deciduous', 'Mixed']) # Check validity of current sample def check_val_status(selection): selected_secondary_lc = False wrote_correct_lc = False if measures.second_class_drop.value != 'Secondary Class Information': selected_secondary_lc = True else: print("Must specify secondary class information!") if measures.lc.value.capitalize( ) == measures.textClass.value.capitalize(): wrote_correct_lc = True if selected_secondary_lc and wrote_correct_lc: measures.valid.value = True measures.save_button.disabled = False # load the feature collection, database, and google sheet def load_everything(sender): measures.sheet = sheets.load_sheet(measures.spreadName.value, 0, measures.spreadsheet.value) measures.sheet2 = sheets.load_sheet(measures.spreadName.value, 1, measures.spreadsheet.value) # Load the sample as a feature collection sample_path = measures.sampleWidget.value fc_df = utils.fc2dfgeo(sample_path) measures.fc_df, first_index = utils.check_id(fc_df) measures.valid_load.value = True measures.valid_load.description = 'Loaded!' measures.current_id = first_index - 1 # If the class type is 'break', turn on necessary widgets def turn_on_break_years(selection): if selection.new == 'Break': measures.break_years.disabled = False measures.break_year.disabled = False else: measures.break_years.disabled = True measures.break_year.disabled = True # Change yaxis for the sample time series def change_yaxis(value): measures.lc2_y.min = measures.ylim.value[0] measures.lc2_y.max = measures.ylim.value[1] # Change xaxis for the sample time series def change_xaxis(value): measures.lc1_x.min = datetime.date(measures.xlim.value[0], 2, 1) measures.lc1_x.max = datetime.date(measures.xlim.value[1], 2, 1) measures.year_range = [measures.xlim.value[0], measures.xlim.value[1]] # Change y axis for the clicked point def change_yaxis2(value): measures.lc2_y2.min = measures.ylim2.value[0] measures.lc2_y2.max = measures.ylim2.value[1] # Change x axis for the clicked point def change_xaxis2(value): measures.lc1_x2.min = datetime.date(measures.xlim2.value[0], 2, 1) measures.lc1_x2.max = datetime.date(measures.xlim2.value[1], 2, 1) # Display date of observation when hovering on scatterplot def hover_event(self, target): measures.hover_label.value = str(target['data']['x']) # Advance to next sample def advance(b): measures.lc4.x = [] measures.lc4.y = [] measures.lc5.x = [] measures.lc5.y = [] measures.lc5.display_legend = False measures.pyccd_flag = False measures.current_id += 1 measures.pt_message.value = "Point ID: {}".format(measures.current_id) measures.map_point() measures.get_ts() measures.plot_ts(measures.lc2, 'ts') measures.plot_ts(measures.lc8, 'doy') measures.change_table(0) measures.valid.value = False measures.description = 'Not Saved' # Go to previous sample def decrease(b): measures.lc4.x = [] measures.lc4.y = [] measures.lc5.x = [] measures.lc5.y = [] measures.lc5.display_legend = False measures.pyccd_flag = False measures.current_id -= 1 measures.pt_message.value = "Point ID: {}".format(measures.current_id) measures.map_point() measures.get_ts() #measures.plot_ts() measures.plot_ts(measures.lc2, 'ts') measures.plot_ts(measures.lc8, 'doy') measures.change_table(0) measures.valid.value = False measures.description = 'Not Saved' # Go to a specific sample def go_to_sample(b): measures.lc4.x = [] measures.lc4.y = [] measures.lc5.x = [] measures.lc5.y = [] measures.lc5.display_legend = False measures.pyccd_flag = False measures.current_id = int(b.value) measures.pt_message.value = "Point ID: {}".format(measures.current_id) measures.valid.value = False measures.description = 'Not Saved' measures.map_point() measures.get_ts() #measures.plot_ts() measures.plot_ts(measures.lc2, 'ts') measures.plot_ts(measures.lc8, 'doy') # Return to sample location def return_to_sample(b): measures.map_point() # Update the table based on current ID def change_table(b): # Get header cursor = measures.c.execute('select * from measures') names = list(map(lambda x: x[0], cursor.description)) previous_inputs = pd.DataFrame() for i, row in enumerate( measures.c.execute("SELECT * FROM measures WHERE id = '%s'" % measures.current_id)): previous_inputs[i] = row previous_inputs = previous_inputs.T if previous_inputs.shape[0] > 0: previous_inputs.columns = names measures.table_widget.df = previous_inputs # Functions for changing image stretch def change_image_band1(change): new_band = change['new'] measures.b1 = new_band def change_image_band2(change): new_band = change['new'] measures.b2 = new_band def change_image_band3(change): new_band = change['new'] measures.b3 = new_band # Band selection for sample point def on_band_selection1(change): band_index = change['owner'].index measures.band_index1 = band_index new_band = change['new'] measures.y_ay1.label = new_band #measures.plot_ts() measures.plot_ts(measures.lc2, 'ts') measures.plot_ts(measures.lc8, 'doy') # Band selection for clicked point def on_band_selection2(change): new_band = change['new'] band_index = change['owner'].index measures.band_index2 = band_index measures.lc3.x = measures.click_df['datetime'] measures.lc3.y = measures.click_df[new_band] #measures.plot_ts(measures.lc3, 'ts') measures.y_ay2.label = new_band if measures.pyccd_flag2: measures.do_pyccd2(0) # Clear everything on map besides current sample def clear_map(b): lft.clear_map(measures.m, streets=True) if hasattr(measures, 'fc_df'): measures.map_point() # Add an image to the map when clicked on time series def add_image(self, target): m = measures.m df = measures.sample_df current_band = measures.band_list[measures.band_index1] sample_col = measures.sample_col stretch_min = measures.stretch_min stretch_max = measures.stretch_max b1 = measures.b1 b2 = measures.b2 b3 = measures.b3 lft.click_event(target, m, current_band, df, sample_col, stretch_min, stretch_max, b1, b2, b3) def add_image2(self, target): m = measures.m df = measures.click_df current_band = measures.band_list[measures.band_index2] sample_col = measures.click_col stretch_min = measures.minv stretch_max = measures.maxv b1 = measures.b1 b2 = measures.b2 b3 = measures.b3 lft.click_event(target, m, current_band, df, sample_col, stretch_min, stretch_max, b1, b2, b3) # Plot ts for point def do_draw(self, action, geo_json): current_band = measures.band_list[measures.band_index2] year_range = measures.year_range doy_range = measures.doy_range _col, _df = utils.handle_draw(action, geo_json, current_band, year_range, doy_range) measures.click_df = _df measures.click_col = _col measures.lc6.x = [] measures.lc6.y = [] measures.lc7.x = [] measures.lc7.y = [] measures.lc3.x = measures.click_df['datetime'] measures.lc3.y = measures.click_df[current_band] if measures.color_check.value == False: measures.lc3.colors = list(measures.point_color) else: measures.lc3.colors = list(measures.click_df['color'].values) # Add point location to map def map_point(): zoom = int(measures.zoom_box.value) kml = measures.kml_link name = 'Sample point' data = measures.fc_df['geometry'][measures.current_id] coord1 = data['coordinates'][0] coord2 = data['coordinates'][1] measures.coord_message.value = "Lat, Lon: {}, {}".format( coord2, coord1) lft.add_map_point(data, zoom, measures.m, kml, name) # Get time series data for location. def get_ts(): measures.error_label.value = 'Loading' coords = measures.fc_df['geometry'][measures.current_id]['coordinates'] year_range = measures.year_range doy_range = measures.doy_range measures.current_band = measures.band_list[measures.band_index1] measures.sample_col = utils.get_full_collection( coords, year_range, doy_range) measures.sample_df = utils.get_df_full(measures.sample_col, coords).dropna() measures.error_label.value = 'Point Loaded!' # TODO: how is this different from handle_draw? def plot_ts(plot, plottype): df = measures.sample_df if measures.color_check.value == True: color_marks = list(measures.sample_df['color'].values) else: color_marks = None band = measures.band_list[measures.band_index1] if plottype == 'ts': plots.add_plot_ts(df, plot, band=band, color_marks=color_marks) else: plots.add_plot_doy(df, plot, band=band, color_marks=color_marks) if measures.pyccd_flag: measures.do_pyccd(0) # Run pyccd for the sample location def do_pyccd(b): pyccd_flag = measures.pyccd_flag display_legend = measures.lc5.display_legend dfPyCCD = measures.sample_df band_index = measures.band_index1 results = ccd_tools.run_pyccd(pyccd_flag, display_legend, dfPyCCD, band_index) ccd_tools.plot_pyccd(dfPyCCD, results, band_index, (0, 4000), measures.lc4, measures.lc5) # Run pyccd for the clicked location def do_pyccd2(b): pyccd_flag = measures.pyccd_flag2 display_legend = measures.lc7.display_legend dfPyCCD = measures.click_df band_index = measures.band_index1 results = ccd_tools.run_pyccd(pyccd_flag, display_legend, dfPyCCD, band_index) ccd_tools.plot_pyccd(dfPyCCD, results, band_index, (0, 4000), measures.lc6, measures.lc7) def clear_pyccd(b): measures.lc4.x = [] measures.lc5.y = [] def clear_pyccd2(b): measures.lc6.x = [] measures.lc7.y = [] # Save sample def save_sample(): # Connect to the database conn = sqlite3.connect(measures.dbPath) c = conn.cursor() # Get everything in right format year1 = measures.years.value[0] year2 = measures.years.value[1] waterType = 'N/A' bareType = 'N/A' albedo = 'N/A' use = 'N/A' height = 'N/A' transport = 'N/A' impervious = 'N/A' density = 'N/A' vegType1 = 'N/A' herbaceousType = 'N/A' shrubType = 'N/A' forestPhenology = 'N/A' leafType = 'N/A' location = 'N/A' condition = measures.drop9.value coverType = measures.drop0.value changeAgent = measures.change_selector.value changeAgent = [str(i) for i in changeAgent] changeAgent = ', '.join(changeAgent) if changeAgent != 'None': confCA = measures.ca_confidence.value break_year = measures.break_year.value break_range1 = measures.break_years.value[0] break_range2 = measures.break_years.value[1] else: confCA = 'N/A' break_year = 'N/A' break_range1 = 'N/A' break_range2 = 'N/A' ca_other = measures.change_other.value if ca_other == 'Specify other': ca_other = 'N/A' direction = measures.direction.value direction = [str(i) for i in direction] direction = ', '.join(direction) class1 = 'Unfilled' # Ice/Snow if measures.drop1.value == 'Yes': class1 = 'Snow/Ice' else: if measures.drop2.value == 'No': #Non-Veg class1 = measures.drop3.value if class1 == 'Water': waterType = measures.drop4.value elif class1 == 'Bare': bareType = measures.drop4.value else: albedo = measures.drop4.value #HERE use = measures.drop5.value height = measures.drop6.value transport = measures.drop7.value impervious = measures.drop8.value elif measures.drop2.value == 'Yes': #Veg density = measures.drop3.value vegType1 = measures.veg_selector.value vegType1 = [str(i) for i in vegType1] vegType1 = ', '.join(vegType1) if measures.drop5.value == 'No': #Herbaceous class1 = 'Herbaceous' herbaceousType = measures.drop6.value elif measures.drop5.value == 'Yes': class1 = 'Forest' forestPhenology = measures.drop6.value leafType = measures.drop7.value location = measures.drop8.value conf = measures.confidence.value notes_value = measures.notes.value idSample = measures.current_id lat = measures.m.center[0] lon = measures.m.center[1] sampleInput = (idSample, lat, lon, year1, year2, direction, coverType, condition, changeAgent, ca_other, confCA, class1, waterType, bareType, albedo, use, height, transport, impervious, density, vegType1, herbaceousType, shrubType, forestPhenology, leafType, location, conf, notes_value, break_year, break_range1, break_range2) # Put sample information into database c.execute("""insert into measures values {i}""".format(i=sampleInput)) # Save (commit) the changes conn.commit() # Close the cursor c.close() # Save to drive sampleInputList = [ str(idSample), str(lat), str(lon), str(year1), str(year2), direction, coverType, condition, changeAgent, ca_other, confCA, class1, waterType, bareType, albedo, use, height, transport, impervious, density, vegType1, herbaceousType, shrubType, forestPhenology, leafType, location, conf, notes_value ] sampleInputListFull = sampleInputList # Save break information to second sheet if condition == 'Break': breakList = [ str(idSample), str(lat), str(lon), changeAgent, ca_other, confCA, break_year, break_range1, break_range2 ] measures.sheet2.insert_row(breakList, 2) count = len(measures.sheet2.col_values(1)) time.sleep(3) count_new = len(measures.sheet2.col_values(1)) else: count = len(measures.sheet.col_values(1)) measures.sheet.insert_row(sampleInputListFull, 2) time.sleep(3) count_new = len(measures.sheet.col_values(1)) if count_new > count: # Change save validity state measures.valid.value = True measures.valid.description = 'Saved!' measures.reset_everything() else: time.sleep(10) if condition == 'Break': count_new = len(measures.sheet2.col_values(1)) else: count_new = len(measures.sheet.col_values(1)) if count_new > count: # Change save validity state measures.valid.value = True measures.valid.description = 'Saved!' measures.reset_everything() # Reset all widgets def reset_everything(): measures.drop1.set_trait('value', 'Persistant Ice?') measures.drop2.set_trait('options', ['Decision 3']) measures.drop3.set_trait('options', ['Decision 4']) measures.drop5.set_trait('options', ['Decision 5']) measures.drop6.set_trait('options', ['Decision 6']) measures.drop7.set_trait('options', ['Decision 7']) measures.drop8.set_trait('options', ['Decision 8']) measures.veg_selector.disabled = True measures.years.set_trait('value', [1990, 1991]) measures.confidence.set_trait('value', 0) measures.ca_confidence.set_trait('value', 0) # Interaction function for saving sample def do_save_sample(a): measures.save_sample() measures.change_table(0) # Widget interactions delete_rows.on_click(delete_data_rows) return_button.on_click(return_to_sample) save_button.on_click(do_save_sample) validate.on_click(check_val_status) drop1.observe(drop1_clicked, 'value') drop2.observe(drop2_clicked, 'value') drop3.observe(drop3_clicked, 'value') drop4.observe(drop4_clicked, 'value') drop5.observe(drop5_clicked, 'value') drop9.observe(turn_on_break_years, 'value') load_button.on_click(load_everything) dc = ipyleaflet.DrawControl(marker={'shapeOptions': { 'color': '#ff0000' }}, polygon={}, circle={}, circlemarker={}, polyline={}) zoom = 5 layout = widgets.Layout(width='50%') center = (3.3890701010382958, -67.32297252983098) m = lft.make_map(zoom, layout, center) lft.add_basemap(m, ipyleaflet.basemaps.Esri.WorldImagery) # Display controls ylim.observe(change_yaxis) xlim.observe(change_xaxis) ylim2.observe(change_yaxis2) xlim2.observe(change_xaxis2) clear_layers.on_click(clear_map) band_selector1.observe(on_band_selection1, names='value') band_selector2.observe(on_band_selection2, names='value') image_band_1.observe(change_image_band1, names='value') image_band_2.observe(change_image_band2, names='value') image_band_3.observe(change_image_band3, names='value') # Samples next_pt.on_click(advance) previous_pt.on_click(decrease) # pyccd pyccd_button.on_click(do_pyccd) pyccd_button2.on_click(do_pyccd2) toggle_pyccd_button.on_click(clear_pyccd) toggle_pyccd_button2.on_click(clear_pyccd2) # Plots lc2.on_element_click(add_image) lc2.tooltip = hover_label lc2.on_hover(hover_event) lc3.on_element_click(add_image2) lc3.tooltip = hover_label lc3.on_hover(hover_event) idBox.on_submit(go_to_sample) # Mapping dc.on_draw(do_draw) m.add_control(dc) m.add_control(ipyleaflet.LayersControl())
def display(self, basemap=False, mapLayout=False, style=False, groupBy=False, colorDict=False, pageTitle='GeoJSON map', outputPath='html/static'): """ Display the dataframe on a map. Markers can be plotted at once, grouped (style='grouped'), or as pie charts (style='pie') grouped by a chosen category (groupBy='COLUMN'). """ if basemap: self.basemap = basemap else: self.basemap = { 'url': 'https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', 'max_zoom': 16, 'attribution': '<a href="https://carto.com">Carto Light NoLabels</a>', 'name': 'Carto Light' } latList = [ x for x in self.df[self.lat].values if type(x) not in [str, list, dict] ] latMean = sum(latList) / len(latList) lonList = [ x for x in self.df[self.lon].values if type(x) not in [str, list, dict] ] lonMean = sum(lonList) / len(lonList) self.center = [latMean, lonMean] self.zoom = 5 self.displayMap = ipyleaflet.Map(center=self.center, zoom=self.zoom, layers=(ipyleaflet.basemap_to_tiles( self.basemap), )) if mapLayout: self.displayMap.layout = mapLayout if not style: markers = self._generateMarkers() for marker in markers: self.displayMap.add_layer(marker) return self.displayMap elif style == 'grouped': markers = self._generateMarkers() self.markerCluster = ipyleaflet.MarkerCluster(markers=markers) self.displayMap.add_control(ipyleaflet.LayersControl()) self.displayMap.add_layer(self.markerCluster) return self.displayMap elif style == 'pie': if not groupBy: raise KeyError( 'Please add groupBy=COLNAME. You need to specify the column containing the categories for the pie chart.' ) html = self._writeHTML(groupCategory=groupBy, pageTitle=pageTitle, outputPath=outputPath) css = self._writeCSS(groupCategory=groupBy, colorDict=colorDict, outputPath=outputPath) print( 'Your map has been generated at\n\t"/html/static/index.html".\nDue to CORS issues, most browsers will not load the GeoJSON in an Iframe correctly.\nPlease open the map in a seperate browser window.' ) return displayHTML( "<iframe allowfullscreen=”true” mozallowfullscreen=”true” webkitallowfullscreen=”true” height=550px; width=100% src='./html/static/index.html'> <iframe>" )
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 show(self, **kwargs): """ Generate and return the map object for displaying the map Parameters ----------- None Returns ---------- map:ipyleaflet.Map """ self.map = ipyleaflet.Map( layers=(ipyleaflet.basemap_to_tiles( ipyleaflet.basemaps.CartoDB.Positron),), **kwargs ) choro_layer = ipyleaflet.Choropleth( name=self.dataset, geo_data=self.geo_data, choro_data=self.choro_data[self.selectedAttr][self.selectedYear], colormap=linear.YlOrRd_04, style={ 'opacity': 1, 'weight': 1.9, 'dashArray': '9', 'fillOpacity': 0.5} ) def handle_click(**kwargs): if kwargs['event'] == 'click': clickedFips = kwargs['properties']['GEOID'] clickedName = self.fipsLookUp[clickedFips] dataBox.value = f"{clickedName} : {self.choro_data[self.selectedAttr][self.selectedYear][clickedFips]:,}" self.clickedID = clickedFips choro_layer.on_click(handle_click) # Year select def handle_year_change(change): new_year = str(change.new) choro_layer.choro_data = self.choro_data[self.selectedAttr][new_year] if self.clickedID: clickedName = self.fipsLookUp[self.clickedID] dataBox.value = f"{clickedName} : {self.choro_data[self.selectedAttr][new_year][self.clickedID]:,}" self.selectedYear = new_year yearList = self.availableYearDict[self.selectedAttr] yearListNum = list(map(int, yearList)) minYear = min(yearListNum) maxYear = max(yearListNum) yearSlider, yearWidget = self.yearSlider(minYear, maxYear, maxYear) yearSlider.observe(handle_year_change, 'value') dataBox, dataWidget = self.dataBox() def handle_attr_change(change): new_attr = change.new choro_layer.choro_data = self.choro_data[new_attr][self.selectedYear] if self.clickedID: clickedName = self.fipsLookUp[self.clickedID] dataBox.value = f"{clickedName} : {self.choro_data[new_attr][self.selectedYear][self.clickedID]:,}" self.selectedAttr = new_attr attrDropdown, attrDropdownWidget = self.attrDropdown() attrDropdown.observe(handle_attr_change, "value") # Add to map self.map.add_layer(choro_layer) self.map.add_control(ipyleaflet.LayersControl()) self.map.add_control(ipyleaflet.FullScreenControl()) self.map.add_control(attrDropdownWidget) self.map.add_control(yearWidget) self.map.add_control(dataWidget) return self.map
class TSTools(object): def __init__(self): TSTools.band_index2 = 4 TSTools.pyccd_flag2 = False TSTools.minv = 0 TSTools.maxv = 6000 TSTools.b1 = 'SWIR1' TSTools.b2 = 'NIR' TSTools.b3 = 'RED' ####### Starting Variables ####### pyccd_flag2 = False current_band = '' band_index2 = 4 click_col = '' point_color = ['#43a2ca'] click_df = pd.DataFrame() click_geojson = '' PyCCDdf = pd.DataFrame() results = '' band_list = ['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2', 'BRIGHTNESS', 'GREENNESS', 'WETNESS', 'NDVI', 'NDFI', 'EVI', 'GV', 'Shade', 'NPV', 'Soil', ] doy_range = [1, 365] step = 1 #in years ###### Widgets ###### ylim2 = plots.make_range_slider([0, 4000], -10000, 10000, 500, 'YLim:') xlim2 = plots.make_range_slider([2000, 2020], 1984, 2020, 1, 'XLim:') band_selector2 = plots.make_drop('SWIR1', band_list, 'Select band') image_band_1 = plots.make_drop('SWIR1', band_list, 'Red:') image_band_2 = plots.make_drop('NIR', band_list, 'Green:') image_band_3 = plots.make_drop('RED', band_list, 'Blue:') # Checkbox color_check = plots.make_checkbox(False, 'Color DOY', False) stretch_min = plots.make_text_float(0, 0, 'Min:') stretch_max = plots.make_text_float(6000, 6000, 'Max:') # Buttons pyccd_button2 = plots.make_button(False, 'Run PyCCD 2', icon='') toggle_pyccd_button2 = plots.make_button(False, 'Clear PyCCD', icon='') clear_layers = plots.make_button(False, 'Clear Map', icon='') # HTML hover_label = plots.make_html('Test Value') ###### Plots ###### # Scales # Dates lc1_x2 = plots.make_bq_scale('date', datetime.date(xlim2.value[0], 2, 1), datetime.date(xlim2.value[1], 1, 1)) # DOY lc1_x3 = plots.make_bq_scale('linear', 0, 365) # Reflectance lc2_y2 = plots.make_bq_scale('linear', ylim2.value[0], ylim2.value[1]) # plots lc3 = plots.make_bq_plot('scatter', [], [], {'x': lc1_x2, 'y': lc2_y2}, [1, 1], {'click': 'select', 'hover': 'tooltip'}, {'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red'}, {'opacity': 0.5}, display_legend=True, labels=['Clicked point']) lc6 = plots.make_bq_plot('lines', [], [], {'x': lc1_x2, 'y': lc2_y2}, [1, 1], {}, {}, {}, colors=['black'], stroke_width=3, labels=['PyCCD Model'], display_legend=False) lc7 = plots.make_bq_plot('scatter', [], [], {'x': lc1_x2, 'y': lc2_y2}, [1, 1], {}, {}, {}, labels=['Model Endpoint'], colors=['red'], marker='triangle-up') lc8 = plots.make_bq_plot('scatter', [], [], {'x': lc1_x3, 'y': lc2_y2}, [1, 1], {'click': 'select', 'hover': 'tooltip'}, {'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red'}, {'opacity': 0.5}, display_legend=True, labels=['Clicked point']) # Axis x_ax2 = plots.make_bq_axis('Date', lc1_x2, num_ticks=6, tick_format='%Y', orientation='horizontal') x_ax3 = plots.make_bq_axis('DOY', lc1_x3, num_ticks=6, orientation='horizontal') y_ay2 = plots.make_bq_axis('SWIR1', lc2_y2, orientation='vertical') # Figures fig2 = plots.make_bq_figure([lc3, lc6, lc7], [x_ax2, y_ay2], {'height': '300px', 'width': '100%'}, 'Clicked TS') fig3 = plots.make_bq_figure([lc8], [x_ax3, y_ay2], {'height': '300px', 'width': '100%'}, 'Clicked DOY') ###### Functions ###### # Change y axis for the clicked point def change_yaxis2(value): TSTools.lc2_y2.min = TSTools.ylim2.value[0] TSTools.lc2_y2.max = TSTools.ylim2.value[1] # Change x axis for the clicked point def change_xaxis2(value): TSTools.lc1_x2.min = datetime.date(TSTools.xlim2.value[0], 2, 1) TSTools.lc1_x2.max = datetime.date(TSTools.xlim2.value[1], 2, 1) # Display date of observation when hovering on scatterplot def hover_event(self, target): TSTools.hover_label.value = str(target['data']['x']) # Functions for changing image stretch def change_image_band1(change): new_band = change['new'] TSTools.b1 = new_band def change_image_band2(change): new_band = change['new'] TSTools.b2 = new_band def change_image_band3(change): new_band = change['new'] TSTools.b3 = new_band # Band selection for clicked point def on_band_selection2(change): new_band = change['new'] band_index = change['owner'].index TSTools.band_index2 = band_index TSTools.lc3.x = TSTools.click_df['datetime'].values TSTools.lc3.y = TSTools.click_df[new_band] TSTools.plot_ts(TSTools.lc3, 'ts') TSTools.plot_ts(TSTools.lc8, 'doy') TSTools.y_ay2.label = new_band if TSTools.pyccd_flag2: TSTools.do_pyccd2(0) # Clear everything on map def clear_map(b): lft.clear_map(TSTools.m, streets=True) def add_image2(self, target): m = TSTools.m df = TSTools.click_df current_band = TSTools.band_list[TSTools.band_index2] sample_col = TSTools.click_col stretch_min = TSTools.stretch_min.value stretch_max = TSTools.stretch_max.value b1 = TSTools.b1 b2 = TSTools.b2 b3 = TSTools.b3 lft.click_event(target, m, current_band, df, sample_col, stretch_min, stretch_max, b1, b2, b3) # Plot ts for point def do_draw(self, action, geo_json): current_band = TSTools.band_list[TSTools.band_index2] doy_range = TSTools.doy_range _col, _df = utils.handle_draw(action, geo_json, current_band, list(TSTools.xlim2.value), doy_range) TSTools.click_geojson = geo_json TSTools.click_df = _df TSTools.click_col = _col TSTools.plot_ts(TSTools.lc3, 'ts') TSTools.plot_ts(TSTools.lc8, 'doy') # Add time series data to plots def plot_ts(plot, plottype): df = TSTools.click_df if TSTools.color_check.value is True: color_marks = list(df['color'].values) else: color_marks = None band = TSTools.band_list[TSTools.band_index2] if plottype == 'ts': plots.add_plot_ts(df, plot, band=band, color_marks=color_marks) else: plots.add_plot_doy(df, plot, band=band, color_marks=color_marks) if TSTools.pyccd_flag2: TSTools.do_pyccd2(0) # Run pyccd for the clicked location def do_pyccd2(b): TSTools.pyccd_flag2 = True display_legend = TSTools.lc7.display_legend dfPyCCD = TSTools.click_df band_index = TSTools.band_index2 TSTools.results = ccd_tools.run_pyccd(display_legend, dfPyCCD, band_index) if band_index > 5: TSTools.lc6.y = [] TSTools.lc6.x = [] TSTools.lc7.y = [] TSTools.lc7.x = [] TSTools.lc7.display_legend = False return else: ccd_tools.plot_pyccd(dfPyCCD, TSTools.results, band_index, (0, 4000), TSTools.lc6, TSTools.lc7) TSTools.lc7.display_legend = True # Clear pyccd results def clear_pyccd2(b): TSTools.lc6.x = [] TSTools.lc7.y = [] ####### Widget Interactions ####### dc = ipyleaflet.DrawControl(marker={'shapeOptions': {'color': '#ff0000'}}, polygon={}, circle={}, circlemarker={}, polyline={}) zoom = 5 layout = widgets.Layout(width='50%') center = (3.3890701010382958, -67.32297252983098) m = lft.make_map(zoom, layout, center) # Display controls ylim2.observe(change_yaxis2) xlim2.observe(change_xaxis2) clear_layers.on_click(clear_map) band_selector2.observe(on_band_selection2, names='value') image_band_1.observe(change_image_band1, names='value') image_band_2.observe(change_image_band2, names='value') image_band_3.observe(change_image_band3, names='value') # pyccd pyccd_button2.on_click(do_pyccd2) toggle_pyccd_button2.on_click(clear_pyccd2) # Plots lc3.on_element_click(add_image2) lc3.tooltip = hover_label lc3.on_hover(hover_event) lc8.on_element_click(add_image2) lc8.tooltip = hover_label lc8.on_hover(hover_event) # Mapping measure = ipyleaflet.MeasureControl(position='bottomleft', active_color = 'orange', primary_length_unit = 'kilometers' ) measure.completed_color = 'red' dc.on_draw(do_draw) m.add_control(dc) m.add_control(measure) m.add_control(ipyleaflet.LayersControl())
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 plot_geo_shapes_vis(data, nuts_shapes, nuts_ids_columns, color_column, timestamp_column): def plot_cbar(name, logarithmic=False): vmin, vmax = app_state['vmin'], app_state['vmax'] if vmin == vmax or any(pd.isna([vmin, vmax])): return fig, ax = plt.subplots(figsize=(.3, 10)) norm = matplotlib.colors.LogNorm( vmin, vmax) if logarithmic else matplotlib.colors.Normalize( vmin, vmax) cbar = matplotlib.colorbar.ColorbarBase(ax, cmap=plt.get_cmap(name), norm=norm, orientation='vertical') return cbar def change_date_range(change): data = _date_filter(app_state['data'], change['new'], timestamp_column=timestamp_column).dropna( subset=nuts_ids_columns, how='all') merged_dfs = [ merge_df(data=data, nuts_shapes=nuts_shapes, nuts_ids_column=nuts_ids_column, color_column=color_column, level=level_selector.value, levels=app_state['nuts_levels']) for nuts_ids_column in nuts_ids_columns ] app_state['vmax'] = np.max( [df[color_column].max() for df in merged_dfs]) interactive_output( plot_cbar, dict(name=cmap_selector, logarithmic=logarithmic_cbox)) m.layers = [l for l in m.layers if type(l) != ipyleaflet.LayerGroup] for merged_df, nuts_ids_column in zip(merged_dfs, nuts_ids_columns): table_columns = [ '_timestamp', 'text_translated', 'num_persons', 'mode', *[col for col in nuts_ids_columns if col != nuts_ids_column] ] layer = get_shapes_heatmap(data=merged_df, nuts_ids_column=nuts_ids_column, color_column=color_column, info_widget_html=info_widget, vmin=app_state['vmin'], vmax=app_state['vmax'], full_data=app_state['full_data'], time_hist=time_hist, date_limits=change['new'], tweets_table=tweets_table, cmap=app_state['cmap'], table_columns=table_columns, logarithmic=app_state['logarithmic']) m.add_layer(layer) if 'full_groups' not in app_state: app_state['full_groups'] = [ l.layers for l in m.layers if type(l) is ipyleaflet.LayerGroup ] cbar_widget.children = [ interactive_output( plot_cbar, dict(name=cmap_selector, logarithmic=logarithmic_cbox)) ] def change_level_layers(change={}): def change_layers(layer_group: ipyleaflet.LayerGroup, all_layers: list): new_layers = [ l for l in all_layers if l.data['features'][0]['properties'] ['LEVL_CODE'] == app_state['level'] ] layer_group.layers = new_layers if app_state[ 'level'] != 'all' else all_layers layer_groups = [ l for l in m.layers if type(l) is ipyleaflet.LayerGroup ] if 'new' in change: app_state['level'] = change['new'] for layer_group, full_group in zip(layer_groups, app_state['full_groups']): change_layers(layer_group, full_group) def change_colormap(): cmap, logarithmic = app_state['cmap'], app_state['logarithmic'] def update_layer(l): val = l.data['features'][0]['properties'][color_column] color = get_color(val, cmap=cmap, vmin=app_state['vmin'], vmax=app_state['vmax'], logarithmic=logarithmic) l.style.update({'fillColor': color, 'color': color}) l.hover_style.update({'fillColor': color, 'color': color}) new_layer = ipyleaflet.GeoJSON(data=l.data, style=l.style, hover_style=l.hover_style) new_layer._hover_callbacks = l._hover_callbacks new_layer._click_callbacks = l._click_callbacks return new_layer app_state['full_groups'] = [[update_layer(l) for l in layers] for layers in app_state['full_groups']] change_level_layers() def change_colormap_name(change): app_state['cmap'] = change['new'] change_colormap() def change_colormap_log(change): app_state['logarithmic'] = change['new'] change_colormap() 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 on_zoom(change, offset=-5): if m.zoom != app_state['zoom']: app_state['zoom'] = m.zoom if level_on_zoom.value: min_level, max_level = np.min( app_state['nuts_levels']), np.max(app_state['nuts_levels']) level = min(max_level, max(min_level, m.zoom + offset)) app_state['level'] = level level_selector.value = level app_state = dict(zoom=4, data=data.dropna(subset=nuts_ids_columns, how='all'), cmap='viridis', logarithmic=False, vmin=1, vmax=1, full_data=data.copy(), level='all', nuts_levels=sorted(nuts_shapes['LEVL_CODE'].unique())) m = ipyleaflet.Map(center=(51, 10), zoom=app_state['zoom'], scroll_wheel_zoom=True, zoom_control=False) m.layout.height = '900px' info_widget_default_text = 'Hover over a Region<br>Click it to see tweets' info_widget = widgets.HTML(info_widget_default_text) add_widget(info_widget, pos='topright', margin='0px 5px 0px 5px') loading_wrapper = _loading_wrapper_factory(info_widget, info_widget_default_text) time_hist = widgets.HBox([]) add_widget(time_hist, pos='bottomleft') tweets_table = widgets.HTML(layout=widgets.Layout( overflow='scroll_hidden')) tweets_box = widgets.HBox([tweets_table], layout=Layout(max_height='400px', overflow_y='auto', max_width='900px')) add_widget(tweets_box, pos='bottomleft') time_slider = get_time_slider(app_state['data']) time_slider.observe(loading_wrapper(change_date_range), type='change', names=('value', )) add_widget(time_slider, 'topleft', margin='0px 5px 0px 5px') level_selector = widgets.Dropdown( options=['all', *app_state['nuts_levels']], description='NUTS levels', layout=Layout(max_width='180px')) level_selector.observe(handler=loading_wrapper(change_level_layers), type='change', names=('value', )) level_on_zoom = widgets.Checkbox(value=True, description='with zoom', layout=Layout(max_width='180px')) level_control = widgets.VBox([level_selector, level_on_zoom]) cmap_selector = widgets.Dropdown( options=['viridis', 'inferno', 'magma', 'winter', 'cool'], description='colormap', layout=Layout(max_width='180px')) logarithmic_cbox = widgets.Checkbox(description='logarithmic', layout=Layout(max_width='180px')) cmap_control = widgets.VBox([cmap_selector, logarithmic_cbox]) cmap_selector.observe(handler=loading_wrapper(change_colormap_name), type='change', names=('value', )) logarithmic_cbox.observe(handler=loading_wrapper(change_colormap_log), type='change', names=('value', )) add_widget(widgets.HBox([level_control, cmap_control]), pos='topleft', margin='5px 5px 0px 5px') cbar_widget = widgets.HBox([ interactive_output( plot_cbar, dict(name=cmap_selector, logarithmic=logarithmic_cbox)) ]) add_widget(cbar_widget, pos='bottomright') m.add_control(ipyleaflet.LayersControl()) m.add_control(ipyleaflet.FullScreenControl()) m.observe(handler=on_zoom) change_date_range(dict(new=time_slider.value)) display(m)
class Plot_interface(object): """Class to handle map and plot interaction""" # Declare class attributes pyccd_flag = False pyccd_flag2 = False current_band = '' band_index1 = 4 band_index2 = 4 click_col = '' point_color = ['#43a2ca'] click_df = pd.DataFrame() sample_col = '' sample_df = pd.DataFrame() PyCCDdf = pd.DataFrame() table = pd.DataFrame() band_list = ['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'] year_range = [1986, 2018] doy_range = [1, 365] step = 1 #in years # Create widget controls next_pt = Button(value=False, description='Next point', disabled=False) previous_pt = Button(value=False, description='Previous point', disabled=False) pyccd_button = Button(value=False, description='Run PyCCD 1', disabled=False) pyccd_button2 = Button(value=False, description='Run PyCCD 2', disabled=False) band_selector1 = Dropdown( options=['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'], description='Select band', value=None) band_selector2 = Dropdown( options=['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'], description='Select band', value=None) image_band_1 = Dropdown( options=['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'], description='Red:', value='SWIR1') image_band_2 = Dropdown( options=['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'], description='Green:', value='NIR') image_band_3 = Dropdown( options=['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'], description='Blue:', value='RED') stretch_min = FloatText(value=0, description='Min:', disabled=False) stretch_max = FloatText(value=6000, description='Min:', disabled=False) # Clear layers on map clear_layers = Button(value=False, description='Clear Map', disabled=False) # Color points by DOY color_check = widgets.Checkbox(value=False, description='Color DOY', disabled=False) idBox = widgets.Text(value='0', description='ID:', disabled=False) ylim = widgets.IntRangeSlider(value=[0, 4000], min=0, max=10000, step=500, description='YLim:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d') xlim = widgets.IntRangeSlider(value=[2000, 2018], min=1986, max=2018, step=1, description='XLim:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d') ylim2 = widgets.IntRangeSlider(value=[0, 4000], min=0, max=10000, step=500, description='YLim:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d') xlim2 = widgets.IntRangeSlider(value=[2000, 2018], min=1986, max=2018, step=1, description='XLim:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d') coords_label = Label() pt_message = HTML("Current ID: ") time_label = HTML(value='') selected_label = HTML("ID of selected point") hover_label = HTML("test value") text_brush = HTML(value='Selected year range:') kml_link = HTML(value='KML:') error_label = HTML(value='Load a point') # Create map including streets and satellite and controls m = ipyleaflet.Map(zoom=5, layout={'height': '400px'}, center=(3.3890701010382958, -67.32297252983098), dragging=True, close_popup_on_click=False, basemap=ipyleaflet.basemaps.Esri.WorldStreetMap) streets = ipyleaflet.basemap_to_tiles( ipyleaflet.basemaps.Esri.WorldImagery) m.add_layer(streets) dc = ipyleaflet.DrawControl(marker={'shapeOptions': { 'color': '#ff0000' }}, polygon={}, circle={}, circlemarker={}, polyline={}) # Table widget table_widget = qgrid.show_grid(table, show_toolbar=False) # Set plots # Plot scales. HERE lc1_x = bqplot.DateScale(min=datetime.date(xlim.value[0], 2, 1), max=datetime.date(xlim.value[1], 1, 1)) # DOY scale lc1_x3 = bqplot.LinearScale(min=0, max=365) lc2_y = bqplot.LinearScale(min=ylim.value[0], max=ylim.value[1]) lc1_x2 = bqplot.DateScale(min=datetime.date(xlim.value[0], 2, 1), max=datetime.date(xlim.value[1], 1, 1)) lc2_y2 = bqplot.LinearScale(min=ylim.value[0], max=ylim.value[1]) # Main scatter plot for samples lc2 = bqplot.Scatter(x=[], y=[], scales={ 'x': lc1_x, 'y': lc2_y }, size=[1, 1], interactions={ 'click': 'select', 'hover': 'tooltip' }, selected_style={ 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, unselected_style={'opacity': 0.5}, display_legend=True, labels=['Sample point']) # Pyccd model fit lc4 = bqplot.Lines( x=[], y=[], colors=['black'], stroke_width=3, scales={ 'x': lc1_x, 'y': lc2_y }, size=[1, 1], ) # Pyccd model break lc5 = bqplot.Scatter(x=[], y=[], marker='triangle-up', colors=['red'], scales={ 'x': lc1_x, 'y': lc2_y }, size=[1, 1], display_legend=False, labels=['Model Endpoint']) # Scatter plot for clicked points in map lc3 = bqplot.Scatter(x=[], y=[], scales={ 'x': lc1_x2, 'y': lc2_y2 }, size=[1, 1], colors=['gray'], interactions={ 'click': 'select', 'hover': 'tooltip' }, selected_style={ 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, unselected_style={'opacity': 0.5}, display_legend=True, labels=['Clicked point']) # Pyccd model fit for clicked point lc6 = bqplot.Lines( x=[], y=[], colors=['black'], stroke_width=3, scales={ 'x': lc1_x2, 'y': lc2_y2 }, size=[1, 1], ) # Pyccd model break for clicked point lc7 = bqplot.Scatter(x=[], y=[], marker='triangle-up', colors=['red'], scales={ 'x': lc1_x2, 'y': lc2_y2 }, size=[1, 1], display_legend=False, labels=['Model Endpoint']) # Scatter for sample DOY lc8 = bqplot.Scatter(x=[], y=[], scales={ 'x': lc1_x3, 'y': lc2_y }, size=[1, 1], interactions={ 'click': 'select', 'hover': 'tooltip' }, selected_style={ 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, unselected_style={'opacity': 0.5}, display_legend=True, labels=['Sample point']) # Plot axes. x_ax1 = bqplot.Axis(label='Date', scale=lc1_x, num_ticks=6, tick_format='%Y') x_ax2 = bqplot.Axis(label='Date', scale=lc1_x2, num_ticks=6, tick_format='%Y') x_ax3 = bqplot.Axis(label='DOY', scale=lc1_x3, num_ticks=6) x_ay1 = bqplot.Axis(label='SWIR1', scale=lc2_y, orientation='vertical') x_ay2 = bqplot.Axis(label='SWIR1', scale=lc2_y2, orientation='vertical') # Create a figure for sample points. fig = bqplot.Figure(marks=[lc2, lc4, lc5], axes=[x_ax1, x_ay1], layout={ 'height': '300px', 'width': '100%' }, title="Sample TS") # Create a figure for clicked points. fig2 = bqplot.Figure(marks=[lc3, lc6, lc7], axes=[x_ax2, x_ay2], layout={ 'height': '300px', 'width': '100%' }, title="Clicked TS") # Create a figure for sample DOY. fig3 = bqplot.Figure(marks=[lc8], axes=[x_ax3, x_ay1], layout={ 'height': '300px', 'width': '100%' }, title="Clicked TS") def __init__(self, navigate): Plot_interface.navigate = navigate Plot_interface.band_index1 = 4 Plot_interface.band_index2 = 4 Plot_interface.pyccd_flag = False Plot_interface.pyccd_flag2 = False Plot_interface.table = None # Set up database conn = sqlite3.connect(Plot_interface.navigate.dbPath) Plot_interface.current_id = Plot_interface.navigate.current_id Plot_interface.c = conn.cursor() Plot_interface.minv = 0 Plot_interface.maxv = 6000 Plot_interface.b1 = 'SWIR1' Plot_interface.b2 = 'NIR' Plot_interface.b3 = 'RED' @classmethod def map_point(self): gjson = ipyleaflet.GeoJSON( data=Plot_interface.navigate.fc_df['geometry'][ Plot_interface.current_id], name="Sample point") Plot_interface.m.center = gjson.data['coordinates'][::-1] Plot_interface.m.zoom = 12 Plot_interface.m.add_layer(gjson) kmlstr = ee.FeatureCollection( ee.Geometry.Point(Plot_interface.navigate.fc_df['geometry'][ Plot_interface.current_id]['coordinates'])).getDownloadURL( "kml") Plot_interface.kml_link.value = "<a '_blank' rel='noopener noreferrer' href={}>KML Link</a>".format( kmlstr) @classmethod def get_ts(self): #try: Plot_interface.error_label.value = 'Loading' Plot_interface.current_band = Plot_interface.band_list[ Plot_interface.band_index1] Plot_interface.sample_col = get_full_collection( Plot_interface.navigate.fc_df['geometry'][ Plot_interface.current_id]['coordinates'], Plot_interface.year_range, Plot_interface.doy_range) Plot_interface.sample_df = get_df_full( Plot_interface.sample_col, Plot_interface.navigate.fc_df['geometry'][ Plot_interface.current_id]['coordinates']).dropna() Plot_interface.error_label.value = 'Point loaded!' #except: # Plot_interface.error_label.value = 'Point could not be loaded!' def clear_map(b): Plot_interface.m.clear_layers() Plot_interface.m.add_layer(Plot_interface.streets) Plot_interface.map_point() @classmethod def plot_ts(self): current_band = Plot_interface.band_list[Plot_interface.band_index1] Plot_interface.lc2.x = Plot_interface.sample_df['datetime'] if Plot_interface.color_check.value == False: Plot_interface.lc2.colors = list(Plot_interface.point_color) Plot_interface.lc8.colors = list(Plot_interface.point_color) else: Plot_interface.lc2.colors = list( Plot_interface.sample_df['color'].values) Plot_interface.lc8.colors = list( Plot_interface.sample_df['color'].values) Plot_interface.lc2.y = Plot_interface.sample_df[current_band] Plot_interface.x_ay1.label = current_band Plot_interface.lc4.x = [] Plot_interface.lc4.y = [] Plot_interface.lc5.x = [] Plot_interface.lc5.y = [] Plot_interface.lc8.x = Plot_interface.sample_df['doy'] Plot_interface.lc8.y = Plot_interface.sample_df[current_band] #if pyccd_flag: if Plot_interface.pyccd_flag: Plot_interface.run_pyccd(0) # Go back or forth between sample points def advance(b): # Plot point in map Plot_interface.lc4.x = [] Plot_interface.lc4.y = [] Plot_interface.lc5.x = [] Plot_interface.lc5.y = [] Plot_interface.lc5.display_legend = False Plot_interface.pyccd_flag = False Plot_interface.current_id += 1 Plot_interface.pt_message.value = "Point ID: {}".format( Plot_interface.current_id) Plot_interface.map_point() Plot_interface.get_ts() Plot_interface.plot_ts() Plot_interface.change_table(0) Plot_interface.navigate.valid.value = False Plot_interface.navigate.description = 'Not Saved' def decrease(b): # Plot point in map Plot_interface.lc4.x = [] Plot_interface.lc4.y = [] Plot_interface.lc5.x = [] Plot_interface.lc5.y = [] Plot_interface.lc5.display_legend = False Plot_interface.pyccd_flag = False Plot_interface.current_id -= 1 Plot_interface.pt_message.value = "Point ID: {}".format( Plot_interface.current_id) Plot_interface.map_point() Plot_interface.get_ts() Plot_interface.plot_ts() Plot_interface.change_table(0) Plot_interface.navigate.valid.value = False Plot_interface.navigate.description = 'Not Saved' def change_table(b): # Update the table based on current ID # Get header cursor = Plot_interface.c.execute('select * from measures') names = list(map(lambda x: x[0], cursor.description)) previous_inputs = pd.DataFrame() for i, row in enumerate( Plot_interface.c.execute( "SELECT * FROM measures WHERE id = '%s'" % Plot_interface.current_id)): previous_inputs[i] = row previous_inputs = previous_inputs.T if previous_inputs.shape[0] > 0: previous_inputs.columns = names Plot_interface.table_widget.df = previous_inputs # Functions for changing image stretch def change_image_band1(change): new_band = change['new'] Plot_interface.b1 = new_band def change_image_band2(change): new_band = change['new'] Plot_interface.b2 = new_band def change_image_band3(change): new_band = change['new'] Plot_interface.b3 = new_band # Band selection for sample point def on_band_selection1(change): new_band = change['new'] #global band_index band_index = change['owner'].index Plot_interface.band_index1 = band_index Plot_interface.plot_ts() # Band selection for clicked point def on_band_selection2(change): new_band = change['new'] band_index = change['owner'].index Plot_interface.band_index2 = band_index Plot_interface.lc3.x = Plot_interface.click_df['datetime'] Plot_interface.lc3.y = Plot_interface.click_df[new_band] Plot_interface.x_ay2.label = new_band if Plot_interface.pyccd_flag2: Plot_interface.run_pyccd2(0) def change_yaxis(value): Plot_interface.lc2_y.min = Plot_interface.ylim.value[0] Plot_interface.lc2_y.max = Plot_interface.ylim.value[1] def change_xaxis(value): Plot_interface.lc1_x.min = datetime.date(Plot_interface.xlim.value[0], 2, 1) Plot_interface.lc1_x.max = datetime.date(Plot_interface.xlim.value[1], 2, 1) Plot_interface.year_range = [ Plot_interface.xlim.value[0], Plot_interface.xlim.value[1] ] def change_yaxis2(value): Plot_interface.lc2_y2.min = Plot_interface.ylim2.value[0] Plot_interface.lc2_y2.max = Plot_interface.ylim2.value[1] def change_xaxis2(value): Plot_interface.lc1_x2.min = datetime.date( Plot_interface.xlim2.value[0], 2, 1) Plot_interface.lc1_x2.max = datetime.date( Plot_interface.xlim2.value[1], 2, 1) def hover_event(self, target): Plot_interface.hover_label.value = str(target['data']['x']) # Add layer from clicked point in sample TS figure def click_event(self, target): pt_index = target['data']['index'] current_band = Plot_interface.band_list[Plot_interface.band_index1] image_id = Plot_interface.sample_df['id'].values[pt_index] selected_image = ee.Image( Plot_interface.sample_col.filterMetadata('system:index', 'equals', image_id).first()) tile_url = GetTileLayerUrl( selected_image.visualize(min=Plot_interface.stretch_min.value, max=Plot_interface.stretch_max.value, bands=[ Plot_interface.b1, Plot_interface.b2, Plot_interface.b3 ])) Plot_interface.m.add_layer( ipyleaflet.TileLayer(url=tile_url, name=image_id)) # Add layer from clicked point in clicked TS figure def click_event2(self, target): pt_index = target['data']['index'] current_band = Plot_interface.band_list[Plot_interface.band_index2] #Find clicked image. .values needed to access the nth element of that list instead of indexing by ID image_id = Plot_interface.click_df['id'].values[pt_index] selected_image = ee.Image( Plot_interface.click_col.filterMetadata('system:index', 'equals', image_id).first()) tile_url = GetTileLayerUrl( selected_image.visualize(min=Plot_interface.minv, max=Plot_interface.maxv, bands=[ Plot_interface.b1, Plot_interface.b2, Plot_interface.b3 ])) Plot_interface.m.add_layer( ipyleaflet.TileLayer(url=tile_url, name=image_id)) # Plot TS from clicked point def handle_draw(self, action, geo_json): # Get the selected coordinates from the map's drawing control. current_band = Plot_interface.band_list[Plot_interface.band_index2] coords = geo_json['geometry']['coordinates'] Plot_interface.click_col = get_full_collection( coords, Plot_interface.year_range, Plot_interface.doy_range) Plot_interface.click_df = get_df_full(Plot_interface.click_col, coords).dropna() Plot_interface.lc6.x = [] Plot_interface.lc6.y = [] Plot_interface.lc7.x = [] Plot_interface.lc7.y = [] Plot_interface.lc3.x = Plot_interface.click_df['datetime'] Plot_interface.lc3.y = Plot_interface.click_df[current_band] if Plot_interface.color_check.value == False: Plot_interface.lc3.colors = list(Plot_interface.point_color) else: Plot_interface.lc3.colors = list( Plot_interface.click_df['color'].values) # Plotting pyccd def plot_pyccd(results, band, plotband, dates, yl, ylabel, ts_type): mask = np.array(results['processing_mask']).astype(np.bool_) predicted_values = [] prediction_dates = [] break_dates = [] start_dates = [] for num, result in enumerate(results['change_models']): days = np.arange(result['start_day'], result['end_day'] + 1) prediction_dates.append(days) break_dates.append(result['break_day']) start_dates.append(result['start_day']) intercept = result[list(result.keys())[6 + band]]['intercept'] coef = result[list(result.keys())[6 + band]]['coefficients'] predicted_values.append( intercept + coef[0] * days + coef[1] * np.cos(days * 1 * 2 * np.pi / 365.25) + coef[2] * np.sin(days * 1 * 2 * np.pi / 365.25) + coef[3] * np.cos(days * 2 * 2 * np.pi / 365.25) + coef[4] * np.sin(days * 2 * 2 * np.pi / 365.25) + coef[5] * np.cos(days * 3 * 2 * np.pi / 365.25) + coef[6] * np.sin(days * 3 * 2 * np.pi / 365.25)) num_breaks = len(break_dates) break_y = [plotband[dates == i][0] for i in break_dates] #break_y = [0] * num_breaks break_dates_plot = [ datetime.datetime.fromordinal(i).strftime('%Y-%m-%d %H:%M:%S.%f') for i in break_dates ] plot_dates = np.array( [datetime.datetime.fromordinal(i) for i in (dates)]) # Predicted curves all_dates = [] all_preds = [] for _preddate, _predvalue in zip(prediction_dates, predicted_values): all_dates.append(_preddate) all_preds.append(_predvalue) all_preds = [item for sublist in all_preds for item in sublist] all_dates = [item for sublist in all_dates for item in sublist] date_ord = [ datetime.datetime.fromordinal(i).strftime('%Y-%m-%d %H:%M:%S.%f') for i in all_dates ] _x = np.array(date_ord, dtype='datetime64') _y = all_preds if ts_type == 'sample_ts': Plot_interface.lc4.x = _x Plot_interface.lc4.y = _y Plot_interface.lc5.x = np.array(break_dates_plot, dtype='datetime64') Plot_interface.lc5.y = break_y elif ts_type == 'clicked_ts': Plot_interface.lc6.x = _x Plot_interface.lc6.y = _y Plot_interface.lc7.x = np.array(break_dates_plot, dtype='datetime64') Plot_interface.lc7.y = break_y # Go to a specific sample def go_to_sample(b): # Plot point in map Plot_interface.lc4.x = [] Plot_interface.lc4.y = [] Plot_interface.lc5.x = [] Plot_interface.lc5.y = [] Plot_interface.lc5.display_legend = False Plot_interface.pyccd_flag = False Plot_interface.current_id = int(b.value) Plot_interface.pt_message.value = "Point ID: {}".format( Plot_interface.current_id) Plot_interface.navigate.valid.value = False Plot_interface.navigate.description = 'Not Saved' Plot_interface.map_point() Plot_interface.get_ts() Plot_interface.plot_ts() # Run pyccd def run_pyccd(b): # Run pyCCD on current point Plot_interface.pyccd_flag = True Plot_interface.lc5.display_legend = True dfPyCCD = Plot_interface.sample_df dfPyCCD['pixel_qa'][dfPyCCD['pixel_qa'] > 4] = 0 #TODO: Paramaterize everything params = { 'QA_BITPACKED': False, 'QA_FILL': 255, 'QA_CLEAR': 0, 'QA_WATER': 1, 'QA_SHADOW': 2, 'QA_SNOW': 3, 'QA_CLOUD': 4 } dates = np.array(dfPyCCD['ord_time']) blues = np.array(dfPyCCD['BLUE']) greens = np.array(dfPyCCD['GREEN']) reds = np.array(dfPyCCD['RED']) nirs = np.array(dfPyCCD['NIR']) swir1s = np.array(dfPyCCD['SWIR1']) swir2s = np.array(dfPyCCD['SWIR2']) thermals = np.array(dfPyCCD['THERMAL']) qas = np.array(dfPyCCD['pixel_qa']) results = ccd.detect(dates, blues, greens, reds, nirs, swir1s, swir2s, thermals, qas, params=params) band_names = [ 'Blue SR', 'Green SR', 'Red SR', 'NIR SR', 'SWIR1 SR', 'SWIR2 SR', 'THERMAL' ] plotlabel = band_names[Plot_interface.band_index1] plot_arrays = [blues, greens, reds, nirs, swir1s, swir2s] plotband = plot_arrays[Plot_interface.band_index1] Plot_interface.plot_pyccd(results, Plot_interface.band_index1, plotband, dates, (0, 4000), 'PyCCD Results', 'sample_ts') def run_pyccd2(b): # Run pyCCD on current point Plot_interface.pyccd_flag2 = True # Display the legend Plot_interface.lc7.display_legend = True dfPyCCD = Plot_interface.click_df # First two lines no longer required bc we are removing NA's when we load the TS dfPyCCD['pixel_qa'][dfPyCCD['pixel_qa'] > 4] = 0 #TODO: Paramaterize everything params = { 'QA_BITPACKED': False, 'QA_FILL': 255, 'QA_CLEAR': 0, 'QA_WATER': 1, 'QA_SHADOW': 2, 'QA_SNOW': 3, 'QA_CLOUD': 4 } dates = np.array(dfPyCCD['ord_time']) blues = np.array(dfPyCCD['BLUE']) greens = np.array(dfPyCCD['GREEN']) reds = np.array(dfPyCCD['RED']) nirs = np.array(dfPyCCD['NIR']) swir1s = np.array(dfPyCCD['SWIR1']) swir2s = np.array(dfPyCCD['SWIR2']) thermals = np.array(dfPyCCD['THERMAL']) qas = np.array(dfPyCCD['pixel_qa']) results = ccd.detect(dates, blues, greens, reds, nirs, swir1s, swir2s, thermals, qas, params=params) band_names = [ 'Blue SR', 'Green SR', 'Red SR', 'NIR SR', 'SWIR1 SR', 'SWIR2 SR', 'THERMAL' ] plotlabel = band_names[Plot_interface.band_index2] plot_arrays = [blues, greens, reds, nirs, swir1s, swir2s] plotband = plot_arrays[Plot_interface.band_index2] Plot_interface.plot_pyccd(results, Plot_interface.band_index2, plotband, dates, (0, 4000), 'PyCCD Results', 'clicked_ts') ylim.observe(change_yaxis) xlim.observe(change_xaxis) ylim2.observe(change_yaxis2) xlim2.observe(change_xaxis2) next_pt.on_click(advance) previous_pt.on_click(decrease) pyccd_button.on_click(run_pyccd) pyccd_button2.on_click(run_pyccd2) clear_layers.on_click(clear_map) band_selector1.observe(on_band_selection1, names='value') band_selector2.observe(on_band_selection2, names='value') image_band_1.observe(change_image_band1, names='value') image_band_2.observe(change_image_band2, names='value') image_band_3.observe(change_image_band3, names='value') lc2.on_element_click(click_event) lc2.tooltip = hover_label lc2.on_hover(hover_event) lc3.on_element_click(click_event2) lc3.tooltip = hover_label lc3.on_hover(hover_event) idBox.on_submit(go_to_sample) dc.on_draw(handle_draw) m.add_control(dc) m.add_control(ipyleaflet.LayersControl())
def plot_maps_dataset_list(dataset_list, client, column='guid', category=False, basemap=True): """Create map window using dataset list. Should be okay whether it is shapefile or geotiff Args: dataset_list (list): A list of dataset to be mapped. column (str): column name to be plot client (Client): pyincore service Client Object category (boolean): turn on/off category option basemap (boolean): turn on/off base map (e.g. openstreetmap) Returns: map(ipyleaflet.Map): ipyleaflet map obejct """ layer_list = [] bbox_all = [9999, 9999, -9999, -9999] for dataset in dataset_list: # check if dataset is shapefile or raster try: if dataset.metadata['format'].lower() == 'shapefile': gdf = gpd.read_file(dataset.local_file_path) geodata = GeoUtil.create_geodata_from_geodataframe( gdf, dataset.metadata['title']) bbox = gdf.total_bounds bbox_all = GeoUtil.merge_bbox(bbox_all, bbox) layer_list.append(geodata) elif dataset.metadata['format'].lower( ) == 'table' or dataset.metadata['format'] == 'csv': # check source dataset gdf = GeoUtil.join_table_dataset_with_source_dataset( dataset, client) if gdf is None: print(dataset.metadata['title'] + "'s data format" + dataset.metadata['format'] + " is not supported.") else: geodata = GeoUtil.create_geodata_from_geodataframe( gdf, dataset.metadata['title']) bbox = gdf.total_bounds bbox_all = GeoUtil.merge_bbox(bbox_all, bbox) layer_list.append(geodata) elif dataset.metadata['format'].lower() == 'raster' \ or dataset.metadata['format'].lower() == 'geotif' \ or dataset.metadata['format'].lower() == 'geotif': input_path = dataset.get_file_path('tif') bbox = GeoUtil.get_raster_boundary(input_path) bbox_all = GeoUtil.merge_bbox(bbox_all, bbox) image_url = GeoUtil.create_data_img_url_from_geotiff_for_ipyleaflet( input_path) image = ImageOverlay(url=image_url, bounds=((bbox[1], bbox[0]), (bbox[3], bbox[2]))) layer_list.append(image) else: print(dataset.metadata['title'] + "'s data format" + dataset.metadata['format'] + " is not supported.") except Exception: print( "There is a problem in dataset format for ' + dataset.metadata['title'] + '." ) map = GeoUtil.get_ipyleaflet_map(bbox_all) for layer in layer_list: map.add_layer(layer) map.add_control(ipylft.LayersControl()) return map
def get_wms_map(datasets: list, wms_url=globals.INCORE_GEOSERVER_WMS_URL, layer_check=True): """Get a map with WMS layers from list of datasets Args: datasets (list): list of pyincore Dataset objects wms_url (str): URL of WMS server layer_check (bool): boolean for checking the layer availability in wms server Returns: obj: A ipylfealet Map object """ # TODO: how to add a style for each WMS layers (pre-defined styles on WMS server) wms_layers = [] # (min_lat, min_lon, max_lat, max_lon) bbox_all = [9999, 9999, -9999, -9999] # the reason for checking this layer_check on/off is that # the process could take very long time based on the number of layers in geoserver. # the process could be relatively faster if there are not many layers in the geoserver # but the processing time could increase based upon the increase of the layers in the server # by putting on/off for this layer checking, it could make the process faster. if layer_check: wms = WebMapService(wms_url + "?", version='1.1.1') for dataset in datasets: wms_layer_name = 'incore:' + dataset.id # check availability of the wms layer # TODO in here, the question is the, should this error quit whole process # or just keep going and show the error message for only the layer with error # if it needs to throw an error and exit the process, use following code block # if layer_check: # wms[dataset.id].boundingBox # else: # raise KeyError( # "Error: The layer " + str(dataset.id) + " does not exist in the wms server") # if it needs to keep going with showing all the layers, use following code block if layer_check: try: wms[dataset.id].boundingBox except KeyError: print("Error: The layer " + str(dataset.id) + " does not exist in the wms server") wms_layer = ipylft.WMSLayer(url=wms_url, layers=wms_layer_name, format='image/png', transparent=True, name=dataset.metadata['title']) wms_layers.append(wms_layer) bbox = dataset.metadata['boundingBox'] bbox_all = GeoUtil.merge_bbox(bbox_all, bbox) m = GeoUtil.get_ipyleaflet_map(bbox_all) for layer in wms_layers: m.add_layer(layer) m.add_control(ipylft.LayersControl()) return m
class pyccd_explorer(object): def __init__(self): measures.band_index1 = 4 measures.band_index2 = 4 measures.pyccd_flag = False measures.pyccd_flag2 = False measures.minv = 0 measures.maxv = 6000 measures.b1 = 'SWIR1' measures.b2 = 'NIR' measures.b3 = 'RED' # Starting variables pyccd_flag = False pyccd_flag2 = False current_band = '' band_index1 = 4 band_index2 = 4 click_col = '' point_color = ['#43a2ca'] click_df = pd.DataFrame() sample_col = '' sample_df = pd.DataFrame() PyCCDdf = pd.DataFrame() table = pd.DataFrame() band_list = ['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'] year_range = [1986, 2018] doy_range = [1, 365] step = 1 #in years current_id = 0 ylim = plots.make_range_slider([0, 4000], -10000, 10000, 500, 'YLim:') xlim = plots.make_range_slider([2000, 2018], 1984, 2019, 1, 'XLim:') ylim2 = plots.make_range_slider([0, 4000], -10000, 10000, 500, 'YLim:') xlim2 = plots.make_range_slider([2000, 2018], 1984, 2019, 1, 'XLim:') band_selector1 = plots.make_drop('SWIR1', band_list, 'Select band') band_selector2 = plots.make_drop('SWIR1', band_list, 'Select band') image_band_1 = plots.make_drop('RED', band_list, 'Red:') image_band_2 = plots.make_drop('GREEN', band_list, 'Green:') image_band_3 = plots.make_drop('BLUE', band_list, 'Blue:') # Checkbox color_check = plots.make_checkbox(False, 'Color DOY', False) stretch_min = plots.make_text_float(0, 0, 'Min:') stretch_max = plots.make_text_float(1450, 0, 'Max:') idBox = plots.make_text('0', '0', 'ID:') load_button = plots.make_button(False, 'Load', icon='') next_pt = plots.make_button(False, 'Next point', icon='') previous_pt = plots.make_button(False, 'Previous point', icon='') pyccd_button = plots.make_button(False, 'Run PyCCD 1', icon='') pyccd_button2 = plots.make_button(False, 'Run PyCCD 2', icon='') clear_layers = plots.make_button(False, 'Clear Map', icon='') # HTML pt_message = plots.make_html('Current ID: ') coord_message = plots.make_html('Lat, Lon: ') time_label = plots.make_html('') selected_label = plots.make_html('ID of selected point') hover_label = plots.make_html('Test Value') text_brush = plots.make_html('Selected year range:') kml_link = plots.make_html('KML:') error_label = plots.make_html('Load a point') # Plots # Scales # Dates lc1_x = plots.make_bq_scale('date', datetime.date(xlim.value[0], 2, 1), datetime.date(xlim.value[1], 1, 1)) lc1_x2 = plots.make_bq_scale('date', datetime.date(xlim.value[0], 2, 1), datetime.date(xlim.value[1], 1, 1)) # DOY lc1_x3 = plots.make_bq_scale('linear', 0, 365) # Reflectance lc2_y = plots.make_bq_scale('linear', ylim.value[0], ylim.value[1]) lc2_y2 = plots.make_bq_scale('linear', ylim.value[0], ylim.value[1]) # plots lc2 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x, 'y': lc2_y }, [1, 1], { 'click': 'select', 'hover': 'tooltip' }, { 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, {'opacity': 0.5}, display_legend=True, labels=['Sample point']) lc3 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x2, 'y': lc2_y2 }, [1, 1], { 'click': 'select', 'hover': 'tooltip' }, { 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, {'opacity': 0.5}, display_legend=True, labels=['Clicked point']) lc4 = plots.make_bq_plot('lines', [], [], { 'x': lc1_x, 'y': lc2_y }, [1, 1], {}, {}, {}, colors=['black'], stroke_width=3) lc5 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x, 'y': lc2_y }, [1, 1], {}, {}, {}, labels=['Model Endpoint'], colors=['red'], marker='triangle-up') lc6 = plots.make_bq_plot('lines', [], [], { 'x': lc1_x2, 'y': lc2_y2 }, [1, 1], {}, {}, {}, colors=['black'], stroke_width=3) lc7 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x2, 'y': lc2_y2 }, [1, 1], {}, {}, {}, labels=['Model Endpoint'], colors=['red'], marker='triangle-up') lc8 = plots.make_bq_plot('scatter', [], [], { 'x': lc1_x3, 'y': lc2_y }, [1, 1], { 'click': 'select', 'hover': 'tooltip' }, { 'opacity': 1.0, 'fill': 'DarkOrange', 'stroke': 'Red' }, {'opacity': 0.5}, display_legend=True, labels=['Sample point']) x_ax1 = plots.make_bq_axis('Date', lc1_x, num_ticks=6, tick_format='%Y', orientation='horizontal') x_ax2 = plots.make_bq_axis('Date', lc1_x2, num_ticks=6, tick_format='%Y', orientation='horizontal') x_ax3 = plots.make_bq_axis('DOY', lc1_x3, num_ticks=6, orientation='horizontal') y_ay1 = plots.make_bq_axis('SWIR1', lc2_y, orientation='vertical') y_ay2 = plots.make_bq_axis('SWIR1', lc2_y2, orientation='vertical') # Figures fig = plots.make_bq_figure([lc2, lc4, lc5], [x_ax1, y_ay1], { 'height': '300px', 'width': '100%' }, 'Sample TS') fig2 = plots.make_bq_figure([lc3, lc6, lc7], [x_ax2, y_ay2], { 'height': '300px', 'width': '100%' }, 'Clicked TS') fig3 = plots.make_bq_figure([lc8], [x_ax3, y_ay1], { 'height': '300px', 'width': '100%' }, 'Clicked TS') # Functions def load_everything(sender): # Load the sample as a feature collection sample_path = measures.sampleWidget.value fc_df = utils.fc2dfgeo(sample_path) measures.fc_df, first_index = utils.check_id(fc_df) measures.current_id = first_index - 1 measures.reset_everything() def change_yaxis(value): measures.lc2_y.min = measures.ylim.value[0] measures.lc2_y.max = measures.ylim.value[1] def change_xaxis(value): measures.lc1_x.min = datetime.date(measures.xlim.value[0], 2, 1) measures.lc1_x.max = datetime.date(measures.xlim.value[1], 2, 1) measures.year_range = [measures.xlim.value[0], measures.xlim.value[1]] def change_yaxis2(value): measures.lc2_y2.min = measures.ylim2.value[0] measures.lc2_y2.max = measures.ylim2.value[1] def change_xaxis2(value): measures.lc1_x2.min = datetime.date(measures.xlim2.value[0], 2, 1) measures.lc1_x2.max = datetime.date(measures.xlim2.value[1], 2, 1) def hover_event(self, target): measures.hover_label.value = str(target['data']['x']) def advance(b): # Plot point in map measures.lc4.x = [] measures.lc4.y = [] measures.lc5.x = [] measures.lc5.y = [] measures.lc5.display_legend = False measures.pyccd_flag = False measures.current_id += 1 measures.pt_message.value = "Point ID: {}".format(measures.current_id) measures.map_point() measures.get_ts() measures.plot_ts() def decrease(b): # Plot point in map measures.lc4.x = [] measures.lc4.y = [] measures.lc5.x = [] measures.lc5.y = [] measures.lc5.display_legend = False measures.pyccd_flag = False measures.current_id -= 1 measures.pt_message.value = "Point ID: {}".format(measures.current_id) measures.map_point() measures.get_ts() measures.plot_ts() # Go to a specific sample def go_to_sample(b): # Plot point in map measures.lc4.x = [] measures.lc4.y = [] measures.lc5.x = [] measures.lc5.y = [] measures.lc5.display_legend = False measures.pyccd_flag = False measures.current_id = int(b.value) measures.pt_message.value = "Point ID: {}".format(measures.current_id) measures.map_point() measures.get_ts() measures.plot_ts() # Functions for changing image stretch def change_image_band1(change): new_band = change['new'] measures.b1 = new_band def change_image_band2(change): new_band = change['new'] measures.b2 = new_band def change_image_band3(change): new_band = change['new'] measures.b3 = new_band # Band selection for sample point def on_band_selection1(change): band_index = change['owner'].index measures.band_index1 = band_index measures.plot_ts() # Band selection for clicked point def on_band_selection2(change): new_band = change['new'] band_index = change['owner'].index measures.band_index2 = band_index measures.lc3.x = measures.click_df['datetime'] measures.lc3.y = measures.click_df[new_band] measures.x_ay2.label = new_band if measures.pyccd_flag2: measures.do_pyccd2(0) def clear_map(b): lft.clear_map(measures.m, streets=True) measures.map_point() def add_image(self, target): m = measures.m df = measures.sample_df current_band = measures.band_list[measures.band_index1] sample_col = measures.sample_col stretch_min = measures.stretch_min stretch_max = measures.stretch_max b1 = measures.b1 b2 = measures.b2 b3 = measures.b3 lft.click_event(target, m, current_band, df, sample_col, stretch_min, stretch_max, b1, b2, b3) def add_image2(self, target): m = measures.m df = measures.click_df current_band = measures.band_list[measures.band_index2] sample_col = measures.click_col stretch_min = measures.minv stretch_max = measures.maxv b1 = measures.b1 b2 = measures.b2 b3 = measures.b3 lft.click_event(target, m, current_band, df, sample_col, stretch_min, stretch_max, b1, b2, b3) def do_draw(self, action, geo_json): current_band = measures.band_list[measures.band_index2] year_range = measures.year_range doy_range = measures.doy_range _col, _df = utils.handle_draw(action, geo_json, current_band, year_range, doy_range) measures.click_df = _df measures.click_col = _col measures.lc6.x = [] measures.lc6.y = [] measures.lc7.x = [] measures.lc7.y = [] measures.lc3.x = measures.click_df['datetime'] measures.lc3.y = measures.click_df[current_band] if measures.color_check.value == False: measures.lc3.colors = list(measures.point_color) else: measures.lc3.colors = list(measures.click_df['color'].values) def map_point(): zoom = 12 kml = measures.kml_link name = 'Sample point' data = measures.fc_df['geometry'][measures.current_id] measures.coord_message.value = "Lat, Lon: {}".format( data['coordinates']) lft.add_map_point(data, zoom, measures.m, kml, name) def get_ts(): measures.error_label.value = 'Loading' coords = measures.fc_df['geometry'][measures.current_id]['coordinates'] year_range = measures.year_range doy_range = measures.doy_range measures.current_band = measures.band_list[measures.band_index1] measures.sample_col = utils.get_full_collection( coords, year_range, doy_range) measures.sample_df = utils.get_df_full(measures.sample_col, coords).dropna() measures.error_label.value = 'Point Loaded!' def plot_ts(): df = measures.sample_df if measures.color_check.value == True: color_marks = list(measures.sample_df['color'].values) else: color_marks = list(measures.point_color) band = measures.band_list[measures.band_index1] plots.add_plot_ts(df, measures.lc2, band, color_marks) plots.add_plot_doy(df, measures.lc8, band, color_marks) if measures.pyccd_flag: measures.do_pyccd(0) def do_pyccd(b): pyccd_flag = measures.pyccd_flag display_legend = measures.lc5.display_legend dfPyCCD = measures.sample_df band_index = measures.band_index1 results = ccd_tools.run_pyccd(pyccd_flag, display_legend, dfPyCCD, band_index) ccd_tools.plot_pyccd(dfPyCCD, results, band_index, (0, 4000), measures.lc4, measures.lc5) def do_pyccd2(b): pyccd_flag = measures.pyccd_flag2 display_legend = measures.lc7.display_legend dfPyCCD = measures.click_df band_index = measures.band_index1 results = ccd_tools.run_pyccd(pyccd_flag, display_legend, dfPyCCD, band_index) ccd_tools.plot_pyccd(dfPyCCD, results, band_index, (0, 4000), measures.lc6, measures.lc7) # Load database and sample load_button.on_click(load_everything) # Map dc = ipyleaflet.DrawControl(marker={'shapeOptions': { 'color': '#ff0000' }}, polygon={}, circle={}, circlemarker={}, polyline={}) zoom = 5 layout = widgets.Layout(width='50%') center = (3.3890701010382958, -67.32297252983098) m = lft.make_map(zoom, layout, center) m = lft.add_basemap(m, ipyleaflet.basemaps.Esri.WorldImagery) # Display controls ylim.observe(change_yaxis) xlim.observe(change_xaxis) ylim2.observe(change_yaxis2) xlim2.observe(change_xaxis2) clear_layers.on_click(clear_map) band_selector1.observe(on_band_selection1, names='value') band_selector2.observe(on_band_selection2, names='value') image_band_1.observe(change_image_band1, names='value') image_band_2.observe(change_image_band2, names='value') image_band_3.observe(change_image_band3, names='value') # .samples next_pt.on_click(advance) previous_pt.on_click(decrease) # PyCCD pyccd_button.on_click(do_pyccd) pyccd_button2.on_click(do_pyccd2) # Plots lc2.on_element_click(add_image) lc2.tooltip = hover_label lc2.on_hover(hover_event) lc3.on_element_click(add_image2) lc3.tooltip = hover_label lc3.on_hover(hover_event) idBox.on_submit(go_to_sample) # Mapping dc.on_draw(do_draw) m.add_control(dc) m.add_control(ipyleaflet.LayersControl())
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')