|
|
### Input file for boneload simulations
|
|
|
|
|
|
Let us have a look at the contents of an input file.
|
|
|
Input files are written in Python and contain a set of parameters gathered in a python dictionary and 2 sets of commands which run either [Metafor](http://metafor.ltas.ulg.ac.be/) or [fossils](https://gitlab.uliege.be/rboman/fossils).
|
|
|
|
|
|
As an example, let us analyze [dolicorhynchops_10k.py](https://gitlab.uliege.be/rboman/fossils/-/blob/master/models/dolicorhynchops/dolicorhynchops_10k.py).
|
|
|
|
|
|
This python file contains 3 parts.
|
|
|
|
|
|
The **first one** is a function named `params` which defines a python dictionary filled with the parameter names and their values.
|
|
|
|
|
|
```python
|
|
|
def parms(d={}):
|
|
|
p = {}
|
|
|
|
|
|
# series of lines such as: p['parameter_name'] = value
|
|
|
# [...]
|
|
|
|
|
|
p.update(d)
|
|
|
return p
|
|
|
```
|
|
|
|
|
|
The **second part** is the entry point of Metafor (a function named `getMetafor`). This function is called by Metafor when the script is executed by Metafor. It imports [bonemodel.py](https://gitlab.uliege.be/rboman/fossils/-/blob/master/models/bonemodel.py) which defines the Metafor model.
|
|
|
```python
|
|
|
def getMetafor(p={}):
|
|
|
import bonemodel as model
|
|
|
return model.getMetafor(parms(p))
|
|
|
```
|
|
|
The **third and last part** is related to fossils. These lines are executed when the input file is run in the frame of fossils. It imports [bonemodel2.py](https://gitlab.uliege.be/rboman/fossils/-/blob/master/models/bonemodel2.py) which is the "fossils" version of `bonemodel.py`. Then, the function named `solve` is called with the parameters as arguments.
|
|
|
```python
|
|
|
if __name__ == "__main__":
|
|
|
import models.bonemodel2 as model
|
|
|
model.solve(parms())
|
|
|
```
|
|
|
In practice, the last two blocks can be blindly copied as shown hereabove at the end of any input file. The only important piece of information, which differs from one input file to the other, is the list of parameters in the `params` function.
|
|
|
|
|
|
### Parameters
|
|
|
|
|
|
#### main dictionary
|
|
|
|
|
|
| name | type | description |
|
|
|
| ------------- | ------------------------------------- | ------------------------------------------------------------ |
|
|
|
| `bone` | filename | Full path to the surface mesh. STL, PLY, MSH and GEO files are accepted. |
|
|
|
| `contact_pts` | list of [x,y,z], or list of filenames | List of coordinates of points where fixations are prescribed during the simulation (e.g.: 2 points: [ [x1,y1,z2], [x2, y2, z2] ]). Each point can also be entered as the filename of a PLY or OFF file containing a single point, instead of a [x,y,z] list. |
|
|
|
| `axis_pt1` | [x,y,z], or filename | Position of the node acting as the first point of the rotation axis of the bone. It can be introduced as a 3-component vector (a list of 3 scalars) or a full path to a PLY or OFF file containing a single point. |
|
|
|
| `axis_pt2` | [x,y,z], or filename | Second point of the rotation axis. |
|
|
|
| `muscles` | list of dict | A list of muscles. Each muscle is defined by a dictionary (see [below](#muscles)). |
|
|
|
| `fixations` | dict (string=>list) | A dict (key=>value) which gives the components that are fixed (value), for the contact points and the 2 points of the axis (keys). The components to be fixed are given as a list of `x`, `y`, `z` characters. |
|
|
|
| `density` | scalar | Bone density (only used by the Chung-Hulbert time integration scheme of Metafor - not used with the linear-statics solver of fossils). |
|
|
|
| `Young` | scalar | Linear elasticity: Young's modulus. |
|
|
|
| `Poisson` | scalar | Linear elasticity: Poisson's coefficient. |
|
|
|
|
|
|
#### muscles
|
|
|
|
|
|
| name | type | description |
|
|
|
| --------- | -------------------- | ------------------------------------------------------------ |
|
|
|
| `file` | filename | Full path to the file containing the part of the surface mesh corresponding to the muscle insertion surface. This mesh should contain a subset of the triangles from the bone surface mesh (see `bone`parameter above). |
|
|
|
| `force` | scalar | Amplitude of the muscle force. The distributed forces will be scaled such that the norm of their sum equals to this value. |
|
|
|
| `focalpt` | [x,y,z], or filename | The position of the focal point specified either with a coordinate list [x,y,z] or a filename of a mesh containing a single point. |
|
|
|
| `method` | string | The load distribution method: <ul><li>`U` (uniform loading): the load is uniformly distributed on the surface; </li><li>`T` (tangential loading): the loads follow the muscle fibres. The forces pointing through the bone are projected onto the tangent plane of the bone surface, </li><li>`T+N` (tangent+normal): same as `T` but a normal component is added to the tangential one, which models the compressive action of the fibres that wrap around the bone.</li></ul><br />More mathematical details [here](boneload). |
|
|
|
|
|
|
### Additional notes
|
|
|
|
|
|
#### Relative paths
|
|
|
|
|
|
Prescribing the full path of mesh files can be done using a relative path built from the path of your input file:
|
|
|
|
|
|
As an example, if your script is located at `c:\Users\Boman\Documents\Mywork\Panthera_pardus.py` on your hard drive and the surface mesh is in the subfolder `150k` in the same folder, instead of writing
|
|
|
|
|
|
```python
|
|
|
def parms(d={}):
|
|
|
p = {}
|
|
|
p['bone'] = r'c:\Users\Boman\Documents\Mywork\150k\Panthera_pardus_mandible.stl'
|
|
|
```
|
|
|
|
|
|
which is not portable (Linux, macOS) and which makes the files not movable from one location to another one, you can retrieve the path of your script (`c:\Users\Boman\Documents\Mywork`\) with `os.path.dirname(__file__)` (in python, `__file__` is the full path to the current script and `os.path.dirname` extracts the folder part of a file name or folder name):
|
|
|
|
|
|
```python
|
|
|
import os
|
|
|
path = os.path.join(os.path.dirname(__file__),'150k')
|
|
|
# from here, path=r'c:\Users\Boman\Documents\Mywork\150k'
|
|
|
```
|
|
|
|
|
|
The previous piece of code can thus be modified into:
|
|
|
|
|
|
```python
|
|
|
def parms(d={}):
|
|
|
p = {}
|
|
|
import os
|
|
|
path = os.path.join(os.path.dirname(__file__),'150k')
|
|
|
p['bone'] = f'{path}/Panthera_pardus_mandible.stl'
|
|
|
```
|
|
|
|
|
|
#### What are these 'r' and 'f' in front of strings?
|
|
|
|
|
|
The `r` character in front of a python string means that the string is a "raw" string which means that it does not contain any "escaped characters" (it means that backslash characters are "real" backslash). If you don't use raw strings on windows the path separator which is a backslash will be sometimes merged with the next character to form an escaped character which has a special meaning (`\n` is a newline, `\t` is a tabulation, etc.).
|
|
|
|
|
|
For example:
|
|
|
|
|
|
* `'Users\Boman'` means `'Users'` + `'\b'` (the bell character) + `'oman'.`
|
|
|
* `r'Users\Boman'` == `'Users\\Boman'` which is the correct set of characters.
|
|
|
|
|
|
The `f` character means that the string contains special formatting substrings between curly braces `{` ,`}`. these strings are called [f-strings](https://realpython.com/python-f-strings/). A variable name between curly braces in a f-string is replaced by python by the value of the variable; thus `f'{path}'` is translated to `'c:\\Users\\Boman\\Documents\\Mywork\\150k'` in the last example.
|
|
|
|
|
|
|
|
|
|
|
|
|