def main(
    input_fits, label, color,
    output, reference
):
    '''
    Plots a sensitivity curve vs real energy. For each energy bin it performs a gridsearch
    to find the theta and gamma_prediction_mean cuts that produce the highest sensitivity.
    '''


    if label and len(input_fits) != len(label):
        print('Must pass as many labels as gamma files as proton files')

    if color and label and len(label) != len(color):
        print('Must pass as many colors as labels')

    t_obs = 50 * u.h

    if not label:
        label = input_fits

    if not color:
        color = [None] * len(input_fits)

    for fits_file, l, c in zip(input_fits, label, color):
        table, bin_edges, _, _ = read_sensitivity_fits(fits_file)

        sens = table['flux'].to(1 / (u.erg * u.s * u.cm**2))
        if 'flux_std' in table.colnames:
            flux_std = table['flux_std'].to(1 / (u.erg * u.s * u.cm**2))
        else:
            flux_std = None

        ax = plot_sensitivity(bin_edges, sens, sensitivity_std=flux_std, ax=None, label=l, color=c)

    plot_spectrum(CrabSpectrum(), 0.003 * u.TeV, 330 * u.TeV, ax=ax, color='gray')

    if reference:
        path = 'resources/ascii/CTA-Performance-prod3b-v1-South-20deg-50h-DiffSens.txt'
        df = pd.read_csv(path, delimiter='\t\t', skiprows=10, names=['e_min', 'e_max', 'sensitivity'], engine='python')
        bin_edges = sorted(list(set(df.e_min) | set(df.e_max))) * u.TeV
        sensitivity = df.sensitivity.values * u.erg/(u.cm**2 * u.s)
        ax = plot_sensitivity(bin_edges, sensitivity, ax=ax, scale=False, label='prod3B reference', color='black')


    ax.set_yscale('log')
    ax.set_xscale('log')
    ax.set_ylabel(r'$ \mathrm{photons} / \mathrm{erg s} \mathrm{cm}^2$ in ' + str(t_obs.to('h')) + ' hours' )
    ax.set_ylabel(r'$ E^2 \cdot \mathrm{photons} \quad \mathrm{erg} /( \mathrm{s} \quad  \mathrm{cm}^2$ )  in ' + str(t_obs.to('h')) )
    ax.set_xlabel(r'$E /  \mathrm{TeV}$')


    if label[0]:
        plt.legend()

    if output:
        plt.savefig(output)
    else:
        plt.show()
Ejemplo n.º 2
0
def main(gammas, protons, output):

    t_obs = 50 * u.h

    gammas = fact.io.read_data(gammas, key='array_events')
    gammas = gammas.dropna()

    gamma_runs = fact.io.read_data(gammas, key='runs')
    mc_production_gamma = MCSpectrum.from_cta_runs(gamma_runs)

    protons = fact.io.read_data(protons, key='array_events')
    protons = protons.dropna()

    # print(f'Plotting {len(protons)} protons and {len(gammas)} gammas.')
    proton_runs = fact.io.read_data(protons, key='runs')
    mc_production_proton = MCSpectrum.from_cta_runs(proton_runs)

    crab = CrabSpectrum()
    cosmic = CosmicRaySpectrum()

    gammas['weight'] = mc_production_gamma.reweigh_to_other_spectrum(
        crab, gammas.mc_energy.values * u.TeV, t_assumed_obs=t_obs)
    protons['weight'] = mc_production_proton.reweigh_to_other_spectrum(
        cosmic, protons.mc_energy.values * u.TeV, t_assumed_obs=t_obs)

    # gammas_gammalike = gammas.query(f'gamma_prediction_mean > {cut}')
    # protons_gammalike = protons.query(f'gamma_prediction_mean > {cut}')

    bin_edges, _, _ = make_energy_bins(gammas.mc_energy.values * u.TeV,
                                       bins=20)
    on, off, alpha = coordinates.split_on_off(gammas,
                                              protons,
                                              on_region_radius=0.4 * u.deg)
    print(f'alpha:{alpha}')
    on['energy_bin'] = pd.cut(on.mc_energy, bin_edges)
    off['energy_bin'] = pd.cut(off.mc_energy, bin_edges)
    for ((_, g_on), (_, g_off)) in zip(on.groupby('energy_bin'),
                                       off.groupby('energy_bin')):
        n_on = g_on.weight.sum()
        n_off = g_off.weight.sum()
        print('----' * 20)
        print(n_on, n_off)
        print(g_on.size, g_off.size)
        print(li_ma_significance(n_on, n_off, alpha=1))

    if output:
        plt.savefig(output)
    else:
        plt.show()
