STIR 6.4.0
PlasmaData.inl
Go to the documentation of this file.
1//
2//
3/*
4 Copyright (C) 2005 - 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*/
21#include "stir/warning.h"
22#include "stir/error.h"
23#include <functional>
24#include <algorithm>
25
26START_NAMESPACE_STIR
27
30{
31 this->set_is_decay_corrected(false);
32}
33
35// ChT::ToDO: Better to use iterators
36PlasmaData::PlasmaData(const std::vector<PlasmaSample>& plasma_blood_plot)
37{
38 this->_plasma_blood_plot = plasma_blood_plot;
39 this->set_is_decay_corrected(false);
40 this->_isotope_halflife = -1.;
41}
42
46
49void
50PlasmaData::read_plasma_data(const std::string input_string)
51{
52 std::ifstream data_stream(input_string.c_str());
53 if (!data_stream)
54 error("cannot read plasma data from file.\n");
55 else
56 {
57 // Get the first line, which should be the number of samples
58 std::string first_line;
59 if (std::getline(data_stream, first_line))
60 {
61 // replace leading/trailing whitespace
62 first_line.erase(std::find_if(first_line.rbegin(),
63 first_line.rend(),
64 std::bind(std::not_equal_to<char>(), ' ', std::placeholders::_1))
65 .base(),
66 first_line.end());
67 first_line.erase(first_line.begin(),
68 std::find_if(first_line.begin(),
69 first_line.end(),
70 std::bind(std::not_equal_to<char>(), ' ', std::placeholders::_1)));
71 // now first, check if the first line is a single character.
72 // this is best done in C style, cleaner than iterating over chars
73 char* p;
74 long converted = strtol(first_line.c_str(), &p, 10);
75 if (*p)
76 error("First line of input function file (" + input_string + ") is not number of samples");
77 else
78 _sample_size = converted;
79 }
80 else
81 {
82 error("Input function file (" + input_string + ") is empty");
83 }
84 }
85 while (true)
86 {
87 float sample_time = 0, blood_sample_radioactivity = 0, plasma_sample_radioactivity = 0;
88 data_stream >> sample_time;
89 data_stream >> plasma_sample_radioactivity;
90 data_stream >> blood_sample_radioactivity;
91 if (!data_stream)
92 break;
93 const PlasmaSample current_sample(sample_time, plasma_sample_radioactivity, blood_sample_radioactivity);
94 (this->_plasma_blood_plot).push_back(current_sample);
95 // Comment: The input function is generally not corrected for decay.
96 this->set_is_decay_corrected(false);
97 }
98}
99
100// Implementation to set the input units not currently used.
101/*
102 void
103 PlasmaData::set_input_units( SamplingTimeUnits input_sampling_time_units,
104 VolumeUnits input_volume_units,
105 RadioactivityUnits input_radioactivity_units )
106{
107 _input_sampling_time_units=input_sampling_time_units ;
108 _input_volume_units=input_volume_units ;
109 _input_radioactivity_units=input_radioactivity_units ;
110}
111*/
112
114void
115PlasmaData::set_plot(const std::vector<PlasmaSample>& plasma_blood_plot)
116{
117 this->_plasma_blood_plot = plasma_blood_plot;
118}
119
121void
122PlasmaData::shift_time(const double time_shift)
123{
124 _time_shift = time_shift;
125 for (std::vector<PlasmaSample>::iterator cur_iter = this->_plasma_blood_plot.begin();
126 cur_iter != this->_plasma_blood_plot.end();
127 ++cur_iter)
128 cur_iter->set_time_in_s(cur_iter->get_time_in_s() + time_shift);
129}
130
132double
134{
135 return PlasmaData::_time_shift;
136}
137
139double
141{
142 return this->_isotope_halflife;
143}
144
146void
147PlasmaData::set_isotope_halflife(const double isotope_halflife)
148{
149 this->_isotope_halflife = isotope_halflife;
150}
151
152void
154{
155 this->_plasma_fdef = plasma_fdef;
156}
157
159PlasmaData::get_time_frame_definitions() const
160{
161 return this->_plasma_fdef;
162}
163
164void
165PlasmaData::set_is_decay_corrected(const bool is_decay_corrected)
166{
167 this->_is_decay_corrected = is_decay_corrected;
168}
169
170bool
171PlasmaData::get_is_decay_corrected() const
172{
173 return this->_is_decay_corrected;
174}
175
176void
178{
179
180 if (this->_is_decay_corrected == true)
181 warning("PlasmaData are already decay corrected");
182 else
183 {
184 assert(this->_isotope_halflife > 0);
185 for (std::vector<PlasmaSample>::iterator cur_iter = this->_plasma_blood_plot.begin();
186 cur_iter != this->_plasma_blood_plot.end();
187 ++cur_iter)
188 {
189 cur_iter->set_plasma_counts_in_kBq(static_cast<float>(
190 cur_iter->get_plasma_counts_in_kBq() * decay_correction_factor(_isotope_halflife, cur_iter->get_time_in_s())));
191 cur_iter->set_blood_counts_in_kBq(static_cast<float>(
192 cur_iter->get_blood_counts_in_kBq() * decay_correction_factor(_isotope_halflife, cur_iter->get_time_in_s())));
193 }
194 PlasmaData::set_is_decay_corrected(true);
195 }
196}
197
201{
202 if (this->_is_decay_corrected == false)
203 {
205 warning("Correcting for decay while sampling into frames.");
206 this->set_is_decay_corrected(true);
207 }
208 std::vector<double> start_times_vector;
209 std::vector<double> durations_vector;
210 const unsigned int num_frames = time_frame_def.get_num_frames();
211 std::vector<PlasmaSample> samples_in_frames_vector(num_frames);
212 PlasmaData::const_iterator cur_iter;
213 std::vector<PlasmaSample>::iterator frame_iter = samples_in_frames_vector.begin();
214
215 // Estimate the plasma_frame_vector and the plasma_frame_sum_vector using the integrate_discrete_function() implementation
216 for (unsigned int frame_num = 1; frame_num <= num_frames && frame_iter != samples_in_frames_vector.end();
217 ++frame_num, ++frame_iter)
218 {
219 std::vector<double> time_frame_vector;
220 std::vector<double> plasma_frame_vector;
221 std::vector<double> blood_frame_vector;
222 const double frame_start_time = time_frame_def.get_start_time(frame_num); // t1
223 const double frame_end_time = time_frame_def.get_end_time(frame_num); // t2
224
225 for (cur_iter = (this->_plasma_blood_plot).begin(); cur_iter != (this->_plasma_blood_plot).end(); ++cur_iter)
226 {
227 const double cur_time = (*cur_iter).get_time_in_s();
228 if (cur_time < frame_start_time)
229 continue;
230 const double cur_plasma_cnt = (*cur_iter).get_plasma_counts_in_kBq();
231 const double cur_blood_cnt = (*cur_iter).get_blood_counts_in_kBq();
232 if (cur_time < frame_end_time)
233 {
234 plasma_frame_vector.push_back(cur_plasma_cnt);
235 blood_frame_vector.push_back(cur_blood_cnt);
236 time_frame_vector.push_back(cur_time);
237 }
238 else
239 {
240 if (plasma_frame_vector.size()
241 < 1) /* In case of no plasma data inside a frame, e.g. when there is large time_shift. */
242 {
243 plasma_frame_vector.push_back(0.);
244 blood_frame_vector.push_back(0.);
245 time_frame_vector.push_back((frame_start_time + frame_end_time) * .5);
246 }
247 else
248 {
249 plasma_frame_vector.push_back(cur_plasma_cnt);
250 blood_frame_vector.push_back(cur_blood_cnt);
251 time_frame_vector.push_back(cur_time);
252 }
253 break;
254 }
255 }
256 if (time_frame_vector.size() != 1)
257 {
258 frame_iter->set_blood_counts_in_kBq(
259 static_cast<float>(integrate_discrete_function(time_frame_vector, blood_frame_vector)
260 / (time_frame_vector[time_frame_vector.size() - 1] - time_frame_vector[0])));
261 frame_iter->set_plasma_counts_in_kBq(
262 static_cast<float>(integrate_discrete_function(time_frame_vector, plasma_frame_vector)
263 / (time_frame_vector[time_frame_vector.size() - 1] - time_frame_vector[0])));
264 frame_iter->set_time_in_s(0.5 * (time_frame_vector[time_frame_vector.size() - 1] + time_frame_vector[0]));
265 start_times_vector.push_back(time_frame_vector[0]);
266 durations_vector.push_back(time_frame_vector[time_frame_vector.size() - 1] - time_frame_vector[0]);
267 }
268 else if (time_frame_vector.size() == 1)
269 {
270 frame_iter->set_plasma_counts_in_kBq(static_cast<float>(plasma_frame_vector[0]));
271 frame_iter->set_blood_counts_in_kBq(static_cast<float>(blood_frame_vector[0]));
272 frame_iter->set_time_in_s(time_frame_vector[0]);
273 start_times_vector.push_back(frame_start_time);
274 durations_vector.push_back(frame_end_time - frame_start_time);
275 }
276 }
277 PlasmaData plasma_data_in_frames(samples_in_frames_vector);
278 TimeFrameDefinitions plasma_fdef(start_times_vector, durations_vector);
279 plasma_data_in_frames.set_is_decay_corrected(this->_is_decay_corrected);
280 plasma_data_in_frames.set_isotope_halflife(this->_isotope_halflife);
281 plasma_data_in_frames.set_time_frame_definitions(plasma_fdef);
282 return plasma_data_in_frames;
283}
284
285// PlasmaData begin() and end() of the PlasmaData ;
286PlasmaData::const_iterator
288{
289 return this->_plasma_blood_plot.begin();
290}
291
292PlasmaData::const_iterator
293PlasmaData::end() const
294{
295 return this->_plasma_blood_plot.end();
296}
297
298unsigned int
299PlasmaData::size() const
300{
301 return static_cast<unsigned>(this->_plasma_blood_plot.size());
302}
303
304/*
305//PlasmaData begin() and end() of the PlasmaData ;
306PlasmaData::iterator
307PlasmaData::begin()
308{ return this->_plasma_blood_plot.begin() ; }
309
310PlasmaData::iterator
311PlasmaData::end()
312{ return this->_plasma_blood_plot.end() ; }
313*/
314
315END_NAMESPACE_STIR
A class for storing plasma and blood samples of a single study.
Definition PlasmaData.h:34
double get_isotope_halflife() const
Function to get the isotope halflife.
Definition PlasmaData.inl:140
void set_time_frame_definitions(const TimeFrameDefinitions &plasma_fdef)
Definition PlasmaData.inl:153
double get_time_shift()
Function to get the time shift.
Definition PlasmaData.inl:133
void shift_time(const double time_shift)
Function to shift the time data.
Definition PlasmaData.inl:122
PlasmaData get_sample_data_in_frames(TimeFrameDefinitions time_frame_def)
Sorts the plasma_data into frames.
Definition PlasmaData.inl:200
~PlasmaData()
default constructor
Definition PlasmaData.inl:44
void set_plot(const std::vector< PlasmaSample > &plasma_blood_plot)
Function to set the plasma_blood_plot.
Definition PlasmaData.inl:115
void read_plasma_data(const std::string input_string)
Implementation to read the input function from ONLY a 3-columns data file (Time-InputFunctionRadioact...
Definition PlasmaData.inl:50
void set_isotope_halflife(const double isotope_halflife)
Function to set the isotope halflife.
Definition PlasmaData.inl:147
PlasmaData(const std::vector< PlasmaSample > &plasma_blood_plot)
constructor giving a vector
Definition PlasmaData.inl:36
const_iterator begin() const
begin() and end() iterators for the plasma curve and the size() function
Definition PlasmaData.inl:287
void decay_correct_PlasmaData()
Function to decay correct the data.
Definition PlasmaData.inl:177
Definition PlasmaSample.h:38
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
Simple functions to compute the decay correction factor.
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
double decay_correction_factor(const double isotope_halflife, const double start_time, const double end_time)
Compute decay-correction factor for a time frame.
Definition decay_correction_factor.h:36
elemT integrate_discrete_function(const std::vector< elemT > &coordinates, const std::vector< elemT > &values, const int interpolation_order=1)
numerical integration of a 1D function
Definition integrate_discrete_function.inl:26
Declaration of stir::integrate_discrete_function function.
Declaration of stir::warning()