Commit 31f23bc7b8017fa83c4232cf528a79b7d671ee16

Authored by Jürgen Knödlseder
2 parents 430c2b2c 9119dabf

Merge branch 'integration' into devel

cscripts/Makefile.am
@@ -11,9 +11,10 @@ pythonscripts = __init__.py \ @@ -11,9 +11,10 @@ pythonscripts = __init__.py \
11 11
12 # Parfiles to be distributed in $(prefix)/syspfiles 12 # Parfiles to be distributed in $(prefix)/syspfiles
13 parfiles = cspull.par cssens.par cstsdist.par cscaldb.par csresmap.par \ 13 parfiles = cspull.par cssens.par cstsdist.par cscaldb.par csresmap.par \
14 - csobsdef.par csspec.par csobsinfo.par \ 14 + csobsdef.par csspec.par cslightcrv.par csobsinfo.par \
15 csmodelinfo.par csmodelmerge.par cstsmapmerge.par \ 15 csmodelinfo.par csmodelmerge.par cstsmapmerge.par \
16 - csobs2caldb.par 16 + csobs2caldb.par \
  17 + csfindobs.par csiactcopy.par csiactdata.par csiactobs.par
17 18
18 # Scripts for which symbolic links will be created in bindir 19 # Scripts for which symbolic links will be created in bindir
19 linkscripts = cspull cssens cstsdist cscaldb csresmap \ 20 linkscripts = cspull cssens cstsdist cscaldb csresmap \
cscripts/cscaldb.py
@@ -37,7 +37,7 @@ class cscaldb(ctools.cscript): @@ -37,7 +37,7 @@ class cscaldb(ctools.cscript):
37 into the "cscaldb.log" log file. 37 into the "cscaldb.log" log file.
38 """ 38 """
39 39
40 - # Constructors and destructors 40 + # Constructor
41 def __init__(self, *argv): 41 def __init__(self, *argv):
42 """ 42 """
43 Constructor. 43 Constructor.
@@ -46,28 +46,13 @@ class cscaldb(ctools.cscript): @@ -46,28 +46,13 @@ class cscaldb(ctools.cscript):
46 self._name = "cscaldb" 46 self._name = "cscaldb"
47 self._version = "1.1.0" 47 self._version = "1.1.0"
48 48
49 - # Initialise application  
50 - if len(argv) == 0:  
51 - ctools.cscript.__init__(self, self._name, self._version)  
52 - elif len(argv) ==1:  
53 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
54 - else:  
55 - raise TypeError("Invalid number of arguments given.")  
56 -  
57 - # Set logger properties  
58 - self._log_header()  
59 - self._log.date(True) 49 + # Initialise application by calling the appropriate class
  50 + # constructor.
  51 + self._init_cscript(argv)
60 52
61 # Return 53 # Return
62 return 54 return
63 55
64 - def __del__(self):  
65 - """  
66 - Destructor.  
67 - """  
68 - # Return  
69 - return  
70 -  
71 56
72 # Private methods 57 # Private methods
73 def _get_parameters(self): 58 def _get_parameters(self):
@@ -164,16 +149,6 @@ class cscaldb(ctools.cscript): @@ -164,16 +149,6 @@ class cscaldb(ctools.cscript):
164 149
165 150
166 # Public methods 151 # Public methods
167 - def execute(self):  
168 - """  
169 - Execute the script.  
170 - """  
171 - # Run the script  
172 - self.run()  
173 -  
174 - # Return  
175 - return  
176 -  
177 def run(self): 152 def run(self):
178 """ 153 """
179 Run the script. 154 Run the script.
@@ -238,6 +213,19 @@ class cscaldb(ctools.cscript): @@ -238,6 +213,19 @@ class cscaldb(ctools.cscript):
238 # Return 213 # Return
239 return 214 return
240 215
  216 + def execute(self):
  217 + """
  218 + Execute the script.
  219 + """
  220 + # Open logfile
  221 + self._logFileOpen()
  222 +
  223 + # Run the script
  224 + self.run()
  225 +
  226 + # Return
  227 + return
  228 +
241 229
242 # ======================== # 230 # ======================== #
243 # Main routine entry point # 231 # Main routine entry point #
@@ -247,8 +235,5 @@ if __name__ == '__main__': @@ -247,8 +235,5 @@ if __name__ == '__main__':
247 # Create instance of application 235 # Create instance of application
248 app = cscaldb(sys.argv) 236 app = cscaldb(sys.argv)
249 237
250 - # Open logfile  
251 - app._logFileOpen()  
252 -  
253 # Execute application 238 # Execute application
254 app.execute() 239 app.execute()
cscripts/csfindobs.par 0 → 100644
  1 +#############################################################################
  2 +# #
  3 +# CTA Science Analysis Tools #
  4 +# #
  5 +# ------------------------------------------------------------------------- #
  6 +# #
  7 +# File: csfindobs.par #
  8 +# Version: 1.1.0 #
  9 +# #
  10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
  13 +# #
  14 +# Purpose: Parameter file for the csfindobs script #
  15 +# #
  16 +#############################################################################
  17 +#
  18 +# Input and output parameters
  19 +#============================
  20 +datapath, s, a, $VHEFITS,,, "Path were data are located"
  21 +prodname, s, a, prod-name,,, "Name of FITS production (Run csiactdata to view your options)"
  22 +outfile, f, a, runlist.lis,,, "Output runlist file"
  23 +
  24 +#
  25 +# Script parameters
  26 +#==================
  27 +ra, r, a, 83.63,,, "Right ascension of selection region centre (deg)"
  28 +dec, r, a, 22.01,,, "Declination of selection region centre (deg)"
  29 +rad, r, a, 2.5,,, "Search radius of selection region (deg)"
  30 +min_qual, i, h, 0,0|1|2,, "Minimum data quality (0=perfect, 1=ok, 2=bad)"
  31 +expression, s, h, NONE,,, "Additional expression"
  32 +master_indx, s, h, master.json,,, "Name of master index file"
  33 +
  34 +#
  35 +# Standard parameters
  36 +#====================
  37 +chatter, i, h, 2,0,4, "Chattiness of output"
  38 +clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
  39 +debug, b, h, no,,, "Debugging mode activated"
  40 +mode, s, h, ql,,, "Mode of automatic parameters"
  41 +logfile, f, h, csfindobs.log,,, "Log filename"
  42 +
  43 +
  44 +
cscripts/csfindobs.py
@@ -33,7 +33,7 @@ class csfindobs(ctools.cscript): @@ -33,7 +33,7 @@ class csfindobs(ctools.cscript):
33 Find observations from an IACT data store. 33 Find observations from an IACT data store.
34 """ 34 """
35 35
36 - # Constructors and destructors 36 + # Constructor
37 def __init__(self, *argv): 37 def __init__(self, *argv):
38 """ 38 """
39 Constructor. 39 Constructor.
@@ -44,68 +44,15 @@ class csfindobs(ctools.cscript): @@ -44,68 +44,15 @@ class csfindobs(ctools.cscript):
44 self._verbose = False 44 self._verbose = False
45 self._datapath = os.getenv("VHEFITS","") 45 self._datapath = os.getenv("VHEFITS","")
46 46
47 - # Make sure that parfile exists  
48 - self._parfile()  
49 -  
50 - # Initialise application  
51 - if len(argv) == 0:  
52 - ctools.cscript.__init__(self, self._name, self._version)  
53 - elif len(argv) ==1:  
54 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
55 - else:  
56 - raise TypeError("Invalid number of arguments given.")  
57 -  
58 - # Set logger properties  
59 - self._log_header()  
60 - self._log.date(True) 47 + # Initialise application by calling the appropriate class
  48 + # constructor.
  49 + self._init_cscript(argv)
61 50
62 # Return 51 # Return
63 return 52 return
64 53
65 - def __del__(self):  
66 - """  
67 - Destructor.  
68 - """  
69 - # Write separator into logger  
70 - if self._logTerse():  
71 - self._log("\n")  
72 -  
73 - # Return  
74 - return  
75 54
76 - def _parfile(self):  
77 - """  
78 - Check if parfile exists. If parfile does not exist then create a  
79 - default parfile. This kluge avoids shipping the cscript with a  
80 - parfile.  
81 - """  
82 - # Set parfile name  
83 - parfile = self._name+".par"  
84 -  
85 - try:  
86 - pars = gammalib.GApplicationPars(parfile)  
87 - except:  
88 - # Signal if parfile was not found  
89 - sys.stdout.write("Parfile "+parfile+" not found. Create default parfile.\n")  
90 -  
91 - # Create default parfile  
92 - pars = gammalib.GApplicationPars()  
93 - pars.append(gammalib.GApplicationPar("datapath","s","a",self._datapath,"","","Path were data are located"))  
94 - pars.append(gammalib.GApplicationPar("prodname","s","a","prod-name","","","Name of FITS production (Run csiactdata to view your options)"))  
95 - pars.append(gammalib.GApplicationPar("outfile","f","a","runlist.lis","","","Runlist outfile"))  
96 - pars.append(gammalib.GApplicationPar("ra","r","a","83.6331","","","Right ascension"))  
97 - pars.append(gammalib.GApplicationPar("dec","r","a","22.01","","","Declination"))  
98 - pars.append(gammalib.GApplicationPar("rad","r","a","2.5","","","Search radius"))  
99 - pars.append(gammalib.GApplicationPar("min_qual","i","h","0","0|1|2","","Minimum data quality (0=perfect, 1=ok, 2=bad)"))  
100 - pars.append(gammalib.GApplicationPar("expression","s","h","NONE","","","Additional expression"))  
101 - pars.append(gammalib.GApplicationPar("master_indx","s","h","master.json","","","Name of master index file"))  
102 - pars.append_standard()  
103 - pars.append(gammalib.GApplicationPar("logfile","f","h","csfindobs.log","","","Log filename"))  
104 - pars.save(parfile)  
105 -  
106 - # Return  
107 - return  
108 - 55 + # Private methods
109 def _get_parameters(self): 56 def _get_parameters(self):
110 """ 57 """
111 Get parameters from parfile and setup the observation. 58 Get parameters from parfile and setup the observation.
@@ -209,27 +156,7 @@ class csfindobs(ctools.cscript): @@ -209,27 +156,7 @@ class csfindobs(ctools.cscript):
209 # Return 156 # Return
210 return 157 return
211 158
212 - def obs_ids(self):  
213 - """  
214 - Return OBS IDs  
215 - """  
216 -  
217 - # Return  
218 - return self.runs  
219 -  
220 - def execute(self):  
221 - """  
222 - Execute the script.  
223 - """  
224 - # Run the script  
225 - self.run()  
226 -  
227 - # Save residual map  
228 - self.save(self._outfile)  
229 -  
230 - # Return  
231 - return  
232 - 159 + # Public methods
233 def run(self): 160 def run(self):
234 """ 161 """
235 Run the script. 162 Run the script.
@@ -304,6 +231,22 @@ class csfindobs(ctools.cscript): @@ -304,6 +231,22 @@ class csfindobs(ctools.cscript):
304 # Return 231 # Return
305 return 232 return
306 233
  234 + def execute(self):
  235 + """
  236 + Execute the script.
  237 + """
  238 + # Open logfile
  239 + self._logFileOpen()
  240 +
  241 + # Run the script
  242 + self.run()
  243 +
  244 + # Save residual map
  245 + self.save(self._outfile)
  246 +
  247 + # Return
  248 + return
  249 +
307 def save(self, outfile): 250 def save(self, outfile):
308 """ 251 """
309 Save. 252 Save.
@@ -323,6 +266,14 @@ class csfindobs(ctools.cscript): @@ -323,6 +266,14 @@ class csfindobs(ctools.cscript):
323 # Return 266 # Return
324 return 267 return
325 268
  269 + def obs_ids(self):
  270 + """
  271 + Return OBS IDs
  272 + """
  273 +
  274 + # Return
  275 + return self._runs
  276 +
326 277
327 # ======================== # 278 # ======================== #
328 # Main routine entry point # 279 # Main routine entry point #
@@ -332,8 +283,5 @@ if __name__ == '__main__': @@ -332,8 +283,5 @@ if __name__ == '__main__':
332 # Create instance of application 283 # Create instance of application
333 app = csfindobs(sys.argv) 284 app = csfindobs(sys.argv)
334 285
335 - # Open logfile  
336 - app._logFileOpen()  
337 -  
338 # Execute application 286 # Execute application
339 app.execute() 287 app.execute()
cscripts/csiactcopy.par 0 → 100644
  1 +#############################################################################
  2 +# #
  3 +# CTA Science Analysis Tools #
  4 +# #
  5 +# ------------------------------------------------------------------------- #
  6 +# #
  7 +# File: csiactcopy.par #
  8 +# Version: 1.1.0 #
  9 +# #
  10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
  13 +# #
  14 +# Purpose: Parameter file for the csiactcopy script #
  15 +# #
  16 +#############################################################################
  17 +#
  18 +# Input and output parameters
  19 +#============================
  20 +remote_master, f, a, /Volumes/mountpoint/master.json,,, "Location of remote master file"
  21 +prodname, s, a, iact-fits,,, "Name of FITS production to download"
  22 +runlist, f, h, NONE,,, "Input list of observation IDs"
  23 +outpath, s, a, /path/to/fits,,, "Destination path of FITS data"
  24 +
  25 +#
  26 +# Standard parameters
  27 +#====================
  28 +chatter, i, h, 2,0,4, "Chattiness of output"
  29 +clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
  30 +debug, b, h, no,,, "Debugging mode activated"
  31 +mode, s, h, ql,,, "Mode of automatic parameters"
  32 +logfile, f, h, csiactcopy.log,,, "Log filename"
cscripts/csiactcopy.py
@@ -34,6 +34,8 @@ class csiactcopy(ctools.cscript): @@ -34,6 +34,8 @@ class csiactcopy(ctools.cscript):
34 It can take a list of observation IDs to allow the download specific 34 It can take a list of observation IDs to allow the download specific
35 observations. Index files get merged and updated accordingly. 35 observations. Index files get merged and updated accordingly.
36 """ 36 """
  37 +
  38 + # Constructor
37 def __init__(self, *argv): 39 def __init__(self, *argv):
38 """ 40 """
39 Constructor. 41 Constructor.
@@ -43,60 +45,15 @@ class csiactcopy(ctools.cscript): @@ -43,60 +45,15 @@ class csiactcopy(ctools.cscript):
43 self._version = "1.1.0" 45 self._version = "1.1.0"
44 self._datapath = os.getenv("VHEFITS","") 46 self._datapath = os.getenv("VHEFITS","")
45 47
46 - # Make sure that parfile exists  
47 - self._parfile()  
48 -  
49 - # Initialise application  
50 - if len(argv) == 0:  
51 - ctools.cscript.__init__(self, self._name, self._version)  
52 - elif len(argv) == 1:  
53 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
54 - else:  
55 - raise TypeError("Invalid number of arguments given.")  
56 -  
57 - # Set logger properties  
58 - self._log_header()  
59 - self._log.date(True) 48 + # Initialise application by calling the appropriate class
  49 + # constructor.
  50 + self._init_cscript(argv)
60 51
61 # Return 52 # Return
62 return 53 return
63 54
64 - def __del__(self):  
65 - """  
66 - Destructor.  
67 - """  
68 -  
69 - # Return  
70 - return  
71 -  
72 - def _parfile(self):  
73 - """  
74 - Check if parfile exists. If parfile does not exist then create a  
75 - default parfile. This kluge avoids shipping the cscript with a  
76 - parfile.  
77 - """  
78 - # Set parfile name  
79 - parfile = self._name+".par"  
80 -  
81 - try:  
82 - pars = gammalib.GApplicationPars(parfile)  
83 - except:  
84 - # Signal if parfile was not found  
85 - print("Parfile "+parfile+" not found. Create default parfile.")  
86 -  
87 - # Create default parfile  
88 - pars = gammalib.GApplicationPars()  
89 - pars.append(gammalib.GApplicationPar("remote_master","f","a","/Volumes/mountpoint/master.json","","","Location of remote master file"))  
90 - pars.append(gammalib.GApplicationPar("prodname","s","a","iact-fits","","","Name of FITS production to download"))  
91 - pars.append(gammalib.GApplicationPar("outpath","s","a","/path/to/fits","","","Destination path of FITS data"))  
92 - pars.append(gammalib.GApplicationPar("runlist","f","h","NONE","","","List of observation IDs"))  
93 - pars.append_standard()  
94 - pars.append(gammalib.GApplicationPar("logfile","f","h","csiactcopy.log","","","Log filename"))  
95 - pars.save(parfile)  
96 -  
97 - # Return  
98 - return  
99 55
  56 + # Private methods
100 def _get_parameters(self): 57 def _get_parameters(self):
101 """ 58 """
102 Get parameters from parfile and setup the observation. 59 Get parameters from parfile and setup the observation.
@@ -114,20 +71,233 @@ class csiactcopy(ctools.cscript): @@ -114,20 +71,233 @@ class csiactcopy(ctools.cscript):
114 self._prodname = self["prodname"].string() 71 self._prodname = self["prodname"].string()
115 self._outpath = gammalib.expand_env(self["outpath"].string()) 72 self._outpath = gammalib.expand_env(self["outpath"].string())
116 self._runlist = self["runlist"].filename() 73 self._runlist = self["runlist"].filename()
117 - 74 +
  75 + # Write input parameters into logger
  76 + if self._logTerse():
  77 + self._log_parameters()
  78 + self._log("\n")
  79 +
118 # Return 80 # Return
119 return 81 return
120 82
121 - def execute(self): 83 + def copy(self, source, clobber):
122 """ 84 """
123 - Execute the script. 85 + copy file to _outpath
124 """ 86 """
125 - # Run the script  
126 - self.run() 87 + # Get file destination
  88 + destination = os.path.join(self._outpath,
  89 + os.path.relpath(source, self._remote_base))
  90 +
  91 + # Initialise return value
  92 + filesize = 0.0
  93 +
  94 + # Logging
  95 + if self._logVerbose():
  96 + self._log("\n")
  97 + self._log.header3("Copy file")
  98 + self._log.parformat("Source")
  99 + self._log(str(source))
  100 + self._log("\n")
  101 + self._log.parformat("Destination")
  102 + self._log(str(destination))
  103 + self._log("\n")
  104 + self._log.parformat("Already exists")
  105 + self._log(str(os.path.isfile(destination)))
  106 + self._log("\n")
  107 + self._log.parformat("Overwrite")
  108 + self._log(str(clobber))
  109 + self._log("\n")
  110 + self._log.parformat("Copying")
  111 +
  112 + # Flag if file destination is already available
  113 + is_file = os.path.isfile(destination)
  114 +
  115 + # check if file could be skipped because clobber=no
  116 + if is_file and clobber == False:
  117 + if self._logVerbose():
  118 + self._log("Skip (clobber=no)")
  119 + self._log("\n")
  120 +
  121 + # check if file could be skipped because it is the same file
  122 + elif is_file and os.path.samefile(destination, source):
  123 + if self._logVerbose():
  124 + self._log("Skip (same file)")
  125 + self._log("\n")
  126 +
  127 + else:
  128 + # Create directory if not existent
  129 + dest_dir = os.path.dirname(destination)
  130 + if not os.path.isdir(dest_dir):
  131 + os.makedirs(dest_dir)
  132 +
  133 + # Copy file (if source not identical to destination)
  134 + shutil.copy2(source, destination)
  135 +
  136 + # Get filesize
  137 + filesize = os.stat(destination).st_size
  138 +
  139 + # Logging
  140 + if self._logVerbose():
  141 + self._log("Done!")
  142 + self._log("\n")
  143 +
  144 + # Return
  145 + return filesize
  146 +
  147 +
  148 + def merge(self, localfits, remotefits, hduname, clobber):
  149 + """
  150 + merge remote and local fits file
  151 + If local fits file not present, a new one is created
  152 + """
  153 +
  154 + if self._logTerse():
  155 + self._log.parformat("Local file")
  156 + self._log(str(localfits))
  157 + self._log("\n")
  158 + self._log.parformat("Remote file")
  159 + self._log(str(remotefits))
  160 + self._log("\n")
  161 + self._log.parformat("HDU name")
  162 + self._log(str(hduname))
  163 + self._log("\n")
  164 + self._log.parformat("Conflict preference")
  165 + if clobber:
  166 + self._log("Remote")
  167 + else:
  168 + self._log("Local")
  169 + self._log("\n")
  170 +
  171 + # Check if local fits file is available
  172 + if os.path.isfile(localfits):
  173 + local = gammalib.GFits(str(localfits))
  174 + local_hdu = local[hduname]
  175 + else:
  176 + # Otherwise load remote fits file and delete rows
  177 + local = gammalib.GFits(str(remotefits))
  178 + local_hdu = local[hduname]
  179 + local_hdu.remove_rows(0,local_hdu.nrows())
  180 +
  181 + # find local obs_id
  182 + local_obs = []
  183 + lobs_col = local_hdu["OBS_ID"]
  184 + for obs_id in lobs_col:
  185 + local_obs.append(obs_id)
  186 +
  187 + # Create selection expression for opening remote fits file
  188 + selection = ""
  189 + if len(self._runs):
  190 + selection += "["+hduname+"]["
  191 + for run in self._runs:
  192 + selection += "OBS_ID=="+str(run)
  193 + selection += "||"
  194 + selection = selection[:-2]
  195 + selection += "]"
  196 +
  197 + # Create file name
  198 + remotefile = remotefits + selection
  199 +
  200 + # open remote fits file
  201 + remote = gammalib.GFits(str(remotefile))
  202 + remote_hdu = remote[hduname]
  203 +
  204 + # Get remote obs_id
  205 + remote_obs = []
  206 + robs_col = remote_hdu["OBS_ID"]
  207 + for obs_id in robs_col:
  208 + remote_obs.append(obs_id)
  209 +
  210 + if self._logTerse():
  211 + self._log.parformat("Remote entries")
  212 + self._log(str(len(remote_obs)))
  213 + self._log("\n")
  214 + self._log.parformat("Local entries")
  215 + self._log(str(len(local_obs)))
  216 + self._log("\n")
  217 +
  218 + # initialise counter for logging
  219 + removed_rows = 0
  220 +
  221 + # If clobber=yes, we use the remote content to overwrite
  222 + # corresponding local content
  223 + if clobber:
  224 +
  225 + # Loop over remote obs_ids
  226 + for remote_obs_id in remote_obs:
  227 +
  228 + # Check if remote obs_id is present locally
  229 + if remote_obs_id in local_obs:
  230 +
  231 + # Remove local obs_id entries
  232 + table_has_obsid = True
  233 + while table_has_obsid:
  234 + for i in range(local_hdu.nrows()):
  235 + if remote_obs_id == local_hdu["OBS_ID"][i]:
  236 + local_hdu.remove_rows(i,1)
  237 + removed_rows += 1
  238 + break
  239 + table_has_obsid = False
  240 + for i in range(local_hdu.nrows()):
  241 + if remote_obs_id == local_hdu["OBS_ID"][i]:
  242 + table_has_obsid = True
  243 + break
  244 +
  245 + # If clobber=false, we keep the local content unchanged and just
  246 + # expand by remote content
  247 + else:
  248 + # Loop over remote obs_ids
  249 + for local_obs_id in local_obs:
  250 +
  251 + # Check if local obs_id is present remotely
  252 + if local_obs_id in remote_obs:
  253 +
  254 + # Remove remote obs_id entries
  255 + table_has_obsid = True
  256 + while table_has_obsid:
  257 + for i in range(remote_hdu.nrows()):
  258 + if local_obs_id == remote_hdu["OBS_ID"][i]:
  259 + remote_hdu.remove_rows(i,1)
  260 + removed_rows += 1
  261 + break
  262 + table_has_obsid = False
  263 + for i in range(remote_hdu.nrows()):
  264 + if local_obs_id == remote_hdu["OBS_ID"][i]:
  265 + table_has_obsid = True
  266 + break
  267 +
  268 + # Store number of local rows
  269 + old_local_rows = local_hdu.nrows()
  270 +
  271 + # Add rmeote HDUs
  272 + local_hdu.insert_rows(old_local_rows, remote_hdu.nrows())
  273 +
  274 + if self._logTerse():
  275 + if clobber:
  276 + self._log.parformat("Removed local rows")
  277 + else:
  278 + self._log.parformat("Skipped remote rows")
  279 + self._log(str(removed_rows))
  280 + self._log("\n")
127 281
  282 + # Loop over columns
  283 + for i in range(local_hdu.ncols()):
  284 +
  285 + # Get local and remote columns
  286 + local_col = local_hdu[i]
  287 + remote_col = remote_hdu[i]
  288 +
  289 + # Loop over entries and merge
  290 + for j in range(remote_col.length()):
  291 + local_col[j+old_local_rows] = remote_col[j]
  292 +
  293 + # Save local fits file
  294 + local.saveto(str(localfits), True)
  295 +
128 # Return 296 # Return
129 return 297 return
130 - 298 +
  299 +
  300 + # Public methods
131 def run(self): 301 def run(self):
132 """ 302 """
133 Run the script. 303 Run the script.
@@ -138,11 +308,6 @@ class csiactcopy(ctools.cscript): @@ -138,11 +308,6 @@ class csiactcopy(ctools.cscript):
138 # Get parameters 308 # Get parameters
139 self._get_parameters() 309 self._get_parameters()
140 310
141 - # Write input parameters into logger  
142 - if self._logTerse():  
143 - self._log_parameters()  
144 - self._log("\n")  
145 -  
146 # Make destination directory if not available 311 # Make destination directory if not available
147 if not os.path.isdir(self._outpath): 312 if not os.path.isdir(self._outpath):
148 os.makedirs(self._outpath) 313 os.makedirs(self._outpath)
@@ -516,221 +681,19 @@ class csiactcopy(ctools.cscript): @@ -516,221 +681,19 @@ class csiactcopy(ctools.cscript):
516 # Return 681 # Return
517 return 682 return
518 683
519 - def copy(self, source, clobber):  
520 - """  
521 - copy file to m_outpath 684 + def execute(self):
522 """ 685 """
523 - # Get file destination  
524 - destination = os.path.join(self._outpath,  
525 - os.path.relpath(source, self._remote_base))  
526 -  
527 - # Initialise return value  
528 - filesize = 0.0  
529 -  
530 - # Logging  
531 - if self._logVerbose():  
532 - self._log("\n")  
533 - self._log.header3("Copy file")  
534 - self._log.parformat("Source")  
535 - self._log(str(source))  
536 - self._log("\n")  
537 - self._log.parformat("Destination")  
538 - self._log(str(destination))  
539 - self._log("\n")  
540 - self._log.parformat("Already exists")  
541 - self._log(str(os.path.isfile(destination)))  
542 - self._log("\n")  
543 - self._log.parformat("Overwrite")  
544 - self._log(str(clobber))  
545 - self._log("\n")  
546 - self._log.parformat("Copying")  
547 -  
548 - # Flag if file destination is already available  
549 - is_file = os.path.isfile(destination)  
550 -  
551 - # check if file could be skipped because clobber=no  
552 - if is_file and clobber == False:  
553 - if self._logVerbose():  
554 - self._log("Skip (clobber=no)")  
555 - self._log("\n")  
556 -  
557 - # check if file could be skipped because it is the same file  
558 - elif is_file and os.path.samefile(destination, source):  
559 - if self._logVerbose():  
560 - self._log("Skip (same file)")  
561 - self._log("\n")  
562 -  
563 - else:  
564 - # Create directory if not existent  
565 - dest_dir = os.path.dirname(destination)  
566 - if not os.path.isdir(dest_dir):  
567 - os.makedirs(dest_dir)  
568 -  
569 - # Copy file (if source not identical to destination)  
570 - shutil.copy2(source, destination)  
571 -  
572 - # Get filesize  
573 - filesize = os.stat(destination).st_size  
574 -  
575 - # Logging  
576 - if self._logVerbose():  
577 - self._log("Done!")  
578 - self._log("\n")  
579 -  
580 - # Return  
581 - return filesize  
582 -  
583 -  
584 - def merge(self, localfits, remotefits, hduname, clobber): 686 + Execute the script.
585 """ 687 """
586 - merge remote and local fits file  
587 - If local fits file not present, a new one is created  
588 - """  
589 -  
590 - if self._logTerse():  
591 - self._log.parformat("Local file")  
592 - self._log(str(localfits))  
593 - self._log("\n")  
594 - self._log.parformat("Remote file")  
595 - self._log(str(remotefits))  
596 - self._log("\n")  
597 - self._log.parformat("HDU name")  
598 - self._log(str(hduname))  
599 - self._log("\n")  
600 - self._log.parformat("Conflict preference")  
601 - if clobber:  
602 - self._log("Remote")  
603 - else:  
604 - self._log("Local")  
605 - self._log("\n")  
606 -  
607 - # Check if local fits file is available  
608 - if os.path.isfile(localfits):  
609 - local = gammalib.GFits(str(localfits))  
610 - local_hdu = local[hduname]  
611 - else:  
612 - # Otherwise load remote fits file and delete rows  
613 - local = gammalib.GFits(str(remotefits))  
614 - local_hdu = local[hduname]  
615 - local_hdu.remove_rows(0,local_hdu.nrows())  
616 -  
617 - # find local obs_id  
618 - local_obs = []  
619 - lobs_col = local_hdu["OBS_ID"]  
620 - for obs_id in lobs_col:  
621 - local_obs.append(obs_id)  
622 -  
623 - # Create selection expression for opening remote fits file  
624 - selection = ""  
625 - if len(self._runs):  
626 - selection += "["+hduname+"]["  
627 - for run in self._runs:  
628 - selection += "OBS_ID=="+str(run)  
629 - selection += "||"  
630 - selection = selection[:-2]  
631 - selection += "]"  
632 -  
633 - # Create file name  
634 - remotefile = remotefits + selection  
635 -  
636 - # open remote fits file  
637 - remote = gammalib.GFits(str(remotefile))  
638 - remote_hdu = remote[hduname]  
639 -  
640 - # Get remote obs_id  
641 - remote_obs = []  
642 - robs_col = remote_hdu["OBS_ID"]  
643 - for obs_id in robs_col:  
644 - remote_obs.append(obs_id)  
645 -  
646 - if self._logTerse():  
647 - self._log.parformat("Remote entries")  
648 - self._log(str(len(remote_obs)))  
649 - self._log("\n")  
650 - self._log.parformat("Local entries")  
651 - self._log(str(len(local_obs)))  
652 - self._log("\n")  
653 -  
654 - # initialise counter for logging  
655 - removed_rows = 0  
656 -  
657 - # If clobber=yes, we use the remote content to overwrite  
658 - # corresponding local content  
659 - if clobber:  
660 -  
661 - # Loop over remote obs_ids  
662 - for remote_obs_id in remote_obs:  
663 -  
664 - # Check if remote obs_id is present locally  
665 - if remote_obs_id in local_obs:  
666 -  
667 - # Remove local obs_id entries  
668 - table_has_obsid = True  
669 - while table_has_obsid:  
670 - for i in range(local_hdu.nrows()):  
671 - if remote_obs_id == local_hdu["OBS_ID"][i]:  
672 - local_hdu.remove_rows(i,1)  
673 - removed_rows += 1  
674 - break  
675 - table_has_obsid = False  
676 - for i in range(local_hdu.nrows()):  
677 - if remote_obs_id == local_hdu["OBS_ID"][i]:  
678 - table_has_obsid = True  
679 - break  
680 -  
681 - # If clobber=false, we keep the local content unchanged and just  
682 - # expand by remote content  
683 - else:  
684 - # Loop over remote obs_ids  
685 - for local_obs_id in local_obs:  
686 -  
687 - # Check if local obs_id is present remotely  
688 - if local_obs_id in remote_obs:  
689 -  
690 - # Remove remote obs_id entries  
691 - table_has_obsid = True  
692 - while table_has_obsid:  
693 - for i in range(remote_hdu.nrows()):  
694 - if local_obs_id == remote_hdu["OBS_ID"][i]:  
695 - remote_hdu.remove_rows(i,1)  
696 - removed_rows += 1  
697 - break  
698 - table_has_obsid = False  
699 - for i in range(remote_hdu.nrows()):  
700 - if local_obs_id == remote_hdu["OBS_ID"][i]:  
701 - table_has_obsid = True  
702 - break  
703 -  
704 - # Store number of local rows  
705 - old_local_rows = local_hdu.nrows()  
706 -  
707 - # Add rmeote HDUs  
708 - local_hdu.insert_rows(old_local_rows, remote_hdu.nrows())  
709 -  
710 - if self._logTerse():  
711 - if clobber:  
712 - self._log.parformat("Removed local rows")  
713 - else:  
714 - self._log.parformat("Skipped remote rows")  
715 - self._log(str(removed_rows))  
716 - self._log("\n") 688 + # Open logfile
  689 + self._logFileOpen()
  690 +
  691 + # Run the script
  692 + self.run()
717 693
718 - # Loop over columns  
719 - for i in range(local_hdu.ncols()):  
720 -  
721 - # Get local and remote columns  
722 - local_col = local_hdu[i]  
723 - remote_col = remote_hdu[i]  
724 -  
725 - # Loop over entries and merge  
726 - for j in range(remote_col.length()):  
727 - local_col[j+old_local_rows] = remote_col[j]  
728 -  
729 - # Save local fits file  
730 - local.saveto(str(localfits), True)  
731 -  
732 # Return 694 # Return
733 return 695 return
  696 +
734 697
735 # ======================== # 698 # ======================== #
736 # Main routine entry point # 699 # Main routine entry point #
@@ -740,8 +703,5 @@ if __name__ == '__main__': @@ -740,8 +703,5 @@ if __name__ == '__main__':
740 # Create instance of application 703 # Create instance of application
741 app = csiactcopy(sys.argv) 704 app = csiactcopy(sys.argv)
742 705
743 - # Open logfile  
744 - app._logFileOpen()  
745 -  
746 # Execute application 706 # Execute application
747 app.execute() 707 app.execute()
cscripts/csiactdata.par 0 → 100644
  1 +#############################################################################
  2 +# #
  3 +# CTA Science Analysis Tools #
  4 +# #
  5 +# ------------------------------------------------------------------------- #
  6 +# #
  7 +# File: csiactdata.par #
  8 +# Version: 1.1.0 #
  9 +# #
  10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
  13 +# #
  14 +# Purpose: Parameter file for the csiactdata script #
  15 +# #
  16 +#############################################################################
  17 +#
  18 +# Input and output parameters
  19 +#============================
  20 +datapath, s, a, $VHEFITS,,, "Path were data is located"
  21 +master_indx, s, h, master.json,,, "Name of master index file"
  22 +
  23 +#
  24 +# Standard parameters
  25 +#====================
  26 +chatter, i, h, 2,0,4, "Chattiness of output"
  27 +clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
  28 +debug, b, h, no,,, "Debugging mode activated"
  29 +mode, s, h, ql,,, "Mode of automatic parameters"
  30 +logfile, f, h, csiactdata.log,,, "Log filename"
  31 +
cscripts/csiactdata.py
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 # ========================================================================== 2 # ==========================================================================
3 # Inspection of IACT data storage 3 # Inspection of IACT data storage
4 # 4 #
5 -# Copyright (C) 2015 Michael Mayer 5 +# Copyright (C) 2015-2016 Michael Mayer
6 # 6 #
7 # This program is free software: you can redistribute it and/or modify 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 8 # it under the terms of the GNU General Public License as published by
@@ -35,6 +35,8 @@ class csiactdata(ctools.cscript): @@ -35,6 +35,8 @@ class csiactdata(ctools.cscript):
35 file or prints it on the screen. These information can be used as input 35 file or prints it on the screen. These information can be used as input
36 for 'csiactobs'. 36 for 'csiactobs'.
37 """ 37 """
  38 +
  39 + # Constructor
38 def __init__(self, *argv): 40 def __init__(self, *argv):
39 """ 41 """
40 Constructor. 42 Constructor.
@@ -45,57 +47,15 @@ class csiactdata(ctools.cscript): @@ -45,57 +47,15 @@ class csiactdata(ctools.cscript):
45 self._datapath = os.getenv("VHEFITS","") 47 self._datapath = os.getenv("VHEFITS","")
46 self._prodnames = [] 48 self._prodnames = []
47 49
48 - # Make sure that parfile exists  
49 - file = self._parfile()  
50 -  
51 - # Initialise application  
52 - if len(argv) == 0:  
53 - ctools.cscript.__init__(self, self._name, self._version)  
54 - elif len(argv) == 1:  
55 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
56 - else:  
57 - raise TypeError("Invalid number of arguments given.")  
58 -  
59 - # Set logger properties  
60 - self._log_header()  
61 - self._log.date(True) 50 + # Initialise application by calling the appropriate class
  51 + # constructor.
  52 + self._init_cscript(argv)
62 53
63 # Return 54 # Return
64 return 55 return
65 56
66 - def __del__(self):  
67 - """  
68 - Destructor.  
69 - """  
70 - # Return  
71 - return  
72 -  
73 - def _parfile(self):  
74 - """  
75 - Check if parfile exists. If parfile does not exist then create a  
76 - default parfile. This kluge avoids shipping the cscript with a  
77 - parfile.  
78 - """  
79 - # Set parfile name  
80 - parfile = self._name+".par"  
81 -  
82 - try:  
83 - pars = gammalib.GApplicationPars(parfile)  
84 - except:  
85 - # Signal if parfile was not found  
86 - sys.stdout.write("Parfile "+parfile+" not found. Create default parfile.\n")  
87 -  
88 - # Create default parfile  
89 - pars = gammalib.GApplicationPars()  
90 - pars.append(gammalib.GApplicationPar("datapath","s","a",self._datapath,"","","Path were data is located"))  
91 - pars.append(gammalib.GApplicationPar("master_indx","s","h","master.json","","","Name of master index file"))  
92 - pars.append_standard()  
93 - pars.append(gammalib.GApplicationPar("logfile","f","h","csiactdata.log","","","Log filename"))  
94 - pars.save(parfile)  
95 -  
96 - # Return  
97 - return  
98 57
  58 + # Private methods
99 def get_parameters(self): 59 def get_parameters(self):
100 """ 60 """
101 Get parameters from parfile and setup the observation. 61 Get parameters from parfile and setup the observation.
@@ -119,16 +79,7 @@ class csiactdata(ctools.cscript): @@ -119,16 +79,7 @@ class csiactdata(ctools.cscript):
119 # Return 79 # Return
120 return 80 return
121 81
122 - def execute(self):  
123 - """  
124 - Execute the script.  
125 - """  
126 - # Run the script  
127 - self.run()  
128 -  
129 - # Return  
130 - return  
131 - 82 + # Public methods
132 def run(self): 83 def run(self):
133 """ 84 """
134 Run the script. 85 Run the script.
@@ -222,6 +173,20 @@ class csiactdata(ctools.cscript): @@ -222,6 +173,20 @@ class csiactdata(ctools.cscript):
222 # Return 173 # Return
223 return 174 return
224 175
  176 + def execute(self):
  177 + """
  178 + Execute the script.
  179 + """
  180 + # Open logfile
  181 + self._logFileOpen()
  182 +
  183 + # Run the script
  184 + self.run()
  185 +
  186 + # Return
  187 + return
  188 +
  189 +
225 def names(self): 190 def names(self):
226 """ 191 """
227 Return available FITS production names 192 Return available FITS production names
@@ -239,8 +204,5 @@ if __name__ == '__main__': @@ -239,8 +204,5 @@ if __name__ == '__main__':
239 # Create instance of application 204 # Create instance of application
240 app = csiactdata(sys.argv) 205 app = csiactdata(sys.argv)
241 206
242 - # Open logfile  
243 - app._logFileOpen()  
244 -  
245 # Execute application 207 # Execute application
246 app.execute() 208 app.execute()
cscripts/csiactobs.par 0 → 100644
  1 +#############################################################################
  2 +# #
  3 +# CTA Science Analysis Tools #
  4 +# #
  5 +# ------------------------------------------------------------------------- #
  6 +# #
  7 +# File: csiactobs.par #
  8 +# Version: 1.1.0 #
  9 +# #
  10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
  13 +# #
  14 +# Purpose: Parameter file for the csiactobs script #
  15 +# #
  16 +#############################################################################
  17 +#
  18 +# Input and output parameters
  19 +#============================
  20 +datapath, s, a, $VHEFITS,,, "Path were data is located"
  21 +prodname, s, a, ,,, "Data storage name"
  22 +infile, f, a, runlist.lis,,, "Input runlist file"
  23 +inmodel, f, h, NONE,,, "Input model definition XML file (optional)"
  24 +master_indx, s, h, master.json,,, "Input master index file"
  25 +outobs, f, a, obs.xml,,, "Output observation definition XML file"
  26 +outmodel, f, a, bgmodels.xml,,, "Output model definition XML file"
  27 +
  28 +#
  29 +# Script parameters
  30 +#==================
  31 +bkgpars, i, a, 1,,, "Number of free parameters per background model"
  32 +bkg_scale, b, h, yes,,, "Apply background scaling factor from observation index file if available?"
  33 +ev_hiera, s, h, events,,, "Hierarchy of event formats"
  34 +aeff_hiera, s, h, aeff_2d,,, "Hierarchy of effective area formats"
  35 +psf_hiera, s, h, psf_king|psf_3gauss,,, "Hierarchy of psf formats"
  36 +edisp_hiera, s, h, edisp_2d,,, "Hierarchy of energy dispersion formats"
  37 +bkg_hiera, s, h, bkg_3d,,, "Hierarchy of background formats"
  38 +bkg_mod_hiera, s, h, irf|aeff|gauss,,, "Hierarchy of background models"
  39 +bkg_gauss_norm, r, h, 1e-8,,, "Input normalisation for Gaussian background"
  40 +bkg_gauss_index, r, h, -2.0,,, "Input spectral index for Gaussian background"
  41 +bkg_gauss_sigma, r, h, 2.5,,, "Input sigma for Gaussian background"
  42 +bkg_aeff_norm, r, h, 1e-14,,, "Input normalisation for effective area background"
  43 +bkg_aeff_index, r, h, -2.0,,, "Input spectral index for effective area background"
  44 +bkg_range_factor, r, h, 100.0,,, "Factor to determine range of background normalisation"
  45 +
  46 +#
  47 +# Standard parameters
  48 +#====================
  49 +chatter, i, h, 2,0,4, "Chattiness of output"
  50 +clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
  51 +debug, b, h, no,,, "Debugging mode activated"
  52 +mode, s, h, ql,,, "Mode of automatic parameters"
  53 +logfile, f, h, csiactobs.log,,, "Log filename"
  54 +
cscripts/csiactobs.py
@@ -37,6 +37,8 @@ class csiactobs(ctools.cscript): @@ -37,6 +37,8 @@ class csiactobs(ctools.cscript):
37 described here: 37 described here:
38 http://gamma-astro-data-formats.readthedocs.org/en/latest/ 38 http://gamma-astro-data-formats.readthedocs.org/en/latest/
39 """ 39 """
  40 +
  41 + # Constructor
40 def __init__(self, *argv): 42 def __init__(self, *argv):
41 """ 43 """
42 Constructor. 44 Constructor.
@@ -53,75 +55,15 @@ class csiactobs(ctools.cscript): @@ -53,75 +55,15 @@ class csiactobs(ctools.cscript):
53 self._models = gammalib.GModels() 55 self._models = gammalib.GModels()
54 self._runlist = [] 56 self._runlist = []
55 57
56 - # Make sure that parfile exists  
57 - file = self._parfile()  
58 -  
59 - # Initialise application  
60 - if len(argv) == 0:  
61 - ctools.cscript.__init__(self, self._name, self._version)  
62 - elif len(argv) == 1:  
63 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
64 - else:  
65 - raise TypeError("Invalid number of arguments given.")  
66 -  
67 - # Set logger properties  
68 - self._log_header()  
69 - self._log.date(True)  
70 -  
71 - # Return  
72 - return 58 + # Initialise application by calling the appropriate class
  59 + # constructor.
  60 + self._init_cscript(argv)
73 61
74 - def __del__(self):  
75 - """  
76 - Destructor.  
77 - """  
78 # Return 62 # Return
79 return 63 return
80 64
81 - def _parfile(self):  
82 - """  
83 - Check if parfile exists. If parfile does not exist then create a  
84 - default parfile. This kluge avoids shipping the cscript with a parfile.  
85 - """  
86 - # Set parfile name  
87 - parfile = self._name+".par"  
88 -  
89 - try:  
90 - pars = gammalib.GApplicationPars(parfile)  
91 - except:  
92 - # Signal if parfile was not found  
93 - sys.stdout.write("Parfile "+parfile+" not found. Create default parfile.\n")  
94 -  
95 - # Create default parfile  
96 - pars = gammalib.GApplicationPars()  
97 - pars.append(gammalib.GApplicationPar("datapath","s","a",self._datapath,"","","Path were data is located"))  
98 - pars.append(gammalib.GApplicationPar("prodname","s","a","","","","Data storage name (Run csiactdata to view your options)"))  
99 - pars.append(gammalib.GApplicationPar("infile","f","a","runlist.lis","","","Runlist file"))  
100 - pars.append(gammalib.GApplicationPar("inmodel","f","h","NONE","","","Input model XML file (optional)"))  
101 - pars.append(gammalib.GApplicationPar("outobs","f","a","obs.xml","","","Observation XML outfile"))  
102 - pars.append(gammalib.GApplicationPar("outmodel","f","a","bgmodels.xml","","","Output model XML file"))  
103 - pars.append(gammalib.GApplicationPar("bkgpars","i","a","1","","","Number of free parameters per background model"))  
104 - pars.append(gammalib.GApplicationPar("master_indx","s","h","master.json","","","Name of master index file"))  
105 - pars.append(gammalib.GApplicationPar("bkg_scale","b","h","yes","","","Specifies whether the background scaling factor from the observation index file should be applied if available. "))  
106 - pars.append(gammalib.GApplicationPar("ev_hiera","s","h","events","","","Hierarchy of event formats"))  
107 - pars.append(gammalib.GApplicationPar("aeff_hiera","s","h","aeff_2d","","","Hierarchy of effective area formats"))  
108 - pars.append(gammalib.GApplicationPar("psf_hiera","s","h","psf_king|psf_3gauss","","","Hierarchy of psf formats"))  
109 - pars.append(gammalib.GApplicationPar("edisp_hiera","s","h","edisp_2d","","","Hierarchy of energy dispersion formats"))  
110 - pars.append(gammalib.GApplicationPar("bkg_hiera","s","h","bkg_3d","","","Hierarchy of background formats"))  
111 - pars.append(gammalib.GApplicationPar("bkg_mod_hiera","s","h","irf|aeff|gauss","","","Hierarchy of background models"))  
112 - pars.append(gammalib.GApplicationPar("bkg_gauss_norm","r","h","1e-8","","","Input normalisation for Gaussian background"))  
113 - pars.append(gammalib.GApplicationPar("bkg_gauss_index","r","h","-2.0","","","Input spectral index for Gaussian background"))  
114 - pars.append(gammalib.GApplicationPar("bkg_gauss_sigma","r","h","2.5","","","Input sigma for Gaussian background"))  
115 - pars.append(gammalib.GApplicationPar("bkg_aeff_norm","r","h","1e-14","","","Input normalisation for effective area background"))  
116 - pars.append(gammalib.GApplicationPar("bkg_aeff_index","r","h","-2.0","","","Input spectral index for effective area background"))  
117 - pars.append(gammalib.GApplicationPar("bkg_range_factor","r","h","100.0","","","Factor to determine range of background normalisation"))  
118 - pars.append_standard()  
119 - pars.append(gammalib.GApplicationPar("logfile","f","h","csiactobs.log","","","Log filename"))  
120 - pars.save(parfile)  
121 -  
122 - # Return  
123 - return  
124 65
  66 + # Private methods
125 def _get_parameters(self): 67 def _get_parameters(self):
126 """ 68 """
127 Get parameters from parfile and setup the observation. 69 Get parameters from parfile and setup the observation.
@@ -366,43 +308,8 @@ class csiactobs(ctools.cscript): @@ -366,43 +308,8 @@ class csiactobs(ctools.cscript):
366 # Return model 308 # Return model
367 return model 309 return model
368 310
369 - def ebounds(self):  
370 - """  
371 - Returns runlist energy range  
372 - """  
373 - return self._ebounds  
374 -  
375 - def obs(self):  
376 - """  
377 - Returns GObservations object  
378 - """  
379 - # Initialise observations  
380 - obs = gammalib.GObservations()  
381 -  
382 - # Read observations if XML is filled  
383 - if self._xml.size():  
384 - obs.read(self._xml)  
385 -  
386 - # Assign models  
387 - obs.models(self._models)  
388 -  
389 - # Return observations  
390 - return obs  
391 -  
392 -  
393 - def execute(self):  
394 - """  
395 - Execute the script.  
396 - """  
397 - # Run the script  
398 - self.run()  
399 -  
400 - # Save residual map  
401 - self.save(self._outobs, self._clobber)  
402 -  
403 - # Return  
404 - return  
405 311
  312 + # Public methods
406 def run(self): 313 def run(self):
407 """ 314 """
408 Run the script. 315 Run the script.
@@ -665,6 +572,22 @@ class csiactobs(ctools.cscript): @@ -665,6 +572,22 @@ class csiactobs(ctools.cscript):
665 # Return 572 # Return
666 return 573 return
667 574
  575 + def execute(self):
  576 + """
  577 + Execute the script.
  578 + """
  579 + # Open logfile
  580 + self._logFileOpen()
  581 +
  582 + # Run the script
  583 + self.run()
  584 +
  585 + # Save residual map
  586 + self.save(self._outobs, self._clobber)
  587 +
  588 + # Return
  589 + return
  590 +
668 def save(self,outfile,clobber): 591 def save(self,outfile,clobber):
669 592
670 # Save observation XML file 593 # Save observation XML file
@@ -676,6 +599,29 @@ class csiactobs(ctools.cscript): @@ -676,6 +599,29 @@ class csiactobs(ctools.cscript):
676 # Return 599 # Return
677 return 600 return
678 601
  602 + def ebounds(self):
  603 + """
  604 + Returns runlist energy range
  605 + """
  606 + return self._ebounds
  607 +
  608 + def obs(self):
  609 + """
  610 + Returns GObservations object
  611 + """
  612 + # Initialise observations
  613 + obs = gammalib.GObservations()
  614 +
  615 + # Read observations if XML is filled
  616 + if self._xml.size():
  617 + obs.read(self._xml)
  618 +
  619 + # Assign models
  620 + obs.models(self._models)
  621 +
  622 + # Return observations
  623 + return obs
  624 +
679 625
680 # ======================== # 626 # ======================== #
681 # Main routine entry point # 627 # Main routine entry point #
@@ -685,8 +631,5 @@ if __name__ == '__main__': @@ -685,8 +631,5 @@ if __name__ == '__main__':
685 # Create instance of application 631 # Create instance of application
686 app = csiactobs(sys.argv) 632 app = csiactobs(sys.argv)
687 633
688 - # Open logfile  
689 - app._logFileOpen()  
690 -  
691 # Execute application 634 # Execute application
692 app.execute() 635 app.execute()
cscripts/cslightcrv.par 0 → 100644
  1 +#############################################################################
  2 +# #
  3 +# CTA Science Analysis Tools #
  4 +# #
  5 +# ------------------------------------------------------------------------- #
  6 +# #
  7 +# File: cslightcrv.par #
  8 +# Version: 1.1.0 #
  9 +# #
  10 +# Author: Juergen Knoedlseder #
  11 +# Jurgen.Knodlseder@irap.omp.eu #
  12 +# IRAP #
  13 +# #
  14 +# Purpose: Parameter file for the cslightcrv script #
  15 +# #
  16 +#############################################################################
  17 +#
  18 +# Input and output parameters
  19 +#============================
  20 +inobs, f, h, events.fits,,, "Input event list, counts cube, or observation definition XML file"
  21 +inmodel, f, a, $CTOOLS/share/models/crab.xml,,, "Input model XML file"
  22 +srcname, s, a, Crab,,, "Source name"
  23 +expcube, f, a, NONE,,, "Input exposure cube file (only needed for stacked analysis)"
  24 +psfcube, f, a, NONE,,, "Input PSF cube file (only needed for stacked analysis)"
  25 +edispcube, f, a, NONE,,, "Input energy dispersion cube file (only needed for stacked analysis)"
  26 +bkgcube, f, a, NONE,,, "Input background cube file (only needed for stacked analysis)"
  27 +caldb, s, a, prod2,,, "Calibration database"
  28 +irf, s, a, South_0.5h,,, "Instrument response function"
  29 +edisp, b, h, no,,, "Apply energy dispersion?"
  30 +outfile, f, a, lightcurve.fits,,, "Output light curve file"
  31 +
  32 +#
  33 +# Script parameters
  34 +#==================
  35 +tbinalg, s, a, GTI,FILE|LIN|GTI,, "Algorithm for defining time bins"
  36 +tmin, r, a, 51544.5,,,"Lightcurve start time (MJD])"
  37 +tmax, r, a, 51544.6,,,"Lightcurve stop time (MJD)"
  38 +tbins, i, a, 5,1,10000, "Number of time bins"
  39 +tbinfile, f, a, NONE,,, "File defining the time binning"
  40 +emin, r, a, 0.1,,, "Lower energy limit of events (TeV)"
  41 +emax, r, a, 100.0,,, "Upper energy limit of events (TeV)"
  42 +enumbins, i, a, 0,0,100, "Number of energy bins for binned (0=unbinned)"
  43 +coordsys, s, a, CEL,CEL|GAL,, "Coordinate System"
  44 +proj, s, a, CAR,AIT|AZP|CAR|MER|MOL|STG|TAN,, "Projection method"
  45 +xref, r, a, 83.63,0,360, "First coordinate of image center in degrees (RA or galactic l)"
  46 +yref, r, a, 22.01,-90,90, "Second coordinate of image center in degrees (DEC or galactic b)"
  47 +nxpix, i, a, 200,,, "Size of the X axis in pixels"
  48 +nypix, i, a, 200,,, "Size of the Y axis in pixels"
  49 +binsz, r, a, 0.02,,, "Pixel size (deg/pixel)"
  50 +calc_ts, b, h, yes,,, "Compute TS value for each bin?"
  51 +calc_ulim, b, h, yes,,, "Compute upper limit for each bin?"
  52 +fix_srcs, b, h, yes,,, "Fix other sky model parameters?"
  53 +fix_bkg, b, h, no,,, "Fix background model parameters?"
  54 +
  55 +#
  56 +# Standard parameters
  57 +#====================
  58 +chatter, i, h, 2,0,4, "Chattiness of output"
  59 +clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
  60 +debug, b, h, no,,, "Debugging mode activated"
  61 +mode, s, h, ql,,, "Mode of automatic parameters"
  62 +logfile, f, h, cslightcrv.log,,, "Log filename"
  63 +
  64 +
  65 +
cscripts/cslightcrv.py
@@ -30,159 +30,70 @@ class cslightcrv(ctools.cscript): @@ -30,159 +30,70 @@ class cslightcrv(ctools.cscript):
30 """ 30 """
31 Generates a lightcurve. 31 Generates a lightcurve.
32 32
33 - This class implements the creation of a light curve. It derives from  
34 - the ctools.cscript class which provides support for parameter files,  
35 - command line arguments, and logging. In that way the Python script  
36 - behaves just as a regular ctool. 33 + The cslightcrv class generates a light curve for Imaging Air Cherenkov
  34 + Telescope event data by performing a maximum likelihood fit using
  35 + ctlike in a series of time bins. The time bins can be either
  36 + specified in an ASCII file, as an interval divided into equally
  37 + sized time bins, or can be taken from the Good Time Intervals of the
  38 + observation(s).
  39 +
  40 + The format of the ASCII file is one row per time bin, each specifying
  41 + the start of stop value of the bin, separated by a whitespace. The
  42 + times are given in Modified Julian Days (MJD).
  43 +
  44 + Examples:
  45 + >>> lcrv = cslightcrv()
  46 + >>> lcrv.run()
  47 + >>> ... (querying for parameters) ...
  48 + >>> fits = lcrv.lightcurve()
  49 + Generates a light curve and retrieves the results in
  50 + a FITS file.
  51 +
  52 + >>> lcrv = cslightcrv()
  53 + >>> lcrv.execute()
  54 + >>> ... (querying for parameters) ...
  55 + Generates a light curve and saves results in a FITS file.
  56 +
  57 + >>> lcrv = cslightcrv(obs)
  58 + >>> lcrv.execute()
  59 + >>> ... (querying for parameters) ...
  60 + Generates a light curve from the observations in an
  61 + observation container and saves results in a FITS file.
37 """ 62 """
38 63
39 - # Constructors and destructors 64 + # Constructor
40 def __init__(self, *argv): 65 def __init__(self, *argv):
41 """ 66 """
42 Constructor. 67 Constructor.
43 """ 68 """
44 -  
45 # Set name 69 # Set name
46 self._name = "cslightcrv" 70 self._name = "cslightcrv"
47 self._version = "1.1.0" 71 self._version = "1.1.0"
48 72
49 # Initialise some members 73 # Initialise some members
50 - self._outfile = ""  
51 -  
52 - # Initialise observation  
53 - if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations):  
54 - self._obs = argv[0]  
55 - argv = argv[1:]  
56 - else:  
57 - self._obs = gammalib.GObservations()  
58 -  
59 - # Make sure that parfile exists  
60 - self._parfile()  
61 -  
62 - # Initialise application  
63 - if len(argv) == 0:  
64 - ctools.cscript.__init__(self, self._name, self._version)  
65 - elif len(argv) ==1:  
66 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
67 - else:  
68 - raise TypeError("Invalid number of arguments given.") 74 + self._srcname = ""
  75 + self._tbins = gammalib.GGti()
  76 + self._stacked = False
69 77
70 - # Set logger properties  
71 - self._log_header()  
72 - self._log.date(True) 78 + # Initialise observation container from constructor arguments.
  79 + self._obs = self._set_input_obs(argv)
73 80
74 - # Return  
75 - return 81 + # Initialise application by calling the appropriate class
  82 + # constructor.
  83 + self._init_cscript(argv)
76 84
77 - def __del__(self):  
78 - """  
79 - Destructor.  
80 - """  
81 # Return 85 # Return
82 return 86 return
83 87
84 88
85 # Private methods 89 # Private methods
86 - def _parfile(self):  
87 - """  
88 - Check if parfile exists. If parfile does not exist then create a  
89 - default parfile. This kluge avoids shipping the cscript with a parfile.  
90 - """  
91 - # Set parfile name  
92 - parfile = self._name+".par"  
93 -  
94 - try:  
95 - pars = gammalib.GApplicationPars(parfile)  
96 - except:  
97 - # Signal if parfile was not found  
98 - sys.stdout.write("Parfile "+parfile+" not found. Create default parfile.\n")  
99 -  
100 - # Create default parfile  
101 - pars = gammalib.GApplicationPars()  
102 - pars.append(gammalib.GApplicationPar("inobs","f","a","events.fits","","","Input event list, counts cube, or observation definition XML file"))  
103 - pars.append(gammalib.GApplicationPar("inmodel","f","a","$CTOOLS/share/models/crab.xml","","","Input model XML file"))  
104 - pars.append(gammalib.GApplicationPar("srcname","s","a","Crab","","","Source name"))  
105 - pars.append(gammalib.GApplicationPar("expcube","f","a","NONE","","","Input exposure cube file (only needed for stacked analysis)"))  
106 - pars.append(gammalib.GApplicationPar("psfcube","f","a","NONE","","","Input PSF cube file (only needed for stacked analysis)"))  
107 - pars.append(gammalib.GApplicationPar("edispcube","f","a","NONE","","","Input energy dispersion cube file (only needed for stacked analysis)"))  
108 - pars.append(gammalib.GApplicationPar("bkgcube","s","a","NONE","","","Input background cube file (only needed for stacked analysis)"))  
109 - pars.append(gammalib.GApplicationPar("edisp","b","h","no","","","Apply energy dispersion?"))  
110 - pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database"))  
111 - pars.append(gammalib.GApplicationPar("irf","s","a","South_0.5h","","","Instrument response function"))  
112 - pars.append(gammalib.GApplicationPar("outfile","f","a","lightcurve.fits","","","Output light curve file"))  
113 - pars.append(gammalib.GApplicationPar("tbinalg","s","a","GTI","FILE|LIN|GTI","", "Algorithm for defining time bins"))  
114 - pars.append(gammalib.GApplicationPar("tmin","r","a","51544.5","","days","Lightcurve start time [MJD]"))  
115 - pars.append(gammalib.GApplicationPar("tmax","r","a","51544.6","","days","Lightcurve stop time [MJD]"))  
116 - pars.append(gammalib.GApplicationPar("tbins","i","a","5","","","Number of time bins"))  
117 - pars.append(gammalib.GApplicationPar("tbinfile","f","a","tbins.fits","","", "File defining the time binning"))  
118 - pars.append(gammalib.GApplicationPar("enumbins","i","a","0","","","Number of energy bins per light curve bin (0=unbinned)"))  
119 - pars.append(gammalib.GApplicationPar("emin","r","a","0.1","","","Lower energy limit of events (TeV)"))  
120 - pars.append(gammalib.GApplicationPar("emax","r","a","100.0","","","Upper energy limit of events (TeV)"))  
121 - pars.append(gammalib.GApplicationPar("coordsys","s","a","CEL","CEL|GAL","","Coordinate System"))  
122 - pars.append(gammalib.GApplicationPar("proj","s","a","CAR","AIT|AZP|CAR|MER|MOL|STG|TAN","","Projection method"))  
123 - pars.append(gammalib.GApplicationPar("xref","r","a","83.63","0","360","First coordinate of image center in degrees (RA or galactic l)"))  
124 - pars.append(gammalib.GApplicationPar("yref","r","a","22.01","-90","90","Second coordinate of image center in degrees (DEC or galactic b)"))  
125 - pars.append(gammalib.GApplicationPar("nxpix","i","a","200","","","Size of the X axis in pixels"))  
126 - pars.append(gammalib.GApplicationPar("nypix","i","a","200","","","Size of the Y axis in pixels"))  
127 - pars.append(gammalib.GApplicationPar("binsz","r","a","0.02","","","Pixel size (deg/pixel)"))  
128 - pars.append(gammalib.GApplicationPar("calc_ts","b","h","yes","yes|no","","Compute TS value for each bin?"))  
129 - pars.append(gammalib.GApplicationPar("calc_ulim","b","h","yes","yes|no","","Compute upper limit for each bin?"))  
130 - pars.append(gammalib.GApplicationPar("fix_srcs","b","h","yes","yes|no","","Fix other sky model parameters?"))  
131 - pars.append(gammalib.GApplicationPar("fix_bkg","b","h","no","yes|no","","Fix background model parameters?"))  
132 - pars.append_standard()  
133 - pars.append(gammalib.GApplicationPar("logfile","f","h","cslightcrv.log","","","Log filename"))  
134 - pars.save(parfile)  
135 -  
136 - # Return  
137 - return  
138 -  
139 - def _create_tbounds(self):  
140 -  
141 - # Create time bin container  
142 - self._tbins = gammalib.GGti()  
143 -  
144 - # check for binning algorithm  
145 - if self["tbinalg"].string() == "FILE":  
146 - try:  
147 - self._tbins.load(self["tbinfile"].filename())  
148 - except:  
149 - csv = gammalib.GCsv(self["tbinfile"].filename())  
150 - for i in range(csv.nrows()):  
151 - tmin = gammalib.GTime()  
152 - tmax = gammalib.GTime()  
153 - tmin.mjd(csv.real(i,0))  
154 - tmax.mjd(csv.real(i,1))  
155 - self._tbins.append(tmin,tmax)  
156 - elif self["tbinalg"].string() == "LIN":  
157 - # Use linear time binning  
158 - time_min = self["tmin"].real()  
159 - time_max = self["tmax"].real()  
160 - nbins = self["tbins"].integer()  
161 - step = (time_max - time_min) / float(nbins)  
162 - for i in range(nbins):  
163 - tmin = gammalib.GTime()  
164 - tmin.mjd(time_min + i*step)# ref)  
165 - tmax = gammalib.GTime()  
166 - tmax.mjd(time_min + (i+1)*step)#ref)  
167 - self._tbins.append(tmin,tmax)  
168 - elif self["tbinalg"].string() == "GTI":  
169 - # Use GTIs of observations  
170 - for obs in self._obs:  
171 - for i in range(obs.events().gti().size()):  
172 - self._tbins.append(obs.events().gti().tstart(i),obs.events().gti().tstop(i))  
173 - else:  
174 - raise AttributeError("tbinalg=\""+self["tbinalg"].string()+"\" unkown. Must be one of \"FILE\", \"LIN\" or \"GTI\"")  
175 -  
176 - # Return  
177 - return  
178 -  
179 def _get_parameters(self): 90 def _get_parameters(self):
180 """ 91 """
181 - Get parameters from parfile and setup the observation. 92 + Get parameters from parfile.
182 """ 93 """
183 # Set observation if not done before 94 # Set observation if not done before
184 if self._obs == None or self._obs.size() == 0: 95 if self._obs == None or self._obs.size() == 0:
185 - self._require_inobs("cslightcrv::get_parameters()") 96 + self._require_inobs("cslightcrv::_get_parameters()")
186 self._obs = self._get_observations() 97 self._obs = self._get_observations()
187 98
188 # Set models if we have none 99 # Set models if we have none
@@ -192,46 +103,35 @@ class cslightcrv(ctools.cscript): @@ -192,46 +103,35 @@ class cslightcrv(ctools.cscript):
192 # Get source name 103 # Get source name
193 self._srcname = self["srcname"].string() 104 self._srcname = self["srcname"].string()
194 105
195 - # Get energy dispersion flag  
196 - self._edisp = self["edisp"].boolean()  
197 -  
198 # Get time boundaries 106 # Get time boundaries
199 - self._create_tbounds() 107 + self._tbins = self._create_tbounds()
  108 +
  109 + # Set stacked analysis flag if the requested number of energy bins
  110 + # is not zero; otherwise an unbinned analysis will be done.
  111 + self._stacked = False if self["enumbins"].integer() == 0 else True
  112 +
  113 + # Make sure that other parameters are queried now and not later
  114 + self["emin"].real()
  115 + self["emax"].real()
  116 + if self._stacked:
  117 + self["coordsys"].string()
  118 + self["proj"].string()
  119 + self["xref"].real()
  120 + self["yref"].real()
  121 + self["nxpix"].integer()
  122 + self["nypix"].integer()
  123 + self["binsz"].real()
  124 +
  125 + # Do the same for the hidden parameters, just in case
  126 + self["edisp"].boolean()
  127 + self["calc_ulim"].boolean()
  128 + self["calc_ts"].boolean()
  129 + self["fix_bkg"].boolean()
  130 + self["fix_srcs"].boolean()
200 131
201 - # Unbinned or binned analysis?  
202 - self._ebins = self["enumbins"].integer()  
203 - if self._ebins == 0:  
204 - self._binned = False  
205 - else:  
206 - self._binned = True  
207 -  
208 - # Get energy range  
209 - self._emin = self["emin"].real()  
210 - self._emax = self["emax"].real()  
211 -  
212 - # Get binning flag  
213 - if self._binned:  
214 - self._coordsys = self["coordsys"].string()  
215 - self._proj = self["proj"].string()  
216 - self._xref = self["xref"].real()  
217 - self._yref = self["yref"].real()  
218 - self._nxpix = self["nxpix"].integer()  
219 - self._nypix = self["nypix"].integer()  
220 - self._binsz = self["binsz"].real()  
221 -  
222 - # Read other parameters  
223 - self._outfile = self["outfile"].filename()  
224 -  
225 - # Get other parameeters  
226 - self._calc_ulimit = self["calc_ulim"].boolean()  
227 - self._calc_ts = self["calc_ts"].boolean()  
228 - self._fix_bkg = self["fix_bkg"].boolean()  
229 - self._fix_srcs = self["fix_srcs"].boolean()  
230 -  
231 - # Set some fixed parameters  
232 - self._chatter = self["chatter"].integer()  
233 - self._clobber = self["clobber"].boolean()  
234 - self._debug = self["debug"].boolean() 132 + # Read ahead output parameters
  133 + if self._read_ahead():
  134 + self["outfile"].filename()
235 135
236 # Write input parameters into logger 136 # Write input parameters into logger
237 if self._logTerse(): 137 if self._logTerse():
@@ -241,26 +141,101 @@ class cslightcrv(ctools.cscript): @@ -241,26 +141,101 @@ class cslightcrv(ctools.cscript):
241 # Return 141 # Return
242 return 142 return
243 143
  144 + def _create_tbounds(self):
  145 + """
  146 + Creates light curve time bins.
244 147
245 - # Public methods  
246 - def run(self): 148 + The method reads the following user parameters:
  149 + tbinalg: Time binning algorithm
  150 + tbinfile: Time binning file (FITS or ASCII)
  151 + tmin: Start time (MJD)
  152 + tmax: Stop time (MJD)
  153 + tbins: Number of time bins
  154 +
  155 + Returns:
  156 + Light curve bins in form of a GTI.
247 """ 157 """
248 - Run the script. 158 + # Initialise Good Time Intervals
  159 + gti = gammalib.GGti()
  160 +
  161 + # Get algorithm to use for defining the time intervals
  162 + algorithm = self["tbinalg"].string()
  163 +
  164 + # Handle a FITS or a ASCII file for time bin definition
  165 + if algorithm == "FILE":
  166 +
  167 + # Get the filename
  168 + filename = self["tbinfile"].filename()
  169 +
  170 + # If the file a FITS file then load GTIs
  171 + if filename.is_fits():
  172 + gti.load(filename)
  173 +
  174 + # ... otherwise load file as CSV ASCII file
  175 + csv = gammalib.GCsv(filename)
  176 + for i in range(csv.nrows()):
  177 + tmin = gammalib.GTime()
  178 + tmax = gammalib.GTime()
  179 + tmin.mjd(csv.real(i,0))
  180 + tmax.mjd(csv.real(i,1))
  181 + gti.append(tmin,tmax)
  182 +
  183 + # Handle linear time binning
  184 + elif algorithm == "LIN":
  185 +
  186 + # Get start and stop time and number of time bins
  187 + time_min = self["tmin"].real()
  188 + time_max = self["tmax"].real()
  189 + nbins = self["tbins"].integer()
  190 +
  191 + # Compute time step and setup time intervals
  192 + time_step = (time_max - time_min) / float(nbins)
  193 + for i in range(nbins):
  194 + tmin = gammalib.GTime()
  195 + tmax = gammalib.GTime()
  196 + tmin.mjd(time_min + i *time_step)
  197 + tmax.mjd(time_min + (i+1)*time_step)
  198 + gti.append(tmin,tmax)
  199 +
  200 + # Handle usage of observation GTIs
  201 + elif algorithm == "GTI":
  202 +
  203 + # Append the GTIs of all observations
  204 + for obs in self._obs:
  205 + for i in range(obs.events().gti().size()):
  206 + gti.append(obs.events().gti().tstart(i),
  207 + obs.events().gti().tstop(i))
  208 +
  209 + # ... otherwise raise an exception (this should never occur)
  210 + else:
  211 + raise AttributeError('Paramter tbinalg="'+algorithm+'" unknown. '
  212 + 'Must be one of "FILE", "LIN" or "GTI".')
  213 +
  214 + # Return Good Time Intervals
  215 + return gti
  216 +
  217 + def _get_free_par_names(self):
249 """ 218 """
250 - # Switch screen logging on in debug mode  
251 - if self._logDebug():  
252 - self._log.cout(True) 219 + Return list of free parameter names.
  220 +
  221 + Returns:
  222 + List of free parameter names.
  223 + """
  224 + # Initialise list of free parameter names
  225 + names = []
253 226
254 - # Get parameters  
255 - self._get_parameters() 227 + # Collect list of free parameter names
  228 + for par in self._obs.models()[self._srcname]:
  229 + if par.is_free():
  230 + names.append(par.name())
256 231
257 - # Write observation into logger  
258 - if self._logTerse():  
259 - self._log("\n")  
260 - self._log.header1("Observation")  
261 - self._log(str(self._obs))  
262 - self._log("\n") 232 + # Return names
  233 + return names
263 234
  235 + def _adjust_model_pars(self):
  236 + """
  237 + Adjust model parameters dependent on user parameters.
  238 + """
264 # Write header 239 # Write header
265 if self._logTerse(): 240 if self._logTerse():
266 self._log("\n") 241 self._log("\n")
@@ -269,85 +244,341 @@ class cslightcrv(ctools.cscript): @@ -269,85 +244,341 @@ class cslightcrv(ctools.cscript):
269 # Adjust model parameters dependent on input user parameters 244 # Adjust model parameters dependent on input user parameters
270 for model in self._obs.models(): 245 for model in self._obs.models():
271 246
272 - # Set TS flag for all models to false.  
273 - # Source of interest will be set to true later 247 + # Set TS flag for all models to false. The source of interest
  248 + # will be set to true later
274 model.tscalc(False) 249 model.tscalc(False)
275 250
276 # Log model name 251 # Log model name
277 - if self._logExplicit(): 252 + if self._logNormal():
278 self._log.header3(model.name()) 253 self._log.header3(model.name())
279 254
280 # Deal with the source of interest 255 # Deal with the source of interest
281 if model.name() == self._srcname: 256 if model.name() == self._srcname:
282 - if self._calc_ts: 257 + if self["calc_ts"].boolean():
283 model.tscalc(True) 258 model.tscalc(True)
284 259
285 - elif self._fix_bkg and not model.classname() == "GModelSky": 260 + elif (self["fix_bkg"].boolean() and
  261 + model.classname() != "GModelSky"):
286 for par in model: 262 for par in model:
287 - if par.is_free() and self._logExplicit():  
288 - self._log(" Fixing \""+par.name()+"\"\n")  
289 - par.fix()  
290 -  
291 - elif self._fix_srcs and model.classname() == "GModelSky": 263 + if par.is_free():
  264 + par.fix()
  265 + if self._logNormal():
  266 + self._log(gammalib.parformat(par.name()))
  267 + self._log("fixed\n")
  268 +
  269 + elif (self["fix_srcs"].boolean() and
  270 + model.classname() == "GModelSky"):
292 for par in model: 271 for par in model:
293 - if par.is_free() and self._logExplicit():  
294 - self._log(" Fixing \""+par.name()+"\"\n")  
295 - par.fix() 272 + if par.is_free():
  273 + par.fix()
  274 + if self._logNormal():
  275 + self._log(gammalib.parformat(par.name()))
  276 + self._log("fixed\n")
296 277
297 - # Write header  
298 - if self._logTerse():  
299 - self._log("\n")  
300 - self._log.header1("Generate lightcurve") 278 + # Return
  279 + return
301 280
302 - # Initialise FITS Table with extension "LIGHTCURVE"  
303 - table = gammalib.GFitsBinTable(self._tbins.size())  
304 - table.extname("LIGHTCURVE") 281 + def _create_fits_table(self, results):
  282 + """
  283 + Creates FITS binary table containing light curve results.
  284 +
  285 + Args:
  286 + results: List of result dictionaries.
305 287
306 - # Add Header for compatibility with gammalib.GMWLSpectrum  
307 - table.card("INSTRUME", "CTA", "Name of Instrument")  
308 - table.card("TELESCOP", "CTA", "Name of Telescope") 288 + Returns:
  289 + FITS binary table containing light curve.
  290 + """
  291 + # Determine number of rows in FITS table
  292 + nrows = len(results)
309 293
310 - # Create FITS table columns  
311 - MJD = gammalib.GFitsTableDoubleCol("MJD", self._tbins.size())  
312 - MJD.unit("days")  
313 - e_MJD = gammalib.GFitsTableDoubleCol("e_MJD", self._tbins.size())  
314 - e_MJD.unit("days") 294 + # Create FITS Table with extension "LIGHTCURVE"
  295 + table = gammalib.GFitsBinTable(nrows)
  296 + table.extname("LIGHTCURVE")
315 297
316 - # Create a FITS column for every free parameter  
317 - columns = [] 298 + # Append time columns
  299 + mjd = gammalib.GFitsTableDoubleCol("MJD", nrows)
  300 + e_mjd = gammalib.GFitsTableDoubleCol("e_MJD", nrows)
  301 + mjd.unit("days")
  302 + e_mjd.unit("days")
  303 + for i, result in enumerate(results):
  304 + mjd[i] = result["mjd"]
  305 + e_mjd[i] = result["e_mjd"]
  306 + table.append(mjd)
  307 + table.append(e_mjd)
  308 +
  309 + # Create parameter columns
318 for par in self._obs.models()[self._srcname]: 310 for par in self._obs.models()[self._srcname]:
319 if par.is_free(): 311 if par.is_free():
320 - col = gammalib.GFitsTableDoubleCol(par.name(), self._tbins.size()) 312 + name = par.name()
  313 + e_name = "e_"+par.name()
  314 + col = gammalib.GFitsTableDoubleCol(name, nrows)
  315 + e_col = gammalib.GFitsTableDoubleCol(e_name, nrows)
321 col.unit(par.unit()) 316 col.unit(par.unit())
322 - columns.append(col)  
323 - e_col = gammalib.GFitsTableDoubleCol("e_"+par.name(), self._tbins.size())  
324 e_col.unit(par.unit()) 317 e_col.unit(par.unit())
325 - columns.append(e_col) 318 + for i, result in enumerate(results):
  319 + col[i] = result['values'][name]
  320 + e_col[i] = result['values'][e_name]
  321 + table.append(col)
  322 + table.append(e_col)
  323 +
  324 + # Append Test Statistic column
  325 + ts = gammalib.GFitsTableDoubleCol("TS", nrows)
  326 + for i, result in enumerate(results):
  327 + ts[i] = result["ts"]
  328 + table.append(ts)
  329 +
  330 + # Append upper limit column
  331 + ulimit = gammalib.GFitsTableDoubleCol("UpperLimit", nrows)
  332 + ulimit.unit("ph/cm2/s")
  333 + for i, result in enumerate(results):
  334 + ulimit[i] = result['ulimit']
  335 + table.append(ulimit)
  336 +
  337 + # Return table
  338 + return table
  339 +
  340 + def _compute_ulimit(self, obs):
  341 + """
  342 + Computes upper flux limit.
326 343
327 - # Create TS and upper limit columns  
328 - TSvalues = gammalib.GFitsTableDoubleCol("TS", self._tbins.size())  
329 - ulim_values = gammalib.GFitsTableDoubleCol("UpperLimit", self._tbins.size())  
330 - ulim_values.unit("ph/cm2/s") 344 + Args:
  345 + obs: Observation container.
331 346
332 - # Loop over energy bins  
333 - for i in range(self._tbins.size()): 347 + Returns:
  348 + Upper flux limit (-1 of not computed).
  349 + """
  350 + # Initialise upper flux limit
  351 + ulimit_value = -1.0
  352 +
  353 + # Perform computation only if requested
  354 + if self["calc_ulim"].boolean():
334 355
335 - # Log information  
336 - if self._logTerse():  
337 - self._log("\n")  
338 - self._log.header2("Time bin "+str(i)) 356 + # Write header in logger
  357 + if self._logExplicit():
  358 + self._log.header3("Computing upper flux limit")
  359 +
  360 + # Create upper limit object
  361 + ulimit = ctools.ctulimit(obs)
  362 + ulimit["srcname"] = self._srcname
  363 + ulimit["eref"] = 1.0
  364 +
  365 + # Try to run upper limit and catch exceptions
  366 + try:
  367 + ulimit.run()
  368 + ulimit_value = ulimit.flux_ulimit()
  369 + except:
  370 + if self._logTerse():
  371 + self._log("Upper limit flux calculation failed.s\n")
  372 + ulimit_value = -1.0
  373 +
  374 + # Return upper limit
  375 + return ulimit_value
  376 +
  377 + def _bin_observation(self, obs):
  378 + """
  379 + Bin an observation is a binned analysis was requested.
  380 +
  381 + Args:
  382 + obs: Observation container.
  383 +
  384 + Returns:
  385 + Observation container with a binned.
  386 + """
  387 + # Header
  388 + if self._logExplicit():
  389 + self._log.header3("Binning events")
  390 +
  391 + # Bin events
  392 + bin = ctools.ctbin(obs)
  393 + bin["usepnt"] = False
  394 + bin["ebinalg"] = "LOG"
  395 + bin["xref"] = self["xref"].real()
  396 + bin["yref"] = self["yref"].real()
  397 + bin["binsz"] = self["binsz"].real()
  398 + bin["nxpix"] = self["nxpix"].integer()
  399 + bin["nypix"] = self["nypix"].integer()
  400 + bin["enumbins"] = self["enumbins"].integer()
  401 + bin["emin"] = self["emin"].real()
  402 + bin["emax"] = self["emax"].real()
  403 + bin["coordsys"] = self["coordsys"].string()
  404 + bin["proj"] = self["proj"].string()
  405 + bin.run()
  406 +
  407 + # Header
  408 + if self._logExplicit():
  409 + self._log.header3("Creating exposure cube")
  410 +
  411 + # Create exposure cube
  412 + expcube = ctools.ctexpcube(obs)
  413 + expcube["incube"] = "NONE"
  414 + expcube["usepnt"] = False
  415 + expcube["ebinalg"] = "LOG"
  416 + expcube["xref"] = self["xref"].real()
  417 + expcube["yref"] = self["yref"].real()
  418 + expcube["binsz"] = self["binsz"].real()
  419 + expcube["nxpix"] = self["nxpix"].integer()
  420 + expcube["nypix"] = self["nypix"].integer()
  421 + expcube["enumbins"] = self["enumbins"].integer()
  422 + expcube["emin"] = self["emin"].real()
  423 + expcube["emax"] = self["emax"].real()
  424 + expcube["coordsys"] = self["coordsys"].string()
  425 + expcube["proj"] = self["proj"].string()
  426 + expcube.run()
  427 +
  428 + # Header
  429 + if self._logExplicit():
  430 + self._log.header3("Creating point spread function cube")
  431 +
  432 + # Create psf cube
  433 + psfcube = ctools.ctpsfcube(obs)
  434 + psfcube["incube"] = "NONE"
  435 + psfcube["usepnt"] = False
  436 + psfcube["ebinalg"] = "LOG"
  437 + psfcube["xref"] = self["xref"].real()
  438 + psfcube["yref"] = self["yref"].real()
  439 + psfcube["binsz"] = self["binsz"].real()
  440 + psfcube["nxpix"] = self["nxpix"].integer()
  441 + psfcube["nypix"] = self["nypix"].integer()
  442 + psfcube["enumbins"] = self["enumbins"].integer()
  443 + psfcube["emin"] = self["emin"].real()
  444 + psfcube["emax"] = self["emax"].real()
  445 + psfcube["coordsys"] = self["coordsys"].string()
  446 + psfcube["proj"] = self["proj"].string()
  447 + psfcube.run()
  448 +
  449 + # Check if we need to include energy dispersion
  450 + if self["edisp"].boolean():
  451 +
  452 + # Header
  453 + if self._logExplicit():
  454 + self._log.header3("Creating energy dispersion cube")
  455 +
  456 + # Create edisp cube
  457 + edispcube = ctools.ctedispcube(obs)
  458 + edispcube["incube"] = "NONE"
  459 + edispcube["usepnt"] = False
  460 + edispcube["ebinalg"] = "LOG"
  461 + edispcube["xref"] = self["xref"].real()
  462 + edispcube["yref"] = self["yref"].real()
  463 + edispcube["binsz"] = self["binsz"].real()
  464 + edispcube["nxpix"] = self["nxpix"].integer()
  465 + edispcube["nypix"] = self["nypix"].integer()
  466 + edispcube["enumbins"] = self["enumbins"].integer()
  467 + edispcube["emin"] = self["emin"].real()
  468 + edispcube["emax"] = self["emax"].real()
  469 + edispcube["coordsys"] = self["coordsys"].string()
  470 + edispcube["proj"] = self["proj"].string()
  471 + edispcube.run()
  472 +
  473 + # Header
  474 + if self._logExplicit():
  475 + self._log.header3("Creating background cube")
  476 +
  477 + # Create background cube
  478 + bkgcube = ctools.ctbkgcube(obs)
  479 + bkgcube["incube"] = "NONE"
  480 + bkgcube["usepnt"] = False
  481 + bkgcube["ebinalg"] = "LOG"
  482 + bkgcube["xref"] = self["xref"].real()
  483 + bkgcube["yref"] = self["yref"].real()
  484 + bkgcube["binsz"] = self["binsz"].real()
  485 + bkgcube["nxpix"] = self["nxpix"].integer()
  486 + bkgcube["nypix"] = self["nypix"].integer()
  487 + bkgcube["enumbins"] = self["enumbins"].integer()
  488 + bkgcube["emin"] = self["emin"].real()
  489 + bkgcube["emax"] = self["emax"].real()
  490 + bkgcube["coordsys"] = self["coordsys"].string()
  491 + bkgcube["proj"] = self["proj"].string()
  492 + bkgcube.run()
  493 +
  494 + # Retrieve a new oberservation container
  495 + new_obs = bin.obs().copy()
  496 +
  497 + # Get new models
  498 + models = bkgcube.models()
  499 +
  500 + # Set stacked response
  501 + if self["edisp"].boolean():
  502 + new_obs[0].response(expcube.expcube(),
  503 + psfcube.psfcube(),
  504 + edispcube.edispcube(),
  505 + bkgcube.bkgcube())
  506 + else:
  507 + new_obs[0].response(expcube.expcube(),
  508 + psfcube.psfcube(),
  509 + bkgcube.bkgcube())
  510 +
  511 + # Fix background models if required
  512 + if self["fix_bkg"].boolean():
  513 + for model in models:
  514 + if model.classname() != "GModelSky":
  515 + for par in model:
  516 + par.fix()
  517 +
  518 + # Set models for new oberservation container
  519 + new_obs.models(models)
  520 +
  521 + # Return new oberservation container
  522 + return new_obs
  523 +
  524 +
  525 + # Public methods
  526 + def run(self):
  527 + """
  528 + Run the script.
  529 + """
  530 + # Switch screen logging on in debug mode
  531 + if self._logDebug():
  532 + self._log.cout(True)
  533 +
  534 + # Get parameters
  535 + self._get_parameters()
  536 +
  537 + # Write observation into logger
  538 + if self._logTerse():
  539 + self._log("\n")
  540 + self._log.header1("Observation")
  541 + self._log(str(self._obs))
  542 + self._log("\n")
  543 +
  544 + # Adjust model parameters dependent on user parameters
  545 + self._adjust_model_pars()
  546 +
  547 + # Write header
  548 + if self._logTerse():
  549 + self._log("\n")
  550 + self._log.header1("Generate lightcurve")
  551 +
  552 + # Initialise list of result dictionaries
  553 + results = []
  554 +
  555 + # Get source parameters
  556 + pars = self._get_free_par_names()
  557 +
  558 + # Loop over time bins
  559 + for i in range(self._tbins.size()):
