GammaLib 2.0.0
Loading...
Searching...
No Matches
GEnergies.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GEnergies.cpp - Energy container class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2013-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 GEnergies.cpp
23 * @brief Energy container class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GTools.hpp"
32#include "GException.hpp"
33#include "GFilename.hpp"
34#include "GEnergies.hpp"
35#include "GEbounds.hpp"
36#include "GFits.hpp"
37#include "GFitsTable.hpp"
38#include "GFitsBinTable.hpp"
39#include "GFitsTableCol.hpp"
41
42/* __ Method name definitions ____________________________________________ */
43#define G_AT "GEnergies::at(int&)"
44#define G_INSERT "GEnergies::insert(int&, GEnergy&)"
45#define G_REMOVE "GEnergies::remove(int&)"
46#define G_SET "GEnergies::set(int&, GEnergy&, GEnergy&, std::string&, "\
47 "double&)"
48#define G_SET_LIN "GEnergies::set_lin(int&, GEnergy&, GEnergy&)"
49#define G_SET_LOG "GEnergies::set_log(int&, GEnergy&, GEnergy&)"
50#define G_SET_POW "GEnergies::set_pow(int&, GEnergy&, GEnergy&, double&)"
51
52/* __ Macros _____________________________________________________________ */
53
54/* __ Coding definitions _________________________________________________ */
55
56/* __ Debug definitions __________________________________________________ */
57
58
59/*==========================================================================
60 = =
61 = Constructors/destructors =
62 = =
63 ==========================================================================*/
64
65/***********************************************************************//**
66 * @brief Void constructor
67 *
68 * Constructs empty energy container.
69 ***************************************************************************/
71{
72 // Initialise members
74
75 // Return
76 return;
77}
78
79
80/***********************************************************************//**
81 * @brief FITS file constructor
82 *
83 * @param[in] filename FITS file name.
84 *
85 * Constructs energy container from a FITS file.
86 ***************************************************************************/
88{
89 // Initialise members
91
92 // Load energies
93 load(filename);
94
95 // Return
96 return;
97}
98
99
100/***********************************************************************//**
101 * @brief Energy boundaries constructor
102 *
103 * @param[in] ebounds Energy boundaries.
104 *
105 * Constructs energy container from energy boundaries.
106 ***************************************************************************/
108{
109 // Initialise members
110 init_members();
111
112 // Set energies from energy boundaries
113 set(ebounds);
114
115 // Return
116 return;
117}
118
119
120/***********************************************************************//**
121 * @brief Copy constructor
122 *
123 * @param[in] energies Energy container.
124 *
125 * Construct energy container by copying from another energy container.
126 ***************************************************************************/
128{
129 // Initialise members
130 init_members();
131
132 // Copy members
133 copy_members(energies);
134
135 // Return
136 return;
137}
138
139
140/***********************************************************************//**
141 * @brief Interval constructor
142 *
143 * @param[in] num Number of energies.
144 * @param[in] emin Minimum energy.
145 * @param[in] emax Maximum energy.
146 * @param[in] method Energy spacing method (one of "LIN", "LOG" or "POW").
147 * @param[in] gamma Power law index for @p POW method.
148 *
149 * Constructs energy container by defining @p num energies between @p emin
150 * and @p emax. The @p method parameter controls the energy spacing of the
151 * energies. See the set() method for more information.
152 ***************************************************************************/
153GEnergies::GEnergies(const int& num,
154 const GEnergy& emin,
155 const GEnergy& emax,
156 const std::string& method,
157 const double& gamma)
158{
159 // Initialise members
160 init_members();
161
162 // Set intervals
163 set(num, emin, emax, method, gamma);
164
165 // Return
166 return;
167}
168
169
170/***********************************************************************//**
171 * @brief Destructor
172 ***************************************************************************/
174{
175 // Free members
176 free_members();
177
178 // Return
179 return;
180}
181
182
183/*==========================================================================
184 = =
185 = Operators =
186 = =
187 ==========================================================================*/
188
189/***********************************************************************//**
190 * @brief Assignment operator
191 *
192 * @param[in] energies Energy container.
193 * @return Energy container.
194 ***************************************************************************/
196{
197 // Execute only if object is not identical
198 if (this != &energies) {
199
200 // Free members
201 free_members();
202
203 // Initialise members
204 init_members();
205
206 // Copy members
207 copy_members(energies);
208
209 } // endif: object was not identical
210
211 // Return this object
212 return *this;
213}
214
215
216/*==========================================================================
217 = =
218 = Public methods =
219 = =
220 ==========================================================================*/
221
222/***********************************************************************//**
223 * @brief Clear energy container
224 *
225 * Removes all energies from the container.
226 ***************************************************************************/
228{
229 // Free members
230 free_members();
231
232 // Initialise members
233 init_members();
234
235 // Return
236 return;
237}
238
239
240/***********************************************************************//**
241 * @brief Clone energy container
242 *
243 * @return Pointer to deep copy of energy container
244 *
245 * Makes a deep copy of the energy container instance.
246 ***************************************************************************/
248{
249 return new GEnergies(*this);
250}
251
252
253/***********************************************************************//**
254 * @brief Return reference to energy
255 *
256 * @param[in] index Energy index [0,...,size()[.
257 *
258 * @exception GException::out_of_range
259 * Energy index is out of range.
260 *
261 * Returns a reference to the energy with the specified @p index.
262 ***************************************************************************/
263GEnergy& GEnergies::at(const int& index)
264{
265 // Raise exception if index is out of range
266 if (index < 0 || index >= size()) {
267 throw GException::out_of_range(G_AT, "Energy index", index, size());
268 }
269
270 // Return reference
271 return m_energies[index];
272}
273
274
275/***********************************************************************//**
276 * @brief Return reference to energy (const version)
277 *
278 * @param[in] index Energy index [0,...,size()[.
279 *
280 * @exception GException::out_of_range
281 * Energy index is out of range.
282 *
283 * Returns a reference to the energy with the specified @p index.
284 ***************************************************************************/
285const GEnergy& GEnergies::at(const int& index) const
286{
287 // Raise exception if index is out of range
288 if (index < 0 || index >= size()) {
289 throw GException::out_of_range(G_AT, "Energy index", index, size());
290 }
291
292 // Return reference
293 return m_energies[index];
294}
295
296
297/***********************************************************************//**
298 * @brief Append energy to container
299 *
300 * @param[in] energy Energy.
301 * @return Reference to appended energy.
302 *
303 * Appends energy to the container by making a deep copy of the energy.
304 ***************************************************************************/
306{
307 // Append energy to list
308 m_energies.push_back(energy);
309
310 // Return reference
311 return m_energies[size()-1];
312}
313
314
315/***********************************************************************//**
316 * @brief Insert energy into container
317 *
318 * @param[in] index Energy index (0,...,size()[.
319 * @param[in] energy Energy.
320 *
321 * @exception GException::out_of_range
322 * Energy index is out of range.
323 *
324 * Inserts an @p energy into the container before the energy with the
325 * specified @p index.
326 ***************************************************************************/
327GEnergy& GEnergies::insert(const int& index, const GEnergy& energy)
328{
329 // Compile option: raise exception if index is out of range
330 #if defined(G_RANGE_CHECK)
331 if (is_empty()) {
332 if (index > 0) {
333 throw GException::out_of_range(G_INSERT, "Energy index",
334 index, size());
335 }
336 }
337 else {
338 if (index < 0 || index >= size()) {
339 throw GException::out_of_range(G_INSERT, "Energy index",
340 index, size());
341 }
342 }
343 #endif
344
345 // Inserts energy
346 m_energies.insert(m_energies.begin()+index, energy);
347
348 // Return reference
349 return m_energies[index];
350}
351
352
353/***********************************************************************//**
354 * @brief Remove energy from container
355 *
356 * @param[in] index Energy index (0,...,size()[.
357 *
358 * @exception GException::out_of_range
359 * Energy index is out of range.
360 *
361 * Remove energy of specified @p index from container.
362 ***************************************************************************/
363void GEnergies::remove(const int& index)
364{
365 // Compile option: raise exception if index is out of range
366 #if defined(G_RANGE_CHECK)
367 if (index < 0 || index >= size()) {
368 throw GException::out_of_range(G_REMOVE, "Energy index",
369 index, size());
370 }
371 #endif
372
373 // Erase energy from container
374 m_energies.erase(m_energies.begin() + index);
375
376 // Return
377 return;
378}
379
380
381/***********************************************************************//**
382 * @brief Append energy container
383 *
384 * @param[in] energies Energy container.
385 *
386 * Append energy container to the container.
387 ***************************************************************************/
388void GEnergies::extend(const GEnergies& energies)
389{
390 // Do nothing if energy container is empty
391 if (!energies.is_empty()) {
392
393 // Get size. Note that we extract the size first to avoid an
394 // endless loop that arises when a container is appended to
395 // itself.
396 int num = energies.size();
397
398 // Reserve enough space
399 reserve(size() + num);
400
401 // Loop over all elements and append them to container
402 for (int i = 0; i < num; ++i) {
403 m_energies.push_back(energies[i]);
404 }
405
406 } // endif: energy container was not empty
407
408 // Return
409 return;
410}
411
412
413/***********************************************************************//**
414 * @brief Set energies from energy boundaries
415 *
416 * @param[in] ebounds Energy boundaries.
417 *
418 * Sets the energies from energy boundaries. Each unique minimum and maximum
419 * energy boundary will be appended as energy to the container.
420 ***************************************************************************/
421void GEnergies::set(const GEbounds& ebounds)
422{
423 // Initialise members
424 clear();
425
426 // Get number of energy boundaries
427 int num = ebounds.size();
428
429 // Append energy boundaries
430 for (int i = 0; i < num; ++i) {
431
432 // Loop over minimum and maximum boundaries
433 for (int j = 0; j < 2; ++j) {
434
435 // Get energy
436 GEnergy energy = (j == 0) ? ebounds.emin(i) : ebounds.emax(i);
437
438 // Append energy if it does not yet exist in the container
439 bool not_found = true;
440 for (int k = 0; k < m_energies.size(); ++k) {
441 if (energy == m_energies[k]) {
442 not_found = false;
443 break;
444 }
445 }
446 if (not_found) {
447 m_energies.push_back(energy);
448 }
449
450 } // endfor: looped over minimum and maximum boundaries
451
452 } // endfor: looped over energy boundaries
453
454 // Return
455 return;
456}
457
458
459/***********************************************************************//**
460 * @brief Set energies
461 *
462 * @param[in] num Number of energies.
463 * @param[in] emin Minimum energy.
464 * @param[in] emax Maximum energy.
465 * @param[in] method Energy spacing method (one of "LIN", "LOG" or "POW").
466 * @param[in] gamma Power law index for @p POW method.
467 *
468 * @exception GException::invalid_argument
469 * Invalid number of energies, energy interval or energy spacing
470 * method specified.
471 *
472 * Sets energies by defining @p num successive energies between @p emin and
473 * @p emax. The @p method parameter controls the energy spacing. See the
474 * set_lin(), set_log() and set_pow() methods for more information.
475 ***************************************************************************/
476void GEnergies::set(const int& num,
477 const GEnergy& emin,
478 const GEnergy& emax,
479 const std::string& method,
480 const double& gamma)
481{
482 // Check validity of number of energies
483 if (num < 0) {
484 std::string msg = "Negative number of energies "+gammalib::str(num)+
485 " specified. Please specify a non-negative number "
486 "of energies.";
488 }
489
490 // Check validity of energies
491 if (emin > emax) {
492 std::string msg = "Minimum energy "+emin.print()+" is larger than "
493 "maximum energy "+emax.print()+". Please specify "
494 "a minimum energy that does not exceed the "
495 "maximum energy.";
497 }
498
499 // If one energy is requested then check that emin and emax are equal
500 if (num == 1) {
501
502 // Check that emin and emax are equal
503 if (emin != emax) {
504 std::string msg = "Single energy is requested but the minimum "
505 "energy "+emin.print()+" differs from the "
506 "maximum energy "+emax.print()+". Please "
507 "specify identical energies.";
509 }
510
511 }
512
513 // Convert method to upper-case string
514 std::string umethod = gammalib::toupper(method);
515
516 // Dispatch to corresponding set methos
517 if (umethod == "LIN") {
518 set_lin(num, emin, emax);
519 }
520 else if (umethod == "LOG") {
521 set_log(num, emin, emax);
522 }
523 else if (umethod == "POW") {
524 set_pow(num, emin, emax, gamma);
525 }
526 else {
527 std::string msg = "Invalid energy spacing method \""+umethod+"\" "
528 "specified. Please provide one of \"LIN\", \"LOG\""
529 ", or \"POW\".";
531 }
532
533 // Return
534 return;
535}
536
537
538/***********************************************************************//**
539 * @brief Load energies from FITS file
540 *
541 * @param[in] filename FITS file name.
542 *
543 * Loads the energies from FITS file.
544 *
545 * If no extension name is provided, the energies are loaded from the
546 * `ENERGIES` extension.
547 ***************************************************************************/
548void GEnergies::load(const GFilename& filename)
549{
550 // Open FITS file
551 GFits fits(filename);
552
553 // Get energies table
554 const GFitsTable& table =
556
557 // Read energies from table
558 read(table);
559
560 // Close FITS file
561 fits.close();
562
563 // Return
564 return;
565}
566
567
568/***********************************************************************//**
569 * @brief Save energies into FITS file
570 *
571 * @param[in] filename FITS filename.
572 * @param[in] clobber Overwrite an existing energies extension?
573 *
574 * Saves energies into a FITS file. If a file with the given @p filename
575 * does not yet exist it will be created, otherwise the method opens the
576 * existing file. Energies can only be appended to an existing file if the
577 * @p clobber flag is set to `true` (otherwise an exception is thrown).
578 *
579 * The method will append a binary FITS table containing the energies to the
580 * FITS file. The extension name can be specified as part of the
581 * @p filename. For example the @p filename
582 *
583 * myfile.fits[ENERGY VALUES]
584 *
585 * will save the energies in the `ENERGY VALUES` extension of the
586 * `myfile.fits` file. If the extension exists already in the file it will be
587 * replaced, otherwise a new extension will be created. If no extension name
588 * is provided, the method will use `ENERGIES` as the default extension name
589 * for energies.
590 ***************************************************************************/
591void GEnergies::save(const GFilename& filename, const bool& clobber) const
592{
593 // Open or create FITS file (without extension name since the requested
594 // extension may not yet exist in the file)
595 GFits fits(filename.url(), true);
596
597 // Write energies to FITS file
599
600 // Save to file
601 fits.save(clobber);
602
603 // Return
604 return;
605}
606
607
608/***********************************************************************//**
609 * @brief Read energies from FITS table
610 *
611 * @param[in] table FITS table.
612 *
613 * Reads the energies from a FITS table.
614 ***************************************************************************/
615void GEnergies::read(const GFitsTable& table)
616{
617 // Free members
618 free_members();
619
620 // Initialise attributes
621 init_members();
622
623 // Extract number of energy bins in FITS file
624 int num = table.integer("NAXIS2");
625
626 // Continue only if there are energy bins
627 if (num > 0) {
628
629 // Get the unit of the energies. If no TUNIT1 header keyword is
630 // found then use MeV
631 std::string unit = "MeV";
632 if (table.has_card("TUNIT1")) {
633 unit = table.string("TUNIT1");
634 }
635
636 // Get the column with the name "Energy"
637 const GFitsTableCol* col_energy = table["Energy"];
638
639 // Set energies
640 for (int i = 0; i < num; ++i) {
641 append(GEnergy(col_energy->real(i), unit));
642 }
643
644 } // endif: there were energy bins
645
646 // Return
647 return;
648}
649
650
651/***********************************************************************//**
652 * @brief Write energies into FITS object
653 *
654 * @param[in] fits FITS file.
655 * @param[in] extname Energy extension name.
656 *
657 * Writes energies into FITS object.
658 ***************************************************************************/
659void GEnergies::write(GFits& fits, const std::string& extname) const
660{
661 // Set number of energies
662 int num = m_energies.size();
663
664 // Create Energy column
665 GFitsTableDoubleCol col_energy("Energy", num);
666
667 // Fill energy column in units of MeV
668 for (int i = 0; i < num; ++i) {
669 col_energy(i) = (*this)[i].MeV();
670 }
671 col_energy.unit("MeV");
672
673 // Create energies table
674 GFitsBinTable table(num);
675 table.append(col_energy);
676 table.extname(extname);
677
678 // If the FITS object contains already an extension with the same
679 // name then remove now this extension
680 if (fits.contains(extname)) {
681 fits.remove(extname);
682 }
683
684 // Append energies table to FITS file
685 fits.append(table);
686
687 // Return
688 return;
689}
690
691
692/***********************************************************************//**
693 * @brief Print energy container information
694 *
695 * @param[in] chatter Chattiness.
696 * @return String containing energy container information.
697 ***************************************************************************/
698std::string GEnergies::print(const GChatter& chatter) const
699{
700 // Initialise result string
701 std::string result;
702
703 // Continue only if chatter is not silent
704 if (chatter != SILENT) {
705
706 // Append header
707 result.append("=== GEnergies ===");
708
709 // Append energy container information
710 result.append("\n"+gammalib::parformat("Number of energies"));
711 result.append(gammalib::str(size()));
712
713 // EXPLICIT: Append energies
714 if (chatter >= EXPLICIT) {
715 for (int i = 0; i < size(); ++i) {
716 result.append("\n");
717 result.append(gammalib::parformat("Energy "+gammalib::str(i)));
718 result.append(m_energies[i].print(chatter));
719 }
720 }
721
722 } // endif: chatter was not silent
723
724 // Return result
725 return result;
726}
727
728
729/*==========================================================================
730 = =
731 = Private methods =
732 = =
733 ==========================================================================*/
734
735/***********************************************************************//**
736 * @brief Initialise class members
737 ***************************************************************************/
739{
740 // Initialise members
741 m_energies.clear();
742
743 // Return
744 return;
745}
746
747
748/***********************************************************************//**
749 * @brief Copy class members
750 *
751 * @param[in] energies Energy container.
752 ***************************************************************************/
754{
755 // Copy attributes
756 m_energies = energies.m_energies;
757
758 // Return
759 return;
760}
761
762
763/***********************************************************************//**
764 * @brief Delete class members
765 ***************************************************************************/
767{
768 // Return
769 return;
770}
771
772
773/***********************************************************************//**
774 * @brief Set linearly spaced energies
775 *
776 * @param[in] num Number of energies (>0).
777 * @param[in] emin Minimum energy.
778 * @param[in] emax Maximum energy.
779 *
780 * Creates \f$N\f$ linearly spaced energy boundaries running from
781 * \f$E_{\rm min}\f$ to \f$E_{\rm max}\f$ defined by
782 *
783 * \f[
784 * E_i = E_{\rm min} + \frac{E_{\rm max} - E_{\rm min}}{N-1}
785 * \times i
786 * \f]
787 *
788 * The method does not check the validity of the @p num, @p emin and @p emax
789 * arguments.
790 ***************************************************************************/
791void GEnergies::set_lin(const int& num,
792 const GEnergy& emin,
793 const GEnergy& emax)
794{
795 // Initialise members
796 clear();
797
798 // If a single energy is requested then just append the minimum energy
799 if (num == 1) {
800 append(emin);
801 }
802
803 // ... otherwise append linearly spaced energies
804 else if (num > 1) {
805
806 // Compute bin width
807 GEnergy ebin = (emax - emin)/double(num-1);
808
809 // Append energies
810 GEnergy energy = emin;
811 for (int i = 0; i < num; ++i) {
812 append(energy);
813 energy += ebin;
814 }
815
816 }
817
818 // Return
819 return;
820}
821
822
823/***********************************************************************//**
824 * @brief Set logarithmically spaced energies
825 *
826 * @param[in] num Number of energies (>0).
827 * @param[in] emin Minimum energy.
828 * @param[in] emax Maximum energy.
829 *
830 * @exception GException::invalid_argument
831 * Minimum or maximum energy are not positive.
832 *
833 * Creates \f$N\f$ logarithmically spaced energy boundaries running from
834 * \f$E_{\rm min}\f$ to \f$E_{\rm max}\f$ defined by
835 *
836 * \f[
837 * E_i = 10^{\log_{10} E_{\rm min} +
838 * \frac{\log_{10} E_{\rm max} - \log_{10} E_{\rm min}}{N-1}
839 * \times i}
840 * \f]
841 *
842 * The method does not check the validity of the @p num, @p emin and @p emax
843 * arguments except for the positivity of @p emin and @p emax.
844 ***************************************************************************/
845void GEnergies::set_log(const int& num,
846 const GEnergy& emin,
847 const GEnergy& emax)
848{
849 // Initialise members
850 clear();
851
852 // Throw an exception if the minimum or maximum energy is not positive
853 if (emin.MeV() <= 0.0) {
854 std::string msg = "Non-positive minimum energy "+emin.print()+
855 " specified. Please provide a positive minimum "
856 "energy value.";
858 }
859 if (emax.MeV() <= 0.0) {
860 std::string msg = "Non-positive maximum energy "+emax.print()+
861 " specified. Please provide a positive minimum "
862 "energy value.";
864 }
865
866 // If a single energy is requested then just append the minimum energy
867 if (num == 1) {
868 append(emin);
869 }
870
871 // ... otherwise append logarithmically spaced energies
872 else if (num > 1) {
873
874 // Compute bin width
875 double elogmin = std::log10(emin.MeV());
876 double elogmax = std::log10(emax.MeV());
877 double elogbin = (elogmax - elogmin)/double(num-1);
878
879 // Append energies
880 GEnergy energy;
881 for (int i = 0; i < num; ++i) {
882 energy.MeV(std::pow(10.0, double(i)*elogbin + elogmin));
883 append(energy);
884 }
885
886 }
887
888 // Return
889 return;
890}
891
892
893/***********************************************************************//**
894 * @brief Set power-law spaced energy intervals
895 *
896 * @param[in] num Number of energy intervals (>0).
897 * @param[in] emin Minimum energy of first interval.
898 * @param[in] emax Maximum energy of last interval.
899 * @param[in] gamma Power law index.
900 *
901 * @exception GException::invalid_argument
902 * Minimum or maximum energy are not positive.
903 *
904 * Creates \f$N\f$ power-law spaced energy boundaries running from
905 * \f$E_{\rm min}\f$ to \f$E_{\rm max}\f$ defined by
906 *
907 * \f[
908 * E_i = \left \{
909 * \begin{array}{l l}
910 * \exp \left( \frac{\log E_{\rm max} - \log E_{\rm min}}{N-1} +
911 * \log E_{i-1} \right)
912 * & \mbox{if $a = 0$} \\
913 * \\
914 * \exp \left( \frac{\log \left(\frac{E_{\rm max}^a - E_{\rm min}^a}{N-1} \right) +
915 * E_{i-1}^{a}}{a} \right)
916 * & \mbox{else}
917 * \end{array}
918 * \right .
919 * \f]
920 *
921 * where \f$i>0\f$, \f$a=1-\gamma\f$ and \f$E_0=E_{\rm min}\f$.
922 *
923 * The method does not check the validity of the @p num, @p emin and @p emax
924 * arguments except for the positivity of @p emin and @p emax.
925 ***************************************************************************/
926void GEnergies::set_pow(const int& num,
927 const GEnergy& emin,
928 const GEnergy& emax,
929 const double& gamma)
930{
931 // Initialise members
932 clear();
933
934 // Throw an exception if the minimum or maximum energy is not positive
935 if (emin.MeV() <= 0.0) {
936 std::string msg = "Non-positive minimum energy "+emin.print()+
937 " specified. Please provide a positive minimum "
938 "energy value.";
940 }
941 if (emax.MeV() <= 0.0) {
942 std::string msg = "Non-positive maximum energy "+emax.print()+
943 " specified. Please provide a positive minimum "
944 "energy value.";
946 }
947
948 // If a single energy is requested then just append the minimum energy
949 if (num == 1) {
950 append(emin);
951 }
952
953 // ... otherwise append logarithmically spaced energies
954 else if (num > 1) {
955
956 // Append first energy
957 append(emin);
958
959 // Precomputation (we work in MeV from now on)
960 double a = 1.0 - gamma;
961 double c = (a == 0.0) ? 1.0 / (std::log(emax.MeV()) - std::log(emin.MeV()))
962 : a / (std::pow(emax.MeV(),a) - std::pow(emin.MeV(),a));
963 double b = double(c*(num-1.0));
964
965 // Initialse first energy
966 double e = emin.MeV();
967
968 // Loop over energies
969 for (int i = 0; i < num-1; ++i) {
970
971 // Compute next energy
972 double log_e_next = (a == 0.0)
973 ? 1.0/b + std::log(e)
974 : std::log(a/b + std::pow(e,a)) / a;
975 double e_next = std::exp(log_e_next);
976
977 // Append next energy
978 append(GEnergy(e_next, "MeV"));
979
980 // Set next energy as starting energy for next iteration
981 e = e_next;
982
983 } // endfor: looped over energies
984
985 } // endif: number of energies was positive
986
987 // Return
988 return;
989}
#define G_AT
Energy boundaries class interface definition.
#define G_SET_POW
Definition GEnergies.cpp:50
#define G_SET_LOG
Definition GEnergies.cpp:49
#define G_SET
Definition GEnergies.cpp:46
Energy container class definition.
Exception handler interface definition.
Filename class interface definition.
FITS binary table class definition.
#define G_INSERT
#define G_REMOVE
FITS table column abstract base class definition.
FITS table double column class interface definition.
FITS table abstract base class interface definition.
FITS file class interface definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ EXPLICIT
Definition GTypemaps.hpp:37
@ SILENT
Definition GTypemaps.hpp:34
Energy boundaries container class.
Definition GEbounds.hpp:60
const GEnergy & emax(void) const
Return maximum energy of all intervals.
Definition GEbounds.hpp:199
int size(void) const
Return number of energy boundaries.
Definition GEbounds.hpp:163
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Definition GEbounds.hpp:187
Energy container class.
Definition GEnergies.hpp:60
std::string print(const GChatter &chatter=NORMAL) const
Print energy container information.
void init_members(void)
Initialise class members.
void read(const GFitsTable &table)
Read energies from FITS table.
void load(const GFilename &filename)
Load energies from FITS file.
GEnergies & operator=(const GEnergies &energies)
Assignment operator.
GEnergies(void)
Void constructor.
Definition GEnergies.cpp:70
void clear(void)
Clear energy container.
int size(void) const
Return number of energies in container.
void set_pow(const int &num, const GEnergy &emin, const GEnergy &emax, const double &gamma)
Set power-law spaced energy intervals.
void copy_members(const GEnergies &energies)
Copy class members.
GEnergy & at(const int &index)
Return reference to energy.
void set(const GEbounds &ebounds)
Set energies from energy boundaries.
void reserve(const int &num)
Reserves space for energies in container.
void extend(const GEnergies &energies)
Append energy container.
GEnergies * clone(void) const
Clone energy container.
GEnergy & append(const GEnergy &energy)
Append energy to container.
void save(const GFilename &filename, const bool &clobber=false) const
Save energies into FITS file.
virtual ~GEnergies(void)
Destructor.
void write(GFits &file, const std::string &extname=gammalib::extname_energies) const
Write energies into FITS object.
void set_lin(const int &num, const GEnergy &emin, const GEnergy &emax)
Set linearly spaced energies.
void remove(const int &index)
Remove energy from container.
bool is_empty(void) const
Signals if there are no energies in container.
void set_log(const int &num, const GEnergy &emin, const GEnergy &emax)
Set logarithmically spaced energies.
GEnergy & insert(const int &index, const GEnergy &energy)
Insert energy into container.
void free_members(void)
Delete class members.
std::vector< GEnergy > m_energies
List of energies.
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
double MeV(void) const
Return energy in MeV.
Definition GEnergy.cpp:321
std::string print(const GChatter &chatter=NORMAL) const
Print energy.
Definition GEnergy.cpp:748
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.
bool has_card(const int &cardno) const
Check existence of header card.
Definition GFitsHDU.hpp:233
const std::string & extname(void) const
Return extension name.
Definition GFitsHDU.hpp:162
std::string string(const std::string &keyname) const
Return card value as string.
Definition GFitsHDU.hpp:410
int integer(const std::string &keyname) const
Return card value as integer.
Definition GFitsHDU.hpp:436
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.
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:1143
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
std::string toupper(const std::string &s)
Convert string to upper case.
Definition GTools.cpp:941
const std::string extname_energies
Definition GEnergies.hpp:44