Exemple #1
0
#!/usr/bin/env python
import veripy, glob, json, re, numpy
import matplotlib.pyplot as plt
from gammalib import GEnergy

specfiles = glob.glob('logs/spec*json')
emin, emax = [GEnergy(e, 'TeV') for e in [4, 70]]

fig = plt.figure()
fax = fig.add_subplot(111)

xranges, yranges = [], []

for f in sorted(specfiles):
    p = re.search('spec\.([A-Za-z\-\+]+)\.([0-9.]+)(\w+)\.json', f)
    branch = p.groups()[0]
    dmmass = GEnergy(float(p.groups()[1]), p.groups()[2])
    blatex = veripy.clumpy_branch_latex(branch)

    with open(f, 'r') as g:
        spec = json.load(g)

    x = [ix * 1e-3 for ix in spec['energy']['data']]
    y = [iy * 1e3 for iy in spec['dnde']['data']]

    plt.plot(x, y, label=r'%s $\rightarrow %s$' % (str(dmmass), blatex))

    xranges += x
    yranges += y

    v = veripy.clumpy_integrate_single_int_spectrum_json(f,
Exemple #2
0
import matplotlib.pyplot as plt

runnumber = 78128
obs = veripy.load_obs_proper([
    'VR%d.ReconMethodDisp.Cut-NTel2-ExtendedSource-Hard.chunk1.fits' %
    runnumber
])
run = obs[0]
fname = 'psf_parameter_space.pdf'
show_events = True

frac = 0.68
thmin = 0.0001
thmax = 2.15
thnbins = 80
enmin = GEnergy(1.5, 'TeV')
enmax = GEnergy(150.0, 'TeV')
ennbins = 120

thdelta = (thmax - thmin) / thnbins
endelta = (enmax.log10TeV() - enmin.log10TeV()) / ennbins
EN, TH, PSF = [], [], []

# loop over offset (th) and energy (en)
for j in range(ennbins):
    en = ((j + 0.5) * endelta) + enmin.log10TeV()
    for i in range(thnbins):
        th = (((i + 0.5) * thdelta) + thmin) * gammalib.deg2rad
        contain_rad = run.response().psf().containment_radius(frac, en, th)
        contain_rad *= gammalib.rad2deg
        EN.append(en)
Exemple #3
0
#!/usr/bin/env python
import glob, veripy, numpy, gammalib, sys, re, os, random
from math import log10
from gammalib import GEnergy
import mpl_toolkits
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
db = veripy.VeritasDB()

enbins = 100
nruns = 1000
emin = GEnergy(300, 'GeV')
emax = GEnergy(500, 'TeV')
elogd = (emax.log10TeV() - emin.log10TeV()) / enbins


def etrue_center(i):
    return pow(10, emin.log10TeV() + ((i + 0.5) * elogd))


total = numpy.full([enbins, enbins], 1e-99, dtype=numpy.float64)
fdir = veripy.get_fits_dir() + '/sgra/*.fits'
fits = glob.glob(fdir)
random.shuffle(fits)
fits = sorted(fits[:nruns])

nr = 0
totallive = 0
for f in fits:
    #r  = int( re.search( 'VR(\d+)', os.path.basename(f) ).group(1) )
Exemple #4
0
#!/usr/bin/env python
import veripy, sys, os, gammalib, shutil, re, glob, ctools, time
import datetime, gc
from io import StringIO
from os.path import join
from math import log10
from gammalib import GModelSpatialPointSource, GModelSpectralPlaw, GModelSpatialDiffuseMap, GModelSpectralFunc, GModelSky, GFilename, GEnergy, GModelSpectralExpPlaw
import matplotlib.pyplot as plt
import matplotlib.patches as patches

emin, emax = 4, 70  # TeV
elmin, elmax = 26, 30.5  # deg
dm_mass = GEnergy(10, 'TeV')
span = 4  # deg

t1 = time.time()
clumpy = join(os.environ['CLUMPY'], 'bin', 'clumpy')
db = veripy.VeritasDB()
sgra = db.source2dir('Sgr A*')
fitsfiles = sorted(
    veripy.scan_for_fits_files(join(veripy.get_veripy_dir(), 'fits/sgra')))


def get_time():
    return datetime.datetime.now()


statistics = []
statfile = 'logs/statistics.txt'
with open(statfile, 'w') as f:
    f.write('')
Exemple #5
0
def write_archive_radial_smart2(obs,
                                fname,
                                enbins=[0.085, 300],
                                fine_energy_hist='',
                                profile_plot_format='',
                                bkg_profile_plot='',
                                bkg_grid_plot='',
                                tmp_dir='',
                                perturb=False,
                                seed=12):
    """Create a ctools background from the input obs, and save it as a fits file to fname.
    
    **Args:**
      obs   : GObservations object containing event list to use
      fname : str, output fits filename
    
    **Opts:**
      enbins              : [float,float], min and max energy, TeV
      fine_energy_hist    : str, output file path for energy histogram used in 
                            scaling radial profiles
      profile_plot_format : str, output filename format, must have '%d' 
                            somewhere in it
      bkg_profile_plot    : str, background vs energy plot filename
      bkg_grid_plot       : str, grid of detx/y background plots
      perturb             : bool, if true, randomly vary bins via poissonian errors
      seed                : int, random seed to use if perturb is True
    """

    # number of radial bins for building the initial radial background histogram
    nradbins = 47

    # outer radius for building initial radial background histogram
    maxrad = 3.0

    # number of bins in each camera axis of the fits 2D background
    nbkgbins = 80

    # number of extra 'empty' maps to add above and below the existing backgrounds
    nenergybordermaps = 3

    # width in energy space of border maps, in log10(TeV) space
    energyborderwidth = 0.2

    # counts/s/sr/MeV value to use at the edge of the camera and energy range
    bordervalue = 1e-13

    # aim for at least this many events per deg2 for each energy bin
    min_population = 150

    # number of bins near the camera center to combine, since their low solid angle tends to
    # cause larger fluctuations in the number of events
    nradbincombine = 2

    # divide up energy range into this many fine energy bins, for use with templates
    nenfine = 65

    # extra factor (so the likelihood doesn't have to travel so far)
    xfactor = 6.51e-3

    # calculate binning and number of events required per spatial template energy bin
    raddelta = maxrad / nradbins

    def offset2radbin(offset):
        return int(offset / raddelta)

    enmin, enmax = sorted(enbins)
    camera_area = math.pi * pow(maxrad, 2)
    pop_thresh = int(min_population *
                     camera_area)  # minimum number of events needed
    print('population threshold:', pop_thresh)

    # find median energy among all events
    enlist = []
    for run in obs:
        for ev in run.events():
            en = ev.energy().TeV()
            if en > enmin and en < enmax:
                enlist += [en]
    enlist = sorted(enlist)
    median_pos = len(enlist) // 2
    median_energy = enlist[median_pos]
    print('median is %.2f TeV at %d' % (median_energy, median_pos))
    if len(enlist) < pop_thresh:
        raise RuntimeError(
            'only %d total events available, need at least %d to reach required population threshold of %d events/deg2...'
            % (len(enlist), pop_thresh, min_population))

    # expand energy binning upwards from the median energy
    enspec = []
    current_pos = median_pos
    while True:
        next_pos = current_pos + pop_thresh
        # gobble the next one too if we're over the edge of the list
        # if we didn't do this, we'd have a low energy bin without enough events to pass pop_thresh
        if next_pos + pop_thresh > len(enlist):
            next_pos = len(enlist) - 1
        tmp_emin = enlist[current_pos]
        tmp_emax = enlist[next_pos] if enlist[next_pos] < enmax else enmax
        enspec = enspec + [[
            GEnergy(tmp_emin, 'TeV'),
            GEnergy(tmp_emax, 'TeV')
        ]]
        if next_pos == len(enlist) - 1: break
        current_pos = next_pos

    # expand energy binning downwards from the median energy
    current_pos = median_pos
    while True:
        next_pos = current_pos - pop_thresh
        # gobble the next one too if we're over the edge of the list
        # if we didn't do this, we'd have a low energy bin without enough events to pass pop_thresh
        if next_pos - pop_thresh < 0:
            next_pos = 0
        tmp_emax = enlist[current_pos]
        tmp_emin = enlist[next_pos] if enlist[next_pos] > enmin else enmin
        enspec = [[GEnergy(tmp_emin, 'TeV'),
                   GEnergy(tmp_emax, 'TeV')]] + enspec
        if next_pos == 0: break
        current_pos = next_pos

    # add indexes to the energy specifications
    for i in range(len(enspec)):
        enspec[i] = [i] + enspec[i]
    print('enspec:')
    for es in enspec:
        print(es[0], '%.2f' % es[1].TeV(), '%.2f' % es[2].TeV())
    print()

    center = GSkyDir()
    center.radec(0.0, 0.0)
    bkgmaps = []
    delta = 2 * maxrad / nbkgbins  # bin width in deg
    binarea = delta * delta * deg2rad * deg2rad  # sr
    bintime = obs2ontime(obs)

    energ_lo, energ_hi = [], []
    detx_lo, detx_hi = [], []
    dety_lo, dety_hi = [], []
    for ix in range(nbkgbins):
        lo = -maxrad + (ix * delta)
        hi = -maxrad + ((ix + 1) * delta)
        detx_lo += [lo]
        detx_hi += [hi]
        dety_lo += [lo]
        dety_hi += [hi]

    # radial interpolation functions and the energies over which they should be used
    rad_interp_funcs = []

    for ien, en_min, en_max in enspec:
        radbins = [0 for i in range(nradbins)]
        binenergy = en_max.MeV() - en_min.MeV()
        bin_volume = binenergy * binarea * bintime

        if perturb:
            # 2d histogram with fine binning
            numpy.random.seed(seed)
            nfine = 137  # number of bins in each dimension
            finelim = 3.0  # deg span
            twodhist = [[0] * nfine for i in range(nfine)]
            minlim = -1 * finelim
            limwid = 2 * finelim
            binwid = limwid / nfine

            def val2index(val):
                return int((val - minlim) / binwid)

            def index2cent(index):
                return ((index + 0.5) * binwid) + minlim

            for run in obs:
                for ev in run.events():
                    en = ev.energy()
                    if en > en_min and en <= en_max:
                        dx = ev.dir().detx() * rad2deg
                        dy = ev.dir().dety() * rad2deg
                        ix = val2index(dx)
                        iy = val2index(dy)
                        twodhist[ix][iy] += 1
                        print(
                            'twodhistfill : ix iy %3d %3d : dx dy %6.3f %6.3f'
                            % (ix, iy, dx, dy))

            # show
            for ix in range(nfine):
                dx = index2cent(ix)
                for iy in range(nfine):
                    dy = index2cent(iy)
                    if twodhist[ix][iy] > 0:
                        print(
                            'twodhistprint : ix iy %3d %3d : dx dy %6.3f %6.3f : twodhist %2d'
                            % (ix, iy, dx, dy, twodhist[ix][iy]))

            # randomly perturb via poissonian statistics
            for ix in range(nfine):
                dx = index2cent(ix)
                for iy in range(nfine):
                    dy = index2cent(iy)
                    twodhist[ix][iy] = numpy.random.poisson(
                        lam=twodhist[ix][iy])
                    if twodhist[ix][iy] > 0:
                        print(
                            'twodhistperturb : ix iy %3d %3d : dx dy %6.3f %6.3f : twodhist %.3f'
                            % (ix, iy, dx, dy, twodhist[ix][iy]))

            # rebin radially
            for ix in range(nfine):
                dx = index2cent(ix)
                for iy in range(nfine):
                    dy = index2cent(iy)
                    detdir = GSkyDir()
                    detdir.radec(dx * deg2rad, dy * deg2rad)
                    offset = center.dist(detdir) * rad2deg
                    print('ix iy %d %d : dx dy %.3f %.3f : offset %.3f' %
                          (ix, iy, dx, dy, offset))
                    if offset > finelim: continue
                    rbin = offset2radbin(offset)
                    print(
                        'twodhist rebin ix iy %3d %3d : dx dy %.2f %.2f : offset %.3f : rbin %d'
                        % (ix, iy, dx, dy, offset, rbin))
                    radbins[rbin] += twodhist[ix][iy]

        else:
            # else radially bin events like normal
            for run in obs:
                for ev in run.events():
                    en = ev.energy()
                    if en > en_min and en <= en_max:
                        detx = ev.dir().detx()
                        dety = ev.dir().dety()
                        detdir = GSkyDir()
                        detdir.radec(detx, dety)
                        offset = center.dist(detdir) * rad2deg
                        rbin = offset2radbin(offset)
                        radbins[rbin] += 1

        #for i in range(
        #print(

        # calculate the average # events per bin area
        radbinavgs = [0 for i in range(len(radbins))]
        yerr = [0 for i in range(len(radbins))]
        time, signal = [], []
        for i, r in enumerate(radbins):

            # if requested, merge the first nradbincombine bins to help them stabilize
            # (the bins close to the camera center tend to fluctuate due to low statistics)
            if i < nradbincombine:
                rcombine = sum(radbins[:nradbincombine])
                rcombine_area = math.pi * pow(nradbincombine * raddelta, 2)
                radbinavgs[i] = rcombine / rcombine_area
                yerr[i] = math.sqrt(rcombine)
            else:
                # otherwise just take the bin's counts / area
                area = math.pi * (pow(
                    (i + 1) * raddelta, 2) - pow(i * raddelta, 2))
                if radbins[i] == 0:
                    radbinavgs[i] = bordervalue
                else:
                    radbinavgs[i] = radbins[i] / area
                yerr[i] = math.sqrt(radbins[i])
                if radbins[i] > 0:
                    time.append((i + 0.5) * raddelta)
                    signal.append(radbinavgs[i])

        # find center of first bin with zero events
        zerorad = maxrad
        for i, r in enumerate(radbins):
            rcenter = (i + 0.5) * raddelta
            # if this bin and all later bins have zero events,
            # this is the radius at which we start zeroing-out background values
            # otherwise the interpolation function bounces around a bit, causing weird values
            if sum(radbins[i:]) == 0:
                zerorad = rcenter
                break
        print()
        print('zero radius : %.2f deg' % zerorad)
        print('ien:%d : %d events : %d events/deg2' %
              (ien, sum(radbins), sum(radbins) / (math.pi * pow(maxrad, 2))))
        for i, r in enumerate(radbinavgs):
            print('  r%2d: %4.2f : %4d : %6.1e : %4.1e' %
                  (i, i * raddelta, radbins[i], r, yerr[i]))
        print()

        # fit a polynomial to this curve
        x = numpy.array([(i + 0.5) * raddelta for i in range(len(radbins))])
        y = numpy.array(radbinavgs)
        ye = numpy.array(yerr)
        # since the bins are radial, the radius=0 bin edge should have a derivative of zero
        # so we repeate the radius=0 bin counts for a few more points to force the interpolation
        # to weight that effect more
        for i in range(4):
            x = numpy.insert(x, 0, x[0] - raddelta, axis=0)
            y = numpy.insert(y, 0, y[0], axis=0)
            ye = numpy.insert(ye, 0, ye[0], axis=0)
        for i in range(6):
            x = numpy.append(x, x[-1] + raddelta)
            y = numpy.append(y, y[-1])
            ye = numpy.append(ye, ye[-1])

        # interpolate from our points
        # the 'kind' kwarg indicates the interpolation mode
        # kind=3 :  uses an interpolating spline with a minimum sum-of-squares discontinuity in the 3rd derivative
        interpf6 = scipy.interpolate.interp1d(x,
                                              y,
                                              kind=3,
                                              axis=-1,
                                              copy=True,
                                              bounds_error=False)

        x2 = numpy.linspace(-0.75, maxrad * 1.2, 200)
        y6 = numpy.array([interpf6(i) for i in x2])

        # interpolate the radial bins
        coefs = numpy.polynomial.polynomial.polyfit(x, y, 4)
        ffit = numpy.polynomial.polynomial.polyval(x2, coefs)
        if len(profile_plot_format) > 0:
            fig = plt.figure()
            ax1 = fig.add_subplot(111)
            ax1.errorbar(x,
                         y,
                         yerr=ye,
                         fmt='o',
                         linewidth=3,
                         capsize=4,
                         elinewidth=3,
                         markeredgewidth=3,
                         label='Observed Events')
            lines = ax1.plot(x2,
                             y6,
                             color='purple',
                             linewidth=3,
                             label='Interpolated Curve')
            plt.title(
                'Events/degrees${}^{2}$ in Radial Bins (%.2f - %.2f TeV)' %
                (en_min.TeV(), en_max.TeV()),
                fontsize=15)
            plt.xlabel(r'Angular Distance from Camera Center (${}^{\circ}$)',
                       fontsize=15)
            plt.ylabel('Events/degree${}^{2}$', fontsize=15)
            #plt.setp( lines, color='purple', linewidth=3 )
            plt.legend(loc='upper right', prop={'size': 15}, numpoints=1)
            plt.tick_params(axis='both', which='major', labelsize=15)
            plt.savefig(profile_plot_format % ien, dpi=150)
            plt.close(fig)

        # add our interpolation function to the list of radial profiles
        rad_interp_funcs += [[en_min, en_max, interpf6, zerorad]]

    # log10 mean of a list of GEnergy objects
    def en_lmean(enlist):
        entotal = sum([en.log10TeV() for en in enlist])
        return GEnergy(pow(10, entotal / len(enlist)), 'TeV')

    # fine energy bin specifications
    e_log_min = math.log10(enmin)
    e_log_max = math.log10(enmax)
    e_log_delta = (math.log10(enmax) - e_log_min) / nenfine

    # figure out how many events are in each fine energy bin
    n_events_fine = [0 for i in range(nenfine)]
    for run in obs:
        for ev in run.events():
            enlog = ev.energy().log10TeV()
            ibin = int((enlog - e_log_min) / e_log_delta)
            if ibin >= 0 and ibin < nenfine:
                n_events_fine[ibin] += 1

    print()
    print('energy histogram')
    for i in range(nenfine):
        en = pow(10, e_log_min + i * e_log_delta)
        print('  %.2f TeV - %d' % (en, n_events_fine[i]))
    print()

    if len(fine_energy_hist) > 0:

        # figure out x limits
        xmin_i, xmax_i = -1, -1
        for i in range(nenfine):
            xmin_i = i
            if n_events_fine[i] > 0: break
        print()
        print('calculating xmax_i:')
        for i in reversed(range(nenfine)):
            xmax_i = i
            print('  i:%2d  xmax:%.3f' % (i, e_log_min +
                                          ((xmax_i + 1) * e_log_delta)))
            if n_events_fine[i] > 0:
                print('  break!')
                break
        xmin = e_log_min + (
            (xmin_i - 1) * e_log_delta)  # with buffer of 1 bin width
        xmax = e_log_min + (
            (xmax_i + 2) * e_log_delta)  # with buffer of 1 bin width
        print()
        print('Fine Energy Histogram')
        print('xmin', xmin)
        print('xmin_i', xmin_i)
        print('xmax', xmax)
        print('xmax_i', xmax_i)
        print()

        # construct the plot
        fig = plt.figure(figsize=[11, 9])
        lowedges = [e_log_min + i * e_log_delta for i in range(nenfine)]
        plt.bar(lowedges, n_events_fine, width=e_log_delta)
        plt.title('Events in Fine Energy Bins', fontsize=20)
        #plt.xscale('log')
        plt.yscale('log')
        plt.xlabel('Energy log10(TeV)', fontsize=15)
        plt.ylabel('# Events', fontsize=15)
        plt.tick_params(axis='both', which='major', labelsize=15)
        plt.xlim([xmin, xmax])
        fig.tight_layout()
        plt.savefig(fine_energy_hist, dpi=100)
        plt.close(fig)

    bin_solid_angle = pow(delta * deg2rad, 2)
    bin_time = obs2ontime(obs)

    print('r= 0.0,  0.5,  1.0')
    bkgmaps = []
    energ_hi = []
    energ_lo = []
    # loop over fine energy bins
    for ifine in range(nenfine):
        ef_min = GEnergy(pow(10, e_log_min + ifine * e_log_delta), 'TeV')
        ef_max = GEnergy(pow(10, e_log_min + (ifine + 1) * e_log_delta), 'TeV')
        ef_lmean = en_lmean([ef_min, ef_max])

        # figure out which unnormalized radial profile to use for this fine energy bin
        rad_interp_mean_en = [en_lmean([b[0], b[1]]) for b in rad_interp_funcs]
        if ef_lmean < min(rad_interp_mean_en):
            # if we're below the lowest radial profile's mean energy, just use it (no interpolation)
            igross = 0
            igross_lmean = en_lmean(
                [rad_interp_funcs[igross][0], rad_interp_funcs[igross][1]])
            zerorad = rad_interp_funcs[igross][3]

            def prof_unnorm(rad):
                return rad_interp_funcs[igross][2](
                    rad) if rad < zerorad else 0.0

            #print('for fine bin %2d %6.2f TeV : using %6.2f TeV Radial Profile (#%d)' % ( ifine, ef_lmean.TeV(), igross_lmean.TeV(), igross ) )

        elif ef_lmean > max(rad_interp_mean_en):
            # if we're above the highest radial profile's mean energy, just use it (no interpolation)
            igross = len(rad_interp_funcs) - 1
            igross_lmean = en_lmean(
                [rad_interp_funcs[igross][0], rad_interp_funcs[igross][1]])
            zerorad = rad_interp_funcs[igross][3]

            def prof_unnorm(rad):
                return rad_interp_funcs[igross][2](
                    rad) if rad < zerorad else 0.0

            #print('for fine bin %2d %6.2f TeV : using %6.2f TeV Radial Profile (#%d)' % ( ifine, ef_lmean.TeV(), igross_lmean.TeV(), igross ) )

        else:
            # pick the two closest (in energy) radial profiles and do a linear interpolation in log space
            rad_interp_indexes = []
            for i in range(len(rad_interp_mean_en) - 1):
                if ef_lmean > rad_interp_mean_en[
                        i] and ef_lmean < rad_interp_mean_en[i + 1]:
                    rad_interp_indexes = [i, i + 1]
            if len(rad_interp_indexes) == 0:
                raise RuntimeError(
                    'could not find two gross-energy-bins to interpolate radial profiles between, for fine energy bin at %.2f TeV...'
                    % ef_lmean.TeV())

            # setup the interpolation
            def prof_unnorm(rad):
                i1, i2 = rad_interp_indexes
                xx1 = en_lmean(rad_interp_funcs[i1][:2]).log10TeV()
                xx2 = en_lmean(rad_interp_funcs[i2][:2]).log10TeV()
                p1 = rad_interp_funcs[i1][2](
                    rad) if rad < rad_interp_funcs[i1][3] else 0.0
                p2 = rad_interp_funcs[i2][2](
                    rad) if rad < rad_interp_funcs[i2][3] else 0.0
                ptargetfunc = scipy.interpolate.interp1d([xx1, xx2], [p1, p2],
                                                         kind='linear',
                                                         axis=-1,
                                                         copy=True,
                                                         bounds_error=False)
                return ptargetfunc(ef_lmean.log10TeV())

            #i1, i2 = rad_interp_indexes
            #x1 = en_lmean( rad_interp_funcs[i1][:2] )
            #x2 = en_lmean( rad_interp_funcs[i2][:2] )
            #print('for fine bin %2d %6.2f TeV : interpolating between gross bins at %6.2f (#%d) and %6.2f TeV (#%d)' % ( ifine, ef_lmean.TeV(), x1.TeV(), i1, x2.TeV(), i2 ) )

        # normalize profile to one by integrating it in polar coordinates around the entire camera
        integ = scipy.integrate.quad(lambda x: x * prof_unnorm(x), 0, maxrad)
        #print('integral: ', integ )
        radnorm = twopi * integ[0]

        def prof(rad):
            p = prof_unnorm(rad)
            return p / radnorm if p > 0 else 0.0

        #total = twopi * scipy.integrate.quad( lambda r : r*prof(r), 0, maxrad )[0]
        print('%6.2f TeV =  %5.3f  :  %5.3f  :  %5.3f  :  %5.3f  :  %9.7f' %
              (ef_lmean.TeV(), prof(0.0), prof(0.5), prof(1.0), prof(1.5),
               prof(2.25)))

        # prepare to print radial profile to a 2D array
        bin_ewidth = ef_max.MeV() - ef_min.MeV()
        nfine = n_events_fine[ifine]
        bin_volume = bin_solid_angle * bin_time * bin_ewidth
        enmap = numpy.zeros((nbkgbins, nbkgbins))

        # loop over x and y bins in the 2D array
        for ix in range(nbkgbins):
            xpos = -maxrad + (ix + 0.5) * delta
            for iy in range(nbkgbins):
                ypos = -maxrad + (iy + 0.5) * delta
                offset = math.sqrt(xpos * xpos + ypos * ypos)

                # scale profile by background counts and the bin's detx/dety/energy volume
                val = nfine * prof(offset) * xfactor / bin_volume

                # add this background value to the counts map
                enmap[ix][iy] = val if val > 0.0 else bordervalue

        bkgmaps += [enmap]
        energ_lo += [ef_min.TeV()]
        energ_hi += [ef_max.TeV()]

    print()

    # figure out which maps are already border maps (they only have one unique element - the bordervalue)
    isborder = [len(numpy.unique(m)) == 1 for m in bkgmaps]

    # count how many border maps we already have (due to 0 events in some fine energy bins)
    nlowborder, nhighborder = 0, 0
    for i in range(len(bkgmaps)):
        if isborder[i]: nlowborder += 1
        else: break
    for i in reversed(range(len(bkgmaps))):
        if isborder[i]: nhighborder += 1
        else: break

    # if we need to add lower energy border maps, add them
    print('found %d lower energy border maps already in place...' % nlowborder)
    print('found %d higher energy border maps already in place...' %
          nhighborder)
    bordermap = numpy.full((nbkgbins, nbkgbins), bordervalue)
    if nlowborder < nenergybordermaps:
        print(
            'so we\'re adding %d extra energy border maps to the low energy end'
            % (nenergybordermaps - nlowborder))
        for i in range(nenergybordermaps - nlowborder):
            bkgmaps = [bordermap] + bkgmaps
            down_energy_max = GEnergy(energ_lo[0], 'TeV')
            down_energy_min = GEnergy(
                pow(10,
                    down_energy_max.log10TeV() - energyborderwidth), 'TeV')
            print('adding upper border map from %.2f-%.2f TeV...' %
                  (down_energy_min.TeV(), down_energy_max.TeV()))
            energ_lo = [down_energy_min.TeV()] + energ_lo
            energ_hi = [down_energy_max.TeV()] + energ_hi

    # or if we have have too many border maps, remove a few until we have nenergybordermaps
    elif nlowborder > nenergybordermaps:
        print('pruning %d excess energy border maps from the low energy end' %
              (nlowborder - nenergybordermaps))
        for i in range(nlowborder - nenergybordermaps):
            del bkgmaps[0]
            del energ_lo[0]
            del energ_hi[0]

    # if we need to add more upper energy border maps, add them
    if nhighborder < nenergybordermaps:
        print('adding %d extra energy border maps to the high energy end' %
              (nenergybordermaps - nhighborder))
        for i in range(nenergybordermaps - nhighborder):
            # add upper-energy border background
            bkgmaps += [bordermap]
            uppp_energy_min = GEnergy(energ_hi[-1], 'TeV')
            uppp_energy_max = GEnergy(
                pow(10,
                    uppp_energy_min.log10TeV() + energyborderwidth), 'TeV')
            print('adding lower border map from %.2f-%.2f TeV...' %
                  (uppp_energy_min.TeV(), uppp_energy_max.TeV()))
            energ_lo += [uppp_energy_min.TeV()]
            energ_hi += [uppp_energy_max.TeV()]

    # or if we have have too many border maps, remove a few until we have nenergybordermaps
    elif nhighborder > nenergybordermaps:
        print('pruning %d excess energy border maps from the high energy end' %
              (nhighborder - nenergybordermaps))
        for i in range(nhighborder - nenergybordermaps):
            del bkgmaps[-1]
            del energ_lo[-1]
            del energ_hi[-1]

    # add our empty energy-border maps, so ctools interpolation behaves
    # properly at the edges of the energy range
    while False:
        for i in range(nenergybordermaps):

            # add lower-energy border background
            bordermap = numpy.full((nbkgbins, nbkgbins), bordervalue)
            bkgmaps = [bordermap] + bkgmaps
            down_energy_max = GEnergy(energ_lo[0], 'TeV')
            print('down_energy_max:', repr(down_energy_max))
            down_energy_min = GEnergy(
                pow(10,
                    down_energy_max.log10TeV() - energyborderwidth), 'TeV')
            print('adding upper border map from %.2f-%.2f TeV...' %
                  (down_energy_min.TeV(), down_energy_max.TeV()))
            energ_lo = [down_energy_min.TeV()] + energ_lo
            energ_hi = [down_energy_max.TeV()] + energ_hi

            # add upper-energy border background
            bkgmaps += [bordermap]
            uppp_energy_min = GEnergy(energ_hi[-1], 'TeV')
            uppp_energy_max = GEnergy(
                pow(10,
                    uppp_energy_min.log10TeV() + energyborderwidth), 'TeV')
            print('adding lower border map from %.2f-%.2f TeV...' %
                  (uppp_energy_min.TeV(), uppp_energy_max.TeV()))
            energ_lo += [uppp_energy_min.TeV()]
            energ_hi += [uppp_energy_max.TeV()]

    # write our background cube
    bkgdata = {}
    bkgdata['BGD'] = bkgmaps
    bkgdata['DETX_LO'] = detx_lo
    bkgdata['DETX_HI'] = detx_hi
    bkgdata['DETY_LO'] = dety_lo
    bkgdata['DETY_HI'] = dety_hi
    bkgdata['ENERG_LO'] = [GEnergy(en, 'TeV') for en in energ_lo]
    bkgdata['ENERG_HI'] = [GEnergy(en, 'TeV') for en in energ_hi]
    background2fits_prototype(bkgdata, fname)

    if len(bkg_profile_plot) > 0 or len(bkg_grid_plot) > 0:
        run = GCTAObservation()
        rsp = GCTAResponseIrf()
        rsp.load_background(fname)
        run.response(rsp)
        if len(bkg_profile_plot) > 0:
            background_profile(run, bkg_profile_plot)
        if len(bkg_grid_plot) > 0:
            plot_fits_background_grid(run, bkg_grid_plot, temp_dir=tmp_dir)

    return
Exemple #6
0
 def en_lmean(enlist):
     entotal = sum([en.log10TeV() for en in enlist])
     return GEnergy(pow(10, entotal / len(enlist)), 'TeV')
Exemple #7
0
run = obs[0]

edisp = run.response().edisp()
table = edisp.table()
atheta = table.axis('THETA')
aetrue = table.axis('ETRUE')
aemigr = table.axis('MIGRA')
amatri = table.table('MATRIX')
ntheta = table.axis_bins(atheta)
netrue = table.axis_bins(aetrue)
nemigr = table.axis_bins(aemigr)

temp_dir = tempfile.mkdtemp()

e_nbins = 110
e_min = GEnergy(300, 'GeV')
e_max = GEnergy(500, 'TeV')
e_logdelta = (e_max.log10TeV() - e_min.log10TeV()) / e_nbins


def etrue_center(i):
    return pow(10, e_min.log10TeV() + ((i + 0.5) * e_logdelta))


def theta_center(i):
    theta_lo = table.axis_lo(atheta, i)
    theta_hi = table.axis_hi(atheta, i)
    return (theta_lo + theta_hi) / 2


# fill energy columns