def calculate_differential_sensitivity(
        gammas,
        protons,
        bin_edges,
        gamma_prediction_cut=0.7,
        signal_region_radius=0.25 * u.deg,
        target_spectrum=CrabSpectrum(),
):
    if 'theta' not in gammas.columns:
        gammas['theta'] = coordinates.calculate_distance_theta(
            gammas, source_az=0 * u.deg, source_alt=70 * u.deg).to(u.deg).value

    if 'theta' not in protons.columns:
        protons['theta'] = coordinates.calculate_distance_theta(
            protons, source_az=0 * u.deg,
            source_alt=70 * u.deg).to(u.deg).value

    gammas['energy_bin'] = pd.cut(gammas.mc_energy, bin_edges)
    protons['energy_bin'] = pd.cut(protons.mc_energy, bin_edges)

    rows = []
    for (
            bin,
            g,
    ), (_, p) in zip(gammas.groupby('energy_bin'),
                     protons.groupby('energy_bin')):
        flux = calculate_sensitivity(g,
                                     p,
                                     bin.left,
                                     bin.right,
                                     gamma_prediction_cut=gamma_prediction_cut,
                                     signal_region=signal_region_radius)

        d = {
            'left_edge': bin.left,
            'right_edge': bin.right,
            'flux': flux.to(1 / (u.m**2 * u.s * u.TeV)).value
        }
        rows.append(d)

    t = Table(rows)
    t['flux'] = t['flux'] / (u.m**2 * u.s * u.TeV)
    t['radius'] = signal_region_radius
    t['threshold'] = gamma_prediction_cut
    t['left_edge'] = t['left_edge'] * u.TeV
    t['right_edge'] = t['right_edge'] * u.TeV
    return t
Ejemplo n.º 4
0
def main(
    gamma_input, proton_input, output,
    n_bins,
    n_jobs,
    optimize,
    iterations,
):
    '''
    Calculates a sensitivity curve vs real energy. For each energy bin it performs a gridsearch
    to find the theta and gamma_prediction_mean cuts that produce the highest sensitivity.
    '''

    t_obs = 50 * u.h
    e_min, e_max = 0.003 * u.TeV, 330 * u.TeV
    bin_edges, _, _ = make_energy_bins(e_min=e_min, e_max=e_max, bins=n_bins)

    columns = ['gamma_prediction_mean', 'az_prediction', 'alt_prediction', 'mc_alt', 'mc_az', 'mc_energy']

    gammas = fact.io.read_data(gamma_input, key='array_events', columns=columns)
    gammas = gammas.dropna()


    gamma_runs = fact.io.read_data(gamma_input, key='runs')
    mc_production_gamma = MCSpectrum.from_cta_runs(gamma_runs)

    protons = fact.io.read_data(proton_input, key='array_events', columns=columns)
    protons = protons.dropna()

    proton_runs = fact.io.read_data(proton_input, key='runs')
    mc_production_proton = MCSpectrum.from_cta_runs(proton_runs)

    crab = CrabSpectrum()
    cosmic = CosmicRaySpectrum()

    gammas['weight'] = mc_production_gamma.reweigh_to_other_spectrum(crab, gammas.mc_energy.values * u.TeV, t_assumed_obs=t_obs)
    protons['weight'] = mc_production_proton.reweigh_to_other_spectrum(cosmic, protons.mc_energy.values * u.TeV, t_assumed_obs=t_obs)


    if optimize:
        result_table = optimize_differential_sensitivity(gammas, protons, bin_edges=bin_edges, num_threads=n_jobs)
    else:
        result_table = calculate_differential_sensitivity(gammas, protons, bin_edges=bin_edges)

    result_table.write(output, overwrite=True)
