GammaLib 2.2.0.dev
Loading...
Searching...
No Matches
GBounds.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GBounds.cpp - Boundary class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2026 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 GBounds.cpp
23 * @brief Boundary class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <cmath>
32#include "GException.hpp"
33#include "GTools.hpp"
34#include "GFilename.hpp"
35#include "GBounds.hpp"
36#include "GFits.hpp"
37#include "GFitsTable.hpp"
38#include "GFitsBinTable.hpp"
40
41/* __ Method name definitions ____________________________________________ */
42#define G_REMOVE_INX "GBounds::remove(int&)"
43#define G_SET "GBounds::set(int&, double&, double&, std::string&, double&)"
44#define G_MIN_SET "GBounds::min(int&, double&)"
45#define G_MAX_SET "GBounds::max(int&, double&)"
46#define G_MIN_GET "GBounds::min(int&)"
47#define G_MAX_GET "GBounds::max(int&)"
48#define G_MEAN "GBounds::mean(int&)"
49#define G_LOGMEAN "GBounds::logmean(int&)"
50#define G_WIDTH "GBounds::width(int&)"
51#define G_INSERT_VALUE "GBounds::insert_value(int&, double&, double&)"
52
53/* __ Macros _____________________________________________________________ */
54
55/* __ Coding definitions _________________________________________________ */
56
57/* __ Debug definitions __________________________________________________ */
58
59
60/*==========================================================================
61 = =
62 = Constructors/destructors =
63 = =
64 ==========================================================================*/
65
66/***********************************************************************//**
67 * @brief Void constructor
68 *
69 * Constructs empty boundaries.
70 ***************************************************************************/
72{
73 // Initialise members
75
76 // Return
77 return;
78}
79
80
81/***********************************************************************//**
82 * @brief FITS file constructor
83 *
84 * @param[in] filename FITS file name.
85 *
86 * Constructs boundaries from a FITS file.
87 ***************************************************************************/
89{
90 // Initialise members
92
93 // Load FITS file
94 load(filename);
95
96 // Return
97 return;
98}
99
100
101/***********************************************************************//**
102 * @brief Array constructor
103 *
104 * @param[in] array Array.
105 * @param[in] unit Boundary units.
106 *
107 * Constructs boundaries from an array of values. Optionally boundary units
108 * may be specified for the array values.
109 ***************************************************************************/
110GBounds::GBounds(const std::vector<double>& array, const std::string& unit)
111{
112 // Initialise members
113 init_members();
114
115 // Set boundaries from array
116 set(array);
117
118 // Set units
119 this->unit(unit);
120
121 // Return
122 return;
123}
124
125
126/***********************************************************************//**
127 * @brief Copy constructor
128 *
129 * @param[in] bounds Boundaries.
130 ***************************************************************************/
132{
133 // Initialise class members for clean destruction
134 init_members();
135
136 // Copy members
137 copy_members(bounds);
138
139 // Return
140 return;
141}
142
143
144/***********************************************************************//**
145 * @brief Interval constructor
146 *
147 * @param[in] min Minimum of the interval.
148 * @param[in] max Maximum of the interval.
149 * @param[in] unit Boundary units.
150 *
151 * Constructs boundaries for one [@p min, @p max[ interval. Optionally
152 * boundary units may be specified for the interval values.
153 ***************************************************************************/
154GBounds::GBounds(const double& min, const double& max, const std::string& unit)
155{
156 // Initialise members
157 init_members();
158
159 // Append interval
160 append(min, max);
161
162 // Set units
163 this->unit(unit);
164
165 // Return
166 return;
167}
168
169
170/***********************************************************************//**
171 * @brief Boundary constructor
172 *
173 * @param[in] num Number of intervals.
174 * @param[in] min Minimum value of first interval.
175 * @param[in] max Maximum value of last interval.
176 * @param[in] method Spacing method (one of "LIN", "LOG" or "POW").
177 * @param[in] unit Boundary units.
178 * @param[in] gamma Power law index for @p POW method.
179 *
180 * Constructs boundaries by defining @p num successive intervals between
181 * @p min and @p max. The @p method parameter controls the spacing of the
182 * boundaries. Optionally boundary units may be specified for the interval
183 * values. For the @p POW method, the parameter @p gamma controls the slope
184 * of the power law. See the set() method for more information.
185 ***************************************************************************/
186GBounds::GBounds(const int& num,
187 const double& min,
188 const double& max,
189 const std::string& method,
190 const std::string& unit,
191 const double& gamma)
192{
193 // Initialise members
194 init_members();
195
196 // Set intervals
197 set(num, min, max, method, gamma);
198
199 // Set units
200 this->unit(unit);
201
202 // Return
203 return;
204}
205
206
207/***********************************************************************//**
208 * @brief Destructor
209 ***************************************************************************/
211{
212 // Free members
213 free_members();
214
215 // Return
216 return;
217}
218
219
220/*==========================================================================
221 = =
222 = Operators =
223 = =
224 ==========================================================================*/
225
226/***********************************************************************//**
227 * @brief Assignment operator
228 *
229 * @param[in] bounds Boundaries to be assigned.
230 * @return Boundaries.
231 ***************************************************************************/
233{
234 // Execute only if object is not identical
235 if (this != &bounds) {
236
237 // Free members
238 free_members();
239
240 // Initialise private members for clean destruction
241 init_members();
242
243 // Copy members
244 copy_members(bounds);
245
246 } // endif: object was not identical
247
248 // Return this object
249 return *this;
250}
251
252
253/*==========================================================================
254 = =
255 = Public methods =
256 = =
257 ==========================================================================*/
258
259/***********************************************************************//**
260 * @brief Clear boundaries
261 ***************************************************************************/
263{
264 // Free members
265 free_members();
266
267 // Initialise private members
268 init_members();
269
270 // Return
271 return;
272}
273
274
275/***********************************************************************//**
276 * @brief Clone boundaries
277 *
278 * @return Pointer to deep copy of boundaries.
279 ***************************************************************************/
281{
282 return new GBounds(*this);
283}
284
285
286/***********************************************************************//**
287 * @brief Append interval
288 *
289 * @param[in] min Minimum value of interval.
290 * @param[in] max Maximum value of interval.
291 *
292 * Appends an interval to the end of the boundaries container.
293 ***************************************************************************/
294void GBounds::append(const double& min, const double& max)
295{
296 // Append interval at the end of the container
298
299 // Return
300 return;
301}
302
303
304/***********************************************************************//**
305 * @brief Insert interval
306 *
307 * @param[in] min Minimum value of interval.
308 * @param[in] max Maximum value of interval.
309 *
310 * Inserts an interval into the boundaries after the first boundary that has
311 * a minimum value smaller than @p min. The method implicitely assumes that
312 * the intervals are ordered by increasing minimum value.
313 ***************************************************************************/
314void GBounds::insert(const double& min, const double& max)
315{
316 // Determine index at which interval should be inserted
317 int inx = 0;
318 for (; inx < size(); ++inx) {
319 if (min < m_min[inx])
320 break;
321 }
322
323 // Insert interval
324 insert_interval(inx, min, max);
325
326 // Return
327 return;
328}
329
330
331/***********************************************************************//**
332 * @brief Remove interval
333 *
334 * @param[in] index Interval index [0,...,size()[.
335 *
336 * Removes interval at @p index from the boundaries container. All intervals
337 * after the specified @p index are moved forward by one position.
338 ***************************************************************************/
339void GBounds::remove(const int& index)
340{
341 #if defined(G_RANGE_CHECK)
342 // If index is outside boundary then throw an error
343 if (index < 0 || index >= size()) {
344 throw GException::out_of_range(G_REMOVE_INX, "Interval index",
345 index, size());
346 }
347 #endif
348
349 // Erase boundary from container
350 m_min.erase(m_min.begin() + index);
351 m_max.erase(m_max.begin() + index);
352
353 // Return
354 return;
355}
356
357
358/***********************************************************************//**
359 * @brief Reserve space for intervals
360 *
361 * @param[in] num Number of elements.
362 ***************************************************************************/
363void GBounds::reserve(const int& num)
364{
365 // Reserve space
366 m_min.reserve(num);
367 m_max.reserve(num);
368
369 // Return
370 return;
371}
372
373
374/***********************************************************************//**
375 * @brief Append boundaries
376 *
377 * @param[in] ebds Energy boundaries.
378 *
379 * Append boundaries to the container.
380 ***************************************************************************/
381void GBounds::extend(const GBounds& bounds)
382{
383 // Do nothing if boundaries are empty
384 if (!bounds.is_empty()) {
385
386 // Get size. Note that we extract the size first to avoid an
387 // endless loop that arises when a container is appended to
388 // itself.
389 int num = bounds.size();
390
391 // Reserve enough space
392 reserve(size() + num);
393
394 // Loop over all elements and append them to container
395 for (int i = 0; i < num; ++i) {
396 m_min.push_back(m_min[i]);
397 m_max.push_back(m_max[i]);
398 }
399
400 } // endif: boundaries were not empty
401
402 // Return
403 return;
404}
405
406
407/***********************************************************************//**
408 * @brief Set boundaries from array
409 *
410 * @param[in] array Array.
411 *
412 * Sets boundaries from an array. Each two subsequent values in the array
413 * will form a boundary. This means that n values will lead to n-1 boundaries
414 * with the following mapping:
415 *
416 * [array[0], array[1]]
417 * [array[1], array[2]]
418 * ...
419 * [array[n-2], array[n-1]]
420 *
421 * If there is only one value in the array the following empty boundary will
422 * be appended:
423 *
424 * [array[0], array[0]]
425 *
426 * Note that the method conserves the units of the boundaries.
427 ***************************************************************************/
428void GBounds::set(const std::vector<double>& array)
429{
430 // Converse boundary units
431 std::string unit = m_unit;
432
433 // Initialise members
434 clear();
435
436 // Put back boundary units
437 m_unit = unit;
438
439 // Get number of values in container
440 int num = array.size();
441
442 // If there is only one value in the container then append an empty
443 // boundary
444 if (num == 1) {
445 append(array[0], array[0]);
446 }
447
448 // ... otherwise if there is more than one value in the container
449 // then append subsequent values as boundaries
450 else if (num > 1) {
451 for (int i = 0; i < num-1; ++i) {
452 append(array[i], array[i+1]);
453 }
454 }
455
456 // Return
457 return;
458}
459
460
461/***********************************************************************//**
462 * @brief Set intervals
463 *
464 * @param[in] num Number of intervals.
465 * @param[in] min Minimum value of first interval.
466 * @param[in] max Maximum value of last interval.
467 * @param[in] method Energy spacing method (one of "LIN", "LOG" or "POW").
468 * @param[in] gamma Power law index for @p POW method.
469 *
470 * @exception GException::invalid_argument
471 * @p num is negative.
472 * @p min value is not smaller than @p max value.
473 * Non-positive @p min value specified for LOG or POW method.
474 * Invalid spacing @p method specified.
475 *
476 * Sets boundaries by defining @p num successive intervals between @p min
477 * and @p max. The @p method parameter controls the spacing of the
478 * boundaries. Note that the @p max value needs to be larger than the @p min
479 * value. For the "LOG" and "POW" methods the @p min value needs to be
480 * positive.
481 *
482 * Note that the method conserves the units of the boundaries.
483 ***************************************************************************/
484void GBounds::set(const int& num,
485 const double& min,
486 const double& max,
487 const std::string& method,
488 const double& gamma)
489{
490 // Converse boundary units
491 std::string unit = m_unit;
492
493 // Initialise members
494 clear();
495
496 // Put back boundary units
497 m_unit = unit;
498
499 // Convert method to upper-case string
500 std::string umethod = gammalib::toupper(method);
501
502 // Check validity of number of values
503 if (num < 0) {
504 std::string msg = "Negative number of values "+gammalib::str(num)+
505 " specified. Please specify a non-negative number "
506 "of values.";
508 }
509
510 // Check validity of minimum value for logarithmic and powerlaw boundaries
511 if ((umethod == "LOG") || (umethod == "POW")) {
512 if (min <= 0.0) {
513 std::string msg = "Minimum value "+gammalib::str(min)+" is not "
514 "positive. \""+method+"\" method requires a "
515 "positive minimum value. Please specify a "
516 "positive minimum value.";
518 }
519 }
520
521 // Check validity of minimum and maximum values
522 if (min > max) {
523 std::string msg = "Minimum value "+gammalib::str(min)+" is larger than "
524 "maximum value "+gammalib::str(max)+". Please specify "
525 "a minimum value that does not exceed the "
526 "maximum value.";
528 }
529
530 // Reserve elements
531 reserve(num);
532
533 // Set linear boundaries
534 if (umethod == "LIN") {
535 double bin = (max - min)/double(num);
536 double value = min;
537 for (int i = 0; i < num; ++i) {
538 append(value, value+bin);
539 value += bin;
540 }
541 }
542
543 // ... otherwise set logarithmic boundaries
544 else if (umethod == "LOG") {
545 double logmin = std::log10(min);
546 double logmax = std::log10(max);
547 double logbin = (logmax - logmin)/double(num);
548 double vmin = min;
549 for (int i = 0; i < num; ++i) {
550 double vmax = std::pow(10.0, double(i+1)*logbin + logmin);
551 append(vmin, vmax);
552 vmin = vmax;
553 }
554 }
555
556 // ... otherwise set power law boundaries
557 else if (umethod == "POW") {
558 double a = 1.0 - gamma;
559 double c = (a == 0.0) ? 1.0 / (std::log(max) - std::log(min))
560 : a / (std::pow(max,a) - std::pow(min,a));
561 double b = double(c*(num));
562 double vmin = min;
563 for (int i = 0; i < num; ++i) {
564 double logvmax = (a == 0.0) ? 1.0/b + std::log(vmin)
565 : std::log(a/b + std::pow(vmin,a)) / a;
566 double vmax = std::exp(logvmax);
567 append(vmin, vmax);
568 vmin = vmax;
569 }
570 }
571
572 // ... otherwise throw an exception
573 else {
574 std::string msg = "Invalid spacing method \""+umethod+"\" "
575 "specified. Please provide one of \"LIN\", \"LOG\""
576 ", or \"POW\".";
578 }
579
580 // Return
581 return;
582}
583
584
585/***********************************************************************//**
586 * @brief Load boundaries from FITS file
587 *
588 * @param[in] filename FITS file name.
589 *
590 * Loads boundaries from a FITS file.
591 *
592 * If no extension name is provided, the boundaries are loaded from the
593 * `BOUNDS` extension.
594 ***************************************************************************/
595void GBounds::load(const GFilename& filename)
596{
597 // Open FITS file
598 GFits fits(filename);
599
600 // Get boundary table
601 const GFitsTable& table = *fits.table(filename.extname(gammalib::extname_bounds));
602
603 // Read boundaries from table
604 read(table);
605
606 // Close FITS file
607 fits.close();
608
609 // Return
610 return;
611}
612
613
614/***********************************************************************//**
615 * @brief Save boundaries into FITS file
616 *
617 * @param[in] filename FITS file name.
618 * @param[in] clobber Overwrite an existing boundaries extension?
619 *
620 * Saves boundaries into a FITS file. If a file with the given @p filename
621 * does not yet exist it will be created, otherwise the method opens the
622 * existing file. Boundaries can only be appended to an existing file if the
623 * @p clobber flag is set to "true" (otherwise an exception is thrown).
624 *
625 * The method will append a binary FITS table containing the boundaries to
626 * the FITS file. The extension name can be specified as part of the
627 * @p filename. For example the @p filename
628 *
629 * myfile.fits[BOUNDARIES]
630 *
631 * will save the boundaries in the `BOUNDARIES` extension of the
632 * "myfile.fits" file. If the extension exists already in the file it will
633 * be replaced, otherwise a new extension will be created. If no extension
634 * name is provided, the method will use `BOUNDS` as the default extension
635 * name for boundaries.
636 ***************************************************************************/
637void GBounds::save(const GFilename& filename,
638 const bool& clobber) const
639{
640 // Open or create FITS file (without extension name since the requested
641 // extension may not yet exist in the file)
642 GFits fits(filename.url(), true);
643
644 // Write boundaries to FITS file
645 write(fits, filename.extname(gammalib::extname_bounds));
646
647 // Save to file
648 fits.save(clobber);
649
650 // Return
651 return;
652}
653
654
655/***********************************************************************//**
656 * @brief Read boundaries from FITS table
657 *
658 * @param[in] table FITS table.
659 *
660 * Reads the boundaries from a FITS table.
661 ***************************************************************************/
662void GBounds::read(const GFitsTable& table)
663{
664 // Clear members
665 clear();
666
667 // Get number of boundaries in file
668 int num = table.nrows();
669
670 // Continue only if there are boundaries
671 if (num > 0) {
672
673 // Get columns
674 const GFitsTableCol* col_min = table["MIN"];
675 const GFitsTableCol* col_max = table["MAX"];
676
677 // Extract unit
678 m_unit = col_min->unit();
679
680 // Reserve space for boundaries
681 reserve(num);
682
683 // Read boundaries
684 for (int i = 0; i < num; ++i) {
685 append(col_min->real(i), col_max->real(i));
686 }
687
688 }
689
690 // Return
691 return;
692}
693
694
695/***********************************************************************//**
696 * @brief Write boundaries into FITS object
697 *
698 * @param[in] fits FITS file.
699 * @param[in] extname Boundary extension name.
700 *
701 * Writes the boundaries into a FITS object.
702 ***************************************************************************/
703void GBounds::write(GFits& fits, const std::string& extname) const
704{
705 // Create boundary columns
706 GFitsTableDoubleCol col_min("MIN", size());
707 GFitsTableDoubleCol col_max("MAX", size());
708
709 // Fill boundary columns
710 for (int i = 0; i < size(); ++i) {
711 col_min(i) = m_min[i];
712 col_max(i) = m_max[i];
713 }
714
715 // Set units
716 col_min.unit(m_unit);
717 col_max.unit(m_unit);
718
719 // Create binary table
720 GFitsBinTable table;
721
722 // Append columns
723 table.append(col_min);
724 table.append(col_max);
725
726 // Set extension name
727 table.extname(extname);
728
729 // If the FITS object contains already an extension with the same
730 // name then remove now this extension
731 if (fits.contains(extname)) {
732 fits.remove(extname);
733 }
734
735 // Append boundary table to FITS file
736 fits.append(table);
737
738 // Return
739 return;
740}
741
742
743/***********************************************************************//**
744 * @brief Returns bin index for a value
745 *
746 * @param[in] value Value.
747 * @return Bin index.
748 *
749 * Returns the boundary bin index for a given value. By convention, the limits
750 * for a bin are defined as
751 *
752 * min <= value < max
753 *
754 * i.e. a value equaling to max falls above the boundary.
755 *
756 * If the value falls outside all boundaries, -1 is returned.
757 ***************************************************************************/
758int GBounds::index(const double& value) const
759{
760 // Initialise index with 'not found'
761 int index = -1;
762
763 // Search all boundaries for containment
764 for (int i = 0; i < size(); ++i) {
765 if (value >= m_min[i] && value < m_max[i]) {
766 index = i;
767 break;
768 }
769 }
770
771 // Return index
772 return index;
773}
774
775
776/***********************************************************************//**
777 * @brief Return minimum value of all intervals
778 *
779 * @return Minimum value of all intervals.
780 ***************************************************************************/
781double GBounds::min(void) const
782{
783 // Initialise minimum value
784 double min = 0.0;
785
786 // If there are intervals then determine their minimum value
787 if (size() > 0) {
788 min = m_min[0];
789 for (int i = 1; i < size(); ++i) {
790 if (m_min[i] < min) {
791 min = m_min[i];
792 }
793 }
794 }
795
796 // Return minimum value
797 return min;
798}
799
800
801/***********************************************************************//**
802 * @brief Return maximum value of all intervals
803 *
804 * @return Maximum value of all intervals.
805 ***************************************************************************/
806double GBounds::max(void) const
807{
808 // Initialise maximum value
809 double max = 0.0;
810
811 // If there are intervals then determine their maximum value
812 if (size() > 0) {
813 max = m_max[0];
814 for (int i = 1; i < size(); ++i) {
815 if (m_max[i] > max) {
816 max = m_max[i];
817 }
818 }
819 }
820
821 // Return maximum value
822 return max;
823}
824
825
826/***********************************************************************//**
827 * @brief Set minimum value for a given interval
828 *
829 * @param[in] index Energy interval index (0,...,size()-1).
830 * @param[in] value Minimum value of interval.
831 *
832 * @exception GException::out_of_range
833 * Specified index is out of range.
834 *
835 * Sets the minimum value for the interval @p index.
836 ***************************************************************************/
837void GBounds::min(const int& index, const double& value)
838{
839 #if defined(G_RANGE_CHECK)
840 // Throw an exception if index is outside valid range
841 if (index < 0 || index >= size()) {
842 throw GException::out_of_range(G_MIN_SET, "Boundary index",
843 index, size());
844 }
845 #endif
846
847 // Set minimum value
848 m_min[index] = value;
849
850 // Return
851 return;
852}
853
854
855/***********************************************************************//**
856 * @brief Set maximum value for a given interval
857 *
858 * @param[in] index Interval index (0,...,size()-1).
859 * @param[in] value Maximum value of interval.
860 *
861 * @exception GException::out_of_range
862 * Specified index is out of range.
863 *
864 * Sets the maximum value for the interval @p index.
865 ***************************************************************************/
866void GBounds::max(const int& index, const double& value)
867{
868 #if defined(G_RANGE_CHECK)
869 // Throw an exception if index is outside valid range
870 if (index < 0 || index >= size()) {
871 throw GException::out_of_range(G_MAX_SET, "boundary index",
872 index, size());
873 }
874 #endif
875
876 // Set maximum value
877 m_max[index] = value;
878
879 // Return
880 return;
881}
882
883
884/***********************************************************************//**
885 * @brief Returns minimum value for a given interval
886 *
887 * @param[in] index Interval index (0,...,size()-1).
888 * @return Minimum value of interval.
889 *
890 * @exception GException::out_of_range
891 * Specified index is out of range.
892 ***************************************************************************/
893double GBounds::min(const int& index) const
894{
895 #if defined(G_RANGE_CHECK)
896 // Throw an exception if index is outside valid range
897 if (index < 0 || index >= size()) {
898 throw GException::out_of_range(G_MIN_GET, "Boundary index",
899 index, size());
900 }
901 #endif
902
903 // Return minimum value
904 return (m_min[index]);
905}
906
907
908/***********************************************************************//**
909 * @brief Returns maximum value for a given interval
910 *
911 * @param[in] index Interval index (0,...,size()-1).
912 * @return Maximum value of interval.
913 *
914 * @exception GException::out_of_range
915 * Specified index is out of range.
916 ***************************************************************************/
917double GBounds::max(const int& index) const
918{
919 #if defined(G_RANGE_CHECK)
920 // Throw an exception if index is outside valid range
921 if (index < 0 || index >= size()) {
922 throw GException::out_of_range(G_MAX_GET, "Boundary index",
923 index, size());
924 }
925 #endif
926
927 // Return maximum value
928 return (m_max[index]);
929}
930
931
932/***********************************************************************//**
933 * @brief Returns mean value for a given interval
934 *
935 * @param[in] index Interval index (0,...,size()-1).
936 * @return Mean value of interval.
937 *
938 * @exception GException::out_of_range
939 * Specified index is out of range.
940 *
941 * Computes the mean value for the interval @p index.
942 ***************************************************************************/
943double GBounds::mean(const int& index) const
944{
945 #if defined(G_RANGE_CHECK)
946 // If index is outside boundary then throw an error
947 if (index < 0 || index >= size()) {
948 throw GException::out_of_range(G_MEAN, "Boundary index",
949 index, size());
950 }
951 #endif
952
953 // Compute mean value
954 double mean = 0.5 * (m_min[index] + m_max[index]);
955
956 // Return mean value
957 return mean;
958}
959
960
961/***********************************************************************//**
962 * @brief Returns logarithmic mean value for a given interval
963 *
964 * @param[in] index Interval index (0,...,size()-1).
965 * @return Logarithmic mean value of interval.
966 *
967 * @exception GException::out_of_range
968 * Specified index is out of range.
969 *
970 * Computes the logarithmic mean value for the interval @p index.
971 ***************************************************************************/
972double GBounds::logmean(const int& index) const
973{
974 #if defined(G_RANGE_CHECK)
975 // If index is outside boundary then throw an error
976 if (index < 0 || index >= size()) {
977 throw GException::out_of_range(G_LOGMEAN, "Boundary index",
978 index, size());
979 }
980 #endif
981
982 // Compute logarithmic mean value
983 double logmean = std::sqrt(m_min[index] * m_max[index]);
984
985 // Return logarithmic mean value
986 return logmean;
987}
988
989
990/***********************************************************************//**
991 * @brief Returns interval width
992 *
993 * @param[in] index Interval index (0,...,size()-1).
994 * @return Interval width.
995 *
996 * @exception GException::out_of_range
997 * Specified index is out of range.
998 ***************************************************************************/
999double GBounds::width(const int& index) const
1000{
1001 #if defined(G_RANGE_CHECK)
1002 // If index is outside boundary then throw an error
1003 if (index < 0 || index >= size()) {
1004 throw GException::out_of_range(G_WIDTH, "Boundary index",
1005 index, size());
1006 }
1007 #endif
1008
1009 // Return
1010 return (m_max[index]-m_min[index]);
1011}
1012
1013
1014/***********************************************************************//**
1015 * @brief Checks whether boundaries contain value
1016 *
1017 * @param[in] value Value to be checked.
1018 * @return True if value falls in at least one interval, false otherwise.
1019 *
1020 * Checks if the @p value falls in at least one of the intervals. The method
1021 * exits when the first matching interval has been found.
1022 ***************************************************************************/
1023bool GBounds::contains(const double& value) const
1024{
1025 // Initialise result
1026 bool contained = false;
1027
1028 // Test all boundaries
1029 for (int i = 0; i < size(); ++i) {
1030 if (value >= m_min[i] && value <= m_max[i]) {
1031 contained = true;
1032 break;
1033 }
1034 }
1035
1036 // Return result
1037 return contained;
1038}
1039
1040
1041/***********************************************************************//**
1042 * @brief Checks whether boundaries contain an interval
1043 *
1044 * @param[in] min Minimum value of interval to be checked.
1045 * @param[in] max Maximum value of interval to be checked.
1046 * @return True if interval [min, max] exists within boundariesi.
1047 *
1048 * Checks if the interval [@p min, @p max] exists within the boundary
1049 * contained.
1050 ***************************************************************************/
1051bool GBounds::contains(const double& min, const double& max) const
1052{
1053 // Initialise result
1054 bool contained = false;
1055
1056 // Test all boundaries
1057 for (int i = 0; i < size(); ++i) {
1058 if (min == m_min[i] && max == m_max[i]) {
1059 contained = true;
1060 break;
1061 }
1062 }
1063
1064 // Return result
1065 return contained;
1066}
1067
1068
1069/***********************************************************************//**
1070 * @brief Print boundaries
1071 *
1072 * @param[in] chatter Chattiness.
1073 * @return String containing boundary information.
1074 ***************************************************************************/
1075std::string GBounds::print(const GChatter& chatter) const
1076{
1077 // Initialise result string
1078 std::string result;
1079
1080 // Continue only if chatter is not silent
1081 if (chatter != SILENT) {
1082
1083 // Append Header
1084 result.append("=== GBounds ===");
1085
1086 // Append information
1087 result.append("\n"+gammalib::parformat("Number of intervals"));
1088 result.append(gammalib::str(size()));
1089 result.append("\n"+gammalib::parformat("Value range"));
1090 result.append(gammalib::str(min()));
1091 result.append(" - ");
1092 result.append(gammalib::str(max()));
1093 if (unit().length() > 0) {
1094 result.append(" ");
1095 result.append(unit());
1096 }
1097
1098 // If there are multiple bins then append them
1099 if (chatter >= EXPLICIT) {
1100 if (size() > 1) {
1101 for (int i = 0; i < size(); ++i) {
1102 result.append("\n");
1103 result.append(gammalib::parformat("Interval "+
1104 gammalib::str(i)));
1105 result.append(gammalib::str(min(i)));
1106 result.append(" - ");
1107 result.append(gammalib::str(max(i)));
1108 }
1109 }
1110 } // endif: chatter was less than explicit
1111
1112 } // endif: chatter was not silent
1113
1114 // Return
1115 return result;
1116}
1117
1118
1119/*==========================================================================
1120 = =
1121 = Private methods =
1122 = =
1123 ==========================================================================*/
1124
1125/***********************************************************************//**
1126 * @brief Initialise class members
1127 ***************************************************************************/
1129{
1130 // Initialise members
1131 m_unit.clear();
1132 m_min.clear();
1133 m_max.clear();
1134
1135 // Return
1136 return;
1137}
1138
1139
1140/***********************************************************************//**
1141 * @brief Copy class members
1142 *
1143 * @param[in] ebds Energy boundaries.
1144 ***************************************************************************/
1146{
1147 // Copy members
1148 m_unit = bounds.m_unit;
1149 m_min = bounds.m_min;
1150 m_max = bounds.m_max;
1151
1152 // Return
1153 return;
1154}
1155
1156
1157/***********************************************************************//**
1158 * @brief Delete class members
1159 ***************************************************************************/
1161{
1162 // Return
1163 return;
1164}
1165
1166
1167/***********************************************************************//**
1168 * @brief Insert interval
1169 *
1170 * @param[in] index Index after with interval is inserted.
1171 * @param[in] min Minimum value of interval.
1172 * @param[in] max Maximum value of interval.
1173 *
1174 * @exception GException::invalid_argument
1175 * Minimum value larger than maximum value
1176 *
1177 * Inserts an interval after the specified @p index in the boundaries. The
1178 * method does not reorder the intervals, instead the client needs to
1179 * determine the approriate @p index.
1180 *
1181 * Invalid parameters do not produce any exception, but are handled
1182 * transparently. If the interval is invalid (i.e. @p min > @p max) an
1183 * exception is thrown. If the @p index is out of the valid range, the
1184 * index will be adjusted to either the first or the last element.
1185 ***************************************************************************/
1186void GBounds::insert_interval(const int& index,
1187 const double& min,
1188 const double& max)
1189{
1190 // Throw an exception if interval is invalid
1191 if (min > max) {
1192 std::string msg = "Invalid interval specified. Minimum"
1193 " value "+gammalib::str(min)+" can not be"
1194 " larger than maximum value "+
1195 gammalib::str(max)+".";
1197 }
1198
1199 // Inserts interval
1200 m_min.insert(m_min.begin()+index, min);
1201 m_max.insert(m_max.begin()+index, max);
1202
1203 // Return
1204 return;
1205}
1206
1207
1208/*==========================================================================
1209 = =
1210 = Friends =
1211 = =
1212 ==========================================================================*/
1213
1214/***********************************************************************//**
1215 * @brief Boundaries equality operator friend
1216 *
1217 * @param[in] a First boundaries.
1218 * @param[in] b Second boundaries.
1219 * @return True if both boundaries are identical.
1220 ***************************************************************************/
1221bool operator==(const GBounds& a, const GBounds& b)
1222{
1223 // Initialise identify flag
1224 bool identity = true;
1225
1226 // Check that both boundaries have the same size
1227 if (a.size() != b.size()) {
1228 identity = false;
1229 }
1230
1231 // Check all boundaries
1232 else {
1233 for (int i = 0; i < a.size(); ++i) {
1234 if ((a.min(i) != b.min(i)) || (a.max(i) != b.max(i))) {
1235 identity = false;
1236 break;
1237 }
1238 }
1239 }
1240
1241 // Return identity flag
1242 return identity;
1243}
#define G_MAX_GET
Definition GBounds.cpp:47
#define G_INSERT_VALUE
Definition GBounds.cpp:51
#define G_MIN_GET
Definition GBounds.cpp:46
bool operator==(const GBounds &a, const GBounds &b)
Boundaries equality operator friend.
Definition GBounds.cpp:1221
#define G_MEAN
Definition GBounds.cpp:48
#define G_MIN_SET
Definition GBounds.cpp:44
#define G_MAX_SET
Definition GBounds.cpp:45
#define G_LOGMEAN
Definition GBounds.cpp:49
Boundaries class interface definition.
#define G_REMOVE_INX
Definition GEbounds.cpp:46
#define G_SET
Definition GEnergies.cpp:46
Exception handler interface definition.
Filename class interface definition.
FITS binary table class definition.
FITS table double column class interface definition.
FITS table abstract base class interface definition.
FITS file class interface definition.
#define G_WIDTH
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ EXPLICIT
Definition GTypemaps.hpp:37
@ SILENT
Definition GTypemaps.hpp:34
double min(const GVector &vector)
Computes minimum vector element.
Definition GVector.cpp:954
double max(const GVector &vector)
Computes maximum vector element.
Definition GVector.cpp:983
Boundaries container class.
Definition GBounds.hpp:59
void insert(const double &min, const double &max)
Insert interval.
Definition GBounds.cpp:314
void extend(const GBounds &bounds)
Append boundaries.
Definition GBounds.cpp:381
void read(const GFitsTable &table)
Read boundaries from FITS table.
Definition GBounds.cpp:662
void remove(const int &index)
Remove interval.
Definition GBounds.cpp:339
void clear(void)
Clear boundaries.
Definition GBounds.cpp:262
GBounds(void)
Void constructor.
Definition GBounds.cpp:71
bool is_empty(void) const
Signal if there are no boundaries.
Definition GBounds.hpp:166
GBounds * clone(void) const
Clone boundaries.
Definition GBounds.cpp:280
void init_members(void)
Initialise class members.
Definition GBounds.cpp:1128
const std::string & unit(void) const
Return boundary units.
Definition GBounds.hpp:178
void free_members(void)
Delete class members.
Definition GBounds.cpp:1160
void append(const double &min, const double &max)
Append interval.
Definition GBounds.cpp:294
void reserve(const int &num)
Reserve space for intervals.
Definition GBounds.cpp:363
void copy_members(const GBounds &bounds)
Copy class members.
Definition GBounds.cpp:1145
std::string m_unit
Unit of values.
Definition GBounds.hpp:130
std::vector< double > m_max
Array of interval maximum values.
Definition GBounds.hpp:132
void save(const GFilename &filename, const bool &clobber=false) const
Save boundaries into FITS file.
Definition GBounds.cpp:637
double max(void) const
Return maximum value of all intervals.
Definition GBounds.cpp:806
GBounds & operator=(const GBounds &bounds)
Assignment operator.
Definition GBounds.cpp:232
std::string print(const GChatter &chatter=NORMAL) const
Print boundaries.
Definition GBounds.cpp:1075
double mean(const int &index) const
Returns mean value for a given interval.
Definition GBounds.cpp:943
double min(void) const
Return minimum value of all intervals.
Definition GBounds.cpp:781
virtual ~GBounds(void)
Destructor.
Definition GBounds.cpp:210
void insert_interval(const int &index, const double &min, const double &max)
Insert interval.
Definition GBounds.cpp:1186
void write(GFits &file, const std::string &extname=gammalib::extname_bounds) const
Write boundaries into FITS object.
Definition GBounds.cpp:703
std::vector< double > m_min
Array of interval minimum values.
Definition GBounds.hpp:131
int size(void) const
Return number of boundaries.
Definition GBounds.hpp:154
void set(const std::vector< double > &array)
Set boundaries from array.
Definition GBounds.cpp:428
bool contains(const double &value) const
Checks whether boundaries contain value.
Definition GBounds.cpp:1023
double logmean(const int &index) const
Returns logarithmic mean value for a given interval.
Definition GBounds.cpp:972
void load(const GFilename &filename)
Load boundaries from FITS file.
Definition GBounds.cpp:595
double width(const int &index) const
Returns interval width.
Definition GBounds.cpp:999
int index(const double &value) const
Returns bin index for a value.
Definition GBounds.cpp:758
Filename class.
Definition GFilename.hpp:62
std::string url(void) const
Return Uniform Resource Locator (URL)
std::string extname(const std::string &defaultname="") const
Return extension name.
FITS binary table class.
const std::string & extname(void) const
Return extension name.
Definition GFitsHDU.hpp:162
Abstract interface for FITS table column.
virtual double real(const int &row, const int &inx=0) const =0
void unit(const std::string &unit)
Set column unit.
FITS table double column.
Abstract interface for FITS table.
GFitsTableCol * append(const GFitsTableCol &column)
Append column to the table.
const int & nrows(void) const
Return number of rows in table.
FITS file class.
Definition GFits.hpp:63
bool contains(const int &extno) const
Check if HDU exists in FITS file.
Definition GFits.hpp:282
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
Definition GFits.cpp:678
void close(void)
Close FITS file.
Definition GFits.cpp:1342
void remove(const int &extno)
Remove HDU from FITS file.
Definition GFits.cpp:862
void save(const bool &clobber=false)
Saves FITS file.
Definition GFits.cpp:1178
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition GFits.cpp:482
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1136
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
const std::string extname_bounds
Definition GBounds.hpp:43
std::string toupper(const std::string &s)
Convert string to upper case.
Definition GTools.cpp:934