53 string key_word =
"number of lines";
56 Cerr(
"***** iProjectorIncrementalSiddonMulti::ReadConfigurationFile() -> Failed to get the '" << key_word <<
"' keyword !" << endl);
73 Cerr(
"***** iProjectorIncrementalSiddonMulti::ReadConfigurationFile() -> Failed to correctly read the list of options !" << endl);
87 cout <<
"This projector uses multiple ray-tracing for a single event in order to estimate the solid angle contribution." << endl;
88 cout <<
"For each line of an event, the end points of the line are randomly chosen inside the detector element." << endl;
89 cout <<
"The ray-tracing is performed with the incremental Siddon algorithm (see incrementalSiddon projector)." << endl;
90 cout <<
"The only parameter of this projector is the number of lines to use per event:" << endl;
91 cout <<
" number of lines: the number of lines used per event" << endl;
104 Cerr(
"***** iProjectorIncrementalSiddonMulti::CheckSpecificParameters() -> The provided number of lines is less than 1 !" << endl);
119 if (
m_verbose>=2)
Cout(
"iProjectorIncrementalSiddonMulti::Initialize() -> Use incremental Siddon projector with " <<
m_nbLines <<
" lines per event" << endl);
137 max_nb_voxels_in_dimension *= 4;
141 return max_nb_voxels_in_dimension;
154 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectWithoutTOF() -> Called while not initialized !" << endl);
159 #ifdef CASTOR_VERBOSE
162 string direction =
"";
163 if (a_direction==
FORWARD) direction =
"forward";
164 else direction =
"backward";
165 Cout(
"iProjectorIncrementalSiddonMulti::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
177 Cerr(
"***** vProjector::Project() -> A problem occured while getting positions and orientations from scanner !" << endl);
184 double event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
185 double event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
197 double length_LOR = ap_ProjectionLine->
GetLength();
202 double alphaFirst[] = { 0.0, 0.0, 0.0 };
203 double alphaLast[] = { 0.0, 0.0, 0.0 };
205 double alphaMin = 0.0f, alphaMax = 1.0f;
206 double delta_pos[] = {
207 event2[ 0 ] - event1[ 0 ],
208 event2[ 1 ] - event1[ 1 ],
209 event2[ 2 ] - event1[ 2 ]
213 for(
int i = 0; i < 3; ++i )
215 if( delta_pos[ i ] != 0.0 )
217 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
218 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
219 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
220 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
226 if( alphaMax <= alphaMin )
return 0;
230 int iMin = 0, iMax = 0;
231 int jMin = 0, jMax = 0;
232 int kMin = 0, kMax = 0;
235 if( delta_pos[ 0 ] > 0.0f)
238 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
240 else if( delta_pos[ 0 ] < 0.0 )
243 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
245 if( delta_pos[ 0 ] == 0 )
251 if( delta_pos[ 1 ] > 0 )
254 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
256 else if( delta_pos[ 1 ] < 0 )
259 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
261 else if( delta_pos[ 1 ] == 0 )
267 if( delta_pos[ 2 ] > 0 )
270 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
272 else if( delta_pos[ 2 ] < 0 )
275 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
277 else if( delta_pos[ 2 ] == 0 )
283 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
284 + ( kMax - kMin + 1 );
287 double alpha_XYZ[ 3 ] = { 1.0, 1.0, 1.0 };
290 if( delta_pos[ 0 ] > 0 )
291 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
292 else if( delta_pos[ 0 ] < 0 )
293 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
296 if( delta_pos[ 1 ] > 0 )
297 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
298 else if( delta_pos[ 1 ] < 0 )
299 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
302 if( delta_pos[ 2 ] > 0 )
303 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
304 else if( delta_pos[ 2 ] < 0 )
305 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
308 double alpha_u[ 3 ] = {
315 INTNB index_u[ 3 ] = {
316 (delta_pos[ 0 ] < 0) ? -1 : 1,
317 (delta_pos[ 1 ] < 0) ? -1 : 1,
318 (delta_pos[ 2 ] < 0) ? -1 : 1
322 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
323 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
324 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
327 double const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ],
328 (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
331 double const alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
332 INTNB index_ijk[ 3 ] = {
342 double alpha_c = alphaMin;
345 for(
int nP = 0; nP < n - 1; ++nP )
347 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
348 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
351 if( ( alpha_XYZ[ 0 ] >= alphaMin )
352 && ( index_ijk[ 0 ] - 1 >= 0 )
353 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
354 && ( index_ijk[ 1 ] - 1 >= 0 )
355 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
356 && ( index_ijk[ 2 ] - 1 >= 0 )
357 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
359 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
360 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
361 ap_ProjectionLine->
AddVoxel(a_direction, numVox, coeff/((
FLTNB)m_nbLines));
365 alpha_c = alpha_XYZ[ 0 ];
366 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
367 index_ijk[ 0 ] += index_u[ 0 ];
369 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
370 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
373 if( ( alpha_XYZ[ 1 ] >= alphaMin )
374 && ( index_ijk[ 0 ] - 1 >= 0 )
375 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
376 && ( index_ijk[ 1 ] - 1 >= 0 )
377 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
378 && ( index_ijk[ 2 ] - 1 >= 0 )
379 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
381 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
382 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
383 ap_ProjectionLine->
AddVoxel(a_direction, numVox, coeff/((
FLTNB)m_nbLines));
387 alpha_c = alpha_XYZ[ 1 ];
388 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
389 index_ijk[ 1 ] += index_u[ 1 ];
391 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
392 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
395 if( ( alpha_XYZ[ 2 ] >= alphaMin )
396 && ( index_ijk[ 0 ] - 1 >= 0 )
397 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
398 && ( index_ijk[ 1 ] - 1 >= 0 )
399 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
400 && ( index_ijk[ 2 ] - 1 >= 0 )
401 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
403 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
404 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
405 ap_ProjectionLine->
AddVoxel(a_direction, numVox, coeff/((
FLTNB)m_nbLines));
409 alpha_c = alpha_XYZ[ 2 ];
410 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
411 index_ijk[ 2 ] += index_u[ 2 ];
426 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectWithTOFPos() -> Not yet implemented !" << endl);
437 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectWithTOFBin() -> Not yet implemented !" << endl);
void ShowHelpSpecific()
A function used to show help about the child module.
bool m_compatibleWithSPECTAttenuationCorrection
FLTNB * GetOrientation1()
This function is used to get the pointer to the mp_orientation1 (3-values tab).
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
This class is designed to generically described any on-the-fly projector.
int ProjectWithTOFPos(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF continuous information.
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
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 GetIndex2()
This function is used to get the index associated to point 2.
FLTNB * GetPosition1()
This function is used to get the pointer to the mp_position1 (3-values tab).
int ProjectWithTOFBin(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF binned information.
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
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...
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
Declaration of class iProjectorIncrementalSiddonMulti.
#define KEYWORD_MANDATORY
virtual int GetRdmPositionsAndOrientations(int a_index1, int a_index2, FLTNB ap_Position1[3], FLTNB ap_Position2[3], FLTNB ap_Orientation1[3], FLTNB ap_Orientation2[3])=0
This is a pure virtual method that must be implemented by children. Get random positions of the sca...
~iProjectorIncrementalSiddonMulti()
The destructor of iProjectorIncrementalSiddonMulti.
This class is designed to manage and store system matrix elements associated to a vEvent...
Declaration of class sOutputManager.
iProjectorIncrementalSiddonMulti()
The constructor of iProjectorIncrementalSiddonMulti.
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.
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
int GetIndex1()
This function is used to get the index associated to point 1.
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.
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project without TOF.
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.