Beispiel #1
0
def define_flux_crab_above_energy(emin=1 * u.TeV, emax=10 * u.TeV):
    crab = CrabSpectrum('meyer').model
    crabMAGIC = LogParabola(amplitude=3.23e-11 * u.Unit('cm-2 s-1 TeV-1'), reference=1 * u.TeV, alpha=2.47, beta=0.24)
    crab_flux_above_1TeV = crabMAGIC.integral(emin=emin, emax=emax)
    crab_flux_above_1TeV_model = crab.integral(emin=emin, emax=emax)

    return crab_flux_above_1TeV, crab_flux_above_1TeV_model
Beispiel #2
0
def plot_meyer_2010():
    model_meyer_ref = CrabSpectrum("meyer").model
    model_meyer_ref.plot(
        [10 * u.GeV, 100 * u.TeV],
        energy_power=2,
        flux_unit="erg-1 cm-2 s-1",
        ls=":",
        lw=2.2,
        color="#555555",
        label="Meyer et al. (2010)",
    )
Beispiel #3
0
    def fill_derived_spectral_info(self):
        """
        Fill derived spectral info computed from basic parameters
        """
        from gammapy.spectrum import CrabSpectrum
        data = self.data
        # total errors
        data['spec_norm_err_tot'] = np.hypot(data['spec_norm_err'],
                                             data['spec_norm_err_sys'])
        data['spec_index_err_tot'] = np.hypot(data['spec_index_err'],
                                              data['spec_index_err_sys'])

        spec_model = self._get_spec_model(data)

        # Integral flux above 1 TeV
        emin, emax = 1, 1E6  # TeV
        flux_above_1TeV = spec_model.integral(emin, emax)
        data['spec_flux_above_1TeV'] = flux_above_1TeV.n
        data['spec_flux_above_1TeV_err'] = flux_above_1TeV.s

        # Integral flux above 1 TeV in crab units
        crab = CrabSpectrum('meyer').model
        emin, emax = 1, 1E6  # TeV
        flux_above_1TeV = spec_model.integral(emin, emax)
        flux_above_1TeV_crab = crab.integral(emin * u.TeV, emax * u.TeV)
        flux_cu = (flux_above_1TeV / flux_above_1TeV_crab.value) * 100
        data['spec_flux_above_1TeV_crab'] = flux_cu.n
        data['spec_flux_above_1TeV_crab_err'] = flux_cu.s

        # Integral flux above erange_min
        emin, emax = data['spec_erange_min'], 1E6  # TeV
        try:
            flux_above_erange_min = spec_model.integral(emin, emax)
            data['spec_flux_above_erange_min'] = flux_above_erange_min.n
            data['spec_flux_above_erange_min_err'] = flux_above_erange_min.s
        except ValueError:
            data['spec_flux_above_erange_min'] = NA.fill_value['number']
            data['spec_flux_above_erange_min_err'] = NA.fill_value['number']

        # Energy flux between 1 TeV and 10 TeV
        emin, emax = 1, 10  # TeV
        energy_flux = spec_model.energy_flux(emin, emax)

        data['spec_energy_flux_1TeV_10TeV'] = energy_flux.n
        data['spec_energy_flux_1TeV_10TeV_err'] = energy_flux.s

        norm_1TeV = spec_model(1)  # TeV
        data['spec_norm_1TeV'] = norm_1TeV.n
        data['spec_norm_1TeV_err'] = norm_1TeV.s
Beispiel #4
0
    def get_logn_logs(self, quantity, variant):
        crab_1_10 = CrabSpectrum().model.integral(1 * u.TeV, 10 *
                                                  u.TeV).to('cm-2 s-1').value
        bins = np.logspace(-6.1, 0.7, 100)

        hists = []
        for component in self.get_components():
            table = component['table']
            points = table['flux_1_10'] / crab_1_10
            hist = Histogram.from_points(bins=bins, points=points)

            if quantity == 'n':
                pass
            elif quantity == 'f':
                hist.vals = hist.vals * hist.bin_centers
            else:
                raise ValueError('Invalid quantity: {}'.format(quantity))

            if variant == 'diff':
                pass
            elif variant == 'int':
                hist.vals = np.cumsum(hist.vals[::-1])[::-1]
            else:
                raise ValueError('Invalid variant: {}'.format(variant))

            hists.append(hist)

        return HistogramStack(hists)
Beispiel #5
0
    def get_logn_logs(self, quantity, variant, tags):
        #print('ere')
        #bins = np.logspace(-3.1, 0.7, 1000)
        bins = np.logspace(-0.5, 2.1, 1000)
        crab_1_10 = CrabSpectrum().model.integral(1 * u.TeV, 10 * u.TeV).to('cm-2 s-1').value
        hists = []
        hists_skip = []

        for component in self.get_components(tags=tags):
            table = component['table']
            tag = component['tag']

            if tag in {'pwn', 'composite'}:
                fluxes = []
                fluxes_skip = []
                for row in table:
                    flux = row['int_flux_above_1TeV_cu']
                    fluxes.append(flux)
                    if (row['skip'] == 0):
                        fluxes_skip.append(flux)

            if ( tag == 'gammacat'):
                fluxes = []
                fluxes_skip = []
                for row in table:
                    flux = (row['flux_1_10']/crab_1_10)*100
                    fluxes.append(flux)
                    fluxes_skip.append(flux)


            hist = Histogram.from_points(bins=bins, points=fluxes)
            hist_skip = Histogram.from_points(bins=bins, points=fluxes_skip)

            if quantity == 'n':
                pass
            elif quantity == 'f':
                hist.vals = hist.vals * hist.bin_centers
                hist_skip.vals = hist_skip.vals * hist_skip.bin_centers
            else:
                raise ValueError('Invalid quantity: {}'.format(quantity))

            if variant == 'diff':
                pass
            elif variant == 'int':
                hist.vals = np.cumsum(hist.vals[::-1])[::-1]
                hist_skip.vals = np.cumsum(hist_skip.vals[::-1])[::-1]
            else:
                raise ValueError('Invalid variant: {}'.format(variant))

            hists.append(hist)
            hists_skip.append(hist_skip)


        return  HistogramStack(hists_skip), HistogramStack(hists)
