Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Example using the VSD database. #109

Open
wants to merge 31 commits into
base: VSD
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d8ca54c
add pat support
modenaxe Mar 5, 2021
52da3e7
add pat support
modenaxe Mar 5, 2021
7a30248
Merge branch 'master' of https://github.com/modenaxe/msk-STAPLE
modenaxe Mar 9, 2021
b9cffe6
comment
modenaxe May 24, 2021
fbd2ca8
Merge branch 'master' of https://github.com/modenaxe/msk-STAPLE
modenaxe Sep 17, 2021
cb61aa0
Added Example_VSDFullBodyBoneModels.m
Jun 18, 2022
5bb91d0
minor update
Jul 20, 2022
56dba5b
Cloning VSD database from git instead of hardcoded path.
Jul 20, 2022
8de766c
Fixed the bug in fitQuadriTalus.m by ensuring the correct order of th…
Nov 2, 2022
54b3554
reverted fitQuadriTalus.m
Nov 19, 2022
6a8a9fc
Fix of fitQuadriTalus.m by ensuring the correct order of the quadrila…
Nov 19, 2022
d467093
Merge pull request #111 from MCM-Fischer/master
renaultJB Nov 23, 2022
613b3de
Merge remote-tracking branch 'remotes/upstream/master' into VSD
Nov 23, 2022
bb17c33
Minor update of FittingFun/fitQuadriTalus.m and STAPLE_talus.m.
Nov 24, 2022
040fc88
Merge pull request #112 from MCM-Fischer/master
renaultJB Dec 1, 2022
b9bf51a
upd file names
May 31, 2023
0a303f0
Merge remote-tracking branch 'origin/master'
modenaxe Jun 5, 2023
387f420
Revert "Merge remote-tracking branch 'origin/master'"
modenaxe Jun 5, 2023
0d7ba08
Revert "Revert "Merge remote-tracking branch 'origin/master'""
modenaxe Jun 5, 2023
97f5b8a
fix misspell
modenaxe Jun 5, 2023
4027b2f
debug plots for pat groove
modenaxe Jun 5, 2023
fbe8dfa
add debug_plot
modenaxe Jun 5, 2023
d522374
fix git mess
modenaxe Jun 5, 2023
3700e71
rm unused
modenaxe Jun 5, 2023
272fb75
add missing toes geom
modenaxe Jun 20, 2023
2b2b53a
Update of Example_VSDFullBodyBoneModels.m
Nov 4, 2023
d6213b5
Bug fix in fitQuadriTalus.m
Nov 4, 2023
ea66f05
Merge branch 'master' of https://github.com/MCM-Fischer/msk-STAPLE in…
Nov 4, 2023
a4ab807
Update of Example_VSDFullBodyBoneModels.m
Nov 5, 2023
b5b91ab
Toes were missing in Example_VSDFullBodyBoneModels.m
Nov 5, 2023
b424633
Remove matGeom from path after execution of Example_VSDFullBodyBoneMo…
Nov 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@ tests/models_from_tests/
*.zip
/*_safe/
*ISSUE*/
# Cloned repositories from Example_VSDFullBodyBoneModels
/VSD
/matGeom

# openSim files
*.log
*.osim
# used for checking intermediate steps of modelling
*.xml

#vim files
# vim files
*.*~


223 changes: 223 additions & 0 deletions Example_VSDFullBodyBoneModels.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
%-------------------------------------------------------------------------%
% Copyright (c) 2022 MCM Fischer. %
% Author: MCM Fischer, 2022 %
% ----------------------------------------------------------------------- %
% This example demonstrates how to setup a STAPLE workflow to
% automatically generate a complete kinematic model of the lower
% extremities using the anatomical VSDFullBodyBoneModels datasets.
% ----------------------------------------------------------------------- %
clear; clc; close all

% STAPLE library
addpath(genpath('STAPLE'));

%% SETTINGS ------------------------------------------------------------- %
output_models_folder = 'opensim_models_examples';
% folder where the various datasets (and their geometries) are located.
datasets_folder = 'bone_datasets';

