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