diff --git a/ChangeLog b/ChangeLog index d35500e..f46401d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,9 @@ -2016-04-25 Juergen Knoedlseder +2016-05-27 Juergen Knoedlseder * Version 1.1.0 released ======================== + Add cscript unit tests. Add "bgdoversample" and "bgdinfill" parameters to csroot2caldb Add csobsdef.pntdef() method (#1771) Add ctmapcube tool (#1760) diff --git a/NEWS b/NEWS index 6d3dd25..27a2ac4 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ New Features and Important Changes in ctools 1.1.0 -25 April 2016 +27 May 2016 Introduction @@ -208,6 +208,8 @@ sampling than the spatial sampling in the ROOT file. Add csobsdef.pntdef() method to set directly a pointing definition from a gammalib.GCsv object (#1771). +Unit tests have been added for all cscripts. + Examples -------- diff --git a/cscripts/Makefile.am b/cscripts/Makefile.am index 9a07797..68f349b 100644 --- a/cscripts/Makefile.am +++ b/cscripts/Makefile.am @@ -71,14 +71,19 @@ linkscripts = cscaldb \ testscripts = tests/__init__.py \ ../test/test_python_cscripts.py \ ../test/test_cscaldb.py \ - ../test/test_cslightcrv.py \ ../test/test_csmodelinfo.py \ ../test/test_csmodelmerge.py \ ../test/test_csobs2caldb.py \ ../test/test_csobsdef.py \ ../test/test_csobsinfo.py \ + ../test/test_cslightcrv.py \ ../test/test_cspull.py \ + ../test/test_csresmap.py \ ../test/test_csroot2caldb.py \ + ../test/test_cssens.py \ + ../test/test_csspec.py \ + ../test/test_cstsdist.py \ + ../test/test_cstsmapmerge.py \ ../test/test_csworkflow.py \ ../test/test_csfindobs.py \ ../test/test_csiactcopy.py \ @@ -91,12 +96,17 @@ testdata = ../test/data/crab.xml \ ../test/data/obs_stacked.xml \ ../test/data/crab_events.fits.gz \ ../test/data/crab_cntmap.fits.gz \ + ../test/data/crab_cntmap_small.fits.gz \ ../test/data/crab_expcube.fits.gz \ ../test/data/crab_psfcube.fits.gz \ + ../test/data/crab_edispcube.fits.gz \ ../test/data/crab_bkgcube.fits.gz \ + ../test/data/tsmap_0.fits \ + ../test/data/tsmap_1.fits \ ../test/data/exclusion.reg \ ../test/data/pntdef.dat \ ../test/data/models.txt \ + ../test/data/tsmaps.txt \ ../test/data/model_cube_background.xml \ ../test/data/model_cube_background2.xml \ ../test/data/crab_bkgcube.xml \ diff --git a/cscripts/csspec.py b/cscripts/csspec.py index 5e2531d..b44aa93 100755 --- a/cscripts/csspec.py +++ b/cscripts/csspec.py @@ -42,8 +42,8 @@ class csspec(ctools.cscript): Constructor. """ # Set name - self._name = "csspec" - self._version = "1.1.0" + self._name = 'csspec' + self._version = '1.1.0' # Initialise some members self._ebounds = gammalib.GEbounds() @@ -136,56 +136,58 @@ class csspec(ctools.cscript): """ # Get ebounds if self._binned_mode: - + + # Initialise energy boundaries for spectrum + self._ebounds = gammalib.GEbounds() + + # Create energy boundaries according to user parameters + ebounds = self._create_ebounds() + # Extract cube ebounds cube_ebounds = self._obs[0].events().ebounds() - - # Read user parameters - enumbins = self["enumbins"].integer() - emin_val = self["emin"].real() - 1e-6 # Rounding tolerance - emax_val = self["emax"].real() + 1e-6 # Rounding tolerance - - # Set energy range - emin = gammalib.GEnergy(emin_val, "TeV") - emax = gammalib.GEnergy(emax_val, "TeV") - - # Determine all cube layers that overlap with the [emin,emax] - # energy range. - use_layers = [] - for i in range(cube_ebounds.size()): - if cube_ebounds.emin(i) < emax and cube_ebounds.emax(i) > emin: - use_layers.append(i) - - # If no layers overlap then throw an exception - if (len(use_layers) == 0): - msg = "Energy range ["+str(cube_ebounds.emin())+ \ - ", "+str(cube_ebounds.emax())+"] of counts "+ \ - "cube does not overlap with specified energy "+ \ - "range ["+ \ - str(emin)+", "+str(emax)+"]. Specify "+ \ - "overlapping energy range." - raise RuntimeError(msg) - - # Determine number of layers to use for each spectral bin - n_layers = int(len(use_layers) / enumbins) - # Don't allow zero layers - if n_layers == 0: - n_layers = 1 + # Loop over user energy boundaries and collect all layers + # that overlap + for i in range(ebounds.size()): + + # Extract minimum and maximum energy of user energy bin, + # including some rounding tolerance + emin = ebounds.emin(i).TeV() - 1e-6 # Rounding tolerance + emax = ebounds.emax(i).TeV() + 1e-6 # Rounding tolerance + + # Set number of overlapping energy bins + nbins = 0 + + # Search first cube bin that is comprised within user energy bin + for k in range(cube_ebounds.size()): + if cube_ebounds.emin(k).TeV() >= emin and \ + cube_ebounds.emax(k).TeV() <= emax: + emin_value = cube_ebounds.emin(k).TeV() + break + + # Search last cube bin that is comprised within user energy bin + for k in range(cube_ebounds.size()): + if cube_ebounds.emin(k).TeV() >= emin and \ + cube_ebounds.emax(k).TeV() <= emax: + emax_value = cube_ebounds.emax(k).TeV() + nbins += 1 + + # Append energy bin if there are overlapping bins in the + # counts cube + if nbins > 0: + self._ebounds.append(gammalib.GEnergy(emin_value, 'TeV'), + gammalib.GEnergy(emax_value, 'TeV')) + + # Raise an exception if there are no overlapping layers + if (len(self._ebounds) == 0): + msg = 'Energy range ['+str(cube_ebounds.emin())+ \ + ', '+str(cube_ebounds.emax())+'] of counts '+ \ + 'cube does not overlap with specified energy '+ \ + 'range ['+ \ + str(ebounds.emin())+', '+str(ebounds.emax())+'].'+ \ + ' Specify overlapping energy range.' + raise RuntimeError(msg) - # Create energy boundaries - self._ebounds = gammalib.GEbounds() - i_start = 0 - i_stop = n_layers - 1 - while i_start < len(use_layers): - if i_stop >= len(use_layers): - i_stop = len(use_layers) - 1 - ebinmin = cube_ebounds.emin(use_layers[i_start]) - ebinmax = cube_ebounds.emax(use_layers[i_stop]) - self._ebounds.append(ebinmin, ebinmax) - i_start += n_layers - i_stop += n_layers - # Unbinned mode else: self._ebounds = self._create_ebounds() diff --git a/cscripts/cstsmapmerge.py b/cscripts/cstsmapmerge.py index a3bf688..075aaa5 100755 --- a/cscripts/cstsmapmerge.py +++ b/cscripts/cstsmapmerge.py @@ -39,12 +39,12 @@ class cstsmapmerge(ctools.cscript): Constructor. """ # Set name - self._name = "cstsmapmerge" - self._version = "1.1.0" + self._name = 'cstsmapmerge' + self._version = '1.1.0' # Initialise class members self._files = None - self._in_filename = "" + self._in_filename = '' self._tsmap = gammalib.GSkyMap() # Empty sky map self._statusmap = gammalib.GSkyMap() # Empty sky map self._maps = [] @@ -67,49 +67,49 @@ class cstsmapmerge(ctools.cscript): Get parameters from parfile. """ # Get input maps string - inmaps = self["inmaps"].string() + inmaps = self['inmaps'].string() # Handle ascii files - if "@" == inmaps[0]: - self._files = open(inmaps.replace("@","")).read().splitlines() + if '@' == inmaps[0]: + self._files = open(inmaps.replace('@','')).read().splitlines() # Handle wild card strings - elif "*" in inmaps: + elif '*' in inmaps: self._files = glob.glob(inmaps) # Handle space-separated list - elif " " in inmaps: - self._files = inmaps.split(" ") + elif ' ' in inmaps: + self._files = inmaps.split(' ') # Handle semi-colon separated list - elif ";" in inmaps: - self._files = inmaps.split(";") + elif ';' in inmaps: + self._files = inmaps.split(';') # Throw exception if input models cannot be decoded else: - msg = "Parameter \"inmaps\" must contain either an @ASCII "\ - "file, a semi-colon-separated or whitespace-separated "\ - "list of files or a wildcard string." + msg = 'Parameter "inmaps" must contain either an @ASCII '\ + 'file, a semi-colon-separated or whitespace-separated '\ + 'list of files or a wildcard string.' raise RuntimeError(msg) # Check number of files. We need at least two files. if len(self._files) <= 1: - msg = "Need at least two files to start merging, "+\ - str(len(self._files))+" file(s) given." + msg = 'Need at least two files to start merging, '+\ + str(len(self._files))+' file(s) given.' raise RuntimeError(msg) # Get other parameters - self._overwrite = self["overwrite"].boolean() - self._delete = self["delete"].boolean() + self._overwrite = self['overwrite'].boolean() + self._delete = self['delete'].boolean() # Read ahead output filename if self._read_ahead(): - self["outmap"].filename() + self['outmap'].filename() # Write input parameters into logger if self._logTerse(): self._log_parameters() - self._log("\n") + self._log('\n') # Return return diff --git a/test/data/tsmaps.txt b/test/data/tsmaps.txt new file mode 100644 index 0000000..58654b1 --- /dev/null +++ b/test/data/tsmaps.txt @@ -0,0 +1,2 @@ +data/tsmap_0.fits +data/tsmap_1.fits diff --git a/test/test_cscripts.sh.in b/test/test_cscripts.sh.in index f4894f4..eb1f73d 100755 --- a/test/test_cscripts.sh.in +++ b/test/test_cscripts.sh.in @@ -257,9 +257,9 @@ else exit 1 fi # === ascii-file === -ls data/tsmap_*.fits > tsmaps.txt +#ls data/tsmap_*.fits > tsmaps.txt @PYTHON_COVERAGE@@abs_top_srcdir@/cscripts/cstsmapmerge.py \ - inmaps="@tsmaps.txt" \ + inmaps="@data/tsmaps.txt" \ outmap="merged_tsmap4.fits" > cstsmapmerge.log $ECHO -n "." if [ -s "merged_tsmap4.fits" ] diff --git a/test/test_csresmap.py b/test/test_csresmap.py new file mode 100755 index 0000000..0f4466f --- /dev/null +++ b/test/test_csresmap.py @@ -0,0 +1,190 @@ +#! /usr/bin/env python +# ========================================================================== +# This scripts performs unit tests for the csresmap script. +# +# Copyright (C) 2016 Juergen Knoedlseder +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# ========================================================================== +import os +import gammalib +import cscripts + + +# ============================== # +# Test class for csresmap script # +# ============================== # +class Test(gammalib.GPythonTestSuite): + """ + Test class for csresmap script. + + This test class makes unit tests for the csresmap script by using it + from the command line and from Python. + """ + + # Constructor + def __init__(self): + """ + Constructor. + """ + # Call base class constructor + gammalib.GPythonTestSuite.__init__(self) + + # Return + return + + # Set test functions + def set(self): + """ + Set all test functions. + """ + # Set test name + self.name('csresmap') + + # Append tests + self.append(self._test_cmd, 'Test csresmap on command line') + self.append(self._test_python, 'Test csresmap from Python') + + # Return + return + + # Test csresmap on command line + def _test_cmd(self): + """ + Test csresmap on the command line. + """ + # Kluge to set the command (installed version has no README file) + if os.path.isfile('README'): + csresmap = '../cscripts/csresmap.py' + else: + csresmap = 'csresmap' + + # Setup csresmap command + cmd = csresmap+' inobs="data/crab_events.fits"'+ \ + ' outmap="csresmap_cmd1.fits"'+ \ + ' inmodel="data/crab.xml"'+ \ + ' caldb="prod2" irf="South_0.5h"' + \ + ' nxpix=50 nypix=50 binsz=0.02'+ \ + ' coordsys="CEL" proj="CAR" xref=83.63 yref=22.01'+ \ + ' algorithm="SUBDIV"'+ \ + ' logfile="csresmap_cmd1.log" chatter=1' + + # Execute csresmap, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution was successful + self.test_assert(rc == 0, + 'Successful csresmap execution on command line') + + # Check result file + self._check_result_file('csresmap_cmd1.fits') + + # Setup csresmap command + cmd = csresmap+' inobs="event_file_that_does_not_exist.fits"'+ \ + ' outmap="csresmap_cmd1.fits"'+ \ + ' inmodel="data/crab.xml"'+ \ + ' caldb="prod2" irf="South_0.5h"' + \ + ' nxpix=50 nypix=50 binsz=0.02'+ \ + ' coordsys="CEL" proj="CAR" xref=83.63 yref=22.01'+ \ + ' algorithm="SUBDIV"'+ \ + ' logfile="csresmap_cmd2.log" chatter=2' + + # Execute csresmap, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution failed + self.test_assert(rc != 0, + 'Failure of csresmap execution on command line') + + # Return + return + + # Test csresmap from Python + def _test_python(self): + """ + Test csresmap from Python. + """ + # Set-up csresmap for event list + resmap = cscripts.csresmap() + resmap['inobs'] = 'data/crab_events.fits' + resmap['outmap'] = 'csresmap_py1.fits' + resmap['inmodel'] = 'data/crab.xml' + resmap['caldb'] = 'prod2' + resmap['irf'] = 'South_0.5h' + resmap['nxpix'] = 50 + resmap['nypix'] = 50 + resmap['binsz'] = 0.02 + resmap['coordsys'] = 'CEL' + resmap['proj'] = 'CAR' + resmap['xref'] = 83.63 + resmap['yref'] = 22.01 + resmap['algorithm'] = 'SUBDIV' + resmap['logfile'] = 'csresmap_py1.log' + resmap['chatter'] = 2 + + # Run csresmap script + resmap.logFileOpen() # Make sure we get a log file + resmap.run() + resmap.save() + + # Check pull distribution file + self._check_result_file('csresmap_py1.fits') + + # Set-up csresmap for counts cube + resmap = cscripts.csresmap() + resmap['inobs'] = 'data/crab_cntmap.fits' + resmap['modcube'] = 'NONE' + resmap['expcube'] = 'NONE' + resmap['psfcube'] = 'NONE' + resmap['edispcube'] = 'NONE' + resmap['bkgcube'] = 'NONE' + resmap['caldb'] = 'prod2' + resmap['irf'] = 'South_0.5h' + resmap['inmodel'] = 'data/crab.xml' + resmap['outmap'] = 'csresmap_py2.fits' + resmap['algorithm'] = 'SUBDIV' + resmap['logfile'] = 'csresmap_py2.log' + resmap['chatter'] = 3 + + # Run csresmap script + resmap.execute() + + # Check pull distribution file + self._check_result_file('csresmap_py2.fits', nx=200, ny=200) + + # Return + return + + # Check result file + def _check_result_file(self, filename, nx=50, ny=50): + """ + Check result file. + """ + # Load residual map + residual = gammalib.GSkyMap(filename) + + # Check residual map + self.test_value(residual.nmaps(), 1, 'One map') + self.test_value(residual.nx(), nx, '%d pixels in X' % nx) + self.test_value(residual.ny(), ny, '%d pixels in Y' % ny) + + # Return + return diff --git a/test/test_cssens.py b/test/test_cssens.py new file mode 100755 index 0000000..370a33c --- /dev/null +++ b/test/test_cssens.py @@ -0,0 +1,159 @@ +#! /usr/bin/env python +# ========================================================================== +# This scripts performs unit tests for the cssens script. +# +# Copyright (C) 2016 Juergen Knoedlseder +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# ========================================================================== +import os +import gammalib +import cscripts + + +# ============================ # +# Test class for cssens script # +# ============================ # +class Test(gammalib.GPythonTestSuite): + """ + Test class for cssens script. + + This test class makes unit tests for the cssens script by using it + from the command line and from Python. + """ + + # Constructor + def __init__(self): + """ + Constructor. + """ + # Call base class constructor + gammalib.GPythonTestSuite.__init__(self) + + # Return + return + + # Set test functions + def set(self): + """ + Set all test functions. + """ + # Set test name + self.name('cssens') + + # Append tests + self.append(self._test_cmd, 'Test cssens on command line') + self.append(self._test_python, 'Test cssens from Python') + + # Return + return + + # Test cssens on command line + def _test_cmd(self): + """ + Test cssens on the command line. + """ + # Kluge to set the command (installed version has no README file) + if os.path.isfile('README'): + cssens = '../cscripts/cssens.py' + else: + cssens = 'cssens' + + # Setup cssens command + cmd = cssens+' inmodel="data/crab.xml"'+ \ + ' srcname="Crab" caldb="prod2" irf="South_0.5h"' + \ + ' duration=1800.0 rad=3.0 emin=1.0 emax=10.0 bins=1'+ \ + ' outfile="cssens_cmd1.dat"'+ \ + ' logfile="cssens_cmd1.log" chatter=1' + + # Execute cssens, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution was successful + self.test_assert(rc == 0, + 'Successful cssens execution on command line') + + # Check result file + self._check_result_file('cssens_cmd1.dat') + + # Setup cssens command + cmd = cssens+' inmodel="model_that_does_not_exist.xml"'+ \ + ' srcname="Crab" caldb="prod2" irf="South_0.5h"' + \ + ' duration=1800.0 rad=3.0 emin=1.0 emax=10.0 bins=1'+ \ + ' outfile="cssens_cmd2.dat"'+ \ + ' logfile="cssens_cmd2.log" chatter=2' + + # Execute cssens, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution failed + self.test_assert(rc != 0, + 'Failure of cssens execution on command line') + + # Return + return + + # Test cssens from Python + def _test_python(self): + """ + Test cssens from Python. + """ + # Set-up cssens + sens = cscripts.cssens() + sens['inobs'] = 'NONE' + sens['inmodel'] = 'data/crab.xml' + sens['srcname'] = 'Crab' + sens['caldb'] = 'prod2' + sens['irf'] = 'South_0.5h' + sens['outfile'] = 'cssens_py1.dat' + sens['duration'] = 1800.0 + sens['rad'] = 3.0 + sens['emin'] = 1.0 + sens['emax'] = 10.0 + sens['bins'] = 1 + sens['logfile'] = 'cssens_py1.log' + sens['chatter'] = 2 + + # Run cssens script + sens.logFileOpen() # Make sure we get a log file + sens.run() + sens.save() + + # Check pull distribution file + self._check_result_file('cssens_py1.dat') + + # Return + return + + # Check result file + def _check_result_file(self, filename): + """ + Check result file. + """ + # Open result file as CSV file + results = gammalib.GCsv(filename, ',') + + # Check dimensions + self.test_value(results.nrows(), 2, 'Check for 2 rows in sensitivity file') + self.test_value(results.ncols(), 7, 'Check for 7 columns in sensitivity file') + + # Return + return diff --git a/test/test_csspec.py b/test/test_csspec.py new file mode 100755 index 0000000..cc2a300 --- /dev/null +++ b/test/test_csspec.py @@ -0,0 +1,186 @@ +#! /usr/bin/env python +# ========================================================================== +# This scripts performs unit tests for the csspec script. +# +# Copyright (C) 2016 Juergen Knoedlseder +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# ========================================================================== +import os +import gammalib +import cscripts + + +# ============================ # +# Test class for csspec script # +# ============================ # +class Test(gammalib.GPythonTestSuite): + """ + Test class for csspec script. + + This test class makes unit tests for the csspec script by using it + from the command line and from Python. + """ + + # Constructor + def __init__(self): + """ + Constructor. + """ + # Call base class constructor + gammalib.GPythonTestSuite.__init__(self) + + # Return + return + + # Set test functions + def set(self): + """ + Set all test functions. + """ + # Set test name + self.name('csspec') + + # Append tests + self.append(self._test_cmd, 'Test csspec on command line') + self.append(self._test_python, 'Test csspec from Python') + + # Return + return + + # Test csspec on command line + def _test_cmd(self): + """ + Test csspec on the command line. + """ + # Kluge to set the command (installed version has no README file) + if os.path.isfile('README'): + csspec = '../cscripts/csspec.py' + else: + csspec = 'csspec' + + # Setup csspec command + cmd = csspec+' inobs="data/crab_events.fits"'+ \ + ' inmodel="data/crab.xml"'+ \ + ' srcname="Crab" caldb="prod2" irf="South_0.5h"' + \ + ' ebinalg="LOG" enumbins=5 emin=0.1 emax=100.0'+ \ + ' outfile="csspec_cmd1.fits"'+ \ + ' logfile="csspec_cmd1.log" chatter=1' + + # Execute csspec, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution was successful + self.test_assert(rc == 0, + 'Successful csspec execution on command line') + + # Check result file + self._check_result_file('csspec_cmd1.fits', 5) + + # Setup csspec command + cmd = csspec+' inobs="input_file_that_does_not_exist.fits"'+ \ + ' inmodel="data/crab.xml"'+ \ + ' srcname="Crab" caldb="prod2" irf="South_0.5h"' + \ + ' ebinalg="LOG" enumbins=5 emin=0.1 emax=100.0'+ \ + ' outfile="csspec_cmd2.fits"'+ \ + ' logfile="csspec_cmd2.log" chatter=1' + + # Execute csspec, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution failed + self.test_assert(rc != 0, + 'Failure of csspec execution on command line') + + # Return + return + + # Test csspec from Python + def _test_python(self): + """ + Test csspec from Python. + """ + # Set-up unbinned csspec + spec = cscripts.csspec() + spec['inobs'] = 'data/crab_events.fits' + spec['inmodel'] = 'data/crab.xml' + spec['srcname'] = 'Crab' + spec['caldb'] = 'prod2' + spec['irf'] = 'South_0.5h' + spec['outfile'] = 'csspec_py1.fits' + spec['ebinalg'] = 'LOG' + spec['enumbins'] = 5 + spec['emin'] = 0.1 + spec['emax'] = 100.0 + spec['logfile'] = 'csspec_py1.log' + spec['chatter'] = 2 + + # Run csspec script + spec.logFileOpen() # Make sure we get a log file + spec.run() + spec.save() + + # Check pull distribution file + self._check_result_file('csspec_py1.fits', 5) + + # Set-up binned csspec + spec = cscripts.csspec() + spec['inobs'] = 'data/crab_cntmap_small.fits' + spec['expcube'] = 'data/crab_expcube.fits' + spec['psfcube'] = 'data/crab_psfcube.fits' + spec['edispcube'] = 'data/crab_edispcube.fits' + spec['bkgcube'] = 'data/crab_bkgcube.fits' + spec['inmodel'] = 'data/crab.xml' + spec['srcname'] = 'Crab' + spec['outfile'] = 'csspec_py2.fits' + spec['ebinalg'] = 'LOG' + spec['enumbins'] = 2 + spec['emin'] = 0.1 + spec['emax'] = 100.0 + spec['logfile'] = 'csspec_py2.log' + spec['chatter'] = 3 + + # Execute csspec script + spec.execute() + + # Check pull distribution file + self._check_result_file('csspec_py2.fits', 2) + + # Return + return + + # Check result file + def _check_result_file(self, filename, bins): + """ + Check result file. + """ + # Open result file + fits = gammalib.GFits(filename) + + # Get spectrum table + spectrum = fits['SPECTRUM'] + + # Check dimensions + self.test_value(spectrum.nrows(), bins, 'Check for %d rows in spectrum' % bins) + self.test_value(spectrum.ncols(), 8, 'Check for 8 columns in spectrum') + + # Return + return diff --git a/test/test_cstsdist.py b/test/test_cstsdist.py new file mode 100755 index 0000000..9162ba9 --- /dev/null +++ b/test/test_cstsdist.py @@ -0,0 +1,167 @@ +#! /usr/bin/env python +# ========================================================================== +# This scripts performs unit tests for the cstsdist script. +# +# Copyright (C) 2016 Juergen Knoedlseder +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# ========================================================================== +import os +import gammalib +import cscripts + + +# ============================== # +# Test class for cstsdist script # +# ============================== # +class Test(gammalib.GPythonTestSuite): + """ + Test class for cstsdist script. + + This test class makes unit tests for the cstsdist script by using it + from the command line and from Python. + """ + + # Constructor + def __init__(self): + """ + Constructor. + """ + # Call base class constructor + gammalib.GPythonTestSuite.__init__(self) + + # Return + return + + # Set test functions + def set(self): + """ + Set all test functions. + """ + # Set test name + self.name('cstsdist') + + # Append tests + self.append(self._test_cmd, 'Test cstsdist on command line') + self.append(self._test_python, 'Test cstsdist from Python') + + # Return + return + + # Test cstsdist on command line + def _test_cmd(self): + """ + Test cstsdist on the command line. + """ + # Kluge to set the command (installed version has no README file) + if os.path.isfile('README'): + cstsdist = '../cscripts/cstsdist.py' + else: + cstsdist = 'cstsdist' + + # Setup cstsdist command + cmd = cstsdist+' inmodel="data/crab.xml"'+ \ + ' srcname="Crab" caldb="prod2" irf="South_0.5h"' + \ + ' ntrials=1 ra=83.63 dec=22.01 emin=0.1 emax=100.0'+ \ + ' enumbins=0 tmax=1800.0 rad=5.0 npix=200 npix=200'+ \ + ' binsz=0.05'+ \ + ' outfile="cstsdist_cmd1.dat"'+ \ + ' logfile="cstsdist_cmd1.log" chatter=1' + + # Execute cstsdist, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution was successful + self.test_assert(rc == 0, + 'Successful cstsdist execution on command line') + + # Check result file + self._check_result_file('cstsdist_cmd1.dat') + + # Setup cstsdist command + cmd = cstsdist+' inmodel="model_that_does_not_exist.xml"'+ \ + ' srcname="Crab" caldb="prod2" irf="South_0.5h"' + \ + ' ntrials=1 ra=83.63 dec=22.01 emin=0.1 emax=100.0'+ \ + ' enumbins=0 tmax=1800.0 rad=5.0 npix=200 npix=200'+ \ + ' binsz=0.05'+ \ + ' outfile="cstsdist_cmd2.dat"'+ \ + ' logfile="cstsdist_cmd2.log" chatter=2' + + # Execute cstsdist, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution failed + self.test_assert(rc != 0, + 'Failure of cstsdist execution on command line') + + # Return + return + + # Test cstsdist from Python + def _test_python(self): + """ + Test cstsdist from Python. + """ + # Set-up cstsdist + tsdist = cscripts.cstsdist() + tsdist['inmodel'] = 'data/crab.xml' + tsdist['srcname'] = 'Crab' + tsdist['caldb'] = 'prod2' + tsdist['irf'] = 'South_0.5h' + tsdist['outfile'] = 'cstsdist_py1.dat' + tsdist['ntrials'] = 1 + tsdist['ra'] = 83.63 + tsdist['dec'] = 22.01 + tsdist['emin'] = 0.1 + tsdist['emax'] = 100.0 + tsdist['enumbins'] = 0 + tsdist['tmax'] = 1800.0 + tsdist['rad'] = 5.0 + tsdist['npix'] = 200 + tsdist['binsz'] = 0.05 + tsdist['logfile'] = 'cstsdist_py1.log' + tsdist['chatter'] = 2 + + # Run cstsdist script + tsdist.logFileOpen() # Make sure we get a log file + tsdist.run() + tsdist.save() + + # Check pull distribution file + self._check_result_file('cstsdist_py1.dat') + + # Return + return + + # Check result file + def _check_result_file(self, filename): + """ + Check result file. + """ + # Open result file as CSV file + results = gammalib.GCsv(filename, ',') + + # Check dimensions + self.test_value(results.nrows(), 2, 'Check for 2 rows in TS file') + self.test_value(results.ncols(), 14, 'Check for 14 columns in TS file') + + # Return + return diff --git a/test/test_cstsmapmerge.py b/test/test_cstsmapmerge.py new file mode 100755 index 0000000..e05752c --- /dev/null +++ b/test/test_cstsmapmerge.py @@ -0,0 +1,197 @@ +#! /usr/bin/env python +# ========================================================================== +# This scripts performs unit tests for the cstsmapmerge script. +# +# Copyright (C) 2016 Juergen Knoedlseder +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# ========================================================================== +import os +import gammalib +import cscripts + + +# ================================== # +# Test class for cstsmapmerge script # +# ================================== # +class Test(gammalib.GPythonTestSuite): + """ + Test class for cstsmapmerge script. + + This test class makes unit tests for the cstsmapmerge script by using it + from the command line and from Python. + """ + + # Constructor + def __init__(self): + """ + Constructor. + """ + # Call base class constructor + gammalib.GPythonTestSuite.__init__(self) + + # Return + return + + # Set test functions + def set(self): + """ + Set all test functions. + """ + # Set test name + self.name('cstsmapmerge') + + # Append tests + self.append(self._test_cmd, 'Test cstsmapmerge on command line') + self.append(self._test_python, 'Test cstsmapmerge from Python') + + # Return + return + + # Test cstsmapmerge on command line + def _test_cmd(self): + """ + Test cstsmapmerge on the command line. + """ + # Kluge to set the command (installed version has no README file) + if os.path.isfile('README'): + cstsmapmerge = '../cscripts/cstsmapmerge.py' + else: + cstsmapmerge = 'cstsmapmerge' + + # Setup cstsmapmerge command + cmd = cstsmapmerge+' inmaps="data/tsmap_0.fits;data/tsmap_1.fits"'+ \ + ' outmap="cstsmapmerge_cmd1.fits"'+ \ + ' logfile="cstsmapmerge_cmd1.log" chatter=1' + + # Execute cstsmapmerge, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution was successful + self.test_assert(rc == 0, + 'Successful cstsmapmerge execution on command line') + + # Check result file + self._check_result_file('cstsmapmerge_cmd1.fits') + + # Setup cstsmapmerge command + cmd = cstsmapmerge+' inmaps="map_that_does_not_exist.fits"'+ \ + ' outmap="cstsmapmerge_cmd2.fits"'+ \ + ' logfile="cstsmapmerge_cmd2.log" chatter=2' + + # Execute cstsmapmerge, make sure we catch any exception + try: + rc = os.system(cmd+' >/dev/null 2>&1') + except: + pass + + # Check if execution failed + self.test_assert(rc != 0, + 'Failure of cstsmapmerge execution on command line') + + # Return + return + + # Test cstsmapmerge from Python + def _test_python(self): + """ + Test cstsmapmerge from Python. + """ + # Set-up semi-colon separated cstsmapmerge + merge = cscripts.cstsmapmerge() + merge['inmaps'] = 'data/tsmap_0.fits;data/tsmap_1.fits' + merge['outmap'] = 'cstsmapmerge_py1.fits' + merge['logfile'] = 'cstsmapmerge_py1.log' + merge['chatter'] = 2 + + # Run cstsmapmerge script + merge.logFileOpen() # Make sure we get a log file + merge.run() + merge.save() + + # Check pull distribution file + self._check_result_file('cstsmapmerge_py1.fits') + + # Set-up space-separated cstsmapmerge + merge = cscripts.cstsmapmerge() + merge['inmaps'] = 'data/tsmap_0.fits data/tsmap_1.fits' + merge['outmap'] = 'cstsmapmerge_py2.fits' + merge['logfile'] = 'cstsmapmerge_py2.log' + merge['chatter'] = 3 + + # Run cstsmapmerge script + merge.execute() + + # Check pull distribution file + self._check_result_file('cstsmapmerge_py2.fits') + + # Set-up wildcard string cstsmapmerge + merge = cscripts.cstsmapmerge() + merge['inmaps'] = 'data/tsmap_*.fits' + merge['outmap'] = 'cstsmapmerge_py3.fits' + merge['logfile'] = 'cstsmapmerge_py3.log' + merge['chatter'] = 4 + + # Run cstsmapmerge script + merge.execute() + + # Check pull distribution file + self._check_result_file('cstsmapmerge_py3.fits') + + # Set-up ASCII file cstsmapmerge + merge = cscripts.cstsmapmerge() + merge['inmaps'] = '@data/tsmaps.txt' + merge['outmap'] = 'cstsmapmerge_py4.fits' + merge['logfile'] = 'cstsmapmerge_py4.log' + merge['chatter'] = 4 + + # Run cstsmapmerge script + merge.execute() + + # Check pull distribution file + self._check_result_file('cstsmapmerge_py4.fits') + + # Return + return + + # Check result file + def _check_result_file(self, filename): + """ + Check result file. + """ + # Open result file + fits = gammalib.GFits(filename) + + # Get HDUs + ts = fits['Primary'] + prefactor = fits['Prefactor'] + index = fits['Index'] + + # Check dimensions + self.test_value(ts.naxis(), 2, 'Check for 2 dimensions') + self.test_value(ts.naxes(0), 2, 'Check for 2 pixels in X') + self.test_value(ts.naxes(1), 1, 'Check for 1 pixel in Y') + self.test_value(prefactor.naxis(), 2, 'Check for 2 dimensions') + self.test_value(prefactor.naxes(0), 2, 'Check for 2 pixels in X') + self.test_value(prefactor.naxes(1), 1, 'Check for 1 pixel in Y') + self.test_value(index.naxis(), 2, 'Check for 2 dimensions') + self.test_value(index.naxes(0), 2, 'Check for 2 pixels in X') + self.test_value(index.naxes(1), 1, 'Check for 1 pixel in Y') + + # Return + return diff --git a/test/test_python_cscripts.py b/test/test_python_cscripts.py index 871558e..f5817d6 100755 --- a/test/test_python_cscripts.py +++ b/test/test_python_cscripts.py @@ -32,11 +32,16 @@ import test_csobs2caldb import test_csobsdef import test_csobsinfo import test_cspull +import test_csresmap import test_csroot2caldb +import test_cssens +import test_csspec +import test_cstsdist +import test_cstsmapmerge +import test_csworkflow import test_csiactcopy import test_csiactdata import test_csiactobs -import test_csworkflow # ================== # @@ -61,29 +66,29 @@ def test(installed=False, debug=False): dirname = os.path.dirname(testdir) # Copy over test data and irf - os.system("cp -r %s %s" % (dirname+"/data", "data")) - os.system("cp -r %s %s" % (dirname+"/iactdata", "iactdata")) - os.system("cp -r %s %s" % (dirname+"/irf", "irf")) + os.system('cp -r %s %s' % (dirname+'/data', 'data')) + os.system('cp -r %s %s' % (dirname+'/iactdata', 'iactdata')) + os.system('cp -r %s %s' % (dirname+'/irf', 'irf')) # ... otherwise set the calibration database else: - os.environ['CALDB'] = "../caldb" + os.environ['CALDB'] = '../caldb' # Set PFILES environment variable try: - os.mkdir("pfiles") + os.mkdir('pfiles') except: pass - os.environ['PFILES'] = "pfiles" + os.environ['PFILES'] = 'pfiles' # Copy over pfiles if not installed: - os.system("cp -r ../cscripts/*.par pfiles/") + os.system('cp -r ../cscripts/*.par pfiles/') else: - os.system("cp -r %s/syspfiles/*.par pfiles/" % (os.environ['CTOOLS'])) + os.system('cp -r %s/syspfiles/*.par pfiles/' % (os.environ['CTOOLS'])) # Allocate test suite container - suites = gammalib.GTestSuites("cscripts unit testing") + suites = gammalib.GTestSuites('cscripts unit testing') # Allocate test suites suite_cscaldb = test_cscaldb.Test() @@ -94,7 +99,12 @@ def test(installed=False, debug=False): suite_csobsdef = test_csobsdef.Test() suite_csobsinfo = test_csobsinfo.Test() suite_cspull = test_cspull.Test() + suite_csresmap = test_csresmap.Test() suite_csroot2caldb = test_csroot2caldb.Test() + suite_cssens = test_cssens.Test() + suite_csspec = test_csspec.Test() + suite_cstsdist = test_cstsdist.Test() + suite_cstsmapmerge = test_cstsmapmerge.Test() suite_csworkflow = test_csworkflow.Test() # Setup unit tests @@ -106,7 +116,12 @@ def test(installed=False, debug=False): suite_csobsdef.set() suite_csobsinfo.set() suite_cspull.set() + suite_csresmap.set() suite_csroot2caldb.set() + suite_cssens.set() + suite_csspec.set() + suite_cstsdist.set() + suite_cstsmapmerge.set() suite_csworkflow.set() # Append tests to container @@ -118,7 +133,12 @@ def test(installed=False, debug=False): suites.append(suite_csobsdef) suites.append(suite_csobsinfo) suites.append(suite_cspull) + suites.append(suite_csresmap) suites.append(suite_csroot2caldb) + suites.append(suite_cssens) + suites.append(suite_csspec) + suites.append(suite_cstsdist) + suites.append(suite_cstsmapmerge) suites.append(suite_csworkflow) # Append tests for Python 2.6+ (the IACT cscripts depend on the json @@ -149,7 +169,7 @@ def test(installed=False, debug=False): # If we have a non-installed version then save test results if not installed: - suites.save("reports/cscripts.xml") + suites.save('reports/cscripts.xml') # If debuging is requested then print test suites if debug: