Commit cfe3f28204f9d2665a79a22a8d49d182e33392ca
1 parent
06ae0bbb
Add csebins script (#1976)
Showing
11 changed files
with
619 additions
and
6 deletions
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 | ... | ... |
NEWS
| 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(), | ... | ... |