Commit 6373db3ed97fc85751aad46a5ee4a79ccddb96d0

Authored by Jürgen Knödlseder
1 parent e2a37e18

Normalize sky map internally and perform bi-linear skymap interpolation in eval …

…and eval_gradients methods. Added filename constructor.

The sky map is now normalized internally, to that the total flux amounts to 1 ph/cm2/s. Note that this scaling can be modified using the normalization (or prefactor) parameter of the class, although in general this makes no sens as the flux is determined from the spectral law.

The eval and eval_gradients methods now make use of the sky direction access operator of the GSkymap class that performs bi-linear interpolation of the sky intensity based on the pixel values. This assures that eval and eval_gradients return a smooth function.

A filename constructor has been added that allows constructing a GModelSpatialMap object by loading a skymap from a FITS file.
include/GModelSpatialMap.hpp
... ... @@ -29,6 +29,7 @@
29 29  
30 30 /* __ Includes ___________________________________________________________ */
31 31 #include <string>
  32 +#include <vector>
32 33 #include "GModelSpatial.hpp"
33 34 #include "GModelPar.hpp"
34 35 #include "GSkyDir.hpp"
... ... @@ -50,6 +51,7 @@ public:
50 51 // Constructors and destructors
51 52 GModelSpatialMap(void);
52 53 explicit GModelSpatialMap(const GXmlElement& xml);
  54 + explicit GModelSpatialMap(const std::string& filename);
53 55 GModelSpatialMap(const GModelSpatialMap& model);
54 56 virtual ~GModelSpatialMap(void);
55 57  
... ... @@ -72,7 +74,7 @@ protected:
72 74 void init_members(void);
73 75 void copy_members(const GModelSpatialMap& model);
74 76 void free_members(void);
75   - void update_mc_cache(void);
  77 + void load_map(const std::string& filename);
76 78  
77 79 // Protected members
78 80 GModelPar m_value; //!< Value
... ...
include/GammaLib.hpp
... ... @@ -152,6 +152,7 @@
152 152 #include "GModelSpatialRegistry.hpp"
153 153 #include "GModelSpatialConst.hpp"
154 154 #include "GModelSpatialCube.hpp"
  155 +#include "GModelSpatialMap.hpp"
155 156 #include "GModelSpatialPtsrc.hpp"
156 157 #include "GModelRadial.hpp"
157 158 #include "GModelRadialRegistry.hpp"
... ...
include/Makefile.am
... ... @@ -49,6 +49,7 @@ pkginclude_HEADERS = GammaLib.hpp \
49 49 GModelSpatialPtsrc.hpp \
50 50 GModelSpatialConst.hpp \
51 51 GModelSpatialCube.hpp \
  52 + GModelSpatialMap.hpp \
52 53 GModelRadial.hpp \
53 54 GModelRadialRegistry.hpp \
54 55 GModelRadialDisk.hpp \
... ...
pyext/GModelSpatialMap.i
... ... @@ -40,6 +40,7 @@ public:
40 40 // Constructors and destructors
41 41 GModelSpatialMap(void);
42 42 explicit GModelSpatialMap(const GXmlElement& xml);
  43 + explicit GModelSpatialMap(const std::string& filename);
43 44 GModelSpatialMap(const GModelSpatialMap& model);
44 45 virtual ~GModelSpatialMap(void);
45 46  
... ...
src/model/GModelSpatialMap.cpp
... ... @@ -93,6 +93,27 @@ GModelSpatialMap::GModelSpatialMap(const GXmlElement&amp; xml) : GModelSpatial()
93 93  
94 94  
95 95 /***********************************************************************//**
  96 + * @brief Filename constructor
  97 + *
  98 + * @param[in] filename Name of FITS file.
  99 + *
  100 + * Creates instance of spatial map model by loading a skymap from a FITS
  101 + * file.
  102 + ***************************************************************************/
  103 +GModelSpatialMap::GModelSpatialMap(const std::string& filename) : GModelSpatial()
  104 +{
  105 + // Initialise members
  106 + init_members();
  107 +
  108 + // Load skymap
  109 + load_map(filename);
  110 +
  111 + // Return
  112 + return;
  113 +}
  114 +
  115 +
  116 +/***********************************************************************//**
96 117 * @brief Copy constructor
97 118 *
98 119 * @param[in] model Spatial map model.
... ... @@ -197,25 +218,17 @@ GModelSpatialMap* GModelSpatialMap::clone(void) const
197 218 *
198 219 * @param[in] srcDir True photon arrival direction.
199 220 *
200   - * Returns the intensity of the skymap at the specified sky direction. If the
201   - * sky direction falls outside the skymap, an intensity of 0 is returned.
  221 + * Returns the intensity of the skymap at the specified sky direction
  222 + * multiplied by the normalization factor. If the sky direction falls outside
  223 + * the skymap, an intensity of 0 is returned.
202 224 ***************************************************************************/
203 225 double GModelSpatialMap::eval(const GSkyDir& srcDir) const
204 226 {
205   - // Initialise intensity with 0
206   - double intensity = 0.0;
  227 + // Get skymap intensity
  228 + double intensity = m_map(srcDir);
207 229  
208   - // Convert sky direction into sky pixel
209   - GSkyPixel pixel = m_map.dir2xy(srcDir);
210   -
211   - // If pixel is in range then determine skymap intensity
212   - if ((pixel.x()+0.5 >= 0.0 && pixel.x()-0.5 < m_map.nx()) &&
213   - (pixel.y()+0.5 >= 0.0 && pixel.y()-0.5 < m_map.ny())) {
214   - intensity = m_map(pixel);
215   - }
216   -
217   - // Return intensity
218   - return intensity;
  230 + // Return intensity times normalization factor
  231 + return (intensity * m_value.real_value());
219 232 }
220 233  
221 234  
... ... @@ -224,21 +237,24 @@ double GModelSpatialMap::eval(const GSkyDir&amp; srcDir) const
224 237 *
225 238 * @param[in] srcDir True photon arrival direction.
226 239 *
227   - * Returns the intensity of the skymap at the specified sky direction. If the
228   - * sky direction falls outside the skymap, an intensity of 0 is returned.
229   - *
230   - * The gradient is set to 0.
  240 + * Returns the intensity of the skymap at the specified sky direction
  241 + * multiplied by the normalization factor. The method also sets the gradient
  242 + * with respect to the normalization factor. If the sky direction falls
  243 + * outside the skymap, an intensity of 0 is returned.
231 244 ***************************************************************************/
232 245 double GModelSpatialMap::eval_gradients(const GSkyDir& srcDir) const
233 246 {
234   - // Get intensity
235   - double intensity = eval(srcDir);
  247 + // Get skymap intensity
  248 + double intensity = m_map(srcDir);
  249 +
  250 + // Compute partial derivatives of the parameter values
  251 + double g_value = (m_value.isfree()) ? intensity * m_value.scale() : 0.0;
236 252  
237 253 // Set gradient to 0 (circumvent const correctness)
238   - ((GModelSpatialMap*)this)->m_value.gradient(0.0);
  254 + ((GModelSpatialMap*)this)->m_value.gradient(g_value);
239 255  
240   - // Return intensity
241   - return intensity;
  256 + // Return intensity times normalization factor
  257 + return (intensity * m_value.real_value());
242 258 }
243 259  
244 260  
... ... @@ -340,17 +356,8 @@ void GModelSpatialMap::read(const GXmlElement&amp; xml)
340 356 " \"Normalization\" parameter.");
341 357 }
342 358  
343   - // Store filename of skymap (for XML writing). Note that we do not
344   - // expand any environment variable at this level, so that if we write
345   - // back the XML element we write the filepath with the environment
346   - // variable
347   - m_filename = xml.attribute("file");
348   -
349 359 // Load skymap
350   - m_map.load(expand_env(m_filename));
351   -
352   - // Update MC cache
353   - update_mc_cache();
  360 + load_map(xml.attribute("file"));
