Commit 6173b98f34b03eb388f7e5666c6302b35ba3132f

Authored by Pierrick Martin
1 parent d0d0e2e4

Implemented ring spatial model

include/GModelSpatialRadialRing.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpatialRadialRing.hpp - Radial ring source model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2011-2016 by Pierrick Martin *
  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 GModelSpatialRadialRing.hpp
  23 + * @brief Radial ring model class interface definition
  24 + * @author Pierrick Martin
  25 + */
  26 +
  27 +#ifndef GMODELSPATIALRADIALRING_HPP
  28 +#define GMODELSPATIALRADIALRING_HPP
  29 +
  30 +/* __ Includes ___________________________________________________________ */
  31 +#include <string>
  32 +#include "GModelSpatialRadial.hpp"
  33 +#include "GModelPar.hpp"
  34 +#include "GSkyDir.hpp"
  35 +#include "GSkyRegionCircle.hpp"
  36 +#include "GXmlElement.hpp"
  37 +
  38 +
  39 +/**************************************************************************
  40 + * @class GModelSpatialRadialRing
  41 + *
  42 + * @brief Ring source model class
  43 + *
  44 + * This class implements the spatial component of the factorised source
  45 + * model for a ring source, i.e. constant surface brightness between an
  46 + * inner radius and an outer radius, and no emission elsewhere.
  47 + ***************************************************************************/
  48 +class GModelSpatialRadialRing : public GModelSpatialRadial {
  49 +
  50 +public:
  51 + // Constructors and destructors
  52 + GModelSpatialRadialRing(void);
  53 + GModelSpatialRadialRing(const bool& dummy, const std::string& type);
  54 + GModelSpatialRadialRing(const GSkyDir& dir, const double& radius, const double& width);
  55 + explicit GModelSpatialRadialRing(const GXmlElement& xml);
  56 + GModelSpatialRadialRing(const GModelSpatialRadialRing& model);
  57 + virtual ~GModelSpatialRadialRing(void);
  58 +
  59 + // Operators
  60 + virtual GModelSpatialRadialRing& operator=(const GModelSpatialRadialRing& model);
  61 +
  62 + // Implemented pure virtual base class methods
  63 + virtual void clear(void);
  64 + virtual GModelSpatialRadialRing* clone(void) const;
  65 + virtual std::string classname(void) const;
  66 + virtual std::string type(void) const;
  67 + virtual double eval(const double& theta,
  68 + const GEnergy& energy,
  69 + const GTime& time,
  70 + const bool& gradients = false) const;
  71 + virtual GSkyDir mc(const GEnergy& energy,
  72 + const GTime& time,
  73 + GRan& ran) const;
  74 + virtual bool contains(const GSkyDir& dir,
  75 + const double& margin = 0.0) const;
  76 + virtual double theta_max(void) const;
  77 + virtual double theta_min(void) const;
  78 + virtual GSkyRegion* region(void) const;
  79 + virtual void read(const GXmlElement& xml);
  80 + virtual void write(GXmlElement& xml) const;
  81 + virtual std::string print(const GChatter& chatter = NORMAL) const;
  82 +
  83 + // Other methods
  84 + double radius(void) const;
  85 + void radius(const double& radius);
  86 + double width(void) const;
  87 + void width(const double& width);
  88 +
  89 +protected:
  90 + // Protected methods
  91 + void init_members(void);
  92 + void copy_members(const GModelSpatialRadialRing& model);
  93 + void free_members(void);
  94 + void update(void) const;
  95 + void set_region(void) const;
  96 +
  97 + // Protected members
  98 + std::string m_type; //!< Model type
  99 + GModelPar m_radius; //!< Ring inner radius (degrees)
  100 + GModelPar m_width; //!< Ring width (degrees)
  101 + mutable GSkyRegionCircle m_region; //!< Bounding circle
  102 +
  103 + // Cached members used for pre-computations
  104 + mutable double m_last_radius; //!< Last ring radius
  105 + mutable double m_last_width; //!< Last ring width
  106 + mutable double m_inner_radius_rad; //!< Inner radius in radians
  107 + mutable double m_outer_radius_rad; //!< Outer radius in radians
  108 + mutable double m_width_rad; //!< Ring width in radians
  109 + mutable double m_norm; //!< Normalization
  110 +};
  111 +
  112 +
  113 +/***********************************************************************//**
  114 + * @brief Return class name
  115 + *
  116 + * @return String containing the class name ("GModelSpatialRadialRing").
  117 + ***************************************************************************/
  118 +inline
  119 +std::string GModelSpatialRadialRing::classname(void) const
  120 +{
  121 + return ("GModelSpatialRadialRing");
  122 +}
  123 +
  124 +
  125 +/***********************************************************************//**
  126 + * @brief Return model type
  127 + *
  128 + * @return Model type.
  129 + *
  130 + * Returns the type of the radial ring model.
  131 + ***************************************************************************/
  132 +inline
  133 +std::string GModelSpatialRadialRing::type(void) const
  134 +{
  135 + return (m_type);
  136 +}
  137 +
  138 +
  139 +/***********************************************************************//**
  140 + * @brief Return ring outer radius
  141 + *
  142 + * @return Ring outer radius (degrees).
  143 + *
  144 + * Returns the outer radius of the ring in degrees.
  145 + ***************************************************************************/
  146 +inline
  147 +double GModelSpatialRadialRing::radius(void) const
  148 +{
  149 + return (m_radius.value());
  150 +}
  151 +
  152 +
  153 +/***********************************************************************//**
  154 + * @brief Set ring outer radius
  155 + *
  156 + * @param[in] Ring outer radius (degrees).
  157 + *
  158 + * Sets the outer radius of the ring in degrees.
  159 + ***************************************************************************/
  160 +inline
  161 +void GModelSpatialRadialRing::radius(const double& radius)
  162 +{
  163 + m_radius.value(radius);
  164 + return;
  165 +}
  166 +
  167 +
  168 +/***********************************************************************//**
  169 + * @brief Return ring width
  170 + *
  171 + * @return Ring width (degrees).
  172 + *
  173 + * Returns the width of the ring in degrees.
  174 + ***************************************************************************/
  175 +inline
  176 +double GModelSpatialRadialRing::width(void) const
  177 +{
  178 + return (m_width.value());
  179 +}
  180 +
  181 +
  182 +/***********************************************************************//**
  183 + * @brief Set ring width
  184 + *
  185 + * @param[in] Ring width (degrees).
  186 + *
  187 + * Sets the width of the ring in degrees.
  188 + ***************************************************************************/
  189 +inline
  190 +void GModelSpatialRadialRing::width(const double& width)
  191 +{
  192 + m_width.value(width);
  193 + return;
  194 +}
  195 +
  196 +/***********************************************************************//**
  197 + * @brief Return boundary sky region
  198 + *
  199 + * @return Boundary sky region.
  200 + *
  201 + * Returns a sky region that fully encloses the spatial model component.
  202 + ***************************************************************************/
  203 +inline
  204 +GSkyRegion* GModelSpatialRadialRing::region(void) const
  205 +{
  206 + set_region();
  207 + return (&m_region);
  208 +}
  209 +
  210 +#endif /* GMODELSPATIALRADIALRING_HPP */
include/GammaLib.hpp
@@ -207,6 +207,7 @@ @@ -207,6 +207,7 @@
207 #include "GModelSpatialRadialDisk.hpp" 207 #include "GModelSpatialRadialDisk.hpp"
208 #include "GModelSpatialRadialGauss.hpp" 208 #include "GModelSpatialRadialGauss.hpp"
209 #include "GModelSpatialRadialShell.hpp" 209 #include "GModelSpatialRadialShell.hpp"
  210 +#include "GModelSpatialRadialRing.hpp"
210 #include "GModelSpatialRadialProfile.hpp" 211 #include "GModelSpatialRadialProfile.hpp"
211 #include "GModelSpatialRadialProfileGauss.hpp" 212 #include "GModelSpatialRadialProfileGauss.hpp"
212 #include "GModelSpatialRadialProfileDMBurkert.hpp" 213 #include "GModelSpatialRadialProfileDMBurkert.hpp"
include/Makefile.am
@@ -165,6 +165,7 @@ pkginclude_HEADERS = GammaLib.hpp \ @@ -165,6 +165,7 @@ pkginclude_HEADERS = GammaLib.hpp \
165 GModelSpatialRadialDisk.hpp \ 165 GModelSpatialRadialDisk.hpp \
166 GModelSpatialRadialGauss.hpp \ 166 GModelSpatialRadialGauss.hpp \
167 GModelSpatialRadialShell.hpp \ 167 GModelSpatialRadialShell.hpp \
  168 + GModelSpatialRadialRing.hpp \
168 GModelSpatialRadialProfile.hpp \ 169 GModelSpatialRadialProfile.hpp \
169 GModelSpatialRadialProfileGauss.hpp \ 170 GModelSpatialRadialProfileGauss.hpp \
170 GModelSpatialRadialProfileDMBurkert.hpp \ 171 GModelSpatialRadialProfileDMBurkert.hpp \
pyext/GModelSpatialRadialRing.i 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpatialRadialRing.i - Radial disk source model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2011-2020 by Pierrick Martin *
  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 GModelSpatialRadialRing.i
  23 + * @brief Radial ring model class Python interface definition
  24 + * @author Pierrick Martin
  25 + */
  26 +%{
  27 +/* Put headers and other declarations here that are needed for compilation */
  28 +#include "GModelSpatialRadialRing.hpp"
  29 +%}
  30 +
  31 +/**************************************************************************
  32 + * @class GModelSpatialRadialRing
  33 + *
  34 + * @brief Ring source model class
  35 + *
  36 + * This class implements the spatial component of the factorised source
  37 + * model for a ring source, i.e. constant surface brightness between an
  38 + * inner radius and an outer radius, and no emission elsewhere.
  39 + ***************************************************************************/
  40 +class GModelSpatialRadialRing : public GModelSpatialRadial {
  41 +
  42 +public:
  43 + // Constructors and destructors
  44 + GModelSpatialRadialRing(void);
  45 + GModelSpatialRadialRing(const GSkyDir& dir, const double& radius, const double& width);
  46 + explicit GModelSpatialRadialRing(const GXmlElement& xml);
  47 + GModelSpatialRadialRing(const GModelSpatialRadialRing& model);
  48 + virtual ~GModelSpatialRadialRing(void);
  49 +
  50 + // Implemented pure virtual methods
  51 + virtual void clear(void);
  52 + virtual GModelSpatialRadialRing* clone(void) const;
  53 + virtual std::string classname(void) const;
  54 + virtual std::string type(void) const;
  55 + virtual double eval(const double& theta,
  56 + const GEnergy& energy,
  57 + const GTime& time,
  58 + const bool& gradients = false) const;
  59 + virtual GSkyDir mc(const GEnergy& energy,
  60 + const GTime& time,
  61 + GRan& ran) const;
  62 + virtual bool contains(const GSkyDir& dir,
  63 + const double& margin = 0.0) const;
  64 + virtual double theta_max(void) const;
  65 + virtual double theta_min(void) const;
  66 + virtual GSkyRegion* region(void) const;
  67 + virtual void read(const GXmlElement& xml);
  68 + virtual void write(GXmlElement& xml) const;
  69 +
  70 + // Other methods
  71 + double radius(void) const;
  72 + void radius(const double& radius);
  73 + double width(void) const;
  74 + void width(const double& width);
  75 +};
  76 +
  77 +
  78 +/***********************************************************************//**
  79 + * @brief GModelSpatialRadialRing class extension
  80 + *
  81 + * The eval(GPhoton&, bool&) method need to be defined in the extension to
  82 + * force swig to build also the interface for these methods that are
  83 + * implemented in the base class only. It's not clear to me why these
  84 + * methods are not inherited automatically. Maybe this could also be handled
  85 + * by a %typemap(typecheck) construct.
  86 + ***************************************************************************/
  87 +%extend GModelSpatialRadialRing {
  88 + GModelSpatialRadialRing copy() {
  89 + return (*self);
  90 + }
  91 + double eval(const GPhoton& photon) const {
  92 + return self->GModelSpatialRadial::eval(photon);
  93 + }
  94 + double eval(const GPhoton& photon, const bool& gradients) const {
  95 + return self->GModelSpatialRadial::eval(photon, gradients);
  96 + }
  97 +%pythoncode {
  98 + def __getstate__(self):
  99 + xml = gammalib.GXmlElement()
  100 + self.write(xml)
  101 + state = (xml,)
  102 + return state
  103 + def __setstate__(self, state):
  104 + self.__init__(state[0])
  105 +}
  106 +};
