Commit 68717400d5ac5edb64e44187e6cc8d03998d7cb6

Authored by Luigi Tibaldo
1 parent 4518c159

first go at flux from circular region, does not work for small sources

include/GModelSpatial.hpp
... ... @@ -34,10 +34,13 @@
34 34 #include "GModelPar.hpp"
35 35 #include "GPhoton.hpp"
36 36 #include "GSkyDir.hpp"
  37 +#include "GSkyRegionCircle.hpp"
37 38 #include "GEnergy.hpp"
38 39 #include "GTime.hpp"
39 40 #include "GXmlElement.hpp"
40 41 #include "GRan.hpp"
  42 +#include "GFunction.hpp"
  43 +#include "GIntegral.hpp"
41 44  
42 45 /* __ Forward declarations _______________________________________________ */
43 46 class GSkyRegion;
... ... @@ -102,6 +105,7 @@ public:
102 105 virtual void write(GXmlElement& xml) const = 0;
103 106 virtual GSkyRegion* region(void) const = 0;
104 107 virtual std::string print(const GChatter& chatter = NORMAL) const = 0;
  108 +
105 109  
106 110 // Methods
107 111 GModelPar& at(const int& index);
... ... @@ -110,6 +114,9 @@ public:
110 114 bool has_free_pars(void) const;
111 115 int size(void) const;
112 116 void autoscale(void);
  117 + double flux(const GSkyRegionCircle& reg,
  118 + const GEnergy& srcEng = GEnergy(),
  119 + const GTime& srcTime = GTime()) const;
113 120  
114 121 protected:
115 122 // Protected methods
... ... @@ -117,6 +124,87 @@ protected:
117 124 void copy_members(const GModelSpatial& model);
118 125 void free_members(void);
119 126  
  127 + /***********************************************************************//**
  128 + * @class circle_int_kern_rho
  129 + *
  130 + * @brief Kernel for circular sky region radial integration
  131 + *
  132 + * This class implements the integration kernel \f$K(\rho)\f$ for the
  133 + * integration
  134 + *
  135 + * \f[
  136 + * \int_{\rho_{\rm min}}^{\rho_{\rm max}} K(\rho | E, t) d\rho
  137 + * \f]
  138 + *
  139 + * of a spatial model over a circular region. The eval() method computes
  140 + *
  141 + * \f[
  142 + * K(\rho | E, t) = \sin \rho \times
  143 + * \int_{\omega} M(\rho, \omega | E, t) d\omega
  144 + * \f]
  145 + *
  146 + * where
  147 + * \f$M(\rho, \omega | E, t)\f$ is the spatial model,
  148 + * \f$\rho\f$ is the distance from the region centre, and
  149 + * \f$\omega\f$ is the position angle with respect to the connecting line
  150 + * between the region centre and the direction on the sky.
  151 + ***************************************************************************/
  152 + class circle_int_kern_rho : public GFunction {
  153 + public:
  154 + circle_int_kern_rho(const GModelSpatial* model,
  155 + const GSkyRegionCircle& reg,
  156 + const GEnergy& srcEng,
  157 + const GTime& srcTime) :
  158 + m_model(model),
  159 + m_reg(reg),
  160 + m_srcEng(srcEng),
  161 + m_srcTime(srcTime) { }
  162 + double eval(const double& rho);
  163 + public:
  164 + const GModelSpatial* m_model; //!< Model
  165 + GSkyRegionCircle m_reg; //!< Region
  166 + GEnergy m_srcEng; //!< Photon energy
  167 + GTime m_srcTime; //!< Photon time
  168 + };
  169 +
  170 + /***********************************************************************//**
  171 + * @class circle_int_kern_omega
  172 + *
  173 + * @brief Kernel for circular sky region azimuth angle integration
  174 + *
  175 + * This class implements the computation of
  176 + *
  177 + * \f[
  178 + * K(\omega | \rho, E, t) = M(\omega | \rho)
  179 + * \f]
  180 + *
  181 + * where
  182 + * \fM(\omega | \rho)\f$ is the spatial model,
  183 + * \f$\rho\f$ is the distance from the region centre, and
  184 + * \f$\omega\f$ is the position angle with respect to the connecting line
  185 + * between the region centre and the direction on the sky.
  186 + ***************************************************************************/
  187 + class circle_int_kern_omega : public GFunction {
  188 + public:
  189 + circle_int_kern_omega(const GModelSpatial* model,
  190 + const GSkyRegionCircle& reg,
  191 + const double& rho,
  192 + const GEnergy& srcEng,
  193 + const GTime& srcTime) :
  194 + m_model(model),
  195 + m_reg(reg),
  196 + m_rho(rho),
  197 + m_srcEng(srcEng),
  198 + m_srcTime(srcTime) { }
  199 + double eval(const double& omega);
  200 + public:
  201 + const GModelSpatial* m_model; //!< Model
  202 + GSkyRegionCircle m_reg; //!< Region
  203 + double m_rho; //!< Offset from center of the region
  204 + GEnergy m_srcEng; //!< Photon energy
  205 + GTime m_srcTime; //!< Photon time
  206 + };
  207 +
