GammaLib 2.1.0.dev
Loading...
Searching...
No Matches
GModelSky.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GModelSky.cpp - Sky model class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2011-2025 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 GModelSky.cpp
23 * @brief Sky model class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GTools.hpp"
32#include "GException.hpp"
33#include "GIntegral.hpp"
34#include "GEnergies.hpp"
35#include "GModelRegistry.hpp"
36#include "GModelSky.hpp"
46#include "GSource.hpp"
47#include "GResponse.hpp"
48
49/* __ Globals ____________________________________________________________ */
50const GModelSky g_pointsource_seed("PointSource");
51const GModelSky g_extendedsource_seed("ExtendedSource");
52const GModelSky g_diffusesource_seed("DiffuseSource");
53const GModelSky g_compositesource_seed("CompositeSource");
54const GModelRegistry g_pointsource_registry(&g_pointsource_seed);
55const GModelRegistry g_extendedsource_registry(&g_extendedsource_seed);
56const GModelRegistry g_diffusesource_registry(&g_diffusesource_seed);
57const GModelRegistry g_compositesource_registry(&g_compositesource_seed);
58
59/* __ Method name definitions ____________________________________________ */
60#define G_NPRED "GModelSky::npred(GEnergy&, GTime&, GObservation&)"
61#define G_XML_SPATIAL "GModelSky::xml_spatial(GXmlElement&)"
62#define G_XML_SPECTRAL "GModelSky::xml_spectral(GXmlElement&)"
63#define G_XML_TEMPORAL "GModelSky::xml_temporal(GXmlElement&)"
64#define G_INTEGRATE_TIME "GModelSky::integrate_time(GEvent&, GObservation&,"\
65 " bool)"
66#define G_INTEGRATE_ENERGY "GModelSky::integrate_energy(GEvent&, GTime&," \
67 " GObservation&, bool)"
68#define G_INTEGRATE_DIR "GModelSky::integrate_dir(GEvent&, GEnergy&, GTime&,"\
69 " GObservation, bool)"
70
71/* __ Macros _____________________________________________________________ */
72
73/* __ Coding definitions _________________________________________________ */
74
75/* __ Debug definitions __________________________________________________ */
76//#define G_DUMP_MC //!< Dump MC information
77//#define G_DUMP_MC_DETAIL //!< Dump detailed MC information
78
79
80/*==========================================================================
81 = =
82 = Constructors/destructors =
83 = =
84 ==========================================================================*/
85
86/***********************************************************************//**
87 * @brief Void constructor
88 *
89 * Construct an empty sky model. An empty sky model has no type.
90 ***************************************************************************/
92{
93 // Initialise members
95
96 // Return
97 return;
98}
99
100
101/***********************************************************************//**
102 * @brief Type constructor
103 *
104 * @param[in] type Model type.
105 *
106 * Construct an empty sky model of the specified @p type. This constructor
107 * does basically the same than the void constructor with the only difference
108 * that the m_type member of the class is set to the specified @p type
109 * string.
110 ***************************************************************************/
111GModelSky::GModelSky(const std::string& type) : GModel()
112{
113 // Initialise members
114 init_members();
115
116 // Set model type
117 m_type = type;
118
119 // Return
120 return;
121}
122
123
124/***********************************************************************//**
125 * @brief XML constructor
126 *
127 * @param[in] xml XML element.
128 *
129 * Constructs a sky model from the model information that is found in the
130 * @p xml element. Only the spatial and spectral information is handled by
131 * this constructor. For the temporal component, a constant model of type
132 * GModelTemporalConst will be allocated.
133 ***************************************************************************/
135{
136 // Initialise members
137 init_members();
138
139 // Get pointers on spectrum and spatial model
140 const GXmlElement* spec = xml.element("spectrum", 0);
141 const GXmlElement* spat = xml.element("spatialModel", 0);
142
143 // Allocate constant
145
146 // Clone spatial and spectral models
147 m_spatial = xml_spatial(*spat);
148 m_spectral = xml_spectral(*spec);
150
151 // Set parameter pointers
152 set_pointers();
153
154 // Set model type dependent on spatial model type
155 set_type();
156
157 // Return
158 return;
159}
160
161
162/***********************************************************************//**
163 * @brief Construct sky model from spatial and spectral XML elements
164 *
165 * @param[in] spatial Spatial XML element.
166 * @param[in] spectral Spectral XML element.
167 *
168 * Constructs a sky model from the @p spatial and @p spectral information
169 * that is found in the respective XML elements. For the temporal component,
170 * a constant model of type GModelTemporalConst will be allocated.
171 ***************************************************************************/
172GModelSky::GModelSky(const GXmlElement& spatial, const GXmlElement& spectral) :
173 GModel()
174{
175 // Initialise private members for clean destruction
176 init_members();
177
178 // Allocate constant
180
181 // Clone spatial and spectral models
185
186 // Set parameter pointers
187 set_pointers();
188
189 // Set model type dependent on spatial model type
190 set_type();
191
192 // Return
193 return;
194}
195
196
197/***********************************************************************//**
198 * @brief Construct sky model from spatial, spectral and temporal XML elements
199 *
200 * @param[in] spatial Spatial XML element.
201 * @param[in] spectral Spectral XML element.
202 * @param[in] temporal Temporal XML element.
203 *
204 * Constructs a sky model from the @p spatial, @p spectral and @p temporal
205 * information that is found in the respective XML elements.
206 ***************************************************************************/
208 const GXmlElement& spectral,
209 const GXmlElement& temporal) :
210 GModel()
211{
212 // Initialise private members for clean destruction
213 init_members();
214
215 // Clone spatial and spectral models
219
220 // Set parameter pointers
221 set_pointers();
222
223 // Set model type dependent on spatial model type
224 set_type();
225
226 // Return
227 return;
228}
229
230
231/***********************************************************************//**
232 * @brief Construct sky model from spatial and spectral components
233 *
234 * @param[in] spatial Spatial model component.
235 * @param[in] spectral Spectral model component.
236 *
237 * Constructs a sky model from @p spatial and @p spectral model components.
238 * For the temporal component, a constant model of type GModelTemporalConst
239 * will be allocated.
240 ***************************************************************************/
242 const GModelSpectral& spectral) :
243 GModel()
244{
245 // Initialise members
246 init_members();
247
248 // Allocate temporal constant model
250
251 // Clone model components
255
256 // Set parameter pointers
257 set_pointers();
258
259 // Set model type dependent on spatial model type
260 set_type();
261
262 // Return
263 return;
264}
265
266
267/***********************************************************************//**
268 * @brief Construct sky model from spatial, spectral and temporal components
269 *
270 * @param[in] spatial Spatial model component.
271 * @param[in] spectral Spectral model component.
272 * @param[in] temporal Temporal model component.
273 *
274 * Constructs a sky model from @p spatial, @p spectral and @p temporal model
275 * components.
276 ***************************************************************************/
278 const GModelSpectral& spectral,
279 const GModelTemporal& temporal) :
280 GModel()
281{
282 // Initialise members
283 init_members();
284
285 // Clone model components
289
290 // Set parameter pointers
291 set_pointers();
292
293 // Set model type dependent on spatial model type
294 set_type();
295
296 // Return
297 return;
298}
299
300
301/***********************************************************************//**
302 * @brief Copy constructor
303 *
304 * @param[in] model Sky model.
305 ***************************************************************************/
307{
308 // Initialise private members for clean destruction
309 init_members();
310
311 // Copy members
312 copy_members(model);
313
314 // Return
315 return;
316}
317
318
319/***********************************************************************//**
320 * @brief Destructor
321 ***************************************************************************/
323{
324 // Free members
325 free_members();
326
327 // Return
328 return;
329}
330
331
332/*==========================================================================
333 = =
334 = Operators =
335 = =
336 ==========================================================================*/
337
338/***********************************************************************//**
339 * @brief Assignment operator
340 *
341 * @param[in] model Sky model.
342 * @return Sky model.
343 ***************************************************************************/
345{
346 // Execute only if object is not identical
347 if (this != &model) {
348
349 // Copy base class members
350 this->GModel::operator=(model);
351
352 // Free members
353 free_members();
354
355 // Initialise private members for clean destruction
356 init_members();
357
358 // Copy members
359 copy_members(model);
360
361 } // endif: object was not identical
362
363 // Return
364 return *this;
365}
366
367
368/*==========================================================================
369 = =
370 = Public methods =
371 = =
372 ==========================================================================*/
373
374/***********************************************************************//**
375 * @brief Clear sky model
376 *
377 * This method properly resets the sky model to an initial state.
378 ***************************************************************************/
380{
381 // Free class members
382 free_members();
383 this->GModel::free_members();
384
385 // Initialise members
386 this->GModel::init_members();
387 init_members();
388
389 // Return
390 return;
391}
392
393
394/***********************************************************************//**
395 * @brief Clone sky model
396 *
397 * @return Pointer to deep copy of sky model.
398 ***************************************************************************/
400{
401 // Clone sky model
402 return new GModelSky(*this);
403}
404
405
406/***********************************************************************//**
407 * @brief Set spatial model component
408 *
409 * @param[in] spatial Pointer to spatial model component.
410 *
411 * Sets the spatial model component of the model.
412 ***************************************************************************/
414{
415 // Free spatial model component only if it differs from current
416 // component. This prevents unintential deallocation of the argument
417 if ((m_spatial != NULL) && (m_spatial != spatial)) {
418 delete m_spatial;
419 }
420
421 // Clone spatial model component if it exists, otherwise set pointer
422 // to NULL
423 m_spatial = (spatial != NULL) ? spatial->clone() : NULL;
424
425 // Set parameter pointers
426 set_pointers();
427
428 // Set model type dependent on spatial model type
429 set_type();
430
431 // Return
432 return;
433}
434
435
436/***********************************************************************//**
437 * @brief Set spectral model component
438 *
439 * @param[in] spectral Pointer to spectral model component.
440 *
441 * Sets the spectral model component of the model.
442 ***************************************************************************/
444{
445 // Free spectral model component only if it differs from current
446 // component. This prevents unintential deallocation of the argument
447 if ((m_spectral != NULL) && (m_spectral != spectral)) {
448 delete m_spectral;
449 }
450
451 // Clone spectral model component if it exists, otherwise set pointer
452 // to NULL
453 m_spectral = (spectral != NULL) ? spectral->clone() : NULL;
454
455 // Set parameter pointers
456 set_pointers();
457
458 // Return
459 return;
460}
461
462
463/***********************************************************************//**
464 * @brief Set temporal model component
465 *
466 * @param[in] temporal Pointer to temporal model component.
467 *
468 * Sets the temporal model component of the model.
469 ***************************************************************************/
471{
472 // Free temporal model component only if it differs from current
473 // component. This prevents unintential deallocation of the argument
474 if ((m_temporal != NULL) && (m_temporal != temporal)) {
475 delete m_temporal;
476 }
477
478 // Clone temporal model component if it exists, otherwise set pointer
479 // to NULL
480 m_temporal = (temporal != NULL) ? temporal->clone() : NULL;
481
482 // Set parameter pointers
483 set_pointers();
484
485 // Return
486 return;
487}
488
489
490/***********************************************************************//**
491 * @brief Return value of sky model for a given photon
492 *
493 * @param[in] photon Photon.
494 * @return Value of sky model.
495 *
496 * Returns the value of the sky model for a given @p photon. If no model
497 * components exist the model will return a value of 1.
498 *
499 * @todo We probably should return a value of 0 is no model components exist.
500 * But we may also make sure that the model never has NULL pointers, which
501 * would avoid all the pointer checks.
502 ***************************************************************************/
503double GModelSky::value(const GPhoton& photon)
504{
505 // Initialise source model
506 double source = 1.0;
507
508 // Evaluate source model
509 if (m_spatial != NULL) source *= m_spatial->eval(photon);
510 if (m_spectral != NULL) source *= m_spectral->eval(photon.energy(),
511 photon.time());
512 if (m_temporal != NULL) source *= m_temporal->eval(photon.time());
513
514 // Return
515 return source;
516}
517
518
519/***********************************************************************//**
520 * @brief Return parameter gradients of sky model for a given photon
521 *
522 * @param[in] photon Photon.
523 * @return Vector of parameter gradients
524 *
525 * Returns a vector of parameter gradients for the sky model for a given
526 * @p photon. If there are no parameters in the sky model, an empty vector
527 * will be returned.
528 ***************************************************************************/
530{
531 // Evaluate source model gradients
532 if (m_spatial != NULL) m_spatial->eval(photon, true);
533 if (m_spectral != NULL) m_spectral->eval(photon.energy(), photon.time(),
534 true);
535 if (m_temporal != NULL) m_temporal->eval(photon.time(), true);
536
537 // Set vector of gradients
539 if (size() > 0) {
541 for (int i = 0; i < size(); ++i) {
542 gradients[i] = m_pars[i]->factor_gradient();
543 }
544 }
545
546 // Return gradients
547 return gradients;
548}
549
550
551/***********************************************************************//**
552 * @brief Evaluate sky model for a given event of an observation
553 *
554 * @param[in] event Observed event.
555 * @param[in] obs Observation.
556 * @param[in] gradients Compute gradients?
557 * @return Value of sky model.
558 *
559 * Evalutes the value of the sky model for an @p event of a specific
560 * observation @p obs.
561 *
562 * If the @p gradients flag is true the method will also compute the
563 * parameter gradients for all model parameters.
564 ***************************************************************************/
565double GModelSky::eval(const GEvent& event,
566 const GObservation& obs,
567 const bool& gradients) const
568{
569 // Evaluate model
570 double value = obs.response()->convolve(*this, event, obs, gradients);
571
572 // If gradients were requested then signal all computed analytical
573 // gradients
574 if (gradients) {
576 }
577
578 // Return
579 return value;
580}
581
582
583/***********************************************************************//**
584 * @brief Evaluate sky model for all events of an observation
585 *
586 * @param[in] obs Observation.
587 * @param[out] gradients Pointer to sparse matrix holding model gradients.
588 * @param[in] offset Column index of first matrix gradient (not used).
589 * @return Values of sky model.
590 *
591 * Evalutes the value of the sky model for an @p event of a specific
592 * observation @p obs.
593 *
594 * If the @p gradients flag is true the method will also compute the
595 * parameter gradients for all model parameters.
596 ***************************************************************************/
598 GMatrixSparse* gradients,
599 const int& offset) const
600{
601 // Evaluate model
602 GVector values = obs.response()->convolve(*this, obs, gradients);
603
604 // If gradients were requested then signal all computed analytical
605 // gradients
606 if (gradients) {
608 }
609
610 // Return
611 return values;
612}
613
614
615/***********************************************************************//**
616 * @brief Return spatially integrated sky model
617 *
618 * @param[in] obsEng Measured photon energy.
619 * @param[in] obsTime Measured photon arrival time.
620 * @param[in] obs Observation.
621 * @return Spatially integrated sky model.
622 *
623 * Computes
624 *
625 * \f[
626 * N_{\rm pred}(E',t') = \int_{\rm ROI}
627 * P(p',E',t') \, dp' \, dE'
628 * \f]
629 *
630 * of the event probability
631 *
632 * \f[
633 * P(p',E',t') = \int \int \int
634 * S(p,E,t) \times R(p',E',t'|p,E,t) \, dp \, dE \, dt
635 * \f]
636 *
637 * where
638 * \f$S(p,E,t)\f$ is the source model,
639 * \f$R(p',E',t'|p,E,t)\f$ is the instrument response function,
640 * \f$p'\f$ is the measured photon direction,
641 * \f$E'\f$ is the measured photon energy,
642 * \f$t'\f$ is the measured photon 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 photon arrival time.
646 *
647 * The method calls the GResponse::nroi() method that does the relevant
648 * integration.
649 ***************************************************************************/
650double GModelSky::npred(const GEnergy& obsEng,
651 const GTime& obsTime,
652 const GObservation& obs) const
653{
654 // Initialise result
655 double npred = 0.0;
656
657 // Continue only if model is valid)
658 if (valid_model()) {
659
660 // Compute Nroi
661 npred = obs.response()->nroi(*this, obsEng, obsTime, obs);
662
663 // Compile option: Check for NaN/Inf
664 #if defined(G_NAN_CHECK)
666 std::cout << "*** ERROR: GModelSky::npred:";
667 std::cout << " NaN/Inf encountered";
668 std::cout << " (npred=" << npred;
669 std::cout << ", obsEng=" << obsEng;
670 std::cout << ", obsTime=" << obsTime;
671 std::cout << ")" << std::endl;
672 }
673 #endif
674
675 } // endif: model was valid
676
677 // Return npred
678 return npred;
679}
680
681
682/***********************************************************************//**
683 * @brief Read sky model from XML element
684 *
685 * @param[in] xml XML element.
686 *
687 * Reads the sky model from an XML element. The XML element is expected to
688 * respect the following format:
689 *
690 * <source name=".." type=".." instrument=".." id=".." ts="..">
691 * <spectrum type="..">
692 * ..
693 * </spectrum>
694 * <spatialModel type="..">
695 * ..
696 * </spatialModel>
697 * <temporal type="..">
698 * ..
699 * </temporal>
700 * </source>
701 *
702 * The temporal element is optional. In no temporal element is specified a
703 * constant component with unity normalization will be assumed.
704 *
705 * Optionally, the model may also contain scale parameters following the
706 * format:
707 *
708 * <source name=".." type=".." instrument=".." id=".." ts="..">
709 * <spectrum type="..">
710 * ..
711 * </spectrum>
712 * <spatialModel type="..">
713 * ..
714 * </spatialModel>
715 * <temporal type="..">
716 * ..
717 * </temporal>
718 * <scaling>
719 * <instrument name=".." scale="1.0" min="0.1" max="10.0" value="1.0" free="0"/>
720 * <instrument name=".." scale="1.0" min="0.1" max="10.0" value="0.5" free="0"/>
721 * </scaling>
722 * </source>
723 *
724 * (see GModel::read_scales() for more information on instrument scales).
725 ***************************************************************************/
727{
728 // Clear sky model
729 clear();
730
731 // Get pointers on spectrum and spatial model
732 const GXmlElement* spec = xml.element("spectrum", 0);
733 const GXmlElement* spat = xml.element("spatialModel", 0);
734
735 // Set spatial and spectral models
736 m_spatial = xml_spatial(*spat);
737 m_spectral = xml_spectral(*spec);
738
739 // Handle optional temporal model
740 if (xml.elements("temporal") > 0) {
741 const GXmlElement* temp = xml.element("temporal", 0);
742 m_temporal = xml_temporal(*temp);
743 }
744 else {
747 }
748
749 // Read model attributes
750 read_attributes(xml);
751
752 // Set parameter pointers
753 set_pointers();
754
755 // Set model type dependent on spatial model type
756 set_type();
757
758 // Return
759 return;
760}
761
762
763/***********************************************************************//**
764 * @brief Write model into XML element
765 *
766 * @param[in] xml Source library.
767 *
768 * Writes the sky model into an XML source library. The format written to
769 * the @p xml element is as follows:
770 *
771 * <source name=".." type=".." instrument=".." id=".." ts="..">
772 * <spectrum type="..">
773 * ..
774 * </spectrum>
775 * <spatialModel type="..">
776 * ..
777 * </spatialModel>
778 * <temporal type="..">
779 * ..
780 * </temporal>
781 * <scaling>
782 * <instrument name=".." scale="1.0" min="0.1" max="10.0" value="1.0" free="0"/>
783 * <instrument name=".." scale="1.0" min="0.1" max="10.0" value="0.5" free="0"/>
784 * </scaling>
785 * </source>
786 *
787 * For compatibility reasons the temporal element will only be written if it
788 * is a non-constant component or a constant component with a normalization
789 * that differs from unity.
790 *
791 * The scaling element will only be written optionally in case that instrument
792 * dependent scaling factors exist (see GModel::write_scales() for more
793 * information on instrument scales).
794 ***************************************************************************/
796{
797 // Initialise pointer on source
798 GXmlElement* src = NULL;
799
800 // Search corresponding source
801 int n = xml.elements("source");
802 for (int k = 0; k < n; ++k) {
803 GXmlElement* element = static_cast<GXmlElement*>(xml.element("source", k));
804 if (element->attribute("name") == name()) {
805 src = element;
806 break;
807 }
808 }
809
810 // If the temporal model is not a constant with unit normalization then
811 // set cons to a NULL pointer
812 GModelTemporalConst* cons = dynamic_cast<GModelTemporalConst*>(temporal());
813 if (cons != NULL) {
814 if (cons->norm() != 1.0) {
815 cons = NULL;
816 }
817 }
818
819 // If no source with corresponding name was found then append one
820 if (src == NULL) {
821 src = xml.append("source");
822 if (spectral() != NULL) src->append(GXmlElement("spectrum"));
823 if (spatial() != NULL) src->append(GXmlElement("spatialModel"));
824 if (temporal() != NULL && cons == NULL) src->append(GXmlElement("temporal"));
825 }
826
827 // Write spectral model
828 if (spectral() != NULL) {
829 GXmlElement* spec = src->element("spectrum", 0);
830 spectral()->write(*spec);
831 }
832
833 // Write spatial model
834 if (spatial() != NULL) {
835 GXmlElement* spat = src->element("spatialModel", 0);
836 spatial()->write(*spat);
837 }
838
839 // Write temporal model (only if not a constant with unit normalization
840 // factor)
841 if (temporal() != NULL && cons == NULL) {
842 GXmlElement* temp = src->element("temporal", 0);
843 temporal()->write(*temp);
844 }
845
846 // Write model attributes
847 write_attributes(*src);
848
849 // Return
850 return;
851}
852
853
854/***********************************************************************//**
855 * @brief Return simulated list of photons
856 *
857 * @param[in] area Simulation surface area (cm2).
858 * @param[in] dir Centre of simulation cone.
859 * @param[in] radius Radius of simulation cone (deg).
860 * @param[in] emin Minimum photon energy.
861 * @param[in] emax Maximum photon energy.
862 * @param[in] tmin Minimum photon arrival time.
863 * @param[in] tmax Maximum photon arrival time.
864 * @param[in,out] ran Random number generator.
865 * @return List of photons
866 *
867 * Returns a list of photons that has been derived by Monte Carlo simulation
868 * from the model. A simulation region is define by specification of
869 * - a simulation cone, which is a circular region on the sky defined by
870 * a centre direction @p dir and a @p radius,
871 * - an energy range [@p emin, @p emax], and
872 * - a time interval [@p tmin, @p tmax].
873 *
874 * Only photons with parameters in the simulation region will be returned
875 * by the method.
876 *
877 * The simulation cone may eventually cover the entire sky (by setting
878 * the radius to 180 degrees), yet simulations will be more efficient if
879 * only the sky region will be simulated that is actually observed by the
880 * telescope.
881 *
882 * @todo Implement unique model ID to assign as Monte Carlo ID
883 ***************************************************************************/
884GPhotons GModelSky::mc(const double& area,
885 const GSkyDir& dir, const double& radius,
886 const GEnergy& emin, const GEnergy& emax,
887 const GTime& tmin, const GTime& tmax,
888 GRan& ran) const
889{
890 // Allocate photons
891 GPhotons photons;
892
893 // Continue only if model is valid)
894 if (valid_model()) {
895
896 // Determine the spatial model normalization within the simulation
897 // cone and check whether the model will produce any photons in that
898 // cone.
899 double norm = m_spatial->mc_norm(dir, radius);
900 bool use_model = (norm > 0.0) ? true : false;
901
902 // Continue only if model overlaps with simulation region
903 if (use_model) {
904
905 // Initialise de-allocation flag
906 bool free_spectral = false;
907
908 // Set pointer to spectral model
910
911 // If the spectral model is a diffuse cube then create a node
912 // function spectral model that is the product of the diffuse
913 // cube node function and the spectral model evaluated at the
914 // energies of the node function
916 dynamic_cast<GModelSpatialDiffuseCube*>(m_spatial);
917 if (cube != NULL) {
918
919 // Set MC cone
920 cube->mc_cone(GSkyRegionCircle(dir, radius));
921
922 // Allocate node function to replace the spectral component
923 GModelSpectralNodes* nodes =
924 new GModelSpectralNodes(cube->spectrum());
925 for (int i = 0; i < nodes->nodes(); ++i) {
926 GEnergy energy = nodes->energy(i);
927 double intensity = nodes->intensity(i);
928 double value = m_spectral->eval(energy, tmin);
929 nodes->intensity(i, value*intensity);
930 }
931
932 // Signal that node function needs to be de-allocated later
933 free_spectral = true;
934
935 // Set the spectral model pointer to the node function
936 spectral = nodes;
937
938 // Kluge: if there are no nodes then the spectral->flux method
939 // will throw an exception. We therefore set here the use_model
940 // flag to false in case that there are no spectral nodes
941 if (nodes->nodes() == 0) {
942 use_model = false;
943 }
944
945 } // endif: spatial model was a diffuse cube
946
947 // Compute flux within [emin, emax] in model from spectral
948 // component (units: ph/cm2/s)
949 double flux = (use_model) ? spectral->flux(emin, emax) : 0.0;
950
951 // Derive expecting counting rate within simulation surface
952 // (units: ph/s)
953 double rate = flux * area * norm;
954
955 // Debug option: dump rate
956 #if defined(G_DUMP_MC)
957 std::cout << "GModelSky::mc(\"" << name() << "\": ";
958 std::cout << "flux=" << flux << " ph/cm2/s, ";
959 std::cout << "rate=" << rate << " ph/s, ";
960 std::cout << "norm=" << norm << ")" << std::endl;
961 #endif
962
963 // Continue only if rate is positive
964 if (rate > 0.0) {
965
966 // Get photon arrival times from temporal model
967 GTimes times = m_temporal->mc(rate, tmin, tmax, ran);
968
969 // Debug option: dump number of times
970 #if defined(G_DUMP_MC_DETAIL)
971 std::cout << " Times=" << times.size() << std::endl;
972 #endif
973
974 // Reserve space for photons
975 if (times.size() > 0) {
976 photons.reserve(times.size());
977 }
978
979 // Loop over photons
980 for (int i = 0; i < times.size(); ++i) {
981
982 // Debug option: dump photon index
983 #if defined(G_DUMP_MC_DETAIL)
984 std::cout << " Photon=" << i << std::endl;
985 #endif
986
987 // Allocate photon
988 GPhoton photon;
989
990 // Set photon arrival time
991 photon.time(times[i]);
992
993 // Debug option: dump time
994 #if defined(G_DUMP_MC_DETAIL)
995 std::cout << " Time=" << times[i] << std::endl;
996 #endif
997
998 // Set photon energy. If an invalid_return_value exception
999 // occurs the energy returned by the spectral Monte Carlo
1000 // method is invalid and the photon is skipped.
1001 try {
1002 photon.energy(spectral->mc(emin, emax, photon.time(),
1003 ran));
1004 }
1006 continue;
1007 }
1008
1009 // Debug option: dump energy
1010 #if defined(G_DUMP_MC_DETAIL)
1011 std::cout << " Energy=" << photon.energy() << std::endl;
1012 #endif
1013
1014 // Set incident photon direction. If an invalid_return_value
1015 // exception occurs the sky direction returned by the
1016 // spatial Monte Carlo method is invalid and the photon is
1017 // skipped.
1018 try {
1019 photon.dir(m_spatial->mc(photon.energy(), photon.time(),
1020 ran));
1021 }
1023 continue;
1024 }
1025
1026 // Debug option: dump direction
1027 #if defined(G_DUMP_MC_DETAIL)
1028 std::cout << " Direction=" << photon.dir() << std::endl;
1029 #endif
1030
1031 // Append photon
1032 if (dir.dist_deg(photon.dir()) <= radius) {
1033 photons.append(photon);
1034 }
1035
1036 } // endfor: looped over photons
1037
1038 } // endif: rate was positive
1039
1040 // Free spectral model if required
1041 if (free_spectral) delete spectral;
1042
1043 } // endif: model was used
1044
1045 } // endif: model was valid
1046
1047 // Return photon list
1048 return photons;
1049}
1050
1051
1052/***********************************************************************//**
1053 * @brief Return sky model photon flux
1054 *
1055 * @param[in] emin Minimum energy.
1056 * @param[in] emax Maximum energy.
1057 * @return Sky model photon flux (cm\f$^{-2}\f$ s\f$^{-1}\f$)
1058 *
1059 * Returns the spatially integrate photon flux in the sky model.
1060 *
1061 * @todo Take spatial photon flux normalisation into account
1062 ***************************************************************************/
1063double GModelSky::flux(const GEnergy& emin, const GEnergy& emax) const
1064{
1065 // Initialise flux
1066 double flux = 0.0;
1067
1068 // Get pointer on diffuse cube spatial model component
1069 const GModelSpatialDiffuseCube* cube =
1070 dynamic_cast<const GModelSpatialDiffuseCube*>(spatial());
1071
1072 // If spatial model is a diffuse cube then compute the flux by
1073 // multiplying the spectrum of the spatial and spectral components
1074 // using a node function
1075 if (cube != NULL) {
1076
1077 // Get spectral nodes
1078 GModelSpectralNodes nodes = cube->spectrum();
1079
1080 // Multiply spectral nodes with spectral model
1081 for (int i = 0; i < nodes.nodes(); ++i) {
1082
1083 // Get energy and intensity
1084 GEnergy energy = nodes.energy(i);
1085 double intensity = nodes.intensity(i);
1086
1087 // Multiply intensity with spectral model
1088 intensity *= spectral()->eval(energy);
1089
1090 // Store intensity
1091 nodes.intensity(i, intensity);
1092
1093 } // endfor: multiplied spectral nodes with spectral model
1094
1095 // Compute flux
1096 flux = nodes.flux(emin, emax);
1097
1098 } // endif: spatial model was a diffuse cube
1099
1100 // ... otherwise assume that the spatial model is unity and compute
1101 // flux from the spectral component
1102 else {
1103 flux = spectral()->flux(emin, emax);
1104 }
1105
1106 // Return flux
1107 return flux;
1108}
1109
1110
1111/***********************************************************************//**
1112 * @brief Return sky model photon flux within sky region
1113 *
1114 * @param[in] region Sky region.
1115 * @param[in] emin Minimum energy.
1116 * @param[in] emax Maximum energy.
1117 * @return Sky model photon flux (cm\f$^{-2}\f$ s\f$^{-1}\f$)
1118 *
1119 * Returns the photon flux of the sky model within a given sky region.
1120 ***************************************************************************/
1121double GModelSky::flux(const GSkyRegion& region,
1122 const GEnergy& emin,
1123 const GEnergy& emax) const
1124{
1125 // Initialise flux
1126 double flux = 0.0;
1127
1128 // Signal for which models the spatial component depends on energy
1129 bool dependence = (spatial()->classname() == "GModelSpatialDiffuseCube") ||
1130 (spatial()->classname() == "GModelSpatialComposite");
1131
1132 // If the spatial component depends on energy then use
1133 if (dependence) {
1134
1135 // Get boundaries in MeV
1136 double mev_min = emin.MeV();
1137 double mev_max = emax.MeV();
1138
1139 // Continue only if valid
1140 if (mev_max > mev_min) {
1141
1142 // Setup integration function
1143 GModelSky::flux_kern integrand(this, &region);
1144 GIntegral integral(&integrand);
1145
1146 // Do Romberg integration
1147 flux = integral.romberg(std::log(mev_min), std::log(mev_max));
1148
1149 } // endif: energy interval was valid
1150
1151 } // endif: spatial model was a diffuse cube
1152
1153 // ... otherwise the spatial model does not depend on energy, hence
1154 // the flux is computed as the product between the spatial and
1155 // spectral flux. Note that this correctly takes the spatial
1156 // normalisation into account since the flux() method does this.
1157 else {
1158 flux = spatial()->flux(region) * spectral()->flux(emin, emax);
1159 }
1160
1161 // Return flux
1162 return flux;
1163}
1164
1165
1166/***********************************************************************//**
1167 * @brief Return sky model energy flux
1168 *
1169 * @param[in] emin Minimum energy.
1170 * @param[in] emax Maximum energy.
1171 * @return Sky model energy flux (erg cm\f$^{-2}\f$ s\f$^{-1}\f$)
1172 *
1173 * Returns the spatially integrate energy flux in the sky model.
1174 ***************************************************************************/
1175double GModelSky::eflux(const GEnergy& emin, const GEnergy& emax) const
1176{
1177 // Initialise energy flux
1178 double eflux = 0.0;
1179
1180 // Get pointer on diffuse cube spatial model component
1181 const GModelSpatialDiffuseCube* cube =
1182 dynamic_cast<const GModelSpatialDiffuseCube*>(spatial());
1183
1184 // If spatial model is a diffuse cube then compute the flux by
1185 // multiplying the spectrum of the spatial and spectral components
1186 // using a node function
1187 if (cube != NULL) {
1188
1189 // Get spectral nodes
1190 GModelSpectralNodes nodes = cube->spectrum();
1191
1192 // Multiply spectral nodes with spectral model
1193 for (int i = 0; i < nodes.nodes(); ++i) {
1194
1195 // Get energy and intensity
1196 GEnergy energy = nodes.energy(i);
1197 double intensity = nodes.intensity(i);
1198
1199 // Multiply intensity with spectral model
1200 intensity *= spectral()->eval(energy);
1201
1202 // Store intensity
1203 nodes.intensity(i, intensity);
1204
1205 } // endfor: multiplied spectral nodes with spectral model
1206
1207 // Compute energy flux
1208 eflux = nodes.eflux(emin, emax);
1209
1210 } // endif: spatial model was a diffuse cube
1211
1212 // ... otherwise assume that the spatial model is unity and compute
1213 // energy flux from the spectral component
1214 else {
1215 eflux = spectral()->eflux(emin, emax);
1216 }
1217
1218 // Return energy flux
1219 return eflux;
1220}
1221
1222
1223/***********************************************************************//**
1224 * @brief Return sky model energy flux within sky region
1225 *
1226 * @param[in] region Sky region.
1227 * @param[in] emin Minimum energy.
1228 * @param[in] emax Maximum energy.
1229 * @return Sky model energy flux (erg cm\f$^{-2}\f$ s\f$^{-1}\f$)
1230 *
1231 * Returns the energy flux of the sky model within a given sky region. If
1232 * the spatial model is energy dependent the method integrates the flux over
1233 * the specified energy range. Otherwise the spatially integrated flux is
1234 * multiplied by the spectral flux.
1235 ***************************************************************************/
1236double GModelSky::eflux(const GSkyRegion& region,
1237 const GEnergy& emin,
1238 const GEnergy& emax) const
1239{
1240 // Initialise flux
1241 double eflux = 0.0;
1242
1243 // Signal for which models the spatial component depends on energy
1244 bool dependence = (spatial()->classname() == "GModelSpatialDiffuseCube") ||
1245 (spatial()->classname() == "GModelSpatialComposite");
1246
1247 // If the spatial component depends on energy then use
1248 if (dependence) {
1249
1250 // Get boundaries in MeV
1251 double mev_min = emin.MeV();
1252 double mev_max = emax.MeV();
1253
1254 // Continue only if valid
1255 if (mev_max > mev_min) {
1256
1257 // Setup integration function
1258 GModelSky::eflux_kern integrand(this, &region);
1259 GIntegral integral(&integrand);
1260
1261 // Do Romberg integration
1262 eflux = integral.romberg(std::log(mev_min), std::log(mev_max));
1263
1264 } // endif: energy interval was valid
1265
1266 } // endif: spatial model was a diffuse cube
1267
1268 // ... otherwise the spatial model does not depend on energy, hence
1269 // the flux is computed as the product between the spatial and
1270 // spectral flux. Note that this correctly takes the spatial
1271 // normalisation into account since the flux() method does this.
1272 else {
1273 eflux = spatial()->flux(region) * spectral()->eflux(emin, emax);
1274 }
1275
1276 // Return flux
1277 return eflux;
1278}
1279
1280
1281/***********************************************************************//**
1282 * @brief Return sky model photon flux error
1283 *
1284 * @param[in] emin Minimum energy.
1285 * @param[in] emax Maximum energy.
1286 * @return Sky model photon flux error (cm\f$^{-2}\f$ s\f$^{-1}\f$)
1287 *
1288 * Returns the spatially integrate photon flux error in the sky model. The
1289 * photon flux error is computed using Gaussian error propagation
1290 *
1291 * \f[
1292 * \Delta F_{ph} = \sqrt{
1293 * \sum_i \left( \frac{\partial F_{ph}}{\partial p_i} \right)^2
1294 * \left( \Delta p_i \right)^2 }
1295 * \f]
1296 *
1297 * where
1298 * \f$F_{ph}\f$ is the sky model photon flux and
1299 * \f$p_i\f$ are the sky model parameters.
1300 ***************************************************************************/
1301double GModelSky::flux_error(const GEnergy& emin, const GEnergy& emax) const
1302{
1303 // Initialise flux error
1304 double flux_error = 0.0;
1305
1306 // Loop over all model parameters
1307 for (int ipar = 0; ipar < size(); ++ipar) {
1308
1309 // Get non-const model pointer
1310 GModelPar* par = const_cast<GModelPar*>(&(*this)[ipar]);
1311
1312 // Consider only free parameters
1313 if (par->is_free()) {
1314
1315 // Save current model parameter
1316 GModelPar current = *par;
1317
1318 // Autoscale model parameter
1319 par->autoscale();
1320
1321 // Get actual parameter value
1322 double x = par->factor_value();
1323
1324 // Set fixed step size for computation of derivative.
1325 const double step_size = 0.0002;
1326 double h = step_size;
1327
1328 // Re-adjust the step-size h in case that the initial step size is
1329 // larger than the allowed parameter range
1330 if (par->has_min() && par->has_max()) {
1331 double par_h = par->factor_max() - par->factor_min();
1332 if (par_h < h) {
1333 h = par_h;
1334 }
1335 }
1336
1337 // Initialise derivative
1338 double derivative = 0.0;
1339
1340 // Continue only if step size is positive
1341 if (h > 0.0) {
1342
1343 // If we are too close to the minimum boundary use a right
1344 // sided difference ...
1345 if (par->has_min() && ((x-par->factor_min()) < h)) {
1346
1347 // Compute fs1
1348 par->factor_value(x);
1349 double fs1 = flux(emin, emax);
1350
1351 // Compute fs2
1352 par->factor_value(x+h);
1353 double fs2 = flux(emin, emax);
1354
1355 // Compute derivative
1356 derivative = (fs1 - fs2) / h;
1357
1358 }
1359
1360 // ... otherwise if we are too close to the maximum boundary use
1361 // a left sided difference ...
1362 else if (par->has_max() && ((par->factor_max()-x) < h)) {
1363
1364 // Compute fs1
1365 par->factor_value(x);
1366 double fs1 = flux(emin, emax);
1367
1368 // Compute fs2
1369 par->factor_value(x-h);
1370 double fs2 = flux(emin, emax);
1371
1372 // Compute derivative
1373 derivative = (fs1 - fs2) / h;
1374
1375 }
1376
1377 // ... otherwise use a symmetric difference
1378 else {
1379
1380 // Compute fs1
1381 par->factor_value(x+h);
1382 double fs1 = flux(emin, emax);
1383
1384 // Compute fs2
1385 par->factor_value(x-h);
1386 double fs2 = flux(emin, emax);
1387
1388 // Compute derivative
1389 derivative = 0.5 * (fs1 - fs2) / h;
1390
1391 }
1392
1393 } // endif: step size was positive
1394
1395 // Add contribution
1396 if (derivative > 0.0) {
1397 double factor = derivative * par->factor_error();
1398 flux_error += factor * factor;
1399 }
1400
1401 // Restore current model parameter
1402 *par = current;
1403
1404 } // endif: parameter was free
1405
1406 } // endfor: looped over all parameters
1407
1408 // Take square root if required
1409 if (flux_error > 0.0) {
1410 flux_error = std::sqrt(flux_error);
1411 }
1412
1413 // Return flux error
1414 return flux_error;
1415}
1416
1417
1418/***********************************************************************//**
1419 * @brief Return sky model photon flux error within sky region
1420 *
1421 * @param[in] region Sky region.
1422 * @param[in] emin Minimum energy.
1423 * @param[in] emax Maximum energy.
1424 * @return Sky model photon flux error (cm\f$^{-2}\f$ s\f$^{-1}\f$)
1425 *
1426 * Returns the spatially integrate photon flux error in the sky model. The
1427 * photon flux error is computed using Gaussian error propagation
1428 *
1429 * \f[
1430 * \Delta F_{ph} = \sqrt{
1431 * \sum_i \left( \frac{\partial F_{ph}}{\partial p_i} \right)^2
1432 * \left( \Delta p_i \right)^2 }
1433 * \f]
1434 *
1435 * where
1436 * \f$F_{ph}\f$ is the sky model photon flux and
1437 * \f$p_i\f$ are the sky model parameters.
1438 ***************************************************************************/
1440 const GEnergy& emin,
1441 const GEnergy& emax) const
1442{
1443 // Initialise flux error
1444 double flux_error = 0.0;
1445
1446 // Loop over all model parameters
1447 for (int ipar = 0; ipar < size(); ++ipar) {
1448
1449 // Get non-const model pointer
1450 GModelPar* par = const_cast<GModelPar*>(&(*this)[ipar]);
1451
1452 // Consider only free parameters
1453 if (par->is_free()) {
1454
1455 // Save current model parameter
1456 GModelPar current = *par;
1457
1458 // Autoscale model parameter
1459 par->autoscale();
1460
1461 // Get actual parameter value
1462 double x = par->factor_value();
1463
1464 // Set fixed step size for computation of derivative.
1465 const double step_size = 0.0002;
1466 double h = step_size;
1467
1468 // Re-adjust the step-size h in case that the initial step size is
1469 // larger than the allowed parameter range
1470 if (par->has_min() && par->has_max()) {
1471 double par_h = par->factor_max() - par->factor_min();
1472 if (par_h < h) {
1473 h = par_h;
1474 }
1475 }
1476
1477 // Initialise derivative
1478 double derivative = 0.0;
1479
1480 // Continue only if step size is positive
1481 if (h > 0.0) {
1482
1483 // If we are too close to the minimum boundary use a right
1484 // sided difference ...
1485 if (par->has_min() && ((x-par->factor_min()) < h)) {
1486
1487 // Compute fs1
1488 par->factor_value(x);
1489 double fs1 = flux(region, emin, emax);
1490
1491 // Compute fs2
1492 par->factor_value(x+h);
1493 double fs2 = flux(region, emin, emax);
1494
1495 // Compute derivative
1496 derivative = (fs1 - fs2) / h;
1497
1498 }
1499
1500 // ... otherwise if we are too close to the maximum boundary use
1501 // a left sided difference ...
1502 else if (par->has_max() && ((par->factor_max()-x) < h)) {
1503
1504 // Compute fs1
1505 par->factor_value(x);
1506 double fs1 = flux(region, emin, emax);
1507
1508 // Compute fs2
1509 par->factor_value(x-h);
1510 double fs2 = flux(region, emin, emax);
1511
1512 // Compute derivative
1513 derivative = (fs1 - fs2) / h;
1514
1515 }
1516
1517 // ... otherwise use a symmetric difference
1518 else {
1519
1520 // Compute fs1
1521 par->factor_value(x+h);
1522 double fs1 = flux(region, emin, emax);
1523
1524 // Compute fs2
1525 par->factor_value(x-h);
1526 double fs2 = flux(region, emin, emax);
1527
1528 // Compute derivative
1529 derivative = 0.5 * (fs1 - fs2) / h;
1530
1531 }
1532
1533 } // endif: step size was positive
1534
1535 // Add contribution
1536 if (derivative > 0.0) {
1537 double factor = derivative * par->factor_error();
1538 flux_error += factor * factor;
1539 }
1540
1541 // Restore current model parameter
1542 *par = current;
1543
1544 } // endif: parameter was free
1545
1546 } // endfor: looped over all parameters
1547
1548 // Take square root if required
1549 if (flux_error > 0.0) {
1550 flux_error = std::sqrt(flux_error);
1551 }
1552 // Return flux error
1553 return flux_error;
1554}
1555
1556
1557/***********************************************************************//**
1558 * @brief Return sky model energy flux error
1559 *
1560 * @param[in] emin Minimum energy.
1561 * @param[in] emax Maximum energy.
1562 * @return Sky model energy flux error (erg cm\f$^{-2}\f$ s\f$^{-1}\f$)
1563 *
1564 * Returns the spatially integrate energy flux error in the sky model. The
1565 * energy flux error is computed using Gaussian error propagation
1566 *
1567 * \f[
1568 * \Delta F_E = \sqrt{
1569 * \sum_i \left( \frac{\partial F_E}{\partial p_i} \right)^2
1570 * \left( \Delta p_i \right)^2 }
1571 * \f]
1572 *
1573 * where
1574 * \f$F_E\f$ is the sky model energy flux and
1575 * \f$p_i\f$ are the sky model parameters.
1576 ***************************************************************************/
1577double GModelSky::eflux_error(const GEnergy& emin, const GEnergy& emax) const
1578{
1579 // Initialise flux error
1580 double eflux_error = 0.0;
1581
1582 // Loop over all model parameters
1583 for (int ipar = 0; ipar < size(); ++ipar) {
1584
1585 // Get non-const model pointer
1586 GModelPar* par = const_cast<GModelPar*>(&(*this)[ipar]);
1587
1588 // Consider only free parameters
1589 if (par->is_free()) {
1590
1591 // Save current model parameter
1592 GModelPar current = *par;
1593
1594 // Autoscale model parameter
1595 par->autoscale();
1596
1597 // Get actual parameter value
1598 double x = par->factor_value();
1599
1600 // Set fixed step size for computation of derivative.
1601 const double step_size = 0.0002;
1602 double h = step_size;
1603
1604 // Re-adjust the step-size h in case that the initial step size is
1605 // larger than the allowed parameter range
1606 if (par->has_min() && par->has_max()) {
1607 double par_h = par->factor_max() - par->factor_min();
1608 if (par_h < h) {
1609 h = par_h;
1610 }
1611 }
1612
1613 // Initialise derivative
1614 double derivative = 0.0;
1615
1616 // Continue only if step size is positive
1617 if (h > 0.0) {
1618
1619 // If we are too close to the minimum boundary use a right
1620 // sided difference ...
1621 if (par->has_min() && ((x-par->factor_min()) < h)) {
1622
1623 // Compute fs1
1624 par->factor_value(x);
1625 double fs1 = eflux(emin, emax);
1626
1627 // Compute fs2
1628 par->factor_value(x+h);
1629 double fs2 = eflux(emin, emax);
1630
1631 // Compute derivative
1632 derivative = (fs1 - fs2) / h;
1633
1634 }
1635
1636 // ... otherwise if we are too close to the maximum boundary use
1637 // a left sided difference ...
1638 else if (par->has_max() && ((par->factor_max()-x) < h)) {
1639
1640 // Compute fs1
1641 par->factor_value(x);
1642 double fs1 = eflux(emin, emax);
1643
1644 // Compute fs2
1645 par->factor_value(x-h);
1646 double fs2 = eflux(emin, emax);
1647
1648 // Compute derivative
1649 derivative = (fs1 - fs2) / h;
1650
1651 }
1652
1653 // ... otherwise use a symmetric difference
1654 else {
1655
1656 // Compute fs1
1657 par->factor_value(x+h);
1658 double fs1 = eflux(emin, emax);
1659
1660 // Compute fs2
1661 par->factor_value(x-h);
1662 double fs2 = eflux(emin, emax);
1663
1664 // Compute derivative
1665 derivative = 0.5 * (fs1 - fs2) / h;
1666
1667 }
1668
1669 } // endif: step size was positive
1670
1671 // Add contribution
1672 if (derivative > 0.0) {
1673 double factor = derivative * par->factor_error();
1674 eflux_error += factor * factor;
1675 }
1676
1677 // Restore current model parameter
1678 *par = current;
1679
1680 } // endif: parameter was free
1681
1682 } // endfor: looped over all parameters
1683
1684 // Take square root if required
1685 if (eflux_error > 0.0) {
1686 eflux_error = std::sqrt(eflux_error);
1687 }
1688
1689 // Return flux error
1690 return eflux_error;
1691}
1692
1693
1694/***********************************************************************//**
1695 * @brief Return sky model energy flux error within sky region
1696 *
1697 * @param[in] region Sky region.
1698 * @param[in] emin Minimum energy.
1699 * @param[in] emax Maximum energy.
1700 * @return Sky model energy flux error (erg cm\f$^{-2}\f$ s\f$^{-1}\f$)
1701 *
1702 * Returns the spatially integrate energy flux error in the sky model. The
1703 * energy flux error is computed using Gaussian error propagation
1704 *
1705 * \f[
1706 * \Delta F_E = \sqrt{
1707 * \sum_i \left( \frac{\partial F_E}{\partial p_i} \right)^2
1708 * \left( \Delta p_i \right)^2 }
1709 * \f]
1710 *
1711 * where
1712 * \f$F_E\f$ is the sky model energy flux and
1713 * \f$p_i\f$ are the sky model parameters.
1714 ***************************************************************************/
1716 const GEnergy& emin,
1717 const GEnergy& emax) const
1718{
1719 // Initialise flux error
1720 double eflux_error = 0.0;
1721
1722 // Loop over all model parameters
1723 for (int ipar = 0; ipar < size(); ++ipar) {
1724
1725 // Get non-const model pointer
1726 GModelPar* par = const_cast<GModelPar*>(&(*this)[ipar]);
1727
1728 // Consider only free parameters
1729 if (par->is_free()) {
1730
1731 // Save current model parameter
1732 GModelPar current = *par;
1733
1734 // Autoscale model parameter
1735 par->autoscale();
1736
1737 // Get actual parameter value
1738 double x = par->factor_value();
1739
1740 // Set fixed step size for computation of derivative.
1741 const double step_size = 0.0002;
1742 double h = step_size;
1743
1744 // Re-adjust the step-size h in case that the initial step size is
1745 // larger than the allowed parameter range
1746 if (par->has_min() && par->has_max()) {
1747 double par_h = par->factor_max() - par->factor_min();
1748 if (par_h < h) {
1749 h = par_h;
1750 }
1751 }
1752
1753 // Initialise derivative
1754 double derivative = 0.0;
1755
1756 // Continue only if step size is positive
1757 if (h > 0.0) {
1758
1759 // If we are too close to the minimum boundary use a right
1760 // sided difference ...
1761 if (par->has_min() && ((x-par->factor_min()) < h)) {
1762
1763 // Compute fs1
1764 par->factor_value(x);
1765 double fs1 = eflux(region, emin, emax);
1766
1767 // Compute fs2
1768 par->factor_value(x+h);
1769 double fs2 = eflux(region, emin, emax);
1770
1771 // Compute derivative
1772 derivative = (fs1 - fs2) / h;
1773
1774 }
1775
1776 // ... otherwise if we are too close to the maximum boundary use
1777 // a left sided difference ...
1778 else if (par->has_max() && ((par->factor_max()-x) < h)) {
1779
1780 // Compute fs1
1781 par->factor_value(x);
1782 double fs1 = eflux(region, emin, emax);
1783
1784 // Compute fs2
1785 par->factor_value(x-h);
1786 double fs2 = eflux(region, emin, emax);
1787
1788 // Compute derivative
1789 derivative = (fs1 - fs2) / h;
1790
1791 }
1792
1793 // ... otherwise use a symmetric difference
1794 else {
1795
1796 // Compute fs1
1797 par->factor_value(x+h);
1798 double fs1 = eflux(region, emin, emax);
1799
1800 // Compute fs2
1801 par->factor_value(x-h);
1802 double fs2 = eflux(region, emin, emax);
1803
1804 // Compute derivative
1805 derivative = 0.5 * (fs1 - fs2) / h;
1806
1807 }
1808
1809 } // endif: step size was positive
1810
1811 // Add contribution
1812 if (derivative > 0.0) {
1813 double factor = derivative * par->factor_error();
1814 eflux_error += factor * factor;
1815 }
1816
1817 // Restore current model parameter
1818 *par = current;
1819
1820 } // endif: parameter was free
1821
1822 } // endfor: looped over all parameters
1823
1824 // Take square root if required
1825 if (eflux_error > 0.0) {
1826 eflux_error = std::sqrt(eflux_error);
1827 }
1828 // Return flux error
1829 return eflux_error;
1830}
1831
1832
1833/***********************************************************************//**
1834 * @brief Print model information
1835 *
1836 * @param[in] chatter Chattiness.
1837 * @return String containing model information.
1838 ***************************************************************************/
1839std::string GModelSky::print(const GChatter& chatter) const
1840{
1841 // Initialise result string
1842 std::string result;
1843
1844 // Continue only if chatter is not silent
1845 if (chatter != SILENT) {
1846
1847 // Append header
1848 result.append("=== GModelSky ===");
1849
1850 // Determine number of parameters per type
1851 int n_spatial = (m_spatial != NULL) ? m_spatial->size() : 0;
1852 int n_spectral = (m_spectral != NULL) ? m_spectral->size() : 0;
1853 int n_temporal = (m_temporal != NULL) ? m_temporal->size() : 0;
1854
1855 // Append attributes
1856 result.append("\n"+print_attributes());
1857
1858 // Append model type
1859 result.append("\n"+gammalib::parformat("Model type")+type());
1860
1861 // Append model components
1862 result.append("\n"+gammalib::parformat("Model components"));
1863 if (n_spatial > 0) {
1864 result.append("\""+spatial()->type()+"\"");
1865 if (n_spectral > 0 || n_temporal > 0) {
1866 result.append(" * ");
1867 }
1868 }
1869 if (n_spectral > 0) {
1870 result.append("\""+spectral()->type()+"\"");
1871 if (n_temporal > 0) {
1872 result.append(" * ");
1873 }
1874 }
1875 if (n_temporal > 0) {
1876 result.append("\""+temporal()->type()+"\"");
1877 }
1878
1879 // Append parameters
1880 result.append("\n"+gammalib::parformat("Number of parameters"));
1881 result.append(gammalib::str(size()));
1882 result.append("\n"+gammalib::parformat("Number of spatial par's"));
1883 result.append(gammalib::str(n_spatial));
1884 for (int i = 0; i < n_spatial; ++i) {
1885 result.append("\n"+(*spatial())[i].print());
1886 }
1887 result.append("\n"+gammalib::parformat("Number of spectral par's"));
1888 result.append(gammalib::str(n_spectral));
1889 for (int i = 0; i < n_spectral; ++i) {
1890 result.append("\n"+(*spectral())[i].print());
1891 }
1892 result.append("\n"+gammalib::parformat("Number of temporal par's"));
1893 result.append(gammalib::str(n_temporal));
1894 for (int i = 0; i < n_temporal; ++i) {
1895 result.append("\n"+(*temporal())[i].print());
1896 }
1897 result.append("\n"+gammalib::parformat("Number of scale par's"));
1898 result.append(gammalib::str(scales()));
1899 for (int i = 0; i < scales(); ++i) {
1900 result.append("\n"+scale(i).print());
1901 }
1902
1903 } // endif: chatter was not silent
1904
1905 // Return result
1906 return result;
1907}
1908
1909
1910/*==========================================================================
1911 = =
1912 = Private methods =
1913 = =
1914 ==========================================================================*/
1915
1916/***********************************************************************//**
1917 * @brief Initialise class members
1918 ***************************************************************************/
1920{
1921 // Initialise members
1922 m_type.clear();
1923 m_spatial = NULL;
1924 m_spectral = NULL;
1925 m_temporal = NULL;
1926
1927 // Return
1928 return;
1929}
1930
1931
1932/***********************************************************************//**
1933 * @brief Copy class members
1934 *
1935 * @param[in] model Sky model.
1936 ***************************************************************************/
1938{
1939 // Copy attributes
1940 m_type = model.m_type;
1941
1942 // Clone model components
1943 m_spatial = (model.m_spatial != NULL) ? model.m_spatial->clone() : NULL;
1944 m_spectral = (model.m_spectral != NULL) ? model.m_spectral->clone() : NULL;
1945 m_temporal = (model.m_temporal != NULL) ? model.m_temporal->clone() : NULL;
1946
1947 // Set parameter pointers
1948 set_pointers();
1949
1950 // Return
1951 return;
1952}
1953
1954
1955/***********************************************************************//**
1956 * @brief Delete class members
1957 ***************************************************************************/
1959{
1960 // Free memory
1961 if (m_spatial != NULL) delete m_spatial;
1962 if (m_spectral != NULL) delete m_spectral;
1963 if (m_temporal != NULL) delete m_temporal;
1964
1965 // Signal free pointers
1966 m_spatial = NULL;
1967 m_spectral = NULL;
1968 m_temporal = NULL;
1969
1970 // Return
1971 return;
1972}
1973
1974
1975/***********************************************************************//**
1976 * @brief Set parameter pointers
1977 *
1978 * Gathers all parameter pointers from the model into a flat array of model
1979 * pointers.
1980 ***************************************************************************/
1982{
1983 // Clear parameters
1984 m_pars.clear();
1985
1986 // Determine the number of parameters
1987 int n_spatial = (spatial() != NULL) ? spatial()->size() : 0;
1988 int n_spectral = (spectral() != NULL) ? spectral()->size() : 0;
1989 int n_temporal = (temporal() != NULL) ? temporal()->size() : 0;
1990 int n_pars = n_spatial + n_spectral + n_temporal;
1991 int n_scales = m_scales.size();
1992
1993 // Continue only if there are parameters
1994 if (n_pars > 0) {
1995
1996 // Gather spatial parameter pointers
1997 for (int i = 0; i < n_spatial; ++i) {
1998 m_pars.push_back(&((*spatial())[i]));
1999 }
2000
2001 // Gather spectral parameters
2002 for (int i = 0; i < n_spectral; ++i) {
2003 m_pars.push_back(&((*spectral())[i]));
2004 }
2005
2006 // Gather temporal parameters
2007 for (int i = 0; i < n_temporal; ++i) {
2008 m_pars.push_back(&((*temporal())[i]));
2009 }
2010
2011 }
2012
2013 // Append scales if they exist
2014 if (n_scales > 0) {
2015 for (int i = 0; i < n_scales; ++i) {
2016 m_pars.push_back(&m_scales[i]);
2017 }
2018 }
2019
2020 // Return
2021 return;
2022}
2023
2024
2025/***********************************************************************//**
2026 * @brief Set model type based on spatial model component
2027 *
2028 * Set the model type depending on the class type of the spatial model
2029 * component.
2030 *
2031 * @todo A method could be implemented in the GModelSpatial class that
2032 * determines the model type. This is however not very critical.
2033 ***************************************************************************/
2035{
2036 // Clear model type
2037 m_type.clear();
2038
2039 // Continue only if we have a spatial model component
2040 if (m_spatial != NULL) {
2041
2042 // Is spatial model a point source?
2043 if (dynamic_cast<const GModelSpatialPointSource*>(m_spatial) != NULL) {
2044 m_type = "PointSource";
2045 }
2046
2047 // ... otherwise, is spatial model a radial source?
2048 else if (dynamic_cast<const GModelSpatialRadial*>(m_spatial) != NULL) {
2049 m_type = "ExtendedSource";
2050 }
2051
2052 // ... otherwise, is spatial model an elliptical source?
2053 else if (dynamic_cast<const GModelSpatialElliptical*>(m_spatial) != NULL) {
2054 m_type = "ExtendedSource";
2055 }
2056
2057 // ... otherwise, is spatial model a composite source?
2058 else if (dynamic_cast<const GModelSpatialComposite*>(m_spatial) != NULL) {
2059 m_type = "CompositeSource";
2060 }
2061
2062 // ... otherwise we have a diffuse model
2063 else {
2064 m_type = "DiffuseSource";
2065 }
2066
2067 } // endif: there was a spatial model component
2068
2069 // Return
2070 return;
2071}
2072
2073
2074/***********************************************************************//**
2075 * @brief Signal all parameters that have analytical gradients for a given
2076 * observation
2077 *
2078 * @param[in] obs Observation.
2079 *
2080 * This method signals all spatial, spectral, temporal and model scaling
2081 * parameters for which analytical gradients exist for a given observation.
2082 * Analytical gradients will be signalled for all of these parameters that
2083 * are free and for which `has_grad()` is `true`.
2084 *
2085 * So far, spatial analytical gradients for shape parameter exist only
2086 * for the "RadialGaussian" model, and since not all convolution method
2087 * support the handling of these analytical gradients, the corresponding
2088 * parameters are excluded here. However other spatial parameters, such as
2089 * scaling parameters, are considered.
2090 ***************************************************************************/
2092{
2093 // If the model has a spatial component then signal all free parameters
2094 // with analytical gradients
2095 if (spatial() != NULL) {
2096 for (int i = 0; i < spatial()->size(); ++i) {
2097 GModelPar& par = (*(spatial()))[i];
2098 if ((par.name() != "GLON") &&
2099 (par.name() != "GLAT") &&
2100 (par.name() != "RA") &&
2101 (par.name() != "DEC") &&
2102 (par.name() != "Sigma")) { // Kludge
2103 if (par.is_free() && par.has_grad()) {
2104 obs.computed_gradient(*this, par);
2105 }
2106 }
2107 }
2108 }
2109
2110 // If the model has a spectral component then signal all free parameters
2111 // with analytical gradients
2112 if (spectral() != NULL) {
2113 for (int i = 0; i < spectral()->size(); ++i) {
2114 GModelPar& par = (*(spectral()))[i];
2115 if (par.is_free() && par.has_grad()) {
2116 obs.computed_gradient(*this, par);
2117 }
2118 }
2119 }
2120
2121 // If the model has a temporal component then signal all free parameters
2122 // with analytical gradients
2123 if (temporal() != NULL) {
2124 for (int i = 0; i < temporal()->size(); ++i) {
2125 GModelPar& par = (*(temporal()))[i];
2126 if (par.is_free() && par.has_grad()) {
2127 obs.computed_gradient(*this, par);
2128 }
2129 }
2130 }
2131
2132 // If the model has a scales then signal all free parameters with
2133 // analytical gradients
2134 if (has_scales()) {
2135 for (int i = 0; i < scales(); ++i) {
2136 const GModelPar& par = scale(i);
2137 if (par.name() == obs.instrument()) {
2138 if (par.is_free() && par.has_grad()) {
2139 obs.computed_gradient(*this, par);
2140 }
2141 }
2142 }
2143 }
2144
2145 // Return
2146 return;
2147}
2148
2149
2150/***********************************************************************//**
2151 * @brief Return pointer to spatial model from XML element
2152 *
2153 * @param[in] spatial XML element.
2154 * @return Pointer to spatial model.
2155 *
2156 * Returns pointer to spatial model that is defined in an XML element.
2157 ***************************************************************************/
2159{
2160 // Get spatial model
2161 GModelSpatialRegistry registry;
2162 GModelSpatial* ptr = registry.alloc(spatial);
2163
2164 // Return pointer
2165 return ptr;
2166}
2167
2168
2169/***********************************************************************//**
2170 * @brief Return pointer to spectral model from XML element
2171 *
2172 * @param[in] spectral XML element.
2173 * @return Pointer to spectral model.
2174 *
2175 * Returns pointer to spectral model that is defined in an XML element.
2176 ***************************************************************************/
2178{
2179 // Get spectral model
2180 GModelSpectralRegistry registry;
2181 GModelSpectral* ptr = registry.alloc(spectral);
2182
2183 // Return pointer
2184 return ptr;
2185}
2186
2187
2188/***********************************************************************//**
2189 * @brief Return pointer to temporal model from XML element
2190 *
2191 * @param[in] temporal XML element.
2192 * @return Pointer to temporal model.
2193 *
2194 * Returns pointer to temporal model that is defined in an XML element.
2195 ***************************************************************************/
2197{
2198 // Get temporal model
2199 GModelTemporalRegistry registry;
2200 GModelTemporal* ptr = registry.alloc(temporal);
2201
2202 // Return pointer
2203 return ptr;
2204}
2205
2206
2207/***********************************************************************//**
2208 * @brief Verifies if model has all components
2209 *
2210 * @return True is model is valid, false otherwise.
2211 ***************************************************************************/
2213{
2214 // Set result
2215 bool result = ((m_spatial != NULL) &&
2216 (m_spectral != NULL) &&
2217 (m_temporal != NULL));
2218
2219 // Return result
2220 return result;
2221}
2222
2223
2224/***********************************************************************//**
2225 * @brief Integration kernel for flux_kern() class
2226 *
2227 * @param[in] x Function value.
2228 * @return Photon flux (erg/cm2/s/MeV)
2229 *
2230 * This method implements the integration kernel needed for the flux()
2231 * method.
2232 ***************************************************************************/
2233double GModelSky::flux_kern::eval(const double& x)
2234{
2235 // Set energy
2236 GEnergy eng;
2237 double expx = std::exp(x);
2238 eng.MeV(expx);
2239
2240 // Get photon flux within sky region -> (ph/cm2/s)
2241 double value = m_parent->spatial()->flux(*m_region, eng);
2242
2243 // Multiply by spectral model -> (ph/cm2/s/MeV)
2244 value *= m_parent->spectral()->eval(eng);
2245
2246 // Correct for variable substitution
2247 value *= expx;
2248
2249 // Return value
2250 return value;
2251}
2252
2253
2254/***********************************************************************//**
2255 * @brief Integration kernel for eflux_kern() class
2256 *
2257 * @param[in] x Function value.
2258 * @return Energy flux (erg/cm2/s/MeV)
2259 *
2260 * This method implements the integration kernel needed for the eflux()
2261 * method.
2262 ***************************************************************************/
2263double GModelSky::eflux_kern::eval(const double& x)
2264{
2265 // Set energy
2266 GEnergy eng;
2267 double expx = std::exp(x);
2268 eng.MeV(expx);
2269
2270 // Get photon flux within sky region -> (ph/cm2/s)
2271 double value = m_parent->spatial()->flux(*m_region, eng);
2272
2273 // Multiply by spectral model -> (ph/cm2/s/MeV)
2274 value *= m_parent->spectral()->eval(eng);
2275
2276 // Correct for variable substitution
2277 value *= expx;
2278
2279 // Multiply by energy in MeV -> (MeV/cm2/s/MeV)
2280 value *= expx * gammalib::MeV2erg;
2281
2282 // Return value
2283 return value;
2284}
Energy container class definition.
Exception handler interface definition.
Integration class interface definition.
Model registry class definition.
const GModelSky g_diffusesource_seed("DiffuseSource")
Definition GModelSky.cpp:56
const GModelSky g_compositesource_seed("CompositeSource")
Definition GModelSky.cpp:57
const GModelSky g_extendedsource_seed("ExtendedSource")
Definition GModelSky.cpp:55
const GModelSky g_pointsource_seed("PointSource")
Definition GModelSky.cpp:54
Sky model class interface definition.
Spatial composite model class interface definition.
Spatial map cube model class interface definition.
Abstract elliptical spatial model base class interface definition.
Point source spatial model class interface definition.
Abstract radial spatial model base class interface definition.
Spatial model registry class definition.
Spectral model registry class definition.
Constant temporal model class interface definition.
Temporal model registry class definition.
Abstract response base class definition.
Source class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
double norm(const GVector &vector)
Computes vector norm.
Definition GVector.cpp:932
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
double MeV(void) const
Return energy in MeV.
Definition GEnergy.cpp:342
Abstract interface for the event classes.
Definition GEvent.hpp:71
GIntegral class interface definition.
Definition GIntegral.hpp:46
double romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
Sparse matrix class interface definition.
Model parameter class.
Definition GModelPar.hpp:87
Interface definition for the model registry class.
double eval(const double &x)
Integration kernel for eflux_kern() class.
const GModelSky * m_parent
Sky model.
double eval(const double &x)
Integration kernel for flux_kern() class.
const GSkyRegion * m_region
Sky region.
Sky model class.
GModelSpectral * xml_spectral(const GXmlElement &spectral) const
Return pointer to spectral model from XML element.
virtual GModelSky & operator=(const GModelSky &model)
Assignment operator.
double eflux_error(const GEnergy &emin, const GEnergy &emax) const
Return sky model energy flux error.
void init_members(void)
Initialise class members.
GModelTemporal * m_temporal
Temporal model.
double value(const GPhoton &photon)
Return value of sky model for a given photon.
void set_pointers(void)
Set parameter pointers.
GModelSpatial * xml_spatial(const GXmlElement &spatial) const
Return pointer to spatial model from XML element.
bool valid_model(void) const
Verifies if model has all components.
GModelSpectral * m_spectral
Spectral model.
GModelSpatial * m_spatial
Spatial model.
double flux(const GEnergy &emin, const GEnergy &emax) const
Return sky model photon flux.
virtual void read(const GXmlElement &xml)
Read sky model from XML element.
std::string m_type
Model type.
virtual GModelSky * clone(void) const
Clone sky model.
void set_type(void)
Set model type based on spatial model component.
double flux_error(const GEnergy &emin, const GEnergy &emax) const
Return sky model photon flux error.
GModelSpectral * spectral(void) const
Return spectral model component.
GPhotons mc(const double &area, const GSkyDir &dir, const double &radius, const GEnergy &emin, const GEnergy &emax, const GTime &tmin, const GTime &tmax, GRan &ran) const
Return simulated list of photons.
virtual double npred(const GEnergy &obsEng, const GTime &obsTime, const GObservation &obs) const
Return spatially integrated sky model.
GVector gradients(const GPhoton &photon)
Return parameter gradients of sky model for a given photon.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print model information.
GModelSky(void)
Void constructor.
Definition GModelSky.cpp:91
void signal_analytical_gradients(const GObservation &obs) const
Signal all parameters that have analytical gradients for a given observation.
virtual void write(GXmlElement &xml) const
Write model into XML element.
virtual double eval(const GEvent &event, const GObservation &obs, const bool &gradients=false) const
Evaluate sky model for a given event of an observation.
virtual void clear(void)
Clear sky model.
void free_members(void)
Delete class members.
double eflux(const GEnergy &emin, const GEnergy &emax) const
Return sky model energy flux.
GModelTemporal * temporal(void) const
Return temporal model component.
void copy_members(const GModelSky &model)
Copy class members.
GModelSpatial * spatial(void) const
Return spatial model component.
virtual std::string type(void) const
Return sky model type.
virtual ~GModelSky(void)
Destructor.
GModelTemporal * xml_temporal(const GXmlElement &temporal) const
Return pointer to temporal model from XML element.
Spatial composite model.
const GModelSpectralNodes & spectrum(void) const
Get map cube spectrum.
void mc_cone(const GSkyRegionCircle &cone) const
Set Monte Carlo simulation cone.
Abstract elliptical spatial model base class.
Point source spatial model.
Abstract radial spatial model base class.
Interface definition for the spatial model registry class.
GModelSpatial * alloc(const GXmlElement &xml) const
Allocate spatial model that is found in XML element.
Abstract spatial model base class.
std::string type(void) const
Return model type.
virtual void write(GXmlElement &xml) const =0
virtual std::string classname(void) const =0
Return class name.
virtual GModelSpatial * clone(void) const =0
Clones object.
virtual GSkyDir mc(const GEnergy &energy, const GTime &time, GRan &ran) const =0
virtual double flux(const GSkyRegion &region, const GEnergy &srcEng=GEnergy(), const GTime &srcTime=GTime()) const
Returns model flux within sky region.
virtual double eval(const GPhoton &photon, const bool &gradients=false) const =0
virtual double mc_norm(const GSkyDir &dir, const double &radius) const =0
int size(void) const
Return number of parameters.
Spectral nodes model class.
virtual double flux(const GEnergy &emin, const GEnergy &emax) const
Returns model photon flux between [emin, emax] (units: ph/cm2/s)
int nodes(void) const
Return number of nodes.
virtual double eflux(const GEnergy &emin, const GEnergy &emax) const
Returns model energy flux between [emin, emax] (units: erg/cm2/s)
double intensity(const int &index) const
Return node intensity.
GEnergy energy(const int &index) const
Return node energy.
Interface definition for the spectral model registry class.
GModelSpectral * alloc(const GXmlElement &xml) const
Allocate spectral model that is found in XML element.
Abstract spectral model base class.
virtual double eval(const GEnergy &srcEng, const GTime &srcTime=GTime(), const bool &gradients=false) const =0
virtual GEnergy mc(const GEnergy &emin, const GEnergy &emax, const GTime &time, GRan &ran) const =0
virtual double flux(const GEnergy &emin, const GEnergy &emax) const =0
virtual GModelSpectral * clone(void) const =0
Clones object.
virtual void write(GXmlElement &xml) const =0
virtual double eflux(const GEnergy &emin, const GEnergy &emax) const =0
virtual std::string type(void) const =0
int size(void) const
Return number of parameters.
Constant temporal model class.
double norm(void) const
Return normalization factor.
Interface definition for the temporal model registry class.
GModelTemporal * alloc(const GXmlElement &xml) const
Allocate temporal model that is found in XML element.
Abstract temporal model base class.
virtual GModelTemporal * clone(void) const =0
Clones object.
virtual double eval(const GTime &srcTime, const bool &gradients=false) const =0
int size(void) const
Return number of parameters.
virtual std::string type(void) const =0
virtual GTimes mc(const double &rate, const GTime &tmin, const GTime &tmax, GRan &ran) const =0
virtual void write(GXmlElement &xml) const =0
Abstract model class.
Definition GModel.hpp:100
GModelPar & scale(const int &index)
Returns reference to scale parameter by index.
Definition GModel.cpp:384
std::vector< GModelPar * > m_pars
Pointers to all model parameters.
Definition GModel.hpp:182
bool has_scales(void) const
Signals that model has scales.
Definition GModel.hpp:359
void write_attributes(GXmlElement &xml) const
Write model attributes.
Definition GModel.cpp:738
void free_members(void)
Delete class members.
Definition GModel.cpp:687
void init_members(void)
Initialise class members.
Definition GModel.cpp:637
std::string print_attributes(void) const
Print model attributes.
Definition GModel.cpp:785
int size(void) const
Return number of parameters in model.
Definition GModel.hpp:237
virtual GModel & operator=(const GModel &model)
Assignment operator.
Definition GModel.cpp:132
void read_attributes(const GXmlElement &xml)
Read model attributes.
Definition GModel.cpp:699
const std::string & name(void) const
Return parameter name.
Definition GModel.hpp:265
int scales(void) const
Return number of scale parameters in model.
Definition GModel.hpp:251
std::vector< GModelPar > m_scales
Model instrument scale factors.
Definition GModel.hpp:180
Abstract observation base class.
void computed_gradient(const GModel &model, const GModelPar &par) const
Signals that an analytical gradient was computed for a model parameter.
virtual std::string instrument(void) const =0
virtual void response(const GResponse &rsp)=0
const double & factor_max(void) const
Return parameter maximum factor boundary.
const double & factor_value(void) const
Return parameter factor value.
bool is_free(void) const
Signal if parameter is free.
const double & factor_error(void) const
Return parameter factor error.
bool has_grad(void) const
Signal if parameter gradient is computed analytically.
bool has_min(void) const
Signal if parameter has minimum boundary.
std::string print(const GChatter &chatter=NORMAL) const
Print parameter information.
void autoscale(void)
Autoscale parameter.
bool has_max(void) const
Signal if parameter has maximum boundary.
const double & factor_min(void) const
Return parameter minimum factor boundary.
const std::string & name(void) const
Return parameter name.
Class that handles photons.
Definition GPhoton.hpp:47
const GTime & time(void) const
Return photon time.
Definition GPhoton.hpp:134
const GSkyDir & dir(void) const
Return photon sky direction.
Definition GPhoton.hpp:110
const GEnergy & energy(void) const
Return photon energy.
Definition GPhoton.hpp:122
Photon container class.
Definition GPhotons.hpp:45
void reserve(const int &num)
Reserve memory for photons in container.
Definition GPhotons.cpp:334
void append(const GPhoton &photon)
Append photon to container.
Definition GPhotons.cpp:219
Random number generator class.
Definition GRan.hpp:44
Sky direction class.
Definition GSkyDir.hpp:62
double dist_deg(const GSkyDir &dir) const
Compute angular distance between sky directions in degrees.
Definition GSkyDir.hpp:288
Interface for the circular sky region class.
Abstract interface for the sky region class.
Time class.
Definition GTime.hpp:55
Time container class.
Definition GTimes.hpp:45
int size(void) const
Return number of times.
Definition GTimes.hpp:100
Vector class.
Definition GVector.hpp:46
XML element node class.
const GXmlAttribute * attribute(const int &index) const
Return attribute.
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition GXmlNode.cpp:287
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition GXmlNode.cpp:640
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition GXmlNode.cpp:586
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1162
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition GTools.hpp:186
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition GTools.hpp:203
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
const double MeV2erg
Definition GTools.hpp:45