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 all 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
66 changes: 66 additions & 0 deletions documentation/release_6.3.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Summary of changes in STIR release 6.3</title>
</head>

<body>
<h1>Summary of changes in STIR release 6.3</h1>


<h2>Overall summary</h2>


<h2>Patch release info</h2>


<h2> Summary for end users (also to be read by developers)</h2>


<h3>New functionality</h3>
<ul>
<li>
<code>ScatterSimulation</code> can now downsample the scanner transaxially (crystals per ring) for <code>BlocksOnCylindrical</code>,
scanners, which speeds up <code>ScatterEstimation</code> considerably. By default, downsampling the detectors per reading
is disabled for backwards compatibility.<br>
<a href=https://github.com/UCL/STIR/pull/1291>PR #1291</a>
</li>
</ul>


<h3>Changed functionality</h3>


<h3>Bug fixes</h3>


<h3>Build system</h3>


<h3>Known problems</h3>
<p>See <a href=https://github.com/UCL/STIR/labels/bug>our issue tracker</a>.</p>


<H2>What is new for developers (aside from what should be obvious from the above):</H2>


<h3>Changed functionality</h3>


<h3>Bug fixes</h3>


<h3>Other code changes</h3>


<h3>Test changes</h3>


<h4>C++ tests</h4>


<h4>recon_test_pack</h4>

</body>

</html>
2 changes: 1 addition & 1 deletion src/buildblock/extend_projdata.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ extend_segment(const SegmentBySinogram<float>& segment,
if (extend_without_wrapping)
{
out[axial_pos][min_dim[2] + view_edge] = out[axial_pos][min_dim[2] + view_extension];
out[axial_pos][max_dim[2] - view_extension] = out[axial_pos][max_dim[2] - view_extension];
out[axial_pos][max_dim[2] - view_edge] = out[axial_pos][max_dim[2] - view_extension];
}
else if (flip_views)
{
Expand Down
386 changes: 307 additions & 79 deletions src/buildblock/interpolate_projdata.cxx

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/include/stir/interpolate_projdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Succeeded interpolate_projdata(ProjData& proj_data_out,
const ProjData& proj_data_in,
const BasicCoordinate<3, BSpline::BSplineType>& these_types,
const bool remove_interleaving);
Succeeded
interpolate_blocks_on_cylindrical_projdata(ProjData& proj_data_out, const ProjData& proj_data_in, bool remove_interleaving);
//@}

END_NAMESPACE_STIR
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ DataSymmetriesForBins_PET_CartesianGrid::find_sym_op_bin0(int segment_num, int v
// No symmetry is implemented for generic scanner
return new TrivialSymmetryOperation();
}
return new TrivialSymmetryOperation();
}

// from symmetries
Expand Down Expand Up @@ -390,6 +391,8 @@ DataSymmetriesForBins_PET_CartesianGrid::find_sym_op_general_bin(int s, int segm
// No symmetry is implemented for generic scanner
return new TrivialSymmetryOperation();
}

return new TrivialSymmetryOperation();
}

bool
Expand Down
9 changes: 9 additions & 0 deletions src/include/stir/scatter/ScatterEstimation.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ class ScatterEstimation : public ParsingObject

inline void set_num_iterations(int);

inline unsigned int get_half_filter_width() const;
inline void set_half_filter_width(unsigned int);

inline void
set_downsample_scanner(bool downsample_scanner, int downsampled_number_of_rings = -1, int downsampled_detectors_per_ring = -1);

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

Expand Down Expand Up @@ -382,6 +388,9 @@ class ScatterEstimation : public ParsingObject
float min_scale_value;

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

//!
unsigned int half_filter_width;

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

unsigned int
ScatterEstimation::get_half_filter_width() const
{
return this->half_filter_width;
}

void
ScatterEstimation::set_half_filter_width(unsigned int arg)
{
this->half_filter_width = arg;
}

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