339 560
340 # Get time boundaries 561 # Get time boundaries
341 tmin = self._tbins.tstart(i) 562 tmin = self._tbins.tstart(i)
342 tmax = self._tbins.tstop(i) 563 tmax = self._tbins.tstop(i)
343 564
  565 + # Write time bin into header
  566 + if self._logTerse():
  567 + self._log.header2("MJD "+
  568 + str(tmin.mjd())+"-"+
  569 + str(tmax.mjd()))
  570 +
344 # Compute time bin center and time width 571 # Compute time bin center and time width
345 twidth = 0.5 * (tmax - tmin) # in seconds 572 twidth = 0.5 * (tmax - tmin) # in seconds
346 tmean = tmin + twidth 573 tmean = tmin + twidth
347 574
348 - # Store time as MJD  
349 - MJD[i] = tmean.mjd()  
350 - e_MJD[i] = twidth / gammalib.sec_in_day # in days 575 + # Initialise result dictionary
  576 + result = {'mjd': tmean.mjd(),
  577 + 'e_mjd': twidth / gammalib.sec_in_day,
  578 + 'ts': 0.0,
  579 + 'ulimit': 0.0,
  580 + 'pars': pars,
  581 + 'values': {}}
351 582
352 # Log information 583 # Log information
353 if self._logExplicit(): 584 if self._logExplicit():
@@ -355,8 +586,8 @@ class cslightcrv(ctools.cscript): @@ -355,8 +586,8 @@ class cslightcrv(ctools.cscript):
355 586
356 # Select events 587 # Select events
357 select = ctools.ctselect(self._obs) 588 select = ctools.ctselect(self._obs)
358 - select["emin"] = self._emin  
359 - select["emax"] = self._emax 589 + select["emin"] = self["emin"].real()
  590 + select["emax"] = self["emax"].real()
360 select["tmin"] = tmin.convert(select._time_reference()) 591 select["tmin"] = tmin.convert(select._time_reference())
361 select["tmax"] = tmax.convert(select._time_reference()) 592 select["tmax"] = tmax.convert(select._time_reference())
362 select["rad"] = "UNDEFINED" 593 select["rad"] = "UNDEFINED"
@@ -367,233 +598,86 @@ class cslightcrv(ctools.cscript): @@ -367,233 +598,86 @@ class cslightcrv(ctools.cscript):
367 # Retrieve observation 598 # Retrieve observation
368 obs = select.obs() 599 obs = select.obs()
369 600
370 - # Binned analysis  
371 - if self._binned:  
372 -  
373 - # Header  
374 - if self._logTerse():  
375 - self._log.header3("Binning events")  
376 -  
377 - # Bin events  
378 - bin = ctools.ctbin(select.obs())  
379 - bin["usepnt"] = False  
380 - bin["ebinalg"] = "LOG"  
381 - bin["xref"] = self._xref  
382 - bin["yref"] = self._yref  
383 - bin["binsz"] = self._binsz  
384 - bin["nxpix"] = self._nxpix  
385 - bin["nypix"] = self._nypix  
386 - bin["enumbins"] = self._ebins  
387 - bin["emin"] = self._emin  
388 - bin["emax"] = self._emax  
389 - bin["coordsys"] = self._coordsys  
390 - bin["proj"] = self._proj  
391 - bin.run()  
392 -  
393 - # Header  
394 - if self._logTerse():  
395 - self._log.header3("Creating exposure cube")  
396 -  
397 - # Create exposure cube  
398 - expcube = ctools.ctexpcube(select.obs())  
399 - expcube["incube"] = "NONE"  
400 - expcube["usepnt"] = False  
401 - expcube["ebinalg"] = "LOG"  
402 - expcube["xref"] = self._xref  
403 - expcube["yref"] = self._yref  
404 - expcube["binsz"] = self._binsz  
405 - expcube["nxpix"] = self._nxpix  
406 - expcube["nypix"] = self._nypix  
407 - expcube["enumbins"] = self._ebins  
408 - expcube["emin"] = self._emin  
409 - expcube["emax"] = self._emax  
410 - expcube["coordsys"] = self._coordsys  
411 - expcube["proj"] = self._proj  
412 - expcube.run()  
413 -  
414 - # Header  
415 - if self._logTerse():  
416 - self._log.header3("Creating point spread function cube")  
417 -  
418 - # Create psf cube  
419 - psfcube = ctools.ctpsfcube(select.obs())  
420 - psfcube["incube"] = "NONE"  
421 - psfcube["usepnt"] = False  
422 - psfcube["ebinalg"] = "LOG"  
423 - psfcube["xref"] = self._xref  
424 - psfcube["yref"] = self._yref  
425 - psfcube["binsz"] = self._binsz  
426 - psfcube["nxpix"] = self._nxpix  
427 - psfcube["nypix"] = self._nypix  
428 - psfcube["enumbins"] = self._ebins  
429 - psfcube["emin"] = self._emin  
430 - psfcube["emax"] = self._emax  
431 - psfcube["coordsys"] = self._coordsys  
432 - psfcube["proj"] = self._proj  
433 - psfcube.run()  
434 -  
435 - # Check if we need to include energy dispersion  
436 - if self._edisp:  
437 -  
438 - # Header  
439 - if self._logTerse():  
440 - self._log.header3("Creating energy dispersion cube")  
441 -  
442 - # Create edisp cube  
443 - edispcube = ctools.ctedispcube(select.obs())  
444 - edispcube["incube"] = "NONE"  
445 - edispcube["usepnt"] = False  
446 - edispcube["ebinalg"] = "LOG"  
447 - edispcube["xref"] = self._xref  
448 - edispcube["yref"] = self._yref  
449 - edispcube["binsz"] = self._binsz  
450 - edispcube["nxpix"] = self._nxpix  
451 - edispcube["nypix"] = self._nypix  
452 - edispcube["enumbins"] = self._ebins  
453 - edispcube["emin"] = self._emin  
454 - edispcube["emax"] = self._emax  
455 - edispcube["coordsys"] = self._coordsys  
456 - edispcube["proj"] = self._proj  
457 - edispcube.run()  
458 -  
459 - # Header  
460 - if self._logTerse():  
461 - self._log.header3("Creating background cube")  
462 -  
463 - # Create background cube  
464 - bkgcube = ctools.ctbkgcube(select.obs())  
465 - bkgcube["incube"] = "NONE"  
466 - bkgcube["usepnt"] = False  
467 - bkgcube["ebinalg"] = "LOG"  
468 - bkgcube["xref"] = self._xref  
469 - bkgcube["yref"] = self._yref  
470 - bkgcube["binsz"] = self._binsz  
471 - bkgcube["nxpix"] = self._nxpix  
472 - bkgcube["nypix"] = self._nypix  
473 - bkgcube["enumbins"] = self._ebins  
474 - bkgcube["emin"] = self._emin  
475 - bkgcube["emax"] = self._emax  
476 - bkgcube["coordsys"] = self._coordsys  
477 - bkgcube["proj"] = self._proj  
478 - bkgcube.run()  
479 -  
480 - # Set new binned observation  
481 - obs = bin.obs()  
482 -  
483 - # Get new models  
484 - models = bkgcube.models()  
485 -  
486 - # Set precomputed binned response  
487 - if self._edisp:  
488 - obs[0].response(expcube.expcube(), psfcube.psfcube(),  
489 - edispcube.edispcube(), bkgcube.bkgcube())  
490 - else:  
491 - obs[0].response(expcube.expcube(), psfcube.psfcube(),  
492 - bkgcube.bkgcube())  
493 -  
494 - # Fix background models if required  
495 - if self._fix_bkg:  
496 - for model in models:  
497 - if not model.classname() == "GModelSky":  
498 - for par in model:  
499 - par.fix()  
500 -  
501 - # Set new models to binned observation  
502 - obs.models(models) 601 + # If a stacked analysis is requested then bin the events
  602 + # and compute the stacked response functions and setup
  603 + # an observation container with a single stacked observation.
  604 + if self._stacked:
  605 + obs = self._bin_observation(obs)
503 606
504 # Header 607 # Header
505 - if self._logTerse():  
506 - self._log.header3("Performing fit") 608 + if self._logExplicit():
  609 + self._log.header3("Fitting the data")
507 610
508 - # Likelihood 611 + # Do maximum likelihood model fitting
509 like = ctools.ctlike(obs) 612 like = ctools.ctlike(obs)
510 - like["edisp"] = self._edisp 613 + like["edisp"] = self["edisp"].boolean()
511 like.run() 614 like.run()
512 615
513 # Skip bin if no event was present 616 # Skip bin if no event was present
514 if like.obs().logL() == 0.0: 617 if like.obs().logL() == 0.0:
515 618
516 - # Log information 619 + # Signal skipping of bin
517 if self._logTerse(): 620 if self._logTerse():
518 - self._log("No event in this time bin. Bin is skipped\n")  
519 -  
520 - # Set all values to 0  
521 - for col in columns:  
522 - col[i] = 0.0  
523 - TSvalues[i] = 0.0  
524 - ulim_values[i] = 0.0  
525 - continue 621 + self._log(gammalib.parformat("Warning"))
  622 + self._log("No event in this time bin, skip bin.\n")
526 623
527 - # Get results  
528 - fitted_models = like.obs().models()  
529 - source = fitted_models[self._srcname] 624 + # Set all results to 0
  625 + for par in pars:
  626 + result['values'][par] = 0.0
  627 + result['values']["e_"+par] = 0.0
530 628
531 - # Calculate Upper Limit  
532 - ulimit_value = -1.0  
533 - if self._calc_ulimit: 629 + # Append result
  630 + results.append(result)
534 631
535 - # Logging information  
536 - if self._logTerse():  
537 - self._log.header3("Computing upper limit")  
538 -  
539 - # Create upper limit object  
540 - ulimit = ctools.ctulimit(like.obs())  
541 - ulimit["srcname"] = self._srcname  
542 - ulimit["eref"] = 1.0  
543 -  
544 - # Try to run upper limit and catch exceptions  
545 - try:  
546 - ulimit.run()  
547 - ulimit_value = ulimit.flux_ulimit()  
548 - except:  
549 - if self._logTerse():  
550 - self._log("Upper limit calculation failed\n")  
551 - ulimit_value = -1.0  
552 -  
553 - # Get TS value  
554 - TS = -1.0  
555 - if self._calc_ts:  
556 - TS = source.ts()  
557 -  
558 - # Set values for storage  
559 - TSvalues[i] = TS  
560 -  
561 - # Set FITS column values  
562 - for col in columns:  
563 - if "e_" == col.name()[:2]:  
564 - col[i] = source.spectral()[col.name()[2:]].error()  
565 - else:  
566 - col[i] = source.spectral()[col.name()].value()  
567 -  
568 - # Store upper limit value if available  
569 - if ulimit_value > 0.0:  
570 - ulim_values[i] = ulimit_value 632 + # Continue with next time bin
  633 + continue
571 634
572 - # Log information  
573 - if self._logExplicit():  
574 - self._log.header3("Results of bin "+str(i)+": MJD "+str(tmin.mjd())+"-"+str(tmax.mjd()))  
575 - for col in columns:  
576 - if "e_" == col.name()[:2]:  
577 - continue  
578 - value = source.spectral()[col.name()].value()  
579 - error = source.spectral()[col.name()].error()  
580 - unit = source.spectral()[col.name()].unit()  
581 - self._log(" > "+col.name()+": "+str(value)+" +- "+str(error)+" "+unit+"\n")  
582 - if self._calc_ts and TSvalues[i] > 0.0:  
583 - self._log(" > TS = "+str(TS)+" \n")  
584 - if self._calc_ulimit and ulim_values[i] > 0.0:  
585 - self._log(" > UL = "+str(ulim_values[i])+" [ph/cm2/s]")  
586 - self._log("\n") 635 + # Retrieve model fitting results for source of interest
  636 + source = like.obs().models()[self._srcname]
587 637
588 - # Append filles columns to fits table  
589 - table.append(MJD)  
590 - table.append(e_MJD)  
591 - for col in columns:  
592 - table.append(col)  
593 - table.append(TSvalues)  
594 - table.append(ulim_values) 638 + # Extract parameter values
  639 + for par in pars:
  640 + result['values'][par] = source.spectral()[par].value()
  641 + result['values']["e_"+par] = source.spectral()[par].error()
595 642
596 - # Create the FITS file now 643 + # Calculate upper limit (-1 if not computed)
  644 + ulimit_value = self._compute_ulimit(like.obs())
  645 + if ulimit_value > 0.0:
  646 + result['ulimit'] = ulimit_value
  647 +
  648 + # Extract Test Statistic value
  649 + if self["calc_ts"].boolean():
  650 + result['ts'] = source.ts()
  651 +
  652 + # Append result to list of dictionaries
  653 + results.append(result)
  654 +
  655 + # Log results for this time bin
  656 + if self._logNormal():
  657 + self._log.header3("Results")
  658 + pars = self._get_free_par_names()
  659 + for par in pars:
  660 + value = source.spectral()[par].value()
  661 + error = source.spectral()[par].error()
  662 + unit = source.spectral()[par].unit()
  663 + self._log(gammalib.parformat(par))
  664 + self._log(str(value))
  665 + self._log(" +/- ")
  666 + self._log(str(error))
  667 + self._log(" ")
  668 + self._log(unit)
  669 + self._log("\n")
  670 + if result['ulimit'] > 0.0:
  671 + self._log(gammalib.parformat("Upper flux limit"))
  672 + self._log(str(result['ulimit'])+" ph/cm2/s\n")
  673 + if self["calc_ts"].boolean():
  674 + self._log(gammalib.parformat("Test Statistic"))
  675 + self._log(str(result['ts'])+"\n")
  676 +
  677 + # Create FITS table from results
  678 + table = self._create_fits_table(results)
  679 +
  680 + # Create FITS file and append FITS table to FITS file
597 self._fits = gammalib.GFits() 681 self._fits = gammalib.GFits()
598 self._fits.append(table) 682 self._fits.append(table)
599 683
@@ -604,6 +688,9 @@ class cslightcrv(ctools.cscript): @@ -604,6 +688,9 @@ class cslightcrv(ctools.cscript):
604 """ 688 """
605 Execute the script. 689 Execute the script.
606 """ 690 """
  691 + # Open logfile
  692 + self._logFileOpen()
  693 +
607 # Read ahead output parameters 694 # Read ahead output parameters
608 self._read_ahead(True) 695 self._read_ahead(True)
609 696
@@ -618,35 +705,37 @@ class cslightcrv(ctools.cscript): @@ -618,35 +705,37 @@ class cslightcrv(ctools.cscript):
618 705
619 def save(self): 706 def save(self):
620 """ 707 """
621 - Save lightcurve. 708 + Save light curve.
622 """ 709 """
623 # Write header 710 # Write header
624 if self._logTerse(): 711 if self._logTerse():
625 - self._log("\n")  
626 - self._log.header1("Save lightcurve") 712 + self._log('\n')
  713 + self._log.header1('Save light curve')
627 714
628 - # Get outmap parameter  
629 - self._outfile = self["outfile"].filename() 715 + # Get light curve filename
  716 + outfile = self["outfile"].filename()
630 717
631 # Continue only filename and residual map are valid 718 # Continue only filename and residual map are valid
632 - if self._outfile != "NONE" and self._fits != None: 719 + if self._fits != None:
633 720
634 # Log file name 721 # Log file name
635 if self._logTerse(): 722 if self._logTerse():
636 - self._log("Save lightcurve into \""+self._outfile+"\".\n") 723 + self._log(gammalib.parformat("Light curve file"))
  724 + self._log(outfile.url())
  725 + self._log("\n")
637 726
638 # Save spectrum 727 # Save spectrum
639 - self._fits.saveto(self._outfile, self._clobber) 728 + self._fits.saveto(outfile, self._clobber())
640 729
641 # Return 730 # Return
642 return 731 return
643 732
644 def lightcurve(self): 733 def lightcurve(self):
645 """ 734 """
646 - Return lightcurve FITS file. 735 + Return light curve FITS file.
647 736
648 Returns: 737 Returns:
649 - FITS file containing lightcurve. 738 + FITS file containing light curve.
650 """ 739 """
651 # Return 740 # Return
652 return self._fits 741 return self._fits
@@ -670,8 +759,5 @@ if __name__ == '__main__': @@ -670,8 +759,5 @@ if __name__ == '__main__':
670 # Create instance of application 759 # Create instance of application
671 app = cslightcrv(sys.argv) 760 app = cslightcrv(sys.argv)
672 761
673 - # Open logfile  
674 - app._logFileOpen()  
675 -  
676 # Execute application 762 # Execute application
677 app.execute() 763 app.execute()
cscripts/csmodelinfo.par
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 # File: csmodelinfo.par # 7 # File: csmodelinfo.par #
8 # Version: 1.1.0 # 8 # Version: 1.1.0 #
9 # # 9 # #
10 -# Author: Juergen Knoedlseder #  
11 -# Jurgen.Knodlseder@irap.omp.eu #  
12 -# IRAP # 10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
13 # # 13 # #
14 # Purpose: Parameter file for the csmodelinfo script # 14 # Purpose: Parameter file for the csmodelinfo script #
15 # # 15 # #
cscripts/csmodelinfo.py
@@ -36,7 +36,7 @@ class csmodelinfo(ctools.cscript): @@ -36,7 +36,7 @@ class csmodelinfo(ctools.cscript):
36 with DS9. 36 with DS9.
37 """ 37 """
38 38
39 - # Constructors and destructors 39 + # Constructor
40 def __init__(self, *argv): 40 def __init__(self, *argv):
41 """ 41 """
42 Constructor. 42 Constructor.
@@ -47,7 +47,7 @@ class csmodelinfo(ctools.cscript): @@ -47,7 +47,7 @@ class csmodelinfo(ctools.cscript):
47 47
48 # Initialise class members 48 # Initialise class members
49 self._models = gammalib.GModels() 49 self._models = gammalib.GModels()
50 - self._ds9file = "NONE" 50 + self._ds9file = gammalib.GFilename("NONE")
51 self._pnt_type = "" 51 self._pnt_type = ""
52 self._pnt_mark_size = 12 52 self._pnt_mark_size = 12
53 self._show_labels = True 53 self._show_labels = True
@@ -59,27 +59,11 @@ class csmodelinfo(ctools.cscript): @@ -59,27 +59,11 @@ class csmodelinfo(ctools.cscript):
59 self._show_ext_type = True 59 self._show_ext_type = True
60 self._free_color = "green" 60 self._free_color = "green"
61 self._fixed_color = "magenta" 61 self._fixed_color = "magenta"
62 - self._read_ahead = False  
63 62
64 - # Initialise application  
65 - if len(argv) == 0:  
66 - ctools.cscript.__init__(self, self._name, self._version)  
67 - elif len(argv) == 1:  
68 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
69 - else:  
70 - raise TypeError("Invalid number of arguments given.") 63 + # Initialise application by calling the appropriate class
  64 + # constructor.
  65 + self._init_cscript(argv)
71 66
72 - # Set logger properties  
73 - self._log_header()  
74 - self._log.date(True)  
75 -  
76 - # Return  
77 - return  
78 -  
79 - def __del__(self):  
80 - """  
81 - Destructor.  
82 - """  
83 # Return 67 # Return
84 return 68 return
85 69
@@ -106,7 +90,7 @@ class csmodelinfo(ctools.cscript): @@ -106,7 +90,7 @@ class csmodelinfo(ctools.cscript):
106 self._fixed_color = self["fixed_color"].string() 90 self._fixed_color = self["fixed_color"].string()
107 91
108 # Read ahead DS9 filename 92 # Read ahead DS9 filename
109 - if self._read_ahead: 93 + if self._read_ahead():
110 self._ds9file = self["ds9file"].filename() 94 self._ds9file = self["ds9file"].filename()
111 95
112 # Write input parameters into logger 96 # Write input parameters into logger
@@ -500,8 +484,11 @@ class csmodelinfo(ctools.cscript): @@ -500,8 +484,11 @@ class csmodelinfo(ctools.cscript):
500 """ 484 """
501 Execute the script. 485 Execute the script.
502 """ 486 """
503 - # Set read ahead flag  
504 - self._read_ahead = True 487 + # Open logfile
  488 + self._logFileOpen()
  489 +
  490 + # Read ahead output parameters
  491 + self._read_ahead(True)
505 492
506 # Run the script 493 # Run the script
507 self.run() 494 self.run()
@@ -521,8 +508,5 @@ if __name__ == '__main__': @@ -521,8 +508,5 @@ if __name__ == '__main__':
521 # Create instance of application 508 # Create instance of application
522 app = csmodelinfo(sys.argv) 509 app = csmodelinfo(sys.argv)
523 510
524 - # Open logfile  
525 - app._logFileOpen()  
526 -  
527 # Execute application 511 # Execute application
528 app.execute() 512 app.execute()
cscripts/csmodelmerge.par
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 # File: csmodelmerge.par # 7 # File: csmodelmerge.par #
8 # Version: 1.1.0 # 8 # Version: 1.1.0 #
9 # # 9 # #
10 -# Author: Juergen Knoedlseder #  
11 -# Jurgen.Knodlseder@irap.omp.eu #  
12 -# IRAP # 10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
13 # # 13 # #
14 # Purpose: Parameter file for the csmodelmerge script # 14 # Purpose: Parameter file for the csmodelmerge script #
15 # # 15 # #
cscripts/csmodelmerge.py
@@ -35,7 +35,7 @@ class csmodelmerge(ctools.cscript): @@ -35,7 +35,7 @@ class csmodelmerge(ctools.cscript):
35 a single model definition XML file. 35 a single model definition XML file.
36 """ 36 """
37 37
38 - # Constructors and destructors 38 + # Constructor
39 def __init__(self, *argv): 39 def __init__(self, *argv):
40 """ 40 """
41 Constructor. 41 Constructor.
@@ -47,28 +47,11 @@ class csmodelmerge(ctools.cscript): @@ -47,28 +47,11 @@ class csmodelmerge(ctools.cscript):
47 # Initialise class members 47 # Initialise class members
48 self._files = None 48 self._files = None
49 self._models = gammalib.GModels() 49 self._models = gammalib.GModels()
50 - self._outmodel = "NONE"  
51 - self._read_ahead = False  
52 -  
53 - # Initialise application  
54 - if len(argv) == 0:  
55 - ctools.cscript.__init__(self, self._name, self._version)  
56 - elif len(argv) == 1:  
57 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
58 - else:  
59 - raise TypeError("Invalid number of arguments given.")  
60 -  
61 - # Set logger properties  
62 - self._log_header()  
63 - self._log.date(True)  
64 50
65 - # Return  
66 - return 51 + # Initialise application by calling the appropriate class
  52 + # constructor.
  53 + self._init_cscript(argv)
67 54
68 - def __del__(self):  
69 - """  
70 - Destructor.  
71 - """  
72 # Return 55 # Return
73 return 56 return
74 57
@@ -105,8 +88,8 @@ class csmodelmerge(ctools.cscript): @@ -105,8 +88,8 @@ class csmodelmerge(ctools.cscript):
105 raise RuntimeError(msg) 88 raise RuntimeError(msg)
106 89
107 # Read ahead output filename 90 # Read ahead output filename
108 - if self._read_ahead:  
109 - self.outmodel = self["outmodel"].filename() 91 + if self._read_ahead():
  92 + self["outmodel"].filename()
110 93
111 # Write input parameters into logger 94 # Write input parameters into logger
112 if self._logTerse(): 95 if self._logTerse():
@@ -178,16 +161,16 @@ class csmodelmerge(ctools.cscript): @@ -178,16 +161,16 @@ class csmodelmerge(ctools.cscript):
178 self._log.header1("Save models") 161 self._log.header1("Save models")
179 162
180 # Get output filename in case it was not read ahead 163 # Get output filename in case it was not read ahead
181 - self._outmodel = self["outmodel"].filename() 164 + outmodel = self["outmodel"].filename()
182 165
183 # Log filename 166 # Log filename
184 if self._logTerse(): 167 if self._logTerse():
185 self._log(gammalib.parformat("Model definition XML file")) 168 self._log(gammalib.parformat("Model definition XML file"))
186 - self._log(self._outmodel.url()) 169 + self._log(outmodel.url())
187 self._log("\n") 170 self._log("\n")
188 171
189 # Save models 172 # Save models
190 - self._models.save(self._outmodel) 173 + self._models.save(outmodel)
191 174
192 # Return 175 # Return
193 return 176 return
@@ -196,8 +179,11 @@ class csmodelmerge(ctools.cscript): @@ -196,8 +179,11 @@ class csmodelmerge(ctools.cscript):
196 """ 179 """
197 Execute the script. 180 Execute the script.
198 """ 181 """
199 - # Set read ahead flag  
200 - self._read_ahead = True 182 + # Open logfile
  183 + self._logFileOpen()
  184 +
  185 + # Read ahead output parameters
  186 + self._read_ahead(True)
