Skip to content

geohey 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 geohey/geohey.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()

    def add_tile_layer(self, url, name, **kwargs):
        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 or a dictionary.
            name (str, optional): The name of the layer. Defaults to "geojson".
        """
        import json

        if isinstance(data, str):
            with open(data) as f:
                data = json.load(f)

        if "style" not in kwargs:
            kwargs["style"] = {"color": "blue", "weight": 1, "fillOpacity": 0}

        if "hover_style" not in kwargs:
            kwargs["hover_style"] = {"fillColor": "#ff0000", "fillOpacity": 0.5}

        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)

    def add_image(self, url, bounds, name="image", **kwargs):
        """Adds an image overlay to the map.

        Args:
            url (str): The URL of the image.
            bounds (list): The bounds of the image.
            name (str, optional): The name of the layer. 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): The path to the raster file.
            name (str, optional): The name of the layer. Defaults to "raster".
        """

        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".
        """
        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 be added.
            position (str, optional): The position of the widget. Defaults to "topright".
        """
        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 to the map.

        Args:
            layer (object): The layer to which the opacity slider is added.
            description (str, optional): The description of the opacity slider. Defaults to "Opacity".
            position (str, optional): The position of the opacity slider. Defaults to "topright".
        """
        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):
            layer.opacity = change["new"]

        opacity_slider.observe(update_opacity, "value")

        control = ipyleaflet.WidgetControl(widget=opacity_slider, position=position)
        self.add(control)

    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".
        """

        basemap_selector = widgets.Dropdown(
            options=[
                "OpenStreetMap",
                "OpenTopoMap",
                "Esri.WorldImagery",
                "Esri.NatGeoWorldMap",
            ],
            description="Basemap",
        )

        def update_basemap(change):
            self.add_basemap(change["new"])

        basemap_selector.observe(update_basemap, "value")

        control = ipyleaflet.WidgetControl(widget=basemap_selector, 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):
            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):
            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):
            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)

    def add_split_map(self, left_layer, right_layer, **kwargs):
        """Adds a split map to the current map.

        Args:
            left_layer (object): The left layer of the split map.
            right_layer (object): The right layer of the split map.
        """

        control = SplitMapControl(
            left_layer=left_layer,
            right_layer=right_layer,
        )
        self.add(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 geohey/geohey.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()

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 geohey/geohey.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 geohey/geohey.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".
    """

    basemap_selector = widgets.Dropdown(
        options=[
            "OpenStreetMap",
            "OpenTopoMap",
            "Esri.WorldImagery",
            "Esri.NatGeoWorldMap",
        ],
        description="Basemap",
    )

    def update_basemap(change):
        self.add_basemap(change["new"])

    basemap_selector.observe(update_basemap, "value")

    control = ipyleaflet.WidgetControl(widget=basemap_selector, 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 or a dictionary.

required
name str

The name of the layer. Defaults to "geojson".

'geojson'
Source code in geohey/geohey.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 or a dictionary.
        name (str, optional): The name of the layer. Defaults to "geojson".
    """
    import json

    if isinstance(data, str):
        with open(data) as f:
            data = json.load(f)

    if "style" not in kwargs:
        kwargs["style"] = {"color": "blue", "weight": 1, "fillOpacity": 0}

    if "hover_style" not in kwargs:
        kwargs["hover_style"] = {"fillColor": "#ff0000", "fillOpacity": 0.5}

    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.

required
bounds list

The bounds of the image.

required
name str

The name of the layer. Defaults to "image".

'image'
Source code in geohey/geohey.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.
        bounds (list): The bounds of the image.
        name (str, optional): The name of the layer. 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 geohey/geohey.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 to the map.

Parameters:

Name Type Description Default
layer object

The layer to which the opacity slider is added.

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'
Source code in geohey/geohey.py
def add_opacity_slider(
    self, layer_index=-1, description="Opacity", position="topright"
):
    """Adds an opacity slider to the map.

    Args:
        layer (object): The layer to which the opacity slider is added.
        description (str, optional): The description of the opacity slider. Defaults to "Opacity".
        position (str, optional): The position of the opacity slider. Defaults to "topright".
    """
    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):
        layer.opacity = change["new"]

    opacity_slider.observe(update_opacity, "value")

    control = ipyleaflet.WidgetControl(widget=opacity_slider, position=position)
    self.add(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

The path to the raster file.

required
name str

The name of the layer. Defaults to "raster".

'raster'
Source code in geohey/geohey.py
def add_raster(self, data, name="raster", zoom_to_layer=True, **kwargs):
    """Adds a raster layer to the map.

    Args:
        data (str): The path to the raster file.
        name (str, optional): The name of the layer. Defaults to "raster".
    """

    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 geohey/geohey.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)

add_split_map(self, left_layer, right_layer, **kwargs)

Adds a split map to the current map.

Parameters:

Name Type Description Default
left_layer object

The left layer of the split map.

required
right_layer object

The right layer of the split map.

required
Source code in geohey/geohey.py
def add_split_map(self, left_layer, right_layer, **kwargs):
    """Adds a split map to the current map.

    Args:
        left_layer (object): The left layer of the split map.
        right_layer (object): The right layer of the split map.
    """

    control = SplitMapControl(
        left_layer=left_layer,
        right_layer=right_layer,
    )
    self.add(control)

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 geohey/geohey.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):
        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):
        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):
        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)

add_widget(self, widget, position='topright')

Adds a widget to the map.

Parameters:

Name Type Description Default
widget object

The widget to be added.

required
position str

The position of the widget. Defaults to "topright".

'topright'
Source code in geohey/geohey.py
def add_widget(self, widget, position="topright"):
    """Adds a widget to the map.

    Args:
        widget (object): The widget to be added.
        position (str, optional): The position of the widget. Defaults to "topright".
    """
    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'
Source code in geohey/geohey.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".
    """
    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"))