Commit 74bcfe43362af53c2d26c0766c6ad4724cb3eb61

Authored by Jürgen Knödlseder
1 parent 7de3c72c

Tune cspull scripts and associated scripts

(still need to remove some debug statements later)
cscripts/cspull.py
@@ -30,22 +30,16 @@ from cscripts import obsutils @@ -30,22 +30,16 @@ from cscripts import obsutils
30 # ============ # 30 # ============ #
31 class cspull(ctools.cscript): 31 class cspull(ctools.cscript):
32 """ 32 """
33 - Generates pull distributions for a model.  
34 -  
35 - This class implements the pull distribution generation script. It derives  
36 - from the ctools.cscript class which provides support for parameter  
37 - files, command line arguments, and logging. In that way the Python  
38 - script behaves just as a regular ctool. 33 + Generates pull distributions for a model
39 """ 34 """
40 -  
41 # Constructor 35 # Constructor
42 def __init__(self, *argv): 36 def __init__(self, *argv):
43 """ 37 """
44 Constructor. 38 Constructor.
45 """ 39 """
46 # Set name 40 # Set name
47 - self._name = "cspull"  
48 - self._version = "1.1.0" 41 + self._name = 'cspull'
  42 + self._version = '1.1.0'
49 43
50 # Initialise some members 44 # Initialise some members
51 self._edisp = False 45 self._edisp = False
@@ -54,15 +48,15 @@ class cspull(ctools.cscript): @@ -54,15 +48,15 @@ class cspull(ctools.cscript):
54 self._bckcube = None 48 self._bckcube = None
55 self._edispcube = None 49 self._edispcube = None
56 self._stackmodels = None 50 self._stackmodels = None
57 - self._coordsys = "CEL"  
58 - self._proj = "TAN"  
59 - self._log_clients = False 51 + self._coordsys = 'CEL'
  52 + self._proj = 'TAN'
  53 + self._log_clients = False # Static parameter
60 self._offset = 0.0 54 self._offset = 0.0
61 self._ntrials = 0 55 self._ntrials = 0
62 self._outfile = gammalib.GFilename() 56 self._outfile = gammalib.GFilename()
63 self._npix = 0 57 self._npix = 0
64 self._binsz = 0.0 58 self._binsz = 0.0
65 - self._pattern = "single" 59 + self._pattern = 'single'
66 self._enumbins = 0 60 self._enumbins = 0
67 self._seed = 1 61 self._seed = 1
68 self._chatter = 2 62 self._chatter = 2
@@ -81,7 +75,7 @@ class cspull(ctools.cscript): @@ -81,7 +75,7 @@ class cspull(ctools.cscript):
81 # Private methods 75 # Private methods
82 def _get_parameters(self): 76 def _get_parameters(self):
83 """ 77 """
84 - Get parameters from parfile. 78 + Get parameters from parfile
85 """ 79 """
86 # If there are no observations in container then get some ... 80 # If there are no observations in container then get some ...
87 if self._obs.size() == 0: 81 if self._obs.size() == 0:
@@ -89,8 +83,8 @@ class cspull(ctools.cscript): @@ -89,8 +83,8 @@ class cspull(ctools.cscript):
89 83
90 # Check for requested pattern and use above 84 # Check for requested pattern and use above
91 # observation parameters to set wobble pattern 85 # observation parameters to set wobble pattern
92 - self._pattern = self["pattern"].string()  
93 - if self._pattern == "four": 86 + self._pattern = self['pattern'].string()
  87 + if self._pattern == 'four':
94 self._obs = self._set_obs() 88 self._obs = self._set_obs()
95 89
96 # ... otherwise add response information and energy boundaries 90 # ... otherwise add response information and energy boundaries
@@ -99,153 +93,173 @@ class cspull(ctools.cscript): @@ -99,153 +93,173 @@ class cspull(ctools.cscript):
99 self._setup_observations(self._obs) 93 self._setup_observations(self._obs)
100 94
101 # Get number of energy bins 95 # Get number of energy bins
102 - self._enumbins = self["enumbins"].integer() 96 + self._enumbins = self['enumbins'].integer()
103 97
104 # Read parameters for binned if requested 98 # Read parameters for binned if requested
105 if self._enumbins != 0: 99 if self._enumbins != 0:
106 - self._npix = self["npix"].integer()  
107 - self._binsz = self["binsz"].real()  
108 - self._coordsys = self["coordsys"].string()  
109 - self._proj = self["proj"].string() 100 + self._npix = self['npix'].integer()
  101 + self._binsz = self['binsz'].real()
  102 + self._coordsys = self['coordsys'].string()
  103 + self._proj = self['proj'].string()
