CASToR  2.0
Tomographic Reconstruction (PET/SPECT/CT)
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iProjectorIRIS.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-2018 all CASToR contributors listed below:
18 
19  --> current contributors: Thibaut MERLIN, Simon STUTE, Didier BENOIT, Claude COMTAT, Marina FILIPOVIC, Mael MILLARDET
20  --> past contributors: Valentin VIELZEUF
21 
22 This is CASToR version 2.0.
23 */
24 
31 #include "iProjectorIRIS.hh"
32 #include "sOutputManager.hh"
33 
34 // =====================================================================
35 // ---------------------------------------------------------------------
36 // ---------------------------------------------------------------------
37 // =====================================================================
38 
40 {
41  mp_pathToIDRFFiles = NULL;
42  mp_IDRF = NULL;
43  m2p_IDRF_CDFs = NULL;
44  m_nbLinesPerLOR = -1;
45  m_nVoxDepthIDRF = -1;
47  m_nVoxAxialIDRF = -1;
48  m_nVoxXYZIDRF = -1;
49  m_nBetaAnglesIDRF = -1;
50  m_nAlphaAnglesIDRF = -1;
51  m_sizeVoxDepthIDRF = -1.;
53  m_sizeVoxAxialIDRF = -1.;
56  // This projector is not compatible with SPECT attenuation correction because
57  // the voxels contributing to the line are not strictly ordered with respect to
58  // their distance to point 2 (due to the use of multiple lines that are
59  // stack one after the other)
61  // This projector is not compatible with compression as it works only with the
62  // detection element indices
64 }
65 
66 // =====================================================================
67 // ---------------------------------------------------------------------
68 // ---------------------------------------------------------------------
69 // =====================================================================
70 
72 {
74 
76  for (int a=0 ; a<m_nAlphaAnglesIDRF*m_nBetaAnglesIDRF ; a++)
77  if (m2p_IDRF_CDFs[a]) delete[] m2p_IDRF_CDFs[a];
78 
79  if (m2p_IDRF_CDFs) delete[] m2p_IDRF_CDFs;
80 
81  if (mp_IDRF) delete[] mp_IDRF;
82 }
83 
84 // =====================================================================
85 // ---------------------------------------------------------------------
86 // ---------------------------------------------------------------------
87 // =====================================================================
88 
89 int iProjectorIRIS::ReadConfigurationFile(const string& a_configurationFile)
90 {
91  if (ReadDataASCIIFile(a_configurationFile, "number lines per LOR", &m_nbLinesPerLOR, 1, 1) )
92  {
93  Cerr("***** iProjectorIRIS::ReadConfigurationFile() -> An error occurred while trying to read the number of lines per LOR from the IRIS configuration file at :" << a_configurationFile << " !" << endl);
94  return 1;
95  }
96 
97  if (ReadDataASCIIFile(a_configurationFile, "number voxels depth", &m_nVoxDepthIDRF, 1, 1) ||
98  ReadDataASCIIFile(a_configurationFile, "number voxels transaxial", &m_nVoxTransaxialIDRF, 1, 1) ||
99  ReadDataASCIIFile(a_configurationFile, "number voxels axial", &m_nVoxAxialIDRF, 1, 1) )
100  {
101  Cerr("***** iProjectorIRIS::ReadConfigurationFile() -> An error occurred while trying to read the IDRF volume dimensions (nb voxels) from the IRIS configuration file at :" << a_configurationFile << " !" << endl);
102  return 1;
103  }
104 
105  // Total number of voxels in the IDRF
107 
108  if (ReadDataASCIIFile(a_configurationFile, "size voxels depth", &m_sizeVoxDepthIDRF, 1, 1) ||
109  ReadDataASCIIFile(a_configurationFile, "size voxels transaxial", &m_sizeVoxTransaxialIDRF, 1, 1) ||
110  ReadDataASCIIFile(a_configurationFile, "size voxels axial", &m_sizeVoxAxialIDRF, 1, 1) )
111  {
112  Cerr("***** iProjectorIRIS::ReadConfigurationFile() -> An error occurred while trying to read the voxel sizes of the IDRF volumes from the IRIS configuration file at :" << a_configurationFile << " !" << endl);
113  return 1;
114  }
115 
116  if (ReadDataASCIIFile(a_configurationFile, "number beta angles", &m_nBetaAnglesIDRF, 1, 1) ||
117  ReadDataASCIIFile(a_configurationFile, "number alpha angles", &m_nAlphaAnglesIDRF, 1, 1) )
118  {
119  Cerr("***** iProjectorIRIS::ReadConfigurationFile() -> An error occurred while trying to read the number of alpha/beta angles from the IRIS configuration file at :" << a_configurationFile << " !" << endl);
120  return 1;
121  }
122 
123  if (ReadDataASCIIFile(a_configurationFile, "step beta angles", &m_stepBetaAnglesIDRF, 1, 1) ||
124  ReadDataASCIIFile(a_configurationFile, "step alpha angles", &m_stepAlphaAnglesIDRF, 1, 1) )
125  {
126  Cerr("***** iProjectorIRIS::ReadConfigurationFile() -> An error occurred while trying to read the alpha/beta angles steps from the IRIS configuration file at :" << a_configurationFile << " !" << endl);
127  return 1;
128  }
129 
130  // Convert angle steps in radians
131  m_stepAlphaAnglesIDRF *= M_PI/180.;
132  m_stepBetaAnglesIDRF *= M_PI/180.;
133 
135 
136  mp_IDRF = new float[m_nVoxXYZIDRF];
138 
139  for(int a=0 ; a<m_nAlphaAnglesIDRF*m_nBetaAnglesIDRF ; a++)
140  m2p_IDRF_CDFs[a] = new float[m_nVoxXYZIDRF];
141 
142  if (ReadDataASCIIFile(a_configurationFile, "IDRFs path", mp_pathToIDRFFiles, 1, m_nAlphaAnglesIDRF*m_nBetaAnglesIDRF, 1) )
143  {
144  Cerr("***** iProjectorIRIS::ReadConfigurationFile() -> An error occurred while trying to read the path to the IDRF files, from the IRIS configuration file at :" << a_configurationFile << " !" << endl);
145  Cerr("***** ("<< m_nAlphaAnglesIDRF*m_nBetaAnglesIDRF << " lines expected)" << endl);
146  return 1;
147  }
148 
149  // Normal end
150  return 0;
151 }
152 
153 // =====================================================================
154 // ---------------------------------------------------------------------
155 // ---------------------------------------------------------------------
156 // =====================================================================
157 
158 int iProjectorIRIS::ReadOptionsList(const string& a_optionsList)
159 {
160  // Configuration is possible only through a configuration file (no command-line options)
161  Cerr("***** iProjectorIRIS::ReadOptionsList() -> This projector should be initialized with a configuration file, and not parameters (-proj IRIS:path_to_configuration_file) !" << endl);
162  return 1;
163 }
164 
165 // =====================================================================
166 // ---------------------------------------------------------------------
167 // ---------------------------------------------------------------------
168 // =====================================================================
169 
171 {
172  cout << "Multiray projector requiring Intrinsic Detector Response Functions (IDRFs) models" << endl;
173  cout << "The projector will generate an user-defined number of lines using from pairs of random points generated using the IDRFs models" << endl;
174  cout << "The lines will be rendered using the Incremental Siddon projector (incrementalSiddon)" << endl;
175  cout << "This projector requires an initialization file and Monte-Carlo generated IDRFs. For more informations, please read [article]" << endl;
176  cout << "INITIALIZATION FILE FIELDS :" << endl;
177  cout << "number lines per LOR : number of lines generated to estimate the CDRF (int32)" << endl;
178  cout << "number voxels depth : number of voxels in the depth direction in the IDRF volumes (int32)" << endl;
179  cout << "number voxels transaxial : number of voxels in the transaxial direction in the IDRF volumes (int32)" << endl;
180  cout << "number voxels axial : number of voxels in the axial direction in the IDRF volumes (int32)" << endl;
181  cout << "size voxels depth : size of voxels in the depth direction of the IDRF volumes (float32)" << endl;
182  cout << "size voxels transaxial : size of voxels in the transaxial direction of the IDRF volume (float32)" << endl;
183  cout << "size voxels axial : size of voxels in the axial direction of the IDRF volume (float32)" << endl;
184  cout << "number beta angles : number of axial angles in the IDRF volumes (int32)" << endl;
185  cout << "number alpha angles : number of transaxial angles in the IDRF volumes (int32)" << endl;
186  cout << "step beta angles : axial angular steps in the IDRF volumes (float32)" << endl;
187  cout << "step alpha angles : transaxial angular steps in the IDRF volumes (float32)" << endl;
188  cout << "IDRFs path : path to the IDRF .vol files (string)" << endl;
189  cout << " : each path should be entered on a separated line" << endl;
190  cout << " " << endl;
191  cout << "Each .vol files should contain a header of 6 float32 fields :" << endl;
192  cout << "number voxels axial ; number voxels transaxial ; number voxels depth ; size voxels axial ; size voxels transaxial ; size voxels depth" << endl;
193  cout << "... followed by number voxels depth*number voxels transaxial*number voxels axial float32 elements corresponding to the IDRF coefficients" << endl;
194 }
195 
196 // =====================================================================
197 // ---------------------------------------------------------------------
198 // ---------------------------------------------------------------------
199 // =====================================================================
200 
202 {
203  if(mp_pathToIDRFFiles==NULL)
204  {
205  Cerr("***** iProjectorIRIS::CheckSpecificParameters() -> path to IDRF files not initialized !" << endl);
206  return 1;
207  }
208  if(mp_IDRF==NULL || m2p_IDRF_CDFs==NULL)
209  {
210  Cerr("***** iProjectorIRIS::CheckSpecificParameters() -> IDRF coefficients not initialized !" << endl);
211  return 1;
212  }
213  if(m_nbLinesPerLOR<0)
214  {
215  Cerr("***** iProjectorIRIS::CheckSpecificParameters() -> number of lines per LOR not initialized !" << endl);
216  return 1;
217  }
219  {
220  Cerr("***** iProjectorIRIS::CheckSpecificParameters() -> number of voxels for the IDRF volumes not initialized !" << endl);
221  return 1;
222  }
224  {
225  Cerr("***** iProjectorIRIS::CheckSpecificParameters() -> voxel sizes of the IDRF volumes not initialized !" << endl);
226  return 1;
227  }
229  {
230  Cerr("***** iProjectorIRIS::CheckSpecificParameters() -> number of angles for the IDRF volumes not initialized !" << endl);
231  return 1;
232  }
234  {
235  Cerr("***** iProjectorIRIS::CheckSpecificParameters() -> step of the IDRF angles not initialized !" << endl);
236  return 1;
237  }
238  // Normal end
239  return 0;
240 }
241 
242 // =====================================================================
243 // ---------------------------------------------------------------------
244 // ---------------------------------------------------------------------
245 // =====================================================================
246 
248 {
249  // Verbose
250  if (m_verbose>=2) Cout("iProjectorIRIS::InitializeSpecific() -> Use IRIS projector" << endl);
251 
252  // Read IDRFs coefficients from the raw data files, and write them on a single vector
253  for(int a=0 ; a<m_nAlphaAnglesIDRF ; a++) // loop on alpha angles
254  for(int b=0 ; b<m_nBetaAnglesIDRF ; b++) // loop on beta angles
255  {
256  // Open & check file existence
257  ifstream IDRF_file(mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b].c_str(), ios::binary| ios::in);
258  if (!IDRF_file.is_open())
259  {
260  Cerr("***** iProjectorIRIS::InitializeSpecific() -> Error reading the IRDF .vol file at the path: '" << mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b] << "'" << endl);
261  return 1;
262  }
263  // Check file size consistency
264  IDRF_file.seekg(0, ios::end);
265  size_t size_in_bytes = IDRF_file.tellg();
266 
267  if(((size_t)((6+m_nVoxXYZIDRF)*sizeof(float))) != size_in_bytes)
268  {
269  Cerr("***** iProjectorIRIS::InitializeSpecific() -> Error : Size of the .vol " << mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b] << " is not consistent with the information provided by the user configuration file!" << endl);
270  Cerr("***** iProjectorIRIS::InitializeSpecific() -> Expected size : "<< (6+m_nVoxXYZIDRF)*sizeof(float) << endl);
271  Cerr("***** iProjectorIRIS::InitializeSpecific() -> Actual size : "<< size_in_bytes << endl << endl);
272  return 1;
273  }
274  // Check header of the volume
275  float vol_file_header[6];
276  // Go back to first character
277  IDRF_file.seekg(0);
278  for(int i=0 ; i<6 ; i++)
279  IDRF_file.read((char*)&vol_file_header[i], sizeof(float));
280  // TODO : Take out header from .vol files. Just use the other checks and delete this condition
281  if ((int)vol_file_header[0]!=m_nVoxAxialIDRF ||
282  (int)vol_file_header[1]!=m_nVoxTransaxialIDRF ||
283  (int)vol_file_header[2]!=m_nVoxDepthIDRF ||
284  fabs(vol_file_header[3]-m_sizeVoxAxialIDRF) > 0.0001 ||
285  fabs(vol_file_header[4]-m_sizeVoxTransaxialIDRF) > 0.0001 ||
286  fabs(vol_file_header[5]-m_sizeVoxDepthIDRF) > 0.0001 )
287  {
288  Cerr("***** iProjectorIRIS::InitializeSpecific() -> Inconsistency between initialized and read header file in the .vol: '" << mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b] << "'" << endl);
289  return 1;
290  }
291  // Read raw data
292  for(int i=0 ; i<m_nVoxXYZIDRF ; i++)
293  {
294  IDRF_file.read((char*)&vol_file_header[0], sizeof(float));
295  mp_IDRF[i] = vol_file_header[0];
296  }
297  if(ComputeIDRF_CDF(a*m_nBetaAnglesIDRF + b) )
298  {
299  Cerr("***** iProjectorIRIS::InitializeSpecific() -> An error occurs while computing the coefficient of the following IDRF volume: alpha " << a*m_stepAlphaAnglesIDRF << " beta " << b*m_stepBetaAnglesIDRF << endl);
300  return 1;
301  }
302  IDRF_file.close();
303  }
304 
305  // Normal end
306  return 0;
307 }
308 
309 // =====================================================================
310 // ---------------------------------------------------------------------
311 // ---------------------------------------------------------------------
312 // =====================================================================
313 
315 {
316  // Find the maximum number of voxels along a given dimension
317  INTNB max_nb_voxels_in_dimension = mp_ImageDimensionsAndQuantification->GetNbVoxX();
318  if (mp_ImageDimensionsAndQuantification->GetNbVoxY()>max_nb_voxels_in_dimension) max_nb_voxels_in_dimension = mp_ImageDimensionsAndQuantification->GetNbVoxY();
319  if (mp_ImageDimensionsAndQuantification->GetNbVoxZ()>max_nb_voxels_in_dimension) max_nb_voxels_in_dimension = mp_ImageDimensionsAndQuantification->GetNbVoxZ();
320  // We should have at most 4 voxels in a given plane, so multiply by 4
321  // (note: this is not true however it ensures no overflow and is already quite optimized for RAM usage !)
322  max_nb_voxels_in_dimension *= 4;
323  // Finally multiply by the number of lines
324  max_nb_voxels_in_dimension *= ((INTNB)m_nbLinesPerLOR);
325  // Return the value
326  return max_nb_voxels_in_dimension;
327 }
328 
329 // =====================================================================
330 // ---------------------------------------------------------------------
331 // ---------------------------------------------------------------------
332 // =====================================================================
333 
334 int iProjectorIRIS::ProjectWithoutTOF(int a_direction, oProjectionLine* ap_ProjectionLine )
335 {
336  #ifdef CASTOR_DEBUG
337  if (!m_initialized)
338  {
339  Cerr("***** iProjectorIRIS::ProjectWithoutTOF() -> Called while not initialized !" << endl);
340  Exit(EXIT_DEBUG);
341  }
342  #endif
343 
344  #ifdef CASTOR_VERBOSE
345  if (m_verbose>=10)
346  {
347  string direction = "";
348  if (a_direction==FORWARD) direction = "forward";
349  else direction = "backward";
350  Cout("iProjectorIRIS::Project without TOF -> Project line '" << ap_ProjectionLine << "' in " << direction << " direction" << endl);
351  }
352  #endif
353 
354  // Get central positions of the crystals
355  FLTNB* event1 = ap_ProjectionLine->GetPosition1();
356  FLTNB* event2 = ap_ProjectionLine->GetPosition2();
357 
358  // Local variables to recover crystal central positions and orientations
359  float x1, y1, z1, crystal_alpha1, x2, y2, z2, crystal_alpha2;
360 
361  x1 = event1[0];
362  y1 = event1[1];
363  z1 = event1[2];
364  x2 = event2[0];
365  y2 = event2[1];
366  z2 = event2[2];
367 
368  // Get transaxial orientations of the two crystals // CHECK HERE
369  FLTNB* orientation1 = ap_ProjectionLine->GetOrientation1();
370  FLTNB* orientation2 = ap_ProjectionLine->GetOrientation2();
371 
372  // Compute transaxial angular orientation of the crystals
373  crystal_alpha1 = atan2f(orientation1[0], orientation1[1]); //LUT_alpha[id1]; //HERE
374  crystal_alpha2 = atan2f(orientation2[0], orientation2[1]); //LUT_alpha[id2]; //HERE
375 
376  // -------
377  // Compute transaxial incident angles (alpha) between the LOR and the crystals
378  // -------
379 
380  float alpha1, alpha2, alpha_lor;
381 
382  // Compute transaxial incident angle of the LOR
383  alpha_lor = atan2f(x1-x2, y1-y2); // alpha_lor = atan2f( y1-y2 , x1-x2 ); //CHECK HERE
384 
385  // Compute incident angle on each crystal surfaces
386  alpha1 = remainderf(alpha_lor-M_PI-crystal_alpha1, M_PI);
387  if(alpha1>(M_PI/2.)) // Check if this operation and other surrounding should require HPFLTNB instead of float
388  alpha1 -= M_PI;
389 
390  alpha2 = remainderf(alpha_lor-M_PI-crystal_alpha2, M_PI);
391  if(alpha2>(M_PI/2.))
392  alpha2 -= M_PI;
393 
394  //alpha1 = remainderf(alpha_lor-Pi-crystal_alpha1, M_PI_2);
395  //alpha2 = remainderf(alpha_lor-crystal_alpha2, M_PI_2);
396 
397 
398 
399  // -------
400  // Compute axial incident angles (beta) between the LOR and the crystals
401  // -------
402 
403  float beta1, beta2, H;
404 
405  // Compute transaxial distance
406  H = sqrtf((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
407 
408  // Compute axial incident angle
409  beta1 = atan2f( (z1-z2), H );
410 
411  // Normalize with Pi
412  beta1 = remainderf(beta1, M_PI);
413  if(beta1>(M_PI/2.))
414  beta1 -= M_PI;
415 
416  beta2 = -beta1;
417  beta2 = remainderf(beta2, M_PI);
418  if(beta2>(M_PI/2.))
419  beta2 -= M_PI;
420 
421 
422  /*
423  float r_to_deg = 180./M_PI;
424 
425  //cout << "pos1 X: " << event1[0] << " Y: " << event1[1] << " Z: " << event1[2] << " vs Cry: " << alpha1*r_to_deg << " ang " << crystal_alpha1*r_to_deg << " bet " << beta1*r_to_deg << endl;
426  //cout << "pos2 X: " << event2[0] << " Y: " << event2[1] << " Z: " << event2[2] << " vs Cry: " << alpha2*r_to_deg << " ang " << crystal_alpha2*r_to_deg << " bet " << beta2*r_to_deg << endl;
427  cout << "pos1 X: " << event1[0] << " Y: " << event1[1] << " Z: " << event1[2] << " vs Cry: " << alpha1*r_to_deg << " ang " << crystal_alpha1*r_to_deg << endl;
428  cout << "pos2 X: " << event2[0] << " Y: " << event2[1] << " Z: " << event2[2] << " vs Cry: " << alpha2*r_to_deg << " ang " << crystal_alpha2*r_to_deg << endl;
429  cout << ap_ProjectionLine->GetIndex1() << " : " << ap_ProjectionLine->GetIndex2() << " : " << alpha_lor*r_to_deg << endl;
430 
431  if(ap_ProjectionLine->GetIndex2()== 17556)
432  {
433  int r;
434  scanf("%d" , &r);
435  }
436 
437  if(ap_ProjectionLine->GetIndex1() == 0
438  && ap_ProjectionLine->GetIndex2() == 50)
439  {
440  cout << endl;
441  cout << "pos1 X: " << event1[0] << " Y: " << event1[1] << " Z: " << event1[2] << " aTrs: " << alpha1*r_to_deg << " aAxl: " << beta1*r_to_deg << endl;
442  cout << "pos2 X: " << event2[0] << " Y: " << event2[1] << " Z: " << event2[2] << " aTrs: " << alpha2*r_to_deg << " aAxl: " << beta2*r_to_deg << endl;
443  }
444 
445 
446  if(ap_ProjectionLine->GetIndex1() == 0
447  && ap_ProjectionLine->GetIndex2() == 308)
448  {
449  cout << endl;
450  cout << "pos1 X: " << event1[0] << " Y: " << event1[1] << " Z: " << event1[2] << " aTrs: " << alpha1*r_to_deg << " aAxl: " << beta1*r_to_deg << endl;
451  cout << "pos2 X: " << event2[0] << " Y: " << event2[1] << " Z: " << event2[2] << " aTrs: " << alpha2*r_to_deg << " aAxl: " << beta2*r_to_deg << endl;
452  }
453 
454  if(ap_ProjectionLine->GetIndex1() == 0
455  && ap_ProjectionLine->GetIndex2() == 17298)
456  {
457  cout << endl;
458  cout << "pos1 X: " << event1[0] << " Y: " << event1[1] << " Z: " << event1[2] << " aTrs: " << alpha1*r_to_deg << " aAxl: " << beta1*r_to_deg << endl;
459  cout << "pos2 X: " << event2[0] << " Y: " << event2[1] << " Z: " << event2[2] << " aTrs: " << alpha2*r_to_deg << " aAxl: " << beta2*r_to_deg << endl;
460  }
461 
462  if(ap_ProjectionLine->GetIndex1() == 0
463  && ap_ProjectionLine->GetIndex2() == 17556)
464  {
465  cout << endl;
466  cout << "pos1 X: " << event1[0] << " Y: " << event1[1] << " Z: " << event1[2] << " aTrs: " << alpha1*r_to_deg << " aAxl: " << beta1*r_to_deg << endl;
467  cout << "pos2 X: " << event2[0] << " Y: " << event2[1] << " Z: " << event2[2] << " aTrs: " << alpha2*r_to_deg << " aAxl: " << beta2*r_to_deg << endl;
468  }
469  */
470 
471 
473  for (int i_line=0; i_line<m_nbLinesPerLOR; ++i_line)
474  {
475  // Generate two random points using the IDRFs.
476  float X1, Y1, Z1;
477  float X2, Y2, Z2;
478  float pos1[3], pos2[3];
479  if (GenerateIRISRdmPos(pos1, alpha1, beta1) )
480  {
481  Cerr("***** iProjectorIRIS::ProjectWithoutTOF() -> An error occurred while trying to generate random position with the IRIS projector" << endl);
482  return 1;
483  }
484 
485  X1 = pos1[0];
486  Y1 = pos1[1];
487  Z1 = pos1[2];
488 
489  if (GenerateIRISRdmPos(pos2, alpha2, beta2) )
490  {
491  Cerr("***** iProjectorIRIS::ProjectWithoutTOF() -> An error occurred while trying to generate random position with the IRIS projector" << endl);
492  return 1;
493  }
494 
495  X2 = pos2[0];
496  Y2 = pos2[1];
497  Z2 = pos2[2];
498 
499  // Move the random points in the frame of reference of the scanner.
500  // IRIS ref:
501  // X = depth
502  // Y = transaxial
503  // Z = axial
504 
505  float tmp_X, tmp_Y;
506  tmp_X = X1; tmp_Y = Y1;
507  X1 = x1 + tmp_X*orientation1[0]-tmp_Y*orientation1[1]; //HERE
508  Y1 = y1 + tmp_X*orientation1[1]+tmp_Y*orientation1[0]; //HERE
509  Z1 += z1;
510  /*
511  cout << "pos1 X: " << event1[0] << " Y: " << event1[1] << " Z: " << event1[2] << endl ;
512  cout << orientation1[0] << " ; " << orientation1[1] << endl;
513  cout << "tmp_X1: " << tmp_X << " tmp_Y1 " << tmp_Y << " --- X1: " << X1 << " Y1 " << Y1 << endl;
514  */
515 
516  tmp_X = X2; tmp_Y = Y2;
517  X2 = x2 + tmp_X*orientation2[0]-tmp_Y*orientation2[1]; //HERE
518  Y2 = y2 + tmp_X*orientation2[1]+tmp_Y*orientation2[0]; //HERE
519  Z2 += z2;
520 
521 /*
522  cout << "pos2 X: " << event2[0] << " Y: " << event2[1] << " Z: " << event2[2] << endl;
523  cout << orientation2[0] << " ; " << orientation2[1] << endl;
524  cout << "tmp_X2: " << tmp_X << " tmp_Y2 " << tmp_Y << " --- X2: " << X2 << " Y2 " << Y2 << endl;
525  int r;
526  scanf("%d", &r);*/
527 
528  // SIDDON ALGORITHM
529 
530  // **************************************
531  // STEP 1: LOR length calculation
532  // **************************************
533  HPFLTNB length_LOR = ap_ProjectionLine->GetLength();
534 
535  // **************************************
536  // STEP 2: Compute entrance voxel indexes
537  // **************************************
538  HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
539  HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
540 
541  HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
542  HPFLTNB delta_pos[] = {
543  X2 - X1, // event2[ 0 ] - event1[ 0 ]
544  Y2 - Y1, // event2[ 1 ] - event1[ 1 ]
545  Z2 - Z1 // event2[ 2 ] - event1[ 2 ]
546  };
547 
548  // Computation of alphaMin et alphaMax values (entrance and exit point of the ray)
549  for( int i = 0; i < 3; ++i )
550  {
551  if( delta_pos[ i ] != 0.0 )
552  {
553  alphaFirst[i] = (-mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
554  alphaLast[i] = ( mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
555  alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
556  alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
557  }
558  }
559 
560  // if alphaMax is less than or equal to alphaMin no intersection
561  // and return an empty buffer
562  if( alphaMax <= alphaMin ) return 0;
563 
564  // Now we have to find the indices of the particular plane
565  // (iMin,iMax), (jMin,jMax), (kMin,kMax)
566  int iMin = 0, iMax = 0;
567  int jMin = 0, jMax = 0;
568  int kMin = 0, kMax = 0;
569 
570  // For the X-axis
571  if( delta_pos[ 0 ] > 0.0f )
572  {
573  iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - ( mp_halfFOV[ 0 ] - alphaMin * delta_pos[ 0 ] - event1[ 0 ] ) / mp_sizeVox[0] );
574  iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-mp_halfFOV[ 0 ]) ) / mp_sizeVox[0] );
575  }
576  else if( delta_pos[ 0 ] < 0.0f )
577  {
578  iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - ( mp_halfFOV[ 0 ] - alphaMax * delta_pos[ 0 ] - event1[ 0 ] ) / mp_sizeVox[0] );
579  iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-mp_halfFOV[ 0 ]) ) / mp_sizeVox[0] );
580  }
581  if( delta_pos[ 0 ] == 0 )
582  {
583  iMin = 1, iMax = 0;
584  }
585 
586  // For the Y-axis
587  if( delta_pos[ 1 ] > 0 )
588  {
589  jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - ( mp_halfFOV[ 1 ] - alphaMin * delta_pos[ 1 ] - event1[ 1 ] ) / mp_sizeVox[1] );
590  jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-mp_halfFOV[ 1 ]) ) / mp_sizeVox[1] );
591  }
592  else if( delta_pos[ 1 ] < 0 )
593  {
594  jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - ( mp_halfFOV[ 1 ] - alphaMax * delta_pos[ 1 ] - event1[ 1 ] ) / mp_sizeVox[1] );
595  jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-mp_halfFOV[ 1 ]) ) / mp_sizeVox[1] );
596  }
597  else if( delta_pos[ 1 ] == 0 )
598  {
599  jMin = 1, jMax = 0;
600  }
601 
602  // For the Z-axis
603  if( delta_pos[ 2 ] > 0 )
604  {
605  kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - ( mp_halfFOV[ 2 ] - alphaMin * delta_pos[ 2 ] - event1[ 2 ] ) / mp_sizeVox[2] );
606  kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-mp_halfFOV[ 2 ]) ) / mp_sizeVox[2] );
607  }
608  else if( delta_pos[ 2 ] < 0 )
609  {
610  kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - ( mp_halfFOV[ 2 ] - alphaMax * delta_pos[ 2 ] - event1[ 2 ] ) / mp_sizeVox[2] );
611  kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-mp_halfFOV[ 2 ]) ) / mp_sizeVox[2] );
612  }
613  else if( delta_pos[ 2 ] == 0 )
614  {
615  kMin = 1, kMax = 0;
616  }
617 
618  // Computing the last term n number of intersection
619  INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
620  + ( kMax - kMin + 1 );
621 
622  // Array storing the first alpha in X, Y and Z
623  HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
624 
625  // Computing the first alpha in X
626  if( delta_pos[ 0 ] > 0 )
627  alpha_XYZ[ 0 ] = ( ( (-mp_halfFOV[ 0 ]) + ( iMin - 1 ) * mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
628  else if( delta_pos[ 0 ] < 0 )
629  alpha_XYZ[ 0 ] = ( ( (-mp_halfFOV[ 0 ]) + ( iMax - 1 ) * mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
630 
631  // Computing the first alpha in Y
632  if( delta_pos[ 1 ] > 0 )
633  alpha_XYZ[ 1 ] = ( ( (-mp_halfFOV[ 1 ]) + ( jMin - 1 ) * mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
634  else if( delta_pos[ 1 ] < 0 )
635  alpha_XYZ[ 1 ] = ( ( (-mp_halfFOV[ 1 ]) + ( jMax - 1 ) * mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
636 
637  // Computing the first alpha in Z
638  if( delta_pos[ 2 ] > 0 )
639  alpha_XYZ[ 2 ] = ( ( (-mp_halfFOV[ 2 ]) + ( kMin - 1 ) * mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
640  else if( delta_pos[ 2 ] < 0 )
641  alpha_XYZ[ 2 ] = ( ( (-mp_halfFOV[ 2 ]) + ( kMax - 1 ) * mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
642 
643  // Computing the alpha updating
644  HPFLTNB alpha_u[ 3 ] = {
645  mp_sizeVox[0] / std::fabs( delta_pos[ 0 ] ),
646  mp_sizeVox[1] / std::fabs( delta_pos[ 1 ] ),
647  mp_sizeVox[2] / std::fabs( delta_pos[ 2 ] )
648  };
649 
650  // Computing the index updating
651  INTNB index_u[ 3 ] = {
652  (delta_pos[ 0 ] < 0) ? -1 : 1,
653  (delta_pos[ 1 ] < 0) ? -1 : 1,
654  (delta_pos[ 2 ] < 0) ? -1 : 1
655  };
656 
657  // Check which alpha is the min/max and increment
658  if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
659  if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
660  if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
661 
662  // Computing the minimum value in the alpha_XYZ buffer
663  HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ],
664  (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
665 
666  // Computing the first index of intersection
667  HPFLTNB const alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
668  INTNB index_ijk[ 3 ] = {
669  1 + (int)( ( event1[ 0 ] + alphaMid * delta_pos[ 0 ] - (-mp_halfFOV[ 0 ]) ) / mp_sizeVox[0] ),
670  1 + (int)( ( event1[ 1 ] + alphaMid * delta_pos[ 1 ] - (-mp_halfFOV[ 1 ]) ) / mp_sizeVox[1] ),
671  1 + (int)( ( event1[ 2 ] + alphaMid * delta_pos[ 2 ] - (-mp_halfFOV[ 2 ]) ) / mp_sizeVox[2] )
672  };
673 
674  INTNB const w = mp_nbVox[ 0 ];
675  INTNB const wh = w * mp_nbVox[ 1 ];
676 
677  // Loop over the number of plane to cross
678  HPFLTNB alpha_c = alphaMin;
679  FLTNB coeff = 0.0f;
680  INTNB numVox = 0;
681  for( int nP = 0; nP < n - 1; ++nP )
682  {
683  if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
684  && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
685  {
686  // Storing values
687  if( ( alpha_XYZ[ 0 ] >= alphaMin )
688  && ( index_ijk[ 0 ] - 1 >= 0 )
689  && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
690  && ( index_ijk[ 1 ] - 1 >= 0 )
691  && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
692  && ( index_ijk[ 2 ] - 1 >= 0 )
693  && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
694  {
695  coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
696  numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
697  ap_ProjectionLine->AddVoxel(a_direction, numVox, coeff/m_nbLinesPerLOR); // TODO Normalizations according to the number of lines are performed in these lines. Perhaps we should do this at a upper level (vProjector)
698  }
699 
700  // Increment values
701  alpha_c = alpha_XYZ[ 0 ];
702  alpha_XYZ[ 0 ] += alpha_u[ 0 ];
703  index_ijk[ 0 ] += index_u[ 0 ];
704  }
705  else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
706  && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
707  {
708  // Storing values
709  if( ( alpha_XYZ[ 1 ] >= alphaMin )
710  && ( index_ijk[ 0 ] - 1 >= 0 )
711  && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
712  && ( index_ijk[ 1 ] - 1 >= 0 )
713  && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
714  && ( index_ijk[ 2 ] - 1 >= 0 )
715  && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
716  {
717  coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
718  numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
719  ap_ProjectionLine->AddVoxel(a_direction, numVox, coeff/m_nbLinesPerLOR);
720  }
721 
722  // Increment values
723  alpha_c = alpha_XYZ[ 1 ];
724  alpha_XYZ[ 1 ] += alpha_u[ 1 ];
725  index_ijk[ 1 ] += index_u[ 1 ];
726  }
727  else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
728  && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
729  {
730  // Storing values
731  if( ( alpha_XYZ[ 2 ] >= alphaMin )
732  && ( index_ijk[ 0 ] - 1 >= 0 )
733  && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
734  && ( index_ijk[ 1 ] - 1 >= 0 )
735  && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
736  && ( index_ijk[ 2 ] - 1 >= 0 )
737  && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
738  {
739  coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
740  numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
741  ap_ProjectionLine->AddVoxel(a_direction, numVox, coeff/m_nbLinesPerLOR);
742  }
743 
744  // Increment values
745  alpha_c = alpha_XYZ[ 2 ];
746  alpha_XYZ[ 2 ] += alpha_u[ 2 ];
747  index_ijk[ 2 ] += index_u[ 2 ];
748  }
749  }
750 
751  }
752 
753  return 0;
754 }
755 
756 // =====================================================================
757 // ---------------------------------------------------------------------
758 // ---------------------------------------------------------------------
759 // =====================================================================
760 
761 int iProjectorIRIS::ProjectWithTOFPos(int a_Projector, oProjectionLine* ap_ProjectionLine)
762 {
763  Cerr("***** iProjectorIRIS::ProjectWithTOFPos() -> Not yet implemented !" << endl);
764  return 1;
765 }
766 
767 // =====================================================================
768 // ---------------------------------------------------------------------
769 // ---------------------------------------------------------------------
770 // =====================================================================
771 
772 int iProjectorIRIS::ProjectWithTOFBin(int a_Projector, oProjectionLine* ap_ProjectionLine)
773 {
774  Cerr("***** iProjectorIRIS::ProjectWithTOFBin() -> Not yet implemented !" << endl);
775  return 1;
776 }
777 
778 // =====================================================================
779 // ---------------------------------------------------------------------
780 // ---------------------------------------------------------------------
781 // =====================================================================
782 
784 {
785  // Compute cumulated sum
786  m2p_IDRF_CDFs[a_angleId][0] = mp_IDRF[0];
787 
788  for(int i = 1; i<m_nVoxXYZIDRF; ++i)
789  m2p_IDRF_CDFs[a_angleId][i] = m2p_IDRF_CDFs[a_angleId][i-1] + mp_IDRF[i];
790 
791  // Normalization
792  if(m2p_IDRF_CDFs[a_angleId][m_nVoxXYZIDRF-1] > 0) // check if not null
793  for(int i = 0; i<m_nVoxXYZIDRF; ++i)
794  m2p_IDRF_CDFs[a_angleId][i] /= m2p_IDRF_CDFs[a_angleId][m_nVoxXYZIDRF-1];
795 
796  return 0;
797 }
798 
799 // =====================================================================
800 // ---------------------------------------------------------------------
801 // ---------------------------------------------------------------------
802 // =====================================================================
803 
804 int iProjectorIRIS::GenerateIRISRdmPos(float ap_generatedPos[3], float a_alpha, float a_beta)
805 {
807 
808  float rdm_pos[3];
809 
810  int alpha_id = (int) (fabsf(a_alpha)/m_stepAlphaAnglesIDRF);
811  int beta_id = (int) (fabsf(a_beta) /m_stepBetaAnglesIDRF);
812 
813  alpha_id = min(alpha_id, m_nAlphaAnglesIDRF-1);
814  beta_id = min(beta_id , m_nBetaAnglesIDRF -1);
815 
816  int id = FindGreaterValue(m2p_IDRF_CDFs[alpha_id*m_nBetaAnglesIDRF+beta_id], p_RNG->GenerateRdmNber(), m_nVoxXYZIDRF);
817 
818  // IDRFs indices sorting are axial/transaxial/DOI, DOI_id being the smallest index.
819  int axial_id = id / (m_nVoxDepthIDRF*m_nVoxTransaxialIDRF);
820  int trans_id = (id-axial_id*m_nVoxTransaxialIDRF*m_nVoxDepthIDRF) / m_nVoxDepthIDRF;
821  int DOI_id = id-axial_id*m_nVoxTransaxialIDRF*m_nVoxDepthIDRF - trans_id*m_nVoxDepthIDRF;
822 
823  // Use random number on each axis to generate a random position on the IDRF voxel
824  rdm_pos[0] = (DOI_id + p_RNG->GenerateRdmNber() - m_nVoxDepthIDRF/2.0f )*m_sizeVoxDepthIDRF; // CHECK : should choose surface central position by default when using IRIS, or adress the difference here
825  rdm_pos[1] = (trans_id + p_RNG->GenerateRdmNber() - m_nVoxTransaxialIDRF/2.0f )*m_sizeVoxTransaxialIDRF;
826  rdm_pos[2] = (axial_id + p_RNG->GenerateRdmNber() - m_nVoxAxialIDRF/2.0f )*m_sizeVoxAxialIDRF;
827 
828  if(a_alpha<0) rdm_pos[1] = -rdm_pos[1];
829  if(a_beta<0) rdm_pos[2] = -rdm_pos[2];
830 
831  ap_generatedPos[0] = rdm_pos[0];
832  ap_generatedPos[1] = rdm_pos[1];
833  ap_generatedPos[2] = rdm_pos[2];
834 
835  return 0;
836 }
837 
838 // =====================================================================
839 // ---------------------------------------------------------------------
840 // ---------------------------------------------------------------------
841 // =====================================================================
842 
843 int iProjectorIRIS::FindGreaterValue(float *ap_val, float a_key, int a_maxValue, int a_minStart, int a_maxStart)
844 {
845  int min = a_minStart, max, mid;
846 
847  max = a_maxStart ? a_maxStart : a_maxValue;
848 
849  int cpt=0;
850 
851  while (min < max)
852  {
853  mid = (min + max) >> 1; //(min+max)/2
854  if (a_key > ap_val[mid])
855  {
856  min = mid + 1;
857  }
858  else
859  {
860  max = mid;
861  }
862 
863  cpt++;
864  }
865 
866  return min;
867 }
bool m_compatibleWithSPECTAttenuationCorrection
Definition: vProjector.hh:355
static sRandomNumberGenerator * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
FLTNB * GetOrientation1()
This function is used to get the pointer to the mp_orientation1 (3-values tab).
FLTNB mp_sizeVox[3]
Definition: vProjector.hh:338
INTNB mp_nbVox[3]
Definition: vProjector.hh:339
#define FLTNB
Definition: gVariables.hh:81
string * mp_pathToIDRFFiles
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
Definition: vProjector.hh:344
#define HPFLTNB
Definition: gVariables.hh:83
This class is designed to generically described any on-the-fly projector.
Definition: vProjector.hh:76
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project without TOF.
FLTNB GetLength()
This function is used to get the length of the line.
FLTNB * GetOrientation2()
This function is used to get the pointer to the mp_orientation2 (3-values tab).
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
void ShowHelpSpecific()
A function used to show help about the child module.
void Exit(int code)
iProjectorIRIS()
The constructor of iProjectorIRIS.
#define Cerr(MESSAGE)
FLTNB * GetPosition1()
This function is used to get the pointer to the mp_position1 (3-values tab).
bool m_initialized
Definition: vProjector.hh:364
int FindGreaterValue(float *ap_val, float a_key, int a_maxValue, int a_minStart=0, int a_maxStart=0)
Find in the array ap_val (arranged in ascending order) the index of the first element greater than va...
FLTNB m_stepAlphaAnglesIDRF
void AddVoxel(int a_direction, INTNB a_voxelIndice, FLTNB a_voxelWeight)
This function is used to add a voxel contribution to the line, assuming TOF bin 0 (i...
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:123
int ProjectWithTOFBin(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF binned information.
Declaration of class iProjectorIRIS.
HPFLTNB GenerateRdmNber()
Generate a random number for the thread which index is recovered from the OpenMP function.
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
Singleton class that generate a thread-safe random generator number for openMP As singleton...
#define INTNB
Definition: gVariables.hh:92
This class is designed to manage and store system matrix elements associated to a vEvent...
~iProjectorIRIS()
The destructor of iProjectorIRIS.
Declaration of class sOutputManager.
int ComputeIDRF_CDF(int a_angleId)
Compute the IDRFs coefficients (arrange the IDRFs coefficients in ascending orders, and normalize).
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
FLTNB m_sizeVoxTransaxialIDRF
FLTNB m_stepBetaAnglesIDRF
int GenerateIRISRdmPos(float ap_generatedPos[3], float a_alpha, float a_beta)
Generate a random point using the IDRF that correspond to the (alpha, beta) incident angle...
float ** m2p_IDRF_CDFs
FLTNB mp_halfFOV[3]
Definition: vProjector.hh:341
#define EXIT_DEBUG
Definition: gVariables.hh:97
int ProjectWithTOFPos(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF continuous information.
FLTNB * GetPosition2()
This function is used to get the pointer to the mp_position2 (3-values tab).
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
#define FORWARD
#define Cout(MESSAGE)
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
bool m_compatibleWithCompression
Definition: vProjector.hh:358
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.