Skip to content

Commit

Permalink
Clean up errors if SimAuto is not installed. Change some formatting. …
Browse files Browse the repository at this point in the history
…Change return data to True if an operation was performed without error and to False if an operation was performed with error.
  • Loading branch information
jessemarkboyd committed Jul 13, 2018
1 parent 29fcb38 commit a1822be
Showing 1 changed file with 113 additions and 84 deletions.
197 changes: 113 additions & 84 deletions pypowerworld/pypowerworld.py
Original file line number Diff line number Diff line change
@@ -1,173 +1,202 @@
#####################################################################
""""#####################################################################
# POWERWORLD INTERFACE FILE #
# This file defines a class object for interfacing with PW. It is #
# instantized by a path to a Power World Binary (pwb) file. The #
# instance methods will be performed on that pwb file. The file may #
# be changed ad hoc. #
#####################################################################

# be changed ad hoc by the opencase method. #
#####################################################################"""

import pandas as pd
import numpy as np
import os.path
import os
import win32com
from win32com.client import VARIANT
import pythoncom

class pypowerworld:
def __init__(self,fullfilepath=None):
self.__pwcom__ = win32com.client.Dispatch('pwrworld.SimulatorAuto')
if fullfilepath == None:
fullfilepath = input('Please enter full pwb file path:')
self.fullfilepath = fullfilepath
self.filefolder = os.path.split(self.fullfilepath)[0]
self.filename = os.path.splitext(os.path.split(self.fullfilepath)[1])[0]
self.auxfilepath = self.filefolder + '/' + self.filename + '.aux'

class PyPowerWorld(object):
"""Class object designed for easy interface with PowerWorld."""
def __init__(self, pwb_file_path=None):
try:
self.__pwcom__ = win32com.client.Dispatch('pwrworld.SimulatorAuto')
except Exception as e:
print(str(e))
print("Unable to launch SimAuto.",
"Please confirm that your PowerWorld license includes the SimAuto add-on ",
"and that SimAuto has been successfuly installed.")
self.pwb_file_path = pwb_file_path
self.__setfilenames__()
self.output = ''
self.error = False
self.errormessage = ''
#self.opencase()

self.error_message = ''
self.COMout = ''
self.opencase()

def __setfilenames__(self):
self.file_folder = os.path.split(self.pwb_file_path)[0]
self.file_name = os.path.splitext(os.path.split(self.pwb_file_path)[1])[0]
self.aux_file_path = self.file_folder + '/' + self.file_name + '.aux' # some operations require an aux file
self.save_file_path = os.path.splitext(os.path.split(self.pwb_file_path)[1])[0]

def __pwerr__(self):
if self.COMout is None:
self.output = None
self.error = False
self.errormessage = ''
self.error_message = ''
elif self.COMout[0] == '':
self.output = None
self.error = False
self.errormessage = ''
self.error_message = ''
elif 'No data' in self.COMout[0]:
self.output = None
self.error = False
self.errormessage = self.COMout[0]
self.error_message = self.COMout[0]
else:
self.output = self.COMout[-1]
self.error = True
self.errormessage = self.COMout[0]
self.error_message = self.COMout[0]
return self.error

def opencase(self):
# Opens case defined by the full file path; if this are undefined, opens by previous file path
if self.fullfilepath is None:
self.__init__()
def opencase(self, pwb_file_path=None):
"""Opens case defined by the full file path; if this is undefined, opens by previous file path"""
if pwb_file_path is None and self.pwb_file_path is None:
pwb_file_path = input('Enter full pwb file path > ')
if pwb_file_path:
self.pwb_file_path = os.path.splitext(pwb_file_path)[0] + '.pwb'
else:
self.COMout = self.__pwcom__.OpenCase(self.filefolder + '/' + self.filename + '.pwb')
self.COMout = self.__pwcom__.OpenCase(self.file_folder + '/' + self.file_name + '.pwb')
if self.__pwerr__():
print('Error opening case:\n\n%s\n\n', self.errormessage)
print('Error opening case:\n\n%s\n\n', self.error_message)
print('Please check the file name and path and try again (using the opencase method)\n')
return False
return True

def savecase(self):
# Saves case with changes to existing file name and path
self.COMout = self.__pwcom__.SaveCase(self.filefolder + '/' + self.filename + '.pwb','PWB', 1)
"""Saves case with changes to existing file name and path."""
self.COMout = self.__pwcom__.SaveCase(self.pwb_file_path, 'PWB', 1)
if self.__pwerr__():
print('Error saving case:\n\n%s\n\n', self.errormessage)
print('Error saving case:\n\n%s\n\n', self.error_message)
print('******CASE NOT SAVED!******\n\n')
return False
return True

def savecaseas(self, fullfilepath=None):
# If file name and path are specified, saves case as a new file. Overwrites any existing file with the same name and path
if fullfilepath is not None:
self.filefolder = os.path.split(fullfilepath)[0]
self.savefilename = os.path.splitext(os.path.split(fullfilepath)[1])[0]
self.auxfilepath = self.filefolder + '/' + self.savefilename + '.aux'
self.savecase()
def savecaseas(self, pwb_file_path=None):
"""If file name and path are specified, saves case as a new file.
Overwrites any existing file with the same name and path."""
if pwb_file_path is not None:
self.pwb_file_path = os.path.splitext(pwb_file_path)[1] + '.pwb'
self.__setfilenames__()
return self.savecase()

def savecaseasaux(self, FileName=None, FilterName='', ObjectType=None, ToAppend=True, FieldList='all'):
# If file name and path are specified, saves case as a new aux file. Overwrites any existing file with the same name and path
if FileName==None:
FileName=self.filefolder + '/' + self.filename + '.aux'

self.filefolder = os.path.split(FileName)[0]
self.savefilename = os.path.splitext(os.path.split(FileName)[1])[0]
self.auxfilepath = self.filefolder + '/' + self.savefilename + '.aux'
self.COMout = self.__pwcom__.WriteAuxFile(self.auxfilepath,FilterName,ObjectType,ToAppend,FieldList)
def savecaseasaux(self, file_name=None, FilterName='', ObjectType=None, ToAppend=True, FieldList='all'):
"""If file name and path are specified, saves case as a new aux file.
Overwrites any existing file with the same name and path."""
if file_name is None:
file_name = self.file_folder + '/' + self.file_name + '.aux'
self.file_folder = os.path.split(file_name)[0]
self.save_file_path = os.path.splitext(os.path.split(file_name)[1])[0]
self.aux_file_path = self.file_folder + '/' + self.save_file_path + '.aux'
self.COMout = self.__pwcom__.WriteAuxFile(self.aux_file_path,FilterName,ObjectType,ToAppend,FieldList)
if self.__pwerr__():
print('Error saving case:\n\n%s\n\n', self.errormessage)
print('Error saving case:\n\n%s\n\n', self.error_message)
print('******CASE NOT SAVED!******\n\n')
return False
return True

def closecase(self):
# Closes case without saving changes
"""Closes case without saving changes."""
self.COMout = self.__pwcom__.CloseCase()
if self.__pwerr__():
print('Error closing case:\n\n%s\n\n', self.errormessage)
print('Error closing case:\n\n%s\n\n', self.error_message)
return False
return True

def runscriptcommand(self,scriptcommand):
# Input a script command as in an Auxiliary file SCRIPT{} statement or the PowerWorld Script command prompt
self.COMout = self.__pwcom__.RunScriptCommand(scriptcommand)
def runscriptcommand(self,script_command):
"""Input a script command as in an Auxiliary file SCRIPT{} statement or the PowerWorld Script command prompt."""
self.COMout = self.__pwcom__.RunScriptCommand(script_command)
if self.__pwerr__():
print('Error encountered with script:\n\n%s\n\n', self.errormessage)
print('Script command which was attempted:\n\n%s\n\n', scriptcommand)
print('Error encountered with script:\n\n%s\n\n', self.error_message)
print('Script command which was attempted:\n\n%s\n\n', script_command)
return False
return True

def loadauxfiletext(self,auxtext):
# Creates and loads an Auxiliary file with the text specified in auxtext parameter
f = open(self.auxfilepath, 'w')
"""Creates and loads an Auxiliary file with the text specified in auxtext parameter."""
f = open(self.aux_file_path, 'w')
f.writelines(auxtext)
f.close()
self.COMout = self.__pwcom__.ProcessAuxFile(self.auxfilepath)
self.COMout = self.__pwcom__.ProcessAuxFile(self.aux_file_path)
if self.__pwerr__():
print('Error running auxiliary text:\n\n%s\n', self.errormessage)
print('Error running auxiliary text:\n\n%s\n', self.error_message)
return False
return True

