Commit ef17b7fb2eedd3cc76ea8d0531e9c926b46f4f23

Authored by Jürgen Knödlseder
1 parent c0406cf2

Add caldb and irf parameters to csbkgmodel, add min/max limits to "Sigma" model …

…parameter, and add csbkgmodel unit test
cscripts/Makefile.am
@@ -129,6 +129,7 @@ testscripts = $(srcdir)/tests/__init__.py \ @@ -129,6 +129,7 @@ testscripts = $(srcdir)/tests/__init__.py \
129 $(top_srcdir)/test/test_python_cscripts.py \ 129 $(top_srcdir)/test/test_python_cscripts.py \
130 $(top_srcdir)/test/test_cscript.py \ 130 $(top_srcdir)/test/test_cscript.py \
131 $(top_srcdir)/test/test_cscaldb.py \ 131 $(top_srcdir)/test/test_cscaldb.py \
  132 + $(top_srcdir)/test/test_csbkgmodel.py \
132 $(top_srcdir)/test/test_csebins.py \ 133 $(top_srcdir)/test/test_csebins.py \
133 $(top_srcdir)/test/test_csfindobs.py \ 134 $(top_srcdir)/test/test_csfindobs.py \
134 $(top_srcdir)/test/test_csinfo.py \ 135 $(top_srcdir)/test/test_csinfo.py \
cscripts/csbkgmodel.par
@@ -17,6 +17,8 @@ @@ -17,6 +17,8 @@
17 # Input and output parameters 17 # Input and output parameters
18 #============================ 18 #============================
19 inobs, f, a, obs.xml,,, "Input observation definition XML file" 19 inobs, f, a, obs.xml,,, "Input observation definition XML file"
  20 +caldb, s, a, prod2,,, "Calibration database"
  21 +irf, s, a, South_0.5h,,, "Instrument response function"
20 outmodel, f, a, model.xml,,, "Output model definition XML file" 22 outmodel, f, a, model.xml,,, "Output model definition XML file"
21 23
22 # 24 #
cscripts/csbkgmodel.py
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 # ========================================================================== 2 # ==========================================================================
3 # Generates background model 3 # Generates background model
4 # 4 #
5 -# Copyright (C) 2018 Juergen Knoedlseder 5 +# Copyright (C) 2018-2019 Juergen Knoedlseder
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
8 # it under the terms of the GNU General Public License as published by 8 # it under the terms of the GNU General Public License as published by
@@ -53,9 +53,9 @@ class csbkgmodel(ctools.csobservation): @@ -53,9 +53,9 @@ class csbkgmodel(ctools.csobservation):
53 """ 53 """
54 Get parameters from parfile 54 Get parameters from parfile
55 """ 55 """
56 - # Setup observations (do not require response, allow event list and  
57 - # counts cube)  
58 - self._setup_observations(self.obs(), False, True, True) 56 + # Setup observations (require response, allow event list and counts
  57 + # cube)
  58 + self._setup_observations(self.obs(), True, True, True)
59 59
60 # Set instrument name 60 # Set instrument name
61 self._instrument = self._get_instrument() 61 self._instrument = self._get_instrument()
@@ -135,11 +135,15 @@ class csbkgmodel(ctools.csobservation): @@ -135,11 +135,15 @@ class csbkgmodel(ctools.csobservation):
135 if self['gradient'].boolean(): 135 if self['gradient'].boolean():
136 spatial = gammalib.GCTAModelSpatialMultiplicative() 136 spatial = gammalib.GCTAModelSpatialMultiplicative()
137 factor1 = gammalib.GCTAModelRadialGauss(3.0) 137 factor1 = gammalib.GCTAModelRadialGauss(3.0)
  138 + factor1['Sigma'].min(1.5)
  139 + factor1['Sigma'].max(10.0)
138 factor2 = gammalib.GCTAModelSpatialGradient() 140 factor2 = gammalib.GCTAModelSpatialGradient()
139 spatial.append(factor1) 141 spatial.append(factor1)
140 spatial.append(factor2) 142 spatial.append(factor2)
141 else: 143 else:
142 spatial = gammalib.GCTAModelRadialGauss(3.0) 144 spatial = gammalib.GCTAModelRadialGauss(3.0)
  145 + spatial['Sigma'].min(1.5)
  146 + spatial['Sigma'].max(10.0)
