There are several ways to output data from AnyBody. The previous tutorials used the 'Dump' class operation to export specific variables. Another option is to have AnyBody write specific variables to a file by adding the 'AnyOutputFile' class to the AnyBody model.
The AnyOutputFile
class in the AnyBody Modeling System produces text files with data. These text files are very similar to comma seperated files with some additional header information.
Here is an example below:
In [1]:
# %load TestOutput.csv
---- AnyBody Output File ---------------------------------
Study Main.MyStudy
Operation Main.MyStudy.InverseDynamics
----------------------------------------------------------
Constants (Name = Value)
Main.MyStudy.FileOutput.ConstName = HelloWorld
Main.MyStudy.nStep = 5
Main.MyModel.Femur.Knee.sRel = { 0.000000000000000e+000, -3.000000000000000e-001, 0.000000000000000e+000}
----------------------------------------------------------
Variables (Column# Name)
col0 Main.MyStudy.t
col1 Main.MyStudy.MomentArm
----------------------------------------------------------
Main.MyStudy.t,Main.MyStudy.MomentArm
0.000000000000000e+000, 3.517106754087954e-002
6.000000000000000e-001, 4.256597756479537e-002
1.200000000000000e+000,-2.495531558514929e-004
1.800000000000000e+000, 4.256603812471121e-002
2.400000000000000e+000, 3.517106649790244e-002
It is not particular difficult to read. You could write you own custom Python, Matlab code to parse the values. But anypytools
has a few convinience functions that makes it very easy to load the files.
This is especially usefull for the header information which can be annoying to parse manually.
In [2]:
from anypytools.datautils import read_anyoutputfile
data, header, constants = read_anyoutputfile("TestOutput.csv")
The function returns three outputs. An array with the time dependent data, and a list of header names:
In [3]:
header, data
Out[3]:
and python dictonary with constant values:
In [4]:
constants
Out[4]:
Sometimes, it can be convenient to save the entire model along with all its data (although this can be several hundred megabytes). It is useful if we later want to analyze other output variables from the model. It can also be useful if we want to load the data in the AnyBody graphical user application and replay the result.
AnyBody has a feature to save the output of a study to an HDF5 file. And like most things in AnyBody, this can also be done with a macro command.
Let us try this with the model from the previous tutorials.
In [5]:
from anypytools.macro_commands import Load, OperationRun, SaveData
macrolist = [
Load('Knee.any'),
OperationRun('Main.MyStudy.Kinematics'),
SaveData('Main.MyStudy', 'output.anydata.h5'),
]
macrolist
Out[5]:
Here we have added a "Save data
" classoperation to the macro.
In [6]:
from anypytools import AnyPyProcess
app = AnyPyProcess()
app.start_macro(macrolist);
The data stored in the file output.anydata.h5 can be re-loaded in the AnyBody GUI application.
To do this; load the model, and then right click the Main.MyStudy.Output
folder and select "Load data".
These files can also be loaded into Matlab or Python. In python this is done using the h5py
module
In [7]:
import numpy as np
import h5py
h5file = h5py.File('output.anydata.h5', "r")
data = np.array( h5file['/Output/MomentArm'] )
h5file.close()
print(data)
The data structure of the HDF5 files can, unfortunately, be very confusing. AnyBody does not save duplicate copies of the same data. If there are multiple references to the same folder, only one will be present in the HDF5 file.
In our model Knee.any
we have a reference to the Knee
joint folder just before the Model
folder in the study section. Thus, all variables inside the Knee
folder cannot be accessed with the path '/Output/Model/Knee/...', but only through the path of the reference '/Output/kneeref/...'.
We can see the problem in the following code snippet:
In [8]:
with h5py.File('output.anydata.h5', "r") as f:
print('/Output/Model/Knee/Pos' in f)
print('/Output/kneeref/Pos' in f)
This makes it difficult to find the correct path in large models with many references. AnyPyTools contains a wrapper for the h5py module, which automatically locates the right data, no matter what path is used. Using this module, we can easily locate the data.
In [9]:
import anypytools.h5py_wrapper as h5py2
with h5py2.File('output.anydata.h5', "r") as f:
print('/Output/Model/Knee/Pos' in f)
print('/Output/kneeref/Pos' in f)
The h5py wrapper will also let us use the AnyScript variable names directly, so we don't have to replace every . (dot) with a / (slash), and remove the stuff before the Output folder.
In [10]:
with h5py2.File('output.anydata.h5', "r") as f:
momentarm = np.array(f['/Output/MomentArm']) # Standard h5py notation
momentarm = np.array(f['Output.MomentArm']) # dot notation
kneeangle = np.array(f['Main.MyStudy.Output.Model.Knee.Pos']) # dot notation with full path
In [11]:
%matplotlib inline
from numpy import degrees
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
plt.plot(degrees(kneeangle), 100*momentarm)
plt.xlabel('Knee flexion (deg)')
plt.ylabel('Moment arm (cm)');
In [ ]: