cboettig commited on
Commit
404e71b
1 Parent(s): be54bd6

maybe got it

Browse files
Files changed (1) hide show
  1. explore.ipynb +291 -98
explore.ipynb CHANGED
@@ -2,7 +2,7 @@
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
- "execution_count": 6,
6
  "id": "f7e6298c-d886-432a-a1b7-c3fee914c24f",
7
  "metadata": {},
8
  "outputs": [],
@@ -20,26 +20,10 @@
20
  },
21
  {
22
  "cell_type": "code",
23
- "execution_count": 104,
24
  "id": "bd9c2561-334a-40d6-adf0-ce20a991a9a7",
25
  "metadata": {},
26
- "outputs": [
27
- {
28
- "data": {
29
- "application/vnd.jupyter.widget-view+json": {
30
- "model_id": "f46fb7de69784a4e89763c5432d06a40",
31
- "version_major": 2,
32
- "version_minor": 1
33
- },
34
- "text/plain": [
35
- "Map(height='600px', map_options={'bearing': 0, 'center': (0, 20), 'pitch': 0, 'style': 'https://basemaps.carto…"
36
- ]
37
- },
38
- "execution_count": 104,
39
- "metadata": {},
40
- "output_type": "execute_result"
41
- }
42
- ],
43
  "source": [
44
  "# Visualize the full data to show overlap:\n",
45
  "import leafmap.maplibregl as leafmap\n",
@@ -76,7 +60,7 @@
76
  },
77
  {
78
  "cell_type": "code",
79
- "execution_count": 158,
80
  "id": "3ceed4c7-b7a2-436e-bca1-c57e7133cdf6",
81
  "metadata": {},
82
  "outputs": [],
@@ -84,9 +68,8 @@
84
  "# Make things faster. Let's zoom in on a subset of the data. \n",
85
  "\n",
86
  "from ibis.interactive import *\n",
87
- "\n",
88
  "ca_parquet = \"/home/rstudio/source.coop/cboettig/ca30x30/ca_areas.parquet\"\n",
89
- "con = ibis.duckdb.connect()\n",
90
  "\n",
91
  "# Ugly code for a cookie cutter zoom\n",
92
  "# Turns out we could have just used filter(_.UNIT_NAME == \"Angeles National Forest\")\n",
@@ -98,19 +81,41 @@
98
  "cookie_cutter = ibis.literal(gdf.geometry.iloc[0])\n",
99
  "\n",
100
  "angeles_forest = (\n",
101
- " con.read_parquet(ca_parquet)\n",
102
  " .cast({\"SHAPE\": \"geometry\"})\n",
103
- " .mutate(geom = _.SHAPE.convert(\"epsg:3310\",\"epsg:4326\"))\n",
104
- " .filter( _.geom.intersects(cookie_cutter))\n",
 
105
  " .filter(_.UNIT_NAME == \"Angeles National Forest\") \n",
106
  " .select(\"reGAP\", \"UNIT_NAME\", \"MNG_AGNCY\", \"Release_Year\", \"OBJECTID\", \"geom\")\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  ")\n",
108
- "\n"
 
 
 
 
109
  ]
110
  },
111
  {
112
  "cell_type": "code",
113
- "execution_count": 159,
114
  "id": "3ed21429-a75e-4b52-b6eb-d41c8f051883",
115
  "metadata": {},
116
  "outputs": [],
@@ -122,7 +127,7 @@
122
  },
123
  {
124
  "cell_type": "code",
125
- "execution_count": 160,
126
  "id": "7bfac88a-822a-4e4e-883e-b7e51544abd1",
127
  "metadata": {},
128
  "outputs": [],
@@ -133,21 +138,23 @@
133
  "\n",
134
  "# THIS IS ALMOST WHAT WE WANT, BUT for some issues\n",
135
  "# All reGAP 1,2 polygons in 2024 that don't intersect 2023\n",
136
- "la_intersects = la_2024.anti_join(la_2023, _.geom.intersects(la_2023.geom))\n"
 
 
 
 
137
  ]
138
  },
