AnyPyTools can create AnyScript macros automatically. Doing so simplifies the process of writing complex macros and makes it easier to do things like parameter studies, Monte Carlo simulation, etc.
There is a class for every macro command:
In [1]:
from anypytools.macro_commands import (MacroCommand, Load, SetValue, SetValue_random, Dump, SaveDesign,
LoadDesign, SaveValues, LoadValues, UpdateValues, OperationRun)
The following shows how the to generate a simple macro.
In [2]:
macrolist = [
Load('Knee.any', defs={'SUBJECT':'"S02"', 'TRIAL':'"T04"'}),
OperationRun('Main.MyStudy.InverseDynamics'),
Dump('Main.MyStudy.Output.MaxMuscleActivity'),
]
macrolist
Out[2]:
Each macro object will generate the macro commands with the correct syntax.
The macro can be launched using the start_macro()
method of the AnyPyProcess
object.
In [3]:
from anypytools import AnyPyProcess
app = AnyPyProcess()
app.start_macro(macrolist);
The macro_commands
module have classes for generating many of the standard AnyScipt macro commands.
Load(mainfile, defines, paths)
: load commandOperationRun(var)
: select operation and run Dump(var)
: classoperation "Dump"LoadDesign(var, filename)
: classoperation "Load design" SaveDesign(var, filename)
: classoperation "Save design" LoadValues(filename)
: classoperation Main "Load Values" SaveValues(filename)
: classoperation Main "Save Values"UpdateValues()
: classoperation "Update Values"SetValue(var,value)
: classoperation "Set Value" MacroCommand(macro_string)
: Add abitrary macro stringThe macro in the previous example would have been easy to write manually. However, in some cases we want to create many macros. Then it is a big advantage to generate them programmatically.
To generate many macros we need an extra class AnyMacro
to wrap our macro list.
In [5]:
from anypytools import AnyMacro
macrolist = [
Load('Knee.any' ),
OperationRun('Main.MyStudy.InverseDynamics'),
]
mg = AnyMacro(macrolist)
mg
Out[5]:
By default AnyMacro
just behaves as a container for our macro. But has additional attributes that specify how many macros we want.
In [6]:
mg = AnyMacro(macrolist, number_of_macros = 5)
mg
Out[6]:
This can also be overidden when calling its create_macros()
function
In [7]:
mg.create_macros(2)
Out[7]:
This list of macros can also be passed to the 'start_macro' function to executed in parallel.
In [8]:
from anypytools import AnyPyProcess
app = AnyPyProcess()
output = app.start_macro(mg.create_macros(100))
Running many macros is only really useful if the macros are different. Some macros classes, like SetValue()
, accepts lists of values which it distributes across the generated macros.
Imagine a list of 5 parameters. We want to create five macros that use these values:
In [9]:
parameter_list = [2.2, 2.5, 2.7, 2.9, 3.1]
mg = AnyMacro(SetValue('Main.MyParameter', parameter_list ))
mg.create_macros(5)
Out[9]:
Let us combine the previous to create a parameter study. We will continue with the simplified knee model where we left off in the previous tutorial. The parameter study will vary the patella tendon length from 2.0cm to 8.0cm, and observe the effect on maximum muscle activity.
First we create a list of patella length parameters.
In [10]:
patella_tendon_lengths = [
0.02 + i*0.01
for i in range(7)
]
print(patella_tendon_lengths)
This list of values is added to the macros with the SetValue
class.
In [11]:
macro = [
Load('Knee.any'),
SetValue('Main.MyModel.PatellaLigament.DriverPos', patella_tendon_lengths ),
OperationRun('Main.MyStudy.InverseDynamics'),
Dump('Main.MyStudy.Output.Abscissa.t'),
Dump('Main.MyStudy.Output.MaxMuscleActivity'),
Dump('Main.MyModel.PatellaLigament.DriverPos'),
]
parameter_study_macro = AnyMacro(macro, number_of_macros= len(patella_tendon_lengths) )
We can now run the model and analyze the resulting maximum muscle activity by plotting the data in the output
variable:
In [12]:
output = app.start_macro(parameter_study_macro)
In [13]:
%matplotlib inline
import matplotlib.pyplot as plt
for data in output:
max_activity = data['Main.MyStudy.Output.MaxMuscleActivity']
time = data['Main.MyStudy.Output.Abscissa.t']
patella_ligament_length = data['Main.MyModel.PatellaLigament.DriverPos'][0]
plt.plot(time, max_activity, label='{:.1f} cm'.format(100* patella_ligament_length) )
plt.title('Effect of changing patella tendon length')
plt.xlabel('Time steps')
plt.ylabel('Max muscle activity')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2);
In [ ]: