diff --git a/ShoulderCase/@Humerus/Humerus.m b/ShoulderCase/@Humerus/Humerus.m index fd807cc..a9aab86 100644 --- a/ShoulderCase/@Humerus/Humerus.m +++ b/ShoulderCase/@Humerus/Humerus.m @@ -1,102 +1,103 @@ classdef Humerus < handle %HUMERUS Properties and methods associated to the humerus % Detailed explanation goes here % Author: Alexandre Terrier, EPFL-LBO % Creation date: 2018-07-01 % Revision date: 2019-06-29 % % TO DO: % Local coordinate system properties landmarks % 5 3D points + insertions center % Center of the humeral head (sphere fit on 5 points radius % Radius of the humeral head (sphere fit on 5 points jointRadius % Radius of cuvature of the articular surface (todo) SHSAngle % Scapulo-humeral subluxation angle SHSPA % Scapulo-humeral subluxation angle in the postero-anterior direction (posterior is negative, as for glenoid version) SHSIS % Scapulo-humeral subluxation angle in the infero-superior direction SHSAmpl % Scapulo-humeral subluxation (center ofset / radius) SHSOrient % Scapulo-humral subluxation orientation (0 degree is posterior) GHSAmpl % Gleno-humeral subluxation (center ofset / radius) GHSOrient % Gleno-humral subluxation orientation (0 degree is posterior) subluxationIndex3D shoulder end methods (Access = ?Shoulder) % Only Shoulder is allowed to construct Humerus function obj = Humerus(shoulder) %HUMERUS Construct an instance of this class % Detailed explanation goes here obj.landmarks = []; obj.center = []; obj.radius = []; obj.jointRadius = []; obj.SHSAngle = []; obj.SHSPA = []; obj.SHSIS = []; obj.SHSAmpl = []; obj.SHSOrient = []; obj.GHSAmpl = []; obj.GHSOrient = []; obj.shoulder = shoulder; end end methods function output = loadData(obj) % Call methods that can be run after the ShoulderCase object has % been instanciated. SCase = obj.shoulder.SCase; if exist(... fullfile(SCase.dataSlicerPath, "HH_landmarks_"+obj.shoulder.side+".mrk.json"),... "file") success = Logger.timeLogExecution(... "Humerus load landmarks (slicer): ",... @(obj) obj.loadSlicerLandmarks, obj); elseif not(isempty(dir(fullfile(SCase.dataAmiraPath, "*HH*.landmarksAscii")))) success = Logger.timeLogExecution(... "Humerus load landmarks (slicer): ",... @(obj) obj.loadSlicerLandmarks, obj); else success = Logger.timeLogExecution(... "Humerus load landmarks: ",... @(message) error(message), "No landmarks file found"); end output = success; end function output = morphology(obj) % Call methods that can be run after loadData() methods has been run % by all ShoulderCase objects. success = Logger.timeLogExecution(... "Humerus center and radius: ",... @(obj) obj.measureCenterAndRadius, obj); output = success; end function output = measureFirst(obj) % Call methods that can be run after morphology() methods has been run % by all ShoulderCase objects. success = Logger.timeLogExecution(... "Humerus scapulo-humeral subluxation: ",... @(obj) obj.measureScapuloHumeralSubluxation, obj); output = success; end function output = measureSecond(obj) % Call methods that can be run after measureFirst() methods has been run % by all ShoulderCase objects. success = Logger.timeLogExecution(... "Humerus gleno-humeral subluxation: ",... @(obj) obj.measureGlenoHumeralSubluxation, obj); success = success & Logger.timeLogExecution(... "Humerus 3D subluxation index: ",... @(obj) obj.measureSubluxationIndex3D, obj); output = success; end end end diff --git a/ShoulderCase/@Humerus/loadSlicerLandmarks.m b/ShoulderCase/@Humerus/loadSlicerLandmarks.m index 5b0fea8..d131c74 100644 --- a/ShoulderCase/@Humerus/loadSlicerLandmarks.m +++ b/ShoulderCase/@Humerus/loadSlicerLandmarks.m @@ -1,12 +1,23 @@ function output = loadSlicerLandmarks(obj) try landmarksFilename = fullfile(... obj.shoulder.SCase.dataSlicerPath,... "HH_landmarks_" + obj.shoulder.side + ".mrk.json"); - fileData = jsondecode(fileread(landmarksFilename)); - obj.landmarks = [fileData.markups.controlPoints.position]'; + landmarks = jsondecode(fileread(landmarksFilename)).markups.controlPoints; + obj.landmarks = [landmarks.position]'; + loadInsertions(obj, landmarks); output = 1; catch output = 0; end +end + +function loadInsertions(obj, landmarks) + for i = 1:size(landmarks, 1) + label = string(landmarks(i).label); + if label.contains("insertion_") + muscleName = label.extractAfter("insertion_"); + obj.insertions.(muscleName) = landmarks(i).position'; + end + end end \ No newline at end of file diff --git a/ShoulderCase/@Muscle/getFullName.m b/ShoulderCase/@Muscle/getFullName.m new file mode 100644 index 0000000..f6cf59c --- /dev/null +++ b/ShoulderCase/@Muscle/getFullName.m @@ -0,0 +1,13 @@ +function output = getFullName(obj) + switch obj.name + case "SC" + output = "subscapularis"; + case "SS" + output = "supraspinatus"; + case "IS" + output = "infraspinatus"; + case "TM" + output = "teres_minor"; + end +end + diff --git a/ShoulderCase/@Muscle/measureHumerusContactPoint.m b/ShoulderCase/@Muscle/measureHumerusContactPoint.m index 4fc2b38..1e70895 100644 --- a/ShoulderCase/@Muscle/measureHumerusContactPoint.m +++ b/ShoulderCase/@Muscle/measureHumerusContactPoint.m @@ -1,19 +1,23 @@ function measureHumerusContactPoint(obj) humerus = obj.container.shoulder.humerus; humeralHeadContactPointFinder = SphereContactPoint(... Sphere(humerus.center, humerus.radius)); - % muscles humeral head insertion is estimated to be the most lateral point of - % the humeral head fitted sphere - MLAxis = obj.container.shoulder.scapula.coordSys.ML; - muscleInsertion = humerus.center + humerus.radius * MLAxis; + % if not segmented, muscles humeral head insertion is estimated to be the most + % lateral point of the humeral head fitted sphere + if ismember(obj.getFullName(), string(fields(humerus.insertions))) + muscleInsertion = humerus.insertions.(obj.getFullName()); + else + MLAxis = obj.container.shoulder.scapula.coordSys.ML; + muscleInsertion = humerus.center + humerus.radius * MLAxis; + end humeralHeadContactPointFinder.setAnchorPoint(muscleInsertion); obj.forceApplicationPoint = []; % find one force application point for each subdivision's centroid for i = 1:size(obj.centroid, 1) humeralHeadContactPointFinder.setPolarPoint(obj.centroid(i,:)); obj.forceApplicationPoint = [obj.forceApplicationPoint... ; humeralHeadContactPointFinder.getContactPoint()]; end end \ No newline at end of file