139
  {
140
  "cell_type": "code",
141
- "execution_count": 164,
142
  "id": "ddae1f9e-988a-4aed-bc71-f1c40d2bb0ea",
143
- "metadata": {
144
- "scrolled": true
145
- },
146
  "outputs": [
147
  {
148
  "data": {
149
  "application/vnd.jupyter.widget-view+json": {
150
- "model_id": "52b3b9c8cb1b4bbf8fe16aebef4d2e25",
151
  "version_major": 2,
152
  "version_minor": 1
153
  },
@@ -155,7 +162,7 @@
155
  "Map(height='600px', map_options={'bearing': 0, 'center': (0, 20), 'pitch': 0, 'style': 'https://basemaps.carto…"
156
  ]
157
  },
158
- "execution_count": 164,
159
  "metadata": {},
160
  "output_type": "execute_result"
161
  }
@@ -179,51 +186,21 @@
179
  "paint = {\"fill-color\": gap, \"fill-opacity\": 0.5}\n",
180
  "\n",
181
  "m = leafmap.Map(style=\"positron\")\n",
182
- "m.add_gdf(allgap_2023.execute(),layer_type=\"fill\", name = \"allgap_2023\", paint=paint)\n",
183
- "m.add_gdf(allgap_2024.execute(),layer_type=\"fill\", name = \"allgap_2024\", paint=paint)\n",
184
- "#m.add_gdf(la_2023.execute(),layer_type=\"fill\", name = \"2023\", paint=paint)\n",
185
- "#m.add_gdf(la_2024.execute(),layer_type=\"fill\", name = \"2024\", paint=paint)\n",
186
- "m.add_gdf(la_intersects.execute(),layer_type=\"fill\", name = \"anti_intersects\", paint=paint)\n",
187
- "#m.add_gdf(intersects.execute(), layer_type=\"fill\", name = \"overlapping\", paint=paint)\n",
188
  "m.add_layer_control()\n",
189
  "m"
190
  ]
191
  },
