Commit ac3d2d26bd2b41c6dc79d95e08a9000566caa441

Authored by Jürgen Knödlseder
1 parent bb3fc5da

Change interface. Now use a specific source from the inout model.

doc/source/reference_manual/cstsdist.rst
@@ -16,30 +16,49 @@ Monte-Carlo simulations. @@ -16,30 +16,49 @@ Monte-Carlo simulations.
16 General parameters 16 General parameters
17 ------------------ 17 ------------------
18 18
19 -``(outfile = ts.dat) [file]`` 19 +``(inobs = NONE) [file]``
  20 + Input event list, counts cube or observation definition XML file.
  21 +
  22 +``inmodel [file]``
  23 + Input source model XML file.
  24 +
  25 +``srcname [string]``
  26 + Name of the source in the source model XML file which should be used
  27 + for sensitivity computation.
  28 +
  29 +``outfile [file]``
20 ASCII file containing the TS distribution values. 30 ASCII file containing the TS distribution values.
21 -  
22 -``ntrials [integer]``  
23 - Number of Monte Carlo samples.  
24 - 31 +
  32 +``expcube [file]``
  33 + Exposure cube file (only needed for stacked analysis).
  34 +
  35 +``psfcube [file]``
  36 + PSF cube file (only needed for stacked analysis).
  37 +
  38 +``bkgcube [file]``
  39 + Background cube file (only needed for stacked analysis).
  40 +
25 ``caldb [string]`` 41 ``caldb [string]``
26 Calibration database. 42 Calibration database.
27 43
28 ``irf [string]`` 44 ``irf [string]``
29 Instrumental response function. 45 Instrumental response function.
30 46
31 -``type <point|gauss|shell|disk> [string]``  
32 - Source model type.  
33 -  
34 -``(index = -2.48) [real]``  
35 - Spectral index for source model.  
36 -  
37 -``offset [real]``  
38 - Source offset angle (in degrees).  
39 -  
40 -``bkg [string]``  
41 - Background model file function (none=power law for subarray E). 47 +``(deadc = 0.95) [real]``
  48 + Average deadtime correction factor.
  49 +
  50 +``(edisp = no) [boolean]``
  51 + Apply energy dispersion to response computation.
  52 +
  53 +``ntrials [integer]``
  54 + Number of Monte Carlo samples.
  55 +
  56 +``ra [real]``
  57 + Right Ascension of CTA pointing (J2000, in degrees).
42 58
  59 +``dec [real]``
  60 + Declination of CTA pointing (J2000, in degrees).
  61 +
43 ``emin [real]`` 62 ``emin [real]``
44 Lower energy limit (in TeV). 63 Lower energy limit (in TeV).
45 64
@@ -49,18 +68,27 @@ General parameters @@ -49,18 +68,27 @@ General parameters
49 ``enumbins [integer]`` 68 ``enumbins [integer]``
50 Number of energy bins (0=unbinned). 69 Number of energy bins (0=unbinned).
51 70
52 -``duration [real]``  
53 - Effective exposure time (in seconds). 71 +``(tmin = 0.0) [real]``
  72 + Start time (in seconds).
54 73
55 -``(rad = 5.0) [real]``  
56 - Radius of ROI (in degrees). 74 +``tmax [real]``
  75 + Stop time (in seconds).
57 76
58 -``(npix = 200) [integer]`` 77 +``npix [integer]``
59 Number of pixels for binned analysis. 78 Number of pixels for binned analysis.
60 79
61 -``(binsz = 0.05) [real]`` 80 +``binsz [real]``
62 Pixel size for binned analysis. 81 Pixel size for binned analysis.
63 82
  83 +``(rad = 5.0) [real]``
  84 + Radius of ROI (in degrees).
  85 +
  86 +``(pattern = single) [string]``
  87 + Pattern for pointing simulation (single/four).
  88 +
  89 +``(offset = 1.5) [real]``
  90 + Observation pattern offset (in degrees).
  91 +
64 92
65 Standard parameters 93 Standard parameters
66 ------------------- 94 -------------------
@@ -86,6 +114,9 @@ Standard parameters @@ -86,6 +114,9 @@ Standard parameters
86 ``(mode = ql) [string]`` 114 ``(mode = ql) [string]``
87 Mode of automatic parameters (default is "ql", i.e. "query and learn"). 115 Mode of automatic parameters (default is "ql", i.e. "query and learn").
88 116
  117 +``(logfile = cstsdist.log) [string]``
  118 + Log filename.
  119 +
89 120
90 Related tools 121 Related tools
91 ------------- 122 -------------
scripts/cstsdist.py
@@ -95,27 +95,29 @@ class cstsdist(ctools.cscript): @@ -95,27 +95,29 @@ class cstsdist(ctools.cscript):
95 # Create default parfile 95 # Create default parfile
96 pars = gammalib.GApplicationPars() 96 pars = gammalib.GApplicationPars()
97 pars.append(gammalib.GApplicationPar("inobs","f","h","NONE","","","Event list, counts cube, or observation definition file")) 97 pars.append(gammalib.GApplicationPar("inobs","f","h","NONE","","","Event list, counts cube, or observation definition file"))
98 - pars.append(gammalib.GApplicationPar("outfile","f","h","ts.dat","","","Output file name")) 98 + pars.append(gammalib.GApplicationPar("inmodel","f","a","$CTOOLS/share/models/crab.xml","","","Source model"))
  99 + pars.append(gammalib.GApplicationPar("srcname","s","a","Crab","","","Source name"))
  100 + pars.append(gammalib.GApplicationPar("outfile","f","a","ts.dat","","","Output file name"))
99 pars.append(gammalib.GApplicationPar("expcube","s","a","NONE","","","Exposure cube file (only needed for stacked analysis)")) 101 pars.append(gammalib.GApplicationPar("expcube","s","a","NONE","","","Exposure cube file (only needed for stacked analysis)"))
100 pars.append(gammalib.GApplicationPar("psfcube","s","a","NONE","","","PSF cube file (only needed for stacked analysis)")) 102 pars.append(gammalib.GApplicationPar("psfcube","s","a","NONE","","","PSF cube file (only needed for stacked analysis)"))
  103 + pars.append(gammalib.GApplicationPar("bkgcube","s","a","NONE","","","Background cube file (only needed for stacked analysis)"))
101 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database")) 104 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database"))
102 pars.append(gammalib.GApplicationPar("irf","s","a","South_50h","","","Instrument response function")) 105 pars.append(gammalib.GApplicationPar("irf","s","a","South_50h","","","Instrument response function"))
103 - pars.append(gammalib.GApplicationPar("ra","r","h","83.63","0","360","RA of pointing (deg)"))  
104 - pars.append(gammalib.GApplicationPar("dec","r","h","22.01","-90","90","Dec of pointing (deg)")) 106 + pars.append(gammalib.GApplicationPar("deadc","r","h","0.95","","","Deadtime correction factor"))
  107 + pars.append(gammalib.GApplicationPar("edisp","b","h","no","","","Apply energy dispersion?"))
  108 + pars.append(gammalib.GApplicationPar("ntrials","i","a","10","","","Number of trials"))
  109 + pars.append(gammalib.GApplicationPar("ra","r","a","83.63","0","360","RA of pointing (deg)"))
  110 + pars.append(gammalib.GApplicationPar("dec","r","a","22.01","-90","90","Dec of pointing (deg)"))
105 pars.append(gammalib.GApplicationPar("emin","r","a","0.1","","","Lower energy limit (TeV)")) 111 pars.append(gammalib.GApplicationPar("emin","r","a","0.1","","","Lower energy limit (TeV)"))
106 pars.append(gammalib.GApplicationPar("emax","r","a","100.0","","","Upper energy limit (TeV)")) 112 pars.append(gammalib.GApplicationPar("emax","r","a","100.0","","","Upper energy limit (TeV)"))
  113 + pars.append(gammalib.GApplicationPar("enumbins","i","a","0","","","Number of energy bins (0=unbinned)"))
107 pars.append(gammalib.GApplicationPar("tmin","r","h","0.0","","","Start time (MET in s)")) 114 pars.append(gammalib.GApplicationPar("tmin","r","h","0.0","","","Start time (MET in s)"))
108 pars.append(gammalib.GApplicationPar("tmax","r","a","1800.0","","","Observation duration (in s)")) 115 pars.append(gammalib.GApplicationPar("tmax","r","a","1800.0","","","Observation duration (in s)"))
109 - pars.append(gammalib.GApplicationPar("enumbins","i","a","0","","","Number of energy bins (0=unbinned)"))  
110 - pars.append(gammalib.GApplicationPar("npix","i","h","200","","","Number of pixels for binned"))  
111 - pars.append(gammalib.GApplicationPar("binsz","r","h","0.05","","","Pixel size for binned (deg/pixel)"))  
112 - pars.append(gammalib.GApplicationPar("deadc","r","h","0.95","","","Deadtime correction factor")) 116 + pars.append(gammalib.GApplicationPar("npix","i","a","200","","","Number of pixels for binned"))
  117 + pars.append(gammalib.GApplicationPar("binsz","r","a","0.05","","","Pixel size for binned (deg/pixel)"))
113 pars.append(gammalib.GApplicationPar("rad","r","h","5.0","","","Radius of ROI (deg)")) 118 pars.append(gammalib.GApplicationPar("rad","r","h","5.0","","","Radius of ROI (deg)"))
114 - pars.append(gammalib.GApplicationPar("ntrials","i","a","10","","","Number of trials"))  
115 - pars.append(gammalib.GApplicationPar("type","s","a","point","","","Source model type (point/gauss/shell/disk)"))  
116 - pars.append(gammalib.GApplicationPar("index","r","h","-2.48","","","Spectral index"))  
117 - pars.append(gammalib.GApplicationPar("offset","r","a","0.0","","","Source offset angle (deg)"))  
118 - pars.append(gammalib.GApplicationPar("bkg","s","a","$CTOOLS/share/models/bkg_dummy.txt","","","Background model file function")) 119 + pars.append(gammalib.GApplicationPar("pattern","s","h","single","","","Observation pattern (single/four)"))
  120 + pars.append(gammalib.GApplicationPar("offset","r","h","1.5","","","Observation pattern offset (deg)"))
119 pars.append_standard() 121 pars.append_standard()
120 pars.append(gammalib.GApplicationPar("logfile","f","h","cstsdist.log","","","Log filename")) 122 pars.append(gammalib.GApplicationPar("logfile","f","h","cstsdist.log","","","Log filename"))
121 pars.save(parfile) 123 pars.save(parfile)
@@ -131,6 +133,15 @@ class cstsdist(ctools.cscript): @@ -131,6 +133,15 @@ class cstsdist(ctools.cscript):
131 # Set observation if not done before 133 # Set observation if not done before
132 if self.obs == None or self.obs.size() == 0: 134 if self.obs == None or self.obs.size() == 0:
133 self.obs = self.get_observations() 135 self.obs = self.get_observations()
  136 +
  137 + # Check for requested pattern and use above
  138 + # observation parameters to set wobble pattern
  139 + self.m_pattern = self["pattern"].string()
  140 + if self.m_pattern == "four":
  141 + self.obs = self.set_obs()
  142 +
  143 + # Get source name
  144 + self.m_srcname = self["srcname"].string()
134 145
135 # Get number of energy bins 146 # Get number of energy bins
136 self.m_enumbins = self["enumbins"].integer() 147 self.m_enumbins = self["enumbins"].integer()
@@ -143,36 +154,21 @@ class cstsdist(ctools.cscript): @@ -143,36 +154,21 @@ class cstsdist(ctools.cscript):
143 # Set dummy values (required by obsutils) 154 # Set dummy values (required by obsutils)
144 self.m_npix = 0 155 self.m_npix = 0
145 self.m_binsz = 0.0 156 self.m_binsz = 0.0
  157 +
  158 + # Set models if we have none
  159 + if self.obs.models().size() == 0:
  160 + self.obs.models(self["inmodel"].filename())
