Commit e9681ff1b66b2dc273d4591200d75c12f8a002aa
Merge branch '3924-GeneralGauss' into integration
# Conflicts: # ChangeLog # NEWS # README.md
Showing
18 changed files
with
2239 additions
and
38 deletions
ChangeLog
| 1 | -2021-12-13 | |
| 1 | +2022-01-10 | |
| 2 | 2 | |
| 3 | 3 | * Version 2.0.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | 6 | Add GCOMObservation::tim() and GCOMObservation::oads() setter methods |
| 7 | + Add GModelSpatialRadialGeneralGauss and | |
| 8 | + GModelSpatialEllipticalGeneralGauss classes (#3924) | |
| 7 | 9 | Remove GCOMSelection::zeta_min() and GCOMSelection::zeta_max() |
| 8 | 10 | methods |
| 9 | - Add GCOMSelection::fpmtflag(), GCOMSelection::use_d1() and | |
| 11 | + Add GCOMSelection::fpmtflag(), GCOMSelection::use_d1() and | |
| 10 | 12 | GCOMSelection::use_d2() methods (#3917) |
| 11 | 13 | Add GCOMModelDRBPhibarBins class (#3913) |
| 12 | 14 | Compute spectral model gradients for negative factor values | ... | ... |
NEWS
| 1 | 1 | New Features and Important Changes in GammaLib 2.0.0 |
| 2 | 2 | |
| 3 | -13 December 2021 | |
| 3 | +10 January 2022 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | 1. Introduction |
| ... | ... | @@ -20,6 +20,8 @@ The following classes have been added: |
| 20 | 20 | - GModelAssociation |
| 21 | 21 | - GModelAssociations |
| 22 | 22 | - GModelSpectralBins |
| 23 | +- GModelSpatialRadialGeneralGauss | |
| 24 | +- GModelSpatialEllipticalGeneralGauss | |
| 23 | 25 | - GCTAModelSkyCube |
| 24 | 26 | - GCTABackground2D |
| 25 | 27 | - GCOMModelDRM |
| ... | ... | @@ -207,6 +209,9 @@ Implemented GMatrixSparse::row() and GMatrixSparse::add_to_row() methods. |
| 207 | 209 | |
| 208 | 210 | 9. Model module |
| 209 | 211 | --------------- |
| 212 | +Added GModelSpatialRadialGeneralGauss and GModelSpatialEllipticalGeneralGauss | |
| 213 | +classes to model general Gaussian functions as spatial components (#3924). | |
| 214 | + | |
| 210 | 215 | Gradients for spectral model parameters are now also computed for all models in |
| 211 | 216 | case that the factor values are negative. This provides now error bars for photon |
| 212 | 217 | and energy flux power laws that are allowed to take negative flux values. | ... | ... |
README.md
| 1 | 1 | GammaLib information |
| 2 | 2 | ==================== |
| 3 | -* Version: 2.0.0.dev (13 December 2021) | |
| 3 | +* Version: 2.0.0.dev (10 January 2022) | |
| 4 | 4 | |
| 5 | 5 | [](https://cta-jenkins.irap.omp.eu/job/gammalib-integrate-os/) |
| 6 | 6 | ... | ... |
doc/source/admin/release_history/2.0.rst
| 1 | 1 | .. _2.0: |
| 2 | 2 | |
| 3 | -GammaLib 2.0 release (3 December 2021) | |
| 3 | +GammaLib 2.0 release (10 January 2022) | |
| 4 | 4 | ====================================== |
| 5 | 5 | |
| 6 | 6 | Overview |
| ... | ... | @@ -96,6 +96,8 @@ Improvements |
| 96 | 96 | New features |
| 97 | 97 | ------------ |
| 98 | 98 | |
| 99 | +* [`3924 <https://cta-redmine.irap.omp.eu/issues/3924>`_] - | |
| 100 | + Add ``GModelSpatialRadialGeneralGauss`` and ``GModelSpatialEllipticalGeneralGauss`` classes | |
| 99 | 101 | * [`3910 <https://cta-redmine.irap.omp.eu/issues/3910>`_] - |
| 100 | 102 | Add ``GCOMModelDRM`` class |
| 101 | 103 | * [`3606 <https://cta-redmine.irap.omp.eu/issues/3606>`_] - | ... | ... |
include/GModelSpatialEllipticalGeneralGauss.hpp
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * GModelSpatialEllipticalGeneralGauss.hpp - Generalised elliptical * | |
| 3 | + * Gaussian source model class * | |
| 4 | + * ----------------------------------------------------------------------- * | |
| 5 | + * copyright (C) 2022 by Luigi Tibaldo * | |
| 6 | + * ----------------------------------------------------------------------- * | |
| 7 | + * * | |
| 8 | + * This program is free software: you can redistribute it and/or modify * | |
| 9 | + * it under the terms of the GNU General Public License as published by * | |
| 10 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 11 | + * (at your option) any later version. * | |
| 12 | + * * | |
| 13 | + * This program is distributed in the hope that it will be useful, * | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 16 | + * GNU General Public License for more details. * | |
| 17 | + * * | |
| 18 | + * You should have received a copy of the GNU General Public License * | |
| 19 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 20 | + * * | |
| 21 | + ***************************************************************************/ | |
| 22 | +/** | |
| 23 | + * @file GModelSpatialEllipticalGeneralGauss.hpp | |
| 24 | + * @brief Generalised elliptical gaussian model class interface definition | |
| 25 | + * @author Luigi Tibaldo | |
| 26 | + */ | |
| 27 | + | |
| 28 | +#ifndef GMODELSPATIALELLIPTICALGENERALGAUSS_HPP | |
| 29 | +#define GMODELSPATIALELLIPTICALGENERALGAUSS_HPP | |
| 30 | + | |
| 31 | +/* __ Includes ___________________________________________________________ */ | |
| 32 | +#include <string> | |
| 33 | +#include "GModelSpatialElliptical.hpp" | |
| 34 | +#include "GModelPar.hpp" | |
| 35 | +#include "GSkyDir.hpp" | |
| 36 | +#include "GSkyRegionCircle.hpp" | |
| 37 | +#include "GXmlElement.hpp" | |
| 38 | + | |
| 39 | + | |
| 40 | +/************************************************************************** | |
| 41 | + * @class GModelSpatialEllipticalGeneralGauss | |
| 42 | + * | |
| 43 | + * @brief Generalised elliptical gaussian source model class | |
| 44 | + * | |
| 45 | + * This class implements the spatial component of the factorised source | |
| 46 | + * model for an generalised elliptical Gaussian source, i.e. surface | |
| 47 | + * brightness according to an asymmetric generalised Gaussian. | |
| 48 | + ***************************************************************************/ | |
| 49 | +class GModelSpatialEllipticalGeneralGauss : public GModelSpatialElliptical { | |
| 50 | + | |
| 51 | +public: | |
| 52 | + // Constructors and destructors | |
| 53 | + GModelSpatialEllipticalGeneralGauss(void); | |
| 54 | + GModelSpatialEllipticalGeneralGauss(const GSkyDir& dir, | |
| 55 | + const double& major, | |
| 56 | + const double& minor, | |
| 57 | + const double& posangle, | |
| 58 | + const double& ridx); | |
| 59 | + explicit GModelSpatialEllipticalGeneralGauss(const GXmlElement& xml); | |
| 60 | + GModelSpatialEllipticalGeneralGauss(const GModelSpatialEllipticalGeneralGauss& model); | |
| 61 | + virtual ~GModelSpatialEllipticalGeneralGauss(void); | |
| 62 | + | |
| 63 | + // Operators | |
| 64 | + virtual GModelSpatialEllipticalGeneralGauss& operator=(const GModelSpatialEllipticalGeneralGauss& model); | |
| 65 | + | |
| 66 | + // Implemented pure virtual base class methods | |
| 67 | + virtual void clear(void); | |
| 68 | + virtual GModelSpatialEllipticalGeneralGauss* clone(void) const; | |
| 69 | + virtual std::string classname(void) const; | |
| 70 | + virtual double eval(const double& theta, | |
| 71 | + const double& posangle, | |
| 72 | + const GEnergy& energy, | |
| 73 | + const GTime& time, | |
| 74 | + const bool& gradients = false) const; | |
| 75 | + virtual GSkyDir mc(const GEnergy& energy, | |
| 76 | + const GTime& time, | |
| 77 | + GRan& ran) const; | |
| 78 | + virtual bool contains(const GSkyDir& dir, | |
| 79 | + const double& margin = 0.0) const; | |
| 80 | + virtual double theta_max(void) const; | |
| 81 | + virtual void read(const GXmlElement& xml); | |
| 82 | + virtual void write(GXmlElement& xml) const; | |
| 83 | + virtual std::string print(const GChatter& chatter = NORMAL) const; | |
| 84 | + | |
| 85 | + // Other methods | |
| 86 | + double ridx(void) const; | |
| 87 | + void ridx(const double& ridx); | |
| 88 | + | |
| 89 | + | |
| 90 | +protected: | |
| 91 | + // Protected methods | |
| 92 | + void init_members(void); | |
| 93 | + void copy_members(const GModelSpatialEllipticalGeneralGauss& model); | |
| 94 | + void free_members(void); | |
| 95 | + void update(void) const; | |
| 96 | + virtual void set_region(void) const; | |
| 97 | + | |
| 98 | + // Protected members | |
| 99 | + GModelPar m_ridx; //!< Reciprocal of exponent of the radial profile | |
| 100 | + | |
| 101 | + // Cached members used for pre-computations | |
| 102 | + mutable double m_last_minor; //!< Last semi-minor axis | |
| 103 | + mutable double m_last_major; //!< Last semi-major axis | |
| 104 | + mutable double m_last_posangle; //!< Last position angle | |
| 105 | + mutable double m_cospos2; //!< squared cosine of position angle | |
| 106 | + mutable double m_sinpos2; //!< squared sine of position angle | |
| 107 | + mutable double m_sin2pos; //!< sine of twice the position angle | |
| 108 | + mutable double m_minor2; //!< square of minor axis | |
| 109 | + mutable double m_major2; //!< square of major axis | |
| 110 | + mutable double m_minor_rad; //!< Minor axis in radians | |
| 111 | + mutable double m_major_rad; //!< Major axis in radians | |
| 112 | + mutable double m_norm; //!< Normalization | |
| 113 | + mutable double m_term1; //!< Help term 1 | |
| 114 | + mutable double m_term2; //!< Help term 2 | |
| 115 | + mutable double m_term3; //!< Help term 3 | |
| 116 | + mutable double m_last_ridx; //!< Last reciprocal radial index | |
| 117 | + mutable double m_inv_ridx; //!< Spatial profile index | |
| 118 | + | |
| 119 | +}; | |
| 120 | + | |
| 121 | + | |
| 122 | +/***********************************************************************//** | |
| 123 | + * @brief Return class name | |
| 124 | + * | |
| 125 | + * @return String containing the class name ("GModelSpatialEllipticalGeneralGauss"). | |
| 126 | + ***************************************************************************/ | |
| 127 | +inline | |
| 128 | +std::string GModelSpatialEllipticalGeneralGauss::classname(void) const | |
| 129 | +{ | |
| 130 | + return ("GModelSpatialEllipticalGeneralGauss"); | |
| 131 | +} | |
| 132 | + | |
| 133 | +/***********************************************************************//** | |
| 134 | + * @brief Return reciprocal of the elliptical profile index | |
| 135 | + * | |
| 136 | + * @return Reciprocal of the elliptical profile index. | |
| 137 | + * | |
| 138 | + * Returns the reciprocal of the elliptical profile index. | |
| 139 | + ***************************************************************************/ | |
| 140 | +inline | |
| 141 | +double GModelSpatialEllipticalGeneralGauss::ridx(void) const | |
| 142 | +{ | |
| 143 | + return (m_ridx.value()); | |
| 144 | +} | |
| 145 | + | |
| 146 | +/***********************************************************************//** | |
| 147 | + * @brief Set reciprocal of the elliptical profile index | |
| 148 | + * | |
| 149 | + * @param[in] ridx Reciprocal of the elliptical profile index. | |
| 150 | + * | |
| 151 | + * Sets the reciprocal of the elliptical profile index. | |
| 152 | + ***************************************************************************/ | |
| 153 | +inline | |
| 154 | +void GModelSpatialEllipticalGeneralGauss::ridx(const double& ridx) | |
| 155 | +{ | |
| 156 | + m_ridx.value(ridx); | |
| 157 | + return; | |
| 158 | +} | |
| 159 | + | |
| 160 | +#endif /* GMODELSPATIALELLIPTICALGENERALGAUSS_HPP */ | ... | ... |
include/GModelSpatialRadialGeneralGauss.hpp
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * GModelSpatialRadialGeneralGauss.hpp - Generalised radial Gaussian * | |
| 3 | + * source model class * | |
| 4 | + * ----------------------------------------------------------------------- * | |
| 5 | + * copyright (C) 2021-2022 by Luigi Tibaldo * | |
| 6 | + * ----------------------------------------------------------------------- * | |
| 7 | + * * | |
| 8 | + * This program is free software: you can redistribute it and/or modify * | |
| 9 | + * it under the terms of the GNU General Public License as published by * | |
| 10 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 11 | + * (at your option) any later version. * | |
| 12 | + * * | |
| 13 | + * This program is distributed in the hope that it will be useful, * | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 16 | + * GNU General Public License for more details. * | |
| 17 | + * * | |
| 18 | + * You should have received a copy of the GNU General Public License * | |
| 19 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 20 | + * * | |
| 21 | + ***************************************************************************/ | |
| 22 | +/** | |
| 23 | + * @file GModelSpatialRadialGeneralGauss.hpp | |
| 24 | + * @brief Generalized radial Gaussian model class interface definition | |
| 25 | + * @author Luigi Tibaldo | |
| 26 | + */ | |
| 27 | + | |
| 28 | +#ifndef GMODELSPATIALRADIALGENERALGAUSS_HPP | |
| 29 | +#define GMODELSPATIALRADIALGENERALGAUSS_HPP | |
| 30 | + | |
| 31 | +/* __ Includes ___________________________________________________________ */ | |
| 32 | +#include <string> | |
| 33 | +#include "GModelSpatialRadial.hpp" | |
| 34 | +#include "GModelPar.hpp" | |
| 35 | +#include "GSkyDir.hpp" | |
| 36 | +#include "GSkyRegionCircle.hpp" | |
| 37 | +#include "GEnergy.hpp" | |
| 38 | +#include "GTime.hpp" | |
| 39 | +#include "GXmlElement.hpp" | |
| 40 | + | |
| 41 | + | |
| 42 | +/***********************************************************************//** | |
| 43 | + * @class GModelSpatialRadialGeneralGauss | |
| 44 | + * | |
| 45 | + * @brief Generalized radial Gaussian model class | |
| 46 | + * | |
| 47 | + * This class implements the spatial component of the factorised source | |
| 48 | + * model for a generalised radial Gaussian source. | |
| 49 | + ***************************************************************************/ | |
| 50 | +class GModelSpatialRadialGeneralGauss : public GModelSpatialRadial { | |
| 51 | + | |
| 52 | +public: | |
| 53 | + // Constructors and destructors | |
| 54 | + GModelSpatialRadialGeneralGauss(void); | |
| 55 | + GModelSpatialRadialGeneralGauss(const GSkyDir& dir, | |
| 56 | + const double& radius, | |
| 57 | + const double& ridx); | |
| 58 | + explicit GModelSpatialRadialGeneralGauss(const GXmlElement& xml); | |
| 59 | + GModelSpatialRadialGeneralGauss(const GModelSpatialRadialGeneralGauss& model); | |
| 60 | + virtual ~GModelSpatialRadialGeneralGauss(void); | |
| 61 | + | |
| 62 | + // Operators | |
| 63 | + virtual GModelSpatialRadialGeneralGauss& operator=(const GModelSpatialRadialGeneralGauss& model); | |
| 64 | + | |
| 65 | + // Implemented pure virtual methods | |
| 66 | + virtual void clear(void); | |
| 67 | + virtual GModelSpatialRadialGeneralGauss* clone(void) const; | |
| 68 | + virtual std::string classname(void) const; | |
| 69 | + virtual double eval(const double& theta, | |
| 70 | + const GEnergy& energy, | |
| 71 | + const GTime& time, | |
| 72 | + const bool& gradients = false) const; | |
| 73 | + virtual GSkyDir mc(const GEnergy& energy, | |
| 74 | + const GTime& time, | |
| 75 | + GRan& ran) const; | |
| 76 | + virtual bool contains(const GSkyDir& dir, | |
| 77 | + const double& margin = 0.0) const; | |
| 78 | + virtual double theta_max(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 ridx(void) const; | |
| 87 | + void ridx(const double& ridx); | |
| 88 | + | |
| 89 | +protected: | |
| 90 | + // Protected methods | |
| 91 | + void init_members(void); | |
| 92 | + void copy_members(const GModelSpatialRadialGeneralGauss& model); | |
| 93 | + void free_members(void); | |
| 94 | + void update(void) const; | |
| 95 | + virtual void set_region(void) const; | |
| 96 | + | |
| 97 | + // Protected members | |
| 98 | + GModelPar m_radius; //!< Gaussian width (deg) | |
| 99 | + GModelPar m_ridx; //!< Reciprocal of exponent of the radial profile | |
| 100 | + | |
| 101 | + // Cached members used for pre-computations | |
| 102 | + mutable double m_last_radius; //!< Last radius | |
| 103 | + mutable double m_inv_radius_rad; //!< radius(rad)^-1 | |
| 104 | + mutable double m_last_ridx; //!< Last reciprocal radial index | |
| 105 | + mutable double m_inv_ridx; //!< Spatial profile index | |
| 106 | + mutable double m_value_norm; //!< 1/(2pi radius(rad)^2 ridx Gamma(ridx)) | |
| 107 | +}; | |
| 108 | + | |
| 109 | + | |
| 110 | +/***********************************************************************//** | |
| 111 | + * @brief Return class name | |
| 112 | + * | |
| 113 | + * @return String containing the class name ("GModelSpatialRadialGeneralGauss"). | |
| 114 | + ***************************************************************************/ | |
| 115 | +inline | |
| 116 | +std::string GModelSpatialRadialGeneralGauss::classname(void) const | |
| 117 | +{ | |
| 118 | + return ("GModelSpatialRadialGeneralGauss"); | |
| 119 | +} | |
| 120 | + | |
| 121 | + | |
| 122 | +/***********************************************************************//** | |
| 123 | + * @brief Return radius | |
| 124 | + * | |
| 125 | + * @return Radius (deg). | |
| 126 | + * | |
| 127 | + * Returns the radius in degrees. | |
| 128 | + ***************************************************************************/ | |
| 129 | +inline | |
| 130 | +double GModelSpatialRadialGeneralGauss::radius(void) const | |
| 131 | +{ | |
| 132 | + return (m_radius.value()); | |
| 133 | +} | |
| 134 | + | |
| 135 | +/***********************************************************************//** | |
| 136 | + * @brief Set radius | |
| 137 | + * | |
| 138 | + * @param[in] radius (deg). | |
| 139 | + * | |
| 140 | + * Sets the radius in degrees. | |
| 141 | + ***************************************************************************/ | |
| 142 | +inline | |
| 143 | +void GModelSpatialRadialGeneralGauss::radius(const double& radius) | |
| 144 | +{ | |
| 145 | + m_radius.value(radius); | |
| 146 | + return; | |
| 147 | +} | |
| 148 | + | |
| 149 | +/***********************************************************************//** | |
| 150 | + * @brief Return ridx | |
| 151 | + * | |
| 152 | + * @return Reciprocal of the radial profile index. | |
| 153 | + * | |
| 154 | + * Returns the reciprocal of the radial profile index. | |
| 155 | + ***************************************************************************/ | |
| 156 | +inline | |
| 157 | +double GModelSpatialRadialGeneralGauss::ridx(void) const | |
| 158 | +{ | |
| 159 | + return (m_ridx.value()); | |
| 160 | +} | |
| 161 | + | |
| 162 | +/***********************************************************************//** | |
| 163 | + * @brief Set reciprocal index | |
| 164 | + * | |
| 165 | + * @param[in] ridx Reciprocal of the radial profile index. | |
| 166 | + * | |
| 167 | + * Sets the reciprocal index of the radial profile. | |
| 168 | + ***************************************************************************/ | |
| 169 | +inline | |
| 170 | +void GModelSpatialRadialGeneralGauss::ridx(const double& ridx) | |
| 171 | +{ | |
| 172 | + m_ridx.value(ridx); | |
| 173 | + return; | |
| 174 | +} | |
| 175 | + | |
| 176 | +#endif /* GMODELSPATIALRADIALGENERALGAUSS_HPP */ | ... | ... |
include/GammaLib.hpp
| ... | ... | @@ -213,6 +213,7 @@ |
| 213 | 213 | #include "GModelSpatialRadial.hpp" |
| 214 | 214 | #include "GModelSpatialRadialDisk.hpp" |
| 215 | 215 | #include "GModelSpatialRadialGauss.hpp" |
| 216 | +#include "GModelSpatialRadialGeneralGauss.hpp" | |
| 216 | 217 | #include "GModelSpatialRadialShell.hpp" |
| 217 | 218 | #include "GModelSpatialRadialRing.hpp" |
| 218 | 219 | #include "GModelSpatialRadialProfile.hpp" |
| ... | ... | @@ -223,6 +224,7 @@ |
| 223 | 224 | #include "GModelSpatialElliptical.hpp" |
| 224 | 225 | #include "GModelSpatialEllipticalDisk.hpp" |
| 225 | 226 | #include "GModelSpatialEllipticalGauss.hpp" |
| 227 | +#include "GModelSpatialEllipticalGeneralGauss.hpp" | |
| 226 | 228 | #include "GModelSpatialDiffuse.hpp" |
| 227 | 229 | #include "GModelSpatialDiffuseConst.hpp" |
| 228 | 230 | #include "GModelSpatialDiffuseCube.hpp" | ... | ... |
include/Makefile.am
| ... | ... | @@ -171,6 +171,7 @@ pkginclude_HEADERS = GammaLib.hpp \ |
| 171 | 171 | GModelSpatialRadial.hpp \ |
| 172 | 172 | GModelSpatialRadialDisk.hpp \ |
| 173 | 173 | GModelSpatialRadialGauss.hpp \ |
| 174 | + GModelSpatialRadialGeneralGauss.hpp \ | |
| 174 | 175 | GModelSpatialRadialShell.hpp \ |
| 175 | 176 | GModelSpatialRadialRing.hpp \ |
| 176 | 177 | GModelSpatialRadialProfile.hpp \ |
| ... | ... | @@ -181,6 +182,7 @@ pkginclude_HEADERS = GammaLib.hpp \ |
| 181 | 182 | GModelSpatialElliptical.hpp \ |
| 182 | 183 | GModelSpatialEllipticalDisk.hpp \ |
| 183 | 184 | GModelSpatialEllipticalGauss.hpp \ |
| 185 | + GModelSpatialEllipticalGeneralGauss.hpp \ | |
| 184 | 186 | GModelSpatialDiffuse.hpp \ |
| 185 | 187 | GModelSpatialDiffuseConst.hpp \ |
| 186 | 188 | GModelSpatialDiffuseCube.hpp \ | ... | ... |
pyext/GModelSpatialEllipticalGeneralGauss.i
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * GModelSpatialEllipticalGeneralGauss.i - Generalised elliptical * | |
| 3 | + * Gaussian source model class * | |
| 4 | + * ----------------------------------------------------------------------- * | |
| 5 | + * copyright (C) 2022 by Luigi Tibaldo * | |
| 6 | + * ----------------------------------------------------------------------- * | |
| 7 | + * * | |
| 8 | + * This program is free software: you can redistribute it and/or modify * | |
| 9 | + * it under the terms of the GNU General Public License as published by * | |
| 10 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 11 | + * (at your option) any later version. * | |
| 12 | + * * | |
| 13 | + * This program is distributed in the hope that it will be useful, * | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 16 | + * GNU General Public License for more details. * | |
| 17 | + * * | |
| 18 | + * You should have received a copy of the GNU General Public License * | |
| 19 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 20 | + * * | |
| 21 | + ***************************************************************************/ | |
| 22 | +/** | |
| 23 | + * @file GModelSpatialEllipticalGeneralGauss.i | |
| 24 | + * @brief Elliptical generalised gauss model class interface definition | |
| 25 | + * @author Luigi Tibaldo | |
| 26 | + */ | |
| 27 | +%{ | |
| 28 | +/* Put headers and other declarations here that are needed for compilation */ | |
| 29 | +#include "GModelSpatialEllipticalGeneralGauss.hpp" | |
| 30 | +%} | |
| 31 | + | |
| 32 | + | |
| 33 | +/***********************************************************************//** | |
| 34 | + * @class GModelSpatialEllipticalGeneralGauss | |
| 35 | + * | |
| 36 | + * @brief Elliptical generalised gauss model class | |
| 37 | + ***************************************************************************/ | |
| 38 | +class GModelSpatialEllipticalGeneralGauss : public GModelSpatialElliptical { | |
| 39 | + | |
| 40 | +public: | |
| 41 | + // Constructors and destructors | |
| 42 | + GModelSpatialEllipticalGeneralGauss(void); | |
| 43 | + GModelSpatialEllipticalGeneralGauss(const GSkyDir& dir, | |
| 44 | + const double& major, | |
| 45 | + const double& minor, | |
| 46 | + const double& posangle, | |
| 47 | + const double& ridx); | |
| 48 | + explicit GModelSpatialEllipticalGeneralGauss(const GXmlElement& xml); | |
| 49 | + GModelSpatialEllipticalGeneralGauss(const GModelSpatialEllipticalGeneralGauss& model); | |
| 50 | + virtual ~GModelSpatialEllipticalGeneralGauss(void); | |
| 51 | + | |
| 52 | + // Implemented pure virtual base class methods | |
| 53 | + virtual void clear(void); | |
| 54 | + virtual GModelSpatialEllipticalGeneralGauss* clone(void) const; | |
| 55 | + virtual std::string classname(void) const; | |
| 56 | + virtual double eval(const double& theta, | |
| 57 | + const double& posangle, | |
| 58 | + const GEnergy& energy, | |
| 59 | + const GTime& time, | |
| 60 | + const bool& gradients = false) const; | |
| 61 | + virtual GSkyDir mc(const GEnergy& energy, | |
| 62 | + const GTime& time, | |
| 63 | + GRan& ran) const; | |
| 64 | + virtual bool contains(const GSkyDir& dir, | |
| 65 | + const double& margin = 0.0) const; | |
| 66 | + virtual double theta_max(void) const; | |
| 67 | + virtual void read(const GXmlElement& xml); | |
| 68 | + virtual void write(GXmlElement& xml) const; | |
| 69 | + | |
| 70 | + // Other methods | |
| 71 | + double ridx(void) const; | |
| 72 | + void ridx(const double& ridx); | |
| 73 | +}; | |
| 74 | + | |
| 75 | + | |
| 76 | +/***********************************************************************//** | |
| 77 | + * @brief GModelSpatialEllipticalGeneralGauss class extension | |
| 78 | + ***************************************************************************/ | |
| 79 | +%extend GModelSpatialEllipticalGeneralGauss { | |
| 80 | + GModelSpatialEllipticalGeneralGauss copy() { | |
| 81 | + return (*self); | |
| 82 | + } | |
| 83 | + double eval(const GPhoton& photon) const { | |
| 84 | + return self->GModelSpatialEllipticalGeneralGauss::eval(photon); | |
| 85 | + } | |
| 86 | + double eval(const GPhoton& photon, const bool& gradients) const { | |
| 87 | + return self->GModelSpatialEllipticalGeneralGauss::eval(photon, gradients); | |
| 88 | + } | |
| 89 | +%pythoncode { | |
| 90 | + def __getstate__(self): | |
| 91 | + xml = gammalib.GXmlElement() | |
| 92 | + self.write(xml) | |
| 93 | + state = (xml,) | |
| 94 | + return state | |
| 95 | + def __setstate__(self, state): | |
| 96 | + self.__init__(state[0]) | |
| 97 | +} | |
| 98 | +}; | ... | ... |
pyext/GModelSpatialRadialGeneralGauss.i
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * GModelSpatialRadialGeneralGauss.i - Generalised radial Gaussian * | |
| 3 | + * source model class * | |
| 4 | + * ----------------------------------------------------------------------- * | |
| 5 | + * copyright (C) 2021-2022 by Luigi Tibaldo * | |
| 6 | + * ----------------------------------------------------------------------- * | |
| 7 | + * * | |
| 8 | + * This program is free software: you can redistribute it and/or modify * | |
| 9 | + * it under the terms of the GNU General Public License as published by * | |
| 10 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 11 | + * (at your option) any later version. * | |
| 12 | + * * | |
| 13 | + * This program is distributed in the hope that it will be useful, * | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 16 | + * GNU General Public License for more details. * | |
| 17 | + * * | |
| 18 | + * You should have received a copy of the GNU General Public License * | |
| 19 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 20 | + * * | |
| 21 | + ***************************************************************************/ | |
| 22 | +/** | |
| 23 | + * @file GModelSpatialRadialGeneralGauss.i | |
| 24 | + * @brief Generalised radial Gaussian model class Python interface definition | |
| 25 | + * @author Luigi Tibaldo | |
| 26 | + */ | |
| 27 | +%{ | |
| 28 | +/* Put headers and other declarations here that are needed for compilation */ | |
| 29 | +#include "GModelSpatialRadialGeneralGauss.hpp" | |
| 30 | +%} | |
| 31 | + | |
| 32 | + | |
| 33 | +/***********************************************************************//** | |
| 34 | + * @class GModelSpatialRadialGeneralGauss | |
| 35 | + * | |
| 36 | + * @brief Generalised radial Gaussian model class | |
| 37 | + ***************************************************************************/ | |
| 38 | +class GModelSpatialRadialGeneralGauss : public GModelSpatialRadial { | |
| 39 | + | |
| 40 | +public: | |
| 41 | + // Constructors and destructors | |
| 42 | + GModelSpatialRadialGeneralGauss(void); | |
| 43 | + GModelSpatialRadialGeneralGauss(const GSkyDir& dir, | |
| 44 | + const double& radius, | |
| 45 | + const double& ridx); | |
| 46 | + explicit GModelSpatialRadialGeneralGauss(const GXmlElement& xml); | |
| 47 | + GModelSpatialRadialGeneralGauss(const GModelSpatialRadialGeneralGauss& model); | |
| 48 | + virtual ~GModelSpatialRadialGeneralGauss(void); | |
| 49 | + | |
| 50 | + // Implemented pure virtual methods | |
| 51 | + virtual void clear(void); | |
| 52 | + virtual GModelSpatialRadialGeneralGauss* clone(void) const; | |
| 53 | + virtual std::string classname(void) const; | |
| 54 | + virtual double eval(const double& theta, | |
| 55 | + const GEnergy& energy, | |
| 56 | + const GTime& time, | |
| 57 | + const bool& gradients = false) const; | |
| 58 | + virtual GSkyDir mc(const GEnergy& energy, | |
| 59 | + const GTime& time, | |
| 60 | + GRan& ran) const; | |
| 61 | + virtual bool contains(const GSkyDir& dir, | |
| 62 | + const double& margin = 0.0) const; | |
| 63 | + virtual double theta_max(void) const; | |
| 64 | + virtual void read(const GXmlElement& xml); | |
| 65 | + virtual void write(GXmlElement& xml) const; | |
| 66 | + | |
| 67 | + // Other methods | |
| 68 | + double radius(void) const; | |
| 69 | + double ridx(void) const; | |
| 70 | + void radius(const double& radius); | |
| 71 | + void ridx(const double& ridx); | |
| 72 | +}; | |
| 73 | + | |
| 74 | + | |
| 75 | +/***********************************************************************//** | |
| 76 | + * @brief GModelSpatialRadialGeneralGauss class extension | |
| 77 | + * | |
| 78 | + * The eval(GPhoton&, bool&) method need to be defined in the extension to | |
| 79 | + * force swig to build also the interface for these methods that are | |
| 80 | + * implemented in the base class only. It's not clear to me why these | |
| 81 | + * methods are not inherited automatically. Maybe this could also be handled | |
| 82 | + * by a %typemap(typecheck) construct. | |
| 83 | + ***************************************************************************/ | |
| 84 | +%extend GModelSpatialRadialGeneralGauss { | |
| 85 | + GModelSpatialRadialGeneralGauss copy() { | |
| 86 | + return (*self); | |
| 87 | + } | |
| 88 | + double eval(const GPhoton& photon) const { | |
| 89 | + return self->GModelSpatialRadialGeneralGauss::eval(photon); | |
| 90 | + } | |
| 91 | + double eval(const GPhoton& photon, const bool& gradients) const { | |
| 92 | + return self->GModelSpatialRadialGeneralGauss::eval(photon, gradients); | |
| 93 | + } | |
| 94 | +%pythoncode { | |
| 95 | + def __getstate__(self): | |
| 96 | + xml = gammalib.GXmlElement() | |
| 97 | + self.write(xml) | |
| 98 | + state = (xml,) | |
| 99 | + return state | |
| 100 | + def __setstate__(self, state): | |
| 101 | + self.__init__(state[0]) | |
| 102 | +} | |
| 103 | +}; | ... | ... |
pyext/gammalib/model.i
| ... | ... | @@ -180,6 +180,7 @@ |
| 180 | 180 | %include "GModelSpatialRadialDisk.i" |
| 181 | 181 | %include "GModelSpatialRadialRing.i" |
| 182 | 182 | %include "GModelSpatialRadialGauss.i" |
| 183 | +%include "GModelSpatialRadialGeneralGauss.i" | |
| 183 | 184 | %include "GModelSpatialRadialShell.i" |
| 184 | 185 | %include "GModelSpatialRadialProfile.i" |
| 185 | 186 | %include "GModelSpatialRadialProfileGauss.i" |
| ... | ... | @@ -189,6 +190,7 @@ |
| 189 | 190 | %include "GModelSpatialElliptical.i" |
| 190 | 191 | %include "GModelSpatialEllipticalDisk.i" |
| 191 | 192 | %include "GModelSpatialEllipticalGauss.i" |
| 193 | +%include "GModelSpatialEllipticalGeneralGauss.i" | |
| 192 | 194 | %include "GModelSpatialDiffuse.i" |
| 193 | 195 | %include "GModelSpatialDiffuseConst.i" |
| 194 | 196 | %include "GModelSpatialDiffuseCube.i" | ... | ... |
src/model/GModelSpatialEllipticalGeneralGauss.cpp
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * GModelSpatialRadialGeneralGauss.cpp - Generalised radial Gaussian * | |
| 3 | + * source model class * | |
| 4 | + * ----------------------------------------------------------------------- * | |
| 5 | + * copyright (C) 2022 by Luigi Tibaldo * | |
| 6 | + * ----------------------------------------------------------------------- * | |
| 7 | + * * | |
| 8 | + * This program is free software: you can redistribute it and/or modify * | |
| 9 | + * it under the terms of the GNU General Public License as published by * | |
| 10 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 11 | + * (at your option) any later version. * | |
| 12 | + * * | |
| 13 | + * This program is distributed in the hope that it will be useful, * | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 16 | + * GNU General Public License for more details. * | |
| 17 | + * * | |
| 18 | + * You should have received a copy of the GNU General Public License * | |
| 19 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 20 | + * * | |
| 21 | + ***************************************************************************/ | |
| 22 | +/** | |
| 23 | + * @file GModelSpatialEllipticalGeneralGauss.cpp | |
| 24 | + * @brief Generalised elliptical Gaussian model class implementation | |
| 25 | + * @author Luigi Tibaldo | |
| 26 | + */ | |
| 27 | + | |
| 28 | +/* __ Includes ___________________________________________________________ */ | |
| 29 | +#ifdef HAVE_CONFIG_H | |
| 30 | +#include <config.h> | |
| 31 | +#endif | |
| 32 | +#include "GException.hpp" | |
| 33 | +#include "GTools.hpp" | |
| 34 | +#include "GMath.hpp" | |
| 35 | +#include "GModelSpatialEllipticalGeneralGauss.hpp" | |
| 36 | +#include "GModelSpatialRadialDisk.hpp" | |
| 37 | +#include "GModelSpatialRegistry.hpp" | |
| 38 | + | |
| 39 | +/* __ Constants __________________________________________________________ */ | |
| 40 | +namespace { | |
| 41 | + const double c_theta_max = 5.0; //!< max distance from center in units of major semiaxis | |
| 42 | +} | |
| 43 | + | |
| 44 | +/* __ Globals ____________________________________________________________ */ | |
| 45 | +const GModelSpatialEllipticalGeneralGauss g_elliptical_general_gauss_seed; | |
| 46 | +const GModelSpatialRegistry g_elliptical_general_gauss_registry(&g_elliptical_general_gauss_seed); | |
| 47 | + | |
| 48 | +/* __ Method name definitions ____________________________________________ */ | |
| 49 | +#define G_READ "GModelSpatialEllipticalGeneralGauss::read(GXmlElement&)" | |
| 50 | +#define G_WRITE "GModelSpatialEllipticalGeneralGauss::write(GXmlElement&)" | |
| 51 | +#define G_MC "GModelSpatialEllipticalGeneralGauss::mc(GEnergy&, GTime&, "\ | |
| 52 | + "GRan&)" | |
| 53 | + | |
| 54 | +/* __ Macros _____________________________________________________________ */ | |
| 55 | + | |
| 56 | +/* __ Coding definitions _________________________________________________ */ | |
| 57 | +#define G_SMALL_ANGLE_APPROXIMATION //!< Use small angle approximation | |
| 58 | + | |
| 59 | +/* __ Debug definitions __________________________________________________ */ | |
| 60 | + | |
| 61 | + | |
| 62 | +/*========================================================================== | |
| 63 | + = = | |
| 64 | + = Constructors/destructors = | |
| 65 | + = = | |
| 66 | + ==========================================================================*/ | |
| 67 | + | |
| 68 | +/***********************************************************************//** | |
| 69 | + * @brief Void constructor | |
| 70 | + ***************************************************************************/ | |
| 71 | +GModelSpatialEllipticalGeneralGauss::GModelSpatialEllipticalGeneralGauss(void) : | |
| 72 | + GModelSpatialElliptical() | |
| 73 | +{ | |
| 74 | + // Initialise members | |
| 75 | + init_members(); | |
| 76 | + | |
| 77 | + // Return | |
| 78 | + return; | |
| 79 | +} | |
| 80 | + | |
| 81 | + | |
| 82 | +/***********************************************************************//** | |
| 83 | + * @brief Elliptical Gaussian constructor | |
| 84 | + * | |
| 85 | + * @param[in] dir Centre of elliptical Gaussian. | |
| 86 | + * @param[in] semimajor Semi-major axis (deg). | |
| 87 | + * @param[in] semiminor Semi-minor axis (deg). | |
| 88 | + * @param[in] posangle Position angle of semi-major axis (deg). | |
| 89 | + * @param[in] ridx Reciprocal of radial profile index. | |
| 90 | + * | |
| 91 | + * Construct elliptical Gaussian model from the ellipse centre direction | |
| 92 | + * (@p dir), the @p semimajor and @p semiminor axes, the position | |
| 93 | + * angle (@p posangle), and the reciprocal of the radial profile index | |
| 94 | + * (@p ridx). | |
| 95 | + ***************************************************************************/ | |
| 96 | +GModelSpatialEllipticalGeneralGauss::GModelSpatialEllipticalGeneralGauss(const GSkyDir& dir, | |
| 97 | + const double& semimajor, | |
| 98 | + const double& semiminor, | |
| 99 | + const double& posangle, | |
| 100 | + const double& ridx) : | |
| 101 | + GModelSpatialElliptical() | |
| 102 | +{ | |
| 103 | + // Initialise members | |
| 104 | + init_members(); | |
| 105 | + | |
| 106 | + // Assign parameters | |
| 107 | + this->dir(dir); | |
| 108 | + this->semiminor(semiminor); | |
| 109 | + this->semimajor(semimajor); | |
| 110 | + this->posangle(posangle); | |
| 111 | + this->ridx(ridx); | |
| 112 | + | |
| 113 | + // Return | |
| 114 | + return; | |
| 115 | +} | |
| 116 | + | |
| 117 | + | |
| 118 | +/***********************************************************************//** | |
| 119 | + * @brief XML constructor | |
| 120 | + * | |
| 121 | + * @param[in] xml XML element. | |
| 122 | + * | |
| 123 | + * Constructs generalised elliptical Gaussian model by extracting information | |
| 124 | + * from an XML element. See the read() method for more information about the | |
| 125 | + * expected structure of the XML element. | |
| 126 | + ***************************************************************************/ | |
| 127 | +GModelSpatialEllipticalGeneralGauss::GModelSpatialEllipticalGeneralGauss(const GXmlElement& xml) : | |
| 128 | + GModelSpatialElliptical() | |
| 129 | +{ | |
| 130 | + // Initialise members | |
| 131 | + init_members(); | |
| 132 | + | |
| 133 | + // Read information from XML element | |
| 134 | + read(xml); | |
| 135 | + | |
| 136 | + // Return | |
| 137 | + return; | |
| 138 | +} | |
| 139 | + | |
| 140 | + | |
| 141 | +/***********************************************************************//** | |
| 142 | + * @brief Copy constructor | |
| 143 | + * | |
| 144 | + * @param[in] model Generalised elliptical Gaussian model. | |
| 145 | + ***************************************************************************/ | |
| 146 | +GModelSpatialEllipticalGeneralGauss::GModelSpatialEllipticalGeneralGauss(const GModelSpatialEllipticalGeneralGauss& model) : | |
| 147 | + GModelSpatialElliptical(model) | |
| 148 | +{ | |
| 149 | + // Initialise members | |
| 150 | + init_members(); | |
| 151 | + | |
| 152 | + // Copy members | |
| 153 | + copy_members(model); | |
| 154 | + | |
| 155 | + // Return | |
| 156 | + return; | |
| 157 | +} | |
| 158 | + | |
| 159 | + | |
| 160 | +/***********************************************************************//** | |
| 161 | + * @brief Destructor | |
| 162 | + ***************************************************************************/ | |
| 163 | +GModelSpatialEllipticalGeneralGauss::~GModelSpatialEllipticalGeneralGauss(void) | |
| 164 | +{ | |
| 165 | + // Free members | |
| 166 | + free_members(); | |
| 167 | + | |
| 168 | + // Return | |
| 169 | + return; | |
| 170 | +} | |
| 171 | + | |
| 172 | + | |
| 173 | +/*========================================================================== | |
| 174 | + = = | |
| 175 | + = Operators = | |
| 176 | + = = | |
| 177 | + ==========================================================================*/ | |
| 178 | + | |
| 179 | +/***********************************************************************//** | |
| 180 | + * @brief Assignment operator | |
| 181 | + * | |
| 182 | + * @param[in] model Generalised elliptical Gaussian model. | |
| 183 | + * @return Generalised elliptical Gaussian model. | |
| 184 | + ***************************************************************************/ | |
| 185 | +GModelSpatialEllipticalGeneralGauss& GModelSpatialEllipticalGeneralGauss::operator=(const GModelSpatialEllipticalGeneralGauss& model) | |
| 186 | +{ | |
| 187 | + // Execute only if object is not identical | |
| 188 | + if (this != &model) { | |
| 189 | + | |
| 190 | + // Copy base class members | |
| 191 | + this->GModelSpatialElliptical::operator=(model); | |
| 192 | + | |
| 193 | + // Free members | |
| 194 | + free_members(); | |
| 195 | + | |
| 196 | + // Initialise members | |
| 197 | + init_members(); | |
| 198 | + | |
| 199 | + // Copy members | |
| 200 | + copy_members(model); | |
| 201 | + | |
| 202 | + } // endif: object was not identical | |
| 203 | + | |
| 204 | + // Return | |
| 205 | + return *this; | |
| 206 | +} | |
| 207 | + | |
| 208 | + | |
| 209 | +/*========================================================================== | |
| 210 | + = = | |
| 211 | + = Public methods = | |
| 212 | + = = | |
| 213 | + ==========================================================================*/ | |
| 214 | + | |
| 215 | +/***********************************************************************//** | |
| 216 | + * @brief Clear generalised elliptical Gaussian model | |
| 217 | + ***************************************************************************/ | |
| 218 | +void GModelSpatialEllipticalGeneralGauss::clear(void) | |
| 219 | +{ | |
| 220 | + // Free class members (base and derived classes, derived class first) | |
| 221 | + free_members(); | |
| 222 | + this->GModelSpatialElliptical::free_members(); | |
| 223 | + this->GModelSpatial::free_members(); | |
| 224 | + | |
| 225 | + // Initialise members | |
| 226 | + this->GModelSpatial::init_members(); | |
| 227 | + this->GModelSpatialElliptical::init_members(); | |
| 228 | + init_members(); | |
| 229 | + | |
| 230 | + // Return | |
| 231 | + return; | |
| 232 | +} | |
| 233 | + | |
| 234 | + | |
| 235 | +/***********************************************************************//** | |
| 236 | + * @brief Clone generalised elliptical Gaussian model | |
| 237 | + * | |
| 238 | + * @return Pointer to deep copy of generalised elliptical Gaussian model. | |
| 239 | + ***************************************************************************/ | |
| 240 | +GModelSpatialEllipticalGeneralGauss* GModelSpatialEllipticalGeneralGauss::clone(void) const | |
| 241 | +{ | |
| 242 | + // Clone generalised elliptical Gaussian model | |
| 243 | + return new GModelSpatialEllipticalGeneralGauss(*this); | |
| 244 | +} | |
| 245 | + | |
| 246 | + | |
| 247 | +/***********************************************************************//** | |
| 248 | + * @brief Evaluate function (in units of sr^-1) | |
| 249 | + * | |
| 250 | + * @param[in] theta Angular distance from disk centre (radians). | |
| 251 | + * @param[in] posangle Position angle (counterclockwise from North) (radians). | |
| 252 | + * @param[in] energy Photon energy. | |
| 253 | + * @param[in] time Photon arrival time. | |
| 254 | + * @param[in] gradients Compute gradients? | |
| 255 | + * @return Model value. | |
| 256 | + * | |
| 257 | + * Evaluates the spatial component for a generalised elliptical Gaussian | |
| 258 | + * source model. | |
| 259 | + * | |
| 260 | + * The generalised elliptical Gaussian function is defined by | |
| 261 | + * \f$S_{\rm p}(\theta, \phi | E, t)\f$, where | |
| 262 | + * \f$\theta\f$ is the angular separation between elliptical Gaussian centre | |
| 263 | + * and the actual location and \f$\phi\f$ the position angle with respect to | |
| 264 | + * the model centre, counted counterclockwise from North. | |
| 265 | + * | |
| 266 | + * The function \f$S_{\rm p}(\theta, \phi | E, t)\f$ is given by | |
| 267 | + * | |
| 268 | + * \f[ | |
| 269 | + * S_{\rm p}(\theta, \phi | E, t) = {\tt m\_norm} \times | |
| 270 | + * \exp \left( -\left(\frac{\theta}{r_{\rm eff}}\right)^1/\eta \right) | |
| 271 | + * \f] | |
| 272 | + * | |
| 273 | + * where the effective ellipse radius \f$r_{\rm eff}\f$ towards a given | |
| 274 | + * position angle is given by | |
| 275 | + * | |
| 276 | + * \f[ | |
| 277 | + * r_{\rm eff} = \frac{ab} | |
| 278 | + * {\sqrt{\left( a \sin (\phi - \phi_0) \right)^2} + | |
| 279 | + * \sqrt{\left( b \cos (\phi - \phi_0) \right)^2}} | |
| 280 | + * \f] | |
| 281 | + * and | |
| 282 | + * \f$a\f$ is the semi-major axis of the ellipse, | |
| 283 | + * \f$b\f$ is the semi-minor axis, | |
| 284 | + * \f$\phi_0\f$ is the position angle of the ellipse, counted | |
| 285 | + * counterclockwise from North, and | |
| 286 | + * \f$\et\f$ is the reciprocal of the radial profile index | |
| 287 | + * \f${\tt m\_norm}\f$ is a normalization constant given by | |
| 288 | + * | |
| 289 | + * \f[ | |
| 290 | + * {\tt m\_norm} = \frac{1}{2 \pi a b \eta \Gamma(\eta)} | |
| 291 | + * \f] | |
| 292 | + * | |
| 293 | + * The method will not compute analytical parameter gradients, even if the | |
| 294 | + * @p gradients argument is set to true. Parameter gradients | |
| 295 | + * need to be computed numerically. | |
| 296 | + * | |
| 297 | + * @warning | |
| 298 | + * The above formula for an elliptical generalised Gaussian are accurate for small | |
| 299 | + * angles, with semimajor and semiminor axes below a few degrees. This | |
| 300 | + * should be fine for most use cases, but you should be aware that the | |
| 301 | + * ellipse will get distorted for larger angles. | |
| 302 | + * Note that the model normalisation is only correct in the small angle | |
| 303 | + * approximation and for \f$\eta\f$ order unity or smaller. | |
| 304 | + ***************************************************************************/ | |
| 305 | +double GModelSpatialEllipticalGeneralGauss::eval(const double& theta, | |
| 306 | + const double& posangle, | |
| 307 | + const GEnergy& energy, | |
| 308 | + const GTime& time, | |
| 309 | + const bool& gradients) const | |
| 310 | +{ | |
| 311 | + // Initialise value | |
| 312 | + double value = 0.0; | |
| 313 | + | |
| 314 | + // Continue only if we're inside circle enclosing the ellipse | |
| 315 | + if (theta <= theta_max()) { | |
| 316 | + | |
| 317 | + // Update precomputation cache | |
| 318 | + update(); | |
| 319 | + | |
| 320 | + // Perform computations to compute exponent | |
| 321 | + #if defined(G_SMALL_ANGLE_APPROXIMATION) | |
| 322 | + double rel_posangle = posangle - this->posangle() * gammalib::deg2rad; | |
| 323 | + double cosinus = std::cos(rel_posangle); | |
| 324 | + double sinus = std::sin(rel_posangle); | |
| 325 | + double arg1 = m_minor_rad * cosinus; | |
| 326 | + double arg2 = m_major_rad * sinus; | |
| 327 | + double r_ellipse = m_minor_rad * m_major_rad / | |
| 328 | + std::sqrt(arg1*arg1 + arg2*arg2); //!< small angle | |
| 329 | + double r_relative = theta/r_ellipse; | |
| 330 | + double exponent = std::pow(r_relative,m_inv_ridx); | |
| 331 | + #else | |
| 332 | + // Perform computations | |
| 333 | + double sinphi = std::sin(posangle); | |
| 334 | + double cosphi = std::cos(posangle); | |
| 335 | + | |
| 336 | + // Compute help term | |
| 337 | + double term1 = m_term1 * cosphi * cosphi; | |
| 338 | + double term2 = m_term2 * sinphi * sinphi; | |
| 339 | + double term3 = m_term3 * sinphi * cosphi; | |
| 340 | + | |
| 341 | + // Compute exponent | |
| 342 | + double exponent = std::pow(theta * std::sqrt(term1 + term2 + term3), m_inv_ridx) ; | |
| 343 | + #endif | |
| 344 | + | |
| 345 | + // Set value | |
| 346 | + value = m_norm * std::exp(-exponent); | |
| 347 | + | |
| 348 | + // Compile option: Check for NaN/Inf | |
| 349 | + #if defined(G_NAN_CHECK) | |
| 350 | + if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) { | |
| 351 | + std::cout << "*** ERROR: GModelSpatialEllipticalGeneralGauss::eval"; | |
| 352 | + std::cout << "(theta=" << theta << "): NaN/Inf encountered"; | |
| 353 | + std::cout << "(posangle=" << posangle << "): NaN/Inf encountered"; | |
| 354 | + std::cout << " (value=" << value; | |
| 355 | + std::cout << ", MinorAxis^2=" << m_minor2; | |
| 356 | + std::cout << ", MaxjorAxis^2=" << m_major2; | |
| 357 | + std::cout << ", m_norm=" << m_norm; | |
| 358 | + std::cout << ")" << std::endl; | |
| 359 | + } | |
| 360 | + #endif | |
| 361 | + | |
| 362 | + } // endif: position was inside enclosing circle | |
| 363 | + | |
| 364 | + // Return value | |
| 365 | + return value; | |
| 366 | +} | |
| 367 | + | |
| 368 | + | |
| 369 | +/***********************************************************************//** | |
| 370 | + * @brief Returns MC sky direction | |
| 371 | + * | |
| 372 | + * @param[in] energy Photon energy. | |
| 373 | + * @param[in] time Photon arrival time. | |
| 374 | + * @param[in,out] ran Random number generator. | |
| 375 | + * @return Sky direction. | |
| 376 | + * | |
| 377 | + * Draws an arbitrary sky direction from the elliptical generalised | |
| 378 | + * Gaussian model. | |
| 379 | + ***************************************************************************/ | |
| 380 | +GSkyDir GModelSpatialEllipticalGeneralGauss::mc(const GEnergy& energy, | |
| 381 | + const GTime& time, | |
| 382 | + GRan& ran) const | |
| 383 | +{ | |
| 384 | + // Update precomputation cache | |
| 385 | + update(); | |
| 386 | + | |
| 387 | + // Initialise simulation | |
| 388 | + #if defined(G_DEBUG_MC) | |
| 389 | + int n_samples = 0; | |
| 390 | + #endif | |
| 391 | + double u_max = m_norm * std::sin(theta_max()); | |
| 392 | + double value = 0.0; | |
| 393 | + double u = 1.0; | |
| 394 | + double theta = 0.0; | |
| 395 | + double phi = 0.0; | |
| 396 | + | |
| 397 | + // Throw an exception if the maximum value is zero | |
| 398 | + if (u_max <= 0.0) { | |
| 399 | + std::string msg = "Non positive maximum ellpitical general Gauss model value."; | |
| 400 | + throw GException::invalid_return_value(G_MC, msg); | |
| 401 | + } | |
| 402 | + | |
| 403 | + // Simulate offset from photon arrival direction using a rejection method | |
| 404 | + do { | |
| 405 | + theta = ran.uniform() * theta_max(); | |
| 406 | + phi = ran.uniform() * gammalib::twopi; | |
| 407 | + value = eval(theta, phi, energy, time) * std::sin(theta); | |
| 408 | + u = ran.uniform() * u_max; | |
| 409 | + #if defined(G_DEBUG_MC) | |
| 410 | + n_samples++; | |
| 411 | + #endif | |
| 412 | + } while (u > value); | |
| 413 | + #if defined(G_DEBUG_MC) | |
| 414 | + std::cout << "#=" << n_samples << " "; | |
| 415 | + #endif | |
| 416 | + | |
| 417 | + // Rotate pointing direction by offset and azimuth angle | |
| 418 | + GSkyDir sky_dir = dir(); | |
| 419 | + sky_dir.rotate_deg(phi * gammalib::rad2deg, theta * gammalib::rad2deg); | |
| 420 | + | |
| 421 | + // Return sky direction | |
| 422 | + return sky_dir; | |
| 423 | +} | |
| 424 | + | |
| 425 | + | |
| 426 | +/***********************************************************************//** | |
| 427 | + * @brief Checks whether model contains specified sky direction | |
| 428 | + * | |
| 429 | + * @param[in] dir Sky direction. | |
| 430 | + * @param[in] margin Margin to be added to sky direction (deg). | |
| 431 | + * @return True if the model contains the sky direction. | |
| 432 | + * | |
| 433 | + * Signals whether a sky direction is contained in the elliptical gauss | |
| 434 | + * model. | |
| 435 | + * | |
| 436 | + * @todo Implement correct evaluation of effective ellipse radius. | |
| 437 | + ***************************************************************************/ | |
| 438 | +bool GModelSpatialEllipticalGeneralGauss::contains(const GSkyDir& dir, | |
| 439 | + const double& margin) const | |
| 440 | +{ | |
| 441 | + // Compute distance to centre (radian) | |
| 442 | + double distance = dir.dist(this->dir()); | |
| 443 | + | |
| 444 | + // Return flag | |
| 445 | + return (distance <= theta_max() + margin*gammalib::deg2rad); | |
| 446 | +} | |
| 447 | + | |
| 448 | + | |
| 449 | +/***********************************************************************//** | |
| 450 | + * @brief Return maximum model radius (in radians) | |
| 451 | + * | |
| 452 | + * @return Returns maximum model radius (radians). | |
| 453 | + * | |
| 454 | + * Returns the maximum of 3.0 semimajor() and 3.0 semiminor() as | |
| 455 | + * approximate edge of the Gaussian. This limit is of course arbitrary, but | |
| 456 | + * allows to limit the integration region for response computation. The value | |
| 457 | + * of 3.0 has been determined by experiment (#1561). | |
| 458 | + ***************************************************************************/ | |
| 459 | +double GModelSpatialEllipticalGeneralGauss::theta_max(void) const | |
| 460 | +{ | |
| 461 | + // Set maximum model radius | |
| 462 | + double theta_max = (semimajor() > semiminor()) | |
| 463 | + ? semimajor() * gammalib::deg2rad * c_theta_max | |
| 464 | + : semiminor() * gammalib::deg2rad * c_theta_max; | |
| 465 | + | |
| 466 | + // Return value | |
| 467 | + return theta_max; | |
| 468 | +} | |
| 469 | + | |
| 470 | + | |
| 471 | +/***********************************************************************//** | |
| 472 | + * @brief Read model from XML element | |
| 473 | + * | |
| 474 | + * @param[in] xml XML element. | |
| 475 | + * | |
| 476 | + * Reads the elliptical gauss model information from an XML element. The XML | |
| 477 | + * element shall have either the format | |
| 478 | + * | |
| 479 | + * <spatialModel type="EllipticalGeneralGaussian"> | |
| 480 | + * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> | |
| 481 | + * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> | |
| 482 | + * <parameter name="PA" scale="1.0" value="45.0" min="-360" max="360" free="1"/> | |
| 483 | + * <parameter name="MinorRadius" scale="1.0" value="0.5" min="0.001" max="10" free="1"/> | |
| 484 | + * <parameter name="MajorRadius" scale="1.0" value="2.0" min="0.001" max="10" free="1"/> | |
| 485 | + * <parameter name="R_Index" scale="1.0" value="0.5" min="0.01" max="10" free="1"/> | |
| 486 | + * </spatialModel> | |
| 487 | + * | |
| 488 | + * or | |
| 489 | + * | |
| 490 | + * <spatialModel type="EllipticalGeneralGaussian"> | |
| 491 | + * <parameter name="GLON" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> | |
| 492 | + * <parameter name="GLAT" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> | |
| 493 | + * <parameter name="PA" scale="1.0" value="45.0" min="-360" max="360" free="1"/> | |
| 494 | + * <parameter name="MinorRadius" scale="1.0" value="0.5" min="0.001" max="10" free="1"/> | |
| 495 | + * <parameter name="MajorRadius" scale="1.0" value="2.0" min="0.001" max="10" free="1"/> | |
| 496 | + * <parameter name="R_Index" scale="1.0" value="0.5" min="0.01" max="10" free="1"/> | |
| 497 | + * </spatialModel> | |
| 498 | + * | |
| 499 | + * @todo Implement a test of the ellipse boundary. The axes | |
| 500 | + * and axes minimum should be >0. | |
| 501 | + ***************************************************************************/ | |
| 502 | +void GModelSpatialEllipticalGeneralGauss::read(const GXmlElement& xml) | |
| 503 | +{ | |
| 504 | + // Verify number of model parameters | |
| 505 | + gammalib::xml_check_parnum(G_READ, xml, 6); | |
| 506 | + | |
| 507 | + // Read gauss location | |
| 508 | + GModelSpatialElliptical::read(xml); | |
| 509 | + | |
| 510 | + // Get parameters | |
| 511 | + const GXmlElement* minor = gammalib::xml_get_par(G_READ, xml, m_semiminor.name()); | |
| 512 | + const GXmlElement* major = gammalib::xml_get_par(G_READ, xml, m_semimajor.name()); | |
| 513 | + const GXmlElement* ridx = gammalib::xml_get_par(G_READ, xml, m_ridx.name()); | |
| 514 | + | |
| 515 | + // Read parameters | |
| 516 | + m_semiminor.read(*minor); | |
| 517 | + m_semimajor.read(*major); | |
| 518 | + m_ridx.read(*ridx); | |
| 519 | + | |
| 520 | + // Return | |
| 521 | + return; | |
| 522 | +} | |
| 523 | + | |
| 524 | + | |
| 525 | +/***********************************************************************//** | |
| 526 | + * @brief Write model into XML element | |
| 527 | + * | |
| 528 | + * @param[in] xml XML element into which model information is written. | |
| 529 | + * | |
| 530 | + * Write the elliptical gauss model information into an XML element. The XML | |
| 531 | + * element will have the format | |
| 532 | + * | |
| 533 | + * <spatialModel type="EllipticalGeneralGaussian"> | |
| 534 | + * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> | |
| 535 | + * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> | |
| 536 | + * <parameter name="PA" scale="1.0" value="45.0" min="-360" max="360" free="1"/> | |
| 537 | + * <parameter name="MinorRadius" scale="1.0" value="0.5" min="0.001" max="10" free="1"/> | |
| 538 | + * <parameter name="MajorRadius" scale="1.0" value="2.0" min="0.001" max="10" free="1"/> | |
| 539 | + * <parameter name="R_Index" scale="1.0" value="0.5" min="0.01" max="10" free="1"/> | |
| 540 | + * </spatialModel> | |
| 541 | + * | |
| 542 | + ***************************************************************************/ | |
| 543 | +void GModelSpatialEllipticalGeneralGauss::write(GXmlElement& xml) const | |
| 544 | +{ | |
| 545 | + // Verify model type | |
| 546 | + gammalib::xml_check_type(G_WRITE, xml, type()); | |
| 547 | + | |
| 548 | + // Write disk location | |
| 549 | + GModelSpatialElliptical::write(xml); | |
| 550 | + | |
| 551 | + // Get or create parameters | |
| 552 | + GXmlElement* minor = gammalib::xml_need_par(G_WRITE, xml, m_semiminor.name()); | |
| 553 | + GXmlElement* major = gammalib::xml_need_par(G_WRITE, xml, m_semimajor.name()); | |
| 554 | + GXmlElement* ridx = gammalib::xml_need_par(G_WRITE, xml, m_ridx.name()); | |
| 555 | + | |
| 556 | + // Write parameters | |
| 557 | + m_semiminor.write(*minor); | |
| 558 | + m_semimajor.write(*major); | |
| 559 | + m_ridx.write(*ridx); | |
| 560 | + | |
| 561 | + // Return | |
| 562 | + return; | |
| 563 | +} | |
| 564 | + | |
| 565 | + | |
| 566 | +/***********************************************************************//** | |
| 567 | + * @brief Print information | |
| 568 | + * | |
| 569 | + * @param[in] chatter Chattiness. | |
| 570 | + * @return String containing model information. | |
| 571 | + ***************************************************************************/ | |
| 572 | +std::string GModelSpatialEllipticalGeneralGauss::print(const GChatter& chatter) const | |
| 573 | +{ | |
| 574 | + // Initialise result string | |
| 575 | + std::string result; | |
| 576 | + | |
| 577 | + // Continue only if chatter is not silent | |
| 578 | + if (chatter != SILENT) { | |
| 579 | + | |
| 580 | + // Append header | |
| 581 | + result.append("=== GModelSpatialEllipticalGeneralGauss ==="); | |
| 582 | + | |
| 583 | + // Append parameters | |
| 584 | + result.append("\n"+gammalib::parformat("Number of parameters")); | |
| 585 | + result.append(gammalib::str(size())); | |
| 586 | + for (int i = 0; i < size(); ++i) { | |
| 587 | + result.append("\n"+m_pars[i]->print(chatter)); | |
| 588 | + } | |
| 589 | + | |
| 590 | + } // endif: chatter was not silent | |
| 591 | + | |
| 592 | + // Return result | |
| 593 | + return result; | |
| 594 | +} | |
| 595 | + | |
| 596 | + | |
| 597 | +/*========================================================================== | |
| 598 | + = = | |
| 599 | + = Private methods = | |
| 600 | + = = | |
| 601 | + ==========================================================================*/ | |
| 602 | + | |
| 603 | +/***********************************************************************//** | |
| 604 | + * @brief Initialise class members | |
| 605 | + ***************************************************************************/ | |
| 606 | +void GModelSpatialEllipticalGeneralGauss::init_members(void) | |
| 607 | +{ | |
| 608 | + // Initialise model type | |
| 609 | + m_type = "EllipticalGeneralGaussian"; | |
| 610 | + | |
| 611 | + // Initialise Reciprocal index | |
| 612 | + m_ridx.clear(); | |
| 613 | + m_ridx.name("R_Index"); | |
| 614 | + m_ridx.value(0.5); // Gaussian | |
| 615 | + m_ridx.min(1.e-15); // need to be > 0 | |
| 616 | + m_ridx.free(); | |
| 617 | + m_ridx.scale(1.0); | |
| 618 | + m_ridx.gradient(0.0); | |
| 619 | + m_ridx.has_grad(false); | |
| 620 | + | |
| 621 | + // Set parameter pointer(s) | |
| 622 | + m_pars.push_back(&m_ridx); | |
| 623 | + | |
| 624 | + // Initialise precomputation cache. Note that zero values flag | |
| 625 | + // uninitialised as a zero radius is not meaningful | |
| 626 | + m_last_minor = 0.0; | |
| 627 | + m_last_major = 0.0; | |
| 628 | + m_minor_rad = 0.0; | |
| 629 | + m_major_rad = 0.0; | |
| 630 | + m_norm = 0.0; | |
| 631 | + m_last_posangle = 9999.0; // Signals that has not been initialised | |
| 632 | + m_sin2pos = 0.0; | |
| 633 | + m_cospos2 = 0.0; | |
| 634 | + m_sinpos2 = 0.0; | |
| 635 | + m_minor2 = 0.0; | |
| 636 | + m_major2 = 0.0; | |
| 637 | + m_term1 = 0.0; | |
| 638 | + m_term2 = 0.0; | |
| 639 | + m_term3 = 0.0; | |
| 640 | + m_last_ridx = 0.0; | |
| 641 | + m_inv_ridx = 0.0; | |
| 642 | + | |
| 643 | + // Return | |
| 644 | + return; | |
| 645 | +} | |
| 646 | + | |
| 647 | + | |
| 648 | +/***********************************************************************//** | |
| 649 | + * @brief Copy class members | |
| 650 | + * | |
| 651 | + * @param[in] model Elliptical Gaussian model. | |
| 652 | + ***************************************************************************/ | |
| 653 | +void GModelSpatialEllipticalGeneralGauss::copy_members(const GModelSpatialEllipticalGeneralGauss& model) | |
| 654 | +{ | |
| 655 | + // Copy members | |
| 656 | + m_type = model.m_type; // Needed to conserve model type | |
| 657 | + m_ridx = model.m_ridx; | |
| 658 | + | |
| 659 | + // Copy precomputation cache | |
| 660 | + m_last_minor = model.m_last_minor; | |
| 661 | + m_last_major = model.m_last_major; | |
| 662 | + m_minor_rad = model.m_minor_rad; | |
| 663 | + m_major_rad = model.m_major_rad; | |
| 664 | + m_norm = model.m_norm; | |
| 665 | + m_last_posangle = model.m_last_posangle; | |
| 666 | + m_sin2pos = model.m_sin2pos; | |
| 667 | + m_cospos2 = model.m_cospos2; | |
| 668 | + m_sinpos2 = model.m_sinpos2; | |
| 669 | + m_minor2 = model.m_minor2; | |
| 670 | + m_major2 = model.m_major2; | |
| 671 | + m_term1 = model.m_term1; | |
| 672 | + m_term2 = model.m_term2; | |
| 673 | + m_term3 = model.m_term3; | |
| 674 | + m_last_ridx = model.m_last_ridx; | |
| 675 | + m_inv_ridx = model.m_inv_ridx; | |
| 676 | + | |
| 677 | + // Return | |
| 678 | + return; | |
| 679 | +} | |
| 680 | + | |
| 681 | + | |
| 682 | +/***********************************************************************//** | |
| 683 | + * @brief Delete class members | |
| 684 | + ***************************************************************************/ | |
| 685 | +void GModelSpatialEllipticalGeneralGauss::free_members(void) | |
| 686 | +{ | |
| 687 | + // Return | |
| 688 | + return; | |
| 689 | +} | |
| 690 | + | |
| 691 | + | |
| 692 | +/***********************************************************************//** | |
| 693 | + * @brief Update precomputation cache | |
| 694 | + * | |
| 695 | + * Computes the normalization | |
| 696 | + * \f[ | |
| 697 | + * {\tt m\_norm} = \frac{1}{2 \pi \times a \times b} | |
| 698 | + * \f] | |
| 699 | + * where | |
| 700 | + * \f$a\f$ is the semi-major axis and | |
| 701 | + * \f$b\f$ is the semi-minor axis of the ellipse. | |
| 702 | + * | |
| 703 | + * @warning | |
| 704 | + * The normalization of the elliptical Gaussian is only valid in the small | |
| 705 | + * angle approximation. | |
| 706 | + ***************************************************************************/ | |
| 707 | +void GModelSpatialEllipticalGeneralGauss::update() const | |
| 708 | +{ | |
| 709 | + // Initialise flag if something has changed | |
| 710 | + bool changed = false; | |
| 711 | + | |
| 712 | + // Update if one axis has changed or radial profile index has changed | |
| 713 | + if (m_last_minor != semiminor() || m_last_major != semimajor() || m_last_ridx != ridx()) { | |
| 714 | + | |
| 715 | + // Signal parameter changes | |
| 716 | + changed = true; | |
| 717 | + | |
| 718 | + // Store last values | |
| 719 | + m_last_minor = semiminor(); | |
| 720 | + m_last_major = semimajor(); | |
| 721 | + m_last_ridx = ridx(); | |
| 722 | + | |
| 723 | + // Compute axes in radians | |
| 724 | + m_minor_rad = m_last_minor * gammalib::deg2rad; | |
| 725 | + m_major_rad = m_last_major * gammalib::deg2rad; | |
| 726 | + | |
| 727 | + // Perform precomputations. Note also | |
| 728 | + // that the model normalisation is only correct in the small angle | |
| 729 | + // approximation and for ridx order unity or smaller. | |
| 730 | + if (m_minor_rad > 0.0 and m_major_rad > 0.0 and ridx() > 0.0) { | |
| 731 | + m_inv_ridx = 1.0 / ridx() ; | |
| 732 | + m_norm = 1.0 / (gammalib::twopi * m_minor_rad * m_major_rad * ridx() * | |
| 733 | + std::exp(gammalib::gammln(2.0 * ridx())) ); | |
| 734 | + } | |
| 735 | + else { | |
| 736 | + m_inv_ridx = 1.0; | |
| 737 | + m_norm = 0.0; | |
| 738 | + } | |
| 739 | + | |
| 740 | + } // endif: update required | |
| 741 | + | |
| 742 | + // Update chache if position angle changed | |
| 743 | + #if !defined(G_SMALL_ANGLE_APPROXIMATION) | |
| 744 | + if (m_last_posangle != posangle()) { | |
| 745 | + | |
| 746 | + // Signal parameter changes | |
| 747 | + changed = true; | |
| 748 | + | |
| 749 | + // Store last value | |
| 750 | + m_last_posangle = posangle(); | |
| 751 | + | |
| 752 | + // Compute angle in radians | |
| 753 | + double posangle_rad = m_last_posangle * gammalib::deg2rad; | |
| 754 | + | |
| 755 | + // Compute sine and cosine | |
| 756 | + double cospos = std::cos(posangle_rad); | |
| 757 | + double sinpos = std::sin(posangle_rad); | |
| 758 | + | |
| 759 | + // Cache important values for further computations | |
| 760 | + m_cospos2 = cospos * cospos; | |
| 761 | + m_sinpos2 = sinpos * sinpos; | |
| 762 | + m_sin2pos = std::sin(2.0 * posangle_rad); | |
| 763 | + | |
| 764 | + } // endif: position angle update required | |
| 765 | + | |
| 766 | + // Perform precomputations in case anything has changed | |
| 767 | + if (changed) { | |
| 768 | + | |
| 769 | + // Compute help terms | |
| 770 | + m_term1 = 0.5 * (m_cospos2 / m_minor2 + m_sinpos2 / m_major2); | |
| 771 | + m_term2 = 0.5 * (m_cospos2 / m_major2 + m_sinpos2 / m_minor2); | |
| 772 | + m_term3 = 0.5 * (m_sin2pos / m_major2 - m_sin2pos / m_minor2); | |
| 773 | + | |
| 774 | + } // endif: something has changed | |
| 775 | + #endif | |
| 776 | + | |
| 777 | + // Return | |
| 778 | + return; | |
| 779 | +} | |
| 780 | + | |
| 781 | + | |
| 782 | +/***********************************************************************//** | |
| 783 | + * @brief Set boundary sky region | |
| 784 | + ***************************************************************************/ | |
| 785 | +void GModelSpatialEllipticalGeneralGauss::set_region(void) const | |
| 786 | +{ | |
| 787 | + // Set maximum model radius | |
| 788 | + double max_radius = (semimajor() > semiminor()) ? semimajor() : semiminor(); | |
| 789 | + | |
| 790 | + // Set sky region circle (maximum Gaussian sigma times a scaling | |
| 791 | + // factor (actually 5)) | |
| 792 | + GSkyRegionCircle region(m_ra.value(), m_dec.value(), max_radius * c_theta_max); | |
| 793 | + | |
| 794 | + // Set region (circumvent const correctness) | |
| 795 | + const_cast<GModelSpatialEllipticalGeneralGauss*>(this)->m_region = region; | |
| 796 | + | |
| 797 | + // Return | |
| 798 | + return; | |
| 799 | +} | ... | ... |
src/model/GModelSpatialRadialGeneralGauss.cpp
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * GModelSpatialRadialGeneralGauss.cpp - Generalised radial Gaussian * | |
| 3 | + * source model class * | |
| 4 | + * ----------------------------------------------------------------------- * | |
| 5 | + * copyright (C) 2021-2022 by Luigi Tibaldo * | |
| 6 | + * ----------------------------------------------------------------------- * | |
| 7 | + * * | |
| 8 | + * This program is free software: you can redistribute it and/or modify * | |
| 9 | + * it under the terms of the GNU General Public License as published by * | |
| 10 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 11 | + * (at your option) any later version. * | |
| 12 | + * * | |
| 13 | + * This program is distributed in the hope that it will be useful, * | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 16 | + * GNU General Public License for more details. * | |
| 17 | + * * | |
| 18 | + * You should have received a copy of the GNU General Public License * | |
| 19 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 20 | + * * | |
| 21 | + ***************************************************************************/ | |
| 22 | +/** | |
| 23 | + * @file GModelSpatialRadialGeneralGauss.cpp | |
| 24 | + * @brief Radial Generallized Gaussian model class implementation | |
| 25 | + * @author Luigi Tibaldo | |
| 26 | + */ | |
| 27 | + | |
| 28 | +/* __ Includes ___________________________________________________________ */ | |
| 29 | +#ifdef HAVE_CONFIG_H | |
| 30 | +#include <config.h> | |
| 31 | +#endif | |
| 32 | +#include "GException.hpp" | |
| 33 | +#include "GTools.hpp" | |
| 34 | +#include "GMath.hpp" | |
| 35 | +#include "GModelSpatialRadialGeneralGauss.hpp" | |
| 36 | +#include "GModelSpatialRegistry.hpp" | |
| 37 | + | |
| 38 | +/* __ Constants __________________________________________________________ */ | |
| 39 | + | |
| 40 | +/* __ Globals ____________________________________________________________ */ | |
| 41 | +const GModelSpatialRadialGeneralGauss g_radial_general_gauss_seed; | |
| 42 | +const GModelSpatialRegistry g_radial_general_gauss_registry(&g_radial_general_gauss_seed); | |
| 43 | + | |
| 44 | +/* __ Method name definitions ____________________________________________ */ | |
| 45 | +#define G_EVAL "GModelSpatialRadialGeneralGauss::eval(double&, GEnergy&, "\ | |
| 46 | + "GTime&, bool&)" | |
| 47 | +#define G_READ "GModelSpatialRadialGeneralGauss::read(GXmlElement&)" | |
| 48 | +#define G_WRITE "GModelSpatialRadialGeneralGauss::write(GXmlElement&)" | |
| 49 | +#define G_MC "GModelSpatialRadialGeneralGauss::mc(GEnergy&, GTime&, GRan&)" | |
| 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 Gaussian model. | |
| 68 | + ***************************************************************************/ | |
| 69 | +GModelSpatialRadialGeneralGauss::GModelSpatialRadialGeneralGauss(void) : | |
| 70 | + GModelSpatialRadial() | |
| 71 | +{ | |
| 72 | + // Initialise members | |
| 73 | + init_members(); | |
| 74 | + | |
| 75 | + // Return | |
| 76 | + return; | |
| 77 | +} | |
| 78 | + | |
| 79 | + | |
| 80 | +/***********************************************************************//** | |
| 81 | + * @brief Constructor | |
| 82 | + * | |
| 83 | + * @param[in] dir Sky position of Gaussian. | |
| 84 | + * @param[in] radius Width of generalised Gaussian (deg). | |
| 85 | + * @param[in] ridx Reciprocal of exponential index of radial profile. | |
| 86 | + * | |
| 87 | + * Constructs a generalised Gaussian spatial model using a sky direction | |
| 88 | + * (@p dir), a Gaussian width parameter @p radius in degrees and a reciprocal | |
| 89 | + * of the exponential index @p ridx. | |
| 90 | + ***************************************************************************/ | |
| 91 | +GModelSpatialRadialGeneralGauss::GModelSpatialRadialGeneralGauss(const GSkyDir& dir, | |
| 92 | + const double& radius, | |
| 93 | + const double& ridx) : | |
| 94 | + GModelSpatialRadial() | |
| 95 | +{ | |
| 96 | + // Initialise members | |
| 97 | + init_members(); | |
| 98 | + | |
| 99 | + // Assign direction and radius | |
| 100 | + this->dir(dir); | |
| 101 | + this->radius(radius); | |
| 102 | + this->ridx(ridx); | |
| 103 | + | |
| 104 | + // Return | |
| 105 | + return; | |
| 106 | +} | |
| 107 | + | |
| 108 | + | |
| 109 | +/***********************************************************************//** | |
| 110 | + * @brief XML constructor | |
| 111 | + * | |
| 112 | + * @param[in] xml XML element. | |
| 113 | + * | |
| 114 | + * Constructs a generalised Gaussian spatial model by extracting information | |
| 115 | + * from an XML element. See the method read() for more information about the | |
| 116 | + * expected structure of the XML element. | |
| 117 | + ***************************************************************************/ | |
| 118 | +GModelSpatialRadialGeneralGauss::GModelSpatialRadialGeneralGauss(const GXmlElement& xml) : | |
| 119 | + GModelSpatialRadial() | |
| 120 | +{ | |
| 121 | + // Initialise members | |
| 122 | + init_members(); | |
| 123 | + | |
| 124 | + // Read information from XML element | |
| 125 | + read(xml); | |
| 126 | + | |
| 127 | + // Return | |
| 128 | + return; | |
| 129 | +} | |
| 130 | + | |
| 131 | + | |
| 132 | +/***********************************************************************//** | |
| 133 | + * @brief Copy constructor | |
| 134 | + * | |
| 135 | + * @param[in] model Generalised radial Gaussian model. | |
| 136 | + ***************************************************************************/ | |
| 137 | +GModelSpatialRadialGeneralGauss::GModelSpatialRadialGeneralGauss(const GModelSpatialRadialGeneralGauss& model) : | |
| 138 | + GModelSpatialRadial(model) | |
| 139 | +{ | |
| 140 | + // Initialise members | |
| 141 | + init_members(); | |
| 142 | + | |
| 143 | + // Copy members | |
| 144 | + copy_members(model); | |
| 145 | + | |
| 146 | + // Return | |
| 147 | + return; | |
| 148 | +} | |
| 149 | + | |
| 150 | + | |
| 151 | +/***********************************************************************//** | |
| 152 | + * @brief Destructor | |
| 153 | + ***************************************************************************/ | |
| 154 | +GModelSpatialRadialGeneralGauss::~GModelSpatialRadialGeneralGauss(void) | |
| 155 | +{ | |
| 156 | + // Free members | |
| 157 | + free_members(); | |
| 158 | + | |
| 159 | + // Return | |
| 160 | + return; | |
| 161 | +} | |
| 162 | + | |
| 163 | + | |
| 164 | +/*========================================================================== | |
| 165 | + = = | |
| 166 | + = Operators = | |
| 167 | + = = | |
| 168 | + ==========================================================================*/ | |
| 169 | + | |
| 170 | +/***********************************************************************//** | |
| 171 | + * @brief Assignment operator | |
| 172 | + * | |
| 173 | + * @param[in] model Generalised radial Gaussian model. | |
| 174 | + * @return Radial Generalised radial Gaussian model. | |
| 175 | + ***************************************************************************/ | |
| 176 | +GModelSpatialRadialGeneralGauss& GModelSpatialRadialGeneralGauss::operator=(const GModelSpatialRadialGeneralGauss& model) | |
| 177 | +{ | |
| 178 | + // Execute only if object is not identical | |
| 179 | + if (this != &model) { | |
| 180 | + | |
| 181 | + // Copy base class members | |
| 182 | + this->GModelSpatialRadial::operator=(model); | |
| 183 | + | |
| 184 | + // Free members | |
| 185 | + free_members(); | |
| 186 | + | |
| 187 | + // Initialise members | |
| 188 | + init_members(); | |
| 189 | + | |
| 190 | + // Copy members | |
| 191 | + copy_members(model); | |
| 192 | + | |
| 193 | + } // endif: object was not identical | |
| 194 | + | |
| 195 | + // Return | |
| 196 | + return *this; | |
| 197 | +} | |
| 198 | + | |
| 199 | + | |
| 200 | +/*========================================================================== | |
| 201 | + = = | |
| 202 | + = Public methods = | |
| 203 | + = = | |
| 204 | + ==========================================================================*/ | |
| 205 | + | |
| 206 | +/***********************************************************************//** | |
| 207 | + * @brief Clear radial Gauss model | |
| 208 | + ***************************************************************************/ | |
| 209 | +void GModelSpatialRadialGeneralGauss::clear(void) | |
| 210 | +{ | |
| 211 | + // Free class members (base and derived classes, derived class first) | |
| 212 | + free_members(); | |
| 213 | + this->GModelSpatialRadial::free_members(); | |
| 214 | + this->GModelSpatial::free_members(); | |
| 215 | + | |
| 216 | + // Initialise members | |
| 217 | + this->GModelSpatial::init_members(); | |
| 218 | + this->GModelSpatialRadial::init_members(); | |
| 219 | + init_members(); | |
| 220 | + | |
| 221 | + // Return | |
| 222 | + return; | |
| 223 | +} | |
| 224 | + | |
| 225 | + | |
| 226 | +/***********************************************************************//** | |
| 227 | + * @brief Clone radial Gauss model | |
| 228 | + ***************************************************************************/ | |
| 229 | +GModelSpatialRadialGeneralGauss* GModelSpatialRadialGeneralGauss::clone(void) const | |
| 230 | +{ | |
| 231 | + // Clone radial Gauss model | |
| 232 | + return new GModelSpatialRadialGeneralGauss(*this); | |
| 233 | +} | |
| 234 | + | |
| 235 | + | |
| 236 | +/***********************************************************************//** | |
| 237 | + * @brief Evaluate Generalised Gaussian source model | |
| 238 | + * | |
| 239 | + * @param[in] theta Angular distance from source centre (radians). | |
| 240 | + * @param[in] energy Photon energy (not used). | |
| 241 | + * @param[in] time Photon arrival time (not used). | |
| 242 | + * @param[in] gradients Compute gradients? | |
| 243 | + * @return Model value (\f${\rm sr}^{-1}\f$). | |
| 244 | + * | |
| 245 | + * Evaluates the spatial component for a Generalised Gaussian source model using | |
| 246 | + * | |
| 247 | + * \f[ | |
| 248 | + * M_{\rm S}({\bf p} | E, t) = M_{\rm S}(\theta) = | |
| 249 | + * \frac{1}{2 \pi r^2 \eta \Gamma(\eta)} \exp | |
| 250 | + * \left(-(\frac{\theta}{r})^1/\eta \right) | |
| 251 | + * \f] | |
| 252 | + * | |
| 253 | + * where | |
| 254 | + * - \f$\theta\f$ is the angular separation from the centre of the model, and | |
| 255 | + * - \f$r\f$ is the Generalised Gaussian radius. | |
| 256 | + * - \f$\eta\f$ is the reciprocal of the radial profile exponent. | |
| 257 | + * | |
| 258 | + * If @p gradients is `true` the method will also compute parameter | |
| 259 | + * gradients | |
| 260 | + * | |
| 261 | + * | |
| 262 | + * Note that the model normalisation is only correct in the small angle | |
| 263 | + * approximation and for \f$\eta\f$ order unity or smaller. | |
| 264 | + ***************************************************************************/ | |
| 265 | +double GModelSpatialRadialGeneralGauss::eval(const double& theta, | |
| 266 | + const GEnergy& energy, | |
| 267 | + const GTime& time, | |
| 268 | + const bool& gradients) const | |
| 269 | +{ | |
| 270 | + // Update | |
| 271 | + update(); | |
| 272 | + | |
| 273 | + // Compute value | |
| 274 | + double arg = -1.0 * std::pow(m_inv_radius_rad * theta,m_inv_ridx); | |
| 275 | + double value = m_value_norm * std::exp(arg); | |
| 276 | + | |
| 277 | + // Compile option: Check for NaN/Inf | |
| 278 | + #if defined(G_NAN_CHECK) | |
| 279 | + if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) { | |
| 280 | + std::string msg = "Model value not a number:"; | |
| 281 | + for (int i = 0; i < m_pars.size(); ++i) { | |
| 282 | + msg += " " + m_pars[i]->name() + "="; | |
| 283 | + msg += gammalib::str(m_pars[i]->value()); | |
| 284 | + } | |
| 285 | + msg += " energy=" + energy.print(); | |
| 286 | + msg += " time=" + time.print(); | |
| 287 | + gammalib::warning(G_EVAL, msg); | |
| 288 | + } | |
| 289 | + #endif | |
| 290 | + | |
| 291 | + // Return value | |
| 292 | + return value; | |
| 293 | +} | |
| 294 | + | |
| 295 | + | |
| 296 | +/***********************************************************************//** | |
| 297 | + * @brief Returns MC sky direction | |
| 298 | + * | |
| 299 | + * @param[in] energy Photon energy. | |
| 300 | + * @param[in] time Photon arrival time. | |
| 301 | + * @param[in,out] ran Random number generator. | |
| 302 | + * @return Sky direction. | |
| 303 | + * | |
| 304 | + * Draws an arbitrary sky direction from the 2D Generalised Gaussian | |
| 305 | + * distribution as function of the photon @p energy and arrival @p time. | |
| 306 | + * | |
| 307 | + * @todo This method is only valid in the small angle approximation. | |
| 308 | + ***************************************************************************/ | |
| 309 | +GSkyDir GModelSpatialRadialGeneralGauss::mc(const GEnergy& energy, | |
| 310 | + const GTime& time, | |
| 311 | + GRan& ran) const | |
| 312 | +{ | |
| 313 | + | |
| 314 | + // Update precomputation cache | |
| 315 | + update(); | |
| 316 | + | |
| 317 | + // Initialise simulation | |
| 318 | + #if defined(G_DEBUG_MC) | |
| 319 | + int n_samples = 0; | |
| 320 | + #endif | |
| 321 | + double u_max = m_value_norm * std::sin(theta_max()); | |
| 322 | + double value = 0.0; | |
| 323 | + double u = 1.0; | |
| 324 | + double theta = 0.0; | |
| 325 | + | |
| 326 | + // Throw an exception if the maximum value is zero | |
| 327 | + if (u_max <= 0.0) { | |
| 328 | + std::string msg = "Non positive maximum radial genral Gauss model value."; | |
| 329 | + throw GException::invalid_return_value(G_MC, msg); | |
| 330 | + } | |
| 331 | + | |
| 332 | + // Simulate offset from photon arrival direction using a rejection method | |
| 333 | + do { | |
| 334 | + theta = ran.uniform() * theta_max(); | |
| 335 | + value = eval(theta, energy, time) * std::sin(theta); | |
| 336 | + u = ran.uniform() * u_max; | |
| 337 | + #if defined(G_DEBUG_MC) | |
| 338 | + n_samples++; | |
| 339 | + #endif | |
| 340 | + } while (u > value); | |
| 341 | + #if defined(G_DEBUG_MC) | |
| 342 | + std::cout << "#=" << n_samples << " "; | |
| 343 | + #endif | |
| 344 | + | |
| 345 | + // Simulate azimuth angle | |
| 346 | + double phi = 360.0 * ran.uniform(); | |
| 347 | + | |
| 348 | + // Rotate pointing direction by offset and azimuth angle | |
| 349 | + GSkyDir sky_dir = dir(); | |
| 350 | + sky_dir.rotate_deg(phi, theta * gammalib::rad2deg); | |
| 351 | + | |
| 352 | + // Return sky direction | |
| 353 | + return sky_dir; | |
| 354 | + | |
| 355 | +} | |
| 356 | + | |
| 357 | + | |
| 358 | +/***********************************************************************//** | |
| 359 | + * @brief Checks where model contains specified sky direction | |
| 360 | + * | |
| 361 | + * @param[in] dir Sky direction. | |
| 362 | + * @param[in] margin Margin to be added to sky direction (deg) | |
| 363 | + * @return True if the model contains the sky direction. | |
| 364 | + * | |
| 365 | + * Signals whether a sky direction is contained in the radial gauss model. | |
| 366 | + ***************************************************************************/ | |
| 367 | +bool GModelSpatialRadialGeneralGauss::contains(const GSkyDir& dir, | |
| 368 | + const double& margin) const | |
| 369 | +{ | |
| 370 | + // Compute distance to centre (radians) | |
| 371 | + double distance = dir.dist(this->dir()); | |
| 372 | + | |
| 373 | + // Return flag | |
| 374 | + return (distance <= theta_max() + margin*gammalib::deg2rad); | |
| 375 | +} | |
| 376 | + | |
| 377 | + | |
| 378 | +/***********************************************************************//** | |
| 379 | + * @brief Return maximum model radius (in radians) | |
| 380 | + * | |
| 381 | + * Returns \f$5 \sigma\f$ as approximate edge of the Gaussian. This limit | |
| 382 | + * is of course arbitrary, but allows to limit the integration region for | |
| 383 | + * response computation. | |
| 384 | + ***************************************************************************/ | |
| 385 | +double GModelSpatialRadialGeneralGauss::theta_max(void) const | |
| 386 | +{ | |
| 387 | + // Return value | |
| 388 | + return (radius() * gammalib::deg2rad * 5.0); | |
| 389 | +} | |
| 390 | + | |
| 391 | + | |
| 392 | +/***********************************************************************//** | |
| 393 | + * @brief Read model from XML element | |
| 394 | + * | |
| 395 | + * @param[in] xml XML element. | |
| 396 | + * | |
| 397 | + * Reads the generalised radial Gaussian model information from an XML | |
| 398 | + * element. The XML element shall have either the format | |
| 399 | + * | |
| 400 | + * <spatialModel type="RadialGeneralGaussian"> | |
| 401 | + * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> | |
| 402 | + * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> | |
| 403 | + * <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/> | |
| 404 | + * <parameter name="R_Index" scale="1.0" value="0.5" min="0.01" max="10" free="1"/> | |
| 405 | + * </spatialModel> | |
| 406 | + * | |
| 407 | + * or | |
| 408 | + * | |
| 409 | + * <spatialModel type="RadialGeneralGaussian"> | |
| 410 | + * <parameter name="GLON" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> | |
| 411 | + * <parameter name="GLAT" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> | |
| 412 | + * <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/> | |
| 413 | + * <parameter name="R_Index" scale="1.0" value="0.5" min="0.01" max="10" free="1"/> | |
| 414 | + * </spatialModel> | |
| 415 | + * | |
| 416 | + * @todo Implement a test of the radius and radius boundary. The sigma | |
| 417 | + * and sigma minimum should be >0. | |
| 418 | + ***************************************************************************/ | |
| 419 | +void GModelSpatialRadialGeneralGauss::read(const GXmlElement& xml) | |
| 420 | +{ | |
| 421 | + // Verify number of model parameters | |
| 422 | + gammalib::xml_check_parnum(G_READ, xml, 4); | |
| 423 | + | |
| 424 | + // Read location | |
| 425 | + GModelSpatialRadial::read(xml); | |
| 426 | + | |
| 427 | + // Get parameters | |
| 428 | + const GXmlElement* radius = gammalib::xml_get_par(G_READ, xml, m_radius.name()); | |
| 429 | + const GXmlElement* ridx = gammalib::xml_get_par(G_READ, xml, m_ridx.name()); | |
| 430 | + | |
| 431 | + // Read parameters | |
| 432 | + m_radius.read(*radius); | |
| 433 | + m_ridx.read(*ridx); | |
| 434 | + | |
| 435 | + // Return | |
| 436 | + return; | |
| 437 | +} | |
| 438 | + | |
| 439 | + | |
| 440 | +/***********************************************************************//** | |
| 441 | + * @brief Write model into XML element | |
| 442 | + * | |
| 443 | + * @param[in] xml XML element into which model information is written. | |
| 444 | + * | |
| 445 | + * Writes the radial disk model information into an XML element. The XML | |
| 446 | + * element will have the format | |
| 447 | + * | |
| 448 | + * <spatialModel type="RadialGeneralGaussian"> | |
| 449 | + * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> | |
| 450 | + * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> | |
| 451 | + * <parameter name="Sigma" scale="1.0" value="0.45" min="0.01" max="10" free="1"/> | |
| 452 | + * <parameter name="R_Index" scale="1.0" value="0.5" min="0.01" max="10" free="1"/> | |
| 453 | + * </spatialModel> | |
| 454 | + * | |
| 455 | + ***************************************************************************/ | |
| 456 | +void GModelSpatialRadialGeneralGauss::write(GXmlElement& xml) const | |
| 457 | +{ | |
| 458 | + // Write Gaussian location | |
| 459 | + GModelSpatialRadial::write(xml); | |
| 460 | + | |
| 461 | + // Get or create parameters | |
| 462 | + GXmlElement* radius = gammalib::xml_need_par(G_WRITE, xml, m_radius.name()); | |
| 463 | + GXmlElement* ridx = gammalib::xml_need_par(G_WRITE, xml, m_ridx.name()); | |
| 464 | + | |
| 465 | + // Write parameters | |
| 466 | + m_radius.write(*radius); | |
| 467 | + m_ridx.write(*ridx); | |
| 468 | + | |
| 469 | + // Return | |
| 470 | + return; | |
| 471 | +} | |
| 472 | + | |
| 473 | + | |
| 474 | +/***********************************************************************//** | |
| 475 | + * @brief Print generalised radial Gaussian source information | |
| 476 | + * | |
| 477 | + * @param[in] chatter Chattiness. | |
| 478 | + * @return String containing model information. | |
| 479 | + ***************************************************************************/ | |
| 480 | +std::string GModelSpatialRadialGeneralGauss::print(const GChatter& chatter) const | |
| 481 | +{ | |
| 482 | + // Initialise result string | |
| 483 | + std::string result; | |
| 484 | + | |
| 485 | + // Continue only if chatter is not silent | |
| 486 | + if (chatter != SILENT) { | |
| 487 | + | |
| 488 | + // Append header | |
| 489 | + result.append("=== GModelSpatialRadialGeneralGauss ==="); | |
| 490 | + | |
| 491 | + // Append parameters | |
| 492 | + result.append("\n"+gammalib::parformat("Number of parameters")); | |
| 493 | + result.append(gammalib::str(size())); | |
| 494 | + for (int i = 0; i < size(); ++i) { | |
| 495 | + result.append("\n"+m_pars[i]->print(chatter)); | |
| 496 | + } | |
| 497 | + | |
| 498 | + } // endif: chatter was not silent | |
| 499 | + | |
| 500 | + // Return result | |
| 501 | + return result; | |
| 502 | +} | |
| 503 | + | |
| 504 | + | |
| 505 | +/*========================================================================== | |
| 506 | + = = | |
| 507 | + = Private methods = | |
| 508 | + = = | |
| 509 | + ==========================================================================*/ | |
| 510 | + | |
| 511 | +/***********************************************************************//** | |
| 512 | + * @brief Initialise class members | |
| 513 | + * | |
| 514 | + * Note that the minimum Gaussian width is set to 1 arcsec | |
| 515 | + * and w set the minimum reciprocal index to 1.e-15 | |
| 516 | + ***************************************************************************/ | |
| 517 | +void GModelSpatialRadialGeneralGauss::init_members(void) | |
| 518 | +{ | |
| 519 | + // Initialise model type | |
| 520 | + m_type = "RadialGeneralGaussian"; | |
| 521 | + | |
| 522 | + // Initialise Radius | |
| 523 | + m_radius.clear(); | |
| 524 | + m_radius.name("Radius"); | |
| 525 | + m_radius.unit("deg"); | |
| 526 | + m_radius.value(2.778e-4); // 1 arcsec | |
| 527 | + m_radius.min(2.778e-4); // 1 arcsec | |
| 528 | + m_radius.free(); | |
| 529 | + m_radius.scale(1.0); | |
| 530 | + m_radius.gradient(0.0); | |
| 531 | + m_radius.has_grad(false); | |
| 532 | + | |
| 533 | + // Initialise Reciprocal index | |
| 534 | + m_ridx.clear(); | |
| 535 | + m_ridx.name("R_Index"); | |
| 536 | + m_ridx.value(0.5); // Gaussian | |
| 537 | + m_ridx.min(1.e-15); // need to be > 0 | |
| 538 | + m_ridx.free(); | |
| 539 | + m_ridx.scale(1.0); | |
| 540 | + m_ridx.gradient(0.0); | |
| 541 | + m_ridx.has_grad(false); // Radial components never have gradients | |
| 542 | + | |
| 543 | + // Set parameter pointer(s) | |
| 544 | + m_pars.push_back(&m_radius); | |
| 545 | + m_pars.push_back(&m_ridx); | |
| 546 | + | |
| 547 | + // Initialise precomputation cache. Note that zero values flag | |
| 548 | + // uninitialised as a zero radius and width shell is not meaningful | |
| 549 | + m_last_radius = 0.0; | |
| 550 | + m_inv_radius_rad = 0.0; | |
| 551 | + m_last_ridx = 0.0; | |
| 552 | + m_inv_ridx = 0.0; | |
| 553 | + m_value_norm = 0.0; | |
| 554 | + | |
| 555 | + // Return | |
| 556 | + return; | |
| 557 | +} | |
| 558 | + | |
| 559 | + | |
| 560 | +/***********************************************************************//** | |
| 561 | + * @brief Copy class members | |
| 562 | + * | |
| 563 | + * @param[in] model Generalised radial Gaussian spatial model. | |
| 564 | + * | |
| 565 | + * We do not have to push back the members on the parameter stack as this | |
| 566 | + * should have been done by init_members() that was called before. Otherwise | |
| 567 | + * we would have sigma twice on the stack. | |
| 568 | + ***************************************************************************/ | |
| 569 | +void GModelSpatialRadialGeneralGauss::copy_members(const GModelSpatialRadialGeneralGauss& model) | |
| 570 | +{ | |
| 571 | + // Copy members | |
| 572 | + m_type = model.m_type; // Needed to conserve model type | |
| 573 | + m_radius = model.m_radius; | |
| 574 | + m_ridx = model.m_ridx; | |
| 575 | + | |
| 576 | + // Copy pre-computation cache | |
| 577 | + m_last_radius = model.m_last_radius; | |
| 578 | + m_inv_radius_rad = model.m_inv_radius_rad; | |
| 579 | + m_last_ridx = model.m_last_ridx; | |
| 580 | + m_inv_ridx = model.m_inv_ridx; | |
| 581 | + m_value_norm = model.m_value_norm; | |
| 582 | + | |
| 583 | + // Return | |
| 584 | + return; | |
| 585 | +} | |
| 586 | + | |
| 587 | + | |
| 588 | +/***********************************************************************//** | |
| 589 | + * @brief Delete class members | |
| 590 | + ***************************************************************************/ | |
| 591 | +void GModelSpatialRadialGeneralGauss::free_members(void) | |
| 592 | +{ | |
| 593 | + // Return | |
| 594 | + return; | |
| 595 | +} | |
| 596 | + | |
| 597 | + | |
| 598 | +/***********************************************************************//** | |
| 599 | + * @brief Update precomputation cache | |
| 600 | + ***************************************************************************/ | |
| 601 | +void GModelSpatialRadialGeneralGauss::update() const | |
| 602 | +{ | |
| 603 | + // Update if radius has changed | |
| 604 | + if (m_last_radius != radius() or m_last_ridx != ridx()) { | |
| 605 | + | |
| 606 | + // Store last values | |
| 607 | + m_last_radius = radius(); | |
| 608 | + m_last_ridx = ridx(); | |
| 609 | + | |
| 610 | + // Compute radius in radians | |
| 611 | + double radius_rad = radius() * gammalib::deg2rad; | |
| 612 | + if (radius_rad > 0.0 and ridx() > 0.0) { | |
| 613 | + m_inv_radius_rad = 1.0 / radius_rad; | |
| 614 | + m_inv_ridx = 1.0 / ridx() ; | |
| 615 | + m_value_norm = 1.0 / (gammalib::twopi * radius_rad * radius_rad * ridx() * | |
| 616 | + std::exp(gammalib::gammln(2.0 * ridx()))); | |
| 617 | + } | |
| 618 | + else { | |
| 619 | + m_inv_radius_rad = 0.0; | |
| 620 | + m_inv_ridx = 1.0; | |
| 621 | + m_value_norm = 0.0; | |
| 622 | + } | |
| 623 | + | |
| 624 | + } // endif: update required | |
| 625 | + | |
| 626 | + // Return | |
| 627 | + return; | |
| 628 | +} | |
| 629 | + | |
| 630 | + | |
| 631 | +/***********************************************************************//** | |
| 632 | + * @brief Set boundary sky region | |
| 633 | + ***************************************************************************/ | |
| 634 | +void GModelSpatialRadialGeneralGauss::set_region(void) const | |
| 635 | +{ | |
| 636 | + // Set sky region circle (5 times radius) | |
| 637 | + GSkyRegionCircle region(m_ra.value(), m_dec.value(), m_radius.value() * 5.0); | |
| 638 | + | |
| 639 | + // Set region (circumvent const correctness) | |
| 640 | + const_cast<GModelSpatialRadialGeneralGauss*>(this)->m_region = region; | |
| 641 | + | |
| 642 | + // Return | |
| 643 | + return; | |
| 644 | +} | ... | ... |
src/model/Makefile.am
| ... | ... | @@ -40,6 +40,7 @@ sources = GModelPar.cpp \ |
| 40 | 40 | GModelSpatialRadialDisk.cpp \ |
| 41 | 41 | GModelSpatialRadialRing.cpp \ |
| 42 | 42 | GModelSpatialRadialGauss.cpp \ |
| 43 | + GModelSpatialRadialGeneralGauss.cpp \ | |
| 43 | 44 | GModelSpatialRadialShell.cpp \ |
| 44 | 45 | GModelSpatialRadialProfile.cpp \ |
| 45 | 46 | GModelSpatialRadialProfileGauss.cpp \ |
| ... | ... | @@ -49,6 +50,7 @@ sources = GModelPar.cpp \ |
| 49 | 50 | GModelSpatialElliptical.cpp \ |
| 50 | 51 | GModelSpatialEllipticalDisk.cpp \ |
| 51 | 52 | GModelSpatialEllipticalGauss.cpp \ |
| 53 | + GModelSpatialEllipticalGeneralGauss.cpp \ | |
| 52 | 54 | GModelSpatialDiffuse.cpp \ |
| 53 | 55 | GModelSpatialDiffuseConst.cpp \ |
| 54 | 56 | GModelSpatialDiffuseCube.cpp \ | ... | ... |
test/data/model_elliptical_general_gauss.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="EllipticalGeneralGaussian"> | |
| 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="PA" scale="1.0" value="45.0" min="-360" max="360" free="1"/> | |
| 13 | + <parameter name="MinorRadius" scale="1.0" value="0.1" min="0.001" max="10" free="1"/> | |
| 14 | + <parameter name="MajorRadius" scale="1.0" value="0.3" min="0.001" max="10" free="1"/> | |
| 15 | + <parameter name="R_Index" scale="1.0" value="0.3" min="0.01" max="10" free="1"/> | |
| 16 | + </spatialModel> | |
| 17 | + </source> | |
| 18 | +</source_library> | ... | ... |
test/data/model_radial_general_gauss.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="RadialGeneralGaussian"> | |
| 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.20" min="0.01" max="10" free="1"/> | |
| 13 | + <parameter name="R_Index" scale="1.0" value="0.3" min="0.01" max="10" free="1"/> | |
| 14 | + </spatialModel> | |
| 15 | + </source> | |
| 16 | +</source_library> | ... | ... |
test/test_GModel.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * test_GModel.cpp - test GModel class * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2009-2021 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2009-2022 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -84,37 +84,39 @@ void TestGModel::set(void) |
| 84 | 84 | m_assoc_file = datadir + "/crab_associations.xml"; |
| 85 | 85 | |
| 86 | 86 | // Set model definiton XML files |
| 87 | - m_xml_model_point_const = datadir + "/model_point_const.xml"; | |
| 88 | - m_xml_model_point_gauss = datadir + "/model_point_gauss.xml"; | |
| 89 | - m_xml_model_point_plaw = datadir + "/model_point_plaw.xml"; | |
| 90 | - m_xml_model_point_plaw_phflux = datadir + "/model_point_plaw_phflux.xml"; | |
| 91 | - m_xml_model_point_plaw_eflux = datadir + "/model_point_plaw_eflux.xml"; | |
| 92 | - m_xml_model_point_eplaw = datadir + "/model_point_eplaw.xml"; | |
| 93 | - m_xml_model_point_einvplaw = datadir + "/model_point_einvplaw.xml"; | |
| 94 | - m_xml_model_point_bplaw = datadir + "/model_point_bplaw.xml"; | |
| 95 | - m_xml_model_point_smoothbplaw = datadir + "/model_point_smoothbplaw.xml"; | |
| 96 | - m_xml_model_point_supeplaw = datadir + "/model_point_supeplaw.xml"; | |
| 97 | - m_xml_model_point_logparabola = datadir + "/model_point_logparabola.xml"; | |
| 98 | - m_xml_model_point_bins = datadir + "/model_point_bins.xml"; | |
| 99 | - m_xml_model_point_nodes = datadir + "/model_point_nodes.xml"; | |
| 100 | - m_xml_model_point_filefct = datadir + "/model_point_filefct.xml"; | |
| 101 | - m_xml_model_point_table = datadir + "/model_point_table.xml"; | |
| 102 | - m_xml_point_multiplicative = datadir + "/model_point_multiplicative.xml"; | |
| 103 | - m_xml_point_exponential = datadir + "/model_point_exponential.xml"; | |
| 104 | - m_xml_model_spectral_composite = datadir + "/model_spectral_composite.xml"; | |
| 105 | - m_xml_model_diffuse_const = datadir + "/model_diffuse_const.xml"; | |
| 106 | - m_xml_model_diffuse_cube = datadir + "/model_diffuse_cube.xml"; | |
| 107 | - m_xml_model_diffuse_map = datadir + "/model_diffuse_map.xml"; | |
| 108 | - m_xml_model_radial_disk = datadir + "/model_radial_disk.xml"; | |
| 109 | - m_xml_model_radial_ring = datadir + "/model_radial_ring.xml"; | |
| 110 | - m_xml_model_radial_gauss = datadir + "/model_radial_gauss.xml"; | |
| 111 | - m_xml_model_radial_shell = datadir + "/model_radial_shell.xml"; | |
| 112 | - m_xml_model_profile_dmburkert = datadir + "/model_profile_dmburkert.xml"; | |
| 113 | - m_xml_model_profile_dmeinasto = datadir + "/model_profile_dmeinasto.xml"; | |
| 114 | - m_xml_model_profile_dmzhao = datadir + "/model_profile_dmzhao.xml"; | |
| 115 | - m_xml_model_elliptical_disk = datadir + "/model_elliptical_disk.xml"; | |
| 116 | - m_xml_model_elliptical_gauss = datadir + "/model_elliptical_gauss.xml"; | |
| 117 | - m_xml_model_spatial_composite = datadir + "/model_spatial_composite.xml"; | |
| 87 | + m_xml_model_point_const = datadir + "/model_point_const.xml"; | |
| 88 | + m_xml_model_point_gauss = datadir + "/model_point_gauss.xml"; | |
| 89 | + m_xml_model_point_plaw = datadir + "/model_point_plaw.xml"; | |
| 90 | + m_xml_model_point_plaw_phflux = datadir + "/model_point_plaw_phflux.xml"; | |
| 91 | + m_xml_model_point_plaw_eflux = datadir + "/model_point_plaw_eflux.xml"; | |
| 92 | + m_xml_model_point_eplaw = datadir + "/model_point_eplaw.xml"; | |
| 93 | + m_xml_model_point_einvplaw = datadir + "/model_point_einvplaw.xml"; | |
| 94 | + m_xml_model_point_bplaw = datadir + "/model_point_bplaw.xml"; | |
| 95 | + m_xml_model_point_smoothbplaw = datadir + "/model_point_smoothbplaw.xml"; | |
| 96 | + m_xml_model_point_supeplaw = datadir + "/model_point_supeplaw.xml"; | |
| 97 | + m_xml_model_point_logparabola = datadir + "/model_point_logparabola.xml"; | |
| 98 | + m_xml_model_point_bins = datadir + "/model_point_bins.xml"; | |
| 99 | + m_xml_model_point_nodes = datadir + "/model_point_nodes.xml"; | |
| 100 | + m_xml_model_point_filefct = datadir + "/model_point_filefct.xml"; | |
| 101 | + m_xml_model_point_table = datadir + "/model_point_table.xml"; | |
| 102 | + m_xml_point_multiplicative = datadir + "/model_point_multiplicative.xml"; | |
| 103 | + m_xml_point_exponential = datadir + "/model_point_exponential.xml"; | |
| 104 | + m_xml_model_spectral_composite = datadir + "/model_spectral_composite.xml"; | |
| 105 | + m_xml_model_diffuse_const = datadir + "/model_diffuse_const.xml"; | |
| 106 | + m_xml_model_diffuse_cube = datadir + "/model_diffuse_cube.xml"; | |
| 107 | + m_xml_model_diffuse_map = datadir + "/model_diffuse_map.xml"; | |
| 108 | + m_xml_model_radial_disk = datadir + "/model_radial_disk.xml"; | |
| 109 | + m_xml_model_radial_ring = datadir + "/model_radial_ring.xml"; | |
| 110 | + m_xml_model_radial_gauss = datadir + "/model_radial_gauss.xml"; | |
| 111 | + m_xml_model_radial_general_gauss = datadir + "/model_radial_general_gauss.xml"; | |
| 112 | + m_xml_model_radial_shell = datadir + "/model_radial_shell.xml"; | |
| 113 | + m_xml_model_profile_dmburkert = datadir + "/model_profile_dmburkert.xml"; | |
| 114 | + m_xml_model_profile_dmeinasto = datadir + "/model_profile_dmeinasto.xml"; | |
| 115 | + m_xml_model_profile_dmzhao = datadir + "/model_profile_dmzhao.xml"; | |
| 116 | + m_xml_model_elliptical_disk = datadir + "/model_elliptical_disk.xml"; | |
| 117 | + m_xml_model_elliptical_gauss = datadir + "/model_elliptical_gauss.xml"; | |
| 118 | + m_xml_model_elliptical_general_gauss = datadir + "/model_elliptical_general_gauss.xml"; | |
| 119 | + m_xml_model_spatial_composite = datadir + "/model_spatial_composite.xml"; | |
| 118 | 120 | |
| 119 | 121 | // Set temporal model definition XML files |
| 120 | 122 | m_xml_model_point_temp_lightcurve = datadir + "/model_temporal_lightcurve.xml"; |
| ... | ... | @@ -155,6 +157,8 @@ void TestGModel::set(void) |
| 155 | 157 | "Test GModelSpatialRadialRing"); |
| 156 | 158 | append(static_cast<pfunction>(&TestGModel::test_radial_gauss), |
| 157 | 159 | "Test GModelSpatialRadialGauss"); |
| 160 | + append(static_cast<pfunction>(&TestGModel::test_radial_general_gauss), | |
| 161 | + "Test GModelSpatialRadialGeneralGauss"); | |
| 158 | 162 | append(static_cast<pfunction>(&TestGModel::test_radial_shell), |
| 159 | 163 | "Test GModelSpatialRadialShell"); |
| 160 | 164 | append(static_cast<pfunction>(&TestGModel::test_profile_dmburkert), |
| ... | ... | @@ -167,6 +171,8 @@ void TestGModel::set(void) |
| 167 | 171 | "Test GModelSpatialEllipticalDisk"); |
| 168 | 172 | append(static_cast<pfunction>(&TestGModel::test_elliptical_gauss), |
| 169 | 173 | "Test GModelSpatialEllipticalGauss"); |
| 174 | + append(static_cast<pfunction>(&TestGModel::test_elliptical_general_gauss), | |
| 175 | + "Test GModelSpatialEllipticalGeneralGauss"); | |
| 170 | 176 | append(static_cast<pfunction>(&TestGModel::test_diffuse_const), |
| 171 | 177 | "Test GModelSpatialDiffuseConst"); |
| 172 | 178 | append(static_cast<pfunction>(&TestGModel::test_diffuse_cube), |
| ... | ... | @@ -1398,6 +1404,80 @@ void TestGModel::test_radial_gauss(void) |
| 1398 | 1404 | return; |
| 1399 | 1405 | } |
| 1400 | 1406 | |
| 1407 | +/***********************************************************************//** | |
| 1408 | + * @brief Test GModelSpatialRadialGauss class | |
| 1409 | + ***************************************************************************/ | |
| 1410 | +void TestGModel::test_radial_general_gauss(void) | |
| 1411 | +{ | |
| 1412 | + // Test void constructor | |
| 1413 | + GModelSpatialRadialGeneralGauss model1; | |
| 1414 | + test_value(model1.type(), "RadialGeneralGaussian"); | |
| 1415 | + | |
| 1416 | + // Test value constructor | |
| 1417 | + GSkyDir dir1; | |
| 1418 | + dir1.radec_deg(83.6331, +22.0145); | |
| 1419 | + GModelSpatialRadialGeneralGauss model2(dir1, 3.0, 0.5); | |
| 1420 | + test_value(model2.ra(), 83.6331); | |
| 1421 | + test_value(model2.dec(), 22.0145); | |
| 1422 | + test_value(model2.radius(), 3.0); | |
| 1423 | + test_value(model2.ridx(), 0.5); | |
| 1424 | + | |
| 1425 | + // Test XML constructor | |
| 1426 | + GXml xml(m_xml_model_radial_general_gauss); | |
| 1427 | + GXmlElement* element = xml.element(0)->element(0)->element("spatialModel", 0); | |
| 1428 | + GModelSpatialRadialGeneralGauss model3(*element); | |
| 1429 | + test_value(model3.size(), 4); | |
| 1430 | + test_value(model3.type(), "RadialGeneralGaussian"); | |
| 1431 | + test_value(model3.ra(), 83.6331); | |
| 1432 | + test_value(model3.dec(), 22.0145); | |
| 1433 | + test_value(model3.radius(), 0.20); | |
| 1434 | + test_value(model3.ridx(), 0.3); | |
| 1435 | + | |
| 1436 | + // Test ra method | |
| 1437 | + model3.ra(100.0); | |
| 1438 | + test_value(model3.ra(), 100.0); | |
| 1439 | + | |
| 1440 | + // Test dec method | |
| 1441 | + model3.dec(10.0); | |
| 1442 | + test_value(model3.dec(), 10.0); | |
| 1443 | + | |
| 1444 | + // Test dir method | |
| 1445 | + GSkyDir dir2; | |
| 1446 | + dir2.radec_deg(83.6331, +22.0145); | |
| 1447 | + model3.dir(dir2); | |
| 1448 | + test_assert(model3.dir() == dir2, "Test sky direction"); | |
| 1449 | + | |
| 1450 | + // Test radius method | |
| 1451 | + model3.radius(3.9); | |
| 1452 | + test_value(model3.radius(), 3.9); | |
| 1453 | + | |
| 1454 | + // Test ridx method | |
| 1455 | + model3.ridx(0.76); | |
| 1456 | + test_value(model3.ridx(), 0.76); | |
| 1457 | + | |
| 1458 | + // Test region method | |
| 1459 | + GSkyDir dir3; | |
| 1460 | + dir3.radec_deg(83.6331, +22.0145); | |
| 1461 | + test_assert(model3.region()->contains(dir3), "Test region() method (inside)"); | |
| 1462 | + dir3.radec_deg(83.6331, -70.0); | |
| 1463 | + test_assert(!model3.region()->contains(dir3), "Test region() method (outside)"); | |
| 1464 | + | |
| 1465 | + // Test operator access | |
| 1466 | + const char* strarray[] = {"RA", "DEC", "Radius", "R_Index"}; | |
| 1467 | + for (int i = 0; i < 4; ++i) { | |
| 1468 | + std::string keyname(strarray[i]); | |
| 1469 | + model3[keyname].value(2.1); | |
| 1470 | + model3[keyname].error(1.9); | |
| 1471 | + model3[keyname].gradient(0.8); | |
| 1472 | + test_value(model3[keyname].value(), 2.1); | |
| 1473 | + test_value(model3[keyname].error(), 1.9); | |
| 1474 | + test_value(model3[keyname].gradient(), 0.8); | |
| 1475 | + } | |
| 1476 | + | |
| 1477 | + // Exit test | |
| 1478 | + return; | |
| 1479 | +} | |
| 1480 | + | |
| 1401 | 1481 | |
| 1402 | 1482 | /***********************************************************************//** |
| 1403 | 1483 | * @brief Test GModelSpatialRadialShell class |
| ... | ... | @@ -1716,6 +1796,92 @@ void TestGModel::test_elliptical_gauss(void) |
| 1716 | 1796 | return; |
| 1717 | 1797 | } |
| 1718 | 1798 | |
| 1799 | +/***********************************************************************//** | |
| 1800 | + * @brief Test GModelSpatialEllipticalGeneralGauss class | |
| 1801 | + ***************************************************************************/ | |
| 1802 | +void TestGModel::test_elliptical_general_gauss(void) | |
| 1803 | +{ | |
| 1804 | + // Test void constructor | |
| 1805 | + GModelSpatialEllipticalGeneralGauss model1; | |
| 1806 | + test_value(model1.type(), "EllipticalGeneralGaussian"); | |
| 1807 | + | |
| 1808 | + // Test value constructor | |
| 1809 | + GSkyDir dir1; | |
| 1810 | + dir1.radec_deg(83.6331, +22.0145); | |
| 1811 | + GModelSpatialEllipticalGeneralGauss model2(dir1, 3.0, 2.0, 45.0,0.5); | |
| 1812 | + test_value(model2.ra(), 83.6331); | |
| 1813 | + test_value(model2.dec(), 22.0145); | |
| 1814 | + test_value(model2.posangle(), 45.0); | |
| 1815 | + test_value(model2.semimajor(), 3.0); | |
| 1816 | + test_value(model2.semiminor(), 2.0); | |
| 1817 | + test_value(model2.semiminor(), 2.0); | |
| 1818 | + test_value(model2.ridx(), 0.5); | |
| 1819 | + | |
| 1820 | + // Test XML constructor | |
| 1821 | + GXml xml(m_xml_model_elliptical_general_gauss); | |
| 1822 | + GXmlElement* element = xml.element(0)->element(0)->element("spatialModel", 0); | |
| 1823 | + GModelSpatialEllipticalGeneralGauss model3(*element); | |
| 1824 | + test_value(model3.size(), 6); | |
| 1825 | + test_value(model3.type(), "EllipticalGeneralGaussian"); | |
| 1826 | + test_value(model3.ra(), 83.6331); | |
| 1827 | + test_value(model3.dec(), 22.0145); | |
| 1828 | + test_value(model3.posangle(), 45.0); | |
| 1829 | + test_value(model3.semimajor(), 0.3); | |
| 1830 | + test_value(model3.semiminor(), 0.1); | |
| 1831 | + test_value(model3.ridx(), 0.3); | |
| 1832 | + | |
| 1833 | + // Test ra method | |
| 1834 | + model3.ra(100.0); | |
| 1835 | + test_value(model3.ra(), 100.0); | |
| 1836 | + | |
| 1837 | + // Test dec method | |
| 1838 | + model3.dec(10.0); | |
| 1839 | + test_value(model3.dec(), 10.0); | |
| 1840 | + | |
| 1841 | + // Test dir method | |
| 1842 | + GSkyDir dir2; | |
| 1843 | + dir2.radec_deg(83.6331, +22.0145); | |
| 1844 | + model3.dir(dir2); | |
| 1845 | + test_assert(model3.dir() == dir2, "Test sky direction"); | |
| 1846 | + | |
| 1847 | + // Test posangle method | |
| 1848 | + model3.posangle(3.9); | |
| 1849 | + test_value(model3.posangle(), 3.9); | |
| 1850 | + | |
| 1851 | + // Test semimajor method | |
| 1852 | + model3.semimajor(3.9); | |
| 1853 | + test_value(model3.semimajor(), 3.9); | |
| 1854 | + | |
| 1855 | + // Test semiminor method | |
| 1856 | + model3.semiminor(3.9); | |
| 1857 | + test_value(model3.semiminor(), 3.9); | |
| 1858 | + | |
| 1859 | + // Test ridx method | |
| 1860 | + model3.ridx(0.7); | |
| 1861 | + test_value(model3.ridx(), 0.7); | |
| 1862 | + | |
| 1863 | + // Test region method | |
| 1864 | + GSkyDir dir3; | |
| 1865 | + dir3.radec_deg(83.6331, +22.0145); | |
| 1866 | + test_assert(model3.region()->contains(dir3), "Test region() method (inside)"); | |
| 1867 | + dir3.radec_deg(83.6331, +61.5); | |
| 1868 | + test_assert(!model3.region()->contains(dir3), "Test region() method (outside)"); | |
| 1869 | + | |
| 1870 | + // Test operator access | |
| 1871 | + const char* strarray[] = {"RA", "DEC", "PA", "MinorRadius", "MajorRadius", "R_Index"}; | |
| 1872 | + for (int i = 0; i < 6; ++i) { | |
| 1873 | + std::string keyname(strarray[i]); | |
| 1874 | + model3[keyname].value(2.1); | |
| 1875 | + model3[keyname].error(1.9); | |
| 1876 | + model3[keyname].gradient(0.8); | |
| 1877 | + test_value(model3[keyname].value(), 2.1); | |
| 1878 | + test_value(model3[keyname].error(), 1.9); | |
| 1879 | + test_value(model3[keyname].gradient(), 0.8); | |
| 1880 | + } | |
| 1881 | + | |
| 1882 | + // Exit test | |
| 1883 | + return; | |
| 1884 | +} | |
| 1719 | 1885 | |
| 1720 | 1886 | /***********************************************************************//** |
| 1721 | 1887 | * @brief Test GModelSpatialComposite class | ... | ... |
test/test_GModel.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * test_GModel.hpp - Test model module * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2012-2021 by Jean-Baptiste Cayrou * | |
| 4 | + * copyright (C) 2012-2022 by Jean-Baptiste Cayrou * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -58,12 +58,14 @@ public: |
| 58 | 58 | void test_radial_disk(void); |
| 59 | 59 | void test_radial_ring(void); |
| 60 | 60 | void test_radial_gauss(void); |
| 61 | + void test_radial_general_gauss(); | |
| 61 | 62 | void test_radial_shell(void); |
| 62 | 63 | void test_profile_dmburkert(void); |
| 63 | 64 | void test_profile_dmeinasto(void); |
| 64 | 65 | void test_profile_dmzhao(void); |
| 65 | 66 | void test_elliptical_disk(void); |
| 66 | 67 | void test_elliptical_gauss(void); |
| 68 | + void test_elliptical_general_gauss(void); | |
| 67 | 69 | void test_spatial_composite(void); |
| 68 | 70 | void test_spatial_model(void); |
| 69 | 71 | void test_const(void); |
| ... | ... | @@ -147,12 +149,14 @@ private: |
| 147 | 149 | std::string m_xml_model_radial_disk; |
| 148 | 150 | std::string m_xml_model_radial_ring; |
| 149 | 151 | std::string m_xml_model_radial_gauss; |
| 152 | + std::string m_xml_model_radial_general_gauss; | |
| 150 | 153 | std::string m_xml_model_radial_shell; |
| 151 | 154 | std::string m_xml_model_profile_dmburkert; |
| 152 | 155 | std::string m_xml_model_profile_dmeinasto; |
| 153 | 156 | std::string m_xml_model_profile_dmzhao; |
| 154 | 157 | std::string m_xml_model_elliptical_disk; |
| 155 | 158 | std::string m_xml_model_elliptical_gauss; |
| 159 | + std::string m_xml_model_elliptical_general_gauss; | |
| 156 | 160 | std::string m_xml_model_spatial_composite; |
| 157 | 161 | std::string m_xml_model_point_temp_lightcurve; |
| 158 | 162 | std::string m_xml_model_point_temp_phasecurve; | ... | ... |