geotask module¶
Main module.
Map (Map)
¶
This is the map class that inherits from ipyleaflet.Map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ipyleaflet |
Map |
The ipyleaflet.Map class. |
required |
Source code in geotask/geotask.py
class Map(ipyleaflet.Map):
"""This is the map class that inherits from ipyleaflet.Map.
Args:
ipyleaflet (Map): The ipyleaflet.Map class.
"""
def __init__(self, center=[20, 0], zoom=2, **kwargs):
"""Initialize the map.
Args:
center (list, optional): Set the center of the map. Defaults to [20, 0].
zoom (int, optional): Set the zoom level of the map. Defaults to 2.
"""
if "scroll_wheel_zoom" not in kwargs:
kwargs["scroll_wheel_zoom"] = True
if "add_layer_control" not in kwargs:
layer_control_flag = True
else:
layer_control_flag = kwargs["add_layer_control"]
kwargs.pop("add_layer_control", None)
super().__init__(center=center, zoom=zoom, **kwargs)
if layer_control_flag:
self.add_layers_control()
self.add_toolbar()
self.add_basemap_gui()
def add_tile_layer(self, url, name, **kwargs):
"""
Adds a tile layer to the current map.
Parameters:
url (str): The URL of the tile layer.
name (str): The name of the tile layer.
**kwargs: Additional keyword arguments for the TileLayer constructor.
Returns:
None
"""
layer = ipyleaflet.TileLayer(url=url, name=name, **kwargs)
self.add(layer)
def add_basemap(self, name):
"""
Adds a basemap to the current map.
Args:
name (str or object): The name of the basemap as a string, or an object representing the basemap.
Raises:
TypeError: If the name is neither a string nor an object representing a basemap.
Returns:
None
"""
if isinstance(name, str):
url = eval(f"basemaps.{name}").build_url()
self.add_tile_layer(url, name)
else:
self.add(name)
def add_layers_control(self, position="topright"):
"""Adds a layers control to the map.
Args:
position (str, optional): The position of the layers control. Defaults to "topright".
"""
self.add_control(ipyleaflet.LayersControl(position=position))
def add_geojson(self, data, name="geojson", **kwargs):
"""Adds a GeoJSON layer to the map.
Args:
data (str | dict): The GeoJSON data as a string, a dictionary, or a URL.
name (str, optional): The name of the layer. Defaults to "geojson".
"""
import json
import requests
if isinstance(data, str):
if data.startswith('http://') or data.startswith('https://'):
response = requests.get(data)
response.raise_for_status()
data = response.json()
else:
# It's a file path
with open(data, 'r') as f:
data = json.load(f)
if "style" not in kwargs:
kwargs["style"] = {"color": "black", "weight": 1, "fillOpacity": 0}
if "hover_style" not in kwargs:
kwargs["hover_style"] = {"fillColor": "#542974", "fillOpacity": 0.7}
layer = ipyleaflet.GeoJSON(data=data, name=name, **kwargs)
self.add(layer)
def add_shp(self, data, name="shp", **kwargs):
"""
Adds a shapefile to the current map.
Args:
data (str or dict): The path to the shapefile as a string, or a dictionary representing the shapefile.
name (str, optional): The name of the layer. Defaults to "shp".
**kwargs: Arbitrary keyword arguments.
Raises:
TypeError: If the data is neither a string nor a dictionary representing a shapefile.
Returns:
None
"""
import shapefile
import json
if isinstance(data, str):
with shapefile.Reader(data) as shp:
data = shp.__geo_interface__
self.add_geojson(data, name, **kwargs)
import geopandas as gpd
from ipyleaflet import GeoData
from shapely.geometry import Point, LineString
def add_vector(self, data):
"""
Add vector data to the map.
Args:
data (str or geopandas.GeoDataFrame): The vector data to add. This can be a file path or a GeoDataFrame.
"""
import geopandas as gpd
from ipyleaflet import GeoData
if isinstance(data, gpd.GeoDataFrame):
vector_layer = GeoData(geo_dataframe=data)
elif isinstance(data, str):
vector_layer = GeoData(geo_dataframe=gpd.read_file(data))
else:
raise ValueError("Unsupported data format. Please provide a GeoDataFrame or a file path.")
self.add_layer(vector_layer)
def add_image(self, url, bounds, name="image", **kwargs):
"""
Adds an image overlay to the map.
Args:
url (str): The URL of the image to add.
bounds (list): The bounds of the image as a list of tuples.
name (str, optional): The name of the image overlay. Defaults to "image".
"""
layer = ipyleaflet.ImageOverlay(url=url, bounds=bounds, name=name, **kwargs)
self.add(layer)
def add_raster(self, data, name="raster", zoom_to_layer=True, **kwargs):
"""Adds a raster layer to the map.
Args:
data (str or rasterio.DatasetReader): The raster data to add. This can be a file path or a rasterio dataset.
colormap (str, optional): The name of the colormap to use. Defaults to "inferno".
name (str, optional): The name of the raster layer. Defaults to "raster".
**kwargs: Arbitrary keyword arguments.
Returns:
None
"""
try:
from localtileserver import TileClient, get_leaflet_tile_layer
except ImportError:
raise ImportError("Please install the localtileserver package.")
client = TileClient(data)
layer = get_leaflet_tile_layer(client, name=name, **kwargs)
self.add(layer)
if zoom_to_layer:
self.center = client.center()
self.zoom = client.default_zoom
def add_zoom_slider(
self, description="Zoom level:", min=0, max=24, value=10, position="topright"
):
"""Adds a zoom slider to the map.
Args:
position (str, optional): The position of the zoom slider. Defaults to "topright".
Returns:
None
"""
zoom_slider = widgets.IntSlider(
description=description, min=min, max=max, value=value
)
control = ipyleaflet.WidgetControl(widget=zoom_slider, position=position)
self.add(control)
widgets.jslink((zoom_slider, "value"), (self, "zoom"))
def add_widget(self, widget, position="topright"):
"""Adds a widget to the map.
Args:
widget (object): The widget to add.
position (str, optional): The position of the widget. Defaults to "topright".
Returns:
None
"""
control = ipyleaflet.WidgetControl(widget=widget, position=position)
self.add(control)
def add_opacity_slider(
self, layer_index=-1, description="Opacity:", position="topright"
):
"""Adds an opacity slider for the specified layer.
Args:
layer (object): The layer for which to add the opacity slider.
description (str, optional): The description of the opacity slider. Defaults to "Opacity:".
position (str, optional): The position of the opacity slider. Defaults to "topright".
Returns:
None
"""
layer = self.layers[layer_index]
opacity_slider = widgets.FloatSlider(
description=description, min=0, max=1, value=layer.opacity, style={"description_width": "initial"}
)
def update_opacity(change):
"""
Updates the opacity of a layer based on the new value from a slider.
This function is designed to be used as a callback for an ipywidgets slider.
It takes a dictionary with a "new" key representing the new value of the slider,
and sets the opacity of a global layer variable to this new value.
Args:
change (dict): A dictionary with a "new" key representing the new value of the slider.
Returns:
None
"""
layer.opacity = change["new"]
opacity_slider.observe(update_opacity, "value")
control = ipyleaflet.WidgetControl(widget=opacity_slider, position=position)
self.add(control)
from ipywidgets import Dropdown, Button, HBox
def add_basemap_gui(self, basemaps=None, position="topright"):
"""Adds a basemap GUI to the map.
Args:
position (str, optional): The position of the basemap GUI. Defaults to "topright".
"""
padding = "0px 0px 0px 5px" # upper, right, bottom, left
basemap_selector = widgets.Dropdown(
options=[
"OpenStreetMap",
"OpenTopoMap",
"Esri.WorldImagery",
"Esri.NatGeoWorldMap",
],
description="",
layout=widgets.Layout(width='auto') # Set the width to auto
)
def update_basemap(change):
"""
Updates the basemap with the new selected value.
Parameters:
change (dict): A dictionary containing the new value. The new basemap is expected to be in change['new'].
Returns:
None
"""
self.add_basemap(change["new"])
basemap_selector.observe(update_basemap, "value")
close_button = widgets.ToggleButton(
value=False,
tooltip="Close the tool",
icon="times",
button_style="primary",
layout=widgets.Layout(height="28px", width="28px", padding=padding),
)
def on_close_button_clicked(change):
"""
Handles the event when the close button is clicked. If the new value of the change is True, it removes the control.
Parameters:
change (dict): A dictionary containing the new value. The new state of the button is expected to be in change['new'].
Returns:
None
"""
if change["new"]:
# Remove the control when the close button is clicked
self.remove(control)
close_button.observe(on_close_button_clicked, "value")
# Create a box to hold the dropdown and the close button
box = widgets.HBox([close_button, basemap_selector])
control = ipyleaflet.WidgetControl(widget=box, position=position)
self.add(control)
def add_toolbar(self, position="topright"):
"""Adds a toolbar to the map.
Args:
position (str, optional): The position of the toolbar. Defaults to "topright".
"""
padding = "0px 0px 0px 5px" # upper, right, bottom, left
toolbar_button = widgets.ToggleButton(
value=False,
tooltip="Toolbar",
icon="wrench",
layout=widgets.Layout(width="28px", height="28px", padding=padding),
)
close_button = widgets.ToggleButton(
value=False,
tooltip="Close the tool",
icon="times",
button_style="primary",
layout=widgets.Layout(height="28px", width="28px", padding=padding),
)
toolbar = widgets.VBox([toolbar_button])
def close_click(change):
"""
Handles the event when the close button is clicked. If the new value of the change is True, it closes the toolbar_button, close_button, and toolbar.
Parameters:
change (dict): A dictionary containing the new value. The new state of the button is expected to be in change['new'].
Returns:
None
"""
if change["new"]:
toolbar_button.close()
close_button.close()
toolbar.close()
close_button.observe(close_click, "value")
rows = 2
cols = 2
grid = widgets.GridspecLayout(
rows, cols, grid_gap="0px", layout=widgets.Layout(width="65px")
)
icons = ["folder-open", "map", "info", "question"]
for i in range(rows):
for j in range(cols):
grid[i, j] = widgets.Button(
description="",
button_style="primary",
icon=icons[i * rows + j],
layout=widgets.Layout(width="28px", padding="0px"),
)
def toolbar_click(change):
"""
Handles the event when the toolbar button is clicked. If the new value of the change is True, it sets the children of the toolbar to include both the close button and the toolbar button, as well as the grid. Otherwise, it sets the children of the toolbar to only include the toolbar button.
Parameters:
change (dict): A dictionary containing the new value. The new state of the button is expected to be in change['new'].
Returns:
None
"""
if change["new"]:
toolbar.children = [widgets.HBox([close_button, toolbar_button]), grid]
else:
toolbar.children = [toolbar_button]
toolbar_button.observe(toolbar_click, "value")
toolbar_ctrl = WidgetControl(widget=toolbar, position="topright")
self.add(toolbar_ctrl)
output = widgets.Output()
output_control = WidgetControl(widget=output, position="bottomright")
self.add(output_control)
def toolbar_callback(change):
"""
Handles the event when a toolbar button is clicked. Depending on the icon of the clicked button, it performs different actions.
Parameters:
change: An object representing the clicked button. The icon of the button is expected to be in change.icon.
Returns:
None
"""
if change.icon == "folder-open":
with output:
output.clear_output()
print(f"You can open a file")
elif change.icon == "map":
with output:
output.clear_output()
print(f"You can add a layer")
else:
with output:
output.clear_output()
print(f"Icon: {change.icon}")
for tool in grid.children:
tool.on_click(toolbar_callback)
with output:
print("Toolbar is ready")
import pandas as pd
import geopandas as gpd
import json
def add_points(self, df):
"""
Adds points to the map based on the data in the DataFrame. Each point represents a city, with its color indicating the population of the city. A rank column is added to the DataFrame based on the population. A legend is also added to the map to indicate the population ranges for each color.
Parameters:
df (pandas.DataFrame): The DataFrame containing the data. It is expected to have columns 'population', 'latitude', 'longitude', 'name', and 'country'.
Returns:
None
"""
# Add a rank column based on population
df['rank'] = df['population'].rank(method='min')
# Define the color bins for the population
bins = [500, 50000, 500000, 5000000, 50000000, float('inf')]
colors = ['#fee5d9', '#fcae91', '#fb6a4a', '#de2d26', '#a50f15']
for _, row in df.iterrows():
# Determine the color for the population
for i, b in enumerate(bins):
if row['population'] <= b:
color = colors[i]
break
circle = ipyleaflet.Circle(
location=(row['latitude'], row['longitude']),
radius=50000, # Increase the radius to make the circle bigger
color=color,
fill_color=color,
fill_opacity=0.8
)
message = widgets.HTML(
value=f"City: {row['name']}<br><b>Country: {row['country']}</b><br>Population: {row['population']}<br><b>Rank: {row['rank']}</b>",
placeholder='',
description='',
)
circle.popup = message
self.add_layer(circle)
# Add a legend
legend_html = """
<div style="width: 100px; height: 90px;
border:2px solid grey; z-index:9999; font-size:10px; line-height:1.2;">
<strong> Population </strong><br>
<div style="margin-top:5px;">
500 <i class="fa fa-circle fa-1x" style="color:#fee5d9"></i><br>
50000 <i class="fa fa-circle fa-1x" style="color:#fcae91"></i><br>
500000 <i class="fa fa-circle fa-1x" style="color:#fb6a4a"></i><br>
5000000 <i class="fa fa-circle fa-1x" style="color:#de2d26"></i><br>
50000000 <i class="fa fa-circle fa-1x" style="color:#a50f15"></i>
</div>
"""
legend = widgets.HTML(legend_html)
legend_control = WidgetControl(widget=legend, position='bottomleft')
self.add_control(legend_control)
__init__(self, center=[20, 0], zoom=2, **kwargs)
special
¶
Initialize the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
center |
list |
Set the center of the map. Defaults to [20, 0]. |
[20, 0] |
zoom |
int |
Set the zoom level of the map. Defaults to 2. |
2 |
Source code in geotask/geotask.py
def __init__(self, center=[20, 0], zoom=2, **kwargs):
"""Initialize the map.
Args:
center (list, optional): Set the center of the map. Defaults to [20, 0].
zoom (int, optional): Set the zoom level of the map. Defaults to 2.
"""
if "scroll_wheel_zoom" not in kwargs:
kwargs["scroll_wheel_zoom"] = True
if "add_layer_control" not in kwargs:
layer_control_flag = True
else:
layer_control_flag = kwargs["add_layer_control"]
kwargs.pop("add_layer_control", None)
super().__init__(center=center, zoom=zoom, **kwargs)
if layer_control_flag:
self.add_layers_control()
self.add_toolbar()
self.add_basemap_gui()
add_basemap(self, name)
¶
Adds a basemap to the current map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str or object |
The name of the basemap as a string, or an object representing the basemap. |
required |
Exceptions:
Type | Description |
---|---|
TypeError |
If the name is neither a string nor an object representing a basemap. |
Returns:
Type | Description |
---|---|
None |
Source code in geotask/geotask.py
def add_basemap(self, name):
"""
Adds a basemap to the current map.
Args:
name (str or object): The name of the basemap as a string, or an object representing the basemap.
Raises:
TypeError: If the name is neither a string nor an object representing a basemap.
Returns:
None
"""
if isinstance(name, str):
url = eval(f"basemaps.{name}").build_url()
self.add_tile_layer(url, name)
else:
self.add(name)
add_basemap_gui(self, basemaps=None, position='topright')
¶
Adds a basemap GUI to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
position |
str |
The position of the basemap GUI. Defaults to "topright". |
'topright' |
Source code in geotask/geotask.py
def add_basemap_gui(self, basemaps=None, position="topright"):
"""Adds a basemap GUI to the map.
Args:
position (str, optional): The position of the basemap GUI. Defaults to "topright".
"""
padding = "0px 0px 0px 5px" # upper, right, bottom, left
basemap_selector = widgets.Dropdown(
options=[
"OpenStreetMap",
"OpenTopoMap",
"Esri.WorldImagery",
"Esri.NatGeoWorldMap",
],
description="",
layout=widgets.Layout(width='auto') # Set the width to auto
)
def update_basemap(change):
"""
Updates the basemap with the new selected value.
Parameters:
change (dict): A dictionary containing the new value. The new basemap is expected to be in change['new'].
Returns:
None
"""
self.add_basemap(change["new"])
basemap_selector.observe(update_basemap, "value")
close_button = widgets.ToggleButton(
value=False,
tooltip="Close the tool",
icon="times",
button_style="primary",
layout=widgets.Layout(height="28px", width="28px", padding=padding),
)
def on_close_button_clicked(change):
"""
Handles the event when the close button is clicked. If the new value of the change is True, it removes the control.
Parameters:
change (dict): A dictionary containing the new value. The new state of the button is expected to be in change['new'].
Returns:
None
"""
if change["new"]:
# Remove the control when the close button is clicked
self.remove(control)
close_button.observe(on_close_button_clicked, "value")
# Create a box to hold the dropdown and the close button
box = widgets.HBox([close_button, basemap_selector])
control = ipyleaflet.WidgetControl(widget=box, position=position)
self.add(control)
add_geojson(self, data, name='geojson', **kwargs)
¶
Adds a GeoJSON layer to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data |
str | dict |
The GeoJSON data as a string, a dictionary, or a URL. |
required |
name |
str |
The name of the layer. Defaults to "geojson". |
'geojson' |
Source code in geotask/geotask.py
def add_geojson(self, data, name="geojson", **kwargs):
"""Adds a GeoJSON layer to the map.
Args:
data (str | dict): The GeoJSON data as a string, a dictionary, or a URL.
name (str, optional): The name of the layer. Defaults to "geojson".
"""
import json
import requests
if isinstance(data, str):
if data.startswith('http://') or data.startswith('https://'):
response = requests.get(data)
response.raise_for_status()
data = response.json()
else:
# It's a file path
with open(data, 'r') as f:
data = json.load(f)
if "style" not in kwargs:
kwargs["style"] = {"color": "black", "weight": 1, "fillOpacity": 0}
if "hover_style" not in kwargs:
kwargs["hover_style"] = {"fillColor": "#542974", "fillOpacity": 0.7}
layer = ipyleaflet.GeoJSON(data=data, name=name, **kwargs)
self.add(layer)
add_image(self, url, bounds, name='image', **kwargs)
¶
Adds an image overlay to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
url |
str |
The URL of the image to add. |
required |
bounds |
list |
The bounds of the image as a list of tuples. |
required |
name |
str |
The name of the image overlay. Defaults to "image". |
'image' |
Source code in geotask/geotask.py
def add_image(self, url, bounds, name="image", **kwargs):
"""
Adds an image overlay to the map.
Args:
url (str): The URL of the image to add.
bounds (list): The bounds of the image as a list of tuples.
name (str, optional): The name of the image overlay. Defaults to "image".
"""
layer = ipyleaflet.ImageOverlay(url=url, bounds=bounds, name=name, **kwargs)
self.add(layer)
add_layers_control(self, position='topright')
¶
Adds a layers control to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
position |
str |
The position of the layers control. Defaults to "topright". |
'topright' |
Source code in geotask/geotask.py
def add_layers_control(self, position="topright"):
"""Adds a layers control to the map.
Args:
position (str, optional): The position of the layers control. Defaults to "topright".
"""
self.add_control(ipyleaflet.LayersControl(position=position))
add_opacity_slider(self, layer_index=-1, description='Opacity:', position='topright')
¶
Adds an opacity slider for the specified layer.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
layer |
object |
The layer for which to add the opacity slider. |
required |
description |
str |
The description of the opacity slider. Defaults to "Opacity:". |
'Opacity:' |
position |
str |
The position of the opacity slider. Defaults to "topright". |
'topright' |
Returns:
Type | Description |
---|---|
None |
Source code in geotask/geotask.py
def add_opacity_slider(
self, layer_index=-1, description="Opacity:", position="topright"
):
"""Adds an opacity slider for the specified layer.
Args:
layer (object): The layer for which to add the opacity slider.
description (str, optional): The description of the opacity slider. Defaults to "Opacity:".
position (str, optional): The position of the opacity slider. Defaults to "topright".
Returns:
None
"""
layer = self.layers[layer_index]
opacity_slider = widgets.FloatSlider(
description=description, min=0, max=1, value=layer.opacity, style={"description_width": "initial"}
)
def update_opacity(change):
"""
Updates the opacity of a layer based on the new value from a slider.
This function is designed to be used as a callback for an ipywidgets slider.
It takes a dictionary with a "new" key representing the new value of the slider,
and sets the opacity of a global layer variable to this new value.
Args:
change (dict): A dictionary with a "new" key representing the new value of the slider.
Returns:
None
"""
layer.opacity = change["new"]
opacity_slider.observe(update_opacity, "value")
control = ipyleaflet.WidgetControl(widget=opacity_slider, position=position)
self.add(control)
from ipywidgets import Dropdown, Button, HBox
add_points(self, df)
¶
Adds points to the map based on the data in the DataFrame. Each point represents a city, with its color indicating the population of the city. A rank column is added to the DataFrame based on the population. A legend is also added to the map to indicate the population ranges for each color.
df (pandas.DataFrame): The DataFrame containing the data. It is expected to have columns 'population', 'latitude', 'longitude', 'name', and 'country'.
None
Source code in geotask/geotask.py
def add_points(self, df):
"""
Adds points to the map based on the data in the DataFrame. Each point represents a city, with its color indicating the population of the city. A rank column is added to the DataFrame based on the population. A legend is also added to the map to indicate the population ranges for each color.
Parameters:
df (pandas.DataFrame): The DataFrame containing the data. It is expected to have columns 'population', 'latitude', 'longitude', 'name', and 'country'.
Returns:
None
"""
# Add a rank column based on population
df['rank'] = df['population'].rank(method='min')
# Define the color bins for the population
bins = [500, 50000, 500000, 5000000, 50000000, float('inf')]
colors = ['#fee5d9', '#fcae91', '#fb6a4a', '#de2d26', '#a50f15']
for _, row in df.iterrows():
# Determine the color for the population
for i, b in enumerate(bins):
if row['population'] <= b:
color = colors[i]
break
circle = ipyleaflet.Circle(
location=(row['latitude'], row['longitude']),
radius=50000, # Increase the radius to make the circle bigger
color=color,
fill_color=color,
fill_opacity=0.8
)
message = widgets.HTML(
value=f"City: {row['name']}<br><b>Country: {row['country']}</b><br>Population: {row['population']}<br><b>Rank: {row['rank']}</b>",
placeholder='',
description='',
)
circle.popup = message
self.add_layer(circle)
# Add a legend
legend_html = """
<div style="width: 100px; height: 90px;
border:2px solid grey; z-index:9999; font-size:10px; line-height:1.2;">
<strong> Population </strong><br>
<div style="margin-top:5px;">
500 <i class="fa fa-circle fa-1x" style="color:#fee5d9"></i><br>
50000 <i class="fa fa-circle fa-1x" style="color:#fcae91"></i><br>
500000 <i class="fa fa-circle fa-1x" style="color:#fb6a4a"></i><br>
5000000 <i class="fa fa-circle fa-1x" style="color:#de2d26"></i><br>
50000000 <i class="fa fa-circle fa-1x" style="color:#a50f15"></i>
</div>
"""
legend = widgets.HTML(legend_html)
legend_control = WidgetControl(widget=legend, position='bottomleft')
self.add_control(legend_control)
add_raster(self, data, name='raster', zoom_to_layer=True, **kwargs)
¶
Adds a raster layer to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data |
str or rasterio.DatasetReader |
The raster data to add. This can be a file path or a rasterio dataset. |
required |
colormap |
str |
The name of the colormap to use. Defaults to "inferno". |
required |
name |
str |
The name of the raster layer. Defaults to "raster". |
'raster' |
**kwargs |
Arbitrary keyword arguments. |
{} |
Returns:
Type | Description |
---|---|
None |
Source code in geotask/geotask.py
def add_raster(self, data, name="raster", zoom_to_layer=True, **kwargs):
"""Adds a raster layer to the map.
Args:
data (str or rasterio.DatasetReader): The raster data to add. This can be a file path or a rasterio dataset.
colormap (str, optional): The name of the colormap to use. Defaults to "inferno".
name (str, optional): The name of the raster layer. Defaults to "raster".
**kwargs: Arbitrary keyword arguments.
Returns:
None
"""
try:
from localtileserver import TileClient, get_leaflet_tile_layer
except ImportError:
raise ImportError("Please install the localtileserver package.")
client = TileClient(data)
layer = get_leaflet_tile_layer(client, name=name, **kwargs)
self.add(layer)
if zoom_to_layer:
self.center = client.center()
self.zoom = client.default_zoom
add_shp(self, data, name='shp', **kwargs)
¶
Adds a shapefile to the current map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data |
str or dict |
The path to the shapefile as a string, or a dictionary representing the shapefile. |
required |
name |
str |
The name of the layer. Defaults to "shp". |
'shp' |
**kwargs |
Arbitrary keyword arguments. |
{} |
Exceptions:
Type | Description |
---|---|
TypeError |
If the data is neither a string nor a dictionary representing a shapefile. |
Returns:
Type | Description |
---|---|
None |
Source code in geotask/geotask.py
def add_shp(self, data, name="shp", **kwargs):
"""
Adds a shapefile to the current map.
Args:
data (str or dict): The path to the shapefile as a string, or a dictionary representing the shapefile.
name (str, optional): The name of the layer. Defaults to "shp".
**kwargs: Arbitrary keyword arguments.
Raises:
TypeError: If the data is neither a string nor a dictionary representing a shapefile.
Returns:
None
"""
import shapefile
import json
if isinstance(data, str):
with shapefile.Reader(data) as shp:
data = shp.__geo_interface__
self.add_geojson(data, name, **kwargs)
import geopandas as gpd
from ipyleaflet import GeoData
from shapely.geometry import Point, LineString
add_tile_layer(self, url, name, **kwargs)
¶
Adds a tile layer to the current map.
url (str): The URL of the tile layer. name (str): The name of the tile layer. **kwargs: Additional keyword arguments for the TileLayer constructor.
None
Source code in geotask/geotask.py
def add_tile_layer(self, url, name, **kwargs):
"""
Adds a tile layer to the current map.
Parameters:
url (str): The URL of the tile layer.
name (str): The name of the tile layer.
**kwargs: Additional keyword arguments for the TileLayer constructor.
Returns:
None
"""
layer = ipyleaflet.TileLayer(url=url, name=name, **kwargs)
self.add(layer)
add_toolbar(self, position='topright')
¶
Adds a toolbar to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
position |
str |
The position of the toolbar. Defaults to "topright". |
'topright' |
Source code in geotask/geotask.py
def add_toolbar(self, position="topright"):
"""Adds a toolbar to the map.
Args:
position (str, optional): The position of the toolbar. Defaults to "topright".
"""
padding = "0px 0px 0px 5px" # upper, right, bottom, left
toolbar_button = widgets.ToggleButton(
value=False,
tooltip="Toolbar",
icon="wrench",
layout=widgets.Layout(width="28px", height="28px", padding=padding),
)
close_button = widgets.ToggleButton(
value=False,
tooltip="Close the tool",
icon="times",
button_style="primary",
layout=widgets.Layout(height="28px", width="28px", padding=padding),
)
toolbar = widgets.VBox([toolbar_button])
def close_click(change):
"""
Handles the event when the close button is clicked. If the new value of the change is True, it closes the toolbar_button, close_button, and toolbar.
Parameters:
change (dict): A dictionary containing the new value. The new state of the button is expected to be in change['new'].
Returns:
None
"""
if change["new"]:
toolbar_button.close()
close_button.close()
toolbar.close()
close_button.observe(close_click, "value")
rows = 2
cols = 2
grid = widgets.GridspecLayout(
rows, cols, grid_gap="0px", layout=widgets.Layout(width="65px")
)
icons = ["folder-open", "map", "info", "question"]
for i in range(rows):
for j in range(cols):
grid[i, j] = widgets.Button(
description="",
button_style="primary",
icon=icons[i * rows + j],
layout=widgets.Layout(width="28px", padding="0px"),
)
def toolbar_click(change):
"""
Handles the event when the toolbar button is clicked. If the new value of the change is True, it sets the children of the toolbar to include both the close button and the toolbar button, as well as the grid. Otherwise, it sets the children of the toolbar to only include the toolbar button.
Parameters:
change (dict): A dictionary containing the new value. The new state of the button is expected to be in change['new'].
Returns:
None
"""
if change["new"]:
toolbar.children = [widgets.HBox([close_button, toolbar_button]), grid]
else:
toolbar.children = [toolbar_button]
toolbar_button.observe(toolbar_click, "value")
toolbar_ctrl = WidgetControl(widget=toolbar, position="topright")
self.add(toolbar_ctrl)
output = widgets.Output()
output_control = WidgetControl(widget=output, position="bottomright")
self.add(output_control)
def toolbar_callback(change):
"""
Handles the event when a toolbar button is clicked. Depending on the icon of the clicked button, it performs different actions.
Parameters:
change: An object representing the clicked button. The icon of the button is expected to be in change.icon.
Returns:
None
"""
if change.icon == "folder-open":
with output:
output.clear_output()
print(f"You can open a file")
elif change.icon == "map":
with output:
output.clear_output()
print(f"You can add a layer")
else:
with output:
output.clear_output()
print(f"Icon: {change.icon}")
for tool in grid.children:
tool.on_click(toolbar_callback)
with output:
print("Toolbar is ready")
add_vector(self, data)
¶
Add vector data to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data |
str or geopandas.GeoDataFrame |
The vector data to add. This can be a file path or a GeoDataFrame. |
required |
Source code in geotask/geotask.py
def add_vector(self, data):
"""
Add vector data to the map.
Args:
data (str or geopandas.GeoDataFrame): The vector data to add. This can be a file path or a GeoDataFrame.
"""
import geopandas as gpd
from ipyleaflet import GeoData
if isinstance(data, gpd.GeoDataFrame):
vector_layer = GeoData(geo_dataframe=data)
elif isinstance(data, str):
vector_layer = GeoData(geo_dataframe=gpd.read_file(data))
else:
raise ValueError("Unsupported data format. Please provide a GeoDataFrame or a file path.")
self.add_layer(vector_layer)
add_widget(self, widget, position='topright')
¶
Adds a widget to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
widget |
object |
The widget to add. |
required |
position |
str |
The position of the widget. Defaults to "topright". |
'topright' |
Returns:
Type | Description |
---|---|
None |
Source code in geotask/geotask.py
def add_widget(self, widget, position="topright"):
"""Adds a widget to the map.
Args:
widget (object): The widget to add.
position (str, optional): The position of the widget. Defaults to "topright".
Returns:
None
"""
control = ipyleaflet.WidgetControl(widget=widget, position=position)
self.add(control)
add_zoom_slider(self, description='Zoom level:', min=0, max=24, value=10, position='topright')
¶
Adds a zoom slider to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
position |
str |
The position of the zoom slider. Defaults to "topright". |
'topright' |
Returns:
Type | Description |
---|---|
None |
Source code in geotask/geotask.py
def add_zoom_slider(
self, description="Zoom level:", min=0, max=24, value=10, position="topright"
):
"""Adds a zoom slider to the map.
Args:
position (str, optional): The position of the zoom slider. Defaults to "topright".
Returns:
None
"""
zoom_slider = widgets.IntSlider(
description=description, min=min, max=max, value=value
)
control = ipyleaflet.WidgetControl(widget=zoom_slider, position=position)
self.add(control)
widgets.jslink((zoom_slider, "value"), (self, "zoom"))