Objects Service¶
The WindPro ObjectsService provides access to functionality related to objects in windPRO. The ObjectService allows for manipulating general properties of objects as well as object layers. Each object has an object type in windPRO scripting that allows to e.g. generate an object of this type or get a list of all objects of that type present in the project. Some objects have additional scripting services that allow access to more specialized functionality and properties of these objects. The table below gives a list of all object types in windPRO scripting and a link to the dedicated service if available.
Object type |
Description |
Scripting Service |
---|---|---|
AreaObj |
Area object |
|
BusBar |
not available |
|
Camera |
not available |
|
CtrlPoint |
Control point |
|
EGrid |
EGrid obejct |
not available |
ELoad |
not available |
|
ExtGrid |
not available |
|
ExistWTG |
Existing ETG |
|
HCData |
Line data |
|
HCGridObj |
Height contour grid |
|
MeteoObjectData |
Meteo object |
|
NewWTG |
New WTG |
|
NSA |
Noise Receptor or area |
|
Obj3DData |
not available |
|
Obstacle |
Obstacle object |
|
Polygons |
not available |
|
Profile |
not available |
|
RadarObject |
Radar |
|
RoadObject |
Road obejct |
not available |
ResultLayerObject |
Result Layers |
not available |
Ruler |
Ruler for measuring |
|
Shadow |
Shadow receptor |
|
SolarPvObject |
Solar PV object |
not available |
Shape |
Shape |
not available |
SiteCenter |
Site center |
not available |
SiteData |
Site data object |
|
Transformer |
not available |
|
Unknown |
Not known type |
not available |
UsrTextData |
Text box |
|
VR |
not available |
|
VRCamera |
not available |
|
WTGareas |
WTG area |
|
WTGnet |
not available |
In the following a few examples are given on how to use the the ObjectsService
To use, create, and edit objects and layers in windPRO with a python script you need to make an instance of the service for objects.
It is done with windproapi.get_service()
, which takes in the type of service as a parameter.
The code below is an example of the setup needed to use the windproapi.
import os
from windproapi.utils import get_windpro_sample_path
from windproapi import WindProApi
_windproapi = WindProApi()
_windproapi.start_windpro_random_port()
objects_service = _windproapi.get_service('ObjectsService')
Manipulate Objects¶
With GetObjectTypes
you get a list of all the object types in windPRO, and with GetObjectCount
you get the number of objects in your project.
The code below shows an example of the method.
project_service = _windproapi.get_service('ProjectService')
working_dir = os.path.join(get_windpro_sample_path("3.6"), 'New Salem\\3.5')
project_path = os.path.join(working_dir, 'New Salem.w35p')
project_service.LoadFromFile(project_path)
# objTypes stores a list of object types
objTypes = objects_service.GetObjectTypes()
# objCount stores the number of objects
objCount = objects_service.GetObjectCount()
GetObject
returns an object as a dictionary with it’s properties, it takes the index of the obejct as a parameter.
Like GetObject
, GetObjectFromHandle
also returns an object a dictionary but takes in the handle of the object as a parameter.
Getting objects by handle is recommended, as the handle will not change if objects are added or deleted.
You can assign properties directly using “.” and then you can apply the changes with SetObjectPropsFromHandle
, where you overwrite the object.
The code below shows an example on these methods as well as an example of a windPRO object in python.
# GetObject() stores information about and object as a dictionary
obj = objects_service.GetObject(1)
# result of obj
"""
{
'Handle': 390762937,
'TypeId': 'NewWTG',
'ObjType': 0,
'ApiObjType': 'NewWTG',
'Lng': -101.406510917218,
'Lat': 46.7555215047512,
'Z': 700.0,
'Count': 1,
'Angle': 0.0,
'UserDescription': 'T24',
'AutoLevel': True,
'OffsetZ': 0.0,
'UserLabel': 'T24',
'SymbolVisible': True
}
"""
# GetObjectFromHandle() stores information about and object as a dictionary
objFromHandle = objects_service.GetObjectFromHandle(Handle)
# Make some changes to the object before applying them with SetObjectPropsFromHandle()
obj.Lng = -101.40
obj.Lat = 46.75
# SetObjectPropsFromHandle() set the properties in the object given as a parameter and returns it with the new information.
obj = objects_service.SetObjectPropsFromHandle(obj)
# GetObjects() returns all objects of a specific type
objects_service.GetObjects('NewWTG')
Often it is needed to get objects of a specific type.
You can also get a list of all objects of a specific type with GetObjects
which takes the object type as a parameter.
All objects types are available from GetObjectTypes
.
# objTypes stores a list of object types
objTypes = objects_service.GetObjectTypes()
print(objTypes)
# Getting all turbines that are in the project. NewWTG in contrast to ExistWTG
new_wtgs_objs = objects_service.GetObjects("NewWTG")
Interaction with windPRO scripting are kept to a relatively basic level for getting object. Getting objects by index can be useful if it is necessary to loop through all objects in the project. Getting objects by handle ensures that this is the exact object that was intended. Often it is necessary to find a specific object from this list of objects, e.g, from its Description in windPRO. With scripting functionality like this can be easily made within the scripting language.
# Getting all turbines that are in the project. NewWTG in contrast to ExistWTG
new_wtgs_objs = objects_service.GetObjects("NewWTG")
# Defining function that loops through a
def get_obj_from_list_by_user_description(objs, user_description):
l_obj = []
for o in objs:
if o["UserDescription"] == user_description:
l_obj.append(o)
if len(l_obj) == 1:
return l_obj[0]
elif len(l_obj) == 0:
raise ValueError(f"Could not find {user_description} in any UserDescription.")
else:
raise ValueError(f"More than one variable UserDescription {user_description}.")
obj_T24 = get_obj_from_list_by_user_description(new_wtgs_objs, "T24")
You can add, save, load, delete, and clone an object using the methods shown below.
With AddObject
you need to give a type, latitude, longitude, and a name of the object.
SaveObject
needs the handle of the object you want to save and the path where you want to save it.
LoadObject
need the path of the file you want to load.
DeleteObject
and CloneObject
need the handle of the object you want to alter.
The code below is an example of these methods.
# AddObject(type, lat, lon, name) adds a new object of a specific type with a name and placed on parsed coordinates.
objects_service.AddObject('NewWTG', 46.75, -101.40, 'New WTG obj')
# CloneObject(handle) copies an object and returns the properties as a dictionary
cloneObj = objects_service.CloneObject(Handle)
# SaveObject(int handle, string path) saves an object to a file and returns true on succes
saveObj = objects_service.SaveObject(Handle, filePath)
# DeleteObject(int handle) deletes an object
objects_service.DeleteObject(Handle)
# LoadObject() loads an object from a file and returns true on succes
loadObj = objects_service.LoadObject(filePath)
Manipulate layers¶
You can get basic information about layers from the ObjectService. It is possible to get the number of layers and the handle of that layer by index. The name of the layer is connected via the layer handle.
# return the count of all layers
layerCount = objects_service.GetLayerCount()
# returns the handle of the layer with the count given
layerHandle = objects_service.GetLayerHandle(1)
# returns the name of the layer by handle
layerName = objects_service.GetLayerName(layerHandle)
You can add, rename, and delete layers simple by following the example shown below. AddLayer returns a handle that can be used to modify this layer. Adding layers requires the handle of the parent folder. If the layer is not supposed to be in a sub folder you need to indicate this by using a 0.
# Adds a layer with a given name and returns the handle
layer = objects_service.AddLayer('newlayer', 0)
# Renames a layer with the handle stored in the layer variable
objects_service.RenameLayer(layer, 'RenamedLayer')
# Deletes layer from handle
objects_service.DeleteLayer(layer)
You can get the current layer in editmode and change it to another layer with the example shown below.
# returns the current edit layer
editLayer = objects_service.GetEditLayer()
# set a layer to edit layer with a handle
objects_service.SetEditLayer(layerHandle)
Layers are like a folder structure but the output from windPRO is a flat list where layers are linked to their parent folder by handle. Transforming the existing layer structure into a dictionary in python is possible with the function get_layer_dict provided in the python package. Be aware that layer folder names need to be unique for this function to work properly.
A full running example showing the presented features is given below. You need the sample project New Salem to execute the script.
Result Layers¶
Result layers are also handles as objects in windPRO. They have a location, even though they are not shown on the windPRO GUI. A good way is to choose the location of the site center for all result layers. Manually adding result layers is necessary for some calculations to display the result in windPRO.
import windproapi.windproapi
import time
import os
from pprint import pprint
from windproapi.utils import get_windpro_sample_path
from windproapi.windproapi import get_layer_dict
from windproapi import WindProApi
# Opening windPRO
_windproapi = WindProApi()
working_dir = os.path.join(get_windpro_sample_path('3.6'), 'New Salem\\3.6')
project_path = os.path.join(working_dir, 'New Salem.w36p')
_windproapi.start_windpro_random_port()
# Services
project_service = _windproapi.get_service('ProjectService')
objects_service = _windproapi.get_service('ObjectsService')
# Open project
project_service.LoadFromFile(filename=project_path)
# Getting all objects that could be included in windPRO
print(objects_service.GetObjectTypes())
for s in objects_service.GetObjectTypes():
print(f'{s}')
# Getting all turbines that are in the project. NewWTG in contrast to ExistWTG
new_wtgs_objs = objects_service.GetObjects(apiObjType='NewWTG')
# Getting information by handle
handle = new_wtgs_objs[0].Handle
obj = objects_service.GetObjectFromHandle(handle=handle)
# Defining function that loops through the output from objects_service.GetObjects to get an object back by its
# user description
def get_obj_from_list_by_user_description(objs, user_description):
l_obj = []
for o in objs:
if o['UserDescription'] == user_description:
l_obj.append(o)
if len(l_obj) == 1:
return l_obj[0]
elif len(l_obj) == 0:
raise ValueError(f'Could not find {user_description} in any UserDescription.')
else:
raise ValueError(f'More than one variable UserDescription {user_description}.')
obj_T24 = get_obj_from_list_by_user_description(new_wtgs_objs, 'T24')
print(obj_T24)
# Make some changes to the object before applying them with SetObjectPropsFromHandle()
# This changes the location of the object
obj.Lng = -101.40
obj.Lat = 46.75
obj.UserLabel = 'T24_new_location'
# in principle se can also change some other not so useful properties like the color
obj.Color.Red = 10
obj.Color.Green = 153
obj.Color.Blue = 25
# SetObjectPropsFromHandle() set the properties in the object given as a parameter and returns it with the new
# information.
obj = objects_service.SetObjectPropsFromHandle(inObj=obj)
# WindPRO layers.
# Get information which layers are in the project.
layer_dict, layer_directories_dict = get_layer_dict(objects_service)
print('Layer names and handles')
pprint(layer_dict)
print('Layer folder names and handles')
pprint(layer_directories_dict)
# Adding new layers to the layer structure
# Adding a new layer. 0 is the base layer, so it is not placed in any folder
objects_service.AddLayer(layerName='New Layer Script Added', parentFolderHandle=0)
# Adding a new layer folder. 0 is the base layer, so the folder is visible in the base layer sturcture.
objects_service.AddLayerFolder(folderName='New layer folder', parentFolderHandle=0)
# Loading layers and layer directories again
layer_dict, layer_directories_dict = get_layer_dict(objects_service)
# Adding layer in the newly generated layer folder by name
objects_service.AddLayer(layerName='New layer in folder script added',
parentFolderHandle=layer_directories_dict['New layer folder'])
# set a layer to edit layer with a handle
objects_service.SetEditLayer(handle=layer_dict["WTG\\WTG's"])
# Making new objects
# AddObject(type, lat, lon, name) adds a new object of a specific type with a name and placed on parsed coordinates.
# To make the object usable in windPRO it needs additional properties set in its specific service.
new_obj = objects_service.AddObject(apiObjType='NewWTG',
lat=46.75,
lng=-101.40,
userDesc='New WTG obj')
handle = new_obj.Handle
# CloneObject(handle) copies an object and returns the properties as a dictionary
clone_obj = objects_service.CloneObject(handle)
# SaveObject(int handle, string path) saves an object to a file and returns true on success
file_path = os.path.join(working_dir, 'turbine.wpobjects')
objects_service.SaveObject(handle=handle, filename=file_path)
# DeleteObject(int handle) deletes an object
objects_service.DeleteObject(handle=handle)
# LoadObject() loads an object from a file and returns true on success
loadObj = objects_service.LoadObject(filename=file_path)