Plotting GDM Models

Plotting GDM Models#

There are two options for plotting GDM models:

  1. Using the plot Function
    This returns an interactive Plotly plot with detailed information displayed on hover.

  2. Plotting from a GeoDataFrame
    Export the model to a GeoDataFrame and use standard geospatial plotting libraries (e.g., GeoPandas or Matplotlib) for visualization.

We start by loading a sample distribution system.

from gdm.distribution import DistributionSystem
from gdmloader.constants import GCS_CASE_SOURCE
from gdmloader.source import SystemLoader
from IPython.display import display, HTML
import plotly.io as pio

pio.renderers.default = "notebook_connected"

gdm_loader = SystemLoader()
gdm_loader.add_source(GCS_CASE_SOURCE)

distribution_system: DistributionSystem = gdm_loader.load_dataset(
    source_name=GCS_CASE_SOURCE.name,
    system_type=DistributionSystem,
    dataset_name="p1rhs7_1247",
)
distribution_system.name = "p1rhs7_1247"
distribution_system.info()
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/gdmloader/source.py:124, in SystemLoader.load_dataset(self, system_type, source_name, dataset_name, version)
    123 try:
--> 124     source.fs.get(
    125         remote_folder,
    126         str(local_folder),
    127         recursive=True,
    128     )
    129 except FileNotFoundError:

File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/fsspec/asyn.py:118, in sync_wrapper.<locals>.wrapper(*args, **kwargs)
    117 self = obj or args[0]
--> 118 return sync(self.loop, func, *args, **kwargs)

File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/fsspec/asyn.py:103, in sync(loop, func, timeout, *args, **kwargs)
    102 elif isinstance(return_result, BaseException):
--> 103     raise return_result
    104 else:

File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/fsspec/asyn.py:56, in _runner(event, coro, result, timeout)
     55 try:
---> 56     result[0] = await coro
     57 except Exception as ex:

File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/fsspec/asyn.py:645, in AsyncFileSystem._get(self, rpath, lpath, recursive, callback, maxdepth, **kwargs)
    644 rpath = self._strip_protocol(rpath)
--> 645 rpaths = await self._expand_path(
    646     rpath, recursive=recursive, maxdepth=maxdepth
    647 )
    648 if source_is_str and (not recursive or maxdepth is not None):
    649     # Non-recursive glob does not copy directories

File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/fsspec/asyn.py:883, in AsyncFileSystem._expand_path(self, path, recursive, maxdepth)
    882 if isinstance(path, str):
--> 883     out = await self._expand_path([path], recursive, maxdepth)
    884 else:

File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/fsspec/asyn.py:912, in AsyncFileSystem._expand_path(self, path, recursive, maxdepth)
    911 if not out:
--> 912     raise FileNotFoundError(path)
    913 return sorted(out)

FileNotFoundError: ['gdm_data/data/DistributionSystem/2_2_0/p1rhs7_1247']

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
Cell In[1], line 12
      9 gdm_loader = SystemLoader()
     10 gdm_loader.add_source(GCS_CASE_SOURCE)
---> 12 distribution_system: DistributionSystem = gdm_loader.load_dataset(
     13     source_name=GCS_CASE_SOURCE.name,
     14     system_type=DistributionSystem,
     15     dataset_name="p1rhs7_1247",
     16 )
     17 distribution_system.name = "p1rhs7_1247"
     18 distribution_system.info()

File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/gdmloader/source.py:131, in SystemLoader.load_dataset(self, system_type, source_name, dataset_name, version)
    129     except FileNotFoundError:
    130         msg = f"{remote_folder=} not found! Check the URL: {source.url}/{remote_folder}"
--> 131         raise ValueError(msg)
    133 system_file = list(dataset_folder.rglob("*.json"))[0]
    134 return system_type.from_json(system_file)

ValueError: remote_folder='gdm_data/data/DistributionSystem/2_2_0/p1rhs7_1247' not found! Check the URL: https://storage.googleapis.com/gdm_data/gdm_data/data/DistributionSystem/2_2_0/p1rhs7_1247

Plotting using Plotly#

fig = distribution_system.plot(
    flip_coordinates=True,
    show=False,
)
display(HTML(pio.to_html(fig, include_plotlyjs="cdn", full_html=False)))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[2], line 5
      1 fig = distribution_system.plot(
      2     flip_coordinates=True,
      3     show=False, 
      4 )
