function resultGUI = matRad_siochiLeafSequencing(resultGUI,stf,dij,numOfLevels,visBool)
0001 function resultGUI = matRad_siochiLeafSequencing(resultGUI,stf,dij,numOfLevels,visBool)
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
0039
0040
0041
0042
0043
0044 if nargin < 5
0045 visBool = 0;
0046 end
0047
0048 numOfBeams = numel(stf);
0049
0050 if visBool
0051
0052 sz = [800 1000];
0053 screensize = get(0,'ScreenSize');
0054 xpos = ceil((screensize(3)-sz(2))/2);
0055 ypos = ceil((screensize(4)-sz(1))/2);
0056 seqFig = figure('position',[xpos,ypos,sz(2),sz(1)]);
0057 end
0058
0059 offset = 0;
0060
0061 for i = 1:numOfBeams
0062
0063 numOfRaysPerBeam = stf(i).numOfRays;
0064
0065
0066 wOfCurrBeams = resultGUI.wUnsequenced(1+offset:numOfRaysPerBeam+offset);
0067
0068 X = ones(numOfRaysPerBeam,1)*NaN;
0069 Z = ones(numOfRaysPerBeam,1)*NaN;
0070
0071 for j = 1:stf(i).numOfRays
0072 X(j) = stf(i).ray(j).rayPos_bev(:,1);
0073 Z(j) = stf(i).ray(j).rayPos_bev(:,3);
0074 end
0075
0076
0077 minX = min(X);
0078 maxX = max(X);
0079 minZ = min(Z);
0080 maxZ = max(Z);
0081
0082 dimOfFluenceMxX = (maxX-minX)/stf(i).bixelWidth + 1;
0083 dimOfFluenceMxZ = (maxZ-minZ)/stf(i).bixelWidth + 1;
0084
0085
0086 fluenceMx = zeros(dimOfFluenceMxZ,dimOfFluenceMxX);
0087
0088
0089
0090 xPos = (X-minX)/stf(i).bixelWidth+1;
0091 zPos = (Z-minZ)/stf(i).bixelWidth+1;
0092
0093
0094 indInFluenceMx = zPos + (xPos-1)*dimOfFluenceMxZ;
0095
0096
0097 fluenceMx(indInFluenceMx) = wOfCurrBeams;
0098
0099
0100 calFac = max(fluenceMx(:));
0101 D_k = round(fluenceMx/calFac*numOfLevels);
0102
0103
0104 D_0 = D_k;
0105
0106
0107
0108 shapes = NaN*ones(dimOfFluenceMxZ,dimOfFluenceMxX,10000);
0109 shapesWeight = zeros(10000,1);
0110 k = 0;
0111
0112 if visBool
0113 clf(seqFig);
0114 colormap(seqFig,'jet');
0115
0116 seqSubPlots(1) = subplot(2,2,1,'parent',seqFig);
0117 imagesc(D_k,'parent',seqSubPlots(1));
0118 set(seqSubPlots(1),'CLim',[0 numOfLevels],'YDir','normal');
0119 title(seqSubPlots(1),['Beam # ' num2str(i) ': max(D_0) = ' num2str(max(D_0(:))) ' - ' num2str(numel(unique(D_0))) ' intensity levels']);
0120 xlabel(seqSubPlots(1),'x - direction parallel to leaf motion ')
0121 ylabel(seqSubPlots(1),'z - direction perpendicular to leaf motion ')
0122 colorbar;
0123 drawnow
0124 end
0125
0126 D_k_nonZero = (D_k~=0);
0127 [D_k_Z, D_k_X] = ind2sub([dimOfFluenceMxZ,dimOfFluenceMxX],find(D_k_nonZero));
0128 D_k_MinZ = min(D_k_Z);
0129 D_k_MaxZ = max(D_k_Z);
0130 D_k_MinX = min(D_k_X);
0131 D_k_MaxX = max(D_k_X);
0132
0133
0134 [tops, bases] = matRad_siochiDecomposePort(D_k,dimOfFluenceMxZ,dimOfFluenceMxX,D_k_MinZ,D_k_MaxZ,D_k_MinX,D_k_MaxX);
0135
0136 if visBool
0137 [shapes,shapesWeight,k,D_k]=matRad_siochiConvertToSegments(shapes,shapesWeight,k,tops,bases,visBool,i,D_k,numOfLevels,seqFig,seqSubPlots);
0138 else
0139 [shapes,shapesWeight,k]=matRad_siochiConvertToSegments(shapes,shapesWeight,k,tops,bases);
0140 end
0141
0142 sequencing.beam(i).numOfShapes = k;
0143 sequencing.beam(i).shapes = shapes(:,:,1:k);
0144 sequencing.beam(i).shapesWeight = shapesWeight(1:k)/numOfLevels*calFac;
0145 sequencing.beam(i).bixelIx = 1+offset:numOfRaysPerBeam+offset;
0146 sequencing.beam(i).fluence = D_0;
0147 sequencing.beam(i).sum = zeros(dimOfFluenceMxZ,dimOfFluenceMxX);
0148
0149 for j = 1:k
0150 sequencing.beam(i).sum = sequencing.beam(i).sum+sequencing.beam(i).shapes(:,:,j)*sequencing.beam(i).shapesWeight(j);
0151 end
0152 sequencing.w(1+offset:numOfRaysPerBeam+offset,1) = sequencing.beam(i).sum(indInFluenceMx);
0153
0154 offset = offset + numOfRaysPerBeam;
0155
0156 end
0157
0158 resultGUI.w = sequencing.w;
0159 resultGUI.wSequenced = sequencing.w;
0160
0161 resultGUI.sequencing = sequencing;
0162 resultGUI.apertureInfo = matRad_sequencing2ApertureInfo(sequencing,stf);
0163
0164 doseSequencedDoseGrid = reshape(dij.physicalDose{1} * sequencing.w,dij.doseGrid.dimensions);
0165
0166 resultGUI.physicalDose = matRad_interp3(dij.doseGrid.x,dij.doseGrid.y',dij.doseGrid.z, ...
0167 doseSequencedDoseGrid, ...
0168 dij.ctGrid.x,dij.ctGrid.y',dij.ctGrid.z);
0169
0170
0171 if isfield(resultGUI,'wDao')
0172 resultGUI = rmfield(resultGUI,'wDao');
0173 end
0174
0175 end
0176
0177 function [tops, bases] = matRad_siochiDecomposePort(map,dimZ,dimX,minZ,maxZ,minX,maxX)
0178
0179
0180
0181
0182 tops = zeros(dimZ, dimX);
0183 bases = zeros(dimZ, dimX);
0184
0185 for i = minX:maxX
0186 maxTop = -1;
0187 TnG = 1;
0188 for j = minZ:maxZ
0189 if i == minX
0190 bases(j,i) = 1;
0191 tops(j,i) = bases(j,i)+map(j,i)-1;
0192 else
0193 if map(j,i) >= map(j,i-1)
0194 bases(j,i) = bases(j,i-1);
0195 tops(j,i) = bases(j,i)+map(j,i)-1;
0196 else
0197 if map(j,i) == 0
0198 bases(j,i) = tops(j,i-1)+1;
0199 tops(j,i) = bases(j,i)-1;
0200 else
0201 tops(j,i) = tops(j,i-1);
0202 bases(j,i) = tops(j,i)-map(j,i)+1;
0203 end
0204 end
0205 end
0206
0207 if tops(j,i) > maxTop
0208 maxTop = tops(j,i);
0209 maxRow = j;
0210 end
0211 end
0212
0213
0214 while(TnG)
0215
0216
0217
0218
0219 for j = (maxRow-1):-1:minZ
0220 if map(j,i) < map(j+1,i)
0221 if tops(j,i) > tops(j+1,i)
0222 tops(j+1,i) = tops(j,i);
0223 bases(j+1,i) = tops(j+1,i)-map(j+1,i)+1;
0224 elseif bases(j,i) < bases(j+1,i)
0225 bases(j,i) = bases(j+1,i);
0226 tops(j,i) = bases(j,i)+map(j,i)-1;
0227 end
0228 else
0229 if tops(j,i) < tops(j+1,i)
0230 tops(j,i) = tops(j+1,i);
0231 bases(j,i) = tops(j,i)-map(j,i)+1;
0232 elseif bases(j,i) > bases(j+1,i)
0233 bases(j+1,i) = bases(j,i);
0234 tops(j+1,i) = bases(j+1,i)+map(j+1,i)-1;
0235 end
0236 end
0237 end
0238
0239 for j = (maxRow+1):maxZ
0240 if map(j,i) < map(j-1,i)
0241 if tops(j,i) > tops(j-1,i)
0242 tops(j-1,i) = tops(j,i);
0243 bases(j-1,i) = tops(j-1,i)-map(j-1,i)+1;
0244 elseif bases(j,i) < bases(j-1,i)
0245 bases(j,i) = bases(j-1,i);
0246 tops(j,i) = bases(j,i)+map(j,i)-1;
0247 end
0248 else
0249 if tops(j,i) < tops(j-1,i)
0250 tops(j,i) = tops(j-1,i);
0251 bases(j,i) = tops(j,i)-map(j,i)+1;
0252 elseif bases(j,i) > bases(j-1,i)
0253 bases(j-1,i) = bases(j,i);
0254 tops(j-1,i) = bases(j-1,i)+map(j-1,i)-1;
0255 end
0256 end
0257 end
0258
0259 TnG = 0;
0260 for j = (minZ+1):maxZ
0261 if map(j,i) < map(j-1,i);
0262 if tops(j,i) > tops(j-1,i)
0263 TnG = 1;
0264 elseif bases(j,i) < bases(j-1,i)
0265 TnG = 1;
0266 end
0267 else
0268 if tops(j,i) < tops(j-1,i)
0269 TnG = 1;
0270 elseif bases(j,i) > bases(j-1,i)
0271 TnG = 1;
0272 end
0273 end
0274 end
0275 end
0276 end
0277
0278 end
0279
0280 function [shapes,shapesWeight,k,D_k] = matRad_siochiConvertToSegments(shapes,shapesWeight,k,tops,bases,visBool,i,D_k,numOfLevels,seqFig,seqSubPlots)
0281
0282
0283 if nargin < 6
0284 visBool = 0;
0285 end
0286
0287
0288 levels = max(tops(:));
0289
0290 for level = 1:levels
0291
0292 if matRad_siochiDifferentSlab(tops,bases,level)
0293 k = k+1;
0294 shape_k = (bases <= level).*(level <= tops);
0295 shapes(:,:,k) = shape_k;
0296 end
0297 shapesWeight(k) = shapesWeight(k)+1;
0298
0299 if visBool
0300
0301 [dimZ,dimX] = size(tops);
0302 seqSubPlots(4) = subplot(2,2,3.5,'parent',seqFig);
0303 imagesc(shape_k,'parent',seqSubPlots(4));
0304 hold(seqSubPlots(4),'on');
0305 set(seqSubPlots(4),'YDir','normal')
0306 xlabel(seqSubPlots(4),'x - direction parallel to leaf motion ')
0307 ylabel(seqSubPlots(4),'z - direction perpendicular to leaf motion ')
0308 title(seqSubPlots(4),['beam # ' num2str(i) ' shape # ' num2str(k) ' d_k = ' num2str(shapesWeight(k))]);
0309 for j = 1:dimZ
0310 leftLeafIx = find(shape_k(j,:)>0,1,'first');
0311 rightLeafIx = find(shape_k(j,:)>0,1,'last');
0312 if leftLeafIx > 1
0313 plot(seqSubPlots(4),[.5 leftLeafIx-.5],j-[.5 .5] ,'w','LineWidth',2)
0314 plot(seqSubPlots(4),[.5 leftLeafIx-.5],j+[.5 .5] ,'w','LineWidth',2)
0315 plot(seqSubPlots(4),[ leftLeafIx-.5 leftLeafIx-.5],j+[.5 -.5] ,'w','LineWidth',2)
0316 end
0317 if rightLeafIx<dimX
0318 plot(seqSubPlots(4),[dimX+.5 rightLeafIx+.5],j-[.5 .5] ,'w','LineWidth',2)
0319 plot(seqSubPlots(4),[dimX+.5 rightLeafIx+.5],j+[.5 .5] ,'w','LineWidth',2)
0320 plot(seqSubPlots(4),[ rightLeafIx+.5 rightLeafIx+.5],j+[.5 -.5] ,'w','LineWidth',2)
0321 end
0322 if isempty(rightLeafIx) && isempty (leftLeafIx)
0323 plot(seqSubPlots(4),[dimX+.5 .5],j-[.5 .5] ,'w','LineWidth',2)
0324 plot(seqSubPlots(4),[dimX+.5 .5],j+[.5 .5] ,'w','LineWidth',2)
0325 plot(seqSubPlots(4),.5*dimX*[1 1]+[0.5],j+[.5 -.5] ,'w','LineWidth',2)
0326 end
0327 end
0328 pause(1);
0329
0330
0331 D_k = D_k-shape_k;
0332 seqSubPlots(2) = subplot(2,2,2,'parent',seqFig);
0333 imagesc(D_k,'parent',seqSubPlots(2));
0334 set(seqSubPlots(2),'CLim',[0 numOfLevels],'YDir','normal');
0335 title(seqSubPlots(2),['k = ' num2str(k)]);
0336 colorbar
0337 drawnow
0338
0339 axis tight
0340 drawnow
0341 end
0342 end
0343
0344 end
0345
0346 function diffSlab = matRad_siochiDifferentSlab(tops,bases,level)
0347
0348
0349 if level == 1
0350 diffSlab = 1;
0351 else
0352 shapeLevel = (bases <= level).*(level <= tops);
0353 shapeLevel_1 = (bases <= level-1).*(level-1 <= tops);
0354 diffSlab = ~isequal(shapeLevel,shapeLevel_1);
0355 end
0356
0357 end
0358