Commit a1073a83 authored by Mark van Turnhout's avatar Mark van Turnhout
Browse files

documentation update

parent 33ca45b4
......@@ -51,7 +51,7 @@ for b = 1:numel(basil)
% distance to this point
D = sqrt(sum(V(dp == min(dp),:).^2));
% set indenter start position (+ 0.5 mm)
% set indenter start position (+ 1 mm)
indSE(1,1:3) = tip - (D+1)*idir';
%% indenter end position
......
......@@ -45,6 +45,8 @@
\newcommand\bas[1]{\texttt{bas\_#1.m}\index{bas_\#1.m@\texttt{bas\_#1.m}}}
\newcommand\MRIroot{\texttt{<MRI-root>}\index{<MRI-root>@\texttt{<MRI-root>}}}
\newcommand\basilhome{\texttt{<basilhome>}\index{<basilhome>@\texttt{<basilhome>}}}
\newcommand\gibbon{GIBB\textsl{On}\index{GIBBOn@GIBB\textsl{On}}}
\newcommand\gib[1]{\texttt{#1}\index{GIBBOn@GIBB\textsl{On}-functions!#1@\texttt{#1}}}
\makeindex
% references and hyperlinks
......@@ -71,7 +73,7 @@
% document specific conventions
\newcommand\gibbon{GIBB\textsl{On}\index{GIBBOn@GIBB\textsl{On}}}
\newcommand\warning{\marginpar{\center\includegraphics[width=1cm]{Exclamation.png}\\}}
\newcommand\adoc{\href{http://furnace.wfw.wtb.tue.nl:2080/v6.14/}{Abaqus documentation}}
% \renewcommand{\thesubsection}{\thesection.\alph{subsection}}
......
......@@ -23,6 +23,11 @@ The FE models are analysed with Abaqus' `Large Displacement' option for geometri
\end{equation}
When you use a hyperelastic material law (such as the Ogden material model that is used in BasilLab), Abaqus will also output the logarithmic strains `LE'. See section `1.2.2 Conventions' in the Abaqus Analysis User's Guide of the \adoc{}.
\subsection{Frame of reference}
The $\vec{x}\vec{y}$-plane is the image plane of the MRI-scanner. The $\vec{z}$-direction is along the logitudinal direction of the rats leg (from knee to ankle).
\section{Directory structure}\label{dirstruct}
BasilLab requires knowledge on two directories: one \MRIroot{} where the (raw) MRI-data can be found, and one \basilhome{} where the processed MRI-data and model data can be found. Raw MRI-data for each individual experiment/animal should be stored in a unique folder \textsl{inside} \texttt{<MRI-root>}. Processed MRI-data and model data is stored \textsl{inside} a unique folder in \basilhome{}.
......
......@@ -132,25 +132,25 @@ contour & scans & purpose & section \\
\end{tabulary}
\end{table}
For the segmentation of the MR image data we rely on the \gibbon{}-function \texttt{uiContourSegment}. This function requires a (3D) `mask' to go with the 3D MR voxel data that is to be segmented. The mask should have the same size as the voxel data, and can change between (2D) MRI-slices.
For the segmentation of the MR image data we rely on the \gibbon{}-function \gib{uiContourSegment}. This function requires a (3D) `mask' to go with the 3D MR voxel data that is to be segmented. The mask should have the same size as the voxel data, and can change between (2D) MRI-slices.
BasilLab is very lazy on the masking part.
The function \bas{maskBG}{} loads the voxel set that you wish to segment and shows a maximum intensity projection over the $z$-direction. In this image, you are asked to interactively select the centre and radius of a circle. The circle will serve as the basis of a cylinder-shaped 3D `mask' for \texttt{uiContourSegment}. \bas{maskBG}{} does not make separate mask for skin and bone.
The function \bas{maskBG}{} loads the voxel set that you wish to segment and shows a maximum intensity projection over the $z$-direction. In this image, you are asked to interactively select the centre and radius of a circle. The circle will serve as the basis of a cylinder-shaped 3D `mask' for \gib{uiContourSegment}. \bas{maskBG}{} does not make separate mask for skin and bone.
The mask for \basilhome\texttt{/<basilid>/}\texttt{MRI\_slices\_<foo>.mat}\footnote{\texttt{<foo>} can be \texttt{preload} or \texttt{loading} or \texttt{postload} or \texttt{flash} (see table \ref{mritomatout}).}will be saved as \basilhome\texttt{/}\-\texttt{<basilid>}\-\texttt{/MRI\_BG\_<foo>.mat}. To mask the data in the scans before (\texttt{1}), during (\texttt{2}) and after indentation (\texttt{3}) for \texttt{<basilid> = 140611} call:
\begin{lstlisting}[numbers=none]
>> bas_maskBG(140611, [1 2 3]);
\end{lstlisting}
\noindent With the masks, we can call \bas{segmentMRI} which in turn calls \gibbon{} for the actual segmentation. The output of \texttt{uiContourSegment} is a Matlab structure called \texttt{Vcs} that contains a cell with contour points $(x, y,z)$ for each 2D MRI-slice. \bas{segmentMRI} saves this structure `as is'. The \texttt{Vcs}-structure for the skin in \basilhome\texttt{/<basilid>/}\texttt{MRI\_slices\_<foo>.mat} will be saved as \basilhome\texttt{/<basilid>/}\texttt{contour\_skin\_<foo>.mat}, that of the tibia as \basilhome\texttt{/<basilid>}\-\texttt{/contour\_bone\_<foo>.mat}.
\noindent With the masks, we can call \bas{segmentMRI} which in turn calls \gibbon{} for the actual segmentation. The output of \gib{uiContourSegment} is a Matlab structure called \texttt{Vcs} that contains a cell with contour points $(x, y,z)$ for each 2D MRI-slice. \bas{segmentMRI} saves this structure `as is'. The \texttt{Vcs}-structure for the skin in \basilhome\texttt{/<basilid>/}\texttt{MRI\_slices\_<foo>.mat} will be saved as \basilhome\texttt{/<basilid>/}\texttt{contour\_skin\_<foo>.mat}, that of the tibia as \basilhome\texttt{/<basilid>}\-\texttt{/contour\_bone\_<foo>.mat}.
Note that \bas{segmentMRI} loaded \basilhome\texttt{/<basilid>/}\texttt{MRI\_voxel\_<foo>.txt} in the process. The dimensions of the saved contours are in mm. To segment the skin and bone data in the scans before (\texttt{1,2}), during (\texttt{3,4}), and the bone contour after indentation (\texttt{6}) for \texttt{<basilid> = 140611} call:
\begin{lstlisting}[numbers=none]
>> bas_segmentMRI(140611, [1:4, 6]);
\end{lstlisting}
\noindent Finally, we need to check for missing contours in de segmented data. The \texttt{Vcs}-structure of \texttt{uiContourSegment} may contain empty cells, and missing contour data may mess op BasilLab and post-processing. The function \bas{checkVsize} loads five contour-sets \texttt{contour\_skin\_preload.mat}, \texttt{contour\_skin\_loading.mat}, \texttt{contour\_bone\_preload.mat}, \texttt{contour\_bone\_loading.mat}, and \texttt{contour\_bone\_postload.mat} from \basilhome\texttt{/<basilid>/}, and deletes a contour that is missing from \textsl{any} set from \textsl{all} sets.
\noindent Finally, we need to check for missing contours in de segmented data. The \texttt{Vcs}-structure of \gib{uiContourSegment} may contain empty cells, and missing contour data may mess op BasilLab and post-processing. The function \bas{checkVsize} loads five contour-sets \texttt{contour\_skin\_preload.mat}, \texttt{contour\_skin\_loading.mat}, \texttt{contour\_bone\_preload.mat}, \texttt{contour\_bone\_loading.mat}, and \texttt{contour\_bone\_postload.mat} from \basilhome\texttt{/<basilid>/}, and deletes a contour that is missing from \textsl{any} set from \textsl{all} sets.
The (new) contour sets are saved with \texttt{-ncc} appended to their file name, i.e.\ the corrected set for \texttt{contour\_skin\_preload.mat} will be saved as \texttt{contour\_skin\_preload-ncc.mat}. The original data will remain untouched. To post-process the contours for \texttt{<basilid> = 140611} and \texttt{<basilid> = 140613} call:
\begin{lstlisting}[numbers=none]
......@@ -165,7 +165,7 @@ The function \bas{mapBone} uses the segmented contours \texttt{contour\_bone\_<f
The output of \bas{mapBone}{} consists of a $3\times 3$ matrix for each of the two cases. The first row contains the centre of mass $[x\;y\;z]$ of the tibia contours (in mm) in the \texttt{preload}-contours, and the second row contains the centre of mass of the tibia contours in the \texttt{loading}- or \texttt{postload}-contours. The third row contains three `Euler angles' $[\alpha\;\beta\;\gamma]$ that describe the rotation of the tibia around its centre of mass. The angles are estimated with a minimisation algorithm that runs on the function \bas{estBoneRot}.
These Euler angles follow the \gibbon-convention (see \texttt{euler2DCM.m}): $\alpha$ is the rotation around the $x$-axis, $\beta$ the rotation around the $y$-axis, and $\gamma$ the rotation around the $z$-axis, such that the 2D $(3\times 3)$ rotation matrix that describes the 3D rotation is given by:
These Euler angles follow the \gibbon-convention (see \gib{euler2DCM.m}): $\alpha$ is the rotation around the $x$-axis, $\beta$ the rotation around the $y$-axis, and $\gamma$ the rotation around the $z$-axis, such that the 2D $(3\times 3)$ rotation matrix that describes the 3D rotation is given by:
\begin{equation}
\mat{R}_{\alpha\beta\gamma} = \mat{R}_\alpha\cdot\mat{R}_\beta \cdot \mat{R}_\gamma
\end{equation}
......@@ -178,13 +178,75 @@ The $3\times 3$ matrix (centres of mass, Euler angles) is written to \texttt{Bon
\subsection{Map indenter movement}\label{mapind}
The indenter movement is of course needed as boundary condition in the FEM. The function \bas{estIndDisp}{}
The indenter movement is of course needed as boundary condition in the FEM. Mapping of the indenter comprises of three steps: (1) The function \bas{estCylPos} finds the 3D orientation and the centre of mass of the indenter with the help from \texttt{MRI\_slices\_loading.mat} and \texttt{contour\_skin\_loading.mat}; next (2) \bas{estIndDisp}{} uses \texttt{contour\_skin\_preload.mat} to find the start position of the indenter (for the FEM); and finally (3) \bas{estIndDisp}{} uses \texttt{contour\_skin\_loading.mat} to find the end position of the indenter.\\
\noindent First, we find the orientation of the indenter in the MRI-data during indentation. The skin contours during indentation are loaded from \texttt{contour\_skin\_loading.mat} and used to dismiss voxel data that belongs to the soft tissue in the \texttt{MRI\_slices\_loading.mat}-MR-data. We are left with the very bright indenter and some noise in these images and from these we can threshold the voxels that belong to the indenter. A call to \bas{getIndDir} gives us the eigenvectors of the mass moment of inertia of the indenter voxels, and the centre of mass of these voxels.
We use the eigenvector that is closest to the image $\vec{x}\vec{y}$-plane as the (main) orientation of the indenter. This orientation vector $\vec{v}$ is transformed to a rotation matrix $\mat{R}$ by the \gibbon-script \gib{vecAngle2Rot} such that
\begin{equation}
\vec{v}^\text{T} = \begin{bmatrix} 0& 0& 1\end{bmatrix}\cdot \mat{R}^\text{T}
\end{equation}
A first estimate of the indenter tip position during indentation is calculated from the centre of mass and the indenter orientation. The results are written to disk as a $4\times 3$ matrix in \basilhome\texttt{/<basilid>}\texttt{/Indenter\_tipNR.txt}. The first row of this matrix contains the estimate of the indenter tip position $[x y z]$ (in mm), and the second to last rows are the $3 \times 3$ rotation matrix $\mat{R}$ from \gib{vecAngle2Rot}.\\
\noindent Next, in \bas{estIndDisp} we use the skin contours before indentation \texttt{contour\_skin\_preload.mat} and the indenter orientation and tip position from \bas{estCylPos} to find the start position of the indenter for the FEM: the indenter is moved `backwards' along its (main) orientation until the indenter tip is 1 mm outside the undeformed skin contours. \\
\noindent Finally, we use the skin contours during indentation \texttt{contour\_skin\_loading.mat} and the indenter orientation and tip position from \bas{estCylPos} to find the end position of the indenter. The indenter is moved along its (main) orientation until the indenter tip starts to penetrate the (deformed) skin contours. This is a minimalisation problem that uses \bas{estIndEnd} as anonymous function to minimize.\\
\noindent The results of \bas{estIndDisp} are written to \basilhome\texttt{/<basilid>}\texttt{/Indenter\_StartEnd.txt} in a $2 \times 3$ matrix. The first row contains the coordinates of the indenter tip $[x y z]$ (in mm) before indentation, the second row contains the coordinates of the indenter tip during indentation.
\subsection{Putting it all together: \bas{prepFEM}}
If all went well, you should now have the files listed in table \eqref{prepfemfiles} in your \basilhome\texttt{/<basilid>/}-directory (in addition to the files listed in table \ref{mritomatout}). The function \bas{prepFEM} checks for the presence of these files and runs the appropriate functions (column two in table \ref{prepfemfiles}) when files are missing. If the \texttt{contour}-files are missing, \bas{prepFEM} calls \bas{segmentMRI} to prompt the user to (manually) segment
\begin{enumerate}
\item the skin contours before indentation;
\item the bone contours before indentation;
\item the skin contours during indentation;
\item the bone contours during indentation; and
\item the bone contours after indentation;
\end{enumerate}
in that order. Other files are produced automagically and do not require user interaction. To prepare your MRI-data for building of the FEM for \texttt{<basilid> = 140611} and \texttt{<basilid> = 140613} call:
\begin{lstlisting}[numbers=none]
>> bas_prepFEM([140611, 140613]);
\end{lstlisting}
\begin{table}[b!]
\center
\caption{Files in \basilhome\texttt{/<basilid>/} after processing of MRI-data (in addition to those listed in table \ref{mritomatout}). The function \bas{prepFEM} checks for the existence of these files, and runs the functions in column two when necessary (i.e.\ when files are missing). }\label{prepfemfiles}
\begin{tabulary}{\linewidth}{l l R}
\hline\noalign{\smallskip}
file in \basilhome\texttt{/<basilid>/}& written by & needed for \\
\noalign{\smallskip}\hline\noalign{\smallskip}
\texttt{contour\_skin\_preload.mat} & \bas{segmentMRI} & \bas{checkVsize}\\
\texttt{contour\_bone\_preload.mat} & \bas{segmentMRI} & \bas{checkVsize}\\
\texttt{contour\_skin\_loading.mat} & \bas{segmentMRI} & \bas{checkVsize}\\
\texttt{contour\_bone\_loading.mat} & \bas{segmentMRI} & \bas{checkVsize}\\
\texttt{contour\_bone\_postload.mat} & \bas{segmentMRI} & \bas{checkVsize}\\
\texttt{contour\_skin\_preload-ncc.mat} & \bas{checkVsize} & \bas{estIndDisp}, \bas{buildFEM}\\
\texttt{contour\_bone\_preload-ncc.mat} & \bas{checkVsize} & \bas{mapBone}, \bas{buildFEM}\\
\texttt{contour\_skin\_loading-ncc.mat} & \bas{checkVsize} & \bas{estIndDisp}\\
\texttt{contour\_bone\_loading-ncc.mat} & \bas{checkVsize} & \bas{mapBone}\\
\texttt{contour\_bone\_postload-ncc.mat} & \bas{checkVsize} & \bas{mapBone}\\
\texttt{Bone\_preload\_loading.txt} & \bas{mapBone} & \bas{buildFEM}\\
\texttt{Bone\_preload\_postload.txt} & \bas{mapBone} & post-processing\\
\texttt{Indenter\_tipNR.txt} & \bas{estCylPos} & \bas{estIndDisp}, \bas{buildFEM}\\
\texttt{Indenter\_StartEnd.txt} & \bas{indDisp} & \bas{buildFEM}\\
\noalign{\smallskip}\hline
\end{tabulary}
\end{table}
\section{Building the FE model}\label{buildmodel}
The FEM building process is described in detail in the next chapter. Briefly, we use the script \bas{buildFEM} to read the necessary model data from \basilhome\texttt{/<basilid>/} and to write an Abaqus python script \textsl{in the current working directory}\footnote{Note: \textsl{in the current working directory}, these files are \textsl{not} written to \basilhome\texttt{/<basilid>/}.}. With this python script, Abaqus builds (and optionally: runs) the FE model: geometry, material parameters, boundary conditions, contact, etc. To write the Abaqus model scripts for \texttt{<basilid> = 140611} and \texttt{<basilid> = 140613} call:
\begin{lstlisting}[numbers=none]
>> bas_buildFEM([140611, 140613], param);
\end{lstlisting}
where \texttt{param} is a structure with modelling options (see chapter \ref{buildFEM}).
The (main) output of \bas{buildFEM} is the python script \texttt{basil<basilid>\_job.py}, and the FEM can be build by calling Abaqus with
\begin{lstlisting}[numbers=none, language=bash]
mark@telab11:~$ abaqus cae noGUI=basil<basilid>_job.py
\end{lstlisting}
\section{Running the FE model}
\section{Post-processing of FE results}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment