Skip to content

ipyleaflet_mapping module

This module provides a custom Map class that extends ipyleaflet.Map

Map (Map)

Source code in biospat/mapping.py
class Map(ipyleaflet.Map):
    def __init__(self, center=[20, 0], zoom=2, height="600px", **kwargs):

        super().__init__(center=center, zoom=zoom, **kwargs)
        self.layout.height = height
        self.scroll_wheel_zoom = True

    def add_basemap(self, basemap="OpenTopoMap"):
        """Add basemap to the map.

        Args:
            basemap (str, optional): Basemap name. Defaults to "OpenTopoMap".

        Available basemaps:
            - "OpenTopoMap": A topographic map.
            - "OpenStreetMap.Mapnik": A standard street map.
            - "Esri.WorldImagery": Satellite imagery.
            - "Esri.WorldTerrain": Terrain map from Esri.
            - "Esri.WorldStreetMap": Street map from Esri.
            - "CartoDB.Positron": A light, minimalist map style.
            - "CartoDB.DarkMatter": A dark-themed map style.
        """

        url = eval(f"ipyleaflet.basemaps.{basemap}").build_url()
        layer = ipyleaflet.TileLayer(url=url, name=basemap)
        self.add(layer)

    def add_basemap_gui(self, options=None, position="topright"):
        """Adds a graphical user interface (GUI) for dynamically changing basemaps.

        Params:
            options (list, optional): A list of basemap options to display in the dropdown.
                Defaults to ["OpenStreetMap.Mapnik", "OpenTopoMap", "Esri.WorldImagery", "Esri.WorldTerrain", "Esri.WorldStreetMap", "CartoDB.DarkMatter", "CartoDB.Positron"].
            position (str, optional): The position of the widget on the map. Defaults to "topright".

        Behavior:
            - A toggle button is used to show or hide the dropdown and close button.
            - The dropdown allows users to select a basemap from the provided options.
            - The close button removes the widget from the map.

        Event Handlers:
            - `on_toggle_change`: Toggles the visibility of the dropdown and close button.
            - `on_button_click`: Closes and removes the widget from the map.
            - `on_dropdown_change`: Updates the map's basemap when a new option is selected.

        Returns:
            None
        """
        if options is None:
            options = [
                "OpenStreetMap.Mapnik",
                "OpenTopoMap",
                "Esri.WorldImagery",
                "Esri.WorldTerrain",
                "Esri.WorldStreetMap",
                "CartoDB.DarkMatter",
                "CartoDB.Positron",
            ]

        toggle = widgets.ToggleButton(
            value=True,
            button_style="",
            tooltip="Click me",
            icon="map",
        )
        toggle.layout = widgets.Layout(width="38px", height="38px")

        dropdown = widgets.Dropdown(
            options=options,
            value=options[0],
            description="Basemap:",
            style={"description_width": "initial"},
        )
        dropdown.layout = widgets.Layout(width="250px", height="38px")

        button = widgets.Button(
            icon="times",
        )
        button.layout = widgets.Layout(width="38px", height="38px")

        hbox = widgets.HBox([toggle, dropdown, button])

        def on_toggle_change(change):
            if change["new"]:
                hbox.children = [toggle, dropdown, button]
            else:
                hbox.children = [toggle]

        toggle.observe(on_toggle_change, names="value")

        def on_button_click(b):
            hbox.close()
            toggle.close()
            dropdown.close()
            button.close()

        button.on_click(on_button_click)

        def on_dropdown_change(change):
            if change["new"]:
                self.layers = self.layers[:-2]
                self.add_basemap(change["new"])

        dropdown.observe(on_dropdown_change, names="value")

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

    def add_widget(self, widget, position="topright", **kwargs):
        """Add a widget to the map.

        Args:
            widget (ipywidgets.Widget): The widget to add.
            position (str, optional): Position of the widget. Defaults to "topright".
            **kwargs: Additional keyword arguments for the WidgetControl.
        """
        control = ipyleaflet.WidgetControl(widget=widget, position=position, **kwargs)
        self.add(control)

    def add_google_map(self, map_type="ROADMAP"):
        """Add Google Map to the map.

        Args:
            map_type (str, optional): Map type. Defaults to "ROADMAP".
        """
        map_types = {
            "ROADMAP": "m",
            "SATELLITE": "s",
            "HYBRID": "y",
            "TERRAIN": "p",
        }
        map_type = map_types[map_type.upper()]

        url = (
            f"https://mt1.google.com/vt/lyrs={map_type.lower()}&x={{x}}&y={{y}}&z={{z}}"
        )
        layer = ipyleaflet.TileLayer(url=url, name="Google Map")
        self.add(layer)

    def add_geojson(
        self,
        data,
        zoom_to_layer=True,
        hover_style=None,
        **kwargs,
    ):
        """Adds a GeoJSON layer to the map.

        Args:
            data (str or dict): The GeoJSON data. Can be a file path (str) or a dictionary.
            zoom_to_layer (bool, optional): Whether to zoom to the layer's bounds. Defaults to True.
            hover_style (dict, optional): Style to apply when hovering over features. Defaults to {"color": "yellow", "fillOpacity": 0.2}.
            **kwargs: Additional keyword arguments for the ipyleaflet.GeoJSON layer.

        Raises:
            ValueError: If the data type is invalid.
        """
        import geopandas as gpd

        if hover_style is None:
            hover_style = {"color": "yellow", "fillOpacity": 0.2}

        if isinstance(data, str):
            gdf = gpd.read_file(data)
            geojson = gdf.__geo_interface__
        elif isinstance(data, dict):
            geojson = data
        layer = ipyleaflet.GeoJSON(data=geojson, hover_style=hover_style, **kwargs)
        self.add_layer(layer)

        if zoom_to_layer:
            bounds = gdf.total_bounds
            self.fit_bounds([[bounds[1], bounds[0]], [bounds[3], bounds[2]]])

    def add_shp(self, data, **kwargs):
        """Adds a shapefile to the map.

        Args:
            data (str): The file path to the shapefile.
            **kwargs: Additional keyword arguments for the GeoJSON layer.
        """
        import geopandas as gpd

        gdf = gpd.read_file(data)
        gdf = gdf.to_crs(epsg=4326)
        geojson = gdf.__geo_interface__
        self.add_geojson(geojson, **kwargs)

    def add_shp_from_url(self, url, **kwargs):
        """Adds a shapefile from a URL to the map.
        Adds a shapefile from a URL to the map.

        This function downloads the shapefile components (.shp, .shx, .dbf) from the specified URL, stores them
        in a temporary directory, reads the shapefile using Geopandas, converts it to GeoJSON format, and
        then adds it to the map. If the shapefile's coordinate reference system (CRS) is not set, it assumes
        the CRS to be EPSG:4326 (WGS84).

        Args:
            url (str): The URL pointing to the shapefile's location. The URL should be a raw GitHub link to
                    the shapefile components (e.g., ".shp", ".shx", ".dbf").
            **kwargs: Additional keyword arguments to pass to the `add_geojson` method for styling and
                    configuring the GeoJSON layer on the map.
        """
        try:
            base_url = url.replace("github.com", "raw.githubusercontent.com").replace(
                "blob/", ""
            )
            shp_url = base_url + ".shp"
            shx_url = base_url + ".shx"
            dbf_url = base_url + ".dbf"

            temp_dir = tempfile.mkdtemp()

            shp_file = requests.get(shp_url).content
            shx_file = requests.get(shx_url).content
            dbf_file = requests.get(dbf_url).content

            with open(os.path.join(temp_dir, "data.shp"), "wb") as f:
                f.write(shp_file)
            with open(os.path.join(temp_dir, "data.shx"), "wb") as f:
                f.write(shx_file)
            with open(os.path.join(temp_dir, "data.dbf"), "wb") as f:
                f.write(dbf_file)

            gdf = gpd.read_file(os.path.join(temp_dir, "data.shp"))

            if gdf.crs is None:
                gdf.set_crs("EPSG:4326", allow_override=True, inplace=True)

            geojson = gdf.__geo_interface__

            self.add_geojson(geojson, **kwargs)

            shutil.rmtree(temp_dir)

        except Exception:
            pass

    def add_gdf(self, gdf, **kwargs):
        """Adds a GeoDataFrame to the map.

        Args:
            gdf (geopandas.GeoDataFrame): The GeoDataFrame to add.
            **kwargs: Additional keyword arguments for the GeoJSON layer.
        """
        gdf = gdf.to_crs(epsg=4326)
        geojson = gdf.__geo_interface__
        self.add_geojson(geojson, **kwargs)

    def add_vector(self, data, **kwargs):
        """Adds vector data to the map.

        Args:
            data (str, geopandas.GeoDataFrame, or dict): The vector data. Can be a file path, GeoDataFrame, or GeoJSON dictionary.
            **kwargs: Additional keyword arguments for the GeoJSON layer.

        Raises:
            ValueError: If the data type is invalid.
        """
        import geopandas as gpd

        if isinstance(data, str):
            gdf = gpd.read_file(data)
            self.add_gdf(gdf, **kwargs)
        elif isinstance(data, gpd.GeoDataFrame):
            self.add_gdf(data, **kwargs)
        elif isinstance(data, dict):
            self.add_geojson(data, **kwargs)
        else:
            raise ValueError("Invalid data type")

    def add_layer_control(self):
        """Adds a layer control widget to the map."""
        control = ipyleaflet.LayersControl(position="topright")
        self.add_control(control)

    def add_raster(self, url, name=None, colormap=None, opacity=1.0, **kwargs):
        """Adds an raster to the map.

        Args:
            url (str): The url or file path to the raster.
            name (str, optional): The name for the raster layer. Defaults to None.
            colormap (str, optional): The colormap to use for the raster. Defaults to None.
            opacity (float, optional): The opacity of the raster layer. Defaults to 1.0.
            **kwargs: Additional keyword arguments for the raster layer.
        """

        from localtileserver import TileClient, get_leaflet_tile_layer

        client = TileClient(url)
        tile_layer = get_leaflet_tile_layer(
            client, name=name, colormap=colormap, opacity=opacity, **kwargs
        )

        self.add(tile_layer)
        self.center = client.center()
        self.zoom = client.default_zoom

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

        Args:
            url (str): The URL of the image to overlay on the map.
            bounds (list): The bounds for the image.
            opacity (float, optional): The opacity of the image overlay. Defaults to 1.0.
            **kwargs: Additional keyword arguments for the ipyleaflet.ImageOverlay layer.
        """

        if bounds is None or not bounds:
            raise ValueError("Bounds must be specified for the image overlay.")
        overlay = ipyleaflet.ImageOverlay(
            url=url, bounds=bounds, opacity=opacity, **kwargs
        )
        self.add(overlay)

    def add_video(self, url, bounds=None, opacity=1.0, **kwargs):
        """Adds a video to the map.

        Args:
            url (str): The file path to the video.
            bounds (list, required): The bounds for the video.
            opacity (float, optional): The opacity of the video overlay. Defaults to 1.0.
            **kwargs: Additional keyword arguments for the ipyleaflet.VideoOverlay layer.
        """

        if bounds is None or not bounds:
            raise ValueError("Bounds must be specified for the video overlay.")
        overlay = ipyleaflet.VideoOverlay(
            url=url, bounds=bounds, opacity=opacity, **kwargs
        )
        self.add(overlay)

    def add_wms_layer(
        self, url, layers, name, format="image/png", transparent=True, **kwargs
    ):
        """Adds a WMS layer to the map.

        Args:
            url (str): The WMS service URL.
            layers (str): The layers to display.
            name (str): The name for the WMS layer.
            format (str, optional): The format of the image. Defaults to "image/png".
            transparent (bool, optional): Whether to use transparency. Defaults to True.
            **kwargs: Additional keyword arguments for the ipyleaflet.WMSLayer layer.
        """
        layer = ipyleaflet.WMSLayer(
            url=url,
            layers=layers,
            name=name,
            format=format,
            transparent=transparent,
            **kwargs,
        )
        self.add(layer)

    def add_markers(self, coordinates, **kwargs):
        """Adds one or more markers to the map at the specified coordinates.

        Args:
            coordinates (list of tuples): List of (latitude, longitude) coordinates for markers.
            popup (str, optional): The popup text to display when the marker is clicked. Defaults to None.
            **kwargs: Additional keyword arguments for the Marker object.

        Returns:
            None
        """
        for coord in coordinates:
            marker = Marker(location=coord, **kwargs)

            self.add(marker)

add_basemap(self, basemap='OpenTopoMap')

Add basemap to the map.

Parameters:

Name Type Description Default
basemap str

Basemap name. Defaults to "OpenTopoMap".

'OpenTopoMap'

Available basemaps: - "OpenTopoMap": A topographic map. - "OpenStreetMap.Mapnik": A standard street map. - "Esri.WorldImagery": Satellite imagery. - "Esri.WorldTerrain": Terrain map from Esri. - "Esri.WorldStreetMap": Street map from Esri. - "CartoDB.Positron": A light, minimalist map style. - "CartoDB.DarkMatter": A dark-themed map style.

Source code in biospat/mapping.py
def add_basemap(self, basemap="OpenTopoMap"):
    """Add basemap to the map.

    Args:
        basemap (str, optional): Basemap name. Defaults to "OpenTopoMap".

    Available basemaps:
        - "OpenTopoMap": A topographic map.
        - "OpenStreetMap.Mapnik": A standard street map.
        - "Esri.WorldImagery": Satellite imagery.
        - "Esri.WorldTerrain": Terrain map from Esri.
        - "Esri.WorldStreetMap": Street map from Esri.
        - "CartoDB.Positron": A light, minimalist map style.
        - "CartoDB.DarkMatter": A dark-themed map style.
    """

    url = eval(f"ipyleaflet.basemaps.{basemap}").build_url()
    layer = ipyleaflet.TileLayer(url=url, name=basemap)
    self.add(layer)

add_basemap_gui(self, options=None, position='topright')

Adds a graphical user interface (GUI) for dynamically changing basemaps.

Parameters:

Name Type Description Default
options list

A list of basemap options to display in the dropdown. Defaults to ["OpenStreetMap.Mapnik", "OpenTopoMap", "Esri.WorldImagery", "Esri.WorldTerrain", "Esri.WorldStreetMap", "CartoDB.DarkMatter", "CartoDB.Positron"].

None
position str

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

'topright'

Behavior

  • A toggle button is used to show or hide the dropdown and close button.
  • The dropdown allows users to select a basemap from the provided options.
  • The close button removes the widget from the map.

Event Handlers: - on_toggle_change: Toggles the visibility of the dropdown and close button. - on_button_click: Closes and removes the widget from the map. - on_dropdown_change: Updates the map's basemap when a new option is selected.

Returns:

Type Description

None

Source code in biospat/mapping.py
def add_basemap_gui(self, options=None, position="topright"):
    """Adds a graphical user interface (GUI) for dynamically changing basemaps.

    Params:
        options (list, optional): A list of basemap options to display in the dropdown.
            Defaults to ["OpenStreetMap.Mapnik", "OpenTopoMap", "Esri.WorldImagery", "Esri.WorldTerrain", "Esri.WorldStreetMap", "CartoDB.DarkMatter", "CartoDB.Positron"].
        position (str, optional): The position of the widget on the map. Defaults to "topright".

    Behavior:
        - A toggle button is used to show or hide the dropdown and close button.
        - The dropdown allows users to select a basemap from the provided options.
        - The close button removes the widget from the map.

    Event Handlers:
        - `on_toggle_change`: Toggles the visibility of the dropdown and close button.
        - `on_button_click`: Closes and removes the widget from the map.
        - `on_dropdown_change`: Updates the map's basemap when a new option is selected.

    Returns:
        None
    """
    if options is None:
        options = [
            "OpenStreetMap.Mapnik",
            "OpenTopoMap",
            "Esri.WorldImagery",
            "Esri.WorldTerrain",
            "Esri.WorldStreetMap",
            "CartoDB.DarkMatter",
            "CartoDB.Positron",
        ]

    toggle = widgets.ToggleButton(
        value=True,
        button_style="",
        tooltip="Click me",
        icon="map",
    )
    toggle.layout = widgets.Layout(width="38px", height="38px")

    dropdown = widgets.Dropdown(
        options=options,
        value=options[0],
        description="Basemap:",
        style={"description_width": "initial"},
    )
    dropdown.layout = widgets.Layout(width="250px", height="38px")

    button = widgets.Button(
        icon="times",
    )
    button.layout = widgets.Layout(width="38px", height="38px")

    hbox = widgets.HBox([toggle, dropdown, button])

    def on_toggle_change(change):
        if change["new"]:
            hbox.children = [toggle, dropdown, button]
        else:
            hbox.children = [toggle]

    toggle.observe(on_toggle_change, names="value")

    def on_button_click(b):
        hbox.close()
        toggle.close()
        dropdown.close()
        button.close()

    button.on_click(on_button_click)

    def on_dropdown_change(change):
        if change["new"]:
            self.layers = self.layers[:-2]
            self.add_basemap(change["new"])

    dropdown.observe(on_dropdown_change, names="value")

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

add_gdf(self, gdf, **kwargs)

Adds a GeoDataFrame to the map.

Parameters:

Name Type Description Default
gdf geopandas.GeoDataFrame

The GeoDataFrame to add.

required
**kwargs

Additional keyword arguments for the GeoJSON layer.

{}
Source code in biospat/mapping.py
def add_gdf(self, gdf, **kwargs):
    """Adds a GeoDataFrame to the map.

    Args:
        gdf (geopandas.GeoDataFrame): The GeoDataFrame to add.
        **kwargs: Additional keyword arguments for the GeoJSON layer.
    """
    gdf = gdf.to_crs(epsg=4326)
    geojson = gdf.__geo_interface__
    self.add_geojson(geojson, **kwargs)

add_geojson(self, data, zoom_to_layer=True, hover_style=None, **kwargs)

Adds a GeoJSON layer to the map.

Parameters:

Name Type Description Default
data str or dict

The GeoJSON data. Can be a file path (str) or a dictionary.

required
zoom_to_layer bool

Whether to zoom to the layer's bounds. Defaults to True.

True
hover_style dict

Style to apply when hovering over features. Defaults to {"color": "yellow", "fillOpacity": 0.2}.

None
**kwargs

Additional keyword arguments for the ipyleaflet.GeoJSON layer.

{}

Exceptions:

Type Description
ValueError

If the data type is invalid.

Source code in biospat/mapping.py
def add_geojson(
    self,
    data,
    zoom_to_layer=True,
    hover_style=None,
    **kwargs,
):
    """Adds a GeoJSON layer to the map.

    Args:
        data (str or dict): The GeoJSON data. Can be a file path (str) or a dictionary.
        zoom_to_layer (bool, optional): Whether to zoom to the layer's bounds. Defaults to True.
        hover_style (dict, optional): Style to apply when hovering over features. Defaults to {"color": "yellow", "fillOpacity": 0.2}.
        **kwargs: Additional keyword arguments for the ipyleaflet.GeoJSON layer.

    Raises:
        ValueError: If the data type is invalid.
    """
    import geopandas as gpd

    if hover_style is None:
        hover_style = {"color": "yellow", "fillOpacity": 0.2}

    if isinstance(data, str):
        gdf = gpd.read_file(data)
        geojson = gdf.__geo_interface__
    elif isinstance(data, dict):
        geojson = data
    layer = ipyleaflet.GeoJSON(data=geojson, hover_style=hover_style, **kwargs)
    self.add_layer(layer)

    if zoom_to_layer:
        bounds = gdf.total_bounds
        self.fit_bounds([[bounds[1], bounds[0]], [bounds[3], bounds[2]]])

add_google_map(self, map_type='ROADMAP')

Add Google Map to the map.

Parameters:

Name Type Description Default
map_type str

Map type. Defaults to "ROADMAP".

'ROADMAP'
Source code in biospat/mapping.py
def add_google_map(self, map_type="ROADMAP"):
    """Add Google Map to the map.

    Args:
        map_type (str, optional): Map type. Defaults to "ROADMAP".
    """
    map_types = {
        "ROADMAP": "m",
        "SATELLITE": "s",
        "HYBRID": "y",
        "TERRAIN": "p",
    }
    map_type = map_types[map_type.upper()]

    url = (
        f"https://mt1.google.com/vt/lyrs={map_type.lower()}&x={{x}}&y={{y}}&z={{z}}"
    )
    layer = ipyleaflet.TileLayer(url=url, name="Google Map")
    self.add(layer)

add_image(self, url, bounds=None, opacity=1.0, **kwargs)

Adds an image to the map.

Parameters:

Name Type Description Default
url str

The URL of the image to overlay on the map.

required
bounds list

The bounds for the image.

None
opacity float

The opacity of the image overlay. Defaults to 1.0.

1.0
**kwargs

Additional keyword arguments for the ipyleaflet.ImageOverlay layer.

{}
Source code in biospat/mapping.py
def add_image(self, url, bounds=None, opacity=1.0, **kwargs):
    """Adds an image to the map.

    Args:
        url (str): The URL of the image to overlay on the map.
        bounds (list): The bounds for the image.
        opacity (float, optional): The opacity of the image overlay. Defaults to 1.0.
        **kwargs: Additional keyword arguments for the ipyleaflet.ImageOverlay layer.
    """

    if bounds is None or not bounds:
        raise ValueError("Bounds must be specified for the image overlay.")
    overlay = ipyleaflet.ImageOverlay(
        url=url, bounds=bounds, opacity=opacity, **kwargs
    )
    self.add(overlay)

add_layer_control(self)

Adds a layer control widget to the map.

Source code in biospat/mapping.py
def add_layer_control(self):
    """Adds a layer control widget to the map."""
    control = ipyleaflet.LayersControl(position="topright")
    self.add_control(control)

add_markers(self, coordinates, **kwargs)

Adds one or more markers to the map at the specified coordinates.

Parameters:

Name Type Description Default
coordinates list of tuples

List of (latitude, longitude) coordinates for markers.

required
popup str

The popup text to display when the marker is clicked. Defaults to None.

required
**kwargs

Additional keyword arguments for the Marker object.

{}

Returns:

Type Description

None

Source code in biospat/mapping.py
def add_markers(self, coordinates, **kwargs):
    """Adds one or more markers to the map at the specified coordinates.

    Args:
        coordinates (list of tuples): List of (latitude, longitude) coordinates for markers.
        popup (str, optional): The popup text to display when the marker is clicked. Defaults to None.
        **kwargs: Additional keyword arguments for the Marker object.

    Returns:
        None
    """
    for coord in coordinates:
        marker = Marker(location=coord, **kwargs)

        self.add(marker)

add_raster(self, url, name=None, colormap=None, opacity=1.0, **kwargs)

Adds an raster to the map.

Parameters:

Name Type Description Default
url str

The url or file path to the raster.

required
name str

The name for the raster layer. Defaults to None.

None
colormap str

The colormap to use for the raster. Defaults to None.

None
opacity float

The opacity of the raster layer. Defaults to 1.0.

1.0
**kwargs

Additional keyword arguments for the raster layer.

{}
Source code in biospat/mapping.py
def add_raster(self, url, name=None, colormap=None, opacity=1.0, **kwargs):
    """Adds an raster to the map.

    Args:
        url (str): The url or file path to the raster.
        name (str, optional): The name for the raster layer. Defaults to None.
        colormap (str, optional): The colormap to use for the raster. Defaults to None.
        opacity (float, optional): The opacity of the raster layer. Defaults to 1.0.
        **kwargs: Additional keyword arguments for the raster layer.
    """

    from localtileserver import TileClient, get_leaflet_tile_layer

    client = TileClient(url)
    tile_layer = get_leaflet_tile_layer(
        client, name=name, colormap=colormap, opacity=opacity, **kwargs
    )

    self.add(tile_layer)
    self.center = client.center()
    self.zoom = client.default_zoom

add_shp(self, data, **kwargs)

Adds a shapefile to the map.

Parameters:

Name Type Description Default
data str

The file path to the shapefile.

required
**kwargs

Additional keyword arguments for the GeoJSON layer.

{}
Source code in biospat/mapping.py
def add_shp(self, data, **kwargs):
    """Adds a shapefile to the map.

    Args:
        data (str): The file path to the shapefile.
        **kwargs: Additional keyword arguments for the GeoJSON layer.
    """
    import geopandas as gpd

    gdf = gpd.read_file(data)
    gdf = gdf.to_crs(epsg=4326)
    geojson = gdf.__geo_interface__
    self.add_geojson(geojson, **kwargs)

add_shp_from_url(self, url, **kwargs)

Adds a shapefile from a URL to the map. Adds a shapefile from a URL to the map.

This function downloads the shapefile components (.shp, .shx, .dbf) from the specified URL, stores them in a temporary directory, reads the shapefile using Geopandas, converts it to GeoJSON format, and then adds it to the map. If the shapefile's coordinate reference system (CRS) is not set, it assumes the CRS to be EPSG:4326 (WGS84).

Parameters:

Name Type Description Default
url str

The URL pointing to the shapefile's location. The URL should be a raw GitHub link to the shapefile components (e.g., ".shp", ".shx", ".dbf").

required
**kwargs

Additional keyword arguments to pass to the add_geojson method for styling and configuring the GeoJSON layer on the map.

{}
Source code in biospat/mapping.py
def add_shp_from_url(self, url, **kwargs):
    """Adds a shapefile from a URL to the map.
    Adds a shapefile from a URL to the map.

    This function downloads the shapefile components (.shp, .shx, .dbf) from the specified URL, stores them
    in a temporary directory, reads the shapefile using Geopandas, converts it to GeoJSON format, and
    then adds it to the map. If the shapefile's coordinate reference system (CRS) is not set, it assumes
    the CRS to be EPSG:4326 (WGS84).

    Args:
        url (str): The URL pointing to the shapefile's location. The URL should be a raw GitHub link to
                the shapefile components (e.g., ".shp", ".shx", ".dbf").
        **kwargs: Additional keyword arguments to pass to the `add_geojson` method for styling and
                configuring the GeoJSON layer on the map.
    """
    try:
        base_url = url.replace("github.com", "raw.githubusercontent.com").replace(
            "blob/", ""
        )
        shp_url = base_url + ".shp"
        shx_url = base_url + ".shx"
        dbf_url = base_url + ".dbf"

        temp_dir = tempfile.mkdtemp()

        shp_file = requests.get(shp_url).content
        shx_file = requests.get(shx_url).content
        dbf_file = requests.get(dbf_url).content

        with open(os.path.join(temp_dir, "data.shp"), "wb") as f:
            f.write(shp_file)
        with open(os.path.join(temp_dir, "data.shx"), "wb") as f:
            f.write(shx_file)
        with open(os.path.join(temp_dir, "data.dbf"), "wb") as f:
            f.write(dbf_file)

        gdf = gpd.read_file(os.path.join(temp_dir, "data.shp"))

        if gdf.crs is None:
            gdf.set_crs("EPSG:4326", allow_override=True, inplace=True)

        geojson = gdf.__geo_interface__

        self.add_geojson(geojson, **kwargs)

        shutil.rmtree(temp_dir)

    except Exception:
        pass

add_vector(self, data, **kwargs)

Adds vector data to the map.

Parameters:

Name Type Description Default
data str, geopandas.GeoDataFrame, or dict

The vector data. Can be a file path, GeoDataFrame, or GeoJSON dictionary.

required
**kwargs

Additional keyword arguments for the GeoJSON layer.

{}

Exceptions:

Type Description
ValueError

If the data type is invalid.

Source code in biospat/mapping.py
def add_vector(self, data, **kwargs):
    """Adds vector data to the map.

    Args:
        data (str, geopandas.GeoDataFrame, or dict): The vector data. Can be a file path, GeoDataFrame, or GeoJSON dictionary.
        **kwargs: Additional keyword arguments for the GeoJSON layer.

    Raises:
        ValueError: If the data type is invalid.
    """
    import geopandas as gpd

    if isinstance(data, str):
        gdf = gpd.read_file(data)
        self.add_gdf(gdf, **kwargs)
    elif isinstance(data, gpd.GeoDataFrame):
        self.add_gdf(data, **kwargs)
    elif isinstance(data, dict):
        self.add_geojson(data, **kwargs)
    else:
        raise ValueError("Invalid data type")

add_video(self, url, bounds=None, opacity=1.0, **kwargs)

Adds a video to the map.

Parameters:

Name Type Description Default
url str

The file path to the video.

required
bounds list, required

The bounds for the video.

None
opacity float

The opacity of the video overlay. Defaults to 1.0.

1.0
**kwargs

Additional keyword arguments for the ipyleaflet.VideoOverlay layer.

{}
Source code in biospat/mapping.py
def add_video(self, url, bounds=None, opacity=1.0, **kwargs):
    """Adds a video to the map.

    Args:
        url (str): The file path to the video.
        bounds (list, required): The bounds for the video.
        opacity (float, optional): The opacity of the video overlay. Defaults to 1.0.
        **kwargs: Additional keyword arguments for the ipyleaflet.VideoOverlay layer.
    """

    if bounds is None or not bounds:
        raise ValueError("Bounds must be specified for the video overlay.")
    overlay = ipyleaflet.VideoOverlay(
        url=url, bounds=bounds, opacity=opacity, **kwargs
    )
    self.add(overlay)

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

Add a widget to the map.

Parameters:

Name Type Description Default
widget ipywidgets.Widget

The widget to add.

required
position str

Position of the widget. Defaults to "topright".

'topright'
**kwargs

Additional keyword arguments for the WidgetControl.

{}
Source code in biospat/mapping.py
def add_widget(self, widget, position="topright", **kwargs):
    """Add a widget to the map.

    Args:
        widget (ipywidgets.Widget): The widget to add.
        position (str, optional): Position of the widget. Defaults to "topright".
        **kwargs: Additional keyword arguments for the WidgetControl.
    """
    control = ipyleaflet.WidgetControl(widget=widget, position=position, **kwargs)
    self.add(control)

add_wms_layer(self, url, layers, name, format='image/png', transparent=True, **kwargs)

Adds a WMS layer to the map.

Parameters:

Name Type Description Default
url str

The WMS service URL.

required
layers str

The layers to display.

required
name str

The name for the WMS layer.

required
format str

The format of the image. Defaults to "image/png".

'image/png'
transparent bool

Whether to use transparency. Defaults to True.

True
**kwargs

Additional keyword arguments for the ipyleaflet.WMSLayer layer.

{}
Source code in biospat/mapping.py
def add_wms_layer(
    self, url, layers, name, format="image/png", transparent=True, **kwargs
):
    """Adds a WMS layer to the map.

    Args:
        url (str): The WMS service URL.
        layers (str): The layers to display.
        name (str): The name for the WMS layer.
        format (str, optional): The format of the image. Defaults to "image/png".
        transparent (bool, optional): Whether to use transparency. Defaults to True.
        **kwargs: Additional keyword arguments for the ipyleaflet.WMSLayer layer.
    """
    layer = ipyleaflet.WMSLayer(
        url=url,
        layers=layers,
        name=name,
        format=format,
        transparent=transparent,
        **kwargs,
    )
    self.add(layer)