110 104
111 # Set models if we have none 105 # Set models if we have none
112 if self._obs.models().size() == 0: 106 if self._obs.models().size() == 0:
113 - self._obs.models(self["inmodel"].filename()) 107 + self._obs.models(self['inmodel'].filename())
114 108
115 # Read other parameters 109 # Read other parameters
116 - self._outfile = self["outfile"].filename()  
117 - self._ntrials = self["ntrials"].integer()  
118 - self._edisp = self["edisp"].boolean()  
119 - self._offset = self["offset"].real()  
120 - self._seed = self["seed"].integer()  
121 - self._chatter = self["chatter"].integer() 110 + self._outfile = self['outfile'].filename()
  111 + self._ntrials = self['ntrials'].integer()
  112 + self._edisp = self['edisp'].boolean()
  113 + self._offset = self['offset'].real()
  114 + self._seed = self['seed'].integer()
  115 + self._chatter = self['chatter'].integer()
122 116
123 # Query some parameters 117 # Query some parameters
124 - self["profile"].boolean() 118 + self['profile'].boolean()
125 119
126 # Write input parameters into logger 120 # Write input parameters into logger
127 if self._logTerse(): 121 if self._logTerse():
128 self._log_parameters() 122 self._log_parameters()
129 - self._log("\n") 123 + self._log('\n')
130 124
131 # Return 125 # Return
132 return 126 return
133 127
134 def _set_obs(self): 128 def _set_obs(self):
135 """ 129 """
136 - Set CTA observation(s). 130 + Set CTA observation(s)
137 131
138 - Returns:  
139 - An observation container. 132 + Returns
  133 + -------
  134 + obs : `~gammalib.GObservations`
  135 + Observation container.
140 """ 136 """
141 # Setup observation definition list 137 # Setup observation definition list
142 obsdeflist = obsutils.set_obs_patterns(self._pattern, 138 obsdeflist = obsutils.set_obs_patterns(self._pattern,
143 - ra=self["ra"].real(),  
144 - dec=self["dec"].real(),  
145 - offset=self["offset"].real()) 139 + ra=self['ra'].real(),
  140 + dec=self['dec'].real(),
  141 + offset=self['offset'].real())
146 142
147 # Create list of observations 143 # Create list of observations
148 obs = obsutils.set_obs_list(obsdeflist, 144 obs = obsutils.set_obs_list(obsdeflist,
149 - tstart=self["tmin"].real(),  
150 - duration=self["tmax"].real()-self["tmin"].real(),  
151 - deadc=self["deadc"].real(),  
152 - emin=self["emin"].real(),  
153 - emax=self["emax"].real(),  
154 - rad=self["rad"].real(),  
155 - irf=self["irf"].string(),  
156 - caldb=self["caldb"].string()) 145 + tstart=self['tmin'].real(),
  146 + duration=self['tmax'].real()-self['tmin'].real(),
  147 + deadc=self['deadc'].real(),
  148 + emin=self['emin'].real(),
  149 + emax=self['emax'].real(),
  150 + rad=self['rad'].real(),
  151 + irf=self['irf'].string(),
  152 + caldb=self['caldb'].string())
157 153
158 # Return observation container 154 # Return observation container
159 return obs 155 return obs
160 156
161 def _set_stacked_irf(self): 157 def _set_stacked_irf(self):
162 """ 158 """
163 - For stacked analysis prepare stacked irfs 159 + Prepare stacked IRFs for stacked analysis
164 """ 160 """
165 # Write header into logger 161 # Write header into logger
166 if self._logTerse(): 162 if self._logTerse():
167 - self._log("\n")  
168 - self._log.header1("Compute stacked response") 163 + self._log('\n')
  164 + self._log.header1('Compute stacked response')
169 165
170 # Get stacked exposure 166 # Get stacked exposure
171 expcube = ctools.ctexpcube(self._obs) 167 expcube = ctools.ctexpcube(self._obs)
172 - expcube["incube"] = "NONE"  
173 - expcube["usepnt"] = True  
174 - expcube["ebinalg"] = "LOG"  
175 - expcube["binsz"] = self._binsz  
176 - expcube["nxpix"] = self._npix  
177 - expcube["nypix"] = self._npix  
178 - expcube["enumbins"] = self._enumbins  
179 - expcube["emin"] = self["emin"].real()  
180 - expcube["emax"] = self["emax"].real()  
181 - expcube["coordsys"] = self._coordsys  
182 - expcube["proj"] = self._proj 168 + expcube['incube'] = 'NONE'
  169 + expcube['usepnt'] = True
  170 + expcube['ebinalg'] = 'LOG'
  171 + expcube['binsz'] = self._binsz
  172 + expcube['nxpix'] = self._npix
  173 + expcube['nypix'] = self._npix
  174 + expcube['enumbins'] = self._enumbins
  175 + expcube['emin'] = self['emin'].real()
  176 + expcube['emax'] = self['emax'].real()
  177 + expcube['coordsys'] = self._coordsys
  178 + expcube['proj'] = self._proj
  179 + expcube['chatter'] = self._chatter
  180 + expcube['debug'] = self._logDebug()
183 expcube.run() 181 expcube.run()
  182 + # JK: Debug
  183 + expcube['outcube'] = 'expcube.fits'
  184 + expcube.save()
