77 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);
85 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);
96 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);
103 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);
110 Cerr(
"***** iProjectorIRIS::ReadConfigurationFile() -> An error occurred while trying to read the alpha/beta angles steps from the IRIS configuration file at :" << a_configurationFile <<
" !" << endl);
128 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(
"***** iProjectorIRIS::ReadOptionsList() -> This projector should be initialized with a configuration file, and not parameters (-proj IRIS:path_to_configuration_file) !" << endl);
156 cout <<
"Multiray projector requiring Intrinsic Detector Response Functions (IDRFs) models" << endl;
157 cout <<
"The projector will generate an user-defined number of lines using from pairs of random points generated using the IDRFs models" << endl;
158 cout <<
"The lines will be rendered using the Incremental Siddon projector (incrementalSiddon)" << endl;
159 cout <<
"This projector requires an initialization file and Monte-Carlo generated IDRFs. For more informations, please read [article]" << endl;
160 cout <<
"INITIALIZATION FILE FIELDS :" << endl;
161 cout <<
"number lines per LOR : number of lines generated to estimate the CDRF (int32)" << endl;
162 cout <<
"number voxels depth : number of voxels in the depth direction in the IDRF volumes (int32)" << endl;
163 cout <<
"number voxels transaxial : number of voxels in the transaxial direction in the IDRF volumes (int32)" << endl;
164 cout <<
"number voxels axial : number of voxels in the axial direction in the IDRF volumes (int32)" << endl;
165 cout <<
"size voxels depth : size of voxels in the depth direction of the IDRF volumes (float32)" << endl;
166 cout <<
"size voxels transaxial : size of voxels in the transaxial direction of the IDRF volume (float32)" << endl;
167 cout <<
"size voxels axial : size of voxels in the axial direction of the IDRF volume (float32)" << endl;
168 cout <<
"number beta angles : number of axial angles in the IDRF volumes (int32)" << endl;
169 cout <<
"number alpha angles : number of transaxial angles in the IDRF volumes (int32)" << endl;
170 cout <<
"step beta angles : axial angular steps in the IDRF volumes (float32)" << endl;
171 cout <<
"step alpha angles : transaxial angular steps in the IDRF volumes (float32)" << endl;
172 cout <<
"IDRFs path : path to the IDRF .vol files (string)" << endl;
173 cout <<
" : each path should be entered on a separated line" << endl;
175 cout <<
"Each .vol files should contain a header of 6 float32 fields :" << endl;
176 cout <<
"number voxels axial ; number voxels transaxial ; number voxels depth ; size voxels axial ; size voxels transaxial ; size voxels depth" << endl;
177 cout <<
"... followed by number voxels depth*number voxels transaxial*number voxels axial float32 elements corresponding to the IDRF coefficients" << endl;
189 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> path to IDRF files not initialized !" << endl);
194 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> IDRF coefficients not initialized !" << endl);
199 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> number of lines per LOR not initialized !" << endl);
204 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> number of voxels for the IDRF volumes not initialized !" << endl);
209 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> voxel sizes of the IDRF volumes not initialized !" << endl);
214 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> number of angles for the IDRF volumes not initialized !" << endl);
219 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> step of the IDRF angles not initialized !" << endl);
234 if (
m_verbose>=2)
Cout(
"iProjectorIRIS::InitializeSpecific() -> Use IRIS projector" << endl);
241 ifstream IDRF_file(
mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b].c_str(), ios::binary| ios::in);
242 if (!IDRF_file.is_open())
244 Cerr(
"***** iProjectorIRIS::InitializeSpecific() -> Error reading the IRDF .vol file at the path: '" <<
mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b] <<
"'" << endl);
248 IDRF_file.seekg(0, ios::end);
249 size_t size_in_bytes = IDRF_file.tellg();
251 if(((
size_t)((6+
m_nVoxXYZIDRF)*
sizeof(
float))) != size_in_bytes)
253 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);
254 Cerr(
"***** iProjectorIRIS::InitializeSpecific() -> Expected size : "<< (6+
m_nVoxXYZIDRF)*
sizeof(
float) << endl);
255 Cerr(
"***** iProjectorIRIS::InitializeSpecific() -> Actual size : "<< size_in_bytes << endl << endl);
259 float vol_file_header[6];
262 for(
int i=0 ; i<6 ; i++)
263 IDRF_file.read((
char*)&vol_file_header[i],
sizeof(
float));
272 Cerr(
"***** iProjectorIRIS::InitializeSpecific() -> Inconsistency between initialized and read header file in the .vol: '" <<
mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b] <<
"'" << endl);
278 IDRF_file.read((
char*)&vol_file_header[0],
sizeof(
float));
279 mp_IDRF[i] = vol_file_header[0];
306 max_nb_voxels_in_dimension *= 4;
310 return max_nb_voxels_in_dimension;
323 Cerr(
"***** iProjectorIRIS::ProjectWithoutTOF() -> Called while not initialized !" << endl);
328 #ifdef CASTOR_VERBOSE
331 string direction =
"";
332 if (a_direction==
FORWARD) direction =
"forward";
333 else direction =
"backward";
334 Cout(
"iProjectorIRIS::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
343 float x1, y1, z1, crystal_alpha1, x2, y2, z2, crystal_alpha2;
357 crystal_alpha1 = atan2f(orientation1[0], orientation1[1]);
358 crystal_alpha2 = atan2f(orientation2[0], orientation2[1]);
364 float alpha1, alpha2, alpha_lor;
367 alpha_lor = atan2f(x1-x2, y1-y2);
370 alpha1 = remainderf(alpha_lor-M_PI-crystal_alpha1, M_PI);
374 alpha2 = remainderf(alpha_lor-M_PI-crystal_alpha2, M_PI);
387 float beta1, beta2, H;
390 H = sqrtf((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
393 beta1 = atan2f( (z1-z2), H );
396 beta1 = remainderf(beta1, M_PI);
401 beta2 = remainderf(beta2, M_PI);
462 float pos1[3], pos2[3];
465 Cerr(
"***** iProjectorIRIS::ProjectWithoutTOF() -> An error occurred while trying to generate random position with the IRIS projector" << endl);
475 Cerr(
"***** iProjectorIRIS::ProjectWithoutTOF() -> An error occurred while trying to generate random position with the IRIS projector" << endl);
490 tmp_X = X1; tmp_Y = Y1;
491 X1 = x1 + tmp_X*orientation1[0]-tmp_Y*orientation1[1];
492 Y1 = y1 + tmp_X*orientation1[1]+tmp_Y*orientation1[0];
500 tmp_X = X2; tmp_Y = Y2;
501 X2 = x2 + tmp_X*orientation2[0]-tmp_Y*orientation2[1];
502 Y2 = y2 + tmp_X*orientation2[1]+tmp_Y*orientation2[0];
517 double length_LOR = ap_ProjectionLine->
GetLength();
522 double alphaFirst[] = { 0.0, 0.0, 0.0 };
523 double alphaLast[] = { 0.0, 0.0, 0.0 };
525 double alphaMin = 0.0f, alphaMax = 1.0f;
526 double delta_pos[] = {
533 for(
int i = 0; i < 3; ++i )
535 if( delta_pos[ i ] != 0.0 )
537 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
538 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
539 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
540 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
546 if( alphaMax <= alphaMin )
return 0;
550 int iMin = 0, iMax = 0;
551 int jMin = 0, jMax = 0;
552 int kMin = 0, kMax = 0;
555 if( delta_pos[ 0 ] > 0.0f )
558 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
560 else if( delta_pos[ 0 ] < 0.0f )
563 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
565 if( delta_pos[ 0 ] == 0 )
571 if( delta_pos[ 1 ] > 0 )
574 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
576 else if( delta_pos[ 1 ] < 0 )
579 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
581 else if( delta_pos[ 1 ] == 0 )
587 if( delta_pos[ 2 ] > 0 )
590 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
592 else if( delta_pos[ 2 ] < 0 )
595 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
597 else if( delta_pos[ 2 ] == 0 )
603 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
604 + ( kMax - kMin + 1 );
607 double alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
610 if( delta_pos[ 0 ] > 0 )
611 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
612 else if( delta_pos[ 0 ] < 0 )
613 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
616 if( delta_pos[ 1 ] > 0 )
617 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
618 else if( delta_pos[ 1 ] < 0 )
619 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
622 if( delta_pos[ 2 ] > 0 )
623 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
624 else if( delta_pos[ 2 ] < 0 )
625 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
628 double alpha_u[ 3 ] = {
635 INTNB index_u[ 3 ] = {
636 (delta_pos[ 0 ] < 0) ? -1 : 1,
637 (delta_pos[ 1 ] < 0) ? -1 : 1,
638 (delta_pos[ 2 ] < 0) ? -1 : 1
642 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
643 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
644 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
647 double const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ],
648 (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
651 double const alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
652 INTNB index_ijk[ 3 ] = {
662 double alpha_c = alphaMin;
665 for(
int nP = 0; nP < n - 1; ++nP )
667 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
668 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
671 if( ( alpha_XYZ[ 0 ] >= alphaMin )
672 && ( index_ijk[ 0 ] - 1 >= 0 )
673 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
674 && ( index_ijk[ 1 ] - 1 >= 0 )
675 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
676 && ( index_ijk[ 2 ] - 1 >= 0 )
677 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
679 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
680 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
681 ap_ProjectionLine->
AddVoxel(a_direction, numVox, coeff/m_nbLinesPerLOR);
685 alpha_c = alpha_XYZ[ 0 ];
686 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
687 index_ijk[ 0 ] += index_u[ 0 ];
689 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
690 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
693 if( ( alpha_XYZ[ 1 ] >= alphaMin )
694 && ( index_ijk[ 0 ] - 1 >= 0 )
695 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
696 && ( index_ijk[ 1 ] - 1 >= 0 )
697 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
698 && ( index_ijk[ 2 ] - 1 >= 0 )
699 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
701 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
702 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
703 ap_ProjectionLine->
AddVoxel(a_direction, numVox, coeff/m_nbLinesPerLOR);
707 alpha_c = alpha_XYZ[ 1 ];
708 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
709 index_ijk[ 1 ] += index_u[ 1 ];
711 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
712 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
715 if( ( alpha_XYZ[ 2 ] >= alphaMin )
716 && ( index_ijk[ 0 ] - 1 >= 0 )
717 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
718 && ( index_ijk[ 1 ] - 1 >= 0 )
719 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
720 && ( index_ijk[ 2 ] - 1 >= 0 )
721 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
723 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
724 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
725 ap_ProjectionLine->
AddVoxel(a_direction, numVox, coeff/m_nbLinesPerLOR);
729 alpha_c = alpha_XYZ[ 2 ];
730 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
731 index_ijk[ 2 ] += index_u[ 2 ];
747 Cerr(
"***** iProjectorIRIS::ProjectWithTOFPos() -> Not yet implemented !" << endl);
758 Cerr(
"***** iProjectorIRIS::ProjectWithTOFBin() -> Not yet implemented !" << endl);
812 if(a_alpha<0) rdm_pos[1] = -rdm_pos[1];
813 if(a_beta<0) rdm_pos[2] = -rdm_pos[2];
815 ap_generatedPos[0] = rdm_pos[0];
816 ap_generatedPos[1] = rdm_pos[1];
817 ap_generatedPos[2] = rdm_pos[2];
829 int min = a_minStart, max, mid;
831 max = a_maxStart ? a_maxStart : a_maxValue;
837 mid = (min + max) >> 1;
838 if (a_key > ap_val[mid])
bool m_compatibleWithSPECTAttenuationCorrection
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).
double GenerateRdmNber()
Generate a random number for the thread whose index is recovered from the ompenMP function...
string * mp_pathToIDRFFiles
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
This class is designed to generically described any on-the-fly projector.
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.
iProjectorIRIS()
The constructor of iProjectorIRIS.
FLTNB * GetPosition1()
This function is used to get the pointer to the mp_position1 (3-values tab).
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...
int ProjectWithTOFBin(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF binned information.
Declaration of class iProjectorIRIS.
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...
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...
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.
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.