143 epivot = gammalib.GEnergy(1.0, 'TeV') 147 epivot = gammalib.GEnergy(1.0, 'TeV')
144 spectral = gammalib.GModelSpectralPlaw(3.0e-4, -1.5, epivot) 148 spectral = gammalib.GModelSpectralPlaw(3.0e-4, -1.5, epivot)
145 spectral['Prefactor'].min(1.0e-8) 149 spectral['Prefactor'].min(1.0e-8)
@@ -303,15 +307,6 @@ class csbkgmodel(ctools.csobservation): @@ -303,15 +307,6 @@ class csbkgmodel(ctools.csobservation):
303 def _generate_runwise_bkg(self): 307 def _generate_runwise_bkg(self):
304 """ 308 """
305 Generate background models 309 Generate background models
306 -  
307 - Parameters  
308 - ----------  
309 - responses : list of dict  
310 - List of response dictionaries  
311 - energy : float  
312 - Energy to insert (TeV)  
313 - comment : str  
314 - Reason for energy insertion  
315 """ 310 """
316 # Loop over observations 311 # Loop over observations
317 for run in self.obs(): 312 for run in self.obs():
doc/source/users/reference_manual/csbkgmodel.rst
@@ -20,6 +20,12 @@ General parameters @@ -20,6 +20,12 @@ General parameters
20 ``inobs [file]`` 20 ``inobs [file]``
21 Event list, counts cube or input observation definition XML file. 21 Event list, counts cube or input observation definition XML file.
22 22
  23 +``caldb [string]``
  24 + Calibration database.
  25 +
  26 +``irf [string]``
  27 + Instrument response function.
  28 +
