Skip to main content

processMotionLabData.m


% This function is part of the NMSM Pipeline, see file for full license.
%
% This function takes the necessary inputs and produces the results of IK,
% ID, and MuscleAnalysis so the values can be used as inputs for
% MuscleTendonPersonalization.
%
% (struct, struct) -> (None)
% Prepares raw data for MuscleTendonPersonalization


function processMotionLabData(inputs, params)
import org.opensim.modeling.Storage
ikResultsDir = 'IKData';
idResultsDir = 'IDData';
maResultsDir = 'MAData';
emgResultsDir = 'EMGData';
verifyInputs(inputs);
verifyParams(params);
makeDirectoryStructure(inputs.resultsDir, ikResultsDir, idResultsDir, ...
maResultsDir, emgResultsDir);
preprocessInverseKinematicsData(inputs, params, ikResultsDir)
preprocessInverseDynamicsData(inputs, params, idResultsDir)
preprocessMuscleAnalysisData(inputs, params, maResultsDir)
preprocessEmgData(inputs, params, emgResultsDir)

filesToSection = makeFilesToSection(inputs, ikResultsDir, idResultsDir, ...
maResultsDir, emgResultsDir);
numBufferRows = calcNumPaddingFrames(inputs.timePairs, params);
paddedTimePairs = addBufferToTimePairs(inputs.timePairs, numBufferRows, ...
params);
sectionDataFiles(filesToSection, paddedTimePairs, ...
2 * numBufferRows + valueOrAlternate(params, 'rowsPerTrial', 101), ...
inputs.prefix);
for i=1:length(filesToSection)
delete(filesToSection(i));
end
moveMAFilesToSeparateDirectories(inputs, maResultsDir, paddedTimePairs)
end


function verifyInputs(inputs)

end

function verifyParams(params)

end

function makeDirectoryStructure(resultsDir, ikDir, idDir, maDir, emgDir)
mkdir(resultsDir)
mkdir(fullfile(resultsDir, ikDir))
mkdir(fullfile(resultsDir, idDir))
mkdir(fullfile(resultsDir, maDir))
mkdir(fullfile(resultsDir, emgDir))
end

function preprocessInverseKinematicsData(inputs, params, ikResultsDir)
import org.opensim.modeling.Storage
[ikColumnLabels, ikTime, ikData] = parseMotToComponents( ...
Model(inputs.model), Storage(inputs.ikResultsFileName));
writeToSto(ikColumnLabels, ikTime, ikData', fullfile(inputs.resultsDir, ...
ikResultsDir, inputs.prefix + ".sto"))
end

function preprocessInverseDynamicsData(inputs, params, idResultsDir)
copyfile(inputs.idResultsFileName, fullfile(inputs.resultsDir, ...
idResultsDir, inputs.prefix + ".sto"))
end

function preprocessMuscleAnalysisData(inputs, params, maResultsDir)
moveMuscleAnalysis(fullfile(inputs.resultsDir, maResultsDir), ...
inputs.maResultsDir, inputs.coordinateNames, inputs.prefix);
end

function preprocessEmgData(inputs, params, emgResultsDir)
import org.opensim.modeling.Storage
if(getFieldByName(params, 'processEmg'))
[emgColumnLabels, emgTime, emgData] = parseMotToComponents( ...
Model(inputs.model), Storage(inputs.emgFileName));
newEmgData = processEmg(emgData, emgTime, params);
writeToSto(emgColumnLabels, emgTime, newEmgData, fullfile( ...
fullfile(inputs.resultsDir, emgResultsDir), strcat(inputs.prefix, ...
"sto")));
else
copyfile(inputs.emgFileName, fullfile(inputs.resultsDir, ...
emgResultsDir, inputs.prefix + ".sto"))
end
end

