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 __________________________________________________________ */
41 const 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
62  init_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
77  init_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
93  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  ***************************************************************************/
144 GModelPar& 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  ***************************************************************************/
177 const 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  ***************************************************************************/
216 GModelPar& 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  ***************************************************************************/
239 const 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  ***************************************************************************/
260 bool 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  ***************************************************************************/
344 double 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
397  GModelSpatial::circle_int_kern_rho integrand(this,
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,
507  m_cosmodrad);
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 }
double m_modrad
Model radius (rad)
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
double romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
Definition: GIntegral.cpp:381
Point source spatial model class interface definition.
double m_dist
Distance model-region (rad)
int size(void) const
Return number of parameters.
GModelSpatial(void)
Void constructor.
bool has_free_pars(void) const
Checks if the spatial model has free parameters.
virtual ~GModelSpatial(void)
Destructor.
GVector cos(const GVector &vector)
Computes cosine of vector elements.
Definition: GVector.cpp:1190
double eval(const double &omega)
Kernel for circular sky region azimuth angle integration.
virtual GModelSpatial & operator=(const GModelSpatial &model)
Assignment operator.
Abstract spatial model base class interface definition.
virtual GModelPar & operator[](const int &index)
Returns model parameter.
Time class.
Definition: GTime.hpp:55
GIntegral class interface definition.
Definition: GIntegral.hpp:46
Interface for the circular sky region class.
GSkyRegionCircle m_region
Bounding circle.
void copy_members(const GModelSpatial &model)
Copy class members.
const double & radius(void) const
Return circular region radius (in degrees)
double m_sindist
Sin of distance model-region.
Class that handles photons.
Definition: GPhoton.hpp:47
Model parameter class.
Definition: GModelPar.hpp:87
const double deg2rad
Definition: GMath.hpp:43
Abstract interface for the sky region class.
Definition: GSkyRegion.hpp:57
double eval(const double &rho)
Kernel for circular sky region radial integration.
const GModelSpatial * m_model
Spatial model.
std::vector< GModelPar * > m_pars
Parameter pointers.
#define G_AT
void rotate(const double &phi, const double &theta)
Rotate sky direction by zenith and azimuth angle.
Definition: GSkyDir.cpp:378
#define G_FLUX
double m_cosmodrad
Cos of model radius.
const GSkyRegionCircle * m_reg
Integration region.
virtual bool overlaps(const GSkyRegion &reg) const =0
const double g_kludge_radius
Tiny angle (radians)
#define G_ACCESS
void silent(const bool &silent)
Set silence flag.
Definition: GIntegral.hpp:245
const GSkyRegion * region(void) const
Return boundary sky region.
const GSkyDir & centre(void) const
Return circular region centre.
void free_members(void)
Delete class members.
std::string m_type
Spatial model type.
GModelPar & at(const int &index)
Returns model parameter.
bool has_par(const std::string &name) const
Checks if parameter name exists.
virtual double flux(const GSkyRegion &region, const GEnergy &srcEng=GEnergy(), const GTime &srcTime=GTime()) const
Returns model flux integrated in circular sky region.
GVector sin(const GVector &vector)
Computes sine of vector elements.
Definition: GVector.cpp:1316
Exception handler interface definition.
double dist(const GSkyDir &dir) const
Compute angular distance between sky directions in radians.
Definition: GSkyDir.hpp:271
Abstract spatial model base class.
void init_members(void)
Initialise class members.
Sky direction class.
Definition: GSkyDir.hpp:62
void autoscale(void)
Autoscale parameters.
double m_cosdist
Cos of distance model-region.
void clear(void)
Clear instance.
Class that handles energies in a unit independent way.
Definition: GEnergy.hpp:48