Passed
Push — master ( fb4dcc...ae5621 )
by Axel
02:38
created

gammapy.irf.tests.test_io.TestIRFWrite.setup()   B

Complexity

Conditions 1

Size

Total Lines 50
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 38
nop 1
dl 0
loc 50
rs 8.968
c 0
b 0
f 0
1
# Licensed under a 3-clause BSD style license - see LICENSE.rst
2
import numpy as np
3
from numpy.testing import assert_allclose
4
import astropy.units as u
5
from astropy.io import fits
6
from astropy.units import Quantity
7
from gammapy.irf import (
8
    Background3D,
9
    EffectiveAreaTable2D,
10
    EnergyDispersion2D,
11
    load_cta_irfs,
12
    load_irf_dict_from_file,
13
)
14
from gammapy.maps import MapAxis
15
from gammapy.utils.scripts import make_path
16
from gammapy.utils.testing import requires_data
17
18
19 View Code Duplication
@requires_data()
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
20
def test_cta_irf():
21
    """Test that CTA IRFs can be loaded and evaluated."""
22
    irf = load_cta_irfs(
23
        "$GAMMAPY_DATA/cta-1dc/caldb/data/cta/1dc/bcf/South_z20_50h/irf_file.fits"
24
    )
25
26
    energy = Quantity(1, "TeV")
27
    offset = Quantity(3, "deg")
28
29
    val = irf["aeff"].evaluate(energy_true=energy, offset=offset)
30
    assert_allclose(val.value, 545269.4675, rtol=1e-5)
31
    assert val.unit == "m2"
32
33
    val = irf["edisp"].evaluate(offset=offset, energy_true=energy, migra=1)
34
    assert_allclose(val.value, 3183.6882, rtol=1e-5)
35
    assert val.unit == ""
36
37
    val = irf["psf"].evaluate(
38
        rad=Quantity(0.1, "deg"), energy_true=energy, offset=offset
39
    )
40
    assert_allclose(val, 3.56989 * u.Unit("deg-2"), rtol=1e-5)
41
42
    val = irf["bkg"].evaluate(energy=energy, fov_lon=offset, fov_lat="0 deg")
43
    assert_allclose(val.value, 9.400071e-05, rtol=1e-5)
44
    assert val.unit == "1 / (MeV s sr)"
45
46
47 View Code Duplication
@requires_data()
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
48
def test_cta_irf_alpha_config_south():
49
    """Test that CTA IRFs can be loaded and evaluated."""
50
    irf = load_cta_irfs(
51
        "$GAMMAPY_DATA/cta-caldb/Prod5-South-20deg-AverageAz-14MSTs37SSTs.180000s-v0.1.fits.gz"
52
    )
53
54
    energy = Quantity(1, "TeV")
55
    offset = Quantity(3, "deg")
56
57
    val = irf["aeff"].evaluate(energy_true=energy, offset=offset)
58
    assert_allclose(val.value, 493538.4460737773, rtol=1e-5)
59
    assert val.unit == "m2"
60
61
    val = irf["edisp"].evaluate(offset=offset, energy_true=energy, migra=1)
62
    assert_allclose(val.value, 0.0499099, rtol=1e-5)
63
    assert val.unit == ""
64
65
    val = irf["psf"].evaluate(
66
        rad=Quantity(0.1, "deg"), energy_true=energy, offset=offset
67
    )
68
    assert_allclose(val, 3.31135957 * u.Unit("deg-2"), rtol=1e-5)
69
70
    val = irf["bkg"].evaluate(energy=energy, fov_lon=offset, fov_lat="0 deg")
71
    assert_allclose(val.value, 8.98793486e-05, rtol=1e-5)
72
    assert val.unit == "1 / (MeV s sr)"
73
74
75 View Code Duplication
@requires_data()
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
76
def test_cta_irf_alpha_config_north():
77
    """Test that CTA IRFs can be loaded and evaluated."""
78
    irf = load_cta_irfs(
79
        "$GAMMAPY_DATA/cta-caldb/Prod5-North-20deg-AverageAz-4LSTs09MSTs.180000s-v0.1.fits.gz"
80
    )
81
82
    energy = Quantity(1, "TeV")
83
    offset = Quantity(3, "deg")
84
85
    val = irf["aeff"].evaluate(energy_true=energy, offset=offset)
86
    assert_allclose(val.value, 277301.26585409, rtol=1e-5)
87
    assert val.unit == "m2"
88
89
    val = irf["edisp"].evaluate(offset=offset, energy_true=energy, migra=1)
90
    assert_allclose(val.value, 0.04070749, rtol=1e-5)
91
    assert val.unit == ""