def optimize_differential_sensitivity(
        gammas,
        protons,
        bin_edges,
        target_spectrum=CrabSpectrum(),
        num_threads=-1,
):

    if 'theta' not in gammas.columns:
        gammas['theta'] = coordinates.calculate_distance_theta(
            gammas, source_az=0 * u.deg, source_alt=70 * u.deg).to(u.deg).value

    if 'theta' not in protons.columns:
        protons['theta'] = coordinates.calculate_distance_theta(
            protons, source_az=0 * u.deg,
            source_alt=70 * u.deg).to(u.deg).value

    gammas['energy_bin'] = pd.cut(gammas.mc_energy, bin_edges)
    protons['energy_bin'] = pd.cut(protons.mc_energy, bin_edges)

    if num_threads == -1:
        num_threads = multiprocessing.cpu_count() // 2

    args = [(gammas[gammas.energy_bin == bin],
             protons[protons.energy_bin == bin], bin)
            for bin in gammas.energy_bin.cat.categories]

    if num_threads > 1:
        with multiprocessing.Pool(processes=num_threads) as pool:
            results = pool.starmap(_find_best_sensitivity_in_bin, args)
    else:
        results = list(starmap(_find_best_sensitivity_in_bin, args))

    # multiply the whole thing by the proper unit. There must be a nicer way to do this.
    # sensitivity = np.array([s[0].value for s in results]) * results[0][0].unit
    return _optimizer_result_to_table(results)
Ejemplo n.º 6
0
import numpy as np
import pandas as pd

import astropy.units as u
from astropy.coordinates import Angle
from astropy.coordinates.angle_utilities import angular_separation
from astropy.coordinates import EarthLocation, AltAz, SkyCoord

from scipy.optimize import brute, minimize_scalar

import fact.io

from spectrum import CosmicRaySpectrum, CrabSpectrum, MCSpectrum

crab = CrabSpectrum()
cosmic_proton = CosmicRaySpectrum()


def read_data(input_file, weight=False, spectrum=None, t_obs=50 * u.h):
    columns = [
        'gamma_score_mean',
        'energy_mean',
        'source_az_mean',
        'source_alt_mean',  #'altitude_raw', 'azimuth_raw', 
        'mc_energy'
    ]

    df_arr = fact.io.read_data(input_file, key='array_events')
    df_tel = fact.io.read_data(input_file, key='telescope_events')
