cassiebuhler commited on
Commit
7d06004
·
1 Parent(s): f12e506

adding layers to pmtiles

Browse files
Files changed (2) hide show
  1. app.py +63 -12
  2. 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/vote.pmtiles"
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
- style = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  "layers": [
80
  {
81
- "id": "counties & municipals",
82
- "source": "vote",
83
- "source-layer": "vote",
84
  "type": "fill-extrusion",
85
  "filter": [
86
  "==",
@@ -122,8 +162,8 @@ style_states = {
122
  "layers": [
123
  {
124
  "id": "states",
125
- "source": "vote_states",
126
- "source-layer": "vote_states",
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
- url_states,
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=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
- "\n",
16
- "conn = ibis.duckdb.connect(extensions=[\"spatial\"])\n",
17
- "\n",
18
- "state_boundaries = \"https://data.source.coop/cboettig/us-boundaries/us-state-territory.parquet\"\n",
19
- "county_boundaries = \"https://data.source.coop/cboettig/us-boundaries/us-county.parquet\"\n",
20
- "states = conn.read_parquet(state_boundaries).rename(state_id = \"STUSPS\", state = \"NAME\")\n",
21
- "county = conn.read_parquet(county_boundaries).rename(county = \"NAMELSAD\", state = \"STATE_NAME\")\n",
22
- "\n",
23
- "localities_boundaries = \"us_localities.parquet\"\n",
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": "09ecf89a-a315-45ef-9ece-783963e6e07e",
34
  "metadata": {},
35
  "outputs": [],
36
  "source": [
37
- "vote_states = (votes\n",
38
- " .filter(_[\"Jurisdiction Type\"] == \"State\")\n",
39
- " .rename(state_id = \"State\")\n",
 
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('state_id', 'Status', 'yes', 'year', 'amount', 'log_amount', )\n",
53
- " )\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  "\n",
55
- "df_states = (states\n",
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
- " )\n"
 
 
 
 
 
 
 
 
 
 
63
  ]
64
  },
65
  {
@@ -69,33 +105,26 @@
69
  "metadata": {},
70
  "outputs": [],
71
  "source": [
72
- "vote_county = (votes\n",
73
- " .filter(_[\"Jurisdiction Type\"] == \"County\")\n",
74
- " .rename(county = \"Jurisdiction Name\", state_id = \"State\")\n",
75
- " .mutate(key = _.county + ibis.literal('-') + _.state_id)\n",
76
- " .rename(amount = 'Conservation Funds at Stake', yes = '% Yes')\n",
77
- " .mutate(amount_n=_.amount.replace('$', '').replace(',', '').cast('float'))\n",
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
- " .join(states.select(\"state\", \"state_id\"), \"state\")\n",
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
- " )\n"
 
 
 
 
 
 
 
 
 
 
99
  ]
100
  },
101
  {
@@ -105,44 +134,28 @@
105
  "metadata": {},
106
  "outputs": [],
107
  "source": [
108
- "vote_local = (votes\n",
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
- "df_local = (locality\n",
128
- " .mutate(key = _.name + ibis.literal('-') + _.state_id)\n",
129
- " .select('key', 'geometry')\n",
130
- " .right_join(vote_local, \"key\")\n",
131
- " .drop('key_right')\n",
132
- " .mutate(jurisdiction = ibis.literal(\"Municipal\"))\n",
 
133
  " .cast({\"geometry\": \"geometry\"})\n",
134
  " .mutate(geometry = _.geometry.buffer(.07))\n",
135
- " )\n"
 
 
136
  ]
137
  },
138
  {
139
- "cell_type": "code",
140
- "execution_count": null,
141
- "id": "a1e81807-8ce3-44bf-9a1c-8563fa33817c",
142
  "metadata": {},
143
- "outputs": [],
144
  "source": [
145
- "df = df_county.union(df_local)"
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\n",
 
 
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": "902ece1d-6e57-4f83-9286-709dbb549fae",
200
  "metadata": {},
201
  "outputs": [],
202
  "source": [
203
- "gdf= df.execute()\n",
204
- "gdf = gdf.set_crs(\"EPSG:4326\")\n",
205
- "\n",
206
- "gdf.to_file(\"vote.geojson\")\n",
207
- "hf_upload(\"vote.geojson\", \"boettiger-lab/landvote\")\n",
208
  "\n",
209
- "generate_pmtiles(\"vote.geojson\", \"vote.pmtiles\")\n",
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": "code",
227
- "execution_count": null,
228
- "id": "fa397626-6e94-4ab9-a3bb-2bcbd14e8d40",
229
- "metadata": {
230
- "scrolled": true
231
- },
232
- "outputs": [],
233
  "source": [
234
- "import leafmap.maplibregl as leafmap\n",
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": "2f85b6e6-4e50-4602-9c7c-d39f19f99a45",
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": {