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