Beispiel #6
0
def plot_crab():
    """Plot Crab pulsar and nebula SED."""
    log.info("Executing plot_crab ...")

    fig, ax = plt.subplots()

    # Plot flux points
    for component in ["pulsar", "nebula"]:
        table = Table.read("data/other/crab_mwl.fits.gz")
        table = table[table["component"] == component]
        x = table["energy"].data
        y = table["energy_flux"].data
        yerr_lo = table["energy_flux_err_lo"].data
        yerr_hi = table["energy_flux_err_hi"].data
        ax.errorbar(x, y, yerr=(yerr_lo, yerr_hi), fmt="o", label=component)

    # Plot SED model
    energy = np.logspace(2, 8, 100) * u.MeV

    crab = CrabSpectrum(reference="meyer")

    flux = crab.model(energy)
    energy_flux = (energy**2 * flux).to("erg cm^-2 s^-1")
    ax.plot(energy.value, energy_flux.value, label="Meyer (2010) model", lw=3)

    ax.set_xlim((3e-1, 3e8))
    ax.set_ylim((3e-12, 3e-8))
    ax.set_xlabel("Energy (MeV)")
    ax.set_ylabel("E^2 dN/dE (erg cm^-2 s^-1)")
    fig.legend(loc="upper center", ncol=3)
    ax.grid()
    ax.loglog()

    path = Path("results/figures")
    path.mkdir(parents=True, exist_ok=True)
    filename = "results/figures/crab_mwl.png"
    log.info(f"Writing {filename}")
    fig.savefig(filename)
Beispiel #7
0
def main():
    # Read arguments
    parser = argparse.ArgumentParser(description='Make performance files')
    parser.add_argument('--config_file', type=str, required=True, help='')
    parser.add_argument(
        '--obs_time',
        type=str,
        required=True,
        help=
        'Observation time, should be given as a string, value and astropy unit separated by an empty space'
    )
    mode_group = parser.add_mutually_exclusive_group()
    mode_group.add_argument('--wave',
                            dest="mode",
                            action='store_const',
                            const="wave",
                            default="tail",
                            help="if set, use wavelet cleaning")
    mode_group.add_argument(
        '--tail',
        dest="mode",
        action='store_const',
        const="tail",
        help="if set, use tail cleaning, otherwise wavelets")
    args = parser.parse_args()

    # Read configuration file
    cfg = load_config(args.config_file)

    # Add obs. time in configuration file
    str_obs_time = args.obs_time.split()
    cfg['analysis']['obs_time'] = {
        'value': float(str_obs_time[0]),
        'unit': str(str_obs_time[-1])
    }

    # Create output directory if necessary
    outdir = os.path.join(
        cfg['general']['outdir'], 'irf_{}_ThSq_{}_Time{:.2f}{}'.format(
            args.mode, cfg['analysis']['thsq_opt']['type'],
            cfg['analysis']['obs_time']['value'],
            cfg['analysis']['obs_time']['unit']))
    if not os.path.exists(outdir):
        os.makedirs(outdir)

    indir = cfg['general']['indir']
    template_input_file = cfg['general']['template_input_file']

    # Load data
    particles = ['gamma', 'electron', 'proton']
    evt_dict = dict()  # Contain DL2 file for each type of particle
    for particle in particles:
        # template looks like dl2_{}_{}_merged.h5
        infile = os.path.join(indir,
                              template_input_file.format(args.mode, particle))
        evt_dict[particle] = pd.read_hdf(infile, key='reco_events')

    # Apply offset cut to proton and electron
    for particle in ['electron', 'proton']:
        # print('Initial stat: {} {}'.format(len(evt_dict[particle]), particle))
        evt_dict[particle] = evt_dict[particle].query('offset <= {}'.format(
            cfg['particle_information'][particle]['offset_cut']))

    # Add required data in configuration file for future computation
    for particle in particles:
        cfg['particle_information'][particle]['n_files'] = \
            len(np.unique(evt_dict[particle]['obs_id']))
        cfg['particle_information'][particle]['n_simulated'] = \
            cfg['particle_information'][particle]['n_files'] * cfg['particle_information'][particle]['n_events_per_file']

    # Define model for the particles
    model_dict = {
        'gamma': CrabSpectrum('hegra').model,
        'proton': cosmic_ray_flux,
        'electron': cosmic_ray_flux
    }

    # Reco energy binning
    cfg_binning = cfg['analysis']['ereco_binning']
    ereco = np.logspace(np.log10(cfg_binning['emin']),
                        np.log10(cfg_binning['emax']),
                        cfg_binning['nbin'] + 1) * u.TeV

    # Handle theta square cut optimisation
    # (compute 68 % containment radius PSF if necessary)
    thsq_opt_type = cfg['analysis']['thsq_opt']['type']
    if thsq_opt_type in 'fixed':
        thsq_values = np.array([cfg['analysis']['thsq_opt']['value']]) * u.deg
        print('Using fixed theta cut: {}'.format(thsq_values))
    elif thsq_opt_type in 'opti':
        thsq_values = np.arange(0.05, 0.40, 0.01) * u.deg
        print('Optimising theta cut for: {}'.format(thsq_values))
    elif thsq_opt_type in 'r68':
        print('Using R68% theta cut')
        print('Computing...')
        cfg_binning = cfg['analysis']['ereco_binning']
        ereco = np.logspace(np.log10(cfg_binning['emin']),
                            np.log10(cfg_binning['emax']),
                            cfg_binning['nbin'] + 1) * u.TeV
        radius = 68

        thsq_values = list()
        for ibin in range(len(ereco) - 1):
            emin = ereco[ibin]
            emax = ereco[ibin + 1]

            energy_query = 'reco_energy > {} and reco_energy <= {}'.format(
                emin.value, emax.value)
            data = evt_dict['gamma'].query(energy_query).copy()

            min_stat = 0
            if len(data) <= min_stat:
                print('  ==> Not enough statistics:')
                print('To be handled...')
                thsq_values.append(0.3)
                continue
                # import sys
                # sys.exit()

            psf = np.percentile(data['offset'], radius)
            psf_err = psf / np.sqrt(len(data))

            thsq_values.append(psf)
        thsq_values = np.array(thsq_values) * u.deg
        # Set 0.05 as a lower value
        idx = np.where(thsq_values.value < 0.05)
        thsq_values[idx] = 0.05 * u.deg
        print('Using theta cut: {}'.format(thsq_values))

    # Cuts optimisation
    print('### Finding best cuts...')
    cut_optimiser = CutsOptimisation(config=cfg,
                                     evt_dict=evt_dict,
                                     verbose_level=0)

    # Weight events
    print('- Weighting events...')
    cut_optimiser.weight_events(
        model_dict=model_dict,
        colname_mc_energy=cfg['column_definition']['mc_energy'])

    # Find best cutoff to reach best sensitivity
    print('- Estimating cutoffs...')
    cut_optimiser.find_best_cutoff(energy_values=ereco,
                                   angular_values=thsq_values)

    # Save results and auxiliary data for diagnostic
    print('- Saving results to disk...')
    cut_optimiser.write_results(outdir,
                                '{}.fits'.format(
                                    cfg['general']['output_table_name']),
                                format='fits')

    # Cuts diagnostic
    print('### Building cut diagnostics...')
    cut_diagnostic = CutsDiagnostic(config=cfg, indir=outdir)
    cut_diagnostic.plot_optimisation_summary()
    cut_diagnostic.plot_diagnostics()

    # Apply cuts and save data
    print('### Applying cuts to data...')
    cut_applicator = CutsApplicator(config=cfg,
                                    evt_dict=evt_dict,
                                    outdir=outdir)
    cut_applicator.apply_cuts()

    # Irf Maker
    print('### Building IRF...')
    irf_maker = IrfMaker(config=cfg, evt_dict=evt_dict, outdir=outdir)
    irf_maker.build_irf()

    # Sensitivity maker
    print('### Estimating sensitivity...')
    sensitivity_maker = SensitivityMaker(config=cfg, outdir=outdir)
    sensitivity_maker.load_irf()
    sensitivity_maker.estimate_sensitivity()
