Mercurial > repos > astroteam > hess_astro_tool
comparison Spectrum_gammapy.py @ 0:02e4bb4fa10c draft
planemo upload for repository https://github.com/esg-epfl-apc/tools-astro/tree/main/tools commit 2991f65b25d4e6d1b69458603fce917adff40f94
author | astroteam |
---|---|
date | Mon, 19 Feb 2024 10:56:44 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:02e4bb4fa10c |
---|---|
1 #!/usr/bin/env python | |
2 # coding: utf-8 | |
3 | |
4 # flake8: noqa | |
5 | |
6 import json | |
7 import os | |
8 import shutil | |
9 | |
10 import astropy.units as u | |
11 import matplotlib.pyplot as plt | |
12 import numpy as np | |
13 from astropy.coordinates import Angle, SkyCoord | |
14 from astropy.time import Time | |
15 from gammapy.data import DataStore | |
16 from gammapy.datasets import ( | |
17 Datasets, | |
18 FluxPointsDataset, | |
19 SpectrumDataset, | |
20 SpectrumDatasetOnOff, | |
21 ) | |
22 from gammapy.makers import ( | |
23 ReflectedRegionsBackgroundMaker, | |
24 SafeMaskMaker, | |
25 SpectrumDatasetMaker, | |
26 ) | |
27 | |
28 # from gammapy.makers.utils import make_theta_squared_table | |
29 from gammapy.maps import MapAxis, RegionGeom, WcsGeom | |
30 from oda_api.data_products import ODAAstropyTable, PictureProduct | |
31 from oda_api.json import CustomJSONEncoder | |
32 from regions import CircleSkyRegion | |
33 | |
34 hess_data = "gammapy-datasets/1.1/hess-dl3-dr1/" | |
35 if not (os.path.exists(hess_data)): | |
36 get_ipython().system("gammapy download datasets") # noqa: F821 | |
37 | |
38 data_store = DataStore.from_dir(hess_data) | |
39 | |
40 # src_name='Crab' #http://odahub.io/ontology#AstrophysicalObject | |
41 # RA = 83.628700 # http://odahub.io/ontology#PointOfInterestRA | |
42 # DEC = 22.014700 # http://odahub.io/ontology#PointOfInterestDEC | |
43 src_name = "PKS 2155-304" | |
44 RA = 329.716938 # http://odahub.io/ontology#PointOfInterestRA | |
45 DEC = -30.225588 # http://odahub.io/ontology#PointOfInterestDEC | |
46 T1 = "2000-10-09T13:16:00.0" # http://odahub.io/ontology#StartTime | |
47 T2 = "2022-10-10T13:16:00.0" # http://odahub.io/ontology#EndTime | |
48 Radius = 2.5 # http://odahub.io/ontology#AngleDegrees | |
49 R_s = 0.5 # http://odahub.io/ontology#AngleDegrees | |
50 | |
51 Emin = 100.0 # http://odahub.io/ontology#Energy_GeV | |
52 Emax = 10000.0 # http://odahub.io/ontology#Energy_GeV | |
53 NEbins = 20 # http://odahub.io/ontology#Integer | |
54 | |
55 _galaxy_wd = os.getcwd() | |
56 | |
57 with open("inputs.json", "r") as fd: | |
58 inp_dic = json.load(fd) | |
59 if "_data_product" in inp_dic.keys(): | |
60 inp_pdic = inp_dic["_data_product"] | |
61 else: | |
62 inp_pdic = inp_dic | |
63 | |
64 for vn, vv in inp_pdic.items(): | |
65 if vn != "_selector": | |
66 globals()[vn] = type(globals()[vn])(vv) | |
67 | |
68 T1 = Time(T1, format="isot", scale="utc").mjd | |
69 T2 = Time(T2, format="isot", scale="utc").mjd | |
70 | |
71 dates1 = data_store.obs_table["DATE-OBS"] | |
72 dates2 = data_store.obs_table["DATE-END"] | |
73 times1 = data_store.obs_table["TIME-OBS"] | |
74 times2 = data_store.obs_table["TIME-END"] | |
75 OBSIDs = data_store.obs_table["OBS_ID"] | |
76 Tstart = [] | |
77 Tstop = [] | |
78 for i in range(len(dates1)): | |
79 Tstart.append( | |
80 Time(dates1[i] + "T" + times1[i], format="isot", scale="utc").mjd | |
81 ) | |
82 Tstop.append( | |
83 Time(dates2[i] + "T" + times2[i], format="isot", scale="utc").mjd | |
84 ) | |
85 | |
86 RA_pnts = np.array(data_store.obs_table["RA_PNT"]) | |
87 DEC_pnts = np.array(data_store.obs_table["DEC_PNT"]) | |
88 | |
89 Coords_s = SkyCoord(RA, DEC, unit="degree") | |
90 COORDS_pnts = SkyCoord(RA_pnts, DEC_pnts, unit="degree") | |
91 seps = COORDS_pnts.separation(Coords_s).deg | |
92 | |
93 mask = np.where((seps < Radius) & (Tstart > T1) & (Tstop < T2))[0] | |
94 OBSlist = [] | |
95 obs_ids = OBSIDs[mask] | |
96 if len(obs_ids) == 0: | |
97 message = "No data found" | |
98 raise RuntimeError("No data found") | |
99 obs_ids | |
100 | |
101 observations = data_store.get_observations(obs_ids) | |
102 | |
103 target_position = Coords_s | |
104 on_region_radius = Angle(str(R_s) + " deg") | |
105 on_region = CircleSkyRegion(center=target_position, radius=on_region_radius) | |
106 skydir = target_position.galactic | |
107 geom = WcsGeom.create( | |
108 npix=(150, 150), binsz=0.05, skydir=skydir, proj="TAN", frame="icrs" | |
109 ) | |
110 | |
111 Emin = 100.0 # http://odahub.io/ontology#Energy_GeV | |
112 Emax = 10000.0 # http://odahub.io/ontology#Energy_GeV | |
113 NEbins = 20 # http://odahub.io/ontology#Integer | |
114 | |
115 energy_axis = MapAxis.from_energy_bounds( | |
116 Emin * 1e-3, | |
117 Emax * 1e-3, | |
118 nbin=NEbins, | |
119 per_decade=True, | |
120 unit="TeV", | |
121 name="energy", | |
122 ) | |
123 energy_axis_true = MapAxis.from_energy_bounds( | |
124 0.05, 100, nbin=20, per_decade=True, unit="TeV", name="energy_true" | |
125 ) | |
126 | |
127 geom = RegionGeom.create(region=on_region, axes=[energy_axis]) | |
128 dataset_empty = SpectrumDataset.create( | |
129 geom=geom, energy_axis_true=energy_axis_true | |
130 ) | |
131 | |
132 dataset_maker = SpectrumDatasetMaker( | |
133 containment_correction=True, selection=["counts", "exposure", "edisp"] | |
134 ) | |
135 bkg_maker = ReflectedRegionsBackgroundMaker() | |
136 safe_mask_masker = SafeMaskMaker(methods=["aeff-max"], aeff_percent=10) | |
137 | |
138 datasets = Datasets() | |
139 | |
140 for obs_id, observation in zip(obs_ids, observations): | |
141 dataset = dataset_maker.run( | |
142 dataset_empty.copy(name=str(obs_id)), observation | |
143 ) | |
144 dataset_on_off = bkg_maker.run(dataset, observation) | |
145 # dataset_on_off = safe_mask_masker.run(dataset_on_off, observation) | |
146 datasets.append(dataset_on_off) | |
147 | |
148 print(datasets) | |
149 | |
150 from pathlib import Path | |
151 | |
152 path = Path("spectrum_analysis") | |
153 path.mkdir(exist_ok=True) | |
154 | |
155 for dataset in datasets: | |
156 dataset.write( | |
157 filename=path / f"obs_{dataset.name}.fits.gz", overwrite=True | |
158 ) | |
159 | |
160 datasets = Datasets() | |
161 | |
162 for obs_id in obs_ids: | |
163 filename = path / f"obs_{obs_id}.fits.gz" | |
164 datasets.append(SpectrumDatasetOnOff.read(filename)) | |
165 | |
166 from gammapy.modeling import Fit | |
167 from gammapy.modeling.models import ExpCutoffPowerLawSpectralModel, SkyModel | |
168 | |
169 spectral_model = ExpCutoffPowerLawSpectralModel( | |
170 amplitude=1e-12 * u.Unit("cm-2 s-1 TeV-1"), | |
171 index=2, | |
172 lambda_=0.1 * u.Unit("TeV-1"), | |
173 reference=1 * u.TeV, | |
174 ) | |
175 model = SkyModel(spectral_model=spectral_model, name="crab") | |
176 | |
177 datasets.models = [model] | |
178 | |
179 fit_joint = Fit() | |
180 result_joint = fit_joint.run(datasets=datasets) | |
181 | |
182 # we make a copy here to compare it later | |
183 model_best_joint = model.copy() | |
184 | |
185 print(result_joint) | |
186 | |
187 display(result_joint.models.to_parameters_table()) # noqa: F821 | |
188 | |
189 e_min, e_max = Emin * 1e-3, Emax * 1e-3 | |
190 energy_edges = np.geomspace(e_min, e_max, NEbins) * u.TeV | |
191 | |
192 from gammapy.estimators import FluxPointsEstimator | |
193 | |
194 fpe = FluxPointsEstimator( | |
195 energy_edges=energy_edges, source="crab", selection_optional="all" | |
196 ) | |
197 flux_points = fpe.run(datasets=datasets) | |
198 | |
199 flux_points_dataset = FluxPointsDataset( | |
200 data=flux_points, models=model_best_joint | |
201 ) | |
202 flux_points_dataset.plot_fit() | |
203 # plt.show() | |
204 plt.savefig("Spectrum.png", format="png", bbox_inches="tight") | |
205 | |
206 res = flux_points.to_table(sed_type="dnde", formatted=True) | |
207 np.array(res["dnde"]) | |
208 | |
209 bin_image = PictureProduct.from_file("Spectrum.png") | |
210 from astropy.table import Table | |
211 | |
212 Emean = np.array(res["e_ref"]) | |
213 Emin = np.array(res["e_min"]) | |
214 Emax = np.array(res["e_max"]) | |
215 flux = Emean**2 * np.array(res["dnde"]) | |
216 flux_err = Emean**2 * np.array(res["dnde_err"]) | |
217 data = [Emean, Emin, Emax, flux, flux_err] | |
218 names = ( | |
219 "Emean[TeV]", | |
220 "Emin[TeV]", | |
221 "Emax[TeV]", | |
222 "Flux[TeV/cm2s]", | |
223 "Flux_error[TeV/cm2s]", | |
224 ) | |
225 spec = ODAAstropyTable(Table(data, names=names)) | |
226 | |
227 picture_png = bin_image # http://odahub.io/ontology#ODAPictureProduct | |
228 spectrum_astropy_table = spec # http://odahub.io/ontology#ODAAstropyTable | |
229 | |
230 # output gathering | |
231 _galaxy_meta_data = {} | |
232 _oda_outs = [] | |
233 _oda_outs.append( | |
234 ( | |
235 "out_Spectrum_gammapy_picture_png", | |
236 "picture_png_galaxy.output", | |
237 picture_png, | |
238 ) | |
239 ) | |
240 _oda_outs.append( | |
241 ( | |
242 "out_Spectrum_gammapy_spectrum_astropy_table", | |
243 "spectrum_astropy_table_galaxy.output", | |
244 spectrum_astropy_table, | |
245 ) | |
246 ) | |
247 | |
248 for _outn, _outfn, _outv in _oda_outs: | |
249 _galaxy_outfile_name = os.path.join(_galaxy_wd, _outfn) | |
250 if isinstance(_outv, str) and os.path.isfile(_outv): | |
251 shutil.move(_outv, _galaxy_outfile_name) | |
252 _galaxy_meta_data[_outn] = {"ext": "_sniff_"} | |
253 elif getattr(_outv, "write_fits_file", None): | |
254 _outv.write_fits_file(_galaxy_outfile_name) | |
255 _galaxy_meta_data[_outn] = {"ext": "fits"} | |
256 elif getattr(_outv, "write_file", None): | |
257 _outv.write_file(_galaxy_outfile_name) | |
258 _galaxy_meta_data[_outn] = {"ext": "_sniff_"} | |
259 else: | |
260 with open(_galaxy_outfile_name, "w") as fd: | |
261 json.dump(_outv, fd, cls=CustomJSONEncoder) | |
262 _galaxy_meta_data[_outn] = {"ext": "json"} | |
263 | |
264 with open(os.path.join(_galaxy_wd, "galaxy.json"), "w") as fd: | |
265 json.dump(_galaxy_meta_data, fd) | |
266 print("*** Job finished successfully ***") |