[592feb]: / MATLAB_tool / MuscleParOptTool / private / sampleMuscleQuantities.m

Download this file

229 lines (195 with data), 10.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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
%-------------------------------------------------------------------------%
% 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, March 2013 %
% revised July 2014 (improved management of joints)%
% modified May 2015 (management of max resolution) %
% email: l.modenese@imperial.ac.uk %
% ----------------------------------------------------------------------- %
%
% Given as INPUT an OpenSim muscle OSModel, OSMuscle, a muscle variable and a nr
% of evaluation points this function returns as
% musOutput a vector of the muscle variable of interest
% obtained by sampling the ROM of the joint spanned by the muscle in
% N_EvalPoints evaluation points.
% For multidof joint the combinations of ROMs are considered.
% For multiarticular muscles the combination of ROM are considered.
% The script is totally general because based on generating strings of code
% correspondent to the encountered code. The strings are evaluated at the end.
%
% IMPORTANT 1
% The function can decrease the N_EvalPoints if there are too many dof
% involved (ASSUMPTION is that a better sampling will be vanified by the
% huge amount of data generated). This is an option that can be controlled
% by the user by deciding if to use it or not (setting limit_discr = 0/1)
% and, in case the sampling is limited, by setting a lower limit to the
% discretization.
%
% IMPORTANT 2
% Another check is done on the dofs: only INDEPENDENT coordinate are
% considered. This is fundamental for patellofemoral joint that both in
% LLLM and Arnold's model are constrained dof, dependent on the knee
% flexion angle. This function assumes to be used with Arnold's model.
% currentState is initialState;
%
% IMPORTANT 3
% At the purposes of the muscle optimizer it is important that here the
% model is initialize every time. So there are no risk of working with an
% old state (important for Schutte muscles for instance, where we observed
% that it was necessary to re-initialize the muscle after updating the
% muscle parameters).
function musOutput = sampleMuscleQuantities(osimModel,OSMuscle,muscleQuant, N_EvalPoints) %#ok<STOUT>
%======= SETTINGS ======
% limit (1) or not (0) the discretization of the joint space sampling
limit_discr = 0;
% minimum angular discretization
%min_increm_in_deg = 2.5;
min_increm_in_deg = 1;
%=======================
% initialize the model
currentState = osimModel.initSystem();
% getting the joint crossed by a muscle
muscleCrossedJointSet = getJointsSpannedByMuscle(osimModel, OSMuscle);
% index f+or effective dofs
n_dof = 1;
DOF_Index = [];
for n_joint = 1:size(muscleCrossedJointSet,2)
% current joint
curr_joint = muscleCrossedJointSet{n_joint};
% get CoordinateSet for the crossed joint
%curr_joint_CoordinateSet = osimModel.getJointSet().get(curr_joint).getCoordinateSet();
% Initial estimation of the nr of Dof of the CoordinateSet for that
% joint before checking for locked and constraint dofs.
%nDOF = osimModel.getJointSet().get(curr_joint).getCoordinateSet().getSize();
nDOF = osimModel.getJointSet().get(curr_joint).numCoordinates();
% skip welded joint and removes welded joint from muscleCrossedJointSet
if nDOF == 0;
continue;
end
% calculating effective dof for that joint
effect_DOF = nDOF;
for n_coord = 0:nDOF-1
% get coordinate
%curr_coord = curr_joint_CoordinateSet.get(n_coord);
curr_coord = osimModel.getJointSet().get(curr_joint).get_coordinates(n_coord);
curr_coord_name = char(curr_coord.getName());
% skip dof if locked
if curr_coord.getLocked(currentState)
continue;
end
% if coordinate is constrained then the independent coordinate and
% associated joint will be listed in the sampling "map"
if curr_coord.isConstrained(currentState) && ~curr_coord.getLocked(currentState)
constraint_coord_name = curr_coord_name;
% finding the independent coordinate
[ind_coord_name, ind_coord_joint_name] = getIndipCoordAndJoint(osimModel, constraint_coord_name); %#ok<NASGU>
% updating the coordinate name to be saved in the list
curr_coord_name = ind_coord_name;
effect_DOF = effect_DOF-1;
% ignoring constrained dof if they point to an independent
% coordinate that has already been stored
if sum(ismember(DOF_Index, osimModel.getCoordinateSet.getIndex(curr_coord_name)))>0
continue
end
% skip dof if independent coordinate locked (the coord
% correspondent to the name needs to be extracted)
if osimModel.getCoordinateSet.get(curr_coord_name).getLocked(currentState)
continue;
end
end
% NB: DOF_Index is used later in the string generated code.
% CRUCIAL: the index of dof now is model based ("global") and
% different from the joint based used until now.
DOF_Index(n_dof) = osimModel.getCoordinateSet.getIndex(curr_coord_name);
% necessary update/reload the curr_coord to avoid problems with
% dependent coordinates
curr_coord = osimModel.getCoordinateSet.get(DOF_Index(n_dof));
% Getting the values defining the range
jointRange(1) = curr_coord.getRangeMin();
jointRange(2) = curr_coord.getRangeMax();
% Storing range of motion conveniently
CoordinateBoundaries(n_dof) = {jointRange}; %#ok<NASGU>
% increments in the variables when sampling the mtl space.
% Increments are different for each dof and based on N_eval.
%Defining the increments
degIncrem(n_dof) = (jointRange(2)-jointRange(1))/(N_EvalPoints-1);
% limit or not the discretization of the joint space sampling
if limit_discr==1
% a limit to the increase can be set though
if degIncrem(n_dof)<(min_increm_in_deg/180*pi)
degIncrem(n_dof)=(min_increm_in_deg/180*pi); %#ok<*AGROW>
end
end
% updating index of list of dof
n_dof = n_dof+1;
end
end
% initializes the counter to save the results
iter = 1; %#ok<NASGU>
% assigns an initial and a final value variable for each dof X
% calling them setAngleStartDofX and setLimitDof respectively.
for n_instr = 1:size(DOF_Index,2);
% setting up the variables
eval(['setAngleStartDof',num2str(n_instr),' = CoordinateBoundaries{',num2str(n_instr),'}(1);'])
eval(['setLimitDof',num2str(n_instr),' = CoordinateBoundaries{',num2str(n_instr),'}(2);'])
end
% setting up for loops in order to explore all the possible combination of
% joint angles (looping on all the dofs of each joint for all the joint
% crossed by the muscle).
% The model pose is updated via: " coordToUpd.setValue(currentState,setAngleDof)"
% The right dof to update is chosen via: "coordToUpd = osimModel.getCoordinateSet.get(n_instr)"
stringToExcute1 = '';
for n_instr = 1:size(DOF_Index,2);
stringToExcute1 = [stringToExcute1,[' for setAngleDof',num2str(n_instr),'=setAngleStartDof',num2str(n_instr),':degIncrem(',num2str(n_instr),'):setLimitDof',num2str(n_instr),'; coordToUpd = osimModel.getCoordinateSet.get(DOF_Index(',num2str(n_instr),')); coordToUpd.setValue(currentState,setAngleDof',num2str(n_instr),');']]; %#ok<AGROW>
end
% calculating muscle length for the muscle
switch muscleQuant
case 'MTL'
stringToExcute2 = 'musOutput(iter) = OSMuscle.getGeometryPath.getLength(currentState);';
case 'LfibNorm'
stringToExcute2 = ['OSMuscle.setActivation(currentState,1.0);',...
' osimModel.equilibrateMuscles(currentState);',...
' musOutput(iter) = OSMuscle.getNormalizedFiberLength(currentState);'];
case 'Lten'
stringToExcute2 = ['OSMuscle.setActivation(currentState,1.0);',...
' osimModel.equilibrateMuscles(currentState);',...
' musOutput(iter) = OSMuscle.getTendonLength(currentState);'];
case 'Ffib'
stringToExcute2 = ['OSMuscle.setActivation(currentState,1.0);',...
' osimModel.equilibrateMuscles(currentState);',...
' musOutput(iter) = OSMuscle.getActiveFiberForce(currentState);'];
case 'all'
stringToExcute2 = [ 'OSMuscle.setActivation(currentState,1.0);',...
' osimModel.equilibrateMuscles(currentState);',...
'musOutput(iter,1) = OSMuscle.getGeometryPath.getLength(currentState);',...
' musOutput(iter,2) = OSMuscle.getNormalizedFiberLength(currentState);',...
' musOutput(iter,3) = OSMuscle.getTendonLength(currentState);',...
' musOutput(iter,4) = OSMuscle.getActiveFiberForce(currentState);',...
' musOutput(iter,5) = OSMuscle.getPennationAngle(currentState);'];
end
% updating iteration
stringToExcute3 =['iter = iter+1;',...
% 'angles.colheaders(iter-1) = {char(osimModel.getCoordinateSet.get(DOF_Index(',num2str(n_instr),')).getName)};'...
% 'angles.data(iter-1,1) = setAngleDof',num2str(n_instr),';'...
''];
% closing the loops started in stringToExcute1 with appropriate nr of end
stringToExcute4 = '';
for n_instr = 1:size(DOF_Index,2);
stringToExcute4 =[stringToExcute4,'end;']; %#ok<AGROW>
end
% assembling the code string
Code = [stringToExcute1,stringToExcute2,stringToExcute3,stringToExcute4];
% evaluate the code
eval(Code)
end