Newer
Older
Nicola Vigano
committed
function [atts_tot, atts, abs_vol] = gtGrainComputeBeamAttenuation(gr, p, det_ind, abs_vol, varargin)
Nicola Vigano
committed
conf = struct('verbose', false, 'sampling_factor', 1);
conf = parse_pv_pairs(conf, varargin);
if (~exist('conf.sampling_factor', 'var') || isempty(conf.sampling_factor))
conf.sampling_factor = 1;
Nicola Vigano
committed
end
Zheheng Liu
committed
if (~exist('det_ind', 'var') || isempty(det_ind))
det_ind = 1;
end
Nicola Vigano
committed
if (isfield(gr.proj, 'ondet'))
Zheheng Liu
committed
gr_included = gr.proj(det_ind).ondet(gr.proj.included);
Nicola Vigano
committed
else
gr_included = gr.ondet(gr.included);
end
Zheheng Liu
committed
rot_l2s = gr.allblobs(det_ind).srot(:, :, gr_included);
Nicola Vigano
committed
% They are reversed because we also use them to find the intersaction
% with the volume border
beam_dirs_in = - p.labgeo.beamdir * reshape(rot_l2s, 3, []);
beam_dirs_in = permute(reshape(beam_dirs_in, 1, 3, []), [3 2 1]);
Zheheng Liu
committed
beam_dirs_out = gr.allblobs(det_ind).dvecsam(gr_included, :);
Nicola Vigano
committed
Nicola Vigano
committed
gr_center_pix = gr.proj(det_ind).centerpix;
if (~exist('abs_vol', 'var') || isempty(abs_vol))
sample = GtSample.loadFromFile();
abs_rec = load(sample.absVolFile);
Zheheng Liu
committed
mask_path = fullfile(p.acq(det_ind).dir, '5_reconstruction', 'volume_mask.mat');
vol_mask = load(mask_path);
abs_vol = abs_rec.abs .* single(vol_mask.vol);
if (isfield(abs_rec, 'rot_angle') && ~isempty(abs_rec.rot_angle))
rot_comp = gtMathsRotationMatrixComp(abs_rec.rot_axis', 'col');
rot_tensor = gtMathsRotationTensor(abs_rec.rot_angle, rot_comp);
beam_dirs_in = gtMathsMatrixProduct(beam_dirs_in, rot_tensor);
beam_dirs_out = gtMathsMatrixProduct(beam_dirs_out, rot_tensor);
gr_center_pix = gr_center_pix * rot_tensor;
end
end
gr_center = gr_center_pix + size(abs_vol) / 2 + 1;
Nicola Vigano
committed
% ray tracing
dists_borders = cat(3, [1 1 1], size(abs_vol)) - gr_center(1, :, [1 1]);
dists_renorm_in = compute_renormalized_distances(dists_borders, beam_dirs_in);
dists_renorm_out = compute_renormalized_distances(dists_borders, beam_dirs_out);
num_refl = numel(gr_included);
atts = zeros(num_refl, 2);
if (conf.verbose)
rescaled_abs_vol = (abs_vol - min(abs_vol(:))) / (max(abs_vol(:)) - min(abs_vol(:)));
rescaled_abs_vol = permute(rescaled_abs_vol, [ 2 1 3]);
[sx, sy, sz] = ndgrid(1:size(abs_vol, 1), 1:size(abs_vol, 2), gr_center(3));
end
Nicola Vigano
committed
for ii = 1:num_refl
% dist_in = dists_borders(d_inds_in_dir(d_inds_in_pm(ii)));
% samp_points_in = linspace(0, dists_renorm_in(ii), ceil(abs(dist_in) * conf.sampling_factor) );
Nicola Vigano
committed
samp_factor_in = ceil(dists_renorm_in(ii) * conf.sampling_factor);
Nicola Vigano
committed
samp_points_in = linspace(0, dists_renorm_in(ii), samp_factor_in);
samp_points_in = bsxfun(@times, beam_dirs_in(ii, :), samp_points_in');
samp_points_in = bsxfun(@plus, samp_points_in, gr_center);
% dist_out = dists_borders(d_inds_out_dir(d_inds_out_pm(ii)));
% samp_points_out = linspace(0, dists_renorm_out(ii), ceil(abs(dist_out) * conf.sampling_factor) );
Nicola Vigano
committed
samp_factor_out = ceil(dists_renorm_out(ii) * conf.sampling_factor);
Nicola Vigano
committed
samp_points_out = linspace(0, dists_renorm_out(ii), samp_factor_out);
samp_points_out = bsxfun(@times, beam_dirs_out(ii, :), samp_points_out');
samp_points_out = bsxfun(@plus, samp_points_out, gr_center);
[inds_in, ints_in] = gtMathsGetInterpolationIndices(samp_points_in);
valid_in = ints_in > eps('single');
inds_in = inds_in(valid_in, :);
ints_in = ints_in(valid_in);
[inds_out, ints_out] = gtMathsGetInterpolationIndices(samp_points_out);
valid_out = ints_out > eps('single');
inds_out = inds_out(valid_out, :);
ints_out = ints_out(valid_out);
inds_in = sub2ind(size(abs_vol), inds_in(:, 1), inds_in(:, 2), inds_in(:, 3));
vals_in = abs_vol(inds_in) .* ints_in;
inds_out = sub2ind(size(abs_vol), inds_out(:, 1), inds_out(:, 2), inds_out(:, 3));
vals_out = abs_vol(inds_out) .* ints_out;
abs_in = sum(vals_in) / samp_factor_in * dists_renorm_in(ii);
abs_out = sum(vals_out) / samp_factor_out * dists_renorm_out(ii);
atts(ii, :) = [abs_in, abs_out];
if (conf.verbose)
f = figure();
ax = axes('parent', f);
hold(ax, 'on')
hsl = slice(ax, rescaled_abs_vol, sx, sy, sz);
hsl.FaceColor = 'interp';
hsl.EdgeColor = 'none';
scatter3(ax, samp_points_in(:, 1), samp_points_in(:, 2), samp_points_in(:, 3));
scatter3(ax, samp_points_out(:, 1), samp_points_out(:, 2), samp_points_out(:, 3));
show_bbox(ax, cat(1, [1 1 1], size(abs_vol)))
hold(ax, 'off')
pause
end
Nicola Vigano
committed
end
% Might need better scaling, for meaningful attenuation!! (0.1 -> mm to cm)
atts = exp(-atts * 0.1);
atts_tot = prod(atts, 2);
Nicola Vigano
committed
if (conf.verbose)
figure, semilogy(atts)
figure, semilogy(atts_tot)
end
Nicola Vigano
committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
end
function [dists_renorm, d_inds_pm, d_inds_dir] = compute_renormalized_distances(dists_borders, beam_dirs)
dists_renorm = bsxfun(@times, dists_borders, 1 ./ beam_dirs);
[dists_renorm, d_inds_pm] = max(dists_renorm, [], 3); % Takes negative out
[dists_renorm, d_inds_dir] = min(dists_renorm, [], 2); % Takes shortest, and removes last remaining nans
end
function show_bbox(ax, borders)
min_sampled_R_vecs = min(borders, [], 1);
max_sampled_R_vecs = max(borders, [], 1);
bbox_R_vecs = [ ...
min_sampled_R_vecs(1), min_sampled_R_vecs(2), min_sampled_R_vecs(3); ...
min_sampled_R_vecs(1), min_sampled_R_vecs(2), max_sampled_R_vecs(3); ...
min_sampled_R_vecs(1), max_sampled_R_vecs(2), min_sampled_R_vecs(3); ...
min_sampled_R_vecs(1), max_sampled_R_vecs(2), max_sampled_R_vecs(3); ...
max_sampled_R_vecs(1), min_sampled_R_vecs(2), min_sampled_R_vecs(3); ...
max_sampled_R_vecs(1), min_sampled_R_vecs(2), max_sampled_R_vecs(3); ...
max_sampled_R_vecs(1), max_sampled_R_vecs(2), min_sampled_R_vecs(3); ...
max_sampled_R_vecs(1), max_sampled_R_vecs(2), max_sampled_R_vecs(3); ...
];
faces = [ ...
1 5; 2 6; 3 7; 4 8; ...
1 3; 2 4; 5 7; 6 8; ...
1 2; 3 4; 5 6; 7 8; ...
];
scatter3(ax, bbox_R_vecs(:, 1), bbox_R_vecs(:, 2), bbox_R_vecs(:, 3), 30, 'y', 'filled');
patch('parent', ax, 'Faces', faces, 'Vertices', bbox_R_vecs, 'FaceColor', 'w');
end