
Using Scripts with NairnFEAMPM
Although NairnFEAMPM best scripted using its Internal Scripting methods (for speed and reliability), it can also be scripted using external AppleScripts or Python scripts. Python, for example, might have some useful high-level options not available to internal scripts. This help topic explains external scripting methods:
- Getting Started with External Scripts
- Using Python 3.x (if needed)
- External Scripting Commands
- Plotting Results in Script Control
Getting Started with External Scripts
This help outlines the techniques for scripting NairnFEAMPM using AppleScripts or Python scripts. Like other scriptable Mac applications, you can read all the external scripting options by opening the NairnFEAMPM scripting "dictionary" using Apple's Script Editor. Scripting dictionaries define all commands and properties accessible to scripts. Since dictionaries on commands are very brief, more details on each command are listed below.
To get started, the following AppleScript is a template for automated control of NairnFEAMPM. Click each section for more details on that section. See a second template below for a similar template script in Python.
-- open a file tell application "NairnFEAMPM" open inpfile set cmdName to name of front document tell document cmdName -- set variables SetVariable named "length" value 10 -- loop over several calculations repeat with i from 1 to 10 SetVariable named "width" value i SetVariable named "archiveRoot" value "Results-" & i -- run analysis until done RunAnalysis repeat while processing is true end repeat -- save the results set fileName to (saveFolder & "/" & baseName & "-" & i & ".fea") tell application "NairnFEAMPM" save front results document in fileName end tell end repeat end tell end tell
The following Python script is a template for automated control of NairnFEAMPM (see below if Python scripts are failing to launch). Note that the NairnFEAMPM scripting dictionary is written for scripts written in AppleScript. The syntax for calling commands in Python are listed below. To read properties listed in the dictionary while using Python, the rules are to remove all spaces (if it has more than one word), capitalize the first letter of any words after a space, and then use parentheses. For example, to read "run status
" in Python, use runStatus()
. To set a property (and only a few can be set), precede the property name with set
, capitalize the name, and follow it with underscore and the setting in parentheses. For example, to set the text
, use setText_("New Text")
.
#!/usr/bin/python # Prepare to use Apple's Scripting Bridge for Python from Foundation import * from ScriptingBridge import * import time # fetch application object and open a file nfm = SBApplication.applicationWithBundleIdentifier_("com.geditcom.NairnFEAMPM") nfm.open_(inpfile) # get front document # need get() because front document will change in the loop ndoc=nfm.documents()[0].get() # set variables ndoc.SetVariableNamed_value_("length",100) # loop over several calculations for i in range(10): ndoc.SetVariableNamed_value_("width",i+1) ndoc.SetVariableNamed_value_("archiveRoot","Results-"+str(i)) # run analysis until done ndoc.RunAnalysis() while ndoc.processing()==True: time.sleep(1.) # save the results in front document fileName=saveFolder+"/"+baseName+"-"+str(i)+".fea" nres=nfm.documents()[0].get() nres.saveAs_in_(None,saveFile)
Prepare to use Apple's Scripting Bridge
Scripts written in Python use Apple's Scripting Bridge, which became available in MacOS 10.5. The first step is to import the Apple "Foundation" and "Scripting Bridge" libraries. The Python commands are in the above template (see below if you get error message about no module named "Foundation").
Next, all Python scripts will fetch the application object for NairnFEAMPM, which is set equal to the variable nfm
in the template script.
Python scripts can use custom modules. If you use a from
or import
command, NairnFEAMPM will first look for the module in the folder ~/Library/Scripts/NairnFEAMPM Scripts/modules
. After that folder, it will search all standard locations for Python modules. You should therefore store all NairnFEAMPM-specific modules in that folder.
Open a File
This template assumes inpfile
is full path name to a valid FEA or MPM commands file, which is either coded into the script or retrieved using scripting tools (such as the user openFile command).
Alternatively, a script might be written to work on the current front document. For such scripts, there is no need to open a different file. You can check the type
property of the front document to verify it is a "Commands" or "Results" document as needed for the script.
Set Variables
SetVariable commands can set any variables. The variables can be used in the commands file. To help developing command files for use with or without scripts, a variable _ScriptMode_
will always be defined when a script is running. For example:
ifNDef _ScriptMode_ #length=20 #width=5 endif
can be used in commands. If the commands file is called from a script, the conditional will be skipped and the variables #length
and #width
will be assumed to have been defined by the script (using the SetVariable
command). When the commands file is executed normally, the conditional will set the variables.
Run Several Calculations
The point of script control is to run multiple calculations. Most script will therefore have a repeat loop. The loop will set one or more variables to some values, run an analysis, and finally read and store results are save some result to disk.
Run Analysis
The RunAnalysis
command starts the analysis. The script then needs to wait until the analysis is done, which can be done by a repeat loop that checks the processing
property. The property processing
will be true
until the calculations are done. When it becomes false, the loop exits and the script continues.
AppleScripts sometimes have problems waiting in such loops, which may be related to script time out issues. These analysis loops seem to work better in Python and is one reason Python is the recommended scripting tool.
Save Results
The results are usually saved to a file. If desired, the text in the results can be interrogated to read the results and store in text for a report (such as a spreadsheet of results) or write results to the message window.
Using Python 3.x
Apple used to preinstall Python 2.7 and later Python 3.0. Python is a legacy version that is no longer used and Apple stopped including any Python in MacOS Monterrey 12.3 or newer. Here are methods needed for running Python scripts in MacOS version that do not have Python installed. Besides install Python 3 3, you also need to install the "Foundation" module, which MacOS uses to let Python talk to Mac apps.
Installing Python When Needed
The following steps should get Python installed (and should only need to be done once on each new computer). You will know an install is needed if you try to run a Python script and you get a window with the message:
The "python3" command requires the command line developer tools. Would you like to install the tools now?"
Click the "Install" button to download and install them. It might take a while depending on your internet speed. Note that if you are a developer yourself and have already installed command lines tools (such as by installing XCode), you should not need this step (and should not even get the window to install them).
This command line tool installation unfortunately does not install all the needed Python tools. It lacks the MacOS libraries that allow Python 3 to talk to applications like NairnFEAMPM (even those with preinstalled command line tools may get this message). You will know those libraries are missing if when you now try running Python script and get a long error message that ends with the line
ModulueNotFoundError: No module named 'Foundation'
In other words, you have to install the MacOS libraries with that module. Here the steps :
- Open the "Terminal" app. It can found in the "Utilities" folder in your "Applications" directory.
- On the command line in the Terminal app, enter:
sudo -H python3 -m pip install pyobjc
When you type return or enter, you will be asked for your administrator password and then this command will download, compile, and install all needed libraries.
Still Having Problems?
If for some reason, you do not get a notice to "install" command line tools and python extensions will not run, you may need to manually install those tools. (Note: here "not run" means will not start at all, while starting but getting the "No module named 'Foundation'" errors means tools are installed OK, but you need the second install explained above.) If Python scripts still are "not running," two options to manually install the command line tools are:
- Install XCode (available in the Mac app store) and tell it to install command line tools.
- Install command line tools without using XCode as explained on this website
Some command-line tools installations go to different locations. The default location for command line tools in a unix environment is to put them in the folder /usr/bin
. If your install did not put them in this standard location, they may have been installed instead in the /Library/Developer/CommandLineTools/usr/bin
folder, where this is the Library
folder at the root level of your hard disk. If you still cannot run python and your tools are in this second location, you can try to following two steps:
- Install the "Foundation" module as described above, but tell it to install at the alternate command line tools installation by using:
sudo -H /Library/Developer/CommandLineTools/usr/bin/python3 -m pip install pyobjc
- Change the path NairnFEAMPM uses to launch Python scripts. This path is currently not changeable in the preferences window, but can be changed in the Terminal app using the
defaults
tool. The read the current setting use:defaults read com.geditcom.NairnFEAMPM "Path to python"
The default setting is/usr/bin/python3
. You can use thedefaults
tool to change to any other path. For example, with alternate command-line tool installations, you might needdefaults write com.geditcom.NairnFEAMPM "Path to python" /Library/Developer/CommandLineTools/usr/bin/python3
For reliable changes, thedefaults
commands should not be used while NairnFEAMPM is running.
Finally, if you did a third-party python install, such as by downloading from python.org, it still should work, but you might have to repeat the above two steps for tools at /Library/Developer/CommandLineTools/usr/bin
but substitute the path to your installed Python 3 binary. In other words, install the "Foundation" module in your installed pPthon location and point the "Path to python" to your installed location.
External Scripting Commands
The above templates can easily be expanded with any features of AppleScript or Python, or by using built-in commands in NairnFEAMPM. For example, you can save key results to a text file (using a scriptable text application such as TextEdit or by saving text in the message window), plot the results (using a scriptable plotting program), or anything else possible in scripts.
Below are the current commands that can be sent to NairnFEAMPM or to various types of NairnFEAMPM documents. You can also open the NairnFEAMPM dictionary in the Script Editor for an outline of these commands. The following commands (in alphabetical order) are supported. Optional arguments are in square brackets; other arguments are required. Each command is also followed by the format needed to call them in Python scripts (which require all arguments).
closeDoc
- Closes the document and all its windows. The Apple Script close command is supposed to handle this tasks, but does not work well in Python. This command provides a second option. If the document has been changed, any changes are lost.
Supported By: command documents, results documents, plot documents
Python use:closeDoc()
console message log text msgText
- This command writes
msgText
to the console log, which can be read using the MacOS Console app. The argument is usually a string, but it will work with some other other objects as well (e.g., list, dictionary, number, etc.). This command is useful for debugging or a place to write messages during long calculations.
Supported By: application (AppleScript only) and documents (all scripts)
Python use:consoleMessageLogText_(msgText)
CrackClosure tip node tipNum [to node adjNode] [normal traction normT] [shear traction shearT]
- Calculate mode I and mode II energy release rates at a crack tip. It will return a record with entries for "GI", "GII", and "Gtot" for the energy release rates. The returned record will have other calculation details as well (similar to what appears in the crack closure window). If there is a error, the returned record will have single entry "ERROR" that describes the error. The tractions allow specification of constant crack-surface tractions.
The crack tip is specified by thetip node
at the crack tip. You can optionally specify the adjacent node back from the crack tip in the intact direction (theto node
argument). When adjacent node is not specified, the calculation will search for it instead (the default and recommended method). Set the adjacent node to 0 in Python to not specify it.
Supported By: results documents
Python use:CrackClosureTipNode_normalTraction_shearTraction_toNode_(100,0,0,0)
ExportXML to file filename
- Export the interpreted commands in a commands document to the file in
filename
. The file name can be a POSIX path (i.e., folders separated by slashes ('/
')) or a colon-delimited path (i.e., Classic Mac path), but if a POSIX path is used, the name cannot contain any colons (':
'). This command in conjunction with theInterpret
command can save a series of input files for submitting batch jobs on a cluster.
Supported By: command documents
Python use:ExportXMLToFile_("path to file")
find global quantity name
- Find array of an archived global quantity with the given
name
, which comes from the list of names available for global archiving.
Supported By: results documents
Python use:findGlobalQuantity_(name)
FindNode near {x,y}
- Find node number closest to a point specified in the list argument. It will return the node number.
Supported By: results documents
Python use:FindNodeNear_([x,y])
FindSection named sectionTitle
- Find all text of a section from a results file with the provided
sectionTitle
. It will return it as a string.
Supported By: results documents
Python use:FindSectionNamed_(sectionTitle)
GetVariable named varName
- Get value of a variable given by string in
varName
(without the leading '#') as defined in the previous commands interpretation (it will be empty string if the variable is not defined).
Supported By: command or results documents
Python use:GetVariableNamed_(name)
Interpret
- Interpret the commands in a commands document, but do not do the calculations. You can monitor the
processing
property of the front document to find out when the interpretation is done.
Supported By: command documents
Python use:Interpret()
Message [set text msgText] [append addText] [save in filename]
- This commands works with the message panel. The
set text
argument will clear the panel and set it to the providedmsgText
. Theappend
argument will appendaddText
to the message panel. Thesave in
argument will save the current message panel text in the file with path infilename
(a colon-delimited path from Classic Mac or common AppleScript methods). Ifset text
andappend
are both given, the panel will be cleared, set tomsgText
and then appended withaddText
. Thesave in
argument can be in addition to other arguments or alone to just save the text. Parameters not used in Python can be set toNone
. You also use standard Python print commands and their output will be appended to the message window.
This message window can store results of calculations or simply display a message about the current state of a long process. When done, the results can be saved to a file. Since there is only one message panel, you have to be careful other windows will not write to the panel while the script is using it, otherwise some text might might be lost.
Supported By: application (AppleScript only) and documents (all scripts)
Python use:MessageAppend_saveIn_setText_(addText,filename,msgText)
RunAnalysis
- Interpret the commands in a commands document and then do the calculations. You can monitor the
processing
property of the front document to find out when the calculations are done. When done, they will appear in a new results document, which will have replaced the commands document as the new front document.
This command will exit as soon as the calculations start. You can monitor theprocessing
attribute of the command document to wait for it to finish.
Warning: This command will create a file in the same folder as the commands file with the same name as the commands file, but with extension ".mpm" or ".fea" for MPM or FEA calculations, respectively. This file will be autosaved after each run, which means it will overwrite any previous file with that same name. To preserve the results, either save the file to a new name or use the RunAnalysisSaving command instead.
Supported By: command documents
Python use:RunAnalysis()
RunAnalysisSaving out path (file_path_name) background (True or False)
- This command is the same as the RunAnalysis command, but you provide path name for the output file and optionally tell it to submit as a background process. The path name can be either a full path or a relative path, where relative path is relative to the saved commands file. The parent directory for the output file must already exist. Hint: the user open folder command can be good way to pick a folder and to be sure it exists. When background is
True
, the process will be submitted as a background job and no results will appear in the output window. When it isFalse
, a standard foreground job is submitted and the results can be read from the output results document when they are done.
This command will exit as soon as the calculations start or the background process is submitted. You can monitor theprocessing
attribute of the command document to wait for it to finish; for a background process it is finished once the submittal command is accepted.
Supported By: command documents
Python use:RunAnalysisSavingOutPath_background_(file_path_name,False)
SetVariable named varName to value
- Set the variable given by string in
varName
(without the leading '#') to the providedvalue
(value
may be string or a number).
Supported By: command documents
Python use:SetVariableNamed_value_(name,value)
time plot plot settings plotOptions
- Plots a selected MPM result as a function of time in a 2D plot document. The result to be plot is determined by the plot settings. See the xy plot command to plot 2D plot of a result through the mesh or mpm grid. Note that the command results before the plot is done. A script will usually need a loop to wait for plot completion. The returned value is a specifier for the new plot document.
Supported By: results documents
Python use:timePlotPlotSettings_(plotOptions)
user choice prompt "Prompt Text" list items {"item 1",";item 2"} [title "Panel Title"] [buttons {"OK","Cancel"}] [multiple true]
- Will display a dialog box where the user can select one item from the provided
list items
. To have an item preselected, use a semicolon (";") as the first character (the semicolon will not be displayed). If no item is marked as selected, the first item will be selected. The requiredprompt
is displayed above the list box to explain the requested selection (it can be any length and use multiple lines). The optionaltitle
is displayed in the title bar of the window. The optionalbuttons
can change the text of the default "OK" and "Cancel" buttons and optionally add a third button. The optionalmultiple
parameter can be true or false to allow selection of multiple items (if it is false and more than one item is marked as selected, only the first one will be selected).
The returned result of this command is a list with three items. The first item is the text of the button that was clicked. The second item will be another list with the text of the one or more items selected by the user. The third item will be another list with indices of the one or more items selected by the user (the first item is index=1).
This command can be done with the choose from list command in AppleScript. It is provided in NairnFEAMPM for use in Python scripts or as an alternative to the AppleScript version in AppleScripts.
Supported By: application (AppleScript only) and documents (all scripts)
Python use:userChoiceListItems_prompt_buttons_multiple_title_(["item 1","item 2","item 3"], "Prompt Text", ["OK","Cancel"], False, "Panel Title")
- use capitalizedTrue
orFalse
in Python. user input prompt "Prompt Text" [initial text "default text"] [title "Panel Title"] [buttons {"OK","Cancel"}]
- Will display a dialog box where the user can enter one line of text. The required
prompt
is displayed above the text field to explain the requested input (it can be any length and use multiple lines). The optionalinitial text
is placed in the text field (it can only be a single line). The optionaltitle
is displayed in the title bar of the window. The optionalbuttons
can change the text of the default "OK" and "Cancel" buttons and optionally add a third button. The returned result of this command is a list with two items. The first item is the text of the button that was clicked. The second item is the text entered by the user in the text field.
This command can be done with the display dialog command in AppleScript. It is provided in NairnFEAMPM for use in Python scripts or as an alternative to the AppleScript version in AppleScripts.
Supported By: application (AppleScript only) and documents (all scripts)
Python use:userInputPrompt_buttons_initialText_title_("Prompt Text", ["OK","Cancel"], "default text", "Panel Title")
user openFile [start "/Users/nairnj/Desktop"] [extensions {"fmcmd", "mpm"}]
- Will display standard MacOS panel for user to select an existing file. The
start
parameter can be used to define the initially selected folder and/or file. Theextensions
list means the user can only select files with those extensions. When done, the command will return the full POSIX path to the selected file (or empty if canceled).
This command can be done with the choose file command in AppleScript. It is provided in NairnFEAMPM for use in Python scripts or as an alternative to the AppleScript version in AppleScripts.
Supported By: application (AppleScript only) and documents (all scripts)
Python use:userOpenFileExtensions_start_(["fmcmd","mpm"], "/Users/nairnj/Desktop")
user openFolder [start "/Users/nairnj/Desktop"]
- Will display standard MacOS panel for user to select an existing folder or create and select a new folder. The
start
parameter can be used to define the initially selected folder. When done, the command will return the full POSIX path to the selected folder (or empty if canceled).
This command can be done with the choose folder command in AppleScript. It is provided in NairnFEAMPM for use in Python scripts or as an alternative to the AppleScript version in AppleScripts.
Supported By: application (AppleScript only) and documents (all scripts)
Python use:userOpenFolderStart_("/Users/nairnj/Desktop")
user option title "Main text" [message "Subtitle text"] [buttons {"OK","Cancel"}]
- Will display a dialog box to the user with one to three buttons (provided in the list). The title is in bold and main text of the window. The message appears below the title to provide extra information. The first button is the default button and the buttons appear right to left. The returned result of this command is the text of the clicked button.
This command can be done with the display dialog command in AppleScript. It is provided in NairnFEAMPM for use in Python scripts or as an alternative to the AppleScript version in AppleScripts.
Supported By: application (AppleScript only) and documents (all scripts)
Python use:userOptionTitle_buttons_message_("Main text", ["OK","Cancel"], "Subtitle text")
user saveFile [start "/Users/nairnj/Desktop"] [extensions {"txt"] [title "Panel Title"]
- Will display standard MacOS panel for selecting file name and location for saving a file. The
start
parameter can be used to define the initially selected folder and/or file name (the file need not exist and you can supply just the name if the start folder is not important). Theextensions
list means the user should save to files with those extensions; if they choose another extension, they will be prompted to use the first extension in the list. Thetitle
parameter is the title at the top for the save file panel. If the selected file already exists, the user will be asked to confirm that it is OK to replace that file. When done, the command will return the full POSIX path to the selected file (or empty if canceled).
This command can be done with the choose file name command in AppleScript. It is provided in NairnFEAMPM for use in Python scripts or as an alternative to the AppleScript version in AppleScripts.
Supported By: application (AppleScript only) and documents (all scripts)
Python use:userSaveFileExtensions_start_title_(["txt"], "/Users/nairnj/Desktop", "Panel Title")
xy plot plot settings plotOptions
- Plots a selected MPM or FEA result as a function of position in a 2D plot document. The result to be plotted is determined by the plot settings. See the time plot command to plot an MPM result as a function of time. Note that the command results before the plot is done. A script will usually need a loop to wait for plot completion. The returned value is a specifier for the new plot document.
Supported By: results documents
Python use:xyPlotPlotSettings_(plotOptions)
Plotting Results in Script Control
The time plot and xy plot commands plot selected results to a 2D plot document. The script can read the data in the results plot for more calculations. The plot that is generated depends on the the command's plotOptions
argument. The current options, which are case insensitive, are:
- Quantity to Plot (all plots):
menutext
- quantity by name in plot menu (string, case sensitive)plotindex
- quantity by index in plot menu (number from 0)component
- quantity by tag (number used in code)tensorindex
- select component of tensor to plot (number from 0)vectorindex
- select component of vector to plot (number from 0)angle
- rotate vector or tensor (in degrees)expression
- enter an valid expression to plot (string)expressiontitle
- enter a title a plotted expression (string)
- Extra options for time plots:
quantity
- whenmenutext
is "Global Results", this value is the global quantity, by name, to plot. Note that first item in returned list is the plotted quantity and the values start at the second item.materialoption
- plot the provide point number (0), average all points (1), average the provided material number (2), sum all points (3), or sum the provided material number (4)initialpoint
- point number to plot whenmaterialoption
= 0.materialnumber
- material number to average whenmaterialoptoin
= 2 or 4.cracknumber
- crack number to plottipnumber
- crack tip to plot for start (0) or end (1).
- Extra options for xy plots:
archive
- select time to plot by archive index (numbered from 1)variable
- plot option (by number) for path though the mesh as 0: x or r, 1: y or z, 2: D, 3: T, 4: p:x+d*t, 5: p0:x0+d*t, or 6: Histogramcontour
- an expression for the plot contour (string even if just a number). For particle plots can be comma separated list of 1 to 6 numbers as needed.contourrange
- range (+/-) to average along the contour (number)cracknumber
- crack number to plot
- Script control:
- proceed - true to generate the plot; if false, the software will stop for more user input in the plot dialog box. This parameter is automatically set to "true" when called from an internal script.
- close - internal scripts close the window after the plot is done unless this key is set to "no" (only used by internal scripts).
- superpose - with any value, the next plot is superposed on the same type of plot from the same document (if available and only used by internal scripts).
The plotting command will return to the script befefore the plot is done. If your want to access the data in the script, you will need to create a loop that waits for the command to finish. The following templates prepare a dictionary, call the plot command, and then tell the new plot document to wait until the plot is completed. Once the plot is done, properties of the new plot document are probed to get x-y data points for the plot. See the NairnFEAMPM AppleScript dictionary for details on properties of plot documents.
An AppleScript plotting template is as follows:
-- plot the data tell front results document set plotOptions to (a dictionary of opions) set pdoc to time plot plot settings plotOptions end tell tell front plot document -- wait for plot to finish repeat while plotting is true end repeat -- read plot data tell last plot set xyData to plot data end tell end tell
A template for plotting in Python is as follows:
# plot the data plotOptions = {a dictionary of options} pdoc = rdoc.xyPlotPlotSettings_(plotOptions) # wait for the plot to finish while pdoc.plotting() == True : time.sleep(1.) # get last plot data plots = pdoc.plots() numPlots = plots.count() plot = plots.objectAtIndex_(numPlots-1) xyData = plot.plotData()