Commit cfe3f28204f9d2665a79a22a8d49d182e33392ca

Authored by Jürgen Knödlseder
1 parent 06ae0bbb

Add csebins script (#1976)

ChangeLog
1 -2017-03-21 1 +2017-03-22
2 2
3 * Version 1.3.0 released 3 * Version 1.3.0 released
4 ======================== 4 ========================
5 5
  6 + Add csebins script (#1976)
6 Take into account RoI in ctskymap and use numerical integration for IRF (#1975) 7 Take into account RoI in ctskymap and use numerical integration for IRF (#1975)
7 Set local language to english (#1370) 8 Set local language to english (#1370)
8 Enhance logfile output of csroot2caldb script 9 Enhance logfile output of csroot2caldb script
1 New Features and Important Changes in ctools 1.3.0.dev1 1 New Features and Important Changes in ctools 1.3.0.dev1
2 2
3 -21 March 2017 3 +22 March 2017
4 4
5 5
6 Introduction 6 Introduction
@@ -112,7 +112,10 @@ None @@ -112,7 +112,10 @@ None
112 112
113 cscripts 113 cscripts
114 -------- 114 --------
115 -None 115 +The csebins script has been added that generates an energy boundaries
  116 +extension that can be used for a stacked analysis. The energy boundaries
  117 +are set as function of the variation in the effective area and background
  118 +rates of the Instrument Response Function (#1976).
116 119
117 120
118 Examples 121 Examples
cscripts/Makefile.am
@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 # Scripts to be distributed in $(pyexecdir)/cscripts 22 # Scripts to be distributed in $(pyexecdir)/cscripts
23 pythonscripts = $(top_builddir)/cscripts/__init__.py \ 23 pythonscripts = $(top_builddir)/cscripts/__init__.py \
24 $(srcdir)/cscaldb.py \ 24 $(srcdir)/cscaldb.py \
  25 + $(srcdir)/csebins.py \
25 $(srcdir)/csinfo.py \ 26 $(srcdir)/csinfo.py \
26 $(srcdir)/cslightcrv.py \ 27 $(srcdir)/cslightcrv.py \
27 $(srcdir)/csmodelinfo.py \ 28 $(srcdir)/csmodelinfo.py \
@@ -53,6 +54,7 @@ pythonscripts = $(top_builddir)/cscripts/__init__.py \ @@ -53,6 +54,7 @@ pythonscripts = $(top_builddir)/cscripts/__init__.py \
53 54
54 # Parfiles to be distributed in $(prefix)/syspfiles 55 # Parfiles to be distributed in $(prefix)/syspfiles
55 parfiles = $(srcdir)/cscaldb.par \ 56 parfiles = $(srcdir)/cscaldb.par \
  57 + $(srcdir)/csebins.par \
56 $(srcdir)/cslightcrv.par \ 58 $(srcdir)/cslightcrv.par \
57 $(srcdir)/csmodelinfo.par \ 59 $(srcdir)/csmodelinfo.par \
58 $(srcdir)/csmodelmerge.par \ 60 $(srcdir)/csmodelmerge.par \
@@ -79,6 +81,7 @@ parfiles = $(srcdir)/cscaldb.par \ @@ -79,6 +81,7 @@ parfiles = $(srcdir)/cscaldb.par \
79 81
80 # Scripts for which symbolic links will be created in bindir 82 # Scripts for which symbolic links will be created in bindir
81 linkscripts = cscaldb \ 83 linkscripts = cscaldb \
  84 + csebins \
82 csinfo \ 85 csinfo \
83 cslightcrv \ 86 cslightcrv \
84 csmodelinfo \ 87 csmodelinfo \
cscripts/__init__.py.in
@@ -25,6 +25,7 @@ cur_version = sys.version_info @@ -25,6 +25,7 @@ cur_version = sys.version_info
25 # List all scripts in this module 25 # List all scripts in this module
26 __all__ = [ 26 __all__ = [
27 "cscaldb", 27 "cscaldb",
  28 + "csebins",
28 "csinfo", 29 "csinfo",
29 "cslightcrv", 30 "cslightcrv",
30 "csmodelinfo", 31 "csmodelinfo",
@@ -59,6 +60,7 @@ if cur_version > req_version: @@ -59,6 +60,7 @@ if cur_version > req_version:
59 # Import 60 # Import
60 from cscripts.cscaldb import cscaldb 61 from cscripts.cscaldb import cscaldb
61 from cscripts.csinfo import csinfo 62 from cscripts.csinfo import csinfo
  63 +from cscripts.csebins import csebins
62 from cscripts.cslightcrv import cslightcrv 64 from cscripts.cslightcrv import cslightcrv
63 from cscripts.csmodelinfo import csmodelinfo 65 from cscripts.csmodelinfo import csmodelinfo
64 from cscripts.csmodelmerge import csmodelmerge 66 from cscripts.csmodelmerge import csmodelmerge
cscripts/csebins.par 0 → 100644
  1 +#############################################################################
  2 +# #
  3 +# CTA Science Analysis Tools #
  4 +# #
  5 +# ------------------------------------------------------------------------- #
  6 +# #
  7 +# File: csebins.par #
  8 +# #
  9 +# Author: Juergen Knoedlseder #
  10 +# Jurgen.Knodlseder@irap.omp.eu #
  11 +# IRAP #
  12 +# #
  13 +# Purpose: Parameter file for the csebins script #
  14 +# #
  15 +#############################################################################
  16 +#
  17 +# Input and output parameters
  18 +#============================
  19 +inobs, f, a, NONE,,, "Input observation definition XML file"
  20 +caldb, s, a, prod2,,, "Calibration database"
  21 +irf, s, a, South_0.5h,,, "Instrument response function"
  22 +outfile, f, a, ebounds.fits,,, "Output energy boundaries file"
  23 +
  24 +#
  25 +# Script parameters
  26 +#==================
  27 +emin, r, a, 0.02,,, "Minimum energy (TeV)"
  28 +emax, r, a, 300.0,,, "Maximum energy (TeV)"
  29 +aeffthres, r, h, 0.2,,, "Fractional effective area change threshold"
  30 +bkgthres, r, h, 0.5,,, "Fractional background rate change threshold"
  31 +
  32 +#
  33 +# Standard parameters
  34 +#====================
  35 +chatter, i, h, 2,0,4, "Chattiness of output"
  36 +clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
  37 +debug, b, h, no,,, "Debugging mode activated"
  38 +mode, s, h, ql,,, "Mode of automatic parameters"
  39 +logfile, f, h, csebins.log,,, "Log filename"
cscripts/csebins.py 0 → 100755
  1 +#! /usr/bin/env python
  2 +# ==========================================================================
  3 +# Generates energy boundaries for stacked analysis
  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 sys
  22 +import math
  23 +import gammalib
  24 +import ctools
  25 +#from cscripts import obsutils
  26 +
  27 +
  28 +# ============= #
  29 +# csebins class #
  30 +# ============= #
  31 +class csebins(ctools.cscript):
  32 + """
  33 + Generates energy boundaries for stacked analysis
  34 + """
  35 +
  36 + # Constructor
  37 + def __init__(self, *argv):
  38 + """
  39 + Constructor
  40 + """
  41 + # Set name and version
  42 + self._name = 'csebins'
  43 + self._version = '1.0.0'
  44 +
  45 + # Set members
  46 + self._ebounds = gammalib.GEbounds()
  47 +
  48 + # Initialise observation container from constructor arguments.
  49 + self._obs, argv = self._set_input_obs(argv)
  50 +
  51 + # Initialise script by calling the appropriate class constructor.
  52 + self._init_cscript(argv)
  53 +
  54 + # Return
  55 + return
  56 +
  57 +
  58 + # Private methods
  59 + def _get_parameters(self):
  60 + """
  61 + Get parameters from parfile
  62 + """
  63 + # Initialise observation container if it is currently empty
  64 + if self._obs.size() == 0:
  65 +
  66 + # Query "inobs" parameter
  67 + filename = self['inobs'].filename()
  68 +
  69 + # If an observation definition file was provided then load it,
  70 + # otherwise build a single observation with response information
  71 + if self._is_valid_filename(filename):
  72 + self._obs = gammalib.GObservations(filename)
  73 + else:
  74 + cta = gammalib.GCTAObservation()
  75 + caldb = gammalib.GCaldb('cta', self['caldb'].string())
  76 + rsp = gammalib.GCTAResponseIrf(self['irf'].string(), caldb)
  77 + cta.response(rsp)
  78 + self._obs.append(cta)
  79 +
  80 + # Query input parameters
  81 + self['emin'].real()
  82 + self['emax'].real()
  83 + self['aeffthres'].real()
  84 + self['bkgthres'].real()
  85 +
  86 + # Query ahead output model filename
  87 + if self._read_ahead():
  88 + self['outfile'].filename()
  89 +
  90 + # Write input parameters into logger
  91 + self._log_parameters(gammalib.TERSE)
  92 +
  93 + # Return
  94 + return
  95 +
  96 + def _insert_energy(self, responses, energy, comment):
  97 + """
  98 + Set energy boundaries for one CTA observation
  99 +
  100 + Parameters
  101 + ----------
  102 + responses : list of dict
  103 + List of response dictionaries
  104 + energy : float
  105 + Energy to insert (TeV)
  106 + comment : str
  107 + Reason for energy insertion
  108 + """
  109 + # Set thresholds of all response components
  110 + logE = math.log10(energy)
  111 + for rsp in responses:
  112 + rsp['thres'] = rsp['irf'](logE, 0.0, 0.0)
  113 +
  114 + # Convert energy into gammalib energy
  115 + eng = gammalib.GEnergy(energy, 'TeV')
  116 +
  117 + # Set insertion message
  118 + msg = str(energy)+' TeV'
  119 + if len(comment) > 0:
  120 + msg += ' ('+comment+')'
  121 +
  122 + # If energy boundaries are empty then append an energy interval
  123 + # with zero size ...
  124 + if self._ebounds.size() == 0:
  125 +
  126 + # Append energy interval with zero size
  127 + self._ebounds.append(eng, eng)
  128 +
  129 + # Log first energy boundary
  130 + self._log_value(gammalib.NORMAL, 'First boundary', msg)
  131 +
  132 + # ... otherwise append an interval
  133 + elif self._ebounds.size() > 0:
  134 +
  135 + # If current boundaries have zero size then recover boundary energy,
  136 + # remove boundary, and append a boundary of non-zero size
  137 + if self._ebounds.emin() == self._ebounds.emax():
  138 +
  139 + # Recover old energy, remove boundary and append new boundary
  140 + emin = self._ebounds.emin().copy() # Because emin becomes zero after remove
  141 + emax = eng
  142 + self._ebounds.remove(0)
  143 + self._ebounds.append(emin, emax)
  144 +
  145 + # Log other energy boundary
  146 + self._log_value(gammalib.NORMAL, 'Boundary', msg)
  147 +
  148 + else:
  149 +
  150 + # Use old emax as new emin. Only append if interval is non zero
  151 + emin = self._ebounds.emax()
  152 + if emin < eng:
  153 + self._ebounds.append(emin, eng)
  154 +
  155 + # Log other energy boundary
  156 + self._log_value(gammalib.NORMAL, 'Boundary', msg)
  157 +
  158 + # Return
  159 + return
  160 +
  161 + def _set_ebounds(self, obs):
  162 + """
  163 + Set energy boundaries for one CTA observation
  164 +
  165 + Parameters
  166 + ----------
  167 + obs : `~gammalib.GObservations`
  168 + CTA observation
  169 + """
  170 + # Get parameters
  171 + emin = self['emin'].real()
  172 + emax = self['emax'].real()
  173 + aeffthres = self['aeffthres'].real()
  174 + bkgthres = self['bkgthres'].real()
  175 +
  176 + # Build list of response dictionaries
  177 + responses = []
  178 +
  179 + # Loop over all observations
  180 + for run in obs:
  181 +
  182 + # Get response name
  183 + mission = run.response().caldb().mission()
  184 + instrument = run.response().caldb().instrument()
  185 + rspname = run.response().rspname()
  186 + name = '%s::%s::%s' % (mission, instrument, rspname)
  187 +
  188 + # If response name exists already then examine next observation
  189 + exists = False
  190 + for rsp in responses:
  191 + if rsp['name'] == name:
  192 + exists = True
  193 + break
  194 + if exists:
  195 + continue
  196 +
  197 + # Append effective area and background template to list
  198 + aeff = {'name': name, 'type': 'Aeff',
  199 + 'irf': run.response().aeff(), 'thres': 0.0}
  200 + bkg = {'name': name, 'type': 'Background',
  201 + 'irf': run.response().background(), 'thres': 0.0}
  202 + responses.append(aeff)
  203 + responses.append(bkg)
  204 +
  205 + # Log response name
  206 + self._log_value(gammalib.NORMAL, 'Append response', '%s (%s) [%s]' %
  207 + (rspname, instrument, mission))
  208 +
  209 + # Setup energy vector in log10(TeV)
  210 + logEs = [math.log10(1.0e-3*float(i)) for i in range(int(emin*1000),int(emax*1000))]
  211 +
  212 + # Loop over all energies
  213 + for logE in logEs:
  214 +
  215 + # Loop over all response components
  216 + for rsp in responses:
  217 +
  218 + # Get IRF value
  219 + irf = rsp['irf'](logE, 0.0, 0.0)
  220 +
  221 + # Get threshold
  222 + if rsp['type'] == 'Aeff':
  223 + threshold = aeffthres
  224 + else:
  225 + threshold = bkgthres
  226 +
  227 + # If threshold is zero and response is positive then insert
  228 + # an energy ...
  229 + if rsp['thres'] == 0.0 and irf > 0.0:
  230 + self._insert_energy(responses, math.pow(10.0, logE), rsp['type'])
  231 + break
  232 +
  233 + # ... otherwise if threshold is not zero then check whether
  234 + # the fractional change exceeds the threshold
  235 + elif rsp['thres'] != 0.0:
  236 + f = irf/rsp['thres']
  237 + if 1.0-f > threshold or f-1.0 > threshold:
  238 + self._insert_energy(responses, math.pow(10.0, logE), rsp['type'])
  239 + break
  240 +
  241 + # Insert energy at end of range
  242 + self._insert_energy(responses, emax, 'End of range')
  243 +
  244 + # Log number of energy boundaries
  245 + self._log_value(gammalib.NORMAL, 'Number of boundaries', self._ebounds.size())
  246 +
  247 + # Return
  248 + return
  249 +
  250 +
  251 + # Public methods
  252 + def run(self):
  253 + """
  254 + Run the script
  255 + """
  256 + # Switch screen logging on in debug mode
  257 + if self._logDebug():
  258 + self._log.cout(True)
  259 +
  260 + # Get parameters
  261 + self._get_parameters()
  262 +
  263 + # Write observation into logger
  264 + self._log_observations(gammalib.NORMAL, self._obs, 'Input observation')
  265 +
  266 + # Write header
  267 + self._log_header1(gammalib.TERSE, 'Define energy boundaries')
  268 +
  269 + # Define energy boundaries for observation container
  270 + self._set_ebounds(self._obs)
  271 +
  272 + # Return
  273 + return
  274 +
  275 + def execute(self):
  276 + """
  277 + Execute the script
  278 + """
  279 + # Open logfile
  280 + self.logFileOpen()
  281 +
  282 + # Read ahead output parameters
  283 + self._read_ahead(True)
  284 +
  285 + # Run the scrip
  286 + self.run()
  287 +
  288 + # Save energy boundaries
  289 + self.save()
  290 +
  291 + # Return
  292 + return
  293 +
  294 + def save(self):
  295 + """
  296 + Save energy boundaries
  297 + """
  298 + # Write header
  299 + self._log_header1(gammalib.TERSE, 'Save energy boundaries')
  300 +
  301 + # Get energy boundaries filename
  302 + outfile = self['outfile'].filename()
  303 +
  304 + # Log file name
  305 + self._log_value(gammalib.NORMAL, 'Energy boundaries file', outfile.url())
  306 +
  307 + # Save energy boundaries
  308 + self._ebounds.save(outfile, self._clobber())
  309 +
  310 + # Return
  311 + return
  312 +
  313 + def ebounds(self):
  314 + """
  315 + Return energy boundaries
  316 +
  317 + Returns
  318 + -------
  319 + ebounds : `~gammalib.GEbounds()`
  320 + Energy boundaries
  321 + """
  322 + # Return
  323 + return self._ebounds
  324 +
  325 +
  326 +# ======================== #
  327 +# Main routine entry point #
  328 +# ======================== #
  329 +if __name__ == '__main__':
  330 +
  331 + # Create instance of application
  332 + app = csebins(sys.argv)
  333 +
  334 + # Execute application
  335 + app.execute()
doc/source/users/reference_manual/csebins.rst 0 → 100644
  1 +.. _csebins:
  2 +
  3 +csebins
  4 +=======
  5 +
  6 +Generates energy boundaries for stacked analysis.
  7 +
  8 +
  9 +Synopsis
  10 +--------
  11 +
  12 +This script generates the energy bounaries for a stacked analysis by inspecting
  13 +the variation in the effective area and the background template of the response
  14 +functions. The script takes either an observation definition XML file or a
  15 +specific instrument response function on input.
  16 +
  17 +csebins writes an energy boundary extension into a FITS file.
  18 +
  19 +
  20 +General parameters
  21 +------------------
  22 +
  23 +``inobs [file]``
  24 + Input observation definition XML file.
  25 +
  26 +``caldb [string]``
  27 + Calibration database.
  28 +
  29 +``irf [string]``
  30 + Instrumental response function.
  31 +
  32 +``outfile [file]``
  33 + Name of the energy boundary output file.
  34 +
  35 +``emin [real]``
  36 + Lower energy limit of energy boundaries (in TeV).
  37 +
  38 +``emax [real]``
  39 + Upper energy limit of energy boundaries (in TeV).
  40 +
  41 +``(aeffthres = 0.2) [real]``
  42 + Fractional change in effective area that leads to insertion of a new energy
  43 + boundary.
  44 +
  45 +``(bkgthres = 0.5) [real]``
  46 + Fractional change in background rate that leads to insertion of a new energy
  47 + boundary.
  48 +
  49 +
  50 +Standard parameters
  51 +-------------------
  52 +
  53 +``(chatter = 2) [integer]``
  54 + Verbosity of the executable:
  55 + chatter = 0: no information will be logged
  56 +
  57 + chatter = 1: only errors will be logged
  58 +
  59 + chatter = 2: errors and actions will be logged
  60 +
  61 + chatter = 3: report about the task execution
  62 +
  63 + chatter = 4: detailed report about the task execution
  64 +
  65 +``(clobber = yes) [boolean]``
  66 + Specifies whether an existing energy boundaries output file should be overwritten.
  67 +
  68 +``(debug = no) [boolean]``
  69 + Enables debug mode. In debug mode the executable will dump any log file output to the console.
  70 +
  71 +``(mode = ql) [string]``
  72 + Mode of automatic parameters (default is "ql", i.e. "query and learn").
  73 +
  74 +``(logfile = csebins.log) [filename]``
  75 + Log filename.
  76 +
  77 +
  78 +Related tools or scripts
  79 +------------------------
  80 +
  81 +:doc:`ctbin`
  82 +:doc:`ctexpcube`
  83 +:doc:`ctpsfcube`
  84 +:doc:`ctedispcube`
  85 +:doc:`ctbkgcube`
doc/source/users/reference_manual/cslightcrv.rst
@@ -46,7 +46,7 @@ General parameters @@ -46,7 +46,7 @@ General parameters
46 Applies energy dispersion to response computation. 46 Applies energy dispersion to response computation.
47 47
48 ``outfile [file]`` 48 ``outfile [file]``
49 - Name of the source spectrum output file. 49 + Name of the light curve output file.
50 50
51 ``(tbinalg = GTI) <FILE|LIN|GTI> [string]`` 51 ``(tbinalg = GTI) <FILE|LIN|GTI> [string]``
52 Algorithm for defining time bins. 52 Algorithm for defining time bins.
@@ -125,7 +125,7 @@ Standard parameters @@ -125,7 +125,7 @@ Standard parameters
125 chatter = 4: detailed report about the task execution 125 chatter = 4: detailed report about the task execution
126 126
127 ``(clobber = yes) [boolean]`` 127 ``(clobber = yes) [boolean]``
128 - Specifies whether an existing source spectrum output file should be overwritten. 128 + Specifies whether an existing light curve output file should be overwritten.
129 129
130 ``(debug = no) [boolean]`` 130 ``(debug = no) [boolean]``
131 Enables debug mode. In debug mode the executable will dump any log file output to the console. 131 Enables debug mode. In debug mode the executable will dump any log file output to the console.
doc/source/users/reference_manual/index.rst
@@ -40,6 +40,7 @@ cscripts @@ -40,6 +40,7 @@ cscripts
40 :maxdepth: 1 40 :maxdepth: 1
41 41
42 cscaldb --- Lists available instrument response functions <cscaldb> 42 cscaldb --- Lists available instrument response functions <cscaldb>
  43 + csebins --- Generates energy boundaries for stacked analysis <csebins>
43 cslightcrv --- Computes lightcurve <cslightcrv> 44 cslightcrv --- Computes lightcurve <cslightcrv>
44 csmodelinfo --- Shows model container content <csmodelinfo> 45 csmodelinfo --- Shows model container content <csmodelinfo>
45 csmodelmerge --- Merges several model containers into one file <csmodelmerge> 46 csmodelmerge --- Merges several model containers into one file <csmodelmerge>
test/test_csebins.py 0 → 100755
  1 +#! /usr/bin/env python
  2 +# ==========================================================================
  3 +# This scripts performs unit tests for the cslightcrv script.
  4 +#
  5 +# Copyright (C) 2016-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 gammalib
  22 +import cscripts
  23 +from testing import test
  24 +
  25 +
  26 +# ============================= #
  27 +# Test class for csebins script #
  28 +# ============================= #
  29 +class Test(test):
  30 + """
  31 + Test class for csebins script
  32 +
  33 + This test class makes unit tests for the csebins script by using it from
  34 + 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 + # Return
  46 + return
  47 +
  48 + # Set test functions
  49 + def set(self):
  50 + """
  51 + Set all test functions.
  52 + """
  53 + # Set test name
  54 + self.name('csebins')
  55 +
  56 + # Append tests
  57 + self.append(self._test_cmd, 'Test csebins on command line')
  58 + self.append(self._test_python, 'Test csebins from Python')
  59 +
  60 + # Return
  61 + return
  62 +
  63 + # Test csebins on command line
  64 + def _test_cmd(self):
  65 + """
  66 + Test csebins on the command line.
  67 + """
  68 + # Set script name
  69 + cslightcrv = self._script('csebins')
  70 +
  71 + # Setup cslightcrv command
  72 + cmd = cslightcrv+' inobs="NONE"'+ \
  73 + ' caldb="'+self._caldb+'" irf="'+self._irf+'"'+ \
  74 + ' emin=0.1 emax=100.0'+ \
  75 + ' outfile="csebins_cmd1.fits"'+ \
  76 + ' logfile="csebins_cmd1.log" chatter=1'
  77 +
  78 + # Check if execution of wrong command fails
  79 + self.test_assert(self._execute('command_that_does_not_exist') != 0,
  80 + 'Self test of test script')
  81 +
  82 + # Check if execution was successful
  83 + self.test_assert(self._execute(cmd) == 0,
  84 + 'Check successful execution from command line')
  85 +
  86 + # Check energy boundaries
  87 + self._check_ebounds('csebins_cmd1.fits', 33)
  88 +
  89 + # Setup cslightcrv command
  90 + cmd = cslightcrv+' inobs="NONE"'+ \
  91 + ' caldb="Database_that_does_not_exist" irf="'+self._irf+'"'+ \
  92 + ' emin=0.1 emax=100.0'+ \
  93 + ' outfile="csebins_cmd2.fits"'+ \
  94 + ' logfile="csebins_cmd2.log" chatter=1'
  95 +
  96 + # Check if execution failed
  97 + self.test_assert(self._execute(cmd) != 0,
  98 + 'Check invalid input file when executed from command line')
  99 +
  100 + # Return
  101 + return
  102 +
  103 + # Test csebins from Python
  104 + def _test_python(self):
  105 + """
  106 + Test csebins from Python
  107 + """
  108 + # Set-up csebins
  109 + ebins = cscripts.csebins()
  110 + ebins['inobs'] = 'NONE'
  111 + ebins['caldb'] = self._caldb
  112 + ebins['irf'] = self._irf
  113 + ebins['emin'] = 0.1
  114 + ebins['emax'] = 100.0
  115 + ebins['outfile'] = 'csebins_py1.fits'
  116 + ebins['logfile'] = 'csebins_py1.log'
  117 + ebins['chatter'] = 2
  118 +
  119 + # Run csebins script and energy boundaries
  120 + ebins.logFileOpen() # Make sure we get a log file
  121 + ebins.run()
  122 + ebins.save()
  123 +
  124 + # Check energy boundaries
  125 + self._check_ebounds('csebins_py1.fits', 33)
  126 +
  127 + # Return
  128 + return
  129 +
  130 + # Check energy boundaries result file
  131 + def _check_ebounds(self, filename, bins):
  132 + """
  133 + Check energy boundaries file
  134 + """
  135 + # Load energy boundaries file
  136 + ebounds = gammalib.GEbounds(filename)
  137 +
  138 + # Check number of energy boundaries
  139 + self.test_value(ebounds.size(), bins)
  140 +
  141 + # Return
  142 + 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 Juergen Knoedlseder 5 +# Copyright (C) 2016-2017 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_csebins
28 import test_csfindobs 29 import test_csfindobs
29 import test_csinfo 30 import test_csinfo
30 import test_cslightcrv 31 import test_cslightcrv
@@ -113,6 +114,7 @@ def test(installed=False, debug=False): @@ -113,6 +114,7 @@ def test(installed=False, debug=False):
113 # Define list of test suites 114 # Define list of test suites
114 tests = [test_cscript.Test(), 115 tests = [test_cscript.Test(),
115 test_cscaldb.Test(), 116 test_cscaldb.Test(),
  117 + test_csebins.Test(),
116 test_csinfo.Test(), 118 test_csinfo.Test(),
117 test_cslightcrv.Test(), 119 test_cslightcrv.Test(),
118 test_csmodelinfo.Test(), 120 test_csmodelinfo.Test(),