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