forked from e0404/matRad
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmatRad_calcDoseInit.m
148 lines (120 loc) · 5.08 KB
/
matRad_calcDoseInit.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
matRad_cfg = MatRad_Config.instance();
% default: dose influence matrix computation
if ~exist('calcDoseDirect','var')
calcDoseDirect = false;
end
% to guarantee downwards compatibility with data that does not have
% ct.x/y/z
if ~any(isfield(ct,{'x','y','z'}))
ct.x = ct.resolution.x*[0:ct.cubeDim(2)-1]-ct.resolution.x/2;
ct.y = ct.resolution.y*[0:ct.cubeDim(1)-1]-ct.resolution.y/2;
ct.z = ct.resolution.z*[0:ct.cubeDim(3)-1]-ct.resolution.z/2;
end
% set grids
if ~isfield(pln,'propDoseCalc') || ...
~isfield(pln.propDoseCalc,'doseGrid') || ...
~isfield(pln.propDoseCalc.doseGrid,'resolution')
% default values
dij.doseGrid.resolution = matRad_cfg.propDoseCalc.defaultResolution;
else
% take values from pln strcut
dij.doseGrid.resolution.x = pln.propDoseCalc.doseGrid.resolution.x;
dij.doseGrid.resolution.y = pln.propDoseCalc.doseGrid.resolution.y;
dij.doseGrid.resolution.z = pln.propDoseCalc.doseGrid.resolution.z;
end
dij.doseGrid.x = ct.x(1):dij.doseGrid.resolution.x:ct.x(end);
dij.doseGrid.y = ct.y(1):dij.doseGrid.resolution.y:ct.y(end);
dij.doseGrid.z = ct.z(1):dij.doseGrid.resolution.z:ct.z(end);
dij.doseGrid.dimensions = [numel(dij.doseGrid.y) numel(dij.doseGrid.x) numel(dij.doseGrid.z)];
dij.doseGrid.numOfVoxels = prod(dij.doseGrid.dimensions);
dij.ctGrid.resolution.x = ct.resolution.x;
dij.ctGrid.resolution.y = ct.resolution.y;
dij.ctGrid.resolution.z = ct.resolution.z;
dij.ctGrid.x = ct.x;
dij.ctGrid.y = ct.y;
dij.ctGrid.z = ct.z;
dij.ctGrid.dimensions = [numel(dij.ctGrid.y) numel(dij.ctGrid.x) numel(dij.ctGrid.z)];
dij.ctGrid.numOfVoxels = prod(dij.ctGrid.dimensions);
% adjust isocenter internally for different dose grid
offset = [dij.doseGrid.resolution.x - dij.ctGrid.resolution.x ...
dij.doseGrid.resolution.y - dij.ctGrid.resolution.y ...
dij.doseGrid.resolution.z - dij.ctGrid.resolution.z];
for i = 1:numel(stf)
stf(i).isoCenter = stf(i).isoCenter + offset;
end
%set up HU to rED or rSP conversion
if ~isfield(pln,'propDoseCalc') || ~isfield(pln.propDoseCalc,'useGivenEqDensityCube')
disableHUconversion = matRad_cfg.propDoseCalc.defaultUseGivenEqDensityCube;
else
disableHUconversion = pln.propDoseCalc.useGivenEqDensityCube;
end
%If we want to omit HU conversion check if we have a ct.cube ready
if disableHUconversion && ~isfield(ct,'cube')
matRad_cfg.dispWarning('HU Conversion requested to be omitted but no ct.cube exists! Will override and do the conversion anyway!');
disableHUconversion = false;
end
% calculate rED or rSP from HU
if disableHUconversion
matRad_cfg.dispInfo('Omitting HU to rED/rSP conversion and using existing ct.cube!\n');
else
ct = matRad_calcWaterEqD(ct, pln);
end
% meta information for dij
dij.numOfBeams = pln.propStf.numOfBeams;
dij.numOfScenarios = 1;
dij.numOfRaysPerBeam = [stf(:).numOfRays];
dij.totalNumOfBixels = sum([stf(:).totalNumOfBixels]);
dij.totalNumOfRays = sum(dij.numOfRaysPerBeam);
% check if full dose influence data is required
if calcDoseDirect
numOfColumnsDij = length(stf);
numOfBixelsContainer = 1;
else
numOfColumnsDij = dij.totalNumOfBixels;
numOfBixelsContainer = ceil(dij.totalNumOfBixels/10);
end
% set up arrays for book keeping
dij.bixelNum = NaN*ones(numOfColumnsDij,1);
dij.rayNum = NaN*ones(numOfColumnsDij,1);
dij.beamNum = NaN*ones(numOfColumnsDij,1);
% Allocate space for dij.physicalDose sparse matrix
for i = 1:dij.numOfScenarios
dij.physicalDose{i} = spalloc(dij.doseGrid.numOfVoxels,numOfColumnsDij,1);
end
% Allocate memory for dose_temp cell array
doseTmpContainer = cell(numOfBixelsContainer,dij.numOfScenarios);
% take only voxels inside patient
VctGrid = [cst{:,4}];
VctGrid = unique(vertcat(VctGrid{:}));
% ignore densities outside of contours
if ~isfield(pln,'propDoseCalc') || ~isfield(pln.propDoseCalc,'ignoreOutsideDensities')
ignoreOutsideDensities = matRad_cfg.propDoseCalc.defaultIgnoreOutsideDensities;
else
ignoreOutsideDensities = pln.propDoseCalc.ignoreOutsideDensities;
end
if ignoreOutsideDensities
eraseCtDensMask = ones(prod(ct.cubeDim),1);
eraseCtDensMask(VctGrid) = 0;
for i = 1:ct.numOfCtScen
ct.cube{i}(eraseCtDensMask == 1) = 0;
end
end
% Convert CT subscripts to linear indices.
[yCoordsV_vox, xCoordsV_vox, zCoordsV_vox] = ind2sub(ct.cubeDim,VctGrid);
% receive linear indices and grid locations from the dose grid
tmpCube = zeros(ct.cubeDim);
tmpCube(VctGrid) = 1;
% interpolate cube
VdoseGrid = find(matRad_interp3(dij.ctGrid.x, dij.ctGrid.y, dij.ctGrid.z,tmpCube, ...
dij.doseGrid.x,dij.doseGrid.y',dij.doseGrid.z,'nearest'));
% Convert CT subscripts to coarse linear indices.
[yCoordsV_voxDoseGrid, xCoordsV_voxDoseGrid, zCoordsV_voxDoseGrid] = ind2sub(dij.doseGrid.dimensions,VdoseGrid);
% load base data% load machine file
fileName = [pln.radiationMode '_' pln.machine];
try
load([fileparts(mfilename('fullpath')) filesep 'basedata' filesep fileName]);
catch
matRad_cfg.dispError('Could not find the following machine file: %s\n',fileName);
end
% compute SSDs
stf = matRad_computeSSD(stf,ct);