Commit 5fbb6c3ebc420786b47bafa922080533fc08b6c3
Merge branch 'devel' into 1948-implement-smoothbrokenpowerlaw
Showing
8 changed files
with
273 additions
and
22 deletions
ChangeLog
| 1 | -2017-03-18 | 1 | +2017-03-22 |
| 2 | 2 | ||
| 3 | * Version 1.3.0 released | 3 | * Version 1.3.0 released |
| 4 | ========================= | 4 | ========================= |
| 5 | 5 | ||
| 6 | + Implement lazy loading of energy dispersion in GCTAEdisp2D (#1940) | ||
| 6 | Add GCTARoi::contains method | 7 | Add GCTARoi::contains method |
| 7 | Do no longer interpret a CTA calibration database as file path (#1969) | 8 | Do no longer interpret a CTA calibration database as file path (#1969) |
| 8 | Add GCTAResponseIrf::rspname() method | 9 | Add GCTAResponseIrf::rspname() method |
NEWS
| 1 | -New Features and Important Changes in GammaLib 1.3.0 | 1 | +New Features and Important Changes in GammaLib 1.3.0.dev1 |
| 2 | 2 | ||
| 3 | -18 March 2017 | 3 | +22 March 2017 |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | 1. Introduction | 6 | 1. Introduction |
| @@ -24,6 +24,7 @@ The following classes have been renamed: | @@ -24,6 +24,7 @@ The following classes have been renamed: | ||
| 24 | The following methods have been added: | 24 | The following methods have been added: |
| 25 | - GCTAResponseIrf::rspname | 25 | - GCTAResponseIrf::rspname |
| 26 | - GCTARoi::contains | 26 | - GCTARoi::contains |
| 27 | +- GCTAEdisp2D::fetch | ||
| 27 | 28 | ||
| 28 | The following methods have been removed: | 29 | The following methods have been removed: |
| 29 | - ... | 30 | - ... |
| @@ -141,6 +142,10 @@ GCTAResponseIrf::read() method (#1969). | @@ -141,6 +142,10 @@ GCTAResponseIrf::read() method (#1969). | ||
| 141 | Add GCTARoi::contains() method that checks whether an instrument direction | 142 | Add GCTARoi::contains() method that checks whether an instrument direction |
| 142 | is contained within the region of interest. | 143 | is contained within the region of interest. |
| 143 | 144 | ||
| 145 | +Lazy loading of the energy dispersion in GCTAEdisp2D has been implemented by | ||
| 146 | +adding a fetch() method to the class. Now the energy dispersion is only loaded | ||
| 147 | +when needed, for example for function evaluation or Monte Carlo sampling (#1940). | ||
| 148 | + | ||
| 144 | 149 | ||
| 145 | 21. COMPTEL interface | 150 | 21. COMPTEL interface |
| 146 | --------------------- | 151 | --------------------- |
inst/cta/include/GCTAEdisp2D.hpp
| 1 | /*************************************************************************** | 1 | /*************************************************************************** |
| 2 | * GCTAEdisp2D.hpp - CTA 2D energy dispersion class * | 2 | * GCTAEdisp2D.hpp - CTA 2D energy dispersion class * |
| 3 | * ----------------------------------------------------------------------- * | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2015-2016 by Florent Forest * | 4 | + * copyright (C) 2015-2017 by Florent Forest * |
| 5 | * ----------------------------------------------------------------------- * | 5 | * ----------------------------------------------------------------------- * |
| 6 | * * | 6 | * * |
| 7 | * This program is free software: you can redistribute it and/or modify * | 7 | * This program is free software: you can redistribute it and/or modify * |
| @@ -90,12 +90,14 @@ public: | @@ -90,12 +90,14 @@ public: | ||
| 90 | std::string print(const GChatter& chatter = NORMAL) const; | 90 | std::string print(const GChatter& chatter = NORMAL) const; |
| 91 | 91 | ||
| 92 | // Methods | 92 | // Methods |
| 93 | + void fetch(void) const; | ||
| 93 | const GCTAResponseTable& table(void) const; | 94 | const GCTAResponseTable& table(void) const; |
| 94 | void table(const GCTAResponseTable& table); | 95 | void table(const GCTAResponseTable& table); |
| 95 | void read(const GFitsTable& table); | 96 | void read(const GFitsTable& table); |
| 96 | void write(GFitsBinTable& table) const; | 97 | void write(GFitsBinTable& table) const; |
| 97 | void save(const GFilename& filename, | 98 | void save(const GFilename& filename, |
| 98 | const bool& clobber = false) const; | 99 | const bool& clobber = false) const; |
| 100 | + | ||
| 99 | private: | 101 | private: |
| 100 | // Methods | 102 | // Methods |
| 101 | void init_members(void); | 103 | void init_members(void); |
| @@ -133,6 +135,7 @@ private: | @@ -133,6 +135,7 @@ private: | ||
| 133 | // Members | 135 | // Members |
| 134 | mutable GFilename m_filename; //!< Name of Edisp response file | 136 | mutable GFilename m_filename; //!< Name of Edisp response file |
| 135 | GCTAResponseTable m_edisp; //!< Edisp response table | 137 | GCTAResponseTable m_edisp; //!< Edisp response table |
| 138 | + mutable bool m_fetched; //!< Signals that Edisp has been fetched | ||
| 136 | int m_inx_etrue; //!< True energy index | 139 | int m_inx_etrue; //!< True energy index |
| 137 | int m_inx_migra; //!< Migration index | 140 | int m_inx_migra; //!< Migration index |
| 138 | int m_inx_theta; //!< Theta index | 141 | int m_inx_theta; //!< Theta index |
inst/cta/src/GCTAEdisp2D.cpp
| @@ -45,6 +45,7 @@ | @@ -45,6 +45,7 @@ | ||
| 45 | #define G_READ "GCTAEdisp2D::read(GFitsTable&)" | 45 | #define G_READ "GCTAEdisp2D::read(GFitsTable&)" |
| 46 | #define G_MC "GCTAEdisp2D::mc(GRan&, double&, double&, double&, double&, "\ | 46 | #define G_MC "GCTAEdisp2D::mc(GRan&, double&, double&, double&, double&, "\ |
| 47 | "double&)" | 47 | "double&)" |
| 48 | +#define G_FETCH "GCTAEdisp2D::fetch()" | ||
| 48 | 49 | ||
| 49 | /* __ Macros _____________________________________________________________ */ | 50 | /* __ Macros _____________________________________________________________ */ |
| 50 | 51 | ||
| @@ -191,6 +192,9 @@ double GCTAEdisp2D::operator()(const double& logEobs, | @@ -191,6 +192,9 @@ double GCTAEdisp2D::operator()(const double& logEobs, | ||
| 191 | const double& zenith, | 192 | const double& zenith, |
| 192 | const double& azimuth) const | 193 | const double& azimuth) const |
| 193 | { | 194 | { |
| 195 | + // Make sure that energy dispersion is online | ||
| 196 | + fetch(); | ||
| 197 | + | ||
| 194 | // Initalize edisp | 198 | // Initalize edisp |
| 195 | double edisp = 0.0; | 199 | double edisp = 0.0; |
| 196 | 200 | ||
| @@ -407,6 +411,9 @@ void GCTAEdisp2D::read(const GFitsTable& table) | @@ -407,6 +411,9 @@ void GCTAEdisp2D::read(const GFitsTable& table) | ||
| 407 | ***************************************************************************/ | 411 | ***************************************************************************/ |
| 408 | void GCTAEdisp2D::write(GFitsBinTable& table) const | 412 | void GCTAEdisp2D::write(GFitsBinTable& table) const |
| 409 | { | 413 | { |
| 414 | + // Make sure that energy dispersion is online | ||
| 415 | + fetch(); | ||
| 416 | + | ||
| 410 | // Write background table | 417 | // Write background table |
| 411 | m_edisp.write(table); | 418 | m_edisp.write(table); |
| 412 | 419 | ||
| @@ -427,17 +434,8 @@ void GCTAEdisp2D::write(GFitsBinTable& table) const | @@ -427,17 +434,8 @@ void GCTAEdisp2D::write(GFitsBinTable& table) const | ||
| 427 | ***************************************************************************/ | 434 | ***************************************************************************/ |
| 428 | void GCTAEdisp2D::load(const GFilename& filename) | 435 | void GCTAEdisp2D::load(const GFilename& filename) |
| 429 | { | 436 | { |
| 430 | - // Open FITS file | ||
| 431 | - GFits fits(filename); | ||
| 432 | - | ||
| 433 | - // Get energy dispersion table | ||
| 434 | - const GFitsTable& table = *fits.table(filename.extname("ENERGY DISPERSION")); | ||
| 435 | - | ||
| 436 | - // Read energy dispersion from table | ||
| 437 | - read(table); | ||
| 438 | - | ||
| 439 | - // Close FITS file | ||
| 440 | - fits.close(); | 437 | + // Clear object |
| 438 | + clear(); | ||
| 441 | 439 | ||
| 442 | // Store filename | 440 | // Store filename |
| 443 | m_filename = filename; | 441 | m_filename = filename; |
| @@ -521,6 +519,9 @@ GEnergy GCTAEdisp2D::mc(GRan& ran, | @@ -521,6 +519,9 @@ GEnergy GCTAEdisp2D::mc(GRan& ran, | ||
| 521 | const double& zenith, | 519 | const double& zenith, |
| 522 | const double& azimuth) const | 520 | const double& azimuth) const |
| 523 | { | 521 | { |
| 522 | + // Make sure that energy dispersion is online | ||
| 523 | + fetch(); | ||
| 524 | + | ||
| 524 | // Get boundaries for observed energy | 525 | // Get boundaries for observed energy |
| 525 | GEbounds ebounds = ebounds_obs(logEsrc, theta, phi, zenith, azimuth); | 526 | GEbounds ebounds = ebounds_obs(logEsrc, theta, phi, zenith, azimuth); |
| 526 | double emin = ebounds.emin().log10TeV(); | 527 | double emin = ebounds.emin().log10TeV(); |
| @@ -582,6 +583,9 @@ GEbounds GCTAEdisp2D::ebounds_obs(const double& logEsrc, | @@ -582,6 +583,9 @@ GEbounds GCTAEdisp2D::ebounds_obs(const double& logEsrc, | ||
| 582 | const double& zenith, | 583 | const double& zenith, |
| 583 | const double& azimuth) const | 584 | const double& azimuth) const |
| 584 | { | 585 | { |
| 586 | + // Make sure that energy dispersion is online | ||
| 587 | + fetch(); | ||
| 588 | + | ||
| 585 | // Compute only if parameters changed | 589 | // Compute only if parameters changed |
| 586 | if (!m_ebounds_obs_computed || theta != m_last_theta_obs) { | 590 | if (!m_ebounds_obs_computed || theta != m_last_theta_obs) { |
| 587 | 591 | ||
| @@ -644,6 +648,9 @@ GEbounds GCTAEdisp2D::ebounds_src(const double& logEobs, | @@ -644,6 +648,9 @@ GEbounds GCTAEdisp2D::ebounds_src(const double& logEobs, | ||
| 644 | const double& zenith, | 648 | const double& zenith, |
| 645 | const double& azimuth) const | 649 | const double& azimuth) const |
| 646 | { | 650 | { |
| 651 | + // Make sure that energy dispersion is online | ||
| 652 | + fetch(); | ||
| 653 | + | ||
| 647 | // Compute only if parameters changed | 654 | // Compute only if parameters changed |
| 648 | if (!m_ebounds_src_computed || theta != m_last_theta_src) { | 655 | if (!m_ebounds_src_computed || theta != m_last_theta_src) { |
| 649 | 656 | ||
| @@ -687,9 +694,101 @@ GEbounds GCTAEdisp2D::ebounds_src(const double& logEobs, | @@ -687,9 +694,101 @@ GEbounds GCTAEdisp2D::ebounds_src(const double& logEobs, | ||
| 687 | 694 | ||
| 688 | 695 | ||
| 689 | /***********************************************************************//** | 696 | /***********************************************************************//** |
| 697 | + * @brief Fetch energy dispersion | ||
| 698 | + * | ||
| 699 | + * @exception GException::file_error | ||
| 700 | + * File not found. | ||
| 701 | + * Unable to load energy dispersion. | ||
| 702 | + * @exception GException::invalid_value | ||
| 703 | + * No file name has been specified. | ||
| 704 | + * | ||
| 705 | + * Fetches the energy dispersion by reading it from a FITS file. This method | ||
| 706 | + * does nothing if the energy dispersion is already loaded, if there is | ||
| 707 | + * nothing to fetch, or if the m_filename member is empty. | ||
| 708 | + * | ||
| 709 | + * The method is thread save. The method checks whether the file from which | ||
| 710 | + * the energy dispersion should be loaded actually exists. | ||
| 711 | + ***************************************************************************/ | ||
| 712 | +void GCTAEdisp2D::fetch(void) const | ||
| 713 | +{ | ||
| 714 | + // Continue only if energy dispersion has not yet been fetched | ||
| 715 | + if (!m_fetched) { | ||
| 716 | + | ||
| 717 | + // Continue only if the file name is not empty | ||
| 718 | + if (!m_filename.is_empty()) { | ||
| 719 | + | ||
| 720 | + // Throw an exception if the file does not exist | ||
| 721 | + if (!m_filename.exists()) { | ||
| 722 | + std::string msg = "File \""+m_filename+"\" not found. Cannot " | ||
| 723 | + "fetch energy dispersion. Maybe the file has " | ||
| 724 | + "been deleted in the meantime."; | ||
| 725 | + GException::file_error(G_FETCH, msg); | ||
| 726 | + } | ||
| 727 | + | ||
| 728 | + // Signal that energy dispersion will be fetched (has to come | ||
| 729 | + // before reading since the ebounds_obs() and ebounds_src() methods | ||
| 730 | + // will otherwise call the fetch() method recursively. | ||
| 731 | + m_fetched = true; | ||
| 732 | + | ||
| 733 | + // Initialise exception flag | ||
| 734 | + bool has_exception = false; | ||
| 735 | + | ||
| 736 | + // Load energy dispersion. Catch any exception. Put the code into | ||
| 737 | + // a critical zone as it might be called from within a parallelized | ||
| 738 | + // thread. | ||
| 739 | + #pragma omp critical | ||
| 740 | + { | ||
| 741 | + try { | ||
| 742 | + | ||
| 743 | + | ||
| 744 | + // Open FITS file | ||
| 745 | + GFits fits(m_filename); | ||
| 746 | + | ||
| 747 | + // Initialise energy dispersion extension name | ||
| 748 | + std::string extname = m_filename.extname("ENERGY DISPERSION"); | ||
| 749 | + | ||
| 750 | + // Get energy dispersion table | ||
| 751 | + const GFitsTable& table = *fits.table(extname); | ||
| 752 | + | ||
| 753 | + // Read energy dispersion from table | ||
| 754 | + const_cast<GCTAEdisp2D*>(this)->read(table); | ||
| 755 | + | ||
| 756 | + // Close FITS file | ||
| 757 | + fits.close(); | ||
| 758 | + | ||
| 759 | + } | ||
| 760 | + catch (...) { | ||
| 761 | + has_exception = true; | ||
| 762 | + } | ||
| 763 | + } | ||
| 764 | + | ||
| 765 | + // Throw an exception if an exception has occured | ||
| 766 | + if (has_exception) { | ||
| 767 | + std::string msg = "Unable to load energy dispersion from " | ||
| 768 | + "file \""+m_filename+"\"."; | ||
| 769 | + throw GException::file_error(G_FETCH, msg); | ||
| 770 | + } | ||
| 771 | + | ||
| 772 | + } // endif: filename was not empty | ||
| 773 | + | ||
| 774 | + // Throw an exception if the FITS file name is not known | ||
| 775 | + else { | ||
| 776 | + std::string msg = "Unable to fetch energy dispersion since no " | ||
| 777 | + "filename is specified."; | ||
| 778 | + throw GException::invalid_value(G_FETCH, msg); | ||
| 779 | + } | ||
| 780 | + | ||
| 781 | + } // endif: energy dispersion had not yet been fetched | ||
| 782 | + | ||
| 783 | + // Return | ||
| 784 | + return; | ||
| 785 | +} | ||
| 786 | + | ||
| 787 | + | ||
| 788 | +/***********************************************************************//** | ||
| 690 | * @brief Print energy dispersion information | 789 | * @brief Print energy dispersion information |
| 691 | * | 790 | * |
| 692 | - * @param[in] chatter Chattiness (defaults to NORMAL). | 791 | + * @param[in] chatter Chattiness. |
| 693 | * @return String containing energy dispersion information. | 792 | * @return String containing energy dispersion information. |
| 694 | ***************************************************************************/ | 793 | ***************************************************************************/ |
| 695 | std::string GCTAEdisp2D::print(const GChatter& chatter) const | 794 | std::string GCTAEdisp2D::print(const GChatter& chatter) const |
| @@ -700,6 +799,9 @@ std::string GCTAEdisp2D::print(const GChatter& chatter) const | @@ -700,6 +799,9 @@ std::string GCTAEdisp2D::print(const GChatter& chatter) const | ||
| 700 | // Continue only if chatter is not silent | 799 | // Continue only if chatter is not silent |
| 701 | if (chatter != SILENT) { | 800 | if (chatter != SILENT) { |
| 702 | 801 | ||
| 802 | + // Make sure that energy dispersion is online | ||
| 803 | + fetch(); | ||
| 804 | + | ||
| 703 | // Compute energy boundaries in TeV | 805 | // Compute energy boundaries in TeV |
| 704 | double emin = m_edisp.axis_lo(m_inx_etrue,0); | 806 | double emin = m_edisp.axis_lo(m_inx_etrue,0); |
| 705 | double emax = m_edisp.axis_hi(m_inx_etrue, | 807 | double emax = m_edisp.axis_hi(m_inx_etrue, |
| @@ -754,6 +856,7 @@ void GCTAEdisp2D::init_members(void) | @@ -754,6 +856,7 @@ void GCTAEdisp2D::init_members(void) | ||
| 754 | // Initialise members | 856 | // Initialise members |
| 755 | m_filename.clear(); | 857 | m_filename.clear(); |
| 756 | m_edisp.clear(); | 858 | m_edisp.clear(); |
| 859 | + m_fetched = false; | ||
| 757 | m_inx_etrue = 0; | 860 | m_inx_etrue = 0; |
| 758 | m_inx_migra = 1; | 861 | m_inx_migra = 1; |
| 759 | m_inx_theta = 2; | 862 | m_inx_theta = 2; |
| @@ -787,6 +890,7 @@ void GCTAEdisp2D::copy_members(const GCTAEdisp2D& edisp) | @@ -787,6 +890,7 @@ void GCTAEdisp2D::copy_members(const GCTAEdisp2D& edisp) | ||
| 787 | // Copy members | 890 | // Copy members |
| 788 | m_filename = edisp.m_filename; | 891 | m_filename = edisp.m_filename; |
| 789 | m_edisp = edisp.m_edisp; | 892 | m_edisp = edisp.m_edisp; |
| 893 | + m_fetched = edisp.m_fetched; | ||
| 790 | m_inx_etrue = edisp.m_inx_etrue; | 894 | m_inx_etrue = edisp.m_inx_etrue; |
| 791 | m_inx_migra = edisp.m_inx_migra; | 895 | m_inx_migra = edisp.m_inx_migra; |
| 792 | m_inx_theta = edisp.m_inx_theta; | 896 | m_inx_theta = edisp.m_inx_theta; |
inst/cta/src/GCTAObservation.cpp
| @@ -1441,7 +1441,7 @@ std::string GCTAObservation::print(const GChatter& chatter) const | @@ -1441,7 +1441,7 @@ std::string GCTAObservation::print(const GChatter& chatter) const | ||
| 1441 | if (m_events != NULL) { | 1441 | if (m_events != NULL) { |
| 1442 | result.append("\n"+m_events->print(reduced_chatter)); | 1442 | result.append("\n"+m_events->print(reduced_chatter)); |
| 1443 | } | 1443 | } |
| 1444 | - | 1444 | + |
| 1445 | } // endif: appended detailed information | 1445 | } // endif: appended detailed information |
| 1446 | 1446 | ||
| 1447 | } // endif: chatter was not silent | 1447 | } // endif: chatter was not silent |
inst/cta/test/dev/test_background_integration.py
0 โ 100755
| 1 | +#! /usr/bin/env python | ||
| 2 | +# ========================================================================== | ||
| 3 | +# This energy integration of GCTABackground3D | ||
| 4 | +# | ||
| 5 | +# Copyright (C) 2017 Juergen Knoedlseder | ||
| 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 | +import os | ||
| 22 | +import math | ||
| 23 | +import gammalib | ||
| 24 | +import matplotlib.pyplot as plt | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +# ========================================= # | ||
| 28 | +# Integrate using Trapezoid rule in log-log # | ||
| 29 | +# ========================================= # | ||
| 30 | +def integrate_trapezoid_loglog(bkg, logE1, logE2): | ||
| 31 | + """ | ||
| 32 | + Integrate using Trapezoid rule in log-log | ||
| 33 | + """ | ||
| 34 | + # Get function values | ||
| 35 | + logf1 = math.log(bkg(logE1, 0.0, 0.0)) | ||
| 36 | + logf2 = math.log(bkg(logE2, 0.0, 0.0)) | ||
| 37 | + | ||
| 38 | + # Compute ln of energy boundaries | ||
| 39 | + lnE1 = logE1 * gammalib.ln10 | ||
| 40 | + lnE2 = logE2 * gammalib.ln10 | ||
| 41 | + | ||
| 42 | + # Compute integral using Trapezoid rule in log-log | ||
| 43 | + integral = (lnE2 - lnE1) * (math.exp(lnE1 + logf1) + | ||
| 44 | + math.exp(lnE2 + logf2)) * 0.5 | ||
| 45 | + | ||
| 46 | + # Return integral | ||
| 47 | + return integral | ||
| 48 | + | ||
| 49 | + | ||
| 50 | +# ========================================= # | ||
| 51 | +# Integrate using Trapezoid rule in lin-lin # | ||
| 52 | +# ========================================= # | ||
| 53 | +def integrate_trapezoid_linlin(bkg, logE1, logE2): | ||
| 54 | + """ | ||
| 55 | + Integrate using Trapezoid rule in lin-lin | ||
| 56 | + """ | ||
| 57 | + # Set number of energy bins | ||
| 58 | + nbins = 1000 | ||
| 59 | + | ||
| 60 | + # Compute log energy bin size | ||
| 61 | + dlogE = (logE2-logE1)/float(nbins-1) | ||
| 62 | + | ||
| 63 | + # Perform integration | ||
| 64 | + integral = 0.0 | ||
| 65 | + for i in range(nbins-1): | ||
| 66 | + logE_low = logE1 + i*dlogE | ||
| 67 | + logE_high = logE_low + dlogE | ||
| 68 | + dE = math.pow(10.0, logE_high) - math.pow(10.0, logE_low) | ||
| 69 | + integral += dE * (bkg(logE_low, 0.0, 0.0) + bkg(logE_high, 0.0, 0.0)) * 0.5 | ||
| 70 | + | ||
| 71 | + # Return integral | ||
| 72 | + return integral | ||
| 73 | + | ||
| 74 | + | ||
| 75 | +# =============== # | ||
| 76 | +# Plot background # | ||
| 77 | +# =============== # | ||
| 78 | +def plot_background(bkg, emin=0.020, emax=120.0): | ||
| 79 | + """ | ||
| 80 | + Plot background | ||
| 81 | + """ | ||
| 82 | + # Generate energy vector | ||
| 83 | + energies = gammalib.GEnergies(100, gammalib.GEnergy(emin,'TeV'), | ||
| 84 | + gammalib.GEnergy(emax,'TeV')) | ||
| 85 | + | ||
| 86 | + # Set energy values | ||
| 87 | + x = [energy.TeV() for energy in energies] | ||
| 88 | + y = [bkg(energy.log10TeV(), 0.0, 0.0) for energy in energies] | ||
| 89 | + | ||
| 90 | + # Get node energies | ||
| 91 | + i_eng = bkg.table().axis('ENERG') | ||
| 92 | + e_nodes = bkg.table().axis_nodes(i_eng) | ||
| 93 | + xo = [math.pow(10.0,logE) for logE in e_nodes] | ||
| 94 | + yo = [bkg(logE, 0.0, 0.0) for logE in e_nodes] | ||
| 95 | + | ||
| 96 | + # Compute integrals | ||
| 97 | + for i in range(len(xo)-1): | ||
| 98 | + if yo[i] > 0 and yo[i+1] > 0: | ||
| 99 | + integral_loglog = integrate_trapezoid_loglog(bkg, e_nodes[i], e_nodes[i+1]) | ||
| 100 | + integral_linlin = integrate_trapezoid_linlin(bkg, e_nodes[i], e_nodes[i+1]) | ||
| 101 | + print('%f-%f: %e %e (%f)' % (xo[i], xo[i+1], integral_loglog, | ||
| 102 | + integral_linlin, | ||
| 103 | + integral_loglog/integral_linlin)) | ||
| 104 | + | ||
| 105 | + # Create figure | ||
| 106 | + plt.figure(1) | ||
| 107 | + plt.title('CTA Background') | ||
| 108 | + | ||
| 109 | + # Plot background | ||
| 110 | + plt.loglog(x, y, 'r-') | ||
| 111 | + plt.loglog(xo, yo, 'ro') | ||
| 112 | + | ||
| 113 | + # Set axes | ||
| 114 | + plt.xlabel("Energy (TeV)") | ||
| 115 | + plt.ylabel("Background (events/s/MeV/sr)") | ||
| 116 | + | ||
| 117 | + # Show plot | ||
| 118 | + plt.show() | ||
| 119 | + | ||
| 120 | + | ||
| 121 | +# ======================== # | ||
| 122 | +# Main routine entry point # | ||
| 123 | +# ======================== # | ||
| 124 | +if __name__ == '__main__': | ||
| 125 | + | ||
| 126 | + # Load background | ||
| 127 | + bkg = gammalib.GCTABackground3D('../../caldb/data/cta/prod2/bcf/South_50h/irf_file.fits') | ||
| 128 | + print(bkg) | ||
| 129 | + | ||
| 130 | + # Plot background | ||
| 131 | + plot_background(bkg) |
src/numerics/GIntegral.cpp
| @@ -385,11 +385,18 @@ double GIntegral::romberg(std::vector<double> bounds, const int& order) | @@ -385,11 +385,18 @@ double GIntegral::romberg(std::vector<double> bounds, const int& order) | ||
| 385 | // Initialise integral | 385 | // Initialise integral |
| 386 | double value = 0.0; | 386 | double value = 0.0; |
| 387 | 387 | ||
| 388 | + // Initialise integration status information | ||
| 389 | + int calls = 0; | ||
| 390 | + | ||
| 388 | // Add integral of all intervals | 391 | // Add integral of all intervals |
| 389 | for (int i = 0; i < bounds.size()-1; ++i) { | 392 | for (int i = 0; i < bounds.size()-1; ++i) { |
| 390 | value += romberg(bounds[i], bounds[i+1], order); | 393 | value += romberg(bounds[i], bounds[i+1], order); |
| 394 | + calls += m_calls; | ||
| 391 | } | 395 | } |
| 392 | 396 | ||
| 397 | + // Set integration status information | ||
| 398 | + m_calls = calls; | ||
| 399 | + | ||
| 393 | // Return value | 400 | // Return value |
| 394 | return value; | 401 | return value; |
| 395 | } | 402 | } |
src/obs/GObservation.cpp
| @@ -352,17 +352,17 @@ double GObservation::model(const GModels& models, | @@ -352,17 +352,17 @@ double GObservation::model(const GModels& models, | ||
| 352 | * | 352 | * |
| 353 | * @returns Total number of observed events. | 353 | * @returns Total number of observed events. |
| 354 | * | 354 | * |
| 355 | - * Returns the total number of observed events. | 355 | + * Returns the total number of observed events. If the observation does not |
| 356 | + * contain any events the method returns zero. | ||
| 356 | ***************************************************************************/ | 357 | ***************************************************************************/ |
| 357 | int GObservation::nobserved(void) const | 358 | int GObservation::nobserved(void) const |
| 358 | { | 359 | { |
| 359 | // Initialise number of observed events | 360 | // Initialise number of observed events |
| 360 | int nobserved = 0; | 361 | int nobserved = 0; |
| 361 | 362 | ||
| 362 | - // Extract number of observed events from event contained | ||
| 363 | - const GEvents* events = this->events(); | ||
| 364 | - if (events != NULL) { | ||
| 365 | - nobserved = events->number(); | 363 | + // Extract number of observed events |
| 364 | + if (m_events != NULL) { | ||
| 365 | + nobserved = m_events->number(); | ||
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | // Return number of observed events | 368 | // Return number of observed events |