HTML mapping example#

This is a code example showing how to create an interactive map using the web/mapping module. This example shows two ways to create an interactive html map: A single map with the desired datasets,and a split map consisting of an overview map with the split geometries which link to individual maps showing the datasets for each split geometry.

The example uses the NUTS dataset from Eurostat and the cities dataset from Natural Earth, both of which are available in geodatasets.

Imports#

import pathlib

import geopandas as gpd
from geodatasets import get_path

from caf.viz.web import mapping

Define constants#

These are constants used to select the desired data from the geodatasets package.

Load data#

Load the datasets to be mapped as geopandas.GeoDataFrame objects.

path_to_data = get_path("eurostat.nuts_rg_10m_2024_3035")
europe = gpd.read_file(path_to_data)

path_to_data = get_path("naturalearth.cities")
cities = gpd.read_file(path_to_data)

europe_countries = europe[europe["LEVL_CODE"] == COUNTRY_CODE]
Downloading file 'NUTS_RG_10M_2024_3035.gpkg' from 'https://gisco-services.ec.europa.eu/distribution/v2/nuts/gpkg/NUTS_RG_10M_2024_3035.gpkg' to '/home/docs/.cache/geodatasets'.
Downloading file 'ne_110m_populated_places_simple.zip' from 'https://naciscdn.org/naturalearth/110m/cultural/ne_110m_populated_places_simple.zip' to '/home/docs/.cache/geodatasets'.

Prepare datasets for mapping#

Prepare datasets for mapping as a mapping.MapData object, which includes the data, the color column to use, and various mapping options in a mapping.ExploreOptions object.

datasets = {"Countries": europe_countries, "Cities": cities}

color_column = {"Countries": None, "Cities": "natscale"}

tooltip = {"Countries": ["NUTS_NAME", "NAME_ENGL", "CAPT"], "Cities": ["name", "natscale"]}

options = {
    "Countries": mapping.ExploreOptions(
        tooltip=tooltip["Countries"],
        show_legend=False,
        style={"fillOpacity": 0.4, "fillColor": "grey", "color": "black"},
    ),
    "Cities": mapping.ExploreOptions(tooltip=tooltip["Cities"], show_legend=True),
}

mapping_datasets = {}
for name, data in datasets.items():
    mapping_datasets[name] = mapping.MapData(
        data=data.to_crs(f"EPSG:{mapping.MAP_CRS_EPSG}"),
        color_column=color_column[name],
        options=options[name],
    )

# Prepare mask
if europe_countries.crs != mapping.MAP_CRS_EPSG:
    filter_zones = europe_countries.to_crs(f"EPSG:{mapping.MAP_CRS_EPSG}")
else:
    filter_zones = europe_countries

Create a Single Map#

map_datasets() will create a folium.Map object from the datasets with OpenStreetMap background, it can be saved to a standalone HTML file with folium.Map.save().

mapping.map_datasets(datasets=mapping_datasets, mask=filter_zones, mask_name="Europe")
Make this Notebook Trusted to load map: File -> Trust Notebook


Create a Split Map#

Create a map which is split across multiple HTML files to allow for more detailed data on each subset map, see Split Map Overview.

Note

HTML file is written to generated documentation folder, so it’s deployed with documentation, normally this can be saved anywhere.

PATH_TO_SAVE_SPLIT_MAP = pathlib.Path(r"../docs/build/html/_generated/examples/split_map.html")
PATH_TO_SAVE_SPLIT_MAP.parent.mkdir(exist_ok=True, parents=True)
europe_regions = europe[europe["LEVL_CODE"] == REGION_CODE]

mapping_datasets = {
    "Regions": mapping.MapData(
        data=europe_regions.to_crs(f"EPSG:{mapping.MAP_CRS_EPSG}"),
        color_column="NAME_ENGL",
        options=mapping.ExploreOptions(
            tooltip=["NUTS_NAME", "NAME_ENGL", "CAPT"],
            show_legend=True,
            style={"fillOpacity": 0.4, "fillColor": "grey", "color": "black"},
        ),
    )
}

# Check map crs for split geometries
if europe_countries.crs != mapping.MAP_CRS_EPSG:
    europe_countries = europe_countries.to_crs(f"EPSG:{mapping.MAP_CRS_EPSG}")

