import leafmap.foliumap as leafmap import rioxarray import geopandas as gpd import streamlit as st import altair as alt import ibis from ibis import _ import ibis.selectors as s from streamlit_folium import st_folium import json from leafmap import pmtiles_style # Common Functions def read_polygon(polygon): """ Take in a polygon from the app and convert it to GeoJSON """ geojson_str = json.dumps(polygon) gdf = gpd.read_file(geojson_str, driver="GeoJSON") gdf.set_crs("epsg:4326") return gdf # Actual Page content below started = None if not started: st.set_page_config(layout="wide", page_title="Huggingface Toy", page_icon="❦") st.title("Huggingface Streamlit Toy") """ This is a toy to play around with Huggingface, Leafmap, and Streamlit I'm looking to implement at least these things: * Visualize raster data from an S3 bucket * Let the user (you!) draw polygons and calculate some stats (mean, median, etc.) * Let user load pre-defined geometries (admin levels? country borders?) * Load boundaries based on the center of the map """ hi = "https://data.source.coop/vizzuality/hfp-100/hfp_2021_100m_v1-2_cog.tif" deforest = "https://data.source.coop/vizzuality/lg-land-carbon-data/deforest_carbon_100m_cog.tif" # Euromap info eurocrops_pmtiles = "https://s3.us-west-2.amazonaws.com/us-west-2.opendata.source.coop/cholmes/eurocrops/eurocrops-all.pmtiles" ec_style = pmtiles_style(eurocrops_pmtiles) m = leafmap.Map(center=[41, -69], zoom=5) # Moved the cog layers into optional scripts to make the pmtile information easier to see. # m.add_cog_layer( # deforest, # palette="reds", # name="deforested", # transparent_bg=True, # opacity=0.5, # zoom_to_layer=False, # ) # m.add_cog_layer( # hi, # palette="purples", # name="human impact", # transparent_bg=True, # opacity=0.5, # zoom_to_layer=False, # ) m.add_pmtiles( eurocrops_pmtiles, name="euro crops", style=ec_style, overlay=True, show=True, zoom_to_layer=False, ) # TODO: automate getting the polygon from the figrue # TODO: Calculate some metrics given the area. # TODO: add a raster to the toy # TODO: Change calculation depending on what layers are present # TODO: Dynamically check the center of the map and change what's displayed depending on that. polygon_ex = '{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-6.108398,40.780541],[-6.108398,54.342149],[15.908203,54.342149],[15.908203,40.780541],[-6.108398,40.780541]]]}}' # code_ex = """ # m.add_gdf(polygon, layer_name="selection") # """ code_ex = "" ## Map controls sidebar with st.sidebar: """ # Map controls ### Polygon selector """ polygon = st.text_area(label="geometry", value=polygon_ex, height=400) """ ### python code for map layer: adjust options or add additional layers using leafmap """ code = st.text_area(label="code:", value=code_ex, height=400) # Here we actually compute the total carbon in the requested polygon # NOTE: It is not possible to access user_roi_bounds from streamlit per: https://github.com/opengeos/leafmap/discussions/152#discussioncomment-1870416 # bounds = m.user_roi_bounds() # if bounds is not None: # bounds.set_crs("epsg:4326") # geo = gpd.read_file(polygon, driver="GeoJSON") # geo.set_crs("epsg:4326") # x = ( # rioxarray.open_rasterio("/vsicurl/" + deforest, masked=True) # .rio.clip(geo.geometry.values, geo.crs, from_disk=True) # .mean() # ) # value = x "### Average of tons of carbon lost:" # st.write(f"{value:,}") st.divider() # run whatever python code is in the python box, just for fun eval(compile(code, "", "exec")) st_data = m.to_streamlit(height=700, bidirectional=True) polygon = st_data["last_active_drawing"] "### Could there be a polygon here?" st.write(f"{polygon is not None}") if polygon is not None: "### The Polygon is: " gdf = read_polygon(polygon) st.write(f"{polygon}") started = True "## Explore Further" st.write(""" To modify the map, add code to the `code` section in the sidebar to the left. Some examples of code to add are below. """) st.code(""" # Show deforested areas: m.add_cog_layer( deforest, palette="reds", name="deforested", transparent_bg=True, opacity=0.5, zoom_to_layer=False, ) # Show human impacted areas m.add_cog_layer( hi, palette="purples", name="human impact", transparent_bg=True, opacity=0.5, zoom_to_layer=False, ) """) """ ## Credits This toy was inspired by boettiger-lab's Carbon Calculator Demo: https://huggingface.co/spaces/boettiger-lab/leafmap ### Data Sources - Human Footprint by Vizzuality, on https://beta.source.coop/repositories/vizzuality/hfp-100, citation: https://doi.org/10.3389/frsen.2023.1130896, License: Public Domain """