201 187
202 # Run the script 188 # Run the script
203 self.run() 189 self.run()
@@ -217,8 +203,5 @@ if __name__ == '__main__': @@ -217,8 +203,5 @@ if __name__ == '__main__':
217 # Create instance of application 203 # Create instance of application
218 app = csmodelmerge(sys.argv) 204 app = csmodelmerge(sys.argv)
219 205
220 - # Open logfile  
221 - app._logFileOpen()  
222 -  
223 # Execute application 206 # Execute application
224 app.execute() 207 app.execute()
cscripts/csobs2caldb.par
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 # File: csobs2caldb.par # 7 # File: csobs2caldb.par #
8 # Version: 1.1.0 # 8 # Version: 1.1.0 #
9 # # 9 # #
10 -# Author: Juergen Knoedlseder #  
11 -# Jurgen.Knodlseder@irap.omp.eu #  
12 -# IRAP # 10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
13 # # 13 # #
14 # Purpose: Parameter file for the csobs2caldb script # 14 # Purpose: Parameter file for the csobs2caldb script #
15 # # 15 # #
cscripts/csobs2caldb.py
@@ -40,7 +40,7 @@ class csobs2caldb(ctools.cscript): @@ -40,7 +40,7 @@ class csobs2caldb(ctools.cscript):
40 index of any observation using the hidden "index" parameter. 40 index of any observation using the hidden "index" parameter.
41 """ 41 """
42 42
43 - # Constructors and destructors 43 + # Constructor
44 def __init__(self, *argv): 44 def __init__(self, *argv):
45 """ 45 """
46 Constructor. 46 Constructor.
@@ -59,28 +59,13 @@ class csobs2caldb(ctools.cscript): @@ -59,28 +59,13 @@ class csobs2caldb(ctools.cscript):
59 self._base_dir = "" 59 self._base_dir = ""
60 self._cal_dir = "" 60 self._cal_dir = ""
61 61
62 - # Initialise application  
63 - if len(argv) == 0:  
64 - ctools.cscript.__init__(self, self._name, self._version)  
65 - elif len(argv) == 1:  
66 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
67 - else:  
68 - raise TypeError("Invalid number of arguments given.")  
69 -  
70 - # Set logger properties  
71 - self._log_header()  
72 - self._log.date(True) 62 + # Initialise application by calling the appropriate class
  63 + # constructor.
  64 + self._init_cscript(argv)
73 65
74 # Return 66 # Return
75 return 67 return
76 68
77 - def __del__(self):  
78 - """  
79 - Destructor.  
80 - """  
81 - # Return  
82 - return  
83 -  
84 69
85 # Private methods 70 # Private methods
86 def _get_parameters(self): 71 def _get_parameters(self):
@@ -395,6 +380,9 @@ class csobs2caldb(ctools.cscript): @@ -395,6 +380,9 @@ class csobs2caldb(ctools.cscript):
395 """ 380 """
396 Execute the script. 381 Execute the script.
397 """ 382 """
  383 + # Open logfile
  384 + self._logFileOpen()
  385 +
398 # Run the script 386 # Run the script
399 self.run() 387 self.run()
400 388
@@ -413,8 +401,5 @@ if __name__ == '__main__': @@ -413,8 +401,5 @@ if __name__ == '__main__':
413 # Create instance of application 401 # Create instance of application
414 app = csobs2caldb(sys.argv) 402 app = csobs2caldb(sys.argv)
415 403
416 - # Open logfile  
417 - app._logFileOpen()  
418 -  
419 # Execute application 404 # Execute application
420 app.execute() 405 app.execute()
cscripts/csobsdef.py
@@ -72,7 +72,7 @@ class csobsdef(ctools.cscript): @@ -72,7 +72,7 @@ class csobsdef(ctools.cscript):
72 IRF in the "dummy" calibration database. 72 IRF in the "dummy" calibration database.
73 """ 73 """
74 74
75 - # Constructors and destructors 75 + # Constructor
76 def __init__(self, *argv): 76 def __init__(self, *argv):
77 """ 77 """
78 Constructor. 78 Constructor.
@@ -85,31 +85,14 @@ class csobsdef(ctools.cscript): @@ -85,31 +85,14 @@ class csobsdef(ctools.cscript):
85 self._obs = gammalib.GObservations() 85 self._obs = gammalib.GObservations()
86 self._inpnt = "" 86 self._inpnt = ""
87 self._tmin = 0.0 87 self._tmin = 0.0
88 - self._outobs = "NONE"  
89 self._chatter = 2 88 self._chatter = 2
90 self._clobber = True 89 self._clobber = True
91 self._debug = False 90 self._debug = False
92 - self._read_ahead = False  
93 91
94 - # Initialise application  
95 - if len(argv) == 0:  
96 - ctools.cscript.__init__(self, self._name, self._version)  
97 - elif len(argv) ==1:  
98 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
99 - else:  
100 - raise TypeError("Invalid number of arguments given.") 92 + # Initialise application by calling the appropriate class
  93 + # constructor.
  94 + self._init_cscript(argv)
101 95
102 - # Set logger properties  
103 - self._log_header()  
104 - self._log.date(True)  
105 -  
106 - # Return  
107 - return  
108 -  
109 - def __del__(self):  
110 - """  
111 - Destructor.  
112 - """  
113 # Return 96 # Return
114 return 97 return
115 98
@@ -123,8 +106,8 @@ class csobsdef(ctools.cscript): @@ -123,8 +106,8 @@ class csobsdef(ctools.cscript):
123 self._inpnt = self["inpnt"].filename() 106 self._inpnt = self["inpnt"].filename()
124 107
125 # Read ahead parameters 108 # Read ahead parameters
126 - if self._read_ahead:  
127 - self._outobs = self["outobs"].filename() 109 + if self._read_ahead():
  110 + self["outobs"].filename()
128 111
129 # Set some fixed parameters 112 # Set some fixed parameters
130 self._chatter = self["chatter"].integer() 113 self._chatter = self["chatter"].integer()
@@ -347,19 +330,19 @@ class csobsdef(ctools.cscript): @@ -347,19 +330,19 @@ class csobsdef(ctools.cscript):
347 self._log.header1("Save observation definition XML file") 330 self._log.header1("Save observation definition XML file")
348 331
349 # Get output filename in case it was not read ahead 332 # Get output filename in case it was not read ahead
350 - self._outobs = self["outobs"].filename() 333 + outobs = self["outobs"].filename()
351 334
352 # Check if observation definition XML file is valid 335 # Check if observation definition XML file is valid
353 - if self._outobs != "NONE": 336 + if outobs.url() != "NONE":
354 337
355 # Log filename 338 # Log filename
356 if self._logTerse(): 339 if self._logTerse():
357 self._log(gammalib.parformat("Observation XML file")) 340 self._log(gammalib.parformat("Observation XML file"))
358 - self._log(self._outobs.url()) 341 + self._log(outobs.url())
359 self._log("\n") 342 self._log("\n")
360 343
361 # Save observation definition XML file 344 # Save observation definition XML file
362 - self._obs.save(self._outobs) 345 + self._obs.save(outobs)
363 346
364 # Return 347 # Return
365 return 348 return
@@ -368,8 +351,11 @@ class csobsdef(ctools.cscript): @@ -368,8 +351,11 @@ class csobsdef(ctools.cscript):
368 """ 351 """
369 Execute the script. 352 Execute the script.
370 """ 353 """
371 - # Set read ahead flag  
372 - self._read_ahead = True 354 + # Open logfile
  355 + self._logFileOpen()
  356 +
  357 + # Read ahead output parameters
  358 + self._read_ahead(True)
373 359
374 # Run the script 360 # Run the script
375 self.run() 361 self.run()
@@ -389,8 +375,5 @@ if __name__ == '__main__': @@ -389,8 +375,5 @@ if __name__ == '__main__':
389 # Create instance of application 375 # Create instance of application
390 app = csobsdef(sys.argv) 376 app = csobsdef(sys.argv)
391 377
392 - # Open logfile  
393 - app._logFileOpen()  
394 -  
395 # Execute application 378 # Execute application
396 app.execute() 379 app.execute()
cscripts/csobsinfo.par
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 # File: csobsinfo.par # 7 # File: csobsinfo.par #
8 # Version: 1.1.0 # 8 # Version: 1.1.0 #
9 # # 9 # #
10 -# Author: Juergen Knoedlseder #  
11 -# Jurgen.Knodlseder@irap.omp.eu #  
12 -# IRAP # 10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
13 # # 13 # #
14 # Purpose: Parameter file for the csobsinfo script # 14 # Purpose: Parameter file for the csobsinfo script #
15 # # 15 # #
cscripts/csobsinfo.py
@@ -31,7 +31,7 @@ class csobsinfo(ctools.cscript): @@ -31,7 +31,7 @@ class csobsinfo(ctools.cscript):
31 Shows the content of an observation container. 31 Shows the content of an observation container.
32 """ 32 """
33 33
34 - # Constructors and destructors 34 + # Constructor
35 def __init__(self, *argv): 35 def __init__(self, *argv):
36 """ 36 """
37 Constructor. 37 Constructor.
@@ -43,7 +43,6 @@ class csobsinfo(ctools.cscript): @@ -43,7 +43,6 @@ class csobsinfo(ctools.cscript):
43 # Initialise class members 43 # Initialise class members
44 self._obj_dir = None 44 self._obj_dir = None
45 self._compute_offset = False 45 self._compute_offset = False
46 - self._ds9file = ""  
47 self._offsets = [] 46 self._offsets = []
48 self._zeniths = [] 47 self._zeniths = []
49 self._azimuths = [] 48 self._azimuths = []
@@ -51,36 +50,17 @@ class csobsinfo(ctools.cscript): @@ -51,36 +50,17 @@ class csobsinfo(ctools.cscript):
51 self._pnt_dec = [] 50 self._pnt_dec = []
52 self._ebounds = gammalib.GEbounds() 51 self._ebounds = gammalib.GEbounds()
53 self._gti = gammalib.GGti() 52 self._gti = gammalib.GGti()
54 - self._read_ahead = False  
55 - if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations):  
56 - self._obs = argv[0]  
57 - argv = argv[1:]  
58 - else:  
59 - self._obs = gammalib.GObservations()  
60 - self._obs.clear()  
61 53
62 - # Initialise application  
63 - if len(argv) == 0:  
64 - ctools.cscript.__init__(self, self._name, self._version)  
65 - elif len(argv) == 1:  
66 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
67 - else:  
68 - raise TypeError("Invalid number of arguments given.") 54 + # Initialise observation container from constructor arguments.
  55 + self._obs = self._set_input_obs(argv)
69 56
70 - # Set logger properties  
71 - self._log_header()  
72 - self._log.date(True) 57 + # Initialise application by calling the appropriate class
  58 + # constructor.
  59 + self._init_cscript(argv)
73 60
74 # Return 61 # Return
75 return 62 return
76 63
77 - def __del__(self):  
78 - """  
79 - Destructor.  
80 - """  
81 - # Return  
82 - return  
83 -  
84 64
85 # Private methods 65 # Private methods
86 def _get_parameters(self): 66 def _get_parameters(self):
@@ -103,8 +83,8 @@ class csobsinfo(ctools.cscript): @@ -103,8 +83,8 @@ class csobsinfo(ctools.cscript):
103 self._obj_dir.radec_deg(ra,dec) 83 self._obj_dir.radec_deg(ra,dec)
104 84
105 # Read ahead DS9 filename 85 # Read ahead DS9 filename
106 - if self._read_ahead:  
107 - self._ds9file = self["ds9file"].filename() 86 + if self._read_ahead():
  87 + self["ds9file"].filename()
108 88
109 # Write input parameters into logger 89 # Write input parameters into logger
110 if self._logTerse(): 90 if self._logTerse():
@@ -387,19 +367,19 @@ class csobsinfo(ctools.cscript): @@ -387,19 +367,19 @@ class csobsinfo(ctools.cscript):
387 self._log.header1("Save pointings in DS9 file") 367 self._log.header1("Save pointings in DS9 file")
388 368
389 # Get output filename in case it was not read ahead 369 # Get output filename in case it was not read ahead
390 - self._ds9file = self["ds9file"].filename() 370 + ds9file = self["ds9file"].filename()
391 371
392 # Check if DS9 file is valid 372 # Check if DS9 file is valid
393 - if self._ds9file != "NONE": 373 + if ds9file.url() != "NONE":
394 374
395 # Log filename 375 # Log filename
396 if self._logTerse(): 376 if self._logTerse():
397 self._log(gammalib.parformat("DS9 filename")) 377 self._log(gammalib.parformat("DS9 filename"))
398 - self._log(self._ds9file.url()) 378 + self._log(ds9file.url())
399 self._log("\n") 379 self._log("\n")
400 380
401 # Open file 381 # Open file
402 - f = open(self._ds9file.url(),"w") 382 + f = open(ds9file.url(),"w")
403 383
404 # Write coordinate system 384 # Write coordinate system
405 f.write("fk5\n") 385 f.write("fk5\n")
@@ -455,8 +435,11 @@ class csobsinfo(ctools.cscript): @@ -455,8 +435,11 @@ class csobsinfo(ctools.cscript):
455 """ 435 """
456 Execute the script. 436 Execute the script.
457 """ 437 """
458 - # Set read ahead flag  
459 - self._read_ahead = True 438 + # Open logfile
  439 + self._logFileOpen()
  440 +
  441 + # Read ahead output parameters
  442 + self._read_ahead(True)
460 443
461 # Run the script 444 # Run the script
462 self.run() 445 self.run()
@@ -476,8 +459,5 @@ if __name__ == '__main__': @@ -476,8 +459,5 @@ if __name__ == '__main__':
476 # Create instance of application 459 # Create instance of application
477 app = csobsinfo(sys.argv) 460 app = csobsinfo(sys.argv)
478 461
479 - # Open logfile  
480 - app._logFileOpen()  
481 -  
482 # Execute application 462 # Execute application
483 app.execute() 463 app.execute()
cscripts/cspull.py
@@ -38,7 +38,7 @@ class cspull(ctools.cscript): @@ -38,7 +38,7 @@ class cspull(ctools.cscript):
38 script behaves just as a regular ctool. 38 script behaves just as a regular ctool.
39 """ 39 """
40 40
41 - # Constructors and destructors 41 + # Constructor
42 def __init__(self, *argv): 42 def __init__(self, *argv):
43 """ 43 """
44 Constructor. 44 Constructor.
@@ -48,7 +48,6 @@ class cspull(ctools.cscript): @@ -48,7 +48,6 @@ class cspull(ctools.cscript):
48 self._version = "1.1.0" 48 self._version = "1.1.0"
49 49
50 # Initialise some members 50 # Initialise some members
51 - self._obs = None  
52 self._model = None 51 self._model = None
53 self._inmodel = None 52 self._inmodel = None
54 self._edisp = False 53 self._edisp = False
@@ -62,25 +61,13 @@ class cspull(ctools.cscript): @@ -62,25 +61,13 @@ class cspull(ctools.cscript):
62 self._proj = "TAN" 61 self._proj = "TAN"
63 self._log_clients = False 62 self._log_clients = False
64 63
65 - # Initialise application  
66 - if len(argv) == 0:  
67 - ctools.cscript.__init__(self, self._name, self._version)  
68 - elif len(argv) ==1:  
69 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
70 - else:  
71 - raise TypeError("Invalid number of arguments given.")  
72 -  
73 - # Set logger properties  
74 - self._log_header()  
75 - self._log.date(True) 64 + # Initialise observation container from constructor arguments.
  65 + self._obs = self._set_input_obs(argv)
76 66
77 - # Return  
78 - return 67 + # Initialise application by calling the appropriate class
  68 + # constructor.
  69 + self._init_cscript(argv)
79 70
80 - def __del__(self):  
81 - """  
82 - Destructor.  
83 - """  
84 # Return 71 # Return
85 return 72 return
86 73
@@ -310,10 +297,10 @@ class cspull(ctools.cscript): @@ -310,10 +297,10 @@ class cspull(ctools.cscript):
310 297
311 # Fit model 298 # Fit model
312 if self._profile: 299 if self._profile:
313 - models = _obs.models() 300 + models = self._obs.models()
314 for i in range(models.size()): 301 for i in range(models.size()):
315 model_name = models[i].name() 302 model_name = models[i].name()
316 - like = obsutils.cterror(_obs, model_name, 303 + like = obsutils.cterror(self._obs, model_name,
317 log=self._log_clients, 304 log=self._log_clients,
318 debug=self._debug, 305 debug=self._debug,
319 chatter=self._chatter) 306 chatter=self._chatter)
@@ -442,6 +429,9 @@ class cspull(ctools.cscript): @@ -442,6 +429,9 @@ class cspull(ctools.cscript):
442 """ 429 """
443 Execute the script. 430 Execute the script.
444 """ 431 """
  432 + # Open logfile
  433 + self._logFileOpen()
  434 +
445 # Run the script 435 # Run the script
446 self.run() 436 self.run()
447 437
@@ -467,8 +457,5 @@ if __name__ == '__main__': @@ -467,8 +457,5 @@ if __name__ == '__main__':
467 # Create instance of application 457 # Create instance of application
468 app = cspull(sys.argv) 458 app = cspull(sys.argv)
469 459
470 - # Open logfile  
471 - app._logFileOpen()  
472 -  
473 # Execute application 460 # Execute application
474 app.execute() 461 app.execute()
cscripts/csresmap.par
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 # File: csresmap.par # 7 # File: csresmap.par #
8 # Version: 1.1.0 # 8 # Version: 1.1.0 #
9 # # 9 # #
10 -# Author: Juergen Knoedlseder #  
11 -# Jurgen.Knodlseder@irap.omp.eu #  
12 -# IRAP # 10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
13 # # 13 # #
14 # Purpose: Parameter file for the csresmap script # 14 # Purpose: Parameter file for the csresmap script #
15 # # 15 # #
cscripts/csresmap.py
@@ -36,7 +36,7 @@ class csresmap(ctools.cscript): @@ -36,7 +36,7 @@ class csresmap(ctools.cscript):
36 behaves just as a regular ctool. 36 behaves just as a regular ctool.
37 """ 37 """
38 38
39 - # Constructors and destructors 39 + # Constructor
40 def __init__(self, *argv): 40 def __init__(self, *argv):
41 """ 41 """
42 Constructor. 42 Constructor.
@@ -49,7 +49,6 @@ class csresmap(ctools.cscript): @@ -49,7 +49,6 @@ class csresmap(ctools.cscript):
49 self._algorithm = "SUB" 49 self._algorithm = "SUB"
50 self._resmap = None 50 self._resmap = None
51 self._modcube = "NONE" 51 self._modcube = "NONE"
52 - self._outmap = "NONE"  
53 self._use_maps = False 52 self._use_maps = False
54 self._skip_binning = False 53 self._skip_binning = False
55 self._publish = False 54 self._publish = False
@@ -74,35 +73,16 @@ class csresmap(ctools.cscript): @@ -74,35 +73,16 @@ class csresmap(ctools.cscript):
74 self._debug = False 73 self._debug = False
75 self._log_clients = False 74 self._log_clients = False
76 75
77 - # Initialise observation  
78 - if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations):  
79 - self._obs = argv[0]  
80 - argv = argv[1:]  
81 - else:  
82 - self._obs = gammalib.GObservations()  
83 -  
84 - # Initialise application  
85 - if len(argv) == 0:  
86 - ctools.cscript.__init__(self, self._name, self._version)  
87 - elif len(argv) ==1:  
88 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
89 - else:  
90 - raise TypeError("Invalid number of arguments given.") 76 + # Initialise observation container from constructor arguments.
  77 + self._obs = self._set_input_obs(argv)
91 78
92 - # Set logger properties  
93 - self._log_header()  
94 - self._log.date(True) 79 + # Initialise application by calling the appropriate class
  80 + # constructor.
  81 + self._init_cscript(argv)
95 82
96 # Return 83 # Return
97 return 84 return
98 85
99 - def __del__(self):  
100 - """  
101 - Destructor.  
102 - """  
103 - # Return  
104 - return  
105 -  
106 86
107 # Private methods 87 # Private methods
108 def _get_parameters(self): 88 def _get_parameters(self):
@@ -177,7 +157,7 @@ class csresmap(ctools.cscript): @@ -177,7 +157,7 @@ class csresmap(ctools.cscript):
177 157
178 # Read ahead output parameters 158 # Read ahead output parameters
179 if (self._read_ahead()): 159 if (self._read_ahead()):
180 - self._outmap = self["outmap"].filename() 160 + self["outmap"].filename()
181 161
182 # Write input parameters into logger 162 # Write input parameters into logger
183 if self._logTerse(): 163 if self._logTerse():
@@ -318,6 +298,9 @@ class csresmap(ctools.cscript): @@ -318,6 +298,9 @@ class csresmap(ctools.cscript):
318 """ 298 """
319 Execute the script. 299 Execute the script.
320 """ 300 """
  301 + # Open logfile
  302 + self._logFileOpen()
  303 +
321 # Read ahead output parameters 304 # Read ahead output parameters
322 self._read_ahead(True) 305 self._read_ahead(True)
323 306
@@ -340,17 +323,19 @@ class csresmap(ctools.cscript): @@ -340,17 +323,19 @@ class csresmap(ctools.cscript):
340 self._log.header1("Save residual map") 323 self._log.header1("Save residual map")
341 324
342 # Get outmap parameter 325 # Get outmap parameter
343 - self._outmap = self["outmap"].filename() 326 + outmap = self["outmap"].filename()
344 327
345 # Continue only filename and residual map are valid 328 # Continue only filename and residual map are valid
346 - if self._outmap != "NONE" and self._resmap != None: 329 + if self._resmap != None:
347 330
348 # Log file name 331 # Log file name
349 if self._logTerse(): 332 if self._logTerse():
350 - self._log("Save residual map into \""+self._outmap+"\".\n") 333 + self._log(gammalib.parformat("Residual map file"))
  334 + self._log(outmap.url())
  335 + self._log("\n")
351 336
352 # Save residual map 337 # Save residual map
353 - self._resmap.save(self._outmap, self._clobber) 338 + self._resmap.save(outmap, self._clobber)
354 339
355 # Return 340 # Return
356 return 341 return
@@ -405,8 +390,5 @@ if __name__ == '__main__': @@ -405,8 +390,5 @@ if __name__ == '__main__':
405 # Create instance of application 390 # Create instance of application
406 app = csresmap(sys.argv) 391 app = csresmap(sys.argv)
407 392
408 - # Open logfile  
409 - app._logFileOpen()  
410 -  
411 # Execute application 393 # Execute application
412 app.execute() 394 app.execute()
cscripts/cssens.py
@@ -41,7 +41,7 @@ class cssens(ctools.cscript): @@ -41,7 +41,7 @@ class cssens(ctools.cscript):
41 the likelihood difference between fitting with and without the test source. 41 the likelihood difference between fitting with and without the test source.
42 """ 42 """
43 43
44 - # Constructors and destructors 44 + # Constructor
45 def __init__(self, *argv): 45 def __init__(self, *argv):
46 """ 46 """
47 Constructor. 47 Constructor.
@@ -54,7 +54,7 @@ class cssens(ctools.cscript): @@ -54,7 +54,7 @@ class cssens(ctools.cscript):
54 self._obs = gammalib.GObservations() 54 self._obs = gammalib.GObservations()
55 self._ebounds = gammalib.GEbounds() 55 self._ebounds = gammalib.GEbounds()
56 self._srcname = "" 56 self._srcname = ""
57 - self._outfile = "" 57 + self._outfile = gammalib.GFilename()
58 self._ra = None 58 self._ra = None
59 self._dec = None 59 self._dec = None
60 self._edisp = False 60 self._edisp = False
@@ -71,28 +71,13 @@ class cssens(ctools.cscript): @@ -71,28 +71,13 @@ class cssens(ctools.cscript):
71 self._log_clients = False 71 self._log_clients = False
72 self._debug = False 72 self._debug = False
73 73
74 - # Initialise application  
75 - if len(argv) == 0:  
76 - ctools.cscript.__init__(self, self._name, self._version)  
77 - elif len(argv) ==1:  
78 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
79 - else:  
80 - raise TypeError("Invalid number of arguments given.")  
81 -  
82 - # Set logger properties  
83 - self._log_header()  
84 - self._log.date(True) 74 + # Initialise application by calling the appropriate class
  75 + # constructor.
  76 + self._init_cscript(argv)
85 77
86 # Return 78 # Return
87 return 79 return
88 80
89 - def __del__(self):  
90 - """  
91 - Destructor.  
92 - """  
93 - # Return  
94 - return  
95 -  
96 81
97 # Private methods 82 # Private methods
98 def _get_parameters(self): 83 def _get_parameters(self):
@@ -734,6 +719,9 @@ class cssens(ctools.cscript): @@ -734,6 +719,9 @@ class cssens(ctools.cscript):
734 """ 719 """
735 Execute the script. 720 Execute the script.
736 """ 721 """
  722 + # Open logfile
  723 + self._logFileOpen()
  724 +
737 # Run the script 725 # Run the script
738 self.run() 726 self.run()
739 727
@@ -750,8 +738,5 @@ if __name__ == '__main__': @@ -750,8 +738,5 @@ if __name__ == '__main__':
750 # Create instance of application 738 # Create instance of application
751 app = cssens(sys.argv) 739 app = cssens(sys.argv)
752 740
753 - # Open logfile  
754 - app._logFileOpen()  
755 -  
756 # Run application 741 # Run application
757 app.execute() 742 app.execute()
cscripts/csspec.py
@@ -51,7 +51,6 @@ class csspec(ctools.cscript): @@ -51,7 +51,6 @@ class csspec(ctools.cscript):
51 self._binned_mode = False 51 self._binned_mode = False
52 self._srcname = "" 52 self._srcname = ""
53 self._edisp = False 53 self._edisp = False
54 - self._outfile = "NONE"  
55 self._calc_ulimit = True 54 self._calc_ulimit = True
56 self._calc_ts = True 55 self._calc_ts = True
57 self._fix_bkg = False 56 self._fix_bkg = False
@@ -60,24 +59,12 @@ class csspec(ctools.cscript): @@ -60,24 +59,12 @@ class csspec(ctools.cscript):
60 self._clobber = True 59 self._clobber = True
61 self._debug = False 60 self._debug = False
62 61
63 - # Initialise observation  
64 - if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations):  
65 - self._obs = argv[0]  
66 - argv = argv[1:]  
67 - else:  
68 - self._obs = gammalib.GObservations()  
69 -  
70 - # Initialise application  
71 - if len(argv) == 0:  
72 - ctools.cscript.__init__(self, self._name, self._version)  
73 - elif len(argv) ==1:  
74 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
75 - else:  
76 - raise TypeError("Invalid number of arguments given.") 62 + # Initialise observation container from constructor arguments.
  63 + self._obs = self._set_input_obs(argv)
77 64
78 - # Set logger properties  
79 - self._log_header()  
80 - self._log.date(True) 65 + # Initialise application by calling the appropriate class
  66 + # constructor.
  67 + self._init_cscript(argv)
81 68
82 # Return 69 # Return
83 return 70 return
@@ -132,8 +119,8 @@ class csspec(ctools.cscript): @@ -132,8 +119,8 @@ class csspec(ctools.cscript):
132 self._debug = self["debug"].boolean() 119 self._debug = self["debug"].boolean()
133 120
134 # Read ahead output parameters 121 # Read ahead output parameters
135 - if (self._read_ahead()):  
136 - self._outfile = self["outfile"].filename() 122 + if self._read_ahead():
  123 + self["outfile"].filename()
137 124
138 # Write input parameters into logger 125 # Write input parameters into logger
139 if self._logTerse(): 126 if self._logTerse():
@@ -494,6 +481,9 @@ class csspec(ctools.cscript): @@ -494,6 +481,9 @@ class csspec(ctools.cscript):
494 """ 481 """
495 Execute the script. 482 Execute the script.
496 """ 483 """
  484 + # Open logfile
  485 + self._logFileOpen()
  486 +
497 # Read ahead output parameters 487 # Read ahead output parameters
498 self._read_ahead(True) 488 self._read_ahead(True)
499 489
@@ -516,17 +506,19 @@ class csspec(ctools.cscript): @@ -516,17 +506,19 @@ class csspec(ctools.cscript):
516 self._log.header1("Save spectrum") 506 self._log.header1("Save spectrum")
517 507
518 # Get outmap parameter 508 # Get outmap parameter
519 - self._outfile = self["outfile"].filename() 509 + outfile = self["outfile"].filename()
520 510
521 # Continue only filename and residual map are valid 511 # Continue only filename and residual map are valid
522 - if self._outfile != "NONE" and self._fits != None: 512 + if self._fits != None:
523 513
524 # Log file name 514 # Log file name
525 if self._logTerse(): 515 if self._logTerse():
526 - self._log("Save spectrum into \""+self._outfile+"\".\n") 516 + self._log(gammalib.parformat("Spectrum file"))
  517 + self._log(outfile.url())
  518 + self._log("\n")