pyext/gammalib/model.i
@@ -170,6 +170,7 @@ @@ -170,6 +170,7 @@
170 %include "GModelSpatialPointSource.i" 170 %include "GModelSpatialPointSource.i"
171 %include "GModelSpatialRadial.i" 171 %include "GModelSpatialRadial.i"
172 %include "GModelSpatialRadialDisk.i" 172 %include "GModelSpatialRadialDisk.i"
  173 +%include "GModelSpatialRadialRing.i"
173 %include "GModelSpatialRadialGauss.i" 174 %include "GModelSpatialRadialGauss.i"
174 %include "GModelSpatialRadialShell.i" 175 %include "GModelSpatialRadialShell.i"
175 %include "GModelSpatialRadialProfile.i" 176 %include "GModelSpatialRadialProfile.i"
src/model/GModelSpatialRadialRing.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * GModelSpatialRadialRing.cpp - Radial ring source model class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2011-2018 by Pierrick Martin *
  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 GModelSpatialRadialRing.cpp
  23 + * @brief Radial ring model class implementation
  24 + * @author Pierrick Martin
  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 "GModelSpatialRadialRing.hpp"
  35 +#include "GModelSpatialRegistry.hpp"
  36 +
  37 +/* __ Constants __________________________________________________________ */
  38 +
  39 +/* __ Globals ____________________________________________________________ */
  40 +const GModelSpatialRadialRing g_radial_ring_seed;
  41 +const GModelSpatialRegistry g_radial_ring_registry(&g_radial_ring_seed);
  42 +#if defined(G_LEGACY_XML_FORMAT)
  43 +const GModelSpatialRadialRing g_radial_ring_legacy_seed(true, "RingFunction");
  44 +const GModelSpatialRegistry g_radial_ring_legacy_registry(&g_radial_ring_legacy_seed);
  45 +#endif
  46 +
  47 +/* __ Method name definitions ____________________________________________ */
  48 +#define G_READ "GModelSpatialRadialRing::read(GXmlElement&)"
  49 +#define G_WRITE "GModelSpatialRadialRing::write(GXmlElement&)"
  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 + * Constructs empty radial ring model.
  68 + ***************************************************************************/
  69 +GModelSpatialRadialRing::GModelSpatialRadialRing(void) : GModelSpatialRadial()
  70 +{
  71 + // Initialise members
  72 + init_members();
  73 +
  74 + // Return
  75 + return;
  76 +}
  77 +
  78 +
  79 +/***********************************************************************//**
  80 + * @brief Model type constructor
  81 + *
  82 + * @param[in] dummy Dummy flag.
  83 + * @param[in] type Model type.
  84 + *
  85 + * Constructs empty radial ring model by specifying a model @p type.
  86 + ***************************************************************************/
  87 +GModelSpatialRadialRing::GModelSpatialRadialRing(const bool& dummy,
  88 + const std::string& type) :
  89 + GModelSpatialRadial()
  90 +{
  91 + // Initialise members
  92 + init_members();
  93 +
  94 + // Set model type
  95 + m_type = type;
  96 +
  97 + // Return
  98 + return;
  99 +}
  100 +
  101 +
  102 +/***********************************************************************//**
  103 + * @brief Ring constructor
  104 + *
  105 + * @param[in] dir Sky position of ring centre.
  106 + * @param[in] radius Ring outer radius (degrees).
  107 + * @param[in] width Ring width (degrees).
  108 + *
  109 + * Constructs radial ring model from the sky position of the ring centre
  110 + * (@p dir) and the ring outer radius @p radius and width
  111 + * @p width in degrees.
  112 + ***************************************************************************/
  113 +GModelSpatialRadialRing::GModelSpatialRadialRing(const GSkyDir& dir,
  114 + const double& radius,
  115 + const double& width) :
  116 + GModelSpatialRadial()
  117 +{
  118 + // Initialise members
  119 + init_members();
  120 +
  121 + // Assign center location
  122 + this->dir(dir);
  123 +
  124 + // Assign radius and width after check
  125 + if (width <= radius) {
  126 + this->radius(radius);
  127 + this->width(width);
  128 + } else {
  129 + this->radius(radius);
  130 + this->width(radius);
  131 + }
  132 +
  133 + // Return
  134 + return;
  135 +}
  136 +
  137 +
  138 +/***********************************************************************//**
  139 + * @brief XML constructor
  140 + *
  141 + * @param[in] xml XML element.
  142 + *
  143 + * Creates instance of radial ring model by extracting information from an
  144 + * XML element. See the read() method for more information about the expected
  145 + * structure of the XML element.
  146 + ***************************************************************************/
  147 +GModelSpatialRadialRing::GModelSpatialRadialRing(const GXmlElement& xml) :
  148 + GModelSpatialRadial()
  149 +{
  150 + // Initialise members
  151 + init_members();
  152 +
  153 + // Read information from XML element
  154 + read(xml);
  155 +
  156 + // Return
  157 + return;
  158 +}
  159 +
  160 +
  161 +/***********************************************************************//**
  162 + * @brief Copy constructor
  163 + *
  164 + * @param[in] model Radial ring model.
  165 + ***************************************************************************/
  166 +GModelSpatialRadialRing::GModelSpatialRadialRing(const GModelSpatialRadialRing& model) :
  167 + GModelSpatialRadial(model)
  168 +{
  169 + // Initialise members
  170 + init_members();
  171 +
  172 + // Copy members
  173 + copy_members(model);
  174 +
  175 + // Return
  176 + return;
  177 +}
  178 +
  179 +
  180 +/***********************************************************************//**
  181 + * @brief Destructor
  182 + ***************************************************************************/
  183 +GModelSpatialRadialRing::~GModelSpatialRadialRing(void)
  184 +{
  185 + // Free members
  186 + free_members();
  187 +
  188 + // Return
  189 + return;
  190 +}
  191 +
  192 +
  193 +/*==========================================================================
  194 + = =
  195 + = Operators =
  196 + = =
  197 + ==========================================================================*/
  198 +
  199 +/***********************************************************************//**
  200 + * @brief Assignment operator
  201 + *
  202 + * @param[in] model Radial ring model.
  203 + * @return Radial ring model.
  204 + ***************************************************************************/
  205 +GModelSpatialRadialRing& GModelSpatialRadialRing::operator=(const GModelSpatialRadialRing& model)
  206 +{
  207 + // Execute only if object is not identical
  208 + if (this != &model) {
  209 +
  210 + // Copy base class members
  211 + this->GModelSpatialRadial::operator=(model);
  212 +
  213 + // Free members
  214 + free_members();
  215 +
  216 + // Initialise members
  217 + init_members();
  218 +
  219 + // Copy members
  220 + copy_members(model);
  221 +
  222 + } // endif: object was not identical
  223 +
  224 + // Return
  225 + return *this;
  226 +}
  227 +
  228 +
  229 +/*==========================================================================
  230 + = =
  231 + = Public methods =
  232 + = =
  233 + ==========================================================================*/
  234 +
  235 +/***********************************************************************//**
  236 + * @brief Clear radial ring model
  237 + ***************************************************************************/
  238 +void GModelSpatialRadialRing::clear(void)
  239 +{
  240 + // Free class members (base and derived classes, derived class first)
  241 + free_members();
  242 + this->GModelSpatialRadial::free_members();
  243 + this->GModelSpatial::free_members();
  244 +
  245 + // Initialise members
  246 + this->GModelSpatial::init_members();
  247 + this->GModelSpatialRadial::init_members();
  248 + init_members();
  249 +
  250 + // Return
  251 + return;
  252 +}
  253 +
  254 +
  255 +/***********************************************************************//**
  256 + * @brief Clone radial ring model
  257 + *
  258 + * @return Pointer to deep copy of radial ring model.
  259 + ***************************************************************************/
  260 +GModelSpatialRadialRing* GModelSpatialRadialRing::clone(void) const
  261 +{
  262 + // Clone radial ring model
  263 + return new GModelSpatialRadialRing(*this);
  264 +}
  265 +
  266 +
  267 +/***********************************************************************//**
  268 + * @brief Evaluate function (in units of sr^-1)
  269 + *
  270 + * @param[in] theta Angular distance from ring centre (radians).
  271 + * @param[in] energy Photon energy.
  272 + * @param[in] time Photon arrival time.
  273 + * @param[in] gradients Compute gradients?
  274 + * @return Model value.
  275 + *
  276 + * Evaluates the spatial component for a ring source model using
  277 + *
  278 + * \f[
  279 + * S_{\rm p}(\vec{p} | E, t) = \left \{
  280 + * \begin{array}{l l}
  281 + * \displaystyle
  282 + * {\tt m\_norm}
  283 + * & \mbox{if $\theta \le $ outer radius and $\theta \ge $ inner radius} \\
  284 + * \\
  285 + * \displaystyle
  286 + * 0 & \mbox{if $\theta > $ outer radius or $\theta < $ inner radius}
  287 + * \end{array}
  288 + * \right .
  289 + * \f]
  290 + *
  291 + * where
  292 + * - \f$\theta\f$ is the angular separation between ring centre and the
  293 + * sky direction of interest, and
  294 + * - \f${\tt m\_norm} = \frac{1}{2 \pi (\cos r_i - \cos r_o)} \f$ is a normalization
  295 + * constant (see the update() method for details).
  296 + *
  297 + * The method will not compute analytical parameter gradients, even if the
  298 + * @p gradients argument is set to true. Radial ring parameter gradients
  299 + * need to be computed numerically.
  300 + ***************************************************************************/
  301 +double GModelSpatialRadialRing::eval(const double& theta,
  302 + const GEnergy& energy,
  303 + const GTime& time,
  304 + const bool& gradients) const
  305 +{
  306 + // Update precomputation cache
  307 + update();
  308 +
  309 + // Set value
  310 + double value = 0.0;
  311 + value = (theta <= m_outer_radius_rad) ? 1.0 : 0.0;
  312 + value *= (theta >= m_inner_radius_rad) ? m_norm : 0.0;
  313 +
  314 + // Compile option: Check for NaN/Inf
  315 + #if defined(G_NAN_CHECK)
  316 + if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
  317 + std::cout << "*** ERROR: GModelSpatialRadialRing::eval";
  318 + std::cout << "(theta=" << theta << "): NaN/Inf encountered";
  319 + std::cout << " (value=" << value;
  320 + std::cout << ", m_inner_radius_rad=" << m_inner_radius_rad;
  321 + std::cout << ", m_outer_radius_rad=" << m_outer_radius_rad;
  322 + std::cout << ", m_norm=" << m_norm;
  323 + std::cout << ")" << std::endl;
  324 + }
  325 + #endif
  326 +
  327 + // Return value
  328 + return value;
  329 +}
  330 +
  331 +
  332 +/***********************************************************************//**
  333 + * @brief Return MC sky direction
  334 + *
  335 + * @param[in] energy Photon energy.
  336 + * @param[in] time Photon arrival time.
  337 + * @param[in,out] ran Random number generator.
  338 + * @return Sky direction.
  339 + *
  340 + * Draws an arbitrary sky direction from the 2D ring distribution as function
  341 + * of the photon @p energy and arrival @p time.
  342 + ***************************************************************************/
  343 +GSkyDir GModelSpatialRadialRing::mc(const GEnergy& energy,
  344 + const GTime& time,
  345 + GRan& ran) const
  346 +{
  347 + // Update precomputation cache
  348 + update();
  349 +
  350 + // Simulate offset from photon arrival direction
  351 + double cosirad = std::cos(m_inner_radius_rad);
  352 + double cosorad = std::cos(m_outer_radius_rad);
  353 + double theta = std::acos(cosirad - ran.uniform() * (cosirad - cosorad)) *
  354 + gammalib::rad2deg;
  355 + double phi = 360.0 * ran.uniform();
  356 +
  357 + // Rotate sky direction by offset
  358 + GSkyDir sky_dir = dir();
  359 + sky_dir.rotate_deg(phi, theta);
  360 +
  361 + // Return sky direction
  362 + return sky_dir;
  363 +}
  364 +
  365 +
  366 +/***********************************************************************//**
  367 + * @brief Checks whether model contains specified sky direction
  368 + *
  369 + * @param[in] dir Sky direction.
  370 + * @param[in] margin Margin to be added to sky direction (degrees)
  371 + * @return True if the model contains the sky direction.
  372 + *
  373 + * Signals whether a sky direction is contained in the radial ring model.
  374 + ***************************************************************************/
  375 +bool GModelSpatialRadialRing::contains(const GSkyDir& dir,
  376 + const double& margin) const
  377 +{
  378 + // Update precomputation cache
  379 + update();
  380 +
  381 + // Compute distance to centre (radians)
  382 + double distance = dir.dist(this->dir());
  383 +
  384 + // Set flag
  385 + bool flag;
  386 + flag = (distance <= m_outer_radius_rad + margin*gammalib::deg2rad)
  387 + *(distance >= m_inner_radius_rad - margin*gammalib::deg2rad);
  388 +
  389 + // Return flag
  390 + return flag;
  391 +}
  392 +
  393 +
  394 +/***********************************************************************//**
  395 + * @brief Return maximum model radius (in radians)
  396 + *
  397 + * @return Maximum model radius (in radians).
  398 + ***************************************************************************/
  399 +double GModelSpatialRadialRing::theta_max(void) const
  400 +{
  401 + // Return value
  402 + return m_outer_radius_rad;
  403 +}
  404 +
  405 +
  406 +/***********************************************************************//**
  407 + * @brief Return minimum model radius (in radians)
  408 + *
  409 + * @return Minimum model radius (in radians).
  410 + ***************************************************************************/
  411 +double GModelSpatialRadialRing::theta_min(void) const
  412 +{
  413 + // Return value
  414 + return m_inner_radius_rad;
  415 +}
  416 +
  417 +/***********************************************************************//**
  418 + * @brief Read model from XML element
  419 + *
  420 + * @param[in] xml XML element.
  421 + *
  422 + * @exception GException::model_invalid_parnum
  423 + * Invalid number of model parameters found in XML element.
  424 + * @exception GException::model_invalid_parnames
  425 + * Invalid model parameter names found in XML element.
  426 + *
  427 + * Reads the radial ring model information from an XML element. The XML
  428 + * element shall have either the format
  429 + *
  430 + * <spatialModel type="RadialRing">
  431 + * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
  432 + * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
  433 + * <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/>
  434 + * <parameter name="Width" scale="1.0" value="0.15" min="0.01" max="10" free="1"/>
  435 + * </spatialModel>
  436 + *
  437 + * or
  438 + *
  439 + * <spatialModel type="RadialRing">
  440 + * <parameter name="GLON" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
  441 + * <parameter name="GLAT" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
  442 + * <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/>
  443 + * <parameter name="Width" scale="1.0" value="0.15" min="0.01" max="10" free="1"/>
  444 + * </spatialModel>
  445 + *
  446 + * @todo Implement a test of the radius and radius boundary. The radius
  447 + * and radius minimum should be >0.
  448 + ***************************************************************************/
  449 +void GModelSpatialRadialRing::read(const GXmlElement& xml)
  450 +{
  451 + // Determine number of parameter nodes in XML element
  452 + int npars = xml.elements("parameter");
  453 +
  454 + // Verify that XML element has exactly 4 parameters
  455 + if (xml.elements() != 4 || npars != 4) {
  456 + throw GException::model_invalid_parnum(G_READ, xml,
  457 + "Ring model requires exactly 4 parameters.");
  458 + }
  459 +
  460 + // Read ring center location
  461 + GModelSpatialRadial::read(xml);
  462 +
  463 + // Get parameters
  464 + const GXmlElement* radius = gammalib::xml_get_par(G_READ, xml, m_radius.name());
  465 + const GXmlElement* width = gammalib::xml_get_par(G_READ, xml, m_width.name());
  466 +
  467 + // Read parameters
  468 + m_radius.read(*radius);
  469 + m_width.read(*width);
  470 +
  471 + // Return
  472 + return;
  473 +}
  474 +
  475 +
  476 +/***********************************************************************//**
  477 + * @brief Write model into XML element
  478 + *
  479 + * @param[in] xml XML element into which model information is written.
  480 + *
  481 + * @exception GException::model_invalid_parnum
  482 + * Invalid number of model parameters found in XML element.
  483 + * @exception GException::model_invalid_parnames
  484 + * Invalid model parameter names found in XML element.
  485 + *
  486 + * Writes the radial ring model information into an XML element. The XML
  487 + * element will have the format
  488 + *
  489 + * <spatialModel type="RadialRing">
  490 + * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
  491 + * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
  492 + * <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/>
  493 + * <parameter name="Width" scale="1.0" value="0.15" min="0.01" max="10" free="1"/>
  494 + * </spatialModel>
  495 + *
  496 + ***************************************************************************/
  497 +void GModelSpatialRadialRing::write(GXmlElement& xml) const
  498 +{
  499 + // Write ring center location
  500 + GModelSpatialRadial::write(xml);
  501 +
  502 + // Get or create parameters
  503 + GXmlElement* radius = gammalib::xml_need_par(G_WRITE, xml, m_radius.name());
  504 + GXmlElement* width = gammalib::xml_need_par(G_WRITE, xml, m_width.name());
  505 +
  506 + // Write parameters
  507 + m_radius.write(*radius);
  508 + m_width.write(*width);
  509 +
  510 + // Return
  511 + return;
  512 +}
  513 +
  514 +
  515 +/***********************************************************************//**
  516 + * @brief Print information
  517 + *
  518 + * @param[in] chatter Chattiness (defaults to NORMAL).
  519 + * @return String containing model information.
  520 + ***************************************************************************/
  521 +std::string GModelSpatialRadialRing::print(const GChatter& chatter) const
  522 +{
  523 + // Initialise result string
  524 + std::string result;
  525 +
  526 + // Continue only if chatter is not silent
  527 + if (chatter != SILENT) {
  528 +
  529 + // Append header
  530 + result.append("=== GModelSpatialRadialRing ===");
  531 +
  532 + // Append parameters
  533 + result.append("\n"+gammalib::parformat("Number of parameters"));
  534 + result.append(gammalib::str(size()));
  535 + for (int i = 0; i < size(); ++i) {
  536 + result.append("\n"+m_pars[i]->print(chatter));
  537 + }
  538 +
  539 + } // endif: chatter was not silent
  540 +
  541 + // Return result
  542 + return result;
  543 +}
  544 +
  545 +
  546 +/*==========================================================================
  547 + = =
  548 + = Private methods =
  549 + = =
  550 + ==========================================================================*/
  551 +
  552 +/***********************************************************************//**
  553 + * @brief Initialise class members
  554 + ***************************************************************************/
  555 +void GModelSpatialRadialRing::init_members(void)
  556 +{
  557 + // Initialise model type
  558 + m_type = "RadialRing";
  559 +
  560 + // Initialise Radius
  561 + m_radius.clear();
  562 + m_radius.name("Radius");
  563 + m_radius.unit("deg");
  564 + m_radius.value(2.778e-4); // 1 arcsec
  565 + m_radius.min(2.778e-4); // 1 arcsec
  566 + m_radius.free();
  567 + m_radius.scale(1.0);
  568 + m_radius.gradient(0.0);
  569 + m_radius.has_grad(false); // Radial components never have gradients
  570 +
  571 + // Set parameter pointer(s)
  572 + m_pars.push_back(&m_radius);
  573 +
  574 + // Initialise Width
  575 + m_width.clear();
  576 + m_width.name("Width");
  577 + m_width.unit("deg");
  578 + m_width.value(2.778e-4); // 1 arcsec
  579 + m_width.min(2.778e-4); // 1 arcsec
  580 + m_width.free();
  581 + m_width.scale(1.0);
  582 + m_width.gradient(0.0);
  583 + m_width.has_grad(false); // Radial components never have gradients
  584 +
  585 + // Set parameter pointer(s)
  586 + m_pars.push_back(&m_width);
  587 +
  588 + // Initialise precomputation cache
  589 + m_last_radius = 0.0;
  590 + m_last_width = 0.0;
  591 + m_inner_radius_rad = 0.0;
  592 + m_outer_radius_rad = 0.0;
  593 + m_width_rad = 0.0;
  594 + m_norm = 0.0;
  595 +
  596 + // Initialise other members
  597 + m_region.clear();
  598 +
  599 + // Return
  600 + return;
  601 +}
  602 +
  603 +
  604 +/***********************************************************************//**
  605 + * @brief Copy class members
  606 + *
  607 + * @param[in] model Radial ring model.
  608 + *
  609 + * We do not have to push back the members on the parameter stack as this
  610 + * should have been done by init_members() that was called before. Otherwise
  611 + * we would have the radius twice on the stack.
  612 + ***************************************************************************/
  613 +void GModelSpatialRadialRing::copy_members(const GModelSpatialRadialRing& model)
  614 +{
  615 + // Copy members
  616 + m_type = model.m_type;
  617 + m_radius = model.m_radius;
  618 + m_width = model.m_width;
  619 + m_region = model.m_region;
  620 +
  621 + // Copy precomputation cache
  622 + m_last_radius = model.m_last_radius;
  623 + m_last_width = model.m_last_width;
  624 + m_inner_radius_rad = model.m_inner_radius_rad;
  625 + m_outer_radius_rad = model.m_outer_radius_rad;
  626 + m_width_rad = model.m_width_rad;
  627 + m_norm = model.m_norm;
  628 +
  629 + // Return
  630 + return;
  631 +}
  632 +
  633 +
  634 +/***********************************************************************//**
  635 + * @brief Delete class members
  636 + ***************************************************************************/
  637 +void GModelSpatialRadialRing::free_members(void)
  638 +{
  639 + // Return
  640 + return;
  641 +}
  642 +
  643 +
  644 +/***********************************************************************//**
  645 + * @brief Update precomputation cache
  646 + *
  647 + * Computes the normalization
  648 + * \f[
  649 + * {\tt m\_norm} = \frac{1}{2 \pi (\cos r_i - \cos r_o)}
  650 + * \f]
  651 + *
  652 + * This is the correct normalization on the sphere for any radii.
  653 + ***************************************************************************/
  654 +void GModelSpatialRadialRing::update() const
  655 +{
  656 + // Update if radius or width has changed
  657 + if ((m_last_radius != radius()) || (m_last_width != width())) {
  658 +
  659 + // Store last values
  660 + m_last_radius = radius();
  661 + m_last_width = width();
  662 +
  663 + // Compute ring parameters in radians
  664 + m_outer_radius_rad = radius() * gammalib::deg2rad;
  665 + m_inner_radius_rad = (radius()-width()) * gammalib::deg2rad;
  666 + m_width_rad = width() * gammalib::deg2rad;
  667 +
  668 + // Perform precomputations
  669 + double denom = gammalib::twopi *
  670 + (std::cos(m_inner_radius_rad) -
  671 + std::cos(m_outer_radius_rad));
  672 + m_norm = (denom > 0.0) ? 1.0 / denom : 0.0;
  673 +
  674 + } // endif: update required
  675 +
  676 + // Also update region
  677 + set_region();
  678 +
  679 + // Return
  680 + return;
  681 +}
  682 +
  683 +
  684 +/***********************************************************************//**
  685 + * @brief Set boundary sky region
  686 + ***************************************************************************/
  687 +void GModelSpatialRadialRing::set_region(void) const
  688 +{
  689 + // Set sky region centre to ring centre
  690 + m_region.centre(m_ra.value(), m_dec.value());
  691 +
  692 + // Set sky region radius to ring radius
  693 + m_region.radius(m_radius.value());
  694 +
  695 + // Return
  696 + return;
  697 +}
