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);
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);
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);
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);
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);
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);
161 Cerr(
"***** iProjectorIRIS::ReadOptionsList() -> This projector should be initialized with a configuration file, and not parameters (-proj IRIS:path_to_configuration_file) !" << endl);
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;
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;
205 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> path to IDRF files not initialized !" << endl);
210 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> IDRF coefficients not initialized !" << endl);
215 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> number of lines per LOR not initialized !" << endl);
220 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> number of voxels for the IDRF volumes not initialized !" << endl);
225 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> voxel sizes of the IDRF volumes not initialized !" << endl);
230 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> number of angles for the IDRF volumes not initialized !" << endl);
235 Cerr(
"***** iProjectorIRIS::CheckSpecificParameters() -> step of the IDRF angles not initialized !" << endl);
250 if (
m_verbose>=2)
Cout(
"iProjectorIRIS::InitializeSpecific() -> Use IRIS projector" << endl);
257 ifstream IDRF_file(
mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b].c_str(), ios::binary| ios::in);
258 if (!IDRF_file.is_open())
260 Cerr(
"***** iProjectorIRIS::InitializeSpecific() -> Error reading the IRDF .vol file at the path: '" <<
mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b] <<
"'" << endl);
264 IDRF_file.seekg(0, ios::end);
265 size_t size_in_bytes = IDRF_file.tellg();
267 if(((
size_t)((6+
m_nVoxXYZIDRF)*
sizeof(
float))) != size_in_bytes)
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);
275 float vol_file_header[6];
278 for(
int i=0 ; i<6 ; i++)
279 IDRF_file.read((
char*)&vol_file_header[i],
sizeof(
float));
288 Cerr(
"***** iProjectorIRIS::InitializeSpecific() -> Inconsistency between initialized and read header file in the .vol: '" <<
mp_pathToIDRFFiles[a*m_nBetaAnglesIDRF+b] <<
"'" << endl);
294 IDRF_file.read((
char*)&vol_file_header[0],
sizeof(
float));
295 mp_IDRF[i] = vol_file_header[0];
322 max_nb_voxels_in_dimension *= 4;
326 return max_nb_voxels_in_dimension;
339 Cerr(
"***** iProjectorIRIS::ProjectWithoutTOF() -> Called while not initialized !" << endl);
344 #ifdef CASTOR_VERBOSE
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);
359 float x1, y1, z1, crystal_alpha1, x2, y2, z2, crystal_alpha2;
373 crystal_alpha1 = atan2f(orientation1[0], orientation1[1]);
374 crystal_alpha2 = atan2f(orientation2[0], orientation2[1]);
380 float alpha1, alpha2, alpha_lor;
383 alpha_lor = atan2f(x1-x2, y1-y2);
386 alpha1 = remainderf(alpha_lor-M_PI-crystal_alpha1, M_PI);
390 alpha2 = remainderf(alpha_lor-M_PI-crystal_alpha2, M_PI);
403 float beta1, beta2, H;
406 H = sqrtf((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
409 beta1 = atan2f( (z1-z2), H );
412 beta1 = remainderf(beta1, M_PI);
417 beta2 = remainderf(beta2, M_PI);
478 float pos1[3], pos2[3];
481 Cerr(
"***** iProjectorIRIS::ProjectWithoutTOF() -> An error occurred while trying to generate random position with the IRIS projector" << endl);
491 Cerr(
"***** iProjectorIRIS::ProjectWithoutTOF() -> An error occurred while trying to generate random position with the IRIS projector" << endl);
506 tmp_X = X1; tmp_Y = Y1;
507 X1 = x1 + tmp_X*orientation1[0]-tmp_Y*orientation1[1];
508 Y1 = y1 + tmp_X*orientation1[1]+tmp_Y*orientation1[0];
516 tmp_X = X2; tmp_Y = Y2;
517 X2 = x2 + tmp_X*orientation2[0]-tmp_Y*orientation2[1];
518 Y2 = y2 + tmp_X*orientation2[1]+tmp_Y*orientation2[0];
538 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
539 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
541 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
549 for(
int i = 0; i < 3; ++i )
551 if( delta_pos[ i ] != 0.0 )
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]));
562 if( alphaMax <= alphaMin )
return 0;
566 int iMin = 0, iMax = 0;
567 int jMin = 0, jMax = 0;
568 int kMin = 0, kMax = 0;
571 if( delta_pos[ 0 ] > 0.0f )
574 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
576 else if( delta_pos[ 0 ] < 0.0f )
579 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
581 if( delta_pos[ 0 ] == 0 )
587 if( delta_pos[ 1 ] > 0 )
590 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
592 else if( delta_pos[ 1 ] < 0 )
595 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
597 else if( delta_pos[ 1 ] == 0 )
603 if( delta_pos[ 2 ] > 0 )
606 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
608 else if( delta_pos[ 2 ] < 0 )
611 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
613 else if( delta_pos[ 2 ] == 0 )
619 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
620 + ( kMax - kMin + 1 );
623 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
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 ];
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 ];
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 ];
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
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 ];
663 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ],
664 (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
667 HPFLTNB const alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
668 INTNB index_ijk[ 3 ] = {
681 for(
int nP = 0; nP < n - 1; ++nP )
683 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
684 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
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 ) )
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);
701 alpha_c = alpha_XYZ[ 0 ];
702 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
703 index_ijk[ 0 ] += index_u[ 0 ];
705 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
706 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
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 ) )
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);
723 alpha_c = alpha_XYZ[ 1 ];
724 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
725 index_ijk[ 1 ] += index_u[ 1 ];
727 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
728 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
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 ) )
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);
745 alpha_c = alpha_XYZ[ 2 ];
746 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
747 index_ijk[ 2 ] += index_u[ 2 ];
763 Cerr(
"***** iProjectorIRIS::ProjectWithTOFPos() -> Not yet implemented !" << endl);
774 Cerr(
"***** iProjectorIRIS::ProjectWithTOFBin() -> Not yet implemented !" << endl);
828 if(a_alpha<0) rdm_pos[1] = -rdm_pos[1];
829 if(a_beta<0) rdm_pos[2] = -rdm_pos[2];
831 ap_generatedPos[0] = rdm_pos[0];
832 ap_generatedPos[1] = rdm_pos[1];
833 ap_generatedPos[2] = rdm_pos[2];
845 int min = a_minStart, max, mid;
847 max = a_maxStart ? a_maxStart : a_maxValue;
853 mid = (min + max) >> 1;
854 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).
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.
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...
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.
bool m_compatibleWithCompression
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.