Skip to content

Commit 57817d7

Browse files
SimonaFawahlnahmadnish
authored
Plot Slice function: title implemented (#854)
* Plot Slice function: title implemented * Plot Slice function bug fixed * Some changes from branch update * Fix title usage and some plotSlice cleanup --------- Co-authored-by: Niklas Wahl <[email protected]> Co-authored-by: Ahmad Neishabouri <[email protected]>
1 parent c8c5f5f commit 57817d7

File tree

2 files changed

+90
-49
lines changed

2 files changed

+90
-49
lines changed

matRad/util/matRad_plotSlice.m

Lines changed: 73 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
defaultDose = [];
4949
defaultCst = [];
5050
defaultSlice = floor(min(ct.cubeDim)./2);
51-
defaultAxesHandle = gca;
51+
defaultAxesHandle = [];
5252
defaultCubeIdx = 1;
5353
defaultPlane = 1;
5454
defaultDoseWindow = [];
@@ -61,10 +61,11 @@
6161
defaultBoolPlotLegend = false;
6262
defaultColorBarLabel = [];
6363
defaultShowCt = true;
64+
defaultTitle = [];
6465

6566
isDose = @(x) isnumeric(x) && all(size(x) == ct.cubeDim);
6667
isSlice = @(x) x>=1 && x<=max(ct.cubeDim) && floor(x)==x;
67-
isAxes = @(x) strcmp(get(gca, 'type'), 'axes');
68+
isAxes = @(x) strcmp(get(x, 'type'), 'axes') || isempty(x);
6869
isCubeIdx = @(x) isscalar(x);
6970
isPlane = @(x) isscalar(x) && (sum(x==[1, 2, 3])==1);
7071
isDoseWindow = @(x) (length(x) == 2 && isvector(x));
@@ -77,55 +78,81 @@
7778
isBoolPlotLegend = @(x) x==0 || x ==1;
7879
isColorBarLabel = @(x) isstring(x) || ischar(x) || isempty(x);
7980
isShowCt = @(x) isscalar(x) && (x==0) || (x==1);
81+
isTitle = @(x) isstring(x) || ischar(x) || isempty(x);
8082

8183
p = inputParser;
8284
p.KeepUnmatched = true;
83-
addRequired(p, 'ct')
84-
85-
addParameter(p, 'dose', defaultDose, isDose)
86-
addParameter(p, 'cst', defaultCst)
87-
addParameter(p, 'slice', defaultSlice, isSlice)
88-
addParameter(p, 'axesHandle', defaultAxesHandle, isAxes)
89-
addParameter(p, 'cubeIdx', defaultCubeIdx, isCubeIdx)
90-
addParameter(p, 'plane', defaultPlane, isPlane)
91-
addParameter(p, 'doseWindow', defaultDoseWindow, isDoseWindow)
92-
addParameter(p, 'thresh', defaultThresh, isThresh)
93-
addParameter(p, 'alpha', defaultAlpha, isAlpha)
94-
addParameter(p, 'doseColorMap', defaultDoseColorMap, isDoseColorMap)
95-
addParameter(p, 'doseIsoLevels', defaultDoseIsoLevels, isDoseIsoLevels)
96-
addParameter(p, 'voiSelection', defaultVOIselection, isVOIselection)
97-
addParameter(p, 'contourColorMap', defaultContourColorMap, isContourColorMap)
98-
addParameter(p, 'boolPlotLegend', defaultBoolPlotLegend, isBoolPlotLegend)
99-
addParameter(p, 'colorBarLabel', defaultColorBarLabel, isColorBarLabel)
100-
addParameter(p, 'showCt', defaultShowCt, isShowCt)
101-
102-
parse(p, ct, varargin{:});
85+
86+
addRequired(p, 'ct');
87+
88+
addParameter(p, 'dose', defaultDose, isDose);
89+
addParameter(p, 'cst', defaultCst);
90+
addParameter(p, 'slice', defaultSlice, isSlice);
91+
addParameter(p, 'axesHandle', defaultAxesHandle, isAxes);
92+
addParameter(p, 'cubeIdx', defaultCubeIdx, isCubeIdx);
93+
addParameter(p, 'plane', defaultPlane, isPlane);
94+
addParameter(p, 'doseWindow', defaultDoseWindow, isDoseWindow);
95+
addParameter(p, 'thresh', defaultThresh, isThresh);
96+
addParameter(p, 'alpha', defaultAlpha, isAlpha);
97+
addParameter(p, 'doseColorMap', defaultDoseColorMap, isDoseColorMap);
98+
addParameter(p, 'doseIsoLevels', defaultDoseIsoLevels, isDoseIsoLevels);
99+
addParameter(p, 'voiSelection', defaultVOIselection, isVOIselection);
100+
addParameter(p, 'contourColorMap', defaultContourColorMap, isContourColorMap);
101+
addParameter(p, 'boolPlotLegend', defaultBoolPlotLegend, isBoolPlotLegend);
102+
addParameter(p, 'colorBarLabel', defaultColorBarLabel, isColorBarLabel);
103+
addParameter(p, 'showCt', defaultShowCt, isShowCt);
104+
addParameter(p, 'title', defaultTitle, isTitle);
105+
106+
p.parse(ct, varargin{:});
103107

104108
%% Unmatched properties
105109
% General properties
106-
lineFieldNames = fieldnames(set(line));
107-
textFieldNames = fieldnames(set(text));
110+
% This is a hack with an invisible figure to obtain the properties
111+
hTmpFig = figure('Visible','off','HandleVisibility','off');
112+
hTmpAx = axes(hTmpFig);
113+
axesFieldNames = fieldnames(set(hTmpAx));
114+
lineFieldNames = fieldnames(set(line(hTmpAx)));
115+
textFieldNames = fieldnames(set(text(hTmpAx)));
116+
delete(hTmpAx);
117+
close(hTmpFig);
118+
108119
% Filter line properties from Unmatched
109120
unmParamNames = fieldnames(p.Unmatched);
110121
lineFields = unmParamNames(ismember(unmParamNames, lineFieldNames));
111122
lineValues = struct2cell(p.Unmatched);
112123
lineValues = lineValues(ismember(unmParamNames, lineFieldNames));
113124
lineVarargin = reshape([lineFields, lineValues]', 1, []);
125+
114126
% Filter text properties from Unmatched
115127
textFields = unmParamNames(ismember(unmParamNames, textFieldNames));
116128
textValues = struct2cell(p.Unmatched);
117129
textValues = textValues(ismember(unmParamNames, textFieldNames));
118130
textVarargin = reshape([textFields, textValues]', 1, []);
131+
%
132+
axesFields = unmParamNames(ismember(unmParamNames, axesFieldNames));
133+
axesValues = struct2cell(p.Unmatched);
134+
axesValues = axesValues(ismember(unmParamNames, axesFieldNames));
135+
axesVarargin = reshape([axesFields, axesValues]', 1, []);
136+
119137

120138
%% Plot ct slice
121139
matRad_cfg = MatRad_Config.instance();
122140

141+
if isempty(p.Results.axesHandle)
142+
axesHandle = axes(figure());
143+
else
144+
axesHandle = p.Results.axesHandle;
145+
end
146+
123147
% Flip axes direction
124-
set(p.Results.axesHandle,'YDir','Reverse');
148+
set(axesHandle,'XTick',[],'YTick',[]);
149+
set(axesHandle,'YDir','Reverse');
125150
% plot ct slice
126151
if p.Results.showCt
127-
hCt = matRad_plotCtSlice(p.Results.axesHandle,p.Results.ct.cubeHU,p.Results.cubeIdx,p.Results.plane,p.Results.slice, [], []);
152+
hCt = matRad_plotCtSlice(axesHandle,p.Results.ct.cubeHU,p.Results.cubeIdx,p.Results.plane,p.Results.slice, [], []);
128153
end
154+
axis(axesHandle, 'off');
155+
129156
hold on;
130157

131158
%% Plot dose
@@ -134,17 +161,17 @@
134161
if ~isempty(p.Results.doseWindow) && p.Results.doseWindow(2) - p.Results.doseWindow(1) <= 0
135162
doseWindow = p.Results.doseWindow;
136163
end
137-
[hDose,doseColorMap,doseWindow] = matRad_plotDoseSlice(p.Results.axesHandle, p.Results.dose, p.Results.plane, p.Results.slice, p.Results.thresh, p.Results.alpha, p.Results.doseColorMap, doseWindow);
164+
[hDose,doseColorMap,doseWindow] = matRad_plotDoseSlice(axesHandle, p.Results.dose, p.Results.plane, p.Results.slice, p.Results.thresh, p.Results.alpha, p.Results.doseColorMap, doseWindow);
138165
hold on;
139166

140167
%% Plot iso dose lines
141168
hIsoDose = [];
142169
if ~isempty(p.Results.doseIsoLevels)
143-
hIsoDose = matRad_plotIsoDoseLines(p.Results.axesHandle,p.Results.dose,[],p.Results.doseIsoLevels,false,p.Results.plane,p.Results.slice,p.Results.doseColorMap,p.Results.doseWindow, lineVarargin{:});
170+
hIsoDose = matRad_plotIsoDoseLines(axesHandle,p.Results.dose,[],p.Results.doseIsoLevels,false,p.Results.plane,p.Results.slice,p.Results.doseColorMap,p.Results.doseWindow, lineVarargin{:});
144171
end
145172

146173
%% Set Colorbar
147-
hCMap = matRad_plotColorbar(p.Results.axesHandle,doseColorMap,doseWindow,'Location','EastOutside');
174+
hCMap = matRad_plotColorbar(axesHandle,doseColorMap,doseWindow,'Location','EastOutside');
148175
set(hCMap,'Color',matRad_cfg.gui.textColor);
149176
if ~isempty(p.Results.colorBarLabel)
150177
set(get(hCMap,'YLabel'),'String', p.Results.colorBarLabel,'FontSize',matRad_cfg.gui.fontSize);
@@ -154,7 +181,7 @@
154181
%% Plot VOI contours & Legend
155182

156183
if ~isempty(p.Results.cst)
157-
[hContour,~] = matRad_plotVoiContourSlice(p.Results.axesHandle, p.Results.cst, p.Results.ct, p.Results.cubeIdx, p.Results.voiSelection, p.Results.plane, p.Results.slice, p.Results.contourColorMap, lineVarargin{:});
184+
[hContour,~] = matRad_plotVoiContourSlice(axesHandle, p.Results.cst, p.Results.ct, p.Results.cubeIdx, p.Results.voiSelection, p.Results.plane, p.Results.slice, p.Results.contourColorMap, lineVarargin{:});
158185

159186
if p.Results.boolPlotLegend
160187
visibleOnSlice = (~cellfun(@isempty,hContour));
@@ -163,7 +190,7 @@
163190
if ~isempty(p.Results.voiSelection)
164191
voiSelection = visibleOnSlice(find(p.Results.voiSelection));
165192
end
166-
hLegend = legend(p.Results.axesHandle,[hContourTmp{:}],[p.Results.cst(voiSelection,2)],'AutoUpdate','off','TextColor',matRad_cfg.gui.textColor);
193+
hLegend = legend(axesHandle,[hContourTmp{:}],[p.Results.cst(voiSelection,2)],'AutoUpdate','off','TextColor',matRad_cfg.gui.textColor);
167194
set(hLegend,'Box','On');
168195
set(hLegend,'TextColor',matRad_cfg.gui.textColor);
169196
if ~isempty(textVarargin)
@@ -177,34 +204,39 @@
177204
end
178205

179206
%% Adjust axes
180-
axis(p.Results.axesHandle,'tight');
181-
set(p.Results.axesHandle,'xtick',[],'ytick',[]);
182-
colormap(p.Results.axesHandle,p.Results.doseColorMap);
207+
axis(axesHandle,'tight');
208+
set(axesHandle,'xtick',[],'ytick',[]);
209+
colormap(axesHandle,p.Results.doseColorMap);
183210
fontSize = [];
184211
if isfield(p.Unmatched, 'FontSize')
185212
fontSize = p.Unmatched.FontSize;
186213
end
187-
matRad_plotAxisLabels(p.Results.axesHandle,p.Results.ct,p.Results.plane,p.Results.slice, fontSize, [])
214+
matRad_plotAxisLabels(axesHandle,p.Results.ct,p.Results.plane,p.Results.slice, fontSize, [])
188215

189216
% Set axis ratio.
190217
ratios = [1/p.Results.ct.resolution.x 1/p.Results.ct.resolution.y 1/p.Results.ct.resolution.z];
191218

192-
set(p.Results.axesHandle,'DataAspectRatioMode','manual');
219+
set(axesHandle,'DataAspectRatioMode','manual');
193220
if p.Results.plane == 1
194221
res = [ratios(3) ratios(2)]./max([ratios(3) ratios(2)]);
195-
set(p.Results.axesHandle,'DataAspectRatio',[res 1])
222+
set(axesHandle,'DataAspectRatio',[res 1])
196223
elseif p.Results.plane == 2 % sagittal plane
197224
res = [ratios(3) ratios(1)]./max([ratios(3) ratios(1)]);
198-
set(p.Results.axesHandle,'DataAspectRatio',[res 1])
225+
set(axesHandle,'DataAspectRatio',[res 1])
199226
elseif p.Results.plane == 3 % Axial plane
200227
res = [ratios(2) ratios(1)]./max([ratios(2) ratios(1)]);
201-
set(p.Results.axesHandle,'DataAspectRatio',[res 1])
228+
set(axesHandle,'DataAspectRatio',[res 1])
229+
end
230+
231+
%% Title
232+
if ~isempty(p.Results.title)
233+
title(axesHandle,p.Results.title);
202234
end
203235

204236
%% Set text properties
205237
if ~isempty(textVarargin)
206-
set(p.Results.axesHandle, textVarargin{:})
207-
set(p.Results.axesHandle.Title, textVarargin{:})
238+
set(axesHandle, textVarargin{:})
239+
set(axesHandle.Title, textVarargin{:})
208240
end
209241

210242
if ~exist('hCMap', 'var')

test/util/test_plotSlice.m

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
function test_plot_ct_only
88

99
load BOXPHANTOM.mat
10-
figure()
1110
[hCMap,hDose,hCt,hContour,hIsoDose] = matRad_plotSlice(ct);
1211
assertTrue(isempty(hCMap));
1312
assertTrue(isempty(hDose));
@@ -17,9 +16,9 @@
1716
end
1817
assertTrue(isempty(hContour));
1918
assertTrue(isempty(hIsoDose));
19+
close(gcf);
2020

2121
load PROSTATE.mat
22-
figure()
2322
[hCMap,hDose,hCt,hContour,hIsoDose] = matRad_plotSlice(ct, 'slice', 91, 'cst', cst);
2423
assertTrue(isempty(hCMap));
2524
assertTrue(isempty(hDose));
@@ -29,12 +28,11 @@
2928
end
3029
assertTrue(isa(hContour, 'cell'));
3130
assertTrue(isempty(hIsoDose));
32-
31+
close(gcf);
3332

3433
function test_plot_dose_slice
3534

3635
load protons_testData.mat
37-
figure();
3836
[hCMap,hDose,hCt,hContour,hIsoDose] = matRad_plotSlice(ct, 'dose', resultGUI.physicalDose);
3937
assertFalse(isempty(hCt));
4038
assertTrue(isempty(hContour));
@@ -44,9 +42,9 @@
4442
assertTrue(isa(hDose, 'matlab.graphics.primitive.Image'));
4543
assertTrue(isa(hCt, 'matlab.graphics.primitive.Image'))
4644
end
45+
close(gcf);
4746

4847
load helium_testData.mat
49-
figure();
5048
[hCMap,hDose,hCt,hContour,hIsoDose] = matRad_plotSlice(ct, 'dose', resultGUI.physicalDose);
5149
assertFalse(isempty(hCt));
5250
assertTrue(isempty(hContour));
@@ -56,9 +54,9 @@
5654
assertTrue(isa(hDose, 'matlab.graphics.primitive.Image'));
5755
assertTrue(isa(hCt, 'matlab.graphics.primitive.Image'))
5856
end
57+
close(gcf);
5958

6059
load carbon_testData.mat
61-
figure();
6260
[hCMap,hDose,hCt,hContour,hIsoDose] = matRad_plotSlice(ct, 'dose', resultGUI.physicalDose);
6361
assertFalse(isempty(hCt));
6462
assertTrue(isempty(hContour));
@@ -68,9 +66,9 @@
6866
assertTrue(isa(hDose, 'matlab.graphics.primitive.Image'));
6967
assertTrue(isa(hCt, 'matlab.graphics.primitive.Image'))
7068
end
69+
close(gcf);
7170

7271
load photons_testData.mat
73-
figure();
7472
[hCMap,hDose,hCt,hContour,hIsoDose] = matRad_plotSlice(ct, 'dose', resultGUI.physicalDose, 'plane', 3);
7573
assertFalse(isempty(hCt));
7674
assertTrue(isempty(hContour));
@@ -80,11 +78,12 @@
8078
assertTrue(isa(hDose, 'matlab.graphics.primitive.Image'));
8179
assertTrue(isa(hCt, 'matlab.graphics.primitive.Image'))
8280
end
81+
close(gcf);
8382

8483
function test_optional_input
8584

8685
load photons_testData.mat
87-
figure();
86+
hF = figure();
8887
doseCube = resultGUI.physicalDose;
8988
boolVOIselection = ones(1, size(cst, 1));
9089
[hCMap,hDose,hCt,hContour,hIsoDose] = matRad_plotSlice(ct, ...
@@ -104,3 +103,13 @@
104103
if ~moxunit_util_platform_is_octave
105104
assertTrue(isa(hDose, 'matlab.graphics.primitive.Image'));
106105
end
106+
close(hF);
107+
108+
function test_title_input
109+
load photons_testData.mat
110+
hF = figure();
111+
hA = axes(hF);
112+
tString = 'Hello';
113+
matRad_plotSlice(ct,'title','Hello','axesHandle',hA);
114+
assertTrue(isequal('Hello',get(get(hA,'Title'),'String')));
115+
close(hF);

0 commit comments

Comments
 (0)