Skip to content

Visualisers

What is the visualiser module?

The visualiser module is responsible to deliver visualiser's primitives such as matplotlib or folium, following a UrbanMapper's analysis.

Meanwhile, we recommend to look through the Example's Visualiser for a more hands-on introduction about the Visualiser module and its usage.

Documentation Under Alpha Construction

This documentation is in its early stages and still being developed. The API may therefore change, and some parts might be incomplete or inaccurate.

Use at your own risk, and please report anything that seems incorrect / outdated you find.

Open An Issue!

VisualiserBase

Bases: ABC

Base class for all visualisers in UrbanMapper

This abstract class defines the common interface that all visualiser implementations must follow. Visualisers are responsible for creating visual representations following a UrbanMapper's analysis.

Method Not Implemented

This is an abstract class and cannot be instantiated directly. Use concrete implementations such as StaticVisualiser or InteractiveVisualiser instead.

Attributes:

Name Type Description
style Dict[str, Any]

A dictionary of style parameters to apply to the visualisation. The specific style parameters depend on the visualiser implementation.

Source code in src/urban_mapper/modules/visualiser/abc_visualiser.py
class VisualiserBase(ABC):
    """Base class for all visualisers in `UrbanMapper`

    This abstract class defines the common interface that all visualiser implementations
    must follow. Visualisers are responsible for creating visual representations following a `UrbanMapper`'s analysis.

    !!! warning "Method Not Implemented"
        This is an abstract class and cannot be instantiated directly. Use concrete
        implementations such as `StaticVisualiser` or `InteractiveVisualiser` instead.

    Attributes:
        style (Dict[str, Any]): A dictionary of style parameters to apply to the
            visualisation. The specific style parameters depend on the visualiser
            implementation.

    """

    def __init__(self, style: Dict[str, Any] = None):
        self.style = style or {}

    @abstractmethod
    def _render(
        self, urban_layer_geodataframe: gpd.GeoDataFrame, columns: List[str], **kwargs
    ) -> Any:
        """Internal implementation method for rendering visualisations.

        Called by `render()` after validation.

        !!! warning "Method Not Implemented"
            This method must be implemented by subclasses. It should contain the logic
            for creating the visualisation based on the provided GeoDataFrame and columns.

        Args:
            urban_layer_geodataframe (gpd.GeoDataFrame): The `GeoDataFrame` to visualise.
            columns (List[str]): List of column names to include in the visualisation.
            **kwargs: Additional implementation-specific parameters.

        Returns:
            Any: The visualisation result, which varies by implementation.

        Raises:
            ValueError: If the visualisation cannot be performed.
        """
        pass

    @require_dynamic_columns("urban_layer_geodataframe", lambda args: args["columns"])
    def render(
        self, urban_layer_geodataframe: gpd.GeoDataFrame, columns: List[str], **kwargs
    ) -> Any:
        """Render a visualisation of the provided GeoDataFrame

        The primary public method for generating visualisations. It validates inputs and
        delegates to the subclass-specific `_render()` method.

        Args:
            urban_layer_geodataframe (gpd.GeoDataFrame): The `GeoDataFrame` to visualise.
            columns (List[str]): List of column names to include in the visualisation.
                These columns must exist in the `GeoDataFrame`.
            **kwargs: Additional implementation-specific parameters for customising the
                visualisation, such as figure size, title, colours, etc.

        Returns:
            Any: The visualisation result, which varies by implementation (e.g., a plot,
                map, figure, or interactive widget).

        Raises:
            ValueError: If urban_layer_geodataframe lacks a 'geometry' column.
            ValueError: If urban_layer_geodataframe is empty.
            ValueError: If any specified columns don't exist in urban_layer_geodataframe.
            ValueError: If the visualisation cannot be performed.

        Examples:
            >>> from urban_mapper.modules.visualiser import InteractiveVisualiser
            >>> viz = InteractiveVisualiser(style={"color": "red", "opacity": 0.7})
            >>> viz.render(
            ...     urban_layer_geodataframe=enriched_gdf,
            ...     columns=["nearest_street", "distance_to_street"],
            ...     title="Streets Analysis"
            ... )
        """
        if "geometry" not in urban_layer_geodataframe.columns:
            raise ValueError("GeoDataFrame must have a 'geometry' column.")
        if urban_layer_geodataframe.empty:
            raise ValueError("GeoDataFrame is empty; nothing to visualise.")
        return self._render(urban_layer_geodataframe, columns, **kwargs)

    @abstractmethod
    def preview(self, format: str = "ascii") -> Any:
        """Generate a preview of this visualiser.

        Provides a summary of the visualiser's configuration for inspection.

        !!! note "Method Not Implemented"
            This method must be implemented by subclasses. It should return a
            representation of the visualiser's configuration.

        Args:
            format (str): The output format. Options are:

                - [x] "ascii": Text-based format for terminal display.
                - [x] "json": JSON-formatted data for programmatic use.
                Defaults to "ascii".

        Returns:
            Any: A representation of the visualiser in the requested format (e.g., str or dict).

        Raises:
            ValueError: If an unsupported format is specified.

        """
        pass

_render(urban_layer_geodataframe, columns, **kwargs) abstractmethod

Internal implementation method for rendering visualisations.

Called by render() after validation.

Method Not Implemented

This method must be implemented by subclasses. It should contain the logic for creating the visualisation based on the provided GeoDataFrame and columns.

Parameters:

Name Type Description Default
urban_layer_geodataframe GeoDataFrame

The GeoDataFrame to visualise.

required
columns List[str]

List of column names to include in the visualisation.

required
**kwargs

Additional implementation-specific parameters.

{}

Returns:

Name Type Description
Any Any

The visualisation result, which varies by implementation.

Raises:

Type Description
ValueError

If the visualisation cannot be performed.

Source code in src/urban_mapper/modules/visualiser/abc_visualiser.py
@abstractmethod
def _render(
    self, urban_layer_geodataframe: gpd.GeoDataFrame, columns: List[str], **kwargs
) -> Any:
    """Internal implementation method for rendering visualisations.

    Called by `render()` after validation.

    !!! warning "Method Not Implemented"
        This method must be implemented by subclasses. It should contain the logic
        for creating the visualisation based on the provided GeoDataFrame and columns.

    Args:
        urban_layer_geodataframe (gpd.GeoDataFrame): The `GeoDataFrame` to visualise.
        columns (List[str]): List of column names to include in the visualisation.
        **kwargs: Additional implementation-specific parameters.

    Returns:
        Any: The visualisation result, which varies by implementation.

    Raises:
        ValueError: If the visualisation cannot be performed.
    """
    pass

render(urban_layer_geodataframe, columns, **kwargs)

Render a visualisation of the provided GeoDataFrame

The primary public method for generating visualisations. It validates inputs and delegates to the subclass-specific _render() method.

Parameters:

