- Goal
This example has two parts: the Python entry and the Property Provider entry.
Python: This part of the script retrieves all Python Code object properties and writes them to the ds.dat file as comments.
Property Provider: The code contained in the Property Provider tab defines property definitions. The example below creates properties that are similar to what you would see in a Force object.
- Python Code
""" To insert commands just prior to the Ansys SOLVE command, use solver_input_file.WriteLine("!Your command") Global Helpers: this -- the datamodel object instance of the python code object you are currently editing in the tree solver_input_file -- file stream that allows you to inject commands into the solver input file solver_data -- data stucture that allows you to access information from the model such as current step, contact pair ids, etc. """ # To access properties created using the Property Provider, please use the following command. # this.GetCustomPropertyByPath("your_property_group_name/your_property_name") # To access scoping properties use the following to access geometry scoping and named selection respectively: # this.GetCustomPropertyByPath("your_property_group_name/your_property_name/Geometry Selection") # this.GetCustomPropertyByPath("your_property_group_name/your_property_name/Named Selection") properties = this.PropertyProvider.GetProperties() for prop in properties: line = "!" + prop.Name + " " + prop.ValueString solver_input_file.WriteLine(line)
- Property Provider Code
def reload_props(): this.PropertyProvider = None # comment the return below to allow the rest of the function definition to be executed and add properties return #Create a new PropertyProvider Instance called Force Force = Provider() #Add a new group to called Definition2 to Force Definition = Force.AddGroup("Definition2") #Add an Expression property "Type" to the Definition2 group and set its value = "Force" type = Definition.AddProperty("Type", Control.Expression ) type.Value = "Force" #Create an instance of the custom ForceProperty that was created above and add it to the Definition2 group force_prop = Definition.AddProperty("Force Property", "Force") #Add an Options property "Applied By" Options property applied_by = Definition.AddProperty("Applied By", Control.Options) applied_by.Options = {0:"Surface Effect", 1:"Direct"} applied_by.Value = 0 #Add Options property "Suppressed" Options property suppressed = Definition.AddProperty("Suppressed", Control.Options) suppressed.Options = {0:"Yes", 1:"No"} suppressed.Value = 1 #Add a new group called "Scope" to Force Scope = Force.AddGroup("Scope") #Add a Scoping Property to the Scope group scoping_prop = Scope.AddProperty("Scoping Property", "Scoping", "property_templates") #Connects the provider instance back to the object by setting the PropertyProvider member on this, 'this' being the #current instance of the Python Code object. this.PropertyProvider = Force #region Property Provider Template from Ansys.ACT.Mechanical.AdditionalProperties import PropertyProviderAdapter from Ansys.ACT.Mechanical.AdditionalProperties import * """ The property_templates module is located in {YOUR_INSTALL_DIR}/DesignSpace/DSPages/Python/mech_templates """ from mech_templates import property_templates property_templates.set_ext_api(ExtAPI) class Provider(Ansys.ACT.Interfaces.Mechanical.IPropertyProvider): """ Provider template that implements IPropertyProvider to demonstrate the usage of IPropertyProvider. It provides helper methods and classes that manage properties that can be dynamicall added to an object. """ # region These are callbacks that as a user you may want to modify to get specific behavior def IsValid(self, prop): """ Called when checking the validity of a property, with the property instance. """ # for double property use the ValidRange property to check validity if(isinstance(prop, DoubleProperty)): return prop.ValidRange[0] <= prop.Value and prop.ValidRange[1] >= prop.Value return True def IsReadOnly(self, prop): """ Called when checking if a property should be readonly, with the property instance. """ return False def IsVisible(self, prop): """ Called when checking if a property should be visible, with the property instance. """ return True def SetValue(self, prop, val): """ Allows you to override the setter of the Value property on the property instance. Keyword Arguments: prop -- property of which the value is being set val -- the value that was set Returns: The value that the Value property should be set to """ return val def GetValue(self, prop, val): """ Allows you to override the getter of the Value property on the property instance. Keyword Arguments: prop -- property of which the value is being set val -- current value of the Value property Returns: The value that the getter on the internal value should return """ return val # endregion #structures that hold property instances prop_list = [] prop_map = {} prop_groups = set() class AnsGroup(): """Helper group class to group properties, and provides methods to add properties to groups.""" provider = None def __init__(self,name=None, provider=None): self.name = name self.provider = provider def __AddScopingProperty(self, name): """ Adds a scoping property with a given name to this group. Keyword Arguments : name -- unique name for the scoping property """ scoping_prop = property_templates.ScopingProperty(name, self.name) for prop in scoping_prop.GetGroupedProps(): self.provider.AddProperty(prop) return scoping_prop.GetGroupedProps() def __AddForceProperty(self, name): """ Adds a Force property with a given name to this group. Keyword Arguments : name -- unique name for the force property """ force_prop = ForceProperty(name, self.name) for prop in force_prop.GetGroupedProps(): self.provider.AddProperty(prop) return force_prop.GetGroupedProps() def AddProperty(self, name=None, prop_control=None, module_name=None): """ Creates an instance of the property and connects delgates in the associated Property Propvider. Keyword Arguments : name -- unique name for the scoping property prop_control -- one of the built in controls, or extended controls module_name -- module where the control is defined """ #special case for scoping property if(prop_control == "Scoping" and module_name == "property_templates"): return self.__AddScopingProperty(name) #special case for Force property if(prop_control == "Force"): return self.__AddForceProperty(name) #if no module_name is passed, use the globals in current module #that has the built in controls imported prop_mod_globals = None if(module_name != None): if(module_name not in globals()): raise Exception("Unknown module : " + module_name) prop_mod_globals = globals()[module_name].get_globals() else: prop_mod_globals = globals() #class name is built based on control + "Property" # Double - > DoubleProperty prop_class_name = str(prop_control) + "Property" if(prop_class_name not in prop_mod_globals): raise Exception("Unknown property class : " + prop_class_name) #instantiate the property based on module and class name prop = prop_mod_globals[prop_class_name](self.name + "/" + name, self.name) if(prop == None): raise Exception("Issue while creating the property instance.") #set the delegates to property provider functions prop.IsValidCallback = self.provider.IsValid prop.IsReadOnlyCallback = self.provider.IsReadOnly prop.IsVisibleCallback = self.provider.IsVisible prop.GetValueCallback = self.provider.GetValue prop.SetValueCallback = self.provider.SetValue #as a default make the property name the property display name prop.DisplayName = name #add property to the provider self.provider.AddProperty(prop) return prop def __init__(self): pass def GetProperties(self): """ Returns a list of properties in the order that they were added to the property provider. """ return [self.prop_map[propName] for propName in self.prop_list] def AddGroup(self, name=None): """ Creates an instance of helper group class and returns it. """ if name in self.prop_groups: raise Exception("Group with name " + name + " already exists, please use a unique group name.") #keep groups names so we can make sure no duplicate groups are added self.prop_groups.add(name) return self.AnsGroup(name, self) def AddProperty(self, prop): """ Method used by the helper group class to add the property to the data-structure holding the property instances. """ if(prop.Name in self.prop_map): raise Exception("Property name must be unique, property with name '" + prop.Name + "' already exisits.") self.prop_list.append(prop.Name) self.prop_map[prop.Name] = prop #end region """ Create a Force like object using PropertyProvider """ class ForceProperty: """ Class to create a custom Force property using a combination of different control types """ grouped_props = [] def __init__(self, name, groupName="Forcing"): #Create a DefineBy property using the OptionsProperty self.def_by_prop = OptionsProperty(name + "/Define By", groupName) self.def_by_prop.Options = {0: "Vector", 1: "Components"} self.def_by_prop.Value = 0 self.def_by_prop.DisplayName = ExtAPI.Application.GetLocalString("ID_ScopingDefineBy") #Create a Magnitude property using DoubleProperty with a valid range. #Override the default IsVisible and IsValid callbacks with the ones defined int this class. self.magnitude = DoubleProperty(name + "/Magnitude", groupName) self.magnitude.Value = 0 self.magnitude.ValidRange = (1.0, 4.0) self.magnitude.DisplayName = ExtAPI.Application.GetLocalString("ID_MagnitudeProperty") self.magnitude.IsVisibleCallback = self.IsVisible self.magnitude.IsValidCallback = self.IsValid #Create a Direction property using GeometetrySelectionProperty from property_templates. #Override the default IsVisible callback with the one defined int this class." self.direction = property_templates.GeometrySelectionProperty(name + "/Direction", groupName) self.direction.DisplayName = ExtAPI.Application.GetLocalString("ID_Direction") self.direction.IsVisibleCallback = self.IsVisible #Create a Coordinate System property using OptionsProperty. #Add an Option and set the value to the first option. #Override the default IsVisible callback with the one defined int this class." self.coordinate_system = OptionsProperty(name + "/Coordinate System", groupName) self.coordinate_system.Options = {0: "Global Coordinate System"} self.coordinate_system.Value = 0 self.coordinate_system.DisplayName = ExtAPI.Application.GetLocalString("ID_Coordinate_System") self.coordinate_system.IsVisibleCallback = self.IsVisible #Create an X Component property using DoubleProperty with a valid range. #Override the default IsVisible and IsValid callbacks with the ones defined int this class. #Allow this property to be parameterized by setting CanParameterize to True. self.x_comp = DoubleProperty(name + "/X Component", groupName) self.x_comp.Value = 0 self.x_comp.ValidRange = (1.0, 4.0) self.x_comp.DisplayName = ExtAPI.Application.GetLocalString("ID_DirectionalXComponent") self.x_comp.IsVisibleCallback = self.IsVisible self.x_comp.CanParameterize = True self.x_comp.IsValidCallback = self.IsValid #Create a Y Component property using DoubleProperty with a valid range. #Override the default IsVisible and IsValid callbacks with the ones defined int this class. #Allow this property to be parameterized by setting CanParameterize to True. self.y_comp = DoubleProperty(name + "/Y Component", groupName) self.y_comp.Value = 0 self.y_comp.ValidRange = (1.0, 4.0) self.y_comp.DisplayName = ExtAPI.Application.GetLocalString("ID_DirectionalYComponent") self.y_comp.IsVisibleCallback = self.IsVisible self.y_comp.CanParameterize = True self.y_comp.IsValidCallback = self.IsValid #Create a Z Component property using DoubleProperty with a valid range. #Override the default IsVisible and IsValid callbacks with the ones defined int this class. #Allow this property to be parameterized by setting CanParameterize to True. self.z_comp = DoubleProperty(name + "/Z Component", groupName) self.z_comp.ValidRange = (1.0, 4.0) self.z_comp.Value = 0 self.z_comp.DisplayName = ExtAPI.Application.GetLocalString("ID_DirectionalZComponent") self.z_comp.IsVisibleCallback = self.IsVisible self.z_comp.CanParameterize = True self.z_comp.IsValidCallback = self.IsValid #Add all properties to the grouped_props list self.grouped_props = [self.def_by_prop, self.magnitude,self.direction, self.coordinate_system, self.x_comp, self.y_comp, self.z_comp] def GetGroupedProps(self): """ Returns the properties list """ return self.grouped_props def IsVisible(self, prop): """ Overrides the IsVisible callback for properties. Decides which properties will be visible in the details pane based on the option selected in the DefineBy property """ if(prop.DisplayName == "Magnitude"): return int(self.def_by_prop.Value) == 0 if(prop.DisplayName == "Direction"): return int(self.def_by_prop.Value) == 0 if(prop.DisplayName == "Coordinate System"): return int(self.def_by_prop.Value) == 1 if(prop.DisplayName == "X Component"): return int(self.def_by_prop.Value) == 1 if(prop.DisplayName == "Y Component"): return int(self.def_by_prop.Value) == 1 if(prop.DisplayName == "Z Component"): return int(self.def_by_prop.Value) == 1 def IsValid(self, prop): """Overrides the isValid callback for properties. """ #for double property use the ValidRange property to check validity if(isinstance(prop, DoubleProperty)): return prop.ValidRange[0] <= prop.Value and prop.ValidRange[1] >= prop.Value return True """ Reload the properties at the end to make sure the class definition is executed before instantiation """ reload_props()