Beispiel #8
0
def main(args):
    paths = {}
    paths['gamma'] = args.dl2_gamma_filename
    paths['proton'] = args.dl2_proton_filename
    paths['electron'] = args.dl2_electron_filename

    # Read configuration file
    cfg = load_config(args.config_file)
    # cfg = configuration()

    cfg['analysis']['obs_time'] = {}
    cfg['analysis']['obs_time']['unit'] = u.h
    cfg['analysis']['obs_time']['value'] = args.obs_time

    cfg['general']['outdir'] = args.outdir

    # Create output directory if necessary
    outdir = os.path.join(
        cfg['general']['outdir'],
        'irf_ThSq_{}_Time{:.2f}{}'.format(cfg['analysis']['thsq_opt']['type'],
                                          cfg['analysis']['obs_time']['value'],
                                          cfg['analysis']['obs_time']['unit']))
    if not os.path.exists(outdir):
        os.makedirs(outdir)

    # Load data
    particles = ['gamma', 'electron', 'proton']
    evt_dict = dict()  # Contain DL2 file for each type of particle
    for particle in particles:
        infile = paths[particle]
        evt_dict[particle] = read_and_update_dl2(infile)
        cfg = get_simu_info(infile, particle, config=cfg)

    # Apply offset cut to proton and electron
    for particle in ['electron', 'proton']:
        evt_dict[particle] = evt_dict[particle].query('offset <= {}'.format(
            cfg['particle_information'][particle]['offset_cut']))

    # Add required data in configuration file for future computation
    for particle in particles:
        # cfg['particle_information'][particle]['n_files'] = \
        #     len(np.unique(evt_dict[particle]['obs_id']))
        cfg['particle_information'][particle]['n_simulated'] = \
            cfg['particle_information'][particle]['n_files'] * cfg['particle_information'][particle][
                'n_events_per_file']

    # Define model for the particles
    model_dict = {
        'gamma': CrabSpectrum('hegra').model,
        'proton': cosmic_ray_flux,
        'electron': cosmic_ray_flux
    }

    # Reco energy binning
    cfg_binning = cfg['analysis']['ereco_binning']
    # ereco = np.logspace(np.log10(cfg_binning['emin']),
    #                     np.log10(cfg_binning['emax']),
    #                     cfg_binning['nbin'] + 1) * u.TeV
    ereco = ctaplot.ana.irf_cta().E_bin * u.TeV

    # Handle theta square cut optimisation
    # (compute 68 % containment radius PSF if necessary)
    thsq_opt_type = cfg['analysis']['thsq_opt']['type']
    print(thsq_opt_type)
    # if thsq_opt_type in 'fixed':
    #     thsq_values = np.array([cfg['analysis']['thsq_opt']['value']]) * u.deg
    #     print('Using fixed theta cut: {}'.format(thsq_values))
    # elif thsq_opt_type in 'opti':
    #     thsq_values = np.arange(0.05, 0.40, 0.01) * u.deg
    #     print('Optimising theta cut for: {}'.format(thsq_values))
    if thsq_opt_type != 'r68':
        raise ValueError("only r68 supported at the moment")
    elif thsq_opt_type in 'r68':
        print('Using R68% theta cut')
        print('Computing...')
        cfg_binning = cfg['analysis']['ereco_binning']
        ereco = np.logspace(np.log10(cfg_binning['emin']),
                            np.log10(cfg_binning['emax']),
                            cfg_binning['nbin'] + 1) * u.TeV
        ereco = ctaplot.ana.irf_cta().E_bin * u.TeV
        radius = 68

        thsq_values = list()
        for ibin in range(len(ereco) - 1):
            emin = ereco[ibin]
            emax = ereco[ibin + 1]

            energy_query = 'reco_energy > {} and reco_energy <= {}'.format(
                emin.value, emax.value)
            data = evt_dict['gamma'].query(energy_query).copy()

            min_stat = 0
            if len(data) <= min_stat:
                print('  ==> Not enough statistics:')
                print('To be handled...')
                thsq_values.append(0.3)
                continue

            psf = np.percentile(data['offset'], radius)

            thsq_values.append(psf)
        thsq_values = np.array(thsq_values) * u.deg
        # Set 0.05 as a lower value
        idx = np.where(thsq_values.value < 0.05)
        thsq_values[idx] = 0.05 * u.deg
        print('Using theta cut: {}'.format(thsq_values))

    # Cuts optimisation
    print('### Finding best cuts...')
    cut_optimiser = CutsOptimisation(config=cfg,
                                     evt_dict=evt_dict,
                                     verbose_level=0)

    # Weight events
    print('- Weighting events...')
    cut_optimiser.weight_events(
        model_dict=model_dict,
        colname_mc_energy=cfg['column_definition']['mc_energy'])

    # Find best cutoff to reach best sensitivity
    print('- Estimating cutoffs...')
    cut_optimiser.find_best_cutoff(energy_values=ereco,
                                   angular_values=thsq_values)

    # Save results and auxiliary data for diagnostic
    print('- Saving results to disk...')
    cut_optimiser.write_results(outdir,
                                '{}.fits'.format(
                                    cfg['general']['output_table_name']),
                                format='fits')

    # Cuts diagnostic
    print('### Building cut diagnostics...')
    cut_diagnostic = CutsDiagnostic(config=cfg, indir=outdir)
    cut_diagnostic.plot_optimisation_summary()
    cut_diagnostic.plot_diagnostics()

    # Apply cuts and save data
    print('### Applying cuts to data...')
    cut_applicator = CutsApplicator(config=cfg,
                                    evt_dict=evt_dict,
                                    outdir=outdir)
    cut_applicator.apply_cuts()

    # Irf Maker
    print('### Building IRF...')
    irf_maker = IrfMaker(config=cfg, evt_dict=evt_dict, outdir=outdir)
    irf_maker.build_irf()

    # Sensitivity maker
    print('### Estimating sensitivity...')
    sensitivity_maker = SensitivityMaker(config=cfg, outdir=outdir)
    sensitivity_maker.load_irf()
    sensitivity_maker.estimate_sensitivity()