Name Type Description Default
urban_layer_geodataframe GeoDataFrame

The GeoDataFrame to visualise.

required
columns List[str]

List of column names to include in the visualisation. These columns must exist in the GeoDataFrame.

required
**kwargs

Additional implementation-specific parameters for customising the visualisation, such as figure size, title, colours, etc.

{}

Returns:

Name Type Description
Any Any

The visualisation result, which varies by implementation (e.g., a plot, map, figure, or interactive widget).

Raises:

Type Description
ValueError

If urban_layer_geodataframe lacks a 'geometry' column.

ValueError

If urban_layer_geodataframe is empty.

ValueError

If any specified columns don't exist in urban_layer_geodataframe.

ValueError

If the visualisation cannot be performed.

Examples:

>>> from urban_mapper.modules.visualiser import InteractiveVisualiser
>>> viz = InteractiveVisualiser(style={"color": "red", "opacity": 0.7})
>>> viz.render(
...     urban_layer_geodataframe=enriched_gdf,
...     columns=["nearest_street", "distance_to_street"],
...     title="Streets Analysis"
... )
Source code in src/urban_mapper/modules/visualiser/abc_visualiser.py
@require_dynamic_columns("urban_layer_geodataframe", lambda args: args["columns"])
def render(
    self, urban_layer_geodataframe: gpd.GeoDataFrame, columns: List[str], **kwargs
) -> Any:
    """Render a visualisation of the provided GeoDataFrame

    The primary public method for generating visualisations. It validates inputs and
    delegates to the subclass-specific `_render()` method.

    Args:
        urban_layer_geodataframe (gpd.GeoDataFrame): The `GeoDataFrame` to visualise.
        columns (List[str]): List of column names to include in the visualisation.
            These columns must exist in the `GeoDataFrame`.
        **kwargs: Additional implementation-specific parameters for customising the
            visualisation, such as figure size, title, colours, etc.

    Returns:
        Any: The visualisation result, which varies by implementation (e.g., a plot,
            map, figure, or interactive widget).

    Raises:
        ValueError: If urban_layer_geodataframe lacks a 'geometry' column.
        ValueError: If urban_layer_geodataframe is empty.
        ValueError: If any specified columns don't exist in urban_layer_geodataframe.
        ValueError: If the visualisation cannot be performed.

    Examples:
        >>> from urban_mapper.modules.visualiser import InteractiveVisualiser
        >>> viz = InteractiveVisualiser(style={"color": "red", "opacity": 0.7})
        >>> viz.render(
        ...     urban_layer_geodataframe=enriched_gdf,
        ...     columns=["nearest_street", "distance_to_street"],
        ...     title="Streets Analysis"
        ... )
    """
    if "geometry" not in urban_layer_geodataframe.columns:
        raise ValueError("GeoDataFrame must have a 'geometry' column.")
    if urban_layer_geodataframe.empty:
        raise ValueError("GeoDataFrame is empty; nothing to visualise.")
    return self._render(urban_layer_geodataframe, columns, **kwargs)

preview(format='ascii') abstractmethod

Generate a preview of this visualiser.

Provides a summary of the visualiser's configuration for inspection.

Method Not Implemented

This method must be implemented by subclasses. It should return a representation of the visualiser's configuration.

Parameters:

Name Type Description Default
format str

The output format. Options are:

  • "ascii": Text-based format for terminal display.
  • "json": JSON-formatted data for programmatic use. Defaults to "ascii".
'ascii'

Returns:

Name Type Description
Any Any

A representation of the visualiser in the requested format (e.g., str or dict).

Raises:

Type Description
ValueError

If an unsupported format is specified.

Source code in src/urban_mapper/modules/visualiser/abc_visualiser.py
@abstractmethod
def preview(self, format: str = "ascii") -> Any:
    """Generate a preview of this visualiser.

    Provides a summary of the visualiser's configuration for inspection.

    !!! note "Method Not Implemented"
        This method must be implemented by subclasses. It should return a
        representation of the visualiser's configuration.

    Args:
        format (str): The output format. Options are:

            - [x] "ascii": Text-based format for terminal display.
            - [x] "json": JSON-formatted data for programmatic use.
            Defaults to "ascii".

    Returns:
        Any: A representation of the visualiser in the requested format (e.g., str or dict).

    Raises:
        ValueError: If an unsupported format is specified.

    """
    pass

StaticVisualiser

Bases: VisualiserBase

A visualiser that creates static plots using Matplotlib.

This visualiser generates static visualisations of geographic data using Matplotlib. It supports plotting a single column from the GeoDataFrame.

Available Style Options

Common style keys for StaticVisualiser include: - figsize: Figure size as a tuple (width, height). - cmap: Colormap for numeric data. - color: Colour for non-numeric data. - markersize: Size of markers. - legend: Whether to show a legend. - vmin: Minimum value for color scaling. - vmax: Maximum value for color scaling.

Attributes:

Name Type Description
short_name str

Short identifier for the visualiser.

allowed_style_keys set

Valid style parameters that can be provided.

style dict

Style parameters applied to the visualisation.

Examples:

