Commit c2b4bfbe98d4798c04ccfe72804b0de60057790d
1 parent
4d7dc233
added bgtype parameter to cshessobs
Showing
1 changed file
with
128 additions
and
75 deletions
cscripts/cshessobs.py
| ... | ... | @@ -23,6 +23,7 @@ import ctools |
| 23 | 23 | import sys |
| 24 | 24 | import os |
| 25 | 25 | import glob |
| 26 | +import math | |
| 26 | 27 | |
| 27 | 28 | |
| 28 | 29 | # =============== # |
| ... | ... | @@ -43,7 +44,7 @@ class cshessobs(ctools.cscript): |
| 43 | 44 | """ |
| 44 | 45 | # Set name |
| 45 | 46 | self.name = "cshessobs" |
| 46 | - self.version = "0.1.0" | |
| 47 | + self.version = "0.2.0" | |
| 47 | 48 | self.datapath = "" |
| 48 | 49 | self.m_erange = gammalib.GEbounds() |
| 49 | 50 | |
| ... | ... | @@ -57,7 +58,6 @@ class cshessobs(ctools.cscript): |
| 57 | 58 | # Initialise some members |
| 58 | 59 | self.inmodels = None |
| 59 | 60 | self.outobs = "obs.xml" |
| 60 | - self.nodes = 1 | |
| 61 | 61 | |
| 62 | 62 | # Make sure that parfile exists |
| 63 | 63 | file = self.parfile() |
| ... | ... | @@ -165,8 +165,9 @@ class cshessobs(ctools.cscript): |
| 165 | 165 | pars.append(gammalib.GApplicationPar("outobs","f","a","obs.xml","","","Observation XML outfile")) |
| 166 | 166 | pars.append(gammalib.GApplicationPar("outmodel","f","a","bgmodels.xml","","","Output model XML file")) |
| 167 | 167 | pars.append(gammalib.GApplicationPar("datapath","s","h",self.datapath,"","","Data directoy")) |
| 168 | - pars.append(gammalib.GApplicationPar("nodes","i","h","1","","","Number of free parameters per background model")) | |
| 168 | + pars.append(gammalib.GApplicationPar("bkgpars","i","a","1","","","Number of free parameters per background model")) | |
| 169 | 169 | pars.append(gammalib.GApplicationPar("usetrig","b","h","yes","yes|no","","Pre-estimate background normalisation? Recommended for binned analysis")) |
| 170 | + pars.append(gammalib.GApplicationPar("bkgtype","s","a","irf","gauss|irf|aeff","","What background model should be used")) | |
| 170 | 171 | pars.append_standard() |
| 171 | 172 | pars.save(parfile) |
| 172 | 173 | |
| ... | ... | @@ -192,7 +193,8 @@ class cshessobs(ctools.cscript): |
| 192 | 193 | self.outmodel = self["outmodel"].filename() |
| 193 | 194 | |
| 194 | 195 | # Read hidden parameters |
| 195 | - self.nodes = self["nodes"].integer() | |
| 196 | + self.bkgpars = self["bkgpars"].integer() | |
| 197 | + self.bkgtype = self["bkgtype"].string() | |
| 196 | 198 | self.usetrig = self["usetrig"].boolean() |
| 197 | 199 | self.datapath = self["datapath"].string() |
| 198 | 200 | |
| ... | ... | @@ -245,82 +247,130 @@ class cshessobs(ctools.cscript): |
| 245 | 247 | |
| 246 | 248 | # Return valid configs |
| 247 | 249 | return newfolders |
| 248 | - | |
| 249 | - # Create instrument background model | |
| 250 | - def hess_inst_background(self,run,aefffile,trgrate=0.0): | |
| 251 | - | |
| 252 | - # Initialise return spectrum | |
| 253 | - spec = 0 | |
| 254 | - | |
| 255 | - # Initialise default value | |
| 256 | - value = 1.0 | |
| 257 | - | |
| 258 | - if self.usetrig and trgrate > 0.0: | |
| 259 | - # Use value from lookup | |
| 260 | - value = 0.00427233352611 * trgrate + 0.181244590076 | |
| 261 | - | |
| 262 | - if self.nodes <= 1: | |
| 263 | - | |
| 264 | - # Use a constant scaling function | |
| 250 | + | |
| 251 | + def background_spectrum(self, run, prefactor, index, aefffile = ""): | |
| 252 | + | |
| 253 | + scale = pow(10,math.floor(math.log10(abs(prefactor)))) | |
| 254 | + | |
| 255 | + if index == 0.0 and self.bkgpars <= 1: | |
| 265 | 256 | spec = gammalib.GModelSpectralConst() |
| 266 | - spec["Value"].min(0.1) | |
| 267 | - spec["Value"].max(10) | |
| 268 | - spec["Value"].value(value) | |
| 269 | - if self.nodes < 1: | |
| 257 | + spec["Value"].min(0.1*scale) | |
| 258 | + spec["Value"].max(10*scale) | |
| 259 | + spec["Value"].value(prefactor) | |
| 260 | + spec["Value"].scale(scale) | |
| 261 | + if self.bkgpars == 0: | |
| 270 | 262 | spec["Value"].fix() |
| 271 | 263 | else: |
| 272 | 264 | spec["Value"].free() |
| 273 | - | |
| 274 | - elif self.nodes == 2: | |
| 275 | - | |
| 276 | - # User a power law scaling function | |
| 277 | - e = gammalib.GEnergy(1.0,"TeV") | |
| 278 | - spec = gammalib.GModelSpectralPlaw(1.0,0.0,e) | |
| 279 | - spec[0].free() | |
| 280 | - spec[0].min(0.01) | |
| 281 | - spec[0].max(10.0) | |
| 282 | - spec[0].scale(1.0) | |
| 283 | - spec[0].value(value) | |
| 284 | - spec[1].free() | |
| 285 | - spec[1].min(-2.0) | |
| 286 | - spec[1].max(2.0) | |
| 287 | - spec[1].scale(1.0) | |
| 288 | - else: | |
| 289 | - | |
| 290 | - # Use several energy-dependent scaling factors | |
| 291 | - fits = gammalib.GFits(aefffile) | |
| 292 | - emin = fits["EFFECTIVE AREA"].real("LO_THRES") | |
| 293 | - emax = fits["EFFECTIVE AREA"].real("HI_THRES") | |
| 294 | - fits.close() | |
| 295 | - spec = gammalib.GModelSpectralNodes() | |
| 296 | - bounds = gammalib.GEbounds(self.nodes,gammalib.GEnergy(emin,"TeV"),gammalib.GEnergy(emax,"TeV"),True) | |
| 297 | - for i in range(bounds.size()): | |
| 298 | - spec.append(bounds.elogmean(i),value) | |
| 299 | - for par in spec: | |
| 300 | - if "Energy" in par.name(): | |
| 301 | - par.fix() | |
| 302 | - elif "Intensity" in par.name(): | |
| 303 | - par.min(0.01) | |
| 304 | - par.max(10.0) | |
| 305 | - | |
| 306 | - # Create background model instance | |
| 307 | - bck = gammalib.GCTAModelIrfBackground(spec) | |
| 308 | - | |
| 265 | + | |
| 266 | + else: | |
| 267 | + | |
| 268 | + # Create power law if number of free parameters are less 2 or less | |
| 269 | + if self.bkgpars <= 2: | |
| 270 | + e = gammalib.GEnergy(1.0,"TeV") | |
| 271 | + spec = gammalib.GModelSpectralPlaw(prefactor, index, e) | |
| 272 | + | |
| 273 | + # Set parameter ranges | |
| 274 | + spec[0].scale(scale) | |
| 275 | + spec[0].min(0.01 * scale) | |
| 276 | + spec[0].max(100.0 * scale) | |
| 277 | + spec[1].scale(1) | |
| 278 | + spec[1].min(-5.0) | |
| 279 | + spec[1].max(5.0) | |
| 280 | + | |
| 281 | + # Set number of free parameters | |
| 282 | + if self.bkgpars == 0: | |
| 283 | + spec[0].fix() | |
| 284 | + spec[1].fix() | |
| 285 | + elif self.bkgpars == 1: | |
| 286 | + spec[0].free() | |
| 287 | + spec[1].fix() | |
| 288 | + else: | |
| 289 | + spec[0].free() | |
| 290 | + spec[1].free() | |
| 291 | + | |
| 292 | + else: | |
| 293 | + # Use several energy-dependent scaling factors | |
| 294 | + fits = gammalib.GFits(aefffile) | |
| 295 | + emin = fits["EFFECTIVE AREA"].real("LO_THRES") | |
| 296 | + emax = fits["EFFECTIVE AREA"].real("HI_THRES") | |
| 297 | + fits.close() | |
| 298 | + | |
| 299 | + # Create reference powerlaw | |
| 300 | + plaw = gammalib.GModelSpectralPlaw(prefactor, index, gammalib.GEnergy(1.0,"TeV")) | |
| 301 | + | |
| 302 | + # Create spectral model and energy values | |
| 303 | + spec = gammalib.GModelSpectralNodes() | |
| 304 | + bounds = gammalib.GEbounds(self.bkgpars,gammalib.GEnergy(emin,"TeV"),gammalib.GEnergy(emax,"TeV"),True) | |
| 305 | + for i in range(bounds.size()): | |
| 306 | + energy = bounds.elogmean(i) | |
| 307 | + spec.append(energy, plaw.eval(energy, gammalib.GTime())) | |
| 308 | + for par in spec: | |
| 309 | + if "Energy" in par.name(): | |
| 310 | + par.fix() | |
| 311 | + elif "Intensity" in par.name(): | |
| 312 | + par.scale(scale) | |
| 313 | + par.min(0.01*par.scale()) | |
| 314 | + par.max(100.0*par.scale()) | |
| 315 | +# print prefactor, index | |
| 316 | +# print spec | |
| 317 | + return spec | |
| 318 | + | |
| 319 | + def hess_background(self, run, aefffile, trgrate, zenith): | |
| 320 | + | |
| 321 | + # Set IrfBackground | |
| 322 | + if self.bkgtype == "irf": | |
| 323 | + prefactor = 1.0 | |
| 324 | + index = 0.0 | |
| 325 | + if self.usetrig and trgrate > 0.0: | |
| 326 | + # Use value from lookup | |
| 327 | + prefactor = 0.00427233352611 * trgrate + 0.181244590076 | |
| 328 | + spec = self.background_spectrum(run, prefactor, index, aefffile) | |
| 329 | + # Create background model instance | |
| 330 | + bck = gammalib.GCTAModelIrfBackground(spec) | |
| 331 | + | |
| 332 | + # Set AeffBackground | |
| 333 | + elif self.bkgtype == "aeff": | |
| 334 | + prefactor = 5e-14 | |
| 335 | + index = -2.5 | |
| 336 | + # Use values from lookup if possible | |
| 337 | + if self.usetrig and trgrate > 0.0: | |
| 338 | + prefactor = 1.52976410372e-16 * trgrate + 2.71805547108e-14 | |
| 339 | + if zenith > 0.0: | |
| 340 | + index = 0.000271928721732 * zenith * zenith -0.0029602286453 * zenith -2.76404600416 | |
| 341 | + | |
| 342 | + spec = self.background_spectrum(run, prefactor, index, aefffile) | |
| 343 | + | |
| 344 | + # Create background model instance | |
| 345 | + bck = gammalib.GCTAModelAeffBackground(spec) | |
| 346 | + | |
| 347 | + # Set Gaussian Background | |
| 348 | + elif self.bkgtype == "gauss": | |
| 349 | + spec = self.background_spectrum(run, 1e-4, -1.8, aefffile) | |
| 350 | + radial = gammalib.GCTAModelRadialGauss(2.5) | |
| 351 | + bck = gammalib.GCTAModelRadialAcceptance(radial, spec) | |
| 352 | + | |
| 353 | + else: | |
| 354 | + sys.exit("Background type \""+self.bkgtype+"\" unsupported") | |
| 355 | + | |
| 356 | + # Copy model | |
| 357 | + model = bck.clone() | |
| 358 | + | |
| 309 | 359 | # Assign specific run id |
| 310 | - bck.ids(str(int(run))) | |
| 311 | - | |
| 360 | + model.ids(str(int(run))) | |
| 361 | + | |
| 312 | 362 | # Assign instrument |
| 313 | - bck.instruments("HESS") | |
| 314 | - | |
| 363 | + model.instruments("HESS") | |
| 364 | + | |
| 315 | 365 | # Set name (arbitrary) |
| 316 | - bck.name("bkg_"+run) | |
| 317 | - | |
| 366 | + model.name("bkg_"+run) | |
| 367 | + | |
| 318 | 368 | # Turn off TS calculation for background model |
| 319 | - bck.tscalc(False) | |
| 320 | - | |
| 369 | + model.tscalc(False) | |
| 370 | + | |
| 321 | 371 | # Return model |
| 322 | - return bck | |
| 323 | - | |
| 372 | + return model | |
| 373 | + | |
| 324 | 374 | |
| 325 | 375 | def erange(self): |
| 326 | 376 | """ |
| ... | ... | @@ -465,10 +515,13 @@ class cshessobs(ctools.cscript): |
| 465 | 515 | fits = gammalib.GFits(eventfile) |
| 466 | 516 | object_name = fits["EVENTS"].string("OBJECT") |
| 467 | 517 | |
| 468 | - # Retrieve trigger rate if available | |
| 518 | + # Retrieve trigger rate and zenith if available | |
| 469 | 519 | trgrate = 0.0 |
| 520 | + zenith = 0.0 | |
| 470 | 521 | if fits["EVENTS"].has_card("ZTRGRATE"): |
| 471 | 522 | trgrate = fits["EVENTS"].real("ZTRGRATE") |
| 523 | + if fits["EVENTS"].has_card("ALT_PNT"): | |
| 524 | + zenith = 90.-fits["EVENTS"].real("ALT_PNT") | |
| 472 | 525 | |
| 473 | 526 | # Close FITS file |
| 474 | 527 | fits.close() |
| ... | ... | @@ -515,10 +568,10 @@ class cshessobs(ctools.cscript): |
| 515 | 568 | obs.append(psf) |
| 516 | 569 | obs.append(edisp) |
| 517 | 570 | obs.append(bck) |
| 518 | - | |
| 571 | + | |
| 519 | 572 | # Append instrumental background model |
| 520 | - self.models.append(self.hess_inst_background(run,aefffile,trgrate)) | |
| 521 | - | |
| 573 | + self.models.append(self.hess_background(run, aefffile, trgrate, zenith)) | |
| 574 | + | |
| 522 | 575 | # Continue only if there are observations available |
| 523 | 576 | if lib.size(): |
| 524 | 577 | ... | ... |