CASToR  1.1
Tomographic Reconstruction (PET/SPECT)
 All Classes Files Functions Variables Typedefs Macros Groups Pages
vOptimizer.cc
Go to the documentation of this file.
1 
2 /*
3  Implementation of class vOptimizer
4 
5  - separators: X
6  - doxygen:
7  - default initialization: X
8  - CASTOR_DEBUG:
9  - CASTOR_VERBOSE:
10 */
11 
18 #include "vOptimizer.hh"
19 
20 // =====================================================================
21 // ---------------------------------------------------------------------
22 // ---------------------------------------------------------------------
23 // =====================================================================
24 
26 {
27  // Affect default values
30  m_nbTOFBins = 0;
31  m_initialValue = 0.;
34  m2p_forwardValues = NULL;
35  m3p_backwardValues = NULL;
38  m_optimizerFOMFlag = false;
40  m4p_FOMLogLikelihood = NULL;
41  m4p_FOMNbBins = NULL;
42  m4p_FOMRMSE = NULL;
43  m4p_FOMNbData = NULL;
44  m_verbose = 0;
45  m2p_attenuationImage = NULL;
46  mp_imageStatNbVox = NULL;
47  mp_imageStatMin = NULL;
48  mp_imageStatMax = NULL;
49  mp_imageStatMean = NULL;
50  mp_imageStatVariance = NULL;
51  mp_correctionStatMean = NULL;
53  //m_penaltyEnergyFunctionDerivativesOrder = 0;
54 }
55 
56 // =====================================================================
57 // ---------------------------------------------------------------------
58 // ---------------------------------------------------------------------
59 // =====================================================================
60 
62 {
63  // Free forward and backward buffers
65  {
67  if (m2p_forwardValues[th]) free(m2p_forwardValues[th]);
68  free(m2p_forwardValues);
69  }
71  {
72  for (int th=0; th<mp_ImageDimensionsAndQuantification->GetNbThreadsMax(); th++)
73  {
74  if (m3p_backwardValues[th])
75  {
76  for (int tof=0; tof<m_nbTOFBins; tof++) if (m3p_backwardValues[th][tof]) free(m3p_backwardValues[th][tof]);
77  free(m3p_backwardValues[th]);
78  }
79  }
80  free(m3p_backwardValues);
81  }
82  // Free pointers to attenuation images for SPECT
84  // Delete all image update statistics tables
86  {
94  }
95  // Delete FOM tables
97  {
98  // Delete the log-likelihood table
100  {
101  for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++)
102  {
103  if (m4p_FOMLogLikelihood[fr])
104  {
105  for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++)
106  {
107  if (m4p_FOMLogLikelihood[fr][rg])
108  {
109  for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++)
110  if (m4p_FOMLogLikelihood[fr][rg][cg]) free(m4p_FOMLogLikelihood[fr][rg][cg]);
111  free(m4p_FOMLogLikelihood[fr][rg]);
112  }
113  }
114  free(m4p_FOMLogLikelihood[fr]);
115  }
116  }
117  free(m4p_FOMLogLikelihood);
118  }
119  // Delete the RMSE table
120  if (m4p_FOMRMSE)
121  {
122  for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++)
123  {
124  if (m4p_FOMRMSE[fr])
125  {
126  for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++)
127  {
128  if (m4p_FOMRMSE[fr][rg])
129  {
130  for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++)
131  if (m4p_FOMRMSE[fr][rg][cg]) free(m4p_FOMRMSE[fr][rg][cg]);
132  free(m4p_FOMRMSE[fr][rg]);
133  }
134  }
135  free(m4p_FOMRMSE[fr]);
136  }
137  }
138  free(m4p_FOMRMSE);
139  }
140  // Delete the nbBins table
141  if (m4p_FOMNbBins)
142  {
143  for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++)
144  {
145  if (m4p_FOMNbBins[fr])
146  {
147  for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++)
148  {
149  if (m4p_FOMNbBins[fr][rg])
150  {
151  for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++)
152  if (m4p_FOMNbBins[fr][rg][cg]) free(m4p_FOMNbBins[fr][rg][cg]);
153  free(m4p_FOMNbBins[fr][rg]);
154  }
155  }
156  free(m4p_FOMNbBins[fr]);
157  }
158  }
159  free(m4p_FOMNbBins);
160  }
161  // Delete the nbData table
162  if (m4p_FOMNbData)
163  {
164  for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++)
165  {
166  if (m4p_FOMNbData[fr])
167  {
168  for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++)
169  {
170  if (m4p_FOMNbData[fr][rg])
171  {
172  for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++)
173  if (m4p_FOMNbData[fr][rg][cg]) free(m4p_FOMNbData[fr][rg][cg]);
174  free(m4p_FOMNbData[fr][rg]);
175  }
176  }
177  free(m4p_FOMNbData[fr]);
178  }
179  }
180  free(m4p_FOMNbData);
181  }
182  }
183 }
184 
185 // =====================================================================
186 // ---------------------------------------------------------------------
187 // ---------------------------------------------------------------------
188 // =====================================================================
189 
191 {
192  // Call the specific help function from the children
194  // Then, say if the child optimizer is compatible with histogram and/or list-mode data
195  if (m_listmodeCompatibility && m_histogramCompatibility) cout << "This optimizer is compatible with both histogram and list-mode data." << endl;
196  else if (m_listmodeCompatibility) cout << "This optimizer is only compatible with list-mode data." << endl;
197  else if (m_histogramCompatibility) cout << "This optimizer is only compatible with histogram data." << endl;
198  else cout << "This optimizer is a total non-sense, not compatible with histogram nor list-mode data !!!" << endl;
199 }
200 
201 // =====================================================================
202 // ---------------------------------------------------------------------
203 // ---------------------------------------------------------------------
204 // =====================================================================
205 
207 {
208  // Check image dimensions
210  {
211  Cerr("***** vOptimizer::CheckParameters() -> oImageDimensionsAndQuantification is null !" << endl);
212  return 1;
213  }
214  // Check data mode
216  {
217  Cerr("***** vOptimizer::CheckParameters() -> No or meaningless data mode provided !" << endl);
218  return 1;
219  }
220  // Check data type
222  {
223  Cerr("***** vOptimizer::CheckParameters() -> No or meaningless data type provided !" << endl);
224  return 1;
225  }
226  // Check verbose level
227  if (m_verbose<0)
228  {
229  Cerr("***** vOptimizer::CheckParameters() -> Verbose level is negative !" << endl);
230  return 1;
231  }
232  // Listmode incompatibility
234  {
235  Cerr("***** vOptimizer::CheckParameters() -> The selected optimizer is not compatible with listmode data !" << endl);
236  return 1;
237  }
238  // Histogram incompatibility
240  {
241  Cerr("***** vOptimizer::CheckParameters() -> The selected optimizer is not compatible with histogram data !" << endl);
242  return 1;
243  }
244  // Send an error if FOM computation is required and verbose is null
245  if (m_optimizerFOMFlag && m_verbose==0)
246  {
247  Cerr("***** vOptimizer::CheckParameters() -> Asked to compute FOMs in the data-space whereas the verbose is not set !" << endl);
248  return 1;
249  }
250  // Send an error if image statistics computation is required and verbose is null
252  {
253  Cerr("***** vOptimizer::CheckParameters() -> Asked to compute image update statistics whereas the verbose is not set !" << endl);
254  return 1;
255  }
256  // Send an error if FOM computation with list-mode data (it has no sense)
258  {
259  Cerr("***** vOptimizer::CheckParameters() -> Computing FOMs in the data-space with list-mode data is not possible !" << endl);
260  return 1;
261  }
262  // Call the CheckSpecificParameters function of the child
264  {
265  Cerr("***** vOptimizer::CheckParameters() -> A problem occured while checking parameters specific to the optimizer module !" << endl);
266  return 1;
267  }
268  // Normal end
269  return 0;
270 }
271 
272 // =====================================================================
273 // ---------------------------------------------------------------------
274 // ---------------------------------------------------------------------
275 // =====================================================================
276 
278 {
279  // Allocate forward buffers (as many as threads and as many as TOF bins)
282  m2p_forwardValues[th] = (FLTNB*)malloc(m_nbTOFBins*sizeof(FLTNB));
283 
284  // Allocate backward buffers (as many as threads then as many as TOF bins and as many as backward images)
286  for (int th=0; th<mp_ImageDimensionsAndQuantification->GetNbThreadsMax(); th++)
287  {
288  m3p_backwardValues[th] = (FLTNB**)malloc(m_nbTOFBins*sizeof(FLTNB*));
289  for (int tof=0; tof<m_nbTOFBins; tof++)
290  m3p_backwardValues[th][tof] = (FLTNB*)malloc(m_nbBackwardImages*sizeof(FLTNB));
291  }
292 
293  // Allocate pointers to the current attenuation image for SPECT attenuation correction
296 
297  // Allocate the thread-safe tables for image update statistics computation
299  {
307  }
308 
309  // We allocate the tables that hold the figures-of-merit if FOM flag is on
310  if (m_optimizerFOMFlag)
311  {
312  m4p_FOMNbBins = (uint64_t****)malloc(mp_ImageDimensionsAndQuantification->GetNbTimeFrames()*sizeof(uint64_t***));
313  m4p_FOMNbData = (double****)malloc(mp_ImageDimensionsAndQuantification->GetNbTimeFrames()*sizeof(double***));
316  for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++)
317  {
318  m4p_FOMNbBins[fr] = (uint64_t***)malloc(mp_ImageDimensionsAndQuantification->GetNbRespGates()*sizeof(uint64_t**));
319  m4p_FOMNbData[fr] = (double***)malloc(mp_ImageDimensionsAndQuantification->GetNbRespGates()*sizeof(double**));
322  for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++)
323  {
324  m4p_FOMNbBins[fr][rg] = (uint64_t**)malloc(mp_ImageDimensionsAndQuantification->GetNbCardGates()*sizeof(uint64_t*));
325  m4p_FOMNbData[fr][rg] = (double**)malloc(mp_ImageDimensionsAndQuantification->GetNbCardGates()*sizeof(double*));
328  for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++)
329  {
330  m4p_FOMNbBins[fr][rg][cg] = (uint64_t*)malloc(mp_ImageDimensionsAndQuantification->GetNbThreadsForProjection()*sizeof(uint64_t));
331  m4p_FOMNbData[fr][rg][cg] = (double*)malloc(mp_ImageDimensionsAndQuantification->GetNbThreadsForProjection()*sizeof(double));
334  }
335  }
336  }
337  }
338 
339  // Call the specific initialization function of the child
340  if (InitializeSpecific())
341  {
342  Cerr("***** vOptimizer::Initialize() -> A problem occured while initializing stuff specific to the optimizer module !" << endl);
343  return 1;
344  }
345 
346  // Normal end
347  return 0;
348 }
349 
350 // =====================================================================
351 // ---------------------------------------------------------------------
352 // ---------------------------------------------------------------------
353 // =====================================================================
354 
355 int vOptimizer::PreDataUpdateStep(int a_iteration, int a_nbIterations, int a_subset, int a_nbSubsets)
356 {
357  // Simply reset FOMs if activated
358  if (m_optimizerFOMFlag)
359  {
360  for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++)
361  for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++)
362  for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++)
364  {
365  m4p_FOMNbBins[fr][rg][cg][th] = 0;
366  m4p_FOMNbData[fr][rg][cg][th] = 0.;
367  m4p_FOMLogLikelihood[fr][rg][cg][th] = 0.;
368  m4p_FOMRMSE[fr][rg][cg][th] = 0.;
369  }
370  }
371  // Then call the specific pre-update-step function from the child optimizer
372  if (PreDataUpdateSpecificStep(a_iteration, a_nbIterations, a_subset, a_nbSubsets))
373  {
374  Cerr("***** vOptimizer::PreDataUpdateStep() -> A problem occured while applying the specific pre-data-update step of the optimizer module !" << endl);
375  return 1;
376  }
377  // Normal end
378  return 0;
379 }
380 
381 // =====================================================================
382 // ---------------------------------------------------------------------
383 // ---------------------------------------------------------------------
384 // =====================================================================
385 
386 int vOptimizer::PreDataUpdateSpecificStep(int a_iteration, int a_nbIterations, int a_subset, int a_nbSubsets)
387 {
388  // By default, just do nothing here. This function is designed to be overloaded by the specific optimizer if needed
389  return 0;
390 }
391 
392 // =====================================================================
393 // ---------------------------------------------------------------------
394 // ---------------------------------------------------------------------
395 // =====================================================================
396 
397 int vOptimizer::PostDataUpdateStep(int a_iteration, int a_nbIterations, int a_subset, int a_nbSubsets)
398 {
399  // Print out the FOMs if activated
400  if (m_optimizerFOMFlag)
401  {
402  // Verbose
403  Cout("vOptimizer::PostDataUpdateStep() -> Data-space figures-of-merit" << endl);
404  // Number of spaces for printing
405  string spaces_fr = ""; if (mp_ImageDimensionsAndQuantification->GetNbTimeFrames()>1) spaces_fr += " ";
406  string spaces_rg = ""; if (mp_ImageDimensionsAndQuantification->GetNbRespGates()>1) spaces_rg += " ";
407  string spaces_cg = ""; if (mp_ImageDimensionsAndQuantification->GetNbCardGates()>1) spaces_cg += " ";
408  // Loop on frames and gates
409  for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++)
410  {
411  // Verbose
413  Cout(spaces_fr << "Frame " << fr+1 << " on " << mp_ImageDimensionsAndQuantification->GetNbTimeFrames() << endl);
414  for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++)
415  {
416  // Verbose
418  Cout(spaces_fr << spaces_rg << "Respiratory gate " << rg+1 << " on " << mp_ImageDimensionsAndQuantification->GetNbRespGates() << endl);
419  for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++)
420  {
421  // Verbose
423  Cout(spaces_fr << spaces_rg << spaces_cg << "Cardiac gate " << cg+1 << " on " << mp_ImageDimensionsAndQuantification->GetNbCardGates() << endl);
424  // Merge thread results
426  {
427  m4p_FOMNbBins[fr][rg][cg][0] += m4p_FOMNbBins[fr][rg][cg][th];
428  m4p_FOMNbData[fr][rg][cg][0] += m4p_FOMNbData[fr][rg][cg][th];
429  m4p_FOMLogLikelihood[fr][rg][cg][0] += m4p_FOMLogLikelihood[fr][rg][cg][th];
430  m4p_FOMRMSE[fr][rg][cg][0] += m4p_FOMRMSE[fr][rg][cg][th];
431  }
432  // Finish mean number of data counts per channel
433  m4p_FOMNbData[fr][rg][cg][0] /= ((double)(m4p_FOMNbBins[fr][rg][cg][0]));
434  // Finish RMSE computation
435  m4p_FOMRMSE[fr][rg][cg][0] /= ((FLTNB)(m4p_FOMNbBins[fr][rg][cg][0]));
436  m4p_FOMRMSE[fr][rg][cg][0] = sqrt(m4p_FOMRMSE[fr][rg][cg][0]);
437  // Print out
438  Cout(spaces_fr << spaces_rg << spaces_cg << " --> Number of data channels used in optimization: " << m4p_FOMNbBins[fr][rg][cg][0] << endl);
439  Cout(spaces_fr << spaces_rg << spaces_cg << " --> Mean number of data counts per channel: " << m4p_FOMNbData[fr][rg][cg][0] << endl);
440  Cout(spaces_fr << spaces_rg << spaces_cg << " --> Log-likelihood: " << m4p_FOMLogLikelihood[fr][rg][cg][0] << endl);
441  Cout(spaces_fr << spaces_rg << spaces_cg << " --> RMSE: " << m4p_FOMRMSE[fr][rg][cg][0] << endl);
442  }
443  }
444  }
445  }
446  // Then call the specific post-update-step function from the child optimizer
447  if (PostDataUpdateSpecificStep(a_iteration, a_nbIterations, a_subset, a_nbSubsets))
448  {
449  Cerr("***** vOptimizer::PostDataUpdateStep() -> A problem occured while applying the specific post-data-update step of the optimizer module !" << endl);
450  return 1;
451  }
452  // Normal end
453  return 0;
454 }
455 
456 // =====================================================================
457 // ---------------------------------------------------------------------
458 // ---------------------------------------------------------------------
459 // =====================================================================
460 
461 int vOptimizer::PostDataUpdateSpecificStep(int a_iteration, int a_nbIterations, int a_subset, int a_nbSubsets)
462 {
463  // By default, just do nothing here. This function is designed to be overloaded by the specific optimizer if needed
464  return 0;
465 }
466 
467 // =====================================================================
468 // ---------------------------------------------------------------------
469 // ---------------------------------------------------------------------
470 // =====================================================================
471 
473  int a_bed, int a_timeFrame, int a_respGate, int a_cardGate,
474  int a_th )
475 {
476  // =======================================================================
477  // 4D forward projection including framing, respiratory and cardiac gating
478  // =======================================================================
479 
480  // Clean buffers
481  for (int b=0; b<ap_Line->GetNbTOFBins(); b++)
482  {
483  m2p_forwardValues[a_th][b] = 0.;
484  for (int img=0; img<m_nbBackwardImages; img++) m3p_backwardValues[a_th][b][img] = 0.;
485  }
486 
487  // Loop over time basis functions
488  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
489  {
490  // Get frame/basis coefficient and continue if null
491  FLTNB time_basis_coef = mp_ImageDimensionsAndQuantification->GetTimeBasisCoefficient(tbf,a_timeFrame);
492  if (time_basis_coef==0.) continue;
493  // Loop over respiratory basis functions
494  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
495  {
496  // Get resp_gate/basis coefficient and continue if null
497  FLTNB resp_basis_coef = mp_ImageDimensionsAndQuantification->GetRespBasisCoefficient(rbf,a_respGate);
498  if (resp_basis_coef==0.) continue;
499  // Loop over cardiac basis functions
500  for (int cbf=0; cbf<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cbf++)
501  {
502  // Get card_gate_basis coefficient and continue if null
503  FLTNB card_basis_coef = mp_ImageDimensionsAndQuantification->GetCardBasisCoefficient(cbf,a_cardGate);
504  if (card_basis_coef==0.) continue;
505  // Compute global coefficient
506  FLTNB global_basis_coef = time_basis_coef * resp_basis_coef * card_basis_coef;
507  // Loop over TOF bins
508  for (int b=0; b<ap_Line->GetNbTOFBins(); b++)
509  {
510  // Set the current TOF bin
511  ap_Line->SetCurrentTOFBin(b);
512  // Project the image and apply dynamic coefficient converions
513  m2p_forwardValues[a_th][b] += ForwardProject(ap_Line,ap_Image->m4p_forwardImage[tbf][rbf][cbf]) * global_basis_coef;
514  }
515  }
516  }
517  }
518 
519  // =====================================
520  // Include the additive correction terms
521  // =====================================
522 
523  // Add additive terms (we multiply by the frame duration because the additive terms are provided as rates)
524  for (int b=0; b<ap_Line->GetNbTOFBins(); b++) m2p_forwardValues[a_th][b] += ap_Event->GetAdditiveCorrections(b) * mp_ImageDimensionsAndQuantification->GetFrameDurationInSec(a_bed, a_timeFrame);
525 
526  // End
527  return 0;
528 }
529 
530 // =====================================================================
531 // ---------------------------------------------------------------------
532 // ---------------------------------------------------------------------
533 // =====================================================================
534 
536  int a_bed, int a_timeFrame, int a_respGate, int a_cardGate,
537  int a_iteration, int a_th )
538 {
539  // Deliberately do nothing!
540  return 0;
541 }
542 
543 // =====================================================================
544 // ---------------------------------------------------------------------
545 // ---------------------------------------------------------------------
546 // =====================================================================
547 
549  int a_bed, int a_timeFrame, int a_respGate, int a_cardGate,
550  int a_th )
551 {
552  // Loop over TOF bins
553  for (int b=0; b<ap_Line->GetNbTOFBins(); b++)
554  {
555  // Set the current TOF bin of the projection-line
556  ap_Line->SetCurrentTOFBin(b);
557  // The weight associated to the line to be backprojected
558  FLTNB weight = 0.;
559  // Call the function to compute specific sensitivity
561  (
562  ap_Event->GetEventValue(b), // 1: the measured data
563  m2p_forwardValues[a_th][b], // 2: the forward model
564  &weight, // 3: the sensitivity weight
565  ap_Event->GetMultiplicativeCorrections(), // 4: the multiplicative corrections
566  ap_Event->GetAdditiveCorrections(b)*mp_ImageDimensionsAndQuantification->GetFrameDurationInSec(a_bed, a_timeFrame), // 5: the additive corrections
567  mp_ImageDimensionsAndQuantification->GetQuantificationFactor(a_bed,a_timeFrame, a_respGate, a_cardGate), // 6: the quantification factor
568  ap_Line // 7: the projection line
569  ))
570  {
571  Cerr("***** vOptimizer::DataStep3BackwardProjectSensitivity() -> A problem occured while performing the sensitivity specific operations !" << endl);
572  return 1;
573  }
574  // Back-project the weight into the sensitivity matrix
575  BackwardProject(ap_Line, ap_Image->m5p_sensitivity[a_th][a_timeFrame][a_respGate][a_cardGate], weight);
576  }
577 
578  // End
579  return 0;
580 }
581 
582 // =====================================================================
583 // ---------------------------------------------------------------------
584 // ---------------------------------------------------------------------
585 // =====================================================================
586 
588  int a_bed, int a_timeFrame, int a_respGate, int a_cardGate,
589  int a_iteration, int a_th )
590 {
591  // Deliberately do nothing!
592  return 0;
593 }
594 
595 // =====================================================================
596 // ---------------------------------------------------------------------
597 // ---------------------------------------------------------------------
598 // =====================================================================
599 
601  int a_bed, int a_timeFrame, int a_respGate, int a_cardGate,
602  int a_th )
603 {
604  // Loop on TOF bins
605  for (int b=0; b<ap_Line->GetNbTOFBins(); b++)
606  {
607  // Set the current TOF bin of the projection-line
608  ap_Line->SetCurrentTOFBin(b);
609  // Then call the pure virtual function for specific data space operations
611  (
612  ap_Event->GetEventValue(b), // 1: the measured data
613  m2p_forwardValues[a_th][b], // 2: the forward model
614  m3p_backwardValues[a_th][b], // 3: the backward values (the result)
615  ap_Event->GetMultiplicativeCorrections(), // 4: the multiplicative corrections
616  ap_Event->GetAdditiveCorrections(b)*mp_ImageDimensionsAndQuantification->GetFrameDurationInSec(a_bed, a_timeFrame), // 5: the additive corrections
617  mp_ImageDimensionsAndQuantification->GetQuantificationFactor(a_bed,a_timeFrame, a_respGate, a_cardGate), // 6: the quantification factor
618  ap_Line // 7: the projection line
619  ))
620  {
621  Cerr("***** vOptimizer::DataStep5ComputeCorrections() -> A problem occured while performing specific data space operations !" << endl);
622  return 1;
623  }
624  }
625 
626  // End
627  return 0;
628 }
629 
630 // =====================================================================
631 // ---------------------------------------------------------------------
632 // ---------------------------------------------------------------------
633 // =====================================================================
634 
636  int a_bed, int a_timeFrame, int a_respGate, int a_cardGate,
637  int a_iteration, int a_th )
638 {
639  // Deliberately do nothing!
640  return 0;
641 }
642 
643 // =====================================================================
644 // ---------------------------------------------------------------------
645 // ---------------------------------------------------------------------
646 // =====================================================================
647 
649  int a_bed, int a_timeFrame, int a_respGate, int a_cardGate,
650  int a_th )
651 {
652  // ========================================================================
653  // 4D backward projection including framing, respiratory and cardiac gating
654  // ========================================================================
655 
656  // Loop over time basis functions
657  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
658  {
659  // Get frame/basis coefficient and continue if null
660  FLTNB time_basis_coef = mp_ImageDimensionsAndQuantification->GetTimeBasisCoefficient(tbf,a_timeFrame);
661  if (time_basis_coef==0.) continue;
662  // Loop over respiratory basis functions
663  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
664  {
665  // Get resp_gate/basis coefficient and continue if null
666  FLTNB resp_basis_coef = mp_ImageDimensionsAndQuantification->GetRespBasisCoefficient(rbf,a_respGate);
667  if (resp_basis_coef==0.) continue;
668  // Loop over cardiac basis functions
669  for (int cbf=0; cbf<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cbf++)
670  {
671  // Get card_gate_basis coefficient and continue if null
672  FLTNB card_basis_coef = mp_ImageDimensionsAndQuantification->GetCardBasisCoefficient(cbf,a_cardGate);
673  if (card_basis_coef==0.) continue;
674  // Compute global coefficient
675  FLTNB global_basis_coef = time_basis_coef * resp_basis_coef * card_basis_coef;
676  // Loop over TOF bins
677  for (int b=0; b<ap_Line->GetNbTOFBins(); b++)
678  {
679  // Set the current TOF bin of the projection-line
680  ap_Line->SetCurrentTOFBin(b);
681  // Loop over backprojection images
682  for (int img=0; img<m_nbBackwardImages; img++)
683  {
684  // Continue if backproj is null or infinity
685  if (m3p_backwardValues[a_th][b][img]==0. || !isfinite(m3p_backwardValues[a_th][b][img])) continue;
686  // Backward project into the backward image
687  BackwardProject( ap_Line, ap_Image->m6p_backwardImage[img][a_th][tbf][rbf][cbf] , m3p_backwardValues[a_th][b][img] * global_basis_coef );
688  }
689  }
690  }
691  }
692  }
693 
694  // End
695  return 0;
696 }
697 
698 // =====================================================================
699 // ---------------------------------------------------------------------
700 // ---------------------------------------------------------------------
701 // =====================================================================
702 
704  int a_timeFrame, int a_respGate, int a_cardGate,
705  int a_thread )
706 {
707  // Loop on TOF bins
708  for (int b=0; b<ap_Line->GetNbTOFBins(); b++)
709  {
710  // Get the model and the data
711  FLTNB model = m2p_forwardValues[a_thread][b];
712  FLTNB data = ap_Event->GetEventValue(b);
713  // Update log likelihood only if model is strictly positive (to avoid numerical issues, we use a threshold at e-10)
714  if (model>1.e-10) m4p_FOMLogLikelihood[a_timeFrame][a_respGate][a_cardGate][a_thread] += data*log(model)-model;
715  // Update RMSE
716  m4p_FOMRMSE[a_timeFrame][a_respGate][a_cardGate][a_thread] += (data-model)*(data-model);
717  // Update number of data channels
718  m4p_FOMNbBins[a_timeFrame][a_respGate][a_cardGate][a_thread]++;
719  // Update the number of data counts
720  m4p_FOMNbData[a_timeFrame][a_respGate][a_cardGate][a_thread] += ((double)data);
721  }
722  // Normal end
723  return 0;
724 }
725 
726 // =====================================================================
727 // ---------------------------------------------------------------------
728 // ---------------------------------------------------------------------
729 // =====================================================================
730 
732 {
733  // Verbose
734  if (m_verbose>=3) Cout("vOptimizer::UpdateVisitedVoxels() -> Tick visited voxels based on sensitivity" << endl);
735 
736  // We loop on the sensitivity for the first frame/gates and look if voxels were 'visited' by LORs
737  int thread0 = 0; int frame0 = 0; int resp_gate0 = 0; int card_gate0 = 0;
738  for (int v=0; v<mp_ImageDimensionsAndQuantification->GetNbVoxXYZ(); v++)
739  // If the voxel has been visited, we add 1. to the ap_Image->mp_visitedVoxelsImage
740  if (ap_Image->m5p_sensitivity[thread0][frame0][resp_gate0][card_gate0][v]!=0.) ap_Image->mp_visitedVoxelsImage[v] += 1.;
741 
742  // End
743  return 0;
744 }
745 
746 // =====================================================================
747 // ---------------------------------------------------------------------
748 // ---------------------------------------------------------------------
749 // =====================================================================
750 
751 int vOptimizer::ImageUpdateStep( oImageSpace* ap_Image, int a_iteration, int a_nbSubsets )
752 {
753  // Verbose
754  if (m_verbose>=2 || m_optimizerImageStatFlag) Cout("vOptimizer::ImageUpdateStep() -> Start image update" << endl);
755  // Number of spaces for nice printing
756  string spaces_tbf = ""; if (mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions()>1) spaces_tbf += " ";
757  string spaces_rbf = ""; if (mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions()>1) spaces_rbf += " ";
758  string spaces_cbf = ""; if (mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions()>1) spaces_cbf += " ";
759  // Loop over time basis functions
760  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
761  {
762  // Verbose
764  {
765  if (mp_ImageDimensionsAndQuantification->GetTimeStaticFlag()) Cout(spaces_tbf << "--> Time frame " << tbf+1 << endl);
766  else Cout(spaces_tbf << "--> Time basis function: " << tbf+1 << endl);
767  }
768  // Loop over respiratory basis functions
769  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
770  {
771  // Verbose
773  {
774  if (mp_ImageDimensionsAndQuantification->GetRespStaticFlag()) Cout(spaces_tbf << spaces_rbf << "--> Respiratory gate " << rbf+1 << endl);
775  else Cout(spaces_tbf << spaces_rbf << "--> Respiratory basis function: " << rbf+1 << endl);
776  }
777  // Loop over cardiac basis functions
778  for (int cbf=0; cbf<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cbf++)
779  {
780  // Verbose
782  {
783  if (mp_ImageDimensionsAndQuantification->GetCardStaticFlag()) Cout(spaces_tbf << spaces_rbf << spaces_cbf << "--> Cardiac gate " << cbf+1 << endl);
784  else Cout(spaces_tbf << spaces_rbf << spaces_cbf << "--> Cardiac basis function: " << cbf+1 << endl);
785  }
786  // Set the number of threads for image computation
787  #ifdef CASTOR_OMP
789  #endif
790  // Reset counter for image stats
792  {
794  {
795  mp_imageStatNbVox[th] = 0;
796  mp_imageStatMin[th] = ap_Image->m4p_image[tbf][rbf][cbf][0];
797  mp_imageStatMax[th] = ap_Image->m4p_image[tbf][rbf][cbf][0];
798  mp_imageStatMean[th] = 0.;
799  mp_imageStatVariance[th] = 0.;
800  mp_correctionStatMean[th] = 0.;
801  mp_correctionStatVariance[th] = 0.;
802  }
803  }
804  // OMP loop over voxels
805  int v;
806  bool error = false;
807  #pragma omp parallel for private(v) schedule(guided)
808  for (v=0 ; v<mp_ImageDimensionsAndQuantification->GetNbVoxXYZ() ; v++)
809  {
810  // Get the thread index
811  int th = 0;
812  #ifdef CASTOR_OMP
813  th = omp_get_thread_num();
814  #endif
815  // Compute sensitivity
816  FLTNB sensitivity = ComputeSensitivity(ap_Image->m5p_sensitivity[0],tbf,rbf,cbf,v,a_nbSubsets);
817  // If the sensitivity is negative or null, we skip this voxel
818  if (sensitivity<=0.) continue;
819  // Keep the current image value in a buffer for update statistics
820  FLTNB old_image_value = ap_Image->m4p_image[tbf][rbf][cbf][v];
821  // Fill class-local buffer of backward values (thread-safe)
822  for (int nb=0; nb<m_nbBackwardImages; nb++)
823  m3p_backwardValues[th][0][nb] = ap_Image->m6p_backwardImage[nb][0][tbf][rbf][cbf][v];
824  // Then call the pure virtual function for specific data space operations
826  (
827  ap_Image->m4p_image[tbf][rbf][cbf][v],
828  // Note: have to be carefull here because we pass rbf and cbf as the actual respgate and cardgate. It may be wrong if one would like
829  // to perform MLAA reconstruction but using PET basis functions different from diracs for example... In this case, we would get
830  // segmentation faults. But actually, this function would be overloaded by MLAA anyway...
831  //ap_Image->m4p_attenuation != NULL ? ap_Image->m4p_attenuation[tbf][rbf][cbf][v] : 0. ,
832  &ap_Image->m4p_image[tbf][rbf][cbf][v],
833  //ap_Image->m4p_attenuation != NULL ? &ap_Image->m4p_attenuation[tbf][rbf][cbf][v] : NULL ,
834  sensitivity,
835  m3p_backwardValues[th][0]
836  ))
837  {
838  Cerr("***** vOptimizer::ImageUpdateStep() -> A problem occured in while performing image space specific operations of the optimizer !" << endl);
839  error = true;
840  }
841  // Do some image statistics
843  {
844  if (mp_imageStatMin[th]>ap_Image->m4p_image[tbf][rbf][cbf][v]) mp_imageStatMin[th] = ap_Image->m4p_image[tbf][rbf][cbf][v];
845  if (mp_imageStatMax[th]<ap_Image->m4p_image[tbf][rbf][cbf][v]) mp_imageStatMax[th] = ap_Image->m4p_image[tbf][rbf][cbf][v];
846  // The one pass algorithm is used to compute the variance here for both the image and correction step.
847  // Do not change anyhting to the order of the operations !
848  mp_imageStatNbVox[th]++;
849  double sample = ((double)(ap_Image->m4p_image[tbf][rbf][cbf][v]));
850  double delta = sample - mp_imageStatMean[th];
851  mp_imageStatMean[th] += delta / ((double)(mp_imageStatNbVox[th]));
852  mp_imageStatVariance[th] += delta * (sample - mp_imageStatMean[th]);
853  // Same one-pass variance algorithm for the correction step
854  sample = ((double)(ap_Image->m4p_image[tbf][rbf][cbf][v] - old_image_value));
855  delta = sample - mp_correctionStatMean[th];
856  mp_correctionStatMean[th] += delta / ((double)(mp_imageStatNbVox[th]));
857  mp_correctionStatVariance[th] += delta * (sample - mp_correctionStatMean[th]);
858  }
859  }
860  // Check for errors (we cannot stop the multi-threaded loop so we do it here)
861  if (error) return 1;
862  // Finish image update statistics computations: these operations are specific to the merging of the
863  // multi-threaded one-pass variance estimations used above.
865  {
867  {
868  // Image minimum and maximum
871  // Cast the counts into double
872  double count1 = ((double)(mp_imageStatNbVox[0]));
873  double count2 = ((double)(mp_imageStatNbVox[th]));
874  // Update the count
876  double count12 = ((double)(mp_imageStatNbVox[0]));
877  // Compute the delta mean
878  double delta = mp_imageStatMean[0] - mp_imageStatMean[th];
879  // Update the variance
880  mp_imageStatVariance[0] += mp_imageStatVariance[th] + delta * delta * count1 * count2 / count12;
881  // Update the mean
882  mp_imageStatMean[0] = (count1*mp_imageStatMean[0] + count2*mp_imageStatMean[th]) / count12;
883  // Do the same for the correction step
885  mp_correctionStatVariance[0] += mp_correctionStatVariance[th] + delta * delta * count1 * count2 / count12;
886  mp_correctionStatMean[0] = (count1*mp_correctionStatMean[0] + count2*mp_correctionStatMean[th]) / count12;
887  }
888  // Finish variance computation
889  mp_imageStatVariance[0] /= ((double)(mp_imageStatNbVox[0]));
890  mp_correctionStatVariance[0] /= ((double)(mp_imageStatNbVox[0]));
891  // Print out
892  Cout(spaces_tbf << spaces_rbf << spaces_cbf << " --> Image update step "
893  << " | mean: " << mp_correctionStatMean[0]
894  << " | stdv: " << sqrt(mp_correctionStatVariance[0]) << endl);
895  Cout(spaces_tbf << spaces_rbf << spaces_cbf << " --> New image estimate"
896  << " | mean: " << mp_imageStatMean[0]
897  << " | stdv: " << sqrt(mp_imageStatVariance[0])
898  << " | min/max: " << mp_imageStatMin[0] << "/" << mp_imageStatMax[0] << endl);
899  }
900  }
901  }
902  }
903 
904  // End
905  return 0;
906 }
907 
908 // =====================================================================
909 // ---------------------------------------------------------------------
910 // ---------------------------------------------------------------------
911 // =====================================================================
912 
914 {
915  // Particular case for SPECT with attenuation correction
916  if (m_dataType==TYPE_SPECT && m2p_attenuationImage[ap_Line->GetThreadNumber()]!=NULL)
917  return ap_Line->ForwardProjectWithSPECTAttenuation( m2p_attenuationImage[ap_Line->GetThreadNumber()], ap_image );
918  // Otherwise call the function without attenuation
919  else
920  return ap_Line->ForwardProject( ap_image );
921 }
922 
923 // =====================================================================
924 // ---------------------------------------------------------------------
925 // ---------------------------------------------------------------------
926 // =====================================================================
927 
928 void vOptimizer::BackwardProject(oProjectionLine* ap_Line, FLTNB* ap_image, FLTNB a_value)
929 {
930  // Particular case for SPECT with attenuation correction
931  if (m_dataType==TYPE_SPECT && m2p_attenuationImage[ap_Line->GetThreadNumber()]!=NULL)
932  ap_Line->BackwardProjectWithSPECTAttenuation( m2p_attenuationImage[ap_Line->GetThreadNumber()], ap_image, a_value );
933  // Otherwise call the function without attenuation
934  else
935  ap_Line->BackwardProject( ap_image, a_value );
936 }
937 
938 // =====================================================================
939 // ---------------------------------------------------------------------
940 // ---------------------------------------------------------------------
941 // =====================================================================
942 
943 FLTNB vOptimizer::ComputeSensitivity( FLTNB**** a4p_sensitivityMatrix,
944  int a_timeBasisFunction, int a_respBasisFunction, int a_cardBasisFunction,
945  int a_voxel, int a_nbSubsets )
946 {
947  // The sensitivity to be computed
948  FLTNB sensitivity = 0.;
949  // Loop over time frames
950  for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++)
951  {
952  // Get frame/basis coefficient and continue if null
953  FLTNB time_basis_coef = mp_ImageDimensionsAndQuantification->GetTimeBasisCoefficient(a_timeBasisFunction,fr);
954  if (time_basis_coef==0.) continue;
955  // Loop over respiratory gates
956  for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++)
957  {
958  // Get resp_gate/basis coefficient and continue if null
959  FLTNB resp_basis_coef = mp_ImageDimensionsAndQuantification->GetRespBasisCoefficient(a_respBasisFunction,rg);
960  if (resp_basis_coef==0.) continue;
961  // Loop over cardiac gates
962  for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++)
963  {
964  // Get card_gate_basis coefficient and continue if null
965  FLTNB card_basis_coef = mp_ImageDimensionsAndQuantification->GetCardBasisCoefficient(a_cardBasisFunction,cg);
966  if (card_basis_coef==0.) continue;
967  // Add actual weight contribution
968  sensitivity += a4p_sensitivityMatrix[fr][rg][cg][a_voxel] *
969  time_basis_coef * resp_basis_coef * card_basis_coef;
970  }
971  }
972  }
973  // If listmode, then divide by the number of subsets
974  if (m_dataMode==MODE_LIST) sensitivity /= ((FLTNB)a_nbSubsets);
975  // Return sensitivity
976  return sensitivity;
977 }
978 
979 // =====================================================================
980 // ---------------------------------------------------------------------
981 // ---------------------------------------------------------------------
982 // =====================================================================
double * mp_imageStatVariance
Definition: vOptimizer.hh:607
FLTNB **** m4p_forwardImage
Definition: oImageSpace.hh:68
FLTNB * mp_imageStatMax
Definition: vOptimizer.hh:605
#define MODE_HISTOGRAM
Definition: vDataFile.hh:36
#define TYPE_PET
Definition: vDataFile.hh:51
FLTNB ForwardProjectWithSPECTAttenuation(FLTNB *ap_attenuation, FLTNB *ap_image=NULL)
Forward projects the provided image for the current TOF bin with an inner loop on the attenuation (fo...
#define TYPE_UNKNOWN
Definition: vDataFile.hh:49
virtual int PostDataUpdateSpecificStep(int a_iteration, int a_nbIterations, int a_subset, int a_nbSubsets)
A private function used to perform any step required by the child optimizer, after the loop on event ...
Definition: vOptimizer.cc:461
#define MODE_LIST
Definition: vDataFile.hh:34
int GetNbCardBasisFunctions()
Get the number of cardiac basis functions.
#define FLTNB
Definition: gVariables.hh:55
FLTNB m_initialValue
Definition: vOptimizer.hh:587
virtual FLTNB GetAdditiveCorrections(int a_bin)=0
Pure virtual function implemented in the child classes.
bool m_listmodeCompatibility
Definition: vOptimizer.hh:588
FLTNB * mp_imageStatMin
Definition: vOptimizer.hh:604
FLTNB GetRespBasisCoefficient(int a_respBasisFunction, int a_respGate)
Get the respiratory basis coefficients for the provided respiratory gate and basis function...
double * mp_correctionStatMean
Definition: vOptimizer.hh:608
void SetCurrentTOFBin(int a_TOFBin)
This function is used to set the current TOF bin that is used.
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
Definition: vOptimizer.hh:591
virtual int DataStep3BackwardProjectSensitivity(oProjectionLine *ap_Line, oImageSpace *ap_Image, vEvent *ap_Event, int a_bed, int a_timeFrame, int a_respGate, int a_cardGate, int a_thread)
A public function used to back-project the sensitivity terms for the provided event.
Definition: vOptimizer.cc:548
#define TYPE_TRANSMISSION
Definition: vDataFile.hh:55
virtual int CheckSpecificParameters()=0
A private function used to check the parameters settings specific to the child optimizer.
virtual int ImageUpdateStep(oImageSpace *ap_Image, int a_iteration, int a_nbSubsets)
A public function used to perform the image update step of the optimizer.
Definition: vOptimizer.cc:751
int GetNbTimeBasisFunctions()
Get the number of time basis functions.
vOptimizer()
The constructor of vOptimizer.
Definition: vOptimizer.cc:25
FLTNB ForwardProject(oProjectionLine *ap_Line, FLTNB *ap_image=NULL)
A function used to forward project the provided image (or 1 if NULL), based on the provided oProjecti...
Definition: vOptimizer.cc:913
virtual FLTNB GetMultiplicativeCorrections()=0
This is a pure virtual function implemented in the child classes.
int GetThreadNumber()
This function is used to get the thread number associated to this line.
uint64_t **** m4p_FOMNbBins
Definition: vOptimizer.hh:599
#define TYPE_SPECT
Definition: vDataFile.hh:53
double * mp_correctionStatVariance
Definition: vOptimizer.hh:609
FLTNB **** m4p_FOMRMSE
Definition: vOptimizer.hh:598
int m_dataMode
Definition: vOptimizer.hh:592
virtual int DataStep1ForwardProjectModel(oProjectionLine *ap_Line, oImageSpace *ap_Image, vEvent *ap_Event, int a_bed, int a_timeFrame, int a_respGate, int a_cardGate, int a_thread)
A public function used to compute the model: forward projection of the provided event.
Definition: vOptimizer.cc:472
bool m_optimizerFOMFlag
Definition: vOptimizer.hh:596
bool GetRespStaticFlag()
Get the respiratory static flag that says if the reconstruction has only one respiratory gate or not...
FLTNB * mp_visitedVoxelsImage
Definition: oImageSpace.hh:104
INTNB * mp_imageStatNbVox
Definition: vOptimizer.hh:603
void BackwardProject(FLTNB *ap_image, FLTNB a_value)
Simply backward projects the provided value inside the provided image, for the current TOF bin...
#define Cerr(MESSAGE)
virtual int DataSpaceSpecificOperations(FLTNB a_data, FLTNB a_forwardModel, FLTNB *ap_backwardValues, FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_quantificationFactor, oProjectionLine *ap_Line)=0
A private function used to compute the correction term in the data space from the provided data...
FLTNB ****** m6p_backwardImage
Definition: oImageSpace.hh:75
bool GetCardStaticFlag()
Get the cardiac static flag that says if the reconstruction has only one cardiac gate or not...
FLTNB **** m4p_image
Definition: oImageSpace.hh:61
void BackwardProjectWithSPECTAttenuation(FLTNB *ap_attenuation, FLTNB *ap_image, FLTNB a_value)
Backward project the provided value inside the provided image with an inner loop on the attenuation (...
int m_nbBackwardImages
Definition: vOptimizer.hh:583
virtual int InitializeSpecific()=0
A private function used to initialize everything specific to the child optimizer. ...
int GetNbThreadsMax()
Get the maximum between the number of threads used for projections and image operations.
void BackwardProject(oProjectionLine *ap_Line, FLTNB *ap_image, FLTNB a_value)
A function used to backward project the provided value into the provided image, based on the provided...
Definition: vOptimizer.cc:928
virtual FLTNB GetEventValue(int a_bin)=0
Pure virtual function implemented in the child classes.
int PreDataUpdateStep(int a_iteration, int a_nbIterations, int a_subset, int a_nbSubsets)
A public function used to do stuff that need to be done at the beginning of a subset (before the data...
Definition: vOptimizer.cc:355
Declaration of class vOptimizer.
FLTNB ** m2p_attenuationImage
Definition: vOptimizer.hh:594
virtual int DataStep4Optional(oProjectionLine *ap_Line, oImageSpace *ap_Image, vEvent *ap_Event, int a_bed, int a_timeFrame, int a_respGate, int a_cardGate, int a_iteration, int a_thread)
A public function which does nothing but being virtual.
Definition: vOptimizer.cc:587
bool m_histogramCompatibility
Definition: vOptimizer.hh:589
bool m_optimizerImageStatFlag
Definition: vOptimizer.hh:602
FLTNB GetQuantificationFactor(int a_bed, int a_frame, int a_respGate, int a_cardGate)
Get the quantification factor corresponding to the provided bed, frame, respiratory and cardiac gates...
virtual int DataStep8ComputeFOM(oProjectionLine *ap_Line, vEvent *ap_Event, int a_timeFrame, int a_respGate, int a_cardGate, int a_thread)
A public function used to update the computation of figures-of-merit in the data space.
Definition: vOptimizer.cc:703
double **** m4p_FOMNbData
Definition: vOptimizer.hh:600
int UpdateVisitedVoxels(oImageSpace *ap_Image)
A public function used to update the 'visited' voxels after each subset.
Definition: vOptimizer.cc:731
FLTNB GetTimeBasisCoefficient(int a_timeBasisFunction, int a_timeFrame)
Get the time basis coefficients for the provided frame and basis function.
bool GetTimeStaticFlag()
Get the time static flag that says if the reconstruction has only one frame or not.
FLTNB ComputeSensitivity(FLTNB ****a4p_sensitivityImage, int a_timeBasisFunction, int a_respBasisFunction, int a_cardBasisFunction, int a_voxel, int a_nbSubsets)
A function used to compute the sensitivity of a given voxel and a given set of dynamic basis function...
Definition: vOptimizer.cc:943
int PostDataUpdateStep(int a_iteration, int a_nbIterations, int a_subset, int a_nbSubsets)
A public function used to do stuff that need to be done at the beginning of a subset (before the data...
Definition: vOptimizer.cc:397
virtual int PreDataUpdateSpecificStep(int a_iteration, int a_nbIterations, int a_subset, int a_nbSubsets)
A private function used to perform any step required by the child optimizer, before the loop on event...
Definition: vOptimizer.cc:386
virtual int DataStep2Optional(oProjectionLine *ap_Line, oImageSpace *ap_Image, vEvent *ap_Event, int a_bed, int a_timeFrame, int a_respGate, int a_cardGate, int a_iteration, int a_thread)
A public function which does nothing but being virtual.
Definition: vOptimizer.cc:535
virtual ~vOptimizer()
The destructor of vOptimizer.
Definition: vOptimizer.cc:61
#define INTNB
Definition: gVariables.hh:64
int m_nbTOFBins
Definition: vOptimizer.hh:584
This class is designed to manage and store system matrix elements associated to a vEvent...
int GetNbCardGates()
Get the number of cardiac gates.
FLTNB **** m4p_FOMLogLikelihood
Definition: vOptimizer.hh:597
int Initialize()
A public function used to initialize the optimizer.
Definition: vOptimizer.cc:277
This class holds all the matrices in the image domain that can be used in the algorithm: image...
Definition: oImageSpace.hh:41
int m_dataType
Definition: vOptimizer.hh:593
Mother class for the Event objects.
Definition: vEvent.hh:23
int GetNbThreadsForImageComputation()
Get the number of threads used for image operations.
int GetNbTimeFrames()
Get the number of time frames.
FLTNB ForwardProject(FLTNB *ap_image=NULL)
Simply forward projects the provided image if not null, or else 1, for the current TOF bin...
INTNB GetNbVoxXYZ()
Get the total number of voxels.
virtual int DataStep5ComputeCorrections(oProjectionLine *ap_Line, vEvent *ap_Event, int a_bed, int a_timeFrame, int a_respGate, int a_cardGate, int a_thread)
A public function used to compute the correction terms in the data space, for the provided event...
Definition: vOptimizer.cc:600
int GetNbTOFBins()
This function is used to get the number of TOF bins in use.
int GetNbThreadsForProjection()
Get the number of threads used for projections.
#define MODE_UNKNOWN
Definition: vDataFile.hh:32
int GetNbRespGates()
Get the number of respiratory gates.
#define Cout(MESSAGE)
virtual void ShowHelpSpecific()=0
A function used to show help about the child module.
virtual int ImageSpaceSpecificOperations(FLTNB a_currentImageValue, FLTNB *ap_newImageValue, FLTNB a_sensitivity, FLTNB *ap_correctionValues)=0
A private function used to update the image value from the provided data.
FLTNB GetFrameDurationInSec(int a_bed, int a_frame)
Get the frame duration for the given bed, in seconds as a FLTNB.
virtual int DataStep7BackwardProjectCorrections(oProjectionLine *ap_Line, oImageSpace *ap_Image, vEvent *ap_Event, int a_bed, int a_timeFrame, int a_respGate, int a_cardGate, int a_thread)
A public function used to back-project the correction terms into the backward correction image...
Definition: vOptimizer.cc:648
void ShowHelp()
A function used to show help about the optimizer.
Definition: vOptimizer.cc:190
double * mp_imageStatMean
Definition: vOptimizer.hh:606
FLTNB ** m2p_forwardValues
Definition: vOptimizer.hh:585
int GetNbRespBasisFunctions()
Get the number of respiratory basis functions.
virtual int DataStep6Optional(oProjectionLine *ap_Line, oImageSpace *ap_Image, vEvent *ap_Event, int a_bed, int a_timeFrame, int a_respGate, int a_cardGate, int a_iteration, int a_thread)
A public function which does nothing but being virtual.
Definition: vOptimizer.cc:635
FLTNB ***** m5p_sensitivity
Definition: oImageSpace.hh:85
FLTNB *** m3p_backwardValues
Definition: vOptimizer.hh:586
int CheckParameters()
A public function used to check the parameters settings.
Definition: vOptimizer.cc:206
virtual int SensitivitySpecificOperations(FLTNB a_data, FLTNB a_forwardModel, FLTNB *ap_weight, FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_quantificationFactor, oProjectionLine *ap_Line)=0
A private function used to compute the sensitivity weight associated to the provided data...
FLTNB GetCardBasisCoefficient(int a_cardBasisFunction, int a_cardGate)
Get the cardiac basis coefficients for the provided cardiac gate and basis function.