src/model/Makefile.am
@@ -36,6 +36,7 @@ sources = GModelPar.cpp \ @@ -36,6 +36,7 @@ sources = GModelPar.cpp \
36 GModelSpatialPointSource.cpp \ 36 GModelSpatialPointSource.cpp \
37 GModelSpatialRadial.cpp \ 37 GModelSpatialRadial.cpp \
38 GModelSpatialRadialDisk.cpp \ 38 GModelSpatialRadialDisk.cpp \
  39 + GModelSpatialRadialRing.cpp \
39 GModelSpatialRadialGauss.cpp \ 40 GModelSpatialRadialGauss.cpp \
40 GModelSpatialRadialShell.cpp \ 41 GModelSpatialRadialShell.cpp \
41 GModelSpatialRadialProfile.cpp \ 42 GModelSpatialRadialProfile.cpp \
test/data/model_radial_ring.xml 0 → 100644
  1 +<?xml version="1.0" standalone="no"?>
  2 +<source_library title="source library">
  3 + <source name="Cen A lobes" type="ExtendedSource">
  4 + <spectrum type="PowerLaw">
  5 + <parameter scale="1e-07" name="Prefactor" min="1e-07" max="1000.0" value="1.73" free="1"/>
  6 + <parameter scale="1.0" name="Index" min="-5.0" max="+5.0" value="-2.1" free="1"/>
  7 + <parameter scale="1.0" name="PivotEnergy" min="10.0" max="1000000.0" value="100.0" free="0"/>
  8 + </spectrum>
  9 + <spatialModel type="RadialRing">
  10 + <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
  11 + <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
  12 + <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/>
  13 + <parameter name="Width" scale="1.0" value="0.15" min="0.01" max="10" free="1"/>
  14 + </spatialModel>
  15 + </source>
  16 +</source_library>
test/test_GModel.cpp
@@ -76,6 +76,7 @@ void TestGModel::set(void) @@ -76,6 +76,7 @@ void TestGModel::set(void)
76 m_xml_model_diffuse_cube = datadir + "/model_diffuse_cube.xml"; 76 m_xml_model_diffuse_cube = datadir + "/model_diffuse_cube.xml";
77 m_xml_model_diffuse_map = datadir + "/model_diffuse_map.xml"; 77 m_xml_model_diffuse_map = datadir + "/model_diffuse_map.xml";
78 m_xml_model_radial_disk = datadir + "/model_radial_disk.xml"; 78 m_xml_model_radial_disk = datadir + "/model_radial_disk.xml";
  79 + m_xml_model_radial_ring = datadir + "/model_radial_ring.xml";
79 m_xml_model_radial_gauss = datadir + "/model_radial_gauss.xml"; 80 m_xml_model_radial_gauss = datadir + "/model_radial_gauss.xml";
80 m_xml_model_radial_shell = datadir + "/model_radial_shell.xml"; 81 m_xml_model_radial_shell = datadir + "/model_radial_shell.xml";
81 m_xml_model_elliptical_disk = datadir + "/model_elliptical_disk.xml"; 82 m_xml_model_elliptical_disk = datadir + "/model_elliptical_disk.xml";
@@ -113,6 +114,8 @@ void TestGModel::set(void) @@ -113,6 +114,8 @@ void TestGModel::set(void)
113 "Test GModelSpatialPointSource"); 114 "Test GModelSpatialPointSource");
114 append(static_cast<pfunction>(&TestGModel::test_radial_disk), 115 append(static_cast<pfunction>(&TestGModel::test_radial_disk),
115 "Test GModelSpatialRadialDisk"); 116 "Test GModelSpatialRadialDisk");
  117 + append(static_cast<pfunction>(&TestGModel::test_radial_ring),
  118 + "Test GModelSpatialRadialRing");
