GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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"
37 #include "GModelTemporalConst.hpp"
38 #include "GModelSpectralNodes.hpp"
40 #include "GCTAObservation.hpp"
41 #include "GCTAResponseIrf.hpp"
42 #include "GCTABackground.hpp"
43 #include "GCTAEventBin.hpp"
44 #include "GCTASupport.hpp"
45 
46 /* __ Globals ____________________________________________________________ */
48 const 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
83  init_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
156  m_spectral = spectral.clone();
157  m_temporal = temporal.clone();
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();
251  this->GModelData::free_members();
252 
253  // Initialise members
254  this->GModelData::init_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  ***************************************************************************/
268 {
269  return new GCTAModelIrfBackground(*this);
270 }
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);
349  const GCTABackground& bgd = gammalib::cta_rsp_bkg(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) {
450  npred = m_npred_values[i];
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);
473  const GCTABackground& bgd = gammalib::cta_rsp_bkg(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)
510  if (gammalib::is_notanumber(npred) || gammalib::is_infinite(npred)) {
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
726  m_spectral = xml_spectral(*spectral);
727 
728  // Optionally get temporal model
729  if (xml.elements("temporal")) {
730  const GXmlElement* temporal = xml.element("temporal", 0);
731  m_temporal = xml_temporal(*temporal);
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  ***************************************************************************/
836 std::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") +
868  gammalib::str(size()));
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,
1073  m_roi_centre,
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 }
void copy_members(const GCTAModelIrfBackground &bgd)
Copy class members.
virtual void write(GXmlElement &xml) const =0
CTA background model base class definition.
const GCTABackground * m_bgd
Pointer to background.
Constant temporal model class interface definition.
std::vector< GEnergy > m_npred_energies
Model energy.
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 * m_temporal
Temporal model.
std::vector< GTime > m_npred_times
Model time.
virtual GCTAEventList * mc(const GObservation &obs, GRan &ran) const
Return simulated list of events.
GEnergy emin(void) const
Return minimum energy of event bin.
#define G_EVAL
virtual GTimes mc(const double &rate, const GTime &tmin, const GTime &tmax, GRan &ran) const =0
virtual GEnergy mc(const GEnergy &emin, const GEnergy &emax, const GTime &time, GRan &ran) const =0
double norm(const GVector &vector)
Computes vector norm.
Definition: GVector.cpp:864
double romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
Definition: GIntegral.cpp:382
void detx(const double &x)
Set DETX coordinate (in radians)
const GCTAInstDir & cta_dir(const std::string &origin, const GEvent &event)
Retrieve CTA instrument direction from generic event.
int size(void) const
Return number of times.
Definition: GTimes.hpp:100
std::string print_attributes(void) const
Print model attributes.
Definition: GModel.cpp:770
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition: GTools.cpp:1386
Abstract spectral model base class.
Interface definition for the model registry class.
virtual std::string instrument(void) const =0
CTA IRF background model class.
CTA IRF background model class definition.
Abstract temporal model base class.
virtual void roi(const GRoi &roi)
Set ROI.
GSkyDir skydir(const GCTAInstDir &instdir) const
Get sky direction direction from instrument direction.
virtual std::string type(void) const
Return data model type.
int size(void) const
Return number of parameters.
void ebounds(const GEbounds &ebounds)
Set energy boundaries.
Definition: GEvents.cpp:136
virtual GCTAModelIrfBackground * clone(void) const
Clone CTA instrument background model.
int size(void) const
Return number of energy boundaries.
Definition: GEbounds.hpp:163
GCTAEventBin class interface definition.
GVector cos(const GVector &vector)
Computes cosine of vector elements.
Definition: GVector.cpp:1190
virtual double eval(const GEnergy &srcEng, const GTime &srcTime=GTime(), const bool &gradients=false) const =0
CTA event bin class interface definition.
void append(const GCTAEventAtom &event)
Append event to event list.
GCTAModelIrfBackground(void)
Void constructor.
CTA instrument response function class definition.
const GCTAPointing & cta_pnt(const std::string &origin, const GObservation &obs)
Retrieve CTA pointing from generic observation.
Abstract interface for the event classes.
Definition: GEvent.hpp:71
CTA event list class.
XML element node class.
Definition: GXmlElement.hpp:48
void gti(const GGti &gti)
Set Good Time Intervals.
Definition: GEvents.cpp:154
void free_members(void)
Delete class members.
Definition: GModelData.cpp:300
Spectral model registry class definition.
GModelTemporal * xml_temporal(const GXmlElement &temporal) const
Return pointer to temporal model from XML element.
virtual void write(GXmlElement &xml) const =0
double log10TeV(void) const
Return log10 of energy in TeV.
Definition: GEnergy.cpp:457
Random number generator class.
Definition: GRan.hpp:44
virtual const GModelSpectralNodes & spectrum(void) const =0
Spectral nodes model class definition.
bool valid_model(void) const
Verifies if model has all components.
double MeV(void) const
Return energy in MeV.
Definition: GEnergy.cpp:321
Interface for the CTA region of interest class.
Definition: GCTARoi.hpp:49
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition: GXmlNode.cpp:586
double eval(const double &theta)
Kernel for offset angle integration of background model.
Time class.
Definition: GTime.hpp:55
Gammalib tools definition.
GIntegral class interface definition.
Definition: GIntegral.hpp:46
virtual GModelTemporalConst * clone(void) const
Clone constant temporal model.
void free_members(void)
Delete class members.
virtual const GTime & time(void) const =0
void init_members(void)
Initialise class members.
const GCTABackground & cta_rsp_bkg(const std::string &origin, const GObservation &obs)
Retrieve CTA background response from generic observation.
void dir(const GSkyDir &dir)
Set sky direction.
void set_pointers(void)
Set pointers.
int size(void) const
Return number of Good Time Intervals.
Definition: GGti.hpp:154
#define G_NPRED
Spectral nodes model class.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print CTA instrument background model information.
void id(const std::string &id)
Set observation identifier.
Time container class.
Definition: GTimes.hpp:45
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition: GTools.hpp:201
std::vector< GModelPar * > m_pars
Pointers to all model parameters.
Definition: GModel.hpp:178
int size(void) const
Return number of parameters in model.
Definition: GModel.hpp:233
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition: GTools.hpp:184
Definition of support function used by CTA classes.
const double deg2rad
Definition: GMath.hpp:43
GCTAModelIrfBackground & operator=(const GCTAModelIrfBackground &bgd)
Assignment operator.
const GEnergy & ewidth(void) const
Return energy width of event bin.
Energy boundaries container class.
Definition: GEbounds.hpp:60
const GXmlAttribute * attribute(const int &index) const
Return attribute.
const std::string & name(void) const
Return parameter name.
Definition: GModel.hpp:261
void reserve(const int &number)
Reserves space for events.
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Definition: GEbounds.hpp:187
virtual void write(GXmlElement &xml) const
Write CTA instrument background model into XML element.
int size(void) const
Return number of parameters.
GCTAInstDir instdir(const GSkyDir &skydir) const
Get instrument direction from sky direction.
GModelTemporal * alloc(const GXmlElement &xml) const
Allocate temporal model that is found in XML element.
virtual const GEnergy & energy(void) const =0
virtual ~GCTAModelIrfBackground(void)
Destructor.
CTA pointing class.
Abstract data model class.
Definition: GModelData.hpp:55
const GCTAEventList & cta_event_list(const std::string &origin, const GObservation &obs)
Retrieve CTA event list from generic observation.
GModelSpectral * alloc(const GXmlElement &xml) const
Allocate spectral model that is found in XML element.
virtual GModelData & operator=(const GModelData &model)
Assignment operator.
Definition: GModelData.cpp:125
GChatter
Definition: GTypemaps.hpp:33
std::vector< double > m_npred_values
Model values.
GModelSpectral * spectral(void) const
Return spectral model component.
Good Time Interval class.
Definition: GGti.hpp:62
virtual double eval(const GTime &srcTime, const bool &gradients=false) const =0
Abstract observation base class.
const GTime & tstop(void) const
Returns latest stop time in Good Time Intervals.
Definition: GGti.hpp:207
const GTime & tstart(void) const
Returns earliest start time in Good Time Intervals.
Definition: GGti.hpp:194
#define G_MC
CTA observation class interface definition.
virtual void clear(void)
Clear CTA instrument background model.
Interface definition for the spectral model registry class.
Interface definition for the temporal model registry class.
void write_attributes(GXmlElement &xml) const
Write model attributes.
Definition: GModel.cpp:723
virtual GModelSpectral * clone(void) const =0
Clones object.
GModelSpectral * xml_spectral(const GXmlElement &spectral) const
Return pointer to spectral model from XML element.
GModelTemporal * temporal(void) const
Return temporal model component.
virtual std::string type(void) const =0
int iter_phi(const double &rho, const double &resolution, const int &iter_min, const int &iter_max)
Determine number of azimuthal Romberg iterations.
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition: GXmlNode.cpp:640
virtual bool is_atom(void) const =0
Temporal model registry class definition.
const GCTAModelCubeBackground g_cta_inst_background_seed
virtual void read(const GXmlElement &xml)
Read CTA instrument background model from XML element.
CTA event atom class.
GVector sin(const GVector &vector)
Computes sine of vector elements.
Definition: GVector.cpp:1316
double eval(const double &phi)
Kernel for azimuth angle integration of background model.
Abstract base class for the CTA background model.
void fixed_iter(const int &iter)
Set fixed number of iterations.
Definition: GIntegral.hpp:189
GModelSpectral * m_spectral
Spectral model.
virtual GModelTemporal * clone(void) const =0
Clones object.
void read_attributes(const GXmlElement &xml)
Read model attributes.
Definition: GModel.cpp:684
CTA instrument direction class.
Definition: GCTAInstDir.hpp:63
virtual GCTAInstDir mc(const GEnergy &energy, const GTime &time, GRan &ran) const =0
void dety(const double &y)
Set DETY coordinate (in radians)
const double twopi
Definition: GMath.hpp:36
const GEnergy & emax(void) const
Return maximum energy of all intervals.
Definition: GEbounds.hpp:199
virtual double flux(const GEnergy &emin, const GEnergy &emax) const =0
Model registry class definition.
std::vector< std::string > m_npred_names
Model names.
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition: GXmlNode.cpp:287
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
virtual double npred(const GEnergy &obsEng, const GTime &obsTime, const GObservation &obs) const
Return spatially integrated background rate in units of events MeV s .
Integration class interface definition.
Sky direction class.
Definition: GSkyDir.hpp:62
virtual double rate_ebin(const GCTAInstDir &dir, const GEnergy &emin, const GEnergy &emax) const =0
void init_members(void)
Initialise class members.
Definition: GModelData.cpp:278
Constant temporal model class.
const GCTAInstDir & dir(void) const
Return instrument direction.
Mathematical function definitions.
Class that handles energies in a unit independent way.
Definition: GEnergy.hpp:48
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489