133 if (
m_verbose>=
VERBOSE_NORMAL)
Cout(
"iScannerSPECTConv::Instantiate() -> Create scanner structure and read parameters from configuration file"<< endl);
142 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the number of SPECT heads !" << endl);
158 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the number of SPECT heads !" << endl);
163 Cerr(
"***** iScannerSPECTConv::Instantiate() -> Scanner radius <= 0. ? really ? :) ... " << endl);
169 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the transaxial number of pixels !" << endl);
174 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the transaxial pixel size !" << endl);
179 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the axial number of pixels !" << endl);
184 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the axial pixel size !" << endl);
189 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read detector depth !" << endl);
194 string *head_name =
new string[ m_nbHeads + 1 ];
197 ostringstream oss( ostringstream::out );
198 oss <<
"head" << i+1;
199 head_name[ i ] = oss.str();
208 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read transaxial focal model of head " << i <<
" !" << endl);
213 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read transaxial number of coef model of head " << i <<
" !" << endl);
218 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read axial focal model of head " << i <<
" !" << endl);
223 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read axial number of coef model of head " << i <<
" !" << endl);
230 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read transaxial model parameters of head " << i <<
" !" << endl);
235 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read axial model parameters of head " << i <<
" !" << endl);
244 Cerr(
"***** iScannerSPECTConv::Instantiate() -> An error occurred while trying to read the multiple bed displacement in the scanner header file !" << endl);
276 if (
m_verbose>=
VERBOSE_NORMAL)
Cout(
"iScannerSPECTConv::BuildLUT -> Build LUT for scanner elements coordinates and orientations"<< endl);
283 Cerr(
"***** iScannerSPECTConv::BuildLUT() -> Transaxial or axial number of pixels in the geometric file should be >0 !" << endl);
304 if (!a_scannerFileIsLUT)
308 Cerr(
"***** iScannerSPECTConv::BuildLUT() -> A problem occured while generating scanner LUT !" << endl);
316 Cerr(
"***** iScannerSPECTConv::BuildLUT() -> A problem occured while loading scanner LUT !" << endl);
342 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Number of crystals has not been initialized !" <<endl);
347 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Number of heads in the SPECT system has not been initialized !" <<endl);
352 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Number of projection angles has not been initialized !" <<endl);
357 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Number of transaxial/axial pixels have not correctly been initialized ! (should be >0)" <<endl);
362 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Transaxial/axial pixel sizes have not correctly been initialized ! (should be >0)" <<endl);
367 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Transaxial/axial number of virtual pixels have not correctly been initialized ! (should be >0)" <<endl);
372 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Transaxial/axial virtual pixel sizes have not correctly been initialized ! (should be >0)" <<endl);
377 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Transaxial/axial pixel gap sizes have not correctly been initialized ! (should be >0)" <<endl);
383 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Crystal depth has not correctly been initialized ! (should be >0)" <<endl);
388 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Transaxial/axial focal models have not correctly been initialized !" <<endl);
393 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Number of coefficients for the transaxial/axial focal models have not correctly been initialized !" <<endl);
398 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Parameters for the transaxial/axial focal models have not correctly been initialized !" <<endl);
403 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Projection angles have not correctly been initialized !" <<endl);
408 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Default scanner radius for each detector heads (scanner file) not correctly initialized !" <<endl);
413 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> Distances between center of rotation and each detector heads have not correctly been initialized !" <<endl);
420 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> LUT elements (crystal central positions) have not correctly been initialized !" <<endl);
427 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> LUT elements (crystal orientations) have not correctly been initialized !" <<endl);
434 Cerr(
"***** iScannerSPECTConv::CheckParameters()-> LUT elements (crystal focal positions) have not correctly been initialized !" <<endl);
458 if (
m_verbose>=
VERBOSE_NORMAL)
Cout(
"iScannerSPECTConv::Initialize() -> Initialize remaining stuff for scanner to be ready"<< endl);
463 Cerr(
"***** iScannerSPECTConv::Initialize() -> Parameters have not been checked !" << endl);
487 Cerr(
"iScannerSPECTConv::LoadLUT() -> Not yet implemented !" << endl);
516 FLTNB *CORx, *CORy, *CORz;
517 FLTNB *head_angleX, *head_angleY, *head_angleZ;
544 crystal_center_ref[c] =
new oMatrix(3,1);
547 for(
int i=0 ; i<3 ; i++)
551 for(
int j=0 ; j<3 ; j++)
563 rotation_mtx[i] =
new oMatrix(3,3);
579 FLTNB size_pixel_trans = 0., size_pixel_axial = 0.;
580 int nb_pixel_trans=0, nb_pixel_axial=0;
619 Cerr(
"***** iScannerSPECTConv::ComputeLUT() -> An error occurred while trying to read the transaxial gap size !" << endl);
625 Cerr(
"***** iScannerSPECTConv::ComputeLUT() -> An error occurred while trying to read the axial gap size !" << endl);
632 FLTNB x_start = -(nb_pixel_trans*size_pixel_trans + (nb_pixel_trans-1)*
m_gapSizeTrans) / 2 + (size_pixel_trans/2);
633 FLTNB z_start = -(nb_pixel_axial*size_pixel_axial + (nb_pixel_axial-1)*
m_gapSizeAxial) / 2 + (size_pixel_axial/2);
635 for(
int jj = 0; jj < nb_pixel_axial; ++jj )
638 for(
int ii = 0; ii < nb_pixel_trans; ++ ii )
642 crystal_center_ref[ii + nb_pixel_trans * jj]->
SetMatriceElt(0,0,Xcrist);
643 crystal_center_ref[ii + nb_pixel_trans * jj]->
SetMatriceElt(1,0, 0);
644 crystal_center_ref[ii + nb_pixel_trans * jj]->
SetMatriceElt(2,0,Zcrist);
663 crystal_center_ref[c]->SetMatriceElt(1,0,Ycrist);
668 int cryID = a*m_nbCrystals + c;
672 rotation_mtx[a]->
Multiplication(crystal_center_ref[c], crystal_center_out);
681 crystal_center_ref[c]->GetMatriceElt(1,0),
682 crystal_center_ref[c]->GetMatriceElt(2,0),
686 Cerr(
"***** iScannerSPECTConv::ComputeLUT() -> An error occurred while computing the focal positions ! " << endl);
702 rotation_mtx[a]->
Multiplication(focal_projection_position_mtx, focal_projection_position_mtx_output);
715 delete rotation_mtx[i];
717 delete[] rotation_mtx;
721 delete crystal_center_ref[c];
723 delete[] crystal_center_ref;
724 delete crystal_center_out;
725 delete focal_projection_position_mtx;
726 delete focal_projection_position_mtx_output;
728 delete[] head_angleX;
729 delete[] head_angleY;
730 delete[] head_angleZ;
780 FLTNB focal_posZ = 0;
791 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Error, the number of coeffs for the axial model should be <4 (max : polynom order 2 = 3 coeffs) ! " << endl);
796 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Error, the number of coeffs for the axial model should be >0 ('axial number of coef model' in geom file) ! " << endl);
811 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Error, the number of coeffs for a slanthole model should be equal to 1 (slope) : 'axial number of coef model' in geom file ! " << endl);
821 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Custom model should be implemented by the user (in iScannerSPECTConv::ComputeFocalPositions()) ! " << endl);
826 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Custom model should be implemented by the user (in iScannerSPECTConv::ComputeFocalPositions()) ! " << endl);
831 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Custom model should be implemented by the user (in iScannerSPECTConv::ComputeFocalPositions()) ! " << endl);
837 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Error, current model " <<
mp_focalModelAxial[a_headID] <<
" is unknown !" << endl);
838 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Should be either 'constant' (parallel), 'polynomial', 'hyperbolic, or 'custom'" << endl);
856 FLTNB focal_posX = 0;
867 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Error, the number of coeffs for the trans model should be <4 (max : polynom order 2 = 3 coeffs) ! " << endl);
872 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Error, the number of coeffs for the axial model should be >0 ('trans number of coef model' in geom file) ! " << endl);
887 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Error, the number of coeffs for a slanthole model should be equal to 1 (slope) : 'trans number of coef model' in geom file ! " << endl);
897 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Custom model should be implemented by the user (in iScannerSPECTConv::ComputeFocalPositions()) ! " << endl);
902 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Custom model should be implemented by the user (in iScannerSPECTConv::ComputeFocalPositions()) ! " << endl);
907 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Custom model should be implemented by the user (in iScannerSPECTConv::ComputeFocalPositions()) ! " << endl);
913 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Error, current model " <<
mp_focalModelTrans[a_headID] <<
" is unknown !" << endl);
914 Cerr(
"***** iScannerSPECTConv::ComputeFocalPositions() -> Should be either 'constant' (parallel), 'polynomial', 'hyperbolic, or 'custom'" << endl);
942 FLTNB ap_Orientation1[3],
FLTNB ap_Orientation2[3],
952 Cerr(
"***** iScannerSPECTConv::GetPositionsAndOrientations() -> Projection index (" << a_index1 <<
") out of range [0:" <<
m_nbOfProjections-1 <<
"] !" << endl);
959 Cerr(
"***** iScannerSPECTConv::GetPositionsAndOrientations() -> Crystal index (" << a_index2 <<
") out of range [0:" <<
m_nbCrystals-1 <<
"] !" << endl);
987 else if (ap_POI2[2]<0.)
989 Cerr(
"***** iScannerSPECTConv::GetPositionsAndOrientations() -> POI management not implemented yet for SPECT !" << endl);
993 else if (ap_POI2[0]==0. && ap_POI2[1]==0.)
995 Cerr(
"***** iScannerSPECTConv::GetPositionsAndOrientations() -> POI management not implemented yet for SPECT !" << endl);
1001 Cerr(
"***** iScannerSPECTConv::GetPositionsAndOrientations() -> POI management not implemented yet for SPECT !" << endl);
1037 FLTNB ap_Position1[3],
FLTNB ap_Position2[3],
1038 FLTNB ap_Orientation1[3],
FLTNB ap_Orientation2[3] )
1047 Cerr(
"***** iScannerSPECTConv::GetPositionsAndOrientations() -> Projection index (" << a_index1 <<
") out of range [0:" <<
m_nbOfProjections-1 <<
"] !" << endl);
1054 Cerr(
"***** iScannerSPECTConv::GetPositionsAndOrientations() -> Crystal index (" << a_index2 <<
") out of range [0:" <<
m_nbCrystals-1 <<
"] !" << endl);
1077 ap_Position2[2] =
mp_crystalCentralPositionZ[index] + axial*sqrt(1-mp_crystalOrientationZ[index]*mp_crystalOrientationZ[index]);
1080 ap_Orientation1[0] = -1.;
1081 ap_Orientation1[1] = -1.;
1082 ap_Orientation1[2] = -1.;
1085 ap_Orientation2[2] = mp_crystalOrientationZ[a_index2];
1108 Cerr(
"***** iScannerSPECTConv::GetPositionWithRandomDepth() -> This function was implemented for PET testing purpose. Not implemented for SPECT !" << endl);
1129 FLTNB ap_CornerInf1[3],
FLTNB ap_CornerSup1[3],
1130 FLTNB ap_CornerInf2[3],
FLTNB ap_CornerSup2[3])
1133 Cerr(
"***** iScannerSPECTConv::GetTwoCorners() -> Not implemented yet !" << endl);
1164 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> An error occurred while trying to read the multiple bed displacement in the datafile header !" << endl);
1170 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> Error while reading number of bins in the header data file " << endl);
1176 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> Error while reading number of projections in the header data file " << endl);
1180 string rotation_direction =
"";
1183 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> Error while reading head rotation orientation in the header data file " << endl);
1189 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> Error occured while trying to initialize head rotation orientation " << endl);
1195 FLTNB first_and_last_angles[2] = {-1.,-1.};
1204 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> Error while reading Angle mandatory field in the header data file '" << endl);
1214 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> Error while reading Angles field in the header data file !'" << endl);
1220 (first_and_last_angles[0] <0 || first_and_last_angles[1] <0) )
1222 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> No information on projection angles provided in the datafile !'" << endl);
1223 Cerr(
" This information should be provided using either the 'Angles' tag, or both 'First angles', 'Last angles' tags !'" << endl);
1229 angles[a] = first_and_last_angles[0] + a*(first_and_last_angles[1]-first_and_last_angles[0]) / (m_nbOfProjections-1);
1245 for(
int a=0 ; a<m_nbOfProjections/
m_nbHeads ; a++)
1255 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> Error while reading the distance between the camera detectors to the center of rotation in the header data file " << endl);
1259 else if (read_flag==2)
1269 else if(read_flag==1)
1272 Cerr(
"***** iScannerSPECTConv::GetGeometricInfoFromDatafile() -> Error while reading the global distance between the camera detectors to the center of rotation in the header data file " << endl);
1275 else if (read_flag==2)
1279 for(
int a=0 ; a<m_nbOfProjections/
m_nbHeads ; a++)
1307 uint16_t* ap_nbHeads,
1308 uint16_t* ap_nbOfBins,
1309 FLTNB* ap_pixSizeXY,
1311 FLTNB*& ap_CORtoDetectorDistance,
1312 int* ap_headRotDirection)
1320 Cerr(
"***** iScannerSPECTConv::GetSPECTSpecificParameters() -> Parameters have not been checked !" << endl);
1356 Cerr(
"***** iScannerSPECTConv::PROJ_SetSPECTAngles -> Error number of projection should be >0 ! '" << endl);
1390 Cerr(
"***** iScannerSPECTConv::PROJ_SetSPECTCORtoDetectorDistance -> Error number of projection should be >0 ! '" << endl);
1443 for(
int i=0 ; i<2 ; i++)
1478 cout <<
"This scanner class is dedicated to the description of parallel, convergent and multi-convergent SPECT systems." << endl;
This class is used to represent any SPECT camera with parallel/convergent collimator.
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
string * mp_focalModelAxial
FLTNB * mp_crystalOrientationY
double GenerateRdmNber()
Generate a random number for the thread whose index is recovered from the ompenMP function...
FLTNB * mp_crystalCentralPositionX
oMatrix * mp_positionMatrix_out
uint16_t m_nbOfProjections
uint32_t m_vNbPixelsTrans
FLTNB * mp_crystalFocalPositionZ
FLTNB ** m2p_axialFocalParameters
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...
uint32_t m_vNbPixelsAxial
FLTNB ** m2p_transFocalParameters
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...
string GetPathToScannerFile()
int SetMatriceElt(uint16_t l, uint16_t c, FLTNBLUT a_val)
Set the matrix element corresponding to the argument indices with the provided value.
void ShowHelp()
Display help.
int PROJ_SetSPECTCORtoDetectorDistance(FLTNB a_distance)
Set distance between the center of rotation and SPECT detectors if arg value>0, Set with the geomet...
FLTNB * mp_crystalCentralPositionY
FLTNB m_multiBedDisplacementInMm
oMatrix * mp_rotationMatrix
iScannerSPECTConv()
iScannerSPECTConv constructor. Initialize the member variables to their default values.
int PROJ_SetSPECTAngles(FLTNB *ap_projectionAngles)
Set the projection angles with the array provided in parameter.
#define SCANNER_SPECT_CONVERGENT
int ComputeLUT()
Computes the LUT of the scanner from a generic (.geom) file.
uint8_t * mp_nbCoefModelTrans
#define VERBOSE_DEBUG_LIGHT
virtual int SetRotDirection(string a_rotDirection)
Set rotation direction of the system.
FLTNB * mp_CORtoDetectorDistance
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.
Declaration of class sScannerManager.
int Multiplication(oMatrix *a_Mtx, oMatrix *a_MtxResult)
Multiply the member matrix with the matrix provided in 1st parameter Return the result in the matric ...
Declaration of class iScannerSPECTConv.
int BuildLUT(bool a_scannerFileIsLUT)
Call the functions to generate the LUT or read the user-made LUT depending on the user choice...
bool m_allParametersChecked
#define KEYWORD_MANDATORY
string * mp_focalModelTrans
FLTNB * mp_crystalOrientationZ
Singleton class that generate a thread-safe random generator number for openMP As singleton...
int GetSPECTSpecificParameters(uint16_t *ap_nbOfProjections, uint16_t *ap_nbHeads, uint16_t *ap_nbOfBins, FLTNB *ap_pixSizeXY, FLTNB *&ap_angles, FLTNB *&ap_CORtoDetectorDistance, int *ap_headRotDirection)
Set pointers passed in argument with the related SPECT specific variables This function is used to ...
FLTNB * mp_projectionAngles
int ComputeFocalPositions(FLTNB a_posX, FLTNB a_posY, FLTNB a_posZ, int a_headID, int a_cryID)
Compute focal positions for a specific crystal ID.
FLTNBLUT GetMatriceElt(uint16_t l, uint16_t c)
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...
Declaration of class sOutputManager.
oMatrix * mp_positionMatrix_ref
uint8_t * mp_nbCoefModelAxial
int Initialize()
Check general initialization and set several parameters to their default value.
Structure designed for basic matrices operations.
int PROJ_SetSPECTNbBins(uint16_t *ap_nbOfBins)
Set number of bins.
int CheckParameters()
Check that all parameters have been correctly initialized.
int PROJ_SetSPECTNbProjections(uint32_t a_nbOfProjections)
Set number of projections.
FLTNB * mp_crystalCentralPositionZ
#define DEBUG_VERBOSE(IGNORED1, IGNORED2)
int GetGeometricInfoFromDatafile(string a_pathToDF)
Recover geometric informations specific to the scanner class from the datafile header.
int PROJ_GetSPECTNbBins(uint16_t *ap_nbOfBins)
Get the number of SPECT heads in the pointer provided in parameter.
int Instantiate(bool a_scannerFileIsLUT)
Get mandatory informations from the scanner file and allocate memory for the member variables...
~iScannerSPECTConv()
iScannerSPECTConv destructor.
FLTNB * mp_crystalOrientationX
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 * mp_crystalFocalPositionY
FLTNB * mp_crystalFocalPositionX
Generic class for scanner objects.
int LoadLUT()
Load a precomputed scanner LUT.
#define VERBOSE_DEBUG_NORMAL