105 Cout(
"iScannerPET::DescribeSpecific() -> Here is some specific content of the PET scanner" << endl);
113 if(l>0)
Cout(
" --> Layer "<<l<<
":"<< endl);
149 if (
m_verbose>=
VERBOSE_NORMAL)
Cout(
"iScannerPET::Instantiate() -> Create scanner structure and read parameters from configuration file"<< endl);
158 Cerr(
"***** iScannerPET::Instantiate() -> An error occurred while trying to read the number of layers in the scanner header file !" << endl);
164 Cerr(
"***** iScannerPET::Instantiate() -> Incorrect value for the number of layer (must be >0) !" << endl);
170 Cerr(
"***** iScannerPET::Instantiate() -> An error occurred while trying to read the number of elements in the scanner header file !" << endl);
198 if (a_scannerFileIsLUT)
205 Cerr(
"***** iScannerPET::Instantiate() -> An error occurred while trying to read the crystals size in the scanner header file !" << endl);
216 Cerr(
"***** iScannerPET::Instantiate() -> An error occurred while trying to read the crystals size in the scanner header file !" << endl);
233 Cerr(
"***** iScannerPET::Instantiate() -> An error occurred while trying to read the mean depth of interaction in the scanner header file !" << endl);
238 Cerr(
"***** iScannerPET::Instantiate() -> An error occurred while trying to read the min angle difference in the scanner header file !" << endl);
243 Cerr(
"***** iScannerPET::Instantiate() -> An error occurred while trying to read the multiple bed displacement in the scanner header file !" << endl);
273 if (
m_verbose>=
VERBOSE_NORMAL)
Cout(
"iScannerPET::BuildLUT() -> Build LUT for scanner elements coordinates and orientations"<< endl);
276 if (!a_scannerFileIsLUT)
280 Cerr(
"***** iScannerPET::BuildLUT() -> A problem occurred while generating scanner LUT !" << endl);
288 Cerr(
"***** iScannerPET::BuildLUT() -> A problem occurred while loading scanner LUT !" << endl);
313 Cerr(
"***** iScannerPET::CheckParameters() -> Scanner type not initialized !" << endl);
318 Cerr(
"***** iScannerPET::CheckParameters() -> Verbosity not initialized !" << endl);
323 Cerr(
"***** iScannerPET::CheckParameters() -> Incorrect value for the number of layer (must be >0) !" << endl);
328 Cerr(
"***** iScannerPET::CheckParameters() -> Number of crystals not initialized !" << endl);
333 Cerr(
"***** iScannerPET::CheckParameters() -> Number of crystals in layer(s) not initialized !" << endl);
338 Cerr(
"***** iScannerPET::CheckParameters() -> Crystals central positions not initialized !" << endl);
343 Cerr(
"***** iScannerPET::CheckParameters() -> Crystals orientations not initialized !" << endl);
348 Cerr(
"***** iScannerPET::CheckParameters() -> Crystals dimensions not initialized !" << endl);
353 Cout(
"***** iScannerPET::CheckParameters() -> Mean depth of interaction not initialized !" << endl);
358 Cerr(
"***** iScannerPET::CheckParameters() -> Minimum angle difference not initialized !" << endl);
363 Cerr(
"***** iScannerPET::CheckParameters() -> Scanner type not initialized !" << endl);
368 Cerr(
"***** iScannerPET::CheckParameters() -> Scanner type not initialized !" << endl);
395 Cerr(
"***** iScannerPET::Initialize() -> Parameters have not been checked !" << endl);
433 Cerr(
"***** iScannerPET::LoadLUT() -> An error occurred while trying to read a mandatory parameter in the scanner header file !" << endl);
441 scanner_lut_file = scanner_lut_file.substr(0, scanner_lut_file.find_last_of(
".")).append(
".lut");
444 FILE* LUT_file = fopen(scanner_lut_file.c_str(),
"rb");
447 Cerr(
"***** iScannerPET::LoadLUT() -> Input LUT file '" << scanner_lut_file <<
"' is missing or corrupted !" << endl);
452 int nb_data_read = 0;
457 nb_data_read += fread(&buffer,
sizeof(
FLTNBLUT),1,LUT_file);
459 nb_data_read += fread(&buffer,
sizeof(
FLTNBLUT),1,LUT_file);
461 nb_data_read += fread(&buffer,
sizeof(
FLTNBLUT),1,LUT_file);
464 nb_data_read += fread(&buffer,
sizeof(
FLTNBLUT),1,LUT_file);
466 nb_data_read += fread(&buffer,
sizeof(
FLTNBLUT),1,LUT_file);
468 nb_data_read += fread(&buffer,
sizeof(
FLTNBLUT),1,LUT_file);
476 if (nb_data_read!=m_nbCrystals*6)
478 Cerr(
"***** iScannerPET::LoadLUT() -> Failed to read all data in input LUT file '" << scanner_lut_file <<
"' !" << endl);
511 int *nb_ang_rsector_lyr,
521 *rsector_first_angle_lyr,
522 *rsector_angular_span_lyr,
523 *gap_axl_rsector_lyr,
528 *gap_trs_crystal_lyr,
529 *gap_axl_crystal_lyr;
551 string rotation_direction =
"";
563 Cerr(
"***** iScannerPET::ComputeLUT() -> An error occurred while trying to read a mandatory parameter for scanner LUT generation in the scanner header file !" << endl);
573 nb_axl_rsector_lyr[ l ] =1;
574 nb_trs_mod_lyr[ l ] =1;
575 nb_axl_mod_lyr[ l ] =1;
576 nb_trs_submod_lyr[ l ] = 1;
577 nb_axl_submod_lyr[ l ] = 1;
578 gap_axl_rsector_lyr[ l ] = 0.;
579 gap_trs_mod_lyr[ l ] = 0.;
580 gap_axl_mod_lyr[ l ] = 0.;
581 gap_trs_submod_lyr[ l ] = 0.;
582 gap_axl_submod_lyr[ l ] = 0.;
583 gap_trs_crystal_lyr[ l ] = 0.;
584 gap_axl_crystal_lyr[ l ] = 0.;
585 rsector_first_angle_lyr[ l ] = 0;
586 rsector_angular_span_lyr[ l ] = 360.;
605 Cerr(
"***** iScannerPET::ComputeLUT() -> An error occurred while trying to read an optionnal parameter for scanner LUT generation in the scanner header file !" << endl);
610 uint16_t *p_nbRings =
new uint16_t[
m_nbLayers];
612 p_nbRings[lyr] = nb_axl_rsector_lyr[ lyr ]
613 * nb_axl_mod_lyr[ lyr ]
614 * nb_axl_submod_lyr[ lyr ]
615 * nb_axl_crystal_lyr[ lyr ];
620 Cerr(
"***** iScannerPET::ComputeLUT() ->Error occurred while trying to initialize head rotation orientation " << endl);
627 int rsector_nb_zshift;
635 Cerr(
"***** iScannerPET::ComputeLUT() -> Error occurred when trying to read z-shift nb !" << endl);
639 else if( rvalue > 1 || rsector_nb_zshift==0)
641 rsector_nb_zshift = 1;
642 zshift =
new FLTNBLUT[rsector_nb_zshift];
648 zshift =
new FLTNBLUT[rsector_nb_zshift];
652 Cerr(
"***** iScannerPET::ComputeLUT() -> No data found about modules z-shift in the scanner header file, whereas z-shift is enabled !" << endl);
658 int nb_crystals_cur = 0;
666 int nb_ang_rsector = nb_ang_rsector_lyr[lyr],
667 nb_axl_rsector = nb_axl_rsector_lyr[lyr],
668 nb_trs_mod = nb_trs_mod_lyr[lyr],
669 nb_axl_mod = nb_axl_mod_lyr[lyr],
670 nb_trs_submod = nb_trs_submod_lyr[lyr],
671 nb_axl_submod = nb_axl_submod_lyr[lyr],
672 nb_trs_crystal = nb_trs_crystal_lyr[lyr],
673 nb_axl_crystal = nb_axl_crystal_lyr[lyr];
676 rsector_first_angle = rsector_first_angle_lyr[lyr],
677 angular_span = rsector_angular_span_lyr[lyr],
678 gap_axl_rsector = gap_axl_rsector_lyr[lyr],
679 gap_trs_mod = gap_trs_mod_lyr[lyr],
680 gap_axl_mod = gap_axl_mod_lyr[lyr],
681 gap_trs_submod = gap_trs_submod_lyr[lyr],
682 gap_axl_submod = gap_axl_submod_lyr[lyr],
683 gap_trs_crystal = gap_trs_crystal_lyr[lyr],
684 gap_axl_crystal = gap_axl_crystal_lyr[lyr];
688 FLTNBLUT size_trs_mod = nb_trs_submod*size_trs_submod + (nb_trs_submod-1)*gap_trs_submod;
689 FLTNBLUT size_axl_mod = nb_axl_submod*size_axl_submod + (nb_axl_submod-1)*gap_axl_submod;
690 FLTNBLUT size_trs_rsector = nb_trs_mod*size_trs_mod + (nb_trs_mod-1)*gap_trs_mod;
691 FLTNBLUT size_axl_rsector = nb_axl_mod*size_axl_mod + (nb_axl_mod-1)*gap_axl_mod;
694 int nb_rsectors = nb_ang_rsector * nb_axl_rsector;
695 int nb_mod = nb_axl_mod * nb_trs_mod;
696 int nb_submod = nb_axl_submod * nb_trs_submod;
697 int nb_crystal = nb_axl_crystal * nb_trs_crystal;
700 int nb_crystals = nb_rsectors*nb_mod*nb_submod*nb_crystal + nb_crystals_cur;
703 Cerr(
"***** iScannerPET::ComputeLUT() -> Computed number of crystals computed from the geom file ("<< nb_crystals
704 <<
") > not consistent with the total number of crystals (including potential layers) provided in the geom file ("<<
m_nbCrystals <<
") !" << endl);
718 oMatrix ******crystal_center =
new oMatrix *****[nb_ang_rsector+1];
720 for(
int rsa = 0; rsa < nb_ang_rsector+1 ; rsa++)
722 crystal_center[rsa] =
new oMatrix ****[ nb_axl_rsector ];
724 for (
int i = 0; i<nb_axl_rsector ; i++)
726 crystal_center[rsa][i] =
new oMatrix ***[ nb_mod ];
728 for (
int j = 0; j<nb_mod ; j++)
730 crystal_center[rsa][i][j] =
new oMatrix **[ nb_submod ];
732 for (
int k = 0; k<nb_submod; k++)
734 crystal_center[rsa][i][j][k] =
new oMatrix*[ nb_crystal ];
736 for (
int l = 0; l<nb_crystal; l++)
738 crystal_center[rsa][i][j][k][l] =
new oMatrix(3,1);
750 for(
int i=0; i<nb_ang_rsector; i++)
751 rotation_mtx[i] =
new oMatrix(3,3);
754 FLTNBLUT rsector_first_angle_rad = rsector_first_angle*M_PI/180.;
755 FLTNBLUT angular_span_rad = angular_span*M_PI/180.;
761 for (
int i = 0; i<nb_ang_rsector; i++)
763 FLTNBLUT angle = remainderf(rsector_first_angle_rad + ((
FLTNBLUT)i)*angular_span_rad/((
FLTNBLUT)(nb_ang_rsector)), 2.*M_PI);
777 for (
int r=0; r < nb_axl_rsector ; r++)
780 FLTNBLUT x_start_r = (-dir*size_trs_rsector) / 2.;
781 FLTNBLUT z_start_r = -(nb_axl_rsector*size_axl_rsector + (nb_axl_rsector-1)*gap_axl_rsector) / 2.;
783 z_start_r += r * (size_axl_rsector + gap_axl_rsector);
785 for (
int i=0; i < nb_mod ; i++)
793 x_start_m += dir*(i%nb_trs_mod) * (size_trs_mod + gap_trs_mod);
794 z_start_m += int(i/nb_trs_mod) * (size_axl_mod + gap_axl_mod);
796 for (
int j=0 ; j < nb_submod ; j++)
801 x_start_sm += dir*(j%nb_trs_submod) * (size_trs_submod + gap_trs_submod);
802 z_start_sm += int(j/nb_trs_submod) * (size_axl_submod + gap_axl_submod);
804 for (
int k=0 ; k < nb_crystal ; k++)
825 for (
int rsa=0 ; rsa<nb_ang_rsector ; rsa++)
826 for (
int rs=0 ; rs<nb_axl_rsector ; rs++)
827 for (
int m=0 ; m<nb_mod ; m++)
828 for (
int sm=0 ; sm<nb_submod ; sm++)
829 for (
int c=0 ; c<nb_crystal ; c++)
832 int cryID = rs * nb_axl_mod * nb_axl_submod * nb_axl_crystal * number_crystals_in_ring
833 + int(m/nb_trs_mod) * nb_axl_submod * nb_axl_crystal * number_crystals_in_ring
834 + int(sm/nb_trs_submod) * nb_axl_crystal * number_crystals_in_ring
835 + int(c/nb_trs_crystal) * number_crystals_in_ring
836 + rsa * nb_trs_mod * nb_trs_submod * nb_trs_crystal
837 + m%nb_trs_mod * nb_trs_submod * nb_trs_crystal
838 + sm%nb_trs_submod * nb_trs_crystal
843 rotation_mtx[rsa]->
Multiplication(crystal_center[0][rs][m][sm][c], crystal_center[rsa+1][rs][m][sm][c]);
861 for (
int rsa = 0; rsa<nb_ang_rsector+1 ; rsa++)
862 for (
int i = 0; i<nb_axl_rsector ; i++)
863 for (
int j = 0; j<nb_mod; j++)
864 for (
int k = 0; k<nb_submod; k++)
865 for (
int l = 0; l<nb_crystal; l++)
867 delete crystal_center[rsa][i][j][k][l];
871 for(
int rsa = 0; rsa < nb_ang_rsector+1 ; rsa++)
872 for(
int i = 0; i < nb_axl_rsector ; i++)
873 for (
int j = 0; j<nb_mod; j++)
874 for (
int k = 0; k<nb_submod; k++)
876 delete[] crystal_center[rsa][i][j][k];
879 for(
int rsa = 0; rsa < nb_ang_rsector+1 ; rsa++)
880 for(
int i = 0; i < nb_axl_rsector ; i++)
881 for (
int j = 0; j<nb_mod; j++)
883 delete[] crystal_center[rsa][i][j];
886 for(
int rsa = 0; rsa < nb_ang_rsector+1 ; rsa++)
887 for(
int i = 0; i < nb_axl_rsector ; i++)
889 delete[] crystal_center[rsa][i];
892 for(
int rsa = 0; rsa < nb_ang_rsector+1 ; rsa++)
893 delete[] crystal_center[rsa];
896 for(
int i = 0; i < nb_ang_rsector ; i++)
897 delete rotation_mtx[i];
899 delete[] crystal_center;
900 delete[] rotation_mtx;
912 string path_to_LUT = path_to_geom_file.substr(0, path_to_geom_file.find_last_of(
"."));
913 string path_to_header_LUT = path_to_LUT +
".ghscan";
914 path_to_LUT.append(
".glut");
918 ofstream LUT_file, header_LUT_file;
919 LUT_file.open(path_to_LUT.c_str(), ios::binary | ios::out);
937 header_LUT_file.open(path_to_header_LUT.c_str(), ios::out);
939 string scanner_name = path_to_geom_file.substr(0, path_to_geom_file.find_last_of(
"."));
940 header_LUT_file <<
"scanner name:" <<
" " <<
GetFileFromPath(scanner_name) << endl;
941 header_LUT_file <<
"modality:" <<
" " <<
"PET" << endl;
943 header_LUT_file <<
"scanner radius:" <<
" " << radius_lyr[0];
945 header_LUT_file <<
"," << radius_lyr[lyr] ;
946 header_LUT_file << endl;
948 header_LUT_file <<
"number of elements:" <<
" " << m_nbCrystals << endl;
949 header_LUT_file <<
"number of layers:" <<
" " << m_nbLayers << endl;
952 header_LUT_file <<
","<< mp_nbCrystalsInLayer[lyr] ;
953 header_LUT_file << endl;
957 header_LUT_file <<
","<< mp_sizeCrystalDepth[lyr] ;
958 header_LUT_file << endl;
962 header_LUT_file <<
","<< mp_sizeCrystalTrans[lyr] ;
963 header_LUT_file << endl;
967 header_LUT_file <<
","<< mp_sizeCrystalAxial[lyr] ;
968 header_LUT_file << endl;
971 uint32_t def_dim_trs = 0, def_dim_axl = 0;
972 FLTNB def_FOV_trs = -1., def_FOV_axl = -1;
979 Cerr(
"***** iScannerPET::ComputeLUT() -> Error occurred when trying to read transaxial/axial dimensions and voxel sizes from scanner geom file !" << endl);
983 header_LUT_file <<
"voxels number transaxial:" <<
" " << def_dim_trs << endl;
984 header_LUT_file <<
"voxels number axial:" <<
" " << def_dim_axl << endl;
986 header_LUT_file <<
"field of view transaxial:" <<
" " << def_FOV_trs << endl;
987 header_LUT_file <<
"field of view axial:" <<
" " << def_FOV_axl << endl;
993 header_LUT_file <<
"," << mp_meanDepthOfInteraction[lyr] ;
994 header_LUT_file <<
" #optional (default value : center of crystal ). Input value must correspond to the distance from the crystal surface, or negative value if default" << endl;
998 if(
m_verbose>=2)
Cout(
"iScannerPET::ComputeLUT() -> Header LUT file writing completed" << endl);
1002 delete[] nb_ang_rsector_lyr;
1003 delete[] nb_axl_rsector_lyr;
1004 delete[] nb_trs_mod_lyr;
1005 delete[] nb_axl_mod_lyr;
1006 delete[] nb_trs_submod_lyr;
1007 delete[] nb_axl_submod_lyr;
1008 delete[] nb_trs_crystal_lyr;
1009 delete[] nb_axl_crystal_lyr;
1011 delete[] radius_lyr;
1012 delete[] rsector_angular_span_lyr;
1013 delete[] rsector_first_angle_lyr;
1015 delete[] gap_axl_rsector_lyr;
1016 delete[] gap_trs_mod_lyr;
1017 delete[] gap_axl_mod_lyr;
1018 delete[] gap_trs_submod_lyr;
1019 delete[] gap_axl_submod_lyr;
1020 delete[] gap_trs_crystal_lyr;
1021 delete[] gap_axl_crystal_lyr;
1050 FLTNB ap_Position1[3],
FLTNB ap_Position2[3],
1051 FLTNB ap_Orientation1[3],
FLTNB ap_Orientation2[3],
1059 Cerr(
"***** iScannerPET::GetPositionsAndOrientations() -> Crystal index 1 (" << a_index1 <<
") out of range [0:" <<
m_nbCrystals-1 <<
"] !" << endl);
1064 Cerr(
"***** iScannerPET::GetPositionsAndOrientations() -> Crystal index 2 (" << a_index2 <<
") out of range [0:" <<
m_nbCrystals-1 <<
"] !" << endl);
1087 else if (ap_POI1[2]<0.)
1092 else if (ap_POI1[0]==0. && ap_POI1[1]==0.)
1114 else if (ap_POI2[2]<0.)
1119 else if (ap_POI2[0]==0. && ap_POI2[1]==0.)
1167 FLTNB ap_Position1[3],
FLTNB ap_Position2[3],
1168 FLTNB ap_Orientation1[3],
FLTNB ap_Orientation2[3] )
1175 Cerr(
"***** iScannerPET::GetRdmPositionsAndOrientations() -> Crystal index 1 (" << a_index1 <<
") out of range [0:" <<
m_nbCrystals-1 <<
"] !" << endl);
1180 Cerr(
"***** iScannerPET::GetRdmPositionsAndOrientations() -> Crystal index 2 (" << a_index2 <<
") out of range [0:" <<
m_nbCrystals-1 <<
"] !" << endl);
1187 Cerr(
"***** iScannerPET::GetRdmPositionsAndOrientations() -> Crystal sizes are unknown or equal to 0. Crystal dimensions are mandatory for this function !" << endl);
1204 FLTNB axial1 = (rdm_axl1-0.5) * size_crystalAxial1;
1205 FLTNB trans1 = (rdm_trs1-0.5) * size_crystalTrans1;
1206 FLTNB depth1 = (rdm_depth1-0.5) * size_crystalDepth1;
1221 depth1 = -size_crystalDepth1*0.5 + mDOI1;
1222 depth1 += mDOI1 < size_crystalDepth1/2 ?
1223 (rdm_depth1-0.5)*mDOI1*2 :
1224 (rdm_depth1-0.5)*(size_crystalDepth1-mDOI1)*2 ;
1231 ap_Orientation1[0] = uX;
1232 ap_Orientation1[1] = uY;
1233 ap_Orientation1[2] = uZ;
1247 + depth1 * uX * sqrt(1 - uZ*uZ)
1252 + depth1 * uY * sqrt(1 - uZ*uZ)
1257 + sgnz * depth1 * uZ
1258 - sgnz * axial1 * sqrt(1 - uZ*uZ);
1272 FLTNB axial2 = (rdm_axl2-0.5) * size_crystalAxial2;
1273 FLTNB trans2 = (rdm_trs2-0.5) * size_crystalTrans2;
1274 FLTNB depth2 = (rdm_depth2-0.5) * size_crystalDepth2;
1287 depth2 = -size_crystalDepth2*0.5 + mDOI2;
1288 depth2 += mDOI2 < size_crystalDepth2*0.5 ?
1289 (rdm_depth2-0.5)*mDOI2*2 :
1290 (rdm_depth2-0.5)*(size_crystalDepth2-mDOI2)*2 ;
1297 ap_Orientation2[0] = uX;
1298 ap_Orientation2[1] = uY;
1299 ap_Orientation2[2] = uZ;
1312 + depth2 * uX * sqrt(1 - uZ*uZ)
1317 + depth2 * uY * sqrt(1 - uZ*uZ)
1322 + sgnz * depth2 * uZ
1323 - sgnz * axial2 * sqrt(1 - uZ*uZ);
1389 FLTNB ap_CornerInf1[3],
FLTNB ap_CornerSup1[3],
1390 FLTNB ap_CornerInf2[3],
FLTNB ap_CornerSup2[3])
1396 Cerr(
"***** iScannerPET::GetTwoCorners() -> Crystal index out of range !" << endl);
1403 Cerr(
"***** iScannerPET::GetRdmPositionsAndOrientations() -> Crystal sizes are unknown or equal to 0. Crystal dimensions are mandatory for this function !" << endl);
1407 Cerr(
"***** iScannerPET::GetTwoCorners() -> Not implemented yet !" << endl);
1417 FLTNB ap_pos_line_point1[3],
FLTNB ap_pos_line_point2[3],
1418 FLTNB ap_pos_point1_x[4],
FLTNB ap_pos_point1_y[4],
FLTNB ap_pos_point1_z[4],
1419 FLTNB ap_pos_point2_x[4],
FLTNB ap_pos_point2_y[4],
FLTNB ap_pos_point2_z[4]
1427 Cerr(
"***** iScannerPET::GetEdgesCenterPositions() -> Crystal indices out of range !" << endl);
1440 ap_pos_point1_x[ 0 ] = ap_pos_line_point1[ 0 ] - half_crystal_trans_1 *
mp_crystalOrientationY[ a_index1 ];
1441 ap_pos_point1_x[ 1 ] = ap_pos_line_point1[ 0 ] + half_crystal_trans_1 * mp_crystalOrientationY[ a_index1 ];
1442 ap_pos_point1_x[ 2 ] = ap_pos_line_point1[ 0 ];
1443 ap_pos_point1_x[ 3 ] = ap_pos_line_point1[ 0 ];
1446 ap_pos_point1_y[ 0 ] = ap_pos_line_point1[ 1 ] + half_crystal_trans_1 *
mp_crystalOrientationX[ a_index1 ];
1447 ap_pos_point1_y[ 1 ] = ap_pos_line_point1[ 1 ] - half_crystal_trans_1 * mp_crystalOrientationX[ a_index1 ];
1448 ap_pos_point1_y[ 2 ] = ap_pos_line_point1[ 1 ];
1449 ap_pos_point1_y[ 3 ] = ap_pos_line_point1[ 1 ];
1452 ap_pos_point1_z[ 0 ] = ap_pos_line_point1[ 2 ];
1453 ap_pos_point1_z[ 1 ] = ap_pos_line_point1[ 2 ];
1454 ap_pos_point1_z[ 2 ] = ap_pos_line_point1[ 2 ] - half_crystal_axial_1;
1455 ap_pos_point1_z[ 3 ] = ap_pos_line_point1[ 2 ] + half_crystal_axial_1;
1460 ap_pos_point2_x[ 0 ] = ap_pos_line_point2[ 0 ] + half_crystal_trans_2 * mp_crystalOrientationY[ a_index2 ];
1461 ap_pos_point2_x[ 1 ] = ap_pos_line_point2[ 0 ] - half_crystal_trans_2 * mp_crystalOrientationY[ a_index2 ];
1462 ap_pos_point2_x[ 2 ] = ap_pos_line_point2[ 0 ];
1463 ap_pos_point2_x[ 3 ] = ap_pos_line_point2[ 0 ];
1466 ap_pos_point2_y[ 0 ] = ap_pos_line_point2[ 1 ] - half_crystal_trans_2 * mp_crystalOrientationX[ a_index2 ];
1467 ap_pos_point2_y[ 1 ] = ap_pos_line_point2[ 1 ] + half_crystal_trans_2 * mp_crystalOrientationX[ a_index2 ];
1468 ap_pos_point2_y[ 2 ] = ap_pos_line_point2[ 1 ];
1469 ap_pos_point2_y[ 3 ] = ap_pos_line_point2[ 1 ];
1472 ap_pos_point2_z[ 0 ] = ap_pos_line_point2[ 2 ];
1473 ap_pos_point2_z[ 1 ] = ap_pos_line_point2[ 2 ];
1474 ap_pos_point2_z[ 2 ] = ap_pos_line_point2[ 2 ] - half_crystal_axial_2;
1475 ap_pos_point2_z[ 3 ] = ap_pos_line_point2[ 2 ] + half_crystal_axial_2;
1498 while (a_idx >= sum_crystals)
1536 abs_angle = (abs_angle>1.) ? 1 : abs_angle;
1537 abs_angle = (abs_angle<-1.) ? -1 : abs_angle;
1539 FLTNB angle_diff = acos(abs_angle);
1574 Cerr(
"***** iScannerPET::GetGeometricInfoFromDataFile() -> Error while reading max number of ring difference in the header data file '" << endl);
1601 Cerr(
"***** iScannerPET::PROJ_GetPETSpecificParameters() -> Parameters have not been checked !" << endl);
1621 cout <<
"This scanner class is dedicated to the description of PET systems." << endl;
int GetPositionWithRandomDepth(int a_index1, int a_index2, FLTNB ap_Position1[3], FLTNB ap_Position2[3])
Get the positions and orientations of scanner elements from their indices, with a random depth...
#define VERBOSE_DEBUG_MAX
int CheckParameters()
Check if all parameters have been correctly initialized.
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
static sRandomNumberGenerator * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
#define VERBOSE_DEBUG_EVENT
FLTNB * mp_sizeCrystalAxial
int Instantiate(bool a_scannerFileIsLUT)
Get mandatory informations from the scanner file and allocate memory for the member variables...
int IsAvailableLOR(int a_elt1, int a_elt2)
Check if the LOR formed by the crystalf whose indices are passed in parameters is available according...
FLTNB * mp_crystalOrientationX
int Initialize()
Check general initialization and set several parameters to their default value.
int GetTwoCorners(int a_index1, int a_index2, FLTNB ap_CornerInf1[3], FLTNB ap_CornerSup1[3], FLTNB ap_CornerInf2[3], FLTNB ap_CornerSup2[3])
Get the cartesian coordinaters of the two opposite corners of a scanner element.
FLTNB m_minAngleDifference
FLTNB * mp_crystalOrientationY
oMatrix * mp_positionMatrix_out
FLTNB m_defaultBedDisplacementInMm
FLTNB * mp_meanDepthOfInteraction
string GetPathToScannerFile()
int GetRdmPositionsAndOrientations(int a_index1, int a_index2, FLTNB ap_Position1[3], FLTNB ap_Position2[3], FLTNB ap_Orientation1[3], FLTNB ap_Orientation2[3])
Get random positions of the scanner elements and their orientations from their indices.
FLTNB * mp_crystalOrientationZ
string GetFileFromPath(const string &a_pathToFile)
Simply return the file from a path string passed in parameter.
Declaration of class iScannerPET.
int GetEdgesCenterPositions(int a_index1, int a_index2, FLTNB ap_pos_line_point1[3], FLTNB ap_pos_line_point2[3], FLTNB ap_pos_point1_x[4], FLTNB ap_pos_point1_y[4], FLTNB ap_pos_point1_z[4], FLTNB ap_pos_point2_x[4], FLTNB ap_pos_point2_y[4], FLTNB ap_pos_point2_z[4])
Implementation of the pure virtual function from vScanner. Get the cartesian coordinaters of the ce...
FLTNB * mp_crystalCentralPositionZ
oMatrix * mp_rotationMatrix
int GetGeometricInfoFromDataFile(string a_pathToDataFilename)
Retrieve PET geometric informations from the datafile.
#define VERBOSE_DEBUG_LIGHT
virtual int SetRotDirection(string a_rotDirection)
Set rotation direction of the system.
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...
Singleton class that Instantiate and initialize the scanner object.
int GetLayer(int a_idx)
Get the layer from which the 'a_index' crystal belongs to.
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)
Get the central positions and orientations of the scanner elements from their indices.
Declaration of class sScannerManager.
bool SaveLUTFlag()
Get flag indicating a LUT generated by a geom file should be written on disk or not.
FLTNB * mp_sizeCrystalDepth
int PROJ_GetPETSpecificParameters(FLTNB *ap_maxAxialDiffmm)
Set pointers passed in argument with the related PET specific variables This function is used to reco...
HPFLTNB GenerateRdmNber()
Generate a random number for the thread which index is recovered from the OpenMP function.
bool m_allParametersChecked
#define KEYWORD_MANDATORY
FLTNB * mp_crystalCentralPositionY
Singleton class that generate a thread-safe random generator number for openMP As singleton...
int LoadLUT()
Load a precomputed scanner LUT.
iScannerPET()
iScannerPET constructor. Initialize the member variables to their default values. ...
Declaration of class sOutputManager.
void ShowHelp()
Display help.
oMatrix * mp_positionMatrix_ref
Structure designed for basic matrices operations.
FLTNB * mp_crystalCentralPositionX
FLTNB * mp_sizeCrystalTrans
#define DEBUG_VERBOSE(IGNORED1, IGNORED2)
~iScannerPET()
iScannerPET destructor.
int BuildLUT(bool a_scannerFileIsLUT)
Call the functions to generate the LUT or read the user-made LUT depending on the user choice...
int Multiplication(oMatrix *ap_Mtx, oMatrix *ap_MtxResult)
Multiply the member matrix with the matrix provided in 1st parameter Return the result in the matric ...
void DescribeSpecific()
Implementation of the pure virtual eponym function that simply prints info about the scanner...
int SetMatriceElt(uint16_t l, uint16_t c, HPFLTNB a_val)
Set the matrix element corresponding to the argument indices with the provided value.
Generic class for scanner objects.
int * mp_nbCrystalsInLayer
#define KEYWORD_OPTIONAL_ERROR
bool FLTNBIsEqual(FLTNB a, FLTNB b, FLTNB a_eps)
Comparison of FLTNB numbers.
int ComputeLUT()
Compute the LUT of the scanner from a generic (.geom) file.