diff --git a/ImportSCase/README.pdf b/ImportSCase/README.pdf deleted file mode 100644 index 8dc87c0..0000000 Binary files a/ImportSCase/README.pdf and /dev/null differ diff --git a/ImportSCase/Reporting_student_project_work_PC.md b/ImportSCase/Reporting_student_project_work_PC.md deleted file mode 100644 index fc3ace8..0000000 --- a/ImportSCase/Reporting_student_project_work_PC.md +++ /dev/null @@ -1,27 +0,0 @@ -# Reporting Paul Cimadomo (PC) work - -## 2019-02-19, by JSM -- JSM introduced the ImportSCases.m script to PC, starting at 10:30 -- The Matlab version found in student computer was 2017b, older than the 2018b in the computer used for development. This could be the reason of an error that raised when running the last version of script *dicominfoSCase.m*. The same script works in Matlab2018b, while in Matlab2017b it produces the following error: - - Error using dialogCellstrHelper - Expected input to be one of these types: char, cell - Instead its type was string. - Error in dialogCellstrHelper (line 10) - validateattributes(inputStr, {'char','cell'}, {'2d'},mfilename); - Error in errordlg (line 45) - ErrorStringCell = dialogCellstrHelper(ErrorStringIn); - Error in dicominfoSCase (line 89) - errordlg(sprintf("%s\n%s",... - - After PC left the office I will install the last version of Matlab2018b - - -- PC worked with a previous version of *ImportScase.m*, from 2019-2-14 and the SOP validated by JSM and AT at 2019-02-18. - - In this version the operator (PC) need to write some parameters manually in the Excel Database and run the script *dicominfoSCase.m* for each new SCase. -- PC imported 11 Normal SCases in its first working day. Leaving the office at 16:00. -- JSM run *dicominfoSCase.m* with Matlab2018b at the end of the day to update the Excel Database. -- 19 + 17 = 36 normal SCases are still waiting to be imported in 2 pending folders: - - *lbovenus.epfl.ch\data\N\pending\N_update-2019-01-30\Normal 2016 - Partie 1\* - - *lbovenus.epfl.ch\data\N\pending\N_update-2019-01-30\Normal 2016 - Partie 2\* -- PC proposed to continue working the friday of the current week 2019-02-22 to finish the normal SCases. -- JSM will provide the last version of *ImportSCase.m* and *dicominfoSCase.m*, after installation of Matlab2018b and testing in the student computer. diff --git a/ImportSCase/importSCaseDev.m b/ImportSCase/importSCaseDev.m deleted file mode 100644 index 7cb93eb..0000000 --- a/ImportSCase/importSCaseDev.m +++ /dev/null @@ -1,1970 +0,0 @@ -function varargout = importSCaseDev(varargin) -% IMPORTSCASEDEV MATLAB code for importSCaseDev.fig -% IMPORTSCASEDEV, by itself, creates a new IMPORTSCASEDEV or raises the existing -% singleton*. -% -% H = IMPORTSCASEDEV returns the handle to a new IMPORTSCASEDEV or the handle to -% the existing singleton*. -% -% IMPORTSCASEDEV('CALLBACK',hObject,eventData,handles,...) calls the local -% function named CALLBACK in IMPORTSCASEDEV.M with the given input arguments. -% -% IMPORTSCASEDEV('Property','Value',...) creates a new IMPORTSCASEDEV or raises the -% existing singleton*. Starting from the left, property value pairs are -% applied to the GUI before importSCaseDev_OpeningFcn gets called. An -% unrecognized property name or invalid value makes property application -% stop. All inputs are passed to importSCaseDev_OpeningFcn via varargin. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help importSCaseDev - -% Last Modified by GUIDE v2.5 15-Jan-2019 16:51:28 - -%% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @importSCaseDev_OpeningFcn, ... - 'gui_OutputFcn', @importSCaseDev_OutputFcn, ... - 'gui_LayoutFcn', [] , ... - 'gui_Callback', []); -if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); -end - -if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); -else - gui_mainfcn(gui_State, varargin{:}); -end -% End initialization code - DO NOT EDIT -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -function importSCaseDev_OpeningFcn(hObject, eventdata, handles, varargin) -%% --- Executes just before importSCaseDev is made visible. -% This function has no output args, see OutputFcn. -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% varargin command line arguments to importSCaseDev (see VARARGIN) -%-------------------------------------------------------------------------- -% Choose default command line output for importSCaseDev -handles.output = hObject; -% Update handles structure -guidata(hObject, handles); -% UIWAIT makes importSCaseDev wait for user response (see UIRESUME) -% uiwait(handles.figure1); -movegui('center') - -%-------------------------------------------------------------------------- -%% Customized by JSM 2018/10/26 -% Setting default values for some global variables - -% Default directory = the current directory -handles.script_dir = pwd; -cd([pwd '/../../../../']); -handles.home_path = pwd; -cd([pwd '/data/']); -handles.base_dir = pwd; -cd(handles.script_dir); - -% Radiobuttons -% *handles.acquisition_stage* => might be 'Normal' or 'Pathologic' -set(handles.radiobutton_Pathologic,'Value',1); -handles.patient_group="P"; -% *handles.shoulder_side* => might be 'Right' or 'Left' -set(handles.radiobutton_right,'Value',1); -% *handles.acquisition_stage* => might be 'Preop' or 'Postop' -set(handles.radiobutton_preop,'Value',1); -% *handles.output_dir* => importation folder. By default the current dir. -set(handles.output_dir,'String',pwd); -% *handles.body* => might be 'Shoulder', 'Elbow' or 'Other[]' -set(handles.radiobutton_shoulder,'Value',1); -% *handles.CTlabel_text* => might be '-1', '-2', ..., '-1p', '-2p', ... -set(handles.CTlabel_text,'String','-xxx'); - -guidata(hObject,handles); - -function varargout = importSCaseDev_OutputFcn(hObject, eventdata, handles) -%% --- Outputs from this function are returned to the command line. -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - -%% ====================================================================== -%% "Create Functions" execute during object creation, after setting all properties. - -function patient_num_CreateFcn(hObject, eventdata, handles) -%% --- Executes during object creation, after setting all properties. -% hObject handle to patient_num (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -%% --- Executes during object creation, after setting all properties. -function slider_2Dslice_CreateFcn(hObject, eventdata, handles) -% hObject handle to slider_2Dslice (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: slider controls usually have a light gray background. -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end -guidata(hObject,handles); - - -function edit_otherBody_CreateFcn(hObject, eventdata, handles) -%% --- Executes during object creation, after setting all properties. -% hObject handle to edit_otherBody (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end -guidata(hObject,handles); - - -function edit_extra_CreateFcn(hObject, eventdata, handles) -%% --- Executes during object creation, after setting all properties. -% hObject handle to edit_extra (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end -set(hObject,'String','Write here every extra info...'); -% update_infoFields(handles); -guidata(hObject,handles); - - - -%% ====================================================================== -%% "Callback Functions" execute on hObject's action events - -%% ************** Patient Type (group) ************** -function radiobutton_Pathologic_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_Pathologic. -% hObject handle to radiobutton_Pathologic (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_Pathologic -handles.patient_group="P"; -set(handles.act3Dview,'value',1) -act3Dview_Callback(handles.act3Dview,eventdata,handles) -patient_num = get(handles.patient_num,'String'); -set(handles.patient_num,'String',['P' patient_num(2:end)]); - - -function radiobutton_Normal_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_Normal. -% hObject handle to radiobutton_Normal (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_Normal -handles.patient_group="N"; -set(handles.act3Dview,'value',0) -act3Dview_Callback(handles.act3Dview,eventdata,handles) -patient_num = get(handles.patient_num,'String'); -set(handles.patient_num,'String',['N' patient_num(2:end)]); - -%% ************** Start new Patient / sCase ************** -function newPatient_Callback(hObject, eventdata, handles) -%% --- Executes on button press in newPatient. -% hObject handle to newPatient (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% This button lunch the initial check of a folder containing a group of -% sets of CTs. It counts the files per subfolder to clasify them - -% Select a limit of minimun dicom files to discard scout scans & other -% small scans as elbows -scoutScanLimit = 30; -smallScanLimit = 90; - -% Choose the main folder for the desired case -newPath = uigetdir(handles.base_dir); -% handles.patient_dir = newPath; -current_dir = pwd; -cd([newPath '/..']); -handles.patient_dir = pwd; -cd(current_dir); - -% Check the given path and extract data from every folder and file inside -dirList = dir(newPath); -% Select only the folders from the current path --> folderList -folderN = 0; -for k=3:length(dirList) - folderN = folderN + dirList(k).isdir - if folderN * dirList(k).isdir >0 - folderList(folderN) = dirList(k); - folderN,folderList(folderN).name - end -end - - -% Check how many dicom files are in each folder (to discard ScoutScans) -wb = waitbar(0,'Checking folders size'); -for k=1:folderN - % will contain a struct with data of files in the desired - % folder - waitbar(k/folderN,wb,sprintf('%s%s%s%i%s%i',"Checking directory ",... - string(folderList(k).name),": ",k,"/",folderN)); - files=dir([folderList(k).folder '/' folderList(k).name]); - filesDicom = 0; % Initialitation of dicom files counter - for n=1:length(files) - % if is a file and this file is a dicom file, note it - % (files.isdicom) and count it - if isfile([files(n).folder '/' files(n).name]) & ... - isdicom([files(n).folder '/' files(n).name]) - files(n).isdicom = 1; % noting down that it is a dicom file - filesDicom = filesDicom +1; % counting the dicom files - % Next line builds a list of dicom file names in cell mode - folderList(k).dicomList(filesDicom) = cellstr(files(n).name); - else - % Otherwise, is not a dicom file and we note it like that - files(n).isdicom = 0; - end - end - % Each folder has it own counter of dicom files - folderList(k).dicomN = filesDicom; - % We add a prefix with the number of files per CT, helping to priorize - % the importation order - if ~contains(folderList(k).name,['s' char(string(folderList(k).dicomN))]) - movefile([folderList(k).folder '/' folderList(k).name],... - [folderList(k).folder '/' 's'... - char(string(folderList(k).dicomN)) '-' folderList(k).name]); - folderList(k).name = ['s' char(string(folderList(k).dicomN))... - '-' folderList(k).name]; - end - %% From here it could be commented and eliminated (JSM 25102018) - % When a folder has few dicom files we can consider that it was a scan - % scout instead of an interesting CT - if folderList(k).dicomN < scoutScanLimit - folderList(k).scanMode = 'scoutScan'; - % Changing the folder name to mark it as scoutScan (if not marked - % before) - if ~contains(folderList(k).name,'scout') - movefile([folderList(k).folder '/' folderList(k).name],... - [folderList(k).folder '/' folderList(k).name '_scoutScan']); - end - elseif folderList(k).dicomN < smallScanLimit - folderList(k).scanMode = 'smallScan'; - % Changing the folder name to mark it as scoutScan (if not marked - % before) - if ~contains(folderList(k).name,'small') - movefile([folderList(k).folder '/' folderList(k).name],... - [folderList(k).folder '/' folderList(k).name '_smallScan']); - end - else - folderList(k).scanMode = 'CT'; - end - % Until here -end - -% Makes handles variable visible to other functions in this script -% hanldes.dicomdir = newPath; -guidata(hObject,handles); - - -%% ************** Load next CT set ************** -function Load_Next_CT_Callback(hObject, eventdata, handles) -%% --- Executes on button press in Load_Next_CT. -% hObject handle to Load_Next_CT (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Before loading a new set of CTs we should remove the last one -clear handles.data - -% Output Directory update -% if isfield(handles,'patient_dir') -% handles.base_dir = handles.patient_dir; -% else -% handles.base_dir = handles.home_path; -% end - -% Also remove the fields 'myinfo' and 'mydicom' (they could be just -% cleared?) -if isfield(handles, 'myinfo'); - handles = rmfield(handles, 'myinfo'); % Removing 'myinfo' field from structure in handles -else if isfield(handles, 'mydicom'); - handles = rmfield(handles, 'mydicom');% Removing 'mydicom' field from structure in handles - end -end - -if isfield(handles,'dicomSet') - handles = rmfield(handles,'dicomSet'); -end -if isfield(handles,'dicomSetSorted') - handles = rmfield(handles,'dicomSetSorted'); -end - -%% Loading CT files -% Using last directory -if isfield(handles,'patient_dir') - [handles.dicomlist, handles.dicomdir] = uigetfile('*.*',... - 'Select the images to load',handles.patient_dir,'MultiSelect', 'on'); -elseif isfield(handles,'base_dir') - [handles.dicomlist, handles.dicomdir] = uigetfile('*.*',... - 'Select the images to load',handles.base_dir,'MultiSelect', 'on'); -else - [handles.dicomlist, handles.dicomdir] = uigetfile('*.*',... - 'Select the images to load',home_path,'MultiSelect', 'on'); -end - -% Showing the dicom name in the interface -set(handles.text_dicom_name,'String',strcat(string(handles.dicomdir), string(handles.dicomlist(1)))); - -% Number of dicom files -handles.N = length(handles.dicomlist); - -% Set parametres for 2D visualization -set(handles.slider_2Dslice, 'Max', handles.N); -set(handles.slider_2Dslice, 'Value', int32(handles.N/2)); -set(handles.slider_2Dslice, 'SliderStep',[1/handles.N 10/handles.N]); -set(handles.slider_2Dslice, 'Min', 1); - -set(handles.info_text, 'ForegroundColor', 'black', 'FontWeight', 'normal'); - -% Read dicom data -try - % This loop reads all the dicom files and builds a new struct with the - % information from each row and the data (the images) - wb = waitbar(0,'Loading DICOM files'); %This creates a waitbar or progressbar - L = length(handles.dicomlist); % number of dicom files to load - for n=1:L - waitbar(n/L,wb,sprintf('%s%i%s%i',"Loading DICOM metadata ",n,"/",L)); - % Reads the info from each dicomfile - handles.dicomSet(n) = dicominfo(sprintf('%s%s',... - handles.dicomdir, char(handles.dicomlist(n))),'UseDictionaryVR',true); - end - for n=1:L - waitbar(n/L,wb,sprintf('%s%i%s%i',"Loading DICOM images ",n,"/",L)); - handles.dicomSet(n).data = dicomread(sprintf('%s%s', ... - handles.dicomdir, char(handles.dicomlist(int32(n))))); - end - - handles.myinfo = handles.dicomSet(1); % To be removed (JSM 25102018) -% % 'handles.myinfo' will keep the metadata of the dicom files loaded -% handles.myinfo(1) = dicominfo(sprintf('%s%s', handles.dicomdir, ... -% char(handles.dicomlist(1))),'UseDictionaryVR',true); - - % Temporal storing of metadata - tempInfo=handles.dicomSet(1); - save('tempInfo.mat','tempInfo'); - - % Shows few metadata in the interface: - % - IPP identification number and Patient Initials - set(handles.IPP_text, 'String', handles.dicomSet(1).PatientID) - set(handles.initials_text,'String',sprintf('(%s%s)',... - handles.dicomSet(1).PatientName.FamilyName(1),... - handles.dicomSet(1).PatientName.GivenName(1))); - set(handles.birthdate_text,'String',handles.dicomSet(1).PatientBirthDate); - set(handles.gender_text,'String',handles.dicomSet(1).PatientSex); - % - CT resolution in mm - set(handles.Resolution_text, 'String', sprintf('%f mm', handles.dicomSet(1).PixelSpacing(1))); - % - CT date - set(handles.CTdate_text, 'String', sprintf('%s', handles.dicomSet(1).AcquisitionDate)); - - % The following function sort the dicomFiles by their slice location -% handles.dicomSetSorted=sortStructByField(handles.dicomSet,{'SliceLocation'}); - handles.dicomSetSorted=sortStructByField(handles.dicomSet,{'InstanceNumber'},handles); - handles.dicomSetOld=handles.dicomSet; - handles.dicomSet=handles.dicomSetSorted; - 'load finished' - -catch except - except - except.identifier - if strcmp(except.identifier,'Error identifier: MATLAB:nonExistentField') - errordlg(except.message,'Loading Error') -% return -% elseif or(strcmp(except.identifier,'MATLAB:heterogeneousStrucAssignment'),... -% strcmp(except.identifier,'MATLAB:heterogeneousStrucAssignment')) -% f = errordlg(sprintf('%s\n\n%s\n%s', ' CT SCAN WITH UNEXPECTED ORIENTATION.',... -% 'Suggestion: mark the current folder as "Wrong_Orientation"',... -% 'and try with another set of CTs'),'Loading Error'); -% return - else - errordlg(sprintf('%s%s','Error identifier: ',except.identifier)) - end -end - -%% Updating the radioButtons "NONE", "BONE"('BONE'), "SOFT"('STANDARD') -if isfield(handles.dicomSet(1), 'ConvolutionKernel') - if strfind(handles.dicomSet(1).ConvolutionKernel, 'BONE') - set(handles.radiobutton_none, 'Value', 0); - set(handles.radiobutton_sharp, 'Value', 1); - set(handles.radiobutton_smooth, 'Value', 0); - elseif strfind(handles.dicomSet(1).ConvolutionKernel, 'STANDARD') - set(handles.radiobutton_none, 'Value', 0); - set(handles.radiobutton_sharp, 'Value', 0); - set(handles.radiobutton_smooth, 'Value', 1); - else - set(handles.radiobutton_none, 'Value', 1); - set(handles.radiobutton_sharp, 'Value', 0); - set(handles.radiobutton_smooth, 'Value', 0); - end -else - set(handles.radiobutton_none, 'Value', 1); - set(handles.radiobutton_sharp, 'Value', 0); - set(handles.radiobutton_smooth, 'Value', 0); -end - -%% Extracting data for interface representation -handles.slice = int32(handles.N / 2); % Chooses the central slice -% handles.mydicom(:,:,handles.slice) = dicomread(sprintf('%s%s', handles.dicomdir, char(handles.dicomlist(handles.slice)))); -if isfield(handles,'mydicom') - handles=rmfield(handles,'mydicom'); -end -handles.mydicom(:,:,handles.slice) = handles.dicomSet(handles.slice).data; - -handles.CTmin = -200; -handles.CTmax = 2000; - -handles.bigmax = 3000; -handles.bigmin = -2000; - -set(handles.slider_2Dcontrast, 'Max', handles.bigmax - handles.bigmin - 1); -set(handles.slider_2Dcontrast, 'Min', 0); -set(handles.slider_2Dcontrast, 'Value', 900); - -set(handles.slider_2Dbrightness, 'Max', handles.bigmax); -set(handles.slider_2Dbrightness, 'Min', handles.bigmin); -set(handles.slider_2Dbrightness, 'Value', 1100); - -set(handles.slice_num, 'String', handles.slice); - -axes(handles.axes_2Dviewer); % Set current axes -% imshow(handles.mydicom(:,:,handles.slice), [handles.CTmin handles.CTmax]); -% imshow(handles.dicomSet(handles.slice).data, [handles.CTmin handles.CTmax]); -% trying dicomreadVolume -% [V, SPATIAL, DIM] = dicomreadVolume(handles.dicomdir); -% imshow(V(:,:,1,handles.slice), [handles.CTmin handles.CTmax]); -imshow(handles.dicomSet(handles.slice).data, [handles.CTmin handles.CTmax]); - -%% ISOSURFACE section ==================================================== -act3Dview_Callback(handles.act3Dview, eventdata, handles); - -axes(handles.axes_2Dviewer); % Set current axes -guidata(hObject,handles); -% handles -if and(get(handles.patient_num,'String') ~="P###",... - exist([char(get(handles.output_dir,'String')) '/readme'])==2) - handles.text_readme.String="listo para leer"; -end -% update_infoFields(handles); -% Makes handles variable visible to other functions in this script - -%% Reset the DB chech result info box -set(handles.text_coincidences_info,'String',"Check DB for coincidences..."); -guidata(hObject,handles); - - -function act3Dview_Callback(hObject, eventdata, handles) -%% --- Executes on button press in act3Dview. -% hObject handle to act3Dview (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of act3Dview -% handles.enable_3Dview = get(hObject,'Value') -if get(hObject,'Value') - C=questdlg(['The 3D viewer might create memory problems when the CT'... - ' contains more than 300 slices. Do you want to activate it?'],... - '3D viewer activation','Yes, Display 3D view','Abort','Abort') - switch C - case 'Yes, Display 3D view' - handles.enable_3Dview = 1 - otherwise - handles.enable_3Dview = 0 - set(hObject,'Value',0) - end -else - handles.enable_3Dview = 0 -end -% clear handles.data -axes(handles.isosurface); % Set current axes -cla - -if isfield(handles,'N') & handles.enable_3Dview - if handles.N>1 - directory=handles.dicomdir; - % Preparing list of dicom full names (including address) - for k=1:handles.N - dicomListFullName(k)=""; - dicomListFullName(k)=[directory char(handles.dicomlist(k))]; - end - try - [V,spatial,dim] = dicomreadVolume(dicomListFullName); - v = squeeze(V); - v = double(v); - v2= imresize3(v,0.2); - handles.v2 = v2; - handles.isoValue = 1400; % default limit for isosurface rendering - p = patch(isosurface(v2,handles.isoValue)); - Sv2 = size(v2); - M = max(max(max(v2))); - m = min(min(min(v2))); - - handles.bigmax = M; - handles.bigmin = m; - set(handles.slider_3Dviewer, 'Max', handles.bigmax); - set(handles.slider_3Dviewer, 'Min', handles.bigmin); - set(handles.slider_3Dviewer, 'Value', handles.isoValue); - - d1=(M-m)/Sv2(1); - d2=(M-m)/Sv2(2); - d3=(M-m)/Sv2(3); - [x,y,z]=meshgrid(m:d1:M,m:d2:M,m:d3:M); - handles.x=x(1:Sv2(1),1:Sv2(2),1:Sv2(3)); - handles.y=y(1:Sv2(1),1:Sv2(2),1:Sv2(3)); - handles.z=z(1:Sv2(1),1:Sv2(2),1:Sv2(3)); - isocolors(handles.x,handles.y,handles.z,v2,p); - p.FaceColor='interp'; - p.EdgeColor='none'; - view(-20, 10); - % isosurface(v2,1400); - rotate3d on; - catch except - if strcmp(except.identifier,'images:dicomread:differentPatientOrientations') - f = errordlg(sprintf('%s\n\n%s\n%s', ' CT SCAN WITH UNEXPECTED ORIENTATION.',... - 'Suggestion: mark the current folder as "Wrong_Orientation"',... - 'and try with another set of CTs'),'Loading Error'); - % We change the folder name to mark it as scoutScan (if not marked before) - if ~contains(handles.dicomdir,'wrong') - movefile([handles.dicomdir(1:end-1)],... - [handles.dicomdir(1:end-1) '_wrongOrientatedScan']); - end - return - else - errordlg(sprintf('%s%s','Error identifier: ',except.identifier)); - % rethrow(except); - end - end - end -end -guidata(hObject,handles); - - -function slider_3Dviewer_Callback(hObject, eventdata, handles) -%% --- Executes on slider movement. -% hObject handle to slider_3Dviewer (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'Value') returns position of slider -% get(hObject,'Min') and get(hObject,'Max') to determine range of slider -guidata(hObject,handles); - - -function radiobutton_left_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_left. -% hObject handle to radiobutton_left (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_left -handles.shoulder_side = 'Left'; -update_readme_Callback(handles.update_readme,eventdata,handles); -guidata(hObject,handles); - -function radiobutton_right_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_right. -% hObject handle to radiobutton_right (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_right -handles.shoulder_side = 'Right'; -update_readme_Callback(handles.update_readme,eventdata,handles); -guidata(hObject,handles); - - -%% --- Executes on button press in radiobutton_preop. -function radiobutton_preop_Callback(hObject, eventdata, handles) -% hObject handle to radiobutton_preop (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_preop -handles.acquisition_stage = 'Preop'; -update_readme_Callback(handles.update_readme,eventdata,handles); -% update_infoFields(handles); -guidata(hObject,handles); - -function radiobutton_postop_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_postop. -% hObject handle to radiobutton_postop (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_postop -handles.acquisition_stage = 'Postop'; -update_readme_Callback(handles.update_readme,eventdata,handles); -% update_infoFields(handles); -guidata(hObject,handles); - - -function Check_Database_Callback(hObject, eventdata, handles) -%% --- Executes on button press in Check_Database. -% hObject handle to Check_Database (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -wb = waitbar(0,'Checking Excel Database'); -"Openning Excel Database" -% Checking Database ----------------------------------- -% Importing database from excel file depending on computer system -% if computer('arch')=="win64" -% handles.data=importDataBaseTab('../../../../data/Excel/ShoulderDataBase.xlsx','sCase',2,2000); -% excelDB = '../../../../data/Excel/ShoulderDataBase.xlsx'; -% else -% % path2DB=[ '/home/shoulder/data/Excel/ShoulderDataBase.xlsx']; -% system('ls /home/shoulder/data/Excel/'); -% path2DB=['/home/shoulder/data/Excel/ShoulderDataBase.xlsx']; -% excelDB = '/home/shoulder/data/Excel/ShoulderDataBase.xlsx'; -% % ls('/home/shoulder/data/Excel/') -% % f=importDataBaseTab_script; -% handles.data=importDataBaseTab(path2DB,'sCase',2,2000); -% -% end -% New way of reading the Excel Database: -[excelDB, DBpath, ~] = uigetfile('*.xlsx','Select the Excel Database File'); -tic -E = exist(sprintf('%s%s',DBpath,excelDB)); -% We store the Excel file adress and name for further use -handles.ExcelDB_path = DBpath; -handles.ExcelDB_fullname = sprintf('%s%s',DBpath,excelDB); - -if E == 2 % Only if the file exist as a known format (XLS) - [~,txt,raw,dates]=xlsread(handles.ExcelDB_fullname,'sCase','','',@convertSpreadsheetExcelDates); - % The dates cell array will have NaN in every cell not containing a "date" - dates(~cellfun(@(x) isnumeric(x) || islogical(x), dates)) = {NaN}; - handles.data.headers = string(txt(1,:)); - % Conversion of dates's cell array to numeric matrix - dates=cell2mat(dates); - % Finding columns with dates - dates_CperR=find(~isnan(dates(1,:))); - date_Cells{1}= dates_CperR; - txt_Cells{1} = []; - for p=2:size(txt,1) - dates_CperR=find(~isnan(dates(p,:))); - date_Cells{p}= dates_CperR; - txt_CperR = find(~ismissing(txt(p,:))); - txt_Cells{p} = txt_CperR; - end - date_columns = []; - txt_columns = []; - for p=1:length(date_Cells) - date_columns= union(date_columns,date_Cells{p}); - txt_columns = union(txt_columns,txt_Cells{p}); - end - num_columns = setdiff(1:size(raw,2),txt_columns); - txt_columns = setdiff(txt_columns,date_columns); - % Inverting the "date to number" convertion done during the importation - dates_only = datetime(dates(2:end,[date_columns]),'ConvertFrom','Excel','Format','dd-MM-yyy'); -% num_only = cell2mat(raw(2:end,num_columns)); - - for n=1:size(txt,2) % for each text headers (column) - [data.(raw{1,n})]=raw(2:end,n); - end - k=1; - for n=date_columns' % for the date columns - [data.(raw{1,n})]=dates_only(:,k); - k=k+1; - end - -elseif E == 0 - warndlg("Excel file not found!") -else - warndlg("Database file has unrecognized format. It should be an Excel file") -end -toc -handles.data=data; - -% ***Obtain the first row available for a new case*** -% Get the colum of sCase.id, including those from rows available -sCase_list = handles.data.SCase_ID; -% Cut the list from the end untill found an existing sCases -[s1,s2]=size(sCase_list); -s0=0; -while sCase_list(end,:)=="" % Last position empty... - sCase_list = sCase_list(1:end-1,:); - s0=s0+1; - waitbar(s0/s1,wb,'Checking Excel Database'); -end - - -sCase_N=[]; -sCase_P=[]; -% sCase_list_sorted=sort(sCase_list); % This helps to avoid errors if a row is eventually void -sCase_list_sorted=string(sCase_list); % This have to be cleaned -for n=1:s1-s0 - if sCase_list_sorted(n,:)~="" - L = length(char(extractAfter(sCase_list_sorted(n,:),1))); - while L<3 - sCase_list_sorted(n,:)=sprintf('%s%s%s',... - extractBefore(sCase_list_sorted(n,:),2),... - '0',extractAfter(sCase_list_sorted(n,:),1)); - L = length(char(extractAfter(sCase_list_sorted(n,:),1))); - end - if extractBefore(sCase_list_sorted(n,:),2)=="N" - sCase_N=[sCase_N; sCase_list_sorted(n,:)]; - elseif extractBefore(sCase_list_sorted(n,:),2)=="P" - sCase_P=[sCase_P; sCase_list_sorted(n,:)]; - else - "there is a row without identification (N or P) in the DataBase" - end - waitbar(s1-s0+n/s1,wb,'Checking Excel Database'); - end -end -sCase_N=sort(sCase_N); -sCase_P=sort(sCase_P); - -% Build the next sCase.id for a potential new sCase - % by extracting the 'id' number of the last sCase and adding '1' -if handles.patient_group=="N" - new_sCase = str2num(extractAfter(char(sCase_N(end)),1))+1; - % Finaly convert to string and add a 'P' for 'Pathological' - new_sCase = string(['N' num2str(new_sCase)]); -elseif handles.patient_group=="P" - new_sCase = str2num(extractAfter(char(sCase_P(end)),1))+1; - % Finaly convert to string and add a 'N' for 'Normal' - new_sCase = string(['P' num2str(new_sCase)]); -end -handles.data.anonymity_IPP=cell2mat(handles.data.anonymity_IPP); -handles.data.shoulder_side=cell2mat(handles.data.shoulder_side); - -% *** Q1: Does the new IPP exist in the Database yet? *** -% Extract the list of patient IDs from Excel database -IPP_list_DB = handles.data.anonymity_IPP; -% Extracting patient ID from dicom-set info -IPP_sCase = str2num(handles.myinfo(1).PatientID) - -% If the IPP of the current case already exist in the database, -% it finds the position of the current patient ID in the list. -% And for this position it extracts the case name "sCase", otherwise it -% leave the variables empty -% handles.patientIndex=find(handles.data.anonymityIPP==str2num(handles.myinfo(1).PatientID)) -handles.patientIndex=find(IPP_list_DB==IPP_sCase); -handles.sCase = handles.data.SCase_ID(handles.patientIndex); - -% Determine how many sCases exits with the same IPP as the current CT -Ncoincidences=length(handles.sCase); - -% *** We start the decision tree *** -if Ncoincidences==0 - % This is a new sCase!! So we write a short message and set the sCase - set(handles.dataCheck_text,'String', sprintf('This is a new case')); - set(handles.dataCheck_panel,'BackgroundColor','g'); - handles.current_sCase=new_sCase; - set(handles.patient_num,'String',sprintf('%s',handles.current_sCase)); - set(handles.text_coincidences_info,'String',"Current IPP not found in DB"); - -% If the IPP exists in the Excel Database in more than one sCase we first -% can discriminate by the shoulder side (rigth or left) -elseif Ncoincidences>1 - % Launch a warning message - set(handles.dataCheck_text,'String',... - ['Patient found in ' num2str(Ncoincidences) ' sCase(s)']); - set(handles.dataCheck_panel,'BackgroundColor','y'); - - % Shows information of the 2 first coincidences - coincidences = sprintf("%s \t%s \t%s \t%s \n%s \t%s \t%s \t\t%s \n%s \t%s \t%s \t\t%s",... - "SCase"," IPP "," CT_date ","Side",... - string(handles.sCase(1)),... - string(IPP_list_DB(handles.patientIndex(1))),... - handles.data.CT_date(handles.patientIndex(1)),... - handles.data.shoulder_side(handles.patientIndex(1)),... - string(handles.sCase(2)),... - string(IPP_list_DB(handles.patientIndex(2))),... - handles.data.CT_date(handles.patientIndex(2)),... - handles.data.shoulder_side(handles.patientIndex(2))); - set(handles.text_coincidences_info,'String',coincidences); - - % *** Q2: is the current CT from the same side of one of the existing? - % Get the side of the coincident sCases - side_sCase = handles.data.shoulder_side(handles.patientIndex); - % Launch 'question dialog' to let the user choose if one the coincident - % sCases matches with the side (rigth or left) of the current CT - question = sprintf("%s %s %s \n%s\n%s",... - "The SCase",string(IPP_sCase),... - "was found in the more than one case in the database.",... - "Please, check the shoulder side of the currently loaded CT",... - "and choose between the following options"); - title = "SCase found in database"; - btn1 = ['Existing case:' char(handles.sCase(1)) ' side:' char(side_sCase(1))]; - btn2 = ['Existing case:' char(handles.sCase(2)) ' side:' char(side_sCase(2))]; - btn3 = ['New case:' char(new_sCase) ' side: ?']; - dfltbtn = btn3; - answer = questdlg(question,title,btn1,btn2,btn3,dfltbtn); - switch answer - case btn1 - handles.current_sCase=handles.sCase(1); - answerN = 1; - case btn2 - handles.current_sCase=handles.sCase(2); - answerN = 2; - case btn3 - handles.current_sCase=string(new_sCase); - answerN = 3; - otherwise - disp("Auto Check DB -ABORTED-"); - return; - end - disp(sprintf("%s %s",string(handles.current_sCase),"chosen")); - - % Update the list of sCases after selection - handles.sCase=handles.current_sCase; - Ncoincidences=1; - - % *** Q3: is the current CT date similar to the CT_date from any of the - % concident sCases in the Database? *** - - % Get the CT's date from the coincident sCase from the Database - try - CTdate_DB = datestr(handles.data.CT_date(handles.patientIndex),'dd-mmm-yyyy'); - catch error - message = sprintf("%s\n%s\n%s\n\n%s\n%s\n%s",... - "Suggested solution:",... - "Opt1. Update InfoCT.xlsx and repeat the 'Auto Check DB'",... - "Opt2. Check the CT_date yourself and use 'Manual sCase'",... - "Error details:",... - error.identifier,error.message); - errordlg(message,"Not valid CT_date found in Database"); - CTdate_DB = NaT; - end - % Get the CT's date from the new CT set - current_CTdate = handles.myinfo.AcquisitionDate - % Adapt date format to make it comparable - current_CTdate=datestr([current_CTdate(1:4),'-',... - current_CTdate(5:6),'-',current_CTdate(7:8)],'dd-mmm-yyyy') - % Compare CT's dates - if isequal(current_CTdate,CTdate_DB) - % The sCase already exits so the user will have to decide if the CT - % must be added to the case of it is already added. - set(handles.dataCheck_text,'String',... - ['Current CT matches in IPP, side and CTdate with others in the database']); - set(handles.dataCheck_panel,'BackgroundColor','r'); - set(handles.patient_num,'String',string(handles.current_sCase)); - else - % The user must check if the current CT set corresponds to a - % post-op shoulder - set(handles.dataCheck_text,'String',... - ['Check if the CT is from a post-op. Current CT matches in IPP, side']); - set(handles.dataCheck_panel,'BackgroundColor','r'); - set(handles.patient_num,'String',string(handles.current_sCase)); - end - -% If only one sCase was found in the Database -elseif Ncoincidences==1 - % Launch a warning message - set(handles.dataCheck_text,'String',... - ['Patient found in one sCase(s)']); - set(handles.dataCheck_panel,'BackgroundColor','r'); - handles.current_sCase=handles.sCase; - - coincidences = sprintf("%s \t%s \t%s \t%s \n%s \t%s \t%s \t\t%s",... - "SCase"," IPP "," CT_date ","Side",... - string(handles.sCase(1)),... - string(IPP_list_DB(handles.patientIndex(1))),... - handles.data.CT_date(handles.patientIndex(1)),... - handles.data.shoulder_side(handles.patientIndex(1))); - set(handles.text_coincidences_info,'String',coincidences); - - side_sCase=handles.data.shoulder_side(handles.patientIndex); - % Creating question dialog to let the user choose between the found - % SCase and a new SCase label - question = sprintf("%s %s %s \n%s\n%s",... - "The loaded SCase",string(IPP_sCase),... - "was found in the SCase list in the database.",... - "Please, check the shoulder side of the currently loaded CT",... - "and choose between the following options"); - title = "SCase found in database"; - btn1 = ['Existing case:' char(handles.sCase(1)) ' side:' char(side_sCase(1))]; - btn2 = ['New case:' char(new_sCase) ' side: ?']; - dfltbtn = btn2; - answer= questdlg(question,title,btn1,btn2,dfltbtn); - - switch answer - case btn1 - handles.current_sCase=handles.sCase(1) - answerN=1; - case btn2 - handles.current_sCase=string(new_sCase); - answerN=2; - otherwise - disp("Auto Check DB -ABORTED-"); - return; - end - disp(sprintf("%s %s",string(handles.current_sCase),"chosen")); - - if answerN==1 - - % *** Q3: is the current CT date similar to the CT_date from any of the - % concident sCases in the Database? *** - - % Get the CT's date from the coincident sCase from the Database - try - CTdate_DB = datestr(handles.data.CT_date(handles.patientIndex),'dd-mmm-yyyy'); - catch error - message = sprintf("%s\n%s\n%s\n\n%s\n%s\n%s",... - "Suggested solution:",... - "Opt1. Update InfoCT.xlsx and repeat the 'Auto Check DB'",... - "Opt2. Check the CT_date yourself and use 'Manual sCase'",... - "Error details:",... - error.identifier,error.message); - errordlg(message,"Not valid CT_date found in Database"); - CTdate_DB = NaT; - end - % Get the CT's date from the new CT set - current_CTdate = handles.myinfo.AcquisitionDate - % Adapt date format to make it comparable - current_CTdate=datestr([current_CTdate(1:4),'-',... - current_CTdate(5:6),'-',current_CTdate(7:8)],'dd-mmm-yyyy') - % Compare CT's dates - if isequal(current_CTdate,CTdate_DB) - % The sCase already exits so the user will have to decide if the CT - % must be added to the case of it is already added. - set(handles.dataCheck_text,'String',... - ['Current CT matches in IPP, side and CTdate with others in the database']); - set(handles.dataCheck_panel,'BackgroundColor','r'); - set(handles.patient_num,'String',sprintf('%s',string(handles.current_sCase))); - else - % The user must check if the current CT set corresponds to a - % post-op shoulder - set(handles.dataCheck_text,'String',... - ['Check if the CT is from a post-op. Current CT matches in IPP, side']); - set(handles.dataCheck_panel,'BackgroundColor','r'); - set(handles.patient_num,'String',sprintf('%s',string(handles.current_sCase))); - end - else - % This is a new sCase!! So we write a short message and set the sCase - set(handles.dataCheck_text,'String', sprintf('This is a new case')); - set(handles.dataCheck_panel,'BackgroundColor','g'); - handles.current_sCase=new_sCase; - set(handles.patient_num,'String',sprintf('%s',string(handles.current_sCase))); - end -end - -F1=extractBefore(char(handles.current_sCase),2); -F2=extractBetween(char(handles.current_sCase),2,2); -F3=extractBetween(char(handles.current_sCase),3,3); - -current_dir = cd(char(strcat(handles.base_dir,'/',F1,'/',F2,'/',F3))); % saving current directory and changing to the output dir -output_dir = pwd; % needed to update the output directory -cd(current_dir); % back to the current directory -set(handles.output_dir,'String',output_dir); -% set(handles.output_dir,'String',strcat(handles.base_dir,F1,'/',F2,'/',F3));%sprintf('%s%s\%s\%s',base_dir,F1,F2,F3)); -waitbar(1,wb,'Checking Excel Database'); -guidata(hObject,handles); - - -function manual_case_selection_Callback(hObject, eventdata, handles) -%% --- Executes on button press in manual_case_selection. -% hObject handle to manual_case_selection (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sCase_dir = uigetdir(handles.base_dir); -set(handles.output_dir,'String',sCase_dir); -update_readme_Callback(handles.update_readme,eventdata,handles); -warndlg('Please uptade the sCase.id accordingly with the chosen output directory') -guidata(hObject,handles); - - -function patient_num_Callback(hObject, eventdata, handles) -%% Executes with 'Enter' in patient_num -% hObject handle to patient_num (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of patient_num as text -% str2double(get(hObject,'String')) returns contents of patient_num as a double - -% The output directory is stablish by the automatic Check of the DB or the -% manual selection. Hence, here we only check whether the sCase number -% matches with the selected output directory -% From "patient_num" which corresponds to sCase number -patient_num = get(handles.patient_num,'String'); % Get the sCase number -F0=char(extractBefore(char(patient_num),1)) -F0=char(extractBefore(char(patient_num),2)) % Extract the 'N' or 'P' -F1=char(extractBetween(char(patient_num),2,2)) % Extract the first digit (1 to 9) -F2=char(extractBetween(char(patient_num),3,3)) % Extract the second digit (0to9) -% From "output_dir" which corresponds to output directory -output_dir = get(handles.output_dir,'String'); % Get the ourput directory -L = length(output_dir); % lenght of the string that contains the directory -D0=char(extractBetween(char(output_dir),L-4,L-4)) % Extact the 'N' or 'P' -D1=char(extractBetween(char(output_dir),L-2,L-2)) % Extract the first digit (1 to 9) -D2=char(extractAfter(char(output_dir),L-1)) % Extract the second digit (0 to 9) - -if F0==D0 & F1==D1 & F2==D2 - handles.enable_importation = 1 -else - handles.enable_importation = 0 - warndlg('Importation cancelled. The sCase (patient number) must be consistant with the Output Directory') -end - -guidata(hObject,handles); - - - -%% --- Executes on slider movement. -function slider_2Dslice_Callback(hObject, eventdata, handles) -% hObject handle to slider_2Dslice (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'Value') returns position of slider -% get(hObject,'Min') and get(hObject,'Max') to determine range of slider -handles.slice = int32(get(hObject,'Value')); -set(handles.slice_num, 'String', handles.slice); -handles.mydicom(:,:,handles.slice) = handles.dicomSet(handles.slice).data; -axes(handles.axes_2Dviewer) % Set current axes -imshow(handles.mydicom(:,:,handles.slice), [handles.CTmin handles.CTmax]) -guidata(hObject,handles); - - -function Import2database_Callback(hObject, eventdata, handles) -%% --- Executes on button press in Import2database. -% hObject handle to Import2database (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -sortPictures = 1; - -set(handles.info_text, 'String', 'Preparing DICOM images to be imported...'); -drawnow - -% Warning message in info panel when any patient number is found -if isempty(get(handles.patient_num,'String')) - set(handles.info_text, 'ForegroundColor', 'red', 'FontWeight', 'bold', 'String', 'Please give a patient number') - return -else - patient = get(handles.patient_num,'String'); -end - -% W -if isempty(get(handles.output_dir,'String')) - outputdir = uigetdir; - if outputdir - set(handles.output_dir,'String', outputdir); - end -else - outputdir = get(handles.output_dir,'String'); -% outputdir = outputdir{1}; -end - -if ~outputdir - set(handles.info_text, 'ForegroundColor', 'red', 'FontWeight', 'bold',... - 'String', 'Please select an output directoy'); - return -end - -set(handles.info_text, 'ForegroundColor', 'black', 'FontWeight', 'normal'); - -% Create name string -newname = [patient, '-', handles.dicomSet(1).PatientID, '_',... - handles.dicomSet(1).PatientName.FamilyName(1),... - handles.dicomSet(1).PatientName.GivenName(1)]; -if get(handles.radiobutton_sharp,'Value') - newname = [newname, '-bone.']; -elseif get(handles.radiobutton_smooth,'Value') - newname = [newname, '-soft.']; -else - newname = [newname, '.']; -end - -% Create output directory -% outputdir = sprintf('%s%s%s%s%s%s%s%s%s%s%s',outputdir,'/', patient,'-',... -% handles.dicomSet(1).PatientID,'/','CT-',patient,'-',... -% handles.dicomSet(1).PatientID,handles.CTlabel_text.String,'/dicom/'); -suggested_outputdir = sprintf('%s%s%s%s%s%s%s%s%s%s%s',outputdir,'/', patient,'-',... - handles.dicomSet(1).PatientID,'/','CT-',patient,'-',... - handles.dicomSet(1).PatientID,handles.CTlabel_text.String,'/dicom/'); -if exist(suggested_outputdir)==7 - outputdir = sprintf('%s%s%s%s%s%s%s%s%s%s%s',outputdir,'/', patient,'-',... - handles.dicomSet(1).PatientID,'/','CT-',patient,'-',... - handles.dicomSet(1).PatientID,'xxx','/dicom/'); -else - outputdir = suggested_outputdir; -end -mkdir(outputdir); - - -% Sort pictures in correct order -if sortPictures == 1 - for h = 1:handles.N - infoTemp = dicominfo(sprintf('%s%s', handles.dicomdir,... - char(handles.dicomlist(h))),'UseDictionaryVR',true); - SliceLoc(h,1) = h; -% sprintf('%s%s', handles.dicomdir, char(handles.dicomlist(h))); - SliceLoc(h,2) = infoTemp.SliceLocation; - end - SliceSorted = sortrows(SliceLoc,2); -end -guidata(hObject,handles); - -% Read all data -% at the importation we set the dicomSet as definitively sorted -handles.dicomSet=handles.dicomSetSorted; % with this sentence we could avoid the very previous sorting... -for i = 1:handles.N - str = sprintf('Copying dicom...\n%d / %d\n', i, handles.N); - set(handles.info_text, 'String', str); - drawnow - - % This replace the Given Name by the patient inicials and kernel info - if get(handles.radiobutton_sharp,'Value') - handles.dicomSet(i).PatientName.GivenName = ... - [handles.dicomSet(i).PatientName.FamilyName(1),... - handles.dicomSet(i).PatientName.GivenName(1), '_bone']; - elseif get(handles.radiobutton_smooth,'Value') - handles.dicomSet(i).PatientName.GivenName = ... - [handles.dicomSet(i).PatientName.FamilyName(1),... - handles.dicomSet(i).PatientName.GivenName(1), '_soft']; - else - handles.dicomSet(i).PatientName.GivenName = ... - [handles.dicomSet(i).PatientName.FamilyName(1),... - handles.dicomSet(i).PatientName.GivenName(1)]; - end - % This replace the Given Name by the IPP - handles.dicomSet(i).PatientName.FamilyName = [patient, '_',... - handles.dicomSet(1).PatientID]; - - % Importation - dicomwrite(handles.dicomSet(i).data,[outputdir, newname,... - sprintf('%04d',i), '.dcm'], handles.dicomSet(i)); -end -guidata(hObject,handles); - -% Create readme.txt file if it does not exist already -localDir = string(get(handles.output_dir,'String')); -localDir = sprintf('%s%s%s%s%s%s',localDir,'/', patient,'-', handles.dicomSet(1).PatientID,'/'); -if ~exist(sprintf('%s%s',localDir,'readme.txt'), 'file') - readme_file=fopen(sprintf('%s%s',localDir,'readme.txt'), 'wt'); - fprintf(readme_file,sprintf('%s%s%s %s %s\r\n',patient,'-',... - handles.dicomSet(1).PatientID,handles.initials_text.String,... - handles.shoulder_side)); - fprintf(readme_file,sprintf('\r\n%s',get(handles.text_readme,'String'))); - fclose(readme_file); -else - readme_file=fopen(sprintf('%s%s',localDir,'readme.txt'), 'at'); % opening to append text - fprintf(readme_file,sprintf('\r\n%s',get(handles.text_readme,'String'))); - fclose(readme_file); -end - -set(handles.info_text, 'String', 'Copied'); -guidata(hObject,handles); - - -function output_dir_Callback(hObject, eventdata, handles) -%% -% hObject handle to output_dir (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of output_dir as text -% str2double(get(hObject,'String')) returns contents of output_dir as a double -guidata(hObject,handles); - - - -function CTlabel_text_Callback(hObject, eventdata, handles) -% hObject handle to CTlabel_text (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of CTlabel_text as text -% str2double(get(hObject,'String')) returns contents of CTlabel_text as a double -update_readme_Callback(handles.update_readme,eventdata,handles); -guidata(hObject,handles); - - -function output_dir_CreateFcn(hObject, eventdata, handles) -%% --- Executes during object creation, after setting all properties. -% hObject handle to output_dir (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'),... - get(0,'defaultUicontrolBackgroundColor')); - set(hObject,'BackgroundColor','white'); -end -guidata(hObject,handles); - - - -%% --- Executes during object creation, after setting all properties. -function info_text_CreateFcn(hObject, eventdata, handles) -% hObject handle to info_text (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -guidata(hObject,handles); - - -%% --- Executes during object creation, after setting all properties. -function DicomInfoBox_CreateFcn(hObject, eventdata, handles) -% hObject handle to info_text (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -guidata(hObject,handles); - - - - -%% --- Executes during object creation, after setting all properties. -function slider_3Dviewer_CreateFcn(hObject, eventdata, handles) -% hObject handle to slider_3Dviewer (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: slider controls usually have a light gray background. -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end -guidata(hObject,handles); - - -%% --- Executes on button press in DicomDetails. -function DicomDetails_Callback(hObject, eventdata, handles) -% hObject handle to DicomDetails (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -try - load tempInfo.mat - tempInfo - handles.DicomInfoBox.String = ['Dicom Info: ',... - 'Patient Sex: ', handles.dicomSet(1).PatientSex,... - '. Birthday: ', handles.dicomSet(1).PatientBirthDate]; -catch exception - "Dicom info not available" -end -guidata(hObject,handles); - - -% function checkbox_IPP_Callback(hObject, eventdata, handles) -% %% --- Executes on button press in checkbox_IPP. -% % hObject handle to checkbox_IPP (see GCBO) -% % eventdata reserved - to be defined in a future version of MATLAB -% % handles structure with handles and user data (see GUIDATA) -% -% % Hint: get(hObject,'Value') returns toggle state of checkbox_IPP -% if get(hObject,'Value') %the IPP must be added to the readme line -% try -% handles.readme.IPP = string(handles.sCase); -% ['IPP info to be added to the Readme line := ' handles.readme.IPP] -% catch except -% sprintf('%s%s','Error identifier: ',except.identifier) -% ['IPP info failed to be added to the Readme line.'] -% handles.readme.IPP = ''; -% end -% else -% handles.readme.IPP = ''; -% ['IPP info not present in Readme line'] -% end -% % update_infoFields(handles); -% update_readme_Callback(handles.update_readme,eventdata,handles); -% guidata(hObject,handles); - - -function checkbox_CTdate_Callback(hObject, eventdata, handles) -%% --- Executes on button press in checkbox_CTdate. -% hObject handle to checkbox_CTdate (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of checkbox_CTdate -if get(hObject,'Value') %the IPP must be added to the readme line - try - handles.readme.CTdate = string(handles.myinfo(1).AcquisitionDate); - ['CTdate info to be added to the Readme line := ' handles.readme.CTdate] - catch except - sprintf('%s%s','Error identifier: ',except.identifier) - ['CTdate info failed to be added to the Readme line.'] - handles.readme.CTdate = ''; - end -else - handles.readme.CTdate = ''; - ['CTdate info not present in Readme line'] -end -% update_infoFields(handles); -update_readme_Callback(handles.update_readme,eventdata,handles); -guidata(hObject,handles); - - -function checkbox_resolution_Callback(hObject, eventdata, handles) -%% --- Executes on button press in checkbox_resolution. -% hObject handle to checkbox_resolution (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of checkbox_resolution -if get(hObject,'Value') %the IPP must be added to the readme line - try - handles.readme.resolution = string(handles.myinfo(1).PixelSpacing(1)); - ['Resolution info to be added to the Readme line := ' handles.readme.resolution] - catch except - sprintf('%s%s','Error identifier: ',except.identifier) - ['Resolution info failed to be added to the Readme line.'] - handles.readme.resolution = ''; - end -else - handles.readme.resolution = ''; - ['Resolution info not present in Readme line'] -end -% update_readme_line(handles) -% update_infoFields(handles); -update_readme_Callback(handles.update_readme,eventdata,handles); -guidata(hObject,handles); - - -function radiobutton_shoulder_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_shoulder. -% hObject handle to radiobutton_shoulder (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_shoulder -handles.body = 'Shoulder'; -set(handles.checkbox_contralateral,'Value',0); -handles.contralateral=''; -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - -function radiobutton_elbow_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_elbow. -% hObject handle to radiobutton_elbow (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_elbow -handles.body = 'Elbow'; -set(handles.checkbox_contralateral,'Value',0); -handles.contralateral=''; -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - - -function radiobutton_thorax_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_thorax. -% hObject handle to radiobutton_thorax (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_thorax -handles.body = 'Thorax'; -set(handles.checkbox_contralateral,'Value',0); -handles.contralateral=''; -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - - -function checkbox_contralateral_Callback(hObject, eventdata, handles) -%% --- Executes on button press in checkbox_contralateral. -% hObject handle to checkbox_contralateral (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of checkbox_contralateral -if get(handles.checkbox_contralateral,'Value') - handles.contralateral = ['Contralateral ']; -else - handles.contralateral = ''; -end -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - - -function radiobutton_otherBody_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_otherBody. -% hObject handle to radiobutton_otherBody (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_otherBody -set(handles.checkbox_contralateral,'Value',0); -handles.contralateral=''; -set(handles.edit_otherBody,'Enable','On'); -handles.body = get(handles.edit_otherBody,'String'); -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - -function edit_otherBody_Callback(hObject, eventdata, handles) -%% -% hObject handle to edit_otherBody (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of edit_otherBody as text -% str2double(get(hObject,'String')) returns contents of edit_otherBody as a double -handles.body = get(handles.edit_otherBody,'String'); -guidata(hObject,handles); - - -function radiobutton_sharp_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_sharp. -% hObject handle to radiobutton_sharp (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_sharp -% -% if get(hObject,'Value') -% set(handles.radiobutton_none,'Value',0); -% set(handles.radiobutton_smooth,'Value',0); -% else -% set(hObject,'Value',1); -% end -handles.kernel='Sharp'; -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - -function radiobutton_smooth_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_smooth. -% hObject handle to radiobutton_smooth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_smooth -% -% if get(hObject,'Value') -% set(handles.radiobutton_none,'Value',0); -% set(handles.radiobutton_sharp,'Value',0); -% else -% set(hObject,'Value',1); -% end -handles.kernel='Smooth'; -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - -function radiobutton_none_Callback(hObject, eventdata, handles) -%% --- Executes on button press in radiobutton_none. -% hObject handle to radiobutton_none (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_none -handles.kernel='none'; -warndlg(char("IMPORTANT: The operator must choose between 'Sharp (Bone)' or 'Smooth (Soft Tissue)'")); -update_readme_Callback(handles.update_readme,eventdata,handles); -guidata(hObject,handles); - - -function checkbox_with_phantoms_Callback(hObject, eventdata, handles) -%% --- Executes on button press in checkbox_with_phantoms. -% hObject handle to checkbox_with_phantoms (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of checkbox_with_phantoms -handles.phantoms = 'with'; -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - - -function radiobutton_without_phantoms_Callback(hObject, eventdata, handles) -% --- Executes on button press in radiobutton_without_phantoms. -% hObject handle to radiobutton_without_phantoms (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hint: get(hObject,'Value') returns toggle state of radiobutton_without_phantoms -handles.phantoms = 'without'; -update_readme_Callback(handles.update_readme, eventdata, handles); -guidata(hObject,handles); - - -function edit_extra_Callback(hObject, eventdata, handles) -%% -% hObject handle to edit_extra (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'String') returns contents of edit_extra as text -% str2double(get(hObject,'String')) returns contents of edit_extra as a double -guidata(hObject,handles); - - -function update_readme_Callback(hObject, eventdata, handles) -%% --- Executes on button press in update_readme. -% hObject handle to update_readme (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -if ~isfield(handles,'shoulder_side') - handles.shoulder_side = '*Sh_Side*'; -end -if ~isfield(handles,'acquisition_stage') - handles.acquisition_stage = '*Pre-o-Post_op*'; -end -% handles.patient_num always exists -% handles.IPP_text -% handles.CTdate_text -% handles.Resolution_text -% handles.CTlabel_text -if ~isfield(handles,'body') - handles.body = '*body*'; -end -if ~isfield(handles,'kernel') - handles.kernel = '*kernel*'; -end -if ~isfield(handles,'phantoms') - handles.phantoms = '*phantoms*'; -end -if ~isfield(handles,'contralateral') - handles.contralateral = ''; -end -if ~isfield(handles,'N') - handles.N = 0; -end - -% choosing handles.CTlabel_text -switch handles.acquisition_stage - case 'Preop' - if ~get(handles.checkbox_contralateral,'Value') - switch handles.body - case 'Shoulder' - switch handles.phantoms - case 'without' - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-1'; - case 'Smooth' - handles.CTlabel_text.String = '-2'; - otherwise - handles.CTlabel_text.String = '-xxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - case 'with' - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-3'; - case 'Smooth' - handles.CTlabel_text.String = '-4'; - otherwise - handles.CTlabel_text.String = '-xxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - otherwise - handles.CTlabel_text.String = '-xxx'; - end - case 'Elbow' - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-5'; - case 'Smooth' - handles.CTlabel_text.String = '-6'; - otherwise - handles.CTlabel_text.String = '-xxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - case 'Thorax' - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-7'; - case 'Smooth' - handles.CTlabel_text.String = '-8'; - otherwise - handles.CTlabel_text.String = '-xxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - otherwise - handles.CTlabel_text.String = '-x11'; - end - else - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-9'; - case 'Smooth' - handles.CTlabel_text.String = '-10'; - otherwise - handles.CTlabel_text.String = '-xxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - end - case 'Postop' - if ~get(handles.checkbox_contralateral,'Value') - switch handles.body - case 'Shoulder' - switch handles.phantoms - case 'without' - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-p1'; - case 'Smooth' - handles.CTlabel_text.String = '-p2'; - otherwise - handles.CTlabel_text.String = '-pxxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - case 'with' - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-p3'; - case 'Smooth' - handles.CTlabel_text.String = '-p4'; - otherwise - handles.CTlabel_text.String = '-pxxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - otherwise - handles.CTlabel_text.String = '-pxxx'; - end - case 'Elbow' - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-p5'; - case 'Smooth' - handles.CTlabel_text.String = '-p6'; - otherwise - handles.CTlabel_text.String = '-pxxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - case 'Thorax' - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-p7'; - case 'Smooth' - handles.CTlabel_text.String = '-p8'; - otherwise - handles.CTlabel_text.String = '-pxxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - otherwise - handles.CTlabel_text.String = '-px11'; - end - else - switch handles.kernel - case 'Sharp' - handles.CTlabel_text.String = '-p9'; - case 'Smooth' - handles.CTlabel_text.String = '-p10'; - otherwise - handles.CTlabel_text.String = '-pxxx'; - warndlg('Operator must choose between Sharp or Smooth kernel'); - end - end - otherwise - handles.CTlabel_text.String = '-xxx'; -end - -RL = sprintf('%s%s%s%s%s %s %s %s %s %s %s %s %s ','CT-',... - handles.patient_num.String,'-',... - handles.IPP_text.String,... - handles.CTlabel_text.String,... - handles.contralateral,... - handles.body,... - handles.kernel,... - handles.phantoms,'phantoms',... - handles.Resolution_text.String,... - string(handles.N),'slices'),... - get(handles.edit_extra,'String'); -set(handles.text_readme,'String',RL); -guidata(hObject,handles); - - -function add_newSCase_excelDB_Callback(hObject, eventdata, handles) -%% --- Executes on button press in add_newSCase_excelDB. -% hObject handle to add_newSCase_excelDB (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Text info to the command window -sprintf('%s:\n%s, %s, %s, %s,\n%s, %s, %s,',"The parameters to write in the Excel Database are",... - "SCase_ID","SCase_idx","anonymity_IPP","anonymity_initials",... - "anonymity_bithDate","patient_gender","shoulder_side") - -% The file SCaseImport.xlsx must be located inside the subfolder -% xlsFromMatlab/ which is in the same directory of the main Database Excel -ExcelImport_fullname = sprintf('%s%s',handles.ExcelDB_path,"xlsFromMatlab/SCaseImport.xlsx"); -sprintf("%s%s", "Writting in file ", ExcelImport_fullname) - -% In order to avoid the repetition of any SCase we have to read and check -% the SCaseImport.xlsx file: -[~,txt,raw,dates]=xlsread(ExcelImport_fullname,'SCaseImport','','',@convertSpreadsheetExcelDates); -% Looking for the "desired new SCase" in the existing list of SCases of -% SCaseImport.xlsx -% Removing void rows -raw=raw(find(string(raw(:,1))~=''),:); -found_SCase_Index = find(string(raw(:,1))==handles.patient_num.String); -new_SCase_Index = length(string(raw(:,1)))+1; - -% If there is no coincidence we set the desired SCase as a new one and can -% allow to write the new line of Import Parameters. Otherwise we will ask -% to overwrite the existing line of parameters or doing nothing. -if isempty(found_SCase_Index) - SCase_Index = new_SCase_Index; -else - question = "The chosen SCase already exist. Do you want to overwrite it?"; - title = "WARNING: SCase repeated"; - btn1 = "Cancel"; - btn2 = "Overwrite"; - dfltbtn = "Cancel"; - answer = questdlg(question,title,btn1,btn2,dfltbtn); - % Handle response - switch answer - case "Overwrite" - SCase_Index = found_SCase_Index; - case "Cancel" - disp("new SCase parameter line aborted") - return; - otherwise - disp("new SCase parameter line aborted") - return; - end -end -% I don't know why this writting is taking a wrong ROW -rowNumber=SCase_Index; -new_SCase_ID = {handles.patient_num.String}; -% Wrtitting SCase_ID -SCaseCell=sprintf('%s%i','A',rowNumber); - % Security Check: avoiding doubling SCases -if isempty(find(string(handles.data.SCase_ID)==string(new_SCase_ID))) - "SCase_ID written" - xlswrite(ExcelImport_fullname,new_SCase_ID,'SCaseImport',SCaseCell) -else - "The selected SCase_ID is already present in the Database" - return -end -% Wrtitting SCase_idx -IdxCell=sprintf('%s%i','B',rowNumber); -xlswrite(ExcelImport_fullname,rowNumber,'SCaseImport',IdxCell) -% Wrtitting anonymity_IPP -IPP_number = str2num(handles.IPP_text.String); -IPPCell=sprintf('%s%i','C',rowNumber); -xlswrite(ExcelImport_fullname,IPP_number,'SCaseImport',IPPCell) -% Wrtitting anonymity_initials -Initials={extractBefore(extractAfter(handles.initials_text.String,'('),')')}; -InitialsCell=sprintf('%s%i','D',rowNumber); -xlswrite(ExcelImport_fullname,Initials,'SCaseImport',InitialsCell) -% Wrtitting anonymity_birthDate -BirthDate ={[handles.birthdate_text.String(1:4) ... - '-' handles.birthdate_text.String(5:6) ... - '-' handles.birthdate_text.String(7:8)]}; -BirthDateCell=sprintf('%s%i','E',rowNumber); -xlswrite(ExcelImport_fullname,BirthDate,'SCaseImport',BirthDateCell) -% Wrtitting patient_gender -GenderCell=sprintf('%s%i','F',rowNumber); -Patient_Gender = handles.gender_text.String; -xlswrite(ExcelImport_fullname,Patient_Gender,'SCaseImport',GenderCell) -% Wrtitting shoulder_side -ShSideCell=sprintf('%s%i','G',rowNumber); -Shoulder_Side = handles.shoulder_side(1); -xlswrite(ExcelImport_fullname,Shoulder_Side,'SCaseImport',ShSideCell) - -%launch 'dicominfoSCase.m' to update CTdicomInfo CSV and XLS -currentFolder=pwd; -cd([currentFolder '/..']) -dicominfoSCase % Lauched without arguments a avoid current error (1'20") -cd(currentFolder) -msgbox("Operation completed!. Remember to add manually SCase_ID and SCase_idx") - - -%% Internal functions - -function update_readme_line(handles) -%% -- Updates readme line -% Complete the line to be writen in the readme file as: -% CT-P454-513554-1 sharp shoulder without phantoms 0.351562 mm 137 slices -try - handles.readme.IPP = handle.myinfo.PatientID; - handles.readme.CTdate = handles.myinfo.AcquisitionDate; - handles.readme.CT_label = handles.CTlabel_text; - if handles.radiobutton_sharp - handles.readme.kernel = 'Sharp (BONE)'; - elseif handles.radiobutton_smooth - handles.readme.kernel = 'Smooth (SOFT)'; - else - handles.readme.kernel = 'None'; - end - - - handles.readme.line = ['CT-' handles.readme.IPP '-' handles.readme.CT_label... - ' ' handles.readme.kernel ' ' handles.readme.body ' '... - handles.readme.phantoms ' ' handles.readme.resolution ' ' ... - handles.readme.slices ' ' handles.readme.stage ' ' handles.readme.extra... - ' '] -catch except - sprintf('%s%s','Error identifier: ',except.identifier) - 'fields lacking' - -end -guidata(hObject,handles); - -function sortedST = sortStructByField(ST,field,handles) -try - "internal fuction activated" - STfields = fieldnames(ST); - STcell = struct2cell(ST); - sz = size(STcell); % Notice that this is a 3 dimensional array. - % For MxN structure array with P fields, the size - % of the converted cell array is PxMxN - - % Once it's a cell array, you can sort using sortrows: - - % Convert to a matrix - STcell = reshape(STcell, sz(1), []); % Px(MxN) - - % Make each field a column - STcell = STcell'; % (MxN)xP - - column=0 - % Sort by field - for k=1:length(STfields) - if isequal(STfields(k),field) - column = k; - end - end - % fieldName=char(STfields(1)) - % field=char(field) - % fieldColum = find(fieldName(1:length(field))==field) - if column == 0 - ['Warning: field ' char(field) ' not found in dicom metadata'] - sortedST = ST; - return - else - fieldColumn = column; - STcell = sortrows(STcell, fieldColumn); - - %And convert it back to a structure array: - - % Put back into original cell array format - STcell = reshape(STcell', sz); - - % Convert to Struct - STsorted = cell2struct(STcell, STfields, 1); - sortedST = STsorted; - end -catch except - except.identifier - except.message - ['exception arised during dicom sorting by field'] -end - - - -% function update_infoFields(hObject, handles) -% %% Updating CT labelling -% % if and(get(handles.patient_num,'String') ~='P###',exist([handles.output_dir '/readme'])==2) -% % set(handles.text_readme, "listo para leer") -% % end -% guidata(hObject,handles); - - -%% Functions to be removed - -function slider_2Dcontrast_Callback(hObject, eventdata, handles) -%% --- Executes on slider movement. -% hObject handle to slider_2Dcontrast (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'Value') returns position of slider -% get(hObject,'Min') and get(hObject,'Max') to determine range of slider - -if ~isfield(handles, 'mydicom'); - return -end - -handles.CTmax = (get(handles.slider_2Dbrightness,'Max') + get(handles.slider_2Dbrightness,'Min') - get(handles.slider_2Dbrightness,'Value')) + (get(hObject,'Max') - get(hObject,'Value'))/2; -handles.CTmin = (get(handles.slider_2Dbrightness,'Max') + get(handles.slider_2Dbrightness,'Min') - get(handles.slider_2Dbrightness,'Value')) - (get(hObject,'Max') - get(hObject,'Value'))/2; - -if handles.CTmax > handles.bigmax - handles.CTmax = handles.bigmax; -end - -if handles.CTmin < handles.bigmin - handles.CTmin = handles.bigmin; -end - -imshow(handles.mydicom(:,:,handles.slice), [handles.CTmin handles.CTmax]); - -guidata(hObject,handles) - - -function slider_2Dcontrast_CreateFcn(hObject, eventdata, handles) -%% --- Executes during object creation, after setting all properties. -% hObject handle to slider_2Dcontrast (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: slider controls usually have a light gray background. -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end -guidata(hObject,handles); - - -function slider_2Dbrightness_Callback(hObject, eventdata, handles) -%% --- Executes on slider movement. -% hObject handle to slider_2Dbrightness (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Hints: get(hObject,'Value') returns position of slider -% get(hObject,'Min') and get(hObject,'Max') to determine range of slider - -if ~isfield(handles, 'mydicom'); - return -end - -handles.CTmax = (get(hObject,'Max') + get(hObject,'Min')... - - get(hObject,'Value')) + (get(handles.slider_2Dcontrast,'Max')... - - get(handles.slider_2Dcontrast,'Value'))/2; -handles.CTmin = (get(hObject,'Max') + get(hObject,'Min')... - - get(hObject,'Value')) - (get(handles.slider_2Dcontrast,'Max')... - - get(handles.slider_2Dcontrast,'Value'))/2; - -if handles.CTmax > handles.bigmax - handles.CTmax = handles.bigmax; -end - -if handles.CTmin < handles.bigmin - handles.CTmin = handles.bigmin; -end - -imshow(handles.mydicom(:,:,handles.slice), [handles.CTmin handles.CTmax]); - -guidata(hObject,handles); - - -function slider_2Dbrightness_CreateFcn(hObject, eventdata, handles) -%% --- Executes during object creation, after setting all properties. -% hObject handle to slider_2Dbrightness (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: slider controls usually have a light gray background. -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end -guidata(hObject,handles); - - - diff --git a/ImportSCase/importSCaseb.fig b/ImportSCase/importSCaseb.fig deleted file mode 100644 index fed56e6..0000000 Binary files a/ImportSCase/importSCaseb.fig and /dev/null differ diff --git a/ImportSCase/tempInfo.mat b/ImportSCase/tempInfo.mat deleted file mode 100644 index f57e69f..0000000 Binary files a/ImportSCase/tempInfo.mat and /dev/null differ diff --git a/log/listSCase.log b/log/listSCase.log deleted file mode 100644 index d2f8032..0000000 --- a/log/listSCase.log +++ /dev/null @@ -1,11 +0,0 @@ -listSCase.log -Date: 01-Mar-2019 14:59:17 -Get list of all SCase with a valid dicom folder -N438 dicom directory is CT-2 -5 has no valid dicom directory -data has no valid dicom directory -data has no valid dicom directory -P550 dicom directory is CT-3 -P581 dicom directory is CT-3 -P582 dicom directory is CT-3 -Number of SCase: 1014 \ No newline at end of file diff --git a/log/measureSCase.log b/log/measureSCase.log deleted file mode 100644 index 8aadb70..0000000 --- a/log/measureSCase.log +++ /dev/null @@ -1,4 +0,0 @@ -measureSCase.log -Date: 18-Feb-2019 15:09:32Data directory not found, check config.txt - -List of SCase \ No newline at end of file