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