Beispiel #9
0
analysis.run(optimize_opts={"print_level": 1})

# ## Results
#
# Let's look at the results, and also compare with a previously published Crab nebula spectrum for reference.

# In[ ]:

print(analysis.fit.result[0])

# In[ ]:

opts = {
    "energy_range": analysis.fit.fit_range,
    "energy_power": 2,
    "flux_unit": "erg-1 cm-2 s-1",
}
axes = analysis.spectrum_result.plot(**opts)
CrabSpectrum().model.plot(ax=axes[0], **opts)

# ## Exercises
#
# Rerun the analysis, changing some aspects of the analysis as you like:
#
# * only use one or two observations
# * a different spectral model
# * different config options for the spectral analysis
# * different energy binning for the spectral point computation
#
# Observe how the measured spectrum changes.
Beispiel #10
0
def plot_fit_results(tool):
    """plot the SEDs result of the gammapy / sherpa fit
    for comparison with the literature we choose only the Mayer spectrum

    Here we plot the butterfly as a result of the multivariate sampling
    with the 68% containment in flux
    """
    fig, ax = plt.subplots()

    model_meyer_ref = CrabSpectrum("meyer").model
    model_meyer_ref.plot(
        [10 * u.GeV, 100 * u.TeV],
        energy_power=2,
        flux_unit="erg-1 cm-2 s-1",
        ls=":",
        lw=2.2,
        color="#555555",
        label="Meyer et al. (2010)",
    )

    # where to take the results, configurations for the individual butterflies
    instruments = ["fermi", "magic", "veritas", "fact", "hess", "joint"]
    labels = ["Fermi-LAT", "MAGIC", "VERITAS", "FACT", "H.E.S.S.", "joint fit"]
    lss = ["--", "--", "--", "--", "--", "-"]
    colors = COLORS
    # with one loop we realize all the butterfly plots
    for instrument, label, color, ls in zip(instruments, labels, colors, lss):

        path = (
            config.repo_path /
            f"results/fit/{tool}/{instrument}/fit_results_logparabola.yaml")

        if not path.exists():
            log.warning(f"Missing: {path} . Skipping.")
            continue

        results = load_yaml(path)
        parameters = results["parameters"]

        model_lp = LogParabola.from_log10(
            amplitude=parameters[0]["value"] * u.Unit(parameters[0]["unit"]),
            reference=parameters[1]["value"] * u.Unit(parameters[1]["unit"]),
            alpha=parameters[2]["value"] * u.Unit(parameters[2]["unit"]),
            beta=parameters[3]["value"] * u.Unit(parameters[3]["unit"]),
        )

        # energy range for the plot
        dataset = config.get_dataset(instrument)
        energy_range = dataset.energy_range

        # just in case of the joint fit put a thicker line and a less transparent butterfly
        if instrument == "joint":
            model_lp.plot(
                energy_range,
                energy_power=2,
                flux_unit="erg-1 cm-2 s-1",
                ls=ls,
                lw=3,
                color=color,
                label=label,
            )
        else:
            model_lp.plot(
                energy_range,
                energy_power=2,
                flux_unit="erg-1 cm-2 s-1",
                ls=ls,
                lw=2.2,
                color=color,
                label=label,
            )

        # read the butterfly from the multivariate sampling results
        table_path = Path(
            f"{config.repo_path}/results/figures/stat_err/{instrument}_flux_errorband.dat"
        )
        log.info(f"reading butterfly values from {table_path}")
        t = Table.read(table_path, format="ascii.ecsv")
        energies = t["energies"].data * t["energies"].unit
        flux_lo = t["flux_lo"].data * t["flux_lo"].unit
        flux_hi = t["flux_hi"].data * t["flux_hi"].unit

        if instrument == "joint":
            alpha = 0.38
        else:
            alpha = 0.28

        plt.fill_between(
            energies.to("TeV"),
            (energies**2 * flux_lo).to("erg cm-2 s-1"),
            (energies**2 * flux_hi).to("erg cm-2 s-1"),
            color=color,
            alpha=alpha,
            label="",
        )

    ax.legend(fontsize=FONTSIZE)
    ax.set_ylim([1e-12, 2e-10])

    ax.set_xlabel(E_UNIT_LABEL, size=FONTSIZE)
    ax.set_ylabel(SED_UNIT_LABEL, size=FONTSIZE)
    # make axis thicker
    for axis in ["top", "bottom", "left", "right"]:
        ax.spines[axis].set_linewidth(1.6)
    ax.tick_params("both",
                   length=7,
                   width=1.6,
                   which="major",
                   labelsize=FONTSIZE)
    ax.tick_params("both",
                   length=4,
                   width=1.6,
                   which="minor",
                   labelsize=FONTSIZE)

    plt.tight_layout()

    filename = f"results/figures/crab_sed_{tool}_fit.png"
    filename_pdf = f"results/figures/crab_sed_{tool}_fit.pdf"
    log.info(f"Writing {filename}")
    fig.savefig(filename)
    fig.savefig(filename_pdf)
