Commit 6373db3ed97fc85751aad46a5ee4a79ccddb96d0
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.
Showing
5 changed files
with
81 additions
and
48 deletions
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
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& 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& 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& 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 | ... | ... |