Skip to content

Commit bc9e996

Browse files
Merge pull request #16 from nextmv-io/feature/eng-5684-fix-jpath-geojson-plotting-in-nextplot
Fixes JPath based nested GeoJSON plotting
2 parents af67550 + edb0325 commit bc9e996

5 files changed

Lines changed: 287 additions & 3 deletions

File tree

nextplot/geojson.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,15 @@ def parse(
104104
Parses the geojson data object(s) from the file(s).
105105
"""
106106
# Load json data
107-
content_geojson, _ = common.load_data(input_geojson, "")
107+
content, _ = common.load_data(input_geojson, "")
108+
json_content = json.loads(content)
108109

109110
# Extract geojsons
110111
if jpath_geojson:
111112
expression = jsonpath_ng.parse(jpath_geojson)
112-
geojsons = [json.loads(match.value) for match in expression.find(content_geojson)]
113+
geojsons = [match.value for match in expression.find(json_content)]
113114
else:
114-
geojsons = [json.loads(content_geojson)]
115+
geojsons = [json_content]
115116

116117
return geojsons
117118

tests/test_cli.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,23 @@ def test_map_plot_cli_geojson():
480480
_run_geojson_test(test)
481481

482482

483+
def test_map_plot_cli_geojson_nested():
484+
test = GeoJSONTest(
485+
"geojson",
486+
[
487+
"geojson",
488+
"--input_geojson",
489+
os.path.join(DATA_DIR, "geojson-nested-data.json"),
490+
"--jpath_geojson",
491+
"assets[*].content",
492+
],
493+
os.path.join(OUTPUT_DIR, "geojson-nested-data.json.map.html"),
494+
os.path.join(DATA_DIR, "geojson-nested-data.json.golden"),
495+
os.path.join(DATA_DIR, "geojson-nested-data.json.map.html.golden"),
496+
)
497+
_run_geojson_test(test)
498+
499+
483500
def test_progression_plot_cli_fleet_cloud_comparison():
484501
test = ProgressionTest(
485502
"fleet-cloud-comparison",
@@ -507,5 +524,6 @@ def test_progression_plot_cli_fleet_cloud_comparison():
507524
test_map_plot_cli_paris_point()
508525
test_map_plot_cli_paris_route_indexed()
509526
test_map_plot_cli_geojson()
527+
test_map_plot_cli_geojson_nested()
510528
test_progression_plot_cli_fleet_cloud_comparison()
511529
print("Everything passed")
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"assets": [
3+
{
4+
"type": "geojson",
5+
"content": {
6+
"type": "FeatureCollection",
7+
"features": [
8+
{
9+
"type": "Feature",
10+
"geometry": {
11+
"type": "Point",
12+
"coordinates": [-74.076, 4.598]
13+
},
14+
"properties": {}
15+
},
16+
{
17+
"type": "Feature",
18+
"geometry": {
19+
"type": "Point",
20+
"coordinates": [-75.1649, 39.9525]
21+
},
22+
"properties": {}
23+
}
24+
]
25+
}
26+
},
27+
{
28+
"type": "geojson",
29+
"content": {
30+
"type": "Feature",
31+
"geometry": {
32+
"type": "Point",
33+
"coordinates": [7.6281, 51.962]
34+
},
35+
"properties": {}
36+
}
37+
}
38+
]
39+
}

tests/testdata/geojson-nested-data.json.golden

Whitespace-only changes.
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
5+
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
6+
7+
<script>
8+
L_NO_TOUCH = false;
9+
L_DISABLE_3D = false;
10+
</script>
11+
12+
<style>html, body {width: 100%;height: 100%;margin: 0;padding: 0;}</style>
13+
<style>#map {position:absolute;top:0;bottom:0;right:0;left:0;}</style>
14+
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.js"></script>
15+
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
16+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
17+
<script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js"></script>
18+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.css"/>
19+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css"/>
20+
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css"/>
21+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.2.0/css/all.min.css"/>
22+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css"/>
23+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css"/>
24+
25+
<meta name="viewport" content="width=device-width,
26+
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
27+
<style>
28+
#map_ {
29+
position: relative;
30+
width: 100.0%;
31+
height: 100.0%;
32+
left: 0.0%;
33+
top: 0.0%;
34+
}
35+
.leaflet-container { font-size: 1rem; }
36+
</style>
37+
38+
<script src="https://cdn.jsdelivr.net/npm/leaflet.fullscreen@3.0.0/Control.FullScreen.min.js"></script>
39+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet.fullscreen@3.0.0/Control.FullScreen.css"/>
40+
<script src="https://cdn.jsdelivr.net/npm/leaflet.control.layers.tree@1.1.0/L.Control.Layers.Tree.min.js"></script>
41+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet.control.layers.tree@1.1.0/L.Control.Layers.Tree.min.css"/>
42+
</head>
43+
<body>
44+
45+
46+
<div class="folium-map" id="map_" ></div>
47+
48+
</body>
49+
<script>
50+
51+
52+
var map_ = L.map(
53+
"map_",
54+
{
55+
center: [28.28, -33.7684],
56+
crs: L.CRS.EPSG3857,
57+
zoom: 10,
58+
zoomControl: true,
59+
preferCanvas: false,
60+
zoomSnap: 0.25,
61+
zoomDelta: 0.25,
62+
wheelPxPerZoomLevel: 180,
63+
}
64+
);
65+
66+
67+
68+
69+
70+
var tile_layer_ = L.tileLayer(
71+
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
72+
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
73+
);
74+
75+
76+
tile_layer_.addTo(map_);
77+
78+
79+
var tile_layer_ = L.tileLayer(
80+
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
81+
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
82+
);
83+
84+
85+
tile_layer_.addTo(map_);
86+
87+
88+
var tile_layer_ = L.tileLayer(
89+
"https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
90+
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors \u0026copy; \u003ca href=\"https://carto.com/attributions\"\u003eCARTO\u003c/a\u003e", "detectRetina": false, "maxNativeZoom": 20, "maxZoom": 20, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abcd", "tms": false}
91+
);
92+
93+
94+
tile_layer_.addTo(map_);
95+
96+
97+
var tile_layer_ = L.tileLayer(
98+
"https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
99+
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors \u0026copy; \u003ca href=\"https://carto.com/attributions\"\u003eCARTO\u003c/a\u003e", "detectRetina": false, "maxNativeZoom": 20, "maxZoom": 20, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abcd", "tms": false}
100+
);
101+
102+
103+
tile_layer_.addTo(map_);
104+
105+
106+
var feature_group_ = L.featureGroup(
107+
{}
108+
);
109+
110+
111+
112+
function geo_json__onEachFeature(feature, layer) {
113+
layer.on({
114+
});
115+
};
116+
var geo_json_ = L.geoJson(null, {
117+
onEachFeature: geo_json__onEachFeature,
118+
119+
});
120+
121+
function geo_json__add (data) {
122+
geo_json_
123+
.addData(data);
124+
}
125+
geo_json__add({"features": [{"geometry": {"coordinates": [-74.076, 4.598], "type": "Point"}, "properties": {}, "type": "Feature"}, {"geometry": {"coordinates": [-75.1649, 39.9525], "type": "Point"}, "properties": {}, "type": "Feature"}], "type": "FeatureCollection"});
126+
geo_json_.setStyle(function(feature) {return feature.properties.style;});
127+
128+
129+
130+
geo_json_.addTo(feature_group_);
131+
132+
133+
feature_group_.addTo(map_);
134+
135+
136+
var feature_group_ = L.featureGroup(
137+
{}
138+
);
139+
140+
141+
142+
function geo_json__onEachFeature(feature, layer) {
143+
layer.on({
144+
});
145+
};
146+
var geo_json_ = L.geoJson(null, {
147+
onEachFeature: geo_json__onEachFeature,
148+
149+
});
150+
151+
function geo_json__add (data) {
152+
geo_json_
153+
.addData(data);
154+
}
155+
geo_json__add({"geometry": {"coordinates": [7.6281, 51.962], "type": "Point"}, "properties": {}, "type": "Feature"});
156+
geo_json_.setStyle(function(feature) {return feature.properties.style;});
157+
158+
159+
160+
geo_json_.addTo(feature_group_);
161+
162+
163+
feature_group_.addTo(map_);
164+
165+
166+
L.control.fullscreen(
167+
{"forceSeparateButton": false, "position": "topright", "title": "Expand me", "titleCancel": "Exit me"}
168+
).addTo(map_);
169+
170+
171+
L.control.layers.tree(
172+
{
173+
"label": "Base Layers",
174+
"children": [
175+
{
176+
"label": "Tiles",
177+
"radioGroup": "tiles",
178+
"children": [
179+
{
180+
"label": "openstreetmap",
181+
"layer": tile_layer_,
182+
},
183+
{
184+
"label": "cartodbdark_matter",
185+
"layer": tile_layer_,
186+
},
187+
{
188+
"label": "cartodb positron",
189+
"layer": tile_layer_,
190+
},
191+
],
192+
},
193+
],
194+
},
195+
{
196+
"label": "Overlays",
197+
"selectAllCheckbox": "Un/select all",
198+
"children": [
199+
{
200+
"label": "GeoJSONs",
201+
"selectAllCheckbox": true,
202+
"collapsed": true,
203+
"children": [
204+
{
205+
"label": "GeoJSON 0",
206+
"layer": feature_group_,
207+
},
208+
{
209+
"label": "GeoJSON 1",
210+
"layer": feature_group_,
211+
},
212+
],
213+
},
214+
],
215+
},
216+
{"closedSymbol": "+", "collapseAll": "", "expandAll": "", "labelIsSelector": "both", "namedToggle": false, "openenedSymbol": "-", "selectorBack": false, "spaceSymbol": "\u0026nbsp;"}
217+
).addTo(map_);
218+
219+
220+
map_.fitBounds(
221+
[[51.962, 7.6281], [51.962, 7.6281]],
222+
{}
223+
);
224+
225+
</script>
226+
</html>

0 commit comments

Comments
 (0)