diff --git a/examples/earthquake_clusters/app.html b/examples/earthquake_clusters/app.html new file mode 100644 index 00000000..d550851d --- /dev/null +++ b/examples/earthquake_clusters/app.html @@ -0,0 +1,167 @@ + + + +
from maplibre import (
- Layer,
- LayerType,
- Map,
- MapOptions,
- output_maplibregl,
- render_maplibregl,
-)
-from maplibre.basemaps import Carto
-from maplibre.sources import GeoJSONSource
-from shiny import App, reactive, ui
-
-EARTHQUAKE_SOURCE = "earthquakes"
-EARTHQUAKE_CIRCLES = "earthquake-circles"
-EARTHQUAKE_CLUSTERS = "earthquake-clusters"
-EARTHQUAKE_LABELS = "earthquake-labels"
-
-CENTER = (-118.0931, 33.78615)
+
+
+import sys
+
+from maplibre import (
+ Layer,
+ LayerType,
+ Map,
+ MapOptions,
+ output_maplibregl,
+ render_maplibregl,
+)
+from maplibre.basemaps import Carto
+from maplibre.sources import GeoJSONSource
+from shiny import App, reactive, ui
+
+EARTHQUAKE_SOURCE = "earthquakes"
+EARTHQUAKE_CIRCLES = "earthquake-circles"
+EARTHQUAKE_CLUSTERS = "earthquake-clusters"
+EARTHQUAKE_LABELS = "earthquake-labels"
-earthquakes_source = GeoJSONSource(
- data="https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
- cluster=True,
- cluster_radius=50,
- cluster_min_points=2,
- cluster_max_zoom=14,
- cluster_properties={
- "maxMag": ["max", ["get", "mag"]],
- "minMag": ["min", ["get", "mag"]],
- },
-)
-
-earthquake_circles = Layer(
- type=LayerType.CIRCLE,
- id=EARTHQUAKE_CIRCLES,
- source=EARTHQUAKE_SOURCE,
- paint={"circle-color": "darkblue"},
- filter=["!", ["has", "point_count"]],
-)
-
-earthquake_clusters = Layer(
- type=LayerType.CIRCLE,
- id=EARTHQUAKE_CLUSTERS,
- source=EARTHQUAKE_SOURCE,
- 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],
- },
-)
-
-earthquake_labels = Layer(
- type=LayerType.SYMBOL,
- id="text",
- source=EARTHQUAKE_SOURCE,
- filter=["has", "point_count"],
- layout={
- "text-field": ["get", "point_count_abbreviated"],
- "text-size": 12,
- },
-)
-
-map_options = MapOptions(style=Carto.POSITRON, center=CENTER, zoom=3, hash=True)
+CENTER = (-118.0931, 33.78615)
+
+earthquakes_source = GeoJSONSource(
+ data="https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
+ cluster=True,
+ cluster_radius=50,
+ cluster_min_points=2,
+ cluster_max_zoom=14,
+ cluster_properties={
+ "maxMag": ["max", ["get", "mag"]],
+ "minMag": ["min", ["get", "mag"]],
+ },
+)
+
+earthquake_circles = Layer(
+ type=LayerType.CIRCLE,
+ id=EARTHQUAKE_CIRCLES,
+ source=EARTHQUAKE_SOURCE,
+ paint={"circle-color": "darkblue"},
+ filter=["!", ["has", "point_count"]],
+)
+
+earthquake_clusters = Layer(
+ type=LayerType.CIRCLE,
+ id=EARTHQUAKE_CLUSTERS,
+ source=EARTHQUAKE_SOURCE,
+ 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],
+ },
+)
+
+earthquake_labels = Layer(
+ type=LayerType.SYMBOL,
+ id="text",
+ source=EARTHQUAKE_SOURCE,
+ filter=["has", "point_count"],
+ layout={
+ "text-field": ["get", "point_count_abbreviated"],
+ "text-size": 12,
+ },
+)
-app_ui = ui.page_fluid(
- ui.panel_title("Earthquakes Cluster"),
- output_maplibregl("maplibre", height=500),
-)
-
-
-def server(input, output, session):
- @render_maplibregl
- def maplibre():
- m = Map(map_options)
- m.add_source(EARTHQUAKE_SOURCE, earthquakes_source)
- m.add_layer(earthquake_clusters)
- m.add_layer(earthquake_circles)
- m.add_tooltip(EARTHQUAKE_CLUSTERS, "maxMag")
- m.add_layer(earthquake_labels)
- return m
-
- @reactive.Effect
- @reactive.event(input.maplibre)
- async def result():
- print(f"result: {input.maplibre()}")
-
-
-app = App(app_ui, server)
-
-if __name__ == "__main__":
- app.run()
+map_options = MapOptions(style=Carto.POSITRON, center=CENTER, zoom=3, hash=True)
+
+
+def create_map() -> Map:
+ m = Map(map_options)
+ m.add_source(EARTHQUAKE_SOURCE, earthquakes_source)
+ m.add_layer(earthquake_clusters)
+ m.add_layer(earthquake_circles)
+ m.add_tooltip(EARTHQUAKE_CLUSTERS, "maxMag")
+ m.add_layer(earthquake_labels)
+ return m
+
+
+app_ui = ui.page_fluid(
+ ui.panel_title("Earthquakes Cluster"),
+ output_maplibregl("maplibre", height=500),
+)
+
+
+def server(input, output, session):
+ @render_maplibregl
+ def maplibre():
+ return create_map()
+
+ @reactive.Effect
+ @reactive.event(input.maplibre)
+ async def result():
+ print(f"result: {input.maplibre()}")
+
+
+app = App(app_ui, server)
+
+if __name__ == "__main__":
+ if len(sys.argv) == 2:
+ file_name = sys.argv[1]
+ with open(file_name, "w") as f:
+ f.write(create_map().to_html())
+ else:
+ app.run()
Run example:
poetry run uvicorn docs.examples.earthquake_clusters.app:app --reload
diff --git a/search/search_index.json b/search/search_index.json
index b259c6c0..e7df2a13 100644
--- a/search/search_index.json
+++ b/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"MapLibre for Python","text":"MapLibre for Python provides Python bindings for MapLibre GL JS.
It integrates seamlessly into Shiny for Python and Jupyter.
"},{"location":"#installation","title":"Installation","text":"# Stable\npip install maplibre\n\npip install \"maplibre[all]\"\n\n# Dev\npip install git+https://github.com/eodaGmbH/py-maplibregl@dev\n
"},{"location":"#basic-usage","title":"Basic usage","text":""},{"location":"#standalone","title":"Standalone","text":"import webbrowser\n\nfrom maplibre import Layer, LayerType, Map, MapOptions\nfrom maplibre.sources import GeoJSONSource\n\nvancouver_blocks = GeoJSONSource(\n data=\"https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/geojson/vancouver-blocks.json\",\n)\n\nmap_options = MapOptions(\n center=(-123.1256, 49.24658),\n zoom=12,\n hash=True,\n pitch=35,\n)\n\nm = Map(map_options)\nm.add_layer(\n Layer(\n type=LayerType.LINE,\n source=vancouver_blocks,\n paint={\"line-color\": \"white\"},\n )\n)\n\ntemp_file = \"/tmp/pymaplibregl.html\"\n\nwith open(temp_file, \"w\") as f:\n f.write(m.to_html(style=\"height: 800px;\"))\n\nwebbrowser.open(temp_file)\n
"},{"location":"#shiny-integration","title":"Shiny integration","text":"from maplibre import Map, MapContext, output_maplibregl, render_maplibregl\nfrom maplibre.controls import Marker\nfrom shiny import App, reactive, ui\n\napp_ui = ui.page_fluid(\n output_maplibregl(\"maplibre\", height=600),\n ui.div(\"Click on map to set a marker\"),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map()\n return m\n\n @reactive.Effect\n @reactive.event(input.maplibre)\n async def coords():\n async with MapContext(\"maplibre\") as m:\n print(input.maplibre())\n lng_lat = tuple(input.maplibre()[\"coords\"].values())\n marker = Marker(lng_lat=lng_lat)\n m.add_marker(marker)\n m.add_call(\"flyTo\", {\"center\": lng_lat})\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n app.run()\n
"},{"location":"#jupyter-widget","title":"Jupyter widget","text":"from maplibre.ipywidget import MapWidget as Map\n\nm = Map()\nm\n
"},{"location":"jupyter/","title":"Jupyter","text":"Use MapWidget
in your Juyper Notebook:
import ipywidgets as widgets\n\nfrom maplibre import Layer, LayerType\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.controls import ScaleControl, Marker\nfrom maplibre.ipywidget import MapWidget as Map\n\n# Create a source\nearthquakes = GeoJSONSource(\n data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\"\n)\n\n# Create a layer\nlayer_id = \"earthquakes\"\n\nearthquake_circles = Layer(\n type=LayerType.CIRCLE,\n id=layer_id,\n source=earthquakes,\n paint={\"circle-color\": \"yellow\"}\n)\n\n# Render map\nm = Map()\nm.add_control(ScaleControl(), position=\"bottom-left\")\nm.add_layer(earthquake_circles)\nm.add_tooltip(layer_id, \"mag\")\nm.add_marker(Marker(lng_lat=(100.507, 13.745)))\nm\n\n# Change radius\nwidgets.interact(\n lambda radius: m.set_paint_property(layer_id, \"circle-radius\", radius),\n radius=5\n)\n\n# Change color\nwidgets.interact(\n lambda color: m.set_paint_property(layer_id, \"circle-color\", color),\n color=[\"green\", \"yellow\", \"orange\", \"red\"]\n)\n\n# Set filter on magnitude\nwidgets.interact(\n lambda mag_min: m.set_filter(layer_id, [\">=\", [\"get\", \"mag\"], mag_min]),\n mag_min=3\n)\n\n# Observe map-on-click event\nfrom IPython.display import clear_output\n\noutput = widgets.Output()\n\n\ndef log_lng_lat(lng_lat):\n with output:\n clear_output()\n print(lng_lat.new)\n\n\nm.observe(log_lng_lat, names=\"lng_lat\")\noutput\n
"},{"location":"layers/","title":"Layers","text":"The paint
and layout
properties for the layers depend on the type of the layer. They are passed as a dict
corresponding to the Layer Style Spec.
For example, to set the radius and the color for a circle layer, the paint
property looks like this:
paint = {\n \"circle-radius\": 5,\n \"circle-color\": \"yellow\"\n}\n
The value for any layout
property, paint
property, or filter
may also be specified as an expression. For details see Expressions.
For example, if the source of your layer has a color
property that contains the color of the feature, you can use the following expression:
paint = {\n \"circle-radius\": 5,\n \"circle-color\": [\"get\", \"color\"]\n}\n
A more complex expression where the color depends on the type
property of the layer's source might look like this:
paint={\n \"circle-color\": [\n \"match\",\n [\"get\", \"type\"],\n # darkred if type == \"mid\"\n \"mid\",\n \"darkred\",\n # darkgreen if type == \"major\"\n \"major\",\n \"darkgreen\",\n # else blue\n \"darkblue\",\n ]\n}\n
Filter features of a source according to its magnitude
property:
# Only show features where magnitude >= 5\nfilter = [\">=\", [\"get\", \"magnitude\"], 5]\n
"},{"location":"shiny/","title":"Shiny","text":""},{"location":"shiny/#input-and-output","title":"Input and output","text":"Use output_maplibregl
in the UI and render_maplibregl
in the server section of your Shiny for Python app:
from shiny import App, ui\nfrom maplibre import output_maplibregl, render_maplibregl, Map\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"MapLibre\"),\n output_maplibregl(\"maplibre\", height=600)\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map()\n return m\n\n\napp = App(app_ui, server)\n
"},{"location":"shiny/#reactivity","title":"Reactivity","text":""},{"location":"shiny/#input-events","title":"Input events","text":"MapLibre for Python provides the following reactive inputs:
map-on-click
event: Sends the coordinates of the location that was clicked on. The name of the input event corresponds to the output id. For output_maplibregl(\"maplibre\")
you need to listen to input.maplibre
. feature-on-click
event: Sends the properties of the feature that was clicked on. The name of the \u00ecnput is made up of the output id + layer
+ layer id. For output_maplibregl(\"maplibre\")
and a layer with id=test
you need to listen to input.maplibre_layer_test
.
"},{"location":"shiny/#map-updates","title":"Map updates","text":"Use MapContext
to update your Map
object.
"},{"location":"shiny/#example","title":"Example","text":"from maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.sources import GeoJSONSource\nfrom shiny import App, reactive, render, ui\n\nLAYER_ID = \"earthquakes\"\nCIRCLE_RADIUS = 5\n\napp_ui = ui.page_fluid(\n #\n # Render map\n #\n ui.panel_title(\"MapLibre\"),\n output_maplibregl(\"maplibre\", height=600),\n #\n # Show coords\n #\n ui.div(\"Click on the map to print the coords.\", style=\"padding: 10px;\"),\n ui.output_text_verbatim(\"coords\", placeholder=True),\n #\n # Show props of a feature\n #\n ui.div(\"Click on a feature to print its props.\", style=\"padding: 10px;\"),\n ui.output_text_verbatim(\"props\", placeholder=True),\n #\n # Change radius\n #\n ui.input_slider(\"radius\", \"Radius\", value=CIRCLE_RADIUS, min=1, max=10),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map(zoom=3)\n m.add_layer(\n Layer(\n type=LayerType.CIRCLE,\n id=LAYER_ID,\n source=GeoJSONSource(\n data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\"\n ),\n paint={\"circle-color\": \"yellow\"},\n )\n )\n return m\n\n @render.text\n def coords():\n return str(input.maplibre())\n\n @render.text\n def props():\n return str(input.maplibre_layer_earthquakes())\n\n @reactive.Effect\n @reactive.event(input.radius)\n async def radius():\n async with MapContext(\"maplibre\") as m:\n m.set_paint_property(LAYER_ID, \"circle-radius\", input.radius())\n\n\napp = App(app_ui, server)\n
Run this example:
poetry run uvicorn docs.examples.getting_started.reactivity:app --reload\n
"},{"location":"api/basemaps/","title":"Basemaps","text":""},{"location":"api/basemaps/#maplibre.basemaps.Carto","title":"maplibre.basemaps.Carto
","text":" Bases: Enum
Carto basemap styles
Attributes:
-
DARK_MATTER
\u2013 dark-matter
-
POSITRON
\u2013 positron
-
VOYAGER
\u2013 voyager
-
POSITRON_NOLABELS
\u2013 positron-nolabels
-
DARK_MATTER_NOLABELS
\u2013 dark-matter-nolabels
-
VOYAGER_NOLABELS
\u2013 voyager-nolabels
Examples:
>>> from maplibre import Map, MapOptions\n>>> from maplibre.basemaps import Carto\n
>>> map = Map(MapOptions(style=Carto.DARK_MATTER))\n
Source code in maplibre/basemaps.py
class Carto(Enum):\n \"\"\"Carto basemap styles\n\n Attributes:\n DARK_MATTER: dark-matter\n POSITRON: positron\n VOYAGER: voyager\n POSITRON_NOLABELS: positron-nolabels\n DARK_MATTER_NOLABELS: dark-matter-nolabels\n VOYAGER_NOLABELS: voyager-nolabels\n\n Examples:\n >>> from maplibre import Map, MapOptions\n >>> from maplibre.basemaps import Carto\n\n >>> map = Map(MapOptions(style=Carto.DARK_MATTER))\n \"\"\"\n\n DARK_MATTER = \"dark-matter\"\n POSITRON = \"positron\"\n VOYAGER = \"voyager\"\n POSITRON_NOLABELS = \"positron-nolabels\"\n DARK_MATTER_NOLABELS = \"dark-matter-nolabels\"\n VOYAGER_NOLABELS = \"voyager-nolabels\"\n
"},{"location":"api/basemaps/#maplibre.basemaps.construct_basemap_style","title":"maplibre.basemaps.construct_basemap_style(name='nice-style', sources={}, layers=[])
","text":"Construct a basemap style
Parameters:
Name Type Description Default name
str
The name of the basemap style.
'nice-style'
sources
dict
The sources to be used for the basemap style.
{}
layers
list
The layers to be used for the basemap style.
[]
Source code in maplibre/basemaps.py
def construct_basemap_style(\n name: str = \"nice-style\", sources: dict = {}, layers: list = []\n) -> dict:\n \"\"\"Construct a basemap style\n\n Args:\n name (str): The name of the basemap style.\n sources (dict): The sources to be used for the basemap style.\n layers (list): The layers to be used for the basemap style.\n \"\"\"\n layers = [\n layer.to_dict() if isinstance(layer, Layer) else layer for layer in layers\n ]\n return {\"name\": name, \"version\": 8, \"sources\": sources, \"layers\": layers}\n
"},{"location":"api/controls/","title":"Markers and controls","text":""},{"location":"api/controls/#maplibre.controls.Popup","title":"maplibre.controls.Popup
","text":" Bases: BaseModel
Popup
Attributes:
Name Type Description text
str
The Text of the popup.
options
PopupOptions | dict
Popup options.
Source code in maplibre/controls.py
class Popup(BaseModel):\n \"\"\"Popup\n\n Attributes:\n text: The Text of the popup.\n options (PopupOptions | dict): Popup options.\n \"\"\"\n\n text: str\n options: Union[PopupOptions, dict] = {}\n
"},{"location":"api/controls/#maplibre.controls.PopupOptions","title":"maplibre.controls.PopupOptions
","text":" Bases: BaseModel
Popup options
Source code in maplibre/controls.py
class PopupOptions(BaseModel):\n \"\"\"Popup options\"\"\"\n\n anchor: str = None\n close_button: bool = Field(False, serialization_alias=\"closeButton\")\n close_on_click: bool = Field(None, serialization_alias=\"closeOnClick\")\n close_on_move: bool = Field(None, serialization_alias=\"closeOnMove\")\n max_width: int = Field(None, serialization_alias=\"maxWidth\")\n offset: Union[int, list, dict] = None\n
"},{"location":"api/controls/#maplibre.controls.Marker","title":"maplibre.controls.Marker
","text":" Bases: BaseModel
Marker
Attributes:
Name Type Description lng_lat
tuple | list
Required. The longitude and latitude of the marker.
popup
Popup | dict
The Popup that is displayed when a user clicks on the marker.
options
MarkerOptions | dict
Marker options.
Source code in maplibre/controls.py
class Marker(BaseModel):\n \"\"\"Marker\n\n Attributes:\n lng_lat (tuple |list): **Required.** The longitude and latitude of the marker.\n popup (Popup | dict): The Popup that is displayed when a user clicks on the marker.\n options (MarkerOptions | dict): Marker options.\n \"\"\"\n\n lng_lat: Union[tuple, list] = Field(None, serialization_alias=\"lngLat\")\n popup: Union[Popup, dict] = None\n options: Union[MarkerOptions, dict] = {}\n
"},{"location":"api/controls/#maplibre.controls.MarkerOptions","title":"maplibre.controls.MarkerOptions
","text":" Bases: BaseModel
Marker options
Source code in maplibre/controls.py
class MarkerOptions(BaseModel):\n \"\"\"Marker options\"\"\"\n\n anchor: str = None\n color: str = None\n draggable: bool = None\n offset: Union[tuple, list] = None\n pitch_alignment: str = Field(None, serialization_alias=\"pitchAlignment\")\n rotation: int = None\n rotation_alignment: str = Field(None, serialization_alias=\"rotationAlignment\")\n scale: int = None\n
"},{"location":"api/controls/#maplibre.controls.ControlPosition","title":"maplibre.controls.ControlPosition
","text":" Bases: Enum
Control position
Attributes:
-
TOP_LEFT
\u2013 top-left
-
TOP_RIGHT
\u2013 top-right
-
BOTTOM_LEFT
\u2013 bottom-left
-
BOTTOM_RIGHT
\u2013 bottom-right
Source code in maplibre/controls.py
class ControlPosition(Enum):\n \"\"\"Control position\n\n Attributes:\n TOP_LEFT: top-left\n TOP_RIGHT: top-right\n BOTTOM_LEFT: bottom-left\n BOTTOM_RIGHT: bottom-right\n \"\"\"\n\n TOP_LEFT = \"top-left\"\n TOP_RIGHT = \"top-right\"\n BOTTOM_LEFT = \"bottom-left\"\n BOTTOM_RIGHT = \"bottom-right\"\n
"},{"location":"api/controls/#maplibre.controls.FullscreenControl","title":"maplibre.controls.FullscreenControl
","text":" Bases: Control
Fullscreen control
Examples:
>>> from maplibre import Map\n>>> from maplibre.controls import FullscreenControl, ControlPosition\n
>>> map = Map()\n>>> map.add_control(FullscreenControl(), ControlPosition.BOTTOM_LEFT)\n
Source code in maplibre/controls.py
class FullscreenControl(Control):\n \"\"\"Fullscreen control\n\n Examples:\n >>> from maplibre import Map\n >>> from maplibre.controls import FullscreenControl, ControlPosition\n\n >>> map = Map()\n >>> map.add_control(FullscreenControl(), ControlPosition.BOTTOM_LEFT)\n \"\"\"\n\n # _name: str = ControlType.FULLSCREEN.value\n pass\n
"},{"location":"api/controls/#maplibre.controls.ScaleControl","title":"maplibre.controls.ScaleControl
","text":" Bases: Control
Scale control
Source code in maplibre/controls.py
class ScaleControl(Control):\n \"\"\"Scale control\"\"\"\n\n # _name: str = ControlType.SCALE.value\n max_width: int = Field(None, serialization_alias=\"maxWidth\")\n unit: Literal[\"imperial\", \"metric\", \"nautical\"] = \"metric\"\n
"},{"location":"api/controls/#maplibre.controls.NavigationControl","title":"maplibre.controls.NavigationControl
","text":" Bases: Control
Navigation control
Source code in maplibre/controls.py
class NavigationControl(Control):\n \"\"\"Navigation control\"\"\"\n\n # _name: str = ControlType.NAVIGATION.value\n show_compass: bool = Field(True, serialization_alias=\"showCompass\")\n show_zoom: bool = Field(True, serialization_alias=\"showZoom\")\n visualize_pitch: bool = Field(False, serialization_alias=\"visualizePitch\")\n
"},{"location":"api/controls/#maplibre.controls.GeolocateControl","title":"maplibre.controls.GeolocateControl
","text":" Bases: Control
Geolocate control
Source code in maplibre/controls.py
class GeolocateControl(Control):\n \"\"\"Geolocate control\"\"\"\n\n # _name: str = ControlType.GEOLOCATE.value\n position_options: dict = Field(None, serialization_alias=\"positionOptions\")\n show_accuracy_circle: bool = Field(True, serialization_alias=\"showAccuracyCircle\")\n show_user_heading: bool = Field(False, serialization_alias=\"showUserHeading\")\n show_user_location: bool = Field(True, serialization_alias=\"showUserLocation\")\n track_user_location: bool = Field(False, serialization_alias=\"trackUserLocation\")\n
"},{"location":"api/layer/","title":"Layer","text":""},{"location":"api/layer/#maplibre.Layer","title":"maplibre.Layer
","text":" Bases: BaseModel
Layer properties
Notes See layers for more details on the paint
and layout
properties of the layers.
Attributes:
Name Type Description id
str
Required. The unique ID of the layer. Defaults to str(uuid4())
.
type
str | LayerType
Required. The type of the layer.
filter
list
The filter expression that is applied to the source of the layer.
layout
dict
The layout properties of the layer.
max_zoom
int
The maximum zoom level for the layer.
min_zoom
int
The minimum zoom level for the layer.
paint
dict
The paint properties of the layer.
source
str | Source
The name (unique ID) of a source or a source object to be used for the layer.
source_layer
str
The layer to use from a vector tile source.
Examples:
>>> from maplibre.layer import Layer, LayerType\n
>>> layer = Layer(id=\"test-layer\", type=LayerType.CIRCLE, source=\"test-source\")\n
Source code in maplibre/layer.py
class Layer(BaseModel):\n \"\"\"Layer properties\n\n Notes:\n See [layers](https://maplibre.org/maplibre-style-spec/layers/) for more details on the\n `paint` and `layout` properties of the layers.\n\n Attributes:\n id (str): **Required.** The unique ID of the layer. Defaults to `str(uuid4())`.\n type (str | LayerType): **Required.** The type of the layer.\n filter (list): The filter expression that is applied to the source of the layer.\n layout (dict): The layout properties of the layer.\n max_zoom (int): The maximum zoom level for the layer.\n min_zoom (int): The minimum zoom level for the layer.\n paint (dict): The paint properties of the layer.\n source (str | Source): The name (unique ID) of a source or a source object to be used for the layer.\n source_layer (str): The layer to use from a vector tile source.\n\n Examples:\n >>> from maplibre.layer import Layer, LayerType\n\n >>> layer = Layer(id=\"test-layer\", type=LayerType.CIRCLE, source=\"test-source\")\n \"\"\"\n\n id: str = Field(default_factory=lambda: str(uuid4()))\n type: LayerType\n filter: list = None\n layout: dict = None\n max_zoom: int = Field(None, serialization_alias=\"maxzoom\")\n metadata: dict = None\n min_zoom: int = Field(None, serialization_alias=\"minzoom\")\n paint: dict = None\n source: Union[str, Source, dict, None] = None\n source_layer: str = Field(None, serialization_alias=\"source-layer\")\n\n @field_validator(\"source\")\n def validate_source(cls, v):\n if isinstance(v, Source):\n return v.to_dict()\n\n return v\n\n @field_validator(\"paint\", \"layout\")\n def fix_paint(cls, v):\n if isinstance(v, dict):\n return fix_keys(v)\n\n return v\n
"},{"location":"api/layer/#maplibre.LayerType","title":"maplibre.LayerType
","text":" Bases: Enum
Rendering type of layer
Attributes:
-
CIRCLE
\u2013 A filled circle.
-
FILL
\u2013 A filled polygon with an optional stroked border.
-
FILL_EXTRUSION
\u2013 An extruded polygon.
-
LINE
\u2013 A stroked line.
-
SYMBOL
\u2013 An icon or a text label.
-
RASTER
\u2013 Raster map textures such as satellite imagery.
-
HEATMAP
\u2013 A heatmap.
-
HILLSHADE
\u2013 A Client-side hillshading visualization based on DEM data.
-
BACKGROUND
\u2013 A background color or pattern.
Source code in maplibre/layer.py
class LayerType(Enum):\n \"\"\"Rendering type of layer\n\n Attributes:\n CIRCLE: A filled circle.\n FILL: A filled polygon with an optional stroked border.\n FILL_EXTRUSION: An extruded polygon.\n LINE: A stroked line.\n SYMBOL: An icon or a text label.\n RASTER: Raster map textures such as satellite imagery.\n HEATMAP: A heatmap.\n HILLSHADE: A Client-side hillshading visualization based on DEM data.\n BACKGROUND: A background color or pattern.\n \"\"\"\n\n CIRCLE = \"circle\"\n FILL = \"fill\"\n FILL_EXTRUSION = \"fill-extrusion\"\n LINE = \"line\"\n SYMBOL = \"symbol\"\n RASTER = \"raster\"\n HEATMAP = \"heatmap\"\n HILLSHADE = \"hillshade\"\n BACKGROUND = \"background\"\n
"},{"location":"api/map/","title":"Map","text":""},{"location":"api/map/#maplibre.Map","title":"maplibre.Map
","text":" Bases: object
Map
Parameters:
Name Type Description Default map_options
MapOptions
Map options.
MapOptions()
**kwargs
Keyword arguments that are appended to the MapOptions
object.
{}
Examples:
>>> from maplibre.map import Map, MapOptions\n
>>> map_options = MapOptions(center=(9.5, 51.31667), zoom=8)\n>>> map = Map(map_options)\n>>> dict(map)\n{'mapOptions': {'center': (9.5, 51.31667), 'style': 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json', 'zoom': 8}, 'calls': []}\n
Source code in maplibre/map.py
class Map(object):\n \"\"\"Map\n\n Args:\n map_options (MapOptions): Map options.\n **kwargs: Keyword arguments that are appended to the `MapOptions` object.\n\n Examples:\n >>> from maplibre.map import Map, MapOptions\n\n >>> map_options = MapOptions(center=(9.5, 51.31667), zoom=8)\n >>> map = Map(map_options)\n >>> dict(map)\n {'mapOptions': {'center': (9.5, 51.31667), 'style': 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json', 'zoom': 8}, 'calls': []}\n \"\"\"\n\n MESSAGE = \"not implemented yet\"\n\n def __init__(self, map_options: MapOptions = MapOptions(), **kwargs):\n self.map_options = map_options.to_dict() | kwargs\n self._message_queue = []\n\n def __iter__(self):\n for k, v in self.to_dict().items():\n yield k, v\n\n def to_dict(self) -> dict:\n return {\"mapOptions\": self.map_options, \"calls\": self._message_queue}\n\n \"\"\"\n @property\n def sources(self) -> list:\n return [item[\"data\"] for item in self._calls if item[\"name\"] == \"addSource\"]\n\n @property\n def layers(self) -> list:\n return [item[\"data\"] for item in self._calls if item[\"name\"] == \"addLayer\"]\n \"\"\"\n\n # TODO: Rename to add_map_call\n def add_call_(self, func_name: str, params: list) -> None:\n self._message_queue.append(\n {\"name\": \"applyFunc\", \"data\": {\"funcName\": func_name, \"params\": params}}\n )\n\n def add_call(self, method_name: str, *args) -> None:\n \"\"\"Add a method call that is executed on the map instance\n\n Args:\n method_name (str): The name of the map method to be executed.\n *args (any): The arguments to be passed to the map method.\n \"\"\"\n # TODO: Pass as dict? {\"name\": method_name, \"args\": args}\n call = [method_name, args]\n self._message_queue.append(call)\n\n def add_control(\n self,\n control: Control,\n position: [str | ControlPosition] = ControlPosition.TOP_RIGHT,\n ) -> None:\n \"\"\"Add a control to the map\n\n Args:\n control (Control): The control to be added to the map.\n position (str | ControlPosition): The position of the control.\n \"\"\"\n self.add_call(\n \"addControl\",\n control.type,\n control.to_dict(),\n ControlPosition(position).value,\n )\n\n def add_source(self, id: str, source: [Source | dict]) -> None:\n \"\"\"Add a source to the map\"\"\"\n if isinstance(source, Source):\n source = source.to_dict()\n\n self.add_call(\"addSource\", id, source)\n\n def add_layer(self, layer: [Layer | dict]) -> None:\n \"\"\"Add a layer to the map\n\n Args:\n layer (Layer | dict): The Layer to be added to the map.\n \"\"\"\n if isinstance(layer, Layer):\n layer = layer.to_dict()\n\n self.add_call(\"addLayer\", layer)\n\n def add_marker(self, marker: Marker) -> None:\n \"\"\"Add a marker to the map\n\n Args:\n marker (Marker): The marker to be added to the map.\n \"\"\"\n self.add_call(\"addMarker\", marker.to_dict())\n\n def add_popup(self, layer_id: str, prop: str) -> None:\n \"\"\"Add a popup to the map\n\n Args:\n layer_id (str): The layer to which the popup is added.\n prop (str): The property of the source to be displayed.\n \"\"\"\n self.add_call(\"addPopup\", layer_id, prop)\n\n def add_tooltip(self, layer_id: str, prop: str) -> None:\n \"\"\"Add a tooltip to the map\n\n Args:\n layer_id (str): The layer to which the tooltip is added.\n prop (str): The property of the source to be displayed.\n \"\"\"\n self.add_call(\"addTooltip\", layer_id, prop)\n\n def set_filter(self, layer_id: str, filter_: list):\n \"\"\"Update the filter of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n filter_ (list): The filter expression that is applied to the source of the layer.\n \"\"\"\n self.add_call(\"setFilter\", layer_id, filter_)\n\n def set_paint_property(self, layer_id: str, prop: str, value: any) -> None:\n \"\"\"Update the paint property of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n prop (str): The name of the paint property to be updated.\n value (any): The new value of the paint property.\n \"\"\"\n self.add_call(\"setPaintProperty\", layer_id, prop, value)\n\n def set_layout_property(self, layer_id: str, prop: str, value: any) -> None:\n \"\"\"Update a layout property of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n prop (str): The name of the layout property to be updated.\n value (any): The new value of the layout property.\n \"\"\"\n self.add_call(\"setLayoutProperty\", layer_id, prop, value)\n\n def set_data(self, source_id: str, data: dict) -> None:\n \"\"\"Update the data of a GeoJSON source\n\n Args:\n source_id (str): The name of the source to be updated.\n data (dict): The data of the source.\n \"\"\"\n self.add_call(\"setSourceData\", source_id, data)\n\n def set_visibility(self, layer_id: str, visible: bool = True) -> None:\n \"\"\"Update the visibility of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n visible (bool): Whether the layer is visible or not.\n \"\"\"\n value = \"visible\" if visible else \"none\"\n self.add_call(\"setLayoutProperty\", layer_id, \"visibility\", value)\n\n def to_html(self, **kwargs) -> str:\n \"\"\"Render to html\n\n Args:\n **kwargs (Any): Additional keyword arguments that are passed to the template.\n Currently, `style` is the only supported keyword argument.\n\n Examples:\n >>> from maplibre import Map\n\n >>> map = Map()\n >>> with open(\"/tmp/map.html\", \"w\") as f:\n ... f.write(map.to_html(style=\"height: 800px;\") # doctest: +SKIP\n \"\"\"\n js_lib = read_internal_file(\"srcjs\", \"index.js\")\n js_snippet = Template(js_template).render(data=json.dumps(self.to_dict()))\n output = Template(html_template).render(\n js=\"\\n\".join([js_lib, js_snippet]), **kwargs\n )\n return output\n
"},{"location":"api/map/#maplibre.Map.add_call","title":"add_call(method_name, *args)
","text":"Add a method call that is executed on the map instance
Parameters:
Name Type Description Default method_name
str
The name of the map method to be executed.
required *args
any
The arguments to be passed to the map method.
()
Source code in maplibre/map.py
def add_call(self, method_name: str, *args) -> None:\n \"\"\"Add a method call that is executed on the map instance\n\n Args:\n method_name (str): The name of the map method to be executed.\n *args (any): The arguments to be passed to the map method.\n \"\"\"\n # TODO: Pass as dict? {\"name\": method_name, \"args\": args}\n call = [method_name, args]\n self._message_queue.append(call)\n
"},{"location":"api/map/#maplibre.Map.add_control","title":"add_control(control, position=ControlPosition.TOP_RIGHT)
","text":"Add a control to the map
Parameters:
Name Type Description Default control
Control
The control to be added to the map.
required position
str | ControlPosition
The position of the control.
TOP_RIGHT
Source code in maplibre/map.py
def add_control(\n self,\n control: Control,\n position: [str | ControlPosition] = ControlPosition.TOP_RIGHT,\n) -> None:\n \"\"\"Add a control to the map\n\n Args:\n control (Control): The control to be added to the map.\n position (str | ControlPosition): The position of the control.\n \"\"\"\n self.add_call(\n \"addControl\",\n control.type,\n control.to_dict(),\n ControlPosition(position).value,\n )\n
"},{"location":"api/map/#maplibre.Map.add_layer","title":"add_layer(layer)
","text":"Add a layer to the map
Parameters:
Name Type Description Default layer
Layer | dict
The Layer to be added to the map.
required Source code in maplibre/map.py
def add_layer(self, layer: [Layer | dict]) -> None:\n \"\"\"Add a layer to the map\n\n Args:\n layer (Layer | dict): The Layer to be added to the map.\n \"\"\"\n if isinstance(layer, Layer):\n layer = layer.to_dict()\n\n self.add_call(\"addLayer\", layer)\n
"},{"location":"api/map/#maplibre.Map.add_marker","title":"add_marker(marker)
","text":"Add a marker to the map
Parameters:
Name Type Description Default marker
Marker
The marker to be added to the map.
required Source code in maplibre/map.py
def add_marker(self, marker: Marker) -> None:\n \"\"\"Add a marker to the map\n\n Args:\n marker (Marker): The marker to be added to the map.\n \"\"\"\n self.add_call(\"addMarker\", marker.to_dict())\n
"},{"location":"api/map/#maplibre.Map.add_popup","title":"add_popup(layer_id, prop)
","text":"Add a popup to the map
Parameters:
Name Type Description Default layer_id
str
The layer to which the popup is added.
required prop
str
The property of the source to be displayed.
required Source code in maplibre/map.py
def add_popup(self, layer_id: str, prop: str) -> None:\n \"\"\"Add a popup to the map\n\n Args:\n layer_id (str): The layer to which the popup is added.\n prop (str): The property of the source to be displayed.\n \"\"\"\n self.add_call(\"addPopup\", layer_id, prop)\n
"},{"location":"api/map/#maplibre.Map.add_source","title":"add_source(id, source)
","text":"Add a source to the map
Source code in maplibre/map.py
def add_source(self, id: str, source: [Source | dict]) -> None:\n \"\"\"Add a source to the map\"\"\"\n if isinstance(source, Source):\n source = source.to_dict()\n\n self.add_call(\"addSource\", id, source)\n
"},{"location":"api/map/#maplibre.Map.add_tooltip","title":"add_tooltip(layer_id, prop)
","text":"Add a tooltip to the map
Parameters:
Name Type Description Default layer_id
str
The layer to which the tooltip is added.
required prop
str
The property of the source to be displayed.
required Source code in maplibre/map.py
def add_tooltip(self, layer_id: str, prop: str) -> None:\n \"\"\"Add a tooltip to the map\n\n Args:\n layer_id (str): The layer to which the tooltip is added.\n prop (str): The property of the source to be displayed.\n \"\"\"\n self.add_call(\"addTooltip\", layer_id, prop)\n
"},{"location":"api/map/#maplibre.Map.set_data","title":"set_data(source_id, data)
","text":"Update the data of a GeoJSON source
Parameters:
Name Type Description Default source_id
str
The name of the source to be updated.
required data
dict
The data of the source.
required Source code in maplibre/map.py
def set_data(self, source_id: str, data: dict) -> None:\n \"\"\"Update the data of a GeoJSON source\n\n Args:\n source_id (str): The name of the source to be updated.\n data (dict): The data of the source.\n \"\"\"\n self.add_call(\"setSourceData\", source_id, data)\n
"},{"location":"api/map/#maplibre.Map.set_filter","title":"set_filter(layer_id, filter_)
","text":"Update the filter of a layer
Parameters:
Name Type Description Default layer_id
str
The name of the layer to be updated.
required filter_
list
The filter expression that is applied to the source of the layer.
required Source code in maplibre/map.py
def set_filter(self, layer_id: str, filter_: list):\n \"\"\"Update the filter of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n filter_ (list): The filter expression that is applied to the source of the layer.\n \"\"\"\n self.add_call(\"setFilter\", layer_id, filter_)\n
"},{"location":"api/map/#maplibre.Map.set_layout_property","title":"set_layout_property(layer_id, prop, value)
","text":"Update a layout property of a layer
Parameters:
Name Type Description Default layer_id
str
The name of the layer to be updated.
required prop
str
The name of the layout property to be updated.
required value
any
The new value of the layout property.
required Source code in maplibre/map.py
def set_layout_property(self, layer_id: str, prop: str, value: any) -> None:\n \"\"\"Update a layout property of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n prop (str): The name of the layout property to be updated.\n value (any): The new value of the layout property.\n \"\"\"\n self.add_call(\"setLayoutProperty\", layer_id, prop, value)\n
"},{"location":"api/map/#maplibre.Map.set_paint_property","title":"set_paint_property(layer_id, prop, value)
","text":"Update the paint property of a layer
Parameters:
Name Type Description Default layer_id
str
The name of the layer to be updated.
required prop
str
The name of the paint property to be updated.
required value
any
The new value of the paint property.
required Source code in maplibre/map.py
def set_paint_property(self, layer_id: str, prop: str, value: any) -> None:\n \"\"\"Update the paint property of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n prop (str): The name of the paint property to be updated.\n value (any): The new value of the paint property.\n \"\"\"\n self.add_call(\"setPaintProperty\", layer_id, prop, value)\n
"},{"location":"api/map/#maplibre.Map.set_visibility","title":"set_visibility(layer_id, visible=True)
","text":"Update the visibility of a layer
Parameters:
Name Type Description Default layer_id
str
The name of the layer to be updated.
required visible
bool
Whether the layer is visible or not.
True
Source code in maplibre/map.py
def set_visibility(self, layer_id: str, visible: bool = True) -> None:\n \"\"\"Update the visibility of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n visible (bool): Whether the layer is visible or not.\n \"\"\"\n value = \"visible\" if visible else \"none\"\n self.add_call(\"setLayoutProperty\", layer_id, \"visibility\", value)\n
"},{"location":"api/map/#maplibre.Map.to_html","title":"to_html(**kwargs)
","text":"Render to html
Parameters:
Name Type Description Default **kwargs
Any
Additional keyword arguments that are passed to the template. Currently, style
is the only supported keyword argument.
{}
Examples:
>>> from maplibre import Map\n
>>> map = Map()\n>>> with open(\"/tmp/map.html\", \"w\") as f:\n... f.write(map.to_html(style=\"height: 800px;\")\n
Source code in maplibre/map.py
def to_html(self, **kwargs) -> str:\n \"\"\"Render to html\n\n Args:\n **kwargs (Any): Additional keyword arguments that are passed to the template.\n Currently, `style` is the only supported keyword argument.\n\n Examples:\n >>> from maplibre import Map\n\n >>> map = Map()\n >>> with open(\"/tmp/map.html\", \"w\") as f:\n ... f.write(map.to_html(style=\"height: 800px;\") # doctest: +SKIP\n \"\"\"\n js_lib = read_internal_file(\"srcjs\", \"index.js\")\n js_snippet = Template(js_template).render(data=json.dumps(self.to_dict()))\n output = Template(html_template).render(\n js=\"\\n\".join([js_lib, js_snippet]), **kwargs\n )\n return output\n
"},{"location":"api/map/#maplibre.MapOptions","title":"maplibre.MapOptions
","text":" Bases: BaseModel
Map options
Note See mapOptions for more details.
Source code in maplibre/map.py
class MapOptions(BaseModel):\n \"\"\"Map options\n\n Note:\n See [mapOptions](https://maplibre.org/maplibre-gl-js/docs/API/types/maplibregl.MapOptions/) for more details.\n \"\"\"\n\n model_config = ConfigDict(\n validate_assignment=True, extra=\"forbid\", use_enum_values=False\n )\n antialias: bool = None\n attribution_control: bool = Field(None, serialization_alias=\"attributionControl\")\n bearing: int = None\n bearing_snap: int = Field(None, serialization_alias=\"bearingSnap\")\n bounds: tuple = None\n box_zoom: bool = Field(None, serialization_alias=\"boxZoom\")\n center: tuple = None\n click_tolerance: int = Field(None, serialization_alias=\"clickTolerance\")\n custom_attribution: bool = Field(None, serialization_alias=\"customAttribution\")\n double_click_zoom: bool = Field(None, serialization_alias=\"doubleClickZoom\")\n fade_duration: int = Field(None, serialization_alias=\"fadeDuration\")\n fit_bounds_options: dict = Field(None, serialization_alias=\"fitBoundsOptions\")\n hash: Union[bool, str] = None\n interactive: bool = None\n keyword: bool = None\n max_bounds: tuple = Field(None, serialization_alias=\"maxBounds\")\n max_pitch: int = Field(None, serialization_alias=\"maxPitch\")\n max_zoom: int = Field(None, serialization_alias=\"maxZoom\")\n min_pitch: int = Field(None, serialization_alias=\"minPitch\")\n min_zoom: int = Field(None, serialization_alias=\"minZoom\")\n pitch: int = None\n scroll_zoom: bool = Field(None, serialization_alias=\"scrollZoom\")\n style: Union[str, Carto, dict] = construct_carto_basemap_url(Carto.DARK_MATTER)\n zoom: int = None\n\n @field_validator(\"style\")\n def validate_style(cls, v):\n if isinstance(v, Carto):\n return construct_carto_basemap_url(v)\n\n return v\n
"},{"location":"api/map/#maplibre.MapContext","title":"maplibre.MapContext
","text":" Bases: Map
MapContext
Use this class to update a Map
instance in a Shiny app. Must be used inside an async function.
See maplibre.Map
for available methods.
Parameters:
Name Type Description Default id
string
The id of the map to be updated.
required session
Session
A Shiny session. If None
, the active session is used.
None
Source code in maplibre/mapcontext.py
class MapContext(Map):\n \"\"\"MapContext\n\n Use this class to update a `Map` instance in a Shiny app.\n Must be used inside an async function.\n\n See `maplibre.Map` for available methods.\n\n Args:\n id (string): The id of the map to be updated.\n session (Session): A Shiny session.\n If `None`, the active session is used.\n \"\"\"\n\n def __init__(self, id: str, session: Session = None) -> None:\n self.id = id\n self._session = require_active_session(session)\n self.map_options = {}\n self._message_queue = []\n\n async def __aenter__(self):\n return self\n\n async def __aexit__(self, exc_type, exc_val, exc_tb):\n await self.render()\n\n async def render(self):\n await self._session.send_custom_message(\n f\"pymaplibregl-{self.id}\", {\"id\": self.id, \"calls\": self._message_queue}\n )\n
"},{"location":"api/map/#maplibre.ipywidget.MapWidget","title":"maplibre.ipywidget.MapWidget
","text":" Bases: AnyWidget
, Map
MapWidget
Use this class to display and update maps in Jupyter Notebooks.
See maplibre.Map
for available methods.
Examples:
>>> from maplibre import MapOptions\n>>> from maplibre.ipywidget import MapWidget as Map\n>>> m = Map(MapOptions(center=(-123.13, 49.254), zoom=11, pitch=45))\n>>> m\n
Source code in maplibre/ipywidget.py
class MapWidget(AnyWidget, Map):\n \"\"\"MapWidget\n\n Use this class to display and update maps in Jupyter Notebooks.\n\n See `maplibre.Map` for available methods.\n\n Examples:\n >>> from maplibre import MapOptions\n >>> from maplibre.ipywidget import MapWidget as Map\n >>> m = Map(MapOptions(center=(-123.13, 49.254), zoom=11, pitch=45))\n >>> m # doctest: +SKIP\n \"\"\"\n\n _esm = join(Path(__file__).parent, \"srcjs\", \"ipywidget.js\")\n _css = join(Path(__file__).parent, \"srcjs\", \"maplibre-gl.css\")\n _use_message_queue = False\n _rendered = traitlets.Bool(False, config=True).tag(sync=True)\n map_options = traitlets.Dict().tag(sync=True)\n calls = traitlets.List().tag(sync=True)\n height = traitlets.Union([traitlets.Int(), traitlets.Unicode()]).tag(sync=True)\n lng_lat = traitlets.Dict().tag(sync=True)\n\n def __init__(self, map_options=MapOptions(), **kwargs) -> None:\n self.calls = []\n AnyWidget.__init__(self, **kwargs)\n Map.__init__(self, map_options, **kwargs)\n\n @traitlets.default(\"height\")\n def _default_height(self):\n return \"400px\"\n\n @traitlets.validate(\"height\")\n def _validate_height(self, proposal):\n height = proposal[\"value\"]\n if isinstance(height, int):\n return f\"{height}px\"\n\n return height\n\n @traitlets.observe(\"_rendered\")\n def _on_rendered(self, change):\n self.send({\"calls\": self._message_queue, \"msg\": \"init\"})\n self._message_queue = []\n\n def use_message_queue(self, value: bool = True) -> None:\n self._use_message_queue = value\n\n def add_call(self, method_name: str, *args) -> None:\n call = [method_name, args]\n if not self._rendered:\n if not self._use_message_queue:\n self.calls = self.calls + [call]\n return\n\n self._message_queue.append(call)\n return\n\n self.send({\"calls\": [call], \"msg\": \"custom call\"})\n
"},{"location":"api/sources/","title":"Sources","text":""},{"location":"api/sources/#maplibre.sources","title":"maplibre.sources
","text":""},{"location":"api/sources/#maplibre.sources.GeoJSONSource","title":"GeoJSONSource
","text":" Bases: Source
GeoJSON Source
Examples:
>>> from maplibre.sources import GeoJSONSource\n
>>> source = GeoJSONSource(data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\")\n
Source code in maplibre/sources.py
class GeoJSONSource(Source):\n \"\"\"GeoJSON Source\n\n Examples:\n >>> from maplibre.sources import GeoJSONSource\n\n >>> source = GeoJSONSource(data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\")\n \"\"\"\n\n data: Union[str, dict]\n attribution: str = None\n buffer: int = None\n cluster: bool = None\n cluster_max_zoom: int = Field(None, serialization_alias=\"clusterMaxZoom\")\n cluster_min_points: int = Field(None, serialization_alias=\"clusterMinPoints\")\n cluster_properties: dict = Field(None, serialization_alias=\"clusterProperties\")\n cluster_radius: int = Field(None, serialization_alias=\"clusterRadius\")\n filter: list = None\n generate_id: bool = Field(None, serialization_alias=\"generateId\")\n line_metrics: bool = Field(None, serialization_alias=\"lineMetrics\")\n maxzoom: int = None\n promote_id: Union[str, dict] = Field(None, serialization_alias=\"promoteId\")\n tolerance: float = None\n\n @computed_field\n @property\n def type(self) -> str:\n return SourceType.GEOJSON.value\n
"},{"location":"api/sources/#maplibre.sources.RasterTileSource","title":"RasterTileSource
","text":" Bases: Source
Raster tile source
Examples:
>>> from maplibre.sources import RasterTileSource\n>>> raster_source = RasterTileSource(\n... tiles=[\"https://tile.openstreetmap.org/{z}/{x}/{y}.png\"],\n... tile_size=256,\n... min_zoom=0,\n... max_zoom=19,\n... )\n
Source code in maplibre/sources.py
class RasterTileSource(Source):\n \"\"\"Raster tile source\n\n Examples:\n >>> from maplibre.sources import RasterTileSource\n >>> raster_source = RasterTileSource(\n ... tiles=[\"https://tile.openstreetmap.org/{z}/{x}/{y}.png\"],\n ... tile_size=256,\n ... min_zoom=0,\n ... max_zoom=19,\n ... )\n \"\"\"\n\n attribution: str = None\n bounds: tuple = None\n max_zoom: int = Field(None, serialization_alias=\"maxzoom\")\n min_zoom: int = Field(None, serialization_alias=\"minzoom\")\n scheme: str = None\n tile_size: int = Field(None, serialization_alias=\"tileSize\")\n tiles: Union[tuple, list] = None\n url: str = None\n volatile: bool = None\n\n @computed_field\n @property\n def type(self) -> str:\n return SourceType.RASTER.value\n
"},{"location":"api/sources/#maplibre.sources.SourceType","title":"SourceType
","text":" Bases: Enum
Source types
Source code in maplibre/sources.py
class SourceType(Enum):\n \"\"\"Source types\"\"\"\n\n RASTER = \"raster\"\n VECTOR = \"vector\"\n RASTER_DEM = \"raster-dem\"\n GEOJSON = \"geojson\"\n IMAGE = \"image\"\n VIDEO = \"video\"\n
"},{"location":"examples/3d_indoor_mapping/","title":"3D Indoor mapping","text":"import sys\nimport webbrowser\n\nfrom maplibre import Layer, LayerType, Map, MapOptions\nfrom maplibre.basemaps import background\nfrom maplibre.sources import GeoJSONSource, RasterTileSource\n\nfile_name = \"/tmp/pymaplibregl_temp.html\"\n\nFLOORPLAN_SOURCE_ID = \"floorplan\"\n\nraster_source = RasterTileSource(\n tiles=[\"https://tile.openstreetmap.org/{z}/{x}/{y}.png\"],\n tile_size=256,\n min_zoom=0,\n max_zoom=19,\n)\n\nraster_layer = Layer(type=LayerType.RASTER, source=raster_source)\n\nfloorplan_source = GeoJSONSource(\n data=\"https://maplibre.org/maplibre-gl-js/docs/assets/indoor-3d-map.geojson\"\n)\n\nfloorplan_layer = Layer(\n type=LayerType.FILL_EXTRUSION,\n id=\"floorplan\",\n source=FLOORPLAN_SOURCE_ID,\n paint={\n \"fill-extrusion-color\": [\"get\", \"color\"],\n \"fill-extrusion-height\": [\"get\", \"height\"],\n \"fill-extrusion-base\": [\"get\", \"base_height\"],\n \"fill-extrusion-opacity\": 0.5,\n },\n)\n\nmap_options = MapOptions(\n style=background(\"yellow\"),\n center=(-87.61694, 41.86625),\n zoom=17,\n pitch=40,\n bearing=20,\n antialias=True,\n)\n\n\ndef create_map():\n m = Map(map_options)\n m.add_layer(raster_layer)\n m.add_source(FLOORPLAN_SOURCE_ID, floorplan_source)\n m.add_layer(floorplan_layer)\n return m\n\n\nif __name__ == \"__main__\":\n m = create_map()\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n\n with open(file_name, \"w\") as f:\n f.write(m.to_html())\n\n webbrowser.open(file_name)\n
Run example:
poetry run python docs/examples/3d_indoor_mapping/app.py\n
"},{"location":"examples/airports/","title":"Airport markers","text":"import pandas as pd\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.basemaps import Carto\nfrom maplibre.controls import Marker, MarkerOptions, Popup, PopupOptions\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.utils import GeometryType, df_to_geojson\nfrom shiny import App, ui\n\nBOUNDS = (-8.92242886, 43.30508298, 13.76496714, 59.87668996)\n\nairports_data = pd.read_json(\n \"https://github.com/visgl/deck.gl-data/raw/master/examples/line/airports.json\"\n)\n\n\ndef get_color(airport_type: str) -> str:\n color = \"darkblue\"\n if airport_type == \"mid\":\n color = \"darkred\"\n elif airport_type == \"major\":\n color = \"darkgreen\"\n\n return color\n\n\ngeojson = df_to_geojson(\n airports_data,\n \"coordinates\",\n GeometryType.POINT,\n properties=[\"type\", \"name\", \"abbrev\"],\n)\n\nairport_circles = Layer(\n type=LayerType.CIRCLE,\n source=GeoJSONSource(data=geojson),\n paint={\n \"circle-color\": [\n \"match\",\n [\"get\", \"type\"],\n \"mid\",\n \"darkred\",\n \"major\",\n \"darkgreen\",\n \"darkblue\",\n ],\n \"circle_radius\": 10,\n \"circle-opacity\": 0.3,\n },\n)\n\nmap_options = MapOptions(\n style=Carto.POSITRON,\n bounds=BOUNDS,\n fit_bounds_options={\"padding\": 20},\n hash=True,\n)\n\npopup_options = PopupOptions(close_button=False)\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Airports\"),\n output_maplibregl(\"maplibre\", height=600),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map(map_options)\n for _, r in airports_data.iterrows():\n marker = Marker(\n lng_lat=r[\"coordinates\"],\n options=MarkerOptions(color=get_color(r[\"type\"])),\n popup=Popup(\n text=r[\"name\"],\n options=popup_options,\n ),\n )\n m.add_marker(marker)\n m.add_layer(airport_circles)\n return m\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n app.run()\n
Run example:
poetry run uvicorn docs.examples.airports.app:app --reload\n
"},{"location":"examples/custom_basemap/","title":"Custom basemap","text":"import sys\nimport webbrowser\n\nfrom maplibre import Layer, LayerType, Map, MapOptions\nfrom maplibre.basemaps import construct_basemap_style\nfrom maplibre.sources import GeoJSONSource\n\nfile_name = \"/tmp/pymaplibregl_temp.html\"\n\nbg_layer = Layer(\n type=LayerType.BACKGROUND,\n id=\"background\",\n source=None,\n paint={\"background-color\": \"darkblue\", \"background-opacity\": 0.8},\n)\n\ncountries_source = GeoJSONSource(\n data=\"https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_110m_admin_0_countries.geojson\"\n)\n\nlines_layer = Layer(\n type=LayerType.LINE,\n source=\"countries\",\n paint={\"line-color\": \"white\", \"line-width\": 1.5},\n)\n\npolygons_layer = Layer(\n type=LayerType.FILL,\n source=\"countries\",\n paint={\"fill-color\": \"darkred\", \"fill-opacity\": 0.8},\n)\n\ncustom_basemap = construct_basemap_style(\n layers=[bg_layer, polygons_layer, lines_layer],\n sources={\"countries\": countries_source},\n)\n\n\nmap_options = MapOptions(\n style=custom_basemap,\n center=(0, 0),\n zoom=2,\n)\n\n\ndef create_map():\n m = Map(map_options)\n m.add_layer(\n Layer(\n type=LayerType.CIRCLE,\n id=\"earthquakes\",\n source=GeoJSONSource(\n data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\"\n ),\n paint={\"circle-color\": \"yellow\", \"circle-radius\": 5},\n )\n )\n m.add_popup(\"earthquakes\", \"mag\")\n return m\n\n\nif __name__ == \"__main__\":\n m = create_map()\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n\n with open(file_name, \"w\") as f:\n f.write(m.to_html())\n\n webbrowser.open(file_name)\n
Run example:
poetry run python docs/examples/custom_basemap/app.py\n
"},{"location":"examples/earthquake_clusters/","title":"Earthquake clusters","text":"from maplibre import (\n Layer,\n LayerType,\n Map,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.basemaps import Carto\nfrom maplibre.sources import GeoJSONSource\nfrom shiny import App, reactive, ui\n\nEARTHQUAKE_SOURCE = \"earthquakes\"\nEARTHQUAKE_CIRCLES = \"earthquake-circles\"\nEARTHQUAKE_CLUSTERS = \"earthquake-clusters\"\nEARTHQUAKE_LABELS = \"earthquake-labels\"\n\nCENTER = (-118.0931, 33.78615)\n\nearthquakes_source = GeoJSONSource(\n data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\",\n cluster=True,\n cluster_radius=50,\n cluster_min_points=2,\n cluster_max_zoom=14,\n cluster_properties={\n \"maxMag\": [\"max\", [\"get\", \"mag\"]],\n \"minMag\": [\"min\", [\"get\", \"mag\"]],\n },\n)\n\nearthquake_circles = Layer(\n type=LayerType.CIRCLE,\n id=EARTHQUAKE_CIRCLES,\n source=EARTHQUAKE_SOURCE,\n paint={\"circle-color\": \"darkblue\"},\n filter=[\"!\", [\"has\", \"point_count\"]],\n)\n\nearthquake_clusters = Layer(\n type=LayerType.CIRCLE,\n id=EARTHQUAKE_CLUSTERS,\n source=EARTHQUAKE_SOURCE,\n filter=[\"has\", \"point_count\"],\n paint={\n \"circle-color\": [\n \"step\",\n [\"get\", \"point_count\"],\n \"#51bbd6\",\n 100,\n \"#f1f075\",\n 750,\n \"#f28cb1\",\n ],\n \"circle-radius\": [\"step\", [\"get\", \"point_count\"], 20, 100, 30, 750, 40],\n },\n)\n\nearthquake_labels = Layer(\n type=LayerType.SYMBOL,\n id=\"text\",\n source=EARTHQUAKE_SOURCE,\n filter=[\"has\", \"point_count\"],\n layout={\n \"text-field\": [\"get\", \"point_count_abbreviated\"],\n \"text-size\": 12,\n },\n)\n\nmap_options = MapOptions(style=Carto.POSITRON, center=CENTER, zoom=3, hash=True)\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Earthquakes Cluster\"),\n output_maplibregl(\"maplibre\", height=500),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map(map_options)\n m.add_source(EARTHQUAKE_SOURCE, earthquakes_source)\n m.add_layer(earthquake_clusters)\n m.add_layer(earthquake_circles)\n m.add_tooltip(EARTHQUAKE_CLUSTERS, \"maxMag\")\n m.add_layer(earthquake_labels)\n return m\n\n @reactive.Effect\n @reactive.event(input.maplibre)\n async def result():\n print(f\"result: {input.maplibre()}\")\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n app.run()\n
Run example:
poetry run uvicorn docs.examples.earthquake_clusters.app:app --reload\n
"},{"location":"examples/every_person_in_manhattan/","title":"Every person in manhattan","text":"import json\nimport sys\n\nimport pandas as pd\nimport shapely\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.basemaps import Carto\nfrom maplibre.controls import ScaleControl\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.utils import df_to_geojson\nfrom shiny import App, reactive, ui\n\nMALE_COLOR = \"rgb(0, 128, 255)\"\nFEMALE_COLOR = \"rgb(255, 0, 128)\"\nLAYER_ID = \"every-person-in-manhattan-circles\"\nCIRCLE_RADIUS = 2\n\npoint_data = pd.read_json(\n \"https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/scatterplot/manhattan.json\"\n)\n\npoint_data.columns = [\"lng\", \"lat\", \"sex\"]\n\nevery_person_in_manhattan_source = GeoJSONSource(\n data=df_to_geojson(point_data, properties=[\"sex\"]),\n)\n\nbbox = shapely.bounds(\n shapely.from_geojson(json.dumps(every_person_in_manhattan_source.data))\n)\n\nevery_person_in_manhattan_circles = Layer(\n type=LayerType.CIRCLE,\n id=LAYER_ID,\n source=every_person_in_manhattan_source,\n paint={\n \"circle-color\": [\"match\", [\"get\", \"sex\"], 1, MALE_COLOR, FEMALE_COLOR],\n \"circle-radius\": CIRCLE_RADIUS,\n },\n)\n\nmap_options = MapOptions(\n style=Carto.POSITRON,\n bounds=tuple(bbox),\n fit_bounds_options={\"padding\": 20},\n)\n\n\ndef create_map() -> Map:\n m = Map(map_options)\n m.add_control(ScaleControl(), position=\"bottom-left\")\n m.add_layer(every_person_in_manhattan_circles)\n return m\n\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Every Person in Manhattan\"),\n output_maplibregl(\"maplibre\", height=600),\n ui.input_slider(\"radius\", \"Radius\", value=CIRCLE_RADIUS, min=1, max=5),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n return create_map()\n\n @reactive.Effect\n @reactive.event(input.radius, ignore_init=True)\n async def radius():\n async with MapContext(\"maplibre\") as m:\n m.set_paint_property(LAYER_ID, \"circle-radius\", input.radius())\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n with open(file_name, \"w\") as f:\n f.write(create_map().to_html())\n else:\n app.run()\n
Run example:
poetry run uvicorn docs.examples.every_person_in_manhattan.app:app --reload\n
"},{"location":"examples/geopandas/","title":"GeoPandas","text":"See example in action
import sys\nimport webbrowser\n\nfrom maplibre import Layer, LayerType, Map, MapOptions\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.utils import geopandas_to_geojson\n\nimport geopandas as gpd\n\nfile_name = \"/tmp/pymaplibregl_temp.html\"\nLAYER_ID = \"wilderness\"\n\ndf_geo = gpd.read_file(\n \"zip+https://github.com/Toblerity/Fiona/files/11151652/coutwildrnp.zip\"\n)\n\nwilderness_source = GeoJSONSource(data=geopandas_to_geojson(df_geo))\n\nwilderness_layer = Layer(\n type=LayerType.FILL,\n id=LAYER_ID,\n source=wilderness_source,\n paint={\"fill-color\": \"darkred\", \"fill-opacity\": 0.5},\n)\n\nmap_options = MapOptions(bounds=df_geo.total_bounds)\n\n\ndef create_map():\n m = Map(map_options)\n m.add_layer(wilderness_layer)\n m.add_tooltip(LAYER_ID, \"NAME\")\n return m\n\n\nif __name__ == \"__main__\":\n m = create_map()\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n\n with open(file_name, \"w\") as f:\n f.write(m.to_html())\n\n webbrowser.open(file_name)\n
Run example:
poetry run python docs/examples/geopandas/app.py\n
"},{"location":"examples/road_safety/","title":"UK Road Safety","text":"import sys\nimport webbrowser\n\nimport h3\nimport pandas as pd\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.utils import df_to_geojson\nfrom shiny import App, reactive, ui\n\nRESOLUTION = 7\nCOLORS = (\n \"lightblue\",\n \"turquoise\",\n \"lightgreen\",\n \"yellow\",\n \"orange\",\n \"darkred\",\n)\n\nroad_safety = pd.read_csv(\n \"https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv\"\n).dropna()\n\n\ndef create_h3_grid(res=RESOLUTION) -> dict:\n road_safety[\"h3\"] = road_safety.apply(\n lambda x: h3.geo_to_h3(x[\"lat\"], x[\"lng\"], resolution=res), axis=1\n )\n df = road_safety.groupby(\"h3\").h3.agg(\"count\").to_frame(\"count\").reset_index()\n df[\"hexagon\"] = df.apply(\n lambda x: [h3.h3_to_geo_boundary(x[\"h3\"], geo_json=True)], axis=1\n )\n df[\"color\"] = pd.cut(\n df[\"count\"],\n bins=len(COLORS),\n labels=COLORS,\n )\n return df_to_geojson(\n df, \"hexagon\", geometry_type=\"Polygon\", properties=[\"count\", \"color\"]\n )\n\n\nsource = GeoJSONSource(data=create_h3_grid())\n\n\ndef create_map() -> Map:\n m = Map(MapOptions(center=(-1.415727, 52.232395), zoom=7, pitch=40, bearing=-27))\n m.add_layer(\n Layer(\n id=\"road-safety\",\n type=LayerType.FILL_EXTRUSION,\n source=source,\n paint={\n \"fill-extrusion-color\": [\"get\", \"color\"],\n \"fill-extrusion-opacity\": 0.7,\n \"fill-extrusion-height\": [\"*\", 100, [\"get\", \"count\"]],\n },\n )\n )\n m.add_tooltip(\"road-safety\", \"count\")\n return m\n\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Road safety in UK\"),\n output_maplibregl(\"mapylibre\", height=700),\n ui.input_slider(\"res\", \"Resolution\", min=4, max=8, step=1, value=RESOLUTION),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def mapylibre():\n return create_map()\n\n @reactive.Effect\n @reactive.event(input.res, ignore_init=True)\n async def resolution():\n async with MapContext(\"mapylibre\") as m:\n with ui.Progress() as p:\n p.set(message=\"H3 calculation in progress\")\n m.set_data(\"road-safety\", create_h3_grid(input.res()))\n p.set(1, message=\"Calculation finished\")\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n filename = sys.argv[1] if len(sys.argv) == 2 else \"/tmp/road_safety.html\"\n with open(filename, \"w\") as f:\n m = create_map()\n f.write(m.to_html(style=\"height: 700px;\"))\n\n webbrowser.open(filename)\n
Run example:
poetry run uvicorn docs.examples.road_safety.app:app --reload\n
"},{"location":"examples/vancouver_blocks/","title":"Vancouver property value","text":"import sys\n\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.basemaps import Carto\nfrom maplibre.controls import ScaleControl\nfrom maplibre.sources import GeoJSONSource\nfrom shiny import App, reactive, ui\n\nSOURCE_ID = \"vancouver-blocks\"\nLAYER_ID_LINES = \"vancouver-blocks-lines\"\nLAYER_ID_FILL = \"vancouver-blocks-fill-extrusion\"\nMAX_FILTER_VALUE = 1000000\n\nvancouver_blocks_source = GeoJSONSource(\n data=\"https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/geojson/vancouver-blocks.json\"\n)\n\nvancouver_blocks_lines = Layer(\n type=LayerType.LINE,\n id=LAYER_ID_LINES,\n source=SOURCE_ID,\n paint={\n \"line-color\": \"white\",\n \"line-width\": 2,\n },\n)\n\nvancouver_blocks_fill = Layer(\n type=LayerType.FILL_EXTRUSION,\n id=LAYER_ID_FILL,\n source=SOURCE_ID,\n paint={\n \"fill-extrusion-color\": {\n \"property\": \"valuePerSqm\",\n \"stops\": [\n [0, \"grey\"],\n [1000, \"yellow\"],\n [5000, \"orange\"],\n [10000, \"darkred\"],\n [50000, \"lightblue\"],\n ],\n },\n \"fill-extrusion-height\": [\"*\", 10, [\"sqrt\", [\"get\", \"valuePerSqm\"]]],\n \"fill-extrusion-opacity\": 0.9,\n },\n)\n\nmap_options = MapOptions(\n style=Carto.DARK_MATTER,\n center=(-123.13, 49.254),\n zoom=11,\n pitch=45,\n bearing=0,\n)\n\n\ndef create_map() -> Map:\n m = Map(map_options)\n m.add_control(ScaleControl(), position=\"bottom-left\")\n m.add_source(SOURCE_ID, vancouver_blocks_source)\n m.add_layer(vancouver_blocks_lines)\n m.add_layer(vancouver_blocks_fill)\n m.add_tooltip(LAYER_ID_FILL, \"valuePerSqm\")\n return m\n\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Vancouver Property Value\"),\n ui.div(\n \"Height of polygons - average property value per square meter of lot\",\n style=\"padding: 10px;\",\n ),\n output_maplibregl(\"maplibre\", height=600),\n ui.input_select(\n \"filter\",\n \"max property value per square meter\",\n choices=[0, 1000, 5000, 10000, 50000, 100000, MAX_FILTER_VALUE],\n selected=MAX_FILTER_VALUE,\n ),\n ui.input_checkbox_group(\n \"layers\",\n \"Layers\",\n choices=[LAYER_ID_FILL, LAYER_ID_LINES],\n selected=[LAYER_ID_FILL, LAYER_ID_LINES],\n ),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = create_map()\n return m\n\n @reactive.Effect\n @reactive.event(input.filter)\n async def filter():\n async with MapContext(\"maplibre\") as m:\n filter_ = [\"<=\", [\"get\", \"valuePerSqm\"], int(input.filter())]\n m.set_filter(LAYER_ID_FILL, filter_)\n\n @reactive.Effect\n @reactive.event(input.layers)\n async def layers():\n visible_layers = input.layers()\n async with MapContext(\"maplibre\") as m:\n for layer in [LAYER_ID_FILL, LAYER_ID_LINES]:\n m.set_visibility(layer, layer in visible_layers)\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n m = create_map()\n with open(file_name, \"w\") as f:\n f.write(m.to_html())\n else:\n app.run()\n
Run example:
poetry run uvicorn docs.examples.vancouver_blocks.app:app --reload\n
"},{"location":"examples/where_is_the_iss/","title":"Where is the ISS","text":"import requests\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.sources import GeoJSONSource\nfrom shiny import App, reactive, ui\n\nMAX_FEATURES = 30\nSOURCE_ID_ISS_POSITION = \"iss_position\"\nSOURCE_ID_ISS_LAST_POSITIONS = \"iss-last-positions\"\n\n\ndef where_is_the_iss() -> tuple:\n r = requests.get(\"https://api.wheretheiss.at/v1/satellites/25544\").json()\n return (r[\"longitude\"], r[\"latitude\"])\n\n\ndef create_feature(lng_lat: tuple) -> dict:\n return {\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": lng_lat,\n },\n \"properties\": {\"coords\": \", \".join(map(str, lng_lat))},\n }\n\n\nlng_lat = where_is_the_iss()\nfeature = create_feature(where_is_the_iss())\nfeature_collection = {\"type\": \"FeatureCollection\", \"features\": [feature]}\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Where is the ISS\"),\n ui.div(\"Click on Update to get the current position of the ISS.\"),\n ui.div(\n \"The yellow dots show the positions before. Hover the blue dot to display the coordinates.\"\n ),\n output_maplibregl(\"mapylibre\", height=600),\n ui.input_action_button(\"update\", \"Update\"),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def mapylibre():\n m = Map(MapOptions(center=lng_lat, zoom=3))\n m.set_paint_property(\"water\", \"fill-color\", \"darkblue\")\n m.add_source(\n SOURCE_ID_ISS_LAST_POSITIONS, GeoJSONSource(data=feature_collection)\n )\n m.add_layer(\n Layer(\n type=LayerType.CIRCLE,\n source=SOURCE_ID_ISS_LAST_POSITIONS,\n paint={\"circle-color\": \"yellow\", \"circle-radius\": 5},\n ),\n )\n m.add_source(SOURCE_ID_ISS_POSITION, GeoJSONSource(data=feature))\n m.add_layer(\n Layer(\n type=LayerType.CIRCLE,\n id=\"iss-position\",\n source=SOURCE_ID_ISS_POSITION,\n paint={\"circle-color\": \"lightblue\", \"circle-radius\": 7},\n )\n )\n m.add_tooltip(\"iss-position\", \"coords\")\n return m\n\n @reactive.Effect\n @reactive.event(input.update)\n async def update():\n print(\"Fetching new position\")\n lng_lat = where_is_the_iss()\n print(lng_lat)\n if len(feature_collection[\"features\"]) == MAX_FEATURES:\n feature_collection[\"features\"] = []\n\n async with MapContext(\"mapylibre\") as m:\n feature = create_feature(lng_lat)\n m.set_data(SOURCE_ID_ISS_POSITION, feature)\n feature_collection[\"features\"].append(feature)\n m.set_data(SOURCE_ID_ISS_LAST_POSITIONS, feature_collection)\n m.add_call(\"flyTo\", {\"center\": lng_lat, \"speed\": 0.5})\n\n\napp = App(app_ui, server)\n
Run example:
poetry run uvicorn docs.examples.where_is_the_iss.app:app --reload\n
"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"MapLibre for Python","text":"MapLibre for Python provides Python bindings for MapLibre GL JS.
It integrates seamlessly into Shiny for Python and Jupyter.
"},{"location":"#installation","title":"Installation","text":"# Stable\npip install maplibre\n\npip install \"maplibre[all]\"\n\n# Dev\npip install git+https://github.com/eodaGmbH/py-maplibregl@dev\n
"},{"location":"#basic-usage","title":"Basic usage","text":""},{"location":"#standalone","title":"Standalone","text":"import webbrowser\n\nfrom maplibre import Layer, LayerType, Map, MapOptions\nfrom maplibre.sources import GeoJSONSource\n\nvancouver_blocks = GeoJSONSource(\n data=\"https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/geojson/vancouver-blocks.json\",\n)\n\nmap_options = MapOptions(\n center=(-123.1256, 49.24658),\n zoom=12,\n hash=True,\n pitch=35,\n)\n\nm = Map(map_options)\nm.add_layer(\n Layer(\n type=LayerType.LINE,\n source=vancouver_blocks,\n paint={\"line-color\": \"white\"},\n )\n)\n\ntemp_file = \"/tmp/pymaplibregl.html\"\n\nwith open(temp_file, \"w\") as f:\n f.write(m.to_html(style=\"height: 800px;\"))\n\nwebbrowser.open(temp_file)\n
"},{"location":"#shiny-integration","title":"Shiny integration","text":"from maplibre import Map, MapContext, output_maplibregl, render_maplibregl\nfrom maplibre.controls import Marker\nfrom shiny import App, reactive, ui\n\napp_ui = ui.page_fluid(\n output_maplibregl(\"maplibre\", height=600),\n ui.div(\"Click on map to set a marker\"),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map()\n return m\n\n @reactive.Effect\n @reactive.event(input.maplibre)\n async def coords():\n async with MapContext(\"maplibre\") as m:\n print(input.maplibre())\n lng_lat = tuple(input.maplibre()[\"coords\"].values())\n marker = Marker(lng_lat=lng_lat)\n m.add_marker(marker)\n m.add_call(\"flyTo\", {\"center\": lng_lat})\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n app.run()\n
"},{"location":"#jupyter-widget","title":"Jupyter widget","text":"from maplibre.ipywidget import MapWidget as Map\n\nm = Map()\nm\n
"},{"location":"jupyter/","title":"Jupyter","text":"Use MapWidget
in your Juyper Notebook:
import ipywidgets as widgets\n\nfrom maplibre import Layer, LayerType\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.controls import ScaleControl, Marker\nfrom maplibre.ipywidget import MapWidget as Map\n\n# Create a source\nearthquakes = GeoJSONSource(\n data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\"\n)\n\n# Create a layer\nlayer_id = \"earthquakes\"\n\nearthquake_circles = Layer(\n type=LayerType.CIRCLE,\n id=layer_id,\n source=earthquakes,\n paint={\"circle-color\": \"yellow\"}\n)\n\n# Render map\nm = Map()\nm.add_control(ScaleControl(), position=\"bottom-left\")\nm.add_layer(earthquake_circles)\nm.add_tooltip(layer_id, \"mag\")\nm.add_marker(Marker(lng_lat=(100.507, 13.745)))\nm\n\n# Change radius\nwidgets.interact(\n lambda radius: m.set_paint_property(layer_id, \"circle-radius\", radius),\n radius=5\n)\n\n# Change color\nwidgets.interact(\n lambda color: m.set_paint_property(layer_id, \"circle-color\", color),\n color=[\"green\", \"yellow\", \"orange\", \"red\"]\n)\n\n# Set filter on magnitude\nwidgets.interact(\n lambda mag_min: m.set_filter(layer_id, [\">=\", [\"get\", \"mag\"], mag_min]),\n mag_min=3\n)\n\n# Observe map-on-click event\nfrom IPython.display import clear_output\n\noutput = widgets.Output()\n\n\ndef log_lng_lat(lng_lat):\n with output:\n clear_output()\n print(lng_lat.new)\n\n\nm.observe(log_lng_lat, names=\"lng_lat\")\noutput\n
"},{"location":"layers/","title":"Layers","text":"The paint
and layout
properties for the layers depend on the type of the layer. They are passed as a dict
corresponding to the Layer Style Spec.
For example, to set the radius and the color for a circle layer, the paint
property looks like this:
paint = {\n \"circle-radius\": 5,\n \"circle-color\": \"yellow\"\n}\n
The value for any layout
property, paint
property, or filter
may also be specified as an expression. For details see Expressions.
For example, if the source of your layer has a color
property that contains the color of the feature, you can use the following expression:
paint = {\n \"circle-radius\": 5,\n \"circle-color\": [\"get\", \"color\"]\n}\n
A more complex expression where the color depends on the type
property of the layer's source might look like this:
paint={\n \"circle-color\": [\n \"match\",\n [\"get\", \"type\"],\n # darkred if type == \"mid\"\n \"mid\",\n \"darkred\",\n # darkgreen if type == \"major\"\n \"major\",\n \"darkgreen\",\n # else blue\n \"darkblue\",\n ]\n}\n
Filter features of a source according to its magnitude
property:
# Only show features where magnitude >= 5\nfilter = [\">=\", [\"get\", \"magnitude\"], 5]\n
"},{"location":"shiny/","title":"Shiny","text":""},{"location":"shiny/#input-and-output","title":"Input and output","text":"Use output_maplibregl
in the UI and render_maplibregl
in the server section of your Shiny for Python app:
from shiny import App, ui\nfrom maplibre import output_maplibregl, render_maplibregl, Map\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"MapLibre\"),\n output_maplibregl(\"maplibre\", height=600)\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map()\n return m\n\n\napp = App(app_ui, server)\n
"},{"location":"shiny/#reactivity","title":"Reactivity","text":""},{"location":"shiny/#input-events","title":"Input events","text":"MapLibre for Python provides the following reactive inputs:
map-on-click
event: Sends the coordinates of the location that was clicked on. The name of the input event corresponds to the output id. For output_maplibregl(\"maplibre\")
you need to listen to input.maplibre
. feature-on-click
event: Sends the properties of the feature that was clicked on. The name of the \u00ecnput is made up of the output id + layer
+ layer id. For output_maplibregl(\"maplibre\")
and a layer with id=test
you need to listen to input.maplibre_layer_test
.
"},{"location":"shiny/#map-updates","title":"Map updates","text":"Use MapContext
to update your Map
object.
"},{"location":"shiny/#example","title":"Example","text":"from maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.sources import GeoJSONSource\nfrom shiny import App, reactive, render, ui\n\nLAYER_ID = \"earthquakes\"\nCIRCLE_RADIUS = 5\n\napp_ui = ui.page_fluid(\n #\n # Render map\n #\n ui.panel_title(\"MapLibre\"),\n output_maplibregl(\"maplibre\", height=600),\n #\n # Show coords\n #\n ui.div(\"Click on the map to print the coords.\", style=\"padding: 10px;\"),\n ui.output_text_verbatim(\"coords\", placeholder=True),\n #\n # Show props of a feature\n #\n ui.div(\"Click on a feature to print its props.\", style=\"padding: 10px;\"),\n ui.output_text_verbatim(\"props\", placeholder=True),\n #\n # Change radius\n #\n ui.input_slider(\"radius\", \"Radius\", value=CIRCLE_RADIUS, min=1, max=10),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map(zoom=3)\n m.add_layer(\n Layer(\n type=LayerType.CIRCLE,\n id=LAYER_ID,\n source=GeoJSONSource(\n data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\"\n ),\n paint={\"circle-color\": \"yellow\"},\n )\n )\n return m\n\n @render.text\n def coords():\n return str(input.maplibre())\n\n @render.text\n def props():\n return str(input.maplibre_layer_earthquakes())\n\n @reactive.Effect\n @reactive.event(input.radius)\n async def radius():\n async with MapContext(\"maplibre\") as m:\n m.set_paint_property(LAYER_ID, \"circle-radius\", input.radius())\n\n\napp = App(app_ui, server)\n
Run this example:
poetry run uvicorn docs.examples.getting_started.reactivity:app --reload\n
"},{"location":"api/basemaps/","title":"Basemaps","text":""},{"location":"api/basemaps/#maplibre.basemaps.Carto","title":"maplibre.basemaps.Carto
","text":" Bases: Enum
Carto basemap styles
Attributes:
-
DARK_MATTER
\u2013 dark-matter
-
POSITRON
\u2013 positron
-
VOYAGER
\u2013 voyager
-
POSITRON_NOLABELS
\u2013 positron-nolabels
-
DARK_MATTER_NOLABELS
\u2013 dark-matter-nolabels
-
VOYAGER_NOLABELS
\u2013 voyager-nolabels
Examples:
>>> from maplibre import Map, MapOptions\n>>> from maplibre.basemaps import Carto\n
>>> map = Map(MapOptions(style=Carto.DARK_MATTER))\n
Source code in maplibre/basemaps.py
class Carto(Enum):\n \"\"\"Carto basemap styles\n\n Attributes:\n DARK_MATTER: dark-matter\n POSITRON: positron\n VOYAGER: voyager\n POSITRON_NOLABELS: positron-nolabels\n DARK_MATTER_NOLABELS: dark-matter-nolabels\n VOYAGER_NOLABELS: voyager-nolabels\n\n Examples:\n >>> from maplibre import Map, MapOptions\n >>> from maplibre.basemaps import Carto\n\n >>> map = Map(MapOptions(style=Carto.DARK_MATTER))\n \"\"\"\n\n DARK_MATTER = \"dark-matter\"\n POSITRON = \"positron\"\n VOYAGER = \"voyager\"\n POSITRON_NOLABELS = \"positron-nolabels\"\n DARK_MATTER_NOLABELS = \"dark-matter-nolabels\"\n VOYAGER_NOLABELS = \"voyager-nolabels\"\n
"},{"location":"api/basemaps/#maplibre.basemaps.construct_basemap_style","title":"maplibre.basemaps.construct_basemap_style(name='nice-style', sources={}, layers=[])
","text":"Construct a basemap style
Parameters:
Name Type Description Default name
str
The name of the basemap style.
'nice-style'
sources
dict
The sources to be used for the basemap style.
{}
layers
list
The layers to be used for the basemap style.
[]
Source code in maplibre/basemaps.py
def construct_basemap_style(\n name: str = \"nice-style\", sources: dict = {}, layers: list = []\n) -> dict:\n \"\"\"Construct a basemap style\n\n Args:\n name (str): The name of the basemap style.\n sources (dict): The sources to be used for the basemap style.\n layers (list): The layers to be used for the basemap style.\n \"\"\"\n layers = [\n layer.to_dict() if isinstance(layer, Layer) else layer for layer in layers\n ]\n return {\"name\": name, \"version\": 8, \"sources\": sources, \"layers\": layers}\n
"},{"location":"api/controls/","title":"Markers and controls","text":""},{"location":"api/controls/#maplibre.controls.Popup","title":"maplibre.controls.Popup
","text":" Bases: BaseModel
Popup
Attributes:
Name Type Description text
str
The Text of the popup.
options
PopupOptions | dict
Popup options.
Source code in maplibre/controls.py
class Popup(BaseModel):\n \"\"\"Popup\n\n Attributes:\n text: The Text of the popup.\n options (PopupOptions | dict): Popup options.\n \"\"\"\n\n text: str\n options: Union[PopupOptions, dict] = {}\n
"},{"location":"api/controls/#maplibre.controls.PopupOptions","title":"maplibre.controls.PopupOptions
","text":" Bases: BaseModel
Popup options
Source code in maplibre/controls.py
class PopupOptions(BaseModel):\n \"\"\"Popup options\"\"\"\n\n anchor: str = None\n close_button: bool = Field(False, serialization_alias=\"closeButton\")\n close_on_click: bool = Field(None, serialization_alias=\"closeOnClick\")\n close_on_move: bool = Field(None, serialization_alias=\"closeOnMove\")\n max_width: int = Field(None, serialization_alias=\"maxWidth\")\n offset: Union[int, list, dict] = None\n
"},{"location":"api/controls/#maplibre.controls.Marker","title":"maplibre.controls.Marker
","text":" Bases: BaseModel
Marker
Attributes:
Name Type Description lng_lat
tuple | list
Required. The longitude and latitude of the marker.
popup
Popup | dict
The Popup that is displayed when a user clicks on the marker.
options
MarkerOptions | dict
Marker options.
Source code in maplibre/controls.py
class Marker(BaseModel):\n \"\"\"Marker\n\n Attributes:\n lng_lat (tuple |list): **Required.** The longitude and latitude of the marker.\n popup (Popup | dict): The Popup that is displayed when a user clicks on the marker.\n options (MarkerOptions | dict): Marker options.\n \"\"\"\n\n lng_lat: Union[tuple, list] = Field(None, serialization_alias=\"lngLat\")\n popup: Union[Popup, dict] = None\n options: Union[MarkerOptions, dict] = {}\n
"},{"location":"api/controls/#maplibre.controls.MarkerOptions","title":"maplibre.controls.MarkerOptions
","text":" Bases: BaseModel
Marker options
Source code in maplibre/controls.py
class MarkerOptions(BaseModel):\n \"\"\"Marker options\"\"\"\n\n anchor: str = None\n color: str = None\n draggable: bool = None\n offset: Union[tuple, list] = None\n pitch_alignment: str = Field(None, serialization_alias=\"pitchAlignment\")\n rotation: int = None\n rotation_alignment: str = Field(None, serialization_alias=\"rotationAlignment\")\n scale: int = None\n
"},{"location":"api/controls/#maplibre.controls.ControlPosition","title":"maplibre.controls.ControlPosition
","text":" Bases: Enum
Control position
Attributes:
-
TOP_LEFT
\u2013 top-left
-
TOP_RIGHT
\u2013 top-right
-
BOTTOM_LEFT
\u2013 bottom-left
-
BOTTOM_RIGHT
\u2013 bottom-right
Source code in maplibre/controls.py
class ControlPosition(Enum):\n \"\"\"Control position\n\n Attributes:\n TOP_LEFT: top-left\n TOP_RIGHT: top-right\n BOTTOM_LEFT: bottom-left\n BOTTOM_RIGHT: bottom-right\n \"\"\"\n\n TOP_LEFT = \"top-left\"\n TOP_RIGHT = \"top-right\"\n BOTTOM_LEFT = \"bottom-left\"\n BOTTOM_RIGHT = \"bottom-right\"\n
"},{"location":"api/controls/#maplibre.controls.FullscreenControl","title":"maplibre.controls.FullscreenControl
","text":" Bases: Control
Fullscreen control
Examples:
>>> from maplibre import Map\n>>> from maplibre.controls import FullscreenControl, ControlPosition\n
>>> map = Map()\n>>> map.add_control(FullscreenControl(), ControlPosition.BOTTOM_LEFT)\n
Source code in maplibre/controls.py
class FullscreenControl(Control):\n \"\"\"Fullscreen control\n\n Examples:\n >>> from maplibre import Map\n >>> from maplibre.controls import FullscreenControl, ControlPosition\n\n >>> map = Map()\n >>> map.add_control(FullscreenControl(), ControlPosition.BOTTOM_LEFT)\n \"\"\"\n\n # _name: str = ControlType.FULLSCREEN.value\n pass\n
"},{"location":"api/controls/#maplibre.controls.ScaleControl","title":"maplibre.controls.ScaleControl
","text":" Bases: Control
Scale control
Source code in maplibre/controls.py
class ScaleControl(Control):\n \"\"\"Scale control\"\"\"\n\n # _name: str = ControlType.SCALE.value\n max_width: int = Field(None, serialization_alias=\"maxWidth\")\n unit: Literal[\"imperial\", \"metric\", \"nautical\"] = \"metric\"\n
"},{"location":"api/controls/#maplibre.controls.NavigationControl","title":"maplibre.controls.NavigationControl
","text":" Bases: Control
Navigation control
Source code in maplibre/controls.py
class NavigationControl(Control):\n \"\"\"Navigation control\"\"\"\n\n # _name: str = ControlType.NAVIGATION.value\n show_compass: bool = Field(True, serialization_alias=\"showCompass\")\n show_zoom: bool = Field(True, serialization_alias=\"showZoom\")\n visualize_pitch: bool = Field(False, serialization_alias=\"visualizePitch\")\n
"},{"location":"api/controls/#maplibre.controls.GeolocateControl","title":"maplibre.controls.GeolocateControl
","text":" Bases: Control
Geolocate control
Source code in maplibre/controls.py
class GeolocateControl(Control):\n \"\"\"Geolocate control\"\"\"\n\n # _name: str = ControlType.GEOLOCATE.value\n position_options: dict = Field(None, serialization_alias=\"positionOptions\")\n show_accuracy_circle: bool = Field(True, serialization_alias=\"showAccuracyCircle\")\n show_user_heading: bool = Field(False, serialization_alias=\"showUserHeading\")\n show_user_location: bool = Field(True, serialization_alias=\"showUserLocation\")\n track_user_location: bool = Field(False, serialization_alias=\"trackUserLocation\")\n
"},{"location":"api/layer/","title":"Layer","text":""},{"location":"api/layer/#maplibre.Layer","title":"maplibre.Layer
","text":" Bases: BaseModel
Layer properties
Notes See layers for more details on the paint
and layout
properties of the layers.
Attributes:
Name Type Description id
str
Required. The unique ID of the layer. Defaults to str(uuid4())
.
type
str | LayerType
Required. The type of the layer.
filter
list
The filter expression that is applied to the source of the layer.
layout
dict
The layout properties of the layer.
max_zoom
int
The maximum zoom level for the layer.
min_zoom
int
The minimum zoom level for the layer.
paint
dict
The paint properties of the layer.
source
str | Source
The name (unique ID) of a source or a source object to be used for the layer.
source_layer
str
The layer to use from a vector tile source.
Examples:
>>> from maplibre.layer import Layer, LayerType\n
>>> layer = Layer(id=\"test-layer\", type=LayerType.CIRCLE, source=\"test-source\")\n
Source code in maplibre/layer.py
class Layer(BaseModel):\n \"\"\"Layer properties\n\n Notes:\n See [layers](https://maplibre.org/maplibre-style-spec/layers/) for more details on the\n `paint` and `layout` properties of the layers.\n\n Attributes:\n id (str): **Required.** The unique ID of the layer. Defaults to `str(uuid4())`.\n type (str | LayerType): **Required.** The type of the layer.\n filter (list): The filter expression that is applied to the source of the layer.\n layout (dict): The layout properties of the layer.\n max_zoom (int): The maximum zoom level for the layer.\n min_zoom (int): The minimum zoom level for the layer.\n paint (dict): The paint properties of the layer.\n source (str | Source): The name (unique ID) of a source or a source object to be used for the layer.\n source_layer (str): The layer to use from a vector tile source.\n\n Examples:\n >>> from maplibre.layer import Layer, LayerType\n\n >>> layer = Layer(id=\"test-layer\", type=LayerType.CIRCLE, source=\"test-source\")\n \"\"\"\n\n id: str = Field(default_factory=lambda: str(uuid4()))\n type: LayerType\n filter: list = None\n layout: dict = None\n max_zoom: int = Field(None, serialization_alias=\"maxzoom\")\n metadata: dict = None\n min_zoom: int = Field(None, serialization_alias=\"minzoom\")\n paint: dict = None\n source: Union[str, Source, dict, None] = None\n source_layer: str = Field(None, serialization_alias=\"source-layer\")\n\n @field_validator(\"source\")\n def validate_source(cls, v):\n if isinstance(v, Source):\n return v.to_dict()\n\n return v\n\n @field_validator(\"paint\", \"layout\")\n def fix_paint(cls, v):\n if isinstance(v, dict):\n return fix_keys(v)\n\n return v\n
"},{"location":"api/layer/#maplibre.LayerType","title":"maplibre.LayerType
","text":" Bases: Enum
Rendering type of layer
Attributes:
-
CIRCLE
\u2013 A filled circle.
-
FILL
\u2013 A filled polygon with an optional stroked border.
-
FILL_EXTRUSION
\u2013 An extruded polygon.
-
LINE
\u2013 A stroked line.
-
SYMBOL
\u2013 An icon or a text label.
-
RASTER
\u2013 Raster map textures such as satellite imagery.
-
HEATMAP
\u2013 A heatmap.
-
HILLSHADE
\u2013 A Client-side hillshading visualization based on DEM data.
-
BACKGROUND
\u2013 A background color or pattern.
Source code in maplibre/layer.py
class LayerType(Enum):\n \"\"\"Rendering type of layer\n\n Attributes:\n CIRCLE: A filled circle.\n FILL: A filled polygon with an optional stroked border.\n FILL_EXTRUSION: An extruded polygon.\n LINE: A stroked line.\n SYMBOL: An icon or a text label.\n RASTER: Raster map textures such as satellite imagery.\n HEATMAP: A heatmap.\n HILLSHADE: A Client-side hillshading visualization based on DEM data.\n BACKGROUND: A background color or pattern.\n \"\"\"\n\n CIRCLE = \"circle\"\n FILL = \"fill\"\n FILL_EXTRUSION = \"fill-extrusion\"\n LINE = \"line\"\n SYMBOL = \"symbol\"\n RASTER = \"raster\"\n HEATMAP = \"heatmap\"\n HILLSHADE = \"hillshade\"\n BACKGROUND = \"background\"\n
"},{"location":"api/map/","title":"Map","text":""},{"location":"api/map/#maplibre.Map","title":"maplibre.Map
","text":" Bases: object
Map
Parameters:
Name Type Description Default map_options
MapOptions
Map options.
MapOptions()
**kwargs
Keyword arguments that are appended to the MapOptions
object.
{}
Examples:
>>> from maplibre.map import Map, MapOptions\n
>>> map_options = MapOptions(center=(9.5, 51.31667), zoom=8)\n>>> map = Map(map_options)\n>>> dict(map)\n{'mapOptions': {'center': (9.5, 51.31667), 'style': 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json', 'zoom': 8}, 'calls': []}\n
Source code in maplibre/map.py
class Map(object):\n \"\"\"Map\n\n Args:\n map_options (MapOptions): Map options.\n **kwargs: Keyword arguments that are appended to the `MapOptions` object.\n\n Examples:\n >>> from maplibre.map import Map, MapOptions\n\n >>> map_options = MapOptions(center=(9.5, 51.31667), zoom=8)\n >>> map = Map(map_options)\n >>> dict(map)\n {'mapOptions': {'center': (9.5, 51.31667), 'style': 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json', 'zoom': 8}, 'calls': []}\n \"\"\"\n\n MESSAGE = \"not implemented yet\"\n\n def __init__(self, map_options: MapOptions = MapOptions(), **kwargs):\n self.map_options = map_options.to_dict() | kwargs\n self._message_queue = []\n\n def __iter__(self):\n for k, v in self.to_dict().items():\n yield k, v\n\n def to_dict(self) -> dict:\n return {\"mapOptions\": self.map_options, \"calls\": self._message_queue}\n\n \"\"\"\n @property\n def sources(self) -> list:\n return [item[\"data\"] for item in self._calls if item[\"name\"] == \"addSource\"]\n\n @property\n def layers(self) -> list:\n return [item[\"data\"] for item in self._calls if item[\"name\"] == \"addLayer\"]\n \"\"\"\n\n # TODO: Rename to add_map_call\n def add_call_(self, func_name: str, params: list) -> None:\n self._message_queue.append(\n {\"name\": \"applyFunc\", \"data\": {\"funcName\": func_name, \"params\": params}}\n )\n\n def add_call(self, method_name: str, *args) -> None:\n \"\"\"Add a method call that is executed on the map instance\n\n Args:\n method_name (str): The name of the map method to be executed.\n *args (any): The arguments to be passed to the map method.\n \"\"\"\n # TODO: Pass as dict? {\"name\": method_name, \"args\": args}\n call = [method_name, args]\n self._message_queue.append(call)\n\n def add_control(\n self,\n control: Control,\n position: [str | ControlPosition] = ControlPosition.TOP_RIGHT,\n ) -> None:\n \"\"\"Add a control to the map\n\n Args:\n control (Control): The control to be added to the map.\n position (str | ControlPosition): The position of the control.\n \"\"\"\n self.add_call(\n \"addControl\",\n control.type,\n control.to_dict(),\n ControlPosition(position).value,\n )\n\n def add_source(self, id: str, source: [Source | dict]) -> None:\n \"\"\"Add a source to the map\"\"\"\n if isinstance(source, Source):\n source = source.to_dict()\n\n self.add_call(\"addSource\", id, source)\n\n def add_layer(self, layer: [Layer | dict]) -> None:\n \"\"\"Add a layer to the map\n\n Args:\n layer (Layer | dict): The Layer to be added to the map.\n \"\"\"\n if isinstance(layer, Layer):\n layer = layer.to_dict()\n\n self.add_call(\"addLayer\", layer)\n\n def add_marker(self, marker: Marker) -> None:\n \"\"\"Add a marker to the map\n\n Args:\n marker (Marker): The marker to be added to the map.\n \"\"\"\n self.add_call(\"addMarker\", marker.to_dict())\n\n def add_popup(self, layer_id: str, prop: str) -> None:\n \"\"\"Add a popup to the map\n\n Args:\n layer_id (str): The layer to which the popup is added.\n prop (str): The property of the source to be displayed.\n \"\"\"\n self.add_call(\"addPopup\", layer_id, prop)\n\n def add_tooltip(self, layer_id: str, prop: str) -> None:\n \"\"\"Add a tooltip to the map\n\n Args:\n layer_id (str): The layer to which the tooltip is added.\n prop (str): The property of the source to be displayed.\n \"\"\"\n self.add_call(\"addTooltip\", layer_id, prop)\n\n def set_filter(self, layer_id: str, filter_: list):\n \"\"\"Update the filter of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n filter_ (list): The filter expression that is applied to the source of the layer.\n \"\"\"\n self.add_call(\"setFilter\", layer_id, filter_)\n\n def set_paint_property(self, layer_id: str, prop: str, value: any) -> None:\n \"\"\"Update the paint property of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n prop (str): The name of the paint property to be updated.\n value (any): The new value of the paint property.\n \"\"\"\n self.add_call(\"setPaintProperty\", layer_id, prop, value)\n\n def set_layout_property(self, layer_id: str, prop: str, value: any) -> None:\n \"\"\"Update a layout property of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n prop (str): The name of the layout property to be updated.\n value (any): The new value of the layout property.\n \"\"\"\n self.add_call(\"setLayoutProperty\", layer_id, prop, value)\n\n def set_data(self, source_id: str, data: dict) -> None:\n \"\"\"Update the data of a GeoJSON source\n\n Args:\n source_id (str): The name of the source to be updated.\n data (dict): The data of the source.\n \"\"\"\n self.add_call(\"setSourceData\", source_id, data)\n\n def set_visibility(self, layer_id: str, visible: bool = True) -> None:\n \"\"\"Update the visibility of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n visible (bool): Whether the layer is visible or not.\n \"\"\"\n value = \"visible\" if visible else \"none\"\n self.add_call(\"setLayoutProperty\", layer_id, \"visibility\", value)\n\n def to_html(self, **kwargs) -> str:\n \"\"\"Render to html\n\n Args:\n **kwargs (Any): Additional keyword arguments that are passed to the template.\n Currently, `style` is the only supported keyword argument.\n\n Examples:\n >>> from maplibre import Map\n\n >>> map = Map()\n >>> with open(\"/tmp/map.html\", \"w\") as f:\n ... f.write(map.to_html(style=\"height: 800px;\") # doctest: +SKIP\n \"\"\"\n js_lib = read_internal_file(\"srcjs\", \"index.js\")\n js_snippet = Template(js_template).render(data=json.dumps(self.to_dict()))\n output = Template(html_template).render(\n js=\"\\n\".join([js_lib, js_snippet]), **kwargs\n )\n return output\n
"},{"location":"api/map/#maplibre.Map.add_call","title":"add_call(method_name, *args)
","text":"Add a method call that is executed on the map instance
Parameters:
Name Type Description Default method_name
str
The name of the map method to be executed.
required *args
any
The arguments to be passed to the map method.
()
Source code in maplibre/map.py
def add_call(self, method_name: str, *args) -> None:\n \"\"\"Add a method call that is executed on the map instance\n\n Args:\n method_name (str): The name of the map method to be executed.\n *args (any): The arguments to be passed to the map method.\n \"\"\"\n # TODO: Pass as dict? {\"name\": method_name, \"args\": args}\n call = [method_name, args]\n self._message_queue.append(call)\n
"},{"location":"api/map/#maplibre.Map.add_control","title":"add_control(control, position=ControlPosition.TOP_RIGHT)
","text":"Add a control to the map
Parameters:
Name Type Description Default control
Control
The control to be added to the map.
required position
str | ControlPosition
The position of the control.
TOP_RIGHT
Source code in maplibre/map.py
def add_control(\n self,\n control: Control,\n position: [str | ControlPosition] = ControlPosition.TOP_RIGHT,\n) -> None:\n \"\"\"Add a control to the map\n\n Args:\n control (Control): The control to be added to the map.\n position (str | ControlPosition): The position of the control.\n \"\"\"\n self.add_call(\n \"addControl\",\n control.type,\n control.to_dict(),\n ControlPosition(position).value,\n )\n
"},{"location":"api/map/#maplibre.Map.add_layer","title":"add_layer(layer)
","text":"Add a layer to the map
Parameters:
Name Type Description Default layer
Layer | dict
The Layer to be added to the map.
required Source code in maplibre/map.py
def add_layer(self, layer: [Layer | dict]) -> None:\n \"\"\"Add a layer to the map\n\n Args:\n layer (Layer | dict): The Layer to be added to the map.\n \"\"\"\n if isinstance(layer, Layer):\n layer = layer.to_dict()\n\n self.add_call(\"addLayer\", layer)\n
"},{"location":"api/map/#maplibre.Map.add_marker","title":"add_marker(marker)
","text":"Add a marker to the map
Parameters:
Name Type Description Default marker
Marker
The marker to be added to the map.
required Source code in maplibre/map.py
def add_marker(self, marker: Marker) -> None:\n \"\"\"Add a marker to the map\n\n Args:\n marker (Marker): The marker to be added to the map.\n \"\"\"\n self.add_call(\"addMarker\", marker.to_dict())\n
"},{"location":"api/map/#maplibre.Map.add_popup","title":"add_popup(layer_id, prop)
","text":"Add a popup to the map
Parameters:
Name Type Description Default layer_id
str
The layer to which the popup is added.
required prop
str
The property of the source to be displayed.
required Source code in maplibre/map.py
def add_popup(self, layer_id: str, prop: str) -> None:\n \"\"\"Add a popup to the map\n\n Args:\n layer_id (str): The layer to which the popup is added.\n prop (str): The property of the source to be displayed.\n \"\"\"\n self.add_call(\"addPopup\", layer_id, prop)\n
"},{"location":"api/map/#maplibre.Map.add_source","title":"add_source(id, source)
","text":"Add a source to the map
Source code in maplibre/map.py
def add_source(self, id: str, source: [Source | dict]) -> None:\n \"\"\"Add a source to the map\"\"\"\n if isinstance(source, Source):\n source = source.to_dict()\n\n self.add_call(\"addSource\", id, source)\n
"},{"location":"api/map/#maplibre.Map.add_tooltip","title":"add_tooltip(layer_id, prop)
","text":"Add a tooltip to the map
Parameters:
Name Type Description Default layer_id
str
The layer to which the tooltip is added.
required prop
str
The property of the source to be displayed.
required Source code in maplibre/map.py
def add_tooltip(self, layer_id: str, prop: str) -> None:\n \"\"\"Add a tooltip to the map\n\n Args:\n layer_id (str): The layer to which the tooltip is added.\n prop (str): The property of the source to be displayed.\n \"\"\"\n self.add_call(\"addTooltip\", layer_id, prop)\n
"},{"location":"api/map/#maplibre.Map.set_data","title":"set_data(source_id, data)
","text":"Update the data of a GeoJSON source
Parameters:
Name Type Description Default source_id
str
The name of the source to be updated.
required data
dict
The data of the source.
required Source code in maplibre/map.py
def set_data(self, source_id: str, data: dict) -> None:\n \"\"\"Update the data of a GeoJSON source\n\n Args:\n source_id (str): The name of the source to be updated.\n data (dict): The data of the source.\n \"\"\"\n self.add_call(\"setSourceData\", source_id, data)\n
"},{"location":"api/map/#maplibre.Map.set_filter","title":"set_filter(layer_id, filter_)
","text":"Update the filter of a layer
Parameters:
Name Type Description Default layer_id
str
The name of the layer to be updated.
required filter_
list
The filter expression that is applied to the source of the layer.
required Source code in maplibre/map.py
def set_filter(self, layer_id: str, filter_: list):\n \"\"\"Update the filter of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n filter_ (list): The filter expression that is applied to the source of the layer.\n \"\"\"\n self.add_call(\"setFilter\", layer_id, filter_)\n
"},{"location":"api/map/#maplibre.Map.set_layout_property","title":"set_layout_property(layer_id, prop, value)
","text":"Update a layout property of a layer
Parameters:
Name Type Description Default layer_id
str
The name of the layer to be updated.
required prop
str
The name of the layout property to be updated.
required value
any
The new value of the layout property.
required Source code in maplibre/map.py
def set_layout_property(self, layer_id: str, prop: str, value: any) -> None:\n \"\"\"Update a layout property of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n prop (str): The name of the layout property to be updated.\n value (any): The new value of the layout property.\n \"\"\"\n self.add_call(\"setLayoutProperty\", layer_id, prop, value)\n
"},{"location":"api/map/#maplibre.Map.set_paint_property","title":"set_paint_property(layer_id, prop, value)
","text":"Update the paint property of a layer
Parameters:
Name Type Description Default layer_id
str
The name of the layer to be updated.
required prop
str
The name of the paint property to be updated.
required value
any
The new value of the paint property.
required Source code in maplibre/map.py
def set_paint_property(self, layer_id: str, prop: str, value: any) -> None:\n \"\"\"Update the paint property of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n prop (str): The name of the paint property to be updated.\n value (any): The new value of the paint property.\n \"\"\"\n self.add_call(\"setPaintProperty\", layer_id, prop, value)\n
"},{"location":"api/map/#maplibre.Map.set_visibility","title":"set_visibility(layer_id, visible=True)
","text":"Update the visibility of a layer
Parameters:
Name Type Description Default layer_id
str
The name of the layer to be updated.
required visible
bool
Whether the layer is visible or not.
True
Source code in maplibre/map.py
def set_visibility(self, layer_id: str, visible: bool = True) -> None:\n \"\"\"Update the visibility of a layer\n\n Args:\n layer_id (str): The name of the layer to be updated.\n visible (bool): Whether the layer is visible or not.\n \"\"\"\n value = \"visible\" if visible else \"none\"\n self.add_call(\"setLayoutProperty\", layer_id, \"visibility\", value)\n
"},{"location":"api/map/#maplibre.Map.to_html","title":"to_html(**kwargs)
","text":"Render to html
Parameters:
Name Type Description Default **kwargs
Any
Additional keyword arguments that are passed to the template. Currently, style
is the only supported keyword argument.
{}
Examples:
>>> from maplibre import Map\n
>>> map = Map()\n>>> with open(\"/tmp/map.html\", \"w\") as f:\n... f.write(map.to_html(style=\"height: 800px;\")\n
Source code in maplibre/map.py
def to_html(self, **kwargs) -> str:\n \"\"\"Render to html\n\n Args:\n **kwargs (Any): Additional keyword arguments that are passed to the template.\n Currently, `style` is the only supported keyword argument.\n\n Examples:\n >>> from maplibre import Map\n\n >>> map = Map()\n >>> with open(\"/tmp/map.html\", \"w\") as f:\n ... f.write(map.to_html(style=\"height: 800px;\") # doctest: +SKIP\n \"\"\"\n js_lib = read_internal_file(\"srcjs\", \"index.js\")\n js_snippet = Template(js_template).render(data=json.dumps(self.to_dict()))\n output = Template(html_template).render(\n js=\"\\n\".join([js_lib, js_snippet]), **kwargs\n )\n return output\n
"},{"location":"api/map/#maplibre.MapOptions","title":"maplibre.MapOptions
","text":" Bases: BaseModel
Map options
Note See mapOptions for more details.
Source code in maplibre/map.py
class MapOptions(BaseModel):\n \"\"\"Map options\n\n Note:\n See [mapOptions](https://maplibre.org/maplibre-gl-js/docs/API/types/maplibregl.MapOptions/) for more details.\n \"\"\"\n\n model_config = ConfigDict(\n validate_assignment=True, extra=\"forbid\", use_enum_values=False\n )\n antialias: bool = None\n attribution_control: bool = Field(None, serialization_alias=\"attributionControl\")\n bearing: int = None\n bearing_snap: int = Field(None, serialization_alias=\"bearingSnap\")\n bounds: tuple = None\n box_zoom: bool = Field(None, serialization_alias=\"boxZoom\")\n center: tuple = None\n click_tolerance: int = Field(None, serialization_alias=\"clickTolerance\")\n custom_attribution: bool = Field(None, serialization_alias=\"customAttribution\")\n double_click_zoom: bool = Field(None, serialization_alias=\"doubleClickZoom\")\n fade_duration: int = Field(None, serialization_alias=\"fadeDuration\")\n fit_bounds_options: dict = Field(None, serialization_alias=\"fitBoundsOptions\")\n hash: Union[bool, str] = None\n interactive: bool = None\n keyword: bool = None\n max_bounds: tuple = Field(None, serialization_alias=\"maxBounds\")\n max_pitch: int = Field(None, serialization_alias=\"maxPitch\")\n max_zoom: int = Field(None, serialization_alias=\"maxZoom\")\n min_pitch: int = Field(None, serialization_alias=\"minPitch\")\n min_zoom: int = Field(None, serialization_alias=\"minZoom\")\n pitch: int = None\n scroll_zoom: bool = Field(None, serialization_alias=\"scrollZoom\")\n style: Union[str, Carto, dict] = construct_carto_basemap_url(Carto.DARK_MATTER)\n zoom: int = None\n\n @field_validator(\"style\")\n def validate_style(cls, v):\n if isinstance(v, Carto):\n return construct_carto_basemap_url(v)\n\n return v\n
"},{"location":"api/map/#maplibre.MapContext","title":"maplibre.MapContext
","text":" Bases: Map
MapContext
Use this class to update a Map
instance in a Shiny app. Must be used inside an async function.
See maplibre.Map
for available methods.
Parameters:
Name Type Description Default id
string
The id of the map to be updated.
required session
Session
A Shiny session. If None
, the active session is used.
None
Source code in maplibre/mapcontext.py
class MapContext(Map):\n \"\"\"MapContext\n\n Use this class to update a `Map` instance in a Shiny app.\n Must be used inside an async function.\n\n See `maplibre.Map` for available methods.\n\n Args:\n id (string): The id of the map to be updated.\n session (Session): A Shiny session.\n If `None`, the active session is used.\n \"\"\"\n\n def __init__(self, id: str, session: Session = None) -> None:\n self.id = id\n self._session = require_active_session(session)\n self.map_options = {}\n self._message_queue = []\n\n async def __aenter__(self):\n return self\n\n async def __aexit__(self, exc_type, exc_val, exc_tb):\n await self.render()\n\n async def render(self):\n await self._session.send_custom_message(\n f\"pymaplibregl-{self.id}\", {\"id\": self.id, \"calls\": self._message_queue}\n )\n
"},{"location":"api/map/#maplibre.ipywidget.MapWidget","title":"maplibre.ipywidget.MapWidget
","text":" Bases: AnyWidget
, Map
MapWidget
Use this class to display and update maps in Jupyter Notebooks.
See maplibre.Map
for available methods.
Examples:
>>> from maplibre import MapOptions\n>>> from maplibre.ipywidget import MapWidget as Map\n>>> m = Map(MapOptions(center=(-123.13, 49.254), zoom=11, pitch=45))\n>>> m\n
Source code in maplibre/ipywidget.py
class MapWidget(AnyWidget, Map):\n \"\"\"MapWidget\n\n Use this class to display and update maps in Jupyter Notebooks.\n\n See `maplibre.Map` for available methods.\n\n Examples:\n >>> from maplibre import MapOptions\n >>> from maplibre.ipywidget import MapWidget as Map\n >>> m = Map(MapOptions(center=(-123.13, 49.254), zoom=11, pitch=45))\n >>> m # doctest: +SKIP\n \"\"\"\n\n _esm = join(Path(__file__).parent, \"srcjs\", \"ipywidget.js\")\n _css = join(Path(__file__).parent, \"srcjs\", \"maplibre-gl.css\")\n _use_message_queue = False\n _rendered = traitlets.Bool(False, config=True).tag(sync=True)\n map_options = traitlets.Dict().tag(sync=True)\n calls = traitlets.List().tag(sync=True)\n height = traitlets.Union([traitlets.Int(), traitlets.Unicode()]).tag(sync=True)\n lng_lat = traitlets.Dict().tag(sync=True)\n\n def __init__(self, map_options=MapOptions(), **kwargs) -> None:\n self.calls = []\n AnyWidget.__init__(self, **kwargs)\n Map.__init__(self, map_options, **kwargs)\n\n @traitlets.default(\"height\")\n def _default_height(self):\n return \"400px\"\n\n @traitlets.validate(\"height\")\n def _validate_height(self, proposal):\n height = proposal[\"value\"]\n if isinstance(height, int):\n return f\"{height}px\"\n\n return height\n\n @traitlets.observe(\"_rendered\")\n def _on_rendered(self, change):\n self.send({\"calls\": self._message_queue, \"msg\": \"init\"})\n self._message_queue = []\n\n def use_message_queue(self, value: bool = True) -> None:\n self._use_message_queue = value\n\n def add_call(self, method_name: str, *args) -> None:\n call = [method_name, args]\n if not self._rendered:\n if not self._use_message_queue:\n self.calls = self.calls + [call]\n return\n\n self._message_queue.append(call)\n return\n\n self.send({\"calls\": [call], \"msg\": \"custom call\"})\n
"},{"location":"api/sources/","title":"Sources","text":""},{"location":"api/sources/#maplibre.sources","title":"maplibre.sources
","text":""},{"location":"api/sources/#maplibre.sources.GeoJSONSource","title":"GeoJSONSource
","text":" Bases: Source
GeoJSON Source
Examples:
>>> from maplibre.sources import GeoJSONSource\n
>>> source = GeoJSONSource(data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\")\n
Source code in maplibre/sources.py
class GeoJSONSource(Source):\n \"\"\"GeoJSON Source\n\n Examples:\n >>> from maplibre.sources import GeoJSONSource\n\n >>> source = GeoJSONSource(data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\")\n \"\"\"\n\n data: Union[str, dict]\n attribution: str = None\n buffer: int = None\n cluster: bool = None\n cluster_max_zoom: int = Field(None, serialization_alias=\"clusterMaxZoom\")\n cluster_min_points: int = Field(None, serialization_alias=\"clusterMinPoints\")\n cluster_properties: dict = Field(None, serialization_alias=\"clusterProperties\")\n cluster_radius: int = Field(None, serialization_alias=\"clusterRadius\")\n filter: list = None\n generate_id: bool = Field(None, serialization_alias=\"generateId\")\n line_metrics: bool = Field(None, serialization_alias=\"lineMetrics\")\n maxzoom: int = None\n promote_id: Union[str, dict] = Field(None, serialization_alias=\"promoteId\")\n tolerance: float = None\n\n @computed_field\n @property\n def type(self) -> str:\n return SourceType.GEOJSON.value\n
"},{"location":"api/sources/#maplibre.sources.RasterTileSource","title":"RasterTileSource
","text":" Bases: Source
Raster tile source
Examples:
>>> from maplibre.sources import RasterTileSource\n>>> raster_source = RasterTileSource(\n... tiles=[\"https://tile.openstreetmap.org/{z}/{x}/{y}.png\"],\n... tile_size=256,\n... min_zoom=0,\n... max_zoom=19,\n... )\n
Source code in maplibre/sources.py
class RasterTileSource(Source):\n \"\"\"Raster tile source\n\n Examples:\n >>> from maplibre.sources import RasterTileSource\n >>> raster_source = RasterTileSource(\n ... tiles=[\"https://tile.openstreetmap.org/{z}/{x}/{y}.png\"],\n ... tile_size=256,\n ... min_zoom=0,\n ... max_zoom=19,\n ... )\n \"\"\"\n\n attribution: str = None\n bounds: tuple = None\n max_zoom: int = Field(None, serialization_alias=\"maxzoom\")\n min_zoom: int = Field(None, serialization_alias=\"minzoom\")\n scheme: str = None\n tile_size: int = Field(None, serialization_alias=\"tileSize\")\n tiles: Union[tuple, list] = None\n url: str = None\n volatile: bool = None\n\n @computed_field\n @property\n def type(self) -> str:\n return SourceType.RASTER.value\n
"},{"location":"api/sources/#maplibre.sources.SourceType","title":"SourceType
","text":" Bases: Enum
Source types
Source code in maplibre/sources.py
class SourceType(Enum):\n \"\"\"Source types\"\"\"\n\n RASTER = \"raster\"\n VECTOR = \"vector\"\n RASTER_DEM = \"raster-dem\"\n GEOJSON = \"geojson\"\n IMAGE = \"image\"\n VIDEO = \"video\"\n
"},{"location":"examples/3d_indoor_mapping/","title":"3D Indoor mapping","text":"import sys\nimport webbrowser\n\nfrom maplibre import Layer, LayerType, Map, MapOptions\nfrom maplibre.basemaps import background\nfrom maplibre.sources import GeoJSONSource, RasterTileSource\n\nfile_name = \"/tmp/pymaplibregl_temp.html\"\n\nFLOORPLAN_SOURCE_ID = \"floorplan\"\n\nraster_source = RasterTileSource(\n tiles=[\"https://tile.openstreetmap.org/{z}/{x}/{y}.png\"],\n tile_size=256,\n min_zoom=0,\n max_zoom=19,\n)\n\nraster_layer = Layer(type=LayerType.RASTER, source=raster_source)\n\nfloorplan_source = GeoJSONSource(\n data=\"https://maplibre.org/maplibre-gl-js/docs/assets/indoor-3d-map.geojson\"\n)\n\nfloorplan_layer = Layer(\n type=LayerType.FILL_EXTRUSION,\n id=\"floorplan\",\n source=FLOORPLAN_SOURCE_ID,\n paint={\n \"fill-extrusion-color\": [\"get\", \"color\"],\n \"fill-extrusion-height\": [\"get\", \"height\"],\n \"fill-extrusion-base\": [\"get\", \"base_height\"],\n \"fill-extrusion-opacity\": 0.5,\n },\n)\n\nmap_options = MapOptions(\n style=background(\"yellow\"),\n center=(-87.61694, 41.86625),\n zoom=17,\n pitch=40,\n bearing=20,\n antialias=True,\n)\n\n\ndef create_map():\n m = Map(map_options)\n m.add_layer(raster_layer)\n m.add_source(FLOORPLAN_SOURCE_ID, floorplan_source)\n m.add_layer(floorplan_layer)\n return m\n\n\nif __name__ == \"__main__\":\n m = create_map()\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n\n with open(file_name, \"w\") as f:\n f.write(m.to_html())\n\n webbrowser.open(file_name)\n
Run example:
poetry run python docs/examples/3d_indoor_mapping/app.py\n
"},{"location":"examples/airports/","title":"Airport markers","text":"import pandas as pd\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.basemaps import Carto\nfrom maplibre.controls import Marker, MarkerOptions, Popup, PopupOptions\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.utils import GeometryType, df_to_geojson\nfrom shiny import App, ui\n\nBOUNDS = (-8.92242886, 43.30508298, 13.76496714, 59.87668996)\n\nairports_data = pd.read_json(\n \"https://github.com/visgl/deck.gl-data/raw/master/examples/line/airports.json\"\n)\n\n\ndef get_color(airport_type: str) -> str:\n color = \"darkblue\"\n if airport_type == \"mid\":\n color = \"darkred\"\n elif airport_type == \"major\":\n color = \"darkgreen\"\n\n return color\n\n\ngeojson = df_to_geojson(\n airports_data,\n \"coordinates\",\n GeometryType.POINT,\n properties=[\"type\", \"name\", \"abbrev\"],\n)\n\nairport_circles = Layer(\n type=LayerType.CIRCLE,\n source=GeoJSONSource(data=geojson),\n paint={\n \"circle-color\": [\n \"match\",\n [\"get\", \"type\"],\n \"mid\",\n \"darkred\",\n \"major\",\n \"darkgreen\",\n \"darkblue\",\n ],\n \"circle_radius\": 10,\n \"circle-opacity\": 0.3,\n },\n)\n\nmap_options = MapOptions(\n style=Carto.POSITRON,\n bounds=BOUNDS,\n fit_bounds_options={\"padding\": 20},\n hash=True,\n)\n\npopup_options = PopupOptions(close_button=False)\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Airports\"),\n output_maplibregl(\"maplibre\", height=600),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = Map(map_options)\n for _, r in airports_data.iterrows():\n marker = Marker(\n lng_lat=r[\"coordinates\"],\n options=MarkerOptions(color=get_color(r[\"type\"])),\n popup=Popup(\n text=r[\"name\"],\n options=popup_options,\n ),\n )\n m.add_marker(marker)\n m.add_layer(airport_circles)\n return m\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n app.run()\n
Run example:
poetry run uvicorn docs.examples.airports.app:app --reload\n
"},{"location":"examples/custom_basemap/","title":"Custom basemap","text":"import sys\nimport webbrowser\n\nfrom maplibre import Layer, LayerType, Map, MapOptions\nfrom maplibre.basemaps import construct_basemap_style\nfrom maplibre.sources import GeoJSONSource\n\nfile_name = \"/tmp/pymaplibregl_temp.html\"\n\nbg_layer = Layer(\n type=LayerType.BACKGROUND,\n id=\"background\",\n source=None,\n paint={\"background-color\": \"darkblue\", \"background-opacity\": 0.8},\n)\n\ncountries_source = GeoJSONSource(\n data=\"https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_110m_admin_0_countries.geojson\"\n)\n\nlines_layer = Layer(\n type=LayerType.LINE,\n source=\"countries\",\n paint={\"line-color\": \"white\", \"line-width\": 1.5},\n)\n\npolygons_layer = Layer(\n type=LayerType.FILL,\n source=\"countries\",\n paint={\"fill-color\": \"darkred\", \"fill-opacity\": 0.8},\n)\n\ncustom_basemap = construct_basemap_style(\n layers=[bg_layer, polygons_layer, lines_layer],\n sources={\"countries\": countries_source},\n)\n\n\nmap_options = MapOptions(\n style=custom_basemap,\n center=(0, 0),\n zoom=2,\n)\n\n\ndef create_map():\n m = Map(map_options)\n m.add_layer(\n Layer(\n type=LayerType.CIRCLE,\n id=\"earthquakes\",\n source=GeoJSONSource(\n data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\"\n ),\n paint={\"circle-color\": \"yellow\", \"circle-radius\": 5},\n )\n )\n m.add_popup(\"earthquakes\", \"mag\")\n return m\n\n\nif __name__ == \"__main__\":\n m = create_map()\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n\n with open(file_name, \"w\") as f:\n f.write(m.to_html())\n\n webbrowser.open(file_name)\n
Run example:
poetry run python docs/examples/custom_basemap/app.py\n
"},{"location":"examples/earthquake_clusters/","title":"Earthquake clusters","text":"import sys\n\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.basemaps import Carto\nfrom maplibre.sources import GeoJSONSource\nfrom shiny import App, reactive, ui\n\nEARTHQUAKE_SOURCE = \"earthquakes\"\nEARTHQUAKE_CIRCLES = \"earthquake-circles\"\nEARTHQUAKE_CLUSTERS = \"earthquake-clusters\"\nEARTHQUAKE_LABELS = \"earthquake-labels\"\n\nCENTER = (-118.0931, 33.78615)\n\nearthquakes_source = GeoJSONSource(\n data=\"https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson\",\n cluster=True,\n cluster_radius=50,\n cluster_min_points=2,\n cluster_max_zoom=14,\n cluster_properties={\n \"maxMag\": [\"max\", [\"get\", \"mag\"]],\n \"minMag\": [\"min\", [\"get\", \"mag\"]],\n },\n)\n\nearthquake_circles = Layer(\n type=LayerType.CIRCLE,\n id=EARTHQUAKE_CIRCLES,\n source=EARTHQUAKE_SOURCE,\n paint={\"circle-color\": \"darkblue\"},\n filter=[\"!\", [\"has\", \"point_count\"]],\n)\n\nearthquake_clusters = Layer(\n type=LayerType.CIRCLE,\n id=EARTHQUAKE_CLUSTERS,\n source=EARTHQUAKE_SOURCE,\n filter=[\"has\", \"point_count\"],\n paint={\n \"circle-color\": [\n \"step\",\n [\"get\", \"point_count\"],\n \"#51bbd6\",\n 100,\n \"#f1f075\",\n 750,\n \"#f28cb1\",\n ],\n \"circle-radius\": [\"step\", [\"get\", \"point_count\"], 20, 100, 30, 750, 40],\n },\n)\n\nearthquake_labels = Layer(\n type=LayerType.SYMBOL,\n id=\"text\",\n source=EARTHQUAKE_SOURCE,\n filter=[\"has\", \"point_count\"],\n layout={\n \"text-field\": [\"get\", \"point_count_abbreviated\"],\n \"text-size\": 12,\n },\n)\n\nmap_options = MapOptions(style=Carto.POSITRON, center=CENTER, zoom=3, hash=True)\n\n\ndef create_map() -> Map:\n m = Map(map_options)\n m.add_source(EARTHQUAKE_SOURCE, earthquakes_source)\n m.add_layer(earthquake_clusters)\n m.add_layer(earthquake_circles)\n m.add_tooltip(EARTHQUAKE_CLUSTERS, \"maxMag\")\n m.add_layer(earthquake_labels)\n return m\n\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Earthquakes Cluster\"),\n output_maplibregl(\"maplibre\", height=500),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n return create_map()\n\n @reactive.Effect\n @reactive.event(input.maplibre)\n async def result():\n print(f\"result: {input.maplibre()}\")\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n with open(file_name, \"w\") as f:\n f.write(create_map().to_html())\n else:\n app.run()\n
Run example:
poetry run uvicorn docs.examples.earthquake_clusters.app:app --reload\n
"},{"location":"examples/every_person_in_manhattan/","title":"Every person in manhattan","text":"import json\nimport sys\n\nimport pandas as pd\nimport shapely\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.basemaps import Carto\nfrom maplibre.controls import ScaleControl\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.utils import df_to_geojson\nfrom shiny import App, reactive, ui\n\nMALE_COLOR = \"rgb(0, 128, 255)\"\nFEMALE_COLOR = \"rgb(255, 0, 128)\"\nLAYER_ID = \"every-person-in-manhattan-circles\"\nCIRCLE_RADIUS = 2\n\npoint_data = pd.read_json(\n \"https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/scatterplot/manhattan.json\"\n)\n\npoint_data.columns = [\"lng\", \"lat\", \"sex\"]\n\nevery_person_in_manhattan_source = GeoJSONSource(\n data=df_to_geojson(point_data, properties=[\"sex\"]),\n)\n\nbbox = shapely.bounds(\n shapely.from_geojson(json.dumps(every_person_in_manhattan_source.data))\n)\n\nevery_person_in_manhattan_circles = Layer(\n type=LayerType.CIRCLE,\n id=LAYER_ID,\n source=every_person_in_manhattan_source,\n paint={\n \"circle-color\": [\"match\", [\"get\", \"sex\"], 1, MALE_COLOR, FEMALE_COLOR],\n \"circle-radius\": CIRCLE_RADIUS,\n },\n)\n\nmap_options = MapOptions(\n style=Carto.POSITRON,\n bounds=tuple(bbox),\n fit_bounds_options={\"padding\": 20},\n)\n\n\ndef create_map() -> Map:\n m = Map(map_options)\n m.add_control(ScaleControl(), position=\"bottom-left\")\n m.add_layer(every_person_in_manhattan_circles)\n return m\n\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Every Person in Manhattan\"),\n output_maplibregl(\"maplibre\", height=600),\n ui.input_slider(\"radius\", \"Radius\", value=CIRCLE_RADIUS, min=1, max=5),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n return create_map()\n\n @reactive.Effect\n @reactive.event(input.radius, ignore_init=True)\n async def radius():\n async with MapContext(\"maplibre\") as m:\n m.set_paint_property(LAYER_ID, \"circle-radius\", input.radius())\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n with open(file_name, \"w\") as f:\n f.write(create_map().to_html())\n else:\n app.run()\n
Run example:
poetry run uvicorn docs.examples.every_person_in_manhattan.app:app --reload\n
"},{"location":"examples/geopandas/","title":"GeoPandas","text":"See example in action
import sys\nimport webbrowser\n\nfrom maplibre import Layer, LayerType, Map, MapOptions\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.utils import geopandas_to_geojson\n\nimport geopandas as gpd\n\nfile_name = \"/tmp/pymaplibregl_temp.html\"\nLAYER_ID = \"wilderness\"\n\ndf_geo = gpd.read_file(\n \"zip+https://github.com/Toblerity/Fiona/files/11151652/coutwildrnp.zip\"\n)\n\nwilderness_source = GeoJSONSource(data=geopandas_to_geojson(df_geo))\n\nwilderness_layer = Layer(\n type=LayerType.FILL,\n id=LAYER_ID,\n source=wilderness_source,\n paint={\"fill-color\": \"darkred\", \"fill-opacity\": 0.5},\n)\n\nmap_options = MapOptions(bounds=df_geo.total_bounds)\n\n\ndef create_map():\n m = Map(map_options)\n m.add_layer(wilderness_layer)\n m.add_tooltip(LAYER_ID, \"NAME\")\n return m\n\n\nif __name__ == \"__main__\":\n m = create_map()\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n\n with open(file_name, \"w\") as f:\n f.write(m.to_html())\n\n webbrowser.open(file_name)\n
Run example:
poetry run python docs/examples/geopandas/app.py\n
"},{"location":"examples/road_safety/","title":"UK Road Safety","text":"import sys\nimport webbrowser\n\nimport h3\nimport pandas as pd\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.sources import GeoJSONSource\nfrom maplibre.utils import df_to_geojson\nfrom shiny import App, reactive, ui\n\nRESOLUTION = 7\nCOLORS = (\n \"lightblue\",\n \"turquoise\",\n \"lightgreen\",\n \"yellow\",\n \"orange\",\n \"darkred\",\n)\n\nroad_safety = pd.read_csv(\n \"https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv\"\n).dropna()\n\n\ndef create_h3_grid(res=RESOLUTION) -> dict:\n road_safety[\"h3\"] = road_safety.apply(\n lambda x: h3.geo_to_h3(x[\"lat\"], x[\"lng\"], resolution=res), axis=1\n )\n df = road_safety.groupby(\"h3\").h3.agg(\"count\").to_frame(\"count\").reset_index()\n df[\"hexagon\"] = df.apply(\n lambda x: [h3.h3_to_geo_boundary(x[\"h3\"], geo_json=True)], axis=1\n )\n df[\"color\"] = pd.cut(\n df[\"count\"],\n bins=len(COLORS),\n labels=COLORS,\n )\n return df_to_geojson(\n df, \"hexagon\", geometry_type=\"Polygon\", properties=[\"count\", \"color\"]\n )\n\n\nsource = GeoJSONSource(data=create_h3_grid())\n\n\ndef create_map() -> Map:\n m = Map(MapOptions(center=(-1.415727, 52.232395), zoom=7, pitch=40, bearing=-27))\n m.add_layer(\n Layer(\n id=\"road-safety\",\n type=LayerType.FILL_EXTRUSION,\n source=source,\n paint={\n \"fill-extrusion-color\": [\"get\", \"color\"],\n \"fill-extrusion-opacity\": 0.7,\n \"fill-extrusion-height\": [\"*\", 100, [\"get\", \"count\"]],\n },\n )\n )\n m.add_tooltip(\"road-safety\", \"count\")\n return m\n\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Road safety in UK\"),\n output_maplibregl(\"mapylibre\", height=700),\n ui.input_slider(\"res\", \"Resolution\", min=4, max=8, step=1, value=RESOLUTION),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def mapylibre():\n return create_map()\n\n @reactive.Effect\n @reactive.event(input.res, ignore_init=True)\n async def resolution():\n async with MapContext(\"mapylibre\") as m:\n with ui.Progress() as p:\n p.set(message=\"H3 calculation in progress\")\n m.set_data(\"road-safety\", create_h3_grid(input.res()))\n p.set(1, message=\"Calculation finished\")\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n filename = sys.argv[1] if len(sys.argv) == 2 else \"/tmp/road_safety.html\"\n with open(filename, \"w\") as f:\n m = create_map()\n f.write(m.to_html(style=\"height: 700px;\"))\n\n webbrowser.open(filename)\n
Run example:
poetry run uvicorn docs.examples.road_safety.app:app --reload\n
"},{"location":"examples/vancouver_blocks/","title":"Vancouver property value","text":"import sys\n\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.basemaps import Carto\nfrom maplibre.controls import ScaleControl\nfrom maplibre.sources import GeoJSONSource\nfrom shiny import App, reactive, ui\n\nSOURCE_ID = \"vancouver-blocks\"\nLAYER_ID_LINES = \"vancouver-blocks-lines\"\nLAYER_ID_FILL = \"vancouver-blocks-fill-extrusion\"\nMAX_FILTER_VALUE = 1000000\n\nvancouver_blocks_source = GeoJSONSource(\n data=\"https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/geojson/vancouver-blocks.json\"\n)\n\nvancouver_blocks_lines = Layer(\n type=LayerType.LINE,\n id=LAYER_ID_LINES,\n source=SOURCE_ID,\n paint={\n \"line-color\": \"white\",\n \"line-width\": 2,\n },\n)\n\nvancouver_blocks_fill = Layer(\n type=LayerType.FILL_EXTRUSION,\n id=LAYER_ID_FILL,\n source=SOURCE_ID,\n paint={\n \"fill-extrusion-color\": {\n \"property\": \"valuePerSqm\",\n \"stops\": [\n [0, \"grey\"],\n [1000, \"yellow\"],\n [5000, \"orange\"],\n [10000, \"darkred\"],\n [50000, \"lightblue\"],\n ],\n },\n \"fill-extrusion-height\": [\"*\", 10, [\"sqrt\", [\"get\", \"valuePerSqm\"]]],\n \"fill-extrusion-opacity\": 0.9,\n },\n)\n\nmap_options = MapOptions(\n style=Carto.DARK_MATTER,\n center=(-123.13, 49.254),\n zoom=11,\n pitch=45,\n bearing=0,\n)\n\n\ndef create_map() -> Map:\n m = Map(map_options)\n m.add_control(ScaleControl(), position=\"bottom-left\")\n m.add_source(SOURCE_ID, vancouver_blocks_source)\n m.add_layer(vancouver_blocks_lines)\n m.add_layer(vancouver_blocks_fill)\n m.add_tooltip(LAYER_ID_FILL, \"valuePerSqm\")\n return m\n\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Vancouver Property Value\"),\n ui.div(\n \"Height of polygons - average property value per square meter of lot\",\n style=\"padding: 10px;\",\n ),\n output_maplibregl(\"maplibre\", height=600),\n ui.input_select(\n \"filter\",\n \"max property value per square meter\",\n choices=[0, 1000, 5000, 10000, 50000, 100000, MAX_FILTER_VALUE],\n selected=MAX_FILTER_VALUE,\n ),\n ui.input_checkbox_group(\n \"layers\",\n \"Layers\",\n choices=[LAYER_ID_FILL, LAYER_ID_LINES],\n selected=[LAYER_ID_FILL, LAYER_ID_LINES],\n ),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def maplibre():\n m = create_map()\n return m\n\n @reactive.Effect\n @reactive.event(input.filter)\n async def filter():\n async with MapContext(\"maplibre\") as m:\n filter_ = [\"<=\", [\"get\", \"valuePerSqm\"], int(input.filter())]\n m.set_filter(LAYER_ID_FILL, filter_)\n\n @reactive.Effect\n @reactive.event(input.layers)\n async def layers():\n visible_layers = input.layers()\n async with MapContext(\"maplibre\") as m:\n for layer in [LAYER_ID_FILL, LAYER_ID_LINES]:\n m.set_visibility(layer, layer in visible_layers)\n\n\napp = App(app_ui, server)\n\nif __name__ == \"__main__\":\n if len(sys.argv) == 2:\n file_name = sys.argv[1]\n m = create_map()\n with open(file_name, \"w\") as f:\n f.write(m.to_html())\n else:\n app.run()\n
Run example:
poetry run uvicorn docs.examples.vancouver_blocks.app:app --reload\n
"},{"location":"examples/where_is_the_iss/","title":"Where is the ISS","text":"import requests\nfrom maplibre import (\n Layer,\n LayerType,\n Map,\n MapContext,\n MapOptions,\n output_maplibregl,\n render_maplibregl,\n)\nfrom maplibre.sources import GeoJSONSource\nfrom shiny import App, reactive, ui\n\nMAX_FEATURES = 30\nSOURCE_ID_ISS_POSITION = \"iss_position\"\nSOURCE_ID_ISS_LAST_POSITIONS = \"iss-last-positions\"\n\n\ndef where_is_the_iss() -> tuple:\n r = requests.get(\"https://api.wheretheiss.at/v1/satellites/25544\").json()\n return (r[\"longitude\"], r[\"latitude\"])\n\n\ndef create_feature(lng_lat: tuple) -> dict:\n return {\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": lng_lat,\n },\n \"properties\": {\"coords\": \", \".join(map(str, lng_lat))},\n }\n\n\nlng_lat = where_is_the_iss()\nfeature = create_feature(where_is_the_iss())\nfeature_collection = {\"type\": \"FeatureCollection\", \"features\": [feature]}\n\napp_ui = ui.page_fluid(\n ui.panel_title(\"Where is the ISS\"),\n ui.div(\"Click on Update to get the current position of the ISS.\"),\n ui.div(\n \"The yellow dots show the positions before. Hover the blue dot to display the coordinates.\"\n ),\n output_maplibregl(\"mapylibre\", height=600),\n ui.input_action_button(\"update\", \"Update\"),\n)\n\n\ndef server(input, output, session):\n @render_maplibregl\n def mapylibre():\n m = Map(MapOptions(center=lng_lat, zoom=3))\n m.set_paint_property(\"water\", \"fill-color\", \"darkblue\")\n m.add_source(\n SOURCE_ID_ISS_LAST_POSITIONS, GeoJSONSource(data=feature_collection)\n )\n m.add_layer(\n Layer(\n type=LayerType.CIRCLE,\n source=SOURCE_ID_ISS_LAST_POSITIONS,\n paint={\"circle-color\": \"yellow\", \"circle-radius\": 5},\n ),\n )\n m.add_source(SOURCE_ID_ISS_POSITION, GeoJSONSource(data=feature))\n m.add_layer(\n Layer(\n type=LayerType.CIRCLE,\n id=\"iss-position\",\n source=SOURCE_ID_ISS_POSITION,\n paint={\"circle-color\": \"lightblue\", \"circle-radius\": 7},\n )\n )\n m.add_tooltip(\"iss-position\", \"coords\")\n return m\n\n @reactive.Effect\n @reactive.event(input.update)\n async def update():\n print(\"Fetching new position\")\n lng_lat = where_is_the_iss()\n print(lng_lat)\n if len(feature_collection[\"features\"]) == MAX_FEATURES:\n feature_collection[\"features\"] = []\n\n async with MapContext(\"mapylibre\") as m:\n feature = create_feature(lng_lat)\n m.set_data(SOURCE_ID_ISS_POSITION, feature)\n feature_collection[\"features\"].append(feature)\n m.set_data(SOURCE_ID_ISS_LAST_POSITIONS, feature_collection)\n m.add_call(\"flyTo\", {\"center\": lng_lat, \"speed\": 0.5})\n\n\napp = App(app_ui, server)\n
Run example:
poetry run uvicorn docs.examples.where_is_the_iss.app:app --reload\n
"}]}
\ No newline at end of file
diff --git a/sitemap.xml.gz b/sitemap.xml.gz
index 41313698..653de036 100644
Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