classdef (Abstract) CasesFinder < handle % The CasesFinder class is looking for data related to a ShoulderCase in a folder tree. % It has been designed to work with the datastructure found in lbovenus.epfl.ch/shoulder/. % % A concrete subclass of CasesFinder must implement the expression related to the % 'branch' of the datastructure it is looking at. % Then, the CasesFinder will list all the cases that can be found following a % fullfile(dataRootPath,casesSpecificExpression) path. % The found cases are then filtered according to the dicom files found following their % path. properties (Access = protected) dataRootPath casesSpecificExpression casesDirectories end methods (Abstract) setCasesSpecificExpression(obj); end methods function obj = CasesFinder(dataRootPath) obj.dataRootPath = dataRootPath; obj.casesSpecificExpression = []; obj.casesDirectories = containers.Map; obj.setCasesSpecificExpression; obj.mapCasesDirectories; obj.removeCasesWithNoCTDirectory; obj.reachBestCTDirectory; end end methods (Access = protected) function mapCasesDirectories(obj) cases = dir(fullfile(obj.dataRootPath,obj.casesSpecificExpression)); cases = obj.addSCaseIDToDirOutput(cases); obj.updateMapWithCases(cases); end function dirOutput = addSCaseIDToDirOutput(obj,dirOutput) for i = 1:length(dirOutput) dirOutput(i).SCaseID = regexp(dirOutput(i).name,'[NP]\d{1,3}','match','once'); end end function updateMapWithCases(obj,cases) for i = 1:length(cases) if not(isempty(cases(i).SCaseID)) obj.casesDirectories(cases(i).SCaseID) = fullfile(cases(i).folder,cases(i).name); end end end function removeCasesWithNoCTDirectory(obj) SCases = obj.casesDirectories.keys; for i = 1:length(SCases) SCase = SCases{i}; if not(obj.containsCTDirectories(obj.casesDirectories(SCase))); obj.casesDirectories.remove(SCase); end end end function output = containsCTDirectories(obj,directory) if isempty(dir(fullfile(directory,'CT*'))) output = false; else output = true; end end function reachBestCTDirectory(obj) SCases = obj.casesDirectories.keys; for i = 1:length(SCases) SCase = SCases{i}; caseWithBestDirectory = obj.getBestCTDirectoryForSCase(SCase); caseWithBestDirectory = obj.addSCaseIDToDirOutput(caseWithBestDirectory); obj.updateMapWithCases(caseWithBestDirectory) end end function output = getBestCTDirectoryForSCase(obj,SCase) % Each SCase directory should at least contain a % directory with a name staring with 'CT' and ending with either % '-1' : preop/shoulder/sharp/noPhantom % '-2' : preop/shoulder/smooth/noPhantom % '-3' : preop/shoulder/sharp/phantom % '-4' : preop/shoulder/smooth/phantom % and containing a 'dicom' subdirectory. The priority is '1', '2', '3', '4', % unless there is a amira folder already present in one of these diretories. observedCTDirectories = dir(fullfile(obj.casesDirectories(SCase),'CT*')); for i = 1:length(observedCTDirectories) if obj.containsAmiraDirectory(observedCTDirectories(i)) output = observedCTDirectories(i); return end end output = observedCTDirectories(1); end function output = containsAmiraDirectory(obj,directory) if isempty(dir(fullfile(directory.folder,directory.name,'amira'))) output = false; else output = true; end end end methods function output = getPathTo(obj,SCase) if obj.containsCase(SCase) output = obj.casesDirectories(SCase); else output = []; end end function output = getAllCasesIDs(obj) output = obj.casesDirectories.keys; end function output = getNumberOfCases(obj) output = obj.casesDirectories.Count; end function output = containsCase(obj,SCase) output = obj.casesDirectories.isKey(SCase); end end end