GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GModels.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GModels.cpp - Model container class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2009-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 GModels.cpp
23  * @brief Model container class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "GTools.hpp"
32 #include "GException.hpp"
33 #include "GFilename.hpp"
34 #include "GModels.hpp"
35 #include "GModel.hpp"
36 #include "GModelRegistry.hpp"
37 #include "GObservation.hpp"
38 #include "GVector.hpp"
39 #include "GMatrixSparse.hpp"
40 #include "GXml.hpp"
41 #include "GXmlElement.hpp"
42 #include "GOptimizerPars.hpp"
43 
44 /* __ Method name definitions ____________________________________________ */
45 #define G_ACCESS "GModels::operator[](std::string&)"
46 #define G_AT "GModels::at(int&)"
47 #define G_SET1 "GModels::set(int&, GModel&)"
48 #define G_SET2 "GModels::set(std::string&, GModel&)"
49 #define G_APPEND "GModels::append(GModel&)"
50 #define G_INSERT1 "GModels::insert(int&, GModel&)"
51 #define G_INSERT2 "GModels::insert(std::string&, GModel&)"
52 #define G_REMOVE1 "GModels::remove(int&)"
53 #define G_REMOVE2 "GModels::remove(std::string&)"
54 #define G_EXTEND "GModels::extend(GModels&)"
55 #define G_READ "GModels::read(GXml&)"
56 
57 /* __ Macros _____________________________________________________________ */
58 
59 /* __ Coding definitions _________________________________________________ */
60 
61 /* __ Debug definitions __________________________________________________ */
62 
63 
64 /*==========================================================================
65  = =
66  = Constructors/destructors =
67  = =
68  ==========================================================================*/
69 
70 /***********************************************************************//**
71  * @brief Void constructor
72  ***************************************************************************/
74 {
75  // Initialise members
76  init_members();
77 
78  // Return
79  return;
80 }
81 
82 
83 /***********************************************************************//**
84  * @brief Copy constructor
85  *
86  * @param[in] models Model container.
87  ***************************************************************************/
88 GModels::GModels(const GModels& models)
89 {
90  // Initialise members
91  init_members();
92 
93  // Copy members
94  copy_members(models);
95 
96  // Return
97  return;
98 }
99 
100 
101 /***********************************************************************//**
102  * @brief Load constructor
103  *
104  * @param[in] filename XML filename.
105  *
106  * Constructs model container from an XML file. See the read() method for
107  * more information about the expected structure of the XML file.
108  ***************************************************************************/
109 GModels::GModels(const GFilename& filename)
110 {
111  // Initialise members
112  init_members();
113 
114  // Load XML file
115  load(filename);
116 
117  // Return
118  return;
119 }
120 
121 
122 /***********************************************************************//**
123  * @brief Destructor
124  ***************************************************************************/
126 {
127  // Free members
128  free_members();
129 
130  // Return
131  return;
132 }
133 
134 
135 /*==========================================================================
136  = =
137  = Operators =
138  = =
139  ==========================================================================*/
140 
141 /***********************************************************************//**
142  * @brief Assignment operator
143  *
144  * @param[in] models Model container.
145  * @return Model container.
146  ***************************************************************************/
148 {
149  // Execute only if object is not identical
150  if (this != &models) {
151 
152  // Free members
153  free_members();
154 
155  // Initialise members
156  init_members();
157 
158  // Copy members
159  copy_members(models);
160 
161  } // endif: object was not identical
162 
163  // Return
164  return *this;
165 }
166 
167 
168 /***********************************************************************//**
169  * @brief Return pointer to model
170  *
171  * @param[in] name Model name.
172  *
173  * @exception GException::invalid_argument
174  * Model with specified name not found in container.
175  *
176  * Returns a pointer to the model with the specified @p name.
177  ***************************************************************************/
178 GModel* GModels::operator[](const std::string& name)
179 {
180  // Get model index
181  int index = get_index(name);
182 
183  // Throw exception if model name was not found
184  if (index == -1) {
185  std::string msg = "Model \""+name+"\" not found in model container. "
186  "Please specify the name of an available model.";
188  }
189 
190  // Return pointer
191  return m_models[index];
192 }
193 
194 
195 /***********************************************************************//**
196  * @brief Return pointer to model (const version)
197  *
198  * @param[in] name Model name.
199  *
200  * @exception GException::invalid_argument
201  * Model with specified name not found in container.
202  *
203  * Returns a const pointer to the model with the specified @p name.
204  ***************************************************************************/
205 const GModel* GModels::operator[](const std::string& name) const
206 {
207  // Get model index
208  int index = get_index(name);
209 
210  // Throw exception if model name was not found
211  if (index == -1) {
212  std::string msg = "Model \""+name+"\" not found in model container. "
213  "Please specify the name of an available model.";
215  }
216 
217  // Return pointer
218  return m_models[index];
219 }
220 
221 
222 /*==========================================================================
223  = =
224  = Public methods =
225  = =
226  ==========================================================================*/
227 
228 /***********************************************************************//**
229  * @brief Clear object
230  *
231  * Removes all models from the container.
232  ***************************************************************************/
233 void GModels::clear(void)
234 {
235  // Free class members (base and derived classes, derived class first)
236  free_members();
237 
238  // Initialise members
239  init_members();
240 
241  // Return
242  return;
243 }
244 
245 
246 /***********************************************************************//**
247  * @brief Clone instance
248  *
249  * @return Pointer to deep copy of model container
250  *
251  * Makes a deep copy of the model container instance.
252  ***************************************************************************/
254 {
255  return new GModels(*this);
256 }
257 
258 
259 /***********************************************************************//**
260  * @brief Return pointer to model
261  *
262  * @param[in] index Model index [0,...,size()-1].
263  *
264  * @exception GException::out_of_range
265  * Model index is out of range.
266  *
267  * Returns a pointer to the model with the specified @p index.
268  ***************************************************************************/
269 GModel* GModels::at(const int& index)
270 {
271  // Compile option: raise an exception if index is out of range
272  #if defined(G_RANGE_CHECK)
273  if (index < 0 || index >= size()) {
274  throw GException::out_of_range(G_AT, "Model index", index, size());
275  }
276  #endif
277 
278  // Return pointer
279  return m_models[index];
280 }
281 
282 
283 /***********************************************************************//**
284  * @brief Return pointer to model (const version)
285  *
286  * @param[in] index Model index [0,...,size()-1].
287  *
288  * @exception GException::out_of_range
289  * Model index is out of range.
290  *
291  * Returns a const pointer to the model with the specified @p index.
292  ***************************************************************************/
293 const GModel* GModels::at(const int& index) const
294 {
295  // Compile option: raise an exception if index is out of range
296  #if defined(G_RANGE_CHECK)
297  if (index < 0 || index >= size()) {
298  throw GException::out_of_range(G_AT, "Model index", index, size());
299  }
300  #endif
301 
302  // Return pointer
303  return m_models[index];
304 }
305 
306 
307 /***********************************************************************//**
308  * @brief Set model in container
309  *
310  * @param[in] index Model index [0,...,size()[.
311  * @param[in] model Model.
312  * @return Pointer to deep copy of model.
313  *
314  * @exception GException::out_of_range
315  * Model index is out of range.
316  * @exception GException::invalid_value
317  * Name of model exists already in container.
318  *
319  * Set model in the container. A deep copy of the model will be made.
320  ***************************************************************************/
321 GModel* GModels::set(const int& index, const GModel& model)
322 {
323  // Compile option: raise exception if index is out of range
324  #if defined(G_RANGE_CHECK)
325  if (index < 0 || index >= size()) {
326  throw GException::out_of_range(G_SET1, "Model index", index, size());
327  }
328  #endif
329 
330  // Check if a model with specified name does not yet exist
331  int inx = get_index(model.name());
332  if (inx != -1 && inx != index) {
333  std::string msg =
334  "Attempt to set model with name \""+model.name()+"\" in model "
335  "container at index "+gammalib::str(index)+", but a model with "
336  "the same name exists already at index "+gammalib::str(inx)+
337  " in the container. Every model in the model container needs a "
338  "unique name.";
339  throw GException::invalid_value(G_SET1, msg);
340  }
341 
342  // Free existing model only if it differs from current model. This
343  // prevents unintential deallocation of the argument
344  if ((m_models[index] != NULL) && (m_models[index] != &model)) {
345  delete m_models[index];
346  }
347 
348  // Assign new model by cloning
349  m_models[index] = model.clone();
350 
351  // Return pointer to model
352  return m_models[index];
353 }
354 
355 
356 /***********************************************************************//**
357  * @brief Set model in container
358  *
359  * @param[in] name Model name.
360  * @param[in] model Model pointer.
361  * @return Pointer to deep copy of model.
362  *
363  * @exception GException::invalid_argument
364  * Model with specified name not found in container.
365  * @exception GException::invalid_value
366  * Name of model exists already in container.
367  *
368  * Set model in the container. A deep copy of the model will be made.
369  ***************************************************************************/
370 GModel* GModels::set(const std::string& name, const GModel& model)
371 {
372  // Get parameter index
373  int index = get_index(name);
374 
375  // Throw exception if parameter name was not found
376  if (index == -1) {
377  std::string msg = "Model \""+name+"\" not found in model container. "
378  "Please specify the name of an available model.";
380  }
381 
382  // Check if a model with specified name does not yet exist
383  int inx = get_index(model.name());
384  if (inx != -1 && inx != index) {
385  std::string msg =
386  "Attempt to set model with name \""+model.name()+"\" in model"
387  " container at index "+gammalib::str(index)+", but a model with"
388  " the same name exists already at index "+gammalib::str(inx)+
389  " in the container.\n"
390  "Every model in the model container needs a unique name.";
391  throw GException::invalid_value(G_SET2, msg);
392  }
393 
394  // Free existing model only if it differs from current model. This
395  // prevents unintential deallocation of the argument
396  if ((m_models[index] != NULL) && (m_models[index] != &model)) {
397  delete m_models[index];
398  }
399 
400  // Assign new model by cloning
401  m_models[index] = model.clone();
402 
403  // Return pointer to model
404  return m_models[index];
405 }
406 
407 
408 /***********************************************************************//**
409  * @brief Append model to container
410  *
411  * @param[in] model Model.
412  * @return Pointer to deep copy of model.
413  *
414  * @exception GException::invalid_value
415  * Name of model exists already in container.
416  *
417  * Appends model to the container by making a deep copy of the model and
418  * storing its pointer.
419  ***************************************************************************/
421 {
422  // Check if a model with specified name does not yet exist
423  int inx = get_index(model.name());
424  if (inx != -1) {
425  std::string msg =
426  "Attempt to append model with name \""+model.name()+"\" to model"
427  " container, but a model with the same name exists already at"
428  " index "+gammalib::str(inx)+" in the container."
429  " Every model in the model container needs a unique name.";
431  }
432 
433  // Create deep copy of model
434  GModel* ptr = model.clone();
435 
436  // Append deep copy of model
437  m_models.push_back(ptr);
438 
439  // Return pointer to model
440  return ptr;
441 }
442 
443 
444 /***********************************************************************//**
445  * @brief Insert model into container
446  *
447  * @param[in] index Model index [0,...,size()[.
448  * @param[in] model Model.
449  * @return Pointer to deep copy of model.
450  *
451  * @exception GException::out_of_range
452  * Model index is out of range.
453  * @exception GException::invalid_value
454  * Name of model exists already in container.
455  *
456  * Inserts a @p model into the container before the model with the specified
457  * @p index.
458  ***************************************************************************/
459 GModel* GModels::insert(const int& index, const GModel& model)
460 {
461  // Compile option: raise exception if index is out of range
462  #if defined(G_RANGE_CHECK)
463  if (is_empty()) {
464  if (index > 0) {
465  throw GException::out_of_range(G_INSERT1, "Model index",
466  index, size());
467  }
468  }
469  else {
470  if (index < 0 || index >= size()) {
471  throw GException::out_of_range(G_INSERT1, "Model index",
472  index, size());
473  }
474  }
475  #endif
476 
477  // Check if a model with specified name does not yet exist
478  int inx = get_index(model.name());
479  if (inx != -1) {
480  std::string msg =
481  "Attempt to insert model with name \""+model.name()+"\" in model"
482  " container before index "+gammalib::str(index)+", but a model"
483  " with the same name exists already at index "+gammalib::str(inx)+
484  " in the container.\n"
485  "Every model in the model container needs a unique name.";
487  }
488 
489  // Create deep copy of model
490  GModel* ptr = model.clone();
491 
492  // Inserts deep copy of model
493  m_models.insert(m_models.begin()+index, ptr);
494 
495  // Return pointer to model
496  return ptr;
497 }
498 
499 
500 /***********************************************************************//**
501  * @brief Insert model into container
502  *
503  * @param[in] name Model name.
504  * @param[in] model Model.
505  * @return Pointer to deep copy of model.
506  *
507  * @exception GException::invalid_argument
508  * Model with specified name not found in container.
509  * @exception GException::invalid_value
510  * Name of model exists already in container.
511  *
512  * Inserts a @p model into the container before the model with the specified
513  * @p name.
514  ***************************************************************************/
515 GModel* GModels::insert(const std::string& name, const GModel& model)
516 {
517  // Get parameter index
518  int index = get_index(name);
519 
520  // Throw exception if parameter name was not found
521  if (index == -1) {
522  std::string msg = "Model \""+name+"\" not found in model container. "
523  "Please specify the name of an available model.";
525  }
526 
527  // Check if a model with specified name does not yet exist
528  int inx = get_index(model.name());
529  if (inx != -1) {
530  std::string msg =
531  "Attempt to insert model with name \""+model.name()+"\" in model"
532  " container before index "+gammalib::str(index)+", but a model"
533  " with the same name exists already at index "+gammalib::str(inx)+
534  " in the container.\n"
535  "Every model in the model container needs a unique name.";
537  }
538 
539  // Create deep copy of model
540  GModel* ptr = model.clone();
541 
542  // Inserts deep copy of model
543  m_models.insert(m_models.begin()+index, ptr);
544 
545  // Return pointer to model
546  return ptr;
547 }
548 
549 
550 /***********************************************************************//**
551  * @brief Remove model from container
552  *
553  * @param[in] index Model index [0,...,size()[.
554  *
555  * @exception GException::out_of_range
556  * Model index is out of range.
557  *
558  * Remove model of specified @p index from container.
559  ***************************************************************************/
560 void GModels::remove(const int& index)
561 {
562  // Compile option: raise exception if index is out of range
563  #if defined(G_RANGE_CHECK)
564  if (index < 0 || index >= size()) {
565  throw GException::out_of_range(G_REMOVE1, "Model index",
566  index, size());
567  }
568  #endif
569 
570  // Delete model
571  delete m_models[index];
572 
573  // Erase model component from container
574  m_models.erase(m_models.begin() + index);
575 
576  // Return
577  return;
578 }
579 
580 
581 /***********************************************************************//**
582  * @brief Remove model from container
583  *
584  * @param[in] name Model name.
585  *
586  * @exception GException::invalid_argument
587  * Model with specified name not found in container.
588  *
589  * Remove model of specified @p name from container.
590  ***************************************************************************/
591 void GModels::remove(const std::string& name)
592 {
593  // Get parameter index
594  int index = get_index(name);
595 
596  // Throw exception if parameter name was not found
597  if (index == -1) {
598  std::string msg = "Model \""+name+"\" not found in model container. "
599  "Please specify the name of an available model.";
601  }
602 
603  // Delete model
604  delete m_models[index];
605 
606  // Erase model component from container
607  m_models.erase(m_models.begin() + index);
608 
609  // Return
610  return;
611 }
612 
613 
614 /***********************************************************************//**
615  * @brief Append model container
616  *
617  * @param[in] models Model container.
618  *
619  * Append model container to the container.
620  ***************************************************************************/
621 void GModels::extend(const GModels& models)
622 {
623  // Do nothing if model container is empty
624  if (!models.is_empty()) {
625 
626  // Get size. Note that we extract the size first to avoid an
627  // endless loop that arises when a container is appended to
628  // itself.
629  int num = models.size();
630 
631  // Reserve enough space
632  reserve(size() + num);
633 
634  // Loop over all model components and append pointers to deep copies
635  for (int i = 0; i < num; ++i) {
636 
637  // Check if model name does not yet exist
638  int inx = get_index(models[i]->name());
639  if (inx != -1) {
640  std::string msg =
641  "Attempt to append model with name \""+models[i]->name()+
642  "\" to model container, but a model with the same name"
643  " exists already at index "+gammalib::str(inx)+" in the"
644  " container.\n"
645  "Every model in the model container needs a unique name.";
647  }
648 
649  // Append model to container
650  m_models.push_back(models[i]->clone());
651 
652  } // endfor: looped over all models
653 
654  } // endif: model container was not empty
655 
656  // Return
657  return;
658 }
659 
660 
661 /***********************************************************************//**
662  * @brief Signals if model name exists
663  *
664  * @param[in] name Model name.
665  * @return True if model with specified @p name exists.
666  *
667  * Searches all model names for a match with the specified @p name. If the
668  * specified name has been found, true is returned.
669  ***************************************************************************/
670 bool GModels::contains(const std::string& name) const
671 {
672  // Get model index
673  int index = get_index(name);
674 
675  // Return
676  return (index != -1);
677 }
678 
679 
680 /***********************************************************************//**
681  * @brief Load models from XML file
682  *
683  * @param[in] filename XML filename.
684  *
685  * Loads all models from an XML file. See the read() method for more
686  * information about the expected structure of the XML file.
687  ***************************************************************************/
688 void GModels::load(const GFilename& filename)
689 {
690  // Clear any existing models
691  clear();
692 
693  // Load XML document
694  GXml xml(filename.url());
695 
696  // Read models from XML document
697  read(xml);
698 
699  // Return
700  return;
701 }
702 
703 
704 /***********************************************************************//**
705  * @brief Save models into XML file
706  *
707  * @param[in] filename XML filename.
708  *
709  * Saves all models in the container into an XML file.
710  ***************************************************************************/
711 void GModels::save(const GFilename& filename) const
712 {
713  // Declare empty XML document
714  GXml xml;
715 
716  // Append source library element
717  GXmlNode* lib =
718  xml.append(GXmlElement("source_library title=\"source library\""));
719 
720  // Write all sources into library.
721  for (int i = 0; i < size(); ++i) {
722 
723  // Allocate XML element
724  GXmlElement source;
725 
726  // Write model into XML element
727  m_models[i]->write(source);
728 
729  // Append source to source library. Since write appends only a
730  // single source we can just access the first element in the
731  // source node.
732  lib->append(*source.element(0));
733 
734  } // endfor: looped over sources
735 
736  // Write models into XML file
737  //write(xml);
738 
739  // Save XML document
740  xml.save(filename);
741 
742  // Return
743  return;
744 }
745 
746 
747 /***********************************************************************//**
748  * @brief Read models from XML document
749  *
750  * @param[in] xml XML document.
751  *
752  * @exception GException::invalid_value
753  * Invalid model type encountered.
754  *
755  * Read models from the first source library found in the XML document. The
756  * XML document is expected to have the following structure
757  *
758  * <source_library title="source library">
759  * <source name="Source1" type="PointSource">
760  * ...
761  * </source>
762  * <source name="Source2" type="DiffuseSource">
763  * ...
764  * </source>
765  * </source_library>
766  *
767  * Each @p source tag will be interpreted as a model component.
768  *
769  * @todo Sources names are not verified so far for uniqueness. This would be
770  * required to achieve an unambiguous update of parameters in an already
771  * existing XML file when using the write method.
772  ***************************************************************************/
773 void GModels::read(const GXml& xml)
774 {
775  // Get pointer on source library
776  const GXmlElement* lib = xml.element("source_library", 0);
777 
778  // Loop over all sources
779  int n = lib->elements("source");
780  for (int i = 0; i < n; ++i) {
781 
782  // Get pointer on source
783  const GXmlElement* src = lib->element("source", i);
784 
785  // Get model type
786  std::string type = src->attribute("type");
787 
788  // Get model
789  GModelRegistry registry;
790  GModel* ptr = registry.alloc(type);
791 
792  // If model if valid then read model from XML file
793  if (ptr != NULL) {
794  ptr->read(*src);
795  }
796 
797  // ... otherwise throw an exception
798  else {
799  std::string msg = "Model type \""+type+"\" unknown. The following "
800  "model types are available: "+registry.content()+
801  ". Please specify one of the available model "
802  "types.";
803  throw GException::invalid_value(G_READ, msg);
804  }
805 
806  // Append model
807  append(*ptr);
808 
809  // Free model (appending clones the model)
810  delete ptr;
811 
812  } // endfor: looped over all sources
813 
814  // Return
815  return;
816 }
817 
818 
819 /***********************************************************************//**
820  * @brief Write models into XML document
821  *
822  * @param[in] xml XML document.
823  *
824  * Write models into the first source library that is found in the XML
825  * document. In case that no source library exists, one is added to the
826  * document.
827  ***************************************************************************/
828 void GModels::write(GXml& xml) const
829 {
830  // If there is no source library then append one
831  if (xml.elements("source_library") == 0) {
832  xml.append(GXmlElement("source_library title=\"source library\""));
833  }
834 
835  // Get pointer on source library
836  GXmlElement* lib = xml.element("source_library", 0);
837 
838  // Write all sources into library
839  for (int i = 0; i < size(); ++i) {
840  m_models[i]->write(*lib);
841  }
842 
843  // Return
844  return;
845 }
846 
847 
848 /***********************************************************************//**
849  * @brief Return number of model parameters in container
850  *
851  * @return Number of model parameters in container.
852  ***************************************************************************/
853 int GModels::npars(void) const
854 {
855  // Initialise number of parameters
856  int npars = 0;
857 
858  // Sum of number of parameters in model
859  for (int i = 0; i < size(); ++i) {
860  npars += m_models[i]->size();
861  }
862 
863  // Return
864  return npars;
865 }
866 
867 
868 /***********************************************************************//**
869  * @brief Return optimizer parameter container
870  *
871  * @return Optimizer parameter container.
872  *
873  * Returns an optimizer parameter container that is built by extracting
874  * all model pointers from the model and attaching them to the parameter
875  * container. The optimizer parameter container will thus contains a flat
876  * array of a model parameters.
877  ***************************************************************************/
879 {
880  // Initialise parameter container
882 
883  // Attach all parameters
884  for (int i = 0; i < size(); ++i) {
885  GModel* model = m_models[i];
886  int npars = model->size();
887  for (int k = 0; k < npars; ++k) {
888  pars.attach(&((*model)[k]));
889  }
890  }
891 
892  // Return
893  return pars;
894 }
895 
896 
897 /***********************************************************************//**
898  * @brief Evaluate sum of all models
899  *
900  * @param[in] event Observed event.
901  * @param[in] obs Observation.
902  * @param[in] gradients Compute gradients?
903  * @return Value of models.
904  *
905  * Evaluates the sum of all models for the specified event and observation.
906  * Only valid models are considered in this evaluation.
907  *
908  * If the @p gradients flag is true the method will also set the parameter
909  * gradients of the model parameters.
910  ***************************************************************************/
911 double GModels::eval(const GEvent& event,
912  const GObservation& obs,
913  const bool& gradients) const
914 {
915  // Initialise model value
916  double value = 0.0;
917 
918  // Evaluate function for all models
919  for (int i = 0; i < size(); ++i) {
920  if (m_models[i]->is_valid(obs.instrument(), obs.id())) {
921  value += m_models[i]->eval(event, obs, gradients);
922  }
923  }
924 
925  // Return model value
926  return value;
927 }
928 
929 
930 /***********************************************************************//**
931  * @brief Evaluate sum vector of all models
932  *
933  * @param[in] obs Observation.
934  * @param[in] gradients Pointer to gradients matrix.
935  * @return Vector of model values.
936  *
937  * Evaluates the sum vector of all models for all events in the observation.
938  * Only valid models are considered in this evaluation.
939  *
940  * If the @p gradients pointer is not NULL the method will fill the
941  * corresponding matrix with the parameter gradients of the model.
942  ***************************************************************************/
944  GMatrixSparse* gradients) const
945 {
946  // Get number of events
947  int nevents = obs.events()->size();
948 
949  // Initialise model sum
950  GVector values(nevents);
951 
952  // Evaluate function for all models
953  for (int i = 0; i < size(); ++i) {
954  if (m_models[i]->is_valid(obs.instrument(), obs.id())) {
955  values += m_models[i]->eval(obs, gradients);
956  }
957  }
958 
959  // Return model values
960  return values;
961 }
962 
963 
964 /***********************************************************************//**
965  * @brief Print models
966  *
967  * @param[in] chatter Chattiness.
968  * @return String containing model container information.
969  *
970  * Prints all models into a string.
971  ***************************************************************************/
972 std::string GModels::print(const GChatter& chatter) const
973 {
974  // Initialise result string
975  std::string result;
976 
977  // Continue only if chatter is not silent
978  if (chatter != SILENT) {
979 
980  // Append header
981  result.append("=== GModels ===");
982 
983  // Append information
984  result.append("\n"+gammalib::parformat("Number of models"));
985  result.append(gammalib::str(size()));
986  result.append("\n"+gammalib::parformat("Number of parameters"));
987  result.append(gammalib::str(npars()));
988 
989  // Append models
990  for (int i = 0; i < size(); ++i) {
991  result.append("\n"+m_models[i]->print(chatter));
992  }
993 
994  } // endif: chatter was not silent
995 
996  // Return result
997  return result;
998 }
999 
1000 
1001 /*==========================================================================
1002  = =
1003  = Private methods =
1004  = =
1005  ==========================================================================*/
1006 
1007 /***********************************************************************//**
1008  * @brief Initialise class members
1009  ***************************************************************************/
1011 {
1012  // Initialise members
1013  m_models.clear();
1014 
1015  // Return
1016  return;
1017 }
1018 
1019 
1020 /***********************************************************************//**
1021  * @brief Copy class members
1022  *
1023  * @param[in] models Model container.
1024  *
1025  * Makes a copy of all class members. All models are deep copied, and the
1026  * linear pointer array for parameter access through the GOptimizerPars
1027  * base class is set.
1028  ***************************************************************************/
1029 void GModels::copy_members(const GModels& models)
1030 {
1031  // Copy models
1032  m_models.clear();
1033  for (int i = 0; i < models.m_models.size(); ++i) {
1034  m_models.push_back((models.m_models[i]->clone()));
1035  }
1036 
1037  // Return
1038  return;
1039 }
1040 
1041 
1042 /***********************************************************************//**
1043  * @brief Delete class members
1044  *
1045  * Deallocates all models. The method loops over the model container and
1046  * deallocates the memory that has been allocated before.
1047  ***************************************************************************/
1049 {
1050  // Free models
1051  for (int i = 0; i < m_models.size(); ++i) {
1052  delete m_models[i];
1053  m_models[i] = NULL;
1054  }
1055 
1056  // Return
1057  return;
1058 }
1059 
1060 
1061 /***********************************************************************//**
1062  * @brief Return model index by name
1063  *
1064  * @param[in] name Model name.
1065  * @return Model index (-1 if model name has not been found)
1066  *
1067  * Returns model index based on the specified @p name. If no model with the
1068  * specified @p name is found the method returns -1.
1069  ***************************************************************************/
1070 int GModels::get_index(const std::string& name) const
1071 {
1072  // Initialise index
1073  int index = -1;
1074 
1075  // Search model with specified name
1076  for (int i = 0; i < size(); ++i) {
1077  if (m_models[i]->name() == name) {
1078  index = i;
1079  break;
1080  }
1081  }
1082 
1083  // Return index
1084  return index;
1085 }
Abstract XML node base class.
Definition: GXmlNode.hpp:57
#define G_APPEND
Definition: GModels.cpp:49
double eval(const GEvent &event, const GObservation &obs, const bool &gradients=false) const
Evaluate sum of all models.
Definition: GModels.cpp:911
Abstract model class.
Definition: GModel.hpp:100
void copy_members(const GModels &models)
Copy class members.
Definition: GModels.cpp:1029
Abstract model base class interface definition.
Sparse matrix class interface definition.
XML element node class interface definition.
void save(const GFilename &filename) const
Save XML document into file.
Definition: GXml.cpp:581
Interface definition for the model registry class.
virtual std::string instrument(void) const =0
void remove(const int &index)
Remove model from container.
Definition: GModels.cpp:560
Model container class definition.
#define G_SET1
Definition: GModels.cpp:47
void read(const GXml &xml)
Read models from XML document.
Definition: GModels.cpp:773
XML class interface definition.
GModels * clone(void) const
Clone instance.
Definition: GModels.cpp:253
GModels(void)
Void constructor.
Definition: GModels.cpp:73
GModel * operator[](const int &index)
Return pointer to model.
Definition: GModels.hpp:231
Optimizer parameter container class.
Abstract interface for the event classes.
Definition: GEvent.hpp:71
void extend(const GModels &models)
Append model container.
Definition: GModels.cpp:621
XML element node class.
Definition: GXmlElement.hpp:48
GOptimizerPars pars(void) const
Return optimizer parameter container.
Definition: GModels.cpp:878
void save(const GFilename &filename) const
Save models into XML file.
Definition: GModels.cpp:711
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition: GXmlNode.cpp:586
Gammalib tools definition.
#define G_INSERT2
Definition: GModels.cpp:51
void reserve(const int &num)
Reserves space for models in container.
Definition: GModels.hpp:287
#define G_REMOVE1
Definition: GModels.cpp:52
void id(const std::string &id)
Set observation identifier.
GModel * insert(const int &index, const GModel &model)
Insert model into container.
Definition: GModels.cpp:459
int size(void) const
Return number of parameters in model.
Definition: GModel.hpp:233
void clear(void)
Clear object.
Definition: GModels.cpp:233
std::string content(void) const
Return list of names in registry.
Definition: GRegistry.cpp:54
#define G_READ
Definition: GModels.cpp:55
std::vector< GModel * > m_models
List of models.
Definition: GModels.hpp:207
int get_index(const std::string &name) const
Return model index by name.
Definition: GModels.cpp:1070
virtual void read(const GXmlElement &xml)=0
Model container class.
Definition: GModels.hpp:152
GXmlElement * element(const int &index)
Return pointer to child element.
Definition: GXml.cpp:419
int elements(void) const
Return number of child elements in XML document root.
Definition: GXml.cpp:384
void free_members(void)
Delete class members.
Definition: GModels.cpp:1048
#define G_REMOVE2
Definition: GModels.cpp:53
const GXmlAttribute * attribute(const int &index) const
Return attribute.
const std::string & name(void) const
Return parameter name.
Definition: GModel.hpp:261
XML class.
Definition: GXml.hpp:172
Filename class.
Definition: GFilename.hpp:62
#define G_EXTEND
Definition: GModels.cpp:54
GModel * set(const int &index, const GModel &model)
Set model in container.
Definition: GModels.cpp:321
#define G_SET2
Definition: GModels.cpp:48
GChatter
Definition: GTypemaps.hpp:33
Optimizer parameters base class definition.
void attach(GOptimizerPar *par)
Attach parameter to container.
Abstract observation base class.
Vector class interface definition.
Abstract observation base class interface definition.
GModel * alloc(const std::string &name) const
Allocate model of given name.
virtual GModel * clone(void) const =0
Clones object.
std::string url(void) const
Return Uniform Resource Locator (URL)
Definition: GFilename.hpp:189
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition: GXmlNode.cpp:640
void write(GXml &xml) const
Write models into XML document.
Definition: GModels.cpp:828
GModel * at(const int &index)
Return pointer to model.
Definition: GModels.cpp:269
void load(const GFilename &filename)
Load models from XML file.
Definition: GModels.cpp:688
bool contains(const std::string &name) const
Signals if model name exists.
Definition: GModels.cpp:670
Sparse matrix class definition.
std::string print(const GChatter &chatter=NORMAL) const
Print models.
Definition: GModels.cpp:972
void init_members(void)
Initialise class members.
Definition: GModels.cpp:1010
virtual GEvents * events(void)
Return events.
#define G_ACCESS
Definition: GModels.cpp:45
Exception handler interface definition.
int npars(void) const
Return number of model parameters in container.
Definition: GModels.cpp:853
virtual ~GModels(void)
Destructor.
Definition: GModels.cpp:125
#define G_AT
Definition: GModels.cpp:46
Vector class.
Definition: GVector.hpp:46
Model registry class definition.
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
#define G_INSERT1
Definition: GModels.cpp:50
GModels & operator=(const GModels &models)
Assignment operator.
Definition: GModels.cpp:147
int size(void) const
Return number of models in container.
Definition: GModels.hpp:259
GModel * append(const GModel &model)
Append model to container.
Definition: GModels.cpp:420
Filename class interface definition.
GXmlNode * append(const GXmlNode &node)
Append child node to XML document root.
Definition: GXml.cpp:279
bool is_empty(void) const
Signals if there are no models in container.
Definition: GModels.hpp:273
virtual int size(void) const =0
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489