GammaLib 2.0.0
Loading...
Searching...
No Matches
GApplicationPars.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GApplicationPars.cpp - Application parameters *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2010-2021 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 GApplicationPars.cpp
23 * @brief Application parameter container class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <pwd.h> // user/passwd function
32#include <fcntl.h> // for file locking
33#include <unistd.h> // access() function
34#include <sys/stat.h> // mkdir() function
35#include <cstdlib> // std::getenv() function
36#include <cstdio> // std::fopen(), etc. functions
37#include <sstream>
38#include "GException.hpp"
39#include "GTools.hpp"
40#include "GFilename.hpp"
41#include "GApplicationPars.hpp"
42
43/* __ Method name definitions ____________________________________________ */
44#define G_ACCESS "GApplicationPars::operator[](std::string&)"
45#define G_AT "GApplicationPar& GApplicationPars::at(int&)"
46#define G_APPEND "GApplicationPars::append(GApplicationPar&)"
47#define G_INSERT1 "GApplicationPar& GApplicationPars::insert(int&, "\
48 "GApplicationPar&)"
49#define G_INSERT2 "GApplicationPar& GApplicationPars::insert(std::string&, "\
50 "GApplicationPar&)"
51#define G_REMOVE1 "GApplicationPars::remove(int&)"
52#define G_REMOVE2 "GApplicationPars::remove(std::string&)"
53#define G_EXTEND "GApplicationPars::extend(GApplicationPars&)"
54#define G_LOAD1 "GApplicationPars::load(GFilename&)"
55#define G_LOAD2 "GApplicationPars::load(GFilename&, "\
56 "std::vector<std::string>&)"
57#define G_SAVE "GApplicationPars::save(GFilename&)"
58#define G_OUTPATH "GApplicationPars::outpath(std::string&)"
59#define G_READ "GApplicationPars::read(std::string&)"
60#define G_WRITE "GApplicationPars::write(std::string&)"
61#define G_PARSE "GApplicationPars::parse()"
62
63/* __ Macros _____________________________________________________________ */
64
65/* __ Coding definitions _________________________________________________ */
66#define G_LOCK_PARFILE //!< Enables parfile locking
67//#define G_CHECK_LOCK_PARFILE //!< Enables check of parfile locking
68
69/* __ Debug definitions __________________________________________________ */
70
71
72/*==========================================================================
73 = =
74 = Constructors/destructors =
75 = =
76 ==========================================================================*/
77
78/***********************************************************************//**
79 * @brief Void constructor
80 ***************************************************************************/
82{
83 // Initialise private members for clean destruction
85
86 // Return
87 return;
88}
89
90
91/***********************************************************************//**
92 * @brief Parameter file constructor
93 *
94 * @param[in] filename Parameter filename.
95 ***************************************************************************/
97{
98 // Initialise private members for clean destruction
100
101 // Load parameters
102 load(filename);
103
104 // Return
105 return;
106}
107
108/***********************************************************************//**
109 * @brief Parameter constructor
110 *
111 * @param[in] filename Parameter filename.
112 * @param[in] args Command line arguments.
113 ***************************************************************************/
115 const std::vector<std::string>& args)
116{
117 // Initialise private members for clean destruction
118 init_members();
119
120 // Load parameters
121 load(filename, args);
122
123 // Return
124 return;
125}
126
127
128/***********************************************************************//**
129 * @brief Copy constructor
130 *
131 * @param[in] pars Parameter container.
132 ***************************************************************************/
134{
135 // Initialise private members for clean destruction
136 init_members();
137
138 // Copy members
139 copy_members(pars);
140
141 // Return
142 return;
143}
144
145
146/***********************************************************************//**
147 * @brief Destructor
148 ***************************************************************************/
150{
151 // Free members
152 free_members();
153
154 // Return
155 return;
156}
157
158
159/*==========================================================================
160 = =
161 = Operators =
162 = =
163 ==========================================================================*/
164
165/***********************************************************************//**
166 * @brief Assignment operator
167 *
168 * @param[in] pars Parameter container.
169 * @return Parameter container.
170 ***************************************************************************/
172{
173 // Execute only if object is not identical
174 if (this != &pars) {
175
176 // Free members
177 free_members();
178
179 // Initialise private members for clean destruction
180 init_members();
181
182 // Copy members
183 copy_members(pars);
184
185 } // endif: object was not identical
186
187 // Return
188 return *this;
189}
190
191
192/***********************************************************************//**
193 * @brief Returns reference to parameter
194 *
195 * @param[in] name Parameter name.
196 * @return Parameter.
197 *
198 * @exception GException::invalid_argument
199 * Parameter with specified name not found in container.
200 ***************************************************************************/
202{
203 // Get parameter index
204 int index = get_index(name);
205
206 // Throw exception if parameter name has not been found
207 if (index == -1) {
208 std::string msg = "Parameter \""+name+"\" has not been found in "
209 "parameter file. Please specify a valid parameter "
210 "name.";
212 }
213
214 // Return reference
215 return (m_pars[index]);
216}
217
218
219/***********************************************************************//**
220 * @brief Returns reference to parameter (const version)
221 *
222 * @param[in] name Parameter name.
223 * @return Parameter.
224 *
225 * @exception GException::invalid_argument
226 * Parameter with specified name not found in container.
227 ***************************************************************************/
228const GApplicationPar& GApplicationPars::operator[](const std::string& name) const
229{
230 // Get parameter index
231 int index = get_index(name);
232
233 // Throw exception if parameter name has not been found
234 if (index == -1) {
235 std::string msg = "Parameter \""+name+"\" has not been found in "
236 "parameter file. Please specify a valid parameter "
237 "name.";
239 }
240
241 // Return reference
242 return (m_pars[index]);
243}
244
245
246/*==========================================================================
247 = =
248 = Public methods =
249 = =
250 ==========================================================================*/
251
252/***********************************************************************//**
253 * @brief Clear parameter container
254 ***************************************************************************/
256{
257 // Free members
258 free_members();
259
260 // Init members
261 init_members();
262
263 // Return
264 return;
265}
266
267
268/***********************************************************************//**
269 * @brief Clone parameter container
270 *
271 * @return Pointer to deep copy of parameter container.
272 ***************************************************************************/
274{
275 return (new GApplicationPars(*this));
276}
277
278
279/***********************************************************************//**
280 * @brief Returns reference to parameter
281 *
282 * @param[in] index Parameter index [0,...,size()-1].
283 *
284 * @exception GException::out_of_range
285 * Parameter index is out of range.
286 ***************************************************************************/
288{
289 // Compile option: raise an exception if index is out of range
290 #if defined(G_RANGE_CHECK)
291 if (index < 0 || index >= size()) {
292 throw GException::out_of_range(G_AT, "Parameter index", index, size());
293 }
294 #endif
295
296 // Return reference
297 return (m_pars[index]);
298}
299
300
301/***********************************************************************//**
302 * @brief Returns reference to parameter (const version)
303 *
304 * @param[in] index Parameter index [0,...,size()-1].
305 *
306 * @exception GException::out_of_range
307 * Parameter index is out of range.
308 ***************************************************************************/
309const GApplicationPar& GApplicationPars::at(const int& index) const
310{
311 // Compile option: raise an exception if index is out of range
312 #if defined(G_RANGE_CHECK)
313 if (index < 0 || index >= size()) {
314 throw GException::out_of_range(G_AT, "Parameter index", index, size());
315 }
316 #endif
317
318 // Return reference
319 return (m_pars[index]);
320}
321
322
323/***********************************************************************//**
324 * @brief Append parameter to container
325 *
326 * @param[in] par Parameter.
327 * @return Reference to deep copy of appended parameter.
328 *
329 * @exception GException::invalid_value
330 * Parameter with same name exists already in container.
331 *
332 * This method appends one parameter to the parameter container. The
333 * parameter provided to the method can be deleted after calling this method.
334 ***************************************************************************/
336{
337 // Check if a parameter with specified name does not yet exist
338 int inx = get_index(par.name());
339 if (inx != -1) {
340 std::string msg =
341 "Attempt to append parameter with name \""+par.name()+"\" in"
342 " parameter container, but a parameter with the same name exists"
343 " already at index "+gammalib::str(inx)+" in the container.\n"
344 "Every parameter in the parameter container needs a unique name.";
346 }
347
348 // Append parameter
349 m_pars.push_back(par);
350
351 // Get reference of appended parameter
352 GApplicationPar& parameter = m_pars[m_pars.size()-1];
353
354 // Build parameter file line
355 size_t start = 0;
356 size_t stop = 0;
357 std::string line = parline(parameter, &start, &stop);
358
359 // Append parameter file line and attributes
360 m_line.push_back(m_parfile.size());
361 m_parfile.push_back(line);
362 m_vstart.push_back(start);
363 m_vstop.push_back(stop);
364
365 // Return parameter reference
366 return parameter;
367}
368
369
370/***********************************************************************//**
371 * @brief Append standard parameters to container
372 *
373 * This method appends the standard parameters to the parameter container.
374 * Standard parameters are: "chatter", "clobber", "debug" and "mode".
375 ***************************************************************************/
377{
378 // Append standard parameters
379 append(GApplicationPar("chatter","i","h","2","0","4","Chattiness of output"));
380 append(GApplicationPar("clobber","b","h","yes","","","Overwrite existing output files with new output files?"));
381 append(GApplicationPar("debug","b","h","no","","","Debugging mode activated"));
382 append(GApplicationPar("mode","s","h","ql","","","Mode of automatic parameters"));
383
384 // Return
385 return;
386}
387
388
389/***********************************************************************//**
390 * @brief Insert parameter into container
391 *
392 * @param[in] index Parameter index [0,...,size()-1].
393 * @param[in] par Parameter.
394 * @return Reference to deep copy of inserted parameter.
395 *
396 * Inserts a parameter into the container before the parameter with the
397 * specified @p index.
398 ***************************************************************************/
400{
401 // Compile option: raise exception if index is out of range
402 #if defined(G_RANGE_CHECK)
403 if (is_empty()) {
404 if (index > 0) {
405 throw GException::out_of_range(G_INSERT1, "Parameter index", index, size());
406 }
407 }
408 else {
409 if (index < 0 || index >= size()) {
410 throw GException::out_of_range(G_INSERT1, "Parameter index", index, size());
411 }
412 }
413 #endif
414
415 // Check if a parameter with specified name does not yet exist
416 int inx = get_index(par.name());
417 if (inx != -1) {
418 std::string msg =
419 "Attempt to insert parameter with name \""+par.name()+"\" in"
420 " parameter container before index "+gammalib::str(index)+
421 ", but a parameter with the same name exists already at index "+
422 gammalib::str(inx)+" in the container.\n"
423 "Every parameter in the parameter container needs a unique name.";
425 }
426
427 // Inserts parameter
428 m_pars.insert(m_pars.begin()+index, par);
429
430 // Get reference of appended parameter
431 GApplicationPar& parameter = m_pars[m_pars.size()-1];
432
433 // Build parameter file line
434 size_t start = 0;
435 size_t stop = 0;
436 std::string line = parline(parameter, &start, &stop);
437
438 // Determine at which line number of the parameter file the parameter
439 // should be inserted
440 int line_number = m_line[index];
441
442 // Insert parameter file line and parameter attributes
443 m_parfile.insert(m_parfile.begin()+line_number, line);
444 m_line.insert(m_line.begin()+index, line_number);
445 m_vstart.insert(m_vstart.begin()+index, start);
446 m_vstop.insert(m_vstop.begin()+index, stop);
447
448 // Increment the line numbers for all parameters after the inserted one
449 for (int i = index+1; i < size(); ++i) {
450 m_line[i]++;
451 }
452
453 // Return parameter reference
454 return parameter;
455}
456
457
458/***********************************************************************//**
459 * @brief Insert parameter into container
460 *
461 * @param[in] name Parameter name.
462 * @param[in] par Parameter.
463 * @return Reference to deep copy of inserted parameter.
464 *
465 * @exception GException::invalid_argument
466 * Parameter with specified name not found in container.
467 *
468 * Inserts a parameter into the container before the parameter with the
469 * specified @p name.
470 ***************************************************************************/
472 const GApplicationPar& par)
473{
474 // Get parameter index
475 int index = get_index(name);
476
477 // Throw exception if parameter name was not found
478 if (index == -1) {
479 std::string msg = "Parameter \""+name+"\" has not been found in "
480 "parameter file. Please specify a valid parameter "
481 "name.";
483 }
484
485 // Insert by index and return parameter reference
486 return (insert(index, par));
487}
488
489
490/***********************************************************************//**
491 * @brief Remove parameter from container
492 *
493 * @param[in] index Parameter index [0,...,size()-1].
494 *
495 * @exception GException::out_of_range
496 * Parameter index is out of range.
497 *
498 * Remove parameter with specified @p index from container.
499 ***************************************************************************/
500void GApplicationPars::remove(const int& index)
501{
502 // Compile option: raise exception if index is out of range
503 #if defined(G_RANGE_CHECK)
504 if (index < 0 || index >= size()) {
505 throw GException::out_of_range(G_REMOVE1, "Parameter index", index, size());
506 }
507 #endif
508
509 // Erase parameter from container
510 m_pars.erase(m_pars.begin() + index);
511
512 // Remove parameter file line and parameter attributes
513 m_parfile.erase(m_parfile.begin() + m_line[index]);
514 m_line.erase(m_line.begin() + index);
515 m_vstart.erase(m_vstart.begin() + index);
516 m_vstop.erase(m_vstop.begin() + index);
517
518 // Decrement the line numbers for all parameters after the removed one
519 for (int i = index; i < size(); ++i) {
520 m_line[i]--;
521 }
522
523 // Return
524 return;
525}
526
527
528/***********************************************************************//**
529 * @brief Remove parameter from container
530 *
531 * @param[in] name Parameter name.
532 *
533 * @exception GException::invalid_argument
534 * Parameter with specified name not found in container.
535 *
536 * Remove parameter with specified @p name from container.
537 ***************************************************************************/
538void GApplicationPars::remove(const std::string& name)
539{
540 // Get parameter index
541 int index = get_index(name);
542
543 // Throw exception if parameter name was not found
544 if (index == -1) {
545 std::string msg = "Parameter \""+name+"\" has not been found in "
546 "parameter file. Please specify a valid parameter "
547 "name.";
549 }
550
551 // Remove by index
552 remove(index);
553
554 // Return
555 return;
556}
557
558
559/***********************************************************************//**
560 * @brief Append parameter container
561 *
562 * @param[in] pars Parameter container.
563 *
564 * @exception GException::invalid_value
565 * Parameter with the same name exists already.
566 *
567 * Append parameter container to the container.
568 ***************************************************************************/
570{
571 // Do nothing if parameter container is empty
572 if (!pars.is_empty()) {
573
574 // Get size. Note that we extract the size first to avoid an
575 // endless loop that arises when a container is appended to
576 // itself.
577 int num = pars.size();
578
579 // Reserve enough space
580 reserve(size() + num);
581
582 // Loop over all parameters and append copies
583 for (int i = 0; i < num; ++i) {
584
585 // Check if parameter name does not yet exist
586 int inx = get_index(pars[i].name());
587 if (inx != -1) {
588 std::string msg =
589 "Attempt to append parameter with name \""+pars[i].name()+
590 "\" to parameter container, but a parameter with the same "
591 "name exists already at index "+gammalib::str(inx)+" in "
592 "the container. Every parameter in the parameter container "
593 "needs to have a unique name.";
595 }
596
597 // Append parameter to container
598 append(pars[i]);
599
600 } // endfor: looped over all parameters
601
602 } // endif: parameter container was not empty
603
604 // Return
605 return;
606}
607
608
609/***********************************************************************//**
610 * @brief Check parameter exists
611 *
612 * @param[in] name Parameter name.
613 * @return True if parameter with specified name exists, false otherwise.
614 *
615 * Determines whether a parameter with the specified name exists already in
616 * the parameter container.
617 ***************************************************************************/
618bool GApplicationPars::contains(const std::string& name) const
619{
620 // Get parameter index
621 int inx = get_index(name);
622
623 // Return test result
624 return (inx != -1);
625}
626
627
628/***********************************************************************//**
629 * @brief Load parameters
630 *
631 * @param[in] filename Parameter filename.
632 *
633 * @exception GException::invalid_argument
634 * Parameter file not found.
635 *
636 * Loads all parameters from parameter file.
637 *
638 * If the syspfiles path is set then load the parameter file from that
639 * location and update the parameters using a paramater file that is found
640 * in the users "pfiles" directory.
641 *
642 * Otherwise, search the parameter file in the usual location (see the
643 * GApplicationPars::inpath method for more information).
644 ***************************************************************************/
646{
647 // Reset parameters
648 m_parfile.clear();
649
650 // If a syspfiles path was set then get parfile from this path and
651 // update the parameters using a copy found in the users "pfiles"
652 // directory
653 std::string path = syspfiles_path(filename.url());
654 if (!path.empty()) {
655
656 // Read parfile
657 read(path);
658
659 // Parse parfile
660 parse();
661
662 // Synchronize parfile using a copy found in the users "pfiles"
663 // directory
664 path = pfiles_path(filename.url());
665 if (!path.empty()) {
666 synchronise(path);
667 }
668
669 }
670
671 // ... otherwise get path to parameter file for input
672 else {
673
674 // Get parfile file path
675 path = inpath(filename.url());
676
677 // If file path is empty then throw an exception
678 if (path.empty()) {
679 std::string msg = "Parameter file \""+filename.url()+"\" not "
680 "found. Please specify an existing parameter "
681 "file.";
683 }
684
685 // Read parfile
686 read(path);
687
688 // Parse parfile
689 parse();
690
691 }
692
693 // Return
694 return;
695}
696
697
698/***********************************************************************//**
699 * @brief Load parameters
700 *
701 * @param[in] filename Parameter filename.
702 * @param[in] args Command line arguments.
703 *
704 * @exception GException::invalid_argument
705 * Invalid command line argument encountered.
706 *
707 * Loads all parameters from parameter file. Parameters are overwritten by
708 * the values specified in the command line arguments.
709 ***************************************************************************/
711 const std::vector<std::string>& args)
712{
713 // Load parameters
714 load(filename);
715
716 // Overwrite parameter values that are specified in the command line
717 for (int i = 1; i < args.size(); ++i) {
718
719 // Extract parameter name and value (empty values are permitted)
720 size_t pos = args[i].find("=");
721 if (pos == std::string::npos) {
722 std::string msg = "No \"=\" symbol found for command line "
723 "parameter \""+args[i]+"\". Please specify a "
724 "valid command line parameter of the form "
725 "\"name=value\".";
727 }
728 std::string name = args[i].substr(0, pos);
729 std::string value = args[i].substr(pos+1);
730 if (name.length() < 1) {
731 std::string msg = "No parameter name found for before the \"=\" "
732 "symbol for command line parameter \""+args[i]+
733 "\". Please specify a valid command line "
734 "parameter of the form \"name=value\".";
736 }
737
738 // Check if parameter exists
739 if (!contains(name)) {
740 std::string msg = "No parameter with name \""+name+"\" found. "
741 "Please specify an existing command line "
742 "parameter.";
744 }
745
746 // Assign value
747 try {
748 (*this)[name].value(value);
749 }
750 catch (GException::invalid_value &e) {
751 std::string msg = "Assignment of command line parameter \""+
752 args[i]+"\" failed.";
754 }
755
756 // Set mode to hidden to prevent querying the parameter
757 if ((*this)[name].mode() == "q") {
758 (*this)[name].mode("h");
759 }
760 else if ((*this)[name].mode() == "ql") {
761 (*this)[name].mode("hl");
762 }
763 else if ((*this)[name].mode() == "lq") {
764 (*this)[name].mode("lh");
765 }
766
767 } // endfor: looped over all parameters
768
769 // Return
770 return;
771}
772
773
774/***********************************************************************//**
775 * @brief Save parameters
776 *
777 * @param[in] filename Parameter filename.
778 *
779 * @exception GException::file_error
780 * No valid directory to write the parameter file has been found.
781 ***************************************************************************/
783{
784 // Get path to parameter file for output
785 std::string path = outpath(filename.url());
786 if (path.size() == 0) {
787 std::string msg = "Parameter file \""+filename+"\" not found. Please "
788 "make sure that the PFILES environment variable is "
789 "set correctly.";
791 }
792
793 // Update parameter file
794 update();
795
796 // Write parfile
797 write(path);
798
799 // Return
800 return;
801}
802
803
804/***********************************************************************//**
805 * @brief Set class from pickled string vector
806 *
807 * @param[in] string String vector containing class information.
808 ***************************************************************************/
809void GApplicationPars::pickle(const std::vector<std::string>& string)
810{
811 // Clear object
812 clear();
813
814 // Extract vector sizes
815 int n_parfile = gammalib::toint(string[0]);
816 int n_pars = gammalib::toint(string[1]);
817 int n_line = gammalib::toint(string[2]);
818 int n_vstart = gammalib::toint(string[3]);
819 int n_vstop = gammalib::toint(string[4]);
820
821 // Initialise string pointer
822 int istring = 5;
823
824 // Extract parameter file lines
825 for (int i = 0; i < n_parfile; ++i, ++istring) {
826 m_parfile.push_back(string[istring]);
827 }
828
829 // Extract application parameters
830 for (int i = 0; i < n_pars; ++i) {
831 int n_par = gammalib::toint(string[istring]);
832 int i_start = istring + 1;
833 int i_end = i_start + n_par;
834 GApplicationPar par;
835 par.pickle(std::vector<std::string>(string.begin()+i_start,
836 string.begin()+i_end));
837 m_pars.push_back(par);
838 istring = i_end;
839 }
840
841 // Extract line numbers
842 for (int i = 0; i < n_line; ++i, ++istring) {
843 m_line.push_back(gammalib::toint(string[istring]));
844 }
845
846 // Extract columns of start values
847 for (int i = 0; i < n_vstart; ++i, ++istring) {
848 m_vstart.push_back((size_t)gammalib::toint(string[istring]));
849 }
850
851 // Extract columns of stop values
852 for (int i = 0; i < n_vstop; ++i, ++istring) {
853 m_vstop.push_back((size_t)gammalib::toint(string[istring]));
854 }
855
856 // Extract effective mode and location of syspfiles
857 m_mode = string[istring++];
858 m_syspfiles = string[istring++];
859
860 // Return
861 return;
862}
863
864
865/***********************************************************************//**
866 * @brief Return pickled string vector
867 *
868 * @return String vector containing class information.
869 ***************************************************************************/
870std::vector<std::string> GApplicationPars::pickle(void) const
871{
872 // Allocate vector of strings
873 std::vector<std::string> string;
874
875 // Store vector lengths
876 string.push_back(gammalib::str(m_parfile.size()));
877 string.push_back(gammalib::str(m_pars.size()));
878 string.push_back(gammalib::str(m_line.size()));
879 string.push_back(gammalib::str(m_vstart.size()));
880 string.push_back(gammalib::str(m_vstop.size()));
881
882 // Store parfile lines
883 for (int i = 0; i < m_parfile.size(); ++i) {
884 string.push_back(m_parfile[i]);
885 }
886
887 // Store application parameters
888 for (int i = 0; i < m_pars.size(); ++i) {
889 std::vector<std::string> par = m_pars[i].pickle();
890 string.push_back(gammalib::str(par.size()));
891 for (int k = 0; k < par.size(); ++k) {
892 string.push_back(par[k]);
893 }
894 }
895
896 // Store line numbers
897 for (int i = 0; i < m_line.size(); ++i) {
898 string.push_back(gammalib::str(m_line[i]));
899 }
900
901 // Store columns of start values
902 for (int i = 0; i < m_vstart.size(); ++i) {
903 string.push_back(gammalib::str(m_vstart[i]));
904 }
905
906 // Store columns of stop values
907 for (int i = 0; i < m_vstop.size(); ++i) {
908 string.push_back(gammalib::str(m_vstop[i]));
909 }
910
911 // Store effective mode and location of syspfiles
912 string.push_back(m_mode);
913 string.push_back(m_syspfiles);
914
915 // Return string vector
916 return string;
917}
918
919
920/***********************************************************************//**
921 * @brief Print parameters
922 *
923 * @param[in] chatter Chattiness.
924 * @return String containing parameter information.
925 ***************************************************************************/
926std::string GApplicationPars::print(const GChatter& chatter) const
927{
928 // Initialise result string
929 std::string result;
930
931 // Continue only if chatter is not silent
932 if (chatter != SILENT) {
933
934 // Append header
935 result.append("=== GApplicationPars ===");
936
937 // Append parameters
938 for (int i = 0; i < size(); ++i) {
939 result.append("\n"+m_pars[i].print(chatter));
940 }
941
942 } // endif: chatter was not silent
943
944 // Return result
945 return result;
946}
947
948
949/*==========================================================================
950 = =
951 = Private methods =
952 = =
953 ==========================================================================*/
954
955/***********************************************************************//**
956 * @brief Initialise class members
957 ***************************************************************************/
959{
960 // Initialise members
961 m_parfile.clear();
962 m_pars.clear();
963 m_line.clear();
964 m_vstart.clear();
965 m_vstop.clear();
966 m_mode = "h";
967 m_syspfiles.clear();
968
969 // Return
970 return;
971}
972
973
974/***********************************************************************//**
975 * @brief Copy class members
976 *
977 * @param[in] pars Object from which members which should be copied.
978 ***************************************************************************/
980{
981 // Copy attributes
982 m_parfile = pars.m_parfile;
983 m_pars = pars.m_pars;
984 m_line = pars.m_line;
985 m_vstart = pars.m_vstart;
986 m_vstop = pars.m_vstop;
987 m_mode = pars.m_mode;
989
990 // Return
991 return;
992}
993
994
995/***********************************************************************//**
996 * @brief Delete class members
997 ***************************************************************************/
999{
1000 // Return
1001 return;
1002}
1003
1004
1005/***********************************************************************//**
1006 * @brief Determine filepath for parameter file input
1007 *
1008 * @param[in] filename Parameter filename to search for.
1009 *
1010 * Locates parameter file for input.
1011 * The parameter file is first searched in the directories that are listed
1012 * in the PFILES environment variable. Directories may be separated by : or
1013 * by ; in PFILES.
1014 *
1015 * If the PFILES environment variable is not set the parameter file is
1016 * searched in the users pfiles directory.
1017 *
1018 * If still no parameter file is found, the parameter file is searched (in
1019 * the given order) in ${GAMMALIB}/syspfiles and in ${prefix}/syspfiles,
1020 * where ${prefix} is the path to the GammaLib installation.
1021 ***************************************************************************/
1022std::string GApplicationPars::inpath(const std::string& filename) const
1023{
1024 // Allocate result path
1025 std::string path;
1026
1027 // Search for parameter file in PFILES directories if the PFILES
1028 // environment variable has been set
1029 char* ptr = std::getenv("PFILES");
1030 if (ptr != NULL) {
1031
1032 // Extract directories from PFILES environment variable
1033 std::string pfiles = ptr;
1034 std::vector<std::string> dirs = gammalib::split(pfiles, ":;");
1035
1036 // Search for first occurence of parameter file
1037 for (int i = 0; i < dirs.size(); ++i) {
1038
1039 // Build filename
1040 std::string fname = dirs[i] + "/" + filename;
1041
1042 // If file is accessible for reading then exit loop
1043 if (access(fname.c_str(), R_OK) == 0) {
1044 path = fname;
1045 break;
1046 }
1047
1048 } // endfor: searched all directories given in PFILES
1049
1050 } // endif: PFILES environment variable has been set
1051
1052 // ... otherwise, if no PFILES environment variable has been set
1053 // then search in users pfiles directory
1054 else {
1055 uid_t uid = geteuid();
1056 struct passwd* pw = getpwuid(uid);
1057 if (pw != NULL) {
1058 std::string fname = std::string(pw->pw_dir) + "/pfiles/" + filename;
1059 if (access(fname.c_str(), R_OK) == 0) {
1060 path = fname;
1061 }
1062 }
1063 } // endif: searched in users pfiles directory
1064
1065 // If we have no valid path so far then search file within GAMMALIB
1066 // repository (${GAMMALIB}/syspfiles)
1067 if (path.size() == 0) {
1068 ptr = std::getenv("GAMMALIB");
1069 if (ptr != NULL) {
1070 std::string fname = std::string(ptr) + "/syspfiles/" + filename;
1071 if (access(fname.c_str(), R_OK) == 0) {
1072 path = fname;
1073 }
1074 }
1075 }
1076
1077 // If we have no valid path so far then search file within GammaLib
1078 // package (${prefix}/syspfiles)
1079 #ifdef PACKAGE_PREFIX
1080 if (path.size() == 0) {
1081 std::string fname = std::string(PACKAGE_PREFIX) + "/syspfiles/" +
1082 filename;
1083 if (access(fname.c_str(), R_OK) == 0) {
1084 path = fname;
1085 }
1086 }
1087 #endif
1088
1089 // Return path
1090 return path;
1091}
1092
1093
1094/***********************************************************************//**
1095 * @brief Return path to parfile in $PFILES or $HOME/pfiles folder
1096 *
1097 * @param[in] filename Parameter filename to search for.
1098 * @return Full parameter filename, including absolute access path.
1099 *
1100 * Locates parameter file in the directories that are listed in the PFILES
1101 * environment variable. Directories may be separated by : or by ; in the
1102 * PFILES environment variable.
1103 *
1104 * If the PFILES environment variable is not set the parameter file is
1105 * searched in the users pfiles directory.
1106 *
1107 * If parameter file was not found, or the parameter file is not
1108 * read-accessible, an empty string is returned.
1109 ***************************************************************************/
1110std::string GApplicationPars::pfiles_path(const std::string& filename) const
1111{
1112 // Allocate result path
1113 std::string path;
1114
1115 // Search for parameter file in PFILES directories if the PFILES
1116 // environment variable has been set
1117 char* ptr = std::getenv("PFILES");
1118 if (ptr != NULL) {
1119
1120 // Extract directories from PFILES environment variable
1121 std::string pfiles = ptr;
1122 std::vector<std::string> dirs = gammalib::split(pfiles, ":;");
1123
1124 // Search for first occurence of parameter file
1125 for (int i = 0; i < dirs.size(); ++i) {
1126
1127 // Build filename
1128 std::string fname = dirs[i] + "/" + filename;
1129
1130 // If file is accessible for reading then exit loop
1131 if (access(fname.c_str(), R_OK) == 0) {
1132 path = fname;
1133 break;
1134 }
1135
1136 } // endfor: searched all directories given in PFILES
1137
1138 } // endif: PFILES environment variable has been set
1139
1140 // ... otherwise, if no PFILES environment variable has been set
1141 // then search in users pfiles directory
1142 else {
1143 uid_t uid = geteuid();
1144 struct passwd* pw = getpwuid(uid);
1145 if (pw != NULL) {
1146 std::string fname = std::string(pw->pw_dir) + "/pfiles/" + filename;
1147 if (access(fname.c_str(), R_OK) == 0) {
1148 path = fname;
1149 }
1150 }
1151 } // endif: searched in users pfiles directory
1152
1153 // Return path
1154 return path;
1155}
1156
1157
1158/***********************************************************************//**
1159 * @brief Return path to parfile in m_syspfiles folder
1160 *
1161 * @param[in] filename Parameter filename to search for.
1162 * @return Full parameter filename, including absolute access path.
1163 *
1164 * Locates parameter file in the directory that is specified by the
1165 * m_syspfiles string. If the string is empty, the specified file is not
1166 * found or read accessible, an empty string is returned.
1167 ***************************************************************************/
1168std::string GApplicationPars::syspfiles_path(const std::string& filename) const
1169{
1170 // Allocate result path
1171 std::string path;
1172
1173 // Continue only if m_syspfiles is not empty
1174 if (!m_syspfiles.empty()) {
1175 std::string fname = m_syspfiles + "/" + filename;
1176 if (access(fname.c_str(), R_OK) == 0) {
1177 path = fname;
1178 }
1179 }
1180
1181 // Return path
1182 return path;
1183}
1184
1185
1186/***********************************************************************//**
1187 * @brief Determine filepath for parameter file output
1188 *
1189 * @param[in] filename Parameter filename.
1190 *
1191 * @exception GException::runtime_error
1192 * Unable to determine users home directory.
1193 * Unable to create pfiles directory.
1194 * Unable to make pfiles directory accessible to user.
1195 *
1196 * Searchs for first writable directory listed in PFILES environment
1197 * variable. If PFILES is not set then use pfiles directory in users
1198 * home directory. If pfiles directory does not exist then create it.
1199 * If directory exists but is not writable then make it writable.
1200 ***************************************************************************/
1201std::string GApplicationPars::outpath(const std::string& filename) const
1202{
1203 // Allocate result path
1204 std::string path;
1205
1206 // Search for writeable PFILES directories
1207 char* ptr = std::getenv("PFILES");
1208 if (ptr != NULL) {
1209
1210 // Extract directories from PFILES environment variable
1211 std::string pfiles = ptr;
1212 std::vector<std::string> dirs = gammalib::split(pfiles, ":;");
1213
1214 // Search for first writeable
1215 for (int i = 0; i < dirs.size(); ++i) {
1216
1217 // If directory is accessible for writing then exit loop
1218 if (access(dirs[i].c_str(), W_OK) == 0) {
1219 path = dirs[i] + "/" + filename;
1220 break;
1221 }
1222
1223 }
1224 } // endif: PFILES environment variable exists
1225
1226 // If no valid directory is found in PFILES environment variable then
1227 // use pfiles directory in users home directory.
1228 if (path.size() == 0) {
1229
1230 // Get users home directory
1231 uid_t uid = geteuid();
1232 gid_t gid = getegid();
1233 struct passwd* pw = getpwuid(uid);
1234 if (pw == NULL) {
1235 std::string msg = "Unable to determine users home directory.";
1237 }
1238
1239 // Set path
1240 path = std::string(pw->pw_dir) + "/pfiles";
1241
1242 // If directory does not exist then create it
1243 if (access(path.c_str(), F_OK) != 0) {
1244 if (mkdir(path.c_str(),
1245 S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
1246 std::string msg = "Unable to create \""+path+"\".";
1248 }
1249 }
1250
1251 // If directory exists but is not writable then make it writable
1252 else if (access(path.c_str(), W_OK) != 0) {
1253 if (chown(path.c_str(), uid, gid) != 0 ||
1254 chmod(path.c_str(),
1255 S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
1256 std::string msg = "Could not make \""+path+"\" write "
1257 "accessible for writing of the applications "
1258 "parameter file.";
1260 }
1261 }
1262
1263 // Append filename
1264 path = path + "/" + filename;
1265
1266 } // endif: no valid directory found in PFILES
1267
1268 // Return path
1269 return path;
1270}
1271
1272
1273/***********************************************************************//**
1274 * @brief Read parameter file
1275 *
1276 * @param[in] filename Parameter filename (absolut path).
1277 *
1278 * @exception GException::file_error
1279 * Unable to open parameter file (read access requested).
1280 *
1281 * Read all lines of the parameter file. Each line is terminated by a newline
1282 * character. The file will be locked to avoid simultaneous access by another
1283 * process.
1284 ***************************************************************************/
1285void GApplicationPars::read(const std::string& filename)
1286{
1287 // Put in OpenMP critical zone. Note that it is important that the zone
1288 // has an identical name to the corresponding zone in the write()
1289 // method so that multiple threads cannot at the same time read and write
1290 // the parameter file (see #3287).
1291 #pragma omp critical(GApplicationsPars_io)
1292 {
1293 // Allocate line buffer
1294 const int n = 1000;
1295 char line[n];
1296
1297 // Trying to get file lock
1298 #if defined(G_LOCK_PARFILE)
1299 struct flock lock;
1300 lock.l_type = F_RDLCK; // Want a read lock
1301 lock.l_whence = SEEK_SET; // Want beginning of file
1302 lock.l_start = 0; // No offset, lock entire file ...
1303 lock.l_len = 0; // ... to the end
1304 lock.l_pid = getpid(); // Current process ID
1305 int fd;
1306 if ((fd = open(filename.c_str(), O_RDONLY)) == -1) {
1307 std::string msg = "Could not open parameter file \""+filename+
1308 "\" for locking.";
1309 throw GException::file_error(G_READ, msg);
1310 }
1311 #if defined(G_CHECK_LOCK_PARFILE)
1312 if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked
1313 std::string msg = "Could not get a lock on the parameter file \""+
1314 filename+"\".";
1315 throw GException::file_error(G_READ, msg);
1316 }
1317 #else
1318 fcntl(fd, F_SETLKW, &lock);
1319 #endif
1320 #endif
1321
1322 // Open parameter file
1323 FILE* fptr = fopen(filename.c_str(), "r");
1324 if (fptr == NULL) {
1325 std::string msg = "Could not open the parameter file \""+
1326 filename+"\" for reading.";
1327 throw GException::file_error(G_READ, msg);
1328 }
1329
1330 // Read lines
1331 while (fgets(line, n, fptr) != NULL) {
1332 m_parfile.push_back(std::string(line));
1333 }
1334
1335 // Close file
1336 fclose(fptr);
1337
1338 // Unlock file
1339 #if defined(G_LOCK_PARFILE)
1340 if (fd != -1) {
1341 lock.l_type = F_UNLCK;
1342 #if defined(G_CHECK_LOCK_PARFILE)
1343 if (fcntl(fd, F_SETLK, &lock) == -1) {
1344 std::string msg = "Could not unlock the parameter file \""+
1345 filename+"\".";
1346 throw GException::file_error(G_READ, msg);
1347 }
1348 #else
1349 fcntl(fd, F_SETLK, &lock);
1350 #endif
1351 close(fd);
1352 }
1353 #endif
1354 }
1355
1356 // Return
1357 return;
1358}
1359
1360
1361/***********************************************************************//**
1362 * @brief Write parameter file
1363 *
1364 * @param[in] filename Parameter filename (absolut path).
1365 *
1366 * @exception GException::file_error
1367 * Unable to open parameter file (write access requested).
1368 *
1369 * Writes all lines of the parameter file. The file will be locked to avoid
1370 * simultaneous access by another process.
1371 ***************************************************************************/
1372void GApplicationPars::write(const std::string& filename) const
1373{
1374 // Put in OpenMP critical zone Note that it is important that the zone
1375 // has an identical name to the corresponding zone in the read()
1376 // method so that multiple threads cannot at the same time read and write
1377 // the parameter file (see #3287).
1378 #pragma omp critical(GApplicationsPars_io)
1379 {
1380 // Trying to get file lock. We have to do this after opening the file
1381 // using the fopen function, as the file may not exist, hence it needs
1382 // to be created first.
1383 #if defined(G_LOCK_PARFILE)
1384 struct flock lock;
1385 lock.l_type = F_WRLCK; // Want a write lock
1386 lock.l_whence = SEEK_SET; // Want beginning of file
1387 lock.l_start = 0; // No offset, lock entire file ...
1388 lock.l_len = 0; // ... to the end
1389 lock.l_pid = getpid(); // Current process ID
1390 int fd;
1391 if ((fd = open(filename.c_str(), O_WRONLY)) != -1) {
1392 #if defined(G_CHECK_LOCK_PARFILE)
1393 if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked
1394 std::string msg = "Could not get a lock on the parameter file \""+
1395 filename+"\".";
1396 throw GException::file_error(G_WRITE, msg);
1397 }
1398 #else
1399 fcntl(fd, F_SETLKW, &lock);
1400 #endif
1401 }
1402 #endif
1403
1404 // Open parameter file.
1405 FILE* fptr = fopen(filename.c_str(), "w");
1406 if (fptr == NULL) {
1407 std::string msg = "Could not open the parameter file \""+
1408 filename+"\" for writing.";
1409 throw GException::file_error(G_WRITE, msg);
1410 }
1411
1412 // If file is not locked then lock it now.
1413 #if defined(G_LOCK_PARFILE)
1414 if (fd == -1) {
1415 if ((fd = open(filename.c_str(), O_WRONLY)) != -1) {
1416 #if defined(G_CHECK_LOCK_PARFILE)
1417 if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked
1418 fclose(fptr);
1419 std::string msg = "Could not get a lock on the parameter "
1420 "file \""+filename+"\".";
1421 throw GException::file_error(G_WRITE, msg);
1422 }
1423 #else
1424 fcntl(fd, F_SETLKW, &lock);
1425 #endif
1426 }
1427 }
1428 #endif
1429
1430 // Write lines
1431 for (int i = 0; i < m_parfile.size(); ++i) {
1432 fprintf(fptr, "%s", m_parfile[i].c_str());
1433 }
1434
1435 // Close file
1436 fclose(fptr);
1437
1438 // Unlock file
1439 #if defined(G_LOCK_PARFILE)
1440 if (fd != -1) {
1441 lock.l_type = F_UNLCK;
1442 #if defined(G_CHECK_LOCK_PARFILE)
1443 if (fcntl(fd, F_SETLK, &lock) == -1) {
1444 std::string msg = "Could not unlock the parameter file \""+
1445 filename+"\".";
1446 throw GException::file_error(G_WRITE, msg);
1447 }
1448 #else
1449 fcntl(fd, F_SETLK, &lock);
1450 #endif
1451 close(fd);
1452 }
1453 #endif
1454 }
1455
1456 // Return
1457 return;
1458}
1459
1460
1461/***********************************************************************//**
1462 * @brief Parse parameter file
1463 *
1464 * @exception GException::invalid_value
1465 * Syntax error encountered in parameter file.
1466 *
1467 * The parameter type has to be one b,i,r,s,f,fr,fw,fe,fn. The fr,fw,fe,fn
1468 * types test for read access, write access, file existence, and file
1469 * absence, respectively.
1470 * The parameter mode has to be one of a,h,l,q,hl,ql,lh,lq. For mode 'a' the
1471 * effective mode equals to the value given by the mode parameter, if it
1472 * exists. Without the presence of the mode parameter the effective mode
1473 * will be 'h'.
1474 ***************************************************************************/
1476{
1477 // Preset effective mode to 'hidden'
1478 m_mode = "h";
1479
1480 // Parse all lines
1481 for (int i = 0; i < m_parfile.size(); ++i) {
1482
1483 // Get line without any leading and trailing whitespace
1484 std::string line = gammalib::strip_whitespace(m_parfile[i]);
1485
1486 // If line contains a single linefeed then skip the line
1487 if (line.length() == 1 && line[0] == '\n')
1488 continue;
1489
1490 // If line is empty or if line starts with # then skip the line
1491 if (line.length() == 0 || line[0] == '#') {
1492 continue;
1493 }
1494
1495 // Get the 7 text fields of valid a parameter line
1496 std::string fields[7];
1497 int quotes = 0;
1498 size_t start = 0;
1499 size_t end = line.length() - 1;
1500 int index = 0;
1501 size_t vstart = 0;
1502 size_t vstop = 0;
1503 for (size_t pos = 0; pos < line.length(); ++pos) {
1504
1505 // Toggle quotes
1506 if (line[pos] == '"') {
1507 quotes = 1-quotes;
1508 }
1509
1510 // Search for comma only if we are outside quotes. If comma is
1511 // found or end of line is reached then extract a field and start
1512 // searching again from the position following the comma. Strip
1513 // leading and trailing quotes from the fields.
1514 if (quotes == 0) {
1515 if (line[pos] == ',' || pos == end) {
1516 if (index < 7) {
1517 fields[index] =
1519 pos-start)), "\"");
1520 if (index == 3) {
1521 vstart = start;
1522 vstop = pos;
1523 }
1524 start = pos + 1;
1525 }
1526 index++;
1527 }
1528 }
1529
1530 } // endfor: looped over line
1531
1532 // Throw an error if quotes are not balanced
1533 if (quotes != 0) {
1534 std::string msg = "Quotes are not balanced in the following line "
1535 "of the parameter file: "+
1536 gammalib::strip_chars(line,"\n")+". Please "
1537 "correct the parameter file.";
1539 }
1540
1541 // Throw an error if line has not 7 fields
1542 if (index != 7) {
1543 std::string msg = "Number of fields ("+gammalib::str(index)+") "
1544 "does not correspond to the expected number of "
1545 "7 fields in the following line of the parameter "
1546 "file: "+gammalib::strip_chars(line,"\n")+". "
1547 "Please correct the parameter file.";
1549 }
1550
1551 // Verify if parameter name does not yet exist
1552 if (contains(fields[0])) {
1553 std::string msg = "Redefinition of parameter name \""+fields[0]+
1554 "\" in the following line of the parameter "
1555 "file: "+gammalib::strip_chars(line,"\n")+". "
1556 "Please correct the parameter file.";
1558 }
1559
1560 // Add parameter
1561 try {
1562 m_pars.push_back(GApplicationPar(fields[0], fields[1], fields[2],
1563 fields[3], fields[4], fields[5],
1564 fields[6]));
1565 m_line.push_back(i);
1566 m_vstart.push_back(vstart);
1567 m_vstop.push_back(vstop);
1568 }
1569 catch (GException::invalid_value &e) {
1570 std::string msg = "Error \""+std::string(e.what())+"\" encountered "
1571 "in the following line of the parameter file: "+
1572 gammalib::strip_chars(line,"\n")+". "
1573 "Please correct the parameter file.";
1575 }
1576
1577 // If parameter name is mode then store the effective mode
1578 if (fields[0] == "mode") {
1579 if (fields[3] != "h" && fields[3] != "q" &&
1580 fields[3] != "hl" && fields[3] != "ql" &&
1581 fields[3] != "lh" && fields[3] != "lq") {
1582 std::string msg = "Mode parameter has invalid value \""+
1583 fields[3]+"\" in the following line of the "
1584 "parameter file: "+
1585 gammalib::strip_chars(line,"\n")+". "
1586 "Please correct the parameter file.";
1588 }
1589 m_mode = fields[3];
1590 }
1591
1592 } // endfor: looped over lines
1593
1594 // Set effective mode for all parameters that have mode 'auto'
1595 for (int i = 0; i < m_pars.size(); ++i) {
1596 if (m_pars[i].mode() == "a") {
1597 m_pars[i].mode(m_mode);
1598 }
1599 }
1600
1601 // Return
1602 return;
1603}
1604
1605
1606/***********************************************************************//**
1607 * @brief Update parameter file
1608 *
1609 * Update lines of parameter file according to the parameter values. This
1610 * method handles correctly formatted parameter files by replacing the value
1611 * at its original location within the line (preserving additional
1612 * whitespace).
1613 * Updating is only done of the parameter mode is 'learn'.
1614 ***************************************************************************/
1616{
1617 // Loop over all parameters
1618 for (int i = 0; i < m_pars.size(); ++i) {
1619
1620 // Update only if requested and allowed
1621 if (m_pars[i].m_update && m_pars[i].is_learn()) {
1622 m_parfile[m_line[i]] = m_parfile[m_line[i]].substr(0, m_vstart[i]) +
1623 m_pars[i].m_value +
1624 m_parfile[m_line[i]].substr(m_vstop[i]);
1625 m_vstop[i] = m_vstart[i] + m_pars[i].m_value.length();
1626 }
1627
1628 } // endfor: looped over all parameters
1629
1630 // Return
1631 return;
1632}
1633
1634
1635/***********************************************************************//**
1636 * @brief Synchronise parameter file with the parameter values in a another
1637 * parameter file
1638 *
1639 * @param[in] filename File name of other parameter file.
1640 *
1641 * Copies over all values from another parameter file that correspond to
1642 * parameters with the same name and type, and that are signaled as "learn"
1643 * in the other parameter file.
1644 ***************************************************************************/
1645void GApplicationPars::synchronise(const std::string& filename)
1646{
1647 // Allocate other application parameters
1648 GApplicationPars pars;
1649
1650 // Read other application parameters
1651 pars.read(filename);
1652
1653 // Parse other parameters
1654 pars.parse();
1655
1656 // Loop over all parameters in parameter file
1657 for (int i = 0; i < m_pars.size(); ++i) {
1658
1659 // If a parameter with the same name and type exists in the other
1660 // parameter file
1661 int inx = pars.get_index(m_pars[i].name());
1662 if (inx != -1) {
1663
1664 // If the parameter types match, the mode in the other parameter
1665 // file is "learn", and the parameter values differ, then copy
1666 // over the value and signal value updating
1667 if ((m_pars[i].type() == pars[inx].type()) &&
1668 pars[inx].is_learn() &&
1669 m_pars[i].m_value != pars[inx].m_value) {
1670 m_pars[i].m_value = pars[inx].m_value;
1671 m_pars[i].m_status = pars[inx].m_status;
1672 m_pars[i].m_update = true;
1673 }
1674
1675 } // endif: parameter with same name existed
1676
1677 } // endfor: looped over all parameters
1678
1679 // Return
1680 return;
1681}
1682
1683
1684/***********************************************************************//**
1685 * @brief Return parameter index by name
1686 *
1687 * @param[in] name Parameter name.
1688 * @return Parameter index (-1 if parameter name has not been found)
1689 *
1690 * Returns parameter index based on the specified @p name. If no parameter
1691 * with the specified @p name is found the method returns -1.
1692 ***************************************************************************/
1693int GApplicationPars::get_index(const std::string& name) const
1694{
1695 // Initialise index
1696 int index = -1;
1697
1698 // Search parameter with specified name
1699 for (int i = 0; i < size(); ++i) {
1700 if (m_pars[i].name() == name) {
1701 index = i;
1702 break;
1703 }
1704 }
1705
1706 // Return index
1707 return index;
1708}
1709
1710
1711/***********************************************************************//**
1712 * @brief Return parameter file line for a specific parameter
1713 *
1714 * @param[in] par Parameter.
1715 * @param[out] start Column of value start.
1716 * @param[out] stop Column of value stop.
1717 * @return Parameter file line (termined by \n).
1718 *
1719 * Constructs the parameter file line for a specific parameter and returns
1720 * the line as a string. The line is terminated by a \n character.
1721 ***************************************************************************/
1723 size_t* start,
1724 size_t* stop) const
1725{
1726 // Declate line
1727 std::string line;
1728
1729 // Build parameter file line
1730 line.append(par.name()+", ");
1731 line.append(par.type()+ ", ");
1732 line.append(par.mode()+ ",");
1733 *start = line.length();
1734 line.append(par.value()+ ",");
1735 *stop = line.length();
1736 line.append(par.min()+ ",");
1737 line.append(par.max()+ ",");
1738 line.append("\""+par.prompt()+"\"\n");
1739
1740 // Return line
1741 return line;
1742}
#define G_WRITE
#define G_AT
#define G_LOAD1
#define G_REMOVE1
#define G_OUTPATH
#define G_READ
#define G_LOAD2
#define G_INSERT2
#define G_PARSE
#define G_APPEND
#define G_INSERT1
#define G_REMOVE2
#define G_EXTEND
#define G_ACCESS
Application parameter container class definition.
Exception handler interface definition.
Filename class interface definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
Application parameter class.
void type(const std::string &type)
Set parameter type.
void mode(const std::string &mode)
Set parameter mode.
const std::string & max(void) const
Returns parameter maximum.
void value(const std::string &value)
Set parameter value.
void pickle(const std::vector< std::string > &string)
Set class from pickled string vector.
const std::string & name(void) const
Returns parameter name.
const std::string & prompt(void) const
Returns parameter prompt.
const std::string & min(void) const
Returns parameter minimum.
Application parameter container class.
void reserve(const int &num)
Reserves space for parameters in container.
virtual ~GApplicationPars(void)
Destructor.
std::vector< GApplicationPar > m_pars
Parameters.
void append_standard(void)
Append standard parameters to container.
GApplicationPar & at(const int &index)
Returns reference to parameter.
GApplicationPar & append(const GApplicationPar &par)
Append parameter to container.
void copy_members(const GApplicationPars &pars)
Copy class members.
std::vector< size_t > m_vstop
Column of value stop.
std::vector< std::string > m_parfile
Parameter file lines.
void free_members(void)
Delete class members.
GApplicationPar & operator[](const int &index)
Returns reference to parameter.
GApplicationPars(void)
Void constructor.
bool is_empty(void) const
Signals if there are no parameters in container.
void load(const GFilename &filename)
Load parameters.
void save(const GFilename &filename)
Save parameters.
void clear(void)
Clear parameter container.
int get_index(const std::string &name) const
Return parameter index by name.
std::string parline(GApplicationPar &par, size_t *start, size_t *stop) const
Return parameter file line for a specific parameter.
bool contains(const std::string &name) const
Check parameter exists.
void remove(const int &index)
Remove parameter from container.
void extend(const GApplicationPars &pars)
Append parameter container.
GApplicationPar & insert(const int &index, const GApplicationPar &par)
Insert parameter into container.
void init_members(void)
Initialise class members.
std::string pfiles_path(const std::string &filename) const
Return path to parfile in $PFILES or $HOME/pfiles folder.
std::string syspfiles_path(const std::string &filename) const
Return path to parfile in m_syspfiles folder.
void update(void)
Update parameter file.
std::string print(const GChatter &chatter=NORMAL) const
Print parameters.
GApplicationPars & operator=(const GApplicationPars &pars)
Assignment operator.
std::vector< std::string > pickle(void) const
Return pickled string vector.
std::string m_mode
Effective mode.
std::vector< int > m_line
Line number of parameter.
void synchronise(const std::string &filename)
Synchronise parameter file with the parameter values in a another parameter file.
void parse(void)
Parse parameter file.
void read(const std::string &filename)
Read parameter file.
void write(const std::string &filename) const
Write parameter file.
std::string inpath(const std::string &filename) const
Determine filepath for parameter file input.
std::vector< size_t > m_vstart
Column of value start.
std::string outpath(const std::string &filename) const
Determine filepath for parameter file output.
GApplicationPars * clone(void) const
Clone parameter container.
std::string m_syspfiles
Optional location of syspfiles.
int size(void) const
Return number of parameters in container.
virtual const char * what() const
Exception message.
Filename class.
Definition GFilename.hpp:62
std::string url(void) const
Return Uniform Resource Locator (URL)
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
int toint(const std::string &arg)
Convert string into integer value.
Definition GTools.cpp:821
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition GTools.cpp:80
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition GTools.cpp:983
std::string strip_chars(const std::string &arg, const std::string &chars)
Strip leading and trailing character from string.
Definition GTools.cpp:94