116 append(static_cast<pfunction>(&TestGModel::test_radial_gauss), 119 append(static_cast<pfunction>(&TestGModel::test_radial_gauss),
117 "Test GModelSpatialRadialGauss"); 120 "Test GModelSpatialRadialGauss");
118 append(static_cast<pfunction>(&TestGModel::test_radial_shell), 121 append(static_cast<pfunction>(&TestGModel::test_radial_shell),
@@ -935,6 +938,88 @@ void TestGModel::test_radial_disk(void) @@ -935,6 +938,88 @@ void TestGModel::test_radial_disk(void)
935 938
936 939
937 /***********************************************************************//** 940 /***********************************************************************//**
  941 + * @brief Test GModelSpatialRadialRing class
  942 + ***************************************************************************/
  943 +void TestGModel::test_radial_ring(void)
  944 +{
  945 + // Test void constructor
  946 + GModelSpatialRadialRing model1;
  947 + test_value(model1.type(), "RadialRing");
  948 +
  949 + // Test value constructor
  950 + GSkyDir dir1;
  951 + dir1.radec_deg(83.6331, +22.0145);
  952 + GModelSpatialRadialRing model2(dir1, 3.0,1.0);
  953 + test_value(model2.ra(), 83.6331);
  954 + test_value(model2.dec(), 22.0145);
  955 + test_value(model2.radius(), 3.0);
  956 + test_value(model2.width(), 1.0);
  957 +
  958 + // Test XML constructor
  959 + GXml xml(m_xml_model_radial_ring);
  960 + GXmlElement* element = xml.element(0)->element(0)->element("spatialModel", 0);
  961 + GModelSpatialRadialRing model3(*element);
  962 + test_value(model3.size(), 4);
  963 + test_value(model3.type(), "RadialRing");
  964 + test_value(model3.ra(), 83.6331);
  965 + test_value(model3.dec(), 22.0145);
  966 + test_value(model3.radius(), 0.45);
  967 + test_value(model3.width(), 0.15);
  968 +
  969 + // Test ra method
  970 + model3.ra(100.0);
  971 + test_value(model3.ra(), 100.0);
  972 +
  973 + // Test dec method
  974 + model3.dec(10.0);
  975 + test_value(model3.dec(), 10.0);
  976 +
  977 + // Test dir method
  978 + GSkyDir dir2;
  979 + dir2.radec_deg(83.6331, +22.0145);
  980 + model3.dir(dir2);
  981 + test_assert(model3.dir() == dir2, "Test sky direction");
  982 +
  983 + // Test radius method
  984 + model3.radius(1.0);
  985 + test_value(model3.radius(), 1.0);
  986 +
  987 + // Test width method
  988 + model3.width(0.5);
  989 + test_value(model3.width(), 0.5);
  990 +
  991 + // Test region method
  992 + GSkyDir dir3;
  993 + dir3.radec_deg(83.6331, +22.0145);
  994 + test_assert(model3.region()->contains(dir3), "Test region() method (inside)");
  995 + dir3.radec_deg(83.6331, +26.0);
  996 + test_assert(!model3.region()->contains(dir3), "Test region() method (outside)");
  997 +
  998 + // Test contains method
  999 + dir3.radec_deg(83.6331, +22.75);
  1000 + test_assert(model3.contains(dir3), "Test contains() method (inside)");
  1001 + dir3.radec_deg(83.6331, +22.0145);
  1002 + test_assert(!model3.contains(dir3), "Test contains() method (outside interior of ring)");
  1003 + dir3.radec_deg(83.6331, +26.0);
  1004 + test_assert(!model3.contains(dir3), "Test contains() method (outside exterior of ring)");
  1005 +
  1006 + // Test operator access
  1007 + const char* strarray[] = {"RA", "DEC", "Radius", "Width"};
  1008 + for (int i = 0; i < 4; ++i) {
  1009 + std::string keyname(strarray[i]);
  1010 + model3[keyname].value(2.1);
  1011 + model3[keyname].error(1.9);
  1012 + model3[keyname].gradient(0.8);
  1013 + test_value(model3[keyname].value(), 2.1);
  1014 + test_value(model3[keyname].error(), 1.9);
  1015 + test_value(model3[keyname].gradient(), 0.8);
  1016 + }
  1017 +
  1018 + // Exit test
  1019 + return;
  1020 +}
  1021 +
  1022 +/***********************************************************************//**
938 * @brief Test GModelSpatialRadialGauss class 1023 * @brief Test GModelSpatialRadialGauss class
939 ***************************************************************************/ 1024 ***************************************************************************/
940 void TestGModel::test_radial_gauss(void) 1025 void TestGModel::test_radial_gauss(void)
@@ -2509,6 +2594,7 @@ void TestGModel::test_spatial_model(void) @@ -2509,6 +2594,7 @@ void TestGModel::test_spatial_model(void)
2509 // Test spatial models XML interface 2594 // Test spatial models XML interface
2510 test_xml_model("GModelSpatialPointSource", m_xml_model_point_plaw); 2595 test_xml_model("GModelSpatialPointSource", m_xml_model_point_plaw);
2511 test_xml_model("GModelSpatialRadialDisk", m_xml_model_radial_disk); 2596 test_xml_model("GModelSpatialRadialDisk", m_xml_model_radial_disk);
  2597 + test_xml_model("GModelSpatialRadialRing", m_xml_model_radial_ring);
2512 test_xml_model("GModelSpatialRadialGauss", m_xml_model_radial_gauss); 2598 test_xml_model("GModelSpatialRadialGauss", m_xml_model_radial_gauss);
2513 test_xml_model("GModelSpatialRadialShell", m_xml_model_radial_shell); 2599 test_xml_model("GModelSpatialRadialShell", m_xml_model_radial_shell);
2514 test_xml_model("GModelSpatialEllipticalDisk", m_xml_model_elliptical_disk); 2600 test_xml_model("GModelSpatialEllipticalDisk", m_xml_model_elliptical_disk);
test/test_GModel.hpp
@@ -54,6 +54,7 @@ public: @@ -54,6 +54,7 @@ public:
54 void test_diffuse_cube(void); 54 void test_diffuse_cube(void);
55 void test_diffuse_map(void); 55 void test_diffuse_map(void);
56 void test_radial_disk(void); 56 void test_radial_disk(void);
  57 + void test_radial_ring(void);
57 void test_radial_gauss(void); 58 void test_radial_gauss(void);
58 void test_radial_shell(void); 59 void test_radial_shell(void);
59 void test_elliptical_disk(void); 60 void test_elliptical_disk(void);
@@ -133,6 +134,7 @@ private: @@ -133,6 +134,7 @@ private:
133 std::string m_xml_model_diffuse_cube; 134 std::string m_xml_model_diffuse_cube;
134 std::string m_xml_model_diffuse_map; 135 std::string m_xml_model_diffuse_map;
135 std::string m_xml_model_radial_disk; 136 std::string m_xml_model_radial_disk;
  137 + std::string m_xml_model_radial_ring;
136 std::string m_xml_model_radial_gauss; 138 std::string m_xml_model_radial_gauss;
137 std::string m_xml_model_radial_shell; 139 std::string m_xml_model_radial_shell;
138 std::string m_xml_model_elliptical_disk; 140 std::string m_xml_model_elliptical_disk;
test/test_GModel.py
@@ -124,6 +124,7 @@ class Test(gammalib.GPythonTestSuite): @@ -124,6 +124,7 @@ class Test(gammalib.GPythonTestSuite):
124 test_support.pickeling(self, gammalib.GModelSpatialEllipticalGauss()) 124 test_support.pickeling(self, gammalib.GModelSpatialEllipticalGauss())
125 test_support.pickeling(self, gammalib.GModelSpatialPointSource()) 125 test_support.pickeling(self, gammalib.GModelSpatialPointSource())
126 test_support.pickeling(self, gammalib.GModelSpatialRadialDisk()) 126 test_support.pickeling(self, gammalib.GModelSpatialRadialDisk())
  127 + test_support.pickeling(self, gammalib.GModelSpatialRadialRing())
127 test_support.pickeling(self, gammalib.GModelSpatialRadialGauss()) 128 test_support.pickeling(self, gammalib.GModelSpatialRadialGauss())
128 test_support.pickeling(self, gammalib.GModelSpatialRadialProfileDMBurkert()) 129 test_support.pickeling(self, gammalib.GModelSpatialRadialProfileDMBurkert())
129 test_support.pickeling(self, gammalib.GModelSpatialRadialProfileDMEinasto()) 130 test_support.pickeling(self, gammalib.GModelSpatialRadialProfileDMEinasto())
@@ -188,6 +189,7 @@ class Test(gammalib.GPythonTestSuite): @@ -188,6 +189,7 @@ class Test(gammalib.GPythonTestSuite):
188 test_support.pickeling(self, gammalib.GModelSpatialEllipticalGauss(dir,0.2,0.3,45.0)) 189 test_support.pickeling(self, gammalib.GModelSpatialEllipticalGauss(dir,0.2,0.3,45.0))
189 test_support.pickeling(self, gammalib.GModelSpatialPointSource(ptsrc)) 190 test_support.pickeling(self, gammalib.GModelSpatialPointSource(ptsrc))
190 test_support.pickeling(self, gammalib.GModelSpatialRadialDisk(dir,0.2)) 191 test_support.pickeling(self, gammalib.GModelSpatialRadialDisk(dir,0.2))
  192 + test_support.pickeling(self, gammalib.GModelSpatialRadialRing(dir,0.3,0.1))
191 test_support.pickeling(self, gammalib.GModelSpatialRadialGauss(dir,0.2)) 193 test_support.pickeling(self, gammalib.GModelSpatialRadialGauss(dir,0.2))
192 #test_support.pickeling(self, gammalib.GModelSpatialRadialProfileDMBurkert()) 194 #test_support.pickeling(self, gammalib.GModelSpatialRadialProfileDMBurkert())
193 #test_support.pickeling(self, gammalib.GModelSpatialRadialProfileDMEinasto()) 195 #test_support.pickeling(self, gammalib.GModelSpatialRadialProfileDMEinasto())