23 ``outmodel [file]`` 29 ``outmodel [file]``
24 Output model XML file. 30 Output model XML file.
25 31
test/test_csbkgmodel.py 0 → 100755
  1 +#! /usr/bin/env python
  2 +# ==========================================================================
  3 +# This scripts performs unit tests for the csbkgmodel script.
  4 +#
  5 +# Copyright (C) 2019 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 gammalib
  22 +import cscripts
  23 +from testing import test
  24 +
  25 +
  26 +# ================================ #
  27 +# Test class for csbkgmodel script #
  28 +# ================================ #
  29 +class Test(test):
  30 + """
  31 + Test class for csbkgmodel script
  32 +
  33 + This test class makes unit tests for the csbkgmodel script by using it
  34 + from the command line and from Python.
  35 + """
  36 +
  37 + # Constructor
  38 + def __init__(self):
  39 + """
  40 + Constructor
  41 + """
  42 + # Call base class constructor
  43 + test.__init__(self)
  44 +
  45 + # Set test datasets and parameters
  46 + self._myevents1 = self._datadir + '/crab_offaxis1.fits'
  47 + self._myevents2 = self._datadir + '/crab_offaxis2.fits'
  48 +
  49 + # Return
  50 + return
  51 +
  52 + # Set test functions
  53 + def set(self):
  54 + """
  55 + Set all test functions.
  56 + """
  57 + # Set test name
  58 + self.name('csbkgmodel')
  59 +
  60 + # Append tests
  61 + self.append(self._test_cmd, 'Test csbkgmodel on command line')
  62 + self.append(self._test_python, 'Test csbkgmodel from Python')
  63 + self.append(self._test_pickeling, 'Test csbkgmodel pickeling')
  64 +
  65 + # Return
  66 + return
  67 +
  68 + # Test csbkgmodel on command line
  69 + def _test_cmd(self):
  70 + """
  71 + Test csbkgmodel on the command line.
  72 + """
  73 + # Set script name
  74 + csbkgmodel = self._script('csbkgmodel')
  75 +
  76 + # Setup csbkgmodel command
  77 + cmd = csbkgmodel+' inobs="'+self._events+'"'+ \
  78 + ' caldb="'+self._caldb+'" irf="'+self._irf+'"' \
  79 + ' instrument=CTA spatial=GAUSS gradient=yes'+ \
  80 + ' spectral=NODES ebinalg=LOG emin=1.0 emax=100.0'+ \
  81 + ' enumbins=8 runwise=yes rad=2.0'+ \
  82 + ' outmodel="csbkgmodel_cmd1.xml"'+ \
  83 + ' logfile="csbkgmodel_cmd1.log" chatter=4'
  84 +
  85 + # Check if execution was successful
  86 + self.test_assert(self._execute(cmd) == 0,
  87 + 'Check successful execution from command line')
  88 +
  89 + # Check background model
  90 + self._check_bkg_model('csbkgmodel_cmd1.xml')
  91 +
  92 + # Setup csbkgmodel command
  93 + cmd = csbkgmodel+' inobs="events_that_do_not_exist.fits"'+ \
  94 + ' caldb="'+self._caldb+'" irf="'+self._irf+'"' \
  95 + ' instrument=CTA spatial=GAUSS gradient=yes'+ \
  96 + ' spectral=NODES ebinalg=LOG emin=1.0 emax=100.0'+ \
  97 + ' enumbins=8 runwise=yes rad=2.0'+ \
  98 + ' outmodel="csbkgmodel_cmd2.xml"' + \
  99 + ' logfile="csbkgmodel_cmd2.log" chatter=1'
  100 +
  101 + # Check if execution failed
  102 + self.test_assert(self._execute(cmd, success=False) != 0,
  103 + 'Check invalid input file when executed from command line')
  104 +
  105 + # Check csbkgmodel --help
  106 + self._check_help(csbkgmodel)
  107 +
  108 + # Return
  109 + return
  110 +
  111 + # Test csbkgmodel from Python
  112 + def _test_python(self):
  113 + """
  114 + Test csbkgmodel from Python
  115 + """
  116 + # Set-up csbkgmodel
  117 + bkgmodel = cscripts.csbkgmodel()
  118 + bkgmodel['inobs'] = self._events
  119 + bkgmodel['caldb'] = self._caldb
  120 + bkgmodel['irf'] = self._irf
  121 + bkgmodel['instrument'] = 'CTA'
  122 + bkgmodel['spatial'] = 'GAUSS'
  123 + bkgmodel['gradient'] = True
  124 + bkgmodel['spectral'] = 'NODES'
  125 + bkgmodel['ebinalg'] = 'LOG'
  126 + bkgmodel['emin'] = 1.0
  127 + bkgmodel['emax'] = 100.0
  128 + bkgmodel['enumbins'] = 8
  129 + bkgmodel['runwise'] = True
  130 + bkgmodel['rad'] = 2.0
  131 + bkgmodel['chatter'] = 2
  132 + bkgmodel['outmodel'] = 'csbkgmodel_py1.xml'
  133 + bkgmodel['logfile'] = 'csbkgmodel_py1.log'
  134 +
  135 + # Run csbkgmodel script and save background model
  136 + bkgmodel.logFileOpen() # Make sure we get a log file
  137 + bkgmodel.run()
  138 + bkgmodel.save()
  139 +
  140 + # Check background model
  141 + self._check_bkg_model('csbkgmodel_py1.xml')
  142 +
  143 + # Now test without gradient, power law and not runwise
  144 + bkgmodel = cscripts.csbkgmodel()
  145 + bkgmodel['inobs'] = self._events
  146 + bkgmodel['caldb'] = self._caldb
  147 + bkgmodel['irf'] = self._irf
  148 + bkgmodel['instrument'] = 'CTA'
  149 + bkgmodel['spatial'] = 'GAUSS'
  150 + bkgmodel['gradient'] = False
  151 + bkgmodel['spectral'] = 'PLAW'
  152 + bkgmodel['ebinalg'] = 'LOG'
  153 + bkgmodel['emin'] = 1.0
  154 + bkgmodel['emax'] = 100.0
  155 + bkgmodel['enumbins'] = 8
  156 + bkgmodel['runwise'] = False
  157 + bkgmodel['rad'] = 2.0
  158 + bkgmodel['chatter'] = 3
  159 + bkgmodel['outmodel'] = 'csbkgmodel_py2.xml'
  160 + bkgmodel['logfile'] = 'csbkgmodel_py2.log'
  161 +
  162 + # Execute csbkgmodel script
  163 + bkgmodel.logFileOpen() # Make sure we get a log file
  164 + bkgmodel.execute()
  165 +
  166 + # Check background model
  167 + self._check_bkg_model('csbkgmodel_py2.xml')
  168 +
  169 + # Now test AEFF model
  170 + bkgmodel = cscripts.csbkgmodel()
  171 + bkgmodel['inobs'] = self._events
  172 + bkgmodel['caldb'] = self._caldb
  173 + bkgmodel['irf'] = self._irf
  174 + bkgmodel['instrument'] = 'CTA'
  175 + bkgmodel['spatial'] = 'AEFF'
  176 + bkgmodel['gradient'] = False
  177 + bkgmodel['spectral'] = 'PLAW'
  178 + bkgmodel['ebinalg'] = 'LOG'
  179 + bkgmodel['emin'] = 1.0
  180 + bkgmodel['emax'] = 100.0
  181 + bkgmodel['enumbins'] = 8
  182 + bkgmodel['runwise'] = False
  183 + bkgmodel['rad'] = 2.0
  184 + bkgmodel['chatter'] = 4
  185 + bkgmodel['outmodel'] = 'csbkgmodel_py3.xml'
  186 + bkgmodel['logfile'] = 'csbkgmodel_py3.log'
  187 +
  188 + # Execute csbkgmodel script
  189 + bkgmodel.logFileOpen() # Make sure we get a log file
  190 + bkgmodel.execute()
  191 +
  192 + # Check background model
  193 + self._check_bkg_model('csbkgmodel_py3.xml')
  194 +
  195 + # Now test IRF model
  196 + bkgmodel = cscripts.csbkgmodel()
  197 + bkgmodel['inobs'] = self._events
  198 + bkgmodel['caldb'] = self._caldb
  199 + bkgmodel['irf'] = self._irf
  200 + bkgmodel['instrument'] = 'CTA'
  201 + bkgmodel['spatial'] = 'AEFF'
  202 + bkgmodel['gradient'] = False
  203 + bkgmodel['spectral'] = 'PLAW'
  204 + bkgmodel['ebinalg'] = 'LOG'
  205 + bkgmodel['emin'] = 1.0
  206 + bkgmodel['emax'] = 100.0
  207 + bkgmodel['enumbins'] = 8
  208 + bkgmodel['runwise'] = False
  209 + bkgmodel['rad'] = 2.0
  210 + bkgmodel['chatter'] = 4
  211 + bkgmodel['outmodel'] = 'csbkgmodel_py4.xml'
  212 + bkgmodel['logfile'] = 'csbkgmodel_py4.log'
  213 +
  214 + # Execute csbkgmodel script
  215 + bkgmodel.logFileOpen() # Make sure we get a log file
  216 + bkgmodel.execute()
  217 +
  218 + # Check background model
  219 + self._check_bkg_model('csbkgmodel_py4.xml')
  220 +
  221 + # Test with multiple input observations
  222 + obs = gammalib.GObservations()
  223 + for s, events in enumerate([self._myevents1, self._myevents2]):
  224 + run = gammalib.GCTAObservation(events)
  225 + run.id(str(s + 1))
  226 + run.response(self._irf, gammalib.GCaldb('cta', self._caldb))
  227 + obs.append(run)
  228 +
  229 + # Set-up csbkgmodel
  230 + bkgmodel = cscripts.csbkgmodel(obs)
  231 + bkgmodel['instrument'] = 'CTA'
  232 + bkgmodel['spatial'] = 'GAUSS'
  233 + bkgmodel['gradient'] = True
  234 + bkgmodel['spectral'] = 'NODES'
  235 + bkgmodel['ebinalg'] = 'LOG'
  236 + bkgmodel['emin'] = 1.0
  237 + bkgmodel['emax'] = 100.0
  238 + bkgmodel['enumbins'] = 8
  239 + bkgmodel['runwise'] = True
  240 + bkgmodel['rad'] = 2.0
  241 + bkgmodel['chatter'] = 2
  242 + bkgmodel['outmodel'] = 'csbkgmodel_py5.xml'
  243 + bkgmodel['logfile'] = 'csbkgmodel_py5.log'
  244 +
  245 + # Execute csbkgmodel script
  246 + bkgmodel.logFileOpen() # Make sure we get a log file
  247 + bkgmodel.execute()
  248 +
  249 + # Check background model
  250 + self._check_bkg_model('csbkgmodel_py5.xml', nmodels=2)
  251 +
  252 + # Return
  253 + return
  254 +
  255 + # Test csbkgmodel pickeling
  256 + def _test_pickeling(self):
  257 + """
  258 + Test csbkgmodel pickeling
  259 + """
  260 + # Perform pickeling tests of empty class
  261 + self._pickeling(cscripts.csbkgmodel())
  262 +
  263 + # Set-up csbkgmodel
  264 + bkgmodel = cscripts.csbkgmodel()
  265 + bkgmodel['inobs'] = self._events
  266 + bkgmodel['caldb'] = self._caldb
  267 + bkgmodel['irf'] = self._irf
  268 + bkgmodel['instrument'] = 'CTA'
  269 + bkgmodel['spatial'] = 'GAUSS'
  270 + bkgmodel['gradient'] = True
  271 + bkgmodel['spectral'] = 'NODES'
  272 + bkgmodel['ebinalg'] = 'LOG'
  273 + bkgmodel['emin'] = 1.0
  274 + bkgmodel['emax'] = 100.0
  275 + bkgmodel['enumbins'] = 8
  276 + bkgmodel['runwise'] = True
  277 + bkgmodel['rad'] = 2.0
  278 + bkgmodel['chatter'] = 2
  279 + bkgmodel['outmodel'] = 'csbkgmodel_py1_pickle.xml'
  280 + bkgmodel['logfile'] = 'csbkgmodel_py1_pickle.log'
  281 +
  282 + # Perform pickeling tests of filled class
  283 + obj = self._pickeling(bkgmodel)
  284 +
  285 + # Run csbkgmodel script and save background model
  286 + obj.logFileOpen() # Make sure we get a log file
  287 + obj.run()
  288 + obj.save()
  289 +
  290 + # Check background model
  291 + self._check_bkg_model('csbkgmodel_py1_pickle.xml')
  292 +
  293 + # Return
  294 + return
  295 +
  296 + # Check background model
  297 + def _check_bkg_model(self, filename, nmodels=1):
  298 + """
  299 + Check background model
  300 + """
  301 + # Load model
  302 + models = gammalib.GModels(filename)
  303 +
  304 + # Check model size
  305 + self.test_value(models.size(), nmodels,
  306 + 'Check for %d model(s) in XML file' % nmodels)
  307 +
  308 + # Return
  309 + return
