CASToR  1.1
Tomographic Reconstruction (PET/SPECT)
 All Classes Files Functions Variables Typedefs Macros Groups Pages
sScannerManager.cc
Go to the documentation of this file.
1 
2 /*
3  Implementation of class sScannerManager
4 
5  - separators: X
6  - doxygen: X
7  - default initialization: X
8  - CASTOR_DEBUG: none
9  - CASTOR_VERBOSE: X
10 */
11 
18 #include "sScannerManager.hh"
19 #include "sAddonManager.hh"
20 
21 // Singleton : set pointer to object to NULL
23 
24 // =====================================================================
25 // ---------------------------------------------------------------------
26 // ---------------------------------------------------------------------
27 // =====================================================================
28 /*
29  \brief sScannerManager constructor.
30  \details It is private at this class is singleton.
31  This class should be instanciated using the GetInstance() function
32  Initialize the member variables to their default values.
33 */
35 {
36  mp_Scanner = NULL;
37  m_verbose = -1;
39  m_scannerName = "";
40  m_hasUserScannerFile = false;
42  m_allParametersChecked = false;
43  m_saveLUTFlag = false;
44 }
45 
46 // =====================================================================
47 // ---------------------------------------------------------------------
48 // ---------------------------------------------------------------------
49 // =====================================================================
50 /*
51  \brief sScannerManager destructor.
52 */
54 {
55  if (mp_Scanner != NULL) delete mp_Scanner;
56 }
57 
58 // =====================================================================
59 // ---------------------------------------------------------------------
60 // ---------------------------------------------------------------------
61 // =====================================================================
62 /*
63  \fn CheckParameters
64  \brief Check if all parameters have been correctly initialized, and call the CheckParameters function of the scanner object
65  \return 0 if success. Positive value otherwise
66 */
68 {
70  // Check mandatory parameters
71  if (mp_Scanner == NULL)
72  {
73  Cerr("***** sScannerManager::CheckParameters() -> Scanner object not initialized !" << endl);
74  return 1;
75  }
77  {
78  Cerr("***** sScannerManager::CheckParameters() -> Scanner file type (generic or user provided) not initialized !" << endl);
79  return 1;
80  }
81  if (m_scannerName.empty())
82  {
83  Cerr("***** sScannerManager::CheckParameters() -> Scanner name not initialized" << endl);
84  return 1;
85  }
86  if (m_pathToScannerFile.empty())
87  {
88  Cerr("***** sScannerManager::CheckParameters() -> Path to scanner file not initialized !" << endl);
89  return 1;
90  }
91  if (m_verbose<0)
92  {
93  Cerr("***** sScannerManager::CheckParameters() -> Verbosity level not initialized !" << endl);
94  return 1;
95  }
96  // Check parameters of the scanner object
98  {
99  Cerr("***** sScannerManager::CheckParameters() -> A problem occurred while checking Scanner Object parameters !" << endl);
100  return 1;
101  }
102  // All parameters are checked
103  m_allParametersChecked = true;
104  // End
105  return 0;
106 }
107 
108 // =====================================================================
109 // ---------------------------------------------------------------------
110 // ---------------------------------------------------------------------
111 // =====================================================================
112 /*
113  \fn Initialize
114  \brief Initialization :
115  - check if all parameters of the manager have been checked
116  - call the initialization function of the scanner object
117  \return 0 if success. Positive value otherwise
118 */
120 {
122  // Parameters checked ?
124  {
125  Cerr("***** sScannerManager::Initialize() -> Parameters have not been checked !" << endl);
126  return 1;
127  }
128  // Verbose
129  if (m_verbose>=VERBOSE_LIGHT) Cout("sScannerManager::Initialize() -> From scanner " << m_scannerName << endl);
130  // Initialize the scanner object
131  if (mp_Scanner->Initialize())
132  {
133  Cerr("***** sScannerManager::Initialize() -> A problem occurred while initializing Scanner Object !" << endl);
134  return 1;
135  }
136  // End
137  return 0;
138 }
139 
140 // =====================================================================
141 // ---------------------------------------------------------------------
142 // ---------------------------------------------------------------------
143 // =====================================================================
144 /*
145  \fn ShowScannersDescription
146  \brief Get the description associated to the different scanners and print all on screen.
147  Walk through the scanner repository and look for the keyword "description" in .geom file and .hscan file.
148  \return 0 if success, positive value otherwise
149  \todo Check everything output correctly for all implemented scanners
150 */
152 {
154 
155  // Return when using MPI and mpi_rank is not 0
156  #ifdef CASTOR_MPI
157  int mpi_rank = 0;
158  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
159  if (mpi_rank!=0) return 0;
160  #endif
161 
162  // Verbose
163  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::ShowScannersDescription ..."<< endl);
164 
165  // Gather all the available scanner from the repository
166  vector<string> list_scanner_names;
167  if (GetAvailableScanners(&list_scanner_names))
168  {
169  Cerr("***** sScannerManager::ShowScannersDescription() -> A problem occurred while recovering scanner names from the scanner repository !" << endl);
170  return 1;
171  }
172 
173  // Print-out descriptions
174  cout << endl << "Here is the list of all available scanners in the repository along with their options:" << endl << endl;
175  for (unsigned int iter = 0; iter!=list_scanner_names.size(); iter++)
176  {
177  // Get the actual scanner in temporary local variable
178  string scanner_file = sOutputManager::GetInstance()->GetPathToConfigDir() + "scanner" + OS_SEP;
179  // Print out the name of this scanner
180  cout << "------------------------------------------------------------------" << endl;
181  cout << "----- \"" << list_scanner_names[iter] << "\"" << endl;
182  cout << "------------------------------------------------------------------" << endl;
183  // Proceed
184  scanner_file.append(list_scanner_names[iter]);
185  // Look for the "description" keyword in the .geom or .hscan file
186  string description;
187  ReadDataASCIIFile(scanner_file, "description", &description, 1, 1);
188  // Print out description
189  cout << description << endl << endl;
190  }
191  return 0;
192 }
193 
194 // =====================================================================
195 // ---------------------------------------------------------------------
196 // ---------------------------------------------------------------------
197 // =====================================================================
198 /*
199  \fn FindScannerSystem
200  \param a_scannerName : string containing name of the required scanner
201  \brief Look for a file matching with the scanner name in parameter inside the scanner repository
202  \return 0 if success (scanner found). Positive value otherwise
203 */
204 int sScannerManager::FindScannerSystem(string a_scannerName)
205 {
207 
208  // Check emptiness
209  if (a_scannerName.empty())
210  {
211  Cerr("***** sScannerManager::FindScannerSystem() -> scanner name is empty !" << endl);
212  return 1;
213  }
214 
215  // Verbose
216  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::FindScannerSystem() -> Search for scanner " << a_scannerName << " in the configuration directory" << endl);
217 
218  // Get the list of scanner from the repository
219  vector<string> repository_scanner_names;
220  if (GetAvailableScanners(&repository_scanner_names))
221  {
222  Cerr("***** sScannerManager::FindScannerSystem() -> A problem occurred while recovering scanner names from the scanner repository !" << endl);
223  return 1;
224  }
225 
226  // Set the scanner name
227  m_scannerName = a_scannerName;
229 
230  // String to recover generic/user-made scanner file
231  string generic_scanner_file, user_scanner_file;
232 
233  // Loop over the scanner available in the repository, and check if the scanner name match with any of these
234  for (unsigned int index_name=0 ; index_name<repository_scanner_names.size() ; index_name++)
235  {
236  string gfile = a_scannerName;
237  string ufile = a_scannerName;
238  // Check if the scanner match a geom file (generic_scanner_file)
239  if (gfile.append(".geom") == repository_scanner_names[index_name])
240  {
241  generic_scanner_file = a_scannerName;
242  generic_scanner_file.append(".geom");
244  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Matched generic file for the scanner system: " << repository_scanner_names[index_name] << endl);
245  }
246  // Check if the scanner match an user file (user provided LUT)
247  if (ufile.append(".hscan") == repository_scanner_names[index_name])
248  {
249  user_scanner_file = a_scannerName;
250  user_scanner_file.append(".hscan");
251  m_hasUserScannerFile = true;
252  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> matched custom LUT for the scanner system: " << repository_scanner_names[index_name] << endl);
253  }
254  }
255 
256  // When both a generic file and user-provided LUT exist for this system, the generic file is selected by default
258  {
260  {
261  Cerr("***** WARNING sScannerManager::FindScannerSystem() -> Both a generic file and user-provided LUT have been detected for the " << a_scannerName << " system." << endl);
262  Cerr(" The generic file (*.geom) will be selected by default." << endl);
263  }
264  m_hasUserScannerFile = false;
265  }
266 
267  // Initialize m_pathToScannerFile member variable
268  if (m_hasGenericScannerFile) m_pathToScannerFile.append(generic_scanner_file.c_str());
269  else if (m_hasUserScannerFile) m_pathToScannerFile.append(user_scanner_file.c_str());
270  // Unknown scanner, output scanner description and throw error
271  else
272  {
273  Cerr("***** sScannerManager::FindScannerSystem() -> Scanner '"<< a_scannerName <<
274  "' is not known in the scanner repository. Please provide a LUT/generic file for this scanner in the scanner repository in: " <<
275  sOutputManager::GetInstance()->GetPathToConfigDir() << "scanner" << OS_SEP << endl << endl;);
277  return 1;
278  }
279  // End
280  return 0;
281 }
282 
283 // =====================================================================
284 // ---------------------------------------------------------------------
285 // ---------------------------------------------------------------------
286 // =====================================================================
287 /*
288  \fn BuildScannerObject()
289  \brief Instantiate the specific scanner object related to the modality, and set verbosity of scanner object
290  \todo delete the check on modality once all scanner classes will be completely implemented ?
291  \return 0 if success. Positive value otherwise
292 */
294 {
296 
297  // Verbose
298  if (m_verbose>=VERBOSE_NORMAL) Cout("sScannerManager::BuildScannerObject() -> Start building"<< endl);
299 
300  // Check scanner modality
301  string scanner_type;
302  typedef vScanner *(*maker_scanner) ();
303 
304  // Get the system type from the value of the modality field inside the scanner header
305  if (ReadDataASCIIFile(m_pathToScannerFile, "modality", &scanner_type, 1, KEYWORD_MANDATORY) == 1)
306  {
307  Cerr("***** sScannerManager::BuildScannerObject() -> 'Modality' field not found in the header of the scanner configuration file at :"<< endl);
308  Cerr("***** " << m_pathToScannerFile << endl);
309  return 1;
310  }
311 
312  // Get scanner's list from addon manager
313  std::map <string,maker_scanner> list = sAddonManager::GetInstance()->mp_listOfScannerTypes;
314 
315  // Instanciate the scanner class corresponding to the modality, throw error if no match
316  if (list[scanner_type]) mp_Scanner = list[scanner_type]();
317  else
318  {
319  Cerr("***** sScannerManager::BuildScannerObject() -> Modality '" << scanner_type << "' is unknown !" << endl);
321  return 1;
322  }
323 
324  // Set scanner verbosity
326 
327  // End
328  return 0;
329 }
330 
331 // =====================================================================
332 // ---------------------------------------------------------------------
333 // ---------------------------------------------------------------------
334 // =====================================================================
335 /*
336  \fn GetGeometricInfoFromDatafile
337  \param a_path : string containing the path to datafile header
338  \brief Call the specialized function of the scanner object in order to
339  get geometric informations from the datafile header
340  \return 0 if success. Positive value otherwise
341 */
343 {
345 
346  // Verbose
347  if (m_verbose>=VERBOSE_NORMAL) Cout("sScannerManager::GetGeometricInfoFromDatafile() -> Look for acquisition specific settings into datafile header"<< endl);
348 
349  // Get information
351  {
352  Cerr("***** sScannerManager::GetGeometricInfoFromDatafile() -> An error occurred while getting information from the datafile." << endl);
353  return 1;
354  }
355 
356  // End
357  return 0;
358 }
359 
360 // =====================================================================
361 // ---------------------------------------------------------------------
362 // ---------------------------------------------------------------------
363 // =====================================================================
364 /*
365  \fn InstantiateScanner
366  \brief Instantiate scanner using the related function in the scanner classes
367  \todo delete the check on scanner type once all scanner classes will be completely implemented.
368  \return 0 if success. Positive value otherwise
369 */
371 {
373 
374  // Verbose
375  if (m_verbose>=VERBOSE_NORMAL) Cout("sScannerManager::InstantiateScanner() -> Instantiate the scanner geometry structure"<< endl);
376 
377  // Check if the scanner object is known (TODO : delete this check once all scanner classes will be completely implemented)
378  if (mp_Scanner->GetScannerType()<0)
379  {
380  Cerr("***** sScannerManager::BuildScannerObject() -> Unknow scanner type !" << endl);
381  return 1;
382  }
383 
384  // Instantiate geometry
386  {
387  Cerr("***** sScannerManager::InstantiateScanner() -> An error occurred while instanciating the Scanner object !" << endl);
388  return 1;
389  }
390 
391  // End
392  return 0;
393 }
394 
395 // =====================================================================
396 // ---------------------------------------------------------------------
397 // ---------------------------------------------------------------------
398 // =====================================================================
399 /*
400  \fn BuildLUT()
401  \brief Call the eponym function of the scanner class
402  \return 0 if success. Positive value otherwise
403 */
405 {
407 
408  // Verbose
409  if (m_verbose>=VERBOSE_NORMAL) Cout("sScannerManager::BuildLUT() -> Generate the geometric Look-Up Table"<< endl);
410 
411  // Generate LUT
413  {
414  Cerr("***** sScannerManager::BuildLUT() -> A problem occurred while generating/reading the LUT !" << endl);
415  return 1;
416  }
417 
418  // End
419  return 0;
420 }
421 
422 // =====================================================================
423 // ---------------------------------------------------------------------
424 // ---------------------------------------------------------------------
425 // =====================================================================
426 /*
427  \fn GetAvailableScanners
428  \param ap_scannerNames : vector list of string to recover the available scanner names
429  \brief Gather all the names of the header files (.geom & .hscan)
430  in the repository folder in the vector<string> passed in parameter
431  \return 0 if sucess, positive value otherwise
432 */
433 int sScannerManager::GetAvailableScanners(vector<string> *ap_scannerNames)
434 {
436 
437  // Verbose
438  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::GetAvailableScanners() -> Scan the scanner configuration directory"<< endl);
439 
440  // Initialize directory
441  DIR *respository_dir;
442  struct dirent *ent;
443  string str_geom(".geom"), str_hscan(".hscan");
444  string scanner_repository = sOutputManager::GetInstance()->GetPathToConfigDir() + "scanner" + OS_SEP;
445 
446  // Open directory
447  if ((respository_dir = opendir(scanner_repository.c_str())) != NULL)
448  {
449  // Print all the files and directories within the repository directory
450  while ((ent = readdir (respository_dir)) != NULL)
451  {
452  string scanner_name = ent->d_name;
453  // Get rid of backup files in linux
454  if(scanner_name.at(scanner_name.size()-1) != '~')
455  // .geom or .hscan file found
456  if(scanner_name.find(str_geom)!=string::npos || scanner_name.find(str_hscan)!=string::npos )
457  {
458  ap_scannerNames->push_back(scanner_name);
459  }
460  }
461  // Close directory
462  closedir (respository_dir);
463  }
464  else
465  {
466  Cerr("***** sScannerManager::GetAvailableScanners() -> Could not open the repository directory at: " << scanner_repository << endl);
467  return 1;
468  }
469 
470  // End
471  return 0;
472 }
473 
474 // =====================================================================
475 // ---------------------------------------------------------------------
476 // ---------------------------------------------------------------------
477 // =====================================================================
478 /*
479  \fn GetScannerLayerNbRings
480  \param a_layer : layer index
481  \brief Ask the number of rings to the scanner object for a specific layer.
482  Returns an error if this information is not available for the scanner type of the object (eg : SPECT systems)
483  \return The number of rings in the system if success. NEGATIVE value otherwise
484 */
486 {
488 
489  // Verbose
490  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::GetScannerLayerNbRings() -> For layer " << a_layer << endl);
491 
492  // Works only for PET scanners
494  {
495  // Get the number of rings
496  int nb_rings = mp_Scanner->GetScannerLayerNbRings(a_layer);
497  // Check for error
498  if (nb_rings <= 0)
499  {
500  Cerr("***** sScannerManager::GetScannerLayerNbRings() -> Error when trying to get the number of rings in the system for the crystal layer " << a_layer+1 << " !" << endl);
501  return -1;
502  }
503  else return nb_rings;
504  }
505  else
506  {
507  Cerr("***** sScannerManager::GetScannerLayerNbRings() -> This function is only available for PET scanners !" << endl);
508  return -1;
509  }
510 }
511 
512 // =====================================================================
513 // ---------------------------------------------------------------------
514 // ---------------------------------------------------------------------
515 // =====================================================================
516 /*
517  \fn GetSPECTSpecificParameters (Reconstruction)
518  \param ap_nbOfProjections : number of views/projections
519  \param ap_nbHeads : number of heads in the SPECT system
520  \param ap_nbOfBins : 2 elements array containing transaxial number of bins
521  \param ap_pixSizeXY : 2 elements array containing transaxial/axial pixel sizes
522  \param ap_angles : an array containing angles for each view
523  \param ap_CORtoDetectorDistance : a distance between the center of rotation and the detector
524  \param ap_headRotDirection : head rotation direction
525  \brief Transfer geometric information recovered from the datafile to the scanner object
526  \return 0 if success, positive value otherwise
527 */
528 int sScannerManager::GetSPECTSpecificParameters(uint16_t* ap_nbOfProjections,
529  uint16_t* ap_nbHeads,
530  uint16_t* ap_nbOfBins,
531  FLTNB* ap_pixSizeXY,
532  FLTNB*& ap_angles,
533  FLTNB*& ap_CORtoDetectorDistance,
534  int* ap_headRotDirection)
535 {
537 
538  // Verbose
539  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::GetSPECTSpecificParameters() -> Get acquisition dependent parameters"<< endl);
540 
541  // Check modality
543  {
544  Cerr("***** sScannerManager::PROJ_GetSPECTSpecificParameters()-> The scanner object is not of PET type !" << endl);
545  return 1;
546  }
547  else
548  {
549  if (mp_Scanner->GetSPECTSpecificParameters(ap_nbOfProjections, ap_nbHeads, ap_nbOfBins, ap_pixSizeXY, ap_angles, ap_CORtoDetectorDistance, ap_headRotDirection) )
550  {
551  Cerr("***** sScannerManager::PROJ_GetSPECTSpecificParameters()-> A problem occurred while retrieving SPECT parameters from the scanner object !" << endl);
552  return 1;
553  }
554 
555  }
556  return 0;
557 }
558 
559 // =====================================================================
560 // ---------------------------------------------------------------------
561 // ---------------------------------------------------------------------
562 // =====================================================================
563 /*
564  \fn PROJ_GetModalityStopValueMainLoop
565  \brief Get the stop value for the main loop of analytic projection depending on the modality
566  \return the required stop value if success, NEGATIVE value otherwise
567  \todo Cases for CT and sinogram scanner types
568 */
570 {
572 
573  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::PROJ_GetModalityStopValueMainLoop ..."<< endl);
574 
576  {
577  return mp_Scanner->GetSystemNbElts();
578  }
581  {
582  return (int64_t)mp_Scanner->PROJ_GetSPECTNbProjections(); // cast from uint16_t to int
583  }
584  else if(mp_Scanner->GetScannerType() == SCANNER_CT)
585  {
586  // TODO
587  Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Not implemented for CT yet!" << endl);
588  return -1;
589  }
591  {
592  // TODO + should call a GetType() like function for scanner defined as a sinogram
593  Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Not implemented for Sinogram scanner yet!" << endl);
594  return -1;
595  }
596  else
597  {
598  Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Unknown scanner type!" << endl);
599  return -1;
600  }
601 
602  return 0;
603 }
604 
605 // =====================================================================
606 // ---------------------------------------------------------------------
607 // ---------------------------------------------------------------------
608 // =====================================================================
609 /*
610  \fn PROJ_GetModalityStartValueInnerLoop
611  \param a_elt1 : Current nb of processed crystals (PET), projections (SPECT)
612  \brief Get the start value for the inner loop of analytic projection depending on the modality
613  \return the required stop value if success, NEGATIVE value otherwise
614  \todo Cases for CT and sinogram scanner types
615  \todo Precise with SS on which index SPECT inner loop should be done
616 */
618 {
620 
622  {
623  return a_elt1+1;
624  }
627  {
628  return 0; // (first crystal)
629  // TODO SS: here the inner loop should be done on the number of views
630  }
631  else if(mp_Scanner->GetScannerType() == SCANNER_CT)
632  {
633  // TODO
634  Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Not implemented for CT yet!" << endl);
635  return -1;
636  }
638  {
639  // TODO + should call a GetType() like function for scanner defined as a sinogram
640  Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Not implemented for Sinogram scanner yet!" << endl);
641  return -1;
642  }
643  else
644  {
645  Cerr("sScannerManager::PROJ_GetModalityStopValueMainLoop()-> Unknown scanner type!" << endl);
646  return -1;
647  }
648 
649  return 0;
650 }
651 
652 // =====================================================================
653 // ---------------------------------------------------------------------
654 // ---------------------------------------------------------------------
655 // =====================================================================
656 /*
657  \fn PROJ_GetCurrentProgression
658  \param a_elt1 : Current nb of processed #1 crystals (PET), projections (SPECT)
659  \param a_elt2 : Current nb of processed #2 crystals (PET), crystals (SPECT)
660  \param ap_nbEltsArray : Total number of elements processed for each #1 crystals (PET/CT systems)
661  \param a_nbRGates
662  \param a_nbCGates
663  \param a_fr
664  \param a_rg
665  \param a_cg
666  \brief Get numerator value according to the modality to compute percent progression during the analytical projection process
667  \return the required progression value if success, negative value otherwise
668  \todo Cases for CT and sinogram scanner types
669  \todo Optimize this, for now it's quite a lot of operation for each couple of elements
670  \todo Check everything is ok for 3D/4D PET and SPECT
671 */
672 int64_t sScannerManager::PROJ_GetCurrentProgression(int64_t a_elt1, int64_t a_elt2, int64_t* ap_nbEltsArray,
673  int a_nbRGates, int a_nbCGates,
674  int a_fr, int a_rg, int a_cg)
675 {
677 
678  // TODO : optimization, maybe too much operations for each couple of elements
680  {
681  int64_t nb_total_elts = mp_Scanner->GetSystemNbElts();
682 
683  return ap_nbEltsArray[a_elt1]+a_elt2+1 +
684  (int64_t)(a_fr*a_nbRGates*a_nbCGates + a_rg*a_nbCGates + a_cg)* nb_total_elts*nb_total_elts/2;
685  }
688  {
689  return a_elt2 + a_elt1*mp_Scanner->GetSystemNbElts() +
690  a_fr * a_nbRGates * a_nbCGates * mp_Scanner->GetSystemNbElts() +
691  a_rg * a_nbCGates * mp_Scanner->GetSystemNbElts() +
692  a_cg * mp_Scanner->GetSystemNbElts();
693  }
694  else if(mp_Scanner->GetScannerType() == SCANNER_CT)
695  {
696  //TODO
697  Cerr("sScannerManager::PROJ_GetCurrentProgression()-> Not implemented for CT yet!" << endl);
698  return -1;
699  }
701  {
702  //TODO + should call a GetType() like function for scanner defined as a sinogram
703  Cerr("sScannerManager::PROJ_GetCurrentProgression()-> Not implemented for Sinogram scanner yet!" << endl);
704  return -1;
705  }
706  else
707  {
708  Cerr("sScannerManager::PROJ_GetCurrentProgression()-> Unknown scanner type!" << endl);
709  return -1;
710  }
711 }
712 
713 // =====================================================================
714 // ---------------------------------------------------------------------
715 // ---------------------------------------------------------------------
716 // =====================================================================
717 /*
718  \fn PROJ_GetProgressionFinalValue
719  \brief Get numerator value according to the modality to compute percent progression during the projection process
720  \return the required progression value if success, negative value otherwise
721  \todo Cases for CT and sinogram scanner types
722 */
724 {
726 
728  {
729  //return mp_Scanner->GetSystemNbElts();
730  int64_t nb_total_elts = mp_Scanner->GetSystemNbElts();
731  return nb_total_elts*nb_total_elts/2;
732  }
735  {
736  return (int64_t)mp_Scanner->PROJ_GetSPECTNbProjections()*mp_Scanner->GetSystemNbElts(); // cast from uint16_t to int
737  }
738  else if(mp_Scanner->GetScannerType() == SCANNER_CT)
739  {
740  //TODO
741  Cerr("sScannerManager::PROJ_GetProgressionFinalValue()-> Not implemented for CT yet!" << endl);
742  return -1;
743  }
745  {
746  //TODO + should call a GetType() like function for scanner defined as a sinogram
747  Cerr("sScannerManager::PROJ_GetProgressionFinalValue()-> Not implemented for Sinogram scanner yet!" << endl);
748  return -1;
749  }
750  else
751  {
752  Cerr("sScannerManager::PROJ_GetProgressionFinalValue()-> Unknown scanner type!" << endl);
753  return -1;
754  }
755 }
756 
757 // =====================================================================
758 // ---------------------------------------------------------------------
759 // ---------------------------------------------------------------------
760 // =====================================================================
761 /*
762  \fn PROJ_SetPETSpecificParameters (Analytic Projection)
763  \param a_maxRingDiff : max number of axial ring difference
764  \brief Deliver to the PET scanner object all informations provided from the datafile header
765  \return 0 if success, positive value otherwise
766  \todo How to handle systems with several layer of rings ?
767 */
769 {
771 
772  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::PROJ_SetPETSpecificParameters ..."<< endl);
773 
775  {
776  Cerr("***** sScannerManager::SetPETSpecificParameters() -> The scanner object is not of PET type !" << endl);
777  return 1;
778  }
779  else
780  {
781  mp_Scanner->SetPETMaxRingDiff(a_maxRingDiff);
782  }
783 
784  return 0;
785 }
786 
787 // =====================================================================
788 // ---------------------------------------------------------------------
789 // ---------------------------------------------------------------------
790 // =====================================================================
791 /*
792  \fn PROJ_GetPETSpecificParameters (Analytic Projection)
793  \param ap_maxRingDiff : max number of axial ring difference
794  \brief Transfer addresses to each geometric parameter of the PET scanner objets to the corresponding pointer of the datafile passed as argument
795  \return 0 if success, positive value otherwise
796  \todo How to handle systems with several layer of rings ?
797 */
799 {
801 
802  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::PROJ_GetPETSpecificParameters ..."<< endl);
803 
805  {
806  Cerr("***** sScannerManager::PROJ_GetPETSpecificParameters()-> The scanner object is not of PET type !" << endl);
807  return 1;
808  }
809  else
810  {
811  int max_ring_diff = -1;
812 
813  if (mp_Scanner->PROJ_GetPETSpecificParameters(&max_ring_diff) )
814  {
815  Cerr("***** sScannerManager::PROJ_GetPETSpecificParameters()-> A problem occurred while retrieving PET parameters from the scanner object !" << endl);
816  return 1;
817  }
818 
819  if (max_ring_diff < 0)
820  {
821  Cerr("***** sScannerManager::PROJ_GetPETSpecificParameters()-> max ring difference should be > 0 !" << endl);
822  return 1;
823  }
824  else
825  *ap_maxRingDiff = max_ring_diff;
826  }
827  return 0;
828 }
829 
830 // =====================================================================
831 // ---------------------------------------------------------------------
832 // ---------------------------------------------------------------------
833 // =====================================================================
834 /*
835  \fn PROJ_SetSPECTSpecificParameters (Analytic Projection)
836  \param ap_nbOfBins : 2 elements array containing transaxial number of bins
837  \param a_nbOfProjections : number of views/projections
838  \param a_firstAngle : angle of the first view
839  \param a_lastAngle : angle of the last view
840  \param ap_projectionAngles : an array containing angles for each view
841  \param a_CORtoDetectorDistance : a distance between the center of rotation and the detector
842  \param a_RotDirection : Rotation direction of the head (clockwise/counter-clockwise)
843  \brief Deliver to the SPECT scanner object all informations provided from the acquisition parameters
844  \details For analytical projection, this data is provided from the command-line options
845  \return 0 if success, positive value otherwise
846 */
848  uint32_t a_nbOfProjections,
849  FLTNB a_firstAngle,
850  FLTNB a_stepAngle,
851  FLTNB* ap_projectionAngles,
852  FLTNB a_CORtoDetectorDistance,
853  string a_rotDirection)
854 {
856 
857  if (m_verbose>=VERBOSE_DETAIL) Cout("sScannerManager::PROJ_SetSPECTSpecificParameters ..."<< endl);
858 
859  // Return error if wrong modality
861  {
862  Cerr("***** sScannerManager::SetPETSpecificParameters()-> The scanner object is not of PET type !" << endl);
863  return 1;
864  }
865  else
866  {
867  // Nb bins
868  mp_Scanner->PROJ_SetSPECTNbBins(ap_nbOfBins);
869 
870  // Nb projections
871  if(a_nbOfProjections == 0)
872  {
873  Cerr("***** sScannerManager::SetSPECTSpecificParameters()-> Error, SPECT analytic projection requires an user-specified number of projections !" << endl);
874  return 1;
875  }
876 
877  mp_Scanner->PROJ_SetSPECTNbProjections(a_nbOfProjections);
878 
879 
880  // Projection angles initialized with either each angles, or calculated from first/last angle
881  // By default, we chose the user-provided custom initialization for SPECT projection angles
882  // If not initialized, we computed them from first/last angle
883  if(ap_projectionAngles == NULL)
884  {
885  // 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
886  if(a_firstAngle<0 || a_stepAngle<0)
887  {
888  Cerr("***** sScannerManager::SetSPECTSpecificParameters()-> Error, SPECT projection requires to set the projection angles using either the '-SPECT_ang' or '-SPECT_c_ang' options !" << endl);
889  return 1;
890  }
891  else
892  {
893  // Fill the SPECT_projection_angles array
894  ap_projectionAngles = new FLTNB[a_nbOfProjections];
895  ap_projectionAngles[0] = a_firstAngle;
896 
897  for(uint32_t a=1 ; a<a_nbOfProjections ; a++)
898  ap_projectionAngles[a] = ap_projectionAngles[a-1] + a_stepAngle;
899  }
900  }
901 
902  if(mp_Scanner->PROJ_SetSPECTAngles(ap_projectionAngles) )
903  {
904  Cerr("***** sScannerManager::SetSPECTAngles() -> An error occured while trying to initialize SPECT projection angles !" << endl);
905  return 1;
906  }
907 
908  // CORtoDetectorDistance
909  if(mp_Scanner->PROJ_SetSPECTCORtoDetectorDistance(a_CORtoDetectorDistance) )
910  {
911  Cerr("***** sScannerManager::SetPETSpecificParameters() -> An error occured while trying to initialize SPECT distance between center of rotation to detectors !" << endl);
912  return 1;
913  }
914 
915  // Set rotation direction
916  mp_Scanner->SetRotDirection(a_rotDirection);
917  }
918 
919  return 0;
920 }
virtual int PROJ_SetSPECTNbBins(uint16_t *ap_nbOfBins)
Set SPECT number of Bins.
Definition: vScanner.cc:268
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
int GetAvailableScanners(vector< string > *ap_scannerNames)
Gather all the names of the header files (.geom & .hscan) in the repository folder in the vector<stri...
virtual int PROJ_SetSPECTNbProjections(uint32_t a_nbOfProjections)
Set SPECT number of views.
Definition: vScanner.cc:289
int64_t PROJ_GetModalityStartValueInnerLoop(int64_t a_elt1)
Get the start value for the inner loop of analytic projection depending on the modality.
#define FLTNB
Definition: gVariables.hh:55
int FindScannerSystem(string a_scannerName)
Look for a file matching with the scanner name in parameter inside the scanner repository.
virtual int PROJ_SetSPECTAngles(FLTNB *ap_projectionAngles)
Set SPECT projection angles.
Definition: vScanner.cc:313
int BuildScannerObject()
Instantiate the specific scanner object related to the modality, and set verbosity of scanner object...
int64_t PROJ_GetProgressionFinalValue()
Get numerator value according to the modality to compute percent progression during the projection pr...
virtual int PROJ_GetPETSpecificParameters(int *ap_maxRingDiff)
Get geometric PET specific parameters to initialize the datafile.
Definition: vScanner.cc:176
#define VERBOSE_DETAIL
char d_name[PATH_MAX]
int PROJ_GetPETSpecificParameters(int *a_maxRingDiff)
Transfer addresses to each geometric parameter of the PET scanner objets to the corresponding pointer...
static sScannerManager * mp_Instance
virtual uint16_t PROJ_GetSPECTNbProjections()
return the total number of projections for a SPECT acquisition
Definition: vScanner.cc:354
virtual int GetScannerLayerNbRings(int a_layer)
Return an error by default.
Definition: vScanner.cc:155
virtual int CheckParameters()=0
This function is implemented in child classes. Check that all parameters have been correctly initia...
std::map< string, maker_scanner > mp_listOfScannerTypes
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
#define SCANNER_PET
virtual int Initialize()=0
This function is implemented in child classes. Check initialization and set several parameters to t...
int CheckParameters()
Check if all parameters have been correctly initialized, and call the CheckParameters function of the...
int GetSPECTSpecificParameters(uint16_t *ap_nbOfProjections, uint16_t *ap_nbHeads, uint16_t *ap_nbOfBins, FLTNB *ap_pixSizeXY, FLTNB *&ap_angles, FLTNB *&ap_CORtoDetectorDistance, int *ap_headRotDirection)
Transfer geometric information recovered from the datafile to the scanner object. ...
int InstantiateScanner()
Instantiate scanner using the related function in the scanner classes.
sScannerManager()
sScannerManager constructor.
static sAddonManager * GetInstance()
#define Cerr(MESSAGE)
#define SCANNER_SPECT_CONVERGENT
virtual int Instantiate(bool a_scannerFileIsLUT)=0
This function is implemented in child classes. Read the mandatory fields from the scanner file and al...
#define VERBOSE_DEBUG_LIGHT
virtual int SetRotDirection(string a_rotDirection)
Set rotation direction of the system.
Definition: vScanner.cc:232
int BuildLUT()
Call the eponym function of the scanner class.
Singleton class that manages output writing on disk (images, sinograms, etc). It also manages loggi...
const string & GetPathToConfigDir()
Return the path to the CASTOR config directory.
#define VERBOSE_LIGHT
int ReadDataASCIIFile(const string &a_file, const string &a_keyword, T *ap_return, int a_nbElts, bool a_mandatoryFlag)
Look for "a_nbElts" elts in the "a_file" file matching the "a_keyword" string passed as parameter a...
Definition: gOptions.cc:111
Singleton class that Instantiate and initialize the scanner object.
#define SCANNER_SINOGRAM
Declaration of class sScannerManager.
static int closedir(DIR *dirp)
int PROJ_SetPETSpecificParameters(int a_maxRingDiff)
Deliver to the PET scanner object all informations provided from the datafile header.
#define VERBOSE_NORMAL
static DIR * opendir(const char *dirname)
int ShowScannersDescription()
Get the description associated to the different scanners and print all on screen. Walk through the ...
~sScannerManager()
sScannerManager destructor.
#define KEYWORD_MANDATORY
Definition: gOptions.hh:25
int PROJ_SetSPECTSpecificParameters(uint16_t *ap_nbOfBins, uint32_t a_nbOfProjections, FLTNB a_firstAngle, FLTNB a_stepAngle, FLTNB *ap_projectionAngles, FLTNB a_CORtoDetectorDistance, string a_rotDirection)
Deliver to the SPECT scanner object all informations provided from the acquisition parameters...
void SetVerbose(int a_verboseLevel)
Set verbosity.
Definition: vScanner.hh:225
int Initialize()
Initialization : .
#define SCANNER_SPECT_PINHOLE
virtual int GetSPECTSpecificParameters(uint16_t *ap_nbOfProjections, uint16_t *ap_nbHeads, uint16_t *ap_nbOfBins, FLTNB *ap_pixSizeXY, FLTNB *&ap_angles, FLTNB *&ap_CORtoDetectorDistance, int *ap_headRotDirection)
Recover geometric SPECT specific parameters from the scanner to initialize the datafile.
Definition: vScanner.cc:204
virtual int PROJ_SetSPECTCORtoDetectorDistance(FLTNB a_CORtoDetectorDistance)
Set distance between center of rotation and SPECT detectors.
Definition: vScanner.cc:334
virtual int GetSystemNbElts()=0
This is a pure virtual method that must be implemented by children.
#define OS_SEP
vScanner * mp_Scanner
virtual int GetGeometricInfoFromDatafile(string a_path)=0
This function is implemented in child classes Recover geometric informations specific to the scanne...
virtual int SetPETMaxRingDiff(int a_maxRingDiff)
Set the maximal ring difference.
Definition: vScanner.cc:137
void ShowHelpScanner()
Show help about all implemented scanners.
int64_t PROJ_GetCurrentProgression(int64_t a_elt1, int64_t a_elt2, int64_t *ap_nbEltsArray, int a_nbRGates, int a_nbCGates, int a_fr, int a_rg, int a_cg)
Get numerator value according to the modality to compute percent progression during the analytical pr...
int GetScannerLayerNbRings(int a_layer)
Ask the number of rings to the scanner object for a specific layer. Returns an error if this inform...
int GetGeometricInfoFromDatafile(string a_pathToDataFilename)
Call the specialized function of the scanner object in order to get geometric informations from the d...
#define DEBUG_VERBOSE(IGNORED1, IGNORED2)
#define Cout(MESSAGE)
int64_t PROJ_GetModalityStopValueMainLoop()
Get the stop value for the main loop of analytic projection depending on the modality.
static struct dirent * readdir(DIR *dirp)
#define SCANNER_CT
Declaration of class sAddonManager.
int GetScannerType()
Definition: vScanner.hh:218
Generic class for scanner objects.
Definition: vScanner.hh:48
virtual int BuildLUT(bool a_scannerFileIsLUT)=0
This function is implemented in child classes. Instantiate the scanner look-up-table (LUT) ...