Beispiel #11
0
print(lc.table.colnames)

# In[ ]:

lc.table["time_min", "time_max", "flux", "flux_err"]

# In[ ]:

lc.plot()

# In[ ]:

# Let's compare to the expected flux of this source
from gammapy.spectrum import CrabSpectrum

crab_spec = CrabSpectrum().model
crab_flux = crab_spec.integral(*energy_range).to("cm-2 s-1")
crab_flux

# In[ ]:

ax = lc.plot(marker="o", lw=2)
ax.hlines(
    crab_flux.value,
    xmin=lc.table["time_min"].min(),
    xmax=lc.table["time_max"].max(),
)

# ## Exercises
#
# * Change the assumed spectral model shape (e.g. to a steeper power-law), and see how the integral flux estimate for the lightcurve changes.
Beispiel #12
0
def main():

    # =========================================================================
    #                   READ INPUT FROM CLI AND CONFIGURATION FILE
    # =========================================================================

    # INPUT FROM CLI

    parser = argparse.ArgumentParser(description="Produce DL3 data from DL2.")

    parser.add_argument(
        "--config_file",
        type=str,
        required=True,
        help="A configuration file like pyirf/resources/performance.yaml .",
    )

    parser.add_argument(
        "--obs_time",
        type=str,
        required=True,
        help=
        "An observation time given as a string in astropy format e.g. '50h' or '30min'",
    )

    parser.add_argument(
        "--pipeline",
        type=str,
        required=True,
        help="Name of the pipeline that has produced the DL2 files.",
    )

    parser.add_argument("--debug",
                        action="store_true",
                        help="Print debugging information.")

    args = parser.parse_args()

    # INPUT FROM THE CONFIGURATION FILE

    cfg = load_config(args.config_file)

    # Add obs. time to the configuration file
    obs_time = u.Quantity(args.obs_time)
    cfg["analysis"]["obs_time"] = {
        "value": obs_time.value,
        "unit": obs_time.unit.to_string("fits"),
    }

    # Get input directory
    indir = cfg["general"]["indir"]

    # Get template of the input file(s)
    template_input_file = cfg["general"]["template_input_file"]

    # Get output directory
    outdir = os.path.join(
        cfg["general"]["outdir"],
        "irf_{}_Time{}{}".format(
            args.pipeline,
            cfg["analysis"]["obs_time"]["value"],
            cfg["analysis"]["obs_time"]["unit"],
        ),
    )  # and create it if necessary
    os.makedirs(outdir, exist_ok=True)

    # =========================================================================
    #                   READ DL2 DATA AND STORE IT ACCORDING TO GADF
    # =========================================================================

    # Load FITS data
    particles = ["gamma", "electron", "proton"]
    evt_dict = dict()  # Contain DL2 file for each type of particle
    for particle in particles:
        if args.debug:
            print(f"Loading {particle} DL2 data...")
        infile = os.path.join(indir, template_input_file.format(particle))
        evt_dict[particle] = read_FITS(config=cfg,
                                       infile=infile,
                                       pipeline=args.pipeline,
                                       debug=args.debug)

    # =========================================================================
    #               PRELIMINARY OPERATIONS FOR SPECIFIC PIPELINES
    # =========================================================================

    # Some pipelines could provide some of the DL2 data in different ways
    # After this part, DL2 data is supposed to be equivalent, regardless
    # of the original pipeline.

    # Later we should move this out of here, perhaps under a "utils" module.

    if args.pipeline == "EventDisplay":

        # EventDisplay provides true and reconstructed directions, so we
        # calculate THETA here and we add it to the tables.

        for particle in particles:

            THETA = angular_separation(
                evt_dict[particle]["TRUE_AZ"],
                evt_dict[particle]["TRUE_ALT"],
                evt_dict[particle]["AZ"],
                evt_dict[particle]["ALT"],
            )  # in degrees

            # Add THETA column
            evt_dict[particle]["THETA"] = THETA

    # =========================================================================
    #                   REST OF THE OPERATIONS (TO BE REFACTORED)
    # =========================================================================

    # Apply offset cut to proton and electron
    for particle in ["electron", "proton"]:

        # There seems to be a problem in using pandas from FITS data
        # ValueError: Big-endian buffer not supported on little-endian compiler
        # I convert to astropy table....
        # should we use only those?

        evt_dict[particle] = Table.from_pandas(evt_dict[particle])

        if args.debug:
            print(particle)
            # print(evt_dict[particle].head(n=5))
            print(evt_dict[particle])

        # print('Initial stat: {} {}'.format(len(evt_dict[particle]), particle))

        mask_theta = (evt_dict[particle]["THETA"] <
                      cfg["particle_information"][particle]["offset_cut"])
        evt_dict[particle] = evt_dict[particle][mask_theta]
        # PANDAS EQUIVALENT
        # evt_dict[particle] = evt_dict[particle].query(
        #     "THETA <= {}".format(cfg["particle_information"][particle]["offset_cut"])
        # )

    # Add required data in configuration file for future computation
    for particle in particles:
        n_files = cfg["particle_information"][particle]["n_files"]
        print(f"{n_files} files for {particle}")
        cfg["particle_information"][particle]["n_files"] = len(
            np.unique(evt_dict[particle]["OBS_ID"]))
        cfg["particle_information"][particle]["n_simulated"] = (
            cfg["particle_information"][particle]["n_files"] *
            cfg["particle_information"][particle]["n_events_per_file"])

    # Define model for the particles
    model_dict = {
        "gamma": CrabSpectrum("hegra").model,
        "proton": cosmic_ray_flux,
        "electron": cosmic_ray_flux,
    }

    # Reco energy binning
    cfg_binning = cfg["analysis"]["ereco_binning"]
    ereco = (np.logspace(
        np.log10(cfg_binning["emin"]),
        np.log10(cfg_binning["emax"]),
        cfg_binning["nbin"] + 1,
    ) * u.TeV)

    # Handle theta square cut optimisation
    # (compute 68 % containment radius PSF if necessary)
    thsq_opt_type = cfg["analysis"]["thsq_opt"]["type"]
    if thsq_opt_type == "fixed":
        thsq_values = np.array([cfg["analysis"]["thsq_opt"]["value"]]) * u.deg
        print("Using fixed theta cut: {}".format(thsq_values))
    elif thsq_opt_type == "opti":
        thsq_values = np.arange(0.05, 0.40, 0.01) * u.deg
        print("Optimising theta cut for: {}".format(thsq_values))
    elif thsq_opt_type == "r68":
        print("Using R68% theta cut")
        print("Computing...")
        cfg_binning = cfg["analysis"]["ereco_binning"]
        ereco = (np.logspace(
            np.log10(cfg_binning["emin"]),
            np.log10(cfg_binning["emax"]),
            cfg_binning["nbin"] + 1,
        ) * u.TeV)
        radius = 68

        thsq_values = list()

        # There seems to be a problem in using pandas from FITS data
        # ValueError: Big-endian buffer not supported on little-endian compiler

        # I convert to astropy table....
        # should we use only those?

        evt_dict["gamma"] = Table.from_pandas(evt_dict["gamma"])
        if args.debug:
            print("GAMMAS")
            # print(evt_dict["gamma"].head(n=5))
            print(evt_dict["gamma"])

        for ibin in range(len(ereco) - 1):
            emin = ereco[ibin]
            emax = ereco[ibin + 1]

            # PANDAS EQUIVALENT
            # energy_query = "reco_energy > {} and reco_energy <= {}".format(
            #     emin.value, emax.value
            # )
            # data = evt_dict["gamma"].query(energy_query).copy()

            mask_energy = (evt_dict["gamma"]["ENERGY"] > emin.value) & (
                evt_dict["gamma"]["ENERGY"] < emax.value)
            data = evt_dict["gamma"][mask_energy]

            min_stat = 0
            if len(data) <= min_stat:
                print("  ==> Not enough statistics:")
                print("To be handled...")
                thsq_values.append(0.3)
                continue
                # import sys
                # sys.exit()

            psf = np.percentile(data["THETA"], radius)
            # psf_err = psf / np.sqrt(len(data)) # not used after?

            thsq_values.append(psf)
        thsq_values = np.array(thsq_values) * u.deg
        # Set 0.05 as a lower value
        idx = np.where(thsq_values.value < 0.05)
        thsq_values[idx] = 0.05 * u.deg
        print("Using theta cut: {}".format(thsq_values))

    # Cuts optimisation
    print("### Finding best cuts...")
    cut_optimiser = CutsOptimisation(config=cfg,
                                     evt_dict=evt_dict,
                                     verbose_level=0)

    # Weight events
    print("- Weighting events...")
    cut_optimiser.weight_events(
        model_dict=model_dict,
        # colname_mc_energy=cfg["column_definition"]["TRUE_ENERGY"],
        colname_mc_energy="TRUE_ENERGY",
    )

    # Find best cutoff to reach best sensitivity
    print("- Estimating cutoffs...")
    cut_optimiser.find_best_cutoff(energy_values=ereco,
                                   angular_values=thsq_values)

    # Save results and auxiliary data for diagnostic
    print("- Saving results to disk...")
    cut_optimiser.write_results(outdir,
                                "{}.fits".format(
                                    cfg["general"]["output_table_name"]),
                                format="fits")

    # Cuts diagnostic
    print("### Building cut diagnostics...")
    cut_diagnostic = CutsDiagnostic(config=cfg, indir=outdir)
    cut_diagnostic.plot_optimisation_summary()
    cut_diagnostic.plot_diagnostics()

    # Apply cuts and save data
    print("### Applying cuts to data...")
    cut_applicator = CutsApplicator(config=cfg,
                                    evt_dict=evt_dict,
                                    outdir=outdir)
    cut_applicator.apply_cuts(args.debug)

    # Irf Maker
    print("### Building IRF...")
    irf_maker = IrfMaker(config=cfg, evt_dict=evt_dict, outdir=outdir)
    irf_maker.build_irf(thsq_values)

    # Sensitivity maker
    print("### Estimating sensitivity...")
    sensitivity_maker = SensitivityMaker(config=cfg, outdir=outdir)
    sensitivity_maker.load_irf()
    sensitivity_maker.estimate_sensitivity()