def getparameterssingleelement(self, element_type = 'BUS', field_list = ['BusName', 'BusNum'], value_list = [0, 1]):
# Retrieves parameter data accourding to the fields specified in field_list.
# value_list consists of identifying parameter values and zeroes and should be the same length as field_list
"""Retrieves parameter data according to the fields specified in field_list.
value_list consists of identifying parameter values and zeroes and should be
the same length as field_list"""
assert len(field_list) == len(value_list)
field_array = VARIANT(pythoncom.VT_VARIANT | pythoncom.VT_ARRAY, field_list)
value_array = VARIANT(pythoncom.VT_VARIANT | pythoncom.VT_ARRAY, value_list)
self.COMout = self.__pwcom__.GetParametersSingleElement(element_type, field_array, value_array)
if self.__pwerr__():
print('Error retrieving single element parameters:\n\n%s', self.errormessage)
elif self.errormessage != '':
print(self.errormessage)
print('Error retrieving single element parameters:\n\n%s', self.error_message)
elif self.error_message != '':
print(self.error_message)
elif self.__pwcom__.output is not None:
df = pd.DataFrame(np.array(self.__pwcom__.output[1]).transpose(),columns=field_list)
df = df.replace('',np.nan,regex=True)
return df
return None

def getparametersmultipleelement(self, elementtype, fieldlist, filtername = ''):
fieldarray = VARIANT(pythoncom.VT_VARIANT | pythoncom.VT_ARRAY, fieldlist)
self.COMout = self.__pwcom__.GetParametersMultipleElement(elementtype, fieldarray, filtername)
if self.__pwerr__():
print('Error retrieving single element parameters:\n\n%s\n\n', self.errormessage)
elif self.errormessage != '':
print(self.errormessage)
print('Error retrieving single element parameters:\n\n%s\n\n', self.error_message)
elif self.error_message != '':
print(self.error_message)
elif self.__pwcom__.output is not None:
df = pd.DataFrame(np.array(self.__pwcom__.output[1]).transpose(),columns=fieldlist)
df = df.replace('',np.nan,regex=True)
df = pd.DataFrame(np.array(self.__pwcom__.output[1]).transpose(), columns=fieldlist)
df = df.replace('', np.nan, regex=True)
return df
return None

def get3PBfaultcurrent(self, busnum):
# Calculates the three phase fault; this can be done even with cases which
# only contain positive sequence impedances
scriptcmd = ('Fault([BUS {}], 3PB);\n'.format(busnum))
"""Calculates the three phase fault; this can be done even with cases which
only contain positive sequence impedances"""
scriptcmd = f'Fault([BUS {busnum}], 3PB);\n'
self.COMout = self.run_script(scriptcmd)
if self.__pwerr__():
print('Error running 3PB fault:\n\n%s\n\n', self.errormessage)
print('Error running 3PB fault:\n\n%s\n\n', self.error_message)
return None
fieldlist = ['BusNum','FaultCurMag']
fieldlist = ['BusNum', 'FaultCurMag']
return self.getparameterssingleelement('BUS', fieldlist, [busnum, 0])

def createfilter(self, condition, objecttype, filtername, filterlogic='AND', filterpre='NO', enabled='YES'):
# this function creates a filter in PowerWorld. The attempt is to reduce the clunkiness of
# creating a filter in the API, which entails creating an aux data file
auxtext = """
"""Creates a filter in PowerWorld. The attempt is to reduce the clunkiness of
# creating a filter in the API, which entails creating an aux data file"""
auxtext = '''
DATA (FILTER, [ObjectType,FilterName,FilterLogic,FilterPre,Enabled])
{
"{}" "{}" "{}" "{}" "YES"
"{objecttype}" "{filtername}" "{filterlogic}" "{filterpre}" "{enabled]"
<SUBDATA Condition>
{}
{condition}
</SUBDATA>
}""".format(objecttype, filtername, filterlogic, filterpre, enabled, condition)
}'''.format(condition=condition, objecttype=objecttype, filtername=filtername, filterlogic=filterlogic,
filterpre=filterpre, enabled=enabled)
self.COMout = self.__pwcom__.load_aux(auxtext)
if self.__pwcom__.error:
print('Error creating filter %s:\n\n' % (filtername,self.__pwcom__.errormessage))
return None
print('Error creating filter %s:\n\n%s' % (filtername,self.__pwcom__.error_message))
return False
return True

def exit(self):
# Clean up for the PowerWorld COM object
"""Clean up for the PowerWorld COM object"""
self.closecase()
del self.__pwcom__
self.__pwcom__ = None
return None

def __del__(self):
self.exit()

0 comments on commit a1822be

Please sign in to comment.