Commit 29bbc390ffb2cc94e8931e741400c9d70d5625e5

Authored by Jürgen Knödlseder
1 parent 15960584

Review cslightcrv script (#1828)

Showing 1 changed file with 230 additions and 224 deletions
cscripts/cslightcrv.py
... ... @@ -28,7 +28,7 @@ import ctools
28 28 # ================ #
29 29 class cslightcrv(ctools.cscript):
30 30 """
31   - Generates a lightcurve.
  31 + Generates a lightcurve
32 32  
33 33 The cslightcrv class generates a light curve for Imaging Air Cherenkov
34 34 Telescope event data by performing a maximum likelihood fit using
... ... @@ -64,14 +64,14 @@ class cslightcrv(ctools.cscript):
64 64 # Constructor
65 65 def __init__(self, *argv):
66 66 """
67   - Constructor.
  67 + Constructor
68 68 """
69 69 # Set name
70   - self._name = "cslightcrv"
71   - self._version = "1.1.0"
  70 + self._name = 'cslightcrv'
  71 + self._version = '1.1.0'
72 72  
73 73 # Initialise some members
74   - self._srcname = ""
  74 + self._srcname = ''
75 75 self._tbins = gammalib.GGti()
76 76 self._stacked = False
77 77 self._fits = gammalib.GFits()
... ... @@ -93,17 +93,17 @@ class cslightcrv(ctools.cscript):
93 93 # Private methods
94 94 def _get_parameters(self):
95 95 """
96   - Get parameters from parfile.
  96 + Get parameters from parfile
97 97 """
98 98 # Setup observations
99 99 self._setup_observations(self._obs)
100 100  
101 101 # Set models if there are none in the container
102 102 if self._obs.models().size() == 0:
103   - self._obs.models(self["inmodel"].filename())
  103 + self._obs.models(self['inmodel'].filename())
104 104  
105 105 # Get source name
106   - self._srcname = self["srcname"].string()
  106 + self._srcname = self['srcname'].string()
107 107  
108 108 # Get time boundaries
109 109 self._tbins = self._create_tbounds()
... ... @@ -111,7 +111,7 @@ class cslightcrv(ctools.cscript):
111 111 # Set stacked analysis flag to True if the requested number of
112 112 # energy bins is positive. Otherwise an unbinned analysis will
113 113 # be done and the stacked analysis flag will be set to False.
114   - if self["enumbins"].integer() > 0:
  114 + if self['enumbins'].integer() > 0:
115 115 self._stacked = True
116 116 else:
117 117 self._stacked = False
... ... @@ -120,61 +120,56 @@ class cslightcrv(ctools.cscript):
120 120 # do not store the actual parameter values as we do not want
121 121 # too many instance attributes with enhances the maintenance
122 122 # costs.
123   - self["emin"].real()
124   - self["emax"].real()
  123 + self['emin'].real()
  124 + self['emax'].real()
125 125 if self._stacked:
126   - self["coordsys"].string()
127   - self["proj"].string()
128   - self["xref"].real()
129   - self["yref"].real()
130   - self["nxpix"].integer()
131   - self["nypix"].integer()
132   - self["binsz"].real()
  126 + self['coordsys'].string()
  127 + self['proj'].string()
  128 + self['xref'].real()
  129 + self['yref'].real()
  130 + self['nxpix'].integer()
  131 + self['nypix'].integer()
  132 + self['binsz'].real()
133 133  
134 134 # Do the same for the hidden parameters, just in case
135   - self["edisp"].boolean()
136   - self["calc_ulim"].boolean()
137   - self["calc_ts"].boolean()
138   - self["fix_bkg"].boolean()
139   - self["fix_srcs"].boolean()
  135 + self['edisp'].boolean()
  136 + self['calc_ulim'].boolean()
  137 + self['calc_ts'].boolean()
  138 + self['fix_bkg'].boolean()
  139 + self['fix_srcs'].boolean()
140 140  
141 141 # Read ahead output parameters
142 142 if self._read_ahead():
143   - self["outfile"].filename()
  143 + self['outfile'].filename()
144 144  
145 145 # Write input parameters into logger
146 146 if self._logTerse():
147 147 self._log_parameters()
148   - self._log("\n")
  148 + self._log('\n')
149 149  
150 150 # Return
151 151 return
152 152  
153 153 def _create_tbounds(self):
154 154 """
155   - Creates light curve time bins.
156   -
157   - The method reads the following user parameters:
158   - tbinalg: Time binning algorithm
159   - tbinfile: Time binning file (FITS or ASCII)
160   - tmin: Start time (MJD)
161   - tmax: Stop time (MJD)
162   - tbins: Number of time bins
  155 + Creates light curve time bins
163 156  
164   - Returns:
165   - Light curve bins in form of a GTI.
  157 + Returns
  158 + -------
  159 + gti : `~gammalib.GGti`
  160 + Light curve bins in form of Good Time Intervals
166 161 """
167 162 # Initialise Good Time Intervals
168 163 gti = gammalib.GGti()
169 164  
170 165 # Get algorithm to use for defining the time intervals
171   - algorithm = self["tbinalg"].string()
  166 + algorithm = self['tbinalg'].string()
172 167  
173 168 # Handle a FITS or a ASCII file for time bin definition
174   - if algorithm == "FILE":
  169 + if algorithm == 'FILE':
175 170  
176 171 # Get the filename
177   - filename = self["tbinfile"].filename()
  172 + filename = self['tbinfile'].filename()
178 173  
179 174 # If the file a FITS file then load GTIs
180 175 if filename.is_fits():
... ... @@ -190,12 +185,12 @@ class cslightcrv(ctools.cscript):
190 185 gti.append(tmin,tmax)
191 186  
192 187 # Handle linear time binning
193   - elif algorithm == "LIN":
  188 + elif algorithm == 'LIN':
194 189  
195 190 # Get start and stop time and number of time bins
196   - time_min = self["tmin"].real()
197   - time_max = self["tmax"].real()
198   - nbins = self["tbins"].integer()
  191 + time_min = self['tmin'].real()
  192 + time_max = self['tmax'].real()
  193 + nbins = self['tbins'].integer()
199 194  
200 195 # Compute time step and setup time intervals
201 196 time_step = (time_max - time_min) / float(nbins)
... ... @@ -207,7 +202,7 @@ class cslightcrv(ctools.cscript):
207 202 gti.append(tmin,tmax)
208 203  
209 204 # Handle usage of observation GTIs
210   - elif algorithm == "GTI":
  205 + elif algorithm == 'GTI':
211 206  
212 207 # Append the GTIs of all observations
213 208 for obs in self._obs:
... ... @@ -225,9 +220,11 @@ class cslightcrv(ctools.cscript):
225 220  
226 221 def _get_free_par_names(self):
227 222 """
228   - Return list of free parameter names.
  223 + Return list of free parameter names
229 224  
230   - Returns:
  225 + Returns
  226 + -------
  227 + names : list of str
231 228 List of free parameter names.
232 229 """
233 230 # Initialise list of free parameter names
... ... @@ -243,75 +240,78 @@ class cslightcrv(ctools.cscript):
243 240  
244 241 def _adjust_model_pars(self):
245 242 """
246   - Adjust model parameters dependent on user parameters.
  243 + Adjust model parameters dependent on user parameters
247 244 """
248 245 # Write header
249 246 if self._logTerse():
250   - self._log("\n")
251   - self._log.header1("Adjust model parameters")
  247 + self._log('\n')
  248 + self._log.header1('Adjust model parameters')
252 249  
253 250 # Adjust model parameters dependent on input user parameters
254 251 for model in self._obs.models():
255 252  
256   - # Set TS flag for all models to false. The source of interest
257   - # will be set to true later
  253 + # Set TS flag for all models to false. The source of interest will
  254 + # be set to true later
258 255 model.tscalc(False)
259 256  
  257 + # Get the model classname to distinguish later sky from background
  258 + # models
  259 + classname = model.classname()
  260 +
260 261 # Log model name
261 262 if self._logNormal():
262 263 self._log.header3(model.name())
263 264  
264   - # Deal with the source of interest
  265 + # If the model is the source of interest and the 'calc_ts' parameter
  266 + # is true then enable the TS computation for the source
265 267 if model.name() == self._srcname:
266   - if self["calc_ts"].boolean():
  268 + if self['calc_ts'].boolean():
267 269 model.tscalc(True)
268 270  
269   - elif (self["fix_bkg"].boolean() and
270   - model.classname() != "GModelSky"):
271   - for par in model:
272   - if par.is_free():
273   - par.fix()
274   - if self._logNormal():
275   - self._log(gammalib.parformat(par.name()))
276   - self._log("fixed\n")
277   -
278   - elif (self["fix_srcs"].boolean() and
279   - model.classname() == "GModelSky"):
  271 + # ... otherwise, if the model is not a sky model and the 'fix_bkg'
  272 + # parameter is true or if the model is a sky model and the
  273 + # 'fix_srcs' parameter is true then fix all parameters of the model
  274 + elif ((self['fix_bkg'].boolean() and classname != 'GModelSky') or
  275 + (self['fix_srcs'].boolean() and classname == 'GModelSky')):
280 276 for par in model:
281 277 if par.is_free():
282 278 par.fix()
283 279 if self._logNormal():
284 280 self._log(gammalib.parformat(par.name()))
285   - self._log("fixed\n")
  281 + self._log('fixed\n')
286 282  
287 283 # Return
288 284 return
289 285  
290 286 def _create_fits_table(self, results):
291 287 """
292   - Creates FITS binary table containing light curve results.
  288 + Creates FITS binary table containing light curve results
293 289  
294   - Args:
295   - results: List of result dictionaries.
  290 + Parameters
  291 + ----------
  292 + results : list of dict
  293 + List of result dictionaries
296 294  
297   - Returns:
298   - FITS binary table containing light curve.
  295 + Returns
  296 + -------
  297 + table : `~gammalib.GFitsBinTable`
  298 + FITS binary table containing light curve
299 299 """
300 300 # Determine number of rows in FITS table
301 301 nrows = len(results)
302 302  
303 303 # Create FITS Table with extension "LIGHTCURVE"
304 304 table = gammalib.GFitsBinTable(nrows)
305   - table.extname("LIGHTCURVE")
  305 + table.extname('LIGHTCURVE')
306 306  
307 307 # Append time columns
308   - mjd = gammalib.GFitsTableDoubleCol("MJD", nrows)
309   - e_mjd = gammalib.GFitsTableDoubleCol("e_MJD", nrows)
310   - mjd.unit("days")
311   - e_mjd.unit("days")
  308 + mjd = gammalib.GFitsTableDoubleCol('MJD', nrows)
  309 + e_mjd = gammalib.GFitsTableDoubleCol('e_MJD', nrows)
  310 + mjd.unit('days')
  311 + e_mjd.unit('days')
312 312 for i, result in enumerate(results):
313   - mjd[i] = result["mjd"]
314   - e_mjd[i] = result["e_mjd"]
  313 + mjd[i] = result['mjd']
  314 + e_mjd[i] = result['e_mjd']
315 315 table.append(mjd)
316 316 table.append(e_mjd)
317 317  
... ... @@ -319,7 +319,7 @@ class cslightcrv(ctools.cscript):
319 319 for par in self._obs.models()[self._srcname]:
320 320 if par.is_free():
321 321 name = par.name()
322   - e_name = "e_"+par.name()
  322 + e_name = 'e_'+par.name()
323 323 col = gammalib.GFitsTableDoubleCol(name, nrows)
324 324 e_col = gammalib.GFitsTableDoubleCol(e_name, nrows)
325 325 col.unit(par.unit())
... ... @@ -331,14 +331,14 @@ class cslightcrv(ctools.cscript):
331 331 table.append(e_col)
332 332  
333 333 # Append Test Statistic column
334   - ts = gammalib.GFitsTableDoubleCol("TS", nrows)
  334 + ts = gammalib.GFitsTableDoubleCol('TS', nrows)
335 335 for i, result in enumerate(results):
336   - ts[i] = result["ts"]
  336 + ts[i] = result['ts']
337 337 table.append(ts)
338 338  
339 339 # Append upper limit column
340   - ulimit = gammalib.GFitsTableDoubleCol("UpperLimit", nrows)
341   - ulimit.unit("ph/cm2/s")
  340 + ulimit = gammalib.GFitsTableDoubleCol('UpperLimit', nrows)
  341 + ulimit.unit('ph/cm2/s')
342 342 for i, result in enumerate(results):
343 343 ulimit[i] = result['ulimit']
344 344 table.append(ulimit)
... ... @@ -348,28 +348,32 @@ class cslightcrv(ctools.cscript):
348 348  
349 349 def _compute_ulimit(self, obs):
350 350 """
351   - Computes upper flux limit.
  351 + Computes upper flux limit
352 352  
353   - Args:
354   - obs: Observation container.
  353 + Parameters
  354 + ----------
  355 + obs : `~gammalib.GObservations`
  356 + Observation container
355 357  
356   - Returns:
357   - Upper flux limit (-1 of not computed).
  358 + Returns
  359 + -------
  360 + ulimit : float
  361 + Upper flux limit (-1.0 of not computed)
358 362 """
359 363 # Initialise upper flux limit
360 364 ulimit_value = -1.0
361 365  
362 366 # Perform computation only if requested
363   - if self["calc_ulim"].boolean():
  367 + if self['calc_ulim'].boolean():
364 368  
365 369 # Write header in logger
366 370 if self._logExplicit():
367   - self._log.header3("Computing upper flux limit")
  371 + self._log.header3('Computing upper flux limit')
368 372  
369 373 # Create upper limit object
370 374 ulimit = ctools.ctulimit(obs)
371   - ulimit["srcname"] = self._srcname
372   - ulimit["eref"] = 1.0
  375 + ulimit['srcname'] = self._srcname
  376 + ulimit['eref'] = 1.0
373 377  
374 378 # Try to run upper limit and catch exceptions
375 379 try:
... ... @@ -377,7 +381,7 @@ class cslightcrv(ctools.cscript):
377 381 ulimit_value = ulimit.flux_ulimit()
378 382 except:
379 383 if self._logTerse():
380   - self._log("Upper limit flux calculation failed.s\n")
  384 + self._log('Upper limit flux calculation failed.\n')
381 385 ulimit_value = -1.0
382 386  
383 387 # Return upper limit
... ... @@ -385,129 +389,129 @@ class cslightcrv(ctools.cscript):
385 389  
386 390 def _bin_observation(self, obs):
387 391 """
388   - Bin an observation is a binned analysis was requested.
  392 + Bin an observation if a binned analysis was requested
389 393  
390   - Args:
391   - obs: Observation container.
  394 + Parameters
  395 + ----------
  396 + obs : `~gammalib.GObservations`
  397 + Observation container
392 398  
393   - Returns:
394   - Observation container with a binned.
  399 + Returns
  400 + -------
  401 + obs : `~gammalib.GObservations`
  402 + Observation container where the first observation is a binned observation
395 403 """
396 404 # Header
397 405 if self._logExplicit():
398   - self._log.header3("Binning events")
  406 + self._log.header3('Binning events')
399 407  
400 408 # Bin events
401 409 cntcube = ctools.ctbin(obs)
402   - cntcube["usepnt"] = False
403   - cntcube["ebinalg"] = "LOG"
404   - cntcube["xref"] = self["xref"].real()
405   - cntcube["yref"] = self["yref"].real()
406   - cntcube["binsz"] = self["binsz"].real()
407   - cntcube["nxpix"] = self["nxpix"].integer()
408   - cntcube["nypix"] = self["nypix"].integer()
409   - cntcube["enumbins"] = self["enumbins"].integer()
410   - cntcube["emin"] = self["emin"].real()
411   - cntcube["emax"] = self["emax"].real()
412   - cntcube["coordsys"] = self["coordsys"].string()
413   - cntcube["proj"] = self["proj"].string()
  410 + cntcube['usepnt'] = False
  411 + cntcube['ebinalg'] = 'LOG'
  412 + cntcube['xref'] = self['xref'].real()
  413 + cntcube['yref'] = self['yref'].real()
  414 + cntcube['binsz'] = self['binsz'].real()
  415 + cntcube['nxpix'] = self['nxpix'].integer()
  416 + cntcube['nypix'] = self['nypix'].integer()
  417 + cntcube['enumbins'] = self['enumbins'].integer()
  418 + cntcube['emin'] = self['emin'].real()
  419 + cntcube['emax'] = self['emax'].real()
  420 + cntcube['coordsys'] = self['coordsys'].string()
  421 + cntcube['proj'] = self['proj'].string()
414 422 cntcube.run()
415 423  
416 424 # Header
417 425 if self._logExplicit():
418   - self._log.header3("Creating exposure cube")
  426 + self._log.header3('Creating exposure cube')
419 427  
420 428 # Create exposure cube
421 429 expcube = ctools.ctexpcube(obs)
422   - expcube["incube"] = "NONE"
423   - expcube["usepnt"] = False
424   - expcube["ebinalg"] = "LOG"
425   - expcube["xref"] = self["xref"].real()
426   - expcube["yref"] = self["yref"].real()
427   - expcube["binsz"] = self["binsz"].real()
428   - expcube["nxpix"] = self["nxpix"].integer()
429   - expcube["nypix"] = self["nypix"].integer()
430   - expcube["enumbins"] = self["enumbins"].integer()
431   - expcube["emin"] = self["emin"].real()
432   - expcube["emax"] = self["emax"].real()
433   - expcube["coordsys"] = self["coordsys"].string()
434   - expcube["proj"] = self["proj"].string()
  430 + expcube['incube'] = 'NONE'
  431 + expcube['usepnt'] = False
  432 + expcube['ebinalg'] = 'LOG'
  433 + expcube['xref'] = self['xref'].real()
  434 + expcube['yref'] = self['yref'].real()
  435 + expcube['binsz'] = self['binsz'].real()
  436 + expcube['nxpix'] = self['nxpix'].integer()
  437 + expcube['nypix'] = self['nypix'].integer()
  438 + expcube['enumbins'] = self['enumbins'].integer()
  439 + expcube['emin'] = self['emin'].real()
  440 + expcube['emax'] = self['emax'].real()
  441 + expcube['coordsys'] = self['coordsys'].string()
  442 + expcube['proj'] = self['proj'].string()
435 443 expcube.run()
436 444  
437 445 # Header
438 446 if self._logExplicit():
439   - self._log.header3("Creating point spread function cube")
  447 + self._log.header3('Creating point spread function cube')
440 448  
441 449 # Compute spatial binning for point spread function and
442 450 # energy dispersion cubes
443   - binsz = 10.0 * self["binsz"].real()
444   - nxpix = self["nxpix"].integer() // 10 # Make sure result is int
445   - nypix = self["nypix"].integer() // 10 # Make sure result is int
446   - if nxpix < 2:
447   - nxpix = 2
448   - if nypix < 2:
449   - nypix = 2
  451 + binsz = 10.0 * self['binsz'].real()
  452 + nxpix = min(self['nxpix'].integer() // 10, 2) # Make sure result is int
  453 + nypix = min(self['nypix'].integer() // 10, 2) # Make sure result is int
450 454  
451 455 # Create point spread function cube
452 456 psfcube = ctools.ctpsfcube(obs)
453   - psfcube["incube"] = "NONE"
454   - psfcube["usepnt"] = False
455   - psfcube["ebinalg"] = "LOG"
456   - psfcube["xref"] = self["xref"].real()
457   - psfcube["yref"] = self["yref"].real()
458   - psfcube["binsz"] = binsz
459   - psfcube["nxpix"] = nxpix
460   - psfcube["nypix"] = nypix
461   - psfcube["enumbins"] = self["enumbins"].integer()
462   - psfcube["emin"] = self["emin"].real()
463   - psfcube["emax"] = self["emax"].real()
464   - psfcube["coordsys"] = self["coordsys"].string()
465   - psfcube["proj"] = self["proj"].string()
  457 + psfcube['incube'] = 'NONE'
  458 + psfcube['usepnt'] = False
  459 + psfcube['ebinalg'] = 'LOG'
  460 + psfcube['xref'] = self['xref'].real()
  461 + psfcube['yref'] = self['yref'].real()
  462 + psfcube['binsz'] = binsz
  463 + psfcube['nxpix'] = nxpix
  464 + psfcube['nypix'] = nypix
  465 + psfcube['enumbins'] = self['enumbins'].integer()
  466 + psfcube['emin'] = self['emin'].real()
  467 + psfcube['emax'] = self['emax'].real()
  468 + psfcube['coordsys'] = self['coordsys'].string()
  469 + psfcube['proj'] = self['proj'].string()
466 470 psfcube.run()
467 471  
468 472 # Check if we need to include energy dispersion
469   - if self["edisp"].boolean():
  473 + if self['edisp'].boolean():
470 474  
471 475 # Header
472 476 if self._logExplicit():
473   - self._log.header3("Creating energy dispersion cube")
  477 + self._log.header3('Creating energy dispersion cube')
474 478  
475 479 # Create energy dispersion cube
476 480 edispcube = ctools.ctedispcube(obs)
477   - edispcube["incube"] = "NONE"
478   - edispcube["usepnt"] = False
479   - edispcube["ebinalg"] = "LOG"
480   - edispcube["xref"] = self["xref"].real()
481   - edispcube["yref"] = self["yref"].real()
482   - edispcube["binsz"] = binsz
483   - edispcube["nxpix"] = nxpix
484   - edispcube["nypix"] = nypix
485   - edispcube["enumbins"] = self["enumbins"].integer()
486   - edispcube["emin"] = self["emin"].real()
487   - edispcube["emax"] = self["emax"].real()
488   - edispcube["coordsys"] = self["coordsys"].string()
489   - edispcube["proj"] = self["proj"].string()
  481 + edispcube['incube'] = 'NONE'
  482 + edispcube['usepnt'] = False
  483 + edispcube['ebinalg'] = 'LOG'
  484 + edispcube['xref'] = self['xref'].real()
  485 + edispcube['yref'] = self['yref'].real()
  486 + edispcube['binsz'] = binsz
  487 + edispcube['nxpix'] = nxpix
  488 + edispcube['nypix'] = nypix
  489 + edispcube['enumbins'] = self['enumbins'].integer()
  490 + edispcube['emin'] = self['emin'].real()
  491 + edispcube['emax'] = self['emax'].real()
  492 + edispcube['coordsys'] = self['coordsys'].string()
  493 + edispcube['proj'] = self['proj'].string()
490 494 edispcube.run()
491 495  
492 496 # Header
493 497 if self._logExplicit():
494   - self._log.header3("Creating background cube")
  498 + self._log.header3('Creating background cube')
495 499  
496 500 # Create background cube
497 501 bkgcube = ctools.ctbkgcube(obs)
498   - bkgcube["incube"] = "NONE"
499   - bkgcube["usepnt"] = False
500   - bkgcube["ebinalg"] = "LOG"
501   - bkgcube["xref"] = self["xref"].real()
502   - bkgcube["yref"] = self["yref"].real()
503   - bkgcube["binsz"] = self["binsz"].real()
504   - bkgcube["nxpix"] = self["nxpix"].integer()
505   - bkgcube["nypix"] = self["nypix"].integer()
506   - bkgcube["enumbins"] = self["enumbins"].integer()
507   - bkgcube["emin"] = self["emin"].real()
508   - bkgcube["emax"] = self["emax"].real()
509   - bkgcube["coordsys"] = self["coordsys"].string()
510   - bkgcube["proj"] = self["proj"].string()
  502 + bkgcube['incube'] = 'NONE'
  503 + bkgcube['usepnt'] = False
  504 + bkgcube['ebinalg'] = 'LOG'
  505 + bkgcube['xref'] = self['xref'].real()
  506 + bkgcube['yref'] = self['yref'].real()
  507 + bkgcube['binsz'] = self['binsz'].real()
  508 + bkgcube['nxpix'] = self['nxpix'].integer()
  509 + bkgcube['nypix'] = self['nypix'].integer()
  510 + bkgcube['enumbins'] = self['enumbins'].integer()
  511 + bkgcube['emin'] = self['emin'].real()
  512 + bkgcube['emax'] = self['emax'].real()
  513 + bkgcube['coordsys'] = self['coordsys'].string()
  514 + bkgcube['proj'] = self['proj'].string()
511 515 bkgcube.run()
512 516  
513 517 # Retrieve a new oberservation container
... ... @@ -517,20 +521,17 @@ class cslightcrv(ctools.cscript):
517 521 models = bkgcube.models()
518 522  
519 523 # Set stacked response
520   - if self["edisp"].boolean():
521   - new_obs[0].response(expcube.expcube(),
522   - psfcube.psfcube(),
523   - edispcube.edispcube(),
524   - bkgcube.bkgcube())
  524 + if self['edisp'].boolean():
  525 + new_obs[0].response(expcube.expcube(), psfcube.psfcube(),
  526 + edispcube.edispcube(), bkgcube.bkgcube())
525 527 else:
526   - new_obs[0].response(expcube.expcube(),
527   - psfcube.psfcube(),
  528 + new_obs[0].response(expcube.expcube(), psfcube.psfcube(),
528 529 bkgcube.bkgcube())
529 530  
530 531 # Fix background models if required
531   - if self["fix_bkg"].boolean():
  532 + if self['fix_bkg'].boolean():
532 533 for model in models:
533   - if model.classname() != "GModelSky":
  534 + if model.classname() != 'GModelSky':
534 535 for par in model:
535 536 par.fix()
536 537  
... ... @@ -544,7 +545,7 @@ class cslightcrv(ctools.cscript):
544 545 # Public methods
545 546 def run(self):
546 547 """
547   - Run the script.
  548 + Run the script
548 549 """
549 550 # Switch screen logging on in debug mode
550 551 if self._logDebug():
... ... @@ -555,18 +556,18 @@ class cslightcrv(ctools.cscript):
555 556  
556 557 # Write observation into logger
557 558 if self._logTerse():
558   - self._log("\n")
559   - self._log.header1("Observation")
  559 + self._log('\n')
  560 + self._log.header1(gammalib.number('Observation',len(self._obs)))
560 561 self._log(str(self._obs))
561   - self._log("\n")
  562 + self._log('\n')
562 563  
563 564 # Adjust model parameters dependent on user parameters
564 565 self._adjust_model_pars()
565 566  
566 567 # Write header
567 568 if self._logTerse():
568   - self._log("\n")
569   - self._log.header1("Generate lightcurve")
  569 + self._log('\n')
  570 + self._log.header1('Generate lightcurve')
570 571  
571 572 # Initialise list of result dictionaries
572 573 results = []
... ... @@ -583,9 +584,7 @@ class cslightcrv(ctools.cscript):
583 584  
584 585 # Write time bin into header
585 586 if self._logTerse():
586   - self._log.header2("MJD "+
587   - str(tmin.mjd())+"-"+
588   - str(tmax.mjd()))
  587 + self._log.header2('MJD '+str(tmin.mjd())+'-'+str(tmax.mjd()))
589 588  
590 589 # Compute time bin center and time width
591 590 twidth = 0.5 * (tmax - tmin) # in seconds
... ... @@ -601,17 +600,17 @@ class cslightcrv(ctools.cscript):
601 600  
602 601 # Log information
603 602 if self._logExplicit():
604   - self._log.header3("Selecting events")
  603 + self._log.header3('Selecting events')
605 604  
606 605 # Select events
607 606 select = ctools.ctselect(self._obs)
608   - select["emin"] = self["emin"].real()
609   - select["emax"] = self["emax"].real()
610   - select["tmin"] = tmin.convert(self._time_reference())
611   - select["tmax"] = tmax.convert(self._time_reference())
612   - select["rad"] = "UNDEFINED"
613   - select["ra"] = "UNDEFINED"
614   - select["dec"] = "UNDEFINED"
  607 + select['emin'] = self['emin'].real()
  608 + select['emax'] = self['emax'].real()
  609 + select['tmin'] = tmin.convert(self._time_reference())
  610 + select['tmax'] = tmax.convert(self._time_reference())
  611 + select['rad'] = 'UNDEFINED'
  612 + select['ra'] = 'UNDEFINED'
  613 + select['dec'] = 'UNDEFINED'
615 614 select.run()
616 615  
617 616 # Retrieve observation
... ... @@ -625,11 +624,11 @@ class cslightcrv(ctools.cscript):
625 624  
626 625 # Header
627 626 if self._logExplicit():
628   - self._log.header3("Fitting the data")
  627 + self._log.header3('Fitting the data')
629 628  
630 629 # Do maximum likelihood model fitting
631 630 like = ctools.ctlike(obs)
632   - like["edisp"] = self["edisp"].boolean()
  631 + like['edisp'] = self['edisp'].boolean()
633 632 like.run()
634 633  
635 634 # Skip bin if no event was present
... ... @@ -637,13 +636,13 @@ class cslightcrv(ctools.cscript):
637 636  
638 637 # Signal skipping of bin
639 638 if self._logTerse():
640   - self._log(gammalib.parformat("Warning"))
641   - self._log("No event in this time bin, skip bin.\n")
  639 + self._log(gammalib.parformat('Warning'))
  640 + self._log('No event in this time bin, skip bin.\n')
642 641  
643 642 # Set all results to 0
644 643 for par in pars:
645 644 result['values'][par] = 0.0
646   - result['values']["e_"+par] = 0.0
  645 + result['values']['e_'+par] = 0.0
647 646  
648 647 # Append result
649 648 results.append(result)
... ... @@ -657,7 +656,7 @@ class cslightcrv(ctools.cscript):
657 656 # Extract parameter values
658 657 for par in pars:
659 658 result['values'][par] = source.spectral()[par].value()
660   - result['values']["e_"+par] = source.spectral()[par].error()
  659 + result['values']['e_'+par] = source.spectral()[par].error()
661 660  
662 661 # Calculate upper limit (-1 if not computed)
663 662 ulimit_value = self._compute_ulimit(like.obs())
... ... @@ -665,7 +664,7 @@ class cslightcrv(ctools.cscript):
665 664 result['ulimit'] = ulimit_value
666 665  
667 666 # Extract Test Statistic value
668   - if self["calc_ts"].boolean():
  667 + if self['calc_ts'].boolean():
669 668 result['ts'] = source.ts()
670 669  
671 670 # Append result to list of dictionaries
... ... @@ -673,7 +672,7 @@ class cslightcrv(ctools.cscript):
673 672  
674 673 # Log results for this time bin
675 674 if self._logNormal():
676   - self._log.header3("Results")
  675 + self._log.header3('Results')
677 676 pars = self._get_free_par_names()
678 677 for par in pars:
679 678 value = source.spectral()[par].value()
... ... @@ -681,17 +680,17 @@ class cslightcrv(ctools.cscript):
681 680 unit = source.spectral()[par].unit()
682 681 self._log(gammalib.parformat(par))
683 682 self._log(str(value))
684   - self._log(" +/- ")
  683 + self._log(' +/- ')
685 684 self._log(str(error))
686   - self._log(" ")
  685 + self._log(' ')
687 686 self._log(unit)
688   - self._log("\n")
  687 + self._log('\n')
689 688 if result['ulimit'] > 0.0:
690   - self._log(gammalib.parformat("Upper flux limit"))
691   - self._log(str(result['ulimit'])+" ph/cm2/s\n")
692   - if self["calc_ts"].boolean():
693   - self._log(gammalib.parformat("Test Statistic"))
694   - self._log(str(result['ts'])+"\n")
  689 + self._log(gammalib.parformat('Upper flux limit'))
  690 + self._log(str(result['ulimit'])+' ph/cm2/s\n')
  691 + if self['calc_ts'].boolean():
  692 + self._log(gammalib.parformat('Test Statistic'))
  693 + self._log(str(result['ts'])+'\n')
695 694  
696 695 # Create FITS table from results
697 696 table = self._create_fits_table(results)
... ... @@ -705,7 +704,7 @@ class cslightcrv(ctools.cscript):
705 704  
706 705 def execute(self):
707 706 """
708   - Execute the script.
  707 + Execute the script
709 708 """
710 709 # Open logfile
711 710 self.logFileOpen()
... ... @@ -724,7 +723,7 @@ class cslightcrv(ctools.cscript):
724 723  
725 724 def save(self):
726 725 """
727   - Save light curve.
  726 + Save light curve
728 727 """
729 728 # Write header
730 729 if self._logTerse():
... ... @@ -732,16 +731,16 @@ class cslightcrv(ctools.cscript):
732 731 self._log.header1('Save light curve')
733 732  
734 733 # Get light curve filename
735   - outfile = self["outfile"].filename()
  734 + outfile = self['outfile'].filename()
736 735  
737 736 # Continue only filename and residual map are valid
738 737 if self._fits != None:
739 738  
740 739 # Log file name
741 740 if self._logTerse():
742   - self._log(gammalib.parformat("Light curve file"))
  741 + self._log(gammalib.parformat('Light curve file'))
743 742 self._log(outfile.url())
744   - self._log("\n")
  743 + self._log('\n')
745 744  
746 745 # Save spectrum
747 746 self._fits.saveto(outfile, self._clobber())
... ... @@ -753,18 +752,25 @@ class cslightcrv(ctools.cscript):
753 752 """
754 753 Return light curve FITS file.
755 754  
756   - Returns:
757   - FITS file containing light curve.
  755 + Returns
  756 + -------
  757 + fits : `~gammalib.GFits()`
  758 + FITS file containing light curve
758 759 """
759 760 # Return
760 761 return self._fits
761 762  
762 763 def models(self, models):
763 764 """
764   - Set model.
  765 + Set model
  766 +
  767 + Parameters
  768 + ----------
  769 + models : `~gammalib.GModels()`
  770 + Set model container
765 771 """
766 772 # Copy models
767   - self._obs.models(models.clone())
  773 + self._obs.models(models)
768 774  
769 775 # Return
770 776 return
... ...