120 208 // Proteced members
121 209 std::vector<GModelPar*> m_pars; //!< Parameter pointers
122 210 };
... ...
pyext/GModelSpatial.i
... ... @@ -64,6 +64,9 @@ public:
64 64 bool has_free_pars(void) const;
65 65 int size(void) const;
66 66 void autoscale(void);
  67 + double flux(const GSkyRegionCircle& reg,
  68 + const GEnergy& srcEng = GEnergy(),
  69 + const GTime& srcTime = GTime()) const;
67 70 };
68 71  
69 72  
... ...
src/model/GModelSpatial.cpp
... ... @@ -307,6 +307,57 @@ void GModelSpatial::autoscale(void)
307 307 return;
308 308 }
309 309  
  310 +/***********************************************************************//**
  311 + * @brief Returns model flux integrated in circular sky region
  312 + *
  313 + * @param[in] reg Sky region.
  314 + * @param[in] srcEng Energy.
  315 + * @param[in] srcTime Time.
  316 + * @return flux (adimensional or or ph/cm2/s).
  317 + *
  318 + * Computes
  319 + *
  320 + * \f[
  321 + * \int_{\rho_{\rm min}}^{\rho_{\rm max}} \sin \rho \times
  322 + * \int_{\omega} M(\rho, \omega | E, t) d\omega d\rho
  323 + * \f]
  324 + *
  325 + * where
  326 + * \f$M(\rho, \omega | E, t)\f$ is the spatial model,
  327 + * \f$\rho\f$ is the distance from the region centre, and
  328 + * \f$\omega\f$ is the position angle with respect to the connecting line
  329 + * between the region centre and the direction on the sky.
  330 + ***************************************************************************/
  331 +double GModelSpatial::flux(const GSkyRegionCircle& reg,
  332 + const GEnergy& srcEng,
  333 + const GTime& srcTime) const
  334 +{
  335 + // Set number of iterations for Romberg integration.
  336 + // Need to test!!!!
  337 + static const int iter_rho = 5;
  338 +
  339 + // Initialise flux
  340 + double flux = 0.0;
  341 +
  342 + // Define radial integration boundaries from 0 to ROI radius (in radians)
  343 + double rho_min = 0.;
  344 + double rho_max = reg.radius() * gammalib::deg2rad;
  345 +
  346 + // Setup integration kernel
  347 + GModelSpatial::circle_int_kern_rho integrand(this,
  348 + reg,
  349 + srcEng,
  350 + srcTime);
  351 + GIntegral integral(&integrand);
  352 +
  353 + // Perform integration
  354 + flux = integral.romberg(rho_min, rho_max);
  355 +
  356 + // Return
  357 + return flux;
  358 +
  359 +}
  360 +