92
93
    val = irf["psf"].evaluate(
94
        rad=Quantity(0.1, "deg"), energy_true=energy, offset=offset
95
    )
96
    assert_allclose(val, 6.20107085 * u.Unit("deg-2"), rtol=1e-5)
97
98
    val = irf["bkg"].evaluate(energy=energy, fov_lon=offset, fov_lat="0 deg")
99
    assert_allclose(val.value, 5.43334659e-05, rtol=1e-5)
100
    assert val.unit == "1 / (MeV s sr)"
101
102
103 View Code Duplication
@requires_data()
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
104
def test_load_irf_dict_from_file():
105
    """Test that the IRF components in a dictionary loaded from a DL3 file can
106
    be loaded in a dictionary and correctly used"""
107
    irf = load_irf_dict_from_file(
108
        "$GAMMAPY_DATA/hess-dl3-dr1/data/hess_dl3_dr1_obs_id_020136.fits.gz"
109
    )
110
111
    energy = Quantity(1, "TeV")
112
    offset = Quantity(0.5, "deg")
113
114
    val = irf["aeff"].evaluate(energy_true=energy, offset=offset)
115
    assert_allclose(val.value, 273372.44851054, rtol=1e-5)
116
    assert val.unit == "m2"
117
118
    val = irf["edisp"].evaluate(offset=offset, energy_true=energy, migra=1)
119
    assert_allclose(val.value, 1.84269482, rtol=1e-5)
120
    assert val.unit == ""
121
122
    val = irf["psf"].evaluate(
123
        rad=Quantity(0.1, "deg"), energy_true=energy, offset=offset
124
    )
125
    assert_allclose(val, 6.75981573 * u.Unit("deg-2"), rtol=1e-5)
126
127
    val = irf["bkg"].evaluate(energy=energy, fov_lon=offset, fov_lat="0.1 deg")
128
    assert_allclose(val.value, 0.00031552, rtol=1e-5)
129
    assert val.unit == "1 / (MeV s sr)"
130
131
132
@requires_data()
133
def test_irf_dict_from_file_duplicate_irfs(caplog, tmp_path):
134
    """catch the warning message about two type of IRF with the same hdu class
135
    encountered in the same file"""
136
    original_file = make_path(
137
        "$GAMMAPY_DATA/hess-dl3-dr1/data/hess_dl3_dr1_obs_id_020136.fits.gz"
138
    )
139
    dummy_file = tmp_path / "020136_duplicated_psf.fits"
140
141
    # create a dummy file with the PSF HDU repeated twice
142
    f = fits.open(original_file)
143
    f.append(f[5].copy())
144
    f[7].name = "PSF2"
145
    f.writeto(dummy_file)
146
147
    load_irf_dict_from_file(dummy_file)
148
149
    assert "more than one HDU" in caplog.text
150
    assert "loaded the PSF HDU in the dictionary" in caplog.text
151
152
153
class TestIRFWrite:
154
    def setup(self):
155
        self.energy_lo = np.logspace(0, 1, 10)[:-1] * u.TeV
156
        self.energy_hi = np.logspace(0, 1, 10)[1:] * u.TeV
157
        self.energy_axis_true = MapAxis.from_energy_bounds(
158
            "1 TeV", "10 TeV", nbin=9, name="energy_true"
159
        )
160
161
        self.offset_lo = np.linspace(0, 1, 4)[:-1] * u.deg
162
        self.offset_hi = np.linspace(0, 1, 4)[1:] * u.deg
163
164
        self.offset_axis = MapAxis.from_bounds(
165
            0, 1, nbin=3, unit="deg", name="offset", node_type="edges"
166
        )
167
        self.migra_lo = np.linspace(0, 3, 4)[:-1]
168
        self.migra_hi = np.linspace(0, 3, 4)[1:]
169
        self.migra_axis = MapAxis.from_bounds(
170
            0, 3, nbin=3, name="migra", node_type="edges"
171
        )
172
        self.fov_lon_lo = np.linspace(-6, 6, 11)[:-1] * u.deg
173
        self.fov_lon_hi = np.linspace(-6, 6, 11)[1:] * u.deg
174
        self.fov_lon_axis = MapAxis.from_bounds(-6, 6, nbin=10, name="fov_lon")
175
176
        self.fov_lat_lo = np.linspace(-6, 6, 11)[:-1] * u.deg
177
        self.fov_lat_hi = np.linspace(-6, 6, 11)[1:] * u.deg
178
        self.fov_lat_axis = MapAxis.from_bounds(-6, 6, nbin=10, name="fov_lat")
179
180
        self.aeff_data = np.random.rand(9, 3) * u.cm * u.cm
181
        self.edisp_data = np.random.rand(9, 3, 3)
182
        self.bkg_data = np.random.rand(9, 10, 10) / u.MeV / u.s / u.sr
183
184
        self.aeff = EffectiveAreaTable2D(
185
            axes=[self.energy_axis_true, self.offset_axis],
186
            data=self.aeff_data.value,
187
            unit=self.aeff_data.unit,
188
        )
189
        self.edisp = EnergyDispersion2D(
190
            axes=[
191
                self.energy_axis_true,
192
                self.migra_axis,
193
                self.offset_axis,
194
            ],
195
            data=self.edisp_data,
196
        )
197
        axes = [
198
            self.energy_axis_true.copy(name="energy"),
199
            self.fov_lon_axis,
200
            self.fov_lat_axis,
201
        ]
202
        self.bkg = Background3D(
203
            axes=axes, data=self.bkg_data.value, unit=self.bkg_data.unit
204
        )
205
206
    def test_array_to_container(self):
207
        assert_allclose(self.aeff.quantity, self.aeff_data)
208
        assert_allclose(self.edisp.quantity, self.edisp_data)
209
        assert_allclose(self.bkg.quantity, self.bkg_data)
210
211
    def test_container_to_table(self):
212
        assert_allclose(self.aeff.to_table()["ENERG_LO"].quantity[0], self.energy_lo)
213
        assert_allclose(self.edisp.to_table()["ENERG_LO"].quantity[0], self.energy_lo)
214
        assert_allclose(self.bkg.to_table()["ENERG_LO"].quantity[0], self.energy_lo)
215
216
        assert_allclose(self.aeff.to_table()["EFFAREA"].quantity[0].T, self.aeff_data)
217
        assert_allclose(self.edisp.to_table()["MATRIX"].quantity[0].T, self.edisp_data)
218
        assert_allclose(self.bkg.to_table()["BKG"].quantity[0].T, self.bkg_data)
219
220
        assert self.aeff.to_table()["EFFAREA"].quantity[0].unit == self.aeff_data.unit
221
        assert self.bkg.to_table()["BKG"].quantity[0].unit == self.bkg_data.unit
222
223
    def test_container_to_fits(self):
224
        assert_allclose(self.aeff.to_table()["ENERG_LO"].quantity[0], self.energy_lo)
225
226
        assert self.aeff.to_table_hdu().header["EXTNAME"] == "EFFECTIVE AREA"
227
        assert self.edisp.to_table_hdu().header["EXTNAME"] == "ENERGY DISPERSION"
228
        assert self.bkg.to_table_hdu().header["EXTNAME"] == "BACKGROUND"
229
230
        hdu = self.aeff.to_table_hdu()
231
        assert_allclose(
232
            hdu.data[hdu.header["TTYPE1"]][0], self.aeff.axes[0].edges[:-1].value
233
        )
234
        hdu = self.aeff.to_table_hdu()
235
        assert_allclose(hdu.data[hdu.header["TTYPE5"]][0].T, self.aeff.data)
236
237
        hdu = self.edisp.to_table_hdu()
238
        assert_allclose(
239
            hdu.data[hdu.header["TTYPE1"]][0], self.edisp.axes[0].edges[:-1].value
240
        )
241
        hdu = self.edisp.to_table_hdu()
242
        assert_allclose(hdu.data[hdu.header["TTYPE7"]][0].T, self.edisp.data)
243
244
        hdu = self.bkg.to_table_hdu()
245
        assert_allclose(
246
            hdu.data[hdu.header["TTYPE1"]][0], self.bkg.axes[0].edges[:-1].value
247
        )
248
        hdu = self.bkg.to_table_hdu()
249
        assert_allclose(hdu.data[hdu.header["TTYPE7"]][0].T, self.bkg.data)
250
251
    def test_writeread(self, tmp_path):
252
        path = tmp_path / "tmp.fits"
253
        fits.HDUList(
254
            [
255
                fits.PrimaryHDU(),
256
                self.aeff.to_table_hdu(),
257
                self.edisp.to_table_hdu(),
258
                self.bkg.to_table_hdu(),
259
            ]
260
        ).writeto(path)
261
262
        read_aeff = EffectiveAreaTable2D.read(path, hdu="EFFECTIVE AREA")
263
        assert_allclose(read_aeff.quantity, self.aeff_data)
264
265
        read_edisp = EnergyDispersion2D.read(path, hdu="ENERGY DISPERSION")
266
        assert_allclose(read_edisp.quantity, self.edisp_data)
267
268
        read_bkg = Background3D.read(path, hdu="BACKGROUND")
269
        assert_allclose(read_bkg.quantity, self.bkg_data)
270