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 3 * Version 1.3.0 released
4 4 ========================
5 5  
  6 + Add csebins script (#1976)
6 7 Take into account RoI in ctskymap and use numerical integration for IRF (#1975)
7 8 Set local language to english (#1370)
8 9 Enhance logfile output of csroot2caldb script
... ...
1 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 6 Introduction
... ... @@ -112,7 +112,10 @@ None
112 112  
113 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 121 Examples
... ...
cscripts/Makefile.am
... ... @@ -22,6 +22,7 @@
22 22 # Scripts to be distributed in $(pyexecdir)/cscripts
23 23 pythonscripts = $(top_builddir)/cscripts/__init__.py \
24 24 $(srcdir)/cscaldb.py \
  25 + $(srcdir)/csebins.py \
25 26 $(srcdir)/csinfo.py \
26 27 $(srcdir)/cslightcrv.py \
27 28 $(srcdir)/csmodelinfo.py \
... ... @@ -53,6 +54,7 @@ pythonscripts = $(top_builddir)/cscripts/__init__.py \
53 54  
54 55 # Parfiles to be distributed in $(prefix)/syspfiles
55 56 parfiles = $(srcdir)/cscaldb.par \
  57 + $(srcdir)/csebins.par \
56 58 $(srcdir)/cslightcrv.par \
57 59 $(srcdir)/csmodelinfo.par \
58 60 $(srcdir)/csmodelmerge.par \
... ... @@ -79,6 +81,7 @@ parfiles = $(srcdir)/cscaldb.par \
79 81  
80 82 # Scripts for which symbolic links will be created in bindir
81 83 linkscripts = cscaldb \
  84 + csebins \
82 85 csinfo \
83 86 cslightcrv \
84 87 csmodelinfo \
... ...
cscripts/__init__.py.in
... ... @@ -25,6 +25,7 @@ cur_version = sys.version_info
25 25 # List all scripts in this module
26 26 __all__ = [
27 27 "cscaldb",
  28 + "csebins",
28 29 "csinfo",
29 30 "cslightcrv",
30 31 "csmodelinfo",
... ... @@ -59,6 +60,7 @@ if cur_version > req_version:
59 60 # Import
60 61 from cscripts.cscaldb import cscaldb
61 62 from cscripts.csinfo import csinfo
  63 +from cscripts.csebins import csebins
62 64 from cscripts.cslightcrv import cslightcrv
63 65 from cscripts.csmodelinfo import csmodelinfo
64 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 46 Applies energy dispersion to response computation.
47 47  
48 48 ``outfile [file]``
49   - Name of the source spectrum output file.
  49 + Name of the light curve output file.
50 50  
51 51 ``(tbinalg = GTI) <FILE|LIN|GTI> [string]``
52 52 Algorithm for defining time bins.
... ... @@ -125,7 +125,7 @@ Standard parameters
125 125 chatter = 4: detailed report about the task execution
126 126  
127 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 130 ``(debug = no) [boolean]``
131 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 40 :maxdepth: 1
41 41  
42 42 cscaldb --- Lists available instrument response functions <cscaldb>
  43 + csebins --- Generates energy boundaries for stacked analysis <csebins>
43 44 cslightcrv --- Computes lightcurve <cslightcrv>
44 45 csmodelinfo --- Shows model container content <csmodelinfo>
45 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 2 # ==========================================================================
3 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 7 # This program is free software: you can redistribute it and/or modify
8 8 # it under the terms of the GNU General Public License as published by
... ... @@ -25,6 +25,7 @@ import cscripts
25 25 sys.path.append(os.path.dirname(os.path.abspath(__file__)))
26 26 import test_cscript
27 27 import test_cscaldb
  28 +import test_csebins
28 29 import test_csfindobs
29 30 import test_csinfo
30 31 import test_cslightcrv
... ... @@ -113,6 +114,7 @@ def test(installed=False, debug=False):
113 114 # Define list of test suites
114 115 tests = [test_cscript.Test(),
115 116 test_cscaldb.Test(),
  117 + test_csebins.Test(),
116 118 test_csinfo.Test(),
117 119 test_cslightcrv.Test(),
118 120 test_csmodelinfo.Test(),
... ...