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,6 +29,7 @@
29 29
30 /* __ Includes ___________________________________________________________ */ 30 /* __ Includes ___________________________________________________________ */
31 #include <string> 31 #include <string>
  32 +#include <vector>
32 #include "GModelSpatial.hpp" 33 #include "GModelSpatial.hpp"
33 #include "GModelPar.hpp" 34 #include "GModelPar.hpp"
34 #include "GSkyDir.hpp" 35 #include "GSkyDir.hpp"
@@ -50,6 +51,7 @@ public: @@ -50,6 +51,7 @@ public:
50 // Constructors and destructors 51 // Constructors and destructors
51 GModelSpatialMap(void); 52 GModelSpatialMap(void);
52 explicit GModelSpatialMap(const GXmlElement& xml); 53 explicit GModelSpatialMap(const GXmlElement& xml);
  54 + explicit GModelSpatialMap(const std::string& filename);
53 GModelSpatialMap(const GModelSpatialMap& model); 55 GModelSpatialMap(const GModelSpatialMap& model);
54 virtual ~GModelSpatialMap(void); 56 virtual ~GModelSpatialMap(void);
55 57
@@ -72,7 +74,7 @@ protected: @@ -72,7 +74,7 @@ protected:
72 void init_members(void); 74 void init_members(void);
73 void copy_members(const GModelSpatialMap& model); 75 void copy_members(const GModelSpatialMap& model);
74 void free_members(void); 76 void free_members(void);
75 - void update_mc_cache(void); 77 + void load_map(const std::string& filename);
76 78
77 // Protected members 79 // Protected members
78 GModelPar m_value; //!< Value 80 GModelPar m_value; //!< Value
include/GammaLib.hpp
@@ -152,6 +152,7 @@ @@ -152,6 +152,7 @@
152 #include "GModelSpatialRegistry.hpp" 152 #include "GModelSpatialRegistry.hpp"
153 #include "GModelSpatialConst.hpp" 153 #include "GModelSpatialConst.hpp"
154 #include "GModelSpatialCube.hpp" 154 #include "GModelSpatialCube.hpp"
  155 +#include "GModelSpatialMap.hpp"
155 #include "GModelSpatialPtsrc.hpp" 156 #include "GModelSpatialPtsrc.hpp"
156 #include "GModelRadial.hpp" 157 #include "GModelRadial.hpp"
157 #include "GModelRadialRegistry.hpp" 158 #include "GModelRadialRegistry.hpp"
include/Makefile.am
@@ -49,6 +49,7 @@ pkginclude_HEADERS = GammaLib.hpp \ @@ -49,6 +49,7 @@ pkginclude_HEADERS = GammaLib.hpp \
49 GModelSpatialPtsrc.hpp \ 49 GModelSpatialPtsrc.hpp \
50 GModelSpatialConst.hpp \ 50 GModelSpatialConst.hpp \
51 GModelSpatialCube.hpp \ 51 GModelSpatialCube.hpp \
  52 + GModelSpatialMap.hpp \
52 GModelRadial.hpp \ 53 GModelRadial.hpp \
53 GModelRadialRegistry.hpp \ 54 GModelRadialRegistry.hpp \
54 GModelRadialDisk.hpp \ 55 GModelRadialDisk.hpp \
pyext/GModelSpatialMap.i
@@ -40,6 +40,7 @@ public: @@ -40,6 +40,7 @@ public:
40 // Constructors and destructors 40 // Constructors and destructors
41 GModelSpatialMap(void); 41 GModelSpatialMap(void);
42 explicit GModelSpatialMap(const GXmlElement& xml); 42 explicit GModelSpatialMap(const GXmlElement& xml);
  43 + explicit GModelSpatialMap(const std::string& filename);
43 GModelSpatialMap(const GModelSpatialMap& model); 44 GModelSpatialMap(const GModelSpatialMap& model);
44 virtual ~GModelSpatialMap(void); 45 virtual ~GModelSpatialMap(void);
45 46
src/model/GModelSpatialMap.cpp
@@ -93,6 +93,27 @@ GModelSpatialMap::GModelSpatialMap(const GXmlElement&amp; xml) : GModelSpatial() @@ -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 * @brief Copy constructor 117 * @brief Copy constructor
97 * 118 *
98 * @param[in] model Spatial map model. 119 * @param[in] model Spatial map model.
@@ -197,25 +218,17 @@ GModelSpatialMap* GModelSpatialMap::clone(void) const @@ -197,25 +218,17 @@ GModelSpatialMap* GModelSpatialMap::clone(void) const
197 * 218 *
198 * @param[in] srcDir True photon arrival direction. 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 double GModelSpatialMap::eval(const GSkyDir& srcDir) const 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,21 +237,24 @@ double GModelSpatialMap::eval(const GSkyDir&amp; srcDir) const
224 * 237 *
225 * @param[in] srcDir True photon arrival direction. 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 double GModelSpatialMap::eval_gradients(const GSkyDir& srcDir) const 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 // Set gradient to 0 (circumvent const correctness) 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,17 +356,8 @@ void GModelSpatialMap::read(const GXmlElement&amp; xml)
340 " \"Normalization\" parameter."); 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 // Load skymap 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 // Return 362 // Return
356 return; 363 return;
@@ -431,9 +438,9 @@ std::string GModelSpatialMap::print(void) const @@ -431,9 +438,9 @@ std::string GModelSpatialMap::print(void) const
431 std::string result; 438 std::string result;
432 439
433 // Append header 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 for (int i = 0; i < size(); ++i) { 444 for (int i = 0; i < size(); ++i) {
438 result.append("\n"+m_pars[i]->print()); 445 result.append("\n"+m_pars[i]->print());
439 } 446 }
@@ -511,16 +518,31 @@ void GModelSpatialMap::free_members(void) @@ -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 m_mc_cache.clear(); 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 // Determine number of skymap pixels 546 // Determine number of skymap pixels
525 int npix = m_map.npix(); 547 int npix = m_map.npix();
526 548
@@ -534,23 +556,29 @@ void GModelSpatialMap::update_mc_cache(void) @@ -534,23 +556,29 @@ void GModelSpatialMap::update_mc_cache(void)
534 m_mc_cache.push_back(0.0); 556 m_mc_cache.push_back(0.0);
535 557
536 // Initialise cache with cumulative pixel fluxes and compute total 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 double sum = 0.0; 561 double sum = 0.0;
539 for (int i = 0; i < npix; ++i) { 562 for (int i = 0; i < npix; ++i) {
540 double flux = m_map(i) * m_map.omega(i); 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 sum += flux; 568 sum += flux;
543 m_mc_cache.push_back(sum); 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 if (sum > 0.0) { 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 m_mc_cache[i] /= sum; 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 m_mc_cache[npix] = 1.0001; 582 m_mc_cache[npix] = 1.0001;
555 583
556 // Dump cache values for debugging 584 // Dump cache values for debugging