184 185
185 # Notify exposure computation 186 # Notify exposure computation
186 if self._logTerse(): 187 if self._logTerse():
187 - self._log("Computed exposure cube\n") 188 + self._log('Computed exposure cube\n')
188 189
189 # Get stacked Psf 190 # Get stacked Psf
190 psfcube = ctools.ctpsfcube(self._obs) 191 psfcube = ctools.ctpsfcube(self._obs)
191 - psfcube["incube"] = "NONE"  
192 - psfcube["usepnt"] = True  
193 - psfcube["ebinalg"] = "LOG"  
194 - psfcube["binsz"] = self._binsz*10.0  
195 - psfcube["nxpix"] = self._npix/10  
196 - psfcube["nypix"] = self._npix/10  
197 - psfcube["enumbins"] = self._enumbins  
198 - psfcube["emin"] = self["emin"].real()  
199 - psfcube["emax"] = self["emax"].real()  
200 - psfcube["coordsys"] = self._coordsys  
201 - psfcube["proj"] = self._proj 192 + psfcube['incube'] = 'NONE'
  193 + psfcube['usepnt'] = True
  194 + psfcube['ebinalg'] = 'LOG'
  195 + psfcube['binsz'] = self._binsz*10.0
  196 + psfcube['nxpix'] = self._npix/10
  197 + psfcube['nypix'] = self._npix/10
  198 + psfcube['enumbins'] = self._enumbins
  199 + psfcube['emin'] = self['emin'].real()
  200 + psfcube['emax'] = self['emax'].real()
  201 + psfcube['coordsys'] = self._coordsys
  202 + psfcube['proj'] = self._proj
  203 + psfcube['chatter'] = self._chatter
  204 + psfcube['debug'] = self._logDebug()
202 psfcube.run() 205 psfcube.run()
  206 + # JK: Debug
  207 + psfcube['outcube'] = 'psfcube.fits'
  208 + psfcube.save()
203 209
204 # Notify Psf computation 210 # Notify Psf computation
205 if self._logTerse(): 211 if self._logTerse():
206 - self._log("Computed point spread function cube\n") 212 + self._log('Computed point spread function cube\n')
207 213
208 # Optionally get stacked Edisp 214 # Optionally get stacked Edisp
209 if self._edisp: 215 if self._edisp:
210 edispcube = ctools.ctedispcube(self._obs) 216 edispcube = ctools.ctedispcube(self._obs)
211 - edispcube["incube"] = "NONE"  
212 - edispcube["usepnt"] = True  
213 - edispcube["ebinalg"] = "LOG"  
214 - edispcube["binsz"] = self._binsz*10.0  
215 - edispcube["nxpix"] = self._npix/10  
216 - edispcube["nypix"] = self._npix/10  
217 - edispcube["enumbins"] = self._enumbins  
218 - edispcube["emin"] = self["emin"].real()  
219 - edispcube["emax"] = self["emax"].real()  
220 - edispcube["coordsys"] = self._coordsys  
221 - edispcube["proj"] = self._proj  
222 - edispcube.run() 217 + edispcube['incube'] = 'NONE'
  218 + edispcube['usepnt'] = True
  219 + edispcube['ebinalg'] = 'LOG'
  220 + edispcube['binsz'] = self._binsz*10.0
  221 + edispcube['nxpix'] = self._npix/10
  222 + edispcube['nypix'] = self._npix/10
  223 + edispcube['enumbins'] = self._enumbins
  224 + edispcube['emin'] = self['emin'].real()
  225 + edispcube['emax'] = self['emax'].real()
  226 + edispcube['coordsys'] = self._coordsys
  227 + edispcube['proj'] = self._proj
  228 + edispcube['chatter'] = self._chatter
  229 + edispcube['debug'] = self._logDebug()
  230 + edispcube.run()
223 231
224 # Store result 232 # Store result
225 self._edispcube = edispcube.edispcube().copy() 233 self._edispcube = edispcube.edispcube().copy()
226 234
227 # Logging 235 # Logging
228 if self._logTerse(): 236 if self._logTerse():
229 - self._log("Computed energy dispersion cube\n") 237 + self._log('Computed energy dispersion cube\n')
230 238
231 # Get stacked background 239 # Get stacked background
232 bkgcube = ctools.ctbkgcube(self._obs) 240 bkgcube = ctools.ctbkgcube(self._obs)
233 - bkgcube["incube"] = "NONE"  
234 - bkgcube["usepnt"] = True  
235 - bkgcube["ebinalg"] = "LOG"  
236 - bkgcube["binsz"] = self._binsz  
237 - bkgcube["nxpix"] = self._npix  
238 - bkgcube["nypix"] = self._npix  
239 - bkgcube["enumbins"] = self._enumbins  
240 - bkgcube["emin"] = self["emin"].real()  
241 - bkgcube["emax"] = self["emax"].real()  
242 - bkgcube["coordsys"] = self._coordsys  
243 - bkgcube["proj"] = self._proj 241 + bkgcube['incube'] = 'NONE'
  242 + bkgcube['usepnt'] = True
  243 + bkgcube['ebinalg'] = 'LOG'
  244 + bkgcube['binsz'] = self._binsz
  245 + bkgcube['nxpix'] = self._npix
  246 + bkgcube['nypix'] = self._npix
  247 + bkgcube['enumbins'] = self._enumbins
  248 + bkgcube['emin'] = self['emin'].real()
  249 + bkgcube['emax'] = self['emax'].real()
  250 + bkgcube['coordsys'] = self._coordsys
  251 + bkgcube['proj'] = self._proj
  252 + bkgcube['chatter'] = self._chatter
  253 + bkgcube['debug'] = self._logDebug()
