CASToR  1.1
Tomographic Reconstruction (PET/SPECT)
 All Classes Files Functions Variables Typedefs Macros Groups Pages
castor-GATERootToCastor.cc
Go to the documentation of this file.
1 
8 #include "gVariables.hh"
9 #include "gOptions.hh"
10 #include "iDataFilePET.hh"
11 #include "iDataFileSPECT.hh"
12 #include "sOutputManager.hh"
13 #include "sScannerManager.hh"
15 #include <iomanip> //std::setprecision
16 
17 #ifdef CASTOR_ROOT
18  #include "TROOT.h"
19  #include "TApplication.h"
20  #include "TGClient.h"
21  #include "TCanvas.h"
22  #include "TSystem.h"
23  #include "TTree.h"
24  #include "TBranch.h"
25  #include "TFile.h"
26 #endif
27 
28 
29 #include "oImageSpace.hh"
30 #include "oProjectorManager.hh"
31 
32 
38 void ShowHelp(int a_returnCode)
39 {
40  cout << endl;
41  cout << "Usage: castor-GATERootToCastor -i path_to_ifile.root -OR- -il path_to_ifile.txt "<< endl;
42  cout << " -s scanner_alias "<< endl;
43  cout << " -o path_to_out_file "<< endl;
44  cout << " -m path_to_macro.mac " << endl;
45  cout << " [-t only convert true prompts]" << endl;
46  cout << " [-oh histogram datafile output]" << endl;
47  cout << " [-atn path_to_atn_image(cm-1)]" << endl;
48  cout << " [-k recover coincidence kind]" << endl;
49  cout << " [-ist isotope_alias" << endl;
50  cout << " [-ot time offsets in s]" << endl;
51  cout << " [-vb verbosity]" << endl;
52  cout << endl;
53  cout << endl;
54  cout << "[Main settings]:" << endl;
55  cout << " -i path_to_file.root : give an input root datafile to convert" << endl;
56  cout << " -il path_to_file.txt : give an input text file containing a list of root files to convert" << endl;
57  cout << " : they will be concatenated into 1 CASToR datafile" << endl;
58  cout << " : the path to each datafile to convert must be entered on a newline" << endl;
59  cout << " -m path_to_macro.mac : gives the input GATE macro file used for the GATE simulation" << endl;
60  cout << " -o path_to_out_file : give the path to the output file which will be created inside this folder (no default)" << endl;
61  cout << " -s scanner_alias : provide the name of the scanner used for to acquire the original data" << endl;
62  cout << " : Must correspond to a .geom or .hscan file in the config/scanner repository." << endl;
63  cout << " : A geom file can be created from the macro files using the facultative option -geo (see below)" << endl;
64  cout << endl;
65  cout << "[Optional settings]:" << endl;
66  cout << " -t : only the true prompts will be converted" << endl;
67  cout << " -oh : Indicate if the output datafile should be written in histogram format (default : List-mode)" << endl;
68  cout << " -atn path_image:proj : For PET histogram output, provide an attenuation image (cm-1) related to the acquisition." << endl;
69  cout << " Analytic projection will be performed during the data conversion in order to estimate PET attenuation correction factors (acf) for each histogram event" << endl;
70  cout << " path_image : path to the attenuation image" << endl;
71  cout << " proj : (optional) projector to use for analytic projection. Defaut projector = Incremental siddon" << endl;
72  cout << " -k : For List-mode output, write kind of coincidence (true/scatter/rdm/...) in the output datafile (disabled by default)" << endl;
73  cout << " -ist isotope_alias : provide alias of the isotope used during the simulation"<< endl;
74  cout << " Aliases for supported PET isotopes and their parameters are listed in config/misc/isotopes_pet"<< endl;
75  cout << " Other isotopes can be added in the same file"<< endl;
76  cout << " -isrc path_to_img:dims : Provide name and dimensions (separated by a colon) of an image generated with the source (annihilation) XYZ position"<< endl;
77  cout << " The option must start with the path to the output image which will be generated." << endl;
78  cout << " Dimensions and voxel sizes of the image must be provided using commas as separators, as in the following template:" << endl;
79  cout << " path/to/image:dimX,dimY,dimZ,voxSizeX,voxSizeY,voxSizeZ"<< endl;
80  cout << " -geo : Generate a CASToR geom file from the provided GATE macro file(s)"<< endl;
81  cout << " A geom file with the 'scanner_alias' (from the -s option) basename will be generated in the scanner repository (default location : /config/scanner)" << endl;
82  cout << " -sp_bins nbinsT,nbinsA : Option specific to simulation using SPECThead systems, with root output."<< endl;
83  cout << " Give transaxial and axial number of bins for projections, separated by a comma."<< endl;
84  cout << " Pixel sizes will be computed from the crystal surface and the transaxial/axial number of bins" << endl;
85  cout << " -ot list : Provide a serie of time offset in seconds to apply before each input file"<< endl;
86  cout << " (In the case of converting several datafiles of a dynamic acquisition, timestamps of events may be resetted for each file" << endl;
87  cout << " This variable allows to manually increment the time between each datafile(s) if required" << endl;
88  cout << " The number of time offsets must be equal to the number of input files, provided by -i or -if options." << endl;
89  cout << " 'list' is a list of time offsets, separated by ','" << endl;
90  cout << endl;
91  cout << "[Miscellaneous settings]:" << endl;
92  cout << " -vb : give the verbosity level, from 0 (no verbose) to above 5 (at the event level) (default: 1)." << endl;
93  cout << endl;
94  #ifdef CASTOR_VERSION
95  cout << " This program is part of the CASToR release version " << CASTOR_VERSION << "." << endl;
96  cout << endl;
97  #endif
98  Exit(a_returnCode);
99 }
100 
101 
102 /*
103  Main program
104 */
105 
106 int main(int argc, char** argv)
107 {
108 
109  // No argument, then show help
110  if (argc==1) ShowHelp(0);
111 
112  // ============================================================================================================
113  // Parameterized variables with their default values
114  // ============================================================================================================
115 
116  // String which gathers the path to the input data filename provided by the user. no default
117  string input_file = "";
118  vector<string> path_to_input_file;
119 
120  // Path to user provided data and output files/images
121  string path_to_out_file = "";
122  string path_to_data_filename = "";
123  string path_to_header_filename = "";
124  string path_to_mac_file = "";
125  string path_to_atn_image = "";
126  string path_to_src_image = "";
127 
128  // Scanner name provided by the user
129  string scanner_name = "";
130 
131  // GATE system type
132  int GATE_system_type = GATE_SYS_UNKNOWN;
133 
134  // Only recover true GEvents
135  bool true_only_flag = false;
136 
137  // Verbosity
138  int vb = 0;
139 
140  // Histogram output
141  bool histo_out_flag = false;
142 
143  // Estimate acf (histogram output)
144  bool estimate_acf_flag = false;
145  // Projector for analytic projection
146  string options_projector = "incrementalSiddon";
147 
148  // Recover kind of coincidence (list-mode output)
149  bool kind_flag = false;
150 
151  // Isotope alias
152  string istp_alias = "";
153 
154  // Variables related to the source image
155  bool src_img_flag = false;
156  INTNB dim_src_img[3];
157  FLTNB vox_src_img[3];
158  FLTNB* p_src_img = NULL;
159 
160  // Generate geom file
161  bool geom_flag = false;
162 
163  // Input is interfile (for SPECT simulation) -> not supported (def = false)
164  bool input_is_intf = false;
165 
166  // SPECT bins
167  uint16_t spect_bin_axl = 0,
168  spect_bin_trs = 0;
169 
170  // Time offsets
171  string offset_time_str = "";
172  uint32_t* offset_time_list = NULL;
173 
174  // ============================================================================================================
175  // Read command-line parameters
176  // ============================================================================================================
177  for (int i=1; i<argc; i++)
178  {
179  string option = (string)argv[i];
180 
181  if (option=="-h" || option=="--help" || option=="-help") ShowHelp(0);
182 
183  // Just one file is provided
184  if (option=="-i")
185  {
186  if (path_to_input_file.size() > 0)
187  {
188  Cerr("***** castor-GATERootToCastor :: the following file names have already been provided (-i/-il options must be used ONCE): " << endl);
189  for (size_t i=0 ; i<path_to_input_file.size() ; i++)
190  Cout(path_to_input_file[i] << endl);
191  Exit(EXIT_FAILURE);
192  }
193  else
194  {
195  if (argv[i+1] == NULL)
196  {
197  Cerr("***** castor-GATERootToCastor :: argument missing for option: " << option << endl);
198  Exit(EXIT_FAILURE);
199  }
200  else
201  {
202  input_file = argv[i+1];
203  path_to_input_file.push_back(input_file);
204  }
205  i++;
206  }
207  }
208 
209  // Read a text file containing a list of root datafiles to read
210  else if (option=="-il")
211  {
212  if (path_to_input_file.size() > 0)
213  {
214  Cerr("***** castor-GATERootToCastor :: the following file names have already been provided (-i/-il options must be used ONCE) " << endl);
215  for (size_t i=0 ; i<path_to_input_file.size() ; i++)
216  Cout(path_to_input_file[i] << endl);
217  Exit(EXIT_FAILURE);
218  }
219  else
220  {
221  if (argv[i+1] == NULL)
222  {
223  Cerr("***** castor-GATERootToCastor :: argument missing for option: " << option << endl);
224  Exit(EXIT_FAILURE);
225  }
226  else
227  {
228  ifstream ifile(argv[i+1], ios::in);
229  string line;
230 
231  // Read list of rootfgiles
232  if(ifile)
233  {
234  // Get the position of the list_file, then append the name of the content datafiles to this position.
235  input_file = argv[i+1];
236 
237  // Recover the files
238  while (getline(ifile, line))
239  {
240  string path_to_datafile = GetPathOfFile(input_file) + OS_SEP + line;
241  path_to_input_file.push_back(path_to_datafile);
242  }
243  }
244  else
245  {
246  Cerr("***** castor-GATERootToCastor :: Error, can't read txt file: " << argv[i+1] << endl);
247  Exit(EXIT_FAILURE);
248  }
249 
250  ifile.close();
251  }
252  i++;
253  }
254  }
255  // Mac file
256  else if (option=="-m")
257  {
258  path_to_mac_file = (string)argv[i+1];
259  i++;
260  }
261  // Scanner alias
262  else if (option=="-s")
263  {
264  if (argv[i+1] == NULL)
265  {
266  Cerr("***** castor-GATERootToCastor :: argument missing for option: " << option << endl);
267  Exit(EXIT_FAILURE);
268  }
269  else
270  scanner_name = argv[i+1];
271  i++;
272  }
273  // Output CASToR datafile
274  else if (option=="-o")
275  {
276  if (argv[i+1] == NULL)
277  {
278  Cerr("***** castor-GATERootToCastor :: argument missing for option: " << option << endl);
279  Exit(EXIT_FAILURE);
280  }
281  else
282  path_to_out_file = argv[i+1];
283  i++;
284  }
285  // Recover only trues
286  else if (option=="-t")
287  {
288  #ifdef CASTOR_ROOT
289  true_only_flag = true;
290  #else
291  Cerr("***** castor-GATERootToCastor :: Option: " << option << " is only available for dataset generated with Gate in a Root format." << endl);
292  Cerr("***** castor-GATERootToCastor :: Root support is currently not enabled (CASTOR_ROOT environnement variable should be set before compilation)" << endl);
293  Exit(EXIT_FAILURE);
294  #endif
295  }
296 
297  // Time offsets
298  else if (option=="-ot")
299  {
300  if (i>=argc-1)
301  {
302  Cerr("***** castor-GATERootToCastor :: Argument missing for option: " << option << endl);
303  Exit(EXIT_FAILURE);
304  }
305  offset_time_str = (string)argv[i+1];
306  i++;
307  }
308 
309  // Output datafile in histogram mode
310  else if (option=="-oh")
311  {
312  histo_out_flag = true;
313  }
314 
315  else if (option=="-atn")
316  {
317  if (i>=argc-1)
318  {
319  Cerr("***** castor-GATERootToCastor :: Argument missing for option: " << option << endl);
320  Exit(EXIT_FAILURE);
321  }
322 
323  path_to_atn_image = argv[i+1];
324 
325  // check first if a projector has been provided (':' included)
326  size_t pos = path_to_atn_image.find_first_of(":");
327 
328  if (pos != string::npos)
329  {
330  options_projector = path_to_atn_image.substr(pos+1);
331  path_to_atn_image = path_to_atn_image.substr(0,pos);
332  }
333 
334  estimate_acf_flag = true;
335  i++;
336  }
337 
338  // Output datafile in histogram mode
339  else if (option=="-k")
340  {
341  kind_flag = true;
342  }
343 
344  // Provide an isotope alias
345  else if (option=="-ist")
346  {
347  if (argv[i+1] == NULL)
348  {
349  Cerr("***** castor-GATERootToCastor :: argument missing for option: " << option << endl);
350  Exit(EXIT_FAILURE);
351  }
352  else
353  istp_alias = argv[i+1];
354 
355  i++;
356  }
357 
358  // Generate image from the sourceID
359  else if (option=="-isrc")
360  {
361  if (argv[i+1] == NULL)
362  {
363  Cerr("***** castor-GATERootToCastor :: argument missing for option: " << option << endl);
364  Exit(EXIT_FAILURE);
365  }
366  else
367  {
368  // Recover the path to the output image
369  string input = argv[i+1];
370  int pos_colon = input.find_first_of(":");
371  path_to_src_image = input.substr(0,pos_colon);
372  input = input.substr(pos_colon + 1);
373 
374  // Get string section related to dimensions
375  string p_dims_str[6];
376  if (ReadStringOption(input.c_str(), p_dims_str, 6, ",", option))
377  {
378  Cerr("***** castor-GATERootToCastor :: Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
379  Exit(EXIT_FAILURE);
380  }
381 
382  // Recover dimensions
383  for(int i=0 ; i<3 ; i++)
384  if (ConvertFromString(p_dims_str[i], &dim_src_img[i]))
385  {
386  Cerr("***** castor-GATERootToCastor :: Conversion error for elt " << p_dims_str[i] << " for option " << option << " !" << endl);
387  Exit(EXIT_FAILURE);
388  }
389 
390  // Recover dimensions
391  for(int i=0 ; i<3 ; i++)
392  if (ConvertFromString(p_dims_str[i+3], &vox_src_img[i]))
393  {
394  Cerr("***** castor-GATERootToCastor :: Conversion error for elt " << p_dims_str[i+3] << " for option " << option << " !" << endl);
395  Exit(EXIT_FAILURE);
396  }
397 
398  // Initilize source image
399  p_src_img = new FLTNB[dim_src_img[0]*dim_src_img[1]*dim_src_img[2]];
400 
401  for(int v=0 ; v<dim_src_img[0]*dim_src_img[1]*dim_src_img[2] ; v++)
402  p_src_img[v] = 0;
403 
404  src_img_flag = true;
405  }
406  i++;
407  }
408 
409  // Generate geom file
410  else if (option=="-geo")
411  {
412  geom_flag = true;
413  }
414 
415  // SPECT bins
416  else if (option=="-sp_bins")
417  {
418  string input = argv[i+1];
419  uint16_t s_bins[2];
420  if (ReadStringOption(input.c_str(), s_bins, 2, ",", option))
421  {
422  Cerr("***** castor-GATERootToCastor :: Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
423  Exit(EXIT_FAILURE);
424  }
425 
426  spect_bin_trs = s_bins[0];
427  spect_bin_axl = s_bins[1];
428 
429  i++;
430  }
431 
432 
433  // Verbosity level
434  else if (option=="-vb")
435  {
436  if (i>=argc-1)
437  {
438  Cerr("***** castor-GATERootToCastor :: Argument missing for option: " << option << endl);
439  Exit(EXIT_FAILURE);
440  }
441  vb = atoi(argv[i+1]);
442  i++;
443  }
444 
445  else
446  {
447  Cerr("***** castor-GATERootToCastor :: Unknown option '" << option << "' !" << endl);
448  Exit(EXIT_FAILURE);
449  }
450  }
451 
452 
453  // ============================================================================================================
454  // Mandatory checks:
455  // ============================================================================================================
456 
457  // Basic initialization checks (minimal initializations mandatory for the next steps)
458 
459  // data files
460  if (path_to_input_file.empty() )
461  {
462  Cerr("***** castor-GATERootToCastor :: Please provide at least one data filename (-i or -if)" << endl);
463  ShowHelp(0);
464  Exit(EXIT_FAILURE);
465  }
466  else
467  {
468  /*
469  // Check if we have interfile
470  if(path_to_input_file.size() == 1)
471  {
472  string check;
473  int rvalue = 0;
474  rvalue = IntfKeyGetValueFromFile(path_to_input_file[0], "interfile", &check, 1, KEYWORD_OPTIONAL);
475 
476  if(rvalue == 1)
477  {
478  // error
479  Cerr("***** castor-GATERootToCastor :: Error when trying to read file: " << path_to_input_file[0] << "!" << endl);
480  Exit(EXIT_FAILURE);
481  }
482  else if(rvalue == 0)
483  // key found, we have an interfile as input
484  input_is_intf = true;
485  }
486  */
487  if(vb >= 2)
488  {
489  Cout(" Selected root data-file(s) to convert: " << endl);
490  for (size_t i=0 ; i<path_to_input_file.size() ; i++)
491  Cout(path_to_input_file[i] << endl);
492  }
493  }
494 
495 
496 
497  if(!input_is_intf)
498  {
499  // Check ROOT is enabled if the input file is not interfile (SPECT)
500  #ifndef CASTOR_ROOT
501  Cerr("***** castor-GATERootToCastor :: CASToR must be compiled with ROOT to read input root files (check installation instructions)" << endl);
502  Exit(EXIT_FAILURE);
503  #endif
504  }
505  else if(src_img_flag) // intf input + image of the source -> error
506  {
507  Cerr("***** castor-GATERootToCastor :: Can't use -isrc with interfile dataset ");
508  Cerr(" (image of the source can only be generated from root file) !" << endl);
509  Exit(EXIT_FAILURE);
510  }
511 
512 
513 
514  // output directory
515  if (path_to_out_file.empty() )
516  {
517  Cerr("***** castor-GATERootToCastor :: Please provide the output file name (-o)" << endl);
518  ShowHelp(0);
519  Exit(EXIT_FAILURE);
520  }
521  else
522  if(vb >= 2) Cout(" selected output file:" << path_to_out_file << endl);
523 
524  // macro
525  if (path_to_mac_file.empty())
526  {
527  Cerr("***** castor-GATERootToCastor :: Please provide the macro file associated to the GATE root datafile (-m) :" << endl);
528  ShowHelp(0);
529  Exit(EXIT_FAILURE);
530  }
531  else
532  if(vb >= 2) Cout(" selected macro file: " << path_to_mac_file << endl);
533 
534  // scanner
535  if (scanner_name.empty())
536  {
537  Cerr("***** castor-GATERootToCastor :: Please provide a scanner alias (-s) :" << endl);
538  ShowHelp(0);
539  Exit(EXIT_FAILURE);
540  }
541  else
542  if(vb >= 2) Cout(" selected scanner alias: " << scanner_name << endl);
543 
544 
545  // (Required for options using interfile I/O)
547 
548 
549  // ============================================================================================================
550  // SOutputManager object initialisation:
551  // ============================================================================================================
552 
553  sOutputManager* p_outputManager = sOutputManager::GetInstance();
554  // Set verbose level
555  p_outputManager->SetVerbose(vb);
556  // Set MPI rank
557  p_outputManager->SetMPIRank(0);
558 
559  // Set path to the config directory
560  if (p_outputManager->CheckConfigDir(""))
561  {
562  Cerr("***** castor-GATERootToCastor :: A problem occured while checking for the config directory path !" << endl);
563  Exit(EXIT_FAILURE);
564  }
565  // Initialize output directory and base name
566  if (p_outputManager->InitOutputDirectory(path_to_out_file, ""))
567  {
568  Cerr("*****castor-GATERootToCastor :: A problem occured while initializing output directory !" << endl);
569  Exit(EXIT_FAILURE);
570  }
571  // Log command line
572  if (p_outputManager->LogCommandLine(argc,argv))
573  {
574  Cerr("***** castor-GATERootToCastor :: A problem occured while logging command line arguments !" << endl);
575  Exit(EXIT_FAILURE);
576  }
577 
578  // Output progression options
579  cout << std::fixed;
580  cout << std::setprecision(2);
581 
582 
583  // ============================================================================================================
584  // Check system type from the macro file
585  // ============================================================================================================
586  GATE_system_type = GetGATESystemType(path_to_mac_file);
587 
588  if(GATE_system_type<0)
589  {
590  // Unknown system
591  Cerr("***** castor-GATERootToCastor :: GATE system type not found : " << endl);
592  Cerr(" This script only supports conversion for cylindricalPET, ecat and SPECThead systems" << endl);
593  Cerr(" The system type is recovered from the lines '/gate/systems/...'" << endl);
594  Exit(EXIT_FAILURE);
595  }
596 
597 
598  // ============================================================================================================
599  // Generate the geom file from the mac file(s) is required
600  // ============================================================================================================
601  if(geom_flag)
602  {
603  string scanner_repository = sOutputManager::GetInstance()->GetPathToConfigDir() + "scanner" + OS_SEP;
604  string path_to_geom = scanner_repository + scanner_name + ".geom";
605 
606  // Check system type
607  switch ( GATE_system_type )
608  {
610  if( vb>=2 )Cout(endl << " --- CylindricalPET system detected. Proceeding to conversion... --- " << endl << endl);
611 
612  if(CreateGeomWithCylindrical(path_to_mac_file , path_to_geom) )
613  {
614  Cerr("***** castor-GATERootToCastor :: An error occured while trying to process mac file for cylindrical system: " << path_to_mac_file << endl);
615  Exit(EXIT_FAILURE);
616  }
617  break;
618 
619  case GATE_SYS_ECAT:
620  if( vb>=2 )Cout(endl << " --- ECAT system detected. Proceeding to conversion... --- " << endl << endl);
621 
622  if(CreateGeomWithECAT(path_to_mac_file , path_to_geom) )
623  {
624  Cerr("***** castor-GATEMacToGeom :: An error occured while trying to process mac file for ecat system: " << path_to_mac_file << endl);
625  Exit(EXIT_FAILURE);
626  }
627  break;
628  // TODO
629  case GATE_SYS_SPECT:
630  if( vb>=2 )Cout(endl << " --- SPECThead system detected. Proceeding to conversion... --- " << endl << endl);
631 
632  if(CreateGeomWithSPECT(path_to_mac_file , path_to_geom) )
633  {
634  Cerr("***** castor-GATEMacToGeom :: An error occured while trying to process mac file for SPECT system: " << path_to_mac_file << endl);
635  Exit(EXIT_FAILURE);
636  }
637  break;
638 
639  default: // Unknown system
640  Cerr("***** castor-GATERootToCastor :: System type not found : " << endl);
641  Cerr(" This script only supports conversion for cylindricalPET ecat and SPECThead systems" << endl);
642  Cerr(" The system type is recovered from the lines '/gate/systems/...'" << endl);
643  Exit(EXIT_FAILURE);
644  break;
645  }
646 
647  if( vb>=2 )Cout(endl << " --- Conversion completed --- " << endl << endl);
648  }
649 
650 
651  // ============================================================================================================
652  // ScannerManager object initialisation:
653  // ============================================================================================================
654 
655  sScannerManager* p_scannermanager = sScannerManager::GetInstance();
656  p_scannermanager->SetVerbose(vb);
657 
658  // Check if the scanner exists and get the name from ScannerManager
659  scanner_name = (scanner_name.find(OS_SEP)) ?
660  scanner_name.substr(scanner_name.find_last_of(OS_SEP)+1) :
661  scanner_name;
662 
663  if(p_scannermanager->FindScannerSystem(scanner_name) )
664  {
665  Cerr("**** castor-GATERootToCastor :: A problem occurred while searching for scanner system !" << endl);
666  Exit(EXIT_FAILURE);
667  }
668 
669  // Build output file names
670  path_to_data_filename = path_to_out_file + ".Cdf";
671  path_to_header_filename = path_to_out_file + ".Cdh";
672 
673 
674  // ============================================================================================================
675  // Instanciate/Initialize CASToR Datafile
676  // ============================================================================================================
677 
678  // Instantiate & Initialize oImageDimensionsAndQuantification object, required for datafile generation (number of threads)
680 
681  // Set isotope if provided
682  if(!istp_alias.empty())
683  {
684  if(p_ID->SetPETIsotope(0, istp_alias) )
685  {
686  Cerr("**** castor-GATERootToCastor :: A problem occurred while checking isotope name !" << endl);
687  Exit(EXIT_FAILURE);
688  }
689  }
690 
691  // Instanciate & Initialize iDataFilePET and Event objects
692  vDataFile* Out_data_file = NULL;
693  vEvent* Event = NULL;
694 
695  uint16_t max_nb_lines_per_event = 1; // No compression for root files
696 
697  if(GATE_system_type == GATE_SYS_SPECT)
698  {
699  Out_data_file = new iDataFileSPECT();
700  iDataFileSPECT* p_datafile = (dynamic_cast<iDataFileSPECT*>(Out_data_file));
701  p_datafile->SetDataType(TYPE_SPECT);
702  p_datafile->SetIsotope(istp_alias);
703  histo_out_flag = true; // force histogram output for SPECT
704  }
705  else
706  {
707  Out_data_file = new iDataFilePET();
708  iDataFilePET* p_datafile = (dynamic_cast<iDataFilePET*>(Out_data_file));
709  p_datafile->SetDataType(TYPE_PET);
710  p_datafile->SetIsotope(istp_alias);
711 
712  // ACF computed
713  if(estimate_acf_flag)
714  p_datafile->SetAtnCorrectionFlagOn();
715 
716  p_datafile->SetMaxNumberOfLinesPerEvent(max_nb_lines_per_event);
717  }
718 
719  Out_data_file->SetImageDimensionsAndQuantification(p_ID);
720  Out_data_file->SetHeaderDataFileName(path_to_header_filename);
721  Out_data_file->SetPercentageLoad(0); // 0 (default)
722  Out_data_file->SetVerbose(0);
723 
724 
725  // Init Histogram-mode Event
726  if(histo_out_flag)
727  {
728  Out_data_file->SetDataMode(MODE_HISTOGRAM);
729 
730  // Instanciate histogram Event depending on modality
731  if(GATE_system_type == GATE_SYS_SPECT)
732  Event = new iEventHistoSPECT();
733  else
734  Event = new iEventHistoPET();
735 
736  Event->SetNbLines(max_nb_lines_per_event);
737  Event->AllocateID();
738  }
739 
740  // Init List-mode Event
741  else
742  {
743  Out_data_file->SetDataMode(MODE_LIST);
744 
745  // Instanciate histogram Event depending on modality
746  if(GATE_system_type == GATE_SYS_SPECT)
747  {
748  Event = new iEventListSPECT();
749  // record coincidence kind or not
750  if(kind_flag)
751  ((iDataFileSPECT*)Out_data_file)->SetEventKindFlagOn();
752  }
753  else
754  {
755  Event = new iEventListPET();
756  // record coincidence kind or not
757  if(kind_flag)
758  ((iDataFilePET*)Out_data_file)->SetEventKindFlagOn();
759  }
760 
761  Event->SetNbLines(max_nb_lines_per_event);
762  Event->AllocateID();
763  }
764 
765  Out_data_file->PROJ_InitFile();
766  Out_data_file->ComputeSizeEvent();
767  Out_data_file->PrepareDataFile();
768 
769 
770  // ============================================================================================================
771  // If acf estimation is enabled for histogram output, initialize all required objects for analytic projection
772  // (Image space, projector and scanner geometry)
773  // ============================================================================================================
774  oProjectorManager* p_ProjectorManager = new oProjectorManager();
775  oImageSpace* p_ImageSpace = new oImageSpace();
776 
777 
778  if(estimate_acf_flag)
779  {
780  // Check if histogram output has been enabled, throw error otherwise
781  if(!histo_out_flag)
782  {
783  Cerr("***** castor-GATERootToCastor :: Estimation of acf from an attenuation image (-atn option) is only available for histogram datafile output !" << endl
784  << " Add the (-oh) option to the command line to enable this option." << endl);
785  Exit(1);
786  }
787 
788  // Check if system is SPECT, throw error in this case
789  if(GATE_system_type == GATE_SYS_SPECT)
790  {
791  Cerr("***** castor-GATERootToCastor :: Estimation of acf from an attenuation image (-atn option) only available for PET systems ! (detected system is SPECT)" << endl);
792  Exit(1);
793  }
794 
795  Intf_fields IF;
796  IntfKeyInitFields(&IF);
797  if(IntfReadHeader(path_to_atn_image, &IF, vb) )
798  {
799  Cerr("***** castor-GATERootToCastor :: An error occurred while trying to read the interfile header of attenuation file " << path_to_atn_image << " !" << endl);
800  Exit(1);
801  }
802 
803  // --- oImageDimensionsAndQuantification initialization ---
804  p_ID->SetNbVoxX(IF.mtx_size[0]);
805  p_ID->SetNbVoxY(IF.mtx_size[1]);
806  p_ID->SetNbVoxZ(IF.mtx_size[2]);
807  p_ID->SetNbThreads("1");
808  p_ID->SetNbBeds(1);
809  p_ID->SetVoxSizeX(IF.vox_size[0]);
810  p_ID->SetVoxSizeY(IF.vox_size[1]);
811  p_ID->SetVoxSizeZ(IF.vox_size[2]);
812  p_ID->SetFOVOutMasking(0., 0);
813  p_ID->SetFOVSizeX(-1.);
814  p_ID->SetFOVSizeY(-1.);
815  p_ID->SetFOVSizeZ(-1.);
816  p_ID->SetOffsetX(0);
817  p_ID->SetOffsetY(0);
818  p_ID->SetOffsetZ(0);
819  p_ID->SetVerbose(vb);
820  p_ID->SetNbRespGates(1);
821  p_ID->SetNbCardGates(1);
822  p_ID->SetFrames("");
823 
824  if (p_ID->CheckParameters())
825  {
826  Cerr("***** castor-GATERootToCastor :: A problem occured while checking image dimensions parameters !" << endl);
827  Exit(1);
828  }
829  if (p_ID->Initialize())
830  {
831  Cerr("***** castor-GATERootToCastor :: A problem occured while initializing image dimensions !" << endl);
832  Exit(1);
833  }
834 
835  // Initialization of DynamicDataManager class, related 4D data splitting management
836  if (p_ID->InitDynamicData( "", 0, 0, 0, 0, 1, 1 ) )
837  {
838  Cerr("***** castor-GATERootToCastor :: A problem occured while initializing Dynamic data manager's class !" << endl);
839  Exit(EXIT_FAILURE);
840  }
841 
842 
843  // --- Image space initialization ---
844  p_ImageSpace->SetImageDimensionsAndQuantification(p_ID);
845  p_ImageSpace->SetVerbose(vb);
846 
847  // Allocate memory for main image
848  p_ImageSpace->LMS_InstantiateImage();
849 
850  // Read attenuation image
851  if(p_ImageSpace->PROJ_LoadInitialImage(path_to_atn_image) )
852  {
853  Cerr("***** castor-GATERootToCastor :: Error during image initialization !" << endl);
854  Exit(EXIT_FAILURE);
855  }
856 
857 
858  // --- Build Scanner geometry ---
859  if(p_scannermanager->BuildScannerObject() )
860  {
861  Cerr("**** castor-GATERootToCastor :: A problem occurred during scanner object construction !" << endl);
862  Exit(EXIT_FAILURE);
863  }
864 
865  if(p_scannermanager->InstantiateScanner() )
866  {
867  Cerr("**** castor-GATERootToCastor :: A problem occurred while creating Scanner object !" << endl);
868  Exit(EXIT_FAILURE);
869  }
870 
871  if(p_scannermanager->BuildLUT() )
872  {
873  Cerr("***** castor-GATERootToCastor :: A problem occurred while generating/reading the LUT !" << endl);
874  Exit(EXIT_FAILURE);
875  }
876 
877  // Check the scanner manager parameters and initialize the scanner
878  if (p_scannermanager->CheckParameters())
879  {
880  Cerr("***** castor-GATERootToCastor :: A problem occured while checking scanner manager parameters !" << endl);
881  Exit(1);
882  }
883 
884  if (p_scannermanager->Initialize())
885  {
886  Cerr("***** castor-GATERootToCastor :: A problem occured while initializing scanner !" << endl);
887  Exit(1);
888  }
889 
890 
891  // --- Projector Manager initialization---
892  p_ProjectorManager->SetScanner(p_scannermanager->GetScannerObject());
893  p_ProjectorManager->SetImageDimensionsAndQuantification(p_ID);
894  p_ProjectorManager->SetDataFile(Out_data_file);
896  p_ProjectorManager->SetOptionsForward(options_projector);
897  p_ProjectorManager->SetOptionsBackward(options_projector);
898  p_ProjectorManager->SetOptionsCommon("");
899  p_ProjectorManager->SetVerbose(vb);
900 
901  // Check parameters
902  if (p_ProjectorManager->CheckParameters())
903  {
904  Cerr("***** castor-GATERootToCastor :: A problem occured while checking projector manager's parameters !" << endl);
905  Exit(EXIT_FAILURE);
906  }
907 
908  // Initialize projector manager
909  if (p_ProjectorManager->Initialize())
910  {
911  Cerr("***** castor-GATERootToCastor :: A problem occured while initializing projector manager !" << endl);
912  Exit(EXIT_FAILURE);
913  }
914  }
915 
916 
917  // ============================================================================================================
918  // Parse Time offsets
919  // ============================================================================================================
920  offset_time_list = new uint32_t[path_to_input_file.size()];
921  for(size_t f=0 ; f<path_to_input_file.size() ; f++)
922  offset_time_list[f] = 0;
923 
924  // Parse offset_time_str, if it contains any data
925  if(offset_time_str != "")
926  {
927  vector<string> offsets;
928  size_t comma_pos = 0;
929  while ((comma_pos=offset_time_str.find_first_of(",")) != string::npos)
930  {
931  string offset = offset_time_str.substr(0,comma_pos);
932  offsets.push_back(offset);
933  offset_time_str = offset_time_str.substr(comma_pos+1);
934  }
935 
936  // Check we have a correct number of offsets
937  if(offsets.size() != path_to_input_file.size())
938  {
939  Cerr("**** castor-GATERootToCastor :: Unmatching number of offsets with -ot option ! "
940  << offsets.size() << " have been found, while "<< path_to_input_file.size() <<"input file have been provided !" << endl);
941  Exit(EXIT_FAILURE);
942  }
943 
944  for(size_t o=0 ; o<offsets.size() ; o++)
945  {
946  double offset;
947  if(ConvertFromString(offsets[o] , &offset) )
948  {
949  Cerr("**** castor-GATERootToCastor :: Error while trying to convert offset : "<< offsets[o] <<" in ms ! " << endl);
950  Exit(EXIT_FAILURE);
951  }
952 
953  // convert in ms
954  offset_time_list[o] = (uint32_t)offset*1000;
955  }
956  }
957 
958 
959  // ============================================================================================================
960  // *********************************************** CONVERSION *************************************************
961  // ============================================================================================================
962  Cout(" --- Start conversion of datafile(s) : " << input_file << endl
963  << " using mac file: " << path_to_mac_file << endl
964  << " CASToR output header datafile: " << path_to_header_filename << endl
965  << " CASToR output binary datafile: " << path_to_data_filename << endl << endl);
966 
967  // ============================================================================================================
968  // Variables initialization
969  // ============================================================================================================
970 
971  // Counter for the number of events (and the number of trues, scatters and randoms for simulated data)
972  uint64_t nLORs_tot = 0,
973  nLORs_trues = 0,
974  nLORs_rdms = 0,
975  nLORs_scatters =0,
976  nLORs_unknown =0,
977  nBINs = 0;
978 
979  // Scanner variables (PET)
980  uint32_t nCrystalsTot = 0;
981  uint32_t nRsectorsPerRing = 1;
982  uint32_t nModulesTransaxial = 1, nModulesAxial = 1;
983  uint32_t nSubmodulesTransaxial = 1, nSubmodulesAxial = 1;
984  uint32_t nCrystalsTransaxial = 1, nCrystalsAxial = 1;
985  uint32_t nBlocksLine = 1, nBlocksPerRing = 1;
986  uint8_t nLayers = 1;
987  uint32_t nb_crystal_per_layer[4] = {0,0,0,0};
988 
989  // Scanner variables (SPECT)
990  uint32_t nProjectionsByHead =1;
991  uint32_t nProjectionsTot = 1;
992  uint32_t nHeads =1;
993  uint32_t nPixelsAxial = 1;
994  uint32_t nPixelsTransaxial = 1;
995  uint32_t nbSimulatedPixels = 1;
996  float_t distToDetector = 0.;
997  int headRotDirection = GEO_ROT_CW;
998  float_t head1stAngleDeg = 0;
999  float_t headAngPitchDeg = -1;
1000  float_t headAngStepDeg = -1;
1001  float_t crystalSizeAxl=-1.,
1002  crystalSizeTrs=-1.;
1003  FLTNB* p_proj_spect_image=NULL;
1004 
1005  // layer repeaters
1006  vector<uint32_t> nLayersRptTransaxial, nLayersRptAxial;
1007 
1008  // Castor variables
1009  uint8_t** p_bins = NULL;
1010  uint32_t bins_elts = 0;
1011  uint32_t start_time_ms = 0; // 0 as default initialization
1012  uint32_t duration_ms = 1000; // 1 second as default initialization
1013 
1014 
1015  #ifdef CASTOR_ROOT
1016  uint32_t castorID1=0;
1017  uint32_t castorID2=0;
1018  uint8_t kind;
1019 
1020  // ROOT data variables
1021  int32_t crystalID1=0, crystalID2=0;
1022 
1023  // cylindricalPET specific
1024  int32_t rsectorID1=0 , rsectorID2=0;
1025  int32_t moduleID1=0 , moduleID2=0;
1026  int32_t submoduleID1=0, submoduleID2=0;
1027  int32_t layerID1=0 , layerID2=0;
1028 
1029  // ecat specific
1030  int32_t blockID1=0, blockID2=0;
1031 
1032  // SPECThead specific
1033  float_t rotAngle;
1034  float_t gPosX, gPosY, gPosZ;
1035  int32_t headID=0;
1036  int32_t pixelID=0;
1037 
1038 
1039  // others
1040  int32_t eventID1= 0, eventID2= 0;
1041  int32_t comptonPhantomID1 = 0, comptonPhantomID2= 0;
1042  int32_t rayleighPhantomID1 = 0,rayleighPhantomID2 = 0;
1043  double_t time1= 0, time2= 0;
1044  int32_t sourceID1=0, sourceID2=0;
1045  float_t sourcePosX1=0., sourcePosY1=0., sourcePosZ1=0.;
1046 
1047 
1048  // ============================================================================================================
1049  // ROOT objects declaration
1050  // ============================================================================================================
1051 
1052  TApplication *Tapp = new TApplication("tapp",0,0);
1053  TTree** GEvents = new TTree *[path_to_input_file.size()];
1054  TFile** Tfile_root = new TFile*[path_to_input_file.size()];
1055 
1056  if(!input_is_intf)
1057  {
1058  // Compute the total number of LORs in the dataset
1059  for (size_t iFic=0 ; iFic<path_to_input_file.size() ; iFic++)
1060  {
1061  Tfile_root[iFic] = new TFile(path_to_input_file[iFic].c_str(),"READ","ROOT file with histograms");
1062  if(GATE_system_type == GATE_SYS_SPECT)
1063  GEvents[iFic] = (TTree*)Tfile_root[iFic]->Get("Singles");
1064  else
1065  GEvents[iFic] = (TTree*)Tfile_root[iFic]->Get("Coincidences");
1066 
1067  nLORs_tot += GEvents[iFic]->GetEntries();
1068  }
1069  }
1070  #endif
1071 
1072 
1073  // Indexes for progression output
1074  uint64_t printing_index = 0;
1075  uint64_t printing_ratio = (nLORs_tot>10000) ? 10000 : nLORs_tot/10;
1076 
1077  // ============================================================================================================
1078  // Recover system geometric elements values
1079  // ============================================================================================================
1080 
1081  // SPECThead system
1082  if(GATE_system_type == GATE_SYS_SPECT)
1083  {
1084  duration_ms =0.;
1085 
1086  // Data provided as an interfile projection image
1087  if(input_is_intf)
1088  {
1089  if(ReadIntfSPECT( path_to_input_file[0],
1090  distToDetector,
1091  nHeads,
1092  nPixelsAxial,
1093  nPixelsTransaxial,
1094  crystalSizeAxl,
1095  crystalSizeTrs,
1096  nProjectionsTot,
1097  nProjectionsByHead,
1098  head1stAngleDeg,
1099  headAngPitchDeg,
1100  headAngStepDeg,
1101  headRotDirection,
1102  start_time_ms,
1103  duration_ms,
1104  vb) )
1105  {
1106  Cerr("**** castor-GATERootToCastor :: Error when reading mac file : "<< path_to_mac_file <<" !" << endl);
1107  Exit(EXIT_FAILURE);
1108  }
1109 
1110  nCrystalsTot = nPixelsAxial * nPixelsTransaxial;
1111 
1112  // Read Interfile
1113  Intf_fields IF_proj_spect_data;
1114  p_proj_spect_image = new FLTNB[nHeads*nProjectionsByHead*nCrystalsTot];
1115 
1116  if( IntfReadProjectionImage(path_to_input_file[0], p_proj_spect_image, &IF_proj_spect_data, vb, false) )
1117  {
1118  Cerr("**** castor-GATERootToCastor :: Error when trying to read image : "<< path_to_input_file[0] <<" !" << endl);
1119  Exit(EXIT_FAILURE);
1120  }
1121  }
1122 
1123  // Data provided as a root file
1124  else
1125  {
1126  if(ReadMacSPECT(path_to_mac_file,
1127  distToDetector,
1128  nHeads,
1129  nPixelsAxial,
1130  nPixelsTransaxial,
1131  crystalSizeAxl,
1132  crystalSizeTrs,
1133  nProjectionsTot,
1134  nProjectionsByHead,
1135  head1stAngleDeg,
1136  headAngPitchDeg,
1137  headAngStepDeg,
1138  headRotDirection,
1139  start_time_ms,
1140  duration_ms,
1141  vb) )
1142  {
1143  Cerr("**** castor-GATERootToCastor :: Error when reading mac file : "<< path_to_mac_file <<" !" << endl);
1144  Exit(EXIT_FAILURE);
1145  }
1146 
1147  nbSimulatedPixels = nPixelsAxial*nPixelsTransaxial;
1148 
1149  if((spect_bin_trs>0 || spect_bin_axl>0) && nbSimulatedPixels > 1 )
1150  {
1151  Cerr("**** castor-GATERootToCastor :: WARNING : Spect bins have been initialized, but the simulation already provide a specific number of pixels (="<< nPixelsAxial*nPixelsTransaxial <<") !"<< endl <<
1152  " Pixel matrix used by default !" << endl);
1153  Exit(EXIT_FAILURE);
1154  }
1155  else // Check bins have been provided, and initialize pixel sizes with provided values
1156  {
1157  if(spect_bin_trs == 0 && spect_bin_axl == 0 && nbSimulatedPixels==1)
1158  {
1159  Cerr("**** castor-GATERootToCastor :: Error : Axial and transaxial bins values expected (use option -spect_b) !"<< endl);
1160  Exit(EXIT_FAILURE);
1161  }
1162 
1163  // check crystal sizes have been correctly read
1164  if(crystalSizeAxl<0 || crystalSizeTrs<0)
1165  {
1166  Cerr("**** castor-GATERootToCastor :: Crystal dimensions not correctly read in the mac files !" << endl);
1167  Exit(EXIT_FAILURE);
1168  }
1169 
1170  nPixelsTransaxial = spect_bin_trs;
1171  nPixelsAxial = spect_bin_axl;
1172 
1173  if(vb>=2) Cout("Transaxial/Axial nb pixels : " << nPixelsTransaxial << " , " << nPixelsAxial << endl <<
1174  "Transaxial/Axial pixel sizes : " << crystalSizeTrs/nPixelsTransaxial << " , " << crystalSizeAxl/nPixelsAxial << endl);
1175  }
1176  }
1177 
1178  nCrystalsTot = nPixelsAxial * nPixelsTransaxial;
1179 
1180  if(vb>=2) Cout("Number of Projections: " << nProjectionsByHead << endl <<
1181  "Detected number of crystals in the system : " << nCrystalsTot << endl);
1182 
1183 
1184  // Histogram bin vector initialization using the total number of projections & pixels
1185  if(histo_out_flag)
1186  {
1187  bins_elts = nHeads*nProjectionsByHead;
1188 
1189  p_bins = new uint8_t*[bins_elts];
1190  for (size_t p=0; p<bins_elts ; p++)
1191  {
1192  p_bins[p] = new uint8_t[nCrystalsTot];
1193 
1194  for (size_t c=0; c<nCrystalsTot ; c++)
1195  {
1196  p_bins[p][c] = input_is_intf ? (uint8_t)p_proj_spect_image[p*nCrystalsTot+c] : 0 ;
1197 
1198  // Get number of singles if input is interfile proj image
1199  if(input_is_intf)
1200  {
1201  nLORs_tot += p_proj_spect_image[p*nCrystalsTot+c];
1202  nLORs_unknown += p_proj_spect_image[p*nCrystalsTot+c];
1203  }
1204  }
1205  }
1206  }
1207 
1208  delete[] p_proj_spect_image;
1209  }
1210 
1211  else // PET systems
1212  {
1213  // cylindricalPET system
1214  if(GATE_system_type == GATE_SYS_CYLINDRICAL)
1215  {
1216  if(ReadMacCylindrical(path_to_mac_file,
1217  nLayers,
1218  nb_crystal_per_layer,
1219  nCrystalsTot,
1220  nCrystalsAxial,
1221  nCrystalsTransaxial,
1222  nLayersRptAxial,
1223  nLayersRptTransaxial,
1224  nSubmodulesAxial,
1225  nSubmodulesTransaxial,
1226  nModulesAxial,
1227  nModulesTransaxial,
1228  nRsectorsPerRing,
1229  start_time_ms,
1230  duration_ms,
1231  vb) )
1232  {
1233  Cerr("**** castor-GATERootToCastor :: Error when reading mac file : "<< path_to_mac_file <<" !" << endl);
1234  Exit(EXIT_FAILURE);
1235  }
1236  }
1237 
1238  else // ECAT
1239  {
1240  // Reading the macro file
1241  if(ReadMacECAT(path_to_mac_file,
1242  nCrystalsTot,
1243  nCrystalsAxial,
1244  nCrystalsTransaxial,
1245  nBlocksLine,
1246  nBlocksPerRing,
1247  start_time_ms,
1248  duration_ms,
1249  vb) )
1250  {
1251  Cerr("**** castor-GATERootToCastor :: Error when reading mac file : "<< path_to_mac_file <<" !" << endl);
1252  Exit(EXIT_FAILURE);
1253  }
1254 
1255  }
1256 
1257  if(vb>=2) Cout("Detected number of crystals in the system : " << nCrystalsTot << endl);
1258 
1259  // Histogram bin vector initialization using the total number of crystals
1260  if(histo_out_flag)
1261  {
1262  Cout(" Allocating memory for bins... " << endl <<
1263  " Warning : this step can require huge amount of memory if the system contains a high number of crystals !" << endl);
1264 
1265  bins_elts = nCrystalsTot;
1266 
1267  p_bins = new uint8_t*[bins_elts];
1268  for (size_t c=0; c<bins_elts ; c++)
1269  {
1270  p_bins[c] = new uint8_t[nCrystalsTot-c];
1271 
1272  for (size_t c2=0; c2<nCrystalsTot-c ; c2++)
1273  p_bins[c][c2] = 0;
1274  }
1275 
1276  Cout(" Memory allocation for bins completed " << endl << endl);
1277  }
1278 
1279  } // end of PET section
1280 
1281 
1282 
1283 
1284  // ============================================================================================================
1285  // Loop on the input datafile(s) and process event by event
1286  // ============================================================================================================
1287  if(!input_is_intf) // SPECT projection interfile : data already processed
1288  for (size_t iFic=0 ; iFic<path_to_input_file.size() ; iFic++)
1289  {
1290  if(vb>=2) Cout(endl << "Processing datafile " << iFic << " : " << path_to_input_file[iFic] << "..." << endl);
1291 
1292  // Set variables of the root tree
1293  // If we got a cylindricalPET system
1294  #ifdef CASTOR_ROOT
1295  if(GATE_system_type == GATE_SYS_CYLINDRICAL)
1296  {
1297  GEvents[iFic]->SetBranchAddress("time1",&time1);
1298  GEvents[iFic]->SetBranchAddress("rsectorID1",&rsectorID1);
1299  GEvents[iFic]->SetBranchAddress("moduleID1",&moduleID1);
1300  GEvents[iFic]->SetBranchAddress("submoduleID1",&submoduleID1);
1301  GEvents[iFic]->SetBranchAddress("crystalID1",&crystalID1);
1302  GEvents[iFic]->SetBranchAddress("layerID1", &layerID1);
1303  GEvents[iFic]->SetBranchAddress("comptonPhantom1",&comptonPhantomID1);
1304  GEvents[iFic]->SetBranchAddress("RayleighPhantom1",&rayleighPhantomID1);
1305  GEvents[iFic]->SetBranchAddress("eventID1",&eventID1);
1306  GEvents[iFic]->SetBranchAddress("sourceID1",&sourceID1);
1307 
1308  GEvents[iFic]->SetBranchAddress("time2",&time2);
1309  GEvents[iFic]->SetBranchAddress("rsectorID2",&rsectorID2);
1310  GEvents[iFic]->SetBranchAddress("moduleID2",&moduleID2);
1311  GEvents[iFic]->SetBranchAddress("submoduleID2",&submoduleID2);
1312  GEvents[iFic]->SetBranchAddress("crystalID2",&crystalID2);
1313  GEvents[iFic]->SetBranchAddress("layerID2", &layerID2);
1314  GEvents[iFic]->SetBranchAddress("comptonPhantom2",&comptonPhantomID2);
1315  GEvents[iFic]->SetBranchAddress("RayleighPhantom2",&rayleighPhantomID2);
1316  GEvents[iFic]->SetBranchAddress("eventID2",&eventID2);
1317  GEvents[iFic]->SetBranchAddress("sourceID2",&sourceID2);
1318 
1319  GEvents[iFic]->SetBranchAddress("sourcePosX1",&sourcePosX1);
1320  GEvents[iFic]->SetBranchAddress("sourcePosY1",&sourcePosY1);
1321  GEvents[iFic]->SetBranchAddress("sourcePosZ1",&sourcePosZ1);
1322  }
1323  else if(GATE_system_type == GATE_SYS_SPECT)
1324  {
1325  GEvents[iFic]->SetBranchAddress("time",&time1);
1326  GEvents[iFic]->SetBranchAddress("headID", &headID);
1327  GEvents[iFic]->SetBranchAddress("crystalID",&crystalID1);
1328  GEvents[iFic]->SetBranchAddress("pixelID", &pixelID);
1329  GEvents[iFic]->SetBranchAddress("rotationAngle", &rotAngle);
1330  GEvents[iFic]->SetBranchAddress("globalPosX",&gPosX);
1331  GEvents[iFic]->SetBranchAddress("globalPosY",&gPosY);
1332  GEvents[iFic]->SetBranchAddress("globalPosZ",&gPosZ);
1333  GEvents[iFic]->SetBranchAddress("comptonPhantom",&comptonPhantomID1);
1334  GEvents[iFic]->SetBranchAddress("RayleighPhantom",&rayleighPhantomID1);
1335  GEvents[iFic]->SetBranchAddress("sourcePosX",&sourcePosX1);
1336  GEvents[iFic]->SetBranchAddress("sourcePosY",&sourcePosY1);
1337  GEvents[iFic]->SetBranchAddress("sourcePosZ",&sourcePosZ1);
1338  }
1339  else
1340  {
1341  GEvents[iFic]->SetBranchAddress("time1",&time1);
1342  GEvents[iFic]->SetBranchAddress("blockID1",&blockID1);
1343  GEvents[iFic]->SetBranchAddress("crystalID1",&crystalID1);
1344  GEvents[iFic]->SetBranchAddress("comptonPhantom1",&comptonPhantomID1);
1345  GEvents[iFic]->SetBranchAddress("RayleighPhantom1",&rayleighPhantomID1);
1346  GEvents[iFic]->SetBranchAddress("eventID1",&eventID1);
1347  GEvents[iFic]->SetBranchAddress("sourceID1",&sourceID1);
1348 
1349  GEvents[iFic]->SetBranchAddress("time2",&time2);
1350  GEvents[iFic]->SetBranchAddress("blockID2",&blockID2);
1351  GEvents[iFic]->SetBranchAddress("crystalID2",&crystalID2);
1352  GEvents[iFic]->SetBranchAddress("comptonPhantom2",&comptonPhantomID2);
1353  GEvents[iFic]->SetBranchAddress("RayleighPhantom2",&rayleighPhantomID2);
1354  GEvents[iFic]->SetBranchAddress("eventID2",&eventID2);
1355  GEvents[iFic]->SetBranchAddress("sourceID2",&sourceID2);
1356  GEvents[iFic]->SetBranchAddress("sourcePosX1",&sourcePosX1);
1357  GEvents[iFic]->SetBranchAddress("sourcePosY1",&sourcePosY1);
1358  GEvents[iFic]->SetBranchAddress("sourcePosZ1",&sourcePosZ1);
1359  }
1360 
1361 
1362 
1363 
1364  //---------------------------------------------- /ROOT data variables
1365 
1366  // Loop on the GEvents in the current datafile
1367  for (int i=0; i<GEvents[iFic]->GetEntries() ; i++)
1368  {
1369  GEvents[iFic]->GetEntry(i);
1370  printing_index++;
1371 
1372  if(vb >= 4)
1373  Cout("File#" << iFic << ", event#" << i << endl;);
1374 
1375  // ID Conversions
1376  if (GATE_system_type == GATE_SYS_CYLINDRICAL)
1377  {
1378  if(vb >= 4)
1379  {
1380  Cout("Crystal 1 : RsectorID: " << rsectorID1 << ", moduleID: " << moduleID1 << ", submoduleID: " << submoduleID1 << ", crystalID: " << crystalID1
1381  << ", layerID: " << layerID1 << endl;);
1382  Cout("Crystal 2 :RsectorID: " << rsectorID2 << ", moduleID2: " << moduleID2 << ", submoduleID: " << submoduleID2 << ", crystalID: " << crystalID2
1383  << ", layerID: " << layerID2 << endl;);
1384  }
1385 
1386  castorID1 = ConvertIDcylindrical(nRsectorsPerRing,
1387  nModulesTransaxial, nModulesAxial,
1388  nSubmodulesTransaxial, nSubmodulesAxial,
1389  nCrystalsTransaxial, nCrystalsAxial,
1390  nLayers, nb_crystal_per_layer,
1391  nLayersRptTransaxial, nLayersRptAxial,
1392  layerID1, crystalID1, submoduleID1, moduleID1, rsectorID1);
1393 
1394  castorID2 = ConvertIDcylindrical(nRsectorsPerRing,
1395  nModulesTransaxial, nModulesAxial,
1396  nSubmodulesTransaxial, nSubmodulesAxial,
1397  nCrystalsTransaxial, nCrystalsAxial,
1398  nLayers, nb_crystal_per_layer,
1399  nLayersRptTransaxial, nLayersRptAxial,
1400  layerID2, crystalID2, submoduleID2, moduleID2, rsectorID2);
1401 
1402  if(vb >= 4)
1403  {
1404  Cout("--> castorID1: " << castorID1 << endl;);
1405  Cout("--> castorID2: " << castorID2 << endl;);
1406  }
1407  }
1408 
1409  else if (GATE_system_type == GATE_SYS_SPECT)
1410  {
1411  if(vb >= 4)
1412  {
1413  Cout("Projection ID : headID: " << headID << ", rotation angle (deg): " << rotAngle << endl;);
1414  Cout("Crystal ID : crystalID: " << crystalID1 << ", pixelID: " << pixelID << ", globalPosX " << gPosX << ", globalPosY " << gPosY << ", globalPosZ " << gPosZ << endl;);
1415  }
1416 
1417  // Get projection ID
1418  castorID1 = ConvertIDSPECTRoot1(headID,
1419  rotAngle,
1420  headAngStepDeg,
1421  nProjectionsByHead);
1422 
1423  // Get crystal ID
1424  castorID2 = ConvertIDSPECTRoot2(nbSimulatedPixels,
1425  nPixelsTransaxial,
1426  nPixelsAxial,
1427  headID,
1428  crystalID1,
1429  pixelID,
1430  rotAngle,
1431  headAngPitchDeg,
1432  crystalSizeAxl,
1433  crystalSizeTrs,
1434  gPosX,
1435  gPosY,
1436  gPosZ);
1437 
1438  if(vb >= 4)
1439  {
1440  Cout("--> castorID1: " << castorID1 << endl;);
1441  Cout("--> castorID2: " << castorID2 << endl;);
1442  }
1443 
1444  }
1445 
1446  else if (GATE_system_type == GATE_SYS_ECAT)
1447  {
1448  if(vb >= 4)
1449  {
1450  Cout("Crystal 1 : BlockID: " << blockID1 << ", crystalID: " << crystalID1 << endl;);
1451  Cout("Crystal 2 : BlockID: " << blockID2 << ", crystalID: " << crystalID2 << endl;);
1452  }
1453 
1454  castorID1 = ConvertIDecat(nBlocksPerRing, nBlocksLine, nCrystalsTransaxial, nCrystalsAxial, crystalID1, blockID1);
1455  castorID2 = ConvertIDecat(nBlocksPerRing, nBlocksLine, nCrystalsTransaxial, nCrystalsAxial, crystalID2, blockID2);
1456 
1457  if(vb >= 4)
1458  {
1459  Cout("--> castorID1: " << castorID1 << endl;);
1460  Cout("--> castorID2: " << castorID2 << endl;);
1461  }
1462 
1463  }
1464 
1465  // Find out the kind of coincidence (true, scatter, random)
1466  kind = ComputeKindGATEEvent(eventID1, eventID2, comptonPhantomID1, comptonPhantomID2, rayleighPhantomID1, rayleighPhantomID2);
1467 
1468  // Count nb LORs according to kind
1469  switch (kind)
1470  {
1471  case 1:
1472  nLORs_trues++;
1473  break;
1474 
1475  case 2:
1476  nLORs_scatters++;
1477  break;
1478 
1479  case 3:
1480  nLORs_scatters++;
1481  break;
1482 
1483  case 4:
1484  nLORs_rdms++;
1485  break;
1486 
1487  default:
1488  nLORs_unknown++;
1489  }
1490 
1491  // Skip next step if event is not true if we only recover true
1492  if (true_only_flag==true && kind != KIND_TRUE)
1493  continue;
1494 
1495 
1496  // --- Write Event ---
1497 
1498  // SPECT event
1499  if(GATE_system_type == GATE_SYS_SPECT)
1500  {
1501  // HISTOGRAM mode
1502  if(histo_out_flag)
1503  p_bins[castorID1][castorID2]++;
1504  else
1505  // LIST-mode
1506  {
1507  // Write event in the datafile
1508  uint32_t time_in_ms = time1*1000;
1509  Event->SetNbLines(1);
1510  Event->SetID1(0, castorID1); // 1st argument : line, 2nd argument :index
1511  Event->SetID2(0, castorID2); // 1st argument : line, 2nd argument :index
1512  Event->SetTimeInMs(time_in_ms);
1513 
1514  ((iEventListSPECT*)Event)->SetKind(kind);
1515 
1516  Out_data_file->PROJ_WriteEvent(Event, 0);
1517  }
1518  }
1519  else // PET event
1520  {
1521  // HISTOGRAM mode
1522  if(histo_out_flag)
1523  {
1524  if (castorID1 < castorID2)
1525  p_bins[castorID1][castorID2-castorID1-1]++;
1526  else
1527  p_bins[castorID2][castorID1-castorID2-1]++;
1528  }
1529  // LIST-mode
1530  else
1531  {
1532  // Write event in the datafile
1533  uint32_t time_in_ms = time1*1000;
1534  int nb_lines_in_event = 1; // 1 by default for GATE root files
1535 
1536  Event->SetNbLines(nb_lines_in_event);
1537  Event->SetID1(0, castorID1); // 1st argument : line, 2nd argument :index
1538  Event->SetID2(0, castorID2); // 1st argument : line, 2nd argument :index
1539  Event->SetTimeInMs(time_in_ms);
1540 
1541  ((iEventListPET*)Event)->SetKind(kind);
1542 
1543  Out_data_file->PROJ_WriteEvent(Event, 0);
1544  }
1545  }
1546 
1547 
1548  // Source image (if no rdm event)
1549  if(src_img_flag &&
1550  eventID1 == eventID2)
1551  {
1552  INTNB x,y,z;
1553  x = (int)(( sourcePosX1 + dim_src_img[0]/2*vox_src_img[0]) / vox_src_img[0]);
1554  // CASToR Y axis inverted in comparison with GATE (left-handed coordinate)
1555  y = (int)(( sourcePosY1 + dim_src_img[1]/2*vox_src_img[1]) / vox_src_img[1]);
1556  z = (int)(( sourcePosZ1 + dim_src_img[2]/2*vox_src_img[2]) / vox_src_img[2]);
1557 
1558  if(x >= 0 && x < dim_src_img[0] &&
1559  y >= 0 && y < dim_src_img[1] &&
1560  z >= 0 && z < dim_src_img[2] )
1561  p_src_img[z*dim_src_img[1]*dim_src_img[0] + y*dim_src_img[0] + x]++;
1562  }
1563 
1564 
1565  // Progression
1566  if (printing_index%(nLORs_tot/printing_ratio) == 0)
1567  {
1568  FLTNB percent = ( ((FLTNB)(printing_index+1))/((FLTNB)nLORs_tot) ) * ((FLTNB)100);
1569  cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b "
1570  << percent << " \% ";
1571  }
1572 
1573 
1574  } // end of loop on events in input datafile iFic
1575  #endif
1576 
1577  if(vb>=2) Cout(endl << "Datafile " << iFic << " : " << path_to_input_file[iFic] << " process OK" << endl);
1578 
1579  } // end of loop on input datafiles
1580 
1581  // Free Root objects
1582  #ifdef CASTOR_ROOT
1583  delete[] Tfile_root;
1584  delete[] GEvents;
1585  delete Tapp;
1586  #endif
1587 
1588 
1589 
1590  // ============================================================================================================
1591  // Write the HISTOGRAM datafile and header
1592  // ============================================================================================================
1593  if(GATE_system_type == GATE_SYS_SPECT)
1594  {
1595  if (histo_out_flag)
1596  {
1597  printing_index=0;
1598 
1599  // Writing the datafile
1600  Cout(endl << "Generate the histogram datafile" << endl);
1601 
1602  uint32_t nb_bins = bins_elts*nCrystalsTot;
1603  printing_ratio = (nb_bins>1000) ? 1000 : nb_bins/10;
1604 
1605  // Loop on the crystal IDs
1606  for (size_t id1=0 ; id1<bins_elts ; id1++)
1607  for (size_t id2=0; id2<nCrystalsTot ; id2++)
1608  {
1609  uint32_t nb_events_in_bin = p_bins[id1][id2];
1610 
1611  int nb_lines = 1; // 1 by default for GATE root file;
1612  Event->SetNbLines(nb_lines);
1613  Event->SetID1(0, id1); // 1st argument : line, 2nd argument :index
1614  Event->SetID2(0, id2); // 1st argument : line, 2nd argument :index
1615  Event->SetEventValue(0, nb_events_in_bin);
1616 
1617  // Write event in Datafile
1618  Out_data_file->PROJ_WriteEvent(Event, 0);
1619  nBINs++;
1620 
1621  // Progression
1622 
1623  if (printing_index%((nb_bins)/printing_ratio) == 0)
1624  {
1625  FLTNB percent = ( ((FLTNB)(printing_index+1))/((FLTNB)nb_bins) ) * ((FLTNB)100);
1626  cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b "
1627  << percent << " \% ";
1628  }
1629 
1630  printing_index++;
1631  }
1632 
1633  Out_data_file->SetStartTime((FLTNB)(start_time_ms)/1000); // start time in s
1634  Out_data_file->SetDuration((FLTNB)(duration_ms)/1000); // duration in s
1635  Out_data_file->SetNbEvents( nBINs );
1636 
1637  Cout(endl << "The output histogram contains " << nBINs << " events." << endl);
1638  }
1639  // Write the List-mode datafile header
1640  else
1641  {
1642 
1643  Out_data_file->SetStartTime((FLTNB)(start_time_ms)/1000); // start time in s
1644  Out_data_file->SetDuration((FLTNB)(duration_ms)/1000); // duration in s
1645  //uint32_t nLORs = (true_only_flag) ? nLORs_trues : nLORs_tot;
1646  Out_data_file->SetNbEvents( (true_only_flag) ?
1647  nLORs_trues :
1648  nLORs_tot ) ;
1649  }
1650 
1651  FLTNB* p_angles = new FLTNB[nProjectionsTot];
1652  FLTNB* p_distToDetector = new FLTNB[nProjectionsTot];
1653 
1654  for(size_t h=0 ; h<nHeads ; h++)
1655  for(size_t p=0 ; p<nProjectionsByHead ; p++)
1656  {
1657  int idx_proj = h*nProjectionsByHead+p;
1658  p_angles[idx_proj] = head1stAngleDeg // initial angular position of the head
1659  + p*headAngStepDeg // projection angular position
1660  + h*headAngPitchDeg; // angular shift for each head
1661 
1662  // same distance for each head with GATE
1663  p_distToDetector[idx_proj] = distToDetector;
1664  }
1665 
1666  ((iDataFileSPECT*)Out_data_file)->SetNbBins(nPixelsTransaxial, nPixelsAxial);
1667  ((iDataFileSPECT*)Out_data_file)->SetNbProjections(nProjectionsTot);
1668 
1669  if( ((iDataFileSPECT*)Out_data_file)->InitAngles(p_angles) )
1670  {
1671  Cerr("**** castor-GATERootToCastor :: Error when trying to set projection angles values !" << endl);
1672  Exit(EXIT_FAILURE);
1673  }
1674 
1675  if( ((iDataFileSPECT*)Out_data_file)->InitCorToDetectorDistance(p_distToDetector) )
1676  {
1677  Cerr("**** castor-GATERootToCastor :: Error when trying to set distance between center of rotation and detectors !" << endl);
1678  Exit(EXIT_FAILURE);
1679  }
1680 
1681  ((iDataFileSPECT*)Out_data_file)->SetHeadRotDirection(headRotDirection);
1682 
1683  delete[] p_angles;
1684  delete[] p_distToDetector;
1685 
1686  Out_data_file->PROJ_WriteHeader();
1687  } // end of SPECT section
1688 
1689  else
1690  {
1691  if (histo_out_flag)
1692  {
1693  printing_index=0;
1694 
1695  // Writing the datafile
1696  Cout(endl << "Generate the histogram datafile" << endl);
1697  uint32_t nb_bins = (nCrystalsTot*nCrystalsTot - nCrystalsTot)/2;
1698  printing_ratio = (nb_bins>1000) ? 1000 : nb_bins/10;
1699 
1700  // Loop on the crystal IDs
1701  for (size_t id1=0 ; id1 <bins_elts ; id1++)
1702  for (size_t id2 = id1+1; id2 < nCrystalsTot;id2++)
1703  {
1704  uint32_t nb_events_in_bin = p_bins[id1][id2-id1-1];
1705 
1706  int nb_lines = 1; // 1 by default for GATE root file;
1707  Event->SetNbLines(nb_lines);
1708  Event->SetID1(0, id1); // 1st argument : line, 2nd argument :index
1709  Event->SetID2(0, id2); // 1st argument : line, 2nd argument :index
1710  Event->SetEventValue(0, nb_events_in_bin);
1711 
1712  // Estimate acf for the bin
1713  if(estimate_acf_flag)
1714  {
1715  // Compute the system matrix elements for the two crystals
1716  oProjectionLine* line = p_ProjectorManager->ComputeProjectionLine(Event, 0);
1717 
1718  // Compute forward projection of attenuation image
1719  FLTNB fp = 0.;
1720  if (line->NotEmptyLine())
1721  fp = line->ForwardProject(p_ImageSpace->m4p_image[0][0][0]) * 0.1; // 0.1 -> convert in mm-1
1722 
1723  // Write atn correction factor in Event
1724  ((iEventPET*)Event)->SetAttenuationCorrectionFactor(1/std::exp(-fp));
1725  }
1726 
1727  // Write event in Datafile
1728  Out_data_file->PROJ_WriteEvent(Event, 0);
1729  nBINs++;
1730 
1731  // Progression
1732  if (printing_index%((nb_bins)/printing_ratio) == 0)
1733  {
1734  FLTNB percent = ( ((FLTNB)(printing_index+1))/((FLTNB)nb_bins) ) * ((FLTNB)100);
1735  cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b "
1736  << percent << " \% ";
1737  }
1738  printing_index++;
1739  }
1740 
1741  Out_data_file->SetStartTime((FLTNB)(start_time_ms)/1000); // start time in s
1742  Out_data_file->SetDuration((FLTNB)(duration_ms)/1000); // duration in s
1743  Out_data_file->SetNbEvents( nBINs );
1744  Out_data_file->PROJ_WriteHeader();
1745 
1746  Cout(endl << "The output histogram contains " << nBINs << " events." << endl);
1747  }
1748  // Write the List-mode datafile header
1749  else
1750  {
1751  Out_data_file->SetStartTime((FLTNB)(start_time_ms)/1000); // start time in s
1752  Out_data_file->SetDuration((FLTNB)(duration_ms)/1000); // duration in s
1753  //uint32_t nLORs = (true_only_flag) ? nLORs_trues : nLORs_tot;
1754  Out_data_file->SetNbEvents( (true_only_flag) ?
1755  nLORs_trues :
1756  nLORs_tot );
1757  Out_data_file->PROJ_WriteHeader();
1758  }
1759  } // end of PET section
1760 
1761 
1762  // Write the source image
1763  if(src_img_flag)
1764  {
1765  if (vb>=2) Cout("Writing source image ..." << endl);
1766 
1767  // Initialize Intf_fields object with the source image dimensions
1768  Intf_fields IF;
1769  IntfKeyInitFields(&IF);
1770 
1771  IF.mtx_size[0] = dim_src_img[0];
1772  IF.mtx_size[1] = dim_src_img[1];
1773  IF.mtx_size[2] = dim_src_img[2];
1774  IF.vox_size[0] = vox_src_img[0];
1775  IF.vox_size[1] = vox_src_img[1];
1776  IF.vox_size[2] = vox_src_img[2];
1777  IF.nb_total_imgs = dim_src_img[2];
1778 
1779  if (IntfWriteImgFile(path_to_src_image.append("_src"), p_src_img, IF, vb) )
1780  {
1781  Cerr("***** castor-GATERootToCastor :: Error writing Interfile of output image !" << endl);
1782  Exit(EXIT_FAILURE);
1783  }
1784  }
1785 
1786  Cout(endl << "The simulated dataset contained " << nLORs_tot << " coincidences/singles, with: " << endl
1787  << " " << nLORs_trues << " trues (" << 100*nLORs_trues/nLORs_tot << " %), " << endl
1788  << " " << nLORs_scatters << " scatters (" << 100*nLORs_scatters/nLORs_tot << " %)," << endl
1789  << " " << nLORs_rdms << " randoms (" << 100*nLORs_rdms/nLORs_tot << " %)," << endl
1790  << " " << nLORs_unknown << " unknown (" << 100*nLORs_unknown/nLORs_tot << " %)." << endl);
1791 
1792  if (vb>=2) Cout("Writing raw datafile ..." << endl); // todo just change name if only one datafile
1793 
1794 
1795  Out_data_file->PROJ_WriteData();
1796  Out_data_file->PROJ_DeleteTmpDatafile();
1797 
1798  Cout(endl << " --- Conversion completed --- " << endl);
1799 
1800  // ============================================================================================================
1801  // End
1802  // ============================================================================================================
1803 
1804  if (vb>=2) Cout(" Deallocating objects ..." << endl);
1805 
1806  // Delete objects
1807  if(histo_out_flag)
1808  {
1809  for(size_t b=0; b<bins_elts ; b++)
1810  delete[] p_bins[b];
1811 
1812  delete[]p_bins;
1813 
1814  if(Event)
1815  {
1816  if(GATE_system_type == GATE_SYS_SPECT)
1817  delete (iEventHistoSPECT*)Event;
1818  else
1819  delete (iEventHistoPET*)Event;
1820  }
1821  }
1822  else
1823  if(Event)
1824  {
1825  if(GATE_system_type == GATE_SYS_SPECT)
1826  delete (iEventListSPECT*)Event;
1827  else
1828  delete (iEventListPET*)Event;
1829  }
1830 
1831  delete[]offset_time_list;
1832  delete Out_data_file;
1833 
1834  if(src_img_flag && p_src_img)
1835  delete[] p_src_img;
1836 
1837  // Free objects created for analytic projection (acf estimation)
1838  if(estimate_acf_flag)
1839  p_ImageSpace->LMS_DeallocateImage();
1840  if(p_ImageSpace) delete p_ImageSpace;
1841  if(p_ProjectorManager) delete p_ProjectorManager;
1842  if(p_ID) delete p_ID;
1843 
1844  Cout(" --- END --- " << endl << endl);
1845 
1846  return 0;
1847 }
void SetDataMode(int a_dataMode)
set the data mode
Definition: vDataFile.hh:359
uint32_t ConvertIDSPECTRoot1(int32_t a_headID, float_t a_rotAngle, float_t a_angStep, uint32_t a_nProjectionsByHead)
Compute a CASToR projection index of a GATE SPECThead system.
This class is designed to be a mother virtual class for Datafile.
Definition: vDataFile.hh:67
void LMS_InstantiateImage()
Allocate memory for the main image matrices (for list-mode sensitivity generation) ...
This header file is mainly used to declare some macro definitions and all includes needed from the st...
int SetPETIsotope(int a_bed, const string &a_isotope)
Set the PET isotope for the provided bed.
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
int InitDynamicData(string a_pathTo4DDataSplittingFile, int a_respMotionCorrectionFlag, int a_cardMotionCorrectionFlag, int a_doubleMotionCorrectionFlag, int a_invMotionCorrectionFlag, int a_nbRespGates, int a_nbCardGates)
Call the eponym function from the oDynamicDataManager object in order to initialize its data...
#define MODE_HISTOGRAM
Definition: vDataFile.hh:36
#define TYPE_PET
Definition: vDataFile.hh:51
void SetNbLines(uint16_t a_value)
Set the number of lines of the Event.
Definition: vEvent.hh:134
void SetVerbose(int a_verbose)
set verbosity
void SetAtnCorrectionFlagOn()
set to true the flag indicating the presence of attenuation correction factors in the datafile ...
void SetFOVSizeZ(FLTNB a_fovSizeZ)
Set the FOV's size along the Z axis, in mm.
#define MODE_LIST
Definition: vDataFile.hh:34
#define GATE_SYS_UNKNOWN
FLTNB vox_size[3]
#define FLTNB
Definition: gVariables.hh:55
This file gathers various function dedicated to data conversion in order to convert various type of G...
uint32_t nb_total_imgs
void SetComputationStrategy(int a_computationStrategy)
Set the computation strategy for the system matrix elements storage.
int Initialize()
A function used to initialize the manager and the projectors or system matrices it manages...
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the image dimensions in use.
int FindScannerSystem(string a_scannerName)
Look for a file matching with the scanner name in parameter inside the scanner repository.
void SetFOVSizeY(FLTNB a_fovSizeY)
Set the FOV's size along the Y axis, in mm.
void SetNbVoxZ(INTNB a_nbVoxZ)
Set the number of voxels along the Z axis.
int ReadMacSPECT(string a_pathMac, float_t &distToDetector, uint32_t &nHeads, uint32_t &nPixAxl, uint32_t &nPixTrs, float_t &crystalSizeAxl, float_t &crystalSizeTrs, uint32_t &nProjectionsTot, uint32_t &nProjectionsByHead, float_t &head1stAngle, float_t &headAngPitch, float_t &headAngStepDeg, int &headRotDirection, uint32_t &start_time_ms, uint32_t &duration_ms, int vb)
Recover informations about the scanner element of an ECAT system, and acquisition duration...
int BuildScannerObject()
Instantiate the specific scanner object related to the modality, and set verbosity of scanner object...
#define GATE_SYS_ECAT
void SetNbRespGates(int a_nbRespGates)
Set the number of respiratory gates.
#define KIND_TRUE
void SetOffsetY(FLTNB a_offsetY)
Set the image offset along the Y axis, in mm.
void ShowHelp(int a_returnCode)
void SetFOVOutMasking(FLTNB a_fovOutPercent, INTNB a_nbSliceOutMask)
Set the output FOV masking settings: transaxial unmasked FOV percent and number of extrem slices to r...
virtual int PROJ_WriteHeader()=0
This function is implemented in child classes. Generate a header file according to the projection a...
Inherit from iEventSPECT. Class for SPECT histogram mode events.
void SetVerbose(int a_verboseLevel)
set verbosity
Definition: vDataFile.hh:394
int ReadMacCylindrical(string a_pathMac, uint8_t &nLayers, uint32_t *nb_crystal_per_layer, uint32_t &nCrystalsTot, uint32_t &nCrystalsAxial, uint32_t &nCrystalsTransaxial, vector< uint32_t > &nLayersRptAxial, vector< uint32_t > &nLayersRptTransaxial, uint32_t &nSubmodulesAxial, uint32_t &nSubmodulesTransaxial, uint32_t &nModulesAxial, uint32_t &nModulesTransaxial, uint32_t &nRsectorsPerRing, uint32_t &start_time_ms, uint32_t &duration_ms, int vb)
Recover informations about the scanner element of a cylindricalPET system and acquisition duration...
void SetOptionsForward(const string &a_optionsForward)
Set the forward projection options contained in the provided string.
void SetDuration(FLTNB a_value)
Definition: vDataFile.hh:463
virtual int ComputeSizeEvent()=0
This function is implemented in child classes Computation of the size of each event according to th...
#define GATE_SYS_SPECT
virtual void SetEventValue(int a_bin, FLTNBDATA a_value)=0
This function is implemented by child classes.
Definition: vEvent.hh:120
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
void SetOffsetZ(FLTNB a_offsetZ)
Set the image offset along the Z axis, in mm.
#define TYPE_SPECT
Definition: vDataFile.hh:53
Declaration of class iDataFilePET.
void SetOptionsCommon(const string &a_optionsCommon)
Set the common projection options contained in the provided string.
int CheckParameters()
Check if all parameters have been correctly initialized, and call the CheckParameters function of the...
void SetNbVoxX(INTNB a_nbVoxX)
Set the number of voxels along the X axis.
int SetNbThreads(const string &a_nbThreads)
Set the number of threads.
Declaration of class iDataFileSPECT.
void Exit(int code)
void SetOptionsBackward(const string &a_optionsBackward)
Set the backward projection options contained in the provided string.
int IntfReadHeader(const string &a_pathToHeaderFile, Intf_fields *ap_IntfFields, int vb)
Read an Interfile header.
int InstantiateScanner()
Instantiate scanner using the related function in the scanner classes.
int LogCommandLine(int argc, char **argv)
Write log file header with the provided command line options and different informations.
int PROJ_LoadInitialImage(const string &a_pathToImage)
Load the initial image for the analytical projection.
void SetIsotope(string a_value)
initialize the isotope string value
int PROJ_WriteData()
Write/Merge chunk of data in a general data file.
Definition: vDataFile.cc:928
int ConvertFromString(const string &a_str, string *a_result)
Copy the 'a_str' string in the position pointed by 'a_result'.
Definition: gOptions.cc:749
void SetIsotope(string a_value)
initialize the isotope string value
#define FIXED_LIST_COMPUTATION_STRATEGY
void SetNbVoxY(INTNB a_nbVoxY)
Set the number of voxels along the Y axis.
int CheckConfigDir(const string &a_path)
Set the path to the CASTOR config directory from the given path if not empty or through the existence...
Inherit from iEventPET. Class for PET list-mode events.
int CheckParameters()
A function used to check the parameters settings.
void SetNbCardGates(int a_nbCardGates)
Set the number of cardiac gates.
#define Cerr(MESSAGE)
Inherit from iEventPET. Class for PET histogram mode events.
FLTNB **** m4p_image
Definition: oImageSpace.hh:61
int BuildLUT()
Call the eponym function of the scanner class.
int ComputeKindGATEEvent(uint32_t eventID1, uint32_t eventID2, int comptonPhantom1, int comptonPhantom2, int rayleighPhantom1, int rayleighPhantom2)
Determine kind of a given coincidence event, from its attributes.
void SetStartTime(FLTNB a_value)
Definition: vDataFile.hh:455
int Initialize()
A function used to initialize all that is needed.
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.
void SetFrames(const string &a_frameList)
Set the frame list (a string that will be parsed by the InitializeFramingAndQuantification function) ...
void SetFOVSizeX(FLTNB a_fovSizeX)
Set the FOV's size along the X axis, in mm.
void SetDataType(int a_dataType)
set the data type
Definition: vDataFile.hh:366
Singleton class that Instantiate and initialize the scanner object.
int IntfReadProjectionImage(const string &a_pathToHeaderFile, FLTNB *ap_ImgMatrix, Intf_fields *ap_IF, int vb, bool a_lerpFlag)
Main function which reads a projection Interfile 3D projection image and store its content in the pro...
void LMS_DeallocateImage()
Free memory for the main image matrices (for list-mode sensitivity generation)
int ReadMacECAT(string a_pathMac, uint32_t &nCrystalsTot, uint32_t &nCrystalsAxial, uint32_t &nCrystalsTransaxial, uint32_t &nBlocksLine, uint32_t &nBlocksPerRing, uint32_t &start_time_ms, uint32_t &duration_ms, int vb)
Recover informations about the scanner element of an ECAT system and acquisition duration, from a GATE macro file.
Declaration of class sScannerManager.
void SetVoxSizeY(FLTNB a_voxSizeY)
Set the voxel's size along the Y axis, in mm.
int CreateGeomWithECAT(string a_pathMac, string a_pathGeom)
Read a GATE macro file containing the description of an ecat system, and convert it to a geom file...
virtual int PrepareDataFile()=0
This function is implemented in child classes Store different kind of information inside arrays (da...
oProjectionLine * ComputeProjectionLine(vEvent *ap_Event, int a_th)
This function is used to compute system matrix elements from the associated projector or pre-computed...
Inherit from vDataFile. Class that manages the reading of a SPECT input file (header + data)...
void SetOffsetX(FLTNB a_offsetX)
Set the image offset along the X axis, in mm.
void SetHeaderDataFileName(const string &a_headerFileName)
set the data header file name
Definition: vDataFile.hh:431
vScanner * GetScannerObject()
void SetVoxSizeX(FLTNB a_voxSizeX)
Set the voxel's size along the X axis, in mm.
void IntfKeyInitFields(Intf_fields *ap_IF)
Init the file of an Interfile fields structure passed in parameter to their default values...
virtual int PROJ_WriteEvent(vEvent *ap_Event, int a_th)=0
This function is implemented in child classes Write event according to the chosen type of data...
int CheckParameters()
A function used to check the parameters settings.
uint32_t mtx_size[7]
void SetMPIRank(int a_mpiRank)
Initialize the machine index for MPI.
void SetVerbose(int a_verboseLevel)
Set the verbose level.
int AllocateID()
Instantiate the mp_ID1 and mp_ID2 indices arrays.
Definition: vEvent.cc:71
int PROJ_DeleteTmpDatafile()
Delete temporary datafile used for multithreaded output writing if needed.
Definition: vDataFile.cc:1008
bool NotEmptyLine()
This function is used to know if the line contains any voxel contribution.
void SetDataFile(vDataFile *ap_DataFile)
Set a data file in use to later recover some information from it.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
set the pointer to the oImageDimensionsAndQuantification object
Definition: oImageSpace.hh:553
#define GATE_SYS_CYLINDRICAL
Inherit from vEvent. Main PET class for the Event objects.
Definition: iEventPET.hh:22
void SetNbEvents(int64_t a_value)
initialize the number of events with a int64_t value
Definition: vDataFile.hh:447
int Initialize()
Initialization : .
void SetVerbose(int a_verbose)
Set the member m_verboseLevel to the provided value.
void SetID2(int a_line, uint32_t a_value)
Set the indice associated with the line index for the 2nd ID of the Event.
Definition: vEvent.hh:150
#define INTNB
Definition: gVariables.hh:64
#define OS_SEP
This class is designed to manage and store system matrix elements associated to a vEvent...
string GetPathOfFile(const string &a_pathToFile)
Simply return the path to the directory of a file path string passed in parameter.
Definition: gOptions.cc:1144
void SetVoxSizeZ(FLTNB a_voxSizeZ)
Set the voxel's size along the Z axis, in mm.
Declaration of class oImageSpace.
void SetVerbose(int a_verboseLevel)
set verbosity
Definition: oImageSpace.hh:546
This class is designed to manage the projection part of the reconstruction.
Interfile fields. This structure contains all the Interfile keys currently managed by CASToR Decl...
void SetTimeInMs(uint32_t a_value)
Set the timestamp of the Event.
Definition: vEvent.hh:119
Declaration of class sOutputManager.
This class holds all the matrices in the image domain that can be used in the algorithm: image...
Definition: oImageSpace.hh:41
Mother class for the Event objects.
Definition: vEvent.hh:23
int InitOutputDirectory(const string &a_pathFout, const string &a_pathDout)
Create the output directory if any, extract the base name and create the log file.
FLTNB ForwardProject(FLTNB *ap_image=NULL)
Simply forward projects the provided image if not null, or else 1, for the current TOF bin...
int main(int argc, char **argv)
uint32_t ConvertIDcylindrical(uint32_t nRsectorsPerRing, uint32_t nModulesTransaxial, uint32_t nModulesAxial, uint32_t nSubmodulesTransaxial, uint32_t nSubmodulesAxial, uint32_t nCrystalsTransaxial, uint32_t nCrystalsAxial, uint8_t nLayers, uint32_t *nCrystalPerLayer, vector< uint32_t > nLayersRptTransaxial, vector< uint32_t > nLayersRptAxial, int32_t layerID, int32_t crystalID, int32_t submoduleID, int32_t moduleID, int32_t rsectorID)
Compute a CASToR crystal index of a GATE cylindricalPET system from its indexes (rsector/module/submo...
This class is designed to manage all dimensions and quantification related stuff. ...
void SetNbBeds(int a_nbBeds)
Set the number of bed positions.
This file is used for all kind of different functions designed for options parsing and ASCII file rea...
void SetVerbose(int a_verboseLevel)
set verbosity
#define Cout(MESSAGE)
uint32_t ConvertIDecat(int32_t nBlocksPerRing, int32_t nBlocksLine, int32_t nCrystalsTransaxial, int32_t nCrystalsAxial, int32_t crystalID, int32_t blockID)
Compute a CASToR crystal index of a GATE ecat system from its indexes (block/crystal) and the system ...
#define CASTOR_VERSION
Definition: gVariables.hh:44
void SetScanner(vScanner *ap_Scanner)
Set the scanner in use.
int ReadIntfSPECT(string a_pathIntf, float_t &ap_distToDetector, uint32_t &ap_nHeads, uint32_t &ap_nPixAxl, uint32_t &ap_nPixTrs, float_t &ap_crystalSizeAxl, float_t &ap_crystalSizeTrs, uint32_t &ap_nProjectionsTot, uint32_t &ap_nProjectionsByHead, float_t &ap_head1stAngle, float_t &ap_headAngPitch, float_t &headAngStepDeg, int &ap_headRotDirection, uint32_t &ap_start_time_ms, uint32_t &ap_duration_ms, int vb)
Recover informations about the scanner element of an ECAT system, and acquisition duration...
Declaration of class oProjectorManager.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
set the pointer to the oImageDimensionsAndQuantification object
Definition: vDataFile.hh:408
Inherit from vDataFile. Class that manages the reading of a PET input file (header + data)...
Definition: iDataFilePET.hh:26
void SetPercentageLoad(int a_percentageLoad)
Set the percentage of the data file that will be loaded in memory.
Definition: vDataFile.hh:380
int ReadStringOption(const string &a_input, T *ap_return, int a_nbElts, const string &sep, const string &a_option)
Parse the 'a_input' string corresponding to the 'a_option' into 'a_nbElts' elements, using the 'sep' separator. The results are returned in the templated 'ap_return' dynamic templated array. Call "ConvertFromString()" to perform the correct conversion depending on the type of the data to convert.
Definition: gOptions.cc:50
int GetGATESystemType(const string &a_pathMac)
Read a GATE macro file and identify the system type from the 'gate/systems/' command lines...
void SetMaxNumberOfLinesPerEvent(uint16_t a_value)
set the max number of line per event in the datafile
int CreateGeomWithCylindrical(string a_pathMac, string a_pathGeom)
Read a GATE macro file containing the description of a cylindricalPET system, and convert it to a geo...
virtual int PROJ_InitFile()=0
This function is implemented in child classes Initialize the fstream objets for output writing as w...
int IntfWriteImgFile(const string &a_pathToImg, FLTNB *ap_ImgMatrix, const Intf_fields &ap_IntfF, int vb)
Main function dedicated to Interfile 3D image writing. Recover image information from a provided In...
#define GEO_ROT_CW
Definition: vScanner.hh:28
int CreateGeomWithSPECT(string a_pathMac, string a_pathGeom)
Read a GATE macro file containing the description of a SPECThead system, and convert it to a geom fil...
void GetUserEndianness()
Check user/host computer endianness and write it to the global variable User_Endianness.
uint32_t ConvertIDSPECTRoot2(uint32_t a_nbSimulatedPixels, uint32_t a_nPixTrs, uint32_t a_nPixAxl, int32_t a_headID, int32_t a_crystalID, int32_t a_pixelID, float_t a_rotAngle, float_t a_headAngPitch, float_t a_crystalSizeAxl, float_t a_crystalSizeTrs, float_t a_gPosX, float_t a_gPosY, float_t a_gPosZ)
Compute a CASToR crystal index of a GATE SPECThead system.
Inherit from iEventSPECT. Class for SPECT list-mode events.
void SetID1(int a_line, uint32_t a_value)
Set the indice associated with the line index for the 1st ID of the Event.
Definition: vEvent.hh:142