![]() |
CASToR
1.0
Tomographic Reconstruction (PET/SPECT)
|
00001 00002 /* 00003 Implementation of class oProjectorManager 00004 00005 - separators: done 00006 - doxygen: done 00007 - default initialization: done 00008 - CASTOR_DEBUG: 00009 - CASTOR_VERBOSE: 00010 */ 00011 00018 #include "oProjectorManager.hh" 00019 #include "sOutputManager.hh" 00020 #include "sAddonManager.hh" 00021 #include "iDataFilePET.hh" 00022 00023 // ===================================================================== 00024 // --------------------------------------------------------------------- 00025 // --------------------------------------------------------------------- 00026 // ===================================================================== 00027 00028 oProjectorManager::oProjectorManager() 00029 { 00030 // Scanner and image dimensions 00031 mp_Scanner = NULL; 00032 mp_ImageDimensionsAndQuantification = NULL; 00033 // Data file (used to get some info about TOF bins and POI) 00034 mp_DataFile = NULL; 00035 // TOF and POI options 00036 m_applyTOF = false; 00037 m_applyPOI = false; 00038 m_nbTOFBins = -1; 00039 // Computation strategy for projection lines 00040 m_computationStrategy = -1; 00041 // Forward and backward options for projectors 00042 m_optionsForward = ""; 00043 m_optionsBackward = ""; 00044 // Common options 00045 m_optionsCommon = ""; 00046 // Forward and backward projectors 00047 mp_SystemMatrixForward = NULL; 00048 mp_SystemMatrixBackward = NULL; 00049 mp_ProjectorForward = NULL; 00050 mp_ProjectorBackward = NULL; 00051 m_UseSystemMatrixForward = false; 00052 m_UseSystemMatrixBackward = false; 00053 m_UseProjectorForward = false; 00054 m_UseProjectorBackward = false; 00055 m_UseMatchedProjectors = false; 00056 // Forward and backward projection lines (as many as threads) 00057 m2p_ProjectionLines = NULL; 00058 // Verbosity 00059 m_verbose = 0; 00060 // Not checked yet 00061 m_checked = false; 00062 // Not initialized yet 00063 m_initialized = false; 00064 } 00065 00066 // ===================================================================== 00067 // --------------------------------------------------------------------- 00068 // --------------------------------------------------------------------- 00069 // ===================================================================== 00070 00071 00072 oProjectorManager::~oProjectorManager() 00073 { 00074 // Go through the destructor only if the object was initialized 00075 if (m_initialized) 00076 { 00077 // Delete projection lines 00078 for (int th=0; th<mp_ImageDimensionsAndQuantification->GetNbThreadsForProjection(); th++) 00079 if (m2p_ProjectionLines[th]) delete m2p_ProjectionLines[th]; 00080 if (m2p_ProjectionLines) delete[] m2p_ProjectionLines; 00081 // Delete projectors 00082 if (m_UseProjectorForward) delete mp_ProjectorForward; 00083 if (m_UseSystemMatrixForward) delete mp_SystemMatrixForward; 00084 if (!m_UseMatchedProjectors) 00085 { 00086 if (m_UseProjectorBackward) delete mp_ProjectorBackward; 00087 if (m_UseSystemMatrixBackward) delete mp_SystemMatrixBackward; 00088 } 00089 } 00090 } 00091 00092 // ===================================================================== 00093 // --------------------------------------------------------------------- 00094 // --------------------------------------------------------------------- 00095 // ===================================================================== 00096 00097 bool oProjectorManager::IsForwardOperatorCompatibleWithSPECTAttenuationCorrection() 00098 { 00099 // Case for a vProjector 00100 if (m_UseProjectorForward) return mp_ProjectorForward->GetCompatibilityWithSPECTAttenuationCorrection(); 00101 // Case for a system matrix 00102 else return mp_SystemMatrixForward->GetCompatibilityWithSPECTAttenuationCorrection(); 00103 } 00104 00105 // ===================================================================== 00106 // --------------------------------------------------------------------- 00107 // --------------------------------------------------------------------- 00108 // ===================================================================== 00109 00110 bool oProjectorManager::IsBackwardOperatorCompatibleWithSPECTAttenuationCorrection() 00111 { 00112 // Case for a vProjector 00113 if (m_UseProjectorBackward) return mp_ProjectorBackward->GetCompatibilityWithSPECTAttenuationCorrection(); 00114 // Case for a system matrix 00115 else return mp_SystemMatrixBackward->GetCompatibilityWithSPECTAttenuationCorrection(); 00116 } 00117 00118 // ===================================================================== 00119 // --------------------------------------------------------------------- 00120 // --------------------------------------------------------------------- 00121 // ===================================================================== 00122 00123 int oProjectorManager::CheckParameters() 00124 { 00125 // Check scanner 00126 if (mp_Scanner==NULL) 00127 { 00128 Cerr("***** oProjectorManager::CheckParameters() -> No scanner provided !" << endl); 00129 return 1; 00130 } 00131 // Check image dimensions 00132 if (mp_ImageDimensionsAndQuantification==NULL) 00133 { 00134 Cerr("***** oProjectorManager::CheckParameters() -> No image dimensions provided !" << endl); 00135 return 1; 00136 } 00137 // Check data file 00138 if (mp_DataFile==NULL) 00139 { 00140 Cerr("***** oProjectorManager::CheckParameters() -> No data file provided !" << endl); 00141 return 1; 00142 } 00143 // Check computation strategy 00144 if ( m_computationStrategy != IMAGE_COMPUTATION_STRATEGY && 00145 m_computationStrategy != FIXED_LIST_COMPUTATION_STRATEGY && 00146 m_computationStrategy != ADAPTATIVE_LIST_COMPUTATION_STRATEGY ) 00147 { 00148 Cerr("***** oProjectorManager::CheckParameters() -> Unknown computation strategy provided !" << endl); 00149 return 1; 00150 } 00151 // Check forward projector options 00152 if (m_optionsForward=="") 00153 { 00154 Cerr("***** oProjectorManager::CheckParameters() -> No forward projector options provided !" << endl); 00155 return 1; 00156 } 00157 // Check backward projector options 00158 if (m_optionsBackward=="") 00159 { 00160 Cerr("***** oProjectorManager::CheckParameters() -> No backward projector options provided !" << endl); 00161 return 1; 00162 } 00163 // Check verbosity 00164 if (m_verbose<0) 00165 { 00166 Cerr("***** oProjectorManager::CheckParameters() -> Wrong verbosity level provided !" << endl); 00167 return 1; 00168 } 00169 // Normal end 00170 m_checked = true; 00171 return 0; 00172 } 00173 00174 // ===================================================================== 00175 // --------------------------------------------------------------------- 00176 // --------------------------------------------------------------------- 00177 // ===================================================================== 00178 00179 int oProjectorManager::Initialize() 00180 { 00181 // Forbid initialization without check 00182 if (!m_checked) 00183 { 00184 Cerr("***** oProjectorManager::Initialize() -> Must call CheckParameters() before Initialize() !" << endl); 00185 return 1; 00186 } 00187 00188 // Verbose 00189 if (m_verbose>=1) Cout("oProjectorManager::Initialize() -> Initialize projectors and projection lines" << endl); 00190 00191 // TOF-PET specific stuff 00192 FLTNB tof_resolution = -1.; 00193 if (mp_DataFile->GetDataType()==TYPE_PET) 00194 { 00195 // Cast the datafile pointer 00196 iDataFilePET* p_pet_datafile = (dynamic_cast<iDataFilePET*>(mp_DataFile)); 00197 // Case of TOF information in the datafile 00198 if (p_pet_datafile->GetTOFInfoFlag()) 00199 { 00200 // Case where it is asked to ignore TOF info 00201 if (p_pet_datafile->GetIgnoreTOFFlag()) 00202 { 00203 m_applyTOF = false; 00204 m_nbTOFBins = 1; 00205 } 00206 // Otherwise, we use TOF 00207 else 00208 { 00209 // TODO: set tof bin size 00210 // Get the number of TOF bins from the data file 00211 m_nbTOFBins = p_pet_datafile->GetNbBinsTOF(); 00212 // Get the TOF resolution from the data file, if we apply TOF 00213 tof_resolution = p_pet_datafile->GetResolutionTOF(); 00214 } 00215 } 00216 // Case no TOF 00217 else 00218 { 00219 m_applyTOF = false; 00220 m_nbTOFBins = 1; 00221 } 00222 } 00223 else m_nbTOFBins = 1; 00224 00225 // Look if we must apply POI or not 00226 if (mp_DataFile->GetPOIInfoFlag() && !mp_DataFile->GetIgnorePOIFlag()) m_applyPOI = true; 00227 else m_applyPOI = false; 00228 // Get POI resolution from the data file 00229 FLTNB* poi_resolution = mp_DataFile->GetResolutionPOI(); 00230 00231 // Compare projector options to know if we use matched ones for forward and backward operations 00232 if (m_optionsForward==m_optionsBackward) m_UseMatchedProjectors = true; 00233 else m_UseMatchedProjectors = false; 00234 00235 // Parse projector options and initialize them 00236 if (ParseOptionsAndInitializeProjectors()) 00237 { 00238 Cerr("***** oProjectorManager::Initialize() -> A problem occured while parsing projector options and initializing it !" << endl); 00239 return 1; 00240 } 00241 00242 // Initialize as many projection lines as threads 00243 m2p_ProjectionLines = new oProjectionLine*[mp_ImageDimensionsAndQuantification->GetNbThreadsForProjection()]; 00244 for (int th=0; th<mp_ImageDimensionsAndQuantification->GetNbThreadsForProjection(); th++) 00245 { 00246 m2p_ProjectionLines[th] = new oProjectionLine(); 00247 m2p_ProjectionLines[th]->SetThreadNumber(th); 00248 m2p_ProjectionLines[th]->SetMatchedProjectors(m_UseMatchedProjectors); 00249 m2p_ProjectionLines[th]->SetNbTOFBins(m_nbTOFBins); 00250 m2p_ProjectionLines[th]->SetTOFResolution(tof_resolution); 00251 m2p_ProjectionLines[th]->SetPOIResolution(poi_resolution); 00252 m2p_ProjectionLines[th]->SetImageDimensionsAndQuantification(mp_ImageDimensionsAndQuantification); 00253 m2p_ProjectionLines[th]->SetComputationStrategy(m_computationStrategy); 00254 m2p_ProjectionLines[th]->SetForwardProjector(mp_ProjectorForward); 00255 m2p_ProjectionLines[th]->SetBackwardProjector(mp_ProjectorBackward); 00256 m2p_ProjectionLines[th]->SetVerbose(m_verbose); 00257 if (m2p_ProjectionLines[th]->CheckParameters()) 00258 { 00259 Cerr("***** oProjectorManager::Initialize() -> An error occured while checking parameters of an oProjectionLine !" << endl); 00260 return 1; 00261 } 00262 if (m2p_ProjectionLines[th]->Initialize()) 00263 { 00264 Cerr("***** oProjectorManager::Initialize() -> An error occured while initializing an oProjectionLine !" << endl); 00265 return 1; 00266 } 00267 } 00268 00269 // Normal end 00270 m_initialized = true; 00271 return 0; 00272 } 00273 00274 // ===================================================================== 00275 // --------------------------------------------------------------------- 00276 // --------------------------------------------------------------------- 00277 // ===================================================================== 00278 00279 int oProjectorManager::ParseOptionsAndInitializeProjectors() 00280 { 00281 string projector = ""; 00282 string list_options = ""; 00283 string file_options = ""; 00284 00285 // This is for the automatic initialization of the projectors 00286 typedef vProjector *(*maker_projector) (); 00287 00288 // --------------------------------------------------------------------------------------------------- 00289 // Manage forward projector 00290 // --------------------------------------------------------------------------------------------------- 00291 00292 // ______________________________________________________________________________ 00293 // Get the projector name in the options and isolate the real projector's options 00294 00295 // Search for a colon ":", this indicates that a configuration file is provided after the projector name 00296 size_t colon = m_optionsForward.find_first_of(":"); 00297 size_t comma = m_optionsForward.find_first_of(","); 00298 00299 // Case 1: we have a colon 00300 if (colon!=string::npos) 00301 { 00302 // Get the projector name before the colon 00303 projector = m_optionsForward.substr(0,colon); 00304 // Get the configuration file after the colon 00305 file_options = m_optionsForward.substr(colon+1); 00306 // List of options is empty 00307 list_options = ""; 00308 } 00309 // Case 2: we have a comma 00310 else if (comma!=string::npos) 00311 { 00312 // Get the projector name before the first comma 00313 projector = m_optionsForward.substr(0,comma); 00314 // Get the list of options after the first comma 00315 list_options = m_optionsForward.substr(comma+1); 00316 // Configuration file is empty 00317 file_options = ""; 00318 } 00319 // Case 3: no colon and no comma (a single projector name) 00320 else 00321 { 00322 // Get the projector name 00323 projector = m_optionsForward; 00324 // List of options is empty 00325 list_options = ""; 00326 // Build the default configuration file 00327 file_options = sOutputManager::GetInstance()->GetPathToConfigDir() + "/projector/" + projector + ".conf"; 00328 } 00329 00330 // ______________________________________________________________________________ 00331 // Case 1: projector is equal to keyword 'matrix', then use a system matrix 00332 if (projector==SYSTEM_MATRIX_KEYWORD) 00333 { 00334 mp_ProjectorForward = NULL; 00335 m_UseProjectorForward = false; 00336 m_UseSystemMatrixForward = true; 00337 // TODO: forbid TOF in PET with system matrix 00338 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> Loading of custom system matrices is not yet implemented !" << endl); 00339 return 1; 00340 } 00341 // ______________________________________________________________________________ 00342 // Case 2: on-the-fly projector 00343 else 00344 { 00345 // Unset system matrix 00346 mp_SystemMatrixForward = NULL; 00347 m_UseSystemMatrixForward = false; 00348 // Set projector on 00349 m_UseProjectorForward = true; 00350 // Get projector's listfrom addon manager 00351 std::map <string,maker_projector> list = sAddonManager::GetInstance()->mp_listOfProjectors; 00352 // Create the projector 00353 if (list[projector]) mp_ProjectorForward = list[projector](); 00354 else 00355 { 00356 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> Projector '" << projector << "' does not exist !" << endl); 00357 return 1; 00358 } 00359 // Set parameters 00360 mp_ProjectorForward->SetScanner(mp_Scanner); 00361 if (mp_ProjectorForward->SetImageDimensionsAndQuantification(mp_ImageDimensionsAndQuantification)) 00362 { 00363 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while setting the image dimensions of the forward projector !" << endl); 00364 return 1; 00365 } 00366 if (mp_ProjectorForward->SetTOFAndPOIOptions(mp_DataFile->GetDataMode(),m_applyTOF,m_applyPOI)) 00367 { 00368 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while setting the TOF and POI options of the forward projector !" << endl); 00369 return 1; 00370 } 00371 mp_ProjectorForward->SetVerbose(m_verbose); 00372 // Provide common options list 00373 if (mp_ProjectorForward->ReadCommonOptionsList(m_optionsCommon)) 00374 { 00375 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while parsing and reading forward projector's common options !" << endl); 00376 return 1; 00377 } 00378 // Provide configuration file if any 00379 if (file_options!="" && mp_ProjectorForward->ReadConfigurationFile(file_options)) 00380 { 00381 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while parsing and reading forward projector's configuration file !" << endl); 00382 return 1; 00383 } 00384 // Provide options if any 00385 if (list_options!="" && mp_ProjectorForward->ReadOptionsList(list_options)) 00386 { 00387 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while parsing and reading forward projector's options !" << endl); 00388 return 1; 00389 } 00390 // Check parameters 00391 if (mp_ProjectorForward->CheckParameters()) 00392 { 00393 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while checking forward projector parameters !" << endl); 00394 return 1; 00395 } 00396 // Initialize the projector 00397 if (mp_ProjectorForward->Initialize()) 00398 { 00399 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while initializing the forward projector !" << endl); 00400 return 1; 00401 } 00402 } 00403 00404 // --------------------------------------------------------------------------------------------------- 00405 // Manage backward projector 00406 // --------------------------------------------------------------------------------------------------- 00407 00408 // If options are the same, then forward and backward are the same 00409 if (m_UseMatchedProjectors) 00410 { 00411 // In this case, matched projectors 00412 m_UseSystemMatrixBackward = m_UseSystemMatrixForward; 00413 m_UseProjectorBackward = m_UseProjectorForward; 00414 mp_SystemMatrixBackward = mp_SystemMatrixForward; 00415 mp_ProjectorBackward = mp_ProjectorForward; 00416 } 00417 // Else, unmatched projectors 00418 else 00419 { 00420 // ______________________________________________________________________________ 00421 // Get the projector name in the options and isolate the real projector's options 00422 00423 // Search for a colon ":", this indicates that a configuration file is provided after the projector name 00424 colon = m_optionsBackward.find_first_of(":"); 00425 comma = m_optionsBackward.find_first_of(","); 00426 00427 // Case 1: we have a colon 00428 if (colon!=string::npos) 00429 { 00430 // Get the projector name before the colon 00431 projector = m_optionsBackward.substr(0,colon); 00432 // Get the configuration file after the colon 00433 file_options = m_optionsBackward.substr(colon+1); 00434 // List of options is empty 00435 list_options = ""; 00436 } 00437 // Case 2: we have a comma 00438 else if (comma!=string::npos) 00439 { 00440 // Get the projector name before the first comma 00441 projector = m_optionsBackward.substr(0,comma); 00442 // Get the list of options after the first comma 00443 list_options = m_optionsBackward.substr(comma+1); 00444 // Configuration file is empty 00445 file_options = ""; 00446 } 00447 // Case 3: no colon and no comma (a single projector name) 00448 else 00449 { 00450 // Get the projector name 00451 projector = m_optionsBackward; 00452 // List of options is empty 00453 list_options = ""; 00454 // Build the default configuration file 00455 file_options = sOutputManager::GetInstance()->GetPathToConfigDir() + "/projector/" + projector + ".conf"; 00456 } 00457 00458 // ______________________________________________________________________________ 00459 // Case 1: projector is equal to keyword 'matrix', then use a system matrix 00460 if (projector==SYSTEM_MATRIX_KEYWORD) 00461 { 00462 mp_ProjectorBackward = NULL; 00463 m_UseProjectorBackward = false; 00464 m_UseSystemMatrixBackward = true; 00465 // TODO: forbid TOF in PET with system matrix 00466 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> Loading of custom system matrices is not yet implemented !" << endl); 00467 return 1; 00468 } 00469 // ______________________________________________________________________________ 00470 // Case 2: on-the-fly projector 00471 else 00472 { 00473 // Unset system matrix 00474 mp_SystemMatrixBackward = NULL; 00475 m_UseSystemMatrixBackward = false; 00476 // Set projector on 00477 m_UseProjectorBackward = true; 00478 // Get projector's listfrom addon manager 00479 std::map <string,maker_projector> list = sAddonManager::GetInstance()->mp_listOfProjectors; 00480 // Create the projector 00481 if (list[projector]) mp_ProjectorBackward = list[projector](); 00482 else 00483 { 00484 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> Projector '" << projector << "' does not exist !" << endl); 00485 return 1; 00486 } 00487 // Set parameters 00488 mp_ProjectorBackward->SetScanner(mp_Scanner); 00489 if (mp_ProjectorBackward->SetImageDimensionsAndQuantification(mp_ImageDimensionsAndQuantification)) 00490 { 00491 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while setting the image dimensions of the backward projector !" << endl); 00492 return 1; 00493 } 00494 if (mp_ProjectorBackward->SetTOFAndPOIOptions(mp_DataFile->GetDataMode(),m_applyTOF,m_applyPOI)) 00495 { 00496 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while setting the TOF and POI of the backward projector !" << endl); 00497 return 1; 00498 } 00499 mp_ProjectorBackward->SetVerbose(m_verbose); 00500 // Provide common options list 00501 if (mp_ProjectorBackward->ReadCommonOptionsList(m_optionsCommon)) 00502 { 00503 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while parsing and reading backward projector's common options !" << endl); 00504 return 1; 00505 } 00506 // Provide configuration file if any 00507 if (file_options!="" && mp_ProjectorBackward->ReadConfigurationFile(file_options)) 00508 { 00509 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while parsing and reading backward projector's configuration file !" << endl); 00510 return 1; 00511 } 00512 // Provide options if any 00513 if (list_options!="" && mp_ProjectorBackward->ReadOptionsList(list_options)) 00514 { 00515 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while parsing and reading backward projector's options !" << endl); 00516 return 1; 00517 } 00518 // Check parameters 00519 if (mp_ProjectorBackward->CheckParameters()) 00520 { 00521 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while checking backward projector parameters !" << endl); 00522 return 1; 00523 } 00524 // Initialize the projector 00525 if (mp_ProjectorBackward->Initialize()) 00526 { 00527 Cerr("***** oProjectorManager::ParseOptionsAndInitializeProjectors() -> A problem occured while initializing backward projector !" << endl); 00528 return 1; 00529 } 00530 } 00531 } 00532 00533 // Normal end 00534 return 0; 00535 } 00536 00537 // ===================================================================== 00538 // --------------------------------------------------------------------- 00539 // --------------------------------------------------------------------- 00540 // ===================================================================== 00541 00542 oProjectionLine* oProjectorManager::ComputeProjectionLine(vEvent* ap_Event, int a_th) 00543 { 00544 #ifdef CASTOR_DEBUG 00545 if (!m_initialized) 00546 { 00547 Cerr("***** oProjectorManager::ComputeProjectionLine() -> Called while not initialized !" << endl); 00548 Exit(EXIT_DEBUG); 00549 } 00550 #endif 00551 00552 #ifdef CASTOR_VERBOSE 00553 if (m_verbose>=10) Cout("oProjectorManager::ComputeProjectionLine() -> Compute a projection line" << endl); 00554 #endif 00555 00556 // Get the list of indices 00557 uint32_t *index1 = ap_Event->GetEventID1(); 00558 uint32_t *index2 = ap_Event->GetEventID2(); 00559 int nb_indices = ap_Event->GetNbLines(); 00560 00561 // Clean the projection line 00562 m2p_ProjectionLines[a_th]->Reset(); 00563 00564 // With list-mode data, we may need POI and/or TOF measurements 00565 if (ap_Event->GetDataMode()==MODE_LIST) 00566 { 00567 // Set POI measurement 00568 if (m_applyPOI) 00569 { 00570 // For PET 00571 if (ap_Event->GetDataType()==TYPE_PET) 00572 { 00573 // Have to dynamic_cast the event into a iEventPETList to access the GetPOI functions 00574 m2p_ProjectionLines[a_th]->SetPOI1((dynamic_cast<iEventListPET*>(ap_Event))->GetPOI1()); 00575 m2p_ProjectionLines[a_th]->SetPOI2((dynamic_cast<iEventListPET*>(ap_Event))->GetPOI2()); 00576 } 00577 // For SPECT 00578 if (ap_Event->GetDataType()==TYPE_SPECT) 00579 { 00580 // By convention in SPECT, the second end point is in the camera (the first one being outside) 00581 //m2p_ProjectionLines[a_th]->SetPOI2((dynamic_cast<iEventListModeSPECT*>(ap_Event))->GetPOI()); 00582 } 00583 // For transmission 00584 if (ap_Event->GetDataType()==TYPE_TRANSMISSION) 00585 { 00586 ; 00587 } 00588 } 00589 // Set TOF measurement (only for PET obviously) 00590 if (m_applyTOF && ap_Event->GetDataType()==TYPE_PET) 00591 { 00592 // Have to dynamic_cast the event into a iEventPETList to access the GetTOF function 00593 m2p_ProjectionLines[a_th]->SetTOFMeasurement((dynamic_cast<iEventListPET*>(ap_Event))->GetTOFMeasurement()); 00594 } 00595 } 00596 00597 // Project forward (and also compute line length) 00598 int return_value = 0; 00599 if (m_UseProjectorForward) 00600 return_value = mp_ProjectorForward->Project( FORWARD, m2p_ProjectionLines[a_th], index1, index2, nb_indices ); 00601 else if (m_UseSystemMatrixForward) 00602 return_value = mp_SystemMatrixForward->Project( FORWARD, m2p_ProjectionLines[a_th], index1, index2, nb_indices ); 00603 if (return_value) 00604 { 00605 Cerr("***** oProjectorManager::ComputeProjectionLine() -> A problem occured while forward projecting an event !" << endl); 00606 return NULL; 00607 } 00608 00609 // Project backward 00610 if (!m_UseMatchedProjectors) 00611 { 00612 // Then project 00613 if (m_UseProjectorBackward) 00614 return_value = mp_ProjectorBackward->Project( BACKWARD, m2p_ProjectionLines[a_th], index1, index2, nb_indices ); 00615 else if (m_UseSystemMatrixBackward) 00616 return_value = mp_SystemMatrixBackward->Project( BACKWARD, m2p_ProjectionLines[a_th], index1, index2, nb_indices); 00617 if (return_value) 00618 { 00619 Cerr("***** oProjectorManager::ComputeProjectionLine() -> A problem occured while backward projecting an event !" << endl); 00620 return NULL; 00621 } 00622 } 00623 00624 // Return the line 00625 return m2p_ProjectionLines[a_th]; 00626 } 00627 00628 // ===================================================================== 00629 // --------------------------------------------------------------------- 00630 // --------------------------------------------------------------------- 00631 // =====================================================================