Skip to content

Conversation

@bobbyxng
Copy link
Contributor

@bobbyxng bobbyxng commented Aug 4, 2025

Changes proposed in this Pull Request

  • Improving n.explore() and extending its functionalities with interactive plots
  • Changing backend from folium to pydeck

Implemented features

  • bus_sizes
  • bus_colors
  • bus_alpha
  • bus_columns
  • line_flow
  • line_colors
  • line_alpha
  • line_widths
  • line_columns
  • link_flow
  • link_colors
  • link_alpha
  • link_widths
  • link_columns
  • transformer_flow
  • transformer_colors
  • transformer_alpha
  • transformer_widths
  • transformer_columns
  • arrow_size_factor
  • arrow_colors
  • arrow_alpha
  • map_style
  • tooltip
  • geomap
  • jitter
  • _cmap,
  • _cmap_norm
  • multi-index bus_sizes for pie charts (Need to create individual pie chart slice polygons)

Checklist

  • Code changes are sufficiently documented; i.e. new functions contain docstrings and further explanations may be given in doc.
  • Unit tests for new features were added (if applicable).
  • A note for the release notes doc/release_notes.rst of the upcoming release is included.
  • I consent to the release of this PR's code under the MIT license.

@bobbyxng bobbyxng self-assigned this Aug 4, 2025
@bobbyxng bobbyxng marked this pull request as draft August 4, 2025 13:50
@bobbyxng bobbyxng changed the title Extending n.explore() New architecture and functions for n.explore() using a new PydeckPlotter class Aug 4, 2025
Base automatically changed from new-opt to master August 12, 2025 21:03
@bobbyxng
Copy link
Contributor Author

Update: Apart from generating pie charts based on multi-index pd.Series, all functionality from static n.plot() are now implemented in n.explore, with identical API wherever applicable:

Create an interactive map of the PyPSA network using Pydeck.

    Parameters
    ----------
    n : Network
        The PyPSA network to plot.
    bus_sizes : float/dict/pandas.Series
        Sizes of bus points in meters, defaults to 5000.
    bus_colors : str/dict/pandas.Series
        Colors for the buses, defaults to "cadetblue".
    bus_alpha : float/dict/pandas.Series
        Add alpha channel to buses, defaults to 0.7.
    bus_columns : list, default None
        List of bus columns to include. If None, only the bus index and x, y coordinates are used.
        Specify additional columns to include in the tooltip.
    line_flow : float/dict/pandas.Series/None
        Series of line flows indexed by line names, defaults to None. If None, no arrows will be created.
        If a float is provided, it will be used as a constant flow for all lines.
    line_colors : str/dict/pandas.Series
        Colors for the lines, defaults to 'rosybrown'.
    line_alpha : float/dict/pandas.Series
        Add alpha channel to lines, defaults to 0.7.
    line_widths : float/dict/pandas.Series
        Widths of lines in meters, defaults to 1500.
    line_columns : list, default None
        List of line columns to include. If None, only the bus0 and bus1 columns are used.
        Specify additional columns to include in the tooltip.
    link_flow : float/dict/pandas.Series/None
        Series of link flows indexed by link names, defaults to None. If None, no arrows will be created.
        If a float is provided, it will be used as a constant flow for all links.
    link_colors : str/dict/pandas.Series
        Colors for the links, defaults to 'darkseagreen'.
    link_alpha : float/dict/pandas.Series
        Add alpha channel to links, defaults to 0.7.
    link_widths : float/dict/pandas.Series
        Widths of links in meters, defaults to 1500.
    link_columns : list, default None
        List of link columns to include. If None, only the bus0 and bus1 columns are used.
        Specify additional columns to include in the tooltip.
    transformer_flow : float/dict/pandas.Series/None
        Series of transformer flows indexed by transformer names, defaults to None. If None, no arrows will be created.
        If a float is provided, it will be used as a constant flow for all transformers.
    transformer_colors : str/dict/pandas.Series
        Colors for the transformers, defaults to 'orange'.
    transformer_alpha : float/dict/pandas.Series
        Add alpha channel to transformers, defaults to 0.7.
    transformer_widths : float/dict/pandas.Series
        Widths of transformers in meters, defaults to 1500.
    transformer_columns : list, default None
        List of transformer columns to include. If None, only the bus0 and bus1 columns are used.
        Specify additional columns to include in the tooltip.
    arrow_size_factor : float, default 2.5
        Factor to scale the arrow size in relation to line_flow. A value of 1 denotes a multiplier of 1xline_width.
    arrow_colors : str/dict/pandas.Series | None, default None
        Colors for the arrows. If not specified, defaults to the same colors as the respective branch component.
    arrow_alpha : float/dict/pandas.Series, default 1.0
        Add alpha channel to arrows, defaults to 1.0.
    map_style : str
        Map style to use for the plot. One of 'light', 'dark', 'road', 'satellite', 'dark_no_labels', and 'light_no_labels'.
    tooltip : bool, default True
        Whether to add a tooltip to the bus layer.

    Returns
    -------
    pdk.Deck
        The interactive map as a Pydeck Deck object.

Currently, n.explore() would directly return a functioning pydeck object which could be directly manipulated using pydecks built-in methods. It also allows for stacking with other already generated pydeck object, very similar to how matplotlib.pyplot handles stacking.

However, by returning a pydeck object directly, subsequent manipulations to the generated object can only be done on the pydeck object level, not on the PydeckPlotter class (which is introduced in pypsa.plot.maps.interactive).

For example, not implemented though, the PydeckPlotter class can have additional properties like buses_without_coordinates, branch_components_dropped, etc. (tbd. whether this is useful at all).

Long story short, here are the options I see:
a) Keep as it is now, only use PydeckPlotter class for structuring methods, return a pydeck object with n.explore()
b) Return a PydeckPlotter object with n.explore(). Then a user would do the following operation to get the pydeck object: map = n.explore(), followed by map.deck()
c) PydeckPlotter inherits from pydeck class and is extended by additional methods and properties. Requires some refactoring of code.

Do you have any thoughts @lkstrp, @fneum, @FabianHofmann ?

@bobbyxng
Copy link
Contributor Author

Sneak preview:
image

@bobbyxng
Copy link
Contributor Author

  • Added auto_scale based on bus_size_max and branch_width_max
  • Added support for geometry column in branch components

@bobbyxng
Copy link
Contributor Author

From my side it's also ready to merge :)
Thank you both @lkstrp and @fneum !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants