diff --git a/ShoulderCase/@ShoulderCase/plot.m b/ShoulderCase/@ShoulderCase/plot.m index d2a8078..8c3f9fd 100644 --- a/ShoulderCase/@ShoulderCase/plot.m +++ b/ShoulderCase/@ShoulderCase/plot.m @@ -1,3 +1,3 @@ function output = plot(obj,varargin) - output = ShoulderCasePlotter(obj); + output = ShoulderCasePlotter(obj, varargin{:}); end \ No newline at end of file diff --git a/ShoulderCase/@ShoulderCasePlotter/ShoulderCasePlotter.m b/ShoulderCase/@ShoulderCasePlotter/ShoulderCasePlotter.m index 0f3e615..e4c231c 100644 --- a/ShoulderCase/@ShoulderCasePlotter/ShoulderCasePlotter.m +++ b/ShoulderCase/@ShoulderCasePlotter/ShoulderCasePlotter.m @@ -1,61 +1,65 @@ classdef ShoulderCasePlotter < handle % Create a figure with ShoulderCase's plots % and buttons to toggle the data visualisation. % % Used by the ShoulderCase.plot() method. properties (Access = private) SCase + shoulderSide = "right" fig axesHandle axesLink axesCamera lightHandle plotHandle buttonHandle options = {'landmarks',... 'scapula surface',... 'glenoid surface',... 'coordinate system',... 'centered coordinate system',... 'rotator cuff',... 'difference'}; end methods (Access = ?ShoulderCase) - function obj = ShoulderCasePlotter(SCase) + function obj = ShoulderCasePlotter(SCase, varargin) obj.SCase = SCase; + if nargin > 1 + obj.shoulderSide = varargin{1}; + end obj.fig = figure('Name',SCase.id,... 'NumberTitle','off',... 'units','normalized',... 'outerposition',[0 0 1 1]); obj.axesHandle = containers.Map; obj.plotHandle = {}; obj.buttonHandle = {}; obj.initializeAxes(); obj.configCamera(); obj.plot(); obj.linkAxes(); obj.initializeButton(); axes(obj.axesHandle('scapula')); end end methods (Access = private) initializeAxes(obj); initializeButton(obj); plot(obj); configCamera(obj); linkAxes(obj); end end \ No newline at end of file diff --git a/ShoulderCase/@ShoulderCasePlotter/configCamera.m b/ShoulderCase/@ShoulderCasePlotter/configCamera.m index 8b79f9b..3b4aa44 100644 --- a/ShoulderCase/@ShoulderCasePlotter/configCamera.m +++ b/ShoulderCase/@ShoulderCasePlotter/configCamera.m @@ -1,35 +1,35 @@ function configCamera(obj) try - view(obj.axesHandle('scapula'),obj.SCase.shoulderManual.scapula.coordSys.ML); + view(obj.axesHandle('scapula'),obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.coordSys.ML); catch - view(obj.axesHandle('scapula'),obj.SCase.shoulderAuto.scapula.coordSys.ML); + view(obj.axesHandle('scapula'),obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.ML); end set(obj.axesHandle('scapula'),'CameraViewAngle',... 0.7*get(obj.axesHandle('scapula'),'CameraViewAngle')); try - set(obj.axesHandle('scapula'),'CameraUpVector',obj.SCase.shoulderManual.scapula.coordSys.IS); + set(obj.axesHandle('scapula'),'CameraUpVector',obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.coordSys.IS); catch - set(obj.axesHandle('scapula'),'CameraUpVector',obj.SCase.shoulderAuto.scapula.coordSys.IS); + set(obj.axesHandle('scapula'),'CameraUpVector',obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.IS); end set(obj.axesHandle('centered coordinate system'),'CameraViewAngle',... 0.6*get(obj.axesHandle('centered coordinate system'),'CameraViewAngle')); set(obj.axesHandle('centered coordinate system'),'CameraTarget',[0 0 0]); cameratoolbar('SetMode','orbit'); cameratoolbar('SetCoordSys','none'); axes(obj.axesHandle('scapula')); - if not(obj.SCase.shoulderAuto.scapula.coordSys.isEmpty) - coordSys = obj.SCase.shoulderAuto.scapula.coordSys; - elseif not(obj.SCase.shoulderManual.scapula.coordSys.isEmpty) - coordSys = obj.SCase.shoulderManual.scapula.coordSys; + if not(obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.isEmpty) + coordSys = obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys; + elseif not(obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.coordSys.isEmpty) + coordSys = obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.coordSys; else return; end obj.lightHandle(1) = light('Position',coordSys.origin + coordSys.PA*200 - coordSys.IS*100 - coordSys.ML*100); obj.lightHandle(2) = light('Position',coordSys.origin - coordSys.PA*200 - coordSys.IS*100 - coordSys.ML*100); obj.lightHandle(3) = light('Position',coordSys.origin + coordSys.IS*200); obj.lightHandle(4) = light('Position',coordSys.origin + coordSys.ML*200); end \ No newline at end of file diff --git a/ShoulderCase/@ShoulderCasePlotter/initializeButton.m b/ShoulderCase/@ShoulderCasePlotter/initializeButton.m index 5e167f3..af3b452 100644 --- a/ShoulderCase/@ShoulderCasePlotter/initializeButton.m +++ b/ShoulderCase/@ShoulderCasePlotter/initializeButton.m @@ -1,111 +1,111 @@ function initializeButton(obj) autoPanel = uipanel(obj.fig,... 'Title','Auto (in blue)',... 'units','pixels',... 'Position',[10 340 190 170]); for i = 1:length(obj.options)-1 try obj.buttonHandle.auto(i) = uicontrol(autoPanel,... 'Style','checkbox',... 'Value',1,... 'String',obj.options{i},... 'position',[10,150-i*20,150,20],... 'Callback',{@setDataVisibility,obj.plotHandle.auto(obj.options{i})}); end end obj.buttonHandle.auto(i+1) = uicontrol(autoPanel,... 'Style','pushbutton',... 'String','check/uncheck all other buttons',... 'position',[10,150-(i+1)*20,170,20],... 'Callback',{@checkUncheckAllButtons,obj.buttonHandle.auto,obj.plotHandle.auto}); manualPanel = uipanel(obj.fig,... 'Title','Manual (in red)',... 'units','pixels',... 'Position',[10 160 190 170]); for i = 1:length(obj.options)-1 try obj.buttonHandle.manual(i) = uicontrol(manualPanel,... 'Style','checkbox',... 'Value',1,... 'String',obj.options{i},... 'position',[10,150-i*20,150,20],... 'Callback',{@setDataVisibility,obj.plotHandle.manual(obj.options{i})}); end end obj.buttonHandle.manual(i+1) = uicontrol(manualPanel,... 'Style','pushbutton',... 'String','check/uncheck all other buttons',... 'position',[10,150-(i+1)*20,170,20],... 'Callback',{@checkUncheckAllButtons,obj.buttonHandle.manual,obj.plotHandle.manual}); try obj.buttonHandle.difference = uicontrol(obj.fig,... 'Style','checkbox',... 'Value',1,... 'String','auto/manual difference',... 'position',[20,130,150,20],... 'Callback',{@setDataVisibility,obj.plotHandle.difference('difference')}); end cameraPanel = uipanel(obj.fig,... 'Title','Camera',... 'units','pixels',... 'Position',[10 60 220 60]); obj.buttonHandle.camera(1) = uicontrol(cameraPanel,... 'Style','pushbutton',... 'String','ML view',... 'position',[10,10,60,30],... 'Callback',{@setCameraView,obj.axesHandle,... - obj.SCase.shoulderAuto.scapula.coordSys.ML,... - obj.SCase.shoulderAuto.scapula.coordSys.IS}); + obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.ML,... + obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.IS}); obj.buttonHandle.camera(2) = uicontrol(cameraPanel,... 'Style','pushbutton',... 'String','IS view',... 'position',[80,10,60,30],... 'Callback',{@setCameraView,obj.axesHandle,... - obj.SCase.shoulderAuto.scapula.coordSys.IS,... - -obj.SCase.shoulderAuto.scapula.coordSys.ML}); + obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.IS,... + -obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.ML}); obj.buttonHandle.camera(3) = uicontrol(cameraPanel,... 'Style','pushbutton',... 'String','PA view',... 'position',[150,10,60,30],... 'Callback',{@setCameraView,obj.axesHandle,... - obj.SCase.shoulderAuto.scapula.coordSys.PA,... - obj.SCase.shoulderAuto.scapula.coordSys.IS}); + obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.PA,... + obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.IS}); end function setDataVisibility(button,event,dataHandle) for i = 1:length(dataHandle) set(dataHandle(i),'Visible',logical(button.Value)); end end function checkUncheckAllButtons(button,event,buttonHandle,plotHandle) buttonState = logical([buttonHandle(:).Value]); if all(buttonState) newValue = false; else newValue = true; end for i = 1:length(buttonHandle) set(buttonHandle(i),'Value',newValue); setDataVisibility(buttonHandle(i),[],plotHandle(buttonHandle(i).String)); end end function setCameraView(button,event,axesHandle,viewAxis,upAxis) axes(axesHandle('scapula')); target = get(gca,'CameraTarget'); view(viewAxis); set(axesHandle('scapula'),'CameraUpVector',upAxis); set(axesHandle('scapula'),'CameraTarget',target); end diff --git a/ShoulderCase/@ShoulderCasePlotter/plot.m b/ShoulderCase/@ShoulderCasePlotter/plot.m index 5720b7d..f785f66 100644 --- a/ShoulderCase/@ShoulderCasePlotter/plot.m +++ b/ShoulderCase/@ShoulderCasePlotter/plot.m @@ -1,100 +1,100 @@ function plot(obj) % set method colors autoColors = {'b','cyan'}; manualColors = {'#D95319','#ffcc00'}; % plot scapula data axes(obj.axesHandle('scapula')); hold on; grid on axis vis3d auto = containers.Map; try - auto('landmarks') = obj.SCase.shoulderAuto.scapula.plotLandmarks(autoColors{2},autoColors{2}); + auto('landmarks') = obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.plotLandmarks(autoColors{2},autoColors{2}); end try - auto('scapula surface') = obj.SCase.shoulderAuto.scapula.plotSurface(autoColors{1},autoColors{1}); + auto('scapula surface') = obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.plotSurface(autoColors{1},autoColors{1}); end try - auto('glenoid surface') = obj.SCase.shoulderAuto.scapula.glenoid.plot(); + auto('glenoid surface') = obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.glenoid.plot(); end try - auto('coordinate system') = obj.SCase.shoulderAuto.scapula.coordSys.plot(autoColors{1},false); + auto('coordinate system') = obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.plot(autoColors{1},false); end manual = containers.Map; try - manual('landmarks') = obj.SCase.shoulderManual.scapula.plotLandmarks(manualColors{2},manualColors{2}); + manual('landmarks') = obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.plotLandmarks(manualColors{2},manualColors{2}); end try - manual('scapula surface') = obj.SCase.shoulderManual.scapula.plotSurface(manualColors{1},manualColors{1}); + manual('scapula surface') = obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.plotSurface(manualColors{1},manualColors{1}); end try - manual('glenoid surface') = obj.SCase.shoulderManual.scapula.glenoid.plot(); + manual('glenoid surface') = obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.glenoid.plot(); end try - manual('coordinate system') = obj.SCase.shoulderManual.scapula.coordSys.plot(manualColors{1},false); + manual('coordinate system') = obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.coordSys.plot(manualColors{1},false); end outliersNormLimit = 10; difference = containers.Map; try difference('difference') = obj.SCase.plotManualAutoDifferences(outliersNormLimit); end % plot centered coordinate system axes(obj.axesHandle('centered coordinate system')); hold on; grid on axis vis3d try - auto('centered coordinate system') = obj.SCase.shoulderAuto.scapula.coordSys.plot(autoColors{1},true); + auto('centered coordinate system') = obj.SCase.shoulders.(obj.shoulderSide).auto.scapula.coordSys.plot(autoColors{1},true); end try - manual('centered coordinate system') = obj.SCase.shoulderManual.scapula.coordSys.plot(manualColors{1},true); + manual('centered coordinate system') = obj.SCase.shoulders.(obj.shoulderSide).manual.scapula.coordSys.plot(manualColors{1},true); end % plot muscles segmentation axes(obj.axesHandle('auto muscles')); title('Auto segmentation with auto landmarks'); hold on; try - auto('rotator cuff') = obj.SCase.shoulderAuto.rotatorCuff.plot(); + auto('rotator cuff') = obj.SCase.shoulders.(obj.shoulderSide).auto.rotatorCuff.plot(); end axes(obj.axesHandle('scapula')) try - auto("rotator cuff") = [auto("rotator cuff") obj.SCase.shoulderAuto.rotatorCuff.plot3()]; + auto("rotator cuff") = [auto("rotator cuff") obj.SCase.shoulders.(obj.shoulderSide).auto.rotatorCuff.plot3()]; end try - auto("rotator cuff") = [auto("rotator cuff") obj.SCase.shoulderAuto.humerus.plot()]; + auto("rotator cuff") = [auto("rotator cuff") obj.SCase.shoulders.(obj.shoulderSide).auto.humerus.plot()]; end axes(obj.axesHandle('manual muscles')); title('Auto segmentation with manual landmarks'); hold on; try - manual('rotator cuff') = obj.SCase.shoulderManual.rotatorCuff.plot(); + manual('rotator cuff') = obj.SCase.shoulders.(obj.shoulderSide).manual.rotatorCuff.plot(); end axes(obj.axesHandle('scapula')) try - manual("rotator cuff") = [manual("rotator cuff") obj.SCase.shoulderManual.rotatorCuff.plot3()]; + manual("rotator cuff") = [manual("rotator cuff") obj.SCase.shoulders.(obj.shoulderSide).manual.rotatorCuff.plot3()]; end try - manual("rotator cuff") = [manual("rotator cuff") obj.SCase.shoulderManual.humerus.plot()]; + manual("rotator cuff") = [manual("rotator cuff") obj.SCase.shoulders.(obj.shoulderSide).manual.humerus.plot()]; end % store the data handles obj.plotHandle.auto = auto; obj.plotHandle.manual = manual; obj.plotHandle.difference = difference; end \ No newline at end of file diff --git a/plotSCase.m b/plotSCase.m index b0422f0..d360874 100755 --- a/plotSCase.m +++ b/plotSCase.m @@ -1,20 +1,20 @@ -function [output,varargout] = plotSCase(SCaseID) +function [output,varargout] = plotSCase(SCaseID, varargin) % Call a ShoulderCase.plot function % % Inputs: id char of shoulder case (e.g. 'P315') % % Output: Corresponding ShoulderCasePlotter object % % Example: SCasePlotter = plotSCase('P315'); % % Author: Alexandre Terrier, EPFL-LBO % Matthieu Boubat, EPFL-LBO % Creation date: 2018-07-01 % Revision date: 2020-08-10 addpath(genpath('ShoulderCase')); SCase = loadSCase(SCaseID); - SCasePlotter = plot(SCase); + SCasePlotter = plot(SCase, varargin{:}); output = SCasePlotter; end