>>> from urban_mapper.modules.visualiser import StaticVisualiser
>>> viz = StaticVisualiser()
>>> viz.render(
...     urban_layer_geodataframe=streets_gdf,
...     columns=["street_name"],
...     figsize=(10, 8),
...     cmap="viridis"
... )
Source code in src/urban_mapper/modules/visualiser/visualisers/static_visualiser.py
@beartype
class StaticVisualiser(VisualiserBase):
    """A visualiser that creates static plots using Matplotlib.

    This visualiser generates static visualisations of geographic data using
    Matplotlib. It supports plotting a single column from the GeoDataFrame.

    !!! tip "Available Style Options"
        Common style keys for `StaticVisualiser` include:
        - `figsize`: Figure size as a tuple (width, height).
        - `cmap`: Colormap for numeric data.
        - `color`: Colour for non-numeric data.
        - `markersize`: Size of markers.
        - `legend`: Whether to show a legend.
        - `vmin`: Minimum value for color scaling.
        - `vmax`: Maximum value for color scaling.

    Attributes:
        short_name (str): Short identifier for the visualiser.
        allowed_style_keys (set): Valid style parameters that can be provided.
        style (dict): Style parameters applied to the visualisation.

    Examples:
        >>> from urban_mapper.modules.visualiser import StaticVisualiser
        >>> viz = StaticVisualiser()
        >>> viz.render(
        ...     urban_layer_geodataframe=streets_gdf,
        ...     columns=["street_name"],
        ...     figsize=(10, 8),
        ...     cmap="viridis"
        ... )

    """

    short_name = "Static"
    allowed_style_keys = {
        "kind",
        "cmap",
        "color",
        "ax",
        "cax",
        "categorical",
        "legend",
        "scheme",
        "k",
        "vmin",
        "vmax",
        "markersize",
        "figsize",
    }

    def _render(
        self, urban_layer_geodataframe: gpd.GeoDataFrame, columns: List[str], **kwargs
    ) -> Any:
        """Render a static plot of the GeoDataFrame.

        Creates a static Matplotlib plot for the specified column.
        It renders each source (data_id column) with different markers, when the GeoDataFrame has data_id column

        !!! note "To Keep in Mind"
            Only supports visualisation of a single column at a time.

        Args:
            urban_layer_geodataframe (gpd.GeoDataFrame): The GeoDataFrame to visualise.
            columns (List[str]): A list with a single column name to plot.
            **kwargs: Additional parameters for customising the plot,
                overriding any style parameters set during initialisation.

        Returns:
            Any: A Matplotlib figure object.

        Raises:
            ValueError: If more than one column is specified.
        """
        if len(columns) > 1:
            raise ValueError("StaticVisualiser only supports a single column.")
        render_kwargs = {**self.style, **kwargs}

        if "data_id" in urban_layer_geodataframe:
            data_ids = urban_layer_geodataframe.data_id.dropna().unique()
            data_ids.sort()

            marker_list = list(Line2D.markers)
            marker_list = marker_list[2:]  ## discard point (.) and pixel (,)
            marker_list = marker_list[: len(data_ids)]

            col = urban_layer_geodataframe[~urban_layer_geodataframe.data_id.isna()][
                columns[0]
            ]
            vmin_val = col.min()
            vmax_val = col.max()

            ax = None
            legend = []

            for id, marker in zip(data_ids, marker_list):
                urban_layer_gdf = urban_layer_geodataframe[
                    urban_layer_geodataframe.data_id == id
                ]
                ax = urban_layer_gdf.plot(
                    column=columns[0],
                    legend=id == data_ids[-1],
                    ax=ax,
                    marker=marker,
                    vmin=vmin_val,
                    vmax=vmax_val,
                    **render_kwargs,
                )
                legend.append(
                    Line2D([], [], color="gray", marker=marker, ls="", label=id)
                )

            ax.legend(handles=legend)
        else:
            ax = urban_layer_geodataframe.plot(
                column=columns[0], legend=True, **render_kwargs
            )
        return ax.get_figure()

    def preview(self, format: str = "ascii") -> Any:
        """Generate a preview of this static visualiser.

        Provides a summary of the visualiser's configuration.

        Args:
            format (str): The output format ("ascii" or "json"). Defaults to "ascii".

        Returns:
            Any: A string (for "ascii") or dict (for "json") representing the visualiser.

        Raises:
            ValueError: If format is unsupported.

        Examples:
            >>> viz = StaticVisualiser()
            >>> print(viz.preview())
            Visualiser: StaticVisualiser using Matplotlib
        """
        if format == "ascii":
            return "Visualiser: StaticVisualiser using Matplotlib"
        elif format == "json":
            return {
                "visualiser": "StaticVisualiser using Matplotlib",
            }
        else:
            raise ValueError(f"Unsupported format '{format}'")

_render(urban_layer_geodataframe, columns, **kwargs)

Render a static plot of the GeoDataFrame.

Creates a static Matplotlib plot for the specified column. It renders each source (data_id column) with different markers, when the GeoDataFrame has data_id column

To Keep in Mind

Only supports visualisation of a single column at a time.

Parameters:

Name Type Description Default
urban_layer_geodataframe GeoDataFrame

The GeoDataFrame to visualise.

required
columns List[str]

A list with a single column name to plot.

required
**kwargs

Additional parameters for customising the plot, overriding any style parameters set during initialisation.

{}

Returns:

Name Type Description
Any Any

A Matplotlib figure object.

Raises:

Type Description
ValueError

If more than one column is specified.

Source code in src/urban_mapper/modules/visualiser/visualisers/static_visualiser.py
def _render(
    self, urban_layer_geodataframe: gpd.GeoDataFrame, columns: List[str], **kwargs
) -> Any:
    """Render a static plot of the GeoDataFrame.

    Creates a static Matplotlib plot for the specified column.
    It renders each source (data_id column) with different markers, when the GeoDataFrame has data_id column

    !!! note "To Keep in Mind"
        Only supports visualisation of a single column at a time.

    Args:
        urban_layer_geodataframe (gpd.GeoDataFrame): The GeoDataFrame to visualise.
        columns (List[str]): A list with a single column name to plot.
        **kwargs: Additional parameters for customising the plot,
            overriding any style parameters set during initialisation.

    Returns:
        Any: A Matplotlib figure object.

    Raises:
        ValueError: If more than one column is specified.
    """
    if len(columns) > 1:
        raise ValueError("StaticVisualiser only supports a single column.")
    render_kwargs = {**self.style, **kwargs}

    if "data_id" in urban_layer_geodataframe:
        data_ids = urban_layer_geodataframe.data_id.dropna().unique()
        data_ids.sort()

        marker_list = list(Line2D.markers)
        marker_list = marker_list[2:]  ## discard point (.) and pixel (,)
        marker_list = marker_list[: len(data_ids)]

        col = urban_layer_geodataframe[~urban_layer_geodataframe.data_id.isna()][
            columns[0]
        ]
        vmin_val = col.min()
        vmax_val = col.max()

        ax = None
        legend = []

        for id, marker in zip(data_ids, marker_list):
            urban_layer_gdf = urban_layer_geodataframe[
                urban_layer_geodataframe.data_id == id
            ]
            ax = urban_layer_gdf.plot(
                column=columns[0],
                legend=id == data_ids[-1],
                ax=ax,
                marker=marker,
                vmin=vmin_val,
                vmax=vmax_val,
                **render_kwargs,
            )
            legend.append(
                Line2D([], [], color="gray", marker=marker, ls="", label=id)
            )

        ax.legend(handles=legend)
    else:
        ax = urban_layer_geodataframe.plot(
            column=columns[0], legend=True, **render_kwargs
        )
    return ax.get_figure()

preview(format='ascii')

Generate a preview of this static visualiser.

Provides a summary of the visualiser's configuration.

Parameters:

Name Type Description Default
format str

The output format ("ascii" or "json"). Defaults to "ascii".

'ascii'

Returns:

Name Type Description
Any Any

A string (for "ascii") or dict (for "json") representing the visualiser.

Raises:

Type Description
ValueError

If format is unsupported.

Examples:

>>> viz = StaticVisualiser()
>>> print(viz.preview())
Visualiser: StaticVisualiser using Matplotlib
Source code in src/urban_mapper/modules/visualiser/visualisers/static_visualiser.py
def preview(self, format: str = "ascii") -> Any:
    """Generate a preview of this static visualiser.

    Provides a summary of the visualiser's configuration.

    Args:
        format (str): The output format ("ascii" or "json"). Defaults to "ascii".

    Returns:
        Any: A string (for "ascii") or dict (for "json") representing the visualiser.

    Raises:
        ValueError: If format is unsupported.

    Examples:
        >>> viz = StaticVisualiser()
        >>> print(viz.preview())
        Visualiser: StaticVisualiser using Matplotlib
    """
    if format == "ascii":
        return "Visualiser: StaticVisualiser using Matplotlib"
    elif format == "json":
        return {
            "visualiser": "StaticVisualiser using Matplotlib",
        }
    else:
        raise ValueError(f"Unsupported format '{format}'")