mapping.produce_map_set(
    output_path=PATH_TO_SAVE_SPLIT_MAP,
    datasets=mapping_datasets,
    split=europe_countries,
    split_name_column="NAME_ENGL",
)
Producing Split Maps maps:   0%|          | 0/39 [00:00<?, ?it/s]
Producing Split Maps maps:   3%|▎         | 1/39 [00:00<00:04,  7.78it/s]
Producing Split Maps maps:   5%|▌         | 2/39 [00:00<00:05,  7.24it/s]
Producing Split Maps maps:   8%|▊         | 3/39 [00:00<00:05,  7.08it/s]
Producing Split Maps maps:  10%|█         | 4/39 [00:00<00:06,  5.62it/s]
Producing Split Maps maps:  13%|█▎        | 5/39 [00:00<00:05,  6.34it/s]
Producing Split Maps maps:  15%|█▌        | 6/39 [00:00<00:05,  6.30it/s]
Producing Split Maps maps:  18%|█▊        | 7/39 [00:01<00:05,  6.38it/s]
Producing Split Maps maps:  21%|██        | 8/39 [00:01<00:04,  6.68it/s]
Producing Split Maps maps:  23%|██▎       | 9/39 [00:01<00:05,  5.62it/s]
Producing Split Maps maps:  26%|██▌       | 10/39 [00:01<00:04,  6.12it/s]
Producing Split Maps maps:  28%|██▊       | 11/39 [00:01<00:04,  6.57it/s]
Producing Split Maps maps:  31%|███       | 12/39 [00:01<00:03,  6.89it/s]
Producing Split Maps maps:  33%|███▎      | 13/39 [00:01<00:03,  6.88it/s]
Producing Split Maps maps:  36%|███▌      | 14/39 [00:02<00:03,  6.61it/s]
Producing Split Maps maps:  38%|███▊      | 15/39 [00:02<00:03,  7.00it/s]
Producing Split Maps maps:  41%|████      | 16/39 [00:02<00:03,  7.17it/s]
Producing Split Maps maps:  44%|████▎     | 17/39 [00:02<00:02,  7.37it/s]
Producing Split Maps maps:  46%|████▌     | 18/39 [00:02<00:02,  7.48it/s]
Producing Split Maps maps:  49%|████▊     | 19/39 [00:02<00:02,  7.61it/s]
Producing Split Maps maps:  51%|█████▏    | 20/39 [00:02<00:02,  7.64it/s]
Producing Split Maps maps:  54%|█████▍    | 21/39 [00:03<00:02,  7.79it/s]
Producing Split Maps maps:  56%|█████▋    | 22/39 [00:03<00:02,  7.36it/s]
Producing Split Maps maps:  59%|█████▉    | 23/39 [00:03<00:02,  6.71it/s]
Producing Split Maps maps:  62%|██████▏   | 24/39 [00:03<00:02,  6.78it/s]
Producing Split Maps maps:  64%|██████▍   | 25/39 [00:03<00:02,  6.90it/s]
Producing Split Maps maps:  67%|██████▋   | 26/39 [00:03<00:01,  7.15it/s]
Producing Split Maps maps:  69%|██████▉   | 27/39 [00:03<00:01,  7.35it/s]
Producing Split Maps maps:  72%|███████▏  | 28/39 [00:04<00:01,  7.05it/s]
Producing Split Maps maps:  74%|███████▍  | 29/39 [00:04<00:01,  7.21it/s]
Producing Split Maps maps:  77%|███████▋  | 30/39 [00:04<00:01,  7.35it/s]
Producing Split Maps maps:  79%|███████▉  | 31/39 [00:04<00:01,  5.09it/s]
Producing Split Maps maps:  82%|████████▏ | 32/39 [00:04<00:01,  5.43it/s]
Producing Split Maps maps:  85%|████████▍ | 33/39 [00:04<00:01,  5.93it/s]
Producing Split Maps maps:  87%|████████▋ | 34/39 [00:05<00:00,  6.30it/s]
Producing Split Maps maps:  90%|████████▉ | 35/39 [00:05<00:00,  6.48it/s]
Producing Split Maps maps:  92%|█████████▏| 36/39 [00:05<00:00,  6.71it/s]
Producing Split Maps maps:  95%|█████████▍| 37/39 [00:05<00:00,  6.55it/s]
Producing Split Maps maps:  97%|█████████▋| 38/39 [00:05<00:00,  6.79it/s]
Producing Split Maps maps: 100%|██████████| 39/39 [00:05<00:00,  7.10it/s]
Producing Split Maps maps: 100%|██████████| 39/39 [00:05<00:00,  6.72it/s]

Total running time of the script: (0 minutes 7.855 seconds)

Gallery generated by Sphinx-Gallery