Commit 1125319657da763967bb935bce560e85e844b4cf
Committed by
Jürgen Knödlseder
1 parent
4e0a5d23
Included model for ebounds in GResponse (3386)
Only relevant for GSpectralGaussian when colvoling with the energy dispersion. The ebounds will just be one bin allowing for proper convolving of response when using a narrow (<< eres) Gaussian
Showing
2 changed files
with
113 additions
and
969 deletions
include/GResponse.hpp
| ... | ... | @@ -33,13 +33,9 @@ |
| 33 | 33 | #include "GFunction.hpp" |
| 34 | 34 | #include "GTime.hpp" |
| 35 | 35 | #include "GResponseCache.hpp" |
| 36 | -#include "GResponseVectorCache.hpp" | |
| 37 | -#include "GFunctions.hpp" | |
| 38 | 36 | |
| 39 | 37 | /* __ Forward declarations _______________________________________________ */ |
| 40 | -class GVector; | |
| 41 | 38 | class GMatrix; |
| 42 | -class GMatrixSparse; | |
| 43 | 39 | class GEvent; |
| 44 | 40 | class GPhoton; |
| 45 | 41 | class GSource; |
| ... | ... | @@ -47,7 +43,6 @@ class GSkyDir; |
| 47 | 43 | class GEnergy; |
| 48 | 44 | class GEbounds; |
| 49 | 45 | class GObservation; |
| 50 | -class GModelPar; | |
| 51 | 46 | class GModelSky; |
| 52 | 47 | class GModelSpatialRadial; |
| 53 | 48 | class GModelSpatialElliptical; |
| ... | ... | @@ -106,34 +101,24 @@ public: |
| 106 | 101 | const GEvent& event, |
| 107 | 102 | const GObservation& obs, |
| 108 | 103 | const bool& grad = true) const; |
| 109 | - virtual GVector convolve(const GModelSky& model, | |
| 110 | - const GObservation& obs, | |
| 111 | - GMatrixSparse* gradients = NULL) const; | |
| 112 | 104 | virtual double irf_spatial(const GEvent& event, |
| 113 | 105 | const GSource& source, |
| 114 | 106 | const GObservation& obs) const; |
| 115 | - virtual GVector irf_spatial(const GModelSky& model, | |
| 116 | - const GObservation& obs, | |
| 117 | - GMatrix* gradients = NULL) const; | |
| 118 | 107 | virtual void remove_response_cache(const std::string& name); |
| 119 | 108 | |
| 109 | + virtual GEbounds ebounds_model(const GModelSky& model) const; | |
| 110 | + | |
| 120 | 111 | protected: |
| 121 | 112 | // Protected methods |
| 122 | - void init_members(void); | |
| 123 | - void copy_members(const GResponse& rsp); | |
| 124 | - void free_members(void); | |
| 125 | - double eval_prob(const GModelSky& model, | |
| 126 | - const GEvent& event, | |
| 127 | - const GEnergy& srcEng, | |
| 128 | - const GTime& srcTime, | |
| 129 | - const GObservation& obs, | |
| 130 | - const bool& grad) const; | |
| 131 | - GVector eval_probs(const GModelSky& model, | |
| 132 | - const GObservation& obs, | |
| 133 | - GMatrixSparse* gradients = NULL) const; | |
| 134 | - int size_edisp_vector(const GModelSky& model, | |
| 135 | - const GObservation& obs, | |
| 136 | - const bool& grad) const; | |
| 113 | + void init_members(void); | |
| 114 | + void copy_members(const GResponse& rsp); | |
| 115 | + void free_members(void); | |
| 116 | + double eval_prob(const GModelSky& model, | |
| 117 | + const GEvent& event, | |
| 118 | + const GEnergy& srcEng, | |
| 119 | + const GTime& srcTime, | |
| 120 | + const GObservation& obs, | |
| 121 | + const bool& grad) const; | |
| 137 | 122 | |
| 138 | 123 | // Virtual protected methods |
| 139 | 124 | virtual double irf_ptsrc(const GEvent& event, |
| ... | ... | @@ -151,42 +136,30 @@ protected: |
| 151 | 136 | virtual double irf_composite(const GEvent& event, |
| 152 | 137 | const GSource& source, |
| 153 | 138 | const GObservation& obs) const; |
| 154 | - virtual GVector irf_ptsrc(const GModelSky& model, | |
| 155 | - const GObservation& obs, | |
| 156 | - GMatrix* gradients = NULL) const; | |
| 157 | - virtual GVector irf_radial(const GModelSky& model, | |
| 158 | - const GObservation& obs, | |
| 159 | - GMatrix* gradients = NULL) const; | |
| 160 | - virtual GVector irf_elliptical(const GModelSky& model, | |
| 161 | - const GObservation& obs, | |
| 162 | - GMatrix* gradients = NULL) const; | |
| 163 | - virtual GVector irf_diffuse(const GModelSky& model, | |
| 164 | - const GObservation& obs, | |
| 165 | - GMatrix* gradients = NULL) const; | |
| 166 | - virtual GVector irf_composite(const GModelSky& model, | |
| 167 | - const GObservation& obs, | |
| 168 | - GMatrix* gradients = NULL) const; | |
| 169 | 139 | |
| 170 | 140 | // Protected classes |
| 171 | - class edisp_kerns : public GFunctions { | |
| 141 | + class edisp_kern : public GFunction { | |
| 172 | 142 | public: |
| 173 | - edisp_kerns(const GResponse* parent, | |
| 174 | - const GObservation* obs, | |
| 175 | - const GModelSky* model, | |
| 176 | - const GEvent* event, | |
| 177 | - const GTime& srcTime, | |
| 178 | - const bool& grad); | |
| 179 | - int size(void) const { return m_size; } | |
| 180 | - GVector eval(const double& etrue); | |
| 143 | + edisp_kern(const GResponse* parent, | |
| 144 | + const GObservation* obs, | |
| 145 | + const GModelSky* model, | |
| 146 | + const GEvent* event, | |
| 147 | + const GTime& srcTime, | |
| 148 | + const bool& grad) : | |
| 149 | + m_parent(parent), | |
| 150 | + m_obs(obs), | |
| 151 | + m_model(model), | |
| 152 | + m_event(event), | |
| 153 | + m_srcTime(srcTime), | |
| 154 | + m_grad(grad) { } | |
| 155 | + double eval(const double& etrue); | |
| 181 | 156 | protected: |
| 182 | - const GResponse* m_parent; //!< Response | |
| 183 | - const GObservation* m_obs; //!< Observation | |
| 184 | - const GModelSky* m_model; //!< Sky model | |
| 185 | - const GEvent* m_event; //!< Event | |
| 186 | - int m_size; //!< Array of values and gradients | |
| 187 | - std::vector<GModelPar*> m_pars; //!< Parameter pointers | |
| 188 | - GTime m_srcTime; //!< True arrival time | |
| 189 | - bool m_grad; //!< Gradient flag | |
| 157 | + const GResponse* m_parent; //!< Response | |
| 158 | + const GObservation* m_obs; //!< Observation | |
| 159 | + const GModelSky* m_model; //!< Sky model | |
| 160 | + const GEvent* m_event; //!< Event | |
| 161 | + GTime m_srcTime; //!< True arrival time | |
| 162 | + bool m_grad; //!< Gradient flag | |
| 190 | 163 | }; |
| 191 | 164 | class irf_radial_kern_theta : public GFunction { |
| 192 | 165 | public: |
| ... | ... | @@ -320,9 +293,8 @@ protected: |
| 320 | 293 | // Cache for irf(GEvent&, GSource&, GObservation&) and |
| 321 | 294 | // nroi(GModelSky&, GEnergy&, GTime&, GEnergy&, GTime&, GObservation&) |
| 322 | 295 | // computations |
| 323 | - mutable GResponseCache m_irf_cache; | |
| 324 | - mutable GResponseCache m_nroi_cache; | |
| 325 | - mutable GResponseVectorCache m_irf_vector_cache; | |
| 296 | + mutable GResponseCache m_irf_cache; | |
| 297 | + mutable GResponseCache m_nroi_cache; | |
| 326 | 298 | }; |
| 327 | 299 | |
| 328 | 300 | #endif /* GRESPONSE_HPP */ | ... | ... |
src/obs/GResponse.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * GResponse.cpp - Abstract response base class * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2008-2021 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2008-2020 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -35,9 +35,7 @@ |
| 35 | 35 | #include "GMath.hpp" |
| 36 | 36 | #include "GVector.hpp" |
| 37 | 37 | #include "GMatrix.hpp" |
| 38 | -#include "GMatrixSparse.hpp" | |
| 39 | 38 | #include "GIntegral.hpp" |
| 40 | -#include "GIntegrals.hpp" | |
| 41 | 39 | #include "GResponse.hpp" |
| 42 | 40 | #include "GEvent.hpp" |
| 43 | 41 | #include "GPhoton.hpp" |
| ... | ... | @@ -48,6 +46,7 @@ |
| 48 | 46 | #include "GObservation.hpp" |
| 49 | 47 | #include "GSkyMap.hpp" |
| 50 | 48 | #include "GModelSky.hpp" |
| 49 | +#include "GModelSpectralGauss.hpp" | |
| 51 | 50 | #include "GModelSpatialPointSource.hpp" |
| 52 | 51 | #include "GModelSpatialRadial.hpp" |
| 53 | 52 | #include "GModelSpatialElliptical.hpp" |
| ... | ... | @@ -57,8 +56,6 @@ |
| 57 | 56 | #include "GModelSpatialComposite.hpp" |
| 58 | 57 | |
| 59 | 58 | /* __ Method name definitions ____________________________________________ */ |
| 60 | -#define G_CONVOLVE "GResponse::convolve(GModelSky&, GObservation&, "\ | |
| 61 | - "GMatrixSparse*)" | |
| 62 | 59 | #define G_IRF_RADIAL "GResponse::irf_radial(GEvent&, GSource&,"\ |
| 63 | 60 | " GObservation&)" |
| 64 | 61 | #define G_IRF_ELLIPTICAL "GResponse::irf_elliptical(GEvent&, GSource&,"\ |
| ... | ... | @@ -71,6 +68,7 @@ |
| 71 | 68 | /* __ Coding definitions _________________________________________________ */ |
| 72 | 69 | |
| 73 | 70 | /* __ Debug definitions __________________________________________________ */ |
| 71 | +#define G_DEBUG_CONVOLVE_EDISP //!< Debug convolve for energy dispersion | |
| 74 | 72 | |
| 75 | 73 | |
| 76 | 74 | /*========================================================================== |
| ... | ... | @@ -168,7 +166,7 @@ GResponse& GResponse::operator=(const GResponse& rsp) |
| 168 | 166 | * @param[in] model Sky model. |
| 169 | 167 | * @param[in] event Event. |
| 170 | 168 | * @param[in] obs Observation. |
| 171 | - * @param[in] grad Should model gradients be computed? | |
| 169 | + * @param[in] grad Should model gradients be computed? (default: true) | |
| 172 | 170 | * @return Event probability. |
| 173 | 171 | * |
| 174 | 172 | * Computes the event probability |
| ... | ... | @@ -205,11 +203,11 @@ double GResponse::convolve(const GModelSky& model, |
| 205 | 203 | // Retrieve true energy boundaries |
| 206 | 204 | GEbounds ebounds = this->ebounds(event.energy()); |
| 207 | 205 | |
| 208 | - // Determine size of result array | |
| 209 | - int size = size_edisp_vector(model, obs, grad); | |
| 210 | - | |
| 211 | 206 | // Initialise vector array |
| 212 | - GVector array(size); | |
| 207 | + //GVector array(ebounds.size()); // need this? | |
| 208 | + | |
| 209 | + // Get Valid Ebounds | |
| 210 | + GEbounds valid_ebounds = this->ebounds_model(model); | |
| 213 | 211 | |
| 214 | 212 | // Loop over all boundaries |
| 215 | 213 | for (int i = 0; i < ebounds.size(); ++i) { |
| ... | ... | @@ -218,67 +216,38 @@ double GResponse::convolve(const GModelSky& model, |
| 218 | 216 | double etrue_min = ebounds.emin(i).MeV(); |
| 219 | 217 | double etrue_max = ebounds.emax(i).MeV(); |
| 220 | 218 | |
| 219 | + | |
| 220 | + // Limit energy bounds for model | |
| 221 | + if (valid_ebounds.size() > 0 ) | |
| 222 | + { | |
| 223 | + if (valid_ebounds.emin(0).MeV() > etrue_min ) | |
| 224 | + { | |
| 225 | + etrue_min = valid_ebounds.emin(0).MeV(); | |
| 226 | + } | |
| 227 | + if (valid_ebounds.emax(0).MeV() < etrue_max ) | |
| 228 | + { | |
| 229 | + etrue_max = valid_ebounds.emax(0).MeV(); | |
| 230 | + } | |
| 231 | + } | |
| 232 | + | |
| 221 | 233 | // Continue only if valid |
| 222 | 234 | if (etrue_max > etrue_min) { |
| 223 | 235 | |
| 224 | 236 | // Setup integration function |
| 225 | - edisp_kerns integrand(this, &obs, &model, &event, srcTime, grad); | |
| 226 | - GIntegrals integral(&integrand); | |
| 237 | + edisp_kern integrand(this, &obs, &model, &event, srcTime, grad); | |
| 238 | + GIntegral integral(&integrand); | |
| 227 | 239 | |
| 228 | 240 | // Set number of iterations |
| 229 | 241 | integral.fixed_iter(iter); |
| 230 | 242 | |
| 231 | 243 | // Do Romberg integration |
| 232 | - array += integral.romberg(etrue_min, etrue_max); | |
| 244 | + prob += integral.romberg(etrue_min, etrue_max); | |
| 233 | 245 | |
| 234 | 246 | } // endif: interval was valid |
| 235 | 247 | |
| 236 | 248 | } // endfor: looped over intervals |
| 237 | 249 | |
| 238 | - // Initialise array index | |
| 239 | - int index = 0; | |
| 240 | - | |
| 241 | - // Get probability | |
| 242 | - prob = array[index++]; | |
| 243 | - | |
| 244 | - // Set gradients | |
| 245 | - if (grad) { | |
| 246 | - | |
| 247 | - // Set spectral gradients | |
| 248 | - if (model.spectral() != NULL) { | |
| 249 | - for (int i = 0; i < model.spectral()->size(); ++i) { | |
| 250 | - GModelPar& par = (*(model.spectral()))[i]; | |
| 251 | - if (par.is_free() && par.has_grad()) { | |
| 252 | - par.factor_gradient(array[index++]); | |
| 253 | - } | |
| 254 | - } | |
| 255 | - } | |
| 256 | - | |
| 257 | - // Set temporal gradients | |
| 258 | - if (model.temporal() != NULL) { | |
| 259 | - for (int i = 0; i < model.temporal()->size(); ++i) { | |
| 260 | - GModelPar& par = (*(model.temporal()))[i]; | |
| 261 | - if (par.is_free() && par.has_grad()) { | |
| 262 | - par.factor_gradient(array[index++]); | |
| 263 | - } | |
| 264 | - } | |
| 265 | - } | |
| 266 | - | |
| 267 | - // Optionally set scale gradient for instrument | |
| 268 | - if (model.has_scales()) { | |
| 269 | - for (int i = 0; i < model.scales(); ++i) { | |
| 270 | - const GModelPar& par = model.scale(i); | |
| 271 | - if (par.name() == obs.instrument()) { | |
| 272 | - if (par.is_free() && par.has_grad()) { | |
| 273 | - par.factor_gradient(array[index++]); | |
| 274 | - } | |
| 275 | - } | |
| 276 | - } | |
| 277 | - } | |
| 278 | - | |
| 279 | - } // endif: set gradients | |
| 280 | - | |
| 281 | - } // endif: Case A | |
| 250 | + } | |
| 282 | 251 | |
| 283 | 252 | // Case B: No integration (assume no energy dispersion) |
| 284 | 253 | else { |
| ... | ... | @@ -289,7 +258,7 @@ double GResponse::convolve(const GModelSky& model, |
| 289 | 258 | // Evaluate probability |
| 290 | 259 | prob = eval_prob(model, event, srcEng, srcTime, obs, grad); |
| 291 | 260 | |
| 292 | - } // endelse: Case B | |
| 261 | + } | |
| 293 | 262 | |
| 294 | 263 | // Compile option: Check for NaN/Inf |
| 295 | 264 | #if defined(G_NAN_CHECK) |
| ... | ... | @@ -310,214 +279,51 @@ double GResponse::convolve(const GModelSky& model, |
| 310 | 279 | } |
| 311 | 280 | |
| 312 | 281 | |
| 282 | + | |
| 313 | 283 | /***********************************************************************//** |
| 314 | - * @brief Convolve sky model with the instrument response | |
| 284 | + * @brief Validity of true energy interval | |
| 315 | 285 | * |
| 316 | - * @param[in] model Sky model. | |
| 317 | - * @param[in] obs Observation. | |
| 318 | - * @param[out] gradients Pointer to matrix of gradients. | |
| 319 | - * @return Vector of event probabilities. | |
| 286 | + * @param[in] GModelSky& model | |
| 287 | + * @return GEbounds | |
| 320 | 288 | * |
| 321 | - * Computes the event probability | |
| 289 | + * Computes the valitdity of the true energy model. | |
| 290 | + * Special treatment of narrow Gaussians as approximation for | |
| 291 | + * monochromatic lines. | |
| 292 | + * For a Gaussian Model return one sigle boundry 5 sigma around the line | |
| 293 | + * energy. | |
| 294 | + * Other models return empty boundry container. | |
| 322 | 295 | * |
| 323 | - * \f[ | |
| 324 | - * P(p',E',t') = \int \int \int | |
| 325 | - * S(p,E,t) \times R(p',E',t'|p,E,t) \, dp \, dE \, dt | |
| 326 | - * \f] | |
| 327 | - * | |
| 328 | - * without taking into account any time dispersion. Energy dispersion is | |
| 329 | - * correctly handled by this method. If time dispersion is indeed needed, | |
| 330 | - * an instrument specific method needs to be provided. | |
| 331 | 296 | ***************************************************************************/ |
| 332 | -GVector GResponse::convolve(const GModelSky& model, | |
| 333 | - const GObservation& obs, | |
| 334 | - GMatrixSparse* gradients) const | |
| 297 | +GEbounds GResponse::ebounds_model(const GModelSky& model) const | |
| 335 | 298 | { |
| 336 | - // Set number of iterations for Romberg integration. | |
| 337 | - static const int iter = 6; | |
| 338 | - | |
| 339 | - // Get number of model parameters and number of events | |
| 340 | - int npars = model.size(); | |
| 341 | - int nevents = obs.events()->size(); | |
| 342 | - | |
| 343 | - // Initialise gradients flag | |
| 344 | - bool grad = (gradients != NULL); | |
| 345 | - | |
| 346 | - // Check matrix consistency | |
| 347 | - if (grad) { | |
| 348 | - if (gradients->columns() != npars) { | |
| 349 | - std::string msg = "Number of "+gammalib::str(gradients->columns())+ | |
| 350 | - " columns in gradient matrix differs from number " | |
| 351 | - "of "+gammalib::str(npars)+" parameters " | |
| 352 | - "in model. Please provide a compatible gradient " | |
| 353 | - "matrix."; | |
| 354 | - throw GException::invalid_argument(G_CONVOLVE, msg); | |
| 355 | - } | |
| 356 | - if (gradients->rows() != nevents) { | |
| 357 | - std::string msg = "Number of "+gammalib::str(gradients->rows())+ | |
| 358 | - " rows in gradient matrix differs from number " | |
| 359 | - "of "+gammalib::str(nevents)+" events in " | |
| 360 | - "observation. Please provide a compatible " | |
| 361 | - "gradient matrix."; | |
| 362 | - throw GException::invalid_argument(G_CONVOLVE, msg); | |
| 363 | - } | |
| 364 | - } | |
| 365 | - | |
| 366 | - // Initialise result | |
| 367 | - GVector probs(nevents); | |
| 368 | - | |
| 369 | - // Continue only if the model has a spatial component | |
| 370 | - if (model.spatial() != NULL) { | |
| 371 | - | |
| 372 | - // Case A: Integration | |
| 373 | - if (use_edisp()) { | |
| 374 | - | |
| 375 | - // Initialise temporary vectors to hold gradients | |
| 376 | - GVector* tmp_gradients = NULL; | |
| 377 | - if (grad) { | |
| 378 | - tmp_gradients = new GVector[npars]; | |
| 379 | - for (int i = 0; i < npars; ++i) { | |
| 380 | - tmp_gradients[i] = GVector(nevents); | |
| 381 | - } | |
| 382 | - } | |
| 383 | - | |
| 384 | - // Determine size of result array | |
| 385 | - int size = size_edisp_vector(model, obs, grad); | |
| 386 | - | |
| 387 | - // Loop over events | |
| 388 | - for (int k = 0; k < nevents; ++k) { | |
| 389 | - | |
| 390 | - // Get reference to event | |
| 391 | - const GEvent& event = *((*obs.events())[k]); | |
| 392 | - | |
| 393 | - // Get source time (no dispersion) | |
| 394 | - GTime srcTime = event.time(); | |
| 395 | - | |
| 396 | - // Retrieve true energy boundaries | |
| 397 | - GEbounds ebounds = this->ebounds(event.energy()); | |
| 398 | - | |
| 399 | - // Initialise vector array | |
| 400 | - GVector array(size); | |
| 401 | - | |
| 402 | - // Loop over all boundaries | |
| 403 | - for (int i = 0; i < ebounds.size(); ++i) { | |
| 404 | - | |
| 405 | - // Get true energy boundaries in MeV | |
| 406 | - double etrue_min = ebounds.emin(i).MeV(); | |
| 407 | - double etrue_max = ebounds.emax(i).MeV(); | |
| 408 | - | |
| 409 | - // Continue only if valid | |
| 410 | - if (etrue_max > etrue_min) { | |
| 411 | - | |
| 412 | - // Setup integration function | |
| 413 | - edisp_kerns integrand(this, &obs, &model, &event, srcTime, grad); | |
| 414 | - GIntegrals integral(&integrand); | |
| 415 | - | |
| 416 | - // Set number of iterations | |
| 417 | - integral.fixed_iter(iter); | |
| 418 | - | |
| 419 | - // Do Romberg integration | |
| 420 | - array += integral.romberg(etrue_min, etrue_max); | |
| 421 | - | |
| 422 | - } // endif: interval was valid | |
| 423 | - | |
| 424 | - } // endfor: looped over intervals | |
| 425 | - | |
| 426 | - // Initialise array index | |
| 427 | - int index = 0; | |
| 428 | - | |
| 429 | - // Get probability | |
| 430 | - probs[k] = array[index++]; | |
| 431 | - | |
| 432 | - // Set gradients | |
| 433 | - if (grad) { | |
| 434 | - | |
| 435 | - // Get number of spatial, spectral and temporal parameters | |
| 436 | - int n_spat = model.spatial()->size(); | |
| 437 | - int n_spec = model.spectral()->size(); | |
| 438 | - int n_temp = model.temporal()->size(); | |
| 439 | - | |
| 440 | - // Set spectral gradients | |
| 441 | - if (model.spectral() != NULL) { | |
| 442 | - int offset = n_spat; | |
| 443 | - for (int i = 0; i < n_spec; ++i) { | |
| 444 | - const GModelPar& par = (*(model.spectral()))[i]; | |
| 445 | - if (par.is_free() && par.has_grad()) { | |
| 446 | - tmp_gradients[offset+i][k] = array[index++]; | |
| 447 | - } | |
| 448 | - } | |
| 449 | - } | |
| 450 | - | |
| 451 | - // Set temporal gradients | |
| 452 | - if (model.temporal() != NULL) { | |
| 453 | - int offset = n_spat + n_spec; | |
| 454 | - for (int i = 0; i < n_temp; ++i) { | |
| 455 | - const GModelPar& par = (*(model.temporal()))[i]; | |
| 456 | - if (par.is_free() && par.has_grad()) { | |
| 457 | - tmp_gradients[offset+i][k] = array[index++]; | |
| 458 | - } | |
| 459 | - } | |
| 460 | - } | |
| 461 | - | |
| 462 | - // Optionally set scale gradient for instrument | |
| 463 | - if (model.has_scales()) { | |
| 464 | - int offset = n_spat + n_spec + n_temp; | |
| 465 | - for (int i = 0; i < model.scales(); ++i) { | |
| 466 | - const GModelPar& par = model.scale(i); | |
| 467 | - if (par.name() == obs.instrument()) { | |
| 468 | - if (par.is_free() && par.has_grad()) { | |
| 469 | - tmp_gradients[offset+i][k] = array[index++]; | |
| 470 | - } | |
| 471 | - } | |
| 472 | - } | |
| 473 | - } | |
| 474 | - | |
| 475 | - } // endif: set gradients | |
| 476 | - | |
| 477 | - // Compile option: Check for NaN/Inf | |
| 478 | - #if defined(G_NAN_CHECK) | |
| 479 | - if (gammalib::is_notanumber(probs[k]) || gammalib::is_infinite(probs[k])) { | |
| 480 | - std::cout << "*** ERROR: GResponse::convolve:"; | |
| 481 | - std::cout << " NaN/Inf encountered"; | |
| 482 | - std::cout << " (probs[" << k << "]=" << probs[k]; | |
| 483 | - std::cout << ", event=" << event; | |
| 484 | - std::cout << ", srcTime=" << srcTime; | |
| 485 | - std::cout << ")" << std::endl; | |
| 486 | - } | |
| 487 | - #endif | |
| 488 | - | |
| 489 | - } // endfor: looped over events | |
| 490 | - | |
| 491 | - // Post-process gradients | |
| 492 | - if (grad) { | |
| 493 | 299 | |
| 494 | - // Fill gradients into matrix | |
| 495 | - for (int i = 0; i < npars; ++i) { | |
| 496 | - gradients->column(i, tmp_gradients[i]); | |
| 497 | - } | |
| 498 | - | |
| 499 | - // Delete temporal gradients | |
| 500 | - delete [] tmp_gradients; | |
| 501 | - | |
| 502 | - } // endif: post-processed gradients | |
| 503 | - | |
| 504 | - } // endif: Case A | |
| 505 | - | |
| 506 | - // Case B: No integration (assume no energy dispersion) | |
| 507 | - else { | |
| 508 | - | |
| 509 | - // Evaluate probability | |
| 510 | - probs = eval_probs(model, obs, gradients); | |
| 511 | - | |
| 512 | - } // endelse: Case B | |
| 513 | - | |
| 514 | - } // endif: spatial component valid | |
| 515 | - | |
| 516 | - // Return probabilities | |
| 517 | - return probs; | |
| 300 | + if(model.spectral()->type() == "Gaussian") | |
| 301 | + { | |
| 302 | + const double size = 5.0; | |
| 303 | + const GModelSpectralGauss* gauss = dynamic_cast<const GModelSpectralGauss*>(model.spectral()); | |
| 304 | + | |
| 305 | + | |
| 306 | + GEnergy mu = gauss->mean(); | |
| 307 | + GEnergy sigma = gauss->sigma(); | |
| 308 | + | |
| 309 | + GEnergy ebound_min = mu - size * sigma; | |
| 310 | + GEnergy ebound_max = mu + size * sigma; | |
| 311 | + | |
| 312 | + GEbounds emebounds(ebound_min, ebound_max); | |
| 313 | + | |
| 314 | + return emebounds; | |
| 315 | + | |
| 316 | + } | |
| 317 | + else | |
| 318 | + { | |
| 319 | + GEbounds empty_ebounds; | |
| 320 | + return empty_ebounds; | |
| 321 | + } | |
| 322 | + | |
| 518 | 323 | } |
| 519 | 324 | |
| 520 | 325 | |
| 326 | + | |
| 521 | 327 | /***********************************************************************//** |
| 522 | 328 | * @brief Return instrument response integrated over the spatial model |
| 523 | 329 | * |
| ... | ... | @@ -569,7 +375,7 @@ double GResponse::irf_spatial(const GEvent& event, |
| 569 | 375 | double irf = 0.0; |
| 570 | 376 | |
| 571 | 377 | // Set IRF value attributes |
| 572 | - std::string name = obs.id() + ":" + source.name(); | |
| 378 | + std::string name = obs.id() + "::" + source.name(); | |
| 573 | 379 | const GInstDir& dir = event.dir(); |
| 574 | 380 | const GEnergy& ereco = event.energy(); |
| 575 | 381 | const GEnergy& etrue = source.energy(); |
| ... | ... | @@ -619,112 +425,6 @@ double GResponse::irf_spatial(const GEvent& event, |
| 619 | 425 | |
| 620 | 426 | |
| 621 | 427 | /***********************************************************************//** |
| 622 | - * @brief Return instrument response vector integrated over the spatial model | |
| 623 | - * | |
| 624 | - * @param[in] model Sky model. | |
| 625 | - * @param[in] obs Observation. | |
| 626 | - * @param[in] gradients Gradients matrix. | |
| 627 | - * @return Instrument response vector to a spatial model. | |
| 628 | - * | |
| 629 | - * Returns the instrument response to a sky model integrated over the spatial | |
| 630 | - * model component for all events in a given observation. The method computes | |
| 631 | - * | |
| 632 | - * \f[ | |
| 633 | - * {\tt irf}(p', E', t') = \int_p M_{\rm S}(p | E, t) \, | |
| 634 | - * R(p', E', t' | p, E, t) \, d\,p | |
| 635 | - * \f] | |
| 636 | - * | |
| 637 | - * where | |
| 638 | - * * \f$M_{\rm S}(p | E, t)\f$ is the spatial model component, | |
| 639 | - * * \f$R(p', E', t' | p, E, t)\f$ is the Instrument Response Function (IRF), | |
| 640 | - * * \f$p'\f$ is the measured instrument direction, | |
| 641 | - * * \f$E'\f$ is the measured or reconstructed energy, | |
| 642 | - * * \f$t'\f$ is the measured arrival time, | |
| 643 | - * * \f$p\f$ is the true photon arrival direction, | |
| 644 | - * * \f$E\f$ is the true photon energy, and | |
| 645 | - * * \f$t\f$ is the true trigger time. | |
| 646 | - * | |
| 647 | - * The integration is done over all relevant true sky directions \f$p\f$. | |
| 648 | - * | |
| 649 | - * Depending on the type of the source model the method branches to the | |
| 650 | - * following methods to perform the actual computations | |
| 651 | - * | |
| 652 | - * * irf_ptsrc() - for the handling of a point source | |
| 653 | - * * irf_radial() - for radial models | |
| 654 | - * * irf_elliptical() - for elliptical models | |
| 655 | - * * irf_diffuse() - for diffuse models | |
| 656 | - * * irf_composite() - for composite models | |
| 657 | - * | |
| 658 | - * The method implements a caching mechanism for spatial models that have all | |
| 659 | - * parameters fixed. For those models the instrument response for a given | |
| 660 | - * event and observation is only computed once and then stored in an internal | |
| 661 | - * cache from which it is fetched back in case that the method is called | |
| 662 | - * again for the same event and observation. | |
| 663 | - ***************************************************************************/ | |
| 664 | -GVector GResponse::irf_spatial(const GModelSky& model, | |
| 665 | - const GObservation& obs, | |
| 666 | - GMatrix* gradients) const | |
| 667 | -{ | |
| 668 | - // Get number of model parameters and number of events | |
| 669 | - int npars = model.size(); | |
| 670 | - int nevents = obs.events()->size(); | |
| 671 | - | |
| 672 | - // Initialise result | |
| 673 | - GVector irfs(nevents); | |
| 674 | - | |
| 675 | - // Continue only if model has a spatial component | |
| 676 | - if (model.spatial() != NULL) { | |
| 677 | - | |
| 678 | - // Set IRF cache identifier | |
| 679 | - std::string cache_id = obs.id() + ":" + model.name(); | |
| 680 | - | |
| 681 | - // Signal if spatial model has free parameters | |
| 682 | - bool has_free_pars = model.spatial()->has_free_pars(); | |
| 683 | - | |
| 684 | - // If the spatial model component has free parameters, or the response | |
| 685 | - // cache should not be used, or the cache does not contain the requested | |
| 686 | - // IRF value then compute the IRF value for the spatial model. | |
| 687 | - if (has_free_pars || | |
| 688 | - !m_use_irf_cache || | |
| 689 | - !m_irf_vector_cache.contains(cache_id, &irfs)) { | |
| 690 | - | |
| 691 | - // Compute IRF for spatial model | |
| 692 | - switch (model.spatial()->code()) { | |
| 693 | - case GMODEL_SPATIAL_POINT_SOURCE: | |
| 694 | - irfs = irf_ptsrc(model, obs, gradients); | |
| 695 | - break; | |
| 696 | - case GMODEL_SPATIAL_RADIAL: | |
| 697 | - irfs = irf_radial(model, obs, gradients); | |
| 698 | - break; | |
| 699 | - case GMODEL_SPATIAL_ELLIPTICAL: | |
| 700 | - irfs = irf_elliptical(model, obs, gradients); | |
| 701 | - break; | |
| 702 | - case GMODEL_SPATIAL_DIFFUSE: | |
| 703 | - irfs = irf_diffuse(model, obs, gradients); | |
| 704 | - break; | |
| 705 | - case GMODEL_SPATIAL_COMPOSITE: | |
| 706 | - irfs = irf_composite(model, obs, gradients); | |
| 707 | - break; | |
| 708 | - default: | |
| 709 | - break; | |
| 710 | - } | |
| 711 | - | |
| 712 | - // If the spatial model has no free parameters and the response cache | |
| 713 | - // should be used then put the IRF value in the response cache. | |
| 714 | - if (!has_free_pars && m_use_irf_cache) { | |
| 715 | - m_irf_vector_cache.set(cache_id, irfs); | |
| 716 | - } | |
| 717 | - | |
| 718 | - } // endif: computed spatial model | |
| 719 | - | |
| 720 | - } // endif: model had spatial component | |
| 721 | - | |
| 722 | - // Return IRF values | |
| 723 | - return irfs; | |
| 724 | -} | |
| 725 | - | |
| 726 | - | |
| 727 | -/***********************************************************************//** | |
| 728 | 428 | * @brief Remove response cache for model |
| 729 | 429 | * |
| 730 | 430 | * @param[in] name Model name. |
| ... | ... | @@ -736,7 +436,6 @@ void GResponse::remove_response_cache(const std::string& name) |
| 736 | 436 | // Remove model from response caches |
| 737 | 437 | m_irf_cache.remove(name); |
| 738 | 438 | m_nroi_cache.remove(name); |
| 739 | - m_irf_vector_cache.remove(name); | |
| 740 | 439 | |
| 741 | 440 | // Return |
| 742 | 441 | return; |
| ... | ... | @@ -766,7 +465,6 @@ void GResponse::init_members(void) |
| 766 | 465 | // Clear cache |
| 767 | 466 | m_irf_cache.clear(); |
| 768 | 467 | m_nroi_cache.clear(); |
| 769 | - m_irf_vector_cache.clear(); | |
| 770 | 468 | |
| 771 | 469 | // Return |
| 772 | 470 | return; |
| ... | ... | @@ -790,7 +488,6 @@ void GResponse::copy_members(const GResponse& rsp) |
| 790 | 488 | m_irf_diffuse_resolution = rsp.m_irf_diffuse_resolution; |
| 791 | 489 | m_irf_cache = rsp.m_irf_cache; |
| 792 | 490 | m_nroi_cache = rsp.m_nroi_cache; |
| 793 | - m_irf_vector_cache = rsp.m_irf_vector_cache; | |
| 794 | 491 | |
| 795 | 492 | // Return |
| 796 | 493 | return; |
| ... | ... | @@ -1094,6 +791,9 @@ double GResponse::irf_diffuse(const GEvent& event, |
| 1094 | 791 | const GEnergy& srcEng = source.energy(); |
| 1095 | 792 | const GTime& srcTime = source.time(); |
| 1096 | 793 | |
| 794 | + // Initialise map | |
| 795 | + //GSkyMap skymap; | |
| 796 | + | |
| 1097 | 797 | // If model is a diffuse map model then extract sky map |
| 1098 | 798 | const GModelSpatialDiffuseMap* map = |
| 1099 | 799 | dynamic_cast<const GModelSpatialDiffuseMap*>(source.model()); |
| ... | ... | @@ -1257,232 +957,6 @@ double GResponse::irf_composite(const GEvent& event, |
| 1257 | 957 | |
| 1258 | 958 | |
| 1259 | 959 | /***********************************************************************//** |
| 1260 | - * @brief Return instrument response to point source sky model | |
| 1261 | - * | |
| 1262 | - * @param[in] model Sky model. | |
| 1263 | - * @param[in] obs Observation. | |
| 1264 | - * @param[in] gradients Gradients matrix. | |
| 1265 | - * @return Instrument response to point source sky model. | |
| 1266 | - * | |
| 1267 | - * Returns the instrument response to a point source sky model for all | |
| 1268 | - * events. | |
| 1269 | - ***************************************************************************/ | |
| 1270 | -GVector GResponse::irf_ptsrc(const GModelSky& model, | |
| 1271 | - const GObservation& obs, | |
| 1272 | - GMatrix* gradients) const | |
| 1273 | -{ | |
| 1274 | - // Get number of events | |
| 1275 | - int nevents = obs.events()->size(); | |
| 1276 | - | |
| 1277 | - // Initialise result | |
| 1278 | - GVector irfs(nevents); | |
| 1279 | - | |
| 1280 | - // Loop over events | |
| 1281 | - for (int k = 0; k < nevents; ++k) { | |
| 1282 | - | |
| 1283 | - // Get reference to event | |
| 1284 | - const GEvent& event = *((*obs.events())[k]); | |
| 1285 | - | |
| 1286 | - // Get source energy and time (no dispersion) | |
| 1287 | - GEnergy srcEng = event.energy(); | |
| 1288 | - GTime srcTime = event.time(); | |
| 1289 | - | |
| 1290 | - // Setup source | |
| 1291 | - GSource source(model.name(), model.spatial(), srcEng, srcTime); | |
| 1292 | - | |
| 1293 | - // Get IRF value for event | |
| 1294 | - irfs[k] = this->irf_ptsrc(event, source, obs); | |
| 1295 | - | |
| 1296 | - } // endfor: looped over events | |
| 1297 | - | |
| 1298 | - // Return IRF value | |
| 1299 | - return irfs; | |
| 1300 | -} | |
| 1301 | - | |
| 1302 | - | |
| 1303 | -/***********************************************************************//** | |
| 1304 | - * @brief Return instrument response to radial source sky model | |
| 1305 | - * | |
| 1306 | - * @param[in] model Sky model. | |
| 1307 | - * @param[in] obs Observation. | |
| 1308 | - * @param[in] gradients Gradients matrix. | |
| 1309 | - * @return Instrument response to radial source sky model. | |
| 1310 | - * | |
| 1311 | - * Returns the instrument response to a radial source sky model for all | |
| 1312 | - * events. | |
| 1313 | - ***************************************************************************/ | |
| 1314 | -GVector GResponse::irf_radial(const GModelSky& model, | |
| 1315 | - const GObservation& obs, | |
| 1316 | - GMatrix* gradients) const | |
| 1317 | -{ | |
| 1318 | - // Get number of events | |
| 1319 | - int nevents = obs.events()->size(); | |
| 1320 | - | |
| 1321 | - // Initialise result | |
| 1322 | - GVector irfs(nevents); | |
| 1323 | - | |
| 1324 | - // Loop over events | |
| 1325 | - for (int k = 0; k < nevents; ++k) { | |
| 1326 | - | |
| 1327 | - // Get reference to event | |
| 1328 | - const GEvent& event = *((*obs.events())[k]); | |
| 1329 | - | |
| 1330 | - // Get source energy and time (no dispersion) | |
| 1331 | - GEnergy srcEng = event.energy(); | |
| 1332 | - GTime srcTime = event.time(); | |
| 1333 | - | |
| 1334 | - // Setup source | |
| 1335 | - GSource source(model.name(), model.spatial(), srcEng, srcTime); | |
| 1336 | - | |
| 1337 | - // Get IRF value for event | |
| 1338 | - irfs[k] = this->irf_radial(event, source, obs); | |
| 1339 | - | |
| 1340 | - } // endfor: looped over events | |
| 1341 | - | |
| 1342 | - // Return IRF value | |
| 1343 | - return irfs; | |
| 1344 | -} | |
| 1345 | - | |
| 1346 | - | |
| 1347 | -/***********************************************************************//** | |
| 1348 | - * @brief Return instrument response to ellipitical source sky model | |
| 1349 | - * | |
| 1350 | - * @param[in] model Sky model. | |
| 1351 | - * @param[in] obs Observation. | |
| 1352 | - * @param[in] gradients Gradients matrix. | |
| 1353 | - * @return Instrument response to ellipitical source sky model. | |
| 1354 | - * | |
| 1355 | - * Returns the instrument response to a ellipitical source sky model for all | |
| 1356 | - * events. | |
| 1357 | - ***************************************************************************/ | |
| 1358 | -GVector GResponse::irf_elliptical(const GModelSky& model, | |
| 1359 | - const GObservation& obs, | |
| 1360 | - GMatrix* gradients) const | |
| 1361 | -{ | |
| 1362 | - // Get number of events | |
| 1363 | - int nevents = obs.events()->size(); | |
| 1364 | - | |
| 1365 | - // Initialise result | |
| 1366 | - GVector irfs(nevents); | |
| 1367 | - | |
| 1368 | - // Loop over events | |
| 1369 | - for (int k = 0; k < nevents; ++k) { | |
| 1370 | - | |
| 1371 | - // Get reference to event | |
| 1372 | - const GEvent& event = *((*obs.events())[k]); | |
| 1373 | - | |
| 1374 | - // Get source energy and time (no dispersion) | |
| 1375 | - GEnergy srcEng = event.energy(); | |
| 1376 | - GTime srcTime = event.time(); | |
| 1377 | - | |
| 1378 | - // Setup source | |
| 1379 | - GSource source(model.name(), model.spatial(), srcEng, srcTime); | |
| 1380 | - | |
| 1381 | - // Get IRF value for event | |
| 1382 | - irfs[k] = this->irf_elliptical(event, source, obs); | |
| 1383 | - | |
| 1384 | - } // endfor: looped over events | |
| 1385 | - | |
| 1386 | - // Return IRF value | |
| 1387 | - return irfs; | |
| 1388 | -} | |
| 1389 | - | |
| 1390 | - | |
| 1391 | -/***********************************************************************//** | |
| 1392 | - * @brief Return instrument response to diffuse source sky model | |
| 1393 | - * | |
| 1394 | - * @param[in] model Sky model. | |
| 1395 | - * @param[in] obs Observation. | |
| 1396 | - * @param[in] gradients Gradients matrix. | |
| 1397 | - * @return Instrument response to diffuse source sky model. | |
| 1398 | - * | |
| 1399 | - * Returns the instrument response to a diffuse source sky model for all | |
| 1400 | - * events. | |
| 1401 | - ***************************************************************************/ | |
| 1402 | -GVector GResponse::irf_diffuse(const GModelSky& model, | |
| 1403 | - const GObservation& obs, | |
| 1404 | - GMatrix* gradients) const | |
| 1405 | -{ | |
| 1406 | - // Get number of events | |
| 1407 | - int nevents = obs.events()->size(); | |
| 1408 | - | |
| 1409 | - // Initialise result | |
| 1410 | - GVector irfs(nevents); | |
| 1411 | - | |
| 1412 | - // Loop over events | |
| 1413 | - for (int k = 0; k < nevents; ++k) { | |
| 1414 | - | |
| 1415 | - // Get reference to event | |
| 1416 | - const GEvent& event = *((*obs.events())[k]); | |
| 1417 | - | |
| 1418 | - // Get source energy and time (no dispersion) | |
| 1419 | - GEnergy srcEng = event.energy(); | |
| 1420 | - GTime srcTime = event.time(); | |
| 1421 | - | |
| 1422 | - // Setup source | |
| 1423 | - GSource source(model.name(), model.spatial(), srcEng, srcTime); | |
| 1424 | - | |
| 1425 | - // Get IRF value for event | |
| 1426 | - irfs[k] = this->irf_diffuse(event, source, obs); | |
| 1427 | - | |
| 1428 | - } // endfor: looped over events | |
| 1429 | - | |
| 1430 | - // Return IRF value | |
| 1431 | - return irfs; | |
| 1432 | -} | |
| 1433 | - | |
| 1434 | - | |
| 1435 | -/***********************************************************************//** | |
| 1436 | - * @brief Return instrument response to composite source sky model | |
| 1437 | - * | |
| 1438 | - * @param[in] model Sky model. | |
| 1439 | - * @param[in] obs Observation. | |
| 1440 | - * @param[in] gradients Gradients matrix. | |
| 1441 | - * @return Instrument response to composite source sky model. | |
| 1442 | - * | |
| 1443 | - * Returns the instrument response to a composite source sky model for all | |
| 1444 | - * events. | |
| 1445 | - ***************************************************************************/ | |
| 1446 | -GVector GResponse::irf_composite(const GModelSky& model, | |
| 1447 | - const GObservation& obs, | |
| 1448 | - GMatrix* gradients) const | |
| 1449 | -{ | |
| 1450 | - // Get number of events | |
| 1451 | - int nevents = obs.events()->size(); | |
| 1452 | - | |
| 1453 | - // Initialise result | |
| 1454 | - GVector irfs(nevents); | |
| 1455 | - | |
| 1456 | - // Get pointer to composite spatial model | |
| 1457 | - const GModelSpatialComposite* composite = | |
| 1458 | - dynamic_cast<const GModelSpatialComposite*>(model.spatial()); | |
| 1459 | - | |
| 1460 | - // Create copy of sky model | |
| 1461 | - GModelSky sky = model; | |
| 1462 | - | |
| 1463 | - // Loop over model components | |
| 1464 | - for (int i = 0; i < composite->components(); ++i) { | |
| 1465 | - | |
| 1466 | - // Set spatial component of sky model | |
| 1467 | - sky.spatial(const_cast<GModelSpatial*>(composite->component(i))); | |
| 1468 | - | |
| 1469 | - // Compute and add IRF values | |
| 1470 | - irfs += irf_spatial(sky, obs, gradients) * composite->scale(i); | |
| 1471 | - | |
| 1472 | - } // endfor: looped over all model components | |
| 1473 | - | |
| 1474 | - // Divide by number of model components | |
| 1475 | - double sum = composite->sum_of_scales(); | |
| 1476 | - if (sum > 0.0) { | |
| 1477 | - irfs /= sum; | |
| 1478 | - } | |
| 1479 | - | |
| 1480 | - // Return IRF values | |
| 1481 | - return irfs; | |
| 1482 | -} | |
| 1483 | - | |
| 1484 | - | |
| 1485 | -/***********************************************************************//** | |
| 1486 | 960 | * @brief Convolve sky model with the instrument response |
| 1487 | 961 | * |
| 1488 | 962 | * @param[in] model Sky model. |
| ... | ... | @@ -1623,346 +1097,41 @@ double GResponse::eval_prob(const GModelSky& model, |
| 1623 | 1097 | } |
| 1624 | 1098 | |
| 1625 | 1099 | |
| 1626 | -/***********************************************************************//** | |
| 1627 | - * @brief Convolve sky model with the instrument response | |
| 1628 | - * | |
| 1629 | - * @param[in] model Sky model. | |
| 1630 | - * @param[in] obs Observation. | |
| 1631 | - * @param[out] gradients Pointer to matrix of gradients. | |
| 1632 | - * @return Event probabilities. | |
| 1633 | - * | |
| 1634 | - * Computes the event probability | |
| 1635 | - * | |
| 1636 | - * \f[ | |
| 1637 | - * P(p',E',t'|E,t) = \int S(p,E,t) \times R(p',E',t'|p,E,t) \, dp | |
| 1638 | - * \f] | |
| 1639 | - * | |
| 1640 | - * for a all events. | |
| 1641 | - ***************************************************************************/ | |
| 1642 | -GVector GResponse::eval_probs(const GModelSky& model, | |
| 1643 | - const GObservation& obs, | |
| 1644 | - GMatrixSparse* gradients) const | |
| 1645 | -{ | |
| 1646 | - // Get number of model parameters and number of events | |
| 1647 | - int npars = model.size(); | |
| 1648 | - int nevents = obs.events()->size(); | |
| 1649 | - | |
| 1650 | - // Initialise gradients flag | |
| 1651 | - bool grad = (gradients != NULL); | |
| 1652 | - | |
| 1653 | - // Initialise result | |
| 1654 | - GVector probs(nevents); | |
| 1655 | 1100 | |
| 1656 | - // Continue only if the model has a spatial component | |
| 1657 | - if (model.spatial() != NULL) { | |
| 1658 | 1101 | |
| 1659 | - // Initialise matrix to hold spatial gradients | |
| 1660 | - GMatrix spat_gradients(nevents, model.spatial()->size()); | |
| 1661 | - | |
| 1662 | - // Compute IRF value | |
| 1663 | - probs = irf_spatial(model, obs, &spat_gradients); | |
| 1664 | - | |
| 1665 | - // Get global model scaling | |
| 1666 | - double scale = (model.has_scales()) | |
| 1667 | - ? model.scale(obs.instrument()).value() : 1.0; | |
| 1668 | - | |
| 1669 | - // Initialise temporary vectors to hold gradients | |
| 1670 | - GVector* tmp_gradients = NULL; | |
| 1671 | - if (grad) { | |
| 1672 | - tmp_gradients = new GVector[npars]; | |
| 1673 | - for (int i = 0; i < npars; ++i) { | |
| 1674 | - tmp_gradients[i] = GVector(nevents); | |
| 1675 | - } | |
| 1676 | - } | |
| 1677 | - | |
| 1678 | - // Loop over events | |
| 1679 | - for (int k = 0; k < nevents; ++k) { | |
| 1680 | - | |
| 1681 | - // Get probability | |
| 1682 | - double spat = probs[k]; | |
| 1683 | - | |
| 1684 | - // Continue only if spatial value is positive | |
| 1685 | - if (spat > 0.0) { | |
| 1686 | - | |
| 1687 | - // Get reference to event | |
| 1688 | - const GEvent& event = *((*obs.events())[k]); | |
| 1689 | - | |
| 1690 | - // Get source energy and time | |
| 1691 | - GEnergy srcEng = event.energy(); | |
| 1692 | - GTime srcTime = event.time(); | |
| 1693 | - | |
| 1694 | - // Evaluate spectral and temporal components | |
| 1695 | - double spec = (model.spectral() != NULL) | |
| 1696 | - ? model.spectral()->eval(srcEng, srcTime, grad) | |
| 1697 | - : 1.0; | |
| 1698 | - double temp = (model.temporal() != NULL) | |
| 1699 | - ? model.temporal()->eval(srcTime, grad) | |
| 1700 | - : 1.0; | |
| 1701 | - | |
| 1702 | - // Compute probability | |
| 1703 | - probs[k] = spat * spec * temp * scale; | |
| 1704 | - | |
| 1705 | - // Optionally compute partial derivatives | |
| 1706 | - if (grad) { | |
| 1707 | - | |
| 1708 | - // Get number of spatial, spectral and temporal parameters | |
| 1709 | - int n_spat = model.spatial()->size(); | |
| 1710 | - int n_spec = model.spectral()->size(); | |
| 1711 | - int n_temp = model.temporal()->size(); | |
| 1712 | - | |
| 1713 | - // Multiply factors to spatial gradients | |
| 1714 | - if (model.spatial() != NULL) { | |
| 1715 | - double fact = spec * temp * scale; | |
| 1716 | - for (int i = 0; i < n_spat; ++i) { | |
| 1717 | - tmp_gradients[i][k] = spat_gradients(k,i) * fact; | |
| 1718 | - } | |
| 1719 | - } | |
| 1720 | - | |
| 1721 | - // Multiply factors to spectral gradients | |
| 1722 | - if (model.spectral() != NULL) { | |
| 1723 | - int offset = n_spat; | |
| 1724 | - double fact = spat * temp * scale; | |
| 1725 | - for (int i = 0; i < n_spec; ++i) { | |
| 1726 | - tmp_gradients[offset+i][k] = | |
| 1727 | - (*(model.spectral()))[i].factor_gradient() * fact; | |
| 1728 | - } | |
| 1729 | - } | |
| 1730 | - | |
| 1731 | - // Multiply factors to temporal gradients | |
| 1732 | - if (model.temporal() != NULL) { | |
| 1733 | - int offset = n_spat + n_spec; | |
| 1734 | - double fact = spat * spec * scale; | |
| 1735 | - for (int i = 0; i < n_temp; ++i) { | |
| 1736 | - tmp_gradients[offset+i][k] = | |
| 1737 | - (*(model.temporal()))[i].factor_gradient() * fact; | |
| 1738 | - } | |
| 1739 | - } | |
| 1740 | - | |
| 1741 | - // Optionally set scale gradient for instrument | |
| 1742 | - if (model.has_scales()) { | |
| 1743 | - int offset = n_spat + n_spec + n_temp; | |
| 1744 | - double fact = spat * spec * temp; | |
| 1745 | - for (int i = 0; i < model.scales(); ++i) { | |
| 1746 | - const GModelPar& par = model.scale(i); | |
| 1747 | - double g_scale = 0.0; | |
| 1748 | - if (par.name() == obs.instrument()) { | |
| 1749 | - if (par.is_free()) { | |
| 1750 | - tmp_gradients[offset+i][k] = par.scale() * fact; | |
| 1751 | - } | |
| 1752 | - } | |
| 1753 | - } | |
| 1754 | - } | |
| 1755 | - | |
| 1756 | - } // endif: computed partial derivatives | |
| 1757 | - | |
| 1758 | - } // endif: IRF spatial value was positive | |
| 1759 | - | |
| 1760 | - // Compile option: Check for NaN/Inf | |
| 1761 | - #if defined(G_NAN_CHECK) | |
| 1762 | - if (gammalib::is_notanumber(probs[k]) || gammalib::is_infinite(probs[k])) { | |
| 1763 | - std::cout << "*** ERROR: GResponse::eval_prob:"; | |
| 1764 | - std::cout << " NaN/Inf encountered"; | |
| 1765 | - std::cout << " (probs[" << k << "]=" << probs[k]; | |
| 1766 | - std::cout << ", spat=" << spat; | |
| 1767 | - std::cout << ")" << std::endl; | |
| 1768 | - } | |
| 1769 | - #endif | |
| 1770 | - | |
| 1771 | - } // endfor: looped over events | |
| 1772 | - | |
| 1773 | - // Post-process gradients | |
| 1774 | - if (grad) { | |
| 1775 | - | |
| 1776 | - // Fill gradients into matrix | |
| 1777 | - for (int i = 0; i < npars; ++i) { | |
| 1778 | - gradients->column(i, tmp_gradients[i]); | |
| 1779 | - } | |
| 1780 | - | |
| 1781 | - // Delete temporal gradients | |
| 1782 | - delete [] tmp_gradients; | |
| 1783 | - | |
| 1784 | - } // endif: gradient post processing | |
| 1785 | - | |
| 1786 | - } // endif: Gamma-ray source model had a spatial component | |
| 1787 | - | |
| 1788 | - // Return event probabilities | |
| 1789 | - return probs; | |
| 1790 | -} | |
| 1791 | - | |
| 1792 | - | |
| 1793 | -/***********************************************************************//** | |
| 1794 | - * @brief Return size of vector for energy dispersion computation | |
| 1795 | - * | |
| 1796 | - * @param[in] model Sky model. | |
| 1797 | - * @param[in] obs Observation. | |
| 1798 | - * @param[out] grad Signals whether gradients should be computed. | |
| 1799 | - * @return Size of vector for energy dispersion computation. | |
| 1800 | - * | |
| 1801 | - * Computes the size of the vector that will be computed for the computation | |
| 1802 | - * of the energy dispersion. | |
| 1803 | - ***************************************************************************/ | |
| 1804 | -int GResponse::size_edisp_vector(const GModelSky& model, | |
| 1805 | - const GObservation& obs, | |
| 1806 | - const bool& grad) const | |
| 1807 | -{ | |
| 1808 | - // Initialise vector size | |
| 1809 | - int size = 1; | |
| 1810 | - | |
| 1811 | - // Determine size of gradient part | |
| 1812 | - if (grad) { | |
| 1813 | - if (model.spectral() != NULL) { | |
| 1814 | - for (int i = 0; i < model.spectral()->size(); ++i) { | |
| 1815 | - GModelPar& par = (*(model.spectral()))[i]; | |
| 1816 | - if (par.is_free() && par.has_grad()) { | |
| 1817 | - size++; | |
| 1818 | - } | |
| 1819 | - } | |
| 1820 | - } | |
| 1821 | - if (model.temporal() != NULL) { | |
| 1822 | - for (int i = 0; i < model.temporal()->size(); ++i) { | |
| 1823 | - GModelPar& par = (*(model.temporal()))[i]; | |
| 1824 | - if (par.is_free() && par.has_grad()) { | |
| 1825 | - size++; | |
| 1826 | - } | |
| 1827 | - } | |
| 1828 | - } | |
| 1829 | - if (model.has_scales()) { | |
| 1830 | - for (int i = 0; i < model.scales(); ++i) { | |
| 1831 | - GModelPar& par = const_cast<GModelPar&>(model.scale(i)); | |
| 1832 | - if (par.name() == obs.instrument()) { | |
| 1833 | - if (par.is_free() && par.has_grad()) { | |
| 1834 | - size++; | |
| 1835 | - } | |
| 1836 | - } | |
| 1837 | - } | |
| 1838 | - } | |
| 1839 | - } | |
| 1840 | - | |
| 1841 | - // Return size | |
| 1842 | - return size; | |
| 1843 | -} | |
| 1844 | 1102 | |
| 1845 | 1103 | |
| 1846 | 1104 | /***********************************************************************//** |
| 1847 | - * @brief Constructor for energy dispersion integration kernels class | |
| 1848 | - * | |
| 1849 | - * @param[in] parent Pointer to response. | |
| 1850 | - * @param[in] obs Pointer to observation. | |
| 1851 | - * @param[in] model Pointer to sky model. | |
| 1852 | - * @param[in] event Pointer to event. | |
| 1853 | - * @param[in] srcTime True time. | |
| 1854 | - * @param[in] grad Evaluate gradients? | |
| 1855 | - * | |
| 1856 | - * This method constructs the integration kernel needed for the energy | |
| 1857 | - * dispersion computation. | |
| 1858 | - ***************************************************************************/ | |
| 1859 | -GResponse::edisp_kerns::edisp_kerns(const GResponse* parent, | |
| 1860 | - const GObservation* obs, | |
| 1861 | - const GModelSky* model, | |
| 1862 | - const GEvent* event, | |
| 1863 | - const GTime& srcTime, | |
| 1864 | - const bool& grad) | |
| 1865 | -{ | |
| 1866 | - // Set members | |
| 1867 | - m_parent = parent; | |
| 1868 | - m_obs = obs; | |
| 1869 | - m_model = model; | |
| 1870 | - m_event = event; | |
| 1871 | - m_size = 1; | |
| 1872 | - m_srcTime = srcTime; | |
| 1873 | - m_grad = grad; | |
| 1874 | - | |
| 1875 | - // If gradients are requested then put pointers to all relevant parameter | |
| 1876 | - // in the parameter pointer vector | |
| 1877 | - m_pars.clear(); | |
| 1878 | - if (m_grad) { | |
| 1879 | - | |
| 1880 | - // Add free spectral parameters with analytical gradients | |
| 1881 | - if (m_model->spectral() != NULL) { | |
| 1882 | - for (int i = 0; i < m_model->spectral()->size(); ++i) { | |
| 1883 | - GModelPar& par = (*(m_model->spectral()))[i]; | |
| 1884 | - if (par.is_free() && par.has_grad()) { | |
| 1885 | - m_pars.push_back(&par); | |
| 1886 | - } | |
| 1887 | - } | |
| 1888 | - } | |
| 1889 | - | |
| 1890 | - // Add free temporal parameters with analytical gradients | |
| 1891 | - if (m_model->temporal() != NULL) { | |
| 1892 | - for (int i = 0; i < m_model->temporal()->size(); ++i) { | |
| 1893 | - GModelPar& par = (*(m_model->temporal()))[i]; | |
| 1894 | - if (par.is_free() && par.has_grad()) { | |
| 1895 | - m_pars.push_back(&par); | |
| 1896 | - } | |
| 1897 | - } | |
| 1898 | - } | |
| 1899 | - | |
| 1900 | - // Add free scaling factors | |
| 1901 | - if (m_model->has_scales()) { | |
| 1902 | - for (int i = 0; i < m_model->scales(); ++i) { | |
| 1903 | - GModelPar& par = const_cast<GModelPar&>(m_model->scale(i)); | |
| 1904 | - if (par.name() == m_obs->instrument()) { | |
| 1905 | - if (par.is_free() && par.has_grad()) { | |
| 1906 | - m_pars.push_back(&par); | |
| 1907 | - } | |
| 1908 | - } | |
| 1909 | - } | |
| 1910 | - } | |
| 1911 | - | |
| 1912 | - // Update size | |
| 1913 | - m_size += m_pars.size(); | |
| 1914 | - | |
| 1915 | - } // endif: gradients were requested | |
| 1916 | - | |
| 1917 | - // Return | |
| 1918 | - return; | |
| 1919 | -} | |
| 1920 | - | |
| 1921 | - | |
| 1922 | -/***********************************************************************//** | |
| 1923 | - * @brief Evaluate energy dispersion integration kernel | |
| 1105 | + * @brief Integration kernel for GResponse::edisp_kern() class | |
| 1924 | 1106 | * |
| 1925 | 1107 | * @param[in] etrue True photon energy in MeV. |
| 1926 | 1108 | * |
| 1927 | 1109 | * This method implements the integration kernel needed for the |
| 1928 | 1110 | * GResponse::edisp_kern() class. |
| 1929 | 1111 | ***************************************************************************/ |
| 1930 | -GVector GResponse::edisp_kerns::eval(const double& etrue) | |
| 1112 | +double GResponse::edisp_kern::eval(const double& etrue) | |
| 1931 | 1113 | { |
| 1932 | - // Initialise result | |
| 1933 | - GVector kernels(m_size); | |
| 1934 | - | |
| 1935 | - // Initialise Ndarray array index | |
| 1936 | - int index = 0; | |
| 1937 | - | |
| 1938 | 1114 | // Set true energy |
| 1939 | 1115 | GEnergy srcEng; |
| 1940 | 1116 | srcEng.MeV(etrue); |
| 1941 | 1117 | |
| 1942 | 1118 | // Get function value |
| 1943 | - kernels[index++] = m_parent->eval_prob(*m_model, *m_event, | |
| 1944 | - srcEng, m_srcTime, *m_obs, | |
| 1945 | - m_grad); | |
| 1946 | - | |
| 1947 | - // If gradients are requested then extract them and put them into the | |
| 1948 | - // array | |
| 1949 | - if (m_grad) { | |
| 1950 | - for (int i = 0; i < m_pars.size(); ++i, ++index) { | |
| 1951 | - kernels[index] = m_pars[i]->factor_gradient(); | |
| 1952 | - } | |
| 1953 | - } | |
| 1119 | + double value = m_parent->eval_prob(*m_model, *m_event, | |
| 1120 | + srcEng, m_srcTime, *m_obs, m_grad); | |
| 1954 | 1121 | |
| 1955 | 1122 | // Compile option: Check for NaN |
| 1956 | 1123 | #if defined(G_NAN_CHECK) |
| 1957 | - if (gammalib::is_notanumber(kernels[0]) || gammalib::is_infinite(kernels[0])) { | |
| 1124 | + if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) { | |
| 1958 | 1125 | std::cout << "*** ERROR: GResponse::edisp_kern::eval"; |
| 1959 | - std::cout << "(etrue=" << etrue << "): NaN/Inf encountered"; | |
| 1960 | - std::cout << " (value=" << kernels[0] << ")" << std::endl; | |
| 1126 | + std::cout << "(etrue=" << etrue << "): "; | |
| 1127 | + std::cout << " NaN/Inf encountered"; | |
| 1128 | + std::cout << " (value=" << value; | |
| 1129 | + std::cout << ")" << std::endl; | |
| 1961 | 1130 | } |
| 1962 | 1131 | #endif |
| 1963 | 1132 | |
| 1964 | - // Return kernels | |
| 1965 | - return kernels; | |
| 1133 | + // Return value | |
| 1134 | + return value; | |
| 1966 | 1135 | } |
| 1967 | 1136 | |
| 1968 | 1137 | |
| ... | ... | @@ -2141,3 +1310,6 @@ double GResponse::irf_elliptical_kern_phi::eval(const double& phi) |
| 2141 | 1310 | // Return |
| 2142 | 1311 | return irf; |
| 2143 | 1312 | } |
| 1313 | + | |
| 1314 | + | |
| 1315 | + | ... | ... |