STIR 6.4.0
ModelMatrix.inl
1//
2//
3/*
4 Copyright (C) 2006 - 2011, Hammersmith Imanet Ltd
5 This file is part of STIR.
6
7 SPDX-License-Identifier: Apache-2.0
8
9 See STIR/LICENSE.txt for details
10
11 \file
12 \ingroup modelling
13
14 \brief Implementations of inline functions of class stir::ModelMatrix
15
16 \author Charalampos Tsoumpas
17
18*/
19
20#include <algorithm>
21#include "stir/warning.h"
22#include "stir/error.h"
23START_NAMESPACE_STIR
24
26template <int num_param>
28{
29 // Calibrated ModelMatrix means that the counts are in kBq/ml, while uncalibrated means that it will be to the same units as the
30 // reconstructed images.
31 this->_is_uncalibrated = false;
32 // Converted ModelMatrix means that it is in total counts in respect to the time_frame_duration, while false means that it will
33 // be in mean count rate.
34 this->_in_correct_scale = false;
35 this->_is_converted_to_total_counts = false;
36}
37
39template <int num_param>
42
44template <int num_param>
45void
46ModelMatrix<num_param>::read_from_file(const std::string input_string)
47{
48 std::ifstream data_stream(input_string.c_str());
49 unsigned int starting_frame, last_frame;
50 if (!data_stream)
51 error("cannot read model matrix from file.\n");
52 else
53 {
54 data_stream >> starting_frame;
55 data_stream >> last_frame;
56 }
57
60 min_range[1] = 1;
61 min_range[2] = starting_frame;
62 max_range[1] = num_param;
63 max_range[2] = last_frame;
64 IndexRange<2> data_range(min_range, max_range);
65 Array<2, float> input_array(data_range);
66 while (true)
67 {
68 for (unsigned int frame_num = starting_frame; frame_num <= last_frame; ++frame_num)
69 for (int param_num = 1; param_num <= num_param; ++param_num)
70 data_stream >> input_array[param_num][frame_num];
71 if (!data_stream)
72 break;
73 }
74 this->_model_array = input_array; // I do not pass info if it is calibrated and if it includes time frame_duration, yet.
75}
76
78template <int num_param>
80ModelMatrix<num_param>::write_to_file(const std::string output_string)
81{
82
83 BasicCoordinate<2, int> model_array_min, model_array_max;
84 if (!(this->_model_array).get_regular_range(model_array_min, model_array_max))
85 error("Model array has not regular range");
86 unsigned int starting_frame = model_array_min[2], last_frame = model_array_max[2];
87
88 std::ofstream data_stream(output_string.c_str(), std::ios::out);
89 if (!data_stream)
90 {
91 warning("ModelMatrix<num_param>::write_to_file: error opening output file %s\n", output_string.c_str());
92 return Succeeded::no;
93 }
94 else
95 {
96 data_stream << starting_frame << " ";
97 data_stream << last_frame << " ";
98 }
99
100 // It will be good to assert that there will be no writing error.
101 for (unsigned int frame_num = starting_frame; frame_num <= last_frame; ++frame_num)
102 {
103 data_stream << "\n";
104 for (int param_num = 1; param_num <= num_param; ++param_num)
105 data_stream << this->_model_array[param_num][frame_num] << " ";
106 }
107 data_stream.close();
108 return Succeeded::yes;
109}
110
111template <int num_param>
112void
113ModelMatrix<num_param>::set_model_array(const Array<2, float>& model_array)
114{
115 this->_model_array = model_array;
116}
117
118template <int num_param>
119Array<2, float>
120ModelMatrix<num_param>::get_model_array() const
121{
122 return this->_model_array;
123}
124
125template <int num_param>
126const VectorWithOffset<float>
127ModelMatrix<num_param>::get_model_array_sum() const
128{
129 BasicCoordinate<2, int> model_array_min, model_array_max;
130 if (!(this->_model_array).get_regular_range(model_array_min, model_array_max))
131 error("Model array has not regular range");
132 VectorWithOffset<float> sum(model_array_min[1], model_array_max[1]);
133 for (int param_num = model_array_min[1]; param_num <= model_array_max[1]; ++param_num)
134 {
135 sum[param_num] = 0.F;
136 for (int frame_num = model_array_min[2]; frame_num <= model_array_max[2]; ++frame_num)
137 sum[param_num] += this->_model_array[param_num][frame_num];
138 }
139 return sum;
140}
141
142template <int num_param>
143void
145{
146 BasicCoordinate<2, int> model_array_min, model_array_max;
147 if (!(this->_model_array).get_regular_range(model_array_min, model_array_max))
148 error("Model array has not regular range");
149
150 for (int param_num = model_array_min[1]; param_num <= model_array_max[1]; ++param_num)
151 for (int frame_num = model_array_min[2]; frame_num <= model_array_max[2]; ++frame_num)
152 if (this->_model_array[param_num][frame_num] <= 0)
153 this->_model_array[param_num][frame_num] = threshold_value;
154}
155
156template <int num_param>
157void
159{
160 this->_is_uncalibrated = is_uncalibrated;
161}
162
163template <int num_param>
164void
165ModelMatrix<num_param>::set_is_in_correct_scale(const bool in_correct_scale)
166{
167 this->_in_correct_scale = in_correct_scale;
168}
169
170template <int num_param>
171void
173{
174 if (this->_is_uncalibrated)
175 warning("ModelMatrix is already uncalibrated, so it will be not re-uncalibrated.");
176 else
177 {
178 BasicCoordinate<2, int> model_array_min, model_array_max;
179 if (!(this->_model_array).get_regular_range(model_array_min, model_array_max))
180 error("Model array has not regular range");
181
182 for (int param_num = model_array_min[1]; param_num <= model_array_max[1]; ++param_num)
183 for (int frame_num = model_array_min[2]; frame_num <= model_array_max[2]; ++frame_num)
184 this->_model_array[param_num][frame_num] /= cal_factor;
185
187 }
188}
189
190template <int num_param>
191void
193{
194 if (this->_in_correct_scale)
195 warning("ModelMatrix is already scaled, so it will not be re-scaled. ");
196 else
197 {
198 BasicCoordinate<2, int> model_array_min, model_array_max;
199 if (!(this->_model_array).get_regular_range(model_array_min, model_array_max))
200 error("Model array has not regular range");
201 for (int param_num = model_array_min[1]; param_num <= model_array_max[1]; ++param_num)
202 for (int frame_num = model_array_min[2]; frame_num <= model_array_max[2]; ++frame_num)
203 this->_model_array[param_num][frame_num] *= scale_factor;
204
205 this->_in_correct_scale = true;
206 }
207}
208
209template <int num_param>
210void
212{
213 if (ModelMatrix<num_param>::_is_converted_to_total_counts == true)
214 warning("ModelMatrix is already converted to total counts, so it will not be re-converted. ");
215 else
216 {
217 BasicCoordinate<2, int> model_array_min, model_array_max;
218 if (!(this->_model_array).get_regular_range(model_array_min, model_array_max))
219 error("Model array has not regular range");
220 for (int param_num = model_array_min[1]; param_num <= model_array_max[1]; ++param_num)
221 for (int frame_num = model_array_min[2]; frame_num <= model_array_max[2]; ++frame_num)
222 this->_model_array[param_num][frame_num] *= static_cast<float>(time_frame_definitions.get_duration(frame_num));
223
224 this->_is_converted_to_total_counts = true;
225 }
226}
227
228template <int num_param>
229void
230ModelMatrix<num_param>::set_time_vector(const VectorWithOffset<float>& time_vector)
231{
232 this->_time_vector = time_vector;
233}
234
235template <int num_param>
236VectorWithOffset<float>
237ModelMatrix<num_param>::get_time_vector() const
238{
239 return this->_time_vector;
240}
241
242template <int num_param>
243void
245 const DynamicDiscretisedDensity& dynamic_image) const
246{
247 BasicCoordinate<2, int> model_array_min, model_array_max;
248 if (!this->_model_array.get_regular_range(model_array_min, model_array_max))
249 error("Model array has not regular range");
250
251 // Assert that the sizes of the one frame of the dynamic image is equal with the parametric image size.
252 // ChT::ToDo::Might be better to assert that each of the dimensions sizes with their voxle sizes are equal.
253 // Could probably use has_same_characteristics()?
254 assert(dynamic_image[1].size_all() == parametric_image.size_all());
255 assert(dynamic_image.get_time_frame_definitions().get_num_frames() == static_cast<unsigned int>(model_array_max[2]));
256 assert(model_array_max[1] - model_array_min[1] + 1 == num_param);
257
258 const int min_k_index = dynamic_image[1].get_min_index();
259 const int max_k_index = dynamic_image[1].get_max_index();
260 for (int k = min_k_index; k <= max_k_index; ++k)
261 {
262 const int min_j_index = dynamic_image[1][k].get_min_index();
263 const int max_j_index = dynamic_image[1][k].get_max_index();
264 for (int j = min_j_index; j <= max_j_index; ++j)
265 {
266 const int min_i_index = dynamic_image[1][k][j].get_min_index();
267 const int max_i_index = dynamic_image[1][k][j].get_max_index();
268 for (int i = min_i_index; i <= max_i_index; ++i)
269 for (int param_num = model_array_min[1]; param_num <= model_array_max[1]; ++param_num)
270 {
271 float sum_over_frames = 0.F;
272 for (int frame_num = model_array_min[2]; frame_num <= model_array_max[2]; ++frame_num)
273 sum_over_frames += this->_model_array[param_num][frame_num] * dynamic_image[frame_num][k][j][i];
274 parametric_image[k][j][i][param_num] += sum_over_frames;
275 }
276 }
277 }
278}
279
280template <int num_param>
281void
283 const DynamicDiscretisedDensity& dynamic_image) const
284{
285 std::fill(parametric_image.begin_all(), parametric_image.end_all(), 0.F);
286 this->multiply_dynamic_image_with_model_and_add_to_input(parametric_image, dynamic_image);
287}
288
289template <int num_param>
290void
292 DynamicDiscretisedDensity& dynamic_image, const ParametricVoxelsOnCartesianGrid& parametric_image) const
293{
294 BasicCoordinate<2, int> model_array_min, model_array_max;
295 if (!(this->_model_array).get_regular_range(model_array_min, model_array_max))
296 error("Model array does not have a regular range");
297
298 // Assert that the sizes of the one frame of the dynamic image is equal with the parametric image size.
299 // ChT::ToDo::Might be better to assert that each of the dimensions sizes with their voxle sizes are equal.
300 // Maybe this will be easier if I clone the single images for the two and then compare them.
301 assert(dynamic_image[1].size_all() == parametric_image.size_all());
302 assert(dynamic_image.get_time_frame_definitions().get_num_frames() == static_cast<unsigned int>(model_array_max[2]));
303 assert(model_array_max[1] - model_array_min[1] + 1 == num_param);
304
305 const int min_k_index = dynamic_image[1].get_min_index();
306 const int max_k_index = dynamic_image[1].get_max_index();
307 for (int k = min_k_index; k <= max_k_index; ++k)
308 {
309 const int min_j_index = dynamic_image[1][k].get_min_index();
310 const int max_j_index = dynamic_image[1][k].get_max_index();
311 for (int j = min_j_index; j <= max_j_index; ++j)
312 {
313 const int min_i_index = dynamic_image[1][k][j].get_min_index();
314 const int max_i_index = dynamic_image[1][k][j].get_max_index();
315 for (int i = min_i_index; i <= max_i_index; ++i)
316 for (int frame_num = model_array_min[2]; frame_num <= model_array_max[2]; ++frame_num)
317 {
318 float sum_over_param = 0.F;
319 for (int param_num = model_array_min[1]; param_num <= model_array_max[1]; ++param_num)
320 sum_over_param += parametric_image[k][j][i][param_num] * this->_model_array[param_num][frame_num];
321 dynamic_image[frame_num][k][j][i] = sum_over_param;
322 }
323 }
324 }
325}
326
327template <int num_param>
328void
330 const ParametricVoxelsOnCartesianGrid& parametric_image) const
331{
332 std::fill(dynamic_image.begin_all(), dynamic_image.end_all(), 0.F);
333 this->multiply_parametric_image_with_model_and_add_to_input(dynamic_image, parametric_image);
334}
335
336template <int num_param>
337void
338ModelMatrix<num_param>::normalise_parametric_image_with_model_sum(ParametricVoxelsOnCartesianGrid& parametric_image_out,
339 const ParametricVoxelsOnCartesianGrid& parametric_image) const
340{
341 BasicCoordinate<2, int> model_array_min, model_array_max;
342 if (!(this->_model_array).get_regular_range(model_array_min, model_array_max))
343 error("Model array has not regular range");
344
345 assert(parametric_image_out.size_all() == parametric_image.size_all());
346 assert(model_array_max[1] - model_array_min[1] + 1 == num_param);
347
348 const int min_k_index = parametric_image.construct_single_density(num_param).get_min_index();
349 const int max_k_index = parametric_image.construct_single_density(num_param).get_max_index();
350 for (int k = min_k_index; k <= max_k_index; ++k)
351 {
352 const int min_j_index = (parametric_image.construct_single_density(num_param))[k].get_min_index();
353 const int max_j_index = (parametric_image.construct_single_density(num_param))[k].get_max_index();
354 for (int j = min_j_index; j <= max_j_index; ++j)
355 {
356 const int min_i_index = (parametric_image.construct_single_density(num_param))[k][j].get_min_index();
357 const int max_i_index = (parametric_image.construct_single_density(num_param))[k][j].get_max_index();
358 for (int i = min_i_index; i <= max_i_index; ++i)
359 {
360 parametric_image_out[k][j][i][1] = parametric_image[k][j][i][1] / ((this->get_model_array_sum())[2]);
361 parametric_image_out[k][j][i][2] = parametric_image[k][j][i][2] / ((this->get_model_array_sum())[1]);
362 }
363 }
364 }
365}
366
367END_NAMESPACE_STIR
This class defines multi-dimensional (numeric) arrays.
Definition Array.h:78
size_t size_all() const
return the total number of elements in this array
Definition Array.inl:262
class BasicCoordinate<int num_dimensions, typename coordT> defines num_dimensions -dimensional coordi...
Definition BasicCoordinate.h:57
Class of multiple image frames, one for each time frame Each time frame is a DiscretisedDensity<3,...
Definition DynamicDiscretisedDensity.h:46
This class defines ranges which can be 'irregular'.
Definition IndexRange.h:69
void multiply_dynamic_image_with_model(ParametricVoxelsOnCartesianGrid &parametric_image, const DynamicDiscretisedDensity &dynamic_image) const
multiply (transpose) model-matrix with dynamic image (overwriting original content of parametric_imag...
Definition ModelMatrix.inl:282
void scale_model_matrix(const float scale_factor)
Definition ModelMatrix.inl:192
~ModelMatrix()
default destructor
Definition ModelMatrix.inl:40
void multiply_parametric_image_with_model(DynamicDiscretisedDensity &dynamic_image, const ParametricVoxelsOnCartesianGrid &parametric_image) const
multiply model-matrix with parametric image (overwriting original content of dynamic_image)
Definition ModelMatrix.inl:329
void threshold_model_array(const float threshold_value)
Function to give the threshold_value to the all elements of the model_array which lower value than th...
Definition ModelMatrix.inl:144
void read_from_file(const std::string input_string)
Implementation to read the model matrix.
Definition ModelMatrix.inl:46
Succeeded write_to_file(const std::string output_string)
Implementation to write the model matrix to a text file.
Definition ModelMatrix.inl:80
void multiply_parametric_image_with_model_and_add_to_input(DynamicDiscretisedDensity &dynamic_image, const ParametricVoxelsOnCartesianGrid &parametric_image) const
multiply model-matrix with parametric image and add result to original dynamic_image
Definition ModelMatrix.inl:291
void convert_to_total_frame_counts(const TimeFrameDefinitions &time_frame_definitions)
Definition ModelMatrix.inl:211
void set_is_uncalibrated(const bool is_uncalibrated)
Function to set _is_calibrated boolean true or false.
Definition ModelMatrix.inl:158
void uncalibrate(const float cal_factor)
Definition ModelMatrix.inl:172
ModelMatrix()
default constructor
Definition ModelMatrix.inl:27
void multiply_dynamic_image_with_model_and_add_to_input(ParametricVoxelsOnCartesianGrid &parametric_image, const DynamicDiscretisedDensity &dynamic_image) const
multiply (transpose) model-matrix with dynamic image and add result to original parametric_image
Definition ModelMatrix.inl:244
void construct_single_density(SingleDiscretisedDensityType &density, const int i) const
construct a single image corresponding to the parameter with index i
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition Succeeded.h:44
Class used for storing time frame durations.
Definition TimeFrameDefinitions.h:39
unsigned int get_num_frames() const
Get number of frames.
Definition TimeFrameDefinitions.cxx:92
A templated class for vectors, but with indices starting not from 0.
Definition VectorWithOffset.h:65
Declaration of stir::error()
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition error.cxx:42
void warning(const char *const s,...)
Print warning with format string a la printf.
Definition warning.cxx:41
elemT sum(IterT start, IterT end, elemT init)
Compute the sum of a sequence using operator+=(), using an initial value.
Definition more_algorithms.inl:52
ParametricDiscretisedDensity< ParametricVoxelsOnCartesianGridBaseType > ParametricVoxelsOnCartesianGrid
Convenience typedef for Cartesian Voxelised Parametric Images with just two parameters.
Definition ParametricDiscretisedDensity.h:172
Declaration of stir::warning()