CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
src/dynamic/iLinearPatlakModel.cc
Go to the documentation of this file.
1 
9 #include "iLinearPatlakModel.hh"
10 
11 // =====================================================================
12 // ---------------------------------------------------------------------
13 // ---------------------------------------------------------------------
14 // =====================================================================
15 /*
16  \fn iLinearPatlakModel
17  \brief Constructor of iLinearPatlakModel. Simply set all data members to default values.
18 */
20 {
21  // Hard coded number as Patlak has always only two basis functions and hence nbModelParameters
22  m_nbTimeBF = 2;
23  m_nbModelParam = 2;
24  m_nnlsN = 2;
27 }
28 
29 
30 
31 
32 // =====================================================================
33 // ---------------------------------------------------------------------
34 // ---------------------------------------------------------------------
35 // =====================================================================
36 /*
37  \fn ~iLinearPatlakModel
38  \brief Destructor of iLinearPatlakModel
39 */
41 {
42  if(m_initialized)
43  {
44 
45  }
46 }
47 
48 
49 
50 
51 // =====================================================================
52 // ---------------------------------------------------------------------
53 // ---------------------------------------------------------------------
54 // =====================================================================
55 /*
56  \fn ShowHelpModelSpecific
57  \brief Print out specific help about the implementation of the Patlak
58  model and its initialization
59 */
61 {
62  cout << "-- This class implements the Patlak Reference Tissue Model : " << endl;
63  cout << "-- Patlak CS, Blasberg RG: Graphical evaluation of blood-to-brain transfer constants from multiple-time uptake data" << endl;
64  cout << "-- J Cereb Blood Flow Metab 1985, 5(4):5 84-590." << endl;
65  cout << "-- DOI http://dx.doi.org/10.1038/jcbfm.1985.87" << endl;
66  cout << "-- It is used to model radiotracers which follows as 2-tissue compartment model with irreversible trapping " << endl;
67  cout << "-- The Patlak temporal basis functions are composed of the Patlak slope (integral of the reference TAC from the injection time " << endl;
68  cout << " divided by the instantaneous reference activity), and intercept (reference tissue TAC) " << endl;
69  cout << endl;
70  cout << " It can be initialized using either an ASCII file or a list of option with the following keywords and information :" << endl;
71  cout << endl;
72  cout << " For ASCII file options: " << endl;
73  cout << " As this class inherits from the iLinearModel class, the following parameters must be declared inside the couple of the following specific tags: " << endl;
74  cout << " - DYNAMIC FRAMING/ENDDF " << endl;
75  cout << " - The ASCII file must contain the following keywords :" << endl;
76  cout << " 'Basis_functions:' (optional) Enter the coefficients of the Patlak basis functions for each time frame (tf) " << endl;
77  cout << " on two successive lines, separated by ',' :" << endl;
78  cout << " -> Patlak_functions: " << endl;
79  cout << " -> coeff_Pplot_tf1,coeff_Pplot_tf2,...,coeff_Pplot_tfn" << endl;
80  cout << " -> coeff_Pintc_tf1,coeff_Pintc_tf2,...,coeff_Pintc_tfn" << endl;
81  cout << endl;
82  cout << " 'AIC_input_file: path/to/file' (optional) As an alternative to direct input of the basis functions, the sampled Arterial Input Function can be given for " << endl;
83  cout << " estimation of the Patlak basis " << endl;
84  cout << " The file must contain the following information in successive lines, separated by ',' " << endl;
85  cout << " -> AIC_number_of_points: " << endl;
86  cout << " -> AIC_time_points: " << endl;
87  cout << " -> AIC_data_points: " << endl;
88  cout << " -> AIC_units: 'seconds' or 'minutes' " << endl;
89  cout << endl;
90  cout << " 'Parametric_image_init: path' (optional) path to an interfile image to be used as initialization for the parametric images." << endl;
91  cout << endl;
92  cout << " 'Optimisation_method:' x (mandatory) optimization method available options: " << endl;
93  cout << " x=0: Direct ( Implementation of basis functions side by system matrix within each tomographic iterative loop ) " << endl;
94  cout << " x=1: Nested EM " << endl;
95  cout << " x=2: Iterative non-negative Least-Square " << endl;
96  cout << " (C.L. Lawson and R.J. Hanson, Solving Least Squares Problems)" << endl;
97  cout << " x=3: Least-Squares linear regression " << endl;
98  cout << endl;
99  cout << " For command line list of options: " << endl;
100  cout << " The list of options must contain the coefficients of both Patlak functions separated by commas, with the following template :" << endl;
101  cout << " coeff_Pplot_tf1,coeff_Pplot_tf2,...,coeff_Pplot_tfn,";
102  cout << " coeff_Pintc_tf1,coeff_Pintc_tf2,...,coeff_Pintc_tfn "<< endl;
103  cout << " Default optimization method is Nested EM "<< endl;
104  cout << " Parametric images will be uniformly initialized with 0.001 and 1. for Patlak slope and intercept by default " << endl;
105  cout << " The parametric images estimations will be written on disk for each iteration" << endl;
106  cout << " " << endl;
107 
108  // Print general help for all dynamic models
109  ShowHelp();
110 
111 }
112 
113 
114 
115 
116 // =====================================================================
117 // ---------------------------------------------------------------------
118 // ---------------------------------------------------------------------
119 // =====================================================================
120 /*
121  \fn ReadAndCheckConfigurationFileSpecific
122  \param const string& a_configurationFile : ASCII file containing information about a dynamic model
123  \brief This function is used to read options from a configuration file.
124  \return 0 if success, other value otherwise.
125 */
127 {
128  if(m_verbose >=3) Cout("iLinearPatlakModel::ReadAndCheckConfigurationFileSpecific ..."<< endl);
129 
130  // Apply the generic linear parameter read for all Linear Models
132  {
133  Cerr("***** iLinearPatlakModel::ReadAndCheckConfigurationFileSpecific -> Error while trying to read configuration file for generic options of all linear models" << endl);
134  return 1;
135  }
136  // Normal End
137  return 0;
138 }
139 
140 
141 
142 
143 // =====================================================================
144 // ---------------------------------------------------------------------
145 // ---------------------------------------------------------------------
146 // =====================================================================
147 /*
148  \fn ReadAndCheckOptionsList
149  \brief This function is used to read parameters from a string.
150  \return 0 if success, other value otherwise.
151 */
152 int iLinearPatlakModel::ReadAndCheckOptionsList(string a_listOptions)
153 {
154  if(m_verbose >=3) Cout("iLinearPatlakModel::ReadAndCheckOptionsList ..."<< endl);
155 
156  // Just recover the string here, it will be processed in the Initialize() function
157  m_listOptions = a_listOptions;
158 
159  // Normal end
160  return 0;
161 }
162 
163 
164 // =====================================================================
165 // ---------------------------------------------------------------------
166 // ---------------------------------------------------------------------
167 // =====================================================================
168 /*
169  \fn CheckSpecificParameters
170  \brief This function is used to check whether all member variables
171  have been correctly initialized or not.
172  \return 0 if success, positive value otherwise.
173 */
175 {
176 
177  // Perform generic checks that apply for the Linear Models
179  {
180  Cerr("***** iLinearPatlakModel::CheckSpecificParameters -> A problem occurred while checking specific parameters ! " << endl);
181  return 1;
182  }
183 
184  // Normal end
185  return 0;
186 }
187 
188 
189 // =====================================================================
190 // ---------------------------------------------------------------------
191 // ---------------------------------------------------------------------
192 // =====================================================================
193 /*
194  \fn InitializeSpecific
195  \brief This function is used to initialize Patlak parametric images and basis functions
196  \return 0 if success, other value otherwise.
197 */
199 {
200  if(m_verbose >=2) Cout("iLinearPatlakModel::InitializeSpecific ..."<< endl);
201 
202  // Run generic Initialization for all Linear Models
204  {
205  Cerr("***** iLinearPatlakModel::InitializeSpecific() -> Error while performing generic initialisations for linear models !" << endl);
206  return 1;
207  }
208 
209  // Initialization with a list of options
210  if(m_listOptions != "")
211  {
212  // Default initialization : Nested-EM
214 
215  // We expect here the coefficients of the functions for each time point
216  // Patlak slope before Patlak intercept
217 
218  // Allocate memory to recover the elements in one tmp vector
219  FLTNB *p_coeffs = new FLTNB[m_nbTimeBF * mp_ID->GetNbTimeFrames()];
220 
221  // Read them
223  p_coeffs,
225  ",",
226  "Patlak model configuration"))
227  {
228  Cerr("***** iPatlakModel::Initialize() -> Failed to correctly read the list of parameters in command-line options !" << endl);
229  return 1;
230  }
231 
232  // Affect coeffs
233  for(int c=0 ; c<m_nbTimeBF * mp_ID->GetNbTimeFrames() ; c++)
234  {
235  int bf = int(c/mp_ID->GetNbTimeFrames()); // Patlak basis function index
236  int fr = int(c%mp_ID->GetNbTimeFrames()); // Frame index
237  m2p_nestedModelTimeBasisFunctions[ bf ][ fr ] = p_coeffs[ c ];
238  }
239 
240  // Delete the tmp vector
241  delete[] p_coeffs;
242  }
243 
244  // --- Default Initialization of time basis functions --- //
245  for(int v=0 ; v<mp_ID->GetNbVoxXYZ() ; v++)
246  {
247  m2p_parametricImages[0][v] = 1.0;
248  m2p_parametricImages[1][v] = 1.0;
249  }
250 
251  if (m_AICfileProvided)
252  {
253  if(m_verbose >=2) Cout("iLinearPatlakModel::Estimating Patlak basis functions ..."<< endl);
254  // Calculate the Patlak Basis functions and set the m2p_nestedModelTimeBasisFunctions --------------------------------------/
255  uint32_t* a_frameTimeStopInMs = mp_ID->GetFramesTimeStopArray(0);
256  uint32_t* a_frameTimeStartInMs = mp_ID->GetFramesTimeStartsArray(0);
257  int a_nbTimeFrames = mp_ID->GetNbTimeFrames();
258 
259  // Get pointer to interpolated Arterial Input Curve
261  // Calculation of the 'Patlak Time' integral in the discrete level with the trapezoidal method
262  // For uniform spacing that is $ \frac{\Delta T}{2} ( f(x_0) + \sum_{k=0}^{N-1} f(x_k) + f(x_N)) $
263  HPFLTNB* a_PatlakTAC = new HPFLTNB[(a_frameTimeStopInMs[a_nbTimeFrames-1])];
264  HPFLTNB RunningSum = 0 ;
265  HPFLTNB halfDeltaT = (0.001/2);
266  // First value of integration over the AIC will be the first value of the AIC * DeltaT
267  a_PatlakTAC[0] = a_AICIntrpY[0] * 0.001;
268  // Then iterate though all the other points using the trapezoidal function for uniform spacing
269  for (uint32_t i=1 ;i<(a_frameTimeStopInMs[a_nbTimeFrames - 1]);i++)
270  {
271  RunningSum += a_AICIntrpY[i-1] ;
272  a_PatlakTAC[i] = (a_AICIntrpY[0] + 2 * RunningSum + a_AICIntrpY[i])*halfDeltaT ;
273  }
274 
275  // Allocate memory for the Patlak Basis functions
277  // Setting initial values to 0
278  for (int tbf=0; tbf<2; tbf++) m2p_nestedModelTimeBasisFunctions[tbf] = new FLTNB [a_nbTimeFrames];
279 
280  // Calculate first basis function - Integration of Patlak time over each frame and division by duration-//
281  for (int fr = 0; fr < a_nbTimeFrames; fr++)
282  {
283  RunningSum = 0 ;
284  // iteration over all the datapoints within the frame
285  for (uint32_t i = a_frameTimeStartInMs[fr]+1 ;i <(a_frameTimeStopInMs[fr]);i++)
286  {
287  RunningSum+=a_PatlakTAC[i];
288  }
289  m2p_nestedModelTimeBasisFunctions[0][fr] = (FLTNB) ((a_PatlakTAC[a_frameTimeStartInMs[fr]] +
290  2 * RunningSum + a_PatlakTAC[a_frameTimeStopInMs[fr]])*halfDeltaT) ;
291  m2p_nestedModelTimeBasisFunctions[0][fr] /= ((FLTNB)(a_frameTimeStopInMs[fr] - a_frameTimeStartInMs[fr]))/1000;
292  }
293 
294  // Calculate second basis function - Average of interpolated AIC over each frame and division by duration-//
295  for (int fr = 0; fr < a_nbTimeFrames; fr++)
296  {
297  RunningSum = 0;
298  // iteration over all the datapoints within the frame
299  for (uint32_t i = a_frameTimeStartInMs[fr]+1; i < (a_frameTimeStopInMs[fr]); i++)
300  {
301  RunningSum += a_AICIntrpY[i];
302  }
303  m2p_nestedModelTimeBasisFunctions[1][fr] = (FLTNB) ((a_AICIntrpY[a_frameTimeStartInMs[fr]] +
304  2 * RunningSum + a_AICIntrpY[a_frameTimeStopInMs[fr]]) * halfDeltaT);
305  m2p_nestedModelTimeBasisFunctions[1][fr] /= ((FLTNB)(a_frameTimeStopInMs[fr] - a_frameTimeStartInMs[fr]))/1000;
306  }
307 
308  // Clear memory for Patlak time
309  if ( a_PatlakTAC ) delete[] a_PatlakTAC;
310  // --------------------------------------------------------------------------------------------------------------/
311 
312  }
313 
314  // Print the basis functions
316 
317  // Normal end
318  m_initialized = true;
319  return 0;
320 }
321 
int ReadStringOption(const string &a_input, T *ap_return, int a_nbElts, const string &sep, const string &a_option)
Parse the &#39;a_input&#39; string corresponding to the &#39;a_option&#39; into &#39;a_nbElts&#39; elements, using the &#39;sep&#39; separator. The results are returned in the templated &#39;ap_return&#39; dynamic templated array. Call "ConvertFromString()" to perform the correct conversion depending on the type of the data to convert.
#define Cerr(MESSAGE)
oImageDimensionsAndQuantification * mp_ID
void ShowHelp()
This function is used to print out general help about dynamic models.
int InitializeSpecificToAllLinearModels()
This function is used to initialize the parametric images and basis functions for all Linear Models...
int InitializeSpecific()
This function is used to initialize Patlak parametric images and basis functions. ...
This class implements a general linear dynamic model applied between the images of a dynamic acquisit...
void ShowBasisFunctions()
This function is used to print the basis functions.
int CheckSpecificParametersForAllLinearModels()
This function is used to check parameters for all Linear Models. .
int ReadAndCheckConfigurationFileSpecific()
This function is used to read options from a configuration file.
oArterialInputCurve * mp_ArterialInputCurve
~iLinearPatlakModel()
Destructor of iLinearPatlakModel.
int ReadAndCheckOptionsList(string a_listOptions)
void ShowHelpModelSpecific()
Print out specific help about the implementation of the Patlak model and its initialization.
#define OPTIMISATION_METHOD_NESTEM
int CheckSpecificParameters()
This function is used to check whether all member variables have been correctly initialized or not...
iLinearPatlakModel()
Constructor of iLinearPatlakModel. Simply set all data members to default values. ...
int ReadAndCheckConfigurationFileSpecificToAllLinearModels()
This function is used to read parameters that are generic for all Linear Models. ...
HPFLTNB * GetInterpolatedAIC()
Set the framing of the reconstruction for the AIC object.
#define Cout(MESSAGE)