Commit 7be3bb2723de39c098cc812e6d45498c19a82adf

Authored by Jürgen Knödlseder
1 parent 0c45c848

Add GModelSpectralFunc spectral constructor (#3626)

ChangeLog
1 -2021-04-29 1 +2021-04-30
2 2
3 * Version 2.0.0 released 3 * Version 2.0.0 released
4 ======================== 4 ========================
5 5
6 Add ASCL shield to "About" page (#3630) 6 Add ASCL shield to "About" page (#3630)
7 - Support spectral line fitting (#3386) 7 + Add GModelSpectralFunc spectral constructor (#3626)
8 Add GModelSpectralBins class (#3606) 8 Add GModelSpectralBins class (#3606)
9 Add carbon footprint estimation to GApplication (#3592) 9 Add carbon footprint estimation to GApplication (#3592)
10 Add phase selection to GCOMSelection and GCOMDri (#3564) 10 Add phase selection to GCOMSelection and GCOMDri (#3564)
@@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
34 Add XML value constructors and access methods to GXmlElement class (#3431) 34 Add XML value constructors and access methods to GXmlElement class (#3431)
35 Correct application elapsed CPU time for OpenMP (#3417) 35 Correct application elapsed CPU time for OpenMP (#3417)
36 Implement sparse vector response cache (#3403) 36 Implement sparse vector response cache (#3403)
  37 + Support spectral line fitting (#3386)
37 Implement GMatrixSparse::row() and GMatrixSparse::add_to_row() methods 38 Implement GMatrixSparse::row() and GMatrixSparse::add_to_row() methods
38 Integrate analytical gradients for energy dispersion computation (#3333) 39 Integrate analytical gradients for energy dispersion computation (#3333)
39 Add GFunctions abstract base class (#3328) 40 Add GFunctions abstract base class (#3328)
1 New Features and Important Changes in GammaLib 2.0.0 1 New Features and Important Changes in GammaLib 2.0.0
2 2
3 -29 April 2021 3 +30 April 2021
4 4
5 5
6 1. Introduction 6 1. Introduction
@@ -56,6 +56,7 @@ The following methods have been added: @@ -56,6 +56,7 @@ The following methods have been added:
56 - GModelSpatialPointSource::flux(GSkyRegion&, GEnergy&, GTime&) 56 - GModelSpatialPointSource::flux(GSkyRegion&, GEnergy&, GTime&)
57 - GModelSpatialRadial::is_energy_dependent() 57 - GModelSpatialRadial::is_energy_dependent()
58 - GModelSpatialRadial::is_time_dependent() 58 - GModelSpatialRadial::is_time_dependent()
  59 +- GModelSpectralFunc(GModelSpectral&, GEnergies&)
59 - GModelSpectralFunc::nodes() 60 - GModelSpectralFunc::nodes()
60 - GModelSpectralFunc::is_empty() 61 - GModelSpectralFunc::is_empty()
61 - GModelSpectralFunc::append() 62 - GModelSpectralFunc::append()
@@ -166,6 +167,9 @@ Implemented GMatrixSparse::row() and GMatrixSparse::add_to_row() methods. @@ -166,6 +167,9 @@ Implemented GMatrixSparse::row() and GMatrixSparse::add_to_row() methods.
166 167
167 9. Model module 168 9. Model module
168 --------------- 169 ---------------
  170 +Added GModelSpectralFunc spectral model constructor that enables creating a file
  171 +function from an arbitrary spectral model (#3626).
  172 +
169 Added GModelSpectralBins class that implements statistically independent spectral 173 Added GModelSpectralBins class that implements statistically independent spectral
170 bins as the spectral model component. In addition, added GModelSpectralNodes::error() 174 bins as the spectral model component. In addition, added GModelSpectralNodes::error()
171 method so that intensity errors can be accessed directly (#3606). 175 method so that intensity errors can be accessed directly (#3606).
README.md
1 GammaLib information 1 GammaLib information
2 ==================== 2 ====================
3 -* Version: 2.0.0.dev (29 April 2021) 3 +* Version: 2.0.0.dev (30 April 2021)
4 4
5 [![Build Status](https://cta-jenkins.irap.omp.eu/buildStatus/icon?job=gammalib-integrate-os)](https://cta-jenkins.irap.omp.eu/job/gammalib-integrate-os/) 5 [![Build Status](https://cta-jenkins.irap.omp.eu/buildStatus/icon?job=gammalib-integrate-os)](https://cta-jenkins.irap.omp.eu/job/gammalib-integrate-os/)
6 6
@@ -181,7 +181,8 @@ refer to the section "Known problems" for more information. @@ -181,7 +181,8 @@ refer to the section "Known problems" for more information.
181 181
182 Windows Installation 182 Windows Installation
183 ==================== 183 ====================
184 -There have been no efforts so far to compile GammaLib under Windows. 184 +On Windows GammaLib needs to be installed into a virtual machine running
  185 +a Linux distribution.
185 186
186 187
187 Testing 188 Testing
@@ -202,8 +203,8 @@ or @@ -202,8 +203,8 @@ or
202 ============================================================================ 203 ============================================================================
203 Testsuite summary for gammalib 2.0.0.dev 204 Testsuite summary for gammalib 2.0.0.dev
204 ============================================================================ 205 ============================================================================
205 - # TOTAL: 21  
206 - # PASS: 21 206 + # TOTAL: 22
  207 + # PASS: 22
207 # SKIP: 0 208 # SKIP: 0
208 # XFAIL: 0 209 # XFAIL: 0
209 # FAIL: 0 210 # FAIL: 0
doc/source/admin/release_history/2.0.rst
1 .. _2.0: 1 .. _2.0:
2 2
3 -GammaLib 2.0 release (23 April 2021) 3 +GammaLib 2.0 release (30 April 2021)
4 ==================================== 4 ====================================
5 5
6 Overview 6 Overview
@@ -35,8 +35,8 @@ Improvements @@ -35,8 +35,8 @@ Improvements
35 35
36 * [`3630 <https://cta-redmine.irap.omp.eu/issues/3630>`_] - 36 * [`3630 <https://cta-redmine.irap.omp.eu/issues/3630>`_] -
37 Add ASCL shield to **About** page 37 Add ASCL shield to **About** page
38 -* [`3386 <https://cta-redmine.irap.omp.eu/issues/3386>`_] -  
39 - Support spectral line fitting 38 +* [`3626 <https://cta-redmine.irap.omp.eu/issues/3626>`_] -
  39 + Add ``GModelSpectralFunc`` spectral constructor
40 * [`3592 <https://cta-redmine.irap.omp.eu/issues/3592>`_] - 40 * [`3592 <https://cta-redmine.irap.omp.eu/issues/3592>`_] -
41 Add carbon footprint estimation to ``GApplication`` 41 Add carbon footprint estimation to ``GApplication``
42 * [`3564 <https://cta-redmine.irap.omp.eu/issues/3564>`_] - 42 * [`3564 <https://cta-redmine.irap.omp.eu/issues/3564>`_] -
@@ -58,6 +58,8 @@ Improvements @@ -58,6 +58,8 @@ Improvements
58 Add GModelSpectralFunc methods to build file function in memory 58 Add GModelSpectralFunc methods to build file function in memory
59 * [`3501 <https://cta-redmine.irap.omp.eu/issues/3501>`_] - 59 * [`3501 <https://cta-redmine.irap.omp.eu/issues/3501>`_] -
60 Implement vectorised response computation for COMPTEL 60 Implement vectorised response computation for COMPTEL
  61 +* [`3386 <https://cta-redmine.irap.omp.eu/issues/3386>`_] -
  62 + Support spectral line fitting
61 * [`3333 <https://cta-redmine.irap.omp.eu/issues/3333>`_] - 63 * [`3333 <https://cta-redmine.irap.omp.eu/issues/3333>`_] -
62 Integrate analytical gradients for energy dispersion computation 64 Integrate analytical gradients for energy dispersion computation
63 * [`3324 <https://cta-redmine.irap.omp.eu/issues/3324>`_] - 65 * [`3324 <https://cta-redmine.irap.omp.eu/issues/3324>`_] -
include/GModelSpectralFunc.hpp
@@ -39,6 +39,7 @@ @@ -39,6 +39,7 @@
39 /* __ Forward declarations _______________________________________________ */ 39 /* __ Forward declarations _______________________________________________ */
40 class GRan; 40 class GRan;
41 class GTime; 41 class GTime;
  42 +class GEnergies;
42 class GXmlElement; 43 class GXmlElement;
43 44
44 45
@@ -63,6 +64,7 @@ public: @@ -63,6 +64,7 @@ public:
63 // Constructors and destructors 64 // Constructors and destructors
64 GModelSpectralFunc(void); 65 GModelSpectralFunc(void);
65 GModelSpectralFunc(const GFilename& filename, const double& norm); 66 GModelSpectralFunc(const GFilename& filename, const double& norm);
  67 + GModelSpectralFunc(const GModelSpectral& model, const GEnergies& energies);
66 explicit GModelSpectralFunc(const GXmlElement& xml); 68 explicit GModelSpectralFunc(const GXmlElement& xml);
67 GModelSpectralFunc(const GModelSpectralFunc& model); 69 GModelSpectralFunc(const GModelSpectralFunc& model);
68 virtual ~GModelSpectralFunc(void); 70 virtual ~GModelSpectralFunc(void);
@@ -132,7 +134,7 @@ protected: @@ -132,7 +134,7 @@ protected:
132 mutable std::vector<double> m_epivot; //!< Power-law pivot energies 134 mutable std::vector<double> m_epivot; //!< Power-law pivot energies
133 mutable std::vector<double> m_flux; //!< Photon fluxes 135 mutable std::vector<double> m_flux; //!< Photon fluxes
134 mutable std::vector<double> m_eflux; //!< Energy fluxes 136 mutable std::vector<double> m_eflux; //!< Energy fluxes
135 - 137 +
136 // Cached members for MC 138 // Cached members for MC
137 mutable GEnergy m_mc_emin; //!< Minimum energy 139 mutable GEnergy m_mc_emin; //!< Minimum energy
138 mutable GEnergy m_mc_emax; //!< Maximum energy 140 mutable GEnergy m_mc_emax; //!< Maximum energy
pyext/GModelSpectralFunc.i
@@ -39,6 +39,7 @@ public: @@ -39,6 +39,7 @@ public:
39 // Constructors and destructors 39 // Constructors and destructors
40 GModelSpectralFunc(void); 40 GModelSpectralFunc(void);
41 GModelSpectralFunc(const GFilename& filename, const double& norm); 41 GModelSpectralFunc(const GFilename& filename, const double& norm);
  42 + GModelSpectralFunc(const GModelSpectral& model, const GEnergies& energies);
42 explicit GModelSpectralFunc(const GXmlElement& xml); 43 explicit GModelSpectralFunc(const GXmlElement& xml);
43 GModelSpectralFunc(const GModelSpectralFunc& model); 44 GModelSpectralFunc(const GModelSpectralFunc& model);
44 virtual ~GModelSpectralFunc(void); 45 virtual ~GModelSpectralFunc(void);
src/model/GModelSpectralFunc.cpp
@@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
33 #include "GTools.hpp" 33 #include "GTools.hpp"
34 #include "GCsv.hpp" 34 #include "GCsv.hpp"
35 #include "GRan.hpp" 35 #include "GRan.hpp"
  36 +#include "GEnergies.hpp"
36 #include "GModelSpectralFunc.hpp" 37 #include "GModelSpectralFunc.hpp"
37 #include "GModelSpectralRegistry.hpp" 38 #include "GModelSpectralRegistry.hpp"
38 39
@@ -135,6 +136,35 @@ GModelSpectralFunc::GModelSpectralFunc(const GXmlElement&amp; xml) : @@ -135,6 +136,35 @@ GModelSpectralFunc::GModelSpectralFunc(const GXmlElement&amp; xml) :
135 136
136 137
137 /***********************************************************************//** 138 /***********************************************************************//**
  139 + * @brief Spectral model constructor
  140 + *
  141 + * @param[in] model Spectral model.
  142 + * @param[in] energies File function node energies.
  143 + *
  144 + * Constructs a spectral file function model from any spectral model.
  145 + * The file function normalisation will be set to unity.
  146 + ***************************************************************************/
  147 +GModelSpectralFunc::GModelSpectralFunc(const GModelSpectral& model,
  148 + const GEnergies& energies) :
  149 + GModelSpectral()
  150 +{
  151 + // Initialise members
  152 + init_members();
  153 +
  154 + // Reserve space for file function nodes
  155 + reserve(energies.size());
  156 +
  157 + // Append nodes for all energies
  158 + for (int i = 0; i < energies.size(); ++i) {
  159 + append(energies[i], model.eval(energies[i]));
  160 + }
  161 +
  162 + // Return
  163 + return;
  164 +}
  165 +
  166 +
  167 +/***********************************************************************//**
138 * @brief Copy constructor 168 * @brief Copy constructor
139 * 169 *
140 * @param[in] model File function model. 170 * @param[in] model File function model.
@@ -178,7 +208,7 @@ GModelSpectralFunc::~GModelSpectralFunc(void) @@ -178,7 +208,7 @@ GModelSpectralFunc::~GModelSpectralFunc(void)
178 * @param[in] model File function model. 208 * @param[in] model File function model.
179 * @return File function model. 209 * @return File function model.
180 ***************************************************************************/ 210 ***************************************************************************/
181 -GModelSpectralFunc& GModelSpectralFunc::operator= (const GModelSpectralFunc& model) 211 +GModelSpectralFunc& GModelSpectralFunc::operator=(const GModelSpectralFunc& model)
182 { 212 {
183 // Execute only if object is not identical 213 // Execute only if object is not identical
184 if (this != &model) { 214 if (this != &model) {
@@ -1016,7 +1046,7 @@ void GModelSpectralFunc::save(const GFilename&amp; filename, const bool&amp; clobber) co @@ -1016,7 +1046,7 @@ void GModelSpectralFunc::save(const GFilename&amp; filename, const bool&amp; clobber) co
1016 csv(i,0) = gammalib::str(m_lin_nodes[i]); 1046 csv(i,0) = gammalib::str(m_lin_nodes[i]);
1017 csv(i,1) = gammalib::str(m_lin_values[i]); 1047 csv(i,1) = gammalib::str(m_lin_values[i]);
1018 } 1048 }
1019 - 1049 +
1020 // Save CSV file 1050 // Save CSV file
1021 csv.save(filename, " ", clobber); 1051 csv.save(filename, " ", clobber);
1022 1052
src/model/GModelSpectralNodes.cpp
@@ -100,6 +100,9 @@ GModelSpectralNodes::GModelSpectralNodes(const GModelSpectral&amp; model, @@ -100,6 +100,9 @@ GModelSpectralNodes::GModelSpectralNodes(const GModelSpectral&amp; model,
100 // Initialise members 100 // Initialise members
101 init_members(); 101 init_members();
102 102
  103 + // Reserve space for nodes
  104 + reserve(energies.size());
  105 +
103 // Append nodes for all energies 106 // Append nodes for all energies
104 for (int i = 0; i < energies.size(); ++i) { 107 for (int i = 0; i < energies.size(); ++i) {
105 append(energies[i], model.eval(energies[i])); 108 append(energies[i], model.eval(energies[i]));
test/test_GModel.cpp
@@ -2721,6 +2721,19 @@ void TestGModel::test_filefct(void) @@ -2721,6 +2721,19 @@ void TestGModel::test_filefct(void)
2721 test_value(model2.norm(), 2.0, "Check normalisation of loaded model"); 2721 test_value(model2.norm(), 2.0, "Check normalisation of loaded model");
2722 test_value(model2.filename().url(), m_filefct, "Check filename of loaded model"); 2722 test_value(model2.filename().url(), m_filefct, "Check filename of loaded model");
2723 2723
  2724 + // Test spectral model constructor
  2725 + GModelSpectralPlaw plaw(5.7e-16, -2.48, GEnergy(0.3, "TeV"));
  2726 + GEnergies energies(3, GEnergy(0.1, "TeV"), GEnergy(100.0, "TeV"));
  2727 + GModelSpectralFunc model8(plaw, energies);
  2728 + test_value(model8.size(), 1);
  2729 + test_value(model8.nodes(), 3);
  2730 + test_value(model8.energy(0).TeV(), 0.1);
  2731 + test_value(model8.intensity(0), 8.69231722336369e-15);
  2732 + test_value(model8.energy(1).TeV(), 3.16227766016838);
  2733 + test_value(model8.intensity(1), 1.65628690171949e-18);
  2734 + test_value(model8.energy(2).TeV(), 100.0);
  2735 + test_value(model8.intensity(2), 3.15598962890354e-22);
  2736 +
2724 // Test XML constructor 2737 // Test XML constructor
2725 GXml xml(m_xml_model_point_filefct); 2738 GXml xml(m_xml_model_point_filefct);
2726 GXmlElement* element = xml.element(0)->element(0)->element("spectrum", 0); 2739 GXmlElement* element = xml.element(0)->element(0)->element("spectrum", 0);
@@ -2981,7 +2994,7 @@ void TestGModel::test_temp_const(void) @@ -2981,7 +2994,7 @@ void TestGModel::test_temp_const(void)
2981 // Test value constructor 2994 // Test value constructor
2982 GModelTemporalConst model2(3.0); 2995 GModelTemporalConst model2(3.0);
2983 test_value(model2.norm(), 3.0); 2996 test_value(model2.norm(), 3.0);
2984 - 2997 +
2985 // Test XML constructor 2998 // Test XML constructor
2986 GModelTemporalConst model3; 2999 GModelTemporalConst model3;
2987 3000
@@ -3021,7 +3034,7 @@ void TestGModel::test_temp_lightcurve(void) @@ -3021,7 +3034,7 @@ void TestGModel::test_temp_lightcurve(void)
3021 test_value(model2.filename().url(), m_temp_lightcurve, 3034 test_value(model2.filename().url(), m_temp_lightcurve,
3022 "Check light curve data file name"); 3035 "Check light curve data file name");
3023 test_value(model2.norm(), 2.0); 3036 test_value(model2.norm(), 2.0);
3024 - 3037 +
3025 // Test XML constructor 3038 // Test XML constructor
3026 GXml xml(m_xml_model_point_temp_lightcurve); 3039 GXml xml(m_xml_model_point_temp_lightcurve);
3027 GXmlElement* element = xml.element(0)->element(0)->element("temporal", 0); 3040 GXmlElement* element = xml.element(0)->element(0)->element("temporal", 0);
@@ -3385,7 +3398,7 @@ void TestGModel::test_models(void) @@ -3385,7 +3398,7 @@ void TestGModel::test_models(void)
3385 "Model \"2FGL J0005.7+3815\" found but not expected."); 3398 "Model \"2FGL J0005.7+3815\" found but not expected.");
3386 test_assert(!models.is_empty(), "Model container is empty."); 3399 test_assert(!models.is_empty(), "Model container is empty.");
3387 test_value(models.size(), 1); 3400 test_value(models.size(), 1);
3388 - 3401 +
3389 // Append model with same name 3402 // Append model with same name
3390 test_try("Append model with same name"); 3403 test_try("Append model with same name");
3391 try { 3404 try {
@@ -3398,7 +3411,7 @@ void TestGModel::test_models(void) @@ -3398,7 +3411,7 @@ void TestGModel::test_models(void)
3398 catch (std::exception &e) { 3411 catch (std::exception &e) {
3399 test_try_failure(e); 3412 test_try_failure(e);
3400 } 3413 }
3401 - 3414 +
3402 // Append model with different name 3415 // Append model with different name
3403 model->name("Appended model"); 3416 model->name("Appended model");
3404 models.append(*model); 3417 models.append(*model);
@@ -3460,7 +3473,7 @@ void TestGModel::test_models(void) @@ -3460,7 +3473,7 @@ void TestGModel::test_models(void)
3460 models.load(m_xml_file); 3473 models.load(m_xml_file);
3461 test_assert(!models.is_empty(), "Model container is empty."); 3474 test_assert(!models.is_empty(), "Model container is empty.");
3462 test_value(models.size(), 1); 3475 test_value(models.size(), 1);
3463 - 3476 +
3464 // Append identical container 3477 // Append identical container
3465 test_try("Append identical container"); 3478 test_try("Append identical container");
3466 try { 3479 try {
@@ -3490,7 +3503,7 @@ void TestGModel::test_models(void) @@ -3490,7 +3503,7 @@ void TestGModel::test_models(void)
3490 catch (std::exception &e) { 3503 catch (std::exception &e) {
3491 test_try_failure(e); 3504 test_try_failure(e);
3492 } 3505 }
3493 - 3506 +
3494 3507
3495 // Setup Crab model 3508 // Setup Crab model
3496 GModelSky crab; 3509 GModelSky crab;
@@ -3549,7 +3562,7 @@ void TestGModel::test_model_registry(void) @@ -3549,7 +3562,7 @@ void TestGModel::test_model_registry(void)
3549 test_assert(ptr != NULL, "Model pointer for \"" + 3562 test_assert(ptr != NULL, "Model pointer for \"" +
3550 registry.name(i)+"\" is NULL"); 3563 registry.name(i)+"\" is NULL");
3551 if (ptr != NULL) { 3564 if (ptr != NULL) {
3552 - 3565 +
3553 // Test model type 3566 // Test model type
3554 test_assert(ptr->type() == registry.name(i), 3567 test_assert(ptr->type() == registry.name(i),
3555 "Expected \""+registry.name(i)+"\" instead" 3568 "Expected \""+registry.name(i)+"\" instead"
@@ -4214,7 +4227,7 @@ void TestGModel::test_flux(void) @@ -4214,7 +4227,7 @@ void TestGModel::test_flux(void)
4214 4227
4215 // Test point source outside ROI 4228 // Test point source outside ROI
4216 test_value(ps.flux(circle1), 0.0, 1.e-7, "Check point source not contained in region"); 4229 test_value(ps.flux(circle1), 0.0, 1.e-7, "Check point source not contained in region");
4217 - 4230 +
4218 // Exit test 4231 // Exit test
4219 return; 4232 return;
4220 } 4233 }