527 519
528 # Save spectrum 520 # Save spectrum
529 - self._fits.saveto(self._outfile, self._clobber) 521 + self._fits.saveto(outfile, self._clobber)
530 522
531 # Return 523 # Return
532 return 524 return
@@ -560,8 +552,5 @@ if __name__ == '__main__': @@ -560,8 +552,5 @@ if __name__ == '__main__':
560 # Create instance of application 552 # Create instance of application
561 app = csspec(sys.argv) 553 app = csspec(sys.argv)
562 554
563 - # Open logfile  
564 - app._logFileOpen()  
565 -  
566 # Execute application 555 # Execute application
567 app.execute() 556 app.execute()
cscripts/cstsdist.py
@@ -39,7 +39,7 @@ class cstsdist(ctools.cscript): @@ -39,7 +39,7 @@ class cstsdist(ctools.cscript):
39 script behaves just as a regular ctool. 39 script behaves just as a regular ctool.
40 """ 40 """
41 41
42 - # Constructors and destructors 42 + # Constructor
43 def __init__(self, *argv): 43 def __init__(self, *argv):
44 """ 44 """
45 Constructor. 45 Constructor.
@@ -55,34 +55,19 @@ class cstsdist(ctools.cscript): @@ -55,34 +55,19 @@ class cstsdist(ctools.cscript):
55 self._enumbins = 0 55 self._enumbins = 0
56 self._npix = 0 56 self._npix = 0
57 self._binsz = 0.0 57 self._binsz = 0.0
58 - self._outfile = "ts.dat" 58 + self._outfile = gammalib.GFilename("ts.dat")
59 self._ntrials = 10 59 self._ntrials = 10
60 self._edisp = False 60 self._edisp = False
61 self._debug = False 61 self._debug = False
62 self._log_clients = False 62 self._log_clients = False
63 63
64 - # Initialise application  
65 - if len(argv) == 0:  
66 - ctools.cscript.__init__(self, self._name, self._version)  
67 - elif len(argv) ==1:  
68 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
69 - else:  
70 - raise TypeError("Invalid number of arguments given.")  
71 -  
72 - # Set logger properties  
73 - self._log_header()  
74 - self._log.date(True) 64 + # Initialise application by calling the appropriate class
  65 + # constructor.
  66 + self._init_cscript(argv)
75 67
76 # Return 68 # Return
77 return 69 return
78 70
79 - def __del__(self):  
80 - """  
81 - Destructor.  
82 - """  
83 - # Return  
84 - return  
85 -  
86 71
87 # Private methods 72 # Private methods
88 def _get_parameters(self): 73 def _get_parameters(self):
@@ -463,6 +448,9 @@ class cstsdist(ctools.cscript): @@ -463,6 +448,9 @@ class cstsdist(ctools.cscript):
463 """ 448 """
464 Execute the script. 449 Execute the script.
465 """ 450 """
  451 + # Open logfile
  452 + self._logFileOpen()
  453 +
466 # Run the script 454 # Run the script
467 self.run() 455 self.run()
468 456
@@ -478,8 +466,5 @@ if __name__ == '__main__': @@ -478,8 +466,5 @@ if __name__ == '__main__':
478 # Create instance of application 466 # Create instance of application
479 app = cstsdist(sys.argv) 467 app = cstsdist(sys.argv)
480 468
481 - # Open logfile  
482 - app._logFileOpen()  
483 -  
484 # Execute application 469 # Execute application
485 app.execute() 470 app.execute()
cscripts/cstsmapmerge.par
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 # File: cstsmapmerge.par # 7 # File: cstsmapmerge.par #
8 # Version: 1.1.0 # 8 # Version: 1.1.0 #
9 # # 9 # #
10 -# Author: Juergen Knoedlseder #  
11 -# Jurgen.Knodlseder@irap.omp.eu #  
12 -# IRAP # 10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
13 # # 13 # #
14 # Purpose: Parameter file for the cstsmapmerge script # 14 # Purpose: Parameter file for the cstsmapmerge script #
15 # # 15 # #
cscripts/cstsmapmerge.py
@@ -33,7 +33,7 @@ class cstsmapmerge(ctools.cscript): @@ -33,7 +33,7 @@ class cstsmapmerge(ctools.cscript):
33 Merge Test Statistic maps. 33 Merge Test Statistic maps.
34 """ 34 """
35 35
36 - # Constructors and destructors 36 + # Constructor
37 def __init__(self, *argv): 37 def __init__(self, *argv):
38 """ 38 """
39 Constructor. 39 Constructor.
@@ -52,28 +52,11 @@ class cstsmapmerge(ctools.cscript): @@ -52,28 +52,11 @@ class cstsmapmerge(ctools.cscript):
52 self._merged_files = [] 52 self._merged_files = []
53 self._overwrite = True 53 self._overwrite = True
54 self._delete = False 54 self._delete = False
55 - self._outmap = "NONE"  
56 - self._read_ahead = False  
57 -  
58 - # Initialise application  
59 - if len(argv) == 0:  
60 - ctools.cscript.__init__(self, self._name, self._version)  
61 - elif len(argv) == 1:  
62 - ctools.cscript.__init__(self, self._name, self._version, *argv)  
63 - else:  
64 - raise TypeError("Invalid number of arguments given.")  
65 -  
66 - # Set logger properties  
67 - self._log_header()  
68 - self._log.date(True)  
69 55
70 - # Return  
71 - return 56 + # Initialise application by calling the appropriate class
  57 + # constructor.
  58 + self._init_cscript(argv)
72 59
73 - def __del__(self):  
74 - """  
75 - Destructor.  
76 - """  
77 # Return 60 # Return
78 return 61 return
79 62
@@ -120,8 +103,8 @@ class cstsmapmerge(ctools.cscript): @@ -120,8 +103,8 @@ class cstsmapmerge(ctools.cscript):
120 self._delete = self["delete"].boolean() 103 self._delete = self["delete"].boolean()
121 104
122 # Read ahead output filename 105 # Read ahead output filename
123 - if self._read_ahead:  
124 - self._outmap = self["outmap"].filename() 106 + if self._read_ahead():
  107 + self["outmap"].filename()
125 108
126 # Write input parameters into logger 109 # Write input parameters into logger
127 if self._logTerse(): 110 if self._logTerse():
@@ -391,12 +374,12 @@ class cstsmapmerge(ctools.cscript): @@ -391,12 +374,12 @@ class cstsmapmerge(ctools.cscript):
391 self._log.header1("Save TS map") 374 self._log.header1("Save TS map")
392 375
393 # Get output filename in case it was not read ahead 376 # Get output filename in case it was not read ahead
394 - self._outmap = self["outmap"].filename() 377 + outmap = self["outmap"].filename()
395 378
396 # Log filename 379 # Log filename
397 if self._logTerse(): 380 if self._logTerse():
398 self._log(gammalib.parformat("TS map file")) 381 self._log(gammalib.parformat("TS map file"))
399 - self._log(self._outmap.url()) 382 + self._log(outmap.url())
400 self._log("\n") 383 self._log("\n")
401 384
402 # Create FITS file 385 # Create FITS file
@@ -426,7 +409,7 @@ class cstsmapmerge(ctools.cscript): @@ -426,7 +409,7 @@ class cstsmapmerge(ctools.cscript):
426 fits[fits.size()-1].extname("STATUS MAP") 409 fits[fits.size()-1].extname("STATUS MAP")
427 410
428 # Save FITS file 411 # Save FITS file
429 - fits.saveto(self._outmap, self._clobber()) 412 + fits.saveto(outmap, self._clobber())
430 413
431 # Delete TS input maps if requested 414 # Delete TS input maps if requested
432 if self._delete: 415 if self._delete:
@@ -444,8 +427,11 @@ class cstsmapmerge(ctools.cscript): @@ -444,8 +427,11 @@ class cstsmapmerge(ctools.cscript):
444 """ 427 """
445 Execute the script. 428 Execute the script.
446 """ 429 """
447 - # Set read ahead flag  
448 - self._read_ahead = True 430 + # Open logfile
  431 + self._logFileOpen()
  432 +
  433 + # Read ahead output parameters
  434 + self._read_ahead(True)
449 435
450 # Run the script 436 # Run the script
451 self.run() 437 self.run()
@@ -465,8 +451,5 @@ if __name__ == '__main__': @@ -465,8 +451,5 @@ if __name__ == '__main__':
465 # Create instance of application 451 # Create instance of application
466 app = cstsmapmerge(sys.argv) 452 app = cstsmapmerge(sys.argv)
467 453
468 - # Open logfile  
469 - app._logFileOpen()  
470 -  
471 # Execute application 454 # Execute application
472 app.execute() 455 app.execute()
cscripts/obsutils.py
1 # ========================================================================== 1 # ==========================================================================
2 -# This script provides a number of functions that are useful for handling  
3 -# CTA observations. 2 +# CTA observation handling support functions.
4 # 3 #
5 -# Copyright (C) 2011-2015 Juergen Knoedlseder 4 +# Copyright (C) 2011-2016 Juergen Knoedlseder
6 # 5 #
7 # This program is free software: you can redistribute it and/or modify 6 # 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 7 # it under the terms of the GNU General Public License as published by
@@ -31,21 +30,28 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0, @@ -31,21 +30,28 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0,
31 """ 30 """
32 Simulate events for all observations in the container. 31 Simulate events for all observations in the container.
33 32
34 - Parameters:  
35 - obs - Observation container  
36 - Keywords:  
37 - log - Create log file(s)  
38 - debug - Create console dump?  
39 - edisp - Apply energy dispersion?  
40 - seed - Seed value for simulations (default: 0)  
41 - nbins - Number of energy bins (default: 0=unbinned)  
42 - binsz - Pixel size for binned simulation (deg/pixel)  
43 - npix - Number of pixels in X and Y for binned simulation 33 + Args:
  34 + obs: Observation container without events
  35 +
  36 + Kwargs:
  37 + log: Create log file(s)
  38 + debug: Create console dump?
  39 + chatter: Chatter level
  40 + edisp: Apply energy dispersion?
  41 + seed: Seed value for simulations (default: 0)
  42 + nbins: Number of energy bins (default: 0=unbinned)
  43 + binsz: Pixel size for binned simulation (deg/pixel)
  44 + npix: Number of pixels in X and Y for binned simulation
  45 + proj: Projection for binned simulation
  46 + coord: Coordinate system for binned simulation
  47 +
  48 + Returns:
  49 + Observation container, filled with simulated events.
44 """ 50 """
45 51
46 # Allocate ctobssim application and set parameters 52 # Allocate ctobssim application and set parameters
47 sim = ctools.ctobssim(obs) 53 sim = ctools.ctobssim(obs)
48 - sim["seed"] = seed 54 + sim["seed"] = seed
49 sim["edisp"] = edisp 55 sim["edisp"] = edisp
50 56
51 # Optionally open the log file 57 # Optionally open the log file
@@ -85,16 +91,16 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0, @@ -85,16 +91,16 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0,
85 91
86 # Allocate ctbin application and set parameters 92 # Allocate ctbin application and set parameters
87 bin = ctools.ctbin(sim.obs()) 93 bin = ctools.ctbin(sim.obs())
88 - bin["ebinalg"] = "LOG"  
89 - bin["emin"] = emin  
90 - bin["emax"] = emax 94 + bin["ebinalg"] = "LOG"
  95 + bin["emin"] = emin
  96 + bin["emax"] = emax
91 bin["enumbins"] = nbins 97 bin["enumbins"] = nbins
92 - bin["usepnt"] = True # Use pointing for map centre  
93 - bin["nxpix"] = npix  
94 - bin["nypix"] = npix  
95 - bin["binsz"] = binsz 98 + bin["usepnt"] = True # Use pointing for map centre
  99 + bin["nxpix"] = npix
  100 + bin["nypix"] = npix
  101 + bin["binsz"] = binsz
96 bin["coordsys"] = coord 102 bin["coordsys"] = coord
97 - bin["proj"] = proj 103 + bin["proj"] = proj
98 104
99 # Optionally open the log file 105 # Optionally open the log file
100 if log: 106 if log:
@@ -350,28 +356,30 @@ def set(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ @@ -350,28 +356,30 @@ def set(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \
350 # ======================= # 356 # ======================= #
351 def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ 357 def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \
352 emin=0.1, emax=100.0, rad=5.0, \ 358 emin=0.1, emax=100.0, rad=5.0, \
353 - irf="South_50h", caldb="prod2", id="000000", instrument="CTA"): 359 + irf="South_50h", caldb="prod2", id="000000"):
354 """ 360 """
355 - Returns a single CTA observation containing an empty CTA event list.  
356 - By looping over this function you can add CTA observations to the  
357 - observation container.  
358 -  
359 - Parameters:  
360 - pntdir - Pointing direction [GSkyDir]  
361 - Keywords:  
362 - tstart - Start time [seconds] (default: 0.0)  
363 - duration - Duration of observation [seconds] (default: 1800.0)  
364 - deadc - Deadtime correction factor (default: 0.95)  
365 - emin - Minimum event energy [TeV] (default: 0.1)  
366 - emax - Maximum event energy [TeV] (default: 100.0)  
367 - rad - ROI radius used for analysis [deg] (default: 5.0)  
368 - irf - Instrument response function (default: cta_dummy_irf)  
369 - caldb - Calibration database path (default: "dummy")  
370 - id - Run identifier (default: "000000")  
371 - instrument - Intrument (default: "CTA") 361 + Set a single CTA observation.
  362 +
  363 + The function sets a single CTA observation containing an empty CTA
  364 + event list. By looping over this function you can add CTA observations
  365 + to the observation container.
  366 +
  367 + Args:
  368 + pntdir: Pointing direction [GSkyDir]
  369 +
  370 + Kwargs:
  371 + tstart: Start time (seconds) (default: 0.0)
  372 + duration: Duration of observation (seconds) (default: 1800.0)
  373 + deadc: Deadtime correction factor (default: 0.95)
  374 + emin: Minimum event energy (TeV) (default: 0.1)
  375 + emax: Maximum event energy (TeV) (default: 100.0)
  376 + rad: ROI radius used for analysis (deg) (default: 5.0)
  377 + irf: Instrument response function (default: "South_50h")
  378 + caldb: Calibration database path (default: "prod2")
  379 + id: Run identifier (default: "000000")
372 """ 380 """
373 # Allocate CTA observation 381 # Allocate CTA observation
374 - obs_cta = gammalib.GCTAObservation(instrument) 382 + obs_cta = gammalib.GCTAObservation()
375 383
376 # Set calibration database 384 # Set calibration database
377 db = gammalib.GCaldb() 385 db = gammalib.GCaldb()
@@ -397,7 +405,7 @@ def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ @@ -397,7 +405,7 @@ def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \
397 gti.append(gammalib.GTime(tstart), gammalib.GTime(tstart+duration)) 405 gti.append(gammalib.GTime(tstart), gammalib.GTime(tstart+duration))
398 406
399 # Set energy boundaries 407 # Set energy boundaries
400 - ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, "TeV"), \ 408 + ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, "TeV"),
401 gammalib.GEnergy(emax, "TeV")) 409 gammalib.GEnergy(emax, "TeV"))
402 410
403 # Allocate event list 411 # Allocate event list
pyext/ctedispcube.i 0 → 100644
  1 +/***************************************************************************
  2 + * ctedispcube - Energy dispersion cube generation tool *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2016 by Maria Haupt *
  5 + * ----------------------------------------------------------------------- *
  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 +/**
  22 + * @file ctedispcube.i
  23 + * @brief Energy dispersion cube generation tool definition
  24 + * @author Chia-Chun Lu
  25 + */
  26 +
  27 +%{
  28 +/* Put headers and other declarations here that are needed for compilation */
  29 +#include "ctedispcube.hpp"
  30 +%}
  31 +
  32 +/***********************************************************************//**
  33 + * @class ctedispcube
  34 + *
  35 + * @brief Energy dispersion cube generation tool
  36 + ***************************************************************************/
  37 +class ctedispcube : public ctool {
  38 +
  39 +public:
  40 + // Constructors and destructors
  41 + ctedispcube(void);
  42 + explicit ctedispcube(const GObservations& obs);
  43 + ctedispcube(int argc, char *argv[]);
  44 + ctedispcube(const ctedispcube& app);
  45 + virtual ~ctedispcube(void);
  46 +
  47 + // Methods
  48 + void clear(void);
  49 + void run(void);
  50 + void save(void);
  51 + const GCTACubeEdisp& edispcube(void) const;
  52 +};
  53 +
  54 +/***********************************************************************//**
  55 + * @brief Energy dispersion cube generation tool Python extensions
  56 + ***************************************************************************/
  57 +%extend ctedispcube {
  58 + ctedispcube copy() {
  59 + return (*self);
  60 + }
  61 +}
pyext/ctool.i
@@ -99,6 +99,7 @@ public: @@ -99,6 +99,7 @@ public:
99 %rename(_set_obs_bounds) set_obs_bounds(GObservations& obs); 99 %rename(_set_obs_bounds) set_obs_bounds(GObservations& obs);
100 %rename(_get_mean_pointing) get_mean_pointing(const GObservations& obs); 100 %rename(_get_mean_pointing) get_mean_pointing(const GObservations& obs);
101 %rename(_get_current_rss) get_current_rss(); 101 %rename(_get_current_rss) get_current_rss();
  102 + %rename(_get_obs_header) get_obs_header();
102 103
103 // Protected methods 104 // Protected methods
104 const bool& read_ahead(void) const; 105 const bool& read_ahead(void) const;
@@ -122,6 +123,7 @@ public: @@ -122,6 +123,7 @@ public:
122 void set_obs_bounds(GObservations& obs); 123 void set_obs_bounds(GObservations& obs);
123 GSkyDir get_mean_pointing(const GObservations& obs); 124 GSkyDir get_mean_pointing(const GObservations& obs);
124 size_t get_current_rss(void); 125 size_t get_current_rss(void);
  126 + std::string get_obs_header(const GObservation* obs);
125 }; 127 };
126 128
127 129
@@ -152,7 +154,7 @@ public: @@ -152,7 +154,7 @@ public:
152 154
153 155
154 /***********************************************************************//** 156 /***********************************************************************//**
155 - * @brief ctool base class Python extension 157 + * @brief ctool base class Python extensions
156 ***************************************************************************/ 158 ***************************************************************************/
157 %extend ctool { 159 %extend ctool {
158 void _read_ahead(const bool& flag) { 160 void _read_ahead(const bool& flag) {
@@ -160,3 +162,35 @@ public: @@ -160,3 +162,35 @@ public:
160 return; 162 return;
161 } 163 }
162 } 164 }
  165 +
  166 +/***********************************************************************//**
  167 + * @brief cscript base class Python extensions
  168 + ***************************************************************************/
  169 +%pythoncode %{
  170 +
  171 +# Initialise observation container from constructor arguments. In case that
  172 +# an observation container is provided as argument, this container will be
  173 +# used to initialise the class.
  174 +def _set_input_obs(self, argv):
  175 + if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations):
  176 + obs = argv[0]
  177 + argv = argv[1:]
  178 + else:
  179 + obs = gammalib.GObservations()
  180 + return obs
  181 +cscript._set_input_obs = _set_input_obs
  182 +
  183 +# Initialise application by calling the appropriate class constructor.
  184 +def _init_cscript(self, argv):
  185 + if len(argv) == 0:
  186 + cscript.__init__(self, self._name, self._version)
  187 + elif len(argv) == 1:
  188 + cscript.__init__(self, self._name, self._version, *argv)
  189 + else:
  190 + raise TypeError("Invalid number of arguments given.")
  191 + # Set logger properties
  192 + self._log_header()
  193 + self._log.date(True)
  194 +cscript._init_cscript = _init_cscript
  195 +
  196 +%}
