Commit 10f11c99e165ee48cd3438a04770bddc2ed08aac

Authored by Jürgen Knödlseder
2 parents 221a703e 89470207

Merge branch '1706-composite-models' into integration

# Conflicts:
#	AUTHORS
#	include/GTools.hpp
#	src/support/GTools.cpp
... ... @@ -16,4 +16,5 @@ Michael Mayer (michael.mayer@physik.hu-berlin.de)
16 16 Ellis Owen (Ellis.Owen@mpi-hd.mpg.de)
17 17 Anneli Schulz (anneli.schulz@desy.de)
18 18 Hubert Siejkowski (h.siejkowski@cyfronet.pl)
  19 +Domenico Tiziani (domenico.tiziani@fau.de)
19 20 Alexander Ziegler (alexander.ziegler@fau.de)
... ...
include/GModelSpatialComposite.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpatialPointSource.hpp - Spatial point source model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2016 by Domenico Tiziani *
  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 GModelSpatialComposite.hpp
  23 + * @brief Spatial composite model class interface definition
  24 + * @author Domenico Tiziani
  25 + */
  26 +
  27 +#ifndef GMODELSPATIALCOMPOSITE_HPP
  28 +#define GMODELSPATIALCOMPOSITE_HPP
  29 +
  30 +/* __ Includes ___________________________________________________________ */
  31 +#include <string>
  32 +#include "GModelSpatial.hpp"
  33 +#include "GModelPar.hpp"
  34 +#include "GSkyDir.hpp"
  35 +#include "GXmlElement.hpp"
  36 +
  37 +
  38 +/***********************************************************************//**
  39 + * @class GModelSpatialComposite
  40 + *
  41 + * @brief Spatial composite model
  42 + *
  43 + * This class implements the spatial model for a composition of spatial
  44 + * models.
  45 + ***************************************************************************/
  46 +class GModelSpatialComposite : public GModelSpatial {
  47 +
  48 +public:
  49 + // Constructors and destructors
  50 + GModelSpatialComposite(void);
  51 + GModelSpatialComposite(const bool& dummy, const std::string& type);
  52 + explicit GModelSpatialComposite(const GXmlElement& xml);
  53 + GModelSpatialComposite(const GModelSpatialComposite& model);
  54 + virtual ~GModelSpatialComposite(void);
  55 +
  56 + // Operators
  57 + virtual GModelSpatialComposite& operator=(const GModelSpatialComposite& model);
  58 +
  59 + // Implemented pure virtual methods
  60 + virtual void clear(void);
  61 + virtual GModelSpatialComposite* clone(void) const;
  62 + virtual std::string classname(void) const;
  63 + virtual std::string type(void) const;
  64 + virtual GClassCode code(void) const;
  65 + virtual double eval(const GPhoton& photon,
  66 + const bool& gradients = false) const;
  67 + virtual GSkyDir mc(const GEnergy& energy,
  68 + const GTime& time,
  69 + GRan& ran) const;
  70 + virtual double mc_norm(const GSkyDir& dir,
  71 + const double& radius) const;
  72 + virtual bool contains(const GSkyDir& dir,
  73 + const double& margin = 0.0) const;
  74 + virtual void read(const GXmlElement& xml);
  75 + virtual void write(GXmlElement& xml) const;
  76 + virtual std::string print(const GChatter& chatter = NORMAL) const;
  77 +
  78 + // Other methods
  79 + int components(void) const;
  80 + void append(const GModelSpatial& component,
  81 + const std::string& name = "");
  82 + const GModelSpatial* component(const int& index) const;
  83 + const GModelSpatial* component(const std::string& name) const;
  84 +
  85 +
  86 +protected:
  87 + // Protected methods
  88 + void init_members(void);
  89 + void copy_members(const GModelSpatialComposite& model);
  90 + void free_members(void);
  91 +
  92 + // Protected members
  93 + std::string m_type; //!< Model type
  94 + std::vector<GModelSpatial*> m_components; //!< Components
  95 + std::vector<std::string> m_component_names; //!< Component names
  96 +};
  97 +
  98 +
  99 +/***********************************************************************//**
  100 + * @brief Return class name
  101 + *
  102 + * @return String containing the class name ("GModelSpatialComposite").
  103 + ***************************************************************************/
  104 +inline
  105 +std::string GModelSpatialComposite::classname(void) const
  106 +{
  107 + return ("GModelSpatialComposite");
  108 +}
  109 +
  110 +
  111 +/***********************************************************************//**
  112 + * @brief Return model type
  113 + *
  114 + * @return Model type.
  115 + *
  116 + * Returns the type of the spatial model.
  117 + ***************************************************************************/
  118 +inline
  119 +std::string GModelSpatialComposite::type(void) const
  120 +{
  121 + return (m_type);
  122 +}
  123 +
  124 +
  125 +/***********************************************************************//**
  126 + * @brief Return class code
  127 + *
  128 + * @return GModelSpatialComposite.
  129 + *
  130 + * Returns the code GModelSpatialComposite of the class.
  131 + ***************************************************************************/
  132 +inline
  133 +GClassCode GModelSpatialComposite::code(void) const
  134 +{
  135 + return GMODEL_SPATIAL_COMPOSITE;
  136 +}
  137 +
  138 +
  139 +/***********************************************************************//**
  140 + * @brief Return normalization of composite source for Monte Carlo
  141 + * simulations
  142 + *
  143 + * @param[in] dir Centre of simulation cone.
  144 + * @param[in] radius Radius of simulation cone (degrees).
  145 + * @return Normalization.
  146 + *
  147 + * Returns unity.
  148 + ***************************************************************************/
  149 +inline
  150 +double GModelSpatialComposite::mc_norm(const GSkyDir& dir,
  151 + const double& radius) const
  152 +{
  153 + return 1.0;
  154 +}
  155 +
  156 +
  157 +/***********************************************************************//**
  158 + * @brief Return number of model components
  159 + *
  160 + * @return Number of model components.
  161 + ***************************************************************************/
  162 +inline
  163 +int GModelSpatialComposite::components(void) const
  164 +{
  165 + return m_components.size();
  166 +}
  167 +
  168 +#endif /* GMODELSPATIALCOMPOSITE_HPP */
... ...
include/GModelSpectralComposite.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpectralComposite.hpp - Spectral power law model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2016 by Michael Mayer *
  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 GModelSpectralComposite.hpp
  23 + * @brief Composite spectral model class interface definition
  24 + * @author Michael Mayer
  25 + */
  26 +
  27 +#ifndef GMODELSPECTRALCOMPOSITE_HPP
  28 +#define GMODELSPECTRALCOMPOSITE_HPP
  29 +
  30 +/* __ Includes ___________________________________________________________ */
  31 +#include <string>
  32 +#include "GModelSpectral.hpp"
  33 +#include "GModelPar.hpp"
  34 +#include "GEnergy.hpp"
  35 +
  36 +/* __ Forward declarations _______________________________________________ */
  37 +class GRan;
  38 +class GTime;
  39 +class GXmlElement;
  40 +
  41 +
  42 +/***********************************************************************//**
  43 + * @class GModelSpectralComposite
  44 + *
  45 + * @brief Composite spectral model class
  46 + *
  47 + * This class implements a composite spectrum. The model is defined by the sum
  48 + * of several individual spectral models. Each spectral model can be added via
  49 + * the XML interface or using the append() method.
  50 + *
  51 + ***************************************************************************/
  52 +class GModelSpectralComposite : public GModelSpectral {
  53 +
  54 +public:
  55 + // Constructors and destructors
  56 + GModelSpectralComposite(void);
  57 + explicit GModelSpectralComposite(const GXmlElement& xml);
  58 + GModelSpectralComposite(const GModelSpectralComposite& model);
  59 + virtual ~GModelSpectralComposite(void);
  60 +
  61 + // Operators
  62 + virtual GModelSpectralComposite& operator=(const GModelSpectralComposite& model);
  63 +
  64 + // Implemented pure virtual methods
  65 + virtual void clear(void);
  66 + virtual GModelSpectralComposite* clone(void) const;
  67 + virtual std::string classname(void) const;
  68 + virtual std::string type(void) const;
  69 + virtual double eval(const GEnergy& srcEng,
  70 + const GTime& srcTime = GTime(),
  71 + const bool& gradients = false) const;
  72 + virtual double flux(const GEnergy& emin,
  73 + const GEnergy& emax) const;
  74 + virtual double eflux(const GEnergy& emin,
  75 + const GEnergy& emax) const;
  76 + virtual GEnergy mc(const GEnergy& emin,
  77 + const GEnergy& emax,
  78 + const GTime& time,
  79 + GRan& ran) const;
  80 + virtual void read(const GXmlElement& xml);
  81 + virtual void write(GXmlElement& xml) const;
  82 + virtual std::string print(const GChatter& chatter = NORMAL) const;
  83 +
  84 + // Other methods
  85 + void append(const GModelSpectral& spec, const std::string& name="");
  86 + int components(void) const;
  87 + const GModelSpectral* component(const int& index) const;
  88 + const GModelSpectral* component(const std::string& name) const;
  89 +
  90 +protected:
  91 + // Protected methods
  92 + void init_members(void);
  93 + void copy_members(const GModelSpectralComposite& model);
  94 + void free_members(void);
  95 + void update_mc_cache(const GEnergy& emin, const GEnergy& emax) const;
  96 +
  97 + // Protected members
  98 + std::string m_type; //!< Model type
  99 + std::vector<GModelSpectral*> m_spectral; //!< Container of spectral models
  100 + std::vector<std::string> m_components; //!< Names of components
  101 +
  102 + // MC cache
  103 + mutable double m_mc_flux; //!< Flux cache
  104 + mutable std::vector<double> m_mc_probs; //!< Probailities of individual components
  105 + mutable GEnergy m_mc_emin; //!< Last minimum energy
  106 + mutable GEnergy m_mc_emax; //!< Last maximum energy
  107 +
  108 +};
  109 +
  110 +
  111 +/***********************************************************************//**
  112 + * @brief Return class name
  113 + *
  114 + * @return String containing the class name ("GModelSpectralComposite").
  115 + ***************************************************************************/
  116 +inline
  117 +std::string GModelSpectralComposite::classname(void) const
  118 +{
  119 + return ("GModelSpectralComposite");
  120 +}
  121 +
  122 +
  123 +/***********************************************************************//**
  124 + * @brief Return model type
  125 + *
  126 + * @return Model type.
  127 + *
  128 + * Returns the type of the spectral composite model.
  129 + ***************************************************************************/
  130 +inline
  131 +std::string GModelSpectralComposite::type(void) const
  132 +{
  133 + return (m_type);
  134 +}
  135 +
  136 +
  137 +/***********************************************************************//**
  138 + * @brief Return number of spectral components
  139 + *
  140 + * @return Number of model components.
  141 + *
  142 + * Returns the number of spectral components.
  143 + ***************************************************************************/
  144 +inline
  145 +int GModelSpectralComposite::components(void) const
  146 +{
  147 + return (m_spectral.size());
  148 +}
  149 +
  150 +
  151 +#endif /* GMODELSPECTRALCOMPOSITE_HPP */
