diff --git a/src/include/stir/recon_buildblock/Parallelproj_projector/BackProjectorByBinParallelproj.h b/src/include/stir/recon_buildblock/Parallelproj_projector/BackProjectorByBinParallelproj.h index e7338c4eb2..91f69f408a 100644 --- a/src/include/stir/recon_buildblock/Parallelproj_projector/BackProjectorByBinParallelproj.h +++ b/src/include/stir/recon_buildblock/Parallelproj_projector/BackProjectorByBinParallelproj.h @@ -95,6 +95,9 @@ class BackProjectorByBinParallelproj : public RegisteredParsingObject&, const int min_axial_pos_num, @@ -111,6 +114,7 @@ class BackProjectorByBinParallelproj : public RegisteredParsingObject); bool _cuda_verbosity; int _num_gpu_chunks; + bool _restrict_to_cylindrical_FOV; }; END_NAMESPACE_STIR diff --git a/src/include/stir/recon_buildblock/Parallelproj_projector/ForwardProjectorByBinParallelproj.h b/src/include/stir/recon_buildblock/Parallelproj_projector/ForwardProjectorByBinParallelproj.h index 42566853ac..88125eecc2 100644 --- a/src/include/stir/recon_buildblock/Parallelproj_projector/ForwardProjectorByBinParallelproj.h +++ b/src/include/stir/recon_buildblock/Parallelproj_projector/ForwardProjectorByBinParallelproj.h @@ -80,14 +80,13 @@ class ForwardProjectorByBinParallelproj : public RegisteredParsingObject& viewgrams, const int min_axial_pos_num, @@ -103,7 +102,7 @@ class ForwardProjectorByBinParallelproj : public RegisteredParsingObject); bool _cuda_verbosity; - bool _use_truncation; + bool _restrict_to_cylindrical_FOV; int _num_gpu_chunks; }; diff --git a/src/include/stir/recon_buildblock/Parallelproj_projector/ProjectorByBinPairUsingParallelproj.h b/src/include/stir/recon_buildblock/Parallelproj_projector/ProjectorByBinPairUsingParallelproj.h index bd83489c0f..c05e98c446 100644 --- a/src/include/stir/recon_buildblock/Parallelproj_projector/ProjectorByBinPairUsingParallelproj.h +++ b/src/include/stir/recon_buildblock/Parallelproj_projector/ProjectorByBinPairUsingParallelproj.h @@ -53,6 +53,9 @@ class ProjectorByBinPairUsingParallelproj /// Set verbosity void set_verbosity(const bool verbosity); + bool get_restrict_to_cylindrical_FOV() const; + void set_restrict_to_cylindrical_FOV(bool val); + private: shared_ptr _helper; @@ -60,6 +63,8 @@ class ProjectorByBinPairUsingParallelproj void initialise_keymap() override; bool post_processing() override; bool _verbosity; + bool _restrict_to_cylindrical_FOV; + bool _already_set_up; }; END_NAMESPACE_STIR diff --git a/src/recon_buildblock/Parallelproj_projector/BackProjectorByBinParallelproj.cxx b/src/recon_buildblock/Parallelproj_projector/BackProjectorByBinParallelproj.cxx index 692b92d582..96f1db3768 100644 --- a/src/recon_buildblock/Parallelproj_projector/BackProjectorByBinParallelproj.cxx +++ b/src/recon_buildblock/Parallelproj_projector/BackProjectorByBinParallelproj.cxx @@ -63,6 +63,7 @@ BackProjectorByBinParallelproj::initialise_keymap() parser.add_start_key("Back Projector Using Parallelproj Parameters"); parser.add_stop_key("End Back Projector Using Parallelproj Parameters"); parser.add_key("verbosity", &_cuda_verbosity); + parser.add_key("restrict to cylindrical FOV", &_restrict_to_cylindrical_FOV); parser.add_key("num_gpu_chunks", &_num_gpu_chunks); } @@ -71,6 +72,19 @@ BackProjectorByBinParallelproj::set_defaults() { _cuda_verbosity = true; _num_gpu_chunks = 1; + _restrict_to_cylindrical_FOV = true; +} + +bool +BackProjectorByBinParallelproj::get_restrict_to_cylindrical_FOV() const +{ + return this->_restrict_to_cylindrical_FOV; +} + +void +BackProjectorByBinParallelproj::set_restrict_to_cylindrical_FOV(bool val) +{ + this->_restrict_to_cylindrical_FOV = val; } void @@ -289,15 +303,12 @@ BackProjectorByBinParallelproj::get_output(DiscretisedDensity<3, float>& density std::copy(image_vec.begin(), image_vec.end(), density.begin_all()); } - // After the back projection, we enforce a truncation outside of the FOV. - // This is because the parallelproj projector seems to have some trouble at the edges and this - // could cause some voxel values to spiral out of control. - // if (_use_truncation) - { - const float radius = p.get_proj_data_info_sptr()->get_scanner_sptr()->get_inner_ring_radius(); - const float image_radius = _helper->voxsize[2] * _helper->imgdim[2] / 2; - truncate_rim(density, static_cast(std::max((image_radius - radius) / _helper->voxsize[2], 0.F))); - } + if (this->_restrict_to_cylindrical_FOV) + { + const float radius = p.get_proj_data_info_sptr()->get_scanner_sptr()->get_inner_ring_radius(); + const float image_radius = _helper->voxsize[2] * _helper->imgdim[2] / 2; + truncate_rim(density, static_cast(std::max((image_radius - radius) / _helper->voxsize[2], 0.F))); + } } void diff --git a/src/recon_buildblock/Parallelproj_projector/ForwardProjectorByBinParallelproj.cxx b/src/recon_buildblock/Parallelproj_projector/ForwardProjectorByBinParallelproj.cxx index ac4a3704c1..d718ffbff1 100644 --- a/src/recon_buildblock/Parallelproj_projector/ForwardProjectorByBinParallelproj.cxx +++ b/src/recon_buildblock/Parallelproj_projector/ForwardProjectorByBinParallelproj.cxx @@ -43,7 +43,7 @@ const char* const ForwardProjectorByBinParallelproj::registered_name = "Parallel ForwardProjectorByBinParallelproj::ForwardProjectorByBinParallelproj() : _cuda_verbosity(true), - _use_truncation(true), + _restrict_to_cylindrical_FOV(true), _num_gpu_chunks(1) { this->_already_set_up = false; @@ -59,6 +59,7 @@ ForwardProjectorByBinParallelproj::initialise_keymap() parser.add_start_key("Forward Projector Using Parallelproj Parameters"); parser.add_stop_key("End Forward Projector Using Parallelproj Parameters"); parser.add_key("verbosity", &_cuda_verbosity); + parser.add_key("restrict to cylindrical FOV", &_restrict_to_cylindrical_FOV); parser.add_key("num_gpu_chunks", &_num_gpu_chunks); } @@ -66,10 +67,22 @@ void ForwardProjectorByBinParallelproj::set_defaults() { _cuda_verbosity = true; - _use_truncation = true; + _restrict_to_cylindrical_FOV = true; _num_gpu_chunks = 1; } +bool +ForwardProjectorByBinParallelproj::get_restrict_to_cylindrical_FOV() const +{ + return this->_restrict_to_cylindrical_FOV; +} + +void +ForwardProjectorByBinParallelproj::set_restrict_to_cylindrical_FOV(bool val) +{ + this->_restrict_to_cylindrical_FOV = val; +} + void ForwardProjectorByBinParallelproj::set_helper(shared_ptr helper) { @@ -144,15 +157,12 @@ ForwardProjectorByBinParallelproj::set_input(const DiscretisedDensity<3, float>& { ForwardProjectorByBin::set_input(density); - // Before forward projection, we enforce a truncation outside of the FOV. - // This is because the parallelproj projector seems to have some trouble at the edges and this - // could cause some voxel values to spiral out of control. - // if (_use_truncation) - { - const float radius = this->_proj_data_info_sptr->get_scanner_sptr()->get_inner_ring_radius(); - const float image_radius = _helper->voxsize[2] * _helper->imgdim[2] / 2; - truncate_rim(*_density_sptr, static_cast(std::max((image_radius - radius) / _helper->voxsize[2], 0.F))); - } + if (this->_restrict_to_cylindrical_FOV) + { + const float radius = this->_proj_data_info_sptr->get_scanner_sptr()->get_inner_ring_radius(); + const float image_radius = _helper->voxsize[2] * _helper->imgdim[2] / 2; + truncate_rim(*_density_sptr, static_cast(std::max((image_radius - radius) / _helper->voxsize[2], 0.F))); + } std::vector image_vec; float* image_ptr; diff --git a/src/recon_buildblock/Parallelproj_projector/ProjectorByBinPairUsingParallelproj.cxx b/src/recon_buildblock/Parallelproj_projector/ProjectorByBinPairUsingParallelproj.cxx index ea35717f35..7452bcd5ae 100644 --- a/src/recon_buildblock/Parallelproj_projector/ProjectorByBinPairUsingParallelproj.cxx +++ b/src/recon_buildblock/Parallelproj_projector/ProjectorByBinPairUsingParallelproj.cxx @@ -34,6 +34,7 @@ ProjectorByBinPairUsingParallelproj::initialise_keymap() parser.add_start_key("Projector Pair Using Parallelproj Parameters"); parser.add_stop_key("End Projector Pair Using Parallelproj Parameters"); parser.add_key("verbosity", &_verbosity); + parser.add_key("restrict to cylindrical FOV", &_restrict_to_cylindrical_FOV); } void @@ -41,6 +42,8 @@ ProjectorByBinPairUsingParallelproj::set_defaults() { base_type::set_defaults(); this->set_verbosity(true); + this->set_restrict_to_cylindrical_FOV(true); + this->_already_set_up = false; } bool @@ -60,6 +63,19 @@ ProjectorByBinPairUsingParallelproj::ProjectorByBinPairUsingParallelproj() set_defaults(); } +bool +ProjectorByBinPairUsingParallelproj::get_restrict_to_cylindrical_FOV() const +{ + return this->_restrict_to_cylindrical_FOV; +} + +void +ProjectorByBinPairUsingParallelproj::set_restrict_to_cylindrical_FOV(bool val) +{ + this->_already_set_up = this->_already_set_up && (this->_restrict_to_cylindrical_FOV == val); + this->_restrict_to_cylindrical_FOV = val; +} + BackProjectorByBinParallelproj* BackProjectorByBinParallelproj::clone() const { @@ -70,15 +86,26 @@ Succeeded ProjectorByBinPairUsingParallelproj::set_up(const shared_ptr& proj_data_info_sptr, const shared_ptr>& image_info_sptr) { - _helper = std::make_shared(*proj_data_info_sptr, *image_info_sptr); - dynamic_pointer_cast(this->forward_projector_sptr)->set_helper(_helper); - dynamic_pointer_cast(this->back_projector_sptr)->set_helper(_helper); + auto fwd_prj_downcast_sptr = dynamic_pointer_cast(this->forward_projector_sptr); + if (!fwd_prj_downcast_sptr) + error("internal error: forward projector should be ParallelProj"); + + auto bck_prj_downcast_sptr = dynamic_pointer_cast(this->back_projector_sptr); + if (!bck_prj_downcast_sptr) + error("internal error: back projector should be ParallelProj"); + + bck_prj_downcast_sptr->set_restrict_to_cylindrical_FOV(this->_restrict_to_cylindrical_FOV); + fwd_prj_downcast_sptr->set_restrict_to_cylindrical_FOV(this->_restrict_to_cylindrical_FOV); + this->_helper = std::make_shared(*proj_data_info_sptr, *image_info_sptr); + fwd_prj_downcast_sptr->set_helper(this->_helper); + bck_prj_downcast_sptr->set_helper(this->_helper); // the forward_projector->set_up etc will be called in the base class if (base_type::set_up(proj_data_info_sptr, image_info_sptr) != Succeeded::yes) return Succeeded::no; + this->_already_set_up = true; return Succeeded::yes; }