pyext/ctools/tools.i
1 /*************************************************************************** 1 /***************************************************************************
2 * ctools - SWIG file * 2 * ctools - SWIG file *
3 * ----------------------------------------------------------------------- * 3 * ----------------------------------------------------------------------- *
4 - * copyright (C) 2010-2014 by Juergen Knoedlseder * 4 + * copyright (C) 2010-2016 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- * 5 * ----------------------------------------------------------------------- *
6 * * 6 * *
7 * This program is free software: you can redistribute it and/or modify * 7 * This program is free software: you can redistribute it and/or modify *
@@ -54,6 +54,7 @@ @@ -54,6 +54,7 @@
54 %include "ctskymap.i" 54 %include "ctskymap.i"
55 %include "ctexpcube.i" 55 %include "ctexpcube.i"
56 %include "ctpsfcube.i" 56 %include "ctpsfcube.i"
  57 +%include "ctedispcube.i"
57 %include "ctbkgcube.i" 58 %include "ctbkgcube.i"
58 %include "ctcubemask.i" 59 %include "ctcubemask.i"
59 %include "cttsmap.i" 60 %include "cttsmap.i"
@@ -66,4 +67,4 @@ @@ -66,4 +67,4 @@
66 def test(): 67 def test():
67 from ctools.tests import test_python_ctools 68 from ctools.tests import test_python_ctools
68 test_python_ctools.test(installed=True) 69 test_python_ctools.test(installed=True)
69 -%}  
70 \ No newline at end of file 70 \ No newline at end of file
  71 +%}
src/ctbin/ctbin.cpp
@@ -52,6 +52,8 @@ const GEnergy g_energy_margin(1.0e-12, &quot;TeV&quot;); @@ -52,6 +52,8 @@ const GEnergy g_energy_margin(1.0e-12, &quot;TeV&quot;);
52 52
53 /***********************************************************************//** 53 /***********************************************************************//**
54 * @brief Void constructor 54 * @brief Void constructor
  55 + *
  56 + * Constructs an empty ctbin tool.
55 ***************************************************************************/ 57 ***************************************************************************/
56 ctbin::ctbin(void) : ctool(CTBIN_NAME, CTBIN_VERSION) 58 ctbin::ctbin(void) : ctool(CTBIN_NAME, CTBIN_VERSION)
57 { 59 {
@@ -68,8 +70,7 @@ ctbin::ctbin(void) : ctool(CTBIN_NAME, CTBIN_VERSION) @@ -68,8 +70,7 @@ ctbin::ctbin(void) : ctool(CTBIN_NAME, CTBIN_VERSION)
68 * 70 *
69 * param[in] obs Observation container. 71 * param[in] obs Observation container.
70 * 72 *
71 - * This method creates an instance of the class by copying an existing  
72 - * observations container. 73 + * Constructs ctbin tool from an observation container.
73 ***************************************************************************/ 74 ***************************************************************************/
74 ctbin::ctbin(const GObservations& obs) : ctool(CTBIN_NAME, CTBIN_VERSION) 75 ctbin::ctbin(const GObservations& obs) : ctool(CTBIN_NAME, CTBIN_VERSION)
75 { 76 {
@@ -90,6 +91,9 @@ ctbin::ctbin(const GObservations&amp; obs) : ctool(CTBIN_NAME, CTBIN_VERSION) @@ -90,6 +91,9 @@ ctbin::ctbin(const GObservations&amp; obs) : ctool(CTBIN_NAME, CTBIN_VERSION)
90 * 91 *
91 * @param[in] argc Number of arguments in command line. 92 * @param[in] argc Number of arguments in command line.
92 * @param[in] argv Array of command line arguments. 93 * @param[in] argv Array of command line arguments.
  94 + *
  95 + * Constructs ctbin tool using command line arguments for user parameter
  96 + * setting.
93 ***************************************************************************/ 97 ***************************************************************************/
94 ctbin::ctbin(int argc, char *argv[]) : 98 ctbin::ctbin(int argc, char *argv[]) :
95 ctool(CTBIN_NAME, CTBIN_VERSION, argc, argv) 99 ctool(CTBIN_NAME, CTBIN_VERSION, argc, argv)
@@ -106,6 +110,8 @@ ctbin::ctbin(int argc, char *argv[]) : @@ -106,6 +110,8 @@ ctbin::ctbin(int argc, char *argv[]) :
106 * @brief Copy constructor 110 * @brief Copy constructor
107 * 111 *
108 * @param[in] app Application. 112 * @param[in] app Application.
  113 + *
  114 + * Constructs ctbin tool from another ctbin instance.
109 ***************************************************************************/ 115 ***************************************************************************/
110 ctbin::ctbin(const ctbin& app) : ctool(app) 116 ctbin::ctbin(const ctbin& app) : ctool(app)
111 { 117 {
@@ -122,6 +128,8 @@ ctbin::ctbin(const ctbin&amp; app) : ctool(app) @@ -122,6 +128,8 @@ ctbin::ctbin(const ctbin&amp; app) : ctool(app)
122 128
123 /***********************************************************************//** 129 /***********************************************************************//**
124 * @brief Destructor 130 * @brief Destructor
  131 + *
  132 + * Destructs ctbin tool.
125 ***************************************************************************/ 133 ***************************************************************************/
126 ctbin::~ctbin(void) 134 ctbin::~ctbin(void)
127 { 135 {
@@ -142,7 +150,10 @@ ctbin::~ctbin(void) @@ -142,7 +150,10 @@ ctbin::~ctbin(void)
142 /***********************************************************************//** 150 /***********************************************************************//**
143 * @brief Assignment operator 151 * @brief Assignment operator
144 * 152 *
145 - * @param[in] app Application. 153 + * @param[in] app ctbin tool.
  154 + * @return ctbin tool.
  155 + *
  156 + * Assigns ctbin tool.
146 ***************************************************************************/ 157 ***************************************************************************/
147 ctbin& ctbin::operator=(const ctbin& app) 158 ctbin& ctbin::operator=(const ctbin& app)
148 { 159 {
@@ -175,7 +186,9 @@ ctbin&amp; ctbin::operator=(const ctbin&amp; app) @@ -175,7 +186,9 @@ ctbin&amp; ctbin::operator=(const ctbin&amp; app)
175 ==========================================================================*/ 186 ==========================================================================*/
176 187
177 /***********************************************************************//** 188 /***********************************************************************//**
178 - * @brief Clear instance 189 + * @brief Clear ctbin tool
  190 + *
  191 + * Clears ctbin tool.
179 ***************************************************************************/ 192 ***************************************************************************/
180 void ctbin::clear(void) 193 void ctbin::clear(void)
181 { 194 {
@@ -195,12 +208,10 @@ void ctbin::clear(void) @@ -195,12 +208,10 @@ void ctbin::clear(void)
195 208
196 209
197 /***********************************************************************//** 210 /***********************************************************************//**
198 - * @brief Bin the event data 211 + * @brief Run the ctbin tool
199 * 212 *
200 - * This method loops over all observations found in the observation conatiner  
201 - * and bins all events from the event list(s) into counts map(s). Note that  
202 - * each event list is binned in a separate counts map, hence no summing of  
203 - * events is done. 213 + * Gets the user parameters and loops over all CTA observations in the
  214 + * observation container to bin the events into a single counts cube.
204 ***************************************************************************/ 215 ***************************************************************************/
205 void ctbin::run(void) 216 void ctbin::run(void)
206 { 217 {
@@ -212,33 +223,17 @@ void ctbin::run(void) @@ -212,33 +223,17 @@ void ctbin::run(void)
212 // Get task parameters 223 // Get task parameters
213 get_parameters(); 224 get_parameters();
214 225
215 - // Write parameters into logger  
216 - if (logTerse()) {  
217 - log_parameters();  
218 - log << std::endl;  
219 - }  
220 -  
221 // Write observation(s) into logger 226 // Write observation(s) into logger
222 if (logTerse()) { 227 if (logTerse()) {
223 log << std::endl; 228 log << std::endl;
224 - if (m_obs.size() > 1) {  
225 - log.header1("Observations");  
226 - }  
227 - else {  
228 - log.header1("Observation");  
229 - } 229 + log.header1(gammalib::number("Observation", m_obs.size()));
230 log << m_obs << std::endl; 230 log << m_obs << std::endl;
231 } 231 }
232 232
233 // Write header 233 // Write header
234 if (logTerse()) { 234 if (logTerse()) {
235 log << std::endl; 235 log << std::endl;
236 - if (m_obs.size() > 1) {  
237 - log.header1("Bin observations");  
238 - }  
239 - else {  
240 - log.header1("Bin observation");  
241 - } 236 + log.header1(gammalib::number("Bin observation", m_obs.size()));
242 } 237 }
243 238
244 // Loop over all observations in the container 239 // Loop over all observations in the container
@@ -246,14 +241,7 @@ void ctbin::run(void) @@ -246,14 +241,7 @@ void ctbin::run(void)
246 241
247 // Write header for observation 242 // Write header for observation
248 if (logTerse()) { 243 if (logTerse()) {
249 - std::string header = m_obs[i]->instrument() + " observation";  
250 - if (m_obs[i]->name().length() > 1) {  
251 - header += " \"" + m_obs[i]->name() + "\"";  
252 - }  
253 - if (m_obs[i]->id().length() > 1) {  
254 - header += " (id=" + m_obs[i]->id() +")";  
255 - }  
256 - log.header3(header); 244 + log.header3(get_obs_header(m_obs[i]));
257 } 245 }
258 246
259 // Get CTA observation 247 // Get CTA observation
@@ -293,12 +281,7 @@ void ctbin::run(void) @@ -293,12 +281,7 @@ void ctbin::run(void)
293 // Write observation(s) into logger 281 // Write observation(s) into logger
294 if (logTerse()) { 282 if (logTerse()) {
295 log << std::endl; 283 log << std::endl;
296 - if (m_obs.size() > 1) {  
297 - log.header1("Binned observations");  
298 - }  
299 - else {  
300 - log.header1("Binned observation");  
301 - } 284 + log.header1(gammalib::number("Binned observation", m_obs.size()));
302 log << m_obs << std::endl; 285 log << m_obs << std::endl;
303 } 286 }
304 287
@@ -339,8 +322,8 @@ void ctbin::save(void) @@ -339,8 +322,8 @@ void ctbin::save(void)
339 322
340 // Log filename 323 // Log filename
341 if (logTerse()) { 324 if (logTerse()) {
342 - log << "Save counts cube into file \""+m_outcube+"\".";  
343 - log << std::endl; 325 + log << gammalib::parformat("Counts cube file");
  326 + log << m_outcube.url() << std::endl;
344 } 327 }
345 328
346 // Save cube 329 // Save cube
@@ -376,7 +359,8 @@ void ctbin::publish(const std::string&amp; name) @@ -376,7 +359,8 @@ void ctbin::publish(const std::string&amp; name)
376 359
377 // Log filename 360 // Log filename
378 if (logTerse()) { 361 if (logTerse()) {
379 - log << "Publish \""+user_name+"\" counts cube." << std::endl; 362 + log << gammalib::parformat("Counts cube name");
  363 + log << user_name << std::endl;
380 } 364 }
381 365
382 // Publish counts cube 366 // Publish counts cube
@@ -496,6 +480,12 @@ void ctbin::get_parameters(void) @@ -496,6 +480,12 @@ void ctbin::get_parameters(void)
496 m_outcube = (*this)["outcube"].filename(); 480 m_outcube = (*this)["outcube"].filename();
497 } 481 }
498 482
  483 + // Write parameters into logger
  484 + if (logTerse()) {
  485 + log_parameters();
  486 + log << std::endl;
  487 + }
  488 +
499 // Return 489 // Return
500 return; 490 return;
501 } 491 }
@@ -521,8 +511,8 @@ void ctbin::fill_cube(GCTAObservation* obs) @@ -521,8 +511,8 @@ void ctbin::fill_cube(GCTAObservation* obs)
521 const GCTAEventList* events = dynamic_cast<const GCTAEventList*>(obs->events()); 511 const GCTAEventList* events = dynamic_cast<const GCTAEventList*>(obs->events());
522 if (events == NULL) { 512 if (events == NULL) {
523 std::string msg = "CTA Observation does not contain an event " 513 std::string msg = "CTA Observation does not contain an event "
524 - "list. Event list information is needed to "  
525 - "fill the counts map."; 514 + "list. An event list is needed to fill the "
  515 + "counts cube.";
526 throw GException::invalid_value(G_FILL_CUBE, msg); 516 throw GException::invalid_value(G_FILL_CUBE, msg);
527 } 517 }
528 518
@@ -534,7 +524,7 @@ void ctbin::fill_cube(GCTAObservation* obs) @@ -534,7 +524,7 @@ void ctbin::fill_cube(GCTAObservation* obs)
534 524
535 // Check for RoI sanity 525 // Check for RoI sanity
536 if (!roi.is_valid()) { 526 if (!roi.is_valid()) {
537 - std::string msg = "No RoI information found in input observation " 527 + std::string msg = "No valid RoI found in input observation "
538 "\""+obs->name()+"\". Run ctselect to specify " 528 "\""+obs->name()+"\". Run ctselect to specify "
539 "an RoI for this observation before running " 529 "an RoI for this observation before running "
540 "ctbin."; 530 "ctbin.";
@@ -624,10 +614,12 @@ void ctbin::fill_cube(GCTAObservation* obs) @@ -624,10 +614,12 @@ void ctbin::fill_cube(GCTAObservation* obs)
624 * @brief Create output observation container. 614 * @brief Create output observation container.
625 * 615 *
626 * Creates an output observation container that combines all input CTA 616 * Creates an output observation container that combines all input CTA
627 - * observation into a single cube-style observation. All non CTA observations  
628 - * present in the observation container are kept. The method furthermore  
629 - * conserves any response information in case that a single CTA observation  
630 - * is provided. This supports the original binned analysis. 617 + * observation into a single stacked observation. All non-CTA observations
  618 + * and all binned CTA observations that were present in the observation
  619 + * container are append to the observation container so that they can
  620 + * be used by other tools. The method furthermore conserves any response
  621 + * information in case that a single CTA observation is provided to support
  622 + * binned analysis.
631 ***************************************************************************/ 623 ***************************************************************************/
632 void ctbin::obs_cube(void) 624 void ctbin::obs_cube(void)
633 { 625 {
@@ -641,26 +633,37 @@ void ctbin::obs_cube(void) @@ -641,26 +633,37 @@ void ctbin::obs_cube(void)
641 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]); 633 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]);
642 if (obs != NULL) { 634 if (obs != NULL) {
643 635
644 - // Only change the event type if we had an unbinned observation 636 + // Change the event type if we had an unbinned observation
645 if (obs->eventtype() == "EventList") { 637 if (obs->eventtype() == "EventList") {
646 638
  639 + // Assign cube to the observation
647 obs->events(this->cube()); 640 obs->events(this->cube());
648 - obs->eventfile("");  
649 - } // endif: observation was unbinned  
650 - else { // input observation was binned and skipped  
651 641
652 - // Create new and empty cube  
653 - GCTAEventCube cube = GCTAEventCube(m_cube, m_ebounds, obs->gti()); 642 + }
  643 +
  644 + // ... otherwise the input observation was binned and hence
  645 + // skipped. In that case we simply append an empty counts
  646 + // cube
  647 + else {
654 648
655 - // Assign empty cube to have a new binned observation 649 + // Create empty counts cube
  650 + GCTAEventCube cube(m_cube, m_ebounds, obs->gti());
  651 +
  652 + // Assign empty cube to observation
656 obs->events(cube); 653 obs->events(cube);
  654 +
657 } 655 }
658 656
  657 + // Reset file name
  658 + obs->eventfile("");
  659 +
659 } // endif: obervation was valid 660 } // endif: obervation was valid
660 661
661 } // endif: we only had one observation in the container 662 } // endif: we only had one observation in the container
662 663
663 - // ... otherwise put a single CTA observation in container 664 + // ... otherwise put a single CTA observation in container and
  665 + // append all observations that have not been used in the binning
  666 + // to the container
664 else { 667 else {
665 668
666 // Allocate observation container 669 // Allocate observation container
@@ -672,10 +675,25 @@ void ctbin::obs_cube(void) @@ -672,10 +675,25 @@ void ctbin::obs_cube(void)
672 // Attach event cube to CTA observation 675 // Attach event cube to CTA observation
673 obs.events(this->cube()); 676 obs.events(this->cube());
674 677
675 - // Set map centre as pointing  
676 - GSkyPixel pixel(0.5*double(m_cube.nx()), 0.5*double(m_cube.ny()));  
677 - GSkyDir centre = m_cube.pix2dir(pixel);  
678 - GCTAPointing pointing(centre); 678 + // Compute average pointing direction for all CTA event lists
  679 + double ra = 0.0;
  680 + double dec = 0.0;
  681 + double number = 0.0;
  682 + for (int i = 0; i < m_obs.size(); ++i) {
  683 + GCTAObservation* cta = dynamic_cast<GCTAObservation*>(m_obs[i]);
  684 + if ((cta != NULL) && (cta->eventtype() == "EventList")) {
  685 + ra += cta->pointing().dir().ra();
  686 + dec += cta->pointing().dir().dec();
  687 + number += 1.0;
  688 + }
  689 + }
  690 + if (number > 0.0) {
  691 + ra /= number;
  692 + dec /= number;
  693 + }
  694 + GSkyDir dir;
  695 + dir.radec(ra, dec);
  696 + GCTAPointing pointing(dir);
679 697
680 // Compute deadtime correction 698 // Compute deadtime correction
681 double deadc = (m_ontime > 0.0) ? m_livetime / m_ontime : 0.0; 699 double deadc = (m_ontime > 0.0) ? m_livetime / m_ontime : 0.0;
@@ -683,8 +701,8 @@ void ctbin::obs_cube(void) @@ -683,8 +701,8 @@ void ctbin::obs_cube(void)
683 // Set CTA observation attributes 701 // Set CTA observation attributes
684 obs.pointing(pointing); 702 obs.pointing(pointing);
685 obs.obs_id(0); 703 obs.obs_id(0);
686 - obs.ra_obj(centre.ra_deg()); //!< Dummy  
687 - obs.dec_obj(centre.dec_deg()); //!< Dummy 704 + obs.ra_obj(dir.ra_deg()); //!< Dummy
  705 + obs.dec_obj(dir.dec_deg()); //!< Dummy
688 obs.ontime(m_ontime); 706 obs.ontime(m_ontime);
689 obs.livetime(m_livetime); 707 obs.livetime(m_livetime);
690 obs.deadc(deadc); 708 obs.deadc(deadc);
@@ -701,6 +719,9 @@ void ctbin::obs_cube(void) @@ -701,6 +719,9 @@ void ctbin::obs_cube(void)
701 if (obs == NULL) { 719 if (obs == NULL) {
702 container.append(*m_obs[i]); 720 container.append(*m_obs[i]);
703 } 721 }
  722 + else if (obs->eventtype() != "EventList") {
  723 + container.append(*m_obs[i]);
  724 + }
704 } 725 }
705 726
706 // Set observation container 727 // Set observation container
src/ctbin/ctbin.par
@@ -7,27 +7,27 @@ @@ -7,27 +7,27 @@
7 # File: ctbin.par # 7 # File: ctbin.par #
8 # Version: 1.1.0 # 8 # Version: 1.1.0 #
9 # # 9 # #
10 -# Author: Jurgen Knodlseder # 10 +# Author: Juergen Knoedlseder #
11 # Jurgen.Knodlseder@irap.omp.eu # 11 # Jurgen.Knodlseder@irap.omp.eu #
12 # IRAP # 12 # IRAP #
13 # # 13 # #
14 -# Purpose: Parameter file for the ctbin application # 14 +# Purpose: Parameter file for the ctbin tool #
15 # # 15 # #
16 ############################################################################# 16 #############################################################################
17 # 17 #
18 # General parameters 18 # General parameters
19 #=================== 19 #===================
20 -inobs, f, a, "events.fits",,, "Input event list or observation definition XML file"  
21 -outcube, f, a, "cntcube.fits",,, "Output counts cube file" 20 +inobs, f, a, events.fits,,, "Input event list or observation definition XML file"
  21 +outcube, f, a, cntcube.fits,,, "Output counts cube file"
22 22
23 # 23 #
24 # Energy binning parameters 24 # Energy binning parameters
25 #========================== 25 #==========================
26 -ebinalg, s, a, "LOG",FILE|LIN|LOG,, "Algorithm for defining energy bins" 26 +ebinalg, s, a, LOG,FILE|LIN|LOG,, "Algorithm for defining energy bins"
27 emin, r, a, 0.1,,, "Start value for first energy bin in TeV" 27 emin, r, a, 0.1,,, "Start value for first energy bin in TeV"
28 emax, r, a, 100.0,,, "Stop value for last energy bin in TeV" 28 emax, r, a, 100.0,,, "Stop value for last energy bin in TeV"
29 -enumbins, i, a, 20,,, "Number of energy bins"  
30 -ebinfile, f, a, "NONE",,, "Name of the file containing the energy bin definition" 29 +enumbins, i, a, 20,1,200, "Number of energy bins"
  30 +ebinfile, f, a, NONE,,, "Name of the file containing the energy bin definition"
31 31
32 # 32 #
33 # Spatial binning parameters 33 # Spatial binning parameters
@@ -36,10 +36,10 @@ usepnt, b, h, no,,, &quot;Use pointing instead of xref/yref parameters?&quot; @@ -36,10 +36,10 @@ usepnt, b, h, no,,, &quot;Use pointing instead of xref/yref parameters?&quot;
36 nxpix, i, a, 200,,, "Size of the X axis in pixels" 36 nxpix, i, a, 200,,, "Size of the X axis in pixels"
37 nypix, i, a, 200,,, "Size of the Y axis in pixels" 37 nypix, i, a, 200,,, "Size of the Y axis in pixels"
38 binsz, r, a, 0.02,,, "Image scale (in degrees/pixel)" 38 binsz, r, a, 0.02,,, "Image scale (in degrees/pixel)"
39 -coordsys, s, a, "CEL", CEL|GAL,,"Coordinate system (CEL - celestial, GAL - galactic)" 39 +coordsys, s, a, CEL,CEL|GAL,,"Coordinate system (CEL - celestial, GAL - galactic)"
40 xref, r, a, 83.63,0,360, "First coordinate of image center in degrees (RA or galactic l)" 40 xref, r, a, 83.63,0,360, "First coordinate of image center in degrees (RA or galactic l)"
41 yref, r, a, 22.01,-90,90, "Second coordinate of image center in degrees (DEC or galactic b)" 41 yref, r, a, 22.01,-90,90, "Second coordinate of image center in degrees (DEC or galactic b)"
42 -proj, s, a, "CAR",AIT|AZP|CAR|MER|MOL|STG|TAN,, "Projection method" 42 +proj, s, a, CAR,AIT|AZP|CAR|MER|MOL|STG|TAN,, "Projection method"
43 43
44 # 44 #
45 # Standard parameters 45 # Standard parameters
@@ -48,5 +48,5 @@ publish, b, h, no,,, &quot;Publish counts cube on VO Hub?&quot; @@ -48,5 +48,5 @@ publish, b, h, no,,, &quot;Publish counts cube on VO Hub?&quot;
48 chatter, i, h, 2,0,4, "Chattiness of output" 48 chatter, i, h, 2,0,4, "Chattiness of output"
49 clobber, b, h, yes,,, "Overwrite existing output files with new output files?" 49 clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
50 debug, b, h, no,,, "Debugging mode activated" 50 debug, b, h, no,,, "Debugging mode activated"
51 -mode, s, h, "ql",,, "Mode of automatic parameters"  
52 -logfile, f, h, "ctbin.log",,, "Log filename" 51 +mode, s, h, ql,,, "Mode of automatic parameters"
  52 +logfile, f, h, ctbin.log,,, "Log filename"
src/ctobssim/ctobssim.cpp
@@ -60,6 +60,8 @@ const double g_roi_margin = 0.5; //!&lt; Simulation radius margin (degrees) @@ -60,6 +60,8 @@ const double g_roi_margin = 0.5; //!&lt; Simulation radius margin (degrees)
60 60
61 /***********************************************************************//** 61 /***********************************************************************//**
62 * @brief Void constructor 62 * @brief Void constructor
  63 + *
  64 + * Constructs an empty ctobssim tool.
63 ***************************************************************************/ 65 ***************************************************************************/
64 ctobssim::ctobssim(void) : ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION) 66 ctobssim::ctobssim(void) : ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION)
65 { 67 {
@@ -76,7 +78,7 @@ ctobssim::ctobssim(void) : ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION) @@ -76,7 +78,7 @@ ctobssim::ctobssim(void) : ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION)
76 * 78 *
77 * @param[in] obs Observation container. 79 * @param[in] obs Observation container.
78 * 80 *
79 - * Constructs application by initialising from an observation container. 81 + * Constructs ctobssim tool from an observation container.
80 ***************************************************************************/ 82 ***************************************************************************/
81 ctobssim::ctobssim(const GObservations& obs) : 83 ctobssim::ctobssim(const GObservations& obs) :
82 ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION) 84 ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION)
@@ -98,7 +100,8 @@ ctobssim::ctobssim(const GObservations&amp; obs) : @@ -98,7 +100,8 @@ ctobssim::ctobssim(const GObservations&amp; obs) :
98 * @param[in] argc Number of arguments in command line. 100 * @param[in] argc Number of arguments in command line.
99 * @param[in] argv Array of command line arguments. 101 * @param[in] argv Array of command line arguments.
100 * 102 *
101 - * Constructs application using command line arguments for parameter setting. 103 + * Constructs ctobssim tool using command line arguments for user parameter
  104 + * setting.
102 ***************************************************************************/ 105 ***************************************************************************/
103 ctobssim::ctobssim(int argc, char *argv[]) : 106 ctobssim::ctobssim(int argc, char *argv[]) :
104 ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION, argc, argv) 107 ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION, argc, argv)
@@ -115,6 +118,8 @@ ctobssim::ctobssim(int argc, char *argv[]) : @@ -115,6 +118,8 @@ ctobssim::ctobssim(int argc, char *argv[]) :
115 * @brief Copy constructor 118 * @brief Copy constructor
116 * 119 *
117 * @param[in] app Application. 120 * @param[in] app Application.
  121 + *
  122 + * Constructs ctobssim tool from another ctobssim instance.
118 ***************************************************************************/ 123 ***************************************************************************/
119 ctobssim::ctobssim(const ctobssim& app) : ctool(app) 124 ctobssim::ctobssim(const ctobssim& app) : ctool(app)
120 { 125 {
@@ -131,6 +136,8 @@ ctobssim::ctobssim(const ctobssim&amp; app) : ctool(app) @@ -131,6 +136,8 @@ ctobssim::ctobssim(const ctobssim&amp; app) : ctool(app)
131 136
132 /***********************************************************************//** 137 /***********************************************************************//**
133 * @brief Destructor 138 * @brief Destructor
  139 + *
  140 + * Destructs ctobssim tool.
134 ***************************************************************************/ 141 ***************************************************************************/
135 ctobssim::~ctobssim(void) 142 ctobssim::~ctobssim(void)
136 { 143 {
@@ -151,8 +158,10 @@ ctobssim::~ctobssim(void) @@ -151,8 +158,10 @@ ctobssim::~ctobssim(void)
151 /***********************************************************************//** 158 /***********************************************************************//**
152 * @brief Assignment operator 159 * @brief Assignment operator
153 * 160 *
154 - * @param[in] app Application.  
155 - * @return Application. 161 + * @param[in] app ctobssim tool.
  162 + * @return ctobssim tool.
  163 + *
  164 + * Assigns ctobssim tool.
156 ***************************************************************************/ 165 ***************************************************************************/
157 ctobssim& ctobssim::operator=(const ctobssim& app) 166 ctobssim& ctobssim::operator=(const ctobssim& app)
158 { 167 {
@@ -185,7 +194,9 @@ ctobssim&amp; ctobssim::operator=(const ctobssim&amp; app) @@ -185,7 +194,9 @@ ctobssim&amp; ctobssim::operator=(const ctobssim&amp; app)
185 ==========================================================================*/ 194 ==========================================================================*/
186 195
187 /***********************************************************************//** 196 /***********************************************************************//**
188 - * @brief Clear application 197 + * @brief Clear ctobssim tool
  198 + *
  199 + * Clears ctobssim tool.
189 ***************************************************************************/ 200 ***************************************************************************/
190 void ctobssim::clear(void) 201 void ctobssim::clear(void)
191 { 202 {
@@ -205,10 +216,10 @@ void ctobssim::clear(void) @@ -205,10 +216,10 @@ void ctobssim::clear(void)
205 216
206 217
207 /***********************************************************************//** 218 /***********************************************************************//**
208 - * @brief Simulate event data 219 + * @brief Run the ctobssim tool.
209 * 220 *
210 - * This method runs the simulation. Results are not saved by this method.  
211 - * Invoke "save" to save the results. 221 + * Gets the user parameters, loops over all CTA observations in the
  222 + * observation container, and simulate events for each observation.
212 ***************************************************************************/ 223 ***************************************************************************/
213 void ctobssim::run(void) 224 void ctobssim::run(void)
214 { 225 {
@@ -286,24 +297,14 @@ void ctobssim::run(void) @@ -286,24 +297,14 @@ void ctobssim::run(void)
286 // Write observation(s) into logger 297 // Write observation(s) into logger
287 if (logTerse()) { 298 if (logTerse()) {
288 log << std::endl; 299 log << std::endl;
289 - if (m_obs.size() > 1) {  
290 - log.header1("Observations");  
291 - }  
292 - else {  
293 - log.header1("Observation");  
294 - } 300 + log.header1(gammalib::number("Observation", m_obs.size()));
295 log << m_obs << std::endl; 301 log << m_obs << std::endl;
296 } 302 }
297 303
298 // Write header 304 // Write header
299 if (logTerse()) { 305 if (logTerse()) {
300 log << std::endl; 306 log << std::endl;
301 - if (m_obs.size() > 1) {  
302 - log.header1("Simulate observations");  
303 - }  
304 - else {  
305 - log.header1("Simulate observation");  
306 - } 307 + log.header1(gammalib::number("Simulate observation", m_obs.size()));
307 } 308 }
308 309
309 // From here on the code can be parallelized if OpenMP support 310 // From here on the code can be parallelized if OpenMP support
@@ -334,14 +335,7 @@ void ctobssim::run(void) @@ -334,14 +335,7 @@ void ctobssim::run(void)
334 335
335 // Write header for observation 336 // Write header for observation
336 if (logTerse()) { 337 if (logTerse()) {
337 - std::string header = m_obs[i]->instrument() + " observation";  
338 - if (m_obs[i]->name().length() > 1) {  
339 - header += " \"" + m_obs[i]->name() + "\"";  
340 - }  
341 - if (m_obs[i]->id().length() > 1) {  
342 - header += " (id=" + m_obs[i]->id() +")";  
343 - }  
344 - wrklog.header3(header); 338 + wrklog.header3(get_obs_header(m_obs[i]));
345 } 339 }
346 340
347 // Get pointer on CTA observation 341 // Get pointer on CTA observation
@@ -1455,8 +1449,8 @@ void ctobssim::save_fits(void) @@ -1455,8 +1449,8 @@ void ctobssim::save_fits(void)
1455 1449
1456 // Log filename 1450 // Log filename
1457 if (logTerse()) { 1451 if (logTerse()) {
1458 - log << "Save event list into file \""+m_outevents+"\".";  
1459 - log << std::endl; 1452 + log << gammalib::parformat("Event list file");
  1453 + log << m_outevents << std::endl;
1460 } 1454 }
1461 1455
1462 // Save observation into FITS file 1456 // Save observation into FITS file
@@ -1483,7 +1477,7 @@ void ctobssim::save_xml(void) @@ -1483,7 +1477,7 @@ void ctobssim::save_xml(void)
1483 { 1477 {
1484 // Get output filename and prefix 1478 // Get output filename and prefix
1485 m_outevents = (*this)["outevents"].filename(); 1479 m_outevents = (*this)["outevents"].filename();
1486 - m_prefix = (*this)["prefix"].string(); 1480 + m_prefix = (*this)["prefix"].string();
1487 1481
1488 // Issue warning if output filename has no .xml suffix 1482 // Issue warning if output filename has no .xml suffix
1489 std::string suffix = gammalib::tolower(m_outevents.substr(m_outevents.length()-4,4)); 1483 std::string suffix = gammalib::tolower(m_outevents.substr(m_outevents.length()-4,4));
@@ -1513,15 +1507,16 @@ void ctobssim::save_xml(void) @@ -1513,15 +1507,16 @@ void ctobssim::save_xml(void)
1513 if (obs->events()->size() != 0) { 1507 if (obs->events()->size() != 0) {
1514 1508
1515 // Set event output file name 1509 // Set event output file name
1516 - std::string outfile = m_prefix + gammalib::str(i) + ".fits"; 1510 + std::string outfile = m_prefix + gammalib::str(i) +
  1511 + ".fits";
1517 1512
1518 // Store output file name in observation 1513 // Store output file name in observation
1519 obs->eventfile(outfile); 1514 obs->eventfile(outfile);
1520 1515
1521 // Log filename 1516 // Log filename
1522 if (logTerse()) { 1517 if (logTerse()) {
1523 - log << "Save event list into file \""+outfile+"\".";  
1524 - log << std::endl; 1518 + log << gammalib::parformat("Event list file");
  1519 + log << outfile << std::endl;
1525 } 1520 }
1526 1521
1527 // Save observation into FITS file 1522 // Save observation into FITS file
src/ctobssim/ctobssim.par
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 # File: ctobssim.par # 7 # File: ctobssim.par #
8 # Version: 1.1.0 # 8 # Version: 1.1.0 #
9 # # 9 # #
10 -# Author: Jurgen Knodlseder # 10 +# Author: Juergen Knoedlseder #
11 # Jurgen.Knodlseder@irap.omp.eu # 11 # Jurgen.Knodlseder@irap.omp.eu #
12 # IRAP # 12 # IRAP #
13 # # 13 # #
@@ -17,13 +17,13 @@ @@ -17,13 +17,13 @@
17 # 17 #
18 # General parameters 18 # General parameters
19 #=================== 19 #===================
20 -inobs, f, h, "NONE",,, "Input event list or observation definition XML file"  
21 -inmodel, f, a, "$CTOOLS/share/models/crab.xml",,, "Input model XML file"  
22 -caldb, s, a, "prod2",,, "Calibration database"  
23 -irf, s, a, "South_0.5h",,, "Instrument response function" 20 +inobs, f, h, NONE,,, "Input event list or observation definition XML file"
  21 +inmodel, f, a, $CTOOLS/share/models/crab.xml,,, "Input model XML file"
  22 +caldb, s, a, prod2,,, "Calibration database"
  23 +irf, s, a, South_0.5h,,, "Instrument response function"
24 edisp, b, h, no,,, "Apply energy dispersion?" 24 edisp, b, h, no,,, "Apply energy dispersion?"
25 -outevents, f, a, "events.fits",,, "Output event data file or observation definition XML file"  
26 -prefix, s, h, "sim_events_",,, "Prefix for event lists in observation definition XML file" 25 +outevents, f, a, events.fits,,, "Output event data file or observation definition XML file"
  26 +prefix, s, h, sim_events_,,, "Prefix for event lists in observation definition XML file"
27 27
28 # 28 #
29 # Simulation parameters 29 # Simulation parameters
@@ -38,7 +38,7 @@ emin, r, a, 0.1,,, &quot;Lower energy limit (TeV)&quot; @@ -38,7 +38,7 @@ emin, r, a, 0.1,,, &quot;Lower energy limit (TeV)&quot;
38 emax, r, a, 100.0,,, "Upper energy limit (TeV)" 38 emax, r, a, 100.0,,, "Upper energy limit (TeV)"
39 deadc, r, h, 0.95,0,1, "Average deadtime correction factor" 39 deadc, r, h, 0.95,0,1, "Average deadtime correction factor"
40 maxrate, r, h, 1.0e6,,, "Maximum photon rate" 40 maxrate, r, h, 1.0e6,,, "Maximum photon rate"
41 -eslices, i, h, 10,1,100,"Number of energy slices" 41 +eslices, i, h, 10,1,100, "Number of energy slices"
42 42
43 # 43 #
44 # Standard parameters 44 # Standard parameters
@@ -46,5 +46,5 @@ eslices, i, h, 10,1,100,&quot;Number of energy slices&quot; @@ -46,5 +46,5 @@ eslices, i, h, 10,1,100,&quot;Number of energy slices&quot;
46 chatter, i, h, 2,0,4, "Chattiness of output" 46 chatter, i, h, 2,0,4, "Chattiness of output"
47 clobber, b, h, yes,,, "Overwrite existing output files with new output files?" 47 clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
48 debug, b, h, no,,, "Debugging mode activated" 48 debug, b, h, no,,, "Debugging mode activated"
49 -mode, s, h, "ql",,, "Mode of automatic parameters"  
50 -logfile, f, h, "ctobssim.log",,, "Log filename" 49 +mode, s, h, ql,,, "Mode of automatic parameters"
  50 +logfile, f, h, ctobssim.log,,, "Log filename"
src/support/ctool.cpp
@@ -1108,6 +1108,39 @@ size_t ctool::get_current_rss(void) @@ -1108,6 +1108,39 @@ size_t ctool::get_current_rss(void)
1108 1108
1109 1109
1110 /***********************************************************************//** 1110 /***********************************************************************//**
  1111 + * @brief Return observation header string
  1112 + *
  1113 + * @param[in] obs Pointer to observation.
  1114 + * @return String containing observation information.
  1115 + *
  1116 + * Returns a string that contains observation information, including the
  1117 + * instrument name, the observation name, and the observation ID. The format
  1118 + * of the string is
  1119 + *
  1120 + * XXX observation "name" (id=YYYYY)
  1121 + *
  1122 + ***************************************************************************/
  1123 +std::string ctool::get_obs_header(const GObservation* obs)
  1124 +{
  1125 + // Initialise header string
  1126 + std::string header = obs->instrument() + " observation";
  1127 +
  1128 + // If observation name is not empty then add name
  1129 + if (!obs->name().empty()) {
  1130 + header += " \"" + obs->name() + "\"";
  1131 + }
  1132 +
  1133 + // If observation ID is not empty then add ID
  1134 + if (!obs->id().empty()) {
  1135 + header += " (id=" + obs->id() +")";
  1136 + }
  1137 +
  1138 + // Return header
  1139 + return header;
  1140 +}
  1141 +
  1142 +
  1143 +/***********************************************************************//**
1111 * @brief Dumps help text in the console 1144 * @brief Dumps help text in the console
1112 ***************************************************************************/ 1145 ***************************************************************************/
1113 void ctool::provide_help(void) const 1146 void ctool::provide_help(void) const
src/support/ctool.hpp
1 /*************************************************************************** 1 /***************************************************************************
2 * ctool - ctool base class * 2 * ctool - ctool base class *
3 * ----------------------------------------------------------------------- * 3 * ----------------------------------------------------------------------- *
4 - * copyright (C) 2014-2015 by Juergen Knoedlseder * 4 + * copyright (C) 2014-2016 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- * 5 * ----------------------------------------------------------------------- *
6 * * 6 * *
7 * This program is free software: you can redistribute it and/or modify * 7 * This program is free software: you can redistribute it and/or modify *
@@ -90,17 +90,18 @@ protected: @@ -90,17 +90,18 @@ protected:
90 void set_obs_bounds(GObservations& obs); 90 void set_obs_bounds(GObservations& obs);
91 GSkyDir get_mean_pointing(const GObservations& obs); 91 GSkyDir get_mean_pointing(const GObservations& obs);
92 size_t get_current_rss(void); 92 size_t get_current_rss(void);
  93 + std::string get_obs_header(const GObservation* obs);
93 94
94 // Protected members 95 // Protected members
95 - bool m_read_ahead; //!< Read ahead parameters 96 + bool m_read_ahead; //!< Read ahead output parameters
96 97
97 protected: 98 protected:
98 // Protected methods 99 // Protected methods
99 - void provide_help(void) const; 100 + void provide_help(void) const;
100 101
101 // Protected members 102 // Protected members
102 - bool m_use_xml; //!< Use XML file instead of FITS file for observations  
103 - GTimeReference m_cta_ref; //!< CTA time reference 103 + bool m_use_xml; //!< Use XML file instead of FITS file for observations
  104 + GTimeReference m_cta_ref; //!< CTA time reference
104 }; 105 };
105 106
106 107
test/test_ctbin.py
1 #! /usr/bin/env python 1 #! /usr/bin/env python
2 # ========================================================================== 2 # ==========================================================================
3 -# This scripts performs unit tests for the ctbin tool. 3 +# This scripts performs unit tests for the ctbin module.
4 # 4 #
5 # Copyright (C) 2014-2016 Juergen Knoedlseder 5 # Copyright (C) 2014-2016 Juergen Knoedlseder
6 # 6 #
@@ -22,13 +22,14 @@ import gammalib @@ -22,13 +22,14 @@ import gammalib
22 import ctools 22 import ctools
23 23
24 24
25 -# ========================= #  
26 -# Test class for ctbin tool #  
27 -# ========================= # 25 +# =========================== #
  26 +# Test class for ctbin module #
  27 +# =========================== #
28 class Test(gammalib.GPythonTestSuite): 28 class Test(gammalib.GPythonTestSuite):
29 """ 29 """
30 - Test class for ctbin tool. 30 + Test class for ctbin module.
31 """ 31 """
  32 +
32 # Constructor 33 # Constructor
33 def __init__(self): 34 def __init__(self):
34 """ 35 """
@@ -38,7 +39,7 @@ class Test(gammalib.GPythonTestSuite): @@ -38,7 +39,7 @@ class Test(gammalib.GPythonTestSuite):
38 gammalib.GPythonTestSuite.__init__(self) 39 gammalib.GPythonTestSuite.__init__(self)
39 40
40 # Set members 41 # Set members
41 - self.events_name = "data/crab_events.fits" 42 + self._events_name = "data/crab_events.fits"
42 43
43 # Return 44 # Return
44 return 45 return
@@ -52,19 +53,19 @@ class Test(gammalib.GPythonTestSuite): @@ -52,19 +53,19 @@ class Test(gammalib.GPythonTestSuite):
52 self.name("ctbin") 53 self.name("ctbin")
53 54
54 # Append tests 55 # Append tests
55 - self.append(self.test_functional, "Test ctbin functionality") 56 + self.append(self._test_ctbin, "Test ctbin")
56 57
57 # Return 58 # Return
58 return 59 return
59 60
60 - # Test ctbin functionnality  
61 - def test_functional(self): 61 + # Test ctbin
  62 + def _test_ctbin(self):
62 """ 63 """
63 - Test ctbin functionnality. 64 + Test ctbin.
64 """ 65 """
65 # Set-up ctbin 66 # Set-up ctbin
66 bin = ctools.ctbin() 67 bin = ctools.ctbin()
67 - bin["inobs"] = self.events_name 68 + bin["inobs"] = self._events_name
68 bin["outcube"] = "cntmap.fits" 69 bin["outcube"] = "cntmap.fits"
69 bin["ebinalg"] = "LOG" 70 bin["ebinalg"] = "LOG"
70 bin["emin"] = 0.1 71 bin["emin"] = 0.1
@@ -78,27 +79,154 @@ class Test(gammalib.GPythonTestSuite): @@ -78,27 +79,154 @@ class Test(gammalib.GPythonTestSuite):
78 bin["xref"] = 83.63 79 bin["xref"] = 83.63
79 bin["yref"] = 22.01 80 bin["yref"] = 22.01
80 81
81 - # Run tool  
82 - self.test_try("Run ctbin")  
83 - try:  
84 - bin.run()  
85 - self.test_try_success()  
86 - #except Exception as e:  
87 - # msg = "Exception occured in ctbin: %s." % (e,)  
88 - except:  
89 - msg = "Exception occured in ctbin."  
90 - self.test_try_failure(msg) 82 + # Run ctbin tool
  83 + bin.run()
  84 +
  85 + # Check content of observation and cube
  86 + self._test_observation(bin, 5542)
  87 + self._test_cube(bin.cube(), 5542)
  88 +
  89 + # Test copy constructor
  90 + cpy_bin = bin.copy()
  91 +
  92 + # Check content of observation and cube
  93 + self._test_observation(cpy_bin, 5542)
  94 + self._test_cube(cpy_bin.cube(), 5542)
  95 +
  96 + # Run copy of ctbin tool again
  97 + cpy_bin.run()
  98 +
  99 + # Check content of observation and cube. We expect now an empty
  100 + # event cube as on input the observation is binned, and any binned
  101 + # observation will be skipped, hence the counts cube should be
  102 + # empty.
  103 + self._test_observation(cpy_bin, 0)
  104 + self._test_cube(cpy_bin.cube(), 0)
  105 +
  106 + # Clear and run copy of ctbin again
  107 + #cpy_bin.clear()
  108 + #cpy_bin.run()
  109 +#RuntimeError: *** ERROR in GXmlAttribute::value(std::string): Invalid XML attribute value: *** ERROR in GPythonTestSuite::test: <type 'exceptions.RuntimeError'>
  110 +#*** ERROR in GApplicationPars::operator[](std::string&): Invalid argument. Parameter "debug" has not been found in parameter file.
  111 +#Please specify a valid parameter name.
91 112
92 # Save counts cube 113 # Save counts cube
93 - self.test_try("Save counts cube") 114 + bin.save()
  115 +
  116 + # Load counts cube and check content.
  117 + evt = gammalib.GCTAEventCube("cntmap.fits")
  118 + self._test_cube(evt, 5542)
  119 +
  120 + # Prepare observation container for stacked analysis
  121 + cta = gammalib.GCTAObservation(self._events_name)
  122 + obs = gammalib.GObservations()
  123 + cta.id("0001")
  124 + obs.append(cta)
  125 + cta.id("0002")
  126 + obs.append(cta)
  127 + cta.id("0003")
  128 + obs.append(cta)
  129 +
  130 + # Set-up ctbin using an observation container
  131 + bin = ctools.ctbin(obs)
  132 + bin["outcube"] = "cntmap.fits"
  133 + bin["ebinalg"] = "LOG"
  134 + bin["emin"] = 0.1
  135 + bin["emax"] = 100.0
  136 + bin["enumbins"] = 20
  137 + bin["nxpix"] = 200
  138 + bin["nypix"] = 200
  139 + bin["binsz"] = 0.02
  140 + bin["coordsys"] = "CEL"
  141 + bin["proj"] = "CAR"
  142 + bin["xref"] = 83.63
  143 + bin["yref"] = 22.01
  144 +
  145 + # Run ctbin tool
  146 + bin.run()
  147 +
  148 + # Check content of observation and cube (need multiplier=3 since
  149 + # three identical observations have been appended)
  150 + self._test_observation(bin, 5542, multiplier=3)
  151 + self._test_cube(bin.cube(), 5542, multiplier=3)
  152 +
  153 + # Set-up ctbin with invalid event file
  154 + bin = ctools.ctbin()
  155 + bin["inobs"] = "event_file_that_does_not_exist.fits"
  156 + bin["outcube"] = "cntmap.fits"
  157 + bin["ebinalg"] = "LOG"
  158 + bin["emin"] = 0.1
  159 + bin["emax"] = 100.0
  160 + bin["enumbins"] = 20
  161 + bin["nxpix"] = 200
  162 + bin["nypix"] = 200
  163 + bin["binsz"] = 0.02
  164 + bin["coordsys"] = "CEL"
  165 + bin["proj"] = "CAR"
  166 + bin["xref"] = 83.63
  167 + bin["yref"] = 22.01
  168 +
  169 + # Run ctbin tool
  170 + self.test_try("Run ctbin with invalid event file")
94 try: 171 try:
95 - bin.save()  
96 - self.test_try_success()  
97 - #except Exception as e:  
98 - # msg = "Exception occured in saving counts cube: %s." % (e,) 172 + bin.run()
  173 + self.test_try_failure()
99 except: 174 except:
100 - msg = "Exception occured in saving counts cube."  
101 - self.test_try_failure(msg) 175 + self.test_try_success()
  176 +
  177 + # Return
  178 + return
  179 +
  180 + # Check observation
  181 + def _test_observation(self, ctbin, nevents, multiplier=1):
  182 + """
  183 + Test content of an observation.
  184 +
  185 + Args:
  186 + ctbin: ctbin instance
  187 + nevents: Expected number of events
  188 +
  189 + Kwargs:
  190 + multiplier: Observation multiplier
  191 + """
  192 + # Test observation container
  193 + obs = gammalib.GCTAObservation(ctbin.obs()[0])
  194 + pnt = obs.pointing()
  195 + self.test_value(ctbin.obs().size(), 1,
  196 + "There is one observation")
  197 + self.test_assert(obs.instrument() == "CTA",
  198 + "Observation is CTA observation")
  199 + self.test_value(obs.ontime(), 1800.0*multiplier, 1.0e-6,
  200 + "Ontime is 1800 sec")
  201 + self.test_value(obs.livetime(), 1710.0*multiplier, 1.0e-6,
  202 + "Livetime is 1710 sec")
  203 + self.test_value(pnt.dir().ra_deg(), 83.63, 1.0e-6,
  204 + "Pointing Right Ascension is 83.63 deg")
  205 + self.test_value(pnt.dir().dec_deg(), 22.01, 1.0e-6,
  206 + "Pointing Declination is 22.01 deg")
  207 +
  208 + # Test event cube
  209 + self._test_cube(obs.events(), nevents, multiplier=multiplier)
  210 +
  211 + # Return
  212 + return
  213 +
  214 + # Check event cube
  215 + def _test_cube(self, cube, nevents, multiplier=1):
  216 + """
  217 + Test content of event cube."
  218 +
  219 + Args:
  220 + cube: Event cube
  221 + nevents: Expected number of events.
  222 +
  223 + Kwargs:
  224 + multiplier: Event number multiplier
  225 + """
  226 + # Test event cube
  227 + self.test_value(cube.size(), 800000, "800000 event bins")
  228 + self.test_value(cube.number(), nevents*multiplier,
  229 + str(nevents*multiplier)+" events")
102 230
103 # Return 231 # Return
104 return 232 return
test/test_ctobssim.py
1 #! /usr/bin/env python 1 #! /usr/bin/env python
2 # ========================================================================== 2 # ==========================================================================
3 -# This scripts performs unit tests for the ctobssim tool. 3 +# This scripts performs unit tests for the ctobssim module.
4 # 4 #
5 # Copyright (C) 2014-2016 Juergen Knoedlseder 5 # Copyright (C) 2014-2016 Juergen Knoedlseder
6 # 6 #
@@ -20,15 +20,17 @@ @@ -20,15 +20,17 @@
20 # ========================================================================== 20 # ==========================================================================
21 import gammalib 21 import gammalib
22 import ctools 22 import ctools
  23 +from cscripts import obsutils
23 24
24 25
25 -# ============================ #  
26 -# Test class for ctobssim tool #  
27 -# ============================ # 26 +# ============================== #
  27 +# Test class for ctobssim module #
  28 +# ============================== #
28 class Test(gammalib.GPythonTestSuite): 29 class Test(gammalib.GPythonTestSuite):
29 """ 30 """
30 - Test class for ctobssim tool. 31 + Test class for ctobssim module.
31 """ 32 """
  33 +
32 # Constructor 34 # Constructor
33 def __init__(self): 35 def __init__(self):
34 """ 36 """
@@ -38,9 +40,9 @@ class Test(gammalib.GPythonTestSuite): @@ -38,9 +40,9 @@ class Test(gammalib.GPythonTestSuite):
38 gammalib.GPythonTestSuite.__init__(self) 40 gammalib.GPythonTestSuite.__init__(self)
39 41
40 # Set members 42 # Set members
41 - self.model_name = "data/crab.xml"  
42 - self.caldb = "irf"  
43 - self.irf = "cta_dummy_irf" 43 + self._model_name = "data/crab.xml"
  44 + self._caldb = "irf"
  45 + self._irf = "cta_dummy_irf"
44 46
45 # Return 47 # Return
46 return 48 return
@@ -54,23 +56,23 @@ class Test(gammalib.GPythonTestSuite): @@ -54,23 +56,23 @@ class Test(gammalib.GPythonTestSuite):
54 self.name("ctobssim") 56 self.name("ctobssim")
55 57
56 # Append tests 58 # Append tests
57 - self.append(self.test_functional, "Test ctobssim functionality")  
58 - self.append(self.test_container, "Test ctobssim on observation container") 59 + self.append(self._test_ctobssim, "Test ctobssim")
  60 + #self.append(self._test_container, "Test ctobssim on observation container")
59 61
60 # Return 62 # Return
61 return 63 return
62 64
63 - # Test ctobssim functionnality  
64 - def test_functional(self): 65 + # Test ctobssim
  66 + def _test_ctobssim(self):
65 """ 67 """
66 - Test ctobssim functionnality. 68 + Test ctobssim.
67 """ 69 """
68 # Set-up ctobssim 70 # Set-up ctobssim
69 sim = ctools.ctobssim() 71 sim = ctools.ctobssim()
70 - sim["inmodel"] = self.model_name 72 + sim["inmodel"] = self._model_name
71 sim["outevents"] = "events.fits" 73 sim["outevents"] = "events.fits"
72 - sim["caldb"] = self.caldb  
73 - sim["irf"] = self.irf 74 + sim["caldb"] = self._caldb
  75 + sim["irf"] = self._irf
74 sim["ra"] = 83.63 76 sim["ra"] = 83.63
75 sim["dec"] = 22.01 77 sim["dec"] = 22.01
76 sim["rad"] = 10.0 78 sim["rad"] = 10.0
@@ -80,154 +82,123 @@ class Test(gammalib.GPythonTestSuite): @@ -80,154 +82,123 @@ class Test(gammalib.GPythonTestSuite):
80 sim["emax"] = 100.0 82 sim["emax"] = 100.0
81 83
82 # Run tool 84 # Run tool
83 - self.test_try("Run ctobssim")  
84 - try:  
85 - sim.run()  
86 - self.test_try_success()  
87 - #except Exception as e:  
88 - # msg = "Exception occured in ctobssim: %s." % (e,)  
89 - except:  
90 - msg = "Exception occured in ctobssim."  
91 - self.test_try_failure(msg) 85 + sim.run()
92 86
93 - # Retrieve observation and check content  
94 - obs = gammalib.GCTAObservation(sim.obs()[0])  
95 - pnt = obs.pointing()  
96 - evt = obs.events()  
97 - self.test_assert(obs.instrument() == "CTA", "Observation not a CTA observation")  
98 - self.test_value(sim.obs().size(), 1, "There is not a single observation")  
99 - self.test_value(obs.ontime(), 1800.0, 1.0e-6, "Ontime is not 1800 sec")  
100 - self.test_value(obs.livetime(), 1710.0, 1.0e-6, "Livetime is not 1710 sec")  
101 - self.test_value(pnt.dir().ra_deg(), 83.63, 1.0e-6, "ROI Right Ascension is not 83.63 deg")  
102 - self.test_value(pnt.dir().dec_deg(), 22.01, 1.0e-6, "ROI Declination is not 22.01 deg")  
103 - self.test_value(evt.size(), 4119, "Number of events is not 4119") 87 + # Check content of observation
  88 + self._test_observation(sim)
  89 + self._test_list(sim.obs()[0].events(), 4119)
104 90
105 # Save events 91 # Save events
106 - self.test_try("Save events")  
107 - try:  
108 - sim.save()  
109 - self.test_try_success()  
110 - #except Exception as e:  
111 - # msg = "Exception occured in saving events: %s." % (e,)  
112 - except:  
113 - msg = "Exception occured in saving events."  
114 - self.test_try_failure(msg) 92 + sim.save()
  93 +
  94 + # Load counts cube and check content.
  95 + evt = gammalib.GCTAEventList("events.fits")
  96 + self._test_list(evt, 4119)
115 97
116 - # Test ctobssim on observation container  
117 - def test_container(self):  
118 - """  
119 - Test ctobssim on observation container.  
120 - """  
121 # Set-up observation container 98 # Set-up observation container
122 - obs = self.set_obs(4) 99 + pnts = [{'ra': 83.63, 'dec': 21.01},
  100 + {'ra': 84.63, 'dec': 22.01},
  101 + {'ra': 83.63, 'dec': 23.01},
  102 + {'ra': 82.63, 'dec': 22.01}]
  103 + obs = obsutils.set_obs_list(pnts, caldb=self._caldb, irf=self._irf)
123 104
124 - # Set-up ctobssim 105 + # Set-up ctobssim from observation container
125 sim = ctools.ctobssim(obs) 106 sim = ctools.ctobssim(obs)
126 sim["outevents"] = "sim_events.xml" 107 sim["outevents"] = "sim_events.xml"
127 - sim["inmodel"] = self.model_name 108 + sim["inmodel"] = self._model_name
  109 +
128 # Run tool 110 # Run tool
129 - self.test_try("Run ctobssim")  
130 - try:  
131 - sim.run()  
132 - self.test_try_success()  
133 - #except Exception as e:  
134 - # msg = "Exception occured in ctobssim: %s." % (e,)  
135 - except:  
136 - msg = "Exception occured in ctobssim."  
137 - self.test_try_failure(msg) 111 + sim.run()
138 112
139 # Retrieve observation and check content 113 # Retrieve observation and check content
140 - self.test_value(sim.obs().size(), 4, "There are not 4 observations") 114 + self._test_observation(sim, nobs=4, pnts=pnts)
  115 + self._test_list(sim.obs()[0].events(), 4063)
  116 + self._test_list(sim.obs()[1].events(), 4059)
  117 + self._test_list(sim.obs()[2].events(), 4010)
  118 + self._test_list(sim.obs()[3].events(), 4138)
141 119
142 # Save events 120 # Save events
143 - self.test_try("Save events") 121 + sim.save()
  122 +
  123 + # Load events
  124 + obs = gammalib.GObservations("sim_events.xml")
  125 +
  126 + # Retrieve observation and check content
  127 + self._test_list(obs[0].events(), 4063)
  128 + self._test_list(obs[1].events(), 4059)
  129 + self._test_list(obs[2].events(), 4010)
  130 + self._test_list(obs[3].events(), 4138)
  131 +
  132 + # Set-up ctobssim with invalid event file
  133 + sim = ctools.ctobssim()
  134 + sim["inmodel"] = "model_file_that_does_not_exist.xml"
  135 + sim["outevents"] = "events.fits"
  136 + sim["caldb"] = self._caldb
  137 + sim["irf"] = self._irf
  138 + sim["ra"] = 83.63
  139 + sim["dec"] = 22.01
  140 + sim["rad"] = 10.0
  141 + sim["tmin"] = 0.0
  142 + sim["tmax"] = 1800.0
  143 + sim["emin"] = 0.1
  144 + sim["emax"] = 100.0
  145 +
  146 + # Run ctbin tool
  147 + self.test_try("Run ctobssim with invalid model file")
144 try: 148 try:
145 - sim.save()  
146 - self.test_try_success()  
147 - #except Exception as e:  
148 - # msg = "Exception occured in saving events: %s." % (e,) 149 + sim.run()
  150 + self.test_try_failure()
149 except: 151 except:
150 - msg = "Exception occured in saving events."  
151 - self.test_try_failure(msg) 152 + self.test_try_success()
  153 +
  154 + # Return
  155 + return
152 156
153 - # Setup observation container  
154 - def set_obs(self, number): 157 + # Check observation
  158 + def _test_observation(self, ctobssim, nobs=1,
  159 + pnts=[{'ra': 83.63, 'dec': 22.01}]):
155 """ 160 """
156 - Setup observation container. 161 + Test content of an observation.
  162 +
  163 + Args:
  164 + ctobssim: ctobssim instance
  165 +
  166 + Kwargs:
  167 + nobs: Number of observations
  168 + pnts: List of pointing dictionaries
157 """ 169 """
158 - # Initialise empty observation container  
159 - obs = gammalib.GObservations()  
160 -  
161 - # Initialise first time and identifier  
162 - tstart = 0.0  
163 - offset = -float(number)/2.0  
164 -  
165 - # Loop over number of observations  
166 - for i in range(number):  
167 - id = "%6.6d" % i  
168 - obs_cta = self.set_one_obs(id, offset)  
169 - offset += 1.0  
170 - tstart += 1830.0  
171 - obs.append(obs_cta)  
172 -  
173 - # Return observation container  
174 - return obs  
175 -  
176 - # Setup one observation  
177 - def set_one_obs(self, id, offset, \  
178 - tstart=0.0, duration=1800.0, deadc=0.95, \  
179 - emin=0.1, emax=100.0, rad=5.0, \  
180 - irf="cta_dummy_irf", caldb="dummy"): 170 + # Test observation container
  171 + self.test_value(ctobssim.obs().size(), nobs,
  172 + "There is one observation")
  173 + for i in range(ctobssim.obs().size()):
  174 + obs = gammalib.GCTAObservation(ctobssim.obs()[i])
  175 + pnt = obs.pointing()
  176 + self.test_assert(obs.instrument() == "CTA",
  177 + "Observation is CTA observation")
  178 + self.test_value(obs.ontime(), 1800.0, 1.0e-6,
  179 + "Ontime is 1800 sec")
  180 + self.test_value(obs.livetime(), 1710.0, 1.0e-6,
  181 + "Livetime is 1710 sec")
  182 + self.test_value(pnt.dir().ra_deg(), pnts[i]['ra'], 1.0e-6,
  183 + "Pointing Right Ascension is "+str(pnts[i]['ra'])+" deg")
  184 + self.test_value(pnt.dir().dec_deg(), pnts[i]['dec'], 1.0e-6,
  185 + "Pointing Declination is "+str(pnts[i]['dec'])+" deg")
  186 +
  187 + # Return
  188 + return
  189 +
  190 + # Check event list
  191 + def _test_list(self, list, nevents):
181 """ 192 """
182 - Setup one observation for test purposes. 193 + Test content of event list."
  194 +
  195 + Args:
  196 + list: Event list
  197 + nevents: Expected number of events.
183 """ 198 """
184 - # Allocate CTA observation  
185 - obs_cta = gammalib.GCTAObservation()  
186 -  
187 - # Set calibration database  
188 - db = gammalib.GCaldb()  
189 - if (gammalib.dir_exists(self.caldb)):  
190 - db.rootdir(self.caldb)  
191 - else:  
192 - db.open("cta", self.caldb)  
193 -  
194 - # Set pointing direction  
195 - pntdir = gammalib.GSkyDir()  
196 - pntdir.radec_deg(83.63, 22.01+offset)  
197 - pnt = gammalib.GCTAPointing()  
198 - pnt.dir(pntdir)  
199 - obs_cta.pointing(pnt)  
200 -  
201 - # Set ROI  
202 - roi = gammalib.GCTARoi()  
203 - instdir = gammalib.GCTAInstDir()  
204 - instdir.dir(pntdir)  
205 - roi.centre(instdir)  
206 - roi.radius(rad)  
207 -  
208 - # Set GTI  
209 - gti = gammalib.GGti()  
210 - gti.append(gammalib.GTime(tstart), gammalib.GTime(tstart+duration))  
211 -  
212 - # Set energy boundaries  
213 - ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, "TeV"), \  
214 - gammalib.GEnergy(emax, "TeV"))  
215 -  
216 - # Allocate event list  
217 - events = gammalib.GCTAEventList()  
218 - events.roi(roi)  
219 - events.gti(gti)  
220 - events.ebounds(ebounds)  
221 - obs_cta.events(events)  
222 -  
223 - # Set instrument response  
224 - obs_cta.response(self.irf, db)  
225 -  
226 - # Set ontime, livetime, and deadtime correction factor  
227 - obs_cta.ontime(duration)  
228 - obs_cta.livetime(duration*deadc)  
229 - obs_cta.deadc(deadc)  
230 - obs_cta.id(id)  
231 -  
232 - # Return CTA observation  
233 - return obs_cta 199 + # Test event list
  200 + self.test_value(list.size(), nevents, str(nevents)+" elements")
  201 + self.test_value(list.number(), nevents, str(nevents)+" events")
  202 +
  203 + # Return
  204 + return
test/test_python_cscripts.py
@@ -34,7 +34,7 @@ def test(installed=False): @@ -34,7 +34,7 @@ def test(installed=False):
34 Perform unit testing for Python interface. 34 Perform unit testing for Python interface.
35 """ 35 """
36 # Allocate test suite container 36 # Allocate test suite container
37 - suites = gammalib.GTestSuites("cscripts unit testing") 37 + suites = gammalib.GTestSuites("cscripts Python module unit testing")
38 38
39 # Allocate test suites and append them to the container 39 # Allocate test suites and append them to the container
40 suite_cscaldb = test_cscaldb.Test() 40 suite_cscaldb = test_cscaldb.Test()
test/test_python_ctools.py
@@ -48,7 +48,7 @@ def test(installed=False): @@ -48,7 +48,7 @@ def test(installed=False):
48 Perform unit testing for Python interface. 48 Perform unit testing for Python interface.
49 """ 49 """
50 # Allocate test suite container 50 # Allocate test suite container
51 - suites = gammalib.GTestSuites("ctools unit testing") 51 + suites = gammalib.GTestSuites("ctools Python module unit testing")
52 52
53 # Allocate test suites and append them to the container 53 # Allocate test suites and append them to the container
54 suite_ctobssim = test_ctobssim.Test() 54 suite_ctobssim = test_ctobssim.Test()