NairnFEAMPM Icon

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

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 :

  1. Open the "Terminal" app. It can found in the "Utilities" folder in your "Applications" directory.
  2. 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:

  1. Install XCode (available in the Mac app store) and tell it to install command line tools.
  2. 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:

  1. 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
  2. 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 the defaults tool to change to any other path. For example, with alternate command-line tool installations, you might need
    defaults write com.geditcom.NairnFEAMPM "Path to python" /Library/Developer/CommandLineTools/usr/bin/python3
    
    For reliable changes, the defaults 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 the tip node at the crack tip. You can optionally specify the adjacent node back from the crack tip in the intact direction (the to 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 the Interpret 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 provided msgText. The append argument will append addText to the message panel. The save in argument will save the current message panel text in the file with path in filename (a colon-delimited path from Classic Mac or common AppleScript methods). If set text and append are both given, the panel will be cleared, set to msgText and then appended with addText. The save in argument can be in addition to other arguments or alone to just save the text. Parameters not used in Python can be set to None. 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 the processing 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 is False, 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 the processing 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 provided value (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 required prompt is displayed above the list box to explain the requested selection (it can be any length and use multiple lines). The optional title is displayed in the title bar of the window. The optional buttons can change the text of the default "OK" and "Cancel" buttons and optionally add a third button. The optional multiple 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 capitalized True or False 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 optional initial text is placed in the text field (it can only be a single line). The optional title is displayed in the title bar of the window. The optional buttons 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. The extensions 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). The extensions 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. The title 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:

  1. 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)
  2. Extra options for time plots:
    • quantity - when menutext 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 when materialoption = 0.
    • materialnumber - material number to average when materialoptoin = 2 or 4.
    • cracknumber - crack number to plot
    • tipnumber - crack tip to plot for start (0) or end (1).
  3. 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: Histogram
    • contour - 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
  4. 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()