STIR 6.5.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 scanner_sptr->set_up();
86 std::unique_ptr<ProjDataInfo> proj_data_info_uptr(ProjDataInfo::ProjDataInfoCTI(scanner_sptr,
87 /*span=*/3,
88 /*max_delta=*/4,
89 /*num_views=*/128,
90 /*num_tang_poss=*/128,
91 /* arc-corrected = */ false));
92 return proj_data_info_uptr;
93}
94
95template <class TargetT>
96void
98{
99 Verbosity::set(1);
100 if (this->_proj_data_filename.empty())
101 {
102 shared_ptr<ProjDataInfo> proj_data_info_sptr(this->construct_default_proj_data_info_uptr());
103 shared_ptr<ExamInfo> exam_info_sptr(new ExamInfo);
104 exam_info_sptr->imaging_modality = ImagingModality::PT;
105 _proj_data_sptr.reset(new ProjDataInMemory(exam_info_sptr, proj_data_info_sptr));
106
107 std::cerr << "Will run tests with projection data with the following settings:\n" << proj_data_info_sptr->parameter_info();
108 }
109 else
110 {
111 shared_ptr<ProjData> proj_data_sptr = ProjData::read_from_file(this->_proj_data_filename);
112 _proj_data_sptr.reset(new ProjDataInMemory(*proj_data_sptr));
113 }
114
115 if (this->_input_density_filename.empty())
116 {
117 CartesianCoordinate3D<float> origin(0, 0, 0);
118 const float zoom = .7F;
119
120 shared_ptr<VoxelsOnCartesianGrid<float>> vox_sptr(new VoxelsOnCartesianGrid<float>(
121 this->_proj_data_sptr->get_exam_info_sptr(), *this->_proj_data_sptr->get_proj_data_info_sptr(), zoom, origin));
122
123 // create very long cylinder, such that we don't have to think about origin
124 EllipsoidalCylinder cylinder(/*length_z*/ 1000.F,
125 /*radius_y*/ 100.F,
126 /*radius_x*/ 90.F,
127 CartesianCoordinate3D<float>(0.F, 0.F, 0.F));
128 cylinder.construct_volume(*vox_sptr, CartesianCoordinate3D<int>(2, 2, 2));
129
130 // filter it a bit to avoid too high frequency stuff creating trouble in the comparison
132 filter.set_fwhms(make_coordinate(10.F, 10.F, 10.F));
133 filter.set_up(*vox_sptr);
134 filter.apply(*vox_sptr);
135 this->_input_density_sptr = vox_sptr;
136 }
137 else
138 {
139 shared_ptr<TargetT> aptr(read_from_file<TargetT>(this->_input_density_filename));
140 this->_input_density_sptr = aptr;
141 }
142
143 // forward project
144 {
145 shared_ptr<ProjMatrixByBin> PM_sptr(new ProjMatrixByBinUsingRayTracing);
146 shared_ptr<ForwardProjectorByBin> fwd_proj_sptr = MAKE_SHARED<ForwardProjectorByBinUsingProjMatrixByBin>(PM_sptr);
147 fwd_proj_sptr->set_up(this->_proj_data_sptr->get_proj_data_info_sptr(), this->_input_density_sptr);
148 fwd_proj_sptr->set_input(*this->_input_density_sptr);
149 fwd_proj_sptr->forward_project(*this->_proj_data_sptr);
150 }
151}
152
153template <class TargetT>
154void
155ReconstructionTests<TargetT>::reconstruct(shared_ptr<TargetT> target_sptr)
156{
157 this->_recon_sptr->set_input_data(this->_proj_data_sptr);
158 this->_recon_sptr->set_disable_output(true);
159 // set a prefix anyway, as some reconstruction algorithms write some files even with disabled output
160 this->_recon_sptr->set_output_filename_prefix("test_recon_" + this->_recon_sptr->method_info());
161 if (this->_recon_sptr->set_up(target_sptr) == Succeeded::no)
162 error("recon::set_up() failed");
163
164 if (this->_recon_sptr->reconstruct(target_sptr) == Succeeded::no)
165 error("recon::reconstruct() failed");
166
167 std::cerr << "\n================================\nReconstruction " << this->_recon_sptr->method_info() << " finished!\n\n";
168}
169
170template <class TargetT>
171void
172ReconstructionTests<TargetT>::compare(const shared_ptr<const TargetT> output_sptr)
173{
174 if (!check(this->_input_density_sptr->has_same_characteristics(*output_sptr), "output image has wrong characteristics"))
175 return;
176
177 shared_ptr<TargetT> diff_sptr(output_sptr->clone());
178 *diff_sptr -= *this->_input_density_sptr;
179 const float diff_min = diff_sptr->find_min();
180 const float diff_max = diff_sptr->find_max();
181 const float max_input = this->_input_density_sptr->find_max();
182 in_place_abs(*diff_sptr);
183 const float mean_abs_error = diff_sptr->sum() / this->_input_density_sptr->size_all();
184 std::cerr << "Reconstruction diff relative range: "
185 << "[" << diff_min / max_input << ", " << diff_max / max_input << "]\n"
186 << "mean abs diff normalised was " << mean_abs_error / max_input << "\n";
187 if (!check_if_less(-0.3F, diff_min / max_input, "relative diff min")
188 || !check_if_less(diff_max / max_input, .3F, "relative diff max")
189 || !check_if_less(mean_abs_error / max_input, .01F, "relative mean abs diff"))
190 {
191 const std::string prefix = "test_recon_" + this->_recon_sptr->method_info();
192 write_to_file(prefix + "_output.hv", *output_sptr);
193 write_to_file(prefix + "_original.hv", *this->_input_density_sptr);
194 write_to_file(prefix + "_diff.hv", *diff_sptr);
195 }
196}
197
198END_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
ProjDataInMemory(shared_ptr< const ExamInfo > const &exam_info_sptr, shared_ptr< const ProjDataInfo > const &proj_data_info_ptr, const bool initialise_with_0=true)
constructor with only info, but no data
Definition ProjDataInMemory.cxx:49
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:488
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:97
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:172
virtual void construct_reconstructor()=0
creates the reconstruction object
virtual void reconstruct(shared_ptr< TargetT > target_sptr)
perform reconstruction
Definition ReconstructionTests.h:155
bool check_if_less(T1 a, T2 b, const std::string &str="")
check if a<b
Definition RunTests.h:543
bool check(const bool, const std::string &str="")
Tests if true, str can be used to tell what you are testing.
Definition RunTests.h:358
RunTests(const double tolerance=1E-4)
Default constructor.
Definition RunTests.h:316
Scanner(Type scanner_type)
constructor that takes scanner type as an input argument
Definition Scanner.cxx:65
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:83
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...