Python Tutorial
Python Tutorial
Application Guide
PowerFactory Version 15.2
Python Tutorial
DIgSILENT Technical Documentation
DIgSILENT GmbH
Heinrich-Hertz-Str. 9
72810 - Gomaringen
Germany
T: +49 7072 9168 00
F: +49 7072 9168 88
http://www.digsilent.de
info@digsilent.de
Revision r1530
Copyright 2014, DIgSILENT GmbH. Copyright of this document belongs to DIgSILENT GmbH.
No part of this document may be reproduced, copied, or transmitted in any form, by any means
electronic or mechanical, without the prior written permission of DIgSILENT GmbH.
Python Tutorial (DIgSILENT Technical Documentation)
Contents
Contents
1 Getting Started in Python-PowerFactory -A Quick Tutorial
1.4 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
13
13
13
13
14
14
14
15
16
. . . . . . . . . . . . . . . . . . . . . . . .
17
18
18
18
19
19
20
20
20
21
21
22
Contents
22
22
23
23
25
25
27
. . . . . . . . . . . . . . . . . . . . . . . . . .
27
27
27
28
28
29
30
30
30
31
32
32
. . . . . . . . . . . . . . . . . . . . . . . .
32
32
34
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
34
34
35
36
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
39
Contents
39
41
. . . . . . . . . . . . . . . . . . . . . . . .
This is a short step-by-step tutorial that attempts to get the user started in writing and running
Python scripts. Before going through this tutorial, the user should already have a basic grasp
of PowerFactory handling and performing simple tasks such as load flows and short circuit
simulations.
Python is not directly installed on host computer by installing PowerFactory . This means user
have to install Python separately. Details on Python installation you may find in PowerFactory
user Manual.
1.1
Firstly, we will create a small sample project. Create a new project and draw the following simple
20kV network using line types from the global library:
1.2
1.3
In contrast to DPL, Python command object ComPython does not contain the scripts code, it
only links the Python script file .py. It stores only the file path of the script and not the code itself.
1.3.1
The powerfactory module interfaces with the PowerFactory API (Application Programming Interface). This solution enables a Python script to have access to a comprehensive range of data
available in PowerFactory :
All objects
All attributes (element data, type data, results)
All commands (load flow calculation, etc)
Most special built-in functions (DPL functions)
To gain access to the PowerFactory environment the command GetApplication() must be added:
app=powerfactory.GetApplication()
1.4
Example
We will now write a Python script that will execute a load flow and print out the name of each
line and its corresponding loading in the output window. Type the following code into the script
file:
Python Tutorial (DIgSILENT Technical Documentation)
Link the .py script file and the Python command object (see section 1.3)
Click Save and then Execute. The following results should be seen in the output window:
Whenever you open a Python command object, you will see a window with a number of tabs :
Basic Options, Advanced Options, Script, Description and Version. We will go through each tab
and the functions that are available.
The Basic Options tab (shown above) has the following functions:
Name field - Changes the name of the Python command object
Define internal input parameters - in the script, the names of the input parameters can be
used like variables and do not need to be redefined
Python Tutorial (DIgSILENT Technical Documentation)
10
Define external objects - these are objects external to the Python command object that
you want to access via the script. This can be any object, e.g. an element in the network
model, a study case, an equipment type, etc. Inside the script, the object can be used like
a variable by calling the name defined here.
Important: To access an external object or input parameter inside of a Python script you have
to call the script object (ComPython) first and then to access the object/parameter through
ScriptObj.ExternObjName:
script=app.GetCurentScript() #to call the current script
extObj=script.NameOfExternObj #to call the External Object
inpPar=script.NameOfInpPram #to call Input Parameter
The Advanced Options tab (shown below) has the following functions:
Select a remote script - rather than use a script defined locally in the Python command
object, you can select a script that has been defined in a separate object.
One reason to employ a remote script is if you have multiple study cases using the same
script code, but different input parameters. If you were to use a remote script, then modifying the master script will affect all the Python objects that refer to it. If you had locally
defined scripts, then you would need to change the code in every single local Python
object individually.
Define result parameters - these are essentially output parameters that are stored inside
the Python command object (even after script execution). You can access these parameters as if they were from any other type of object, i.e. either by another Python script or as
a variable to display on a plot.
The Description and Version tabs are informational tabs for script descriptions and revision
information.
The Python command object may contain objects or references to other objects available in
the PowerFactory database. These can be accessed by clicking on the Contents button. New
objects are defined by first clicking the New Object
icon in the toolbar of the Python script
contents dialogue and then by selecting the required object from the New Object pop-up window
11
which appears. References to other objects are created by defining a IntRef reference object.
An example showing the possible contents of a Python command object is shown in Figure 2.3.
12
3.1
The general approach for accessing network objects in Python purely through code is as follows:
Get a list of the relevant network objects that you are looking for (using the GetCalcRelevantObjects() command), based on a specific element type, e.g. lines, transformers,
motors, etc
Get an object within this list through indexing (list[x]) or by using a for loop, etc
The code snippet below gets the set of all lines, cycles through each line object and prints out
its full name:
import powerfactory
app=powerfactory.GetApplication()
Lines=app.GetCalcRelevantObjects(*.ElmLne) #get list of all lines
for line in Lines:
app.PrintPlain(line.loc_name)
The code snippet below gets the set of all objects, and tries to find the particular line called
Line1:
import powerfactory
app=powerfactory.GetApplication()
AllObj=app.GetCalcRelevantObjects() #get list of all objects
Line=app.GetCalcRelevantObjects(Line1.ElmLne) #get a line Line1
app.PrintPlain(Line[0].loc_name)
The code snippet below gets the list of all objects, filters for all lines starting with Line, cycles
through each line object in the filtered set of lines and prints out its full name.
import powerfactory
app=powerfactory.GetApplication()
AllObj=app.GetCalcRelevantObjects() #get list of all objects
#Filter the set with all lines starting with Line
Lines=app.GetCalcRelevantObjects(Line*.ElmLne)
for Line in Lines:
app.PrintPlain(Lines.loc_name)
3.2
Once a specific object has been selected, the way to access the object parameters or variables
is by typing out the object name and the variable name separated by a point ., e.g.
Object name.Variable name
for example
NameOfALine=Line.loc_name
3.2.1
Variable names can often be found in the manual and in the technical references, but the easiest
way to identify variable names is to open the Edit dialogue of the relevant object and hover the
Python Tutorial (DIgSILENT Technical Documentation)
13
mouse over the field of interest. A tooltip will appear with the corresponding variable name. For
example, hovering over the power factor field in the static generator element yields the variable
name: cosn:
3.2.2
Accessing Parameter
Suppose we have a line object oLine and we want to save the length of the line (variable name
= dline) to an internal Python variable dLength, the instruction below may be used:
dLength=oLine.dline
3.2.3
Modifying Parameters
Suppose we have a line object oLine and we want to change the length of the line (variable
name = dline) to 2km, the instruction below may be used:
oLine.dline=2
3.3
There are at least three ways to create new objects in the database:
Copy template object contained inside the script object
Python Tutorial (DIgSILENT Technical Documentation)
14
3.3.1
Copying an interal template object is potentially the easiest option for creating new objects. The
Python command object can contain other objects within it. To access the contents of a Python
object, click on the smarksContents button of the Python command dialogue:
You can use an internal object inside the Python command object as a template for the object
type you want to create. In the figure above, an event (EvtShc) object named SC Event is
placed inside the Python command object and used as template.
To create the object, you can use the AddCopy(object name) command. In order to use this
command, you must first locate the folder (or object) that you want to copy the template into.
For example, suppose oFold is an object with the reference to the target folder and SC Event
is the internal template object, a new object will be created in the target folder by the following
command:
oFold.AddCopy(SCEvent)
The code snippet below copies an internal short circuit event template into the simulation events
folder of the active study case and then changes the time of the copied event to t=1.
import powerfactory
app=powerfactory.GetApplication()
#Get the simulation events folder from the active study case
oFold=app.GetFromStudyCase(IntEVt)
app.PrintPlain(oFold)
#Get Internal template object
15
Script=app.GetCurrentScript()
Contents=Script.GetContents()
SC_Event=Contents[0]
#Copy the template short circuit event into the events folder
oFold.AddCopy(SC_Event)
#Get the copied event and set the time to 1
EventSet=oFold.GetContents(*.EvtShc)
app.PrintPlain(EventSet)
oEvent=EventSet[0][0]
oEvent.time=1
3.3.2
This procedure is almost identical to copying an object from an internal template, except that
an external object is referenced instead of using an object from inside the Python command. In
the Python command dialogue (under Basic Options), there is an area for referencing external
objects:
To use this area, simply double-click on the object field and select an object you would like to
reference from anywhere in the project hierarchy. One distinction of this method is that you can
give the object any name (using the Name field). This is the name that the object will be called
inside the Python script.
Once the external template object has been selected, you can use the AddCopy(object name)
command to create a new object in the database. In order to use this command, you must first
locate the folder (or object) that you want to copy the template into.
For example, suppose oFold is an object with the reference to the target folder and SC Event
is the external template object, a new object will be created in the target folder by the following:
oFold.AddCopy(SC Event)
16
The code snippet below copies an external short circuit event template into the simulation events
folder of the active study case and then changes the time of the copied event to t=1.
import powerfactory
app=powerfactory.GetApplication()
#Get the simulation events folder from the active study case
oFold=app.GetFromStudyCase(IntEVt)
app.PrintPlain(oFold)
#Get External template object
Script=app.GetCurrentScript()
SC_Event=Script.SC_Event
#Copy the template short circuit event into the events folder
oFold.AddCopy(SC_Event)
#Get the copied event and set the time to 1
EventSet=oFold.GetContents(*.EvtShc)
app.PrintPlain(EventSet)
oEvent=EventSet[0][0]
oEvent.time=1
3.3.3
Creating new objects purely by code is the most intensive method for making new objects, because all of the object parameters need to be set in code. With template objects, you can set
default parameters and even add child objects inside the template).
The CreateObject(class name, object name) function is used to create new objects. Like
the previous two methods, you must first locate the folder (or object) that you want to create the
object in.
For example, suppose oFold is an object with the reference to the target folder and you want
to create a short-circuit event object (*.EvtShc) called SC Event, you would use the following
command:
oFolder.CreateObject(EvtShc,SC Event)
Note that if the target folder (or object) does not accept the object class you are trying to create
(e.g. a VI page object in the simulation events folder) then an error will be raised.
The code snippet below creates a new short circuit event into the simulation events folder of
the active study case and then sets the time of the event to t=1.
import powerfactory
app=powerfactory.GetApplication()
#Get the simulation events folder from the active study case
oFold=app.GetFromStudyCase(IntEVt)
app.PrintPlain(oFold)
#Copy the template short circuit event into the events folder
oFold.CreateObject(EvtShc,SC_Event)
#Get the copied event and set the time to 1
EventSet=oFold.GetContents(*.EvtShc)
app.PrintPlain(EventSet)
17
oEvent=EventSet[0][0]
oEvent.time=1
3.4
3.4.1
As an entry or starting point into the project folder hierarchy, use the GetProjectFolder(string)
function. This function will return an object with a reference to the top level of project folders,
e.g. the folders containing study cases, scripts, libraries, diagrams, etc.
For example, the following line puts a reference to the equipment type library folder into object oFold:
oFold=app.GetProjectFolder(equip)
A list of the project folders available and the corresponding string is shown below:
String
equip
netmod
oplib
scen
script
study
templ
netdat
dia
scheme
cbrat
therm
ra
mvar
outage
fault
3.4.2
Folder Description
Equipment type libary
Network model
Operational libary
Operational scenario
Script
Study Case
Template
Network data
Diagram
Variation
CB rating
Thermal rating
Running arrangement
Mvar limits curve
Outage
Fault
Object Contents
The GetContents(string) function is a generic way of navigating through objects and finding
the list of objects contained within them. The function returns a list of objects that meet the
criteria in the string.
Some examples:
Return all objects contained in oObj into the list Contents
Contents=oObj.GetContents()
Return ElmTerm type objects (terminals) contained in oObj into the list Contents
Contents=oObj.GetContents(*.ElmTerm)
18
Return the specific object T2.ElmTerm contained in oObj into the list Contents
Contents = oObj.GetContents(T2.ElmTerm)
Return all ElmTerm type objects that have names starting with T contained in oObj
into the list Contents
Contents = oObj.GetContents(T*.ElmTerm)
3.4.3
In order to access objects within the active study case (e.g. calculation command objects, simulation events, graphics boards, sets, outputs of results, title blocks, etc), you can use the function
GetFromStudyCase(string).
This function is essentially a shortcut to accessing objects inside a study case, which is used to
navigate to the study case project folder, selecting a study case and then selecting an object.
The other advantage of GetFromStudyCase() is that if the object does not exist inside the study
case, the function will create it.
Note however that this function only works with the active study case.
The code snippet below gets the graphics board object from the active study case.
import powerfactory
app=powerfactory.GetApplication()
oDesk=app.GetFromStudyCase(SetDesktop)
app.PrintPlain(oDesk)
3.5
Study cases are IntCase objects that are stored in the study cases project folder. In order to
access a study case, you must first access the study case folder.
The code snippet below does the following:
Gets the list of all study cases.
Counts the number of study cases.
Activates each study case and prints its full name.
import powerfactory
app=powerfactory.GetApplication()
#Get the study case folder and its contents
aFolder=app.GetProjectFolder(study)
aCases=aFolder.GetContents(*.IntCase)
aCases=aCases[0]
#Counts the number of study cases
iCases=len(aCases)
if iCases==0:
app.PrintError(There is 0 of study cases)
else:
19
Note that if there are subfolders within the study case folder, then further processing needs to
be done to access the study case objects within these subfolders. For more information please
refer to Navigating Project Folders in section 3.4.
3.6
Executing Calculations
Load flow
Short circuit
Time domain (RMS or EMT) simulation
Time domain initial conditions
Contingency analysis
Reliability assessment
Modal analysis
Harmonic load flow
Initialise generation adequacy
Run generation adequacy
Optimal capacitor placement
Load flow sensiivities
Network reduction
Voltage sag table assessment
Cable reinforcement optimisation
Tie open point optimisation
State estimator
Flickermeter
The code snippet below executes a load flow in the active study case:
import powerfactory
app=powerfactory.GetApplication()
#Get load flow object from study case
ldf=app.GetFromStudyCase(ComLdf)
#Execute load flow calculation
ldf.Execute()
3.7
3.7.1
Accessing Results
Static Calculations (Load Flow, Short Circuit, etc)
The results of static calculations are stored as parameters in the objects themselves. To get the
value of these results you can use GetAttribute(string) method.
20
3.7.2
Dynamic Simulations
Unlike the static cases, the results of dynamic simulations are not stored as part of the object
parameter, but in a separate results file .ElmRes. Refer to the section 5 for more information.
3.8
Python offers a few options for writing text to the output window:
Print a formatted string to the output window
app.PrintPlain(string %(variables))
this function works on the same way as printf in DPL
app.PrintPlain(Hallo world)
Prints the string in output window
app.PrintPlain(Voltage = %f %(dVoltage))
Prints combination out of string and value. Note that by default, PowerFactory prints 6
decimal places for floating point variables. To change the number of decimal places, use
the decimal place specifier in the % tag. For example, for 3 decimal places
app.PrintPlain(Voltage = %.3f %(dVoltage))
Print a error, warning and information message
app.PrintError(string)
app.PrintWarn(string)
app.PrintInfo(string)
21
3.9
Plotting Results
Plots from dynamic (time-domain) or static simulations can be easily created using Python.
3.9.1
You can create a new virtual instrument (VI) page using a graphics board object (*.SetDesktop).
The functionGetPage (string name, int create) will create a new page provided the name does
not refer to an existing VI page and the create flag is activated (=1).
For example, the snippet below uses the graphics board object Desktop to create a VI page
called Plots:
Desktop=app.GetFromStudyCase(SetDesktop)
Vi=Desktop.GetPage(Plots,1)
3.9.2
Similar to creating a new VI page, you can use the VI page object (*.SetVipage) to create a new
virtual instrument with the function GetVI (string name, string class, int create). To create a
new VI, the name should not be the same as another existing VI and the create flag should be
activated (=1).
The class of the VI is the type of VI that you want to create. If it is not entered, the class is
set as a subplot (*.VisPlot) by default. The classes for virtual instruments are shown below:
VisPlot - Subplot
VisPlot2 - Subplot with two y-axis
VisXyplot - X-Y plot
VisFft - FFT plot
VisOcplot - Time-overcurrent plot
VisDraw - R-X plot
VisPlotz - Time-distance plot
VisEigen - Eigenvalue plot
VisModbar - Mode bar plot
VisModphasor - Mode phasor plot
VisVec - Vector diagram
VisHrm - Waveform plot
VisBdia - Distortion plot
VisPath - Voltage profile plot
VisVsag - Voltage sag plot
VisPdc - Probability density plot
22
3.9.3
In order to show the actual plots on a VI, you need to add objects and variables to the VI. Using
the VI object, use the AddVars function to add variables and objects to the plot. The function
AddVars can be used in one of two ways:
AddVars(string V, object O1,...O8)
Here we want to add the variable V to objects O1 to O8 (i.e. variables can be added
to up to 8 objects simultaneously).
For example, the snippet below adds the variable m:u1 for the objects oBus1 and
oBus2 to the VI object oPlot (oBus1 and oBus2 could be substation buses and we
want to plot the voltage m:u1 on these buses):
oPlot.AddVars(m:u1, oBus1, oBus2)
AddVars(object O, string V1,..V8)
Alternatively, we can add multiple variables V1 to V8 to a single object O (i.e. up to 8
variables can be added to an object simultaneously).
For example, the snippet below adds the variables m:u1 and m:phiu for the object
oBus1 to the VI object oPlot:
oPlot.AddVars( oBus1, m:u1, m:phiu)
3.9.4
Plotting Example
The example below gets the current graphics board, creates a new VI page called Plots,
creates a subplot, adds the variable m:u1 for the object oBus (which is defined elsewhere)
and then adjusts the y-axis maximum and minimum range:
#Get current graphic board
oGrb=app.GetGraphicsBoard()
#Create VI Page
oViPg=oGrb.GetPage(Plats,1)
#Create a new subplot
23
oPlot=oViPg[0].GetVI(Subplot,VisVec,1)
#Add variable m:u1 for the object oBus
oPlot[0].AddVars(oBus[0],m:u1)
#Adjust y-axis min and max settings
oPlot[0].y_max=2
oPlot[0].y_min=0
For further details on manipulating Virtual Instrument panels in Python, please refer to section
6.
24
4.1
Topological Search
It is sometimes useful to be able to navigate topologically through a network and search for elements using Python. For example, suppose you want to get the list of transformers connected
to a bus, or you want to follow a branch circuit through lines and transformers to its end point.
PowerFactory has a number of python functions that can help in this task.
Some of the useful topological search functions:
Object Functions
get a list of the elements connected to an object
GetConnectedElms(Breakers,disconnectors,out of service)
Example a): setObj=oTerm.GetConnectedElms(1,1,0)
Gets all of elements connected to oTerm and puts it into the list setObj, taking
into account the state of breakers and switch-disconnector, but disregarding out of
service flags.
Example b): setObj=oTerm.GetConnectedElms()
By default, the options are set to (0,0,0). Therefore, this gets the set of all elements
connected to oTerm, irrespective of breaker/ switch operating states and out of service flags.
Important Node: when using this function to find connected terminals, one must
be careful about the use of the internal node option in terminals.
25
26
of the branch, and taking into account switch states (i.e. it will stop at an open switch).
Example b): setObj=oCub.GetAll(0,0)
Gets the list of all network elements starting from cubicle oCub in the direction
of the terminal, ignoring switch states.
Example c): setObj=oCub.GetAll()
Without setting any of the options, the above snippet is equivalent to calling oCub.GetAll(1,0),
i.e. traversal in the direction of the branch ignoring switch states.
4.2
4.2.1
The standard file I/O methods for Python scripting in PowerFactory are the same as in Python.
For more information please refer to standard Python literature e.g. https://docs.python.org/3/
4.2.2
The function WriteWMF(filename) can be used to export the active graphics page to a graphic
file in Windows Metafile (WMF) format. The function can only be used with a graphics board
object (*.SetDesktop), so a relevant graphics board object needs to be retrieved before exporting to a WMF.
The example below gets the first graphics board in the active study case and exports the active
VI page to the path / file c:\temp\results1.wmf:
import powerfactory
app=powerfactory.GetApplication()
oDesk=app.GetFromStudyCase(SetDesktop)
oDesk.WriteWMF(C:\Users\.....\Desktop\result)
4.3
A Fast Fourier Transform (FFT) can be executed on the results of a time domain simulation
using the FFT Calculation object (ComFft):
27
To execute an FFT in Python, the easiest approach is to manually create the FFT Calculation
object inside the Python command object with the relevant settings pre-defined. The following
steps should then be followed to set up the results files, run the FFT and accessing the results.
4.3.1
The FFT calculation object requires a time domain simulation results file (ElmRes) and the FFT
calculation output is stored in another results file. These input and output results files need to
be specified. In the Python script, these can be specified by using the FFT calculation object
variables pRes in and pRes out.
For example, given the FFT calculation object FFT Calculation:
FFT Calculation.pRes in=EMT Calc
FFT Calculation.pRes out=FFT Results
4.3.2
To execute the FFT calculation, simply use the Execute() method of the FFT calculation object:
FFT Calculation.Execute()
28
4.3.3
The FFT results are stored in the output results file that was specified earlier in the FFT calculation object. How to access this result data please see Chapter 5.
29
Suppose you want to get a PowerFactory Results file (of type ElmRes) from a dynamic simulation, peer into it, pull out a set of relevant values, perform some calculations on the data and
generate some outputs. How do you do that? This section describes how to use a Python script
to manipulate Results files from dynamic simulations.
5.1
The easiest way to work with a results file is to save it into the Python script command object.
For example, you can drag and drop an All Calculations results file into your script. Note that
the name of the results file needs to be changed to eliminate spaces, e.g. in the screenshot
below, All Calculations has been renamed to All calcs.
Once it has been dragged or created into the script, the Results file can be called inside the
Python script. All object methods and functions are exposed.
5.2
In order to manipulate the data in a Results file, it is important to understand the structure of the
file and how data is stored inside it. The results file is structured as a 2d matrix as shown in the
figure below.
30
The number of rows represents the total number of time intervals for the simulation. For example, if there is 10s of simulation with a time step of 0.01s, then there would be 1,000 rows. Each
row represents a time interval.
Column 1 in the Results file is the time of the simulation.
Columns 2 onward represent the objects (shown in the diagram as object 1 to object n) and
their respective variables (shown in the diagram as var1 to vark). An object can be any PowerFactory object (e.g. a line, motor, terminal, load, etc) and a variable is any element defined
in a variable set for the specific object that is to be measured during the simulation (e.g. m:u1,
s:speed, etc)
Note that in the diagram above, each object has k variables, but this is not necessarily the
case in practice as each object can be defined with an arbitrary number of variables in the set.
It is important to know that accessing data from a specific object and variable in the Results
file hinges on knowing the relevant column index. Similarly, accessing data for a particular time
requires the row number for the relevant time interval.
5.3
Adding a Results file to a Python script does not enable access to the data contained within it.
You must first load the results file into memory using the command:
app.LoadResData(ResultsFile)
LoadResData loads the contents of a Results file into memory and allows you to begin accessing the data. You can only load one Results file into memory at any one time.
31
5.4
In order to access the object and variable of interest, you need to know the right column number
in the Results file. To do this, use the following command to search for the relevant column
number:
app.ResGetIndex(Result File, Object, Variable Name)
ResIndex returns an integer, which is the column number for the object and variable you have
searched for. Object is the specific PowerFactory object of interest (which can be defined explicitly or by a general selection). Variable Name is the variable of interest (e.g. m:u1, s:speed,
etc)
5.5
Once you know the relevant column index (object / variable) and row index (time), you can start
getting data from the Results file. Data points can only be accessed one at a time (i.e. you can
not get a vector of data from the Results file). Use the following command to get a data point:
app.ResGetData(Result File, row index, column index)
The row and column indices are integers.
5.6
To find the number of time intervals in the simulation (i.e. number of rows), use the command:
app.ResGetValueCount(Result File, column index)
The ResGetValueCount function returns an integer with the number of time intervals for a specific column. Using Column index = 0 gives the total number of rows.
Similar function ResGetVariableCount returns number of variables stored in Result File
app.ResGetVariableCount(Result File)
5.7
A Simple Example
This example opens a Results file, prints number of rows and columns of it, and all values for
m:Ikks:Z:bus1 variable of the an object. Note that in the example below, result file Result has
been added into the Python script.
import powerfactory
app=powerfactory.GetApplication()
#Get Result file ElmRes
script=app.GetCurrentScript()
res=script.GetContents(Results.ElmRes)
res=res[0][0]
#Loading of Result file
app.ResLoadData(res)
32
33
6.1
Introduction
Virtual instrument (VI) panels are contained in SetVipage objects within a graphics board, and
are used to visualise the results of dynamic simulations for relevant variables of interest.
This document provides some detailed instructions on manipulating virtual instrument panel
objects using the Python scripting language. Firstly some general definitions for the objects
related to virtual instrument panels:
Graphics Bord - is the container for all graphics, including the VI panels
VI Panel - is the name of the whole virtual instrument page (*.setVIpage)
Visplots - are the individual plots inside a VI panel (*.VisPlot)
6.2
Title blocks are SetTitm objects that can be attached to VI graphical objects. The title blocks
provide drawing information, revision numbers, dates and logos and is therefore primarily used
for printouts of VI graphics. One can manipulate the data in title blocks using Python, which
makes automation possible for a large number of similarly themed drawings.
6.2.1
By default, a global title block is applied to each VI panel with common title block information
(but with different page numbers). But sometimes you may want to have different title block
Python Tutorial (DIgSILENT Technical Documentation)
34
information for each VI page. Local title blocks can be created with information specific to the
individual VI panel.
You can create local title blocks manually by right-clicking on the default title block and selected
Create local Title from the context menu (see screenshot below).
6.2.2
Creating local title blocks manually can be tedious if you have to do it for many VI panels. A
faster way is to use a Python script. However there is not straightforward way of creating local
title block objects via a Python script. Instead, the simplest way is to copy a template title block
into a VI panel object.
First, find the template title block and add it as an external object to the Python command
object. The template title block can be any title block in the graphics board. In the example
below, the default global title block for the graphics board is used as the template (which can be
found in the main graphics board object).
Next, get the VI panel object (*.SetVipage) and use the general object method AddCopy to
copy the title block template into the object. This creates a local title block for the VI panel.
Python Tutorial (DIgSILENT Technical Documentation)
35
You can now fill in the title block information by getting the title block object (*.SetTitm) and
accessing its variables. For example, if the title block object is oTitle, then you can change
the annex, title 1 and title 2 by accessing the variables oTitle:annex, oTitle:sub1z and
oTitle:sub2z respectively.
The variable names for each title block field is shown below:
6.2.3
This Python script gets the first graphics board and cycles through each VI panel. The script
then checks to see if it has a local title block and adds one if it does not. Lastly, the script fills
in the title block information. In this example, the object of the class SetTitm (title block) will be
created with methond CreateObject().
import powerfactory
app=powerfactory.GetApplication()
#Get the graphic board
oCase=app.GetActiveStudyCase()
allDesks=oCase.GetContents(*.SetDesktop)
app.PrintPlain(allDesks)
#Get a list of all VI panels
pgs=allDesks[0][0].GetContents(*.SetVipage)
#go throught each VI panel
for pg in pgs[0]:
app.PrintPlain(Name of object: + pg.loc_name)
#get the first local title block
allTitms=pg.GetContents(*.SetTitm)
app.PrintPlain(allTitms)
#If no local title block available create one
if not allTitms[0] :
36
IMPORTANT NOTE: Objects cannot be created into a VI panel object while the graphic is open.
Therefore, close the graphics board prior to executing any Python scripts that will manipulate
title block objects.
6.3
Often you will want to send VI panels as a picture file or insert it into a report. Obviously, you
could do this manually using the export command (i.e. to a WMF or a BMP):
But this can be a tedious task if there are many VI panels to export. A quicker alternative is
to use a Python script to bulk export VI panels or any other type of graphic (this was covered
briefly in Section 4.2.2). The general process is as follows:
Locate the relevant graphics board
Select the VI panels or graphic object that you want to export
Export the VI panel with the WriteWMF function
The following example gets the first graphic board in the active study case and exports all of the
VI panels in the graphics board as ViPanel.loc name.wmf in the directory File name:
import powerfactory
app=powerfactory.GetApplication()
#Get the graphic board
oCase=app.GetActiveStudyCase()
allDesks=oCase.GetContents(*.SetDesktop)
app.PrintPlain(allDesks)
37
38
7
7.1
On single line diagrams, graphical representations of network elements, text objects and other
graphics (e.g. rectangles, circles, etc) are stored Graphical Net Objects (*.IntGrf) inside diagram graphics (*.IntGrfnet), which are in turn located in the Network Model / Diagrams subfolder.
The figure below presents the contents of diagram graphic Grid, showing a number of graphical net objects stored inside the diagram:
If we were to edit a Graphical Net Object (GNO), we would see the following:
The Net Data Object field (variable name pDataObj) highlighted in red indicates that this GNO
is associated with grid element Load1, which simply means that this is a graphical representation of a network element. There can be more than one graphical representation of the
same object across many diagrams, though not in a single diagram. When the GNO does not
represent a grid element (e.g. it is just a rectangle, circle, etc), the Net Data Object field is blank.
The Symbol Name field (variable name pSymNam) defines the graphical symbol for this GNO,
in this case a load symbol.
39
The X-Position and Y-Position fields(variable names rCenterX and rCenterY respectively)
specifies the (x,y) coordinates in the diagram where the symbol should be drawn (centre points).
There is another type of graphical object that defines the connections between two objects
(e.g. a load connected to a bus). This object is called a Graphical Connection Object (*.IntGrfcon) and can typically be found inside a GNO:
Editing the first Graphical Connection Object (GCO), we get the dialog box on the following
page:
The GCO specifies the (x, y) coordinates for straight-line connections between the GNO (e.g. a
Python Tutorial (DIgSILENT Technical Documentation)
40
load) and its connected element (e.g. a bus). In the example above, the GCO shows a simple
vertical connection with endpoint (x, y) coordinates (96.25, 100.625) and (96.25, 113.75).
This brief background was intended to describe the nature of graphical objects and how they
are used in PowerFactory . By understanding the concepts of GNOs and GCOs, we can start
using Python to manipulate graphical objects.
7.2
As with other Python applications, the easiest way to create a graphical object is by copying a
template object. As the configuration of the graphical objects will be largely dependent on the
specific application, only a general process for creating graphical objects is presented here.
Create template graphical net object (GNO), complete with graphical connection object
(GCO) stored within. Make sure the template objects are accessible by the Python script
either as internally or externally referenced object (see section 3.3)
Find the diagram object (*.IntGrfnet) where you want to create the graphical objects
Find or create the network element with which you want to associate the graphical object
Copy the template GNO into the selected diagram object (with the AddCopy function)
Get the newly created GNO and modify the following (as required):
Associated network element (GNO:pDataObj)
Graphical symbol (GNO:pSymNam)
X- and Y- coordinates for object (GNO:rCenterX and GNO:rCenterY)
Access the associated GCO and modify the X- and Y- coordinates for the connections
(GCO:rX and GCO:rY)
41