diff --git a/MatRad_Config.m b/MatRad_Config.m index cb4c8c253..ad6e5a60d 100644 --- a/MatRad_Config.m +++ b/MatRad_Config.m @@ -259,6 +259,7 @@ function setDefaultPropertiesForEduMode(obj) obj.devMode = false; obj.eduMode = true; + end function setDefaultGUIProperties(obj) diff --git a/dicom/matRad_importDicom.m b/dicom/matRad_importDicom.m index a8a3dac68..4c854e918 100644 --- a/dicom/matRad_importDicom.m +++ b/dicom/matRad_importDicom.m @@ -35,7 +35,8 @@ % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%[env, ~] = matRad_getEnvironment(); +[env, ~] = matRad_getEnvironment(); + %% if ~exist('dicomMetaBool','var') @@ -54,7 +55,7 @@ resolution.z = files.resz; % [mm] / lps coordinate system if files.useDoseGrid && isfield(files,'rtdose') % get grid from dose cube - if verLessThan('matlab','9') + if isOctave || verLessThan('matlab','9') doseInfo = dicominfo(files.rtdose{1,1}); else doseInfo = dicominfo(files.rtdose{1,1},'UseDictionaryVR',true); @@ -161,3 +162,21 @@ resultGUI.w = [resultGUI.w; [stf(i).ray.weight]']; end end + + +%% save ct, cst, pln, dose +matRadFileName = [files.ct{1,3} '.mat']; % use default from dicom +[FileName,PathName] = uiputfile('*','Save as...',matRadFileName); +if ischar(FileName) + % delete unnecessary variables + switch env + case 'MATLAB' + clearvars -except ct cst pln stf resultGUI FileName PathName; + save([PathName, FileName], '-regexp', '^(?!(FileName|PathName)$).','-v7'); + case 'OCTAVE' + clear -x ct cst pln stf resultGUI FileName PathName; + save([PathName, FileName],'-v6'); + end + % save all except FileName and PathName + +end diff --git a/dicom/matRad_importDicomRtss.m b/dicom/matRad_importDicomRtss.m index 5839b69ce..e8663e623 100644 --- a/dicom/matRad_importDicomRtss.m +++ b/dicom/matRad_importDicomRtss.m @@ -37,7 +37,7 @@ if nargin < 3 visBool = 0; end - +matRad_cfg = MatRad_Config.instance(); env = matRad_getEnvironment(); matRad_checkEnvDicomRequirements(env); isOctave = strcmp(env,'OCTAVE'); @@ -52,9 +52,17 @@ end % list the defined structures -listOfDefStructs = fieldnames(structInfo.StructureSetROISequence); +try + listOfDefStructs = fieldnames(structInfo.StructureSetROISequence); +catch + matRad_cfg.dispError('StructureSetROISequence not defined ') +end % list of contoured structures -listOfContStructs = fieldnames(structInfo.ROIContourSequence); +try + listOfContStructs = fieldnames(structInfo.ROIContourSequence); +catch + matRad_cfg.dispError('ROIContourSequence not defined ') +end %% process structure data numOfDefStructs = numel(listOfDefStructs); @@ -86,11 +94,11 @@ listOfSlices = fieldnames(structInfo.ROIContourSequence.(... listOfContStructs{i}).ContourSequence); else - warning(['Contour ' structures(i).structName ' is empty']) + matRad_cfg.dispWarning(['Contour ' structures(i).structName ' is empty']) continue; end else - warning(['Contour ' structures(i).structName ' is empty']) + matRad_cfg.dispWarning(['Contour ' structures(i).structName ' is empty']) continue; end @@ -113,12 +121,12 @@ % sanity check 1 if numel(unique(structZ)) > 1 - error('Detected contour points outside of single slice\n'); + matRad_cfg.dispError('Detected contour points outside of single slice\n'); end % sanity check 2 if unique(structZ) > max(dicomInfo.SlicePositions) || unique(structZ) < min(dicomInfo.SlicePositions) - warning(['Omitting contour data for ' structures(i).structName ' at slice position ' num2str(unique(structZ)) 'mm - no ct data available.\n']); + matRad_cfg.dispWarning(['Omitting contour data for ' structures(i).structName ' at slice position ' num2str(unique(structZ)) 'mm - no ct data available.\n']); else structures(i).item(j).points = [structX, structY, structZ]; end diff --git a/dicom/matRad_scanDicomImportFolder.m b/dicom/matRad_scanDicomImportFolder.m index b2c97c76a..9b66186f5 100644 --- a/dicom/matRad_scanDicomImportFolder.m +++ b/dicom/matRad_scanDicomImportFolder.m @@ -41,6 +41,7 @@ % dicom import needs image processing toolbox -> check if available available = matRad_checkEnvDicomRequirements(); +isOctave = strcmp(matRad_cfg.env,'OCTAVE'); if ~available matRad_cfg.dispError('Image processing toolbox / packages not available!'); diff --git a/examples/matRad_example2_photons.m b/examples/matRad_example2_photons.m index 328276735..5c4ae303a 100644 --- a/examples/matRad_example2_photons.m +++ b/examples/matRad_example2_photons.m @@ -126,7 +126,7 @@ %% % Enable sequencing and disable direct aperture optimization (DAO) for now. % A DAO optimization is shown in a seperate example. -pln.propOpt.runSequencing = 1; +pln.propSeq.runSequencing = 1; pln.propOpt.runDAO = 0; %% diff --git a/examples/matRad_example3_photonsDAO.m b/examples/matRad_example3_photonsDAO.m index eb67ebc55..d93f4fa3a 100644 --- a/examples/matRad_example3_photonsDAO.m +++ b/examples/matRad_example3_photonsDAO.m @@ -64,8 +64,8 @@ %% % Enable sequencing and direct aperture optimization (DAO). -pln.propOpt.runSequencing = 1; -pln.propOpt.runDAO = 1; +pln.propSeq.runSequencing = true; +pln.propOpt.runDAO = true; %% Generate Beam Geometry STF stf = matRad_generateStf(ct,cst,pln); @@ -90,7 +90,7 @@ % order to modulate the intensity of the beams with multiple static % segments, so that translates each intensity map into a set of deliverable % aperture shapes. -resultGUI = matRad_siochiLeafSequencing(resultGUI,stf,dij,5); +resultGUI = matRad_sequencing(resultGUI,stf,dij,pln); %% DAO - Direct Aperture Optimization % The Direct Aperture Optimization is an optimization approach where we diff --git a/examples/matRad_example4_photonsMC.m b/examples/matRad_example4_photonsMC.m index e6e34fbe3..63a9ac8a4 100644 --- a/examples/matRad_example4_photonsMC.m +++ b/examples/matRad_example4_photonsMC.m @@ -42,7 +42,7 @@ pln.propStf.bixelWidth = 10; pln.propStf.numOfBeams = numel(pln.propStf.gantryAngles); pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct,0); -pln.propOpt.runSequencing = 0; +pln.propSeq.runSequencing = 0; pln.propOpt.runDAO = 0; % dose calculation settings diff --git a/examples/matRad_example5_protons.m b/examples/matRad_example5_protons.m index 0d743fe82..dfb0e89fb 100644 --- a/examples/matRad_example5_protons.m +++ b/examples/matRad_example5_protons.m @@ -70,7 +70,7 @@ pln.propStf.numOfBeams = numel(pln.propStf.gantryAngles); pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct,0); pln.propOpt.runDAO = 0; -pln.propOpt.runSequencing = 0; +pln.propSeq.runSequencing = 0; % dose calculation settings pln.propDoseCalc.doseGrid.resolution.x = 3; % [mm] diff --git a/examples/matRad_example6_protonsNoise.m b/examples/matRad_example6_protonsNoise.m index 617205353..37499d024 100644 --- a/examples/matRad_example6_protonsNoise.m +++ b/examples/matRad_example6_protonsNoise.m @@ -47,7 +47,7 @@ pln.propStf.numOfBeams = numel(pln.propStf.gantryAngles); pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct,0); pln.propOpt.runDAO = 0; -pln.propOpt.runSequencing = 0; +pln.propSeq.runSequencing = 0; % dose calculation settings pln.propDoseCalc.doseGrid.resolution.x = 3; % [mm] diff --git a/examples/matRad_example7_carbon.m b/examples/matRad_example7_carbon.m index 550f4c205..c0eff961e 100644 --- a/examples/matRad_example7_carbon.m +++ b/examples/matRad_example7_carbon.m @@ -66,7 +66,7 @@ pln.propStf.numOfBeams = numel(pln.propStf.gantryAngles); pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct,0); pln.propOpt.runDAO = 0; -pln.propOpt.runSequencing = 0; +pln.propSeq.runSequencing = 0; % dose calculation settings pln.propDoseCalc.doseGrid.resolution.x = 3; % [mm] diff --git a/gui/icons8-gamma-16.png b/gui/icons8-gamma-16.png new file mode 100644 index 000000000..2e8aa6d0f Binary files /dev/null and b/gui/icons8-gamma-16.png differ diff --git a/gui/matRad_MainGUI.m b/gui/matRad_MainGUI.m index c7fb92f4e..ec19417fb 100644 --- a/gui/matRad_MainGUI.m +++ b/gui/matRad_MainGUI.m @@ -16,6 +16,7 @@ StructureVisibilityWidget InfoWidget ViewingWidget + DVHStatsWidget eventListeners matRad_cfg = MatRad_Config.instance(); diff --git a/gui/matRad_Widget.m b/gui/matRad_Widget.m index 7493f4f31..604ac2725 100644 --- a/gui/matRad_Widget.m +++ b/gui/matRad_Widget.m @@ -1,4 +1,27 @@ classdef matRad_Widget < handle + + % matRad_Widget Main Class for GUI widget generation + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties (GetAccess = public , SetAccess = protected) widgetHandle %Holds parent widget handle diff --git a/gui/widgets/matRad_3DWidget.m b/gui/widgets/matRad_3DWidget.m index d02868ca2..fc94be71a 100644 --- a/gui/widgets/matRad_3DWidget.m +++ b/gui/widgets/matRad_3DWidget.m @@ -1,5 +1,27 @@ classdef matRad_3DWidget < matRad_ViewingWidget - + + % matRad_3DWidget class to generate GUI widget for 3D plan visualization + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties viewingWidgetHandle; end diff --git a/gui/widgets/matRad_DVHStatsWidget.m b/gui/widgets/matRad_DVHStatsWidget.m index 6b78a8080..b7915c5b8 100644 --- a/gui/widgets/matRad_DVHStatsWidget.m +++ b/gui/widgets/matRad_DVHStatsWidget.m @@ -1,20 +1,41 @@ classdef matRad_DVHStatsWidget < matRad_Widget - + + % matRad_DVHStatsWidget class to generate GUI widget display DVH and + % stats + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% properties - SelectedCube='physicalDose'; - + selectedDisplayOption; + lockUpdate = false; dvhWidgetHandle = []; statWidgetHandle = []; end - - events - - end - + methods - function this = matRad_DVHStatsWidget(handleParent) + function this = matRad_DVHStatsWidget(selectedDisplayOption,handleParent) + + matRad_cfg = MatRad_Config.instance(); - if nargin < 1 + if nargin < 2 + handleParent = figure(... 'Units','normalized',... 'Position',[0.005 0.05 0.495 0.9],... @@ -22,33 +43,60 @@ 'Color',matRad_cfg.gui.backgroundColor,... 'CloseRequestFcn',@(hObject,eventdata) figure1_CloseRequestFcn(this,hObject,eventdata),... 'IntegerHandle','off',... 'Colormap',[0 0 0.5625;0 0 0.625;0 0 0.6875;0 0 0.75;0 0 0.8125;0 0 0.875;0 0 0.9375;0 0 1;0 0.0625 1;0 0.125 1;0 0.1875 1;0 0.25 1;0 0.3125 1;0 0.375 1;0 0.4375 1;0 0.5 1;0 0.5625 1;0 0.625 1;0 0.6875 1;0 0.75 1;0 0.8125 1;0 0.875 1;0 0.9375 1;0 1 1;0.0625 1 1;0.125 1 0.9375;0.1875 1 0.875;0.25 1 0.8125;0.3125 1 0.75;0.375 1 0.6875;0.4375 1 0.625;0.5 1 0.5625;0.5625 1 0.5;0.625 1 0.4375;0.6875 1 0.375;0.75 1 0.3125;0.8125 1 0.25;0.875 1 0.1875;0.9375 1 0.125;1 1 0.0625;1 1 0;1 0.9375 0;1 0.875 0;1 0.8125 0;1 0.75 0;1 0.6875 0;1 0.625 0;1 0.5625 0;1 0.5 0;1 0.4375 0;1 0.375 0;1 0.3125 0;1 0.25 0;1 0.1875 0;1 0.125 0;1 0.0625 0;1 0 0;0.9375 0 0;0.875 0 0;0.8125 0 0;0.75 0 0;0.6875 0 0;0.625 0 0;0.5625 0 0],... - 'MenuBar','none',... + 'MenuBar','figure',... + 'ToolBar','figure',... 'Name','MatRad Plan Analysis',... 'NumberTitle','off',... 'HandleVisibility','callback',... - 'Tag','figure1'); + 'Tag','figDVHStat'); end - - this = this@matRad_Widget(handleParent); + this = this@matRad_Widget(handleParent); + this.selectedDisplayOption = selectedDisplayOption; + this.dvhWidgetHandle.selectedCube = selectedDisplayOption; + this.statWidgetHandle.selectedCube = selectedDisplayOption; + this.lockUpdate = true; + this.dvhWidgetHandle.lockUpdate = true; + this.statWidgetHandle.lockUpdate = true; + this.update(); + end function this=update(this,evt) - if nargin == 2 - doUpdate = this.checkUpdateNecessary({'resultGUI','cst','pln'},evt); - - if doUpdate - this.dvhWidgetHandle.update(evt); - this.statWidgetHandle.update(evt); + if this.lockUpdate + if nargin == 2 + doUpdate = this.checkUpdateNecessary({'resultGUI','cst','pln'},evt); + + if doUpdate + this.dvhWidgetHandle.update(evt); + this.statWidgetHandle.update(evt); + end + else + if ~strcmp(this.dvhWidgetHandle.selectedCube, this.selectedDisplayOption) + this.dvhWidgetHandle.selectedCube = this.selectedDisplayOption; + this.statWidgetHandle.selectedCube = this.selectedDisplayOption; + + end + this.dvhWidgetHandle = this.dvhWidgetHandle.update(); + this.statWidgetHandle = this.statWidgetHandle.update(); + if numel(this.dvhWidgetHandle.widgetHandle.Children) > 2 + this.removeOverlap(); + end + end - else - this.dvhWidgetHandle.update(); - this.statWidgetHandle.update(); end end - + function set.selectedDisplayOption(this,value) + this.selectedDisplayOption = value; + this.update(); + + end + function removeOverlap(this) + delete(this.dvhWidgetHandle.widgetHandle.Children(3)); % to clear previous plotted objects + delete(this.dvhWidgetHandle.widgetHandle.Children(3)); + end end - + methods(Access = protected) function this = createLayout(this) h88 = this.widgetHandle; @@ -58,7 +106,7 @@ p1 = uipanel(... 'Parent',h88,... 'BackgroundColor',matRad_cfg.gui.backgroundColor,... - 'Tag','uipanel1',... + 'Tag','panelDVH',... 'Clipping','off',... 'Position',[0.005 0.505 0.99 0.495],... 'FontName',matRad_cfg.gui.fontName,... @@ -69,7 +117,7 @@ p2 = uipanel(... 'Parent',h88,... 'BackgroundColor',matRad_cfg.gui.backgroundColor,... - 'Tag','uipanel2',... + 'Tag','panelStats',... 'Clipping','off',... 'Position',[0.005 0.005 0.99 0.495],... 'FontName',matRad_cfg.gui.fontName,... @@ -77,11 +125,12 @@ 'FontWeight',matRad_cfg.gui.fontWeight,... 'Title','Statistics'); - this.dvhWidgetHandle = matRad_DVHWidget(p1); - this.statWidgetHandle = matRad_StatisticsWidget(p2); - + this.dvhWidgetHandle = matRad_DVHWidget([],p1); + this.statWidgetHandle = matRad_StatisticsWidget([],p2); this.createHandles(); end + end -end \ No newline at end of file +end + diff --git a/gui/widgets/matRad_DVHWidget.m b/gui/widgets/matRad_DVHWidget.m index 861dd8376..cfa5759d8 100644 --- a/gui/widgets/matRad_DVHWidget.m +++ b/gui/widgets/matRad_DVHWidget.m @@ -1,105 +1,108 @@ classdef matRad_DVHWidget < matRad_Widget - + % matRad_DVHWidget class to generate GUI widget to display DVH + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% properties - SelectedCube='physicalDose'; - end - - events - + SelectedCube; + lockUpdate = false; + end - + methods - function this = matRad_DVHWidget(handleParent) - if nargin < 1 + function this = matRad_DVHWidget( SelectedCube,handleParent) + + matRad_cfg = MatRad_Config.instance(); + if nargin<2 handleParent = figure(... 'Units','normalized',... 'Position',[0.005 0.5 0.495 0.45],... 'Visible','on',... - 'Color',[0.501960784313725 0.501960784313725 0.501960784313725],... 'CloseRequestFcn',@(hObject,eventdata) figure1_CloseRequestFcn(this,hObject,eventdata),... - 'IntegerHandle','off',... + 'Color',matRad_cfg.gui.backgroundColor,... 'CloseRequestFcn',@(hObject,eventdata) figure1_CloseRequestFcn(this,hObject,eventdata),... + 'IntegerHandle','on',... 'Colormap',[0 0 0.5625;0 0 0.625;0 0 0.6875;0 0 0.75;0 0 0.8125;0 0 0.875;0 0 0.9375;0 0 1;0 0.0625 1;0 0.125 1;0 0.1875 1;0 0.25 1;0 0.3125 1;0 0.375 1;0 0.4375 1;0 0.5 1;0 0.5625 1;0 0.625 1;0 0.6875 1;0 0.75 1;0 0.8125 1;0 0.875 1;0 0.9375 1;0 1 1;0.0625 1 1;0.125 1 0.9375;0.1875 1 0.875;0.25 1 0.8125;0.3125 1 0.75;0.375 1 0.6875;0.4375 1 0.625;0.5 1 0.5625;0.5625 1 0.5;0.625 1 0.4375;0.6875 1 0.375;0.75 1 0.3125;0.8125 1 0.25;0.875 1 0.1875;0.9375 1 0.125;1 1 0.0625;1 1 0;1 0.9375 0;1 0.875 0;1 0.8125 0;1 0.75 0;1 0.6875 0;1 0.625 0;1 0.5625 0;1 0.5 0;1 0.4375 0;1 0.375 0;1 0.3125 0;1 0.25 0;1 0.1875 0;1 0.125 0;1 0.0625 0;1 0 0;0.9375 0 0;0.875 0 0;0.8125 0 0;0.75 0 0;0.6875 0 0;0.625 0 0;0.5625 0 0],... 'MenuBar','none',... 'Name','MatRad DVH',... 'NumberTitle','off',... 'HandleVisibility','callback',... - 'Tag','figure1',... + 'Tag','figDVH',... 'PaperSize',[20.99999864 29.69999902]); - + end - - this = this@matRad_Widget(handleParent); + this = this@matRad_Widget(handleParent); + this.SelectedCube = SelectedCube; - if evalin('base','exist(''resultGUI'')') - this.showDVH(); - end end function this=initialize(this) end function this=update(this,evt) + + if this.lockUpdate doUpdate = true; - if nargin == 2 - doUpdate = this.checkUpdateNecessary({'resultGUI','cst','pln'},evt); - end + if nargin == 2 + doUpdate = this.checkUpdateNecessary({'resultGUI','cst','pln'},evt); + end - if doUpdate && evalin('base','exist(''resultGUI'')') && evalin('base','exist(''cst'')') - this.showDVH(); - end + if doUpdate && evalin('base','exist(''resultGUI'')') && evalin('base','exist(''cst'')') + this.showDVH(); + if numel(this.widgetHandle.Children) > 2 + this.removeOverlap(); + end + end + end + end + + function removeOverlap(this) + delete(this.widgetHandle.Children(3)); % clear previous plotted objects from the figure + delete(this.widgetHandle.Children(3)); end + end - + methods(Access = protected) function this = createLayout(this) h88 = this.widgetHandle; - this.createHandles(); end end methods - function showDVH(this) - + + function set.SelectedCube(this,value) + this.SelectedCube=value; + end + function showDVH(this) + resultGUI = evalin('base','resultGUI'); - %Content = get(handles.popupDisplayOption,'String'); - - %SelectedCube = Content{get(handles.popupDisplayOption,'Value')}; - pln = evalin('base','pln'); - resultGUI_SelectedCube.physicalDose = resultGUI.(this.SelectedCube); - - if ~strcmp(pln.propOpt.bioOptimization,'none') - - %check if one of the default fields is selected - if sum(strcmp(this.SelectedCube,{'physicalDose','effect','RBE,','RBExDose','alpha','beta'})) > 0 - resultGUI_SelectedCube.physicalDose = resultGUI.physicalDose; - resultGUI_SelectedCube.RBExDose = resultGUI.RBExDose; - else - Idx = find(this.SelectedCube == '_'); - SelectedSuffix = this.SelectedCube(Idx(1):end); - resultGUI_SelectedCube.physicalDose = resultGUI.(['physicalDose' SelectedSuffix]); - resultGUI_SelectedCube.RBExDose = resultGUI.(['RBExDose' SelectedSuffix]); - end - end - cst = evalin('base','cst'); - - %matRad_indicatorWrapper(this.widgetHandle,cst,pln,resultGUI_SelectedCube); - - - if isfield(resultGUI_SelectedCube,'RBExDose') - doseCube = resultGUI_SelectedCube.RBExDose; - else - doseCube = resultGUI_SelectedCube.physicalDose; - end - + + doseCube = resultGUI.(this.SelectedCube); dvh = matRad_calcDVH(cst,doseCube,'cum'); - matRad_showDVH(axes(this.widgetHandle),dvh,cst,pln); - - end + this.widgetHandle.Children(2).Title.String = strrep(this.SelectedCube, '_',' '); + end end end \ No newline at end of file diff --git a/gui/widgets/matRad_GammaWidget.m b/gui/widgets/matRad_GammaWidget.m new file mode 100644 index 000000000..0d86ca6b7 --- /dev/null +++ b/gui/widgets/matRad_GammaWidget.m @@ -0,0 +1,560 @@ +classdef matRad_GammaWidget < matRad_Widget + % matRad_GammaWidget : GUI widget for gamma index based comparisons of + % dose cubes stored within resultGUI struct. + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + properties + SelectedDisplayOption1 = 'physicalDose' ; + SelectedDisplayOption2 = 'physicalDose' ; + SelectedDisplayAllOptions = strings; + criteria = [3 3]; + n = 0; + localglobal = 'global'; + resolution; + lockUpdate = false; + maxSlice; + slice; + gammaCube; + gammaPassRateCell; + updated = false; + + end + properties (Constant) + normalization = {'local','global'} ; + end + + events + + end + + methods + function this = matRad_GammaWidget(handleParent) + matRad_cfg = MatRad_Config.instance(); + if nargin < 2 + handleParent = figure(... + 'Units','normalized',... + 'Position',[0.1 0.1 0.7 0.7],... + 'Visible','on',... + 'Color',matRad_cfg.gui.backgroundColor,... 'CloseRequestFcn',@(hObject,eventdata) figure1_CloseRequestFcn(this,hObject,eventdata),... + 'IntegerHandle','off',... + 'Colormap',[0 0 0.5625;0 0 0.625;0 0 0.6875;0 0 0.75;0 0 0.8125;0 0 0.875;0 0 0.9375;0 0 1;0 0.0625 1;0 0.125 1;0 0.1875 1;0 0.25 1;0 0.3125 1;0 0.375 1;0 0.4375 1;0 0.5 1;0 0.5625 1;0 0.625 1;0 0.6875 1;0 0.75 1;0 0.8125 1;0 0.875 1;0 0.9375 1;0 1 1;0.0625 1 1;0.125 1 0.9375;0.1875 1 0.875;0.25 1 0.8125;0.3125 1 0.75;0.375 1 0.6875;0.4375 1 0.625;0.5 1 0.5625;0.5625 1 0.5;0.625 1 0.4375;0.6875 1 0.375;0.75 1 0.3125;0.8125 1 0.25;0.875 1 0.1875;0.9375 1 0.125;1 1 0.0625;1 1 0;1 0.9375 0;1 0.875 0;1 0.8125 0;1 0.75 0;1 0.6875 0;1 0.625 0;1 0.5625 0;1 0.5 0;1 0.4375 0;1 0.375 0;1 0.3125 0;1 0.25 0;1 0.1875 0;1 0.125 0;1 0.0625 0;1 0 0;0.9375 0 0;0.875 0 0;0.8125 0 0;0.75 0 0;0.6875 0 0;0.625 0 0;0.5625 0 0],... + 'MenuBar','none',... + 'Name','MatRad Gamma Analysis',... + 'NumberTitle','off',... + 'HandleVisibility','callback',... + 'Tag','GammaWidget'); + + end + this = this@matRad_Widget(handleParent); + + this.initialize(); + this.update(); + end + + function this = initialize(this) + if evalin( 'base', 'exist(''resultGUI'')' ) + resultGUI = evalin('base','resultGUI'); + resultnames = fieldnames(resultGUI) ; + j = 1; + for i = 1:numel(resultnames) + if ndims(resultGUI.(resultnames{i}))==3 + this.SelectedDisplayAllOptions(j) = resultnames{i}; + j=j+1; + end + end + % get and set display options + this.SelectedDisplayAllOptions = pad(this.SelectedDisplayAllOptions); + set(this.handles.popupSelectedDisplayOption1,'String',this.SelectedDisplayAllOptions); + set(this.handles.popupSelectedDisplayOption2,'String',this.SelectedDisplayAllOptions); + this.maxSlice = size(resultGUI.physicalDose,3); + this.slice = round(this.maxSlice/2); + end + if evalin( 'base', 'exist(''ct'')' ) + ct = evalin('base','ct'); + this.resolution = [ct.resolution.x, ct.resolution.y, ct.resolution.z]; + set(this.handles.editResolution,'String', regexprep(num2str(this.resolution),'\s+',' ')); + end + + set(this.handles.editGammaCrit,'String', regexprep(num2str(this.criteria),'\s+',' ')); + + end + + function this = update (this,~) + + if evalin( 'base', 'exist(''resultGUI'')' ) && this.lockUpdate + resultGUI = evalin('base','resultGUI'); + resultnames = fieldnames(resultGUI) ; + j = 1; + for i = 1:numel(resultnames) + if ndims(resultGUI.(resultnames{i}))==3 + this.SelectedDisplayAllOptions(j) = resultnames{i}; + j=j+1; + end + end + % get and set display options + this.SelectedDisplayAllOptions = pad(this.SelectedDisplayAllOptions); + set(this.handles.popupSelectedDisplayOption1,'String',this.SelectedDisplayAllOptions); + set(this.handles.popupSelectedDisplayOption2,'String',this.SelectedDisplayAllOptions); + + %slider options %CAN ALSO SET MIN AND MAX TO NONZERO SLICES + + if size(resultGUI.(this.SelectedDisplayOption1),3) == size(resultGUI.(this.SelectedDisplayOption2),3) + this.maxSlice = size(resultGUI.(this.SelectedDisplayOption1),3); + this.slice = round(this.maxSlice/2); + set(this.handles.sliderSlice,'Min',1,'Max',this.maxSlice,... + 'Value', this.slice, ... + 'SliderStep',[1 1]); + else + error('Mismatch in dimensions of selected cubes') + end + + + this.calcGamma(); + this.plotGamma(); + this.lockUpdate = false; + end + + end + % METHOD FOR WHEN WORKSPACE IS CHANGED + + function set.SelectedDisplayOption1(this, value) + this.SelectedDisplayOption1 = value; + this.lockUpdate = true; + this.update(); + end + + function set.SelectedDisplayOption2(this, value) + this.SelectedDisplayOption2 = value; + this.lockUpdate = true; + this.update(); + end + + function set.resolution(this,value) + this.resolution = value; + this.lockUpdate = true; + this.update(); + end + + function set.criteria(this,value) + this.criteria = value; + this.lockUpdate = true; + this.update(); + end + + function set.localglobal(this,value) + this.localglobal = value; + this.lockUpdate = true; + this.update(); + end + function set.n(this,value) + this.n = value; + this.lockUpdate = true; + this.update(); + end + + + end + + methods (Access = protected) + + function this = createLayout(this) + h20 = this.widgetHandle; + + matRad_cfg = MatRad_Config.instance(); + + %Create Main Grid layout + gridSize = [6 20]; + elSize = [0.9 0.6]; + [i,j] = ndgrid(1:gridSize(1),1:gridSize(2)); + gridPos = arrayfun(@(i,j) computeGridPos(this,[i j],gridSize,elSize),i,j,'UniformOutput',false); + + txt = sprintf('Choose Reference Cube from ResultGUI'); + h21 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Reference cube 1:',... + 'Tooltip',txt,... + 'Style','text',... + 'Position',gridPos{3,1},... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Tag','txtCube1',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + h22 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Please select ...',... + 'Tooltip',txt,... + 'Style','popupmenu',... + 'Value',1,... + 'Position',gridPos{4,1},... + 'BackgroundColor',matRad_cfg.gui.elementColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Callback',@(hObject,eventdata)popupSelectedDisplayOption1_Callback(this,hObject,eventdata),... + 'Tag','popupSelectedDisplayOption1',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + txt = sprintf('Choose Reference Cube from ResultGUI'); + h23 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Reference cube 2:',... + 'Tooltip',txt,... + 'Style','text',... + 'Position',gridPos{5,1},... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Tag','txtCube2',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + h24 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Please select ...',... + 'Tooltip',txt,... + 'Style','popupmenu',... + 'Value',1,... + 'Position',gridPos{6,1},... + 'BackgroundColor',matRad_cfg.gui.elementColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Callback',@(hObject,eventdata)popupSelectedDisplayOption2_Callback(this,hObject,eventdata),... + 'Tag','popupSelectedDisplayOption2',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + txt = sprintf('Gamma Criteria [mm %%]'); + h25 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Gamma Criteria [mm %]:',... + 'Tooltip',txt,... + 'Style','text',... + 'Position',gridPos{1,3},... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Tag','txtGammaCrit',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + h26 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','0 0',... + 'Tooltip',txt,... + 'Style','edit',... + 'Position',gridPos{1,4},... + 'BackgroundColor',matRad_cfg.gui.elementColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Callback',@(hObject,eventdata)editGammaCrit_Callback(this,hObject,eventdata),... + 'Tag','editGammaCrit',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + txt = sprintf('Resolution of cube [mm/voxel]'); + h27 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Resolution of cube [mm/voxel]:',... + 'Tooltip',txt,... + 'Style','text',... + 'Position',gridPos{1,5},... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Tag','txtResolution',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + h28 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','0 0 0',... + 'Tooltip',txt,... + 'Style','edit',... + 'Position',gridPos{1,6},... + 'BackgroundColor',matRad_cfg.gui.elementColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Callback',@(hObject,eventdata)editResolution_Callback(this,hObject,eventdata),... + 'Tag','editResolution',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + txt = sprintf('Number of interpolations, max suggested value is 3'); + h29 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Number of interpolations n:',... + 'Tooltip',txt,... + 'Style','text',... + 'Position',gridPos{1,7},... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Tag','txtInterpolations',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + h30 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','0',... + 'Tooltip',txt,... + 'Style','edit',... + 'Position',gridPos{1,8},... + 'BackgroundColor',matRad_cfg.gui.elementColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Callback',@(hObject,eventdata)editInterpolations_Callback(this,hObject,eventdata),... + 'Tag','editInterpolations',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + txt = sprintf('local and global normalizations'); + h31 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Type of normalization:',... + 'Tooltip',txt,... + 'Style','text',... + 'Position',gridPos{1,9},... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Tag','txtInterpolations',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + h32 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String',this.normalization,... + 'Tooltip',txt,... + 'Style','popupmenu',... + 'Value',1,... + 'Position',gridPos{1,10},... + 'BackgroundColor',matRad_cfg.gui.elementColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Callback',@(hObject,eventdata)popupNormalization_Callback(this,hObject,eventdata),... + 'Tag','popupRadMode',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + txt = sprintf('Choose which slice should be displayed in intensity plots'); + h33 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Slice',... + 'Tooltip',txt,... + 'Style','text',... + 'Position',gridPos{1,11},... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Tag','txtInterpolations',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + h34 = uicontrol(... + 'Parent',h20,... + 'Units','normalized',... + 'String','Slider',... + 'Tooltip','Choose which slice should be displayed in intensity plots',... + 'Style','slider',... + 'Callback',@(hObject,eventdata) sliderSlice_Callback(this,hObject,eventdata),... + 'BusyAction','cancel',... + 'Interruptible','off',... + 'Position',gridPos{1,12},... + 'BackgroundColor',matRad_cfg.gui.elementColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight,... + 'Tag','sliderSlice'); + + p1 = uipanel(... + 'Parent',h20,... + 'Units','normalized',... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'Tag','panelGammaIdx',... + 'Clipping','off',... + 'Position',[0.22 0.01 0.7 0.9],... + 'FontName',matRad_cfg.gui.fontName,... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontWeight',matRad_cfg.gui.fontWeight,... + 'Title','Gamma Analysis'); + + % h35 = uicontrol(... + % 'Parent',p1,... + % 'Units','normalized',... + % 'String','Gamma Pass Rate : ',... + % 'Tooltip',txt,... + % 'Style','text',... + % 'Position',[0.05 0.05 0.5 0.95],... + % 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + % 'ForegroundColor',matRad_cfg.gui.textColor,... + % 'Tag','txtGammaPass',... + % 'FontSize',matRad_cfg.gui.fontSize,... + % 'FontName',matRad_cfg.gui.fontName,... + % 'FontWeight',matRad_cfg.gui.fontWeight); + % + % h36 = uifigure(... + % 'Parent',p1,... + % 'Units','normalized',... + % 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + % 'Tag','figGammaMap',... + % 'Clipping','off',... + % 'Position',[0.05 0.05 1 1],... + % 'FontName',matRad_cfg.gui.fontName,... + % 'FontSize',matRad_cfg.gui.fontSize,... + % 'FontWeight',matRad_cfg.gui.fontWeight); + + this.createHandles(); + end + + end + methods (Access = private) + + function popupNormalization_Callback(this, hObject, eventdata) + contents = cellstr(get(hObject,'String')); + this.localglobal = contents{get(hObject,'Value')}; + + end + function popupSelectedDisplayOption1_Callback(this,hObject,eventdata) + contents = cellstr(get(hObject,'String')); + this.SelectedDisplayOption1 = strtrim(contents{get(hObject,'Value')}); + + end + function popupSelectedDisplayOption2_Callback(this,hObject,eventdata) + contents = cellstr(get(hObject,'String')); + this.SelectedDisplayOption2 = strtrim(contents{get(hObject,'Value')}); + + end + + function editResolution_Callback(this, hObject, ~) + t = sscanf (get(hObject,'String'), '%f'); + if numel(t) ~=3 + error('Resolution value error') + else + this.resolution = t; + end + + end + function editGammaCrit_Callback(this, hObject, ~) + t = sscanf (get(hObject,'String'), '%f'); + if numel(t) ~=2 + error('Gamma Criterion value error') + else + this.criteria = t; + end + + end + + function editInterpolations_Callback(this, hObject, ~) + t = str2double(get(hObject,'String')); + if ~isnumeric(t) + error('Number of Interpolations value error') + else + this.n = t; + end + + end + function sliderSlice_Callback(this,hObject, ~) + % hObject handle to sliderSlice (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 + %UpdatePlot(handles) + + this.slice = round(get(hObject,'Value')); + + this.plotGamma(); + end + + + end + + + methods + function calcGamma(this) + if evalin( 'base', 'exist(''resultGUI'')' ) + resultGUI = evalin('base','resultGUI'); + else + % no result cube + end + if evalin( 'base', 'exist(''cst'')' ) + cst = evalin('base','cst'); + else + %no cst + end + + + + [this.gammaCube,this.gammaPassRateCell] = matRad_gammaIndex(resultGUI.(this.SelectedDisplayOption1) ,resultGUI.(this.SelectedDisplayOption2),... + this.resolution,this.criteria,[],this.n,this.localglobal,cst); + + end + function plotGamma(this) + this.widgetHandle; + % visualize if applicable + + if ~isempty(this.slice) && ~isempty(this.gammaCube) + if isempty(this.handles.panelGammaIdx(1).Children) + ax = axes('Parent',this.handles.panelGammaIdx); + else + % overwrite previous plot in the panel + ax = this.handles.panelGammaIdx(1).Children(2); + + end + % ax = figure('Parent',this.handles.panelGammaIdx); + % set(ax,'Color',[1 1 1]); + imagesc(ax, this.gammaCube(:,:,this.slice)) + myColormap = matRad_getColormap('gammaIndex'); + + set(ax,'colormap',myColormap); + + colorbar(ax); + titletxt = {[num2str(this.gammaPassRateCell{1,2},5) '% of points > ' num2str(this.criteria(1)) ... + '% pass gamma criterion (' num2str(this.criteria(1)) '% / ' ... + num2str(this.criteria(2)) 'mm)']; ['with ' num2str(2^this.n-1) ' interpolation points']}; + title(ax, titletxt); + % set(this.handles.panelGammaIdx(1).Children(2),'Title',titletxt); + + + + % this.createHandles(); + end + end + + end + +end diff --git a/gui/widgets/matRad_InfoWidget.m b/gui/widgets/matRad_InfoWidget.m index ab0dfb8cd..c232961eb 100644 --- a/gui/widgets/matRad_InfoWidget.m +++ b/gui/widgets/matRad_InfoWidget.m @@ -1,5 +1,27 @@ classdef matRad_InfoWidget < matRad_Widget - + % matRad_InfoWidget class to generate GUI widget to display system and + % version information + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties end diff --git a/gui/widgets/matRad_LogoWidget.m b/gui/widgets/matRad_LogoWidget.m index 098a7941f..9d408aa91 100644 --- a/gui/widgets/matRad_LogoWidget.m +++ b/gui/widgets/matRad_LogoWidget.m @@ -1,5 +1,26 @@ classdef matRad_LogoWidget < matRad_Widget - + % matRad_InfoWidget class to display GUI logo widget + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties end diff --git a/gui/widgets/matRad_OptimizationWidget.m b/gui/widgets/matRad_OptimizationWidget.m index e9f37320d..be208b9ce 100644 --- a/gui/widgets/matRad_OptimizationWidget.m +++ b/gui/widgets/matRad_OptimizationWidget.m @@ -1,5 +1,27 @@ classdef matRad_OptimizationWidget < matRad_Widget - + % matRad_OptimizationWidget class to generate GUI widget to set + % optimization options + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties end diff --git a/gui/widgets/matRad_PlanWidget.m b/gui/widgets/matRad_PlanWidget.m index 553eff302..751d28ec4 100644 --- a/gui/widgets/matRad_PlanWidget.m +++ b/gui/widgets/matRad_PlanWidget.m @@ -1,5 +1,26 @@ classdef matRad_PlanWidget < matRad_Widget - + % matRad_PlanWidget class to generate GUI widget for plan parameters + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties State = false Machines @@ -116,7 +137,7 @@ h15 = uicontrol(... 'Parent',h12,... 'Units','normalized',... - 'String','Gantry Angle in °',... + 'String','Gantry Angle in °',... 'Tooltip',txt,... 'Style','text',... 'Position',gridPos{1,2},... @@ -147,7 +168,7 @@ h17 = uicontrol(... 'Parent',h12,... 'Units','normalized',... - 'String','Couch Angle in °',... + 'String','Couch Angle in °',... 'Tooltip',txt,... 'Style','text',... 'Position',gridPos{1,3},... @@ -168,6 +189,7 @@ 'Position',gridPos{2,3},... 'BackgroundColor',matRad_cfg.gui.elementColor,... 'ForegroundColor',matRad_cfg.gui.textColor,... + 'Callback',@(hObject,eventdata)standardCallback(this,hObject,eventdata),... 'Tag','editCouchAngle',... 'FontSize',matRad_cfg.gui.fontSize,... 'FontName',matRad_cfg.gui.fontName,... @@ -281,7 +303,7 @@ 'Tag','checkIsoCenter'); - pos = gridPos{4,3}; + pos = gridPos{4,2}; pos(3) = pos(3)*2; txt = sprintf('Check this if you want to run a MLC sequencing\nThe number of stratification levels can be adjusted below'); @@ -320,7 +342,7 @@ 'Enable','off',... 'Tag','btnRunDAO' ); - pos = gridPos{4,4}; + pos = gridPos{4,3}; pos(3) = pos(3) * 1.5; h28 = uicontrol(... @@ -338,10 +360,10 @@ 'FontWeight',matRad_cfg.gui.fontWeight,... 'Tag','txtSequencing' ); - pos = gridPos{4,5}; + + pos = gridPos{5,3}; pos(3) = pos(3) / 2; - %pos(1) = pos(1) + pos(3); - + h29 = uicontrol(... 'Parent',h12,... @@ -459,7 +481,7 @@ 'FontName',matRad_cfg.gui.fontName,... 'FontWeight',matRad_cfg.gui.fontWeight); - pos = gridPos{4,2}; + pos = gridPos{4,1}; pos(3) = pos(3)*2; h36 = uicontrol(... @@ -495,7 +517,7 @@ 'FontSize',matRad_cfg.gui.fontSize,... 'FontName',matRad_cfg.gui.fontName,... 'FontWeight',matRad_cfg.gui.fontWeight); - + % positioning dose grid size input boxes pos(1) = pos(1) + pos(3) + 0.005; h38 = uicontrol(... @@ -548,8 +570,42 @@ 'FontName',matRad_cfg.gui.fontName,... 'FontWeight',matRad_cfg.gui.fontWeight); - this.createHandles(); + + h40 = uicontrol(... + 'Parent',h12,... + 'Units','normalized',... + 'String','Sequencer : ',... + 'Tooltip','Set the sequencing algorithm',... + 'HorizontalAlignment','left',... + 'Style','text',... + 'Position',gridPos{4,4},... + 'BackgroundColor',matRad_cfg.gui.backgroundColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,.... + 'Interruptible','off',... + 'Tag','txtSequencer',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + + txt = sprintf('Choose a sequencing algorithm (siochi, xia or engel)'); + h41 = uicontrol(... + 'Parent',h12,... + 'Units','normalized',... + 'String',{ 'siochi','xia','engel' },... + 'Tooltip',txt,... + 'Style','popupmenu',... + 'Value',1,... + 'Position',gridPos{5,4},... + 'BackgroundColor',matRad_cfg.gui.elementColor,... + 'ForegroundColor',matRad_cfg.gui.textColor,.... + 'Callback',@(hObject,eventdata) popUpMenuSequencer_Callback(this,hObject,eventdata),... + 'Tag','popUpMenuSequencer',... + 'Enable', 'off',... + 'FontSize',matRad_cfg.gui.fontSize,... + 'FontName',matRad_cfg.gui.fontName,... + 'FontWeight',matRad_cfg.gui.fontWeight); + this.createHandles(); end function this = setPlnDefaultValues(this) @@ -624,11 +680,15 @@ contentPopUp = get(handles.popMenuBioOpt,'String'); ix = find(strcmp(pln.propOpt.bioOptimization,contentPopUp)); set(handles.popMenuBioOpt,'Value',ix); - - set(handles.btnRunSequencing,'Value',pln.propOpt.runSequencing); + set(handles.btnRunSequencing,'Value',pln.propSeq.runSequencing); set(handles.btnRunDAO,'Value',pln.propOpt.runDAO); - set(handles.radiobutton3Dconf,'Value',pln.propOpt.conf3D); - + if isfield(pln.propSeq, 'sequencingLevel') + set(handles.editSequencingLevel,'String',num2str(pln.propSeq.sequencingLevel)); + end + if isfield (pln.propOpt, 'conf3D') + set(handles.radiobutton3Dconf,'Value',pln.propOpt.conf3D); + end + set(handles.editDoseX,'String',num2str(pln.propDoseCalc.doseGrid.resolution.x)); set(handles.editDoseY,'String',num2str(pln.propDoseCalc.doseGrid.resolution.y)); set(handles.editDoseZ,'String',num2str(pln.propDoseCalc.doseGrid.resolution.z)); @@ -682,7 +742,10 @@ function updatePlnInWorkspace(this) pln.propOpt.bioOptimization = 'none'; end - pln.propOpt.runSequencing = logical(get(handles.btnRunSequencing,'Value')); + contents = get(handles.popUpMenuSequencer,'String'); + pln.propSeq.sequencer = contents{get(handles.popUpMenuSequencer,'Value')}; + pln.propSeq.runSequencing = logical(get(handles.btnRunSequencing,'Value')); + pln.propSeq.sequencingLevel = this.parseStringAsNum(get(handles.editSequencingLevel,'String'),false); pln.propOpt.runDAO = logical(get(handles.btnRunDAO,'Value')); pln.propOpt.conf3D = logical(get(handles.radiobutton3Dconf,'Value')); @@ -707,7 +770,7 @@ function updatePlnInWorkspace(this) set(handles.editIsoCenter,'Enable','off') assignin('base','pln',pln); catch ME - warning(ME.identifier,'couldn''t set isocenter in pln update! Reason: %s\n',ME.message) + warning(ME.identifier,'could not set isocenter in pln update! Reason: %s\n',ME.message) end else set(handles.editIsoCenter,'Enable','on') @@ -740,7 +803,8 @@ function updatePlnInWorkspace(this) end end catch ME - warning(ME.identifier,'couldn''t set isocenter in pln update! Reason: %s\n',ME.message) + + showWarning(this,'Could not set isocenter in pln update! Reason: %s\n',ME.message) %% showWarning vs warning end end @@ -780,7 +844,22 @@ function switchEnables(this) set(handles.btnRunDAO,'Enable','on'); set(handles.radiobutton3Dconf,'Enable','on'); set(handles.txtSequencing,'Enable','on'); - set(handles.editSequencingLevel,'Enable','on'); + set(handles.editSequencingLevel,'Enable','on'); + set(handles.popUpMenuSequencer,'Enable','on'); + set(handles.txtSequencer,'Enable','on'); + + if ~(get(handles.btnRunSequencing,'Value') || get(handles.btnRunDAO,'Value')) + + set(handles.txtSequencing,'Enable','off'); + set(handles.editSequencingLevel,'Enable','off'); + set(handles.popUpMenuSequencer,'Enable','off'); + set(handles.txtSequencer,'Enable','off'); + else + set(handles.txtSequencing,'Enable','on'); + set(handles.editSequencingLevel,'Enable','on'); + set(handles.popUpMenuSequencer,'Enable','on'); + set(handles.txtSequencer,'Enable','on'); + end case 'protons' set(handles.popMenuBioOpt,'Enable','on'); @@ -791,6 +870,8 @@ function switchEnables(this) set(handles.radiobutton3Dconf,'Enable','off'); set(handles.txtSequencing,'Enable','off'); set(handles.editSequencingLevel,'Enable','off'); + set(handles.popUpMenuSequencer,'Enable','off'); + set(handles.txtSequencer,'Enable','off'); case 'carbon' @@ -801,7 +882,9 @@ function switchEnables(this) set(handles.btnRunDAO,'Enable','off'); set(handles.radiobutton3Dconf,'Enable','off'); set(handles.txtSequencing,'Enable','off'); - set(handles.editSequencingLevel,'Enable','off'); + set(handles.editSequencingLevel,'Enable','off'); + set(handles.popUpMenuSequencer,'Enable','off'); + set(handles.txtSequencer,'Enable','off'); end selectedBioOpt = get(handles.popMenuBioOpt,'Value'); @@ -811,6 +894,7 @@ function switchEnables(this) else set(handles.btnSetTissue,'Enable','on'); end + this.handles = handles; end @@ -872,8 +956,35 @@ function popupRadMode_Callback(this, hObject, eventdata) updatePlnInWorkspace(this); end + + function popUpMenuSequencer_Callback(this, hObject, eventdata) + handles = this.handles; + contents = cellstr(get(hObject,'String')); + SeqIdentifier = contents{get(hObject,'Value')}; + contentPopUp = get(handles.popUpMenuSequencer,'String'); + + switch SeqIdentifier + case 'siochi' + ix = find(strcmp(contentPopUp,'siochi')); + set(handles.popUpMenuSequencer,'Value',ix); + + case 'xia' + ix = find(strcmp(contentPopUp,'xia')); + set(handles.popUpMenuSequencer,'Value',ix); + case 'engel' + ix = find(strcmp(contentPopUp,'engel')); + set(handles.popUpMenuSequencer,'Value',ix); + end + + pln = evalin('base','pln'); + + + this.handles = handles; + updatePlnInWorkspace(this); + end + function popUpMachine_Callback(this, hObject, eventdata) - % M�GLICHER FEHLER WEGEN VALUE WERT! + % MOEGLICHER FEHLER WEGEN VALUE WERT! handles = this.handles; contents = cellstr(get(hObject,'String')); MachineIdentifier = contents{get(hObject,'Value')}; @@ -886,7 +997,7 @@ function popUpMachine_Callback(this, hObject, eventdata) getMachines(this); pln = evalin('base','pln'); - % M�GLICHEE FEHLER HIER VALUE UND GENERIC WERDEN VERGLICHEN + % MOEGLICHEE FEHLER HIER VALUE UND GENERIC WERDEN VERGLICHEN if strcmp(contents(get(hObject,'Value')),'Generic') try AllVarNames = evalin('base','who'); @@ -901,7 +1012,7 @@ function popUpMachine_Callback(this, hObject, eventdata) end catch end - % M�GLICHEE FEHLER HIER VALUE UND GENERIC WERDEN VERGLICHEN + % MOEGLICHEE FEHLER HIER VALUE UND GENERIC WERDEN VERGLICHEN elseif strcmp(contents(get(hObject,'Value')),'generic_MCsquare') try AllVarNames = evalin('base','who'); @@ -992,7 +1103,7 @@ function btnSetTissue_Callback(this, hObject, eventdata) 'Position', [Width-(0.5*Width) 0.1 * Height 80 30],... 'Callback', 'close'); catch ME - warning(ME.identifier,'couldn''t set isocenter in pln update! Reason: %s\n',ME.message) + warning(ME.identifier,'Could not set isocenter in pln update! Reason: %s\n',ME.message) end end this.handles = handles; diff --git a/gui/widgets/matRad_StatisticsWidget.m b/gui/widgets/matRad_StatisticsWidget.m index ac9954715..e38e1405b 100644 --- a/gui/widgets/matRad_StatisticsWidget.m +++ b/gui/widgets/matRad_StatisticsWidget.m @@ -1,7 +1,30 @@ classdef matRad_StatisticsWidget < matRad_Widget - + % matRad_StatisticsWidget class to generate GUI widget to display plan + % statistics. + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% properties - SelectedCube='physicalDose'; + SelectedCube; + lockUpdate = false; + end events @@ -9,44 +32,50 @@ end methods - function this = matRad_StatisticsWidget(handleParent) - if nargin < 1 + + function this = matRad_StatisticsWidget(SelectedCube,handleParent) % use (varargin) ? + + matRad_cfg = MatRad_Config.instance(); + if nargin < 2 + handleParent = figure(... 'Units','normalized',... 'Position',[0.005 0.05 0.495 0.45],... 'Visible','on',... - 'Color',[0.501960784313725 0.501960784313725 0.501960784313725],... 'CloseRequestFcn',@(hObject,eventdata) figure1_CloseRequestFcn(this,hObject,eventdata),... + 'Color',matRad_cfg.gui.backgroundColor,... 'CloseRequestFcn',@(hObject,eventdata) figure1_CloseRequestFcn(this,hObject,eventdata),... 'IntegerHandle','off',... 'Colormap',[0 0 0.5625;0 0 0.625;0 0 0.6875;0 0 0.75;0 0 0.8125;0 0 0.875;0 0 0.9375;0 0 1;0 0.0625 1;0 0.125 1;0 0.1875 1;0 0.25 1;0 0.3125 1;0 0.375 1;0 0.4375 1;0 0.5 1;0 0.5625 1;0 0.625 1;0 0.6875 1;0 0.75 1;0 0.8125 1;0 0.875 1;0 0.9375 1;0 1 1;0.0625 1 1;0.125 1 0.9375;0.1875 1 0.875;0.25 1 0.8125;0.3125 1 0.75;0.375 1 0.6875;0.4375 1 0.625;0.5 1 0.5625;0.5625 1 0.5;0.625 1 0.4375;0.6875 1 0.375;0.75 1 0.3125;0.8125 1 0.25;0.875 1 0.1875;0.9375 1 0.125;1 1 0.0625;1 1 0;1 0.9375 0;1 0.875 0;1 0.8125 0;1 0.75 0;1 0.6875 0;1 0.625 0;1 0.5625 0;1 0.5 0;1 0.4375 0;1 0.375 0;1 0.3125 0;1 0.25 0;1 0.1875 0;1 0.125 0;1 0.0625 0;1 0 0;0.9375 0 0;0.875 0 0;0.8125 0 0;0.75 0 0;0.6875 0 0;0.625 0 0;0.5625 0 0],... 'MenuBar','none',... 'Name','MatRad Statistics',... 'NumberTitle','off',... 'HandleVisibility','callback',... - 'Tag','figure1',... + 'Tag','figStat',... 'PaperSize',[20.99999864 29.69999902]); + - end - - this = this@matRad_Widget(handleParent); - + end + this = this@matRad_Widget(handleParent); + this.SelectedCube = SelectedCube; end function this=update(this) - doUpdate = true; - if nargin == 2 - doUpdate = this.checkUpdateNecessary({'resultGUI','cst','pln'},evt); - end - - if ~doUpdate - return; - end - - if evalin('base','exist(''resultGUI'')') - this.showStatistics(); + + if this.lockUpdate + doUpdate = true; + if nargin == 2 + doUpdate = this.checkUpdateNecessary({'resultGUI','cst','pln'},evt); + end + + if ~doUpdate + return; + end + + if evalin('base','exist(''resultGUI'')') + this.showStatistics(); + end end end - end methods(Access = protected) @@ -58,38 +87,15 @@ end methods + function set.SelectedCube(this,value) + this.SelectedCube=value; + end function showStatistics(this) resultGUI = evalin('base','resultGUI'); - %Content = get(handles.popupDisplayOption,'String'); - - %SelectedCube = Content{get(handles.popupDisplayOption,'Value')}; - pln = evalin('base','pln'); - resultGUI_SelectedCube.physicalDose = resultGUI.(this.SelectedCube); - - if ~strcmp(pln.propOpt.bioOptimization,'none') - - %check if one of the default fields is selected - if sum(strcmp(this.SelectedCube,{'physicalDose','effect','RBE,','RBExDose','alpha','beta'})) > 0 - resultGUI_SelectedCube.physicalDose = resultGUI.physicalDose; - resultGUI_SelectedCube.RBExDose = resultGUI.RBExDose; - else - Idx = find(this.SelectedCube == '_'); - SelectedSuffix = this.SelectedCube(Idx(1):end); - resultGUI_SelectedCube.physicalDose = resultGUI.(['physicalDose' SelectedSuffix]); - resultGUI_SelectedCube.RBExDose = resultGUI.(['RBExDose' SelectedSuffix]); - end - end - cst = evalin('base','cst'); - %matRad_indicatorWrapper(this.widgetHandle,cst,pln,resultGUI_SelectedCube); - - if isfield(resultGUI_SelectedCube,'RBExDose') - doseCube = resultGUI_SelectedCube.RBExDose; - else - doseCube = resultGUI_SelectedCube.physicalDose; - end + doseCube = resultGUI.(this.SelectedCube); if ~exist('refVol', 'var') refVol = []; @@ -100,7 +106,6 @@ function showStatistics(this) end qi = matRad_calcQualityIndicators(cst,pln,doseCube,refGy,refVol); - ixVoi = cellfun(@(c) c.Visible == 1,cst(:,5)); qi = qi(ixVoi); matRad_showQualityIndicators(this.widgetHandle,qi); diff --git a/gui/widgets/matRad_StructureVisibilityWidget.m b/gui/widgets/matRad_StructureVisibilityWidget.m index e2a0a63f9..8e9e90ba6 100644 --- a/gui/widgets/matRad_StructureVisibilityWidget.m +++ b/gui/widgets/matRad_StructureVisibilityWidget.m @@ -1,4 +1,27 @@ classdef matRad_StructureVisibilityWidget < matRad_Widget + % matRad_StructureVisibilityWidget class to generate GUI widget to set + % visibility of structure in viewing widget + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + methods function this = matRad_StructureVisibilityWidget(handleParent) if nargin < 1 diff --git a/gui/widgets/matRad_ViewerOptionsWidget.m b/gui/widgets/matRad_ViewerOptionsWidget.m index af097f22d..826f63578 100644 --- a/gui/widgets/matRad_ViewerOptionsWidget.m +++ b/gui/widgets/matRad_ViewerOptionsWidget.m @@ -1,5 +1,27 @@ classdef matRad_ViewerOptionsWidget < matRad_Widget - + % matRad_ViewerOptionsWidget class to generate GUI widget to set + % options for the plan ViewingWidget + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties viewingWidgetHandle; colormapLocked = false; diff --git a/gui/widgets/matRad_ViewingWidget.m b/gui/widgets/matRad_ViewingWidget.m index 9917056ef..c29a8d82a 100644 --- a/gui/widgets/matRad_ViewingWidget.m +++ b/gui/widgets/matRad_ViewingWidget.m @@ -1,5 +1,27 @@ classdef matRad_ViewingWidget < matRad_Widget - + % matRad_ViewingWidget class to generate GUI widget to display plan + % dose distributions and ct + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties plane = 3; slice = 1; @@ -25,10 +47,10 @@ plotLegend = true; plotColorBar = true; ProfileType = 'lateral'; - SelectedDisplayOption =''; - SelectedDisplayAllOptions=''; - CutOffLevel= 0.01; - dispWindow= cell(3,2); + SelectedDisplayOption = 'physicalDose'; + SelectedDisplayAllOptions = ''; + CutOffLevel = 0.01; + dispWindow = cell(3,2); doseOpacity = 0.6; IsoDose_Levels= []; NewIsoDoseFlag = true; @@ -1285,7 +1307,14 @@ function updateValues(this) end minMaxRange = this.dispWindow{2,1}; - + + if (length(this.IsoDose_Levels) == 1 && this.IsoDose_Levels(1,1) == 0) + + vLevels = [0.1:0.1:0.9 0.95:0.05:upperMargin]; + referenceDose = (minMaxRange(1,2))/(upperMargin); + this.IsoDose_Levels = minMaxRange(1,1) + (referenceDose-minMaxRange(1,1)) * vLevels; + this.IsoDose_Contours = matRad_computeIsoDoseContours(dose,this.IsoDose_Levels); + end % update cached IsoDose contours vLevels = [0.1:0.1:0.9 0.95:0.05:upperMargin]; @@ -1294,9 +1323,9 @@ function updateValues(this) this.IsoDose_Contours = matRad_computeIsoDoseContours(dose,this.IsoDose_Levels); end - end this.lockUpdate=lockState; end end + end end \ No newline at end of file diff --git a/gui/widgets/matRad_VisualizationWidget.m b/gui/widgets/matRad_VisualizationWidget.m index 93859fbed..3adb36f10 100644 --- a/gui/widgets/matRad_VisualizationWidget.m +++ b/gui/widgets/matRad_VisualizationWidget.m @@ -1,7 +1,30 @@ classdef matRad_VisualizationWidget < matRad_Widget - + % matRad_VisualizationWidget class to generate GUI widget to set + % viewing options + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% properties viewingWidgetHandle; + dvhStatWidgetHandle; + end methods @@ -44,7 +67,7 @@ set(handles.radiobtnPlan,'Enable','off'); set(handles.btn3Dview,'Enable','off'); end - this.handles=handles; + this.handles = handles; end @@ -59,7 +82,7 @@ % get the default values from the viewer widget this.getFromViewingWidget(); else - handles=this.handles; + handles = this.handles; % disable all buttons set(handles.popupDisplayOption,'Enable','off'); set(handles.popupProfileType,'Enable','off'); @@ -73,7 +96,7 @@ set(handles.radiobtnIsoDoseLinesLabels,'Enable','off'); set(handles.radioBtnIsoCenter,'Enable','off'); set(handles.radiobtnPlan,'Enable','off'); - this.handles=handles; + this.handles = handles; end end @@ -528,7 +551,7 @@ methods (Access = protected) function getFromViewingWidget(this) - handles=this.handles; + handles = this.handles; if strcmp(this.viewingWidgetHandle.ProfileType,'lateral') set(handles.popupProfileType,'Value',2); else @@ -612,7 +635,7 @@ function getFromViewingWidget(this) end end - this.handles=handles; + this.handles = handles; end % H37 Calback @@ -632,7 +655,7 @@ function popupPlane_Callback(this, hObject, event) %45 Callback function popupTypeOfPlot_Callback(this, hObject, event) - this.viewingWidgetHandle.typeOfPlot=get(hObject,'Value'); + this.viewingWidgetHandle.typeOfPlot = get(hObject,'Value'); handles = this.handles; % intensity plot @@ -690,12 +713,14 @@ function popupDisplayOption_Callback(this, hObject, event) handles = this.handles; this.viewingWidgetHandle.SelectedDisplayOption = content{get(hObject,'Value'),1}; - - %UpdatePlot(handles); this.handles = handles; - - - + % if matRad Plan Analysis exists use that + fh = findobj( 'Type', 'Figure', 'Name', 'MatRad Plan Analysis' ); + if ~isempty(fh) + this.dvhStatWidgetHandle.SelectedDisplayOption = content{get(hObject,'Value'),1}; + end + + end % H49 Callback @@ -739,7 +764,7 @@ function popupProfileType_Callback(this, hObject, event) % 52 Callback function btnDVH_Callback(this, hObject, event) - matRad_DVHStatsWidget(); + this.dvhStatWidgetHandle = matRad_DVHStatsWidget(this.viewingWidgetHandle.SelectedDisplayOption); % pass fieldname in resultGUI end %H55 Callback @@ -760,7 +785,7 @@ function radiobtnContour_Callback(this,hObject, ~) % Hint: get(hObject,'Value') returns toggle state of radiobtnContour %UpdatePlot(handles) - this.viewingWidgetHandle.plotContour=get(hObject,'Value'); + this.viewingWidgetHandle.plotContour = get(hObject,'Value'); end % --- Executes on slider movement. function sliderSlice_Callback(this,hObject, ~) @@ -772,7 +797,7 @@ function sliderSlice_Callback(this,hObject, ~) % get(hObject,'Min') and get(hObject,'Max') to determine range of slider %UpdatePlot(handles) - this.viewingWidgetHandle.slice= round(get(hObject,'Value')); + this.viewingWidgetHandle.slice = round(get(hObject,'Value')); end function radiobtnCT_Callback(this,hObject, ~) @@ -782,7 +807,7 @@ function radiobtnCT_Callback(this,hObject, ~) % Hint: get(hObject,'Value') returns toggle state of radiobtnCT %UpdatePlot(handles) - this.viewingWidgetHandle.plotCT=get(hObject,'Value'); + this.viewingWidgetHandle.plotCT = get(hObject,'Value'); end % --- Executes on button press in radiobtnPlan. @@ -793,7 +818,7 @@ function radiobtnPlan_Callback(this,hObject, ~) % Hint: get(hObject,'Value') returns toggle state of radiobtnPlan %UpdatePlot(handles) - this.viewingWidgetHandle.plotPlan=get(hObject,'Value'); + this.viewingWidgetHandle.plotPlan = get(hObject,'Value'); end % --- Executes on button press in radiobtnIsoDoseLines. @@ -803,7 +828,7 @@ function radiobtnIsoDoseLines_Callback(this,hObject, ~) % handles structure with handles and user data (see GUIDATA) % Hint: get(hObject,'Value') returns toggle state of radiobtnIsoDoseLines - this.viewingWidgetHandle.plotIsoDoseLines=get(hObject,'Value'); + this.viewingWidgetHandle.plotIsoDoseLines = get(hObject,'Value'); end @@ -821,7 +846,7 @@ function radiobtnDose_Callback(this,hObject, ~) % radio button: plot isolines labels function radiobtnIsoDoseLinesLabels_Callback(this,hObject, ~) %UpdatePlot(handles); - this.viewingWidgetHandle.plotIsoDoseLinesLabels=get(hObject,'Value'); + this.viewingWidgetHandle.plotIsoDoseLinesLabels = get(hObject,'Value'); end % --- Executes on button press in radioBtnIsoCenter. @@ -831,7 +856,7 @@ function radioBtnIsoCenter_Callback(this,hObject, eventdata) % handles structure with handles and user data (see GUIDATA) %UpdatePlot(handles) % Hint: get(hObject,'Value') returns toggle state of radioBtnIsoCenter - this.viewingWidgetHandle.plotIsoCenter=get(hObject,'Value'); + this.viewingWidgetHandle.plotIsoCenter = get(hObject,'Value'); end end end diff --git a/gui/widgets/matRad_WorkflowWidget.m b/gui/widgets/matRad_WorkflowWidget.m index d09969bbe..0385e5324 100644 --- a/gui/widgets/matRad_WorkflowWidget.m +++ b/gui/widgets/matRad_WorkflowWidget.m @@ -1,5 +1,27 @@ classdef matRad_WorkflowWidget < matRad_Widget - + % matRad_WorkflowWidget class to generate GUI widget to run through the + % treatment planning workflow + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties end @@ -112,7 +134,8 @@ function btnLoadMat_Callback(this, hObject, event) matRad_cfg = MatRad_Config.instance(); - h72 = this.addControlToGrid([2 5],... + + h72 = this.addControlToGrid([2 4],... 'Style','text',... 'String','Status:',... 'BackgroundColor',matRad_cfg.gui.backgroundColor,... @@ -120,7 +143,8 @@ function btnLoadMat_Callback(this, hObject, event) 'Tag','txtStatus',... 'FontSize',round(matRad_cfg.gui.fontSize*1.2)); - h73 = this.addControlToGrid([3 5],... + + h73 = this.addControlToGrid([3 4],... 'String','no data loaded',... 'Style','text',... 'BackgroundColor',matRad_cfg.gui.backgroundColor,... @@ -238,11 +262,15 @@ function btnLoadMat_Callback(this, hObject, event) set(handles.btn_export,'Enable','off'); set(handles.exportDicomButton,'Enable','off'); - if evalin('base','exist(''pln'')') - - if evalin('base','exist(''ct'')') && ... + + if evalin('base','exist(''ct'')') && ... evalin('base','exist(''cst'')') + set(handles.txtInfo,'String','loaded and ready'); + + if evalin('base','exist(''pln'')') + + % ct cst and pln available; ready for dose calculation set(handles.txtInfo,'String','ready for dose calculation'); set(handles.btnCalcDose,'Enable','on'); @@ -402,12 +430,12 @@ function btnOptimize_Callback(this, hObject, eventdata) set(InterfaceObj,'Enable','off'); pln = evalin('base','pln'); - ct = evalin('base','ct'); - + dij = evalin('base','dij'); + cst = evalin('base','cst'); % optimize - [resultGUIcurrentRun,usedOptimizer] = matRad_fluenceOptimization(evalin('base','dij'),evalin('base','cst'),pln); + [resultGUIcurrentRun,usedOptimizer] = matRad_fluenceOptimization(dij,cst,pln); if pln.propOpt.conf3D && strcmp(pln.radiationMode,'photons') - resultGUIcurrentRun.w = resultGUIcurrentRun.w * ones(dij.totalNumOfBixels,1); + resultGUIcurrentRun.w = resultGUIcurrentRun.w .* ones(dij.totalNumOfBixels,1); resultGUIcurrentRun.wUnsequenced = resultGUIcurrentRun.w; end @@ -430,27 +458,9 @@ function btnOptimize_Callback(this, hObject, eventdata) else resultGUI = resultGUIcurrentRun; end + assignin('base','resultGUI',resultGUI); - % - % % set some values - % if handles.plane == 1 - % set(handles.sliderSlice,'Value',ceil(pln.propStf.isoCenter(1,2)/ct.resolution.x)); - % elseif handles.plane == 2 - % set(handles.sliderSlice,'Value',ceil(pln.propStf.isoCenter(1,1)/ct.resolution.y)); - % elseif handles.plane == 3 - % set(handles.sliderSlice,'Value',ceil(pln.propStf.isoCenter(1,3)/ct.resolution.z)); - % end - - % handles.State = 3; - % handles.SelectedDisplayOptionIdx = 1; - % if strcmp(pln.radiationMode,'carbon') || (strcmp(pln.radiationMode,'protons') && strcmp(pln.propOpt.bioOptimization,'const_RBExD')) - % handles.SelectedDisplayOption = 'RBExDose'; - % else - % handles.SelectedDisplayOption = 'physicalDose'; - % end - % handles.selectedBeam = 1; - % check IPOPT status and return message for GUI user if no DAO or - % particles + if ~pln.propOpt.runDAO || ~strcmp(pln.radiationMode,'photons') CheckOptimizerStatus(this,usedOptimizer,'Fluence') end @@ -466,14 +476,11 @@ function btnOptimize_Callback(this, hObject, eventdata) % perform sequencing and DAO try - %% sequencing - if strcmp(pln.radiationMode,'photons') && (pln.propOpt.runSequencing || pln.propOpt.runDAO) - resultGUI = matRad_siochiLeafSequencing(resultGUI,evalin('base','stf'),evalin('base','dij')... - ,str2double(get(handles.editSequencingLevel,'String'))); - - assignin('base','resultGUI',resultGUI); - end + + resultGUI = matRad_sequencing(resultGUI,evalin('base','stf'),dij,pln); + assignin('base','resultGUI',resultGUI); + catch ME % change state from busy to normal @@ -487,7 +494,8 @@ function btnOptimize_Callback(this, hObject, eventdata) try %% DAO if strcmp(pln.radiationMode,'photons') && pln.propOpt.runDAO - handles = showWarning(handles,['Observe: You are running direct aperture optimization' filesep 'This is experimental code that has not been thoroughly debugged - especially in combination with constrained optimization.']); + + showWarning(this,['Observe: You are running direct aperture optimization' filesep 'This is experimental code that has not been thoroughly debugged - especially in combination with constrained optimization.']); % was assigned to handles WHY ? [resultGUI,usedOptimizer] = matRad_directApertureOptimization(evalin('base','dij'),evalin('base','cst'),... resultGUI.apertureInfo,resultGUI,pln); assignin('base','resultGUI',resultGUI); @@ -495,7 +503,9 @@ function btnOptimize_Callback(this, hObject, eventdata) CheckOptimizerStatus(this,usedOptimizer,'DAO'); end - if strcmp(pln.radiationMode,'photons') && (pln.propOpt.runSequencing || pln.propOpt.runDAO) + + if strcmp(pln.radiationMode,'photons') && (pln.propSeq.runSequencing || pln.propOpt.runDAO) + matRad_visApertureInfo(resultGUI.apertureInfo); end @@ -511,14 +521,6 @@ function btnOptimize_Callback(this, hObject, eventdata) % change state from busy to normal set(Figures, 'pointer', 'arrow'); set(InterfaceObj,'Enable','on'); - % handles.dispWindow{3,1} = []; % reset dose ranges - % handles.dispWindow{3,2} = []; % reset min max dose values - % handles.rememberCurrAxes = false; - % handles.IsoDose.Levels = 0; % ensure to use default iso dose line spacing - % handles.cBarChanged = true; - % handles = updateIsoDoseLineCache(handles); - % UpdatePlot(handles); - % handles.rememberCurrAxes = true; this.handles = handles; this.changedWorkspace('resultGUI'); @@ -533,7 +535,6 @@ function btnLoadDicom_Callback(this, hObject, event) handles = this.handles; try % delete existing workspace - parse variables from base workspace - % set(handles.popupDisplayOption,'String','no option available'); AllVarNames = evalin('base','who'); RefVarNames = {'ct','cst','pln','stf','dij','resultGUI'}; for i = 1:length(RefVarNames) @@ -548,8 +549,7 @@ function btnLoadDicom_Callback(this, hObject, event) end this.handles = handles; - %changeWorkspace(this); - %getFromWorkspace(this); + end % H78 Callback - button: refresh @@ -567,7 +567,7 @@ function pushbutton_recalc_Callback(this, hObject, eventdata) try % indicate that matRad is busy % change mouse pointer to hour glass - Figures = gcf;%findobj('type','figure'); + Figures = gcf; set(Figures, 'pointer', 'watch'); drawnow; % disable all active objects @@ -580,16 +580,7 @@ function pushbutton_recalc_Callback(this, hObject, eventdata) ct = evalin('base','ct'); cst = evalin('base','cst'); resultGUI = evalin('base','resultGUI'); - - % % get weights of the selected cube - % Content = get(handles.popupDisplayOption,'String'); - % SelectedCube = Content{get(handles.popupDisplayOption,'Value')}; - % Suffix = strsplit(SelectedCube,'_'); - % if length(Suffix)>1 - % Suffix = ['_' Suffix{2}]; - % else - % Suffix = ''; - % end + if sum([stf.totalNumOfBixels]) ~= length(resultGUI.w)%(['w' Suffix])) warndlg('weight vector does not corresponding to current steering file'); @@ -630,19 +621,12 @@ function pushbutton_recalc_Callback(this, hObject, eventdata) % assign results to base worksapce assignin('base','dij',dij); assignin('base','resultGUI',resultGUI); - - - % % show physicalDose of newly computed state - % handles.SelectedDisplayOption = 'physicalDose'; - % set(handles.popupDisplayOption,'Value',find(strcmp('physicalDose',Content))); + % change state from busy to normal set(Figures, 'pointer', 'arrow'); set(InterfaceObj,'Enable','on'); - - % handles.cBarChanged = true; - % handles = updateIsoDoseLineCache(handles); - + this.handles = handles; this.changedWorkspace('dij','resultGUI'); @@ -699,8 +683,7 @@ function btnSaveToGUI_Callback(this, hObject, eventdata) uiwait(figDialog); this.handles = handles; - %changeWorkspace(this); - %getFromWorkspace(this); + end function SaveResultToGUI(this, ~, ~) @@ -834,41 +817,6 @@ function pushbutton_importFromBinary_Callback(this, hObject, eventdata) h=matRad_importWidget; uiwait(h.widgetHandle); -% %Check if we have the variables in the workspace -% if evalin('base','exist(''cst'',''var'')') == 1 && evalin('base','exist(''ct'',''var'')') == 1 -% cst = evalin('base','cst'); -% ct = evalin('base','ct'); -% %cst = generateCstTable(this,cst); -% % handles.TableChanged = false; -% % set(handles.popupTypeOfPlot,'Value',1); -% -% % compute HU values -% if ~isfield(ct, 'cubeHU') -% ct = matRad_electronDensitiesToHU(ct); -% end -% % if ~isfield(ct, 'cubeHU') -% % handles.cubeHUavailable = false; -% % else -% % handles.cubeHUavailable = true; -% % end -% -% % % precompute contours -% % cst = precomputeContours(this,ct,cst); -% -% assignin('base','ct',ct); -% assignin('base','cst',cst); -% -% if evalin('base','exist(''pln'',''var'')') -% assignin('base','pln',pln); -% % setPln(handles); -% % else -% % getPlnFromGUI(handles); -% % setPln(handles); -% end -% -% -% -% end this.handles = handles; this.changedWorkspace(); catch ME diff --git a/gui/widgets/matRad_exportDicomWidget.m b/gui/widgets/matRad_exportDicomWidget.m index 1311eb4bc..e640c6ed0 100644 --- a/gui/widgets/matRad_exportDicomWidget.m +++ b/gui/widgets/matRad_exportDicomWidget.m @@ -1,5 +1,27 @@ classdef matRad_exportDicomWidget < matRad_Widget - + % matRad_exportDicomWidget class to generate GUI widget to export plan + % to dicom files + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties variables = {'ct','cst','resultGUI'}; %variables to export end diff --git a/gui/widgets/matRad_exportWidget.m b/gui/widgets/matRad_exportWidget.m index d8e728d08..781dec05c 100644 --- a/gui/widgets/matRad_exportWidget.m +++ b/gui/widgets/matRad_exportWidget.m @@ -1,5 +1,29 @@ classdef matRad_exportWidget < matRad_Widget - + + % matRad_exportWidget class to generate GUI widget to export plan as + % dicom, nrrd etc. + % + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties end diff --git a/gui/widgets/matRad_importDicomWidget.m b/gui/widgets/matRad_importDicomWidget.m index b803c5323..69ad0cca0 100644 --- a/gui/widgets/matRad_importDicomWidget.m +++ b/gui/widgets/matRad_importDicomWidget.m @@ -1,5 +1,27 @@ classdef matRad_importDicomWidget < matRad_Widget - + % matRad_importDicomWidget class to generate GUI widget to import dicom + % files + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties end @@ -390,8 +412,8 @@ end - % H?? CHECKBOX§ CALLBACK - function this = checkbox3_Callback(this, hObject, eventdata) + % H38 CHECKBOX USE RT DOSE GRID CALLBACK + function this = checkUseRTdoseGrid_Callback(this, hObject, eventdata) % hObject handle to checkbox3 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) @@ -924,7 +946,7 @@ 'FontSize',matRad_cfg.gui.fontSize,... 'FontName',matRad_cfg.gui.fontName,... 'FontWeight',matRad_cfg.gui.fontWeight,... - 'Callback',@(hObject,event) checkbox3_Callback(this,hObject,event),... + 'Callback',@(hObject,event) checkUseRTdoseGrid_Callback(this,hObject,event),... 'Enable','off',... 'Tag','checkbox3' ); diff --git a/gui/widgets/matRad_importWidget.m b/gui/widgets/matRad_importWidget.m index c6409c3f7..1f364e6a2 100644 --- a/gui/widgets/matRad_importWidget.m +++ b/gui/widgets/matRad_importWidget.m @@ -1,5 +1,27 @@ classdef matRad_importWidget < matRad_Widget - + % matRad_importWidget class to generate GUI widget to import various + % formats : dicom, nrrd, etc. + % Describes a standard fluence optimization problem by providing the + % implementation of the objective & constraint function/gradient wrappers + % and managing the mapping and backprojection of the respective dose- + % related quantity + % + % References + % - + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Copyright 2020 the matRad development team. + % + % This file is part of the matRad project. It is subject to the license + % terms in the LICENSE file found in the top-level directory of this + % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part + % of the matRad project, including this file, may be copied, modified, + % propagated, or distributed except according to the terms contained in the + % LICENSE file. + % + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties end diff --git a/matRad.m b/matRad.m index a56a806ed..1384b6553 100644 --- a/matRad.m +++ b/matRad.m @@ -18,22 +18,22 @@ % load patient data, i.e. ct, voi, cst %load HEAD_AND_NECK -load TG119.mat +% load TG119.mat %load PROSTATE.mat %load LIVER.mat %load BOXPHANTOM.mat % meta information for treatment plan -pln.radiationMode = 'photons'; % either photons / protons / carbon +pln.radiationMode = 'protons'; % either photons / protons / carbon pln.machine = 'Generic'; pln.numOfFractions = 30; % beam geometry settings pln.propStf.bixelWidth = 5; % [mm] / also corresponds to lateral spot spacing for particles -pln.propStf.gantryAngles = [0:72:359]; % [?] -pln.propStf.couchAngles = [0 0 0 0 0]; % [?] +pln.propStf.gantryAngles = [0]; % [?] +pln.propStf.couchAngles = [0]; % [?] pln.propStf.numOfBeams = numel(pln.propStf.gantryAngles); pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct,0); @@ -47,7 +47,8 @@ pln.propOpt.bioOptimization = 'none'; % none: physical optimization; const_RBExD; constant RBE of 1.1; % LEMIV_effect: effect-based optimization; LEMIV_RBExD: optimization of RBE-weighted dose pln.propOpt.runDAO = false; % 1/true: run DAO, 0/false: don't / will be ignored for particles -pln.propOpt.runSequencing = false; % 1/true: run sequencing, 0/false: don't / will be ignored for particles and also triggered by runDAO below + +pln.propSeq.runSequencing = true; % true: run sequencing, false: don't / will be ignored for particles and also triggered by runDAO below %% initial visualization and change objective function settings if desired matRadGUI @@ -67,11 +68,8 @@ resultGUI = matRad_fluenceOptimization(dij,cst,pln); %% sequencing -if strcmp(pln.radiationMode,'photons') && (pln.propOpt.runSequencing || pln.propOpt.runDAO) - %resultGUI = matRad_xiaLeafSequencing(resultGUI,stf,dij,5); - %resultGUI = matRad_engelLeafSequencing(resultGUI,stf,dij,5); - resultGUI = matRad_siochiLeafSequencing(resultGUI,stf,dij,5); -end +resultGUI = matRad_sequencing(resultGUI,stf,dij,pln); + %% DAO if strcmp(pln.radiationMode,'photons') && pln.propOpt.runDAO diff --git a/matRad_rc.m b/matRad_rc.m index 8bd7d7546..a98da5e3c 100644 --- a/matRad_rc.m +++ b/matRad_rc.m @@ -27,8 +27,9 @@ function matRad_rc(clearWindow) matRad_cfg = MatRad_Config.instance(); end +% clear command window and close all figures if clearWindow - %clear command window and close all figures + clc; close all; end @@ -41,3 +42,4 @@ function matRad_rc(clearWindow) clear env envver vString; +end \ No newline at end of file diff --git a/matRad_sequencing.m b/matRad_sequencing.m new file mode 100644 index 000000000..bbb071eea --- /dev/null +++ b/matRad_sequencing.m @@ -0,0 +1,67 @@ +function resultGUI = matRad_sequencing(resultGUI,stf,dij,pln,visBool) +% matRad inverse planning wrapper function +% +% call +% resultGUI = matRad_sequencing(resultGUI,stf,dij,pln) +% +% input +% dij: matRad dij struct +% stf: matRad stf struct +% pln: matRad pln struct +% resultGUI: struct containing optimized fluence vector, dose, and (for +% biological optimization) RBE-weighted dose etc. +% +% output +% resultGUI: struct containing optimized fluence vector, dose, and (for +% biological optimization) RBE-weighted dose etc. +% +% References +% - +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Copyright 2016 the matRad development team. +% +% This file is part of the matRad project. It is subject to the license +% terms in the LICENSE file found in the top-level directory of this +% distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part +% of the matRad project, including this file, may be copied, modified, +% propagated, or distributed except according to the terms contained in the +% LICENSE file. +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +matRad_cfg = MatRad_Config.instance(); + +if nargin < 5 + visBool = 0; +end + +if strcmp(pln.radiationMode,'photons') && (pln.propSeq.runSequencing || pln.propOpt.runDAO) + + if ~isfield(pln.propSeq, 'sequencer') + pln.propSeq.sequencer = 'siochi'; % default: siochi sequencing algorithm + matRad_cfg.dispWarning ('pln.propSeq.sequencer not specified. Using siochi leaf sequencing (default).') + end + + if ~isfield(pln.propSeq, 'sequencingLevel') + pln.propSeq.sequencingLevel = 5; + matRad_cfg.dispWarning ('pln.propSeq.sequencingLevel not specified. Using 5 sequencing levels (default).') + end + + switch pln.propSeq.sequencer + case 'xia' + resultGUI = matRad_xiaLeafSequencing(resultGUI,stf,dij,pln.propSeq.sequencingLevel,visBool); + case 'engel' + resultGUI = matRad_engelLeafSequencing(resultGUI,stf,dij,pln.propSeq.sequencingLevel,visBool); + case 'siochi' + resultGUI = matRad_siochiLeafSequencing(resultGUI,stf,dij,pln.propSeq.sequencingLevel,visBool); + otherwise + matRad_cfg.dispError('Could not find specified sequencing algorithm'); + end +elseif ~strcmp(pln.radiationMode,'photons') + matRad_cfg.dispWarning('Sequencing is only specified for pln.radiationMode = "photons". Continuing with out sequencing ... ') +end +end + + diff --git a/matRad_showDVH.m b/matRad_showDVH.m index d0e4e0be7..8d5bc7a2b 100644 --- a/matRad_showDVH.m +++ b/matRad_showDVH.m @@ -102,3 +102,4 @@ function matRad_showDVH(axesHandle,dvh,cst,pln,lineStyleIndicator) else xlabel(axesHandle,'Dose [Gy]','FontSize',fontSizeValue); end +hold(axesHandle,'off');