CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
toolkits/castor-PetScannerLutEx.cc
Go to the documentation of this file.
1 
14 #include "gVariables.hh"
15 #include "gOptions.hh"
16 #include "sOutputManager.hh"
17 #include "oMatrix.hh"
18 
19 
25 void ShowHelp(int a_returnCode)
26 {
27  cout << endl;
28  cout << "Usage: castor-PetScannerLutEx -alias scanner_name [settings]" << endl;
29  cout << endl;
30  cout << "[Input settings]:" << endl;
31  cout << " -alias scanner_name : give the alias of the scanner for which the LUT will be generated (suggested template Modality-Constructor-Model (ex: PET_GE_DLS)" << endl;
32  cout << " the resulting file will be written in the scanner repository (default : /config/scanner directory)" << endl;
33  cout << endl;
34  #ifdef CASTOR_VERSION
35  cout << " This program is part of the CASToR release version " << CASTOR_VERSION << "." << endl;
36  cout << endl;
37  #endif
38  Exit(a_returnCode);
39 }
40 
41 
46 int main(int argc, char** argv)
47 {
48 
49  // ============================================================================================================
50  // MPI stuff (we make all instances but the first one returning 0 directly)
51  // ============================================================================================================
52  #ifdef CASTOR_MPI
53  int mpi_rank = 0;
54  int mpi_size = 1;
55  MPI_Init(&argc, &argv);
56  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
57  MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
58  if (mpi_rank!=0) return 0;
59  #endif
60 
61  // No argument, then show help
62  if (argc==1) ShowHelp(0);
63 
64  string scanner_name = "";
65  string path_to_LUT = "";
66  string path_to_headerLUT = "";
67  ofstream LUT_file, header_LUT_file;
68 
69  // ============================================================================================================
70  // Read command-line parameters
71  // ============================================================================================================
72  for (int i=1; i<argc; i++)
73  {
74  string option = (string)argv[i];
75 
76  if (option=="-h" || option=="--help" || option=="-help") ShowHelp(0);
77 
78  else if (option=="-alias")
79  {
80  if (i>=argc-1)
81  {
82  cerr << "***** castor-PetScannerLutEx :: Argument missing for option: " << option << endl;
83  Exit(EXIT_FAILURE);
84  }
85  scanner_name = argv[i+1];
86  string path_base = sOutputManager::GetInstance()->GetPathToConfigDir();
87 
88  path_base.append("scanner");
89  path_to_LUT = path_base+OS_SEP;
90  path_to_headerLUT = path_base+OS_SEP;
91  path_to_LUT.append(scanner_name.c_str()).append(".lut");
92  path_to_headerLUT.append(scanner_name.c_str()).append(".hscan");
93  i++;
94  }
95  else
96  {
97  cerr << "***** castor-PetScannerLutEx :: Unknown option '" << option << "' !" << endl;
98  Exit(EXIT_FAILURE);
99  }
100  }
101 
102 
103 
104  // ============================================================================================================
105  // Checks options have been provided
106  // ============================================================================================================
107 
108  // Checks
109  // output directory
110  if (scanner_name.empty() )
111  {
112  cerr << "***** castor-PetScannerLutEx :: Please provide an alias for this scanner !" << endl;
113  ShowHelp(0);
114  Exit(EXIT_FAILURE);
115  }
116  else
117  {
118  cout << endl << "Generating LUT with the following alias: " << scanner_name << "... " << endl << endl;
119  }
120 
121 
122 
123  // ============================================================================================================
124  // Input parameter declarations
125  // ============================================================================================================
126  int nb_rings;
127  int nb_elts;
128  FLTNBLUT min_trs_angle_diff;
129  string scanner_modality;
130  string description;
131  FLTNBLUT angular_span;
132 
133  int *nb_rsectors_lyr,
134  *nb_trans_mod_lyr,
135  *nb_axial_mod_lyr,
136  *nb_trans_submod_lyr,
137  *nb_axial_submod_lyr,
138  *nb_trans_crystal_lyr,
139  *nb_axial_crystal_lyr,
140  *nb_crystals_lyr;
141 
142  FLTNBLUT *radius_lyr,
143  *gap_trans_mod_lyr,
144  *gap_axial_mod_lyr,
145  *gap_trans_submod_lyr,
146  *gap_axial_submod_lyr,
147  *gap_trans_crystal_lyr,
148  *gap_axial_crystal_lyr,
149  *crystal_size_depth_lyr,
150  *crystal_size_trans_lyr,
151  *crystal_size_axial_lyr,
152  *mean_depth_of_interaction_lyr;
153 
154 
155  // Layer-dependent variables
156  int nbLayers = 1;
157  nb_rsectors_lyr = new int[nbLayers];
158  nb_trans_mod_lyr = new int[nbLayers];
159  nb_axial_mod_lyr = new int[nbLayers];
160  nb_trans_submod_lyr = new int[nbLayers];
161  nb_axial_submod_lyr = new int[nbLayers];
162  nb_trans_crystal_lyr = new int[nbLayers];
163  nb_axial_crystal_lyr = new int[nbLayers];
164  nb_crystals_lyr = new int[nbLayers];
165 
166  radius_lyr = new FLTNBLUT[nbLayers];
167 
168  gap_trans_mod_lyr = new FLTNBLUT[nbLayers];
169  gap_axial_mod_lyr = new FLTNBLUT[nbLayers];
170  gap_trans_submod_lyr = new FLTNBLUT[nbLayers];
171  gap_axial_submod_lyr = new FLTNBLUT[nbLayers];
172  gap_trans_crystal_lyr = new FLTNBLUT[nbLayers];
173  gap_axial_crystal_lyr = new FLTNBLUT[nbLayers];
174  crystal_size_depth_lyr = new FLTNBLUT[nbLayers];
175  crystal_size_trans_lyr = new FLTNBLUT[nbLayers];
176  crystal_size_axial_lyr = new FLTNBLUT[nbLayers];
177  mean_depth_of_interaction_lyr = new FLTNBLUT[nbLayers];
178 
179 
180  // Initialize value of each scanner element according to the scanner system
181 
182  description = "User-made LUT of a GATE model of the GE DRX PET scanner system, generated by the castor-PetScannerLutEx script";
183  scanner_modality = "PET";
184 
185  // System minimal transaxial angle difference between two scanner elements
186  // to get a LOR
187  min_trs_angle_diff = 40.;
188 
189  // radius in mm (from isocenter to crystal surface)
190  radius_lyr[0]= 443;
191 
192  // nb scanner elements
193  nb_rsectors_lyr[0] = 70;
194  nb_trans_mod_lyr[0] = 1;
195  nb_axial_mod_lyr[0] = 4;
196  nb_trans_submod_lyr[0] = 1;
197  nb_axial_submod_lyr[0] = 1;
198  nb_trans_crystal_lyr[0] = 9;
199  nb_axial_crystal_lyr[0] = 6;
200 
201 
202  // Gaps between scanner elements
203  gap_trans_mod_lyr[0] = 0;
204  gap_axial_mod_lyr[0] = 1.75;
205  gap_trans_submod_lyr[0] = 0;
206  gap_axial_submod_lyr[0] = 0;
207  gap_trans_crystal_lyr[0] = 0.065;
208  gap_axial_crystal_lyr[0] = 0.1;
209 
210  // crystal dimensions (mm)
211  crystal_size_depth_lyr[0] = 30;
212  crystal_size_trans_lyr[0] = 4.230;
213  crystal_size_axial_lyr[0] = 6.350;
214 
215  // mean depth of interaction in the crystal (mm)
216  // negative value means no depth of interaction
217  mean_depth_of_interaction_lyr[0] = -1.;
218 
219  // angular span in degree = 360 by defaut
220  // (rsectors will be uniformly positionned according to this value)
221  angular_span = 360.;
222 
223  // Default reconstruction parameters for the scanner
224  int default_dim_trans, default_dim_axial;
225  default_dim_trans = 256;
226  default_dim_axial = 47;
227 
228  // default field of view
229  FLTNBLUT default_FOV_trans, default_FOV_axial; //mm
230  default_FOV_trans = 700;
231  default_FOV_axial = 153.69;
232 
233 
234  // Z-shifts (rsector axial shift for each module)
235 
236  // Default initialization
237  int nb_rsctr_axial_shift = 1;
238  FLTNBLUT *rsctr_zshift;
239  rsctr_zshift = new FLTNBLUT[nb_rsctr_axial_shift];
240 
241  // System contains z-shifts)
242  if(nb_rsctr_axial_shift > 1)
243  {
244  for(int zs=0 ; zs<nb_rsctr_axial_shift ; zs++)
245  rsctr_zshift[zs] = 0.; // Add specific z-shift values for each layer
246  }
247  // No z-shift, default initialization
248  else
249  rsctr_zshift[0] = 0.;
250 
251 
252  // Compute the total number of elements
253  nb_elts = 0;
254  for(int lyr=0 ; lyr<nbLayers ; lyr++)
255  nb_elts += nb_rsectors_lyr[lyr] * nb_trans_mod_lyr[lyr] * nb_axial_mod_lyr[lyr]
256  * nb_trans_submod_lyr[lyr] * nb_axial_submod_lyr[lyr]
257  * nb_trans_crystal_lyr[lyr] * nb_axial_crystal_lyr[lyr];
258 
259  // Cumulative number of crystal (in order to keep track of crystal index if nb_layer>1)
260  uint32_t nb_cry_cur = 0;
261 
262  // Number of crystal in this layer
263  uint32_t nb_cry_in_layer = 0;
264 
265  // Loop on layers.
266  // Write the crytal LUT elements successively for each layer
267  for(int lyr=0 ; lyr<nbLayers ; lyr++)
268  {
269  // Default position for the first rsector in CASToR is directly above isocenter
270  // The gate model of this scanner locates the first rsector on the right side of the scanner
271  // This variable allows to provides the position of the first rsector in comparison with
272  // CASToR convention
273  // This is required to recover angular orientations of the crystals
274  FLTNBLUT rsector_first_angle = 90;
275 
276  int nb_rsectors = nb_rsectors_lyr[lyr],
277  nb_trans_mod = nb_trans_mod_lyr[lyr],
278  nb_axial_mod = nb_axial_mod_lyr[lyr],
279  nb_trans_submod = nb_trans_submod_lyr[lyr],
280  nb_axial_submod = nb_axial_submod_lyr[lyr],
281  nb_trans_crystal = nb_trans_crystal_lyr[lyr],
282  nb_axial_crystal = nb_axial_crystal_lyr[lyr];
283 
284  FLTNBLUT radius = radius_lyr[lyr],
285  gap_trans_mod = gap_trans_mod_lyr[lyr],
286  gap_axial_mod = gap_axial_mod_lyr[lyr],
287  gap_trans_submod = gap_trans_submod_lyr[lyr],
288  gap_axial_submod = gap_axial_submod_lyr[lyr],
289  gap_trans_crystal = gap_trans_crystal_lyr[lyr],
290  gap_axial_crystal = gap_axial_crystal_lyr[lyr],
291  crystal_size_trans = crystal_size_trans_lyr[lyr],
292  crystal_size_axial = crystal_size_axial_lyr[lyr],
293  crystal_size_depth = crystal_size_depth_lyr[lyr];
294 
295  // Compute system element sizes
296  FLTNBLUT size_trans_submod = nb_trans_crystal*crystal_size_trans + (nb_trans_crystal-1)*gap_trans_crystal;
297  FLTNBLUT size_axial_submod = nb_axial_crystal*crystal_size_axial + (nb_axial_crystal-1)*gap_axial_crystal;
298  FLTNBLUT size_trans_mod = nb_trans_submod*size_trans_submod + (nb_trans_submod-1)*gap_trans_submod;
299  FLTNBLUT size_axial_mod = nb_axial_submod*size_axial_submod + (nb_axial_submod-1)*gap_axial_submod;
300 
301  int nb_mod = nb_axial_mod*nb_trans_mod;
302  int nb_submod = nb_axial_submod*nb_trans_submod;
303  int nb_crystal = nb_trans_crystal*nb_axial_crystal;
304 
305  nb_cry_in_layer = nb_rsectors
306  * nb_mod
307  * nb_submod
308  * nb_crystal;
309 
310  nb_crystals_lyr[lyr] = nb_cry_in_layer;
311 
312  nb_rings = nb_rsectors
313  * nb_trans_mod
314  * nb_trans_submod
315  * nb_trans_crystal;
316 
317  int number_crystals_in_ring = nb_crystals_lyr[lyr]/nb_rings;
318 
319  // Variables gathering the LUT elements
320  FLTNBLUT* crystal_positionX = new FLTNBLUT[ nb_crystals_lyr[lyr] ];
321  FLTNBLUT* crystal_positionY = new FLTNBLUT[ nb_crystals_lyr[lyr] ];
322  FLTNBLUT* crystal_positionZ = new FLTNBLUT[ nb_crystals_lyr[lyr] ];
323  FLTNBLUT* crystal_orientationX = new FLTNBLUT[ nb_crystals_lyr[lyr] ];
324  FLTNBLUT* crystal_orientationY = new FLTNBLUT[ nb_crystals_lyr[lyr] ];
325  FLTNBLUT* crystal_orientationZ = new FLTNBLUT[ nb_crystals_lyr[lyr] ];
326 
327 
328  // ============================================================================================================
329  // Main part of the program: Generate the LUT
330  // ============================================================================================================
331 
332  // Loop to nb_rsectors+1. crystal_center[0] will be used to gather position of the reference rsector (directly above isocenter)
333  oMatrix *****crystal_center = new oMatrix ****[nb_rsectors];
334 
335  for(int i = 0; i < nb_rsectors+1 ; i++)
336  {
337  crystal_center[i] = new oMatrix ***[nb_axial_mod*nb_trans_mod];
338 
339  for (int j = 0; j<nb_axial_mod*nb_trans_mod; j++)
340  {
341  crystal_center[i][j] = new oMatrix **[nb_axial_submod*nb_trans_submod];
342 
343  for (int k = 0; k<nb_axial_submod*nb_trans_submod; k++)
344  {
345  crystal_center[i][j][k] = new oMatrix*[nb_axial_crystal*nb_trans_crystal];
346 
347  for (int l = 0; l<nb_axial_crystal*nb_trans_crystal; l++)
348  crystal_center[i][j][k][l] = new oMatrix(3,1);
349  }
350  }
351  }
352 
353 
354  // ============================================================================================================
355  // Generation of the rotation matrix allowing to compute the position of all the rsectors.
356  // ============================================================================================================
357  oMatrix** rotation_mtx = new oMatrix*[nb_rsectors];
358 
359  for(int i=0; i<nb_rsectors; i++)
360  rotation_mtx[i] = new oMatrix(3,3);
361 
362  FLTNBLUT angular_span_rad = angular_span*M_PI/180.;
363  for (int i = 0; i<nb_rsectors; i++)
364  {
365  FLTNBLUT angle = remainderf((FLTNB)i*angular_span_rad/((FLTNB)nb_rsectors), 2.*M_PI);
366 
367  rotation_mtx[i]->SetMatriceElt(0,0,cos(angle) );
368  rotation_mtx[i]->SetMatriceElt(1,0,-sin(angle) );
369  rotation_mtx[i]->SetMatriceElt(2,0,0);
370  rotation_mtx[i]->SetMatriceElt(0,1,sin(angle) );
371  rotation_mtx[i]->SetMatriceElt(1,1,cos(angle) );
372  rotation_mtx[i]->SetMatriceElt(2,1,0);
373  rotation_mtx[i]->SetMatriceElt(0,2,0);
374  rotation_mtx[i]->SetMatriceElt(1,2,0);
375  rotation_mtx[i]->SetMatriceElt(2,2,1);
376  }
377 
378 
379 
380  // ============================================================================================================
381  // Compute scanner elements positions for the first rsector
382  // (For the example scanner, it is located and centered on the right side of isocenter in the GATE model
383  // ============================================================================================================
384 
385  for (int i=0; i < nb_mod ; i++)
386  {
387  // Define the transaxial and axial edge start positions for the rsector
388  FLTNBLUT y_start_m = (nb_trans_mod*size_trans_mod + (nb_trans_mod-1)*gap_trans_mod) / 2;
389  FLTNBLUT z_start_m = -(nb_axial_mod*size_axial_mod + (nb_axial_mod-1)*gap_axial_mod) / 2 ;
390 
391  // Define the transaxial and axial edge start positions for the i-Module in the rsector.
392  // Enumeration starting with the transaxial modules.
393  y_start_m -= (i%nb_trans_mod) * (size_trans_mod + gap_trans_mod);
394  z_start_m += int(i/nb_trans_mod) * (size_axial_mod + gap_axial_mod);
395 
396  for (int j=0 ; j < nb_submod ; j++)
397  {
398  FLTNBLUT y_start_sm = y_start_m;
399  FLTNBLUT z_start_sm = z_start_m;
400 
401  y_start_sm -= (j%nb_trans_submod) * (size_trans_submod + gap_trans_submod);
402  z_start_sm += int(j/nb_trans_submod) * (size_axial_submod + gap_axial_submod);
403 
404  for (int k=0 ; k < nb_crystal ; k++)
405  {
406  // Define the transaxial and axial center positions for the j-SubModule (crystal) i-Module of the rsector.
407  // Enumeration starting with the transaxial submodules.
408  FLTNBLUT Xcrist = radius + crystal_size_depth/2;
409  FLTNBLUT Ycrist = y_start_sm - (k%nb_trans_crystal) * (crystal_size_trans + gap_trans_crystal) - crystal_size_trans/2;
410  FLTNBLUT Zcrist = z_start_sm + int(k/nb_trans_crystal) * (crystal_size_axial + gap_axial_crystal) + crystal_size_axial/2;
411 
412  crystal_center[0][i][j][k]->SetMatriceElt(0,0,Xcrist);
413  crystal_center[0][i][j][k]->SetMatriceElt(1,0,Ycrist);
414  crystal_center[0][i][j][k]->SetMatriceElt(2,0,Zcrist);
415  }
416  }
417  }
418 
419 
420  // ============================================================================================================
421  // Loop over all the other rsectors.
422  // Mandatory informations about crystals are recovered in :
423  // crystal_position(X,Y,Z) : Cartesian positions of the center of the crystals
424  // crystal_orientation(X,Y,Z) : Vector orientation recovering crystal angles
425  // (usually identical for all crystals inside the same rsector)
426  // ============================================================================================================
427 
428  for (int rs=0 ; rs<nb_rsectors ; rs++)
429  {
430 
431  // Compute angle for orientation vector for this rsector
432  FLTNBLUT rsector_first_angle_rad = rsector_first_angle*M_PI/180.;
433  FLTNBLUT orientation_angle = remainderf(rsector_first_angle_rad + (FLTNB)rs*angular_span_rad/((FLTNB)nb_rsectors), 2.*M_PI);
434 
435  for (int j=0 ; j<nb_mod ; j++)
436  for (int k=0 ; k<nb_submod ; k++)
437  for (int l=0 ; l<nb_crystal ; l++)
438  {
439  // crystal indexation
440  int cryID = int(j/nb_trans_mod)*nb_axial_submod*nb_axial_crystal*number_crystals_in_ring // = nb indexed crystals in the rings covered by the previous (axial) modules
441  + int(k/nb_trans_submod)*nb_axial_crystal*number_crystals_in_ring // = nb indexed crystals in the rings covered by the previous (axial) submodules
442  + int(l/nb_trans_crystal)*number_crystals_in_ring // = nb indexed crystals in the rings covered by the previous (axial) crystals
443  + rs*nb_trans_mod*nb_trans_submod*nb_trans_crystal // = nb indexed crystals in the previous rsectors
444  + j/nb_axial_mod*nb_trans_submod*nb_trans_crystal // = nb indexed crystals in the previous modules
445  + k/nb_axial_submod*nb_trans_crystal // = nb indexed crystals in the previous submodules
446  + l%nb_trans_crystal // previous crystals in the submodule
447  + nb_cry_cur; // = number of crystals already indexed if lyr>0
448 
449  rotation_mtx[rs]->Multiplication(crystal_center[0][j][k][l], crystal_center[rs+1][j][k][l]);
450  crystal_positionX[cryID] = crystal_center[rs+1][j][k][l]->GetMatriceElt(0,0);
451  crystal_positionY[cryID] = crystal_center[rs+1][j][k][l]->GetMatriceElt(1,0);
452  crystal_positionZ[cryID] = crystal_center[rs+1][j][k][l]->GetMatriceElt(2,0);
453  crystal_positionZ[cryID] += rsctr_zshift[rs%nb_rsctr_axial_shift];
454 
455  crystal_orientationX[cryID] = cos(orientation_angle);
456  crystal_orientationY[cryID] = sin(orientation_angle);
457  crystal_orientationZ[cryID] = 0;
458  }
459  }
460 
461  // Update nb of crystal for systems with (required if nb_layers>1)
462  nb_cry_cur += nb_crystals_lyr[lyr];
463 
464  // ============================================================================================================
465  // Write the binary LUT file (append if nb_layers > 1)
466  // ============================================================================================================
467 
468  cout << ">>> Start writing binary LUT file for layer #" << lyr << "..." << endl;
469  // Write binary file, overwrite mode
470  if(lyr == 0)
471  LUT_file.open(path_to_LUT.c_str(), ios::binary | ios::out);
472  // Append otherwise (data for crystals from the next layer)
473  else
474  LUT_file.open(path_to_LUT.c_str(), ios::binary | ios::out | ios::app);
475 
476 
477  // Write the corresponding crystal parameters in the LUT
478  for(int i=0 ; i<nb_crystals_lyr[lyr] ; i++)
479  {
480  LUT_file.write(reinterpret_cast<char*>(&crystal_positionX[i]), sizeof(FLTNBLUT));
481  LUT_file.write(reinterpret_cast<char*>(&crystal_positionY[i]), sizeof(FLTNBLUT));
482  LUT_file.write(reinterpret_cast<char*>(&crystal_positionZ[i]), sizeof(FLTNBLUT));
483  LUT_file.write(reinterpret_cast<char*>(&crystal_orientationX[i]), sizeof(FLTNBLUT));
484  LUT_file.write(reinterpret_cast<char*>(&crystal_orientationY[i]), sizeof(FLTNBLUT));
485  LUT_file.write(reinterpret_cast<char*>(&crystal_orientationZ[i]), sizeof(FLTNBLUT));
486  }
487 
488  LUT_file.close();
489  cout << ">>> Binary LUT writing OK" << endl;
490 
491  // ============================================================================================================
492  // Free memory
493  // ============================================================================================================
494 
495  // Delete objects
496 
497  for (int i = 0; i < nb_rsectors ; i++)
498  for (int j = 0; j<nb_axial_mod*nb_trans_mod; j++)
499  for (int k = 0; k<nb_axial_submod*nb_trans_submod; k++)
500  for (int l = 0; l<nb_axial_crystal*nb_trans_crystal; l++)
501  delete crystal_center[i][j][k][l];
502 
503  for(int i = 0; i < nb_rsectors ; i++)
504  for (int j = 0; j<nb_axial_mod*nb_trans_mod; j++)
505  for (int k = 0; k<nb_axial_submod*nb_trans_submod; k++)
506  delete[] crystal_center[i][j][k];
507 
508  for(int i = 0; i < nb_rsectors ; i++)
509  for (int j = 0; j<nb_axial_mod*nb_trans_mod; j++)
510  delete[] crystal_center[i][j];
511 
512  for(int i = 0; i < nb_rsectors ; i++)
513  {
514  delete[] crystal_center[i];
515  delete rotation_mtx[i];
516  }
517 
518  delete[] crystal_center;
519  delete[] rotation_mtx;
520  delete[] crystal_positionX;
521  delete[] crystal_positionY;
522  delete[] crystal_positionZ;
523  delete[] crystal_orientationX;
524  delete[] crystal_orientationY;
525  delete[] crystal_orientationZ;
526 
527  } // end of loop on layers
528 
529 
530  // ============================================================================================================
531  // Write header file
532  // ============================================================================================================
533 
534  cout << ">>> Start writing header LUT file..." << endl;
535  header_LUT_file.open(path_to_headerLUT.c_str(), ios::out);
536 
537  header_LUT_file << "scanner name:" << " " << scanner_name << endl;
538  header_LUT_file << "modality:" << " " << scanner_modality << endl;
539 
540  header_LUT_file << "scanner radius:" << " " << radius_lyr[0];
541  for (int lyr=1 ; lyr<nbLayers ; lyr++)
542  header_LUT_file << "," << radius_lyr[lyr] ;
543  header_LUT_file << endl;
544 
545  header_LUT_file << "number of rings in scanner:" << " " << nb_rings << endl;
546  header_LUT_file << "number of elements:" << " " << nb_elts << endl;
547  header_LUT_file << "number of layers:" << " " << nbLayers << endl;
548  header_LUT_file << "number of crystals in layer(s):" << " " << nb_crystals_lyr[0];
549  for (int lyr=1 ; lyr<nbLayers ; lyr++)
550  header_LUT_file << ","<< nb_crystals_lyr[lyr] ;
551  header_LUT_file << endl;
552 
553  header_LUT_file << "crystals size depth:" << " " << crystal_size_depth_lyr[0];
554  for (int lyr=1 ; lyr<nbLayers ; lyr++)
555  header_LUT_file << ","<< crystal_size_depth_lyr[lyr] ;
556  header_LUT_file << endl;
557 
558  header_LUT_file << "crystals size transaxial:" << " " << crystal_size_trans_lyr[0];
559  for (int lyr=1 ; lyr<nbLayers ; lyr++)
560  header_LUT_file << ","<< crystal_size_trans_lyr[lyr] ;
561  header_LUT_file << endl;
562 
563  header_LUT_file << "crystals size axial:" << " " << crystal_size_axial_lyr[0];
564  for (int lyr=1 ; lyr<nbLayers ; lyr++)
565  header_LUT_file << ","<< crystal_size_axial_lyr[lyr] ;
566  header_LUT_file << endl;
567 
568 
569  //default reconstruction parameters
570  header_LUT_file << "voxels number transaxial:" << " " << default_dim_trans << endl;
571  header_LUT_file << "voxels number axial:" << " " << default_dim_axial << endl;
572 
573  header_LUT_file << "field of view transaxial:" << " " << default_FOV_trans << endl;
574  header_LUT_file << "field of view axial:" << " " << default_FOV_axial << endl;
575 
576  header_LUT_file << "min angle difference:" << " " << min_trs_angle_diff << " #deg" << endl;
577 
578  header_LUT_file << "mean depth of interaction:" << " " << mean_depth_of_interaction_lyr[0];
579  for (int lyr=1 ; lyr<nbLayers ; lyr++)
580  header_LUT_file << ","<< mean_depth_of_interaction_lyr[lyr] ;
581  header_LUT_file << " #optional (default value : center of crystal ). Input value must correspond to the distance from the crystal surface, or negative value if default" << endl;
582 
583  header_LUT_file << "description:" << " " << description << endl;
584 
585  cout << ">>> Header LUT file writing OK" << endl;
586 
587  // Free memory
588  delete rsctr_zshift;
589  delete nb_rsectors_lyr;
590  delete nb_trans_mod_lyr;
591  delete nb_axial_mod_lyr;
592  delete nb_trans_submod_lyr;
593  delete nb_axial_submod_lyr;
594  delete nb_trans_crystal_lyr;
595  delete nb_axial_crystal_lyr;
596 
597  delete radius_lyr;
598  delete gap_trans_mod_lyr;
599  delete gap_axial_mod_lyr;
600  delete gap_trans_submod_lyr;
601  delete gap_axial_submod_lyr;
602  delete gap_trans_crystal_lyr;
603  delete gap_axial_crystal_lyr;
604  delete crystal_size_depth_lyr;
605  delete crystal_size_trans_lyr;
606  delete crystal_size_axial_lyr;
607 
608  cout << "Binary file has been created in: " << path_to_LUT << endl;
609  cout << "Header file has been created in: " << path_to_headerLUT << endl << endl;
610  cout << "End of LUT generation" << endl << endl;
611 
612  return EXIT_SUCCESS;
613 }
614 
void Exit(int code)
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
void ShowHelp(int a_returnCode)
const string & GetPathToConfigDir()
Return the path to the CASTOR config directory.
HPFLTNB GetMatriceElt(uint16_t l, uint16_t c)
Structure designed for basic matrices operations.
int main(int argc, char **argv)
int Multiplication(oMatrix *ap_Mtx, oMatrix *ap_MtxResult)
int SetMatriceElt(uint16_t l, uint16_t c, HPFLTNB a_val)