InteractiveVisualiser

Bases: VisualiserBase

A visualiser that creates interactive web maps with Folium.

This visualiser generates interactive maps using Folium, allowing for zooming, panning, layer selection, tooltips, and popups. For multiple columns, it provides a dropdown to switch between different data visualisations.

Available Style Options

Common style keys for InteractiveVisualiser include: - width: Width of the map in pixels. - height: Height of the map in pixels. - color: Colour for non-numeric data. - opacity: Transparency level. - tiles: Base map tiles (e.g., "OpenStreetMap", "CartoDB positron"). See further in Folium Tiles - tooltip: Whether to show tooltips on hover. - popup: Whether to show popups on click. - cmap: Colormap for numeric data. - legend: Whether to show a legend. - vmin: Minimum value for color scaling. - vmax: Maximum value for color scaling. - colorbar_text_color: Text color for the color bar.

Attributes:

Name Type Description
short_name str

Short identifier for the visualiser.

allowed_style_keys set

Valid style parameters that can be provided.

style dict

Style parameters applied to the visualisation.

Examples:

>>> from urban_mapper.modules.visualiser import InteractiveVisualiser
>>> viz = InteractiveVisualiser()
>>> viz.render(
...     urban_layer_geodataframe=streets_gdf,
...     columns=["street_name"]
... )
>>> viz = InteractiveVisualiser(style={
...     "color": "red",
...     "opacity": 0.7,
...     "tooltip": True,
...     "tiles": "CartoDB positron"
... })
>>> viz.render(
...     urban_layer_geodataframe=enriched_gdf,
...     columns=["nearest_street", "distance_to_street"],
...     legend=True
... )
Source code in src/urban_mapper/modules/visualiser/visualisers/interactive_visualiser.py
@beartype
class InteractiveVisualiser(VisualiserBase):
    """A visualiser that creates interactive web maps with Folium.

    This visualiser generates interactive maps using Folium, allowing for `zooming`,
    `panning`, `layer selection`, `tooltips`, and `popups`. For `multiple columns`, it provides
    a `dropdown` to switch between different data visualisations.

    !!! tip "Available Style Options"
        Common style keys for `InteractiveVisualiser` include:
        - `width`: Width of the map in pixels.
        - `height`: Height of the map in pixels.
        - `color`: Colour for non-numeric data.
        - `opacity`: Transparency level.
        - `tiles`: Base map tiles (e.g., "OpenStreetMap", "CartoDB positron"). See further in [Folium Tiles](https://leaflet-extras.github.io/leaflet-providers/preview/)
        - `tooltip`: Whether to show tooltips on hover.
        - `popup`: Whether to show popups on click.
        - `cmap`: Colormap for numeric data.
        - `legend`: Whether to show a legend.
        - `vmin`: Minimum value for color scaling.
        - `vmax`: Maximum value for color scaling.
        - `colorbar_text_color`: Text color for the color bar.

    Attributes:
        short_name (str): Short identifier for the visualiser.
        allowed_style_keys (set): Valid style parameters that can be provided.
        style (dict): Style parameters applied to the visualisation.

    Examples:
        >>> from urban_mapper.modules.visualiser import InteractiveVisualiser
        >>> viz = InteractiveVisualiser()
        >>> viz.render(
        ...     urban_layer_geodataframe=streets_gdf,
        ...     columns=["street_name"]
        ... )
        >>> viz = InteractiveVisualiser(style={
        ...     "color": "red",
        ...     "opacity": 0.7,
        ...     "tooltip": True,
        ...     "tiles": "CartoDB positron"
        ... })
        >>> viz.render(
        ...     urban_layer_geodataframe=enriched_gdf,
        ...     columns=["nearest_street", "distance_to_street"],
        ...     legend=True
        ... )

    """

    short_name = "Interactive"
    allowed_style_keys = {
        "cmap",
        "color",
        "m",
        "tiles",
        "attr",
        "tooltip",
        "popup",
        "highlight",
        "categorical",
        "legend",
        "scheme",
        "k",
        "vmin",
        "vmax",
        "width",
        "height",
        "colorbar_text_color",
        "marker_type",
        "marker_kwds",
    }

    def _render(
        self, urban_layer_geodataframe: gpd.GeoDataFrame, columns: List[str], **kwargs
    ) -> Any:
        """Render an interactive map of the GeoDataFrame.

        Creates an interactive Folium map displaying the data. For numeric columns,
        it creates choropleth maps with color scales. For categorical columns, it
        creates categorical maps with distinct colors. When multiple columns are
        provided, it includes a dropdown to switch between them.

        !!! note "To Keep in Mind"
            Requires an internet connection for map tiles and interactivity.

        Args:
            urban_layer_geodataframe (gpd.GeoDataFrame): The GeoDataFrame to visualise.
            columns (List[str]): List of column names to include in the visualisation.
            **kwargs: Additional parameters for customising the visualisation,
                overriding any style parameters set during initialisation.

        Returns:
            Any: A Folium map object for a single column, or an ipywidgets.VBox for multiple columns.

        Raises:
            ValueError: If no columns are specified.
        """
        if not columns:
            raise ValueError("At least one column must be specified.")
        render_kwargs = {**self.style, **kwargs}

        legend = render_kwargs.pop("legend", True)
        text_color = render_kwargs.pop("colorbar_text_color", "black")

        def get_map(column):
            if pd.api.types.is_numeric_dtype(urban_layer_geodataframe[column]):
                vmin = render_kwargs.get("vmin", urban_layer_geodataframe[column].min())
                vmax = render_kwargs.get("vmax", urban_layer_geodataframe[column].max())
                cmap = render_kwargs.get("cmap", "viridis")

                folium_map = urban_layer_geodataframe.explore(
                    column=column, legend=False, **render_kwargs
                )

                if legend:
                    mpl_cmap = plt.get_cmap(cmap)

                    colors = mpl_cmap(np.linspace(0, 1, 256))
                    colors = [tuple(color) for color in colors]
                    colormap = cm.LinearColormap(
                        colors=colors,
                        vmin=vmin,
                        vmax=vmax,
                        caption=column,
                        text_color=text_color,
                    )

                    folium_map.add_child(colormap)
            else:
                folium_map = urban_layer_geodataframe.explore(
                    column=column, legend=legend, **render_kwargs
                )

            return folium_map

        if len(columns) == 1:
            return get_map(columns[0])
        else:
            dropdown = widgets.Dropdown(
                options=columns, value=columns[0], description="Column:"
            )
            output = widgets.Output()

            def on_change(change):
                with output:
                    output.clear_output()
                    display(get_map(change["new"]))

            dropdown.observe(on_change, names="value")
            with output:
                display(get_map(columns[0]))
            return widgets.VBox([dropdown, output])

    def preview(self, format: str = "ascii") -> Any:
        """Generate a preview of this interactive visualiser.

        Provides a summary of the visualiser's configuration.

        Args:
            format (str): The output format ("ascii" or "json"). Defaults to "ascii".

        Returns:
            Any: A string (for "ascii") or dict (for "json") representing the visualiser.

        Raises:
            ValueError: If format is unsupported.

        Examples:
            >>> viz = InteractiveVisualiser()
            >>> print(viz.preview())
            Visualiser: InteractiveVisualiser using Folium
            Style: Default styling
        """
        if format == "ascii":
            style_preview = (
                ", ".join(f"{k}: {v}" for k, v in self.style.items())
                if self.style
                else "Default styling"
            )
            return f"Visualiser: InteractiveVisualiser using Folium\nStyle: {style_preview}"
        elif format == "json":
            return {
                "visualiser": "InteractiveVisualiser",
                "library": "Folium",
                "allowed_style_keys": list(self.allowed_style_keys),
                "current_style": self.style,
            }
        else:
            raise ValueError(f"Unsupported format '{format}'")

