Commit e3a0f9eb0ebfeaf22e0e63006ae0a32189d6ece7

Authored by Jürgen Knödlseder
1 parent 2eec961d

Implement computation of integral sensitivity

doc/source/reference_manual/cssens.rst
... ... @@ -45,12 +45,6 @@ General parameters
45 45 ``outfile [file]``
46 46 ASCII file containing the sensitivity values.
47 47  
48   -``type <point|gauss|shell|disk> [string]``
49   - Source model type.
50   -
51   -``offset [real]``
52   - Source offset angle (in degrees).
53   -
54 48 ``duration [real]``
55 49 Effective exposure time (in seconds).
56 50  
... ... @@ -75,6 +69,9 @@ General parameters
75 69 ``(binsz = 0.05) [real]``
76 70 Pixel size for binned analysis.
77 71  
  72 +``(type = Differential) <Differential|Integral> [string]``
  73 + Sensitivity type.
  74 +
78 75 ``(sigma = 5.0) [real]``
79 76 Significance threshold.
80 77  
... ...
examples/show_sensitivity.py 100644 → 100755
... ... @@ -46,13 +46,35 @@ def read_sensitivity(filename):
46 46 values.append(float(csv[row+1,column]))
47 47 sensitivity[name] = values
48 48  
  49 + # Check where file contains differential or integral sensitivity
  50 + mode = "Integral"
  51 + if sensitivity.has_key("emax"):
  52 + emax_ref = -1.0
  53 + for value in sensitivity["emax"]:
  54 + if emax_ref < 0.0:
  55 + emax_ref = value
  56 + elif emax_ref != value:
  57 + mode = "Differential"
  58 + break
  59 +
  60 + # Add mode
  61 + sensitivity["mode"] = mode
  62 +
49 63 # Add linear energy values
50   - if sensitivity.has_key("loge"):
51   - name = 'energy'
52   - values = []
53   - for value in sensitivity["loge"]:
54   - values.append(math.pow(10.0, value))
55   - sensitivity[name] = values
  64 + if mode == "Differential":
  65 + if sensitivity.has_key("loge"):
  66 + name = 'energy'
  67 + values = []
  68 + for value in sensitivity["loge"]:
  69 + values.append(math.pow(10.0, value))
  70 + sensitivity[name] = values
  71 + else:
  72 + if sensitivity.has_key("emin"):
  73 + name = 'energy'
  74 + values = []
  75 + for value in sensitivity["emin"]:
  76 + values.append(value)
  77 + sensitivity[name] = values
56 78  
57 79 # Return
58 80 return sensitivity
... ... @@ -61,10 +83,13 @@ def read_sensitivity(filename):
61 83 # ===================== #
62 84 # Show sensitivity data #
63 85 # ===================== #
64   -def show_sensitivity(sensitivity, title="Sensitivity"):
  86 +def show_sensitivity(sensitivity, filename):
65 87 """
66 88 Plot sensitivity.
67 89 """
  90 + # Build title
  91 + title = sensitivity['mode'] + ' sensitivity ('+filename+')'
  92 +
68 93 # Create figure
69 94 plt.figure()
70 95  
... ... @@ -78,7 +103,10 @@ def show_sensitivity(sensitivity, title=&quot;Sensitivity&quot;):
78 103  
79 104 # Set labels
80 105 plt.xlabel("Energy (TeV)")
81   - plt.ylabel(r"Sensitivity (erg cm$^{-2}$ s$^{-1}$)")
  106 + if sensitivity['mode'] == "Differential":
  107 + plt.ylabel(r"E$\times$ F(E) (erg cm$^{-2}$ s$^{-1}$)")
  108 + else:
  109 + plt.ylabel(r"E$\times$ F($>$E) (erg cm$^{-2}$ s$^{-1}$)")
82 110  
83 111 # Show plot
84 112 plt.show()
... ... @@ -105,11 +133,8 @@ if __name__ == &#39;__main__&#39;:
105 133 else:
106 134 filename = sys.argv[1]
107 135  
108   - # Set title
109   - title = 'Differential sensitivity ('+filename+')'
110   -
111 136 # Read sensitivity data
112 137 sensitivity = read_sensitivity(filename)
113 138  
114 139 # Show sensitivity data
115   - show_sensitivity(sensitivity, title=title)
  140 + show_sensitivity(sensitivity, filename)
... ...
scripts/cssens.py
... ... @@ -47,9 +47,9 @@ class cssens(ctools.cscript):
47 47 self.version = "1.0.0"
48 48  
49 49 # Initialise some parameters
50   - self.obs = None
51   - self.m_ra = None
52   - self.m_dec = None
  50 + self.obs = None
  51 + self.m_ra = None
  52 + self.m_dec = None
53 53  
54 54 # Make sure that parfile exists
55 55 file = self.parfile()
... ... @@ -113,6 +113,7 @@ class cssens(ctools.cscript):
113 113 pars.append(gammalib.GApplicationPar("enumbins","i","h","0","","","Number of energy bins (0=unbinned)"))
114 114 pars.append(gammalib.GApplicationPar("npix","i","h","200","","","Number of pixels for binned"))
115 115 pars.append(gammalib.GApplicationPar("binsz","r","h","0.05","","","Pixel size for binned (deg/pixel)"))
  116 + pars.append(gammalib.GApplicationPar("type","s","h","Differential","Differential|Integral","","Sensitivity type"))