310 361  
311 362 /*==========================================================================
312 363 = =
... ... @@ -350,3 +401,102 @@ void GModelSpatial::free_members(void)
350 401 // Return
351 402 return;
352 403 }
  404 +
  405 +/***********************************************************************//**
  406 + * @brief Kernel for circular sky region radial integration
  407 + *
  408 + * @param[in] rho Radial distance from region centre (radians).
  409 + * @return Integration kernel defined as
  410 + *
  411 + * \f[
  412 + * \int_{\rho_{\rm min}}^{\rho_{\rm max}} K(\rho | E, t) d\rho
  413 + * \f]
  414 + *
  415 + * of a spatial model over a circular region. The eval() method computes
  416 + *
  417 + * \f[
  418 + * K(\rho | E, t) = \sin \rho \times
  419 + * \int_{\omega} M(\rho, \omega | E, t) d\omega
  420 + * \f]
  421 + *
  422 + * where
  423 + * \f$M(\rho, \omega | E, t)\f$ is the spatial model,
  424 + * \f$\rho\f$ is the distance from the region centre, and
  425 + * \f$\omega\f$ is the position angle with respect to the connecting line
  426 + * between the region centre and the direction on the sky.
  427 + ***************************************************************************/
  428 +double GModelSpatial::circle_int_kern_rho::eval(const double& rho)
  429 +{
  430 + // Initialise model value
  431 + double flux = 0.0;
  432 +
  433 + // Continue only if rho is positive
  434 + if (rho > 0.0) {
  435 +
  436 + // Integrate over entire circular region
  437 + // omega between 0 and 2pi
  438 + double omega_min = 0.;
  439 + double omega_max = 2 * gammalib::pi;
  440 +
  441 + // Setup integration kernel for azimuth integration
  442 + GModelSpatial::circle_int_kern_omega integrand(m_model,
  443 + m_reg,
  444 + rho,
  445 + m_srcEng,
  446 + m_srcTime);
  447 +
  448 + // Setup integrator
  449 + GIntegral integral(&integrand);
  450 +
  451 + // Compute sine term for radial integration
  452 + double sin_rho = std::sin(rho);
  453 +
  454 + // Integrate over omega
  455 + flux = integral.romberg(omega_min, omega_max) * sin_rho;
  456 +
  457 + } // endif: rho was positive
  458 +
  459 +
  460 + // Return
  461 + return flux;
  462 +}
  463 +
  464 +/***********************************************************************//**
  465 + * @brief Kernel for circular sky region azimuth angle integration
  466 + *
  467 + * @param[in] omega Azimuth angle (radians).
  468 +* Computes
  469 + *
  470 + * \f[
  471 + * K(\omega | \rho, E, t) = M(\omega | \rho)
  472 + * \f]
  473 + *
  474 + * where
  475 + * \fM(\omega | \rho)\f$ is the spatial model,
  476 + * \f$\rho\f$ is the distance from the region centre, and
  477 + * \f$\omega\f$ is the position angle with respect to the connecting line
  478 + * between the region centre and the direction on the sky.
  479 + ***************************************************************************/
  480 +double GModelSpatial::circle_int_kern_omega::eval(const double& omega)
  481 +{
  482 + // Initialise model value
  483 + double flux = 0.0;
  484 +
  485 + // Precompute rho and omega in degrees
  486 + double omega_deg = omega * gammalib::rad2deg;
  487 + double rho_deg = m_rho * gammalib::rad2deg;
  488 +
  489 + // Compute sky direction corresponding to given rho, omega
  490 + // Deep copy of region centre
  491 + GSkyDir dir = GSkyDir(m_reg.centre());
  492 + // Rotate to otain requested sky direction
  493 + dir.rotate_deg(omega_deg,rho_deg);
  494 +
  495 + // Evaluate model for this sky direction
  496 + GPhoton photon = GPhoton(dir,m_srcEng,m_srcTime);
  497 + flux = m_model->eval(photon);
  498 +
  499 + // Return
  500 + return flux;
  501 +
  502 +}
... ...