GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GModelAssociation.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GModelAssociation.cpp - Model association 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 GModelAssociation.cpp
23  * @brief Model association class implementation
24  * @author Juergen Knodlseder
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"
34 #include "GModelAssociation.hpp"
35 
36 /* __ Constants __________________________________________________________ */
37 
38 /* __ Method name definitions ____________________________________________ */
39 #define G_VALUE "GModelAssociation::value(std::string&)"
40 #define G_ERROR "GModelAssociation::error(std::string&)"
41 #define G_PROPERTY "GModelAssociation::property(std::string&, std::string&,"\
42  " std::string&)"
43 #define G_GET_PROPERTY_XML "GModelAssociation::get_property_xml("\
44  "GXmlElement&, std::string&)"
45 
46 /* __ Macros _____________________________________________________________ */
47 
48 /* __ Coding definitions _________________________________________________ */
49 
50 /* __ Debug definitions __________________________________________________ */
51 
52 
53 /*==========================================================================
54  = =
55  = Constructors/destructors =
56  = =
57  ==========================================================================*/
58 
59 /***********************************************************************//**
60  * @brief Void constructor
61  ***************************************************************************/
63 {
64  // Initialise private members
65  init_members();
66 
67  // Return
68  return;
69 }
70 
71 
72 /***********************************************************************//**
73  * @brief Association name constructor
74  *
75  * @param[in] name Association name.
76  *
77  * Construct a model association from an association name.
78  ***************************************************************************/
79 GModelAssociation::GModelAssociation(const std::string& name)
80 {
81  // Initialise private members
82  init_members();
83 
84  // Set association name
85  this->name(name);
86 
87  // Return
88  return;
89 }
90 
91 
92 /***********************************************************************//**
93  * @brief XML element constructor
94  *
95  * @param[in] xml XML element.
96  *
97  * Construct a model association from an XML element.
98  ***************************************************************************/
100 {
101  // Initialise private members
102  init_members();
103 
104  // Read model association from XML element
105  read(xml);
106 
107  // Return
108  return;
109 }
110 
111 
112 /***********************************************************************//**
113  * @brief Copy constructor
114  *
115  * @param[in] association Model association.
116  ***************************************************************************/
118 {
119  // Initialise private members
120  init_members();
121 
122  // Copy members
123  copy_members(association);
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] association Model association.
153  * @return Model association.
154  ***************************************************************************/
156 {
157  // Execute only if object is not identical
158  if (this != &association) {
159 
160  // Free members
161  free_members();
162 
163  // Initialise private members for clean destruction
164  init_members();
165 
166  // Copy members
167  copy_members(association);
168 
169  } // endif: object was not identical
170 
171  // Return
172  return *this;
173 }
174 
175 
176 /*==========================================================================
177  = =
178  = Public methods =
179  = =
180  ==========================================================================*/
181 
182 /***********************************************************************//**
183  * @brief Clear model association
184  ***************************************************************************/
186 {
187  // Free members
188  free_members();
189 
190  // Initialise private members
191  init_members();
192 
193  // Return
194  return;
195 }
196 
197 
198 /***********************************************************************//**
199  * @brief Clone model association
200  *
201  * @return Pointer to deep copy of model association.
202  ***************************************************************************/
204 {
205  // Clone this model association
206  return new GModelAssociation(*this);
207 }
208 
209 
210 /***********************************************************************//**
211  * @brief Return property value
212  *
213  * @param[in] name Property name
214  * @return Property value.
215  *
216  * @exception GException::invalid_argument
217  * Property name not found
218  *
219  * Returns the value of the property with the specified @p name.
220  ***************************************************************************/
221 const std::string& GModelAssociation::value(const std::string& name) const
222 {
223  // Get model index
224  int index = get_index(name);
225 
226  // Throw exception if property name was not found
227  if (index == -1) {
228  std::string msg = "Property \""+name+"\" not found in association.";
230  }
231 
232  // Return property value
233  return (m_values[index]);
234 }
235 
236 
237 /***********************************************************************//**
238  * @brief Return property error
239  *
240  * @param[in] name Property name
241  * @return Property error.
242  *
243  * @exception GException::invalid_argument
244  * Property name not found
245  *
246  * Returns the error of the property with the specified @p name.
247  ***************************************************************************/
248 const std::string& GModelAssociation::error(const std::string& name) const
249 {
250  // Get model index
251  int index = get_index(name);
252 
253  // Throw exception if property name was not found
254  if (index == -1) {
255  std::string msg = "Association property \""+name+"\" not found.";
257  }
258 
259  // Return property error
260  return (m_errors[index]);
261 }
262 
263 
264 /***********************************************************************//**
265 * @brief Set property value and (optionally) error
266 *
267 * @param[in] name Property name
268 * @param[in] value Property value
269 * @param[in] error Property error
270 *
271 * @exception GException::invalid_argument
272 * Property with specified @p name exists aleady
273 *
274 * Sets the value and optionally the error of the property with the
275 * specified @p name.
276 ***************************************************************************/
277 void GModelAssociation::property(const std::string& name,
278  const std::string& value,
279  const std::string& error)
280 {
281  // Throw an exception if property exists already
282  if (get_index(name) != -1) {
283  std::string msg = "Association property \""+name+"\" exists already.";
285  }
286 
287  // Push name, value and error in property lists
288  m_names.push_back(name);
289  m_values.push_back(value);
290  m_errors.push_back(error);
291 
292  // Return
293  return;
294 }
295 
296 
297 /***********************************************************************//**
298  * @brief Read model association from XML document
299  *
300  * @param[in] xml XML element.
301  *
302  * Read model association from the XML element. The XML element is expected
303  * to have the following structure
304  *
305  * <association name="Crab">
306  * <property name="RA" value="83.6331"/>
307  * <property name="DEC" value="22.0145"/>
308  * <property name="distance" value="0.0123"/>
309  * <property name="probability" value="0.978"/>
310  * </association>
311  *
312  * Properties need to have unique names. If properties with identical names
313  * are encountered, and exception is thrown.
314  ***************************************************************************/
316 {
317  // Initialise properties
318  m_names.clear();
319  m_values.clear();
320  m_errors.clear();
321 
322  // Set association name
323  name(xml.attribute("name"));
324 
325  // Get number of properties
326  int n = xml.elements("property");
327 
328  // Loop over all properties
329  for (int i = 0; i < n; ++i) {
330 
331  // Get pointer on property
332  const GXmlElement* property = xml.element("property", i);
333 
334  // Read name, value and error. If one of the attributes does not
335  // exist an empty string will be returned
336  std::string name = property->attribute("name");
337  std::string value = property->attribute("value");
338  std::string error = property->attribute("error");
339 
340  // Set property
341  this->property(name, value, error);
342 
343  } // endfor: looped over properties
344 
345  // Return
346  return;
347 }
348 
349 
350 /***********************************************************************//**
351  * @brief Write model association into XML element
352  *
353  * @param[in] xml XML element.
354  *
355  * Write model association into the XML element. The following structure
356  * will be written
357  *
358  * <association name="Crab">
359  * <property name="RA" value="83.6331"/>
360  * <property name="DEC" value="22.0145"/>
361  * <property name="distance" value="0.0123"/>
362  * <property name="probability" value="0.978"/>
363  * </association>
364  *
365  ***************************************************************************/
367 {
368  // Write association name
369  xml.attribute("name", name());
370 
371  // Loop over all association properties
372  for (int i = 0; i < size(); ++i) {
373  GXmlElement* property = get_property_xml(xml, m_names[i]);
374  property->attribute("name", m_names[i]);
375  property->attribute("value", m_values[i]);
376  if (!m_errors[i].empty()) {
377  property->attribute("error", m_errors[i]);
378  }
379  }
380 
381  // Return
382  return;
383 }
384 
385 
386 /***********************************************************************//**
387  * @brief Print model association
388  *
389  * @param[in] chatter Chattiness.
390  * @return String containing model association information.
391  ***************************************************************************/
392 std::string GModelAssociation::print(const GChatter& chatter) const
393 {
394  // Initialise result string
395  std::string result;
396 
397  // Continue only if chatter is not silent
398  if (chatter != SILENT) {
399 
400  // Append header
401  result.append("=== GModelAssociation ===");
402 
403  // Append association name
404  result.append("\n"+gammalib::parformat("Name")+name());
405 
406  // Append association properties
407  result.append("\n"+gammalib::parformat("Number of properties"));
408  result.append(gammalib::str(size()));
409  for (int i = 0; i < size(); ++i) {
410  result.append("\n"+gammalib::parformat(m_names[i])+m_values[i]);
411  if (m_errors[i] != "") {
412  result.append(" +/- "+m_errors[i]);
413  }
414  }
415 
416  } // endif: chatter was not silent
417 
418  // Return
419  return result;
420 }
421 
422 
423 /*==========================================================================
424  = =
425  = Private methods =
426  = =
427  ==========================================================================*/
428 
429 /***********************************************************************//**
430  * @brief Initialise class members
431  ***************************************************************************/
433 {
434  // Initialise members
435  m_name.clear();
436  m_names.clear();
437  m_values.clear();
438  m_errors.clear();
439 
440  // Return
441  return;
442 }
443 
444 
445 /***********************************************************************//**
446  * @brief Copy class members
447  *
448  * @param[in] association Model association.
449  ***************************************************************************/
451 {
452  // Copy members
453  m_name = association.m_name;
454  m_names = association.m_names;
455  m_values = association.m_values;
456  m_errors = association.m_errors;
457 
458  // Return
459  return;
460 }
461 
462 
463 /***********************************************************************//**
464  * @brief Delete class members
465  ***************************************************************************/
467 {
468  // Return
469  return;
470 }
471 
472 
473 /***********************************************************************//**
474  * @brief Return property index by name
475  *
476  * @param[in] name Property name.
477  * @return Property index (-1 if not found)
478  *
479  * Returns the index of the property with the specified @p name. If no
480  * property with the specified @p name is found the method returns -1.
481  ***************************************************************************/
482 int GModelAssociation::get_index(const std::string& name) const
483 {
484  // Initialise index
485  int index = -1;
486 
487  // Search property names for the specified name
488  for (int i = 0; i < size(); ++i) {
489  if (m_names[i] == name) {
490  index = i;
491  break;
492  }
493  }
494 
495  // Return index
496  return index;
497 }
498 
499 
500 /***********************************************************************//**
501  * @brief Return pointer to property with given name in XML element
502  *
503  * @param[in] xml XML element.
504  * @param[in] name Property name.
505  * @return Pointer to property XML element.
506  *
507  * @exception GException::invalid_value
508  * Invalid XML format encountered.
509  *
510  * Returns pointer to property with given @p name in XML element. If the
511  * @p name is not found, a property with the given @p name is added.
512  *
513  * The function checks for multiple occurences of a property and throws an
514  * exception in case that more than one property with a given name is found.
515  ***************************************************************************/
517  const std::string& name) const
518 {
519  // Initialize XML element pointer
520  GXmlElement* property = NULL;
521 
522  // Number of elements
523  int number = 0;
524 
525  // Get number of elements in XML element
526  int n = xml.elements("property");
527 
528  // Search for property with given name
529  for (int i = 0; i < n; ++i) {
530  GXmlElement* element = xml.element("property", i);
531  if (element->attribute("name") == name) {
532  property = element;
533  number++;
534  }
535  }
536 
537  // Create property if none was found
538  if (number == 0) {
539  property = static_cast<GXmlElement*>(xml.append(GXmlElement("property name=\""+name+"\"")));
540  number++;
541  }
542 
543  // Throw case dependent exception
544  if (number < 1) {
545  std::string msg = "Property \""+name+"\" not found in XML element."
546  " Please verify the XML format.";
548  }
549  else if (number > 1) {
550  std::string msg = "Property \""+name+"\" found "+
551  gammalib::str(number)+" times in XML element."
552  " Please verify the XML format.";
554  }
555 
556  // Return
557  return property;
558 }
#define G_ERROR
std::string m_name
Association name.
int size(void) const
Return number of association properties.
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition: GTools.cpp:1167
void clear(void)
Clear model association.
XML element node class interface definition.
#define G_VALUE
XML element node class.
Definition: GXmlElement.hpp:48
const std::string & value(const std::string &name) const
Return property value.
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition: GXmlNode.cpp:586
Gammalib tools definition.
GXmlElement * get_property_xml(GXmlElement &xml, const std::string &name) const
Return pointer to property with given name in XML element.
Model association class.
std::string print(const GChatter &chatter=NORMAL) const
Print model association.
virtual ~GModelAssociation(void)
Destructor.
std::vector< std::string > m_names
Property names.
std::vector< std::string > m_values
Property values.
const GXmlAttribute * attribute(const int &index) const
Return attribute.
GModelAssociation(void)
Void constructor.
void read(const GXmlElement &xml)
Read model association from XML document.
const std::string & error(const std::string &name) const
Return property error.
GChatter
Definition: GTypemaps.hpp:33
std::vector< std::string > m_errors
Property errors.
GModelAssociation * clone(void) const
Clone model association.
int get_index(const std::string &name) const
Return property index by name.
GModelAssociation & operator=(const GModelAssociation &association)
Assignment operator.
void copy_members(const GModelAssociation &association)
Copy class members.
#define G_GET_PROPERTY_XML
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition: GXmlNode.cpp:640
Model association class definition.
Exception handler interface definition.
const std::string & name(void) const
Return association name.
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_PROPERTY
void init_members(void)
Initialise class members.
void free_members(void)
Delete class members.
void write(GXmlElement &xml) const
Write model association into XML element.
void property(const std::string &name, const std::string &value, const std::string &error="")
Set property value and (optionally) error.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489