116 117 pars.append(gammalib.GApplicationPar("sigma","r","h","5.0","","","Significance threshold"))
117 118 pars.append(gammalib.GApplicationPar("max_iter","i","h","50","","","Maximum number of iterations"))
118 119 pars.append(gammalib.GApplicationPar("num_avg","i","h","3","","","Number of iterations for sliding average"))
... ... @@ -147,17 +148,18 @@ class cssens(ctools.cscript):
147 148 # Read parameters for binned if requested
148 149 self.m_enumbins = self["enumbins"].integer()
149 150 if not self.m_enumbins == 0:
150   - self.m_npix = self["npix"].integer()
151   - self.m_binsz = self["binsz"].real()
  151 + self.m_npix = self["npix"].integer()
  152 + self.m_binsz = self["binsz"].real()
152 153 else:
153 154 # Set dummy values (required by obsutils)
154   - self.m_npix = 0
  155 + self.m_npix = 0
155 156 self.m_binsz = 0.0
156 157  
157 158 # Read remaining parameters
158 159 self.m_ts_thres = self["sigma"].real()*self["sigma"].real()
159 160 self.m_max_iter = self["max_iter"].integer()
160 161 self.m_num_avg = self["num_avg"].integer()
  162 + self.m_type = self["type"].string()
161 163  
162 164 # Set some fixed parameters
163 165 self.m_log = False # Logging in client tools
... ... @@ -219,20 +221,28 @@ class cssens(ctools.cscript):
219 221 if self.logTerse():
220 222 self.log("\n")
221 223 self.log.header1("Sensitivity determination")
  224 + self.log.parformat("Type")
  225 + self.log(self.m_type)
  226 + self.log("\n")
222 227  
223 228 # Loop over energy bins
224 229 for ieng in range(self.m_ebounds.size()):
225 230  
226 231 # Set energies
227   - emean = self.m_ebounds.elogmean(ieng).TeV()
228   - emin = self.m_ebounds.emin(ieng).TeV()
229   - emax = self.m_ebounds.emax(ieng).TeV()
230   -
231   - # Set energy boundaries
232   - self.set_obs_ebounds(emin, emax)
  232 + if self.m_type == "Differential":
  233 + emin = self.m_ebounds.emin(ieng)
  234 + emax = self.m_ebounds.emax(ieng)
  235 + elif self.m_type == "Integral":
  236 + emin = self.m_ebounds.emin(ieng)
  237 + emax = self.m_ebounds.emax()
  238 + else:
  239 + msg = "Invalid sensitivity type \""+self.m_type+"\" encountered."+ \
  240 + " Either use \"Differential\" or \"Integral\"."
  241 + raise gammalib.GException.invalid_value("cssens", msg)
233 242  
234 243 # Determine sensitivity
235   - result = self.get_sensitivity(self.obs, bkg_model, full_model)
  244 + result = self.get_sensitivity(self.obs, emin, emax, \
  245 + bkg_model, full_model)
236 246  
237 247 # Write results
238 248 if ieng == 0:
... ... @@ -305,13 +315,16 @@ class cssens(ctools.cscript):
305 315 def set_obs_ebounds(self, emin, emax):
306 316 """
307 317 Set energy boundaries for observation in container.
  318 +
  319 + Parameters:
  320 + emin - Minimum energy
  321 + emax - Maximum energy
308 322 """
309 323 # Loop over all observations in container
310 324 for obs in self.obs:
311 325  
312 326 # Set energy boundaries
313   - ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, "TeV"), \
314   - gammalib.GEnergy(emax, "TeV"))
  327 + ebounds = gammalib.GEbounds(emin, emax)
315 328 obs.events().ebounds(ebounds)
316 329  
317 330 # Return
... ... @@ -382,27 +395,35 @@ class cssens(ctools.cscript):
382 395 # Return models
383 396 return full_model, bkg_model
384 397  
385   - def get_sensitivity(self, obs, bkg_model, full_model):
  398 + def get_sensitivity(self, obs, emin, emax, bkg_model, full_model):
386 399 """
387   - Determine sensitivity for a given observations.
  400 + Determine sensitivity for given observations.
388 401  
389 402 Parameters:
390 403 obs - Observation container
  404 + emin - Minimum energy for fitting and flux computation
  405 + emax - Maximum energy for fitting and flux computation
391 406 bkg_model - Background model
392 407 full_model - Source model
393 408 """
394 409 # Set TeV->erg conversion factor
395 410 tev2erg = 1.6021764
  411 +
  412 + # Set energy boundaries
  413 + self.set_obs_ebounds(emin, emax)
396 414  
397 415 # Determine energy boundaries from first observation in
398 416 # the container
399   - for run in obs:
400   - emin = run.events().ebounds().emin()
401   - emax = run.events().ebounds().emax()
402   - loge = math.log10(math.sqrt(emin.TeV()*emax.TeV()))
403   - erg_mean = math.pow(10.0, loge) * tev2erg
404   - erg_width = (emax.TeV()-emin.TeV()) * tev2erg
405   - break
  417 + #for run in obs:
  418 + # emin = run.events().ebounds().emin()
  419 + # emax = run.events().ebounds().emax()
  420 + # loge = math.log10(math.sqrt(emin.TeV()*emax.TeV()))
  421 + # erg_mean = math.pow(10.0, loge) * tev2erg
  422 + # erg_width = (emax.TeV()-emin.TeV()) * tev2erg
  423 + # break
  424 + loge = math.log10(math.sqrt(emin.TeV()*emax.TeV()))
  425 + erg_mean = math.pow(10.0, loge) * tev2erg
  426 + erg_width = (emax.TeV()-emin.TeV()) * tev2erg
406 427  
407 428 # Compute Crab unit (this is the factor with which the Prefactor needs
408 429 # to be multiplied to get 1 Crab
... ...