----> 5 display(HTML(pio.to_html(fig, include_plotlyjs="cdn", full_html=False)))

File /opt/homebrew/Caskroom/miniconda/base/envs/gdm2/lib/python3.12/site-packages/plotly/io/_html.py:130, in to_html(fig, config, auto_play, include_plotlyjs, include_mathjax, post_script, full_html, animation_opts, default_width, default_height, validate, div_id)
    127 from plotly.io.json import to_json_plotly
    129 # ## Validate figure ##
--> 130 fig_dict = validate_coerce_fig_to_dict(fig, validate)
    132 # ## Generate div id ##
    133 plotdivid = div_id or str(uuid.uuid4())

File /opt/homebrew/Caskroom/miniconda/base/envs/gdm2/lib/python3.12/site-packages/plotly/io/_utils.py:20, in validate_coerce_fig_to_dict(fig, validate)
     18         fig_dict = fig.to_plotly_json()
     19     else:
---> 20         raise ValueError(
     21             """
     22 The fig parameter must be a dict or Figure.
     23     Received value of type {typ}: {v}""".format(
     24                 typ=type(fig), v=fig
     25             )
     26         )
     27     return fig_dict

ValueError: 
The fig parameter must be a dict or Figure.
    Received value of type <class 'NoneType'>: None
from gdm.distribution.enums import MapType, PlotingStyle

fig = distribution_system.plot(
    map_type=MapType.SCATTER_MAP,
    style=PlotingStyle.OPEN_STREET_MAP,
    flip_coordinates=True,
    show=False,
)
display(HTML(pio.to_html(fig, include_plotlyjs="cdn", full_html=False)))
distribution_system.plot(
    map_type=MapType.SCATTER_MAP,
    style=PlotingStyle.CARTO_DARKMATTER,
    flip_coordinates=True,
    show=False,
)
display(HTML(pio.to_html(fig, include_plotlyjs="cdn", full_html=False)))
fig = distribution_system.plot(
    map_type=MapType.SCATTER_MAP,
    style=PlotingStyle.CARTO_POSITRON,
    flip_coordinates=True,
    show=False,
)
display(HTML(pio.to_html(fig, include_plotlyjs="cdn", full_html=False)))

Distribution system plots can be styled by passing plotting options to the function to customize their appearance.

from gdm.distribution.enums import ColorNodeBy, ColorLineBy

distribution_system.plot(
    color_node_by=ColorNodeBy.VOLTAGE_LEVEL,
    color_line_by=ColorLineBy.PHASE,
    flip_coordinates=True,
)
display(HTML(pio.to_html(fig, include_plotlyjs="cdn", full_html=False)))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[3], line 8
      1 from gdm.distribution.enums import ColorNodeBy, ColorLineBy
      3 distribution_system.plot(
      4     color_node_by=ColorNodeBy.VOLTAGE_LEVEL, 
      5     color_line_by=ColorLineBy.PHASE,
      6     flip_coordinates=True,
      7 )
----> 8 display(HTML(pio.to_html(fig, include_plotlyjs="cdn", full_html=False)))

File /opt/homebrew/Caskroom/miniconda/base/envs/gdm2/lib/python3.12/site-packages/plotly/io/_html.py:130, in to_html(fig, config, auto_play, include_plotlyjs, include_mathjax, post_script, full_html, animation_opts, default_width, default_height, validate, div_id)
    127 from plotly.io.json import to_json_plotly
    129 # ## Validate figure ##
--> 130 fig_dict = validate_coerce_fig_to_dict(fig, validate)
    132 # ## Generate div id ##
    133 plotdivid = div_id or str(uuid.uuid4())

File /opt/homebrew/Caskroom/miniconda/base/envs/gdm2/lib/python3.12/site-packages/plotly/io/_utils.py:20, in validate_coerce_fig_to_dict(fig, validate)
     18         fig_dict = fig.to_plotly_json()
     19     else:
---> 20         raise ValueError(
     21             """
     22 The fig parameter must be a dict or Figure.
     23     Received value of type {typ}: {v}""".format(
     24                 typ=type(fig), v=fig
     25             )
     26         )
     27     return fig_dict

ValueError: 
The fig parameter must be a dict or Figure.
    Received value of type <class 'NoneType'>: None
## Plotting using Matplotlib

df = distribution_system.to_gdf()
df.plot()
<Axes: >
../_images/eca421608ced819edca1a282042abdeed3e17d923efef41f6989d2fa666faf99.png