Skip to content

foliumap module

This module provides a custom map class extending folium.Map!

Map (Map)

A custom map class extending folium.Map.

Source code in salmongis/foliumap.py
class Map(folium.Map):
    """
    A custom map class extending folium.Map.
    """

    def __init__(self, center: Tuple[float, float] = (0, 0), zoom: int = 2, **kwargs) -> None:
        """
        Initializes the map with a given center and zoom level.

        Args:
            center (tuple): The initial center of the map as (latitude, longitude).
            zoom (int): The initial zoom level of the map.
            **kwargs: Additional keyword arguments for folium.Map.
        """
        super().__init__(location=center, zoom_start=zoom, **kwargs)
        folium.LayerControl().add_to(self)

    def add_geojson(
        self,
        data: Union[str, Dict],
        zoom_to_layer: bool = True,
        hover_style: Dict = None,
        **kwargs,
    ) -> None:
        """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 folium.GeoJson layer.

        Raises:
            ValueError: If the data type is invalid.
        """
        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
        else:
            raise ValueError("Invalid data type")

        geojson_layer = folium.GeoJson(data=geojson, **kwargs)
        geojson_layer.add_to(self)

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

        Args:
            data (str): The file path to the shapefile.
            **kwargs: Additional keyword arguments for the GeoJSON layer.
        """
        gdf = gpd.read_file(data)
        gdf = gdf.to_crs(epsg=4326)
        geojson = gdf.__geo_interface__
        self.add_geojson(geojson, **kwargs)

    def add_gdf(self, gdf: gpd.GeoDataFrame, **kwargs) -> None:
        """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_basemap(self, basemap: str = "OpenStreetMap") -> None:
        """
        Adds a basemap layer to the map.

        Args:
            basemap (str): The name of the basemap to add. Options include:
                "OpenStreetMap", "Stamen Terrain", "Stamen Toner", "Stamen Watercolor".
                Defaults to "OpenStreetMap".
        """
        basemaps = {
            "OpenStreetMap": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
            "Stamen Terrain": "http://{s}.tile.stamen.com/terrain/{z}/{x}/{y}.png",
            "Stamen Toner": "http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png",
            "Stamen Watercolor": "http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg",
        }
        folium.TileLayer(
            tiles=basemaps.get(basemap, basemaps["OpenStreetMap"]), attr=basemap
        ).add_to(self)

    def add_vector(self, data: Union[str, gpd.GeoDataFrame, Dict], **kwargs) -> None:
        """
        Adds a vector layer to the map from various data formats.

        Args:
            data (str, geopandas.GeoDataFrame, or dict): The vector data to add. Can be:
                - A file path or URL to a GeoJSON or shapefile.
                - A GeoDataFrame.
                - A GeoJSON-like dictionary.
            **kwargs: Additional keyword arguments for folium.GeoJson.

        Raises:
            ValueError: If the data type is not supported.
        """
        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) -> None:
        """
        Adds a layer control widget to the map.

        The layer control allows users to toggle visibility of layers on the map.
        """
        folium.LayerControl().add_to(self)

    def add_split_map(self, left_basemap: str, right_basemap: str) -> None:
        """
        Adds a split map to the map, displaying two basemaps side by side.

        Args:
            left_basemap (str): The name of the basemap to display on the left side.
            right_basemap (str): The name of the basemap to display on the right side.

        Raises:
            ValueError: If the provided basemap names are not supported.
        """ 
        attr = (
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> '
        'contributors, &copy; <a href="https://cartodb.com/attributions">CartoDB</a>'
)

        layer_right = folium.TileLayer(left_basemap, attr=attr)
        layer_left = folium.TileLayer(right_basemap, attr=attr)

        sbs = folium.plugins.SideBySideLayers(layer_left=layer_left, layer_right=layer_right)
        self.add_child(sbs)

__init__(self, center=(0, 0), zoom=2, **kwargs) special

Initializes the map with a given center and zoom level.

Parameters:

Name Type Description Default
center tuple

The initial center of the map as (latitude, longitude).

(0, 0)
zoom int

The initial zoom level of the map.

2
**kwargs

Additional keyword arguments for folium.Map.

{}
Source code in salmongis/foliumap.py
def __init__(self, center: Tuple[float, float] = (0, 0), zoom: int = 2, **kwargs) -> None:
    """
    Initializes the map with a given center and zoom level.

    Args:
        center (tuple): The initial center of the map as (latitude, longitude).
        zoom (int): The initial zoom level of the map.
        **kwargs: Additional keyword arguments for folium.Map.
    """
    super().__init__(location=center, zoom_start=zoom, **kwargs)
    folium.LayerControl().add_to(self)

add_basemap(self, basemap='OpenStreetMap')