test/test_python_cscripts.py
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 # ========================================================================== 2 # ==========================================================================
3 # This scripts performs unit tests for cscripts 3 # This scripts performs unit tests for cscripts
4 # 4 #
5 -# Copyright (C) 2016-2018 Juergen Knoedlseder 5 +# Copyright (C) 2016-2019 Juergen Knoedlseder
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
8 # it under the terms of the GNU General Public License as published by 8 # it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@ import cscripts @@ -25,6 +25,7 @@ import cscripts
25 sys.path.append(os.path.dirname(os.path.abspath(__file__))) 25 sys.path.append(os.path.dirname(os.path.abspath(__file__)))
26 import test_cscript 26 import test_cscript
27 import test_cscaldb 27 import test_cscaldb
  28 +import test_csbkgmodel
28 import test_csebins 29 import test_csebins
29 import test_csfindobs 30 import test_csfindobs
30 import test_csinfo 31 import test_csinfo
@@ -119,6 +120,7 @@ def test(installed=False, debug=False): @@ -119,6 +120,7 @@ def test(installed=False, debug=False):
119 120
120 # Define list of test suites 121 # Define list of test suites
121 tests = [test_cscript.Test(), 122 tests = [test_cscript.Test(),
  123 + test_csbkgmodel.Test(),
122 test_cscaldb.Test(), 124 test_cscaldb.Test(),
123 test_csebins.Test(), 125 test_csebins.Test(),
124 test_csinfo.Test(), 126 test_csinfo.Test(),