File size: 7,507 Bytes
1aa7583
 
 
 
 
 
 
 
1c76a96
 
 
2236dd4
 
1c76a96
 
 
cc8b36c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1c76a96
 
263f645
 
 
1aa7583
66fa388
1c76a96
7d06004
46bc3f8
 
690fe2e
46bc3f8
 
 
 
 
7d06004
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1aa7583
 
7d06004
 
 
1aa7583
 
 
 
 
46bc3f8
 
 
690fe2e
 
 
46bc3f8
690fe2e
 
 
 
 
 
46bc3f8
690fe2e
 
 
 
 
 
 
 
 
 
 
46bc3f8
 
 
1aa7583
 
 
656f25c
8424379
 
 
46bc3f8
7d06004
 
8424379
 
 
 
 
46bc3f8
 
 
690fe2e
 
 
 
 
 
 
 
 
 
 
 
 
46bc3f8
690fe2e
 
 
 
 
 
46bc3f8
690fe2e
46bc3f8
 
8424379
 
 
 
46bc3f8
 
1aa7583
7d06004
46bc3f8
1aa7583
46bc3f8
1aa7583
46bc3f8
1aa7583
8424379
7d06004
 
 
 
 
 
 
 
 
 
 
8424379
46bc3f8
7d06004
8424379
46bc3f8
8424379
46bc3f8
8424379
46bc3f8
 
656f25c
d1dca6b
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
import ibis
from ibis import _
import streamlit as st

st.set_page_config(layout="wide",
                   page_title="TPL LandVote",
                   page_icon=":globe:")

'''
# LandVote Prototype

An experimental platform for visualizing data on ballot measures for conservation, based on data from <https://landvote.org/> curated by the Trust for Public Land.

'''


## Chatbot
import os
import pandas as pd
import matplotlib.pyplot as plt
from pandasai.llm.openai import OpenAI
from pandasai import Agent
from pandasai.responses.streamlit_response import StreamlitResponse

llm = OpenAI(api_token=st.secrets["OPENAI_API_KEY"])
df1 = pd.read_csv("data.csv")

agent = Agent(
    [df1],
    config={"verbose": True, "response_parser": StreamlitResponse, "llm": llm},
)



with st.sidebar:

    '''
    ## Data Assistant (experimental)

    Ask questions about the landvote data, like:

    - What are the top states for approved conservation funds?
    - Plot the total funds spent in conservation each year.
    - What city has approved the most funds in a single measure? What was the description of that vote?
    - Which state has had largest number measures fail? What is that as a fraction of it's total measures?
    '''
    
    prompt = st.chat_input("Ask about the data")
    if prompt:
        with st.spinner():
            resp = agent.chat(prompt)
            if os.path.isfile('exports/charts/temp_chart.png'):
                im = plt.imread('exports/charts/temp_chart.png')
                st.image(im)
                os.remove('exports/charts/temp_chart.png')
            st.write(resp)
        


# year = st.slider("Select a year", min_value=1988, max_value=2024, value=2022, step=2)
year = st.slider("Select a year", min_value=1988, max_value=2024, value=2022, step=1)

import leafmap.maplibregl as leafmap
m = leafmap.Map(style="positron",   center=(-100, 40), zoom=3)

url = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/landvote.pmtiles"

dark_orange = 'rgba(171, 86, 1, 1)'   # dark orange - min value 
light_orange = 'rgba(243, 211, 177, 1)' # light orange 
grey = 'rgba(211, 211, 211, 1)'        # grey
light_green = 'rgba(195, 219, 195, 1)' # light green 
dark_green = 'rgba(65, 125, 65, 1)'    # dark green  - max value 


