CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
src/dynamic/oArterialInputCurve.cc
Go to the documentation of this file.
1 
8 #include "oArterialInputCurve.hh"
9 #include "sOutputManager.hh"
10 #include "gOptions.hh"
11 
12 // =====================================================================
13 // ---------------------------------------------------------------------
14 // ---------------------------------------------------------------------
15 // =====================================================================
16 /*
17  \fn oArterialInputCurve
18  \brief Constructor of oArterialInputCurve. Simply set all data members to default values.
19 */
20 
22 {
23 
24  m_pathToAICfile = "";
25  m_verbose = -1;
26 
28  mp_AICDataPoints = NULL;
29  mp_AICDataPointsTimes = NULL;
30 
31 
32  mp_AICIntrpY = NULL;
34 
35  m_nbTimeFrames = -1;
36  mp_frameTimeStartInMs = NULL;
37  mp_frameTimeStopInMs = NULL;
38 
39 }
40 
42 {
43 
46 
47  if (mp_AICIntrpY) delete(mp_AICIntrpY);
48 
49 }
50 
52 {
53  // Check that the provided sampled AIC covers the first frame
55  {
56  Cerr("***** oArterialInputCurve::CheckParameters() -> AIC datapoints need to start before the first frame " << endl);
57  return 1;
58  }
59  // Check if the provided sampled AIC covers the requested total reconstruction time ( last time point of last frame )
61  {
62  Cerr("***** oArterialInputCurve::CheckParameters() -> Requested reconstruction framing is longer than the provided AIC time points" << endl);
63  return 1;
64  }
65  // End
66  return 0;
67 }
68 
69 void oArterialInputCurve::SetFrames(int a_nbTimeFrames, uint32_t *a_frameTimeStartInMs, uint32_t *a_frameTimeStopInMs)
70 {
71  m_nbTimeFrames = a_nbTimeFrames;
72  mp_frameTimeStartInMs = a_frameTimeStartInMs;
73  mp_frameTimeStopInMs = a_frameTimeStopInMs;
74 }
75 
77 {
78 
79  if (m_verbose>=2) Cout("oArterialInputCurve::InitializeInputData() -> Initializing input from the provided Arterial Input Curve " << endl );
80 
81  // Read number of AIC data points
83  {
84  Cerr("***** oArterialInputCurve::InitializeInputData() -> Error while reading number of data points from AIC file )" << endl);
85  return 1;
86  }
87 
88  // Allocate memory for data points
91  // need floating point numbers for input data points
92  FLTNB* input_time_points_FLTNB = new FLTNB[ m_nbinputDataPoints ];
93 
94 
95  // Populate arrays with data from AIC file
97  {
98  Cerr( "***** oArterialInputCurve::InitializeInputData() -> Error while trying to read Data points from AIC file: " << m_pathToAICfile << endl);
99  return 1;
100  }
101  if ( ReadDataASCIIFile(m_pathToAICfile, "AIC_time_points", input_time_points_FLTNB, m_nbinputDataPoints , KEYWORD_MANDATORY) )
102  {
103  Cerr("***** oArterialInputCurve::InitializeInputData() -> Error while trying to read Time Data points from AIC file: " << m_pathToAICfile << endl);
104  return 1;
105  }
106 
107  // Get Units from file
108  string Units = "";
109  ReadDataASCIIFile(m_pathToAICfile, "AIC_units", &Units,1, KEYWORD_OPTIONAL);
110 
111  bool time_points_inMinutes = false;
112 
113  if (Units=="minutes" || Units=="Minutes")
114  {
115  time_points_inMinutes = true ;
116  }
117 
118  // Case of Time points provided in minutes
119  if (time_points_inMinutes)
120  {
121  // Convert all time points from minutes to milliseconds and cast into the uint32_t variable
122  for (int i=0;i<m_nbinputDataPoints;i++) { mp_AICDataPointsTimes[i] = (uint32_t) (input_time_points_FLTNB[i]*60000);}
123  }
124  // Else case of time points provided in seconds
125  else
126  {
127  // Convert all time points from seconds to milliseconds and cast into the uint32_t variable
128  for (int i = 0; i < m_nbinputDataPoints; i++) { mp_AICDataPointsTimes[i] = (uint32_t) (input_time_points_FLTNB[i]*1000);}
129  }
130 
131  // delete temporary array
132  if (input_time_points_FLTNB) delete [] (input_time_points_FLTNB);
133 
134  // Print data points
135  if (m_verbose>=3)
136  {
137  Cout("oArterialInputCurve::InitializeInputData() -> Printing input Data \n Time(ms),Datapoint (Bq/ml) " << endl );
138  for (int i = 0; i < m_nbinputDataPoints; i++)
139  {
140  Cout (mp_AICDataPointsTimes[i] << ", " << mp_AICDataPoints [i]<< endl);
141  }
142  }
143  // End
144  return 0;
145 }
146 
148 {
149  // Creating variables for storing the slopes and intercepts between each pair of datapoints
150  HPFLTNB* slopes = new HPFLTNB[m_nbinputDataPoints-1];
151  HPFLTNB* intercepts = new HPFLTNB[m_nbinputDataPoints-1];
152 
153  // Allocating memory for the interpolated data values ( one for each discrete unit -> 1 millisecond )
154  // Only calculating and storing the interpolated values until the end of the last frame
156 
157  // Calculating slopes and intercepts for each pair & interpolate for every millisecond value
158  for (int i=0;i<(m_nbinputDataPoints-1);i++)
159  {
160  // m = (y2-y1)/(x2-x1)
161  slopes[i] = (mp_AICDataPoints[i + 1] - mp_AICDataPoints[i]) / ((HPFLTNB) (mp_AICDataPointsTimes[i + 1] - mp_AICDataPointsTimes[i]));
162  //b = (-1)*(m)*(x2)+y2
163  intercepts[i] = -1 * slopes[i] * ((HPFLTNB)(mp_AICDataPointsTimes[i + 1])) + mp_AICDataPoints[i + 1];
164 
165  // Calculate the interpolated values for the evaluated data-pair and populate mp_AICIntrpY
166  // If first data point is within the range proceed
167  if (mp_AICDataPointsTimes[i] <= mp_frameTimeStopInMs[m_nbTimeFrames - 1])
168  {
169  // Check if second data point is also within the range
170  if (mp_AICDataPointsTimes[i + 1] <= mp_frameTimeStopInMs[m_nbTimeFrames - 1])
171  {
172  // Populate the whole range with interpolated values
173  for (uint32_t k = mp_AICDataPointsTimes[i]; k < mp_AICDataPointsTimes[i + 1]; k++)
174  {
175  mp_AICIntrpY[k] = (HPFLTNB)k * slopes[i] + intercepts[i];
176  }
177  }
178  // if second data point is out of range , populate up until the last frame point
179  else if (mp_AICDataPointsTimes[i + 1] > mp_frameTimeStopInMs[m_nbTimeFrames - 1])
180  {
181  // Populate the whole range with interpolated values
182  for (uint32_t k = mp_AICDataPointsTimes[i]; k <= mp_frameTimeStopInMs[m_nbTimeFrames - 1]; k++)
183  {
184  mp_AICIntrpY[k] = (HPFLTNB)k * slopes[i] + intercepts[i];
185  }
186  }
187  }
188  }
189  // Report any negative values and set to zero
190  for (uint32_t k = 0; k <= mp_frameTimeStopInMs[m_nbTimeFrames - 1]; k++)
191  {
192  if ( mp_AICIntrpY[k] <0 )
193  {
194  mp_AICIntrpY[k] = 0 ;
195  Cout (" Negative interpolated AIF value detected at: " << k <<"ms --> setting AIF to zero" << endl);
196  }
197  }
198 
199  // clear memory
200  if (slopes) delete[] (slopes);
201  if (intercepts) delete[] (intercepts);
202  // Also clear input data points from memory , as we dont re-use them for interpolation
203  // (that could change in the future with new models that might require other operations on the input datapoints)
204  if (mp_AICDataPoints) delete [] (mp_AICDataPoints);
206 
207 
208  //Normal End
209  return 0;
210 }
211 
212 
213 // =====================================================================
214 // ---------------------------------------------------------------------
215 // ---------------------------------------------------------------------
216 // Downsampling of interpolated AIC for speeding-up convolution operations
217 // =====================================================================
219 {
220  // Number of total samples required
221  int total_samples_forDownsample = (int)(((float)mp_frameTimeStopInMs[m_nbTimeFrames - 1] / 1000.) * 10);
222  // plus one for index 0
223  total_samples_forDownsample+=1;
224  if (m_verbose>=3) Cout(" Downsampling to 100 msec time intervals " << endl);
225  // Allocate memory for downsampled AIC
226  mp_AICIntrpY_downsampled = new HPFLTNB[total_samples_forDownsample];
227  // Seting the index and the zero value (first data-point)
228  int index=0;
230  for (int i=1;i<=int(mp_frameTimeStopInMs[m_nbTimeFrames - 1]);i++)
231  {
232  // If exact division by 100 , datapoint is a 0.1 of a second -> set to downsampled datapoints
233  if (i%100==0)
234  {
235  index ++;
237  }
238  }
239  if (m_verbose>=3) Cout( " Downsampling complete to total # of points : " << index << endl);
240 
241  // Normal End
242  return 0;
243 }
int Downsample()
This function downsamples the interpolated arterial input function Currently needed to speed up convo...
#define Cerr(MESSAGE)
oArterialInputCurve()
Constructor of oArterialInputCurve. Simply set all data members to default values.
int InterpolateAIC()
This function performs a linear interpolation within the provided AIC range for every discrete unit o...
~oArterialInputCurve()
Destructor of oArterialInputCurve. Free memory from all allocated tabs.
int InitializeInputData()
This function is used to initialize the input arterial curve samples from the file provided by the us...
#define KEYWORD_MANDATORY
#define KEYWORD_OPTIONAL
void SetFrames(int a_nbTimeFrames, uint32_t *a_frameTimeStartInMs, uint32_t *a_frameTimeStopInMs)
int CheckParameters()
This function is used to check that the required input parameters are provided from the file provided...
int ReadDataASCIIFile(const string &a_file, const string &a_keyword, T *ap_return, int a_nbElts, bool a_mandatoryFlag)
Look for "a_nbElts" elts in the "a_file" file matching the "a_keyword" string passed as parameter a...
#define Cout(MESSAGE)