Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/v0.1.3 #32

Merged
merged 22 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .examples/earthquakes_cluster/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from shiny import App, reactive, ui

from maplibre import Layer, Map, MapOptions, output_maplibregl, render_maplibregl
from maplibre.basemaps import Carto
from maplibre.sources import GeoJSONSource
from shiny import App, reactive, ui

SOURCE_ID = "earthquakes"
LAYER_ID = "earthquakes"
Expand Down
14 changes: 4 additions & 10 deletions .examples/experimental/app2.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import requests as req
from shiny import App, reactive, render, ui

from maplibre import (
Layer,
LayerType,
Map,
MapContext,
output_maplibregl,
render_maplibregl,
)
from maplibre import (Layer, LayerType, Map, MapContext, output_maplibregl,
render_maplibregl)
from maplibre.basemaps import Carto
from maplibre.experimental import LineLayer
from shiny import App, reactive, render, ui

LAYER_ID = "counties"
LAYER_ID_LINE = "us-states-line"
Expand Down Expand Up @@ -103,3 +96,4 @@ async def color():

if __name__ == "__main__":
app.run()
un()
10 changes: 8 additions & 2 deletions .examples/experimental/flights.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

import pandas as pd
import shapely
from maplibre import (Layer, LayerType, Map, MapContext, output_maplibregl,
render_maplibregl)
from maplibre import (
Layer,
LayerType,
Map,
MapContext,
output_maplibregl,
render_maplibregl,
)
from maplibre.basemaps import Carto
from maplibre.utils import GeometryType, df_to_geojson
from shiny import App, reactive, ui
Expand Down
13 changes: 3 additions & 10 deletions .examples/h3_hexagons/app.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import h3
import pandas as pd
from shiny import App, reactive, ui

# import shapely
from maplibre import (
Layer,
LayerType,
Map,
MapContext,
output_maplibregl,
render_maplibregl,
)
from maplibre import (Layer, LayerType, Map, MapContext, output_maplibregl,
render_maplibregl)
from maplibre.basemaps import Carto
from maplibre.utils import GeometryType, df_to_geojson, get_bounds
from shiny import App, reactive, ui

LAYER_ID = "motor_vehicle_collisions"

Expand Down
2 changes: 1 addition & 1 deletion .examples/motor_vehicle_collisions/app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import h3
import pandas as pd
from shiny import App, reactive, ui

# import shapely
from maplibre import (
Expand All @@ -13,6 +12,7 @@
)
from maplibre.basemaps import Carto
from maplibre.utils import GeometryType, df_to_geojson, get_bounds
from shiny import App, reactive, ui

LAYER_ID = "motor_vehicle_collisions"

Expand Down
3 changes: 1 addition & 2 deletions .examples/text_layer/app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from maplibre import (Layer, LayerType, Map, output_maplibregl,
render_maplibregl)
from maplibre import Layer, LayerType, Map, output_maplibregl, render_maplibregl
from maplibre.basemaps import Carto
from shiny import App, reactive, render, ui

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog for MapLibre for Python

## maplibre v0.1.3

