Skip to content

Commit a47775f

Browse files
authored
Rewrite (#4)
* rewrite. Use GLMakie. Basic version is working! * make PolygonFeature mutable * nearing done * add geojson write * cleanup * wip * discovered segfault... * workaround for segfault, fix geojson serialization * basic tests * readme
1 parent 2397931 commit a47775f

File tree

10 files changed

+731
-114
lines changed

10 files changed

+731
-114
lines changed

.DS_Store

0 Bytes
Binary file not shown.

Project.toml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,26 @@ authors = ["Josh Day <[email protected]> and contributors"]
44
version = "0.1.0"
55

66
[deps]
7-
Pluto = "c3e4b0f8-55cb-11ea-2926-15256bba5781"
8-
Scratch = "6c6a2e73-6563-6170-7368-637461726353"
7+
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
8+
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
9+
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
10+
Observables = "510215fc-4207-5dde-b226-833fc4488ee2"
11+
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
12+
Rasters = "a3a2b9e3-a471-40c9-b274-f788e487c689"
13+
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
914

1015
[compat]
11-
julia = "1"
12-
Scratch = "1.1"
13-
Pluto = "0.19"
16+
GLMakie = "0.10"
17+
JSON3 = "1"
18+
Observables = "0.5"
19+
OrderedCollections = "1.6"
20+
Rasters = "0.11"
21+
julia = "1.10"
1422

1523
[extras]
24+
GeoJSON = "61d90e0f-e114-555e-ac52-39dfb47a3ef9"
25+
RasterDataSources = "3cb90ccd-e1b6-4867-9617-4276c8b2ca36"
1626
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1727

1828
[targets]
19-
test = ["Test"]
29+
test = ["Test", "RasterDataSources", "GeoJSON"]

README.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
11
# InteractiveGeo
22

3-
**InteractiveGeo** is a Julia package that provides interactive tools that aid in working with geospatial data.
3+
- **InteractiveGeo** is a Julia package that provides interactive tools that aid in working with geospatial data.
4+
- **InteractiveGeo** is built primarily on top of [GLMakie](https://docs.makie.org/stable/explanations/backends/glmakie#glmakie) and [Rasters](https://rafaqz.github.io/Rasters.jl/dev/).
45

5-
## Pluto Notebooks
6+
## Usage
67

7-
### Draw a polygon over raster data and save it as GeoJSON.
88

99
```julia
10-
InteractiveGeo.draw_polygon()
10+
using Rasters, InteractiveGeo, RasterDataSources
11+
12+
# Load a Raster
13+
files = getraster(WorldClim{Climate}, :wind; month=1:12)
14+
r = Raster(files[1])
15+
16+
# Create an Interactive Map of the Raster
17+
# The returned `features` object is an `Observable` that is populated based on features (polygons) drawn on the map
18+
features = draw_features(r)
19+
20+
# You can now add Markdown annotations to the polygon features
21+
features[]["polygon_label"] = md"My notes"
22+
23+
# Finally, you can save features as GeoJSON
24+
str = geojson(features[]) # String representation of the GeoJSON
25+
write("features.geojson", str) # Save the GeoJSON to a file
1126
```
1227

13-
![](https://user-images.githubusercontent.com/8075494/214069659-63fb77c7-43d3-4a38-b24b-a9f7bfc2dcf4.png)
28+
![](https://github.com/user-attachments/assets/dc7c8641-873b-4b9f-ade9-cff07a01b3ee)

pluto/annotated_polygons.jl

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
### A Pluto.jl notebook ###
2+
# v0.19.46
3+
4+
using Markdown
5+
using InteractiveUtils
6+
7+
# ╔═╡ eaa940d8-660f-11ef-3578-c7ec2f570496
8+
begin
9+
using Pkg
10+
Pkg.activate(joinpath(@__DIR__, ".."))
11+
12+
using ArchGDAL, CoordinateTransformations, Rasters, PlutoUI, Extents, GLMakie,
13+
About, PlutoHooks, DataFrames
14+
using Cobweb: h
15+
using PlotlyLight
16+
PlotlyLight.settings.div = h.div(style="width:700px;height:700px")
17+
import GeoJSON
18+
PlutoUI.TableOfContents()
19+
end
20+
21+
# ╔═╡ 3a8b1fd6-d4ef-41f2-8862-44588d4f933d
22+
md"""
23+
# Load Raster
24+
25+
| Variable (w/ Default) | Description |
26+
|----------|-------------|
27+
`path = ""` | file path of raster
28+
`geojson_path = ""` | file path of geojson file
29+
`max_res = 1000` | Maximum resolution to plot
30+
`colorscale = cbrt` | Remap function
31+
`colormap = :viridis` | Colorscale of heatmap
32+
`band = 1` | Band to view (only for 3D Arrays)
33+
"""
34+
35+
# ╔═╡ 0d1f7998-bfc7-477b-9b30-c37ec8a53b79
36+
path = "/Users/joshday/datasets/geospatial/FARAD_X_BAND/20151027_1027X04_PS0011_PT000001_N03_M1_CH0_OSAPF.ntf"
37+
38+
# ╔═╡ c2008154-09ec-4599-88c6-06d5686e6cf2
39+
geojson_path = ""
40+
41+
# ╔═╡ 8b31bd88-a734-49cf-a147-e61274385d47
42+
max_res = 1000
43+
44+
# ╔═╡ 058602ca-ebb8-446a-86f5-6a929eb25846
45+
colorscale = cbrt
46+
47+
# ╔═╡ 9c28755a-db49-4317-9d6d-a9d6150f4348
48+
colormap = :viridis
49+
50+
# ╔═╡ 766ea541-72c0-4da9-8067-a7f220c34b0e
51+
band = 1
52+
53+
# ╔═╡ f76f9eb8-8edd-4693-8901-342a9e2cf0d3
54+
begin
55+
geojson = if isempty(geojson_path)
56+
@info "No GeoJSON File provided. Creating new table."
57+
DataFrame(; geometry=[])
58+
else
59+
DataFrame(GeoJSON.read(geojson_path))
60+
end
61+
end
62+
63+
# ╔═╡ 72c8035f-0b08-4529-bfe7-788efda4f834
64+
Rasters.GeoJSON
65+
66+
# ╔═╡ bb7b0c84-aeed-4f15-9f58-651f994f63d9
67+
begin
68+
colorscale_opts = sort!(["Greys", "Blues", "YlOrRd", "YlGnBu", "RdBu", "Portland", "Picnic", "Jet", "Hot", "Greens", "Electric", "Earth", "Bluered", "Blackbody"])
69+
70+
md"""
71+
# Plot
72+
"""
73+
end
74+
75+
# ╔═╡ df240886-bdf1-4f2d-a2df-5a0bd642c5af
76+
# ╠═╡ disabled = true
77+
#=╠═╡
78+
begin
79+
idx = length(size(r2)) == 3 ? [:, :, band] : [:, :]
80+
81+
fig = Figure()
82+
ax = Axis(fig[1,1])
83+
hmap = heatmap!(ax, getindex(r2, idx...); colormap, colorscale)
84+
Colorbar(fig[1,2], hmap)
85+
fig
86+
end
87+
╠═╡ =#
88+
89+
# ╔═╡ b0740d40-9d57-44cb-aff0-752e8e054653
90+
md"""
91+
# State
92+
"""
93+
94+
# ╔═╡ d799c8ba-363f-4c29-9672-5f1f60e57dbe
95+
coordinates, set_coordinates = @use_state([])
96+
97+
# ╔═╡ 7064de72-e113-4f1f-9629-b4abe9f431d7
98+
features, set_features = @use_state([])
99+
100+
# ╔═╡ bad0141f-ee94-48ba-84be-9b6a2477eed3
101+
md"# Notebook Utilities"
102+
103+
# ╔═╡ e0ed90e2-12ee-456b-9491-4628871f49be
104+
macro ifdata(ex)
105+
esc(quote
106+
if !isempty(path)
107+
$ex
108+
elseif !isfile(path)
109+
@warn "No file found at path: $path"
110+
else
111+
@info "no dataset selected."
112+
end
113+
end)
114+
end
115+
116+
# ╔═╡ f238af1b-0643-44dd-9ed6-f2177b1c564a
117+
@ifdata begin
118+
r = Raster(path)
119+
ext = Extents.extent(r)
120+
nbands = size(r.data, 3)
121+
122+
@info """
123+
Source Raster
124+
=============
125+
126+
- $(summary(r))
127+
- X: $(ext.X)
128+
- Y: $(ext.Y)
129+
"""
130+
end;
131+
132+
# ╔═╡ 314472b5-9eab-47f1-a629-f77f72e030cb
133+
begin
134+
r2 = Rasters._maybe_resample(r)
135+
r2 = Rasters._subsample(r2, max_res)
136+
@info """
137+
Subsampled Raster
138+
=================
139+
140+
- $(summary(r2))
141+
"""
142+
end
143+
144+
# ╔═╡ 0c0528c0-f989-4afb-963c-0b52bf52238d
145+
begin
146+
idx = length(size(r2)) == 3 ? [:, :, band] : [:, :]
147+
A = getindex(r2, idx...)
148+
@info """
149+
Raster to Plot
150+
==============
151+
152+
- $(summary(A))
153+
"""
154+
end
155+
156+
# ╔═╡ d6f6ea9e-4064-48ad-a0a3-3016b660a803
157+
begin
158+
p = PlotlyLight.plot(z=A, type="heatmap")
159+
160+
h.div(class="width=100%;height=100%",
161+
PlotlyLight.html_div(p; id="_plot_"),
162+
h.script("""
163+
var p = document.getElementById("_plot_");
164+
165+
console.log("hi")
166+
""")
167+
)
168+
end
169+
170+
# ╔═╡ 43b89c8c-4149-4900-9e5e-445ffe81902c
171+
function haversine(a, b; R=6372.8)
172+
Δlat = b.lat - a.lat
173+
Δlon = b.lon - a.lon
174+
a = sind(Δlat / 2) ^ 2 + cosd(a.lat) * cosd(b.lat) * sind(Δlon / 2) ^ 2
175+
2R * asin(min(sqrt(a), one(a)))
176+
end
177+
178+
# ╔═╡ 15526a94-7d8f-4494-8a2a-0388da1609ed
179+
function latlonratio(lat, lon)
180+
Δlat = haversine((lat=0,lon=0), (lat=1,lon=0))
181+
Δlon = haversine((;lat, lon = lon - .5), (;lat, lon = lon + .5))
182+
Δlat / Δlon
183+
end
184+
185+
# ╔═╡ Cell order:
186+
# ╠═eaa940d8-660f-11ef-3578-c7ec2f570496
187+
# ╟─3a8b1fd6-d4ef-41f2-8862-44588d4f933d
188+
# ╠═0d1f7998-bfc7-477b-9b30-c37ec8a53b79
189+
# ╠═c2008154-09ec-4599-88c6-06d5686e6cf2
190+
# ╠═8b31bd88-a734-49cf-a147-e61274385d47
191+
# ╠═058602ca-ebb8-446a-86f5-6a929eb25846
192+
# ╠═9c28755a-db49-4317-9d6d-a9d6150f4348
193+
# ╠═766ea541-72c0-4da9-8067-a7f220c34b0e
194+
# ╟─f238af1b-0643-44dd-9ed6-f2177b1c564a
195+
# ╟─314472b5-9eab-47f1-a629-f77f72e030cb
196+
# ╟─0c0528c0-f989-4afb-963c-0b52bf52238d
197+
# ╠═d6f6ea9e-4064-48ad-a0a3-3016b660a803
198+
# ╠═f76f9eb8-8edd-4693-8901-342a9e2cf0d3
199+
# ╠═72c8035f-0b08-4529-bfe7-788efda4f834
200+
# ╠═bb7b0c84-aeed-4f15-9f58-651f994f63d9
201+
# ╠═df240886-bdf1-4f2d-a2df-5a0bd642c5af
202+
# ╟─b0740d40-9d57-44cb-aff0-752e8e054653
203+
# ╠═d799c8ba-363f-4c29-9672-5f1f60e57dbe
204+
# ╠═7064de72-e113-4f1f-9629-b4abe9f431d7
205+
# ╟─bad0141f-ee94-48ba-84be-9b6a2477eed3
206+
# ╟─e0ed90e2-12ee-456b-9491-4628871f49be
207+
# ╟─43b89c8c-4149-4900-9e5e-445ffe81902c
208+
# ╟─15526a94-7d8f-4494-8a2a-0388da1609ed

0 commit comments

Comments
 (0)