CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
src/image/iDeformationRigid.cc
Go to the documentation of this file.
1 
8 #include "iDeformationRigid.hh"
9 
10 // =====================================================================
11 // ---------------------------------------------------------------------
12 // ---------------------------------------------------------------------
13 // =====================================================================
14 /*
15  \fn iDeformationRigid
16  \brief Constructor of iDeformationRigid. Simply set all data members to default values.
17 */
19 {
20  mp_OriginalArray = NULL;
21  mp_OutputArray = NULL;
22  mp_tX = NULL;
23  mp_tY = NULL;
24  mp_tZ = NULL;
25  mp_rA = NULL;
26  mp_rB = NULL;
27  mp_rC = NULL;
28  m2p_FTmtx = NULL;
29  m2p_BTmtx = NULL;
30  m_rotConvention = "XYZ";
31  m_cmpTransfoFlag = true;
32 }
33 
34 
35 
36 
37 // =====================================================================
38 // ---------------------------------------------------------------------
39 // ---------------------------------------------------------------------
40 // =====================================================================
41 /*
42  \fn ~iDeformationRigid
43  \brief Destructor of iDeformationRigid. Free memory from all allocated tabs.
44 */
46 {
47  if(m_initialized)
48  {
50  if(mp_OutputArray) delete[] mp_OutputArray;
51  }
52 
53  for(int t=0; t<m_nbTransformations; t++)
54  {
55  if (m2p_FTmtx[t]) delete m2p_FTmtx[t];
56  if (m2p_BTmtx[t]) delete m2p_BTmtx[t];
57  }
58 
59  if(m2p_FTmtx) delete[] m2p_FTmtx;
60  if(m2p_BTmtx) delete[] m2p_BTmtx;
61 
62 
63  if(mp_tX) delete[] mp_tX;
64  if(mp_tY) delete[] mp_tY;
65  if(mp_tZ) delete[] mp_tZ;
66  if(mp_rA) delete[] mp_rA;
67  if(mp_rB) delete[] mp_rB;
68  if(mp_rC) delete[] mp_rC;
69 
70 }
71 
72 
73 
74 
75 // =====================================================================
76 // ---------------------------------------------------------------------
77 // ---------------------------------------------------------------------
78 // =====================================================================
79 /*
80  \fn ShowHelp
81  \brief This function is used to print out specific help about the deformation and its options.
82 */
84 {
85  // todo : really we should rather use param files in binary format here
86  cout << "-- Rigid transformation algorithm based on trilinear interpolation --" << endl;
87  cout << "Each transformation requires 3 translation (x,y,z) and 3 rotation parameters, provided by command-line option or in a text file" << endl;
88  cout << "The transformation parameters can be either defined between: " << endl;
89  cout << "- A position n and the following position n+1 " << endl;
90  cout << "- A reference position and the actual position n (default) " << endl;
91  cout << " (Check the 'Transformation mode' keyword below for more information) " << endl;
92  cout << endl;
93  cout << "--------------------------------------------------------" << endl;
94  cout << "Command-line options:" <<endl;
95  cout << "Parameters for each transformation must be provided sequentially and separated by commas" << endl;
96  cout << "Example for a dataset containing 3 transformations:" << endl;
97  cout << "-rm deformationRigid:trX1,trY1,trZ1,rotX1,rotY1,rotZ1,trX2,trY2,trZ2,rotX2,rotY2,rotZ2,trX3,trY3,trZ3,rotX3,rotY3,rotZ3" << endl;
98  cout << "--------------------------------------------------------" << endl;
99  cout << "Text file:" <<endl;
100  cout << "Parameters for each transformation must be provided after a 'Transformation parameters' key, on a separate line, and separated by commas" << endl;
101  cout << "Translations must be provided in mm, for each axis." << endl;
102  cout << "Rotations must be provided in degree. Use the Rotation convention optional parameter in order to set up the rotation orientation." << endl;
103  cout << "Example for a dataset containing 3 transformations:" << endl;
104  cout << "Transformation_parameters:" << endl;
105  cout << "trX1,trY1,trZ1,rotA1,rotB1,rotC1" << endl;
106  cout << "trX2,trY2,trZ2,rotA2,rotB2,rotC2" << endl;
107  cout << "trX3,trY3,trZ3,rotA3,rotB3,rotC3" << endl;
108  cout << "etc..." << endl;
109  cout << endl;
110  cout << "--------------------------------------------------------" << endl;
111  cout << "Optional parameters (configuration file only):" << endl;
112  cout << endl;
113  cout << "Rotation_convention: Any combinations of 'x', 'y', and 'z'" << endl;
114  cout << "Define the axe on which the rotation will be performed using rotA, rotB and rotC angle in 1 (default): XYZ" << endl;
115  cout << endl;
116  cout << "Transformation_mode: (1 or 0)" << endl;
117  cout << "0 (default): Transformation between the reference position to the n position." << endl;
118  cout << "1 : Transformation between the n-1 position to the n position." << endl;
119  cout << " They will be recomputed to represent transformations from a reference position to i as required by CASToR" << endl;
120 
121 }
122 
123 
124 
125 
126 // =====================================================================
127 // ---------------------------------------------------------------------
128 // ---------------------------------------------------------------------
129 // =====================================================================
130 /*
131  \fn ReadAndCheckConfigurationFile
132  \param a_configurationFile
133  \brief This function is used to read options from a configuration file.
134  \return 0 if success, other value otherwise.
135 */
136 int iDeformationRigid::ReadAndCheckConfigurationFile(const string& a_fileOptions)
137 {
138  if (m_verbose >=VERBOSE_DETAIL) Cout("iDeformationRigid::ReadAndCheckConfigurationFile ..."<< endl);
139 
140  // First, check the nb of transformations has correctly been initializeds
141  if (m_nbTransformations<0)
142  {
143  Cerr("***** iDeformationRigid::ReadAndCheckConfigurationFile() -> Number of transformations in the deformation has not been initialized !" << endl);
144  return 1;
145  }
146 
147 
148  ifstream in_file(a_fileOptions.c_str(), ios::in);
149 
150  if(in_file)
151  {
152  // Local array to recover rigid transformation parameters
153  HPFLTNB* p_coeffs = new HPFLTNB[m_nbTransformations*6];
154 
155  // Read 6 parameters for each transformations, on each line
156  if (ReadDataASCIIFile(a_fileOptions, "Transformation_parameters", p_coeffs, 6, m_nbTransformations, KEYWORD_MANDATORY))
157  {
158  Cerr("***** iDeformationRigid::ReadAndCheckConfigurationFile -> A problem occurred while trying to recover transformation parameters from file !" << endl);
159  return 1;
160  }
161 
162  // Read 6 parameters for each transformations, on each line
163  if (ReadDataASCIIFile(a_fileOptions, "Transformation_mode", &m_cmpTransfoFlag, 1, KEYWORD_OPTIONAL) == KEYWORD_OPTIONAL_ERROR)
164  {
165  Cerr("***** iDeformationRigid::ReadAndCheckConfigurationFile -> A problem occurred while trying to read 'compute_transformations' flag (must be 1 (true) or 0 (false))!" << endl);
166  return 1;
167  }
168 
169  // Read 6 parameters for each transformations, on each line
170  if (ReadDataASCIIFile(a_fileOptions, "Rotation_convention", &m_rotConvention, 1, KEYWORD_OPTIONAL) == KEYWORD_OPTIONAL_ERROR)
171  {
172  Cerr("***** iDeformationRigid::ReadAndCheckConfigurationFile -> A problem occurred while trying to read rotation convention (string) !" << endl);
173  return 1;
174  }
175 
176  // Allocate memory for each parameter
183 
184  // Recover parameters
185  for(int t=0 ; t<m_nbTransformations ; t++)
186  {
187  mp_tX[t] = p_coeffs[t*6];
188  mp_tY[t] = p_coeffs[t*6+1];
189  mp_tZ[t] = p_coeffs[t*6+2];
190  mp_rA[t] = p_coeffs[t*6+3];
191  mp_rB[t] = p_coeffs[t*6+4];
192  mp_rC[t] = p_coeffs[t*6+5];
193  }
194 
196  {
197  Cerr("***** iDeformationRigid::ReadAndCheckOptionsList() -> An error occurred while building Transformation matrices !" << endl);
198  return 1;
199  }
200 
201  // Delete local objects
202  delete[] p_coeffs;
203  }
204  else
205  {
206  Cerr("***** iDeformationRigid::ReadAndCheckConfigurationFile -> Error while trying to read configuration file : " << a_fileOptions << endl);
207  return 1;
208  }
209 
210  return 0;
211 }
212 
213 // =====================================================================
214 // ---------------------------------------------------------------------
215 // ---------------------------------------------------------------------
216 // =====================================================================
217 /*
218  \fn ReadAndCheckOptionsList
219  \param a_optionsList
220  \brief This function is used to read options from a list of options.
221  Throw error by defaut for this method, as a file has to be used for initialization
222  \return 0 if success, other value otherwise.
223 */
224 int iDeformationRigid::ReadAndCheckOptionsList(const string& a_listOptions)
225 {
226  if(m_verbose >=VERBOSE_DETAIL) Cout("iDeformationRigid::ReadAndCheckOptionsList ..."<< endl);
227 
228  // First, check the nb of transformations has correctly been initializeds
229  if (m_nbTransformations<0)
230  {
231  Cerr("***** iDeformationRigid::ReadAndCheckOptionsList() -> Number of transformations in the deformation has not been initialized !" << endl);
232  return 1;
233  }
234 
235  // Local array to recover rigid transformation parameters
236  HPFLTNB* p_coeffs = new HPFLTNB[m_nbTransformations*6];
237 
238  if (ReadStringOption(a_listOptions,
239  p_coeffs,
240  m_nbTransformations*6,
241  ",",
242  "Rigid deformation configuration"))
243  {
244  Cerr("***** iDeformationRigid::ReadAndCheckOptionsList() -> Failed to correctly read the list of parameters in command-line options !" << endl);
245  Cerr("***** "<<m_nbTransformations*6<<" parameters were expected (6 parameters for each transformation)" << endl);
246  return 1;
247  }
248 
249  // Allocate memory for each parameter
250 
257 
258  // Recover parameters
259  for(int t=0 ; t<m_nbTransformations ; t++)
260  {
261  mp_tX[t] = p_coeffs[t*6];
262  mp_tY[t] = p_coeffs[t*6+1];
263  mp_tZ[t] = p_coeffs[t*6+2];
264  mp_rA[t] = p_coeffs[t*6+3];
265  mp_rB[t] = p_coeffs[t*6+4];
266  mp_rC[t] = p_coeffs[t*6+5];
267  }
268 
270  {
271  Cerr("***** iDeformationRigid::ReadAndCheckOptionsList() -> An error occurred while building Transformation matrices !" << endl);
272  return 1;
273  }
274 
275  delete[] p_coeffs;
276 
277  // Normal end
278  return 0;
279 }
280 
281 
282 
283 
284 // =====================================================================
285 // ---------------------------------------------------------------------
286 // ---------------------------------------------------------------------
287 // =====================================================================
288 /*
289  \fn ComputeTransformationMatrices
290  \brief Initialize transformation matrices from parameters
291  \return 0 if success, positive value otherwise.
292 */
294 {
295  // Check initialization has been done
296  if( mp_tX==NULL || mp_tY==NULL || mp_tZ==NULL ||
297  mp_rA==NULL || mp_rB==NULL || mp_rC==NULL )
298  {
299  Cerr("***** iDeformationRigid::ComputeTransformationMatrices() -> Parameters not initialized !" << endl);
300  return 1;
301  }
302 
303  // Allocate tmp matrices (translation, rotation, and backup)
304  oMatrix *p_trs_mtx = new oMatrix(4,4);
305  oMatrix *p_rot_mtx = new oMatrix(4,4);
306  oMatrix *p_tmp_mtx = new oMatrix(4,4);
307 
308  // Allocate transformation matrices
311 
312 
313  for(int t=0; t<m_nbTransformations; t++)
314  {
315  // Allocate matrices for this transformation
316  m2p_FTmtx[t] = new oMatrix(4,4);
317  m2p_BTmtx[t] = new oMatrix(4,4);
318 
319  FLTNB tx = mp_tX[t];
320  FLTNB ty = mp_tY[t];
321  FLTNB tz = mp_tZ[t];
322  FLTNB x_rad = mp_rA[t] * M_PI/180.;
323  FLTNB y_rad = mp_rB[t] * M_PI/180.;
324  FLTNB z_rad = mp_rC[t] * M_PI/180.;
325 
326  // For both direction
327  for(int d=0 ; d<2 ; d++)
328  {
329  if (d == 1)
330  {
331  tx = -tx;
332  ty = -ty;
333  tz = -tz;
334  x_rad = -mp_rA[t] * M_PI/180.;
335  y_rad = -mp_rB[t] * M_PI/180.;
336  z_rad = -mp_rC[t] * M_PI/180.;
337  }
338 
339  // Set translation matrix
340  p_trs_mtx->SetMatriceElt(0,0, 1 );
341  p_trs_mtx->SetMatriceElt(0,1, 0 );
342  p_trs_mtx->SetMatriceElt(0,2, 0);
343  p_trs_mtx->SetMatriceElt(0,3, -tx);
344  p_trs_mtx->SetMatriceElt(1,0, 0 );
345  p_trs_mtx->SetMatriceElt(1,1, 1 );
346  p_trs_mtx->SetMatriceElt(1,2, 0);
347  p_trs_mtx->SetMatriceElt(1,3, -ty);
348  p_trs_mtx->SetMatriceElt(2,0, 0 );
349  p_trs_mtx->SetMatriceElt(2,1, 0 );
350  p_trs_mtx->SetMatriceElt(2,2, 1);
351  p_trs_mtx->SetMatriceElt(2,3, -tz);
352  p_trs_mtx->SetMatriceElt(3,0, 0 );
353  p_trs_mtx->SetMatriceElt(3,1, 0 );
354  p_trs_mtx->SetMatriceElt(3,2, 0);
355  p_trs_mtx->SetMatriceElt(3,3, 1);
356 
357  // Set rotation matrix (ZYX)
358  if(SetRotationMatrix(p_rot_mtx, x_rad, y_rad, z_rad, m_rotConvention))
359  {
360  Cerr("***** iDeformationRigid::ComputeTransformationMatrices() -> Error occurred when initializing rotation matrices !" << endl);
361  return 1;
362  }
363 
364  // Compute forward or backward transformation matrix from t to t+1
365  (d == 0) ?
366  p_trs_mtx->Multiplication(p_rot_mtx, m2p_FTmtx[t]):
367  p_trs_mtx->Multiplication(p_rot_mtx, m2p_BTmtx[t]);
368  }
369 
370  // Compute transformation matrices from and toward reference position
371 
372  if(m_cmpTransfoFlag && t>0)
373  {
374  // forward transformation matrix
375  m2p_FTmtx[t]->Multiplication( m2p_FTmtx[t-1], p_tmp_mtx );
376 
377  for(int l=0 ; l<4 ; l++)
378  for(int c=0 ; c<4 ; c++)
379  m2p_FTmtx[t]->SetMatriceElt(l,c, p_tmp_mtx->GetMatriceElt(l,c) );
380 
381  // backward transformation matrix
382  m2p_BTmtx[t]->Multiplication( m2p_BTmtx[t-1], p_tmp_mtx );
383 
384  for(int l=0 ; l<4 ; l++)
385  for(int c=0 ; c<4 ; c++)
386  m2p_BTmtx[t]->SetMatriceElt(l,c, p_tmp_mtx->GetMatriceElt(l,c) );
387  }
388  }
389 
390  delete p_trs_mtx;
391  delete p_rot_mtx;
392  delete p_tmp_mtx;
393 
394  return 0;
395 }
396 
397 
398 
399 
400 // =====================================================================
401 // ---------------------------------------------------------------------
402 // ---------------------------------------------------------------------
403 // =====================================================================
404 /*
405  \fn CheckSpecificParameters
406  \brief This function is used to check parameters after the latter
407  have been all set using Set functions.
408  \return 0 if success, positive value otherwise.
409 */
411 {
412  if(m_verbose >= VERBOSE_DETAIL) Cout("iDeformationRigid::CheckSpecificParameters ..."<< endl);
413 
414  // Check vector files
415  if (!mp_tX ||
416  !mp_tY ||
417  !mp_tZ ||
418  !mp_rA ||
419  !mp_rB ||
420  !mp_rC )
421  {
422  Cerr("***** iDeformationRigid::CheckSpecificParameters() -> Transformation parameters not initialized !" << endl);
423  return 1;
424  }
425 
426  // Normal end
427  m_checked = true;
428  return 0;
429 }
430 
431 // =====================================================================
432 // ---------------------------------------------------------------------
433 // ---------------------------------------------------------------------
434 // =====================================================================
435 /*
436  \fn Initialize
437  \brief This function is used to initialize specific stuff in the deformation model.
438  \details Allocate memory for image matrices, and initialize images containing transformation parameters
439  \return 0 if success, other value otherwise.
440 */
442 {
443  if(m_verbose >=VERBOSE_NORMAL) Cout("iDeformationRigid::Initialize ..."<< endl);
444 
445  // Forbid initialization without check
446  if (!m_checked)
447  {
448  Cerr("***** iDeformationRigid::Initialize() -> Parameters should be checked before Initialize() !" << endl);
449  return 1;
450  }
451 
452  // Memory allocation for image matrices
455 
456  // Normal end
457  m_initialized = true;
458  return 0;
459 }
460 
461 // =====================================================================
462 // ---------------------------------------------------------------------
463 // ---------------------------------------------------------------------
464 // =====================================================================
465 /*
466  \fn ApplyDeformations
467  \param ap_inputImage : input image to deform
468  \param ap_outputImage : image in which the output of the deformation should be recovered
469  \param a_direction : a direction for the deformation to perform (forward or backward)
470  \param a_defIdx : index of the deformation
471  \brief This function prepares the deformation to perform
472  \details 1. Selects the right deformation parameters file according to the direction and deformation index argument
473  2. Copy the image to deform in the buffer image of this class
474  3. Call the deformation function (TransformImage)
475  4. Copy back the output of the deformation image to the output image matrice passed in argument
476  \return 0 if success, other value otherwise.
477 */
478 int iDeformationRigid::ApplyDeformations(FLTNB* ap_inputImage, FLTNB* ap_outputImage, int a_direction, int a_defIdx)
479 {
480  #ifdef CASTOR_DEBUG
481  if (!m_initialized)
482  {
483  Cerr("***** iDeformationRigid::ApplyDeformations() -> Called while not initialized !" << endl);
484  Exit(EXIT_DEBUG);
485  }
486  #endif
487 
488  if(m_verbose >= VERBOSE_DETAIL) Cout("iDeformationRigid::ApplyDeformations #" << a_defIdx+1 << " ("
489  << (string)((a_direction==FORWARD_DEFORMATION)?"forward":"backward") << "), with parameters "
490  << mp_tX[a_defIdx] << ";" << mp_tY[a_defIdx] << ";" << mp_tZ[a_defIdx] << ";"
491  << mp_rA[a_defIdx] << ";" << mp_rB[a_defIdx] << ";" << mp_rC[a_defIdx] << ";" << endl);
492 
493  for(int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
494  {
495  mp_OriginalArray[v] = (HPFLTNB) ap_inputImage[v];
496  mp_OutputArray[v] = 0.;
497  }
498 
499  // Apply all required deformations
500  TransformImage(a_direction, a_defIdx, mp_OriginalArray, mp_OutputArray);
501 
502  for(int v=0; v<mp_ID->GetNbVoxXYZ(); v++)
503  {
504  if (mp_OutputArray[v] < 0) mp_OutputArray[v] = 0.;
505  ap_outputImage[v] = (FLTNB) mp_OutputArray[v];
506  }
507 
508  return 0;
509 }
510 
511 
512 
513 
514 // =====================================================================
515 // ---------------------------------------------------------------------
516 // ---------------------------------------------------------------------
517 // =====================================================================
518 /*
519  \fn TransformImage
520  \param a_vectorFileIdx : deformation vector file
521  \param ap_inputImage : image on which the deformation should be performed
522  \param ap_outputImage : matrice which recovers the image after deformation
523  \brief This function performs a rigid transformation using x,y,z displacement vectors and trilinear interpolation
524  \details 1. Load the X,Y,Z transformation vectors from the file passed in argument
525  2. Loop on the voxels and compute the new voxels value using trilinear interpolation
526  \todo : perhaps add options to load all the vector parameters in RAM during initialization, instead on reading files during reconstruction
527  \todo : perhaps use padded image in order to avoid if statements
528  \return 0 if success, other value otherwise.
529 */
530 int iDeformationRigid::TransformImage(int a_direction, int a_defIdx, HPFLTNB *ap_inputImage, HPFLTNB *ap_outputImage)
531 {
532  #ifdef CASTOR_VERBOSE
533  if(m_verbose >=VERBOSE_DETAIL) Cout("iDeformationRigid::TransformImage() ... : "<< endl);
534  #endif
535 
536  // Set vectors to recover voxel locations before/after transformation
537  oMatrix *iVect = new oMatrix(4,1);
538  oMatrix *oVect = new oMatrix(4,1);
539 
540  // Recover image dimensions variables
541  FLTNB sX = mp_ID->GetVoxSizeX();
542  FLTNB sY = mp_ID->GetVoxSizeY();
543  FLTNB sZ = mp_ID->GetVoxSizeZ();
544  FLTNB dX = mp_ID->GetNbVoxX();
545  FLTNB dY = mp_ID->GetNbVoxY();
546  FLTNB dZ = mp_ID->GetNbVoxZ();
547  FLTNB dXY = mp_ID->GetNbVoxXY();
548 
549 
550  // Loop on voxels
551  for(int v=0 ; v<mp_ID->GetNbVoxXYZ() ; v++)
552  {
553  // Get voxel index by axis
554  uint32_t iZ = v/mp_ID->GetNbVoxXY();
555  uint32_t iY = (v - iZ*mp_ID->GetNbVoxXY()) / mp_ID->GetNbVoxX();
556  uint32_t iX = v - iZ*mp_ID->GetNbVoxXY() - iY*mp_ID->GetNbVoxX();
557 
558  // Set input vector
559  iVect->SetMatriceElt(0,0, iX*sX - dX*sX/2 + sX*0.5);
560  iVect->SetMatriceElt(1,0, iY*sY - dY*sY/2 + sY*0.5);
561  iVect->SetMatriceElt(2,0, iZ*sZ - dZ*sZ/2 + sZ*0.5);
562  iVect->SetMatriceElt(3,0, 1);
563 
564  // Compute output vector with the correct related matrix
565  if (a_direction==FORWARD_DEFORMATION)
566  m2p_FTmtx[a_defIdx]->Multiplication(iVect, oVect);
567  else if (a_direction==BACKWARD_DEFORMATION)
568  m2p_BTmtx[a_defIdx]->Multiplication(iVect, oVect);
569  else
570  {
571  Cerr("*****iDeformationRigid::ApplyDeformationToForwardImage()->Error, unknown direction type( must be 'forward' or 'backward' # " << endl);
572  return 1;
573  }
574 
575  // Get index of the voxel to be interpolated in the input image
576  uint32_t ivZ = (oVect->GetMatriceElt(2,0) + dZ*sZ/2) / sZ;
577  uint32_t ivY = (oVect->GetMatriceElt(1,0) + dY*sY/2) / sY;
578  uint32_t ivX = (oVect->GetMatriceElt(0,0) + dX*sX/2) / sX;
579  uint32_t iv = ivZ*dXY + ivY*dX + ivX;
580 
581  // Compute difference between cartesian position after transformation and center of estimated vox position
582  FLTNB dvX, dvY, dvZ;
583  dvZ = (oVect->GetMatriceElt(2,0) - (ivZ*sZ - dZ*sZ/2 + sZ*0.5) ) / sZ;
584  dvY = (oVect->GetMatriceElt(1,0) - (ivY*sY - dY*sY/2 + sY*0.5) ) / sY;
585  dvX = (oVect->GetMatriceElt(0,0) - (ivX*sX - dX*sX/2 + sX*0.5) ) / sX;
586 
587  // Set constraints
588  if (dvX>1) dvX =1;
589  if (dvY>1) dvY =1;
590  if (dvZ>1) dvZ =1;
591  if (dvX<-1) dvX =-1;
592  if (dvY<-1) dvY =-1;
593  if (dvZ<-1) dvZ =-1;
594 
595  // Get Tlerp of destination voxel
596  Tlerp(ap_inputImage, ap_outputImage, v, iv, dvX, dvY, dvZ);
597  }
598 
599  delete iVect;
600  delete oVect;
601 
602  return 0;
603 }
604 
605 
606 
607 
608 /*
609  \fn SetRotationMatrix(oMatrix* apRotMtx, FLTNB a_ang1, FLTNB a_ang2, FLTNB a_ang3, string a_cvt)
610  \param apRotMtx : Rotation oMatrix to initialize
611  \param a_ang1 : 1st rotation angle (rad)
612  \param a_ang2 : 2nd rotation angle (rad)
613  \param a_ang3 : 3rd rotation angle (rad)
614  \param a_cvt : rotation convention (must be any combinations of 'x', 'y', and 'z'. (Default: xyz) )
615  \brief This function set the rotation matrix passed in parameter with the provided angles in radian
616  and rotation convention
617  \todo Check this function, add missing conventions
618  \return 0 if success, other value otherwise.
619 */
620 int iDeformationRigid::SetRotationMatrix(oMatrix* apRotMtx, FLTNB a_ang1, FLTNB a_ang2, FLTNB a_ang3, string a_cvt)
621 {
622  oMatrix *r1 = new oMatrix(3,3);
623  oMatrix *r2 = new oMatrix(3,3);
624  oMatrix *r3 = new oMatrix(3,3);
625  oMatrix *rtmp = new oMatrix(3,3);
626 
627 
628  // Set up rotation matrix according to the convention
629  string a = a_cvt.substr(0, 1);
630  string b = a_cvt.substr(1, 1);
631  string c = a_cvt.substr(2, 1);
632 
633 
634  if (a == "X" || a == "x")
635  r1->SetXRotMtx(a_ang1);
636  else if(a == "Y" || a == "y")
637  r1->SetYRotMtx(a_ang1);
638  else if(a == "Z" || a == "z")
639  r1->SetZRotMtx(a_ang1);
640  else
641  {
642  Cerr("*****iDeformationRigid::SetRotationMatrix()-> Symbol'"<< a << "' unknown for rotation convention! " << endl);
643  return 1;
644  }
645 
646  // Set up rotation matrix according to the convention
647  if (b == "X" || b == "x")
648  r2->SetXRotMtx(a_ang2);
649  else if(b == "Y" || b == "y")
650  r2->SetYRotMtx(a_ang2);
651  else if(b == "Z" || b == "z")
652  r2->SetZRotMtx(a_ang2);
653  else
654  {
655  Cerr("*****iDeformationRigid::SetRotationMatrix()-> Symbol'"<< b << "' unknown for rotation convention! " << endl);
656  return 1;
657  }
658 
659  // Set up rotation matrix according to the convention
660  if (c == "X" || c == "x")
661  r3->SetXRotMtx(a_ang3);
662  else if(c == "Y" || c == "y")
663  r3->SetYRotMtx(a_ang3);
664  else if(c == "Z" || c == "z")
665  r3->SetZRotMtx(a_ang3);
666  else
667  {
668  Cerr("*****iDeformationRigid::SetRotationMatrix()-> Symbol'"<< c << "' unknown for rotation convention! " << endl);
669  return 1;
670  }
671 
672  // r1*r2. Recover result in rtmp
673  r1->Multiplication(r2, rtmp);
674 
675  // rtmp*r3. Recover result in r1
676  rtmp->Multiplication(r3, r1);
677 
678 
679  // Set up rotation matrix with r1
680  apRotMtx->SetMatriceElt(0,0, r1->GetMatriceElt(0,0) );
681  apRotMtx->SetMatriceElt(0,1, r1->GetMatriceElt(0,1) );
682  apRotMtx->SetMatriceElt(0,2, r1->GetMatriceElt(0,2));
683  apRotMtx->SetMatriceElt(0,3, 0);
684  apRotMtx->SetMatriceElt(1,0, r1->GetMatriceElt(1,0) );
685  apRotMtx->SetMatriceElt(1,1, r1->GetMatriceElt(1,1) );
686  apRotMtx->SetMatriceElt(1,2, r1->GetMatriceElt(1,2));
687  apRotMtx->SetMatriceElt(1,3, 0);
688  apRotMtx->SetMatriceElt(2,0, r1->GetMatriceElt(2,0));
689  apRotMtx->SetMatriceElt(2,1, r1->GetMatriceElt(2,1) );
690  apRotMtx->SetMatriceElt(2,2, r1->GetMatriceElt(2,2));
691  apRotMtx->SetMatriceElt(2,3, 0);
692  apRotMtx->SetMatriceElt(3,0, 0 );
693  apRotMtx->SetMatriceElt(3,1, 0 );
694  apRotMtx->SetMatriceElt(3,2, 0);
695  apRotMtx->SetMatriceElt(3,3, 1);
696 
697  /*
698  HPFLTNB cx = cos(a_ang1);
699  HPFLTNB cy = cos(a_ang2);
700  HPFLTNB cz = cos(a_ang3);
701  HPFLTNB sx = sin(a_ang1);
702  HPFLTNB sy = sin(a_ang2);
703  HPFLTNB sz = sin(a_ang3);
704 
705  if(a_cvt == "XYZ" || a_cvt == "xyz")
706  {
707  apRotMtx->SetMatriceElt(0,0, cy*cz );
708  apRotMtx->SetMatriceElt(0,1, -cy*sz );
709  apRotMtx->SetMatriceElt(0,2, sy);
710  apRotMtx->SetMatriceElt(0,3, 0);
711  apRotMtx->SetMatriceElt(1,0, sx*sy*cz + cx*sz );
712  apRotMtx->SetMatriceElt(1,1, -sx*sy*sz + cx*cz );
713  apRotMtx->SetMatriceElt(1,2, -sx*cy);
714  apRotMtx->SetMatriceElt(1,3, 0);
715  apRotMtx->SetMatriceElt(2,0, -cx*sy*cz + sx*sz );
716  apRotMtx->SetMatriceElt(2,1, cx*sy*sz + sx*cz );
717  apRotMtx->SetMatriceElt(2,2, cx*cy);
718  apRotMtx->SetMatriceElt(2,3, 0);
719  apRotMtx->SetMatriceElt(3,0, 0 );
720  apRotMtx->SetMatriceElt(3,1, 0 );
721  apRotMtx->SetMatriceElt(3,2, 0);
722  apRotMtx->SetMatriceElt(3,3, 1);
723  }
724  */
725 
726  delete r1;
727  delete r2;
728  delete r3;
729  delete rtmp;
730 
731  return 0;
732 }
void ShowHelp()
This function is used to print out specific help about the deformation and its options.
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.
~iDeformationRigid()
Destructor of iDeformationRigid. Free memory from all allocated tabs.
FLTNB GetVoxSizeX()
Get the voxel&#39;s size along the X axis, in mm.
#define Cerr(MESSAGE)
#define FORWARD_DEFORMATION
int ReadAndCheckConfigurationFile(const string &a_fileOptions)
FLTNB GetVoxSizeZ()
Get the voxel&#39;s size along the Z axis, in mm.
#define BACKWARD_DEFORMATION
void Exit(int code)
int ReadAndCheckOptionsList(const string &a_listOptions)
FLTNB GetVoxSizeY()
Get the voxel&#39;s size along the Y axis, in mm.
int Tlerp(HPFLTNB *ap_inputImage, HPFLTNB *ap_outputImage, uint32_t iov, uint32_t iiv, FLTNB dX, FLTNB dY, FLTNB dZ)
int CheckSpecificParameters()
This function is used to check parameters after the latter have been all set using Set functions...
int TransformImage(int a_direction, int a_defIdx, HPFLTNB *ap_inputImage, HPFLTNB *ap_outputImage)
int SetRotationMatrix(oMatrix *apRotMtx, FLTNB a_ang1, FLTNB a_ang2, FLTNB a_ang3, string a_cvt)
This function set the rotation matrix passed in parameter with the provided angles in radian and rota...
int ComputeTransformationMatrices()
Initialize transformation matrices from parameters.
This is the mother class of image-based transformation class.
HPFLTNB GetMatriceElt(uint16_t l, uint16_t c)
#define KEYWORD_MANDATORY
#define KEYWORD_OPTIONAL
oImageDimensionsAndQuantification * mp_ID
iDeformationRigid()
Constructor of iDeformationRigid. Simply set all data members to default values.
Structure designed for basic matrices operations.
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
int SetXRotMtx(HPFLTNB ang)
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
int Multiplication(oMatrix *ap_Mtx, oMatrix *ap_MtxResult)
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...
int SetMatriceElt(uint16_t l, uint16_t c, HPFLTNB a_val)
#define Cout(MESSAGE)
int SetZRotMtx(HPFLTNB ang)
int ApplyDeformations(FLTNB *ap_inputImage, FLTNB *ap_outputImage, int a_direction, int a_defIdx)
int Initialize()
This function is used to initialize specific stuff in the deformation model.
int SetYRotMtx(HPFLTNB ang)
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.
#define KEYWORD_OPTIONAL_ERROR