diff --git a/ChangeLog b/ChangeLog index c38d211..c778e2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,9 @@ -2016-04-17 Juergen Knoedlseder +2016-04-22 Juergen Knoedlseder * Version 1.1.0 released ======================== + Add csobsdef.pntdef() method (#1771) Add ctmapcube tool (#1760) Add "seed" parameter to cspull (#1755) Add ctedispcube tool (#1724) diff --git a/NEWS b/NEWS index 272a371..9765167 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ New Features and Important Changes in ctools 1.1.0 -17 April 2016 +22 April 2016 Introduction @@ -200,6 +200,9 @@ Add csworkflow script that executes an arbitrary analysis workflow (#1508). Transformed cta_root2caldb into csroot2caldb script. +Add csobsdef.pntdef() method to set directly a pointing definition from a +gammalib.GCsv object (#1771). + Examples -------- diff --git a/cscripts/csobsdef.py b/cscripts/csobsdef.py index 4af97cc..f388c8e 100755 --- a/cscripts/csobsdef.py +++ b/cscripts/csobsdef.py @@ -76,18 +76,21 @@ class csobsdef(ctools.cscript): def __init__(self, *argv): """ Constructor. + + Parameters + ---------- + argv : list of str + List of IRAF command line parameter strings of the form + ``parameter=3``. """ # Set name and version - self._name = "csobsdef" - self._version = "1.1.0" + self._name = 'csobsdef' + self._version = '1.1.0' # Initialise class members - self._obs = gammalib.GObservations() - self._inpnt = "" - self._tmin = 0.0 - self._chatter = 2 - self._clobber = True - self._debug = False + self._obs = gammalib.GObservations() + self._pntdef = gammalib.GCsv() + self._tmin = 0.0 # Initialise application by calling the appropriate class # constructor. @@ -102,22 +105,18 @@ class csobsdef(ctools.cscript): """ Get parameters from parfile. """ - # Read parameters - self._inpnt = self["inpnt"].filename() + # Query input filename if necessary + if self._pntdef.size() == 0: + self['inpnt'].filename() # Read ahead parameters if self._read_ahead(): - self["outobs"].filename() - - # Set some fixed parameters - self._chatter = self["chatter"].integer() - self._clobber = self["clobber"].boolean() - self._debug = self["debug"].boolean() + self['outobs'].filename() # Write input parameters into logger if self._logTerse(): self._log_parameters() - self._log("\n") + self._log('\n') # Return return @@ -134,8 +133,8 @@ class csobsdef(ctools.cscript): xml = gammalib.GXmlElement() # Append parameter - parameter = "parameter name=\"Calibration\" database=\""+\ - caldb+"\" response=\""+irf+"\"" + parameter = 'parameter name="Calibration" database="'+caldb+\ + '" response="'+irf+'"' xml.append(gammalib.GXmlElement(parameter)) # Create CTA response @@ -153,6 +152,11 @@ class csobsdef(ctools.cscript): def run(self): """ Run the script. + + Raises + ------ + RuntimeError + Invalid pointing definition file format. """ # Switch screen logging on in debug mode if self._logDebug(): @@ -163,17 +167,18 @@ class csobsdef(ctools.cscript): # Write header into logger if self._logTerse(): - self._log("\n") - self._log.header1("Creating observation definition XML file") + self._log('\n') + self._log.header1('Creating observation definition XML file') - # Load pointing definition file - pntdef = gammalib.GCsv(self._inpnt, ",") - ncols = pntdef.ncols() - npnt = pntdef.nrows()-1 + # Load pointing definition file if it is not already set + if self._pntdef.size() == 0: + self._pntdef = gammalib.GCsv(self['inpnt'].filename(), ',') + ncols = self._pntdef.ncols() + npnt = self._pntdef.nrows()-1 # Throw an exception is there is no header information - if pntdef.nrows() < 1: - raise RuntimeError("No header found in pointing definition file.") + if self._pntdef.nrows() < 1: + raise RuntimeError('No header found in pointing definition file.') # Clear observation container self._obs.clear() @@ -182,7 +187,7 @@ class csobsdef(ctools.cscript): # Extract header from pointing definition file header = [] for col in range(ncols): - header.append(pntdef[0,col]) + header.append(self._pntdef[0,col]) # Loop over all pointings for pnt in range(npnt): @@ -194,60 +199,60 @@ class csobsdef(ctools.cscript): obs = gammalib.GCTAObservation() # Set observation name - if "name" in header: - name = pntdef[row, header.index("name")] + if 'name' in header: + name = self._pntdef[row, header.index('name')] else: - name = "None" + name = 'None' obs.name(name) # Set identifier - if "id" in header: - id_ = pntdef[row, header.index("id")] + if 'id' in header: + id_ = self._pntdef[row, header.index('id')] else: - id_ = "%6.6d" % identifier + id_ = '%6.6d' % identifier identifier += 1 obs.id(id_) # Set pointing - if "ra" in header and "dec" in header: - ra = float(pntdef[row, header.index("ra")]) - dec = float(pntdef[row, header.index("dec")]) + if 'ra' in header and 'dec' in header: + ra = float(self._pntdef[row, header.index('ra')]) + dec = float(self._pntdef[row, header.index('dec')]) pntdir = gammalib.GSkyDir() pntdir.radec_deg(ra,dec) - elif "lon" in header and "lat" in header: - lon = float(pntdef[row, header.index("lon")]) - lat = float(pntdef[row, header.index("lat")]) + elif 'lon' in header and 'lat' in header: + lon = float(self._pntdef[row, header.index('lon')]) + lat = float(self._pntdef[row, header.index('lat')]) pntdir = gammalib.GSkyDir() pntdir.lb_deg(lon,lat) else: - raise RuntimeError("No (ra,dec) or (lon,lat) columns " - "found in pointing definition file.") + raise RuntimeError('No (ra,dec) or (lon,lat) columns ' + 'found in pointing definition file.') obs.pointing(gammalib.GCTAPointing(pntdir)) # Set response function - if "caldb" in header: - caldb = pntdef[row, header.index("caldb")] + if 'caldb' in header: + caldb = self._pntdef[row, header.index('caldb')] else: - caldb = self["caldb"].string() - if "irf" in header: - irf = pntdef[row, header.index("irf")] + caldb = self['caldb'].string() + if 'irf' in header: + irf = self._pntdef[row, header.index('irf')] else: - irf = self["irf"].string() - if caldb != "" and irf != "": + irf = self['irf'].string() + if caldb != '' and irf != '': obs = self._set_response(obs, caldb, irf) # Set deadtime correction factor - if "deadc" in header: - deadc = float(pntdef[row, header.index("deadc")]) + if 'deadc' in header: + deadc = float(self._pntdef[row, header.index('deadc')]) else: - deadc = self["deadc"].real() + deadc = self['deadc'].real() obs.deadc(deadc) # Set Good Time Interval - if "duration" in header: - duration = float(pntdef[row, header.index("duration")]) + if 'duration' in header: + duration = float(self._pntdef[row, header.index('duration')]) else: - duration = self["duration"].real() + duration = self['duration'].real() tmin = self._tmin tmax = self._tmin + duration gti = gammalib.GGti(self._time_reference()) @@ -261,33 +266,33 @@ class csobsdef(ctools.cscript): # Set Energy Boundaries has_emin = False has_emax = False - if "emin" in header: - emin = float(pntdef[row, header.index("emin")]) + if 'emin' in header: + emin = float(self._pntdef[row, header.index('emin')]) has_emin = True else: - if self["emin"].is_valid(): - emin = self["emin"].real() + if self['emin'].is_valid(): + emin = self['emin'].real() has_emin = True - if "emax" in header: - emax = float(pntdef[row, header.index("emax")]) + if 'emax' in header: + emax = float(self._pntdef[row, header.index('emax')]) has_emax = True else: - if self["emax"].is_valid(): - emax = self["emax"].real() + if self['emax'].is_valid(): + emax = self['emax'].real() has_emax = True has_ebounds = has_emin and has_emax if has_ebounds: - ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, "TeV"), - gammalib.GEnergy(emax, "TeV")) + ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, 'TeV'), + gammalib.GEnergy(emax, 'TeV')) # Set ROI has_roi = False - if "rad" in header: - rad = float(pntdef[row, header.index("rad")]) + if 'rad' in header: + rad = float(self._pntdef[row, header.index('rad')]) has_roi = True else: - if self["rad"].is_valid(): - rad = self["rad"].real() + if self['rad'].is_valid(): + rad = self['rad'].real() has_roi = True if has_roi: roi = gammalib.GCTARoi(gammalib.GCTAInstDir(pntdir), rad) @@ -308,11 +313,11 @@ class csobsdef(ctools.cscript): # Write observation into logger if self._logExplicit(): self._log(str(obs)) - self._log("\n") + self._log('\n') elif self._logTerse(): - self._log(gammalib.parformat(obs.instrument()+" observation")) - self._log("Name=\""+obs.name()+"\" ") - self._log("ID=\""+obs.id()+"\"\n") + self._log(gammalib.parformat(obs.instrument()+' observation')) + self._log('Name="'+obs.name()+'" ') + self._log('ID="'+obs.id()+'"\n') # Append observation self._obs.append(obs) @@ -326,20 +331,20 @@ class csobsdef(ctools.cscript): """ # Write header and filename into logger if self._logTerse(): - self._log("\n") - self._log.header1("Save observation definition XML file") + self._log('\n') + self._log.header1('Save observation definition XML file') # Get output filename in case it was not read ahead - outobs = self["outobs"].filename() + outobs = self['outobs'].filename() # Check if observation definition XML file is valid - if outobs.url() != "NONE": + if outobs.url() != 'NONE': # Log filename if self._logTerse(): - self._log(gammalib.parformat("Observation XML file")) + self._log(gammalib.parformat('Observation XML file')) self._log(outobs.url()) - self._log("\n") + self._log('\n') # Save observation definition XML file self._obs.save(outobs) @@ -366,6 +371,21 @@ class csobsdef(ctools.cscript): # Return return + def pntdef(self, csv): + """ + Set pointing definition from a CSV table. + + Parameters + ---------- + csv : `~gammalib.GCsv` + Comma-separated values table + """ + # Set pointing definition + self._pntdef = csv + + # Return + return + # ======================== # # Main routine entry point # diff --git a/cscripts/csroot2caldb.py b/cscripts/csroot2caldb.py index b6ff1cd..4441b5d 100755 --- a/cscripts/csroot2caldb.py +++ b/cscripts/csroot2caldb.py @@ -27,7 +27,7 @@ from datetime import datetime # Optional ROOT import try: - from ROOTx import TFile, TH2F, TH3F + from ROOT import TFile, TH2F, TH3F _has_root = True except: _has_root = False diff --git a/test/test_csobsdef.py b/test/test_csobsdef.py index c199954..2d6f838 100755 --- a/test/test_csobsdef.py +++ b/test/test_csobsdef.py @@ -51,11 +51,11 @@ class Test(gammalib.GPythonTestSuite): Set all test functions. """ # Set test name - self.name("csobsdef") + self.name('csobsdef') # Append tests - self.append(self._test_cmd, "Test csobsdef on command line") - self.append(self._test_python, "Test csobsdef from Python") + self.append(self._test_cmd, 'Test csobsdef on command line') + self.append(self._test_python, 'Test csobsdef from Python') # Return return @@ -66,47 +66,47 @@ class Test(gammalib.GPythonTestSuite): Test csobsdef on the command line. """ # Kluge to set the command (installed version has no README file) - if os.path.isfile("README"): - csobsdef = "../cscripts/csobsdef.py" + if os.path.isfile('README'): + csobsdef = '../cscripts/csobsdef.py' else: - csobsdef = "csobsdef" + csobsdef = 'csobsdef' # Setup csobsdef command cmd = csobsdef+' inpnt="data/pntdef.dat"'+ \ - ' outobs="obsdef_cmd1.xml"'+ \ + ' outobs="csobsdef_cmd1.xml"'+ \ ' caldb="prod2" irf="South_0.5h"'+ \ ' emin=0.1 emax=100.0 duration=1800.0 rad=5.0'+ \ ' logfile="csobsdef_cmd1.log" chatter=1' # Execute csobsdef, make sure we catch any exception try: - rc = os.system(cmd+" >/dev/null 2>&1") + rc = os.system(cmd+' >/dev/null 2>&1') except: pass # Check if execution was successful self.test_assert(rc == 0, - "Successful csobsdef execution on command line") + 'Successful csobsdef execution on command line') # Check observation definition file - self._check_obsdef_file("obsdef_cmd1.xml") + self._check_obsdef_file('csobsdef_cmd1.xml') # Setup csobsdef command cmd = csobsdef+' inpnt="obs_definition_that_does_not_exist.dat"'+ \ - ' outobs="obsdef_cmd1.xml"'+ \ + ' outobs="csobsdef_cmd1.xml"'+ \ ' caldb="prod2" irf="South_0.5h"'+ \ ' emin=0.1 emax=100.0 duration=1800.0 rad=5.0'+ \ ' logfile="csobsdef_cmd2.log"' # Execute csobsdef, make sure we catch any exception try: - rc = os.system(cmd+" >/dev/null 2>&1") + rc = os.system(cmd+' >/dev/null 2>&1') except: pass # Check if execution failed self.test_assert(rc != 0, - "Failure of csobsdef execution on command line") + 'Failure of csobsdef execution on command line') # Return return @@ -118,16 +118,16 @@ class Test(gammalib.GPythonTestSuite): """ # Set-up csobsdef obsdef = cscripts.csobsdef() - obsdef["inpnt"] = "data/pntdef.dat" - obsdef["outobs"] = "obsdef_py1.xml" - obsdef["caldb"] = "prod2" - obsdef["irf"] = "South_0.5h" - obsdef["emin"] = 0.1 - obsdef["emax"] = 100.0 - obsdef["duration"] = 1800.0 - obsdef["rad"] = 5.0 - obsdef["logfile"] = "csobsdef_py1.log" - obsdef["chatter"] = 2 + obsdef['inpnt'] = 'data/pntdef.dat' + obsdef['outobs'] = 'csobsdef_py1.xml' + obsdef['caldb'] = 'prod2' + obsdef['irf'] = 'South_0.5h' + obsdef['emin'] = 0.1 + obsdef['emax'] = 100.0 + obsdef['duration'] = 1800.0 + obsdef['rad'] = 5.0 + obsdef['logfile'] = 'csobsdef_py1.log' + obsdef['chatter'] = 2 # Run csobsdef script and save XML file obsdef.logFileOpen() # Make sure we get a log file @@ -135,26 +135,48 @@ class Test(gammalib.GPythonTestSuite): obsdef.save() # Check model file - self._check_obsdef_file("obsdef_py1.xml") + self._check_obsdef_file('csobsdef_py1.xml') # Set-up csobsdef obsdef = cscripts.csobsdef() - obsdef["inpnt"] = "data/pntdef.dat" - obsdef["outobs"] = "obsdef_py2.xml" - obsdef["caldb"] = "prod2" - obsdef["irf"] = "South_0.5h" - obsdef["emin"] = 0.1 - obsdef["emax"] = 100.0 - obsdef["duration"] = 1800.0 - obsdef["rad"] = 5.0 - obsdef["logfile"] = "csobsdef_py2.log" - obsdef["chatter"] = 3 + obsdef['inpnt'] = 'data/pntdef.dat' + obsdef['outobs'] = 'csobsdef_py2.xml' + obsdef['caldb'] = 'prod2' + obsdef['irf'] = 'South_0.5h' + obsdef['emin'] = 0.1 + obsdef['emax'] = 100.0 + obsdef['duration'] = 1800.0 + obsdef['rad'] = 5.0 + obsdef['logfile'] = 'csobsdef_py2.log' + obsdef['chatter'] = 3 # Execute csobsdef script obsdef.execute() # Check model file - self._check_obsdef_file("obsdef_py2.xml") + self._check_obsdef_file('csobsdef_py2.xml') + + # Load CSV table + csv = gammalib.GCsv('data/pntdef.dat', ',') + + # Set-up csobsdef + obsdef = cscripts.csobsdef() + obsdef.pntdef(csv) + obsdef['outobs'] = 'csobsdef_py3.xml' + obsdef['caldb'] = 'prod2' + obsdef['irf'] = 'South_0.5h' + obsdef['emin'] = 0.1 + obsdef['emax'] = 100.0 + obsdef['duration'] = 1800.0 + obsdef['rad'] = 5.0 + obsdef['logfile'] = 'csobsdef_py3.log' + obsdef['chatter'] = 4 + + # Execute csobsdef script + obsdef.execute() + + # Check model file + self._check_obsdef_file('csobsdef_py3.xml') # Return return @@ -173,7 +195,7 @@ class Test(gammalib.GPythonTestSuite): # Loop over all observations for o in obs: - self.test_assert(o.instrument() == "CTA", + self.test_value(o.instrument(), 'CTA', 'Check for "CTA" instrument') self.test_value(o.ontime(), 1800.0, 1.0e-6, 'Check for ontime of 1800 sec')