Skip to content

Commit c60cf57

Browse files
committed
deprecate matRad_generateSingleBixelStf
1 parent d8c5b05 commit c60cf57

File tree

1 file changed

+7
-212
lines changed

1 file changed

+7
-212
lines changed

matRad/util/matRad_generateSingleBixelStf.m

Lines changed: 7 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -30,223 +30,18 @@
3030

3131
matRad_cfg = MatRad_Config.instance();
3232

33-
matRad_cfg.dispInfo('matRad: Generating single bixel stf struct... ');
33+
matRad_cfg.dispDeprecationWarning('The function %s is not intendet to be used, check out the Single Bixel Stf Generators in the steering folder',fileparts(mfilename));
3434

35-
if nargin < 4
36-
visMode = 0;
37-
end
38-
39-
if numel(pln.propStf.gantryAngles) ~= numel(pln.propStf.couchAngles)
40-
matRad_cfg.dispError('Inconsistent number of gantry and couch angles.');
41-
end
42-
43-
if pln.propStf.bixelWidth < 0 || ~isfinite(pln.propStf.bixelWidth)
44-
matRad_cfg.dispError('bixel width (spot distance) needs to be a real number [mm] larger than zero.');
45-
end
46-
47-
% prepare structures necessary for particles
48-
fileName = [pln.radiationMode '_' pln.machine '.mat'];
49-
try
50-
machine = matRad_loadMachine(pln);
51-
catch
52-
matRad_cfg.dispError('Could not find the following machine file: %s',fileName);
53-
end
54-
55-
SAD = machine.meta.SAD;
56-
57-
if strcmp(pln.radiationMode,'protons') || strcmp(pln.radiationMode,'carbon') || strcmp(pln.radiationMode,'helium')
58-
59-
availableEnergies = [machine.data.energy];
60-
availablePeakPos = [machine.data.peakPos] + [machine.data.offset];
61-
62-
if sum(availablePeakPos<0)>0
63-
matRad_cfg.dispError('at least one available peak position is negative - inconsistent machine file')
64-
end
65-
%clear machine;
66-
end
67-
68-
% calculate rED or rSP from HU
69-
ct = matRad_calcWaterEqD(ct, pln);
70-
71-
% take only voxels inside patient
72-
V = [cst{:,4}];
73-
V = unique(vertcat(V{:}));
74-
75-
% ignore densities outside of contours
76-
eraseCtDensMask = ones(prod(ct.cubeDim),1);
77-
eraseCtDensMask(V) = 0;
78-
for i = 1:ct.numOfCtScen
79-
ct.cube{i}(eraseCtDensMask == 1) = 0;
80-
end
81-
82-
% Define steering file like struct. Prellocating for speed.
83-
stf = struct;
84-
85-
% find set of energyies with adequate spacing
86-
if ~isfield(pln.propStf, 'longitudinalSpotSpacing')
87-
longitudinalSpotSpacing = matRad_cfg.defaults.propStf.longitudinalSpotSpacing;
35+
if any(strcmp(pln.radiationMode,{'protons','helium','carbon','oxygen'}))
36+
stfGen = matRad_ParticleStfGeneratorSingleBeamlet(pln);
37+
elseif strcmp(pln.radiationMode,'photons')
38+
stfGen = matRad_PhotonStfGeneratorSingleBeamlet(pln);
8839
else
89-
longitudinalSpotSpacing = pln.propStf.longitudinalSpotSpacing;
40+
matRad_cfg.dispError('Unsupported Radiation Mode!');
9041
end
9142