Beispiel #13
0
from gammapy.datasets import load_crab_flux_points
from gammapy.spectrum import CrabSpectrum

# Plot flux points
for component in ['pulsar', 'nebula']:
    table = load_crab_flux_points(component=component)
    x = table['energy'].data
    y = table['energy_flux'].data
    yerr_lo = table['energy_flux_err_lo'].data
    yerr_hi = table['energy_flux_err_hi'].data
    plt.errorbar(x, y, yerr=(yerr_lo, yerr_hi), fmt='o', label=component)

# Plot SED model
energy = np.logspace(2, 8, 100) * u.MeV

crab = CrabSpectrum(reference='meyer')

flux = crab.model(energy)
energy_flux = (energy ** 2 * flux).to('erg cm^-2 s^-1')
plt.plot(energy.value, energy_flux.value, label='Meyer (2010) model', lw=3)

plt.title('Crab pulsar and nebula spectral energy distribution (SED)')
plt.xlim((3e-14, 3e8))
plt.ylim((3e-13, 3e-7))
plt.xlabel('Energy (MeV)')
plt.ylabel('E^2 dN/dE (erg cm^-2 s^-1)')
plt.legend(loc='upper center', ncol=3)
plt.grid()
plt.loglog()
plt.savefig('crab_mwl.png')
Beispiel #14
0
import numpy as np
import click
import matplotlib.pyplot as plt
import os
from gammapy.spectrum import CrabSpectrum
import astropy.units as u


