Working with data from AnyBody

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.

Working with AnyOutputFiles

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
 0.000000000000000e+000, 3.517106754087954e-002
 6.000000000000000e-001, 4.256597756479537e-002
 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

(['Main.MyStudy.t', 'Main.MyStudy.MomentArm'],
 array([[ 0.00000000e+00,  3.51710675e-02],
        [ 6.00000000e-01,  4.25659776e-02],
        [ 1.20000000e+00, -2.49553156e-04],
        [ 1.80000000e+00,  4.25660381e-02],
        [ 2.40000000e+00,  3.51710665e-02]]))

and python dictonary with constant values:

In [4]:

{'Main.MyStudy.FileOutput.ConstName': 'HelloWorld',
 'Main.MyStudy.nStep': 5.0,
 'Main.MyModel.Femur.Knee.sRel': array([ 0. , -0.3,  0. ])}

Working with HDF5 files

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 = [
  SaveData('Main.MyStudy', 'output.anydata.h5'),

[load "Knee.any", operation Main.MyStudy.Kinematics
 run, classoperation Main.MyStudy.Output "Save data" --type="Deep" --file="output.anydata.h5"]

Here we have added a "Save data" classoperation to the macro.

In [6]:
from anypytools import AnyPyProcess 
app = AnyPyProcess()


Completed: 1

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'] )

[0.03517107 0.03518544 0.03522538 0.03529129 0.03538355 0.03550231
 0.03564761 0.03581929 0.03601707 0.03624048 0.03648895 0.03676178
 0.03705816 0.03737724 0.03771812 0.03807991 0.03846173 0.03886281
 0.03928244 0.03972002 0.0401751  0.04064731 0.04113638 0.04164206
 0.04216406 0.04270195 0.04325503 0.04382223 0.04440197 0.04499208
 0.04558969 0.04619126 0.04679259 0.04738895 0.04797527 0.04854637
 0.0490972  0.04962319 0.05012044 0.0505859  0.051017   0.0514114
 0.05176698 0.0520819  0.05235456 0.05258365 0.05276812 0.05290715
 0.05300015 0.05304675 0.05304675 0.05300015 0.05290715 0.05276812
 0.05258365 0.05235456 0.0520819  0.05176698 0.0514114  0.051017
 0.0505859  0.05012044 0.04962319 0.0490972  0.04854637 0.04797527
 0.04738895 0.04679259 0.04619126 0.04558969 0.04499208 0.04440197
 0.04382223 0.04325503 0.04270195 0.04216406 0.04164206 0.04113638
 0.04064731 0.0401751  0.03972002 0.03928244 0.03886281 0.03846173
 0.03807991 0.03771812 0.03737724 0.03705816 0.03676178 0.03648895
 0.03624048 0.03601707 0.03581929 0.03564761 0.03550231 0.03538355
 0.03529129 0.03522538 0.03518546 0.03517104]

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 [ ]: