Exemplo n.º 1
0
def test_model(model):
    print(model)
    print(model(energy=Q(10, 'TeV')))
    print(model.integral(emin=Q(1, 'TeV'), emax=Q(2, 'TeV')))

    # plot
    # butterfly
    # npred
    reco_bins = 5
    true_bins = 10
    e_reco = Q(np.logspace(-1, 1, reco_bins + 1), 'TeV')
    e_true = Q(np.logspace(-1.5, 1.5, true_bins + 1), 'TeV')
    livetime = Q(26, 'min')
    aeff_data = Q(np.ones(true_bins) * 1e5, 'cm2')
    aeff = EffectiveAreaTable(energy=e_true, data=aeff_data)
    edisp_data = make_perfect_resolution(e_true, e_reco)
    edisp = EnergyDispersion(edisp_data, EnergyBounds(e_true),
                             EnergyBounds(e_reco))
    npred = calculate_predicted_counts(model=model,
                                       livetime=livetime,
                                       aeff=aeff,
                                       edisp=edisp)
    print(npred.data)
def cta_perf_root_to_fits(root_filename, fits_filename):
    """
    Convert CTA performance file from ROOT to FITS format.

    Parameters
    ----------
    root_filename : str
        Input ROOT filename
    fits_filename : str
        Output FITS filename
    """
    from ROOT import TFile

    print('Reading {}'.format(root_filename))
    root_file = TFile(root_filename)

    # Bg rate
    bg_rate = hist1d_to_table(hist=root_file.Get('BGRate'))
    # ENERG_LO
    bg_rate.rename_column('x_bin_lo', 'ENERG_LO')
    bg_rate['ENERG_LO'].unit = u.TeV
    bg_rate['ENERG_LO'].format = 'E'
    bg_rate.replace_column('ENERG_LO', 10 ** (bg_rate['ENERG_LO']))
    # ENERG_HI
    bg_rate.rename_column('x_bin_hi', 'ENERG_HI')
    bg_rate['ENERG_HI'].unit = u.TeV
    bg_rate['ENERG_HI'].format = 'E'
    bg_rate.replace_column('ENERG_HI', 10 ** (bg_rate['ENERG_HI']))
    # BGD
    bg_rate.rename_column('y', 'BGD')
    bg_rate['BGD'].unit = u.Hz
    bg_rate['BGD'].format = 'E'

    bg_rate_hdu = fits.BinTableHDU.from_columns([
        fits.Column('ENERG_LO',
                    bg_rate['ENERG_LO'].format,
                    unit=bg_rate['ENERG_LO'].unit.to_string(),
                    array=bg_rate['ENERG_LO']),
        fits.Column('ENERG_HI',
                    bg_rate['ENERG_HI'].format,
                    unit=bg_rate['ENERG_HI'].unit.to_string(),
                    array=bg_rate['ENERG_HI']),
        fits.Column('BGD',
                    bg_rate['BGD'].format,
                    unit=bg_rate['BGD'].unit.to_string(),
                    array=bg_rate['BGD']),
    ])

    bg_rate_hdu.header.set("EXTNAME", "BACKGROUND")

    # EffectiveAreaEtrue
    area = hist1d_to_table(hist=root_file.Get('EffectiveAreaEtrue'))
    # ENERG_LO
    area.rename_column('x_bin_lo', 'ENERG_LO')
    area['ENERG_LO'].unit = u.TeV
    area['ENERG_LO'].format = 'E'
    area.replace_column('ENERG_LO', 10 ** (area['ENERG_LO']))
    # ENERG_HI
    area.rename_column('x_bin_hi', 'ENERG_HI')
    area['ENERG_HI'].unit = u.TeV
    area['ENERG_HI'].format = 'E'
    area.replace_column('ENERG_HI', 10 ** (area['ENERG_HI']))
    # EFFAREA
    area.rename_column('y', 'SPECRESP')
    area['SPECRESP'].unit = u.meter * u.meter
    area['SPECRESP'].format = 'E'
    area.replace_column('SPECRESP', area['SPECRESP'])

    area_hdu = fits.BinTableHDU.from_columns([
        fits.Column('ENERG_LO',
                    area['ENERG_LO'].format,
                    unit=area['ENERG_LO'].unit.to_string(),
                    array=area['ENERG_LO']),
        fits.Column('ENERG_HI',
                    area['ENERG_HI'].format,
                    unit=area['ENERG_HI'].unit.to_string(),
                    array=area['ENERG_HI']),
        fits.Column('SPECRESP',
                    area['SPECRESP'].format,
                    unit=area['SPECRESP'].unit.to_string(),
                    array=area['SPECRESP']),
    ])

    area_hdu.header.set("EXTNAME", "SPECRESP")

    # PSF
    psf = hist1d_to_table(hist=root_file.Get('AngRes'))
    # ENERG_LO
    psf.rename_column('x_bin_lo', 'ENERG_LO')
    psf['ENERG_LO'].unit = u.TeV
    psf['ENERG_LO'].format = 'E'
    psf.replace_column('ENERG_LO', 10 ** (psf['ENERG_LO']))
    # ENERG_HI
    psf.rename_column('x_bin_hi', 'ENERG_HI')
    psf['ENERG_HI'].unit = u.TeV
    psf['ENERG_HI'].format = 'E'
    psf.replace_column('ENERG_HI', 10 ** (psf['ENERG_HI']))
    # PSF68
    psf.rename_column('y', 'PSF68')
    psf['PSF68'].unit = u.degree
    psf['PSF68'].format = 'E'
    psf.replace_column('PSF68', psf['PSF68'])

    psf_hdu = fits.BinTableHDU.from_columns([
        fits.Column('ENERG_LO',
                    psf['ENERG_LO'].format,
                    unit=psf['ENERG_LO'].unit.to_string(),
                    array=psf['ENERG_LO']),
        fits.Column('ENERG_HI',
                    psf['ENERG_HI'].format,
                    unit=psf['ENERG_HI'].unit.to_string(),
                    array=psf['ENERG_HI']),
        fits.Column('PSF68',
                    psf['PSF68'].format,
                    unit=psf['PSF68'].unit.to_string(),
                    array=psf['PSF68']),
    ])

    psf_hdu.header.set("EXTNAME", "POINT SPREAD FUNCTION")

    # MigMatrix (x=e_reco, y=e_true, z=prob)
    histo_edisp = root_file.Get('MigMatrix')
    # data
    data = TH2_to_FITS_data(hist=histo_edisp, flipx=False)
    # get e_reco
    x_axis = histo_edisp.GetXaxis()
    x_nbins = x_axis.GetNbins()
    x_min = 10 ** (x_axis.GetBinLowEdge(1))
    x_max = 10 ** (x_axis.GetBinUpEdge(x_nbins))
    e_reco = BinnedDataAxis.logspace(x_min, x_max, x_nbins, unit=u.TeV)
    # get e_true
    y_axis = histo_edisp.GetYaxis()
    y_nbins = y_axis.GetNbins()
    y_min = 10 ** (y_axis.GetBinLowEdge(1))
    y_max = 10 ** (y_axis.GetBinUpEdge(y_nbins))
    e_true = BinnedDataAxis.logspace(y_min, y_max, y_nbins, unit=u.TeV)
    e_disp = EnergyDispersion(data=data, e_true=e_true, e_reco=e_reco)

    edisp_hdus = e_disp.to_hdulist()

    # Sensitivity
    sens = hist1d_to_table(hist=root_file.Get('DiffSens'))
    # ENERG_LO
    sens.rename_column('x_bin_lo', 'ENERG_LO')
    sens['ENERG_LO'].unit = u.TeV
    sens['ENERG_LO'].format = 'E'
    sens.replace_column('ENERG_LO', 10 ** (sens['ENERG_LO']))
    # ENERG_HI
    sens.rename_column('x_bin_hi', 'ENERG_HI')
    sens['ENERG_HI'].unit = u.TeV
    sens['ENERG_HI'].format = 'E'
    sens.replace_column('ENERG_HI', 10 ** (sens['ENERG_HI']))
    # BGD
    sens.rename_column('y', 'SENSITIVITY')
    sens['SENSITIVITY'].unit = u.erg / (u.cm * u.cm * u.s)
    sens['SENSITIVITY'].format = 'E'

    sens_hdu = fits.BinTableHDU.from_columns([
        fits.Column('ENERG_LO',
                    sens['ENERG_LO'].format,
                    unit=sens['ENERG_LO'].unit.to_string(),
                    array=sens['ENERG_LO']),
        fits.Column('ENERG_HI',
                    sens['ENERG_HI'].format,
                    unit=sens['ENERG_HI'].unit.to_string(),
                    array=sens['ENERG_HI']),
        fits.Column('SENSITIVITY',
                    sens['SENSITIVITY'].format,
                    unit=sens['SENSITIVITY'].unit.to_string(),
                    array=sens['SENSITIVITY']),
    ])

    sens_hdu.header.set("EXTNAME", "SENSITIVITY")

    hdulist = fits.HDUList([
        edisp_hdus[0], area_hdu, psf_hdu,
        edisp_hdus[1], edisp_hdus[2],
        bg_rate_hdu, sens_hdu,
    ])

    print('Writing {}'.format(fits_filename))
    hdulist.writeto(fits_filename, overwrite=True)
Exemplo n.º 3
0
    def get_energy_dispersion(self, position, e_reco, migra_step=5e-3):
        """Get energy dispersion at a given position.

        Parameters
        ----------
        position : `~astropy.coordinates.SkyCoord`
            the target position. Should be a single coordinates
        e_reco : `~astropy.units.Quantity`
            Reconstructed energy axis binning
        migra_step : float
            Integration step in migration

        Returns
        -------
        edisp : `~gammapy.irf.EnergyDispersion`
            the energy dispersion (i.e. rmf object)
        """
        # TODO: reduce code duplication with EnergyDispersion2D.get_response
        if position.size != 1:
            raise ValueError(
                "EnergyDispersion can be extracted at one single position only."
            )

        # axes ordering fixed. Could be changed.
        pix_ener = np.arange(self.edisp_map.geom.axes[1].nbin)

        # Define a vector of migration with mig_step step
        mrec_min = self.edisp_map.geom.axes[0].edges[0]
        mrec_max = self.edisp_map.geom.axes[0].edges[-1]
        mig_array = np.arange(mrec_min, mrec_max, migra_step)
        pix_migra = (mig_array -
                     mrec_min) / mrec_max * self.edisp_map.geom.axes[0].nbin

        # Convert position to pixels
        pix_lon, pix_lat = self.edisp_map.geom.to_image().coord_to_pix(
            position)

        # Build the pixels tuple
        pix = np.meshgrid(pix_lon, pix_lat, pix_migra, pix_ener)
        # Interpolate in the EDisp map. Squeeze to remove dimensions of length 1
        edisp_values = np.squeeze(
            self.edisp_map.interp_by_pix(pix) *
            u.Unit(self.edisp_map.unit)  # * migra_step
        )
        e_trues = self.edisp_map.geom.axes[1].center
        data = []

        for i, e_true in enumerate(e_trues):
            # We now perform integration over migra
            # The code is adapted from `~gammapy.EnergyDispersion2D.get_response`

            # migration value of e_reco bounds
            migra_e_reco = e_reco / e_true

            # Compute normalized cumulative sum to prepare integration
            tmp = np.nan_to_num(
                np.cumsum(edisp_values[:, i]) / np.sum(edisp_values[:, i]))

            # Determine positions (bin indices) of e_reco bounds in migration array
            pos_mig = np.digitize(migra_e_reco, mig_array) - 1
            # We ensure that no negative values are found
            pos_mig = np.maximum(pos_mig, 0)

            # We compute the difference between 2 successive bounds in e_reco
            # to get integral over reco energy bin
            integral = np.diff(tmp[pos_mig])

            data.append(integral)

        data = np.asarray(data)
        # EnergyDispersion uses edges of true energy bins
        e_true_edges = self.edisp_map.geom.axes[1].edges

        e_lo, e_hi = e_true_edges[:-1], e_true_edges[1:]
        ereco_lo, ereco_hi = (e_reco[:-1], e_reco[1:])

        return EnergyDispersion(
            e_true_lo=e_lo,
            e_true_hi=e_hi,
            e_reco_lo=ereco_lo,
            e_reco_hi=ereco_hi,
            data=data,
        )