Download this file

179 lines (150 with data), 8.9 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
%-------------------------------------------------------------------------%
% Copyright (c) 2019 Modenese L., Ceseracciu, E., Reggiani M., Lloyd, D.G.%
% %
% Licensed under the Apache License, Version 2.0 (the "License"); %
% you may not use this file except in compliance with the License. %
% You may obtain a copy of the License at %
% http://www.apache.org/licenses/LICENSE-2.0. %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or %
% implied. See the License for the specific language governing %
% permissions and limitations under the License. %
% %
% Author: Luca Modenese, July 2014 %
% revised May 2015 (v2) %
% email: l.modenese@sheffield.ac.uk %
% ----------------------------------------------------------------------- %
%
% Script to evaluate the results of the muscle optimization.
% The script calculated the normalized fiber lengths for the model template
% and for the scaled model with optimized muscle parameters at N_error
% points and computes an RMSE (assuming that the optimization is aiming
% to "track" the normalized FL curve of the muscles) in the reference model
% and the mean and maximum error in the tracking (ranges across muscles).
% N_eval identifies the optimized model, obtained by sampling each
% degree of freedom's range in N_Eval points.
%
function Results_MusMapMetrics = assessMuscleMapping(osimModel_ref,...
osimModel_opt,...
N_eval,...
N_error)
% importing OpenSim libraries
import org.opensim.modeling.*
% Extracting muscle sets from the two models
muscles_ref = osimModel_ref.getMuscles();
muscles_opt = osimModel_opt.getMuscles();
% %initializing the models
% initialState = Template_osimModel.initSystem();
% initialState_Opt = Opt_osimModel.initSystem();
%=============== FILE WHERE TO STORE THE METRICS ================
% results file identifier
res_file_id_exp = ['_N',num2str(N_eval)];
% name of the result file
res_mat_file_name = ['Results_MusMapMetrics',res_file_id_exp,'_NError',num2str(N_error)];
% if the file exists it will ask if to re-calculate or just load the file
if exist([res_mat_file_name,'.mat'], 'file')==2
% ask the user
pref = input([res_mat_file_name, ' exists. Do you want to re-evaluate? [y/n].'], 's');
switch pref
case 'n'
display('Loading existing file.')
load([res_mat_file_name,'.mat']);
return
case 'y'
display('Re-evaluating mapping results');
end
end
for n_mus = 0:muscles_ref.getSize()-1
% current muscle name
curr_mus_name = muscles_ref.get(n_mus).getName;
display(['Processing ',char(curr_mus_name)])
% Extracting the current muscle from the two models
curr_muscle_ref = muscles_ref.get(curr_mus_name);
curr_muscle_opt = muscles_opt.get(curr_mus_name);
%======= NORMALIZED FIBER LENGTHS CALCULATED AT N_Error POINTS ========
% Normalized fiber lengths from the reference model at N_Error points
% per dof
Lm_Norm_ref = sampleMuscleQuantities(osimModel_ref,curr_muscle_ref,'LfibNorm', N_error);
% Normalized fiber lengths from the optimized model at N_Error points
% per dof
Lm_Norm_opt = sampleMuscleQuantities(osimModel_opt,curr_muscle_opt,'LfibNorm', N_error);
%========= CHECK FOR NaN ==============
% checks on NaN on the results
if isnan(Lm_Norm_ref)
warndlg(['NaN detected for muscle ',char(curr_mus_name),' in the template model.']);
end
if isnan(Lm_Norm_opt)
warndlg(['NaN detected for muscle ',char(curr_mus_name),' in optimized model.']);
end
%========= CHECK FOR UNREALISTIC FIBER LENGTHS ==============
% Check on the results of the sampling: if the reference model sampling gave some
% unrealistic fiber lengths, this is where this should be corrected
% boundaries for normalized fiber lengths
%======= FIBER LENGTHS THAT MAKE PENNATION ANGLE >= 90 deg =========
% calculating minimum fiber length before having pennation 90 deg
% acos(0.1) = 1.47 red = 84 degrees, chosen as in OpenSim
limitPenAngle = acos(0.1);
% this is the minimum length the fiber can be for geometrical reasons.
PenAngleOpt = curr_muscle_ref.getPennationAngleAtOptimalFiberLength();
LfibNorm_min_templ = sin(PenAngleOpt)/sin(limitPenAngle);
%======= NORMALIZED FIBER LENGTHS < 0.5 =========
% LfibNorm as calculated above can be shorter than the minimum length
% at which the fiber can generate force (taken to be 0.5 Zajac 1989)
if (LfibNorm_min_templ<0.5)==1
LfibNorm_min_templ = 0.5;
end
% indices of points that are ok according to previous criteria
ok_point_ind = find(Lm_Norm_ref>LfibNorm_min_templ);
% checking the muscle configuration that do not respect the condition.
Lm_Norm_ref = Lm_Norm_ref(ok_point_ind);
% checking the muscle configuration that do not respect the condition.
Lm_Norm_opt = Lm_Norm_opt(ok_point_ind);
%======= NULL NORMALIZED FIBER LENGTHS ===========
% Muscle normalized length cannot be zero either
if min(Lm_Norm_ref)==0
menu(['Zero Lnorm for muscle ',char(curr_mus_name),' in template model. Removing points with zero lengths.'],'OK');
ok_points = (Lm_Norm_ref~=0);
Lm_Norm_ref = Lm_Norm_ref(ok_points);
Lm_Norm_opt = Lm_Norm_opt(ok_points);
end
%============== CALCULATING THE METRICS ================
% difference between the two normalized fiber length vectors evaluated
% at N_error
Diff_Lfnorm = Lm_Norm_ref-Lm_Norm_opt;
% structure of results
Results_MusMapMetrics.colheaders{n_mus+1} = char(curr_muscle_ref.getName);
Results_MusMapMetrics.RMSE(n_mus+1) = sqrt(sum(Diff_Lfnorm.^2.0)/length(Lm_Norm_ref));
Results_MusMapMetrics.MaxPercError(n_mus+1) = max(abs(Diff_Lfnorm)./Lm_Norm_ref)*100;
Results_MusMapMetrics.MinPercError(n_mus+1) = min(abs(Diff_Lfnorm)./Lm_Norm_ref)*100;
Results_MusMapMetrics.MeanPercError(n_mus+1) = mean(abs(Diff_Lfnorm)./Lm_Norm_ref,2)*100;
Results_MusMapMetrics.StandDevPercError(n_mus+1)= std(abs(Diff_Lfnorm)./Lm_Norm_ref,0,2)*100;
[rho,P_val] = corr(Lm_Norm_ref', Lm_Norm_opt');
Results_MusMapMetrics.corrCoeff(n_mus+1,1:2) = [rho,P_val];
% clearing variables to avoid issue for different sampling
clear Lm_Norm_opt Lm_Norm_ref
end
% Computing min and max RMSE
[RMSE_max, Ind_max] = max(Results_MusMapMetrics.RMSE);
[RMSE_min, Ind_min] = min(Results_MusMapMetrics.RMSE);
Results_MusMapMetrics.RMSE_range(1) = RMSE_min;
Results_MusMapMetrics.RMSE_range(2) = RMSE_max;
Results_MusMapMetrics.RMSE_range_mus = {Results_MusMapMetrics.colheaders{Ind_min}, Results_MusMapMetrics.colheaders{Ind_max}};
% Computing min and max MeanPercError
[MeanPercError_max, Ind_max] = max(Results_MusMapMetrics.MeanPercError);
[MeanPercError_min, Ind_min] = min(Results_MusMapMetrics.MeanPercError);
Results_MusMapMetrics.MeanPercError_range(1) = MeanPercError_min;
Results_MusMapMetrics.MeanPercError_range(2) = MeanPercError_max;
Results_MusMapMetrics.MeanPercError_range_mus = {Results_MusMapMetrics.colheaders{Ind_min}, Results_MusMapMetrics.colheaders{Ind_max}};
% Computing max and min variations for MaxPercError
[MaxPercError_max, Ind_max] = max(Results_MusMapMetrics.MaxPercError);
[MaxPercError_min, Ind_min] = min(Results_MusMapMetrics.MaxPercError);
Results_MusMapMetrics.MaxPercError_range(1) = MaxPercError_min;
Results_MusMapMetrics.MaxPercError_range(2) = MaxPercError_max;
Results_MusMapMetrics.MaxPercError_range_mus = {Results_MusMapMetrics.colheaders{Ind_min}, Results_MusMapMetrics.colheaders{Ind_max}};
% Extracting max and min corr coeff and p values
Results_MusMapMetrics.rho_pval_range = [min(Results_MusMapMetrics.corrCoeff),max(Results_MusMapMetrics.corrCoeff)];
% save structures with results
save(res_mat_file_name,'Results_MusMapMetrics');
end