GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GCTAModelSpatialMultiplicative.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GCTAModelSpatialMultiplicative.cpp - Multiplicative spatial model class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2018 by Jurgen Knodlseder *
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 GCTAModelSpatialMultiplicative.cpp
23  * @brief Multiplicative spatial model class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cmath>
32 #include "GException.hpp"
33 #include "GTools.hpp"
34 #include "GMath.hpp"
35 #include "GRan.hpp"
36 #include "GEnergy.hpp"
37 #include "GTime.hpp"
38 #include "GXmlElement.hpp"
39 #include "GCTAObservation.hpp"
40 #include "GCTAInstDir.hpp"
41 #include "GCTARoi.hpp"
44 
45 /* __ Constants __________________________________________________________ */
46 
47 /* __ Globals ____________________________________________________________ */
49 const GCTAModelSpatialRegistry g_cta_spatial_multi_registry(&g_cta_spatial_multi_seed);
50 
51 /* __ Method name definitions ____________________________________________ */
52 #define G_READ "GCTAModelSpatialMultiplicative::read(GXmlElement&)"
53 #define G_WRITE "GCTAModelSpatialMultiplicative::write(GXmlElement&)"
54 #define G_COMPONENT_INDEX "GCTAModelSpatialMultiplicative::component(int&)"
55 #define G_COMPONENT_NAME "GCTAModelSpatialMultiplicative::component"\
56  "(std::string&)"
57 #define G_APPEND "GCTAModelSpatialMultiplicative::append(GCTAModelSpatial&, "\
58  "std::string&)"
59 
60 /* __ Macros _____________________________________________________________ */
61 
62 /* __ Coding definitions _________________________________________________ */
63 
64 /* __ Debug definitions __________________________________________________ */
65 
66 
67 /*==========================================================================
68  = =
69  = Constructors/destructors =
70  = =
71  ==========================================================================*/
72 
73 /***********************************************************************//**
74  * @brief Void constructor
75  ***************************************************************************/
78 {
79  // Initialise members
80  init_members();
81 
82  // Return
83  return;
84 }
85 
86 
87 /***********************************************************************//**
88  * @brief XML constructor
89  *
90  * @param[in] xml XML element.
91  *
92  * Creates instance of a multiplicative spatial model by extracting
93  * information from an XML element.
94  * See GCTAModelSpatialMultiplicative::read() for more information about the
95  * expected structure of the XML element.
96  ***************************************************************************/
99 {
100  // Initialise members
101  init_members();
102 
103  // Read information from XML element
104  read(xml);
105 
106  // Return
107  return;
108 }
109 
110 
111 /***********************************************************************//**
112  * @brief Copy constructor
113  *
114  * @param[in] model Spatial model.
115  ***************************************************************************/
118 {
119  // Initialise members
120  init_members();
121 
122  // Copy members
123  copy_members(model);
124 
125  // Return
126  return;
127 }
128 
129 
130 /***********************************************************************//**
131  * @brief Destructor
132  ***************************************************************************/
134 {
135  // Free members
136  free_members();
137 
138  // Return
139  return;
140 }
141 
142 
143 /*==========================================================================
144  = =
145  = Operators =
146  = =
147  ==========================================================================*/
148 
149 /***********************************************************************//**
150  * @brief Assignment operator
151  *
152  * @param[in] model Spatial model.
153  ***************************************************************************/
155 {
156  // Execute only if object is not identical
157  if (this != &model) {
158 
159  // Copy base class members
160  this->GCTAModelSpatial::operator=(model);
161 
162  // Free members
163  free_members();
164 
165  // Initialise members
166  init_members();
167 
168  // Copy members
169  copy_members(model);
170 
171  } // endif: object was not identical
172 
173  // Return
174  return *this;
175 }
176 
177 
178 /*==========================================================================
179  = =
180  = Public methods =
181  = =
182  ==========================================================================*/
183 
184 /***********************************************************************//**
185  * @brief Clear instance
186  ***************************************************************************/
188 {
189  // Free class members (base and derived classes, derived class first)
190  free_members();
192 
193  // Initialise members
195  init_members();
196 
197  // Return
198  return;
199 }
200 
201 
202 /***********************************************************************//**
203  * @brief Clone instance
204  ***************************************************************************/
206 {
207  return new GCTAModelSpatialMultiplicative(*this);
208 }
209 
210 
211 /***********************************************************************//**
212  * @brief Evaluate function (in units of sr^-1)
213  *
214  * @param[in] dir Event direction.
215  * @param[in] energy Event energy.
216  * @param[in] time Event time.
217  * @param[in] gradients Compute gradients?
218  * @return Model value
219  *
220  * Evaluate spatial model for a given event direction.
221  ***************************************************************************/
223  const GEnergy& energy,
224  const GTime& time,
225  const bool& gradients) const
226 {
227  // Initialise result
228  double value = 0.0;
229 
230  // Check for available spatial components
231  if (m_spatial.size() > 0) {
232 
233  // Initialise vector of values
234  std::vector<double> values(m_spatial.size(), 0.0);
235 
236  // Compute values of components and function value
237  for (int i = 0; i < m_spatial.size(); ++i) {
238  values[i] = m_spatial[i]->eval(dir, energy, time, gradients);
239  if (i == 0) {
240  value = values[0];
241  }
242  else {
243  value *= values[i];
244  }
245  }
246 
247  // Modify gradients if requested
248  if (gradients) {
249 
250  // Loop over model components
251  for (int i = 0; i < m_spatial.size(); ++i) {
252 
253  // Initialise scaling factor
254  double factor = 1.0;
255 
256  // Loop over other model components and compute factor
257  for (int j = 0; j < m_spatial.size(); ++j) {
258  if (i != j) {
259  factor *= values[j];
260  }
261  }
262 
263  // Loop over model parameters
264  for (int ipar = 0; ipar < m_spatial[i]->size(); ++ipar) {
265 
266  // Get reference to model parameter
267  GModelPar& par = m_spatial[i]->operator[](ipar);
268 
269  // Scale parameter gradient
270  par.gradient(par.gradient()*factor);
271 
272  } // endfor: loop over model parameters
273 
274  } // endfor: loop over models
275 
276  } //endif: compute gradients
277 
278  } // endif: there were spatial components
279 
280  // Compile option: Check for NaN/Inf
281  #if defined(G_NAN_CHECK)
282  if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
283  std::cout << "*** ERROR: GCTAModelSpatialMultiplicative::eval";
284  std::cout << "(dir=" << dir.print();
285  std::cout << ", energy=" << energy;
286  std::cout << ", time=" << time << "):";
287  std::cout << " NaN/Inf encountered";
288  std::cout << " (value=" << value;
289  std::cout << ")" << std::endl;
290  }
291  #endif
292 
293  // Return value
294  return value;
295 }
296 
297 
298 /***********************************************************************//**
299  * @brief Return maximum function value for Monte Carlo simulations
300  *
301  * @param[in] obs CTA Observation.
302  * @return Maximum function value for Monte Carlo simulations.
303  ***************************************************************************/
305 {
306  // Initialise maximum value
307  double value = 1.0;
308 
309  // Compute maximum value from components
310  for (int i = 0; i < m_spatial.size(); ++i) {
311  value *= m_spatial[i]->mc_max_value(obs);
312  }
313 
314  // Return maximum value
315  return value;
316 }
317 
318 
319 /***********************************************************************//**
320  * @brief Read model from XML element
321  *
322  * @param[in] xml XML element.
323  *
324  * Reads the spatial information from an XML element.
325  ***************************************************************************/
327 {
328  // Get number of spatial components
329  int n_spatials = xml.elements("spatialModel");
330 
331  // Loop over spatial elements
332  for (int i = 0; i < n_spatials; ++i) {
333 
334  // Get spatial XML element
335  const GXmlElement* spatial = xml.element("spatialModel", i);
336 
337  // Allocate a spatial registry object
338  GCTAModelSpatialRegistry registry;
339 
340  // Read spatial model
341  GCTAModelSpatial* ptr = registry.alloc(*spatial);
342 
343  // Get component attribute from XML file
344  std::string component_name = spatial->attribute("component");
345 
346  // Append spatial component to container
347  append(*ptr, component_name);
348 
349  // Free spatial model
350  delete ptr;
351 
352  } // endfor: loop over components
353 
354  // Return
355  return;
356 }
357 
358 
359 /***********************************************************************//**
360  * @brief Write model into XML element
361  *
362  * @param[in] xml XML element.
363  *
364  * Writes the spatial information into an XML element.
365  ***************************************************************************/
367 {
368  // Check model type
370 
371  // Loop over model components
372  for (int i = 0; i < m_spatial.size(); i++) {
373 
374  // Write spatial model
375  if (m_spatial[i] != NULL) {
376 
377  // Create new spectrum node
378  xml.append(GXmlElement("spatialModel"));
379 
380  // Get new spatial node
381  GXmlElement* spatial = xml.element("spatialModel",
382  xml.elements("spatialModel")-1);
383 
384  // Create temporary copy of the spatial model. This is a kluge to
385  // write out the original parameters.
386  GCTAModelSpatial* cpy = m_spatial[i]->clone();
387 
388  // Loop over parameters of model
389  for (int j = 0; j < cpy->size(); ++j) {
390 
391  // Get model parameter and name
392  GModelPar& par = (*cpy)[j];
393  std::string parname = par.name();
394 
395  // Check if name contains colon
396  if (gammalib::contains(parname, ":")) {
397 
398  // Split at the colon
399  std::vector<std::string> splits = gammalib::split(parname, ":");
400 
401  // Use second part of the string to recover original
402  // parameter name
403  par.name(splits[1]);
404  }
405 
406  } // endfor: loop over parameters
407 
408  // Write spatial component
409  cpy->write(*spatial);
410 
411  // Add component name if previously available
412  if (m_components[i] != gammalib::str(i+1)) {
413  spatial->attribute("component", m_components[i]);
414  }
415 
416  // Remove temporary copy
417  delete cpy;
418 
419  } // endif: spatial model was not NULL
420 
421  } // endfor: loop over model components
422 
423  // Return
424  return;
425 }
426 
427 
428 /***********************************************************************//**
429  * @brief Append spatial component
430  *
431  * @param[in] spatial Spatial model component.
432  * @param[in] name Name of spatial component (can be empty).
433  *
434  * @exception GException::invalid_value
435  * Invalid component name specified
436  *
437  * Appends a spatial component to the multiplicative model
438  ***************************************************************************/
440  const std::string& name)
441 {
442  // Append model container
443  m_spatial.push_back(spatial.clone());
444 
445  // Get index of latest model
446  int index = m_spatial.size()-1;
447 
448  // Use model index as component name if component name is empty
449  std::string component_name = !name.empty() ? name
450  : gammalib::str(m_spatial.size());
451 
452  // Check if component name is unique, throw exception if not
453  if (gammalib::contains(m_components, component_name)) {
454  std::string msg = "Attempt to append component with name \""+
455  component_name+"\" to multiplicative spatial model "
456  "container, but a component with the same name exists "
457  "already. Every component in the container needs a "
458  "unique name. On default the system will increment "
459  "an integer if no component name is provided.";
461  }
462 
463  // Add component name (for now simple number)
464  m_components.push_back(component_name);
465 
466  // Get number of spatial parameters from model
467  int npars = m_spatial[index]->size();
468 
469  // Loop over model parameters
470  for (int ipar = 0; ipar < npars; ++ipar) {
471 
472  // Get model parameter
473  GModelPar* par = &(m_spatial[index]->operator[](ipar));
474 
475  // Prepend component name to parameter name
476  par->name(component_name+":"+par->name());
477 
478  // Append model parameter with new name to internal container
479  m_pars.push_back(par);
480 
481  } // endfor: loop over model parameters
482 
483  // Return
484  return;
485 }
486 
487 
488 /***********************************************************************//**
489  * @brief Return spatial model component by index
490  *
491  * @param[in] index Index of spectral component.
492  * @return Pointer to spatial model.
493  *
494  * @exception GException::out_of_range
495  * Model index out of valid range
496  *
497  * Returns a component of the multiplicative spatial model by @p index.
498  ***************************************************************************/
500 {
501  // Check if index is in validity range
502  if (index >= m_spatial.size() || index < 0) {
503  throw GException::out_of_range(G_COMPONENT_INDEX, "Component Index",
504  index, m_spatial.size());
505  }
506 
507  // Return spatial component
508  return m_spatial[index];
509 }
510 
511 
512 /***********************************************************************//**
513  * @brief Return spatial model component by name
514  *
515  * @param[in] name Name of spatial component.
516  * @return Pointer to spatial model.
517  *
518  * @exception GException::invalid_argument
519  * Spatial component not found
520  *
521  * Returns a component of the multiplicative spatial model by @p name.
522  ***************************************************************************/
523 const GCTAModelSpatial* GCTAModelSpatialMultiplicative::component(const std::string& name) const
524 {
525  // Check if model name is found
526  int index = -1;
527  for (int i = 0; i < m_components.size(); ++i) {
528  if (m_components[i] == name) {
529  index = i;
530  break;
531  }
532  }
533 
534  // Check if component name was found
535  if (index == -1) {
536  std::string msg = "Model component \""+name+"\" not found in "
537  "multiplicative spatial model.";
539  }
540 
541  // Return spatial component
542  return m_spatial[index];
543 }
544 
545 
546 /***********************************************************************//**
547  * @brief Print multiplicative spatial model information
548  *
549  * @param[in] chatter Chattiness.
550  * @return String containing model information.
551  ***************************************************************************/
552 std::string GCTAModelSpatialMultiplicative::print(const GChatter& chatter) const
553 {
554  // Initialise result string
555  std::string result;
556 
557  // Continue only if chatter is not silent
558  if (chatter != SILENT) {
559 
560  // Append header
561  result.append("=== GCTAModelSpatialMultiplicative ===");
562 
563  // Append information
564  result.append("\n"+gammalib::parformat("Number of components"));
565  result.append(gammalib::str(components()));
566  result.append("\n"+gammalib::parformat("Number of parameters"));
567  result.append(gammalib::str(size()));
568 
569  // Print parameter information
570  for (int i = 0; i < size(); ++i) {
571  result.append("\n"+m_pars[i]->print(chatter));
572  }
573 
574  } // endif: chatter was not silent
575 
576  // Return result
577  return result;
578 }
579 
580 
581 /*==========================================================================
582  = =
583  = Private methods =
584  = =
585  ==========================================================================*/
586 
587 /***********************************************************************//**
588  * @brief Initialise class members
589  ***************************************************************************/
591 {
592  // Initialise model type
593  m_type = "Multiplicative";
594 
595  // Clear spatial models
596  m_spatial.clear();
597  m_components.clear();
598 
599  // Return
600  return;
601 }
602 
603 
604 /***********************************************************************//**
605  * @brief Copy class members
606  *
607  * @param[in] model Spatial background model component.
608  ***************************************************************************/
610 {
611  // Copy members
612  m_type = model.m_type;
613  m_components = model.m_components;
614 
615  // Copy pointer(s) of spatial component
616  m_spatial.clear();
617  for (int i = 0; i < model.components(); ++i) {
618  m_spatial.push_back(model.m_spatial[i]->clone());
619  }
620 
621  // Store pointers to spatial parameters
622  m_pars.clear();
623  for (int i = 0; i < model.components(); ++i) {
624 
625  // Retrieve spatial model
626  GCTAModelSpatial* spatial = m_spatial[i];
627 
628  // Loop over parameters
629  for (int ipar = 0; ipar < spatial->size(); ++ipar) {
630 
631  // Get model parameter reference
632  GModelPar& par = spatial->operator[](ipar);
633 
634  // Append model parameter pointer to internal container
635  m_pars.push_back(&par);
636  }
637  }
638 
639  // Return
640  return;
641 }
642 
643 
644 /***********************************************************************//**
645  * @brief Delete class members
646  ***************************************************************************/
648 {
649  // Free memory
650  for (int i = 0; i < m_spatial.size(); ++i) {
651 
652  // Delete component i
653  if (m_spatial[i] != NULL) delete m_spatial[i];
654 
655  // Signal free pointer
656  m_spatial[i] = NULL;
657 
658  }
659 
660  // Return
661  return;
662 }
const GCTAModelSpatialMultiplicative g_cta_spatial_multi_seed
bool contains(const std::string &str, const std::string &substring)
Checks if a substring is in a string.
Definition: GTools.cpp:1342
void free_members(void)
Delete class members.
Abstract spatial model class.
int components(void) const
Return number of spatial components.
Energy value class definition.
const std::string & name(void) const
Return parameter name.
Random number generator class definition.
XML element node class interface definition.
virtual void clear(void)
Clear instance.
double gradient(void) const
Return parameter gradient.
Multiplicative spatial model class.
virtual void write(GXmlElement &xml) const =0
virtual GCTAModelSpatial & operator=(const GCTAModelSpatial &model)
Assignment operator.
XML element node class.
Definition: GXmlElement.hpp:48
const GCTAModelSpatial * component(const int &index) const
Return spatial model component by index.
virtual double eval(const GCTAInstDir &dir, const GEnergy &energy, const GTime &time, const bool &gradients=false) const
Evaluate function (in units of sr^-1)
void copy_members(const GCTAModelSpatialMultiplicative &model)
Copy class members.
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition: GTools.cpp:983
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition: GXmlNode.cpp:586
Time class.
Definition: GTime.hpp:55
Gammalib tools definition.
virtual void write(GXmlElement &xml) const
Write model into XML element.
virtual double mc_max_value(const GCTAObservation &obs) const
Return maximum function value for Monte Carlo simulations.
Interface definition for the spatial model registry class.
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition: GTools.hpp:201
std::vector< std::string > m_components
Names of components.
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition: GTools.hpp:184
Model parameter class.
Definition: GModelPar.hpp:87
virtual void read(const GXmlElement &xml)
Read model from XML element.
Multiplicative spatial model class interface definition.
void init_members(void)
Initialise class members.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print multiplicative spatial model information.
const GXmlAttribute * attribute(const int &index) const
Return attribute.
void free_members(void)
Delete class members.
virtual GCTAModelSpatialMultiplicative & operator=(const GCTAModelSpatialMultiplicative &model)
Assignment operator.
void init_members(void)
Initialise class members.
CTA instrument direction class interface definition.
virtual GCTAModelSpatialMultiplicative * clone(void) const
Clone instance.
int size(void) const
Return number of model parameters.
virtual ~GCTAModelSpatialMultiplicative(void)
Destructor.
GChatter
Definition: GTypemaps.hpp:33
#define G_COMPONENT_NAME
virtual std::string print(const GChatter &chatter=NORMAL) const
Print instrument direction information.
#define G_COMPONENT_INDEX
CTA region of interest class interface definition.
CTA observation class interface definition.
virtual std::string type(void) const
Return model type.
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition: GXmlNode.cpp:640
void append(const GCTAModelSpatial &spatial, const std::string &name="")
Append spatial component.
GCTAModelSpatialMultiplicative(void)
Void constructor.
Exception handler interface definition.
CTA instrument direction class.
Definition: GCTAInstDir.hpp:63
GCTAModelSpatial * alloc(const GXmlElement &xml) const
Allocate spatial model that is found in XML element.
virtual GCTAModelSpatial * clone(void) const =0
Clones object.
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition: GXmlNode.cpp:287
CTA observation class.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
std::vector< GModelPar * > m_pars
Parameter pointers.
std::vector< GCTAModelSpatial * > m_spatial
Container of spatial models.
Time class interface definition.
Spatial model registry class definition.
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
void xml_check_type(const std::string &origin, GXmlElement &xml, const std::string &type)
Checks the model type.
Definition: GTools.cpp:1819