GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GModelSpectralBins.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GModelSpectralBins.cpp - Spectral bins model class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2021 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GModelSpectralBins.cpp
23  * @brief Spectral bins model class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cmath>
32 #include "GException.hpp"
33 #include "GTools.hpp"
34 #include "GRan.hpp"
35 #include "GEbounds.hpp"
36 #include "GModelSpectralBins.hpp"
38 
39 /* __ Constants __________________________________________________________ */
40 
41 /* __ Globals ____________________________________________________________ */
43 const GModelSpectralRegistry g_spectral_bins_registry(&g_spectral_bins_seed);
44 
45 /* __ Method name definitions ____________________________________________ */
46 #define G_FLUX "GModelSpectralBins::flux(GEnergy&, GEnergy&)"
47 #define G_EFLUX "GModelSpectralBins::eflux(GEnergy&, GEnergy&)"
48 #define G_MC "GModelSpectralBins::mc(GEnergy&, GEnergy&, GTime&, GRan&)"
49 #define G_READ "GModelSpectralBins::read(GXmlElement&)"
50 #define G_WRITE "GModelSpectralBins::write(GXmlElement&)"
51 #define G_APPEND "GModelSpectralBins::append(GEnergy&, GEnergy&, double&)"
52 #define G_INSERT "GModelSpectralBins::insert(int&, GEnergy&, GEnergy&, "\
53  "double&)"
54 #define G_REMOVE "GModelSpectralBins::remove(int&)"
55 #define G_EMIN_GET "GModelSpectralBins::emin(int&)"
56 #define G_EMAX_GET "GModelSpectralBins::emax(int&)"
57 #define G_EMIN_SET "GModelSpectralBins::emin(int&, GEnergy&)"
58 #define G_EMAX_SET "GModelSpectralBins::emax(int&, GEnergy&)"
59 #define G_INTENSITY_GET "GModelSpectralBins::intensity(int&)"
60 #define G_INTENSITY_SET "GModelSpectralBins::intensity(int&, double&)"
61 #define G_ERROR_GET "GModelSpectralBins::error(int&)"
62 
63 /* __ Macros _____________________________________________________________ */
64 
65 /* __ Coding definitions _________________________________________________ */
66 
67 /* __ Debug definitions __________________________________________________ */
68 
69 
70 /*==========================================================================
71  = =
72  = Constructors/destructors =
73  = =
74  ==========================================================================*/
75 
76 /***********************************************************************//**
77  * @brief Void constructor
78  *
79  * Constructs an empty spectral bin model.
80  ***************************************************************************/
82 {
83  // Initialise members
84  init_members();
85 
86  // Return
87  return;
88 }
89 
90 
91 /***********************************************************************//**
92  * @brief Spectral model constructor
93  *
94  * @param[in] model Spectral model.
95  * @param[in] ebounds Energy boundaries.
96  * @param[in] index Spectral index.
97  *
98  * Constructs a spectral bins model from any spectral model using the
99  * energy boundaries that are specified by @p ebounds. Within each spectral
100  * bin the intensity follows a power law with spectral index @p index.
101  ***************************************************************************/
103  const GEbounds& ebounds,
104  const double& index) :
106 {
107  // Initialise members
108  init_members();
109 
110  // Append bins for all energies
111  for (int i = 0; i < ebounds.size(); ++i) {
112  append(ebounds.emin(i), ebounds.emax(i), model.eval(ebounds.elogmean(i)));
113  }
114 
115  // Store index
116  this->index(index);
117 
118  // Return
119  return;
120 }
121 
122 
123 /***********************************************************************//**
124  * @brief XML constructor
125  *
126  * @param[in] xml XML element.
127  *
128  * Construct spectral bins model by extracting information from an XML
129  * element. See the read() method for more information about the expected
130  * structure of the XML element.
131  ***************************************************************************/
134 {
135  // Initialise members
136  init_members();
137 
138  // Read information from XML element
139  read(xml);
140 
141  // Return
142  return;
143 }
144 
145 
146 /***********************************************************************//**
147  * @brief Copy constructor
148  *
149  * @param[in] model Spectral bins model.
150  ***************************************************************************/
152  GModelSpectral(model)
153 {
154  // Initialise members
155  init_members();
156 
157  // Copy members
158  copy_members(model);
159 
160  // Return
161  return;
162 }
163 
164 
165 /***********************************************************************//**
166  * @brief Destructor
167  ***************************************************************************/
169 {
170  // Free members
171  free_members();
172 
173  // Return
174  return;
175 }
176 
177 
178 /*==========================================================================
179  = =
180  = Operators =
181  = =
182  ==========================================================================*/
183 
184 /***********************************************************************//**
185  * @brief Assignment operator
186  *
187  * @param[in] model Spectral bins model.
188  * @return Spectral bins model.
189  ***************************************************************************/
191 {
192  // Execute only if object is not identical
193  if (this != &model) {
194 
195  // Copy base class members
196  this->GModelSpectral::operator=(model);
197 
198  // Free members
199  free_members();
200 
201  // Initialise members
202  init_members();
203 
204  // Copy members
205  copy_members(model);
206 
207  } // endif: object was not identical
208 
209  // Return
210  return *this;
211 }
212 
213 
214 /*==========================================================================
215  = =
216  = Public methods =
217  = =
218  ==========================================================================*/
219 
220 /***********************************************************************//**
221  * @brief Clear spectral bins model
222  ***************************************************************************/
224 {
225  // Free class members (base and derived classes, derived class first)
226  free_members();
228 
229  // Initialise members
231  init_members();
232 
233  // Return
234  return;
235 }
236 
237 
238 /***********************************************************************//**
239  * @brief Clone spectral bins model
240 ***************************************************************************/
242 {
243  // Clone spectral bins model
244  return new GModelSpectralBins(*this);
245 }
246 
247 
248 /***********************************************************************//**
249  * @brief Evaluate function
250  *
251  * @param[in] srcEng True photon energy.
252  * @param[in] srcTime True photon arrival time.
253  * @param[in] gradients Compute gradients?
254  * @return Model value (ph/cm2/s/MeV).
255  *
256  * @todo Document method.
257  ***************************************************************************/
258 double GModelSpectralBins::eval(const GEnergy& srcEng,
259  const GTime& srcTime,
260  const bool& gradients) const
261 {
262  // Initialise value
263  double value = 0.0;
264 
265  // Optionally initialise partial derivatives
266  if (gradients) {
268  for (int i = 0; i < m_values.size(); ++i) {
269  m_values[i].factor_gradient(0.0);
270  }
271  }
272 
273  // Get bin index
274  int ibin = bin_index(srcEng);
275 
276  // Continue only if index is valid
277  if (ibin >= 0) {
278 
279  // Get power-law index
280  double index = m_index.value();
281 
282  // Compute and store value
283  double eng = srcEng.MeV();
284  double e_norm = eng / m_epivot[ibin];
285  double power = (index != 0.0) ? std::pow(e_norm, index) : 1.0;
286 
287  // Compute function value
288  value = m_values[ibin].value() * power;
289 
290  // Compute gradients
291  if (gradients) {
292 
293  // Compute partial derivatives of the parameter values
294  double g_norm = (m_values[ibin].is_free())
295  ? m_values[ibin].scale() * power : 0.0;
296  double g_index = (m_index.is_free())
297  ? value * m_index.scale() * std::log(e_norm) : 0.0;
298 
299  // Set gradients
300  m_values[ibin].factor_gradient(g_norm);
301  m_index.factor_gradient(g_index);
302 
303  } // endif: gradient computation was requested
304 
305  // Compile option: Check for NaN/Inf
306  #if defined(G_NAN_CHECK)
307  if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
308  std::cout << "*** ERROR: GModelSpectralBins::eval";
309  std::cout << "(srcEng=" << srcEng;
310  std::cout << ", srcTime=" << srcTime << "):";
311  std::cout << " NaN/Inf encountered";
312  std::cout << " (value=" << value;
313  std::cout << ", power=" << power;
314  std::cout << ")" << std::endl;
315  }
316  #endif
317 
318  } // endif: bin index was valid
319 
320  // Return
321  return value;
322 }
323 
324 
325 /***********************************************************************//**
326  * @brief Returns model photon flux between [emin, emax] (units: ph/cm2/s)
327  *
328  * @param[in] emin Minimum photon energy.
329  * @param[in] emax Maximum photon energy.
330  * @return Photon flux (ph/cm2/s).
331  *
332  * Computes
333  *
334  * \f[
335  * \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) dE
336  * \f]
337  *
338  * where
339  * - [@p emin, @p emax] is an energy interval, and
340  * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV).
341  ***************************************************************************/
343  const GEnergy& emax) const
344 {
345  // Initialise flux
346  double flux = 0.0;
347 
348  // Compute only if integration range is valid
349  if (emin < emax) {
350 
351  // Get energy range in MeV
352  double e_min = emin.MeV();
353  double e_max = emax.MeV();
354 
355  // Loop over all bins
356  for (int ibin = 0; ibin < bins(); ++ibin) {
357 
358  // Get energy boundaires of bin in MeV
359  double e_bin_min = m_emin[ibin].value();
360  double e_bin_max = m_emax[ibin].value();
361 
362  // Skip bins that do not overlap with energy range
363  if (e_min >= e_bin_max || e_max < e_bin_min) {
364  continue;
365  }
366 
367  // Raise lower boundary to minimum energy
368  if (e_bin_min < e_min) {
369  e_bin_min = e_min;
370  }
371 
372  // Lower upper boundary to maximum energy
373  if (e_bin_max > e_max) {
374  e_bin_max = e_max;
375  }
376 
377  // If energy interval is positive then compute flux
378  if (e_bin_max > e_bin_min) {
379 
380  // Add photon flux
381  flux += m_values[ibin].value() *
382  gammalib::plaw_photon_flux(e_bin_min,
383  e_bin_max,
384  m_epivot[ibin],
385  m_index.value());
386 
387  } // endif: energy interval was positive
388 
389  } // endfor: looped over all spectral bins
390 
391  } // endif: integration range was valid
392 
393  // Return
394  return flux;
395 }
396 
397 
398 /***********************************************************************//**
399  * @brief Returns model energy flux between [emin, emax] (units: erg/cm2/s)
400  *
401  * @param[in] emin Minimum photon energy.
402  * @param[in] emax Maximum photon energy.
403  * @return Energy flux (erg/cm2/s).
404  *
405  * Computes
406  *
407  * \f[
408  * \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) E \, dE
409  * \f]
410  *
411  * where
412  * - [@p emin, @p emax] is an energy interval, and
413  * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV).
414  ***************************************************************************/
416  const GEnergy& emax) const
417 {
418  // Initialise flux
419  double eflux = 0.0;
420 
421  // Compute only if integration range is valid
422  if (emin < emax) {
423 
424 
425  // Get energy range in MeV
426  double e_min = emin.MeV();
427  double e_max = emax.MeV();
428 
429  // Loop over all bins
430  for (int ibin = 0; ibin < bins(); ++ibin) {
431 
432  // Get energy boundaires of bin in MeV
433  double e_bin_min = m_emin[ibin].value();
434  double e_bin_max = m_emax[ibin].value();
435 
436  // Skip bins that do not overlap with energy range
437  if (e_min >= e_bin_max || e_max < e_bin_min) {
438  continue;
439  }
440 
441  // Raise lower boundary to minimum energy
442  if (e_bin_min < e_min) {
443  e_bin_min = e_min;
444  }
445 
446  // Lower upper boundary to maximum energy
447  if (e_bin_max > e_max) {
448  e_bin_max = e_max;
449  }
450 
451  // If energy interval is positive then compute flux
452  if (e_bin_max > e_bin_min) {
453 
454  // Add energy flux
455  eflux += m_values[ibin].value() *
456  gammalib::plaw_energy_flux(e_bin_min,
457  e_bin_max,
458  m_epivot[ibin],
459  m_index.value());
460 
461  } // endif: energy interval was positive
462 
463  } // endfor: looped over all spectral bins
464 
465  // Convert from MeV/cm2/s to erg/cm2/s
466  eflux *= gammalib::MeV2erg;
467 
468  } // endif: integration range was valid
469 
470  // Return flux
471  return eflux;
472 }
473 
474 
475 /***********************************************************************//**
476  * @brief Returns MC energy between [emin, emax]
477  *
478  * @param[in] emin Minimum photon energy.
479  * @param[in] emax Maximum photon energy.
480  * @param[in] time True photon arrival time.
481  * @param[in,out] ran Random number generator.
482  * @return Energy.
483  *
484  * @exception GException::invalid_return_value
485  * No valid Monte Carlo cache
486  *
487  * Returns Monte Carlo energy by randomly drawing from bin function.
488  ***************************************************************************/
490  const GEnergy& emax,
491  const GTime& time,
492  GRan& ran) const
493 {
494  // Check energy interval
496 
497  // Allocate energy
498  GEnergy energy;
499 
500  // Update cache
501  mc_update(emin, emax);
502 
503  // Determine in which bin we reside. If this fails then thrown an
504  // exception
505  int inx = 0;
506  if (m_mc_cum.size() > 1) {
507  double u = ran.uniform();
508  for (inx = m_mc_cum.size()-1; inx > 0; --inx) {
509  if (m_mc_cum[inx-1] <= u) {
510  break;
511  }
512  }
513  }
514  else if (m_mc_cum.size() == 0) {
515  std::string msg = "No valid bins found for energy interval ["+
516  emin.print()+","+emax.print()+"]. Either restrict "
517  "the energy range to the one covered by the "
518  "spectral bins or extend the spectral bins "
519  "in energy.";
521  }
522 
523  // Get random energy for specific bin
524  if (m_mc_exp[inx] != 0.0) {
525  double e_min = m_mc_min[inx];
526  double e_max = m_mc_max[inx];
527  double u = ran.uniform();
528  double eng = (u > 0.0)
529  ? std::exp(std::log(u * (e_max - e_min) + e_min) / m_mc_exp[inx])
530  : 0.0;
531  energy.MeV(eng);
532  }
533  else {
534  double e_min = m_mc_min[inx];
535  double e_max = m_mc_max[inx];
536  double u = ran.uniform();
537  double eng = std::exp(u * (e_max - e_min) + e_min);
538  energy.MeV(eng);
539  }
540 
541  // Return energy
542  return energy;
543 }
544 
545 
546 /***********************************************************************//**
547  * @brief Read model from XML element
548  *
549  * @param[in] xml XML element.
550  *
551  * @exception GException::invalid_value
552  * Lower energy limit larger than upper energy limit.
553  *
554  * Reads the spectral information from an XML element. The format of the XML
555  * elements is
556  *
557  * <spectrum type="BinFunction">
558  * <parameter name="Index" ../>
559  * <bin>
560  * <parameter name="LowerLimit" ../>
561  * <parameter name="UpperLimit" ../>
562  * <parameter name="Intensity" ../>
563  * </bin>
564  * ...
565  * <bin>
566  * <parameter name="LowerLimit" ../>
567  * <parameter name="UpperLimit" ../>
568  * <parameter name="Intensity" ../>
569  * </bin>
570  * </spectrum>
571  *
572  * @todo Check that bins are ordered
573  * @todo Check that energy boundaries are not overlapping
574  ***************************************************************************/
576 {
577  // Free space for bins
578  m_emin.clear();
579  m_emax.clear();
580  m_values.clear();
581 
582  // Get index parameter pointer
584 
585  // Read index parameter
586  m_index.read(*index);
587 
588  // Get number of bins from XML file
589  int bins = xml.elements("bin");
590 
591  // Loop over all bins
592  for (int i = 0; i < bins; ++i) {
593 
594  // Allocate bin parameters
595  GModelPar emin;
596  GModelPar emax;
598 
599  // Get bins
600  const GXmlElement* bin = xml.element("bin", i);
601 
602  // Get parameters
603  const GXmlElement* lpar = gammalib::xml_get_par(G_READ, *bin, "LowerLimit");
604  const GXmlElement* upar = gammalib::xml_get_par(G_READ, *bin, "UpperLimit");
605  const GXmlElement* ipar = gammalib::xml_get_par(G_READ, *bin, "Intensity");
606 
607  // Read parameters
608  emin.read(*lpar);
609  emax.read(*upar);
610  intensity.read(*ipar);
611 
612  // Throw an exception if either LowerLimit is larger than UpperLimit
613  if (emin.value() > emax.value()) {
614  std::string msg = "Lower energy limit "+gammalib::str(emin.value())+
615  " MeV is larger than upper energy limit "+
616  gammalib::str(emax.value())+" MeV. Please "
617  "specify lower energy limits that are smaller "
618  "than the upper energy limits.";
619  throw GException::invalid_value(G_READ, msg);
620  }
621 
622  // Push bin parameters on list
623  m_emin.push_back(emin);
624  m_emax.push_back(emax);
625  m_values.push_back(intensity);
626 
627  } // endfor: looped over bins
628 
629  // Update parameter mapping
630  update_pars();
631 
632  // Set pre-computation cache
633  set_cache();
634 
635  // Return
636  return;
637 }
638 
639 
640 /***********************************************************************//**
641  * @brief Write model into XML element
642  *
643  * @param[in] xml XML element into which model information is written.
644  *
645  * @exception GException::invalid_value
646  * Existing XML element is not of required type
647  * Invalid number of model parameters or bins found in XML element.
648  *
649  * Writes the spectral information into an XML element. The format of the XML
650  * element is
651  *
652  * <spectrum type="BinFunction">
653  * <parameter name="Index" ../>
654  * <bin>
655  * <parameter name="LowerLimit" ../>
656  * <parameter name="UpperLimit" ../>
657  * <parameter name="Intensity" ../>
658  * </bin>
659  * ...
660  * <bin>
661  * <parameter name="LowerLimit" ../>
662  * <parameter name="UpperLimit" ../>
663  * <parameter name="Intensity" ../>
664  * </bin>
665  * </spectrum>
666  ***************************************************************************/
668 {
669  // Verify model type
671 
672  // Get index parameter
674 
675  // Write index parameter
676  m_index.write(*index);
677 
678  // Determine number of bins
679  int bins = this->bins();
680 
681  // If XML element has 0 bins then append bins
682  if (xml.elements("bin") == 0) {
683  for (int i = 0; i < bins; ++i) {
684  xml.append(GXmlElement("bin"));
685  }
686  }
687 
688  // Verify that XML element has the required number of bins and elements.
689  // Recall that the power-law index also counts as one element.
690  if (xml.elements() != bins+1) {
691  std::string msg = "Spectral bins model contains "+
692  gammalib::str(xml.elements())+
693  " elements but "+gammalib::str(bins+1)+" elements "
694  "were expected.";
696  }
697  if (xml.elements("bin") != bins) {
698  std::string msg = "Spectral bins model contains "+
699  gammalib::str(xml.elements("bin"))+
700  " \"bin\" elements but "+gammalib::str(bins)+
701  " \"bin\" elements were expected.";
703  }
704 
705  // Loop over all bins
706  for (int i = 0; i < bins; ++i) {
707 
708  // Get bins
709  GXmlElement* bin = xml.element("bin", i);
710 
711  // Get copy of parameters so that we can change their names
712  GModelPar emin = m_emin[i];
713  GModelPar emax = m_emax[i];
715 
716  // Set names since we appended for internal usage the indices to the
717  // parameter names, and we want to get rid of them for writing the
718  // model into the XML element
719  emin.name("LowerLimit");
720  emax.name("UpperLimit");
721  intensity.name("Intensity");
722 
723  // Get XML parameters
724  GXmlElement* lpar = gammalib::xml_need_par(G_WRITE, *bin, emin.name());
725  GXmlElement* upar = gammalib::xml_need_par(G_WRITE, *bin, emax.name());
726  GXmlElement* ipar = gammalib::xml_need_par(G_WRITE, *bin, intensity.name());
727 
728  // Write parameters
729  emin.write(*lpar);
730  emax.write(*upar);
731  intensity.write(*ipar);
732 
733  } // endfor: looped over bins
734 
735  // Return
736  return;
737 }
738 
739 
740 /***********************************************************************//**
741  * @brief Append bin
742  *
743  * @param[in] emin Lower energy limit.
744  * @param[in] emax Upper energy limit.
745  * @param[in] intensity Bin intensity.
746  *
747  * @exception GException::invalid_argument
748  * Lower energy limit is larger than upper energy limit.
749  *
750  * Appends one bin to the bin function. By default the lower and upper energy
751  * limit of the bin is fixed while the intensity of the bin is free.
752  ***************************************************************************/
754  const GEnergy& emax,
755  const double& intensity)
756 {
757  // Throw an exception if lower limit is larger than upper limit
758  if (emin > emax) {
759  std::string msg = "Lower energy limit "+emin.print()+" is larger than "
760  "upper energy limit "+emax.print()+". Please "
761  "specify a lower energy limit that is smaller "
762  "than the upper energy limit.";
764  }
765 
766  // Allocate bin parameters
767  GModelPar par_emin;
768  GModelPar par_emax;
769  GModelPar par_intensity;
770 
771  // Set emin attributes
772  par_emin.name("LowerLimit");
773  par_emin.value(emin.MeV());
774  par_emin.unit("MeV");
775  par_emin.has_grad(false);
776  par_emin.fix();
777 
778  // Set emax attributes
779  par_emax.name("UpperLimit");
780  par_emax.value(emax.MeV());
781  par_emax.unit("MeV");
782  par_emax.has_grad(false);
783  par_emax.fix();
784 
785  // Set intensity attributes
786  par_intensity.name("Intensity");
787  par_intensity.value(intensity);
788  par_intensity.unit("ph/cm2/s/MeV");
789  par_intensity.has_grad(true);
790  par_intensity.free();
791 
792  // Append to bins
793  m_emin.push_back(par_emin);
794  m_emax.push_back(par_emax);
795  m_values.push_back(par_intensity);
796 
797  // Update parameter mapping
798  update_pars();
799 
800  // Set pre-computation cache
801  set_cache();
802 
803  // Return
804  return;
805 }
806 
807 
808 /***********************************************************************//**
809  * @brief Insert bin
810  *
811  * @param[in] index Bin index [0,...,bins()-1].
812  * @param[in] emin Lower energy limit.
813  * @param[in] emax Upper energy limit.
814  * @param[in] intensity Bin intensity.
815  *
816  * @exception GException::out_of_range
817  * Bin index is out of range.
818  * @exception GException::invalid_argument
819  * Lower energy limit is larger than upper energy limit.
820  *
821  * Inserts a bin into the bin function before the bin with the specified
822  * @p index. By default the lower and upper energy limit of the bin is fixed
823  * while the intensity of the bin is free.
824  ***************************************************************************/
825 void GModelSpectralBins::insert(const int& index,
826  const GEnergy& emin,
827  const GEnergy& emax,
828  const double& intensity)
829 {
830  // Raise exception if index is outside boundary
831  #if defined(G_RANGE_CHECK)
832  if (index < 0 || index >= bins()) {
833  throw GException::out_of_range(G_INSERT, "Bin index", index, bins());
834  }
835  #endif
836 
837  // Throw an exception if lower limit is larger than upper limit
838  if (emin > emax) {
839  std::string msg = "Lower energy limit "+emin.print()+" is larger than "
840  "upper energy limit "+emax.print()+". Please "
841  "specify a lower energy limit that is smaller "
842  "than the upper energy limit.";
844  }
845 
846  // Allocate bin parameters
847  GModelPar par_emin;
848  GModelPar par_emax;
849  GModelPar par_intensity;
850 
851  // Set emin attributes
852  par_emin.name("LowerLimit");
853  par_emin.value(emin.MeV());
854  par_emin.unit("MeV");
855  par_emin.has_grad(false);
856  par_emin.fix();
857 
858  // Set emax attributes
859  par_emax.name("UpperLimit");
860  par_emax.value(emax.MeV());
861  par_emax.unit("MeV");
862  par_emax.has_grad(false);
863  par_emax.fix();
864 
865  // Set intensity attributes
866  par_intensity.name("Intensity");
867  par_intensity.value(intensity);
868  par_intensity.unit("ph/cm2/s/MeV");
869  par_intensity.has_grad(true);
870  par_intensity.free();
871 
872  // Insert bin
873  m_emin.insert(m_emin.begin()+index, par_emin);
874  m_emax.insert(m_emax.begin()+index, par_emax);
875  m_values.insert(m_values.begin()+index, par_intensity);
876 
877  // Update parameter mapping
878  update_pars();
879 
880  // Set pre-computation cache
881  set_cache();
882 
883  // Return
884  return;
885 }
886 
887 
888 /***********************************************************************//**
889  * @brief Remove bin
890  *
891  * @param[in] index Bin index [0,...,bins()-1].
892  *
893  * @exception GException::out_of_range
894  * Bin index is out of range.
895  *
896  * Removes bin of specified @p index from the bin function.
897  ***************************************************************************/
898 void GModelSpectralBins::remove(const int& index)
899 {
900  // Raise exception if index is outside boundary
901  #if defined(G_RANGE_CHECK)
902  if (index < 0 || index >= bins()) {
903  throw GException::out_of_range(G_REMOVE, "Bin index", index, bins());
904  }
905  #endif
906 
907  // Erase energy and intensity
908  m_emin.erase(m_emin.begin() + index);
909  m_emax.erase(m_emax.begin() + index);
910  m_values.erase(m_values.begin() + index);
911 
912  // Update parameter mapping
913  update_pars();
914 
915  // Set pre-computation cache
916  set_cache();
917 
918  // Return
919  return;
920 }
921 
922 
923 /***********************************************************************//**
924  * @brief Reserve space for bins
925  *
926  * @param[in] num Number of reserved bins.
927  *
928  * Reserves space for @p num bins.
929  ***************************************************************************/
930 void GModelSpectralBins::reserve(const int& num)
931 {
932  // Reserve space
933  m_emin.reserve(num);
934  m_emax.reserve(num);
935  m_values.reserve(num);
936 
937  // Return
938  return;
939 }
940 
941 
942 /***********************************************************************//**
943  * @brief Append bins from bin function
944  *
945  * @param[in] bins Bin function.
946  *
947  * Appends all bins from a bin function to current object.
948  ***************************************************************************/
950 {
951  // Get number of bins in bin function. Note that we extract the size
952  // first to avoid an endless loop that arises when a container is
953  // appended to itself.
954  int num = bins.bins();
955 
956  // Continue only if bin function is not empty
957  if (num > 0) {
958 
959  // Reserve enough space
960  reserve(this->bins() + num);
961 
962  // Loop over all bins and append them to the bin function
963  for (int i = 0; i < num; ++i) {
964  m_emin.push_back(bins.m_emin[i]);
965  m_emax.push_back(bins.m_emax[i]);
966  m_values.push_back(bins.m_values[i]);
967  }
968 
969  // Update parameter mapping
970  update_pars();
971 
972  // Set pre-computation cache
973  set_cache();
974 
975  } // endif: bin function was not empty
976 
977  // Return
978  return;
979 }
980 
981 
982 /***********************************************************************//**
983  * @brief Return spectral power law index
984  *
985  * @return Spectrel power law index.
986  *
987  * Returns the spectral power law index.
988  ***************************************************************************/
989 double GModelSpectralBins::index(void) const
990 {
991  // Return spectral power law index
992  return (m_index.value());
993 }
994 
995 
996 /***********************************************************************//**
997  * @brief Set spectral power law index
998  *
999  * @param[in] index Spectrel power law index.
1000  *
1001  * Set spectral power law index.
1002  ***************************************************************************/
1003 void GModelSpectralBins::index(const double& index)
1004 {
1005  // Set m_index
1006  m_index.value(index);
1007 
1008  // Return
1009  return;
1010 }
1011 
1012 
1013 /***********************************************************************//**
1014  * @brief Return lower energy limit of bin
1015  *
1016  * @param[in] index Bin index [0,...,bins()-1].
1017  * @return Lower energy limit of bin @p index.
1018  *
1019  * @exception GException::out_of_range
1020  * Index is out of range.
1021  *
1022  * Returns the lower energy limit of bin @p index.
1023  ***************************************************************************/
1024 GEnergy GModelSpectralBins::emin(const int& index) const
1025 {
1026  // Raise an exception if index is out of range
1027  #if defined(G_RANGE_CHECK)
1028  if (index < 0 || index >= bins()) {
1029  throw GException::out_of_range(G_EMIN_GET, "Bin index", index, bins());
1030  }
1031  #endif
1032 
1033  // Retrieve energy
1034  GEnergy energy;
1035  energy.MeV(m_emin[index].value());
1036 
1037  // Return energy
1038  return energy;
1039 }
1040 
1041 
1042 /***********************************************************************//**
1043  * @brief Return upper energy limit of bin
1044  *
1045  * @param[in] index Bin index [0,...,bins()-1].
1046  * @return Upper energy limit of bin @p index.
1047  *
1048  * @exception GException::out_of_range
1049  * Index is out of range.
1050  *
1051  * Returns the upper energy limit of bin @p index.
1052  ***************************************************************************/
1053 GEnergy GModelSpectralBins::emax(const int& index) const
1054 {
1055  // Raise an exception if index is out of range
1056  #if defined(G_RANGE_CHECK)
1057  if (index < 0 || index >= bins()) {
1058  throw GException::out_of_range(G_EMAX_GET, "Bin index", index, bins());
1059  }
1060  #endif
1061 
1062  // Retrieve energy
1063  GEnergy energy;
1064  energy.MeV(m_emax[index].value());
1065 
1066  // Return energy
1067  return energy;
1068 }
1069 
1070 
1071 /***********************************************************************//**
1072  * @brief Set lower energy limit of bin
1073  *
1074  * @param[in] index Bin index [0,...,bins()-1].
1075  * @param[in] emin Lower energy limit of bin @p index.
1076  *
1077  * @exception GException::out_of_range
1078  * Index is out of range.
1079  *
1080  * Sets the lower energy limit of bin @p index.
1081  ***************************************************************************/
1082 void GModelSpectralBins::emin(const int& index, const GEnergy& emin)
1083 {
1084  // Raise an exception if index is out of range
1085  #if defined(G_RANGE_CHECK)
1086  if (index < 0 || index >= bins()) {
1087  throw GException::out_of_range(G_EMIN_SET, "Bin index", index, bins());
1088  }
1089  #endif
1090 
1091  // Set energy
1092  m_emin[index].value(emin.MeV());
1093 
1094  // Set pre-computation cache
1095  set_cache();
1096 
1097  // Return
1098  return;
1099 }
1100 
1101 
1102 /***********************************************************************//**
1103  * @brief Set upper energy limit of bin
1104  *
1105  * @param[in] index Bin index [0,...,bins()-1].
1106  * @param[in] emax Upper energy limit of bin @p index.
1107  *
1108  * @exception GException::out_of_range
1109  * Index is out of range.
1110  *
1111  * Sets the upper energy limit of bin @p index.
1112  ***************************************************************************/
1113 void GModelSpectralBins::emax(const int& index, const GEnergy& emax)
1114 {
1115  // Raise an exception if index is out of range
1116  #if defined(G_RANGE_CHECK)
1117  if (index < 0 || index >= bins()) {
1118  throw GException::out_of_range(G_EMAX_SET, "Bin index", index, bins());
1119  }
1120  #endif
1121 
1122  // Set energy
1123  m_emax[index].value(emax.MeV());
1124 
1125  // Set pre-computation cache
1126  set_cache();
1127 
1128  // Return
1129  return;
1130 }
1131 
1132 
1133 /***********************************************************************//**
1134  * @brief Return bin intensity
1135  *
1136  * @param[in] index Bin index [0,...,bins()-1].
1137  * @return Intensity of bin @p index.
1138  *
1139  * @exception GException::out_of_range
1140  * Index is out of range.
1141  *
1142  * Returns the intensity of bin @p index.
1143  ***************************************************************************/
1144 double GModelSpectralBins::intensity(const int& index) const
1145 {
1146  // Raise an exception if index is out of range
1147  #if defined(G_RANGE_CHECK)
1148  if (index < 0 || index >= bins()) {
1149  throw GException::out_of_range(G_INTENSITY_GET, "Bin index", index, bins());
1150  }
1151  #endif
1152 
1153  // Return intensity
1154  return (m_values[index].value());
1155 }
1156 
1157 
1158 /***********************************************************************//**
1159  * @brief Return intensity error of bin
1160  *
1161  * @param[in] index Bin index [0,...,bins()-1].
1162  * @return Intensity error of bin @p index.
1163  *
1164  * @exception GException::out_of_range
1165  * Index is out of range.
1166  *
1167  * Returns the intensity error of bin @p index.
1168  ***************************************************************************/
1169 double GModelSpectralBins::error(const int& index) const
1170 {
1171  // Raise an exception if index is out of range
1172  #if defined(G_RANGE_CHECK)
1173  if (index < 0 || index >= bins()) {
1174  throw GException::out_of_range(G_ERROR_GET, "Bin index", index, bins());
1175  }
1176  #endif
1177 
1178  // Return intensity error
1179  return (m_values[index].error());
1180 }
1181 
1182 
1183 /***********************************************************************//**
1184  * @brief Set bin intensity
1185  *
1186  * @param[in] index Bin index [0,...,bins()-1].
1187  * @param[in] intensity Intensity of bin @p index.
1188  *
1189  * @exception GException::out_of_range
1190  * Index is out of range.
1191  *
1192  * Set the intensity of bin @p index.
1193  ***************************************************************************/
1194 void GModelSpectralBins::intensity(const int& index, const double& intensity)
1195 {
1196  // Raise an exception if index is out of range
1197  #if defined(G_RANGE_CHECK)
1198  if (index < 0 || index >= bins()) {
1199  throw GException::out_of_range(G_INTENSITY_SET, "Bin index", index, bins());
1200  }
1201  #endif
1202 
1203  // Set intensity
1204  m_values[index].value(intensity);
1205 
1206  // Return
1207  return;
1208 }
1209 
1210 
1211 /***********************************************************************//**
1212  * @brief Print bin function information
1213  *
1214  * @param[in] chatter Chattiness.
1215  * @return String containing bin function information.
1216  ***************************************************************************/
1217 std::string GModelSpectralBins::print(const GChatter& chatter) const
1218 {
1219  // Initialise result string
1220  std::string result;
1221 
1222  // Continue only if chatter is not silent
1223  if (chatter != SILENT) {
1224 
1225  // Append header
1226  result.append("=== GModelSpectralBins ===");
1227 
1228  // Append information
1229  result.append("\n"+gammalib::parformat("Number of bins"));
1230  result.append(gammalib::str(bins()));
1231  result.append("\n"+gammalib::parformat("Number of parameters"));
1232  result.append(gammalib::str(size()));
1233  for (int i = 0; i < size(); ++i) {
1234  result.append("\n"+m_pars[i]->print(chatter));
1235  }
1236 
1237  } // endif: chatter was not silent
1238 
1239  // Return result
1240  return result;
1241 }
1242 
1243 
1244 /*==========================================================================
1245  = =
1246  = Private methods =
1247  = =
1248  ==========================================================================*/
1249 
1250 /***********************************************************************//**
1251  * @brief Initialise class members
1252  ***************************************************************************/
1254 {
1255  // Initialise powerlaw index
1256  m_index.clear();
1257  m_index.name("Index");
1258  m_index.scale(1.0);
1259  m_index.value(-2.0); // default: -2.0
1260  m_index.range(-10.0,+10.0); // range: [-10,+10]
1261  m_index.fix();
1262  m_index.gradient(0.0);
1263  m_index.has_grad(true);
1264 
1265  // Initialise bin parameter vectors
1266  m_emin.clear();
1267  m_emax.clear();
1268  m_values.clear();
1269 
1270  // Initialise evaluation cache
1271  m_epivot.clear();
1272 
1273  // Initialise MC cache
1274  m_mc_emin.clear();
1275  m_mc_emax.clear();
1276  m_mc_cum.clear();
1277  m_mc_min.clear();
1278  m_mc_max.clear();
1279  m_mc_exp.clear();
1280 
1281  // Update parameter mapping
1282  update_pars();
1283 
1284  // Return
1285  return;
1286 }
1287 
1288 
1289 /***********************************************************************//**
1290  * @brief Copy class members
1291  *
1292  * @param[in] model Spectral bin function.
1293  ***************************************************************************/
1295 {
1296  // Copy bin energies and values
1297  m_index = model.m_index;
1298  m_emin = model.m_emin;
1299  m_emax = model.m_emax;
1300  m_values = model.m_values;
1301 
1302  // Copy evluation cache
1303  m_epivot = model.m_epivot;
1304 
1305  // Copy MC cache
1306  m_mc_emin = model.m_mc_emin;
1307  m_mc_emax = model.m_mc_emax;
1308  m_mc_cum = model.m_mc_cum;
1309  m_mc_min = model.m_mc_min;
1310  m_mc_max = model.m_mc_max;
1311  m_mc_exp = model.m_mc_exp;
1312 
1313  // Update parameter mapping
1314  update_pars();
1315 
1316  // Return
1317  return;
1318 }
1319 
1320 
1321 /***********************************************************************//**
1322  * @brief Delete class members
1323  ***************************************************************************/
1325 {
1326  // Return
1327  return;
1328 }
1329 
1330 
1331 /***********************************************************************//**
1332  * @brief Return bin index for energy
1333  *
1334  * @param[in] energy Energy.
1335  * @return Bin index (-1 if energy bin was not found).
1336  ***************************************************************************/
1337 int GModelSpectralBins::bin_index(const GEnergy& energy) const
1338 {
1339  // Initialise bin index
1340  int bin = -1;
1341 
1342  // Get energy in MeV
1343  double energy_MeV = energy.MeV();
1344 
1345  // Search bin index
1346  for (int i = 0; i < bins(); ++i) {
1347  if (energy_MeV >= m_emin[i].value() && energy_MeV < m_emax[i].value()) {
1348  bin = i;
1349  break;
1350  }
1351  }
1352 
1353  // Return bin index
1354  return bin;
1355 }
1356 
1357 
1358 /***********************************************************************//**
1359  * @brief Update parameter mapping
1360  *
1361  * Sets the parameter pointers in the m_pars array, enabling iterating over
1362  * all model parameters. This method needs to be called after changing the
1363  * number of bins in the spectral model. The method needs not to be called
1364  * after value update.
1365  ***************************************************************************/
1367 {
1368  // Clear parameter pointer(s)
1369  m_pars.clear();
1370 
1371  // Push back common spectral index
1372  m_pars.push_back(&m_index);
1373 
1374  // Set parameter pointers for all bins
1375  for (int i = 0; i < bins(); ++i) {
1376 
1377  // Set parameter names
1378  std::string lowerlimit_name = "LowerLimit" + gammalib::str(i);
1379  std::string upperlimit_name = "UpperLimit" + gammalib::str(i);
1380  std::string intensity_name = "Intensity" + gammalib::str(i);
1381 
1382  // Set lower limit attributes
1383  m_emin[i].name(lowerlimit_name);
1384  m_emin[i].unit("MeV");
1385  m_emin[i].has_grad(false);
1386 
1387  // Set upper limit attributes
1388  m_emax[i].name(upperlimit_name);
1389  m_emax[i].unit("MeV");
1390  m_emax[i].has_grad(false);
1391 
1392  // Set intensity attributes
1393  m_values[i].name(intensity_name);
1394  m_values[i].unit("ph/cm2/s/MeV");
1395  m_values[i].has_grad(true);
1396 
1397  // Set pointer
1398  m_pars.push_back(&(m_emin[i]));
1399  m_pars.push_back(&(m_emax[i]));
1400  m_pars.push_back(&(m_values[i]));
1401 
1402  } // endfor: looped over bins
1403 
1404  // Return
1405  return;
1406 }
1407 
1408 
1409 /***********************************************************************//**
1410  * @brief Set cache
1411  *
1412  * Sets the computation cache. The method computes for the time being the
1413  * pivot energies for all bins in MeV.
1414  ***************************************************************************/
1416 {
1417  // Clear cache
1418  m_epivot.clear();
1419 
1420  // Compute pivot energies for all bins
1421  for (int i = 0; i < bins(); ++i) {
1422  double epivot = std::sqrt(m_emin[i].value() * m_emax[i].value());
1423  m_epivot.push_back(epivot);
1424  }
1425 
1426  // Return
1427  return;
1428 }
1429 
1430 
1431 /***********************************************************************//**
1432  * @brief Set MC pre-computation cache
1433  *
1434  * @param[in] emin Minimum energy.
1435  * @param[in] emax Maximum energy.
1436  *
1437  * This method sets up an array of indices and the cumulative distribution
1438  * function needed for MC simulations.
1439  ***************************************************************************/
1441  const GEnergy& emax) const
1442 {
1443  // Check if we need to update the cache
1444  if (emin != m_mc_emin || emax != m_mc_emax) {
1445 
1446  // Store new energy interval
1447  m_mc_emin = emin;
1448  m_mc_emax = emax;
1449 
1450  // Initialise cache
1451  m_mc_cum.clear();
1452  m_mc_min.clear();
1453  m_mc_max.clear();
1454  m_mc_exp.clear();
1455 
1456  // Get energy range in MeV
1457  double e_min = emin.MeV();
1458  double e_max = emax.MeV();
1459 
1460  // Continue only if e_max > e_min
1461  if (e_max > e_min) {
1462 
1463  // Loop over all bins
1464  for (int ibin = 0; ibin < bins(); ++ibin) {
1465 
1466  // Get energy boundaires of bin in MeV
1467  double e_bin_min = m_emin[ibin].value();
1468  double e_bin_max = m_emax[ibin].value();
1469 
1470  // Skip bins that do not overlap with energy range
1471  if (e_min >= e_bin_max || e_max < e_bin_min) {
1472  continue;
1473  }
1474 
1475  // Raise lower boundary to minimum energy
1476  if (e_bin_min < e_min) {
1477  e_bin_min = e_min;
1478  }
1479 
1480  // Lower upper boundary to maximum energy
1481  if (e_bin_max > e_max) {
1482  e_bin_max = e_max;
1483  }
1484 
1485  // If energy interval is positive then compute flux
1486  if (e_bin_max > e_bin_min) {
1487 
1488  // Get index
1489  double index = m_index.value();
1490 
1491  // Compute flux
1492  double flux = m_values[ibin].value() *
1493  gammalib::plaw_photon_flux(e_bin_min,
1494  e_bin_max,
1495  m_epivot[ibin],
1496  index);
1497 
1498  // Push results in cache
1499  m_mc_cum.push_back(flux);
1500  m_mc_min.push_back(e_bin_min);
1501  m_mc_max.push_back(e_bin_max);
1502  m_mc_exp.push_back(index);
1503 
1504  } // endif: energy interval was positive
1505 
1506  } // endfor: looped over all spectral bins
1507 
1508  // Build cumulative distribution
1509  for (int i = 1; i < m_mc_cum.size(); ++i) {
1510  m_mc_cum[i] += m_mc_cum[i-1];
1511  }
1512  double norm = m_mc_cum[m_mc_cum.size()-1];
1513  if (norm > 0.0) {
1514  for (int i = 0; i < m_mc_cum.size(); ++i) {
1515  m_mc_cum[i] /= norm;
1516  }
1517  }
1518 
1519  // Set MC values
1520  for (int i = 0; i < m_mc_cum.size(); ++i) {
1521 
1522  // Compute exponent
1523  double exponent = m_mc_exp[i] + 1.0;
1524 
1525  // Exponent dependend computation
1526  if (std::abs(exponent) > 1.0e-11) {
1527 
1528  // If the exponent is too small then use lower energy
1529  // boundary
1530  if (exponent < -50.0) {
1531  m_mc_exp[i] = 0.0;
1532  m_mc_min[i] = std::log(m_mc_min[i]);
1533  m_mc_max[i] = m_mc_min[i];
1534  }
1535 
1536  // ... otherwise if exponent is too large then use
1537  // upper energy boundary
1538  else if (exponent > +50.0) {
1539  m_mc_exp[i] = 0.0;
1540  m_mc_min[i] = std::log(m_mc_max[i]);
1541  m_mc_max[i] = m_mc_min[i];
1542  }
1543 
1544  // ... otherwise use transformation formula
1545  else {
1546  m_mc_exp[i] = exponent;
1547  m_mc_min[i] = std::pow(m_mc_min[i], exponent);
1548  m_mc_max[i] = std::pow(m_mc_max[i], exponent);
1549  }
1550  }
1551  else {
1552  m_mc_exp[i] = 0.0;
1553  m_mc_min[i] = std::log(m_mc_min[i]);
1554  m_mc_max[i] = std::log(m_mc_max[i]);
1555  }
1556 
1557  } // endfor: set MC values
1558 
1559  } // endif: e_max > e_min
1560 
1561  } // endif: Update was required
1562 
1563  // Return
1564  return;
1565 }
virtual double flux(const GEnergy &emin, const GEnergy &emax) const
Returns model photon flux between emin, emax
GEnergy emax(const int &index) const
Return upper energy limit of bin.
virtual GModelSpectralBins & operator=(const GModelSpectralBins &model)
Assignment operator.
GEnergy emin(const int &index) const
Return lower energy limit of bin.
double intensity(const int &index) const
Return bin intensity.
void insert(const int &index, const GEnergy &emin, const GEnergy &emax, const double &intensity)
Insert bin.
const double & factor_gradient(void) const
Return parameter factor gradient.
double norm(const GVector &vector)
Computes vector norm.
Definition: GVector.cpp:864
#define G_EMIN_GET
std::vector< GModelPar > m_emin
Lower energy limits.
const std::string & name(void) const
Return parameter name.
Spectral bins model class definition.
Random number generator class definition.
void init_members(void)
Initialise class members.
Abstract spectral model base class.
double gradient(void) const
Return parameter gradient.
int size(void) const
Return number of parameters.
GVector abs(const GVector &vector)
Computes absolute of vector elements.
Definition: GVector.cpp:1253
virtual GModelSpectral & operator=(const GModelSpectral &model)
Assignment operator.
void write(GXmlElement &xml) const
Set or update parameter attributes in XML element.
Definition: GModelPar.cpp:351
int size(void) const
Return number of energy boundaries.
Definition: GEbounds.hpp:163
virtual double eval(const GEnergy &srcEng, const GTime &srcTime=GTime(), const bool &gradients=false) const =0
std::vector< GModelPar * > m_pars
Parameter pointers.
std::vector< double > m_mc_max
Upper boundary for MC.
#define G_ERROR_GET
XML element node class.
Definition: GXmlElement.hpp:48
Spectral model registry class definition.
virtual double eval(const GEnergy &srcEng, const GTime &srcTime=GTime(), const bool &gradients=false) const
Evaluate function.
Random number generator class.
Definition: GRan.hpp:44
virtual std::string print(const GChatter &chatter=NORMAL) const
Print bin function information.
GEnergy m_mc_emax
Maximum energy.
virtual void read(const GXmlElement &xml)
Read model from XML element.
Spectral bins model class.
double MeV(void) const
Return energy in MeV.
Definition: GEnergy.cpp:321
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition: GXmlNode.cpp:586
#define G_READ
Time class.
Definition: GTime.hpp:55
virtual GModelSpectralBins * clone(void) const
Clone spectral bins model.
#define G_MC
Gammalib tools definition.
virtual std::string type(void) const
Return model type.
std::vector< GModelPar > m_values
Bin values.
double plaw_energy_flux(const double &emin, const double &emax, const double &epivot, const double &gamma)
Compute energy flux between two energies for a power law.
Definition: GTools.cpp:1248
#define G_REMOVE
bool is_free(void) const
Signal if parameter is free.
void update_pars(void)
Update parameter mapping.
#define G_EMAX_GET
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition: GTools.hpp:201
void mc_update(const GEnergy &emin, const GEnergy &emax) const
Set MC pre-computation cache.
#define G_EMIN_SET
const double & scale(void) const
Return parameter scale.
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition: GTools.hpp:184
Model parameter class.
Definition: GModelPar.hpp:87
std::vector< GModelPar > m_emax
Upper energy limits.
GVector sqrt(const GVector &vector)
Computes square root of vector elements.
Definition: GVector.cpp:1358
#define G_INTENSITY_GET
bool has_grad(void) const
Signal if parameter gradient is computed analytically.
#define G_EMAX_SET
void remove(const int &index)
Remove bin.
Energy boundaries container class.
Definition: GEbounds.hpp:60
virtual double eflux(const GEnergy &emin, const GEnergy &emax) const
Returns model energy flux between emin, emax
std::string print(const GChatter &chatter=NORMAL) const
Print energy.
Definition: GEnergy.cpp:748
void free(void)
Free a parameter.
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Definition: GEbounds.hpp:187
void fix(void)
Fix a parameter.
void reserve(const int &num)
Reserve space for bins.
GXmlElement * xml_need_par(const std::string &origin, GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1637
#define G_WRITE
#define G_APPEND
GVector log(const GVector &vector)
Computes natural logarithm of vector elements.
Definition: GVector.cpp:1274
double uniform(void)
Returns random double precision floating value in range 0 to 1.
Definition: GRan.cpp:242
void check_energy_interval(const std::string &origin, const GEnergy &emin, const GEnergy &emax)
Checks energy interval.
Definition: GException.cpp:364
void clear(void)
Clear parameter.
GChatter
Definition: GTypemaps.hpp:33
void append(const GEnergy &emin, const GEnergy &emax, const double &intensity)
Append bin.
GEnergy elogmean(const int &index) const
Returns logarithmic mean energy for a given energy interval.
Definition: GEbounds.cpp:1126
#define G_INSERT
std::vector< double > m_epivot
Power-law pivot energies in MeV.
void extend(const GModelSpectralBins &bins)
Append bins from bin function.
virtual ~GModelSpectralBins(void)
Destructor.
void free_members(void)
Delete class members.
GModelSpectralBins(void)
Void constructor.
Interface definition for the spectral model registry class.
int bins(void) const
Return number of bins.
GEnergy m_mc_emin
Minimum energy.
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition: GXmlNode.cpp:640
void init_members(void)
Initialise class members.
std::vector< double > m_mc_cum
Cumulative distribution.
const double MeV2erg
Definition: GTools.hpp:45
void range(const double &min, const double &max)
Set minimum and maximum parameter boundaries.
void copy_members(const GModelSpectralBins &model)
Copy class members.
void read(const GXmlElement &xml)
Extract parameter attributes from XML element.
Definition: GModelPar.cpp:229
double value(void) const
Return parameter value.
const std::string & unit(void) const
Return parameter unit.
GVector pow(const GVector &vector, const double &power)
Computes tanh of vector elements.
Definition: GVector.cpp:1422
Energy boundaries class interface definition.
Exception handler interface definition.
GVector exp(const GVector &vector)
Computes exponential of vector elements.
Definition: GVector.cpp:1232
void set_cache(void) const
Set cache.
GModelPar m_index
Spectral index of all bins.
const GEnergy & emax(void) const
Return maximum energy of all intervals.
Definition: GEbounds.hpp:199
#define G_INTENSITY_SET
double index(void) const
Return spectral power law index.
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition: GXmlNode.cpp:287
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
virtual void clear(void)
Clear spectral bins model.
int bin_index(const GEnergy &energy) const
Return bin index for energy.
std::vector< double > m_mc_min
Lower boundary for MC.
std::vector< double > m_mc_exp
Exponent for MC.
const GModelSpectralBins g_spectral_bins_seed
virtual void write(GXmlElement &xml) const
Write model into XML element.
const GXmlElement * xml_get_par(const std::string &origin, const GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1689
void free_members(void)
Delete class members.
void clear(void)
Clear instance.
Definition: GEnergy.cpp:261
virtual GEnergy mc(const GEnergy &emin, const GEnergy &emax, const GTime &time, GRan &ran) const
Returns MC energy between [emin, emax].
double error(const int &index) const
Return intensity error of bin.
Class that handles energies in a unit independent way.
Definition: GEnergy.hpp:48
double plaw_photon_flux(const double &emin, const double &emax, const double &epivot, const double &gamma)
Compute photon flux between two energies for a power law.
Definition: GTools.cpp:1200
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489
void xml_check_type(const std::string &origin, GXmlElement &xml, const std::string &type)
Checks the model type.
Definition: GTools.cpp:1819