![]() |
CASToR
1.0
Tomographic Reconstruction (PET/SPECT)
|
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 }