gVirtualXRay  2.0.10
VirtualX-RayImagingLibraryonGPU
XRayBeam.inl
Go to the documentation of this file.
1 /*
2 
3 Copyright (c) 2014, Dr Franck P. Vidal (franck.p.vidal@fpvidal.net),
4 http://www.fpvidal.net/
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation and/or
15 other materials provided with the distribution.
16 
17 3. Neither the name of the Bangor University nor the names of its contributors
18 may be used to endorse or promote products derived from this software without
19 specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 
32 */
33 
34 
63 //******************************************************************************
64 // Include
65 //******************************************************************************
66 #include <fstream>
67 #include <sstream>
68 #include <cfloat>
69 #include <algorithm>
70 
71 #ifndef __ElementSet_h
73 #endif
74 
75 #ifndef __FileDoesNotExistException_h
77 #endif
78 
79 #ifndef __OutOfBoundsException_h
81 #endif
82 
83 #ifndef __Logger_h
84 #include <gVirtualXRay/Logger.h>
85 #endif
86 
87 #ifndef __PythonSingleton_h
89 #endif
90 
91 
92 //******************************************************************************
93 // definitions
94 //******************************************************************************
95 #undef USE_PYTHON
96 
97 
98 //******************************************************************************
99 // namespace
100 //******************************************************************************
101 namespace gVirtualXRay {
102 
103 
104 //-------------------------------------------------
106 //-------------------------------------------------
107  m_bin_total_energy_lower_threshold(1 * eV),
108  m_use_poisson_noise(false),
109  m_number_of_photons_per_pixel(0),
110  m_voltage(-1),
111  m_tube_angle_in_degrees(12),
112  m_mAs(-1),
113  m_use_spekpy(false),
114  m_use_xpecgen(false),
115  m_need_to_update_tube_spectrum(false)
116 //-------------------------------------------------
117 {
118  useSpekpy();
119 }
120 
121 
122 //--------------------------
124 //--------------------------
125 {
126  clear();
127 }
128 
129 
130 //---------------------------
131 inline void XRayBeam::clear()
132 //---------------------------
133 {
134  // Remove all the energy channels
136 
137  m_voltage = -1;
139  m_mAs = -1;
140 
141  m_filtration.clear();
143 }
144 
145 
146 //---------------------------------------
148 //---------------------------------------
149 {
150  // Remove all the energy channels
151  m_beam_spectrum.clear();
153  m_photon_count_bands.clear();
155 
157 }
158 
159 
160 //-----------------------------------------------------------------------
161 inline bool XRayBeam::addChannel(const RATIONAL_NUMBER& aNumberOfPhotons,
162  const RATIONAL_NUMBER& anIncidentEnergy)
163 //-----------------------------------------------------------------------
164 {
165  // Temporary structure
166  SpectrumRecord temp;
167 
168  // Store the number of photons
169  temp.m_photon_number = aNumberOfPhotons;
170 
171  // Store the energy
172  temp.m_energy = anIncidentEnergy;
173 
174  // The tube voltage is not used
176 
177  // The total energy of the bin is above the cut-off threshold
179  {
180  // Store the data
181  m_beam_spectrum.push_back(temp);
182 
183  // Add the number of photons
184  m_number_of_photons_per_pixel += aNumberOfPhotons;
185 
186  // Sort the spectrum
187  sort();
188 
189  return true;
190  }
191 
192  return false;
193 }
194 
195 
196 //-----------------------------------------------------------------------
197 inline void XRayBeam::initialise(const RATIONAL_NUMBER& anIncidentEnergy)
198 //-----------------------------------------------------------------------
199 {
200  // Empty the current beam spectrum
201  m_beam_spectrum.clear();
202 
203  // Add the record
204  m_beam_spectrum.push_back(SpectrumRecord(1, anIncidentEnergy));
206 
208 }
209 
210 
211 //------------------------------------------------------------------------------
213 //------------------------------------------------------------------------------
214 {
216 }
217 
218 
219 //----------------------------------------------------
220 inline unsigned int XRayBeam::getEnergyChannelNumber()
221 //----------------------------------------------------
222 {
224 
225  return (m_beam_spectrum.size());
226 }
227 
228 
229 //------------------------------------------------------------------------
230 inline const SpectrumRecord& XRayBeam::getEnergyChannel(unsigned int anID)
231 //------------------------------------------------------------------------
232 {
234 
235  if (anID >= getEnergyChannelNumber())
236  {
237  throw OutOfBoundsException(__FILE__, __FUNCTION__, __LINE__);
238  }
239 
240  return (m_beam_spectrum[anID]);
241 }
242 
243 
244 //-----------------------------------------------
246 //-----------------------------------------------
247 {
249 
250  // Compute the total incident energy
251  RATIONAL_NUMBER total_energy(0);
252  for (std::vector<SpectrumRecord>::const_iterator ite_beam_spectrum(m_beam_spectrum.begin());
253  ite_beam_spectrum != m_beam_spectrum.end();
254  ++ite_beam_spectrum)
255  {
256  total_energy += ite_beam_spectrum->m_energy * ite_beam_spectrum->m_photon_number;
257  }
258 
259  return (total_energy);
260 }
261 
262 
263 //----------------------------------------
265 //----------------------------------------
266 {
267  m_use_poisson_noise = true;
268 }
269 
270 
271 //-----------------------------------------
273 //-----------------------------------------
274 {
275  m_use_poisson_noise = false;
276 }
277 
278 
279 //------------------------------------------------------------------------
280 inline void XRayBeam::setNumberOfPhotons(RATIONAL_NUMBER aNumberOfPhotons)
281 //------------------------------------------------------------------------
282 {
283  // Update m_number_of_photons_per_pixel if needed
285 
286  // Change its value
287  RATIONAL_NUMBER backup_number_of_photons = m_number_of_photons_per_pixel;
288  m_number_of_photons_per_pixel = aNumberOfPhotons;
289 
290  // Compute a scaling factor
291  RATIONAL_NUMBER old_to_new = m_number_of_photons_per_pixel / backup_number_of_photons;
292 
293  // Apply this scaling factor on all the bins
294  for (std::vector<SpectrumRecord>::iterator ite_beam_spectrum(m_beam_spectrum.begin());
295  ite_beam_spectrum != m_beam_spectrum.end();
296  ++ite_beam_spectrum)
297  {
298  ite_beam_spectrum->m_photon_number *= old_to_new;
299  }
300 }
301 
302 
303 //---------------------------------------------------
305 //---------------------------------------------------
306 {
308 
310 }
311 
312 
313 //-----------------------------------------------
314 inline void XRayBeam::usePoissonNoise(bool aFlag)
315 //-----------------------------------------------
316 {
317  m_use_poisson_noise = aFlag;
318 }
319 
320 
321 //-------------------------------------------
322 inline bool XRayBeam::usePoissonNoise() const
323 //-------------------------------------------
324 {
325  return (m_use_poisson_noise);
326 }
327 
328 
329 //--------------------------
330 inline void XRayBeam::sort()
331 //--------------------------
332 {
333  std::sort(m_beam_spectrum.begin(), m_beam_spectrum.end());
334 }
335 
336 
337 //------------------------------------------------------------
339 //------------------------------------------------------------
340 {
342 
344 }
345 
346 
347 //------------------------------------------------------------------
348 inline void XRayBeam::activatePhotonCountingBand(unsigned int aBand)
349 //------------------------------------------------------------------
350 {
352 
353  // The functionality is in use
355  {
356  // aBand is valid
357  if (aBand > getNumberOfPhotonCountingBands())
358  {
359  throw OutOfBoundsException(__FILE__, __FUNCTION__, __LINE__);
360  }
361 
362  // Replace the current spectrum with the corresponding band
364 
365  // Update the total number of photons in the band
367  for (std::vector<SpectrumRecord>::const_iterator ite_beam_spectrum(m_beam_spectrum.begin());
368  ite_beam_spectrum != m_beam_spectrum.end();
369  ++ite_beam_spectrum)
370  {
371  m_number_of_photons_per_pixel += ite_beam_spectrum->m_photon_number;
372  }
373  }
374 }
375 
376 
377 
378 //---------------------------------------------------------------------------
379 inline const std::vector<RATIONAL_NUMBER>& XRayBeam::getPhotonCountingBands()
380 //---------------------------------------------------------------------------
381 {
383 
384  return m_photon_count_bands;
385 }
386 
387 
388 //---------------------------------------------------------------
389 inline void XRayBeam::setVoltage(const RATIONAL_NUMBER& aVoltage)
390 //---------------------------------------------------------------
391 {
392  m_voltage = aVoltage;
394 
395 #ifdef USE_PYTHON
396 #ifndef HAS_PythonLibs
397  LOGGER.logWarning("PythonLibs support was disabled when the library was compiled. This function ") <<
398  __FUNCTION__ << " in " << __FILE__ << " may have no visible effect." << std::endl;
399 #endif
400 #endif
401 }
402 
403 
404 //-------------------------------------------------
406 //-------------------------------------------------
407 {
408  return m_voltage;
409 }
410 
411 
412 //---------------------------------------------------------
413 inline void XRayBeam::setmAs(const RATIONAL_NUMBER& an_mAs)
414 //---------------------------------------------------------
415 {
416  m_mAs = an_mAs;
418 
419 #ifdef USE_PYTHON
420 #ifndef HAS_PythonLibs
421  LOGGER.logWarning("PythonLibs support was disabled when the library was compiled. This function ") <<
422  __FUNCTION__ << " in " << __FILE__ << " may have no visible effect." << std::endl;
423 #endif
424 #endif
425 }
426 
427 
428 //---------------------------------------------
430 //---------------------------------------------
431 {
432  return m_mAs;
433 }
434 
435 
436 //----------------------------------------------------------------
437 inline void XRayBeam::setTubeAngle(const RATIONAL_NUMBER& anAngle)
438 //----------------------------------------------------------------
439 {
442 
443 #ifdef USE_PYTHON
444 #ifndef HAS_PythonLibs
445  LOGGER.logWarning("PythonLibs support was disabled when the library was compiled. This function ") <<
446  __FUNCTION__ << " in " << __FILE__ << " may have no visible effect." << std::endl;
447 #endif
448 #endif
449 }
450 
451 
452 //---------------------------------------------------
454 //---------------------------------------------------
455 {
457 }
458 
459 
460 //-------------------------------------
462 //-------------------------------------
463 {
464  m_filtration.clear();
466 
467 #ifdef USE_PYTHON
468 #ifndef HAS_PythonLibs
469  LOGGER.logWarning("PythonLibs support was disabled when the library was compiled. This function ") <<
470  __FUNCTION__ << " in " << __FILE__ << " may have no visible effect." << std::endl;
471 #endif
472 #endif
473 }
474 
475 
476 //--------------------------------------------------------------------------------------------------------------
477 inline void XRayBeam::setFiltration(const std::vector<std::pair<unsigned int, RATIONAL_NUMBER> >& aSetOfFilters)
478 //--------------------------------------------------------------------------------------------------------------
479 {
480  m_filtration = aSetOfFilters;
482 
483 #ifdef USE_PYTHON
484 #ifndef HAS_PythonLibs
485  LOGGER.logWarning("PythonLibs support was disabled when the library was compiled. This function ") <<
486  __FUNCTION__ << " in " << __FILE__ << " may have no visible effect." << std::endl;
487 #endif
488 #endif
489 }
490 
491 
492 //-----------------------------------------------------------
493 inline void XRayBeam::addFilter(const std::string& aMaterial,
494  const double& aThickness)
495 //-----------------------------------------------------------
496 {
497  m_filtration.push_back(
498  std::pair<unsigned int, RATIONAL_NUMBER>(
499  ElementSet::getInstance().getElement(aMaterial).getZ(),
500  aThickness
501  )
502  );
504 
505 #ifdef USE_PYTHON
506 #ifndef HAS_PythonLibs
507  LOGGER.logWarning("PythonLibs support was disabled when the library was compiled. This function ") <<
508  __FUNCTION__ << " in " << __FILE__ << " may have no visible effect." << std::endl;
509 #endif
510 #endif
511 }
512 
513 
514 //-------------------------------------------------------
515 inline void XRayBeam::addFilter(unsigned int aMaterial,
516  const double& aThickness)
517 //-------------------------------------------------------
518 {
519  m_filtration.push_back(std::pair<unsigned int, RATIONAL_NUMBER>(aMaterial, aThickness));
521 
522 #ifdef USE_PYTHON
523 #ifndef HAS_PythonLibs
524  LOGGER.logWarning("PythonLibs support was disabled when the library was compiled. This function ") <<
525  __FUNCTION__ << " in " << __FILE__ << " may have no visible effect." << std::endl;
526 #endif
527 #endif
528 }
529 
530 
531 //--------------------------------------------------------------------------------------------------
532 inline const std::vector<std::pair<unsigned int, RATIONAL_NUMBER> >& XRayBeam::getFiltration() const
533 //--------------------------------------------------------------------------------------------------
534 {
535  return m_filtration;
536 }
537 
538 
539 //-------------------------------
540 inline bool XRayBeam::hasSpekpy()
541 //-------------------------------
542 {
544 }
545 
546 
547 //--------------------------------
548 inline bool XRayBeam::hasXpecgen()
549 //--------------------------------
550 {
552 }
553 
554 
555 //-------------------------------
556 inline void XRayBeam::useSpekpy()
557 //-------------------------------
558 {
559 #ifdef USE_PYTHON
560  if (!m_use_spekpy)
561  {
563  {
564  LOGGER.logNow("Use Spekpy to generate beam spectrums from tube voltages.") << std::endl;
565  m_use_spekpy = true;
566  m_use_xpecgen = false;
568  }
569  else
570  {
571  LOGGER.logWarning("Spekpy is not installed, try Xpecgen instead.") << std::endl;
572  m_use_spekpy = false;
573 
575  {
576  if (!m_use_xpecgen)
577  {
578  LOGGER.logNow("Use Xpecgen to generate beam spectrums from tube voltages.") << std::endl;
579  m_use_xpecgen = true;
581  }
582  }
583  else
584  {
585  LOGGER.logWarning("Xpecgen is not installed either.") << std::endl;
586  m_use_xpecgen = false;
587  }
588  }
589  }
590 #endif
591 }
592 
593 
594 //--------------------------------
595 inline void XRayBeam::useXpecgen()
596 //--------------------------------
597 {
598 #ifdef USE_PYTHON
599  if (!m_use_xpecgen)
600  {
602  {
603  LOGGER.logNow("Use Xpecgen to generate beam spectrums from tube voltages.") << std::endl;
604  m_use_xpecgen = true;
605  m_use_spekpy = false;
607  }
608  else
609  {
610  LOGGER.logWarning("Xpecgen is not installed, try Spekpy instead.") << std::endl;
611  m_use_xpecgen = false;
612 
614  {
615  if (!m_use_spekpy)
616  {
617  LOGGER.logNow("Use Spekpy to generate beam spectrums from tube voltages.") << std::endl;
618  m_use_spekpy = true;
620  }
621  }
622  else
623  {
624  LOGGER.logWarning("Spekpy is not installed either.") << std::endl;
625  m_use_spekpy = false;
626  }
627  }
628  }
629 #endif
630 }
631 
632 
633 //---------------------------------------
634 inline bool XRayBeam::usingSpekpy() const
635 //---------------------------------------
636 {
637  return m_use_spekpy;
638 }
639 
640 
641 //----------------------------------------
642 inline bool XRayBeam::usingXpecgen() const
643 //----------------------------------------
644 {
645  return m_use_xpecgen;
646 }
647 
648 
649 
650 } // namespace gVirtualXRay
RATIONAL_NUMBER getVoltage() const
Definition: XRayBeam.inl:405
void setTubeAngle(const RATIONAL_NUMBER &anAngle)
Definition: XRayBeam.inl:437
unsigned int getNumberOfPhotonCountingBands()
Definition: XRayBeam.inl:338
RATIONAL_NUMBER getNumberOfPhotons()
Accessor on the total number of photons per pixel when Poisson noise is enable.
Definition: XRayBeam.inl:304
std::vector< std::pair< unsigned int, RATIONAL_NUMBER > > m_filtration
Definition: XRayBeam.h:328
RATIONAL_NUMBER m_number_of_photons_per_pixel
Definition: XRayBeam.h:319
~XRayBeam()
Destructor.
Definition: XRayBeam.inl:123
const std::vector< std::pair< unsigned int, RATIONAL_NUMBER > > & getFiltration() const
Definition: XRayBeam.inl:532
SpectrumRecord is a class to handle a record of the X-Ray beam, i.e. an energy bin (number of photons...
void setmAs(const RATIONAL_NUMBER &an_mAs)
Definition: XRayBeam.inl:413
void setVoltage(const RATIONAL_NUMBER &aVoltage)
Definition: XRayBeam.inl:389
RATIONAL_NUMBER m_energy
The energy of the photons.
bool usingXpecgen() const
Definition: XRayBeam.inl:642
Singleton to handle the initialisation and release of Python.
bool usePoissonNoise() const
Check if Poisson noise for the energy fluence is enable or disable.
Definition: XRayBeam.inl:322
bool addChannel(const RATIONAL_NUMBER &aNumberOfPhotons, const RATIONAL_NUMBER &anIncidentEnergy)
Add an energy channel to the beam.
Definition: XRayBeam.inl:161
void enablePoissonNoise()
Enable Poisson noise for the energy fluence.
Definition: XRayBeam.inl:264
RATIONAL_NUMBER m_photon_number
The number of photons.
Class to manage a table of elements in material.
RATIONAL_NUMBER m_voltage
Definition: XRayBeam.h:325
void initialise(const char *aFileName, const RATIONAL_NUMBER &aUnit, unsigned int aMergeChannelFlag=1)
Initialise the X-ray beam specturm with a polychromatic spectrum.
void sort()
Sort the spectrum in ascending energy.
Definition: XRayBeam.inl:330
void addFilter(const std::string &aMaterial, const double &aThickness)
Definition: XRayBeam.inl:493
RATIONAL_NUMBER getmAs() const
Definition: XRayBeam.inl:429
Class to handle exceptions when trying to open a read-only file that is not accessible.
RATIONAL_NUMBER m_bin_total_energy_lower_threshold
Definition: XRayBeam.h:313
std::vector< RATIONAL_NUMBER > m_photon_count_bands
Definition: XRayBeam.h:323
void setNumberOfPhotons(RATIONAL_NUMBER aNumberOfPhotons)
Set the total number of photons per pixel when Poisson noise is enable.
Definition: XRayBeam.inl:280
RATIONAL_NUMBER getTubeAngle() const
Definition: XRayBeam.inl:453
static ElementSet & getInstance()
RATIONAL_NUMBER m_mAs
Definition: XRayBeam.h:327
std::vector< SpectrumRecord > m_beam_spectrum
Set of photon bins.
Definition: XRayBeam.h:308
float RATIONAL_NUMBER
Type of data used to store real numbers.
Definition: Types.h:107
const double eV
electronvolt
Definition: Units.h:134
void clear()
Remove all the energy channels from the beam and all its parameters.
Definition: XRayBeam.inl:131
std::ostream & logWarning(const std::string &aMessage="")
void clearSpectrumOnly()
Remove all the energy channels from the beam.
Definition: XRayBeam.inl:147
void disablePoissonNoise()
Disable Poisson noise for the energy fluence.
Definition: XRayBeam.inl:272
RATIONAL_NUMBER getTotalEnergy()
Accessor on a total energy of the beam.
Definition: XRayBeam.inl:245
const std::vector< RATIONAL_NUMBER > & getPhotonCountingBands()
Definition: XRayBeam.inl:379
XRayBeam()
Default constructor.
Definition: XRayBeam.inl:105
std::ostream & logNow(const std::string &aMessage="")
static PythonSingleton & getInstance()
const SpectrumRecord & getEnergyChannel(unsigned int anID)
Accessor on a given energy bin.
Definition: XRayBeam.inl:230
void setFiltration(const std::vector< std::pair< unsigned int, RATIONAL_NUMBER > > &aSetOfFilters)
Definition: XRayBeam.inl:477
void activatePhotonCountingBand(unsigned int aBand)
Definition: XRayBeam.inl:348
Class to handle exceptions when accessing an array cell that is not accessible, i.e. out of bounds memory access.
unsigned int getEnergyChannelNumber()
Accessor on the number of bins in the spectrum.
Definition: XRayBeam.inl:220
void setBinTotalEnergyCutoff(const RATIONAL_NUMBER &aThreshold)
Set a threshold to discard energy bins with a tiny amount of energy.
Definition: XRayBeam.inl:212
bool m_need_to_update_tube_spectrum
Definition: XRayBeam.h:331
RATIONAL_NUMBER m_tube_angle_in_degrees
Definition: XRayBeam.h:326
bool usingSpekpy() const
Definition: XRayBeam.inl:634
std::vector< std::vector< SpectrumRecord > > m_beam_spectrum_for_photon_count_detector
Set of photon bins.
Definition: XRayBeam.h:322