META Automation Users Guide
META Automation Users Guide
User’s Guide
META Post Processor Automation User’s Guide
The META Automation User's Guide is an integral part of the META software.
This User's Guide, in whole or in part, may not be copied, reproduced, translated, transferred, or
reduced to any form, including electronic medium or machine-readable form, or transmitted or
publicly performed by any means, electronic or otherwise, unless BETA CAE Systems consents in
writing in advance.
Use of the software and its documentation has been provided under a software license agreement.
BETA CAE Systems assumes no responsibility or liability for any damages or data loss caused by
installation or use of the software.
Information described in this documentation is furnished for information only, is subject to change
without notice, and should not be construed as a commitment by BETA CAE Systems. BETA CAE
Systems assumes no responsibility or liability for any errors or inaccuracies that may appear in this
manual.
The software and its documentation contain valuable trade secrets and proprietary information and
are protected by copyright laws. Unauthorized use of the software or its documentation can result in
civil damages and criminal prosecution.
All other company and product names, mentioned in the software and its documentation, are
property, trademarks or registered trademarks of their respective owners.
This User's Guide serves as a reference of the automation abilities and interface of META,
presenting an outline of used functions for viewing results with META.
If you have any questions about this User‟s Guide, or would like to contribute by reporting errors or
omissions you have found in it, please contact BETA CAE Systems at: [email protected].
1. Introduction
META offers a variety of tools and functions for automating the post-processing. The most
important of them are:
- Variables
- Built-in Functions
- Session files
- Scripting language
- User Toolbars
Variables store static, dynamic or string values. They are used to communicate these data between
different tools but they can also be used in commands, in sessions and in scripting language. For
more information check APPENDIX VARIABLES
Built-in Functions are expressions which can return different types of values like field or curve data
for specified entities, results or states. The Built-in Functions can be used to fill variables, as
arguments in the Adv. Filter and in scripting language. For more information check APPENDIX
Build in functions.
Session files are text files containing a series of META commands. When executed, each
command is applied sequentially. For more information check Session Files chapter.
Scripting is C-like programming language which can be used for advanced automation procedures.
Scripts can run as standalone files or used inside session files and user toolbars. Through scripts it
is easier to create and handle conditional statements, store in the memory tabular data and apply
complex procedures. It is also possible to create custom windows. For more information check
Scipting chapter
User Toolbars are custom toolbars designed to hold custom functionality. They can contain widgets
like buttons, textboxes, checkboxes etc. Commands, whole sessions or scripts can be assigned
and applied when each widget is used. For more information check Toolbar Designer
2.1. Introduction
Session files (or Sessions) are text files containing a series of META commands. When executed,
each command is applied sequentially.
An example of a session file follows:
2.2. Syntax
2.2.1. General
Lines Each line must contain one META command.
Comments A line can be commented out by adding the # or $ characters in the beginning.
Variables Variables can be used in the place of names, values or parameters by adding
the $ character in front of the variable name. For example:
options state $full_load
If necessary, the variable name must be added inside the { and } characters
to declare when the variable‟s name ends. For example:
write png ${model_name}_top_view.png
Arguments Argument parameters can be used in session files when executing a session
with the -s running option.
They are denoted within the session with the $ character followed by an
integer.
For example:
When executing a session with the system command:
meta_post64.sh –s reforces.ses file.op2 Rotational
and the session contains the line:
read fun Nastran /home/user/$0 all SPCForces, $1
The $0 will be replaced by file.op2 and the $1 by Rotational
Remarks
Counting arguments starts from 0.
Arguments must be separated with space.
If the string of an argument contains a space character, then it is mandatory to
enclose is in double quotes “”.
Disable redraw Add the ! character in front of a line to disable screen redraw when executing
the command. This results to faster execution time.
Remarks
To disable redraw during all session or for more lines, use the commands:
options session controldraw disable
options session controldraw enable
Relative Paths Paths written in a session can be relative. A relative path has the
following syntax:
-Folder1
-Folder1_1 ./FolderIn_1/file.extension
-Folder1_2 ../FolderOut_1/file.extension, ../../Folder1/file.extension
- FolderOut Relative paths in a session indicate to the current directory.
-Current_Directory
As current directory is considered:
-FolderIn_1
-FolderIn_2 - The session‟s directory
-FolderOut_1 - The META_CUR_DIR, the directory form where META is launched
-FolderOut_2 In case the file is not found in the session‟s directory, META search in
the META_CUR_DIR.
Example 1
A dialog opens asking to enter the value 1 or 2 representing the top or bottom view respectively.
The session checks the input and applies the respective view or posts a warning if the input is not
correct. In this case the dialog opens again.
#:start
options var valuelbltext value Give_View_(1=TOP, 2=BOTTOM)
options var view “$value”
#if $view==1
view default top
#goto end
#elseif $view==2
view default bottom
#goto end
#endif
options var view 0
options warning value should be 1 or 2
#goto start
#:end
Example 2
Multiple snapshots of the model are stored into the current directory. The session waits for manual
change of view. When the Enter button is pressed, a picture is saved. A dialog opens asking for
numerical input 1 or 0 representing the option Yes or No. Depending on the input, more pictures
can be taken:
options var root ${META_CUR_DIR}
options message Your snapshot will be stored in $root directory
options var file_name 1
#:start
options session wait select your snapshot view and press ENTER
write tif "$root/$file_name.tif" 0
options var valuelbltext cont Continue with Snapshots (Y-1/N-0)?
#if $cont==1
options var file_name "$file_name+1"
#goto start
#endif
2.3. Settings
The following settings can be found in Global Settings > General of the Settings card.
Pause execution on error The session pauses when a command is not executed correctly.
User action is needed to continue execution.
Session decoding unicode Decode ASCII files as Unicode; otherwise the file is decoded
according to the local settings.
Note that the language environmental variable should also be set,
e.g.: setenv LANG POSIX
Through the options session... command it is possible to set the behavior of a session while
running. The most useful commands are:
options session controldraw push Save the current status of the controldraw
command.
options session controldraw pop Returns to the saved status of the controldraw
command.
options session sleep <ms value> Session‟s execution stops for a period of
milliseconds, equal to the value which is set.
2.5.1. Interface
The Session Editor is a complete tool to create, open, edit, run and debug sessions.
The Session Editor window can be invoked through:
Tools > Session Editor from the Main Toolbar.
Editor
Main menu Contains functions distributed under the File, Edit, Project, Tools, Script,
Windows and View drop down menus.
Toolbars Contains buttons distributed under the Files Options, Edit Options, Project and
Tools toolbars.
Editor This is the text area where the session is written or tested. Every open session
file is located under a separate tab. The asterisk next of the session name on
tab label declares an unsaved session.
Output window Displays information (statistics, errors and warnings) of the session.
Set Parameters Contains functions for handling the parameters and also for creating variables.
window
Remarks
- All the windows inside the Meta Session Editor are totally customizable as all the other windows in
META. They can be moved, resized and docked.
File
Open The file manager opens to browse a session file (i.e. *.ses). A new
tab, having the name of the session, is added in the main window.
There is no restriction regarding how many sessions can be
remained opened simultaneously.
Open Current Session Open the current session from the META_post.ses file.
Run Compressed Package Load and run a compressed package. A package is a group of files
in a folder that contains all the necessary files in order to run a
session (see 2.5.8. Create package, pg.22).
Project
Insert Breakpoint Insert a breakpoint at current line. Breakpoints can be used to stop
execution of session while debugging.
Debug Run and pause the session execution when a breakpoint is met.
Press the Enter key to continue execution line by line.
Tools
Check Session For Errors Searches the session file and displays in the Output window warning
and error messages for anything found not according to the rules of a
session file.
By double clicking on a message the corresponding line in the
session will be highlighted in the session. Pressing Ctrl+> or Ctr+<
keys the cursor will navigate to the next or previous position of the
session referred to by an error or warning.
Create User Toolbar Automatically create a User Toolbar from all or selected lines (see
2.5.9. Create User Toolbar,pg.24).
Snippets Open the Snippets tool. Snippets are parts of code that can be saved
for use on other parts of the same or of a different script or session
(see 2.5.10. Snippets, pg.25).
Create Package Open the Create Package window. A package is a group of files in a
folder that contains all the necessary files in order to run a session
(see 2.5.8. Create package, pg.22).
Suppress Redundant Keep only the last command when a series of the same commands
Commands are applied. The function is applied only on commands which when
removed, the final state will not be altered.
When a session is recorded from it might contain many unnecessary
commands making it hard to use or edit and slowing down its
execution.
An example is a series of commands that change the view of the FE
model, only the last one is necessary.
Command Description Get information about the syntax of the command of the selected
line and also suggestions about correction of a syntax fault.
Script
Write Script Add in the session text the required keywords that enable the
insertion of Python / BETA scripting language within the session,
e.g.:
#!script
#include "meta_structs"
def main()
{
//type your code here
}
#!EOF
(see 4. Scripting, pg.65).
Smart Check Lines inside session that seems to be BETA scripting code lines are
identified. The indicator #!script line can be added before a
script starts.
View
Options Invoke the options card to set up the General Options and Colors.
An empty, named Untitled.ses, session file is created. A new tab in the main
window area is added.
The file manager opens to browse a session file (i.e. *.ses). A new tab, having
the name of the session, is added in the main window. There is no restriction
regarding how many sessions can be remained opened simultaneously.
Functions Cut, Copy and Paste can be applied in session text within and between
windows.
The Find window opens, to search a desired text in the session. Searching
parameters can also be defined.
Searches the session file and displays in the Output window warning and error
messages for anything found not according to the rules of a session file.
By double clicking on a message the corresponding line in the session will be
highlighted in the session. Pressing Ctrl+> or Ctr+< keys the cursor will navigate to
the next or previous position of the session referred to by an error or warning.
Automatically create a User Toolbar from all or selected lines (see 2.5.9. Create
User Toolbar, pg.24).
Add in the session text the required keywords that enable the insertion of Python /
BETA scripting language within the session, e.g.:
#!script
#include "meta_structs"
def main()
{
//type your code here
}
#!EOF
(see 4. Scripting, pg.65).
Lines inside session that seems to be BETA scripting code lines are identified. The
indicator #!Script line can be added before a script starts.
2.5.4. Editor
The Editor is a specialized text editor where all open session are listed in separate tabs.
Tabs Each session is placed under a different tab. All functions are applied to the
active tab.
If a session file being edited has not been saved, its name on the corresponding
tab will be marked with an asterisk.
Single click on a tab to activate it.
Use the arrows on the right to scroll between tabs.
Lines All lines are numbered. The number of lines which contain breakpoints are
highlighted.
Controls
Right click Open the context menu which contains text editing functions.
General Options
Open File Open new files in new or the current tab of the editor.
Recent Files Set the number of recent files to be kept in File > Open Recent File
menu.
Colors
Fonts Colors When writing a session text is colored differently, according to certain
rules.
Change the color by pressing on the respective button.
Comment Comments are lines that start with the $ or # characters. Comments do
not affect the session.
Linecount Text The color of the numbers showing the line‟s row.
Background Colors
Current Statement When running the session in debugging mode, the current line is
highlighted.
Command in Line Change the referenced line number to view the description for
another line.
Command Type another command, even if it is not present in the session file
and press the Enter key to view its description.
Description View description, help and suggestions for the command and its
arguments.
In case there is a fault, it is noted with a respective message.
List Anything that can be parameterized can be listed. The contents of the
list depend on the function selected on the right side of the tool.
Any actions are applied only to checked entities.
Hits: Shows how many times an entity is present in the session. Each
entity is listed only once even if it has more than one hit.
Expand the tree to see the line and the command where the entity is
used.
Filenames List all filenames found in the session including their path.
Values List all values found in the session. Values can be numbers but also
ranges, type of results, names or advanced filter arguments.
Custom Name When enabled, a name will be asked when creating new parameters.
Else, they will be named automatically.
Static Parameter Each selected filename, directory or value will be replaced by a variable and
the respective command that creates this variable will be added in the top of
the session. This way it is easy to control any parameters without having to
search for them in large session files.
For example the line:
options state 4
will become:
options state ${p0}
and the following line will be added in the top of the session:
opt var add p0 4
The line:
read dist Nastran /home/user/file.op2 all Displacements
will become:
read dis Nastran ${p0} all Displacements
and the following line will be added in the top of the session:
opt var filetext p0
All commands created by this function are openening dialogs where the user
enters or pick the required value, file or entity.
Parameters List all parameters set by the tool or any variables to be created with this
session. At the same time a new set of functions become available:
Static to Dynamic Convert selected static parameters to dynamic. As for the Dynamic
Parameter function, a dialog comes up for each selected parameter in order
to select its type.
Dynamic to Static Convert dynamic parameter to static. A dialog comes up asking to enter the
value of the parameter.
Delete Parameter Delete selected parameters. If a parameter is dynamic, the value must be
entered.
Merge Parameters Merge two or more parameters to a new one with name, type
(static/dynamic) and value (in case of a static parameter).
Add a description.
Search for, Find Search and create parameter from any text.
Create
Folder The session file and any files referred in the session will be copied to the
target folder.
Compressed File Create a compressed file which will contain all the needed files and the
session
Target Folder Set where the session file and the files will be created.
Compressed File Set the path and name of the compressed file.
Password Protected Protect the file with a password. A dialog will ask for the password when
pressing the OK button.
Compression Level Set the compression level for the compressed file.
OK Create the package. Only files checked in the list will be included. All
paths within the session will change from absolute to relative.
Preview See how the contents of the new folder or compressed file will be
structured.
Files list
The initial locations of all files that are referred in the session as well as the path of the session are
listed.
Control which files are going to be included in the created package by checking the corresponding
check box ahead of each file.
To review the dependencies between the files, select the Show Dependencies option from the
context menu.
Save as session Save the selected lines in a session file. The user toolbar will execute the
commands from this file.
Add directly All commands will be added directly to the User Toolbar.
File Textbox A file textbox will be created for each selected parameter.
Directory Textbox A directory textbox will be created for each selected parameter.
Add all parameters as Enable the respective textbox to create the corresponding type of textbox
... for each parameter.
Once the toolbar has been created it will be listed under the Toolbars drop down menu. The user
can save, edit and delete the created toolbar through the Toolbars > Toolbar Designer (see 3.
Toolbar Designer, pg.32).
2.5.10. Snippets
Snippets are parts of code that can be saved for use on other parts of the same or of a different
script or session.
Invoke the Snippets tool from Tools > Snippets.
Snippet name Enter a name for the selected snippet. Use the Save button to store the name.
Save selected snippet. Snippets are stored in the snippets.xml file created in
the current directory (where META is called from).
Export current snippet to the Session’s Editor’s current tab. The snippet is
inserted at the current cursor position.
The session‟s filename should be a single character that corresponds to keyboard‟s key.
For example a session saved as h.ses in the current directory will run by pressing the Ctrl+Shift+H
keys.
4 1
3
2
1. Press the F7 key or press on the Check 3. Click on the number of the required line.
Session File For Errors button. The respective line number is highlighted.
2. Warnings or errors appear in the Output 4. Press the Shift+F5 button or press on the
window. Double click on each warning or Debug Current Session File button.
error to go to the respective line and correct
the errors manually. 5. The session runs but pauses just before the
breakpoint. The command to be executed
Even if no errors or warning appear, it is is highlighted.
still possible that the session does not
produce the required result. In this case, it 6. Continue running the session line by line by
pressing the Enter key or the middle mouse
is recommended to insert a breakpoint in a
line up to which the session runs as button to check the result of every executed
expected and then run the session line by command until the error is located.
line. To do so: 7. Exit debugging mode press the Esc button.
4
The line will change to:
read geometry Nastran $p0
At the top of the session the following line will be written:
opt var filetext p0
When the session will be executed, the File Manager will come up.
1. Open or create the session that is to be used with the toolbar. All filenames / values that should be
input through toolbar entities (textboxes, filetextboxes, etc.) need to be parameterized first and
exist as static parameters in the session. Select some lines of the session or do not select anything
so that all session is used.
2. Press the Create User Toolbar button.
3. In the dialog box Press Yes to add static parameters as textboxes.
5. If Save as session is
selected, the session/part of
session will be saved as a
session file and this session
file will be executed from the
toolbar. If Add directly is
selected, the session/part of
session will be saved
directly as commands inside
the toolbar.
3.1. General
Unlimited number of toolbars can be created in META. These toolbars hold buttons that have one
or more commands assigned to them. All created user toolbars are held under the Toolbars drop-
down menu of META general interface. Some toolbars may also be selected to be shown in the
context menu of a 3d Window. The toolbars can be defined either directly in META through the
Toolbar Designer tool or inside the META_post.defaults file using a text editor.
3.2. Interface
This tool is used for the interactive creation / modification of toolbars. It is invoked from the Toolbars
pull-down menu: Toolbars>Toolbar Designer.
The first time this tool is opened, it appears as a list of all currently available toolbars in META.
These are the toolbars that META has read from the various META_post.defaults file upon
launching. This list appears as it is shown in the picture below:
The toolbars are listed in a tree form. As soon as an item from the list is selected, a different section
appears in the right side of the list. Toolbars that have been edited but not saved in the defaults file
are highlighted in orange. The following picture provides an overview of the interface.
Property Viewer A list with all available toolbars in a tree form. The list contains the following
columns:
- Item: Names of the different items are enlisted. As Items are regarded all
buttons, checkboxes, textboxes, etc. of a toolbar and the toolbar itself
- Type: The type of each item is enlisted.
- Source Defaults File (only for Toolbar Items):It contains the default file a
toolbar has been read from
- Target Defaults File (only for Toolbar Items): It contains the file-path, where
the toolbar will be saved. The Target Defaults File comprises one of the
properties of a toolbar and can be modified. Moreover, the Target defaults File
can be any of the *.defaults files that META has read upon launching.
Propeties The section on the right side includes the properties that have been specified
for the selected item. These properties and consequently the layout of this
section depend upon the Type of the selected Item. The most commonly met
fields on the top part of this section are:
- Name
- Label
- info-tip
- Image
- Color of:
- Text
- Background
- Orientation
- Horizontal
- Vertical
The bottom part of the Properties section includes the commands that have
been assigned to the selected item (obviously all commands are not available
for all Types of items). These commands cannot be edited directly, but in the
Property editor tab which can be accessed either by pressing the Edit
commands list button or by selecting the tab itself. All items respond to one, two
or zero Command fields (see 3.3. Item Properties, pg.37).
Load Load toolbars that have been saved in any ASCII file. This file does not have to
be one of the META_post.defaults file that META reads upon launching.
Save to Defaults Save all new and modified toolbars to their Target default files. META provides
a warning about the actions that should be performed upon saving, where
Target default files may be updated or even the whole process may be
canceled.
New or modified toolbars that have not saved in the defaults file are marked
orange in the list.
Reload from Reload all toolbars from the available META_post.defaults files. In this case
Defaults only the information related to toolbars is reloaded, not all information existing
in the META_post.defaults. Therefore, it is not the same as applying the
command:
options rereaddefaults
Move selected items up and down in the list within the same tree-structure level
3.2. Context menu, create new items, save and delete selected items
Show at right click Activate this option so that the toolbar is also shown when the right
mouse button is pressed on a 3d plot window.
Export to Session Editor A new tab will be created in the Session Editor window and the session
commands assigned to the selected toolbar / button / box will be
exported to it.
- Group - Checkbox
- Menu - Textbox
- Tab - File textbox
- Button - Directory textbox
Save as... Save a toolbar in a *.defaults file. Only available for toolbars
Set target defaults Set the target defaults where the toolbars will be saved with the Save
to Defaults button.
Paste Paste copied items in under selected item. The option appears only if
there are any items copied.
3.3.1. Introduction
In this section different properties of different Items are presented. Fields that appear in more than
one Items’ Properties are explained only the first time met.
Name Input the characteristic text that META uses to understand that toolbar.
Label Input the label to appear as name of the toolbar. Due to the use of the Name in
commands, there may be a need to not include gaps in the Name and use short
Names for easier handling. In that case a different Label can be set, which is the
name that actually appears as title in the toolbar window. If the button is
activated Label will have the same input as Name and it will not be editable.
Expand into Activate this option so that the submenus, groups, buttons, etc. of the Toolbar will
User Toolbars appear as further expansions under Toolbars menu of META (Toolbars>
submenu Toolbar>...).
Commands Input META commands, to be executed with the execution of the Item. They can
be edited by pressing the Edit commands list button.
Commands Input META commands, to be executed with the activation / deactivation of the
On / Off Item. They can be edited by pressing Edit commands on / off list buttons
respectively.
Info tip Activate this checkbox to display the text written in the respective field when
the mouse cursor is left on the Menu.
Image checkbox Use an image from a valid file path to be displayed in the drop-down button
of the Menu.
Button Type Select the type of the button among the following options:
- Simple Button
- Font Selection Button: When pressed a Font selection window will be
invoked
- Color button: When pressed a color selection window will be invoked. The
button will colored according to the picked color.
Commands Press Edit commands list button to edit the commands that the button will
execute.
Initial State Set initial state of the checkbox when invoked (with the toolbar):
- Unckecked
- Checked
Execute Initial Enable execution of the commands that correspond to the above selection of
commands the Initial State, i.e. Checked (Commands On) or Unchecked (Commands
Off).
Commands On / Edit the commands applied when the checkbox is activated / deactivated by
Off the Edit commands on / off list buttons respectively.
Initial State Set initial state of the checkbox when invoked (with the toolbar):
- Unckecked
- Checked
Execute Initial commands Enable execution of the commands that correspond to the above
selection of the Initial State, i.e. Checked (Commands On) or
Unchecked (Commands Off).
Commands On / Off Edit the commands applied when the checkbox is activated /
deactivated by the Edit commands on / off list buttons
respectively.
Commands Edit the commands applied when the radio-button is activated by pressing Edit
commands list button.
Radiobuttons are deactivated when at least 1 more Radiobutton is available and
activated at the same Group and its commands are applied instead.
Enable tracking When active, the commands will be applied when the slider is moved.
Otherwise the commands will be applied when the slider is left at rest, i.e.
after its movement has stopped.
Slider Style Set the type of the slider using the options:
- Slider Only
- Spinbox Only
- Both
Range Control the range of the slider setting the appropriate values in the fields:
- Min
- Max
Commands Edit the commands applied when setting the slider pressing the Edit
commands list button.
Disable edit Enable this checkbox to disable edit of the textbox. By enabling this
option, the Trigger on text checkbox will be hidden and enabled by
default.
Trigger on text Enabling this checkbox, commands will be applied while typing the
text.
Initial State Write a text to be the default value of the textbox when launching
the toolbar.
Execute initial commands Activating this checkbox, if arguments of META commands exist in
the Initial State field, the corresponding commands will be
executed.
Commands Press the Edit commands list button to execute the commands of
the Textbox.
File Selection - Any file: The file manager invoked by the file textbox will contain a Save
button.
- Only existing file: The file manager invoked by the file textbox will contain an
Open button.
Trigger on text Enabling this checkbox, commands will be applied while typing the text.
Initial State Write a text to be the default value of the textbox when launching the toolbar.
Execute initial Activating this checkbox, if arguments of META commands exist in the Initial
commands State field, the corresponding commands will be executed.
Commands Press the Edit commands list button to execute the commands of the Textbox.
Wildcards Pressing the Edit wildcards list,to edit the Wildcards of the Filetextbox to appear
as available File Types in the File Manager that will be invoked from it.
History Enter string values to form a list of predefined options to select in the appearing
drop-down menu of the Textbox, by pressing the Edit history list button.
Initial State Write a text to be the default value of the textbox when
launching the toolbar.
The image depicts the Property editor tab, specifically that of Radibutton Commands. The available
options in this tab depend upon the Type of item that has been selected to be edited.
The available tabs are
- Commands
- Commands On
- Commands Off
- Wildcards
- History.
The commands that are listed in the Command list (On / Off) are the ones that will be assigned to
the selected item as soon as the Apply button is pressed.
Import Session File Import a session file with commands to be assigned on the
respective item.
Edit in Session Editor Edit the commands typed in the blank field in Session Editor.
Pressing the button the Session Editor window will be invoked
containing everything typed in the blank field until that moment.
Add Environment variable Select an environment variable from a list containing all environment
variables.
Apply Assign the input commands to the item
Scripts can also be embedded within the commands list, separated from the rest of the commands
using a starting, #!script, line and an ending, #!EOF, line.
For all types of text buttons, apart from the above options, there are extra similar options for multiple
arguments that can be passed to these types of buttons.
Furthermore, in History
tab the control of the
History options is
available for the
respective Items.
Move selected entries in the History list. This way the values will fill back the History
field.
Automated procedures that execute toolbar commands are supported. The functionality of a button
or checkbox etc. can be applied with the command:
toolbar edit click <toolbar name><button name>
The command can be used within another section of the same toolbar or another toolbar to repeat
some process automatically. To have a set of default settings in a toolbar by opening it, for example,
the previous command can be used. In order to activate checkboxes by the startup of a toolbar (or
similar action), without applying their functionality, the following command can be used:
toolbar edit onlytoggle <toolbar name> <checkbox name> on/off
7. Press Apply
8. Repeat steps 3 and 4 to create two more radio buttons: one for writing only Geometry and
Displacement results (Displacement) and the other for writing Geometry and Function results
(Function).
3
4
Conventions:
Courier New Bold: Keywords used for creation of items of the toolbars
Courier New Bold Italics Any META command with the same syntax as in the
command line of the program.
Keywords:
7 toolbar endgroup
Denotes the end of a group definition. This is related to groups defined either with the
toolbar subgroup or the toolbar hsubgroup keywords.
9 toolbar endtab
Denotes the end of a tab section.
- To define multiple filters as one option: Separate filters with semi-colons (;) or
spaces
- To define multiple filters as multiple options: Separate filter options with |. In that
case, the last defined filter will be the current when opening the File Browser.
- The filterfiletext keyword must be the next specified keyword after the respective
filetext or sfiletext button definition.
24 toolbar endmenu .
This keyword is used to denote the end of the definition of a pulldown menu.
4.1. Introduction
The METAScripting Interface is an Application Programming Interface (API) that allows developers
to access the META core functionality and data. In scripts, all META commands can be combined
with programming capabilities. The Scripting Interface allows for:
- creation and modification of the META data/entities
- creation of custom GUI
- reading and writing custom file formats
- Access and manipulate data from nodes, elements, boundary elements, materials, annotations,
models, groups, cut planes and isofunctions.
- Manipulate 2D plots: create and select curves, access data from curves and their points and
modify them.
- Create coordinate systems and access information of defined coordinate systems.
- Create new results with user-defined data (deformation-scalar-vector) on nodes and elements.
- Create and manipulate META 3D and 2D windows.
- Create and manipulate windows during the execution of scripts.
- Manipulate files and directories.
- Create and handle data in XML form.
- Use system commands.
Scripts are created, edited and handled with Script Editor. However a script can also be written in
any text editor.
4.2.1. Interface
Script Editor is a complete code-developing tool to create, edit and debug scripts of META scripting
language.
The Script Editor can be accessed through:
Tools > Script Editor
Main menu Contains the Script Editor functions distributed under the File, Edit,
Project, Debug, Tools, View, Window and Help drop down menus.
Standard toolbar Contains buttons for calling the most important edit and debug functions.
Editor This is the text area where the code is written or tested. Every open
script file is located on its own tab. The Immediate tab allows the
debugging of script code lines missing the main function.
Functions list Offers a list of META script functions distributed in three tabs: Library,
Dynamic help and Search.
Library: Lists all available functions grouped by type (Annotations
functions, Elements functions, etc.)
Dynamic help: Displays the types of the parameters needed by the typed
function as arguments. It appears as a function is typed, in order to
assure that the function is typed right.
Search: Displays a list of all functions sorted in alphabetical order. It also
features an input field that can be used for filtering.
Watch window Displays information about the variables and the functions contained in a
script while debugging.
Project Window Displays the structure of a Project in a tree mode view. Also files and
includes can be created, added or removed in the Project.
New... Creates a named Untitled, script file. A new tab in the editor window is added.
The name of the script in the tab is followed by an asterisk (*) until the script is
saved.
In the Select file type window that popup appear the options to creae a Beta or
a Python script and to create an empty script or a script, where the main
function is already defined.
Open... Invokes the file manager to browse for a script file (i.e. *.bs, *.c, *.ses) to open.
Script opens in a new tab in Editor window. There is no restriction regarding
how many scripts can be remained opened simultaneously.
Open recent Select to open, from a list of the recently opened script files.
Save Saves the current edited script. By default scripts are saved in the working
directory.
Save as... Invokes the file manager to save the currently edited script. The name of the
script tab also changes accordingly.
Print Invokes the Print window to print and define the printing options of the current
script.
Edit
Undo, Redo Undo and redo editing actions in the current edited script.
Cut, Copy, Paste Cut, Copy and Paste script text within and between windows.
Find... Invokes the Find window to search for a word in the script.
Find next Functional only when the Find window is open. Finds the next match (F3).
Replace text Invokes the Find and Replace window to replace certain words in the script.
Project
New... Creates a new Project. In the New Project window specify the project‟s name
and the directory.
Append extension to main script checkbox, append the default extension .bs
(beta script) to the final main script.
Open... Invokes the file manager to browse for a project (i.e. *.bpr) to open
Open recent Select to open, from a list of the recently opened projects.
Export main script Creates a script file named as the project, into the project‟s directory which
includes the Search script files of the project.
Parse file Examines the scripts, analyzing for possible syntax errors that will be printed
in the Output tab.
Compile Invokes the file manager to save the file (i.e. *.bs) in binary format.
Note that a compiled script although can be executed cannot be edited. A
compiled script can be loaded and run throughout all the normal ways
(command line, script menu) except the Script Editor. Furthermore, all the
contained functions can be called from any other script even from decompiled
ones. A compiled script can be used as include file or project file.
Scripts can be compiled normally even if they contain #include or
#projectfile statements.
Remark
Note that an opened project has compilation priority. This means that if a project is opened, then
the Parse file, Compile, Run, Run function, Debug and Debug function commands, will generate
and run the project code and not the code of the current opened file.
Debug
Run Runs the script without stopping at breakpoints. While in debugging mode, it
starts the automatic execution of the script until next breakpoint.
Debug Run the script in debugging mode. The execution stops if a breakpoint is met.
Breakpoint Add / Remove a breakpoint in the selected line(s). Line should not be emty.
Step Execute one line of script stopping on the next line of script in the same source
file. This will run any functions encountered until the above condition is met.
Step into Execute exactly one line of script. This means that will "Step into" the current
function, if necessary.
Run function Invokes the Select script function window. Select one function from the
available to run individually. Arguments that may need are entered manually.
Debug function Invokes the Select script function window. Select one function from the available
to debug individually. Arguments that may need are entered manually.
Tools
Designer Invokes the BETA windows designer which uses the BCGUI (BETA C
interface Graphical User Interface) library to create windows.
Code snippets Invokes the Select snippet window, to manage and import a snippet.
Make snippet Invokes the Make new snippet window, to create a snippet. If lines of script
code are selected they are automatically passed as the contents of the new
snippet.
Fix obsolete Automatically fixes commands that are written in an obsolete format or syntax.
There are commands in META scripting language that are currently obsolete
but they are still supported in order to keep compatibility with previous
versions. For example command print is obsolete but is still supported.
View
Add variable Adds in the Watch window > variables list, the variable on which the cursor
points to. Cursor should point on to variable‟s name.
Tabbed GUI Turns off/on the tabbed GUI interface (each script opens on its own tab).
Needs restart to take effect. If applied each script opens on its own window.
Select font Invokes the Select Font window to manage the font‟s type in Editor.
Editor colors Invokes the Script editor colors window to manage the coloring code of META
scripting language layout.
Window
Help
Edit help Invokes the Script Help Editor window where the help text of commands can
be edited.
Complete help Invokes the Script Help Editor window where the help text of commands can
be edited.
Diff help Invokes the Script Help Diff/Editor window where two *.xml help files can be
compared.
Undo, Redo (Ctrl+Z, Ctrl+Y), Edit > Undo, Edit > Redo:
Undo and redo editing actions in the current edited script.
Cut, Copy, Paste (Ctrl+X, Ctrl+C, Ctrl+V), Edit > Cut, Edit > Copy, Edit > Paste:
Cut, Copy and Paste script text within and between windows.
function, if necessary.
4.2.4. Editor
4.2.4.1. Interface
In Editor all opened scripts are tabbed. The Immediate tab is always accessible.
Tabs Each script is placed under a different tab. All functions are applied to the
active tab.
If a script is not saved and asterisk is present next to its name.
Single click on a tab to activate it.
Use the arrows on the right to scroll between tabs.
Text The script code text is colored according to the type of the word.
While the cursor is in line with a command, guide about the syntax is displayed
in the Status bar. Also information about the types of the parameters of the
typed function are displayed in the Function list > Dynamic help tab.
Controls
left mouse button Clicking sequentially selects the whole word and next the whole line of code.
F1 While the cursor points on a function the corresponding function‟s help text is
displayed in the Help window.
Add function The following code lines are added to the script body to write a function:
def <func_name>(<args>)
{
// add function code here
return 0;
}
Add watch Available only when the cursor points to a variable‟s name. Adds the variable
in the Watch window > variables list, in order to monitor it during debugging.
Make snippet Available only when a script part is selected. Invokes the Make new snippet
window. The selected script is added in the contents of a new snippet.
Comment out Available only when a script part is selected. The selected code is comment
out the script body between /* */. The enclosed script code is colored
gray and is not executed when running the script.
Uncomment code Available only when a script part is selected. Uncomment the selected code if
it is commented out.
The immediate tab is used for testing functions or a few lines of code.
For simplicity, the code inside is not allowed to have any def statement. Consequently, any variable
that is written in the global section of the script has no sense.
Scripts made in the immediate environment can be executed normally.
Next follows a code that tests how many models exist. written for both Immediate and script tab:
The META Window Designer uses BCGUI (BETA C interface Graphical User Interface) library and
supports creation of a graphical interface trough which scripts can be called and controlled. This
way a graphical interactive environment can be built to run a complete project automatically and
interactively (see 4.6. BCGUIDesigner, pg.225).
4.2.6. Snippets
Snippets are sections of code or complete functions that can be created or loaded anytime through
the Script Editor. The first time a snippet is created, it is saved without any warning in an xml file
called snippets.xml, located in HOME directory and can hold separately any number of snippets. In
this way a library of mostly used functions or codes can created.
The Select snippet depicted following is accesses through Tools > Code snippets
and is invoked generally to import snippets in the current edited script.
The Make new snippet window accessed through Tools > Make snippet
follows the same functionality except of importing a snipped into the script. Thus only edit and
creation of snippets is possible.
Snippet name Displays the name of the selected snipped in the list. Also the name of a new
snipped can typed.
Snippets list The available snippets are listed. They are divided into two groups: ANSA and
META snippets depending the on the source of the snippet that is created.
Code area The script code lines of the selected snipped are displayed. Editing of the snippet
is allowed and follows the general rules that apply in Script Editor.
Save Saves the listed snippets in the default snippets.xml file, located in HOME
directory.
In case a snippet name is set in the Snippet name field then it is also created and
added into the snippets list.
Import Passes the selected snippet in the list to the current script.
Font style Set the style of font (i.e. Normal, Italic, Bold, Bold Italic)
Color definition Pressing the buttons the Select color window opens to define the color of the
buttons mentioned Script Editor layout.
There are thirteen coloring codes in the Script Editor. The button‟s color
represents the currently selected color for the corresponding layout.
Sample code Display a preview of the current display color mode of Script Editor.
2 3
4
1. Click on the Watch window button to make visible the Watch window and switch to variables
tab or select View > Watch window.
2. Move the cursor to, or select a variable‟s text (e.g. multiplier).
3. In the context menu select Add watch: multi::multiplier.
The multiplier variable is added in the variables list in Watch window.
Pointing on a variable the Add watch prompt option, follows the syntax:
Add watch:<function name>:: <variable name>
4. Repeat the same for the other variables.
While in debugging mode the variables value will be monitored in the Watch window.
Debugging is the line by line manually execution of a code. In order to debug a script at least one
breakpoint should be set.
Consider that the aforementioned script have to debugged.
3 4 1
th
1. Point on the 5 line and press the Breakpoint button or (F9).
The line is highlighted pink.
th
2. Repeat the same, pointing on the 12 line.
3. Press the Run button or (F5).
The script output results will displayed in the Output window.
No debugging took place. Run function ignores all set breakpoints.
4. Press the Debug button or (Shift + F5).
Script will be executed till the first breakpoint is met (line 5).
The current line (the line where the breakpoint is set), which is to be executed next, is
highlighted light blue.
At this state, script is running in debugging mode. The script can be run line by line. While in
debugging mode, all messages are displayed in the Output tab of the Output window.
5. Press the Run button or (F5).
The script will executed till the next breakpoint is reached
6. Press the Run button or (F5) multiple times till the execution of script is finished and watch the
values of monitored variables.
7 8 9
Make sure the execution of script is finished and point into the script.
7. Press the Debug button or (Shift + F5).
8. Press the Step into button or (F11) to go into a sub function. Press the F11 key multiple times
and watch the values of monitored variables as well the Output window.
9. Press the Step out button or (F12) to step out the sub function. Continue pressing the F12 key
till the end of execution of the script.
The script can be run line by line by pressing the Step button (F10) . This way debugging
proceeds only through the lines of the main function, without stepping into the sub functions.
While in debugging mode, at any time the Script Editor window can be minimized to review the
results of the commands applied up to the current line reflected in the corresponding META
windows.
A project is a collection of user scripts, organized in a way that they can be accessed anytime
through the Script Editor. In the project environment, embedded in Script Editor, two distinctive
capabilities are offered:
- The creation of an xml project file, holding references to scripts‟ file paths.
- The creation of a main script with #projectfile statements. The files that are referenced in this
script are those that are included in the xml file.
The project environment can be activated through Window > Project window.
4.3.1. Introduction
4.3.1.1. Introduction
This guide is intended to provide a quick introduction of Python 3 and to describe the META python
module. For more information about the capabilities of the Python programming language please
refer to the online language documentation provided by the Python Software Foundation
(www.python.org). In addition there are numerous of books and resources that are available from
third party vendors and contributors.
The data type determines the kind of data that a variable or a function can hold. Data types include
integer or floating point numbers, strings, matrices etc, as well as user defined types. The following
paragraphs describe the Python built-in data types
4.3.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
A sequence is an object containing a series of objects. There are three types of built in sequences
in Python. These are the list, tuple and string.
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
Lists 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 BETA
Scripting language.
Tuple
Tuple objects simple groups 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
Dictionaries are unordered collections. In dictionaries items are stored and fetched by key instead
of by positional offset. Indexing a dictionary is a very fast and powerful operation. Dictionaries are
the equivalent to Maps of the BETA Scripting Language.
del data[k]
del data[i:j]
del obj.attr
del variable
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: '+str(x))
4.3.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
In computer programming, a scope is the context within a computer program in which a variable
name or other identifier is valid and can be used, or within which a declaration has effect. Outside
of the scope of a variable name, the variable's value may still be stored, and may even be
accessible in some way, but the name does not refer to it; that is, the name is not bound to the
variable's storage.
The if statement is the basic decision statement of a script. Its operation is based on the evaluation
of a condition that will yield a result that is either true or false. If the condition is true (i.e. not equal
to 0), then the if-block of statements is executed. If the condition is false, then the else-block of
statements is executed. The if statement general form is:
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
A loop comprises of a block of statements that are executed repetitively. When the end of the loop
is reached, the block is repeated from the start of the loop.
The for statement allows the iteration over the elements of a sequence. for loops do not maintain
any explicit counter. The general form of the statement is:
all_properties = ["PSHELL","PCOMP","PBAR","PBEAM","PELAS"]
for property in all_properties:
print(property)
the result is
PSHELL
PCOMP
PBAR
PBEAM
PELAS
The while statement introduces a conditional exit loop. The program executes the specified
statements repetitively for as long as the given condition remains true (i.e. not equal to 0). Its
general form is:
while (condition):
body-statement
If operators are to be used for the expression of the condition, these must be of logical relational
type.
a = 0
while a<3:
print(a)
a += 1
The continue and break statements can be used to redirect the execution order of a loop. The
break statement allows the termination of a loop regardless of the loop control condition. In other
words it can lead to an unconditional branching. A typical example is given below:
a = 0
while a<5:
print(a)
a += 1
if a == 3:
break;
The continue statement jumps back to the beginning of the loop‟s block to begin the next iteration.
BETA CAE Systems 93 META Automation User’s Guide
4. Scripting
a = 0
while a<5:
a += 1
if a == 3:
continue
print(a)
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]]
To retrieve a value of a specific member of a list, the user must provide the corresponding index
operator:
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.
Characters may be assigned to string variables, using statements similar to those of numeric types:
property = 'PSHELL'
mat_name = 'steel_105'
The operators that can be used to form expressions between string data types are:
+%
Both of them generate a string as the result of the concatenation of two or more strings, e.g.
property = 'PSHELL'
id = 'with id 1'
property_id = property + id
Strings can be treated as matrices, so any part of them can be isolated without the use of any built
in function. A string corresponds to a matrix, which has a length equal to the number of characters
that comprise it. Each character corresponds to a matrix member.
Example
str = 'Bumber_Front'
The above string has 12 characters.
We can get any part of the string by using the indices of the characters. Here are some examples:
val = str[0:6] #This will get the "Bumber"
val = str[7:12] #This will get the "Front"
val = str[7:8] #This will get the character "F"
val = str[6:7] #This will get the character "_"
val = str[2:8] #This will get the "mber_F"
val = str[4:] #This will ge the "er_Front"
val = str[:7] #This will get the "Bumber_"
The length of a string (an integer) can be obtained calling the function len:
length = len(str)
myDictionary = dict()
#or
myDictionary = {}
Alternatively:
myDictionary['Name'] = 'aluminum'
myDictionary['pid'] = 19987
since the former node uses a string-type key and the latter node uses a numeric key. Note that
when maps are used as keys, they are sorted according to the number of nodes they have, with
larger maps taking precedence over smaller maps.
To retrieve a value of a specific key, the user must provide the corresponding key:
i = myDictionary['Name']
print(i)
del myDictionary['Name']
length = len(myDictionary)
del myDictionary
User functions allow to group a set of operations into a compact unit that can be easily and
repeatedly accessed. The repetitive use of functions saves much time while reduces the chances of
error. Each user function is given a name, optionally uses some input parameters (arguments) and
returns the results as output parameters.
4.3.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 indented. A typical function has the form:
def main(list of arguments if exist):
.......
Statement
.......
Since the target of each sub-function is to perform a certain task, there must be a way to notify the
main function that called it for the result of the procedure it performed.
The communication between the functions can be achieved through the return command. This
command can be used anywhere in the code and is followed by any data. A function that calls
another function can store the returned value in an output argument or even can ignore it.
Functions that don‟t return anything are executed normally and may not use the return command.
Equivalent, they can return a dummy value.
Note: The named arguments pattern is widely supported in the META module.
The common practice has proven that even the most experienced programmer needs to keep some
BETA CAE Systems 98 META Automation User’s Guide
4. Scripting
comments in order for the code to be readable and understandable. InPython comments can be
added after the # sign. Comments between three pairs of quotes (“””Comment”””), under the
function declaration, define a python docstring (see python documentation for more information)
# PYTHON script
import meta
from meta import parts
def fun1():
"""Docstring for function help"""
# Collect Parts
model_id = 0
pids = parts.Parts(model_id)
# Print the id of each Part
for pid in pids:
print(pid.id) #Print the id
In contrast to local variables, global variables are valid throughout the program, so they can be
accessed and changed by any individual function of the program. Global variables must be
declared prior to the definition of any function (global section).
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
For storing and retrieving strings as long as the META session is opened, the functions
BetaSetVariable, BetaGetVariable, MetaSetVariable and MetaGetVariable must be used. Any
variables defined this way are considered as part of the program and thus they are accessible by
any script. In META vairables only strings can be stored, as META variables are also accessible
from other META tools as well. In Beta variables bytes objects are stored, so respective python
library funtions must be used to generate the objects and then retrieve the values from them.
import meta
from meta import *
def main():
utils.MetaSetVariable('program_var1', '10')
val1 = utils.MetaGetVariable('program_var1')
print('val1: '+val1)
META variables' values can be cleared using the META command opt var delete.
import pickle
import meta
from meta import session
def main():
p = 1
v = pickle.dumps(p)
session.BetaSetVariable('a', v)
v = session.BetaGetVariable('a')
p = pickle.loads(v)
print(p)
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 error:
print('Key Name does not exist')
import math
BETA CAE Systems 100 META Automation User’s Guide
4. Scripting
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):
print('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))
In python modules are imported with the import statement. At the top of your python file import the
desired modules like in the example shown below
import math
import sys
import meta
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
Since the target of each sub-function is to perform a certain task, there must be a way to notify the
main function that called it for the result of the procedure it performed.
The communication between the functions can be achieved through the return command. This
command can be used anywhere in the code and is followed by any data. A function that calls
another function can store the returned value in an output argument or even can ignore it.
Functions that don‟t return anything are executed normally and may not use the return command.
Equivalent, they can return a dummy value.
def main():
utils.MetaCommand('write tif "C:/ses/ses2/test.tif" 0.9')
Any string operation is acceptable for the string given as argument for the MetaCommand.
So, the values of variables can also be used:
file = "/home/demo/one folder/image1.tif"
MetaCommand ('write tif "'+file+'" 0.9')
command = 'write tif "'+file+'" 0.9'
MetaCommand (command)
The basic idea behind the scripting language is to automate many repetitive and tedious
procedures with the minimum user interaction and to perform specific tasks that are not covered by
the standard META commands and META session capabilities. Some of the tasks that can be
performed within scripting language are the following:
- Extracting any type of information from an already loaded model (data from nodes, elements,
boundary elements, materials, models, coordinate systems and groups).
- Access and manipulate data from META entities like annotations, groups, cut planes and
isofunctions.
- Manipulating 2D plots: create and select curves, access data from curves and their points and
modify them.
- Creating new results (deformation-scalar-vector) on nodes and elements with custom calculated
data.
- Creating and manipulate META 3D and 2D windows.
- Creating user-defined windows.
- Manipulating files and directories.
- Reading and writing ASCII and binary files.
- Creating and handling data in XML form.
- Use of session commands.
- Use of system commands.
- Running automatically (after launching META) a series of functions.
- Communication with the interface (File Manager functions, Pick functions).
All these tasks that can interact with the model and META entities data are controlled through a
series of META specific functions.
In order to use a META specific function in Python, the relevant module has to be imported from
META. The names of the modules are the available categories in the drop-down menu in tab
Library in Functions List window. The functions are then called as methods of the imported module.
In Python the meta structs are objects and their attributes can be used directly without having to
define the variable type first.
For example to print the ids and names of the visible parts
# PYTHON script
import meta
from meta import parts
def main():
pids = parts.VisibleParts()
for pid in pids:
print('Id: '+str(pid.id)+' Name: '+pid.name)
Using the available META modules it is possible to access and manipulate the data of the various
METAentities. Contrary to BETA Scripting, the attributes of the META objects can be accessed
directly without the need to define the object type first (as it is needed to define the META struct
first).
META classes can be subclassed as shown in the example in the description of each class in
Function List of Script Editor. An example is given below:
# PYTHON script
import meta
from meta import *
class MyModel(models.Model):
def __init__(self, r):
super(MyModel,self).__init__(
r.id,
r.name,
r.label,
r.deck,
r.active)
self.function_labels = models.FunctionLabelsOfModel(r.id)
def main():
model_id = 0
r = models.ModelById(model_id)
if r:
print(r.id, r.name, r.label, r.deck, r.active)
my_r = MyModel(r)
print(my_r.id, my_r.name, my_r.label, my_r.deck,
my_r.active, my_r.function_labels)
if __name__ == '__main__':
main()
In META there is a separate group of script functions for META entities. For example, there are
Element functions to collect the elements, Node functions to collect the nodes, etc.
Additionally, there are the following generic functions CollectEntities to collect all the specified
entities that are loaded in META:
Function Description
CollectEntities Collect all existing entities of the specified type in the current
META session
CollectModelEntities Collect all existing entities of the specified type in a model
CollectWindowEntities Collect all existing entities of the specified type in a window
The types of entities that can be collected using these functions are:
ANNOTATIONs
BOUNDARIEs
COORDINATE SYSTEMs
CUT PLANEs
ELEMENTs (SHELLs, SOLIDs, BEAMs, etc)
GROUPs
BETA CAE Systems 105 META Automation User’s Guide
4. Scripting
ISOFUNCTIONs
MATERIALs
META WINDOW entities (WINDOWs, FRINGEs, COLORs)
MODELs
NODEs
PAGEs
PARTs
PLOT2d entites (PLOTs, CURVEs and POINTs)
RESULTSETs
FRINGEs
VISUAL entities (FRAMEs, IMAGEs, VIDEOs)
For collecting all entities, the appropriate functions are the functions with just the type of the entities
to be collected, e.g. Annotations(), Boundaries(), LoadsOfBoundary(), Elements(), Nodes(), Parts(),
Models(), Groups(),Resultsets(), Connections(), CyclesList() etc. Please note that Groups refer to
the entities Parts/Groups of Part Manager, Includes, Boundaries, Connections, Sets
In the case of model entities, the model id is given as argument.
To access the entities directly according to their id, the list with the model objects can be converted
to a dictionary with the XxxListToDict() functions where the key is the entities' id, e.g.
AnnotationsListToDict(), ElementsListToDict(), etc.
# PYTHON script
import meta
from meta import parts
def main():
model_id = 0
all_parts = parts.Parts(model_id)
for p in all_parts:
print(p.id)
print(p.name)
dict_parts = parts.PartsListToDict(all_parts)
for key, p in dict_parts.items():
print(key)
print(p)
if(__name__ == '__main__'):
main()
To get the entities types of a model, the functions XxxTypeXxx() are available, e.g.
ElementsTypes(), CurvesTypesNastran(), DeformationTypes(), ScalarTypes(), VectorTypes() etc.
# PYTHON script
import meta
from meta import elements
def main():
model_id = 0
all_types = elements.ElementsTypes(model_id)
for element_type in all_types:
print(element_type)
if(__name__ == '__main__'):
main()
To get the available results in a database the functions XxxTypes(), XxxTypesAll(), XxxTypesList()
are available, e.g. DeformationTypes(), DeformationTypesAll(), DeformationTypesList(),
ScalarTypesList(), VectorTypesList(), etc. To retrieve deformation results types of a database the
following can be used.
# PYTHON script
import meta
from meta import results
def main():
filename = 'X:/project.metadb'
deck = 'METADB'
all_types = results.DeformationTypes(filename, deck)
for one_type in all_types:
total = len(one_type)
deform_type = one_type[0] # Deformation type
print(deform_type)
for i in range(1,total):
state = one_type[i]
print(state)
print(i) # Id of the state
if(__name__ == '__main__'):
main()
For curves types of Dyna, Pamcrash and Radios files the functions
CurvesTypesDynaWithNames(), CurvesTypesPamcrashWithNames() and
CurvesTypesRadiosWithNames() are available to get also their name.
4.3.4.3.3. Collect entities according to their attributes (results, name, id, type, position,
comments, failure, free, outer)
There are specific functions in order to collect entities according to one of their attributes, e.g.
NodesByName(), NodesByField10(), ElementById(), CurvesByName(), ElementsByType(),
FailedElements, FreeNodes(), OuterElements(), FollowNodes() etc.
# PYTHON script
import meta
from meta import parts
from meta import constants
def main():
model_id = 0
part_type =constants.PSHELL
collected_parts = parts.PartsByType(model_id, part_type)
for p in collected_parts:
print(p.id,p.type,p.subtype,p.visible,p.name,p.mat_id,
p.shell_thick,p.model_id)
if(__name__ == '__main__'):
main()
When the function returns only one entity (e.g. ElementById()), then it returns the meta object of
this entity. When it may return more than one entities (e.g. ElementsByType()), then it always
returns a matrix with meta objects(even when only one entity is returned).
For entities that need to be collected and which are neighbors of other entities, the functions
NeighbourElements(),NeighbourMaterials(),NeighbourParts() etc can be used. Neighboring entities
are those which are directly attached to the specified entity or calculated by the solver.
For entities that need to be collected according to their nearest relative position to one given point,
the functions NearestNodeOfPart, NearestNodeOfGroup, NearestElementOfPart,
def main():
model_id = 0
adv_filters = list()
adv_filters.append('add:Parts:id:==1:Keep All')
adv_filters.append('intersect:Elements:centroidfuncmax::Max 3')
all_resultsets = results.Resultsets(model_id)
result = all_resultsets[1]
collected_elements = elements.AdvFiltersOnElements(model_id,
adv_filters, result)
for e in collected_elements:
print(e.id)
if(__name__ == '__main__'):
main()
# PYTHON script
import meta
from meta import plot2d
def main():
window_name = 'Window1'
collected_curves = plot2d.CurvesFromAdvFilters(window_name)
for c in collected_curves:
Print(c.id,c.name)
if(__name__ == '__main__'):
main()
There are many functions to collect entities from other entities, e.g. ElementsOfPart(),
NodesOfElement(), ElementsOfNode(), PartsOfGroup(), etc. There is a separate function for each
combination of the entities to collect and the entity that these belong to.
There are also functions that collect only the entities with specific attributes from other entities, e.g.
ElementsOfNodeByType(), VisiblePartsOfGroupByType(), SelectedCurvesOfWindow(), etc.
# PYTHON script
import meta
from meta import parts
def main():
model_id = 0
group_name = 'My_Group'
group_parts = parts.PartsOfGroup(model_id, group_name)
for p in group_parts:
print(p.id,p.type,p.subtype,p.visible,p.name,p.mat_id,p.shell_thic
k,p.model_id)
if(__name__ == '__main__'):
main()
For collecting the visible entities, the appropriate functions are the functions which include the word
visible, e.g. VisibleAnnotations(), VisibleElements(), VisibleCurves(), etc.
There are also functions that collect only the visible entities with specific attributes, or only the
visible entities from another entity, or only the visible entities with specific attributes from another
entity, e.g. VisibleElementsByType(), VisiblePartsOfGroup(), VisiblePartsOfGroupByType(),
VisibleCurvesOfPlot(), etc.
# PYTHON script
import meta
from meta import parts
def main():
model_id = 0
group_name = 'My_Group'
window_name = 'MetaPost'
visible_parts = parts.VisiblePartsOfGroup(model_id, group_name,
window_name)
for p in visible_parts:
print(p.id,p.type,p.subtype,p.visible,p.name,p.mat_id,
p.shell_thick,p.model_id)
if(__name__ == '__main__'):
main()
For getting only the identified entities of a model the respective functions are IdentifiedXxx(), e.g.
IdentifiedElements(), IdentifiedNodes(), IdentifiedParts(), etc.
There is a series of functions to get information from the loaded models, like NumOfNodes(),
NumOfModels(), NumOfPartsByType(), etc.
Also information only for the active Models, Pages, Plots, Plot axes and Windows can be retrieved
through the functions ActiveModels(), ActivePages(), ActivePlots(),ActivePlotAxes() and
ActiveWindows().
# PYTHON script
import meta
from meta import models
def main():
act_models = models.ActiveModels()
for r in act_models:
print(r.id,r.name,r.label,r.deck,r.active)
if(__name__ == '__main__'):
main()
Information about the currently loaded plot models (the plot files listed in the Read Results >
Curves > Files List) that may exist can be retrieved through the function PlotModels().
# PYTHON script
import meta
from meta import plot2d
def main():
plot_models = plot2d.PlotModels()
for pmod in plot_models:
print(pmod.id,pmod.deck,pmod.filename)
if(__name__ == '__main__'):
main()
For collecting all newly created entities of a specific type, the respective functions to use are
CreateNewXxxStart(), ReportNewXxx() and CreateNewXxxEnd()
The syntax is, for example: CreateNewAnnotationsStart(), ReportNewAnnotations(),
CreateNewAnnotationsEnd(), etc.
This can be very useful in order to get the number and ids of entities created through filters or
session Commands.
For example, for curves created through the Curve Function User Defined the function
ReportNewXxx() will return the entity‟s structs without ending the recording of the created entities.
To collect newly created entities within a period, the functions to use are CollectNewXxxStart() and
CollectNewXxxEnd()
# PYTHON script
import meta
from meta import utils
from meta import plot2d
def main():
utils.MetaCommand('xyplot read lsdyna "Window1" "Z:/demo/nodout"
Node 1 Magnitude_of_acceleration_(ma)')
plot2d.CollectNewCurvesStart()
utils.MetaCommand('xyplot curve function userdef "Displacement
Difference" "c1.x" "c1.y-c2.y" "Window1"')
new_curves =plot2d.CollectNewCurvesEnd()
for c in new_curves:
print(c.id,c.name)
if(__name__ == '__main__'):
main()
For collecting files (of specific formats) or directories, the commands of the python os module
can be used. A simple example to get the files in a directory is the following:
# PYTHON script
import meta
import os
def main():
path = 'Z:/demo'
files = os.listdir(path)
for f in files:
print(f)
if(__name__ == '__main__'):
main()
An example to get the installation directory is:
# PYTHON script
import meta
import os
from meta import constants
def main():
print(os.path.realpath(constants.app_root_dir))
if __name__ == '__main__':
main()#
For collecting view parameters, the functions XxxOfView() can be used. An example is the
following:
# PYTHON script
import meta
from meta import windows
BETA CAE Systems 112 META Automation User’s Guide
4. Scripting
def main():
window_name = 'MetaPost'
view_name = 'view0'
#Save view
utils.MetaCommand('view save "'+view_name+'"')
#Apply view
if camera_position and reference_position and up_vector and
front_clipping_distance and back_clipping_distance and viewing_angle:
utils.MetaCommand('view set '+str(camera_position[ 0
])+','+str(camera_position[ 1 ])+','+str(camera_position[ 2
])+','+str(reference_position[ 0 ])+','+str(reference_position[ 1
])+','+str(reference_position[ 2 ])+','+str(up_vector[ 0
])+','+str(up_vector[ 1 ])+','+str(up_vector[ 2
])+','+str(reference_position[ 0 ])+','+str(reference_position[ 1
])+','+str(reference_position[ 2
])+','+str(front_clipping_distance)+','+str(back_clipping_distance)+','+s
tr(viewing_angle)+','+str(perspective_mode))
if __name__ == '__main__':
main()
4.3.4.3.11. Select files or directories through the file manager
Scripting language interacts directly with the File Manager through the commands SelectOpenDir,
SelectSaveDir, SelectOpenFile, SelectSaveFile, SelectOpenFileIn, SelectSaveFileIn. These
functions open the File Manager and allow the selection or creation of files and directories. This is
an elegant way to use file and directory paths in user scripts, since it enables the interactive
definition of script parameters. The functions that deal with files return a matrix containing strings
that represent the full path to the selected files, while those for directories return a string indicating
the full path to the folder.
# PYTHON script
import meta
from meta import utils
def main():
print('Select the file for reading')
read_file = utils.SelectOpenFile(0, 'csv files (*.csv)')
if not read_file:
print('No file was selected')
else:
print('The file that was selected is: '+read_file[0])
print('Select the log file for writing the error messages')
save_file = utils.SelectSaveFile()
if not save_file:
print('No file was selected')
else:
print('The file that was selected for writing errors is:
'+save_file[0])
print('Select the directory where the META files are located');
dir = utils.SelectOpenDir('');
if not dir:
print('No dir was selected')
else:
print('The selected directory is: '+dir)
if(__name__ == '__main__'):
main()
If nothing is selected, it can be identified using the if not statement.
The entities Annotations, Cut planes, Groups, Isofunctions, Windows, Models, Pages, Plots,
Curves, Images and Videos can be created edited and deleted through script functions. The entities
nodes, elements, parts, materials and boundaries CANNOT be created, edited or deleted in META
in general, so this is also not possible through scripitng. Coordinate systems can be created but
cannot be deleted. Moreover, specific functions exist for other operations related to the entities, e.g.
to show, hide, get results from them, etc.
For creating entities the respective functions are CreateXxx(), e.g. CreateEmptyAnnotation(),
CreatePlane(), CreateGroupFromElements(), etc..
The entities can also be created by applying the respective session commands (see also chapter
“META session commands for use in Scripting Language”). However, one advantage of creating
the entities through script functions is that the function returns the structs of the created entities. For
example, when creating a curve through scripting, the id of the curve is available.
# PYTHON script
import meta
from meta import annotations
def main():
window_name = 'MetaPost'
if(__name__ == '__main__'):
main()
There is a series of script functions for editing directly entities and their settings, for example
SetSettingsOfAllCurves(),SetSettingsOfAllAnnotations(), SetAnnotationPointerOnlement(),
ChangeOriginOfPlane(), AddPartsOnGroup(), RotateView(), etc. However, the full possibilities of
editing entities in META are covered through the META session commands and can be achieved
by using the MetaCommand syntax (see also chapter “META session commands for use in
Scripting Language”).
# PYTHON script
import meta
from meta import planes
from meta import utils
def main():
plane_name = 'plane_axis2'
#Change origin through script function
xorig = 1.26
yorig = 7.52
zorig = 3.59
planes.ChangeOriginOfPlane(plane_name, xorig, yorig, zorig)
#Change section width through session command
utils.MetaCommand('plane options width 3 "'+plane_name+'"')
if(__name__ == '__main__'):
main()
For deleting entities the respective functions are DeleteXxx(), e.g. DeleteAnnotation(),
DeleteCurve(), DeleteModel(), etc.
The entities can also be deleted by applying the respective session commands.
For showing / hiding entities the respective functions are ShowXxx() and HideXxx(), e.g.
ShowAnnotation(), HideCurve(), ShowModel(), etc.
When more than one 3d model entities or curves need to be shown / hidden, it is much faster to
use the functions ShowSomeXxx() and HideSomeXxx(), e.g. ShowSomeElements(),
HideSomeParts(), ShowSomeCurves(), etc. In this case the entities must be given as matrix.
The entities can also be shown / hidden by applying the respective session commands.
For identifying 3d model entities the respective functions are IdentifyXxx(), e.g. IdentifyNode(),
IdentifyElement(), IdentifyMaterial(), etc.
When more than one 3d model entities need to be identified, it is much faster to use the functions
IdentifySomeXxx(), e.g. IdentifySomeElements(), IdentifySomeParts(), etc. In this case the entities
must be given as matrix.
The entities can also be identified by applying the respective session commands.
To get the properties of a material the script function PropertyOfMaterial() can be used. To set
these attributes the script function SetPropertyOfMaterial() can be used. If “all” is used as
argument for property type in the PropertyOfMaterial() function then all material information lines
will be returned, as in the input deck.
# PYTHON script
import meta
from meta import materials
def main():
model_id = 0
material_id = 1
property_type = 'all'
property_value = materials.PropertyOfMaterial(model_id,
material_id, property_type)
print(property_value)
if(__name__ == '__main__'):
main()
4.3.4.4.8. Get results/attributes of entities
First of all, to get the states for which the resultsets are needed, the functions that can be used are
CurrentResultset(), ResultsetsXxx(), FilterResultsetsXxx(), GeneratedResultsetsXxx().
If more than one labels exist for the resultset, the functions DeformationLabelsOfResultsets(),
FunctionLabelsOfResultsets() can be used to get directly all the label results of the state.
Alternatively, the functions StringDeformationLabelsOfResultsets(),
StringFunctionLabelsOfResultsets() can be used to get the available labels and then the functions
GetResultsetFromDeformationLabel() and GetResultsetFromFunctionLabel() can be used to get
the specific label result of the state.
After the needed resultset is found, the functions to get the loaded results depend on the entity from
which the result which is needed. So, in the Nodes functions group there are functions to get results
on the nodes, in the Elements functions group there are functions to get results on elements, in the
Parts functions group functions to get all results from a part, in the Materials functions group
functions to get all results from a material, in the Groups functions group functions to get all results
from a group and in the Models functions group there are functions to get all results from a model.
Moreover, there is a different function for each specific result needed. For nodes, to get the
deformation results, there is the function DeformationOfNode(), to get the coordinates
CoordinatesOfNode(), to get scalar results NodalScalarOfNode() and to get vector results
NodalVectorOfNode().
Similarly for results on elements, there are functions DeformationsOfElement(),
MaxDeformationOfElement(), CentroidScalarOfElement(), CornerScalarOfElement(),
NodalScalarsOfElement() and more.
For parts / materials / models there are functions that return the results on all the nodes or
BETA CAE Systems 116 META Automation User’s Guide
4. Scripting
elements, e.g. CentroidVectorOfPart(), and functions that return directly the maximum and
minimum result, e.g. MinMaxNodalScalarOfModel().
For CELAS spring connection elements the functions StiffnessOfElasElement,
DampingOfDampElement and MassOfMassElement can be used to get information about the
stiffness, damping and mass respectively.
To get and set the number of steps of an axis the functions StepsOfPlotAxis() and
SetStepsOfPlotAxis() respectively can be used.
To get, calculate, and set the material tension, compression, shear, x_tension, y_tension,
x_compression, y_compression, shear and f12 limits of composites materials, the functions
MaterialLimitOfMaterial() and MaterialLimitOfPart() or AddMaterialLimitOfMaterial() and
AddMaterialLimitOfPart() can be used respectively.
Remarks
When the function returns only one entity (e.g. NodalScalarOfNode()), then it returns the
meta_struct of this entity, when it may return more than one entities
(e.g. DeformationsOfElement()), then it always returns a matrix with meta_structs (even when only
one entity is returned).
# PYTHON script
import meta
from meta import results
from meta import nodes
def main():
model_id = 0
result = results.CurrentResultset(model_id)
node_id = 10
deform = nodes.DeformationOfNode(result, node_id)
if(results.IsValidDeformation(deform)):
print(deform.x,deform.y,deform.z,deform.total,
deform.node_id)
if(__name__ == '__main__'):
main()
# PYTHON script
import meta
from meta import results
from meta import models
def main():
model_id = 0
all_resultsets = results.Resultsets(model_id)
result = all_resultsets[2]
print(result)
nodal = models.MinMaxNodalVectorOfModel(result)
print(len(nodal))
if(len(nodal)):
min_nodal = nodal[0] #Struct with the minimum nodal vector
value
print(min_nodal.value) #Minimum nodal vector value
print(min_nodal.x,min_nodal.y,min_nodal.z) #Normalized
coordinates (X, Y, Z) of the minimun nodal vector value
print(min_nodal.node_id) #Id of the node with the minimum
nodal vector value
print(min_nodal.part_id); #Id of the part or -1 if no part
exists
if(__name__ == '__main__'):
main()
4.3.4.4.9. Get measurements from entities
The functions to get measurements depend on the entity from which the measurement is needed.
So, in the Nodes functions group there are functions to get measurements from the nodes, in the
Elements functions group there are functions to get measurements from the elements, in the Parts
functions group functions to get measurements from a part and in the Groups functions group
functions to get measurements from a group.
Moreover, there is a different function for each specific measurement needed. To get the distance
between a node and another node there is the function DistanceNodeToNode(), to get the distance
between a node and a part the function is DistanceNodeToPart(), etc. To get the angle formed by
nodes the function is AngleOfNodes(). To get the distance between a part and a group the function
is DistancePartToGroup().
# PYTHON script
import meta
from meta import results
from meta import parts
def main():
part_model = 0
all_resultsets =results.Resultsets(part_model)
part_result = all_resultsets[1]
part_type = 13
part_id = 1
group_model = 0
group_result = all_resultsets[2]
group_name = "My_Group"
if(__name__ == '__main__'):
main()
In cases that the connected elements or nodes are needed, the functions NeighbourElementsXxx(),
NodesOfElements() and ElementsOfNodes() should be used. In case of mesh independent
spotweld connections, where there is no node connectivity, the functions NeighbourElementsXxx()
can still be used as long as the connectivity is supported in META.
The above script functions should be preferred from the visibility session commands, e.g. “add
connected”, as the first are much faster.
# PYTHON script
import meta
from meta import elements
def main():
model_id = 0
element_type = 3
element_id = 1
second_id = -1
neighbour_type =3
neighbour_elements = elements.NeighbourElementsByType(model_id,
element_type, element_id, second_id, neighbour_type)
for e in neighbour_elements:
print(e.id)
if(__name__ == '__main__'):
main()
In cases that the connected elements, nodes, parts etc to connections are needed, the functions
ConnectedXxxOfConnection() should be used.
# PYTHON script
import meta
from meta import connections
def main():
model_id = 0
connection_id = 100001
connected_elements =
connections.ConnectedElementsOfConnection(model_id, connection_id)
for e in connected_elements:
print(e.id)
if(__name__ == '__main__'):
main()
There are functions to get data stored in a spreadsheet. To get a cells data the function
SpreadsheetCellByRowColumn(sheet_name, row, col) can be used.
Also the entire row‟s or column‟s data can be stored in a matrix through the functions
SpreadsheetCellsByRow(sheet_name, row). and SpreadsheetCellsByColumn(sheet_name, col).
Returned matrix stops at the last non-empty cell. If all cells are empty, an empty matrix is returned)
To get cells data of an entire cells area the functions SpreadsheetCellsByArea(sheet_name,
top_row, left_col, bottom_row, right_col) and SpreadsheetCellsByLabel(sheet_name, cell_label)
can be used. Cells data are stored in a matrix of same size as the defined spreadsheet area.
Also in order to identify the spreadsheet cells area that involves data the function
SpreadsheetBoundingArea(sheet_name) can be used. A matrix that determines the bounding box
of non-empty cells (matrix[0][0]: top-row, matrix[0][1]: left-column, matrix[1][0]: bottom-row,
matrix[1][1]: right-column) will be returned.
To get the attributes of specific entities of user Toolbars the functions CheckboxStateOfToolbar(),
SliderValueOfToolbar() and TextboxValueOfToolbar() are available.
# PYTHON script
import meta
from meta import utils
def main():
toolbar_name = 'Toolbar 1'
checkbox_name = 'Checkbox 1'
state = utils.CheckboxStateOfToolbar(toolbar_name, checkbox_name)
if state == 1:
print('Checked')
elif state == 0:
print('Not checked')
elif state == -1:
print('Failure!')
if(__name__ == '__main__'):
main()
For loading geometry the respective functions are LoadModel() for solver geometry data files and
LoadProjectModel() for geometries from META databases and META projects.
For loading field results the functions are LoadDeformations(), LoadModalDeformations(),
LoadScalar() and LoadVector() for solver results data files and LoadProjectDeformations(),
LoadProjectScalar() and LoadProjectVector() for results from META databases and META
projects.
The argument “data” which is needed for the functions is the same as the argument used in the
equivalent META session commands. The best way to retrieve the correct syntax is to load the
result manually from the META interface and view the session command passed to the current
META_post.ses file.
In order to append the loaded geometry/results the functions LoadAppendDeformations(),
LoadAppendProjectDeformations(), LoadAppendScalar(), LoadAppendScalarGetCoordSystems(),
LoadAppendProjectScalar(), LoadAppendVector(), LoadAppendVectorGetCoordSystems(),
LoadAppendProjectVector() are available.
For loading curves from history results files the respective functions are LoadCurvesXxx(), e.g.
LoadCurvesNastran(), LoadCurvesDyna().
The arguments which are needed for the functions, e.g. entities, variables, etc, are the same as the
arguments used in the META session commands. The best way to retrieve the correct syntax is to
load the result manually from the META interface and view the session command passed to the
current META_post.ses file. The only difference is that the results are passed as matrices to the
script functions. The string expressions can be easily changed to matrices and vice versa through
the functions RangeToMatrix() and MatrixToRange().
Especially for loading curves from RADIOSS history results files, the function LoadCurvesRadioss()
needs the time history id as argument. In case the time history id is not known, strings „all‟ or „*‟ can
be used referring to all available time history ids or the function GetRadiossTimeHistoryId() can be
used to find the time history id for a specific history result.
The entities can also be loaded by applying the respective session commands (see also chapter
“META session commands for use in Scripting Language”). However, one advantage of loading the
entities through script functions is that the function returns the structs of the created entities. For
example, when loading a model through the script function, the id of the model is available.
# PYTHON script
import meta
from meta import models
from meta import results
def main():
window_name = 'MetaPost'
filename = '/home/demo/example.op2'
deck = 'NASTRAN'
r = models.LoadModel(window_name, filename, deck)
if models.IsValidModel(r):
model_id = r.id
states = '1-3'
data = 'Displacements,Translational'
new_resultsets =results. LoadDeformations(model_id,
filename, deck, states, data)
data = 'Stresses,VonMises,MaxofTopBottom'
new_resultsets = results.LoadScalar(model_id, filename,
deck, states, data)
for res in new_resultsets:
print(res.name,res.nodal_data_name,res.function_data_name,res.stat
e)
if(__name__ == '__main__'):
main()
# PYTHON script
import meta
from meta import plot2d
def main():
window_name = 'Window1'
plot_id = 0
filename = '/home/demo/exmampleT01'
entity_id = '12954'
entity_type = 'node'
variable = ""
time_history = [ plot2d.GetRadiossTimeHistoryId(filename,
entity_id, entity_type, variable) ]
#time_history = ['all' ]
entities = [ entity_id ]
variables = [ 'dx' ]
new_curves = plot2d.LoadCurvesRadioss(window_name, plot_id,
filename, entity_type, time_history, entities, variables)
for c in new_curves:
print(c.id)
if(__name__ == '__main__'):
main()
Remarks
The deck of the results is given as argument in the functions to load geometry and field results,
whereas different functions exist for each deck for loading history results.
Apart from loading solver results, it is possible to create user defined field results using the results
from calculations realized inside the script.
First of all a new empty state for field results can be created with the function CreateResultSet().
To add a new label to the resultset and set the results to the nodes or the elements, the functions to
be used are AddDeformationOnAllNodes(), AddNodalScalarOnAllNodes() and
AddNodalVectorOnAllNodes().
For more complicated procedures:
To reset all the values of a resultset and add values to the nodes or the elements, the functions to
be used are StartAddingXxx() and EndAddingXxx(), e.g. StartAddingDeformations(),
EndAddindDeformations().
To change the values of a resultset the functions to be used are StartChangingXxx() and
EndAddingXxx(), e.g. StartChangingCentroidVector(), EndAddingCentroidVector().
To append a new label to a resultset and set values to the nodes or the elements for this label, the
functions to be used are StartAppendingXxx() and EndAddingXxx(), e.g.
StartAppendingCentroidScalar(), EndAddingCentroidScalar().
Between the StartXxx() and EndXxx() functions the values can be assigned to the nodes with the
functions AddCentroidScalarOnElement(), AddCentroidScalarOnSomeElements(),
AddCentroidVectorOnElement(), AddCentroidVectorOnSomeElements(),
AddCornerScalarOnElement(), AddCornerScalarOnSomeElements(), AddDeformationOnNode()
and AddDeformationOnSomeNodes(). When values are to be to more than one elements / nodes,
functions XxxOnSomeElements() and XxxOnSomeNodes() should be preferred, as they are much
faster.
Improtant Note: The EndAddingXxx() function must be called at the end, or else the values will not
be assigned to the resultset.
When executing scripts in META some points should be taken into consideration in order to achieve
minimum execution times.
- When the script includes functions that change the display of the META windows, each redraw will
result to time consumption. To speed up the execution of the script, the redraws can be disabled,
and enabled only at the end of the script, in order to display directly the final state.
This can be achieved through the lines
MetaCommand('options session controldraw disable')
MetaCommand('options session controldraw enable')
- When a function needs to be applied on more than one entities, it is always faster to use the
function that applies directly on all the needed entities XxxOnSomeXxx, e.g. IdentifySomeNodes(),
AddElementScalarOnSomeElements(), etc, instead of applying the single function for each entitty.
- When all the results from entitiy are needed, it is faster to use the function that gets all the results
directly, e.g. DeformationsOfModel, CentroidScalarOfPart(), etc, instead of getting the result for
each element / node separately.
- In cases the connected elements or nodes are needed the functions NeighbourElementsXxx(),
NodesOfElements() and ElementsOfNodes() should be preferred from the visibility session
META scripting language enables the creation of user defined buttons and fully customized
graphical interfaces. The buttons that can be created are similar to the buttons of the GUI and are
used to invoke user functions. For the management of specific tasks that must be controlled
through a number of definitions and actions, it is very useful to create a custom GUI. There are two
libraries of functions to create custom user interface. The first supports only the basic widgets that a
GUI can hold, like checkbuttons, radio buttons, menu buttons, lists, tables, while the second library,
BCGUI functions, is more extensive and except from the main widgets mentioned before it also
supports hundreds of more sophisticated tools. These tools allow the creation of any complex
interface that may also contain tab widgets, popup menus, spin boxes, group of buttons, tooltips
and so on. The first library is similar for Python and BETA Scripting language and is described in
the relevant paragraph of the chapter BETA Scripting Language. The second library is described in
a separate chapter for both Python and BETA Scripting Lanuage.
4.4.1. Introduction
Script is a code (series of commands) written in the, C-like, BETA scripting language and is saved
as text file. An example of script code follows:
def Main()
{
//Comment
count = 0;
pshells = CollectEntities(NASTRAN,0,"PSHELL",0);
foreach pshell in pshells
{
GetEntityCardValues(NASTRAN,pshell,"Name",name);
pos = MatchString(name,"Default");
if(pos)
{
to_del[count++]= pshell;
}
}
DeleteEntity(to_del,1);
}
4.4.2. Syntax
Commands Each command consists from a series of valid words and characters
that ends to a semicolon (;). Execution of a command is not
depended on the lines on which this is written. Thus all the following
three examples pass the value 1 to the variable a, and print its value
in the Output and META terminal window.
Spaces Spaces count only to separate string words, otherwise they are
ignored. Also multiple spaces in a row count as one space. Thus:
Print(“aa”); is the same as
Print ( “aa”) ; but different from
Print(“a a”); as this prints: a a and not: aa
Also:
PrintMonitor(“text”); prints the word “text” in a monitor
window and
Print Monitor(“text”); leads to a syntax error while
Print Monitor is not a valid syntax for the Print command.
Capital and lower case META scripting language is case sensitive. Thus:
if (a==1)Print(a); prints the a variable value if is equal to 1 and
Comments Comments are script code lines that are not taken into consideration
when the script is parsed and executed. These lines are generally
used to inform the developer.
Rows starting with // are considered as comments. Also anything
that follows the // in a row is commented out.
The data type determines the kind of data that a variable or a function can hold. Data types include
integer or floating point numbers, strings, matrices etc, as well as user defined types. The following
paragraphs describe the available data types for writing an META script. Note however that
variables used in META scripts, are considered typeless.
Integers
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;
Strings
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 internally represented as arrays of characters.
s = "a string";
Elements
This is a specific data type used in functionality to create windows and in specific functions in
ANSA.
Typically, the element data type is used in the declaration of function arguments.
In many cases, user scripts can be more elegantly and concisely expressed if they can be written in
terms of aggregate structures. Such structures can be considered as user defined data types that
represent a collection of one or more variables, possibly of different types, grouped together under
a single name for convenient handling. The keyword used to declare such collections is struct and
the individual variables within the collection are called its members.
A very important feature of META scripting is the use of meta_structs variables. meta structs is a
special group of structs, which are used to carry information about entities in META and through
them it is possible to access and modify their data.
In order for meta structs to be used, they need to be defined first. Their definition exists in the file
meta_structs, which is provided with the META software inside the folder config. This file must be
included in each script that uses meta structs through the keyword
#include "meta_structs"
The above line is inserted automatically each time the user selects to create a new script. With the
above line, META searches to find the file in the config directory.
An example of a meta struct is the meta_struct for the elements:
Elem:
meta struct elem is used to carry information about the elements loaded in META. It has the
following structure:
struct {
int id; // Id of the element
int second_id; // Second id of the element (GAP, TUBE, JOINT) , -1 if
there is not a second id
int model_id; // Model number of the element
int type; // Type of the element
int subtype; // Subtype of the element
int visible; // 1 if element is visible, 0 if model is not visible
int part_id; // Id of the part it belongs to, -1 if element belongs to
no part
} elem;
4.4.4. Variables
4.4.4.1. Introduction
A variable is a named memory location that contains data and can be modified during script
execution. Every variable is distinguished according to its data type and its value:
The data type describes what particular kind of data is stored in a variable, such as an integer
number, a string etc. As seen earlier, variables are typeless, i.e. their type is defined by the way the
variables are used.
The value of the data that a variable contains at any point is determined by the instructions of the
code and, of course, this value will usually change many times during program execution.
The variable's name is called an identifier, or more conveniently, a variable name. Variable names
can include the letters A-Z (in upper or lower case), the numbers 0-9 and the underscore character.
All other characters including the blank space are illegal. A variable name is case sensitive and
must begin with a letter or an underscore. Names usually indicate the kind of information that is
stored in the variable and must be chosen in a manner that will not confuse the user. The following
table lists some valid and invalid variable names:
Although the number of characters in a variable name can be unlimited, it is usually a good
programming practice to keep it short. Furthermore, the language reserves some "names" as
"keywords". These names are used to represent internal functions and are not allowed to be used
as variable or function names.
The reserved characters and for writing a META script are listed below:
When writing META scripts, it is not necessary to explicitly define the data type of variables. This is
because all variables used in META scripts are considered by default typeless and automatically
acquire the proper data type depending on their use at the time. For example, in a statement like:
my_var = 13;
the variable my_var is treated as being of integer type. But, if later on, the same variable is found
in another statement like:
my_var = "my string";
it will switch from integer to string type.
The use of typeless variables reduces the total number of variables used in a script, since the same
variable can be used in different ways. However, typeless variables can be proven dangerous when
they must be passed as arguments to a function, since the function should be aware as to how to
treat these variables. Thus, in such cases, the data type of all variables that are communicated to a
function must be explicitly declared in the functions' arguments. For example, if 'var1', 'var2' and
'var3' represent integer, float and string variables respectively, they should be declared as:
def my_function (int var1, float var2, string var3)
A variable can get a unique and unchangeable value if defined as constant. Once it is defined, it
keeps its original value even if later on is given a different value. This kind of variables can be
declared in global or function code using the keyword const followed by the type of variable. The
type is auxiliary and is used only for the definition.
const float pi = 3.14;
def main()
{ pi = 3;
Print(pi);//The 3.14 will be printed
}
A very frequent problem for all programmers is the spelling of variables. Especially in lengthy codes
where there is a significant number of variables, an error like that can cause erroneous results and
a serious waste of time for debugging. This can be totally avoided if using the statement #stricton
written in the global section of the script. The parser issues a warning when it comes across an
undeclared variable. The variable type is given explicitly either in the global section or within a
function and it is not binding. The script stops this check by invoking the statement #strictoff. Thus,
any code located between the two statements is examined for variables‟ spelling errors.
float b;
float param;
def main()
{
a = 1;
b= 1.2;
value = a*b;
params = a/b;
}
#strictoff
Remarks:
- Although the variables get a type, they are still typeless.
- There is no restriction to the number of times the #stricton and #strictoff can be invoked inside a
script.
- #strictoff is the default state.
Most problems that occur in practice require more than simple variables for their definition and
solution. Thus, it is often necessary to handle data as sets of similar or different kind objects.
Towards this direction comes the definition of matrices and maps.
4.4.5.2. Matrices
A matrix data type provides a way to collect entities under the same storage. As a good
programming practice, matrices should be declared so that the program will reserve enough space
to store the data. The corresponding keyword for this declaration is matrix.
Since matrix members are actually variables, they can hold any type of variable, so a matrix like:
m = {1, 1.23, "some string", "a", 2, 99.23};
is perfectly valid.
Example
matrix m={1,2,3,4};
m={1, 1.23, "some string", "a", {2, 3.15, "string2"}, 99.23};
m[532]=56.7;
The memory reserved for the matrix depends on the position of the last member in the matrix, so
the user has to be very careful in order not to reserve unused memory. In the third example above,
if this is the first definition regarding the matrix m, 533 places of memory (from 0 to 532) will be
reserved although the other positions of the matrix have not been assigned any value from the
user.
The functions dealing with the creation and manipulation of matrices are presented in paragraph
“Handling Matrices”.
4.4.5.3. Maps
A map data type can be seen as an expansion of the matrix, since the indexing is done with
arbitrary values. The keyword that specifies this data type is map.
A map is characterized by a name and is like a user defined tree-structure, where each node holds
a specific value and is referenced by a specific key. The key can be of any data type.
A map is initialized using the command CreateMap:
m = CreateMap();
Example
m = CreateMap();
m[1140]=1;
m["some string"]=10.5;
In maps, memory is reserved only for the specific node in the map, for example when typing
m = CreateMap();
m[1140]=1;
only one position will be reserved in memory contrary to the case m was a matrix, where 1141
positions would be reserved.
The functions dealing with the creation and manipulation of maps are presented in paragraph
“Handling Maps”.
Note that a map is the only data that needs to be destroyed, as the memory used by it is not
automatically released at the end of the execution of the script.
Various data types can be combined, by the appropriate operators, to form expressions. These
expressions are evaluated when the script is executed. The results of a calculation can be stored
for future use by assigning a value to a variable. This is done by an assignment statement whose
general form is:
<variable name> = <expression>;
where <variable name> is the name of the variable, while <expression> is an expression
formed by the combination of variable names using operators.
The sets of operators and the rules of how expressions may be written and evaluated are
determined by the types of the operands involved. Therefore, the data type is a very critical attribute
of any data value.
An expression is formed by the combination of variables, constants and operators. Operators are
used in order to compute new values out of old ones, and can be arithmetic, assignment,
increment / decrement and logical operators. Operators can also be used in expressions and
assignments for string data types.
There are five different arithmetic operators that can occur in numeric expressions. These are:
# Operator Operation
BETA CAE Systems 131 META Automation User’s Guide
4. Scripting
1. + Addition
2. - Subtraction
3. * Multiplication
4. / Division
5. ** Exponentiation
The assignment operators are the ones that actually assign a value to a variable. The well-known:
“=“ sign, is an assignment operator. For example
x = 1;
sets 1 to variable x, and
a = b;
sets to whatever b's value is. The expression:
i = i + 1;
is a standard programming idiom for increasing a variable's value by 1, while
i = i - 1;
i = i * 2;
i = i / 2;
will decrease a variable‟s value by 1, multiply and divide it by 2 respectively.
For the most common cases where we add or subtract the constant value 1 from a variable, META
scripting language allows the use of auto-increment or auto-decrement operators. In their simpler
form, they look like this:
i++;
i--;
These expressions correspond to the slightly longer:
i += 1;
i -= 1;
and to the fully expanded:
i = i + 1;
i = i - 1;
# Operator Meaning
BETA CAE Systems 133 META Automation User’s Guide
4. Scripting
Characters may be assigned to string variables, using statements similar to those of numeric types:
property = "PSHELL";
mat_name = "steel_105";
The operators that can be used to form expressions between string data types are:
# Operator Meaning
1. + string catenation
2. % string catenation
A typical example of a user defined data type is the meta struct node. Its structure is the following:
struct {
int id; // id of the node
int model_id; // Model number of the node
float x; // X coordinate of node
float y; // Y coordinate of node
float z; // Z coordinate of node
int visible; // 1 if node is visible, 0 if node is not visible
} node;
The above line defines a structure called node whose members are the integers called id and
model_id three floats for the coordinates x, y, z and an integer which defines if the node is visible.
Each node occupies a position in space as dictated by its coordinates and may also have a unique
ID and a unique model ID to distinguish it from other nodes.
Once the structure is defined, it can be used as a regular data type for the declaration of other
variables. For example, to declare a node n in space, just type: node n;
Now, the n variable can automatically reference the members of the node structure. In other words
structure “n” can reference its id and its x, y, z coordinates.
The syntax for this reference is struct.member and in this case takes the form:
Reference Meaning
n.id …the id of node n
n.model_id …the id of the model of node n
n.x …x-coordinate of n
n.y …y-coordinate of n
n.z …z-coordinate of n
n.visible …the integer defining if the node is visible
Examples:
Reference Meaning
n.id = 13; assign number 13 as the id of node PA
n.x = 123.45; assign the x coordinate of node PA
n.y = 321.00; assign the y coordinate of node PA
n.z = 456.78; assign the z coordinate of node PA
As an extension to declaring a single node n that belongs to the structure node, an array (matrix) of
nodes can be declared. For example, to declare an array called nds of 10 nodes in space using the
structure node type:
node nds[10];
The reference to the individual variables of the nds array follows the same rules as before. For
example, to assign 13 as the id of the 5th node of the nds array, the following should be typed:
nds[5].id = 13;
and to assign the coordinates of nds[5] type:
nds[5].x = 123.45;
nds[5].y = 321.00;
nds[5].z = 456.78;
When a script function is used that returns a matrix of meta structs, for example
el_nodes = NodesOfElement(model_id,element_type,element_id,second_id);
the variable element_nodes has to be defined as a matrix, although it contains meta structs.
Structure members cannot be accessed through expressions like:
el_nodes[3].id
To access the data of a member directly the following steps should be followed.
- first define a meta struct variable
- assign to it the desired matrix member and
- access the data of the meta struct variable.
The examples below show how the data of returned meta structs can be accessed, either using the
foreach statement or directly.
Example
node n; node n;
matrix el_nodes; matrix el_nodes;
el_nodes=NodesOfElement(0,7,66,5); el_nodes=NodesOfElement(0,7,66,5);
foreach n in el_nodes n=el_nodes[0];
{ Print(n.id); Print(n.x);
Print(n.id); Print(n.x); Print(n.y);
Print(n.y); Print(n.z); n=el_nodes[3];
} Print(n.id); Print(n.x);
Print(n.y);
The if statement, is the basic decision statement of a script. Its operation is based on the evaluation
of a condition that will yield a result that is either true or false. If the condition is true (i.e. not equal
to 0), then the if-block of statements is executed. If the condition is false, then the else-block of
statements is executed. The if statement general form, is:
if (condition)
statement;
The switch statement is an alternative form of a conditional statement, which allows the definition
of multiple possible execution paths. The general form of the statement is:
switch (expression)
{
case constant1:
statement;
....
break;
case constant2:
statement;
/* fall through */
case constant3:
statement;
....
break;
....
default:
statement;
break;
}
The switch statement evaluates the value of an expression and branches to one of the case labels.
Duplicate labels are not allowed, so only one case will be selected. The expression can evaluate an
integer or a string. The case labels can be in any order and must be constants or strings. The
default label can be placed anywhere in the switch. Note that two case labels cannot have the
same value. When META reach a switch statement, it evaluates the expression and then looks for
a matching case label. If none is found, the default label is used. If no default is found, the
statement does nothing, e.g.:
a = 2;
switch (a)
{
case 0:
Print("a is zero");
break;
case 1:
Print("a is one");
break;
case 2:
Print("a is two");
break;
/* will fall through default as well */
default:
Print("a is not zero");
break;
}
The result is: 'a is two'.
The goto statement is a powerful branching statement. It can be used to create jumps and redirect
the execution order of a program. Its general form is:
goto < label >
The foreach statement allows the iteration over the elements of an array. foreach loops do not
maintain any explicit counter. The general form of the statement is:
foreach <item> in <array>
{
do something to <item>
}
the result is
1
2
3
4
5
foo
The for statement introduces an indexed loop, where the number of repetitions is known before the
loop is started. The general form of the for statement is:
for (initial-statement; condition; iteration-statement)
body-statement;
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.
for (a=0; a<5; a++)
Print (a);
the result is
0
1
2
3
4
Remarks
- When a foreach or for loop statement affects only one line then it is not necessary to enclose this
line in brackets:
The while statement introduces a conditional exit loop. The program executes the specified
statements repetitively for as long as the given condition remains true (i.e. not equal to 0). Its
general form is:
while (condition)
body-statement;
If operators are to be used for the expression of the condition, these must be of logical relational
type.
a = 0;
while (a<3)
{
Print(a);
a++;
}
While the for and while statements check the condition before entering the loop, the do while
construct makes the check after every pass of the loop and thus guarantees that at least one pass
will take place. Its general form is:
do
body-statement;
while (condition);
the result is 1.
The continue and break statements can be used to redirect the execution order of a loop. The
break statement allows the termination of a loop regardless of the loop control condition. In other
words it can lead to an unconditional branching. A typical example is given below:
a = 0;
while (a<5)
{
Print(a);
a++;
if ( a == 3)
break;
}
In this case the result would be:
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++;
if ( a == 3)
continue;
Print(a);
}
In this case the result would be:
1
2
4
BETA CAE Systems 141 META Automation User’s Guide
4. Scripting
Most problems that occur in practice require more than simple variables for their definition and
solution. Thus, it is often necessary to use matrices as sets of data.
To set some data to a specific position in a matrix type:
m[3] = 10;
To specify all the matrix members at once:
m={10,7,9};
Matrix members can be other matrices, e.g.the expression forms a 3x3 2-dimension matrix:
m = {{10,7,9},
{5,2,17}
{6,12,25}};
To retrieve a value of a specific member of a matrix, the user must provide the corresponding index
operator:
i = m[0];
For the 3x3 2 dimension matrix given above, the following expression will assign to i the value of 5:
i = m [1][0];
Remarks
- There is also available the MatSize function that retrieves the same result as MatLen.
- Note that matrices are always stored in memory as one dimensional entity.
- An entity in a matrix may be also a matrix.
- Writing a matrix in a row, column format is not necessary for each row to consist of the same
number of columns. A matrix like the following is absolutely valid:
M = {{10,{1,2},9,8,90},
{4,6},
{5,3,17}};
All algebraic operations between matrices and constant values are interpreted as operations
between each member of the matrix and the constant value. For example the expression:
B = 10*A;
will result to a matrix B, whose members are 10 times the corresponding members of A.
Addition, subtraction, division and exponentiation operations between matrices should take place
only between conformable matrices (i.e. matrices having the same shape).
On the other hand, the multiplication operation can take place between matrices only when the
second dimension of the first matrix equals the first dimension of the second matrix. This means
that, if the first matrix is A (a x b) and the second matrix is B (c x d), then b must equal with c in
order to multiply the matrices.
Having two non-conformable matrices (i.e. A 2x3 and B 3x1):
A = {{10,7,9},
{5,2,17}};
B = {{1},
{2},
{1}};
a multiplication operation:
C = A * B;
will lead to a matrix C 2x1:
C = {{10*1+7*2+9*1},
{5*1+2*2+17*1}};
while a multiplication operation:
C = B * A;
leads to error.
Strings can be treated as matrices, so any part of them can be isolated without the use of any built
in function. A string corresponds to a matrix, which has a length equal to the number of characters
that comprise it. Each character corresponds to a matrix member. The first character has index 1
and the last has index equal to the string length.
Example
str = "Bumber_Front";
The above string has 12 characters where “B” has index 1, “u” has index 2……and “t” has index 12.
We can get any part of the string by using the indices of the characters. Here are some examples:
str = str(1:6); //This will get the "Bumber"
str = str(8:12);//This will get the "Front"
str = str(8:8); //This will get the character "F"
str = str(7:7); //This will get the character "_"
str = str(3:8); //This will get the "mber_F"
str = str(5:); //This will ge the "er_Front"
str = str(:7); //This will get the "Bumber_"
The size of a string (an integer) can be obtained calling the built-in function „Strlen‟:
length = Strlen(s)
The function „TokenizeString‟ splits a string according to a specified character and returns a matrix
containing each split part of the string as matrix members.
TokenizeString (string s, string t, integer flag);
Example
str = "one/two";
m = TokenizeString (str, "/", 0 );
Two strings can be combined to create a new one, containing the text of both. This is achieved by
the string catenation operators or using the built-in function „Strcat‟.
Examples:
new_string = old_string1 % old_string2;
new_string = old_string1 + old_string2;
Strcat(string1, string2);
The difference between the use of catenation operators and the command Strcat is that 'Strcat'
actually uses the first string as destination of the operation, thus modifying its value.
The function „Strcmp‟ performs a lexicographical comparison between the two strings:
val = Strcmp(s1,s2);
if val < 0 then s1<s2
if val > 0 then s1>s2
if val = 0 then s1=s2
Finally, the function 'Strcpy' copies the contents of a string into another:
Strcpy(a,b);
copies b to a (copies the second string to the first and it returns the destination string).
Alternatively it can be written as:
a = b;
A map is characterized by a name and is like a user defined tree-structure, where each node
holds a specific value and is referenced by a specific key:
(map_name, key, value)
To use a map, it does not need to be defined first, but it needs to be initialized using the command
CreateMap:
m = CreateMap();
To manipulate the map node values, array like indexing or the following script functions
SetMapNode(m, key, value) and GetMapNode(m, key)
can be used.
The value of a map can be either a string or a number. However, the key can be a string, a number
or even another map. Nodes within the same map are sorted according to their key. The
corresponding precedence order is
String < map < number
For example, node (m,"1140",1) comes before node (m,1140,2), since the former node uses a
string-type key and the latter node uses a numeric key. Note that when maps are used as keys,
they are sorted according to the number of nodes they have, with larger maps taking precedence
over smaller maps.
Example
In order to search through the data of a map, the user must first identify the first or the last node of
the map using the GetFirstNode or the GetLastNode commands respectively:
i = GetFirstNode(m, key, value);
i = GetLastNode(m, key, value);
Both functions return 1 on success and 0 upon failure (e.g. when the map is empty or not defined).
Looping through the map is achieved using the GetNextNode and GetPreviousNode commands:
i = GetNextNode(m, key, value);
i = GetPreviousNode(m, key, value);
Example
for(ret=GetFirstNode(m,key,value); ret; ret=GetNextNode(m,key,value))
{
Print(key);
Print(value);
}
Remark
- The foreach command can also be used to loop through the data of map.
User functions allow to group a set of operations into a compact unit that can be easily and
repeatedly accessed. The repetitive use of functions saves much time while reduces the chances of
error. Each user function is given a name, optionally uses some input parameters (arguments) and
returns the results as output parameters.
4.4.10.2. Definition
User functions are defined using the def statement. This statement is followed by the function
name. The rest of the code must be enclosed in brackets. A typical function has the form:
def main(list of arguments if exist)
{
.......
Statement
.......
}
Each user-defined function accepts a number of input arguments (<=40). These arguments are
passed as parameters and are used as initial values inside the function that is called. During the
declaration of a sub-function it is necessary to define explicitly the type of the input arguments: (int,
float, string, element etc)
Remarks
- A sub-function can be called from a main function or from another sub-function.
- Variable number of input arguments is not valid.
Examples:
def main()
{
Print("This is an example of a function");
}
A new functionality introduced after v6.3.0 enables the definition of functions‟ names as variables.
The benefits from this are multiple since all actions inside a code can be controlled parametrically.
A useful implementation could be the following: Imagine that it is needed to call different functions
with same data sequentially. Instead of using an if structure which makes the code difficult to
maintain, a parametric call would be more handy.
def main()
{
s = {1,3,"title"};
functs = {"test1","test2"};
for(i=0;i<2;i++)
{
functs[i](s);
}
}
Since the target of each sub-function is to perform a certain task, there must be a way to notify the
main function that called it for the result of the procedure it performed.
The communication between the functions can be achieved through the return command. This
command can be used anywhere in the code and is followed by any data. A function that calls
another function can store the returned value in an output argument or even can ignore it.
Functions that don‟t return anything are executed normally and may not use the return command.
Equivalent, they can return a dummy value.
Only the data that are passing through the return command are valid for the main function.
Remarks
BETA CAE Systems 148 META Automation User’s Guide
4. Scripting
- If the return command is used in the main function, then the execution of the script is terminated.
Another way of exchanging data is through the byref statement. This is very useful in cases where
it is important for the user to know the new modified values of any variables that had been passed
to a sub-function.
def main()
{
width=10;
height=3;
area = RectArea(width, height);
}
def RectArea(byref int w, int h)
{
a = w * h;
w = 20;
return a;
}
In the above example, the values of the variables right before the end of the execution of the scripts
will be:
Variable Value
width 20
height 3
area 30
a not defined
w not defined
h not defined
Remarks
- The matrices, the maps, the structures and the pointers are considered byref by default.
A variable's scope is determined by its location. When a variable is declared within a function, then
only the function's code can access or change its value. It is then said that this variable is local to
the function. As a result, there is no conflict to have two or more variables of local character sharing
the same name in different functions.
In contrast to local variables, global variables are valid throughout the program, so they can be
accessed and changed by any individual function of the program. global variables must be
declared prior to the definition of any function (global section), and are defined either using the
global keyword or by declaring their type followed by their name. The type is auxiliary and helps
the language to distinguish a local from a global variable. As said before, the variables still remain
typeless. In the following script code the variables k, name, value, inline and i are considered
as global variables and j as local.
int k;
string name;
float value;
def main()
{
j = 10;
Print(inline);
Print(i+j);
}
However, a variable can be declared as local and global simultaneously in the same script. In this
case it can be treated as being two different variables if using the scope operator „::‟
int a;
def main()
{
int a;
a = 3;//This value is assigned in local 'a'
::a = 5;// This value is assigned in global 'a'
i = a+1;
Print(i);
k = ::a+1;
Print(k);}
}
There is also a third type of variable called static. Static variables are the variables, which can keep
their value even if the execution of the script has come to an end. However, static variables retain
data only when the script file is loaded as a module.
In META, it is better to hold data between executions of functions using META variables.
def main()
{
i = Atoi(MetaGetVariable("meta_i"));
i = i++;
Print(i);
MetaSetVariable("meta_i", i);
}
A function can be hided even it is not a static one. This is very useful especially in cases where a
function must not be seen, accessed or invoked from other users. This function although is loaded
normally is not visible and thus it considered private. However, in META scripting language all
functions are by default public. The private: statement is used to create such functions while the
public: turns the code in the default status.
def main()
{
test1();
test2();
test3();
}
def test3()
{
Print("test3");
}
Scripting language enables the collection of several existing functions into a file. This declaration is
made with the #include statement. Each line like the one below:
#include "fullpath to the name of file"
is substituted from the contents of the included file (the quotes are necessary). The include
statement, must be declared in the global section of the script and its usage has two major
advantages:
1) The files remain short.
2) Assures that no mistake will be made since no cutting or pasting actions are performed.
#include "/home/work/CreatePoint_struct.bs"
def CreatePoint()
{
set_P point;//The set_p structure is placed in "CreatePoint_struct.bs"
//x,y,z members were defined in "CreatePoint_struct.bs"
point.x = 11;
point.y = 10;
point.z = 3;
}
Remarks
- It is recommended to avoid using include files for loading functions. On the contrary, they should
be used only for type definitions (structs, global variables, etc).
External files can be treated also as project files. This declaration is made in the global section with
the #projectfile statement. Each line like the one below:
#projectfile "fullpath to the name of file"
it is NOT substituted from the contents of the project file (the quotes are necessary) but only
enables the usage of file contents. Static variables sharing the same name but located in different
project files are loaded normally.
META scripts can be compiled only through Script Editor (see also respective Chapter). The
compiled script is treated as any other script - regarding loading and executing - but it cannot be
edited since it is not human readable anymore.
Sometimes, a code must be partially compiled either for security reasons or for keeping as small as
possible the size of a file. This job is controlled through the internal script preprocessor which
searches for specific statements/keywords. A part of a code is defined in the preprocessor via the
#define keyword followed by an identifier which can be anything:
#define status
The existence of an identifier is checked through the #ifdef, #if defined and #ifndef keywords. All
definitions can be optionally combined with an #else statement but definitely must end with an
#endif. The code between the above statements is ignored.
Suppose that a script must be compiled and specific users need to have different level of access to
included functions. In this case, it would be very annoying and time consuming to maintain two or
more versions of the script. Thus, the best solution would be to assign the relevant functions in the
pre-processor.
The compiled version of next script is appealed to „user1‟ and will not contain the function
„fun_for_user2‟.
If the user that is going to use the script is „user2‟ then just comment out (//) the first line:
„#define user1‟ and uncomment the second one:
„#define user2‟.
In this case the „fun_for_user1‟ will be ignored. In the same way different compilations schemes
Remarks
- The logical operators: !, ||, && are allowed.
#define FOO
#define GOO
#define ZOO
#if defined FOO && (!defined GOO || defined ZOO)
def main()
{
#endif
Another use of preprocessor is to protect the user from loading a part of a code more than once. A
concrete example is when a file includes some scripts and additionally one of them includes again
at least one of the previous included scripts. If the double defined script contain only user functions
this wouldn‟t be a problem because the last read will be kept. But, if the script contains global code
like a struct definition this can cause problems. To avoid this, it is recommended to add within all
included scripts a series of preprocessor statements that will ensure no multiple definitions.
Consider that Script1 is used as include and contains only a structure defined in the global section.
Script2 includes Script1 and Script3 which in turn includes Script1.
Such an improper definition leads to a syntax error and no loading takes place. If instead, the
structure had been defined as part of the preprocessor, the corresponding code would be loaded
only once and any other time the Script1 was invoked, it would be ignored.
Thus the correct approach could be the following:
Finally, the identifiers MACHINE_NAME and USR_NAME can be used in the same manner for
acquiring the name of the machine and the user's name.
Recursive structures are supported in scripting language. This means that a function can call itself
as many times as needed. Recursive structures in META have been proved very helpful when
trying to search into entities that have a hierarchical structure. A common example is the extraction
of all META files that exist under a directory tree.
def main()
{
filenames = 0;
path = "/home/demo/model";
type = "META";
parse_tree(filenames,path,type);
}
A well-structured algorithm implies that any variables or matrices that change their values during
the execution of a script must be first initialized. The initialization is very crucial especially when a
variable is used as counter for filling the indices of a matrix. Variables or matrices are initialized by
assigning to them an initial value (zero value is preferred in most of the cases).
To release the memory occupied by matrices, the ReleaseVar function can be used to reset them
to uninitialized state. This function comes handy in cases an existing matrix must be refilled with
new data.
def main()
{
//Initialize counter i
i = 0;
//Initialize matrix m
m = 0;
//Define matrix data1
data1 ={10,20,30,40};
len = MatLen(data1);
for(k=0;k<len;k++)
{
m[i++] = data[k];
}
.....
statements
.....
data2 ={1,2,3,4};
ReleaseVar(m);
len = MatLen(data2);
for(k=0;k<len;k++)
{
m[i++] = data[k];
}
.....
statements
.....
}
Initialization of variables can also be done in global section but only if they are preceded by their
type. For example all the following declarations made in global section are valid.
int a = 10;
float b = 2.5;
string s = "alpha";
def main()
{
c = a+b+100;
Print(c);
}
Keep in mind that the type is not binding since it is only used for syntax checking. Thus, it can be
changed anytime.
Finally, a variable can get an initial value from a function call not only within the function code but in
global section too. This is the way of invoking a function before the 'main' or other user defined
def main()
{
...
...
}
def InitVal()
{
no_of_props = MatLen(CollectEntities(NASTRAN,0,"PSHELL"));
return no_of_props;
}
Past experience has proven that even experienced programmers need to write some comments
within the code to make it more readable and understandable. In META scripting language there
are two ways to add comments. Using the symbol // ideal for single-line comments and including
multiple-line comments within the bounds of a /* comment */.
def my_fun()
{
part p;
matrix group_parts;
model_id = 0; //Define the id of the model
group_name = "My_Group"; //Define the name of the group
//Collect the parts
group_parts = PartsOfGroup(model_id, group_name);
/*Print the id and the name
of the collected parts*/
foreach p in group_parts {
Print(p.id+”: ”+p.name);
}
}
A comment line denoted by // symbol can be incorporated in a comment block (/* comment */).
A script function can also have its own help description. This description is a text that must be
enclosed between the symbols ## and must be written always prior to the function which describes.
##
Name: NcogToSet
Description: Function that adds the Ncog nodes of PAMCRASH rbodies to a
set
##
def NcogToSet()
{
statement
}
The user script help can be accessed through the File>Script>Run function.
The basic idea behind the scripting language is to automate many repetitive and tedious
procedures with the minimum user interaction and to perform specific tasks that are not covered by
the standard META commands and META session capabilities. Some of the tasks that can be
performed within scripting language are the following:
- Extracting any type of information from an already loaded model (data from nodes, elements,
boundary elements, materials, models, coordinate systems and groups).
- Access and manipulate data from META entities like annotations, groups, cut planes and
isofunctions.
- Manipulating 2D plots: create and select curves, access data from curves and their points and
modify them.
- Creating new results (deformation-scalar-vector) on nodes and elements with custom calculated
data.
- Creating and manipulate META 3D and 2D windows.
- Creating user-defined windows.
- Manipulating files and directories.
- Reading and writing ASCII and binary files.
- Creating and handling data in XML form.
- Use of session commands.
- Use of system commands.
- Running automatically (after launching META) a series of functions.
- Communication with the interface (File Manager functions, Pick functions).
All these tasks that can interact with the model and META entities data are controlled through a
series of META specific functions. Before proceeding to the explanation of individual functions, it is
important to emphasize the meaning of meta structs.
As mentioned in Chapter 1, one of the data types that are used within scripting language is the user
structure data type. In META the data all entities, either model entities (nodes, elements, etc) or
META entities (cut planes, annotations, etc) can be accessed through the use of META structs.
META structs is a special group of variables with struct data type, introduced in version v6.2.0.
These structs are used to carry information about entities in META and through them it is possible
to access and modify their data. In order for meta structs to be used, they need to be defined first.
Their definition exists in the file meta_structs, which is provided with the META software inside the
folder config. This file must be included in each script that uses meta structs through the keyword
#include "meta_structs"
The above line is inserted automatically each time the user selects to create a new script. With the
above line, META searches to find the file in the config directory.
Model:
META Struct model is used to carry information about the models loaded in META. It has the
following structure:
struct {
int id; // Model number - Id
string name; // Filename of the model
string label; // Label of the model
string deck; // Deck name of the model
int active; // 1 if model is active, 0 if model is not active
} model;
Elem:
META Struct elem is used to carry information about the elements of models loaded in META. It
has the following structure:
struct {
int id; // Id of the element
int second_id; // Second id of the element (GAP, TUBE, JOINT) , -1 if
there is not a second id
int model_id; // Model number of the element
int type; // Type of the element (META KEYWORD)
int subtype; // Subtype of the element
int visible; // 1 if element is visible, 0 if model is not visible
int part_id; // Id of the part it belongs to, -1 if element belongs to
no part
} elem;
The type of the element is described through an integer index number corresponding to specific
META KEYWORD. However, the user can use the expression
variable = <META KEYWORD>
to assign the value of the integer corresponding to this META KEYWORD to the variable.
Example
el_type= QUAD4
will assign the value 3, to variable el_type.
The expression SHELL can be used to denote all the respective shell element META KEYWORDS
- TRIA3, TRIA6, QUAD4, QUAD8.
The expression SOLID can be used to denote all the respective solid element META KEYWORDS -
TETRA, PENTA, HEXA, TETRA10, PENTA14, HEXA20.
There is a correspondence between the integer, the META KEYWORDS and the KEYWORDS of
each deck.
Node:
META Struct node is used to carry information about the nodes loaded in META. It has the
following structure:
struct {
int id; // id of the node
int model_id; // Model number of the node
float x; // X coordinate of node
float y; // Y coordinate of node
float z; // Z coordinate of node
visible; // 1 if node is visible, 0 if node is not visible
} node;
Part:
META Struct part is used to carry information about the parts loaded in META. It has the following
structure:
struct {
int id; // Id of the part
int model_id; // Model number of the part
int type; // Type of the part (META KEYWORD)
int subtype; // Subtype of the part
int visible; // 1 if part is visible, 0 if part is not visible
string name; // Name of the part
int mat_id; // The id of the corresponding to the part material
float shell_thick; // Shell thickness for PSHELL, or -1 for rest types
of parts
} part;
The type of the part is described through an integer index number corresponding to specific META
KEYWORD. However, the user can use the expression
variable = <META KEYWORD>
to assign the value of the integer corresponding to this META KEYWORD to the variable.
Example
part_type= PROD
will assign the value 1 to variable part_type.
Boundary:
META Struct boundary is used to carry information about the boundary elements loaded in META.
It has the following structure:
struct {
int id; // Id of the boundary element
int second_id; // Second id of the boundary element
int model_id; // Model number of the boundary element
int type; // Type of the boundary element (META KEYWORD)
int subtype; // Subtype of the boundary element
int visible; // 1 if boundary element is visible, 0 if boundary
element is not visible
} boundary;
The type of the boundary element is described through an integer index number corresponding to
specific META KEYWORD. However, the user can use the expression
variable = <META KEYWORD>
to assign the value of the integer corresponding to this META KEYWORD to the variable.
Example
bound_type = SPC
will assign the value 1 to variable bound_type.
Material:
META Struct material is used to carry information about the materials loaded in META. It has the
following structure:
struct {
int id; // Id of the material
int model_id; // Model number of the material
int type; // Type of the material (META KEYWORD)
string name; // Name of the material
} material;
The type of the material is described through an integer index number corresponding to specific
META KEYWORD. However, the user can use the expression
variable = <META KEYWORD>
to assign the value of the integer corresponding to this META KEYWORD to the variable.
Example
mat_type = MAT1
will assign the value 1 to variable mat_type.
Page:
META Struct page is used to carry information about the existing pages in a META session. It has
the following structure:
struct {
int id; // id of the page
string name; // name of the page
int active; // 1 if page is active, 0 if page is not active
} page;
Window:
META Struct window is used to carry information about the existing windows in a META session. It
has the following structure:
struct {
string name; // Name of the window
int active; // 1 if window is active, 0 if window is not active
int width; // The width of the window
int height; // The height of the window
int plot2d; // 1 if it is a plot2D window, 0 if window is not a plot2d
(3D window)
int enabled; // 1 if window is enabled, 0 if window is not enabled
int page_id; // id of the page of the window
} window;
Group:
META Struct group is used to carry information about the current groups in a META session. It has
the following structure:
struct {
string name; // Name of the group
int model_id; // Model number of the group;
string module_id; // Module id
string version; // Version
string representation; // Representation
string study_version; // Study version
string vsc_number; // VSC number
float target_mass; // Target mass
string user_group; // User group
int pid_offset; // Pid offset
int freeze; // Freeze
string type; // Type of the group ("part", "set", "boundary",
"connection", "include")
int instance; // Instance of the group
} group;
Resultset:
META Struct resultset is used to carry information about results which can be loaded in META. It
has the following structure:
struct {
int cycle; // Cycle number of the resultset
int model_id; // Model number of the resultset
string name; // Name of the resultset
string nodal_data_name; // Nodal data name of the resultset, NONE if
it does not exist
string function_data_name; // Function data name of the resultset,
NONE if it does not exist
string filename; // Filename of the resultset
int subcase; // Subcase of the resultset
float state; // State of the resultset
float step; // Step of the resultset
float frequency; // Frequency of the resultset
float time; // Time of the resultset
int mode; // Mode of the resultset
float eigenvalue; // Eigenvalue of the resultset
float imaginary_eigenvalue; // Imaginary eigenvalue of the resultset
float loadstep; // Loadstep of the resultset
int generate_sequence; // Generate number of the resultset
int internal1; // System use only
int internal2; // System use only element
int internal3; // System use only
string nodal_data_label; // Nodal data label of the resultset, NONE if
it does not exist
string function_data_label; // Function data label of the resultset,
NONE if it does not exist
string vector_data_label; // Vector data label of the resultset, NONE
if it does not exist
string vector_data_name; // Vector data name of the resulsett, NONE if
it does not exist
} resultset;
Deformation:
META Struct deformation is used to carry information about the deformation data on a node. It has
the following structure:
struct {
float x; // X deformation
float y; // Y deformation
float z; // Z deformation
float total; // Total deformation
int node_id; // Node id
} deformation;
Modal Deformation:
META Struct modal deformation is used to carry information about the modal deformation data on a
node. It has the following structure:
struct {
float x; // X deformation
float y; // Y deformation
float z; // Z deformation
float rx; // Rotational X deformation
float ry; // Rotational Y deformation
float rz; // Rotational Z deformation
int node_id; // Node id
} modal_deformation;
Nodal_scalar:
META Struct nodal_scalar is used to carry information about scalar function data on a node. It has
the following structure:
struct {
float value; // Value
int node_id; // Node id
int part_id; // Id of the part of the nodal scalar value, or -1 for
nodes not belonging to a part
} nodal_scalar;
Centroid_scalar:
META Struct centroid_scalar is used to carry information about scalar function data on the centroid
of an element. It has the following structure:
struct {
float value; // Value
int element_id; // Element id
int second_id; // Element second id
int type; // Element type (META KEYWORD)
} centroid_scalar;
Corner_scalar:
META Struct corner_scalar is used to carry information about scalar function data on the corners of
an element. It has the following structure:
struct {
float value; // Value
int element_id; // Element id
Centroid_vector:
META Struct centroid_vector is used to carry information about vector function data on the centroid
of an element. It has the following structure:
struct {
float value; // Value
float x; // Normalized coordinate X of vector
float y; // Normalized coordinate Y of vector
float z; // Normalized coordinate Z of vector
int element_id; // Element id
int second_id; // Element second id
int type; // Element type (META KEYWORD)
} centroid_vector;
Plot:
META Struct plot is used to carry information about 2D plots in a META session. It has the following
structure:
struct {
int id; // Plot number - Id
string window_name; // Name of the window
int active; // 1 if plot is active, 0 if plot is not active
string type; // Type of the plot (plain, realimag, magphase, polar)
int page_id; // id of the page of the window
} plot;
Curve:
META Struct curve is used to carry information about curves in a META session. It has the
following structure:
struct {
int id; // Curve id
int plot_id; // Plot number of the curve
string window_name; // Name of the plot2d window of the curve
string name; // Name of the curve
int visible; // 1 if curve is visible, 0 if it is not visible
BETA CAE Systems 165 META Automation User’s Guide
4. Scripting
Coord_system:
META Struct coord_system is used to carry information about coordinate systems in META. It has
the following structure:
struct {
int id; // Id of the coordinate system
int model_id; // Model number of the coordinate system
int type; // Type of the coordinate system (META KEYWORD)
matrix origin; // Origin
matrix xaxis; // X-axis
matrix yaxis; // Y-axis
matrix zaxis; // Z-axis
int visible; // 1 if coordinate system is visible, 0 if coordinate
system is not visible
int ref_id; // Id of the reference coordsystem, -1 if no reference
coordsystem exists
} coord_system;
The type of the coordinate system is described through an integer index number corresponding to
specific META KEYWORD. However, the user can use the expression
variable = <META KEYWORD>
to assign the value of the integer corresponding to this META KEYWORD to the variable.
Example
coord_type= COORD1R
will assign the value 1 to variable coord_type.
Annotation:
META Struct annotation is used to carry information about annotations in a META session. It has
the following structure:
struct {
int id; // Id of the annotation
string window_name; // Name of the window of the annotation
string text; // Displayed text of the annotation
string origin_text; // String with variables of the annotation
int visible; // 1 if annotation is visible, 0 if it is not visible
Color:
META Struct color is used to carry information about colors in a META session. It has the following
structure:
struct {
string name; // Name of the color
int r; // Red value [0..255]
int g; // Green value [0..255]
int b; // Blue value [0..255]
int a; // Alpha value [0..255]
} color;
Image:
META Struct image is used to carry information about the existing images in a META session. It
has the following structure:
struct {
string name; // Name of the image
string window_name; // Name of the window
int width; // Width of the image
int height; // Height of the image
string filename; // Filename of the image
int zorder; // Z-order of the image
int visible; // 1 if image is visible, 0 if it is not visible
int page_id; // Id of the page of the image
}image;
Video:
META Struct video is used to carry information about the existing videos in a META session. It has
the following structure:
struct {
string name; // Name of the video
string window_name; // Name of the window
int width; // Width of the video
int height; // Height of the video
string filename; // Filename of the video
int zorder; // Z-order of the video
int visible; // 1 if video is visible, 0 if it is not visible
int page_id; // Id of the page of the video
int frames; // Number of video frames
} video;
Plane:
META Struct plane is used to carry information about the existing planes in a META session. It has
the following structure:
struct {
string name; // Name of the plane
string clip_type; // Clip type ("plane", "section", "none")
Isofunction:
META Struct isofunction is used to carry information about the existing isofunctions in a META
session. It has the following structure:
struct {
string name; // Name of the isofunction
string window_name; // Name of the window
string type; // Type of the isofunction ("function", "xdeform",
"ydeform", "zdeform", "tdeform")
float value; // Value of the isofunction
int visible; // 1 if isofunction is visible, or 0 if it is not visible
int page_id; // Id of the page of the isofunction
} isofunction;
struct {
string name; // Name of the curve group
int plot_id; // Plot number of the curve group
string window_name; // Name of the window
int page_id; // Id of the page of the curve group
} curve_group;
Annotation group:
META Struct annotation group is used to carry information about the existing annotation groups in a
META session. It has the following structure:
struct {
string name; // Name of the annotation group
string window_name; // Name of the window
int page_id; // Id of the page of the annotation group
} annotation_group;
Plot Axis:
META Struct plot axis is used to carry information about the x and y axes of a META 2d window. It
has the following structure:
struct {
int id; // Plot axis id
string type; // Plot axis type ("xaxis", "yaxis", "caxis")
int plot_id; // Plot number
string window_name; // Name of the plot2d window of the plot axis
int active; // 1 if plot axis is active, or 0 if it is not active
int visible; // 1 if plot axis is visible, or 0 if it is not visible
float min_value; // Minimum value of plot axis
float max_value; // Maximum value of plot axis
int page_id; // Id of the page of the plot axis
} plot_axis;
Connection:
META Struct connection is used to carry information about connections in META. It has the
following structure:
struct {
int id; // Id of the connection
int model_id; // Model number of the connection
int type; // Type of the connection (META KEYWORD)
int subtype; // Subtype of the connection (META KEYWORD)
} connection;
Plot_model:
META Struct plot_model is used to carry information about loaded plot models like time history
files (2d models) in a META session. It has the following structure:
struct {
int id; // Id of the plot_model
string deck; // Deck name of the model
string filename; // Filename of the resultset
} plot_model;
Spreadsheet cell:
META Struct connection is used to carry information about cells in Spreadsheet Editor in META.
struct {
int row; // Row number of the spreadsheet cell
int col; // Column number of the spreadsheet cell
string cell_label; // Label of the spreadsheet cell (e.g. A1)
string spreadsheet; // Name of the parent spreadsheet
string text; // Displayed text of the spreadsheet cell
string orig_text; // Original (not parsed) text of the spreadsheet
cell
} spreadsheet_cell;
In META there is a separate group of script functions for META entities. For example, there are
Element functions to collect the elements, Node functions to collect the nodes, etc.
Additionally, there are the following generic functions CollectEntities to collect all the specified
entities that are loaded in META:
Function Description
CollectEntities Collect all existing entities of the specified type in the current
META session
CollectModelEntities Collect all existing entities of the specified type in a model
CollectWindowEntities Collect all existing entities of the specified type in a window
The types of entities that can be collected using these functions are:
ANNOTATIONs
BOUNDARIEs
COORDINATE SYSTEMs
CUT PLANEs
ELEMENTs (SHELLs, SOLIDs, BEAMs, etc)
GROUPs
ISOFUNCTIONs
MATERIALs
META WINDOW entities (WINDOWs, FRINGEs, COLORs)
MODELs
NODEs
PAGEs
PARTs
PLOT2d entites (PLOTs, CURVEs and POINTs)
RESULTSETs
FRINGEs
VISUAL entities (FRAMEs, IMAGEs, VIDEOs)
For collecting all entities, the appropriate functions are the functions with just the type of the entities
to be collected, e.g. Annotations(), Boundaries(), LoadsOfBoundary(),Elements(), Nodes(), Parts(),
Models(), Groups(),Resultsets(), Connections(), etc. Please note that Groups refer to the entities
Parts/Groups of Part Manager, Includes, Boundaries, Connections, Sets
In the case of model entities, the model id is given as argument.
To access the entities directly according to their id, the matrix with the model structs can be
converted to a map with the XxxMatrixToMap() functions where the key is the entities' id, e.g.
AnnotationsMatrixToMap(), ElementsMatrixToMap(), etc.
#include "meta_structs"
def main()
{
part p;
matrix all_parts;
model_id = 0;
all_parts = Parts(model_id);
foreach p in all_parts {
Print(p.id); Print(p.type); Print(p.subtype);
Print(p.visible);
Print(p.name); Print(p.mat_id); Print(p.shell_thick);
Print(p.model_id);
}
map_parts = PartsMatrixToMap(all_parts);
for(i=GetFirstNode(map_parts,part_id,p); i;
i=GetNextNode(map_parts,part_id,p))
{
Print(p.id); Print(p.name);
}
p = map_parts[ 10 ]; //Get directly part with id 10
Print(p.name);
DestroyMap(map_parts);
}
To get the entities types of a model directly, the functions XxxTypeXxx() are available, e.g.
ElementsTypes(), CurvesTypesNastran(), DeformationTypes(), ScalarTypes(), VectorTypes() etc.
#include "meta_structs"
def main()
{
matrix all_types;
int element_type;
model_id = 0;
all_types = ElementsTypes(model_id);
foreach element_type in all_types {
Print(element_type);
}
}
def main()
{
string deform_type;
string state;
matrix one_type;
matrix all_types;
filename = "/home/proj1.metadb";
deck = "METADB";
all_types = DeformationTypes(filename, deck);
foreach one_type in all_types {
total = MatLen(one_type);
deform_type = one_type[0]; // Deformation type
Print(deform_type);
for(k = 1; k < total; k++) {
state = one_type[k];
Print(state);
Print(k); // Id of the state
}
}
}
For curves types of Dyna, Pamcrash and Radios files the functions
CurvesTypesDynaWithNames(), CurvesTypesPamcrashWithNames() and
CurvesTypesRadiosWithNames() are available to get also their name.
4.4.12.3.3. Collect entities according to their attributes (results, name, id, type, position,
comments, failure, free, outer)
There are specific functions in order to collect entities according to one of their attributes, e.g.
NodesByName(), NodesByField10(), ElementById(), CurvesByName(), ElementsByType(),
FailedElements, FreeNodes(), OuterElements(), FollowNodes() etc.
#include "meta_structs"
def main()
{
part p;
matrix collected_parts;
model_id = 0;
part_type = PSHELL;
collected_parts = PartsByType(model_id, part_type);
foreach p in collected_parts {
Print(p.id); Print(p.type); Print(p.subtype)
Print(p.visible);
Print(p.name); Print(p.mat_id); Print(p.shell_thick);
Print(p.model_id);
}
}
When the function returns only one entity (e.g. ElementById()), then it returns the meta_struct of
this entity, when it may return more than one entities (e.g. ElementsByType()), then it always
returns a matrix with meta_structs (even when only one entity is returned).
For entities that need to be collected and which are neighbors of other entities, the functions
#include "meta_structs"
def main()
{
curve c;
matrix collected_curves;
window_name = "Window1";
collected_curves = CurvesFromAdvFilters(window_name);
foreach c in collected_curves {
Print(c.id); Print(c.name);
}
}
There are many functions to collect entities from other entities, e.g. ElementsOfPart(),
NodesOfElement(), ElementsOfNode(), PartsOfGroup(), etc. There is a separate function for each
combination of the entities to collect and the entity that these belong to.
There are also functions that collect only the entities with specific attributes from other entities, e.g.
ElementsOfNodeByType(), VisiblePartsOfGroupByType(), SelectedCurvesOfWindow(), etc.
#include "meta_structs"
def main()
{
part p;
matrix group_parts;
model_id = 0;
group_name = "My_Group";
group_parts = PartsOfGroup(model_id, group_name);
foreach p in group_parts {
Print(p.id);
Print(p.type);
Print(p.subtype);
Print(p.visible);
Print(p.name);
Print(p.mat_id);
Print(p.shell_thick);
Print(p.model_id);
}
}
For collecting the visible entities, the appropriate functions are the functions which include the word
visible, e.g. VisibleAnnotations(), VisibleElements(), VisibleCurves(), etc.
There are also functions that collect only the visible entities with specific attributes, or only the
visible entities from another entity, or only the visible entities with specific attributes from another
entity, e.g. VisibleElementsByType(), VisiblePartsOfGroup(), VisiblePartsOfGroupByType(),
VisibleCurvesOfPlot(), etc.
#include "meta_structs"
def main()
{
part p;
matrix visible_parts;
model_id = 0;
group_name = "My_Group";
window_name = "Window1";
visible_parts = VisiblePartsOfGroup(model_id, group_name,
window_name);
foreach p in visible_parts {
Print(p.id);
Print(p.type);
Print(p.subtype);
Print(p.visible);
Print(p.name);
Print(p.mat_id);
Print(p.shell_thick);
BETA CAE Systems 174 META Automation User’s Guide
4. Scripting
Print(p.model_id);
}
}
For getting only the identified entities of a model the respective functions are IdentifiedXxx(), e.g.
IdentifiedElements(), IdentifiedNodes(), IdentifiedParts(), etc.
There is a series of functions to get information from the loaded models, like NumOfNodes(),
NumOfModels(), NumOfPartsByType(), etc.
Also information only for the active Models, Pages, Plots, Plot axes and Windows can be retrieved
through the functions ActiveModels(), ActivePages(), ActivePlots(),ActivePlotAxes() and
ActiveWindows().
#include "meta_structs"
def main()
{
model r;
matrix act_models;
act_models = ActiveModels();
foreach r in act_models {
Print(r.id); Print(r.name); Print(r.label); Print(r.deck);
Print(r.active);
}
}
Information about the currently loaded plot models (the plot files listed in the Read Results >
Curves > Files List) that may exist can be retrieved through the function PlotModels().
#include "meta_structs"
def main()
{
plot_model pmod;
matrix plot_models;
plot_models = PlotModels();
foreach pmod in plot_models {
Print(pmod.id); Print(pmod.deck); Print(pmod.filename);
}
}
For collecting all newly created entities of a specific type, the respective functions to use are
CollectNewXxxStart(), ReportNewXxx() and CollectNewXxxEnd()
The syntax is, for example: CollectNewAnnotationsStart(), ReportNewAnnotations(),
CollectNewAnnotationsEnd(), etc.
This can be very useful in order to get the number and ids of entities created through filters or
session Commands.
For example, for curves created through the Curve Function User Defined the function
BETA CAE Systems 175 META Automation User’s Guide
4. Scripting
ReportNewXxx() will return the entity‟s structs without ending the recording of the created entities.
To collect newly created entities within a period, the functions to use are CollectNewXxxStart() and
CollectNewXxxEnd()
#include "meta_structs"
def main()
{
curve c;
matrix new_curves;
MetaCommand("xyplot read pamcrash
\"Window1\" \"/home/demo/example.THP\" Node 1/2 xd”);
CollectNewCurvesStart();
MetaCommand("xyplot curve function userdef \"Displacement
Difference\" \"c1.x\" \"c1.y-c2.y\" \"Window1\"”);
new_curves = CollectNewCurvesEnd();
foreach c in new_curves {
Print(c.id);
Print(c.name);
Print(c.plot_id);
Print(c.visible);
Print(c.selected);
Print(c.window_name);
Print(c.page_id);
Print(c.command);
Print(c.entity_id);
}
}
4.4.12.3.9. Collect files and directories
For collecting efficiently a number of files (of specific formats) or directories, the commands FileList
and DirList must be used. Actually, these functions return a matrix with all the paths that were
identified. Then, these paths can be passed as strings in other functions.
When it is needed to identify a directory hierarchy it is recommended to use the DirList recursively.
A typical example is when a number of solver files, that exist in many directories, must be found:
Suppose that all the files exist under 5 directories which are located under a folder named
'my_project'. A simple code should be like the following:
def main()
{
//Get the 5 directories and store the paths into the matrix "dirs".
dirs = DirList("/home/work/my_project/");
//Loop through the directories
foreach dir in dirs
{
//Find only the solver files that exist under each directory
solver_files = FileList("/home/work/my_project/"+dir, "/*.nas");
//Loop through the solver files
foreach file in solver_files
{
Print(file);
}
}
}
Scripting language interacts directly with the File Manager through the commands SelectOpenDir,
SelectSaveDir, SelectOpenFile, SelectSaveFile, SelectOpenFileIn, SelectSaveFileIn. These
functions open the File Manager and allow the selection or creation of files and directories. This is
an elegant way to use file and directory paths in user scripts, since it enables the interactive
definition of script parameters. The functions that deal with files return a matrix containing strings
that represent the full path to the selected files, while those for directories return a string indicating
the full path to the folder.
def Selection()
{
Print("Select the file for reading");
read_file = 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 = SelectSaveFile();
Print("The file that was selected for writing errors is:
"+save_file);
Print("Select the directory where the META files are located");
dir = SelectOpenDir("");
Print("The selected directory is: "+dir);
}
or
dir = SelectOpenDir("");
if(!dir)
{
Print("No directory was selected");
}
The entities Annotations, Cut planes, Groups, Isofunctions, Windows, Models, Pages, Plots,
Curves, Images and Videos can be created edited and deleted through script functions. The entities
nodes, elements, parts, materials and boundaries CANNOT be created, edited or deleted in META
in general, so this is also not possible through scripitng. Coordinate systems can be created but
cannot be deleted. Moreover, specific functions exist for other operations related to the entities, e.g.
to show, hide, get results from them, etc.
For creating entities the respective functions are CreateXxx(), e.g. CreateEmptyAnnotation(),
BETA CAE Systems 177 META Automation User’s Guide
4. Scripting
def main()
{
annotation a;
window_name = "Window1";
text = "10th Annotation";
a = CreateEmptyAnnotation(window_name, text);
if(IsValidAnnotation(a)) {
Print(a.id);
}
}
4.4.12.4.3. Edit entities
There is a series of script functions for editing directly entities and their settings, for example
SetSettingsOfAllCurves(),SetSettingsOfAllAnnotations(), SetAnnotationPointerOnlement(),
ChangeOriginOfPlane(), AddPartsOnGroup(), RotateView(), etc. However, the full possibilities of
editing entities in META are covered through the META session commands and can be achieved
by using the MetaCommand syntax (see also chapter “META session commands for use in
Scripting Language”).
#include "meta_structs"
def main()
{
plane_name = "plane_axis0";
//Change origin through script function
xorig = 1.26;
yorig = 7.52;
zorig = 3.59;
ChangeOriginOfPlane(plane_name, xorig, yorig, zorig);
//Change section width through session command
MetaCommand(“plane options width 3.0 \””+plane_name+”\””);
}
For deleting entities the respective functions are DeleteXxx(), e.g. DeleteAnnotation(),
DeleteCurve(), DeleteModel(), etc.
The entities can also be deleted by applying the respective session commands.
For showing / hiding entities the respective functions are ShowXxx() and HideXxx(), e.g.
ShowAnnotation(), HideCurve(), ShowModel(), etc.
When more than one 3d model entities or curves need to be shown / hidden, it is much faster to
use the functions ShowSomeXxx() and HideSomeXxx(), e.g. ShowSomeElements(),
HideSomeParts(), ShowSomeCurves(), etc. In this case the entities must be given as matrix.
The entities can also be shown / hidden by applying the respective session commands.
For identifying 3d model entities the respective functions are IdentifyXxx(), e.g. IdentifyNode(),
IdentifyElement(), IdentifyMaterial(), etc.
When more than one 3d model entities need to be identified, it is much faster to use the functions
IdentifySomeXxx(), e.g. IdentifySomeElements(), IdentifySomeParts(), etc. In this case the entities
must be given as matrix.
The entities can also be identified by applying the respective session commands.
To get the properties of amaterial the script function PropertyOfMaterial() can be used. To set these
attributes the script function Set PropertyOfMaterial() can be used. If „all‟ is used as argument for
property type in PropertyOfMaterial(), then all material information lines, as in the input deck, will be
returned.
// BETA script
#include "meta_structs"
def main()
{
float property_value;
model_id = 0;
material_id = 1;
property_type = "all";
property_value = PropertyOfMaterial(model_id, material_id,
property_type);
Print(property_value);
}
4.4.12.4.8. Get results/attributes of entities
First of all, to get the states for which the resultsets are needed, the functions that can be used are
CurrentResultset(), ResultsetsXxx(), FilterResultsetsXxx(), GeneratedResultsetsXxx().
If more than one labels exist for the resultset, the functions DeformationLabelsOfResultsets(),
FunctionLabelsOfResultsets() can be used to get directly all the label results of the state.
Alternatively, the functions StringDeformationLabelsOfResultsets(),
StringFunctionLabelsOfResultsets() can be used to get the available labels and then the functions
GetResultsetFromDeformationLabel() and GetResultsetFromFunctionLabel() can be used to get
the specific label result of the state.
After the needed resultset is found, the functions to get the loaded results depend on the entity from
which the result which is needed. So, in the Nodes functions group there are functions to get results
on the nodes, in the Elements functions group there are functions to get results on elements, in the
Parts functions group functions to get all results from a part, in the Materials functions group
functions to get all results from a material, in the Groups functions group functions to get all results
from a group and in the Models functions group there are functions to get all results from a model.
Moreover, there is a different function for each specific result needed. For nodes, to get the
deformation results, there is the function DeformationOfNode(), to get the coordinates
CoordinatesOfNode(), to get scalar results NodalScalarOfNode() and to get vector results
NodalVectorOfNode().
Similarly for results on elements, there are functions DeformationsOfElement(),
MaxDeformationOfElement(), CentroidScalarOfElement(), CornerScalarOfElement(),
NodalScalarsOfElement() and more.
For parts / materials / models there are functions that return the results on all the nodes or
elements, e.g. CentroidVectorOfPart(), and functions that return directly the maximum and
minimum result, e.g. MinMaxNodalScalarOfModel().
For CELAS spring connection elements the functions StiffnessOfElasElement,
DampingOfDampElement and MassOfMassElement can be used to get information about the
stiffness, damping and mass respectively.
To get and set the number of steps of an axis the functions StepsOfPlotAxis() and
SetStepsOfPlotAxis() respectively can be used.
To get, calculate, and set the material tension, compression, shear, x_tension, y_tension,
x_compression, y_compression, shear and f12 limits of composites materials, the functions
MaterialLimitOfMaterial() and MaterialLimitOfPart() or AddMaterialLimitOfMaterial() and
AddMaterialLimitOfPart() can be used respectively.
Remarks
When the function returns only one entity (e.g. NodalScalarOfNode()), then it returns the
meta_struct of this entity, when it may return more than one entities
(e.g. DeformationsOfElement()), then it always returns a matrix with meta_structs (even when only
one entity is returned).
#include "meta_structs"
def main()
{
deformation deform;
resultset result;
model_id = 0;
result = CurrentResultset(model_id);
node_id = 7322;
deform = DeformationOfNode(result, node_id);
if(IsValidDeformation(deform)) {
Print(deform.x); // X deformation
Print(deform.y); // Y deformation
Print(deform.z); // Z deformation
Print(deform.total); // Total deformation
Print(deform.node_id); // Id of the node
}
}
#include "meta_structs"
def main()
{
nodal_vector min_nodal; nodal_vector max_nodal;
matrix nodal;
resultset result;
model_id = 0;
all_resultsets = Resultsets(model_id);
result = all_resultsets[1];
nodal = MinMaxNodalVectorOfModel(result);
if(MatLen(nodal)) {
min_nodal = nodal[0]; // Struct with the minimum nodal
vector value
Print(min_nodal.value); // Minimum nodal vector value
BETA CAE Systems 180 META Automation User’s Guide
4. Scripting
The functions to get measurements depend on the entity from which the measurement is needed.
So, in the Nodes functions group there are functions to get measurements from the nodes, in the
Elements functions group there are functions to get measurements from the elements, in the Parts
functions group functions to get measurements from a part and in the Groups functions group
functions to get measurements from a group.
Moreover, there is a different function for each specific measurement needed. To get the distance
between a node and another node there is the function DistanceNodeToNode(), to get the distance
between a node and a part the function is DistanceNodeToPart(), etc. To get the angle formed by
nodes the function is AngleOfNodes(). To get the distance between a part and a group the function
is DistancePartToGroup().
#include "meta_structs"
def main()
{
float dist_x; float dist_y; float dist_z; float dist_total;
matrix distance;
resultset part_result;
part_model = 0;
all_resultsets = Resultsets(part_model);
part_result = all_resultsets[1];
part_type = PSHELL;
part_id = 4;
resultset group_result;
group_model = 1;
all_resultsets = Resultsets(group_model);
group_result = all_resultsets[1];
group_name = "My_Group";
In cases that the connected elements or nodes are needed, the functions NeighbourElementsXxx(),
NodesOfElements() and ElementsOfNodes() should be used. In case of mesh independent
spotweld connections, where there is no node connectivity, the functions NeighbourElementsXxx()
can still be used as long as the connectivity is supported in META.
The above script functions should be preferred from the visibility session commands, e.g. “add
connected”, as the first are much faster.
#include "meta_structs"
def main()
{
elem e;
matrix neighbour_elements;
model_id = 0;
element_type = SHELL;
element_id = 1045789;
second_id = -1;
neighbour_type = SHELL;
neighbour_elements = NeighbourElementsByType(model_id,
element_type, element_id, second_id, neighbour_type);
foreach e in neighbour_elements {
Print(e.id);
}
}
In cases that the connected elements, nodes, parts etc to connections are needed, the functions
ConnectedXxxOfConnection() should be used.
#include "meta_structs"
def main()
{
elem e;
matrix connected_elements;
model_id = 0;
connection_id = 100238;
connected_elements = ConnectedElementsOfConnection(model_id,
connection_id);
foreach e in connected_elements {
Print(e.id); Print(e.second_id); Print(e.type);
Print(e.subtype); Print(e.part_id); Print(e.visible); Print(e.model_id);
}
}
There are functions to get data stored in a spreadsheet. To get a cells data the function
SpreadsheetCellByRowColumn(sheet_name, row, col) can be used.
Also the entire row‟s or column‟s data can be stored in a matrix through the functions
SpreadsheetCellsByRow(sheet_name, row). and SpreadsheetCellsByColumn(sheet_name, col).
Returned matrix stops at the last non-empty cell. If all cells are empty, an empty matrix is returned)
To get cells data of an entire cells area the functions SpreadsheetCellsByArea(sheet_name,
top_row, left_col, bottom_row, right_col) and SpreadsheetCellsByLabel(sheet_name, cell_label)
can be used. Cells data are stored in a matrix of same size as the defined spreadsheet area.
Also in order to identify the spreadsheet cells area that involves data the function
SpreadsheetBoundingArea(sheet_name) can be used. A matrix that determines the bounding box
of non-empty cells (matrix[0][0]: top-row, matrix[0][1]: left-column, matrix[1][0]: bottom-row,
matrix[1][1]: right-column) will be returned.
To get the attributes of specific entities of user Toolbars the functions CheckboxStateOfToolbar(),
SliderValueOfToolbar() and TextboxValueOfToolbar() are available.
#include "meta_structs"
def main()
{ int state;
toolbar_name = "Toolbar1";
checkbox_name = "Checkbox1";
state = CheckboxStateOfToolbar(toolbar_name, checkbox_name);
if(state == 1) {
Print("Checked");
}else if(state == 0) {
Print("Not checked");
}else if(state == -1) {
Print("Failure!");
}
}
For loading geometry the respective functions are LoadModel() for solver geometry data files and
LoadProjectModel() for geometries from META databases and META projects.
For loading field results the functions are LoadDeformations(), LoadModalDeformations(),
LoadScalar() and LoadVector() for solver results data files and LoadProjectDeformations(),
LoadProjectScalar() and LoadProjectVector() for results from META databases and META
projects.
The argument “data” which is needed for the functions is the same as the argument used in the
equivalent META session commands. The best way to retrieve the correct syntax is to load the
result manually from the META interface and view the session command passed to the current
META_post.ses file.
In order to append the loaded geometry/results the functions LoadAppendDeformations(),
LoadAppendProjectDeformations(), LoadAppendScalar(), LoadAppendScalarGetCoordSystems(),
LoadAppendProjectScalar(), LoadAppendVector(), LoadAppendVectorGetCoordSystems(),
LoadAppendProjectVector() are available.
For loading curves from history results files the respective functions are LoadCurvesXxx(), e.g.
LoadCurvesNastran(), LoadCurvesDyna().
The arguments which are needed for the functions, e.g. entities, variables, etc, are the same as the
arguments used in the META session commands. The best way to retrieve the correct syntax is to
load the result manually from the META interface and view the session command passed to the
current META_post.ses file. The only difference is that the results are passed as matrices to the
script functions. The string expressions can be easily changed to matrices and vice versa through
the functions RangeToMatrix() and MatrixToRange().
Especially for loading curves from RADIOSS history results files, the function LoadCurvesRadioss()
needs the time history id as argument. In case the time history id is not known, strings “*” or “all”
can be used referring to all available time history ids or the function GetRadiossTimeHistoryId() can
be used to find the time history id for a specific history result.
The entities can also be loaded by applying the respective session commands (see also chapter
“META session commands for use in Scripting Language”). However, one advantage of loading the
entities through script functions is that the function returns the structs of the created entities. For
example, when loading a model through the script function, the id of the model is available.
#include "meta_structs"
def main()
{
model r;
resultset res;
window_name = "MetaPost";
filename = "/home/demo/example.op2";
deck = "NASTRAN";
r = LoadModel(window_name, filename, deck);
if(IsValidModel(r)) {
model_id = r.id;
matrix new_resultsets;
states = "1-5,7,9-11";
data = "Displacements,Translational";
new_resultsets = LoadDeformations(model_id, filename, deck,
states, data);
data = "Stresses,VonMises,MaxofTopBottom";
new_resultsets = LoadScalar(model_id, filename, deck,
states, data);
foreach res in new_resultsets {
Print(res.name); Print(res.nodal_data_name);
Print(res.function_data_name);
Print(res.state);
}
}
}
#include "meta_structs"
def main()
{
curve c;
int th_id;
matrix new_curves;
window_name = "Window1";
plot_id = 0;
filename = "/home/demo/ExampleT01";
type = "shell";
entity_id = 3;
entity_type = "Accel";
variable = "";
time_history[0] = GetRadiossTimeHistoryId(filename, entity_id,
entity_type, variable);
//time_history[0] = "all";
matrix entities;
entities[0] = "22021";
entities[1] = "22025";
matrix variables;
variables[0] = "Membrane Strain E1 (e1)";
new_curves = LoadCurvesRadioss(window_name, plot_id, filename,
type, time_history, entities, variables);
foreach c in new_curves {
Print(c.id);
}
}
Remarks
The deck of the results is given as argument in the functions to load geometry and field results,
whereas different functions exist for each deck for loading history results.
Apart from loading solver results, it is possible to create user defined field results using the results
from calculations realized inside the script.
First of all a new empty state for field results can be created with the function CreateResultSet().
To add a new label to the resultset and set the results to the nodes or the elements, the functions to
be used are AddDeformationOnAllNodes(), AddNodalScalarOnAllNodes() and
AddNodalVectorOnAllNodes().
For more complicated procedures:
To reset all the values of a resultset and add values to the nodes or the elements, the functions to
be used are StartAddingXxx() and EndAddingXxx(), e.g. StartAddingDeformations(),
EndAddindDeformations().
To change the values of a resultset the functions to be used are StartChangingXxx() and
EndAddingXxx(), e.g. StartChangingCentroidVector(), EndAddingCentroidVector().
To append a new label to a resultset and set values to the nodes or the elements for this label, the
functions to be used are StartAppendingXxx() and EndAddingXxx(), e.g.
StartAppendingCentroidScalar(), EndAddingCentroidScalar().
Between the StartXxx() and EndXxx() functions the values can be assigned to the nodes with the
functions AddCentroidScalarOnElement(), AddCentroidScalarOnSomeElements(),
AddCentroidVectorOnElement(), AddCentroidVectorOnSomeElements(),
AddCornerScalarOnElement(), AddCornerScalarOnSomeElements(), AddDeformationOnNode()
and AddDeformationOnSomeNodes(). When values are to be to more than one elements / nodes,
functions XxxOnSomeElements() and XxxOnSomeNodes() should be preferred, as they are much
faster.
Improtant Note: The EndAddingXxx() function must be called at the end, or else the values will not
be assigned to the resultset.
When executing scripts in META some points should be taken into consideration in order to achieve
minimum execution times.
- When the script includes functions that change the display of the META windows, each redraw will
result to time consumption. To speed up the execution of the script, the redraws can be disabled,
and enabled only at the end of the script, in order to display directly the final state.
This can be achieved through the lines
MetaCommand(“options session controldraw disable”);
MetaCommand(“options session controldraw enable”);
- When a function needs to be applied on more than one entities, it is always faster to use the
function that applies directly on all the needed entities XxxOnSomeXxx, e.g. IdentifySomeNodes(),
AddElementScalarOnSomeElements(), etc, instead of applying the single function for each entitty.
- When all the results from entitiy are needed, it is faster to use the function that gets all the results
directly, e.g. DeformationsOfModel, CentroidScalarOfPart(), etc, instead of getting the result for
each element / node separately.
- In cases the connected elements or nodes are needed the functions NeighbourElementsXxx(),
META scripting language enables the creation of user defined buttons and fully customized
graphical interfaces. The buttons that can be created are similar to the buttons of the GUI and are
used to invoke user functions. For the management of specific tasks that must be controlled
through a number of definitions and actions, it is very useful to create a custom GUI. There are two
libraries of functions to create custom user interface. The first supports only the basic widgets that a
GUI can hold, like checkbuttons, radio buttons, menu buttons, lists, tables, while the second library,
BCGUI functions, is more extensive and except from the main widgets mentioned before it also
supports hundreds of more sophisticated tools. These tools allow the creation of any complex
interface that may also contain tab widgets, popup menus, spin boxes, group of buttons, tooltips
and so on. This chapter will focus on the syntax of the functions of the first library. The second
library is described in a separate chapter for both Python and BETA Scripting Lanuage.
One of the most advanced capabilities of scripting language is the creation of user-defined
graphical user interfaces. A GUI is defined through a series of matrices. The format of each matrix
is specific and basically contains information regarding the attributes of controls (caption, position,
size), a reference name for handling the control and optionally the name of the function (Callback)
that will be called with the control activation. Each control is defined in a separate matrix while all
these matrices are parts of a total matrix. A typical syntax of a control matrix is the following:
Finally, an additional matrix must be created for the overall window. Its definition is different from
Notice that 'x' and 'y' are set to zero. In this case the window will be placed in a default position.
Since all necessary matrices were created, the function CreateWindow must be called in order to
create the window. This function needs a reference name and the window matrix.
Remarks
The CreateWindow function creates a window but it doesn't open it.
Almost all types of user-defined windows need an OK and a CANCEL button. The functions
SetOkButton and SetCancelButton are used in order to give to these special buttons their known
characteristics. Their syntax needs the window reference name and the control reference name of
each button.
SetOkButton ("Win1", "okbtn");
SetCancelButton ("Win1", "cancelbtn");
After creating the window and setting the default values of the controls, the user interface is ready
to open. The OpenWindow function opens the window using its reference name:
res = OpenWindow ("Win1");
The output takes a value that corresponds to the pressed button, thus can be very helpful for any
actions that follow its activation. Every code that creates windows must end with the function
DestroyWindow. This function destroys a window that was created by a call to CreateWindow. It
is used to free the internal memory of the windowing system, when the window is no longer
needed.
DestroyWindow("Win1");
In the end the GUI should look like the image on the
left
A callback function is a separate routine that is called every time a control is activated. Its name is
defined in a control matrix. There are certain arguments required for its definition. In most cases
these are the window reference name, the control reference name and the control result.
controls = {
...
{ 20,"BUTTON", 40, 60, 120, 41,"My Button 1","button_LT","LT_btn"},
...
}
The code between the CreateWindow and OpenWindow statements is used for an initial set up of
any type of control. Usually, the setting of a control needs additional definitions of matrices, like in
cases of menus and tables, but there are also cases where a simple call to a function is enough like
in edit fields and check buttons.
An edit field can be set up using the functions StringSet, IntSet, FloatSet, which assign a string,
integer and float respectively. All of them take three input arguments, which are the window name,
the internal reference name of the control and the value:
controls = {
{1, "EDIT", 50, 45, 310, 20, "text", "ref_name"},
...
}
CreateWindow("Win2", dialog);
IntSet("Win1", "ref_name", 1);
// FloatSet("Win1", "ref_name", 1.34);
// StringSet("Win1", "ref_name", "none");
OpenWindow("Win1");
In case none of this function is called, the initial value will be the one defined in the control matrix
The function for setting the state of a check box is the SetCheckButton. The first two arguments
are the window name and the internal reference name of the control, while the third is an integer
that takes zero value for unchecked state and 1 for checked state.
Special attention must be given in the creation of menus and radio buttons since they require some
extra definitions. First, both controls are defined in the control matrix as described in section 4.2.
Their types are "RADIO" and "BUTTON" respectively. In this phase it is not allowed to set a
Callback function since this will be done later with functions SetRadioGroup and SetMenu.
controls = {
{10, "LABEL", 10, 10, 290, 21, "Select Deck", "labeltop"},
{20, "RADIO", 20, 50, 160, 30, "NASTRAN", "radio1"},
{30, "RADIO", 20, 90, 160, 30, "ABAQUS", "radio2"},
{40, "RADIO", 20, 130, 160, 30, "PAMCRASH", "radio3"},
{50, "LABEL", 20, 170, 160, 30, "Select Entities", "labelbottom"},
{60, "BUTTON", 20, 210, 160, 30, "btn", "btn_lower"},
{ 1, "BUTTON", 30, 340, 91, 41, "OK", "okbtn"},
{ 2, "BUTTON", 190, 340, 91, 41, "Cancel", "cancelbtn"}};
dialog = {100, 0, 0, 311, 404, MatLen ( controls ), controls, "Demo"};
win = CreateWindow ("Win4", dialog);
The above control matrix contains 2 labels, three radio buttons and a menu button. After the
creation of the window two group matrices must be defined for radio and menu control. These
matrices will contain the available options with the difference that in case of radio buttons the
internal reference names must be given while in menus the available options are given directly:
radio_group = {"radio1","radio2","radio3"};
menu_group = {"Elements","Nodes"};
In the final step these matrices will be passed to the respective setup functions:
The SetRadioGroup requires the window name 'Win4', the group matrix 'radio_group', an integer,
indicating the active radio button, an internal reference name for the group 'rgroup_1' and the name
of callback function 'RadioCallback'.
The SetMenu requires similarly the window name 'Win4', the internal reference name as it is
defined in control matrix 'bnn_lower', the name of the callback function, the group matrix 'menu
group' and the active option. Keep in mind that the option number starts always from zero.
After setting up the radio buttons and the menu, the callback functions which will allow to recognize
any change of the controls must be created. These functions accept the typical three arguments
(see section 4.2.3) and in their simpler form can be like the following:
def MenuCallBack (string window_name, string btn_name, string option)
{
if(option=="Elements")
Print("Elements option was selected");
if(option=="Nodes")
Print("Nodes option was selected");
StringSet (window_name, btn_name, option);
}
In this case, the StringSet built in function will change the status of menu.
def RadioCallback (string window_name, string group, string option)
{
if(Atoi(option)==0)
Print("NASTRAN option was selected");
if(Atoi(option)==1)
Print("ABAQUS option was selected");
if(Atoi(option)==2)
Print("PAMCRASH option was selected");
}
After all settings the window must be destroyed.
def main()
{
controls = {
{10, "LABEL", 10, 10, 290, 21, "Select Deck", "labeltop"},
{20, "RADIO", 20, 50, 160, 30, "NASTRAN", "radio1"},
{30, "RADIO", 20, 90, 160, 30, "ABAQUS", "radio2"},
{40, "RADIO", 20, 130, 160, 30, "PAMCRASH", "radio3"},
{50, "LABEL", 20, 170, 160, 30, "Select Entities", "labelbotton"},
{60, "BUTTON", 20, 210, 201, 30, "btn", "btn_lower"},
{ 1, "BUTTON", 20, 250, 91, 41, "OK", "okbtn"},
{ 2, "BUTTON", 130, 250, 91, 41, "Cancel", "cancelbtn"}};
dialog = {100, 0, 0, 241, 281, MatLen ( controls ), controls, "Radio
Buttons Demo"};
win = CreateWindow ("Win4", dialog);
SetOkButton ("Win4", "okbtn");
SetCancelButton ("Win4", "cancelbtn");
radio_group = {"radio1","radio2","radio3"};
SetRadioGroup ("Win4", radio_group, 0, "rgroup_1", "RadioCallback");
menu_group = {"Elements", "Nodes"};
The third argument is the unique id of the item that was selected/highlighted. Note that the counting
starts from zero.
For getting the text of the current item the LBCurText function must be used.
current_text = LBCurText("Window2","list1")
Print("current text:"+ current_text);
For multiselections the above function returns the string represented from the last selected item.
Special attention must be given to the callback onModify of the control matrix that will be used for
items modifications:
static def onModify(string window_name, string btn_name)
{
cur = LBCurrent(window_name, "list1");
res = UserInput("Please type some text", txt);
if (res)
{
if (cur >= 0)
{
SetLBItemText(window_name, "list1", cur, txt);
}
}
}
Before setting a new value to an item, it must be first recognized by its id. This is made with the
LBCurrent function, which returns the unique id of the item. Next, this output is given as third
argument in the SetLBItemText . The new text will be given in the forth argument.
Making a loop in the Selected_items matrix, all item texts are taken with the LBItemText.
foreach sel_item_id in Selected_items
{
BETA CAE Systems 195 META Automation User’s Guide
4. Scripting
def main()
{
controls = {
{100, "LIST_BOX", 10,10,360,230, "", "list1"},
{102, "BUTTON", 50,270,80,30, "Modify", "modify", "onModify"},
{ 1, "BUTTON", 250,270,80,30, "Ok", "okbutton"}
};
dialog = {1000, 100,100, 380,320, MatLen(controls), controls, "Window2"};
window = CreateWindow("Window2", dialog);
SetOkButton("Window2", "okbutton");
res = OpenWindow("Window2");
if (res)
{
Print("current text:"+LBCurText("Window2","list1"));
Selected_items = LBSelectedItems("Window2","list1");
BETA CAE Systems 196 META Automation User’s Guide
4. Scripting
The visibility of all controls can be handled through the HideControl and ShowControl functions.
Their syntax is the same and needs the window name and the reference name of the control. In the
example that will follow, the visibility of all buttons is controlled through a callback, which hides or
shows the buttons according to the status of a check box.
static def onCheckChange(string window_name, string btn_name, string state)
{
if (state ==0)
{
ShowControl(window_name, "btn_1");
ShowControl(window_name, "btn_2");
}
else
{
HideControl(window_name, "btn_1");
HideControl(window_name, "btn_2");
}
}
def main()
{
controls = {
{102, "CHECK" , 50,30,250,20, "hide / show buttons", "check1",
"onCheckChange"},
{103, "BUTTON" , 50,75,150,20, "Option 1","btn_1"},
{104, "BUTTON" , 50,100,150,20, "Option 2","btn_2"},
{ 1, "BUTTON", 165,160,70,30, "Ok", "okbutton"}
};
dialog = {1000, 100,100, 400,210, MatLen(controls), controls,
"Hide/Show"};
window = CreateWindow("Hide/Show", dialog);
SetOkButton("Hide/Show", "okbutton");
res = OpenWindow("Hide/Show");
DestroyWindow("Hide/Show");
}
META scripting language is capable of handling external ASCII, XML and BINARY files. The
treatment of such files includes operations like opening, reading, creating the file or browsing
through its contents. In this way it is possible to pass any information from a file that contains any
data (engineering data, connection information) to an META database and vice versa. Some basic
functions that can be used for these purposes are presented and explained in the following
paragraphs.
The most important functions for handling text files are listed in the following table:
# Function Description
Fopen("/home/work/test.txt","w"); Opens a file for writing.
1. Fopen("/home/work/test.txt","r"); Opens a file for reading.
Fopen("/home/work/test.txt","a"); Opens a file for appending.
2. Fclose(f); Closes a file.
3. Read(f,line); Reads each line of a fille
4. Write(f,"text to write"); Writes into a file.
5. TokenizeString("1,2,5,20",",",0) Breaks a string into tokens
6. MatchString("10_PID:40",": "); Locates a substring
The last two functions are the most significant string functions. Their use is necessary during the
reading of an ASCII file.
In the most general case, when reading or appending to a file, the language checks if the user has
permissions on this file. If everything is ok, it returns an integer which is used later for any action
instead of the filename. The script functions that are used to open and a close a file are the Fopen
and Fclose.
def main()
{
f = Fopen("home/work/test.csv","r"); //Opens a file for reading
.....
Statements
.....
Fclose(f);//Closes the file
}
Remarks
Attempting to open a file for writing or appending to it while the file doesn't exist, it creates the file
automatically.
The reading of an ASCII file is made line-by-line, making use of the output integer of the Fopen
function. The script function that is used is called Read and most of the times it is used together
with a while statement. This is made in order to assure that the file will be read from the beginning
to the end. Suppose that each line of the following text must be read and printed:
SUBSTRUCTURE = side
MODULE_ID = 100
TITLE = B-PILLAR
MODULE_ID = 1000
PID = 20
PIDNAME = MAT1_BP
THICKNESS = 0.8
MAT_NAME = Steel
X_AXIS = 1,0,0
Y_AXIS = 0,1,0
Z_AXIS = 0,0,1
ORIGIN = 0,0,0
def main(){
f = Fopen("/home/work/test.attr","r"); //Opens the file for reading
//Read each line of the file and store it under the variable s
while(Read(f,s))
{
Print(s);//Print each line
}
Fclose(f);//Closes the file
}
TokenizeString and MatchString are the most appropriate functions for handling strings. The
TokenizeString splits a string into tokens taking into account a delimiter. For example, a variable
called „line‟ that indicates a node id and its coordinates, in a comma-separated form, can be split
into four different strings. The new strings are stored in a matrix.
def main()
{
// NID, xcoord, ycoord, zcoord
line = "234,-42.505,-44.245,17.782";
tokens = TokenizeString(line, ",",0);
Print("The string line was separated in "+MatLen(tokens)+ "tokens");
}
After the execution of the script the function will return a matrix with the tokens. In the current
example the length of the matrix is 4 and each entry will have the following values:
tokens[0] = 234
tokens[1] = -42.505
tokens[2] = -44.245
tokens[3] = 17.782
It is recommended to convert each of the tokens to the appropriate form (float, integer etc.) before
any further use. The second argument can host any number of separators:
def main()
{
// NID, xcoord ycoord zcoord
line = "234,-42.505_-44.245:17.782";
tokens = TokenizeString(line, ",_:",0);
Print("The string line was separated in "+MatLen(tokens)+"tokens");
}
The result will be a matrix with the same entries as before.
Some types of separators need the backslash symbol \ for their definition.
For tab separator: TokenizeString(line,"\t",0);
For " separator : TokenizeString(line,"\"",0);
For \ separator : TokenizeString(line,"\\",0);
For a blank separator just leave a space: TokenizeString(line, " " ,0);
The last argument declares if a blank token will be saved in the output matrix (flag=1) or not
(flag=0):
def main()
{
line = 234,-42.505,,-44.245,17.782
tokens = TokenizeString(line,",",1);
Print("The string line was separated in "+MatLen(tokens)+" tokens");
}
In this case the number of entries in 'tokens' will be five, since the function has used 1 as last input
argument. The extra entry will be an empty string.
Optionally, a forth argument denotes if the delimeters will be consider as one word, e.g.:
def main()
{
m = TokenizeString("that is a string to break", "is", 0, 1);
//returns a matrix containing the strings "that " and " a string to
break"
}
The MatchString is used to identify a specific sub-string within a parent string. It returns an integer
indicating the position of the first occurrence of the sub-string. If nothing is found zero is returned.
First input argument is the parent string and second argument is the sub-string that must be
matched.
def main()
{
parent = "name_roof_pid_100";
pos = MatchString(parent, "pid");
}
th
The 'pos' variable will be 11 since the first occurrence of 'pid' is in the 11 position.
A very useful application is demonstrated in the following example were all PSHELLs with names
that contain the string “Default” are identified and deleted.
def SubStitute()
{
//Initialize
count = 0;
pshells = CollectEntities(NASTRAN,0,"PSHELL",0);
foreach pshell in pshells
{
GetEntityCardValues(NASTRAN,pshell,"Name",name);
pos = MatchString(name,"Default");
if(pos)
{
to_del[count++]= pshell;
}
}
DeleteEntity(to_del,1);
}
For more complicated cases, where the sub-string follows a pattern, the MatchRegex function can
be used instead. In the example that follows the function searches in insensitive mode, a material
name starting with the string 'Default' :
def main()
{
match_name = MatchRegex(material_name, "^Default\b", "case_sensitive",
"false");
if ( match_name )
{
Print("Default material: "+material_name);
}
}
The function Write is used to write a file. The arguments that uses are the integer returned by the
Fopen function and the text to write. Every time the function is called a new line is written. Suppose
that the information like the pid, thickness and name of all PSHELL properties must be written in a
csv (comma separated) file. A simple code should be like the following:
def main()
{
part p;
matrix all_parts;
model_id=0;
f = Fopen("home/work/test.csv","w"); //Opens a file for writing
//Write the HEADER
Write(f,"PID,Name,Thickness");
all_parts = Parts(model_id); //Collect all parts of model 0.
//Loop through the Parts
foreach p in all_parts
{
Write(f,p.id+","+p.name+","+p.shell_thick);
}
Fclose(f);
}
For writing more than one lines after each call of Write, use the \n symbol enclosed in quotes.
The most important functions for the handling of xml files are listed in the following table:
# Function Description
1. XmlOpenBase("/home/script.xml", "scripted"); Opens a XML data base
XmlGetNode(base, "VTAElements/"); Fetces a node
2.
XmlGetNode(base, root,"VTAElements/");
XmlGetSubNodes(base,node); Fetches the subnodes of a
3.
node
4. XmlNodeName(base, sub_param); Gets the name of a node
XmlGetStringValue(base,sub_param,"Name",""); Gets the string value of a
5.
node
6. XmlGetNodeData(base,node); Gets node's data
XmlNewNode(base,"Connection Elements",1); Creates new node
7.
XmlNewNode(base,node_connection,"Spotwelds",1);
8. XmlSetStringValue(base, sub_node, "val","str"); Set a string value to a node
9. XmlSetNodeData(base, sub_node, "some_data"); Sets node's data
For the clarification of the most important xml functions the following schema is going to be used for
reading and writing:
<Data>
<Connection_Elements>
<SpotweldPoints>
<Parameter Code = "Connection Name">Spot1</Parameter>
<Parameter Code = "xcoord">1.2</Parameter>
<Parameter Code = "ycoord">5.0</Parameter>
<Parameter Code = "zcoord">3.5</Parameter>
<Parameter Code = "comment">"Connect 2 flanges"</Parameter>
</SpotweldPoints>
<Parts>
<PartInfo Code = "Part Name 1">"upper"</PartInfo>
<PartInfo Code = "Part Name 2">"lower"</PartInfo>
<PartInfo Code = "Prop Id 1">10</PartInfo>
<PartInfo Code = "Prop Id 2">20</PartInfo>
</Parts>
</Connection_Elements>
</Data>
as base node. In case of reading, it can take an arbitrary internal name that will not be used further.
When this function points to a nonexistent file then a file is automatically created.
For getting the element (pointer) of a node the XmlGetNode must be used. In the current example
nodes are considered the tags <Data>, <Connection_Elements>, <SpotweldPoints> and <Parts>.
The root node in this structure is considered the <Data> and this is the node that must be fetched
first. The syntax for getting it is:
Since "Data" is the root the second argument can be also blank:
The output data is a matrix that contains the element (pointer) of ,"Data"
The nodes that comes hierarchically just after the root, like the <Connection_Elements>, can be
taken as following:
//For getting the <Connection_Elements>
connection_elements = XmlGetNode (base,data[0],"Connection_Elements");
Alternatively, after getting a node it is easy to get its sub-nodes using the XmlGetSubNodes.
Attention must be given in the function's second argument since it must be taken from the output
matrix of the XmlGetNode that was called before. The node <Connection_Elements> is the
subnode of <Data>, while the nodes <SpotweldPoints> and <Parts> are the subnodes of
<Connection_Elements>. The code that must be used is:
data = XmlGetNode(base,"Data/");
//For getting the <Connection_Elements>
connection_elements = XmlGetNode (base,data[0],"Connection_Elements");
//For getting the <SpotweldPoints>, <Parts>
subnodes = XmlGetSubNodes(base, connection_elements[0]);
The output is always a matrix that contains the elements (pointers) of the sub-nodes.
In an XML file each node holds a name, which describes most of the times an area of interest. The
name can be extracted using the XmlNodeName function. Its syntax needs the base and the node
element (pointer).
connection_elements = XmlGetNode (base,data[0],"Connection_Elements");
//For getting the <SpotweldPoints>, <Parts>
subnodes = XmlGetSubNodes(base, connection_elements[0]);
foreach subnode in subnodes
{
node_name = XmlNodeName(base,subnode);
Print(node_name);
}
In the above example the names 'SpotweldPoints' and 'Parts' are going to be displayed on the
screen.
Apart from its name, a node can have attributes and data that are also important for the process.
Consider the node <SpotweldPoints> that has the sub-nodes <Parameter> which in turn have the
attribute 'Code'. This attribute has five parameter names ('Connection Name', 'xcoord', 'ycoord',
'zcoord', 'comment'), while each node holds data that is associated with each of these parameters
('Spot1, 1.2, 5, 3.5, Connect 2 flanges'). To extract this information, the functions
XmlGetStringValue and XmlGetNodeData. Can be used as follows:
def main()
{
base = XmlOpenBase("/home/work/connections.xml", "internal_name");
data = XmlGetNode(base,"Data/");
connection_elements = XmlGetNode(base,data[0],"Connection_Elements");
sub_nodes = XmlGetSubNodes(base,connection_elements[0]);
foreach sub_node in sub_nodes
{
node_name = XmlNodeName(base,sub_node);
if(node_name=="SpotweldPoints")
{
subs_of_spots = XmlGetSubNodes(base,sub_node);
foreach sub_of_spots in subs_of_spots
{
param_name = XmlGetStringValue(base,sub_of_spots,"Code","");
if(param_name=="Connection Name")
connection_name = XmlGetNodeData(base,sub_of_spots);
if(param_name=="xcoord")
xcoord = XmlGetNodeData(base,sub_of_spots);
if(param_name=="ycoord")
ycoord = XmlGetNodeData(base,sub_of_spots);
if(param_name=="zcoord")
zcoord = XmlGetNodeData(base,sub_of_spots);
if(param_name=="comment")
comment = XmlGetNodeData(base,sub_of_spots);
}
Print("connection_name:"+connection_name);
Print("xcoord:"+xcoord);
Print("ycoord:"+ycoord);
Print("zcoord:"+zcoord);
Print("comment:"+comment);
}
}
}
Remarks:
- The name of an attribute is necessary for retrieving the attribute values.
- If the attribute hasn't got a value then a default can be assigned through the forth argument of
XmlGetStringValue.
In order to create a new XML file, the function XmlOpenBase must be used. The second defines
the base node, which in this case is the <Data>.
base = XmlOpenBase("/home/tmp/test.xml","Data");
A new node can be created with the function XmlNewNode. Its syntax accepts either 3 or 4
arguments. Depending on the syntax a node can be created just after the base node (3 arguments)
or in any other place (4 arguments). In the latter case an element (pointer) indicating the parent
node will be needed.
In the following example the node 'Connection Elements' will be placed after the node 'Data':
while writing:
node_spot = XmlNewNode(base,node_connection,"SpotweldPoints",1);
the node 'SpotweldPoints' will be created after the 'Connection Elements'. It is clear that in this case
the output of the previous call was used. Last argument indicates whether the node appears once
(1) or more (0). In the current example it is 1 since both nodes are written once. On the other hand
the node 'Parameter' which appears more than once, must be created using as 0 as last option.
node_param = XmlNewNode(base,node_spot,"Parameters",0);
Attribute names and parameters can be set using the XmlSetStringValue function:
XmlSetStringValue(base,node_param,"Code","Connection name");
or
XmlSetStringValue(base,node_param,"Code","xcoord");
XmlSetNodeData(base,node_param,"Spot1");
or
XmlSetNodeData(base,node_param,"1.2");
To sum-up the above, the final code for writing the whole xml file is the following:
def main()
{
base = XmlOpenBase("/home/tmp/test.xml","Data");
node_connection = XmlNewNode(base,"Connection Elements",1);
node_spot = XmlNewNode(base,node_connection,"SpotweldPoints",1);
parameter_names_spots = {"Connection
name","xcoord","ycoord","zcoord","comment"};
node_data_spots = {"Spot1","1.2","5.0","3.5","Connect 2 flanges"};
for(i=0;i<5;i++)
{
node_param = XmlNewNode(base,node_spot,"Parameters",0);
XmlSetStringValue(base,node_param,"Code",parameter_names_spots[i]);
XmlSetNodeData(base,node_param,node_data_spots[i]);
}
node_parts = XmlNewNode(base,node_connection,"Parts",1);
parameter_names_parts = {"Part Name 1","Part Name 2","Prop Id 1","Prop
Id 2"};
node_data_parts = {"upper","lower","10","20"};
for(i=0;i<4;i++)
{
node_param = XmlNewNode(base,node_parts,"Parameters",0);
XmlSetStringValue(base,node_param,"Code",parameter_names_parts[i]);
XmlSetNodeData(base,node_param,node_data_parts[i]);
}
XmlCloseBase(base,1);
}
The functions for handling binary files are listed in the following table:
# Function Description
1. ReadCharacter Reads a character from a binary file
2. ReadDouble Reads a double precision number from a binary file
3. ReadFloat Reads a single precision number from a binary file
4. ReadInt Reads an integer number from a binary file
5. ReadString Reads a character string from a binary file
6. WriteCharacter Writes a character in a binary file
7. WriteDouble Writes a double precision number in a binary file
8. WriteFloat Writes a single precision number in a binary file
9. WriteInt Writes an integer number in a binary file
10. WriteString Writes a character string in a binary file
A binary file can be opened for writing or reading with the Fopen function using either the wb or rb
mode.
The way of reading and writing binary files is the same with the one used for ASCII files. The only
exception is that each type of variable must be handled with different function. For example the
WriteFloat and ReadFloat are used for floats, the WriteInt and ReadInt are used for integers etc.
All functions used for writing accept 2 arguments which are the file identifier and the value to write.
Only for string types a third argument, which is the number of bytes to write, is used.
Fopen("/home/user/file.dat","wb"); //Opens a binary file for writing
WriteInt(fw,10);
WriteFloat(fw,1.3);
WriteString(fw,"The value is:"+12,11);
Fclose(fw);
The functions used for reading accept 2 arguments which are the file identifier and the variable
where the value will be stored. Again, only for string types, a third argument is needed for declaring
the number of bytes to read.
fr = Fopen("/home/user/file.dat","rb"); //Opens a binary file for reading
ReadInt(fr,int_val);
ReadFloat(fr,float_val);
ReadString(fr, str_val,11);
Fclose(fw);
Remarks
- A binary file is written and read sequentially.
This category includes the important GUI entities that are visible and manageable by the user, like
windows, buttons, combo boxes etc.
BCWindow
Provides a window that may hold any other widget, layout or item. It is the highest-level widget that
can be created by the BCGUI library. A vertical layout is provided by default.
BCPushButton
It is a button that can perform an action on click or on toggle.
BCLineEdit
Provides a one-line text editor.
BCCheckBox
Provides an option box with a text label on the right.
BCPopupMenu
Provides a pull down menu of choices.
BCComboBox
It is a combination of a 'BCPushButton', a 'BCLineEdit' and a 'BCPopupMenu'.
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
Provides a column of tabbed widget items. It displays a column of tabs one above the other, with
the 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'.
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'.
In the following picture a 'BCWindow' containing a 'BCLabel', a 'BCButtonLineEdit' are shown. The
'BCPushButton' inside the 'BCButtonLineEdit', when pressed pops up a calculator. The upper
lineEdit displays user's input and the lower the calculation's output. By pressing the '->' button the
calculator's output, shown in the second lineEdit is inserted into the 'BCButtonLineEdit' from which
the calculator was called.
BCPushButtonit
BCButtonLineEdit
BCLabel
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.
BCTable
The BCTable class provides a flexible editable (spreadsheet-like) table widget. In 'BCTable's' other
widgets can be inserted as well.
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 META is used.
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.
These are the invisible entities that manage the layout of widgets.
BCBoxLayout
The 'BCBoxLayout' is one of the most useful tools for managing geometry. It consists of a
rectangular box having transparent outside border which can obtain horizontal or vertical orientation
for its children (either widgets or other layouts). It is usually used as a parent in widgets creation.
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.
4.5.2.4. Items
BCSpacer
Provides a blank space in a layout. It can be
extended to all directions, according to the
default parameters.
The creation of graphical interface with BCGUI may include any of the above widgets, layouts or
items following the parent-child logic. This means that a BCGUI entity is constructed as a child of
another one. In this way the relationship, i.e. the placement and the dependencies of each entity,
can be easily defined. Actions like showing, hiding or destroying a parent widget, automatically are
applied recursively to all its children.
The 'BCWindow' is the highest level widget a user can create in script and META's Main Window is
set automatically as parent:
Pseudocode for a simple BCWindow
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.
A pseudocode example for the layouts follows:
Pseudocode for layouts example
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)
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 META_post.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.
In the previous example a 'BCWindow' with 2 “dummy” buttons was created, i.e. on button click no
operation has been defined. This is where the user needs to define callback functions, i.e. functions
that will be called when a user interacts with widgets or items.
Callback functions are defined as normal script functions and their name is passed as a string
argument to the appropriate BCGUI functions, followed by a user argument of any data type (float,
string, integer, matrix etc).
Help about BCGUI callback functions (prototype, arguments etc.) can be found at the end of the
description section of each BCGUI function that uses a callback as an argument.
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);
guitk.BCLineEditSetEnterPressedFunction(input, calculateFun,
output)
butPrint = guitk.BCPushButtonCreate(grid, None, printFun, output)
guitk.BCButtonSetPixmapFile(butPrint, "print_16.png")
guitk.BCGridLayoutAddWidget(grid, butPrint, 1, 1,
guitk.constants.BCAlignCenter)
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.
4.5.3.3. Moving more data around Creating and using callback functions
An alternative way to pass more data to callbacks is to use the BCSetUserDataKey and
BCGetUserDataKey functions. The first one associates key- data pairs (of types string-element)
to a widget or layout and the second one retrieves the data using the corresponding string keys.
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)
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)
This example demonstrates how widgets can be placed inside container widgets, such as
'BCDrawerGrids', 'BCToolBoxes' and 'BCTabWidgets'. It also demonstrates how the widgets' state
can be saved in the current xml file (apart from the 'BCWindow's' position and size, which is done
automatically) and retrieve it on demand. Finally, some interesting ways of controlling and
displaying data are shown.
The 'BCWindow' flashes when 'Enter' is pressed with an invalid 'BCSpinBox' value.
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 META. 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 META 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)
none = "None";
comboVals = (wp, a, none)
#'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
BETA CAE Systems 222 META Automation User’s Guide
4. Scripting
right or left.")
def main():
window = guitk.BCWindowCreate("AutoSavingSettings",
guitk.constants.BCOnExitDestroy)
4.6. BCGUIDesigner
4.6.1. Introduction
The Designer is a tool that enables the easy generation of windows using a graphical user
interface. The functions used for creating the interface belong to the BCGUI function group. The
great advantage of the Designer is the automatic generation of code that reduces the preparation
time of a script. The following paragraphs will focus in the presentation of the Designer's interface
but without any particular emphasis on the BCGUI functions that are used in the background.
CallBack Functions
This is the window where it hosts all created callback functions.
Parameters
This window displays all the parameters related to the selected item of the Constructed Items list
window.
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.
The visibility of the aforementioned sections can be controlled from the View menu. The interface is
customizable. All sections can be untagged double clicking on their title bar and tagged in another
window side position.
4.6.3. Toolbox
The ToolBox, depicted on the left, 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, named
'TopWindow'. This will make the rest of categories
available.
The parent object controls the objects' order. The created items are listed in the Constructed Item
list in the order they have been created. Selected Item in the Constructed Item list is highlighted in
yellow color.
As it is shown above, any object that is added directly to the top window is distributed vertically. To
control the order add the same objects under a BoxLayout container of the Containers group. In
BETA CAE Systems 227 META Automation User’s Guide
4. Scripting
order to do so first create the BoxLayout container throught the Toolbox and then in the
Constructed Item list mondify the items tree structure in the desired way by siply dragging theitems
in the list. In order to add an item as a child of another it should be draged on to the parent item:
In the following image, a tooltip is going to be added for the button 'BCPushButton_1'. Select the
button object from the Constructed Items list or from the screen and type the tooltip text under the
Values column of the AddToolTip>string tip parameter.
After confirmation, place the cursor over the button to see the tooltip. Fields that can be edited
became editable double clicking on them.
4.6.6. Parameters
The Parameters window, depicted on the left,
lists all the unique options of a selected object.
As soon as an object is selected either from
the screen or from the Constructed Items list,
the title of the Parameters window and the
actual parameters change accordingly.
The name and the input arguments of the
parameters are displayed in two separate
columns. The name of each parameter
describes its use.
As in any other list of parameters, the
corresponding options have the default values
but they can get new ones by the user. For
example, to change the button's name,
expand the 'ButtonSetText' and type a new
value for the option 'text'.
At the end, press the Apply Settings button to confirm the changes.
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.
Note that a callback function should be already set for the object in order to be listed in the
CallBack Functions list. In order to do so the name of th efunction that will be called when the
button is pressed shouldbe entered in the BC_BUTTON_CLICKED_FUNCTION value.
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.
4.7.1. Introduction
A script can be executed from META GUI through one of the following ways:
To run a script through the Script Editor, it must be loaded in the Editor window. Through the option
Debug > Run (F5), normally the main function of the script loaded in the current opened window is
executed (see comments below).
Through the option Debug > Run Function, the function to be executed can be selected from the list
of the functions which exist in the open Beta script and Python files. In the field Type functions
arguments, the arguments of the function are typed separated by comma. Any syntax errors are
reported in the output area.
Running the script through the Script Editor, the comments #!script and #!EOF are not
necessary, but no session commands should be included.
Which function is called – Python Scripting
By default, a newly created Python script contains the lines
If (__name__ ==„ __main__„):
main()
at the end of the script. These lines define the function to be called when the script is executed in
the script editor or through the read session command described below. By default the main
function is set to be called.
Which function is called – BETA Scripting
By default, if the script contains a function called “main”, then running it, this particular function is
executed. However, adding 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 when
running the script. In the following code example, the “test” function will be executed instead of
“main”.
entrypoint def test()
{
Print("test function will be executed");
}
To run a script, the following command can be applied in the META command line:
script execute "<path>\<script filename>::<function name>(<arguments>)"
This way the specified function inside the defined filename will be executed with the arguments
given.
To run a script saved within a project, the following command can be applied in the META
command line:
script project execute <path>\<project filename> <script_ids>
This way the specified script inside the defined project will be executed. Also multiple scripts can be
executed entering the ids of scripts (e.g. 1,2 or 1-5 or all to execute all scripts).
To run a script and assign the return value of the script to a META variable apply one of the
following META commands:
Examples:
- The following command will execute the function Funct_1 inside the file /home/example.bs
with arguments 10 and string meta and the above expression will be replaced by the return value
of the function:
script execute "/home/example.bs::Funct_1(10, „meta„)"
Note that string arguments of called function should be written between single quotes „‟.
- The following command will execute the function Funct_1 inside the file /home/example.bs
with arguments 10 and string meta and the return value of the function will be assigned to variable
var1:
script execute getresult var1 "/home/example.bs::Funct_1(10, „meta„)"
2. Through read session command, in META command line. Which function is called is
explained in Chapter “Running scripts from the script Editor”
3. Point the script file as META running option in META Launcher either:
In that case script file should be located in the META current directory.
However, if the script is to be executed as a session, the following comment lines have to be placed
in the script code.
BETA Scripting language
Python
A script can also be a part of a session file. In this case, it is also mandatory to have the comments:
BETA Scripting language
Python
In the beginning of script: # PYTHON script Note: Space char. between # and PYTHON
More than one scripts can be embedded in a single session file, so that parts of session file and
scripts are executed sequentially.
A function that exists in another script file can be run through LoadExecuteFunc() script function.
This function returns the return value of the called function.
Examples:
The following will run the function some_fun located in example.bs:
LoadExecuteFunc("/home/demo/example.bs", "some_fun");
To run a script as a built-in function inside other META tools (e.g. Annotations, Variables, Curves,
User defined function etc) the following should be typed:
`<path>\<script filename>::<function name>(<arguments>)`
This way the specified function inside the defined filename will be executed with the arguments
given and this part will be replaced by the return value of the function.
This can also be used for when applying any command from command line. The built-in function
will be replaced by the return value of the script and the command will be applied with the replaced
value.
Example
The following function will execute the function Funct_1 inside the file /home/example.bs with
arguments 10 and string meta:
`/home/example.bs::Funct_1(10, „meta„)`
The above expression will be replaced by the return value of the function.
Remarks
When a function is called from a built-in function, all the messages that are printed by the script in
the message window are hidden by default. This can be changed through the META commands
script messages show / hide
To run a script inside the statistics tool, a user defined column should be created. In the column‟s
expression the following should be typed:
<path>\<script filename>::<function name>(<arguments>)
This way the specified function inside the defined filename will be executed with the arguments
given and the return value of the function will be displayed in the column. The values of other
columns can be given as arguments to the function.
Example
The following command will execute the function Funct_1 inside the file /home/example.bs,
with arguments 10 and the value of column C0 for each row:
`/home/example.bs::Funct_1(10,C0)`
META can also run without GUI. In such case META runs in batch mode.
META can be run in batch mode through the running options:
–b and –noqui
In batch mode a script can be run as a session through the:
–s running option
and a script function can be run as a session through the:
–exec running option.
Note that only the main function of the script will be executed. Also in order to execute the script as
a session the following comment lines have to be placed as first and last lines of the script code:
Remark
The script function BatchMode() is available in order to get whether META runs in batch mode.
If meta_post64.sh is the shortcut command used to launch META and test.bs is the willing
script, regarding the OS, the following can be written:
Linux OS:
meta -b -s /home/demo/test.bs
or
meta -nogui -s /home/demo/test.bs
Windows OS:
Remark
In case arguments need to be passed, these can be passed as session arguments after the –s
running option.
The arguments can be retrieved as $0, $1, etc variables and stored to META variables.
Then arguments can be retrieved afterwards from the script function through the script function
MetaGetVariable().
The script that follows next can be run through:
meta –b -s /home/demo/test.bs "This is argument 1" 10 23.2
input variables are This is argument 1, 10 and 23.2.
The script prints the first variable and the sum of second and third.
// BETA script
#include "meta_structs"
def main()
{
MetaCommand("opt var add var0 $0");
MetaCommand("opt var add var1 $1");
MetaCommand("opt var add var2 $2");
script_var0 = MetaGetVariable("var0");
script_var1 = Atof(MetaGetVariable("var1"));
script_var2 = Atof(MetaGetVariable("var2"));
Print(script_var0);
x = script_var1 + script_var2;
Print(x);
}
Note that counting arguments starts from 0. Arguments must be separated with space. If the string
of an argument contains a space character, then it is mandatory to enclose is in double quotes “”.
If meta_post64.sh is the shortcut command used to launch META and fun1 is the function in
test.bs script to be executed, regarding the OS, the following can be written:
Linux OS:
Windows OS:
Remark
The function fun1, in the script named test.bs that follows next can be run through:
meta -b -exec "script execute /home/demo/test.bs::fun1('This is argument
1', 10, 23.2)"
input arguments are This is argument 1, 10 and 23.2.
The function prints the first argument and the sum of second and third.
// BETA script
#include "meta_structs"
def main():
print(i)
script.CheckBreak()
if __name__ == '__main__':
main()
A list with all the META KEYWORDS and their correspondence can be found as following:
- Open Script Editor
- Go to Function List window (if this is not visible go to main menu is Script Editor window, Window
> Funciton List)
- In Library tab select betameta_structs for Python or Meta help for BETA Scripting language and
and then double click on META_KEYWORDS to get all the lists in the Output window of the Script
Editor. If the Output window is not visible, activate it from main menu in Script Editor, Window >
Output window
- In Python Scripting in order to use the KEYWORDS the module constants needs to be imported
first as in example below:
Index
B Data types ............................................. 88
Exceptions ...........................................100
BCGUI Designer ....................................... 225 Handling Dictionaries ............................ 96
Callback functions ............................... 231 Handling Lists ........................................ 94
Common Parameters .......................... 229 Handling Strings .................................... 95
Help ..................................................... 232 Interacting with META ........................103
Parameters .......................................... 230 Loop statements ................................... 92
Toolbox ............................................... 226 META Classes ......................................104
Window Designer ................................ 225 Modules and namespaces..................... 90
BCGUI Functions ...................................... 208 User functions ....................................... 97
BETA Scripting Language
Conditional statements and branching S
........................................................ 137
Script Editor
Custom GUI ......................................... 188
Debug .................................................... 84
Data types ........................................... 126
META Window Designer ....................... 79
Exchanging data .................................. 198
Monitor ................................................. 83
Handling Maps .................................... 145
Project ................................................... 86
Handling Matrices ............................... 142
ScriptEdit window ................................. 71
Handling String.................................... 144
Snippets................................................. 80
Interacting with META ........................ 159
Session
Introduction ........................................ 125
Encrypt Session ..................................... 10
Loop statements ................................. 139
Suppress Redundant Commands .......... 10
Matrices and Maps ............................. 130
Session decoding ......................................... 7
META session commands ................... 158
Session Editor .............................................. 8
META Structs ....................................... 160
Create Package ..................................... 22
Operators and basic calculations ........ 131
Create User Toolbar .............................. 24
User functions ..................................... 147
Debug .................................................... 27
Variables ............................................. 127
Snippets................................................. 25
XML files .............................................. 202
Session files ................................................. 3
C T
Controldraw ............................................ 4, 7
Toolbar Designer ....................................... 33
I Checkbox ............................................... 41
Directory textbox .................................. 47
Installation directory ............................... 112 Filetextbox............................................. 45
Property Editor ...................................... 48
P Radio button ......................................... 42
Python Slider ..................................................... 43
Conditional statements and branching . 91 Textbox.................................................. 44
Custom GUI ......................................... 124