CASToR  2.0
Tomographic Reconstruction (PET/SPECT/CT)
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vProjector.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 "vProjector.hh"
32 #include "vScanner.hh"
33 #include "vDataFile.hh"
34 
35 // =====================================================================
36 // ---------------------------------------------------------------------
37 // ---------------------------------------------------------------------
38 // =====================================================================
39 
41 {
42  // Affect default values
43  mp_Scanner = NULL;
45  mp_sizeVox[0] = -1.;
46  mp_sizeVox[1] = -1.;
47  mp_sizeVox[2] = -1.;
48  mp_nbVox[0] = -1;
49  mp_nbVox[1] = -1;
50  mp_nbVox[2] = -1;
51  m_nbVoxXY = -1;
52  mp_halfFOV[0] = -1.;
53  mp_halfFOV[1] = -1.;
54  mp_halfFOV[2] = -1.;
55  m_sensitivityMode = false;
56  m_applyTOF = -1;
57  m_TOFnbSigmas = 3.;
58  m_applyPOI = false;
61  m_verbose = 0;
62  m_checked = false;
63  m_initialized = false;
64  mp_mask = NULL;
65  m_hasMask = false;
66 }
67 
68 // =====================================================================
69 // ---------------------------------------------------------------------
70 // ---------------------------------------------------------------------
71 // =====================================================================
72 
74 {
75  ;
76 }
77 
78 // =====================================================================
79 // ---------------------------------------------------------------------
80 // ---------------------------------------------------------------------
81 // =====================================================================
82 
84 {
85  // Check that the parameter is not NULL
86  if (ap_ImageDimensionsAndQuantification==NULL)
87  {
88  Cerr("***** vProjector::SetImageDimensionsAndQuantification() -> Input image dimensions object is null !" << endl);
89  return 1;
90  }
91  // Affect image dimensions
92  mp_sizeVox[0] = ap_ImageDimensionsAndQuantification->GetVoxSizeX();
93  mp_sizeVox[1] = ap_ImageDimensionsAndQuantification->GetVoxSizeY();
94  mp_sizeVox[2] = ap_ImageDimensionsAndQuantification->GetVoxSizeZ();
95  mp_nbVox[0] = ap_ImageDimensionsAndQuantification->GetNbVoxX();
96  mp_nbVox[1] = ap_ImageDimensionsAndQuantification->GetNbVoxY();
97  mp_nbVox[2] = ap_ImageDimensionsAndQuantification->GetNbVoxZ();
98  m_nbVoxXY = mp_nbVox[0] * mp_nbVox[1];
99  mp_halfFOV[0] = mp_sizeVox[0] * ((FLTNB)mp_nbVox[0]) / 2.;
100  mp_halfFOV[1] = mp_sizeVox[1] * ((FLTNB)mp_nbVox[1]) / 2.;
101  mp_halfFOV[2] = mp_sizeVox[2] * ((FLTNB)mp_nbVox[2]) / 2.;
102  mp_ImageDimensionsAndQuantification = ap_ImageDimensionsAndQuantification;
103  // Normal end
104  return 0;
105 }
106 
107 // =====================================================================
108 // ---------------------------------------------------------------------
109 // ---------------------------------------------------------------------
110 // =====================================================================
111 
113 {
114  // Return when using MPI and mpi_rank is not 0
115  #ifdef CASTOR_MPI
116  int mpi_rank = 0;
117  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
118  if (mpi_rank!=0) return;
119  #endif
120  // Show help
121  cout << "------------------------------------------------------------------" << endl;
122  cout << "----- Common options for all projectors" << endl;
123  cout << "------------------------------------------------------------------" << endl;
124  cout << "Currently a single common option is implemented, relevant only for TOF recon: " << endl;
125  cout << " the number of standard deviations for truncating the TOF distribution." << endl;
126 }
127 
128 // =====================================================================
129 // ---------------------------------------------------------------------
130 // ---------------------------------------------------------------------
131 // =====================================================================
132 
134 {
135  // Call the specific help function from the children
137  // Then, say if the child projector in use is compatible with SPECT attenuation correction or not
138  if (m_compatibleWithSPECTAttenuationCorrection) cout << "This projector is compatible with SPECT attenuation correction." << endl;
139  else cout << "This projector is NOT compatible with SPECT attenuation correction." << endl;
140 }
141 
142 // =====================================================================
143 // ---------------------------------------------------------------------
144 // ---------------------------------------------------------------------
145 // =====================================================================
146 
147 int vProjector::ReadCommonOptionsList(const string& a_optionsList)
148 {
149  // TODO : make this more explicit, here it is assumed that a single specific option can be provided
150  // (number of standard deviations for TOF truncation)
151  if (a_optionsList!="")
152  {
153  FLTNB option[1];
154  // Read the option for the number of standard deviations for the truncation of TOF weighting function
155  if (ReadStringOption(a_optionsList, option, 1, ",", "Common options"))
156  {
157  Cerr("***** vProjector::ReadCommonOptionsList() -> Failed to correctly read the list of options !" << endl);
158  return 1;
159  }
160  m_TOFnbSigmas = option[0];
161  }
162  return 0;
163 }
164 
165 // =====================================================================
166 // ---------------------------------------------------------------------
167 // ---------------------------------------------------------------------
168 // =====================================================================
169 
171 {
172  // Check scanner
173  if (mp_Scanner==NULL)
174  {
175  Cerr("***** vProjector::CheckParameters() -> Please provide a valid scanner object !" << endl);
176  return 1;
177  }
178  // Check image dimensions
180  {
181  Cerr("***** vProjector::CheckParameters() -> Please provide a valid image dimensions and quantification object !" << endl);
182  return 1;
183  }
184  if (mp_sizeVox[0]<=0. || mp_sizeVox[1]<=0. || mp_sizeVox[2]<=0.)
185  {
186  Cerr("***** vProjector::CheckParameters() -> One or more voxel sizes is negative or null !" << endl);
187  return 1;
188  }
189  if (mp_nbVox[0]<=0 || mp_nbVox[1]<=0 || mp_nbVox[2]<=0)
190  {
191  Cerr("***** vProjector::CheckParameters() -> One or more number of voxels is negative or null !" << endl);
192  return 1;
193  }
194  // Check TOF
196  {
197  Cerr("***** vProjector::CheckParameters() -> TOF flag is incorrect or not set !" << endl);
198  return 1;
199  }
200  // Check verbose level
201  if (m_verbose<0)
202  {
203  Cerr("***** vProjector::CheckParameters() -> Verbose level is negative !" << endl);
204  return 1;
205  }
206  // Check parameters of the child class
208  {
209  Cerr("***** vProjector::CheckParameters() -> An error occurred while checking parameters of the child projector class !" << endl);
210  return 1;
211  }
212  // Check the number of sigmas for TOF
213  if (m_TOFnbSigmas<=0.)
214  {
215  Cerr("***** vProjector::CheckParameters() -> TOF number of standard deviations is not > 0 !" << endl);
216  return 1;
217  }
218  // Normal end
219  m_checked = true;
220  return 0;
221 }
222 
223 // =====================================================================
224 // ---------------------------------------------------------------------
225 // ---------------------------------------------------------------------
226 // =====================================================================
227 
229 {
230  // First check that the parameters has been checked !
231  if (!m_checked)
232  {
233  Cerr("***** vProjector::Initialize() -> Must call the CheckParameters() function before initialization !" << endl);
234  return 1;
235  }
236  // Call the intialize function specific to the children
237  if (InitializeSpecific())
238  {
239  Cerr("***** vProjector::Initialize() -> A problem occured while calling the specific initialization of the child projector !" << endl);
240  return 1;
241  }
242 
243  // Normal end
244  m_initialized = true;
245  return 0;
246 }
247 
248 // =====================================================================
249 // ---------------------------------------------------------------------
250 // ---------------------------------------------------------------------
251 // =====================================================================
252 
254 {
256 }
257 
258 // =====================================================================
259 // ---------------------------------------------------------------------
260 // ---------------------------------------------------------------------
261 // =====================================================================
262 
263 int vProjector::Project(int a_direction, oProjectionLine* ap_ProjectionLine, uint32_t* ap_index1, uint32_t* ap_index2, int a_nbIndices)
264 {
265  #ifdef CASTOR_DEBUG
266  if (!m_initialized)
267  {
268  Cerr("***** vProjector::Project() -> Called while not initialized !" << endl);
269  Exit(EXIT_DEBUG);
270  }
271  #endif
272 
274 
275  // ---------------------------------------------------------------------------------------
276  // First: Get cartesian coordinates from the scanner and average positions if compression.
277  // Here, we differentiate the case with no compression (i.e. a_nbIndices==1) from the
278  // compression case, because it will avoid to perform useless computation without
279  // compression. However, it produces some duplication of code parts as a compromise.
280  // ---------------------------------------------------------------------------------------
281 
282  // ______________________________________________________________________________________
283  // Case1: no compression (i.e. a_nbIndices==1)
284  if (a_nbIndices==1)
285  {
286  // Set indices of the line
287  ap_ProjectionLine->SetIndex1(((int)(ap_index1[0])));
288  ap_ProjectionLine->SetIndex2(((int)(ap_index2[0])));
289  // Get positions and orientations from the scanner (mean depth of interaction intrinsicaly taken into account), taking POI into account if any
290  if (mp_Scanner->GetPositionsAndOrientations( ((int)(ap_index1[0])), ((int)(ap_index2[0])),
291  ap_ProjectionLine->GetPosition1(), ap_ProjectionLine->GetPosition2(),
292  ap_ProjectionLine->GetOrientation1(), ap_ProjectionLine->GetOrientation2(),
293  ap_ProjectionLine->GetPOI1(), ap_ProjectionLine->GetPOI2() ))
294  {
295  Cerr("***** vProjector::Project() -> A problem occured while getting positions and orientations from scanner !" << endl);
296  return 1;
297  }
298  }
299  // ______________________________________________________________________________________
300  // Case2: compression (i.e. a_nbIndices>1)
301  else
302  {
303  // Set default indices of the line to -1 when compression
304  ap_ProjectionLine->SetIndex1(-1);
305  ap_ProjectionLine->SetIndex2(-1);
306  // Buffer pointers for positions and orientations handled by the projection line
307  FLTNB* position1 = ap_ProjectionLine->GetPosition1();
308  FLTNB* position2 = ap_ProjectionLine->GetPosition2();
309  FLTNB* orientation1 = ap_ProjectionLine->GetOrientation1();
310  FLTNB* orientation2 = ap_ProjectionLine->GetOrientation2();
311  FLTNB* buffer_position1 = ap_ProjectionLine->GetBufferPosition1();
312  FLTNB* buffer_position2 = ap_ProjectionLine->GetBufferPosition2();
313  FLTNB* buffer_orientation1 = ap_ProjectionLine->GetBufferOrientation1();
314  FLTNB* buffer_orientation2 = ap_ProjectionLine->GetBufferOrientation2();
315  // Zero the position and orientation
316  for (int i=0; i<3; i++)
317  {
318  position1[i] = 0.;
319  position2[i] = 0.;
320  orientation1[i] = 0.;
321  orientation2[i] = 0.;
322  }
323  // Loop on provided indices
324  for (int l=0; l<a_nbIndices; l++)
325  {
326  // Get positions and orientations from scanner (mean depth of interaction intrinsicaly taken into account), taking POI into account if any
327  if (mp_Scanner->GetPositionsAndOrientations( ((int)(ap_index1[l])), ((int)(ap_index2[l])),
328  buffer_position1, buffer_position2,
329  buffer_orientation1, buffer_orientation2,
330  ap_ProjectionLine->GetPOI1(), ap_ProjectionLine->GetPOI2() ))
331  {
332  Cerr("***** vProjector::Project() -> A problem occured while getting positions and orientations from scanner !" << endl);
333  return 1;
334  }
335  // Add those contributions to the mean position and orientation
336  for (int i=0; i<3; i++)
337  {
338  position1[i] += buffer_position1[i];
339  position2[i] += buffer_position2[i];
340  orientation1[i] += buffer_orientation1[i];
341  orientation2[i] += buffer_orientation2[i];
342  }
343  }
344  // Average positions and orientations
345  for (int i=0; i<3; i++)
346  {
347  position1[i] /= ((FLTNB)a_nbIndices);
348  position2[i] /= ((FLTNB)a_nbIndices);
349  orientation1[i] /= ((FLTNB)a_nbIndices);
350  orientation2[i] /= ((FLTNB)a_nbIndices);
351  }
352  }
353 
354  // --------------------------------------------------------------
355  // Second: Modify the end points coordinates from common options,
356  // random, offset, and LOR displacements.
357  // -----------------------------------------------------------
358 
359  // Apply common options TODO
360 
361  // Apply LORs displacement TODO
362 
363  // Apply global image offset
364  ap_ProjectionLine->ApplyOffset();
365 
366  // Apply bed position offset
367  ap_ProjectionLine->ApplyBedOffset();
368 
369  // -----------------------------------------------------------
370  // Third: project the line
371  // -----------------------------------------------------------
372 
373  // Compute LOR length
374  ap_ProjectionLine->ComputeLineLength();
375 
376  // Switch on different TOF options
377  switch (m_applyTOF)
378  {
379  case USE_NOTOF:
380  if (ProjectWithoutTOF( a_direction, ap_ProjectionLine ))
381  {
382  Cerr("***** vProjector::Project() -> A problem occured while projecting a line without time-of-flight !" << endl);
383  return 1;
384  }
385  break;
386  case USE_TOFPOS:
387  if (ProjectWithTOFPos( a_direction, ap_ProjectionLine ))
388  {
389  Cerr("***** vProjector::Project() -> A problem occured while projecting a line with time-of-flight position !" << endl);
390  return 1;
391  }
392  break;
393  case USE_TOFBIN:
394  if (ProjectWithTOFBin( a_direction, ap_ProjectionLine ))
395  {
396  Cerr("***** vProjector::Project() -> A problem occured while projecting a line with binned time-of-flight !" << endl);
397  return 1;
398  }
399  break;
400  // No default
401  }
402 
403  #ifdef CASTOR_VERBOSE
404  if (m_verbose>=10)
405  {
406  Cout("vProjector::Project() -> Exit function" << endl);
407  }
408  #endif
409 
410  // End
411  return 0;
412 }
413 
414 // =====================================================================
415 // ---------------------------------------------------------------------
416 // ---------------------------------------------------------------------
417 // =====================================================================
bool m_applyPOI
Definition: vProjector.hh:351
bool m_checked
Definition: vProjector.hh:362
bool m_compatibleWithSPECTAttenuationCorrection
Definition: vProjector.hh:355
FLTNB * GetOrientation1()
This function is used to get the pointer to the mp_orientation1 (3-values tab).
#define VERBOSE_DEBUG_EVENT
FLTNB mp_sizeVox[3]
Definition: vProjector.hh:338
FLTNB * GetPOI1()
This function is used to get the pointer to POI of point 1 (3-values tab).
static void ShowCommonHelp()
This function is used to print out some help about the use of options common to all projectors...
Definition: vProjector.cc:112
INTNB m_nbVoxXY
Definition: vProjector.hh:340
INTNB mp_nbVox[3]
Definition: vProjector.hh:339
#define FLTNB
Definition: gVariables.hh:81
FLTNB GetVoxSizeX()
Get the voxel's size along the X axis, in mm.
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
Definition: vProjector.hh:344
FLTNB GetVoxSizeZ()
Get the voxel's size along the Z axis, in mm.
FLTNB * GetBufferPosition2()
This function is used to get the pointer to the mp_bufferPosition2 (3-values tab).
vProjector()
The constructor of vProjector.
Definition: vProjector.cc:40
int Initialize()
A public function used to initialize the projector.
Definition: vProjector.cc:228
virtual int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)=0
A function to project without TOF.
int Project(int a_direction, oProjectionLine *ap_ProjectionLine, uint32_t *ap_index1, uint32_t *ap_index2, int a_nbIndices)
A function use to computed the projection elements with respect to the provided parameters.
Definition: vProjector.cc:263
FLTNB * GetBufferPosition1()
This function is used to get the pointer to the mp_bufferPosition1 (3-values tab).
virtual int ProjectWithTOFBin(int a_direction, oProjectionLine *ap_ProjectionLine)=0
A function to project with TOF binned information.
FLTNB * GetOrientation2()
This function is used to get the pointer to the mp_orientation2 (3-values tab).
void SetIndex2(int a_index2)
This function is used to set the index m_index1 of point 2.
void Exit(int code)
virtual int CheckSpecificParameters()=0
A private function used to check the parameters settings specific to the child projector.
void ComputeLineLength()
Simply compute and update the m_length using the associated mp_position1 and mp_position2.
int ReadCommonOptionsList(const string &a_optionsList)
This function is used to read options common to all projectors given as a string. ...
Definition: vProjector.cc:147
FLTNB GetVoxSizeY()
Get the voxel's size along the Y axis, in mm.
#define Cerr(MESSAGE)
void ApplyOffset()
Apply the offset of oImageDimensionsAndQuantification to the mp_position1 and mp_position2.
FLTNB * GetPosition1()
This function is used to get the pointer to the mp_position1 (3-values tab).
virtual void ShowHelpSpecific()=0
A function used to show help about the child module.
bool m_initialized
Definition: vProjector.hh:364
bool m_sensitivityMode
Definition: vProjector.hh:353
Declaration of class vProjector.
bool * mp_mask
Definition: vProjector.hh:365
FLTNB * GetBufferOrientation1()
This function is used to get the pointer to the mp_bufferOrientation1 (3-values tab).
virtual ~vProjector()
The destructor of vProjector.
Definition: vProjector.cc:73
Declaration of class vScanner.
Declaration of class vDataFile.
int CheckParameters()
A public function used to check the parameters settings.
Definition: vProjector.cc:170
FLTNB * GetBufferOrientation2()
This function is used to get the pointer to the mp_bufferOrientation2 (3-values tab).
void SetIndex1(int a_index1)
This function is used to set the index m_index1 of point 1.
bool m_hasMask
Definition: vProjector.hh:366
FLTNB m_TOFnbSigmas
Definition: vProjector.hh:349
#define INTNB
Definition: gVariables.hh:92
This class is designed to manage and store system matrix elements associated to a vEvent...
virtual int ProjectWithTOFPos(int a_direction, oProjectionLine *ap_ProjectionLine)=0
A function to project with TOF continuous information.
virtual int InitializeSpecific()=0
A private function used to initialize everything specific to the child projector. ...
INTNB GetNbVoxXYZ()
Get the total number of voxels.
FLTNB mp_halfFOV[3]
Definition: vProjector.hh:341
#define EXIT_DEBUG
Definition: gVariables.hh:97
This class is designed to manage all dimensions and quantification related stuff. ...
#define USE_TOFPOS
Definition: vProjector.hh:50
FLTNB * GetPosition2()
This function is used to get the pointer to the mp_position2 (3-values tab).
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
#define DEBUG_VERBOSE(IGNORED1, IGNORED2)
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
#define USE_NOTOF
Definition: vProjector.hh:52
#define Cout(MESSAGE)
#define USE_TOFBIN
Definition: vProjector.hh:48
virtual INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
Definition: vProjector.cc:253
bool m_compatibleWithCompression
Definition: vProjector.hh:358
void ShowHelp()
A function used to show help about the projector.
Definition: vProjector.cc:133
FLTNB * GetPOI2()
This function is used to get the pointer to POI of point 2 (3-values tab).
int SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the pointer to the image dimensions in use and copy locally some often use variables.
Definition: vProjector.cc:83
int ReadStringOption(const string &a_input, T *ap_return, int a_nbElts, const string &sep, const string &a_option)
Parse the 'a_input' string corresponding to the 'a_option' into 'a_nbElts' elements, using the 'sep' separator. The results are returned in the templated 'ap_return' dynamic templated array. Call "ConvertFromString()" to perform the correct conversion depending on the type of the data to convert.
Definition: gOptions.cc:62
virtual int GetPositionsAndOrientations(int a_index1, int a_index2, FLTNB ap_Position1[3], FLTNB ap_Position2[3], FLTNB ap_Orientation1[3], FLTNB ap_Orientation2[3], FLTNB *ap_POI1=NULL, FLTNB *ap_POI2=NULL)=0
This is a pure virtual method that must be implemented by children. Get the central positions and o...
void ApplyBedOffset()
Apply the bed offset of m_bedOffset to the mp_position1 and mp_position2.
vScanner * mp_Scanner
Definition: vProjector.hh:346
int m_applyTOF
Definition: vProjector.hh:348
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.