123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723 |
- classdef XTPS < handle
- %XTPS Main GUI for RDXTPS front end.
- %
- % Default to contain three SliceViewerPanels for viewing.
- %
- % TODO:
- % Move Geometry and optResults into SliceViewerPanelSource completely so that
- % only one copy exist.
- % Move color stuff into Geometry so that can be saved.
- %
- % See also SliceViewerPanel
- %
- % Author Xiaohu Mo
- properties
- handles
- patient_dir
- dosecalcSetup
- end
- methods
- %-------------------------------------------------------------------------------
- function obj = XTPS() % XTPS constructor
- hMainFigure = figure('MenuBar', 'none', 'Name', 'RDXTPS: No Patient', 'Position', [100 100 800 600], 'Renderer', 'painters');
- obj.handles = guihandles(hMainFigure);
- obj.handles.hMainFigure = hMainFigure;
- % Adding widgets
- obj.handles.hROIPanel = uipanel('Parent', obj.handles.hMainFigure, 'Title', 'ROI display');
- obj.handles.hROITable = uitable('Parent', obj.handles.hROIPanel);
- obj.handles.hDosePanel = uipanel('Parent', obj.handles.hMainFigure, 'Title', 'Dose display');
- obj.handles.hDoseTable = uitable('Parent', obj.handles.hDosePanel);
- obj.handles.hDoseModeDropdown = uicontrol('Parent', obj.handles.hDosePanel, 'Style', 'popupmenu');
- obj.handles.hDoseModeLabel = uicontrol('Parent', obj.handles.hDosePanel, 'Style', 'text');
- obj.handles.hMiscPanel = uipanel('Parent', obj.handles.hMainFigure, 'Title', 'Misc settings');
- obj.handles.hTCSShow = uicontrol('Parent', obj.handles.hMiscPanel, 'Style', 'checkbox');
- obj.handles.hWWLabel = uicontrol('Parent', obj.handles.hMiscPanel, 'Style', 'edit');
- obj.handles.hWWSlider = uicontrol('Parent', obj.handles.hMiscPanel, 'Style', 'slider');
- obj.handles.hWWEdit = uicontrol('Parent', obj.handles.hMiscPanel, 'Style', 'edit');
- obj.handles.hWLLabel = uicontrol('Parent', obj.handles.hMiscPanel, 'Style', 'edit');
- obj.handles.hWLSlider = uicontrol('Parent', obj.handles.hMiscPanel, 'Style', 'slider');
- obj.handles.hWLEdit = uicontrol('Parent', obj.handles.hMiscPanel, 'Style', 'edit');
- obj.handles.hSVPS = SliceViewerPanelSource();
- obj.handles.hSliceViewerPanel(1) = SliceViewerPanel(obj.handles.hSVPS, 3, obj.handles.hMainFigure);
- obj.handles.hSliceViewerPanel(2) = SliceViewerPanel(obj.handles.hSVPS, 2, obj.handles.hMainFigure);
- obj.handles.hSliceViewerPanel(3) = SliceViewerPanel(obj.handles.hSVPS, 1, obj.handles.hMainFigure);
- % File menu
- obj.handles.hFileMenu = uimenu(obj.handles.hMainFigure, 'Label','File');
- obj.handles.hImportDicomRTMenu = uimenu(obj.handles.hFileMenu, 'Label', '1a. Import DicomRT Geometry');
- obj.handles.hNRRD1 = uimenu(obj.handles.hFileMenu, 'Label', '1b. Geometry wizard (am/nrrd)');
- obj.handles.hNRRD2 = uimenu(obj.handles.hFileMenu, 'Label', '1b. Add Geometry ROI');
- obj.handles.hImgDownsample = uimenu(obj.handles.hFileMenu, 'Label', '1(c). Downsample data');
-
- obj.handles.hDosecalcMenu = uimenu(obj.handles.hFileMenu, 'Label', '2.1 Beamlet Dose Calculation');
- obj.handles.hMergeBeamlets = uimenu(obj.handles.hFileMenu, 'Label', '2.2 Merge Beamlets');
-
- obj.handles.hOptimMenu = uimenu(obj.handles.hFileMenu, 'Label', '3a.1 Classical Optimization');
- obj.handles.hSaveOptimResultsMenu = uimenu(obj.handles.hFileMenu, 'Label', '3a.2 Save Optimization Results');
- obj.handles.hGetFullDose = uimenu(obj.handles.hFileMenu, 'Label', '3a.3 Get Full Dose');
-
- obj.handles.hRO_GoalSpec = uimenu(obj.handles.hFileMenu, 'Label', '3a. RO Goal Spec');
- obj.handles.hRO_Optimize = uimenu(obj.handles.hFileMenu, 'Label', '3b. RO Optimization');
- obj.handles.hRO_fullDose = uimenu(obj.handles.hFileMenu, 'Label', '3c. Full dose calc');
-
-
- obj.handles.hLoadGeometryMenu = uimenu(obj.handles.hFileMenu, 'Label', 'Load Geometry', 'Separator','on');
- obj.handles.hLoadOptresultsMenu = uimenu(obj.handles.hFileMenu, 'Label', 'Load OptResults');
-
- obj.handles.hSaveAsGeometryMenu = uimenu(obj.handles.hFileMenu, 'Label', 'Save Geometry As...', 'Separator','on');
- obj.handles.hSaveAsOptResultsMenu = uimenu(obj.handles.hFileMenu, 'Label', 'Save OptResults As...');
-
- obj.handles.hExportPinnacleMenu = uimenu(obj.handles.hFileMenu, 'Label', 'Export Pinnacle Files', 'Separator','on');
-
- % Tools menu
- obj.handles.hToolsMenu = uimenu(obj.handles.hMainFigure, 'Label', 'Tools');
- obj.handles.hPlotDVHMenu = uimenu(obj.handles.hToolsMenu, 'Label', 'Plot DVH');
- obj.handles.hResampleGeometry = uimenu(obj.handles.hToolsMenu, 'Label', 'Resample Geometry');
-
- % Associate callbacks
- set(obj.handles.hMainFigure, 'ResizeFcn', @obj.set_layout);
- set(obj.handles.hROITable, 'CellSelectionCallback', @obj.ROITable_CellSelectionCallback);
- set(obj.handles.hDoseTable, 'CellSelectionCallback', @obj.DoseTable_CellSelectionCallback);
- set(obj.handles.hDoseTable, 'CellEditCallback', @obj.DoseTable_CellEditCallback);
- set(obj.handles.hImportDicomRTMenu, 'Callback', @obj.ImportDicomRTMenu_Callback);
- set(obj.handles.hDosecalcMenu, 'Callback', @obj.DosecalcMenu_Callback);
-
- % Grozomah
- set(obj.handles.hNRRD1, 'Callback', @obj.NRRD1_Callback);
- set(obj.handles.hNRRD2, 'Callback', @obj.NRRD2_Callback);
- set(obj.handles.hImgDownsample, 'Callback', @obj.ImgDownsample_Callback);
-
- set(obj.handles.hRO_GoalSpec, 'Callback', @obj.RO_GoalSpec);
- set(obj.handles.hRO_Optimize, 'Callback', @obj.RO_Optimize);
- set(obj.handles.hRO_fullDose, 'Callback', @obj.RO_fullDose);
-
- % Grozomah
- set(obj.handles.hMergeBeamlets, 'Callback', @obj.MergeBeamlets_Callback);
- set(obj.handles.hGetFullDose, 'Callback', @obj.GetFullDose_Callback);
-
- set(obj.handles.hSaveOptimResultsMenu, 'Callback', @obj.SaveOptimResultsMenu_Callback);
- set(obj.handles.hOptimMenu, 'Callback', @obj.OptimMenu_Callback);
- set(obj.handles.hLoadGeometryMenu, 'Callback', @obj.LoadGeometryMenu_Callback);
- set(obj.handles.hLoadOptresultsMenu, 'Callback', @obj.LoadOptresultsMenu_Callback);
- set(obj.handles.hSaveAsGeometryMenu, 'Callback', @obj.SaveAsGeometryMenu_Callback);
- set(obj.handles.hSaveAsOptResultsMenu, 'Callback', @obj.SaveAsOptResultsMenu_Callback);
- set(obj.handles.hExportPinnacleMenu, 'Callback', @obj.ExportPinnacleMenu_Callback);
- set(obj.handles.hPlotDVHMenu, 'Callback', @obj.PlotDVHMenu_Callback);
- set(obj.handles.hResampleGeometry, 'Callback', @obj.ResampleGeometry_Callback);
- set(obj.handles.hDoseModeDropdown, 'Callback', @obj.DoseModeDropdown_Callback);
- set(obj.handles.hWWSlider, 'Callback', @obj.WWSlider_Callback);
- set(obj.handles.hWWEdit, 'Callback', @obj.WWEdit_Callback);
- set(obj.handles.hWLSlider, 'Callback', @obj.WLSlider_Callback);
- set(obj.handles.hWLEdit, 'Callback', @obj.WLEdit_Callback);
-
- set(obj.handles.hTCSShow, 'Callback', @obj.TCSShow_Callback);
- obj.set_widget_properties();
- obj.set_layout();
- obj.updateROITable();
- obj.updateDoseTable();
- obj.updateCTWindowControls();
- end % XTPS constructor
- %-------------------------------------------------------------------------------
- function set_widget_properties(obj)
- %% Set widget default properties, excluding those related to data
- h = obj.handles; % shortcut
- set(h.hROITable, 'ColumnEditable', logical([1 0 0]));
- set(h.hROITable, 'ColumnFormat', {'logical', 'char', 'char'});
- set(h.hROITable, 'ColumnName', {'V' 'C' 'ROI'});
- set(h.hROITable, 'ColumnWidth',{20 15 'auto'});
- set(h.hROITable, 'RowName', {'numbered'});
- set(h.hROITable, 'RowStriping', 'off');
- set(h.hROITable, 'ToolTipString', 'click to set color');
- set(h.hDoseTable, 'ColumnEditable', logical([0 1 1]));
- set(h.hDoseTable, 'ColumnFormat', {'char' 'numeric' 'numeric'});
- set(h.hDoseTable, 'ColumnName', {'C' 'Dose' 'Alpha'});
- set(h.hDoseTable, 'ColumnWidth',{15 'auto' 'auto'});
- set(h.hDoseTable, 'RowName', []);
- set(h.hDoseTable, 'RowStriping', 'off');
- set(h.hDoseTable, 'ToolTipString', 'click to set color');
- set(h.hDoseModeLabel, 'String', 'display mode');
- set(h.hDoseModeDropdown, 'String', {'None' 'Isodose' 'IsodoseLine' 'Colorwash'});
-
- set(h.hWWLabel, 'String', 'Win. Width');
- set(h.hWWSlider, 'Min', 0, 'Max', 2048, 'SliderStep', [10/2048 100/2048]);
- set(h.hWLLabel, 'String', 'Win. Level');
- set(h.hWLSlider, 'Min', 0, 'Max', 2048, 'SliderStep', [10/2048 100/2048]);
-
- set(h.hTCSShow, 'String', 'Show TCS planes', 'Value', get(h.hTCSShow, 'Max'));
- % BackgroundColor (get all ui object handles except uitable)
- set(findobj(h.hMainFigure, '-property', 'BackgroundColor', '-not', 'Type', 'uitable'), ...
- 'BackgroundColor', get(h.hMainFigure, 'Color'));
- end
- %-------------------------------------------------------------------------------
- function set_layout(obj, src, evt)
- % Set widget positions and size. Also as ResizeFcn.
- h = obj.handles; % shortcut
- set(findobj(h.hMainFigure, '-property', 'Units'), 'Units', 'Normalized');
- padding = [0.005 0.01];
- setPositionXY(h.hDosePanel, [0 0.2], [0.2 0.5], padding);
- setPositionXY(h.hROIPanel, [0 0.2], [0.5 1], padding);
- setPositionXY(h.hMiscPanel, [0 0.2], [0 0.2], padding);
- setPositionXY(h.hSliceViewerPanel(1).hPanel, [0.2 0.7], [0 1], padding);
- setPositionXY(h.hSliceViewerPanel(2).hPanel, [0.7 1], [0.5 1], padding);
- setPositionXY(h.hSliceViewerPanel(3).hPanel, [0.7 1], [0 0.5], padding);
- setPositionXY(h.hROITable, [0 1], [0 1], padding);
- setPositionXY(h.hDoseModeDropdown, [0.5 1], [0.9 1], padding);
- setPositionXY(h.hDoseModeLabel, [0 0.5], [0.9 1], padding);
- setPositionXY(h.hDoseTable, [0 1], [0 0.9], padding);
-
- setPositionXY(h.hWWLabel, [0 0.3], [0.67 1], padding, 1.5, 'characters');
- setPositionXY(h.hWWSlider, [0.3 0.85], [0.67 1], padding, 1.5, 'characters');
- setPositionXY(h.hWWEdit, [0.85 1], [0.67 1], padding, 1.5, 'characters');
- setPositionXY(h.hWLLabel, [0 0.3], [0.33 0.67], padding, 1.5, 'characters');
- setPositionXY(h.hWLSlider, [0.3 0.85], [0.33 0.67], padding, 1.5, 'characters');
- setPositionXY(h.hWLEdit, [0.85 1], [0.33 0.67], padding, 1.5, 'characters');
- setPositionXY(h.hTCSShow, [0 1], [0.0 0.33], padding, 1.5, 'characters');
-
- table_width = getWidthPixel(obj.handles.hROITable);
- set(obj.handles.hROITable, 'ColumnWidth', {20 15 table_width-20-15-35});
- table_width = getWidthPixel(obj.handles.hDoseTable);
- set(obj.handles.hDoseTable, 'ColumnWidth', {15 (table_width-15)/2-2 (table_width-15)/2-2});
-
- % Panel ResizeFcn not executed after init. Has to manually call.
- for i = 1:numel(h.hSliceViewerPanel)
- h.hSliceViewerPanel(i).set_layout();
- end
- end
- %-------------------------------------------------------------------------------
- function load_geometry(obj, geometry_filename)
- %% load geometry
- if nargin == 2 % load the geometry file if supplied
- load(geometry_filename);
- elseif nargin == 1 % Geometry should be loaded already
- Geometry = obj.handles.hSVPS.Geometry;
- if isempty(obj.handles.hSVPS.Geometry)
- % TODO appropriate handling
- return;
- end
- end
- % add x,y,z axis for plotting purposes
- Geometry.x = Geometry.start(1) + Geometry.voxel_size(1) * (0:size(Geometry.rhomw, 1)-1);
- Geometry.y = Geometry.start(2) + Geometry.voxel_size(2) * (0:size(Geometry.rhomw, 2)-1);
- Geometry.z = Geometry.start(3) + Geometry.voxel_size(3) * (0:size(Geometry.rhomw, 3)-1);
- for i = 1:numel(Geometry.ROIS)
- % TODO unify curves as N x 3 cell array so we don't need Xcurves & Ycurves,
- % but that way will break back-compatibility.
- if isfield(Geometry.ROIS{i}, 'Xcurves')
- Xcurves_coordinate = cellfun(@(c)c(1,1), Geometry.ROIS{i}.Xcurves);
- Geometry.ROIS{i}.Xcurves_slices = ...
- round((Xcurves_coordinate - Geometry.start(1)) / Geometry.voxel_size(1)) + 1;
- else
- % Old version doesn't have XYcurves. Create an empty index to skip plotting.
- Geometry.ROIS{i}.Xcurves_slices = [];
- end
-
- if isfield(Geometry.ROIS{i}, 'Ycurves')
- Ycurves_coordinate = cellfun(@(c)c(1,2), Geometry.ROIS{i}.Ycurves);
- Geometry.ROIS{i}.Ycurves_slices = ...
- round((Ycurves_coordinate - Geometry.start(2)) / Geometry.voxel_size(2)) + 1;
- else
- % Old version doesn't have XYcurves. Create an empty index to skip plotting.
- Geometry.ROIS{i}.Ycurves_slices = [];
- end
-
- if isfield(Geometry.ROIS{i}, 'curves')
- Zcurves_coordinate = cellfun(@(c)c(1,3), Geometry.ROIS{i}.curves);
- Geometry.ROIS{i}.Zcurves_slices = ...
- round((Zcurves_coordinate - Geometry.start(3)) / Geometry.voxel_size(3)) + 1;
- else
- Geometry.ROIS{i}.Zcurves_slices = [];
- end
- end
-
- % Convert data into float
- if isinteger(Geometry.data)
- Geometry.data = single(Geometry.data);
- end
- % Init/set display settings if absent
- num_ROI = numel(Geometry.ROIS);
- for i = 1:num_ROI
- if ~isfield(Geometry.ROIS{i}, 'visible')
- Geometry.ROIS{i}.visible = false;
- end
- if ~isfield(Geometry.ROIS{i}, 'color')
- Geometry.ROIS{i}.color = rand(1,3);
- end
- end
- % Set/save to SliceViewerPanelSource
- obj.handles.hSVPS.Geometry = Geometry;
- obj.handles.hSVPS.TCSVisible = ...
- (get(obj.handles.hTCSShow, 'Value') == get(obj.handles.hTCSShow, 'Max'));
-
- % updates
- obj.handles.hSliceViewerPanel(1).load_data();
- obj.handles.hSliceViewerPanel(2).load_data();
- obj.handles.hSliceViewerPanel(3).load_data();
- obj.updateROITable();
- end
- %-------------------------------------------------------------------------------
- function load_optResults(obj, optresults_filename)
- if nargin == 2 % load the optResults file if supplied
- load(optresults_filename, 'optResults');
- obj.handles.hSVPS.optResults = optResults;
- elseif nargin == 1 % optResults should exist already
- % Do nothing for now
- end
- obj.updateDoseTable();
- end
- %-------------------------------------------------------------------------------
- function updateROITable(obj)
- % Update ROITable using values in Geometry.ROIS
- if isempty(obj.handles.hSVPS.Geometry); return; end
- tdata = get(obj.handles.hROITable, 'Data');
- % Update table data according to display settings
- for i = 1:numel(obj.handles.hSVPS.Geometry.ROIS)
- tdata{i, 1} = obj.handles.hSVPS.Geometry.ROIS{i}.visible;
- c = obj.handles.hSVPS.Geometry.ROIS{i}.color;
- tdata{i, 2} = sprintf('<html><span style="color:%s">■</span></html>', rgb2str(c));
- tdata{i, 3} = obj.handles.hSVPS.Geometry.ROIS{i}.name;
- end
- set(obj.handles.hROITable, 'Data', tdata);
- drawnow;
- obj.set_layout();
- end
- %-------------------------------------------------------------------------------
- function updateDoseTable(obj)
- % Update DoseTable using data in SliceViewerPanelSource.dosedisp
- % if isempty(obj.handles.hSVPS.Geometry) && isempty(obj.handles.hSVPS.optResults); return; end
- tdata = cell(0);
- % Update table data according to display settings
- for i = 1:numel(obj.handles.hSVPS.dosedisp.level)
- tdata{i, 1} = sprintf('<html><span style="color:%s">■</span></html>', rgb2str(obj.handles.hSVPS.dosedisp.color(i,:)));
- tdata{i, 2} = obj.handles.hSVPS.dosedisp.level(i);
- tdata{i, 3} = obj.handles.hSVPS.dosedisp.alpha(i);
- end
- % disable the callback to prevent recursion
- set(obj.handles.hDoseTable, 'CellSelectionCallback', []);
- set(obj.handles.hDoseTable, 'Data', tdata);
- drawnow; % Flush //IMPORTANT
- set(obj.handles.hDoseTable, 'CellSelectionCallback', @obj.DoseTable_CellSelectionCallback);
- end
- %-------------------------------------------------------------------------------
- function updateCTWindowControls(obj)
- set(obj.handles.hWWSlider, 'Value', obj.handles.hSVPS.ctWindow.ww);
- set(obj.handles.hWWEdit, 'String', num2str(obj.handles.hSVPS.ctWindow.ww));
- set(obj.handles.hWLSlider, 'Value', obj.handles.hSVPS.ctWindow.wl);
- set(obj.handles.hWLEdit, 'String', num2str(obj.handles.hSVPS.ctWindow.wl));
- end
- %-------------------------------------------------------------------------------
- function ROITable_CellSelectionCallback(obj, hObject, eventdata)
- % eventdata structure with the following fields (see UITABLE)
- % Indices: row and column indices of the cell(s) currently selecteds
- % Avoid "fake" event during initialization
- if ~isempty(eventdata.Indices)
- roi_idx = eventdata.Indices(1);
- if eventdata.Indices(2) == 1
- % toggle ROI display in display settings
- tdata = get(hObject, 'Data');
- obj.handles.hSVPS.Geometry.ROIS{roi_idx}.visible = ~tdata{roi_idx, 1};
- else % eventdata.Indices(2) ~= 1
- % pick and save color
- c = uisetcolor;
- if ~(isscalar(c) && c == 0)
- obj.handles.hSVPS.Geometry.ROIS{roi_idx}.color = c;
- % also make it visible
- obj.handles.hSVPS.Geometry.ROIS{roi_idx}.visible = true;
- end
- end
- obj.updateROITable();
- end
- end
- %-------------------------------------------------------------------------------
- function DoseTable_CellSelectionCallback(obj, tilde, eventdata)
- % eventdata structure with the following fields (see UITABLE)
- % Indices: row and column indices of the cell(s) currently selecteds
- % Avoid fake event during initialization
- if ~isempty(eventdata.Indices)
- if eventdata.Indices(2) == 1
- % pick and save color
- c = uisetcolor;
- if ~(isscalar(c) && c == 0)
- obj.handles.hSVPS.dosedisp.color(eventdata.Indices(1), :) = c;
- obj.updateDoseTable();
- end
- end
- end
- end
- %-------------------------------------------------------------------------------
- function DoseTable_CellEditCallback(obj, tilde, eventdata)
- % Update handles.hSVPS.dosedisp
- if eventdata.Indices(2) == 2
- obj.handles.hSVPS.dosedisp.level(eventdata.Indices(1)) = eventdata.NewData;
- elseif eventdata.Indices(2) == 3
- obj.handles.hSVPS.dosedisp.alpha(eventdata.Indices(1)) = eventdata.NewData;
- end
- obj.updateDoseTable();
- end
- %-------------------------------------------------------------------------------
- function WWSlider_Callback(obj, src, evt)
- % set window width property of SliceViewerPancelSource
- value = round(get(src, 'Value'));
-
- obj.handles.hSVPS.ctWindow.ww = value;
- obj.updateCTWindowControls();
- end
- %-------------------------------------------------------------------------------
- function WWEdit_Callback(obj, src, evt)
- % set window width property of SliceViewerPancelSource
- value = round(str2double(get(src, 'String')));
- % clipping to valid value
- value = max(value, get(obj.handles.hWWSlider, 'Min'));
- value = min(value, get(obj.handles.hWWSlider, 'Max'));
-
- obj.handles.hSVPS.ctWindow.ww = value;
- obj.updateCTWindowControls();
- end
- %-------------------------------------------------------------------------------
- function WLSlider_Callback(obj, src, evt)
- % set window width property of SliceViewerPancelSource
- value = round(get(src, 'Value'));
-
- obj.handles.hSVPS.ctWindow.wl = value;
- obj.updateCTWindowControls();
- end
- %-------------------------------------------------------------------------------
- function WLEdit_Callback(obj, src, evt)
- % set window width property of SliceViewerPancelSource
- value = round(str2double(get(src, 'String')));
- % clipping to valid value
- value = max(value, get(obj.handles.hWLSlider, 'Min'));
- value = min(value, get(obj.handles.hWLSlider, 'Max'));
-
- obj.handles.hSVPS.ctWindow.wl = value;
- obj.updateCTWindowControls();
- end
- %-------------------------------------------------------------------------------
- function ImportDicomRTMenu_Callback(obj, src, evt)
-
- [obj.handles.hSVPS.Geometry obj.patient_dir] = RDXTPS_geometry_setup_wizard_ASP();
- obj.load_geometry();
-
- obj.handles.hSVPS.Geometry.patient_dir
-
-
- a=obj.handles.hSVPS.Geometry;
- disp(1)
- end
-
- %-------------------------------------------------------------------------------
- % Grozomah
- function NRRD1_Callback(obj, src, evt)
- [obj.handles.hSVPS.Geometry] = load2geometry();
- obj.load_geometry();
-
- [obj.handles.hSVPS.Geometry] = nrrd2ROI(obj.handles.hSVPS.Geometry);
- obj.load_geometry();
- disp('New ROI loaded!')
- end
- %-------------------------------------------------------------------------------
- % Grozomah
- function NRRD2_Callback(obj, src, evt)
- [obj.handles.hSVPS.Geometry] = nrrd2ROI(obj.handles.hSVPS.Geometry);
- obj.load_geometry();
- disp('New ROI loaded!')
- end
-
- %-------------------------------------------------------------------------------
- % Grozomah
- function ImgDownsample_Callback(obj, src, evt)
- disp('Making downsampled geometry')
-
- make_downsampled_Geometry(obj.handles.hSVPS.Geometry)
-
- end
-
-
- %-------------------------------------------------------------------------------
- function DosecalcMenu_Callback(obj, src, evt)
- % TODO fix patient_dir system
- % [obj.dosecalcSetup obj.patient_dir] = RDXTPS_dosecalcSetup(obj.dosecalcSetup, obj.patient_dir, obj.handles.hSVPS.Geometry);
- % [obj.dosecalcSetup obj.patient_dir] = RDXTPS_dosecalcSetup(obj.dosecalcSetup, [], obj.handles.hSVPS.Geometry);
- %
- % % Temporary fix for Gustavo asking energy limit
- % answer = inputdlg('Machine energy limit: (MeV)', 'Energy limit', 1, {'250'});
- % maxMachineEnergyStr = answer{1};
- %
- % % run beamlet dose calculation
- % cmdline = ['.' filesep 'RDXdosecalc.exe "' fullfile(obj.patient_dir, 'dosecalc_input.txt') '"' ' ' maxMachineEnergyStr];
- % % Grozomah ##
- % % cmdline = ['.' filesep 'RDXoptimizer.exe "' fullfile(obj.patient_dir, 'dosecalc_input.txt') '"'];
- %
- % if ispc
- % execline = ['cmd /c ' cmdline ' &'];
- % elseif isunix
- % % xterm -e "export LD_LIBRARY_PATH=. ; ./RDXdosecalc.exe '../patients/Knew/dosecalc_input.txt' ; read" &
- % % TODO fix single quote
- % cmdline = ['xterm -e "export LD_LIBRARY_PATH=. ; ./RDXdosecalc.exe ' fullfile(obj.patient_dir, 'dosecalc_input.txt') ' ; read" &'];
- % end
- % msgbox(sprintf('Start beamlet dose calculation.\nRun this if not started automatically:\n%s', cmdline));
- % system(execline);
- obj.handles.hSVPS.Geometry.num_batches = helicalDosecalcSetup7(obj.handles.hSVPS.Geometry.patient_dir)
- end
- %-------------------------------------------------------------------------------
- % Grozomah
- function MergeBeamlets_Callback(obj, src, evt)
- if isfield(obj.handles.hSVPS.Geometry, 'num_batches')
- merge_beamlets(obj.handles.hSVPS.Geometry.num_batches, obj.handles.hSVPS.Geometry.patient_dir);
- else
- % num_batches = 1;
- str = input('Enter num of beam batches: ','s');
- merge_beamlets(str2double(str), obj.handles.hSVPS.Geometry.patient_dir);
- end
-
- disp('Beamlets merged!')
- end
- %-------------------------------------------------------------------------------
- function OptimMenu_Callback(obj, src, evt)
- % TODO fix patient_dir system
- % if isempty(obj.patient_dir)
- load('WiscPlan_preferences.mat')
- obj.patient_dir = uigetdir([WiscPlan_preferences.patientDataPath], 'Select the patient directory');
- % end
- source_filename = fullfile(obj.patient_dir, 'batch_dose.bin');
- target_filename = fullfile(obj.patient_dir, 'beamlet_batch_files', 'beamletbatch0.bin');
- mkdir(fullfile(obj.patient_dir, 'beamlet_batch_files'));
- try
- if ispc % MATLAB movefile() super slow on windows
- % TODO confirm overwrite
- system(['move "' source_filename '" "' target_filename '"']);
- else
- movefile(source_filename, target_filename);
- end
- catch
- msgbox('Error moving the beamlet file. Please do so manually.');
- end
- Nbeamlets = read_ryan_beamlets(target_filename, 'info');
- RDXTPS_optimSetup(Nbeamlets, obj.patient_dir, obj.handles.hSVPS.Geometry);
- % run optimizer
- %---
- cd('C:\010-work\003_localGit\WiscPlan_v2\WiscPlanPhotonkV125\WiscPlanEXE')
-
- cmdline = ['.' filesep 'RDXoptimizer.exe "' fullfile(obj.patient_dir, 'optInput.txt') '"'];
- msgbox(sprintf('Start optimization\nRun this if not started automatically:\n%s', cmdline));
- if ispc
- execline = ['cmd /c ' cmdline ' &'];
- elseif isunix
- % TODO fix single quote
- execline = [cmdline];
- end
- system(execline);
- end
- %-------------------------------------------------------------------------------
- function SaveOptimResultsMenu_Callback(obj, src, evt)
- % TODO fix patient_dir system
- % if isempty(obj.patient_dir)
- load('WiscPlan_preferences.mat')
- obj.patient_dir = uigetdir([WiscPlan_preferences.patientDataPath], 'Select the patient directory');
- % obj.patient_dir = uifile('getdir', 'Select the patient directory');
- % end
- [tilde, obj.handles.hSVPS.optResults] = loadOptResults(obj.patient_dir, 'optInput.txt');
- obj.load_optResults();
- end
- %-------------------------------------------------------------------------------
- % Grozomah
- function GetFullDose_Callback(obj, src, evt)
- get_full_dose([obj.patient_dir])
- disp('Full dose calculated.')
- end
- %-------------------------------------------------------------------------------
- % Grozomah
- function RO_GoalSpec(obj, src, evt)
- disp('RO Goal spec called!')
- goal_def_UI
- end
- %-------------------------------------------------------------------------------
- % Grozomah
- function RO_Optimize(obj, src, evt)
- disp('RO Optimization called!')
-
- Pat_path = [obj.handles.hSVPS.Geometry.patient_dir];
- [Obj_file,Obj_path,indx] = uigetfile([obj.handles.hSVPS.Geometry.patient_dir '\matlab_files\*.mat'], 'Select OptGoal file' );
- path2goal = [Obj_path, Obj_file];
- [D_full, w_fin, Geometry, optGoal] = NLP_optimizer_v3(Pat_path, path2goal);
-
- % This part needs work still
- % obj.handles.hSVPS.optResults = optResults;
-
- end
-
- function RO_fullDose(obj, src, evt)
- disp('Full dose calculation called ...')
-
- Pat_path = [obj.handles.hSVPS.Geometry.patient_dir];
- [NLP_file,NLP_path,indx] = uigetfile([obj.handles.hSVPS.Geometry.patient_dir '\matlab_files\*.mat'], 'Select NLP file' );
- NLP_getFullDose(NLP_path, NLP_file);
-
- disp('Full dose calculation completed!')
-
- end
-
- %-------------------------------------------------------------------------------
- function LoadGeometryMenu_Callback(obj, src, evt)
- [filename pathname] = uifile('get', '*.mat', 'Choose Geometry file to load');
- % do nothing if cancelled
- if isscalar(filename) && filename == 0; return; end
- obj.load_geometry(fullfile(pathname, filename));
- end
- %-------------------------------------------------------------------------------
- function LoadOptresultsMenu_Callback(obj, src, evt)
- load('WiscPlan_preferences.mat')
- [FileName,PathName,FilterIndex] = uigetfile([WiscPlan_preferences.patientDataPath '\*.mat'], 'Choose OptResults file to load');
- % [filename pathname] = uifile('get', '*.mat', 'Choose OptResults file to load');
- % do nothing if cancelled
- if isscalar(FileName) && FileName == 0; return; end
- obj.load_optResults(fullfile(PathName, FileName));
-
- % % Extra dose scaling. Temporary code for comparison with Tomo plans
- % answer = inputdlg({'Dose', '% Volume'}, 'Scale final dose');
- % if ~isempty(answer)
- % % choose target
- % ROI_names = cellfun(@(c)c.name, obj.handles.hSVPS.Geometry.ROIS, 'UniformOutput', false);
- % [target_idx] = listdlg('ListString', ROI_names, ...
- % 'SelectionMode', 'single', 'Name', 'Target Selection', ...
- % 'PromptString', 'Please select the target ROI.');
- % opt_dose = prctile(obj.handles.hSVPS.optResults.dose{end}(obj.handles.hSVPS.Geometry.ROIS{target_idx}.ind), 100 - str2double(answer{2}));
- % obj.handles.hSVPS.optResults.dose{end} = obj.handles.hSVPS.optResults.dose{end} * str2double(answer{1}) / opt_dose;
- % end
- % % END OF Extra dose scaling
-
- msgbox('Load optResults successfully.')
- end
- %-------------------------------------------------------------------------------
- function ExportPinnacleMenu_Callback(obj, src, evt)
- if isempty(obj.handles.hSVPS.Geometry)
- obj.LoadGeometryMenu_Callback([], [], obj);
- end
- if isempty(obj.handles.hSVPS.optResults)
- obj.LoadOptresultsMenu_Callback([], [], obj);
- end
- RDXTPS_exportPinnGrid4Tomo(obj.handles.hSVPS.Geometry, obj.handles.hSVPS.optResults);
- end
- %-------------------------------------------------------------------------------
- function PlotDVHMenu_Callback(obj, src, evt)
- answer = inputdlg({'Enter figure number:', 'Enter line style'}, 'Choose figure');
- if isempty(answer{1})
- return;
- else
- fig_idx = str2double(answer{1});
- end
- if isempty(answer{2})
- line_style = '-';
- else
- line_style = answer{2};
- end
- figure(fig_idx); hold on;
-
- % temp solution for karthik dosimetry data
- answer = inputdlg('number of fractions');
- nfrac = str2double(answer{1});
-
- for roi_idx = 1:numel(obj.handles.hSVPS.Geometry.ROIS)
- if obj.handles.hSVPS.Geometry.ROIS{roi_idx}.visible == true % display == ON
- fprintf('%s\n', obj.handles.hSVPS.Geometry.ROIS{roi_idx}.name);
- % [dvh dosebins] = dvhist(obj.handles.hSVPS.optResults.dose{end}, obj.handles.hSVPS.Geometry.ROIS{roi_idx}.ind);
- % temp solution for karthik dosimetry data
- [dvh dosebins] = dvhist(obj.handles.hSVPS.optResults.dose{end}, ...
- obj.handles.hSVPS.Geometry, ...
- roi_idx, ...
- nfrac);
- plot(dosebins, dvh, ...
- 'Color', obj.handles.hSVPS.Geometry.ROIS{roi_idx}.color, ...
- 'LineStyle', line_style, ...
- 'DisplayName', obj.handles.hSVPS.Geometry.ROIS{roi_idx}.name);
- end
- end
- set(gca, 'XMinorTick', 'on', 'YMinorTick', 'on');
- grid(gca, 'on');
- box(gca, 'on');
- legend('show');
- xlabel('Dose (Gy)');
- ylabel('% volume');
- hold off;
- end
-
- %-------------------------------------------------------------------------------
- function ResampleGeometry_Callback(obj, src, evt)
- %% --- make the figure prompt for number of angles and beamlets
-
-
- % call the resample function
- resample_geometry(obj.handles.hSVPS.Geometry)
- disp('Resampled geometry created!')
-
- end
- %-------------------------------------------------------------------------------
- function DoseModeDropdown_Callback(obj, src, evt)
- str = get(obj.handles.hDoseModeDropdown, 'String');
- obj.handles.hSVPS.dosedisp.mode = str{get(obj.handles.hDoseModeDropdown, 'Value')};
- end
- %-------------------------------------------------------------------------------
- function TCSShow_Callback(obj, src, evt)
- obj.handles.hSVPS.TCSVisible = ...
- get(src, 'Value') == get(src, 'Max');
- end
- %-------------------------------------------------------------------------------
- function SaveAsGeometryMenu_Callback(obj, src, evt)
- [filename pathname] = uifile('put', '*.mat', 'Save Geometry as...');
- % do nothing if cancelled
- if isscalar(filename) && filename == 0; return; end
-
- Geometry = obj.handles.hSVPS.Geometry;
- for i = 1:numel(Geometry.ROIS)
- if isfield(Geometry.ROIS{i}, 'BW')
- Geometry.ROIS{i}.BW = [];
- end
- end
- save(fullfile(pathname, filename), 'Geometry');
- end
- %-------------------------------------------------------------------------------
- function SaveAsOptResultsMenu_Callback(obj, src, evt)
- [filename pathname] = uifile('put', '*.mat', 'Save OptResults as...');
- % do nothing if cancelled
- if isscalar(filename) && filename == 0; return; end
-
- optResults = obj.handles.hSVPS.optResults;
- save(fullfile(pathname, filename), 'optResults');
- end
- %-------------------------------------------------------------------------------
- end % methods
- end
|