GammaLib 2.0.0
Loading...
Searching...
No Matches
GModelAssociations.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GModelAssociations.cpp - Model associations container class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2020-2022 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 GModelAssociations.cpp
23 * @brief Model associations 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 "GXmlElement.hpp"
35#include "GModelAssociation.hpp"
36
37/* __ Method name definitions ____________________________________________ */
38#define G_ACCESS "GModelAssociations::operator[](std::string&)"
39#define G_AT "GModelAssociations::at(int&)"
40#define G_SET1 "GModelAssociations::set(int&, GModelAssociation&)"
41#define G_SET2 "GModelAssociations::set(std::string&, GModelAssociation&)"
42#define G_APPEND "GModelAssociations::append(GModelAssociation&)"
43#define G_INSERT1 "GModelAssociations::insert(int&, GModelAssociation&)"
44#define G_INSERT2 "GModelAssociations::insert(std::string&, "\
45 "GModelAssociation&)"
46#define G_REMOVE1 "GModelAssociations::remove(int&)"
47#define G_REMOVE2 "GModelAssociations::remove(std::string&)"
48#define G_EXTEND "GModelAssociations::extend(GModelAssociations&)"
49#define G_READ "GModelAssociations::read(GXml&)"
50#define G_GET_ASSOCIATION_XML "GModelAssociations::get_association_xml("\
51 "GXmlElement&, std::string&)"
52
53/* __ Macros _____________________________________________________________ */
54
55/* __ Coding definitions _________________________________________________ */
56
57/* __ Debug definitions __________________________________________________ */
58
59
60/*==========================================================================
61 = =
62 = Constructors/destructors =
63 = =
64 ==========================================================================*/
65
66/***********************************************************************//**
67 * @brief Void constructor
68 ***************************************************************************/
70{
71 // Initialise members
73
74 // Return
75 return;
76}
77
78
79/***********************************************************************//**
80 * @brief XML element constructor
81 *
82 * @param[in] xml XML element.
83 *
84 * Construct a model associations container from an XML element.
85 ***************************************************************************/
87{
88 // Initialise private members
90
91 // Read model associations container from XML element
92 read(xml);
93
94 // Return
95 return;
96}
97
98
99/***********************************************************************//**
100 * @brief Copy constructor
101 *
102 * @param[in] associations Model associations container.
103 ***************************************************************************/
105{
106 // Initialise members
107 init_members();
108
109 // Copy members
110 copy_members(associations);
111
112 // Return
113 return;
114}
115
116
117/***********************************************************************//**
118 * @brief Destructor
119 ***************************************************************************/
121{
122 // Free members
123 free_members();
124
125 // Return
126 return;
127}
128
129
130/*==========================================================================
131 = =
132 = Operators =
133 = =
134 ==========================================================================*/
135
136/***********************************************************************//**
137 * @brief Assignment operator
138 *
139 * @param[in] associations Model associations container.
140 * @return Model associations container.
141 ***************************************************************************/
143{
144 // Execute only if object is not identical
145 if (this != &associations) {
146
147 // Free members
148 free_members();
149
150 // Initialise members
151 init_members();
152
153 // Copy members
154 copy_members(associations);
155
156 } // endif: object was not identical
157
158 // Return
159 return *this;
160}
161
162
163/***********************************************************************//**
164 * @brief Return reference to model association
165 *
166 * @param[in] name Model association name.
167 *
168 * @exception GException::invalid_argument
169 * Model association with specified @p name not found in container.
170 *
171 * Returns a reference to the model with the specified @p name.
172 ***************************************************************************/
174{
175 // Return association using const method
176 return const_cast<GModelAssociation&>((*static_cast<const GModelAssociations*>(this))[name]);
177}
178
179
180/***********************************************************************//**
181 * @brief Return reference to model association (const version)
182 *
183 * @param[in] name Model association name.
184 *
185 * @exception GException::invalid_argument
186 * Model association with specified @p name not found in container.
187 *
188 * Returns a const reference to the model with the specified @p name.
189 ***************************************************************************/
190const GModelAssociation& GModelAssociations::operator[](const std::string& name) const
191{
192 // Get model index
193 int index = get_index(name);
194
195 // Throw exception if model name was not found
196 if (index == -1) {
197 std::string msg = "Model association \""+name+"\" not found in "
198 "container.";
200 }
201
202 // Return pointer
203 return m_associations[index];
204}
205
206
207/*==========================================================================
208 = =
209 = Public methods =
210 = =
211 ==========================================================================*/
212
213/***********************************************************************//**
214 * @brief Clear object
215 *
216 * Removes all model associations from the container.
217 ***************************************************************************/
219{
220 // Free class members
221 free_members();
222
223 // Initialise members
224 init_members();
225
226 // Return
227 return;
228}
229
230
231/***********************************************************************//**
232 * @brief Clone instance
233 *
234 * @return Pointer to deep copy of model associations container
235 *
236 * Makes a deep copy of the model associations container instance.
237 ***************************************************************************/
239{
240 return new GModelAssociations(*this);
241}
242
243
244/***********************************************************************//**
245 * @brief Return reference to model association
246 *
247 * @param[in] index Model association index [0,...,size()-1].
248 *
249 * @exception GException::out_of_range
250 * Model association index is out of range.
251 *
252 * Returns a reference to the model association with the specified @p index.
253 ***************************************************************************/
255{
256 // Return association using const method
257 return const_cast<GModelAssociation&>(static_cast<const GModelAssociations*>(this)->at(index));
258}
259
260
261/***********************************************************************//**
262 * @brief Return reference to model association (const version)
263 *
264 * @param[in] index Model association index [0,...,size()-1].
265 *
266 * @exception GException::out_of_range
267 * Model association index is out of range.
268 *
269 * Returns a const reference to the model association with the specified
270 * @p index.
271 ***************************************************************************/
272const GModelAssociation& GModelAssociations::at(const int& index) const
273{
274 // Compile option: raise an exception if index is out of range
275 #if defined(G_RANGE_CHECK)
276 if (index < 0 || index >= size()) {
277 throw GException::out_of_range(G_AT, "Model association index", index, size());
278 }
279 #endif
280
281 // Return pointer
282 return m_associations[index];
283}
284
285
286/***********************************************************************//**
287 * @brief Append model association to container
288 *
289 * @param[in] association Model association.
290 * @return Reference to appended model association.
291 *
292 * @exception GException::invalid_value
293 * Name of model association exists already in container.
294 *
295 * Appends model association to the container.
296 ***************************************************************************/
298{
299 // Check if a model association with specified name does not yet exist
300 int inx = get_index(association.name());
301 if (inx != -1) {
302 std::string msg =
303 "Attempt to append model association \""+association.name()+"\" "
304 "to association container, but an association with the same name "
305 "exists already at index "+gammalib::str(inx)+" in the container. "
306 "Every model association in the container needs a unique name.";
308 }
309
310 // Append model association
311 m_associations.push_back(association);
312
313 // Return reference to model association
314 return (m_associations[size()-1]);
315}
316
317
318/***********************************************************************//**
319 * @brief Insert model association into container
320 *
321 * @param[in] index Model association index [0,...,size()-1].
322 * @param[in] association Model association.
323 * @return Reference to inserted model association.
324 *
325 * @exception GException::out_of_range
326 * Model association index is out of range.
327 * @exception GException::invalid_value
328 * Name of model association exists already in container.
329 *
330 * Inserts a @p model association into the container before the model
331 * association with the specified @p index.
332 ***************************************************************************/
334 const GModelAssociation& association)
335{
336 // Compile option: raise exception if index is out of range
337 #if defined(G_RANGE_CHECK)
338 if (is_empty()) {
339 if (index > 0) {
340 throw GException::out_of_range(G_INSERT1, "Model association index",
341 index, size());
342 }
343 }
344 else {
345 if (index < 0 || index >= size()) {
346 throw GException::out_of_range(G_INSERT1, "Model association index",
347 index, size());
348 }
349 }
350 #endif
351
352 // Check if a model association with specified name does not yet exist
353 int inx = get_index(association.name());
354 if (inx != -1) {
355 std::string msg =
356 "Attempt to insert model association \""+association.name()+"\" "
357 "in container before index "+gammalib::str(index)+", but an "
358 "association with the same name exists already at index "+
359 gammalib::str(inx)+" in the container. Every model association "
360 "in the container needs a unique name.";
362 }
363
364 // Inserts deep copy of model association
365 m_associations.insert(m_associations.begin()+index, association);
366
367 // Return reference to model association
368 return (m_associations[index]);
369}
370
371
372/***********************************************************************//**
373 * @brief Insert model association into container
374 *
375 * @param[in] name Model association name.
376 * @param[in] association Model association.
377 * @return Reference to inserted model association.
378 *
379 * @exception GException::invalid_argument
380 * Model association with specified name not found in container.
381 * @exception GException::invalid_value
382 * Name of model association exists already in container.
383 *
384 * Inserts a @p model association into the container before the model
385 * association with the specified @p name.
386 ***************************************************************************/
388 const GModelAssociation& association)
389{
390 // Get association index
391 int index = get_index(name);
392
393 // Throw exception if parameter name was not found
394 if (index == -1) {
395 std::string msg = "Model association \""+name+"\" not found in "
396 "container.";
398 }
399
400 // Check if a model with specified name does not yet exist
401 int inx = get_index(association.name());
402 if (inx != -1) {
403 std::string msg =
404 "Attempt to insert model association \""+association.name()+"\" "
405 "in container before index "+gammalib::str(index)+", but an "
406 "association with the same name exists already at index "+
407 gammalib::str(inx)+" in the container. Every model association "
408 "in the container needs a unique name.";
410 }
411
412 // Inserts deep copy of model association
413 m_associations.insert(m_associations.begin()+index, association);
414
415 // Return reference to model association
416 return (m_associations[index]);
417}
418
419
420/***********************************************************************//**
421 * @brief Remove model association from container
422 *
423 * @param[in] index Model association index [0,...,size()-1].
424 *
425 * @exception GException::out_of_range
426 * Model association index is out of range.
427 *
428 * Remove model association of specified @p index from container.
429 ***************************************************************************/
430void GModelAssociations::remove(const int& index)
431{
432 // Compile option: raise exception if index is out of range
433 #if defined(G_RANGE_CHECK)
434 if (index < 0 || index >= size()) {
435 throw GException::out_of_range(G_REMOVE1, "Model association index",
436 index, size());
437 }
438 #endif
439
440 // Erase model association component from container
441 m_associations.erase(m_associations.begin() + index);
442
443 // Return
444 return;
445}
446
447
448/***********************************************************************//**
449 * @brief Remove model association from container
450 *
451 * @param[in] name Model association name.
452 *
453 * @exception GException::invalid_argument
454 * Model association with specified name not found in container.
455 *
456 * Remove model association of specified @p name from container.
457 ***************************************************************************/
458void GModelAssociations::remove(const std::string& name)
459{
460 // Get parameter index
461 int index = get_index(name);
462
463 // Throw exception if parameter name was not found
464 if (index == -1) {
465 std::string msg = "Model association \""+name+"\" not found in "
466 "container.";
468 }
469
470 // Erase model association component from container
471 m_associations.erase(m_associations.begin() + index);
472
473 // Return
474 return;
475}
476
477
478/***********************************************************************//**
479 * @brief Append model association container
480 *
481 * @param[in] associations Model association container.
482 *
483 * Append model association container to the container.
484 ***************************************************************************/
486{
487 // Do nothing if model association container is empty
488 if (!associations.is_empty()) {
489
490 // Get size. Note that we extract the size first to avoid an
491 // endless loop that arises when a container is appended to
492 // itself.
493 int num = associations.size();
494
495 // Reserve enough space
496 reserve(size() + num);
497
498 // Loop over all model association components and append pointers
499 // to deep copies
500 for (int i = 0; i < num; ++i) {
501
502 // Check if model association name does not yet exist
503 int inx = get_index(associations[i].name());
504 if (inx != -1) {
505 std::string msg =
506 "Attempt to append model association \""+
507 associations[i].name()+"\" to container, but an "
508 "association with the same name exists already at "
509 "index "+gammalib::str(inx)+" in the container. Every "
510 "model association in the container needs a unique name.";
512 }
513
514 // Append model association to container
515 m_associations.push_back(associations[i]);
516
517 } // endfor: looped over all model associations
518
519 } // endif: model association container was not empty
520
521 // Return
522 return;
523}
524
525
526/***********************************************************************//**
527 * @brief Signals if model association name exists
528 *
529 * @param[in] name Model association name.
530 * @return True if model association with specified @p name exists.
531 *
532 * Searches all model association names for a match with the specified
533 * @p name. If the specified name has been found, true is returned.
534 ***************************************************************************/
535bool GModelAssociations::contains(const std::string& name) const
536{
537 // Get model association index
538 int index = get_index(name);
539
540 // Return
541 return (index != -1);
542}
543
544
545/***********************************************************************//**
546 * @brief Read model associations from XML document
547 *
548 * @param[in] xml XML element.
549 *
550 * Read model associations from the XML element. The XML element is expected
551 * to have the following structure
552 *
553 * <associations>
554 * <association name="Crab">
555 * <property name="RA" value="83.6331"/>
556 * <property name="DEC" value="22.0145"/>
557 * <property name="distance" value="0.0123"/>
558 * <property name="probability" value="0.978"/>
559 * </association>
560 * </associations>
561 *
562 * This method does nothing if no "associations" tag is present in the XML
563 * element.
564 ***************************************************************************/
566{
567 // Initialise associations
568 m_associations.clear();
569
570 // Continue only if there is an <associations> tag
571 if (xml.elements("associations") > 0) {
572
573 // Get pointer on associations
574 const GXmlElement* associations = xml.element("associations", 0);
575
576 // Determine number of associations
577 int n = associations->elements("association");
578
579 // Loop over all associations
580 for (int i = 0; i < n; ++i) {
581
582 // Get pointer on association
583 const GXmlElement* element = associations->element("association", i);
584
585 // Construct association from XML element
586 GModelAssociation association(*element);
587
588 // Append assocition to container
589 append(association);
590
591 } // endfor: looped over all associations
592
593 } // endif: an association tag was present
594
595 // Return
596 return;
597}
598
599
600/***********************************************************************//**
601 * @brief Write models into XML element
602 *
603 * @param[in] xml XML element.
604 *
605 * Write model associations into the first "associations" element that is
606 * found in the XML element. In case that no "associations" element exists,
607 * one is added to the XML element. The written XML element has the
608 * following structure
609 *
610 * <associations>
611 * <association name="Crab">
612 * <property name="RA" value="83.6331"/>
613 * <property name="DEC" value="22.0145"/>
614 * <property name="distance" value="0.0123"/>
615 * <property name="probability" value="0.978"/>
616 * </association>
617 * </associations>
618 *
619 * This method does nothing if there are no associations in the instance.
620 ***************************************************************************/
622{
623 // Continue only if there are associations
624 if (!is_empty()) {
625
626 // If there is no associations tag then append one
627 if (xml.elements("associations") == 0) {
628 xml.append(GXmlElement("associations"));
629 }
630
631 // Get pointer on model associations
632 GXmlElement* associations = xml.element("associations", 0);
633
634 // Write all model associations into the XML element
635 for (int i = 0; i < size(); ++i) {
636 GXmlElement* association = get_association_xml(*associations,
637 m_associations[i].name());
638 m_associations[i].write(*association);
639 }
640
641 } // endif: there were associations to write
642
643 // Return
644 return;
645}
646
647
648/***********************************************************************//**
649 * @brief Print model associations
650 *
651 * @param[in] chatter Chattiness.
652 * @return String containing model association container information.
653 *
654 * Prints all model associations into a string.
655 ***************************************************************************/
656std::string GModelAssociations::print(const GChatter& chatter) const
657{
658 // Initialise result string
659 std::string result;
660
661 // Continue only if chatter is not silent
662 if (chatter != SILENT) {
663
664 // Append header
665 result.append("=== GModelAssociations ===");
666
667 // Append information
668 result.append("\n"+gammalib::parformat("Number of associations"));
669 result.append(gammalib::str(size()));
670
671 // Append associations
672 for (int i = 0; i < size(); ++i) {
673 result.append("\n"+m_associations[i].print(chatter));
674 }
675
676 } // endif: chatter was not silent
677
678 // Return result
679 return result;
680}
681
682
683/*==========================================================================
684 = =
685 = Private methods =
686 = =
687 ==========================================================================*/
688
689/***********************************************************************//**
690 * @brief Initialise class members
691 ***************************************************************************/
693{
694 // Initialise members
695 m_associations.clear();
696
697 // Return
698 return;
699}
700
701
702/***********************************************************************//**
703 * @brief Copy class members
704 *
705 * @param[in] associations Model association container.
706 ***************************************************************************/
708{
709 // Copy members
710 m_associations = associations.m_associations;
711
712 // Return
713 return;
714}
715
716
717/***********************************************************************//**
718 * @brief Delete class members
719 ***************************************************************************/
721{
722 // Return
723 return;
724}
725
726
727/***********************************************************************//**
728 * @brief Return model association index by name
729 *
730 * @param[in] name Model ssociation name.
731 * @return Model association index (-1 if not found)
732 *
733 * Returns model association index based on the specified @p name. If no
734 * model association with the specified @p name is found the method returns
735 * -1.
736 ***************************************************************************/
737int GModelAssociations::get_index(const std::string& name) const
738{
739 // Initialise index
740 int index = -1;
741
742 // Search model association with specified name
743 for (int i = 0; i < size(); ++i) {
744 if (m_associations[i].name() == name) {
745 index = i;
746 break;
747 }
748 }
749
750 // Return index
751 return index;
752}
753
754
755/***********************************************************************//**
756 * @brief Return pointer to model association with given name in XML element
757 *
758 * @param[in] xml XML element.
759 * @param[in] name Model association name.
760 * @return Pointer to model association XML element.
761 *
762 * @exception GException::invalid_value
763 * Invalid XML format encountered.
764 *
765 * Returns pointer to model association with given @p name in XML element.
766 * If the @p name is not found, a model association with the given @p name
767 * is added.
768 *
769 * The function checks for multiple occurences of a model association and
770 * throws an exception in case that more than one association with a given
771 * name is found.
772 ***************************************************************************/
774 const std::string& name) const
775{
776 // Initialize XML element pointer
777 GXmlElement* association = NULL;
778
779 // Number of elements
780 int number = 0;
781
782 // Get number of elements in XML element
783 int n = xml.elements("association");
784
785 // Search for property with given name
786 for (int i = 0; i < n; ++i) {
787 GXmlElement* element = xml.element("association", i);
788 if (element->attribute("name") == name) {
789 association = element;
790 number++;
791 }
792 }
793
794 // Create property if none was found
795 if (number == 0) {
796 association = static_cast<GXmlElement*>(xml.append(GXmlElement("association name=\""+name+"\"")));
797 number++;
798 }
799
800 // Throw case dependent exception
801 if (number < 1) {
802 std::string msg = "Model association \""+name+"\" not found in XML "
803 " element. Please verify the XML format.";
805 }
806 else if (number > 1) {
807 std::string msg = "Model association \""+name+"\" found "+
808 gammalib::str(number)+" times in XML element."
809 " Please verify the XML format.";
811 }
812
813 // Return
814 return association;
815}
#define G_AT
#define G_REMOVE1
#define G_INSERT2
#define G_APPEND
#define G_INSERT1
#define G_REMOVE2
#define G_EXTEND
#define G_ACCESS
Exception handler interface definition.
Model association class definition.
#define G_GET_ASSOCIATION_XML
Model associations container class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
XML element node class interface definition.
Model association class.
const std::string & name(void) const
Return association name.
Model associations container class.
virtual ~GModelAssociations(void)
Destructor.
GXmlElement * get_association_xml(GXmlElement &xml, const std::string &name) const
Return pointer to model association with given name in XML element.
void init_members(void)
Initialise class members.
bool contains(const std::string &name) const
Signals if model association name exists.
void read(const GXmlElement &xml)
Read model associations from XML document.
GModelAssociations * clone(void) const
Clone instance.
GModelAssociations & operator=(const GModelAssociations &associations)
Assignment operator.
GModelAssociation & at(const int &index)
Return reference to model association.
GModelAssociation & insert(const int &index, const GModelAssociation &association)
Insert model association into container.
int get_index(const std::string &name) const
Return model association index by name.
bool is_empty(void) const
Signals if there are no associations in container.
void clear(void)
Clear object.
void write(GXmlElement &xml) const
Write models into XML element.
int size(void) const
Return number of associations in container.
std::string print(const GChatter &chatter=NORMAL) const
Print model associations.
GModelAssociation & append(const GModelAssociation &association)
Append model association to container.
std::vector< GModelAssociation > m_associations
List of associations.
GModelAssociations(void)
Void constructor.
void reserve(const int &num)
Reserves space for associations in container.
GModelAssociation & operator[](const int &index)
Return reference to association.
void copy_members(const GModelAssociations &associations)
Copy class members.
void free_members(void)
Delete class members.
void remove(const int &index)
Remove model association from container.
void extend(const GModelAssociations &associations)
Append model association container.
XML element node class.
const GXmlAttribute * attribute(const int &index) const
Return attribute.
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition GXmlNode.cpp:287
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition GXmlNode.cpp:640
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition GXmlNode.cpp:586
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489