... ...
include/GTools.hpp
... ... @@ -109,7 +109,7 @@ namespace gammalib {
109 109 bool is_notanumber(const double& x);
110 110 bool contains(const std::string& str,
111 111 const std::string& substring);
112   - bool contains(const std::vector<std::string>& strings,
  112 + bool contains(const std::vector<std::string> strings,
113 113 const std::string& string);
114 114 void warning(const std::string& origin,
115 115 const std::string& message);
... ...
include/GTypemaps.hpp
... ... @@ -43,7 +43,8 @@ typedef enum {
43 43 GMODEL_SPATIAL_POINT_SOURCE,
44 44 GMODEL_SPATIAL_RADIAL,
45 45 GMODEL_SPATIAL_ELLIPTICAL,
46   - GMODEL_SPATIAL_DIFFUSE
  46 + GMODEL_SPATIAL_DIFFUSE,
  47 + GMODEL_SPATIAL_COMPOSITE
47 48 } GClassCode;
48 49  
49 50 /* __ Typemaps ___________________________________________________________ */
... ...
include/GammaLib.hpp
... ... @@ -208,6 +208,7 @@
208 208 #include "GModelSpatialDiffuseConst.hpp"
209 209 #include "GModelSpatialDiffuseCube.hpp"
210 210 #include "GModelSpatialDiffuseMap.hpp"
  211 +#include "GModelSpatialComposite.hpp"
211 212 #include "GModelSpectral.hpp"
212 213 #include "GModelSpectralRegistry.hpp"
213 214 #include "GModelSpectralBrokenPlaw.hpp"
... ... @@ -223,6 +224,7 @@
223 224 #include "GModelSpectralPlaw.hpp"
224 225 #include "GModelSpectralPlawPhotonFlux.hpp"
225 226 #include "GModelSpectralPlawEnergyFlux.hpp"
  227 +#include "GModelSpectralComposite.hpp"
226 228 #include "GModelTemporal.hpp"
227 229 #include "GModelTemporalRegistry.hpp"
228 230 #include "GModelTemporalConst.hpp"
... ...
include/Makefile.am
... ... @@ -166,6 +166,7 @@ pkginclude_HEADERS = GammaLib.hpp \
166 166 GModelSpatialDiffuseConst.hpp \
167 167 GModelSpatialDiffuseCube.hpp \
168 168 GModelSpatialDiffuseMap.hpp \
  169 + GModelSpatialComposite.hpp \
169 170 GModelSpectral.hpp \
170 171 GModelSpectralRegistry.hpp \
171 172 GModelSpectralBrokenPlaw.hpp \
... ... @@ -181,6 +182,7 @@ pkginclude_HEADERS = GammaLib.hpp \
181 182 GModelSpectralPlaw.hpp \
182 183 GModelSpectralPlawPhotonFlux.hpp \
183 184 GModelSpectralPlawEnergyFlux.hpp \
  185 + GModelSpectralComposite.hpp \
184 186 GModelTemporal.hpp \
185 187 GModelTemporalRegistry.hpp \
186 188 GModelTemporalConst.hpp
... ...
inst/cta/include/GCTAResponseCube.hpp
... ... @@ -136,6 +136,9 @@ private:
136 136 double irf_diffuse(const GEvent& event,
137 137 const GSource& source,
138 138 const GObservation& obs) const;
  139 + double irf_composite(const GEvent& event,
  140 + const GSource& source,
  141 + const GObservation& obs) const;
139 142  
140 143 // Private data members
141 144 GCTACubeExposure m_exposure; //!< Exposure cube
... ...
inst/cta/include/GCTAResponseIrf.hpp
... ... @@ -176,6 +176,9 @@ private:
176 176 double irf_diffuse(const GEvent& event,
177 177 const GSource& source,
178 178 const GObservation& obs) const;
  179 + double irf_composite(const GEvent& event,
  180 + const GSource& source,
  181 + const GObservation& obs) const;
179 182 double nroi_ptsrc(const GModelSky& model,
180 183 const GEnergy& srcEng,
181 184 const GTime& srcTime,
... ... @@ -200,6 +203,12 @@ private:
200 203 const GEnergy& obsEng,
201 204 const GTime& obsTime,
202 205 const GObservation& obs) const;
  206 + double nroi_composite(const GModelSky& model,
  207 + const GEnergy& srcEng,
  208 + const GTime& srcTime,
  209 + const GEnergy& obsEng,
  210 + const GTime& obsTime,
  211 + const GObservation& obs) const;
203 212  
204 213 // Private data members
205 214 GCaldb m_caldb; //!< Calibration database
... ...
inst/cta/src/GCTAResponseCube.cpp
... ... @@ -40,6 +40,7 @@
40 40 #include "GModelSpatialRadial.hpp"
41 41 #include "GModelSpatialRadialShell.hpp"
42 42 #include "GModelSpatialElliptical.hpp"
  43 +#include "GModelSpatialComposite.hpp"
43 44 #include "GModelSpatialDiffuse.hpp"
44 45 #include "GPhoton.hpp"
45 46 #include "GSource.hpp"
... ... @@ -417,6 +418,9 @@ double GCTAResponseCube::irf(const GEvent&amp; event,
417 418 case GMODEL_SPATIAL_DIFFUSE:
418 419 irf = irf_diffuse(event, source, obs);
419 420 break;
  421 + case GMODEL_SPATIAL_COMPOSITE:
  422 + irf = irf_composite(event, source, obs);
  423 + break;
420 424 default:
421 425 break;
422 426 }
... ... @@ -1493,3 +1497,47 @@ double GCTAResponseCube::irf_diffuse(const GEvent&amp; event,
1493 1497 // Return IRF value
1494 1498 return irf;
1495 1499 }
  1500 +
  1501 +
  1502 +/***********************************************************************//**
  1503 + * @brief Return instrument response to composite source
  1504 + *
  1505 + * @param[in] event Observed event.
  1506 + * @param[in] source Source.
  1507 + * @param[in] obs Observation.
  1508 + * @return Instrument response to composite source.
  1509 + *
  1510 + * Returns the instrument response to a specified composite source.
  1511 + ***************************************************************************/
  1512 +double GCTAResponseCube::irf_composite(const GEvent& event,
  1513 + const GSource& source,
  1514 + const GObservation& obs) const
  1515 +{
  1516 + // Initialise IRF
  1517 + double irf = 0.0;
  1518 +
  1519 + // Get pointer to composite model
  1520 + const GModelSpatialComposite* model =
  1521 + dynamic_cast<const GModelSpatialComposite*>(source.model());
  1522 +
  1523 + // Loop over model components
  1524 + for (int i = 0; i < model->components(); ++i) {
  1525 +
  1526 + // Get pointer to spatial component
  1527 + GModelSpatial* spat = const_cast<GModelSpatial*>(model->component(i));
  1528 +
  1529 + // Create new GSource object
  1530 + GSource src(source.name(), spat, source.energy(), source.time());
  1531 +
  1532 + // Compute irf value
  1533 + irf += this->irf(event, source, obs);
  1534 +
  1535 + }
  1536 +
  1537 + // Divide by number of model components
  1538 + if (model->components() > 0) {
  1539 + irf /= double(model->components());
  1540 + }
  1541 +
  1542 + return irf;
  1543 +}
... ...
inst/cta/src/GCTAResponseIrf.cpp
... ... @@ -44,6 +44,7 @@
44 44 #include "GModelSpatialRadial.hpp"
45 45 #include "GModelSpatialRadialShell.hpp"
46 46 #include "GModelSpatialElliptical.hpp"
  47 +#include "GModelSpatialComposite.hpp"
47 48 #include "GCTAObservation.hpp"
48 49 #include "GCTAResponseIrf.hpp"
49 50 #include "GCTAResponse_helpers.hpp"
... ... @@ -431,6 +432,9 @@ double GCTAResponseIrf::irf(const GEvent&amp; event,
431 432 case GMODEL_SPATIAL_DIFFUSE:
432 433 irf = irf_diffuse(event, source, obs);
433 434 break;
  435 + case GMODEL_SPATIAL_COMPOSITE:
  436 + irf = irf_composite(event, source, obs);
  437 + break;
434 438 default:
435 439 break;
436 440 }
... ... @@ -1864,6 +1868,9 @@ double GCTAResponseIrf::nroi(const GModelSky&amp; model,
1864 1868 case GMODEL_SPATIAL_DIFFUSE:
1865 1869 nroi = nroi_diffuse(model, srcEng, srcTime, obsEng, obsTime, obs);
1866 1870 break;
  1871 + case GMODEL_SPATIAL_COMPOSITE:
  1872 + nroi = nroi_composite(model, srcEng, srcTime, obsEng, obsTime, obs);
  1873 + break;
1867 1874 default:
1868 1875 break;
1869 1876 }
... ... @@ -2846,6 +2853,51 @@ double GCTAResponseIrf::irf_diffuse(const GEvent&amp; event,
2846 2853  
2847 2854  
2848 2855 /***********************************************************************//**
  2856 + * @brief Return instrument response to composite source
  2857 + *
  2858 + * @param[in] event Observed event.
  2859 + * @param[in] source Source.
  2860 + * @param[in] obs Observation.
  2861 + * @return Instrument response to composite source.
  2862 + *
  2863 + * Returns the instrument response to a specified composite source.
  2864 + ***************************************************************************/
  2865 +double GCTAResponseIrf::irf_composite(const GEvent& event,
  2866 + const GSource& source,
  2867 + const GObservation& obs) const
  2868 +{
  2869 + // Initialise IRF
  2870 + double irf = 0.0;
  2871 +
  2872 + // Get pointer to composite model
  2873 + const GModelSpatialComposite* model =
  2874 + dynamic_cast<const GModelSpatialComposite*>(source.model());
  2875 +
  2876 + // Loop over model components
  2877 + for (int i = 0; i < model->components(); ++i) {
  2878 +
  2879 + // Get pointer to spatial component
  2880 + GModelSpatial* spat = const_cast<GModelSpatial*>(model->component(i));
  2881 +
  2882 + // Create new GSource object
  2883 + GSource src(source.name(), spat, source.energy(), source.time());
  2884 +
  2885 + // Compute irf value
  2886 + irf += this->irf(event, src, obs);
  2887 +
  2888 + }
  2889 +
  2890 + // Divide by number of model components
  2891 + if (model->components() > 0) {
  2892 + irf /= double(model->components());
  2893 + }
  2894 +
  2895 + // Return IRF value
  2896 + return irf;
  2897 +}
  2898 +
  2899 +
  2900 +/***********************************************************************//**
2849 2901 * @brief Return spatial integral of point source model
2850 2902 *
2851 2903 * @param[in] model Sky Model.
... ... @@ -3432,3 +3484,68 @@ double GCTAResponseIrf::nroi_diffuse(const GModelSky&amp; model,
3432 3484 // Return Nroi
3433 3485 return nroi;
3434 3486 }
  3487 +
  3488 +
  3489 +/***********************************************************************//**
  3490 + * @brief Return spatial integral of composite source model
  3491 + *
  3492 + * @param[in] model Sky Model.
  3493 + * @param[in] srcEng True photon energy.
  3494 + * @param[in] srcTime True photon arrival time.
  3495 + * @param[in] obsEng Observed event energy.
  3496 + * @param[in] obsTime Observed event arrival time.
  3497 + * @param[in] obs Observation.
  3498 + *
  3499 + * Computes the integral
  3500 + *
  3501 + * \f[
  3502 + * N_{\rm ROI}(E',t'|E,t) = \int_{\rm ROI} P(p',E',t'|E,t) dp'
  3503 + * \f]
  3504 + *
  3505 + * of
  3506 + *
  3507 + * \f[
  3508 + * P(p',E',t'|E,t) = \int
  3509 + * S(p,E,t) \times R(p',E',t'|p,E,t) \, dp
  3510 + * \f]
  3511 + *
  3512 + * over the Region of Interest (ROI) for a composite source model
  3513 + * \f$S(p,E,t)\f$ and the response function \f$R(p',E',t'|p,E,t)\f$.
  3514 + ***************************************************************************/
  3515 +double GCTAResponseIrf::nroi_composite(const GModelSky& model,
  3516 + const GEnergy& srcEng,
  3517 + const GTime& srcTime,
  3518 + const GEnergy& obsEng,
  3519 + const GTime& obsTime,
  3520 + const GObservation& obs) const
  3521 +{
  3522 + // Initialise nroi
  3523 + double nroi = 0.0;
  3524 +
  3525 + // Get composite model
  3526 + GModelSpatialComposite* comp =
  3527 + dynamic_cast<GModelSpatialComposite*>(model.spatial());
  3528 +
  3529 + // Loop over model components
  3530 + for (int i = 0; i < comp->components(); ++i) {
  3531 +
  3532 + // Create new sky model
  3533 + GModelSky sky = GModelSky(model);
  3534 +
  3535 + // Assign spatial part
  3536 + sky.spatial(comp->component(i));
  3537 +
  3538 + // Compute nroi
  3539 + nroi += this->nroi(sky, srcEng, srcTime, obsEng, obsTime, obs);
  3540 +
  3541 + }
  3542 +
  3543 + // Divide by number of model components
  3544 + if (comp->components() > 0) {
  3545 + nroi /= double(comp->components());
  3546 + }
  3547 +
  3548 + // Return nroi
  3549 + return nroi;
  3550 +
  3551 +}
... ...
pyext/GModelSpatialComposite.i 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpatialComposite.i - Spatial point source model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2016 by Domenico Tiziani *
  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 GModelSpatialComposite.i
  23 + * @brief Spatial composite model class Python interface
  24 + * @author Domenico Tiziani
  25 + */
  26 +%{
  27 +/* Put headers and other declarations here that are needed for compilation */
  28 +#include "GModelSpatialComposite.hpp"
  29 +%}
  30 +
  31 +
  32 +/***********************************************************************//**
  33 + * @class GModelSpatialComposite
  34 + *
  35 + * @brief Spatial composite model
  36 + ***************************************************************************/
  37 +class GModelSpatialComposite : public GModelSpatial {
  38 +
  39 +public:
  40 + // Constructors and destructors
  41 + GModelSpatialComposite(void);
  42 + explicit GModelSpatialComposite(const GXmlElement& xml);
  43 + GModelSpatialComposite(const GModelSpatialComposite& model);
  44 + virtual ~GModelSpatialComposite(void);
  45 +
  46 + // Implemented virtual methods
  47 + virtual void clear(void);
  48 + virtual GModelSpatialComposite* clone(void) const;
  49 + virtual std::string classname(void) const;
  50 + virtual std::string type(void) const;
  51 + virtual double eval(const GPhoton& photon,
  52 + const bool& gradients = false) const;
  53 + virtual GSkyDir mc(const GEnergy& energy,
  54 + const GTime& time,
  55 + GRan& ran) const;
  56 + virtual double mc_norm(const GSkyDir& dir,
  57 + const double& radius) const;
  58 + virtual bool contains(const GSkyDir& dir,
  59 + const double& margin = 0.0) const;
  60 + virtual void read(const GXmlElement& xml);
  61 + virtual void write(GXmlElement& xml) const;
  62 +
  63 + // Other methods
  64 + int components(void) const;
  65 + void append(const GModelSpatial& component,
  66 + const std::string& name = "");
  67 + const GModelSpatial* component(const int& index) const;
  68 + const GModelSpatial* component(const std::string& name) const;
  69 +};
  70 +
  71 +
  72 +/***********************************************************************//**
  73 + * @brief GModelSpatialComposite class extension
  74 + ***************************************************************************/
  75 +%extend GModelSpatialComposite {
  76 + GModelSpatialComposite copy() {
  77 + return (*self);
  78 + }
  79 +};
... ...
pyext/GModelSpectralComposite.i 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpectralComposite.i - Spectral power law model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2016 Michael Mayer *
  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 GModelSpecComposite spectral model class interface definition
  23 + * @author Michael Mayer
  24 + */
  25 +%{
  26 +/* Put headers and other declarations here that are needed for compilation */
  27 +#include "GModelSpectralComposite.hpp"
  28 +%}
  29 +
  30 +
  31 +/***********************************************************************//**
  32 + * @class GModelSpectralComposite
  33 + *
  34 + * @brief Composite spectral model class
  35 + ***************************************************************************/
  36 +class GModelSpectralComposite : public GModelSpectral {
  37 +public:
  38 + // Constructors and destructors
  39 + GModelSpectralComposite(void);
  40 + explicit GModelSpectralComposite(const GXmlElement& xml);
  41 + GModelSpectralComposite(const GModelSpectralComposite& model);
  42 + virtual ~GModelSpectralComposite(void);
  43 +
  44 + // Implemented pure virtual methods
  45 + virtual void clear(void);
  46 + virtual GModelSpectralComposite* clone(void) const;
  47 + virtual std::string classname(void) const;
  48 + virtual std::string type(void) const;
  49 + virtual double eval(const GEnergy& srcEng,
  50 + const GTime& srcTime = GTime(),
  51 + const bool& gradients = false) const;
  52 + virtual double flux(const GEnergy& emin,
  53 + const GEnergy& emax) const;
  54 + virtual double eflux(const GEnergy& emin,
  55 + const GEnergy& emax) const;
  56 + virtual GEnergy mc(const GEnergy& emin,
  57 + const GEnergy& emax,
  58 + const GTime& time,
  59 + GRan& ran) const;
  60 + virtual void read(const GXmlElement& xml);
  61 + virtual void write(GXmlElement& xml) const;
  62 +
  63 + // Other methods
  64 + void append(const GModelSpectral& spec, const std::string& name="");
  65 + int components(void) const;
  66 + GModelSpectral* component(const int& index) const;
  67 + GModelSpectral* component(const std::string& name) const;
  68 +
  69 +};
  70 +
  71 +
  72 +/***********************************************************************//**
  73 + * @brief GModelSpectralComposite class extension
  74 + ***************************************************************************/
  75 +%extend GModelSpectralComposite {
  76 + GModelSpectralComposite copy() {
  77 + return (*self);
  78 + }
  79 +};
... ...
pyext/gammalib/model.i
... ... @@ -141,6 +141,7 @@
141 141 %include "GModelSpatialDiffuseConst.i"
142 142 %include "GModelSpatialDiffuseCube.i"
143 143 %include "GModelSpatialDiffuseMap.i"
  144 +%include "GModelSpatialComposite.i"
144 145 %include "GModelSpectral.i"
145 146 %include "GModelSpectralRegistry.i"
146 147 %include "GModelSpectralBrokenPlaw.i"
... ... @@ -155,6 +156,7 @@
155 156 %include "GModelSpectralPlaw.i"
156 157 %include "GModelSpectralPlawPhotonFlux.i"
157 158 %include "GModelSpectralPlawEnergyFlux.i"
  159 +%include "GModelSpectralComposite.i"
158 160 %include "GModelTemporal.i"
159 161 %include "GModelTemporalRegistry.i"
160 162 %include "GModelTemporalConst.i"
... ...
src/model/GModelSky.cpp
... ... @@ -48,9 +48,11 @@
48 48 const GModelSky g_pointsource_seed("PointSource");
49 49 const GModelSky g_extendedsource_seed("ExtendedSource");
50 50 const GModelSky g_diffusesource_seed("DiffuseSource");
  51 +const GModelSky g_compositesource_seed("CompositeSource");
51 52 const GModelRegistry g_pointsource_registry(&g_pointsource_seed);
52 53 const GModelRegistry g_extendedsource_registry(&g_extendedsource_seed);
53 54 const GModelRegistry g_diffusesource_registry(&g_diffusesource_seed);
  55 +const GModelRegistry g_compositesource_registry(&g_compositesource_seed);
54 56  
55 57 /* __ Method name definitions ____________________________________________ */
56 58 #define G_NPRED "GModelSky::npred(GEnergy&, GTime&, GObservation&)"
... ...
src/model/GModelSpatialComposite.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpatialComposite.cpp - Spatial composite model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2016 by Domenico Tiziani *
  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 GModelSpatialComposite.cpp
  23 + * @brief Spatial composite model class implementation
  24 + * @author Domenico Tiziani
  25 + */
  26 +
  27 +/* __ Includes ___________________________________________________________ */
  28 +#ifdef HAVE_CONFIG_H
  29 +#include <config.h>
  30 +#endif
  31 +#include "GException.hpp"
  32 +#include "GTools.hpp"
  33 +#include "GMath.hpp"
  34 +#include "GModelSpatialComposite.hpp"
  35 +#include "GModelSpatialRegistry.hpp"
  36 +
  37 +/* __ Constants __________________________________________________________ */
  38 +
  39 +
  40 +/* __ Globals ____________________________________________________________ */
  41 +const GModelSpatialComposite g_spatial_comp_seed;
  42 +const GModelSpatialRegistry g_spatial_comp_registry(&g_spatial_comp_seed);
  43 +
  44 +/* __ Method name definitions ____________________________________________ */
  45 +#define G_READ "GModelSpatialComposite::read(GXmlElement&)"
  46 +#define G_WRITE "GModelSpatialComposite::write(GXmlElement&)"
  47 +#define G_COMPONENT_INDEX "GModelSpatialComposite::component(int&)"
  48 +#define G_COMPONENT_NAME "GModelSpatialComposite::component(std::string&)"
  49 +#define G_APPEND "GModelSpatialComposite::append(GModelSpatial&, "\
  50 + "std::string&)"
  51 +
  52 +/* __ Macros _____________________________________________________________ */
  53 +
  54 +/* __ Coding definitions _________________________________________________ */
  55 +
  56 +/* __ Debug definitions __________________________________________________ */
  57 +
  58 +
  59 +/*==========================================================================
  60 + = =
  61 + = Constructors/destructors =
  62 + = =
  63 + ==========================================================================*/
  64 +
  65 +/***********************************************************************//**
  66 + * @brief Void constructor
  67 + *
  68 + * Constructs empty spatial composite model.
  69 + ***************************************************************************/
  70 +GModelSpatialComposite::GModelSpatialComposite(void) : GModelSpatial()
  71 +{
  72 + // Initialise members
  73 + init_members();
  74 +
  75 + // Return
  76 + return;
  77 +}
  78 +
  79 +
  80 +/***********************************************************************//**
  81 + * @brief Model type constructor
  82 + *
  83 + * @param[in] dummy Dummy flag.
  84 + * @param[in] type Model type.
  85 + *
  86 + * Constructs empty spatial composite model by specifying a model @p type.
  87 + ***************************************************************************/
  88 +GModelSpatialComposite::GModelSpatialComposite(const bool& dummy,
  89 + const std::string& type) :
  90 + GModelSpatial()
  91 +{
  92 + // Initialise members
  93 + init_members();
  94 +
  95 + // Set model type
  96 + m_type = type;
  97 +
  98 + // Return
  99 + return;
  100 +}
  101 +
  102 +
  103 +/***********************************************************************//**
  104 + * @brief XML constructor
  105 + *
  106 + * @param[in] xml XML element.
  107 + *
  108 + * Construct a spatial composite model by extracting information from an
  109 + * XML element. See the read() method for more information about the expected
  110 + * structure of the XML element.
  111 + ***************************************************************************/
  112 +GModelSpatialComposite::GModelSpatialComposite(const GXmlElement& xml) :
  113 + GModelSpatial()
  114 +{
  115 + // Initialise members
  116 + init_members();
  117 +
  118 + // Read information from XML element
  119 + read(xml);
  120 +
  121 + // Return
  122 + return;
  123 +}
  124 +
  125 +
  126 +/***********************************************************************//**
  127 + * @brief Copy constructor
  128 + *
  129 + * @param[in] model Spatial composite model.
  130 + ***************************************************************************/
  131 +GModelSpatialComposite::GModelSpatialComposite(const GModelSpatialComposite& model) :
  132 + GModelSpatial(model)
  133 +{
  134 + // Initialise members
  135 + init_members();
  136 +
  137 + // Copy members
  138 + copy_members(model);
  139 +
  140 + // Return
  141 + return;
  142 +}
  143 +
  144 +
  145 +/***********************************************************************//**
  146 + * @brief Destructor
  147 + ***************************************************************************/
  148 +GModelSpatialComposite::~GModelSpatialComposite(void)
  149 +{
  150 + // Free members
  151 + free_members();
  152 +
  153 + // Return
  154 + return;
  155 +}
  156 +
  157 +
  158 +/*==========================================================================
  159 + = =
  160 + = Operators =
  161 + = =
  162 + ==========================================================================*/
  163 +
  164 +/***********************************************************************//**
  165 + * @brief Assignment operator
  166 + *
  167 + * @param[in] model Spatial composite model.
  168 + * @return Spatial composite model.
  169 + ***************************************************************************/
  170 +GModelSpatialComposite& GModelSpatialComposite::operator=(const GModelSpatialComposite& model)
  171 +{
  172 + // Execute only if object is not identical
  173 + if (this != &model) {
  174 +
  175 + // Copy base class members
  176 + this->GModelSpatial::operator=(model);
  177 +
  178 + // Free members
  179 + free_members();
  180 +
  181 + // Initialise members
  182 + init_members();
  183 +
  184 + // Copy members
  185 + copy_members(model);
  186 +
  187 + } // endif: object was not identical
  188 +
  189 + // Return
  190 + return *this;
  191 +}
  192 +
  193 +
  194 +/*==========================================================================
  195 + = =
  196 + = Public methods =
  197 + = =
  198 + ==========================================================================*/
  199 +
  200 +/***********************************************************************//**
  201 + * @brief Clear spatial composite model
  202 + ***************************************************************************/
  203 +void GModelSpatialComposite::clear(void)
  204 +{
  205 + // Free class members (base and derived classes, derived class first)
  206 + free_members();
  207 + this->GModelSpatial::free_members();
  208 +
  209 + // Initialise members
  210 + this->GModelSpatial::init_members();
  211 + init_members();
  212 +
  213 + // Return
  214 + return;
  215 +}
  216 +
  217 +
  218 +/***********************************************************************//**
  219 + * @brief Clone spatial composite model
  220 + *
  221 + * @return Pointer to deep copy of spatial composite model.
  222 + ***************************************************************************/
  223 +GModelSpatialComposite* GModelSpatialComposite::clone(void) const
  224 +{
  225 + // Clone point source model
  226 + return new GModelSpatialComposite(*this);
  227 +}
  228 +
  229 +
  230 +/***********************************************************************//**
  231 + * @brief Evaluate function
  232 + *
  233 + * @param[in] photon Incident photon.
  234 + * @param[in] gradients Compute gradients?
  235 + * @return Model value.
  236 + *
  237 + * Evaluates the spatial composite model by summing all model components and
  238 + * dividing the sum by the number of components.
  239 + ***************************************************************************/
  240 +double GModelSpatialComposite::eval(const GPhoton& photon,
  241 + const bool& gradients) const
  242 +{
  243 + // Initalise value
  244 + double value = 0.0;
  245 +
  246 + // Sum over all components
  247 + for (int i = 0; i < m_components.size(); ++i) {
  248 + value += m_components[i]->eval(photon, gradients);
  249 + }
  250 +
  251 + // Normalise sum by the number of components
  252 + if (m_components.size() > 0) {
  253 + value /= double(m_components.size());
  254 + }
  255 +
  256 + // Return value
  257 + return value;
  258 +}
  259 +
  260 +
  261 +/***********************************************************************//**
  262 + * @brief Returns MC sky direction
  263 + *
  264 + * @param[in] energy Photon energy.
  265 + * @param[in] time Photon arrival time.
  266 + * @param[in,out] ran Random number generator.
  267 + * @return Sky direction.
  268 + *
  269 + * Draws an arbitrary model component and an arbitrary direction from that
  270 + * component.
  271 + ***************************************************************************/
  272 +GSkyDir GModelSpatialComposite::mc(const GEnergy& energy,
  273 + const GTime& time,
  274 + GRan& ran) const
  275 +{
  276 + // Randomly choose one model component
  277 + int index = int(ran.uniform() * double(m_components.size()));
  278 + if (index >= m_components.size()) {
  279 + index = m_components.size();
  280 + }
  281 +
  282 + // Draw random sky direction from the selected component
  283 + GSkyDir sky_dir = m_components[index]->mc(energy, time, ran);
  284 +
  285 + // Return sky direction
  286 + return (sky_dir);
  287 +}
  288 +
  289 +
  290 +/***********************************************************************//**
  291 + * @brief Checks where model contains specified sky direction
  292 + *
  293 + * @param[in] dir Sky direction.
  294 + * @param[in] margin Margin to be added to sky direction (degrees)
  295 + * @return True if the model contains the sky direction.
  296 + *
  297 + * Signals whether a sky direction is contained in one of the
  298 + * model components.
  299 + ***************************************************************************/
  300 +bool GModelSpatialComposite::contains(const GSkyDir& dir,
  301 + const double& margin) const
  302 +{
  303 + // Initialise containment flag
  304 + bool containment = false;
  305 +
  306 + // Loop over all components
  307 + for (int i = 0; i < m_components.size(); ++i) {
  308 + if (m_components[i]->contains(dir, margin)) {
  309 + containment = true;
  310 + break;
  311 + }
  312 + }
  313 +
  314 + // Return containment
  315 + return containment;
  316 +}
  317 +
  318 +
  319 +/***********************************************************************//**
  320 + * @brief Read model from XML element
  321 + *
  322 + * @param[in] xml XML element.
  323 + *
  324 + * Reads the spatial information from an XML element.
  325 + ***************************************************************************/
  326 +void GModelSpatialComposite::read(const GXmlElement& xml)
  327 +{
  328 + // Get number of spatial components
  329 + int n_comp = xml.elements("spatialModel");
  330 +
  331 + // Loop over spatial elements
  332 + for (int i = 0; i < n_comp; ++i) {
  333 +
  334 + // Get spatial XML element
  335 + const GXmlElement* spec = xml.element("spatialModel", i);
  336 +
  337 + // Initialise a spatial registry object
  338 + GModelSpatialRegistry registry;
  339 +
  340 + // Read spatial model
  341 + GModelSpatial* ptr = registry.alloc(*spec);
  342 +
  343 + // Get component attribute from XML file
  344 + std::string component_name = spec->attribute("component");
  345 +
  346 + // Append spatial component to container
  347 + append(*ptr, component_name);
  348 +
  349 + } // endfor: loop over components
  350 +
  351 + // Return
  352 + return;
  353 +}
  354 +
  355 +
  356 +/***********************************************************************//**
  357 + * @brief Write model into XML element
  358 + *
  359 + * @param[in] xml XML element into which model information is written.
  360 + *
  361 + * @exception GException::model_invalid_spatial
  362 + * Existing XML element is not of type 'SkyDirFunction'
  363 + * @exception GException::model_invalid_parnum
  364 + * Invalid number of model parameters found in XML element.
  365 + * @exception GException::model_invalid_parnames
  366 + * Invalid model parameter names found in XML element.
  367 + *
  368 + * Write the spatial information into an XML element.
  369 + ***************************************************************************/
  370 +void GModelSpatialComposite::write(GXmlElement& xml) const
  371 +{
  372 + // Set model type
  373 + if (xml.attribute("type") == "") {
  374 + xml.attribute("type", type());
  375 + }
  376 +
  377 + // Verify model type
  378 + if (xml.attribute("type") != type()) {
  379 + throw GException::model_invalid_spatial(G_WRITE, xml.attribute("type"),
  380 + "Spatial model is not of type \""+type()+"\".");
  381 + }
  382 +
  383 + // Write all model components
  384 + for (int i = 0; i < m_components.size(); ++i) {
  385 +
  386 + // Get spatial component
  387 + GModelSpatial* component = m_components[i];
  388 +
  389 + // Fall through if component is empty
  390 + if (component == NULL) {
  391 + continue;
  392 + }
  393 +
  394 + // Find XML element with matching name
  395 + GXmlElement *matching_model = NULL;
  396 + for (int k = 0; k < xml.elements("spatialModel"); ++k) {
  397 + if (xml.element("spatialModel", k)->attribute("name") ==
  398 + m_component_names[i]) {
  399 + matching_model = xml.element("spatialModel", k);
  400 + break;
  401 + }
  402 + } // endfor: loop over all XML elements
  403 +
  404 + // Create copy of the spatial model
  405 + GModelSpatial* spatial = component->clone();
  406 +
  407 + // Loop over all parameters of component and strip prefix
  408 + for (int k = 0; k < spatial->size(); ++k) {
  409 +
  410 + // Get model parameter
  411 + GModelPar& par = (*spatial)[k];
  412 +
  413 + // If name contains colon then strip the prefix and the colon from
  414 + // the name
  415 + std::string name = par.name();
  416 + int found = name.find(":");
  417 + if (found != std::string::npos) {
  418 + name = name.substr(found+1, std::string::npos);
  419 + par.name(name);
  420 + }
  421 +
  422 + } // endfor looped over all parameters
  423 +
  424 + // If an XML element exists then use it ...
  425 + if (matching_model != NULL) {
  426 + spatial->write(*matching_model);
  427 + }
  428 +
  429 + // ... otherwise create new XML element
  430 + else {
  431 + GXmlElement element("spatialModel");
  432 + spatial->write(element);
  433 + xml.append(element);
  434 + }
  435 +
  436 + // Delete clone
  437 + delete spatial;
  438 +
  439 + } // endfor: loop over all components
  440 +
  441 + // TODO: Remove unused xml elements
  442 +
  443 + // Return
  444 + return;
  445 +}
  446 +
  447 +
  448 +/***********************************************************************//**
  449 + * @brief Append spatial component
  450 + *
  451 + * @param[in] component Spatial model component to append
  452 + * @param[in] name Name of spatial model (can be empty)
  453 + *
  454 + * Appends a spatial component to the composite model
  455 + ***************************************************************************/
  456 +void GModelSpatialComposite::append(const GModelSpatial& component,
  457 + const std::string& name)
  458 +{
  459 + // Append model container
  460 + m_components.push_back(component.clone());
  461 +
  462 + // Get index of latest model
  463 + int index = m_components.size()-1;
  464 +
  465 + // Use model index if component name is empty
  466 + std::string component_name = !name.empty() ? name
  467 + : gammalib::str(m_components.size());
  468 +
  469 + // Check if component name is unique, throw exception if not
  470 + if (gammalib::contains(m_component_names, component_name)) {
  471 + std::string msg = "Attempt to append component \""+component_name+"\" "
  472 + "to composite spatial model, but a component with the "
  473 + "same name exists already. Each component needs a "
  474 + "unique name.";
  475 + throw GException::invalid_value(G_APPEND, msg);
  476 + }
  477 +
  478 + // Add component name
  479 + m_component_names.push_back(component_name);
  480 +
  481 + // Get number of spectral parameters from model
  482 + int npars = m_components[index]->size();
  483 +
  484 + // Loop over model parameters
  485 + for (int ipar = 0; ipar < npars; ++ipar) {
  486 +
  487 + // Get model parameter
  488 + GModelPar* par = &(m_components[index]->operator[](ipar));
  489 +
  490 + // Modify parameter name
  491 + par->name(component_name+":"+par->name());
  492 +
  493 + // Append model parameter with new name to internal container
  494 + m_pars.push_back(par);
  495 +
  496 + } // endfor: loop over model parameters
  497 +
  498 + // Return
  499 + return;
  500 +}
  501 +
  502 +
  503 +/***********************************************************************//**
  504 + * @brief Returns pointer to spatial component element
  505 + *
  506 + * @param[in] index Index of spatial component [0,...,components()-1].
  507 + * @return Spatial model.
  508 + *
  509 + * @exception GException::out_of_range
  510 + * Index is out of range.
  511 + *
  512 + * Returns a spatial component to the composite model
  513 + ***************************************************************************/
  514 +const GModelSpatial* GModelSpatialComposite::component(const int& index) const
  515 +{
  516 + // Check if index is in validity range
  517 + if (index < 0 || index >= m_components.size()) {
  518 + throw GException::out_of_range(G_COMPONENT_INDEX, "Component Index",
  519 + index, m_components.size());
  520 + }
  521 +
  522 + // Return spatial component
  523 + return m_components[index];
  524 +}
  525 +
  526 +
  527 +/***********************************************************************//**
  528 + * @brief Returns pointer to specific spatial component
  529 + *
  530 + * @param[in] name Name of spatial component.
  531 + * @return Spatial model.
  532 + *
  533 + * @exception GException::invalid_argument
  534 + * Spatial model not found.
  535 + *
  536 + * Returns a spatial component of the composite model
  537 + ***************************************************************************/
  538 +const GModelSpatial* GModelSpatialComposite::component(const std::string& name) const
  539 +{
  540 + // Check if model name is found
  541 + int index = -1;
  542 + for (int i = 0; i < m_component_names.size(); ++i) {
  543 + if (m_component_names[i] == name) {
  544 + index = i;
  545 + break;
  546 + }
  547 + }
  548 +
  549 + // Check if component name was found
  550 + if (index == -1) {
  551 + std::string msg = "Model component \""+name+"\" not found in composite "
  552 + "spatial model.";
  553 + throw GException::invalid_argument(G_COMPONENT_NAME, msg);
  554 + }
  555 +
  556 + // Return spatial component
  557 + return m_components[index];
  558 +}
  559 +
  560 +
  561 +/***********************************************************************//**
  562 + * @brief Print composite spatial model information
  563 + *
  564 + * @param[in] chatter Chattiness.
  565 + * @return String containing composite spatial model information.
  566 + ***************************************************************************/
  567 +std::string GModelSpatialComposite::print(const GChatter& chatter) const
  568 +{
  569 + // Initialise result string
  570 + std::string result;
  571 +
  572 + // Continue only if chatter is not silent
  573 + if (chatter != SILENT) {
  574 +
  575 + // Append header
  576 + result.append("=== GModelSpatialComposite ===");
  577 +
  578 + // Append information
  579 + result.append("\n"+gammalib::parformat("Number of components"));
  580 + result.append(gammalib::str(components()));
  581 + result.append("\n"+gammalib::parformat("Number of parameters"));
  582 + result.append(gammalib::str(size()));
  583 +
  584 + // Print parameter information
  585 + for (int i = 0; i < size(); ++i) {
  586 + result.append("\n"+m_pars[i]->print(chatter));
  587 + }
  588 +
  589 + } // endif: chatter was not silent
  590 +
  591 + // Return result
  592 + return result;
  593 +}
  594 +
  595 +
  596 +/*==========================================================================
  597 + = =
  598 + = Private methods =
  599 + = =
  600 + ==========================================================================*/
  601 +
  602 +/***********************************************************************//**
  603 + * @brief Initialise class members
  604 + ***************************************************************************/
  605 +void GModelSpatialComposite::init_members(void)
  606 +{
  607 + // Initialise model type
  608 + m_type = "Composite";
  609 +
  610 + // Initialise models vector
  611 + m_components.clear();
  612 + m_component_names.clear();
  613 +
  614 + // Return
  615 + return;
  616 +}
  617 +
  618 +
  619 +/***********************************************************************//**
  620 + * @brief Copy class members
  621 + *
  622 + * @param[in] model Spatial composite model.
  623 + ***************************************************************************/
  624 +void GModelSpatialComposite::copy_members(const GModelSpatialComposite& model)
  625 +{
  626 + // Copy members
  627 + m_type = model.m_type;
  628 + m_component_names = model.m_component_names;
  629 +
  630 + // Initialise components
  631 + m_components.clear();
  632 + m_pars.clear();
  633 +
  634 + // Copy components
  635 + for (int i = 0; i < model.m_components.size(); ++i) {
  636 +
  637 + // Clone component
  638 + m_components.push_back(model.m_components[i]->clone());
  639 +
  640 + // Get number of parameters to append
  641 + int npars = m_components[i]->size();
  642 +
  643 + // Append parameter references
  644 + for (int ipar = 0; ipar < npars; ++ipar) {
  645 + GModelPar& par = (*m_components[i])[ipar];
  646 + m_pars.push_back(&par);
  647 + }
  648 +
  649 + } // endfor: looped over all components
  650 +
  651 + // Return
  652 + return;
  653 +}
  654 +
  655 +
  656 +/***********************************************************************//**
  657 + * @brief Delete class members
  658 + ***************************************************************************/
  659 +void GModelSpatialComposite::free_members(void)
  660 +{
  661 + // Free model components
  662 + for (int i = 0; i < m_components.size(); ++i) {
  663 +
  664 + // Delete component i
  665 + delete m_components[i];
  666 +
  667 + // Signal free pointer
  668 + m_components[i] = NULL;
  669 +
  670 + }
  671 +
  672 + // Return
  673 + return;
  674 +}
... ...
src/model/GModelSpatialEllipticalDisk.cpp
... ... @@ -599,7 +599,7 @@ void GModelSpatialEllipticalDisk::write(GXmlElement&amp; xml) const
599 599 /***********************************************************************//**
600 600 * @brief Print information
601 601 *
602   - * @param[in] chatter Chattiness (defaults to NORMAL).
  602 + * @param[in] chatter Chattiness.
603 603 * @return String containing model information.
604 604 ***************************************************************************/
605 605 std::string GModelSpatialEllipticalDisk::print(const GChatter& chatter) const
... ...
src/model/GModelSpatialPointSource.cpp
... ... @@ -501,6 +501,7 @@ void GModelSpatialPointSource::write(GXmlElement&amp; xml) const
501 501 /***********************************************************************//**
502 502 * @brief Print point source information
503 503 *
  504 + * @param[in] chatter Chattiness.
504 505 * @return String containing point source information.
505 506 ***************************************************************************/
506 507 std::string GModelSpatialPointSource::print(const GChatter& chatter) const
... ...
src/model/GModelSpectralComposite.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpectralComposite.cpp - Spectral composite model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2016 by Michael Mayer *
  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 GModelSpectralComposite.cpp
  23 + * @brief Composite spectral model class implementation
  24 + * @author Michael Mayer
  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 "GModelSpectralComposite.hpp"
  36 +#include "GModelSpectralRegistry.hpp"
  37 +
  38 +/* __ Constants __________________________________________________________ */
  39 +
  40 +/* __ Globals ____________________________________________________________ */
  41 +const GModelSpectralComposite g_spectral_comp_seed;
  42 +const GModelSpectralRegistry g_spectral_comp_registry(&g_spectral_comp_seed);
  43 +
  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&)"
  50 +
  51 +/* __ Macros _____________________________________________________________ */
  52 +
  53 +/* __ Coding definitions _________________________________________________ */
  54 +
  55 +/* __ Debug definitions __________________________________________________ */
  56 +
  57 +
  58 +/*==========================================================================
  59 + = =
  60 + = Constructors/destructors =
  61 + = =
  62 + ==========================================================================*/
  63 +
  64 +/***********************************************************************//**
  65 + * @brief Void constructor
  66 + ***************************************************************************/
  67 +GModelSpectralComposite::GModelSpectralComposite(void) : GModelSpectral()
  68 +{
  69 + // Initialise private members for clean destruction
  70 + init_members();
  71 +
  72 + // Return
  73 + return;
  74 +}
  75 +
  76 +
  77 +/***********************************************************************//**
  78 + * @brief XML constructor
  79 + *
  80 + * @param[in] xml XML element containing position information.
  81 + *
  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.
  85 + ***************************************************************************/
  86 +GModelSpectralComposite::GModelSpectralComposite(const GXmlElement& xml) : GModelSpectral()
  87 +{
  88 + // Initialise members
  89 + init_members();
  90 +
  91 + // Read information from XML element
  92 + read(xml);
  93 +
  94 + // Return
  95 + return;
  96 +}
  97 +
  98 +
  99 +/***********************************************************************//**
  100 + * @brief Copy constructor
  101 + *
  102 + * @param[in] model Spectral power law model.
  103 + ***************************************************************************/
  104 +GModelSpectralComposite::GModelSpectralComposite(const GModelSpectralComposite& model)
  105 + : GModelSpectral(model)
  106 +{
  107 + // Initialise members
  108 + init_members();
  109 +
  110 + // Copy members
  111 + copy_members(model);
  112 +
  113 + // Return
  114 + return;
  115 +}
  116 +
  117 +
  118 +/***********************************************************************//**
  119 + * @brief Destructor
  120 + ***************************************************************************/
  121 +GModelSpectralComposite::~GModelSpectralComposite(void)
  122 +{
  123 + // Free members
  124 + free_members();
  125 +
  126 + // Return
  127 + return;
  128 +}
  129 +
  130 +
  131 +/*==========================================================================
  132 + = =
  133 + = Operators =
  134 + = =
  135 + ==========================================================================*/
  136 +
  137 +/***********************************************************************//**
  138 + * @brief Assignment operator
  139 + *
  140 + * @param[in] model Spectral power law model.
  141 + * @return Spectral power law model.
  142 + ***************************************************************************/
  143 +GModelSpectralComposite& GModelSpectralComposite::operator=(const GModelSpectralComposite& model)
  144 +{
  145 + // Execute only if object is not identical
  146 + if (this != &model) {
  147 +
  148 + // Copy base class members
  149 + this->GModelSpectral::operator=(model);
  150 +
  151 + // Free members
  152 + free_members();
  153 +
  154 + // Initialise members
  155 + init_members();
  156 +
  157 + // Copy members
  158 + copy_members(model);
  159 +
  160 + } // endif: object was not identical
  161 +
  162 + // Return
  163 + return *this;
  164 +}
  165 +
  166 +
  167 +/*==========================================================================
  168 + = =
  169 + = Public methods =
  170 + = =
  171 + ==========================================================================*/
  172 +
  173 +/***********************************************************************//**
  174 + * @brief Clear spectral power law model
  175 + ***************************************************************************/
  176 +void GModelSpectralComposite::clear(void)
  177 +{
  178 + // Free class members (base and derived classes, derived class first)
  179 + free_members();
  180 + this->GModelSpectral::free_members();
  181 +
  182 + // Initialise members
  183 + this->GModelSpectral::init_members();
  184 + init_members();
  185 +
  186 + // Return
  187 + return;
  188 +}
  189 +
  190 +
  191 +/***********************************************************************//**
  192 + * @brief Clone spectral power law model
  193 + *
  194 + * @return Pointer to deep copy of spectral power law model.
  195 + ***************************************************************************/
  196 +GModelSpectralComposite* GModelSpectralComposite::clone(void) const
  197 +{
  198 + // Clone spectral power law model
  199 + return new GModelSpectralComposite(*this);
  200 +}
  201 +
  202 +
  203 +/***********************************************************************//**
  204 + * @brief Evaluate function
  205 + *
  206 + * @param[in] srcEng True photon energy.
  207 + * @param[in] srcTime True photon arrival time.
  208 + * @param[in] gradients Compute gradients?
  209 + * @return Model value (ph/cm2/s/MeV).
  210 + *
  211 + * Evaluates
  212 + *
  213 + * \f[
  214 + * \sum_{i=0}^{N} {M_{\rm i}}(\rm srcEng, srcTime)
  215 + * \f]
  216 + *
  217 + * where \f${M_{\rm i}}\f$ is the model evaluation of the i-th model
  218 + *
  219 + * 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.
  223 + ***************************************************************************/
  224 +double GModelSpectralComposite::eval(const GEnergy& srcEng,
  225 + const GTime& srcTime,
  226 + const bool& gradients) const
  227 +{
  228 + // Initialise result
  229 + double value = 0.0;
  230 +
  231 + // Loop over model components
  232 + for (int i = 0; i < m_spectral.size(); ++i) {
  233 +
  234 + // Add model component
  235 + value += m_spectral[i]->eval(srcEng, srcTime, gradients);
  236 +
  237 + } // endfor: loop over model components
  238 +
  239 + // Compile option: Check for NaN/Inf
  240 + #if defined(G_NAN_CHECK)
  241 + if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
  242 + std::cout << "*** ERROR: GModelSpectralComposite::eval";
  243 + std::cout << "(srcEng=" << srcEng;
  244 + std::cout << ", srcTime=" << srcTime << "):";
  245 + std::cout << " NaN/Inf encountered";
  246 + std::cout << " (value=" << value;
  247 + std::cout << ")" << std::endl;
  248 + }
  249 + #endif
  250 +
  251 + // Return
  252 + return value;
  253 +}
  254 +
  255 +
  256 +/***********************************************************************//**
  257 + * @brief Returns model photon flux between [emin, emax] (units: ph/cm2/s)
  258 + *
  259 + * @param[in] emin Minimum photon energy.
  260 + * @param[in] emax Maximum photon energy.
  261 + * @return Photon flux (ph/cm2/s).
  262 + *
  263 + * Computes the sum of all photon fluxes of each individual component
  264 + *
  265 + ***************************************************************************/
  266 +double GModelSpectralComposite::flux(const GEnergy& emin,
  267 + const GEnergy& emax) const
  268 +{
  269 + // Initialise flux
  270 + double flux = 0.0;
  271 +
  272 + // Compute only if integration range is valid
  273 + if (emin < emax) {
  274 +
  275 + // Loop over model components
  276 + for (int i = 0; i < m_spectral.size(); ++i) {
  277 +
  278 + // Add model component
  279 + flux += m_spectral[i]->flux(emin, emax);
  280 +
  281 + } // endfor: loop over model components
  282 +
  283 + } // endif: integration range was valid
  284 +
  285 + // Return flux
  286 + return flux;
  287 +}
  288 +
  289 +
  290 +/***********************************************************************//**
  291 + * @brief Returns model energy flux between [emin, emax] (units: erg/cm2/s)
  292 + *
  293 + * @param[in] emin Minimum photon energy.
  294 + * @param[in] emax Maximum photon energy.
  295 + * @return Energy flux (erg/cm2/s).
  296 + *
  297 + * Computes the sum of all energy fluxes of each individual component
  298 + *
  299 + ***************************************************************************/
  300 +double GModelSpectralComposite::eflux(const GEnergy& emin,
  301 + const GEnergy& emax) const
  302 +{
  303 + // Initialise eflux
  304 + double eflux = 0.0;
  305 +
  306 + // Compute only if integration range is valid
  307 + if (emin < emax) {
  308 +
  309 + // Loop over model components
  310 + for (int i = 0; i < m_spectral.size(); ++i) {
  311 +
  312 + // Add model component
  313 + eflux += m_spectral[i]->flux(emin, emax);
  314 +
  315 + } // endfor: loop over model components
  316 +
  317 + } // endif: integration range was valid
  318 +
  319 + // Return flux
  320 + return eflux;
  321 +}
  322 +
  323 +
  324 +/***********************************************************************//**
  325 + * @brief Returns Monte Carlo energy between [emin, emax]
  326 + *
  327 + * @param[in] emin Minimum photon energy.
  328 + * @param[in] emax Maximum photon energy.
  329 + * @param[in] time True photon arrival time.
  330 + * @param[in,out] ran Random number generator.
  331 + * @return Energy.
  332 + *
  333 + * @exception GException::erange_invalid
  334 + * Energy range is invalid (emin < emax required).
  335 + *
  336 + * Returns Monte Carlo energy by randomly drawing from a power law.
  337 + ***************************************************************************/
  338 +GEnergy GModelSpectralComposite::mc(const GEnergy& emin,
  339 + const GEnergy& emax,
  340 + const GTime& time,
  341 + GRan& ran) const
  342 +{
  343 + // Throw an exception if energy range is invalid
  344 + if (emin >= emax) {
  345 + throw GException::erange_invalid(G_MC, emin.MeV(), emax.MeV(),
  346 + "Minimum energy < maximum energy required.");
  347 + }
  348 +
  349 + // Throw exception if model container is empty
  350 + if (m_spectral.size() == 0) {
  351 + throw GException::runtime_error(G_MC,
  352 + "Composite spectral model is empty. It is required to have at"\
  353 + " least one spectral model to run simulations");
  354 + }
  355 +
  356 + // Update MC cache
  357 + update_mc_cache(emin, emax);
  358 +
  359 + // Get random value
  360 + double u = ran.uniform();
  361 +
  362 + // Initialise index of model to use for simulation
  363 + int index = 0;
  364 +
  365 + // Loop over spectral components and compute relative probabilites
  366 + for (int i = 0; i < m_mc_probs.size(); ++i) {
  367 +
  368 + if (u <= m_mc_probs[i]) {
  369 + index = i;
  370 + break;
  371 + }
  372 + }
  373 +
  374 + // Set energy
  375 + GEnergy energy = m_spectral[index]->mc(emin, emax, time, ran);
  376 +
  377 + // Return energy
  378 + return energy;
  379 +}
  380 +
  381 +
  382 +/***********************************************************************//**
  383 + * @brief Read model from XML element
  384 + *
  385 + * @param[in] xml XML element.
  386 + *
  387 + * Reads the spectral information from an XML element.
  388 + ***************************************************************************/
  389 +void GModelSpectralComposite::read(const GXmlElement& xml)
  390 +{
  391 + // Get number of spectral components
  392 + int n_spectrals = xml.elements("spectrum");
  393 +
  394 + // Loop over spectral elements
  395 + for(int i = 0; i < n_spectrals; ++i) {
  396 +
  397 + // Get spectral XML element
  398 + const GXmlElement* spec = xml.element("spectrum", i);
  399 +
  400 + // Initialise a spectral registry object
  401 + GModelSpectralRegistry registry;
  402 +
  403 + // Read spectral model
  404 + GModelSpectral* ptr = registry.alloc(*spec);
  405 +
  406 + // Get component attribute from XML file
  407 + std::string component_name = spec->attribute("component");
  408 +
  409 + // Append spectral component to container
  410 + append(*ptr, component_name);
  411 +
  412 + } // endfor: loop over components
  413 +
  414 + // Return
  415 + return;
  416 +}
  417 +
  418 +
  419 +/***********************************************************************//**
  420 + * @brief Write model into XML element
  421 + *
  422 + * @param[in] xml XML element.
  423 + *
  424 + * @exception GException::model_invalid_spectral
  425 + * Existing XML element is not of the expected type.
  426 + *
  427 + * Writes the spectral information into an XML element.
  428 + ***************************************************************************/
  429 +void GModelSpectralComposite::write(GXmlElement& xml) const
  430 +{
  431 + // Set model type
  432 + if (xml.attribute("type") == "") {
  433 + xml.attribute("type", type());
  434 + }
  435 +
  436 + // Verify model type
  437 + if (xml.attribute("type") != type()) {
  438 + throw GException::model_invalid_spectral(G_WRITE, xml.attribute("type"),
  439 + "Spectral model is not of type \""+type()+"\".");
  440 + }
  441 +
  442 + // Loop over model components
  443 + for(int i = 0; i < m_spectral.size(); i++) {
  444 +
  445 + // Write spectral model
  446 + if (m_spectral[i] != NULL) {
  447 +
  448 + // Create new spectrum node
  449 + xml.append(GXmlElement("spectrum"));
  450 +
  451 + // Get new spectrum node
  452 + GXmlElement* spec = xml.element("spectrum", xml.elements("spectrum")-1);
  453 +
  454 + // Create temporary copy of the spectral model
  455 + // This is a kluge to write out the original parameters.
  456 + GModelSpectral* cpy = m_spectral[i]->clone();
  457 +
  458 + // Loop over parameters of model
  459 + for (int j = 0; j < cpy->size(); ++j) {
  460 +
  461 + // Get model parameter and name
  462 + GModelPar& par = (*cpy)[j];
  463 + std::string parname = par.name();
  464 +
  465 + // Check if name contains colon
  466 + if (gammalib::contains(parname, ":")) {
  467 +
  468 + // Split at the colon
  469 + std::vector<std::string> splits = gammalib::split(parname, ":");
  470 +
  471 + // Use second part of the string to recover original parameter name
  472 + par.name(splits[1]);
  473 + }
  474 +
  475 + } // endfor: loop over parameters
  476 +
  477 + // Write spectral component
  478 + cpy->write(*spec);
  479 +
  480 + // Add component name if previously available
  481 + if (m_components[i] != gammalib::str(i+1)) {
  482 + spec->attribute("component", m_components[i]);
  483 + }
  484 +
  485 + // Remove temporary copy
  486 + delete cpy;
  487 +
  488 + } // endif: spectral model was not NULL
  489 +
  490 + } // endfor: loop over model components
  491 +
  492 + // Return
  493 + return;
  494 +}
  495 +
  496 +
  497 +/***********************************************************************//**
  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 + * @brief Append spectral component
  534 + *
  535 + * @param[in] spec Spectral model component
  536 + * @param[in] name Name of spectral component (can be empty)
  537 + *
  538 + * Appends a spectral component to the composite model
  539 + ***************************************************************************/
  540 +void GModelSpectralComposite::append(const GModelSpectral& spec, const std::string& name)
  541 +{
  542 + // Append model container
  543 + m_spectral.push_back(spec.clone());
  544 +
  545 + // Get index of latest model
  546 + int index = m_spectral.size()-1;
  547 +
  548 + // Use model index if component name is empty
  549 + std::string component_name = !name.empty() ? name : gammalib::str(m_spectral.size());
  550 +
  551 + // Check if component name is unique, throw exception if not
  552 + 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.";
  558 + throw GException::invalid_value(G_APPEND, msg);
  559 + }
  560 +
  561 + // Add component name (for now simple number)
  562 + m_components.push_back(component_name);
  563 +
  564 + // Get number of spectral parameters from model
  565 + int npars = m_spectral[index]->size();
  566 +
  567 + // Loop over model parameters
  568 + for (int ipar = 0; ipar < npars; ++ipar) {
  569 +
  570 + // Get model parameter
  571 + GModelPar* par = &(m_spectral[index]->operator[](ipar));
  572 +
  573 + // Modify parameter name
  574 + par->name(component_name+":"+par->name());
  575 +
  576 + // Append model parameter with new name to internal container
  577 + m_pars.push_back(par);
  578 +
  579 + } // endfor: loop over model parameters
  580 +}
  581 +
  582 +
  583 +/***********************************************************************//**
  584 + * @brief Returns spectral component element
  585 + *
  586 + * @param[in] index Index of spectral component.
  587 + * @return Spectral model.
  588 + *
  589 + * Returns a spectral component to the composite model
  590 + ***************************************************************************/
  591 +const GModelSpectral* GModelSpectralComposite::component(const int& index) const
  592 +{
  593 + // Check if index is in validity range
  594 + if (index >= m_spectral.size() || index < 0) {
  595 + throw GException::out_of_range(G_COMPONENT_INDEX, "Component Index", index, m_spectral.size(),"");
  596 + }
  597 +
  598 + // Return spectral component
  599 + return m_spectral[index];
  600 +
  601 +}
  602 +
  603 +
  604 +/***********************************************************************//**
  605 + * @brief Returns pointer to specific spectral component
  606 + *
  607 + * @param[in] name Name of spectral component.
  608 + * @return Spectral model.
  609 + *
  610 + * Returns a spectral component of the composite model
  611 + ***************************************************************************/
  612 +const GModelSpectral* GModelSpectralComposite::component(const std::string& name) const
  613 +{
  614 + // Check if model name is found
  615 + int index = -1;
  616 + for(int i = 0; i < m_components.size(); ++i) {
  617 + if (m_components[i] == name) {
  618 + index = i;
  619 + break;
  620 + }
  621 + }
  622 +
  623 + // Check if component name was found
  624 + if (index == -1) {
  625 + throw GException::model_not_found(G_COMPONENT_NAME, name,"");
  626 + }
  627 +
  628 + // Return spectral component
  629 + return m_spectral[index];
  630 +
  631 +}
  632 +
  633 +/*==========================================================================
  634 + = =
  635 + = Private methods =
  636 + = =
  637 + ==========================================================================*/
  638 +
  639 +/***********************************************************************//**
  640 + * @brief Initialise class members
  641 + ***************************************************************************/
  642 +void GModelSpectralComposite::init_members(void)
  643 +{
  644 + // Initialise model type
  645 + m_type = "Composite";
  646 +
  647 + // Clear spectral models
  648 + m_spectral.clear();
  649 + m_components.clear();
  650 +
  651 + // Clear MC cache
  652 + m_mc_probs.clear();
  653 + m_mc_emin.clear();
  654 + m_mc_emax.clear();
  655 + m_mc_flux = 0.0;
  656 +
  657 + // Return
  658 + return;
  659 +}
  660 +
  661 +
  662 +/***********************************************************************//**
  663 + * @brief Copy class members
  664 + *
  665 + * @param[in] model GModelSpectralComposite members which should be copied.
  666 + ***************************************************************************/
  667 +void GModelSpectralComposite::copy_members(const GModelSpectralComposite& model)
  668 +{
  669 + // Copy members
  670 + m_type = model.m_type;
  671 + m_components = model.m_components;
  672 +
  673 + // Copy MC cache
  674 + m_mc_probs = model.m_mc_probs;
  675 + m_mc_emin = model.m_mc_emin;
  676 + m_mc_emax = model.m_mc_emax;
  677 + m_mc_flux = model.m_mc_flux;
  678 +
  679 + // Copy pointer(s) of spectral component
  680 + m_spectral.clear();
  681 +
  682 + // Clear parameters and copy the pointers from the clone
  683 + m_pars.clear();
  684 + for(int i = 0; i < model.components(); ++i) {
  685 + m_spectral.push_back(model.m_spectral[i]->clone());
  686 +
  687 + // Retrieve spectral model
  688 + GModelSpectral* spec = m_spectral[i];
  689 +
  690 + // Loop over parameters and store pointers
  691 + for (int ipar = 0; ipar < spec->size(); ++ipar) {
  692 +
  693 + // Get model parameter reference
  694 + GModelPar& par = spec->operator[](ipar);
  695 +
  696 + // Append model parameter pointer to internal container
  697 + m_pars.push_back(&par);
  698 +
  699 + } // endfor: loop over parameters
  700 +
  701 + } // endfor: loop over spectral models
  702 +
  703 + // Return
  704 + return;
  705 +}
  706 +
  707 +
  708 +/***********************************************************************//**
  709 + * @brief Delete class members
  710 + ***************************************************************************/
  711 +void GModelSpectralComposite::free_members(void)
  712 +{
  713 + // Free memory
  714 + for(int i = 0; i < m_spectral.size(); ++i) {
  715 +
  716 + // Delete component i
  717 + if (m_spectral[i] != NULL) delete m_spectral[i];
  718 +
  719 + // Signal free pointer
  720 + m_spectral[i] = NULL;
  721 + }
  722 +
  723 + // Return
  724 + return;
  725 +}
  726 +
  727 +
  728 +/***********************************************************************//**
  729 + * @brief Update Monte Carlo pre computation cache
  730 + *
  731 + * @param[in] emin Minimum photon energy.
  732 + * @param[in] emax Maximum photon energy.
  733 + *
  734 + * Updates the precomputation cache for Monte Carlo simulations.
  735 + ***************************************************************************/
  736 +void GModelSpectralComposite::update_mc_cache(const GEnergy& emin,
  737 + const GEnergy& emax) const
  738 +
  739 +{
  740 + // Update cache if energy range has changed
  741 + if (emin != m_mc_emin || emax != m_mc_emax) {
  742 + m_mc_emin = emin;
  743 + m_mc_emax = emax;
  744 + m_mc_flux = flux(m_mc_emin, m_mc_emax);
  745 +
  746 + // Initialise sum and probabilites
  747 + double sum = 0.0;
  748 + m_mc_probs.clear();
  749 +
  750 + // Loop over spectral components and compute relative probabilites
  751 + for (int i = 0; i < m_spectral.size(); ++i) {
  752 +
  753 + // Relative probability
  754 + double prob = m_spectral[i]->flux(emin, emax) / m_mc_flux;
  755 +
  756 + // Add probability
  757 + m_mc_probs.push_back(prob + sum);
  758 +
  759 + // Increment sum
  760 + sum += prob;
  761 +
  762 + } //endfor: looped over spectral components
  763 +
  764 + } // endif: emin and emax have changed
  765 +
  766 + // Return
  767 + return;
  768 +}
... ...
src/model/Makefile.am
... ... @@ -45,6 +45,7 @@ sources = GModelPar.cpp \
45 45 GModelSpatialDiffuseConst.cpp \
46 46 GModelSpatialDiffuseCube.cpp \
47 47 GModelSpatialDiffuseMap.cpp \
  48 + GModelSpatialComposite.cpp \
48 49 GModelSpectral.cpp \
49 50 GModelSpectralRegistry.cpp \
50 51 GModelSpectralBrokenPlaw.cpp \
... ... @@ -60,6 +61,7 @@ sources = GModelPar.cpp \
60 61 GModelSpectralPlaw.cpp \
61 62 GModelSpectralPlawPhotonFlux.cpp \
62 63 GModelSpectralPlawEnergyFlux.cpp \
  64 + GModelSpectralComposite.cpp \
63 65 GModelTemporal.cpp \
64 66 GModelTemporalRegistry.cpp \
65 67 GModelTemporalConst.cpp \
... ...
src/obs/GResponse.cpp
... ... @@ -43,7 +43,6 @@
43 43 #include "GEbounds.hpp" // will become obsolete
44 44 #include "GObservation.hpp"
45 45 #include "GModelSky.hpp"
46   -#include "GModelSpatialPointSource.hpp"
47 46  
48 47 /* __ Method name definitions ____________________________________________ */
49 48 #define G_IRF_RADIAL "GResponse::irf_radial(GEvent&, GSource&,"\
... ... @@ -322,9 +321,8 @@ double GResponse::eval_prob(const GModelSky&amp; model,
322 321  
323 322 // Set source
324 323 GSource source(model.name(), model.spatial(), srcEng, srcTime);
325   -
326   - // Get IRF value. This method returns the spatial component of the
327   - // source model.
  324 +
  325 + // Compute IRF value
328 326 double irf = this->irf(event, source, obs);
329 327  
330 328 // If required, apply instrument specific model scaling
... ...
src/support/GTools.cpp
... ... @@ -1180,7 +1180,7 @@ bool gammalib::contains(const std::string&amp; str, const std::string&amp; substring)
1180 1180 bool result = false;
1181 1181  
1182 1182 // checks if substring is in str
1183   - if (str.find(substring) != std::string::npos){
  1183 + if (str.find(substring) != std::string::npos) {
1184 1184 result = true;
1185 1185 }
1186 1186  
... ... @@ -1193,13 +1193,13 @@ bool gammalib::contains(const std::string&amp; str, const std::string&amp; substring)
1193 1193 * @brief Checks if a string is contained in a vector of strings
1194 1194 *
1195 1195 * @param[in] strings Vector of strings you want to search in.
1196   - * @param[in] string String you are looking for in strings.
  1196 + * @param[in] string string you are looking for in strings.
1197 1197 * @return True if a string is contained a vector.
1198 1198 *
1199 1199 * Checks if a string is contained in a vector of strings
1200 1200 ***************************************************************************/
1201   -bool gammalib::contains(const std::vector<std::string>& strings,
1202   - const std::string& string)
  1201 +bool gammalib::contains(const std::vector<std::string> strings,
  1202 + const std::string& string)
1203 1203 {
1204 1204 // Compute result
1205 1205 bool result = std::find(strings.begin(), strings.end(), string) !=
... ...
test/data/model_spatial_composite.xml 0 → 100644
  1 +<?xml version="1.0" standalone="no"?>
  2 +<source_library title="source library">
  3 + <source name="Crab" type="CompositeSource">
  4 + <spectrum type="PowerLaw">
  5 + <parameter name="Prefactor" scale="1e-16" value="5.7" min="1e-07" max="1000.0" free="1"/>
  6 + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="+5.0" free="1"/>
  7 + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/>
  8 + </spectrum>
  9 + <spatialModel type="Composite">
  10 + <spatialModel type="PointSource" component="PointSource">
  11 + <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
  12 + <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
  13 + </spatialModel>
  14 + <spatialModel type="RadialGaussian">
  15 + <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
  16 + <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
  17 + <parameter name="Sigma" scale="1.0" value="0.20" min="0.01" max="10" free="1"/>
  18 + </spatialModel>
  19 + </spatialModel>
  20 + </source>
  21 +</source_library>
... ...
test/data/model_spectral_composite.xml 0 → 100644
  1 +<?xml version="1.0" standalone="no"?>
  2 +<source_library title="source library">
  3 + <source name="Crab" type="PointSource">
  4 + <spectrum type="Composite">
  5 + <spectrum type="PowerLaw" component="SoftComponent">
  6 + <parameter name="Prefactor" scale="1e-17" value="3" min="1e-07" max="1000.0" free="1"/>
  7 + <parameter name="Index" scale="-1" value="3.5" min="0.0" max="+5.0" free="1"/>
  8 + <parameter name="PivotEnergy" scale="1e6" value="1" min="0.01" max="1000.0" free="0"/>
  9 + </spectrum>
  10 + <spectrum type="PowerLaw" component="HardComponent">
  11 + <parameter name="Prefactor" scale="1e-17" value="5" min="1e-07" max="1000.0" free="1"/>
  12 + <parameter name="Index" scale="-1" value="2.0" min="0.0" max="+5.0" free="1"/>
  13 + <parameter name="PivotEnergy" scale="1e6" value="1" min="0.01" max="1000.0" free="0"/>
  14 + </spectrum>
  15 + </spectrum>
  16 + <spatialModel type="PointSource">
  17 + <parameter free="0" max="360" min="-360" name="RA" scale="1" value="83.6331" />
  18 + <parameter free="0" max="90" min="-90" name="DEC" scale="1" value="22.0145" />
  19 + </spatialModel>
  20 + </source>
  21 +</source_library>
... ...
test/test_GModel.cpp
... ... @@ -67,6 +67,7 @@ void TestGModel::set(void)
67 67 m_xml_point_multiplicative = datadir + "/model_point_multiplicative.xml";
68 68 m_xml_model_point_nodes = datadir + "/model_point_nodes.xml";
69 69 m_xml_model_point_filefct = datadir + "/model_point_filefct.xml";
  70 + m_xml_model_spectral_composite = datadir + "/model_spectral_composite.xml";
70 71 m_xml_model_diffuse_const = datadir + "/model_diffuse_const.xml";
71 72 m_xml_model_diffuse_cube = datadir + "/model_diffuse_cube.xml";
72 73 m_xml_model_diffuse_map = datadir + "/model_diffuse_map.xml";
... ... @@ -75,6 +76,7 @@ void TestGModel::set(void)
75 76 m_xml_model_radial_shell = datadir + "/model_radial_shell.xml";
76 77 m_xml_model_elliptical_disk = datadir + "/model_elliptical_disk.xml";
77 78 m_xml_model_elliptical_gauss = datadir + "/model_elliptical_gauss.xml";
  79 + m_xml_model_spatial_composite = datadir + "/model_spatial_composite.xml";
78 80  
79 81 // Set legacy model definition XML files
80 82 m_xml_legacy_radial_disk = datadir + "/legacy_radial_disk.xml";
... ... @@ -116,6 +118,8 @@ void TestGModel::set(void)
116 118 "Test GModelSpatialDiffuseCube");
117 119 append(static_cast<pfunction>(&TestGModel::test_diffuse_map),
118 120 "Test GModelSpatialDiffuseMap");
  121 + append(static_cast<pfunction>(&TestGModel::test_spatial_composite),
  122 + "Test GModelSpatialComposite");
119 123 append(static_cast<pfunction>(&TestGModel::test_spatial_model),
120 124 "Test spatial model XML I/O");
121 125  
... ... @@ -146,6 +150,8 @@ void TestGModel::set(void)
146 150 "Test GModelSpectralNodes");
147 151 append(static_cast<pfunction>(&TestGModel::test_filefct),
148 152 "Test GModelSpectralFunc");
  153 + append(static_cast<pfunction>(&TestGModel::test_spectral_composite),
  154 + "Test GModelSpectralComposite");
149 155 append(static_cast<pfunction>(&TestGModel::test_spectral_model),
150 156 "Test spectral model XML I/O");
151 157  
... ... @@ -1402,6 +1408,49 @@ void TestGModel::test_elliptical_gauss(void)
1402 1408 }
1403 1409  
1404 1410  
  1411 +/***********************************************************************//**
  1412 + * @brief Test GModelSpatialComposite class
  1413 + ***************************************************************************/
  1414 +void TestGModel::test_spatial_composite(void)
  1415 +{
  1416 + // Test void constructor
  1417 + GModelSpatialComposite model1;
  1418 + test_value(model1.type(), "Composite", "Check void model type");
  1419 +
  1420 + // Set sky direction
  1421 + GSkyDir dir = GSkyDir();
  1422 + dir.radec_deg(83.6331, 22.01);
  1423 +
  1424 + // Test append method
  1425 + model1.append(GModelSpatialPointSource(dir));
  1426 + model1.append(GModelSpatialRadialGauss(dir, 0.2));
  1427 + test_value(model1.components(), 2);
  1428 + test_value(model1.size(), 5);
  1429 +
  1430 + // Test XML constructor
  1431 + GXml xml(m_xml_model_spatial_composite);
  1432 + GXmlElement* element = xml.element(0)->element(0)->element("spatialModel", 0);
  1433 + GModelSpatialComposite model2(*element);
  1434 + test_value(model2.size(), 5);
  1435 + test_value(model2.type(), "Composite", "Check model type");
  1436 +
  1437 + // Test access of individual parameters
  1438 + test_value(model2["2:RA"].value(), 83.6331);
  1439 + test_value(model2["2:DEC"].value(), 22.0145);
  1440 + test_value(model2["2:Sigma"].value(), 0.2);
  1441 + test_value(model2["PointSource:RA"].value(), 83.6331);
  1442 + test_value(model2["2:RA"].value(), 83.6331);
  1443 + model2["2:RA"].value(83.1331);
  1444 + test_value(model2["2:RA"].value(), 83.1331);
  1445 + model2["2:DEC"].value(22.51);
  1446 + test_value(model2["2:DEC"].value(), 22.51);
  1447 + model2["2:Sigma"].value(0.6);
  1448 + test_value(model2["2:Sigma"].value(), 0.6);
  1449 +
  1450 + // Exit test
  1451 + return;
  1452 +}
  1453 +
