Spaces:

File size: 3,865 Bytes
7d1d8b9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

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

def extract_geom(gdf, cog):
    x = (rioxarray.
         open_rasterio('/vsicurl/'+cog, masked=True).
         rio.clip(gdf.geometry.values, gdf.crs, from_disk=True)
    )
    return x

def read_polygon(polygon):
    geojson_str = json.dumps(polygon)
    gdf = gpd.read_file(geojson_str, driver='GeoJSON')
    gdf.set_crs('epsg:4326')
    return gdf

def area_hectares(gdf):
    area = gdf.to_crs("EPSG:9822").area / 10000.
    return area


# +
st.set_page_config(layout="wide", page_title="Paradise Valley", page_icon="⚡")

st.title("Land Use change in Paradise Valley")

DESCRIPTION='''
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.
(use esc key to exit drawing mode).  Map will display acres of land converted.
'''

built = "https://huggingface.co/datasets/boettiger-lab/yellowstone/resolve/main/diffs_cog.tif"


m = leafmap.Map(center=[35, -100], zoom=3)

## Map controls sidebar
with st.sidebar:
    st.markdown(DESCRIPTION)

    cog_layers = {
            "Expanded Built Land, 2017-2023": built,
            }

    selection = st.radio("Data", cog_layers)
    cog = cog_layers[selection]
    m.add_cog_layer(cog, palette="reds", name=selection,
                    transparent_bg=True, opacity = 0.8, 
                    zoom_to_layer=False)

    "### python code for map layer:"
    "adjust options or add additional layers using leafmap"
    code = st.text_area(
        label = "code:",
        value = code_ex, 
        height = 400)

# run whatever python code is in the python box, just for fun
eval(compile(code, "<string>", "exec"))
st_data = m.to_streamlit(height=400, bidirectional=True)

polygon = st_data["last_active_drawing"]
# Here we actually compute the total carbon in the requested polygon
if polygon is not None:
    gdf = read_polygon(polygon)
    x = extract_geom(gdf, cog).fillna(0)    
    count = x.count()
    area = round(float(area_hectares(gdf)))
    carbon_total = round(float(x.mean()) * area) # no, mean does not include zeros
    col2, col3 = st.columns(3)
    col2.metric(label=f"Area", value=f"{area:,} Hectares")
    col3.metric(label=f"pixels", value=f"{count:,}")


# pixel sums instead of means
#    value = round(float(x.sum()))
#    if(selection in ["Vulnerable Carbon (2018)",
#                     "Manageable Carbon (2018)",
#                     "Irrecoverable Carbon (2018)"]):
#        value = value * 9 # 300m pixels, each pixel is 9 hectres


st.divider()

'''
Note: this is just a proof-of-principle demonstration of these tools, and these calculations have not been validated. 

## Credits

### Data sources

- <https://planetarycomputer.microsoft.com/dataset/io-lulc-annual-v02>

### Software stack
 
- Streamlit (python) app hosted on free-tier HuggingFace spaces ([source code](https://huggingface.co/spaces/boettiger-lab/leafmap/blob/main/app.py)).
- Cloud-optimized geotifs hosted on [Source.Coop](https://source.coop)
- Mapping with Leafmap, calculations with rasterio

'''