From dc95c3732be81c98200b1b05dd41f99a2bd6e22e Mon Sep 17 00:00:00 2001 From: Qiusheng Wu Date: Sun, 13 Jun 2021 23:36:15 -0400 Subject: [PATCH] Added Planet basemaps GUI #9 --- docs/notebooks/20_planet_imagery.ipynb | 12 +-- examples/notebooks/20_planet_imagery.ipynb | 12 +-- leafmap/basemaps.py | 4 +- leafmap/common.py | 26 +++--- leafmap/leafmap.py | 90 +++++++++++++++++++ leafmap/toolbar.py | 100 ++++++++++++++++++++- 6 files changed, 214 insertions(+), 30 deletions(-) diff --git a/docs/notebooks/20_planet_imagery.ipynb b/docs/notebooks/20_planet_imagery.ipynb index d3dacfd2d5..7c1d601a49 100644 --- a/docs/notebooks/20_planet_imagery.ipynb +++ b/docs/notebooks/20_planet_imagery.ipynb @@ -26,7 +26,7 @@ "outputs": [], "source": [ "import os\n", - "import leafmap.foliumap as leafmap" + "import leafmap" ] }, { @@ -65,7 +65,7 @@ "metadata": {}, "outputs": [], "source": [ - "# leafmap.planet_biannual_catalog()" + "# leafmap.planet_biannual_tropical()" ] }, { @@ -74,7 +74,7 @@ "metadata": {}, "outputs": [], "source": [ - "# leafmap.planet_monthly_catalog()" + "# leafmap.planet_monthly_tropical()" ] }, { @@ -83,7 +83,7 @@ "metadata": {}, "outputs": [], "source": [ - "# leafmap.planet_catalog()" + "# leafmap.planet_catalog_tropical()" ] }, { @@ -92,7 +92,7 @@ "metadata": {}, "outputs": [], "source": [ - "biannual_tiles = leafmap.planet_biannual_tiles(api_key=None, token_name='PLANET_API_KEY', tile_format=tile_format)" + "biannual_tiles = leafmap.planet_biannual_tiles_tropical(api_key=None, token_name='PLANET_API_KEY', tile_format=tile_format)" ] }, { @@ -101,7 +101,7 @@ "metadata": {}, "outputs": [], "source": [ - "monthly_tiles = leafmap.planet_monthly_tiles(api_key=None, token_name='PLANET_API_KEY', tile_format=tile_format)" + "monthly_tiles = leafmap.planet_monthly_tiles_tropical(api_key=None, token_name='PLANET_API_KEY', tile_format=tile_format)" ] }, { diff --git a/examples/notebooks/20_planet_imagery.ipynb b/examples/notebooks/20_planet_imagery.ipynb index d3dacfd2d5..7c1d601a49 100644 --- a/examples/notebooks/20_planet_imagery.ipynb +++ b/examples/notebooks/20_planet_imagery.ipynb @@ -26,7 +26,7 @@ "outputs": [], "source": [ "import os\n", - "import leafmap.foliumap as leafmap" + "import leafmap" ] }, { @@ -65,7 +65,7 @@ "metadata": {}, "outputs": [], "source": [ - "# leafmap.planet_biannual_catalog()" + "# leafmap.planet_biannual_tropical()" ] }, { @@ -74,7 +74,7 @@ "metadata": {}, "outputs": [], "source": [ - "# leafmap.planet_monthly_catalog()" + "# leafmap.planet_monthly_tropical()" ] }, { @@ -83,7 +83,7 @@ "metadata": {}, "outputs": [], "source": [ - "# leafmap.planet_catalog()" + "# leafmap.planet_catalog_tropical()" ] }, { @@ -92,7 +92,7 @@ "metadata": {}, "outputs": [], "source": [ - "biannual_tiles = leafmap.planet_biannual_tiles(api_key=None, token_name='PLANET_API_KEY', tile_format=tile_format)" + "biannual_tiles = leafmap.planet_biannual_tiles_tropical(api_key=None, token_name='PLANET_API_KEY', tile_format=tile_format)" ] }, { @@ -101,7 +101,7 @@ "metadata": {}, "outputs": [], "source": [ - "monthly_tiles = leafmap.planet_monthly_tiles(api_key=None, token_name='PLANET_API_KEY', tile_format=tile_format)" + "monthly_tiles = leafmap.planet_monthly_tiles_tropical(api_key=None, token_name='PLANET_API_KEY', tile_format=tile_format)" ] }, { diff --git a/leafmap/basemaps.py b/leafmap/basemaps.py index 0a5154a620..bfdc08a88f 100644 --- a/leafmap/basemaps.py +++ b/leafmap/basemaps.py @@ -528,9 +528,9 @@ leaf_basemaps[name] = basemap_to_tiles(eval(basemap)) if os.environ.get("PLANET_API_KEY") is not None: - from .common import planet_tiles + from .common import planet_tiles_tropical - planet_dict = planet_tiles() + planet_dict = planet_tiles_tropical() for key in planet_dict: leaf_basemaps[key] = planet_dict[key] diff --git a/leafmap/common.py b/leafmap/common.py index f7be96c0fc..bebf5d1e13 100644 --- a/leafmap/common.py +++ b/leafmap/common.py @@ -1717,7 +1717,7 @@ def vector_col_names(filename, **kwargs): return col_names -def planet_monthly_catalog(api_key=None, token_name="PLANET_API_KEY"): +def planet_monthly_tropical(api_key=None, token_name="PLANET_API_KEY"): """Generates Planet monthly imagery URLs based on API key. See https://assets.planet.com/docs/NICFI_UserGuidesFAQ.pdf Args: @@ -1760,7 +1760,7 @@ def planet_monthly_catalog(api_key=None, token_name="PLANET_API_KEY"): return url_list -def planet_biannual_catalog(api_key=None, token_name="PLANET_API_KEY"): +def planet_biannual_tropical(api_key=None, token_name="PLANET_API_KEY"): """Generates Planet bi-annual imagery URLs based on API key. See https://assets.planet.com/docs/NICFI_UserGuidesFAQ.pdf Args: @@ -1803,7 +1803,7 @@ def planet_biannual_catalog(api_key=None, token_name="PLANET_API_KEY"): return url_list -def planet_catalog(api_key=None, token_name="PLANET_API_KEY"): +def planet_catalog_tropical(api_key=None, token_name="PLANET_API_KEY"): """Generates Planet bi-annual and monthly imagery URLs based on API key. See https://assets.planet.com/docs/NICFI_UserGuidesFAQ.pdf Args: @@ -1813,12 +1813,12 @@ def planet_catalog(api_key=None, token_name="PLANET_API_KEY"): Returns: list: A list of tile URLs. """ - biannual = planet_biannual_catalog(api_key, token_name) - monthly = planet_monthly_catalog(api_key, token_name) + biannual = planet_biannual_tropical(api_key, token_name) + monthly = planet_monthly_tropical(api_key, token_name) return biannual + monthly -def planet_monthly_tiles( +def planet_monthly_tiles_tropical( api_key=None, token_name="PLANET_API_KEY", tile_format="ipyleaflet" ): """Generates Planet monthly imagery TileLayer based on API key. See https://assets.planet.com/docs/NICFI_UserGuidesFAQ.pdf @@ -1841,7 +1841,7 @@ def planet_monthly_tiles( raise ValueError("The tile format must be either ipyleaflet or folium.") tiles = {} - url_list = planet_monthly_catalog(api_key, token_name) + url_list = planet_monthly_tropical(api_key, token_name) for url in url_list: index = url.find("20") name = "Planet_" + url[index : index + 7] @@ -1862,7 +1862,7 @@ def planet_monthly_tiles( return tiles -def planet_biannual_tiles( +def planet_biannual_tiles_tropical( api_key=None, token_name="PLANET_API_KEY", tile_format="ipyleaflet" ): """Generates Planet bi-annual imagery TileLayer based on API key. See https://assets.planet.com/docs/NICFI_UserGuidesFAQ.pdf @@ -1886,7 +1886,7 @@ def planet_biannual_tiles( raise ValueError("The tile format must be either ipyleaflet or folium.") tiles = {} - url_list = planet_biannual_catalog(api_key, token_name) + url_list = planet_biannual_tropical(api_key, token_name) for url in url_list: index = url.find("20") name = "Planet_" + url[index : index + 15] @@ -1905,7 +1905,9 @@ def planet_biannual_tiles( return tiles -def planet_tiles(api_key=None, token_name="PLANET_API_KEY", tile_format="ipyleaflet"): +def planet_tiles_tropical( + api_key=None, token_name="PLANET_API_KEY", tile_format="ipyleaflet" +): """Generates Planet monthly imagery TileLayer based on API key. See https://assets.planet.com/docs/NICFI_UserGuidesFAQ.pdf Args: @@ -1921,8 +1923,8 @@ def planet_tiles(api_key=None, token_name="PLANET_API_KEY", tile_format="ipyleaf """ catalog = {} - biannul = planet_biannual_tiles(api_key, token_name, tile_format) - monthly = planet_monthly_tiles(api_key, token_name, tile_format) + biannul = planet_biannual_tiles_tropical(api_key, token_name, tile_format) + monthly = planet_monthly_tiles_tropical(api_key, token_name, tile_format) for key in biannul: catalog[key] = biannul[key] diff --git a/leafmap/leafmap.py b/leafmap/leafmap.py index 3a8d465cb4..9d43f046da 100644 --- a/leafmap/leafmap.py +++ b/leafmap/leafmap.py @@ -2228,3 +2228,93 @@ def split_map( raise Exception(e) return m + + +def ts_inspector( + layers_dict=None, + left_name=None, + right_name=None, + width="120px", + center=[40, -100], + zoom=4, + **kwargs, +): + + import ipywidgets as widgets + + add_zoom = True + add_fullscreen = True + + if "toolbar_control" not in kwargs: + kwargs["toolbar_control"] = False + if "draw_control" not in kwargs: + kwargs["draw_control"] = False + if "measure_control" not in kwargs: + kwargs["measure_control"] = False + if "zoom_control" not in kwargs: + kwargs["zoom_control"] = False + else: + add_zoom = kwargs["zoom_control"] + if "fullscreen_control" not in kwargs: + kwargs["fullscreen_control"] = False + else: + add_fullscreen = kwargs["fullscreen_control"] + + if layers_dict is None: + layers_dict = {} + keys = dict(basemap_tiles).keys() + for key in keys: + if isinstance(basemap_tiles[key], ipyleaflet.WMSLayer): + pass + else: + layers_dict[key] = basemap_tiles[key] + + keys = list(layers_dict.keys()) + if left_name is None: + left_name = keys[0] + if right_name is None: + right_name = keys[-1] + + left_layer = layers_dict[left_name] + right_layer = layers_dict[right_name] + + m = Map(center=center, zoom=zoom, google_map=None, **kwargs) + control = ipyleaflet.SplitMapControl(left_layer=left_layer, right_layer=right_layer) + m.add_control(control) + + left_dropdown = widgets.Dropdown( + options=keys, value=left_name, layout=widgets.Layout(width=width) + ) + + left_control = ipyleaflet.WidgetControl(widget=left_dropdown, position="topleft") + m.add_control(left_control) + + right_dropdown = widgets.Dropdown( + options=keys, value=right_name, layout=widgets.Layout(width=width) + ) + + right_control = ipyleaflet.WidgetControl(widget=right_dropdown, position="topright") + m.add_control(right_control) + + if add_zoom: + m.add_control(ipyleaflet.ZoomControl()) + if add_fullscreen: + m.add_control(ipyleaflet.FullScreenControl()) + + split_control = None + for ctrl in m.controls: + if isinstance(ctrl, ipyleaflet.SplitMapControl): + split_control = ctrl + break + + def left_change(change): + split_control.left_layer.url = layers_dict[left_dropdown.value].url + + left_dropdown.observe(left_change, "value") + + def right_change(change): + split_control.right_layer.url = layers_dict[right_dropdown.value].url + + right_dropdown.observe(right_change, "value") + + return m diff --git a/leafmap/toolbar.py b/leafmap/toolbar.py index 44e79cb4d4..c797d9552e 100644 --- a/leafmap/toolbar.py +++ b/leafmap/toolbar.py @@ -207,22 +207,38 @@ def main_toolbar(m): "name": "basemap", "tooltip": "Change basemap", }, + "adjust": { + "name": "split_map", + "tooltip": "Split-panel map", + }, + "globe": { + "name": "planet", + "tooltip": "Planet imagery", + }, "folder-open": { "name": "open_data", "tooltip": "Open local vector/raster data", }, - "eraser": { - "name": "eraser", - "tooltip": "Remove all drawn features", - }, "gears": { "name": "whitebox", "tooltip": "WhiteboxTools for local geoprocessing", }, + "eraser": { + "name": "eraser", + "tooltip": "Remove all drawn features", + }, "camera": { "name": "save_map", "tooltip": "Save map as HTML or image", }, + # "smile-o": { + # "name": "placeholder", + # "tooltip": "This is a placehold", + # }, + "spinner": { + "name": "placeholder2", + "tooltip": "This is a placehold", + }, "question": { "name": "help", "tooltip": "Get help", @@ -271,6 +287,10 @@ def tool_callback(change): if tool_name == "basemap": change_basemap(m) + if tool_name == "split_map": + split_basemaps(m) + if tool_name == "planet": + split_basemaps(m, layers_dict=planet_tiles_tropical()) elif tool_name == "open_data": open_data_widget(m) elif tool_name == "eraser": @@ -900,3 +920,75 @@ def ok_cancel_clicked(change): save_map_control = WidgetControl(widget=save_map_widget, position="topright") m.add_control(save_map_control) m.save_map_control = save_map_control + + +def split_basemaps(m, layers_dict=None, left_name=None, right_name=None, width="120px"): + + from .basemaps import basemap_tiles + + m.layers = [m.layers[0]] + m.clear_controls() + + # layers_dict = None + # left_name = None + # right_name = None + # width = "120px" + add_zoom = True + add_fullscreen = True + + if layers_dict is None: + layers_dict = {} + keys = dict(basemap_tiles).keys() + for key in keys: + if isinstance(basemap_tiles[key], ipyleaflet.WMSLayer): + pass + else: + layers_dict[key] = basemap_tiles[key] + + keys = list(layers_dict.keys()) + if left_name is None: + left_name = keys[0] + if right_name is None: + right_name = keys[-1] + + left_layer = layers_dict[left_name] + right_layer = layers_dict[right_name] + + control = ipyleaflet.SplitMapControl(left_layer=left_layer, right_layer=right_layer) + m.add_control(control) + + left_dropdown = widgets.Dropdown( + options=keys, value=left_name, layout=widgets.Layout(width=width) + ) + + left_control = ipyleaflet.WidgetControl(widget=left_dropdown, position="topleft") + m.add_control(left_control) + + right_dropdown = widgets.Dropdown( + options=keys, value=right_name, layout=widgets.Layout(width=width) + ) + + right_control = ipyleaflet.WidgetControl(widget=right_dropdown, position="topright") + m.add_control(right_control) + + if add_zoom: + m.add_control(ipyleaflet.ZoomControl()) + if add_fullscreen: + m.add_control(ipyleaflet.FullScreenControl()) + m.add_control(ipyleaflet.ScaleControl(position="bottomleft")) + + split_control = None + for ctrl in m.controls: + if isinstance(ctrl, ipyleaflet.SplitMapControl): + split_control = ctrl + break + + def left_change(change): + split_control.left_layer.url = layers_dict[left_dropdown.value].url + + left_dropdown.observe(left_change, "value") + + def right_change(change): + split_control.right_layer.url = layers_dict[right_dropdown.value].url + + right_dropdown.observe(right_change, "value")