Spaces:
Sleeping
Sleeping
more streamlined
Browse files- app.py +110 -76
- requirements.txt +1 -0
app.py
CHANGED
|
@@ -19,48 +19,73 @@ import altair as alt
|
|
| 19 |
import ibis
|
| 20 |
from ibis import _
|
| 21 |
import ibis.selectors as s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
|
| 24 |
# +
|
| 25 |
st.set_page_config(layout="wide", page_title="Leafmap Explorer", page_icon="⚡")
|
| 26 |
|
| 27 |
-
|
| 28 |
-
# Demo Carbon Calculator
|
| 29 |
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
Map will zoom in on selected area and display the tons of carbon lost between 2002 - 2022 below.
|
| 34 |
Data comes from Vizzuality repo on [source.coop](https://beta.source.coop/repositories/vizzuality/lg-land-carbon-data/description/).
|
| 35 |
'''
|
| 36 |
|
|
|
|
|
|
|
| 37 |
deforest = "https://data.source.coop/vizzuality/lg-land-carbon-data/deforest_carbon_100m_cog.tif"
|
|
|
|
| 38 |
irrecoverable = "https://data.source.coop/cboettig/carbon/cogs/irrecoverable_c_total_2018.tif"
|
| 39 |
vulnerable = "https://data.source.coop/cboettig/carbon/cogs/vulnerable_c_total_2018.tif"
|
|
|
|
| 40 |
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
|
| 46 |
-
polygon_ex ='{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-124.628906,34.741612],[-124.628906,42.423457],[-117.246094,42.423457],[-117.246094,34.741612],[-124.628906,34.741612]]]}}'
|
| 47 |
-
code_ex = '''
|
| 48 |
-
m.add_gdf(geo, layer_name="selection")
|
| 49 |
-
'''
|
| 50 |
|
|
|
|
| 51 |
|
| 52 |
## Map controls sidebar
|
| 53 |
with st.sidebar:
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
"### python code for map layer:"
|
| 66 |
"adjust options or add additional layers using leafmap"
|
|
@@ -69,66 +94,71 @@ with st.sidebar:
|
|
| 69 |
value = code_ex,
|
| 70 |
height = 400)
|
| 71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
|
|
|
| 73 |
# Here we actually compute the total carbon in the requested polygon
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
x = (
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
value =
|
| 82 |
|
|
|
|
| 83 |
|
| 84 |
-
"### Tons of carbon lost:"
|
| 85 |
-
st.write(f'{value:,}')
|
| 86 |
-
st.divider()
|
| 87 |
|
| 88 |
-
|
| 89 |
-
eval(compile(code, "<string>", "exec"))
|
| 90 |
-
m.to_streamlit(height=700)
|
| 91 |
|
| 92 |
"## Explore further"
|
| 93 |
-
st.write('''
|
| 94 |
-
Try adding additional options to the map. Some suggested examples are shown below.
|
| 95 |
-
(Of course any self-respecting streamlit app would make these into toggle buttons,
|
| 96 |
-
but this is a demo and it's fun & flexible to be able to execute arbitrary code).
|
| 97 |
|
| 98 |
-
|
| 99 |
-
'''
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
"
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
"
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
"
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
|
| 131 |
-
# +
|
| 132 |
st.divider()
|
| 133 |
|
| 134 |
'''
|
|
@@ -137,9 +167,13 @@ st.divider()
|
|
| 137 |
### Data sources
|
| 138 |
|
| 139 |
- Carbon-loss by Vizzuality, on https://beta.source.coop/repositories/vizzuality/lg-land-carbon-data. citation: https://doi.org/10.1101/2023.11.01.565036, License: CC-BY
|
| 140 |
-
- 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
|
| 141 |
-
- Fire polygons by USGS, reprocessed to PMTiles on https://beta.source.coop/cboettig/fire/, License: Public Domain.
|
| 142 |
- Irrecoverable Carbon from Conservation International, reprocessed to COG on https://beta.source.coop/cboettig/carbon, citation: https://doi.org/10.1038/s41893-021-00803-6, License: CC-BY-NC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
|
| 144 |
-
Software stack: Streamlit (python) app hosted on free-tier HuggingFace spaces. Mapping with Leafmap.
|
| 145 |
'''
|
|
|
|
| 19 |
import ibis
|
| 20 |
from ibis import _
|
| 21 |
import ibis.selectors as s
|
| 22 |
+
from streamlit_folium import st_folium
|
| 23 |
+
import json
|
| 24 |
+
|
| 25 |
+
def extract_geom(gdf, cog):
|
| 26 |
+
x = (rioxarray.
|
| 27 |
+
open_rasterio('/vsicurl/'+cog, masked=True).
|
| 28 |
+
rio.clip(gdf.geometry.values, gdf.crs, from_disk=True)
|
| 29 |
+
)
|
| 30 |
+
return x
|
| 31 |
+
|
| 32 |
+
def read_polygon(polygon):
|
| 33 |
+
geojson_str = json.dumps(polygon)
|
| 34 |
+
gdf = gpd.read_file(geojson_str, driver='GeoJSON')
|
| 35 |
+
gdf.set_crs('epsg:4326')
|
| 36 |
+
return gdf
|
| 37 |
+
|
| 38 |
+
def area_hectares(gdf):
|
| 39 |
+
area = gdf.to_crs("EPSG:3857").area / 10000.
|
| 40 |
+
return area
|
| 41 |
|
| 42 |
|
| 43 |
# +
|
| 44 |
st.set_page_config(layout="wide", page_title="Leafmap Explorer", page_icon="⚡")
|
| 45 |
|
| 46 |
+
st.title("Demo Carbon Calculator")
|
|
|
|
| 47 |
|
| 48 |
+
DESCRIPTION='''
|
| 49 |
+
Pan and zoom to the desired location on the map. Then, use the map tools to draw a polygon (pentagon tool), bounding box (square tool) or other shape anywhere on the map.
|
| 50 |
+
(use esc key to exit drawing mode). Map will display the tons of carbon lost between 2002 - 2022 below.
|
|
|
|
| 51 |
Data comes from Vizzuality repo on [source.coop](https://beta.source.coop/repositories/vizzuality/lg-land-carbon-data/description/).
|
| 52 |
'''
|
| 53 |
|
| 54 |
+
code_ex = ""
|
| 55 |
+
|
| 56 |
deforest = "https://data.source.coop/vizzuality/lg-land-carbon-data/deforest_carbon_100m_cog.tif"
|
| 57 |
+
# measured in Mg / Hct (tons)
|
| 58 |
irrecoverable = "https://data.source.coop/cboettig/carbon/cogs/irrecoverable_c_total_2018.tif"
|
| 59 |
vulnerable = "https://data.source.coop/cboettig/carbon/cogs/vulnerable_c_total_2018.tif"
|
| 60 |
+
manageable = "https://data.source.coop/cboettig/carbon/cogs/manageable_c_total_2018.tif"
|
| 61 |
|
| 62 |
+
#rsr = "https://data.source.coop/cboettig/mobi/range-size-rarity-all/RSR_All.tif"
|
| 63 |
+
#richness = "https://data.source.coop/cboettig/mobi/species-richness-all/SpeciesRichness_All.tif"
|
| 64 |
+
|
| 65 |
+
# Use signed data layers
|
| 66 |
+
#rsr = "https://data.source.coop/cboettig/mobi/range-size-rarity-all/RSR_All.tif"
|
| 67 |
+
#richness = "https://data.source.coop/cboettig/mobi/species-richness-all/SpeciesRichness_All.tif"
|
| 68 |
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
+
m = leafmap.Map(center=[35, -100], zoom=2)
|
| 72 |
|
| 73 |
## Map controls sidebar
|
| 74 |
with st.sidebar:
|
| 75 |
+
st.markdown(DESCRIPTION)
|
| 76 |
+
|
| 77 |
+
cog_layers = {
|
| 78 |
+
"Carbon Lost, 2002-2022": deforest,
|
| 79 |
+
"Vulnerable Carbon (2018)": vulnerable,
|
| 80 |
+
"Manageable Carbon (2018)": manageable,
|
| 81 |
+
"Irrecoverable Carbon (2018)": irrecoverable
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
selection = st.radio("Data", cog_layers)
|
| 85 |
+
cog = cog_layers[selection]
|
| 86 |
+
m.add_cog_layer(cog, palette="reds", name=selection,
|
| 87 |
+
transparent_bg=True, opacity = 0.8,
|
| 88 |
+
zoom_to_layer=False)
|
| 89 |
|
| 90 |
"### python code for map layer:"
|
| 91 |
"adjust options or add additional layers using leafmap"
|
|
|
|
| 94 |
value = code_ex,
|
| 95 |
height = 400)
|
| 96 |
|
| 97 |
+
# run whatever python code is in the python box, just for fun
|
| 98 |
+
eval(compile(code, "<string>", "exec"))
|
| 99 |
+
st_data = m.to_streamlit(height=400, bidirectional=True)
|
| 100 |
+
|
| 101 |
+
units="Tonnes"
|
| 102 |
|
| 103 |
+
polygon = st_data["last_active_drawing"]
|
| 104 |
# Here we actually compute the total carbon in the requested polygon
|
| 105 |
+
if polygon is not None:
|
| 106 |
+
gdf = read_polygon(polygon)
|
| 107 |
+
x = extract_geom(gdf, cog)
|
| 108 |
+
value = float(x.sum())
|
| 109 |
+
if(selection in ["Vulnerable Carbon (2018)",
|
| 110 |
+
"Manageable Carbon (2018)",
|
| 111 |
+
"Irrecoverable Carbon (2018)"]):
|
| 112 |
+
value = value * 9 # 300m pixels, each pixel is 9 hectres
|
| 113 |
|
| 114 |
+
st.metric(label=f"{selection}", value=f"{value:,} {units}")
|
| 115 |
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
+
st.divider()
|
|
|
|
|
|
|
| 118 |
|
| 119 |
"## Explore further"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
|
| 121 |
+
with st.expander("code examples"):
|
| 122 |
+
st.write('''
|
| 123 |
+
Try adding additional options to the map. Some suggested examples are shown below.
|
| 124 |
+
(Of course any self-respecting streamlit app would make these into toggle buttons,
|
| 125 |
+
but this is a demo and it's fun & flexible to be able to execute arbitrary code).
|
| 126 |
+
|
| 127 |
+
To explore further, simply modify the Streamlit app.py file from the Files menu up top!
|
| 128 |
+
'''
|
| 129 |
+
)
|
| 130 |
+
|
| 131 |
+
st.code('''
|
| 132 |
+
# irrecoverable carbon (Conservation International):
|
| 133 |
+
carbon = "https://data.source.coop/cboettig/carbon/cogs/irrecoverable_c_total_2018.tif"
|
| 134 |
+
m.add_cog_layer(carbon, palette="reds", name="irrecoverable carbon",
|
| 135 |
+
transparent_bg=True, opacity = 0.8, zoom_to_layer=False)
|
| 136 |
+
|
| 137 |
+
# Human Impacts, Vizzuality
|
| 138 |
+
hi="https://data.source.coop/vizzuality/hfp-100/hfp_2021_100m_v1-2_cog.tif"
|
| 139 |
+
m.add_cog_layer(hi, palette="purples", name="human impact",
|
| 140 |
+
transparent_bg=True, opacity = 0.8, zoom_to_layer=False)
|
| 141 |
+
|
| 142 |
+
# Fire Polygons, USGS
|
| 143 |
+
usgs = "https://data.source.coop/cboettig/fire/usgs-mtbs.pmtiles"
|
| 144 |
+
combined_style = {
|
| 145 |
+
"version": 8,
|
| 146 |
+
"sources": {
|
| 147 |
+
"source1": {
|
| 148 |
+
"type": "vector",
|
| 149 |
+
"url": "pmtiles://" + usgs,
|
| 150 |
+
"attribution": "USGS"}},
|
| 151 |
+
"layers": [{
|
| 152 |
+
"id": "usgs",
|
| 153 |
+
"source": "source1",
|
| 154 |
+
"source-layer": "mtbs_perims_DD",
|
| 155 |
+
"type": "fill",
|
| 156 |
+
"paint": {"fill-color": "#FFA500", "fill-opacity": 0.2}}]}
|
| 157 |
+
|
| 158 |
+
m.add_pmtiles(usgs, name="Fire", style=combined_style, overlay=True, show=True, zoom_to_layer=False)
|
| 159 |
+
''')
|
| 160 |
|
| 161 |
|
|
|
|
| 162 |
st.divider()
|
| 163 |
|
| 164 |
'''
|
|
|
|
| 167 |
### Data sources
|
| 168 |
|
| 169 |
- Carbon-loss by Vizzuality, on https://beta.source.coop/repositories/vizzuality/lg-land-carbon-data. citation: https://doi.org/10.1101/2023.11.01.565036, License: CC-BY
|
|
|
|
|
|
|
| 170 |
- Irrecoverable Carbon from Conservation International, reprocessed to COG on https://beta.source.coop/cboettig/carbon, citation: https://doi.org/10.1038/s41893-021-00803-6, License: CC-BY-NC
|
| 171 |
+
- Fire polygons by USGS, reprocessed to PMTiles on https://beta.source.coop/cboettig/fire/, License: Public Domain.
|
| 172 |
+
|
| 173 |
+
### Software stack
|
| 174 |
+
|
| 175 |
+
- Streamlit (python) app hosted on free-tier HuggingFace spaces ([source code](https://huggingface.co/spaces/boettiger-lab/leafmap/blob/main/app.py)).
|
| 176 |
+
- Cloud-optimized geotifs hosted on [Source.Coop](https://source.coop)
|
| 177 |
+
- Mapping with Leafmap, calculations with rasterio
|
| 178 |
|
|
|
|
| 179 |
'''
|
requirements.txt
CHANGED
|
@@ -7,3 +7,4 @@ ibis-framework[duckdb]
|
|
| 7 |
altair
|
| 8 |
rioxarray
|
| 9 |
geopandas
|
|
|
|
|
|
| 7 |
altair
|
| 8 |
rioxarray
|
| 9 |
geopandas
|
| 10 |
+
streamlit-folium
|