END_NAMESPACE_STIR
26 changes: 14 additions & 12 deletions src/scatter_buildblock/ScatterEstimation.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "stir/recon_buildblock/ChainedBinNormalisation.h"
#include "stir/ProjDataInterfile.h"
#include "stir/ProjDataInMemory.h"
#include "stir/inverse_SSRB.h"
#include "stir/ExamInfo.h"
#include "stir/ProjDataInfo.h"
#include "stir/ProjDataInfoCylindricalNoArcCorr.h"
Expand Down Expand Up @@ -77,6 +78,8 @@ ScatterEstimation::set_defaults()
this->override_scanner_template = true;
this->override_density_image = true;
this->downsample_scanner_bool = true;
this->downsampled_number_of_rings = -1;
this->downsampled_detectors_per_ring = -1;
this->remove_interleaving = true;
this->atten_image_filename = "";
this->atten_coeff_filename = "";
Expand Down Expand Up @@ -124,6 +127,8 @@ 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 rings", &this->downsampled_number_of_rings);
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 @@ -597,7 +602,7 @@ ScatterEstimation::set_up()
}

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

// Check if Load a mask proj_data

Expand Down Expand Up @@ -834,7 +839,7 @@ ScatterEstimation::process_data()
float local_min_scale_value = 0.5f;
float local_max_scale_value = 0.5f;

stir::BSpline::BSplineType spline_type = stir::BSpline::quadratic;
stir::BSpline::BSplineType spline_type = stir::BSpline::linear;
markus-jehl marked this conversation as resolved.
Show resolved Hide resolved

// This has been set to 2D or 3D in the set_up()
shared_ptr<ProjData> unscaled_est_projdata_sptr(
Expand Down Expand Up @@ -1026,16 +1031,13 @@ ScatterEstimation::process_data()
shared_ptr<BinNormalisation> normalisation_factors_3d_sptr
= this->get_normalisation_object_sptr(this->multiplicative_binnorm_sptr);

upsample_and_fit_scatter_estimate(*scatter_estimate_sptr,
*this->input_projdata_sptr,
*temp_projdata,
*normalisation_factors_3d_sptr,
*this->input_projdata_sptr,
1.0f,
1.0f,
1,
spline_type,
false);
ProjDataInMemory interpolated_scatter(this->input_projdata_sptr->get_exam_info_sptr(),
this->input_projdata_sptr->get_proj_data_info_sptr()->create_shared_clone());
inverse_SSRB(interpolated_scatter, *temp_projdata);
normalisation_factors_3d_sptr->set_up(this->input_projdata_sptr->get_exam_info_sptr(),
this->input_projdata_sptr->get_proj_data_info_sptr()->create_shared_clone());
normalisation_factors_3d_sptr->undo(interpolated_scatter);
scatter_estimate_sptr->fill(interpolated_scatter);
}
else
{
Expand Down
40 changes: 36 additions & 4 deletions src/scatter_buildblock/ScatterSimulation.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -841,19 +841,51 @@ 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();
}

// STIR does not like block spacings that are smaller than number of crystals times crystal spacing,
// therefore add a 1% extension on top for the downsampled scanner, to avoid running into floating point issues
const float block_spacing_factor = 1.01;

// 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, but place crystals equidistantly
float scanner_length = old_scanner_ptr->get_axial_length();
float new_ring_spacing = scanner_length / (new_num_rings - 1);

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_rings(new_num_rings);
new_scanner_sptr->set_num_detectors_per_ring(new_num_dets);

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 * block_spacing_factor);

float transaxial_bucket_width
= old_scanner_ptr->get_transaxial_block_spacing() * (old_scanner_ptr->get_num_transaxial_blocks_per_bucket() - 1)
+ old_scanner_ptr->get_transaxial_crystal_spacing() * (old_scanner_ptr->get_num_transaxial_crystals_per_block() - 1);

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
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_width / (new_transaxial_dets_per_bucket - 1);

new_scanner_sptr->set_num_transaxial_blocks_per_bucket(1);
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_transaxial_dets_per_bucket * new_det_spacing * block_spacing_factor);
markus-jehl marked this conversation as resolved.
Show resolved Hide resolved
// avoid problems with Scanner checks by setting singles_units to 1 crystal
// (only used for dead-time processing in ECAY norm)
new_scanner_sptr->set_num_axial_crystals_per_singles_unit(1);
new_scanner_sptr->set_num_transaxial_crystals_per_singles_unit(1);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ set(buildblock_simple_tests
include(stir_test_exe_targets)

foreach(source ${buildblock_simple_tests})
create_stir_test(${source} "buildblock;IO;buildblock;numerics_buildblock;display;IO;recon_buildblock;Shape_buildblock" "")
create_stir_test(${source} "buildblock;IO;buildblock;numerics_buildblock;display;IO;recon_buildblock;Shape_buildblock;scatter_buildblock" "")
endforeach()
#

Expand Down
Loading
Loading