diff --git a/measureSCase.m b/measureSCase.m index f10f2ec..dfb1398 100755 --- a/measureSCase.m +++ b/measureSCase.m @@ -1,304 +1,433 @@ function [status,message] = measureSCase(varargin) % MEASURESCASE Update the entire SCase DB with anatimical measurements. -% The script measureSCase will replace 3 prevvious functions -% 1) rebuildDatabaseScapulaMeasurements.m --> list of all sCases --> execute scapula_measure.m -% 2) scapula_measure.m --> execute scapula_calculation and save results in Excel and SQL -% 3) scapula_calculation.m --> perform anatomical analysis --> results varaiable +% The function can be run from (lbovenus) server with the following shell command +% cd /home/shoulder/methods/matlab/database; matlab -nodisplay -nosplash -r "measureSCase;quit" -% Currently, the script should be run for the entire DB +% Progress can be checked through log file with following shell command +% cd /home/shoulder/methods/matlab/database;tail -f log/measureSCase.log -% Run from lbovenus -% The script can be run from (lbovenus) server as follows -% cd /home/shoulder/methods/matlab/database -% matlab -nojvm -nodisplay -nosplash -r "measureSCase;quit" -% The log file can be checked with shell command -% tail -f log/measureSCase.log % It take ~30 min for 700 cases when run from server. % After run from server, the output file % /shoulder/data/Excel/xlsFromMatlab/anatomy.csv % must be open from Excel and saved % as xls at the same location. +% The script measureSCase will replace 3 previous functions +% 1) rebuildDatabaseScapulaMeasurements.m --> list of all SCases --> execute scapula_measure.m +% 2) scapula_measure.m --> execute scapula_calculation and save results in Excel and SQL +% 3) scapula_calculation.m --> perform anatomical analysis --> results varaiable + +% The current version produces correctly the entire csv when run +% without arguments only (for the entire database) + % Input -% No output yet +% Either empty, 'N', 'P', or a SCase ('P315') % Output % File /shoulder/data/Excel/xlsFromMatlab/anatomy.csv % File /shoulder/data/Excel/xlsFromMatlab/anatomy.xls (only windows) % File /home/shoulder/data/matlab/SCaseDB.mat % File {SCaseId}.mat in each {SCaseId}/{CT}/matlab directory % logs in /log/measureSCase.log % Example: measureSCase % Author: Alexandre Terrier, EPFL-LBO % Creation date: 2018-07-01 -% Revision date: 2018-08-15 +% Revision date: 2018-09-18 % TO DO: % Read first last anatomy.csv and/or SCaseDB.mat % Fill with patient and clinical data, from excel or MySQL % use argument to redo or update % Save csv within the main loop (not sure it's a good idea) % Add more message in log % Add more test to assess validity of data % Update MySQL % Rename all objects with a capital % Make it faster by not loading scapula surface if already in SCaseDB.mat % Add argument 'load' to force reload files even if they are alerady in DB % Add argument 'measure' to force re-measuring event if measurement is already in DB % Add "scapula_addmeasure.m" --> should be coded in ShoulderCase class tic; % Start stopwatch timer %% Initialisation of paths % Should be replaced by a function dataDir = '../../../data'; % location of data logDir = 'log'; % log file in xls folder xlsDir = [dataDir '/Excel/xlsFromMatlab']; matlabDir = [dataDir '/matlab']; %% Add path to ShoulderCase class addpath('ShoulderCase'); %% Open log file filename = 'measureSCase.log'; filename = [logDir '/' filename]; -logFileId = fopen(filename, 'w'); -fprintf(logFileId, 'measureSCase log file'); -fprintf(logFileId, ['\nDate: ' datestr(datetime)]); +logFileID = fopen(filename, 'w'); +fprintf(logFileID, 'Log file of measureSCase'); +fprintf(logFileID, ['\nDate: ' datestr(datetime)]); %% Instance of a ShoulderCase object -if (exist('sCase','var') > 0) - clear sCase; % Check for delete method +if (exist('SCase','var') > 0) + clear SCase; % Check for delete method end -sCase = ShoulderCase; % Instanciate a ShoulderCase object +SCase = ShoulderCase; % Instanciate a ShoulderCase object %% Get list of all SCase -sCaseList = listSCase(); % get list of sCases ('N', 'P', no arg for all) - -% For debuging, sCaseList is reduced to the first 5 cases -% sCaseList = sCaseList(1:5); - -% For debuging, sCaseList is reduced to 1 element -% sCaseList(1) = struct('id', 'P313', 'dir', 'toto'); -% sCaseList(2) = struct('id', 'P315', 'dir', 'toto'); - -%% Start loop over sCases in sCaseList -sCaseN = length(sCaseList); % Number of sCases -for sCaseIdx = 1:sCaseN - sCaseId = sCaseList(sCaseIdx).id; % - fprintf(logFileId, ['\n' num2str(sCaseIdx) '/' num2str(sCaseN) '. ' sCaseId ': ']); - sCase(sCaseIdx).id = sCaseId; - output = sCase(sCaseIdx).path; % Set data path of this sCase - if output % Continue if sCase amira path exist - % Load scapula data from amira folder and set scapular coordinate system - output = sCase(sCaseIdx).shoulder.scapula.load; % Load data from amira directory +% Get list of SCases from varargin +fprintf(logFileID, '\n\nList of SCase'); +if nargin == 0 % findScapulaLandmarksSCase called without argument + SCaseList = listSCase; +elseif nargin == 1 + inputArg = varargin{1}; + SCaseList = listSCase(inputArg); +else + error('inputArg can be empty, N, P, or a SCaseID') +end + +%% Load current xls database (for clinical data) +fprintf(logFileID, '\nLoad xls database'); +addpath('XLS_MySQL_DB'); +filename = [dataDir '/Excel/ShoulderDataBase.xlsx']; +excelRaw = rawFromExcel(filename); % cell array + +excelSCaseID = excelRaw(2:end, 1); +excelDiagnosis = excelRaw(2:end, 4); +excelPatientHeight = excelRaw(2:end, 23); +excelGlenoidWalch = excelRaw(2:end, 55); + +% Lines below adapted from XLS_MySQL_DB/MainExcel2XLS +% Excel.diagnosisList = diagnosisListFromExcel(Excel.Raw); +% Excel.treatmentList = treatmentListFromExcel(Excel.Raw); +% ExcelData.Patient = patientFromExcel(excelRaw); % Structure with patient data +% Excel.shoulder = shoulderFromExcel(Excel.patient, Excel.Raw); +% [Excel.SCase, Excel.diagnosis, Excel.treatment, Excel.outcome, Excel.study] = SCaseFromExcel(... +% Excel.shoulder, Excel.patient, Excel.diagnosisList, Excel.treatmentList, Excel.Raw); +% fprintf(logFileID, ': OK'); + +%% Start loop over SCases in SCaseList +nSCase = length(SCaseList); % Number of SCases +for iSCaseID = 1:nSCase + SCaseID = SCaseList(iSCaseID).id; % + SCase(iSCaseID).id = SCaseID; + percentProgress = num2str(iSCaseID/nSCase*100, '%3.1f'); + fprintf(logFileID, ['\n\nSCaseID: ' SCaseID ' (' percentProgress '%%)']); + + % There are 3 parts within this SCase loop: + % 1) Load & analyses manual data from amira + % 2) Load & analyses auto data from matlab (Statistical Shape Model) + % 3) Load clinical data from Excel database, and set them to SCase + % 4) Save SCase in file SCaseID/matlab/SCase.mat + + % 1) Load & analyses manual data from amira + fprintf(logFileID, '\n Segmentation manual '); + output = SCase(iSCaseID).path; % Set data path of this SCase + if output % Continue if amira dir exists in SCase + fprintf(logFileID, '\n Load scapula surface and landmarks'); + output = SCase(iSCaseID).shoulder.scapula.load; + if output + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Set coord. syst.'); + output = SCase(iSCaseID).shoulder.scapula.coordSysSet; + if output + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Load glenoid surface'); + output = SCase(iSCaseID).shoulder.scapula.glenoid.load; + if output + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Measure glenoid anatomy'); + output = SCase(iSCaseID).shoulder.scapula.glenoid.morphology; + if output + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Measure glenoid density'); + output = SCase(iSCaseID).shoulder.scapula.glenoid.calcDensity; + if output + fprintf(logFileID, ': OK'); + end + fprintf(logFileID, '\n Load humerus data'); + output = SCase(iSCaseID).shoulder.humerus.load; + if output + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Measure humerus subluxation'); + output = SCase(iSCaseID).shoulder.humerus.subluxation; + if output + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Measure acromion anatomy'); + % Should be run after SCase.shoulder.humerus (for AI) + output = SCase(iSCaseID).shoulder.scapula.acromion.morphology; + if output + fprintf(logFileID, ': OK'); + else + fprintf(logFileID, ': Error'); + end % Acromion anatmy + else + fprintf(logFileID, ': Error'); + end % Subluxation humerus + else + fprintf(logFileID, ': Error'); + end % Load humerus + else + fprintf(logFileID, ': Error'); + end % Anatomy glenoid + else + fprintf(logFileID, ': Error'); + end % Load glenoid + else + fprintf(logFileID, '\n No amira folder'); + end % Set coord. syst. + end % Load scapula + end % Amira path exist + + % 2) Load & analyses auto data from matlab (Statistical Shape Model) + fprintf(logFileID, '\n Segmentation auto '); + % Load scapula surface and landmarks + fprintf(logFileID, '\n Load scapula surface and landmarks'); + output = SCase(iSCaseID).shoulder.scapulaAuto.loadAuto; % Load auto data from matlab directory + if output + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Set coord. syst.'); + output = SCase(iSCaseID).shoulder.scapulaAuto.coordSysSet; if output - sCase(sCaseIdx).shoulder.scapula.coordSysSet; % Set scapular coordinate system - % Load glenoid data from amira folder and set glenoid morphology - output = sCase(sCaseIdx).shoulder.scapula.glenoid.load; % Load data from amira directory + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Load glenoid surface'); + output = SCase(iSCaseID).shoulder.scapulaAuto.glenoid.loadAuto; if output - sCase(sCaseIdx).shoulder.scapula.glenoid.morphology; % Perform morphological measurements - % Load humerus data from amira folder and set subluxation - output = sCase(sCaseIdx).shoulder.humerus.load; % load data from amira directory + fprintf(logFileID, ': OK'); + fprintf(logFileID, '\n Measure glenoid anatomy'); + output = SCase(iSCaseID).shoulder.scapulaAuto.glenoid.morphology; if output - sCase(sCaseIdx).shoulder.humerus.subluxation; % Calcul subluxation - % Acromion morphology - sCase(sCaseIdx).shoulder.scapula.acromion.morphology; % Should be run after sCase.shoulder.humerus - - % Save sCase object in file sCase.id/matlab/sCase_CNNN.m - sCase(sCaseIdx).matlabSave; - % We might add here the cvs save - - fprintf(logFileId, 'OK'); + fprintf(logFileID, ': OK'); else - fprintf(logFileId, 'humerus.load problem'); + fprintf(logFileID, ': Error'); end else - fprintf(logFileId, 'glenoid.load problem'); + fprintf(logFileID, ': Error'); end else - fprintf(logFileId, 'scapula.load problem'); - end + fprintf(logFileID, ': Error'); + end else - fprintf(logFileId, 'No amira folder'); + fprintf(logFileID, ': Error'); end -end + + % 3) Set clinical data from Excel database to SCase + fprintf(logFileID, '\n Set clinical data from Excel'); + + % Get idx of excelRaw for SCaseID + % Use cell2struct when dots are removed from excel headers + idx = find(strcmp(excelRaw, SCaseID)); % Index of SCaseID in excelRaw + SCase(iSCaseID).diagnosis = excelRaw{idx,4}; + SCase(iSCaseID).treatment = excelRaw{idx,9}; + SCase(iSCaseID).patient.gender = excelRaw{idx,19}; + SCase(iSCaseID).patient.age = excelRaw{idx,21}; + SCase(iSCaseID).patient.height = excelRaw{idx,23}; + SCase(iSCaseID).patient.weight = excelRaw{idx,24}; + SCase(iSCaseID).patient.BMI = excelRaw{idx,25}; + SCase(iSCaseID).shoulder.scapula.glenoid.walch = excelRaw{idx,55}; + + + % Patient data --> TO DO + % find patient id (in SQL) corresponding to iSCaseID +% +% +% idxSCase = find(contains(ExcelData, SCaseID)); +% SCase(iSCaseID).patient.id = ExcelData(idxSCase).patient.patient_id; % SQL patient id +% SCase(iSCaseID).patient.idMed = ExcelData(idxSCase).patient.IPP; % IPP to be replace by coded (anonymized) IPP from SecuTrial +% SCase(iSCaseID).patient.gender = ExcelData(idxSCase).patient.gender; +% SCase(iSCaseID).patient.age = []; % Age (years) at treatment, or preop CT (we might also add birthdate wi day et at 15 of the month) +% SCase(iSCaseID).patient.ethnicity = ExcelData(idxSCase).patient.IPP; +% SCase(iSCaseID).patient.weight = ExcelData(idxSCase).patient.weight; +% SCase(iSCaseID).patient.height = ExcelData(idxSCase).patient.height; +% SCase(iSCaseID).patient.BMI = ExcelData(idxSCase).pateint.BMI; +% SCase(iSCaseID).patient.comment = ExcelData(idxSCase).patient.comment; + + % 4) Save SCase in file SCaseID/matlab/SCase.mat + fprintf(logFileID, '\n Save SCase'); + output = SCase(iSCaseID).saveMatlab; + if output + fprintf(logFileID, ': OK'); + else + fprintf(logFileID, ': Error'); + end +end % End of loop on SCaseList %% Save the entire SCase array as a matlab file +fprintf(logFileID, '\n\n Save SCase database'); filename = 'SCaseDB'; filename = [matlabDir '/' filename '.mat']; try - SCaseDB = sCase; + SCaseDB = SCase; save(filename, 'SCaseDB'); - fprintf(logFileId, ['\nSaved dat file: ' filename]); - outputArg = 1; + fprintf(logFileID, ': OK'); catch - fprintf(logFileId, '\nError saving SCaseDB matlab file \n'); - outputArg = -1; + fprintf(logFileID, ': Error'); end %% Write csv file % This might be a function (SCase.csvSave()). The input would be a filename and a structure % data +fprintf(logFileID, '\n Save csv database'); + % Replace header and data by structure. Currently not working %{ txtFilename = [xlsDir, '/anatomy.txt']; % Name of the txt file DataStruc = struc(... - 'sCase_id', sCase.id, ... - 'shoulder_side', sCase.shoulder.side,... - 'glenoid_radius', sCase.shoulder.scapula.glenoid.radius,... - 'glenoid_sphereRMSE', sCase.shoulder.scapula.glenoid.sphereRMSE,... - 'glenoid_depth', sCase.shoulder.scapula.glenoid.depth,... - 'glenoid_width', sCase.shoulder.scapula.glenoid.width,... - 'glenoid_height', sCase.shoulder.scapula.glenoid.height,... - 'glenoid_centerPA', sCase.shoulder.scapula.glenoid.centerLocal(1),... - 'glenoid_centerIS', sCase.shoulder.scapula.glenoid.centerLocal(2),... - 'glenoid_centerML', sCase.shoulder.scapula.glenoid.centerLocal(3),... - 'glenoid_versionAmpl', sCase.shoulder.scapula.glenoid.versionAmpl,... - 'glenoid_versionOrient', sCase.shoulder.scapula.glenoid.versionOrient,... - 'glenoid_version', sCase.shoulder.scapula.glenoid.version,... - 'glenoid_inclination', sCase.shoulder.scapula.glenoid.inclination,... - 'humerus_jointRadius', sCase.shoulder.humerus.jointRadius,... - 'humerus_headRadius', sCase.shoulder.humerus.radius,... - 'humerus_GHSAmpl', sCase.shoulder.humerus.GHSAmpl,... - 'humerus_GHSOrient', sCase.shoulder.humerus.GHSOrient,... - 'humerus_SHSAmpl', sCase.shoulder.humerus.SHSAmpl,... - 'humerus_SHSOrient', sCase.shoulder.humerus.SHSOrient,... - 'humerus_SHSAngle', sCase.shoulder.humerus.SHSAngle,... - 'humerus_SHSPA', sCase.shoulder.humerus.SHSPA,... - 'humerus_SHSIS', sCase.shoulder.humerus.SHSIS,... - 'acromion_AI', sCase.shoulder.scapula.acromion.AI,... - 'acromion_CSA', sCase.shoulder.scapula.acromion.CSA,... - 'acromion_PS', sCase.shoulder.scapula.acromion.PS... + 'SCase_id', SCase.id, ... + 'shoulder_side', SCase.shoulder.side,... + 'glenoid_radius', SCase.shoulder.scapula.glenoid.radius,... + 'glenoid_sphereRMSE', SCase.shoulder.scapula.glenoid.sphereRMSE,... + 'glenoid_depth', SCase.shoulder.scapula.glenoid.depth,... + 'glenoid_width', SCase.shoulder.scapula.glenoid.width,... + 'glenoid_height', SCase.shoulder.scapula.glenoid.height,... + 'glenoid_centerPA', SCase.shoulder.scapula.glenoid.centerLocal(1),... + 'glenoid_centerIS', SCase.shoulder.scapula.glenoid.centerLocal(2),... + 'glenoid_centerML', SCase.shoulder.scapula.glenoid.centerLocal(3),... + 'glenoid_versionAmpl', SCase.shoulder.scapula.glenoid.versionAmpl,... + 'glenoid_versionOrient', SCase.shoulder.scapula.glenoid.versionOrient,... + 'glenoid_version', SCase.shoulder.scapula.glenoid.version,... + 'glenoid_inclination', SCase.shoulder.scapula.glenoid.inclination,... + 'humerus_jointRadius', SCase.shoulder.humerus.jointRadius,... + 'humerus_headRadius', SCase.shoulder.humerus.radius,... + 'humerus_GHSAmpl', SCase.shoulder.humerus.GHSAmpl,... + 'humerus_GHSOrient', SCase.shoulder.humerus.GHSOrient,... + 'humerus_SHSAmpl', SCase.shoulder.humerus.SHSAmpl,... + 'humerus_SHSOrient', SCase.shoulder.humerus.SHSOrient,... + 'humerus_SHSAngle', SCase.shoulder.humerus.SHSAngle,... + 'humerus_SHSPA', SCase.shoulder.humerus.SHSPA,... + 'humerus_SHSIS', SCase.shoulder.humerus.SHSIS,... + 'acromion_AI', SCase.shoulder.scapula.acromion.AI,... + 'acromion_CSA', SCase.shoulder.scapula.acromion.CSA,... + 'acromion_PS', SCase.shoulder.scapula.acromion.PS... ); DataTable = strct2table(Data); writetable(DataTable,filename); %} % Header of the csv file dataHeader = [... - 'sCase_id,' ... + 'SCase_id,' ... 'shoulder_side,' ... 'glenoid_radius,' ... 'glenoid_sphereRMSE,' ... 'glenoid_depth,' ... 'glenoid_width,' ... 'glenoid_height,' ... 'glenoid_centerPA,' ... 'glenoid_centerIS,' ... 'glenoid_centerML,' ... 'glenoid_versionAmpl,' ... 'glenoid_versionOrient,' ... 'glenoid_version,' ... 'glenoid_inclination,' ... 'humerus_jointRadius,' ... 'humerus_headRadius,' ... 'humerus_GHSAmpl,' ... 'humerus_GHSOrient,' ... 'humerus_SHSAmpl,' ... 'humerus_SHSOrient,' ... 'humerus_SHSAngle,' ... 'humerus_SHSPA,' ... 'humerus_SHSIS,' ... 'acromion_AI,' ... 'acromion_CSA,' ... - 'acromion_PS,'... - 'acromion_IE'... + 'acromion_PSA,'... + 'acromion_AAA'... ]; csvFilename = [xlsDir, '/anatomy.csv']; % Name of the csv file csvFileId = fopen(csvFilename, 'w'); fprintf(csvFileId,dataHeader); % Write header -for sCaseIdx = 1:length(sCaseList) % Loop on sCaseList to write data in csv +for iSCaseID = 1:length(SCaseList) % Loop on SCaseList to write data in csv + disp(SCase(iSCaseID).id); % For debug fprintf(csvFileId,['\n'... - sCase(sCaseIdx).id ','... % sCase_id - sCase(sCaseIdx).shoulder.side ','... % shoulder_side - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.radius) ','... % glenoid_radius - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.sphereRMSE) ','... % glenoid_sphereRMSE - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.depth) ','... % glenoid_depth - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.width) ','... % glenoid_width - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.height) ','... % glenoid_height - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.centerLocal(1)) ','... % glenoid_centerPA - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.centerLocal(2)) ','... % glenoid_centerIS - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.centerLocal(3)) ','... % glenoid_centerML - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.versionAmpl) ','... % glenoid_versionAmpl - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.versionOrient) ','... % glenoid_versionOrient - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.version) ','... % glenoid_version - num2str(sCase(sCaseIdx).shoulder.scapula.glenoid.inclination) ','... % glenoid_inclination - num2str(sCase(sCaseIdx).shoulder.humerus.jointRadius) ','... % humerus_jointRadius - num2str(sCase(sCaseIdx).shoulder.humerus.radius) ','... % humerus_headRadius - num2str(sCase(sCaseIdx).shoulder.humerus.GHSAmpl) ','... % humerus_GHSAmpl - num2str(sCase(sCaseIdx).shoulder.humerus.GHSOrient) ','... % humerus_GHSOrient - num2str(sCase(sCaseIdx).shoulder.humerus.SHSAmpl) ','... % humerus_SHSAmpl - num2str(sCase(sCaseIdx).shoulder.humerus.SHSOrient) ','... % humerus_SHSOrient - num2str(sCase(sCaseIdx).shoulder.humerus.SHSAngle) ','... % humerus_SHSAgle - num2str(sCase(sCaseIdx).shoulder.humerus.SHSPA) ','... % humerus_SHSPA - num2str(sCase(sCaseIdx).shoulder.humerus.SHSIS) ','... % humerus_SHSIS - num2str(sCase(sCaseIdx).shoulder.scapula.acromion.AI) ','... % acromion_AI - num2str(sCase(sCaseIdx).shoulder.scapula.acromion.CSA) ','... % acromion_CSA - num2str(sCase(sCaseIdx).shoulder.scapula.acromion.PS) ','... % acromion_PS - num2str(sCase(sCaseIdx).shoulder.scapula.acromion.IE)... % acromion_IE + SCase(iSCaseID).id ','... % SCase_id + SCase(iSCaseID).shoulder.side ','... % shoulder_side + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.radius) ','... % glenoid_radius + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.sphereRMSE) ','... % glenoid_sphereRMSE + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.depth) ','... % glenoid_depth + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.width) ','... % glenoid_width + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.height) ','... % glenoid_height + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.centerLocal.x) ','... % glenoid_centerPA + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.centerLocal.y) ','... % glenoid_centerIS + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.centerLocal.z) ','... % glenoid_centerML + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.versionAmpl) ','... % glenoid_versionAmpl + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.versionOrient) ','... % glenoid_versionOrient + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.version) ','... % glenoid_version + num2str(SCase(iSCaseID).shoulder.scapula.glenoid.inclination) ','... % glenoid_inclination + num2str(SCase(iSCaseID).shoulder.humerus.jointRadius) ','... % humerus_jointRadius + num2str(SCase(iSCaseID).shoulder.humerus.radius) ','... % humerus_headRadius + num2str(SCase(iSCaseID).shoulder.humerus.GHSAmpl) ','... % humerus_GHSAmpl + num2str(SCase(iSCaseID).shoulder.humerus.GHSOrient) ','... % humerus_GHSOrient + num2str(SCase(iSCaseID).shoulder.humerus.SHSAmpl) ','... % humerus_SHSAmpl + num2str(SCase(iSCaseID).shoulder.humerus.SHSOrient) ','... % humerus_SHSOrient + num2str(SCase(iSCaseID).shoulder.humerus.SHSAngle) ','... % humerus_SHSAgle + num2str(SCase(iSCaseID).shoulder.humerus.SHSPA) ','... % humerus_SHSPA + num2str(SCase(iSCaseID).shoulder.humerus.SHSIS) ','... % humerus_SHSIS + num2str(SCase(iSCaseID).shoulder.scapula.acromion.AI) ','... % acromion_AI + num2str(SCase(iSCaseID).shoulder.scapula.acromion.CSA) ','... % acromion_CSA + num2str(SCase(iSCaseID).shoulder.scapula.acromion.PSA) ','... % acromion_PSA + num2str(SCase(iSCaseID).shoulder.scapula.acromion.AAA)... % acromion_AAA ]); end fclose(csvFileId); -fprintf(logFileId, ['\nSaved csv file: ' csvFilename]); +fprintf(logFileID, [': ' csvFilename]); %% Write xls file (Windows only) [~,message] = csv2xlsSCase(csvFilename); -fprintf(logFileId, message); +fprintf(logFileID, message); % If run from non-windows system, only csv will be produced. The xls can be % produced by opening the csv from Excel and save as xls. % Could be a function with 1 input (cvsFilenames %{ xlsFilename = strrep(csvFilename, '.csv', '.xls'); % Replace .csv by .xls if ispc % Check if run from windows! % Read cvs file as table and write the table as xls cvsTable = readtable(csvFilename); % Get table from csv (only way to read non-numeric data) cvsCell = table2cell(cvsTable); % Tranform table cell array dataHeader = cvsTable.Properties.VariableNames; % Get header cvsCell = [dataHeader; cvsCell]; % Add header - + sheet = 'anatomy'; % Sheet name of the xls file - + [status,message] = xlswrite(xlsFilename, cvsCell, sheet); % Save xls - if status + if status fprintf(logFileId, ['\nSaved ' xlsFilename]); else fprintf(logFileId, ['\nCould not save ' xlsFilename]); fprintf(logFileId, ['\n' message.identifier]); fprintf(logFileId, ['\n' message.message]); end else fprintf(logFileId, ['\n' xlsFilename ' not saved. Open and save as xls from Excel']); end %} %% Close log file -fprintf(logFileId, '\n\nsCases measured: %s', num2str(length(sCaseList))); % Number of sCases measured -fprintf(logFileId, '\nElapsed time (s): %s', num2str(toc)); % stopwatch timer -fprintf(logFileId, '\n\n'); -fclose(logFileId); % Close log file +fprintf(logFileID, '\n\nSCase measured: %s', num2str(length(SCaseList))); % Number of SCases measured +fprintf(logFileID, '\nElapsed time (s): %s', num2str(toc)); % stopwatch timer +fprintf(logFileID, '\n'); +fclose(logFileID); % Close log file -%% Output of the sCase if required by argument -% sCase.output % inputArg = abaqus/density/references/ +%% Output of the SCase if required by argument +% SCase.output % inputArg = abaqus/density/references/ % update mySQL -% sCase.sqlSave +% SCase.sqlSave status = 1; message = 'OK'; -end \ No newline at end of file +end diff --git a/readme.md b/readme.md index 8f9de78..a550085 100755 --- a/readme.md +++ b/readme.md @@ -1,43 +1,43 @@ -# Desciption of folder /shoulder/methods/matlab/database +# Description of folder /shoulder/methods/matlab/database Author: Alexandre Terrier, EPFL-LBO Last update: 2018-08-15 ## Comments In the 2018 version (updated), adding a SCase is done in 3 steps: 1. Import CT - Use CT/dicomCopier (to be updated) to move CT from pending to N/P. Update ShoulderDatabase.xlsx - Use dicominfoSCase to get CT info and produce file data/Excel/xlsFromMatlab/CTdicomInfo.csv (and/or xls). (2 could be merged with 1) - Not yet mendatory, run the automatic segmentation. Could be done after or before 3, or even merged with 1. 3. Perform some tasks in amira, according to SOP. (Might be done by Matlab?, still manually) 4. Use measureSCase to perform measurements and produce file data/Excel/xlsFromMatlab/anatomy.csv (and/or xls) ## Updated * measureSCase.m: function to measure (and save) SCase (all or part of database) * dicominfoSCase.m: function to get dicom info if SCase, to replace CT/infoCT * listSCase.m: funcion to list SCase in /shoulder/data/ * plotSCase.m: function to plot SCase * csv2xlsSCase.m: fonction to write a xls file from a csv file (for SCase) * statSCase.m: script to perform statistical analyses on SCaseDB * ShoulderCase: directory with classes related to the shoulder cases * log: Directory with log files * segmentation: Directory with functions related to the automatic segementaton of the CT ## Oldies to be rewritten and/or removed * anatomy: Directory with functions related to the anatomical analysis of the shoulder CT * CT: Directory with functions for the reading of dicom field * Generated_Amira_TCL_Scripts: Ditrectory with tcl scripts for Amira, created by matlab functions * muscles: Directory with functions related to the analysis of muscle degeneration * XLS_MySQL_DB: Directory with function related to the access to the MySQL database * CylinderReferences_P403_AmiraCode.dat: To be checked ## To be cleaned * imageToolsExperimentation.m: ?? * Button 1 pushed.ps: ?? * LBODicomViewer.fig: ?? * LBODicomViewer.m: ?? * tempInfo.mat: ??