GammaLib  1.7.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GTools.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GTools.cpp - GammaLib tools *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2008-2020 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 GTools.cpp
23  * @brief Gammalib tools implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <unistd.h> // access() functions
32 #include <fcntl.h> // fcntl() functions
33 #include <sys/stat.h>
34 #include <sys/time.h> // timeval
35 #include <sys/select.h> // select() function
36 #include <sys/types.h>
37 #include <sys/socket.h> // recv() function
38 #include <pwd.h>
39 #include <cmath>
40 #include <cfloat>
41 #include <cctype>
42 #include <cstdlib> // std::getenv() function
43 #include <cstring> // std::strlen() function
44 #include <iostream>
45 #include <sstream>
46 #include <algorithm>
47 #include "GTools.hpp"
48 #include "GException.hpp"
49 #include "GFits.hpp"
50 #include "GEnergy.hpp"
51 #include "GFilename.hpp"
52 #include "GMath.hpp"
53 #include "GXmlElement.hpp"
54 #include "GXmlNode.hpp"
55 #include "GXmlText.hpp"
56 
57 /* __ Compile options ____________________________________________________ */
58 //#define G_CHECK_FOR_NAN
59 
60 /* __ Function name definitions __________________________________________ */
61 #define G_XML2STRING "gammalib::xml2string(std::string&)"
62 
63 /* __ Coding definitions _________________________________________________ */
64 #define G_PARFORMAT_LENGTH 29
65 
66 
67 /***********************************************************************//**
68  * @brief Strip leading and trailing whitespace from string
69  *
70  * @param[in] arg String from which whitespace should be stripped.
71  * @return String with stripped whitespace.
72  ***************************************************************************/
73 std::string gammalib::strip_whitespace(const std::string& arg)
74 {
75  // Return result
76  return (strip_chars(arg, " "));
77 }
78 
79 
80 /***********************************************************************//**
81  * @brief Strip leading and trailing character from string
82  *
83  * @param[in] arg String from which character should be stripped.
84  * @param[in] chars Character(s) to be stripped.
85  * @return String with stripped characters.
86  ***************************************************************************/
87 std::string gammalib::strip_chars(const std::string& arg,
88  const std::string& chars)
89 {
90  // Initialise empty result string
91  std::string result;
92 
93  // Continue only if argument is not empty
94  if (!arg.empty()) {
95 
96  // Get start and stop
97  std::string::size_type start = arg.find_first_not_of(chars);
98  std::string::size_type stop = arg.find_last_not_of(chars);
99 
100  // Continue only if start and stop are valid
101  if (start != std::string::npos && stop != std::string::npos) {
102 
103  // Continue only if stop is larger then or equal to start
104  if (start <= stop) {
105  result = arg.substr(start, stop-start+1);
106  }
107 
108  } // endif: start and stop were valid
109 
110  } // endif: argument was not empty
111 
112  // Return result
113  return result;
114 }
115 
116 
117 /***********************************************************************//**
118  * @brief Strip trailing character from string
119  *
120  * @param[in] arg String from which character should be stripped.
121  * @param[in] chars Character(s) to be stripped.
122  * @return String with stripped characters.
123  ***************************************************************************/
124 std::string gammalib::rstrip_chars(const std::string& arg,
125  const std::string& chars)
126 {
127  // Initialise empty result string
128  std::string result;
129 
130  // Continue only if argument is not empty
131  if (!arg.empty()) {
132 
133  // Get stop
134  std::string::size_type stop = arg.find_last_not_of(chars);
135 
136  // Continue only if stop is valid
137  if (stop != std::string::npos) {
138  result = arg.substr(0, stop+1);
139  }
140 
141  } // endif: argument was not empty
142 
143  // Return result
144  return result;
145 }
146 
147 
148 /***********************************************************************//**
149  * @brief Replace string segment in string
150  *
151  * @param[in] arg String in which character segements are to be replaced
152  * @param[in] segment String segment to be replaced.
153  * @param[in] replacement Replacement string.
154  * @return String with replaced segements.
155  *
156  * Replaces string segments by a replacement string in a given string.
157  *
158  * If the input string @p arg is "Wonderful", the @p segment is "onder" and
159  * the @p replacement is "ish" the method will return "Wishful".
160  ***************************************************************************/
161 std::string gammalib::replace_segment(const std::string& arg,
162  const std::string& segment,
163  const std::string& replacement)
164 {
165  // Initialise result string by argument
166  std::string result = arg;
167 
168  // Initialise character pointer
169  std::string::size_type pos = 0;
170  std::string::size_type start = 0;
171 
172  // Loop over string
173  while (start != std::string::npos) {
174  start = result.find(segment, pos);
175  if (start != std::string::npos) {
176  result = result.replace(start, segment.length(), replacement);
177  pos = start + replacement.length();
178  }
179  }
180 
181  // Return result
182  return result;
183 }
184 
185 
186 /***********************************************************************//**
187  * @brief Expand environment variables in string
188  *
189  * @param[in] arg String.
190  * @return String with expected environment variables.
191  *
192  * Expands any environment variable that is found in a string. Valid
193  * delimiters for environment variables are $ENV{<name>}, $ENV(<name>),
194  * ${<name>}, $(<name>) and $<name> (in the last case the terminating
195  * delimiter is either a / or a blank character or the end of the string).
196  * Environment variables occuring within single quotes (') are ignored.
197  * Environment variables that do not exist will be kept as specified.
198  *
199  * The method also replaces ~ or ~user by the user's home directory, ~+
200  * by the value of the PWD environment variable and ~- by the value of the
201  * OLDPWD variable. If the user or the PWD or OLDPWD variable are not found,
202  * no replacement is done.
203  *
204  * This function has been inspired by the function ape_util_expand_env_var
205  * from ape_util.c in the ape software developed at HEASARC.
206  ***************************************************************************/
207 std::string gammalib::expand_env(const std::string& arg)
208 {
209  // Set environment variable delimiters
210  static const char* begin_delim[] = { "$ENV{", "$ENV(", "${", "$(", "$", "~" };
211  static const char* end_delim[] = { "}", ")", "}", ")", "/", "/" };
212  static const int num_delim = 6;
213 
214  // Initialise result with argument
215  std::string result = arg;
216 
217  // Initialise parse parameters
218  size_t index = 0;
219  bool in_quote = false;
220 
221  // Loop over string
222  while (index < result.length()) {
223 
224  // If we have an escaped character then skip the current character
225  // and the next one
226  if (result[index] == '\\') {
227  index += 2;
228  continue;
229  }
230 
231  // If we have a single quote then toggle the quote state
232  if (result[index] == '\'') {
233  in_quote = !in_quote;
234  index++;
235  continue;
236  }
237 
238  // Don't expand environment variables inside single quotes. Note
239  // that double quotes are ok.
240  if (in_quote) {
241  index++;
242  continue;
243  }
244 
245  // Find delimiter which indicates beginning of an environment variable
246  size_t begin_length = 0;
247  int delim_idx = 0;
248  for (; delim_idx < num_delim; ++delim_idx) {
249  size_t len = std::strlen(begin_delim[delim_idx]);
250  if (result.compare(index, len, begin_delim[delim_idx]) == 0) {
251  begin_length = len;
252  break;
253  }
254  }
255 
256  // If we found a delimiter then process the environment variable
257  if (begin_length > 0) {
258 
259  // Search for the termination delimiter of the environment
260  // variable. There is a special case for delimiters 4 and 5:
261  // It has always an end_length of zero as the / is not a real
262  // delimiter, but just an indicator that the environment variable
263  // ends. Another indicator is a blank. If the end of the
264  // string has been reached this is also acceptable.
265  size_t i_start = index + begin_length;
266  size_t i_end = i_start;
267  size_t end_length = 0;
268  if (delim_idx == 4 || delim_idx == 5) {
269  while (i_end < result.length() &&
270  result.compare(i_end, 1, "/") != 0 &&
271  result.compare(i_end, 1, " ") != 0) {
272  i_end++;
273  }
274  }
275  else {
276  end_length = std::strlen(end_delim[delim_idx]);
277  while (i_end < result.length() &&
278  result.compare(i_end, end_length, end_delim[delim_idx]) != 0) {
279  i_end++;
280  }
281  }
282 
283  // If termination delimiter has been found then expand the
284  // environment variable
285  if (i_end < result.length() || delim_idx == 4 || delim_idx == 5) {
286 
287  // Extract environment variable name
288  std::string name = result.substr(i_start, i_end-i_start);
289  size_t name_length = name.length();
290 
291  // Initialise pointer on environment variable
292  const char* env = NULL;
293 
294  // Handle ~
295  if (delim_idx == 5) {
296  if (name_length == 0) {
297  if ((env = std::getenv("HOME")) == NULL) {
298  struct passwd *pw = getpwuid(getuid());
299  if (pw != NULL) {
300  env = pw->pw_dir;
301  }
302  }
303  }
304  else {
305  if (name == "+") {
306  env = std::getenv("PWD");
307  }
308  else if (name == "-") {
309  env = std::getenv("OLDPWD");
310  }
311  else {
312  struct passwd *pw = getpwnam(name.c_str());
313  if (pw != NULL) {
314  env = pw->pw_dir;
315  }
316  }
317  }
318  }
319 
320  // ... otherwise get the environment variable
321  else {
322  env = std::getenv(name.c_str());
323  }
324 
325  // If the environment variable has been found then replace
326  // it by its value
327  if (env != NULL) {
328 
329  // Erase delimiters and environment variable
330  result.erase(index, begin_length+name_length+end_length);
331 
332  // Set replacement string and its length
333  std::string replace(env);
334  size_t replace_length = replace.length();
335 
336  // Insert replacement string
337  result.insert(index, replace);
338 
339  // Advance pointer
340  index += replace_length;
341 
342  } // endif: environment variable has been found
343 
344  // If no environment variable has been found then set
345  // index=i_end+1
346  else {
347  index = i_end + 1;
348  }
349 
350  } // endif: termination delimiter found
351 
352  // If no environment variable has been found then set index=i_end+1
353  else {
354  index = i_end + 1;
355  }
356 
357  } // endif: we found an environment variable delimiter
358 
359  // ... otherwise advance to next character
360  else {
361  index++;
362  }
363 
364  } // endwhile: looped over string
365 
366  // Return result
367  return result;
368 }
369 
370 
371 /***********************************************************************//**
372  * @brief Build file path from path name and file name
373  *
374  * @param[in] pathname Path name.
375  * @param[in] filename File name.
376  * @return File path.
377  *
378  * Builds a file path by combining the @p pathname and the @p filename
379  * following
380  *
381  * filepath = pathname/filename
382  *
383  * If @p pathname is an empty string, the method simply returns the
384  * @p filename.
385  ***************************************************************************/
386 std::string gammalib::filepath(const std::string& pathname,
387  const std::string& filename)
388 {
389  // Initialise filepath
390  std::string filepath;
391 
392  // If path name is empty, simply return the file name
393  if (pathname.empty()) {
394  filepath = filename;
395  }
396 
397  // ... otherwise combine both
398  else {
399  filepath = pathname + "/" + filename;
400  }
401 
402  // Return the file path
403  return filepath;
404 }
405 
406 
407 /***********************************************************************//**
408  * @brief Convert unsigned short integer value into string
409  *
410  * @param[in] value Unsigned short integer to be converted into string.
411  * @return String with unsigned short integer value.
412  ***************************************************************************/
413 std::string gammalib::str(const unsigned short int& value)
414 {
415  std::ostringstream s_value;
416  s_value << value;
417  return s_value.str();
418 }
419 
420 
421 /***********************************************************************//**
422  * @brief Convert unsigned integer value into string
423  *
424  * @param[in] value Unsigned integer to be converted into string.
425  * @return String with unsigned integer value.
426  ***************************************************************************/
427 std::string gammalib::str(const unsigned int& value)
428 {
429  std::ostringstream s_value;
430  s_value << value;
431  return s_value.str();
432 }
433 
434 
435 /***********************************************************************//**
436  * @brief Convert unsigned long integer value into string
437  *
438  * @param[in] value Unsigned long integer to be converted into string.
439  * @return String with unsigned long integer value.
440  ***************************************************************************/
441 std::string gammalib::str(const unsigned long int& value)
442 {
443  std::ostringstream s_value;
444  s_value << value;
445  return s_value.str();
446 }
447 
448 
449 /***********************************************************************//**
450  * @brief Convert unsigned long long integer value into string
451  *
452  * @param[in] value Unsigned long long integer to be converted into string.
453  * @return String with unsigned long long integer value.
454  ***************************************************************************/
455 std::string gammalib::str(const unsigned long long int& value)
456 {
457  std::ostringstream s_value;
458  s_value << value;
459  return s_value.str();
460 }
461 
462 
463 /***********************************************************************//**
464  * @brief Convert short integer value into string
465  *
466  * @param[in] value Short integer to be converted into string.
467  * @return String with short integer value.
468  ***************************************************************************/
469 std::string gammalib::str(const short int& value)
470 {
471  std::ostringstream s_value;
472  s_value << value;
473  return s_value.str();
474 }
475 
476 
477 /***********************************************************************//**
478  * @brief Convert integer value into string
479  *
480  * @param[in] value Integer to be converted into string.
481  * @return String with integer value.
482  ***************************************************************************/
483 std::string gammalib::str(const int& value)
484 {
485  std::ostringstream s_value;
486  s_value << value;
487  return s_value.str();
488 }
489 
490 
491 /***********************************************************************//**
492  * @brief Convert long integer value into string
493  *
494  * @param[in] value Long integer to be converted into string.
495  * @return String with long integer value.
496  ***************************************************************************/
497 std::string gammalib::str(const long int& value)
498 {
499  std::ostringstream s_value;
500  s_value << value;
501  return s_value.str();
502 }
503 
504 
505 /***********************************************************************//**
506  * @brief Convert long long integer value into string
507  *
508  * @param[in] value Long long integer to be converted into string.
509  * @return String with long long integer value.
510  ***************************************************************************/
511 std::string gammalib::str(const long long int& value)
512 {
513  std::ostringstream s_value;
514  s_value << value;
515  return s_value.str();
516 }
517 
518 
519 /***********************************************************************//**
520  * @brief Convert single precision value into string
521  *
522  * @param[in] value Single precision value to be converted into string.
523  * @param[in] precision Floating point precision.
524  * @return String with single precision value.
525  *
526  * Converts a single precision value into a string. Any positive
527  * @p precision argument specifies the exact number of digits after the
528  * comma.
529  ***************************************************************************/
530 std::string gammalib::str(const float& value, const int& precision)
531 {
532  // Allocate output stream
533  std::ostringstream s_value;
534 
535  // If specified then set the requested fixed point precision. Otherwise
536  // use a precision that should be sufficient for floating point values.
537  if (precision > 0) {
538  s_value.precision(precision);
539  s_value.setf(std::ios::fixed, std::ios::floatfield);
540  }
541  else {
542  s_value.precision(7);
543  }
544 
545  // Put floating point value in stream
546  s_value << value;
547 
548  // Convert to a string
549  std::string result = s_value.str();
550 
551  // Return result
552  return result;
553 }
554 
555 
556 /***********************************************************************//**
557  * @brief Convert double precision value into string
558  *
559  * @param[in] value Double precision value to be converted into string.
560  * @param[in] precision Floating point precision.
561  * @return String with double precision value.
562  *
563  * Converts a double precision value into a string. Any positive
564  * @p precision argument specifies the exact number of digits after the
565  * comma.
566  ***************************************************************************/
567 std::string gammalib::str(const double& value, const int& precision)
568 {
569  // Allocate output stream
570  std::ostringstream s_value;
571 
572  // If specified then set the requested fixed point precision. Otherwise
573  // use a precision that should be sufficient for floating point values.
574  if (precision > 0) {
575  s_value.precision(precision);
576  s_value.setf(std::ios::fixed, std::ios::floatfield);
577  }
578  else {
579  s_value.precision(15);
580  }
581 
582  // Put double precision floating point value in stream
583  s_value << value;
584 
585  // Convert to a string
586  std::string result = s_value.str();
587 
588  // Return result
589  return result;
590 }
591 
592 
593 /***********************************************************************//**
594  * @brief Convert complex value into string
595  *
596  * @param[in] value Complex value to be converted into string.
597  * @param[in] precision Floating point precision.
598  * @return String with complex value.
599  *
600  * Converts a complex value into a string. Any positive @p precision argument
601  * specifies the exact number of digits after the comma.
602  ***************************************************************************/
603 std::string gammalib::str(const std::complex<double>& value,
604  const int& precision)
605 {
606  // Allocate output stream
607  std::ostringstream s_value;
608 
609  // If specified then set the requested fixed point precision. Otherwise
610  // use a precision that should be sufficient for floating point values.
611  if (precision > 0) {
612  s_value.precision(precision);
613  s_value.setf(std::ios::fixed, std::ios::floatfield);
614  }
615  else {
616  s_value.precision(15);
617  }
618 
619  // Put double precision floating point value in stream
620  s_value << value.real();
621  if (value.imag() < 0.0) {
622  s_value << "-";
623  }
624  else {
625  s_value << "+";
626  }
627  s_value << std::abs(value.imag()) << "j";
628 
629  // Convert to a string
630  std::string result = s_value.str();
631 
632  // Return result
633  return result;
634 }
635 
636 
637 
638 /***********************************************************************//**
639  * @brief Convert string to C string
640  *
641  * @param[in] arg String to be converted.
642  * @return C string.
643  *
644  * Allocates a C string with the content of a C++ string.
645  ***************************************************************************/
646 char* gammalib::tochar(const std::string& arg)
647 {
648  // Allocate C string
649  char* str = new char[arg.length()+1];
650 
651  // Copy characters
652  for (std::size_t i = 0; i < arg.length(); ++i) {
653  str[i] = arg[i];
654  }
655 
656  // Set line end character
657  str[arg.length()] = '\0';
658 
659  // Return C string
660  return str;
661 }
662 
663 
664 /***********************************************************************//**
665  * @brief Convert string into short value
666  *
667  * @param[in] arg String to be converted.
668  * @return Short value.
669  ***************************************************************************/
670 short gammalib::toshort(const std::string& arg)
671 {
672  std::istringstream iss(arg);
673  short result;
674  iss >> std::dec >> result;
675  return result;
676 }
677 
678 
679 /***********************************************************************//**
680  * @brief Convert string into unsigned short value
681  *
682  * @param[in] arg String to be converted.
683  * @return Unsigned short value.
684  ***************************************************************************/
685 unsigned short gammalib::toushort(const std::string& arg)
686 {
687  std::istringstream iss(arg);
688  unsigned short result;
689  iss >> std::dec >> result;
690  return result;
691 }
692 
693 
694 /***********************************************************************//**
695  * @brief Convert string into integer value
696  *
697  * @param[in] arg String to be converted.
698  * @return Integer value.
699  ***************************************************************************/
700 int gammalib::toint(const std::string& arg)
701 {
702  std::istringstream iss(arg);
703  int result;
704  iss >> std::dec >> result;
705  return result;
706 }
707 
708 
709 /***********************************************************************//**
710  * @brief Convert string into unsigned integer value
711  *
712  * @param[in] arg String to be converted.
713  * @return Unsigned integer value.
714  ***************************************************************************/
715 unsigned int gammalib::touint(const std::string& arg)
716 {
717  std::istringstream iss(arg);
718  unsigned int result;
719  iss >> std::dec >> result;
720  return result;
721 }
722 
723 
724 /***********************************************************************//**
725  * @brief Convert string into long value
726  *
727  * @param[in] arg String to be converted.
728  * @return Long value.
729  ***************************************************************************/
730 long gammalib::tolong(const std::string& arg)
731 {
732  std::istringstream iss(arg);
733  long result;
734  iss >> std::dec >> result;
735  return result;
736 }
737 
738 
739 /***********************************************************************//**
740  * @brief Convert string into unsigned long value
741  *
742  * @param[in] arg String to be converted.
743  * @return Unsigned long value.
744  ***************************************************************************/
745 unsigned long gammalib::toulong(const std::string& arg)
746 {
747  std::istringstream iss(arg);
748  unsigned long result;
749  iss >> std::dec >> result;
750  return result;
751 }
752 
753 
754 /***********************************************************************//**
755  * @brief Convert string into long long value
756  *
757  * @param[in] arg String to be converted.
758  * @return Long long value.
759  ***************************************************************************/
760 long long gammalib::tolonglong(const std::string& arg)
761 {
762  std::istringstream iss(arg);
763  long long result;
764  iss >> std::dec >> result;
765  return result;
766 }
767 
768 
769 /***********************************************************************//**
770  * @brief Convert string into unsigned long long value
771  *
772  * @param[in] arg String to be converted.
773  * @return Unsigned long long value.
774  ***************************************************************************/
775 unsigned long long gammalib::toulonglong(const std::string& arg)
776 {
777  std::istringstream iss(arg);
778  unsigned long long result;
779  iss >> std::dec >> result;
780  return result;
781 }
782 
783 
784 /***********************************************************************//**
785  * @brief Convert string into single precision value
786  *
787  * @param[in] arg String to be converted.
788  * @return Single precision value.
789  ***************************************************************************/
790 float gammalib::tofloat(const std::string& arg)
791 {
792  std::istringstream iss(arg);
793  float result;
794  iss >> std::dec >> result;
795  return result;
796 }
797 
798 
799 /***********************************************************************//**
800  * @brief Convert string into double precision value
801  *
802  * @param[in] arg String to be converted.
803  * @return Double precision value.
804  ***************************************************************************/
805 double gammalib::todouble(const std::string& arg)
806 {
807  std::istringstream iss(arg);
808  double result;
809  iss >> std::dec >> result;
810  return result;
811 }
812 
813 
814 /***********************************************************************//**
815  * @brief Convert string to upper case
816  *
817  * @param[in] arg String to be converted to upper case.
818  * @return String converted to upper case.
819  ***************************************************************************/
820 std::string gammalib::toupper(const std::string& arg)
821 {
822  std::string s = arg;
823  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
824  return s;
825 }
826 
827 
828 /***********************************************************************//**
829  * @brief Convert string to lower case
830  *
831  * @param[in] arg String to be converted to upper case.
832  * @return String converted to lower case.
833  ***************************************************************************/
834 std::string gammalib::tolower(const std::string& arg)
835 {
836  std::string s = arg;
837  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
838  return s;
839 }
840 
841 
842 /***********************************************************************//**
843  * @brief Split string
844  *
845  * @param[in] s String to be splitted.
846  * @param[in] sep Separator(s).
847  * @return Vector of split strings.
848  *
849  * Splits a string on the basis of one or multiple separator characters. The
850  * separator characters are provided by the @p sep argument. Subsequent
851  * separator characters that are not seperated by some other characters will
852  * lead to an empty string element, except for a blank separator where
853  * subsequent blanks are takens as a single separator. Below a few examples
854  * that illustrate how the function will split a given string.
855  *
856  * "Name;RA;DEC" => ["Name","RA","DEC"] (sep=";")
857  * "My house is red" => ["My","house","is","red"] (sep=" ")
858  * "IRF::FRONT" => ["IRF","","FRONT"] (sep=":")
859  * "Fields;RA,DEC,Flux" => ["Fields","RA","DEC","Flux"] (sep=";,")
860  * "Last;Field;" => ["Last","Field",""] (sep=";")
861  ***************************************************************************/
862 std::vector<std::string> gammalib::split(const std::string& s,
863  const std::string& sep)
864 {
865  // Allocate result string vector
866  std::vector<std::string> result;
867 
868  // Initialise counters
869  std::size_t pos = 0;
870  std::size_t len = s.length();
871 
872  // Loop over string
873  while (pos < len && pos != std::string::npos) {
874 
875  // Get index of first separator occurence and preset the length
876  // of the substring to the end of the string
877  std::size_t index = s.find_first_of(sep, pos);
878  std::size_t n = std::string::npos;
879 
880  // If we did not reach the end then compute now the length of the
881  // substring
882  if (index != std::string::npos) {
883  n = index-pos;
884  }
885 
886  // If we have no whitespace separator and the length of the
887  // substring is zero then push back an empty string. If the
888  // length of the substring is positive then push back the
889  // substring.
890  if (sep != " " && n == 0) {
891  result.push_back("");
892  }
893  else if (n > 0) {
894  result.push_back(s.substr(pos, n));
895  }
896 
897  // Go to the string position after the last separator
898  pos = (index != std::string::npos) ? index + 1 : std::string::npos;
899 
900  // If the position is pointing right beyong the last string
901  // character we terminated with a separator, hence we need to push
902  // back one more empty string before we leave
903  if (sep != " " && pos == len) {
904  result.push_back("");
905  }
906 
907  } // endwhile: there were still characters in the string
908 
909  // Return result
910  return result;
911 }
912 
913 
914 /***********************************************************************//**
915  * @brief Fill string with n strings of same type
916  *
917  * @param[in] s String to be filled.
918  * @param[in] n Number of fillings.
919  * @return Filled strings.
920  *
921  * Replicates a given string n time.
922  ***************************************************************************/
923 std::string gammalib::fill(const std::string& s, const int& n)
924 {
925  // Initialise result
926  std::string result = "";
927 
928  // Replicate string
929  for (int i = 0; i < n; ++i) {
930  result.append(s);
931  }
932 
933  // Return result
934  return result;
935 }
936 
937 
938 /***********************************************************************//**
939  * @brief Left justify string to achieve a length of n characters
940  *
941  * @param[in] s String to be centred.
942  * @param[in] n Requested total width.
943  * @param[in] c Fill character.
944  * @return Left justified string.
945  *
946  * Left justify string by adding whitespace to the right to achieve a length
947  * of n characters.
948  ***************************************************************************/
949 std::string gammalib::left(const std::string& s, const int& n, const char& c)
950 {
951  // Compute number of characters to fill right
952  int n_right = n - s.length();
953 
954  // Set result
955  std::string result = s + fill(std::string(1,c), n_right);
956 
957  // Return result
958  return result;
959 }
960 
961 
962 /***********************************************************************//**
963  * @brief Right justify string to achieve a length of n characters
964  *
965  * @param[in] s String to be centred.
966  * @param[in] n Requested total width.
967  * @param[in] c Fill character.
968  * @return Right justified string.
969  *
970  * Right justify string by adding whitespace to the left to achieve a length
971  * of n characters.
972  ***************************************************************************/
973 std::string gammalib::right(const std::string& s, const int& n, const char& c)
974 {
975  // Compute number of characters to fill right
976  int n_left = n - s.length();
977 
978  // Set result
979  std::string result = fill(std::string(1,c), n_left) + s;
980 
981  // Return result
982  return result;
983 }
984 
985 
986 /***********************************************************************//**
987  * @brief Centre string to achieve a length of n characters
988  *
989  * @param[in] s String to be centred.
990  * @param[in] n Requested total width.
991  * @param[in] c Left fill character.
992  * @return Centred string.
993  *
994  * Centre string by adding whitespace to the left and the right to achieve a
995  * length of n characters.
996  ***************************************************************************/
997 std::string gammalib::centre(const std::string& s, const int& n, const char& c)
998 {
999  // Compute number of characters to fill left and right
1000  int n_right = (n-s.length()) / 2;
1001  int n_left = n - s.length() - n_right;
1002 
1003  // Set result
1004  std::string result = fill(std::string(1,c), n_left) + s +
1005  fill(std::string(1,c), n_right);
1006 
1007  // Return result
1008  return result;
1009 }
1010 
1011 
1012 /***********************************************************************//**
1013  * @brief Convert string in parameter format
1014  *
1015  * @param[in] s String to be converted.
1016  * @param[in] indent Indentation of parameter.
1017  * @return Parameter string.
1018  *
1019  * Converts and string into the parameter format of type "s ......: " with a
1020  * total length of G_PARFORMAT_LENGTH.
1021  ***************************************************************************/
1022 std::string gammalib::parformat(const std::string& s, const int& indent)
1023 {
1024  // Compute number of characters to fill right. Do not clip the string if
1025  // it is too long since we do not want to loose information.
1026  int n_right = G_PARFORMAT_LENGTH - s.length() - 3 - indent;
1027 
1028  // Set result
1029  std::string result = " " + s + " " + fill(".", n_right) + ": ";
1030 
1031  // Return result
1032  return result;
1033 }
1034 
1035 
1036 /***********************************************************************//**
1037  * @brief Convert singular noun into number noun
1038  *
1039  * @param[in] noun Singular noun.
1040  * @param[in] number Number of instance of noun.
1041  * @return Converted noun.
1042  *
1043  * Converts a singular noun into a number noun by appending a "s" to the
1044  * noun if the @p number of the instances of the noun is not one.
1045  ***************************************************************************/
1046 std::string gammalib::number(const std::string& noun, const int& number)
1047 {
1048  // Copy input noun
1049  std::string result(noun);
1050 
1051  // Append "s" if number if not one
1052  if (number != 1) {
1053  result += "s";
1054  }
1055 
1056  // Return result
1057  return result;
1058 }
1059 
1060 
1061 /***********************************************************************//**
1062  * @brief Compute photon flux between two energies for a power law
1063  *
1064  * @param[in] emin Minimum energy.
1065  * @param[in] emax Maximum energy.
1066  * @param[in] epivot Pivot energy.
1067  * @param[in] gamma Spectral index.
1068  * @return Photon flux under power law.
1069  *
1070  * Analytically computes
1071  * \f[\int_{E_{\rm min}}^{E_{\rm max}}
1072  * \left( E/E_{\rm pivot} \right)^{\gamma} dE\f]
1073  * where
1074  * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
1075  * energy, respectively, and
1076  * \f$E_{\rm pivot}\f$ is the pivot energy, and
1077  * \f$\gamma\f$ is the spectral index.
1078  ***************************************************************************/
1079 double gammalib::plaw_photon_flux(const double& emin, const double& emax,
1080  const double& epivot, const double& gamma)
1081 {
1082  // Initialise flux
1083  double flux = 0.0;
1084 
1085  // Continue only if emax > emin
1086  if (emax > emin) {
1087 
1088  // Compute photon flux. Computations dependend on the exponent. We
1089  // add here a kluge to assure numerical accuracy.
1090  double exponent = gamma + 1.0;
1091  if (std::abs(exponent) > 1.0e-11) {
1092  double xmin = emin / epivot;
1093  double xmax = emax / epivot;
1094  flux = epivot / exponent * (std::pow(xmax, exponent) -
1095  std::pow(xmin, exponent));
1096  }
1097  else {
1098  double ratio = emax / emin;
1099  flux = epivot * std::log(ratio);
1100  }
1101 
1102  } // endif: emax > emin
1103 
1104  // Return result
1105  return flux;
1106 }
1107 
1108 
1109 /***********************************************************************//**
1110  * @brief Compute energy flux between two energies for a power law
1111  *
1112  * @param[in] emin Minimum energy.
1113  * @param[in] emax Maximum energy.
1114  * @param[in] epivot Pivot energy.
1115  * @param[in] gamma Spectral index.
1116  * @return Energy flux under power law.
1117  *
1118  * Analytically computes
1119  * \f[\int_{E_{\rm min}}^{E_{\rm max}}
1120  * \left( E/E_{\rm pivot} \right)^{\gamma} E dE\f]
1121  * where
1122  * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
1123  * energy, respectively, and
1124  * \f$E_{\rm pivot}\f$ is the pivot energy, and
1125  * \f$\gamma\f$ is the spectral index.
1126  ***************************************************************************/
1127 double gammalib::plaw_energy_flux(const double& emin, const double& emax,
1128  const double& epivot, const double& gamma)
1129 {
1130  // Initialise flux
1131  double flux = 0.0;
1132 
1133  // Continue only if emax > emin
1134  if (emax > emin) {
1135 
1136  // Compute energy flux. Computations dependend on the exponent. We
1137  // add here a kluge to assure numerical accuracy.
1138  double exponent = gamma + 2.0;
1139  double epivot2 = epivot * epivot;
1140  if (std::abs(exponent) > 1.0e-11) {
1141  double xmin = emin / epivot;
1142  double xmax = emax / epivot;
1143  flux = epivot2 / exponent * (std::pow(xmax, exponent) -
1144  std::pow(xmin, exponent));
1145  }
1146  else {
1147  double ratio = emax / emin;
1148  flux = epivot2 * (std::log(ratio));
1149  }
1150 
1151  } // endif: emax > emin
1152 
1153  // Return result
1154  return flux;
1155 }
1156 
1157 
1158 /***********************************************************************//**
1159  * @brief Computes log mean energy
1160  *
1161  * @param[in] a First energy.
1162  * @param[in] b Second energy.
1163  * @return Log mean energy.
1164  *
1165  * Computes the logarithmic mean energy
1166  * \f$10^{0.5 * (\log E_{\rm a} + \log E_{\rm b})}\f$
1167  * for two energies.
1168  ***************************************************************************/
1170 {
1171  // Compute logarithmic mean energy
1172  GEnergy elogmean;
1173  double eloga = a.log10MeV();
1174  double elogb = b.log10MeV();
1175  elogmean.MeV(std::pow(10.0, 0.5 * (eloga + elogb)));
1176 
1177  // Return
1178  return elogmean;
1179 }
1180 
1181 
1182 /***********************************************************************//**
1183  * @brief Checks if directory exists
1184  *
1185  * @param[in] dirname Directory name.
1186  * @return True if directory exists, false otherwise.
1187  *
1188  * Checks if a directory exists. The function expands any environment
1189  * variable prior to checking.
1190  ***************************************************************************/
1191 bool gammalib::dir_exists(const std::string& dirname)
1192 {
1193  // Initialise result
1194  bool result = false;
1195 
1196  // Allocate file information structure
1197  struct stat info;
1198 
1199  // Get file information structure
1200  int ret = stat(gammalib::expand_env(dirname).c_str(), &info);
1201 
1202  // Check if we have a directory
1203  if (ret == 0 && S_ISDIR(info.st_mode)) {
1204  result = true;
1205  }
1206 
1207  // Return result
1208  return result;
1209 }
1210 
1211 
1212 /***********************************************************************//**
1213  * @brief Checks if a substring is in a string
1214  *
1215  * @param[in] str String you want to search in.
1216  * @param[in] substring String you are looking for in @p str.
1217  * @return True if a string contains a sub string.
1218  *
1219  * Checks if substring is contained in str
1220  ***************************************************************************/
1221 bool gammalib::contains(const std::string& str, const std::string& substring)
1222 {
1223  // Initialise result
1224  bool result = false;
1225 
1226  // checks if substring is in str
1227  if (str.find(substring) != std::string::npos) {
1228  result = true;
1229  }
1230 
1231  // Return result
1232  return result;
1233 }
1234 
1235 
1236 /***********************************************************************//**
1237  * @brief Checks if a string is contained in a vector of strings
1238  *
1239  * @param[in] strings Vector of strings you want to search in.
1240  * @param[in] string string you are looking for in strings.
1241  * @return True if a string is contained a vector.
1242  *
1243  * Checks if a string is contained in a vector of strings
1244  ***************************************************************************/
1245 bool gammalib::contains(const std::vector<std::string> strings,
1246  const std::string& string)
1247 {
1248  // Compute result
1249  bool result = std::find(strings.begin(), strings.end(), string) !=
1250  strings.end();
1251 
1252  // Return result
1253  return result;
1254 }
1255 
1256 
1257 /***********************************************************************//**
1258  * @brief Emits warning
1259  *
1260  * @param[in] origin Name of method that emits warning.
1261  * @param[in] message Warning message.
1262  *
1263  * Writes a warning to the console.
1264  ***************************************************************************/
1265 void gammalib::warning(const std::string& origin,
1266  const std::string& message)
1267 {
1268  // Compile option: enable/disable warnings
1269  #if defined(G_WARNINGS)
1270 
1271  // Set warning message
1272  std::string warning = "+++ WARNING in " + origin + ": " + message;
1273 
1274  // Writes warning to the console
1275  std::cout << warning << std::endl;
1276 
1277  // End of compile option
1278  #endif
1279 
1280  // Return
1281  return;
1282 }
1283 
1284 
1285 /***********************************************************************//**
1286  * @brief Convert XML character references in string to characters
1287  *
1288  * @param[in] arg String containing XML character references.
1289  * @return String with character reference replaced by respective characters.
1290  *
1291  * Converts all character references found in a string in their respective
1292  * characters. For more information about XML character references read
1293  * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
1294  ***************************************************************************/
1295 std::string gammalib::xml2str(const std::string& arg)
1296 {
1297  // Initialise string
1298  std::string result;
1299 
1300  // Iitialise position, lenghts and flags
1301  size_t length = arg.length();
1302  size_t pos = 0;
1303  size_t start = 0;
1304  size_t stop = 0;
1305  size_t len = 0; // Length of string preceeding char. reference
1306  bool found = false;
1307 
1308  // Loop over string
1309  while (pos < length) {
1310 
1311  // If we have not yet found a character reference then search for
1312  // the next one. If we do not find one we break here.
1313  if (!found) {
1314  start = arg.find("&", pos);
1315  if (start != std::string::npos) {
1316  len = start - pos;
1317  pos = start;
1318  found = true;
1319  }
1320  else {
1321  break;
1322  }
1323  }
1324 
1325  // ... otherwise search for end of the actual character reference.
1326  // Throw an exception if no end is found.
1327  else {
1328  stop = arg.find(";", pos);
1329  if (stop != std::string::npos) {
1330 
1331  // First attach leading string to the result
1332  if (len > 0) {
1333  result += arg.substr(start-len, len);
1334  }
1335 
1336  // Next extract character reference
1337  std::string cref = arg.substr(start+1, stop-start-1);
1338  len = cref.length();
1339 
1340  // Check for a numerical character reference
1341  //TODO: Check that there are only valid characters in
1342  // numerical field
1343  if (len >= 2 && cref[0] == '#') {
1344  int number = -1;
1345  if (cref[1] == 'x') {
1346  number = (int)std::strtol(cref.substr(2,len-2).c_str(), NULL, 16);
1347  }
1348  else {
1349  number = toint(cref.substr(1,len-1));
1350  }
1351  if (number != -1) {
1352  result.push_back((char)number);
1353  }
1354  else {
1355  std::string msg = "Could not extract number from "
1356  "numerical character reference &"+
1357  cref+";";
1359  }
1360  }
1361 
1362  // ... otherwise check for a character entity reference
1363  // and push back the corresponding character to the result
1364  // string
1365  else {
1366  if (cref == "quot") {
1367  result.push_back((char)34);
1368  }
1369  else if (cref == "amp") {
1370  result.push_back((char)38);
1371  }
1372  else if (cref == "apos") {
1373  result.push_back((char)39);
1374  }
1375  else if (cref == "lt") {
1376  result.push_back((char)60);
1377  }
1378  else if (cref == "gt") {
1379  result.push_back((char)62);
1380  }
1381  else {
1382  std::string msg = "Unknown character entity reference "
1383  "&"+cref+"; encountered in XML string \""+
1384  arg+"\".";
1386  }
1387  }
1388 
1389  // Signal that we're done and that we search for the
1390  // next character reference
1391  found = false;
1392  pos = stop + 1;
1393 
1394  } // endif: end of character reference found
1395 
1396  // ... otherwise throw an exception
1397  else {
1398  std::string msg = "Missing ; character at end of character "
1399  "reference in XML string \""+arg+"\".";
1401  }
1402 
1403  } // endelse: search for end of character reference
1404 
1405  } // endwhile
1406 
1407  // Append any pending string to the result
1408  if (pos < length) {
1409  len = length - pos;
1410  result += arg.substr(pos, len);
1411  }
1412 
1413  // Return result
1414  return result;
1415 }
1416 
1417 
1418 /***********************************************************************//**
1419  * @brief Convert special characters in string to XML character references
1420  *
1421  * @param[in] arg String.
1422  * @return String with special characters replaced by character references.
1423  *
1424  * Converts all special characters found in a string into character
1425  * references. For more information about XML character references read
1426  * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
1427  ***************************************************************************/
1428 std::string gammalib::str2xml(const std::string& arg)
1429 {
1430  // Initialise string
1431  std::string result;
1432 
1433  // Loop over string
1434  for (int i = 0; i < arg.length(); ++i) {
1435 
1436  // Initialize string to add
1437  std::string character = arg.substr(i, 1);
1438 
1439  // Replace special characters
1440  if (character == "\"") {
1441  character = "&quot;";
1442  }
1443  else if (character == "&") {
1444  character = "&amp;";
1445  }
1446  else if (character == "'") {
1447  character = "&apos;";
1448  }
1449  else if (character == "<") {
1450  character = "&lt;";
1451  }
1452  else if (character == ">") {
1453  character = "&gt;";
1454  }
1455 
1456  // Append character
1457  result += character;
1458 
1459  }
1460 
1461  // Return result
1462  return result;
1463 }
1464 
1465 
1466 /***********************************************************************//**
1467  * @brief Checks if parameter with given name in XML element exists
1468  *
1469  * @param[in] xml XML element.
1470  * @param[in] name Parameter name.
1471  * @return True if parameter exists, false otherwise.
1472  *
1473  * Checks whether a parameter with given @p name exists in XML element.
1474  ***************************************************************************/
1475 bool gammalib::xml_has_par(const GXmlElement& xml, const std::string& name)
1476 {
1477  // Initialize flag
1478  bool found = false;
1479 
1480  // Search for parameter with given name
1481  for (int i = 0; i < xml.elements("parameter"); ++i) {
1482  const GXmlElement* element = xml.element("parameter", i);
1483  if (element->attribute("name") == name) {
1484  found = true;
1485  break;
1486  }
1487  }
1488 
1489  // Return
1490  return found;
1491 }
1492 
1493 
1494 /***********************************************************************//**
1495  * @brief Return pointer to parameter with given name in XML element
1496  *
1497  * @param[in] origin Method requesting parameter.
1498  * @param[in] xml XML element.
1499  * @param[in] name Parameter name.
1500  * @return Pointer to parameter XML element.
1501  *
1502  * @exception GException::invalid_value
1503  * Invalid XML format encountered.
1504  *
1505  * Returns pointer to parameter with given @p name in XML element. If the
1506  * @p name is not found, a parameter with the given @p name is added. In
1507  * that respect the function differs from xml_get_par which does not add a
1508  * parameter element.
1509  *
1510  * The function checks for multiple occurences of a parameter and throws an
1511  * exception in case that more than one parameter with a given name is found.
1512  ***************************************************************************/
1513 GXmlElement* gammalib::xml_need_par(const std::string& origin,
1514  GXmlElement& xml,
1515  const std::string& name)
1516 {
1517  // Initialize XML element pointer
1518  GXmlElement* par = NULL;
1519 
1520  // Number of elements
1521  int number = 0;
1522 
1523  // Search for parameter with given name
1524  for (int i = 0; i < xml.elements("parameter"); ++i) {
1525  GXmlElement* element = xml.element("parameter", i);
1526  if (element->attribute("name") == name) {
1527  par = element;
1528  number++;
1529  }
1530  }
1531 
1532  // Create parameter if none was found
1533  if (number == 0) {
1534  par = static_cast<GXmlElement*>(xml.append(GXmlElement("parameter name=\""+name+"\"")));
1535  number++;
1536  }
1537 
1538  // Check that there are no multiple parameters
1539  gammalib::xml_check_par(origin, name, number);
1540 
1541  // Return
1542  return par;
1543 }
1544 
1545 
1546 /***********************************************************************//**
1547  * @brief Return pointer to parameter with given name in XML element
1548  *
1549  * @param[in] origin Method requesting parameter.
1550  * @param[in] xml XML element.
1551  * @param[in] name Parameter name.
1552  * @return Pointer to parameter XML element.
1553  *
1554  * @exception GException::invalid_value
1555  * Invalid XML format encountered.
1556  *
1557  * Returns pointer to parameter with given @p name in XML element. The
1558  * function checks whether the parameter has been found and throws an
1559  * exception if no parameter or multiple occurences of a parameter with given
1560  * @p name are found.
1561  ***************************************************************************/
1562 const GXmlElement* gammalib::xml_get_par(const std::string& origin,
1563  const GXmlElement& xml,
1564  const std::string& name)
1565 {
1566  // Initialize XML element pointer
1567  const GXmlElement* par = NULL;
1568 
1569  // Number of elements
1570  int number = 0;
1571 
1572  // Search for parameter with given name
1573  for (int i = 0; i < xml.elements("parameter"); ++i) {
1574  const GXmlElement* element = xml.element("parameter", i);
1575  if (element->attribute("name") == name) {
1576  par = element;
1577  number++;
1578  }
1579  }
1580 
1581  // Check that there is at least one parameter and that there are no
1582  // multiple parameters
1583  gammalib::xml_check_par(origin, name, number);
1584 
1585  // Return
1586  return par;
1587 }
1588 
1589 
1590 /***********************************************************************//**
1591  * @brief Return attribute value for a given parameter in XML element
1592  *
1593  * @param[in] origin Method requesting parameter.
1594  * @param[in] xml XML element.
1595  * @param[in] name Parameter name.
1596  * @param[in] attribute Attribute name.
1597  * @return Value of attribute.
1598  *
1599  * @exception GException::invalid_value
1600  * Attribute not found.
1601  *
1602  * Returns the value of @p attribute of parameter @p name in XML element.
1603  * The function checks whether the parameter has been found and throws an
1604  * exception if no parameter or multiple occurences of a parameter with given
1605  * @p name are found. The function furthermore checks whether the attribute
1606  * exists.
1607  ***************************************************************************/
1608 std::string gammalib::xml_get_attr(const std::string& origin,
1609  const GXmlElement& xml,
1610  const std::string& name,
1611  const std::string& attribute)
1612 {
1613  // Initialise attribute value
1614  std::string value = "";
1615 
1616  // Get parameter
1617  const GXmlElement* par = gammalib::xml_get_par(origin, xml, name);
1618 
1619  // Throw an exception if a parameter has not the requested attribute
1620  if (!par->has_attribute(attribute)) {
1621  std::string msg = "Attribute \""+attribute+"\" not found in XML "
1622  "parameter \""+name+"\". Please verify the XML "
1623  "format.";
1624  throw GException::invalid_value(origin, msg);
1625  }
1626 
1627  // Extract attribute
1628  value = par->attribute(attribute);
1629 
1630  // Return attribute value
1631  return value;
1632 }
1633 
1634 
1635 /***********************************************************************//**
1636  * @brief Checks whether a parameter has occured once
1637  *
1638  * @param[in] origin Method performing the check.
1639  * @param[in] name Parameter name.
1640  * @param[in] number Number of occurences of parameter.
1641  *
1642  * @exception GException::invalid_value
1643  * Invalid XML format encountered.
1644  *
1645  * Throws an exception if a given parameter has not exactly occured once.
1646  * The exception text is adapted to the case that none or multiple parameters
1647  * have been found.
1648  ***************************************************************************/
1649 void gammalib::xml_check_par(const std::string& origin,
1650  const std::string& name,
1651  const int& number)
1652 {
1653  // Throw case dependent exception
1654  if (number < 1) {
1655  std::string msg = "Parameter \""+name+"\" not found in XML element."
1656  " Please verify the XML format.";
1657  throw GException::invalid_value(origin, msg);
1658  }
1659  else if (number > 1) {
1660  std::string msg = "Parameter \""+name+"\" found "+
1661  gammalib::str(number)+" times in XML element."
1662  " Please verify the XML format.";
1663  throw GException::invalid_value(origin, msg);
1664  }
1665 
1666  // Return
1667  return;
1668 }
1669 
1670 
1671 /***********************************************************************//**
1672  * @brief Expand file name provided as XML attribute for loading
1673  *
1674  * @param[in] xml XML element.
1675  * @param[in] filename File name.
1676  * @return Expanded file name.
1677  *
1678  * Expands file name provided as XML attribute for loading. If the file name
1679  * is not empty and has no path it is assumed that the file is located in the
1680  * same directory as the XML file, and the XML file access path is prepended
1681  * to the file name.
1682  ***************************************************************************/
1684  const std::string& filename)
1685 {
1686  // Set file name
1687  GFilename fname(filename);
1688 
1689  // If the file name is not empty and has no path we assume that the file
1690  // name is a relative file name with respect to the XML file access path
1691  // and we therefore prepend the XML file access path to the file name
1692  if (!fname.is_empty() && fname.path().length() == 0) {
1693  fname = xml.filename().path() + fname;
1694  }
1695 
1696  // Return file name
1697  return fname;
1698 }
1699 
1700 
1701 /***********************************************************************//**
1702  * @brief Reduce file name provided for writing as XML attribute
1703  *
1704  * @param[in] xml XML element.
1705  * @param[in] filename File name.
1706  * @return Reduced file name.
1707  *
1708  * Reduces file name provided for writing as XML attribute. If the file name
1709  * is not empty and has the same access path as the XML file it is assumed
1710  * that both files are located in the same directory, and the access path is
1711  * stripped from the file name.
1712  ***************************************************************************/
1714  const std::string& filename)
1715 {
1716  // Set file name
1717  GFilename fname(filename);
1718 
1719  // If the file name is not empty and has the same access path as the XML
1720  // file it is assumed that both files are located in the same directory,
1721  // and the access path is stripped from the file name.
1722  if (!fname.is_empty() && fname.path() == xml.filename().path()) {
1723  fname = fname.file();
1724  }
1725 
1726  // Return file name
1727  return fname;
1728 }
1729 
1730 
1731 /***********************************************************************//**
1732  * @brief Extract name / value pair from XML node
1733  *
1734  * @param[in] node Pointer to XML node.
1735  * @param[out] name Name string.
1736  * @param[out] value Value string.
1737  *
1738  * Extracts a name / value pair from a XML node. If the XML node pointer is
1739  * NULL, the name and value strings will be empty.
1740  ***************************************************************************/
1742  std::string& name,
1743  std::string& value)
1744 {
1745  // Clear name and value strings
1746  name.clear();
1747  value.clear();
1748 
1749  // Continue only if node is valid
1750  if (node != NULL) {
1751 
1752  // Get name node and extract text content
1753  const GXmlNode* ptr = node->element("name", 0);
1754  if (ptr != NULL) {
1755  const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
1756  if (text != NULL) {
1757  name = text->text();
1758  }
1759  }
1760 
1761  // Get value node and extract text content
1762  ptr = node->element("value", 0);
1763  if (ptr != NULL) {
1764  const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
1765  if (text != NULL) {
1766  value = text->text();
1767  }
1768  }
1769  }
1770 
1771  // Return
1772  return;
1773 }
1774 
1775 
1776 /***********************************************************************//**
1777  * @brief Checks whether a parameter has occured once
1778  *
1779  * @param[in] fd Socket file descriptor.
1780  * @param[out] buffer Buffer to hold data.
1781  * @param[in] len Maximum number of bytes to recv().
1782  * @param[in] flags Flags (as the fourth param to recv() ).
1783  * @param[in] timeout Timeout in milliseconds.
1784  * @return recv() error code, -2 == timeout
1785  *
1786  * This function implements the recv() function with a timeout. The timeout
1787  * is specified in milliseconds.
1788  ***************************************************************************/
1789 int gammalib::recv(int fd, char *buffer, int len, int flags, int timeout)
1790 {
1791  // Initialise error code with time out
1792  int error = -2;
1793 
1794  // Initialize the set
1795  fd_set readset;
1796  FD_ZERO(&readset);
1797  FD_SET(fd, &readset);
1798 
1799  // Initialize time out struct
1800  struct timeval tv;
1801  if (timeout >= 1000) {
1802  tv.tv_sec = timeout/1000;
1803  tv.tv_usec = 0;
1804  }
1805  else {
1806  tv.tv_sec = 0;
1807  tv.tv_usec = timeout*1000;
1808  }
1809 
1810  // select()
1811  int result = select(fd+1, &readset, NULL, NULL, &tv);
1812 
1813  // Check status
1814  if (result < 0) {
1815  error = -1;
1816  }
1817  else if (result > 0 && FD_ISSET(fd, &readset)) {
1818 
1819  // Initialise flags
1820  int iof = -1;
1821 
1822  // Set non-blocking mode
1823  if ((iof = fcntl(fd, F_GETFL, 0)) != -1) {
1824  fcntl(fd, F_SETFL, iof | O_NONBLOCK);
1825  }
1826 
1827  // Receive data
1828  result = ::recv(fd, buffer, len, flags);
1829 
1830  // Set as before
1831  if (iof != -1) {
1832  fcntl(fd, F_SETFL, iof);
1833  }
1834 
1835  // Set error
1836  error = result;
1837  }
1838 
1839  // Return error
1840  return error;
1841 }
1842 
1843 
1844 /***********************************************************************//**
1845  * @brief Returns length of circular arc within circular ROI
1846  *
1847  * @param[in] rad Circle radius in radians (<pi).
1848  * @param[in] dist Circle centre distance to ROI centre (<pi).
1849  * @param[in] cosdist Cosine of circle centre distance to ROI centre.
1850  * @param[in] sindist Sinus of circle centre distance to ROI centre.
1851  * @param[in] roi Radius of ROI in radians.
1852  * @param[in] cosroi Cosine of ROI radius.
1853  *
1854  * This method returns the arclength in radians of a circle of radius 'rad'
1855  * with a centre that is offset by 'dist' from the ROI centre, where the ROI
1856  * radius is given by 'roi'. To speed-up computations, the cosines and sinus
1857  * of 'roi' and 'psf' should be calculated by the client and be passed to
1858  * the method.
1859  ***************************************************************************/
1860 double gammalib::roi_arclength(const double& rad, const double& dist,
1861  const double& cosdist, const double& sindist,
1862  const double& roi, const double& cosroi)
1863 {
1864  // Declare arclength
1865  double arclength;
1866 
1867  // Handle special case that circle centre matches ROI centre
1868  if (dist == 0.0) {
1869  if (rad > roi) arclength = 0.0; // Circle outside ROI
1870  else arclength = gammalib::twopi; // Circle inside ROI
1871  }
1872 
1873  // ... otherwise circle and ROI centres are not identical
1874  else {
1875 
1876  // Handle special case that we evaluate exactly at the circle
1877  // centre. In this case we have in fact a point, and if this point
1878  // falls within the ROI it has a formal arclength of 2pi.
1879  //
1880  if (rad == 0.0) {
1881  if (dist > roi) arclength = 0.0; // Circle centre outside ROI
1882  else arclength = gammalib::twopi; // Circle centre inside ROI
1883  }
1884 
1885  // ... otherwise we have to handle the general case
1886  else {
1887  double d = roi - dist;
1888  if (-rad >= d) {
1889  arclength = 0.0;
1890  }
1891  else if (rad <= d) {
1892  arclength = gammalib::twopi;
1893  }
1894  else {
1895  double cosrad = std::cos(rad);
1896  double sinrad = std::sin(rad);
1897  double cosang = (cosroi - cosdist*cosrad) / (sindist*sinrad);
1898  arclength = 2.0 * gammalib::acos(cosang);
1899  #if defined(G_CHECK_FOR_NAN)
1900  if (gammalib::is_infinite(arclength) ||
1901  gammalib::is_notanumber(arclength)) {
1902  std::cout << "roi_arclength: NaN occured";
1903  std::cout << " rad=" << rad;
1904  std::cout << " sinrad=" << sinrad;
1905  std::cout << " cosrad=" << cosrad;
1906  std::cout << " sindist=" << sindist;
1907  std::cout << " cosdist=" << cosdist;
1908  std::cout << " cosang=" << cosang;
1909  std::cout << std::endl;
1910  }
1911  #endif
1912  }
1913  }
1914 
1915  } // endelse: Circle and ROI centres were not identical
1916 
1917  // Return arclength
1918  return arclength;
1919 }
Abstract XML node base class.
Definition: GXmlNode.hpp:57
bool contains(const std::string &str, const std::string &substring)
Checks if a substring is in a string.
Definition: GTools.cpp:1221
void xml_get_name_value_pair(const GXmlNode *node, std::string &name, std::string &value)
Extract name / value pair from XML node.
Definition: GTools.cpp:1741
std::string file(void) const
Return name of file.
Definition: GFilename.hpp:231
std::string replace_segment(const std::string &arg, const std::string &segment, const std::string &replacement)
Replace string segment in string.
Definition: GTools.cpp:161
double roi_arclength(const double &rad, const double &dist, const double &cosdist, const double &sindist, const double &roi, const double &cosroi)
Returns length of circular arc within circular ROI.
Definition: GTools.cpp:1860
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition: GTools.cpp:1046
GFilename filename(void) const
Return filename of XML file.
Definition: GXmlNode.cpp:540
void xml_check_par(const std::string &origin, const std::string &name, const int &number)
Checks whether a parameter has occured once.
Definition: GTools.cpp:1649
Energy value class definition.
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition: GTools.cpp:1265
XML element node class interface definition.
GVector abs(const GVector &vector)
Computes absolute of vector elements.
Definition: GVector.cpp:1163
GVector cos(const GVector &vector)
Computes cosine of vector elements.
Definition: GVector.cpp:1100
bool is_empty(void) const
Signal if filename is empty.
Definition: GFilename.hpp:160
XML element node class.
Definition: GXmlElement.hpp:47
#define G_XML2STRING
Definition: GTools.cpp:61
int recv(int fd, char *buffer, int len, int flags, int timeout)
Checks whether a parameter has occured once.
Definition: GTools.cpp:1789
double acos(const double &arg)
Computes acos by avoiding NaN due to rounding errors.
Definition: GMath.cpp:69
std::string strip_chars(const std::string &arg, const std::string &chars)
Strip leading and trailing character from string.
Definition: GTools.cpp:87
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition: GTools.cpp:862
double MeV(void) const
Return energy in MeV.
Definition: GEnergy.cpp:321
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition: GXmlNode.cpp:580
Gammalib tools definition.
FITS file class interface definition.
long tolong(const std::string &arg)
Convert string into long value.
Definition: GTools.cpp:730
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition: GTools.cpp:73
GFilename xml_file_reduce(const GXmlElement &xml, const std::string &filename)
Reduce file name provided for writing as XML attribute.
Definition: GTools.cpp:1713
double plaw_energy_flux(const double &emin, const double &emax, const double &epivot, const double &gamma)
Compute energy flux between two energies for a power law.
Definition: GTools.cpp:1127
std::string centre(const std::string &s, const int &n, const char &c= ' ')
Centre string to achieve a length of n characters.
Definition: GTools.cpp:997
double log10MeV(void) const
Return log10 of energy in MeV.
Definition: GEnergy.cpp:423
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition: GTools.hpp:184
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition: GTools.hpp:167
std::string right(const std::string &s, const int &n, const char &c= ' ')
Right justify string to achieve a length of n characters.
Definition: GTools.cpp:973
std::string path(void) const
Return access path.
Definition: GFilename.hpp:217
const GXmlAttribute * attribute(const int &index) const
Return attribute.
short toshort(const std::string &arg)
Convert string into short value.
Definition: GTools.cpp:670
char * tochar(const std::string &arg)
Convert string to C string.
Definition: GTools.cpp:646
Filename class.
Definition: GFilename.hpp:62
std::string left(const std::string &s, const int &n, const char &c= ' ')
Left justify string to achieve a length of n characters.
Definition: GTools.cpp:949
bool has_attribute(const std::string &name) const
Check if element has a given attribute.
GXmlElement * xml_need_par(const std::string &origin, GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1513
XML text node class.
Definition: GXmlText.hpp:43
GVector log(const GVector &vector)
Computes natural logarithm of vector elements.
Definition: GVector.cpp:1184
const std::string & text(void) const
Return text.
Definition: GXmlText.hpp:97
bool dir_exists(const std::string &dirname)
Checks if directory exists.
Definition: GTools.cpp:1191
XML text node class interface definition.
unsigned long long toulonglong(const std::string &arg)
Convert string into unsigned long long value.
Definition: GTools.cpp:775
bool xml_has_par(const GXmlElement &xml, const std::string &name)
Checks if parameter with given name in XML element exists.
Definition: GTools.cpp:1475
std::string xml2str(const std::string &arg)
Convert XML character references in string to characters.
Definition: GTools.cpp:1295
long long tolonglong(const std::string &arg)
Convert string into long long value.
Definition: GTools.cpp:760
unsigned long toulong(const std::string &arg)
Convert string into unsigned long value.
Definition: GTools.cpp:745
std::string rstrip_chars(const std::string &arg, const std::string &chars)
Strip trailing character from string.
Definition: GTools.cpp:124
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition: GXmlNode.cpp:634
GVector pow(const GVector &vector, const double &power)
Computes tanh of vector elements.
Definition: GVector.cpp:1332
unsigned int touint(const std::string &arg)
Convert string into unsigned integer value.
Definition: GTools.cpp:715
unsigned short toushort(const std::string &arg)
Convert string into unsigned short value.
Definition: GTools.cpp:685
GVector sin(const GVector &vector)
Computes sine of vector elements.
Definition: GVector.cpp:1226
Exception handler interface definition.
std::string toupper(const std::string &s)
Convert string to upper case.
Definition: GTools.cpp:820
std::string tolower(const std::string &s)
Convert string to lower case.
Definition: GTools.cpp:834
std::string xml_get_attr(const std::string &origin, const GXmlElement &xml, const std::string &name, const std::string &attribute)
Return attribute value for a given parameter in XML element.
Definition: GTools.cpp:1608
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition: GTools.cpp:207
int toint(const std::string &arg)
Convert string into integer value.
Definition: GTools.cpp:700
const double twopi
Definition: GMath.hpp:36
std::string filepath(const std::string &pathname, const std::string &filename)
Build file path from path name and file name.
Definition: GTools.cpp:386
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition: GXmlNode.cpp:284
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1022
std::string str2xml(const std::string &arg)
Convert special characters in string to XML character references.
Definition: GTools.cpp:1428
std::string fill(const std::string &s, const int &n)
Fill string with n strings of same type.
Definition: GTools.cpp:923
#define G_PARFORMAT_LENGTH
Definition: GTools.cpp:64
Abstract XML node base class interface definition.
const GXmlElement * xml_get_par(const std::string &origin, const GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1562
Filename class interface definition.
Mathematical function definitions.
GEnergy elogmean(const GEnergy &a, const GEnergy &b)
Computes log mean energy.
Definition: GTools.cpp:1169
double todouble(const std::string &arg)
Convert string into double precision value.
Definition: GTools.cpp:805
Class that handles energies in a unit independent way.
Definition: GEnergy.hpp:48
double plaw_photon_flux(const double &emin, const double &emax, const double &epivot, const double &gamma)
Compute photon flux between two energies for a power law.
Definition: GTools.cpp:1079
float tofloat(const std::string &arg)
Convert string into single precision value.
Definition: GTools.cpp:790
GFilename xml_file_expand(const GXmlElement &xml, const std::string &filename)
Expand file name provided as XML attribute for loading.
Definition: GTools.cpp:1683
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:413