244 bkgcube.run() 254 bkgcube.run()
  255 + # JK: Debug
  256 + bkgcube['outcube'] = 'bkgcube.fits'
  257 + bkgcube['outmodel'] = 'cube_model.xml'
  258 + bkgcube.save()
245 259
246 # Notify background cube computation 260 # Notify background cube computation
247 if self._logTerse(): 261 if self._logTerse():
248 - self._log("Computed background cube\n") 262 + self._log('Computed background cube\n')
249 263
250 # Store results 264 # Store results
251 self._exposure = expcube.expcube().copy() 265 self._exposure = expcube.expcube().copy()
@@ -256,19 +270,63 @@ class cspull(ctools.cscript): @@ -256,19 +270,63 @@ class cspull(ctools.cscript):
256 # Return 270 # Return
257 return 271 return
258 272
259 - def _trial(self, seed): 273 + def _obs_string(self, obs):
260 """ 274 """
261 - Compute the pull for a single trial. 275 + Generate summary string for observation
  276 +
  277 + Parameters
  278 + ----------
  279 + obs : `~gammalib.GCTAObservation`
  280 + Observation
262 281
263 - Args:  
264 - seed: Random number generator seed. 282 + Returns
  283 + -------
  284 + text : str
  285 + Summary string
  286 + """
  287 + # Extract information from observation
  288 + emin = obs.events().ebounds().emin().TeV()
  289 + emax = obs.events().ebounds().emax().TeV()
  290 + events = obs.events().number()
  291 + binned = (obs.events().classname() == 'GCTAEventCube')
  292 + if binned:
  293 + mode = 'binned'
  294 + else:
  295 + mode = 'unbinned'
  296 +
  297 + # Compose summary string
  298 + if events > 0:
  299 + text = '%d events, %.3f-%.3f TeV, %s' % (events, emin, emax, mode)
  300 + else:
  301 + text = '%.3f-%.3f TeV, %s' % (emin, emax, mode)
  302 +
  303 + # Return summary string
  304 + return text
  305 +
  306 + def _trial(self, seed, stacked):
  307 + """
  308 + Compute the pull for a single trial
  309 +
  310 + Parameters
  311 + ----------
  312 + seed : int
  313 + Random number generator seed
  314 + stacked : bool
  315 + Use stacked analysis
  316 +
  317 + Returns
  318 + -------
  319 + result : dict
  320 + Dictionary of results
265 """ 321 """
266 # Write header 322 # Write header
267 if self._logNormal(): 323 if self._logNormal():
268 - self._log.header2("Trial "+str(seed+1)) 324 + self._log.header2('Trial '+str(seed-self._seed+1))
269 325
270 # Simulate events 326 # Simulate events
271 obs = obsutils.sim(self._obs, 327 obs = obsutils.sim(self._obs,
  328 + emin=self['emin'].real(),
  329 + emax=self['emax'].real(),
272 nbins=self._enumbins, 330 nbins=self._enumbins,
273 seed=seed, 331 seed=seed,
274 binsz=self._binsz, 332 binsz=self._binsz,
@@ -281,7 +339,7 @@ class cspull(ctools.cscript): @@ -281,7 +339,7 @@ class cspull(ctools.cscript):
281 chatter=self._chatter) 339 chatter=self._chatter)
282 340
283 # Set response for a stacked observation 341 # Set response for a stacked observation
284 - if self._obs.size() > 1 and self._enumbins > 0: 342 + if stacked:
285 if self._edisp: 343 if self._edisp:
286 obs[0].response(self._exposure, self._psfcube, 344 obs[0].response(self._exposure, self._psfcube,
287 self._edispcube, self._bckcube) 345 self._edispcube, self._bckcube)
@@ -289,6 +347,8 @@ class cspull(ctools.cscript): @@ -289,6 +347,8 @@ class cspull(ctools.cscript):
289 obs[0].response(self._exposure, self._psfcube, 347 obs[0].response(self._exposure, self._psfcube,
290 self._bckcube) 348 self._bckcube)
291 obs.models(self._stackmodels) 349 obs.models(self._stackmodels)
  350 + # JK: Test
  351 + obs[0].save('stacked_cube.fits', True)
292 352
293 # Determine number of events in simulation 353 # Determine number of events in simulation
294 nevents = 0.0 354 nevents = 0.0
@@ -297,13 +357,21 @@ class cspull(ctools.cscript): @@ -297,13 +357,21 @@ class cspull(ctools.cscript):
297 357
298 # Write simulation results 358 # Write simulation results
299 if self._logNormal(): 359 if self._logNormal():
300 - self._log.header3("Simulation")  
301 - self._log.parformat("Number of simulated events") 360 + self._log.header3('Simulation')
  361 + for run in self._obs:
  362 + self._log.parformat('Input observation %s' % (run.id()))
  363 + self._log(self._obs_string(run))
  364 + self._log('\n')
  365 + for run in obs:
  366 + self._log.parformat('Output observation %s' % (run.id()))
  367 + self._log(self._obs_string(run))
  368 + self._log('\n')
  369 + self._log.parformat('Number of simulated events')
302 self._log(nevents) 370 self._log(nevents)
303 - self._log("\n") 371 + self._log('\n')
304 372
305 # Fit model 373 # Fit model
306 - if self["profile"].boolean(): 374 + if self['profile'].boolean():
307 models = self._obs.models() 375 models = self._obs.models()
308 for i in range(models.size()): 376 for i in range(models.size()):
309 model_name = models[i].name() 377 model_name = models[i].name()
@@ -324,17 +392,17 @@ class cspull(ctools.cscript): @@ -324,17 +392,17 @@ class cspull(ctools.cscript):
324 392
325 # Write result header 393 # Write result header
326 if self._logNormal(): 394 if self._logNormal():
327 - self._log.header3("Pulls") 395 + self._log.header3('Pulls')
328 396
329 # Gather results 397 # Gather results
330 colnames = [] 398 colnames = []
331 values = {} 399 values = {}
332 - colnames.append("LogL")  
333 - colnames.append("Sim_Events")  
334 - colnames.append("Npred_Events")  
335 - values["LogL"] = logL  
336 - values["Sim_Events"] = nevents  
337 - values["Npred_Events"] = npred 400 + colnames.append('LogL')
  401 + colnames.append('Sim_Events')
  402 + colnames.append('Npred_Events')
  403 + values['LogL'] = logL
  404 + values['Sim_Events'] = nevents
  405 + values['Npred_Events'] = npred
338 for i in range(models.size()): 406 for i in range(models.size()):
339 model = models[i] 407 model = models[i]
340 model_name = model.name() 408 model_name = model.name()
@@ -343,12 +411,12 @@ class cspull(ctools.cscript): @@ -343,12 +411,12 @@ class cspull(ctools.cscript):
343 if par.is_free(): 411 if par.is_free():
344 412
345 # Set parameter name 413 # Set parameter name
346 - name = model_name+"_"+par.name() 414 + name = model_name+'_'+par.name()
347 415
348 # Append parameter, Pull_parameter and Unc_parameter 416 # Append parameter, Pull_parameter and Unc_parameter
349 colnames.append(name) 417 colnames.append(name)
350 - colnames.append("Pull_"+name)  
351 - colnames.append("Unc_"+name) 418 + colnames.append('Pull_'+name)
  419 + colnames.append('Unc_'+name)
352 420
353 # Compute pull 421 # Compute pull
354 fitted_value = par.value() 422 fitted_value = par.value()
@@ -361,18 +429,18 @@ class cspull(ctools.cscript): @@ -361,18 +429,18 @@ class cspull(ctools.cscript):
361 429
362 # Store results 430 # Store results
363 values[name] = fitted_value 431 values[name] = fitted_value
364 - values["Pull_"+name] = pull  
365 - values["Unc_"+name] = error 432 + values['Pull_'+name] = pull
  433 + values['Unc_'+name] = error
366 434
367 # Write result 435 # Write result
368 if self._logNormal(): 436 if self._logNormal():
369 self._log.parformat(name) 437 self._log.parformat(name)
370 self._log(pull) 438 self._log(pull)
371 - self._log(" (") 439 + self._log(' (')
372 self._log(fitted_value) 440 self._log(fitted_value)
373 - self._log(" +/- ") 441 + self._log(' +/- ')
374 self._log(error) 442 self._log(error)
375 - self._log(")\n") 443 + self._log(')\n')
376 444
377 # Bundle together results 445 # Bundle together results
378 result = {'colnames': colnames, 'values': values} 446 result = {'colnames': colnames, 'values': values}
@@ -384,7 +452,7 @@ class cspull(ctools.cscript): @@ -384,7 +452,7 @@ class cspull(ctools.cscript):
384 # Public methods 452 # Public methods
385 def run(self): 453 def run(self):
386 """ 454 """
387 - Run the script. 455 + Run the script
388 """ 456 """
389 # Switch screen logging on in debug mode 457 # Switch screen logging on in debug mode
390 if self._logDebug(): 458 if self._logDebug():
@@ -395,25 +463,29 @@ class cspull(ctools.cscript): @@ -395,25 +463,29 @@ class cspull(ctools.cscript):
395 463
396 # Write observation into logger 464 # Write observation into logger
397 if self._logTerse(): 465 if self._logTerse():
398 - self._log("\n")  
399 - self._log.header1("Observation(s)") 466 + self._log('\n')
  467 + self._log.header1(gammalib.number('Observation',len(self._obs)))
