cboettig commited on
Commit
7d1d8b9
·
1 Parent(s): f20d8dc

so it begins...

Browse files
Files changed (2) hide show
  1. app.py +121 -0
  2. requirements.txt +10 -0
app.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ import leafmap.foliumap as leafmap
15
+ import rioxarray
16
+ import geopandas as gpd
17
+ import streamlit as st
18
+ import altair as alt
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:9822").area / 10000.
40
+ return area
41
+
42
+
43
+ # +
44
+ st.set_page_config(layout="wide", page_title="Paradise Valley", page_icon="⚡")
45
+
46
+ st.title("Land Use change in Paradise Valley")
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 acres of land converted.
51
+ '''
52
+
53
+ built = "https://huggingface.co/datasets/boettiger-lab/yellowstone/resolve/main/diffs_cog.tif"
54
+
55
+
56
+ m = leafmap.Map(center=[35, -100], zoom=3)
57
+
58
+ ## Map controls sidebar
59
+ with st.sidebar:
60
+ st.markdown(DESCRIPTION)
61
+
62
+ cog_layers = {
63
+ "Expanded Built Land, 2017-2023": built,
64
+ }
65
+
66
+ selection = st.radio("Data", cog_layers)
67
+ cog = cog_layers[selection]
68
+ m.add_cog_layer(cog, palette="reds", name=selection,
69
+ transparent_bg=True, opacity = 0.8,
70
+ zoom_to_layer=False)
71
+
72
+ "### python code for map layer:"
73
+ "adjust options or add additional layers using leafmap"
74
+ code = st.text_area(
75
+ label = "code:",
76
+ value = code_ex,
77
+ height = 400)
78
+
79
+ # run whatever python code is in the python box, just for fun
80
+ eval(compile(code, "<string>", "exec"))
81
+ st_data = m.to_streamlit(height=400, bidirectional=True)
82
+
83
+ polygon = st_data["last_active_drawing"]
84
+ # Here we actually compute the total carbon in the requested polygon
85
+ if polygon is not None:
86
+ gdf = read_polygon(polygon)
87
+ x = extract_geom(gdf, cog).fillna(0)
88
+ count = x.count()
89
+ area = round(float(area_hectares(gdf)))
90
+ carbon_total = round(float(x.mean()) * area) # no, mean does not include zeros
91
+ col2, col3 = st.columns(3)
92
+ col2.metric(label=f"Area", value=f"{area:,} Hectares")
93
+ col3.metric(label=f"pixels", value=f"{count:,}")
94
+
95
+
96
+ # pixel sums instead of means
97
+ # value = round(float(x.sum()))
98
+ # if(selection in ["Vulnerable Carbon (2018)",
99
+ # "Manageable Carbon (2018)",
100
+ # "Irrecoverable Carbon (2018)"]):
101
+ # value = value * 9 # 300m pixels, each pixel is 9 hectres
102
+
103
+
104
+ st.divider()
105
+
106
+ '''
107
+ Note: this is just a proof-of-principle demonstration of these tools, and these calculations have not been validated.
108
+
109
+ ## Credits
110
+
111
+ ### Data sources
112
+
113
+ - <https://planetarycomputer.microsoft.com/dataset/io-lulc-annual-v02>
114
+
115
+ ### Software stack
116
+
117
+ - Streamlit (python) app hosted on free-tier HuggingFace spaces ([source code](https://huggingface.co/spaces/boettiger-lab/leafmap/blob/main/app.py)).
118
+ - Cloud-optimized geotifs hosted on [Source.Coop](https://source.coop)
119
+ - Mapping with Leafmap, calculations with rasterio
120
+
121
+ '''
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ pandas
2
+ pydeck
3
+ pmtiles
4
+ streamlit
5
+ leafmap
6
+ ibis-framework[duckdb]
7
+ altair
8
+ rioxarray
9
+ geopandas
10
+ streamlit-folium