GammaLib 2.1.0.dev
Loading...
Searching...
No Matches
GTools.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GTools.cpp - GammaLib tools *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2008-2024 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> // geteuid(), 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 <netinet/in.h> // struct sockaddr_in, struct sockaddr
39#include <netdb.h> // struct hostent, gethostbyname
40#include <pwd.h> // getpwuid()
41#include <cmath>
42#include <cfloat>
43#include <cctype>
44#include <ctime>
45#include <cstdlib> // std::getenv() function
46#include <cstring> // std::strlen() and std::memcpy functions
47#include <iostream>
48#include <sstream>
49#include <algorithm>
50#include <cstdio> // sprintf
51#include "GTools.hpp"
52#include "GException.hpp"
53#include "GFits.hpp"
54#include "GEnergy.hpp"
55#include "GFilename.hpp"
56#include "GMath.hpp"
57#include "GXmlElement.hpp"
58#include "GXmlNode.hpp"
59#include "GXmlText.hpp"
60
61/* __ OpenMP section _____________________________________________________ */
62#ifdef _OPENMP
63#include <omp.h>
64#endif
65
66/* __ Includes for memory usage determination ____________________________ */
67#if defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
68#include <unistd.h>
69#include <sys/resource.h>
70#if defined(__APPLE__) && defined(__MACH__)
71#include <mach/mach.h>
72#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
73#include <fcntl.h>
74#include <procfs.h>
75#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
76#include <stdio.h>
77#endif
78#endif
79
80/* __ Compile options ____________________________________________________ */
81//#define G_CHECK_FOR_NAN
82//#define G_USE_CURL //!< Use curl in host_country()
83
84/* __ Function name definitions __________________________________________ */
85#define G_XML2STRING "gammalib::xml2string(std::string&)"
86#define G_HTTP_QUERY "gammalib::http_query(str::string&, std::string&)"
87
88/* __ Coding definitions _________________________________________________ */
89#define G_PARFORMAT_LENGTH 29
90#define G_CHAR_BUFFER 256
91
92
93/***********************************************************************//**
94 * @brief Strip leading and trailing whitespace from string
95 *
96 * @param[in] arg String from which whitespace should be stripped.
97 * @return String with stripped whitespace.
98 ***************************************************************************/
99std::string gammalib::strip_whitespace(const std::string& arg)
100{
101 // Return result
102 return (strip_chars(arg, " "));
103}
104
105
106/***********************************************************************//**
107 * @brief Strip leading and trailing character from string
108 *
109 * @param[in] arg String from which character should be stripped.
110 * @param[in] chars Character(s) to be stripped.
111 * @return String with stripped characters.
112 ***************************************************************************/
113std::string gammalib::strip_chars(const std::string& arg,
114 const std::string& chars)
115{
116 // Initialise empty result string
117 std::string result;
118
119 // Continue only if argument is not empty
120 if (!arg.empty()) {
121
122 // Get start and stop
123 std::string::size_type start = arg.find_first_not_of(chars);
124 std::string::size_type stop = arg.find_last_not_of(chars);
125
126 // Continue only if start and stop are valid
127 if (start != std::string::npos && stop != std::string::npos) {
128
129 // Continue only if stop is larger then or equal to start
130 if (start <= stop) {
131 result = arg.substr(start, stop-start+1);
132 }
133
134 } // endif: start and stop were valid
135
136 } // endif: argument was not empty
137
138 // Return result
139 return result;
140}
141
142
143/***********************************************************************//**
144 * @brief Strip trailing character from string
145 *
146 * @param[in] arg String from which character should be stripped.
147 * @param[in] chars Character(s) to be stripped.
148 * @return String with stripped characters.
149 ***************************************************************************/
150std::string gammalib::rstrip_chars(const std::string& arg,
151 const std::string& chars)
152{
153 // Initialise empty result string
154 std::string result;
155
156 // Continue only if argument is not empty
157 if (!arg.empty()) {
158
159 // Get stop
160 std::string::size_type stop = arg.find_last_not_of(chars);
161
162 // Continue only if stop is valid
163 if (stop != std::string::npos) {
164 result = arg.substr(0, stop+1);
165 }
166
167 } // endif: argument was not empty
168
169 // Return result
170 return result;
171}
172
173
174/***********************************************************************//**
175 * @brief Replace string segment in string
176 *
177 * @param[in] arg String in which character segements are to be replaced
178 * @param[in] segment String segment to be replaced.
179 * @param[in] replacement Replacement string.
180 * @return String with replaced segements.
181 *
182 * Replaces string segments by a replacement string in a given string.
183 *
184 * If the input string @p arg is "Wonderful", the @p segment is "onder" and
185 * the @p replacement is "ish" the method will return "Wishful".
186 ***************************************************************************/
187std::string gammalib::replace_segment(const std::string& arg,
188 const std::string& segment,
189 const std::string& replacement)
190{
191 // Initialise result string by argument
192 std::string result = arg;
193
194 // Initialise character pointer
195 std::string::size_type pos = 0;
196 std::string::size_type start = 0;
197
198 // Loop over string
199 while (start != std::string::npos) {
200 start = result.find(segment, pos);
201 if (start != std::string::npos) {
202 result = result.replace(start, segment.length(), replacement);
203 pos = start + replacement.length();
204 }
205 }
206
207 // Return result
208 return result;
209}
210
211
212/***********************************************************************//**
213 * @brief Expand environment variables in string
214 *
215 * @param[in] arg String.
216 * @return String with expected environment variables.
217 *
218 * Expands any environment variable that is found in a string. Valid
219 * delimiters for environment variables are $ENV{<name>}, $ENV(<name>),
220 * ${<name>}, $(<name>) and $<name> (in the last case the terminating
221 * delimiter is either a / or a blank character or the end of the string).
222 * Environment variables occuring within single quotes (') are ignored.
223 * Environment variables that do not exist will be kept as specified.
224 *
225 * The method also replaces ~ or ~user by the user's home directory, ~+
226 * by the value of the PWD environment variable and ~- by the value of the
227 * OLDPWD variable. If the user or the PWD or OLDPWD variable are not found,
228 * no replacement is done.
229 *
230 * This function has been inspired by the function ape_util_expand_env_var
231 * from ape_util.c in the ape software developed at HEASARC.
232 ***************************************************************************/
233std::string gammalib::expand_env(const std::string& arg)
234{
235 // Set environment variable delimiters
236 static const char* begin_delim[] = { "$ENV{", "$ENV(", "${", "$(", "$", "~" };
237 static const char* end_delim[] = { "}", ")", "}", ")", "/", "/" };
238 static const int num_delim = 6;
239
240 // Initialise result with argument
241 std::string result = arg;
242
243 // Initialise parse parameters
244 size_t index = 0;
245 bool in_quote = false;
246
247 // Loop over string
248 while (index < result.length()) {
249
250 // If we have an escaped character then skip the current character
251 // and the next one
252 if (result[index] == '\\') {
253 index += 2;
254 continue;
255 }
256
257 // If we have a single quote then toggle the quote state
258 if (result[index] == '\'') {
259 in_quote = !in_quote;
260 index++;
261 continue;
262 }
263
264 // Don't expand environment variables inside single quotes. Note
265 // that double quotes are ok.
266 if (in_quote) {
267 index++;
268 continue;
269 }
270
271 // Find delimiter which indicates beginning of an environment variable
272 size_t begin_length = 0;
273 int delim_idx = 0;
274 for (; delim_idx < num_delim; ++delim_idx) {
275 size_t len = std::strlen(begin_delim[delim_idx]);
276 if (result.compare(index, len, begin_delim[delim_idx]) == 0) {
277 begin_length = len;
278 break;
279 }
280 }
281
282 // If we found a delimiter then process the environment variable
283 if (begin_length > 0) {
284
285 // Search for the termination delimiter of the environment
286 // variable. There is a special case for delimiters 4 and 5:
287 // It has always an end_length of zero as the / is not a real
288 // delimiter, but just an indicator that the environment variable
289 // ends. Another indicator is a blank. If the end of the
290 // string has been reached this is also acceptable.
291 size_t i_start = index + begin_length;
292 size_t i_end = i_start;
293 size_t end_length = 0;
294 if (delim_idx == 4 || delim_idx == 5) {
295 while (i_end < result.length() &&
296 result.compare(i_end, 1, "/") != 0 &&
297 result.compare(i_end, 1, " ") != 0) {
298 i_end++;
299 }
300 }
301 else {
302 end_length = std::strlen(end_delim[delim_idx]);
303 while (i_end < result.length() &&
304 result.compare(i_end, end_length, end_delim[delim_idx]) != 0) {
305 i_end++;
306 }
307 }
308
309 // If termination delimiter has been found then expand the
310 // environment variable
311 if (i_end < result.length() || delim_idx == 4) {
312
313 // Extract environment variable name
314 std::string name = result.substr(i_start, i_end-i_start);
315 size_t name_length = name.length();
316
317 // Initialise pointer on environment variable
318 const char* env = NULL;
319
320 // Handle ~
321 if (delim_idx == 5) {
322 if (name_length == 0) {
323 if ((env = std::getenv("HOME")) == NULL) {
324 struct passwd *pw = getpwuid(getuid());
325 if (pw != NULL) {
326 env = pw->pw_dir;
327 }
328 }
329 }
330 else {
331 if (name == "+") {
332 env = std::getenv("PWD");
333 }
334 else if (name == "-") {
335 env = std::getenv("OLDPWD");
336 }
337 else {
338 struct passwd *pw = getpwnam(name.c_str());
339 if (pw != NULL) {
340 env = pw->pw_dir;
341 }
342 }
343 }
344 }
345
346 // ... otherwise get the environment variable
347 else {
348 env = std::getenv(name.c_str());
349 }
350
351 // If the environment variable has been found then replace
352 // it by its value
353 if (env != NULL) {
354
355 // Erase delimiters and environment variable
356 result.erase(index, begin_length+name_length+end_length);
357
358 // Set replacement string and its length
359 std::string replace(env);
360 size_t replace_length = replace.length();
361
362 // Insert replacement string
363 result.insert(index, replace);
364
365 // Advance pointer
366 index += replace_length;
367
368 } // endif: environment variable has been found
369
370 // If no environment variable has been found then set
371 // index=i_end+1
372 else {
373 index = i_end + 1;
374 }
375
376 } // endif: termination delimiter found
377
378 // If no environment variable has been found then set index=i_end+1
379 else {
380 index = i_end + 1;
381 }
382
383 } // endif: we found an environment variable delimiter
384
385 // ... otherwise advance to next character
386 else {
387 index++;
388 }
389
390 } // endwhile: looped over string
391
392 // Return result
393 return result;
394}
395
396
397/***********************************************************************//**
398 * @brief Build file path from path name and file name
399 *
400 * @param[in] pathname Path name.
401 * @param[in] filename File name.
402 * @return File path.
403 *
404 * Builds a file path by combining the @p pathname and the @p filename
405 * following
406 *
407 * filepath = pathname/filename
408 *
409 * If @p pathname is an empty string, the method simply returns the
410 * @p filename.
411 ***************************************************************************/
412std::string gammalib::filepath(const std::string& pathname,
413 const std::string& filename)
414{
415 // Initialise filepath
416 std::string filepath;
417
418 // If path name is empty, simply return the file name
419 if (pathname.empty()) {
420 filepath = filename;
421 }
422
423 // ... otherwise combine both
424 else {
425 filepath = pathname + "/" + filename;
426 }
427
428 // Return the file path
429 return filepath;
430}
431
432
433/***********************************************************************//**
434 * @brief Return temporary file name
435 *
436 * @return Temporary file name.
437 *
438 * Returns a temporary file name.
439 ***************************************************************************/
440std::string gammalib::tmpnam(void)
441{
442 // Set default temporary directory
443 char default_tmpdir[] = "/tmp";
444
445 // Get pointer to name of temporary directory by searching various
446 // possible environment variables
447 char *tmpdir = NULL;
448 if ((tmpdir = std::getenv("TEMP")) == NULL) {
449 if ((tmpdir = std::getenv("TMP")) == NULL) {
450 if ((tmpdir = std::getenv("TMPDIR")) == NULL) {
451 tmpdir = default_tmpdir;
452 }
453 }
454 }
455
456 // Allocate empty filename
457 char filename[256];
458 filename[0] = '\0';
459
460 // Combine temporary directory with temporary filename
461 strcat(filename, tmpdir);
462 strcat(filename, "/gammalibXXXXXX");
463
464 // Create temporary file
465 int fd = mkstemp(filename);
466 std::string tmpname(filename);
467 close(fd);
468 unlink(filename);
469
470 // Return temporary file name
471 return tmpname;
472}
473
474
475/***********************************************************************//**
476 * @brief Return value of environment variable
477 *
478 * @param[in] arg Environment variable
479 * @return Value of environment variable.
480 *
481 * Returns the value of an environment variable @p arg. If the environment
482 * variable is not found an empty string will be returned.
483 ***************************************************************************/
484std::string gammalib::getenv(const std::string& arg)
485{
486 // Initialise environment variable
487 std::string env;
488
489 // Get pointer to environment variable string
490 const char* ptr = std::getenv(arg.c_str());
491
492 // If pointer is not NULL then extract value of environment variable
493 if (ptr != NULL) {
494 env = std::string(ptr);
495 }
496
497 // Return environment variable
498 return env;
499}
500
501
502/***********************************************************************//**
503 * @brief Convert unsigned short integer value into string
504 *
505 * @param[in] value Unsigned short integer to be converted into string.
506 * @return String with unsigned short integer value.
507 ***************************************************************************/
508std::string gammalib::str(const unsigned short int& value)
509{
510 std::ostringstream s_value;
511 s_value << value;
512 return s_value.str();
513}
514
515
516/***********************************************************************//**
517 * @brief Convert unsigned integer value into string
518 *
519 * @param[in] value Unsigned integer to be converted into string.
520 * @return String with unsigned integer value.
521 ***************************************************************************/
522std::string gammalib::str(const unsigned int& value)
523{
524 std::ostringstream s_value;
525 s_value << value;
526 return s_value.str();
527}
528
529
530/***********************************************************************//**
531 * @brief Convert unsigned long integer value into string
532 *
533 * @param[in] value Unsigned long integer to be converted into string.
534 * @return String with unsigned long integer value.
535 ***************************************************************************/
536std::string gammalib::str(const unsigned long int& value)
537{
538 std::ostringstream s_value;
539 s_value << value;
540 return s_value.str();
541}
542
543
544/***********************************************************************//**
545 * @brief Convert unsigned long long integer value into string
546 *
547 * @param[in] value Unsigned long long integer to be converted into string.
548 * @return String with unsigned long long integer value.
549 ***************************************************************************/
550std::string gammalib::str(const unsigned long long int& value)
551{
552 std::ostringstream s_value;
553 s_value << value;
554 return s_value.str();
555}
556
557
558/***********************************************************************//**
559 * @brief Convert short integer value into string
560 *
561 * @param[in] value Short integer to be converted into string.
562 * @return String with short integer value.
563 ***************************************************************************/
564std::string gammalib::str(const short int& value)
565{
566 std::ostringstream s_value;
567 s_value << value;
568 return s_value.str();
569}
570
571
572/***********************************************************************//**
573 * @brief Convert integer value into string
574 *
575 * @param[in] value Integer to be converted into string.
576 * @param[in] fmt Format string.
577 * @return String with integer value.
578 ***************************************************************************/
579std::string gammalib::str(const int& value, const std::string& fmt)
580{
581 // Allocate character buffer
582 char buffer[G_CHAR_BUFFER];
583
584 // Put integer into buffer
585 sprintf(buffer, fmt.c_str(), value);
586
587 // Convert buffer into string
588 std::string str_buffer(buffer);
589
590 // Return string buffer
591 return str_buffer;
592}
593
594
595/***********************************************************************//**
596 * @brief Convert long integer value into string
597 *
598 * @param[in] value Long integer to be converted into string.
599 * @return String with long integer value.
600 ***************************************************************************/
601std::string gammalib::str(const long int& value)
602{
603 std::ostringstream s_value;
604 s_value << value;
605 return s_value.str();
606}
607
608
609/***********************************************************************//**
610 * @brief Convert long long integer value into string
611 *
612 * @param[in] value Long long integer to be converted into string.
613 * @return String with long long integer value.
614 ***************************************************************************/
615std::string gammalib::str(const long long int& value)
616{
617 std::ostringstream s_value;
618 s_value << value;
619 return s_value.str();
620}
621
622
623/***********************************************************************//**
624 * @brief Convert single precision value into string
625 *
626 * @param[in] value Single precision value to be converted into string.
627 * @param[in] precision Floating point precision.
628 * @return String with single precision value.
629 *
630 * Converts a single precision value into a string. Any positive
631 * @p precision argument specifies the exact number of digits after the
632 * comma.
633 ***************************************************************************/
634std::string gammalib::str(const float& value, const int& precision)
635{
636 // Allocate output stream
637 std::ostringstream s_value;
638
639 // If specified then set the requested fixed point precision. Otherwise
640 // use a precision that should be sufficient for floating point values.
641 if (precision > 0) {
642 s_value.precision(precision);
643 s_value.setf(std::ios::fixed, std::ios::floatfield);
644 }
645 else {
646 s_value.precision(7);
647 }
648
649 // Put floating point value in stream
650 s_value << value;
651
652 // Convert to a string
653 std::string result = s_value.str();
654
655 // Return result
656 return result;
657}
658
659
660/***********************************************************************//**
661 * @brief Convert double precision value into string
662 *
663 * @param[in] value Double precision value to be converted into string.
664 * @param[in] precision Floating point precision.
665 * @return String with double precision value.
666 *
667 * Converts a double precision value into a string. Any positive
668 * @p precision argument specifies the exact number of digits after the
669 * comma.
670 ***************************************************************************/
671std::string gammalib::str(const double& value, const int& precision)
672{
673 // Allocate output stream
674 std::ostringstream s_value;
675
676 // If specified then set the requested fixed point precision. Otherwise
677 // use a precision that should be sufficient for floating point values.
678 if (precision > 0) {
679 s_value.precision(precision);
680 s_value.setf(std::ios::fixed, std::ios::floatfield);
681 }
682 else {
683 s_value.precision(15);
684 }
685
686 // Put double precision floating point value in stream
687 s_value << value;
688
689 // Convert to a string
690 std::string result = s_value.str();
691
692 // Return result
693 return result;
694}
695
696
697/***********************************************************************//**
698 * @brief Convert complex value into string
699 *
700 * @param[in] value Complex value to be converted into string.
701 * @param[in] precision Floating point precision.
702 * @return String with complex value.
703 *
704 * Converts a complex value into a string. Any positive @p precision argument
705 * specifies the exact number of digits after the comma.
706 ***************************************************************************/
707std::string gammalib::str(const std::complex<double>& value,
708 const int& precision)
709{
710 // Allocate output stream
711 std::ostringstream s_value;
712
713 // If specified then set the requested fixed point precision. Otherwise
714 // use a precision that should be sufficient for floating point values.
715 if (precision > 0) {
716 s_value.precision(precision);
717 s_value.setf(std::ios::fixed, std::ios::floatfield);
718 }
719 else {
720 s_value.precision(15);
721 }
722
723 // Put double precision floating point value in stream
724 s_value << value.real();
725 if (value.imag() < 0.0) {
726 s_value << "-";
727 }
728 else {
729 s_value << "+";
730 }
731 s_value << std::abs(value.imag()) << "j";
732
733 // Convert to a string
734 std::string result = s_value.str();
735
736 // Return result
737 return result;
738}
739
740
741/***********************************************************************//**
742 * @brief Return current date
743 *
744 * Returns the current date as string in the format yyyy-mm-ddThh:mm:ss.
745 ***************************************************************************/
746std::string gammalib::strdate(void)
747{
748 // Allocate variables
749 struct std::tm timeStruct;
750 std::time_t now;
751 char buffer[100];
752
753 // Get time
754 now = std::time(NULL);
755 #ifdef HAVE_GMTIME_R
756 std::gmtime_r(&now, &timeStruct);
757 #else
758 std::memcpy(&timeStruct, gmtime(&now), sizeof(struct tm));
759 #endif
760
761 // Write message type, time and task name to buffer
762 std::sprintf(buffer, "%04d-%02d-%02dT%02d:%02d:%02d",
763 timeStruct.tm_year + 1900,
764 timeStruct.tm_mon + 1,
765 timeStruct.tm_mday,
766 timeStruct.tm_hour,
767 timeStruct.tm_min,
768 timeStruct.tm_sec);
769
770 // Build string from buffer
771 std::string date = buffer;
772
773 // Return date
774 return date;
775}
776
777
778/***********************************************************************//**
779 * @brief Convert string to C string
780 *
781 * @param[in] arg String to be converted.
782 * @return C string.
783 *
784 * Allocates a C string with the content of a C++ string.
785 ***************************************************************************/
786char* gammalib::tochar(const std::string& arg)
787{
788 // Allocate C string
789 char* str = new char[arg.length()+1];
790
791 // Copy characters
792 for (std::size_t i = 0; i < arg.length(); ++i) {
793 str[i] = arg[i];
794 }
795
796 // Set line end character
797 str[arg.length()] = '\0';
798
799 // Return C string
800 return str;
801}
802
803
804/***********************************************************************//**
805 * @brief Convert string into short value
806 *
807 * @param[in] arg String to be converted.
808 * @return Short value.
809 ***************************************************************************/
810short gammalib::toshort(const std::string& arg)
811{
812 std::istringstream iss(arg);
813 short result;
814 iss >> std::dec >> result;
815 return result;
816}
817
818
819/***********************************************************************//**
820 * @brief Convert string into unsigned short value
821 *
822 * @param[in] arg String to be converted.
823 * @return Unsigned short value.
824 ***************************************************************************/
825unsigned short gammalib::toushort(const std::string& arg)
826{
827 std::istringstream iss(arg);
828 unsigned short result;
829 iss >> std::dec >> result;
830 return result;
831}
832
833
834/***********************************************************************//**
835 * @brief Convert string into integer value
836 *
837 * @param[in] arg String to be converted.
838 * @return Integer value.
839 ***************************************************************************/
840int gammalib::toint(const std::string& arg)
841{
842 std::istringstream iss(arg);
843 int result;
844 iss >> std::dec >> result;
845 return result;
846}
847
848
849/***********************************************************************//**
850 * @brief Convert string into unsigned integer value
851 *
852 * @param[in] arg String to be converted.
853 * @return Unsigned integer value.
854 ***************************************************************************/
855unsigned int gammalib::touint(const std::string& arg)
856{
857 std::istringstream iss(arg);
858 unsigned int result;
859 iss >> std::dec >> result;
860 return result;
861}
862
863
864/***********************************************************************//**
865 * @brief Convert string into long value
866 *
867 * @param[in] arg String to be converted.
868 * @return Long value.
869 ***************************************************************************/
870long gammalib::tolong(const std::string& arg)
871{
872 std::istringstream iss(arg);
873 long result;
874 iss >> std::dec >> result;
875 return result;
876}
877
878
879/***********************************************************************//**
880 * @brief Convert string into unsigned long value
881 *
882 * @param[in] arg String to be converted.
883 * @return Unsigned long value.
884 ***************************************************************************/
885unsigned long gammalib::toulong(const std::string& arg)
886{
887 std::istringstream iss(arg);
888 unsigned long result;
889 iss >> std::dec >> result;
890 return result;
891}
892
893
894/***********************************************************************//**
895 * @brief Convert string into long long value
896 *
897 * @param[in] arg String to be converted.
898 * @return Long long value.
899 ***************************************************************************/
900long long gammalib::tolonglong(const std::string& arg)
901{
902 std::istringstream iss(arg);
903 long long result;
904 iss >> std::dec >> result;
905 return result;
906}
907
908
909/***********************************************************************//**
910 * @brief Convert string into unsigned long long value
911 *
912 * @param[in] arg String to be converted.
913 * @return Unsigned long long value.
914 ***************************************************************************/
915unsigned long long gammalib::toulonglong(const std::string& arg)
916{
917 std::istringstream iss(arg);
918 unsigned long long result;
919 iss >> std::dec >> result;
920 return result;
921}
922
923
924/***********************************************************************//**
925 * @brief Convert string into single precision value
926 *
927 * @param[in] arg String to be converted.
928 * @return Single precision value.
929 ***************************************************************************/
930float gammalib::tofloat(const std::string& arg)
931{
932 std::istringstream iss(arg);
933 float result;
934 iss >> std::dec >> result;
935 return result;
936}
937
938
939/***********************************************************************//**
940 * @brief Convert string into double precision value
941 *
942 * @param[in] arg String to be converted.
943 * @return Double precision value.
944 ***************************************************************************/
945double gammalib::todouble(const std::string& arg)
946{
947 std::istringstream iss(arg);
948 double result;
949 iss >> std::dec >> result;
950 return result;
951}
952
953
954/***********************************************************************//**
955 * @brief Convert string to upper case
956 *
957 * @param[in] arg String to be converted to upper case.
958 * @return String converted to upper case.
959 ***************************************************************************/
960std::string gammalib::toupper(const std::string& arg)
961{
962 std::string s = arg;
963 std::transform(s.begin(), s.end(), s.begin(), ::toupper);
964 return s;
965}
966
967
968/***********************************************************************//**
969 * @brief Convert string to lower case
970 *
971 * @param[in] arg String to be converted to upper case.
972 * @return String converted to lower case.
973 ***************************************************************************/
974std::string gammalib::tolower(const std::string& arg)
975{
976 std::string s = arg;
977 std::transform(s.begin(), s.end(), s.begin(), ::tolower);
978 return s;
979}
980
981
982/***********************************************************************//**
983 * @brief Split string
984 *
985 * @param[in] s String to be splitted.
986 * @param[in] sep Separator(s).
987 * @return Vector of split strings.
988 *
989 * Splits a string on the basis of one or multiple separator characters. The
990 * separator characters are provided by the @p sep argument. Subsequent
991 * separator characters that are not seperated by some other characters will
992 * lead to an empty string element, except for a blank separator where
993 * subsequent blanks are takens as a single separator. Below a few examples
994 * that illustrate how the function will split a given string.
995 *
996 * "Name;RA;DEC" => ["Name","RA","DEC"] (sep=";")
997 * "My house is red" => ["My","house","is","red"] (sep=" ")
998 * "IRF::FRONT" => ["IRF","","FRONT"] (sep=":")
999 * "Fields;RA,DEC,Flux" => ["Fields","RA","DEC","Flux"] (sep=";,")
1000 * "Last;Field;" => ["Last","Field",""] (sep=";")
1001 ***************************************************************************/
1002std::vector<std::string> gammalib::split(const std::string& s,
1003 const std::string& sep)
1004{
1005 // Allocate result string vector
1006 std::vector<std::string> result;
1007
1008 // Initialise counters
1009 std::size_t pos = 0;
1010 std::size_t len = s.length();
1011
1012 // Loop over string
1013 while (pos < len && pos != std::string::npos) {
1014
1015 // Get index of first separator occurence and preset the length
1016 // of the substring to the end of the string
1017 std::size_t index = s.find_first_of(sep, pos);
1018 std::size_t n = std::string::npos;
1019
1020 // If we did not reach the end then compute now the length of the
1021 // substring
1022 if (index != std::string::npos) {
1023 n = index-pos;
1024 }
1025
1026 // If we have no whitespace separator and the length of the
1027 // substring is zero then push back an empty string. If the
1028 // length of the substring is positive then push back the
1029 // substring.
1030 if (sep != " " && n == 0) {
1031 result.push_back("");
1032 }
1033 else if (n > 0) {
1034 result.push_back(s.substr(pos, n));
1035 }
1036
1037 // Go to the string position after the last separator
1038 pos = (index != std::string::npos) ? index + 1 : std::string::npos;
1039
1040 // If the position is pointing right beyong the last string
1041 // character we terminated with a separator, hence we need to push
1042 // back one more empty string before we leave
1043 if (sep != " " && pos == len) {
1044 result.push_back("");
1045 }
1046
1047 } // endwhile: there were still characters in the string
1048
1049 // Return result
1050 return result;
1051}
1052
1053
1054/***********************************************************************//**
1055 * @brief Fill string with n strings of same type
1056 *
1057 * @param[in] s String to be filled.
1058 * @param[in] n Number of fillings.
1059 * @return Filled strings.
1060 *
1061 * Replicates a given string n time.
1062 ***************************************************************************/
1063std::string gammalib::fill(const std::string& s, const int& n)
1064{
1065 // Initialise result
1066 std::string result = "";
1067
1068 // Replicate string
1069 for (int i = 0; i < n; ++i) {
1070 result.append(s);
1071 }
1072
1073 // Return result
1074 return result;
1075}
1076
1077
1078/***********************************************************************//**
1079 * @brief Left justify string to achieve a length of n characters
1080 *
1081 * @param[in] s String to be left justified.
1082 * @param[in] n Requested total width.
1083 * @param[in] c Fill character.
1084 * @return Left justified string.
1085 *
1086 * Left justify string by adding @p c to the right to achieve a length of
1087 * @p n characters.
1088 ***************************************************************************/
1089std::string gammalib::left(const std::string& s, const int& n, const char& c)
1090{
1091 // Compute number of characters to fill right
1092 int n_right = n - s.length();
1093
1094 // Set result
1095 std::string result = s + fill(std::string(1,c), n_right);
1096
1097 // Return result
1098 return result;
1099}
1100
1101
1102/***********************************************************************//**
1103 * @brief Right justify string to achieve a length of n characters
1104 *
1105 * @param[in] s String to be right justified.
1106 * @param[in] n Requested total width.
1107 * @param[in] c Fill character.
1108 * @return Right justified string.
1109 *
1110 * Right justify string by adding @p c to the left to achieve a length of
1111 * @p n characters.
1112 ***************************************************************************/
1113std::string gammalib::right(const std::string& s, const int& n, const char& c)
1114{
1115 // Compute number of characters to fill right
1116 int n_left = n - s.length();
1117
1118 // Set result
1119 std::string result = fill(std::string(1,c), n_left) + s;
1120
1121 // Return result
1122 return result;
1123}
1124
1125
1126/***********************************************************************//**
1127 * @brief Centre string to achieve a length of n characters
1128 *
1129 * @param[in] s String to be centred.
1130 * @param[in] n Requested total width.
1131 * @param[in] c Fill character.
1132 * @return Centred string.
1133 *
1134 * Centre string by adding @p c to the left and the right to achieve a length
1135 * of @p n characters.
1136 ***************************************************************************/
1137std::string gammalib::centre(const std::string& s, const int& n, const char& c)
1138{
1139 // Compute number of characters to fill left and right
1140 int n_right = (n-s.length()) / 2;
1141 int n_left = n - s.length() - n_right;
1142
1143 // Set result
1144 std::string result = fill(std::string(1,c), n_left) + s +
1145 fill(std::string(1,c), n_right);
1146
1147 // Return result
1148 return result;
1149}
1150
1151
1152/***********************************************************************//**
1153 * @brief Convert string in parameter format
1154 *
1155 * @param[in] s String to be converted.
1156 * @param[in] indent Indentation of parameter.
1157 * @return Parameter string.
1158 *
1159 * Converts and string into the parameter format of type "s ......: " with a
1160 * total length of G_PARFORMAT_LENGTH.
1161 ***************************************************************************/
1162std::string gammalib::parformat(const std::string& s, const int& indent)
1163{
1164 // Compute number of characters to fill right. Do not clip the string if
1165 // it is too long since we do not want to loose information.
1166 int n_right = G_PARFORMAT_LENGTH - s.length() - 3 - indent;
1167
1168 // Set result
1169 std::string result = " " + s + " " + fill(".", n_right) + ": ";
1170
1171 // Return result
1172 return result;
1173}
1174
1175
1176/***********************************************************************//**
1177 * @brief Convert singular noun into number noun
1178 *
1179 * @param[in] noun Singular noun.
1180 * @param[in] number Number of instance of noun.
1181 * @return Converted noun.
1182 *
1183 * Converts a singular noun into a number noun by appending a "s" to the
1184 * noun if the @p number of the instances of the noun is not one.
1185 ***************************************************************************/
1186std::string gammalib::number(const std::string& noun, const int& number)
1187{
1188 // Copy input noun
1189 std::string result(noun);
1190
1191 // Append "s" if number if not one
1192 if (number != 1) {
1193 result += "s";
1194 }
1195
1196 // Return result
1197 return result;
1198}
1199
1200
1201/***********************************************************************//**
1202 * @brief Compute photon flux between two energies for a power law
1203 *
1204 * @param[in] emin Minimum energy.
1205 * @param[in] emax Maximum energy.
1206 * @param[in] epivot Pivot energy.
1207 * @param[in] gamma Spectral index.
1208 * @return Photon flux under power law.
1209 *
1210 * Analytically computes
1211 * \f[\int_{E_{\rm min}}^{E_{\rm max}}
1212 * \left( E/E_{\rm pivot} \right)^{\gamma} dE\f]
1213 * where
1214 * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
1215 * energy, respectively, and
1216 * \f$E_{\rm pivot}\f$ is the pivot energy, and
1217 * \f$\gamma\f$ is the spectral index.
1218 ***************************************************************************/
1219double gammalib::plaw_photon_flux(const double& emin, const double& emax,
1220 const double& epivot, const double& gamma)
1221{
1222 // Initialise flux
1223 double flux = 0.0;
1224
1225 // Continue only if emax > emin
1226 if (emax > emin) {
1227
1228 // Compute photon flux. Computations dependend on the exponent. We
1229 // add here a kluge to assure numerical accuracy.
1230 double exponent = gamma + 1.0;
1231 if (std::abs(exponent) > 1.0e-11) {
1232 double xmin = emin / epivot;
1233 double xmax = emax / epivot;
1234 flux = epivot / exponent * (std::pow(xmax, exponent) -
1235 std::pow(xmin, exponent));
1236 }
1237 else {
1238 double ratio = emax / emin;
1239 flux = epivot * std::log(ratio);
1240 }
1241
1242 } // endif: emax > emin
1243
1244 // Return result
1245 return flux;
1246}
1247
1248
1249/***********************************************************************//**
1250 * @brief Compute energy flux between two energies for a power law
1251 *
1252 * @param[in] emin Minimum energy.
1253 * @param[in] emax Maximum energy.
1254 * @param[in] epivot Pivot energy.
1255 * @param[in] gamma Spectral index.
1256 * @return Energy flux under power law.
1257 *
1258 * Analytically computes
1259 * \f[\int_{E_{\rm min}}^{E_{\rm max}}
1260 * \left( E/E_{\rm pivot} \right)^{\gamma} E dE\f]
1261 * where
1262 * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
1263 * energy, respectively, and
1264 * \f$E_{\rm pivot}\f$ is the pivot energy, and
1265 * \f$\gamma\f$ is the spectral index.
1266 ***************************************************************************/
1267double gammalib::plaw_energy_flux(const double& emin, const double& emax,
1268 const double& epivot, const double& gamma)
1269{
1270 // Initialise flux
1271 double flux = 0.0;
1272
1273 // Continue only if emax > emin
1274 if (emax > emin) {
1275
1276 // Compute energy flux. Computations dependend on the exponent. We
1277 // add here a kluge to assure numerical accuracy.
1278 double exponent = gamma + 2.0;
1279 double epivot2 = epivot * epivot;
1280 if (std::abs(exponent) > 1.0e-11) {
1281 double xmin = emin / epivot;
1282 double xmax = emax / epivot;
1283 flux = epivot2 / exponent * (std::pow(xmax, exponent) -
1284 std::pow(xmin, exponent));
1285 }
1286 else {
1287 double ratio = emax / emin;
1288 flux = epivot2 * (std::log(ratio));
1289 }
1290
1291 } // endif: emax > emin
1292
1293 // Return result
1294 return flux;
1295}
1296
1297
1298/***********************************************************************//**
1299 * @brief Computes log mean energy
1300 *
1301 * @param[in] a First energy.
1302 * @param[in] b Second energy.
1303 * @return Log mean energy.
1304 *
1305 * Computes the logarithmic mean energy
1306 * \f$10^{0.5 * (\log E_{\rm a} + \log E_{\rm b})}\f$
1307 * for two energies.
1308 ***************************************************************************/
1310{
1311 // Compute logarithmic mean energy
1313 double eloga = a.log10MeV();
1314 double elogb = b.log10MeV();
1315 elogmean.MeV(std::pow(10.0, 0.5 * (eloga + elogb)));
1316
1317 // Return
1318 return elogmean;
1319}
1320
1321
1322/***********************************************************************//**
1323 * @brief Checks if directory exists
1324 *
1325 * @param[in] dirname Directory name.
1326 * @return True if directory exists, false otherwise.
1327 *
1328 * Checks if a directory exists. The function expands any environment
1329 * variable prior to checking.
1330 ***************************************************************************/
1331bool gammalib::dir_exists(const std::string& dirname)
1332{
1333 // Initialise result
1334 bool result = false;
1335
1336 // Allocate file information structure
1337 struct stat info;
1338
1339 // Get file information structure
1340 int ret = stat(gammalib::expand_env(dirname).c_str(), &info);
1341
1342 // Check if we have a directory
1343 if (ret == 0 && S_ISDIR(info.st_mode)) {
1344 result = true;
1345 }
1346
1347 // Return result
1348 return result;
1349}
1350
1351
1352/***********************************************************************//**
1353 * @brief Checks if a substring is in a string
1354 *
1355 * @param[in] str String you want to search in.
1356 * @param[in] substring String you are looking for in @p str.
1357 * @return True if a string contains a sub string.
1358 *
1359 * Checks if substring is contained in str
1360 ***************************************************************************/
1361bool gammalib::contains(const std::string& str, const std::string& substring)
1362{
1363 // Initialise result
1364 bool result = false;
1365
1366 // checks if substring is in str
1367 if (str.find(substring) != std::string::npos) {
1368 result = true;
1369 }
1370
1371 // Return result
1372 return result;
1373}
1374
1375
1376/***********************************************************************//**
1377 * @brief Checks if a string is contained in a vector of strings
1378 *
1379 * @param[in] strings Vector of strings you want to search in.
1380 * @param[in] string string you are looking for in strings.
1381 * @return True if a string is contained a vector.
1382 *
1383 * Checks if a string is contained in a vector of strings
1384 ***************************************************************************/
1385bool gammalib::contains(const std::vector<std::string>& strings,
1386 const std::string& string)
1387{
1388 // Compute result
1389 bool result = std::find(strings.begin(), strings.end(), string) !=
1390 strings.end();
1391
1392 // Return result
1393 return result;
1394}
1395
1396
1397/***********************************************************************//**
1398 * @brief Emits warning
1399 *
1400 * @param[in] origin Name of method that emits warning.
1401 * @param[in] message Warning message.
1402 *
1403 * Writes a warning to the console.
1404 ***************************************************************************/
1405void gammalib::warning(const std::string& origin,
1406 const std::string& message)
1407{
1408 // Compile option: enable/disable warnings
1409 #if defined(G_WARNINGS)
1410
1411 // Set warning message
1412 std::string warning = "+++ WARNING in " + origin + ": " + message;
1413
1414 // Writes warning to the console
1415 std::cout << warning << std::endl;
1416
1417 // End of compile option
1418 #endif
1419
1420 // Return
1421 return;
1422}
1423
1424
1425/***********************************************************************//**
1426 * @brief Convert XML character references in string to characters
1427 *
1428 * @param[in] arg String containing XML character references.
1429 * @return String with character reference replaced by respective characters.
1430 *
1431 * Converts all character references found in a string in their respective
1432 * characters. For more information about XML character references read
1433 * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
1434 ***************************************************************************/
1435std::string gammalib::xml2str(const std::string& arg)
1436{
1437 // Initialise string
1438 std::string result;
1439
1440 // Iitialise position, lenghts and flags
1441 size_t length = arg.length();
1442 size_t pos = 0;
1443 size_t start = 0;
1444 size_t stop = 0;
1445 size_t len = 0; // Length of string preceeding char. reference
1446 bool found = false;
1447
1448 // Loop over string
1449 while (pos < length) {
1450
1451 // If we have not yet found a character reference then search for
1452 // the next one. If we do not find one we break here.
1453 if (!found) {
1454 start = arg.find("&", pos);
1455 if (start != std::string::npos) {
1456 len = start - pos;
1457 pos = start;
1458 found = true;
1459 }
1460 else {
1461 break;
1462 }
1463 }
1464
1465 // ... otherwise search for end of the actual character reference.
1466 // Throw an exception if no end is found.
1467 else {
1468 stop = arg.find(";", pos);
1469 if (stop != std::string::npos) {
1470
1471 // First attach leading string to the result
1472 if (len > 0) {
1473 result += arg.substr(start-len, len);
1474 }
1475
1476 // Next extract character reference
1477 std::string cref = arg.substr(start+1, stop-start-1);
1478 len = cref.length();
1479
1480 // Check for a numerical character reference
1481 //TODO: Check that there are only valid characters in
1482 // numerical field
1483 if (len >= 2 && cref[0] == '#') {
1484 int number = -1;
1485 if (cref[1] == 'x') {
1486 number = (int)std::strtol(cref.substr(2,len-2).c_str(), NULL, 16);
1487 }
1488 else {
1489 number = toint(cref.substr(1,len-1));
1490 }
1491 if (number != -1) {
1492 result.push_back((char)number);
1493 }
1494 else {
1495 std::string msg = "Could not extract number from "
1496 "numerical character reference &"+
1497 cref+";";
1499 }
1500 }
1501
1502 // ... otherwise check for a character entity reference
1503 // and push back the corresponding character to the result
1504 // string
1505 else {
1506 if (cref == "quot") {
1507 result.push_back((char)34);
1508 }
1509 else if (cref == "amp") {
1510 result.push_back((char)38);
1511 }
1512 else if (cref == "apos") {
1513 result.push_back((char)39);
1514 }
1515 else if (cref == "lt") {
1516 result.push_back((char)60);
1517 }
1518 else if (cref == "gt") {
1519 result.push_back((char)62);
1520 }
1521 else {
1522 std::string msg = "Unknown character entity reference "
1523 "&"+cref+"; encountered in XML string \""+
1524 arg+"\".";
1526 }
1527 }
1528
1529 // Signal that we're done and that we search for the
1530 // next character reference
1531 found = false;
1532 pos = stop + 1;
1533
1534 } // endif: end of character reference found
1535
1536 // ... otherwise throw an exception
1537 else {
1538 std::string msg = "Missing ; character at end of character "
1539 "reference in XML string \""+arg+"\".";
1541 }
1542
1543 } // endelse: search for end of character reference
1544
1545 } // endwhile
1546
1547 // Append any pending string to the result
1548 if (pos < length) {
1549 len = length - pos;
1550 result += arg.substr(pos, len);
1551 }
1552
1553 // Return result
1554 return result;
1555}
1556
1557
1558/***********************************************************************//**
1559 * @brief Convert special characters in string to XML character references
1560 *
1561 * @param[in] arg String.
1562 * @return String with special characters replaced by character references.
1563 *
1564 * Converts all special characters found in a string into character
1565 * references. For more information about XML character references read
1566 * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
1567 ***************************************************************************/
1568std::string gammalib::str2xml(const std::string& arg)
1569{
1570 // Initialise string
1571 std::string result;
1572
1573 // Loop over string
1574 for (int i = 0; i < arg.length(); ++i) {
1575
1576 // Initialize string to add
1577 std::string character = arg.substr(i, 1);
1578
1579 // Replace special characters
1580 if (character == "\"") {
1581 character = "&quot;";
1582 }
1583 else if (character == "&") {
1584 character = "&amp;";
1585 }
1586 else if (character == "'") {
1587 character = "&apos;";
1588 }
1589 else if (character == "<") {
1590 character = "&lt;";
1591 }
1592 else if (character == ">") {
1593 character = "&gt;";
1594 }
1595
1596 // Append character
1597 result += character;
1598
1599 }
1600
1601 // Return result
1602 return result;
1603}
1604
1605
1606/***********************************************************************//**
1607 * @brief Checks if parameter with given name in XML element exists
1608 *
1609 * @param[in] xml XML element.
1610 * @param[in] name Parameter name.
1611 * @return True if parameter exists, false otherwise.
1612 *
1613 * Checks whether a parameter with given @p name exists in XML element.
1614 ***************************************************************************/
1615bool gammalib::xml_has_par(const GXmlElement& xml, const std::string& name)
1616{
1617 // Initialize flag
1618 bool found = false;
1619
1620 // Get number of elements
1621 int n = xml.elements("parameter");
1622
1623 // Search for parameter with given name
1624 for (int i = 0; i < n; ++i) {
1625 const GXmlElement* element = xml.element("parameter", i);
1626 if (element->attribute("name") == name) {
1627 found = true;
1628 break;
1629 }
1630 }
1631
1632 // Return
1633 return found;
1634}
1635
1636
1637/***********************************************************************//**
1638 * @brief Return pointer to parameter with given name in XML element
1639 *
1640 * @param[in] origin Method requesting parameter.
1641 * @param[in] xml XML element.
1642 * @param[in] name Parameter name.
1643 * @return Pointer to parameter XML element.
1644 *
1645 * @exception GException::invalid_value
1646 * Invalid XML format encountered.
1647 *
1648 * Returns pointer to parameter with given @p name in XML element. If the
1649 * @p name is not found, a parameter with the given @p name is added. In
1650 * that respect the function differs from xml_get_par which does not add a
1651 * parameter element.
1652 *
1653 * The function checks for multiple occurences of a parameter and throws an
1654 * exception in case that more than one parameter with a given name is found.
1655 ***************************************************************************/
1656GXmlElement* gammalib::xml_need_par(const std::string& origin,
1657 GXmlElement& xml,
1658 const std::string& name)
1659{
1660 // Initialize XML element pointer
1661 GXmlElement* par = NULL;
1662
1663 // Number of elements
1664 int number = 0;
1665
1666 // Get number of elements in XML element
1667 int n = xml.elements("parameter");
1668
1669 // Search for parameter with given name
1670 for (int i = 0; i < n; ++i) {
1671 GXmlElement* element = xml.element("parameter", i);
1672 if (element->attribute("name") == name) {
1673 par = element;
1674 number++;
1675 }
1676 }
1677
1678 // Create parameter if none was found
1679 if (number == 0) {
1680 par = static_cast<GXmlElement*>(xml.append(GXmlElement("parameter name=\""+name+"\"")));
1681 number++;
1682 }
1683
1684 // Check that there are no multiple parameters
1685 gammalib::xml_check_par(origin, name, number);
1686
1687 // Return
1688 return par;
1689}
1690
1691
1692/***********************************************************************//**
1693 * @brief Return pointer to parameter with given name in XML element
1694 *
1695 * @param[in] origin Method requesting parameter.
1696 * @param[in] xml XML element.
1697 * @param[in] name Parameter name.
1698 * @return Pointer to parameter XML element.
1699 *
1700 * @exception GException::invalid_value
1701 * Invalid XML format encountered.
1702 *
1703 * Returns pointer to parameter with given @p name in XML element. The
1704 * function checks whether the parameter has been found and throws an
1705 * exception if no parameter or multiple occurences of a parameter with given
1706 * @p name are found.
1707 ***************************************************************************/
1708const GXmlElement* gammalib::xml_get_par(const std::string& origin,
1709 const GXmlElement& xml,
1710 const std::string& name)
1711{
1712 // Initialize XML element pointer
1713 const GXmlElement* par = NULL;
1714
1715 // Number of elements
1716 int number = 0;
1717
1718 // Get number of elements in XML element
1719 int n = xml.elements("parameter");
1720
1721 // Search for parameter with given name
1722 for (int i = 0; i < n; ++i) {
1723 const GXmlElement* element = xml.element("parameter", i);
1724 if (element->attribute("name") == name) {
1725 par = element;
1726 number++;
1727 }
1728 }
1729
1730 // Check that there is at least one parameter and that there are no
1731 // multiple parameters
1732 gammalib::xml_check_par(origin, name, number);
1733
1734 // Return
1735 return par;
1736}
1737
1738
1739/***********************************************************************//**
1740 * @brief Return attribute value for a given parameter in XML element
1741 *
1742 * @param[in] origin Method requesting parameter.
1743 * @param[in] xml XML element.
1744 * @param[in] name Parameter name.
1745 * @param[in] attribute Attribute name.
1746 * @return Value of attribute.
1747 *
1748 * @exception GException::invalid_value
1749 * Attribute not found.
1750 *
1751 * Returns the value of @p attribute of parameter @p name in XML element.
1752 * The function checks whether the parameter has been found and throws an
1753 * exception if no parameter or multiple occurences of a parameter with given
1754 * @p name are found. The function furthermore checks whether the attribute
1755 * exists.
1756 ***************************************************************************/
1757std::string gammalib::xml_get_attr(const std::string& origin,
1758 const GXmlElement& xml,
1759 const std::string& name,
1760 const std::string& attribute)
1761{
1762 // Initialise attribute value
1763 std::string value = "";
1764
1765 // Get parameter
1766 const GXmlElement* par = gammalib::xml_get_par(origin, xml, name);
1767
1768 // Throw an exception if a parameter has not the requested attribute
1769 if (!par->has_attribute(attribute)) {
1770 std::string msg = "Attribute \""+attribute+"\" not found in XML "
1771 "parameter \""+name+"\". Please verify the XML "
1772 "format.";
1773 throw GException::invalid_value(origin, msg);
1774 }
1775
1776 // Extract attribute
1777 value = par->attribute(attribute);
1778
1779 // Return attribute value
1780 return value;
1781}
1782
1783
1784/***********************************************************************//**
1785 * @brief Checks number of parameters
1786 *
1787 * @param[in] origin Method performing the check.
1788 * @param[in] xml XML element.
1789 * @param[in] number Expected number of parameters.
1790 *
1791 * @exception GException::invalid_value
1792 * Invalid XML format encountered.
1793 *
1794 * Checks the number of parameter in an XML element.
1795 ***************************************************************************/
1796void gammalib::xml_check_parnum(const std::string& origin,
1797 const GXmlElement& xml,
1798 const int& number)
1799{
1800 // Throw exception if number of elements does not correspond to the
1801 // expected number
1802 if (xml.elements() != number) {
1803 std::string msg = "Number of "+gammalib::str(xml.elements())+
1804 " child elements in XML file does not correspond "
1805 "to expected number of "+gammalib::str(number)+
1806 " elements. Please verify the XML format.";
1807 throw GException::invalid_value(origin, msg);
1808 }
1809
1810 // Throw exception if number of "parameter" elements does not correspond
1811 // to the xpected number
1812 int npars = xml.elements("parameter");
1813 if (npars != number) {
1814 std::string msg = "Number of "+gammalib::str(npars)+" \"parameter\" "
1815 "child elements in XML file does not correspond to "
1816 "expected number of "+gammalib::str(number)+
1817 " elements. Please verify the XML format.";
1818 throw GException::invalid_value(origin, msg);
1819 }
1820
1821 // Return
1822 return;
1823}
1824
1825
1826/***********************************************************************//**
1827 * @brief Checks the model type
1828 *
1829 * @param[in] origin Method performing the check.
1830 * @param[in,out] xml XML element.
1831 * @param[in] type Expected model typeN.
1832 *
1833 * @exception GException::invalid_value
1834 * Invalid XML format encountered.
1835 *
1836 * Checks the number of parameter in an XML element.
1837 ***************************************************************************/
1838void gammalib::xml_check_type(const std::string& origin,
1839 GXmlElement& xml,
1840 const std::string& type)
1841{
1842 // If XML element has no model type then set model type
1843 if (xml.attribute("type") == "") {
1844 xml.attribute("type", type);
1845 }
1846
1847 // Throw an exception if the model type is not the expected one
1848 if (xml.attribute("type") != type) {
1849 std::string msg = "Model type \""+xml.attribute("type")+"\" is not "
1850 "the expected type \""+type+"\". Please verify "
1851 "the XML format.";
1852 throw GException::invalid_value(origin, msg);
1853 }
1854
1855 // Return
1856 return;
1857}
1858
1859
1860/***********************************************************************//**
1861 * @brief Checks whether a parameter has occured once
1862 *
1863 * @param[in] origin Method performing the check.
1864 * @param[in] name Parameter name.
1865 * @param[in] number Number of occurences of parameter.
1866 *
1867 * @exception GException::invalid_value
1868 * Invalid XML format encountered.
1869 *
1870 * Throws an exception if a given parameter has not exactly occured once.
1871 * The exception text is adapted to the case that none or multiple parameters
1872 * have been found.
1873 ***************************************************************************/
1874void gammalib::xml_check_par(const std::string& origin,
1875 const std::string& name,
1876 const int& number)
1877{
1878 // Throw case dependent exception
1879 if (number < 1) {
1880 std::string msg = "Parameter \""+name+"\" not found in XML element."
1881 " Please verify the XML format.";
1882 throw GException::invalid_value(origin, msg);
1883 }
1884 else if (number > 1) {
1885 std::string msg = "Parameter \""+name+"\" found "+
1886 gammalib::str(number)+" times in XML element."
1887 " Please verify the XML format.";
1888 throw GException::invalid_value(origin, msg);
1889 }
1890
1891 // Return
1892 return;
1893}
1894
1895
1896/***********************************************************************//**
1897 * @brief Expand file name provided as XML attribute for loading
1898 *
1899 * @param[in] xml XML element.
1900 * @param[in] filename File name.
1901 * @return Expanded file name.
1902 *
1903 * Expands file name provided as XML attribute for loading. The XML file
1904 * access path will be prepended to the file name access path if the file
1905 * name has not an absolute path and if the file name access path does not
1906 * start with the XML file access path.
1907 ***************************************************************************/
1909 const std::string& filename)
1910{
1911 // Set file name
1912 GFilename fname(filename);
1913
1914 // If the file name is not empty and is not an absolute path then we
1915 // assume that the filename is a relative file name with respect to the
1916 // XML file access path and we therefore prepend the XML file access path
1917 // to the file name
1918 if (!fname.is_empty()) {
1919 size_t access_length = fname.path().length();
1920 size_t xml_length = xml.filename().path().length();
1921
1922 // If filename has no access path and the XML file has an access path
1923 // then preprend the XML file access path
1924 if (access_length == 0) {
1925 if (xml_length > 0) {
1926 fname = xml.filename().path() + fname;
1927 }
1928 }
1929
1930 // If filename assess path is not absolute then continue ...
1931 else if (fname.path()[0] != '/') {
1932
1933 // If XML file access path is not contained in file name access
1934 // path then prepend the XML file access path
1935 if (access_length >= xml_length) {
1936 if (fname.path().compare(0, xml_length, xml.filename().path()) != 0) {
1937 fname = xml.filename().path() + fname;
1938 }
1939 }
1940
1941 // If file name access pass is shorter than XML file access path
1942 // then prepend the XML file access path
1943 else {
1944 fname = xml.filename().path() + fname;
1945 }
1946 }
1947 }
1948
1949 // Return file name
1950 return fname;
1951}
1952
1953
1954/***********************************************************************//**
1955 * @brief Reduce file name provided for writing as XML attribute
1956 *
1957 * @param[in] xml XML element.
1958 * @param[in] filename File name.
1959 * @return Reduced file name.
1960 *
1961 * Reduces file name provided for writing as XML attribute. If the file name
1962 * is not empty and its access path starts has the same access path as the
1963 * XML file the XML file access path is stripped from the file name.
1964 ***************************************************************************/
1966 const std::string& filename)
1967{
1968 // Set file name
1969 GFilename fname(filename);
1970
1971 // If the file name is not empty and the access path starts with the
1972 // same characters as the XML file access path then we assume that the
1973 // access path has been added and hence we strip it now
1974 if (!fname.is_empty()) {
1975 size_t access_length = fname.path().length();
1976 size_t xml_length = xml.filename().path().length();
1977 if (xml_length > 0) {
1978 if (access_length == xml_length) {
1979 if (fname.path() == xml.filename().path()) {
1980 fname = fname.file();
1981 }
1982 }
1983 else if (access_length > xml_length) {
1984 if (fname.path().compare(0, xml_length, xml.filename().path()) == 0) {
1985 std::string relpath = fname.path().substr(xml_length, access_length-xml_length);
1986 fname = GFilename(relpath + fname.file());
1987 }
1988 }
1989 }
1990 }
1991
1992 // Return file name
1993 return fname;
1994}
1995
1996
1997/***********************************************************************//**
1998 * @brief Extract name / value pair from XML node
1999 *
2000 * @param[in] node Pointer to XML node.
2001 * @param[out] name Name string.
2002 * @param[out] value Value string.
2003 *
2004 * Extracts a name / value pair from a XML node. If the XML node pointer is
2005 * NULL, the name and value strings will be empty.
2006 ***************************************************************************/
2008 std::string& name,
2009 std::string& value)
2010{
2011 // Clear name and value strings
2012 name.clear();
2013 value.clear();
2014
2015 // Continue only if node is valid
2016 if (node != NULL) {
2017
2018 // Get name node and extract text content
2019 const GXmlNode* ptr = node->element("name", 0);
2020 if (ptr != NULL) {
2021 const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
2022 if (text != NULL) {
2023 name = text->text();
2024 }
2025 }
2026
2027 // Get value node and extract text content
2028 ptr = node->element("value", 0);
2029 if (ptr != NULL) {
2030 const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
2031 if (text != NULL) {
2032 value = text->text();
2033 }
2034 }
2035 }
2036
2037 // Return
2038 return;
2039}
2040
2041
2042/***********************************************************************//**
2043 * @brief Checks whether a parameter has occured once
2044 *
2045 * @param[in] fd Socket file descriptor.
2046 * @param[out] buffer Buffer to hold data.
2047 * @param[in] len Maximum number of bytes to recv().
2048 * @param[in] flags Flags (as the fourth param to recv() ).
2049 * @param[in] timeout Timeout in milliseconds.
2050 * @return recv() error code, -2 == timeout
2051 *
2052 * This function implements the recv() function with a timeout. The timeout
2053 * is specified in milliseconds.
2054 ***************************************************************************/
2055int gammalib::recv(int fd, char *buffer, int len, int flags, int timeout)
2056{
2057 // Initialise error code with time out
2058 int error = -2;
2059
2060 // Initialize the set
2061 fd_set readset;
2062 FD_ZERO(&readset);
2063 FD_SET(fd, &readset);
2064
2065 // Initialize time out struct
2066 struct timeval tv;
2067 if (timeout >= 1000) {
2068 tv.tv_sec = timeout/1000;
2069 tv.tv_usec = 0;
2070 }
2071 else {
2072 tv.tv_sec = 0;
2073 tv.tv_usec = timeout*1000;
2074 }
2075
2076 // select()
2077 int result = select(fd+1, &readset, NULL, NULL, &tv);
2078
2079 // Check status
2080 if (result < 0) {
2081 error = -1;
2082 }
2083 else if (result > 0 && FD_ISSET(fd, &readset)) {
2084
2085 // Initialise flags
2086 int iof = -1;
2087
2088 // Set non-blocking mode
2089 if ((iof = fcntl(fd, F_GETFL, 0)) != -1) {
2090 fcntl(fd, F_SETFL, iof | O_NONBLOCK);
2091 }
2092
2093 // Receive data
2094 result = ::recv(fd, buffer, len, flags);
2095
2096 // Set as before
2097 if (iof != -1) {
2098 fcntl(fd, F_SETFL, iof);
2099 }
2100
2101 // Set error
2102 error = result;
2103 }
2104
2105 // Return error
2106 return error;
2107}
2108
2109
2110/***********************************************************************//**
2111 * @brief Returns length of circular arc within circular ROI
2112 *
2113 * @param[in] rad Circle radius in radians (<pi).
2114 * @param[in] dist Circle centre distance to ROI centre (<pi).
2115 * @param[in] cosdist Cosine of circle centre distance to ROI centre.
2116 * @param[in] sindist Sinus of circle centre distance to ROI centre.
2117 * @param[in] roi Radius of ROI in radians.
2118 * @param[in] cosroi Cosine of ROI radius.
2119 *
2120 * This method returns the arclength in radians of a circle of radius 'rad'
2121 * with a centre that is offset by 'dist' from the ROI centre, where the ROI
2122 * radius is given by 'roi'. To speed-up computations, the cosines and sinus
2123 * of 'roi' and 'psf' should be calculated by the client and be passed to
2124 * the method.
2125 ***************************************************************************/
2126double gammalib::roi_arclength(const double& rad, const double& dist,
2127 const double& cosdist, const double& sindist,
2128 const double& roi, const double& cosroi)
2129{
2130 // Declare arclength
2131 double arclength;
2132
2133 // Handle special case that circle centre matches ROI centre
2134 if (dist == 0.0) {
2135 if (rad > roi) arclength = 0.0; // Circle outside ROI
2136 else arclength = gammalib::twopi; // Circle inside ROI
2137 }
2138
2139 // ... otherwise circle and ROI centres are not identical
2140 else {
2141
2142 // Handle special case that we evaluate exactly at the circle
2143 // centre. In this case we have in fact a point, and if this point
2144 // falls within the ROI it has a formal arclength of 2pi.
2145 //
2146 if (rad == 0.0) {
2147 if (dist > roi) arclength = 0.0; // Circle centre outside ROI
2148 else arclength = gammalib::twopi; // Circle centre inside ROI
2149 }
2150
2151 // ... otherwise we have to handle the general case
2152 else {
2153 double d = roi - dist;
2154 if (-rad >= d) {
2155 arclength = 0.0;
2156 }
2157 else if (rad <= d) {
2158 arclength = gammalib::twopi;
2159 }
2160 else {
2161 double cosrad = std::cos(rad);
2162 double sinrad = std::sin(rad);
2163 double cosang = (cosroi - cosdist*cosrad) / (sindist*sinrad);
2164 arclength = 2.0 * gammalib::acos(cosang);
2165 #if defined(G_CHECK_FOR_NAN)
2166 if (gammalib::is_infinite(arclength) ||
2167 gammalib::is_notanumber(arclength)) {
2168 std::cout << "roi_arclength: NaN occured";
2169 std::cout << " rad=" << rad;
2170 std::cout << " sinrad=" << sinrad;
2171 std::cout << " cosrad=" << cosrad;
2172 std::cout << " sindist=" << sindist;
2173 std::cout << " cosdist=" << cosdist;
2174 std::cout << " cosang=" << cosang;
2175 std::cout << std::endl;
2176 }
2177 #endif
2178 }
2179 }
2180
2181 } // endelse: Circle and ROI centres were not identical
2182
2183 // Return arclength
2184 return arclength;
2185}
2186
2187
2188/***********************************************************************//**
2189 * @brief Compare two floating point values with tolerance
2190 *
2191 * @param[in] a First floating point value.
2192 * @param[in] b Second floating point value.
2193 * @param[in] tol Relative tolerance.
2194 * @return True if both floating point values are identical within
2195 * the tolerance.
2196 *
2197 * This method tests whether @p a is identical to @p b within a given
2198 * relative tolerance @p tol. The test verifies whether
2199 *
2200 * \f[|a - b| \le |a \times tol|\f]
2201 *
2202 * for \f$a \ne 0\f$ or whether
2203 *
2204 * \f[|a - b| \le |b \times tol|\f]
2205 *
2206 * for \f$b \ne 0\f$. If both \f$a = 0\f$ and \f$b = 0\f$ the method
2207 * returns true.
2208 ***************************************************************************/
2209bool gammalib::compare(const double& a, const double& b, const double& tol)
2210{
2211 // Initialise identity
2212 bool identity = false;
2213
2214 // Case A: a is not zero
2215 if (a != 0.0) {
2216 identity = std::abs(a - b) <= std::abs(a * tol);
2217 }
2218
2219 // Case B: b is not zero
2220 else if (b != 0.0) {
2221 identity = std::abs(a - b) <= std::abs(b * tol);
2222 }
2223
2224 // Case C: a and b are zero
2225 else {
2226 identity = true;
2227 }
2228
2229 // Return identity
2230 return identity;
2231}
2232
2233
2234/***********************************************************************//**
2235 * @brief Return response to a HTTP query
2236 *
2237 * @param[in] host Host address.
2238 * @param[in] query Query string.
2239 * @return Response to a HTTP query.
2240 *
2241 * @exception GException::runtime_error
2242 * Unable to open or to connect to socket.
2243 * @exception GException::invalid_argument
2244 * Host not found.
2245 *
2246 * Returns response to a HTTP query. Be aware that this method will not
2247 * work for https servers.
2248 ***************************************************************************/
2249std::string gammalib::http_query(const std::string& host, const std::string& query)
2250{
2251 // Set constants
2252 const int portno = 80;
2253
2254 // Initialise buffers
2255 char message[1024];
2256 char response[4096];
2257 memset(message, 0, sizeof(message));
2258 memset(response, 0, sizeof(response));
2259
2260 // Build message string
2261 sprintf(message, "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", query.c_str(), host.c_str());
2262
2263 // Create the socket
2264 int sockfd = socket(AF_INET, SOCK_STREAM, 0);
2265 if (sockfd < 0) {
2266 std::string msg = "Unable to open socket.";
2268 }
2269
2270 // Lookup IP address
2271 struct hostent* server = gethostbyname(host.c_str());
2272 if (server == NULL) {
2273 std::string msg = "Unable to find host \""+host+"\".";
2275 }
2276
2277 // Fill in structure
2278 struct sockaddr_in serveraddr;
2279 memset(&serveraddr, 0, sizeof(serveraddr));
2280 serveraddr.sin_family = AF_INET;
2281 memcpy(&serveraddr.sin_addr.s_addr, server->h_addr, server->h_length);
2282 serveraddr.sin_port = htons(portno);
2283
2284 // Connect the socket
2285 if (connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) {
2286 std::string msg = "Unable to connect to socket for host \""+host+"\".";
2288 }
2289
2290 // Send request
2291 write(sockfd, message, strlen(message));
2292
2293 // Receive response
2294 read(sockfd, response, sizeof(response)-1);
2295
2296 // Close socket
2297 close(sockfd);
2298
2299 // Return response
2300 return std::string(response);
2301}
2302
2303
2304#if defined(G_USE_CURL)
2305/***********************************************************************//**
2306 * @brief Return two-digit host country code
2307 *
2308 * @param[in] force_query Force query of host country code?
2309 * @return Host two-digit host country code.
2310 *
2311 * Returns two-digit host country code, either by reading the code from the
2312 * $HOME/.gamma/host-country file, or if the file does not exist, by using
2313 * the http query
2314 * http://ip-api.com/line/?fields=countryCode.
2315 *
2316 * The result is saved in a static variable, hence once the country code is
2317 * retrieved no queries will be executed anymore. The http query is issued
2318 * using the curl tool with a timeout of one second. If the query fails,
2319 * or the curl tool is not available, the method returns an empty string.
2320 *
2321 * If no host-country file exists and the method retrieved a two-digit
2322 * country code it will write the results into a host-country file.
2323 ***************************************************************************/
2324#else
2325/***********************************************************************//**
2326 * @brief Return two-digit host country code
2327 *
2328 * @param[in] force_query Force query of host country code?
2329 * @return Host two-digit host country code.
2330 *
2331 * Returns two-digit host country code, either by reading the code from the
2332 * $HOME/.gamma/host-country file, or if the file does not exist, by using
2333 * the http query
2334 * http://ip-api.com/line/?fields=countryCode.
2335 *
2336 * The result is saved in a static variable, hence once the country code is
2337 * retrieved no queries will be executed anymore. The http query is issued
2338 * using the http_query() method. If the query fails the method returns an
2339 * empty string.
2340 *
2341 * If no host-country file exists and the method retrieved a two-digit
2342 * country code it will write the results into a host-country file.
2343 ***************************************************************************/
2344#endif
2345std::string gammalib::host_country(const bool& force_query)
2346{
2347 // Initialise country as static variable
2348 static std::string country;
2349
2350 // Continue only if host country is empty
2351 if (country.empty()) {
2352
2353 // Attempt to get host country from $HOME/.gamma/host-country file
2354 GFilename filename = gammalib::gamma_filename("host-country");
2355
2356 // Continue only if file exists
2357 if ((!force_query) && (access(filename.url().c_str(), R_OK) == 0)) {
2358
2359 // OpenMP critical zone to read host-country file
2360 #pragma omp critical(GammaLib_host_country)
2361 {
2362
2363 // Get file lock. Continue only in case of success.
2364 struct flock lock;
2365 lock.l_type = F_RDLCK; // Want a read lock
2366 lock.l_whence = SEEK_SET; // Want beginning of file
2367 lock.l_start = 0; // No offset, lock entire file ...
2368 lock.l_len = 0; // ... to the end
2369 lock.l_pid = getpid(); // Current process ID
2370 int fd = open(filename.url().c_str(), O_RDONLY);
2371 if (fd != -1) {
2372
2373 // Lock file
2374 fcntl(fd, F_SETLKW, &lock);
2375
2376 // Open host-country file. Continue only if opening was
2377 // successful.
2378 FILE* fptr = fopen(filename.url().c_str(), "r");
2379 if (fptr != NULL) {
2380
2381 // Allocate line buffer
2382 const int n = 1000;
2383 char line[n];
2384
2385 // Read line
2386 fgets(line, n-1, fptr);
2387
2388 // Close file
2389 fclose(fptr);
2390
2391 // Extract country string
2392 country = gammalib::strip_chars(std::string(line), "\n");
2393
2394 } // endif: host-country file opened successfully
2395
2396 // Unlock file
2397 lock.l_type = F_UNLCK;
2398 fcntl(fd, F_SETLK, &lock);
2399 close(fd);
2400
2401 } // endif: file locking successful
2402
2403 } // end of OMP critial zone
2404
2405 } // endif: file existed
2406
2407 // ... otherwise there is no host-country file then get the
2408 // information from a geolocalisation web site
2409 else {
2410
2411 // If curl should be used, the curl tool is available and the
2412 // country code is not set then determine the country code
2413 // from a geolocalisation web site
2414 #if defined(G_USE_CURL)
2415 #if defined(G_HAS_CURL)
2416 // If curl is available then use curl to infer the country code
2417 char command[256];
2418
2419 // Setup curl command with timeout if possible to avoid lock up
2420 #if defined(G_HAS_PERL)
2421 sprintf(command, "a=$(perl -e 'alarm shift; exec \"curl --silent"
2422 " http://ip-api.com/line/?fields=countryCode"
2423 " 2>/dev/null\"' \"1\";);echo $a");
2424 #elif defined(G_HAS_TIMEOUT)
2425 sprintf(command, "timeout 1s curl --silent http://ip-api.com/line/"
2426 "?fields=countryCode 2>/dev/null");
2427 #else
2428 sprintf(command, "curl --silent http://ip-api.com/line/?fields=countryCode"
2429 " 2>/dev/null");
2430 #endif
2431
2432 // Open the process with given 'command' for reading
2433 FILE* file = popen(command, "r");
2434
2435 // Retrieve curl output
2436 char output[1024];
2437 if (fgets(output, sizeof(output)-1, file) != NULL) {
2438 country = strip_chars(std::string(output), "\n");
2439 }
2440
2441 // Close process
2442 pclose(file);
2443 #endif
2444
2445 // ... otherwise use the http_query method. Catch any exceptions.
2446 #else
2447 try {
2448 std::string response = http_query("ip-api.com", "line/?fields=countryCode");
2449 std::vector<std::string> lines = split(response, "\n");
2450 bool body = false;
2451 for (int i = 0; i < lines.size(); ++i) {
2452 if (body) {
2453 country = lines[i];
2454 break;
2455 }
2456 if ((lines[i] == "\n") || (lines[i] == "\r") || (lines[i] == " ")) {
2457 body = true;
2458 }
2459 }
2460 } // endtry
2461 catch (const std::exception& e) {
2462 //
2463 }
2464 #endif
2465
2466 // If we have a two-digit country code then write the code into
2467 // host-country file
2468 if (country.length() == 2) {
2469
2470 // OpenMP critical zone to write host-country file
2471 #pragma omp critical(GammaLib_host_country)
2472 {
2473
2474 // Open host-country file, and in case of success, write
2475 // country
2476 FILE* fptr = fopen(filename.url().c_str(), "w");
2477 if (fptr != NULL) {
2478 fprintf(fptr, "%s\n", country.c_str());
2479 fclose(fptr);
2480 }
2481
2482 } // end of OMP critial zone
2483
2484 } // endif: had no two digit country code
2485
2486 } // endelse: there was no host country file
2487
2488 } // endif: host country was empty
2489
2490 // Return country
2491 return country;
2492}
2493
2494
2495/***********************************************************************//**
2496 * @brief Returns filename in .gamma directory
2497 *
2498 * @param[in] name Name of file in .gamma directory.
2499 * @return Filename in .gamma directory.
2500 *
2501 * Returns the filename of the name of a file in the .gamma directory.
2502 ***************************************************************************/
2503GFilename gammalib::gamma_filename(const std::string& name)
2504{
2505 // Initialise lock filename
2506 GFilename filename;
2507
2508 // First try accessing the user ID to get the home directory
2509 uid_t uid = geteuid();
2510 struct passwd* pw = getpwuid(uid);
2511 if (pw != NULL) {
2512 filename = std::string(pw->pw_dir) + "/.gamma/" + name;
2513 }
2514
2515 // ... otherwise try using the $HOME environment variable
2516 else {
2517
2518 // First attempt fetching $HOME environment variable
2519 char* home_ptr = std::getenv("HOME");
2520 if (home_ptr != NULL) {
2521 filename = std::string(home_ptr) + "/.gamma/" + name;
2522 }
2523
2524 // ... otherwise use ~ as home directory
2525 else {
2526 filename = "~/.gamma/" + name;
2527 }
2528 }
2529
2530 // Return filename
2531 return filename;
2532}
2533
2534
2535/***********************************************************************//**
2536 * @brief Get current resident set size (physical memory use) in Bytes
2537 *
2538 * @return Physical memory use in Bytes.
2539 ***************************************************************************/
2541{
2542 // Initialize resident set size
2543 size_t rss = 0;
2544
2545 // Determine resident set size (architecture dependent)
2546 // OSX
2547 #if defined(__APPLE__) && defined(__MACH__)
2548 #ifdef MACH_TASK_BASIC_INFO
2549 struct mach_task_basic_info info;
2550 mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
2551 if (task_info(mach_task_self( ), MACH_TASK_BASIC_INFO,
2552 (task_info_t)&info, &infoCount) == KERN_SUCCESS) {
2553 rss = (size_t)info.resident_size;
2554 }
2555 #else
2556 struct task_basic_info info;
2557 mach_msg_type_number_t info_count = TASK_BASIC_INFO_COUNT;
2558 if (task_info(mach_task_self(), TASK_BASIC_INFO,
2559 (task_info_t)&info, &info_count) == KERN_SUCCESS) {
2560 rss = (size_t)info.resident_size;
2561 }
2562 #endif
2563 // Linux
2564 #elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
2565 FILE* fp = NULL;
2566 if ((fp = fopen( "/proc/self/statm", "r" )) != NULL) {
2567 if (fscanf( fp, "%*s%ld", &rss ) == 1) {
2568 rss *= (size_t)sysconf(_SC_PAGESIZE);
2569 }
2570 fclose(fp);
2571 }
2572 // AIX, BSD, Solaris, and Unknown OS
2573 #else
2574 rss = 0;
2575 #endif
2576
2577 // Return resident set size
2578 return rss;
2579}
2580
2581
2582/***********************************************************************//**
2583 * @brief Get current clock in seconds
2584 *
2585 * @return Current clock in seconds.
2586 ***************************************************************************/
2588{
2589 // Get current clock in seconds
2590 #ifdef _OPENMP
2591 double time = omp_get_wtime();
2592 #else
2593 double time = double(clock()) / (double)CLOCKS_PER_SEC;
2594 #endif
2595
2596 // Return time
2597 return time;
2598}
Energy value class definition.
Exception handler interface definition.
Filename class interface definition.
FITS file class interface definition.
Mathematical function definitions.
#define G_CHAR_BUFFER
Definition GTools.cpp:90
#define G_XML2STRING
Definition GTools.cpp:85
#define G_PARFORMAT_LENGTH
Definition GTools.cpp:89
#define G_HTTP_QUERY
Definition GTools.cpp:86
Gammalib tools definition.
XML element node class interface definition.
Abstract XML node base class interface definition.
XML text node class interface definition.
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
double MeV(void) const
Return energy in MeV.
Definition GEnergy.cpp:342
double log10MeV(void) const
Return log10 of energy in MeV.
Definition GEnergy.cpp:458
Filename class.
Definition GFilename.hpp:62
std::string path(void) const
Return access path.
std::string file(void) const
Return name of file.
std::string url(void) const
Return Uniform Resource Locator (URL)
bool is_empty(void) const
Signal if filename is empty.
XML element node class.
const GXmlAttribute * attribute(const int &index) const
Return attribute.
bool has_attribute(const std::string &name) const
Check if element has a given attribute.
Abstract XML node base class.
Definition GXmlNode.hpp:57
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition GXmlNode.cpp:287
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition GXmlNode.cpp:640
GFilename filename(void) const
Return filename of XML file.
Definition GXmlNode.cpp:546
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition GXmlNode.cpp:586
XML text node class.
Definition GXmlText.hpp:43
const std::string & text(void) const
Return text.
Definition GXmlText.hpp:97
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1162
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition GTools.cpp:1186
GFilename gamma_filename(const std::string &name)
Returns filename in .gamma directory.
Definition GTools.cpp:2503
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition GTools.hpp:186
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:1219
std::string strdate(void)
Return current date.
Definition GTools.cpp:746
std::string http_query(const std::string &host, const std::string &query)
Return response to a HTTP query.
Definition GTools.cpp:2249
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition GTools.hpp:203
GEnergy elogmean(const GEnergy &a, const GEnergy &b)
Computes log mean energy.
Definition GTools.cpp:1309
char * tochar(const std::string &arg)
Convert string to C string.
Definition GTools.cpp:786
long tolong(const std::string &arg)
Convert string into long value.
Definition GTools.cpp:870
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
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:1708
double todouble(const std::string &arg)
Convert string into double precision value.
Definition GTools.cpp:945
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:1757
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:1089
bool compare(const double &a, const double &b, const double &tol)
Compare two floating point values with tolerance.
Definition GTools.cpp:2209
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:1113
std::string replace_segment(const std::string &arg, const std::string &segment, const std::string &replacement)
Replace string segment in string.
Definition GTools.cpp:187
std::string filepath(const std::string &pathname, const std::string &filename)
Build file path from path name and file name.
Definition GTools.cpp:412
std::string tolower(const std::string &s)
Convert string to lower case.
Definition GTools.cpp:974
unsigned long long toulonglong(const std::string &arg)
Convert string into unsigned long long value.
Definition GTools.cpp:915
int toint(const std::string &arg)
Convert string into integer value.
Definition GTools.cpp:840
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:1656
std::string rstrip_chars(const std::string &arg, const std::string &chars)
Strip trailing character from string.
Definition GTools.cpp:150
std::string xml2str(const std::string &arg)
Convert XML character references in string to characters.
Definition GTools.cpp:1435
GFilename xml_file_reduce(const GXmlElement &xml, const std::string &filename)
Reduce file name provided for writing as XML attribute.
Definition GTools.cpp:1965
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition GTools.cpp:99
std::string str2xml(const std::string &arg)
Convert special characters in string to XML character references.
Definition GTools.cpp:1568
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:2126
float tofloat(const std::string &arg)
Convert string into single precision value.
Definition GTools.cpp:930
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition GTools.cpp:233
unsigned long toulong(const std::string &arg)
Convert string into unsigned long value.
Definition GTools.cpp:885
bool dir_exists(const std::string &dirname)
Checks if directory exists.
Definition GTools.cpp:1331
unsigned int touint(const std::string &arg)
Convert string into unsigned integer value.
Definition GTools.cpp:855
bool contains(const std::string &str, const std::string &substring)
Checks if a substring is in a string.
Definition GTools.cpp:1361
std::string host_country(const bool &force_query=false)
Return two-digit host country code.
Definition GTools.cpp:2345
short toshort(const std::string &arg)
Convert string into short value.
Definition GTools.cpp:810
double get_current_clock(void)
Get current clock in seconds.
Definition GTools.cpp:2587
double acos(const double &arg)
Computes acos by avoiding NaN due to rounding errors.
Definition GMath.cpp:69
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:1137
void xml_check_parnum(const std::string &origin, const GXmlElement &xml, const int &number)
Checks number of parameters.
Definition GTools.cpp:1796
std::string tmpnam(void)
Return temporary file name.
Definition GTools.cpp:440
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:2007
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition GTools.cpp:1405
const double twopi
Definition GMath.hpp:36
unsigned short toushort(const std::string &arg)
Convert string into unsigned short value.
Definition GTools.cpp:825
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:1267
std::string fill(const std::string &s, const int &n)
Fill string with n strings of same type.
Definition GTools.cpp:1063
std::string getenv(const std::string &arg)
Return value of environment variable.
Definition GTools.cpp:484
bool xml_has_par(const GXmlElement &xml, const std::string &name)
Checks if parameter with given name in XML element exists.
Definition GTools.cpp:1615
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:1874
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition GTools.cpp:1002
int recv(int fd, char *buffer, int len, int flags, int timeout)
Checks whether a parameter has occured once.
Definition GTools.cpp:2055
std::string toupper(const std::string &s)
Convert string to upper case.
Definition GTools.cpp:960
GFilename xml_file_expand(const GXmlElement &xml, const std::string &filename)
Expand file name provided as XML attribute for loading.
Definition GTools.cpp:1908
long long tolonglong(const std::string &arg)
Convert string into long long value.
Definition GTools.cpp:900
void xml_check_type(const std::string &origin, GXmlElement &xml, const std::string &type)
Checks the model type.
Definition GTools.cpp:1838
std::string strip_chars(const std::string &arg, const std::string &chars)
Strip leading and trailing character from string.
Definition GTools.cpp:113
size_t get_current_rss(void)
Get current resident set size (physical memory use) in Bytes.
Definition GTools.cpp:2540