style_municipals = {
    "layers": [
        {
            "id": "municipals",
            "source": "municipal",
            "source-layer": "municipal",
            "type": "fill-extrusion",
            "filter": [
                "==",
                ["get", "year"],
                year,
            ],
            "paint": {
                "fill-extrusion-color": [
                    "case",
                    # if passed, color green
                    ["==", ["get", "Status"], "Pass"],
                    [
                        "interpolate", ["linear"], [
                            "to-number", ["slice", ["get", "yes"], 0, -1]  # convert 'yes' string to number
                        ],
                        50, grey,    
                        55, light_green,     # higher yes % -> darker green
                        100, dark_green     # 100 is the max of data 
                    ],
                    # if failed, color orange
                    ["==", ["get", "Status"], "Fail"],
                    [
                        "interpolate", ["linear"], [
                            "to-number", ["slice", ["get", "yes"], 0, -1]  # convert 'yes' string to number
                        ],
                        0, dark_orange,     # higher yes % -> lighter orange 
                        50, light_orange,   
                        67, grey # 67 is the max of data.
                    ],
                    grey  # if no match 
                ],
                "fill-extrusion-height": ["*", ["get", "log_amount"], 5000],
            }
        },
    ],
}

style_counties = {
    "layers": [
        {
            "id": "counties",
            "source": "county",
            "source-layer": "county",
            "type": "fill-extrusion",
            "filter": [
                "==",
                ["get", "year"],
                year,
            ],
            "paint": {
                "fill-extrusion-color": [
                    "case",
                    # if passed, color green
                    ["==", ["get", "Status"], "Pass"],
                    [
                        "interpolate", ["linear"], [
                            "to-number", ["slice", ["get", "yes"], 0, -1]  # convert 'yes' string to number
                        ],
                        50, grey,    
                        55, light_green,     # higher yes % -> darker green
                        100, dark_green     # 100 is the max of data 
                    ],
                    # if failed, color orange
                    ["==", ["get", "Status"], "Fail"],
                    [
                        "interpolate", ["linear"], [
                            "to-number", ["slice", ["get", "yes"], 0, -1]  # convert 'yes' string to number
                        ],
                        0, dark_orange,     # higher yes % -> lighter orange 
                        50, light_orange,   
                        67, grey # 67 is the max of data.
                    ],
                    grey  # if no match 
                ],
                "fill-extrusion-height": ["*", ["get", "log_amount"], 5000],
            }
        },
    ],
}

style_states = {
    "layers": [
        {
            "id": "states",
            "source": "state",
            "source-layer": "state",
            "type": "fill",
            "filter": [
                "==",
                ["get", "year"],
                year,
            ],
            "paint": {
                "fill-color": [
                    "case",
                    # if passed, color green
                    ["==", ["get", "Status"], "Pass"],
                    [
                        "interpolate", ["linear"], [
                            "to-number", ["slice", ["get", "yes"], 0, -1]  # convert 'yes' string to number
                        ],
                        50, grey,    
                        55, light_green,     # higher yes % -> darker green
                        100, dark_green     # 100 is the max of data 
                    ],
                    # if failed, color orange
                    ["==", ["get", "Status"], "Fail"],
                    [
                        "interpolate", ["linear"], [
                            "to-number", ["slice", ["get", "yes"], 0, -1]  # convert 'yes' string to number
                        ],
                        0, dark_orange,     # higher yes % -> lighter orange 
                        50, light_orange,   
                        67, grey # 67 is the max of data.
                    ],
                    grey  # if no match 
                ]
            }
        },
    ],
}


#states are 2D and transparent, thus added separately.
m.add_pmtiles(
    url,
    style=style_states,
    visible=True,
    opacity=0.6,
    tooltip=True,
    fit_bounds=False
)

#states are 2D and transparent, thus added separately.
m.add_pmtiles(
    url,
    style=style_counties,
    visible=True,
    opacity=0.6,
    tooltip=True,
    fit_bounds=False
)


m.add_pmtiles(
    url,
    style=style_municipals,
    visible=True,
    opacity=1.0,
    tooltip=True,
    fit_bounds=False
)

m.add_layer_control()
m.to_streamlit()