GammaLib 2.0.0
Loading...
Searching...
No Matches
GModelSpatialRadialDisk.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GModelSpatialRadialDisk.cpp - Radial disk source model class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2011-2022 by Christoph Deil *
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 GModelSpatialRadialDisk.cpp
23 * @brief Radial disk model class implementation
24 * @author Christoph Deil
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GException.hpp"
32#include "GTools.hpp"
33#include "GMath.hpp"
36
37/* __ Constants __________________________________________________________ */
38
39/* __ Globals ____________________________________________________________ */
41const GModelSpatialRegistry g_radial_disk_registry(&g_radial_disk_seed);
42#if defined(G_LEGACY_XML_FORMAT)
43const GModelSpatialRadialDisk g_radial_disk_legacy_seed(true, "DiskFunction");
44const GModelSpatialRegistry g_radial_disk_legacy_registry(&g_radial_disk_legacy_seed);
45#endif
46
47/* __ Method name definitions ____________________________________________ */
48#define G_CONSTRUCTOR "GModelSpatialRadialDisk::GModelSpatialRadialDisk("\
49 "GSkyDir&, double&, std::string&)"
50#define G_READ "GModelSpatialRadialDisk::read(GXmlElement&)"
51#define G_WRITE "GModelSpatialRadialDisk::write(GXmlElement&)"
52
53/* __ Macros _____________________________________________________________ */
54
55/* __ Coding definitions _________________________________________________ */
56
57/* __ Debug definitions __________________________________________________ */
58
59
60/*==========================================================================
61 = =
62 = Constructors/destructors =
63 = =
64 ==========================================================================*/
65
66/***********************************************************************//**
67 * @brief Void constructor
68 *
69 * Constructs empty radial disk model.
70 ***************************************************************************/
72{
73 // Initialise members
75
76 // Return
77 return;
78}
79
80
81/***********************************************************************//**
82 * @brief Model type constructor
83 *
84 * @param[in] dummy Dummy flag.
85 * @param[in] type Model type.
86 *
87 * Constructs empty radial disk model by specifying a model @p type.
88 ***************************************************************************/
90 const std::string& type) :
92{
93 // Initialise members
95
96 // Set model type
97 m_type = type;
98
99 // Return
100 return;
101}
102
103
104/***********************************************************************//**
105 * @brief Disk constructor
106 *
107 * @param[in] dir Sky position of disk centre.
108 * @param[in] radius Disk radius (degrees).
109 * @param[in] coordsys Coordinate system (either "CEL" or "GAL")
110 *
111 * @exception GException::invalid_argument
112 * Invalid @p coordsys argument specified.
113 *
114 * Constructs radial disk model from the sky position of the disk centre
115 * (@p dir) and the disk @p radius in degrees. The @p coordsys parameter
116 * specifies whether the sky direction should be interpreted in the
117 * celestial or Galactic coordinate system.
118 ***************************************************************************/
120 const double& radius,
121 const std::string& coordsys) :
123{
124 // Throw an exception if the coordinate system is invalid
125 if ((coordsys != "CEL") && (coordsys != "GAL")) {
126 std::string msg = "Invalid coordinate system \""+coordsys+"\" "
127 "specified. Please specify either \"CEL\" or "
128 "\"GAL\".";
130 }
131
132 // Initialise members
133 init_members();
134
135 // Set parameter names
136 if (coordsys == "CEL") {
137 m_lon.name("RA");
138 m_lat.name("DEC");
139 }
140 else {
141 m_lon.name("GLON");
142 m_lat.name("GLAT");
143 }
144
145 // Assign parameters
146 this->dir(dir);
147 this->radius(radius);
148
149 // Return
150 return;
151}
152
153
154/***********************************************************************//**
155 * @brief XML constructor
156 *
157 * @param[in] xml XML element.
158 *
159 * Creates instance of radial disk model by extracting information from an
160 * XML element. See the read() method for more information about the expected
161 * structure of the XML element.
162 ***************************************************************************/
165{
166 // Initialise members
167 init_members();
168
169 // Read information from XML element
170 read(xml);
171
172 // Return
173 return;
174}
175
176
177/***********************************************************************//**
178 * @brief Copy constructor
179 *
180 * @param[in] model Radial disk model.
181 ***************************************************************************/
184{
185 // Initialise members
186 init_members();
187
188 // Copy members
189 copy_members(model);
190
191 // Return
192 return;
193}
194
195
196/***********************************************************************//**
197 * @brief Destructor
198 ***************************************************************************/
200{
201 // Free members
202 free_members();
203
204 // Return
205 return;
206}
207
208
209/*==========================================================================
210 = =
211 = Operators =
212 = =
213 ==========================================================================*/
214
215/***********************************************************************//**
216 * @brief Assignment operator
217 *
218 * @param[in] model Radial disk model.
219 * @return Radial disk model.
220 ***************************************************************************/
222{
223 // Execute only if object is not identical
224 if (this != &model) {
225
226 // Copy base class members
228
229 // Free members
230 free_members();
231
232 // Initialise members
233 init_members();
234
235 // Copy members
236 copy_members(model);
237
238 } // endif: object was not identical
239
240 // Return
241 return *this;
242}
243
244
245/*==========================================================================
246 = =
247 = Public methods =
248 = =
249 ==========================================================================*/
250
251/***********************************************************************//**
252 * @brief Clear radial disk model
253 ***************************************************************************/
255{
256 // Free class members (base and derived classes, derived class first)
257 free_members();
260
261 // Initialise members
264 init_members();
265
266 // Return
267 return;
268}
269
270
271/***********************************************************************//**
272 * @brief Clone radial disk model
273 *
274 * @return Pointer to deep copy of radial disk model.
275 ***************************************************************************/
277{
278 // Clone radial disk model
279 return new GModelSpatialRadialDisk(*this);
280}
281
282
283/***********************************************************************//**
284 * @brief Evaluate function (in units of sr^-1)
285 *
286 * @param[in] theta Angular distance from disk centre (radians).
287 * @param[in] energy Photon energy.
288 * @param[in] time Photon arrival time.
289 * @param[in] gradients Compute gradients?
290 * @return Model value.
291 *
292 * Evaluates the spatial component for a disk source model using
293 *
294 * \f[
295 * S_{\rm p}(\vec{p} | E, t) = \left \{
296 * \begin{array}{l l}
297 * \displaystyle
298 * {\tt m\_norm}
299 * & \mbox{if $\theta \le $ radius} \\
300 * \\
301 * \displaystyle
302 * 0 & \mbox{if $\theta > $ radius}
303 * \end{array}
304 * \right .
305 * \f]
306 *
307 * where
308 * - \f$\theta\f$ is the angular separation between disk centre and the
309 * sky direction of interest, and
310 * - \f${\tt m\_norm} = \frac{1}{2 \pi (1 - \cos r)} \f$ is a normalization
311 * constant (see the update() method for details).
312 *
313 * The method will not compute analytical parameter gradients, even if the
314 * @p gradients argument is set to true. Radial disk parameter gradients
315 * need to be computed numerically.
316 ***************************************************************************/
317double GModelSpatialRadialDisk::eval(const double& theta,
318 const GEnergy& energy,
319 const GTime& time,
320 const bool& gradients) const
321{
322 // Update precomputation cache
323 update();
324
325 // Set value
326 double value = (theta <= m_radius_rad) ? m_norm : 0.0;
327
328 // Compile option: Check for NaN/Inf
329 #if defined(G_NAN_CHECK)
330 if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
331 std::cout << "*** ERROR: GModelSpatialRadialDisk::eval";
332 std::cout << "(theta=" << theta << "): NaN/Inf encountered";
333 std::cout << " (value=" << value;
334 std::cout << ", m_radius_rad=" << m_radius_rad;
335 std::cout << ", m_norm=" << m_norm;
336 std::cout << ")" << std::endl;
337 }
338 #endif
339
340 // Return value
341 return value;
342}
343
344
345/***********************************************************************//**
346 * @brief Return MC sky direction
347 *
348 * @param[in] energy Photon energy.
349 * @param[in] time Photon arrival time.
350 * @param[in,out] ran Random number generator.
351 * @return Sky direction.
352 *
353 * Draws an arbitrary sky direction from the 2D disk distribution as function
354 * of the photon @p energy and arrival @p time.
355 ***************************************************************************/
357 const GTime& time,
358 GRan& ran) const
359{
360 // Simulate offset from photon arrival direction
361 double cosrad = std::cos(radius() * gammalib::deg2rad);
362 double theta = std::acos(1.0 - ran.uniform() * (1.0 - cosrad)) *
364 double phi = 360.0 * ran.uniform();
365
366 // Rotate sky direction by offset
367 GSkyDir sky_dir = dir();
368 sky_dir.rotate_deg(phi, theta);
369
370 // Return sky direction
371 return sky_dir;
372}
373
374
375/***********************************************************************//**
376 * @brief Checks where model contains specified sky direction
377 *
378 * @param[in] dir Sky direction.
379 * @param[in] margin Margin to be added to sky direction (degrees)
380 * @return True if the model contains the sky direction.
381 *
382 * Signals whether a sky direction is contained in the radial disk model.
383 ***************************************************************************/
385 const double& margin) const
386{
387 // Compute distance to centre (radians)
388 double distance = dir.dist(this->dir());
389
390 // Return flag
391 return (distance <= theta_max() + margin*gammalib::deg2rad);
392}
393
394
395/***********************************************************************//**
396 * @brief Return maximum model radius (in radians)
397 *
398 * @return Maximum model radius (in radians).
399 ***************************************************************************/
401{
402 // Return value
403 return (radius() * gammalib::deg2rad);
404}
405
406
407/***********************************************************************//**
408 * @brief Read model from XML element
409 *
410 * @param[in] xml XML element.
411 *
412 * Reads the radial disk model information from an XML element. The XML
413 * element shall have either the format
414 *
415 * <spatialModel type="RadialDisk">
416 * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
417 * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
418 * <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/>
419 * </spatialModel>
420 *
421 * or
422 *
423 * <spatialModel type="RadialDisk">
424 * <parameter name="GLON" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
425 * <parameter name="GLAT" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
426 * <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/>
427 * </spatialModel>
428 *
429 * @todo Implement a test of the radius and radius boundary. The radius
430 * and radius minimum should be >0.
431 ***************************************************************************/
433{
434 // Verify that XML element has exactly 3 parameters
436
437 // Read disk location
439
440 // Get parameters
442
443 // Read parameters
445
446 // Return
447 return;
448}
449
450
451/***********************************************************************//**
452 * @brief Write model into XML element
453 *
454 * @param[in] xml XML element into which model information is written.
455 *
456 * @exception GException::model_invalid_parnum
457 * Invalid number of model parameters found in XML element.
458 * @exception GException::model_invalid_parnames
459 * Invalid model parameter names found in XML element.
460 *
461 * Writes the radial disk model information into an XML element. The XML
462 * element will have the format
463 *
464 * <spatialModel type="RadialDisk">
465 * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
466 * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
467 * <parameter name="Radius" scale="1.0" value="0.45" min="0.01" max="10" free="1"/>
468 * </spatialModel>
469 *
470 ***************************************************************************/
472{
473 // Verify model type
475
476 // Write disk location
478
479 // Get or create parameters
481
482 // Write parameters
484
485 // Return
486 return;
487}
488
489
490/***********************************************************************//**
491 * @brief Print information
492 *
493 * @param[in] chatter Chattiness.
494 * @return String containing model information.
495 ***************************************************************************/
496std::string GModelSpatialRadialDisk::print(const GChatter& chatter) const
497{
498 // Initialise result string
499 std::string result;
500
501 // Continue only if chatter is not silent
502 if (chatter != SILENT) {
503
504 // Append header
505 result.append("=== GModelSpatialRadialDisk ===");
506
507 // Append parameters
508 result.append("\n"+gammalib::parformat("Number of parameters"));
509 result.append(gammalib::str(size()));
510 for (int i = 0; i < size(); ++i) {
511 result.append("\n"+m_pars[i]->print(chatter));
512 }
513
514 } // endif: chatter was not silent
515
516 // Return result
517 return result;
518}
519
520
521/*==========================================================================
522 = =
523 = Private methods =
524 = =
525 ==========================================================================*/
526
527/***********************************************************************//**
528 * @brief Initialise class members
529 ***************************************************************************/
531{
532 // Initialise model type
533 m_type = "RadialDisk";
534
535 // Initialise Radius
536 m_radius.clear();
537 m_radius.name("Radius");
538 m_radius.unit("deg");
539 m_radius.value(2.778e-4); // 1 arcsec
540 m_radius.min(2.778e-4); // 1 arcsec
541 m_radius.free();
542 m_radius.scale(1.0);
543 m_radius.gradient(0.0);
544 m_radius.has_grad(false); // Radial components never have gradients
545
546 // Set parameter pointer(s)
547 m_pars.push_back(&m_radius);
548
549 // Initialise precomputation cache. Note that zero values flag
550 // uninitialised as a zero radius is not meaningful
551 m_last_radius = 0.0;
552 m_radius_rad = 0.0;
553 m_norm = 0.0;
554
555 // Return
556 return;
557}
558
559
560/***********************************************************************//**
561 * @brief Copy class members
562 *
563 * @param[in] model Radial disk model.
564 *
565 * We do not have to push back the members on the parameter stack as this
566 * should have been done by init_members() that was called before. Otherwise
567 * we would have the radius twice on the stack.
568 ***************************************************************************/
570{
571 // Copy members
572 m_type = model.m_type; // Needed to conserve model type
573 m_radius = model.m_radius;
574
575 // Copy precomputation cache
578 m_norm = model.m_norm;
579
580 // Return
581 return;
582}
583
584
585/***********************************************************************//**
586 * @brief Delete class members
587 ***************************************************************************/
589{
590 // Return
591 return;
592}
593
594
595/***********************************************************************//**
596 * @brief Update precomputation cache
597 *
598 * Computes the normalization
599 * \f[
600 * {\tt m\_norm} = \frac{1}{2 \pi (1 - \cos r)}
601 * \f]
602 *
603 * Note that this is the correct normalization on the sphere for any
604 * disk radius r. For small r it is very similar to the cartesian
605 * approximation you might have expected:
606 * \f[{\tt m\_norm} = \frac{1}{\pi r ^ 2}\f]
607 ***************************************************************************/
609{
610 // Update if radius has changed
611 if (m_last_radius != radius()) {
612
613 // Store last values
615
616 // Compute disk radius in radians
618
619 // Perform precomputations
620 double denom = gammalib::twopi * (1 - std::cos(m_radius_rad));
621 m_norm = (denom > 0.0) ? 1.0 / denom : 0.0;
622
623 } // endif: update required
624
625 // Return
626 return;
627}
628
629
630/***********************************************************************//**
631 * @brief Set boundary sky region
632 ***************************************************************************/
634{
635 // Set sky region circle
637
638 // Set region (circumvent const correctness)
639 const_cast<GModelSpatialRadialDisk*>(this)->m_region = region;
640
641 // Return
642 return;
643}
#define G_WRITE
#define G_READ
Exception handler interface definition.
Mathematical function definitions.
#define G_CONSTRUCTOR
Definition GMatrix.cpp:41
const GModelSpatialRadialDisk g_radial_disk_seed
Radial disk model class interface definition.
Spatial model registry class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
void write(GXmlElement &xml) const
Set or update parameter attributes in XML element.
void read(const GXmlElement &xml)
Extract parameter attributes from XML element.
double radius(void) const
Return disk radius.
void copy_members(const GModelSpatialRadialDisk &model)
Copy class members.
virtual ~GModelSpatialRadialDisk(void)
Destructor.
GModelPar m_radius
Disk radius (degrees)
void update(void) const
Update precomputation cache.
virtual void write(GXmlElement &xml) const
Write model into XML element.
virtual GSkyDir mc(const GEnergy &energy, const GTime &time, GRan &ran) const
Return MC sky direction.
void free_members(void)
Delete class members.
virtual void clear(void)
Clear radial disk model.
virtual double eval(const double &theta, const GEnergy &energy, const GTime &time, const bool &gradients=false) const
Evaluate function (in units of sr^-1)
virtual std::string print(const GChatter &chatter=NORMAL) const
Print information.
double m_last_radius
Last disk radius.
virtual GModelSpatialRadialDisk & operator=(const GModelSpatialRadialDisk &model)
Assignment operator.
virtual void set_region(void) const
Set boundary sky region.
virtual bool contains(const GSkyDir &dir, const double &margin=0.0) const
Checks where model contains specified sky direction.
double m_radius_rad
Radius in radians.
virtual GModelSpatialRadialDisk * clone(void) const
Clone radial disk model.
virtual double theta_max(void) const
Return maximum model radius (in radians)
virtual void read(const GXmlElement &xml)
Read model from XML element.
GModelSpatialRadialDisk(void)
Void constructor.
void init_members(void)
Initialise class members.
Abstract radial spatial model base class.
void free_members(void)
Delete class members.
GModelPar m_lon
Right Ascension or Galactic longitude (deg)
virtual void write(GXmlElement &xml) const
Write model into XML element.
virtual void read(const GXmlElement &xml)
Read model from XML element.
std::string coordsys(void) const
Return coordinate system.
void init_members(void)
Initialise class members.
virtual GModelSpatialRadial & operator=(const GModelSpatialRadial &model)
Assignment operator.
const GSkyDir & dir(void) const
Return position of radial spatial model.
GModelPar m_lat
Declination or Galactic latitude (deg)
Interface definition for the spatial model registry class.
std::string m_type
Spatial model type.
std::string type(void) const
Return model type.
const GSkyRegion * region(void) const
Return boundary sky region.
std::vector< GModelPar * > m_pars
Parameter pointers.
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.
void free(void)
Free a parameter.
const double & scale(void) const
Return parameter scale.
bool has_grad(void) const
Signal if parameter gradient is computed analytically.
const std::string & unit(void) const
Return parameter unit.
double min(void) const
Return parameter minimum boundary.
double gradient(void) const
Return parameter gradient.
void clear(void)
Clear parameter.
double value(void) const
Return parameter value.
const std::string & name(void) const
Return parameter name.
Random number generator class.
Definition GRan.hpp:44
double uniform(void)
Returns random double precision floating value in range 0 to 1.
Definition GRan.cpp:242
Sky direction class.
Definition GSkyDir.hpp:62
void rotate_deg(const double &phi, const double &theta)
Rotate sky direction by zenith and azimuth angle.
Definition GSkyDir.cpp:424
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.
Time class.
Definition GTime.hpp:55
XML element node class.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition GTools.hpp:184
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition GTools.hpp:201
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
const GXmlElement * xml_get_par(const std::string &origin, const GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition GTools.cpp:1689
GXmlElement * xml_need_par(const std::string &origin, GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition GTools.cpp:1637
const double deg2rad
Definition GMath.hpp:43
void xml_check_parnum(const std::string &origin, const GXmlElement &xml, const int &number)
Checks number of parameters.
Definition GTools.cpp:1777
const double twopi
Definition GMath.hpp:36
const double rad2deg
Definition GMath.hpp:44
void xml_check_type(const std::string &origin, GXmlElement &xml, const std::string &type)
Checks the model type.
Definition GTools.cpp:1819