% format of input geometries
input_geom_format = 'tri';
% visualization geometry format (options: 'stl' or 'obj')
vis_geom_format = 'obj';
% body sides
sides = {'r', 'l'};
% choose the definition of the joint coordinate systems (see documentation)
joint_defs = 'Modenese2018';
% ----------------------------------------------------------------------- %

%% Download VSDFullBodyBoneModels
% Clone example data
if ~exist('VSD', 'dir')
try
!git clone https://github.com/MCM-Fischer/VSDFullBodyBoneModels VSD
rmdir('VSD/.git', 's')
catch
warning([newline 'Clone (or copy) the example data from: ' ...
'https://github.com/MCM-Fischer/VSDFullBodyBoneModels' newline 'to: ' ...
fileparts([mfilename('fullpath'), '.m']) '\VSD' ...
' and try again!' newline])
return
end
end

% Download matGeom
if ~exist('matGeom', 'dir')
try
!git clone https://github.com/mattools/matGeom matGeom
rmdir('matGeom/.git', 's')
catch
warning([newline 'Clone (or copy) the example data from: ' ...
'https://github.com/mattools/matGeom' newline 'to: ' ...
fileparts([mfilename('fullpath'), '.m']) '\matGeom' ...
' and try again!' newline])
return
end
end
addpath(genpath('matGeom'))

