import streamlit as st import streamlit.components.v1 as components import base64 import leafmap.maplibregl as leafmap import altair as alt import ibis from ibis import _ import ibis.selectors as s from typing import Optional def to_streamlit( self, width: Optional[int] = None, height: Optional[int] = 600, scrolling: Optional[bool] = False, **kwargs, ): try: import streamlit.components.v1 as components import base64 raw_html = self.to_html().encode("utf-8") raw_html = base64.b64encode(raw_html).decode() return components.iframe( f"data:text/html;base64,{raw_html}", width=width, height=height, scrolling=scrolling, **kwargs, ) except Exception as e: raise Exception(e) ca_pmtiles = "https://data.source.coop/cboettig/ca30x30/ca_areas.pmtiles" # ca_pmtiles = "ca_areas.pmtiles" # ca_parquet = "https://data.source.coop/cboettig/ca30x30/ca_areas.parquet" ca_parquet = "ca_areas.parquet" ca_area_acres = 1.014e8 #acres style_choice = "GAP Status Code" # style_choice = "Easement" # style_choice = "Year" con = ibis.duckdb.connect() ca = (con .read_parquet(ca_parquet) .cast({"SHAPE": "geometry"}) .mutate( area=_.SHAPE.area()) # .head() ) # print(ca.schema()) # ca = ca.filter(ca.Release_Year == 2024) private_color = "#DE881E" # orange #"#850101" # red tribal_color = "#BF40BF" # purple mixed_color = "#005a00" # green public_color = "#3388ff" # blue year2023_color = "#26542C" # green year2024_color = "#F3AB3D" # orange def summary_table(column, colors): df = (ca # .rename(area = "area_square_meters") .group_by(column) .aggregate(hectares_protected = (_.area.sum() / 10000).round(), percent_protected = 100 * _.Acres.sum() / ca_area_acres ) .mutate(percent_protected = _.percent_protected.round(1), ) .inner_join(colors, column) ) df = df.to_pandas() df[column] = df[column].astype(str) return df def area_plot(df, column): base = alt.Chart(df).encode( alt.Theta("percent_protected:Q").stack(True), ) pie = ( base .mark_arc(innerRadius= 40, outerRadius=100) .encode(alt.Color("color:N").scale(None).legend(None), tooltip=['percent_protected', 'hectares_protected', column]) ) text = ( base .mark_text(radius=80, size=14, color="white") .encode(text = column + ":N") ) plot = pie # pie + text return plot.properties(width="container", height=300) def pad_style(paint, alpha): return { "version": 8, "sources": { "ca": { "type": "vector", "url": "pmtiles://" + ca_pmtiles, }}, "layers": [{ "id": "layer1", "source": "ca", "source-layer": "CA_Cons_Areas_parentlyr_Merge_ecofix", "type": "fill", "paint": { "fill-color": paint, "fill-opacity": alpha } }]} manager = { 'property': 'cpad_MNG_AG_LEV', 'type': 'categorical', 'stops': [ ['Federal', "darkblue"], ['State', public_color], ['Non Profit', "lightblue"], ['Special District', "darkgreen"], ['', "grey"], ['Joint', "green"], ['Tribal', tribal_color], ['Private', "darkred"], ['City', "pink"], ['County', "blue"], ['Home Owners Association', "lightgreen"] ] } easement = { 'property': 'Easement', 'type': 'categorical', 'stops': [ [0, public_color], [1, private_color] ] } year = { 'property': 'Release_Year', 'type': 'categorical', 'stops': [ [2023, year2023_color], [2024, year2024_color] ] } access = { 'property': 'ACCESS_TYP', 'type': 'categorical', 'stops': [ ['Open Access', public_color], ['No Public Access', private_color], ['Unknown Access', "grey"], ['Restricted Access', tribal_color] ] } gap = { 'property': 'reGAP', 'type': 'categorical', 'stops': [ [1, "#26633d"], [2, "#879647"], [3, "#BBBBBB"], [4, "#F8F8F8"] ] } style_options = { "GAP Status Code": gap, "Management Agency": manager, "Easement": easement, "Public Access": access, "Year": year } st.set_page_config(layout="wide", page_title="CA Protected Areas Explorer", page_icon=":globe:") ''' # CA 30X30 Prototype ''' m = leafmap.Map(style="positron") with st.sidebar: if st.toggle("Protected Areas", True): style_choice = st.radio("Color by:", style_options) alpha = st.slider("transparency", 0.0, 1.0, 0.5) style = pad_style(style_options[style_choice], alpha) m.add_pmtiles(ca_pmtiles, style=style, visible=True, opacity=alpha, tooltip=True) select_column = { "GAP Status Code": "reGAP", "Management Agency": "cpad_MNG_AG_LEV", "Easement": "Easement", "Year": "Release_Year", "Public Access": "ACCESS_TYP"} column = select_column[style_choice] select_colors = { "Management Agency": manager["stops"], "Easement": easement["stops"], "Public Access": access["stops"], "Year": year["stops"], "GAP Status Code": gap["stops"]} colors = (ibis .memtable(select_colors[style_choice], columns = [column, "color"]) .to_pandas() ) main = st.container() with main: map_col, stats_col = st.columns([2,1]) with map_col: to_streamlit(m, height=700) df = summary_table(column, colors) total_percent = df.percent_protected.sum().round(1) with stats_col: with st.container(): f"{total_percent}% CA Covered" st.altair_chart(area_plot(df, column), use_container_width=True) st.divider() footer = st.container()