354 361  
355 362 // Return
356 363 return;
... ... @@ -431,9 +438,9 @@ std::string GModelSpatialMap::print(void) const
431 438 std::string result;
432 439  
433 440 // Append header
434   - result.append("=== GModelSpatialMap ===\n");
435   - result.append(parformat("Sky map file")+m_filename);
436   - result.append(parformat("Number of parameters")+str(size()));
  441 + result.append("=== GModelSpatialMap ===");
  442 + result.append("\n"+parformat("Sky map file")+m_filename);
  443 + result.append("\n"+parformat("Number of parameters")+str(size()));
437 444 for (int i = 0; i < size(); ++i) {
438 445 result.append("\n"+m_pars[i]->print());
439 446 }
... ... @@ -511,16 +518,31 @@ void GModelSpatialMap::free_members(void)
511 518  
512 519  
513 520 /***********************************************************************//**
514   - * @brief Update Monte Carlo cache
  521 + * @brief Load skymap into the model class
515 522 *
516   - * The Monte Carlo cache consists of a linear array that maps a value between
517   - * 0 and 1 into the skymap pixel
  523 + * Loads skymap into the model class. After loading, the map is normalized
  524 + * so that the total flux in the map amounts to 1 ph/cm2/s. Negative skymap
  525 + * pixels are set to zero intensity.
  526 + *
  527 + * The method also initialises a cache for Monte Carlo sampling of the
  528 + * skymap. This Monte Carlo cache consists of a linear array that maps a
  529 + * value between 0 and 1 into the skymap pixel.
518 530 ***************************************************************************/
519   -void GModelSpatialMap::update_mc_cache(void)
  531 +void GModelSpatialMap::load_map(const std::string& filename)
520 532 {
521   - // Initialise cache
  533 + // Initialise skymap and cache
  534 + m_map.clear();
522 535 m_mc_cache.clear();
523 536  
  537 + // Store filename of skymap (for XML writing). Note that we do not
  538 + // expand any environment variable at this level, so that if we write
  539 + // back the XML element we write the filepath with the environment
  540 + // variable
  541 + m_filename = filename;
  542 +
  543 + // Load skymap
  544 + m_map.load(expand_env(m_filename));
  545 +
524 546 // Determine number of skymap pixels
525 547 int npix = m_map.npix();
526 548  
... ... @@ -534,23 +556,29 @@ void GModelSpatialMap::update_mc_cache(void)
534 556 m_mc_cache.push_back(0.0);
535 557  
536 558 // Initialise cache with cumulative pixel fluxes and compute total
537   - // flux in skymap for normalization. Negative pixels are ignored.
  559 + // flux in skymap for normalization. Negative pixels are set to
  560 + // zero intensity in the skymap.
538 561 double sum = 0.0;
539 562 for (int i = 0; i < npix; ++i) {
540 563 double flux = m_map(i) * m_map.omega(i);
541   - if (flux < 0.0) flux = 0.0;
  564 + if (flux < 0.0) {
  565 + m_map(i) = 0.0;
  566 + flux = 0.0;
  567 + }
542 568 sum += flux;
543 569 m_mc_cache.push_back(sum);
544 570 }
545 571  
546   - // Normalize pixel fluxes so that the cache runs from 0 to 1
  572 + // Normalize skymap and pixel fluxes in the cache so that the values
  573 + // in the cache run from 0 to 1
547 574 if (sum > 0.0) {
548   - for (int i = 0; i < npix+1; ++i) {
  575 + for (int i = 0; i < npix; ++i) {
  576 + m_map(i) /= sum;
549 577 m_mc_cache[i] /= sum;
550 578 }
551 579 }
552 580  
553   - // Make sure that last pixel is >1
  581 + // Make sure that last pixel in the cache is >1
554 582 m_mc_cache[npix] = 1.0001;
555 583  
556 584 // Dump cache values for debugging
... ...