_render(urban_layer_geodataframe, columns, **kwargs)

Render an interactive map of the GeoDataFrame.

Creates an interactive Folium map displaying the data. For numeric columns, it creates choropleth maps with color scales. For categorical columns, it creates categorical maps with distinct colors. When multiple columns are provided, it includes a dropdown to switch between them.

To Keep in Mind

Requires an internet connection for map tiles and interactivity.

Parameters:

Name Type Description Default
urban_layer_geodataframe GeoDataFrame

The GeoDataFrame to visualise.

required
columns List[str]

List of column names to include in the visualisation.

required
**kwargs

Additional parameters for customising the visualisation, overriding any style parameters set during initialisation.

{}

Returns:

Name Type Description
Any Any

A Folium map object for a single column, or an ipywidgets.VBox for multiple columns.

Raises:

Type Description
ValueError

If no columns are specified.

Source code in src/urban_mapper/modules/visualiser/visualisers/interactive_visualiser.py
def _render(
    self, urban_layer_geodataframe: gpd.GeoDataFrame, columns: List[str], **kwargs
) -> Any:
    """Render an interactive map of the GeoDataFrame.

    Creates an interactive Folium map displaying the data. For numeric columns,
    it creates choropleth maps with color scales. For categorical columns, it
    creates categorical maps with distinct colors. When multiple columns are
    provided, it includes a dropdown to switch between them.

    !!! note "To Keep in Mind"
        Requires an internet connection for map tiles and interactivity.

    Args:
        urban_layer_geodataframe (gpd.GeoDataFrame): The GeoDataFrame to visualise.
        columns (List[str]): List of column names to include in the visualisation.
        **kwargs: Additional parameters for customising the visualisation,
            overriding any style parameters set during initialisation.

    Returns:
        Any: A Folium map object for a single column, or an ipywidgets.VBox for multiple columns.

    Raises:
        ValueError: If no columns are specified.
    """
    if not columns:
        raise ValueError("At least one column must be specified.")
    render_kwargs = {**self.style, **kwargs}

    legend = render_kwargs.pop("legend", True)
    text_color = render_kwargs.pop("colorbar_text_color", "black")

    def get_map(column):
        if pd.api.types.is_numeric_dtype(urban_layer_geodataframe[column]):
            vmin = render_kwargs.get("vmin", urban_layer_geodataframe[column].min())
            vmax = render_kwargs.get("vmax", urban_layer_geodataframe[column].max())
            cmap = render_kwargs.get("cmap", "viridis")

            folium_map = urban_layer_geodataframe.explore(
                column=column, legend=False, **render_kwargs
            )

            if legend:
                mpl_cmap = plt.get_cmap(cmap)

                colors = mpl_cmap(np.linspace(0, 1, 256))
                colors = [tuple(color) for color in colors]
                colormap = cm.LinearColormap(
                    colors=colors,
                    vmin=vmin,
                    vmax=vmax,
                    caption=column,
                    text_color=text_color,
                )

                folium_map.add_child(colormap)
        else:
            folium_map = urban_layer_geodataframe.explore(
                column=column, legend=legend, **render_kwargs
            )

        return folium_map

    if len(columns) == 1:
        return get_map(columns[0])
    else:
        dropdown = widgets.Dropdown(
            options=columns, value=columns[0], description="Column:"
        )
        output = widgets.Output()

        def on_change(change):
            with output:
                output.clear_output()
                display(get_map(change["new"]))

        dropdown.observe(on_change, names="value")
        with output:
            display(get_map(columns[0]))
        return widgets.VBox([dropdown, output])

preview(format='ascii')

Generate a preview of this interactive visualiser.

Provides a summary of the visualiser's configuration.

Parameters:

Name Type Description Default
format str

The output format ("ascii" or "json"). Defaults to "ascii".

'ascii'

Returns:

Name Type Description
Any Any

A string (for "ascii") or dict (for "json") representing the visualiser.

Raises:

Type Description
ValueError

If format is unsupported.

Examples:

>>> viz = InteractiveVisualiser()
>>> print(viz.preview())
Visualiser: InteractiveVisualiser using Folium
Style: Default styling
Source code in src/urban_mapper/modules/visualiser/visualisers/interactive_visualiser.py
def preview(self, format: str = "ascii") -> Any:
    """Generate a preview of this interactive visualiser.

    Provides a summary of the visualiser's configuration.

    Args:
        format (str): The output format ("ascii" or "json"). Defaults to "ascii".

    Returns:
        Any: A string (for "ascii") or dict (for "json") representing the visualiser.

    Raises:
        ValueError: If format is unsupported.

    Examples:
        >>> viz = InteractiveVisualiser()
        >>> print(viz.preview())
        Visualiser: InteractiveVisualiser using Folium
        Style: Default styling
    """
    if format == "ascii":
        style_preview = (
            ", ".join(f"{k}: {v}" for k, v in self.style.items())
            if self.style
            else "Default styling"
        )
        return f"Visualiser: InteractiveVisualiser using Folium\nStyle: {style_preview}"
    elif format == "json":
        return {
            "visualiser": "InteractiveVisualiser",
            "library": "Folium",
            "allowed_style_keys": list(self.allowed_style_keys),
            "current_style": self.style,
        }
    else:
        raise ValueError(f"Unsupported format '{format}'")

VisualiserFactory

Factory class for creating and configuring data visualisers

