GammaLib 2.0.0
Loading...
Searching...
No Matches
GCTAModelIrfBackground.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GCTAModelIrfBackground.cpp - CTA IRF background model class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2014-2021 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- *
6 * *
7 * This program is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GCTAModelIrfBackground.cpp
23 * @brief CTA IRF background 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 "GMath.hpp"
33#include "GIntegral.hpp"
34#include "GModelRegistry.hpp"
40#include "GCTAObservation.hpp"
41#include "GCTAResponseIrf.hpp"
42#include "GCTABackground.hpp"
43#include "GCTAEventBin.hpp"
44#include "GCTASupport.hpp"
45
46/* __ Globals ____________________________________________________________ */
48const GModelRegistry g_cta_inst_background_registry(&g_cta_inst_background_seed);
49
50/* __ Method name definitions ____________________________________________ */
51#define G_EVAL "GCTAModelIrfBackground::eval(GEvent&, GObservation&, bool&)"
52#define G_NPRED "GCTAModelIrfBackground::npred(GEnergy&, GTime&,"\
53 " GObservation&)"
54#define G_MC "GCTAModelIrfBackground::mc(GObservation&, GRan&)"
55#define G_XML_SPECTRAL "GCTAModelIrfBackground::xml_spectral(GXmlElement&)"
56#define G_XML_TEMPORAL "GCTAModelIrfBackground::xml_temporal(GXmlElement&)"
57
58/* __ Macros _____________________________________________________________ */
59
60/* __ Coding definitions _________________________________________________ */
61#define G_USE_NPRED_CACHE
62#define G_USE_RATE_EBIN
63
64/* __ Debug definitions __________________________________________________ */
65//#define G_DUMP_MC
66//#define G_DEBUG_NPRED
67
68/* __ Constants __________________________________________________________ */
69
70
71/*==========================================================================
72 = =
73 = Constructors/destructors =
74 = =
75 ==========================================================================*/
76
77/***********************************************************************//**
78 * @brief Void constructor
79 ***************************************************************************/
81{
82 // Initialise class members
84
85 // Return
86 return;
87}
88
89
90/***********************************************************************//**
91 * @brief Constructor
92 *
93 * @param[in] xml XML element.
94 *
95 * Constructs a CTA instrumental background model from the information
96 * provided by an XML element. The XML element is expected to have the
97 * following structure
98 *
99 * <source name="..." type="..." instrument="...">
100 * <spectrum type="...">
101 * ...
102 * </spectrum>
103 * </source>
104 *
105 * Optionally, a temporal model may be provided using the following
106 * syntax
107 *
108 * <source name="..." type="..." instrument="...">
109 * <spectrum type="...">
110 * ...
111 * </spectrum>
112 * <temporalModel type="...">
113 * ...
114 * </temporalModel>
115 * </source>
116 *
117 * If no temporal component is found a constant model is assumed.
118 ***************************************************************************/
120 GModelData(xml)
121{
122 // Initialise members
123 init_members();
124
125 // Read XML
126 read(xml);
127
128 // Set parameter pointers
129 set_pointers();
130
131 // Return
132 return;
133}
134
135
136/***********************************************************************//**
137 * @brief Construct from spectral component
138 *
139 * @param[in] spectral Spectral model component.
140 *
141 * Constructs a CTA instrumental background model from a spectral
142 * model component. The temporal component is assumed to be constant.
143 * Please refer to the classe GModelSpectral to learn more about the
144 * definition of the spectral components.
145 ***************************************************************************/
147 GModelData()
148{
149 // Initialise members
150 init_members();
151
152 // Allocate temporal constant model
154
155 // Clone model components
158
159 // Set parameter pointers
160 set_pointers();
161
162 // Return
163 return;
164}
165
166
167/***********************************************************************//**
168 * @brief Copy constructor
169 *
170 * @param[in] bgd CTA instrument background model.
171 ***************************************************************************/
173 GModelData(bgd)
174{
175 // Initialise class members
176 init_members();
177
178 // Copy members
179 copy_members(bgd);
180
181 // Return
182 return;
183}
184
185
186/***********************************************************************//**
187 * @brief Destructor
188 ***************************************************************************/
190{
191 // Free members
192 free_members();
193
194 // Return
195 return;
196}
197
198
199/*==========================================================================
200 = =
201 = Operators =
202 = =
203 ==========================================================================*/
204
205/***********************************************************************//**
206 * @brief Assignment operator
207 *
208 * @param[in] bgd CTA instrument background model.
209 * @return CTA instrument background model.
210 ***************************************************************************/
212{
213 // Execute only if object is not identical
214 if (this != &bgd) {
215
216 // Copy base class members
217 this->GModelData::operator=(bgd);
218
219 // Free members
220 free_members();
221
222 // Initialise private members
223 init_members();
224
225 // Copy members
226 copy_members(bgd);
227
228 } // endif: object was not identical
229
230 // Return this object
231 return *this;
232}
233
234
235/*==========================================================================
236 = =
237 = Public methods =
238 = =
239 ==========================================================================*/
240
241/***********************************************************************//**
242 * @brief Clear CTA instrument background model
243 *
244 * This method properly resets the CTA instrument background model to an
245 * initial state.
246 ***************************************************************************/
248{
249 // Free class members (base and derived classes, derived class first)
250 free_members();
252
253 // Initialise members
255 init_members();
256
257 // Return
258 return;
259}
260
261
262/***********************************************************************//**
263 * @brief Clone CTA instrument background model
264 *
265 * @return Pointer to deep copy of CTA instrument background model.
266 ***************************************************************************/
271
272
273/***********************************************************************//**
274 * @brief Set spectral model component
275 *
276 * @param[in] spectral Pointer to spectral model component.
277 *
278 * Sets the spectral model component of the model.
279 ***************************************************************************/
281{
282 // Free spectral model component only if it differs from current
283 // component. This prevents unintential deallocation of the argument
284 if ((m_spectral != NULL) && (m_spectral != spectral)) {
285 delete m_spectral;
286 }
287
288 // Clone spectral model component if it exists, otherwise set pointer
289 // to NULL
290 m_spectral = (spectral != NULL) ? spectral->clone() : NULL;
291
292 // Set parameter pointers
293 set_pointers();
294
295 // Return
296 return;
297}
298
299
300/***********************************************************************//**
301 * @brief Set temporal model component
302 *
303 * @param[in] temporal Pointer to temporal model component.
304 *
305 * Sets the temporal model component of the model.
306 ***************************************************************************/
308{
309 // Free temporal model component only if it differs from current
310 // component. This prevents unintential deallocation of the argument
311 if ((m_temporal != NULL) && (m_temporal != temporal)) {
312 delete m_temporal;
313 }
314
315 // Clone temporal model component if it exists, otherwise set pointer
316 // to NULL
317 m_temporal = (temporal != NULL) ? temporal->clone() : NULL;
318
319 // Set parameter pointers
320 set_pointers();
321
322 // Return
323 return;
324}
325
326
327/***********************************************************************//**
328 * @brief Return background rate in units of events MeV\f$^{-1}\f$
329 * s\f$^{-1}\f$ sr\f$^{-1}\f$
330 *
331 * @param[in] event Observed event.
332 * @param[in] obs Observation.
333 * @param[in] gradients Compute gradients?
334 * @return Background rate (events MeV\f$^{-1}\f$ s\f$^{-1}\f$ sr\f$^{-1}\f$).
335 *
336 * The method returns a real rate, defined by the number of counts per MeV,
337 * steradian and ontime.
338 *
339 * If the @p gradients flag is true the method will also set the parameter
340 * gradients of the model parameters.
341 ***************************************************************************/
343 const GObservation& obs,
344 const bool& gradients) const
345{
346 // Get reference on CTA pointing and effective area response from
347 // observation and reference on CTA instrument direction from event
348 const GCTAPointing& pnt = gammalib::cta_pnt(G_EVAL, obs);
350 const GCTAInstDir& dir = gammalib::cta_dir(G_EVAL, event);
351
352 // Set DETX and DETY in instrument direction
353 GCTAInstDir inst_dir = pnt.instdir(dir.dir());
354
355 // Evaluate spatial component
356 #if defined(G_USE_RATE_EBIN)
357 double spat = 0.0;
358 if (event.is_atom()) {
359 double logE = event.energy().log10TeV();
360 spat = bgd(logE, inst_dir.detx(), inst_dir.dety());
361 }
362 else {
363 const GCTAEventBin* bin = static_cast<const GCTAEventBin*>(&event);
364 GEnergy emin = bin->emin();
365 GEnergy emax = emin + bin->ewidth();
366 double norm = 1.0 / bin->ewidth().MeV();
367 spat = bgd.rate_ebin(inst_dir, emin, emax) * norm;
368 }
369 #else
370 double logE = event.energy().log10TeV();
371 double spat = bgd(logE, inst_dir.detx(), inst_dir.dety());
372 #endif
373
374 // Evaluate function
375 double spec = (spectral() != NULL)
376 ? spectral()->eval(event.energy(), event.time(), gradients)
377 : 1.0;
378 double temp = (temporal() != NULL)
379 ? temporal()->eval(event.time(), gradients) : 1.0;
380
381 // Compute value
382 double value = spat * spec * temp;
383
384 // If gradients were requested then multiply factors to spectral and
385 // temporal gradients
386 if (gradients) {
387
388 // Multiply factors to spectral gradients
389 if (spectral() != NULL) {
390 double fact = spat * temp;
391 if (fact != 1.0) {
392 for (int i = 0; i < spectral()->size(); ++i)
393 (*spectral())[i].factor_gradient((*spectral())[i].factor_gradient() * fact);
394 }
395 }
396
397 // Multiply factors to temporal gradients
398 if (temporal() != NULL) {
399 double fact = spat * spec;
400 if (fact != 1.0) {
401 for (int i = 0; i < temporal()->size(); ++i)
402 (*temporal())[i].factor_gradient((*temporal())[i].factor_gradient() * fact);
403 }
404 }
405
406 } // endif: gradients were requested
407
408 // Return value
409 return value;
410}
411
412
413/***********************************************************************//**
414 * @brief Return spatially integrated background rate in units of
415 * events MeV\f$^{-1}\f$ s\f$^{-1}\f$
416 *
417 * @param[in] obsEng Measured event energy.
418 * @param[in] obsTime Measured event time.
419 * @param[in] obs Observation.
420 * @return Spatially integrated background rate
421 * (events MeV\f$^{-1}\f$ s\f$^{-1}\f$)
422 *
423 * Spatially integrates the instrumental background model for a given
424 * measured event energy and event time. The method returns a real rate,
425 * defined as the number of counts per MeV and ontime.
426 ***************************************************************************/
428 const GTime& obsTime,
429 const GObservation& obs) const
430{
431 // Set number of iterations for Romberg integration.
432 static const int iter_theta = 6;
433 static const int iter_phi = 6;
434
435 // Initialise result
436 double npred = 0.0;
437 bool has_npred = false;
438
439 // Build unique identifier
440 std::string id = obs.instrument() + "::" + obs.id();
441
442 // Check if Npred value is already in cache
443 #if defined(G_USE_NPRED_CACHE)
444 if (!m_npred_names.empty()) {
445
446 // Search for unique identifier, and if found, recover Npred value
447 // and break
448 for (int i = 0; i < m_npred_names.size(); ++i) {
449 if (m_npred_names[i] == id && m_npred_energies[i] == obsEng) {
451 has_npred = true;
452 #if defined(G_DEBUG_NPRED)
453 std::cout << "GCTAModelIrfBackground::npred:";
454 std::cout << " cache=" << i;
455 std::cout << " npred=" << npred << std::endl;
456 #endif
457 break;
458 }
459 }
460
461 } // endif: there were values in the Npred cache
462 #endif
463
464 // Continue only if no Npred cache value has been found
465 if (!has_npred) {
466
467 // Evaluate only if model is valid
468 if (valid_model()) {
469
470 // Get reference on CTA pointing, background response and event
471 // list from observation
472 const GCTAPointing& pnt = gammalib::cta_pnt(G_NPRED, obs);
474 const GCTAEventList& events = gammalib::cta_event_list(G_NPRED, obs);
475
476 // Get instrument direction of RoI centre
477 GCTAInstDir roi_centre = pnt.instdir(events.roi().centre().dir());
478
479 // Get ROI radius in radians
480 double roi_radius = events.roi().radius() * gammalib::deg2rad;
481
482 // Get log10 of energy in TeV
483 double logE = obsEng.log10TeV();
484
485 // Setup integration function
487 logE,
488 roi_centre,
489 iter_phi);
490
491 // Setup integration
492 GIntegral integral(&integrand);
493
494 // Set fixed number of iterations
495 integral.fixed_iter(iter_theta);
496
497 // Spatially integrate radial component
498 npred = integral.romberg(0.0, roi_radius);
499
500 // Store result in Npred cache
501 #if defined(G_USE_NPRED_CACHE)
502 m_npred_names.push_back(id);
503 m_npred_energies.push_back(obsEng);
504 m_npred_times.push_back(obsTime);
505 m_npred_values.push_back(npred);
506 #endif
507
508 // Debug: Check for NaN
509 #if defined(G_NAN_CHECK)
511 std::string origin = "GCTAModelIrfBackground::npred";
512 std::string message = " NaN/Inf encountered (npred=" +
513 gammalib::str(npred) + ", roi_radius=" +
514 gammalib::str(roi_radius) + ")";
515 gammalib::warning(origin, message);
516 }
517 #endif
518
519 } // endif: model was valid
520
521 } // endif: Npred computation required
522
523 // Multiply in spectral and temporal components
524 npred *= spectral()->eval(obsEng, obsTime);
525 npred *= temporal()->eval(obsTime);
526
527 // Return Npred
528 return npred;
529}
530
531
532/***********************************************************************//**
533 * @brief Return simulated list of events
534 *
535 * @param[in] obs Observation.
536 * @param[in] ran Random number generator.
537 * @return Pointer to list of simulated events (needs to be de-allocated by
538 * client)
539 *
540 * Draws a sample of events from the background model using a Monte
541 * Carlo simulation. The region of interest, the energy boundaries and the
542 * good time interval for the sampling will be extracted from the observation
543 * argument that is passed to the method. The method also requires a random
544 * number generator of type GRan which is passed by reference, hence the
545 * state of the random number generator will be changed by the method.
546 *
547 * For each event in the returned event list, the sky direction, the nominal
548 * coordinates (DETX and DETY), the energy and the time will be set.
549 ***************************************************************************/
551{
552 // Initialise new event list
553 GCTAEventList* list = new GCTAEventList;
554
555 // Continue only if model is valid)
556 if (valid_model()) {
557
558 // Get reference on CTA pointing, background response and event list
559 // from observation
560 const GCTAPointing& pnt = gammalib::cta_pnt(G_MC, obs);
561 const GCTABackground& bgd = gammalib::cta_rsp_bkg(G_MC, obs);
562 const GCTAEventList& events = gammalib::cta_event_list(G_MC, obs);
563
564 // Get simulation region
565 const GCTARoi& roi = events.roi();
566 const GEbounds& ebounds = events.ebounds();
567 const GGti& gti = events.gti();
568
569 // Set simulation region for result event list
570 list->roi(roi);
571 list->ebounds(ebounds);
572 list->gti(gti);
573
574 // Create a spectral model that combines the information from the
575 // background information and the spectrum provided by the model
577 for (int i = 0; i < spectral.nodes(); ++i) {
578 GEnergy energy = spectral.energy(i);
579 double intensity = spectral.intensity(i);
580 double norm = m_spectral->eval(energy);
581 spectral.intensity(i, norm*intensity);
582 }
583
584 // Loop over all energy boundaries
585 for (int ieng = 0; ieng < ebounds.size(); ++ieng) {
586
587 // Compute the background rate in model within the energy
588 // boundaries from spectral component (units: cts/s).
589 // Note that the time here is ontime. Deadtime correction will
590 // be done later.
591 double rate = spectral.flux(ebounds.emin(ieng), ebounds.emax(ieng));
592
593 // Debug option: dump rate
594 #if defined(G_DUMP_MC)
595 std::cout << "GCTAModelIrfBackground::mc(\"" << name() << "\": ";
596 std::cout << "rate=" << rate << " cts/s)" << std::endl;
597 #endif
598
599 // If the rate is not positive then skip this energy bins
600 if (rate <= 0.0) {
601 continue;
602 }
603
604 // Loop over all good time intervals
605 for (int itime = 0; itime < gti.size(); ++itime) {
606
607 // Get Monte Carlo event arrival times from temporal model
608 GTimes times = m_temporal->mc(rate,
609 gti.tstart(itime),
610 gti.tstop(itime),
611 ran);
612
613 // Get number of events
614 int n_events = times.size();
615
616 // Reserve space for events
617 if (n_events > 0) {
618 list->reserve(n_events);
619 }
620
621 // Debug option: provide number of times and initialize
622 // statisics
623 #if defined(G_DUMP_MC)
624 std::cout << " Interval " << itime;
625 std::cout << " events=" << n_events << std::endl;
626 int n_killed_by_roi = 0;
627 #endif
628
629 // Loop over events
630 for (int i = 0; i < n_events; ++i) {
631
632 // Get Monte Carlo event energy from spectral model
633 GEnergy energy = spectral.mc(ebounds.emin(ieng),
634 ebounds.emax(ieng),
635 times[i],
636 ran);
637
638 // Get Monte Carlo event direction from spatial model.
639 // This only will set the DETX and DETY coordinates.
640 GCTAInstDir instdir = bgd.mc(energy, times[i], ran);
641
642 // Derive sky direction from instrument coordinates
643 GSkyDir skydir = pnt.skydir(instdir);
644
645 // Set sky direction in GCTAInstDir object
646 instdir.dir(skydir);
647
648 // Allocate event
649 GCTAEventAtom event;
650
651 // Set event attributes
652 event.dir(instdir);
653 event.energy(energy);
654 event.time(times[i]);
655
656 // Append event to list if it falls in ROI
657 if (events.roi().contains(event)) {
658 list->append(event);
659 }
660 #if defined(G_DUMP_MC)
661 else {
662 n_killed_by_roi++;
663 }
664 #endif
665
666 } // endfor: looped over all events
667
668 // Debug option: provide statisics
669 #if defined(G_DUMP_MC)
670 std::cout << " Killed by ROI=";
671 std::cout << n_killed_by_roi << std::endl;
672 #endif
673
674 } // endfor: looped over all GTIs
675
676 } // endfor: looped over all energy boundaries
677
678 } // endif: model was valid
679
680 // Return
681 return list;
682}
683
684
685/***********************************************************************//**
686 * @brief Read CTA instrument background model from XML element
687 *
688 * @param[in] xml XML element.
689 *
690 * Set up CTA instrument background model from the information provided by
691 * an XML element. The XML element is expected to have the following
692 * structure
693 *
694 * <source name="..." type="..." instrument="...">
695 * <spectrum type="...">
696 * ...
697 * </spectrum>
698 * </source>
699 *
700 * Optionally, a temporal model may be provided using the following
701 * syntax
702 *
703 * <source name="..." type="..." instrument="...">
704 * <spectrum type="...">
705 * ...
706 * </spectrum>
707 * <temporal type="...">
708 * ...
709 * </temporal>
710 * </source>
711 *
712 * If no temporal component is found a constant model is assumed.
713 ***************************************************************************/
715{
716 // Clear model
717 clear();
718
719 // Initialise XML elements
720 const GXmlElement* spectral = NULL;
721
722 // Get pointer on spectrum
723 spectral = xml.element("spectrum", 0);
724
725 // Extract spectral model
727
728 // Optionally get temporal model
729 if (xml.elements("temporal")) {
730 const GXmlElement* temporal = xml.element("temporal", 0);
732 }
733 else {
734 GModelTemporalConst constant;
735 m_temporal = constant.clone();
736 }
737
738 // Read model attributes
739 read_attributes(xml);
740
741 // Set parameter pointers
742 set_pointers();
743
744 // Return
745 return;
746}
747
748
749/***********************************************************************//**
750 * @brief Write CTA instrument background model into XML element
751 *
752 * @param[in] xml XML element.
753 *
754 * Write CTA instrument background model information into an XML element.
755 * The XML element will have the following structure
756 *
757 * <source name="..." type="..." instrument="...">
758 * <spectrum type="...">
759 * ...
760 * </spectrum>
761 * </source>
762 *
763 * If the model contains a non-constant temporal model, the temporal
764 * component will also be written following the syntax
765 *
766 * <source name="..." type="..." instrument="...">
767 * <spectrum type="...">
768 * ...
769 * </spectrum>
770 * <temporal type="...">
771 * ...
772 * </temporal>
773 * </source>
774 *
775 * If no temporal component is found a constant model is assumed.
776 ***************************************************************************/
778{
779 // Initialise pointer on source
780 GXmlElement* src = NULL;
781
782 // Search corresponding source
783 int n = xml.elements("source");
784 for (int k = 0; k < n; ++k) {
785 GXmlElement* element = xml.element("source", k);
786 if (element->attribute("name") == name()) {
787 src = element;
788 break;
789 }
790 }
791
792 // If we have a temporal model that is either not a constant, or a
793 // constant with a normalization value that differs from 1.0 then
794 // write the temporal component into the XML element. This logic
795 // assures compatibility with the Fermi/LAT format as this format
796 // does not handle temporal components.
797 bool write_temporal = ((m_temporal != NULL) &&
798 (m_temporal->type() != "Constant" ||
799 (*m_temporal)[0].value() != 1.0));
800
801 // If no source with corresponding name was found then append one
802 if (src == NULL) {
803 src = xml.append("source");
804 if (spectral() != NULL) src->append(GXmlElement("spectrum"));
805 if (write_temporal) src->append(GXmlElement("temporal"));
806 }
807
808 // Write spectral model
809 if (spectral() != NULL) {
810 GXmlElement* spec = src->element("spectrum", 0);
811 spectral()->write(*spec);
812 }
813
814 // Optionally write temporal model
815 if (write_temporal) {
816 if (dynamic_cast<GModelTemporalConst*>(temporal()) == NULL) {
817 GXmlElement* temp = src->element("temporal", 0);
818 temporal()->write(*temp);
819 }
820 }
821
822 // Write model attributes
823 write_attributes(*src);
824
825 // Return
826 return;
827}
828
829
830/***********************************************************************//**
831 * @brief Print CTA instrument background model information
832 *
833 * @param[in] chatter Chattiness.
834 * @return String containing CTA instrument background model information.
835 ***************************************************************************/
836std::string GCTAModelIrfBackground::print(const GChatter& chatter) const
837{
838 // Initialise result string
839 std::string result;
840
841 // Continue only if chatter is not silent
842 if (chatter != SILENT) {
843
844 // Append header
845 result.append("=== GCTAModelIrfBackground ===");
846
847 // Determine number of parameters per type
848 int n_spectral = (spectral() != NULL) ? spectral()->size() : 0;
849 int n_temporal = (temporal() != NULL) ? temporal()->size() : 0;
850
851 // Append attributes
852 result.append("\n"+print_attributes());
853
854 // Append model type
855 result.append("\n"+gammalib::parformat("Model type"));
856 if (n_spectral > 0) {
857 result.append("\""+spectral()->type()+"\"");
858 if (n_temporal > 0) {
859 result.append(" * ");
860 }
861 }
862 if (n_temporal > 0) {
863 result.append("\""+temporal()->type()+"\"");
864 }
865
866 // Append parameters
867 result.append("\n"+gammalib::parformat("Number of parameters") +
869 result.append("\n"+gammalib::parformat("Number of spectral par's") +
870 gammalib::str(n_spectral));
871 for (int i = 0; i < n_spectral; ++i) {
872 result.append("\n"+(*spectral())[i].print());
873 }
874 result.append("\n"+gammalib::parformat("Number of temporal par's") +
875 gammalib::str(n_temporal));
876 for (int i = 0; i < n_temporal; ++i) {
877 result.append("\n"+(*temporal())[i].print());
878 }
879
880 } // endif: chatter was not silent
881
882 // Return result
883 return result;
884}
885
886
887/*==========================================================================
888 = =
889 = Private methods =
890 = =
891 ==========================================================================*/
892
893/***********************************************************************//**
894 * @brief Initialise class members
895 ***************************************************************************/
897{
898 // Initialise members
899 m_spectral = NULL;
900 m_temporal = NULL;
901
902 // Initialise Npred cache
903 m_npred_names.clear();
904 m_npred_energies.clear();
905 m_npred_times.clear();
906 m_npred_values.clear();
907
908 // Return
909 return;
910}
911
912
913/***********************************************************************//**
914 * @brief Copy class members
915 *
916 * @param[in] bgd CTA background model.
917 ***************************************************************************/
919{
920 // Copy cache
925
926 // Clone spectral and temporal model components
927 m_spectral = (bgd.m_spectral != NULL) ? bgd.m_spectral->clone() : NULL;
928 m_temporal = (bgd.m_temporal != NULL) ? bgd.m_temporal->clone() : NULL;
929
930 // Set parameter pointers
931 set_pointers();
932
933 // Return
934 return;
935}
936
937
938/***********************************************************************//**
939 * @brief Delete class members
940 ***************************************************************************/
942{
943 // Free memory
944 if (m_spectral != NULL) delete m_spectral;
945 if (m_temporal != NULL) delete m_temporal;
946
947 // Signal free pointers
948 m_spectral = NULL;
949 m_temporal = NULL;
950
951 // Return
952 return;
953}
954
955
956/***********************************************************************//**
957 * @brief Set pointers
958 *
959 * Set pointers to all model parameters. The pointers are stored in a vector
960 * that is member of the GModelData base class.
961 ***************************************************************************/
963{
964 // Clear parameters
965 m_pars.clear();
966
967 // Determine the number of parameters
968 int n_spectral = (spectral() != NULL) ? spectral()->size() : 0;
969 int n_temporal = (temporal() != NULL) ? temporal()->size() : 0;
970 int n_pars = n_spectral + n_temporal;
971
972 // Continue only if there are parameters
973 if (n_pars > 0) {
974
975 // Gather spectral parameters
976 for (int i = 0; i < n_spectral; ++i) {
977 m_pars.push_back(&((*spectral())[i]));
978 }
979
980 // Gather temporal parameters
981 for (int i = 0; i < n_temporal; ++i) {
982 m_pars.push_back(&((*temporal())[i]));
983 }
984
985 }
986
987 // Return
988 return;
989}
990
991
992/***********************************************************************//**
993 * @brief Verifies if model has all components
994 *
995 * Returns 'true' if models has a spectral and a temporal component.
996 * Otherwise returns 'false'.
997 ***************************************************************************/
999{
1000 // Set result
1001 bool result = ((spectral() != NULL) && (temporal() != NULL));
1002
1003 // Return result
1004 return result;
1005}
1006
1007
1008/***********************************************************************//**
1009 * @brief Return pointer to spectral model from XML element
1010 *
1011 * @param[in] spectral XML element.
1012 * @return Pointer to spectral model.
1013 *
1014 * Returns pointer to spectral model that is defined in an XML element.
1015 ***************************************************************************/
1017{
1018 // Get spectral model
1019 GModelSpectralRegistry registry;
1020 GModelSpectral* ptr = registry.alloc(spectral);
1021
1022 // Return pointer
1023 return ptr;
1024}
1025
1026
1027/***********************************************************************//**
1028 * @brief Return pointer to temporal model from XML element
1029 *
1030 * @param[in] temporal XML element.
1031 * @return Pointer to temporal model.
1032 *
1033 * Returns pointer to temporal model that is defined in an XML element.
1034 ***************************************************************************/
1036{
1037 // Get temporal model
1038 GModelTemporalRegistry registry;
1039 GModelTemporal* ptr = registry.alloc(temporal);
1040
1041 // Return pointer
1042 return ptr;
1043}
1044
1045
1046/***********************************************************************//**
1047 * @brief Kernel for offset angle integration of background model
1048 *
1049 * @param[in] theta Offset angle from ROI centre (radians).
1050 *
1051 * Computes
1052 *
1053 * \f[
1054 * K(\rho | E, t) = \sin \theta \times
1055 * \int_{0}^{2\pi}
1056 * B(\theta,\phi | E, t) d\phi
1057 * \f]
1058 *
1059 * where \f$B(\theta,\phi | E, t)\f$ is the background model for a specific
1060 * observed energy \f$E\f$ and time \f$t\f$.
1061 ***************************************************************************/
1063{
1064 // Initialise value
1065 double value = 0.0;
1066
1067 // Continue only if offset angle is positive
1068 if (theta > 0.0) {
1069
1070 // Setup phi integration kernel
1072 m_logE,
1074 theta);
1075
1076 // Setup integration
1077 GIntegral integral(&integrand);
1078
1079 // Set fixed number of iterations
1080 integral.fixed_iter(m_iter);
1081
1082 // Integrate over phi
1083 value = integral.romberg(0.0, gammalib::twopi) * std::sin(theta);
1084
1085 // Debug: Check for NaN
1086 #if defined(G_NAN_CHECK)
1087 if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
1088 std::string origin = "GCTAModelIrfBackground::npred_roi_kern_theta::eval"
1089 "(" + gammalib::str(theta) + ")";
1090 std::string message = " NaN/Inf encountered (value=" +
1091 gammalib::str(value) + ")";
1092 gammalib::warning(origin, message);
1093 }
1094 #endif
1095
1096 } // endif: offset angle was positive
1097
1098 // Return value
1099 return value;
1100}
1101
1102
1103/***********************************************************************//**
1104 * @brief Kernel for azimuth angle integration of background model
1105 *
1106 * @param[in] phi Azimuth angle around ROI centre (radians).
1107 *
1108 * Computes
1109 *
1110 * \f[
1111 * B(\theta, \phi | E, t)
1112 * \f]
1113 *
1114 * using
1115 *
1116 * \f[ {\rm detx} = \theta \cos \phi \f]
1117 * \f[ {\rm dety} = \theta \sin \phi \f]
1118 *
1119 * @todo Verify correct orientation of detx and dety with respect to phi
1120 ***************************************************************************/
1122{
1123 // Compute detx and dety in radians
1124 double detx = m_roi_centre.detx();
1125 double dety = m_roi_centre.dety();
1126 if (m_theta > 0.0 ) {
1127 detx += m_theta * std::cos(phi);
1128 dety += m_theta * std::sin(phi);
1129 }
1130
1131 // Get background value
1132 double value = (*m_bgd)(m_logE, detx, dety);
1133
1134 // Debug: Check for NaN
1135 #if defined(G_NAN_CHECK)
1136 if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
1137 std::string origin = "GCTAModelIrfBackground::npred_roi_kern_phi::eval"
1138 "(" + gammalib::str(phi) + ")";
1139 std::string message = " NaN/Inf encountered (value=" +
1140 gammalib::str(value) + ", detx=" +
1141 gammalib::str(detx) + ", dety=" +
1142 gammalib::str(dety) + ")";
1143 gammalib::warning(origin, message);
1144 }
1145 #endif
1146
1147 // Return Npred
1148 return value;
1149}
CTA background model base class definition.
CTA event bin class interface definition.
const GCTAModelIrfBackground g_cta_inst_background_seed
CTA IRF background model class definition.
CTA observation class interface definition.
CTA instrument response function class definition.
Definition of support function used by CTA classes.
Integration class interface definition.
Mathematical function definitions.
#define G_EVAL
Model registry class definition.
#define G_NPRED
Definition GModelSky.cpp:60
Spectral nodes model class definition.
Spectral model registry class definition.
Constant temporal model class interface definition.
Temporal model registry 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:864
Abstract base class for the CTA background model.
virtual GCTAInstDir mc(const GEnergy &energy, const GTime &time, GRan &ran) const =0
virtual const GModelSpectralNodes & spectrum(void) const =0
virtual double rate_ebin(const GCTAInstDir &dir, const GEnergy &emin, const GEnergy &emax) const =0
CTA event atom class.
const GCTAInstDir & dir(void) const
Return instrument direction.
GCTAEventBin class interface definition.
const GEnergy & ewidth(void) const
Return energy width of event bin.
GEnergy emin(void) const
Return minimum energy of event bin.
CTA event list class.
virtual void roi(const GRoi &roi)
Set ROI.
void reserve(const int &number)
Reserves space for events.
void append(const GCTAEventAtom &event)
Append event to event list.
CTA instrument direction class.
void dir(const GSkyDir &dir)
Set sky direction.
void dety(const double &y)
Set DETY coordinate (in radians)
void detx(const double &x)
Set DETX coordinate (in radians)
double eval(const double &phi)
Kernel for azimuth angle integration of background model.
double eval(const double &theta)
Kernel for offset angle integration of background model.
const GCTABackground * m_bgd
Pointer to background.
CTA IRF background model class.
virtual double eval(const GEvent &event, const GObservation &obs, const bool &gradients=false) const
Return background rate in units of events MeV s sr .
GModelTemporal * xml_temporal(const GXmlElement &temporal) const
Return pointer to temporal model from XML element.
virtual double npred(const GEnergy &obsEng, const GTime &obsTime, const GObservation &obs) const
Return spatially integrated background rate in units of events MeV s .
virtual void write(GXmlElement &xml) const
Write CTA instrument background model into XML element.
GCTAModelIrfBackground & operator=(const GCTAModelIrfBackground &bgd)
Assignment operator.
GModelTemporal * temporal(void) const
Return temporal model component.
std::vector< GTime > m_npred_times
Model time.
GModelTemporal * m_temporal
Temporal model.
std::vector< double > m_npred_values
Model values.
GModelSpectral * m_spectral
Spectral model.
GCTAModelIrfBackground(void)
Void constructor.
void set_pointers(void)
Set pointers.
GModelSpectral * xml_spectral(const GXmlElement &spectral) const
Return pointer to spectral model from XML element.
void free_members(void)
Delete class members.
bool valid_model(void) const
Verifies if model has all components.
virtual GCTAEventList * mc(const GObservation &obs, GRan &ran) const
Return simulated list of events.
GModelSpectral * spectral(void) const
Return spectral model component.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print CTA instrument background model information.
void init_members(void)
Initialise class members.
virtual void clear(void)
Clear CTA instrument background model.
virtual ~GCTAModelIrfBackground(void)
Destructor.
virtual void read(const GXmlElement &xml)
Read CTA instrument background model from XML element.
std::vector< GEnergy > m_npred_energies
Model energy.
std::vector< std::string > m_npred_names
Model names.
virtual GCTAModelIrfBackground * clone(void) const
Clone CTA instrument background model.
void copy_members(const GCTAModelIrfBackground &bgd)
Copy class members.
CTA pointing class.
GCTAInstDir instdir(const GSkyDir &skydir) const
Get instrument direction from sky direction.
GSkyDir skydir(const GCTAInstDir &instdir) const
Get sky direction direction from instrument direction.
Interface for the CTA region of interest class.
Definition GCTARoi.hpp:49
Energy boundaries container class.
Definition GEbounds.hpp:60
const GEnergy & emax(void) const
Return maximum energy of all intervals.
Definition GEbounds.hpp:199
int size(void) const
Return number of energy boundaries.
Definition GEbounds.hpp:163
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Definition GEbounds.hpp:187
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
double log10TeV(void) const
Return log10 of energy in TeV.
Definition GEnergy.cpp:457
double MeV(void) const
Return energy in MeV.
Definition GEnergy.cpp:321
Abstract interface for the event classes.
Definition GEvent.hpp:71
virtual bool is_atom(void) const =0
virtual const GEnergy & energy(void) const =0
virtual const GTime & time(void) const =0
void gti(const GGti &gti)
Set Good Time Intervals.
Definition GEvents.cpp:154
void ebounds(const GEbounds &ebounds)
Set energy boundaries.
Definition GEvents.cpp:136
Good Time Interval class.
Definition GGti.hpp:62
const GTime & tstop(void) const
Returns latest stop time in Good Time Intervals.
Definition GGti.hpp:207
int size(void) const
Return number of Good Time Intervals.
Definition GGti.hpp:154
const GTime & tstart(void) const
Returns earliest start time in Good Time Intervals.
Definition GGti.hpp:194
GIntegral class interface definition.
Definition GIntegral.hpp:46
double romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
void fixed_iter(const int &iter)
Set fixed number of iterations.
Abstract data model class.
void init_members(void)
Initialise class members.
void free_members(void)
Delete class members.
virtual GModelData & operator=(const GModelData &model)
Assignment operator.
Interface definition for the model registry class.
Spectral nodes model class.
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 std::string type(void) const =0
int size(void) const
Return number of parameters.
Constant temporal model class.
virtual GModelTemporalConst * clone(void) const
Clone constant temporal model.
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
std::vector< GModelPar * > m_pars
Pointers to all model parameters.
Definition GModel.hpp:178
void write_attributes(GXmlElement &xml) const
Write model attributes.
Definition GModel.cpp:723
std::string print_attributes(void) const
Print model attributes.
Definition GModel.cpp:770
int size(void) const
Return number of parameters in model.
Definition GModel.hpp:233
void read_attributes(const GXmlElement &xml)
Read model attributes.
Definition GModel.cpp:684
const std::string & name(void) const
Return parameter name.
Definition GModel.hpp:261
Abstract observation base class.
virtual std::string instrument(void) const =0
void id(const std::string &id)
Set observation identifier.
Random number generator class.
Definition GRan.hpp:44
Sky direction class.
Definition GSkyDir.hpp:62
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
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: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
const GCTAPointing & cta_pnt(const std::string &origin, const GObservation &obs)
Retrieve CTA pointing from generic observation.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
const GCTAInstDir & cta_dir(const std::string &origin, const GEvent &event)
Retrieve CTA instrument direction from generic event.
const GCTABackground & cta_rsp_bkg(const std::string &origin, const GObservation &obs)
Retrieve CTA background response from generic observation.
const GCTAEventList & cta_event_list(const std::string &origin, const GObservation &obs)
Retrieve CTA event list from generic observation.
const double deg2rad
Definition GMath.hpp:43
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition GTools.cpp:1386
const double twopi
Definition GMath.hpp:36