Commit e1462d5237d99cbb3d01f24a0e378ad43c5e988a

Authored by Rolf Buehler
1 parent 0ec4abd9

Added obsutils.specpoints to make spectral points

Showing 1 changed file with 110 additions and 1 deletions
pyext/ctools/obsutils.py
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 # ========================================================================== 20 # ==========================================================================
21 import ctools 21 import ctools
22 import gammalib 22 import gammalib
  23 +import math
23 24
24 25
25 # ===================== # 26 # ===================== #
@@ -124,7 +125,7 @@ def sim(obs, log=False, debug=False, edisp=False, seed=0, nbins=0, @@ -124,7 +125,7 @@ def sim(obs, log=False, debug=False, edisp=False, seed=0, nbins=0,
124 # ================ # 125 # ================ #
125 # Fit observations # 126 # Fit observations #
126 # ================ # 127 # ================ #
127 -def fit(obs, log=False, debug=False, edisp=False): 128 +def fit(obs, log=False, debug=False, edisp=False, tscalc=False):
128 """ 129 """
129 Perform maximum likelihood fitting of observations in the container. 130 Perform maximum likelihood fitting of observations in the container.
130 131
@@ -145,9 +146,14 @@ def fit(obs, log=False, debug=False, edisp=False): @@ -145,9 +146,14 @@ def fit(obs, log=False, debug=False, edisp=False):
145 # Optionally switch-on debugging model 146 # Optionally switch-on debugging model
146 if debug: 147 if debug:
147 like["debug"].boolean(True) 148 like["debug"].boolean(True)
  149 +
  150 + # Optionally turn on TS calculation
  151 + if tscalc:
  152 + like["tscalc"].boolean(True)
148 153
149 # Optionally apply energy dispersion 154 # Optionally apply energy dispersion
150 like["edisp"].boolean(edisp) 155 like["edisp"].boolean(edisp)
  156 + like["edisp"].boolean(edisp)
151 157
152 # Run ctlike application. 158 # Run ctlike application.
153 like.run() 159 like.run()
@@ -516,3 +522,106 @@ def set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5): @@ -516,3 +522,106 @@ def set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5):
516 522
517 # Return observation definition list 523 # Return observation definition list
518 return obsdeflist 524 return obsdeflist
  525 +
  526 +# ================================================= #
  527 +# Make spectrum for one Source in a CTA Observation #
  528 +# ================================================= #
  529 +
  530 +def getlogbins(nbins=12,emin=0.1,emax=100):
  531 + """
  532 + Returns list with logarithmiscenergy bins in
  533 + format [[emin1,emax1],[emin2,emax2],..]
  534 +
  535 + Parameters:
  536 + nbins Number of bins
  537 + emin Minimum energy
  538 + emax Maximum energy
  539 + """
  540 + lgemin=math.log10(emin)
  541 + lgemax=math.log10(emax)
  542 + lgsize=(lgemax-lgemin)/nbins
  543 + ebins=[]
  544 + for ii in range(0,nbins):
  545 + ebins.append([math.pow(10,lgemin),math.pow(10,lgemin+lgsize)])
  546 + lgemin=lgemin+lgsize
  547 + return ebins
  548 +
  549 +# Please note that specpoints can make spectra for any given
  550 +# spectral model, as long as it has a "Prefactor" or "Integral"
  551 +# parameter which scales the function
  552 +def specpoints(obs,source,ebins):
  553 + """
  554 + Returns spectral points in the given binning for
  555 + the passed observations and source.
  556 +
  557 + Parameters:
  558 + obs - Pointing direction
  559 + source - Source name for which spectrum should be done
  560 + ebins - Binning passed as a list in units of TeV as
  561 + [[emin1,emax1],[emin2,emax2],..]
  562 + Keywords:
  563 + """
  564 + #Check if parameters Prefactor or Integral exist to scale mdoel
  565 + normpar = "Prefactor"
  566 + srcmodel = obs.models()[source]
  567 + if not srcmodel.has_par(normpar):
  568 + if srcmodel.has_par("Integral"):
  569 + normpar = "Integral"
  570 + else:
  571 + print "Error: your spectral model of ",source,"does not\
  572 + have a scaling parameter named 'Prefactor' or 'Integral'"
  573 + return
  574 +
  575 + #Fix all parameters except prefactor
  576 + opt_spectral = srcmodel.spectral()
  577 + for model in obs.models():
  578 + for par in range(model.size()):
  579 + model[par].fix()
  580 + opt_spectral[normpar].free()
  581 +
  582 + #Define spectrum dictionary, units are in format readable by astropy
  583 + pars = {"value":[],"eu_value":[],"ed_value":[],"unit":[]}
  584 + spec = {"energy":pars.copy(),"flux":pars.copy(),"TS":[]}
  585 +
  586 + #Loop over energy bins, fit and write result to spectrum
  587 + for ebin in ebins:
  588 + #Get logarithmic bin center and flux value of all energy fit
  589 + ecenter = math.pow(10,(math.log10(ebin[1])+math.log10(ebin[0]))/2.)
  590 + allflux = opt_spectral.eval(gammalib.GEnergy(ecenter,"TeV"),gammalib.GTime(0))
  591 +
  592 + #Clone observations and reset energy thresholds
  593 + select = ctools.ctselect(obs)
  594 + select["ra"].real(-1.0)
  595 + select["dec"].real(-1.0)
  596 + select["rad"].real(-1.0)
  597 + select["tmin"].real(0)
  598 + select["tmax"].real(0)
  599 + select["emin"].real(ebin[0])
  600 + select["emax"].real(ebin[1])
  601 + select.run()
  602 + obsclone = select.obs()
  603 +
  604 + #Refit and write out to spectrum
  605 + binlike=fit(obsclone,log=False, debug=False, edisp=False,tscalc=True)
  606 + binopt_spectral = binlike.obs().models()[source].spectral()
  607 + binflux=binopt_spectral.eval(gammalib.GEnergy(ecenter,"TeV"),gammalib.GTime(0))
  608 + if binopt_spectral[normpar].value()>0:
  609 + relerr=binopt_spectral[normpar].error()/binopt_spectral[normpar].value()
  610 + else:
  611 + relerr=0
  612 +
  613 + #Store and convert to TeV from MeV
  614 + spec["energy"]["value"].append(ecenter)
  615 + spec["energy"]["ed_value"].append(ecenter-ebin[0])
  616 + spec["energy"]["eu_value"].append(ebin[1]-ecenter)
  617 + spec["energy"]["unit"].append("1e12 eV")
  618 +
  619 + spec["flux"]["value"].append(binflux*1e6)
  620 + spec["flux"]["ed_value"].append(relerr*binflux*1e6)
  621 + spec["flux"]["eu_value"].append(relerr*binflux*1e6)
  622 + spec["flux"]["unit"].append("cm-2 1e-12 eV-1")
  623 +
  624 + spec["TS"].append(binlike.obs().models()[source].ts())
  625 +
  626 + #Return spectrum
  627 + return spec