function varargout = VMAT(varargin)
% VMAT MATLAB code for VMAT.fig
% This program will analyze Volumetric-Modulated Arc Therapy (VMAT) QA
% EPID images and automatically calculate results.
%
% The images should follow the patterns described in Jorgensen et al
% (2011) in Medical Physics. Two tests are provided:
%
% --Gantry Speed
% &
% --Dose Rate MLC Speed
%
% A settings panel accesible through the File menu allows personal
% setting of the allowable tolerance.
%
% Questions/bugs/feature requests: jkerns100@gmail.com
% Edit the above text to modify the response to help VMAT
% Last Modified by GUIDE v2.5 23-Apr-2013 10:58:00
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @VMAT_OpeningFcn, ...
'gui_OutputFcn', @VMAT_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
% --- Executes just before VMAT is made visible.
function VMAT_OpeningFcn(hObject, eventdata, handles, varargin)
% 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 VMAT (see VARARGIN)
% Choose default command line output for VMAT
handles.output = hObject;
axis([handles.Openfieldplot handles.DMLCplot],'off')
handles.ratiotol = LoadOrSetPref('VMATsettings','ratiotol',3,false);
handles.isprocessed = false;
guidata(hObject, handles);
% --- Executes on button press in loadMLCimage.
function loadMLCimage_Callback(hObject, eventdata, handles)
% hObject handle to loadMLCimage (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
[filename, path]=uigetfile('*.dcm',...
'Select the VMAT DMLC image','Multiselect','off');
if filename == 0 % if user hits cancel
return
end
handles.DMLC = dicomread(fullfile(path,filename));
axes(handles.DMLCplot);
imshow(handles.DMLC,[]);
set(handles.Results,'BackgroundColor','w') %sets to white in case processing has made it green/red from previous computation
handles.isprocessed = false;
guidata(hObject,handles)
% --- Executes on button press in loadOpenfield.
function loadOpenfield_Callback(hObject, eventdata, handles)
% hObject handle to loadOpenfield (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
[filename, path]=uigetfile('*.dcm',...
'Select the Open field image','Multiselect','off');
if filename == 0 % if user hits cancel
return
end
cd(path) % matlab doesn't like this for deployed apps, but I don't know of another good way to do this, nor have I had problems so far
handles.OPEN = dicomread(fullfile(path,filename));
axes(handles.Openfieldplot);
imshow(handles.OPEN,[]);
set(handles.Results,'BackgroundColor','w')
handles.isprocessed = false;
guidata(hObject,handles)
%% Structure Field Initialization & grab user test choice
% --- Executes on button press in ProcessImages.
function ProcessImages_Callback(hObject, eventdata, handles)
% hObject handle to ProcessImages (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%error check if both images haven't been loaded
if ~isfield(handles,'DMLC') || ~isfield(handles,'OPEN')
warndlg('Both images have not yet been loaded in. Please do so before proceeding.','Load Images First')
return
end
axes(handles.DMLCplot);
imshow(handles.DMLC,[]);
% empties out matrices in event processing is done twice.
[handles.roi,handles.roistd,handles.hrect,handles.hresult] = deal([]);
%get test choice
choicelist = cellstr(get(handles.TestChoice,'String'));
handles.testchoice = choicelist(get(handles.TestChoice,'Value'));
%% MLC Speed Test
if strcmp(handles.testchoice,choicelist{2}); %2 = MLC Speed
% Positions of ROIs in DMLC image. These are the values to use if the Jorgensen
% test is performed.
handles.DmlcPos = {[150 10 45 370],[207 10 45 370],[265 10 45 370],[325 10 45 370]};
% Pull DMLC and Open ROIs out of DMLC Image. Also draws rectangles on DMLC
% image
[RawROIs, handles.hrect] = PullRois(handles);
% Actual calculation of individual ROI DMLC to OPEN ratio value and stand. dev.
[roi, roistd] = CalcRois(RawROIs);
handles.roi = roi; handles.roistd = roistd;
% Drawing of rectangles on DMLC image
handles.hresult{1} = text(173,90,sprintf('1.6 cm/s: %4.3f +/- %4.3f',roi{1},roistd{1}),'Rotation',-90,'Color','g','FontSize',14);
handles.hresult{2} = text(230,90,sprintf('2.4 cm/s: %4.3f +/- %4.3f',roi{2},roistd{2}),'Rotation',-90,'Color','g','FontSize',14);
handles.hresult{3} = text(288,90,sprintf('0.8 cm/s: %4.3f +/- %4.3f',roi{3},roistd{3}),'Rotation',-90,'Color','g','FontSize',14);
handles.hresult{4} = text(348,90,sprintf('0.4 cm/s: %4.3f +/- %4.3f',roi{4},roistd{4}),'Rotation',-90,'Color','g','FontSize',14);
% Displaying of results
string = sprintf('Results (Tol. +/-%1.0f%%):\n 1.6cm/s: %4.3f +/- %4.3f \n 2.4cm/s: %4.3f +/- %4.3f \n 0.8cm/s: %4.3f +/- %4.3f \n 0.4cm/s: %4.3f +/- %4.3f',...
handles.ratiotol,roi{1},roistd{1},roi{2},roistd{2},roi{3},roistd{3},roi{4},roistd{4});
set(handles.Results,'String',string)
% Check of ROI results to see if they pass tolerance. Turns text red for
% ROIs that fail
checkROIs(handles)
%% Dose-Rate Gantry-Speed Test
elseif strcmp(handles.testchoice,choicelist{1}); %1 = DRGS
% Positions of ROIs in DMLC image. These are static values if the Jorgensen
% test is performed.
handles.DmlcPos = {[148 10 26 370],[186 10 27 370],[224 10 27 370],[262 10 27 370],...
[300 10 27 370],[338 10 27 370],[377 10 27 370]};
% Pull DMLC and Open ROIs out of DMLC Image. Also draws rectangles on DMLC
% image
[RawROIs, handles.hrect] = PullRois(handles);
% Actual calculation of individual ROI DMLC to OPEN ratio value and stand. dev.
[roi, roistd] = CalcRois(RawROIs);
handles.roi = roi; handles.roistd = roistd;
% Drawing of text on DMLC image
handles.hresult{1} = text(162,100,sprintf('105 MU/min: %4.3f +/- %4.3f',roi{1},roistd{1}),'Rotation',-90,'Color','g','FontSize',12);
handles.hresult{2} = text(200,100,sprintf('210 MU/min: %4.3f +/- %4.3f',roi{2},roistd{2}),'Rotation',-90,'Color','g','FontSize',12);
handles.hresult{3} = text(238,100,sprintf('314 MU/min: %4.3f +/- %4.3f',roi{3},roistd{3}),'Rotation',-90,'Color','g','FontSize',12);
handles.hresult{4} = text(276,100,sprintf('417 MU/min: %4.3f +/- %4.3f',roi{4},roistd{4}),'Rotation',-90,'Color','g','FontSize',12);
handles.hresult{5} = text(314,100,sprintf('524 MU/min: %4.3f +/- %4.3f',roi{5},roistd{5}),'Rotation',-90,'Color','g','FontSize',12);
handles.hresult{6} = text(352,100,sprintf('592 MU/min: %4.3f +/- %4.3f',roi{6},roistd{6}),'Rotation',-90,'Color','g','FontSize',12);
handles.hresult{7} = text(390,100,sprintf('600 MU/min: %4.3f +/- %4.3f',roi{7},roistd{7}),'Rotation',-90,'Color','g','FontSize',12);
% Displaying of results
string = sprintf('Results (Tol. +/-%1.0f%%):\n 105MU/min: %4.3f +/- %4.3f \n 210MU/min: %4.3f +/- %4.3f \n 314MU/min: %4.3f +/- %4.3f \n 417MU/min: %4.3f +/- %4.3f \n 524MU/min: %4.3f +/- %4.3f \n 592MU/min: %4.3f +/- %4.3f \n 600MU/min: %4.3f +/- %4.3f',...
handles.ratiotol,roi{1},roistd{1},roi{2},roistd{2},roi{3},roistd{3},roi{4},roistd{4},roi{5},roistd{5},roi{6},roistd{6},roi{7},roistd{7});
set(handles.Results,'String',string)
% Check of ROI results to see if they pass tolerance. Turns text red for
% ROIs that fail
checkROIs(handles)
end
handles.isprocessed = true;
guidata(hObject,handles)
%% Pull ROIs out of Images
function [RawROIs, recthandles] = PullRois(handles)
% Pull DMLC and Open ROIs out of DMLC Image. Also draws rectangles on DMLC
% image
for i=1:numel(handles.DmlcPos)
RawROIs.dmlc.roi{i} = double(imcrop(handles.DMLC,handles.DmlcPos{i}));
RawROIs.open.roi{i} = double(imcrop(handles.OPEN,handles.DmlcPos{i}));
recthandles{i} = rectangle('Position',handles.DmlcPos{i},'EdgeColor','g');
end
% Calculate overall DMLC and OPEN image ROI average
RawROIs.dmlc.mean = mean(mean([RawROIs.dmlc.roi{:}]));
RawROIs.open.mean = mean(mean([RawROIs.open.roi{:}]));
%% Calculate ROI ratios and st. dev.
function [roi, roistd] = CalcRois(RawROIs)
% This function finds the ratio of mean response of the DMLC image to the
% response of the Open image. This ratio is then normalized to the overall
% ratio of normalized response of all ROIs of each the DMLC and Open image.
% Overall image normalization
ImageNorm = RawROIs.dmlc.mean/RawROIs.open.mean;
% Preallocation
[roi, roistd] = deal(cell(1,numel(RawROIs.dmlc.roi)));
% Since function is used for both MLC Speed and DRGS there are varying
% numbers of elements in RawROIs, thus a for loop for all elements
for i=1:numel(RawROIs.dmlc.roi)
roi{i} = mean(RawROIs.dmlc.roi{i}(:))/mean(RawROIs.open.roi{i}(:))/ImageNorm;
s = (RawROIs.dmlc.roi{i}./RawROIs.open.roi{i})/ImageNorm;
roistd{i} = std(s(:));
end
%% Check results for pass/fail
function checkROIs(handles)
if any([handles.roi{:}] < 1-handles.ratiotol/100 | [handles.roi{:}] > 1+handles.ratiotol/100)
B = find([handles.roi{:}] < 1-handles.ratiotol/100 | [handles.roi{:}] > 1+handles.ratiotol/100);
for i=1:numel(B)
set(handles.hresult{B(i)},'Color','r')
set(handles.hrect{B(i)},'EdgeColor','r')
end
set(handles.Results,'BackgroundColor','r')
else
set(handles.Results,'BackgroundColor','g')
end
%% Save to PDF
% --- Executes on button press in savetopdf.
function savetopdf_Callback(hObject, eventdata, handles)
% hObject handle to savetopdf (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%error check that images have been processed
if handles.isprocessed == false
warndlg('Images have not yet been loaded or processed. Please do so before continuing.')
return
end
[fileoutput, pathname] = uiputfile({'*.pdf','PDF (*.pdf)'},'Save VMAT QA Results...',['VMAT QA - ' date()]);
if fileoutput == 0 % if user hits cancel
return
end
if exist('export_fig') == 2 % if user has export_fig function...
export_fig(fullfile(pathname,fileoutput),'-painters','-q101','-pdf')
else
print(gcf,'-dpdf','-opengl','-r400','-loose',fullfile(pathname,fileoutput)); %#ok<MCPRT>
end
msgbox(['Report saved successively at ' fullfile(pathname,fileoutput)],'Report Saved','help')
% --------------------------------------------------------------------
function settings_Callback(hObject, eventdata, handles)
% hObject handle to settings (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
h = VMAT_settings;
waitfor(h);
handles.ratiotol = getappdata(0,'ratiotol');
guidata(hObject,handles)
%% GUI initialization and unused functions
% --- Executes during object creation, after setting all properties.
function TestChoice_CreateFcn(hObject, eventdata, handles)
% hObject handle to TestChoice (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: listbox 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 Results_CreateFcn(hObject, eventdata, handles)
% hObject handle to Results (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
% --- Outputs from this function are returned to the command line.
function varargout = VMAT_OutputFcn(hObject, eventdata, handles)
% 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;
% --------------------------------------------------------------------
function File_Callback(hObject, eventdata, handles)
% hObject handle to File (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% --- Executes on selection change in TestChoice.
function TestChoice_Callback(hObject, eventdata, handles)
% hObject handle to TestChoice (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: contents = cellstr(get(hObject,'String')) returns TestChoice contents as cell array
% contents{get(hObject,'Value')} returns selected item from TestChoice
% --- Executes when user attempts to close figure1.
function figure1_CloseRequestFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: delete(hObject) closes the figure
delete(hObject);