-
Notifications
You must be signed in to change notification settings - Fork 0
/
Scanner.m
123 lines (92 loc) · 5.06 KB
/
Scanner.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
classdef Scanner
properties
name
sourcePosition
sourceEnergy
detectorPosition
detectorPhysicalSize
detectorMatrixSize
phantom
end
methods
function obj = Scanner(name, sourcePosition, sourceEnergy, ...
detectorPosition, detectorPhysicalSize, ...
detectorMatrixSize, phantom)
obj.name = name;
obj.sourcePosition = sourcePosition;
obj.sourceEnergy = sourceEnergy;
obj.detectorPosition = detectorPosition;
obj.detectorPhysicalSize = detectorPhysicalSize;
obj.detectorMatrixSize = detectorMatrixSize;
obj.phantom = phantom;
end
function image = run(obj)
% The image is initialized as NaN
image = nan(obj.detectorMatrixSize(1), obj.detectorMatrixSize(2));
% Finding real pixel size
pixelSize = obj.detectorPhysicalSize(1)/obj.detectorMatrixSize(1); % cm
% Determining the upper left corner of the first pixel
detectorCornerUL = [obj.detectorPosition(2) - obj.detectorPhysicalSize(1)/2, ...
obj.detectorPosition(3) + obj.detectorPhysicalSize(2)/2];
% Center position of the first pixel
centerOfFirstPixel(1) = detectorCornerUL(1) + 0.5 * pixelSize;
centerOfFirstPixel(2) = detectorCornerUL(2) - 0.5 * pixelSize;
% Calculating attenuation for all pixels of the detector
for rowIndice = 1 : obj.detectorMatrixSize(1)
for columnIndice = 1 : obj.detectorMatrixSize(2)
% Determine current pixel position
centerOfCurrentPixel = centerOfFirstPixel + [pixelSize*(columnIndice - 1), - pixelSize*(rowIndice - 1)];
% Determining the line between source and current pixel
% center
lineNotNormal = [obj.detectorPosition(1), centerOfCurrentPixel] - obj.sourcePosition;
% Normalizing the line
lineNormal = lineNotNormal ./ sqrt(sum(lineNotNormal.^2));
% Check all objects in phantom
intersectData = intersectPrivate(obj.phantom, obj.sourcePosition, lineNormal, obj.sourceEnergy);
intersectData(cellfun(@(x) isnan(x), intersectData(:,1)),:) = [];
if size(intersectData, 1) > 0
% Obtain attenuation coefficients for rays passing
% through objects
attenuationCoefficients = cell2mat(intersectData(:, 4));
% Obtain path data
numberOfPaths = numel(attenuationCoefficients);
% Initialize start point, end point, distance
% between them, attenuation intensity, and inital
% intensity levels
startPoint=nan(numberOfPaths,1);
endPoint=nan(numberOfPaths,1);
distance=nan(numberOfPaths,1);
attenuationIntensity=nan(numberOfPaths,1);
initialIntensityLevel=nan(numberOfPaths,1);
intersections = cell2mat(intersectData(:, 1:2));
% Sorting intersection points to find the start and
% end points
intersectionPointsSorted = sort([intersections(:,1); intersections(:,2)]);
% Initialize an intensity level
initialIntensityLevel(1)=obj.sourceEnergy;
% Calculating attenuation for each path passing
% through each sub object
for i = 1 : numberOfPaths
% Determine start, end and length of the path
startPoint(i) = intersectionPointsSorted(i);
endPoint(i) = intersectionPointsSorted(i + 1);
distance(i) = abs( startPoint(i) - endPoint(i) );
% Calculate intensity using Lambert-Beer Law
attenuationIntensity(i) = initialIntensityLevel(i) * ...
exp( - attenuationCoefficients(i) * distance(i) );
% If we have subobjects inside calculate
% attenuation for them also
if i < numberOfPaths
initialIntensityLevel(i+1) = attenuationIntensity(i);
end
end
% Assign final intensity value to the pixel
image(rowIndice, columnIndice) = attenuationIntensity(end);
else
image(rowIndice, columnIndice) = obj.sourceEnergy;
end
end
end
end
end
end