ANSA_Scripting_Python_Programming_Interface (1)
ANSA_Scripting_Python_Programming_Interface (1)
Table of Contents
1. DESCRIPTION OF THE PROGRAMMING INTERFACE........................................................................5
1.1 Introduction.........................................................................................................................................5
1.2 The Python Programming Language................................................................................................5
1.3 Python Version...................................................................................................................................5
1.4 Python Documentation.......................................................................................................................5
4. SPECIALIZED FUNCTIONS.................................................................................................................33
4.1 General..............................................................................................................................................33
4.2 Creating Connectors and GEBs......................................................................................................33
4.3 Executing specialized script functions from Connection Manager..............................................35
4.3.1 Updating Connection's User Field................................................................................................35
4.3.2 User Thickness to Diameter Map.................................................................................................35
4.3.3 Updating RADIOSS spring PID....................................................................................................36
4.3.4 The post-realization script function...............................................................................................37
4.4 Includes Configurator.......................................................................................................................41
4.5 Results Mapper.................................................................................................................................42
4.6 Input - Output post functions..........................................................................................................43
4.6.1 Example of a Post Input Script.....................................................................................................43
4.6.2 Example of a Post Output Script...................................................................................................44
8.1 General..............................................................................................................................................63
8.2 Script commands related with Catia...............................................................................................63
8.2.1 Catia orientation check.................................................................................................................63
8.2.2 Extracting thickness from catia entities.........................................................................................63
8.2.3 Check geometry existence...........................................................................................................64
8.3 Reading the attributes of cad files (CATIA, NX, ProE)...................................................................64
8.4 Handling of catia properties............................................................................................................64
8.5 Writing in the cad log file.................................................................................................................65
8.5.1 The "Extra Options" field of Cad Translator..................................................................................65
9. BCGUI FUNCTIONS.............................................................................................................................66
9.1 What is BCGUI..................................................................................................................................66
9.2 BCGUI structure and philosophy....................................................................................................66
9.2.1 Widget classes or widgets............................................................................................................66
9.2.2 Layout classes or layouts.............................................................................................................71
9.2.3 Items.............................................................................................................................................71
9.2.4 General remarks...........................................................................................................................72
9.3 BCGUI examples...............................................................................................................................73
9.3.1 A simple BCWindow.....................................................................................................................73
9.3.2 Creating and using callback functions..........................................................................................73
9.3.3 Moving more data around.............................................................................................................74
9.3.4 Interacting with ANSA entities......................................................................................................75
9.3.5 Advanced BCGUI functionality.....................................................................................................81
2.1.1 Numbers
Integer
The integer data type is used by variables that can only have whole numbers as values.
my_var = 10
Floating Point
Values that are not integral are stored as floating point numbers. A floating point variable can be
expressed as a decimal number such as 112.5, or with an exponent such as 1.125E2. In the latter case
the decimal part is multiplied by the power of 10 after the E symbol.
A floating point must contain a decimal point, or an exponent or both.
my_var = 112.5
Complex
c = 4+3j
Bool
b = True
String
A string, is declared as a series of printable text characters representing human readable stuff. A string
value is enclosed in quotes (e.g. "this is a string") and can be assigned to any variable for storage and
easy access. String variables are represented as lists of characters.
s = 'a string'
s = "a string"
List
A List is an ordered collection object type. A list can contain any type of an object such as integer, float
string, other lists, custom objects etc. Lists are mutable objects. Objects can be added, removed and
their order can be changed. The List object is similar to the matrix of the ANSA Scripting language.
Tuple
A Tuple object is a simple group of objects. They are like lists but are immutable. They are constructed
once and no further change can be done to the object. No new objects can be added, nor can they be
removed or reordered.
Dictionary
A Dictionary is an unordered collection. In a dictionary items are stored and fetched by a key instead of a
positional offset. Indexing a dictionary is a very fast and powerful operation. Dictionaries are the
equivalent to Maps of the ANSA Scripting Language.
Python provides a special object called None, which is always considered to be false. It is a special data
type and it serves as an empty placeholder.
2.2.1 Module
The module-based model in python is the core idea behind program architecture. Every file of Python
source code is a module. Other python files can access the items defined in a module by importing that
module. Import operations load another python file and allow access to that file's contents.
import math
import os
def main():
x = math.sqrt(9)
print('The square root is: '+str(x))
os.system('echo the square root of 9 is: ',x)
2.2.2 Namespaces
Each module file is a self-contained package of variables (Namespaces). One module file cannot see the
names of another module unless it is imported to that file, thus minimizing name collisions, even if
variables are spelled the same way.
if condition:
statement
if condition:
statement
elif condition:
statement
else:
statement
Since the condition is interpreted as a logical operator, the operators used for its expression are the
logical relational operators. Such operators are summarized in the table below:
Operator Meaning
< less than
<= less than or equal to
> greater than
>= greater than or equal to
== equal to
!= not equal to
or Logical OR
and Logical AND
not Logical NOT
all_properties = ["PSHELL","PCOMP","PBAR","PBEAM","PELAS"]
the result is
PSHELL
PCOMP
PBAR
PBEAM
PELAS
The 'initial-statement' initializes the explicit counter, the 'condition' specifies the number of repetitions and
the 'iteration-statement' dictates the increment or decrement value of the explicit counter during the loop.
all_properties = {"PSHELL","PCOMP","PBAR","PBEAM","PELAS"};
length = len(all_properties)
for i in range(len):
property = all_properties[i]
print(property)
while condition:
body-statement
If operators are to be used for the expression of the condition, these must be of logical relational type (see
section 2.4.1).
a = 0
while a<3:
print(a)
a += 1
0
1
2
a = 0
while a<5:
print(a)
a += 1
if a == 3:
break
0
1
2
The continue statement jumps back to the beginning of the loop’s block to begin the next iteration. Thus,
it omits a certain block of statements. A typical example is given below:
a = 0
while a<5:
a += 1
if a == 3:
continue
print(a)
1
2
4
my_list = list()
my_list.append('hello')
my_list.append('world')
m = [10, 7, 9]
List members can be even other lists. Thus, a definition like the following would form a 3x3 list:
my_list = [[10,7,9],
[5,2,17],
[6,12,55]]
val = my_list[0]
val = my_list[1][0]
length = len(m)
In case of a 2 dimension list the function will return the number of rows. In order to get the number of
columns of a row, ask the length of a specific row, e.g
C = [[20,7,9],
[5,4,17]];
length = len(C[1])
In the above example, the number of columns for the second row will be 3.
property = 'PSHELL'
mat_name = 'steel_105'
property = 'PSHELL'
id = 'with id 1'
property_id = property + id
str = 'Bumber_Front'
The above string has 12 characters where B has index 1, u has index 2……and t has index 12.
Any part of the string can be retrieved using the indices of the characters. Here are some examples:
Important Note: The length of a string can be found using the function len.
myDictionary = dict()
or
myDictionary = {}
Alternatively:
myDictionary['Name'] = 'aluminum'
myDictionary['pid'] = 19987
To retrieve a value of a specific key, the user must provide the corresponding key:
print(myDictionary['pid'])
val = myDictionary['Name']
print(val)
del myDictionary['Name']
if 'pid' in myDictionary:
print('OK')
length = len(myDictionary)
del myDictionary
2.9.1 Definition
User functions are defined using the def statement. This statement is followed by the function name. The
rest of the code must be idented. A typical function has the form:
def substr(a,b):
def substr(a, b): def substr(a, b): res = a-b
res = a-b res = a-b return 1
return res
Python provides additional techniques that alter the way arguments are passed to the called functions.
These are optional but allow the writing of code that supports very flexible calling patterns. The table
bellow describes these patterns.
Note: The named arguments pattern is widely supported in the ANSA module.
import ansa
from ansa import base
from ansa import constants
def my_fun():
“””Docstrings for function help “””
#Collect the parts
search_type = ('ANSAPART',)
parts = base.CollectEntities(constants.NASTRAN, None, search_type, True)
#Use each part as a container in order to collect its faces
search_type = ('FACE',)
faces = list()
for part in parts
container = [part] #The container must be in a matrix form
faces.append(base.CollectEntities(constants.NASTRAN,
container,earch_type,False))
myInteger = 12
myFloat = 5.78 #myFloat and myInteger are now global for all functions
def main():
global myInteger
print('initial value: '+str(myInteger))
myInteger = 7
print('Final value: '+str(myInteger))
def fun():
global myInteger
sum = myInteger + 7
global myFloat
myFloat += 1.0
def main():
var = 10
var_bo = pickle.dumps(var)
base.AnsaSetVariable('program_var1', var_bo)
m = [1, 10]
m_bo = pickle.dumps(m)
base.AnsaSetVariable('program_var2', m_bo)
def main():
val1 = base.AnsaGetVariable('program_var1')
val1_ = pickle.loads(val1)
print('val1: '+val1_)
val2 = base.AnsaGetVariable('program_var2')
val2_ = pickle.loads(val2)
for entry in val2_:
print("val2: "+entry)
Exception handling is the process of responding to the occurrence, during computation, of exceptions –
anomalous or exceptional situations requiring special processing – often changing the normal flow of
program execution. It is provided by specialized programming language constructs or computer hardware
mechanisms.
In python exceptions are handled with try and except statements. Any code that runs inside the try block
and raises an exception, the exception can be handled in the catch block.
try:
res = x / y
except DivisionByZero:
print('division by zero')
else:
print('result: '+str(res))
try:
val = myDict['Name']
except KeyError:
print('Key Name does not exist')
val = 0
import math
class Point:
"""A class that stores the x,y,z coordinates of a a point,
with a method that calculates the distance from the origin and
a method that prints the description of the class"""
def __init__(self, x_coord, y_coord, z_coord):
"""This is the constructor of the class"""
self.x = x_coord
self.y = y_coord
self.z = z_coord
def distFromOrigin(self):
"""Method that calculates the distancefrom the origin"""
dist = math.sqrt(self.x**2 + self.y**2 + self.z**2)
return dist
def __repr__(self):
return 'A point with X: '+str(self.x)+' Y: '+str(self.y)+' Z'+ str(self.x)
def main():
myPoint = Point(100.57, 786.46, 436.89) #creation of class instance myPoint
distance = myPoint.distFromOrigin()
print('The distance from the origin is: '+str(distance))
import math
import sys
import ansa
The import statement cannot take a full path. It looks directly into the python home directory. If a module
that needs to be imported resides outside the python home the following method needs to be called.
import sys
sys.path.append()
An example of this:
import sys
sys.path.append('/home/myHome/myLibrary.py')
import myLibrary
Note: Please refer to the official Python 3 documentation for more information on modules management
The ansa.ImportCode(filepath) function in the ANSA extension of Python allows to easily import Python
modules. It imports both compiled and ascii modules
An example is:
import ansa
ansa.ImportCode('/home/myHome/myLibrary.pyb')
def main():
myLibray.myFunction()
All these tasks that can affect the model definition, are controlled through a series of functions that
interact with the ANSA interface. Before proceeding to the explanation of individual functions, it is
important to emphasize in two basic topics: the treatment of ANSA elements and the meaning of ANSA
entities and cards.
Module Description
ansa.batchmesh Batchmesh related functions
ansa.guitk BCGUI functions
ansa.cad CAD and translator functions
ansa.base Topo, deck, visibility, element manipulation functions
ansa.connections Connections handling and realization functions
Ansa.constants A collection of all the ANSA constants and reserved methods
ansa.utils General functions
ansa.morph Morph functions
ansa.calc Mathematical fanctions
ansa.session ANSA session commands
ansa.taskmanager Task Manager functionality
reserved variables:
FILENAME, FILEPATH, FLANCH_PROPERTY_ID,
PART_COORD_SYS_DX1, PART_COORD_SYS_DX2, PART_COORD_SYS_DX3,
PART_COORD_SYS_DY1, PART_COORD_SYS_DY2, PART_COORD_SYS_DY3,
PART_COORD_SYS_DZ1, PART_COORD_SYS_DZ2, PART_COORD_SYS_DZ3,
PART_COORD_SYS_X, PART_COORD_SYS_Y, PART_COORD_SYS_Z,
PART_ID, PART_MASS, PART_MATERIAL_ID, PART_MATERIAL_NAME,
ansa.constants.NASTRAN
Note: If zero value is given instead of the deck constant, then the current deck will be considered.
Constants Description
ansa.constants.app_version returns the version as a string
ansa.constants.app_version_int returns the ANSA version as an integer
ansa.constants.app_home_dir The system directory used for configuration files by the
application
ansa.constants. app_root_dir It returns the application's root directory
_id
returns the ANSA Entity id
_name
returns the ANSA Entity name
and methods:
_isDefunct()
returns true if the referenced ANSA entity has been destroyed
_ansaType(deck)
returns the ANSA type of entity in the specified deck
l = []
l.append(shell)
n = ansa.base.Entity(ansa.constants.ABAQUS, 1, "NODE")
The types of entities that either don't have entity cards or the rule described before doesn’t cover them
are the following:
Important Note: The deck curves use a variety of keywords that can be found under the help text of the
built in function CreateLoadCurve.
Function Description
CollectEntities Collect entities massively
GetEntity Get a single entity
GetPartFromModuleId Get PARTs or GROUPs
NameToEnts Get entities from their name
CollectNewModelEntities Object that monitors and reports new model entity creation
TypesInCategory Collect types of entities that exist in mode
The types of entities that can be collected by using these functions are:
Important Note 1: If zero value is given instead of the deck name, then the current deck will be taken into
account.
Important Note 2: The MORPH statement must be used for handling entities coming from morph menu.
def main():
#Define into a matrix the keywords of entities that you want to collect.
#These keywords are taken from the title of their cards
search_type = ['PSHELL', 'PSOLID']
ents = base.CollectEntities(constants.NASTRAN,None,search_type,True)
In this approach the input arguments are matrices. The second argument indicates the search domain
and in case the user needs to collect entities from the whole database it must be zero. The output
argument is a matrix that contains the elements (pointers) of PSHELLs and PSOLIDs of the database.
The definition of the deck must be compatible with the entities that are going to be collected. An approach
like the following is not accepted:search_type = ('PSHELL","PSOLID')
ents = base.CollectEntities(constants.PAMCRASH,None,search_type,False)
In this case the equivalent keywords for PAMCRASH deck are PART_SHELL and PART_SOLID.
For collecting all the properties or materials of the database a string indicating the entity category must be
used:
def main():
all_props = base.CollectEntities(constants.NASTRAN,None,'__PROPERTIES__')
all_mats = base.CollectEntities(constants.NASTRAN,None,'__MATERIALS__')
def main():
#Collect first the shells of the whole database
search_type = ('SHELL',)
shells = CollectEntities(NASTRAN,0,"SHELL")
#Collect the grids of the shells
search_grid = ('GRID',)
grids = base.CollectEntities(constants.NASTRAN,shells,search_grid)
Alternatively, the entity's keyword could have been used instead (as string).
def main():
#Collect first the shells of the whole database
shells = base.CollectEntities(constants.NASTRAN,None,"SHELL")
#Collect the grids of the shells
grids = base.CollectEntities(constants.NASTRAN,shells,"GRID")
The third argument that defines the type of entities, can be also set to zero. This setting can be used for
collecting all the entities that are included into a superior entity. This makes sense in SETs, PARTs, or
Connections.
def main():
#Collect the sets of the database
sets = base.CollectEntities(constants.NASTRAN,0,"SET")
#Collect all the entities that belong to these sets
ents = CollectEntities(cpnstatns.NASTRAN,sets,False)
Attention must be given in the meaning of containers. Many entities in ANSA are considered as
containers since they include other entities inside them e.g. SHELLs include GRIDs. These containers
are classified according to their level. For instance, SHELLs are of higher level than GRIDs while
PSHELLs are of higher level than SHELLs and GRIDs. So, for searching entities inside a container the
CollectEntities must recursively search until the lower level. This is very clear in the following examples.
def main():
pshells = base.CollectEntities(constants.NASTRAN,None,'PSHELL',recursive=False)
shells = CollectEntities(constants.NASTRAN,pshells,'SHELL',False)
print(len(shells))
The last argument of CollectEntities is zero since SHELLs is only one level under PSHELLs.
Another equivalent syntax could be:
shells = base.CollectEntities(constants.NASTRAN,pshells,'SHELL',recursive=False)
For finding directly the GRIDs that are used by PSHELLs, the last argument must be set to 1 in order to
search recursively until the lower level.
def main():
pshells = base.CollectEntities(constants.NASTRAN,None,'PSHELL',recursive=False)
grids = base.CollectEntities(NASTRAN,pshells,"GRID",recursive=True)
print(len(grids))
A matrix that contains entities of specific type cannot be used as container for collecting entities of the
same type. For example, a matrix that contains elements (pointers) of SHELLs and SOLIDs cannot be
used as container for collecting SHELLs or SOLIDs but it can be used only for GRIDs which is a lower
level entity type.
Important Note: The matrix of elements (pointers) that is returned is not sorted according to the ids of the
entities that they reference.
Important Note: Visible are considered all entities that their visibility is controlled through the Database
Browser, thus it is impossible to collect visible entities like PROPERTIES or MATERIALS.
def main():
shells = base.CollectEntities(constants.NASTRAN,0,'SHELL',filter_visible=True)
props=base.CollectEntities(constants.NASTRAN,shells,'PSHELL',prop_from_entities=True)
len = len(props)
for i in range(len):
ret = base.GetEntityCardValues(constants.NASTRAN,props[i],('PID',))
print('PID: ',ret['PID'])
def main():
part = base.GetPartFromModuleId('1')
mats = base.CollectEntities(constantsNASTRAN,part,'MAT1',mat_from_entities=True)
If the type of material is not known then the “__MATERIALS__” can be used instead of “MAT1”
mats=base.CollectEntities(constants.NASTRAN,part,"__MATERIALS__",mat_from_entities=1)C
ollecting the entity types of a deck
As shown in paragraphs 2.3.2, 2.3.3, 2.3.4, the CollectEntities function needs to know what types of
entities to search for. In simple cases where specific types are needed, the user just have to open the
respective card and see the entity's keyword. For more complicated cases where the searching entities
are not well known or they are too many to open their cards one by one, the use of the function
TypesInCategory is necessary. The function uses two input arguments which are the name of the deck
and a string that defines the searching area. The output is a matrix with all supported types. The string
that denotes the searching area can get the following forms:
Category Description
"__MATERIALS__" Gets all available material types of the specified deck
"__PROPERTIES__" Gets all available property types of the specified deck
"__ELEMENTS__" Gets all available element types of the specified deck
"__VISIBLE__" Gets all visible element types of the specified deck, that their visibility can be
controlled through the Database Browser
"__ALL_ENTITIES__" Gets all supported entities of the specified deck
"__CONNECTIONS__" Gets all supported weld types
A useful example could be the collection of all connections types of the database in order to be realized.
def RealizeAllConnections():
#Get all connection types
connection_types = base.TypesInCategory(constants.LSDYNA,'__CONNECTIONS__')
connections = base.CollectEntities(constants.LSDYNA,None,connection_types)
base.RealizeConnections(connections,len(connections))
def GetSingleEntity():
group = base.GetEntity(constants.PAMCRASH,'GROUP',100)
In this example the element (pointer) of the Pam-Crash GROUP with id 100 is returned.
The type is not necessarily needed if the function is used for getting properties or materials. In this case,
instead of the entity type, the keywords "__MATERIALS__" and "__PROPERTIES__" can be used.
def main():
prop = base.GetEntity(constants.NASTRAN,'__PROPERTIES__',10)
mat = base.GetEntity(constants.NASTRAN,'__MATERIALS__',10)
Important Note: The GetEntity function cannot collect ANSAPARTS and ANSAGROUPS of PART
MANAGER through their Module Id.
def main():
part = base.GetPartFromModuleId("1A")
group = base.GetPartFromModuleId("100")
def main():
#Collect entities that satisfy the searching pattern
ents = base.Name2Ents("^Default.*")
pshells = list()
psolids = list()
for ent in ents:
type = base.GetEntityType(ent)
#Distinguish the type of entity
if type == "PSHELL":
pshells.append(ent)
if type == "PSOLID":
psolids.append(ent)
If no entities are found the function returns nothing. This case can be identified using the "!" operator.
ents = base.Name2Ents("^Default.*")
if not ents:
print('No entities were found')
def main():
collector = base.CollectNewModelEntities()
n = base.CreateEntity(ansa.constants.ABAQUS, 'NODE')
new_entities = collector.report()
del collector
print(len(new_entities))
For collecting only specific types of entities, the CollectNewModelEntities must be initialized with the
parameter “filter_types” followed by a matrix containing the entity types to be monitored:
def main():
ents = ("SHELL_SECTION","SHELL")
container = base.CollectNewModelEntitiesStart(constants.ABAQUS,filter_types=pshell)
base.InputAbaqus("./"+abaqus_model_name, "nooffset", "nooffset", "nooffset",
"nooffset","", "", "", "", "", "on")
connections.ReadConnections("XML","/home/work/connections.xml")
new_entities = container.Report()
del container
for new_entity in new_entities:
print(base.GetEntityType(constants.ABAQUS, new_entity))
def main():
types_to_pick = ('SHELL','SOLID')
ents = base.PickEntities(constants.NASTRAN,types_to_pick)
print(len(ents))
Import ansa
from ansa import utils
def Selection():
print('Select the file for reading')
read_file = utils.SelectOpenFile(0, 'csv files (*.csv)')
#The matrix 'read_file' contains only one entry since the
#the first argument of 'SelectOpenFile' was 0
print('The file that was selected is: '+read_file[0])
print('Select the log file for writing the error messages')
save_file = utils.SelectSaveFile()
print('The file that was selected for writing errors is: '+save_file)
dir = utils.SelectOpenDir('')
if not dir:
print('No directory was selected')
Function Description
GetEntityCardValues Get values from a card
SetEntityCardValues Set values to a card
CreateEntity Creates a new entity
CreateConnectionPoint Creates a connection point
CreateConnectionLine Create a connection line
CreateConnectionFace Create a connection face
RealizeConnections Realize connections
DeleteEntity Delete an entity
NewPart Creates new parts
NewGroup Creates new groups
import ansa
from ansa import base
from ansa import constants
def GetValues():
props = base.CollectEntities(LSDYNA,None,'SECTION_SHELL')
#Initialize counters
names = list()
thickness = list()
pids = list()
mids = list()
.....
statement
It is obvious that the user must be familiar with the labels of each edit card since they must be written
exactly as they appear in the cards. The output value of the function is a dictionary with keys the
requested fields and values the corresponding values. If an error occurs the return of the particular field
will be None
To avoid opening and closing cards only for seeing the names of the labels, three global label – keywords
can be used. These keywords allow the extraction of the entity's id, property and type without knowing the
name of the respective labels. Their syntax is the following:
status = base.GetEntityCardValues(constants.LSDYNA,prop,('__id__','__prop__'))
For getting values from a card different than the one that is currently used, the redirection symbol '-> ' can
be used. A typical example is to get the material name while the property card is accessed.
def main():
pshell = base.GetEntity(constants.NASTRAN,'PSHELL',100)
ret = base.GetEntityCardValues(NASTRAN,pshell,('MID1->Name',))
print(ret['MID1->Name'])
def SetValues():
#Get the PART_SHELL property with id 10
prop = base.GetEntity(constants.PAMCRASH,'PART_SHELL',10)
#Set the new values for id and thickness.
base.SetEntityCardValues(constants.PAMCRASH,prop,{'IDPRT':1000,'h':1.75})
If a keyword is given wrong, the function will not work even if all the other keywords had been defined
correctly. In this case the function will return the number of wrong occurrences.
status = base.SetEntityCardValues(constants.PAMCRASH,prop,{'IDPRT':1000,'h':1.75})
Although the 'IDPRT' is correct, the function will not work because of the 'h1' label and therefore will
return 'status=1'.
Important Note: The global labels ( __id__ ,__prop__ ,__type__ ) are also valid.
keyword (see section 3.3.2) and pairs of labels – values. It returns the reference of the newly created
entity.
def CreateGrid():
vals = {'NID':100,'X1':3.5,'X2':10.8,'X3':246.7}
base.CreateEntity(constants.NASTRAN,"GRID",vals)
During the creation of an entity, all the fields that are necessary for its definition but were not specified by
the user (e.g. the id) are automatically filled by ANSA.
Important Note: Not all entities of ANSA can be created with the CreateEntity.
def main():
#Create a part with name 'door' and id 10
part = base.NewPart('door','10')
#Create a group with name 'side' and without id
group = base.NewGroup('side','')
import ansa
from ansa import connections
from ansa import base
from ansa import constants
def CreateCnctEnts():
#create a spotweld point of ID 122 at (2.3, 3.0, -1.0)
xyz = (2.3, 3.0, -1.0)
cnctn_p=connections.CreateConnectionPoint('SpotweldPoint_Type',122,xyz=3,
part_ids_point=3)
#create an adhesive line of arbitrary ID
curves = (base.GetEntity(constants.NASTRAN, 'CURVE',15),))
#part ids that will be connected
part_ids_curve = (2,3)
cnctn_c=connections.CreateConnectionLine('AdhesiveLine_Type",0,curves,1,
part_ids_curve=2)
base.SetEntityCardValues(constants.NASTRAN, cnctn_c, {'W':1})
As noticed, the length of each matrix must follow the matrix itself, e.g.
xyz, 3
part_ids_point, 3
curves, 1
part_ids_curve, 2
Attention must be given in the first argument of all three functions since this string indicates the type of the
entity that will be created. The syntax of it can be found in the title of each connection card.
Connections = base.CollectEntities(constants.NASTRAN,None,'SpotweldPoint_Type',
recursive=False)
for connection in connections:
vals = ('ID','X','Y','Z','P1','P2','P3','P4')
ret= base.GetEntityCardvalues(NASTRAN,connection,vals)
print("ID "+str(ret['ID'])+" x:"+str(ret['X']))
...
or
connections = base.CollectEntities(constants.NASTRAN,None,'AdhesiveLine_Type',
recursive=False)
for connection in connections:
base.SetEntityCardvalues(constants.NASTRAN,connection,{'W':1})
# SpotweldPoint_SPIDER2_PBAR_ID =
# SpotweldPoint_SPIDER2_ForceZeroGap = n
# SpotweldPoint_SPIDER2_DoNotMove = y
# SpotweldPoint_SPIDER2_CBARPinFlags = 0
# SpotweldPoint_RBE3-HEXA-RBE3_UseThicknessAsHeight = n
# SpotweldPoint_RBE3-HEXA-RBE3_SpecifyHeight = n
# SpotweldPoint_RBE3-HEXA-RBE3_SeparateRefCPinflags = n
# SpotweldPoint_RBE3-HEXA-RBE3_SearchDist =
# SpotweldPoint_RBE3-HEXA-RBE3_RefCPinFlags = 123
# SpotweldPoint_RBE3-HEXA-RBE3_PinFlags = 123
# SpotweldPoint_RBE3-HEXA-RBE3_PSOLID_ID =
# SpotweldPoint_RBE3-HEXA-RBE3_Height =
# SpotweldPoint_RBE3-HEXA-RBE3_ForceOrthoSolids = n
# SpotweldPoint_RBE3-HEXA-RBE3_FailIfAspect = 0.000000
# SpotweldPoint_RBE3-HEXA-RBE3_DoNotMove = y
# SpotweldPoint_RBE3-HEXA-RBE3_AreaScaleFactor = 0.000000
In the example that follows the spotweld points must be realized in NASTRAN CWELDs with option
ELPAT and specific PWELD id, while the adhesive lines must be realized in RBE3-HEXA-RBE3 with 2
stripes, specific PSOLID id and the option ‘Force Ortho Solids’ activated. The RealizeConnections will
be used instead of the RealizeConnection since it can realize massively and thus faster.
def RealizeAllCncts():
#Collect the spotwelds of the database
spots = base.CollectEntities(constants.NASTRAN,None,'SpotweldPoint_Type')
#Collect the adhesive lines of the database
adh_lines = base.CollectEntities(constants.NASTRAN, None,'AdhesiveLine_Type')
#Number of connection points
no_spots = len(spots)
#Number of adhesive lines
no_lines = len(adh_lines)
#Realize the spotwelds
connections.RealizeConnections(spots,no_spots,
{"SpotweldPoint_Type":"NASTRAN CWELD",
"SpotweldPoint_NASTRAN-CWELD_WeldType":2,
"SpotweldPoint_NASTRAN-CWELD_SearchDist":10,
"SpotweldPoint_NASTRAN-CWELD_PWELD_ID":1000})
#Realize the adhesive lines
connections.RealizeConnections(adh_lines,no_lines,
{"AdhesiveLine_RBE3_HEXA_RBE3_SearchDist":10,
"AdhesiveLine_RBE3_HEXA_RBE3_NumOfStripes":2,
"AdhesiveLine_RBE3_HEXA_RBE3_ForceOrthoSolids":"y",
"AdhesiveLine_RBE3_HEXA_RBE3_PSOLID_ID":2000})
def CheckRBE3_HEXA_RBE3():
nastran = constants.NASTRAN
if type=="SOLID":
if j==0:
no_of_solids = ent._id
j = 1
else:
no_of_solids = str(no_of_solids)+","+str(eid)
print("Connection with cid ",cid," has RBE3s with ids:",no_of_rbe," and SOLIDs with
ids:",no_of_solids)
no_of_rbe = 0
no_of_solids = 0
print("Done")
def DeleteNodes():
nodes = base.CheckFree("all")
base.DeleteEntity(nodes,0)
The second argument is a force flag. Use 1 to delete entities and any references to these entities. For
example the force flag for deleting PSHELLs properties must be 1 since there are shells that use this
property. After the execution of DeleteEntity the property and the shells / grids that are associated with it
will all be deleted.
Important Note 1: To significantly reduce execution time, it is highly recommended to delete entities
massively instead one at a time.
Important Note 2: It is recommended to use the DeletePart function for deleting ANSAPARTs since it
offers more options.
Important Note 3: To delete unused entities use the Compress function
Inheritance is one of the most fundamental concepts of object orientated programming. It is a way to
reuse code of existing objects, or to establish a subtype from an existing object. In the example below by
subclassing the ANSA Entity object we extend the behavior of this object of meet our program design
requirements.
import ansa
from ansa import base
from ansa import constants
class extendedProp(ansa.base.Entity):
”””subclassing the entity of object of type ELEMENT_SHELL we extend
its behavior to return the cog and to return the number of Elements”””
def __init__(self, deck, id, type):
super().__init__(deck, id, type)
def CalculateCog(self):
return base.Cog(self)
def ElementNumber(self):
ents = base.CollectEntities(constants.LSDYNA, self, "ELEMENT_SHELL")
return len(ents)
def main():
ents = base.CollectEntities(constants.LSDYNA, None, "SECTION_SHELL")
extended = list()
for ent in ents:
ret = base.GetEntityCardValues(deck=constants.LSDYNA, entity=ent,
fields=('PID',))
(x, y, z) = extended[0].CalculateCog()
print('cog: %f %f %f' % ( x, y, z))
ret = extended[0].ElementNumber()
print('number of elements: '+str(ret))
4. Specialized Functions
4.1 General
Specialized functions in scripting language are actually user functions that have a unique syntax (input
and output arguments) and can be called automatically by the program when the user performs specific
tasks. Connectors, GEBs, Connection Manager, Includes Configurator, Results Mapper, I/O windows are
the tools where these functions can operate.
In the example shown, the function to be executed is named ‘BarInterface’. This function is defined as
follows:
The matrix ‘FromSearch’ contains all the nodes that lie in the inner/outer zone of the hole. The matrix
‘FromRepr’ contains one ‘Spc1’ node, which is by default located at the x, y, z Generic Entity coordinates.
Finally, the string 'args' will be the string '60' specified in the ‘func_arguments’ field.
Note that the function must return a non-zero value on success and a zero value on failure. In the latter
case the GEB will get a failure status. After the realization of this generic entity, each node identified from
the search will be connected to the ‘Spc1’ node with a ‘CBAR’ element.
return 1
Important Note 1: Press F1 on the 'func_name' field to load the user script function.
Important Note 2: The number and type of input arguments denotes the signature of the user function.
Thus, after loading, only the functions of a specific signature will be recognized.
Alternatively, the user can specify its name in the ANSA.defaults, under the variable:
weld_user_field_update = UserPlinkProp
The input argument of this function is the element (pointer) of the entity that is going to be created. Having
this, it is easy to extract all necessary information. At the end of the script a string must be returned. A
possible use of this function is to display in the 'User' field the property id of the newly created plinks:
def UserPlinkProp(connection):
if connection._ansaType(constants.PAMCRASH) == 'PLINK':
ret = base.GetEntityCardValues(PAMCRASH,connection,('IPART',))
return ret['IPART']
Important Note 1: The number and type of input arguments denotes the signature of the user function.
Thus, after loading, only the functions of a specific signature will be recognized.
By default ANSA will follow the thickness-diameter table method with the default table available in the
ANSA.defaults:
thick_spw_diam = 4.00,1.02,5.00,1.78,6.00
To define a mapping scheme that cannot be described by a table, a user-script function can be used. In
this approach, Connection Manager will automatically call this function every time a spotweld is applied
(provided that the flag 'Use thickness to Diameter Map' -when available, is active).
The script function can be loaded and specified in the general connections settings (Window>Options), by
hitting F1 key in the 'Function name' field.
Alternatively, the user can specify its name in the ANSA.defaults, under the variable:
thick_spw_diam = AssignDiameter
Function(thickness)
The input argument is a thickness value while the returned value is the diameter that will be applied:
def AssignDiameter(thickness):
if thickness <= 1:
diameter = thickness
elif thickness > 1 and thickness < 2:
diameter = thickness/4
elif thickness >= 2 && thickness < 3:
diameter = thickness/2
else
diameter = thickness*2
return diameter
Important Note 1: The thickness that is given as input, is the one that calculated according to the 'Master
Flange Election Method'.
Important Note 2: The number and type of input arguments denotes the signature of the thickness to
diameter map function. Thus, after loading, only the functions of a specific signature will be recognized.
Alternatively, the user can specify its name in the ANSA.defaults, under the variable:
shell_to_spring_pid = DefineSpringId
Function(shells)
The input argument is a matrix that contains the projected shells while the output is the element (pointer)
of the property that is going to be assigned to the newly created radioss springs. The property is created
by the function or it can be any existing one.
def DefineSpringId(shells):
thickness = list()
for shell in shells:
max_thick = max(thickness)
print(max_thick)
if max_thick <= 1:
vals = {"Name":"Maximum thickness less than "+str(max_thick),
"PID":500",
"TYPE":"SPR_BEAM 13",
"MASS":0.5}
ent = base.CreateEntity(RADIOSS,"PROP/SPR_BEAM", vals)
else:
vals = {"Name”:"Maximum thickness greater than "+str(max),
"PID":1000",
"TYPE":"SPR_BEAM 13",
"MASS":1}
ent = base.CreateEntity(constants.RADIOSS,"PROP/SPR_BEAM",vals)
return ent
In the above example a different PROP/SPR_BEAM is assigned to each spring according to the
thicknesses of the shells that connects.
Important Note 1: The number and type of input arguments denotes the signature of the user function.
Thus, after loading, only the functions of a specific signature will be recognized.
hole_data = misc[1]
central_shells = hole_data["center_elements"]
zone1_shells = hole_data["zone1_elements"]
zone2_shells = hole_data["zone2_elements"]
all_connected_parts = len (projections)
for i in range(all_connected_parts):
central_shells_of_flange = central_shells[i]
zone1_shells_of_flange = zone1_shells[i]
zone2_shells_of_flange = zone2_shells[i]
The return value of the post-realization function determines what should be the “Error Class” for each
connection and signifies connection modification success or failure. The supported return values with
their meaning are listed in the table below:
The name of post-realization script function must be declared so that the Connection Manager knows
which function to execute. This declaration is performed in the general connections options, under
Windows>Options.
Press F1 in the 'Post Realization Function' field to launch the Select Script Function window. From this
window the user can also load the script , thus complete both steps at once.
Alternatively, the user can specify its name in the ANSA.defaults, under the variable:
post_realization_fn = PostRealizationFunction
Example 1: Understanding the input arguments: This post-realization function will just print some
information in the ANSA Info window
flange = 1
for ents in proj_ents:
for ent in ents:
type = ent._ansaType(constants.NASTRAN)
print ("Projection ent on flange "+str(flange)+" : "+type+" ID: "+ent._id)
flange += 1
flange = 1;
for ents in interfaces:
for ent in ents:
type = ent._ansaType(constants.NASTRAN)
flange += 1
flange = 1;
for ents in bodies:
for ent in ents:
type = ent._ansaType(constants.NASTRAN)
print("Body ent on flange "+flange+" : "+type+" ID: "+ent._id)
flange += 1
return 1
if not prop_id:
vals = {"Name":"SPW_SPIDER_D="+D, "A(A)":A,
"I1(A)":I1, "I2(A)":I2, "J(A)":J}
return 1
Important Note 1:The post-realization function can work for all connection points, connection lines and
surfaces and for all FE-representations except of SPIDER.
Important Note 2: To have the same post-realization function available every time ANSA is launched
load the script through an ANSA_TRANSL.
where:
-conf is the Includes Configuration entity.
-arg is a map that is automatically created, having the following entries:
i) arg["UserArgs"] is the string that is input by the user in the pre- post- or output_func_arguments
field of the configuration's card.
ii) arg["Include"] is an Include entity that can be created when updating/reloading a configuration. If the
user assigns entities to this Include, then it will be added to the configuration. If this include remains
intact, then it is discarded from the database. This entry is not available for the Output script.
The user can add as many other entries as needed in map arg.
The following sample script prints the user argument in the Ansa Info window and reports the contents of
each Include of the configuration in a log file:
where:
-source_entities are all the entities of the source file (i.e. entities that would be created in ANSA if the file
were input).
-target_and new_entities is a matrix that contains: i) the entities of the current (target) mesh, that have
been identified based on the specified connectivity and search pattern, ii) entities that have been created
from the results mapper (e.g. pressures, temperatures etc.). The latter are available only for the post map
function. The respective argument of the pre map function is a matrix that contains only the target entities.
-user_args is the string that can be specified from the user in the pre_func_arguments or
post_func_arguments fields.
An example of application of a pre-map function is the case when the Transformation matrix is already
known and its values reside in text file like the following:
A pre-map script can extract info from this file and assign it to the results mapper:
The post input and output functions must have specific arguments:
PostInput(input_filename, input_function_args)
where:
- input_filename is the full path to the selected deck file.
- input_function_args is a set of auxiliary user defined arguments.
PostOutput(output_filename, output_function_args)
where
- output_filename is the full path to the created deck file.
- output_function_args is a set of auxiliary user defined arguments.
In both cases the function must return 1 for success, otherwise an error message will be printed in the
Ansa Info window.
To set up the Post Input Script and the Post Output Script functions the corresponding scripts must be
first loaded. The 'Post func name' must be declared so that ANSA knows which function to execute. Hit
F1 in the 'Post func name' field to launch the 'Select script function' window and load the script. Pick the
relative function and press Ok to assign its name in the field. In the 'Post func args' type any string
representing user define data. If no auxiliary data are needed, leave the field blank.
Important Note: The number and type of input arguments denotes the signature of the user function.
Thus, after loading, only the functions of a specific signature will be recognized.
base.SetGeneralComment(comment)
A Post Output Script is executed only when all physical data have been already exported. The user could
use a Post output function in order to add to the exported deck file some comments written in a specific
syntax suitable for reading by another software. In this case no 'Post func args' need to be defined.
Each time a script is set as default, the functions that holds become available. The one that was
previously default remains loaded but its functions are not available anymore.
Important Note: Imported scripts are not listed in the above window.
• Tools>Script>Reload:
Reloads the last loaded script.
• Tools>Script>Unload:
Unloads loaded or added scripts. Selecting this button opens the list with all loaded and added scripts of
the database. Select the script to unload and confirm with Ok. When the default script is unloaded then as
default becomes the script with the next index. Consequently, all the functions of the first one are lost and
the functions of the second become available.
Functions of imported scripts retain a relationship with the zero index script since they are appended to it.
So, if a user unloads the zero index script then the functions of the imported scripts will be lost too.
Similarly, if the default status is changed, the functions of the imported script will become unavailable.
• Tools>Script>Run function:
Runs a function. When selecting this button the following window opens:
In the Function list all available functions are displayed. These functions come from the imported scripts
and from the default script. In Available modules menu, all the available scripts are displayed while the
default one is always active. If another module is selected, then automatically its functions will become
available while the previous ones will be unavailable. Other useful buttons are the Load module which
acts similarly to Tools>Script>Add and the Reload module which reloads the active script.
Select a function from the list. Its help is displayed in the User function description. If the function needs
input arguments, then these must be given in the Type function arguments field in comma separated
form. Press Ok to proceed to the function execution or Cancel to abort.
The Command Line window is an easy tool for handling scripts. Typing in the command line the word
USER>ANSA lists all available auxiliary built in functions in the Ansa Info window.
load_script
Usage: USER:load_script: <full path to the new script>
Example: USER>:oad_script:/home/jharal/work/CombineSets.c
Description: Clear all previous loaded scripts and loads the one specified above
reload_script
Usage: USER:reload_script()
Example: USER:reload_script()
Description: Reloads all loaded scripts.
add_script
Usage: USER:add_script: <full path to the new script>
Example: USER:add_script: /home/jharal/work/CombineSets.c
Description: Adds a script.
import_script
Usage: USER:import_script: <full path to the new script>
Example: USER:import_script:/home/jharal/work/CombineSets.c
Description: Append new script in the current active ones
unload_script
Usage:USER:unload_script()
Example: USER:unload_script()
Description: Unloads all loaded functions
default
Usage: USER:default()
Example: USER:default()
Description: Opens a window with all loaded scripts and waits the user to select the new default one.
In the above example the script 'MakeSkin.bs' has an error in line 25.
After all necessary corrections the script is loaded again. This time no errors occurred.
Important Note 1: If a script has more than one error, then only the first occurrence will be displayed.
Important Note 2: A wrong syntax of a built in function is reported in run time.
USER>load_script(ANSA_TRANSL)
If function contains input arguments it is displayed in Ansa Info window in the form:
USER><function name (type of input argument)> i.e, USER:PrintText('ANSA', 'v14.2.2')
The 'PrintText' function accepts two strings as input arguments. These arguments are given in the
command line after the name of the function and have to be separated with comma. All other ways are
ignored.
Finally, all functions that executed via command line display their possible messages in the Ansa Info
window.
Decorator Comment
@ansa.session.defbutton The function name is the button name placed in the
default button group
@ansa.session.defbutton('Visibility') The function name is the button name placed in the
specified button group
@ansa.session.defbutton('Visibility', 'Test Button') Button name and group is specified in the defbutton
import ansa
@ansa.session.defbutton
def Test_Button():
print('ANSA')
For placing buttons in specific groups, the name of the group must be specified in the defbutton:
import ansa
@ansa.session.defbutton('Visibility')
def Test_Button():
base.SetViewAngles("F10")
Once the script is loaded, a button called "Test_Button" is created under the "Visibility" group of
Windows>User Script Buttons and placed in the first free position.
ANSA reads the plugins always starting from the config/plugins directory and afterwards from the user
directory. A message is always displayed in ANSA Info window informing the user regarding the loading
process of all plugins.
In the above case, ANSA loaded two plugins from a user directory and one plugin from the
/config/plugins/ folder. The plugins then are considered extensions of the program and can be executed
through the File>Script plugins
Important Note: Plugin functions are loaded normally even if they have the same name.
def main():
print("Hello")
Linux OS:
Windows OS:
Linux OS:
Windows OS:
Important Note: Any scripting functions related to graphics performance cannot be executed in 'nogui'
mode, e.g. the SelectOpenFile, SelectOpenDir, PrintToFile etc. Exceptions are the OREntity,
ANDEntity, NOTEntity.
1. ANSA_HOME Directory
This is the directory where the environment variable ANSA_HOME is pointing at.
2. Hidden BETA directory located in User's HOME Directory
This is the directory that is created as soon as ANSA is launched for the first time. Its location is in:
/home/user/.BETA/ANSA/version_13.x/
3. Working Directory
This is the directory from which ANSA was called to run.
During the attempt to read an ANSA_TRANSL, ANSA will display the following messages in the Ansa Info
window:
global a
string b
def CAD_Translate():
...code...
def Translation():
...code...
If ANSA finds among the ANSA_TRANSL files more than one global code then the last read will be kept.
Similarly, if functions with same name are identified, then the last read will overwrite the previous ones.
Important Note 1: It is recommended the CAD_Translate and all common user functions to be kept in
the ANSA_TRANSL of ANSA installation directory.
Important Note 2: Any ANSA_TRANSL that comes from versions prior to v13.0 is valid only if it is in
binary format.
The basic advantage of registers is that they can pass directly a value to an entity without first to search
for the entity. Clearly, this approximation saves a lot of user work, minimize the code and eliminates the
possibility of error. For example, the registers PART_PROPERTY_NAME and PART_MATERIAL_NAME
can be used to assign the property and material name of the component.
PART_PROPERTY_NAME = "panel"
PART_MATERIAL_NAME = "steel"
pshell = base.GetFirstEntity(constants.NASTRAN,"PSHELL")
base.SetEntityCardValues(constants.NASTRAN,pshell,"Name","panel")
material = base.GetFirstEntity(constants.NASTRAN,"MAT1")
SetEntityCardValues(constants.NASTRAN, material,"Name","steel")
Obviously, in the second case more lines of code are needed and consequently the possibilities of
making an error are greater.
Important Note: If the cad file has more than one properties, then registers like
PART_PROPERTY_NAME, PART_PROPERTY_THICKNESS etc, will affect them all.
def CAD_Translate():
cad_filepath = "/home/demo/test.CATPart"
os.system("/home/demo/beta/ansa_v13.1.1/ansa_cad.sh -i "+cad_filepath)
The System command can also use the environment variables of the system. Especially for calling the
cad translator, the 'ANSA_EXEC_DIR' can be used to access the ANSA installation directory. The dollar
character $ must be in front of an environment variable in order to get its value:
def CAD_Translate():
os.ystem("$ANSA_EXEC_DIR/ansa_cad.sh -i "+cad_filepath)
Important Note: The function EnvironmentVar gets the value of any environment variable.
126,12,2,0,0,0,0,0.,0.,0.,0.25,0.25,0.375,0.375,0.5,0.5,0.75, 1P 1
0.75,0.875,0.875,1.,1.,1.,1.,1.,1.,0.707107,1.,0.707107,1.,1., 1P 2
1.,0.707107,1.,0.707107,1.,406.539,1057.63,-6.75,401.539, 1P 3
1057.63,-6.75,396.539,1057.63,-6.75,396.539,1050.88,-6.75, 1P 4
396.539,1050.88,0.,396.539,1050.88,6.75,396.539,1057.63,6.75, 1P 5
401.539,1057.63,6.75,406.539,1057.63,6.75,406.539,1050.88,6.75, 1P 6
406.539,1050.88,0.,406.539,1050.88,-6.75,406.539,1057.63,-6.75, 1P 7
0.5,0.75,0.,0.,0.; 1P 8
S 13G 3D 2P 8 T 1
The above HEADER is easy to be extracted using only the following 2 lines under the CAD_Translate
function:
def CAD_Translate():
for line in in_line:
print(in_line)
Besides the header section of a CAD file, information about a part can also be given through standard
text files, the so called attribute files. In this case, for each CAD file that is opened into ANSA,
ANSA_TRANSL will read the corresponding attribute file and retrieve information about the specific part.
This information is then assigned to the related fields within ANSA. Suppose that the attribute file has the
form:
SUBSTRUCTURE = LEFT
TITLE = B PILLAR
MODULE ID = 999
PID = 100
PROPERTY NAME = B_PILLAR_999
THICKNESS = 0.97
MID = 1000
MATERIAL NAME = MAT1_STEEL
ORIGIN = 0.,-100.,0.
X_AXIS = 1.,0.,0.
Y_AXIS = 0.,1.,0.
Z_AXIS = 0.,1.,0.
The ANSA_TRANSL that could be used in order to read the attribute file and assign the values to every
imported cad file is the following:
/*---------------------------------------------------*/
/*---Informations are written in ANSA_TRANSL.log-----*/
/*---------------------------------------------------*/
def CAD_Translate()
m = TokenizeString(in_line,"=",0);
sub_ass_name = GetString(m[1]);
NewGroup(sub_ass_name,0);
}
/* Look for a "TITLE = ...." line */
else if(MatchString(in_line,"TITLE"))
{
m = TokenizeString(in_line,"=",0);
pdm_id = GetString(m[1]);
}
/* Look for a "MODULE ID = ...." line */
else if(MatchString(in_line,"MODULE ID"))
{
m = TokenizeString(in_line,"=",0);
module_id = GetInt(m[1]);
}
/* Look for a "PROPERTY NAME = ...." line */
else if(MatchString(in_line,"PROPERTY NAME"))
{
m = TokenizeString(in_line,"=",0);
property_name = GetString(m[1]);
}
/* Look for a "PID = ...." line */
else if(MatchString(in_line,"PID"))
{
m = TokenizeString(in_line,"=",0);
property_id = GetInt(m[1]);
}
/* Look for a "MATERIAL NAME = ...." line */
else if(MatchString(in_line,"MATERIAL NAME"))
{
m = TokenizeString(in_line,"=",0);
material_name = GetString(m[1]);
}
/* Look for a "MID = ...." line */
else if(MatchString(in_line,"MID"))
{
m = TokenizeString(in_line,"=",0);
material_id = GetInt(m[1]);
}
/* Look for a "THICKNESS = ...." line */
else if(MatchString(in_line,"THICKNESS"))
{
m = TokenizeString(in_line,"=",0);
thickness = GetFloat(m[1]);
}
/* Look for an "ORIGIN = ...." line */
else if(MatchString(in_line,"ORIGIN"))
{
/* Read X,Y,Z Origin Coordinates */
m = TokenizeString(in_line,"=,",0);
PART_COORD_SYS_X = GetFloat(m[1]);
PART_COORD_SYS_Y = GetFloat(m[2]);
PART_COORD_SYS_Z = GetFloat(m[3]);
}
/* Look for a "X_AXIS = ...." line */
else if(MatchString(in_line,"X_AXIS"))
{
/* Read DX,DY,DZ of X Axis Vector */
m = TokenizeString(in_line,"=,",0);
PART_COORD_SYS_DX1 = GetFloat(m[1]);
PART_COORD_SYS_DY1 = GetFloat(m[2]);
PART_COORD_SYS_DZ1 = GetFloat(m[3]);
}
/* Look for a "Y_AXIS = ...." line */
else if(MatchString(in_line,"Y_AXIS"))
{
/* Read DX,DY,DZ of Y Axis Vector */
m = TokenizeString(in_line,"=,",0);
PART_COORD_SYS_DX2 = GetFloat(m[1]);
PART_COORD_SYS_DY2 = GetFloat(m[2]);
PART_COORD_SYS_DZ2 = GetFloat(m[3]);
}
/* Look for a "Z_AXIS = ...." line */
else if(MatchString(in_line,"Z_AXIS"))
{
/* Read DX,DY,DZ of Z Axis Vector */
m = TokenizeString(in_line,"=,",0);
PART_COORD_SYS_DX3 = GetFloat(m[1]);
PART_COORD_SYS_DY3 = GetFloat(m[2]);
PART_COORD_SYS_DZ3 = GetFloat(m[3]);
}
}
}
else
{
/* Warn user if Attributes File does not Exist */
if(fd_log)
Write(fd_log,"Warning : No Attributes File");
else
Print("Warning : No Attributes File");
}
if(!pdm_id)
{
/* Warn user if No PDM data in Attributes File */
if(fd_log)
Write(fd_log,"Warning : NO PDM Id");
else
Print("Warning : NO PDM Id");
}
/* Construct PART name to the taste of user */
if(i = MatchSeparators(FILENAME))
{
if(pdm_id)
name = FILENAME(:i-1)%"_"%pdm_id;
else
name = FILENAME(:i-1);
}
else
{
if(pdm_id)
name = FILENAME%"_"%pdm_id;
else
name = FILENAME;
}
/* Finally Assign PART Atributes to ANSA Registers */
PART_NAME = pdm_id;
PART_ID = module_id;
PART_PROPERTY_ID = property_id;
PART_PROPERTY_NAME = property_name;
PART_PROPERTY_THICKNESS = thickness;
PART_MATERIAL_ID = material_id;
PART_MATERIAL_NAME = material_name;
}
It is clear that the use of registers made the code more compact and easy to read since it was avoided
the use of other built in functions which could do the same actions in a more ‘complicated’ way.
T-SNR :8165630
T-KOGR :4115
T-LRKZ ;R
T-SDKZ ;
T-EBEZ :XYZ
T-TNAME:CSAULE OUTER
====================
V-MATNR;10163
V-MATNO;DIN EN 10163
V-MATNA;St14
V-MATDI; 0.
In this case the sample ANSA_TRANSL script file has the appropriate format in order to import the
information needed from the sample vda file.
def CAD_Translate(){
SEPARATORS = ":;";
version = "A";
while(GetNextFileLine(in_line)) {
if(i = MatchString(in_line,"V-VERSI")) {
if(j = MatchSeparators(in_line(i:))) {
cur_version = GetString(in_line(j+i:));
}
}
else if(MatchString(in_line,"Modelfile:")) {
if(GetNextFileLine(in_line)) {
serial_number = GetInt(in_line(:7));
}
else break;
}
else if(!position && (i = MatchString(in_line,"T-LRKZ"))) {
if(j = MatchSeparators(in_line(i:))) position = GetString(in_line(j+i:));
}
else if(!name && (i = MatchString(in_line,"T-TNAME"))) {
if(j = MatchSeparators(in_line(i:))) name = GetString(in_line(j+i:));
}
else if(!serial_number && (i = MatchString(in_line,"T-SNR"))) {
if(j = MatchSeparators(in_line(i:))) serial_number = GetInt(in_line(j+i:));
}
else if(!model_name && (i = MatchString(in_line,"T-EBEZ"))) {
if(j = MatchSeparators(in_line(i:))) model_name = GetString(in_line(j+i:));
}
else if(!status && (i = MatchString(in_line,"D-DOALT"))) {
if(j = MatchSeparators(in_line(i:))) status = GetString(in_line(j+i:));
}
else if(version == cur_version) {
if(i = MatchString(in_line,"V-MATDI")) {
if(j = MatchSeparators(in_line(i:))) thickness = GetFloat(in_line(j+i:));
}
else if(i = MatchString(in_line,"V-MATNR")) {
if(j = MatchSeparators(in_line(i:))) material_id = GetInt(in_line(j+i:));
}
else if(i = MatchString(in_line,"V-MATNA")) {
if(j = MatchSeparators(in_line(i:))) material_name =
GetString(in_line(j+i:));
}
}
}
if(!serial_number)
{
i = MatchString(FILENAME,".");
serial_number = GetInt(FILENAME(:i-1));
}
if(!name) name = FILENAME;
if(!version) version = "A";
if(!position) position = "L";
if(!serial_number) property_id = 1;
else property_id = serial_number;
if(!model_name) model_name = "U";
if(!status) status = "U";
if(!thickness) thickness = 1.5;
if(!material_id) material_id = 1;
if(!material_name) material_name = "Default Material MAT1";
if(serial_number && !symmetry_number) symmetry_number = serial_number;
PART_NAME = name ;
PART_VERSION = version;
PART_MODEL_NAME = model_name ;
PART_ID = serial_number ;
SYMMETRY_PART_ID = symmetry_number ;
PART_PROPERTY_NAME = version%"_"%status%"_"%serial_number%"_"%position%"_"%name ;
PART_PROPERTY_ID = property_id ;
SYMMETRY_PART_PID_OFFSET= 0;
PART_PROPERTY_THICKNESS = thickness ;
PART_MATERIAL_NAME = material_name ;
PART_MATERIAL_ID = material_id ;
}
If ANSA finds the autoexec function, it will automatically execute any command that is located within,
without any further user intervention. Thus, the autoexec can be used to automate any series of
commands prior to start working with ANSA, for example to print a ‘Hello’ message followed by the
current date and time as soon as ANSA is launched.
def autoexec()
NEW("discard");
Print("Hello");
Print("Today is: "+Date());
Print("ANSA opened at "+Time());
}
Important Note: If the autoexec function exist in more than one ANSA_TRANSL files the last one will be
executed and all the others will be unloaded. A message then will be displayed in the Ansa Info window:
unloading function: autoexec, in: <path of ANSA_TRANSL that was read before the last
one>
The functions used to recognize such definitions are the MaterialVector and OrientationVector. Both
accept no arguments and return 1 on success and 0 on failure. In the following example every file that is
translated is checked whether it contains an orientation vector. In case of a missing vector a message is
written in an ANSA_TRANSL.log file.
def CAD_Translate():
orient_found = cad.OrientationVector()
if not orient_found:
fw = open("ANSA_TRANSL.log","w")
fw.write(FILENAME+" doesn’t contain an orientation
vector in the specified layer ")
fw.fclose(fw)
def CAD_Translate():
thickness = cad.MatVecThickness();
ents = base.CollectEntities(constants.NASTRAN, None, 'PSHELL')
vals = {"T":thickness, "cad_thickness":thickness}
base.SetEntityCardValues(NASTRAN,ents[0], vals)
def CAD_Translate():
status = cad.PartContainsGeometry();
if not status:
fw = open('report.txt','a')
text = FILENAME+" doesn’t contain any geometry"
fw.write(text)
fw.fclose()
The above code writes a report with all parts that don’t contain any geometric entity.
def CAD_Translate():
ents = base.CollectEntities(constants.NASTRAN, None, 'ANSAPART')
ret_vals = base.GetEntityCardValues(constants.NASTRAN,ents[0],("Comment",))
lines = ret_vals['Comment'].split("\n")
for line in lines:
m = line.split(":")
attribute_name = m[0].letters()
if attribute_name == "PartNumber":
module_id = m[1].letters()
print(module_id)
elif attribute_name=="Revision":
version = m[1].letters()
print(version)
Important Note: The function GetNextFileLine cannot read the cad files headers and attributes.
def CAD_Translate{
tp_del = list()
pshells = base.CollectEntities(constants.NASTRAN,None,"PSHELL")
for pshell in pshells:
ret_val = base.GetEntityCardValues(constants.NASTRAN,pshell,("Name",))
if ret_val['Name'] == "Bolts" or et_val['Name'] == "Auxiliaries":
to_del.append(pshell)
base.DeleteEntity(to_del,1)
def CAD_Translate:
fid = cad.TranslatorLogFile()
pshells = base.CollectEntities(constants.NASTRAN,None,"PSHELL")
no_pshells = str(len(pshells))
fid.write("The file contains "+no_pshells+" of PSHELL properties")
The above code appends in the end of the log file a message regarding the number of the created
PSHELL properties.
def CAD_Translate:
args = utils.ProgramArguments()
for arg in args:
if arg.find("skin"))
base.Skin(1,0,3,1,0,0,5)
elif arg.find("link"):
base.OffsetLink("0.5")
9. BCGUI Functions
9.1 What is BCGUI
BCGUI (BETA C interface Graphical User Interface ) is a powerful and versatile library of GUI functions. It
is meant to help script users build windows that consist of any type of graphical interface, like lineEdits,
comboBoxes, checkBoxes, Lists etc, in order to interact faster and easier with ANSA entities.
BCLineEdit
Provides a one-line text editor.
BCCheckBox
Provides an option box with a text label on the right.
BCComboBox
It is a combination of a 'BCPushButton', a 'BCLineEdit' and
a 'BCPopupMenu'.
BCPushButton
It is a button that can perform an action on click or on toggle.
BCFrame
The 'BCFrame' class provides a flexible visual box which can obtain several shadow styles and
accommodate other widgets. A layout must be set in a 'BCFrame' since they do not have one by default.
For placing widgets inside, vertically or horizontally, use functions BCVBoxCreate or BCHBoxCreate
respectively.
BCLabel
Provides text or image display.
BCLabelTicker
Provides an auto-scrolling label
BCSpinBox
Provides a widget that allows the user to choose a value either by clicking the up/down buttons to
increase/decrease the value currently displayed or by typing the value directly into it.
BCSeparator
Creates a thin line to separate widgets.
BCSlider
Provides a vertical or horizontal widget for controlling a bounded value. It lets the user move a slider
along a horizontal or vertical groove and translates the slider's position into an integer value within the
legal range.
BCStatusBar
Provides a horizontal bar suitable for presenting status information.
BCToolBox
BCLabel BCSpinBox
Provides a column of tabbed widget items. It displays a column of tabs one above the other, with the
BCFrame
BCSeparator
BCFrame
BCSlider
BCStatusBar
current item displayed below the current tab. Every tab has an index position within the column of tabs. A
tab's item is a widget (e.g. a 'BCFrame').
BCDrawerGrid
It is a widget that can accommodate other widgets and manage their visibility.
BCButtonGroup
Provides a box frame with a title at the top. 'BCPushButtons', 'BCToolButtons', 'BCRadioButtons' and
'BCCheckBoxes' can be inserted. These widgets can be arranged vertically or horizontally.
BCRadioButton
Provides a two-state button with a text label, that can be switched on (checked) or off (unchecked). Radio
buttons when grouped, provide a "one of many" choice.
BCDialogButtonBox
It is a widget that automatically adds to itself an 'Ok' and a 'Cancel' 'BCPushButton' when it is created.
This is the recommended way to create the 'Ok' and 'Cancel' buttons since they are automatically
connected to the accept and reject functions of the 'BCWindow'.
BCDrawerGrid
opened
BCRadioButton
BCButtonGroup
BCDrawerGrid closed
BCToolBox
BCDialogButtonBox
The same 'BCWindow' with the 'BCDrawerGrid' open, showing the 'BCPushButton' it holds.
BCToolButton
Performs an action on press, on click or on toggle. Unlike 'BCPushButtons', they tend to occupy all
available space and they have a different look and feel. They are also ideal to be used with other widgets,
like 'BCButtonLineEdits', 'BCButtonComboBoxes', 'BCListViews' etc.
BCButtonLineEdit
Provides a one-line text editor that can hold buttons to its left or to its right.
BCCalculator
This class consists of a function set that create and manage a calculator window. It can be easily
combined with a 'BCButtonLineEdit' by inserting a 'toolButton' which provides a calculator when pressed.
The calculator's output can be sent back to the 'BCButtonLineEdit' by pressing the '->' calculator's button
(see the images below).
BCButtonComboBox
The 'BCButtonComboBox' can be seen as a combination of a 'BCComboBox' and a 'BCButtonLineEdit'. It
has the advantage that one or many buttons can be displayeComboVal_d left or right of its 'lineEdit'.
BCWidgetStack
Provides a stack of widgets of which only one (the top most) is visible at any time.
BCSplitter
Provides a splitter widget that lets the user control the size of child widgets by dragging the boundary
between the children.
In the following image a 'BCSplitter' separates a 'BCListView' from a 'BCWidgetStack'. The selection of a
'BCListViewItem' from the 'BCListView' raises a different 'BCFrame' (i.e. widget) on the widget area.
BCTabWidget
Provides a 'tabBar' of tabs and a 'page area' below the tabs. Each tab is associated with a different page.
Only the current tab's page is shown in the page area; all the other tabs' pages are hidden.
BCTextEdit
Provides a powerful single-page rich text editor. 'BCTextEdit' by default allows undo/redo history to be
kept while some other word processing attributes (for example <Ctrl+C> for copy, <Ctrl+V> for paste). It
works on paragraphs and characters. A paragraph is a formatted string which is word-wrapped to fit into
the width of the widget. By default when reading plain text, one newline signify a paragraph. A document
consists of zero or more paragraphs, indexed from 0. Characters are indexed on a per-paragraph basis,
also indexed from 0.
BCTextBrowser
Provides a BCTextEdit with hypertext navigation.
In the image below a 'BCTabWidget' with 2 tabs was inserted in a 'BCWidgetStack'. Each tab holds a
'BCTextEdit'.
BCTable
The BCTable class provides a flexible editable (spreadsheet-like) table widget. In 'BCTable's' other
widgets can be inserted as well.
BCPopupMenu
Provides a pull down menu of choices.
A 'BCTable' has a vertical and a horizontal header. Rows and columns can be selected through the
headers.
BCListView
It implements a list/tree view. It can display and control a hierarchy of multi-column items, and provides
the ability to add new items at any time.
BCListViewInfoBox
It is a 'BCFrame' placed at the bottom of a 'BCListView' providing information about the total and the
selected items of a 'BCListView', as well as custom texts.
BCWidgetExpand
It is a widget used to save space in forms. Use this class to provide expansion functionality to the widgets
without having to resize the parent window. The class is simple to use and really useful in widgets
applying a scroll bar (such as 'BCListViews' or 'BCTextEdits'). Drag the mouse towards the direction
where the widget must be expanded, while holding 'Shift' and middle mouse button. The widget remains
expanded while the mouse cursor is inside it.
BCLineEditPath
It is a 'BCFrame' containing a 'BCComboBox' with the more recent paths used, a 'BCToolButton' for
browsing files and another 'BCToolButton' for clearing the history. These paths will be available any time
ANSA is used. The history-box frame can be a 'files', 'folders' or 'everything' type and it can be used with
'open' or 'save as' mode.
BCTimer
The 'BCTimer' provides timer signals and single-shot timers.
BCProgressBar
It is used to give the user an indication of the progress of an operation and to reassure them that the
application is still running.
BCGridLayout
The 'BCGridLayout' class lays out widgets in a grid. It takes the space made available to it (by its parent
layout or widget), divides it up into rows and columns, and puts each widget it manages into the correct
cell.
Layouts are used to define the widgets' placement inside a 'BCWindow'. A 'BCWindow' has by default a
'BCBoxLayout' with a vertical orientation (red lines). This means that all children of the 'BCWindow' or its
'BCBoxLayout' will be placed one below the other, according to the order they have been created. In the
following example, children can be either widgets (the 'Ok' and 'Cancel' BCPushButtons) or other layouts
(the horizontal 'BCBoxLayout' and the 'BCGridLayout').
9.2.3 Items
BCSpacer
Provides a blank space in a layout. It can be extended to all directions, according to the default
parameters.
w = guitk.BCWindowCreate()
le = guitk.BCLineEditCreate(w) #le has parent w
f = guitk.BCFrameCreate(w) #f has parent w and placed below le
l = guitk.BCBoxLayoutCreate(f) #l has parent f
b1 = guitk.BCPushButtonCreate(l) #b1 has parent l
b2 = guitk.BCPushButtonCreate(l) #b2 has parent l and will be placed next
#to or below b1, according l's orientation.
w = guitk.BCWindowCreate()
horizontal = guitk.BCBoxLayoutCreate(w) #horizontal layout is the 1st child
guitk.BCLabelCreate(horizontal) #label belongs to horizontal
guitk.BCLineEdit(horizontal) #lineEdit is horizontal's 2nd child
grid = guitk.BCGridLayout(w) #grid layout is placed below horizontal
for row in range(3):
for col in range(3):
but = guitkBCPushButtonCreate(grid) #Create button at (row, col)
BCGUI functions were built in a way to be immediately comprehensible, even by beginner users.
Help for all BCGUI functions (prototype, arguments, operation etc.) can be found in script editor's help.
The name of a BCGUI function consists of the class it belongs to (e.g. BCLineEdit) plus the action
performed on an object of this class (e.g. SetText). Thus, the function name is BCLineEditSetText.
If a function does not begin with a class name, it means that it is a general function, applicable to all
widgets and layouts (not items). For example BCName function returns the name that may have been set
to a widget or layout by the BCSetName.
Also in case of 'BCPushButtons' and 'BCToolButtons' there are many BCButton... functions, applicable to
both classes of buttons.
Generally, the first argument of functions is the widget, layout on which an action will be performed, or its
parent in case of BC...Create functions.
def main():
w = guitk.BCWindowCreate('Simple BCWindow', guitk.constants.BCOnExitDestroy)
le = guitk.BCLineEditCreate(w, 'This is a lineEdit')
f = guitk.BCFrameCreate(w)
l = guitk.BCBoxLayoutCreate(f, guitk.constants.BCHorizontal)
b1 = guitk.BCPushButtonCreate(l, "Button 1", None, 0)
b2 = guitk.BCPushButtonCreate(l, "Button 2", None, 0)
guitk.BCShow(w)
In order for a widget to be displayed, BCShow must be called for it. This will trigger a recursive call for the
widget's children as well. In the example above, only one BCShow call for 'BCWindow' 'w' is enough to
show everything that it contains. The 'BCOnExitDestroy' option used in 'BCWindowCreate' means that
when the window closes (by pressing escape <esc>, return or the[x] button) it will be destroyed. The
other available option is the 'BCOnExitHide' but it is strongly recommended to avoid using it, since a
wrong usage may lead to memory leaks.
Note that a 'BCWindow' is good to have a unique name. Any information about the window (e.g size,
position, values of its widgets etc) will be stored in ANSA.xml under this name. However, it must not be
confused with the name of the title bar that can be always changed by using the BCSetCaption.
def main():
w = guitk.BCWindowCreate('Sqrt calculation', guitk.constants.BCOnExitDestroy)
grid = guitk.BCGridLayoutCreate(w, 2, 2)
input = guitk.BCLineEditCreateDouble(grid, 0)
guitk.BCGridLayoutAddWidget(grid, input, 0, 0,
guitk.constants.BCAlignLeft+guitk.constants.BCAlignVCenter)
output = guitk.BCLineEditCreateDouble(grid, 0)
guitk.BCGridLayoutAddWidget(grid, output, 1, 0,
guitk.constants.BCAlignLeft+guitk.constants.BCAlignVCenter)
//Alignment enumerators OR'ed together
guitk.BCLineEditSetReadOnly(output, 1);
Keep in mind that it is not allowed to pass directly a matrix with its contents to a callback, e.g.:
Important Note: Any changes of the user argument of callbacks can be known to the 'main' function if the
datatype of the argument is defined with the 'byref' statement.
def calculateEquation(data):
#Retrieving widgets from BCWindow w (==data)
input = guitk.BCGetUserDataKey(data, "input")
sp1 = guitk.BCGetUserDataKey(data, "sp1")
sp2 = guitk.BCGetUserDataKey(data, "sp2")
lab = guitk.BCGetUserDataKey(data, "lab")
output = guitk.BCGetUserDataKey(data, "output")
#Calculation
d = guitk.BCLineEditGetDouble(input);
if d == 0: return
i_1 = guitk.BCSpinBoxGetInt(sp1)
i_2 = guitk.BCSpinBoxGetInt(sp2)
result = math.power(d, i_1) * math.exp(i_2) / math.log(d)
//Show result
guitk.BCLabelSetText(lab, d)
guitk.BCLineEditSetDouble(output, result)
calculateEquation(data)
return 0
def main():
w = guitk.BCWindowCreate("Equation calculation", guitk.constants.BCOnExitDestroy)
l1 = guitk.BCBoxLayoutCreate(w, guitk.constants.BCHorizontal)
input = guitk.constants.BCLineEditCreateDouble(l1, 0)
guitk.BCLineEditSetDouble(input, 1)
guitk.BCLabelCreate(l1, " ^ ")
sp1 = guitk.BCSpinBoxCreate(l1)
guitk.BCSpinBoxSetMinValue(sp1, 2)
guitk.BCSpinBoxSetMaxValue(sp1, 15)
guitk.BCLabelCreate(l1, " * e ^ ")
sp2 = guitk.BCSpinBoxCreate(l1)
guitk.BCSpinBoxSetMinValue(sp2, 1)
guitk.BCSpinBoxSetMaxValue(sp2, 10)
guitk.BCLabelCreate(l1, " / log(")
lab = guitk.BCLabelCreate(l1, guitk.BCLineEditGetText(input))
guitk.BCLabelCreate(l1, ")")
guitk.BCSpacerCreate(w)
l2 = guitk.BCBoxLayoutCreate(w, BCHorizontal)
output = guitk.BCLineEditCreateDouble(l2, 0)
guitk.BCLineEditSetReadOnly(output, 1)
butPrint = guitk.BCPushButtonCreate(l2, None, printFun, w) #You can also set
#the widget before the data assignment
guitk.BCButtonSetPixmapFile(butPrint, "print_16.png")
guitk.BCSpacerCreate(l2) #Horizontal spacer. Keeps output and butPrint to the left
guitk.BCSpinBoxSetValueChangedFunction(sp1, spinBoxChangedFun, w)
guitk.BCSpinBoxSetValueChangedFunction(sp2, spinBoxChangedFun, w)
guitk.BCLineEditSetTextChangeFunction(input,lineEditChangedFun, w)
guitk.BCDialogButtonBoxCreate(w)
guitk.BCShow(w)
Elements visibility
Color
PID
Name
Element number
MID
FROZEN_ID
LINE_EDIT_PATH_ID = 0
PROGRESS_BAR_ID = 1
pshell = guitk.BCListViewItemGetUserData(item);
v = None
for ent in shells:
v += IsEntityVisible(ent)
if v: v = 1
base.BCCheckListItemSetOn(item, v)
base.BCListViewItemSetRectangleColor(item, COLOR_COL, ret['color_r'],
ret['color_g'],
ret['color_b'])
base.BCListViewItemSetText(item, PID_COL, ret['PID'])
base.BCListViewItemSetText(item, NAME_COL, ret['Name'])
base.BCListViewItemSetText(item, ELEMS_COL, num)
base.BCListViewItemSetText(item, MID_COL, ret['MID'])
base.BCListViewItemSetText(item, FROZEN_COL, ret['FROZEN_ID'])
base.BCListViewFilterUpdateComboBox(list, FROZEN_COL)
def destroyItem(item):
#Just delete the item, not the PSHELL itself.
BCListViewItemDestroy(item)
return 0
pshell = guitk.BCListViewItemGetUserData(item)
base.EditEntity(pshell)
updateItem(list, item) #Update item after a possible editing.
return 1
search_type[ = ("PSHELL",)
pshells = CollectEntities(NASTRAN, None, search_type, False)
BCProgressBarSetTotalSteps(pb, len(pshells))
search_type = ("FACE", "SHELL")
rename = (0, 0, 0, 3, 0, 2, 0)
for pshell in pshells:
if v: v = 1
#Update progressBar
current = base.BCProgressBarProgress(pb)
base.BCProgressBarSetProgress(pb, current+1)
base.BCCheckListItemSetOn(item, v)
base.BCCheckListItemSetStateChangedFunction(item, checkButtonPressedFun, 0)
i += 1
base.BCListViewFilterUpdateComboBox(list, FROZEN_COL)
base.BCWidgetStackRaiseId(ws, LINE_EDIT_PATH_ID)
base.SetCurrentDeck(constants.NASTRAN)
w = guitk.BCWindowCreate("PIDs list", guitk.constants.BCOnExitDestroy)
#Setting BCLineEditPath
combo = guitk.BCLineEditPathGetCombo(lep);
guitk.BCComboBoxSetSizePolicy(combo, guitk.constants.BCExpanding,
guitk.constants.BCExpanding) //You can resize lep to minimum
le = guitk.BCComboBoxGetLineEdit(combo);
guitk.BCLineEditSetExtentionsFilter(le, ("ansa",)) #Show only *.ansa files
#The file selected by file manager will update the list, as well
guitk.BCLineEditPathSetDialogEnterEnabled(lep, 1)
guitk.BCLineEditPathSetEnterPressedFunction(lep, "onEnterFun", list)
ddb = guitk.BCDialogButtonBoxCreate(w)
clear = guitk.BCPushButtonCreate(ddb, "Clear list", clearListFun, list)
guitk.BCDialogButtonBoxAddButton(ddb, clear)
guitk.BCShow(w)
On script run the 'BCWindow' containing the 'BCListView' and other widgets is created, showing the
PSHELLs of the current database. It is then docked by the user to the left docking area and resized to
minimum width in order to save space for the drawing area. The use of 'BCWidgetExpand' tool is shown
here:
After 'Enter' was pressed the MID changed back to its original value and a warning appeared in the
'BCListViewInfoBox'.
The PSHELL card appears on double-click and the FROZEN_ID value is changed to 'YES'.
When the current tab changes, the 'BCCaption' of 'BCWindow' (the title) changes as well to the tab's
label. Nevertheless, its 'BCName' ('AutoSavingSettings') must never change and it must be unique, i.e. no
other window with the same 'BCName' should exist in ANSA. The reason for this is that all settings are
saved to xml under this name.
A control has been set for closing 'BCWindow's' when pressing 'Enter'. Normally, a window closes on
'Enter' unless a BCWindowSetCheckFunction or a BCWindowSetAcceptFunction are set. In this case
the first one must be used, and the 'BCWindow's' exit is controlled by the current value of the 'BCSpinBox'
found in the “Red frame”. If it is higher than 6, a warning appears in ANSA Info , the 'BCWindow' flashes
and stays open.
Initially, the 'BCComboBox' in the “Green frame” has 3 options: 'All', 'None' and 'Write Protected'. The first
2 operate as normal 'comboBox' options. If the last is selected a 'BCPopupMenu' appears containing a
hierarchical 'BCListView' and a 'BCPushButton' at the bottom. In this way any options offered by a
'BCComboBox' can be refined to the finest detail.
for i in range(num):
lvitem = guitk.BCListViewAddItem(lview, 1, iName, rename)
guitk.BCListViewItemAddItem(lvitem, 1, iName, rename)
#'Blue frame'
#Check out the widget setting to a BCDrawerGridCreate
drawer = guitk.BCDrawerGridCreate(blueFrame)
checkFrame = guitk.BCFrameCreate(drawer)
guitk.BCBoxLayoutCreate(checkFrame, guitk.constants,BCHorizontal)
checkBoxA = guitk.BCCheckBoxCreate(checkFrame, "CheckBox A")
checkBoxB = guitk.BCCheckBoxCreate(checkFrame, "CheckBox B")
checkBoxC = guitk.BCCheckBoxCreate(checkFrame, "CheckBox C")
bgroup = guitk.BCButtonGroupCreate(drawer, "Exclusive Radios",
guitk.constants.BCVertical)
guitk.BCButtonGroupSetCheckable(bgroup, 1)
for i in range(numButtons):
ii = i + 1
name = "RadioButton " + str(ii)
rb = guitk.BCRadioButtonCreate(bgroup, name, "", 0)
guitk.BCRadioButtonSetPressFunction(rb, "", 0)
guitk.BCButtonGroupInsert(bgroup, rb, i)
guitk.BCButtonGroupSetPressedFunction(bgroup, "radioButtonGroupPressed", 0)
buttonFrame = guitk.BCFrameCreate(drawer)
guitk.BCBoxLayoutCreate(buttonFrame, guitk.constants.BCHorizontal)
toggleButton1 = guitk.BCPushButtonCreate(buttonFrame, "toggleButton1", "", 0)
guitk.BCRadioButtonAddManagedWidget(rb, toggleButton1, BCManagedShow,
BCManagedHide)
toggleButton2 = guitk.BCToolButtonCreate(buttonFrame, "filter_16.png",
"toggleButton2", "", 0)
guitk.BCButtonSetToggleButton(toggleButton1, 1)
guitk.BCDrawerGridInsertWidget(drawer, checkFrame, 1, "CheckBoxes")
guitk.BCDrawerGridInsertStableWidget(drawer, bgroup)
guitk.BCDrawerGridInsertWidget(drawer, buttonFrame, 1, "Buttons")
#'Red frame'
guitk.BCLabelCreate(redFrame, "Degrees");
spin = guitk.BCSpinBoxCreate(redFrame);
guitk.BCSetUserDataKey(window, "spin", spin);
#'Green frame'
guitk.BCLabelCreate(greenFrame, "Include Files")
combo = guitk.BCComboBoxCreate(greenFrame, comboVals)
guitk.BCComboBoxSetActivatedFunction(combo, "comboActFun", 0)
guitk.BCTextEditCreate(vb2, "")
guitk.BCLabelTickerCreate(vb2, "BCTicker has the ability to scroll from left to
right if the text can not fit in the widget`s width.
User can also scroll left or right by pressing (and keep pressed) the left mouse
button and moving the cursor right or left.")
def main():
window = guitk.BCWindowCreate("AutoSavingSettings",
guitk.constants.BCOnExitDestroy)
Every time a new script is imported, a new tab having the name of the script is added in the main
window. There is no restriction regarding how many scripts can be remained opened simultaneously.
By default, if the script contains a function called 'main', then every time the F5 button is pressed this
particular function is executed. However, if the user add the keyword entrypoint in front of the def
statement of a function, then this function becomes stronger than 'main' and it will be finally executed if
the F5 will be pressed.
In the most general case, any function regardless of its name, can be executed through the Debug>Run
function which acts similar to File>Script>Run function (see section 5.2.1). Any syntax errors are
reported in the output area.
spots = CollectEntities(NASTRAN,0,"SpotweldPoint_Type");
Print(MatLen(spots));
Instead of
def fun_name()
{
spots = CollectEntities(NASTRAN,0,"SpotweldPoint_Type");
Print(MatLen(spots));
}
Important Note: Scripts made in the immediate environment can be executed normally.
In the above example, the Dynamic help recognized the CollectEntities and therefore the necessary
parameters were displayed according to their precedence. An arrow on the left of every parameter
indicates which argument must be written next.
Important Note 1: Pressing F1 while the cursor is pointing on a built in function name (written in the main
window), the respective help text is displayed in the Output Area.
Important Note 2: A color code indicates the built in commands and the reserved keywords.
Important Note 1: A compiled script can be used as projectfile but not as include file.
Important Note 2: Scripts can be compiled normally even if they contain #include or #projectfile
statements.
Automatically, the selected code goes to the code section of the window where the user can further edit it.
Moreover, a snippet is distinguished from its name and it is stored either in an ANSA or a META snippets
list. By default the ANSA tab is active. A snippet can be imported from the Tools>Code snippets option
of the main menu. This function opens the previous window where the user can select a snippet from the
available list on the left. Selecting it and pressing the Import button, the respective code is inserted into
the main window at the cursor position.
After pressing ok, a file named ANSA_TRANSL.bpr is created in the selected folder. This is the project
file and initially has the following form:
Two categories can been seen in the above picture. The category Include files can host auxiliary files
that are added normally in the project file but are not incorporated in the ‘main’ script. The Source files
are the basic files that will be referenced either in the project file or in the ‘main’ script.
From the File manager that opens, select one or more scripts to add. After selection the project structure
will be as following:
An added file can be accessed if double click on it with left mouse button. As soon as the file is selected,
its content is displayed in the main window where can be viewed or edited. Press the Project>Save
project to update the xml project file and next edit the file to see the changes:
Suppose that some of these files use include files that the user would like also to add in the project. This
can be done if right click on the respective option and select Add existing include. Again, the File
manager opens and waits for files selection. The selected file is added under the Include files category:
To update the xml project file press again the Project>Save project.
Select the Empty script option and press Ok (If the right window is opened activate the extra option). A
new source file is added with initial name 'Untitled new file' and a new empty file is created in main
window. Write the new script and press the save file button
Name the file and select the directory where it will be saved. Automatically, the initial file path is updated.
The source files were added in the main script using the #projectfile statement. As mentioned before, no
include file was added in the main ‘script’.
In the above example the cursor is pointing on variable b and therefore when selecting on the menu that
opens the option Add watch: main::b, b is added in the watch list. This list can be displayed pressing the
button or through the View>Watch window of the main menu.
This window displays also the variable name, the function where it belongs, its type (local or global) and
the current value.
Finally, the lines where the execution of the script will be paused must be selected. After each stop any
change of the variable can be viewed in the list. Consequently, it is recommended the lines that are
selected to be just before or after the variable definition. For letting the editor to distinguish these lines,
breakpoints are inserted to them. Having the cursor on a line and pressing the button inserts a
breakpoint. On the other hand pressing the button deletes a breakpoint. Whenever a breakpoint is
inserted, the respective line is colored red.
For running the function in debug mode the button must be pressed. Alternatively, press {Shift+F5}
or Debug>Debug.
Suppose that any changes of matrix b'. must be traced. Insert a breakpoint in line 5 and open the watch
window. Press <Shift+F5> to run in debug mode. The execution stops in line 5 and the current status of
'b' is displayed in watch window. From now on every time the button or <F10> is pressed, the
execution continues and stops in each line. Pressing anytime the button , the script runs without stop until
the end. In the example, after the second stop the matrix 'b' holds the first two values {10,13}.
Important Note: When the execution stops over a breakpoint, the line is colored blue.
If the 'watched' variable is not in the "main" function but in a sub function, the debugger cannot reach it
unless the way that searches the code is changed. This can be achieved through the buttons and
. The first instructs the execution sequence to step into a sub function, while the second to step out of
a sub function. Let’s see it with an example:
Assume that the 'watched' variable 'k' is located in sub function 'foo'. Set a breakpoint in a line prior to
'foo' call (line 6) and press <Shift+F5>. The execution stops in this line and from that point press the
button until the debugger gets inside 'foo'.
ToolBox
This is the window that hosts all the functions for creating widgets, layouts or items.
Parameters
This window displays all the parameters related to the selected item of the List with Constructed Items
window.
CallBack Functions
This is the window where it hosts all created callback functions.
Source Code
This is the area where the automatically created code resides.
Help
This is the area where the help text of the selected parameter is displayed.
11.2.1 ToolBox
The ToolBox is the starting point of all actions performed in designer. It hosts in separate tabs all the
necessary functions for creating the main window, buttons, containers, views, widgets and input items.
Initially, only the Window tab is active since this will create the window that will be used as the parent of
all features. Expand the Window tree and press the Apply Settings button to create the main window
with the name 'TopWindow'.
Expanding any object under any category will reveal a set of basic options necessary for the creation of
the object. These options are actually the input arguments of a BCGUI function and thus they are
characterized by their type (integer, string, element etc) and their value. The options initially have the
default values but they can be also set up by the user, except those that are of element type. The button
Apply Settings always creates the object. In the following example a button and a check box have been
created under the top window.
The parent object controls the objects' order. As it is shown above, any object that is added directly to the
top window is distributed vertically. To control the order create a predefined horizontal HBox or a vertical
box layout VBox, or a BoxLayout with controllable orientation and add the two widgets within.
Actions like drug and drop are allowed and thus the position of an object can be altered any time.
Pressing on an object of the list, highlights with yellow the corresponding object of the TopWindow. On
the contrary, pressing <Ctrl+Left mouse button> over an object of the TopWindow, highlights the object
on the list.
Any object can be deleted either pressing the Delete button of the keyboard or with the Delete Item
option under the right mouse button
In order to change the default parameter options, expand the parameter and type where it is allowed the
new value. At the end, press the Apply Settings button to confirm the changes. In the following image, a
tooltip is going to be added for the button 'BCPushButton_1'. Select the button object from the List With
Constructed Items or from the screen and type the tooltip text under the Values column of the tip
parameter. After confirmation, place the cursor over the button to see the tooltip.
11.2.4 Parameters
The Parameters window lists all the unique options of a selected object. As soon as an object is selected
either from the screen or from the List With Constructed Items, the title of the Parameters window and
the actual parameters change accordingly. The picture below shows the Parameters window when the
check box is selected. The name and the input arguments of the parameters are displayed in two
separate columns.
Two callbacks of different type have been filtered. The user can change any option according to his
needs. When the Apply Settings button is pressed the callback type and its name automatically are
listed under the CallBack window. The title of the window indicates the parent object type:
The last argument of all callback functions can be of any type and corresponds to user data.
The help text of functions that set up callbacks, contain also the syntax of the callback. Thus, the user is
also informed about the input arguments and the return values of it.
The source code is not editable and changes automatically only when an action is performed or when an
object is deleted. However, it can be totally cleared without destroying the created window through the
Code>Clear Source Code. The next time an action will be performed, the source code will be again
generated.
Replace the 'add_function_name' with 'main' and run the code in order to launch the created interface.
Important Note: The designer cannot be used for opening scripts unless it is free of user defined code.