Пример #1
0
    def find_energy(self, aeff, emin=None, emax=None):
        """Find energy for a given effective area.

        In case the solution is not unique, provide the `emin` or `emax` arguments
        to limit the solution to the given range. By default the peak energy of the
        effective area is chosen as `emax`.

        Parameters
        ----------
        aeff : `~astropy.units.Quantity`
            Effective area value
        emin : `~astropy.units.Quantity`
            Lower bracket value in case solution is not unique.
        emax : `~astropy.units.Quantity`
            Upper bracket value in case solution is not unique.

        Returns
        -------
        energy : `~astropy.units.Quantity`
            Energy corresponding to the given aeff.
        """
        from gammapy.modeling.models import TemplateSpectralModel

        energy = self.energy.center

        if emin is None:
            emin = energy[0]
        if emax is None:
            # use the peak effective area as a default for the energy maximum
            emax = energy[np.argmax(self.data.data)]

        aeff_spectrum = TemplateSpectralModel(energy, self.data.data)
        return aeff_spectrum.inverse(aeff, emin=emin, emax=emax)
Пример #2
0
def test_TemplateSpectralModel_single_value():
    energy = [1] * u.TeV
    values = [1e-12] * u.Unit("TeV-1 s-1 cm-2")

    model = TemplateSpectralModel(energy=energy, values=values)
    result = model.evaluate([0.5, 2] * u.TeV)

    assert_allclose(result.data, 1e-12)
Пример #3
0
def test_TemplateSpectralModel_evaluate_tiny():
    energy = np.array([1.00000000e06, 1.25892541e06, 1.58489319e06, 1.99526231e06])
    values = np.array([4.39150790e-38, 1.96639562e-38, 8.80497507e-39, 3.94262401e-39])

    model = TemplateSpectralModel(
        energy=energy, values=values * u.Unit("MeV-1 s-1 sr-1")
    )
    result = model.evaluate(energy)
    tiny = np.finfo(np.float32).tiny
    mask = abs(values) - tiny > tiny
    np.testing.assert_allclose(
        values[mask] / values.max(), result[mask].value / values.max()
    )
    mask = abs(result.value) - tiny <= tiny
    assert np.all(result[mask] == 0.0)
Пример #4
0
def test_table_model_from_file():
    filename = "$GAMMAPY_DATA/ebl/ebl_franceschini.fits.gz"
    absorption_z03 = TemplateSpectralModel.read_xspec_model(
        filename=filename, param=0.3
    )
    with mpl_plot_check():
        absorption_z03.plot(energy_range=(0.03, 10), energy_unit=u.TeV, flux_unit="")
Пример #5
0
def test_table_model_from_file():
    filename = "$GAMMAPY_DATA/ebl/ebl_franceschini.fits.gz"
    absorption_z03 = TemplateSpectralModel.read_xspec_model(
        filename=filename, param=0.3
    )
    value = absorption_z03(1 * u.TeV)
    assert_allclose(value, 1)
Пример #6
0
 def table_model(self):
     """Spectrum as `~gammapy.modeling.models.TemplateSpectralModel`."""
     subtable = self.table[self.table["mDM"] == self.mDM.value]
     energies = (10**subtable["Log[10,x]"]) * self.mDM
     channel_name = self.channel_registry[self.channel]
     dN_dlogx = subtable[channel_name]
     dN_dE = dN_dlogx / (energies * np.log(10))
     return TemplateSpectralModel(energy=energies, values=dN_dE)
Пример #7
0
    def from_table(cls, table, sed_type=None, reference_model=None):
        """Create flux points from table

        Parameters
        ----------
        table : `~astropy.table.Table`
            Table
        sed_type : {"dnde", "flux", "eflux", "e2dnde", "likelihood"}
            Sed type
        reference_model : `SpectralModel`
            Reference spectral model

        Returns
        -------
        flux_points : `FluxPoints`
            Flux points
        """
        table = table_standardise_units_copy(table)

        if sed_type is None:
            sed_type = table.meta.get("SED_TYPE", None)

        if sed_type is None:
            sed_type = cls._guess_sed_type(table)

        if sed_type is None:
            raise ValueError("Specifying the sed type is required")

        cls._validate_data(data=table, sed_type=sed_type)

        if sed_type in ["dnde", "eflux", "e2dnde", "flux"]:
            if reference_model is None:
                log.warning(
                    "No reference model set for FluxPoints. Assuming point source with E^-2 spectrum."
                )

                reference_model = PowerLawSpectralModel()

            data = cls._convert_flux_columns(
                table=table, reference_model=reference_model, sed_type=sed_type
            )

        elif sed_type == "likelihood":
            data = cls._convert_loglike_columns(table)
            reference_model = TemplateSpectralModel(
                energy=table["e_ref"].quantity,
                values=table["ref_dnde"].quantity
            )
        else:
            raise ValueError(f"Not a valid SED type {sed_type}")

        # We add the remaining maps
        for key in OPTIONAL_QUANTITIES_COMMON:
            if key in table.colnames:
                data[key] = table[key]

        data.meta["SED_TYPE"] = "likelihood"
        return cls(data=data, reference_spectral_model=reference_model)
Пример #8
0
def table_model():
    energy = MapAxis.from_energy_bounds(0.1 * u.TeV, 100 * u.TeV, 1000).center

    model = PowerLawSpectralModel(
        index=2.3, amplitude="4 cm-2 s-1 TeV-1", reference="1 TeV"
    )
    dnde = model(energy)

    return TemplateSpectralModel(energy, dnde)
Пример #9
0
def table_model():
    energy_edges = energy_logspace(0.1 * u.TeV, 100 * u.TeV, 1000)
    energy = np.sqrt(energy_edges[:-1] * energy_edges[1:])

    model = PowerLawSpectralModel(index=2.3,
                                  amplitude="4 cm-2 s-1 TeV-1",
                                  reference="1 TeV")
    dnde = model(energy)

    return TemplateSpectralModel(energy, dnde, 1)
Пример #10
0
    def get_bias_energy(self, bias, energy_min=None, energy_max=None):
        """Find energy corresponding to a given bias.

        In case the solution is not unique, provide the ``energy_min`` or ``energy_max`` arguments
        to limit the solution to the given range.  By default the peak energy of the
        bias is chosen as ``energy_min``.

        Parameters
        ----------
        bias : float
            Bias value.
        energy_min : `~astropy.units.Quantity`
            Lower bracket value in case solution is not unique.
        energy_max : `~astropy.units.Quantity`
            Upper bracket value in case solution is not unique.

        Returns
        -------
        bias_energy : `~astropy.units.Quantity`
            Reconstructed energy corresponding to the given bias.
        """
        from gammapy.modeling.models import TemplateSpectralModel

        energy_true = self.axes["energy_true"].center
        values = self.get_bias(energy_true)

        if energy_min is None:
            # use the peak bias energy as default minimum
            energy_min = energy_true[np.nanargmax(values)]
        if energy_max is None:
            energy_max = energy_true[-1]

        bias_spectrum = TemplateSpectralModel(energy=energy_true,
                                              values=values)

        energy_true_bias = bias_spectrum.inverse(Quantity(bias),
                                                 energy_min=energy_min,
                                                 energy_max=energy_max)
        if np.isnan(energy_true_bias[0]):
            energy_true_bias[0] = energy_min
        # return reconstructed energy
        return energy_true_bias * (1 + bias)
Пример #11
0
def table_model():
    energy_edges = energy_logspace(0.1 * u.TeV, 100 * u.TeV, 1000)
    energy = np.sqrt(energy_edges[:-1] * energy_edges[1:])

    index = 2.3 * u.Unit("")
    amplitude = 4 / u.cm**2 / u.s / u.TeV
    reference = 1 * u.TeV
    pl = PowerLawSpectralModel(index, amplitude, reference)
    flux = pl(energy)

    return TemplateSpectralModel(energy, flux, 1 * u.Unit(""))
Пример #12
0
    def table_psf_in_energy_range(self,
                                  energy_range,
                                  spectrum=None,
                                  n_bins=11,
                                  **kwargs):
        """Average PSF in a given energy band.

        Expected counts in sub energy bands given the given exposure
        and spectrum are used as weights.

        Parameters
        ----------
        energy_range : `~astropy.units.Quantity`
            Energy band
        spectrum : `~gammapy.modeling.models.SpectralModel`
            Spectral model used for weighting the PSF. Default is a power law
            with index=2.
        n_bins : int
            Number of energy points in the energy band, used to compute the
            weighted PSF.

        Returns
        -------
        psf : `EnergyDependentTablePSF`
            Table PSF
        """
        from gammapy.modeling.models import PowerLawSpectralModel, TemplateSpectralModel

        if spectrum is None:
            spectrum = PowerLawSpectralModel()

        exposure = TemplateSpectralModel(self.axes["energy_true"].center,
                                         self.exposure)

        e_min, e_max = energy_range
        energy = MapAxis.from_energy_bounds(e_min, e_max,
                                            n_bins).edges[:, np.newaxis]

        weights = spectrum(energy) * exposure(energy)
        weights /= weights.sum()

        psf_value = self.evaluate(energy_true=energy)
        psf_value_weighted = weights * psf_value

        energy_axis = MapAxis.from_edges(energy_range, name="energy_true")

        data = psf_value_weighted.sum(axis=0, keepdims=True)
        return self.__class__(axes=[energy_axis, self.axes["rad"]],
                              data=data.value,
                              unit=data.unit,
                              **kwargs)
Пример #13
0
    def make_mask_energy_aeff_max(self, dataset, observation=None):
        """Make safe energy mask from effective area maximum value.

        Parameters
        ----------
        dataset : `~gammapy.datasets.MapDataset` or `~gammapy.datasets.SpectrumDataset`
            Dataset to compute mask for.
        observation: `~gammapy.data.Observation`
            Observation to compute mask for. It is a mandatory argument when fixed_offset is set.

        Returns
        -------
        mask_safe : `~numpy.ndarray`
            Safe data range mask.
        """
        geom, exposure = dataset._geom, dataset.exposure

        if self.fixed_offset:
            if observation:
                position = observation.pointing_radec.directional_offset_by(
                    position_angle=0.0 * u.deg, separation=self.fixed_offset)
            else:
                raise ValueError(
                    f"observation argument is mandatory with {self.fixed_offset}"
                )

        elif self.position:
            position = self.position
        else:
            position = geom.center_skydir

        aeff = exposure.get_spectrum(position) / exposure.meta["livetime"]
        model = TemplateSpectralModel.from_region_map(aeff)

        energy_true = model.energy
        energy_min = energy_true[np.where(model.values > 0)[0][0]]
        energy_max = energy_true[-1]

        aeff_thres = (self.aeff_percent / 100) * aeff.quantity.max()
        inversion = model.inverse(aeff_thres,
                                  energy_min=energy_min,
                                  energy_max=energy_max)

        if not np.isnan(inversion[0]):
            energy_min = inversion[0]

        return geom.energy_mask(energy_min=energy_min)
Пример #14
0
def get_test_cases():
    e_true = Quantity(np.logspace(-1, 2, 120), "TeV")
    e_reco = Quantity(np.logspace(-1, 2, 100), "TeV")
    return [
        dict(model=PowerLawSpectralModel(amplitude="1e2 TeV-1"),
             e_true=e_true,
             npred=999),
        dict(
            model=PowerLaw2SpectralModel(amplitude="1",
                                         emin="0.1 TeV",
                                         emax="100 TeV"),
            e_true=e_true,
            npred=1,
        ),
        dict(
            model=PowerLawSpectralModel(amplitude="1e-11 TeV-1 cm-2 s-1"),
            aeff=EffectiveAreaTable.from_parametrization(e_true),
            livetime="10 h",
            npred=1448.05960,
        ),
        dict(
            model=PowerLawSpectralModel(reference="1 GeV",
                                        amplitude="1e-11 GeV-1 cm-2 s-1"),
            aeff=EffectiveAreaTable.from_parametrization(e_true),
            livetime="30 h",
            npred=4.34417881,
        ),
        dict(
            model=PowerLawSpectralModel(amplitude="1e-11 TeV-1 cm-2 s-1"),
            aeff=EffectiveAreaTable.from_parametrization(e_true),
            edisp=EnergyDispersion.from_gauss(e_reco=e_reco,
                                              e_true=e_true,
                                              bias=0,
                                              sigma=0.2),
            livetime="10 h",
            npred=1437.450076,
        ),
        dict(
            model=TemplateSpectralModel(
                energy=[0.1, 0.2, 0.3, 0.4] * u.TeV,
                values=[4.0, 3.0, 1.0, 0.1] * u.Unit("TeV-1"),
            ),
            e_true=[0.1, 0.2, 0.3, 0.4] * u.TeV,
            npred=0.554513062,
        ),
    ]
Пример #15
0
    def table_psf_in_energy_band(self,
                                 energy_band,
                                 spectrum=None,
                                 n_bins=11,
                                 **kwargs):
        """Average PSF in a given energy band.

        Expected counts in sub energy bands given the given exposure
        and spectrum are used as weights.

        Parameters
        ----------
        energy_band : `~astropy.units.Quantity`
            Energy band
        spectrum : `~gammapy.modeling.models.SpectralModel`
            Spectral model used for weighting the PSF. Default is a power law
            with index=2.
        n_bins : int
            Number of energy points in the energy band, used to compute the
            weigthed PSF.

        Returns
        -------
        psf : `TablePSF`
            Table PSF
        """
        from gammapy.modeling.models import PowerLawSpectralModel, TemplateSpectralModel

        if spectrum is None:
            spectrum = PowerLawSpectralModel()

        exposure = TemplateSpectralModel(self.energy_axis_true.center,
                                         self.exposure)

        e_min, e_max = energy_band
        energy = MapAxis.from_energy_bounds(e_min, e_max, n_bins).edges

        weights = spectrum(energy) * exposure(energy)
        weights /= weights.sum()

        psf_value = self.evaluate(energy=energy)
        psf_value_weighted = weights[:, np.newaxis] * psf_value
        return TablePSF(self.rad_axis, psf_value_weighted.sum(axis=0),
                        **kwargs)
Пример #16
0
def test_TemplateSpectralModel_compound():
    energy = [1.00e06, 1.25e06, 1.58e06, 1.99e06] * u.MeV
    values = [4.39e-7, 1.96e-7, 8.80e-7, 3.94e-7] * u.Unit("MeV-1 s-1 sr-1")

    template = TemplateSpectralModel(energy=energy, values=values)
    correction = PowerLawNormSpectralModel(norm=2)
    model = CompoundSpectralModel(template, correction, operator=operator.mul)
    assert np.allclose(model(energy), 2 * values)

    model_mul = template * correction
    assert isinstance(model_mul, CompoundSpectralModel)
    assert np.allclose(model_mul(energy), 2 * values)

    model_dict = model.to_dict()
    assert model_dict["spectral"]["operator"] == "mul"
    model_class = SPECTRAL_MODEL_REGISTRY.get_cls(model_dict["spectral"]["type"])
    new_model = model_class.from_dict(model_dict)
    assert isinstance(new_model, CompoundSpectralModel)
    assert np.allclose(new_model(energy), 2 * values)
Пример #17
0
    def make_mask_energy_aeff_max(self, dataset, observation=None):
        """Make safe energy mask from effective area maximum value.

        Parameters
        ----------
        dataset : `~gammapy.datasets.MapDataset` or `~gammapy.datasets.SpectrumDataset`
            Dataset to compute mask for.
        observation: `~gammapy.data.Observation`
            Observation to compute mask for. It is a mandatory argument when fixed_offset is set.

        Returns
        -------
        mask_safe : `~numpy.ndarray`
            Safe data range mask.
        """
        geom = dataset._geom

        if self.fixed_offset:
            if observation:
                position = observation.pointing_radec.directional_offset_by(
                    position_angle=0. * u.deg, separation=self.fixed_offset)
            else:
                raise ValueError(
                    f"observation argument is mandatory with {self.fixed_offset}"
                )

        elif self.position is None and self.fixed_offset is None:
            position = PointSkyRegion(dataset.counts.geom.center_skydir)
        else:
            position = PointSkyRegion(self.position)

        aeff = dataset.exposure.get_spectrum(
            position) / dataset.exposure.meta["livetime"]
        model = TemplateSpectralModel.from_region_map(aeff)

        aeff_thres = (self.aeff_percent / 100) * aeff.quantity.max()
        energy_min = model.inverse(aeff_thres)
        return geom.energy_mask(energy_min=energy_min)
Пример #18
0
    def from_table(cls,
                   table,
                   sed_type=None,
                   format="gadf-sed",
                   reference_model=None,
                   gti=None):
        """Create flux points from a table. The table column names must be consistent with the
        sed_type

        Parameters
        ----------
        table : `~astropy.table.Table`
            Table
        sed_type : {"dnde", "flux", "eflux", "e2dnde", "likelihood"}
            Sed type
        format : {"gadf-sed", "lightcurve", "profile"}
            Table format.
        reference_model : `SpectralModel`
            Reference spectral model
        gti : `GTI`
            Good time intervals
        meta : dict
            Meta data.

        Returns
        -------
        flux_points : `FluxPoints`
            Flux points
        """
        table = table_standardise_units_copy(table)

        if sed_type is None:
            sed_type = table.meta.get("SED_TYPE", None)

        if sed_type is None:
            sed_type = cls._guess_sed_type(table.colnames)

        if sed_type is None:
            raise ValueError("Specifying the sed type is required")

        if sed_type == "likelihood":
            table = cls._convert_loglike_columns(table)
            if reference_model is None:
                reference_model = TemplateSpectralModel(
                    energy=flat_if_equal(table["e_ref"].quantity),
                    values=flat_if_equal(table["ref_dnde"].quantity),
                )

        maps = Maps()
        table.meta.setdefault("SED_TYPE", sed_type)

        for name in cls.all_quantities(sed_type=sed_type):
            if name in table.colnames:
                maps[name] = RegionNDMap.from_table(table=table,
                                                    colname=name,
                                                    format=format)

        meta = cls._get_meta_gadf(table)
        return cls.from_maps(
            maps=maps,
            reference_model=reference_model,
            meta=meta,
            sed_type=sed_type,
            gti=gti,
        )
Пример #19
0
    def from_fits(cls,
                  filename,
                  vis=None,
                  prompt=False,
                  ebl=None,
                  n_night=None,
                  Emax=None,
                  t0=Time('1800-01-01T00:00:00', format='isot', scale='utc'),
                  magnify=1,
                  forced_visible=False,
                  dbg=0):
        """
        Read the GRB data from a fits file. 
        Fluxes are given for a series of (t,E) values
        So far no flux exists beyond the last point.

        The spectrum is stored as a table, TemplateSpectralModel, that takes as 
        an input a series of flux values as a function of the energy.
        The model will return values interpolated in log-space with
        math::`scipy.interpolate.interp1d`, returning zero for energies
        outside of the limits of the provided energy array.
        
        The trigger time, time of the GRB explosion, is given either as an 
        absolute date or as a duration in days since an arbitrary date. 
        In that case, a start date is provided to which the eleased times are
        added .
        
        The original time bins and energy bins can be limited by a maximal 
        number of nights, or a maximal energy (This can be useful to get 
        fast approximate results).
        
        The spectra is modifief for an EBL absorption.
        
        The afterglow flux can be adjusted by a multiplicatice factor for 
        various tests.
        
        If requested, the associated prompt spectrum is read.

        Note that TemplateSpectralModel makes an interpolation.
        Following a question on the Slack gammapy channel on
        November 27th, and the answer by Axel Donath:
        The following statement later in the code gave an error
        (dlist_onoff is a collection of Dataset)
        dlist_onoff.write(datapath,prefix="cls",overwrite=True)
        gives:
        ...\gammapy\modeling\models\spectral.py", line 989, in to_dict
        "data": self.energy.data.tolist(),
        NotImplementedError: memoryview: unsupported format >f
        This error comes from the fact that the energy list as to be
        explicitely passed as a float as done below:
            cls.Eval.astype(float)
        (A Quantity is passed as requested but the underlying numpy
        dtype is not supported by energy.data.tolist())


        Parameters
        ----------
        cls : GammaRayBurst class
            GammaRayBurst class instance
        filename : Path
            GRB input file name
        prompt: Boolean
            If True, read information from the associated prompt component
        ebl : STRING, optional
            The EBL absorption model considered. If ebl is "built-in", uses
            the absorbed specrum from the data.
        n_night : Integer, optional
            Maximum number of nights (from the visibility) duting which the 
            data are considered.The default is 10. This ensure that the data 
            are cut after the very last night window for a visibility with 
            less than 10 nights.        
        Emax : Astropy Quantity, optional
            Maximal energy considered in the data. The default is None.
        t0: Astropy Time
            A start date to be added to the slice elapsed time when no GRB 
            explosion date is given.
        magnify : float, optional
            Flux multiplicative factor for tests to the afterglow model. 
            Default is 1
        forced_visible: Boolean
            If True, the GRB is always visible, in particular the obervation
            is always during night. Default is False.
        dbg: Integer
            A debugging level. Default is zero, no debugging messages.
            
        Returns
        -------
        A GammaRayBurst instance.

        """

        # Check if file was compressed and/or if it exists
        # Strangely path.is_file() does not give False but an error
        if not os.path.exists(filename):  # Current file does not exist
            if filename.suffix == ".gz":  # If a gz file, try the non gz file
                filename = filename.with_suffix("")
            else:  # If this not a gz file, try the gz file
                filename = filename.with_suffix(filename.suffix + ".gz")
        if not os.path.exists(filename):  # Check that the new file exist
            sys.exit("grp.py: {} not found".format(filename))

        # Open files and get header and data, and keys in header
        hdul = fits.open(filename)
        hdr = hdul[0].header
        keys_0 = list(hdul[0].header.keys())

        cls = GammaRayBurst()  # Default constructor

        cls.z = hdr['Z']
        # Remove all extensions
        cls.name = str(filename.name).rstrip(''.join(filename.suffixes))

        cls.radec = SkyCoord(hdr['RA'] * u.degree,
                             hdr['DEC'] * u.degree,
                             frame='icrs')
        cls.Eiso = hdr['EISO'] * u.erg
        cls.Epeak = hdr['EPEAK'] * u.keV
        cls.t90 = hdr['Duration'] * u.s
        cls.G0H = hdr['G0H']
        if "G0W" in keys_0:  # Not in SHORTFITS
            cls.G0W = hdr['G0W']
        cls.Fluxpeak = hdr['PHFLUX'] * u.Unit("ph.cm-2.s-1")
        cls.gamma_le = hdr['LOWSP']
        cls.gamma_he = hdr['HIGHSP']

        # GRB trigger time
        if "GRBJD" in keys_0:  # Not in SHORTFITS
            cls.t_trig = Time(hdr['GRBJD'] * u.day, format="jd", scale="utc")
        elif "GRBTIME" in keys_0:  # Add start date
            cls.t_trig = Time(hdr['GRBTIME'] + t0.jd, format="jd", scale="utc")

        ###--------------------------
        ### Time slices - so far common to afterglow and prompt
        ###--------------------------
        tval = QTable.read(hdul["TIMES (AFTERGLOW)"])

        # Temporary : in short GRB fits file, unit is omitted
        # The flux value is given on an interval ("col0", "col1°°.
        # The default is to consider that the flux is valid at the end of the
        # interval.
        if isinstance(tval[0][0], astropy.units.quantity.Quantity):
            cls.tval = np.array(tval[tval.colnames[0]].value) * tval[0][0].unit
        else:  # In SHORT GRB, the time bin is given, [t1, t2].
            cls.tval = np.array(tval["col1"]) * u.s

        ###--------------------------
        ### Visibilities --- requires tval span if computed on the fly
        ###--------------------------
        # Either read the default visibility from the GRB fits file (None)
        # or recompute it(a keyword has been given and a dictionnary retrieved)
        # or read it from the specified folder
        for loc in ["North", "South"]:
            if vis == None:
                cls.vis[loc] = cls.vis[loc].from_fits(cls,
                                                      hdr,
                                                      hdul,
                                                      hdu=1,
                                                      loc=loc)
            elif isinstance(vis, dict):
                cls.vis[loc] = Visibility.compute(cls,
                                                  loc,
                                                  param=vis,
                                                  force_vis=forced_visible,
                                                  debug=bool(dbg > 2))
            else:
                name = Path(vis, cls.name + "_" + loc + "_vis.bin")
                cls.vis[loc] = Visibility.read(name)

        ###--------------------------
        ### Limit the data to a certain number of nights
        ###--------------------------
        if n_night != None:
            # Find end of last night to be considered (if a night is found)
            # Check that there are enough nights available"
            tmax = 0  # In days

            for loc in ["North", "South"]:
                if len(cls.vis[loc].t_twilight[0]) \
                    and len(cls.vis[loc].t_true[0]):
                    # Limit to exisiting nights
                    n_night = min(n_night, len(cls.vis[loc].t_twilight))
                    tmax = max(
                        tmax, cls.vis[loc].t_twilight[n_night - 1][1].jd -
                        cls.t_trig.jd)
            tmax = max(1 * u.h, tmax * u.d)
            if tmax < cls.tval[-1]:  # tval assumed ordered
                warning(" Data up to {:5.3f} restricted to {:5.3f}".format(
                    cls.tval[-1].to("d"), tmax))
                cls.tval = cls.tval[cls.tval <= tmax]

                # Limit the visibility windows accordingly
                for loc in ["North", "South"]:
                    if len(cls.vis[loc].t_true[0]):
                        tends = [(t[1] - cls.t_trig).jd
                                 for t in cls.vis[loc].t_true]
                        idmax = np.where(
                            np.array(tends) <= tmax.to_value(u.day))
                        if len(idmax[0]):  # At least one element
                            cls.vis[loc].t_true = cls.vis[
                                loc].t_true[:idmax[0][-1] + 1]
                        else:  # No visibility period within n_night
                            cls.vis[loc].vis = False
                            cls.vis[loc].vis_night = False
                            cls.vis[loc].t_true = [[]]
        ###--------------------------
        ### Afterglow Energies - Limited to Emax if defined
        ###--------------------------
        k = "Energies (afterglow)"
        cls.Eval = Table.read(hdul[k])[k].quantity
        cls.Eval = np.array(cls.Eval) * cls.Eval[0].unit
        if Emax != None and Emax <= cls.Eval[-1]:
            warning(" Data up to {:5.3f} restricted to {:5.3f}".format(
                cls.Eval[-1], Emax))
            cls.Eval = cls.Eval[cls.Eval <= Emax]

        ###--------------------------
        ### Afterglow flux
        ###--------------------------

        # Get flux,possibly already absorbed
        if (ebl == "in-file"):  # Read default absorbed model
            flux = QTable.read(hdul["EBL-ABS. SPECTRA (AFTERGLOW)"])
        else:
            flux = QTable.read(hdul["SPECTRA (AFTERGLOW)"])

        flux_unit = u.Unit(flux.meta["UNITS"]) / u.Unit("ph")  # Removes ph

        # Store the flux. Note the transposition
        itmax = len(cls.tval) - 1
        jEmax = len(cls.Eval) - 1
        cls.fluxval = np.zeros((itmax + 1, jEmax + 1)) * flux_unit

        for i in range(0, itmax + 1):
            for j in range(0, jEmax + 1):
                cls.fluxval[i][j] = magnify * flux[j][i] * flux_unit  # transp!

        # Build time series of interpolated spectra - limited to dtmax
        for i, t in enumerate(cls.tval):
            glow = TemplateSpectralModel(energy=cls.Eval.astype(float),
                                         values=cls.fluxval[i],
                                         interp_kwargs={"values_scale": "log"})
            cls.spec_afterglow.append(glow)

        ###--------------------------
        ### Prompt - a unique energy spectrum
        ###--------------------------

        # Get the prompt if potentially visible and if requested
        cls.prompt = False  # No prompt component was found
        if prompt:
            if cls.vis["North"].vis_prompt or cls.vis["South"].vis_prompt:
                # Deduce prompt folder from GRB path name
                folder = Path(filename.absolute().parents[0], "../prompt/")
                cls.spec_prompt = cls.get_prompt(grb_id=cls.name[5:],
                                                 folder=folder,
                                                 debug=bool(dbg))
                if cls.spec_prompt != None:
                    cls.prompt = True

        ###--------------------------
        ### Total attenuated spectra
        ###--------------------------

        # Build the total attenuated model
        for i, t in enumerate(cls.tval):
            spec_tot = cls.spec_afterglow[i]
            if cls.prompt:
                if i <= cls.id90: spec_tot += cls.spec_prompt[i]
            model = cls.EBLabsorbed(spec_tot, ebl)
            cls.spectra.append(model)

        hdul.close()

        return cls
