geoai-py 0.11.1__py2.py3-none-any.whl → 0.12.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1502 @@
1
+ from typing import Any, Dict, List, Optional, Union
2
+
3
+ import leafmap.maplibregl as leafmap
4
+ from strands import tool
5
+
6
+
7
+ class MapSession:
8
+ """Manages a leafmap session with map instance."""
9
+
10
+ def __init__(self, m: Optional[leafmap.Map] = None) -> None:
11
+ """Initialize map session.
12
+
13
+ Args:
14
+ m: Optional existing map instance. If None, creates a default map.
15
+ """
16
+ # allow user to pass a map, otherwise create a default
17
+ self.m: leafmap.Map = m or leafmap.Map(style="liberty", projection="globe")
18
+
19
+
20
+ class MapTools:
21
+ """Collection of tools for interacting with leafmap instances."""
22
+
23
+ def __init__(self, session: Optional[MapSession] = None) -> None:
24
+ """Initialize map tools.
25
+
26
+ Args:
27
+ session: Optional MapSession instance. If None, creates a default session.
28
+ """
29
+ self.session: MapSession = session or MapSession()
30
+
31
+ @tool(
32
+ description="Create or reset a Leafmap map with optional center/zoom and basemap."
33
+ )
34
+ def create_map(
35
+ self,
36
+ center_lat: float = 20.0,
37
+ center_lon: float = 0.0,
38
+ zoom: int = 2,
39
+ style: str = "liberty",
40
+ projection: str = "globe",
41
+ use_message_queue: bool = True,
42
+ ) -> str:
43
+ """Create or reset a Leafmap map with specified parameters.
44
+
45
+ Args:
46
+ center_lat: Latitude for map center (default: 20.0).
47
+ center_lon: Longitude for map center (default: 0.0).
48
+ zoom: Initial zoom level (default: 2).
49
+ style: Map style name (default: "liberty").
50
+ projection: Map projection (default: "globe").
51
+ use_message_queue: Whether to use message queue (default: True).
52
+
53
+ Returns:
54
+ Confirmation message.
55
+ """
56
+ self.session.m = leafmap.Map(
57
+ center=[center_lon, center_lat],
58
+ zoom=zoom,
59
+ style=style,
60
+ projection=projection,
61
+ use_message_queue=use_message_queue,
62
+ )
63
+ self.session.m.create_container()
64
+ return "Map created."
65
+
66
+ @tool(description="Add a basemap by name")
67
+ def add_basemap(self, name: str) -> str:
68
+ """Add a basemap to the map by name.
69
+
70
+ Args:
71
+ name: Name of the basemap to add.
72
+
73
+ Returns:
74
+ Confirmation message with basemap name.
75
+ """
76
+ self.session.m.add_basemap(name)
77
+ return f"Basemap added: {name}"
78
+
79
+ @tool(description="Add a vector dataset (GeoJSON, Shapefile, etc.)")
80
+ def add_vector(self, data: str, name: Optional[str] = None) -> str:
81
+ """Add a vector dataset to the map.
82
+
83
+ Args:
84
+ data: Path or URL to the vector data file.
85
+ name: Optional name for the layer.
86
+
87
+ Returns:
88
+ Confirmation message with layer name.
89
+ """
90
+ self.session.m.add_vector(data=data, name=name)
91
+ return f"Vector added: {name}"
92
+
93
+ @tool(description="Fly to a specific location")
94
+ def fly_to(self, longitude: float, latitude: float, zoom: int = 12) -> str:
95
+ """Fly to a specific geographic location.
96
+
97
+ Args:
98
+ longitude: Target longitude coordinate.
99
+ latitude: Target latitude coordinate.
100
+ zoom: Zoom level for the target location (default: 12).
101
+
102
+ Returns:
103
+ Confirmation message with coordinates and zoom level.
104
+ """
105
+ self.session.m.fly_to(longitude, latitude, zoom)
106
+ return f"Flown to: {longitude}, {latitude}, zoom {zoom}"
107
+
108
+ @tool(description="Add Cloud Optimized GeoTIFF (COG) to the map")
109
+ def add_cog_layer(
110
+ self,
111
+ url: str,
112
+ name: Optional[str] = None,
113
+ attribution: str = "TiTiler",
114
+ opacity: float = 1.0,
115
+ visible: bool = True,
116
+ bands: Optional[List[int]] = None,
117
+ nodata: Optional[Union[int, float]] = 0,
118
+ titiler_endpoint: str = "https://giswqs-titiler-endpoint.hf.space",
119
+ ) -> str:
120
+ """Add a Cloud Optimized GeoTIFF (COG) layer to the map.
121
+
122
+ Args:
123
+ url: URL to the COG file.
124
+ name: Optional name for the layer.
125
+ attribution: Attribution text (default: "TiTiler").
126
+ opacity: Layer opacity from 0.0 to 1.0 (default: 1.0).
127
+ visible: Whether the layer is initially visible (default: True).
128
+ bands: Optional list of band indices to display.
129
+ nodata: No data value (default: 0).
130
+ titiler_endpoint: TiTiler endpoint URL (default: "https://giswqs-titiler-endpoint.hf.space").
131
+
132
+ Returns:
133
+ Confirmation message with COG URL.
134
+ """
135
+ self.session.m.add_cog_layer(
136
+ url, name, attribution, opacity, visible, bands, nodata, titiler_endpoint
137
+ )
138
+ return f"COG layer added: {url}"
139
+
140
+ @tool(description="Remove a layer by name")
141
+ def remove_layer(self, name: str) -> str:
142
+ """Remove a layer from the map by name.
143
+
144
+ Args:
145
+ name: Name of the layer to remove.
146
+
147
+ Returns:
148
+ Confirmation message with removed layer name.
149
+ """
150
+ layer_names = self.session.m.get_layer_names()
151
+ if name in layer_names:
152
+ self.session.m.remove_layer(name)
153
+ return f"Removed: {name}"
154
+ else:
155
+ for layer_name in layer_names:
156
+ if name.lower() in layer_name.lower():
157
+ self.session.m.remove_layer(layer_name)
158
+ return f"Removed: {layer_name}"
159
+ return f"Layer {name} not found"
160
+
161
+ @tool(description="Add 3D buildings from Overture Maps to the map")
162
+ def add_overture_3d_buildings(
163
+ self,
164
+ release: Optional[str] = None,
165
+ style: Optional[Dict[str, Any]] = None,
166
+ values: Optional[List[int]] = None,
167
+ colors: Optional[List[str]] = None,
168
+ visible: bool = True,
169
+ opacity: float = 1.0,
170
+ tooltip: bool = True,
171
+ template: str = "simple",
172
+ fit_bounds: bool = False,
173
+ **kwargs: Any,
174
+ ) -> None:
175
+ """Add 3D buildings from Overture Maps to the map.
176
+
177
+ Args:
178
+ release (Optional[str], optional): The release date of the Overture Maps data.
179
+ Defaults to the latest release. For more info, see
180
+ https://github.com/OvertureMaps/overture-tiles.
181
+ style (Optional[Dict[str, Any]], optional): The style dictionary for
182
+ the buildings. Defaults to None.
183
+ values (Optional[List[int]], optional): List of height values for
184
+ color interpolation. Defaults to None.
185
+ colors (Optional[List[str]], optional): List of colors corresponding
186
+ to the height values. Defaults to None.
187
+ visible (bool, optional): Whether the buildings layer is visible.
188
+ Defaults to True.
189
+ opacity (float, optional): The opacity of the buildings layer.
190
+ Defaults to 1.0.
191
+ tooltip (bool, optional): Whether to show tooltips on the buildings.
192
+ Defaults to True.
193
+ template (str, optional): The template for the tooltip. It can be
194
+ "simple" or "all". Defaults to "simple".
195
+ fit_bounds (bool, optional): Whether to fit the map bounds to the
196
+ buildings layer. Defaults to False.
197
+
198
+ Raises:
199
+ ValueError: If the length of values and colors lists are not the same.
200
+ """
201
+ self.session.m.add_overture_3d_buildings(
202
+ release=release,
203
+ style=style,
204
+ values=values,
205
+ colors=colors,
206
+ visible=visible,
207
+ opacity=opacity,
208
+ tooltip=tooltip,
209
+ template=template,
210
+ fit_bounds=fit_bounds,
211
+ **kwargs,
212
+ )
213
+ return f"Overture 3D buildings added: {release}"
214
+
215
+ @tool(description="Set the pitch of the map")
216
+ def set_pitch(self, pitch: float) -> None:
217
+ """
218
+ Sets the pitch of the map.
219
+
220
+ This function sets the pitch of the map to the specified value. The pitch is the
221
+ angle of the camera measured in degrees where 0 is looking straight down, and 60 is
222
+ looking towards the horizon. Additional keyword arguments can be provided to control
223
+ the pitch. For more information, see https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#setpitch
224
+
225
+ Args:
226
+ pitch (float): The pitch value to set.
227
+ **kwargs (Any): Additional keyword arguments to control the pitch.
228
+
229
+ Returns:
230
+ None
231
+ """
232
+ self.session.m.set_pitch(pitch=pitch)
233
+ return f"Map pitched to: {pitch}"
234
+
235
+ @tool
236
+ def add_draw_control(
237
+ self,
238
+ options: Optional[Dict[str, Any]] = None,
239
+ controls: Optional[Dict[str, Any]] = None,
240
+ position: str = "top-right",
241
+ geojson: Optional[Dict[str, Any]] = None,
242
+ **kwargs: Any,
243
+ ) -> None:
244
+ """
245
+ Adds a drawing control to the map.
246
+
247
+ This method enables users to add interactive drawing controls to the map,
248
+ allowing for the creation, editing, and deletion of geometric shapes on
249
+ the map. The options, position, and initial GeoJSON can be customized.
250
+
251
+ Args:
252
+ options (Optional[Dict[str, Any]]): Configuration options for the
253
+ drawing control. Defaults to None.
254
+ controls (Optional[Dict[str, Any]]): The drawing controls to enable.
255
+ Can be one or more of the following: 'polygon', 'line_string',
256
+ 'point', 'trash', 'combine_features', 'uncombine_features'.
257
+ Defaults to None.
258
+ position (str): The position of the control on the map. Defaults
259
+ to "top-right".
260
+ geojson (Optional[Dict[str, Any]]): Initial GeoJSON data to load
261
+ into the drawing control. Defaults to None.
262
+ **kwargs (Any): Additional keyword arguments to be passed to the
263
+ drawing control.
264
+
265
+ Returns:
266
+ None
267
+ """
268
+ self.session.m.add_draw_control(
269
+ options=options,
270
+ controls=controls,
271
+ position=position,
272
+ geojson=geojson,
273
+ **kwargs,
274
+ )
275
+ return f"Draw control added: {position}"
276
+
277
+ @tool
278
+ def add_vector_tile(
279
+ self,
280
+ url: str,
281
+ layer_id: str,
282
+ layer_type: str = "fill",
283
+ source_layer: Optional[str] = None,
284
+ name: Optional[str] = None,
285
+ paint: Optional[Dict] = None,
286
+ layout: Optional[Dict] = None,
287
+ filter: Optional[Dict] = None,
288
+ minzoom: Optional[int] = None,
289
+ maxzoom: Optional[int] = None,
290
+ visible: bool = True,
291
+ opacity: float = 1.0,
292
+ add_popup: bool = True,
293
+ before_id: Optional[str] = None,
294
+ source_args: Dict = None,
295
+ overwrite: bool = False,
296
+ **kwargs: Any,
297
+ ) -> None:
298
+ """
299
+ Adds a vector tile layer to the map.
300
+
301
+ This method adds a vector tile layer to the map using a vector tile source.
302
+ Vector tiles are a data format for efficiently storing and transmitting
303
+ vector map data.
304
+
305
+ Args:
306
+ url (str): The URL template for the vector tiles. Should contain {z}, {x},
307
+ and {y} placeholders for tile coordinates.
308
+ layer_id (str): The ID of the layer within the vector tile source.
309
+ layer_type (str, optional): The type of layer to create. Can be 'fill',
310
+ 'line', 'symbol', 'circle', etc. Defaults to 'fill'.
311
+ source_layer (str, optional): The name of the source layer within the
312
+ vector tiles. If None, uses layer_id.
313
+ name (str, optional): The name to use for the layer. If None, uses layer_id.
314
+ paint (dict, optional): Paint properties for the layer. If None, uses
315
+ default styling based on layer_type.
316
+ layout (dict, optional): Layout properties for the layer.
317
+ filter (dict, optional): Filter expression for the layer.
318
+ minzoom (int, optional): Minimum zoom level for the layer.
319
+ maxzoom (int, optional): Maximum zoom level for the layer.
320
+ visible (bool, optional): Whether the layer should be visible by default.
321
+ Defaults to True.
322
+ opacity (float, optional): The opacity of the layer. Defaults to 1.0.
323
+ add_popup (bool, optional): Whether to add a popup to the layer. Defaults to True.
324
+ before_id (str, optional): The ID of an existing layer before which the
325
+ new layer should be inserted.
326
+ source_args (dict, optional): Additional keyword arguments passed to the
327
+ vector tile source.
328
+ overwrite (bool, optional): Whether to overwrite an existing layer with
329
+ the same name. Defaults to False.
330
+ **kwargs: Additional keyword arguments passed to the Layer class.
331
+
332
+ Returns:
333
+ None
334
+
335
+ Example:
336
+ >>> m = Map()
337
+ >>> m.add_vector_tile(
338
+ ... url="https://api.maptiler.com/tiles/contours/tiles.json?key={api_key}",
339
+ ... layer_id="contour-lines",
340
+ ... layer_type="line",
341
+ ... source_layer="contour",
342
+ ... paint={"line-color": "#ff69b4", "line-width": 1}
343
+ ... )
344
+ """
345
+ self.session.m.add_vector_tile(
346
+ url=url,
347
+ layer_id=layer_id,
348
+ layer_type=layer_type,
349
+ source_layer=source_layer,
350
+ name=name,
351
+ paint=paint,
352
+ layout=layout,
353
+ filter=filter,
354
+ minzoom=minzoom,
355
+ maxzoom=maxzoom,
356
+ visible=visible,
357
+ opacity=opacity,
358
+ add_popup=add_popup,
359
+ before_id=before_id,
360
+ source_args=source_args,
361
+ overwrite=overwrite,
362
+ **kwargs,
363
+ )
364
+ return f"Vector tile layer added: {url}"
365
+
366
+ @tool
367
+ def add_wms_layer(
368
+ self,
369
+ url: str,
370
+ layers: str,
371
+ format: str = "image/png",
372
+ name: str = "WMS Layer",
373
+ attribution: str = "",
374
+ opacity: float = 1.0,
375
+ visible: bool = True,
376
+ tile_size: int = 256,
377
+ before_id: Optional[str] = None,
378
+ source_args: Dict = None,
379
+ overwrite: bool = False,
380
+ **kwargs: Any,
381
+ ) -> None:
382
+ """
383
+ Adds a WMS layer to the map.
384
+
385
+ This method adds a WMS layer to the map. The WMS is created from
386
+ the specified URL, and it is added to the map with the specified
387
+ name, attribution, visibility, and tile size.
388
+
389
+ Args:
390
+ url (str): The URL of the tile layer.
391
+ layers (str): The layers to include in the WMS request.
392
+ format (str, optional): The format of the tiles in the layer.
393
+ name (str, optional): The name to use for the layer. Defaults to
394
+ 'WMS Layer'.
395
+ attribution (str, optional): The attribution to use for the layer.
396
+ Defaults to ''.
397
+ visible (bool, optional): Whether the layer should be visible by
398
+ default. Defaults to True.
399
+ tile_size (int, optional): The size of the tiles in the layer.
400
+ Defaults to 256.
401
+ before_id (str, optional): The ID of an existing layer before which
402
+ the new layer should be inserted.
403
+ source_args (dict, optional): Additional keyword arguments that are
404
+ passed to the RasterTileSource class.
405
+ overwrite (bool, optional): Whether to overwrite an existing layer with the same name.
406
+ Defaults to False.
407
+ **kwargs: Additional keyword arguments that are passed to the Layer class.
408
+ See https://eodagmbh.github.io/py-maplibregl/api/layer/ for more information.
409
+
410
+ Returns:
411
+ None
412
+ """
413
+ self.session.m.add_wms_layer(
414
+ url=url,
415
+ layers=layers,
416
+ format=format,
417
+ name=name,
418
+ attribution=attribution,
419
+ opacity=opacity,
420
+ visible=visible,
421
+ tile_size=tile_size,
422
+ before_id=before_id,
423
+ source_args=source_args,
424
+ overwrite=overwrite,
425
+ **kwargs,
426
+ )
427
+ return f"WMS layer added: {url}"
428
+
429
+ @tool
430
+ def add_nwi_basemap(
431
+ self,
432
+ name: str = "NWI Wetlands",
433
+ format: str = "image/png",
434
+ attribution: str = "USFWS",
435
+ opacity: float = 1.0,
436
+ visible: bool = True,
437
+ tile_size: int = 256,
438
+ before_id: Optional[str] = None,
439
+ overwrite: bool = False,
440
+ **kwargs: Any,
441
+ ) -> None:
442
+ """
443
+ Adds a NWI Wetlands basemap to the map.
444
+
445
+ This method adds a NWI Wetlands basemap to the map. The NWI Wetlands basemap is created from
446
+ the specified URL, and it is added to the map with the specified
447
+ name, attribution, visibility, and tile size.
448
+
449
+ Args:
450
+ name (str, optional): The name to use for the layer. Defaults to
451
+ 'NWI Wetlands'.
452
+ format (str, optional): The format of the tiles in the layer.
453
+ attribution (str, optional): The attribution to use for the layer.
454
+ Defaults to ''.
455
+ visible (bool, optional): Whether the layer should be visible by
456
+ default. Defaults to True.
457
+ tile_size (int, optional): The size of the tiles in the layer.
458
+ Defaults to 256.
459
+ before_id (str, optional): The ID of an existing layer before which
460
+ the new layer should be inserted.
461
+ overwrite (bool, optional): Whether to overwrite an existing layer with the same name.
462
+ Defaults to False.
463
+ **kwargs: Additional keyword arguments that are passed to the Layer class.
464
+ See https://eodagmbh.github.io/py-maplibregl/api/layer/ for more information.
465
+
466
+ Returns:
467
+ None
468
+ """
469
+ self.session.m.add_nwi_basemap(
470
+ name=name,
471
+ format=format,
472
+ attribution=attribution,
473
+ opacity=opacity,
474
+ visible=visible,
475
+ tile_size=tile_size,
476
+ before_id=before_id,
477
+ overwrite=overwrite,
478
+ **kwargs,
479
+ )
480
+ return f"NWI Wetlands basemap added: {name}"
481
+
482
+ @tool
483
+ def add_raster(
484
+ self,
485
+ source,
486
+ indexes=None,
487
+ colormap=None,
488
+ vmin=None,
489
+ vmax=None,
490
+ nodata=None,
491
+ name="Raster",
492
+ before_id=None,
493
+ fit_bounds=True,
494
+ visible=True,
495
+ opacity=1.0,
496
+ array_args=None,
497
+ client_args={"cors_all": True},
498
+ overwrite: bool = True,
499
+ **kwargs,
500
+ ):
501
+ """Add a local raster dataset to the map.
502
+ If you are using this function in JupyterHub on a remote server
503
+ (e.g., Binder, Microsoft Planetary Computer) and if the raster
504
+ does not render properly, try installing jupyter-server-proxy using
505
+ `pip install jupyter-server-proxy`, then running the following code
506
+ before calling this function. For more info, see https://bit.ly/3JbmF93.
507
+
508
+ import os
509
+ os.environ['LOCALTILESERVER_CLIENT_PREFIX'] = 'proxy/{port}'
510
+
511
+ Args:
512
+ source (str): The path to the GeoTIFF file or the URL of the Cloud
513
+ Optimized GeoTIFF.
514
+ indexes (int, optional): The band(s) to use. Band indexing starts
515
+ at 1. Defaults to None.
516
+ colormap (str, optional): The name of the colormap from `matplotlib`
517
+ to use when plotting a single band.
518
+ See https://matplotlib.org/stable/gallery/color/colormap_reference.html.
519
+ Default is greyscale.
520
+ vmin (float, optional): The minimum value to use when colormapping
521
+ the palette when plotting a single band. Defaults to None.
522
+ vmax (float, optional): The maximum value to use when colormapping
523
+ the palette when plotting a single band. Defaults to None.
524
+ nodata (float, optional): The value from the band to use to interpret
525
+ as not valid data. Defaults to None.
526
+ attribution (str, optional): Attribution for the source raster. This
527
+ defaults to a message about it being a local file.. Defaults to None.
528
+ layer_name (str, optional): The layer name to use. Defaults to 'Raster'.
529
+ layer_index (int, optional): The index of the layer. Defaults to None.
530
+ zoom_to_layer (bool, optional): Whether to zoom to the extent of the
531
+ layer. Defaults to True.
532
+ visible (bool, optional): Whether the layer is visible. Defaults to True.
533
+ opacity (float, optional): The opacity of the layer. Defaults to 1.0.
534
+ array_args (dict, optional): Additional arguments to pass to
535
+ `array_to_memory_file` when reading the raster. Defaults to {}.
536
+ client_args (dict, optional): Additional arguments to pass to
537
+ localtileserver.TileClient. Defaults to { "cors_all": False }.
538
+ overwrite (bool, optional): Whether to overwrite an existing layer with the same name.
539
+ Defaults to True.
540
+ **kwargs: Additional keyword arguments to be passed to the underlying
541
+ `add_tile_layer` method.
542
+ """
543
+ self.session.m.add_raster(
544
+ source=source,
545
+ indexes=indexes,
546
+ colormap=colormap,
547
+ vmin=vmin,
548
+ vmax=vmax,
549
+ nodata=nodata,
550
+ name=name,
551
+ before_id=before_id,
552
+ fit_bounds=fit_bounds,
553
+ visible=visible,
554
+ opacity=opacity,
555
+ array_args=array_args,
556
+ client_args=client_args,
557
+ overwrite=overwrite,
558
+ **kwargs,
559
+ )
560
+ return f"Raster added: {source}"
561
+
562
+ @tool
563
+ def save_map(
564
+ self,
565
+ output: str = "map.html",
566
+ title: str = "My Awesome Map",
567
+ width: str = "100%",
568
+ height: str = "100%",
569
+ replace_key: bool = False,
570
+ remove_port: bool = True,
571
+ preview: bool = False,
572
+ overwrite: bool = False,
573
+ **kwargs,
574
+ ):
575
+ """Render the map to an HTML page.
576
+
577
+ Args:
578
+ output (str, optional): The output HTML file. If None, the HTML content
579
+ is returned as a string. Defaults to 'map.html'.
580
+ title (str, optional): The title of the HTML page. Defaults to 'My Awesome Map'.
581
+ width (str, optional): The width of the map. Defaults to '100%'.
582
+ height (str, optional): The height of the map. Defaults to '100%'.
583
+ replace_key (bool, optional): Whether to replace the API key in the HTML.
584
+ If True, the API key is replaced with the public API key.
585
+ The API key is read from the environment variable `MAPTILER_KEY`.
586
+ The public API key is read from the environment variable `MAPTILER_KEY_PUBLIC`.
587
+ Defaults to False.
588
+ remove_port (bool, optional): Whether to remove the port number from the HTML.
589
+ preview (bool, optional): Whether to preview the HTML file in a web browser.
590
+ Defaults to False.
591
+ overwrite (bool, optional): Whether to overwrite the output file if it already exists.
592
+ **kwargs: Additional keyword arguments that are passed to the
593
+ `maplibre.ipywidget.MapWidget.to_html()` method.
594
+
595
+ Returns:
596
+ str: The HTML content of the map.
597
+ """
598
+ self.session.m.to_html(
599
+ output=output,
600
+ title=title,
601
+ width=width,
602
+ height=height,
603
+ replace_key=replace_key,
604
+ remove_port=remove_port,
605
+ preview=preview,
606
+ overwrite=overwrite,
607
+ **kwargs,
608
+ )
609
+ return f"HTML file created: {output}"
610
+
611
+ @tool
612
+ def set_paint_property(self, name: str, prop: str, value: Any) -> None:
613
+ """
614
+ Set the paint property of a layer.
615
+
616
+ This method sets the opacity of the specified layer to the specified value.
617
+
618
+ Args:
619
+ name (str): The name of the layer.
620
+ prop (str): The paint property to set.
621
+ value (Any): The value to set.
622
+
623
+ Returns:
624
+ None
625
+ """
626
+ self.session.m.set_paint_property(name=name, prop=prop, value=value)
627
+ return f"Paint property set: {name}, {prop}, {value}"
628
+
629
+ @tool
630
+ def set_layout_property(self, name: str, prop: str, value: Any) -> None:
631
+ """
632
+ Set the layout property of a layer.
633
+
634
+ This method sets the layout property of the specified layer to the specified value.
635
+
636
+ Args:
637
+ name (str): The name of the layer.
638
+ prop (str): The layout property to set.
639
+ value (Any): The value to set.
640
+
641
+ Returns:
642
+ None
643
+ """
644
+ self.session.m.set_layout_property(name=name, prop=prop, value=value)
645
+ return f"Layout property set: {name}, {prop}, {value}"
646
+
647
+ @tool
648
+ def set_color(self, name: str, color: str) -> None:
649
+ """
650
+ Set the color of a layer.
651
+
652
+ This method sets the color of the specified layer to the specified value.
653
+
654
+ Args:
655
+ name (str): The name of the layer.
656
+ color (str): The color value to set.
657
+
658
+ Returns:
659
+ None
660
+ """
661
+ self.session.m.set_color(name=name, color=color)
662
+ return f"Color set: {name}, {color}"
663
+
664
+ @tool
665
+ def set_opacity(self, name: str, opacity: float) -> None:
666
+ """
667
+ Set the opacity of a layer.
668
+
669
+ This method sets the opacity of the specified layer to the specified value.
670
+
671
+ Args:
672
+ name (str): The name of the layer.
673
+ opacity (float): The opacity value to set.
674
+
675
+ Returns:
676
+ None
677
+ """
678
+ self.session.m.set_opacity(name=name, opacity=opacity)
679
+ return f"Opacity set: {name}, {opacity}"
680
+
681
+ @tool
682
+ def set_visibility(self, name: str, visible: bool) -> None:
683
+ """
684
+ Set the visibility of a layer.
685
+
686
+ This method sets the visibility of the specified layer to the specified value.
687
+
688
+ Args:
689
+ name (str): The name of the layer.
690
+ visible (bool): The visibility value to set.
691
+
692
+ Returns:
693
+ None
694
+ """
695
+ self.session.m.set_visibility(name=name, visible=visible)
696
+ return f"Visibility set: {name}, {visible}"
697
+
698
+ @tool
699
+ def add_pmtiles(
700
+ self,
701
+ url: str,
702
+ style: Optional[Dict] = None,
703
+ visible: bool = True,
704
+ opacity: float = 1.0,
705
+ exclude_mask: bool = False,
706
+ tooltip: bool = True,
707
+ properties: Optional[Dict] = None,
708
+ template: Optional[str] = None,
709
+ attribution: str = "PMTiles",
710
+ fit_bounds: bool = True,
711
+ **kwargs: Any,
712
+ ) -> None:
713
+ """
714
+ Adds a PMTiles layer to the map.
715
+
716
+ Args:
717
+ url (str): The URL of the PMTiles file.
718
+ style (dict, optional): The CSS style to apply to the layer. Defaults to None.
719
+ See https://docs.mapbox.com/style-spec/reference/layers/ for more info.
720
+ visible (bool, optional): Whether the layer should be shown initially. Defaults to True.
721
+ opacity (float, optional): The opacity of the layer. Defaults to 1.0.
722
+ exclude_mask (bool, optional): Whether to exclude the mask layer. Defaults to False.
723
+ tooltip (bool, optional): Whether to show tooltips on the layer. Defaults to True.
724
+ properties (dict, optional): The properties to use for the tooltips. Defaults to None.
725
+ template (str, optional): The template to use for the tooltips. Defaults to None.
726
+ attribution (str, optional): The attribution to use for the layer. Defaults to 'PMTiles'.
727
+ fit_bounds (bool, optional): Whether to zoom to the layer extent. Defaults to True.
728
+ **kwargs: Additional keyword arguments to pass to the PMTilesLayer constructor.
729
+
730
+ Returns:
731
+ None
732
+ """
733
+ self.session.m.add_pmtiles(
734
+ url=url,
735
+ style=style,
736
+ visible=visible,
737
+ opacity=opacity,
738
+ exclude_mask=exclude_mask,
739
+ tooltip=tooltip,
740
+ properties=properties,
741
+ template=template,
742
+ attribution=attribution,
743
+ fit_bounds=fit_bounds,
744
+ **kwargs,
745
+ )
746
+ return f"PMTiles layer added: {url}"
747
+
748
+ @tool
749
+ def add_marker(
750
+ self,
751
+ lng_lat: List[Union[float, float]],
752
+ popup: Optional[Dict] = None,
753
+ options: Optional[Dict] = None,
754
+ ) -> None:
755
+ """
756
+ Adds a marker to the map.
757
+
758
+ Args:
759
+ marker (Marker, optional): A Marker object. Defaults to None.
760
+ lng_lat (List[Union[float, float]]): A list of two floats
761
+ representing the longitude and latitude of the marker.
762
+ popup (Optional[str], optional): The text to display in a popup when
763
+ the marker is clicked. Defaults to None.
764
+ options (Optional[Dict], optional): A dictionary of options to
765
+ customize the marker. Defaults to None.
766
+
767
+ Returns:
768
+ None
769
+ """
770
+ self.session.m.add_marker(lng_lat=lng_lat, popup=popup, options=options)
771
+ return f"Marker added: {lng_lat}"
772
+
773
+ @tool
774
+ def add_image(
775
+ self,
776
+ id: str = None,
777
+ image: Union[str, Dict] = None,
778
+ width: int = None,
779
+ height: int = None,
780
+ coordinates: List[float] = None,
781
+ position: str = None,
782
+ icon_size: float = 1.0,
783
+ **kwargs: Any,
784
+ ) -> None:
785
+ """Add an image to the map.
786
+
787
+ Args:
788
+ id (str): The layer ID of the image.
789
+ image (Union[str, Dict, np.ndarray]): The URL or local file path to
790
+ the image, or a dictionary containing image data, or a numpy
791
+ array representing the image.
792
+ width (int, optional): The width of the image. Defaults to None.
793
+ height (int, optional): The height of the image. Defaults to None.
794
+ coordinates (List[float], optional): The longitude and latitude
795
+ coordinates to place the image.
796
+ position (str, optional): The position of the image. Defaults to None.
797
+ Can be one of 'top-right', 'top-left', 'bottom-right', 'bottom-left'.
798
+ icon_size (float, optional): The size of the icon. Defaults to 1.0.
799
+
800
+ Returns:
801
+ None
802
+ """
803
+ self.session.m.add_image(
804
+ id=id,
805
+ image=image,
806
+ width=width,
807
+ height=height,
808
+ coordinates=coordinates,
809
+ position=position,
810
+ icon_size=icon_size,
811
+ **kwargs,
812
+ )
813
+ return f"Image added: {id}"
814
+
815
+ @tool
816
+ def rotate_to(
817
+ self, bearing: float, options: Dict[str, Any] = {}, **kwargs: Any
818
+ ) -> None:
819
+ """
820
+ Rotate the map to a specified bearing.
821
+
822
+ This function rotates the map to a specified bearing. The bearing is specified in degrees
823
+ counter-clockwise from true north. If the bearing is not specified, the map will rotate to
824
+ true north. Additional options and keyword arguments can be provided to control the rotation.
825
+ For more information, see https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#rotateto
826
+
827
+ Args:
828
+ bearing (float): The bearing to rotate to, in degrees counter-clockwise from true north.
829
+ options (Dict[str, Any], optional): Additional options to control the rotation. Defaults to {}.
830
+ **kwargs (Any): Additional keyword arguments to control the rotation.
831
+
832
+ Returns:
833
+ None
834
+ """
835
+ self.session.m.rotate_to(bearing=bearing, options=options, **kwargs)
836
+ return f"Map rotated to: {bearing}"
837
+
838
+ @tool
839
+ def pan_to(
840
+ self,
841
+ lnglat: List[float],
842
+ options: Dict[str, Any] = {},
843
+ **kwargs: Any,
844
+ ) -> None:
845
+ """
846
+ Pans the map to a specified location.
847
+
848
+ This function pans the map to the specified longitude and latitude coordinates.
849
+ Additional options and keyword arguments can be provided to control the panning.
850
+ For more information, see https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#panto
851
+
852
+ Args:
853
+ lnglat (List[float, float]): The longitude and latitude coordinates to pan to.
854
+ options (Dict[str, Any], optional): Additional options to control the panning. Defaults to {}.
855
+ **kwargs (Any): Additional keyword arguments to control the panning.
856
+
857
+ Returns:
858
+ None
859
+ """
860
+ self.session.m.pan_to(lnglat=lnglat, options=options, **kwargs)
861
+ return f"Map panned to: {lnglat}"
862
+
863
+ @tool
864
+ def jump_to(self, options: Dict[str, Any] = {}, **kwargs: Any) -> None:
865
+ """
866
+ Jumps the map to a specified location.
867
+
868
+ This function jumps the map to the specified location with the specified options.
869
+ Additional keyword arguments can be provided to control the jump. For more information,
870
+ see https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#jumpto
871
+
872
+ Args:
873
+ options (Dict[str, Any], optional): Additional options to control the jump. Defaults to {}.
874
+ **kwargs (Any): Additional keyword arguments to control the jump.
875
+
876
+ Returns:
877
+ None
878
+ """
879
+ self.session.m.jump_to(options=options, **kwargs)
880
+ return f"Map jumped to: {options}"
881
+
882
+ @tool
883
+ def zoom_to(self, zoom: float, options: Dict[str, Any] = {}) -> None:
884
+ """
885
+ Zooms the map to a specified zoom level.
886
+
887
+ This function zooms the map to the specified zoom level. Additional options and keyword
888
+ arguments can be provided to control the zoom. For more information, see
889
+ https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#zoomto
890
+
891
+ Args:
892
+ zoom (float): The zoom level to zoom to.
893
+ options (Dict[str, Any], optional): Additional options to control the zoom. Defaults to {}.
894
+ **kwargs (Any): Additional keyword arguments to control the zoom.
895
+
896
+ Returns:
897
+ None
898
+ """
899
+ self.session.m.zoom_to(zoom=zoom, options=options)
900
+ return f"Map zoomed to: {zoom}"
901
+
902
+ @tool
903
+ def first_symbol_layer_id(self) -> Optional[str]:
904
+ """
905
+ Get the ID of the first symbol layer in the map's current style.
906
+ """
907
+ return self.session.m.first_symbol_layer_id
908
+
909
+ @tool
910
+ def add_text(
911
+ self,
912
+ text: str,
913
+ fontsize: int = 20,
914
+ fontcolor: str = "black",
915
+ bold: bool = False,
916
+ padding: str = "5px",
917
+ bg_color: str = "white",
918
+ border_radius: str = "5px",
919
+ position: str = "bottom-right",
920
+ **kwargs: Any,
921
+ ) -> None:
922
+ """
923
+ Adds text to the map with customizable styling.
924
+
925
+ This method allows adding a text widget to the map with various styling options such as font size, color,
926
+ background color, and more. The text's appearance can be further customized using additional CSS properties
927
+ passed through kwargs.
928
+
929
+ Args:
930
+ text (str): The text to add to the map.
931
+ fontsize (int, optional): The font size of the text. Defaults to 20.
932
+ fontcolor (str, optional): The color of the text. Defaults to "black".
933
+ bold (bool, optional): If True, the text will be bold. Defaults to False.
934
+ padding (str, optional): The padding around the text. Defaults to "5px".
935
+ bg_color (str, optional): The background color of the text widget. Defaults to "white".
936
+ To make the background transparent, set this to "transparent".
937
+ To make the background half transparent, set this to "rgba(255, 255, 255, 0.5)".
938
+ border_radius (str, optional): The border radius of the text widget. Defaults to "5px".
939
+ position (str, optional): The position of the text widget on the map. Defaults to "bottom-right".
940
+ **kwargs (Any): Additional CSS properties to apply to the text widget.
941
+
942
+ Returns:
943
+ None
944
+ """
945
+ self.session.m.add_text(
946
+ text=text,
947
+ fontsize=fontsize,
948
+ fontcolor=fontcolor,
949
+ bold=bold,
950
+ padding=padding,
951
+ bg_color=bg_color,
952
+ border_radius=border_radius,
953
+ position=position,
954
+ **kwargs,
955
+ )
956
+ return f"Text added: {text}"
957
+
958
+ @tool
959
+ def add_html(
960
+ self,
961
+ html: str,
962
+ bg_color: str = "white",
963
+ position: str = "bottom-right",
964
+ **kwargs: Union[str, int, float],
965
+ ) -> None:
966
+ """
967
+ Add HTML content to the map.
968
+
969
+ This method allows for the addition of arbitrary HTML content to the map, which can be used to display
970
+ custom information or controls. The background color and position of the HTML content can be customized.
971
+
972
+ Args:
973
+ html (str): The HTML content to add.
974
+ bg_color (str, optional): The background color of the HTML content. Defaults to "white".
975
+ To make the background transparent, set this to "transparent".
976
+ To make the background half transparent, set this to "rgba(255, 255, 255, 0.5)".
977
+ position (str, optional): The position of the HTML content on the map. Can be one of "top-left",
978
+ "top-right", "bottom-left", "bottom-right". Defaults to "bottom-right".
979
+ **kwargs: Additional keyword arguments for future use.
980
+
981
+ Returns:
982
+ None
983
+ """
984
+ self.session.m.add_html(
985
+ html=html, bg_color=bg_color, position=position, **kwargs
986
+ )
987
+ return f"HTML added: {html}"
988
+
989
+ @tool
990
+ def add_legend(
991
+ self,
992
+ title: str = "Legend",
993
+ legend_dict: Optional[Dict[str, str]] = None,
994
+ labels: Optional[List[str]] = None,
995
+ colors: Optional[List[str]] = None,
996
+ fontsize: int = 15,
997
+ bg_color: str = "white",
998
+ position: str = "bottom-right",
999
+ builtin_legend: Optional[str] = None,
1000
+ shape_type: str = "rectangle",
1001
+ **kwargs: Union[str, int, float],
1002
+ ) -> None:
1003
+ """
1004
+ Adds a legend to the map.
1005
+
1006
+ This method allows for the addition of a legend to the map. The legend can be customized with a title,
1007
+ labels, colors, and more. A built-in legend can also be specified.
1008
+
1009
+ Args:
1010
+ title (str, optional): The title of the legend. Defaults to "Legend".
1011
+ legend_dict (Optional[Dict[str, str]], optional): A dictionary with legend items as keys and colors as values.
1012
+ If provided, `labels` and `colors` will be ignored. Defaults to None.
1013
+ labels (Optional[List[str]], optional): A list of legend labels. Defaults to None.
1014
+ colors (Optional[List[str]], optional): A list of colors corresponding to the labels. Defaults to None.
1015
+ fontsize (int, optional): The font size of the legend text. Defaults to 15.
1016
+ bg_color (str, optional): The background color of the legend. Defaults to "white".
1017
+ To make the background transparent, set this to "transparent".
1018
+ To make the background half transparent, set this to "rgba(255, 255, 255, 0.5)".
1019
+ position (str, optional): The position of the legend on the map. Can be one of "top-left",
1020
+ "top-right", "bottom-left", "bottom-right". Defaults to "bottom-right".
1021
+ builtin_legend (Optional[str], optional): The name of a built-in legend to use. Defaults to None.
1022
+ shape_type (str, optional): The shape type of the legend items. Can be one of "rectangle", "circle", or "line".
1023
+ **kwargs: Additional keyword arguments for future use.
1024
+
1025
+ Returns:
1026
+ None
1027
+ """
1028
+ self.session.m.add_legend(
1029
+ title=title,
1030
+ legend_dict=legend_dict,
1031
+ labels=labels,
1032
+ colors=colors,
1033
+ fontsize=fontsize,
1034
+ bg_color=bg_color,
1035
+ position=position,
1036
+ builtin_legend=builtin_legend,
1037
+ shape_type=shape_type,
1038
+ **kwargs,
1039
+ )
1040
+ return f"Legend added: {title}"
1041
+
1042
+ @tool
1043
+ def add_colorbar(
1044
+ self,
1045
+ width: Optional[float] = 3.0,
1046
+ height: Optional[float] = 0.2,
1047
+ vmin: Optional[float] = 0,
1048
+ vmax: Optional[float] = 1.0,
1049
+ palette: Optional[List[str]] = None,
1050
+ vis_params: Optional[Dict[str, Union[str, float, int]]] = None,
1051
+ cmap: Optional[str] = "gray",
1052
+ discrete: Optional[bool] = False,
1053
+ label: Optional[str] = None,
1054
+ label_size: Optional[int] = 10,
1055
+ label_weight: Optional[str] = "normal",
1056
+ tick_size: Optional[int] = 8,
1057
+ bg_color: Optional[str] = "white",
1058
+ orientation: Optional[str] = "horizontal",
1059
+ dpi: Optional[Union[str, float]] = "figure",
1060
+ transparent: Optional[bool] = False,
1061
+ position: str = "bottom-right",
1062
+ **kwargs,
1063
+ ) -> str:
1064
+ """
1065
+ Add a colorbar to the map.
1066
+
1067
+ This function uses matplotlib to generate a colorbar, saves it as a PNG file, and adds it to the map using
1068
+ the Map.add_html() method. The colorbar can be customized in various ways including its size, color palette,
1069
+ label, and orientation.
1070
+
1071
+ Args:
1072
+ width (Optional[float]): Width of the colorbar in inches. Defaults to 3.0.
1073
+ height (Optional[float]): Height of the colorbar in inches. Defaults to 0.2.
1074
+ vmin (Optional[float]): Minimum value of the colorbar. Defaults to 0.
1075
+ vmax (Optional[float]): Maximum value of the colorbar. Defaults to 1.0.
1076
+ palette (Optional[List[str]]): List of colors or a colormap name for the colorbar. Defaults to None.
1077
+ vis_params (Optional[Dict[str, Union[str, float, int]]]): Visualization parameters as a dictionary.
1078
+ cmap (Optional[str]): Matplotlib colormap name. Defaults to "gray".
1079
+ discrete (Optional[bool]): Whether to create a discrete colorbar. Defaults to False.
1080
+ label (Optional[str]): Label for the colorbar. Defaults to None.
1081
+ label_size (Optional[int]): Font size for the colorbar label. Defaults to 10.
1082
+ label_weight (Optional[str]): Font weight for the colorbar label. Defaults to "normal".
1083
+ tick_size (Optional[int]): Font size for the colorbar tick labels. Defaults to 8.
1084
+ bg_color (Optional[str]): Background color for the colorbar. Defaults to "white".
1085
+ orientation (Optional[str]): Orientation of the colorbar ("vertical" or "horizontal"). Defaults to "horizontal".
1086
+ dpi (Optional[Union[str, float]]): Resolution in dots per inch. If 'figure', uses the figure's dpi value. Defaults to "figure".
1087
+ transparent (Optional[bool]): Whether the background is transparent. Defaults to False.
1088
+ position (str): Position of the colorbar on the map. Defaults to "bottom-right".
1089
+ **kwargs: Additional keyword arguments passed to matplotlib.pyplot.savefig().
1090
+
1091
+ Returns:
1092
+ str: Path to the generated colorbar image.
1093
+ """
1094
+ self.session.m.add_colorbar(
1095
+ width=width,
1096
+ height=height,
1097
+ vmin=vmin,
1098
+ vmax=vmax,
1099
+ palette=palette,
1100
+ vis_params=vis_params,
1101
+ cmap=cmap,
1102
+ discrete=discrete,
1103
+ label=label,
1104
+ label_size=label_size,
1105
+ label_weight=label_weight,
1106
+ tick_size=tick_size,
1107
+ bg_color=bg_color,
1108
+ orientation=orientation,
1109
+ dpi=dpi,
1110
+ transparent=transparent,
1111
+ position=position,
1112
+ **kwargs,
1113
+ )
1114
+ return f"Colorbar added: {position}"
1115
+
1116
+ @tool
1117
+ def add_layer_control(
1118
+ self,
1119
+ layer_ids: Optional[List[str]] = None,
1120
+ theme: str = "default",
1121
+ css_text: Optional[str] = None,
1122
+ position: str = "top-left",
1123
+ bg_layers: Optional[Union[bool, List[str]]] = False,
1124
+ ) -> None:
1125
+ """
1126
+ Adds a layer control to the map.
1127
+
1128
+ This function creates and adds a layer switcher control to the map, allowing users to toggle the visibility
1129
+ of specified layers. The appearance and functionality of the layer control can be customized with parameters
1130
+ such as theme, CSS styling, and position on the map.
1131
+
1132
+ Args:
1133
+ layer_ids (Optional[List[str]]): A list of layer IDs to include in the control. If None, all layers
1134
+ in the map will be included. Defaults to None.
1135
+ theme (str): The theme for the layer switcher control. Can be "default" or other custom themes. Defaults to "default".
1136
+ css_text (Optional[str]): Custom CSS text for styling the layer control. If None, a default style will be applied.
1137
+ Defaults to None.
1138
+ position (str): The position of the layer control on the map. Can be "top-left", "top-right", "bottom-left",
1139
+ or "bottom-right". Defaults to "top-left".
1140
+ bg_layers (bool): If True, background layers will be included in the control. Defaults to False.
1141
+
1142
+ Returns:
1143
+ None
1144
+ """
1145
+ self.session.m.add_layer_control(
1146
+ layer_ids=layer_ids,
1147
+ theme=theme,
1148
+ css_text=css_text,
1149
+ position=position,
1150
+ bg_layers=bg_layers,
1151
+ )
1152
+ return f"Layer control added: {position}"
1153
+
1154
+ @tool
1155
+ def add_video(
1156
+ self,
1157
+ urls: Union[str, List[str]],
1158
+ coordinates: List[List[float]],
1159
+ layer_id: str = "video",
1160
+ before_id: Optional[str] = None,
1161
+ ) -> None:
1162
+ """
1163
+ Adds a video layer to the map.
1164
+
1165
+ This method allows embedding a video into the map by specifying the video URLs and the geographical coordinates
1166
+ that the video should cover. The video will be stretched and fitted into the specified coordinates.
1167
+
1168
+ Args:
1169
+ urls (Union[str, List[str]]): A single video URL or a list of video URLs. These URLs must be accessible
1170
+ from the client's location.
1171
+ coordinates (List[List[float]]): A list of four coordinates in [longitude, latitude] format, specifying
1172
+ the corners of the video. The coordinates order should be top-left, top-right, bottom-right, bottom-left.
1173
+ layer_id (str): The ID for the video layer. Defaults to "video".
1174
+ before_id (Optional[str]): The ID of an existing layer to insert the new layer before. If None, the layer
1175
+ will be added on top. Defaults to None.
1176
+
1177
+ Returns:
1178
+ None
1179
+ """
1180
+ self.session.m.add_video(
1181
+ urls=urls,
1182
+ coordinates=coordinates,
1183
+ layer_id=layer_id,
1184
+ before_id=before_id,
1185
+ )
1186
+ return f"Video added: {layer_id}"
1187
+
1188
+ @tool
1189
+ def add_nlcd(self, years: list = [2023], add_legend: bool = True, **kwargs) -> None:
1190
+ """
1191
+ Adds National Land Cover Database (NLCD) data to the map.
1192
+
1193
+ Args:
1194
+ years (list): A list of years to add. It can be any of 1985-2023. Defaults to [2023].
1195
+ add_legend (bool): Whether to add a legend to the map. Defaults to True.
1196
+ **kwargs: Additional keyword arguments to pass to the add_cog_layer method.
1197
+
1198
+ Returns:
1199
+ None
1200
+ """
1201
+ self.session.m.add_nlcd(
1202
+ years=years,
1203
+ add_legend=add_legend,
1204
+ **kwargs,
1205
+ )
1206
+ return f"NLCD added: {years}"
1207
+
1208
+ @tool
1209
+ def add_data(
1210
+ self,
1211
+ data: Union[str],
1212
+ column: str,
1213
+ cmap: Optional[str] = None,
1214
+ colors: Optional[str] = None,
1215
+ labels: Optional[str] = None,
1216
+ scheme: Optional[str] = "Quantiles",
1217
+ k: int = 5,
1218
+ add_legend: Optional[bool] = True,
1219
+ legend_title: Optional[bool] = None,
1220
+ legend_position: Optional[str] = "bottom-right",
1221
+ legend_kwds: Optional[dict] = None,
1222
+ classification_kwds: Optional[dict] = None,
1223
+ legend_args: Optional[dict] = None,
1224
+ layer_type: Optional[str] = None,
1225
+ extrude: Optional[bool] = False,
1226
+ scale_factor: Optional[float] = 1.0,
1227
+ filter: Optional[Dict] = None,
1228
+ paint: Optional[Dict] = None,
1229
+ name: Optional[str] = None,
1230
+ fit_bounds: bool = True,
1231
+ visible: bool = True,
1232
+ opacity: float = 1.0,
1233
+ before_id: Optional[str] = None,
1234
+ source_args: Dict = {},
1235
+ **kwargs: Any,
1236
+ ) -> None:
1237
+ """Add vector data to the map with a variety of classification schemes.
1238
+
1239
+ Args:
1240
+ data (str | pd.DataFrame | gpd.GeoDataFrame): The data to classify.
1241
+ It can be a filepath to a vector dataset, a pandas dataframe, or
1242
+ a geopandas geodataframe.
1243
+ column (str): The column to classify.
1244
+ cmap (str, optional): The name of a colormap recognized by matplotlib. Defaults to None.
1245
+ colors (list, optional): A list of colors to use for the classification. Defaults to None.
1246
+ labels (list, optional): A list of labels to use for the legend. Defaults to None.
1247
+ scheme (str, optional): Name of a choropleth classification scheme (requires mapclassify).
1248
+ Name of a choropleth classification scheme (requires mapclassify).
1249
+ A mapclassify.MapClassifier object will be used
1250
+ under the hood. Supported are all schemes provided by mapclassify (e.g.
1251
+ 'BoxPlot', 'EqualInterval', 'FisherJenks', 'FisherJenksSampled',
1252
+ 'HeadTailBreaks', 'JenksCaspall', 'JenksCaspallForced',
1253
+ 'JenksCaspallSampled', 'MaxP', 'MaximumBreaks',
1254
+ 'NaturalBreaks', 'Quantiles', 'Percentiles', 'StdMean',
1255
+ 'UserDefined'). Arguments can be passed in classification_kwds.
1256
+ k (int, optional): Number of classes (ignored if scheme is None or if
1257
+ column is categorical). Default to 5.
1258
+ add_legend (bool, optional): Whether to add a legend to the map. Defaults to True.
1259
+ legend_title (str, optional): The title of the legend. Defaults to None.
1260
+ legend_position (str, optional): The position of the legend. Can be 'top-left',
1261
+ 'top-right', 'bottom-left', or 'bottom-right'. Defaults to 'bottom-right'.
1262
+ legend_kwds (dict, optional): Keyword arguments to pass to :func:`matplotlib.pyplot.legend`
1263
+ or `matplotlib.pyplot.colorbar`. Defaults to None.
1264
+ Keyword arguments to pass to :func:`matplotlib.pyplot.legend` or
1265
+ Additional accepted keywords when `scheme` is specified:
1266
+ fmt : string
1267
+ A formatting specification for the bin edges of the classes in the
1268
+ legend. For example, to have no decimals: ``{"fmt": "{:.0f}"}``.
1269
+ labels : list-like
1270
+ A list of legend labels to override the auto-generated labblels.
1271
+ Needs to have the same number of elements as the number of
1272
+ classes (`k`).
1273
+ interval : boolean (default False)
1274
+ An option to control brackets from mapclassify legend.
1275
+ If True, open/closed interval brackets are shown in the legend.
1276
+ classification_kwds (dict, optional): Keyword arguments to pass to mapclassify.
1277
+ Defaults to None.
1278
+ legend_args (dict, optional): Additional keyword arguments for the add_legend method. Defaults to None.
1279
+ layer_type (str, optional): The type of layer to add. Can be 'circle', 'line', or 'fill'. Defaults to None.
1280
+ filter (dict, optional): The filter to apply to the layer. If None,
1281
+ no filter is applied.
1282
+ paint (dict, optional): The paint properties to apply to the layer.
1283
+ If None, no paint properties are applied.
1284
+ name (str, optional): The name of the layer. If None, a random name
1285
+ is generated.
1286
+ fit_bounds (bool, optional): Whether to adjust the viewport of the
1287
+ map to fit the bounds of the GeoJSON data. Defaults to True.
1288
+ visible (bool, optional): Whether the layer is visible or not.
1289
+ Defaults to True.
1290
+ before_id (str, optional): The ID of an existing layer before which
1291
+ the new layer should be inserted.
1292
+ source_args (dict, optional): Additional keyword arguments that are
1293
+ passed to the GeoJSONSource class.
1294
+ **kwargs: Additional keyword arguments to pass to the GeoJSON class, such as
1295
+ fields, which can be a list of column names to be included in the popup.
1296
+
1297
+ """
1298
+ self.session.m.add_data(
1299
+ data=data,
1300
+ column=column,
1301
+ cmap=cmap,
1302
+ colors=colors,
1303
+ labels=labels,
1304
+ scheme=scheme,
1305
+ k=k,
1306
+ add_legend=add_legend,
1307
+ legend_title=legend_title,
1308
+ legend_position=legend_position,
1309
+ legend_kwds=legend_kwds,
1310
+ classification_kwds=classification_kwds,
1311
+ legend_args=legend_args,
1312
+ layer_type=layer_type,
1313
+ extrude=extrude,
1314
+ scale_factor=scale_factor,
1315
+ filter=filter,
1316
+ paint=paint,
1317
+ name=name,
1318
+ fit_bounds=fit_bounds,
1319
+ visible=visible,
1320
+ opacity=opacity,
1321
+ before_id=before_id,
1322
+ source_args=source_args,
1323
+ **kwargs,
1324
+ )
1325
+ return f"Data added: {name}"
1326
+
1327
+ @tool
1328
+ def add_mapillary(
1329
+ self,
1330
+ minzoom: int = 6,
1331
+ maxzoom: int = 14,
1332
+ sequence_lyr_name: str = "sequence",
1333
+ image_lyr_name: str = "image",
1334
+ before_id: str = None,
1335
+ sequence_paint: dict = None,
1336
+ image_paint: dict = None,
1337
+ image_minzoom: int = 17,
1338
+ add_popup: bool = True,
1339
+ access_token: str = None,
1340
+ opacity: float = 1.0,
1341
+ visible: bool = True,
1342
+ add_to_sidebar: bool = False,
1343
+ style: str = "photo",
1344
+ radius: float = 0.00005,
1345
+ height: int = 420,
1346
+ frame_border: int = 0,
1347
+ default_message: str = "No Mapillary image found",
1348
+ widget_icon: str = "mdi-image",
1349
+ widget_label: str = "Mapillary StreetView",
1350
+ **kwargs: Any,
1351
+ ) -> None:
1352
+ """
1353
+ Adds Mapillary layers to the map.
1354
+
1355
+ Args:
1356
+ minzoom (int): Minimum zoom level for the Mapillary tiles. Defaults to 6.
1357
+ maxzoom (int): Maximum zoom level for the Mapillary tiles. Defaults to 14.
1358
+ sequence_lyr_name (str): Name of the sequence layer. Defaults to "sequence".
1359
+ image_lyr_name (str): Name of the image layer. Defaults to "image".
1360
+ before_id (str): The ID of an existing layer to insert the new layer before. Defaults to None.
1361
+ sequence_paint (dict, optional): Paint properties for the sequence layer. Defaults to None.
1362
+ image_paint (dict, optional): Paint properties for the image layer. Defaults to None.
1363
+ image_minzoom (int): Minimum zoom level for the image layer. Defaults to 17.
1364
+ add_popup (bool): Whether to add popups to the layers. Defaults to True.
1365
+ access_token (str, optional): Access token for Mapillary API. Defaults to None.
1366
+ opacity (float): Opacity of the Mapillary layers. Defaults to 1.0.
1367
+ visible (bool): Whether the Mapillary layers are visible. Defaults to True.
1368
+
1369
+ Raises:
1370
+ ValueError: If no access token is provided.
1371
+
1372
+ Returns:
1373
+ None
1374
+ """
1375
+ self.session.m.add_mapillary(
1376
+ minzoom=minzoom,
1377
+ maxzoom=maxzoom,
1378
+ sequence_lyr_name=sequence_lyr_name,
1379
+ image_lyr_name=image_lyr_name,
1380
+ before_id=before_id,
1381
+ sequence_paint=sequence_paint,
1382
+ image_paint=image_paint,
1383
+ image_minzoom=image_minzoom,
1384
+ add_popup=add_popup,
1385
+ access_token=access_token,
1386
+ opacity=opacity,
1387
+ visible=visible,
1388
+ add_to_sidebar=add_to_sidebar,
1389
+ style=style,
1390
+ radius=radius,
1391
+ height=height,
1392
+ frame_border=frame_border,
1393
+ default_message=default_message,
1394
+ widget_icon=widget_icon,
1395
+ widget_label=widget_label,
1396
+ **kwargs,
1397
+ )
1398
+ return f"Mapillary added: {sequence_lyr_name}"
1399
+
1400
+ @tool
1401
+ def add_labels(
1402
+ self,
1403
+ source: Union[str, Dict[str, Any]],
1404
+ column: str,
1405
+ name: Optional[str] = None,
1406
+ text_size: int = 14,
1407
+ text_anchor: str = "center",
1408
+ text_color: str = "black",
1409
+ min_zoom: Optional[float] = None,
1410
+ max_zoom: Optional[float] = None,
1411
+ layout: Optional[Dict[str, Any]] = None,
1412
+ paint: Optional[Dict[str, Any]] = None,
1413
+ before_id: Optional[str] = None,
1414
+ opacity: float = 1.0,
1415
+ visible: bool = True,
1416
+ **kwargs: Any,
1417
+ ) -> None:
1418
+ """
1419
+ Adds a label layer to the map.
1420
+
1421
+ This method adds a label layer to the map using the specified source and column for text values.
1422
+
1423
+ Args:
1424
+ source (Union[str, Dict[str, Any]]): The data source for the labels. It can be a GeoJSON file path
1425
+ or a dictionary containing GeoJSON data.
1426
+ column (str): The column name in the source data to use for the label text.
1427
+ name (Optional[str]): The name of the label layer. If None, a random name is generated. Defaults to None.
1428
+ text_size (int): The size of the label text. Defaults to 14.
1429
+ text_anchor (str): The anchor position of the text. Can be "center", "left", "right", etc. Defaults to "center".
1430
+ text_color (str): The color of the label text. Defaults to "black".
1431
+ min_zoom (Optional[float]): The minimum zoom level at which the labels are visible. Defaults to None.
1432
+ max_zoom (Optional[float]): The maximum zoom level at which the labels are visible. Defaults to None.
1433
+ layout (Optional[Dict[str, Any]]): Additional layout properties for the label layer. Defaults to None.
1434
+ For more information, refer to https://maplibre.org/maplibre-style-spec/layers/#symbol.
1435
+ paint (Optional[Dict[str, Any]]): Additional paint properties for the label layer. Defaults to None.
1436
+ before_id (Optional[str]): The ID of an existing layer before which the new layer should be inserted. Defaults to None.
1437
+ opacity (float): The opacity of the label layer. Defaults to 1.0.
1438
+ visible (bool): Whether the label layer is visible by default. Defaults to True.
1439
+ **kwargs (Any): Additional keyword arguments to customize the label layer.
1440
+
1441
+ Returns:
1442
+ None
1443
+ """
1444
+ self.session.m.add_labels(
1445
+ source=source,
1446
+ column=column,
1447
+ name=name,
1448
+ text_size=text_size,
1449
+ text_anchor=text_anchor,
1450
+ text_color=text_color,
1451
+ min_zoom=min_zoom,
1452
+ max_zoom=max_zoom,
1453
+ layout=layout,
1454
+ paint=paint,
1455
+ before_id=before_id,
1456
+ opacity=opacity,
1457
+ visible=visible,
1458
+ **kwargs,
1459
+ )
1460
+ return f"Labels added: {name}"
1461
+
1462
+ @tool
1463
+ def get_layer_names(self) -> list:
1464
+ """Gets layer names as a list.
1465
+
1466
+ Returns:
1467
+ list: A list of layer names.
1468
+ """
1469
+ return self.session.m.get_layer_names()
1470
+
1471
+ @tool
1472
+ def set_terrain(
1473
+ self,
1474
+ source: str = "https://elevation-tiles-prod.s3.amazonaws.com/terrarium/{z}/{x}/{y}.png",
1475
+ exaggeration: float = 1.0,
1476
+ tile_size: int = 256,
1477
+ encoding: str = "terrarium",
1478
+ source_id: str = "terrain-dem",
1479
+ ) -> None:
1480
+ """Add terrain visualization to the map.
1481
+
1482
+ Args:
1483
+ source: URL template for terrain tiles. Defaults to AWS elevation tiles.
1484
+ exaggeration: Terrain exaggeration factor. Defaults to 1.0.
1485
+ tile_size: Tile size in pixels. Defaults to 256.
1486
+ encoding: Encoding for the terrain tiles. Defaults to "terrarium".
1487
+ source_id: Unique identifier for the terrain source. Defaults to "terrain-dem".
1488
+ """
1489
+ self.session.m.set_terrain(
1490
+ source=source,
1491
+ exaggeration=exaggeration,
1492
+ tile_size=tile_size,
1493
+ encoding=encoding,
1494
+ source_id=source_id,
1495
+ )
1496
+ return f"Terrain added: {source}"
1497
+
1498
+ @tool
1499
+ def remove_terrain(self) -> None:
1500
+ """Remove terrain visualization from the map."""
1501
+ self.session.m.remove_terrain()
1502
+ return "Terrain removed."