Skip to content

Commit 62fde50

Browse files
authored
Merge branch 'dev' into dev
2 parents 9821c82 + ba49be4 commit 62fde50

File tree

8 files changed

+134
-88
lines changed

8 files changed

+134
-88
lines changed

matRad/doseCalc/+DoseEngines/matRad_PhotonPencilBeamSVDEngine.m

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
enableDijSampling = true;
4343
dijSampling; %struct with lateral dij sampling parameters
44+
ignoreInvalidValues = false; %ignore negative, infinite or NaN values in bixel calculation
4445
end
4546

4647
%Calculation variables
@@ -302,7 +303,8 @@ function setDefaults(this)
302303
currRay.radDepths,...
303304
currRay.geoDepths,...
304305
currRay.isoLatDists(:,1),...
305-
currRay.isoLatDists(:,2));
306+
currRay.isoLatDists(:,2),...
307+
this.ignoreInvalidValues);
306308

307309
% sample dose only for bixel based dose calculation
308310
if this.enableDijSampling && ~this.isFieldBasedDoseCalc
@@ -536,7 +538,7 @@ function setDefaults(this)
536538
end
537539

538540
function bixelDose = calcSingleBixel(SAD,m,betas,interpKernels,...
539-
radDepths,geoDists,isoLatDistsX,isoLatDistsZ)
541+
radDepths,geoDists,isoLatDistsX,isoLatDistsZ,ignoreInvalidValues)
540542
% matRad photon dose calculation for an individual bixel
541543
% This is defined as a static function so it can also be
542544
% called individually for certain applications without having
@@ -568,6 +570,10 @@ function setDefaults(this)
568570
% [1] http://www.ncbi.nlm.nih.gov/pubmed/8497215
569571
%
570572

573+
if nargin < 9
574+
ignoreInvalidValues = false;
575+
end
576+
571577
% Compute depth dose components according to [1, eq. 17]
572578
doseComponent = betas./(betas-m) .* (exp(-m*radDepths) - exp(-betas.*radDepths));
573579

@@ -587,9 +593,11 @@ function setDefaults(this)
587593
% check if we have valid dose values and adjust numerical instabilities
588594
% from fft convolution
589595
bixelDose(bixelDose < 0 & bixelDose > -1e-14) = 0;
590-
if any(isnan(bixelDose)) || any(bixelDose<0)
596+
if ~ignoreInvalidValues && any(isnan(bixelDose) | bixelDose<0)
591597
matRad_cfg = MatRad_Config.instance();
592-
matRad_cfg.dispError('Invalid numerical values in photon dose calculation.');
598+
matRad_cfg.dispError([ ...
599+
'Invalid numerical values in photon dose calculation.\n' ...
600+
'Check your kernel or set ignoreInvalidValues to true.']);
593601
end
594602
end
595603

matRad/gui/matRad_MainGUI.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,10 +482,10 @@ function uipushtool_screenshot_ClickedCallback(this,hObject, eventdata)
482482
% eventdata reserved - to be defined in a future version of MATLAB
483483
% handles structure with handles and user data (see GUIDATA)
484484

485-
486-
tmpFig = figure('position',[100 100 700 600],'Visible','off','name','Current View');
485+
matRad_cfg = MatRad_Config.instance();
486+
tmpFig = figure('position',[100 100 700 600],'Visible','off','name','Current View','Color',matRad_cfg.gui.backgroundColor);
487487
cBarHandle = this.ViewingWidget.cBarHandle; %findobj(handles.figure1,'Type','colorbar');
488-
if ~isempty(cBarHandle)
488+
if ~isempty(cBarHandle) && ishghandle(cBarHandle)
489489
new_handle = copyobj([this.ViewingWidget.handles.axesFig cBarHandle],tmpFig);
490490
else
491491
new_handle = copyobj(this.ViewingWidget.handles.axesFig,tmpFig);

matRad/gui/widgets/matRad_PlanWidget.m

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -843,10 +843,19 @@
843843
end
844844

845845
set(handles.editFraction,'String',num2str(pln.numOfFractions));
846-
847-
846+
847+
if ~isfield(pln,'bioParam')
848+
pln.bioParam = matRad_bioModel(pln.radiationMode,'physicalDose','none');
849+
end
850+
848851
contentPopUpQuantityOpt = get(handles.popMenuQuantityOpt,'String');
852+
849853
ix = find(strcmp(pln.bioParam.quantityOpt,contentPopUpQuantityOpt));
854+
855+
if isempty(ix)
856+
ix = 1;
857+
end
858+
850859
set(handles.popMenuQuantityOpt,'Value',ix);
851860

852861
contentPopUpBioModel = get(handles.popMenuBioModel,'String');
@@ -876,7 +885,7 @@
876885
end
877886

878887
if ~isfield(pln,'propDoseCalc') || ~isfield(pln.propDoseCalc,'doseGrid')
879-
pln.propDoseCalc.doseGrid.resolution = matRad_cfg.defaults.propDoseCalc.resolution;
888+
pln.propDoseCalc.doseGrid.resolution = matRad_cfg.defaults.propDoseCalc.doseGrid.resolution;
880889
end
881890

882891
set(handles.editDoseX,'String',num2str(pln.propDoseCalc.doseGrid.resolution.x));

matRad/gui/widgets/matRad_ViewingWidget.m

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ function notifyPlotUpdated(obj)
185185
function set.typeOfPlot(this,value)
186186
this.typeOfPlot=value;
187187
evt = matRad_WorkspaceChangedEvent('image_display');
188+
cla(this.handles.axesFig,'reset');
188189
this.update(evt);
189190
end
190191

@@ -699,10 +700,12 @@ function UpdatePlot(this)
699700
res = [ratios(1) ratios(2)]./max([ratios(1) ratios(2)]);
700701
set(handles.axesFig,'DataAspectRatio',[res 1])
701702
end
703+
704+
axis(handles.axesFig,'tight');
702705

703706

704707
%% profile plot
705-
if this.typeOfPlot == 2 && exist('Result','var')
708+
if this.typeOfPlot == 2 && exist('result','var')
706709
% set SAD
707710
fileName = [pln.radiationMode '_' pln.machine];
708711
try
@@ -714,9 +717,16 @@ function UpdatePlot(this)
714717

715718
% clear view and initialize some values
716719
cla(handles.axesFig,'reset')
717-
set(handles.axesFig,'YDir','normal');
718-
ylabel('{\color{black}dose [Gy]}')
719-
cColor={'black','green','magenta','cyan','yellow','red','blue'};
720+
set(handles.axesFig,'YDir','normal','Color',matRad_cfg.gui.elementColor,'XColor',matRad_cfg.gui.textColor);
721+
hold(handles.axesFig,'on');
722+
tmpColor = rgb2hsv(matRad_cfg.gui.elementColor);
723+
if tmpColor(3) > 0.5
724+
tmpColor = 'black';
725+
else
726+
tmpColor = 'white';
727+
end
728+
ylabel(['{\color{' tmpColor '}dose [Gy]}']);
729+
cColor={tmpColor,'green','magenta','cyan','yellow','red','blue'};
720730

721731
% Rotate the system into the beam.
722732
% passive rotation & row vector multiplication & inverted rotation requires triple matrix transpose
@@ -735,15 +745,16 @@ function UpdatePlot(this)
735745

736746
% perform raytracing on the central axis of the selected beam, use unit
737747
% electron density for plotting against the geometrical depth
738-
[~,l,rho,~,ix] = matRad_siddonRayTracer(pln.propStf.isoCenter(this.selectedBeam,:),ct.resolution,rotSourcePointBEV,rotTargetPointBEV,{0*ct.cubeHU{1}+1});
748+
cubeIsoCenter = matRad_world2cubeCoords(pln.propStf.isoCenter(this.selectedBeam,:),ct);
749+
[~,l,rho,~,ix] = matRad_siddonRayTracer(cubeIsoCenter,ct.resolution,rotSourcePointBEV,rotTargetPointBEV,{0*ct.cubeHU{1}+1});
739750
d = [0 l .* rho{1}];
740751
% Calculate accumulated d sum.
741752
vX = cumsum(d(1:end-1));
742753

743754
% plot physical dose
744755
%Content =this.SelectedDisplayOption; %get(this.popupDisplayOption,'String');
745756
SelectedCube = this.SelectedDisplayOption; %Content{get(this.popupDisplayOption,'Value')};
746-
if sum(strcmp(SelectedCube,{'physicalDose','effect','RBExDose','alpha','beta','RBE'})) > 0
757+
if sum(strcmp(SelectedCube,{'physicalDose','effect','RBExD','alpha','beta','RBE','BED'})) > 0
747758
Suffix = '';
748759
else
749760
Idx = find(SelectedCube == '_');
@@ -758,6 +769,8 @@ function UpdatePlot(this)
758769

759770
% plot counter
760771
Cnt=2;
772+
773+
rightAx = [];
761774

762775
if isfield(result,['RBE' Suffix])
763776

@@ -767,12 +780,12 @@ function UpdatePlot(this)
767780
%this.DispInfo{2,2}=0;
768781

769782
% generate two lines for ylabel
770-
StringYLabel1 = '\fontsize{8}{\color{red}RBE x dose [Gy(RBE)] \color{black}dose [Gy] ';
783+
StringYLabel1 = ['\fontsize{8}{\color{red}RBE x dose [Gy(RBE)] \color{' tmpColor '}dose [Gy] '];
771784
StringYLabel2 = '';
772785
for i=1:1:size(this.DispInfo,1)
773786
if this.DispInfo{i,2} && sum(strcmp(this.DispInfo{i,1},{['effect' Suffix],['alpha' Suffix],['beta' Suffix]})) > 0
774787
%physicalDose is already plotted and RBExD vs RBE is plotted later with plotyy
775-
if ~strcmp(this.DispInfo{i,1},['RBExDose' Suffix]) &&...
788+
if ~strcmp(this.DispInfo{i,1},['RBExD' Suffix]) &&...
776789
~strcmp(this.DispInfo{i,1},['RBE' Suffix]) && ...
777790
~strcmp(this.DispInfo{i,1},['physicalDose' Suffix])
778791

@@ -786,25 +799,28 @@ function UpdatePlot(this)
786799
end
787800
StringYLabel2 = [StringYLabel2 '}'];
788801
% always plot RBExD against RBE
789-
mRBExDose = result.(['RBExDose' Suffix]);
802+
mRBExDose = result.(['RBExD' Suffix]);
790803
vBED = mRBExDose(ix);
791804
mRBE = result.(['RBE' Suffix]);
792805
vRBE = mRBE(ix);
793806

794807
% plot biological dose against RBE
795-
[ax, PlotHandles{Cnt,1}, PlotHandles{Cnt+1,1}]=plotyy(handles.axesFig,vX,vBED,vX,vRBE,'plot');hold(handles.axesFig,'on');
796-
PlotHandles{Cnt,2}='RBExDose';
797-
PlotHandles{Cnt+1,2}='RBE';
808+
[ax, PlotHandles{Cnt,1}, PlotHandles{Cnt+1,1}]=plotyy(handles.axesFig,vX,vBED,vX,vRBE,'plot');
809+
hold(ax(2),'on');
810+
PlotHandles{Cnt,2}='RBExD';
811+
PlotHandles{Cnt+1,2}='RBE';
798812

799813
% set plotyy properties
800-
set(get(ax(2),'Ylabel'),'String','RBE [a.u.]','FontSize',8);
814+
set(get(ax(2),'Ylabel'),'String','RBE [1]','FontSize',defaultFontSize);
815+
801816
ylabel({StringYLabel1;StringYLabel2})
802817
set(PlotHandles{Cnt,1},'Linewidth',4,'color','r');
803818
set(PlotHandles{Cnt+1,1},'Linewidth',3,'color','b');
804819
set(ax(1),'ycolor','r')
805820
set(ax(2),'ycolor','b')
806-
set(ax,'FontSize',8);
821+
set(ax,'FontSize',defaultFontSize);
807822
Cnt=Cnt+2;
823+
rightAx = ax(2);
808824
end
809825

810826
% asses target coordinates
@@ -819,9 +835,9 @@ function UpdatePlot(this)
819835
end
820836
end
821837

822-
str = sprintf('profile plot - central axis of %d beam gantry angle %d? couch angle %d?',...
838+
str = sprintf('profile plot - central axis of %d beam, gantry angle %d°, couch angle %d°',...
823839
this.selectedBeam ,pln.propStf.gantryAngles(this.selectedBeam),pln.propStf.couchAngles(this.selectedBeam));
824-
h_title = title(handles.axesFig,str,'FontSize',defaultFontSize);
840+
h_title = title(handles.axesFig,str,'FontSize',defaultFontSize,'Color',matRad_cfg.gui.highlightColor);
825841
pos = get(h_title,'Position');
826842
set(h_title,'Position',[pos(1)-40 pos(2) pos(3)])
827843

@@ -836,18 +852,21 @@ function UpdatePlot(this)
836852
if ~isempty(WEPL_Target_Entry) && ~isempty(WEPL_Target_Exit)
837853
hold(handles.axesFig,'on');
838854
PlotHandles{Cnt,1} = ...
839-
plot([WEPL_Target_Entry WEPL_Target_Entry],get(handles.axesFig,'YLim'),'--','Linewidth',3,'color','k');hold(handles.axesFig,'on');
840-
plot([WEPL_Target_Exit WEPL_Target_Exit],get(handles.axesFig,'YLim'),'--','Linewidth',3,'color','k');hold(handles.axesFig,'on');
855+
plot([WEPL_Target_Entry WEPL_Target_Entry],get(handles.axesFig,'YLim'),'--','Linewidth',3,'color',matRad_cfg.gui.highlightColor);hold(handles.axesFig,'on');
856+
plot([WEPL_Target_Exit WEPL_Target_Exit],get(handles.axesFig,'YLim'),'--','Linewidth',3,'color',matRad_cfg.gui.highlightColor);hold(handles.axesFig,'on');
841857

842858
else
843859
PlotHandles{Cnt,1} =[];
844860
end
845861

846862
Lines = PlotHandles(~cellfun(@isempty,PlotHandles(:,1)),1);
847863
Labels = PlotHandles(~cellfun(@isempty,PlotHandles(:,1)),2);
848-
l=legend(handles.axesFig,[Lines{:}],Labels{:});
849-
xlabel('radiological depth [mm]','FontSize',8);
864+
l=legend(handles.axesFig,[Lines{:}],Labels{:},'TextColor',matRad_cfg.gui.textColor,'FontSize',defaultFontSize,'Color',matRad_cfg.gui.backgroundColor,'EdgeColor',matRad_cfg.gui.textColor);
865+
xlabel('radiological depth [mm]','FontSize',matRad_cfg.gui.fontSize,'Color',matRad_cfg.gui.textColor);
850866
grid on, grid minor
867+
if ~isempty(rightAx)
868+
set(rightAx,'XLim',get(handles.axesFig,'XLim'));
869+
end
851870
else
852871
% create legend for the visible VOI
853872
if this.typeOfPlot==2 || ~this.plotContour || isempty([this.AxesHandlesVOI{:}]) %isempty(find(this.VOIPlotFlag, 1))
@@ -871,8 +890,6 @@ function UpdatePlot(this)
871890
end
872891
this.legendHandle=l;
873892

874-
%zoom(handles.figure1,'reset');
875-
axis(handles.axesFig,'tight');
876893

877894
% if this.rememberCurrAxes
878895
% axis(handles.axesFig);%currAxes);
@@ -918,8 +935,8 @@ function UpdatePlot(this)
918935

919936
%if function is called for the first time then set display parameters
920937
if isempty(this.dispWindow{2,2}) || ~this.lockColorSettings
921-
this.dispWindow{2,1} = [min(dose(:)) max(dose(:))]; % set default dose range
922-
this.dispWindow{2,2} = [min(dose(:)) max(dose(:))]; % set min max values
938+
this.dispWindow{2,1} = [min(dose(:)) max(dose(:))*1.001]; % set default dose range
939+
this.dispWindow{2,2} = [min(dose(:)) max(dose(:))*1.001]; % set min max values
923940
end
924941

925942
minMaxRange = this.dispWindow{2,1};
@@ -1268,22 +1285,36 @@ function updateDisplaySelection(this,visSelection)
12681285
else
12691286
%second dimension indicates if it should be plotted
12701287
this.DispInfo{i,2} = true;
1271-
% determine units
1288+
% determine units (third dimension) and left or
1289+
% right axis (fourth dimension, ignored so far
12721290
if strfind(this.DispInfo{i,1},'physicalDose')
1273-
this.DispInfo{i,3} = '[Gy]';
1291+
this.DispInfo{i,3} = 'Gy';
1292+
this.DispInfo{i,4} = 'left';
12741293
elseif strfind(this.DispInfo{i,1},'alpha')
1275-
this.DispInfo{i,3} = '[Gy^{-1}]';
1294+
this.DispInfo{i,3} = 'Gy^{-1}';
1295+
this.DispInfo{i,4} = 'left';
12761296
elseif strfind(this.DispInfo{i,1},'beta')
1277-
this.DispInfo{i,3} = '[Gy^{-2}]';
1297+
this.DispInfo{i,3} = 'Gy^{-2}';
1298+
this.DispInfo{i,4} = 'left';
12781299
elseif strfind(this.DispInfo{i,1},'RBExD')
1279-
this.DispInfo{i,3} = '[Gy(RBE)]';
1300+
this.DispInfo{i,3} = 'Gy(RBE)';
1301+
this.DispInfo{i,4} = 'left';
12801302
elseif strfind(this.DispInfo{i,1},'LET')
1281-
this.DispInfo{i,3} = '[keV/um]';
1303+
this.DispInfo{i,3} = 'keV/um';
1304+
this.DispInfo{i,4} = 'left';
1305+
elseif strfind(this.DispInfo{i,1},'effect')
1306+
this.DispInfo{i,3} = '1';
1307+
this.DispInfo{i,4} = 'right';
1308+
elseif strfind(this.DispInfo{i,1},'RBE')
1309+
this.DispInfo{i,3} = '1';
1310+
this.DispInfo{i,4} = 'right';
1311+
elseif strfind(this.DispInfo{i,1},'BED')
1312+
this.DispInfo{i,3} = 'Gy';
1313+
this.DispInfo{i,4} = 'left';
12821314
else
1283-
this.DispInfo{i,3} = '[a.u.]';
1315+
this.DispInfo{i,3} = 'a.u.';
1316+
this.DispInfo{i,4} = 'right';
12841317
end
1285-
this.DispInfo{i,4} = []; % optional for the future: color range for plotting
1286-
this.DispInfo{i,5} = []; % optional for the future: min max values
12871318
end
12881319
end
12891320

0 commit comments

Comments
 (0)