STIR 6.4.0
ReconstructionTests.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2020, University College London
3 This file is part of STIR.
4 SPDX-License-Identifier: Apache-2.0
5 See STIR/LICENSE.txt for details
6*/
13
14#include "stir/RunTests.h"
22#include "stir/ArrayFunction.h"
24#include "stir/Verbosity.h"
25#include "stir/error.h"
26
27START_NAMESPACE_STIR
28
33template <class TargetT>
35{
36public:
38 explicit inline ReconstructionTests(const std::string& proj_data_filename = "", const std::string& density_filename = "");
39
40 ~ReconstructionTests() override {}
41
43 virtual inline std::unique_ptr<ProjDataInfo> construct_default_proj_data_info_uptr() const;
44
46
51 virtual inline void construct_input_data();
53
54 virtual inline void construct_reconstructor() = 0;
56
59 virtual inline void reconstruct(shared_ptr<TargetT> target_sptr);
61
62 virtual inline void compare(const shared_ptr<const TargetT> output_sptr);
63
64protected:
65 std::string _proj_data_filename;
66 std::string _input_density_filename;
67 shared_ptr<ProjDataInMemory> _proj_data_sptr;
68 shared_ptr<TargetT> _input_density_sptr;
69 shared_ptr<Reconstruction<TargetT>> _recon_sptr;
70};
71
72template <class TargetT>
73ReconstructionTests<TargetT>::ReconstructionTests(const std::string& proj_data_filename, const std::string& density_filename)
74 : _proj_data_filename(proj_data_filename),
75 _input_density_filename(density_filename)
76{}
77
78template <class TargetT>
79std::unique_ptr<ProjDataInfo>
81{
82 // construct a small scanner and sinogram
83 shared_ptr<Scanner> scanner_sptr(new Scanner(Scanner::E953));
84 scanner_sptr->set_num_rings(5);
85 std::unique_ptr<ProjDataInfo> proj_data_info_uptr(ProjDataInfo::ProjDataInfoCTI(scanner_sptr,
86 /*span=*/3,
87 /*max_delta=*/4,
88 /*num_views=*/128,
89 /*num_tang_poss=*/128));
90 return proj_data_info_uptr;
91}
92
93template <class TargetT>
94void
96{
97 Verbosity::set(1);
98 if (this->_proj_data_filename.empty())
99 {
100 shared_ptr<ProjDataInfo> proj_data_info_sptr(this->construct_default_proj_data_info_uptr());
101 shared_ptr<ExamInfo> exam_info_sptr(new ExamInfo);
102 exam_info_sptr->imaging_modality = ImagingModality::PT;
103 _proj_data_sptr.reset(new ProjDataInMemory(exam_info_sptr, proj_data_info_sptr));
104
105 std::cerr << "Will run tests with projection data with the following settings:\n" << proj_data_info_sptr->parameter_info();
106 }
107 else
108 {
109 shared_ptr<ProjData> proj_data_sptr = ProjData::read_from_file(this->_proj_data_filename);
110 _proj_data_sptr.reset(new ProjDataInMemory(*proj_data_sptr));
111 }
112
113 if (this->_input_density_filename.empty())
114 {
115 CartesianCoordinate3D<float> origin(0, 0, 0);
116 const float zoom = .7F;
117
118 shared_ptr<VoxelsOnCartesianGrid<float>> vox_sptr(new VoxelsOnCartesianGrid<float>(
119 this->_proj_data_sptr->get_exam_info_sptr(), *this->_proj_data_sptr->get_proj_data_info_sptr(), zoom, origin));
120
121 // create very long cylinder, such that we don't have to think about origin
122 EllipsoidalCylinder cylinder(/*length_z*/ 1000.F,
123 /*radius_y*/ 100.F,
124 /*radius_x*/ 90.F,
125 CartesianCoordinate3D<float>(0.F, 0.F, 0.F));
126 cylinder.construct_volume(*vox_sptr, CartesianCoordinate3D<int>(2, 2, 2));
127
128 // filter it a bit to avoid too high frequency stuff creating trouble in the comparison
130 filter.set_fwhms(make_coordinate(10.F, 10.F, 10.F));
131 filter.set_up(*vox_sptr);
132 filter.apply(*vox_sptr);
133 this->_input_density_sptr = vox_sptr;
134 }
135 else
136 {
137 shared_ptr<TargetT> aptr(read_from_file<TargetT>(this->_input_density_filename));
138 this->_input_density_sptr = aptr;
139 }
140
141 // forward project
142 {
143 shared_ptr<ProjMatrixByBin> PM_sptr(new ProjMatrixByBinUsingRayTracing);
144 shared_ptr<ForwardProjectorByBin> fwd_proj_sptr = MAKE_SHARED<ForwardProjectorByBinUsingProjMatrixByBin>(PM_sptr);
145 fwd_proj_sptr->set_up(this->_proj_data_sptr->get_proj_data_info_sptr(), this->_input_density_sptr);
146 fwd_proj_sptr->set_input(*this->_input_density_sptr);
147 fwd_proj_sptr->forward_project(*this->_proj_data_sptr);
148 }
149}
150
151template <class TargetT>
152void
153ReconstructionTests<TargetT>::reconstruct(shared_ptr<TargetT> target_sptr)
154{
155 this->_recon_sptr->set_input_data(this->_proj_data_sptr);
156 this->_recon_sptr->set_disable_output(true);
157 // set a prefix anyway, as some reconstruction algorithms write some files even with disabled output
158 this->_recon_sptr->set_output_filename_prefix("test_recon_" + this->_recon_sptr->method_info());
159 if (this->_recon_sptr->set_up(target_sptr) == Succeeded::no)
160 error("recon::set_up() failed");
161
162 if (this->_recon_sptr->reconstruct(target_sptr) == Succeeded::no)
163 error("recon::reconstruct() failed");
164
165 std::cerr << "\n================================\nReconstruction " << this->_recon_sptr->method_info() << " finished!\n\n";
166}
167
168template <class TargetT>
169void
170ReconstructionTests<TargetT>::compare(const shared_ptr<const TargetT> output_sptr)
171{
172 if (!check(this->_input_density_sptr->has_same_characteristics(*output_sptr), "output image has wrong characteristics"))
173 return;
174
175 shared_ptr<TargetT> diff_sptr(output_sptr->clone());
176 *diff_sptr -= *this->_input_density_sptr;
177 const float diff_min = diff_sptr->find_min();
178 const float diff_max = diff_sptr->find_max();
179 const float max_input = this->_input_density_sptr->find_max();
180 in_place_abs(*diff_sptr);
181 const float mean_abs_error = diff_sptr->sum() / this->_input_density_sptr->size_all();
182 std::cerr << "Reconstruction diff relative range: "
183 << "[" << diff_min / max_input << ", " << diff_max / max_input << "]\n"
184 << "mean abs diff normalised was " << mean_abs_error / max_input << "\n";
185 if (!check_if_less(-0.3F, diff_min / max_input, "relative diff min")
186 || !check_if_less(diff_max / max_input, .3F, "relative diff max")
187 || !check_if_less(mean_abs_error / max_input, .01F, "relative mean abs diff"))
188 {
189 const std::string prefix = "test_recon_" + this->_recon_sptr->method_info();
190 write_to_file(prefix + "_output.hv", *output_sptr);
191 write_to_file(prefix + "_original.hv", *this->_input_density_sptr);
192 write_to_file(prefix + "_diff.hv", *diff_sptr);
193 }
194}
195
196END_NAMESPACE_STIR
This include file provides some additional functionality for stir::Array objects.
Declaration of class stir::EllipsoidalCylinder.
definition of stir::ForwardProjectorByBinUsingProjMatrixByBin
Declaration of class stir::ProjDataInMemory.
stir::ProjMatrixByBinUsingRayTracing's definition
declares the stir::Reconstruction class
defines the stir::RunTests class
Declaration of class stir::Verbosity.
a templated class for 3-dimensional coordinates.
Definition CartesianCoordinate3D.h:53
Succeeded apply(DataT &data)
Calls set_up() (if not already done before) and process data in-place.
Definition DataProcessor.inl:66
Succeeded set_up(const DataT &data)
Initialises any internal data (if necessary) using data as a template for sizes, sampling distances e...
Definition DataProcessor.inl:32
Three-dimensional ellipsoidal cylinder.
Definition EllipsoidalCylinder.h:68
a class for storing information about 1 exam (or scan)
Definition ExamInfo.h:42
A class which reads/writes projection data from/to memory.
Definition ProjDataInMemory.h:39
static ProjDataInfo * ProjDataInfoCTI(const shared_ptr< Scanner > &scanner_ptr, const int span, const int max_delta, const int num_views, const int num_tangential_poss, const bool arc_corrected=true, const int tof_mash_factor=0)
Old name for construct_proj_data_info()
Definition ProjDataInfo.cxx:489
static shared_ptr< ProjData > read_from_file(const std::string &filename, const std::ios::openmode open_mode=std::ios::in)
A static member to get the projection data from a file.
Definition ProjData.cxx:89
Computes projection matrix elements for VoxelsOnCartesianGrid images by using a Length of Intersectio...
Definition ProjMatrixByBinUsingRayTracing.h:114
virtual void construct_input_data()
creates input
Definition ReconstructionTests.h:95
ReconstructionTests(const std::string &proj_data_filename="", const std::string &density_filename="")
Constructor that can take some input data to run the test with.
Definition ReconstructionTests.h:73
virtual std::unique_ptr< ProjDataInfo > construct_default_proj_data_info_uptr() const
default proj_data_info
Definition ReconstructionTests.h:80
virtual void compare(const shared_ptr< const TargetT > output_sptr)
compares output and input
Definition ReconstructionTests.h:170
virtual void construct_reconstructor()=0
creates the reconstruction object
virtual void reconstruct(shared_ptr< TargetT > target_sptr)
perform reconstruction
Definition ReconstructionTests.h:153
bool check_if_less(T1 a, T2 b, const std::string &str="")
check if a<b
Definition RunTests.h:517
bool check(const bool, const std::string &str="")
Tests if true, str can be used to tell what you are testing.
Definition RunTests.h:347
RunTests(const double tolerance=1E-4)
Default constructor.
Definition RunTests.h:305
A class for storing some info on the scanner.
Definition Scanner.h:108
A class in the DataProcessor hierarchy that implements Gaussian filtering.
Definition SeparableGaussianImageFilter.h:54
virtual void construct_volume(VoxelsOnCartesianGrid< float > &image, const CartesianCoordinate3D< int > &num_samples) const
construct an image representation the shape in a discretised manner
Definition Shape3D.cxx:101
This class is used to represent voxelised densities on a cuboid grid (3D).
Definition VoxelsOnCartesianGrid.h:46
Declaration of stir::error()
Array< 1, elemT > & in_place_abs(Array< 1, elemT > &v)
Replace elements by their absolute value, 1D version.
Definition ArrayFunction.inl:82
unique_ptr< DataT > read_from_file(const FileSignature &signature, FileT file)
Function that reads data from file using the default InputFileFormatRegistry, using the provided File...
Definition read_from_file.h:46
std::string write_to_file(const std::string &filename, const DataT &data)
Function that writes data to file using the default OutputFileFormat.
Definition write_to_file.h:46
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition error.cxx:42
Declaration of stir::read_from_file functions (providing easy access to class stir::InputFileFormatRe...
#define MAKE_SHARED
work-around for using std::make_shared on old compilers (deprecated)
Definition shared_ptr.h:31
Declaration of class stir::SeparableGaussianImageFilter.
Declaration of stir::write_to_file function (providing easy access to the default stir::OutputFileFor...