* Display all properties in popup and tooltip if `prop = None` (#26)
* Support [mustache](https://github.com/janl/mustache.js) templates for popups and tooltips (#27)

## maplibre v0.1.2

* Add `Map.set_data`
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ poetry install

poetry run pytest

poetry run pytest --doctest-modules maplibre
poetry run pytest --ignore=maplibre/ipywidget.py --doctest-modules maplibre
```

### JavaScript
Expand Down
6 changes: 6 additions & 0 deletions build-docs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
set -e

cp CHANGELOG.md docs/changelog.md

poetry run mkdocs build
19 changes: 19 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Changelog for MapLibre for Python

## maplibre v0.1.3

* Display all properties in popup and tooltip if `prop = None` (#26)
* Support [mustache](https://github.com/janl/mustache.js) templates for popups and tooltips (#27)

## maplibre v0.1.2

* Add `Map.set_data`
* Add `Map.set_visibility`
* Do not import `ipywidget.MapWidget` in `__init__` and skip tests for `MapWidget`, because it causes a `core dumped` error, see [anywidget issue](https://github.com/manzt/anywidget/issues/374)
* Remove `requests` dependency
* Remove dead code
* Add more examples

## maplibre v0.1.1

* Initial PyPI release
4 changes: 3 additions & 1 deletion docs/examples/3d_indoor_mapping/index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<a href="app.html" target="_blank">See example in action</a>
<!-- <a href="app.html" target="_blank">See example in action</a> -->

<iframe src="app.html" height="620px", width="100%" style="border:none;"></iframe>

```python
-8<-- "3d_indoor_mapping/app.py"
Expand Down
167 changes: 167 additions & 0 deletions docs/examples/airports/app.html

Large diffs are not rendered by default.

39 changes: 25 additions & 14 deletions docs/examples/airports/app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import sys

import pandas as pd
from maplibre import (
Layer,
Expand Down Expand Up @@ -64,6 +66,23 @@ def get_color(airport_type: str) -> str:

popup_options = PopupOptions(close_button=False)


def create_map() -> Map:
m = Map(map_options)
m.add_layer(airport_circles)
for _, r in airports_data.iterrows():
marker = Marker(
lng_lat=r["coordinates"],
options=MarkerOptions(color=get_color(r["type"])),
popup=Popup(
text=r["name"],
options=popup_options,
),
)
m.add_marker(marker)
return m


app_ui = ui.page_fluid(
ui.panel_title("Airports"),
output_maplibregl("maplibre", height=600),
Expand All @@ -73,22 +92,14 @@ def get_color(airport_type: str) -> str:
def server(input, output, session):
@render_maplibregl
def maplibre():
m = Map(map_options)
for _, r in airports_data.iterrows():
marker = Marker(
lng_lat=r["coordinates"],
options=MarkerOptions(color=get_color(r["type"])),
popup=Popup(
text=r["name"],
options=popup_options,
),
)
m.add_marker(marker)
m.add_layer(airport_circles)
return m
return create_map()


app = App(app_ui, server)

if __name__ == "__main__":
app.run()
if len(sys.argv) == 2:
with open(sys.argv[1], "w") as f:
f.write(create_map().to_html())
else:
app.run()
2 changes: 2 additions & 0 deletions docs/examples/airports/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<iframe src="app.html" height="620px", width="100%" style="border:none;"></iframe>

```python
-8<-- "airports/app.py"
```
Expand Down
6 changes: 4 additions & 2 deletions docs/examples/custom_basemap/index.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<!-- <a href="app.html" target="_blank">See example in action</a> -->

<iframe src="app.html" height="620px", width="100%" style="border:none;"></iframe>

```python
-8<-- "custom_basemap/app.py"
```

<a href="app.html" target="_blank">See example in action</a>

Run example:

``` bash
Expand Down
167 changes: 167 additions & 0 deletions docs/examples/earthquake_clusters/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>Pymaplibregl</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css"/>
<body>
<div id="pymaplibregl" style="height:600px;"></div>
<script>
(() => {
// srcjs/pymaplibregl.js
var PyMapLibreGL = class {
constructor(mapOptions) {
this._id = mapOptions.container;
this._map = new maplibregl.Map(mapOptions);
this._map.on("mouseover", () => {
this._map.getCanvas().style.cursor = "pointer";
});
this._map.on("mouseout", () => {
this._map.getCanvas().style.cursor = "";
});
this._map.addControl(new maplibregl.NavigationControl());
}
getMap() {
return this._map;
}
applyMapMethod(name, params) {
this._map[name](...params);
}
addControl(type, options, position) {
this._map.addControl(new maplibregl[type](options), position);
}
addMarker({ lngLat, popup, options }) {
const marker = new maplibregl.Marker(options).setLngLat(lngLat);
if (popup) {
const popup_ = new maplibregl.Popup(popup.options).setHTML(popup.text);
marker.setPopup(popup_);
}
marker.addTo(this._map);
}
addLayer(layer) {
this._map.addLayer(layer);
if (typeof Shiny !== "undefined") {
this._map.on("click", layer.id, (e) => {
console.log(e, e.features[0]);
const layerId_ = layer.id.replaceAll("-", "_");
const inputName = `${this._id}_layer_${layerId_}`;
const feature = {
props: e.features[0].properties,
layer_id: layer.id
};
console.log(inputName, feature);
Shiny.onInputChange(inputName, feature);
});
}
}
addPopup(layerId, property) {
const popupOptions = {
closeButton: false
};
const popup = new maplibregl.Popup(popupOptions);
this._map.on("click", layerId, (e) => {
const feature = e.features[0];
const text = feature.properties[property];
popup.setLngLat(e.lngLat).setHTML(text).addTo(this._map);
});
}
addTooltip(layerId, property) {
const popupOptions = {
closeButton: false,
closeOnClick: false
};
const popup = new maplibregl.Popup(popupOptions);
this._map.on("mousemove", layerId, (e) => {
const feature = e.features[0];
const text = feature.properties[property];
popup.setLngLat(e.lngLat).setHTML(text).addTo(this._map);
});
this._map.on("mouseleave", layerId, () => {
popup.remove();
});
}
setSourceData(sourceId, data) {
this._map.getSource(sourceId).setData(data);
}
render(calls) {
calls.forEach(([name, params]) => {
if ([
"addLayer",
"addPopup",
"addTooltip",
"addMarker",
"addPopup",
"addControl",
"setSourceData"
].includes(name)) {
console.log("Custom method", name, params);
this[name](...params);
return;
}
console.log("Map method", name);
this.applyMapMethod(name, params);
});
}
};

// srcjs/index.js
var version = "0.1.0";
console.log("pymaplibregl", version);
if (typeof Shiny === "undefined") {
window.pymaplibregl = function({ mapOptions, calls }) {
const id = "pymaplibregl";
const container = document.getElementById(id);
const pyMapLibreGL = new PyMapLibreGL(
Object.assign({ container: container.id }, mapOptions)
);
const map = pyMapLibreGL.getMap();
map.on("load", () => {
pyMapLibreGL.render(calls);
});
};
}
if (typeof Shiny !== "undefined") {
class MapLibreGLOutputBinding extends Shiny.OutputBinding {
find(scope) {
return scope.find(".shiny-maplibregl-output");
}
renderValue(el, payload) {
console.log("id:", el.id, "payload:", payload);
const pyMapLibreGL = new PyMapLibreGL(
Object.assign({ container: el.id }, payload.mapData.mapOptions)
);
const map = pyMapLibreGL.getMap();
map.on("load", () => {
pyMapLibreGL.render(payload.mapData.calls);
});
map.on("click", (e) => {
console.log(e);
const inputName = `${el.id}`;
const data = { coords: e.lngLat, point: e.point };
console.log(inputName, data);
Shiny.onInputChange(inputName, data);
});
const messageHandlerName = `pymaplibregl-${el.id}`;
console.log(messageHandlerName);
Shiny.addCustomMessageHandler(messageHandlerName, ({ id, calls }) => {
console.log(id, calls);
pyMapLibreGL.render(calls);
});
}
}
Shiny.outputBindings.register(
new MapLibreGLOutputBinding(),
"shiny-maplibregl-output"
);
}
})();

// ...
(() => {
var data = {"mapOptions": {"center": [-118.0931, 33.78615], "hash": true, "style": "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json", "zoom": 3}, "calls": [["addSource", ["earthquakes", {"data": "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson", "cluster": true, "clusterMaxZoom": 14, "clusterMinPoints": 2, "clusterProperties": {"maxMag": ["max", ["get", "mag"]], "minMag": ["min", ["get", "mag"]]}, "clusterRadius": 50, "type": "geojson"}]], ["addLayer", [{"id": "earthquake-clusters", "type": "circle", "filter": ["has", "point_count"], "paint": {"circle-color": ["step", ["get", "point_count"], "#51bbd6", 100, "#f1f075", 750, "#f28cb1"], "circle-radius": ["step", ["get", "point_count"], 20, 100, 30, 750, 40]}, "source": "earthquakes"}]], ["addLayer", [{"id": "earthquake-circles", "type": "circle", "filter": ["!", ["has", "point_count"]], "paint": {"circle-color": "darkblue"}, "source": "earthquakes"}]], ["addTooltip", ["earthquake-clusters", "maxMag"]], ["addLayer", [{"id": "text", "type": "symbol", "filter": ["has", "point_count"], "layout": {"text-field": ["get", "point_count_abbreviated"], "text-size": 12}, "source": "earthquakes"}]]]};
pymaplibregl(data);
})();
</script>
</body>
</html>
Loading
Loading