diff --git a/cscripts/Makefile.am b/cscripts/Makefile.am index 1173aae..5a6c64c 100644 --- a/cscripts/Makefile.am +++ b/cscripts/Makefile.am @@ -152,7 +152,8 @@ testdata = $(top_srcdir)/test/data/crab.xml \ $(top_srcdir)/test/data/models_spectral.xml \ $(top_srcdir)/test/data/model_filefunction.txt \ $(top_srcdir)/test/data/model_map.fits.gz \ - $(top_srcdir)/test/data/model_mapcube.fits.gz + $(top_srcdir)/test/data/model_mapcube.fits.gz \ + $(top_srcdir)/test/data/iact_runlist.dat # Test data to be distributed in $(pyexecdir)/cscripts/tests/data/iactdata testiactdata = $(top_srcdir)/test/data/iactdata/hdu-index.fits.gz \ diff --git a/cscripts/csiactobs.py b/cscripts/csiactobs.py index 5e07032..37d9418 100755 --- a/cscripts/csiactobs.py +++ b/cscripts/csiactobs.py @@ -47,9 +47,10 @@ class csiactobs(ctools.cscript): """ # Set name and version self._name = 'csiactobs' - self._version = '1.1.0' + self._version = '1.2.0' # Initialise some members + self._obs = gammalib.GObservations() self._ebounds = gammalib.GEbounds() self._datapath = os.getenv('VHEFITS','') self._inmodels = gammalib.GModels() @@ -59,8 +60,8 @@ class csiactobs(ctools.cscript): self._runlist = [] self._runlistfile = gammalib.GFilename() self._bkgpars = 0 - self._outmodel = gammalib.GFilename() - self._outobs = gammalib.GFilename() + #self._outmodel = gammalib.GFilename() + #self._outobs = gammalib.GFilename() self._master_indx = '' self._use_bkg_scale = False self._ev_hiera = [''] @@ -80,8 +81,7 @@ class csiactobs(ctools.cscript): self._subdir = '' self._debug = False - # Initialise application by calling the appropriate class - # constructor. + # Initialise application by calling the appropriate class constructor self._init_cscript(argv) # Return @@ -91,7 +91,7 @@ class csiactobs(ctools.cscript): # Private methods def _get_parameters(self): """ - Get parameters from parfile and setup the observation. + Get parameters from parfile and setup the observation """ # Set data path if self._datapath == '': @@ -105,7 +105,7 @@ class csiactobs(ctools.cscript): self._datapath = gammalib.expand_env(self._datapath) # Read FITS production - self._prodname = self['prodname'].string() + self._prodname = self['prodname'].string() # Read runlist file if list not already filled if len(self._runlist) == 0: @@ -125,13 +125,12 @@ class csiactobs(ctools.cscript): runfile.close() # Read number of background parameters - self._bkgpars = self['bkgpars'].integer() - - # Output model file - self._outmodel = self['outmodel'].filename() - - # Observation outfile - self._outobs = self['outobs'].filename() + self._bkgpars = self['bkgpars'].integer() + + # Query ahead output parameters + if self._read_ahead(): + self['outmodel'].filename() + self['outobs'].filename() # Master index file name self._master_indx = self['master_indx'].string() @@ -227,30 +226,6 @@ class csiactobs(ctools.cscript): # Return return - def runlist(self, runlist): - """ - Set observation list - - Parameters - ---------- - runlist : list - List of observation IDs - """ - - # Check if convertable to a python list - try: - - # Store a copy of input argument - self._runlist = list(runlist) - - except: - - # raise error if wrong type detected - raise RuntimeError('Argument of csiactobs.runlist() must be of type "list"') - - # Return - return - def _background_spectrum(self, prefactor, index, emin = 0.01, emax = 100.0): """ Create a background spectrum model dependent on user parameters @@ -767,17 +742,64 @@ class csiactobs(ctools.cscript): def save(self): """ - Save model definition XML file + Save observation definition and model definition XML file """ - # Save observation XML file - self._xml.save(self._outobs) + # Write header + if self._logTerse(): + self._log('\n') + self._log.header1('Save XML files') + + # Get filenames + outobs = self['outobs'].filename() + outmodel = self['outmodel'].filename() + + # Log file name + if self._logTerse(): + self._log(gammalib.parformat('Obs. definition XML file')) + self._log(outobs.url()) + self._log('\n') + + # Save observation definition XML file + self._xml.save(outobs.url()) + + # Log file name + if self._logTerse(): + self._log(gammalib.parformat('Model definiton XML file')) + self._log(outmodel.url()) + self._log('\n') # Save model XML file - self._models.save(self._outmodel) + self._models.save(outmodel.url()) # Return return + def runlist(self, runlist): + """ + Set runlist + + Parameters + ---------- + runlist : list + List of observation IDs + + Raises + ------ + RuntimeError + Input runlist is not a Python list + """ + # If the runlist is convertable to a Python list then store the + # runlist in the class + try: + self._runlist = list(runlist) + + # ... otherwise raise an exception + except: + raise RuntimeError('Argument is not a Python list') + + # Return + return + def ebounds(self): """ Return runlist energy boundaries @@ -787,20 +809,20 @@ class csiactobs(ctools.cscript): def obs(self): """ - Returns GObservations object + Return observations container """ - # Initialise observations - obs = gammalib.GObservations() + # Clear observations + self._obs.clear() # Read observations if XML is filled if self._xml.size(): - obs.read(self._xml) + self._obs.read(self._xml) # Assign models - obs.models(self._models) + self._obs.models(self._models) # Return observations - return obs + return self._obs # ======================== # diff --git a/test/data/iact_runlist.dat b/test/data/iact_runlist.dat new file mode 100644 index 0000000..ff95acd --- /dev/null +++ b/test/data/iact_runlist.dat @@ -0,0 +1 @@ +0 diff --git a/test/test_csiactdata.py b/test/test_csiactdata.py index 6ae03ee..0333ef5 100755 --- a/test/test_csiactdata.py +++ b/test/test_csiactdata.py @@ -1,6 +1,6 @@ #! /usr/bin/env python # ========================================================================== -# This scripts performs unit tests for the csiactdata script. +# This scripts performs unit tests for the csiactdata script # # Copyright (C) 2016 Juergen Knoedlseder # diff --git a/test/test_csiactobs.py b/test/test_csiactobs.py index 0c43440..08cf4af 100755 --- a/test/test_csiactobs.py +++ b/test/test_csiactobs.py @@ -1,6 +1,6 @@ #! /usr/bin/env python # ========================================================================== -# This scripts performs unit tests for the csiactobs script. +# This scripts performs unit tests for the csiactobs script # # Copyright (C) 2016 Juergen Knoedlseder # @@ -44,6 +44,7 @@ class Test(test): # Set data members self._datapath = self._datadir + '/iactdata' + self._runlist = self._datadir + '/iact_runlist.dat' # Return return @@ -74,10 +75,10 @@ class Test(test): # Setup csiactobs command cmd = csiactobs+' datapath="'+self._datapath+'"'+ \ ' prodname="unit-test"'+ \ - ' infile="runlist_cmd1.dat"'+ \ + ' infile="'+self._runlist+'"'+ \ ' bkgpars=1'+\ - ' outobs="obs_iactobs_cmd1.xml"'+ \ - ' outmodel="bkg_iactobs_cmd1.xml"'+ \ + ' outobs="csiactobs_obs_cmd1.xml"'+ \ + ' outmodel="csiactobs_bgd_cmd1.xml"'+ \ ' logfile="csiactobs_cmd1.log" chatter=1' # Check if execution of wrong command fails @@ -89,18 +90,18 @@ class Test(test): 'Check successful execution from command line') # Check observation definition XML file - self._check_obsdef('obs_iactobs_cmd1.xml') + self._check_obsdef('csiactobs_obs_cmd1.xml') # Check model definition XML file - self._check_moddef('bkg_iactobs_cmd1.xml') + self._check_moddef('csiactobs_bgd_cmd1.xml') # Setup csiactobs command cmd = csiactobs+' datapath="data_path_that_does_not_exist"'+ \ ' prodname="unit-test"'+ \ - ' infile="runlist_cmd1.dat"'+ \ + ' infile="'+self._runlist+'"'+ \ ' bkgpars=1'+\ - ' outobs="obs_iactobs_cmd2.xml"'+ \ - ' outmodel="bkg_iactobs_cmd2.xml"'+ \ + ' outobs="csiactobs_obs_cmd2.xml"'+ \ + ' outmodel="csiactobs_bgd_cmd2.xml"'+ \ ' logfile="csiactobs_cmd2.log" chatter=1' # Check if execution failed @@ -110,10 +111,10 @@ class Test(test): # Setup csiactobs command cmd = csiactobs+' datapath="'+self._datapath+'"'+ \ ' prodname="unit-test-doesnt-exist"'+ \ - ' infile="runlist_cmd1.dat"'+ \ + ' infile="'+self._runlist+'"'+ \ ' bkgpars=1'+\ - ' outobs="obs_iactobs_cmd3.xml"'+ \ - ' outmodel="bkg_iactobs_cmd3.xml"'+ \ + ' outobs="csiactobs_obs_cmd3.xml"'+ \ + ' outmodel="csiactobs_bgd_cmd3.xml"'+ \ ' logfile="csiactobs_cmd3.log" chatter=1' # Check if execution failed @@ -132,10 +133,10 @@ class Test(test): iactobs = cscripts.csiactobs() iactobs['datapath'] = self._datapath iactobs['prodname'] = 'unit-test' - iactobs['infile'] = 'runlist_py1.dat' + iactobs['infile'] = self._runlist iactobs['bkgpars'] = 1 - iactobs['outobs'] = 'obs_iactobs_py1.xml' - iactobs['outmodel'] = 'bkg_iactobs_py1.xml' + iactobs['outobs'] = 'csiactobs_obs_py1.xml' + iactobs['outmodel'] = 'csiactobs_bgd_py1.xml' iactobs['logfile'] = 'csiactobs_py1.log' iactobs['chatter'] = 2 @@ -145,21 +146,21 @@ class Test(test): iactobs.save() # Check observation definition XML file - self._check_obsdef('obs_iactobs_py1.xml') + self._check_obsdef('csiactobs_obs_py1.xml') # Check model definition XML file - self._check_moddef('bkg_iactobs_py1.xml') + self._check_moddef('csiactobs_bgd_py1.xml') # Create test runlist runlist = ['0'] - # Set-up csiactobs - part 2 (set runlist via function, 2 background pars) + # Set-up csiactobs using a runlist with 2 background parameters iactobs = cscripts.csiactobs() iactobs['datapath'] = self._datapath iactobs['prodname'] = 'unit-test' iactobs['bkgpars'] = 2 - iactobs['outobs'] = 'obs_iactobs_py2.xml' - iactobs['outmodel'] = 'bkg_iactobs_py2.xml' + iactobs['outobs'] = 'csiactobs_obs_py2.xml' + iactobs['outmodel'] = 'csiactobs_bgd_py2.xml' iactobs['logfile'] = 'csiactobs_py2.log' iactobs['chatter'] = 3 iactobs.runlist(runlist) @@ -170,71 +171,63 @@ class Test(test): iactobs.save() # Test return functions - obs = iactobs.obs() - ebounds = iactobs.ebounds() - - self.test_assert(obs.size() == 1, - 'Check output observation container') - self.test_assert(ebounds.size() == 0, - 'Check output energy boundaries container') + self.test_value(iactobs.obs().size(), 1, + 'Check number of observations in container') + self.test_value(iactobs.ebounds().size(), 0, + 'Check number of energy boundaries') # Check observation definition XML file - self._check_obsdef('obs_iactobs_py2.xml') + self._check_obsdef('csiactobs_obs_py2.xml') # Check model definition XML file - self._check_moddef('bkg_iactobs_py2.xml') + self._check_moddef('csiactobs_bgd_py2.xml') - # Set-up csiactobs - part 3 (use a large number of free parameters, aeff background) + # Set-up csiactobs with a large number of free parameters and "aeff" + # background iactobs = cscripts.csiactobs() iactobs['datapath'] = self._datapath iactobs['prodname'] = 'unit-test' - iactobs['infile'] = 'runlist_py1.dat' + iactobs['infile'] = self._runlist iactobs['bkgpars'] = 8 iactobs['bkg_mod_hiera'] = 'aeff' - iactobs['outobs'] = 'obs_iactobs_py3.xml' - iactobs['outmodel'] = 'bkg_iactobs_py3.xml' + iactobs['outobs'] = 'csiactobs_obs_py3.xml' + iactobs['outmodel'] = 'csiactobs_bgd_py3.xml' iactobs['logfile'] = 'csiactobs_py3.log' iactobs['chatter'] = 4 - # Run csiactobs script and save run list - iactobs.logFileOpen() # Make sure we get a log file - iactobs.run() - iactobs.save() + # Execute csiactobs script + iactobs.execute() # Check observation definition XML file - self._check_obsdef('obs_iactobs_py3.xml') + self._check_obsdef('csiactobs_obs_py3.xml') # Check model definition XML file - self._check_moddef('bkg_iactobs_py3.xml') + self._check_moddef('csiactobs_bgd_py3.xml') - # Set-up csiactobs - part 4 (use a Gauss background and inmodel parameter) + # Set-up csiactobs with a "gauss" background and "inmodel" parameter iactobs = cscripts.csiactobs() iactobs['datapath'] = self._datapath - iactobs['inmodel'] = 'results.xml' + iactobs['inmodel'] = self._model iactobs['prodname'] = 'unit-test' - iactobs['infile'] = 'runlist_py1.dat' + iactobs['infile'] = self._runlist iactobs['bkgpars'] = 1 iactobs['bkg_mod_hiera'] = 'gauss' iactobs['outobs'] = 'NONE' iactobs['outmodel'] = 'NONE' iactobs['logfile'] = 'csiactobs_py4.log' - iactobs['chatter'] = 2 + iactobs['chatter'] = 4 # Run csiactobs script iactobs.logFileOpen() # Make sure we get a log file iactobs.run() - # Get observations and models - observations = iactobs.obs() - models = observations.models() - - # Check number of models - self.test_assert(models.size() == 3, - 'Check for three models in container') - # Check number of observations - self.test_assert(observations.size() == 1, - 'Check for one observation in container') + self.test_value(iactobs.obs().size(), 1, + 'Check number of observations in container') + + # Check number of models + self.test_value(iactobs.obs().models().size(), 3, + 'Check number of models in container') # Return return @@ -253,34 +246,26 @@ class Test(test): # Check number of observations self.test_value(obs.size(), 1, 'Check for single observation in XML file') - self.test_assert(obs[0].eventfile().file() == 'events.fits.gz', - 'Check event file name') - self.test_assert(obs[0].eventfile().extname() == 'EVENTS', - 'Check event extension name') - self.test_assert(rsp.aeff().filename().file() == - 'irf_file.fits.gz', - 'Check effective area name') - self.test_assert(rsp.aeff().filename().extname() == - 'EFFECTIVE AREA', - 'Check effective area extension name') - self.test_assert(rsp.psf().filename().file() == - 'irf_file.fits.gz', - 'Check point spread function name') - self.test_assert(rsp.psf().filename().extname() == - 'POINT SPREAD FUNCTION', - 'Check point spread function extension name') - self.test_assert(rsp.edisp().filename().file() == - 'irf_file.fits.gz', - 'Check energy dispersion name') - self.test_assert(rsp.edisp().filename().extname() == - 'ENERGY DISPERSION', - 'Check energy dispersion extension name') - self.test_assert(rsp.background().filename().file() == - 'irf_file.fits.gz', - 'Check background name') - self.test_assert(rsp.background().filename().extname() == - 'BACKGROUND', - 'Check background extension name') + self.test_value(obs[0].eventfile().file(), 'events.fits.gz', + 'Check event file name') + self.test_value(obs[0].eventfile().extname(), 'EVENTS', + 'Check event extension name') + self.test_value(rsp.aeff().filename().file(), 'irf_file.fits.gz', + 'Check effective area file name') + self.test_value(rsp.aeff().filename().extname(), 'EFFECTIVE AREA', + 'Check effective area extension name') + self.test_value(rsp.psf().filename().file(), 'irf_file.fits.gz', + 'Check point spread function file name') + self.test_value(rsp.psf().filename().extname(), 'POINT SPREAD FUNCTION', + 'Check point spread function extension name') + self.test_value(rsp.edisp().filename().file(), 'irf_file.fits.gz', + 'Check energy dispersion file name') + self.test_value(rsp.edisp().filename().extname(), 'ENERGY DISPERSION', + 'Check energy dispersion extension name') + self.test_value(rsp.background().filename().file(), 'irf_file.fits.gz', + 'Check background file name') + self.test_value(rsp.background().filename().extname(), 'BACKGROUND', + 'Check background extension name') # Return return