1
|
|
|
# Licensed under a 3-clause BSD style license - see LICENSE.rst |
2
|
|
|
import logging |
3
|
|
|
from regions import CircleSkyRegion |
4
|
|
|
from .map import MapDatasetMaker |
5
|
|
|
|
6
|
|
|
__all__ = ["SpectrumDatasetMaker"] |
7
|
|
|
|
8
|
|
|
log = logging.getLogger(__name__) |
9
|
|
|
|
10
|
|
|
|
11
|
|
|
class SpectrumDatasetMaker(MapDatasetMaker): |
12
|
|
|
"""Make spectrum for a single IACT observation. |
13
|
|
|
|
14
|
|
|
The irfs and background are computed at a single fixed offset, |
15
|
|
|
which is recommend only for point-sources. |
16
|
|
|
|
17
|
|
|
Parameters |
18
|
|
|
---------- |
19
|
|
|
selection : list |
20
|
|
|
List of str, selecting which maps to make. |
21
|
|
|
Available: 'counts', 'exposure', 'background', 'edisp' |
22
|
|
|
By default, all spectra are made. |
23
|
|
|
containment_correction : bool |
24
|
|
|
Apply containment correction for point sources and circular on regions. |
25
|
|
|
background_oversampling : int |
26
|
|
|
Background evaluation oversampling factor in energy. |
27
|
|
|
use_region_center : bool |
28
|
|
|
Approximate the IRFs by the value at the center of the region |
29
|
|
|
""" |
30
|
|
|
|
31
|
|
|
tag = "SpectrumDatasetMaker" |
32
|
|
|
available_selection = ["counts", "background", "exposure", "edisp"] |
33
|
|
|
|
34
|
|
|
def __init__( |
35
|
|
|
self, |
36
|
|
|
selection=None, |
37
|
|
|
containment_correction=False, |
38
|
|
|
background_oversampling=None, |
39
|
|
|
use_region_center=True, |
40
|
|
|
): |
41
|
|
|
self.containment_correction = containment_correction |
42
|
|
|
self.use_region_center = use_region_center |
43
|
|
|
super().__init__( |
44
|
|
|
selection=selection, background_oversampling=background_oversampling |
45
|
|
|
) |
46
|
|
|
|
47
|
|
|
def make_exposure(self, geom, observation): |
48
|
|
|
"""Make exposure. |
49
|
|
|
|
50
|
|
|
Parameters |
51
|
|
|
---------- |
52
|
|
|
geom : `~gammapy.maps.RegionGeom` |
53
|
|
|
Reference map geom. |
54
|
|
|
observation: `~gammapy.data.Observation` |
55
|
|
|
Observation to compute effective area for. |
56
|
|
|
|
57
|
|
|
Returns |
58
|
|
|
------- |
59
|
|
|
exposure : `~gammapy.maps.RegionNDMap` |
60
|
|
|
Exposure map. |
61
|
|
|
""" |
62
|
|
|
exposure = super().make_exposure( |
63
|
|
|
geom, observation, use_region_center=self.use_region_center |
64
|
|
|
) |
65
|
|
|
|
66
|
|
|
is_pointlike = exposure.meta.get("is_pointlike", False) |
67
|
|
|
if is_pointlike: |
68
|
|
|
log.warning( |
69
|
|
|
"MapMaker: use_region_center=False should not be used with point-like IRF. " |
70
|
|
|
"Results are likely inaccurate." |
71
|
|
|
) |
72
|
|
|
|
73
|
|
|
if self.containment_correction: |
74
|
|
|
if is_pointlike: |
75
|
|
|
raise ValueError( |
76
|
|
|
"Cannot apply containment correction for point-like IRF." |
77
|
|
|
) |
78
|
|
|
|
79
|
|
|
if not isinstance(geom.region, CircleSkyRegion): |
80
|
|
|
raise TypeError( |
81
|
|
|
"Containment correction only supported for circular regions." |
82
|
|
|
) |
83
|
|
|
offset = geom.separation(observation.pointing_radec) |
84
|
|
|
containment = observation.psf.containment( |
85
|
|
|
rad=geom.region.radius, |
86
|
|
|
offset=offset, |
87
|
|
|
energy_true=geom.axes["energy_true"].center, |
88
|
|
|
) |
89
|
|
|
exposure.quantity *= containment.reshape(geom.data_shape) |
90
|
|
|
|
91
|
|
|
return exposure |
92
|
|
|
|