92-
if ~isfield(pln.propStf,'useRangeShifter')
93-
pln.propStf.useRangeShifter = false;
94-
end
95-
96-
%Get Isocenter voxel as target
97-
ct = matRad_getWorldAxes(ct);
98-
99-
100-
% loop over all angles
101-
for i = 1:length(pln.propStf.gantryAngles)
102-
103-
% Save meta information for treatment plan
104-
stf(i).gantryAngle = pln.propStf.gantryAngles(i);
105-
stf(i).couchAngle = pln.propStf.couchAngles(i);
106-
stf(i).bixelWidth = pln.propStf.bixelWidth;
107-
stf(i).radiationMode = pln.radiationMode;
108-
stf(i).SAD = SAD;
109-
stf(i).isoCenter = pln.propStf.isoCenter(i,:);
110-
stf(i).numOfRays = 1;
111-
stf(i).numOfBixelsPerRay = 1;
112-
stf(i).totalNumOfBixels = 1;
113-
stf(i).machine = pln.machine;
114-
115-
%Voxel index of Isocenter
116-
isoIx = matRad_world2cubeIndex(stf(i).isoCenter,ct,true);
117-
isoIx(isoIx < 1) = 1;
118-
isoIx(isoIx > ct.cubeDim) = ct.cubeDim(isoIx > ct.cubeDim);
119-
120-
% generate voi cube for targets
121-
voiTarget = zeros(ct.cubeDim);
122-
voiTarget(isoIx(1),isoIx(2),isoIx(3)) = 1;
123-
adds = unique(perms([1 0 0]),'rows');
124-
adds = [adds; -adds];
125-
for p = 1:size(adds,1)
126-
padIx = isoIx + adds(p,:);
127-
if any(padIx < 1) || any(padIx > ct.cubeDim)
128-
continue;
129-
end
130-
voiTarget(padIx(1),padIx(2),padIx(3)) = 1;
131-
end
132-
133-
%voiTarget = matRad_addMargin(voiTarget,cst,ct.resolution,ct.resolution);
134-
135-
% Get the (active) rotation matrix. We perform a passive/system
136-
% rotation with row vector coordinates, which would introduce two
137-
% inversions / transpositions of the matrix, thus no changes to the
138-
% rotation matrix are necessary
139-
rotMat_system_T = matRad_getRotationMatrix(pln.propStf.gantryAngles(i),pln.propStf.couchAngles(i));
140-
rotMat_vectors_T = transpose(rotMat_system_T);
141-
142-
stf(i).sourcePoint_bev = [0 -SAD 0];
143-
stf(i).sourcePoint = stf(i).sourcePoint_bev*rotMat_vectors_T;
144-
145-
stf(i).ray.rayPos_bev = [0 0 0];
146-
stf(i).ray.targetPoint_bev = [0 SAD 0];
147-
148-
149-
shiftedIsoCenter = matRad_world2cubeCoords(vertcat(stf(i).isoCenter),ct);
150-
151-
stf(i).ray.rayPos = stf(i).ray.rayPos_bev * rotMat_vectors_T;
152-
stf(i).ray.targetPoint = [0 SAD 0] * rotMat_vectors_T;
153-
154-
155-
% find appropriate energies for particles
156-
if strcmp(stf(i).radiationMode,'protons') || strcmp(stf(i).radiationMode,'carbon') || strcmp(stf(i).radiationMode,'helium')
157-
stf(i).longitudinalSpotSpacing = longitudinalSpotSpacing;
158-
159-
% ray tracing necessary to determine depth of the target
160-
[alphas,l,rho,d12,~] = matRad_siddonRayTracer(shiftedIsoCenter, ...
161-
ct.resolution, ...
162-
stf(i).sourcePoint, ...
163-
stf(i).ray.targetPoint, ...
164-
[{ct.cube{1}} {voiTarget}]);
165-
166-
%Used for generic range-shifter placement
167-
ctEntryPoint = alphas(1) * d12;
168-
169-
% target hit
170-
if sum(rho{2}) > 0
171-
172-
% compute radiological depths
173-
% http://www.ncbi.nlm.nih.gov/pubmed/4000088, eq 14
174-
radDepths = cumsum(l .* rho{1});
175-
176-
% find target entry & exit
177-
diff_voi = diff([rho{2}]);
178-
if rho{2}(1) > 0
179-
targetEntry = 1;
180-
else
181-
targetEntry = radDepths(diff_voi == 1);
182-
end
183-
184-
targetExit = radDepths(diff_voi == -1);
185-
186-
if numel(targetEntry) ~= numel(targetExit)
187-
matRad_cfg.dispError('Inconsistency during ray tracing. Please check correct assignment and overlap priorities of structure types OAR & TARGET.');
188-
end
189-
190-
raShiThickness = 50;
191-
192-
% Save energies in stf struct
193-
bestPeakPos = mean([targetExit,targetEntry]) + raShiThickness;
194-
[~,closest] = min(abs(availablePeakPos - bestPeakPos));
195-
stf(i).ray.energy = availableEnergies(closest);
196-
197-
198-
% book keeping & calculate focus index
199-
currentMinimumFWHM = matRad_interp1(machine.meta.LUT_bxWidthminFWHM(1,:)',...
200-
machine.meta.LUT_bxWidthminFWHM(2,:)',...
201-
pln.propStf.bixelWidth, ...
202-
machine.meta.LUT_bxWidthminFWHM(2,end));
203-
[~, vEnergyIx] = min(abs(bsxfun(@minus,[machine.data.energy]',...
204-
repmat(stf(i).ray.energy,length([machine.data]),1))));
205-
206-
% get for each spot the focus index
207-
stf(i).ray.focusIx = find(machine.data(vEnergyIx).initFocus.SisFWHMAtIso > currentMinimumFWHM,1,'first');
208-
209-
if pln.propStf.useRangeShifter
210-
211-
%Include range shifter data
212-
stf(i).ray.rangeShifter.ID = 1;
213-
stf(i).ray.rangeShifter.eqThickness = raShiThickness;
214-
215-
%Place range shifter 2 times the range away from isocenter, but
216-
%at least 10 cm
217-
sourceRaShi = round(ctEntryPoint - 2*raShiThickness,-1); %place a little away from entry, round to cms to reduce number of unique settings;
218-
stf(i).ray.rangeShifter.sourceRashiDistance = sourceRaShi;
219-
else
220-
stf(i).ray.rangeShifter.ID = 0;
221-
stf(i).ray.rangeShifter.eqThickness = 0;
222-
stf(i).ray.rangeShifter.sourceRashiDistance = 0;
223-
end
224-
225-
else % target not hit
226-
stf(i).ray = [];
227-
stf(i).numOfBixelsPerray = [];
228-
end
229-
230-
elseif strcmp(stf(i).radiationMode,'photons')
231-
232-
% book keeping for photons
233-
stf(i).ray.energy = machine.data.energy;
43+
stf = stfGen.generate(ct,cst);
23444

