CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
src/image/vDeformation.cc
Go to the documentation of this file.
1 
8 #include "vDeformation.hh"
9 #include "oImageDimensionsAndQuantification.hh"
10 #include "oImageSpace.hh"
11 
12 // =====================================================================
13 // ---------------------------------------------------------------------
14 // ---------------------------------------------------------------------
15 // =====================================================================
16 /*
17  \fn vDeformation
18  \brief Constructor of vDeformation. Simply set all data members to default values.
19 */
21 {
22  mp_ID = NULL;
24  m_verbose = -1;
25  m_checked = false;
26  m_initialized = false;
27 }
28 
29 
30 
31 
32 // =====================================================================
33 // ---------------------------------------------------------------------
34 // ---------------------------------------------------------------------
35 // =====================================================================
36 /*
37  \fn ~vDeformation
38  \brief Destructor of vDeformation.
39 */
41 
42 
43 
44 
45 // =====================================================================
46 // ---------------------------------------------------------------------
47 // ---------------------------------------------------------------------
48 // =====================================================================
56 {
57  if(m_verbose>=VERBOSE_DETAIL) Cout("vDeformation::CheckParameters ..."<< endl);
58 
59  // Check image dimensions
60  if (mp_ID==NULL)
61  {
62  Cerr("***** vDeformation::CheckParameters() -> No image dimensions provided !" << endl);
63  return 1;
64  }
65 
66  // Check verbosity
67  if (m_verbose<0)
68  {
69  Cerr("***** vDeformation::CheckParameters() -> Wrong verbosity level provided !" << endl);
70  return 1;
71  }
72 
73  // Check number of basis functions
74  if (m_nbTransformations <0)
75  {
76  Cerr("***** vDeformation::CheckParameters() -> Number of transformations in the deformation has not been initialized !" << endl);
77  return 1;
78  }
79 
80  // Check parameters of the child class (if this function is overloaded)
82  {
83  Cerr("***** vDeformation::CheckParameters() -> An error occurred while checking parameters of the child dynamic class !" << endl);
84  return 1;
85  }
86 
87  // Normal end
88  m_checked = true;
89  return 0;
90 }
91 
92 
93 
94 
95 
96 
97 
98 // =====================================================================
99 // ---------------------------------------------------------------------
100 // ---------------------------------------------------------------------
101 // =====================================================================
102 /*
103  \fn ApplyDeformationsToBackwardImage
104  \param ap_Image : required to access the backward image and its deformation backup matrice
105  \param a_fr : frame index
106  \param a_defIdx : index of the deformation
107  \brief Apply backward transformation of the backward image to the reference position
108  \details Loop on frames
109  Recover any potential data stored in the backup matrice m2p_defTmpBackwardImage
110  \return 0 if success, positive value otherwise
111 */
112 int vDeformation::ApplyDeformationsToBackwardImage(oImageSpace* ap_Image, int a_fr, int a_defIdx)
113 {
114  if(m_verbose >= VERBOSE_DEBUG_NORMAL) Cout("vDeformation::ApplyDeformationsToBackwardImage ... " <<endl);
115 
116  #ifdef CASTOR_DEBUG
117  if (!m_initialized)
118  {
119  Cerr("***** vDeformation::ApplyDeformationsToBackwardImage() -> Called while not initialized !" << endl);
120  Exit(EXIT_DEBUG);
121  }
122  #endif
123 
124  for(int bimg=0; bimg<ap_Image->GetNbBackwardImages(); bimg++)
125  for(int rimg=0; rimg<mp_ID->GetNbRespGates(); rimg++)
126  for(int cimg=0; cimg<mp_ID->GetNbCardGates(); cimg++)
127  {
128  // Perform backward deformation
129  if(ApplyDeformations(ap_Image->m6p_backwardImage[bimg][0][a_fr][rimg][cimg],
130  ap_Image->m6p_backwardImage[bimg][0][a_fr][rimg][cimg],
132  a_defIdx) )
133  {
134  Cerr("***** vDeformation::ApplyDeformationsToBackwardImage()-> An error occurred while performing backward deformation of the backward image !" << endl);
135  Cerr("***** frame index " << a_fr << " respiratory image index " << rimg<< " cardiac image index " << cimg<< " !" << endl);
136  return 1;
137  }
138 
139  // Recover the content of the temporary backup deformation image to the backward image
140  for(int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
141  ap_Image->m6p_backwardImage[bimg][0][a_fr][rimg][cimg][v] += ap_Image->m5p_refDynBackwardImage[bimg][a_fr][rimg][cimg][v] ;
142  }
143 
144  return 0;
145 }
146 
147 
148 
149 
150 // =====================================================================
151 // ---------------------------------------------------------------------
152 // ---------------------------------------------------------------------
153 // =====================================================================
154 /*
155  \fn ApplyDeformationsToHistoSensitivityImage
156  \param ap_Image : required to access the backward image and its deformation backup matrice
157  \param a_fr : frame index
158  \param a_defIdx : index of the deformation
159  \brief Apply backward transformations of the sensitivity image to the reference position (histogram mode)
160  \details Loop on frames
161  Recover any potential data stored in the backup matrice m4p_defTmpSensitivityImage
162  \return 0 if success, positive value otherwise
163 */
164 int vDeformation::ApplyDeformationsToHistoSensitivityImage(oImageSpace* ap_Image, int a_fr, int a_defIdx)
165 {
166  if(m_verbose >= VERBOSE_DETAIL) Cout("vDeformation::ApplyDeformationsToHistoSensitivityImage ... " <<endl);
167 
168  #ifdef CASTOR_DEBUG
169  if (!m_initialized)
170  {
171  Cerr("***** vDeformation::ApplyDeformationsToHistoSensitivityImage() -> Called while not initialized !" << endl);
172  Exit(EXIT_DEBUG);
173  }
174  #endif
175 
176  for(int rimg=0; rimg<mp_ID->GetNbRespGates() ; rimg++)
177  for(int cimg=0; cimg<mp_ID->GetNbCardGates() ; cimg++)
178  {
179  // Perform backward deformation
180  if( ApplyDeformations(ap_Image->m5p_sensitivity[0][a_fr][rimg][cimg],
181  ap_Image->m5p_sensitivity[0][a_fr][rimg][cimg],
183  a_defIdx) )
184  {
185  Cerr("***** vDeformation::ApplyDeformationsToHistoSensitivityImage()-> An error occurred while performing backward deformation of the backward image !" << endl);
186  Cerr("***** frame index " << a_fr << " respiratory image index " << rimg<< " cardiac image index " << cimg<< " !" << endl);
187  return 1;
188  }
189 
190  // Recover the content of the temporary backup deformation image in the sensitivity image
191  for(int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
192  ap_Image->m5p_sensitivity[0][a_fr][rimg][cimg][v] += ap_Image->m4p_refDynSensitivityImage[a_fr][rimg][cimg][v];
193  }
194 
195  return 0;
196 }
197 
198 
199 
200 
201 // =====================================================================
202 // ---------------------------------------------------------------------
203 // ---------------------------------------------------------------------
204 // =====================================================================
205 /*
206  \fn PerformDeformation
207  \param ap_Image : required to access oImageSpace image matrices
208  \param a_defIdx : index of the deformation
209  \param a_fr : frame index
210  \param a_rimg : respiratory image index
211  \param a_cimg : cardiac image index
212  \brief Apply deformations during reconstruction
213  \details 1. Recover all the data of the multithreaded backward image matrices in the first one (thread index 0)
214  2. Perform backward deformation of the backward image to the reference position with defIdx-1
215  3. Add coefficients of the backward image matrice to the temporary backup image matrice & reset backward image
216  4. Apply forward deformation of the forward image with defIdx
217  \return 0 if success, positive value otherwise
218 */
219 int vDeformation::PerformDeformation(oImageSpace* ap_Image, int a_defIdx, int a_fr, int a_rimg, int a_cimg)
220 {
221  if(m_verbose >= VERBOSE_DEBUG_NORMAL) Cout("vDeformation::PerformDeformation, transformation parameter #" << a_defIdx << endl);
222 
223  #ifdef CASTOR_DEBUG
224  if (!m_initialized)
225  {
226  Cerr("***** vDeformation::PerformDeformation() -> Called while not initialized !" << endl);
227  Exit(EXIT_DEBUG);
228  }
229  #endif
230 
231  // REDUCE
232  for (int bimg=0; bimg<ap_Image->GetNbBackwardImages(); bimg++)
233  {
234  for (int th=1 ; th<mp_ID->GetNbThreadsForProjection() ; th++) //TODO add 4D loops
235  {
236  // Synchronization of the multi-threaded backwardImages inside the first image Reduce)
237  for(int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
238  ap_Image->m6p_backwardImage[bimg][0][a_fr][a_rimg][a_cimg][v] += ap_Image->m6p_backwardImage[bimg][th][a_fr][a_rimg][a_cimg][v];
239  }
240 
241  // BACKWARD DEFORMATION of the backward image
242  if (a_defIdx > 0 // Check: index must be > 0
243  && ApplyDeformations(ap_Image->m6p_backwardImage[bimg][0][a_fr][a_rimg][a_cimg],
244  ap_Image->m6p_backwardImage[bimg][0][a_fr][a_rimg][a_cimg],
246  a_defIdx-1) )
247  {
248  Cerr("***** vDeformation::ApplyDeformations()-> An error occurred while performing backward deformation of the backward image !" << endl);
249  Cerr("***** frame index " << a_fr << " respiratory image index " << a_rimg<< " cardiac image index " << a_cimg<< " !" << endl);
250  return 1;
251  }
252 
253  // Store Backward deformation update coefficients in the temporary backup image //TODO add loops
254  for (int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
255  ap_Image->m5p_refDynBackwardImage[bimg][a_fr][a_rimg][a_cimg][v] += ap_Image->m6p_backwardImage[bimg][0][a_fr][a_rimg][a_cimg][v];
256  }
257 
258  // Reset the backward images (i.e set all voxels to the specific fr/rimg/cimg to 0)
259  for (int bimg=0; bimg<ap_Image->GetNbBackwardImages(); bimg++)
260  for(int th=0 ; th<mp_ID->GetNbThreadsForProjection() ; th++)
261  for (int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
262  ap_Image->m6p_backwardImage[bimg][th][a_fr][a_rimg][a_cimg][v] = 0.;
263 
264 
265  // Forward deformation of the forward image (from the temporary forward image matrix)
266  if (ApplyDeformations(ap_Image->m4p_refDynForwardImage[a_fr][a_rimg][a_cimg],
267  ap_Image->m4p_forwardImage[a_fr][a_rimg][a_cimg],
269  a_defIdx) )
270  {
271  Cerr("***** vDeformation::ApplyDeformations()-> An error occurred while performing forward deformation of the forward image !" << endl);
272  Cerr("***** frame index " << a_fr << " respiratory image index " << a_rimg<< " cardiac image index " << a_cimg<< " !" << endl);
273  return 1;
274  }
275 
276  return 0;
277 }
278 
279 
280 
281 
282 // =====================================================================
283 // ---------------------------------------------------------------------
284 // ---------------------------------------------------------------------
285 // =====================================================================
286 /*
287  \fn PerformHistoSensitivityDeformation
288  \param ap_Image : required to access oImageSpace image matrices
289  \param a_defIdx : index of the deformation
290  \param fr : frame index
291  \param rimg : respiratory image index
292  \param cimg : cardiac image index
293  \brief Apply deformations on the sensitivity image during reconstruction in histogram mode
294  \details 1. Recover all the data of the multithreaded sensitivity image matrice in the first one (thread index 0)
295  2. Perform backward deformation of the sensitivity image to the reference position with defIdx-1
296  3. Add coefficients of the sensitivity image matrice to the temporary backup image matrice & reset sensitivity image
297  \return 0 if success, positive value otherwise
298 */
299 int vDeformation::PerformHistoSensitivityDeformation(oImageSpace* ap_Image, int a_defIdx, int fr, int rimg, int cimg)
300 {
301  if(m_verbose >= VERBOSE_DETAIL) Cout("vDeformation::PerformHistoSensitivityDeformation ... " <<endl);
302 
303  #ifdef CASTOR_DEBUG
304  if (!m_initialized)
305  {
306  Cerr("***** vDeformation::PerformHistoSensitivityDeformation() -> Called while not initialized !" << endl);
307  Exit(EXIT_DEBUG);
308  }
309  #endif
310 
311  // REDUCE
312  for (int th=1 ; th<mp_ID->GetNbThreadsForProjection() ; th++)
313  {
314  // Synchronisation of the multi-threaded sensitivity images inside the first image )
315  for(int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
316  ap_Image->m5p_sensitivity[0][fr][rimg][cimg][v] += ap_Image->m5p_sensitivity[th][fr][rimg][cimg][v];
317  }
318 
319  // BACKWARD DEFORMATION of the sensitivity image
320  if (a_defIdx > 0 // Check: index must be > 0
321  && ApplyDeformations(ap_Image->m5p_sensitivity[0][fr][rimg][cimg],
322  ap_Image->m5p_sensitivity[0][fr][rimg][cimg],
324  a_defIdx-1) )
325  {
326  Cerr("***** vDeformation::PerformHistoSensitivityDeformation()-> An error occurred while performing backward deformation of the sensitivity image !" << endl);
327  Cerr("***** frame index " << fr << " respiratory image index " << rimg<< " cardiac image index " << cimg<< " !" << endl);
328  return 1;
329  }
330 
331  // Store Backward deformation update coefficients in temporary image
332  for (int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
333  ap_Image->m4p_refDynSensitivityImage[fr][rimg][cimg][v] += ap_Image->m5p_sensitivity[0][fr][rimg][cimg][v];
334 
335  // Reset the sensitivity images (i.e set all voxels to the specific fr/rimg/cimg to 0)
336  for (int th=0; th<mp_ID->GetNbThreadsForProjection(); th++)
337  for (int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
338  ap_Image->m5p_sensitivity[th][fr][rimg][cimg][v] = 0.;
339 
340  return 0;
341 }
342 
343 
344 
345 
346 // =====================================================================
347 // ---------------------------------------------------------------------
348 // ---------------------------------------------------------------------
349 // =====================================================================
350 /*
351  \fn PerformSensitivityDeformation
352  \param ap_Image : required to access oImageSpace image matrices
353  \param a_defDirection : a direction for the deformation to perform (forward or backward)
354  \param a_defIdx : index of the deformation
355  \param fr : frame index
356  \param rg : respiratory gate index
357  \param cg : cardiac gate index
358  \brief Apply image deformations during sensitivity image generation for list-mode
359  \details Depending on the deformation direction (forward or backward):
360  Forward : Perform forward deformation of the forward image to the deformation index position
361  Backward: Perform backward deformation of the backward image to the reference position
362  \return 0 if success, positive value otherwise
363 */
364 int vDeformation::PerformSensitivityDeformation(oImageSpace* ap_Image, int a_defDirection, int a_defIdx, int fr, int rg, int cg)
365 {
366  if(m_verbose >= VERBOSE_DEBUG_NORMAL) Cout("vDeformation::PerformSensitivityDeformation ... " << endl);
367 
368  #ifdef CASTOR_DEBUG
369  if (!m_initialized)
370  {
371  Cerr("***** vDeformation::PerformSensitivityDeformation() -> Called while not initialized !" << endl);
372  Exit(EXIT_DEBUG);
373  }
374  #endif
375 
376  if (a_defDirection == FORWARD_DEFORMATION)
377  {
378  if (ApplyDeformations(ap_Image->m4p_forwardImage[fr][rg][cg],
379  ap_Image->m4p_forwardImage[fr][rg][cg],
380  a_defDirection,
381  a_defIdx) )
382  {
383  Cerr("***** vDeformation::PerformSensitivityDeformation -> An error occurred while performing forward deformation !" << endl);
384  Cerr("***** frame index " << fr << " respiratory gate index " << rg<< " cardiac gate index " << cg<< " !" << endl);
385  return 1;
386  }
387  }
388  else if (a_defDirection == BACKWARD_DEFORMATION)
389  {
390  if (ApplyDeformations(ap_Image->m6p_backwardImage[0][0][fr][rg][cg],
391  ap_Image->m6p_backwardImage[0][0][fr][rg][cg],
392  a_defDirection,
393  a_defIdx) )
394  {
395  Cerr("***** vDeformation::PerformSensitivityDeformation -> An error occurred while performing backward deformation !" << endl);
396  Cerr("***** frame index " << fr << " respiratory gate index " << rg<< " cardiac gate index " << cg<< " !" << endl);
397  return 1;
398  }
399  }
400  else
401  {
402  Cerr("***** vDeformation::PerformDeformation -> Unknown type of deformation !" << endl);
403  return 1;
404  }
405 
406  return 0;
407 }
408 
409 
410 
411 
412 /*
413  \fn Tlerp
414  \param ap_inputImage : input image matrix
415  \param ap_outputImage : output image matrix
416  \param iov : index of the voxel to interpolate in the output image
417  \param iiv : index of the input image central voxel for interpolation
418  \param dx : x-axis difference between output voxel cartesian position after transformation and center of estimated vox position
419  \param dy : y-axis difference between output voxel cartesian position after transformation and center of estimated vox position
420  \param dz : z-axis difference between output voxel cartesian position after transformation and center of estimated vox position
421  \brief This function performs a trilinear interpolation for a specific voxel
422  \todo : perhaps use padded image in order to avoid if statements
423  \return 0 if success, other value otherwise.
424 */
425 int vDeformation::Tlerp(HPFLTNB *ap_inputImage, HPFLTNB *ap_outputImage, uint32_t iov, uint32_t iiv, FLTNB dX, FLTNB dY, FLTNB dZ)
426 {
427  // Trilinear interpolation
428  // Todo : Use padded image in order to avoid 'if' statements ?
429  int incX = dX>0 ? 1 : -1;
430  int incY = dY>0 ? mp_ID->GetNbVoxX() : -mp_ID->GetNbVoxX();
431  int incZ = dZ>0 ? mp_ID->GetNbVoxXY() : -mp_ID->GetNbVoxXY();
432 
433  dX = (dX>=0) ? dX : -dX;
434  dY = (dY>=0) ? dY : -dY;
435  dZ = (dZ>=0) ? dZ : -dZ;
436 
437  uint32_t nb_tot_vox = (uint32_t)mp_ID->GetNbVoxXYZ();
438 
439  if ((iiv < nb_tot_vox)
440  && (iiv >= 0))
441  ap_outputImage[iov] += ap_inputImage[iiv] * (1.-dX)*(1.-dY)*(1.-dZ);
442 
443  if ((iiv+incX < nb_tot_vox)
444  && (((int)iiv)+incX >= 0))
445  ap_outputImage[iov] += ap_inputImage[iiv+incX] * dX*(1.-dY)*(1.-dZ);
446 
447  if ((iiv+incY < nb_tot_vox )
448  && (((int)iiv)+incY >= 0))
449  ap_outputImage[iov] += ap_inputImage[iiv +incY] * (1.-dX)*dY*(1.-dZ);
450 
451  if ((iiv+incX+incY < nb_tot_vox)
452  && ( ((int)iiv)+incX+incY >= 0))
453  ap_outputImage[iov] += ap_inputImage[iiv+incX+incY] * dX*dY*(1.-dZ);
454 
455  if ((iiv+incZ < nb_tot_vox)
456  && (((int)iiv)+incZ) >= 0)
457  ap_outputImage[iov] += ap_inputImage[iiv+incZ] * (1.-dX)*(1.-dY)*dZ;
458 
459  if ((iiv+incX+incZ) < nb_tot_vox
460  && (((int)iiv)+incX+incZ) >=0 )
461  ap_outputImage[iov] += ap_inputImage[iiv+incX+incZ] * dX*(1.-dY)*dZ;
462 
463  if ((iiv+incY+incZ < nb_tot_vox)
464  && (((int)iiv)+incY+incZ >= 0))
465  ap_outputImage[iov] += ap_inputImage[iiv+incY+incZ] * (1.-dX)*dY*dZ;
466 
467  if ((iiv+incX+incY+incZ < nb_tot_vox)
468  && (((int)iiv)+incX+incY+incZ >= 0))
469  ap_outputImage[iov] += ap_inputImage[iiv+incX+incY+incZ] *dX*dY*dZ;
470 
471 
472  return 0;
473 }
vDeformation()
Constructor of vDeformation. Simply set all data members to default values.
virtual ~vDeformation()
Destructor of vDeformation.
virtual int ApplyDeformationsToBackwardImage(oImageSpace *ap_Image, int a_fr, int a_defIdx)
#define Cerr(MESSAGE)
#define FORWARD_DEFORMATION
virtual int PerformDeformation(oImageSpace *ap_Image, int a_defIdx, int a_fr, int a_rimg, int a_cimg)
#define BACKWARD_DEFORMATION
virtual int PerformHistoSensitivityDeformation(oImageSpace *ap_Image, int a_defIdx, int fr, int rimg, int cimg)
void Exit(int code)
virtual int CheckParameters()
This function is used to check parameters after the latter have been all set using Set functions...
int Tlerp(HPFLTNB *ap_inputImage, HPFLTNB *ap_outputImage, uint32_t iov, uint32_t iiv, FLTNB dX, FLTNB dY, FLTNB dZ)
virtual int ApplyDeformations(FLTNB *ap_inputImage, FLTNB *ap_outputImage, int a_direction, int a_defIdx)=0
oImageDimensionsAndQuantification * mp_ID
virtual int PerformSensitivityDeformation(oImageSpace *ap_Image, int a_defDirection, int a_defIdx, int fr, int rg, int cg)
This class holds all the matrices in the image domain that can be used in the algorithm: image...
int GetNbThreadsForProjection()
Get the number of threads used for projections.
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
virtual int CheckSpecificParameters()=0
This function is used to check the parameters of the child functions before initialization if require...
#define Cout(MESSAGE)
virtual int ApplyDeformationsToHistoSensitivityImage(oImageSpace *ap_Image, int a_fr, int a_defIdx)