gVirtualXRay  2.0.10
VirtualX-RayImagingLibraryonGPU
XRayRenderer.inl
Go to the documentation of this file.
1 /*
2 
3 Copyright (c) 2013-2023, Dr Franck P. Vidal, Bangor University, All rights reserved.
4 Copyright (c) 2023-present, Prof Franck P. Vidal (franck.vidal@stfc.ac.uk),
5 UK Research and Innovation, All rights reserved.
6 
7 
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10 
11 1. Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13 
14 2. Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation and/or
16 other materials provided with the distribution.
17 
18 3. Neither the name of Bangor University, UK Research and Innovation nor the
19 names of its contributors may be used to endorse or promote products derived
20 from this software without specific prior written permission.
21 
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 */
34 
35 
63 //******************************************************************************
64 // Include
65 //******************************************************************************
66 #ifndef GVXR_CONFIG_H
68 #endif
69 
70 #include <cmath>
71 #include <sstream>
72 
73 #ifndef __OpenGLUtilities_h
75 #endif
76 
77 #ifndef __Utilities_h
78 #include "gVirtualXRay/Utilities.h"
79 #endif
80 
81 #ifndef __ElementSet_h
83 #endif
84 
85 #ifndef __MaterialSet_h
87 #endif
88 
89 #ifndef __Logger_h
90 #include <gVirtualXRay/Logger.h>
91 #endif
92 
93 
94 //******************************************************************************
95 // define
96 //******************************************************************************
97 
98 // 2D FBOs first, then 3D FBOs
99 #define XRAY_DETECTOR_UNCLEANED_LBUFFER_FBO_ID 0
100 #define XRAY_DETECTOR_CLEANED_LBUFFER_FBO_ID 1
101 #define XRAY_DETECTOR_CUMULATED_LBUFFERS_FBO_ID 2
102 #define XRAY_DETECTOR_ENERGY_FLUENCE_FBO_ID 3
103 #define XRAY_DETECTOR_SUM_MUx_Dx_FBO_ID 4
104 
105 // 2D textures first, then 3D textures
106 #define XRAY_DETECTOR_UNCLEANED_LBUFFER_TEXTURE_NAME_ID 0
107 #define XRAY_DETECTOR_CLEANED_LBUFFER_TEXTURE_NAME_ID 1
108 #define XRAY_DETECTOR_CUMULATED_LBUFFERS_TEXTURE_NAME_ID 2
109 #define XRAY_DETECTOR_ENERGY_FLUENCE_TEXTURE_NAME_ID 3
110 #define XRAY_DETECTOR_SUM_MUx_Dx_TEXTURE_NAME_ID 4
111 #define XRAY_DETECTOR_ZBUFFER_TEXTURE_NAME_ID 5
112 
113 
114 //******************************************************************************
115 // namespace
116 //******************************************************************************
117 namespace gVirtualXRay {
118 
119 
120  //----------------------------------
122  //----------------------------------
123  {
124  release();
125  }
126 
127 
128  //-----------------------------------------------------------------------------
130  //-----------------------------------------------------------------------------
131  {
132  RATIONAL_NUMBER total_energy = 0.0;
133 
134  // Proceed each energy channel
135  for (unsigned int current_slice(0);
136  current_slice < m_p_xray_beam->getEnergyChannelNumber();
137  ++current_slice)
138  {
139  RATIONAL_NUMBER photon_number(m_p_xray_beam->getEnergyChannel(current_slice).getPhotonNumber());
140  RATIONAL_NUMBER photon_energy(m_p_xray_beam->getEnergyChannel(current_slice).getPhotonEnergy());
141 
142  //std::cout << current_slice << "\t" << photon_number << "\t" << photon_energy;
143 
144  // Apply the energy response
145  photon_energy = m_p_detector->applyEnergyResponse(photon_energy);
146  RATIONAL_NUMBER input_energy(photon_number * photon_energy / RATIONAL_NUMBER(m_p_detector->getNumberOfSourceSamples()));
147 
148  //std::cout << "\t" << photon_energy << std::endl;
149  total_energy += input_energy;
150  }
151 
152  return total_energy;
153  }
154 
155 
156  //------------------------------------------------------------
158  //------------------------------------------------------------
159  {
160  m_negative_display_flag = aFlag;
161  }
162 
163 
164  //--------------------------------------------------------
166  //--------------------------------------------------------
167  {
168  return (m_negative_display_flag);
169  }
170 
171 
172  //------------------------------------------------------------------------
173  inline void XRayRenderer::addInnerSurface(const SceneGraphNode* apSurface)
174  //------------------------------------------------------------------------
175  {
176  m_p_inner_surface_set.push_back(const_cast<SceneGraphNode*>(apSurface));
178  }
179 
180 
181  //------------------------------------------------------------------------
182  inline void XRayRenderer::addOuterSurface(const SceneGraphNode* apSurface)
183  //------------------------------------------------------------------------
184  {
185  m_p_outer_surface = const_cast<SceneGraphNode*>(apSurface);
187  }
188 
189 
190  //---------------------------------------------------------------------
191  inline void XRayRenderer::addInnerSurface(const PolygonMesh* apSurface)
192  //---------------------------------------------------------------------
193  {
194  // Create a node label
195  std::stringstream label;
196  label << "node_" << m_p_internal_data_storage.size();
197 
198  // Add a new SceneGraphNode into the internal storage of the instance
199  // (not an actual SceneGraphNode, but it allows backward compatibility)
200  m_p_internal_data_storage.push_back(
201  new SceneGraphNode(label.str(),
202  const_cast<PolygonMesh*>(apSurface),
203  VEC3(),
204  NULL));
205 
206  // Use the node as an inner surface
208 
209  // Make sure the grouping per material is up-to-date when needed
211  }
212 
213 
214  //---------------------------------------------------------------------
215  inline void XRayRenderer::addOuterSurface(const PolygonMesh* apSurface)
216  //---------------------------------------------------------------------
217  {
218  // Create a node label
219  std::stringstream label;
220  label << "node_" << m_p_internal_data_storage.size();
221 
222  // Add a new SceneGraphNode into the internal storage of the instance
223  // (not an actual SceneGraphNode, but it allows backward compatibility)
224  m_p_internal_data_storage.push_back(
225  new SceneGraphNode(label.str(),
226  const_cast<PolygonMesh*>(apSurface),
227  VEC3(),
228  NULL));
229 
230  // Use the node as an outer surface
232 
233  // Make sure the grouping per material is up-to-date when needed
235  }
236 
237 
238  //--------------------------------------------------------------------
239  inline bool XRayRenderer::isInnerSurface(const SceneGraphNode* apNode)
240  //--------------------------------------------------------------------
241  {
242  for (std::vector<SceneGraphNode*>::const_iterator ite(m_p_inner_surface_set.begin());
243  ite != m_p_inner_surface_set.end();
244  ++ite)
245  {
246  if (*ite == apNode) return true;
247  }
248 
249  return false;
250  }
251 
252 
253  //--------------------------------------------------------------------
254  inline bool XRayRenderer::isOuterSurface(const SceneGraphNode* apNode)
255  //--------------------------------------------------------------------
256  {
257  return (apNode == m_p_outer_surface);
258  }
259 
260 
261  //---------------------------------------------
263  //---------------------------------------------
264  {
265  m_p_inner_surface_set.clear();
267 
268  std::vector<std::vector<SceneGraphNode*>::iterator> waiting_list;
269 
270  for (std::vector<SceneGraphNode*>::iterator ite = m_p_internal_data_storage.begin();
271  ite != m_p_internal_data_storage.end();
272  ++ite)
273  {
274  if (*ite != m_p_outer_surface)
275  {
276  delete *ite;
277  waiting_list.push_back(ite);
278  }
279  }
280 
281  for (std::vector<std::vector<SceneGraphNode*>::iterator>::reverse_iterator ite = waiting_list.rbegin();
282  ite != waiting_list.rend();
283  ++ite)
284  {
285  m_p_internal_data_storage.erase(*ite);
286  }
287  }
288 
289 
290  //--------------------------------------------
292  //--------------------------------------------
293  {
294  std::vector<std::vector<SceneGraphNode*>::iterator> waiting_list;
295 
296  for (std::vector<SceneGraphNode*>::iterator ite = m_p_internal_data_storage.begin();
297  ite != m_p_internal_data_storage.end();
298  ++ite)
299  {
300  if (*ite == m_p_outer_surface)
301  {
302  delete *ite;
303  waiting_list.push_back(ite);
304  }
305  }
306 
307  for (std::vector<std::vector<SceneGraphNode*>::iterator>::reverse_iterator ite = waiting_list.rbegin();
308  ite != waiting_list.rend();
309  ++ite)
310  {
311  m_p_internal_data_storage.erase(*ite);
312  }
313 
314  m_p_outer_surface = 0;
315  }
316 
317 
318  //--------------------------------------------------------------
319  inline void XRayRenderer::printFBO(unsigned int aFBOID,
320  const std::string& aFileName,
321  bool useCompression)
322  //--------------------------------------------------------------
323  {
324  printFBO(aFBOID, aFileName.data(), useCompression);
325  }
326 
327 
328  //--------------------------------------------------------------------
329  inline void XRayRenderer::print2DTexture(unsigned int aTextureID,
330  const std::string& aFileName,
331  bool useCompression)
332  //--------------------------------------------------------------------
333  {
334  print2DTexture(aTextureID, aFileName.data(), useCompression);
335  }
336 
337 
338  //------------------------------------------------------------------
339  inline void XRayRenderer::printLBuffer(const std::string& aFileName,
340  bool useCompression)
341  //------------------------------------------------------------------
342  {
343  printLBuffer(aFileName.data(), useCompression);
344  }
345 
346 
347  //---------------------------------------------------------------------------
348  inline void XRayRenderer::printCumulatedLBuffer(const std::string& aFileName,
349  bool useCompression)
350  //---------------------------------------------------------------------------
351  {
352  printCumulatedLBuffer(aFileName.data(), useCompression);
353  }
354 
355 
356  //-------------------------------------------------------------------
357  inline void XRayRenderer::printSumMuxDx(const std::string& aFileName, bool useCompression)
358  //-------------------------------------------------------------------
359  {
360  printSumMuxDx(aFileName.data(), useCompression);
361  }
362 
363 
364  //------------------------------------------------------------------------
365  inline void XRayRenderer::printEnergyFluence(const std::string& aFileName, bool useCompression)
366  //------------------------------------------------------------------------
367  {
368  printEnergyFluence(aFileName.data(), useCompression);
369  }
370 
371 
372  //--------------------------------------------------------------------
373  inline void XRayRenderer::printXRayImage(const std::string& aFileName, bool useCompression)
374  //--------------------------------------------------------------------
375  {
376  printXRayImage(aFileName.data(), useCompression);
377  }
378 
379 
380  //-----------------------------------------------------------------------
381  inline void XRayRenderer::printMuWaterTable(std::ostream& anOutputStream)
382  //-----------------------------------------------------------------------
383  {
384  for (std::vector<AttenuationCoefficient>::const_iterator ite(m_mu_water_set.begin());
385  ite != m_mu_water_set.end();
386  ++ite)
387  {
388  anOutputStream << *ite << std::endl;
389  }
390  }
391 
392 
393  //----------------------------------------
395  //----------------------------------------
396  {
397  for (std::vector<unsigned int>::iterator ite(m_p_texture_name_set.begin());
398  ite != m_p_texture_name_set.end();
399  ++ite)
400  {
401  // Delete the PBO
402  try
403  {
404  if (*ite != 0)
405  {
406  deletePBO(*ite);
407  }
408  }
409  catch (std::exception& e)
410  {
411  LOGGER.logError(e.what()) << std::endl;
412  }
413 
414  // Make sure the value is reset
415  *ite = 0;
416 
417  // Create a new PBO
418  createPBO(*ite);
419  }
420  }
421 
422 
423  //------------------------------------------------------------------------------
424  inline void XRayRenderer::init2DTextures(int anInternalTextureFormat)
425  //------------------------------------------------------------------------------
426  {
427  // Store the texturing flags
428  pushTexture2D();
429 
430  // Initialise textures
431  for (int i(0); i < XRAY_DETECTOR_2D_TEXTURE_NUMBER; ++i)
432  {
433  create2DTexture(&m_p_texture_name_set[i], anInternalTextureFormat, GL_RGBA);
434  }
435 
436  create2DTexture(&m_zbuffer_texture_id, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT);
437 
438  // Restore the texturing flags
439  popTexture();
440  }
441 
442 
443  //-----------------------------------------------------------------------------------------
445  const RATIONAL_NUMBER& mu_water)
446  //-----------------------------------------------------------------------------------------
447  {
448  // Convert a Hounsfield value into a liner attenuation coefficient given mu(water)
449  return RATIONAL_NUMBER(mu_water * (1.0 + HU / 1000.0));
450  }
451 
452 
453  //-------------------------------------------------------------------------------
455  const RATIONAL_NUMBER& anEnergy)
456  //-------------------------------------------------------------------------------
457  {
458  return (MaterialSet::getInstance().getMaterial(HU).getMu(HU, anEnergy));
459  }
460 
461 
462  //--------------------------------------------------------------------------------------------
464  const RATIONAL_NUMBER& anEnergy)
465  //--------------------------------------------------------------------------------------------
466  {
467  return (MaterialSet::getInstance().getMaterial(HU).getMassAttenuationTotal(anEnergy));
468  }
469 
470 
471  //------------------------------------------------------------------------------
473  //------------------------------------------------------------------------------
474  {
475  return (TissueMaterial::getDensity(HU));
476  }
477 
478 
479  //-------------------------------------------------------------------------------
480  inline RATIONAL_NUMBER XRayRenderer::getElementMu(const char* anElementSymbol,
481  const RATIONAL_NUMBER& anEnergy)
482  //-------------------------------------------------------------------------------
483  {
484  return (ElementSet::getInstance().getElement(anElementSymbol).getMU(anEnergy));
485  }
486 
487 
488  //--------------------------------------------------------------------------------------------
489  inline RATIONAL_NUMBER XRayRenderer::getElementMassAttenuation(const char* anElementSymbol,
490  const RATIONAL_NUMBER& anEnergy)
491  //--------------------------------------------------------------------------------------------
492  {
493  return (ElementSet::getInstance().getElement(anElementSymbol).getMassAttenuationTotal(anEnergy));
494  }
495 
496 
497  //------------------------------------------------------------------------------
498  inline RATIONAL_NUMBER XRayRenderer::getElementDensity(const char* anElementSymbol)
499  //------------------------------------------------------------------------------
500  {
501  return (ElementSet::getInstance().getElement(anElementSymbol).getDensity());
502  }
503 
504 
505  //----------------------------------------------------------------
506  inline unsigned int XRayRenderer::getNumberOfInnerSurfaces() const
507  //----------------------------------------------------------------
508  {
509  return (m_p_inner_surface_set.size());
510  }
511 
512 
513  //----------------------------------------------------------------
514  inline unsigned int XRayRenderer::getNumberOfOuterSurfaces() const
515  //----------------------------------------------------------------
516  {
517  if (m_p_outer_surface)
518  {
519  return (1);
520  }
521  else
522  {
523  return (0);
524  }
525  }
526 
527 
528  //-----------------------------------------------------------------------
529  inline void XRayRenderer::displayInnerSurface(unsigned int anIndex) const
530  //-----------------------------------------------------------------------
531  {
532  if (anIndex >= m_p_inner_surface_set.size())
533  {
534  throw OutOfBoundsException(__FILE__, __FUNCTION__, __LINE__);
535  }
536 
537  m_p_inner_surface_set[anIndex]->display();
538  }
539 
540 
541  //---------------------------------------------------
543  //---------------------------------------------------
544  {
545  if (!m_p_outer_surface)
546  {
547  throw OutOfBoundsException(__FILE__, __FUNCTION__, __LINE__);
548  }
549 
551  }
552 
553 
554  //-----------------------------------------------------------
556  //-----------------------------------------------------------
557  {
559  }
560 
561 
562  //-----------------------------------------------------------
564  //-----------------------------------------------------------
565  {
567  }
568 
569 
570  //-------------------------------------------------------------------------------
572  //-------------------------------------------------------------------------------
573  {
574  return (m_sinogram_image);
575  }
576 
577 
578  //-------------------------------------------------------------------
580  //-------------------------------------------------------------------
581  {
582  return (m_sinogram_image);
583  }
584 
585 
586  //----------------------------------------------------------------------------
588  //----------------------------------------------------------------------------
589  {
590  return (m_sinogram_image.getRawData());
591  }
592 
593 
594  //--------------------------------------------------------------------------------
596  //--------------------------------------------------------------------------------
597  {
598  return (m_projection_set);
599  }
600 
601 
602  //--------------------------------------------------------------------
604  //--------------------------------------------------------------------
605  {
606  return (m_projection_set);
607  }
608 
609 
610  //---------------------------------------------------------------------------
612  {
613  return (m_projection_set.getRawData());
614  }
615 
616 
617  // //---------------------------------------------------------------------------------
618  // inline const Image<XRayRenderer::PixelType>& XRayRenderer::getEnergyFluence() const
619  // //---------------------------------------------------------------------------------
620  // {
621  // std::cout << "\t01" << std::endl;
622  // RATIONAL_NUMBER* p_target(const_cast<RATIONAL_NUMBER*>(m_energy_fluence_image.getRawData()));
623  // std::cout << "\t02" << std::endl;
624  // RATIONAL_NUMBER* p_source(const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_ENERGY_FLUENCE_FBO_ID));
625  // std::cout << "\t03" << std::endl;
626  // std::cout << m_energy_fluence_image.getWidth() << "x" << m_energy_fluence_image.getHeight() << std::endl;
627  // memcpy(p_target,
628  // p_source,
629  // sizeof(RATIONAL_NUMBER) * m_energy_fluence_image.getWidth() * m_energy_fluence_image.getHeight());
630  // std::cout << "\t04" << std::endl;
631 
632  // // Apply the LSF if needed
633  // if (m_p_detector)
634  // {
635  // std::cout << "\t05" << std::endl;
636  // if (m_p_detector->getLSF().size())
637  // {
638  // std::cout << "\t06" << std::endl;
639  // Image<PixelType>& temp = const_cast<Image<PixelType>&>(m_energy_fluence_image);
640  // temp = m_energy_fluence_image.convolution1D(m_p_detector->getLSF());
641  // std::cout << "\t07" << std::endl;
642  // }
643  // }
644 
645  // std::cout << "\t08" << std::endl;
646  // return (m_energy_fluence_image);
647  // }
648 
649 
650  //--------------------------------------------------------------------
652  //--------------------------------------------------------------------
653  {
657 
658  // Add noise
660  {
662  }
663 
664  // Apply the impulse response of the detector if needed
665  if (m_p_detector)
666  {
667  // Favour PSF over LSF
669  {
671  }
672  else if (m_p_detector->getLSF().size())
673  {
675  }
676  }
677 
678  return (m_energy_fluence_image);
679  }
680 
681 
682  // //---------------------------------------------------------------------------
683  // inline const XRayRenderer::PixelType* XRayRenderer::getEnergyFluenceRawData()
684  // //---------------------------------------------------------------------------
685  // {
686  // getEnergyFluence();
687  // return (m_energy_fluence_image.getRawData());
688  // }
689 
690 
691  //---------------------------------------------------------------------------
693  //---------------------------------------------------------------------------
694  {
695  RATIONAL_NUMBER* p_target(const_cast<RATIONAL_NUMBER*>(m_l_buffer_image.getRawData()));
696  RATIONAL_NUMBER* p_source = 0;
697 
699  {
700  p_source = const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_CLEANED_LBUFFER_FBO_ID);
701  }
702  else
703  {
704  p_source = const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_UNCLEANED_LBUFFER_FBO_ID);
705  }
706 
707  memcpy(p_target,
708  p_source,
710 
711  return (m_l_buffer_image);
712  }
713 
714 
715  //---------------------------------------------------------------
717  //---------------------------------------------------------------
718  {
720  RATIONAL_NUMBER* p_source = 0;
721 
723  {
724  p_source = const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_CLEANED_LBUFFER_FBO_ID);
725  }
726  else
727  {
728  p_source = const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_UNCLEANED_LBUFFER_FBO_ID);
729  }
730 
731  memcpy(p_target,
732  p_source,
734 
735  return (m_l_buffer_image);
736  }
737 
738 
739 
740 
741  //---------------------------------------------------------------------------
743  //---------------------------------------------------------------------------
744  {
745  RATIONAL_NUMBER* p_target(const_cast<RATIONAL_NUMBER*>(m_cumulated_lbuffer_image.getRawData()));
746  RATIONAL_NUMBER* p_source = 0;
747 
748  p_source = const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_CUMULATED_LBUFFERS_FBO_ID);
749 
750  memcpy(p_target,
751  p_source,
753 
754  return (m_cumulated_lbuffer_image);
755  }
756 
757 
758  //---------------------------------------------------------------
760  //---------------------------------------------------------------
761  {
763  RATIONAL_NUMBER* p_source = 0;
764 
765  p_source = const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_CUMULATED_LBUFFERS_FBO_ID);
766 
767  memcpy(p_target,
768  p_source,
770 
771  return (m_cumulated_lbuffer_image);
772  }
773 
774 
775  //---------------------------------------------------------------------
777  //---------------------------------------------------------------------
778  {
780  RATIONAL_NUMBER* p_source = 0;
781 
783  {
784  p_source = const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_CLEANED_LBUFFER_FBO_ID);
785  }
786  else
787  {
788  p_source = const_cast<XRayRenderer*>(this)->getFBO(XRAY_DETECTOR_UNCLEANED_LBUFFER_FBO_ID);
789  }
790 
791  memcpy(p_target,
792  p_source,
794 
795  return (m_l_buffer_image.getRawData());
796  }
797 
798 
799  //-----------------------------------------------------------------------
800  inline const std::string& XRayRenderer::getProjectionOutputPathCT() const
801  //-----------------------------------------------------------------------
802  {
804  }
805 
806 
807  //-----------------------------------------------------------------------
808  inline const std::string& XRayRenderer::getScreenshotOutputPathCT() const
809  //-----------------------------------------------------------------------
810  {
812  }
813 
814 
815  //----------------------------------------------------------------
816  inline unsigned int XRayRenderer::getNumberOfProjectionsCT() const
817  //----------------------------------------------------------------
818  {
819  return m_CT_angle_set.size();
820  }
821 
822 
823  //-----------------------------------------------------------------------
825  //-----------------------------------------------------------------------
826  {
827  // No detector set: can't define what the number of projections should be
828  if (!m_p_detector) return 0;
829 
830  float ncols = m_p_detector->getNumberOfPixels()[0];
831  float spacing = m_p_detector->getPixelSpacingInUnitOfLength()[0];
832  float voxel_size = spacing;
833 
834  // Parallel beam over 180 degrees
836  {
837  return round((Pi / 2.0) * ncols);
838  }
839  // CBCT over 360 degrees
840  // See Zhao Z, Gang GJ, Siewerdsen JH.
841  // Noise, sampling, and the number of projections in cone-beam CT with a flat-panel detector.
842  // Med Phys. 2014 Jun;41(6):061909. doi: 10.1118/1.4875688. PMID: 24877820; PMCID: PMC4032401.
843  else
844  {
845  return round(2.0 * Pi / atan((2.0 * voxel_size) / (ncols / spacing)));
846  }
847  }
848 
849 
850 
851  //----------------------------------------------------------
853  //----------------------------------------------------------
854  {
855  return m_CT_first_angle;
856  }
857 
858 
859  //---------------------------------------------------------
861  //---------------------------------------------------------
862  {
863  return m_CT_last_angle;
864  }
865 
866 
867  //---------------------------------------------------------
869  //---------------------------------------------------------
870  {
872  }
873 
874 
875  //-------------------------------------------------------------------
876  inline unsigned int XRayRenderer::getWhiteImagesInFlatFieldCT() const
877  //-------------------------------------------------------------------
878  {
880  }
881 
882 
883  //--------------------------------------------------------------------
885  //--------------------------------------------------------------------
886  {
888  }
889 
890 
891  //--------------------------------------------------------
892  inline const VEC3& XRayRenderer::getRotationAxisCT() const
893  //--------------------------------------------------------
894  {
895  return m_CT_rotation_axis;
896  }
897 
898 
899  //----------------------------------------------------------------------------
900  inline const std::vector<RATIONAL_NUMBER>& XRayRenderer::getAngleSetCT() const
901  //----------------------------------------------------------------------------
902  {
903  return m_CT_angle_set;
904  }
905 
906 
907  //------------------------------------------------------
909  //------------------------------------------------------
910  {
913  }
914 
915 
916  //------------------------------------------------------
918  //------------------------------------------------------
919  {
922  }
923 
924 
925  //------------------------------------------------------
927  //------------------------------------------------------
928  {
930  }
931 
932 
933  //------------------------------------------------------
935  //------------------------------------------------------
936  {
938  }
939 
940 
941  //-------------------------------------------------------
943  //-------------------------------------------------------
944  {
946  }
947 
948 
949  //-------------------------------------------------------
951  //-------------------------------------------------------
952  {
954  }
955 
956 
957  //-------------------------------------------------------
959  //-------------------------------------------------------
960  {
962  }
963 
964 
965  //-------------------------------------------------------
967  //-------------------------------------------------------
968  {
970  }
971 
972 
973  //-------------------------------------------------------------
975  //-------------------------------------------------------------
976  {
978 
980  {
982  }
983  }
984 
985 
986  //------------------------------------------------------------
988  //------------------------------------------------------------
989  {
991 
993  {
995  }
996  }
997 
998 
999  //-------------------------------------------------------------
1001  //-------------------------------------------------------------
1002  {
1004  }
1005 
1006 
1007  //-------------------------------------------------------------
1009  //-------------------------------------------------------------
1010  {
1012  }
1013 
1014 
1015  //---------------------------------------------------------
1017  //---------------------------------------------------------
1018  {
1020  }
1021 
1022 
1023  //---------------------------------------------------------
1025  //---------------------------------------------------------
1026  {
1028  }
1029 
1030 
1031  //---------------------------------------------------------
1033  //---------------------------------------------------------
1034  {
1036  }
1037 
1038 
1039  //---------------------------------------------------------
1041  //---------------------------------------------------------
1042  {
1044  }
1045 
1046 
1047  //-------------------------------------------------------------------------
1049  //-------------------------------------------------------------------------
1050  {
1052  }
1053 
1054 
1055  //-------------------------------------------------------------------------------
1056  inline void XRayRenderer::setMaxRadiusLbufferArtefactFilter(unsigned int aRadius)
1057  //-------------------------------------------------------------------------------
1058  {
1060  }
1061 
1062 
1063  //------------------------------------------------------------
1064  inline void XRayRenderer::printSinogram(const char* aFileName,
1065  bool useCompression)
1066  //------------------------------------------------------------
1067  {
1068  m_sinogram_image.save(aFileName, false, "Sinogram", useCompression);
1069  }
1070 
1071 
1072  //-------------------------------------------------------------------
1073  inline void XRayRenderer::printSinogram(const std::string& aFileName, bool useCompression)
1074  //-------------------------------------------------------------------
1075  {
1076  printSinogram(aFileName.data(), useCompression);
1077  }
1078 
1079 
1080  //-----------------------------------------------------------------
1081  inline void XRayRenderer::printProjectionSet(const char* aFileName, bool useCompression)
1082  //-----------------------------------------------------------------
1083  {
1084  m_projection_set.save(aFileName, false, "Projection set", useCompression);
1085  }
1086 
1087 
1088  //------------------------------------------------------------------------
1089  inline void XRayRenderer::printProjectionSet(const std::string& aFileName, bool useCompression)
1090  //------------------------------------------------------------------------
1091  {
1092  printProjectionSet(aFileName.data(), useCompression);
1093  }
1094 
1095 
1096  //--------------------------------------------
1098  //--------------------------------------------
1099  {
1100  // The energy fluence is not empty
1102  {
1103  switch (m_computing_mode)
1104  {
1105  case OPENGL:
1106  case OPENMP:
1108  break;
1109 
1110  case CUDA:
1111  throw Exception(__FILE__, __FUNCTION__, __LINE__, "CUDA is not supported.");
1112  break;
1113 
1114  case OPENCL:
1115  throw Exception(__FILE__, __FUNCTION__, __LINE__, "OpenCL is not supported.");
1116  break;
1117 
1118  default:
1119  throw Exception(__FILE__, __FUNCTION__, __LINE__, "Unsupported computing mode.");
1120  break;
1121  }
1122  }
1123 
1124  // The energy fluence is now empty
1125  m_energy_fluence_empty = true;
1126  }
1127 
1128 
1129  //---------------------------------------
1131  //---------------------------------------
1132  {
1133  switch (m_computing_mode)
1134  {
1135  case OPENGL:
1136  case OPENMP:
1138  break;
1139 
1140  case CUDA:
1141  throw Exception(__FILE__, __FUNCTION__, __LINE__, "CUDA is not supported.");
1142  break;
1143 
1144  case OPENCL:
1145  throw Exception(__FILE__, __FUNCTION__, __LINE__, "OpenCL is not supported.");
1146  break;
1147 
1148  default:
1149  throw Exception(__FILE__, __FUNCTION__, __LINE__, "Unsupported computing mode.");
1150  break;
1151  }
1152  }
1153 
1154 
1155  //-----------------------------------------------------------
1156  inline void XRayRenderer::printLBuffer(const char* aFileName, bool useCompression)
1157  //-----------------------------------------------------------
1158  {
1160  {
1161  //print2DTexture(XRAY_DETECTOR_CLEANED_LBUFFER_TEXTURE_NAME_ID, aFileName);
1162  printFBO(XRAY_DETECTOR_CLEANED_LBUFFER_FBO_ID, aFileName, useCompression);
1163  }
1164  else
1165  {
1166  //print2DTexture(XRAY_DETECTOR_UNCLEANED_LBUFFER_TEXTURE_NAME_ID, aFileName);
1167  printFBO(XRAY_DETECTOR_UNCLEANED_LBUFFER_FBO_ID, aFileName, useCompression);
1168  }
1169  }
1170 
1171 
1172  //--------------------------------------------------------------------
1173  inline void XRayRenderer::printCumulatedLBuffer(const char* aFileName, bool useCompression)
1174  //--------------------------------------------------------------------
1175  {
1176  //print2DTexture(XRAY_DETECTOR_LBUFFER_TEXTURE_NAME_ID, aFileName);
1177  printFBO(XRAY_DETECTOR_CUMULATED_LBUFFERS_FBO_ID, aFileName, useCompression);
1178  }
1179 
1180 
1181  //------------------------------------------------------------
1182  inline void XRayRenderer::printSumMuxDx(const char* aFileName, bool useCompression)
1183  //------------------------------------------------------------
1184  {
1185  //print2DTexture(XRAY_DETECTOR_SUM_MUx_Dx_TEXTURE_NAME_ID, aFileName);
1186  printFBO(XRAY_DETECTOR_SUM_MUx_Dx_FBO_ID, aFileName, useCompression);
1187  }
1188 
1189 
1190  //-----------------------------------------------------------------
1191  inline void XRayRenderer::printEnergyFluence(const char* aFileName, bool useCompression)
1192  //-----------------------------------------------------------------
1193  {
1194  //print2DTexture(XRAY_DETECTOR_ENERGY_FLUENCE_TEXTURE_NAME_ID, aFileName);
1195  printFBO(XRAY_DETECTOR_ENERGY_FLUENCE_FBO_ID, aFileName, useCompression);
1196  }
1197 
1198 
1199  //-------------------------------------------------------------
1200  inline void XRayRenderer::printXRayImage(const char* aFileName, bool useCompression)
1201  //-------------------------------------------------------------
1202  {
1203  //print2DTexture(XRAY_DETECTOR_ENERGY_FLUENCE_TEXTURE_NAME_ID, aFileName);
1204  printFBO(XRAY_DETECTOR_ENERGY_FLUENCE_FBO_ID, aFileName, useCompression);
1205  }
1206 
1207 /*
1208  //------------------------------------------------
1209  inline RATIONAL_NUMBER* XRayRenderer::getLBuffer()
1210  //------------------------------------------------
1211  {
1212  if (m_use_l_buffer_artefact_filtering)
1213  {
1214  //return (get2DTexture(XRAY_DETECTOR_CLEANED_LBUFFER_TEXTURE_NAME_ID));
1215  return (getFBO(XRAY_DETECTOR_CLEANED_LBUFFER_FBO_ID));
1216  }
1217  else
1218  {
1219  //return (get2DTexture(XRAY_DETECTOR_UNCLEANED_LBUFFER_TEXTURE_NAME_ID));
1220  return (getFBO(XRAY_DETECTOR_UNCLEANED_LBUFFER_FBO_ID));
1221  }
1222  }
1223 
1224 
1225  //---------------------------------------------------------
1226  inline RATIONAL_NUMBER* XRayRenderer::getCumulatedLBuffer()
1227  //---------------------------------------------------------
1228  {
1229  //return (get2DTexture(XRAY_DETECTOR_LBUFFER_TEXTURE_NAME_ID));
1230  return (getFBO(XRAY_DETECTOR_CUMULATED_LBUFFERS_FBO_ID));
1231  }
1232 
1233 
1234  //-------------------------------------------------
1235  inline RATIONAL_NUMBER* XRayRenderer::getSumMuxDx()
1236  //-------------------------------------------------
1237  {
1238  //return (get2DTexture(XRAY_DETECTOR_SUM_MUx_Dx_TEXTURE_NAME_ID));
1239  return (getFBO(XRAY_DETECTOR_SUM_MUx_Dx_FBO_ID));
1240  }
1241 
1242 
1243  //------------------------------------------------------
1244  inline RATIONAL_NUMBER* XRayRenderer::getEnergyFluence()
1245  //------------------------------------------------------
1246  {
1247  //return (get2DTexture(XRAY_DETECTOR_ENERGY_FLUENCE_TEXTURE_NAME_ID));
1248  return (getFBO(XRAY_DETECTOR_ENERGY_FLUENCE_FBO_ID));
1249  }
1250 
1251 
1252  //--------------------------------------------------
1253  inline RATIONAL_NUMBER* XRayRenderer::getXRayImage()
1254  //--------------------------------------------------
1255  {
1256  //return (get2DTexture(XRAY_DETECTOR_ENERGY_FLUENCE_TEXTURE_NAME_ID));
1257  return (getFBO(XRAY_DETECTOR_ENERGY_FLUENCE_FBO_ID));
1258  }
1259 */
1260 
1261  //----------------------------------------
1263  //----------------------------------------
1264  {
1266  {
1268  }
1269  else
1270  {
1272  }
1273  }
1274 
1275 
1276  //----------------------------------------------
1278  //----------------------------------------------
1279  {
1281  }
1282 
1283 
1284  //------------------------------------------
1286  //------------------------------------------
1287  {
1289  }
1290 
1291  //-------------------------------------------------------
1292  inline const XRayBeam* XRayRenderer::getXRayBeam( ) const
1293  //-------------------------------------------------------
1294  {
1295  return m_p_xray_beam;
1296  }
1297 
1298 
1299  //------------------------------------------------------------------------
1300  inline const std::vector<VEC3>& XRayRenderer::getSourcePositionSet() const
1301  //------------------------------------------------------------------------
1302  {
1303  return m_source_positions_set;
1304  }
1305 
1306 
1307  //--------------------------------------------------------------------------
1308  inline const std::vector<VEC3>& XRayRenderer::getDetectorPositionSet() const
1309  //--------------------------------------------------------------------------
1310  {
1311  return m_detector_positions_set;
1312  }
1313 
1314 
1315  //-----------------------------------------------------------------------------
1316  inline const std::vector<VEC3>& XRayRenderer::getDetectorRightVectorSet() const
1317  //-----------------------------------------------------------------------------
1318  {
1320  }
1321 
1322 
1323  //--------------------------------------------------------------------------
1324  inline const std::vector<VEC3>& XRayRenderer::getDetectorUpVectorSet() const
1325  //--------------------------------------------------------------------------
1326  {
1327  return m_detector_up_vector_set;
1328  }
1329 
1330 
1331 } // namespace gVirtualXRay
unsigned int getNumberOfProjectionsCT() const
RATIONAL_NUMBER applyEnergyResponse(const RATIONAL_NUMBER &anEnergy) const
Apply the energy response if any.
bool useParallelBeam() const
Accessor on the flag about projection.
#define XRAY_DETECTOR_UNCLEANED_LBUFFER_FBO_ID
void printEnergyFluence(const char *aFileName, bool useCompression=false)
Save the current energy fluence into a file (same as printXRayImage()).
void enableArtifactFilteringOnGPU()
Enable artefact filtering on GPU.
Sinogram< PixelType > m_sinogram_image
Sinogram.
void usePoissonNoise(bool aFlag)
Enable or disable Poisson noise for the energy fluence.
Definition: XRayBeam.inl:314
void disableArtefactFilteringOnCPU()
Disable artefact filtering on CPU.
unsigned int getNumberOfOuterSurfaces() const
void removeInnerSurfaces()
Remove the external surface from the renderer if any.
std::vector< VEC3 > m_source_positions_set
void addInnerSurface(const SceneGraphNode *apSurface)
Add a 3D object to be rendered. It will be used as an internal surface.
const std::vector< RATIONAL_NUMBER > & getAngleSetCT() const
void resetSumMuxDx()
Reset the Mu_x * D_x FBO to 0.
bool getNegativeFilteringFlag() const
Accessor on the flag control the display of the final in negative.
XRayBeam is a class to handle the X-Ray beam. The beam spectrum is discretised into energy channels...
Definition: XRayBeam.h:108
RATIONAL_NUMBER getPhotonEnergy() const
Accessor on the energy of photons.
const std::vector< VEC3 > & getDetectorPositionSet() const
const Sinogram< XRayRenderer::PixelType > & getSinogram() const
const Image< XRayRenderer::PixelType > & getCumulatedLBuffer() const
Image< T > convolution1D(const std::vector< float > &aKernel) const
Definition: Image.inl:1360
static RATIONAL_NUMBER getMuFromHUAndMuWater(const RATIONAL_NUMBER &HU, const RATIONAL_NUMBER &mu_water)
Convert a Hounsfield value into a linear attenuation coefficient ( ).
const std::vector< VEC3 > & getDetectorUpVectorSet() const
#define XRAY_DETECTOR_CLEANED_LBUFFER_FBO_ID
void reset2DBuffer(unsigned int aFrameBuffer)
Reset the value of a FBO to 0.
bool isInnerSurface(const SceneGraphNode *apNode)
Check if a given PolygonMesh is an inner surface.
XRayRenderer is a class to compute and renderer X-ray images on GPU.
Definition: XRayRenderer.h:176
Computation using OpenGL.
Definition: XRayRenderer.h:189
void printSumMuxDx(const char *aFileName, bool useCompression=false)
Save the current Mux Dx into a file.
RATIONAL_NUMBER getLastAngleCT() const
Accessor on the last angle of the CT scan acquisition simulation.
const PixelType * getSinogramRawData() const
std::vector< VEC3 > m_detector_up_vector_set
unsigned int m_zbuffer_texture_id
void printMuWaterTable(std::ostream &anOutputStream)
Output the talbe of attenuation coefficients of water into a data stream.
bool m_use_l_buffer_artefact_filtering_on_gpu
Flag set to true to use L-buffer artefact filtering.
RATIONAL_NUMBER m_CT_last_angle
RATIONAL_NUMBER getElementMassAttenuation(const char *anElementSymbol, const RATIONAL_NUMBER &anEnergy)
Get the mass attenuation coefficient ( ) of a chemical element.
RATIONAL_NUMBER PixelType
Pixel type.
Definition: XRayRenderer.h:181
bool useArtefactFilteringOnGPU() const
void printCumulatedLBuffer(const char *aFileName, bool useCompression=false)
Save the current cumulated L-buffer into a file.
bool m_energy_fluence_empty
Flag use for lazy evaluation and blending of the energy fluence.
void addPoissonNoise(Image< PixelType > &anImage)
Use the number of photons to add the Poisson noise.
#define XRAY_DETECTOR_UNCLEANED_LBUFFER_TEXTURE_NAME_ID
bool useArtifactFilteringOnGPU() const
RATIONAL_NUMBER m_max_value_in_simulated_xray_image
Max value in simulated X-ray image.
Class to manage a table of elements in material.
#define XRAY_DETECTOR_ENERGY_FLUENCE_TEXTURE_NAME_ID
void print2DTexture(unsigned int aTextureID, const char *aFileName, bool useCompression=false)
Save a texture into a file.
void printFBO(unsigned int aFBOID, const char *aFileName, bool useCompression=false)
Save a FBO into a file.
Exception is a class to handle exceptions.
Definition: Exception.h:109
void printProjectionSet(const char *aFileName, bool useCompression=false)
#define XRAY_DETECTOR_2D_TEXTURE_NUMBER
The total number of 2D textures.
Definition: XRayRenderer.h:152
Sinogram is a class to reconstruct images from a sinogram.
Definition: Image.h:94
bool getIncludeLastAngleFlagCT() const
#define XRAY_DETECTOR_CLEANED_LBUFFER_TEXTURE_NAME_ID
static RATIONAL_NUMBER getElementMu(const char *anElementSymbol, const RATIONAL_NUMBER &anEnergy)
Get the linear attenuation coefficient ( ) of a chemical element.
#define XRAY_DETECTOR_SUM_MUx_Dx_FBO_ID
unsigned int getNumberOfInnerSurfaces() const
const std::vector< RATIONAL_NUMBER > & getLSF() const
Accessor on the line spread function.
void printXRayImage(const char *aFileName, bool useCompression=false)
bool useArtefactFilteringOnCPU() const
void enableArtefactFilteringOnGPU()
Enable artefact filtering on GPU.
void useNegativeFilteringFlag(bool aFlag=true)
Display the final image in negative or not.
Class to manage a table of materials.
Image< PixelType > m_projection_set
Projection set.
unsigned int m_CT_white_images_in_flat_field
RATIONAL_NUMBER getMinPixelValue() const
RATIONAL_NUMBER getMaxPixelValue() const
RATIONAL_NUMBER getTotalEnergyWithDetectorResponse() const
Accessor on a total energy of the beam when the detector response is applied.
Image< PixelType > m_cumulated_lbuffer_image
Cumulated L-buffer for all the inner surfaces.
T * getRawData()
Accessor on the raw data.
Definition: Image.inl:717
void save(const char *aFileName, bool anInvertLUTFlag=false, const char *aComment="", bool useDeflateCompressionIfPossible=false) const
Save the image in a file.
Definition: Image.inl:2432
ComputingMode m_computing_mode
The computing mode (OPENGL, CUDA, or OPENCL)
void disableArtefactFilteringOnGPU()
Disable artefact filtering on GPU.
void enableArtifactFilteringOnCPU()
Enable artefact filtering on CPU.
static ElementSet & getInstance()
Computation using CUDA.
Definition: XRayRenderer.h:191
const Vec2ui & getNumberOfPixels() const
Accessor on the number of pixels.
std::vector< RATIONAL_NUMBER > m_CT_angle_set
PolygonMesh is a class to handle polygon (triangles) meshes.
Definition: PolygonMesh.h:114
Image< PixelType > m_energy_fluence_image
Energy fluence.
Image< XRayRenderer::PixelType > & getEnergyFluence()
Image is a class to manage a greyscale image.
Definition: Image.h:92
unsigned int m_negative_display_flag
Flag to display the result in negative or not.
void removeOuterSurface()
Remove the internal surfaces from the renderer if any.
unsigned int getMaxRadiusLbufferArtefactFilter() const
Accessor on the max radius of the L-buffer artefact correction filter.
const PixelType * getLBufferRawData()
void displayEnergyFluence()
Display the energy fluence using OpenGL (same as displayXRayImage()).
float RATIONAL_NUMBER
Type of data used to store real numbers.
Definition: Types.h:107
void deletePBO(unsigned int &aPBO)
Delete a PBO.
unsigned int getHeight() const
Number of pixels along the vertical axis.
Definition: Image.inl:792
bool useArtifactFilteringOnCPU() const
std::string m_CT_screenshot_output_path
const std::vector< VEC3 > & getDetectorRightVectorSet() const
const PixelType * getProjectionSetRawData()
static MaterialSet & getInstance()
void disableArtifactFilteringOnCPU()
Disable artefact filtering on CPU.
RATIONAL_NUMBER m_min_value_in_simulated_xray_image
Min value in simulated X-ray image.
Vec3< RATIONAL_NUMBER > VEC3
Type of data used to store 3D vectors.
Definition: Types.h:115
void pushTexture2D()
Add the current 2D texture binding to the texture stack.
RATIONAL_NUMBER getFirstAngleCT() const
Accessor on the first angle of the CT scan acquisition simulation.
const VEC3 & getCentreOfRotationPositionCT() const
unsigned int m_max_radius_Lbuffer_artefact_filter
Max radius of L-buffer artefact filter.
Image< T > convolution2D(const Image< float > &aKernel) const
Definition: Image.inl:1396
bool isOuterSurface(const SceneGraphNode *apNode)
Check if a given PolygonMesh is an outer surface.
void displayLBuffer()
Display the L-buffer using OpenGL.
Some utility functions about OpenGL. Now supports GLSL450 and OpenGL 4.5.
void displayInnerSurface(unsigned int anIndex) const
Some utility functions that do not fit anywhere else.
#define XRAY_DETECTOR_CUMULATED_LBUFFERS_FBO_ID
void addOuterSurface(const SceneGraphNode *apSurface)
Add a 3D object to be rendered. It will be used as an external surface.
const Image< XRayRenderer::PixelType > & getLBuffer() const
const std::string & getProjectionOutputPathCT() const
RATIONAL_NUMBER getPhotonNumber() const
Accessor on the number of photons in the bin.
XRayDetector * m_p_detector
The X-ray detector.
void initialisePBOs()
Initialise the PBOs.
std::vector< VEC3 > m_detector_right_vector_set
Computation on CPU using OpenMP.
Definition: XRayRenderer.h:193
RATIONAL_NUMBER m_CT_first_angle
const std::string & getScreenshotOutputPathCT() const
unsigned int getWidth() const
Number of pixels along the horizontal axis.
Definition: Image.inl:784
static double getDensity(short aHounsfieldValue)
Get the density for a given material (in HU).
const SpectrumRecord & getEnergyChannel(unsigned int anID)
Accessor on a given energy bin.
Definition: XRayBeam.inl:230
static RATIONAL_NUMBER getMuFromHU(const RATIONAL_NUMBER &HU, const RATIONAL_NUMBER &anEnergy)
Convert a Hounsfield value into a linear attenuation coefficient ( ).
void createPBO(unsigned int &aPBO)
Create a PBO.
const XRayBeam * getXRayBeam() const
Returns the actual Beam.
unsigned int getOptimalNumberOfProjectionsCT() const
SceneGraphNode * m_p_outer_surface
The 3D geometry that will wrap the ones in m_p_inner_surface_set.
unsigned int getNumberOfSourceSamples() const
std::vector< unsigned int > m_p_texture_name_set
Set of textures.
void display2DTexture(unsigned int aTextureID)
Display a 2D texture using OpenGL.
Image< PixelType > m_l_buffer_image
L-buffer.
const Image< RATIONAL_NUMBER > & getPSF() const
Accessor on the point spread function.
const VEC3 & getRotationAxisCT() const
void setMaxRadiusLbufferArtefactFilter(unsigned int aRadius)
Set the max radius of the L-buffer artefact correction filter.
void create2DTexture(unsigned int *apTextureID, int anInternalTextureFormat, int aType)
Create a 2D texture.
std::vector< SceneGraphNode * > m_p_inner_surface_set
Set of 3D geometries.
#define XRAY_DETECTOR_ENERGY_FLUENCE_FBO_ID
std::ostream & logError(const std::string &aMessage="")
static RATIONAL_NUMBER getMassAttenuationFromHU(const RATIONAL_NUMBER &HU, const RATIONAL_NUMBER &anEnergy)
Convert a Hounsfield value into a mass attenuation coefficient ( ).
const double Pi
Pi.
void disableArtifactFilteringOnGPU()
Disable artefact filtering on GPU.
unsigned int getEnergyChannelNumber()
Accessor on the number of bins in the spectrum.
Definition: XRayBeam.inl:220
void init2DTextures(int anInternalTextureFormat)
Initialise the 2D textures.
Computation using OpenCL.
Definition: XRayRenderer.h:192
static std::vector< AttenuationCoefficient > m_mu_water_set
The table of water energy fluence coefficients.
std::string m_CT_projection_output_path
void resetEnergyFluence()
Reset the energy fluence FBO to 0.
XRayBeam * m_p_xray_beam
The X-ray beam.
std::vector< SceneGraphNode * > m_p_internal_data_storage
RATIONAL_NUMBER * getFBO(unsigned int aFBOID)
Accessor on the raw data from a FBO.
void printLBuffer(const char *aFileName, bool useCompression=false)
Save the current L-buffer into a file.
const Image< XRayRenderer::PixelType > & getProjectionSet() const
unsigned int getWhiteImagesInFlatFieldCT() const
RATIONAL_NUMBER getElementDensity(const char *anElementSymbol)
Get the density ( ) of a chemical element.
static RATIONAL_NUMBER getDensityFromHU(const RATIONAL_NUMBER &HU)
Get the density ( ) of a tissue given a Hounsfield value.
void printSinogram(const char *aFileName, bool useCompression=false)
void popTexture()
void enableArtefactFilteringOnCPU()
Enable artefact filtering on CPU.
const std::vector< VEC3 > & getSourcePositionSet() const
std::vector< VEC3 > m_detector_positions_set
const VEC2 & getPixelSpacingInUnitOfLength() const
Accessor on the pixel spacing (in unit of length).