CASToR  1.0
Tomographic Reconstruction (PET/SPECT)
sScannerManager.cc
Go to the documentation of this file.
00001 
00002 /*
00003   Implementation of class sScannerManager
00004 
00005   - separators: X
00006   - doxygen: X
00007   - default initialization: X
00008   - CASTOR_DEBUG: none
00009   - CASTOR_VERBOSE: X
00010 */
00011 
00018 #include "sScannerManager.hh"
00019 #include "sAddonManager.hh"
00020 
00021 // Singleton : set pointer to object to NULL
00022 sScannerManager *sScannerManager::mp_Instance = NULL;
00023 
00024 // =====================================================================
00025 // ---------------------------------------------------------------------
00026 // ---------------------------------------------------------------------
00027 // =====================================================================
00028 /*
00029   \brief sScannerManager constructor.
00030   \details It is private at this class is singleton. 
00031            This class should be instanciated using the GetInstance() function 
00032            Initialize the member variables to their default values.
00033 */
00034 sScannerManager::sScannerManager()
00035 {
00036   mp_Scanner = NULL;
00037   m_verbose = -1;
00038   m_pathToScannerFile = "";
00039   m_scannerName = "";
00040   m_hasUserScannerFile = false;
00041   m_hasGenericScannerFile = false;
00042   m_allParametersChecked = false;
00043   m_saveLUTFlag = false;
00044 }
00045 
00046 
00047 
00048 // =====================================================================
00049 // ---------------------------------------------------------------------
00050 // ---------------------------------------------------------------------
00051 // =====================================================================
00052 /*
00053   \brief sScannerManager destructor. 
00054 */
00055 sScannerManager::~sScannerManager()
00056 {
00057   if(mp_Scanner != NULL) delete mp_Scanner;
00058 }
00059 
00060 
00061 
00062 // =====================================================================
00063 // ---------------------------------------------------------------------
00064 // ---------------------------------------------------------------------
00065 // =====================================================================
00066 /*
00067   \fn CheckParameters
00068   \brief Check if all parameters have been correctly initialized, and call the CheckParameters function of the scanner object
00069   \return 0 if success. Positive value otherwise
00070 */
00071 int sScannerManager::CheckParameters()
00072 {
00073   if (m_verbose>=2) Cout("sScannerManager::CheckParameters ..."<< endl); 
00074     
00075   if (mp_Scanner == NULL)
00076   {
00077      Cerr("***** sScannerManager::CheckParameters() -> Scanner object not initialized" << endl);
00078      return 1;
00079   }
00080   
00081   if (m_hasUserScannerFile == false && m_hasGenericScannerFile == false)
00082   {
00083      Cerr("***** sScannerManager::CheckParameters() -> Scanner file type (generic or user provided) not initialized" << endl);
00084      return 1;
00085   }
00086 
00087   if (m_scannerName.empty())
00088   {
00089      Cerr("***** sScannerManager::CheckParameters() -> Scanner name not initialized" << endl);
00090      return 1;
00091   }
00092 
00093   if (m_pathToScannerFile.empty())
00094   {
00095      Cerr("***** sScannerManager::CheckParameters() -> Path to scanner file not initialized" << endl);
00096      return 1;
00097   }
00098   
00099   if (m_verbose<0)
00100   {
00101      Cerr("***** sScannerManager::CheckParameters() -> Verbosity level not initialized" << endl);
00102      return 1;
00103   }
00104   
00105   // Check parameters of the scanner object
00106   if (mp_Scanner->CheckParameters())
00107   {
00108     Cerr("***** sScannerManager::BuildScannerObject() -> A problem occurred while checking Scanner Object parameters !" << endl);
00109     return 1;
00110   }
00111   
00112   m_allParametersChecked = true;
00113   
00114   return 0;
00115 }
00116 
00117 
00118 
00119 // =====================================================================
00120 // ---------------------------------------------------------------------
00121 // ---------------------------------------------------------------------
00122 // =====================================================================
00123 /*
00124   \fn Initialize
00125   \brief Initialization :
00126          - check if all parameters of the manager have been checked
00127          - call the initialization function of the scanner object 
00128   \return 0 if success. Positive value otherwise
00129 */
00130 int sScannerManager::Initialize()
00131 {
00132   if(m_verbose>=2) Cout("sScannerManager::Initialize ..."<< endl); 
00133     
00134   if(m_allParametersChecked == false)
00135   {
00136      Cerr("***** sScannerManager::Initialize() -> Parameters have not been checked !" << endl);
00137      return 1;
00138   }
00139 
00140   // Initialize the scanner object
00141   if(mp_Scanner->Initialize())
00142   {
00143     Cerr("***** sScannerManager::BuildScannerObject() -> A problem occurred while initializing Scanner Object !" << endl);
00144     return 1;
00145   }
00146 
00147   return 0;
00148 }
00149 
00150 
00151 
00152 // =====================================================================
00153 // ---------------------------------------------------------------------
00154 // ---------------------------------------------------------------------
00155 // =====================================================================
00156 /*
00157   \fn ShowScannersDescription
00158   \brief Get the description associated to the different scanners and print all on screen.
00159          Walk through the scanner repository and look for the keyword "description" in .geom file and .hscan file.
00160   \return 0 if success, positive value otherwise
00161   \todo Check everything output correctly for all implemented scanners
00162 */
00163 int sScannerManager::ShowScannersDescription()
00164 {
00165   if(m_verbose>=3) Cout("sScannerManager::ShowScannersDescription ..."<< endl); 
00166     
00167   // Return when using MPI and mpi_rank is not 0
00168   #ifdef CASTOR_MPI
00169   int mpi_rank = 0;
00170   MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
00171   if (mpi_rank!=0) return 0;
00172   #endif
00173   
00174   // Gather all the available scanner from the repository
00175   vector<string> list_scanner_names;
00176   if(GetAvailableScanners(&list_scanner_names))
00177   {
00178     Cerr("***** sScannerManager::ShowScannersDescription() -> a problem occurred when recovering scanner names from the scanner repository !" << endl);
00179     return 1;
00180   }
00181   
00182   cout << endl << "Here is the list of all available scanners in the repository along with their options:" << endl << endl;
00183   for (unsigned int iter = 0; iter!=list_scanner_names.size(); iter++)
00184   {
00185     // Get the actual scanner in temporary local variable
00186     string scanner_file = sOutputManager::GetInstance()->GetPathToConfigDir() + "scanner" + OS_SEP;
00187     // Print out the name of this scanner
00188     cout << "------------------------------------------------------------------" << endl;
00189     cout << "-----  \"" << list_scanner_names[iter] << "\"" << endl;
00190     cout << "------------------------------------------------------------------" << endl;
00191     // Proceed
00192     scanner_file.append(list_scanner_names[iter]);
00193     // look for the "description" keyword in the .geom or .hscan file
00194     string description;
00195 
00196     ReadDataASCIIFile(scanner_file, "description", &description, 1, 1);
00197     // look for the "description" keyword in the .geom or .hscan file
00198     cout << description << endl << endl;
00199   }
00200   return 0;
00201 }
00202 
00203 
00204 
00205 // =====================================================================
00206 // ---------------------------------------------------------------------
00207 // ---------------------------------------------------------------------
00208 // =====================================================================
00209 /*
00210   \fn FindScannerSystem
00211   \param a_scannerName : string containing name of the required scanner
00212   \brief Look for a file matching with the scanner name in parameter inside the scanner repository 
00213   \return 0 if success (scanner found). Positive value otherwise
00214 */
00215 int sScannerManager::FindScannerSystem(string a_scannerName)
00216 {
00217   if (m_verbose>=3) Cout("sScannerManager::FindScannerSystem() -> Search the scanner of data file in the configuration directory"<< endl); 
00218     
00219   if (a_scannerName.empty())
00220   {
00221     Cerr("***** sScannerManager::FindScannerSystem() -> scanner name is empty !" << endl);
00222     return 1;
00223   }
00224   else
00225   {
00226     // Get the list of scanner from the repository
00227     vector<string> repository_scanner_names;
00228     if(GetAvailableScanners(&repository_scanner_names))
00229     {
00230       Cerr("***** sScannerManager::FindScannerSystem() -> a problem occurred when recovering scanner names from the scanner repository !" << endl);
00231       return 1;
00232     }
00233   
00234     m_scannerName = a_scannerName;
00235     m_pathToScannerFile = sOutputManager::GetInstance()->GetPathToConfigDir() + "scanner" + OS_SEP;
00236     
00237     // String to recover generic/user-made scanner file
00238     string generic_scanner_file, user_scanner_file;
00239     
00240     // Loop over the scanner available in the repository, and check if the scanner name match with any of these
00241     for (unsigned int index_name=0 ; index_name<repository_scanner_names.size() ; index_name++)
00242     {
00243       string gfile = a_scannerName;
00244       string ufile = a_scannerName;
00245 
00246       // Check if the scanner match a geom file (generic_scanner_file)
00247       if (gfile.append(".geom") == repository_scanner_names[index_name])
00248       {
00249         generic_scanner_file = a_scannerName;
00250         generic_scanner_file.append(".geom");
00251         m_hasGenericScannerFile = true;
00252         
00253         if(m_verbose >= 3) Cout("sScannerManager::FindScannerSystem() -> matched generic file for the scanner system: " << repository_scanner_names[index_name] << endl);
00254       }
00255       
00256       // Check if the scanner match an user file (user provided LUT)
00257       if (ufile.append(".hscan") == repository_scanner_names[index_name])
00258       {
00259         user_scanner_file = a_scannerName;
00260         user_scanner_file.append(".hscan");
00261         m_hasUserScannerFile = true;
00262  
00263         if(m_verbose >= 3) Cout("sScannerManager::FindScannerSystem() -> matched custom LUT for the scanner system: " << repository_scanner_names[index_name] << endl);
00264       }
00265 
00266     }
00267     
00268     // Both a generic file and user-provided LUT exist for this system.
00269     // Generic file selected by default
00270     if(m_hasGenericScannerFile == true && m_hasUserScannerFile == true)
00271     {
00272       if(m_verbose >= 3)
00273       {
00274         Cerr("***** WARNING sScannerManager::FindScannerSystem() -> Both a generic file and user-provided LUT have been detected for the " << a_scannerName << " system." << endl);
00275         Cerr("                                                      The generic file (*.geom) will be selected by default." << endl);
00276       }
00277      
00278       m_hasUserScannerFile = false;
00279     }
00280     
00281     // Initialize m_pathToScannerFile member variable
00282     if(m_hasGenericScannerFile == true)
00283       m_pathToScannerFile.append(generic_scanner_file.c_str());
00284     else if(m_hasUserScannerFile == true)
00285       m_pathToScannerFile.append(user_scanner_file.c_str());
00286     else // Unknown scanner, output scanner description and throw error
00287     {
00288       Cerr("***** sScannerManager::FindScannerSystem() -> Scanner '"<< a_scannerName << 
00289            "' is not known in the scanner repository. Please provide a LUT/generic file for this scanner in the scanner repository in: " << 
00290            sOutputManager::GetInstance()->GetPathToConfigDir() << "scanner" << OS_SEP << endl << endl;);
00291       
00292       ShowScannersDescription();
00293       
00294       return 1;
00295     }
00296     
00297     return 0;
00298   }
00299 }
00300 
00301 
00302 
00303 // =====================================================================
00304 // ---------------------------------------------------------------------
00305 // ---------------------------------------------------------------------
00306 // =====================================================================
00307 /*
00308   \fn BuildScannerObject()
00309   \brief Instantiate the specific scanner object related to the modality, and set verbosity of scanner object
00310   \todo delete the check on modality once all scanner classes will be completely implemented ? 
00311   \return 0 if success. Positive value otherwise
00312 */
00313 int sScannerManager::BuildScannerObject()
00314 {
00315   if(m_verbose>=2) Cout("sScannerManager::BuildScannerObject ..."<< endl); 
00316     
00317   // Check scanner modality
00318   string scanner_type;
00319   
00320   typedef vScanner *(*maker_scanner) ();
00321 
00322   // Get the system type from the value of the modality field inside the scanner header
00323   if (ReadDataASCIIFile(m_pathToScannerFile, "modality", &scanner_type, 1, KEYWORD_MANDATORY) == 1)
00324   {
00325     Cerr("***** sScannerManager::BuildScannerObject() -> 'Modality' field not found in the header of the scanner configuration file at :"<< endl);
00326     Cerr("*****                                          "<<m_pathToScannerFile << endl);
00327     return 1;
00328   }
00329       
00330   // Get scanner's list from addon manager
00331   std::map <string,maker_scanner> list = sAddonManager::GetInstance()->mp_listOfScannerTypes;
00332 
00333   // Instanciate the scanner class corresponding to the modality
00334   // Throw error if no match
00335   if (list[scanner_type]) mp_Scanner = list[scanner_type]();
00336   else
00337   {
00338     Cerr("***** sScannerManager::BuildScannerObject() -> Modality '" << scanner_type << "' is unknown !" << endl);
00339     sAddonManager::GetInstance()->ShowHelpScanner();
00340     return 1;
00341   }
00342 
00343   // Set scanner verbosity
00344   mp_Scanner->SetVerbose(m_verbose);
00345 
00346   return 0;
00347 }
00348 
00349 
00350 
00351 
00352 // =====================================================================
00353 // ---------------------------------------------------------------------
00354 // ---------------------------------------------------------------------
00355 // =====================================================================
00356 /*
00357   \fn GetGeometricInfoFromDatafile
00358   \param a_path : string containing the path to datafile header
00359   \brief Call the specialized function of the scanner object in order to 
00360          get geometric informations from the datafile header
00361   \return 0 if success. Positive value otherwise
00362 */
00363 int sScannerManager::GetGeometricInfoFromDatafile(string a_path)
00364 {
00365   if(m_verbose>=2) Cout("sScannerManager::GetGeometricInfoFromDatafile ..."<< endl); 
00366     
00367   if (mp_Scanner->GetGeometricInfoFromDatafile(a_path))
00368   {
00369     Cerr("***** sScannerManager::GetGeometricInfoFromDatafile() -> An error occurred while getting information from the datafile." << endl);          
00370     return 1;
00371   }
00372 
00373   return 0;
00374 }
00375 
00376 
00377 
00378 // =====================================================================
00379 // ---------------------------------------------------------------------
00380 // ---------------------------------------------------------------------
00381 // =====================================================================
00382 /*
00383   \fn InstantiateScanner
00384   \brief Instantiate scanner using the related function in the scanner classes
00385   \todo delete the check on scanner type once all scanner classes will be completely implemented. 
00386   \return 0 if success. Positive value otherwise
00387 */
00388 int sScannerManager::InstantiateScanner()
00389 {
00390   if(m_verbose>=2) Cout("sScannerManager::InstantiateScanner ..."<< endl); 
00391   
00392   // Check if the scanner object is known (TODO : delete this check once all scanner classes will be completely implemented)
00393   if (mp_Scanner->GetScannerType() < 0)
00394   {
00395     Cerr("***** sScannerManager::BuildScannerObject() -> Unknow scanner type !" << endl);
00396     return 1;
00397   }
00398 
00399   // Instantiate geometry
00400   if (mp_Scanner->Instantiate(m_hasUserScannerFile))
00401   {
00402     Cerr("***** sScannerManager::InstantiateScanner() -> An error occurred while instanciating the Scanner object !" << endl);
00403     return 1;
00404   }
00405 
00406   return 0;
00407 }
00408 
00409 
00410 
00411 // =====================================================================
00412 // ---------------------------------------------------------------------
00413 // ---------------------------------------------------------------------
00414 // =====================================================================
00415 /*
00416   \fn BuildLUT()
00417   \brief Call the eponym function of the scanner class
00418   \return 0 if success. Positive value otherwise
00419 */
00420 int sScannerManager::BuildLUT()
00421 {
00422   if(m_verbose>=2) Cout("sScannerManager::Generate the geometric Look-Up Table ..."<< endl); 
00423     
00424   // Generate LUT
00425   if (mp_Scanner->BuildLUT(m_hasUserScannerFile))
00426   {
00427     Cerr("***** sScannerManager::BuildLUT() -> A problem occurred while generating/reading the LUT ." << endl);          
00428     return 1;
00429   }
00430 
00431   return 0;
00432 }
00433 
00434 
00435 
00436 // =====================================================================
00437 // ---------------------------------------------------------------------
00438 // ---------------------------------------------------------------------
00439 // =====================================================================
00440 /*
00441   \fn GetAvailableScanners
00442   \param ap_scannerNames : vector list of string to recover the available scanner names
00443   \brief Gather all the names of the header files (.geom & .hscan) 
00444          in the repository folder in the vector<string> passed in parameter
00445   \return 0 if sucess, positive value otherwise
00446 */
00447 int sScannerManager::GetAvailableScanners(vector<string> *ap_scannerNames)
00448 {
00449   if(m_verbose>=3) Cout("sScannerManager::GetAvailableScanners ..."<< endl); 
00450     
00451   DIR *respository_dir;
00452   struct dirent *ent;
00453   
00454   string str_geom(".geom"), str_hscan(".hscan");
00455   string scanner_repository = sOutputManager::GetInstance()->GetPathToConfigDir() + "scanner" + OS_SEP;
00456   
00457   if ((respository_dir = opendir(scanner_repository.c_str())) != NULL) 
00458   {
00459     // print all the files and directories within the repository directory
00460     while ((ent = readdir (respository_dir)) != NULL) 
00461     {
00462       string scanner_name = ent->d_name;
00463       
00464       if(scanner_name.at(scanner_name.size()-1) != '~') // Get rid of backup files in linux.
00465       
00466       // .geom or .hscan file found
00467       if(scanner_name.find(str_geom)!=string::npos || scanner_name.find(str_hscan)!=string::npos )
00468       {
00469         ap_scannerNames->push_back(scanner_name);
00470       }
00471     }
00472     closedir (respository_dir);
00473   } 
00474   else 
00475   {
00476     Cerr("***** sScannerManager::GetAvailableScanners() -> could not open the repository directory at: " << scanner_repository << endl);
00477     return 1;
00478   }
00479 
00480   return 0;
00481 }
00482 
00483 
00484 
00485 // =====================================================================
00486 // ---------------------------------------------------------------------
00487 // ---------------------------------------------------------------------
00488 // =====================================================================
00489 /*
00490   \fn GetScannerLayerNbRings
00491   \param a_layer : layer index
00492   \brief Ask the number of rings to the scanner object for a specific layer. 
00493          Returns an error if this information is not available for the scanner type of the object (eg : SPECT systems) 
00494   \return The number of rings in the system if success. NEGATIVE value otherwise
00495 */
00496 int sScannerManager::GetScannerLayerNbRings(int a_layer)
00497 {
00498   if(m_verbose>=3) Cout("sScannerManager::GetScannerLayerNbRings ..."<< endl); 
00499     
00500   if(mp_Scanner->GetScannerType() == SCANNER_PET) 
00501   {
00502     int nb_rings = mp_Scanner->GetScannerLayerNbRings(a_layer);
00503     
00504     // Check for error
00505     if (nb_rings <= 0)
00506     {
00507       Cerr("***** sScannerManager::GetScannerLayerNbRings() -> error when trying to get the number of rings in the system for the crystal layer " << a_layer+1 << " !" << endl);
00508       return -1;
00509     }
00510     else 
00511       return nb_rings;
00512   }
00513   else
00514   {
00515     Cerr("***** sScannerManager::GetScannerLayerNbRings() -> This function is only available for PET scans !" << endl);
00516     return -1;
00517   }
00518 }
00519 
00520 
00521 
00522 // =====================================================================
00523 // ---------------------------------------------------------------------
00524 // ---------------------------------------------------------------------
00525 // =====================================================================
00526 /*
00527   \fn PROJ_GetModalityStopValueMainLoop
00528   \brief Get the stop value for the main loop of analytic projection depending on the modality 
00529   \return the required stop value if success, NEGATIVE value otherwise
00530   \todo Cases for CT and sinogram scanner types
00531 */
00532 int64_t sScannerManager::PROJ_GetModalityStopValueMainLoop()
00533 {
00534   if(m_verbose>=3) Cout("sScannerManager::PROJ_GetModalityStopValueMainLoop ..."<< endl); 
00535   
00536   if (mp_Scanner->GetScannerType() == SCANNER_PET)
00537   {
00538     return mp_Scanner->GetSystemNbElts();
00539   }
00540   else if(mp_Scanner->GetScannerType() == SCANNER_SPECT_PINHOLE ||
00541           mp_Scanner->GetScannerType() == SCANNER_SPECT_CONVERGENT )
00542   {
00543     return (int64_t)mp_Scanner->PROJ_GetSPECTNbProjections(); // cast from uint16_t to int
00544   }
00545   else if(mp_Scanner->GetScannerType() == SCANNER_CT)
00546   {
00547     // TODO
00548     Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Not implemented for CT yet!" << endl);
00549     return -1;
00550   }
00551   else if(mp_Scanner->GetScannerType() == SCANNER_SINOGRAM)
00552   {
00553     // TODO + should call a GetType() like function for scanner defined as a sinogram
00554     Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Not implemented for Sinogram scanner yet!" << endl);
00555     return -1;
00556   }
00557   else
00558   {
00559     Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Unknown scanner type!" << endl);
00560     return -1;
00561   }
00562   
00563   return 0;
00564 }
00565 
00566 
00567 
00568 // =====================================================================
00569 // ---------------------------------------------------------------------
00570 // ---------------------------------------------------------------------
00571 // =====================================================================
00572 /*
00573   \fn PROJ_GetModalityStartValueInnerLoop
00574   \param a_elt1 : Current nb of processed crystals (PET), projections (SPECT)
00575   \brief Get the start value for the inner loop of analytic projection depending on the modality 
00576   \return the required stop value if success, NEGATIVE value otherwise
00577   \todo Cases for CT and sinogram scanner types
00578   \todo Precise with SS on which index SPECT inner loop should be done
00579 */
00580 int64_t sScannerManager::PROJ_GetModalityStartValueInnerLoop(int64_t a_elt1)
00581 {  
00582   #ifdef CASTOR_VERBOSE
00583   if(m_verbose>=4) Cout("sScannerManager::PROJ_GetModalityStopValueMainLoop ..."<< endl); 
00584   #endif
00585   
00586   if (mp_Scanner->GetScannerType() == SCANNER_PET)
00587   {
00588     return a_elt1+1;
00589   }
00590   else if(mp_Scanner->GetScannerType() == SCANNER_SPECT_PINHOLE ||
00591           mp_Scanner->GetScannerType() == SCANNER_SPECT_CONVERGENT )
00592   {
00593     return 0; // (first crystal)
00594     // TODO SS: here the inner loop should be done on the number of views
00595   }
00596   else if(mp_Scanner->GetScannerType() == SCANNER_CT)
00597   {
00598     // TODO
00599     Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Not implemented for CT yet!" << endl);
00600     return -1;
00601   }
00602   else if(mp_Scanner->GetScannerType() == SCANNER_SINOGRAM)
00603   {
00604     // TODO + should call a GetType() like function for scanner defined as a sinogram
00605     Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Not implemented for Sinogram scanner yet!" << endl);
00606     return -1;
00607   }
00608   else
00609   {
00610     Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Unknown scanner type!" << endl);
00611     return -1;
00612   }
00613   
00614   return 0;
00615 }
00616 
00617 
00618 
00619 // =====================================================================
00620 // ---------------------------------------------------------------------
00621 // ---------------------------------------------------------------------
00622 // =====================================================================
00623 /*
00624   \fn PROJ_GetCurrentProgression
00625   \param a_elt1 : Current nb of processed #1 crystals (PET), projections (SPECT)
00626   \param a_elt2 : Current nb of processed #2 crystals (PET), crystals (SPECT)
00627   \param ap_nbEltsArray : Total number of elements processed for each #1 crystals (PET/CT systems) 
00628   \param a_nbRGates
00629   \param a_nbCGates
00630   \param a_fr
00631   \param a_rg
00632   \param a_cg
00633   \brief Get numerator value according to the modality to compute percent progression during the analytical projection process
00634   \return the required progression value if success, negative value otherwise
00635   \todo Cases for CT and sinogram scanner types
00636   \todo Optimize this, for now it's quite a lot of operation for each couple of elements
00637   \todo Check everything is ok for 3D/4D PET and SPECT 
00638 */
00639 int64_t sScannerManager::PROJ_GetCurrentProgression(int64_t a_elt1, int64_t a_elt2, int64_t* ap_nbEltsArray, 
00640                                                      int a_nbRGates, int a_nbCGates,
00641                                                      int a_fr, int a_rg, int a_cg)
00642 {
00643   #ifdef CASTOR_VERBOSE
00644   if(m_verbose>=4) Cout("sScannerManager::PROJ_GetCurrentProgression ..."<< endl); 
00645   #endif
00646   
00647   // TODO : optimization, maybe too much operations for each couple of elements
00648   if (mp_Scanner->GetScannerType() == SCANNER_PET)
00649   {
00650     int64_t nb_total_elts = mp_Scanner->GetSystemNbElts();
00651 
00652     return ap_nbEltsArray[a_elt1]+a_elt2+1 + 
00653            (int64_t)(a_fr*a_nbRGates*a_nbCGates + a_rg*a_nbCGates + a_cg)* nb_total_elts*nb_total_elts/2;
00654   }
00655   else if(mp_Scanner->GetScannerType() == SCANNER_SPECT_PINHOLE ||
00656           mp_Scanner->GetScannerType() == SCANNER_SPECT_CONVERGENT )
00657   {
00658     return a_elt2 + a_elt1*mp_Scanner->GetSystemNbElts() + 
00659            a_fr * a_nbRGates * a_nbCGates * mp_Scanner->GetSystemNbElts() +
00660            a_rg * a_nbCGates * mp_Scanner->GetSystemNbElts() +
00661            a_cg * mp_Scanner->GetSystemNbElts();
00662   }
00663   else if(mp_Scanner->GetScannerType() == SCANNER_CT)
00664   {
00665     //TODO
00666     Cerr("sScannerManager::PROJ_GetCurrentProgression()-> Not implemented for CT yet!" << endl);
00667     return -1;
00668   }
00669   else if(mp_Scanner->GetScannerType() == SCANNER_SINOGRAM)
00670   {
00671     //TODO + should call a GetType() like function for scanner defined as a sinogram
00672     Cerr("sScannerManager::PROJ_GetCurrentProgression()-> Not implemented for Sinogram scanner yet!" << endl);
00673     return -1;
00674   }
00675   else
00676   {
00677     Cerr("sScannerManager::PROJ_GetCurrentProgression()-> Unknown scanner type!" << endl);
00678     return -1;
00679   }
00680 }
00681 
00682 
00683 
00684 // =====================================================================
00685 // ---------------------------------------------------------------------
00686 // ---------------------------------------------------------------------
00687 // =====================================================================
00688 /*
00689   \fn PROJ_GetProgressionFinalValue
00690   \brief Get numerator value according to the modality to compute percent progression during the projection process
00691   \return the required progression value if success, negative value otherwise
00692   \todo Cases for CT and sinogram scanner types
00693 */
00694 int64_t sScannerManager::PROJ_GetProgressionFinalValue()
00695 {
00696   if(m_verbose>=3) Cout("sScannerManager::PROJ_GetProgressionFinalValue ..."<< endl); 
00697   
00698   if (mp_Scanner->GetScannerType() == SCANNER_PET)
00699   {
00700     //return mp_Scanner->GetSystemNbElts();
00701     int64_t nb_total_elts = mp_Scanner->GetSystemNbElts();
00702     return nb_total_elts*nb_total_elts/2;
00703   }
00704   else if(mp_Scanner->GetScannerType() == SCANNER_SPECT_PINHOLE ||
00705           mp_Scanner->GetScannerType() == SCANNER_SPECT_CONVERGENT )
00706   {
00707     return (int64_t)mp_Scanner->PROJ_GetSPECTNbProjections()*mp_Scanner->GetSystemNbElts(); // cast from uint16_t to int
00708   }
00709   else if(mp_Scanner->GetScannerType() == SCANNER_CT)
00710   {
00711     //TODO
00712     Cerr("sScannerManager::PROJ_GetProgressionFinalValue()-> Not implemented for CT yet!" << endl);
00713     return -1;
00714   }
00715   else if(mp_Scanner->GetScannerType() == SCANNER_SINOGRAM)
00716   {
00717     //TODO + should call a GetType() like function for scanner defined as a sinogram
00718     Cerr("sScannerManager::PROJ_GetProgressionFinalValue()-> Not implemented for Sinogram scanner yet!" << endl);
00719     return -1;
00720   }
00721   else
00722   {
00723     Cerr("sScannerManager::PROJ_GetProgressionFinalValue()-> Unknown scanner type!" << endl);
00724     return -1;
00725   }
00726 }
00727 
00728 
00729 
00730 // =====================================================================
00731 // ---------------------------------------------------------------------
00732 // ---------------------------------------------------------------------
00733 // =====================================================================
00734 /*
00735   \fn PROJ_SetPETSpecificParameters (Analytic Projection)
00736   \param a_maxRingDiff : max number of axial ring difference
00737   \brief Deliver to the PET scanner object all informations provided from the datafile header
00738   \return 0 if success, positive value otherwise
00739   \todo How to handle systems with several layer of rings ?
00740 */
00741 int sScannerManager::PROJ_SetPETSpecificParameters(int a_maxRingDiff)
00742 {
00743   if(m_verbose>=3) Cout("sScannerManager::PROJ_SetPETSpecificParameters ..."<< endl); 
00744   
00745   if (mp_Scanner->GetScannerType() != SCANNER_PET)
00746   {
00747     Cerr("***** sScannerManager::SetPETSpecificParameters() -> The scanner object is not of PET type !" << endl);
00748     return 1;
00749   }
00750   else
00751   {
00752     mp_Scanner->SetPETMaxRingDiff(a_maxRingDiff);
00753   }
00754   
00755   return 0;
00756 }
00757 
00758 
00759 
00760 // =====================================================================
00761 // ---------------------------------------------------------------------
00762 // ---------------------------------------------------------------------
00763 // =====================================================================
00771 int sScannerManager::PROJ_GetPETSpecificParameters(int* ap_maxRingDiff)
00772 {
00773   if(m_verbose>=3) Cout("sScannerManager::PROJ_GetPETSpecificParameters ..."<< endl); 
00774     
00775   if (mp_Scanner->GetScannerType() != SCANNER_PET )
00776   {
00777     Cerr("***** sScannerManager::PROJ_GetPETSpecificParameters()-> The scanner object is not of PET type !" << endl);
00778     return 1;
00779   }
00780   else
00781   {
00782     int max_ring_diff = -1;
00783     
00784     if (mp_Scanner->PROJ_GetPETSpecificParameters(&max_ring_diff) )
00785     {
00786       Cerr("***** sScannerManager::PROJ_GetPETSpecificParameters()-> A problem occurred while retrieving PET parameters from the scanner object !" << endl);
00787       return 1;
00788     }
00789     
00790     if (max_ring_diff < 0)
00791     {
00792       Cerr("***** sScannerManager::PROJ_GetPETSpecificParameters()-> max ring difference should be > 0 !" << endl);
00793       return 1;
00794     }
00795     else
00796       *ap_maxRingDiff = max_ring_diff;
00797   }
00798   return 0;
00799 }
00800 
00801 
00802 
00803 // =====================================================================
00804 // ---------------------------------------------------------------------
00805 // ---------------------------------------------------------------------
00806 // =====================================================================
00807 /*
00808   \fn PROJ_SetSPECTSpecificParameters (Analytic Projection)
00809   \param ap_nbOfBins : 2 elements array containing transaxial number of bins
00810   \param a_nbOfProjections : number of views/projections
00811   \param a_firstAngle : angle of the first view
00812   \param a_lastAngle : angle of the last view
00813   \param ap_projectionAngles : an array containing angles for each view
00814   \param a_CORtoDetectorDistance : a distance between the center of rotation and the detector
00815   \param a_RotDirection : Rotation direction of the head (clockwise/counter-clockwise)
00816   \brief Deliver to the SPECT scanner object all informations provided from the acquisition parameters
00817   \details For analytical projection, this data is provided from the command-line options 
00818   \return 0 if success, positive value otherwise
00819 */
00820 int sScannerManager::PROJ_SetSPECTSpecificParameters(uint16_t* ap_nbOfBins, 
00821                                                      uint32_t a_nbOfProjections, 
00822                                                      FLTNB a_firstAngle, 
00823                                                      FLTNB a_stepAngle, 
00824                                                      FLTNB* ap_projectionAngles, 
00825                                                      FLTNB a_CORtoDetectorDistance,
00826                                                      string a_rotDirection)
00827 {
00828   if(m_verbose>=3) Cout("sScannerManager::PROJ_SetSPECTSpecificParameters ..."<< endl); 
00829     
00830   // Return error if wrong modality
00831   if (mp_Scanner->GetScannerType() != SCANNER_SPECT_CONVERGENT && mp_Scanner->GetScannerType() != SCANNER_SPECT_PINHOLE)
00832   {
00833     Cerr("***** sScannerManager::SetPETSpecificParameters()-> The scanner object is not of PET type !" << endl);
00834     return 1;
00835   }
00836   else
00837   {
00838     // Nb bins
00839     mp_Scanner->PROJ_SetSPECTNbBins(ap_nbOfBins);
00840     
00841     // Nb projections
00842     if(a_nbOfProjections == 0)
00843     {
00844       Cerr("***** sScannerManager::SetSPECTSpecificParameters()-> Error, SPECT analytic projection requires an user-specified number of projections !" << endl);
00845       return 1;
00846     }
00847     
00848     mp_Scanner->PROJ_SetSPECTNbProjections(a_nbOfProjections);
00849 
00850 
00851     // Projection angles initialized with either each angles, or calculated from first/last angle
00852     // By default, we chose the user-provided custom initialization for SPECT projection angles
00853     // If not initialized, we computed them from first/last angle
00854     if(ap_projectionAngles == NULL)
00855     {
00856       // If no custom initialization have been provided, then we check if we have first and last angles values for automatic initialization of the projection angles
00857       if(a_firstAngle<0 || a_stepAngle<0)
00858       {
00859         Cerr("***** sScannerManager::SetSPECTSpecificParameters()-> Error, SPECT projection requires to set the projection angles using either the '-SPECT_ang' or '-SPECT_c_ang' options !" << endl);
00860         return 1;
00861       }
00862       else
00863       {
00864         // Fill the SPECT_projection_angles array
00865         ap_projectionAngles = new FLTNB[a_nbOfProjections];
00866         ap_projectionAngles[0] = a_firstAngle;
00867         
00868         for(uint32_t a=1 ; a<a_nbOfProjections ; a++)
00869           ap_projectionAngles[a] = ap_projectionAngles[a-1] + a_stepAngle;
00870       }
00871     }
00872     
00873     if(mp_Scanner->PROJ_SetSPECTAngles(ap_projectionAngles) )
00874     {
00875       Cerr("***** sScannerManager::SetSPECTAngles() -> An error occured while trying to initialize SPECT projection angles !" << endl);
00876       return 1;
00877     }
00878 
00879     // CORtoDetectorDistance
00880     if(mp_Scanner->PROJ_SetSPECTCORtoDetectorDistance(a_CORtoDetectorDistance) )
00881     {
00882       Cerr("***** sScannerManager::SetPETSpecificParameters() -> An error occured while trying to initialize SPECT distance between center of rotation to detectors !" << endl);
00883       return 1;
00884     }
00885     
00886     // Nb bins
00887     mp_Scanner->PROJ_SetSPECTRotDirection(a_rotDirection);
00888   }
00889   
00890   return 0;
00891 }
00892 
00893 
00894 
00895 // =====================================================================
00896 // ---------------------------------------------------------------------
00897 // ---------------------------------------------------------------------
00898 // =====================================================================
00899 /*
00900   \fn GetSPECTSpecificParameters (Reconstruction)
00901   \param ap_nbOfProjections : number of views/projections
00902   \param ap_nbHeads : number of heads in the SPECT system
00903   \param ap_nbOfBins : 2 elements array containing transaxial number of bins
00904   \param ap_pixSizeXY : 2 elements array containing transaxial/axial pixel sizes
00905   \param ap_angles : an array containing angles for each view
00906   \param ap_CORtoDetectorDistance : a distance between the center of rotation and the detector  
00907   \param ap_headRotDirection : head rotation direction
00908   \brief Transfer geometric information recovered from the datafile to the scanner object
00909   \return 0 if success, positive value otherwise
00910 */
00911 int sScannerManager::GetSPECTSpecificParameters(uint16_t* ap_nbOfProjections, 
00912                                                 uint16_t* ap_nbHeads, 
00913                                                 uint16_t* ap_nbOfBins, 
00914                                                 FLTNB* ap_pixSizeXY,
00915                                                 FLTNB*& ap_angles, 
00916                                                 FLTNB*& ap_CORtoDetectorDistance,
00917                                                 int* ap_headRotDirection)
00918 {
00919   if(m_verbose>=3) Cout("sScannerManager::GetSPECTSpecificParameters ..."<< endl); 
00920     
00921   // Check modality
00922   if (mp_Scanner->GetScannerType() != SCANNER_SPECT_CONVERGENT && mp_Scanner->GetScannerType() != SCANNER_SPECT_PINHOLE)
00923   {
00924     Cerr("***** sScannerManager::PROJ_GetSPECTSpecificParameters()-> The scanner object is not of PET type !" << endl);
00925     return 1;
00926   }
00927   else
00928   {
00929     if (mp_Scanner->GetSPECTSpecificParameters(ap_nbOfProjections, ap_nbHeads, ap_nbOfBins, ap_pixSizeXY, ap_angles, ap_CORtoDetectorDistance, ap_headRotDirection) )
00930     {
00931       Cerr("***** sScannerManager::PROJ_GetSPECTSpecificParameters()-> A problem occurred while retrieving SPECT parameters from the scanner object !" << endl);
00932       return 1;
00933     }
00934     
00935   }
00936   return 0;
00937 }
 All Classes Files Functions Variables Typedefs Defines