Commit 60616f4d79873c850bfac7af6d8cdf3de9b497bb

Authored by Jürgen Knödlseder
1 parent 10f11c99

Integrate code

ChangeLog
... ... @@ -3,6 +3,7 @@
3 3 * Version 1.2.0 released
4 4 =========================
5 5  
  6 + Add composite spatial and spectral models (#1706)
6 7 Add GObservations::save_covmat() method (#1863)
7 8 Add GFft and GFftWavetable classes (#1731)
8 9 Add GNdarray class (#1768)
... ...
... ... @@ -15,6 +15,8 @@ The following classes have been added:
15 15 - GModelSpectralExpInvPlaw
16 16 - GModelSpectralPlawEnergyFlux
17 17 - GModelSpectralMultiplicative
  18 +- GModelSpectralComposite
  19 +- GModelSpatialComposite
18 20 - GVOTable
19 21 - GNdarray
20 22 - GFft
... ... @@ -156,6 +158,10 @@ power law. The cut-off parameter is the inverse of the cut-off energy
156 158 The GModelSpectralMultiplicative class has been added that implements the
157 159 product of spectral model components as a new spectral model (#1861).
158 160  
  161 +The GModelSpectralComposite and GModelSpatialComposite classes have been
  162 +added that implement composite spectral and spatial models, which are sums
  163 +of models as a new model component (#1706).
  164 +
159 165  
160 166 9. Numerics module
161 167 ------------------
... ...
include/GModelSpectralComposite.hpp
1 1 /***************************************************************************
2   - * GModelSpectralComposite.hpp - Spectral power law model class *
  2 + * GModelSpectralComposite.hpp - Spectral composite model class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2016 by Michael Mayer *
  4 + * copyright (C) 2016 by Michael Mayer *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -82,7 +82,8 @@ public:
82 82 virtual std::string print(const GChatter& chatter = NORMAL) const;
83 83  
84 84 // Other methods
85   - void append(const GModelSpectral& spec, const std::string& name="");
  85 + void append(const GModelSpectral& spec,
  86 + const std::string& name="");
86 87 int components(void) const;
87 88 const GModelSpectral* component(const int& index) const;
88 89 const GModelSpectral* component(const std::string& name) const;
... ... @@ -104,7 +105,7 @@ protected:
104 105 mutable std::vector<double> m_mc_probs; //!< Probailities of individual components
105 106 mutable GEnergy m_mc_emin; //!< Last minimum energy
106 107 mutable GEnergy m_mc_emax; //!< Last maximum energy
107   -
  108 + mutable std::vector<double> m_mc_values; //!< Parameter values
108 109 };
109 110  
110 111  
... ... @@ -147,5 +148,4 @@ int GModelSpectralComposite::components(void) const
147 148 return (m_spectral.size());
148 149 }
149 150  
150   -
151 151 #endif /* GMODELSPECTRALCOMPOSITE_HPP */
... ...
pyext/GModelSpectralComposite.i
1 1 /***************************************************************************
2   - * GModelSpectralComposite.i - Spectral power law model class *
  2 + * GModelSpectralComposite.i - Spectral composite model class *
3 3 * ----------------------------------------------------------------------- *
4 4 * copyright (C) 2016 Michael Mayer *
5 5 * ----------------------------------------------------------------------- *
... ... @@ -19,7 +19,8 @@
19 19 * *
20 20 ***************************************************************************/
21 21 /**
22   - * @file GModelSpecComposite spectral model class interface definition
  22 + * @file GModelSpectralComposite.i
  23 + * @brief Composite spectral model class interface definition
23 24 * @author Michael Mayer
24 25 */
25 26 %{
... ... @@ -61,11 +62,11 @@ public:
61 62 virtual void write(GXmlElement& xml) const;
62 63  
63 64 // Other methods
64   - void append(const GModelSpectral& spec, const std::string& name="");
  65 + void append(const GModelSpectral& spec,
  66 + const std::string& name="");
65 67 int components(void) const;
66 68 GModelSpectral* component(const int& index) const;
67 69 GModelSpectral* component(const std::string& name) const;
68   -
69 70 };
70 71  
71 72  
... ...
src/model/GModelSpatialComposite.cpp
... ... @@ -662,7 +662,7 @@ void GModelSpatialComposite::free_members(void)
662 662 for (int i = 0; i < m_components.size(); ++i) {
663 663  
664 664 // Delete component i
665   - delete m_components[i];
  665 + if (m_components[i] != NULL) delete m_components[i];
666 666  
667 667 // Signal free pointer
668 668 m_components[i] = NULL;
... ...
src/model/GModelSpectralComposite.cpp
... ... @@ -38,15 +38,16 @@
38 38 /* __ Constants __________________________________________________________ */
39 39  
40 40 /* __ Globals ____________________________________________________________ */
41   -const GModelSpectralComposite g_spectral_comp_seed;
42   -const GModelSpectralRegistry g_spectral_comp_registry(&g_spectral_comp_seed);
  41 +const GModelSpectralComposite g_spectral_comp_seed;
  42 +const GModelSpectralRegistry g_spectral_comp_registry(&g_spectral_comp_seed);
43 43  
44 44 /* __ Method name definitions ____________________________________________ */
45   -#define G_MC "GModelSpectralComposite::mc(GEnergy&, GEnergy&, GTime&, GRan&)"
46   -#define G_WRITE "GModelSpectralComposite::write(GXmlElement&)"
47   -#define G_COMPONENT_INDEX "GModelSpectralComposite::component(const int&)"
48   -#define G_COMPONENT_NAME "GModelSpectralComposite::component(const std::string&)"
49   -#define G_APPEND "GModelSpectralComposite::append(const GModelSpectral&, const std::string&)"
  45 +#define G_MC "GModelSpectralComposite::mc(GEnergy&, GEnergy&, GTime&, GRan&)"
  46 +#define G_WRITE "GModelSpectralComposite::write(GXmlElement&)"
  47 +#define G_COMPONENT_INDEX "GModelSpectralComposite::component(int&)"
  48 +#define G_COMPONENT_NAME "GModelSpectralComposite::component(std::string&)"
  49 +#define G_APPEND "GModelSpectralComposite::append(GModelSpectral&, "\
  50 + "std::string&)"
50 51  
51 52 /* __ Macros _____________________________________________________________ */
52 53  
... ... @@ -77,13 +78,13 @@ GModelSpectralComposite::GModelSpectralComposite(void) : GModelSpectral()
77 78 /***********************************************************************//**
78 79 * @brief XML constructor
79 80 *
80   - * @param[in] xml XML element containing position information.
  81 + * @param[in] xml XML element containing model information.
81 82 *
82   - * Constructs a power law spectral model by extracting information from an
83   - * XML element. See the read() method for more information about the expected
84   - * structure of the XML element.
  83 + * Constructs a composite spectral model by extracting information from an
  84 + * XML element.
85 85 ***************************************************************************/
86   -GModelSpectralComposite::GModelSpectralComposite(const GXmlElement& xml) : GModelSpectral()
  86 +GModelSpectralComposite::GModelSpectralComposite(const GXmlElement& xml) :
  87 + GModelSpectral()
87 88 {
88 89 // Initialise members
89 90 init_members();
... ... @@ -99,10 +100,10 @@ GModelSpectralComposite::GModelSpectralComposite(const GXmlElement&amp; xml) : GMode
99 100 /***********************************************************************//**
100 101 * @brief Copy constructor
101 102 *
102   - * @param[in] model Spectral power law model.
  103 + * @param[in] model Composite spectral model.
103 104 ***************************************************************************/
104   -GModelSpectralComposite::GModelSpectralComposite(const GModelSpectralComposite& model)
105   - : GModelSpectral(model)
  105 +GModelSpectralComposite::GModelSpectralComposite(const GModelSpectralComposite& model) :
  106 + GModelSpectral(model)
106 107 {
107 108 // Initialise members
108 109 init_members();
... ... @@ -137,8 +138,8 @@ GModelSpectralComposite::~GModelSpectralComposite(void)
137 138 /***********************************************************************//**
138 139 * @brief Assignment operator
139 140 *
140   - * @param[in] model Spectral power law model.
141   - * @return Spectral power law model.
  141 + * @param[in] model Composite spectral model.
  142 + * @return Composite spectral model.
142 143 ***************************************************************************/
143 144 GModelSpectralComposite& GModelSpectralComposite::operator=(const GModelSpectralComposite& model)
144 145 {
... ... @@ -171,7 +172,7 @@ GModelSpectralComposite&amp; GModelSpectralComposite::operator=(const GModelSpectral
171 172 ==========================================================================*/
172 173  
173 174 /***********************************************************************//**
174   - * @brief Clear spectral power law model
  175 + * @brief Clear composite spectral model
175 176 ***************************************************************************/
176 177 void GModelSpectralComposite::clear(void)
177 178 {
... ... @@ -189,9 +190,9 @@ void GModelSpectralComposite::clear(void)
189 190  
190 191  
191 192 /***********************************************************************//**
192   - * @brief Clone spectral power law model
  193 + * @brief Clone composite spectral model
193 194 *
194   - * @return Pointer to deep copy of spectral power law model.
  195 + * @return Pointer to deep copy of composite spectral model.
195 196 ***************************************************************************/
196 197 GModelSpectralComposite* GModelSpectralComposite::clone(void) const
197 198 {
... ... @@ -217,13 +218,12 @@ GModelSpectralComposite* GModelSpectralComposite::clone(void) const
217 218 * where \f${M_{\rm i}}\f$ is the model evaluation of the i-th model
218 219 *
219 220 * If the @p gradients flag is true the method will also compute the
220   - * partial derivatives of each model component with respect to the parameters using
221   - *
222   - * @todo The method expects that energy!=0. Otherwise Inf or NaN may result.
  221 + * partial derivatives of each model component with respect to the
  222 + * parameters.
223 223 ***************************************************************************/
224 224 double GModelSpectralComposite::eval(const GEnergy& srcEng,
225   - const GTime& srcTime,
226   - const bool& gradients) const
  225 + const GTime& srcTime,
  226 + const bool& gradients) const
227 227 {
228 228 // Initialise result
229 229 double value = 0.0;
... ... @@ -260,11 +260,10 @@ double GModelSpectralComposite::eval(const GEnergy&amp; srcEng,
260 260 * @param[in] emax Maximum photon energy.
261 261 * @return Photon flux (ph/cm2/s).
262 262 *
263   - * Computes the sum of all photon fluxes of each individual component
264   - *
  263 + * Computes the sum of the photon fluxes in all components.
265 264 ***************************************************************************/
266 265 double GModelSpectralComposite::flux(const GEnergy& emin,
267   - const GEnergy& emax) const
  266 + const GEnergy& emax) const
268 267 {
269 268 // Initialise flux
270 269 double flux = 0.0;
... ... @@ -294,11 +293,10 @@ double GModelSpectralComposite::flux(const GEnergy&amp; emin,
294 293 * @param[in] emax Maximum photon energy.
295 294 * @return Energy flux (erg/cm2/s).
296 295 *
297   - * Computes the sum of all energy fluxes of each individual component
298   - *
  296 + * Computes the sum of the energy fluxes in all components.
299 297 ***************************************************************************/
300 298 double GModelSpectralComposite::eflux(const GEnergy& emin,
301   - const GEnergy& emax) const
  299 + const GEnergy& emax) const
302 300 {
303 301 // Initialise eflux
304 302 double eflux = 0.0;
... ... @@ -333,12 +331,13 @@ double GModelSpectralComposite::eflux(const GEnergy&amp; emin,
333 331 * @exception GException::erange_invalid
334 332 * Energy range is invalid (emin < emax required).
335 333 *
336   - * Returns Monte Carlo energy by randomly drawing from a power law.
  334 + * Returns Monte Carlo energy by randomly drawing from a composite spectral
  335 + * model.
337 336 ***************************************************************************/
338 337 GEnergy GModelSpectralComposite::mc(const GEnergy& emin,
339   - const GEnergy& emax,
340   - const GTime& time,
341   - GRan& ran) const
  338 + const GEnergy& emax,
  339 + const GTime& time,
  340 + GRan& ran) const
342 341 {
343 342 // Throw an exception if energy range is invalid
344 343 if (emin >= emax) {
... ... @@ -364,7 +363,6 @@ GEnergy GModelSpectralComposite::mc(const GEnergy&amp; emin,
364 363  
365 364 // Loop over spectral components and compute relative probabilites
366 365 for (int i = 0; i < m_mc_probs.size(); ++i) {
367   -
368 366 if (u <= m_mc_probs[i]) {
369 367 index = i;
370 368 break;
... ... @@ -392,7 +390,7 @@ void GModelSpectralComposite::read(const GXmlElement&amp; xml)
392 390 int n_spectrals = xml.elements("spectrum");
393 391  
394 392 // Loop over spectral elements
395   - for(int i = 0; i < n_spectrals; ++i) {
  393 + for (int i = 0; i < n_spectrals; ++i) {
396 394  
397 395 // Get spectral XML element
398 396 const GXmlElement* spec = xml.element("spectrum", i);
... ... @@ -495,49 +493,15 @@ void GModelSpectralComposite::write(GXmlElement&amp; xml) const
495 493  
496 494  
497 495 /***********************************************************************//**
498   - * @brief Print powerlaw information
499   - *
500   - * @param[in] chatter Chattiness (defaults to NORMAL).
501   - * @return String containing model information.
502   - ***************************************************************************/
503   -std::string GModelSpectralComposite::print(const GChatter& chatter) const
504   -{
505   - // Initialise result string
506   - std::string result;
507   -
508   - // Continue only if chatter is not silent
509   - if (chatter != SILENT) {
510   -
511   - // Append header
512   - result.append("=== GModelSpectralComposite ===");
513   -
514   - // Append information
515   - result.append("\n"+gammalib::parformat("Number of components"));
516   - result.append(gammalib::str(components()));
517   - result.append("\n"+gammalib::parformat("Number of parameters"));
518   - result.append(gammalib::str(size()));
519   -
520   - // Print parameter information
521   - for (int i = 0; i < size(); ++i) {
522   - result.append("\n"+m_pars[i]->print(chatter));
523   - }
524   -
525   - } // endif: chatter was not silent
526   -
527   - // Return result
528   - return result;
529   -}
530   -
531   -
532   -/***********************************************************************//**
533 496 * @brief Append spectral component
534 497 *
535   - * @param[in] spec Spectral model component
536   - * @param[in] name Name of spectral component (can be empty)
  498 + * @param[in] spec Spectral model component.
  499 + * @param[in] name Name of spectral component.
537 500 *
538 501 * Appends a spectral component to the composite model
539 502 ***************************************************************************/
540   -void GModelSpectralComposite::append(const GModelSpectral& spec, const std::string& name)
  503 +void GModelSpectralComposite::append(const GModelSpectral& spec,
  504 + const std::string& name)
541 505 {
542 506 // Append model container
543 507 m_spectral.push_back(spec.clone());
... ... @@ -546,15 +510,15 @@ void GModelSpectralComposite::append(const GModelSpectral&amp; spec, const std::stri
546 510 int index = m_spectral.size()-1;
547 511  
548 512 // Use model index if component name is empty
549   - std::string component_name = !name.empty() ? name : gammalib::str(m_spectral.size());
  513 + std::string component_name = !name.empty() ? name
  514 + : gammalib::str(m_spectral.size());
550 515  
551 516 // Check if component name is unique, throw exception if not
552 517 if (gammalib::contains(m_components, component_name)) {
553   - std::string msg =
554   - "Attempt to append component with name \""+component_name+"\" to composite"
555   - " spectral model container, but a component with the same name exists already.\n"
556   - "Every component in the container needs a unique name. On default the system will"
557   - "increment an integer if no component name is provided.";
  518 + std::string msg = "Attempt to append component \""+component_name+"\" "
  519 + "to composite spectral model, but a component with "
  520 + "the same name exists already. Each component needs "
  521 + "a unique name.";
558 522 throw GException::invalid_value(G_APPEND, msg);
559 523 }
560 524  
... ... @@ -577,6 +541,9 @@ void GModelSpectralComposite::append(const GModelSpectral&amp; spec, const std::stri
577 541 m_pars.push_back(par);
578 542  
579 543 } // endfor: loop over model parameters
  544 +
  545 + // Return
  546 + return;
580 547 }
581 548  
582 549  
... ... @@ -586,18 +553,21 @@ void GModelSpectralComposite::append(const GModelSpectral&amp; spec, const std::stri
586 553 * @param[in] index Index of spectral component.
587 554 * @return Spectral model.
588 555 *
  556 + * @exception GException::out_of_range
  557 + * Index is out of range.
  558 + *
589 559 * Returns a spectral component to the composite model
590 560 ***************************************************************************/
591 561 const GModelSpectral* GModelSpectralComposite::component(const int& index) const
592 562 {
593 563 // Check if index is in validity range
594 564 if (index >= m_spectral.size() || index < 0) {
595   - throw GException::out_of_range(G_COMPONENT_INDEX, "Component Index", index, m_spectral.size(),"");
  565 + throw GException::out_of_range(G_COMPONENT_INDEX, "Component Index",
  566 + index, m_spectral.size());
596 567 }
597 568  
598 569 // Return spectral component
599 570 return m_spectral[index];
600   -
601 571 }
602 572  
603 573  
... ... @@ -607,6 +577,9 @@ const GModelSpectral* GModelSpectralComposite::component(const int&amp; index) const
607 577 * @param[in] name Name of spectral component.
608 578 * @return Spectral model.
609 579 *
  580 + * @exception GException::invalid_argument
  581 + * Spectral model not found.
  582 + *
610 583 * Returns a spectral component of the composite model
611 584 ***************************************************************************/
612 585 const GModelSpectral* GModelSpectralComposite::component(const std::string& name) const
... ... @@ -622,7 +595,9 @@ const GModelSpectral* GModelSpectralComposite::component(const std::string&amp; name
622 595  
623 596 // Check if component name was found
624 597 if (index == -1) {
625   - throw GException::model_not_found(G_COMPONENT_NAME, name,"");
  598 + std::string msg = "Model component \""+name+"\" not found in composite "
  599 + "spectral model.";
  600 + throw GException::invalid_argument(G_COMPONENT_NAME, msg);
626 601 }
627 602  
628 603 // Return spectral component
... ... @@ -630,6 +605,42 @@ const GModelSpectral* GModelSpectralComposite::component(const std::string&amp; name
630 605  
631 606 }
632 607  
  608 +
  609 +/***********************************************************************//**
  610 + * @brief Print composite spectral model information
  611 + *
  612 + * @param[in] chatter Chattiness.
  613 + * @return String containing composite spectral model information.
  614 + ***************************************************************************/
  615 +std::string GModelSpectralComposite::print(const GChatter& chatter) const
  616 +{
  617 + // Initialise result string
  618 + std::string result;
  619 +
  620 + // Continue only if chatter is not silent
  621 + if (chatter != SILENT) {
  622 +
  623 + // Append header
  624 + result.append("=== GModelSpectralComposite ===");
  625 +
  626 + // Append information
  627 + result.append("\n"+gammalib::parformat("Number of components"));
  628 + result.append(gammalib::str(components()));
  629 + result.append("\n"+gammalib::parformat("Number of parameters"));
  630 + result.append(gammalib::str(size()));
  631 +
  632 + // Print parameter information
  633 + for (int i = 0; i < size(); ++i) {
  634 + result.append("\n"+m_pars[i]->print(chatter));
  635 + }
  636 +
  637 + } // endif: chatter was not silent
  638 +
  639 + // Return result
  640 + return result;
  641 +}
  642 +
  643 +
633 644 /*==========================================================================
634 645 = =
635 646 = Private methods =
... ... @@ -652,6 +663,7 @@ void GModelSpectralComposite::init_members(void)
652 663 m_mc_probs.clear();
653 664 m_mc_emin.clear();
654 665 m_mc_emax.clear();
  666 + m_mc_values.clear();
655 667 m_mc_flux = 0.0;
656 668  
657 669 // Return
... ... @@ -674,6 +686,7 @@ void GModelSpectralComposite::copy_members(const GModelSpectralComposite&amp; model)
674 686 m_mc_probs = model.m_mc_probs;
675 687 m_mc_emin = model.m_mc_emin;
676 688 m_mc_emax = model.m_mc_emax;
  689 + m_mc_values = model.m_mc_values;
677 690 m_mc_flux = model.m_mc_flux;
678 691  
679 692 // Copy pointer(s) of spectral component
... ... @@ -681,8 +694,10 @@ void GModelSpectralComposite::copy_members(const GModelSpectralComposite&amp; model)
681 694  
682 695 // Clear parameters and copy the pointers from the clone
683 696 m_pars.clear();
684   - for(int i = 0; i < model.components(); ++i) {
685   - m_spectral.push_back(model.m_spectral[i]->clone());
  697 + for (int i = 0; i < model.components(); ++i) {
  698 +
  699 + // Clone spectral component
  700 + m_spectral.push_back(model.m_spectral[i]->clone());
686 701  
687 702 // Retrieve spectral model
688 703 GModelSpectral* spec = m_spectral[i];
... ... @@ -711,7 +726,7 @@ void GModelSpectralComposite::copy_members(const GModelSpectralComposite&amp; model)
711 726 void GModelSpectralComposite::free_members(void)
712 727 {
713 728 // Free memory
714   - for(int i = 0; i < m_spectral.size(); ++i) {
  729 + for (int i = 0; i < m_spectral.size(); ++i) {
715 730  
716 731 // Delete component i
717 732 if (m_spectral[i] != NULL) delete m_spectral[i];
... ... @@ -734,13 +749,40 @@ void GModelSpectralComposite::free_members(void)
734 749 * Updates the precomputation cache for Monte Carlo simulations.
735 750 ***************************************************************************/
736 751 void GModelSpectralComposite::update_mc_cache(const GEnergy& emin,
737   - const GEnergy& emax) const
  752 + const GEnergy& emax) const
738 753  
739 754 {
740   - // Update cache if energy range has changed
741   - if (emin != m_mc_emin || emax != m_mc_emax) {
  755 + // Check if one of the parameters has changed. If the dimension of the
  756 + // parameter value cache differs from the number of parameters then notify
  757 + // a change. This will clear the cache and store the parameter values
  758 + // later
  759 + bool par_changed = (m_mc_values.size() != size());
  760 + if (par_changed == false) {
  761 + for (int i = 0; i < size(); ++i) {
  762 + if (m_pars[i]->value() != m_mc_values[i]) {
  763 + par_changed = true;
  764 + break;
  765 + }
  766 + }
  767 + }
  768 +
  769 + // Update cache if energy range or parameters have changed
  770 + if (par_changed || emin != m_mc_emin || emax != m_mc_emax) {
  771 +
  772 + // Store energy range
742 773 m_mc_emin = emin;
743 774 m_mc_emax = emax;
  775 +
  776 + // If parameters have changed then store the current parameter
  777 + // values for a comparison check for the next method call
  778 + if (par_changed) {
  779 + m_mc_values.clear();
  780 + for (int i = 0; i < size(); ++i) {
  781 + m_mc_values.push_back(m_pars[i]->value());
  782 + }
  783 + }
  784 +
  785 + // Compute MC flux
744 786 m_mc_flux = flux(m_mc_emin, m_mc_emax);
745 787  
746 788 // Initialise sum and probabilites
... ...