146 161
147 # Get other parameters 162 # Get other parameters
148 - self.m_outfile = self["outfile"].filename()  
149 - self.m_ntrials = self["ntrials"].integer()  
150 - self.m_type = self["type"].string()  
151 - self.m_index = self["index"].real()  
152 - self.m_offset = self["offset"].real()  
153 - self.m_bkg = self["bkg"].string() 163 + self.m_outfile = self["outfile"].filename()
  164 + self.m_ntrials = self["ntrials"].integer()
  165 + self.m_edisp = self["edisp"].boolean()
  166 + self.m_offset = self["offset"].real()
154 167
155 # Set some fixed parameters 168 # Set some fixed parameters
156 - self.m_log = False # Logging in client tools  
157 - self.m_debug = False # Debugging in client tools  
158 -  
159 - pnt = gammalib.GSkyDir()  
160 - pnt.radec_deg(self["ra"].real(),self["dec"].real())  
161 -  
162 - # Initialise models. Note that we centre the point source at the  
163 - # center of our observation, so we're onaxis.  
164 - self.bkg_model = gammalib.GModels()  
165 - self.full_model = gammalib.GModels()  
166 - self.bkg_model.append(self.set_bkg_model())  
167 - self.full_model.append(self.set_bkg_model())  
168 - self.full_model.append(self.set_src_model(pnt.l_deg(), pnt.b_deg()+self.m_offset, \  
169 - flux=0.010, \  
170 - type=self.m_type, \  
171 - index=self.m_index))  
172 -  
173 - # Attach background model to observation container  
174 - self.obs.models(self.bkg_model)  
175 - 169 + self.m_log = False # Logging in client tools
  170 + self.m_debug = self["debug"].boolean() # Debugging in client tools
  171 +
176 # Return 172 # Return
177 return 173 return
178 174
@@ -211,6 +207,20 @@ class cstsdist(ctools.cscript): @@ -211,6 +207,20 @@ class cstsdist(ctools.cscript):
211 if self.logTerse(): 207 if self.logTerse():
212 self.log_parameters() 208 self.log_parameters()
213 self.log("\n") 209 self.log("\n")
  210 +
  211 + # Initialise models
  212 + full_model, bkg_model = self.set_models()
  213 +
  214 + # Write models into logger
  215 + if self.logTerse():
  216 + self.log("\n")
  217 + self.log.header1("Models")
  218 + self.log.header2("Background model")
  219 + self.log(str(bkg_model))
  220 + self.log("\n\n")
  221 + self.log.header2("Full model")
  222 + self.log(str(full_model))
  223 + self.log("\n")
214 224
215 # Write observation into logger 225 # Write observation into logger
216 if self.logTerse(): 226 if self.logTerse():
@@ -235,7 +245,7 @@ class cstsdist(ctools.cscript): @@ -235,7 +245,7 @@ class cstsdist(ctools.cscript):
235 for seed in range(self.m_ntrials): 245 for seed in range(self.m_ntrials):
236 246
237 # Make a trial 247 # Make a trial
238 - result = self.trial(seed) 248 + result = self.trial(seed, full_model, bkg_model)
239 249
240 # Write out result immediately 250 # Write out result immediately
241 if seed == 0: 251 if seed == 0:
@@ -251,97 +261,89 @@ class cstsdist(ctools.cscript): @@ -251,97 +261,89 @@ class cstsdist(ctools.cscript):
251 # Return 261 # Return
252 return 262 return
253 263
254 - def set_bkg_model(self, fitsigma=False): 264 + def set_models(self, fitpos=False, fitspec=False):
255 """ 265 """
256 - Setup CTA background model. 266 + Set full and background model.
257 """ 267 """
258 - # Define radial component  
259 - radial = gammalib.GCTAModelRadialGauss(3.0)  
260 - if fitsigma:  
261 - radial["Sigma"].free()  
262 - else:  
263 - radial["Sigma"].fix()  
264 -  
265 - # Define spectral component  
266 - spectrum = gammalib.GModelSpectralFunc(self.m_bkg, 1.0) 268 + # Retrieve full model from observation container
  269 + full_model = self.obs.models().copy()
  270 +
  271 + # Get source model
  272 + model = full_model[self.m_srcname]