%% Convert VSD to STAPLE format
vsdSubjects = readtable(fullfile('VSD\MATLAB\res\', 'VSD_Subjects.xlsx'));
% Remove subjects with incomplete skeletal anatomy
vsdSubjects = vsdSubjects(cellfun(@(x) isempty(strfind(x,'cut off')), vsdSubjects.Comment),:); %#ok<STREMP>

% Select subjects to be processed
subs = 1; %1:size(vsdSubjects,1);

for n_sub = subs
load(fullfile('VSD', 'Bones', [vsdSubjects.ID{n_sub} '.mat']),'B','M')
subFolder = fullfile(datasets_folder, ['VSD_' vsdSubjects.ID{n_sub}] , input_geom_format);
if ~isfolder(subFolder)
mkdir(subFolder)
disp(['Created: ' datasets_folder '\' subFolder])
end
% Create 'pelvis_no_sacrum.mat'
trPath = fullfile(subFolder, 'pelvis_no_sacrum.mat');
if ~isfile(trPath)
TR = concatenateMeshes(B(ismember({B.name},'Hip_R')).mesh,B(ismember({B.name},'Hip_L')).mesh);
TR = triangulation(TR.faces, TR.vertices);
save(trPath,'TR')
end
% Create legs
for n_side = 1:length(sides)
% Create 'femur_*.mat'
trPath = fullfile(subFolder, ['femur_' sides{n_side}]);
if ~isfile(trPath)
TR = splitMesh(B(ismember({B.name},['Femur_' upper(sides{n_side})])).mesh,'maxBoundingBox');
TR = triangulation(TR.faces, TR.vertices);
save(trPath,'TR')
end
% Create 'tibia_*.mat'
trPath = fullfile(subFolder, ['tibia_' sides{n_side}]);
if ~isfile(trPath)
TR = concatenateMeshes(...
B(ismember({B.name},['Tibia_' upper(sides{n_side})])).mesh,...
B(ismember({B.name},['Fibula_' upper(sides{n_side})])).mesh);
TR = triangulation(TR.faces, TR.vertices);
save(trPath,'TR')
end
% Create 'talus_*.mat'
trPath = fullfile(subFolder, ['talus_' sides{n_side}]);
if ~isfile(trPath)
TR = splitMesh(B(ismember({B.name},['Talus_' upper(sides{n_side})])).mesh,'maxBoundingBox');
TR = triangulation(TR.faces, TR.vertices);
save(trPath,'TR')
end
% Create 'calcn_*.mat'
trPath = fullfile(subFolder, ['calcn_' sides{n_side}]);
if ~isfile(trPath)
TR = splitMesh(B(ismember({B.name},['Calcaneus_' upper(sides{n_side})])).mesh,'maxBoundingBox');
TR = concatenateMeshes(TR,...
B(ismember({B.name},['Tarsals_' upper(sides{n_side})])).mesh,...
B(ismember({B.name},['Metatarsals_' upper(sides{n_side})])).mesh);
TR = triangulation(TR.faces, TR.vertices);
save(trPath,'TR')
end
% Create 'toes_*.mat'
trPath = fullfile(subFolder, ['toes_' sides{n_side}]);
if ~isfile(trPath)
TR = B(ismember({B.name},['Phalanges_' upper(sides{n_side})])).mesh;
TR = triangulation(TR.faces, TR.vertices);
save(trPath,'TR')
end
end
end

%% STAPLE
% datasets that are processed
datasets = strcat('VSD_',vsdSubjects.ID');
% masses for models
subj_mass_set = vsdSubjects.Weight'; %kg

tic

% create model folder if required
if ~isfolder(output_models_folder); mkdir(output_models_folder); end

for n_d = subs

% current dataset being processed
cur_dataset = datasets{n_d};

% folder from which triangulations will be read
tri_folder = fullfile(datasets_folder, cur_dataset, input_geom_format);

% log printout
log_file = fullfile(output_models_folder, [cur_dataset,'_bilateral.log']);
logConsolePrintout('on', log_file);

for n_side = 1:2

% get current body side
[sign_side , cur_side] = bodySide2Sign(sides{n_side});

% cell array with the bone geometries that you would like to process
bones_list = {...
'pelvis_no_sacrum', ...
['femur_', cur_side],...
['tibia_', cur_side], ...
['talus_', cur_side],...
['calcn_', cur_side],...
['toes_', cur_side]};

% model and model file naming
cur_model_name = ['auto_',datasets{n_d},'_',upper(cur_side)];
model_file_name = [cur_model_name, '.osim'];

% create geometry set structure for all 3D bone geometries in the dataset
triGeom_set = createTriGeomSet(bones_list, tri_folder);

% create bone geometry folder for visualization
geometry_folder_name = [cur_model_name, '_Geometry'];
geometry_folder_path = fullfile(output_models_folder,geometry_folder_name);

% convert geometries in chosen format (30% of faces for faster visualization)
writeModelGeometriesFolder(triGeom_set, geometry_folder_path, vis_geom_format,0.3);

% initialize OpenSim model
osimModel = initializeOpenSimModel(cur_model_name);

% create bodies
osimModel = addBodiesFromTriGeomBoneSet(osimModel, triGeom_set, geometry_folder_name, vis_geom_format);

% process bone geometries (compute joint parameters and identify markers)
[JCS, BL, CS] = processTriGeomBoneSet(triGeom_set, cur_side, [],'Kai2014');

% create joints
createOpenSimModelJoints(osimModel, JCS, joint_defs);

% update mass properties to those estimated using a scale version of
% gait2392 with COM based on Winters's book.
osimModel = assignMassPropsToSegments(osimModel, JCS, subj_mass_set(n_d));

% add markers to the bones
addBoneLandmarksAsMarkers(osimModel, BL);

% finalize connections
osimModel.finalizeConnections();

% print
osim_model_file = fullfile(output_models_folder, model_file_name);
osimModel.print(osim_model_file);

% inform the user about time employed to create the model
disp('-------------------------')
disp(['Model generated in ', sprintf('%.1f', toc), ' s']);
disp(['Saved as ', osim_model_file,'.']);
disp(['Model geometries saved in folder: ', geometry_folder_path,'.'])
disp('-------------------------')
clear triGeom_set JCS BL CS

% store model file (with path) for merging
osim_model_set(n_side) = {osim_model_file}; %#ok<SAGROW>
end
% merge the two sides
merged_model_file = fullfile(output_models_folder,[cur_dataset,'_bilateral.osim']);
mergeOpenSimModels(osim_model_set{1}, osim_model_set{2}, merged_model_file);

% stop logger
logConsolePrintout('off');
end
% remove paths
rmpath(genpath('matGeom'));
rmpath(genpath('STAPLE'));
Loading