235-
rayPos = stf(i).ray.rayPos;
236-
237-
stf(i).ray.beamletCornersAtIso = [rayPos + [+stf(i).bixelWidth/2,0,+stf(i).bixelWidth/2];...
238-
rayPos + [-stf(i).bixelWidth/2,0,+stf(i).bixelWidth/2];...
239-
rayPos + [-stf(i).bixelWidth/2,0,-stf(i).bixelWidth/2];...
240-
rayPos + [+stf(i).bixelWidth/2,0,-stf(i).bixelWidth/2]]*rotMat_vectors_T;
241-
stf(i).ray.rayCorners_SCD = (repmat([0, machine.meta.SCD - SAD, 0],4,1)+ (machine.meta.SCD/SAD) * ...
242-
[rayPos + [+stf(i).bixelWidth/2,0,+stf(i).bixelWidth/2];...
243-
rayPos + [-stf(i).bixelWidth/2,0,+stf(i).bixelWidth/2];...
244-
rayPos + [-stf(i).bixelWidth/2,0,-stf(i).bixelWidth/2];...
245-
rayPos + [+stf(i).bixelWidth/2,0,-stf(i).bixelWidth/2]])*rotMat_vectors_T;
246-
247-
else
248-
matRad_cfg.dispError('Error generating stf struct: invalid radiation modality.');
249-
end
25045
end
25146

25247

0 commit comments

Comments
 (0)