Provides a fluent chaining-methods-based interface to instantiate visualisers, configure settings, and render visualisations within the UrbanMapper framework.

Attributes:

Name Type Description
_type Optional[str]

The type of visualiser to create.

_style Dict[str, Any]

Style configuration for the visualiser.

_columns Optional[List[str]]

Columns from the data to visualise.

_instance Optional[VisualiserBase]

The visualiser instance (internal use).

_preview Optional[dict]

Preview configuration (internal use).

Examples:

>>> from urban_mapper import UrbanMapper
>>> import geopandas as gpd
>>> mapper = UrbanMapper()
>>> neighborhoods = mapper.urban_layer.region_neighborhoods().from_place("Manhattan, New York")
>>> map_viz = mapper.visual.with_type("InteractiveVisualiser")        ...     .with_style({"width": 800, "height": 600})        ...     .show("neighborhood")        ...     .render(neighborhoods)
Source code in src/urban_mapper/modules/visualiser/visualiser_factory.py
@beartype
class VisualiserFactory:
    """Factory class for creating and configuring data visualisers

    Provides a fluent chaining-methods-based interface to instantiate visualisers, configure settings, and
    render visualisations within the UrbanMapper framework.

    Attributes:
        _type (Optional[str]): The type of visualiser to create.
        _style (Dict[str, Any]): Style configuration for the visualiser.
        _columns (Optional[List[str]]): Columns from the data to visualise.
        _instance (Optional[VisualiserBase]): The visualiser instance (internal use).
        _preview (Optional[dict]): Preview configuration (internal use).

    Examples:
        >>> from urban_mapper import UrbanMapper
        >>> import geopandas as gpd
        >>> mapper = UrbanMapper()
        >>> neighborhoods = mapper.urban_layer.region_neighborhoods().from_place("Manhattan, New York")
        >>> map_viz = mapper.visual.with_type("InteractiveVisualiser")\
        ...     .with_style({"width": 800, "height": 600})\
        ...     .show("neighborhood")\
        ...     .render(neighborhoods)
    """

    def __init__(self):
        self._type = None
        self._style = {}
        self._columns = None
        self._instance: Optional[VisualiserBase] = None
        self._preview: Optional[dict] = None

    @reset_attributes_before(["_type", "_style", "_columns"])
    def with_type(self, primitive_type: str) -> "VisualiserFactory":
        """Specify the type of visualiser to create.

        Sets the type of visualiser, determining the visualisation strategy.

        !!! question "How to find available visualiser types?"
            To find available visualiser types, you can check the `VISUALISER_REGISTRY` dictionary.
            Or directly going to the `urban_mapper.modules.visualiser.visualisers` directory.
            Each visualiser class should have a `short_name` attribute that serves as its identifier.

            Instead, you simply also can se `list(VISUALISER_REGISTRY.keys())` to see available visualiser types.

        Args:
            primitive_type (str): The name of the visualiser type (e.g., "InteractiveVisualiser").

        Returns:
            VisualiserFactory: Self for method chaining.

        Raises:
            ValueError: If primitive_type is not in VISUALISER_REGISTRY.

        Examples:
            >>> visualiser = mapper.visual.with_type("InteractiveVisualiser")

        """
        if primitive_type not in VISUALISER_REGISTRY:
            available = list(VISUALISER_REGISTRY.keys())
            match, score = process.extractOne(primitive_type, available)
            if score > 80:
                suggestion = f" Maybe you meant '{match}'?"
            else:
                suggestion = ""
            raise ValueError(
                f"Unknown visualiser type '{primitive_type}'. Available: {', '.join(available)}.{suggestion}"
            )
        self._type = primitive_type
        logger.log(
            "DEBUG_LOW",
            f"WITH_TYPE: Initialised VisualiserFactory with type={primitive_type}",
        )
        return self

    @reset_attributes_before(["_style"])
    def with_style(self, style: Dict[str, Any]) -> "VisualiserFactory":
        """Set the style options for the visualiser.

        Configures style options like colours, width, height, and opacity.

        !!! tip "how to know which style options are available?"
            To know which style options are available, you can check the `allowed_style_keys` attribute
            in each visualiser class. This attribute contains a set of keys that are accepted for styling.

        Args:
            style (Dict[str, Any]): A dictionary of style options.

        Returns:
            VisualiserFactory: Self for method chaining.

        Examples:
            >>> visualiser = mapper.visual.with_style({
            ...     "width": 800,
            ...     "height": 600,
            ...     "color": "blue",
            ...     "opacity": 0.7
            ... })
        """
        self._style.update(style)
        logger.log(
            "DEBUG_LOW", f"WITH_STYLE: Initialised VisualiserFactory with style={style}"
        )
        return self

    def show(self, columns: Union[str, List[str]]) -> "VisualiserFactory":
        """Specify which columns from the data should be visualised.

        Sets the columns to include in the visualisation.

        Args:
            columns (Union[str, List[str]]): A single column name or list of column names.

        Returns:
            VisualiserFactory: Self for method chaining.

        Examples:
            >>> visualiser = mapper.visual.show("population")
            >>> visualiser = mapper.visual.show(["population", "area"])
        """
        if isinstance(columns, str):
            columns = [columns]
        self._columns = columns
        logger.log(
            "DEBUG_LOW",
            f"SHOW: Initialised VisualiserFactory while displaying columns={columns}",
        )
        return self

    def render(self, urban_layer_geodataframe: gpd.GeoDataFrame) -> Any:
        """Render the visualisation using the provided data.

        Creates and renders a visualiser instance with the configured options.

        Args:
            urban_layer_geodataframe (gpd.GeoDataFrame): The `GeoDataFrame` to visualise.

        Returns:
            Any: The visualisation output (e.g., a map widget or figure).

        Raises:
            ValueError: If _type or _columns are not set, or if invalid style keys are used.

        Examples:
            >>> map_viz = VisualiserFactory().with_type("InteractiveVisualiser")\
            ...     .show("neighborhood")\
            ...     .render(neighborhoods_gdf)
        """
        if self._type is None:
            raise ValueError("Visualiser type must be specified.")
        if self._columns is None:
            raise ValueError("Columns to visualise must be specified.")

        visualiser_class = VISUALISER_REGISTRY[self._type]
        allowed_keys = visualiser_class.allowed_style_keys
        invalid_keys = set(self._style.keys()) - allowed_keys
        if invalid_keys:
            allowed = ", ".join(sorted(allowed_keys))
            raise ValueError(
                f"Invalid style keys for {self._type}: {invalid_keys}. Allowed keys: {allowed}"
            )

        self._instance = visualiser_class()
        if self._preview is not None:
            self.preview(format=self._preview["format"])
        return self._instance.render(
            urban_layer_geodataframe, self._columns, **self._style
        )

    def build(self) -> VisualiserBase:
        """Build and return the configured visualiser instance.

        Creates a visualiser instance for use in pipelines or deferred rendering.

        !!! note "To Keep In Mind"
            Prefer `render()` for immediate visualisation; use `build()` for pipelines.

        Returns:
            VisualiserBase: A configured visualiser instance.

        Raises:
            ValueError: If _type is not set.

        Examples:
            >>> visualiser = mapper.visual.with_type("StaticVisualiser")\
            ...     .with_style({"figsize": (10, 8)})\
            ...     .build()

        """
        logger.log(
            "DEBUG_MID",
            "WARNING: build() should only be used in UrbanPipeline. "
            "In other cases, using render() is a better option.",
        )
        if self._type is None:
            raise ValueError("Visualiser type must be specified.")
        visualiser_class = VISUALISER_REGISTRY[self._type]
        self._instance = visualiser_class(style=self._style)
        if self._preview is not None:
            self.preview(format=self._preview["format"])
        return self._instance

    def preview(self, format: str = "ascii") -> None:
        """Generate a preview of the configured visualiser.

        Shows the visualiser’s configuration in the specified format.

        Args:
            format (str): The format to display ("ascii" or "json"). Defaults to "ascii".

        Raises:
            ValueError: If format is unsupported.

        Examples:
            >>> factory = mappper.visual.with_type("InteractiveVisualiser").build()
            >>> factory.preview(format="json")
        """
        if self._instance is None:
            print("No visualiser instance available to preview. Call build() first.")
            return
        if hasattr(self._instance, "preview"):
            preview_data = self._instance.preview(format=format)
            if format == "ascii":
                print(preview_data)
            elif format == "json":
                print(json.dumps(preview_data, indent=2))
            else:
                raise ValueError(f"Unsupported format '{format}'.")
        else:
            print("Preview not supported for this visualiser instance.")

    def with_preview(self, format: str = "ascii") -> "VisualiserFactory":
        """Configure the factory to display a preview after building.

        Enables automatic preview after `build()` or `render()`.

        Args:
            format (str): The preview format ("ascii" or "json"). Defaults to "ascii".

        Returns:
            VisualiserFactory: Self for chaining.

        Examples:
            >>> visualiser = mapper.visual.with_type("InteractiveVisualiser")\
            ...     .with_preview(format="json")\
            ...     .build()
        """
        self._preview = {"format": format}
        return self