400 self._log(str(self._obs)) 468 self._log(str(self._obs))
401 - self._log("\n") 469 + self._log('\n')
  470 +
  471 + # Signal if stacked analysis is requested
  472 + #stacked = self._obs.size() > 1 and self._enumbins > 0
  473 + stacked = self._enumbins > 0
402 474
403 # If several observations and binned: prepare stacked irfs 475 # If several observations and binned: prepare stacked irfs
404 - if self._obs.size() > 1 and self._enumbins > 0: 476 + if stacked:
405 self._set_stacked_irf() 477 self._set_stacked_irf()
406 478
407 # Write header 479 # Write header
408 if self._logTerse(): 480 if self._logTerse():
409 - self._log("\n")  
410 - self._log.header1("Generate pull distribution") 481 + self._log('\n')
  482 + self._log.header1('Generate pull distribution')
411 483
412 # Loop over trials 484 # Loop over trials
413 for seed in range(self._ntrials): 485 for seed in range(self._ntrials):
414 486
415 # Make a trial and add initial seed 487 # Make a trial and add initial seed
416 - result = self._trial(seed + self._seed) 488 + result = self._trial(seed + self._seed, stacked)
417 489
418 # Write out result immediately 490 # Write out result immediately
419 if seed == 0: 491 if seed == 0:
@@ -434,7 +506,7 @@ class cspull(ctools.cscript): @@ -434,7 +506,7 @@ class cspull(ctools.cscript):
434 506
435 def execute(self): 507 def execute(self):
436 """ 508 """
437 - Execute the script. 509 + Execute the script
438 """ 510 """
439 # Open logfile 511 # Open logfile
440 self.logFileOpen() 512 self.logFileOpen()
@@ -447,10 +519,15 @@ class cspull(ctools.cscript): @@ -447,10 +519,15 @@ class cspull(ctools.cscript):
447 519
448 def models(self, models): 520 def models(self, models):
449 """ 521 """
450 - Set model. 522 + Set model
  523 +
  524 + Parameters
  525 + ----------
  526 + models : `~gammalib.GModels`
  527 + Set model container
451 """ 528 """
452 - # Copy models  
453 - self.obs.models(models.copy()) 529 + # Set model container
  530 + self._obs.models(models)
454 531
455 # Return 532 # Return
456 return 533 return
cscripts/obsutils.py
@@ -24,46 +24,58 @@ import ctools @@ -24,46 +24,58 @@ import ctools
24 # ===================== # 24 # ===================== #
25 # Simulate observations # 25 # Simulate observations #
26 # ===================== # 26 # ===================== #
27 -def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0,  
28 - binsz=0.05, npix=200, proj="TAN", coord="GAL"): 27 +def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0,
  28 + emin=None, emax=None, nbins=0,
  29 + binsz=0.05, npix=200, proj='TAN', coord='GAL'):
29 """ 30 """
30 - Simulate events for all observations in the container.  
31 -  
32 - Args:  
33 - obs: Observation container without events  
34 -  
35 - Kwargs:  
36 - log: Create log file(s)  
37 - debug: Create console dump?  
38 - chatter: Chatter level  
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  
44 - proj: Projection for binned simulation  
45 - coord: Coordinate system for binned simulation  
46 -  
47 - Returns:  
48 - Observation container, filled with simulated events. 31 + Simulate events for all observations in the container
  32 +
  33 + Parameters
  34 + ----------
  35 + obs : `~gammalib.GObservations`
  36 + Observation container without events
  37 + log : bool, optional
  38 + Create log file(s)
  39 + debug : bool, optional
  40 + Create console dump?
  41 + chatter : int, optional
  42 + Chatter level
  43 + edisp : bool, optional
  44 + Apply energy dispersion?
  45 + seed : int, integer
  46 + Seed value for simulations
  47 + emin : float, optional
  48 + Minimum energy of counts cube for binned (TeV)
  49 + emax : float, optional
  50 + Maximum energy of counts cube for binned (TeV)
  51 + nbins : int, optional
  52 + Number of energy bins (0=unbinned)
  53 + binsz : float, optional
  54 + Pixel size for binned simulation (deg/pixel)
  55 + npix : int, optional
  56 + Number of pixels in X and Y for binned simulation
  57 + proj : str, optional
  58 + Projection for binned simulation
  59 + coord : str, optional
  60 + Coordinate system for binned simulation
  61 +
  62 + Returns
  63 + -------
  64 + obs : `~gammalib.GObservations`
  65 + Observation container filled with simulated events