267 273
268 - # Create background model  
269 - model = gammalib.GCTAModelRadialAcceptance(radial, spectrum)  
270 - model.name("Background")  
271 - model.instruments("CTA")  
272 -  
273 - # Return background model  
274 - return model  
275 -  
276 - def set_src_model(self, l, b, flux=1.0, index=-2.48, \  
277 - type="point", sigma=1.0, radius=1.0, width=0.1, \  
278 - fitpos=False, fitidx=False):  
279 - """  
280 - Returns a single source with Crab-like spectrum. The source flux  
281 - can be scaled in Crab units. The Crab spectrum is based on MAGIC  
282 - observations (Albert et al. 2008, ApJ, 674, 1037). 274 + # Check that model has a Prefactor
  275 + if not model.has_par("Prefactor"):
  276 + msg = "Model \""+self.m_srcname+"\" has no parameter \"Prefactor\"."+ \
  277 + " Only spectral models with a \"Prefactor\" parameter are supported."
  278 + raise gammalib.GException.invalid_value("cssens", msg)
283 279
284 - Parameters:  
285 - l - Galactic longitude of source location [deg]  
286 - b - Galactic latitude of source location [deg]  
287 - Keywords:  
288 - flux - Source flux [Crabs]  
289 - index - Spectral index  
290 - type - Source type ("point", "gauss", "disk", "shell")  
291 - sigma - Gaussian sigma (for type="gauss")  
292 - radius - Disk or shell inner radius [deg] (for type="disk" and type="shell")  
293 - width - Shell width [deg] (for type="shell")  
294 - fitpos - Fit position? (default: True)  
295 - fitidx - Fit index? (default: True)  
296 - """  
297 - # Set source location  
298 - location = gammalib.GSkyDir()  
299 - location.lb_deg(l, b)  
300 -  
301 - # Set source spectrum  
302 - spectrum = gammalib.GModelSpectralPlaw(flux*5.7e-16, index, gammalib.GEnergy(0.3, "TeV"))  
303 - if fitidx:  
304 - spectrum["Index"].free() 280 + # Fit or fix spatial parameters
  281 + if fitpos:
  282 + if model.has_par("RA"):
  283 + model["RA"].free()
  284 + if model.has_par("DEC"):
  285 + model["DEC"].free()
  286 + if model.has_par("Sigma"):
  287 + model["Sigma"].free()
  288 + if model.has_par("Radius"):
  289 + model["Radius"].free()
  290 + if model.has_par("Width"):
  291 + model["Width"].free()
305 else: 292 else:
306 - spectrum["Index"].fix()  
307 -  
308 - # Set source  
309 - if type == "point":  
310 - spatial = gammalib.GModelSpatialPointSource(location)  
311 - if fitpos:  
312 - spatial[0].free()  
313 - spatial[1].free()  
314 - elif type == "gauss":  
315 - spatial = gammalib.GModelSpatialRadialGauss(location, sigma)  
316 - if fitpos:  
317 - spatial[0].free()  
318 - spatial[1].free()  
319 - elif type == "disk":  
320 - spatial = gammalib.GModelSpatialRadialDisk(location, radius)  
321 - if fitpos:  
322 - spatial[0].free()  
323 - spatial[1].free()  
324 - elif type == "shell":  
325 - spatial = gammalib.GModelSpatialRadialShell(location, radius, width)  
326 - if fitpos:  
327 - spatial[0].free()  
328 - spatial[1].free() 293 + if model.has_par("RA"):
  294 + model["RA"].fix()
  295 + if model.has_par("DEC"):
  296 + model["DEC"].fix()
  297 + if model.has_par("Sigma"):
  298 + model["Sigma"].fix()
  299 + if model.has_par("Radius"):
  300 + model["Radius"].fix()
  301 + if model.has_par("Width"):
  302 + model["Width"].fix()
  303 +
  304 + # Fit or fix spectral parameters
  305 + if fitspec:
  306 + if model.has_par("Index"):
  307 + model["Index"].free()
  308 + if model.has_par("Cutoff"):
  309 + model["Cutoff"].free()
329 else: 310 else:
330 - self.log("ERROR: Unknown source type '"+type+"'.\n")  
331 - return None  
332 - source = gammalib.GModelSky(spatial, spectrum) 311 + if model.has_par("Index"):
  312 + model["Index"].fix()
  313 + if model.has_par("Cutoff"):
  314 + model["Cutoff"].fix()