with_type(primitive_type)

Specify the type of visualiser to create.

Sets the type of visualiser, determining the visualisation strategy.

How to find available visualiser types?

To find available visualiser types, you can check the VISUALISER_REGISTRY dictionary. Or directly going to the urban_mapper.modules.visualiser.visualisers directory. Each visualiser class should have a short_name attribute that serves as its identifier.

Instead, you simply also can se list(VISUALISER_REGISTRY.keys()) to see available visualiser types.

Parameters:

Name Type Description Default
primitive_type str

The name of the visualiser type (e.g., "InteractiveVisualiser").

required

Returns:

Name Type Description
VisualiserFactory VisualiserFactory

Self for method chaining.

Raises:

Type Description
ValueError

If primitive_type is not in VISUALISER_REGISTRY.

Examples:

>>> visualiser = mapper.visual.with_type("InteractiveVisualiser")
Source code in src/urban_mapper/modules/visualiser/visualiser_factory.py
@reset_attributes_before(["_type", "_style", "_columns"])
def with_type(self, primitive_type: str) -> "VisualiserFactory":
    """Specify the type of visualiser to create.

    Sets the type of visualiser, determining the visualisation strategy.

    !!! question "How to find available visualiser types?"
        To find available visualiser types, you can check the `VISUALISER_REGISTRY` dictionary.
        Or directly going to the `urban_mapper.modules.visualiser.visualisers` directory.
        Each visualiser class should have a `short_name` attribute that serves as its identifier.

        Instead, you simply also can se `list(VISUALISER_REGISTRY.keys())` to see available visualiser types.

    Args:
        primitive_type (str): The name of the visualiser type (e.g., "InteractiveVisualiser").

    Returns:
        VisualiserFactory: Self for method chaining.

    Raises:
        ValueError: If primitive_type is not in VISUALISER_REGISTRY.

    Examples:
        >>> visualiser = mapper.visual.with_type("InteractiveVisualiser")

    """
    if primitive_type not in VISUALISER_REGISTRY:
        available = list(VISUALISER_REGISTRY.keys())
        match, score = process.extractOne(primitive_type, available)
        if score > 80:
            suggestion = f" Maybe you meant '{match}'?"
        else:
            suggestion = ""
        raise ValueError(
            f"Unknown visualiser type '{primitive_type}'. Available: {', '.join(available)}.{suggestion}"
        )
    self._type = primitive_type
    logger.log(
        "DEBUG_LOW",
        f"WITH_TYPE: Initialised VisualiserFactory with type={primitive_type}",
    )
    return self

with_style(style)

Set the style options for the visualiser.

Configures style options like colours, width, height, and opacity.

how to know which style options are available?

To know which style options are available, you can check the allowed_style_keys attribute in each visualiser class. This attribute contains a set of keys that are accepted for styling.

Parameters:

Name Type Description Default
style Dict[str, Any]

A dictionary of style options.

required

Returns:

Name Type Description
VisualiserFactory VisualiserFactory

Self for method chaining.

Examples:

>>> visualiser = mapper.visual.with_style({
...     "width": 800,
...     "height": 600,
...     "color": "blue",
...     "opacity": 0.7
... })
Source code in src/urban_mapper/modules/visualiser/visualiser_factory.py
@reset_attributes_before(["_style"])
def with_style(self, style: Dict[str, Any]) -> "VisualiserFactory":
    """Set the style options for the visualiser.

    Configures style options like colours, width, height, and opacity.

    !!! tip "how to know which style options are available?"
        To know which style options are available, you can check the `allowed_style_keys` attribute
        in each visualiser class. This attribute contains a set of keys that are accepted for styling.

    Args:
        style (Dict[str, Any]): A dictionary of style options.

    Returns:
        VisualiserFactory: Self for method chaining.

    Examples:
        >>> visualiser = mapper.visual.with_style({
        ...     "width": 800,
        ...     "height": 600,
        ...     "color": "blue",
        ...     "opacity": 0.7
        ... })
    """
    self._style.update(style)
    logger.log(
        "DEBUG_LOW", f"WITH_STYLE: Initialised VisualiserFactory with style={style}"
    )
    return self

show(columns)

Specify which columns from the data should be visualised.

Sets the columns to include in the visualisation.

Parameters:

Name Type Description Default
columns Union[str, List[str]]

A single column name or list of column names.

required

Returns:

Name Type Description
VisualiserFactory VisualiserFactory

Self for method chaining.

Examples:

