106 Cout(
"iScannerCT::DescribeSpecific() -> Here is some specific content of the CT scanner" << endl);
112 Cout(
" --> Projection angles: " << endl);
118 for (
int p=0 ; p<10 ; p++)
139 Cout(
" --> Total number of transaxial pixels as defined in the system file: " <<
m_nbPixelsTrans << endl);
141 Cout(
" --> Gap size between each transaxial pixe as defined in the system file: " <<
m_gapSizeTrans << endl);
142 Cout(
" --> Total number of axial pixels as defined in the system file: " <<
m_nbPixelsAxial << endl);
144 Cout(
" --> Gap size between each axial pixel as defined in the system file: " <<
m_gapSizeAxial << endl);
146 Cout(
" --> Width of the source, along the direction tangential to the scanner radius: " <<
m_spotSizeWidth << endl);
147 Cout(
" --> Depth of the source, along the direction of the scanner radius: " <<
m_spotSizeDepth << endl);
162 if (
m_verbose>=
VERBOSE_NORMAL)
Cout(
"iScannerCT::Instantiate() -> Create scanner structure and read parameters from configuration file" << endl);
170 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the transaxial number of pixels !" << endl);
175 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the transaxial pixel size !" << endl);
180 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the axial number of pixels !" << endl);
185 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the axial pixel size !" << endl);
190 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read detector depth !" << endl);
195 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read detector to COR distance as \"detector radius\" !" << endl);
200 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read source to COR distance as \"source radius\" !" << endl);
205 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the spot size width !" << endl);
210 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the spot size height !" << endl);
218 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the multiple bed displacement in the scanner header file !" << endl);
253 if (!a_scannerFileIsLUT)
257 Cerr(
"***** iScannerCT::BuildLUT() -> A problem occured while generating scanner LUT !" << endl);
265 Cerr(
"***** iScannerCT::BuildLUT() -> A problem occured while loading scanner LUT !" << endl);
286 Cerr(
"***** iScannerCT::CheckParameters()-> Number of crystals has not been initialized !" <<endl);
291 Cerr(
"***** iScannerCT::CheckParameters()-> Number of projection angles has not been initialized !" <<endl);
296 Cerr(
"***** iScannerCT::CheckParameters()-> Number of transaxial/axial pixels have not correctly been initialized ! (should be >0)" <<endl);
301 Cerr(
"***** iScannerCT::CheckParameters()-> Transaxial/axial pixel sizes have not correctly been initialized ! (should be >0)" <<endl);
306 Cerr(
"***** iScannerCT::CheckParameters()-> Transaxial/axial pixel gap sizes have not correctly been initialized ! (should be >0)" <<endl);
311 Cerr(
"***** iScannerCT::CheckParameters()-> Crystal depth has not correctly been initialized ! (should be >0)" <<endl);
316 Cerr(
"***** iScannerCT::CheckParameters()-> Projection angles have not correctly been initialized !" <<endl);
321 Cerr(
"***** iScannerCT::CheckParameters()-> Distance between center of rotation and detector surface has not correctly been initialized !" <<endl);
326 Cerr(
"***** iScannerCT::CheckParameters()-> Distance between center of rotation and source surface has not correctly been initialized !" <<endl);
333 Cerr(
"***** iScannerCT::CheckParameters()-> LUT elements (crystal central positions) have not correctly been initialized !" <<endl);
340 Cerr(
"***** iScannerCT::CheckParameters()-> LUT elements (crystal orientations) have not correctly been initialized !" <<endl);
347 Cerr(
"***** iScannerCT::CheckParameters()-> LUT elements (crystal focal positions) have not correctly been initialized !" <<endl);
371 Cerr(
"***** iScannerCT::Initialize() -> Parameters have not been checked !" << endl);
389 Cerr(
"iScannerCT::LoadLUT() -> Not yet implemented !" << endl);
408 omp_set_num_threads(nb_threads);
419 crystal_center_ref[c] =
new oMatrix(3,1);
425 for (
int th=0; th<nb_threads; th++)
427 crystal_center_out[th] =
new oMatrix(3,1);
428 source_center_out[th] =
new oMatrix(3,1);
435 rotation_mtx[i] =
new oMatrix(3,3);
451 Cerr(
"***** iScannerCT::ComputeLUT() -> An error occurred while trying to read the transaxial gap size !" << endl);
457 Cerr(
"***** iScannerCT::ComputeLUT() -> An error occurred while trying to read the axial gap size !" << endl);
470 crystal_center_ref[ii + m_nbPixelsTrans * jj]->
SetMatriceElt(0,0,Xcryst);
473 crystal_center_ref[ii + m_nbPixelsTrans * jj]->
SetMatriceElt(2,0,Zcryst);
490 #pragma omp parallel for private(a) schedule(guided)
496 th = omp_get_thread_num();
502 int cryID = a*m_nbPixels + c;
505 rotation_mtx[a]->
Multiplication(crystal_center_ref[c], crystal_center_out[th]);
516 rotation_mtx[a]->
Multiplication(source_center_ref, source_center_out[th]);
524 delete rotation_mtx[i];
525 delete[] rotation_mtx;
527 delete crystal_center_ref[c];
528 delete[] crystal_center_ref;
529 delete source_center_ref;
530 for (
int th=0; th<nb_threads; th++)
532 delete crystal_center_out[th];
533 delete source_center_out[th];
535 delete[] crystal_center_out;
536 delete[] source_center_out;
550 FLTNB ap_Orientation1[3],
FLTNB ap_Orientation2[3],
560 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> Projection index (" << a_index1 <<
") out of range [0:" <<
m_nbOfProjections-1 <<
"] !" << endl);
567 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> Pixel index (" << a_index2 <<
") out of range [0:" <<
m_nbPixels-1 <<
"] !" << endl);
591 else if (ap_POI2[2]<0.)
593 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> POI management not implemented yet for CT !" << endl);
597 else if (ap_POI2[0]==0. && ap_POI2[1]==0.)
599 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> POI management not implemented yet for CT !" << endl);
605 Cerr(
"***** iScannerCT::GetPositionsAndOrientations() -> POI management not implemented yet for CT !" << endl);
627 FLTNB ap_Orientation1[3],
FLTNB ap_Orientation2[3] )
631 Cerr(
"***** iScannerCT::GetRdmPositionsAndOrientations() -> Not yet implemented for CT !" << endl);
645 Cerr(
"***** iScannerCT::GetPositionWithRandomDepth() -> This function was implemented for PET testing purpose. Not implemented for CT !" << endl);
655 FLTNB ap_CornerInf1[3],
FLTNB ap_CornerSup1[3],
656 FLTNB ap_CornerInf2[3],
FLTNB ap_CornerSup2[3])
659 Cerr(
"***** iScannerCT::GetTwoCorners() -> Not implemented yet !" << endl);
669 FLTNB ap_pos_line_point1[3],
FLTNB ap_pos_line_point2[3],
670 FLTNB ap_pos_point1_x[4],
FLTNB ap_pos_point1_y[4],
FLTNB ap_pos_point1_z[4],
671 FLTNB ap_pos_point2_x[4],
FLTNB ap_pos_point2_y[4],
FLTNB ap_pos_point2_z[4]
679 Cerr(
"***** iScannerCT::GetPositionEdge() -> Crystal index or projection index out of range !" << endl);
684 int global_index =
m_nbPixels * a_index1 + a_index2;
695 ap_pos_point1_x[ 0 ] = ap_pos_line_point1[ 0 ] - half_spot_size_trans * -
mp_crystalOrientationY[ global_index ];
696 ap_pos_point1_x[ 1 ] = ap_pos_line_point1[ 0 ] + half_spot_size_trans * -mp_crystalOrientationY[ global_index ];
697 ap_pos_point1_x[ 2 ] = ap_pos_line_point1[ 0 ];
698 ap_pos_point1_x[ 3 ] = ap_pos_line_point1[ 0 ];
701 ap_pos_point1_y[ 0 ] = ap_pos_line_point1[ 1 ] - half_spot_size_trans *
mp_crystalOrientationX[ global_index ];
702 ap_pos_point1_y[ 1 ] = ap_pos_line_point1[ 1 ] + half_spot_size_trans * mp_crystalOrientationX[ global_index ];
703 ap_pos_point1_y[ 2 ] = ap_pos_line_point1[ 1 ];
704 ap_pos_point1_y[ 3 ] = ap_pos_line_point1[ 1 ];
707 ap_pos_point1_z[ 0 ] = ap_pos_line_point1[ 2 ];
708 ap_pos_point1_z[ 1 ] = ap_pos_line_point1[ 2 ];
709 ap_pos_point1_z[ 2 ] = ap_pos_line_point1[ 2 ] - half_spot_size_axial;
710 ap_pos_point1_z[ 3 ] = ap_pos_line_point1[ 2 ] + half_spot_size_axial;
715 ap_pos_point2_x[ 0 ] = ap_pos_line_point2[ 0 ] + half_pixel_trans * mp_crystalOrientationY[ global_index ];
716 ap_pos_point2_x[ 1 ] = ap_pos_line_point2[ 0 ] - half_pixel_trans * mp_crystalOrientationY[ global_index ];
717 ap_pos_point2_x[ 2 ] = ap_pos_line_point2[ 0 ];
718 ap_pos_point2_x[ 3 ] = ap_pos_line_point2[ 0 ];
721 ap_pos_point2_y[ 0 ] = ap_pos_line_point2[ 1 ] + half_pixel_trans * -mp_crystalOrientationX[ global_index ];
722 ap_pos_point2_y[ 1 ] = ap_pos_line_point2[ 1 ] - half_pixel_trans * -mp_crystalOrientationX[ global_index ];
723 ap_pos_point2_y[ 2 ] = ap_pos_line_point2[ 1 ];
724 ap_pos_point2_y[ 3 ] = ap_pos_line_point2[ 1 ];
727 ap_pos_point2_z[ 0 ] = ap_pos_line_point2[ 2 ];
728 ap_pos_point2_z[ 1 ] = ap_pos_line_point2[ 2 ];
729 ap_pos_point2_z[ 2 ] = ap_pos_line_point2[ 2 ] - half_pixel_axial;
730 ap_pos_point2_z[ 3 ] = ap_pos_line_point2[ 2 ] + half_pixel_axial;
754 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error while reading number of projections in the header data file " << endl);
760 FLTNB first_and_last_angles[2] = {-1.,-1.};
769 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error while reading Angle mandatory field in the header data file '" << endl);
773 string rotation_direction =
"";
776 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error while reading head rotation orientation in the header data file " << endl);
781 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error occured while trying to initialize scanner rotation orientation " << endl);
791 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> Error while reading Angles field in the header data file !'" << endl);
797 (first_and_last_angles[0] <0 || first_and_last_angles[1] <0) )
799 Cerr(
"***** iScannerCT::GetGeometricInfoFromDataFile() -> No information on projection angles provided in the datafile !'" << endl);
800 Cerr(
" This information should be provided using either the 'Angles' tag, or both 'First angles', 'Last angles' tags !'" << endl);
806 while (first_and_last_angles[0]>=360.) first_and_last_angles[0] -= 360.;
807 while (first_and_last_angles[0]<0.) first_and_last_angles[0] += 360.;
808 while (first_and_last_angles[1]>=360.) first_and_last_angles[1] -= 360.;
809 while (first_and_last_angles[1]<0.) first_and_last_angles[1] += 360.;
813 FLTNB angle_increment = dir*(first_and_last_angles[1] - first_and_last_angles[0]);
814 while (angle_increment>=360.) angle_increment -= 360.;
815 while (angle_increment<0.) angle_increment += 360.;
820 angles[a] = first_and_last_angles[0] + dir * angle_increment * ((
FLTNB)a);
821 while (angles[a]>=360.) angles[a] -= 360.;
822 while (angles[a]<0.) angles[a] += 360.;
825 angles[m_nbOfProjections-1] = first_and_last_angles[1];
845 int* ap_detectorRotDirection)
849 if (
m_verbose>=
VERBOSE_DETAIL)
Cout(
"iScannerCT::GetCTSpecificParameters() -> Copy pointers inside scanner to the datafile to get information" << endl
850 <<
" depending on the datafile inside the scanner" << endl);
854 Cerr(
"***** iScannerCT::GetCTSpecificParameters() -> Parameters have not been checked !" << endl);
873 cout <<
"This scanner class is dedicated to the description of CT systems." << endl;
iScannerCT()
iScannerCT constructor. Initialize the member variables to their default values.
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.
#define VERBOSE_DEBUG_EVENT
FLTNB * mp_crystalOrientationZ
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...
FLTNB m_CORtoDetectorDistance
FLTNB * mp_projectionAngles
FLTNB * mp_sourcePositionX
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])
Get the focal point and random positions on the crystal surface and its orientations from the event i...
FLTNB m_defaultBedDisplacementInMm
FLTNB * mp_crystalOrientationX
int Initialize()
Check general initialization and set several parameters to their default value.
FLTNB GetMatriceElt(uint16_t l, uint16_t c)
Declaration of class iScannerCT.
string GetPathToScannerFile()
int GetGeometricInfoFromDataFile(string a_pathToDF)
Recover geometric informations specific to the scanner class from the datafile header.
uint16_t m_nbOfProjections
int BuildLUT(bool a_scannerFileIsLUT)
Call the functions to generate the LUT or read the user-made LUT depending on the user choice...
oImageDimensionsAndQuantification * mp_ID
FLTNB m_CORtoSourceDistance
#define VERBOSE_DEBUG_LIGHT
virtual int SetRotDirection(string a_rotDirection)
Set rotation direction of the system.
int CheckParameters()
Check that all parameters have been correctly initialized.
FLTNB * mp_sourcePositionY
FLTNB * mp_crystalOrientationY
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 GetNbThreadsMax()
Get the maximum between the number of threads used for projections and image operations.
Singleton class that Instantiate and initialize the scanner object.
int SetMatriceElt(uint16_t l, uint16_t c, FLTNB a_val)
Set the matrix element corresponding to the argument indices with the provided value.
FLTNB * mp_crystalCentralPositionX
void DescribeSpecific()
Implementation of the pure virtual eponym function that simply prints info about the scanner...
Declaration of class sScannerManager.
bool m_allParametersChecked
#define KEYWORD_MANDATORY
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.
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...
Declaration of class sOutputManager.
~iScannerCT()
iScannerCT destructor.
Structure designed for basic matrices operations.
FLTNB * mp_crystalCentralPositionY
#define DEBUG_VERBOSE(IGNORED1, IGNORED2)
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)
This is a pure virtual method that must be implemented by children. Get the central positions and o...
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 ...
int GetCTSpecificParameters(uint16_t *ap_nbOfProjections, FLTNB *&ap_angles, int *ap_detectorRotDirection)
Set pointers passed in argument with the related CT specific variables This function is used to rec...
int Instantiate(bool a_scannerFileIsLUT)
Get mandatory informations from the scanner file and allocate memory for the member variables...
FLTNB * mp_crystalCentralPositionZ
Generic class for scanner objects.
void ShowHelp()
Display help.
FLTNB * mp_sourcePositionZ