I want to take you through a small function that we have written that will combine the entire PSSE subsystem data retrieval API into a single, easier to use function.
What does the original subsystem data retrieval api look like?
Have you ever looked at the PSSE subsystem data retrieval API (Chapter 8 in the PSSE API guide)? With it you can get information about branches and buses (and other elements like machines) for an entire subsystem. So how would we go about getting a list of all of the bus numbers in subsystem 2?
1
|
|
Things become tricky when we want the bus names and the bus numbers though.
1 2 |
|
We had to know that the NAME
attribute uses a different API call to the
NUMBER
attribute. If we wanted to get the bus per unit voltage we would
need another API call again, and if we wanted the total in service fixed bus
shunt in MW and MVar a fourth API call would be required.
1 2 3 4 |
|
Each of the return values from the API is a nested list. If you wanted to get the name and pu voltage for bus number 340:
1 2 3 |
|
The resulting code can be extremely difficult to read, and quite verbose.
A wrapper around the old API
Using the new subsystem_info
function is easy.
Lets get the bus numbers, names, pu voltages and actual shunt values for subsystem id 2:
1 2 3 4 5 |
|
All of the information we were looking for is organised neatly into rows, rather than separate columns. Here is how we made that function.
How does this work?
The new function relies on some helpful design choices in the original PSSE subsystem data retrieval api.
Each of the functions are named using a regular pattern:
1 2 3 4 |
|
a element type api data type
a bus int
There is a lookup function called abustypes
(we’ll call it types) which
will return a character string that represents each of the api data types. For
example
1 2 |
|
We ask the types function about each of the attributes the user has
requested. So a query like ["NUMBER", "NAME", "PU"]
might return
["I", "R", "C"]
, being int, real and char respectively.
Use a dictionary to store functions
Ok, so we can find a character "I", "R", "C"
that represents the API type.
Translating that character into the correct retrieval function to use is the
clever part.
There is a Python dictionary to look up the corresponding API call for the
attribute requested. So asking for "NUMBER"
which returns "I"
from the
types function will retrieve the psspy.abusint
function from the
dictionary. Using a dictionary to look up a function like this is called the
‘dispatch table pattern’
(example 4.16 in the Python Cookbook if you have a copy)
Grouping related calls to the API together
The difficult part is grouping and returning the API calls in rows and in the
order they were requested. The itertools groupby
function is used to group related API calls together so if we requested
["NUMBER", "TYPE", "NAME"]
we might get ["I", "I", "C"]
from abustypes
.
The groupby
will group the two consecutive “I” api calls together so we can
make one function call:
1
|
|
instead of two function calls:
1 2 |
|
Transpose columns to rows
Finally, we use the built in zip
function to transpose a list of columns into
a list of rows
1 2 |
|