49 """ 66 """
50 67
51 # Allocate ctobssim application and set parameters 68 # Allocate ctobssim application and set parameters
52 sim = ctools.ctobssim(obs) 69 sim = ctools.ctobssim(obs)
53 - sim["seed"] = seed  
54 - sim["edisp"] = edisp 70 + sim['seed'] = seed
  71 + sim['edisp'] = edisp
  72 + sim['chatter'] = chatter
  73 + sim['debug'] = debug
55 74
56 # Optionally open the log file 75 # Optionally open the log file
57 if log: 76 if log:
58 sim.logFileOpen() 77 sim.logFileOpen()
59 78
60 - # Optionally switch-on debugging model  
61 - if debug:  
62 - sim["debug"] = True  
63 -  
64 - # Set chatter level  
65 - sim["chatter"] = chatter  
66 -  
67 # Run ctobssim application. This will loop over all observations in the 79 # Run ctobssim application. This will loop over all observations in the
68 # container and simulation the events for each observation. Note that 80 # container and simulation the events for each observation. Note that
69 # events are not added together, they still apply to each observation 81 # events are not added together, they still apply to each observation
@@ -73,45 +85,42 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0, @@ -73,45 +85,42 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0,
73 # Binned option? 85 # Binned option?
74 if nbins > 0: 86 if nbins > 0:
75 87
76 - # Determine common energy boundaries for observations  
77 - emin = None  
78 - emax = None  
79 - for run in sim.obs():  
80 - run_emin = run.events().ebounds().emin().TeV()  
81 - run_emax = run.events().ebounds().emax().TeV()  
82 - if emin == None:  
83 - emin = run_emin  
84 - elif run_emin > emin:  
85 - emin = run_emin  
86 - if emax == None:  
87 - emax = run_emax  
88 - elif run_emax > emax:  
89 - emax = run_emax 88 + # If energy boundaries are not given then determine common energy
  89 + # boundaries for all observations
  90 + if emin == None or emax == None:
  91 + emin = None
  92 + emax = None
  93 + for run in sim.obs():
  94 + run_emin = run.events().ebounds().emin().TeV()
  95 + run_emax = run.events().ebounds().emax().TeV()
  96 + if emin == None:
  97 + emin = run_emin
  98 + elif run_emin > emin:
  99 + emin = run_emin
  100 + if emax == None:
  101 + emax = run_emax
  102 + elif run_emax > emax:
  103 + emax = run_emax
90 104
91 # Allocate ctbin application and set parameters 105 # Allocate ctbin application and set parameters
92 bin = ctools.ctbin(sim.obs()) 106 bin = ctools.ctbin(sim.obs())
93 - bin["ebinalg"] = "LOG"  
94 - bin["emin"] = emin  
95 - bin["emax"] = emax  
96 - bin["enumbins"] = nbins  
97 - bin["usepnt"] = True # Use pointing for map centre  
98 - bin["nxpix"] = npix  
99 - bin["nypix"] = npix  
100 - bin["binsz"] = binsz  
101 - bin["coordsys"] = coord  
102 - bin["proj"] = proj 107 + bin['ebinalg'] = 'LOG'
  108 + bin['emin'] = emin
  109 + bin['emax'] = emax
  110 + bin['enumbins'] = nbins
  111 + bin['usepnt'] = True # Use pointing for map centre
  112 + bin['nxpix'] = npix
  113 + bin['nypix'] = npix
  114 + bin['binsz'] = binsz
  115 + bin['coordsys'] = coord
  116 + bin['proj'] = proj
  117 + bin['chatter'] = chatter
  118 + bin['debug'] = debug