192
  {
193
  "cell_type": "code",
194
- "execution_count": 170,
195
  "id": "6832038f-0342-495f-8cbf-9a8f3cc83aac",
196
  "metadata": {},
197
- "outputs": [
198
- {
199
- "data": {
200
- "text/html": [
201
- "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓\n",
202
- "┃<span style=\"font-weight: bold\"> OBJECTID_right </span>┃<span style=\"font-weight: bold\"> geom </span>┃<span style=\"font-weight: bold\"> reGAP </span>┃\n",
203
- "┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩\n",
204
- "│ <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">int64</span> │ <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">geospatial:geometry</span> │ <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">int16</span> │\n",
205
- "├────────────────┼──────────────────────────────────────────────────────────────────────────────────┼───────┤\n",
206
- "│ <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">21105</span> │ <span style=\"font-weight: bold\">&lt;</span><span style=\"color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold\">MULTIPOLYGON</span><span style=\"color: #000000; text-decoration-color: #000000\"> Z </span><span style=\"color: #000000; text-decoration-color: #000000; font-weight: bold\">(((</span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">-118.017</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">34.499</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span><span style=\"color: #000000; text-decoration-color: #000000\">, </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">-118.019</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">34.499</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span><span style=\"color: #000000; text-decoration-color: #000000\">, </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">-118.019</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">34.499</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span><span style=\"color: #000000; text-decoration-color: #000000\">, </span><span style=\"color: #808000; text-decoration-color: #808000\">...</span><span style=\"font-weight: bold\">&gt;</span> │ <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2</span> │\n",
207
- "│ <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">22618</span> │ <span style=\"font-weight: bold\">&lt;</span><span style=\"color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold\">MULTIPOLYGON</span><span style=\"color: #000000; text-decoration-color: #000000\"> Z </span><span style=\"color: #000000; text-decoration-color: #000000; font-weight: bold\">(((</span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">-118.297</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">34.433</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span><span style=\"color: #000000; text-decoration-color: #000000\">, </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">-118.298</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">34.433</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span><span style=\"color: #000000; text-decoration-color: #000000\">, </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">-118.303</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">34.433</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span><span style=\"color: #000000; text-decoration-color: #000000\">, </span><span style=\"color: #808000; text-decoration-color: #808000\">...</span><span style=\"font-weight: bold\">&gt;</span> │ <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2</span> │\n",
208
- "└────────────────┴──────────────────────────────────────────────────────────────────────────────────┴───────┘\n",
209
- "</pre>\n"
210
- ],
211
- "text/plain": [
212
- "┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓\n",
213
- "┃\u001b[1m \u001b[0m\u001b[1mOBJECTID_right\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mgeom\u001b[0m\u001b[1m \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mreGAP\u001b[0m\u001b[1m \u001b[0m┃\n",
214
- "┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩\n",
215
- "│ \u001b[2mint64\u001b[0m │ \u001b[2mgeospatial:geometry\u001b[0m │ \u001b[2mint16\u001b[0m │\n",
216
- "├────────────────┼──────────────────────────────────────────────────────────────────────────────────┼───────┤\n",
217
- "│ \u001b[1;36m21105\u001b[0m │ \u001b[1m<\u001b[0m\u001b[1;95mMULTIPOLYGON\u001b[0m\u001b[39m Z \u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;36m-118.017\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m34.499\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m0\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m-118.019\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m34.499\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m0\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m-118.019\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m34.499\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m0\u001b[0m\u001b[39m, \u001b[0m\u001b[33m...\u001b[0m\u001b[1m>\u001b[0m │ \u001b[1;36m2\u001b[0m │\n",
218
- "�� \u001b[1;36m22618\u001b[0m │ \u001b[1m<\u001b[0m\u001b[1;95mMULTIPOLYGON\u001b[0m\u001b[39m Z \u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;36m-118.297\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m34.433\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m0\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m-118.298\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m34.433\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m0\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m-118.303\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m34.433\u001b[0m\u001b[39m \u001b[0m\u001b[1;36m0\u001b[0m\u001b[39m, \u001b[0m\u001b[33m...\u001b[0m\u001b[1m>\u001b[0m │ \u001b[1;36m2\u001b[0m │\n",
219
- "└────────────────┴──────────────────────────────────────────────────────────────────────────────────┴───────┘"
220
- ]
221
- },
222
- "execution_count": 170,
223
- "metadata": {},
224
- "output_type": "execute_result"
225
- }
226
- ],
227
  "source": [
228
  "## It intersects these, even though it looks like it shouldn't\n",
229
  "\n",
@@ -239,14 +216,97 @@
239
  },
240
  {
241
  "cell_type": "code",
242
- "execution_count": 162,
243
  "id": "b41b0af6-635c-4ffb-9f19-342284f18e62",
244
  "metadata": {},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  "outputs": [
246
  {
247
  "data": {
248
  "application/vnd.jupyter.widget-view+json": {
249
- "model_id": "64cd02336fac4d9884e2c7ed66472146",
250
  "version_major": 2,
251
  "version_minor": 0
252
  },
@@ -260,47 +320,180 @@
260
  {
261
  "data": {
262
  "application/vnd.jupyter.widget-view+json": {
263
- "model_id": "9729a29cd0f345fd9a9bc46dec111744",
264
  "version_major": 2,
265
- "version_minor": 1
266
  },
267
  "text/plain": [
268
- "Map(height='600px', map_options={'bearing': 0, 'center': (0, 20), 'pitch': 0, 'style': 'https://basemaps.carto…"
269
  ]
270
  },
271
- "execution_count": 162,
272
  "metadata": {},
273
- "output_type": "execute_result"
 
 
 
 
 
 
 
 
 
 
 
274
  }
275
  ],
276
  "source": [
277
- "import leafmap.maplibregl as leafmap\n",
278
- "import ibis\n",
279
- "from ibis import _\n",
280
- "## Minimal look\n",
281
- "areas = (\n",
282
- " con.read_parquet(\"https://data.source.coop/cboettig/ca30x30/ca_areas.parquet\")\n",
283
- " .cast({\"SHAPE\": \"geometry\"})\n",
284
- " .rename(geom = \"SHAPE\")\n",
285
- " .select(\"Release_Year\", \"reGAP\", \"OBJECTID\", \"geom\")\n",
286
- " .mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\"))\n",
287
- " \n",
288
- ")\n",
289
  "\n",
290
- "#areas.filter(_.Release_Year join(la_2023, _.geom.intersects(la_2023.geom), how=\"left\")\n",
 
291
  "\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  "\n",
293
- "new = areas.filter(_.OBJECTID == 111913)\n",
294
- "old = areas.filter(_.OBJECTID == 21105)\n",
295
- "# old.geom.difference(new.geom)\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  "\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  "\n",
298
  "m = leafmap.Map(style=\"positron\")\n",
299
- "#m.add_gdf(old.execute(),layer_type=\"fill\", name = \"2023\", paint=paint)\n",
300
- "m.add_gdf(new.execute(),layer_type=\"fill\", name = \"2024\", paint=paint)\n",
 
301
  "m.add_layer_control()\n",
302
- "m"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  ]
 
 
 
 
 
 
 
 
304
  }
305
  ],
306
  "metadata": {
 
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
+ "execution_count": 16,
6
  "id": "f7e6298c-d886-432a-a1b7-c3fee914c24f",
7
  "metadata": {},
8
  "outputs": [],
 
20
  },
21
  {
22
  "cell_type": "code",
23
+ "execution_count": null,
24
  "id": "bd9c2561-334a-40d6-adf0-ce20a991a9a7",
25
  "metadata": {},
26
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  "source": [
28
  "# Visualize the full data to show overlap:\n",
29
  "import leafmap.maplibregl as leafmap\n",
 
60
  },
61
  {
62
  "cell_type": "code",
63
+ "execution_count": 10,
64
  "id": "3ceed4c7-b7a2-436e-bca1-c57e7133cdf6",
65
  "metadata": {},
66
  "outputs": [],
 
68
  "# Make things faster. Let's zoom in on a subset of the data. \n",
69
  "\n",
70
  "from ibis.interactive import *\n",
 
71
  "ca_parquet = \"/home/rstudio/source.coop/cboettig/ca30x30/ca_areas.parquet\"\n",
72
+ "conn = ibis.duckdb.connect()\n",
73
  "\n",
74
  "# Ugly code for a cookie cutter zoom\n",
75
  "# Turns out we could have just used filter(_.UNIT_NAME == \"Angeles National Forest\")\n",
 
81
  "cookie_cutter = ibis.literal(gdf.geometry.iloc[0])\n",
82
  "\n",
83
  "angeles_forest = (\n",
84
+ " conn.read_parquet(ca_parquet)\n",
85
  " .cast({\"SHAPE\": \"geometry\"})\n",
86
+ " .rename(geom = \"SHAPE\")\n",
87
+ " # .mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\"))\n",
88
+ " # .filter( _.geom.intersects(cookie_cutter))\n",
89
  " .filter(_.UNIT_NAME == \"Angeles National Forest\") \n",
90
  " .select(\"reGAP\", \"UNIT_NAME\", \"MNG_AGNCY\", \"Release_Year\", \"OBJECTID\", \"geom\")\n",
91
+ ")"
92
+ ]
93
+ },
94
+ {
95
+ "cell_type": "code",
96
+ "execution_count": null,
97
+ "id": "a0cb34b1-8d70-49bf-80c6-244ecc8ddf84",
98
+ "metadata": {},
99
+ "outputs": [],
100
+ "source": [
101
+ "import ibis\n",
102
+ "from ibis import _\n",
103
+ "\n",
104
+ "tbl = (\n",
105
+ " conn.read_parquet(\"https://data.source.coop/cboettig/ca30x30/ca_areas.parquet\")\n",
106
+ " .cast({\"SHAPE\": \"geometry\"})\n",
107
+ " .filter(_.UNIT_NAME == \"Angeles National Forest\", _.reGAP < 3) \n",
108
  ")\n",
109
+ "\n",
110
+ "tbl_2023 = tbl.filter(_.Release_Year == 2023)\n",
111
+ "tbl_2024 = tbl.filter(_.Release_Year == 2024)\n",
112
+ "intersects = tbl_2024.anti_join(tbl_2023, _.SHAPE.intersects(tbl_2023.SHAPE))\n",
113
+ "intersects"
114
  ]
115
  },
116
  {
117
  "cell_type": "code",
118
+ "execution_count": 11,
119
  "id": "3ed21429-a75e-4b52-b6eb-d41c8f051883",
120
  "metadata": {},
121
  "outputs": [],
 
127
  },
128
  {
129
  "cell_type": "code",
130
+ "execution_count": 12,
131
  "id": "7bfac88a-822a-4e4e-883e-b7e51544abd1",
132
  "metadata": {},
133
  "outputs": [],
 
138
  "\n",
139
  "# THIS IS ALMOST WHAT WE WANT, BUT for some issues\n",
140
  "# All reGAP 1,2 polygons in 2024 that don't intersect 2023\n",
141
+ "la_intersects = la_2024.anti_join(la_2023, _.geom.intersects(la_2023.geom))\n",
142
+ "\n",
143
+ "#la_contains = la_2024.anti_join(la_2023, _.geom.contains(la_2023.geom.centroid()))\n",
144
+ "#centroids = la_2023.filter(_.reGAP == 2).mutate( geom = la_2023.filter(_.reGAP == 2).geom.centroid() )\n",
145
+ "#centroids = old.mutate( geom = old.geom.centroid() )"
146
  ]
147
  },
148
  {
149
  "cell_type": "code",
150
+ "execution_count": 23,
151
  "id": "ddae1f9e-988a-4aed-bc71-f1c40d2bb0ea",
152
+ "metadata": {},
 
 
153
  "outputs": [
154
  {
155
  "data": {
156
  "application/vnd.jupyter.widget-view+json": {
157
+ "model_id": "ff9365d5ed2848399f1a00952cf6508f",
158
  "version_major": 2,
159
  "version_minor": 1
160
  },
 
162
  "Map(height='600px', map_options={'bearing': 0, 'center': (0, 20), 'pitch': 0, 'style': 'https://basemaps.carto…"
163
  ]
164
  },
165
+ "execution_count": 23,
166
  "metadata": {},
167
  "output_type": "execute_result"
168
  }
 
186
  "paint = {\"fill-color\": gap, \"fill-opacity\": 0.5}\n",
187
  "\n",
188
  "m = leafmap.Map(style=\"positron\")\n",
189
+ "#m.add_gdf(allgap_2023.mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\")).execute(),layer_type=\"fill\", name = \"allgap_2023\", paint=paint)\n",
190
+ "#m.add_gdf(allgap_2024.mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\")).execute(),layer_type=\"fill\", name = \"allgap_2024\", paint=paint)\n",
191
+ "m.add_gdf(la_2023.mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\")).execute(),layer_type=\"fill\", name = \"2023\", paint=paint)\n",
192
+ "#m.add_gdf(la_2024.mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\")).execute(),layer_type=\"fill\", name = \"2024\", paint=paint)\n",
193
+ "#m.add_gdf(la_intersects.mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\")).execute(),layer_type=\"fill\", name = \"anti_intersects\", paint=paint)\n",
 
194
  "m.add_layer_control()\n",
195
  "m"
196
  ]
197
  },
