8 #include "iScannerCT.hh" 9 #include "sOutputManager.hh" 10 #include "sScannerManager.hh" 83 Cout(
"iScannerCT::DescribeSpecific() -> Here is some specific content of the CT scanner" << endl);
89 Cout(
" --> Projection angles: " << endl);
95 for (
int p=0 ; p<10 ; p++)
116 Cout(
" --> Total number of transaxial pixels as defined in the system file: " <<
m_nbPixelsTrans << endl);
118 Cout(
" --> Gap size between each transaxial pixe as defined in the system file: " <<
m_gapSizeTrans << endl);
119 Cout(
" --> Total number of axial pixels as defined in the system file: " <<
m_nbPixelsAxial << endl);
121 Cout(
" --> Gap size between each axial pixel as defined in the system file: " <<
m_gapSizeAxial << endl);
123 Cout(
" --> Width of the source, along the direction tangential to the scanner radius: " <<
m_spotSizeWidth << endl);
124 Cout(
" --> Depth of the source, along the direction of the scanner radius: " <<
m_spotSizeDepth << endl);
139 if (
m_verbose>=
VERBOSE_NORMAL)
Cout(
"iScannerCT::Instantiate() -> Create scanner structure and read parameters from configuration file" << endl);
147 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the transaxial number of pixels !" << endl);
152 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the transaxial pixel size !" << endl);
157 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the axial number of pixels !" << endl);
162 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the axial pixel size !" << endl);
167 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read detector depth !" << endl);
172 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read detector to COR distance as \"detector radius\" !" << endl);
177 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read source to COR distance as \"source radius\" !" << endl);
182 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the spot size width !" << endl);
187 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the spot size height !" << endl);
195 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the multiple bed displacement in the scanner header file !" << endl);
230 if (!a_scannerFileIsLUT)
234 Cerr(
"***** iScannerCT::BuildLUT() -> A problem occurred while generating scanner LUT !" << endl);
242 Cerr(
"***** iScannerCT::BuildLUT() -> A problem occurred while loading scanner LUT !" << endl);
263 Cerr(
"***** iScannerCT::CheckParameters()-> Number of crystals has not been initialized !" <<endl);
268 Cerr(
"***** iScannerCT::CheckParameters()-> Number of projection angles has not been initialized !" <<endl);
273 Cerr(
"***** iScannerCT::CheckParameters()-> Number of transaxial/axial pixels have not correctly been initialized ! (should be >0)" <<endl);
278 Cerr(
"***** iScannerCT::CheckParameters()-> Transaxial/axial pixel sizes have not correctly been initialized ! (should be >0)" <<endl);
283 Cerr(
"***** iScannerCT::CheckParameters()-> Transaxial/axial pixel gap sizes have not correctly been initialized ! (should be >0)" <<endl);
288 Cerr(
"***** iScannerCT::CheckParameters()-> Crystal depth has not correctly been initialized ! (should be >0)" <<endl);
293 Cerr(
"***** iScannerCT::CheckParameters()-> Projection angles have not correctly been initialized !" <<endl);
298 Cerr(
"***** iScannerCT::CheckParameters()-> Distance between center of rotation and detector surface has not correctly been initialized !" <<endl);
303 Cerr(
"***** iScannerCT::CheckParameters()-> Distance between center of rotation and source surface has not correctly been initialized !" <<endl);
310 Cerr(
"***** iScannerCT::CheckParameters()-> LUT elements (crystal central positions) have not correctly been initialized !" <<endl);
317 Cerr(
"***** iScannerCT::CheckParameters()-> LUT elements (crystal orientations) have not correctly been initialized !" <<endl);
324 Cerr(
"***** iScannerCT::CheckParameters()-> LUT elements (crystal focal positions) have not correctly been initialized !" <<endl);
348 Cerr(
"***** iScannerCT::Initialize() -> Parameters have not been checked !" << endl);
366 Cerr(
"iScannerCT::LoadLUT() -> Not yet implemented !" << endl);
385 omp_set_num_threads(nb_threads);
396 crystal_center_ref[c] =
new oMatrix(3,1);
402 for (
int th=0; th<nb_threads; th++)
404 crystal_center_out[th] =
new oMatrix(3,1);
405 source_center_out[th] =
new oMatrix(3,1);
412 rotation_mtx[i] =
new oMatrix(3,3);
428 Cerr(
"***** iScannerCT::ComputeLUT() -> An error occurred while trying to read the transaxial gap size !" << endl);
434 Cerr(
"***** iScannerCT::ComputeLUT() -> An error occurred while trying to read the axial gap size !" << endl);
447 crystal_center_ref[ii + m_nbPixelsTrans * jj]->
SetMatriceElt(0,0,Xcryst);
450 crystal_center_ref[ii + m_nbPixelsTrans * jj]->
SetMatriceElt(2,0,Zcryst);
467 #pragma omp parallel for private(a) schedule(guided) 473 th = omp_get_thread_num();
479 int cryID = a*m_nbPixels + c;
482 rotation_mtx[a]->
Multiplication(crystal_center_ref[c], crystal_center_out[th]);
493 rotation_mtx[a]->
Multiplication(source_center_ref, source_center_out[th]);
501 delete rotation_mtx[i];
502 delete[] rotation_mtx;
504 delete crystal_center_ref[c];
505 delete[] crystal_center_ref;
506 delete source_center_ref;
507 for (
int th=0; th<nb_threads; th++)
509 delete crystal_center_out[th];
510 delete source_center_out[th];
512 delete[] crystal_center_out;
513 delete[] source_center_out;
527 FLTNB ap_Orientation1[3],
FLTNB ap_Orientation2[3],
535 if (a_index1<0 || a_index1>=m_nbOfProjections)
537 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> Projection index (" << a_index1 <<
") out of range [0:" << m_nbOfProjections-1 <<
"] !" << endl);
542 if (a_index2<0 || a_index2>=m_nbPixels)
544 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> Pixel index (" << a_index2 <<
") out of range [0:" << m_nbPixels-1 <<
"] !" << endl);
549 int index = a_index1*m_nbPixels + a_index2;
568 else if (ap_POI2[2]<0.)
570 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> POI management not implemented yet for CT !" << endl);
574 else if (ap_POI2[0]==0. && ap_POI2[1]==0.)
576 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> POI management not implemented yet for CT !" << endl);
582 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> POI management not implemented yet for CT !" << endl);
604 FLTNB ap_Orientation1[3],
FLTNB ap_Orientation2[3] )
608 Cerr(
"***** iScannerCT::GetRdmPositionsAndOrientations() -> Not yet implemented for CT !" << endl);
622 Cerr(
"***** iScannerCT::GetPositionWithRandomDepth() -> This function was implemented for PET testing purpose. Not implemented for CT !" << endl);
632 FLTNB ap_CornerInf1[3],
FLTNB ap_CornerSup1[3],
633 FLTNB ap_CornerInf2[3],
FLTNB ap_CornerSup2[3])
636 Cerr(
"***** iScannerCT::GetTwoCorners() -> Not implemented yet !" << endl);
646 FLTNB ap_pos_line_point1[3],
FLTNB ap_pos_line_point2[3],
647 FLTNB ap_pos_point1_x[4],
FLTNB ap_pos_point1_y[4],
FLTNB ap_pos_point1_z[4],
648 FLTNB ap_pos_point2_x[4],
FLTNB ap_pos_point2_y[4],
FLTNB ap_pos_point2_z[4]
653 if ( a_index1<0 || a_index1>=m_nbOfProjections
654 || a_index2<0 || a_index2>=m_nbPixels )
656 Cerr(
"***** iScannerCT::GetPositionEdge() -> Crystal index or projection index out of range !" << endl);
661 int global_index = m_nbPixels * a_index1 + a_index2;
672 ap_pos_point1_x[ 0 ] = ap_pos_line_point1[ 0 ] - half_spot_size_trans * -
mp_crystalOrientationY[ global_index ];
673 ap_pos_point1_x[ 1 ] = ap_pos_line_point1[ 0 ] + half_spot_size_trans * -mp_crystalOrientationY[ global_index ];
674 ap_pos_point1_x[ 2 ] = ap_pos_line_point1[ 0 ];
675 ap_pos_point1_x[ 3 ] = ap_pos_line_point1[ 0 ];
678 ap_pos_point1_y[ 0 ] = ap_pos_line_point1[ 1 ] - half_spot_size_trans *
mp_crystalOrientationX[ global_index ];
679 ap_pos_point1_y[ 1 ] = ap_pos_line_point1[ 1 ] + half_spot_size_trans * mp_crystalOrientationX[ global_index ];
680 ap_pos_point1_y[ 2 ] = ap_pos_line_point1[ 1 ];
681 ap_pos_point1_y[ 3 ] = ap_pos_line_point1[ 1 ];
684 ap_pos_point1_z[ 0 ] = ap_pos_line_point1[ 2 ];
685 ap_pos_point1_z[ 1 ] = ap_pos_line_point1[ 2 ];
686 ap_pos_point1_z[ 2 ] = ap_pos_line_point1[ 2 ] - half_spot_size_axial;
687 ap_pos_point1_z[ 3 ] = ap_pos_line_point1[ 2 ] + half_spot_size_axial;
692 ap_pos_point2_x[ 0 ] = ap_pos_line_point2[ 0 ] + half_pixel_trans * mp_crystalOrientationY[ global_index ];
693 ap_pos_point2_x[ 1 ] = ap_pos_line_point2[ 0 ] - half_pixel_trans * mp_crystalOrientationY[ global_index ];
694 ap_pos_point2_x[ 2 ] = ap_pos_line_point2[ 0 ];
695 ap_pos_point2_x[ 3 ] = ap_pos_line_point2[ 0 ];
698 ap_pos_point2_y[ 0 ] = ap_pos_line_point2[ 1 ] + half_pixel_trans * -mp_crystalOrientationX[ global_index ];
699 ap_pos_point2_y[ 1 ] = ap_pos_line_point2[ 1 ] - half_pixel_trans * -mp_crystalOrientationX[ global_index ];
700 ap_pos_point2_y[ 2 ] = ap_pos_line_point2[ 1 ];
701 ap_pos_point2_y[ 3 ] = ap_pos_line_point2[ 1 ];
704 ap_pos_point2_z[ 0 ] = ap_pos_line_point2[ 2 ];
705 ap_pos_point2_z[ 1 ] = ap_pos_line_point2[ 2 ];
706 ap_pos_point2_z[ 2 ] = ap_pos_line_point2[ 2 ] - half_pixel_axial;
707 ap_pos_point2_z[ 3 ] = ap_pos_line_point2[ 2 ] + half_pixel_axial;
731 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error while reading number of projections in the header data file " << endl);
737 FLTNB first_and_last_angles[2] = {-1.,-1.};
746 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error while reading Angle mandatory field in the header data file '" << endl);
750 string rotation_direction =
"";
753 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error while reading head rotation orientation in the header data file " << endl);
758 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() ->Error occurred while trying to initialize scanner rotation orientation " << endl);
768 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error while reading Angles field in the header data file !'" << endl);
774 (first_and_last_angles[0] <0 || first_and_last_angles[1] <0) )
776 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> No information on projection angles provided in the datafile !'" << endl);
777 Cerr(
" This information should be provided using either the 'Angles' tag, or both 'First angles', 'Last angles' tags !'" << endl);
783 while (first_and_last_angles[0]>=360.) first_and_last_angles[0] -= 360.;
784 while (first_and_last_angles[0]<0.) first_and_last_angles[0] += 360.;
785 while (first_and_last_angles[1]>=360.) first_and_last_angles[1] -= 360.;
786 while (first_and_last_angles[1]<0.) first_and_last_angles[1] += 360.;
790 FLTNB angle_increment = dir*(first_and_last_angles[1] - first_and_last_angles[0]);
791 while (angle_increment>=360.) angle_increment -= 360.;
792 while (angle_increment<0.) angle_increment += 360.;
793 angle_increment /= ((
FLTNB)(m_nbOfProjections-1));
797 angles[a] = first_and_last_angles[0] + dir * angle_increment * ((
FLTNB)a);
798 while (angles[a]>=360.) angles[a] -= 360.;
799 while (angles[a]<0.) angles[a] += 360.;
802 angles[m_nbOfProjections-1] = first_and_last_angles[1];
822 int* ap_detectorRotDirection)
826 if (
m_verbose>=
VERBOSE_DETAIL)
Cout(
"iScannerCT::GetCTSpecificParameters() -> Copy pointers inside scanner to the datafile to get information" << endl
827 <<
" depending on the datafile inside the scanner" << endl);
831 Cerr(
"***** iScannerCT::GetCTSpecificParameters() -> Parameters have not been checked !" << endl);
850 cout <<
"This scanner class is dedicated to the description of CT systems." << endl;
iScannerCT()
iScannerCT constructor. Initialize the member variables to their default values.
oImageDimensionsAndQuantification * mp_ID
int LoadLUT()
Load a precomputed scanner LUT.
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
int GetPositionWithRandomDepth(int a_index1, int a_index2, FLTNB ap_Position1[3], FLTNB ap_Position2[3])
FLTNB m_CORtoDetectorDistance
FLTNB * mp_crystalCentralPositionX
int ComputeLUT()
Computes the LUT of the scanner from a generic (.geom) file.
int GetRdmPositionsAndOrientations(int a_index1, int a_index2, FLTNB ap_Position1[3], FLTNB ap_Position2[3], FLTNB ap_Orientation1[3], FLTNB ap_Orientation2[3])
FLTNB m_defaultBedDisplacementInMm
int Initialize()
Check general initialization and set several parameters to their default value.
FLTNB * mp_crystalCentralPositionY
string GetPathToScannerFile()
int GetGeometricInfoFromDataFile(string a_pathToDF)
uint16_t m_nbOfProjections
FLTNB * mp_crystalOrientationY
int BuildLUT(bool a_scannerFileIsLUT)
FLTNB * mp_sourcePositionZ
FLTNB m_CORtoSourceDistance
virtual int SetRotDirection(string a_rotDirection)
int CheckParameters()
Check that all parameters have been correctly initialized.
#define DEBUG_VERBOSE(IGNORED1, IGNORED2)
int GetNbThreadsMax()
Get the maximum between the number of threads used for projections and image operations.
Singleton class that Instantiate and initialize the scanner object.
FLTNB * mp_crystalCentralPositionZ
void DescribeSpecific()
Implementation of the pure virtual eponym function that simply prints info about the scanner...
FLTNB * mp_sourcePositionY
FLTNB * mp_crystalOrientationX
HPFLTNB GetMatriceElt(uint16_t l, uint16_t c)
bool m_allParametersChecked
#define KEYWORD_MANDATORY
FLTNB * mp_crystalOrientationZ
int GetTwoCorners(int a_index1, int a_index2, FLTNB ap_CornerInf1[3], FLTNB ap_CornerSup1[3], FLTNB ap_CornerInf2[3], FLTNB ap_CornerSup2[3])
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])
~iScannerCT()
iScannerCT destructor.
FLTNB * mp_sourcePositionX
Structure designed for basic matrices operations.
FLTNB * mp_projectionAngles
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)
#define VERBOSE_DEBUG_LIGHT
int Multiplication(oMatrix *ap_Mtx, oMatrix *ap_MtxResult)
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 GetCTSpecificParameters(uint16_t *ap_nbOfProjections, FLTNB *&ap_angles, int *ap_detectorRotDirection)
int SetMatriceElt(uint16_t l, uint16_t c, HPFLTNB a_val)
int Instantiate(bool a_scannerFileIsLUT)
Generic class for scanner objects.
void ShowHelp()
Display help.
#define VERBOSE_DEBUG_EVENT