333 315
334 - # Set source name  
335 - source.name("Test") 316 + # Create background model
  317 + bkg_model = full_model.copy()
  318 + bkg_model.remove(self.m_srcname)
  319 +
  320 + # Return models
  321 + return full_model, bkg_model
  322 +
  323 + def set_obs(self):
  324 + """
  325 + Returns an observation container with a set of CTA observations.
336 326
337 - # Turn TS value computation off  
338 - # since we compute it by hand later on  
339 - source.tscalc(False)  
340 -  
341 - # Return source  
342 - return source 327 + Keywords:
  328 + """
  329 +
  330 + # Setup observation definition list
  331 + obsdeflist = obsutils.set_obs_patterns(self.m_pattern, \
  332 + ra=self["ra"].real(), dec=self["dec"].real(), \
  333 + offset=self["offset"].real())
  334 +
  335 + # Create list of observations
  336 + obs = obsutils.set_obs_list(obsdeflist, \
  337 + tstart=self["tmin"].real(), duration=self["tmax"].real()-self["tmin"].real(), \
  338 + deadc=self["deadc"].real(), \
  339 + emin=self["emin"].real(), emax=self["emax"].real(), \
  340 + rad=self["rad"].real(), \
  341 + irf=self["irf"].string(), caldb=self["caldb"].string())
343 342
344 - def trial(self, seed): 343 + # Return observation container
  344 + return obs
  345 +
  346 + def trial(self, seed, full_model, bkg_model):
345 """ 347 """
346 Create the TS for a single trial. 348 Create the TS for a single trial.
347 349
@@ -373,9 +375,9 @@ class cstsdist(ctools.cscript): @@ -373,9 +375,9 @@ class cstsdist(ctools.cscript):
373 self.log("\n") 375 self.log("\n")
374 376
375 # Fit background only 377 # Fit background only
376 - sim.models(self.bkg_model) 378 + sim.models(bkg_model)
377 like_bgm = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) 379 like_bgm = obsutils.fit(sim, log=self.m_log, debug=self.m_debug)
378 - result_bgm = like_bgm.obs().models() 380 + result_bgm = like_bgm.obs().models().copy()
379 LogL_bgm = like_bgm.opt().value() 381 LogL_bgm = like_bgm.opt().value()
380 npred_bgm = like_bgm.obs().npred() 382 npred_bgm = like_bgm.obs().npred()
381 383
@@ -396,9 +398,9 @@ class cstsdist(ctools.cscript): @@ -396,9 +398,9 @@ class cstsdist(ctools.cscript):
396 self.log(str(par)+"\n") 398 self.log(str(par)+"\n")
397 399
398 # Fit background and test source 400 # Fit background and test source
399 - sim.models(self.full_model) 401 + sim.models(full_model)
400 like_all = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) 402 like_all = obsutils.fit(sim, log=self.m_log, debug=self.m_debug)
401 - result_all = like_all.obs().models() 403 + result_all = like_all.obs().models().copy()
402 LogL_all = like_all.opt().value() 404 LogL_all = like_all.opt().value()
403 npred_all = like_all.obs().npred() 405 npred_all = like_all.obs().npred()
404 ts = 2.0*(LogL_bgm-LogL_all) 406 ts = 2.0*(LogL_bgm-LogL_all)
@@ -428,9 +430,9 @@ class cstsdist(ctools.cscript): @@ -428,9 +430,9 @@ class cstsdist(ctools.cscript):
428 self.log("TS=") 430 self.log("TS=")
429 self.log(ts) 431 self.log(ts)
430 self.log(" Prefactor=") 432 self.log(" Prefactor=")
431 - self.log(result_all["Test"]["Prefactor"].value()) 433 + self.log(result_all[self.m_srcname]["Prefactor"].value())
432 self.log("+/-") 434 self.log("+/-")
433 - self.log(result_all["Test"]["Prefactor"].error()) 435 + self.log(result_all[self.m_srcname]["Prefactor"].error())
434 self.log("\n") 436 self.log("\n")
435 437
436 # Initialise results 438 # Initialise results