Пример #20
0
`naima.models.TemplateSpectralModel`
"""

# %%
# Example plot
# ------------
# Here is an example plot of the model:

import numpy as np
from astropy import units as u
import matplotlib.pyplot as plt
from gammapy.modeling.models import Models, SkyModel, TemplateSpectralModel

energy_range = [0.1, 1] * u.TeV
energy = np.array([1e6, 3e6, 1e7, 3e7]) * u.MeV
values = np.array([4.4e-38, 2.0e-38, 8.8e-39, 3.9e-39
                   ]) * u.Unit("MeV-1 s-1 cm-2")
model = TemplateSpectralModel(energy=energy, values=values)
model.plot(energy_range)
plt.grid(which="both")

# %%
# YAML representation
# -------------------
# Here is an example YAML file using the model:

model = SkyModel(spectral_model=model, name="template-model")
models = Models([model])

print(models.to_yaml())
Пример #21
0
# Corrections to templates can be applied by multiplication with a normalized spectral model,
# for example `gammapy.modeling.models.PowerLawNormSpectralModel`.
# This operation create a new `gammapy.modeling.models.CompoundSpectralModel`
#
from gammapy.modeling.models import (
    Models,
    PowerLawNormSpectralModel,
    SkyModel,
    TemplateSpectralModel,
)

energy_bounds = [0.1, 1] * u.TeV
energy = np.array([1e6, 3e6, 1e7, 3e7]) * u.MeV
values = np.array([4.4e-38, 2.0e-38, 8.8e-39, 3.9e-39
                   ]) * u.Unit("MeV-1 s-1 cm-2")
template = TemplateSpectralModel(energy=energy, values=values)
template.plot(energy_bounds)
plt.grid(which="both")

new_model = template * PowerLawNormSpectralModel(norm=2, tilt=0)

print(new_model)

# %%
# YAML representation
# -------------------
# Here is an example YAML file using the model:

model = SkyModel(spectral_model=template, name="template-model")
models = Models([model])
Пример #22
0
    def from_yaml(cls, data, ebl=None, magnify=1):
        """

        Returns
        -------
        A GammaRayBurst instance.

        """

        cls = GammaRayBurst()  # This calls the constructor

        cls.z = data["z"]
        cls.name = data["name"]
        cls.radec = SkyCoord(data["ra"], data["dec"], frame='icrs')
        cls.Eiso = u.Quantity(data["Eiso"])
        cls.Epeak = u.Quantity(data['Epeak'])
        cls.t90 = u.Quantity(data['t90'])
        cls.G0H = data['G0H']
        cls.G0W = data['G0W']
        cls.Fluxpeak = u.Quantity(data['Fluxpeak'])
        cls.gamma_le = data['gamma_le']
        cls.gamma_he = data['gamma_he']
        cls.t_trig = Time(data["t_trig"], format="datetime", scale="utc")

        ### Energies, times and fluxes ---
        Emin = u.Quantity(data["Emin"])
        Emax = u.Quantity(data["Emax"])
        tmin = u.Quantity(data["tmin"])
        tmax = u.Quantity(data["tmax"])
        ntbin = data["ntbin"]
        cls.Eval = np.asarray([Emin.value,
                               Emax.to(Emin.unit).value]) * Emin.unit

        if ntbin != 1:
            cls.tval = np.logspace(np.log10(tmin.to(u.s).value),
                                   np.log10(tmax.to(u.s).value), ntbin) * u.s
        else:  # A single wtime window
            cls.tval = np.array([tmin.value,
                                 tmax.to(tmin.unit).value]) * tmin.unit

        flux_unit = u.Unit("1/(cm2 GeV s)")
        cls.fluxval = np.zeros((len(cls.tval), len(cls.Eval))) * flux_unit

        for i, t in enumerate(cls.tval):
            for j, E in enumerate(cls.Eval):
                dnde = (u.Quantity(data["K"]) *
                        (E / data["E0"])**-data["gamma"] *
                        (t / data["t0"])**-data["beta"])
                #print(i,j,dnde)
                cls.fluxval[i][j] = magnify * dnde.to(flux_unit)

        ### Visibilities --- includes tval span
        for loc in ["North", "South"]:
            cls.vis[loc] = Visibility(cls, loc)
            # Recomputing done in the main
            # cls.vis[loc].compute(debug=False)

        ### No prompt component foreseen in this case
        cls.prompt = False

        for i, t in enumerate(cls.tval):
            # Note that TableModel makes an interpolation
            # Following a question on the Slack gammapy channel on
            # November 27th, and the answer by Axel Donath:
            # The foloowing statement later in the code gave an error
            # (dlist_onoff is a collection of Dataset)
            # dlist_onoff.write(datapath,prefix="cls",overwrite=True)
            # gives:
            # ...\gammapy\modeling\models\spectral.py", line 989, in to_dict
            # "data": self.energy.data.tolist(),
            # NotImplementedError: memoryview: unsupported format >f
            # This error comes from the fact that the energy list as to be
            # explicitely passed as a float as done below:
            #    cls.Eval.astype(float)
            # (A Quantity is passed as requested but the underlying numpy
            # dtype is not supported by energy.data.tolist()
            tab = TemplateSpectralModel(energy=cls.Eval.astype(float),
                                        values=cls.fluxval[i],
                                        interp_kwargs={"values_scale": "log"})

            model = cls.EBLabsorbed(tab, ebl)
            cls.spectra.append(model)

        return cls
Пример #23
0
    def get_prompt(self,
                   grb_id=None,
                   folder=None,
                   subfolder="ctagrbs_spop",
                   debug=False):
        """
        Get the prompt component associated to the afterglow.
        The prompt spectra are produced so that they correspond to the values 
        provided by Giancarlo (Lorentz Factor, peak energy, photon flux, and 
        redshift). 
        A single set of spectra is given spanning over the T90 GRB duration. 
        The flux is an "average" prompt spectrum over T90. 

        Parameters
        ----------
        grb_id : integer, optional
            The GRB identifier. The default is None.
        folder : String, optional
            Where to find the prompt data, below the 'lightcurves/prompt' 
            folder. The default is None.
        debug : Boolean, optional
            If True, let's talk a bit. The default is False.

        Returns
        -------
        TYPE
            DESCRIPTION.

        """

        ###----------------------------
        ### Check everything goes well
        ###----------------------------

        # Define the prompt data folder from the afterglow parent folder
        folder = Path(folder, subfolder)
        if not folder.exists(): sys.exit(" Wrong prompt data folder")

        if grb_id == None: sys.exit(" Provide a GRB identifier")

        # if grb_id in [6, 30 ,191]:
        #     failure(" GRB prompt",grb_id," simulated with a Wind profile")
        #     failure(" It cannot be associated to the current afterglow !")
        #     return -1, None

        ###----------------------------
        ### Mask times beyong t90
        ###----------------------------

        # Find the closest time bin at t90 in the Afterglow
        # id90 is the index of the time following the t90 value
        # t90 is therefore between the index id90-1 and id90
        self.id90 = np.where(self.tval >= self.t90)[0][0]
        if self.id90 == 0:
            warning(
                "{} : t90 = {} is before the first afterglow time bin".format(
                    self.name, self.t90))
            return None

        # Define a reduction for each time slice, either 0 or 1 except at t90.
        fraction = (self.t90 - self.tval[self.id90 - 1])
        fraction = fraction / (self.tval[self.id90] - self.tval[self.id90 - 1])
        self.weight = np.concatenate(
            (np.ones(self.id90), [fraction],
             np.zeros(len(self.tval) - self.id90 - 1)))

        ###----------------------------
        ### Read prompt data
        ###----------------------------
        # Open file - read the lines
        filename = Path(folder, grb_id + "-spec.dat")
        if not filename.exists():
            failure("{} does no exist".format(filename))
            return None

        file = open(filename, "r")
        lines = file.readlines()

        # get Gamma and z
        data = lines[0].split()
        gamma_prompt = float(data[2])
        redshift = float(data[5])

        # Consistency check - Zeljka data are rounded at 2 digits
        if np.abs(self.z - redshift)>0.01 or \
           np.abs(self.G0H - gamma_prompt)>0.01:
            failure(
                " {:10s}: Afterglow / prompt : z= {:4.2f} / {:4.2f}  G0H/gamma= {:5.2f} / {:5.2f} (G0W= {:5.2f})"
                .format(self.name, self.z, redshift, self.G0H, gamma_prompt,
                        self.G0W))

        # Get units - omit "ph" in flux unit
        data = lines[1].split()
        unit_e = data[0][1:-1]
        unit_flx = ''.join([x + " " for x in data[2:]])[1:-2]

        # Get flux points - assign units to data, use afterglow units
        data = lines
        Eval = []
        fluxval = []
        for line in lines[4:]:
            data = line.split()
            Eval.append(float(data[0]))
            fluxval.append(float(data[1]))

        self.E_prompt = Eval * u.Unit(unit_e)
        self.flux_prompt = fluxval * u.Unit(unit_flx)

        if (unit_e != self.Eval.unit):
            if debug:
                warning("Converting energy units from {} to {}".format(
                    unit_e, self.Eval[0].unit))
            self.E_prompt = self.E_prompt.to(self.Eval[0].unit)

        if (unit_flx != self.fluxval[0].unit):
            if debug:
                warning("Converting flux units from {} to {}".format(
                    unit_flx, self.fluxval[0][0].unit))
            self.flux_prompt = self.flux_prompt.to(self.fluxval[0][0].unit)

        ###----------------------------
        ### Create a list of weighted models for non-zero weights
        ###----------------------------
        models = []
        for i in range(self.id90 + 1):
            flux_w = self.flux_prompt * self.weight[i]
            models.append(
                TemplateSpectralModel(energy=self.E_prompt,
                                      values=flux_w,
                                      interp_kwargs={"values_scale": "log"}))

        if debug:
            print("Prompt associated to ", self.name)
            print("Gamma = ", gamma_prompt, " redshift =", redshift)
            print("  {:8} : {:10}".format(unit_e, unit_flx))
            for E, flux in zip(self.E_prompt, self.flux_prompt):
                print("  {:8.2f} : {:10.2e} ".format(E.value, flux.value))
            islice = 0
            print(" {:>8} - {:>5} ".format("Time", "Weight"), end="")
            for t, w in zip(self.tval, self.weight):
                print(" {:8.2f} - {:5.2f} ".format(t, w), end="")
                print("*") if islice == self.id90 else print("")
                islice += 1

            print("Prompt is between: ", self.tval[self.id90 - 1],
                  self.tval[self.id90])

        return models
Пример #24
0
# Spectral correction
# Corrections to templates can be applied by multiplication with a normalized spectral model,
# for example `gammapy.modeling.models.PowerLawNormSpectralModel`.
# This operation create a new `gammapy.modeling.models.CompoundSpectralModel`
#
from gammapy.modeling.models import (
    Models,
    PowerLawNormSpectralModel,
    SkyModel,
    TemplateSpectralModel,
)

energy_range = [0.1, 1] * u.TeV
energy = np.array([1e6, 3e6, 1e7, 3e7]) * u.MeV
values = np.array([4.4e-38, 2.0e-38, 8.8e-39, 3.9e-39]) * u.Unit("MeV-1 s-1 cm-2")
template = TemplateSpectralModel(energy=energy, values=values)
template.plot(energy_range)
plt.grid(which="both")


new_model = template * PowerLawNormSpectralModel(norm=2, tilt=0)

print(new_model)

# %%
# YAML representation
# -------------------
# Here is an example YAML file using the model:

model = SkyModel(spectral_model=template, name="template-model")
models = Models([model])
Пример #25
0
plt.ylabel("Flux (cm-2 s-1 MeV-1 sr-1)")

# In[ ]:

# TODO: show how one can fix the extrapolate to high energy
# by computing and padding an extra plane e.g. at 1e3 TeV
# that corresponds to a linear extrapolation

# ## Isotropic diffuse background
#
# To load the isotropic diffuse model with Gammapy, use the [gammapy.modeling.models.TemplateSpectralModel](https://docs.gammapy.org/dev/api/gammapy.modeling.models.TemplateSpectralModel.html). We are using `'fill_value': 'extrapolate'` to extrapolate the model above 500 GeV:

# In[ ]:

diffuse_iso = TemplateSpectralModel.read_fermi_isotropic_model(
    filename="$GAMMAPY_DATA/fermi_3fhl/iso_P8R2_SOURCE_V6_v06.txt",
    interp_kwargs={"fill_value": None},
)

# We can plot the model in the energy range between 50 GeV and 2000 GeV:

# In[ ]:

erange = [50, 2000] * u.GeV
diffuse_iso.plot(erange, flux_unit="1 / (cm2 MeV s sr)")

# ## PSF
#
# Next we will tke a look at the PSF. It was computed using ``gtpsf``, in this case for the Galactic center position. Note that generally for Fermi-LAT, the PSF only varies little within a given regions of the sky, especially at high energies like what we have here. We use the [gammapy.irf.EnergyDependentTablePSF](https://docs.gammapy.org/dev/api/gammapy.irf.EnergyDependentTablePSF.html) class to load the PSF and use some of it's methods to get some information about it.

# In[ ]:
Пример #26
0
    def read_prompt(cls,
                    filename,
                    glow=None,
                    ebl=None,
                    z=0 * u.dimensionless_unscaled,
                    magnify=1):
        """
        This function is for tests using ttime-resolved spectra.
        Read prompt data from a file and associate it to the afterglow
        information if requested (or keep the default from the constructor
        otherwise)

        Parameters
        ----------
        cls : GammaRayBurst
            Class intance
        filename : String
            DESCRIPTION.
        glow : boolean, optional
            If defined, the Prompt characteritics are obatined from the
            afterglow with same id. The default is None.
        ebl : string, optional
            The name of an EBL absoprtion model in the Gammapy data.
            The default is None.
        z : float, optional
            GRB redshift. The default is 0*u.dimensionless_unscaled.
        magnify : float, optional
            Flux multiplicative factor for tests. Default is 1

        Returns
        -------
        grb : GammaRayBurst
            A GammaRayBurst instance

        """

        if (glow != None):
            grb = glow  # Copy afterglow parameters
            #grb.z = 0
            # Flux table - Flux at a series of points
            grb.Eval = [0] * u.GeV
            grb.tval = [0] * u.s
            grb.fluxval = [0] * u.Unit("1 / (cm2 GeV s)")
            grb.spectra = []  # Gammapy models (one per t slice)
        else:
            grb = cls()  # This calls the constructor

        hdul = fits.open(filename)

        grb.name = Path(filename.name).stem

        # Energies, times and fluxes
        grb.Eval = Table.read(hdul, hdu=1)["energy"].quantity * u.TeV
        grb.tval = Table.read(hdul, hdu=2)["time"].quantity * u.s
        flux = Table.read(hdul, hdu=3)
        flux_unit = u.Unit("1/(cm2 TeV s)")

        icol_t = len(flux.colnames)  # column number - time
        jrow_E = len(flux[flux.colnames[0]])  # row number

        # Note the transposition from flux to fluxval
        grb.fluxval = np.zeros((icol_t, jrow_E)) * flux_unit
        for i in range(0, icol_t):
            for j in range(0, jrow_E):
                f = flux[j][i]
                if (f > 1):
                    # print(i,j,f)
                    f = 0  # Correct a bug in event #172 - to be removed
                grb.fluxval[i][j] = magnify * f * flux_unit  # transp!

        for i, t in enumerate(grb.tval):
            # Note that TableModel makes an interpolation
            tab = TemplateSpectralModel(energy=grb.Eval.astype(float),
                                        values=grb.fluxval[i],
                                        norm=1.,
                                        interp_kwargs={"values_scale": "log"})
            model = cls.EBLabosrbed(tab, ebl)
            grb.spectra.append(model)

        hdul.close()
        return grb
Пример #27
0
def stacked_model(ds, ds_stack=None, first=False, debug=False):
    """
    This function is not finalised and should be checked. It is intended to
    recompute an effective spectral model from the exisiting already stacked 
    model -from the previous call- and the current model in a dataset list. It
    also extract the masked dataset of the first dataset in the list 
    (when first = True)

    Parameters
    ----------
    ds : Dataset
        The current dataset.
    ds_stack : Dataset, optional
        The current stacked dataset if first is False. The default is None.
    first : Boolean, optional
        If True, extract the masked dataset - Valid for the first dataset of 
        the list. The default is False.
    debug : Boolean, optional
        If True, let's talk a bit. The default is False.

    Returns
    -------
    model : Skymodel
        The current stcake model.

    """

    # Get unmasked Reconstructed E bining from current dataset
    # (but they are all identical)
    e_axis = ds.background.geom.axes[0]  # E reco sampling from the IRF

    if first:
        # The reconstructed binning is required to apply the masking
        # The theoretical spectrum is therefore evaluated on reconstrcuted energies which
        # assumes that the reconstructed energy is not too different from the true one.
        # e_axis = dsets[0].aeff.data.axes[0] # E true sampling from the IRF
        flux_org = ds.models[0].spectral_model(e_axis.center)
        mask_org = ds.mask_safe.data.flatten()

        spec = TemplateSpectralModel(energy=e_axis.center,
                                     values=flux_org * mask_org,
                                     interp_kwargs={"values_scale": "log"})
        model = SkyModel(spectral_model=spec, name="Stack" + "-" + ds.name)

    else:
        flux_stacked = ds_stack.models[0].spectral_model(e_axis.center)
        dt_stack = ds_stack.gti.time_sum  # Duration on present stack

        flux_org = ds.models[0].spectral_model(e_axis.center)
        mask_org = ds.mask_safe.data.flatten()
        dt = ds.gti.time_sum  # Duration on present stack

        # Create ad-hoc new flux and model
        dt_new = dt + dt_stack
        flux_new = (dt_stack.value * flux_stacked + dt.value * flux_org *
                    mask_org) / (dt_stack.value + dt.value)

        # Create a new SkyModel from the flux template model
        spec = TemplateSpectralModel(energy=e_axis.center,
                                     values=flux_new,
                                     interp_kwargs={"values_scale": "log"})
        model = SkyModel(spectral_model=spec, name="Stack" + "-" + ds.name)

        if debug:
            livetime = ds.gti.time_sum  # Duration on present stack
            print(72 * "-")
            print(" Current dataset dt={:10.2f} - {} with model {}".format(
                livetime, ds.name, ds.models[0].name))
            print("    On stack  : dt=", dt_stack, " F0 = ", flux_stacked[0])
            print("    To add    : dt=", dt, " F0 = ", flux_org[0])
            print("    To stack  : dt=", dt_new, " F0 = ", flux_new[0])
            print("")

    return model
Пример #28
0
def generate_dataset(Eflux,
                     flux,
                     Erange=None,
                     tstart=Time('2000-01-01 02:00:00', scale='utc'),
                     tobs=100 * u.s,
                     irf_file=None,
                     alpha=1 / 5,
                     name=None,
                     fake=True,
                     onoff=True,
                     seed='random-seed',
                     debug=False):
    """
    Generate a dataset from a list of energies and flux points either as
    a SpectrumDataset or a SpectrumDatasetOnOff

    Note :
    - in SpectrumDataset, the backgound counts are assumed precisely know and
    are not fluctuated.
    - in SpectrumDatasetOnOff, the background counts (off counts) are
    fluctuated from the IRF known values.

    Parameters
    ----------
    Eflux : Quantity
        Energies at which the flux is given.
    flux : Quantity
        Flux corresponding to the given energies.
    Erange : List, optional
        The energy boundaries within which the flux is defined, if not over all
        energies. The default is None.
    tstart : Time object, optional
        Start date of the dataset.
        The default is Time('2000-01-01 02:00:00',scale='utc').
    tobs : Quantity, optional
        Duration of the observation. The default is 100*u.s.
    irf_file : String, optional
        The IRf file name. The default is None.
    alpha : Float, optional
        The on over off surface ratio for the On-Off analysis.
        The default is 1/5.
    name : String, optional
        The dataset name, also used to name tthe spectrum. The default is None.
    fake : Boolean, optional
        If True, the dataset counts are fluctuated. The default is True.
    onoff : Boolean, optional
        If True, use SpectrumDatasetOnOff, otherwise SpectrumDataSet.
        The default is True.
    seed : String, optional
        The seed for the randome generator; If an integer will generate the
        same random series at each run. The default is 'random-seed'.
    debug: Boolean
        If True, let's talk a bit. The default is False.

    Returns
    -------
    ds : Dataset object
        The dataset.

    """
    random_state = get_random_state(seed)

    ### Define on region
    on_pointing = SkyCoord(ra=0 * u.deg, dec=0 * u.deg,
                           frame="icrs")  # Observing region
    on_region = CircleSkyRegion(center=on_pointing, radius=0.5 * u.deg)

    # Define energy axis (see spectrum analysis notebook)
    # edges for SpectrumDataset - all dataset should have the same axes
    # Note that linear spacing is clearly problematic for powerlaw fluxes
    # Axes can also be defined using MapAxis
    unit = u.GeV
    E1v = min(Eflux).to(unit).value
    E2v = max(Eflux).to(unit).value
    #     ereco = np.logspace(np.log10(1.1*E1v), np.log10(0.9*E2v), 20) * unit
    #     ereco_axis = MapAxis.from_edges(ereco.to("TeV").value,
    #                                    unit="TeV",
    #                                    name="energy",
    #                                    interp="log")

    ereco_axis = MapAxis.from_energy_bounds(1.1 * E1v * unit,
                                            0.9 * E2v * unit,
                                            nbin=4,
                                            per_decade=True,
                                            name="energy")

    #     etrue = np.logspace(np.log10(    E1v), np.log10(    E2v), 50) * unit
    #     etrue_axis = MapAxis.from_edges(etrue.to("TeV").value,
    #                                    unit="TeV",
    #                                    name="energy_true",
    #                                    interp="log")
    etrue_axis = MapAxis.from_energy_bounds(E1v * unit,
                                            E2v * unit,
                                            nbin=4,
                                            per_decade=True,
                                            name="energy_true")
    if (debug):
        print("Dataset ", name)
        print("Etrue : ", etrue_axis.edges)
        print("Ereco : ", ereco_axis.edges)

    # Load IRF
    irf = load_cta_irfs(irf_file)

    spec = TemplateSpectralModel(energy=Eflux,
                                 values=flux,
                                 interp_kwargs={"values_scale": "log"})

    model = SkyModel(spectral_model=spec, name="Spec" + str(name))
    obs = Observation.create(obs_id=1,
                             pointing=on_pointing,
                             livetime=tobs,
                             irfs=irf,
                             deadtime_fraction=0,
                             reference_time=tstart)

    ds_empty = SpectrumDataset.create(
        e_reco=ereco_axis,  # Ereco.edges,
        e_true=etrue_axis,  #Etrue.edges,
        region=on_region,
        name=name)
    maker = SpectrumDatasetMaker(containment_correction=False,
                                 selection=["exposure", "background", "edisp"])
    ds = maker.run(ds_empty, obs)
    ds.models = model
    mask = ds.mask_safe.geom.energy_mask(energy_min=Erange[0],
                                         energy_max=Erange[1])

    mask = mask & ds.mask_safe.data
    ds.mask_safe = RegionNDMap(ds.mask_safe.geom, data=mask)

    ds.fake(random_state=random_state)  # Fake is mandatory ?

    # Transform SpectrumDataset into SpectrumDatasetOnOff if needed
    if (onoff):

        ds = SpectrumDatasetOnOff.from_spectrum_dataset(dataset=ds,
                                                        acceptance=1,
                                                        acceptance_off=1 /
                                                        alpha)
        print("Transformed in ONOFF")

    if fake:
        print(" Fluctuations : seed = ", seed)
        if (onoff):
            ds.fake(npred_background=ds.npred_background())
        else:
            ds.fake(random_state=random_state)

    print("ds.energy_range = ", ds.energy_range)

    return ds
Пример #29
0
def test_fermi_isotropic():
    filename = "$GAMMAPY_DATA/fermi_3fhl/iso_P8R2_SOURCE_V6_v06.txt"
    model = TemplateSpectralModel.read_fermi_isotropic_model(filename)
    assert_quantity_allclose(model(50 * u.GeV),
                             1.463 * u.Unit("1e-13 MeV-1 cm-2 s-1 sr-1"),
                             rtol=1e-3)