def calculate_sensitivity(gammas,
                          protons,
                          min_energy,
                          max_energy,
                          gamma_prediction_cut=0.5,
                          signal_region=0.01,
                          target_spectrum=CrabSpectrum()):

    if 'theta' not in gammas.columns:
        gammas['theta'] = coordinates.calculate_distance_theta(
            gammas, source_az=0 * u.deg, source_alt=70 * u.deg).to(u.deg).value

    if 'theta' not in protons.columns:
        protons['theta'] = coordinates.calculate_distance_theta(
            protons, source_az=0 * u.deg,
            source_alt=70 * u.deg).to(u.deg).value

    selected_gammas = gammas.query(
        f'gamma_prediction_mean >={gamma_prediction_cut}').copy()
    selected_protons = protons.query(
        f'gamma_prediction_mean >={gamma_prediction_cut}').copy()

    # import IPython; IPython.embed()

    # print(selected_gammas.shape)
    # print(selected_protons.shape)

    if len(selected_protons) < 100 or len(selected_gammas) < 20:
        # print('Not enough events')
        return np.inf / (u.erg * u.s * u.cm**2)

    on, off, alpha = coordinates.split_on_off(selected_protons,
                                              selected_gammas,
                                              on_region_radius=signal_region)
    if (len(off) < 1000):
        print('Not enough off events')
        return np.inf / (u.erg * u.s * u.cm**2)

    n_off = off.weight.sum()
    n_on = on.weight.sum()

    # n_on, n_off, alpha = get_on_and_off_counts(
    #     selected_gammas,
    #     selected_protons,
    #     on_region_radius=signal_region
    # )
    if (n_off * alpha + 10 > n_on):
        print('N_off larger than n_on')
        return np.inf / (u.erg * u.s * u.cm**2)

    relative_flux = relative_sensitivity(
        n_on,
        n_off,
        alpha=alpha,
    )

    if np.isnan(relative_flux):
        return np.inf / (u.erg * u.s * u.cm**2)

    # print(f'conf cut = {gamma_prediction_cut}, region = {signal_region},  relative_flux={relative_flux}, lima={li_ma_significance(n_on, n_off, alpha=alpha)}, aplha= {alpha}')
    # print(f'n_on = {n_on}, n_off*alpha = {alpha*n_off}, n_off = {n_off}, ')

    bin_center = np.sqrt(min_energy * max_energy) * u.TeV
    sens = target_spectrum.flux(bin_center) * relative_flux
    return sens.to(1 / (u.erg * u.s * u.cm**2))