def model(amplitude, alpha, beta):
    amplitude *= 1E-11
    return lambda xx: amplitude * np.power(xx, (-alpha - beta * np.log10(xx)))


magic_model = CrabSpectrum('magic_lp').model
meyer_model = CrabSpectrum('meyer').model

fact_model = model(3.49, 2.54, 0.42)
magic_joint_model = model(4.15, 2.6, 0.44)
hess_joint_model = model(4.47, 2.39, 0.37)


@click.command()
@click.argument('input_dir', type=click.Path(dir_okay=True, file_okay=False))
@click.option('--output',
              '-o',
              type=click.Path(dir_okay=False, file_okay=True))
@click.option('--color', default='crimson')
def main(input_dir, output, color):

    alphas = []
    betas = []
def main():
    # Read arguments
    parser = argparse.ArgumentParser(description="Make performance files")
    parser.add_argument("--config_file", type=str, required=True, help="")
    parser.add_argument(
        "--obs_time",
        type=str,
        required=True,
        help="Observation time, should be given as a string, value and astropy unit separated by an empty space",
    )
    mode_group = parser.add_mutually_exclusive_group()
    mode_group.add_argument(
        "--wave",
        dest="mode",
        action="store_const",
        const="wave",
        default="tail",
        help="if set, use wavelet cleaning",
    )
    mode_group.add_argument(
        "--tail",
        dest="mode",
        action="store_const",
        const="tail",
        help="if set, use tail cleaning, otherwise wavelets",
    )
    args = parser.parse_args()

    # Read configuration file
    cfg = load_config(args.config_file)

    # Add obs. time in configuration file
    str_obs_time = args.obs_time.split()
    cfg["analysis"]["obs_time"] = {
        "value": float(str_obs_time[0]),
        "unit": str(str_obs_time[-1]),
    }

    # Create output directory if necessary
    outdir = os.path.join(
        cfg["general"]["outdir"],
        "irf_{}_ThSq_{}_Time{:.2f}{}".format(
            args.mode,
            cfg["analysis"]["thsq_opt"]["type"],
            cfg["analysis"]["obs_time"]["value"],
            cfg["analysis"]["obs_time"]["unit"],
        ),
    )
    if not os.path.exists(outdir):
        os.makedirs(outdir)

    indir = cfg["general"]["indir"]
    template_input_file = cfg["general"]["template_input_file"]

    # Load data
    particles = ["gamma", "electron", "proton"]
    evt_dict = dict()  # Contain DL2 file for each type of particle
    for particle in particles:
        # template looks like dl2_{}_{}_merged.h5
        infile = os.path.join(indir, template_input_file.format(args.mode, particle))
        evt_dict[particle] = pd.read_hdf(infile, key="reco_events")

    # Apply offset cut to proton and electron
    for particle in ["electron", "proton"]:
        # print('Initial stat: {} {}'.format(len(evt_dict[particle]), particle))
        evt_dict[particle] = evt_dict[particle].query('offset <= {}'.format(
            cfg['analysis']['max_bg_radius'])
        )

    # Add required data in configuration file for future computation
    for particle in particles:
        cfg['particle_information'][particle]['n_files'] = \
            len(np.unique(evt_dict[particle]['obs_id']))
        cfg['particle_information'][particle]['n_simulated'] = \
            cfg['particle_information'][particle]['n_files'] * cfg['particle_information'][particle]['num_showers'] * cfg['particle_information'][particle]['num_use']

    # Define model for the particles
    model_dict = {
        "gamma": CrabSpectrum("hegra").model,
        "proton": cosmic_ray_flux,
        "electron": cosmic_ray_flux,
    }

    # Reco energy binning
    cfg_binning = cfg["analysis"]["ereco_binning"]
    ereco = (
        np.logspace(
            np.log10(cfg_binning["emin"]),
            np.log10(cfg_binning["emax"]),
            cfg_binning["nbin"] + 1,
        )
        * u.TeV
    )

    # Handle theta square cut optimisation
    # (compute 68 % containment radius PSF if necessary)
    thsq_opt_type = cfg["analysis"]["thsq_opt"]["type"]
    if thsq_opt_type in "fixed":
        thsq_values = np.array([cfg["analysis"]["thsq_opt"]["value"]]) * u.deg
        print("Using fixed theta cut: {}".format(thsq_values))
    elif thsq_opt_type in "opti":
        thsq_values = np.arange(0.05, 0.40, 0.01) * u.deg
        print("Optimising theta cut for: {}".format(thsq_values))
    elif thsq_opt_type in "r68":
        print("Using R68% theta cut")
        print("Computing...")
        cfg_binning = cfg["analysis"]["ereco_binning"]
        ereco = (
            np.logspace(
                np.log10(cfg_binning["emin"]),
                np.log10(cfg_binning["emax"]),
                cfg_binning["nbin"] + 1,
            )
            * u.TeV
        )
        radius = 68

        thsq_values = list()
        for ibin in range(len(ereco) - 1):
            emin = ereco[ibin]
            emax = ereco[ibin + 1]

            energy_query = "reco_energy > {} and reco_energy <= {}".format(
                emin.value, emax.value
            )
            data = evt_dict["gamma"].query(energy_query).copy()

            min_stat = 0
            if len(data) <= min_stat:
                print("  ==> Not enough statistics:")
                print("To be handled...")
                thsq_values.append(0.3)
                continue
                # import sys
                # sys.exit()

            psf = np.percentile(data["offset"], radius)
            psf_err = psf / np.sqrt(len(data))

            thsq_values.append(psf)
        thsq_values = np.array(thsq_values) * u.deg
        # Set 0.05 as a lower value
        idx = np.where(thsq_values.value < 0.05)
        thsq_values[idx] = 0.05 * u.deg
        print("Using theta cut: {}".format(thsq_values))

    # Cuts optimisation
    print("### Finding best cuts...")
    cut_optimiser = CutsOptimisation(config=cfg, evt_dict=evt_dict, verbose_level=0)

    # Weight events
    print("- Weighting events...")
    cut_optimiser.weight_events(
        model_dict=model_dict, colname_mc_energy=cfg["column_definition"]["mc_energy"]
    )

    # Find best cutoff to reach best sensitivity
    print("- Estimating cutoffs...")
    cut_optimiser.find_best_cutoff(energy_values=ereco, angular_values=thsq_values)

    # Save results and auxiliary data for diagnostic
    print("- Saving results to disk...")
    cut_optimiser.write_results(
        outdir, "{}.fits".format(cfg["general"]["output_table_name"]), format="fits"
    )

    # Cuts diagnostic
    print("### Building cut diagnostics...")
    cut_diagnostic = CutsDiagnostic(config=cfg, indir=outdir)
    cut_diagnostic.plot_optimisation_summary()
    cut_diagnostic.plot_diagnostics()

    # Apply cuts and save data
    print("### Applying cuts to data...")
    cut_applicator = CutsApplicator(config=cfg, evt_dict=evt_dict, outdir=outdir)
    cut_applicator.apply_cuts()

    # Irf Maker
    print("### Building IRF...")
    irf_maker = IrfMaker(config=cfg, evt_dict=evt_dict, outdir=outdir)
    irf_maker.build_irf()

    # Sensitivity maker
    print("### Estimating sensitivity...")
    sensitivity_maker = SensitivityMaker(config=cfg, outdir=outdir)
    sensitivity_maker.load_irf()
    sensitivity_maker.estimate_sensitivity()
