In [1]:
import pandas as pd
import numpy as np
from psst.network.graph import (
NetworkModel, NetworkViewBase, NetworkView
)
from psst.case import read_matpower
case = read_matpower('../cases/case118.m')
In [2]:
# Create the model from a PSSTCase, optionally passing a sel_bus
m = NetworkModel(case, sel_bus='Bus1')
In [3]:
display(m.case) # saves the case
display(m.network) # creates a PSSTNetwork
display(m.G) # stores the networkX graph (an attribute of the PSSTNetwork)
display(m.model) # builds/solves the model
In [4]:
# Creates df of x,y positions for each node (bus, load, gen), based off self.network.positions
m.all_pos.head(n=10)
Out[4]:
In [5]:
# Creates a df of start and end x,y positions for each edge, based off self.G.edges()
m.all_edges.head(n=10)
Out[5]:
In [6]:
# `sel_bus` is a single bus, upon which the visualization is initially centered.
# It can be changed programatically, or via the dropdown menu.
m.sel_bus
Out[6]:
In [7]:
# At first, it is the only bus in view_buses.
# More buses get added to view_buses as they are clicked.
m.view_buses
Out[7]:
In [8]:
# Create the view from the model
# (It can, alternatively, be created from a case.)
v = NetworkView(model=m)
In [9]:
v
view_buses list get changed, it triggers the callback _callback_view_changesubset_positions and subset_edgesbus, gen, and loadNetworkView can use.
In [10]:
# The subsetting that occurs is all based on `view_buses`
m.view_buses
Out[10]:
In [11]:
# Subset positions creates self.pos
m.pos
Out[11]:
The function looks like this:
def subset_positions(self):
"""Subset self.all_pos to include only nodes adjacent to those in view_buses list."""
nodes = [list(self.G.adj[item].keys()) for item in self.view_buses] # get list of nodes adj to selected buses
nodes = set(itertools.chain.from_iterable(nodes)) # chain lists together, eliminate duplicates w/ set
nodes.update(self.view_buses) # Add the view_buses themselves to the set
return self.all_pos.loc[nodes] # Subset df of all positions to include only desired nodes.
In [12]:
# Subset edges creates self.edges
m.edges
Out[12]:
The function looks like this:
def subset_edges(self):
"""Subset all_edges, with G.edges() info, based on view_buses list."""
edge_list = self.G.edges(nbunch=self.view_buses) # get edges of view_buses as list of tuples
edges_fwd = self.all_edges.loc[edge_list] # query all_pos with edge_list
edge_list_rev = [tuple(reversed(tup)) for tup in edge_list] # reverse order of each tuple
edges_rev = self.all_edges.loc[edge_list_rev] # query all_pos again, with reversed edge_list
edges = edges_fwd.append(edges_rev).dropna(subset=['start_x']) # combine results, dropping false hits
return edges
If you want a closer look...
In [13]:
m.view_buses = ['Bus2','Bus3']
In [14]:
edge_list = m.G.edges(nbunch=m.view_buses) # get edges of view_buses as list of tuples
edge_list
Out[14]:
In [15]:
edges_fwd = m.all_edges.loc[edge_list] # query all_pos with edge_list
edges_fwd
Out[15]:
In [16]:
edge_list_rev = [tuple(reversed(tup)) for tup in edge_list] # reverse order of each tuple
edge_list_rev
Out[16]:
In [17]:
edges_rev = m.all_edges.loc[edge_list_rev] # query all_pos again, with reversed edge_list
edges_rev
Out[17]:
In [18]:
edges = edges_fwd.append(edges_rev).dropna(subset=['start_x']) # combine results, dropping false hits
edges
Out[18]:
bus, case, and load, using the names in case.bus, case.gen, and case.loadNetworkViewExtracting bus data looks like this:
bus_pos = self.pos[self.pos.index.isin(self.case.bus_name)]
self.bus_x_vals = bus_pos['x']
self.bus_y_vals = bus_pos['y']
self.bus_names = list(bus_pos.index)
(Similar for the other nodes)
In [19]:
print("x_vals: ", m.bus_x_vals)
print("y_vals: ", m.bus_y_vals)
print("names: ", m.bus_names)
Extracting branch data looks like this:
edges = self.edges.reset_index()
_df = edges.loc[edges.start.isin(self.case.bus_name) & edges.end.isin(self.case.bus_name)]
self.bus_x_edges = [tuple(edge) for edge in _df[['start_x', 'end_x']].values]
self.bus_y_edges = [tuple(edge) for edge in _df[['start_y', 'end_y']].values]
(Similar for the other edges)
In [20]:
print("bus_x_edges:")
print(m.bus_x_edges)
print("\nbus_y_edges:")
print(m.bus_y_edges)