Ejemplo n.º 8
0
def main(gammas_dl3, protons_dl3, output_pdf, bins, threshold):
    cols = ['az_prediction', 'alt_prediction', 'mc_energy']

    gammas = fact.io.read_data(gammas_dl3, key='array_events')
    print(f'Reading {len(gammas)} gammas')
    # import IPython; IPython.embed()

    gammas = gammas.dropna(subset=cols)

    protons = fact.io.read_data(protons_dl3, key='array_events')
    print(f'Reading {len(protons)} protons')
    protons = protons.dropna(subset=cols)

    gamma_runs = fact.io.read_data(gammas_dl3, key='runs')
    mc_production_gamma = MCSpectrum.from_cta_runs(gamma_runs)

    proton_runs = fact.io.read_data(protons_dl3, key='runs')
    mc_production_proton = MCSpectrum.from_cta_runs(proton_runs)

    crab = CrabSpectrum()
    cosmic = CosmicRaySpectrum()
    t_obs = 60 * u.s
    gammas['weight'] = mc_production_gamma.reweigh_to_other_spectrum(
        crab, gammas.mc_energy.values * u.TeV, t_assumed_obs=t_obs)
    protons['weight'] = mc_production_proton.reweigh_to_other_spectrum(
        cosmic, protons.mc_energy.values * u.TeV, t_assumed_obs=t_obs)

    with PdfPages(output_pdf) as pdf:

        plt.figure()
        bin_edges, _, _ = make_energy_bins(gammas.mc_energy.values * u.TeV,
                                           bins=20)
        plt.hist(gammas.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='gammas true energy')
        plt.hist(protons.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='proton true energy')
        plt.legend()

        plt.xscale('log')
        plt.xlabel(r'$Energy /  \mathrm{TeV}$')
        plt.ylabel('Counts')
        pdf.savefig()
        plt.close()

        plt.figure()
        gammas['theta'] = calculate_distance(gammas)
        protons['theta'] = calculate_distance(protons)

        bins = np.linspace(0, 25.2, 40)
        kwargs = {'histtype': 'step', 'lw': 2.0}
        plt.hist(gammas['theta'],
                 bins=bins,
                 label='gamma',
                 density=True,
                 **kwargs)
        plt.hist(protons['theta'],
                 bins=bins,
                 label='proton',
                 density=True,
                 **kwargs)
        plt.legend()
        plt.xlabel(r'$Distance /  Degree$')
        plt.ylabel('Normalized Counts')
        pdf.savefig()
        plt.close()

        plt.figure()
        plt.hist(gammas['theta']**2,
                 bins=bins,
                 label='gamma',
                 density=True,
                 **kwargs)
        plt.hist(protons['theta']**2,
                 bins=bins,
                 label='proton',
                 density=True,
                 **kwargs)
        plt.legend()
        plt.xlabel(r'$Distance Squared /  Degree^2$')
        plt.ylabel('Normalized Counts')
        pdf.savefig()
        plt.close()

        plt.figure()
        bins = np.linspace(0, 0.30, 40)
        plt.hist(gammas['theta']**2,
                 bins=bins,
                 label='gamma',
                 density=True,
                 **kwargs)
        plt.hist(protons['theta']**2,
                 bins=bins,
                 label='proton',
                 density=True,
                 **kwargs)
        plt.legend()
        plt.xlabel(r'$Distance Squared /  Degree^2$')
        plt.ylabel('Normalized Counts')
        pdf.savefig()
        plt.close()

        plt.figure()
        bins = np.linspace(0, 0.30, 40)
        on = gammas.append(protons)
        plt.hist(gammas['theta']**2,
                 bins=bins,
                 label='gammas',
                 weights=gammas.weight,
                 **kwargs)
        plt.hist(protons['theta']**2,
                 bins=bins,
                 label='proton',
                 weights=protons.weight,
                 **kwargs)
        plt.legend()
        plt.xlabel(r'$Distance Squared /  Degree^2$')
        plt.ylabel('weighted Counts')
        pdf.savefig()
        plt.close()

        plt.figure()
        bins = np.linspace(0, 0.30, 40)
        on = gammas.append(protons)
        plt.hist(on['theta']**2,
                 bins=bins,
                 label='on (gammas + protons)',
                 weights=on.weight,
                 **kwargs)
        plt.hist(protons['theta']**2,
                 bins=bins,
                 label='proton',
                 weights=protons.weight,
                 **kwargs)
        plt.legend()
        plt.xlabel(r'$Distance Squared /  Degree^2$')
        plt.ylabel('weighted Counts')
        pdf.savefig()
        plt.close()

        fig, ax = plt.subplots()

        c = coordinates.skyccords_from_dl3_table(gammas).icrs
        ra = c.ra.deg
        dec = c.dec.deg

        ra_bins = np.linspace(11, 17, 50)
        dec_bins = np.linspace(41, 47, 50)

        _, _, _, im = ax.hist2d(ra,
                                dec,
                                bins=[ra_bins, dec_bins],
                                cmap='magma')
        ax.set_aspect('equal', )
        plt.colorbar(im, ax=ax)
        plt.title('gammas')
        plt.xlabel(r'$Right Ascension /  Degree$')
        plt.ylabel(r'$Declination /  Degree$')
        pdf.savefig()
        plt.close()

        fig, ax = plt.subplots()

        c = coordinates.skyccords_from_dl3_table(protons).icrs
        ra = c.ra.deg
        dec = c.dec.deg

        _, _, _, im = ax.hist2d(ra,
                                dec,
                                bins=[ra_bins, dec_bins],
                                cmap='magma')
        ax.set_aspect('equal')
        plt.title('protons')
        plt.colorbar(im, ax=ax)
        plt.xlabel(r'$Right Ascension /  Degree$')
        plt.ylabel(r'$Declination /  Degree$')
        pdf.savefig()
        plt.close()

        fig, ax = plt.subplots()
        on, off, _ = coordinates.split_on_off(gammas, protons)
        c = coordinates.skyccords_from_dl3_table(on).icrs
        _, _, _, im = ax.hist2d(c.ra.deg,
                                c.dec.deg,
                                bins=[ra_bins, dec_bins],
                                cmap='magma')
        ax.set_aspect('equal')
        plt.title('on region')
        plt.colorbar(im, ax=ax)
        pdf.savefig()
        plt.close()

        fig, ax = plt.subplots()
        c = coordinates.skyccords_from_dl3_table(off).icrs
        _, _, _, im = ax.hist2d(c.ra.deg,
                                c.dec.deg,
                                bins=[ra_bins, dec_bins],
                                cmap='magma')
        ax.set_aspect('equal')
        plt.colorbar(im, ax=ax)
        plt.title('off region')
        pdf.savefig()
        plt.close()

        plt.figure()
        plt.hist(on.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='on region true energy',
                 density=True)
        plt.hist(off.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='off region true energy',
                 density=True)

        plt.hist(gammas.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='gammas true energy',
                 color='gray',
                 density=True)
        plt.hist(protons.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='proton true energy',
                 color='lightgray',
                 density=True)
        plt.legend()

        plt.xscale('log')
        plt.xlabel(r'$Energy /  \mathrm{TeV}$')
        plt.ylabel(' Normalized  Counts')
        pdf.savefig()
        plt.close()

        gammas = gammas.query(f'gamma_prediction_mean > {threshold}')
        protons = protons.query(f'gamma_prediction_mean > {threshold}')

        plt.figure()
        bins = np.linspace(0, 0.22, 40)
        plt.hist(gammas['theta']**2,
                 bins=bins,
                 label='gamma',
                 density=True,
                 **kwargs)
        plt.hist(protons['theta']**2,
                 bins=bins,
                 label='proton',
                 density=True,
                 **kwargs)
        plt.legend()
        plt.xlabel(r'$Distance Squared /  Degree^2$')
        plt.ylabel(f'Normalized Counts t > {threshold}')
        pdf.savefig()
        plt.close()

        fig, ax = plt.subplots()
        on, off, _ = coordinates.split_on_off(gammas, protons)
        c = coordinates.skyccords_from_dl3_table(on).icrs
        _, _, _, im = ax.hist2d(c.ra.deg,
                                c.dec.deg,
                                bins=[ra_bins, dec_bins],
                                cmap='magma')
        ax.set_aspect('equal')
        plt.colorbar(im, ax=ax)
        plt.title(
            f'{len(on)} gammalike events in on region threshold={threshold}')
        pdf.savefig()
        plt.close()

        fig, ax = plt.subplots()
        c = coordinates.skyccords_from_dl3_table(off).icrs
        _, _, _, im = ax.hist2d(c.ra.deg,
                                c.dec.deg,
                                bins=[ra_bins, dec_bins],
                                cmap='magma')
        ax.set_aspect('equal')
        plt.colorbar(im, ax=ax)
        plt.title(
            f'{len(off)} gammalike events in off region threshold={threshold}')
        pdf.savefig()
        plt.close()

        plt.figure()
        plt.title('gammalike events')
        plt.hist(on.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='on region true energy',
                 density=True)
        plt.hist(off.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='off region true energy',
                 density=True)

        plt.hist(gammas.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='gammas true energy',
                 color='gray',
                 density=True)
        plt.hist(protons.mc_energy,
                 bins=bin_edges,
                 histtype='step',
                 lw=2,
                 label='proton true energy',
                 color='lightgray',
                 density=True)
        plt.legend()

        plt.xscale('log')
        plt.xlabel(r'$Energy /  \mathrm{TeV}$')
        plt.ylabel('Normalized Counts')
        pdf.savefig()
        plt.close()

        plt.figure()
        plt.title('gammalike events')
        plt.hist(
            on.mc_energy,
            bins=bin_edges,
            histtype='step',
            lw=2,
            label='on region true energy',
        )
        plt.hist(
            off.mc_energy,
            bins=bin_edges,
            histtype='step',
            lw=2,
            label='off region true energy',
        )

        plt.hist(
            gammas.mc_energy,
            bins=bin_edges,
            histtype='step',
            lw=2,
            label='gammas true energy',
            color='gray',
        )
        plt.hist(
            protons.mc_energy,
            bins=bin_edges,
            histtype='step',
            lw=2,
            label='proton true energy',
            color='lightgray',
        )
        plt.legend()

        plt.xscale('log')
        plt.yscale('log')
        plt.xlabel(r'$Energy /  \mathrm{TeV}$')
        plt.ylabel('Counts')
        pdf.savefig()
        plt.close()