1405 1454  
1406 1455 /***********************************************************************//**
1407 1456 * @brief Test GModelSpectralConst class
... ... @@ -2194,6 +2243,51 @@ void TestGModel::test_filefct(void)
2194 2243 return;
2195 2244 }
2196 2245  
  2246 +/***********************************************************************//**
  2247 + * @brief Test GModelSpectralComposite class
  2248 + ***************************************************************************/
  2249 +void TestGModel::test_spectral_composite(void)
  2250 +{
  2251 + // Test void constructor
  2252 + GModelSpectralComposite model1;
  2253 + test_value(model1.type(), "Composite", "Check void model type");
  2254 +
  2255 + // Test append method
  2256 + model1.append(GModelSpectralPlaw(3e-17,-3.5, GEnergy(1, "TeV")));
  2257 + model1.append(GModelSpectralPlaw(5e-17,-2.0, GEnergy(1, "TeV")));
  2258 + test_value(model1.size(), 6);
  2259 + test_value(model1.components(), 2);
  2260 + test_value(model1.eval(GEnergy(1.0, "TeV")), 8.0e-17);
  2261 +
  2262 + // Test XML constructor
  2263 + GXml xml(m_xml_model_spectral_composite);
  2264 + GXmlElement* element = xml.element(0)->element(0)->element("spectrum", 0);
  2265 + GModelSpectralComposite model2(*element);
  2266 + test_value(model2.size(), 6);
  2267 + test_value(model2.components(), 2);
  2268 + test_value(model2.type(), "Composite", "Check model type");
  2269 +
  2270 + // Test access of individual parameters
  2271 + test_value(model2["HardComponent:Prefactor"].value(), 5e-17);
  2272 + test_value(model2["HardComponent:Index"].value(), -2.0);
  2273 + test_value(model2["HardComponent:PivotEnergy"].value(), 1.0e6);
  2274 +
  2275 + // Test prefactor method
  2276 + model2["SoftComponent:Prefactor"].value(2.3e-16);
  2277 + test_value(model2["SoftComponent:Prefactor"].value(), 2.3e-16);
  2278 +
  2279 + // Test index method
  2280 + model2["SoftComponent:Index"].value(-2.6);
  2281 + test_value(model2["SoftComponent:Index"].value(), -2.6);
  2282 +
  2283 + // Test pivot method
  2284 + model2["SoftComponent:PivotEnergy"].value(0.5e6);
  2285 + test_value(model2["SoftComponent:PivotEnergy"].value(), 0.5e6);
  2286 +
  2287 + // Exit test
  2288 + return;
  2289 +}
  2290 +
