Spaces:
Sleeping
Sleeping
cassiebuhler
commited on
Commit
·
7d06004
1
Parent(s):
f12e506
adding layers to pmtiles
Browse files- app.py +63 -12
- static-maps.ipynb +115 -155
app.py
CHANGED
@@ -63,10 +63,7 @@ year = st.slider("Select a year", min_value=1988, max_value=2024, value=2022, st
|
|
63 |
import leafmap.maplibregl as leafmap
|
64 |
m = leafmap.Map(style="positron", center=(-100, 40), zoom=3)
|
65 |
|
66 |
-
url = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/
|
67 |
-
|
68 |
-
url_states = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/vote_states.pmtiles"
|
69 |
-
|
70 |
|
71 |
dark_orange = 'rgba(171, 86, 1, 1)' # dark orange - min value
|
72 |
light_orange = 'rgba(243, 211, 177, 1)' # light orange
|
@@ -75,12 +72,55 @@ light_green = 'rgba(195, 219, 195, 1)' # light green
|
|
75 |
dark_green = 'rgba(65, 125, 65, 1)' # dark green - max value
|
76 |
|
77 |
|
78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
"layers": [
|
80 |
{
|
81 |
-
"id": "counties
|
82 |
-
"source": "
|
83 |
-
"source-layer": "
|
84 |
"type": "fill-extrusion",
|
85 |
"filter": [
|
86 |
"==",
|
@@ -122,8 +162,8 @@ style_states = {
|
|
122 |
"layers": [
|
123 |
{
|
124 |
"id": "states",
|
125 |
-
"source": "
|
126 |
-
"source-layer": "
|
127 |
"type": "fill",
|
128 |
"filter": [
|
129 |
"==",
|
@@ -163,7 +203,7 @@ style_states = {
|
|
163 |
|
164 |
#states are 2D and transparent, thus added separately.
|
165 |
m.add_pmtiles(
|
166 |
-
|
167 |
style=style_states,
|
168 |
visible=True,
|
169 |
opacity=0.6,
|
@@ -171,9 +211,20 @@ m.add_pmtiles(
|
|
171 |
fit_bounds=False
|
172 |
)
|
173 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
m.add_pmtiles(
|
175 |
url,
|
176 |
-
style=
|
177 |
visible=True,
|
178 |
opacity=1.0,
|
179 |
tooltip=True,
|
|
|
63 |
import leafmap.maplibregl as leafmap
|
64 |
m = leafmap.Map(style="positron", center=(-100, 40), zoom=3)
|
65 |
|
66 |
+
url = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/landvote.pmtiles"
|
|
|
|
|
|
|
67 |
|
68 |
dark_orange = 'rgba(171, 86, 1, 1)' # dark orange - min value
|
69 |
light_orange = 'rgba(243, 211, 177, 1)' # light orange
|
|
|
72 |
dark_green = 'rgba(65, 125, 65, 1)' # dark green - max value
|
73 |
|
74 |
|
75 |
+
style_municipals = {
|
76 |
+
"layers": [
|
77 |
+
{
|
78 |
+
"id": "municipals",
|
79 |
+
"source": "municipal",
|
80 |
+
"source-layer": "municipal",
|
81 |
+
"type": "fill-extrusion",
|
82 |
+
"filter": [
|
83 |
+
"==",
|
84 |
+
["get", "year"],
|
85 |
+
year,
|
86 |
+
],
|
87 |
+
"paint": {
|
88 |
+
"fill-extrusion-color": [
|
89 |
+
"case",
|
90 |
+
# if passed, color green
|
91 |
+
["==", ["get", "Status"], "Pass"],
|
92 |
+
[
|
93 |
+
"interpolate", ["linear"], [
|
94 |
+
"to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number
|
95 |
+
],
|
96 |
+
50, grey,
|
97 |
+
55, light_green, # higher yes % -> darker green
|
98 |
+
100, dark_green # 100 is the max of data
|
99 |
+
],
|
100 |
+
# if failed, color orange
|
101 |
+
["==", ["get", "Status"], "Fail"],
|
102 |
+
[
|
103 |
+
"interpolate", ["linear"], [
|
104 |
+
"to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number
|
105 |
+
],
|
106 |
+
0, dark_orange, # higher yes % -> lighter orange
|
107 |
+
50, light_orange,
|
108 |
+
67, grey # 67 is the max of data.
|
109 |
+
],
|
110 |
+
grey # if no match
|
111 |
+
],
|
112 |
+
"fill-extrusion-height": ["*", ["get", "log_amount"], 5000],
|
113 |
+
}
|
114 |
+
},
|
115 |
+
],
|
116 |
+
}
|
117 |
+
|
118 |
+
style_counties = {
|
119 |
"layers": [
|
120 |
{
|
121 |
+
"id": "counties",
|
122 |
+
"source": "county",
|
123 |
+
"source-layer": "county",
|
124 |
"type": "fill-extrusion",
|
125 |
"filter": [
|
126 |
"==",
|
|
|
162 |
"layers": [
|
163 |
{
|
164 |
"id": "states",
|
165 |
+
"source": "state",
|
166 |
+
"source-layer": "state",
|
167 |
"type": "fill",
|
168 |
"filter": [
|
169 |
"==",
|
|
|
203 |
|
204 |
#states are 2D and transparent, thus added separately.
|
205 |
m.add_pmtiles(
|
206 |
+
url,
|
207 |
style=style_states,
|
208 |
visible=True,
|
209 |
opacity=0.6,
|
|
|
211 |
fit_bounds=False
|
212 |
)
|
213 |
|
214 |
+
#states are 2D and transparent, thus added separately.
|
215 |
+
m.add_pmtiles(
|
216 |
+
url,
|
217 |
+
style=style_counties,
|
218 |
+
visible=True,
|
219 |
+
opacity=0.6,
|
220 |
+
tooltip=True,
|
221 |
+
fit_bounds=False
|
222 |
+
)
|
223 |
+
|
224 |
+
|
225 |
m.add_pmtiles(
|
226 |
url,
|
227 |
+
style=style_municipals,
|
228 |
visible=True,
|
229 |
opacity=1.0,
|
230 |
tooltip=True,
|
static-maps.ipynb
CHANGED
@@ -12,31 +12,28 @@
|
|
12 |
"import streamlit as st\n",
|
13 |
"import ibis.expr.datatypes as dt # Make sure to import the necessary module\n",
|
14 |
"\n",
|
15 |
-
"\
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
"
|
24 |
-
"locality = conn.read_parquet(localities_boundaries)\n",
|
25 |
-
"\n",
|
26 |
-
"\n",
|
27 |
-
"votes = conn.read_csv(\"landvote.csv\")"
|
28 |
]
|
29 |
},
|
30 |
{
|
31 |
"cell_type": "code",
|
32 |
"execution_count": null,
|
33 |
-
"id": "
|
34 |
"metadata": {},
|
35 |
"outputs": [],
|
36 |
"source": [
|
37 |
-
"
|
38 |
-
"
|
39 |
-
"
|
|
|
40 |
" .rename(amount = 'Conservation Funds at Stake', yes = '% Yes')\n",
|
41 |
" .mutate(amount_n=_.amount.replace('$', '').replace(',', '').cast('float'))\n",
|
42 |
" .mutate(log_amount=_.amount_n.log())\n",
|
@@ -48,18 +45,57 @@
|
|
48 |
" .else_(None) # Default to None for other cases\n",
|
49 |
" .end()\n",
|
50 |
" )\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
" .mutate(log_amount = _.log_amount.round(4))\n",
|
52 |
-
" .select('
|
53 |
-
" )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
"\n",
|
55 |
-
"
|
56 |
" .select('state_id','geometry')\n",
|
57 |
-
" .right_join(vote_states, \"state_id\")\n",
|
58 |
-
" .mutate(key = _.state_id)\n",
|
59 |
-
" .select('key','geometry','Status', 'yes', 'year', 'amount', 'log_amount')\n",
|
60 |
-
" .mutate(jurisdiction = ibis.literal(\"State\"))\n",
|
61 |
" .cast({\"geometry\": \"geometry\"})\n",
|
62 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
]
|
64 |
},
|
65 |
{
|
@@ -69,33 +105,26 @@
|
|
69 |
"metadata": {},
|
70 |
"outputs": [],
|
71 |
"source": [
|
72 |
-
"
|
73 |
-
"
|
74 |
-
"
|
75 |
-
"
|
76 |
-
"
|
77 |
-
"
|
78 |
-
" .mutate(log_amount=_.amount_n.log())\n",
|
79 |
-
" .mutate(year=_['Date'].year().cast('int32'))\n",
|
80 |
-
" .mutate(\n",
|
81 |
-
" yes=ibis.case()\n",
|
82 |
-
" .when(_.yes.isin(['Pass', 'None','Fail']), None) # Handle non-numeric cases\n",
|
83 |
-
" .when(_.yes.notnull(), (_.yes.replace('%', '').cast('float').round(2).cast(dt.float64)).cast(dt.string) + '%') # Convert valid percentages and add %\n",
|
84 |
-
" .else_(None) # Default to None for other cases\n",
|
85 |
-
" .end()\n",
|
86 |
-
" )\n",
|
87 |
-
" .mutate(log_amount = _.log_amount.round(4))\n",
|
88 |
-
" .select('key', 'Status', 'yes', 'year', 'amount', 'log_amount', )\n",
|
89 |
-
" )\n",
|
90 |
"df_county = (county\n",
|
91 |
-
" .
|
92 |
-
" .mutate(key = _.county + ibis.literal('-') + _.state_id)\n",
|
93 |
-
" .select('key', 'geometry')\n",
|
94 |
-
" .right_join(vote_county, \"key\")\n",
|
95 |
-
" .drop('key_right')\n",
|
96 |
-
" .mutate(jurisdiction = ibis.literal(\"County\"))\n",
|
97 |
" .cast({\"geometry\": \"geometry\"})\n",
|
98 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
]
|
100 |
},
|
101 |
{
|
@@ -105,44 +134,28 @@
|
|
105 |
"metadata": {},
|
106 |
"outputs": [],
|
107 |
"source": [
|
108 |
-
"
|
109 |
-
" .filter(_[\"Jurisdiction Type\"] == \"Municipal\")\n",
|
110 |
-
" .rename(city = \"Jurisdiction Name\", state_id = \"State\")\n",
|
111 |
-
" .mutate(key = _.city + ibis.literal('-') + _.state_id)\n",
|
112 |
-
" .rename(amount = 'Conservation Funds at Stake', yes = '% Yes')\n",
|
113 |
-
" .mutate(amount_n=_.amount.replace('$', '').replace(',', '').cast('float'))\n",
|
114 |
-
" .mutate(log_amount=_.amount_n.log())\n",
|
115 |
-
" .mutate(year=_['Date'].year().cast('int32'))\n",
|
116 |
-
" .mutate(\n",
|
117 |
-
" yes=ibis.case()\n",
|
118 |
-
" .when(_.yes.isin(['Pass', 'None','Fail']), None) # Handle non-numeric cases\n",
|
119 |
-
" .when(_.yes.notnull(), (_.yes.replace('%', '').cast('float').round(2).cast(dt.float64)).cast(dt.string) + '%') # Convert valid percentages and add %\n",
|
120 |
-
" .else_(None) # Default to None for other cases\n",
|
121 |
-
" .end()\n",
|
122 |
-
" )\n",
|
123 |
-
" .mutate(log_amount = _.log_amount.round(4))\n",
|
124 |
-
" .select('key', 'Status', 'yes', 'year', 'amount', 'log_amount', )\n",
|
125 |
-
" )\n",
|
126 |
"\n",
|
127 |
-
"
|
128 |
-
"
|
129 |
-
"
|
130 |
-
"
|
131 |
-
"
|
132 |
-
"
|
|
|
133 |
" .cast({\"geometry\": \"geometry\"})\n",
|
134 |
" .mutate(geometry = _.geometry.buffer(.07))\n",
|
135 |
-
" )\n"
|
|
|
|
|
136 |
]
|
137 |
},
|
138 |
{
|
139 |
-
"cell_type": "
|
140 |
-
"
|
141 |
-
"id": "a1e81807-8ce3-44bf-9a1c-8563fa33817c",
|
142 |
"metadata": {},
|
143 |
-
"outputs": [],
|
144 |
"source": [
|
145 |
-
"
|
146 |
]
|
147 |
},
|
148 |
{
|
@@ -168,7 +181,7 @@
|
|
168 |
" repo_id=repo_id,\n",
|
169 |
" repo_type=\"dataset\",\n",
|
170 |
" )\n",
|
171 |
-
"def generate_pmtiles(input_file, output_file, max_zoom=12):\n",
|
172 |
" # Ensure Tippecanoe is installed\n",
|
173 |
" if subprocess.call([\"which\", \"tippecanoe\"], stdout=subprocess.DEVNULL) != 0:\n",
|
174 |
" raise RuntimeError(\"Tippecanoe is not installed or not in PATH\")\n",
|
@@ -181,9 +194,10 @@
|
|
181 |
" \"--extend-zooms-if-still-dropping\",\n",
|
182 |
" \"--force\",\n",
|
183 |
" \"--projection\", \"EPSG:4326\", \n",
|
184 |
-
" input_file
|
|
|
|
|
185 |
" ]\n",
|
186 |
-
"\n",
|
187 |
" # Run Tippecanoe\n",
|
188 |
" try:\n",
|
189 |
" subprocess.run(command, check=True)\n",
|
@@ -196,94 +210,40 @@
|
|
196 |
{
|
197 |
"cell_type": "code",
|
198 |
"execution_count": null,
|
199 |
-
"id": "
|
200 |
"metadata": {},
|
201 |
"outputs": [],
|
202 |
"source": [
|
203 |
-
"
|
204 |
-
"
|
205 |
-
"\n",
|
206 |
-
"gdf.to_file(\"vote.geojson\")\n",
|
207 |
-
"hf_upload(\"vote.geojson\", \"boettiger-lab/landvote\")\n",
|
208 |
"\n",
|
209 |
-
"
|
210 |
-
"hf_upload(\"vote.pmtiles\", \"boettiger-lab/landvote\")\n",
|
211 |
"\n",
|
212 |
-
"\n",
|
213 |
-
"\n"
|
214 |
-
"gdf_states= df_states.execute()\n",
|
215 |
-
"gdf_states = gdf_states.set_crs(\"EPSG:4326\")\n",
|
216 |
-
"\n",
|
217 |
-
"gdf_states.to_file(\"vote_states.geojson\")\n",
|
218 |
-
"hf_upload(\"vote_states.geojson\", \"boettiger-lab/landvote\")\n",
|
219 |
-
"\n",
|
220 |
-
"generate_pmtiles(\"vote_states.geojson\", \"vote_states.pmtiles\")\n",
|
221 |
-
"hf_upload(\"vote_states.pmtiles\", \"boettiger-lab/landvote\")\n",
|
222 |
-
"\n"
|
223 |
]
|
224 |
},
|
225 |
{
|
226 |
-
"cell_type": "
|
227 |
-
"
|
228 |
-
"
|
229 |
-
"metadata": {
|
230 |
-
"scrolled": true
|
231 |
-
},
|
232 |
-
"outputs": [],
|
233 |
"source": [
|
234 |
-
"
|
235 |
-
"m = leafmap.Map(style=\"positron\")\n",
|
236 |
-
"\n",
|
237 |
-
"\n",
|
238 |
-
"url_states = \"https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/vote_states.pmtiles\"\n",
|
239 |
-
"\n",
|
240 |
-
"outcome = [\n",
|
241 |
-
" 'match',\n",
|
242 |
-
" ['get', 'Status'], \n",
|
243 |
-
" \"Pass\", '#2E865F',\n",
|
244 |
-
" \"Fail\", '#FF3300', \n",
|
245 |
-
" '#ccc'\n",
|
246 |
-
" ]\n",
|
247 |
-
"paint_states = {\"fill-color\": outcome, \n",
|
248 |
-
" # \"fill-opacity\": 0.2,\n",
|
249 |
-
" }\n",
|
250 |
-
"style_states = {\n",
|
251 |
-
" \"layers\": [\n",
|
252 |
-
" {\n",
|
253 |
-
" \"id\": \"votes_states\",\n",
|
254 |
-
" \"source\": \"vote_states\",\n",
|
255 |
-
" \"source-layer\": \"vote_states\",\n",
|
256 |
-
" \"type\": \"fill\",\n",
|
257 |
-
" \"filter\": [\n",
|
258 |
-
" \"==\",\n",
|
259 |
-
" [\"get\", \"year\"],\n",
|
260 |
-
" 2022,\n",
|
261 |
-
" ], # only show buildings with height info\n",
|
262 |
-
" \"paint\": paint_states\n",
|
263 |
-
" },\n",
|
264 |
-
" ],\n",
|
265 |
-
"}\n",
|
266 |
-
"\n",
|
267 |
-
"m.add_pmtiles(\n",
|
268 |
-
" url_states,\n",
|
269 |
-
" style=style_states,\n",
|
270 |
-
" visible=True,\n",
|
271 |
-
" opacity=0.4,\n",
|
272 |
-
" tooltip=True,\n",
|
273 |
-
" fit_bounds=False,\n",
|
274 |
-
")\n",
|
275 |
-
"\n",
|
276 |
-
"m\n",
|
277 |
-
"\n"
|
278 |
]
|
279 |
},
|
280 |
{
|
281 |
"cell_type": "code",
|
282 |
"execution_count": null,
|
283 |
-
"id": "
|
284 |
"metadata": {},
|
285 |
"outputs": [],
|
286 |
-
"source": [
|
|
|
|
|
|
|
|
|
|
|
287 |
}
|
288 |
],
|
289 |
"metadata": {
|
|
|
12 |
"import streamlit as st\n",
|
13 |
"import ibis.expr.datatypes as dt # Make sure to import the necessary module\n",
|
14 |
"\n",
|
15 |
+
"conn = ibis.duckdb.connect(extensions=[\"spatial\"])"
|
16 |
+
]
|
17 |
+
},
|
18 |
+
{
|
19 |
+
"cell_type": "markdown",
|
20 |
+
"id": "943e4127-4af5-42c9-b1e2-48af2d888c24",
|
21 |
+
"metadata": {},
|
22 |
+
"source": [
|
23 |
+
"# Landvote data"
|
|
|
|
|
|
|
|
|
24 |
]
|
25 |
},
|
26 |
{
|
27 |
"cell_type": "code",
|
28 |
"execution_count": null,
|
29 |
+
"id": "b486df27-e64c-48af-a577-89a74752ed5b",
|
30 |
"metadata": {},
|
31 |
"outputs": [],
|
32 |
"source": [
|
33 |
+
"landvote = conn.read_csv(\"landvote.csv\")\n",
|
34 |
+
"\n",
|
35 |
+
"landvote_df = (landvote\n",
|
36 |
+
" .rename(jurisdiction = \"Jurisdiction Type\", state = \"State\", name = \"Jurisdiction Name\")\n",
|
37 |
" .rename(amount = 'Conservation Funds at Stake', yes = '% Yes')\n",
|
38 |
" .mutate(amount_n=_.amount.replace('$', '').replace(',', '').cast('float'))\n",
|
39 |
" .mutate(log_amount=_.amount_n.log())\n",
|
|
|
45 |
" .else_(None) # Default to None for other cases\n",
|
46 |
" .end()\n",
|
47 |
" )\n",
|
48 |
+
" .mutate(\n",
|
49 |
+
" municipal=ibis.case()\n",
|
50 |
+
" .when(_.jurisdiction.isin(['State','County']), None) \n",
|
51 |
+
" .else_(_.name) \n",
|
52 |
+
" .end()\n",
|
53 |
+
" )\n",
|
54 |
+
" .mutate(\n",
|
55 |
+
" county=ibis.case()\n",
|
56 |
+
" .when(_.jurisdiction.isin(['State','Municipal']), None) \n",
|
57 |
+
" .else_(_.name) \n",
|
58 |
+
" .end()\n",
|
59 |
+
" )\n",
|
60 |
" .mutate(log_amount = _.log_amount.round(4))\n",
|
61 |
+
" .select('name','state','county','municipal','jurisdiction','Status', 'yes', 'year', 'amount', 'log_amount', )\n",
|
62 |
+
" )"
|
63 |
+
]
|
64 |
+
},
|
65 |
+
{
|
66 |
+
"cell_type": "markdown",
|
67 |
+
"id": "b78ad1e0-3b4e-4f56-bd25-b8da186d2857",
|
68 |
+
"metadata": {},
|
69 |
+
"source": [
|
70 |
+
"# State Data"
|
71 |
+
]
|
72 |
+
},
|
73 |
+
{
|
74 |
+
"cell_type": "code",
|
75 |
+
"execution_count": null,
|
76 |
+
"id": "09ecf89a-a315-45ef-9ece-783963e6e07e",
|
77 |
+
"metadata": {},
|
78 |
+
"outputs": [],
|
79 |
+
"source": [
|
80 |
+
"state_boundaries = \"https://data.source.coop/cboettig/us-boundaries/us-state-territory.parquet\"\n",
|
81 |
+
"states = conn.read_parquet(state_boundaries).rename(state_id = \"STUSPS\", state = \"NAME\")\n",
|
82 |
+
"\n",
|
83 |
+
"landvote_states = landvote_df.filter(_.jurisdiction == \"State\")\n",
|
84 |
"\n",
|
85 |
+
"df_state = (states\n",
|
86 |
" .select('state_id','geometry')\n",
|
|
|
|
|
|
|
|
|
87 |
" .cast({\"geometry\": \"geometry\"})\n",
|
88 |
+
" .right_join(landvote_states, landvote_states['state'] == states['state_id'] )\n",
|
89 |
+
" .select('state','county','municipal','jurisdiction','geometry','Status', 'yes', 'year', 'amount', 'log_amount', )\n",
|
90 |
+
" )"
|
91 |
+
]
|
92 |
+
},
|
93 |
+
{
|
94 |
+
"cell_type": "markdown",
|
95 |
+
"id": "010717bb-1d7e-4915-b476-a4038728131c",
|
96 |
+
"metadata": {},
|
97 |
+
"source": [
|
98 |
+
"# County Data"
|
99 |
]
|
100 |
},
|
101 |
{
|
|
|
105 |
"metadata": {},
|
106 |
"outputs": [],
|
107 |
"source": [
|
108 |
+
"landvote_county = landvote_df.filter(_.jurisdiction == \"County\")\n",
|
109 |
+
"\n",
|
110 |
+
"county_boundaries = \"https://data.source.coop/cboettig/us-boundaries/us-county.parquet\"\n",
|
111 |
+
"county = conn.read_parquet(county_boundaries).rename(county = \"NAMELSAD\", state = \"STATE_NAME\")\n",
|
112 |
+
"\n",
|
113 |
+
"\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
"df_county = (county\n",
|
115 |
+
" .select('state','county','geometry')\n",
|
|
|
|
|
|
|
|
|
|
|
116 |
" .cast({\"geometry\": \"geometry\"})\n",
|
117 |
+
" .right_join(landvote_county, \"county\" )\n",
|
118 |
+
" .select('state','county','municipal','jurisdiction','geometry','Status', 'yes', 'year', 'amount', 'log_amount', )\n",
|
119 |
+
" )"
|
120 |
+
]
|
121 |
+
},
|
122 |
+
{
|
123 |
+
"cell_type": "markdown",
|
124 |
+
"id": "913b4a98-82eb-452f-8d81-8bce2b58a4c3",
|
125 |
+
"metadata": {},
|
126 |
+
"source": [
|
127 |
+
"# Municipal Data"
|
128 |
]
|
129 |
},
|
130 |
{
|
|
|
134 |
"metadata": {},
|
135 |
"outputs": [],
|
136 |
"source": [
|
137 |
+
"landvote_local = landvote_df.filter(_.jurisdiction == \"Municipal\")\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
"\n",
|
139 |
+
"local = (conn\n",
|
140 |
+
" .read_parquet(\"us_localities.parquet\")\n",
|
141 |
+
" .rename(municipal = \"name\",state = \"state_id\")\n",
|
142 |
+
" )\n",
|
143 |
+
"\n",
|
144 |
+
"df_local = (local\n",
|
145 |
+
" .select('state','county','municipal','geometry')\n",
|
146 |
" .cast({\"geometry\": \"geometry\"})\n",
|
147 |
" .mutate(geometry = _.geometry.buffer(.07))\n",
|
148 |
+
" .right_join(landvote_local, [\"municipal\",\"state\"])\n",
|
149 |
+
" .select('state','county','municipal','jurisdiction','geometry','Status', 'yes', 'year', 'amount', 'log_amount', )\n",
|
150 |
+
" )"
|
151 |
]
|
152 |
},
|
153 |
{
|
154 |
+
"cell_type": "markdown",
|
155 |
+
"id": "728993c4-7d58-4e89-924d-72dd43333585",
|
|
|
156 |
"metadata": {},
|
|
|
157 |
"source": [
|
158 |
+
"# Make PMTiles. Each jurisdiction type is its own layer"
|
159 |
]
|
160 |
},
|
161 |
{
|
|
|
181 |
" repo_id=repo_id,\n",
|
182 |
" repo_type=\"dataset\",\n",
|
183 |
" )\n",
|
184 |
+
"def generate_pmtiles(input_file, input_file2, input_file3, output_file, max_zoom=12):\n",
|
185 |
" # Ensure Tippecanoe is installed\n",
|
186 |
" if subprocess.call([\"which\", \"tippecanoe\"], stdout=subprocess.DEVNULL) != 0:\n",
|
187 |
" raise RuntimeError(\"Tippecanoe is not installed or not in PATH\")\n",
|
|
|
194 |
" \"--extend-zooms-if-still-dropping\",\n",
|
195 |
" \"--force\",\n",
|
196 |
" \"--projection\", \"EPSG:4326\", \n",
|
197 |
+
" \"-L\",\"state:\"+input_file,\n",
|
198 |
+
" \"-L\",\"county:\"+input_file2,\n",
|
199 |
+
" \"-L\",\"municipal:\"+input_file3\n",
|
200 |
" ]\n",
|
|
|
201 |
" # Run Tippecanoe\n",
|
202 |
" try:\n",
|
203 |
" subprocess.run(command, check=True)\n",
|
|
|
210 |
{
|
211 |
"cell_type": "code",
|
212 |
"execution_count": null,
|
213 |
+
"id": "26ffccfd-2666-445a-9c03-2089bd589650",
|
214 |
"metadata": {},
|
215 |
"outputs": [],
|
216 |
"source": [
|
217 |
+
"df_state.execute().to_file(\"vote_state.geojson\")\n",
|
218 |
+
"df_county.execute().to_file(\"vote_county.geojson\")\n",
|
219 |
+
"df_local.execute().to_file(\"vote_municipal.geojson\")\n",
|
|
|
|
|
220 |
"\n",
|
221 |
+
"# hf_upload(\"vote.geojson\", \"boettiger-lab/landvote\")\n",
|
|
|
222 |
"\n",
|
223 |
+
"generate_pmtiles(\"vote_state.geojson\", \"vote_county.geojson\",\"vote_municipal.geojson\", \"landvote.pmtiles\")\n",
|
224 |
+
"hf_upload(\"landvote.pmtiles\", \"boettiger-lab/landvote\")\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
]
|
226 |
},
|
227 |
{
|
228 |
+
"cell_type": "markdown",
|
229 |
+
"id": "4af09411-a4fe-475a-8b2b-f2d36388aa19",
|
230 |
+
"metadata": {},
|
|
|
|
|
|
|
|
|
231 |
"source": [
|
232 |
+
"# Combine all 3 jurisdiction types into a parquet."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
]
|
234 |
},
|
235 |
{
|
236 |
"cell_type": "code",
|
237 |
"execution_count": null,
|
238 |
+
"id": "fa6db898-a132-4ad5-86e9-de80613275d4",
|
239 |
"metadata": {},
|
240 |
"outputs": [],
|
241 |
+
"source": [
|
242 |
+
"df_temp = df_county.union(df_local)\n",
|
243 |
+
"df = df_temp.union(df_state)\n",
|
244 |
+
"df.execute().to_parquet(\"landvote.parquet\")\n",
|
245 |
+
"hf_upload(\"landvote.parquet\", \"boettiger-lab/landvote\")\n"
|
246 |
+
]
|
247 |
}
|
248 |
],
|
249 |
"metadata": {
|