>>> visualiser = mapper.visual.show("population")
>>> visualiser = mapper.visual.show(["population", "area"])
Source code in src/urban_mapper/modules/visualiser/visualiser_factory.py
def show(self, columns: Union[str, List[str]]) -> "VisualiserFactory":
    """Specify which columns from the data should be visualised.

    Sets the columns to include in the visualisation.

    Args:
        columns (Union[str, List[str]]): A single column name or list of column names.

    Returns:
        VisualiserFactory: Self for method chaining.

    Examples:
        >>> visualiser = mapper.visual.show("population")
        >>> visualiser = mapper.visual.show(["population", "area"])
    """
    if isinstance(columns, str):
        columns = [columns]
    self._columns = columns
    logger.log(
        "DEBUG_LOW",
        f"SHOW: Initialised VisualiserFactory while displaying columns={columns}",
    )
    return self

render(urban_layer_geodataframe)

Render the visualisation using the provided data.

Creates and renders a visualiser instance with the configured options.

Parameters:

Name Type Description Default
urban_layer_geodataframe GeoDataFrame

The GeoDataFrame to visualise.

required

Returns:

Name Type Description
Any Any

The visualisation output (e.g., a map widget or figure).

Raises:

Type Description
ValueError

If _type or _columns are not set, or if invalid style keys are used.

Examples:

>>> map_viz = VisualiserFactory().with_type("InteractiveVisualiser")            ...     .show("neighborhood")            ...     .render(neighborhoods_gdf)
Source code in src/urban_mapper/modules/visualiser/visualiser_factory.py
def render(self, urban_layer_geodataframe: gpd.GeoDataFrame) -> Any:
    """Render the visualisation using the provided data.

    Creates and renders a visualiser instance with the configured options.

    Args:
        urban_layer_geodataframe (gpd.GeoDataFrame): The `GeoDataFrame` to visualise.

    Returns:
        Any: The visualisation output (e.g., a map widget or figure).

    Raises:
        ValueError: If _type or _columns are not set, or if invalid style keys are used.

    Examples:
        >>> map_viz = VisualiserFactory().with_type("InteractiveVisualiser")\
        ...     .show("neighborhood")\
        ...     .render(neighborhoods_gdf)
    """
    if self._type is None:
        raise ValueError("Visualiser type must be specified.")
    if self._columns is None:
        raise ValueError("Columns to visualise must be specified.")

    visualiser_class = VISUALISER_REGISTRY[self._type]
    allowed_keys = visualiser_class.allowed_style_keys
    invalid_keys = set(self._style.keys()) - allowed_keys
    if invalid_keys:
        allowed = ", ".join(sorted(allowed_keys))
        raise ValueError(
            f"Invalid style keys for {self._type}: {invalid_keys}. Allowed keys: {allowed}"
        )

    self._instance = visualiser_class()
    if self._preview is not None:
        self.preview(format=self._preview["format"])
    return self._instance.render(
        urban_layer_geodataframe, self._columns, **self._style
    )

build()

Build and return the configured visualiser instance.

Creates a visualiser instance for use in pipelines or deferred rendering.

To Keep In Mind

Prefer render() for immediate visualisation; use build() for pipelines.

Returns:

Name Type Description
VisualiserBase VisualiserBase

A configured visualiser instance.

Raises:

Type Description
ValueError

If _type is not set.

Examples:

>>> visualiser = mapper.visual.with_type("StaticVisualiser")            ...     .with_style({"figsize": (10, 8)})            ...     .build()
Source code in src/urban_mapper/modules/visualiser/visualiser_factory.py
def build(self) -> VisualiserBase:
    """Build and return the configured visualiser instance.

    Creates a visualiser instance for use in pipelines or deferred rendering.

    !!! note "To Keep In Mind"
        Prefer `render()` for immediate visualisation; use `build()` for pipelines.

    Returns:
        VisualiserBase: A configured visualiser instance.

    Raises:
        ValueError: If _type is not set.

    Examples:
        >>> visualiser = mapper.visual.with_type("StaticVisualiser")\
        ...     .with_style({"figsize": (10, 8)})\
        ...     .build()

    """
    logger.log(
        "DEBUG_MID",
        "WARNING: build() should only be used in UrbanPipeline. "
        "In other cases, using render() is a better option.",
    )
    if self._type is None:
        raise ValueError("Visualiser type must be specified.")
    visualiser_class = VISUALISER_REGISTRY[self._type]
    self._instance = visualiser_class(style=self._style)
    if self._preview is not None:
        self.preview(format=self._preview["format"])
    return self._instance

preview(format='ascii')

Generate a preview of the configured visualiser.

Shows the visualiser’s configuration in the specified format.

Parameters:

Name Type Description Default
format str

The format to display ("ascii" or "json"). Defaults to "ascii".

'ascii'

Raises:

Type Description
ValueError

If format is unsupported.

Examples:

>>> factory = mappper.visual.with_type("InteractiveVisualiser").build()
>>> factory.preview(format="json")
Source code in src/urban_mapper/modules/visualiser/visualiser_factory.py
def preview(self, format: str = "ascii") -> None:
    """Generate a preview of the configured visualiser.

    Shows the visualiser’s configuration in the specified format.

    Args:
        format (str): The format to display ("ascii" or "json"). Defaults to "ascii".

    Raises:
        ValueError: If format is unsupported.

    Examples:
        >>> factory = mappper.visual.with_type("InteractiveVisualiser").build()
        >>> factory.preview(format="json")
    """
    if self._instance is None:
        print("No visualiser instance available to preview. Call build() first.")
        return
    if hasattr(self._instance, "preview"):
        preview_data = self._instance.preview(format=format)
        if format == "ascii":
            print(preview_data)
        elif format == "json":
            print(json.dumps(preview_data, indent=2))
        else:
            raise ValueError(f"Unsupported format '{format}'.")
    else:
        print("Preview not supported for this visualiser instance.")

with_preview(format='ascii')

Configure the factory to display a preview after building.

Enables automatic preview after build() or render().

Parameters:

Name Type Description Default
format str

The preview format ("ascii" or "json"). Defaults to "ascii".

'ascii'

Returns:

Name Type Description
VisualiserFactory VisualiserFactory

Self for chaining.

Examples:

>>> visualiser = mapper.visual.with_type("InteractiveVisualiser")            ...     .with_preview(format="json")            ...     .build()
Source code in src/urban_mapper/modules/visualiser/visualiser_factory.py
def with_preview(self, format: str = "ascii") -> "VisualiserFactory":
    """Configure the factory to display a preview after building.

    Enables automatic preview after `build()` or `render()`.

    Args:
        format (str): The preview format ("ascii" or "json"). Defaults to "ascii".

    Returns:
        VisualiserFactory: Self for chaining.

    Examples:
        >>> visualiser = mapper.visual.with_type("InteractiveVisualiser")\
        ...     .with_preview(format="json")\
        ...     .build()
    """
    self._preview = {"format": format}
    return self
Provost Simon