CASToR  2.0
Tomographic Reconstruction (PET/SPECT/CT)
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
castor-datafileExplorer.cc
Go to the documentation of this file.
1 /*
2 This file is part of CASToR.
3 
4  CASToR is free software: you can redistribute it and/or modify it under the
5  terms of the GNU General Public License as published by the Free Software
6  Foundation, either version 3 of the License, or (at your option) any later
7  version.
8 
9  CASToR is distributed in the hope that it will be useful, but WITHOUT ANY
10  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12  details.
13 
14  You should have received a copy of the GNU General Public License along with
15  CASToR (in file GNU_GPL.TXT). If not, see <http://www.gnu.org/licenses/>.
16 
17 Copyright 2017-2018 all CASToR contributors listed below:
18 
19  --> current contributors: Thibaut MERLIN, Simon STUTE, Didier BENOIT, Claude COMTAT, Marina FILIPOVIC, Mael MILLARDET
20  --> past contributors: Valentin VIELZEUF
21 
22 This is CASToR version 2.0.
23 */
24 
31 #include "gVariables.hh"
32 #include "gOptions.hh"
34 #include "iDataFilePET.hh"
35 #include "iDataFileSPECT.hh"
36 #include "iDataFileCT.hh"
37 #include "sOutputManager.hh"
38 #include "sScannerManager.hh"
40 #include "iScannerPET.hh"
41 #include "sAddonManager.hh"
42 
43 // =============================================================================================================================================
44 // =============================================================================================================================================
45 // =============================================================================================================================================
46 // H E L P F U N C T I O N S
47 // =============================================================================================================================================
48 // =============================================================================================================================================
49 // =============================================================================================================================================
50 
51 
56 void ShowHelp()
57 {
58  // Show help
59  cout << endl;
60  cout << "Usage: castor-datafileExplorer -df datafile.cdh [settings]" << endl;
61  cout << endl;
62  cout << "This program can be used to explore a datafile and get some info about it. By default, it simply prints general information recovered" << endl;
63  cout << "from the reader. If the '-e' option is supply, an event-by-event exploration will be performed: information about each event will be" << endl;
64  cout << "displayed." << endl;
65  cout << endl;
66  cout << "[Mandatory parameters]:" << endl;
67  cout << " -df datafile.cdh : Give the path to a single datafile." << endl;
68  cout << endl;
69  cout << "[Options]:" << endl;
70  cout << " -e : Flag for event by event exploration (will list the content of each event)." << endl;
71  cout << " -i : Flag for interactive one by one event exploration when -e option is supplied." << endl;
72  cout << " -g : Flag for global exploration (will not list the content of each event but will supply a summary)." << endl;
73  cout << " -vb value : Give the verbosity level, from 0 (no verbose) to 2 (default: 1)" << endl;
74  cout << " --help,-h,-help : Print out this help page." << endl; // managed by main
75  cout << endl;
76  #ifdef BUILD_DATE
77  cout << " Build date: " << BUILD_DATE << endl;
78  cout << endl;
79  #endif
80  #ifdef CASTOR_VERSION
81  cout << " This program is part of the CASToR release version " << CASTOR_VERSION << "." << endl;
82  cout << endl;
83  #endif
84 }
85 
86 // =============================================================================================================================================
87 // =============================================================================================================================================
88 // =============================================================================================================================================
89 // M A I N P R O G R A M
90 // =============================================================================================================================================
91 // =============================================================================================================================================
92 // =============================================================================================================================================
93 
94 int main(int argc, char** argv)
95 {
96  // ============================================================================================================
97  // MPI stuff (we make all instances but the first one returning 0 directly)
98  // ============================================================================================================
99  #ifdef CASTOR_MPI
100  int mpi_rank = 0;
101  int mpi_size = 1;
102  MPI_Init(&argc, &argv);
103  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
104  MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
105  if (mpi_rank!=0) return 0;
106  #endif
107 
108  // No argument, then show help
109  if (argc==1)
110  {
111  ShowHelp();
112  Exit(EXIT_SUCCESS);
113  }
114 
115  // ============================================================================================================
116  // The few parameters
117  // ============================================================================================================
118 
119  // String of a single path to a data file name
120  string path_to_data_filename;
121  // General verbose level
122  int verbose = 1;
123  // Flag for event-by-event exploring
124  bool event_by_event_flag = false;
125  // Flag for interactive mode for event-by-event
126  bool interactive_flag = false;
127  // Flag for global exploration
128  bool global_flag = false;
129 
130  // ============================================================================================================
131  // Read command-line parameters
132  // ============================================================================================================
133 
134  // Must manually increment the option index when an argument is needed after an option
135  for (int i=1; i<argc; i++)
136  {
137  // Get the option as a string
138  string option = (string)argv[i];
139  // Show help
140  if (option=="-h" || option=="--help" || option=="-help")
141  {
142  ShowHelp();
143  Exit(EXIT_SUCCESS);
144  }
145  // General verbosity level
146  else if (option=="-vb")
147  {
148  if (i>=argc-1)
149  {
150  Cerr("***** castor-datafileExplorer() -> Argument missing for option: " << option << endl);
151  Exit(EXIT_FAILURE);
152  }
153  if (ConvertFromString(argv[i+1], &verbose))
154  {
155  Cerr("***** castor-datafileExplorer() -> Exception when trying to read provided verbosity level '" << verbose << " for option: " << option << endl);
156  Exit(EXIT_FAILURE);
157  }
158  i++;
159  }
160  // DataFile
161  else if (option=="-df") // This is a mandatory option
162  {
163  if (i>=argc-1)
164  {
165  Cerr("***** castor-datafileExplorer() -> Argument missing for option: " << option << endl);
166  Exit(EXIT_FAILURE);
167  }
168  path_to_data_filename = (string)argv[i+1];
169  i++;
170  }
171  // Event by event exploration
172  else if (option=="-e")
173  {
174  event_by_event_flag = true;
175  }
176  // Interactive mode for event-by-event exploration
177  else if (option=="-i")
178  {
179  interactive_flag = true;
180  }
181  // Global exploration
182  else if (option=="-g")
183  {
184  global_flag = true;
185  }
186  // Unknown option!
187  else
188  {
189  Cerr("***** castor-datafileExplorer() -> Unknown option '" << option << "' !" << endl);
190  Exit(EXIT_FAILURE);
191  }
192  }
193 
194  // ============================================================================================================
195  // Some checks
196  // ============================================================================================================
197 
198  // Check for a datafile name
199  if (path_to_data_filename=="")
200  {
201  Cerr("***** castor-datafileExplorer() -> Please provide a datafile name !" << endl);
202  Exit(EXIT_FAILURE);
203  }
204  // Verbose
205  if (verbose<=0)
206  {
207  Cerr("***** castor-datafileExplorer() -> Verbose less than 1 has no sense for a program used to solely print out information on screen !" << endl);
208  Exit(EXIT_FAILURE);
209  }
210  // Restrict verbose level to 2 to avoid having to much useless information during initialization
211  if (verbose>2) verbose = 2;
212  // Cannot have event-by-event and global both enables
213  if (global_flag && event_by_event_flag)
214  {
215  Cerr("***** castor-datafileExplorer() -> Cannot use global and event-by-event mode at the same time !" << endl);
216  Exit(EXIT_FAILURE);
217  }
218 
219  // ============================================================================================================
220  // Initializations
221  // ============================================================================================================
222 
223  // Verbose (we know it is at least 1 so we don't check it)
224  Cout("==============================================================" << endl);
225  Cout("castor-datafileExplorer() -> Initialization starts" << endl);
226 
227  // ----------------------------------------------------------------------------------------
228  // Create sScannerManager
229  // ----------------------------------------------------------------------------------------
230 
231  // Get user endianness (interfile I/O)
233 
234  // Create the scanner manager
235  sScannerManager* p_ScannerManager = sScannerManager::GetInstance();
236  p_ScannerManager->SetVerbose(verbose);
237 
238  // Get system name from the dataFile
239  string scanner_name = "";
240  if (ReadDataASCIIFile(path_to_data_filename, "Scanner name", &scanner_name, 1, KEYWORD_MANDATORY))
241  {
242  Cerr("***** castor-datafileExplorer() -> A problem occured while trying to find the system name in the datafile header !" << endl);
243  Exit(EXIT_FAILURE);
244  }
245  if (p_ScannerManager->FindScannerSystem(scanner_name) )
246  {
247  Cerr("***** castor-datafileExplorer() -> A problem occurred while searching for scanner system !" << endl);
248  Exit(EXIT_FAILURE);
249  }
250  if (p_ScannerManager->BuildScannerObject() )
251  {
252  Cerr("***** castor-datafileExplorer() -> A problem occurred during scanner object construction ! !" << endl);
253  Exit(EXIT_FAILURE);
254  }
255  if (p_ScannerManager->InstantiateScanner() )
256  {
257  Cerr("***** castor-datafileExplorer() -> A problem occurred while creating Scanner object !" << endl);
258  Exit(EXIT_FAILURE);
259  }
260  if (p_ScannerManager->GetGeometricInfoFromDataFile(path_to_data_filename))
261  {
262  Cerr("***** castor-datafileExplorer() -> A problem occurred while retrieving scanner fields from the datafile header !" << endl);
263  Exit(EXIT_FAILURE);
264  }
265  if (p_ScannerManager->BuildLUT() )
266  {
267  Cerr("***** castor-datafileExplorer() -> A problem occurred while generating/reading the LUT !" << endl);
268  Exit(EXIT_FAILURE);
269  }
270  if (p_ScannerManager->CheckParameters())
271  {
272  Cerr("***** castor-datafileExplorer() -> A problem occured while checking scanner manager parameters !" << endl);
273  Exit(EXIT_FAILURE);
274  }
275  if (p_ScannerManager->Initialize())
276  {
277  Cerr("***** castor-datafileExplorer() -> A problem occured while initializing scanner !" << endl);
278  Exit(EXIT_FAILURE);
279  }
280 
281  // ----------------------------------------------------------------------------------------
282  // Create vDataFile
283  // ----------------------------------------------------------------------------------------
284 
285  // Create a default image dimensions and quantification object
287  p_ID->SetDefault();
288  p_ID->SetVerbose(verbose);
289  // Virtual datafile
290  vDataFile* p_DataFile = NULL;
291  // Create specific data file
292  if (p_ScannerManager->GetScannerType() == SCANNER_PET) p_DataFile = new iDataFilePET();
293  else if (p_ScannerManager->GetScannerType() == SCANNER_SPECT_CONVERGENT) p_DataFile = new iDataFileSPECT();
294  else if (p_ScannerManager->GetScannerType() == SCANNER_CT) p_DataFile = new iDataFileCT();
295  // Unknown scanner
296  else
297  {
298  Cerr("***** castor-datafileExplorer() -> Unknown scanner type (" << p_ScannerManager->GetScannerType() << ") for datafile construction ! Abort." << endl);
299  Exit(EXIT_FAILURE);
300  }
301  // Set data file name
302  p_DataFile->SetHeaderDataFileName(path_to_data_filename);
303  // Few parameters
304  p_DataFile->SetImageDimensionsAndQuantification(p_ID);
305  p_DataFile->SetBedIndex(0);
306  p_DataFile->SetVerbose(verbose);
307  // Read information from the header, without affecting the quantification (as no ImageDimensionsAndQuantification object is used here)
308  bool do_not_affect_quantification = false;
309  if (p_DataFile->ReadInfoInHeader(do_not_affect_quantification))
310  {
311  Cerr("***** castor-datafileExplorer() -> A problem occurred during datafile header reading ! Abort." << endl);
312  Exit(EXIT_FAILURE);
313  }
314  if (p_DataFile->CheckParameters())
315  {
316  Cerr("***** castor-datafileExplorer() -> A problem occurred while checking datafile parameters ! Abort." << endl);
317  Exit(EXIT_FAILURE);
318  }
319  if (p_DataFile->ComputeSizeEvent())
320  {
321  Cerr("***** castor-datafileExplorer() -> A problem occurred in datafile initialization ! Abort." << endl);
322  Exit(EXIT_FAILURE);
323  }
324  if (p_DataFile->InitializeMappedFile())
325  {
326  Cerr("***** castor-datafileExplorer() -> A problem occurred in datafile initialization ! Abort." << endl);
327  Exit(EXIT_FAILURE);
328  }
329  if (p_DataFile->PrepareDataFile())
330  {
331  Cerr("***** castor-datafileExplorer() -> A problem occured in datafile preparation ! Abort." << endl);
332  Exit(EXIT_FAILURE);
333  }
334 
335  // Verbose
336  Cout("castor-datafileExplorer() -> End of initialization" << endl);
337  Cout("==============================================================" << endl);
338 
339  // ============================================================================================================
340  // Actions
341  // ============================================================================================================
342 
343  // -------------------------------------------------------------------
344  // Ask the datafile to describe itself
345  // -------------------------------------------------------------------
346  p_DataFile->Describe();
347  Cout("==============================================================" << endl);
348 
349  // -------------------------------------------------------------------
350  // Then if the event-by-event option is on, describe each event
351  // -------------------------------------------------------------------
352 
353  if (event_by_event_flag)
354  {
355  Cout("castor-datafileExplorer() -> Start exploration of all events" << endl);
356  // Get index start and stop
357  int64_t index_start = 0; int64_t index_stop = 0;
358  p_DataFile->GetEventIndexStartAndStop(&index_start, &index_stop);
359  // Launch the loop on all events
360  int64_t index = index_start;
361  while (index>=index_start && index<index_stop)
362  {
363  // Verbose
364  Cout("------------------------- Event index " << index << " -------------------------" << endl);
365  // Get the current event
366  vEvent* p_event = p_DataFile->GetEvent(index);
367  if (p_event==NULL)
368  {
369  Cerr("***** castor-datafileExplorer() -> An error occured while getting the event from index " << index << " !" << endl);
370  Exit(EXIT_FAILURE);
371  }
372  // Describe the event
373  p_event->Describe();
374  // Interactive mode
375  if (interactive_flag)
376  {
377  // The user may provide a specific event index or simply press enter to get to the next
378  cout << "--------> Give an event index or simply press enter for next event: " << flush;
379  // Read the answer
380  string answer = ""; getline(cin,answer);
381  cout << endl;
382  // If empty answer, then go to the next event
383  if (answer=="") index++;
384  // Otherwise
385  else
386  {
387  // Convert the answer to int64_t
388  int64_t next_index = stoll(answer);
389  if (next_index<index_start || next_index>=index_stop)
390  {
391  Cerr("***** castor-datafileExplorer() -> The provided event index (" << next_index << ") is out of datafile range"
392  << " [" << index_start << ":" << index_stop << "[ !" << endl);
393  break;
394  }
395  else index = next_index;
396  }
397  }
398  else index++;
399  }
400  Cout("==============================================================" << endl);
401  }
402 
403  // -------------------------------------------------------------------
404  // Or perform a global exploration
405  // -------------------------------------------------------------------
406 
407  else if (global_flag)
408  {
409  // Verbose
410  Cout("castor-datafileExplorer() -> Start global exploration of all events" << endl);
411  // Progression (increments of 2%)
412  cout << "0 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%" << endl;
413  cout << "|----|----|----|----|----|----|----|----|----|----|" << endl;
414  cout << "|" << flush;
415  int progression_percentage_old = 0;
416  int progression_nb_bars = 0;
417  uint64_t progression_printing_index = 0;
418  // Get index start and stop
419  int64_t index_start = 0; int64_t index_stop = 0;
420  p_DataFile->GetEventIndexStartAndStop(&index_start, &index_stop);
421  // Cumulative values
422  HPFLTNB total_nb_data = 0.;
423  // Launch the loop on all events
424  for (int64_t index=index_start ; index<index_stop ; index++)
425  {
426  // Print progression
427  if (progression_printing_index%1000==0)
428  {
429  int progression_percentage_new = ((int)( (((float)(index-index_start+1))/((float)(index_stop-index_start)) ) * 100.));
430  if (progression_percentage_new>=progression_percentage_old+2) // Increments of 2%
431  {
432  int nb_steps = (progression_percentage_new-progression_percentage_old)/2;
433  for (int i=0; i<nb_steps; i++)
434  {
435  cout << "-" << flush;
436  progression_nb_bars++;
437  }
438  progression_percentage_old += nb_steps*2;
439  }
440  }
441  progression_printing_index++;
442  // Get the current event
443  vEvent* p_event = p_DataFile->GetEvent(index);
444  if (p_event==NULL)
445  {
446  Cerr("***** castor-datafileExplorer() -> An error occured while getting the event from index " << index << " !" << endl);
447  Exit(EXIT_FAILURE);
448  }
449  // Number of data
450  for (INTNB b=0; b<p_event->GetNbValueBins(); b++) total_nb_data += ((HPFLTNB)(p_event->GetEventValue(b)));
451  }
452  // End of progression printing (do not log out with Cout here)
453  int progression_total_bars = 49;
454  for (int i=0; i<progression_total_bars-progression_nb_bars; i++) cout << "-";
455  cout << "|" << endl;
456  Cout(" --> Total number of data: " << total_nb_data << endl);
457  Cout("==============================================================" << endl);
458  }
459 
460  // ============================================================================================================
461  // End
462  // ============================================================================================================
463 
464  // Delete objects in the inverse order in which they were created
465  delete p_DataFile;
466 
467  // Ending
468  #ifdef CASTOR_MPI
469  MPI_Finalize();
470  #endif
471  return EXIT_SUCCESS;
472 }
This class is designed to be a mother virtual class for DataFile.
Definition: vDataFile.hh:103
This header file is mainly used to declare some macro definitions and all includes needed from the st...
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
void GetEventIndexStartAndStop(int64_t *ap_indexStart, int64_t *ap_indexStop, int a_subsetNum=0, int a_NbSubsets=1)
Compute the index start and stop of the events loop with respect to the current subset and MPI size a...
Definition: vDataFile.cc:671
Declaration of class oImageDimensionsAndQuantification.
int CheckParameters()
Check the initialization of member variables Call the CheckSpecificParameters() function implemente...
Definition: vDataFile.cc:315
int FindScannerSystem(string a_scannerName)
Look for a file matching with the scanner name in parameter inside the scanner repository.
#define HPFLTNB
Definition: gVariables.hh:83
int BuildScannerObject()
Instantiate the specific scanner object related to the modality, and set verbosity of scanner object...
int ReadInfoInHeader(bool a_affectQuantificationFlag=true)
Read and check general information from the header datafile Call the ReadSpecificInformationInHeade...
Definition: vDataFile.cc:110
void SetVerbose(int a_verboseLevel)
set verbosity
Definition: vDataFile.hh:439
virtual int ComputeSizeEvent()=0
This function is implemented in child classes Computation of the size of each event according to th...
#define SCANNER_PET
Declaration of class iDataFileCT.
Declaration of class iDataFilePET.
int CheckParameters()
Check if all parameters have been correctly initialized, and call the CheckParameters function of the...
Declaration of class iDataFileSPECT.
void Exit(int code)
int InitializeMappedFile()
Check the datafile existency, map it to memory and get the raw char* pointer. .
Definition: vDataFile.cc:462
Declaration of class iScannerPET.
int InstantiateScanner()
Instantiate scanner using the related function in the scanner classes.
void ShowHelp()
int ConvertFromString(const string &a_str, string *a_result)
Copy the 'a_str' string in the position pointed by 'a_result'.
Definition: gOptions.cc:771
vEvent * GetEvent(int64_t a_eventIndex, int a_th=0)
Definition: vDataFile.cc:598
#define Cerr(MESSAGE)
#define SCANNER_SPECT_CONVERGENT
int BuildLUT()
Call the eponym function of the scanner class.
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:123
Singleton class that Instantiate and initialize the scanner object.
virtual FLTNB GetEventValue(int a_bin)=0
Pure virtual function implemented in the child classes.
Declaration of class sScannerManager.
virtual int PrepareDataFile()=0
This function is implemented in child classes Store different kind of information inside arrays (da...
Inherit from vDataFile. Class that manages the reading of a SPECT input file (header + data)...
void SetHeaderDataFileName(const string &a_headerFileName)
set the data header file name
Definition: vDataFile.hh:476
int main(int argc, char **argv)
#define KEYWORD_MANDATORY
Definition: gOptions.hh:48
int Initialize()
Initialization : .
Declaration of class sRandomNumberGenerator.
void SetVerbose(int a_verbose)
Set the member m_verboseLevel to the provided value.
#define INTNB
Definition: gVariables.hh:92
void SetBedIndex(int a_bedIndex)
set the bed index corresponding to this data file
Definition: vDataFile.hh:420
virtual void Describe()=0
This function can be used to get a description of the event printed out.
Declaration of class sOutputManager.
Mother class for the Event objects.
Definition: vEvent.hh:43
Inherit from vDataFile. Class that manages the reading of a CT input file (header + data)...
Definition: iDataFileCT.hh:48
void Describe()
A function used to describe the generic parts of the datafile.
Definition: vDataFile.cc:510
This class is designed to manage all dimensions and quantification related stuff. ...
This file is used for all kind of different functions designed for options parsing and ASCII file rea...
virtual INTNB GetNbValueBins()=0
Get the number of event value bins.
void SetVerbose(int a_verboseLevel)
set verbosity
#define Cout(MESSAGE)
#define CASTOR_VERSION
Definition: gVariables.hh:70
#define SCANNER_CT
void SetDefault()
A function used to set number of threads and MPI instances to 1 and bypass the CheckParameters() func...
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
set the pointer to the oImageDimensionsAndQuantification object
Definition: vDataFile.hh:453
Inherit from vDataFile. Class that manages the reading of a PET input file (header + data)...
Definition: iDataFilePET.hh:44
int GetGeometricInfoFromDataFile(string a_pathToDataFilename)
Call the specialized function of the scanner object in order to get geometric informations from the d...
Declaration of class sAddonManager.
void GetUserEndianness()
Check user/host computer endianness and write it to the global variable User_Endianness.