103 119
104 # Optionally open the log file 120 # Optionally open the log file
105 if log: 121 if log:
106 bin.logFileOpen() 122 bin.logFileOpen()
107 123
108 - # Optionally switch-on debugging model  
109 - if debug:  
110 - bin["debug"] = True  
111 -  
112 - # Set chatter level  
113 - bin["chatter"] = chatter  
114 -  
115 # Run ctbin application. This will loop over all observations in 124 # Run ctbin application. This will loop over all observations in
116 # the container and bin the events in counts maps 125 # the container and bin the events in counts maps
117 bin.run() 126 bin.run()
src/ctexpcube/ctexpcube.cpp
@@ -220,12 +220,7 @@ void ctexpcube::run(void) @@ -220,12 +220,7 @@ void ctexpcube::run(void)
220 // Write observation(s) into logger 220 // Write observation(s) into logger
221 if (logTerse()) { 221 if (logTerse()) {
222 log << std::endl; 222 log << std::endl;
223 - if (m_obs.size() > 1) {  
224 - log.header1("Observations");  
225 - }  
226 - else {  
227 - log.header1("Observation");  
228 - } 223 + log.header1(gammalib::number("Observation",m_obs.size()));
229 log << m_obs << std::endl; 224 log << m_obs << std::endl;
230 } 225 }
231 226
src/ctlike/ctlike.cpp
@@ -230,13 +230,8 @@ void ctlike::run(void) @@ -230,13 +230,8 @@ void ctlike::run(void)
230 // Write observation(s) into logger 230 // Write observation(s) into logger
231 if (logTerse()) { 231 if (logTerse()) {
232 log << std::endl; 232 log << std::endl;
233 - if (m_obs.size() > 1) {  
234 - log.header1("Observations");  
235 - }  
236 - else {  
237 - log.header1("Observation");  
238 - }  
239 - log << m_obs << std::endl; 233 + log.header1(gammalib::number("Observation",m_obs.size()));
  234 + log << m_obs.print(m_chatter) << std::endl;
240 } 235 }
241 236
242 // Optimize model parameters using LM optimizer 237 // Optimize model parameters using LM optimizer
@@ -311,7 +306,7 @@ void ctlike::run(void) @@ -311,7 +306,7 @@ void ctlike::run(void)
311 if (logTerse()) { 306 if (logTerse()) {
312 log << std::endl; 307 log << std::endl;
313 log.header1("Maximum likelihood optimisation results"); 308 log.header1("Maximum likelihood optimisation results");
314 - log << *m_opt << std::endl; 309 + log << m_opt->print(m_chatter) << std::endl;
315 log << gammalib::parformat("Maximum log likelihood"); 310 log << gammalib::parformat("Maximum log likelihood");
316 log << gammalib::str(m_logL,3) << std::endl; 311 log << gammalib::str(m_logL,3) << std::endl;
317 log << gammalib::parformat("Observed events (Nobs)"); 312 log << gammalib::parformat("Observed events (Nobs)");
@@ -321,7 +316,7 @@ void ctlike::run(void) @@ -321,7 +316,7 @@ void ctlike::run(void)
321 log << " (Nobs - Npred = "; 316 log << " (Nobs - Npred = ";
322 log << gammalib::str(num_events-npred); 317 log << gammalib::str(num_events-npred);
323 log << ")" << std::endl; 318 log << ")" << std::endl;
324 - log << m_obs.models() << std::endl; 319 + log << m_obs.models().print(m_chatter) << std::endl;
325 } 320 }
326 321
327 // Restore energy dispersion flag for all CTA observations 322 // Restore energy dispersion flag for all CTA observations
@@ -430,6 +425,7 @@ void ctlike::get_parameters(void) @@ -430,6 +425,7 @@ void ctlike::get_parameters(void)
430 m_refit = (*this)["refit"].boolean(); 425 m_refit = (*this)["refit"].boolean();
431 m_apply_edisp = (*this)["edisp"].boolean(); 426 m_apply_edisp = (*this)["edisp"].boolean();
432 m_fix_spat_for_ts = (*this)["fix_spat_for_ts"].boolean(); 427 m_fix_spat_for_ts = (*this)["fix_spat_for_ts"].boolean();
  428 + m_chatter = static_cast<GChatter>((*this)["chatter"].integer());
433 429
434 // Optionally read ahead parameters so that they get correctly 430 // Optionally read ahead parameters so that they get correctly
435 // dumped into the log file 431 // dumped into the log file
@@ -592,6 +588,7 @@ void ctlike::init_members(void) @@ -592,6 +588,7 @@ void ctlike::init_members(void)
592 m_opt = NULL; 588 m_opt = NULL;
593 m_apply_edisp = false; 589 m_apply_edisp = false;
594 m_fix_spat_for_ts = false; 590 m_fix_spat_for_ts = false;
  591 + m_chatter = static_cast<GChatter>(2);
595 592
596 // Set logger properties 593 // Set logger properties
597 log.date(true); 594 log.date(true);
@@ -628,6 +625,7 @@ void ctlike::copy_members(const ctlike&amp; app) @@ -628,6 +625,7 @@ void ctlike::copy_members(const ctlike&amp; app)
628 m_opt = app.m_opt->clone(); 625 m_opt = app.m_opt->clone();
629 m_apply_edisp = app.m_apply_edisp; 626 m_apply_edisp = app.m_apply_edisp;
630 m_fix_spat_for_ts = app.m_fix_spat_for_ts; 627 m_fix_spat_for_ts = app.m_fix_spat_for_ts;
  628 + m_chatter = app.m_chatter;
631 629
632 // Return 630 // Return
633 return; 631 return;
src/ctlike/ctlike.hpp
@@ -77,6 +77,7 @@ protected: @@ -77,6 +77,7 @@ protected:
77 GFilename m_outmodel; //!< Source model output XML file name 77 GFilename m_outmodel; //!< Source model output XML file name
78 bool m_apply_edisp; //!< Apply energy dispersion? 78 bool m_apply_edisp; //!< Apply energy dispersion?
79 bool m_fix_spat_for_ts; //!< Fix spatial parameters for TS computation? 79 bool m_fix_spat_for_ts; //!< Fix spatial parameters for TS computation?
  80 + GChatter m_chatter; //!< Chattiness
80 81
81 // Members 82 // Members
82 GObservations m_obs; //!< Observations 83 GObservations m_obs; //!< Observations