Beispiel #16
0
def plot_spectra(sampler,
                 mle_result,
                 fit_range=[0.03, 30] * u.TeV,
                 min_sample=50):
    joint_model = Log10Parabola(
        amplitude=3.78 * 1e-11 * u.Unit('cm-2 s-1 TeV-1'),
        reference=1 * u.Unit('TeV'),
        alpha=2.49 * u.Unit(''),
        beta=0.22 * u.Unit(''),
    )
    joint_model.plot(energy_range=fit_range,
                     energy_power=2,
                     color='black',
                     label='joint')

    r = np.median(sampler.chain[:, min_sample:, :3], axis=(0, 1))
    fitted_model = Log10Parabola(
        amplitude=r[0] * 1e-11 * u.Unit('cm-2 s-1 TeV-1'),
        reference=1 * u.Unit('TeV'),
        alpha=r[1] * u.Unit(''),
        beta=r[2] * u.Unit(''),
    )
    fitted_model.plot(energy_range=fit_range,
                      energy_power=2,
                      color='crimson',
                      label='mcmc')

    mle_model = Log10Parabola(
        amplitude=mle_result.x[0] * 1e-11 * u.Unit('cm-2 s-1 TeV-1'),
        reference=1 * u.Unit('TeV'),
        alpha=mle_result.x[1] * u.Unit(''),
        beta=mle_result.x[2] * u.Unit(''),
    )
    mle_model.plot(energy_range=fit_range,
                   energy_power=2,
                   color='orange',
                   ls='--',
                   label='mle')

    fact_model = Log10Parabola(
        amplitude=3.47 * 1e-11 * u.Unit('cm-2 s-1 TeV-1'),
        reference=1 * u.Unit('TeV'),
        alpha=2.56 * u.Unit(''),
        beta=0.4 * u.Unit(''),
    )
    fact_model.plot(energy_range=fit_range,
                    energy_power=2,
                    color='gray',
                    label='fact')

    magic_model = Log10Parabola(
        amplitude=4.20 * 1e-11 * u.Unit('cm-2 s-1 TeV-1'),
        reference=1 * u.Unit('TeV'),
        alpha=2.58 * u.Unit(''),
        beta=0.43 * u.Unit(''),
    )
    magic_model.plot(energy_range=fit_range,
                     energy_power=2,
                     color='gray',
                     ls='--',
                     label='magic')

    CrabSpectrum(reference='meyer').model.plot(energy_range=[0.01, 100] *
                                               u.TeV,
                                               energy_power=2,
                                               color='black',
                                               ls=':')