198
  {
199
  "cell_type": "code",
200
+ "execution_count": null,
201
  "id": "6832038f-0342-495f-8cbf-9a8f3cc83aac",
202
  "metadata": {},
203
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  "source": [
205
  "## It intersects these, even though it looks like it shouldn't\n",
206
  "\n",
 
216
  },
217
  {
218
  "cell_type": "code",
219
+ "execution_count": null,
220
  "id": "b41b0af6-635c-4ffb-9f19-342284f18e62",
221
  "metadata": {},
222
+ "outputs": [],
223
+ "source": [
224
+ "import leafmap.maplibregl as leafmap\n",
225
+ "import ibis\n",
226
+ "from ibis import _\n",
227
+ "## Minimal look\n",
228
+ "areas = (\n",
229
+ " conn.read_parquet(\"https://data.source.coop/cboettig/ca30x30/ca_areas.parquet\")\n",
230
+ " .cast({\"SHAPE\": \"geometry\"})\n",
231
+ " .rename(geom = \"SHAPE\")\n",
232
+ " .select(\"Release_Year\", \"reGAP\", \"OBJECTID\", \"geom\")\n",
233
+ " .mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\"))\n",
234
+ " \n",
235
+ ")\n",
236
+ "new = areas.filter(_.OBJECTID == 111913)\n",
237
+ "old = areas.filter(_.OBJECTID == 21105)\n",
238
+ "# old.geom.difference(new.geom)\n",
239
+ "\n",
240
+ "\n",
241
+ "m = leafmap.Map(style=\"positron\")\n",
242
+ "m.add_gdf(old.execute(),layer_type=\"fill\", name = \"2023\", paint=paint)\n",
243
+ "m.add_gdf(new.execute(),layer_type=\"fill\", name = \"2024\", paint=paint)\n",
244
+ "m.add_layer_control()\n",
245
+ "m"
246
+ ]
247
+ },
248
+ {
249
+ "cell_type": "code",
250
+ "execution_count": null,
251
+ "id": "ab985b4f-2257-46ce-95af-508c17323ca3",
252
+ "metadata": {},
253
+ "outputs": [],
254
+ "source": []
255
+ },
256
+ {
257
+ "cell_type": "code",
258
+ "execution_count": 13,
259
+ "id": "96cefbe6-12c9-4ca4-9352-c3573924c91c",
260
+ "metadata": {},
261
+ "outputs": [],
262
+ "source": [
263
+ "la_2023.execute().to_file(\"la_2023.geojson\")\n",
264
+ "la_2024.execute().to_file(\"la_2024.geojson\")\n"
265
+ ]
266
+ },
267
+ {
268
+ "cell_type": "code",
269
+ "execution_count": null,
270
+ "id": "4b9ee360-8583-4096-b1e1-43772f32a182",
271
+ "metadata": {},
272
+ "outputs": [],
273
+ "source": [
274
+ "la_2024.filter(_.OBJECTID == 111913).execute().to_file(\"new.geojson\")\n",
275
+ "la_2023.filter(_.OBJECTID == 21105).execute().to_file(\"old.geojson\")\n"
276
+ ]
277
+ },
278
+ {
279
+ "cell_type": "code",
280
+ "execution_count": 41,
281
+ "id": "1e538620-19f5-42eb-8233-e280b5c5b920",
282
+ "metadata": {},
283
+ "outputs": [],
284
+ "source": [
285
+ "import ibis\n",
286
+ "from ibis import _\n",
287
+ "\n",
288
+ "tbl = (\n",
289
+ " conn.read_parquet(\"https://data.source.coop/cboettig/ca30x30/ca_areas.parquet\")\n",
290
+ " .cast({\"SHAPE\": \"geometry\"})\n",
291
+ " .filter(_.UNIT_NAME == \"Angeles National Forest\", _.reGAP < 3) \n",
292
+ ")\n",
293
+ "\n",
294
+ "tbl_2023 = tbl.filter(_.Release_Year == 2023)\n",
295
+ "tbl_2024 = tbl.filter(_.Release_Year == 2024)\n",
296
+ "# old method\n",
297
+ "#intersects = tbl_2024.anti_join(tbl_2023, _.SHAPE.intersects(tbl_2023.SHAPE))"
298
+ ]
299
+ },
300
+ {
301
+ "cell_type": "code",
302
+ "execution_count": 57,
303
+ "id": "34e264c1-e6d4-4982-b8a7-5b856a3d22c3",
304
+ "metadata": {},
305
  "outputs": [
306
  {
307
  "data": {
308
  "application/vnd.jupyter.widget-view+json": {
309
+ "model_id": "11300de9b00446b88e10c2e4f41d81ca",
310
  "version_major": 2,
311
  "version_minor": 0
312
  },
 
320
  {
321
  "data": {
322
  "application/vnd.jupyter.widget-view+json": {
323
+ "model_id": "8ca97fd0f9d74a898d03fa41497c4836",
324
  "version_major": 2,
325
+ "version_minor": 0
326
  },
327
  "text/plain": [
328
+ "FloatProgress(value=0.0, layout=Layout(width='auto'), style=ProgressStyle(bar_color='black'))"
329
  ]
330
  },
 
331
  "metadata": {},
332
+ "output_type": "display_data"
333
+ },
334
+ {
335
+ "ename": "InternalException",
336
+ "evalue": "INTERNAL Error: Calling StringValue::Get on a NULL value\nThis error signals an assertion failure within DuckDB. This usually occurs due to unexpected conditions or errors in the program's logic.\nFor more information, see https://duckdb.org/docs/dev/internal_errors",
337
+ "output_type": "error",
338
+ "traceback": [
339
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
340
+ "\u001b[0;31mInternalException\u001b[0m Traceback (most recent call last)",
341
+ "Cell \u001b[0;32mIn[57], line 9\u001b[0m\n\u001b[1;32m 7\u001b[0m con\u001b[38;5;241m.\u001b[39minstall_extension(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mspatial\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 8\u001b[0m con\u001b[38;5;241m.\u001b[39mload_extension(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mspatial\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m----> 9\u001b[0m \u001b[43mdb\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msql\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'''\u001b[39;49m\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124;43mCOPY(\u001b[39;49m\n\u001b[1;32m 11\u001b[0m \u001b[38;5;124;43m SELECT ST_DIFFERENCE(_2024.geom, _2023.geom) AS geom,\u001b[39;49m\n\u001b[1;32m 12\u001b[0m \u001b[38;5;124;43m FROM ST_Read(\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mla_2024.geojson\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m) _2024\u001b[39;49m\n\u001b[1;32m 13\u001b[0m \u001b[38;5;124;43m LEFT JOIN (\u001b[39;49m\n\u001b[1;32m 14\u001b[0m \u001b[38;5;124;43m SELECT *\u001b[39;49m\n\u001b[1;32m 15\u001b[0m \u001b[38;5;124;43m FROM ST_Read(\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mla_2023.geojson\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m)\u001b[39;49m\n\u001b[1;32m 16\u001b[0m \u001b[38;5;124;43m ) _2023\u001b[39;49m\n\u001b[1;32m 17\u001b[0m \u001b[38;5;124;43m ON ST_INTERSECTS(_2024.geom,_2023.geom)\u001b[39;49m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;124;43m) TO \u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43msimple.geojson\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m WITH (FORMAT GDAL, DRIVER \u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mGeoJSON\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m, LAYER_CREATION_OPTIONS \u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mWRITE_BBOX=YES\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m)\u001b[39;49m\n\u001b[1;32m 19\u001b[0m \u001b[38;5;124;43m'''\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 21\u001b[0m \u001b[38;5;66;03m# IF(_2023.objectid IS NULL, _2024.geom, ST_DIFFERENCE(_2024.geom, _2023.geom)) AS geom,\u001b[39;00m\n",
342
+ "\u001b[0;31mInternalException\u001b[0m: INTERNAL Error: Calling StringValue::Get on a NULL value\nThis error signals an assertion failure within DuckDB. This usually occurs due to unexpected conditions or errors in the program's logic.\nFor more information, see https://duckdb.org/docs/dev/internal_errors"
343
+ ]
344
  }
345
  ],
346
  "source": [
347
+ "import duckdb\n",
 
 
 
 
 
 
 
 
 
 
 
348
  "\n",
349
+ "tbl_2023.execute().to_file(\"la_2023.geojson\")\n",
350
+ "tbl_2024.execute().to_file(\"la_2024.geojson\")\n",
351
  "\n",
352
+ "con = duckdb.connect()\n",
353
+ "con.install_extension(\"spatial\")\n",
354
+ "con.load_extension(\"spatial\")\n",
355
+ "db.sql('''\n",
356
+ "COPY(\n",
357
+ " SELECT ST_DIFFERENCE(_2024.geom, _2023.geom) AS geom,\n",
358
+ " FROM ST_Read('la_2024.geojson') _2024\n",
359
+ " LEFT JOIN (\n",
360
+ " SELECT *\n",
361
+ " FROM ST_Read('la_2023.geojson')\n",
362
+ " ) _2023\n",
363
+ " ON ST_INTERSECTS(_2024.geom,_2023.geom)\n",
364
+ ") TO 'simple.geojson' WITH (FORMAT GDAL, DRIVER 'GeoJSON', LAYER_CREATION_OPTIONS 'WRITE_BBOX=YES')\n",
365
+ "''')\n",
366
  "\n",
367
+ "# IF(_2023.objectid IS NULL, _2024.geom, ST_DIFFERENCE(_2024.geom, _2023.geom)) AS geom,\n",
368
+ "\n"
369
+ ]
370
+ },
371
+ {
372
+ "cell_type": "code",
373
+ "execution_count": 3,
374
+ "id": "21dbc7c4-20e2-4422-ac21-cd50badcae58",
375
+ "metadata": {},
376
+ "outputs": [],
377
+ "source": [
378
+ "import duckdb\n",
379
+ "db = duckdb.connect()\n",
380
+ "db.install_extension(\"spatial\")\n",
381
+ "db.load_extension(\"spatial\")\n",
382
+ "\n",
383
+ "\n",
384
+ "db.sql('''\n",
385
+ "CREATE OR REPLACE TABLE t1 AS SELECT OBJECTID AS gid, geom, FROM st_read(\"la_2024.geojson\");\n",
386
+ "CREATE OR REPLACE TABLE t2 AS SELECT OBJECTID AS gid, geom, FROM st_read(\"la_2023.geojson\");\n",
387
+ "''')\n",
388
+ "\n"
389
+ ]
390
+ },
391
+ {
392
+ "cell_type": "code",
393
+ "execution_count": 9,
394
+ "id": "d467548c-892f-4786-bfb2-0599f6d3d159",
395
+ "metadata": {},
396
+ "outputs": [],
397
+ "source": [
398
  "\n",
399
+ "db.sql('''\n",
400
+ "COPY (\n",
401
+ "with temp as \n",
402
+ "(\n",
403
+ " select b.gid, st_union_agg(a.geom) as geom\n",
404
+ " from t1 b join t2 a on st_intersects(a.geom, b.geom)\n",
405
+ " group by b.gid\n",
406
+ ") \n",
407
+ "select st_difference(b.geom,coalesce(t.geom, 'GEOMETRYCOLLECTION EMPTY'::geometry)) as geom\n",
408
+ "from t1 b left join temp t on b.gid = t.gid\n",
409
+ ") TO 'simple.geojson' WITH (FORMAT GDAL, DRIVER 'GeoJSON', LAYER_CREATION_OPTIONS 'WRITE_BBOX=YES')\n",
410
+ "''')"
411
+ ]
412
+ },
413
+ {
414
+ "cell_type": "code",
415
+ "execution_count": 10,
416
+ "id": "d869c220-a4c2-46b1-9e02-d5cce5a2bffa",
417
+ "metadata": {},
418
+ "outputs": [],
419
+ "source": [
420
+ "import ibis\n",
421
+ "from ibis import _\n",
422
+ "con = ibis.duckdb.connect()\n",
423
+ "diff = con.read_geo(\"simple.geojson\").mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\"))\n"
424
+ ]
425
+ },
426
+ {
427
+ "cell_type": "code",
428
+ "execution_count": 16,
429
+ "id": "598d096a-5cae-4ddc-938c-908eba334b91",
430
+ "metadata": {},
431
+ "outputs": [
432
+ {
433
+ "data": {
434
+ "application/vnd.jupyter.widget-view+json": {
435
+ "model_id": "9eae57f133a44d0799e4622fdb318e30",
436
+ "version_major": 2,
437
+ "version_minor": 1
438
+ },
439
+ "text/plain": [
440
+ "Map(height='600px', map_options={'bearing': 0, 'center': (0, 20), 'pitch': 0, 'style': 'https://basemaps.carto…"
441
+ ]
442
+ },
443
+ "execution_count": 16,
444
+ "metadata": {},
445
+ "output_type": "execute_result"
446
+ }
447
+ ],
448
+ "source": [
449
+ "import leafmap.maplibregl as leafmap\n",
450
  "\n",
451
  "m = leafmap.Map(style=\"positron\")\n",
452
+ "#m.add_gdf(la_2023.mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\")).execute(),layer_type=\"fill\", name = \"la_2023\", paint = {\"fill-opacity\": 0.5})\n",
453
+ "#m.add_gdf(la_2024.mutate(geom = _.geom.convert(\"epsg:3310\",\"epsg:4326\")).execute(),layer_type=\"fill\", name = \"la_2024\", paint = {\"fill-opacity\": 0.5})\n",
454
+ "m.add_gdf(diff.execute(),layer_type=\"fill\", name = \"diff\", paint = {\"fill-opacity\": 0.5})\n",
455
  "m.add_layer_control()\n",
456
+ "m\n"
457
+ ]
458
+ },
459
+ {
460
+ "cell_type": "code",
461
+ "execution_count": null,
462
+ "id": "d7c08912-3c8a-4810-b046-ea46008880ca",
463
+ "metadata": {},
464
+ "outputs": [],
465
+ "source": [
466
+ "import duckdb\n",
467
+ "\n",
468
+ "con = duckdb.connect()\n",
469
+ "con.install_extension(\"spatial\")\n",
470
+ "con.load_extension(\"spatial\")\n",
471
+ "con.sql('''\n",
472
+ "COPY(\n",
473
+ "WITH geom1 AS (\n",
474
+ " SELECT geom\n",
475
+ " FROM ST_Read('new.geojson')\n",
476
+ "),\n",
477
+ "geom2 AS (\n",
478
+ " SELECT geom\n",
479
+ " FROM ST_Read('old.geojson')\n",
480
+ ")\n",
481
+ "SELECT ST_Difference(\n",
482
+ " (SELECT geom FROM geom1),\n",
483
+ " (SELECT geom FROM geom2)\n",
484
+ ") AS geom\n",
485
+ ") TO 'simple.geojson' WITH (FORMAT GDAL, DRIVER 'GeoJSON', LAYER_CREATION_OPTIONS 'WRITE_BBOX=YES')\n",
486
+ "''')\n",
487
+ "\n"
488
  ]
489
+ },
490
+ {
491
+ "cell_type": "code",
492
+ "execution_count": null,
493
+ "id": "b47fd840-a918-4690-adc0-ca074d09932c",
494
+ "metadata": {},
495
+ "outputs": [],
496
+ "source": []
497
  }
498
  ],
499
  "metadata": {