0001 function varargout = matRadGUI(varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 matRad_cfg = MatRad_Config.instance();
0039
0040 if matRad_cfg.disableGUI
0041 matRad_cfg.dispInfo('matRad GUI disabled in matRad_cfg!\n');
0042 return;
0043 end
0044
0045 if ~isdeployed
0046 matRadRootDir = fileparts(mfilename('fullpath'));
0047 addpath(genpath(matRadRootDir));
0048 end
0049
0050 [env, versionString] = matRad_getEnvironment();
0051
0052
0053 switch env
0054 case 'MATLAB'
0055
0056 case 'OCTAVE'
0057 matRad_cfg.dispInfo(['matRad GUI not available for ' env ' ' versionString ' \n']);
0058 return;
0059 otherwise
0060 matRad_cfg.dispInfo('not yet tested');
0061 end
0062
0063
0064
0065 if ispc
0066 lf = 'com.sun.java.swing.plaf.windows.WindowsLookAndFeel';
0067 elseif isunix
0068 lf = 'com.jgoodies.looks.plastic.Plastic3DLookAndFeel';
0069 elseif ismac
0070 lf = 'com.apple.laf.AquaLookAndFeel';
0071 end
0072 javax.swing.UIManager.setLookAndFeel(lf);
0073
0074 gui_Singleton = 1;
0075 gui_State = struct('gui_Name', mfilename, ...
0076 'gui_Singleton', gui_Singleton, ...
0077 'gui_OpeningFcn', @matRadGUI_OpeningFcn, ...
0078 'gui_OutputFcn', @matRadGUI_OutputFcn, ...
0079 'gui_LayoutFcn', [] , ...
0080 'gui_Callback', []);
0081 if nargin && ischar(varargin{1})
0082 gui_State.gui_Callback = str2func(varargin{1});
0083 end
0084
0085 if nargout
0086 [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
0087 else
0088 gui_mainfcn(gui_State, varargin{:});
0089 end
0090
0091
0092
0093 function handles = resetGUI(hObject, handles, varargin)
0094
0095 if ispc
0096 opengl software
0097 elseif ismac
0098
0099 end
0100
0101
0102 handles.output = hObject;
0103
0104 axes(handles.axesLogo)
0105 [im, ~, alpha] = imread('matrad_logo.png');
0106 f = image(im);
0107 axis equal off
0108 set(f, 'AlphaData', alpha);
0109
0110 axes(handles.axesDKFZ)
0111 [im, ~, alpha] = imread('DKFZ_Logo.png');
0112 f = image(im);
0113 axis equal off;
0114 set(f, 'AlphaData', alpha);
0115
0116
0117
0118 handles.dcm_obj = datacursormode(handles.figure1);
0119 set(handles.dcm_obj,'DisplayStyle','window');
0120 if strcmpi(get(handles.dcm_obj,'Enable'),'on')
0121 set(handles.dcm_obj,'Enable','off');
0122 end
0123
0124 set(handles.dcm_obj,'UpdateFcn',@dataCursorUpdateFunction);
0125
0126
0127 set(gcf,'WindowScrollWheelFcn',@matRadScrollWheelFcn);
0128
0129
0130 if handles.initialGuiStart
0131 hToolbar = findall(hObject,'tag','uitoolbar1');
0132 jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer');
0133 jToolbar.setBorderPainted(false);
0134 color = java.awt.Color.gray;
0135
0136 jToolbar.setBackground(color);
0137
0138 warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
0139 jFrame = get(handle(hObject),'JavaFrame');
0140 jFrame.showTopSeparator(false);
0141 jtbc = jToolbar.getComponents;
0142 for idx=1:length(jtbc)
0143 jtbc(idx).setOpaque(false);
0144 jtbc(idx).setBackground(color);
0145 for childIdx = 1 : length(jtbc(idx).getComponents)
0146 jtbc(idx).getComponent(childIdx-1).setBackground(color);
0147 end
0148 end
0149 end
0150
0151
0152 set(handles.legendTable,'String',{'no data loaded'});
0153
0154 if isfield(handles,'VOIPlotFlag')
0155 handles = rmfield(handles,'VOIPlotFlag');
0156 end
0157
0158
0159 handles.Modalities = {'photons','protons','carbon'};
0160 for i = 1:length(handles.Modalities)
0161 pattern = [handles.Modalities{1,i} '_*'];
0162 if isdeployed
0163 baseroot = [ctfroot filesep 'matRad'];
0164 else
0165 baseroot = fileparts(mfilename('fullpath'));
0166 end
0167 Files = dir([baseroot filesep 'basedata' filesep pattern]);
0168
0169 for j = 1:length(Files)
0170 if ~isempty(Files)
0171 MachineName = Files(j).name(numel(handles.Modalities{1,i})+2:end-4);
0172 if isfield(handles,'Machines')
0173 if sum(strcmp(handles.Machines,MachineName)) == 0
0174 handles.Machines{size(handles.Machines,2)+1} = MachineName;
0175 end
0176 else
0177 handles.Machines = cell(1);
0178 handles.Machines{1} = MachineName;
0179 end
0180 end
0181 end
0182 end
0183 set(handles.popUpMachine,'String',handles.Machines);
0184
0185
0186 vChar = get(handles.editGantryAngle,'String');
0187 if strcmp(vChar(1,1),'0') && length(vChar)==6
0188 set(handles.editGantryAngle,'String','0');
0189 end
0190 vChar = get(handles.editCouchAngle,'String');
0191 if strcmp(vChar(1,1),'0') && length(vChar)==3
0192 set(handles.editCouchAngle,'String','0')
0193 end
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205 handles.CutOffLevel = 0.01;
0206 handles.IsoDose.NewIsoDoseFlag = false;
0207 handles.TableChanged = false;
0208 handles.State = 0;
0209 handles.doseOpacity = 0.6;
0210 handles.IsoDose.Levels = 0;
0211 handles.dispWindow = cell(3,2);
0212
0213
0214 set(handles.checkIsoCenter, 'Value', 0);
0215 set(handles.editIsoCenter,'Enable','on')
0216
0217
0218 handles.cubeHUavailable = false;
0219
0220 handles.initialGuiStart = false;
0221 guidata(hObject, handles);
0222
0223
0224
0225
0226
0227 function initViewSliceSlider(handles)
0228
0229
0230 if handles.State > 0
0231 ct = evalin('base', 'ct');
0232
0233
0234 planePermute = [2 1 3];
0235 ctRes = [ct.resolution.x ct.resolution.y ct.resolution.z];
0236 planePermIx = planePermute(handles.plane);
0237 planeDim = ct.cubeDim(handles.plane);
0238
0239
0240 try
0241 if evalin('base','exist(''pln'',''var'')')
0242 currPln = evalin('base','pln');
0243
0244 if sum(currPln.propStf.isoCenter(:)) ~= 0
0245
0246 currSlice = round(currPln.propStf.isoCenter(1,planePermIx) / ctRes(planePermIx));
0247 end
0248 end
0249 catch
0250 currSlice = 0;
0251 end
0252
0253
0254 if currSlice < 1 || currSlice > planeDim
0255 currSlice = ceil(planeDim/2);
0256 end
0257
0258 set(handles.sliderSlice,'Min',1,'Max',planeDim,...
0259 'Value',currSlice,...
0260 'SliderStep',[1/(planeDim-1) 1/(planeDim-1)]);
0261 else
0262
0263 set(handles.sliderSlice,'Min',0,'Max',1,'Value',0,'SliderStep',[1 1]);
0264 end
0265
0266
0267
0268 function handles = reloadGUI(hObject, handles, ct, cst)
0269 AllVarNames = handles.AllVarNames;
0270
0271 if nargin >=3 && ismember('ct',AllVarNames)
0272
0273 if ~isfield(ct, 'cubeHU')
0274 ct = matRad_electronDensitiesToHU(ct);
0275 assignin('base','ct',ct);
0276 end
0277 if ~isfield(ct, 'cubeHU')
0278 handles.cubeHUavailable = false;
0279 else
0280 handles.cubeHUavailable = true;
0281 end
0282 end
0283
0284
0285 try
0286 if ismember('pln',AllVarNames) && handles.State > 0
0287
0288 pln = evalin('base','pln');
0289 if ~isfield(pln,'propStf')
0290 handles = showWarning(handles,'GUI OpeningFunc: Overwriting outdated pln format with default GUI pln');
0291 evalin('base','clear pln');
0292 getPlnFromGUI(handles);
0293 end
0294 setPln(handles);
0295 elseif handles.State > 0
0296 getPlnFromGUI(handles);
0297 setPln(handles);
0298 end
0299
0300 catch
0301 handles.State = 0;
0302 handles = showError(handles,'GUI OpeningFunc: Could not set or get pln');
0303 end
0304
0305
0306 if ismember('dij',AllVarNames)
0307 handles.State = 2;
0308 end
0309
0310
0311 if ismember('resultGUI',AllVarNames)
0312 handles.State = 3;
0313 end
0314
0315
0316 if handles.State == 2 || handles.State == 3
0317 set(handles.popupDisplayOption,'String','physicalDose');
0318 handles.SelectedDisplayOption ='physicalDose';
0319 handles.SelectedDisplayOptionIdx=1;
0320 else
0321 handles.resultGUI = [];
0322 set(handles.popupDisplayOption,'String','no option available');
0323 handles.SelectedDisplayOption='';
0324 handles.SelectedDisplayOptionIdx=1;
0325 end
0326
0327
0328 if handles.State == 3
0329 handles = updateIsoDoseLineCache(handles);
0330 end
0331
0332
0333 handles.selectedBeam = 1;
0334 handles.plane = get(handles.popupPlane,'Value');
0335 handles.DijCalcWarning = false;
0336
0337
0338 initViewSliceSlider(handles);
0339
0340
0341 if handles.State > 0
0342 for i = 1:size(cst,1)
0343 if cst{i,5}.Visible
0344 handles.VOIPlotFlag(i) = true;
0345 else
0346 handles.VOIPlotFlag(i) = false;
0347 end
0348 end
0349 end
0350
0351
0352 handles.doseColorMap = 'jet';
0353 handles.ctColorMap = 'bone';
0354 handles.cMapSize = 64;
0355 handles.cBarChanged = true;
0356
0357
0358 availableColormaps = matRad_getColormap();
0359 set(handles.popupmenu_chooseColormap,'String',availableColormaps);
0360
0361 currentCtMapIndex = find(strcmp(availableColormaps,handles.ctColorMap));
0362 currentDoseMapIndex = find(strcmp(availableColormaps,handles.doseColorMap));
0363
0364 if handles.State >= 1
0365 set(handles.popupmenu_chooseColormap,'Value',currentCtMapIndex);
0366 end
0367
0368 if handles.State >= 3
0369 set(handles.popupmenu_chooseColormap,'Value',currentDoseMapIndex);
0370 end
0371
0372
0373 handles.profileOffset = 0;
0374 UpdateState(handles)
0375
0376 axes(handles.axesFig)
0377
0378 handles.rememberCurrAxes = false;
0379 UpdatePlot(handles)
0380 handles.rememberCurrAxes = true;
0381 guidata(hObject, handles);
0382
0383
0384
0385 function matRadGUI_OpeningFcn(hObject, ~, handles, varargin)
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 handles.initialGuiStart = true;
0398
0399 p = inputParser;
0400 addParameter(p,'devMode',false,@validateModeValue);
0401 addParameter(p,'eduMode',false,@validateModeValue);
0402 p.KeepUnmatched = true;
0403
0404 parse(p,varargin{:});
0405 parsedInput = p.Results;
0406
0407 if ischar(parsedInput.devMode) || isstring(parsedInput.devMode)
0408 parsedInput.devMode = str2double(parsedInput.devMode);
0409 end
0410
0411 if ischar(parsedInput.eduMode) || isstring(parsedInput.eduMode)
0412 parsedInput.eduMode = str2double(parsedInput.eduMode);
0413 end
0414
0415
0416
0417
0418 handles.devMode = logical(parsedInput.devMode);
0419 if handles.devMode
0420 disp('matRadGUI starting in developer mode!');
0421 end
0422
0423
0424
0425 handles.eduMode = logical(parsedInput.eduMode);
0426 if handles.eduMode
0427 disp('matRadGUI starting in educational mode!');
0428 end
0429
0430
0431 set(handles.radiobtnPlan,'value',0);
0432
0433
0434
0435 if handles.eduMode
0436
0437 eduHideHandles = {handles.radiobutton3Dconf,...
0438 handles.btnRunDAO,...
0439 handles.pushbutton_importFromBinary,...
0440 handles.btnLoadDicom,...
0441 handles.btn_export,...
0442 handles.importDoseButton};
0443 eduDisableHandles = {handles.editCouchAngle,handles.popUpMachine};
0444 cellfun(@(h) set(h,'Visible','Off'),eduHideHandles);
0445 cellfun(@(h) set(h,'Enable','Off'),eduDisableHandles);
0446 end
0447
0448
0449
0450 vString = matRad_version();
0451 vPos = get(handles.text15,'Position');
0452 urlPos = get(handles.text31,'Position');
0453 btnPos = get(handles.btnAbout,'Position');
0454
0455
0456 vPos([1 3]) = [0 1];
0457 vPos(4) = vPos(4)*1.25;
0458 btnPos(2) = 0.05;
0459 urlPos(2) = btnPos(2)+btnPos(4)+0.05;
0460 vPos(2) = urlPos(2) + urlPos(4) + 0.05;
0461 vPos(4) = 0.98 - vPos(2);
0462
0463 set(handles.btnAbout,'Position',btnPos);
0464 set(handles.text31,'String','www.matRad.org','Position',urlPos,'Enable','inactive','ButtonDownFcn', @(~,~) web('www.matrad.org','-browser'));
0465 set(handles.text15,'String',vString,'Position',vPos);
0466
0467 handles = resetGUI(hObject, handles);
0468
0469
0470 AllVarNames = evalin('base','who');
0471 handles.AllVarNames = AllVarNames;
0472 try
0473 if ismember('ct',AllVarNames) && ismember('cst',AllVarNames)
0474 ct = evalin('base','ct');
0475 cst = evalin('base','cst');
0476
0477 cst = generateCstTable(handles,cst);
0478 handles.State = 1;
0479 cst = matRad_computeVoiContoursWrapper(cst,ct);
0480 assignin('base','cst',cst);
0481
0482 elseif ismember('ct',AllVarNames) && ~ismember('cst',AllVarNames)
0483 handles = showError(handles,'GUI OpeningFunc: could not find cst file');
0484 elseif ~ismember('ct',AllVarNames) && ismember('cst',AllVarNames)
0485 handles = showError(handles,'GUI OpeningFunc: could not find ct file');
0486 end
0487 catch
0488 handles = showError(handles,'GUI OpeningFunc: Could not load ct and cst file');
0489 end
0490
0491 if ismember('ct',AllVarNames) && ismember('cst',AllVarNames)
0492 handles = reloadGUI(hObject, handles, ct, cst);
0493 else
0494 handles = reloadGUI(hObject, handles);
0495 end
0496
0497 guidata(hObject, handles);
0498
0499
0500 function validateModeValue(x)
0501
0502 if isdeployed || ischar(x) || isstring(x)
0503 x=str2double(x);
0504 end
0505 validateattributes(x,{'logical','numeric'},{'scalar','binary'});
0506
0507
0508
0509 function Callback_StructVisibilty(source,~)
0510
0511 handles = guidata(findobj('Name','matRadGUI'));
0512
0513 contextUiChildren = get(get(handles.figure1,'UIContextMenu'),'Children');
0514
0515 Idx = find(strcmp(get(contextUiChildren,'Label'),get(source,'Label')));
0516 if strcmp(get(source,'Checked'),'on')
0517 set(contextUiChildren(Idx),'Checked','off');
0518 else
0519 set(contextUiChildren(Idx),'Checked','on');
0520 end
0521
0522 UpdatePlot(handles);
0523
0524
0525 function varargout = matRadGUI_OutputFcn(~, ~, handles)
0526
0527
0528
0529
0530
0531
0532 varargout{1} = handles.output;
0533
0534
0535 if isfield(handles,'ErrorDlg')
0536 figure(handles.ErrorDlg)
0537 end
0538
0539
0540 function btnLoadMat_Callback(hObject, ~, handles)
0541
0542
0543
0544
0545 [FileName, FilePath] = uigetfile('*.mat');
0546 if FileName == 0
0547 return;
0548 end
0549
0550 handles = resetGUI(hObject, handles);
0551
0552 try
0553
0554
0555 AllVarNames = evalin('base','who');
0556 RefVarNames = {'ct','cst','pln','stf','dij','resultGUI'};
0557
0558 for i = 1:length(RefVarNames)
0559 if sum(ismember(AllVarNames,RefVarNames{i}))>0
0560 evalin('base',['clear ', RefVarNames{i}]);
0561 end
0562 end
0563
0564
0565 load([FilePath FileName]);
0566 set(handles.legendTable,'String',{'no data loaded'});
0567 set(handles.popupDisplayOption,'String','no option available');
0568
0569 catch ME
0570 handles = showError(handles,'LoadMatFileFnc: Could not load *.mat file',ME);
0571
0572 guidata(hObject,handles);
0573 UpdateState(handles);
0574 UpdatePlot(handles);
0575 return
0576 end
0577
0578 try
0579 generateCstTable(handles,cst);
0580 handles.TableChanged = false;
0581 set(handles.popupTypeOfPlot,'Value',1);
0582 cst = matRad_computeVoiContoursWrapper(cst,ct);
0583
0584 assignin('base','ct',ct);
0585 assignin('base','cst',cst);
0586 handles.State = 1;
0587 catch ME
0588 handles = showError(handles,'LoadMatFileFnc: Could not load *.mat file',ME);
0589 end
0590
0591
0592 if exist('stf','var')
0593 assignin('base','stf',stf);
0594 end
0595 if exist('pln','var')
0596 assignin('base','pln',pln);
0597 end
0598 if exist('dij','var')
0599 assignin('base','dij',dij);
0600 end
0601
0602
0603
0604
0605 if exist('resultGUI','var')
0606 assignin('base','resultGUI',resultGUI);
0607
0608
0609 end
0610
0611
0612 AllVarNames = evalin('base','who');
0613 handles.AllVarNames = AllVarNames;
0614
0615 if ismember('ct',AllVarNames) && ismember('cst',AllVarNames)
0616 handles = reloadGUI(hObject, handles, ct, cst);
0617 else
0618 handles = reloadGUI(hObject, handles);
0619 end
0620
0621 guidata(hObject,handles);
0622
0623
0624 function btnLoadDicom_Callback(hObject, ~, handles)
0625
0626
0627
0628 try
0629
0630 set(handles.popupDisplayOption,'String','no option available');
0631 AllVarNames = evalin('base','who');
0632 RefVarNames = {'ct','cst','pln','stf','dij','resultGUI'};
0633 for i = 1:length(RefVarNames)
0634 if sum(ismember(AllVarNames,RefVarNames{i}))>0
0635 evalin('base',['clear ', RefVarNames{i}]);
0636 end
0637 end
0638 handles.State = 0;
0639 matRad_importDicomGUI;
0640
0641 catch
0642 handles = showError(handles,'DicomImport: Could not import data');
0643 end
0644 UpdateState(handles);
0645 guidata(hObject,handles);
0646
0647
0648
0649 function btn_export_Callback(hObject, eventdata, handles)
0650
0651
0652
0653
0654 try
0655 matRad_exportGUI;
0656 catch
0657 handles = showError(handles,'Could not export data');
0658 end
0659 UpdateState(handles);
0660 guidata(hObject,handles);
0661
0662 function editBixelWidth_Callback(hObject, ~, handles)
0663
0664
0665
0666
0667
0668
0669 getPlnFromGUI(handles);
0670 if handles.State > 0
0671 handles.State = 1;
0672 UpdateState(handles);
0673 guidata(hObject,handles);
0674 end
0675
0676 function editGantryAngle_Callback(hObject, ~, handles)
0677
0678
0679
0680
0681
0682
0683 getPlnFromGUI(handles);
0684 if handles.State > 0
0685 handles.State = 1;
0686 UpdateState(handles);
0687 UpdatePlot(handles);
0688 guidata(hObject,handles);
0689 end
0690
0691 function editCouchAngle_Callback(hObject, ~, handles)
0692
0693
0694
0695
0696
0697
0698 getPlnFromGUI(handles);
0699 if handles.State > 0
0700 handles.State = 1;
0701 UpdateState(handles);
0702 guidata(hObject,handles);
0703 end
0704
0705
0706 function popupRadMode_Callback(hObject, eventdata, handles)
0707
0708
0709
0710 checkRadiationComposition(handles);
0711 contents = cellstr(get(hObject,'String'));
0712 RadIdentifier = contents{get(hObject,'Value')};
0713 contentPopUp = get(handles.popMenuBioOpt,'String');
0714 switch RadIdentifier
0715 case 'photons'
0716
0717 set(handles.popMenuBioOpt,'Enable','off');
0718 ix = find(strcmp(contentPopUp,'none'));
0719 set(handles.popMenuBioOpt,'Value',ix);
0720 set(handles.btnSetTissue,'Enable','off');
0721
0722 set(handles.btnRunSequencing,'Enable','on');
0723 set(handles.btnRunDAO,'Enable','on');
0724 set(handles.radiobutton3Dconf,'Enable','on');
0725 set(handles.txtSequencing,'Enable','on');
0726 set(handles.editSequencingLevel,'Enable','on');
0727
0728 case 'protons'
0729
0730 set(handles.popMenuBioOpt,'Enable','on');
0731 ix = find(strcmp(contentPopUp,'const_RBExD'));
0732 set(handles.popMenuBioOpt,'Value',ix);
0733 set(handles.btnSetTissue,'Enable','on');
0734
0735 set(handles.btnSetTissue,'Enable','off');
0736 set(handles.btnRunSequencing,'Enable','off');
0737 set(handles.btnRunDAO,'Enable','off');
0738 set(handles.radiobutton3Dconf,'Enable','off');
0739 set(handles.txtSequencing,'Enable','off');
0740 set(handles.editSequencingLevel,'Enable','off');
0741
0742 case 'carbon'
0743
0744 set(handles.popMenuBioOpt,'Enable','on');
0745 ix = find(strcmp(contentPopUp,'LEMIV_RBExD'));
0746 set(handles.popMenuBioOpt,'Value',ix);
0747 set(handles.btnSetTissue,'Enable','on');
0748
0749 set(handles.btnRunSequencing,'Enable','off');
0750 set(handles.btnRunDAO,'Enable','off');
0751 set(handles.radiobutton3Dconf,'Enable','off');
0752 set(handles.txtSequencing,'Enable','off');
0753 set(handles.editSequencingLevel,'Enable','off');
0754 end
0755
0756 if handles.State > 0
0757 pln = evalin('base','pln');
0758 if handles.State > 0 && ~strcmp(contents(get(hObject,'Value')),pln.radiationMode)
0759
0760
0761 if strcmp(contents(get(hObject,'Value')),'photons')
0762 try
0763 AllVarNames = evalin('base','who');
0764 if ismember('resultGUI',AllVarNames)
0765 resultGUI = evalin('base','resultGUI');
0766 if isfield(resultGUI,'alpha'); resultGUI = rmfield(resultGUI,'alpha'); end
0767 if isfield(resultGUI,'beta'); resultGUI = rmfield(resultGUI,'beta'); end
0768 if isfield(resultGUI,'RBExDose'); resultGUI = rmfield(resultGUI,'RBExDose');end
0769 if isfield(resultGUI,'RBE'); resultGUI = rmfield(resultGUI,'RBE'); end
0770 assignin('base','resultGUI',resultGUI);
0771 handles = updateIsoDoseLineCache(handles);
0772 end
0773 catch
0774 end
0775 elseif strcmp(contents(get(hObject,'Value')),'protons')
0776 try
0777 AllVarNames = evalin('base','who');
0778 if ismember('resultGUI',AllVarNames)
0779 resultGUI = evalin('base','resultGUI');
0780 if isfield(resultGUI,'alpha'); resultGUI = rmfield(resultGUI,'alpha');end
0781 if isfield(resultGUI,'beta'); resultGUI = rmfield(resultGUI,'beta'); end
0782 if isfield(resultGUI,'RBE'); resultGUI = rmfield(resultGUI,'RBE'); end
0783 assignin('base','resultGUI',resultGUI);
0784 handles = updateIsoDoseLineCache(handles);
0785 end
0786 catch
0787 end
0788 end
0789
0790 guidata(hObject,handles);
0791 UpdatePlot(handles);
0792
0793 getPlnFromGUI(handles);
0794 handles.State = 1;
0795 UpdateState(handles);
0796
0797 end
0798
0799 guidata(hObject,handles);
0800
0801 end
0802
0803
0804
0805 function btnCalcDose_Callback(hObject, ~, handles)
0806
0807
0808
0809
0810
0811
0812
0813
0814 try
0815
0816
0817 Figures = gcf;
0818 set(Figures, 'pointer', 'watch');
0819 drawnow;
0820
0821 InterfaceObj = findobj(Figures,'Enable','on');
0822 set(InterfaceObj,'Enable','off');
0823
0824
0825
0826 getPlnFromGUI(handles);
0827
0828
0829
0830 pln = evalin('base','pln');
0831
0832 if length(pln.propStf.gantryAngles) ~= length(pln.propStf.couchAngles)
0833 handles = showWarning(handles,'number of gantryAngles != number of couchAngles');
0834 end
0835
0836 if ~checkRadiationComposition(handles)
0837 fileName = [pln.radiationMode '_' pln.machine];
0838 handles = showError(handles,errordlg(['Could not find the following machine file: ' fileName ]));
0839 guidata(hObject,handles);
0840 return;
0841 end
0842
0843
0844 if ~isfield(pln.propStf,'isoCenter')
0845 handles = showWarning(handles,'no iso center set - using center of gravity based on structures defined as TARGET');
0846 pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(evalin('base','cst'),evalin('base','ct'));
0847 assignin('base','pln',pln);
0848 elseif ~get(handles.checkIsoCenter,'Value')
0849 if ~strcmp(get(handles.editIsoCenter,'String'),'multiple isoCenter')
0850 pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1)*str2num(get(handles.editIsoCenter,'String'));
0851 end
0852 end
0853
0854 catch ME
0855 handles = showError(handles,'CalcDoseCallback: Error in preprocessing!',ME);
0856
0857 set(Figures, 'pointer', 'arrow');
0858 set(InterfaceObj,'Enable','on');
0859 guidata(hObject,handles);
0860 return;
0861 end
0862
0863
0864 try
0865 currPln = evalin('base','pln');
0866
0867
0868 if strcmp(pln.radiationMode,'photons') && get(handles.radiobutton3Dconf,'Value')
0869 currpln.propOpt.runDAO = true;
0870 end
0871 stf = matRad_generateStf(evalin('base','ct'),...
0872 evalin('base','cst'),...
0873 currPln);
0874 assignin('base','stf',stf);
0875 catch ME
0876 handles = showError(handles,'CalcDoseCallback: Error in steering file generation!',ME);
0877
0878 set(Figures, 'pointer', 'arrow');
0879 set(InterfaceObj,'Enable','on');
0880 guidata(hObject,handles);
0881 return;
0882 end
0883
0884
0885 try
0886 if strcmp(pln.radiationMode,'photons')
0887 dij = matRad_calcPhotonDose(evalin('base','ct'),stf,pln,evalin('base','cst'));
0888 elseif strcmp(pln.radiationMode,'protons') || strcmp(pln.radiationMode,'carbon')
0889 dij = matRad_calcParticleDose(evalin('base','ct'),stf,pln,evalin('base','cst'));
0890 end
0891
0892
0893 assignin('base','dij',dij);
0894 handles.State = 2;
0895 handles.TableChanged = false;
0896 UpdateState(handles);
0897 UpdatePlot(handles);
0898 guidata(hObject,handles);
0899 catch ME
0900 handles = showError(handles,'CalcDoseCallback: Error in dose calculation!',ME);
0901
0902 set(Figures, 'pointer', 'arrow');
0903 set(InterfaceObj,'Enable','on');
0904 guidata(hObject,handles);
0905 return;
0906 end
0907
0908
0909 set(Figures, 'pointer', 'arrow');
0910 set(InterfaceObj,'Enable','on');
0911
0912 guidata(hObject,handles);
0913
0914
0915
0916
0917 function UpdatePlot(handles)
0918
0919
0920
0921 axes(handles.axesFig);
0922
0923
0924
0925 drawnow;
0926
0927 defaultFontSize = 8;
0928 currAxes = axis(handles.axesFig);
0929 AxesHandlesCT_Dose = gobjects(0);
0930 AxesHandlesVOI = cell(0);
0931 AxesHandlesIsoDose = gobjects(0);
0932
0933 if handles.State == 0
0934 cla reset
0935 return
0936 elseif handles.State > 0
0937 ct = evalin('base','ct');
0938 cst = evalin('base','cst');
0939 pln = evalin('base','pln');
0940 end
0941
0942
0943 AllVarNames = evalin('base','who');
0944 if ismember('resultGUI',AllVarNames)
0945 Result = evalin('base','resultGUI');
0946 end
0947
0948 if exist('Result','var')
0949 if ~isempty(Result) && ~isempty(ct.cubeHU) && ~isfield(handles,'DispInfo')
0950
0951 DispInfo = fieldnames(Result);
0952
0953 for i = 1:size(DispInfo,1)
0954
0955
0956 if isstruct(Result.(DispInfo{i,1})) || isvector(Result.(DispInfo{i,1}))
0957 Result = rmfield(Result,DispInfo{i,1});
0958 DispInfo{i,2}=false;
0959 else
0960
0961 DispInfo{i,2} = true;
0962
0963 if strfind(DispInfo{i,1},'physicalDose')
0964 DispInfo{i,3} = '[Gy]';
0965 elseif strfind(DispInfo{i,1},'alpha')
0966 DispInfo{i,3} = '[Gy^{-1}]';
0967 elseif strfind(DispInfo{i,1},'beta')
0968 DispInfo{i,3} = '[Gy^{-2}]';
0969 elseif strfind(DispInfo{i,1},'RBExD')
0970 DispInfo{i,3} = '[Gy(RBE)]';
0971 elseif strfind(DispInfo{i,1},'LET')
0972 DispInfo{i,3} = '[keV/um]';
0973 else
0974 DispInfo{i,3} = '[a.u.]';
0975 end
0976 DispInfo{i,4} = [];
0977 DispInfo{i,5} = [];
0978 end
0979 end
0980
0981 set(handles.popupDisplayOption,'String',fieldnames(Result));
0982 if sum(strcmp(handles.SelectedDisplayOption,fieldnames(Result))) == 0
0983 handles.SelectedDisplayOption = DispInfo{find([DispInfo{:,2}],1,'first'),1};
0984 end
0985 set(handles.popupDisplayOption,'Value',find(strcmp(handles.SelectedDisplayOption,fieldnames(Result))));
0986
0987 end
0988 end
0989
0990
0991 plane = get(handles.popupPlane,'Value');
0992 slice = round(get(handles.sliderSlice,'Value'));
0993 hold(handles.axesFig,'on');
0994 if get(handles.popupTypeOfPlot,'Value')==1
0995 set(handles.axesFig,'YDir','Reverse');
0996 end
0997
0998
0999 plotColorbarSelection = get(handles.popupmenu_chooseColorData,'Value');
1000
1001 if get(handles.popupTypeOfPlot,'Value')==2 || plotColorbarSelection == 1
1002 if isfield(handles,'cBarHandel')
1003 delete(handles.cBarHandel);
1004 end
1005
1006
1007 ch = findall(gcf,'tag','Colorbar');
1008 if ~isempty(ch)
1009 delete(ch);
1010 end
1011 end
1012
1013 selectIx = get(handles.popupmenu_chooseColorData,'Value');
1014
1015 cla(handles.axesFig);
1016
1017 if ~isempty(ct) && get(handles.popupTypeOfPlot,'Value')==1
1018
1019 if selectIx == 3
1020 ctIx = 2;
1021 else
1022 ctIx = selectIx;
1023 end
1024
1025 if handles.cubeHUavailable
1026 plotCtCube = ct.cubeHU;
1027 ctLabel = 'Hounsfield Units';
1028 else
1029 plotCtCube = ct.cube;
1030 ctLabel = 'Electron Density / WEQ';
1031 end
1032
1033 ctMap = matRad_getColormap(handles.ctColorMap,handles.cMapSize);
1034
1035 if isempty(handles.dispWindow{ctIx,2})
1036 handles.dispWindow{ctIx,2} = [min(reshape([ct.cubeHU{:}],[],1)) max(reshape([ct.cubeHU{:}],[],1))];
1037 end
1038
1039 if get(handles.radiobtnCT,'Value')
1040 [AxesHandlesCT_Dose(end+1),~,handles.dispWindow{ctIx,1}] = matRad_plotCtSlice(handles.axesFig,plotCtCube,1,plane,slice,ctMap,handles.dispWindow{ctIx,1});
1041
1042
1043 if plotColorbarSelection == 2 && handles.cBarChanged
1044
1045 handles.cBarHandel = matRad_plotColorbar(handles.axesFig,ctMap,handles.dispWindow{ctIx,1},'fontsize',defaultFontSize);
1046
1047 set(get(handles.cBarHandel,'ylabel'),'String', ctLabel,'fontsize',defaultFontSize);
1048
1049 set(get(handles.cBarHandel,'ylabel'),'interpreter','none');
1050 end
1051 end
1052 end
1053
1054
1055 if handles.State >= 1 && get(handles.popupTypeOfPlot,'Value')== 1 && exist('Result','var')
1056 doseMap = matRad_getColormap(handles.doseColorMap,handles.cMapSize);
1057 doseIx = 3;
1058
1059
1060 if ~isfield(Result,handles.SelectedDisplayOption)
1061 CubeNames = fieldnames(Result);
1062 handles.SelectedDisplayOption = CubeNames{1,1};
1063 end
1064
1065 dose = Result.(handles.SelectedDisplayOption);
1066
1067
1068 if ~isempty(dose) && ~isvector(dose)
1069
1070 if isempty(handles.dispWindow{doseIx,2})
1071 handles.dispWindow{doseIx,2} = [min(dose(:)) max(dose(:))];
1072 end
1073
1074 if get(handles.radiobtnDose,'Value')
1075 [doseHandle,~,handles.dispWindow{doseIx,1}] = matRad_plotDoseSlice(handles.axesFig,dose,plane,slice,handles.CutOffLevel,handles.doseOpacity,doseMap,handles.dispWindow{doseIx,1});
1076 AxesHandlesCT_Dose(end+1) = doseHandle;
1077 end
1078
1079
1080 if plotColorbarSelection > 2 && handles.cBarChanged
1081
1082 handles.cBarHandel = matRad_plotColorbar(handles.axesFig,doseMap,handles.dispWindow{selectIx,1},'fontsize',defaultFontSize);
1083
1084 Idx = find(strcmp(handles.SelectedDisplayOption,DispInfo(:,1)));
1085 set(get(handles.cBarHandel,'ylabel'),'String', [DispInfo{Idx,1} ' ' DispInfo{Idx,3} ],'fontsize',defaultFontSize);
1086
1087 set(get(handles.cBarHandel,'ylabel'),'interpreter','none');
1088 end
1089 end
1090
1091
1092
1093 if get(handles.radiobtnIsoDoseLines,'Value')
1094 plotLabels = get(handles.radiobtnIsoDoseLinesLabels,'Value') == 1;
1095
1096
1097
1098 if ~isfield(handles.IsoDose,'Contours')
1099 try
1100 handles.IsoDose.Contours = matRad_computeIsoDoseContours(dose,handles.IsoDose.Levels);
1101 catch
1102
1103
1104
1105
1106 handles.IsoDose.Contours = [];
1107 warning('Could not compute isodose lines! Will try slower contour function!');
1108 end
1109 end
1110 AxesHandlesIsoDose = matRad_plotIsoDoseLines(handles.axesFig,dose,handles.IsoDose.Contours,handles.IsoDose.Levels,plotLabels,plane,slice,doseMap,handles.dispWindow{doseIx,1},'LineWidth',1.5);
1111 end
1112 end
1113
1114 selectIx = get(handles.popupmenu_chooseColorData,'Value');
1115 set(handles.txtMinVal,'String',num2str(handles.dispWindow{selectIx,2}(1,1)));
1116 set(handles.txtMaxVal,'String',num2str(handles.dispWindow{selectIx,2}(1,2)));
1117
1118
1119 if get(handles.radiobtnContour,'Value') && get(handles.popupTypeOfPlot,'Value')==1 && handles.State>0
1120 AxesHandlesVOI = [AxesHandlesVOI matRad_plotVoiContourSlice(handles.axesFig,cst,ct,1,handles.VOIPlotFlag,plane,slice,[],'LineWidth',2)];
1121 end
1122
1123
1124 matRad_plotAxisLabels(handles.axesFig,ct,plane,slice,defaultFontSize);
1125
1126 if get(handles.radioBtnIsoCenter,'Value') == 1 && get(handles.popupTypeOfPlot,'Value') == 1 && ~isempty(pln)
1127 hIsoCenterCross = matRad_plotIsoCenterMarker(handles.axesFig,pln,ct,plane,slice);
1128 end
1129
1130 if get(handles.radiobtnPlan,'value') == 1 && ~isempty(pln)
1131 matRad_plotProjectedGantryAngles(handles.axesFig,pln,ct,plane);
1132 end
1133
1134
1135
1136
1137
1138 ratios = [1/ct.resolution.x 1/ct.resolution.y 1/ct.resolution.z];
1139 set(handles.axesFig,'DataAspectRatioMode','manual');
1140 if plane == 1
1141 res = [ratios(3) ratios(1)]./max([ratios(3) ratios(1)]);
1142 set(handles.axesFig,'DataAspectRatio',[res 1])
1143 elseif plane == 2
1144 res = [ratios(3) ratios(2)]./max([ratios(3) ratios(2)]);
1145 set(handles.axesFig,'DataAspectRatio',[res 1])
1146 elseif plane == 3
1147 res = [ratios(1) ratios(2)]./max([ratios(1) ratios(2)]);
1148 set(handles.axesFig,'DataAspectRatio',[res 1])
1149 end
1150
1151
1152
1153 if get(handles.popupTypeOfPlot,'Value') == 2 && exist('Result','var')
1154
1155 fileName = [pln.radiationMode '_' pln.machine];
1156 try
1157 load(['basedata' filesep fileName]);
1158 SAD = machine.meta.SAD;
1159 catch
1160 error(['Could not find the following machine file: ' fileName ]);
1161 end
1162
1163
1164 cla(handles.axesFig,'reset')
1165 set(gca,'YDir','normal');
1166 ylabel('{\color{black}dose [Gy]}')
1167 cColor={'black','green','magenta','cyan','yellow','red','blue'};
1168
1169
1170
1171 rotMat_system_T = transpose(matRad_getRotationMatrix(pln.propStf.gantryAngles(handles.selectedBeam),pln.propStf.couchAngles(handles.selectedBeam)));
1172
1173 if strcmp(handles.ProfileType,'longitudinal')
1174 sourcePointBEV = [handles.profileOffset -SAD 0];
1175 targetPointBEV = [handles.profileOffset SAD 0];
1176 elseif strcmp(handles.ProfileType,'lateral')
1177 sourcePointBEV = [-SAD handles.profileOffset 0];
1178 targetPointBEV = [ SAD handles.profileOffset 0];
1179 end
1180
1181 rotSourcePointBEV = sourcePointBEV * rotMat_system_T;
1182 rotTargetPointBEV = targetPointBEV * rotMat_system_T;
1183
1184
1185
1186 [~,l,rho,~,ix] = matRad_siddonRayTracer(pln.propStf.isoCenter(handles.selectedBeam,:),ct.resolution,rotSourcePointBEV,rotTargetPointBEV,{0*ct.cubeHU{1}+1});
1187 d = [0 l .* rho{1}];
1188
1189 vX = cumsum(d(1:end-1));
1190
1191
1192
1193 figHandles = get(0,'Children');
1194 idxHandle = [];
1195 if ~isempty(figHandles)
1196 v=version;
1197 if str2double(v(1:3))>= 8.5
1198 idxHandle = strcmp({figHandles(:).Name},'matRadGUI');
1199 else
1200 idxHandle = strcmp(get(figHandles,'Name'),'matRadGUI');
1201 end
1202 end
1203 figure(figHandles(idxHandle));
1204
1205
1206 Content = get(handles.popupDisplayOption,'String');
1207 SelectedCube = Content{get(handles.popupDisplayOption,'Value')};
1208 if sum(strcmp(SelectedCube,{'physicalDose','effect','RBExDose','alpha','beta','RBE'})) > 0
1209 Suffix = '';
1210 else
1211 Idx = find(SelectedCube == '_');
1212 Suffix = SelectedCube(Idx:end);
1213 end
1214
1215 mPhysDose = Result.(['physicalDose' Suffix]);
1216 PlotHandles{1} = plot(handles.axesFig,vX,mPhysDose(ix),'color',cColor{1,1},'LineWidth',3); hold on;
1217 PlotHandles{1,2} ='physicalDose';
1218 ylabel(handles.axesFig,'dose in [Gy]');
1219 set(handles.axesFig,'FontSize',defaultFontSize);
1220
1221
1222 Cnt=2;
1223
1224 if isfield(Result,['RBE' Suffix])
1225
1226
1227
1228
1229
1230
1231
1232 StringYLabel1 = '\fontsize{8}{\color{red}RBE x dose [Gy(RBE)] \color{black}dose [Gy] ';
1233 StringYLabel2 = '';
1234 for i=1:1:size(DispInfo,1)
1235 if DispInfo{i,2} && sum(strcmp(DispInfo{i,1},{['effect' Suffix],['alpha' Suffix],['beta' Suffix]})) > 0
1236
1237 if ~strcmp(DispInfo{i,1},['RBExDose' Suffix]) &&...
1238 ~strcmp(DispInfo{i,1},['RBE' Suffix]) && ...
1239 ~strcmp(DispInfo{i,1},['physicalDose' Suffix])
1240
1241 mCube = Result.([DispInfo{i,1}]);
1242 PlotHandles{Cnt,1} = plot(handles.axesFig,vX,mCube(ix),'color',cColor{1,Cnt},'LineWidth',3);hold on;
1243 PlotHandles{Cnt,2} = DispInfo{i,1};
1244 StringYLabel2 = [StringYLabel2 ' \color{' cColor{1,Cnt} '}' DispInfo{i,1} ' [' DispInfo{i,3} ']'];
1245 Cnt = Cnt+1;
1246 end
1247 end
1248 end
1249 StringYLabel2 = [StringYLabel2 '}'];
1250
1251 mRBExDose = Result.(['RBExDose' Suffix]);
1252 vBED = mRBExDose(ix);
1253 mRBE = Result.(['RBE' Suffix]);
1254 vRBE = mRBE(ix);
1255
1256
1257 [ax, PlotHandles{Cnt,1}, PlotHandles{Cnt+1,1}]=plotyy(handles.axesFig,vX,vBED,vX,vRBE,'plot');hold on;
1258 PlotHandles{Cnt,2}='RBExDose';
1259 PlotHandles{Cnt+1,2}='RBE';
1260
1261
1262 set(get(ax(2),'Ylabel'),'String','RBE [a.u.]','FontSize',8);
1263 ylabel({StringYLabel1;StringYLabel2})
1264 set(PlotHandles{Cnt,1},'Linewidth',4,'color','r');
1265 set(PlotHandles{Cnt+1,1},'Linewidth',3,'color','b');
1266 set(ax(1),'ycolor','r')
1267 set(ax(2),'ycolor','b')
1268 set(ax,'FontSize',8);
1269 Cnt=Cnt+2;
1270 end
1271
1272
1273 tmpPrior = intmax;
1274 tmpSize = 0;
1275 for i=1:size(cst,1)
1276 if strcmp(cst{i,3},'TARGET') && tmpPrior >= cst{i,5}.Priority && tmpSize<numel(cst{i,4}{1})
1277 linIdxTarget = unique(cst{i,4}{1});
1278 tmpPrior=cst{i,5}.Priority;
1279 tmpSize=numel(cst{i,4}{1});
1280 VOI = cst{i,2};
1281 end
1282 end
1283
1284 str = sprintf('profile plot - central axis of %d beam gantry angle %d? couch angle %d?',...
1285 handles.selectedBeam ,pln.propStf.gantryAngles(handles.selectedBeam),pln.propStf.couchAngles(handles.selectedBeam));
1286 h_title = title(handles.axesFig,str,'FontSize',defaultFontSize);
1287 pos = get(h_title,'Position');
1288 set(h_title,'Position',[pos(1)-40 pos(2) pos(3)])
1289
1290
1291 mTargetCube = zeros(ct.cubeDim);
1292 mTargetCube(linIdxTarget) = 1;
1293 vProfile = mTargetCube(ix);
1294 WEPL_Target_Entry = vX(find(vProfile,1,'first'));
1295 WEPL_Target_Exit = vX(find(vProfile,1,'last'));
1296 PlotHandles{Cnt,2} =[VOI ' boundary'];
1297
1298 if ~isempty(WEPL_Target_Entry) && ~isempty(WEPL_Target_Exit)
1299 hold on
1300 PlotHandles{Cnt,1} = ...
1301 plot([WEPL_Target_Entry WEPL_Target_Entry],get(handles.axesFig,'YLim'),'--','Linewidth',3,'color','k');hold on
1302 plot([WEPL_Target_Exit WEPL_Target_Exit],get(handles.axesFig,'YLim'),'--','Linewidth',3,'color','k');hold on
1303
1304 else
1305 PlotHandles{Cnt,1} =[];
1306 end
1307
1308 Lines = PlotHandles(~cellfun(@isempty,PlotHandles(:,1)),1);
1309 Labels = PlotHandles(~cellfun(@isempty,PlotHandles(:,1)),2);
1310 h=legend(handles.axesFig,[Lines{:}],Labels{:});
1311 set(h,'FontSize',defaultFontSize);
1312 xlabel('radiological depth [mm]','FontSize',8);
1313 grid on, grid minor
1314
1315 end
1316
1317 zoom(handles.figure1,'reset');
1318 axis(handles.axesFig,'tight');
1319
1320
1321 if isfield(handles,'rememberCurrAxes') && handles.rememberCurrAxes
1322 axis(currAxes);
1323 end
1324
1325 hold(handles.axesFig,'off');
1326
1327 handles.cBarChanged = false;
1328 guidata(handles.axesFig,handles);
1329
1330 if get(handles.popupTypeOfPlot,'Value')==1
1331 UpdateColormapOptions(handles);
1332 end
1333
1334 Update3DView(handles);
1335
1336
1337
1338
1339 function Update3DView(handles)
1340
1341 if isfield(handles,'axesFig3D') && isfield(handles,'fig3D') && isgraphics(handles.axesFig3D) && isgraphics(handles.fig3D)
1342 axesFig3D = handles.axesFig3D;
1343 fig3D = handles.fig3D;
1344 else
1345 return
1346 end
1347
1348 if handles.State == 0
1349 return
1350 elseif handles.State > 0
1351 AllVarNames = evalin('base','who');
1352 if ismember('resultGUI',AllVarNames)
1353 Result = evalin('base','resultGUI');
1354 end
1355
1356 if ismember('stf',AllVarNames)
1357 stf = evalin('base','stf');
1358 else
1359 stf = [];
1360 end
1361
1362 ct = evalin('base','ct');
1363 cst = evalin('base','cst');
1364 pln = evalin('base','pln');
1365 end
1366
1367 oldView = get(axesFig3D,'View');
1368
1369 cla(axesFig3D);
1370
1371
1372
1373
1374 plane = get(handles.popupPlane,'Value');
1375 slice = round(get(handles.sliderSlice,'Value'));
1376 defaultFontSize = 8;
1377
1378
1379 if size(cst,2) < 8
1380 cst = matRad_computeAllVoiSurfaces(ct,cst);
1381 assignin('base','cst',cst);
1382 end
1383
1384 set(fig3D,'Color',0.5*[1 1 1]);
1385 set(axesFig3D,'Color',1*[0 0 0]);
1386
1387
1388 hold(axesFig3D,'on');
1389 if get(handles.radiobtnContour,'Value') && handles.State>0
1390 voiPatches = matRad_plotVois3D(axesFig3D,ct,cst,handles.VOIPlotFlag,colorcube);
1391 end
1392
1393
1394 if get(handles.radiobtnCT,'Value')
1395 window = handles.dispWindow{2,1};
1396 ctMap = matRad_getColormap(handles.ctColorMap,handles.cMapSize);
1397 ctHandle = matRad_plotCtSlice3D(axesFig3D,ct,1,plane,slice,ctMap,window);
1398 end
1399
1400
1401 if handles.State >= 1 && exist('Result','var')
1402 doseMap = matRad_getColormap(handles.doseColorMap,handles.cMapSize);
1403 doseIx = 3;
1404
1405
1406 if ~isfield(Result,handles.SelectedDisplayOption)
1407 CubeNames = fieldnames(Result);
1408 handles.SelectedDisplayOption = CubeNames{1,1};
1409 end
1410
1411 dose = Result.(handles.SelectedDisplayOption);
1412
1413
1414 if ~isempty(dose) && ~isvector(dose)
1415
1416 if isempty(handles.dispWindow{doseIx,2})
1417 handles.dispWindow{doseIx,2} = [min(dose(:)) max(dose(:))];
1418 end
1419
1420 if get(handles.radiobtnDose,'Value')
1421 [doseHandle,~,handles.dispWindow{doseIx,1}] = matRad_plotDoseSlice3D(axesFig3D,ct,dose,plane,slice,handles.CutOffLevel,handles.doseOpacity,doseMap,handles.dispWindow{doseIx,1});
1422 end
1423 if get(handles.radiobtnIsoDoseLines,'Value')
1424 matRad_plotIsoDoseLines3D(axesFig3D,ct,dose,handles.IsoDose.Contours,handles.IsoDose.Levels,plane,slice,doseMap,handles.dispWindow{doseIx,1},'LineWidth',1.5);
1425 end
1426 end
1427 end
1428
1429 if get(handles.radiobtnPlan,'Value')
1430 matRad_plotPlan3D(axesFig3D,pln,stf);
1431 end
1432
1433
1434
1435
1436
1437 xlabel(axesFig3D,'x [voxels]','FontSize',defaultFontSize)
1438 ylabel(axesFig3D,'y [voxels]','FontSize',defaultFontSize)
1439 zlabel(axesFig3D,'z [voxels]','FontSize',defaultFontSize)
1440 title(axesFig3D,'matRad 3D view');
1441
1442
1443 ratios = [1 1 1];
1444 ratios = ratios([2 1 3]);
1445 set(axesFig3D,'DataAspectRatioMode','manual');
1446 set(axesFig3D,'DataAspectRatio',ratios./max(ratios));
1447
1448 set(axesFig3D,'Ydir','reverse');
1449
1450 set(axesFig3D,'view',oldView);
1451
1452
1453
1454 function popupPlane_Callback(hObject, ~, handles)
1455
1456
1457
1458
1459
1460
1461
1462
1463 handles.plane = get(hObject,'value');
1464 initViewSliceSlider(handles);
1465
1466 handles.rememberCurrAxes = false;
1467 UpdatePlot(handles);
1468 handles.rememberCurrAxes = true;
1469 guidata(hObject,handles);
1470
1471
1472 function sliderSlice_Callback(~, ~, handles)
1473
1474
1475
1476
1477
1478
1479 UpdatePlot(handles)
1480
1481
1482 function radiobtnContour_Callback(~, ~, handles)
1483
1484
1485
1486
1487
1488 UpdatePlot(handles)
1489
1490
1491 function radiobtnDose_Callback(~, ~, handles)
1492
1493
1494
1495
1496
1497 UpdatePlot(handles)
1498
1499
1500 function radiobtnIsoDoseLines_Callback(~, ~, handles)
1501
1502
1503
1504
1505
1506 UpdatePlot(handles)
1507
1508
1509 function btnOptimize_Callback(hObject, eventdata, handles)
1510
1511
1512
1513
1514 try
1515
1516
1517 Figures = gcf;
1518 set(Figures, 'pointer', 'watch');
1519 drawnow;
1520
1521 InterfaceObj = findobj(Figures,'Enable','on');
1522 set(InterfaceObj,'Enable','off');
1523
1524 btnTableSave_Callback([],[],handles);
1525
1526
1527
1528 if handles.DijCalcWarning == true
1529
1530 choice = questdlg('Overlap priorites of OAR constraints have been edited, a new OAR VOI was added or a critical row constraint was deleted. A new Dij calculation might be necessary.', ...
1531 'Title','Cancel','Calculate Dij then Optimize','Optimze directly','Optimze directly');
1532
1533 switch choice
1534 case 'Cancel'
1535 set(Figures, 'pointer', 'arrow');
1536 set(InterfaceObj,'Enable','on');
1537 guidata(hObject,handles);
1538 return;
1539 case 'Calculate dij again and optimize'
1540 handles.DijCalcWarning = false;
1541 btnCalcDose_Callback(hObject, eventdata, handles)
1542 case 'Optimze directly'
1543 handles.DijCalcWarning = false;
1544 end
1545 end
1546
1547 pln = evalin('base','pln');
1548 ct = evalin('base','ct');
1549
1550
1551 if get(handles.radiobutton3Dconf,'Value') && strcmp(handles.Modalities{get(handles.popupRadMode,'Value')},'photons')
1552
1553 if ~matRad_checkForConnectedBixelRows(evalin('base','stf'))
1554 error('disconnetced dose influence data in BEV - run dose calculation again with consistent settings');
1555 end
1556 [resultGUIcurrentRun,usedOptimizer] = matRad_fluenceOptimization(matRad_collapseDij(evalin('base','dij')),evalin('base','cst'),pln);
1557 resultGUIcurrentRun.w = resultGUIcurrentRun.w * ones(evalin('base','dij.totalNumOfBixels'),1);
1558 resultGUIcurrentRun.wUnsequenced = resultGUIcurrentRun.w;
1559 else
1560 if pln.propOpt.runDAO
1561 if ~matRad_checkForConnectedBixelRows(evalin('base','stf'))
1562 error('disconnetced dose influence data in BEV - run dose calculation again with consistent settings');
1563 end
1564 end
1565
1566 [resultGUIcurrentRun,usedOptimizer] = matRad_fluenceOptimization(evalin('base','dij'),evalin('base','cst'),pln);
1567 end
1568
1569
1570 AllVarNames = evalin('base','who');
1571 if ismember('resultGUI',AllVarNames)
1572 resultGUI = evalin('base','resultGUI');
1573 sNames = fieldnames(resultGUIcurrentRun);
1574 oldNames = fieldnames(resultGUI);
1575 if(length(oldNames) > length(sNames))
1576 for j = 1:length(oldNames)
1577 if strfind(oldNames{j}, 'beam')
1578 resultGUI = rmfield(resultGUI, oldNames{j});
1579 end
1580 end
1581 end
1582 for j = 1:length(sNames)
1583 resultGUI.(sNames{j}) = resultGUIcurrentRun.(sNames{j});
1584 end
1585 else
1586 resultGUI = resultGUIcurrentRun;
1587 end
1588 assignin('base','resultGUI',resultGUI);
1589
1590
1591 if handles.plane == 1
1592 set(handles.sliderSlice,'Value',ceil(pln.propStf.isoCenter(1,2)/ct.resolution.x));
1593 elseif handles.plane == 2
1594 set(handles.sliderSlice,'Value',ceil(pln.propStf.isoCenter(1,1)/ct.resolution.y));
1595 elseif handles.plane == 3
1596 set(handles.sliderSlice,'Value',ceil(pln.propStf.isoCenter(1,3)/ct.resolution.z));
1597 end
1598
1599 handles.State = 3;
1600 handles.SelectedDisplayOptionIdx = 1;
1601 if strcmp(pln.radiationMode,'carbon') || (strcmp(pln.radiationMode,'protons') && strcmp(pln.propOpt.bioOptimization,'const_RBExD'))
1602 handles.SelectedDisplayOption = 'RBExDose';
1603 else
1604 handles.SelectedDisplayOption = 'physicalDose';
1605 end
1606 handles.selectedBeam = 1;
1607
1608
1609 if ~pln.propOpt.runDAO || ~strcmp(pln.radiationMode,'photons')
1610 CheckOptimizerStatus(usedOptimizer,'Fluence')
1611 end
1612
1613 catch ME
1614 handles = showError(handles,'OptimizeCallback: Could not optimize!',ME);
1615
1616 set(Figures, 'pointer', 'arrow');
1617 set(InterfaceObj,'Enable','on');
1618 guidata(hObject,handles);
1619 return;
1620 end
1621
1622
1623 try
1624
1625
1626 if strcmp(pln.radiationMode,'photons') && (pln.propOpt.runSequencing || pln.propOpt.runDAO)
1627
1628
1629
1630
1631 resultGUI = matRad_siochiLeafSequencing(resultGUI,evalin('base','stf'),evalin('base','dij')...
1632 ,str2double(get(handles.editSequencingLevel,'String')));
1633
1634 assignin('base','resultGUI',resultGUI);
1635 end
1636
1637 catch ME
1638 handles = showError(handles,'OptimizeCallback: Could not perform sequencing',ME);
1639
1640 set(Figures, 'pointer', 'arrow');
1641 set(InterfaceObj,'Enable','on');
1642 guidata(hObject,handles);
1643 return;
1644 end
1645
1646 try
1647
1648 if strcmp(pln.radiationMode,'photons') && pln.propOpt.runDAO
1649 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.']);
1650 [resultGUI,usedOptimizer] = matRad_directApertureOptimization(evalin('base','dij'),evalin('base','cst'),...
1651 resultGUI.apertureInfo,resultGUI,pln);
1652 assignin('base','resultGUI',resultGUI);
1653
1654 CheckOptimizerStatus(usedOptimizer,'DAO');
1655 end
1656
1657 if strcmp(pln.radiationMode,'photons') && (pln.propOpt.runSequencing || pln.propOpt.runDAO)
1658 matRad_visApertureInfo(resultGUI.apertureInfo);
1659 end
1660
1661 catch ME
1662 handles = showError(handles,'OptimizeCallback: Could not perform direct aperture optimization',ME);
1663
1664 set(Figures, 'pointer', 'arrow');
1665 set(InterfaceObj,'Enable','on');
1666 guidata(hObject,handles);
1667 return;
1668 end
1669
1670
1671 set(Figures, 'pointer', 'arrow');
1672 set(InterfaceObj,'Enable','on');
1673 handles.dispWindow{3,1} = [];
1674 handles.dispWindow{3,2} = [];
1675 handles.rememberCurrAxes = false;
1676 handles.IsoDose.Levels = 0;
1677 handles.cBarChanged = true;
1678
1679 guidata(hObject,handles);
1680 handles = updateIsoDoseLineCache(handles);
1681 UpdateState(handles);
1682 UpdatePlot(handles);
1683 handles.rememberCurrAxes = true;
1684 guidata(hObject,handles);
1685
1686
1687
1688
1689 function FlagValid = CheckValidityPln(cst)
1690
1691 FlagValid = true;
1692
1693 for i = 1:size(cst,1)
1694 if ~isempty(cst{i,6})
1695 if ~isempty(strfind([cst{i,6}.type],'mean')) && isempty(strfind([cst{i,6}.type],'square'))
1696 FlagValid = false;
1697 warndlg('mean constraint needs to be defined in addition to a second constraint (e.g. squared deviation)');
1698 break
1699 end
1700 end
1701 end
1702
1703
1704
1705 function popupTypeOfPlot_Callback(hObject, ~, handles)
1706
1707
1708 if get(hObject,'Value') == 1
1709
1710 set(handles.sliderBeamSelection,'Enable','off')
1711 set(handles.sliderOffset,'Enable','off')
1712 set(handles.popupDisplayOption,'Enable','on')
1713 set(handles.btnProfileType,'Enable','off');
1714 set(handles.popupPlane,'Enable','on');
1715 set(handles.radiobtnCT,'Enable','on');
1716 set(handles.radiobtnContour,'Enable','on');
1717 set(handles.radiobtnDose,'Enable','on');
1718 set(handles.radiobtnIsoDoseLines,'Enable','on');
1719 set(handles.radiobtnIsoDoseLinesLabels,'Enable','on');
1720 set(handles.sliderSlice,'Enable','on');
1721
1722
1723 elseif get(hObject,'Value') == 2
1724
1725 if handles.State > 0
1726 if length(parseStringAsNum(get(handles.editGantryAngle,'String'),true)) > 1
1727
1728 set(handles.sliderBeamSelection,'Enable','on');
1729 handles.selectedBeam = 1;
1730 pln = evalin('base','pln');
1731 set(handles.sliderBeamSelection,'Min',handles.selectedBeam,'Max',pln.propStf.numOfBeams,...
1732 'Value',handles.selectedBeam,...
1733 'SliderStep',[1/(pln.propStf.numOfBeams-1) 1/(pln.propStf.numOfBeams-1)],...
1734 'Enable','on');
1735
1736 else
1737 handles.selectedBeam = 1;
1738 end
1739
1740 handles.profileOffset = get(handles.sliderOffset,'Value');
1741
1742 vMinMax = [-100 100];
1743 vRange = sum(abs(vMinMax));
1744
1745 ct = evalin('base','ct');
1746 if strcmp(get(handles.btnProfileType,'String'),'lateral')
1747 SliderStep = vRange/ct.resolution.x;
1748 else
1749 SliderStep = vRange/ct.resolution.y;
1750 end
1751
1752 set(handles.sliderOffset,'Min',vMinMax(1),'Max',vMinMax(2),...
1753 'Value',handles.profileOffset,...
1754 'SliderStep',[1/SliderStep 1/SliderStep],...
1755 'Enable','on');
1756 end
1757
1758
1759 set(handles.popupDisplayOption,'Enable','on');
1760 set(handles.btnProfileType,'Enable','on');
1761 set(handles.popupPlane,'Enable','off');
1762 set(handles.radiobtnCT,'Enable','off');
1763 set(handles.radiobtnContour,'Enable','off');
1764 set(handles.radiobtnDose,'Enable','off');
1765 set(handles.radiobtnIsoDoseLines,'Enable','off');
1766 set(handles.sliderSlice,'Enable','off');
1767 set(handles.radiobtnIsoDoseLinesLabels,'Enable','off');
1768
1769
1770 set(handles.btnProfileType,'Enable','on')
1771
1772 if strcmp(get(handles.btnProfileType,'String'),'lateral')
1773 handles.ProfileType = 'longitudinal';
1774 else
1775 handles.ProfileType = 'lateral';
1776 end
1777
1778 end
1779
1780 handles.cBarChanged = true;
1781
1782 handles.rememberCurrAxes = false;
1783 cla(handles.axesFig,'reset');
1784 UpdatePlot(handles);
1785 handles.rememberCurrAxes = true;
1786 guidata(hObject, handles);
1787
1788
1789 function popupDisplayOption_Callback(hObject, ~, handles)
1790 content = get(hObject,'String');
1791 handles.SelectedDisplayOption = content{get(hObject,'Value'),1};
1792 handles.SelectedDisplayOptionIdx = get(hObject,'Value');
1793
1794
1795 if ~isfield(handles,'colormapLocked') || ~handles.colormapLocked
1796 handles.dispWindow{3,1} = []; handles.dispWindow{3,2} = [];
1797 end
1798
1799 handles = updateIsoDoseLineCache(handles);
1800 handles.cBarChanged = true;
1801 guidata(hObject, handles);
1802 UpdatePlot(handles);
1803 guidata(hObject, handles);
1804
1805
1806 function sliderBeamSelection_Callback(hObject, ~, handles)
1807
1808
1809
1810
1811
1812
1813
1814
1815 handles.selectedBeam = round(get(hObject,'Value'));
1816 set(hObject, 'Value', handles.selectedBeam);
1817 handles.rememberCurrAxes = false;
1818 UpdatePlot(handles);
1819 handles.rememberCurrAxes = true;
1820 guidata(hObject,handles);
1821
1822
1823 function btnProfileType_Callback(hObject, ~, handles)
1824
1825
1826
1827 if strcmp(get(hObject,'Enable') ,'on')
1828 if strcmp(handles.ProfileType,'lateral')
1829 handles.ProfileType = 'longitudinal';
1830 set(hObject,'String','lateral');
1831 else
1832 handles.ProfileType = 'lateral';
1833 set(hObject,'String','longitudinal');
1834 end
1835
1836 handles.rememberCurrAxes = false;
1837 UpdatePlot(handles);
1838 handles.rememberCurrAxes = true;
1839
1840 guidata(hObject, handles);
1841
1842 end
1843
1844
1845 function UpdateState(handles)
1846
1847 if handles.State > 0
1848 pln = evalin('base','pln');
1849
1850 if strcmp(pln.radiationMode,'carbon')
1851 set(handles.popMenuBioOpt,'Enable','on');
1852 set(handles.btnSetTissue,'Enable','on');
1853 elseif strcmp(pln.radiationMode,'protons')
1854 set(handles.popMenuBioOpt,'Enable','on');
1855 set(handles.btnSetTissue,'Enable','off');
1856 else
1857 set(handles.popMenuBioOpt,'Enable','off');
1858 set(handles.btnSetTissue,'Enable','off');
1859 end
1860
1861 cMapControls = allchild(handles.uipanel_colormapOptions);
1862 for runHandles = cMapControls
1863 set(runHandles,'Enable','on');
1864 end
1865 end
1866
1867 if handles.cubeHUavailable
1868 cMapOptionsSelectList = {'None','CT (HU)','Result (i.e. dose)'};
1869 set(handles.popupmenu_windowPreset,'Visible','on');
1870 set(handles.text_windowPreset,'String','Window Preset');
1871 else
1872 cMapOptionsSelectList = {'None','CT (ED)','Result (i.e. dose)'};
1873 set(handles.popupmenu_windowPreset,'Visible','off');
1874 set(handles.text_windowPreset,'String','No available Window Presets');
1875 end
1876 handles.cBarChanged = true;
1877
1878 switch handles.State
1879
1880 case 0
1881
1882 set(handles.txtInfo,'String','no data loaded');
1883 set(handles.btnCalcDose,'Enable','off');
1884 set(handles.btnOptimize ,'Enable','off');
1885 set(handles.pushbutton_recalc,'Enable','off');
1886 set(handles.btnSaveToGUI,'Enable','off');
1887 set(handles.btnDVH,'Enable','off');
1888 set(handles.importDoseButton,'Enable','off');
1889 set(handles.btn_export,'Enable','off');
1890 set(handles.btn3Dview,'Enable','off');
1891
1892 cMapControls = allchild(handles.uipanel_colormapOptions);
1893 for runHandles = cMapControls
1894 set(runHandles,'Enable','off');
1895 end
1896
1897 set(handles.popupmenu_chooseColorData,'String',cMapOptionsSelectList{1})
1898 set(handles.popupmenu_chooseColorData,'Value',1);
1899
1900 case 1
1901
1902 set(handles.txtInfo,'String','ready for dose calculation');
1903 set(handles.btnCalcDose,'Enable','on');
1904 set(handles.btnOptimize ,'Enable','off');
1905 set(handles.pushbutton_recalc,'Enable','off');
1906 set(handles.btnSaveToGUI,'Enable','off');
1907 set(handles.btnDVH,'Enable','off');
1908 set(handles.importDoseButton,'Enable','off');
1909 set(handles.btn_export,'Enable','on');
1910 set(handles.btn3Dview,'Enable','on');
1911
1912 set(handles.popupmenu_chooseColorData,'String',cMapOptionsSelectList(1:2))
1913 set(handles.popupmenu_chooseColorData,'Value',2);
1914 AllVarNames = evalin('base','who');
1915 if ~isempty(AllVarNames)
1916 if ismember('resultGUI',AllVarNames)
1917 set(handles.pushbutton_recalc,'Enable','on');
1918 set(handles.btnSaveToGUI,'Enable','on');
1919 set(handles.btnDVH,'Enable','on');
1920 set(handles.popupmenu_chooseColorData,'String',cMapOptionsSelectList(1:3))
1921 set(handles.popupmenu_chooseColorData,'Value',3);
1922 end
1923 end
1924
1925 case 2
1926
1927 set(handles.txtInfo,'String','ready for optimization');
1928 set(handles.btnCalcDose,'Enable','on');
1929 set(handles.btnOptimize ,'Enable','on');
1930 set(handles.pushbutton_recalc,'Enable','off');
1931 set(handles.btnSaveToGUI,'Enable','off');
1932 set(handles.btnDVH,'Enable','off');
1933 set(handles.importDoseButton,'Enable','off');
1934 set(handles.btn_export,'Enable','on');
1935 set(handles.btn3Dview,'Enable','on');
1936 set(handles.popupmenu_chooseColorData,'String',cMapOptionsSelectList(1:2))
1937 set(handles.popupmenu_chooseColorData,'Value',2);
1938 AllVarNames = evalin('base','who');
1939
1940 if ~isempty(AllVarNames)
1941 if ismember('resultGUI',AllVarNames)
1942 set(handles.pushbutton_recalc,'Enable','on');
1943 set(handles.btnSaveToGUI,'Enable','on');
1944 set(handles.btnDVH,'Enable','on');
1945 set(handles.popupmenu_chooseColorData,'String',cMapOptionsSelectList(1:3))
1946 set(handles.popupmenu_chooseColorData,'Value',3);
1947 end
1948 end
1949
1950 case 3
1951 set(handles.txtInfo,'String','plan is optimized');
1952 set(handles.btnCalcDose,'Enable','on');
1953 set(handles.btnOptimize ,'Enable','on');
1954 set(handles.pushbutton_recalc,'Enable','on');
1955 set(handles.btnSaveToGUI,'Enable','on');
1956 set(handles.btnDVH,'Enable','on');
1957 set(handles.btn_export,'Enable','on');
1958 set(handles.btn3Dview,'Enable','on');
1959
1960
1961 set(handles.importDoseButton,'Enable','on');
1962 set(handles.popupmenu_chooseColorData,'String',cMapOptionsSelectList(1:3))
1963 set(handles.popupmenu_chooseColorData,'Value',3);
1964 end
1965
1966 guidata(handles.figure1,handles);
1967
1968
1969 function setPln(handles)
1970 pln = evalin('base','pln');
1971
1972 if size(pln.propStf.isoCenter,1) ~= pln.propStf.numOfBeams && size(pln.propStf.isoCenter,1) == 1
1973 pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * pln.propStf.isoCenter(1,:);
1974 elseif size(pln.propStf.isoCenter,1) ~= pln.propStf.numOfBeams && size(pln.propStf.isoCenter,1) ~= 1
1975 error('Isocenter in plan file are incosistent.');
1976 end
1977 set(handles.editBixelWidth,'String',num2str(pln.propStf.bixelWidth));
1978 set(handles.editFraction,'String',num2str(pln.numOfFractions));
1979
1980 if isfield(pln.propStf,'isoCenter')
1981 if size(unique(pln.propStf.isoCenter,'rows'),1) == 1
1982 set(handles.editIsoCenter,'String',regexprep(num2str((round(pln.propStf.isoCenter(1,:)*10))./10), '\s+', ' '));
1983 set(handles.editIsoCenter,'Enable','on');
1984 set(handles.checkIsoCenter,'Enable','on');
1985 else
1986 set(handles.editIsoCenter,'String','multiple isoCenter');
1987 set(handles.editIsoCenter,'Enable','off');
1988 set(handles.checkIsoCenter,'Value',0);
1989 set(handles.checkIsoCenter,'Enable','off');
1990 end
1991 end
1992 set(handles.editGantryAngle,'String',num2str((pln.propStf.gantryAngles)));
1993 set(handles.editCouchAngle,'String',num2str((pln.propStf.couchAngles)));
1994 set(handles.popupRadMode,'Value',find(strcmp(get(handles.popupRadMode,'String'),pln.radiationMode)));
1995 set(handles.popUpMachine,'Value',find(strcmp(get(handles.popUpMachine,'String'),pln.machine)));
1996
1997 if ~strcmp(pln.propOpt.bioOptimization,'none')
1998 set(handles.popMenuBioOpt,'Enable','on');
1999 contentPopUp = get(handles.popMenuBioOpt,'String');
2000 ix = find(strcmp(pln.propOpt.bioOptimization,contentPopUp));
2001 set(handles.popMenuBioOpt,'Value',ix);
2002 set(handles.btnSetTissue,'Enable','on');
2003 else
2004 set(handles.popMenuBioOpt,'Enable','off');
2005 set(handles.btnSetTissue,'Enable','off');
2006 end
2007
2008 if strcmp(pln.radiationMode,'photons') && pln.propOpt.runSequencing
2009 set(handles.btnRunSequencing,'Enable','on');
2010 set(handles.btnRunSequencing,'Value',1);
2011 elseif strcmp(pln.radiationMode,'photons') && ~pln.propOpt.runSequencing
2012 set(handles.btnRunSequencing,'Enable','on');
2013 set(handles.btnRunSequencing,'Value',0);
2014 else
2015 set(handles.btnRunSequencing,'Enable','off');
2016 end
2017
2018 if strcmp(pln.radiationMode,'photons') && pln.propOpt.runDAO
2019 set(handles.btnRunDAO,'Enable','on');
2020 set(handles.btnRunDAO,'Value',1);
2021 elseif strcmp(pln.radiationMode,'photons') && ~pln.propOpt.runDAO
2022 set(handles.btnRunDAO,'Enable','on');
2023 set(handles.btnRunDAO,'Value',0);
2024 else
2025 set(handles.btnRunDAO,'Enable','off');
2026 end
2027
2028 if strcmp(pln.radiationMode,'photons')
2029 set(handles.txtSequencing,'Enable','on');
2030 set(handles.radiobutton3Dconf,'Enable','on');
2031 set(handles.editSequencingLevel,'Enable','on');
2032 else
2033 set(handles.txtSequencing,'Enable','off');
2034 set(handles.radiobutton3Dconf,'Enable','off');
2035 set(handles.editSequencingLevel,'Enable','off');
2036 end
2037
2038
2039 function btnTableSave_Callback(~, ~, handles)
2040
2041
2042
2043
2044 if get(handles.checkIsoCenter,'Value')
2045 pln = evalin('base','pln');
2046 pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(evalin('base','cst'),evalin('base','ct'));
2047 set(handles.editIsoCenter,'String',regexprep(num2str((round(pln.propStf.isoCenter(1,:) * 10))./10), '\s+', ' '));
2048 assignin('base','pln',pln);
2049 end
2050 getPlnFromGUI(handles);
2051
2052
2053 function listBoxCmd_Callback(hObject, ~, ~)
2054 numLines = size(get(hObject,'String'),1);
2055 set(hObject, 'ListboxTop', numLines);
2056
2057
2058 function sliderOffset_Callback(hObject, ~, handles)
2059 handles.profileOffset = get(hObject,'Value');
2060 UpdatePlot(handles);
2061
2062
2063
2064
2065
2066
2067 function flagValidity = CheckValidity(Val)
2068
2069 flagValidity = true;
2070
2071 if ischar(Val)
2072 Val = str2num(Val);
2073 end
2074
2075 if length(Val) > 2
2076 warndlg('invalid input!');
2077 end
2078
2079 if isempty(Val)
2080 warndlg('Input not a number!');
2081 flagValidity = false;
2082 end
2083
2084 if any(Val < 0)
2085 warndlg('Input not a positive number!');
2086 flagValidity = false;
2087 end
2088
2089
2090 function CheckOptimizerStatus(usedOptimizer,OptCase)
2091
2092 [statusmsg,statusflag] = usedOptimizer.GetStatus();
2093
2094 if statusflag == 0 || statusflag == 1
2095 status = 'none';
2096 else
2097 status = 'warn';
2098 end
2099
2100 msgbox(['Optimizer finished with status ' num2str(statusflag) ' (' statusmsg ')'],'Optimizer',status,'modal');
2101
2102
2103 function getPlnFromGUI(handles)
2104
2105
2106
2107 if evalin('base','exist(''pln'',''var'')')
2108 pln = evalin('base','pln');
2109 end
2110
2111 pln.propStf.bixelWidth = parseStringAsNum(get(handles.editBixelWidth,'String'),false);
2112 pln.propStf.gantryAngles = parseStringAsNum(get(handles.editGantryAngle,'String'),true);
2113
2114 if handles.eduMode
2115 set(handles.editCouchAngle,'String',num2str(zeros(size(pln.propStf.gantryAngles))));
2116 end
2117
2118 pln.propStf.couchAngles = parseStringAsNum(get(handles.editCouchAngle,'String'),true);
2119 pln.propStf.numOfBeams = numel(pln.propStf.gantryAngles);
2120 try
2121 ct = evalin('base','ct');
2122 pln.numOfVoxels = prod(ct.cubeDim);
2123 pln.voxelDimensions = ct.cubeDim;
2124 catch
2125 end
2126 pln.numOfFractions = parseStringAsNum(get(handles.editFraction,'String'),false);
2127 contents = get(handles.popupRadMode,'String');
2128 pln.radiationMode = contents{get(handles.popupRadMode,'Value')};
2129 contents = get(handles.popUpMachine,'String');
2130 pln.machine = contents{get(handles.popUpMachine,'Value')};
2131
2132 if (~strcmp(pln.radiationMode,'photons'))
2133 contentBioOpt = get(handles.popMenuBioOpt,'String');
2134 pln.propOpt.bioOptimization = contentBioOpt{get(handles.popMenuBioOpt,'Value'),:};
2135 else
2136 pln.propOpt.bioOptimization = 'none';
2137 end
2138
2139 pln.propOpt.runSequencing = logical(get(handles.btnRunSequencing,'Value'));
2140 pln.propOpt.runDAO = logical(get(handles.btnRunDAO,'Value'));
2141
2142 try
2143 cst = evalin('base','cst');
2144 if (sum(strcmp('TARGET',cst(:,3))) > 0 && get(handles.checkIsoCenter,'Value')) || ...
2145 (sum(strcmp('TARGET',cst(:,3))) > 0 && ~isfield(pln.propStf,'isoCenter'))
2146 pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct);
2147 set(handles.checkIsoCenter,'Value',1);
2148 else
2149 if ~strcmp(get(handles.editIsoCenter,'String'),'multiple isoCenter')
2150 pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * str2num(get(handles.editIsoCenter,'String'));
2151 end
2152 end
2153 catch
2154 warning('couldnt set isocenter in getPln function')
2155 end
2156
2157 handles.pln = pln;
2158 assignin('base','pln',pln);
2159
2160
2161 function number = parseStringAsNum(stringIn,isVector)
2162 if isnumeric(stringIn)
2163 number = stringIn;
2164 else
2165 number = str2num(stringIn);
2166 if isempty(number) || length(number) > 1 && ~isVector
2167 warndlg(['could not parse all parameters (pln, optimization parameter)']);
2168 number = NaN;
2169 elseif isVector && iscolumn(number)
2170 number = number';
2171 end
2172 end
2173
2174
2175
2176 function handles = showError(handles,Message,ME)
2177
2178 if nargin == 3
2179
2180 if isfield(handles,'devMode') && handles.devMode
2181 meType = 'extended';
2182 else
2183 meType = 'basic';
2184 end
2185 Message = {Message,ME.getReport(meType,'hyperlinks','off')};
2186 end
2187
2188 if isfield(handles,'ErrorDlg')
2189 if ishandle(handles.ErrorDlg)
2190 close(handles.ErrorDlg);
2191 end
2192 end
2193 handles.ErrorDlg = errordlg(Message);
2194
2195
2196 function handles = showWarning(handles,Message,ME)
2197
2198 if nargin == 3
2199
2200 if isfield(handles,'devMode') && handles.devMode
2201 meType = 'extended';
2202 else
2203 meType = 'basic';
2204 end
2205 Message = {Message,ME.getReport(meType,'hyperlinks','off')};
2206 end
2207
2208 if isfield(handles,'WarnDlg')
2209 if ishandle(handles.WarnDlg)
2210 close(handles.WarnDlg);
2211 end
2212 end
2213 handles.WarnDlg = warndlg(Message);
2214
2215
2216 function flag = checkRadiationComposition(handles)
2217 flag = true;
2218 contents = cellstr(get(handles.popUpMachine,'String'));
2219 Machine = contents{get(handles.popUpMachine,'Value')};
2220 contents = cellstr(get(handles.popupRadMode,'String'));
2221 radMod = contents{get(handles.popupRadMode,'Value')};
2222
2223 if isdeployed
2224 baseroot = [ctfroot filesep 'matRad'];
2225 else
2226 baseroot = fileparts(mfilename('fullpath'));
2227 end
2228 FoundFile = dir([baseroot filesep 'basedata' filesep radMod '_' Machine '.mat']);
2229
2230
2231 if isempty(FoundFile)
2232 warndlg(['No base data available for machine: ' Machine]);
2233 flag = false;
2234 end
2235
2236 function matRadScrollWheelFcn(src,event)
2237
2238
2239 handles = guidata(src);
2240
2241
2242 currSlice = round(get(handles.sliderSlice,'Value'));
2243 newSlice = currSlice - event.VerticalScrollCount;
2244
2245
2246 newSlice = min(newSlice,get(handles.sliderSlice,'Max'));
2247 newSlice = max(newSlice,get(handles.sliderSlice,'Min'));
2248
2249
2250 set(handles.sliderSlice,'Value',newSlice);
2251
2252
2253 guidata(src,handles);
2254
2255
2256 UpdatePlot(handles);
2257
2258
2259
2260
2261
2262
2263
2264
2265 function btnDVH_Callback(~, ~, handles)
2266
2267 resultGUI = evalin('base','resultGUI');
2268 Content = get(handles.popupDisplayOption,'String');
2269 SelectedCube = Content{get(handles.popupDisplayOption,'Value')};
2270
2271 pln = evalin('base','pln');
2272 resultGUI_SelectedCube.physicalDose = resultGUI.(SelectedCube);
2273
2274 if ~strcmp(pln.propOpt.bioOptimization,'none')
2275
2276
2277 if sum(strcmp(SelectedCube,{'physicalDose','effect','RBE,','RBExDose','alpha','beta'})) > 0
2278 resultGUI_SelectedCube.physicalDose = resultGUI.physicalDose;
2279 resultGUI_SelectedCube.RBExDose = resultGUI.RBExDose;
2280 else
2281 Idx = find(SelectedCube == '_');
2282 SelectedSuffix = SelectedCube(Idx(1):end);
2283 resultGUI_SelectedCube.physicalDose = resultGUI.(['physicalDose' SelectedSuffix]);
2284 resultGUI_SelectedCube.RBExDose = resultGUI.(['RBExDose' SelectedSuffix]);
2285 end
2286 end
2287
2288
2289 cst = evalin('base','cst');
2290 for i = 1:size(cst,1)
2291 cst{i,5}.Visible = handles.VOIPlotFlag(i);
2292 end
2293
2294 matRad_indicatorWrapper(cst,pln,resultGUI_SelectedCube);
2295
2296 assignin('base','cst',cst);
2297
2298
2299 function radiobtnIsoDoseLinesLabels_Callback(~, ~, handles)
2300 UpdatePlot(handles);
2301
2302
2303 function btnRefresh_Callback(hObject, ~, handles)
2304
2305 handles = resetGUI(hObject, handles);
2306
2307
2308 AllVarNames = evalin('base','who');
2309 handles.AllVarNames = AllVarNames;
2310 try
2311 if ismember('ct',AllVarNames) && ismember('cst',AllVarNames)
2312 ct = evalin('base','ct');
2313 cst = evalin('base','cst');
2314
2315 cst = generateCstTable(handles,cst);
2316 handles.State = 1;
2317 cst = matRad_computeVoiContoursWrapper(cst,ct);
2318 assignin('base','cst',cst);
2319 handles = reloadGUI(hObject, handles, ct, cst);
2320 elseif ismember('ct',AllVarNames) && ~ismember('cst',AllVarNames)
2321 handles = showError(handles,'GUI OpeningFunc: could not find cst file');
2322 ct = evalin('base','ct');
2323 handles = reloadGUI(hObject,handles,ct);
2324 elseif ~ismember('ct',AllVarNames) && ismember('cst',AllVarNames)
2325 handles = showError(handles,'GUI OpeningFunc: could not find ct file');
2326 handles = reloadGUI(hObject, handles);
2327 else
2328 handles = reloadGUI(hObject, handles);
2329 end
2330 catch
2331 handles = showError(handles,'GUI OpeningFunc: Could not load ct and cst file');
2332 handles = reloadGUI(hObject, handles);
2333 end
2334
2335 guidata(hObject, handles);
2336
2337
2338
2339 function editFraction_Callback(hObject, ~, handles)
2340 getPlnFromGUI(handles);
2341 guidata(hObject,handles);
2342
2343
2344 function editSequencingLevel_Callback(~, ~, ~)
2345
2346
2347 function editIsoCenter_Callback(hObject, ~, handles)
2348
2349 pln = evalin('base','pln');
2350 tmpIsoCenter = str2num(get(hObject,'String'));
2351
2352 if length(tmpIsoCenter) == 3
2353 if sum(any(unique(pln.propStf.isoCenter,'rows')~=tmpIsoCenter))
2354 pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1)*tmpIsoCenter;
2355 handles.State = 1;
2356 UpdateState(handles);
2357 end
2358 else
2359 handles = showError(handles,'EditIsoCenterCallback: Could not set iso center');
2360 end
2361
2362 assignin('base','pln',pln);
2363 guidata(hObject,handles);
2364
2365
2366 function checkIsoCenter_Callback(hObject, ~, handles)
2367
2368 W = evalin('base','whos');
2369 doesPlnExist = ismember('pln',{W(:).name});
2370
2371 if get(hObject,'Value') && doesPlnExist
2372 pln = evalin('base','pln');
2373 if ~isfield(pln.propStf,'isoCenter')
2374 pln.propStf.isoCenter = NaN;
2375 end
2376 tmpIsoCenter = matRad_getIsoCenter(evalin('base','cst'),evalin('base','ct'));
2377 if ~isequal(tmpIsoCenter,pln.propStf.isoCenter)
2378 pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1)*tmpIsoCenter;
2379 handles.State = 1;
2380 UpdateState(handles);
2381 end
2382 set(handles.editIsoCenter,'String',regexprep(num2str((round(tmpIsoCenter*10))./10), '\s+', ' '));
2383 set(handles.editIsoCenter,'Enable','off')
2384 assignin('base','pln',pln);
2385 else
2386 set(handles.editIsoCenter,'Enable','on')
2387 end
2388
2389
2390 function btnRunSequencing_Callback(~, ~, handles)
2391 getPlnFromGUI(handles);
2392
2393
2394 function btnRunDAO_Callback(~, ~, handles)
2395 getPlnFromGUI(handles);
2396
2397
2398 function btnSetIsoDoseLevels_Callback(hObject, ~, handles)
2399 prompt = {['Enter iso dose levels in [Gy]. Enter space-separated numbers, e.g. 1.5 2 3 4.98. Enter 0 to use default values']};
2400 if isequal(handles.IsoDose.Levels,0) || ~isvector(handles.IsoDose.Levels) || any(~isnumeric(handles.IsoDose.Levels)) || any(isnan(handles.IsoDose.Levels))
2401 defaultLine = {'1 2 3 '};
2402 else
2403 if isrow(handles.IsoDose.Levels)
2404 defaultLine = cellstr(num2str(handles.IsoDose.Levels,'%.2g '));
2405 else
2406 defaultLine = cellstr(num2str(handles.IsoDose.Levels','%.2g '));
2407 end
2408 end
2409
2410 try
2411 Input = inputdlg(prompt,'Set iso dose levels ', [1 70],defaultLine);
2412 if ~isempty(Input)
2413 handles.IsoDose.Levels = (sort(str2num(Input{1})));
2414 if length(handles.IsoDose.Levels) == 1 && (handles.IsoDose.Levels(1) ~= 0)
2415 handles.IsoDose.Levels = [handles.IsoDose.Levels handles.IsoDose.Levels];
2416 end
2417 handles.IsoDose.NewIsoDoseFlag = true;
2418 end
2419 catch
2420 warning('Couldnt parse iso dose levels - using default values');
2421 handles.IsoDose.Levels = 0;
2422 end
2423 handles = updateIsoDoseLineCache(handles);
2424 handles.IsoDose.NewIsoDoseFlag = false;
2425 UpdatePlot(handles);
2426 guidata(hObject,handles);
2427
2428
2429
2430 function popUpMachine_Callback(hObject, ~, handles)
2431 contents = cellstr(get(hObject,'String'));
2432 checkRadiationComposition(handles);
2433 if handles.State > 0
2434 pln = evalin('base','pln');
2435 if handles.State > 0 && ~strcmp(contents(get(hObject,'Value')),pln.machine)
2436 handles.State = 1;
2437 UpdateState(handles);
2438 guidata(hObject,handles);
2439 end
2440 getPlnFromGUI(handles);
2441 end
2442
2443
2444 function toolbarLoad_ClickedCallback(hObject, eventdata, handles)
2445 btnLoadMat_Callback(hObject, eventdata, handles);
2446
2447
2448 function toolbarSave_ClickedCallback(hObject, eventdata, handles)
2449
2450 btnTableSave_Callback(hObject, eventdata, handles);
2451
2452 try
2453
2454 if handles.State > 0
2455 ct = evalin('base','ct');
2456 cst = evalin('base','cst');
2457 pln = evalin('base','pln');
2458 end
2459
2460 if handles.State > 1
2461 stf = evalin('base','stf');
2462 dij = evalin('base','dij');
2463 end
2464
2465 if handles.State > 2
2466 resultGUI = evalin('base','resultGUI');
2467 end
2468
2469 switch handles.State
2470 case 1
2471 uisave({'cst','ct','pln'});
2472 case 2
2473 uisave({'cst','ct','pln','stf','dij'});
2474 case 3
2475 uisave({'cst','ct','pln','stf','dij','resultGUI'});
2476 end
2477
2478 catch
2479 handles = showWarning(handles,'Could not save files');
2480 end
2481 guidata(hObject,handles);
2482
2483
2484 function btnAbout_Callback(hObject, eventdata, handles)
2485
2486 [~,matRadVer] = matRad_version;
2487
2488 msg{1} = ['matRad ''' matRadVer.name ''''];
2489 if handles.eduMode
2490 msg{1} = [msg{1} ' Educational'];
2491 end
2492 msg{end+1} = sprintf('v%d.%d.%d',matRadVer.major,matRadVer.minor,matRadVer.patch);
2493 if isdeployed
2494 msg{end+1} = 'Standalone Version';
2495 elseif ~isempty(matRadVer.branch) && ~isempty(matRadVer.commitID)
2496 msg{end+1} = sprintf('Git: Branch %s, commit %s',matRadVer.branch,matRadVer.commitID(1:8));
2497 end
2498
2499 [env,envver] = matRad_getEnvironment();
2500 msg{end+1} = sprintf('Environment: %s v%s %s',env,envver,version('-release'));
2501
2502 msg{end+1} = 'Web: www.matrad.org';
2503 msg{end+1} = 'E-Mail: contact@matrad.org';
2504
2505 msgbox(msg,'About matRad');
2506
2507
2508 function figure1_CloseRequestFcn(hObject, ~, ~)
2509 set(0,'DefaultUicontrolBackgroundColor',[0.5 0.5 0.5]);
2510 selection = questdlg('Do you really want to close matRad?',...
2511 'Close matRad',...
2512 'Yes','No','Yes');
2513
2514
2515 switch selection
2516 case 'Yes'
2517 delete(hObject);
2518 case 'No'
2519 return
2520 end
2521
2522
2523 function pushbutton_recalc_Callback(hObject, ~, handles)
2524
2525
2526 if evalin('base','exist(''pln'',''var'')') && ...
2527 evalin('base','exist(''stf'',''var'')') && ...
2528 evalin('base','exist(''ct'',''var'')') && ...
2529 evalin('base','exist(''cst'',''var'')') && ...
2530 evalin('base','exist(''resultGUI'',''var'')')
2531
2532 try
2533
2534
2535
2536 Figures = gcf;
2537 set(Figures, 'pointer', 'watch');
2538 drawnow;
2539
2540 InterfaceObj = findobj(Figures,'Enable','on');
2541 set(InterfaceObj,'Enable','off');
2542
2543
2544 pln = evalin('base','pln');
2545 stf = evalin('base','stf');
2546 ct = evalin('base','ct');
2547 cst = evalin('base','cst');
2548 resultGUI = evalin('base','resultGUI');
2549
2550
2551 Content = get(handles.popupDisplayOption,'String');
2552 SelectedCube = Content{get(handles.popupDisplayOption,'Value')};
2553 Suffix = strsplit(SelectedCube,'_');
2554 if length(Suffix)>1
2555 Suffix = ['_' Suffix{2}];
2556 else
2557 Suffix = '';
2558 end
2559
2560 if sum([stf.totalNumOfBixels]) ~= length(resultGUI.(['w' Suffix]))
2561 warndlg('weight vector does not corresponding to current steering file');
2562 return
2563 end
2564
2565
2566
2567 for i = 1:numel(pln.propStf.gantryAngles)
2568 stf(i).isoCenter = pln.propStf.isoCenter(i,:);
2569 end
2570
2571
2572 if strcmp(pln.radiationMode,'photons')
2573 dij = matRad_calcPhotonDose(ct,stf,pln,cst);
2574 elseif strcmp(pln.radiationMode,'protons') || strcmp(pln.radiationMode,'carbon')
2575 dij = matRad_calcParticleDose(ct,stf,pln,cst);
2576 end
2577
2578
2579 resultGUIreCalc = matRad_calcCubes(resultGUI.(['w' Suffix]),dij,cst);
2580
2581
2582 if isfield(resultGUI,'effect')
2583 resultGUI = rmfield(resultGUI,'effect');
2584 resultGUI = rmfield(resultGUI,'RBExDose');
2585 resultGUI = rmfield(resultGUI,'RBE');
2586 resultGUI = rmfield(resultGUI,'alpha');
2587 resultGUI = rmfield(resultGUI,'beta');
2588 end
2589
2590
2591 sNames = fieldnames(resultGUIreCalc);
2592 for j = 1:length(sNames)
2593 resultGUI.(sNames{j}) = resultGUIreCalc.(sNames{j});
2594 end
2595
2596
2597 assignin('base','dij',dij);
2598 assignin('base','resultGUI',resultGUI);
2599
2600 handles.State = 3;
2601
2602
2603 handles.SelectedDisplayOption = 'physicalDose';
2604 set(handles.popupDisplayOption,'Value',find(strcmp('physicalDose',Content)));
2605
2606
2607 set(Figures, 'pointer', 'arrow');
2608 set(InterfaceObj,'Enable','on');
2609
2610 handles.cBarChanged = true;
2611
2612 handles = updateIsoDoseLineCache(handles);
2613
2614 UpdateState(handles);
2615
2616 handles.rememberCurrAxes = false;
2617 UpdatePlot(handles);
2618 handles.rememberCurrAxes = true;
2619
2620 guidata(hObject,handles);
2621
2622 catch ME
2623 handles = showError(handles,'CalcDoseCallback: Error in dose recalculation!',ME);
2624
2625
2626 set(Figures, 'pointer', 'arrow');
2627 set(InterfaceObj,'Enable','on');
2628
2629 guidata(hObject,handles);
2630 return;
2631
2632 end
2633
2634 end
2635
2636
2637
2638 function btnSetTissue_Callback(hObject, ~, handles)
2639
2640
2641 if handles.State == 0
2642 return
2643 end
2644
2645
2646 cst = evalin('base','cst');
2647 pln = evalin('base','pln');
2648
2649 fileName = [pln.radiationMode '_' pln.machine];
2650 load(['basedata' filesep fileName]);
2651
2652
2653 for i = 1:size(machine.data(1).alphaX,2)
2654 CellType{i} = [num2str(machine.data(1).alphaX(i)) ' ' num2str(machine.data(1).betaX(i))];
2655 end
2656
2657
2658 for i = 1:size(cst,1)
2659 data{i,1} = cst{i,2};
2660 data{i,2} = [num2str(cst{i,5}.alphaX) ' ' num2str(cst{i,5}.betaX)];
2661 data{i,3} = (cst{i,5}.alphaX / cst{i,5}.betaX );
2662 end
2663
2664 Width = 400;
2665 Height = 200 + 20*size(data,1);
2666 ScreenSize = get(0,'ScreenSize');
2667
2668 figHandles = get(0,'Children');
2669 if ~isempty(figHandles)
2670 IdxHandle = strcmp(get(figHandles,'Name'),'Set Tissue Parameters');
2671 else
2672 IdxHandle = [];
2673 end
2674
2675
2676 if any(IdxHandle)
2677 IdxTable = find(strcmp({figHandles(IdxHandle).Children.Type},'uitable'));
2678 set(figHandles(IdxHandle).Children(IdxTable), 'Data', []);
2679 figTissue = figHandles(IdxHandle);
2680
2681 figure(figTissue);
2682 else
2683 figTissue = figure('Name','Set Tissue Parameters','Color',[.5 .5 .5],'NumberTitle','off','Position',...
2684 [ceil(ScreenSize(3)/2) ceil(ScreenSize(4)/2) Width Height]);
2685 end
2686
2687
2688 cNames = {'VOI','alphaX betaX','alpha beta ratio'};
2689 columnformat = {'char',CellType,'numeric'};
2690
2691 tissueTable = uitable('Parent', figTissue,'Data', data,'ColumnEditable',[false true false],...
2692 'ColumnName',cNames, 'ColumnFormat',columnformat,'Position',[50 150 10 10]);
2693 set(tissueTable,'CellEditCallback',@tissueTable_CellEditCallback);
2694
2695 currTablePos = get(tissueTable,'Position');
2696 currTableExt = get(tissueTable,'Extent');
2697 currTablePos(3) = currTableExt(3);
2698 currTablePos(4) = currTableExt(4);
2699 set(tissueTable,'Position',currTablePos);
2700
2701
2702 uicontrol('Parent', figTissue,'Style', 'pushbutton', 'String', 'Save&Close',...
2703 'Position', [Width-(0.25*Width) 0.1 * Height 70 30],...
2704 'Callback', @(hpb,eventdata)SaveTissueParameters(hpb,eventdata,handles,tissueTable));
2705
2706 uicontrol('Parent', figTissue,'Style', 'pushbutton', 'String', 'Cancel&Close',...
2707 'Position', [Width-(0.5*Width) 0.1 * Height 80 30],...
2708 'Callback', 'close');
2709
2710 guidata(hObject,handles);
2711 UpdateState(handles);
2712
2713
2714 function SaveTissueParameters(~, ~, handles,tissueTable)
2715 cst = evalin('base','cst');
2716
2717
2718
2719 data = get(tissueTable,'data');
2720
2721 for i = 1:size(cst,1)
2722 for j = 1:size(data,1)
2723 if strcmp(cst{i,2},data{j,1})
2724 alphaXBetaX = str2num(data{j,2});
2725 cst{i,5}.alphaX = alphaXBetaX(1);
2726 cst{i,5}.betaX = alphaXBetaX(2);
2727 end
2728 end
2729 end
2730 assignin('base','cst',cst);
2731 close(get(tissueTable,'Parent'));
2732 handles.State = 2;
2733 UpdateState(handles);
2734
2735
2736 function tissueTable_CellEditCallback(hObject, eventdata, ~)
2737 if eventdata.Indices(2) == 2
2738 alphaXBetaX = str2num(eventdata.NewData);
2739 data = get(hObject,'Data');
2740 data{eventdata.Indices(1),3} = alphaXBetaX(1)/alphaXBetaX(2);
2741 set(hObject,'Data',data);
2742 end
2743
2744
2745 function btnSaveToGUI_Callback(hObject, ~, handles)
2746
2747 Width = 400;
2748 Height = 200;
2749 ScreenSize = get(0,'ScreenSize');
2750
2751
2752 figHandles = get(0,'Children');
2753 if ~isempty(figHandles)
2754 IdxHandle = strcmp(get(figHandles,'Name'),'Provide result name');
2755 else
2756 IdxHandle = [];
2757 end
2758
2759
2760 if any(IdxHandle)
2761 figDialog = figHandles(IdxHandle);
2762
2763 figure(figDialog);
2764 else
2765 figDialog = dialog('Position',[ceil(ScreenSize(3)/2) ceil(ScreenSize(4)/2) Width Height],'Name','Provide result name','Color',[0.5 0.5 0.5]);
2766
2767 uicontrol('Parent',figDialog,...
2768 'Style','text',...
2769 'Position',[20 Height - (0.35*Height) 350 60],...
2770 'String','Please provide a decriptive name for your optimization result:','FontSize',10,'BackgroundColor',[0.5 0.5 0.5]);
2771
2772 uicontrol('Parent',figDialog,...
2773 'Style','edit',...
2774 'Position',[30 60 350 60],...
2775 'String','Please enter name here...','FontSize',10,'BackgroundColor',[0.55 0.55 0.55]);
2776
2777 uicontrol('Parent', figDialog,'Style', 'pushbutton', 'String', 'Save','FontSize',10,...
2778 'Position', [0.42*Width 0.1 * Height 70 30],...
2779 'Callback', @(hpb,eventdata)SaveResultToGUI(hpb,eventdata,guidata(hpb)));
2780 end
2781
2782 uiwait(figDialog);
2783 guidata(hObject, handles);
2784 UpdateState(handles)
2785 UpdatePlot(handles)
2786
2787
2788 function SaveResultToGUI(~, ~, ~)
2789 AllFigHandles = get(0,'Children');
2790 ixHandle = strcmp(get(AllFigHandles,'Name'),'Provide result name');
2791 uiEdit = get(AllFigHandles(ixHandle),'Children');
2792
2793 if strcmp(get(uiEdit(2),'String'),'Please enter name here...')
2794
2795 formatOut = 'mmddyyHHMM';
2796 Suffix = ['_' datestr(now,formatOut)];
2797 else
2798
2799 Suffix = get(uiEdit(2),'String');
2800 logIx = isstrprop(Suffix,'alphanum');
2801 Suffix = ['_' Suffix(logIx)];
2802 end
2803
2804 pln = evalin('base','pln');
2805 resultGUI = evalin('base','resultGUI');
2806
2807 if isfield(resultGUI,'physicalDose')
2808 resultGUI.(['physicalDose' Suffix]) = resultGUI.physicalDose;
2809 end
2810 if isfield(resultGUI,'w')
2811 resultGUI.(['w' Suffix]) = resultGUI.w;
2812 end
2813
2814
2815 if ~strcmp(pln.propOpt.bioOptimization,'none')
2816
2817 if isfield(resultGUI,'RBExDose')
2818 resultGUI.(['RBExDose' Suffix]) = resultGUI.RBExDose;
2819 end
2820
2821 if strcmp(pln.radiationMode,'carbon') == 1
2822 if isfield(resultGUI,'effect')
2823 resultGUI.(['effect' Suffix])= resultGUI.effect;
2824 end
2825
2826 if isfield(resultGUI,'RBE')
2827 resultGUI.(['RBE' Suffix]) = resultGUI.RBE;
2828 end
2829 if isfield(resultGUI,'alpha')
2830 resultGUI.(['alpha' Suffix]) = resultGUI.alpha;
2831 end
2832 if isfield(resultGUI,'beta')
2833 resultGUI.(['beta' Suffix]) = resultGUI.beta;
2834 end
2835 end
2836 end
2837
2838 close(AllFigHandles(ixHandle));
2839 assignin('base','resultGUI',resultGUI);
2840
2841
2842 function cst = precomputeContours(ct,cst)
2843 mask = zeros(ct.cubeDim);
2844 for s = 1:size(cst,1)
2845 cst{s,7} = cell(max(ct.cubeDim(:)),3);
2846 mask(:) = 0;
2847 mask(cst{s,4}{1}) = 1;
2848 for slice = 1:ct.cubeDim(1)
2849 if sum(sum(mask(slice,:,:))) > 0
2850 cst{s,7}{slice,1} = contourc(squeeze(mask(slice,:,:)),.5*[1 1]);
2851 end
2852 end
2853 for slice = 1:ct.cubeDim(2)
2854 if sum(sum(mask(:,slice,:))) > 0
2855 cst{s,7}{slice,2} = contourc(squeeze(mask(:,slice,:)),.5*[1 1]);
2856 end
2857 end
2858 for slice = 1:ct.cubeDim(3)
2859 if sum(sum(mask(:,:,slice))) > 0
2860 cst{s,7}{slice,3} = contourc(squeeze(mask(:,:,slice)),.5*[1 1]);
2861 end
2862 end
2863 end
2864
2865
2866 function handles = updateIsoDoseLineCache(handles)
2867 resultGUI = evalin('base','resultGUI');
2868
2869 if ~isfield(resultGUI,handles.SelectedDisplayOption)
2870 CubeNames = fieldnames(resultGUI);
2871 dose = resultGUI.(CubeNames{1,1});
2872 else
2873 dose = resultGUI.(handles.SelectedDisplayOption);
2874 end
2875
2876
2877 if isempty(handles.dispWindow{3,2})
2878 handles.dispWindow{3,1} = [min(dose(:)) max(dose(:))];
2879 handles.dispWindow{3,2} = [min(dose(:)) max(dose(:))];
2880 end
2881
2882 minMaxRange = handles.dispWindow{3,1};
2883
2884 upperMargin = 1;
2885 if abs((max(dose(:)) - handles.dispWindow{3,1}(1,2))) < 0.01 * max(dose(:))
2886 upperMargin = 1.2;
2887 end
2888
2889 if (length(handles.IsoDose.Levels) == 1 && handles.IsoDose.Levels(1,1) == 0) || ~handles.IsoDose.NewIsoDoseFlag
2890 vLevels = [0.1:0.1:0.9 0.95:0.05:upperMargin];
2891 referenceDose = (minMaxRange(1,2))/(upperMargin);
2892 handles.IsoDose.Levels = minMaxRange(1,1) + (referenceDose-minMaxRange(1,1)) * vLevels;
2893 end
2894 handles.IsoDose.Contours = matRad_computeIsoDoseContours(dose,handles.IsoDose.Levels);
2895
2896
2897
2898
2899
2900
2901
2902 function popUpMachine_CreateFcn(hObject, ~, ~)
2903 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2904 set(hObject,'BackgroundColor','white');
2905 end
2906
2907
2908 function txtMaxVal_CreateFcn(hObject, ~, ~)
2909
2910 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2911 set(hObject,'BackgroundColor','white');
2912 end
2913
2914
2915 function editIsoCenter_CreateFcn(hObject, ~, ~)
2916 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2917 set(hObject,'BackgroundColor','white');
2918 end
2919
2920
2921 function editSequencingLevel_CreateFcn(hObject, ~, ~)
2922 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2923 set(hObject,'BackgroundColor','white');
2924 end
2925
2926 function slicerPrecision_CreateFcn(hObject, ~, ~)
2927 if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2928 set(hObject,'BackgroundColor',[.9 .9 .9]);
2929 end
2930
2931 function editBixelWidth_CreateFcn(hObject, ~, ~)
2932 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2933 set(hObject,'BackgroundColor','white');
2934 end
2935
2936 function editGantryAngle_CreateFcn(hObject, ~, ~)
2937 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2938 set(hObject,'BackgroundColor','white');
2939 end
2940
2941 function editCouchAngle_CreateFcn(hObject, ~, ~)
2942 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2943 set(hObject,'BackgroundColor','white');
2944 end
2945
2946 function popupRadMode_CreateFcn(hObject, ~, ~)
2947 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2948 set(hObject,'BackgroundColor','white');
2949 end
2950
2951 function editFraction_CreateFcn(hObject, ~, ~)
2952 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2953 set(hObject,'BackgroundColor','white');
2954 end
2955
2956 function popupPlane_CreateFcn(hObject, ~, ~)
2957 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2958 set(hObject,'BackgroundColor','white');
2959 end
2960
2961 function sliderSlice_CreateFcn(hObject, ~, ~)
2962 if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2963 set(hObject,'BackgroundColor',[.9 .9 .9]);
2964 end
2965
2966 function popupTypeOfPlot_CreateFcn(hObject, ~, ~)
2967 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2968 set(hObject,'BackgroundColor','white');
2969 end
2970
2971 function popupDisplayOption_CreateFcn(hObject, ~, ~)
2972 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2973 set(hObject,'BackgroundColor','white');
2974 end
2975
2976 function sliderBeamSelection_CreateFcn(hObject, ~, ~)
2977 if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2978 set(hObject,'BackgroundColor',[.9 .9 .9]);
2979 end
2980
2981 function listBoxCmd_CreateFcn(hObject, ~, ~)
2982 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2983 set(hObject,'BackgroundColor','white');
2984 end
2985
2986 function sliderOffset_CreateFcn(hObject, ~, ~)
2987 if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
2988 set(hObject,'BackgroundColor',[.9 .9 .9]);
2989 end
2990
2991
2992 function legendTable_Callback(hObject, eventdata, handles)
2993
2994
2995
2996
2997
2998
2999 cst = evalin('base','cst');
3000
3001 idx = get(hObject,'Value');
3002 clr = dec2hex(round(cst{idx,5}.visibleColor(:)*255),2)';
3003 clr = ['#';clr(:)]';
3004
3005
3006 tmpString = get(handles.legendTable,'String');
3007
3008 if handles.VOIPlotFlag(idx)
3009 handles.VOIPlotFlag(idx) = false;
3010 cst{idx,5}.Visible = false;
3011 tmpString{idx} = ['<html><table border=0 ><TR><TD bgcolor=',clr,' width="18"></TD><TD>',cst{idx,2},'</TD></TR> </table></html>'];
3012 elseif ~handles.VOIPlotFlag(idx)
3013 handles.VOIPlotFlag(idx) = true;
3014 cst{idx,5}.Visible = true;
3015 tmpString{idx} = ['<html><table border=0 ><TR><TD bgcolor=',clr,' width="18"><center>✔</center></TD><TD>',cst{idx,2},'</TD></TR> </table></html>'];
3016 end
3017 set(handles.legendTable,'String',tmpString);
3018
3019
3020 assignin('base','cst',cst)
3021
3022 guidata(hObject, handles);
3023 UpdatePlot(handles)
3024
3025
3026 function legendTable_CreateFcn(hObject, eventdata, handles)
3027
3028
3029
3030
3031
3032
3033 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3034 set(hObject,'BackgroundColor','white');
3035 end
3036
3037
3038
3039 function importDoseButton_Callback(hObject,eventdata, handles)
3040
3041
3042
3043 extensions{1} = '*.nrrd';
3044 [filenames,filepath,~] = uigetfile(extensions,'MultiSelect','on');
3045
3046 if ~iscell(filenames)
3047 tmp = filenames;
3048 filenames = cell(1);
3049 filenames{1} = tmp;
3050 end
3051
3052 ct = evalin('base','ct');
3053 resultGUI = evalin('base','resultGUI');
3054
3055 for filename = filenames
3056 [~,name,~] = fileparts(filename{1});
3057 [cube,~] = matRad_readCube(fullfile(filepath,filename{1}));
3058 if ~isequal(ct.cubeDim, size(cube))
3059 errordlg('Dimensions of the imported cube do not match with ct','Import failed!','modal');
3060 continue;
3061 end
3062
3063 fieldname = ['import_' matlab.lang.makeValidName(name, 'ReplacementStyle','delete')];
3064 resultGUI.(fieldname) = cube;
3065 end
3066
3067 assignin('base','resultGUI',resultGUI);
3068 btnRefresh_Callback(hObject, eventdata, handles)
3069
3070
3071 function pushbutton_importFromBinary_Callback(hObject, eventdata, handles)
3072
3073
3074
3075
3076 try
3077
3078 set(handles.popupDisplayOption,'String','no option available');
3079 AllVarNames = evalin('base','who');
3080 RefVarNames = {'ct','cst','pln','stf','dij','resultGUI'};
3081 for i = 1:length(RefVarNames)
3082 if sum(ismember(AllVarNames,RefVarNames{i}))>0
3083 evalin('base',['clear ', RefVarNames{i}]);
3084 end
3085 end
3086 handles.State = 0;
3087
3088
3089 uiwait(matRad_importGUI);
3090
3091
3092 if evalin('base','exist(''cst'',''var'')') == 1 && evalin('base','exist(''ct'',''var'')') == 1
3093 cst = evalin('base','cst');
3094 ct = evalin('base','ct');
3095
3096 generateCstTable(handles,cst);
3097 handles.TableChanged = false;
3098 set(handles.popupTypeOfPlot,'Value',1);
3099
3100
3101 if ~isfield(ct, 'cubeHU')
3102 ct = matRad_electronDensitiesToHU(ct);
3103 assignin('base','ct',ct);
3104 end
3105 if ~isfield(ct, 'cubeHU')
3106 handles.cubeHUavailable = false;
3107 else
3108 handles.cubeHUavailable = true;
3109 end
3110
3111
3112 cst = precomputeContours(ct,cst);
3113
3114 assignin('base','ct',ct);
3115 assignin('base','cst',cst);
3116
3117 if evalin('base','exist(''pln'',''var'')')
3118 assignin('base','pln',pln);
3119 setPln(handles);
3120 else
3121 getPlnFromGUI(handles);
3122 setPln(handles);
3123 end
3124 handles.State = 1;
3125 end
3126
3127
3128 handles.plane = get(handles.popupPlane,'value');
3129 if handles.State >0
3130 set(handles.sliderSlice,'Min',1,'Max',ct.cubeDim(handles.plane),...
3131 'Value',round(ct.cubeDim(handles.plane)/2),...
3132 'SliderStep',[1/(ct.cubeDim(handles.plane)-1) 1/(ct.cubeDim(handles.plane)-1)]);
3133 end
3134
3135 if handles.State > 0
3136
3137 for i = 1:size(cst,1)
3138 if cst{i,5}.Visible
3139 handles.VOIPlotFlag(i) = true;
3140 else
3141 handles.VOIPlotFlag(i) = false;
3142 end
3143 end
3144 end
3145
3146 handles.dispWindow = cell(3,2);
3147 handles.cBarChanged = true;
3148
3149 UpdateState(handles);
3150 handles.rememberCurrAxes = false;
3151 UpdatePlot(handles);
3152 handles.rememberCurrAxes = true;
3153 catch
3154 handles = showError(handles,'Binary Patient Import: Could not import data');
3155 UpdateState(handles);
3156 end
3157
3158 guidata(hObject,handles);
3159
3160
3161 function radioBtnIsoCenter_Callback(hObject, eventdata, handles)
3162
3163
3164
3165 UpdatePlot(handles)
3166
3167
3168
3169 function uipushtool_screenshot_ClickedCallback(hObject, eventdata, handles)
3170
3171
3172
3173
3174
3175 tmpFig = figure('position',[100 100 700 600],'Visible','off','name','Current View');
3176 cBarHandle = findobj(handles.figure1,'Type','colorbar');
3177 if ~isempty(cBarHandle)
3178 new_handle = copyobj([handles.axesFig cBarHandle],tmpFig);
3179 else
3180 new_handle = copyobj(handles.axesFig,tmpFig);
3181 end
3182
3183 oldPos = get(handles.axesFig,'Position');
3184 set(new_handle(1),'units','normalized', 'Position',oldPos);
3185
3186 if ~isfield(handles,'lastStoragePath') || exist(handles.lastStoragePath,'dir') ~= 7
3187 lastStoragePath = [];
3188 else
3189 lastStoragePath = handles.lastStoragePath;
3190 end
3191
3192 [filename, pathname] = uiputfile({'*.jpg;*.tif;*.png;*.gif','All Image Files'; '*.fig','MATLAB figure file'},'Save current view',[lastStoragePath 'screenshot.png']);
3193
3194
3195
3196 if ~isequal(filename,0) && ~isequal(pathname,0)
3197 handles.lastStoragePath = pathname;
3198 set(gcf, 'pointer', 'watch');
3199 saveas(tmpFig,fullfile(pathname,filename));
3200 set(gcf, 'pointer', 'arrow');
3201 close(tmpFig);
3202 uiwait(msgbox('Current view has been succesfully saved!'));
3203 else
3204 uiwait(msgbox('Aborted saving, showing figure instead!'));
3205 set(tmpFig,'Visible','on');
3206 end
3207
3208 guidata(hObject,handles);
3209
3210
3211
3212 function UpdateColormapOptions(handles)
3213
3214 if isfield(handles,'colormapLocked') && handles.colormapLocked
3215 return;
3216 end
3217
3218 selectionIndex = get(handles.popupmenu_chooseColorData,'Value');
3219
3220 cMapSelectionIndex = get(handles.popupmenu_chooseColormap,'Value');
3221 cMapStrings = get(handles.popupmenu_chooseColormap,'String');
3222
3223 if selectionIndex > 1
3224 set(handles.uitoggletool8,'State','on');
3225 else
3226 set(handles.uitoggletool8,'State','off');
3227 end
3228
3229 try
3230 if selectionIndex == 2
3231 ct = evalin('base','ct');
3232 currentMap = handles.ctColorMap;
3233 window = handles.dispWindow{selectionIndex,1};
3234 if handles.cubeHUavailable
3235 minMax = [min(ct.cubeHU{1}(:)) max(ct.cubeHU{1}(:))];
3236 else
3237 minMax = [min(ct.cube{1}(:)) max(ct.cube{1}(:))];
3238 end
3239
3240 handles.windowPresets(1).width = max(window) - min(window);
3241 handles.windowPresets(1).center = mean(window);
3242
3243 handles.windowPresets(2).width = minMax(2) - minMax(1);
3244 handles.windowPresets(2).center = mean(minMax);
3245 elseif selectionIndex == 3
3246 result = evalin('base','resultGUI');
3247 dose = result.(handles.SelectedDisplayOption);
3248 currentMap = handles.doseColorMap;
3249 minMax = [min(dose(:)) max(dose(:))];
3250 window = handles.dispWindow{selectionIndex,1};
3251 else
3252 window = [0 1];
3253 minMax = window;
3254 currentMap = 'bone';
3255 end
3256 catch
3257 window = [0 1];
3258 minMax = window;
3259 currentMap = 'bone';
3260 end
3261
3262 valueRange = minMax(2) - minMax(1);
3263
3264 windowWidth = window(2) - window(1);
3265 windowCenter = mean(window);
3266
3267
3268 sliderCenterMinMax = [minMax(1)-valueRange/2 minMax(2)+valueRange/2];
3269 sliderWidthMinMax = [0 valueRange*2];
3270
3271
3272
3273 if windowCenter < sliderCenterMinMax(1)
3274 sliderCenterMinMax(1) = windowCenter;
3275 end
3276 if windowCenter > sliderCenterMinMax(2)
3277 sliderCenterMinMax(2) = windowCenter;
3278 end
3279 if windowWidth < sliderWidthMinMax(1)
3280 sliderWidthMinMax(1) = windowWidth;
3281 end
3282 if windowCenter > sliderCenterMinMax(2)
3283 sliderWidthMinMax(2) = windowWidth;
3284 end
3285
3286
3287 set(handles.edit_windowCenter,'String',num2str(windowCenter,3));
3288 set(handles.edit_windowWidth,'String',num2str(windowWidth,3));
3289 set(handles.edit_windowRange,'String',num2str(window,4));
3290 set(handles.slider_windowCenter,'Min',sliderCenterMinMax(1),'Max',sliderCenterMinMax(2),'Value',windowCenter);
3291 set(handles.slider_windowWidth,'Min',sliderWidthMinMax(1),'Max',sliderWidthMinMax(2),'Value',windowWidth);
3292
3293 cMapPopupIndex = find(strcmp(currentMap,cMapStrings));
3294 set(handles.popupmenu_chooseColormap,'Value',cMapPopupIndex);
3295
3296 guidata(gcf,handles);
3297
3298
3299 function popupmenu_chooseColorData_Callback(hObject, eventdata, handles)
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309 handles.cBarChanged = true;
3310
3311 guidata(hObject,handles);
3312 UpdatePlot(handles);
3313
3314
3315
3316 function popupmenu_chooseColorData_CreateFcn(hObject, eventdata, handles)
3317
3318
3319
3320
3321
3322
3323 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3324 set(hObject,'BackgroundColor','white');
3325 end
3326
3327
3328
3329 function slider_windowCenter_Callback(hObject, eventdata, handles)
3330
3331
3332
3333
3334
3335
3336
3337 newCenter = get(hObject,'Value');
3338 range = get(handles.slider_windowWidth,'Value');
3339 selectionIndex = get(handles.popupmenu_chooseColorData,'Value');
3340
3341 handles.dispWindow{selectionIndex,1} = [newCenter-range/2 newCenter+range/2];
3342 handles.cBarChanged = true;
3343
3344 guidata(hObject,handles);
3345 UpdatePlot(handles);
3346
3347
3348 function slider_windowCenter_CreateFcn(hObject, eventdata, handles)
3349
3350
3351
3352
3353
3354 if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3355 set(hObject,'BackgroundColor',[.9 .9 .9]);
3356 end
3357
3358 set(hObject,'Value',0.5);
3359
3360
3361 function slider_windowWidth_Callback(hObject, eventdata, handles)
3362
3363
3364
3365
3366
3367
3368
3369 newWidth = get(hObject,'Value');
3370 center = get(handles.slider_windowCenter,'Value');
3371 selectionIndex = get(handles.popupmenu_chooseColorData,'Value');
3372 handles.dispWindow{selectionIndex,1} = [center-newWidth/2 center+newWidth/2];
3373 handles.cBarChanged = true;
3374
3375 guidata(hObject,handles);
3376 UpdatePlot(handles);
3377
3378
3379 function slider_windowWidth_CreateFcn(hObject, eventdata, handles)
3380
3381
3382
3383
3384
3385 if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3386 set(hObject,'BackgroundColor',[.9 .9 .9]);
3387 end
3388
3389 set(hObject,'Value',1.0);
3390
3391
3392
3393 function popupmenu_chooseColormap_Callback(hObject, eventdata, handles)
3394
3395
3396
3397
3398
3399
3400
3401 index = get(hObject,'Value');
3402 strings = get(hObject,'String');
3403
3404 selectionIndex = get(handles.popupmenu_chooseColorData,'Value');
3405
3406 switch selectionIndex
3407 case 2
3408 handles.ctColorMap = strings{index};
3409 case 3
3410 handles.doseColorMap = strings{index};
3411 otherwise
3412 end
3413
3414 handles.cBarChanged = true;
3415
3416 guidata(hObject,handles);
3417 UpdatePlot(handles);
3418
3419
3420 function popupmenu_chooseColormap_CreateFcn(hObject, eventdata, handles)
3421
3422
3423
3424
3425
3426
3427 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3428 set(hObject,'BackgroundColor','white');
3429 end
3430
3431
3432 function edit_windowRange_Callback(hObject, eventdata, handles)
3433
3434
3435
3436
3437
3438
3439
3440 selectionIndex = get(handles.popupmenu_chooseColorData,'Value');
3441 vRange = str2num(get(hObject,'String'));
3442
3443 if numel(vRange) == 3
3444 vRange = vRange(vRange~=0);
3445 end
3446
3447 handles.dispWindow{selectionIndex,1} = sort(vRange);
3448
3449 handles.cBarChanged = true;
3450
3451
3452 if selectionIndex > 2
3453 guidata(hObject,handles);
3454 handles = updateIsoDoseLineCache(handles);
3455 end
3456
3457 guidata(hObject,handles);
3458 UpdatePlot(handles);
3459
3460
3461 function edit_windowRange_CreateFcn(hObject, eventdata, handles)
3462
3463
3464
3465
3466
3467
3468 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3469 set(hObject,'BackgroundColor','white');
3470 end
3471
3472 set(hObject,'String','0 1');
3473
3474
3475 function edit_windowCenter_Callback(hObject, eventdata, handles)
3476
3477
3478
3479
3480
3481
3482
3483 newCenter = str2double(get(hObject,'String'));
3484 width = get(handles.slider_windowWidth,'Value');
3485 selectionIndex = get(handles.popupmenu_chooseColorData,'Value');
3486 handles.dispWindow{selectionIndex,1} = [newCenter-width/2 newCenter+width/2];
3487 handles.cBarChanged = true;
3488 guidata(hObject,handles);
3489 UpdatePlot(handles);
3490
3491
3492 function edit_windowCenter_CreateFcn(hObject, eventdata, handles)
3493
3494
3495
3496
3497
3498
3499 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3500 set(hObject,'BackgroundColor','white');
3501 end
3502
3503
3504
3505 function edit_windowWidth_Callback(hObject, eventdata, handles)
3506
3507
3508
3509
3510
3511
3512
3513 newWidth = str2double(get(hObject,'String'));
3514 center = get(handles.slider_windowCenter,'Value');
3515 selectionIndex = get(handles.popupmenu_chooseColorData,'Value');
3516 handles.dispWindow{selectionIndex,1} = [center-newWidth/2 center+newWidth/2];
3517 handles.cBarChanged = true;
3518 guidata(hObject,handles);
3519 UpdatePlot(handles);
3520
3521
3522
3523 function edit_windowWidth_CreateFcn(hObject, eventdata, handles)
3524
3525
3526
3527
3528
3529
3530 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3531 set(hObject,'BackgroundColor','white');
3532 end
3533
3534
3535
3536 function uitoggletool8_ClickedCallback(hObject, eventdata, handles)
3537
3538
3539
3540
3541
3542 val = strcmp(get(hObject,'State'),'on');
3543
3544
3545 if ~val
3546 newSelection = 1;
3547 else
3548
3549 selections = get(handles.popupmenu_chooseColorData,'String');
3550 newSelection = numel(selections);
3551 end
3552 set(handles.popupmenu_chooseColorData,'Value',newSelection);
3553
3554 handles.cBarChanged = true;
3555 guidata(hObject,handles);
3556 UpdatePlot(handles);
3557
3558
3559 function sliderOpacity_Callback(hObject, eventdata, handles)
3560
3561
3562
3563 handles.doseOpacity = get(hObject,'Value');
3564 guidata(hObject,handles);
3565 UpdatePlot(handles);
3566
3567
3568 function sliderOpacity_CreateFcn(hObject, eventdata, handles)
3569
3570
3571
3572
3573
3574 if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3575 set(hObject,'BackgroundColor',[.9 .9 .9]);
3576 end
3577
3578
3579 function cursorText = dataCursorUpdateFunction(obj,event_obj)
3580
3581
3582
3583
3584
3585 target = findall(0,'Name','matRadGUI');
3586
3587
3588 handles = guidata(target);
3589
3590
3591 pos = get(event_obj,'Position');
3592
3593
3594 if get(handles.popupTypeOfPlot,'Value')==1
3595 cursorText = cell(0,1);
3596 try
3597 if handles.State >= 1
3598 plane = get(handles.popupPlane,'Value');
3599 slice = round(get(handles.sliderSlice,'Value'));
3600
3601
3602 ct = evalin('base','ct');
3603
3604
3605
3606 cubePos = zeros(1,3);
3607 cubePos(plane) = slice;
3608 cubePos(1:end ~= plane) = fliplr(pos);
3609 cubeIx = round(cubePos);
3610
3611
3612
3613 cursorText{end+1,1} = ['Cube Index: ' mat2str(cubeIx)];
3614
3615 coords = zeros(1,3);
3616 coords(1) = cubePos(2)*ct.resolution.y;
3617 coords(2) = cubePos(1)*ct.resolution.x;
3618 coords(3) = cubePos(3)*ct.resolution.z;
3619 cursorText{end+1,1} = ['Space Coordinates: ' mat2str(coords,5) ' mm'];
3620
3621 ctVal = ct.cubeHU{1}(cubeIx(1),cubeIx(2),cubeIx(3));
3622 cursorText{end+1,1} = ['HU Value: ' num2str(ctVal,3)];
3623 end
3624
3625
3626 if handles.State == 3
3627
3628 result = evalin('base','resultGUI');
3629
3630
3631 resultNames = get(handles.popupDisplayOption,'String');
3632
3633
3634 for runResult = 1:numel(resultNames)
3635 name = resultNames{runResult};
3636 if isfield(result,name)
3637 field = result.(name);
3638 val = field(cubeIx(1),cubeIx(2),cubeIx(3));
3639 cursorText{end+1,1} = [name ': ' num2str(val,3)];
3640 end
3641 end
3642 end
3643 catch
3644 cursorText{end+1,1} = 'Error while retreiving Data!';
3645 end
3646 else
3647 cursorText = cell(2,1);
3648 cursorText{1} = ['Radiological Depth: ' num2str(pos(1),3) ' mm'];
3649 cursorText{2} = [get(target,'DisplayName') ': ' num2str(pos(2),3)];
3650 end
3651
3652
3653
3654
3655 function popMenuBioOpt_Callback(hObject, ~, handles)
3656 pln = evalin('base','pln');
3657 contentBioOpt = get(handles.popMenuBioOpt,'String');
3658 NewBioOptimization = contentBioOpt(get(handles.popMenuBioOpt,'Value'),:);
3659
3660 if handles.State > 0
3661 if (strcmp(pln.propOpt.bioOptimization,'LEMIV_effect') && strcmp(NewBioOptimization,'LEMIV_RBExD')) ||...
3662 (strcmp(pln.propOpt.bioOptimization,'LEMIV_RBExD') && strcmp(NewBioOptimization,'LEMIV_effect'))
3663
3664 elseif ((strcmp(pln.propOpt.bioOptimization,'const_RBE') && strcmp(NewBioOptimization,'none')) ||...
3665 (strcmp(pln.propOpt.bioOptimization,'none') && strcmp(NewBioOptimization,'const_RBE'))) && isequal(pln.radiationMode,'protons')
3666
3667 else
3668 handles.State = 1;
3669 end
3670 end
3671 getPlnFromGUI(handles);
3672
3673 UpdateState(handles);
3674 guidata(hObject,handles);
3675
3676
3677 function popMenuBioOpt_CreateFcn(hObject, eventdata, handles)
3678 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3679 set(hObject,'BackgroundColor','white');
3680 end
3681
3682
3683 function btn3Dview_Callback(hObject, eventdata, handles)
3684
3685
3686
3687
3688 if ~isfield(handles,'axesFig3D') || ~isfield(handles,'axesFig3D') || ~isgraphics(handles.axesFig3D)
3689 handles.fig3D = figure('Name','matRad 3D View');
3690 handles.axesFig3D = axes('Parent',handles.fig3D);
3691 view(handles.axesFig3D,3);
3692 try
3693 ct = evalin('base','ct');
3694
3695 xlim(handles.axesFig3D,[0 ct.resolution.x*ct.cubeDim(2)]);
3696 ylim(handles.axesFig3D,[0 ct.resolution.y*ct.cubeDim(1)]);
3697 zlim(handles.axesFig3D,[0 ct.resolution.z*ct.cubeDim(3)]);
3698 catch
3699 end
3700 end
3701
3702
3703 UpdatePlot(handles);
3704
3705 guidata(hObject,handles);
3706
3707
3708 function radiobtnCT_Callback(hObject, eventdata, handles)
3709
3710
3711
3712
3713
3714 UpdatePlot(handles)
3715
3716
3717 function radiobtnPlan_Callback(hObject, eventdata, handles)
3718
3719
3720
3721
3722
3723 UpdatePlot(handles)
3724
3725
3726
3727 function popupmenu_windowPreset_Callback(hObject, eventdata, handles)
3728
3729
3730
3731
3732
3733
3734
3735 selectionIndexCube = 2;
3736 selectionIndexWindow = get(handles.popupmenu_windowPreset,'Value');
3737 newCenter = handles.windowPresets(selectionIndexWindow).center;
3738 newWidth = handles.windowPresets(selectionIndexWindow).width;
3739
3740 handles.dispWindow{selectionIndexCube,1} = [newCenter - newWidth/2 newCenter + newWidth/2];
3741 handles.cBarChanged = true;
3742 guidata(hObject,handles);
3743 UpdatePlot(handles);
3744 UpdateColormapOptions(handles);
3745
3746
3747
3748 function popupmenu_windowPreset_CreateFcn(hObject, eventdata, handles)
3749
3750
3751
3752
3753
3754
3755 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
3756 set(hObject,'BackgroundColor','white');
3757 end
3758
3759
3760
3761 windowNames = {'Custom','Full','Abd/Med', 'Head', 'Liver', 'Lung', 'Spine', 'Vrt/Bone'};
3762 windowCenter = {NaN, NaN, -10, 45, 80, -500, 30, 400};
3763 windowWidth = {NaN, NaN, 330, 125, 305, 1500, 300, 1500};
3764 windowPresets = cell2struct([windowNames', windowCenter', windowWidth'], {'name', 'center', 'width'},2);
3765
3766
3767 handles.windowPresets = windowPresets;
3768
3769 selectionList = {windowPresets(:).name};
3770 set(hObject,'String',selectionList(:));
3771 set(hObject,'Value',1);
3772
3773
3774 guidata(hObject,handles);
3775
3776
3777 function checkbox_lockColormap_Callback(hObject, eventdata, handles)
3778
3779
3780
3781
3782
3783 handles.colormapLocked = get(hObject,'Value');
3784
3785 if handles.colormapLocked
3786 state = 'Off';
3787 else
3788 state = 'On';
3789 end
3790
3791 set(handles.popupmenu_chooseColorData,'Enable',state);
3792 set(handles.popupmenu_windowPreset,'Enable',state);
3793 set(handles.slider_windowWidth,'Enable',state);
3794 set(handles.slider_windowCenter,'Enable',state);
3795 set(handles.edit_windowWidth,'Enable',state);
3796 set(handles.edit_windowCenter,'Enable',state);
3797 set(handles.edit_windowRange,'Enable',state);
3798 set(handles.popupmenu_chooseColormap,'Enable',state);
3799
3800
3801 guidata(hObject,handles);
3802
3803
3804 function cst = updateStructureTable(handles,cst)
3805 colorAssigned = true;
3806
3807
3808 for i = 1:size(cst,1)
3809 if ~isfield(cst{i,5},'visibleColor')
3810 colorAssigned = false;
3811 break;
3812 elseif isempty(cst{i,5}.visibleColor)
3813 colorAssigned = false;
3814 break;
3815 end
3816 end
3817
3818
3819 if colorAssigned == false
3820 m = 64;
3821 colorStep = ceil(m/size(cst,1));
3822 colors = colorcube(colorStep*size(cst,1));
3823
3824 colors = colors(1:colorStep:end,:);
3825
3826 for i = 1:size(cst,1)
3827 cst{i,5}.visibleColor = colors(i,:);
3828 end
3829 end
3830
3831 for s = 1:size(cst,1)
3832 handles.VOIPlotFlag(s) = cst{s,5}.Visible;
3833 clr = dec2hex(round(cst{s,5}.visibleColor(:)*255),2)';
3834 clr = ['#';clr(:)]';
3835 if handles.VOIPlotFlag(s)
3836 tmpString{s} = ['<html><table border=0 ><TR><TD bgcolor=',clr,' width="18"><center>✔</center></TD><TD>',cst{s,2},'</TD></TR> </table></html>'];
3837 else
3838 tmpString{s} = ['<html><table border=0 ><TR><TD bgcolor=',clr,' width="18"></TD><TD>',cst{s,2},'</TD></TR> </table></html>'];
3839 end
3840 end
3841 set(handles.legendTable,'String',tmpString);
3842
3843
3844 function cst = generateCstTable(handles,cst)
3845
3846 cst = updateStructureTable(handles,cst);
3847
3848 cstPanel = handles.uipanel3;
3849
3850
3851 cstPanelPosUnit = get(cstPanel,'Units');
3852 set(cstPanel,'Units','pixels');
3853 cstPanelPosPix = get(cstPanel,'Position');
3854 set(cstPanel,'Units',cstPanelPosUnit);
3855
3856 aspectRatio = cstPanelPosPix(3) / cstPanelPosPix(4);
3857
3858
3859 objHeight = 0.095;
3860 lineHeight = 0.1;
3861 yTopSep = 0.12;
3862 tableViewHeight = 1 - yTopSep;
3863
3864
3865 buttonW = objHeight / aspectRatio;
3866 nameW = 3.5*buttonW;
3867 typeW = 3*buttonW;
3868 opW = buttonW;
3869 functionW = 6*buttonW;
3870 penaltyW = 2*buttonW;
3871 paramTitleW = 4*buttonW;
3872 paramW = 2*buttonW;
3873 fieldSep = 0.25*buttonW;
3874
3875
3876
3877
3878 cstPanelChildren = get(cstPanel,'Children');
3879 cstVertTableScroll = findobj(cstPanelChildren,'Style','slider');
3880 if isempty(cstVertTableScroll)
3881 sliderPos = 0;
3882 else
3883 sliderPos = get(cstVertTableScroll,'Max') - get(cstVertTableScroll,'Value');
3884 end
3885
3886 ypos = @(c) tableViewHeight - c*lineHeight + sliderPos;
3887
3888
3889 delete(cstPanelChildren);
3890
3891
3892 tmpAxes = axes('Parent',cstPanel,'units','normalized','position',[0 0 1 1],'visible','off');
3893
3894 organTypes = {'OAR', 'TARGET'};
3895
3896
3897
3898
3899 mpkgObjectives = meta.package.fromName('DoseObjectives');
3900 mpkgConstraints = meta.package.fromName('DoseConstraints');
3901 classList = [mpkgObjectives.ClassList; mpkgConstraints.ClassList];
3902
3903 classList = classList(not([classList.Abstract]));
3904
3905
3906 classNames = cell(2,numel(classList));
3907 for clIx = 1:numel(classList)
3908 cl = classList(clIx);
3909 pList = cl.PropertyList;
3910 pNameIx = arrayfun(@(p) strcmp(p.Name,'name'),pList);
3911 p = pList(pNameIx);
3912 pName = p.DefaultValue;
3913 classNames(:,clIx) = {cl.Name; pName};
3914 end
3915
3916 numOfObjectives = sum(cellfun(@numel,cst(:,6)));
3917
3918 cnt = 0;
3919
3920 newline = '\n';
3921
3922
3923 xPos = 0.01;
3924
3925 h = uicontrol(cstPanel,'Style','text','String','+/-','Units','normalized','Position',[xPos ypos(cnt) buttonW objHeight],'TooltipString','Remove or add Constraint or Objective');
3926 tmp_pos = get(h,'Position');
3927 xPos = xPos + tmp_pos(3) + fieldSep;
3928 h = uicontrol(cstPanel,'Style','text','String','VOI name','Units','normalized','Position',[xPos ypos(cnt) nameW objHeight],'TooltipString','Name of the structure with objective/constraint');
3929 tmp_pos = get(h,'Position');
3930 xPos = xPos + tmp_pos(3) + fieldSep;
3931 h = uicontrol(cstPanel,'Style','text','String','VOI type','Units','normalized','Position',[xPos ypos(cnt) typeW objHeight],'TooltipString','Segmentation Classification');
3932 tmp_pos = get(h,'Position');
3933 xPos = xPos + tmp_pos(3) + fieldSep;
3934 h = uicontrol(cstPanel,'Style','text','String','OP','Units','normalized','Position',[xPos ypos(cnt) opW objHeight],'TooltipString',['Overlap Priority' char(10) '(Smaller number overlaps higher number)']);
3935 tmp_pos = get(h,'Position');
3936 xPos = xPos + tmp_pos(3) + fieldSep;
3937 h = uicontrol(cstPanel,'Style','text','String','Function','Units','normalized','Position',[xPos ypos(cnt) functionW objHeight],'TooltipString','Objective/Constraint function type');
3938 tmp_pos = get(h,'Position');
3939 xPos = xPos + tmp_pos(3) + fieldSep;
3940 h = uicontrol(cstPanel,'Style','text','String','p','Units','normalized','Position',[xPos ypos(cnt) penaltyW objHeight],'TooltipString','Optimization penalty');
3941 tmp_pos = get(h,'Position');
3942 xPos = xPos + tmp_pos(3) + fieldSep;
3943 h = uicontrol(cstPanel,'Style','text','String','| Parameters','Units','normalized','Position',[xPos ypos(cnt) paramTitleW objHeight],'TooltipString','List of parameters','HorizontalAlignment','left');
3944 tmp_pos = get(h,'Position');
3945 xPos = xPos + tmp_pos(3) + fieldSep;
3946 cnt = cnt + 1;
3947
3948
3949 for i = 1:size(cst,1)
3950 if strcmp(cst(i,3),'IGNORED')~=1
3951
3952 if isstruct(cst{i,6})
3953 cst{i,6} = arrayfun(@matRad_DoseOptimizationFunction.convertOldOptimizationStruct,cst{i,6},'UniformOutput',false);
3954 end
3955 for j=1:numel(cst{i,6})
3956
3957 obj = cst{i,6}{j};
3958
3959
3960 if ~isa(obj,'matRad_DoseOptimizationFunction')
3961 try
3962 obj = matRad_DoseOptimizationFunction.createInstanceFromStruct(obj);
3963 catch ME
3964 warning('Objective/Constraint not valid!\n%s',ME.message)
3965 continue;
3966 end
3967 end
3968
3969
3970 xPos = 0.01;
3971
3972 h = uicontrol(cstPanel,'Style','pushbutton','String','-','Units','normalized','Position',[xPos ypos(cnt) buttonW objHeight],'TooltipString','Remove Objective/Constraint','Callback',{@btObjRemove_Callback,handles},...
3973 'UserData',[i,j]);
3974 tmp_pos = get(h,'Position');
3975 xPos = xPos + tmp_pos(3) + fieldSep;
3976 h = uicontrol(cstPanel','Style','edit','String',cst{i,2},'Units','normalized','Position',[xPos ypos(cnt) nameW objHeight],'TooltipString','Name',...
3977 'Enable','inactive',...
3978 'UserData',[i,2],'Callback',{@editCstParams_Callback,handles});
3979 tmp_pos = get(h,'Position');
3980 xPos = xPos + tmp_pos(3) + fieldSep;
3981 h = uicontrol(cstPanel,'Style','popupmenu','String',organTypes','Value',find(strcmp(cst{i,3},organTypes)),'Units','normalized','Position',[xPos ypos(cnt) typeW objHeight],'TooltipString','Segmentation Classification',...
3982 'UserData',[i,3],'Callback',{@editCstParams_Callback,handles});
3983 tmp_pos = get(h,'Position');
3984 xPos = xPos + tmp_pos(3) + fieldSep;
3985 h = uicontrol(cstPanel,'Style','edit','String',num2str(cst{i,5}.Priority),'Units','normalized','Position',[xPos ypos(cnt) opW objHeight],'TooltipString',['Overlap Priority' newline '(Smaller number overlaps higher number)'],...
3986 'UserData',[i,5],'Callback',{@editCstParams_Callback,handles});
3987 tmp_pos = get(h,'Position');
3988 xPos = xPos + tmp_pos(3) + fieldSep;
3989
3990 h = uicontrol(cstPanel,'Style','popupmenu','String',classNames(2,:)','Value',find(strcmp(obj.name,classNames(2,:))),'Units','normalized','Position',[xPos ypos(cnt) functionW objHeight],'TooltipString','Select Objective/Constraint',...
3991 'UserData',{[i,j],classNames(1,:)},'Callback',{@changeObjFunction_Callback,handles});
3992 tmp_pos = get(h,'Position');
3993 xPos = xPos + tmp_pos(3) + fieldSep;
3994
3995
3996 if isa(obj,'DoseObjectives.matRad_DoseObjective')
3997 h = uicontrol(cstPanel,'Style','edit','String',num2str(obj.penalty),'Units','normalized','Position',[xPos ypos(cnt) penaltyW objHeight],'TooltipString','Objective Penalty','UserData',[i,j,0],'Callback',{@editObjParam_Callback,handles});
3998 else
3999 h = uicontrol(cstPanel,'Style','edit','String','----','Units','normalized','Position',[xPos ypos(cnt) penaltyW objHeight],'Enable','off');
4000 end
4001 tmp_pos = get(h,'Position');
4002 xPos = xPos + tmp_pos(3) + fieldSep;
4003
4004
4005 for p = 1:numel(obj.parameterNames)
4006 h = text('Parent',tmpAxes,'String',['| ' obj.parameterNames{p} ':'],'VerticalAlignment','middle','Units','normalized','Position',[xPos ypos(cnt)+lineHeight/2],'Interpreter','tex','FontWeight','normal',...
4007 'FontSize',get(cstPanel,'FontSize'),'FontName',get(cstPanel,'FontName'),'FontUnits',get(cstPanel,'FontUnits'),'FontWeight','normal');
4008 tmp_pos = get(h,'Extent');
4009 xPos = xPos + tmp_pos(3) + fieldSep;
4010
4011
4012 if iscell(obj.parameterTypes{p})
4013 h = uicontrol(cstPanel,'Style','popupmenu','String',obj.parameterTypes{p}','Value',obj.parameters{p},'TooltipString',obj.parameterNames{p},'Units','normalized','Position',[xPos ypos(cnt) paramW*2 objHeight],'UserData',[i,j,p],'Callback',{@editObjParam_Callback,handles});
4014 else
4015 h = uicontrol(cstPanel,'Style','edit','String',num2str(obj.parameters{p}),'TooltipString',obj.parameterNames{p},'Units','normalized','Position',[xPos ypos(cnt) paramW objHeight],'UserData',[i,j,p],'Callback',{@editObjParam_Callback,handles});
4016 end
4017
4018 tmp_pos = get(h,'Position');
4019 xPos = xPos + tmp_pos(3) + fieldSep;
4020 end
4021
4022 cnt = cnt +1;
4023 end
4024 end
4025 end
4026 xPos = 0.01;
4027 hAdd = uicontrol(cstPanel,'Style','pushbutton','String','+','Units','normalized','Position',[xPos ypos(cnt) buttonW objHeight],'TooltipString','Add Objective/Constraint','Callback',{@btObjAdd_Callback,handles});
4028 tmp_pos = get(hAdd,'Position');
4029 xPos = xPos + tmp_pos(3) + fieldSep;
4030 h = uicontrol(cstPanel,'Style','popupmenu','String',cst(:,2)','Units','normalized','Position',[xPos ypos(cnt) nameW objHeight]);
4031 set(hAdd,'UserData',h);
4032
4033
4034 lastPos = ypos(cnt);
4035 firstPos = ypos(0);
4036 tableHeight = abs(firstPos - lastPos);
4037
4038 exceedFac = tableHeight / tableViewHeight;
4039 if exceedFac > 1
4040 sliderFac = exceedFac - 1;
4041 uicontrol(cstPanel,'Style','slider','Units','normalized','Position',[0.975 0 0.025 1],'Min',0,'Max',ceil(sliderFac)*tableViewHeight,'SliderStep',[lineHeight tableViewHeight] ./ (ceil(sliderFac)*tableViewHeight),'Value',ceil(sliderFac)*tableViewHeight - sliderPos,'Callback',{@cstTableSlider_Callback,handles});
4042 end
4043
4044
4045
4046 function uipanel3_SizeChangedFcn(hObject, eventdata, handles)
4047
4048
4049
4050
4051 try
4052 generateCstTable(handles,evalin('base','cst'));
4053 catch
4054 end
4055
4056 function btObjAdd_Callback(hObject, ~, handles)
4057
4058
4059
4060 popupHandle = hObject.UserData;
4061 cstIndex = popupHandle.Value;
4062
4063 cst = evalin('base','cst');
4064
4065 if strcmp(cst{cstIndex,3},'TARGET')
4066 cst{cstIndex,6}{end+1} = struct(DoseObjectives.matRad_SquaredDeviation);
4067 else
4068 cst{cstIndex,6}{end+1} = struct(DoseObjectives.matRad_SquaredOverdosing);
4069 end
4070
4071 assignin('base','cst',cst);
4072
4073 generateCstTable(handles,cst);
4074
4075 function btObjRemove_Callback(hObject, ~, handles)
4076
4077
4078
4079 ix = hObject.UserData;
4080
4081 cst = evalin('base','cst');
4082
4083
4084 cst{ix(1),6}(ix(2)) = [];
4085
4086 assignin('base','cst',cst);
4087
4088 generateCstTable(handles,cst);
4089
4090 function editObjParam_Callback(hObject, ~, handles)
4091
4092
4093
4094 ix = hObject.UserData;
4095
4096 cst = evalin('base','cst');
4097
4098
4099
4100
4101
4102
4103 if ix(3) == 0
4104 cst{ix(1),6}{ix(2)}.penalty = str2double(hObject.String);
4105 elseif isequal(hObject.Style,'popupmenu')
4106 cst{ix(1),6}{ix(2)}.parameters{ix(3)} = hObject.Value;
4107 else
4108 cst{ix(1),6}{ix(2)}.parameters{ix(3)} = str2double(hObject.String);
4109 end
4110
4111 assignin('base','cst',cst);
4112
4113 generateCstTable(handles,cst);
4114
4115 function changeObjFunction_Callback(hObject, ~, handles)
4116
4117
4118
4119 data = hObject.UserData;
4120 ix = data{1};
4121 classNames = data{2};
4122 classToCreate = classNames{hObject.Value};
4123
4124 cst = evalin('base','cst');
4125
4126
4127
4128
4129 currentObj = cst{ix(1),6}{ix(2)};
4130 currentClass = class(currentObj);
4131 if ~strcmp(currentClass,classToCreate)
4132 newObj = eval(classToCreate);
4133
4134
4135
4136 if (isfield(currentObj,'penalty') || isprop(currentObj,'penalty')) && isprop(newObj,'penalty')
4137 newObj.penalty = currentObj.penalty;
4138 end
4139
4140 cst{ix(1),6}{ix(2)} = struct(newObj);
4141
4142 assignin('base','cst',cst);
4143
4144 generateCstTable(handles,cst);
4145 end
4146
4147 function editCstParams_Callback(hObject,~,handles)
4148 data = hObject.UserData;
4149 ix = data(1);
4150 col = data(2);
4151
4152 cst = evalin('base','cst');
4153
4154 switch col
4155 case 2
4156 cst{ix,col} = hObject.String;
4157 case 3
4158 cst{ix,col} = hObject.String{hObject.Value};
4159 case 5
4160 cst{ix,col}.Priority = uint32(str2double(hObject.String));
4161 otherwise
4162 warning('Wrong column assignment in GUI based cst setting');
4163 end
4164
4165 assignin('base','cst',cst);
4166
4167 generateCstTable(handles,cst);
4168
4169
4170
4171 function radiobutton3Dconf_Callback(hObject, eventdata, handles)
4172
4173
4174
4175
4176
4177
4178 function x = matRad_checkForConnectedBixelRows(stf)
4179
4180 x = true;
4181
4182 for i = 1:size(stf,2)
4183
4184 bixelPos = reshape([stf(i).ray.rayPos_bev],3,[]);
4185
4186 rowCoords = unique(bixelPos(3,:));
4187
4188 for j = 1:numel(rowCoords)
4189
4190 increments = diff(bixelPos(1,rowCoords(j) == bixelPos(3,:)));
4191
4192
4193 if numel(unique(increments)) > 1
4194 x = false;
4195 return;
4196 end
4197 end
4198
4199 end
4200
4201
4202 function cstTableSlider_Callback(hObject, eventdata, handles)
4203
4204
4205
4206
4207
4208
4209 generateCstTable(handles,evalin('base','cst'));
4210
4211
4212 function cstTableSlider_CreateFcn(hObject, eventdata, handles)
4213
4214
4215
4216
4217
4218 if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
4219 set(hObject,'BackgroundColor',[.9 .9 .9]);
4220 end
4221