Loading [MathJax]/extensions/tex2jax.js
GammaLib 2.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GModelSpatial.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GModelSpatial.cpp - Abstract spatial model base class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2009-2021 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- *
6 * *
7 * This program is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GModelSpatial.cpp
23 * @brief Abstract spatial model base class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GException.hpp"
32#include "GModelSpatial.hpp"
34
35/* __ Method name definitions ____________________________________________ */
36#define G_ACCESS "GModelSpatial::operator[](std::string&)"
37#define G_AT "GModelPar& GModelSpatial::at(int&)"
38#define G_FLUX "GModelSpatial::flux(GSkyRegionCircle&, GEnergy&, GTime&)"
39
40/* __ Constants __________________________________________________________ */
41const double g_kludge_radius = 1.0e-12; //!< Tiny angle (radians)
42
43/* __ Macros _____________________________________________________________ */
44
45/* __ Coding definitions _________________________________________________ */
46
47/* __ Debug definitions __________________________________________________ */
48
49
50/*==========================================================================
51 = =
52 = Constructors/destructors =
53 = =
54 ==========================================================================*/
55
56/***********************************************************************//**
57 * @brief Void constructor
58 ***************************************************************************/
60{
61 // Initialise members
63
64 // Return
65 return;
66}
67
68
69/***********************************************************************//**
70 * @brief Copy constructor
71 *
72 * @param[in] model Spatial model.
73 ***************************************************************************/
75{
76 // Initialise members
78
79 // Copy members
80 copy_members(model);
81
82 // Return
83 return;
84}
85
86
87/***********************************************************************//**
88 * @brief Destructor
89 ***************************************************************************/
91{
92 // Free members
94
95 // Return
96 return;
97}
98
99
100/*==========================================================================
101 = =
102 = Operators =
103 = =
104 ==========================================================================*/
105
106/***********************************************************************//**
107 * @brief Assignment operator
108 *
109 * @param[in] model Spatial model.
110 * @return Spatial model.
111 ***************************************************************************/
113{
114 // Execute only if object is not identical
115 if (this != &model) {
116
117 // Free members
118 free_members();
119
120 // Initialise members
121 init_members();
122
123 // Copy members
124 copy_members(model);
125
126 } // endif: object was not identical
127
128 // Return
129 return *this;
130}
131
132
133/***********************************************************************//**
134 * @brief Returns model parameter
135 *
136 * @param[in] name Parameter name.
137 * @return Model parameter reference.
138 *
139 * @exception GException::invalid_argument
140 * Parameter with specified name not found.
141 *
142 * Returns reference to the model parameter of specified @p name.
143 ***************************************************************************/
144GModelPar& GModelSpatial::operator[](const std::string& name)
145{
146 // Get parameter index
147 int index = 0;
148 for (; index < size(); ++index) {
149 if (m_pars[index]->name() == name) {
150 break;
151 }
152 }
153
154 // Throw exception if parameter name was not found
155 if (index >= size()) {
156 std::string msg = "Model parameter \""+name+"\" not found in model. "
157 "Please specify a valid model parameter name.";
159 }
160
161 // Return reference
162 return *(m_pars[index]);
163}
164
165
166/***********************************************************************//**
167 * @brief Returns model parameter (const version)
168 *
169 * @param[in] name Parameter name.
170 * @return Model parameter reference.
171 *
172 * @exception GException::invalid_argument
173 * Parameter with specified name not found.
174 *
175 * Returns reference to the model parameter of specified @p name.
176 ***************************************************************************/
177const GModelPar& GModelSpatial::operator[](const std::string& name) const
178{
179 // Get parameter index
180 int index = 0;
181 for (; index < size(); ++index) {
182 if (m_pars[index]->name() == name) {
183 break;
184 }
185 }
186
187 // Throw exception if parameter name was not found
188 if (index >= size()) {
189 std::string msg = "Model parameter \""+name+"\" not found in model. "
190 "Please specify a valid model parameter name.";
192 }
193
194 // Return reference
195 return *(m_pars[index]);
196}
197
198
199/*==========================================================================
200 = =
201 = Public methods =
202 = =
203 ==========================================================================*/
204
205/***********************************************************************//**
206 * @brief Returns model parameter
207 *
208 * @param[in] index Parameter index [0,...,size()[.
209 * @return Model parameter.
210 *
211 * @exception GException::out_of_range
212 * Parameter index is out of range.
213 *
214 * Returns model parameter with @p index range checking.
215 ***************************************************************************/
216GModelPar& GModelSpatial::at(const int& index)
217{
218 // Compile option: raise exception if index is out of range
219 if (index < 0 || index >= size()) {
220 throw GException::out_of_range(G_AT, "Parameter index", index, size());
221 }
222
223 // Return reference
224 return *(m_pars[index]);
225}
226
227
228/***********************************************************************//**
229 * @brief Returns model parameter (const version)
230 *
231 * @param[in] index Parameter index [0,...,size()[.
232 * @return Model parameter.
233 *
234 * @exception GException::out_of_range
235 * Parameter index is out of range.
236 *
237 * Returns model parameter with @p index range checking.
238 ***************************************************************************/
239const GModelPar& GModelSpatial::at(const int& index) const
240{
241 // Compile option: raise exception if index is out of range
242 if (index < 0 || index >= size()) {
243 throw GException::out_of_range(G_AT, "Parameter index", index, size());
244 }
245
246 // Return reference
247 return *(m_pars[index]);
248}
249
250
251/***********************************************************************//**
252 * @brief Checks if parameter name exists
253 *
254 * @param[in] name Parameter name.
255 * @return True if parameter with specified @p name exists.
256 *
257 * Searches all parameter names for a match with the specified @p name. If
258 * the specified name has been found, true is returned.
259 ***************************************************************************/
260bool GModelSpatial::has_par(const std::string& name) const
261{
262 // Default found flag to false
263 bool found = false;
264
265 // Search for parameter name
266 for (int i = 0; i < size(); ++i) {
267 if (m_pars[i]->name() == name) {
268 found = true;
269 break;
270 }
271 }
272
273 // Return
274 return found;
275}
276
277
278/***********************************************************************//**
279 * @brief Checks if the spatial model has free parameters
280 *
281 * @return True if spatial model has free parameters.
282 ***************************************************************************/
284{
285 // Initialise result flag
286 bool has_free_pars = false;
287
288 // Search for free parameters
289 for (int i = 0; i < size(); ++i) {
290 if (m_pars[i]->is_free()) {
291 has_free_pars = true;
292 break;
293 }
294 }
295
296 // Return result
297 return has_free_pars;
298}
299
300
301/***********************************************************************//**
302 * @brief Autoscale parameters
303 *
304 * Sets the scale factors for all parameters so that the values are unity.
305 ***************************************************************************/
307{
308 // Loop over all parameters
309 for (int i = 0; i < m_pars.size(); ++i) {
310 if (m_pars[i] != NULL) {
311 m_pars[i]->autoscale();
312 }
313 }
314
315 // Return
316 return;
317}
318
319
320/***********************************************************************//**
321 * @brief Returns model flux integrated in circular sky region
322 *
323 * @param[in] region Sky region.
324 * @param[in] srcEng Energy.
325 * @param[in] srcTime Time.
326 * @return Flux (adimensional or ph/cm2/s).
327 *
328 * @exception GException::feature_not_implemented
329 * Regions are not circular.
330 *
331 * Computes
332 *
333 * \f[
334 * \int_{\rho_{\rm min}}^{\rho_{\rm max}} \sin \rho \times
335 * \int_{\omega} M(\rho, \omega | E, t) d\omega d\rho
336 * \f]
337 *
338 * where
339 * \f$M(\rho, \omega | E, t)\f$ is the spatial model,
340 * \f$\rho\f$ is the distance from the region centre, and
341 * \f$\omega\f$ is the position angle with respect to the connecting line
342 * between the region centre and the direction on the sky.
343 ***************************************************************************/
344double GModelSpatial::flux(const GSkyRegion& region,
345 const GEnergy& srcEng,
346 const GTime& srcTime) const
347{
348 // Initialise flux
349 double flux = 0.0;
350
351 // Continue only if region overlaps with model
352 const GSkyRegion* model_reg = this->region();
353 if (model_reg->overlaps(region)) {
354
355 // Throw an exception if region is not a sky circle
356 const GSkyRegionCircle* reg_circle = dynamic_cast<const GSkyRegionCircle*>(&region);
357 if (reg_circle == NULL) {
358 std::string msg = "Flux can only be computed for a circular "
359 "region.";
361 }
362
363 // Throw an exception if model region is not a sky circle
364 const GSkyRegionCircle* model_circle = dynamic_cast<const GSkyRegionCircle*>(model_reg);
365 if (model_circle == NULL) {
366 std::string msg = "Flux can only be computed for spatial model "
367 "with region defined as circle.";
369 }
370
371 // Model centre and radius in radians
372 GSkyDir model_centre = model_circle->centre();
373 double model_radius = model_circle->radius() * gammalib::deg2rad;
374
375 // Distance between region and model centres in radians
376 double distance = model_centre.dist(reg_circle->centre());
377
378 // Take the distance between centers minus radius of model region as
379 // the minimum radial integration boundary (in radians)
380 double rho_min = distance - model_radius;
381
382 // Make sure that rho_min does not become negative
383 if (rho_min < 0.0) {
384 rho_min = 0.0;
385 }
386
387 // Take the region radius as the maximum radial integration boundary
388 // (in radians)
389 double rho_max = reg_circle->radius() * gammalib::deg2rad;
390
391 // Pre-compute some quantities for arclength
392 double cosdist = std::cos(distance);
393 double sindist = std::sin(distance);
394 double cosmodrad = std::cos(model_radius);
395
396 // Setup integration kernel
398 reg_circle,
399 srcEng,
400 srcTime,
401 distance,
402 cosdist,
403 sindist,
404 model_radius,
405 cosmodrad);
406 GIntegral integral(&integrand);
407
408 // Suppress integration warnings
409 integral.silent(true);
410
411 // Perform integration
412 flux = integral.romberg(rho_min, rho_max);
413
414 } // endif: model overlaps with region
415
416 // Return
417 return flux;
418}
419
420
421/*==========================================================================
422 = =
423 = Private methods =
424 = =
425 ==========================================================================*/
426
427/***********************************************************************//**
428 * @brief Initialise class members
429 ***************************************************************************/
431{
432 // Initialise members
433 m_type.clear();
434 m_region.clear();
435 m_pars.clear();
436
437 // Return
438 return;
439}
440
441
442/***********************************************************************//**
443 * @brief Copy class members
444 *
445 * @param[in] model Spatial model.
446 ***************************************************************************/
448{
449 // Copy members
450 m_type = model.m_type;
451 m_region = model.m_region;
452 m_pars = model.m_pars;
453
454 // Return
455 return;
456}
457
458
459/***********************************************************************//**
460 * @brief Delete class members
461 ***************************************************************************/
463{
464 // Return
465 return;
466}
467
468
469/***********************************************************************//**
470 * @brief Kernel for circular sky region radial integration
471 *
472 * @param[in] rho Radial distance from region centre (radians).
473 * @return Integration kernel defined as
474 *
475 * \f[
476 * \int_{\rho_{\rm min}}^{\rho_{\rm max}} K(\rho | E, t) d\rho
477 * \f]
478 *
479 * of a spatial model over a circular region. The eval() method computes
480 *
481 * \f[
482 * K(\rho | E, t) = \sin \rho \times
483 * \int_{\omega} M(\rho, \omega | E, t) d\omega
484 * \f]
485 *
486 * where
487 * \f$M(\rho, \omega | E, t)\f$ is the spatial model,
488 * \f$\rho\f$ is the distance from the region centre, and
489 * \f$\omega\f$ is the position angle with respect to the connecting line
490 * between the region centre and the direction on the sky.
491 ***************************************************************************/
493{
494 // Initialise model value
495 double flux = 0.0;
496
497 // Continue only if rho is positive
498 if (rho > 0.0) {
499
500 // Compute half length of the arc (in radians) from a circle with
501 // radius rho that intersects with model circle
502 double domega = 0.5 * gammalib::roi_arclength(rho,
503 m_dist,
504 m_cosdist,
505 m_sindist,
506 m_modrad,
508
509 // Continue only if arc length is positive
510 if (domega > 0.0) {
511
512 // Reduce rho by an infinite amount to avoid rounding errors
513 // at the boundary of a sharp edged model
514 double rho_kludge = rho - g_kludge_radius;
515 if (rho_kludge < 0.0) {
516 rho_kludge = 0.0;
517 }
518
519 // Compute omega integration range
520 double omega_min = -domega;
521 double omega_max = +domega;
522
523 // Setup integration kernel for azimuth integration
525 m_reg,
526 rho_kludge,
527 m_srcEng,
528 m_srcTime);
529
530 // Setup integrator
531 GIntegral integral(&integrand);
532
533 // Compute sine term for radial integration
534 double sin_rho = std::sin(rho);
535
536 // Integrate over omega
537 flux = integral.romberg(omega_min, omega_max) * sin_rho;
538
539 } //endif: domega was positive
540
541 } // endif: rho was positive
542
543 // Return
544 return flux;
545}
546
547
548/***********************************************************************//**
549 * @brief Kernel for circular sky region azimuth angle integration
550 *
551 * @param[in] omega Azimuth angle (radians).
552 * @return Integration kernel defined as
553 *
554 * \f[
555 * K(\omega | \rho, E, t) = M(\omega | \rho)
556 * \f]
557 *
558 * where
559 * \f$M(\omega | \rho)\f$ is the spatial model,
560 * \f$\rho\f$ is the distance from the region centre, and
561 * \f$\omega\f$ is the position angle with respect to the connecting line
562 * between the region centre and the direction on the sky.
563 ***************************************************************************/
565{
566 // Compute sky direction corresponding to given rho, omega
567 GSkyDir dir = GSkyDir(m_reg->centre());
568
569 // Rotate to obtain requested sky direction
570 dir.rotate(omega, m_rho);
571
572 // Set photon for this sky direction
573 GPhoton photon = GPhoton(dir, m_srcEng, m_srcTime);
574
575 // Evaluate model for this sky direction
576 double flux = m_model->eval(photon);
577
578 // Return
579 return flux;
580}
#define G_AT
#define G_ACCESS
Exception handler interface definition.
Point source spatial model class interface definition.
#define G_FLUX
const double g_kludge_radius
Tiny angle (radians)
Abstract spatial model base class interface definition.
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
GIntegral class interface definition.
Definition GIntegral.hpp:46
double romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
void silent(const bool &silent)
Set silence flag.
Model parameter class.
Definition GModelPar.hpp:87
double eval(const double &omega)
Kernel for circular sky region azimuth angle integration.
double m_sindist
Sin of distance model-region.
const GModelSpatial * m_model
Spatial model.
double m_cosmodrad
Cos of model radius.
const GSkyRegionCircle * m_reg
Integration region.
double m_cosdist
Cos of distance model-region.
double m_dist
Distance model-region (rad)
double eval(const double &rho)
Kernel for circular sky region radial integration.
double m_modrad
Model radius (rad)
Abstract spatial model base class.
void autoscale(void)
Autoscale parameters.
std::string m_type
Spatial model type.
bool has_free_pars(void) const
Checks if the spatial model has free parameters.
const GSkyRegion * region(void) const
Return boundary sky region.
virtual ~GModelSpatial(void)
Destructor.
virtual double flux(const GSkyRegion &region, const GEnergy &srcEng=GEnergy(), const GTime &srcTime=GTime()) const
Returns model flux integrated in circular sky region.
GModelPar & at(const int &index)
Returns model parameter.
bool has_par(const std::string &name) const
Checks if parameter name exists.
GModelSpatial(void)
Void constructor.
std::vector< GModelPar * > m_pars
Parameter pointers.
void copy_members(const GModelSpatial &model)
Copy class members.
virtual GModelSpatial & operator=(const GModelSpatial &model)
Assignment operator.
void init_members(void)
Initialise class members.
int size(void) const
Return number of parameters.
void free_members(void)
Delete class members.
GSkyRegionCircle m_region
Bounding circle.
virtual GModelPar & operator[](const int &index)
Returns model parameter.
Class that handles photons.
Definition GPhoton.hpp:47
Sky direction class.
Definition GSkyDir.hpp:62
void rotate(const double &phi, const double &theta)
Rotate sky direction by zenith and azimuth angle.
Definition GSkyDir.cpp:378
double dist(const GSkyDir &dir) const
Compute angular distance between sky directions in radians.
Definition GSkyDir.hpp:271
Interface for the circular sky region class.
void clear(void)
Clear instance.
const double & radius(void) const
Return circular region radius (in degrees)
const GSkyDir & centre(void) const
Return circular region centre.
Abstract interface for the sky region class.
virtual bool overlaps(const GSkyRegion &reg) const =0
Time class.
Definition GTime.hpp:55
double roi_arclength(const double &rad, const double &dist, const double &cosdist, const double &sindist, const double &roi, const double &cosroi)
Returns length of circular arc within circular ROI.
Definition GTools.cpp:2107
const double deg2rad
Definition GMath.hpp:43