Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added downsampling of BlocksOnCylindrical scanners in scatter #1291

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
beeeea9
Added downsampling of BlocksOnCylindrical scanners in scatter
Nov 28, 2023
674d1ef
Merge branch 'master' into issue/1290-speeding-up-scatter-simulation-…
Feb 14, 2024
22e4b51
Avoid calling interpolation twice at end of scatter estimation.
Mar 8, 2024
f33c4bd
Changed interpolation in scatter estimation to linear, added set_half…
Mar 8, 2024
d72f7df
Merge branch 'master' into issue/1290-speeding-up-scatter-simulation-…
Jun 13, 2024
3f8b0e8
Fix swig file formatting causing the build to fail. Plus added config…
Jun 13, 2024
2e6d69c
Added handling of bucket intersections in transaxial direction to avo…
Jun 19, 2024
99c0377
Merge remote-tracking branch 'UCL-STIR/master' into issue/1290-speedi…
Jul 4, 2024
9a1a8a8
Clean implementation of interpolation using linear crystal spacing on…
Jul 4, 2024
c227630
Fixing merge issue.
Jul 4, 2024
fbc4917
Correctly using gaps between blocks. Also, small unrelated bugfix in …
Jul 9, 2024
5a1704d
For BlocksOnCylindrical, no longer go via proj data interpolator and …
Jul 10, 2024
312b2b0
Added test for transaxial upsampling using interpolate_projdata and a…
Jul 16, 2024
bac6128
Another merge fix.
Jul 17, 2024
9e47c0c
Some code cleanup and updating the release notes.
Jul 17, 2024
19815b9
Merge branch 'master' into issue/1290-speeding-up-scatter-simulation-…
markus-jehl Jul 17, 2024
c69784c
[ci skip] reverting merge related formatting change in stir.i
Jul 18, 2024
292ab4a
Adding function to get half filter width.
Jul 18, 2024
ad0b6a4
Codacy fix.
Jul 22, 2024
69d0594
Code review change
markus-jehl Jul 24, 2024
1a0d947
Code review changes.
Aug 23, 2024
581f3d9
Merge remote-tracking branch 'UCL-STIR/master' into issue/1290-speedi…
Aug 23, 2024
07d9a82
Updated release notes.
Aug 23, 2024
ee436f9
Added description of the blocks on cylindrical interpolation function.
Aug 23, 2024
f3e697d
Added an additional test that compares sinogram bins for LORs that do…
Aug 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 6 additions & 14 deletions src/buildblock/interpolate_projdata.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -239,17 +239,9 @@ interpolate_projdata(ProjData& proj_data_out,
};
}
else
{ // for BlocksOnCylindrical, views and tangential positions are not subsampled and can be mapped 1:1
if (proj_data_in_info.get_num_tangential_poss() != proj_data_out_info.get_num_tangential_poss())
{
error("Interpolation of BlocksOnCylindrical scanners assumes that number of tangential positions "
"is the same in the downsampled scanner.");
}
if (proj_data_in_info.get_num_views() != proj_data_out_info.get_num_views())
{
error("Interpolation of BlocksOnCylindrical scanners assumes that number of views "
"is the same in the downsampled scanner.");
}
{ // for BlocksOnCylindrical, views and tangential positions are scaled by a fixed value
auto scale_factor
= (double)proj_data_out_info.get_num_tangential_poss() / (double)proj_data_in_info.get_num_tangential_poss();

// only extending in axial direction - an extension of 2 was found to be sufficient
proj_data_interpolator.set_coef(extend_segment(segment, 0, 2, 0));
Expand All @@ -267,7 +259,7 @@ interpolate_projdata(ProjData& proj_data_out,
}

// define a function to translate indices in the output proj data to indices in input proj data
index_converter = [&proj_data_out_info, m_offset, m_sampling](
index_converter = [&proj_data_out_info, m_offset, m_sampling, scale_factor](
const BasicCoordinate<3, int>& index_out) -> BasicCoordinate<3, double> {
// translate index on output to coordinate
auto bin
Expand All @@ -277,8 +269,8 @@ interpolate_projdata(ProjData& proj_data_out,
// translate to indices in input proj data
BasicCoordinate<3, double> index_in;
index_in[1] = (out_m - m_offset) / m_sampling;
index_in[2] = index_out[2];
index_in[3] = index_out[3];
index_in[2] = index_out[2] / scale_factor;
index_in[3] = index_out[3] / scale_factor;

return index_in;
};
Expand Down
4 changes: 4 additions & 0 deletions src/include/stir/scatter/ScatterEstimation.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ class ScatterEstimation : public ParsingObject

inline void set_num_iterations(int);

inline void set_downsample_scanner(bool downsample_scanner, int downsampled_detectors_per_ring = 0);
markus-jehl marked this conversation as resolved.
Show resolved Hide resolved

void set_output_scatter_estimate_prefix(const std::string&);
void set_export_scatter_estimates_of_each_iteration(bool);

Expand Down Expand Up @@ -379,6 +381,8 @@ class ScatterEstimation : public ParsingObject
float min_scale_value;

bool downsample_scanner_bool;
int downsampled_detectors_per_ring;
markus-jehl marked this conversation as resolved.
Show resolved Hide resolved

//!
unsigned int half_filter_width;

Expand Down
7 changes: 7 additions & 0 deletions src/include/stir/scatter/ScatterEstimation.inl
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,11 @@ ScatterEstimation::set_num_iterations(int arg)
this->num_scatter_iterations = arg;
}

void
ScatterEstimation::set_downsample_scanner(bool downsample_scanner, int downsampled_detectors_per_ring)
{
this->downsample_scanner_bool = downsample_scanner;
this->downsampled_detectors_per_ring = downsampled_detectors_per_ring;
}

END_NAMESPACE_STIR
4 changes: 3 additions & 1 deletion src/scatter_buildblock/ScatterEstimation.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ ScatterEstimation::set_defaults()
this->override_scanner_template = true;
this->override_density_image = true;
this->downsample_scanner_bool = true;
this->downsampled_detectors_per_ring = 0;
markus-jehl marked this conversation as resolved.
Show resolved Hide resolved
this->remove_interleaving = true;
this->atten_image_filename = "";
this->atten_coeff_filename = "";
Expand Down Expand Up @@ -124,6 +125,7 @@ ScatterEstimation::initialise_keymap()
this->parser.add_parsing_key("Scatter Simulation type", &this->scatter_simulation_sptr);
this->parser.add_key("scatter simulation parameter filename", &this->scatter_sim_par_filename);
this->parser.add_key("use scanner downsampling in scatter simulation", &this->downsample_scanner_bool);
this->parser.add_key("override number of downsampled detectors per ring", &this->downsampled_detectors_per_ring);

this->parser.add_key("override attenuation image", &this->override_density_image);
this->parser.add_key("override scanner template", &this->override_scanner_template);
Expand Down Expand Up @@ -585,7 +587,7 @@ ScatterEstimation::set_up()
}

if (this->downsample_scanner_bool)
this->scatter_simulation_sptr->downsample_scanner();
this->scatter_simulation_sptr->downsample_scanner(-1, this->downsampled_detectors_per_ring);

// Check if Load a mask proj_data

Expand Down
37 changes: 20 additions & 17 deletions src/scatter_buildblock/ScatterSimulation.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -840,36 +840,39 @@ ScatterSimulation::downsample_scanner(int new_num_rings, int new_num_dets)
float approx_num_non_arccorrected_bins;
if (new_scanner_sptr->get_scanner_geometry() != "Cylindrical")
{
new_num_dets = this->proj_data_info_sptr->get_scanner_ptr()->get_num_detectors_per_ring();
approx_num_non_arccorrected_bins = this->proj_data_info_sptr->get_num_tangential_poss();
if (new_num_dets <= 0)
{ // by default, do not downsample the detectors per ring for BlocksOnCylindrical
new_num_dets = this->proj_data_info_sptr->get_scanner_ptr()->get_num_detectors_per_ring();
}

// extend the bins by a small amount to avoid edge-effects, at the expense of longer computation time
approx_num_non_arccorrected_bins = ceil(this->proj_data_info_sptr->get_num_tangential_poss() * float(new_num_dets)
/ old_scanner_ptr->get_num_detectors_per_ring())
+ 1;
// preserve the length of the scanner the following includes gaps
float scanner_length_block = new_scanner_sptr->get_num_axial_buckets() * new_scanner_sptr->get_num_axial_blocks_per_bucket()
* new_scanner_sptr->get_axial_block_spacing();
new_scanner_sptr->set_num_axial_blocks_per_bucket(1);
// new_scanner_sptr->set_num_transaxial_blocks_per_bucket(1);
new_scanner_sptr->set_num_transaxial_blocks_per_bucket(1);

new_scanner_sptr->set_num_rings(new_num_rings);
// float transaxial_bucket_spacing=old_scanner_ptr->get_transaxial_block_spacing()
// *old_scanner_ptr->get_num_transaxial_blocks_per_bucket();
float transaxial_bucket_spacing
= old_scanner_ptr->get_transaxial_block_spacing() * old_scanner_ptr->get_num_transaxial_blocks_per_bucket();
float new_ring_spacing = scanner_length_block / new_scanner_sptr->get_num_rings();
// int num_trans_buckets=old_scanner_ptr->get_num_transaxial_buckets();
int num_trans_buckets = old_scanner_ptr->get_num_transaxial_buckets();
// get a new number of detectors that is a multiple of the number of buckets to preserve scanner shape
// float frac,whole;
// frac = std::modf(float(new_num_dets/new_scanner_sptr->get_num_transaxial_buckets()), &whole);
// int newest_num_dets=whole*new_scanner_sptr->get_num_transaxial_buckets();
// new_scanner_sptr->set_num_detectors_per_ring(newest_num_dets);
// int new_transaxial_dets_per_bucket=newest_num_dets/num_trans_buckets;
// float new_det_spacing=transaxial_bucket_spacing/new_transaxial_dets_per_bucket;
new_scanner_sptr->set_num_detectors_per_ring(new_num_dets);
int new_transaxial_dets_per_bucket = new_num_dets / num_trans_buckets;
float new_det_spacing = transaxial_bucket_spacing / new_transaxial_dets_per_bucket;

new_scanner_sptr->set_axial_crystal_spacing(new_ring_spacing);
new_scanner_sptr->set_ring_spacing(new_ring_spacing);
new_scanner_sptr->set_num_axial_crystals_per_block(new_num_rings);
new_scanner_sptr->set_axial_block_spacing(new_ring_spacing * new_scanner_sptr->get_num_axial_crystals_per_block());
new_scanner_sptr->set_axial_block_spacing(new_ring_spacing * new_num_rings);

// new_scanner_sptr->set_num_transaxial_crystals_per_block(new_transaxial_dets_per_bucket);
// new_scanner_sptr->set_transaxial_crystal_spacing(new_det_spacing);
// new_scanner_sptr->set_transaxial_block_spacing(new_det_spacing
// * new_scanner_sptr->get_num_transaxial_crystals_per_block());
new_scanner_sptr->set_num_transaxial_crystals_per_block(new_transaxial_dets_per_bucket);
new_scanner_sptr->set_transaxial_crystal_spacing(new_det_spacing);
new_scanner_sptr->set_transaxial_block_spacing(transaxial_bucket_spacing);
}
else
{
Expand Down
Loading