2197 2291  
2198 2292 /***********************************************************************//**
2199 2293 * @brief Test GModelTemporalConst class
... ... @@ -2297,6 +2391,7 @@ void TestGModel::test_spectral_model(void)
2297 2391 test_xml_model("GModelSpectralLogParabola", m_xml_model_point_logparabola);
2298 2392 test_xml_model("GModelSpectralNodes", m_xml_model_point_nodes);
2299 2393 test_xml_model("GModelSpectralFunc", m_xml_model_point_filefct);
  2394 + test_xml_model("GModelSpectralComposite", m_xml_model_spectral_composite);
2300 2395  
2301 2396 // Return
2302 2397 return;
... ...
test/test_GModel.hpp
... ... @@ -58,6 +58,7 @@ public:
58 58 void test_radial_shell(void);
59 59 void test_elliptical_disk(void);
60 60 void test_elliptical_gauss(void);
  61 + void test_spatial_composite(void);
61 62 void test_spatial_model(void);
62 63 void test_const(void);
63 64 void test_gauss(void);
... ... @@ -72,6 +73,7 @@ public:
72 73 void test_multiplicative(void);
73 74 void test_nodes(void);
74 75 void test_filefct(void);
  76 + void test_spectral_composite(void);
75 77 void test_spectral_model(void);
76 78 void test_temp_const(void);
77 79 void test_model(void);
... ... @@ -115,6 +117,7 @@ private:
115 117 std::string m_xml_point_multiplicative;
116 118 std::string m_xml_model_point_nodes;
117 119 std::string m_xml_model_point_filefct;
  120 + std::string m_xml_model_spectral_composite;
118 121 std::string m_xml_model_diffuse_const;
119 122 std::string m_xml_model_diffuse_cube;
120 123 std::string m_xml_model_diffuse_map;
... ... @@ -123,6 +126,7 @@ private:
123 126 std::string m_xml_model_radial_shell;
124 127 std::string m_xml_model_elliptical_disk;
125 128 std::string m_xml_model_elliptical_gauss;
  129 + std::string m_xml_model_spatial_composite;
126 130  
127 131 // Legacy model definition XML files
128 132 std::string m_xml_legacy_radial_disk;
... ...