function filesToSection= makeFilesToSection(inputs, ikResultsDir, ...
idResultsDir, maResultsDir, emgResultsDir)
filesToSection = [ ...
fullfile(inputs.resultsDir, maResultsDir, inputs.prefix + ...
"_Length.sto"), ...
fullfile(inputs.resultsDir, maResultsDir, inputs.prefix + ...
"_Velocity.sto"), ...
fullfile(inputs.resultsDir, emgResultsDir, inputs.prefix + ".sto"), ...
fullfile(inputs.resultsDir, ikResultsDir, inputs.prefix + ".sto"), ...
fullfile(inputs.resultsDir, idResultsDir, inputs.prefix + ".sto")
];
for i=1:length(inputs.coordinateNames)
filesToSection(end+1) = fullfile(inputs.resultsDir, maResultsDir, ...
inputs.prefix + "_MomentArm_" + inputs.coordinateNames(i) + ".sto");
end
end

function moveMuscleAnalysis(resultsDir, inputDir, coordinates, prefix)
files = dir(inputDir);
for i=1:length(coordinates)
found = false;
for j=1:length(files)
if(~files(j).isdir && contains(files(j).name, "_MomentArm_" ...
+ coordinates(i)))
copyfile(fullfile(inputDir, files(j).name), ...
fullfile(resultsDir, prefix + "_MomentArm_" + ...
coordinates(i) + ".sto"))
found = true;
break;
end
end
if(~found)
throwCantFindMAFileException("_MomentArm_" + coordinates(i));
end
end
% now move length file
found = false;
for k=1:length(files)
if(~files(k).isdir && contains(files(k).name, "MuscleAnalysis_Length"))
copyfile(fullfile(inputDir, files(k).name), ...
fullfile(resultsDir, prefix + "_Length.sto"))
found = true;
break;
end
end
if(~found) throwCantFindMAFileException("_MuscleAnalysis_Length.sto"); end

createMuscleTendonVelocity(fullfile(resultsDir, prefix + ...
"_Length.sto"), fullfile(resultsDir, prefix + "_Velocity.sto"), ...
muscleTendonVelocityCutoffFrequency);
end


function throwCantFindMAFileException(fileName)
throw(MException('', "Cannot find Muscle Analysis file for " + fileName));
end

function numFramesBuffer = calcNumPaddingFrames(timePairs, params)
normalizedNumDataPoints = valueOrAlternate(params, 'rowsPerTrial', 101);
shortestTrialLength = timePairs(1,2) - timePairs(1,1);
for i=2:size(timePairs, 1)
if(timePairs(i,2) - timePairs(i,1) < shortestTrialLength)
shortestTrialLength = timePairs(i,2) - timePairs(i,1);
end
end
timePerFrame = shortestTrialLength / (normalizedNumDataPoints-1);
numFramesBuffer = ceil(0.2 / timePerFrame);
end

function newTimePairs = addBufferToTimePairs(timePairs, numBufferRows, ...
params)
rowsPerTrial = valueOrAlternate(params, 'rowsPerTrial', 101);
for i=1:size(timePairs, 1)
trialTime = timePairs(i,2) - timePairs(i,1);
timePairs(i,1) = timePairs(i,1) - (numBufferRows / ...
(rowsPerTrial - 1) * trialTime);
timePairs(i,2) = timePairs(i,2) + (numBufferRows / ...
(rowsPerTrial - 1) * trialTime);
end
newTimePairs = timePairs;
end

function moveMAFilesToSeparateDirectories(inputs, maResultsDir, ...
paddedTimePairs)
for i=1:length(paddedTimePairs)
mkdir(fullfile(inputs.resultsDir, maResultsDir, inputs.prefix + "_" ...
+ i));
files = dir(fullfile(inputs.resultsDir, maResultsDir));
for j=1:length(files)
if(~files(j).isdir && contains(files(j).name, inputs.prefix + ...
"_" + num2str(i)))
movefile(fullfile(inputs.resultsDir, maResultsDir, ...
files(j).name), fullfile(inputs.resultsDir, ...
maResultsDir, inputs.prefix + "_" + i));
end
end
end
end