Adds a basemap layer to the map.

Parameters:

Name Type Description Default
basemap str

The name of the basemap to add. Options include: "OpenStreetMap", "Stamen Terrain", "Stamen Toner", "Stamen Watercolor". Defaults to "OpenStreetMap".

'OpenStreetMap'
Source code in salmongis/foliumap.py
def add_basemap(self, basemap: str = "OpenStreetMap") -> None:
    """
    Adds a basemap layer to the map.

    Args:
        basemap (str): The name of the basemap to add. Options include:
            "OpenStreetMap", "Stamen Terrain", "Stamen Toner", "Stamen Watercolor".
            Defaults to "OpenStreetMap".
    """
    basemaps = {
        "OpenStreetMap": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
        "Stamen Terrain": "http://{s}.tile.stamen.com/terrain/{z}/{x}/{y}.png",
        "Stamen Toner": "http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png",
        "Stamen Watercolor": "http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg",
    }
    folium.TileLayer(
        tiles=basemaps.get(basemap, basemaps["OpenStreetMap"]), attr=basemap
    ).add_to(self)

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 salmongis/foliumap.py
def add_gdf(self, gdf: gpd.GeoDataFrame, **kwargs) -> None:
    """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 folium.GeoJson layer.

{}

Exceptions:

Type Description
ValueError

If the data type is invalid.

Source code in salmongis/foliumap.py
def add_geojson(
    self,
    data: Union[str, Dict],
    zoom_to_layer: bool = True,
    hover_style: Dict = None,
    **kwargs,
) -> None:
    """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 folium.GeoJson layer.

    Raises:
        ValueError: If the data type is invalid.
    """
    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
    else:
        raise ValueError("Invalid data type")

    geojson_layer = folium.GeoJson(data=geojson, **kwargs)
    geojson_layer.add_to(self)

add_layer_control(self)

Adds a layer control widget to the map.

The layer control allows users to toggle visibility of layers on the map.

Source code in salmongis/foliumap.py
def add_layer_control(self) -> None:
    """
    Adds a layer control widget to the map.

    The layer control allows users to toggle visibility of layers on the map.
    """
    folium.LayerControl().add_to(self)

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 salmongis/foliumap.py
def add_shp(self, data: str, **kwargs) -> None:
    """Adds a shapefile to the map.

    Args:
        data (str): The file path to the shapefile.
        **kwargs: Additional keyword arguments for the GeoJSON layer.
    """
    gdf = gpd.read_file(data)
    gdf = gdf.to_crs(epsg=4326)
    geojson = gdf.__geo_interface__
    self.add_geojson(geojson, **kwargs)

add_split_map(self, left_basemap, right_basemap)

Adds a split map to the map, displaying two basemaps side by side.

Parameters:

Name Type Description Default
left_basemap str

The name of the basemap to display on the left side.

required
right_basemap str

The name of the basemap to display on the right side.

required

Exceptions:

Type Description
ValueError

If the provided basemap names are not supported.

Source code in salmongis/foliumap.py
    def add_split_map(self, left_basemap: str, right_basemap: str) -> None:
        """
        Adds a split map to the map, displaying two basemaps side by side.

        Args:
            left_basemap (str): The name of the basemap to display on the left side.
            right_basemap (str): The name of the basemap to display on the right side.

        Raises:
            ValueError: If the provided basemap names are not supported.
        """ 
        attr = (
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> '
        'contributors, &copy; <a href="https://cartodb.com/attributions">CartoDB</a>'
)

        layer_right = folium.TileLayer(left_basemap, attr=attr)
        layer_left = folium.TileLayer(right_basemap, attr=attr)

        sbs = folium.plugins.SideBySideLayers(layer_left=layer_left, layer_right=layer_right)
        self.add_child(sbs)

add_vector(self, data, **kwargs)

Adds a vector layer to the map from various data formats.

Parameters:

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

The vector data to add. Can be: - A file path or URL to a GeoJSON or shapefile. - A GeoDataFrame. - A GeoJSON-like dictionary.

required
**kwargs

Additional keyword arguments for folium.GeoJson.

{}

Exceptions:

Type Description
ValueError

If the data type is not supported.

Source code in salmongis/foliumap.py
def add_vector(self, data: Union[str, gpd.GeoDataFrame, Dict], **kwargs) -> None:
    """
    Adds a vector layer to the map from various data formats.

    Args:
        data (str, geopandas.GeoDataFrame, or dict): The vector data to add. Can be:
            - A file path or URL to a GeoJSON or shapefile.
            - A GeoDataFrame.
            - A GeoJSON-like dictionary.
        **kwargs: Additional keyword arguments for folium.GeoJson.

    Raises:
        ValueError: If the data type is not supported.
    """
    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")