jaxspec 0.0.3__py3-none-any.whl → 0.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jaxspec/data/example_data/fakeit.pha +335 -1
- jaxspec/data/obsconf.py +101 -71
- jaxspec/data/observation.py +24 -6
- jaxspec/data/util.py +17 -31
- jaxspec/model/additive.py +4 -5
- {jaxspec-0.0.3.dist-info → jaxspec-0.0.4.dist-info}/METADATA +5 -3
- {jaxspec-0.0.3.dist-info → jaxspec-0.0.4.dist-info}/RECORD +9 -9
- jaxspec/tables/apec.nc +0 -0
- {jaxspec-0.0.3.dist-info → jaxspec-0.0.4.dist-info}/LICENSE.md +0 -0
- {jaxspec-0.0.3.dist-info → jaxspec-0.0.4.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
SIMPLE = T / file does conform to FITS standard BITPIX = 8 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 12 / width of table in bytes NAXIS2 = 4096 / number of rows in table PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 4 / number of fields in each row TTYPE1 = 'CHANNEL ' / label for field 1 TFORM1 = 'J ' / data format of field: 4-byte INTEGER TTYPE2 = 'COUNTS ' / label for field 2 TFORM2 = 'J ' / data format of field: 4-byte INTEGER TTYPE3 = 'QUALITY ' / label for field 3 TFORM3 = 'I ' / data format of field: 2-byte INTEGER TTYPE4 = 'GROUPING' / label for field 4 TFORM4 = 'I ' / data format of field: 2-byte INTEGER EXTNAME = 'SPECTRUM' / name of this binary table extension HDUCLASS= 'OGIP ' / format conforms to OGIP standard HDUCLAS1= 'SPECTRUM' / PHA dataset (OGIP memo OGIP-92-007) HDUVERS = '1.2.1 ' / Version of format (OGIP memo OGIP-92-007a) TELESCOP= 'XMM ' / mission/satellite name INSTRUME= 'EPN ' / instrument name DETNAM = 'UNKNOWN ' / detector name FILTER = 'Medium ' / filter name STOKESPR= 'UNKNOWN ' / Stokes parameter(s) STOKESWT= 'UNKNOWN ' / Stokes weighting CHANTYPE= 'PI ' / channel type (PHA, PI etc) DATE = '2024-03-20T11:51:55' / file creation date (YYYY-MM-DDThh:mm:ss UT) HISTORY Fake data file created by XSPEC version: 12.13.1 "fakeit" command FKSRC001= 'cutoffpl' FKRSP001= 'PN.rmf ' FKARF001= 'PN.arf ' RESPFILE= 'PN.rmf ' / associated redistrib matrix filename ANCRFILE= 'PN.arf ' / associated ancillary response filename CORRFILE= ' ' / associated correction filename CORRSCAL= 1. / correction file scaling factor BACKFILE= ' ' / associated background filename EXPOSURE= 10000. / exposure (in seconds) TLMIN1 = 0 / Lowest legal channel number TLMAX1 = 4095 / Highest legal channel number DETCHANS= 4096 / total number possible channels POISSERR= T / Pois. err assumed ? AREASCAL= 1. / area scaling factor BACKSCAL= 1. / background file scaling factor END �!�x�����a��$8 0�
|
|
2
|
+
;{D-L�
|
|
3
|
+
�����������8������<��H�����������~�������#��|�����n�����������������/�������X��"��_��i��-�������Z��������������������N�����q��<�����q��������������_��������������������A�����������a��������Y��2�����n�����d��������!���?�_�` ��
|
|
4
|
+
���+�+
|
|
5
|
+
&�'��(��)��*�+�<,�-�Q.��/��0��1�02�3�4�^5��6�[7�8�(9�a:�H;~�<�=~>}??|c@|A|8B{�C{mDy�E{�F{HGyHymIy�JxtKy�LyMx�Nw�Ow�PxRQw�RxSvTv�UvtVu�WuXXv4Yu�ZuY[u�\u�]t�^t�_t,`s�ar�bqNcr�drBeq�fp�gpxhn�im�jm�kk�ll�mk�ni
|
|
6
|
+
oipg�qgUre�sd�tc�ub�v`�wa�x`�y`Oz^�{]�|]�}] ~]_\��[��]�\(�[��[F�Z��[�Z��Zn�ZH�Y��Y��X��YK�Y.�W��X�V��W��X�WN�X��W`�U��U��U��V�V&�U�T��T��T��Ty�T0�S�S�Sl�R'�R*�R��QZ�Q3�QA�P}�O��O��N��NR�L��L��K��K}�JN�I��H+�G,�F=�EI�E��D��C)�B,�Ap�@��?Z�=��=��<L�:��:X�9(�9 �7t�7��5�6��4��4#�3��3b�2{�2��2$�1��1q�0�/��/��0M�/��/|�0n�/��/��/��/5�/��/�.��/x�0,�0 �/�/��.��/��/D�.��/5�.��0�.��0,�/I�/e�/�/2�/d�/
|
|
7
|
+
.4-�-�
|
|
8
|
+
� ��!
|
|
9
|
+
�!� �� �� �� �� ���� 1� �� >� x� � � u� �� 9� A� *� /��� �� �T� � �����_�v���i�q���n�v���'���:�'��������&��}�lm����Z �
|
|
10
|
+
.d�
|
|
11
|
+
I��
|
|
12
|
+
!
|
|
13
|
+
�q3r
|
|
14
|
+
�stu
|
|
15
|
+
�vw
|
|
16
|
+
�x$y z
|
|
17
|
+
�{
|
|
18
|
+
�|
|
|
19
|
+
�}(~
|
|
20
|
+
o
|
|
21
|
+
��
|
|
22
|
+
f�
|
|
23
|
+
��
|
|
24
|
+
��
|
|
25
|
+
��
|
|
26
|
+
���
|
|
27
|
+
��
|
|
28
|
+
��
|
|
29
|
+
Y�
|
|
30
|
+
��
|
|
31
|
+
x�
|
|
32
|
+
t�
|
|
33
|
+
,�
|
|
34
|
+
i�
|
|
35
|
+
H�
|
|
36
|
+
+�
|
|
37
|
+
��
|
|
38
|
+
b�
|
|
39
|
+
u�
|
|
40
|
+
�
|
|
41
|
+
n�
|
|
42
|
+
*�
|
|
43
|
+
� ��
|
|
44
|
+
h�
|
|
45
|
+
� ��
|
|
46
|
+
�
|
|
47
|
+
�
|
|
48
|
+
� �� �� �� �� �� �� �� ��
|
|
49
|
+
"� �� W� �� �� �� �� `� l� 1� o� N� x� g� � I� i� C� 5� � �� =� <� j� %� i��� D� M� 1� <��� F������� L��������� ��� �[�x�����U���v���������=���p�I�]�0����:�}�������D���D�(����E����p�������"�����|���������������}� �
|
|
50
|
+
�D�
|
|
51
|
+
0�1�2�3�45�6�7�8�9�:�;�<�=�>S?~@�A�B�C�DpE]FLGVHvI"JsK�L�MZN�O�P.Q_R'SST�UxVWX�YWZ�[�\R]�^�_R`9ab!cd�e�f�g�h�i�j�k:lm�n�o�p�q�r�s�t�u�v�w�x�y�z�{�|�}�~�����������~���g�������F�I�^�p�i�V�R�\�s�U�*�E�v�1�p� �=���E�����=���#����������8�'�.�M�������������������������������������������������������h�������������������o�u�r�p���S�w�9�j�G�i��������!��R����T��Z�7�>�-�i� �5�����+�
|
|
52
|
+
��S���.�����;�360�� �
|
|
53
|
+
��
|
|
54
|
+
���
|
|
55
|
+
� � �
|
|
56
|
+
*
|
|
57
|
+
+
|
|
58
|
+
-
|
|
59
|
+
+
|
|
60
|
+
&
|
|
61
|
+
3
|
|
62
|
+
'
|
|
63
|
+
&
|
|
64
|
+
1
|
|
65
|
+
-
|
|
66
|
+
|
|
67
|
+
1
|
|
68
|
+
&
|
|
69
|
+
-
|
|
70
|
+
|
|
71
|
+
!
|
|
72
|
+
|
|
73
|
+
*
|
|
74
|
+
|
|
75
|
+
*
|
|
76
|
+
|
|
77
|
+
,
|
|
78
|
+
'
|
|
79
|
+
,
|
|
80
|
+
!
|
|
81
|
+
"
|
|
82
|
+
1
|
|
83
|
+
(
|
|
84
|
+
)
|
|
85
|
+
*
|
|
86
|
+
%
|
|
87
|
+
'
|
|
88
|
+
/
|
|
89
|
+
|
|
90
|
+
!,
|
|
91
|
+
",
|
|
92
|
+
#0
|
|
93
|
+
$)
|
|
94
|
+
%#
|
|
95
|
+
&
|
|
96
|
+
'
|
|
97
|
+
(,
|
|
98
|
+
)
|
|
99
|
+
*
|
|
100
|
+
+,
|
|
101
|
+
,
|
|
102
|
+
-'
|
|
103
|
+
.
|
|
104
|
+
/!
|
|
105
|
+
0
|
|
106
|
+
1&
|
|
107
|
+
2
|
|
108
|
+
3
|
|
109
|
+
4%
|
|
110
|
+
5
|
|
111
|
+
6#
|
|
112
|
+
7
|
|
113
|
+
8
|
|
114
|
+
9&
|
|
115
|
+
:
|
|
116
|
+
;
|
|
117
|
+
<
|
|
118
|
+
=
|
|
119
|
+
>%
|
|
120
|
+
?/
|
|
121
|
+
@
|
|
122
|
+
A"
|
|
123
|
+
B'
|
|
124
|
+
C'
|
|
125
|
+
D%
|
|
126
|
+
E
|
|
127
|
+
F
|
|
128
|
+
G
|
|
129
|
+
H(
|
|
130
|
+
I
|
|
131
|
+
J#
|
|
132
|
+
K
|
|
133
|
+
L
|
|
134
|
+
M-
|
|
135
|
+
N
|
|
136
|
+
O#
|
|
137
|
+
P
|
|
138
|
+
Q
|
|
139
|
+
R
|
|
140
|
+
S!
|
|
141
|
+
T
|
|
142
|
+
U
|
|
143
|
+
V%
|
|
144
|
+
W
|
|
145
|
+
X"
|
|
146
|
+
Y
|
|
147
|
+
Z
|
|
148
|
+
[
|
|
149
|
+
\
|
|
150
|
+
]
|
|
151
|
+
^
|
|
152
|
+
_
|
|
153
|
+
`
|
|
154
|
+
a
|
|
155
|
+
b
|
|
156
|
+
c
|
|
157
|
+
d
|
|
158
|
+
e
|
|
159
|
+
f
|
|
160
|
+
g
|
|
161
|
+
h
|
|
162
|
+
i
|
|
163
|
+
j
|
|
164
|
+
k
|
|
165
|
+
l
|
|
166
|
+
m
|
|
167
|
+
n
|
|
168
|
+
o
|
|
169
|
+
p
|
|
170
|
+
q
|
|
171
|
+
r
|
|
172
|
+
s
|
|
173
|
+
t
|
|
174
|
+
u
|
|
175
|
+
v
|
|
176
|
+
w
|
|
177
|
+
x
|
|
178
|
+
y
|
|
179
|
+
z
|
|
180
|
+
{
|
|
181
|
+
|
|
|
182
|
+
}
|
|
183
|
+
~
|
|
184
|
+
|
|
185
|
+
�
|
|
186
|
+
�
|
|
187
|
+
�
|
|
188
|
+
�
|
|
189
|
+
�
|
|
190
|
+
�
|
|
191
|
+
�
|
|
192
|
+
�
|
|
193
|
+
�
|
|
194
|
+
�
|
|
195
|
+
�
|
|
196
|
+
�
|
|
197
|
+
�
|
|
198
|
+
�
|
|
199
|
+
�
|
|
200
|
+
�
|
|
201
|
+
�
|
|
202
|
+
�
|
|
203
|
+
�
|
|
204
|
+
�
|
|
205
|
+
�
|
|
206
|
+
�
|
|
207
|
+
�
|
|
208
|
+
�
|
|
209
|
+
�
|
|
210
|
+
�
|
|
211
|
+
�
|
|
212
|
+
�
|
|
213
|
+
�
|
|
214
|
+
�
|
|
215
|
+
�
|
|
216
|
+
�
|
|
217
|
+
�
|
|
218
|
+
�
|
|
219
|
+
�
|
|
220
|
+
�
|
|
221
|
+
�
|
|
222
|
+
�
|
|
223
|
+
�
|
|
224
|
+
�
|
|
225
|
+
�
|
|
226
|
+
�
|
|
227
|
+
�
|
|
228
|
+
�
|
|
229
|
+
�
|
|
230
|
+
�
|
|
231
|
+
�
|
|
232
|
+
�
|
|
233
|
+
�
|
|
234
|
+
�
|
|
235
|
+
|
|
236
|
+
�
|
|
237
|
+
�
|
|
238
|
+
�
|
|
239
|
+
�
|
|
240
|
+
�
|
|
241
|
+
�
|
|
242
|
+
�
|
|
243
|
+
�
|
|
244
|
+
�
|
|
245
|
+
�
|
|
246
|
+
�
|
|
247
|
+
�
|
|
248
|
+
�
|
|
249
|
+
�
|
|
250
|
+
�
|
|
251
|
+
�
|
|
252
|
+
�
|
|
253
|
+
�
|
|
254
|
+
�
|
|
255
|
+
�
|
|
256
|
+
�
|
|
257
|
+
|
|
258
|
+
�
|
|
259
|
+
�
|
|
260
|
+
�
|
|
261
|
+
�
|
|
262
|
+
�
|
|
263
|
+
�
|
|
264
|
+
�
|
|
265
|
+
�
|
|
266
|
+
�
|
|
267
|
+
�
|
|
268
|
+
�
|
|
269
|
+
�
|
|
270
|
+
�
|
|
271
|
+
�
|
|
272
|
+
�
|
|
273
|
+
�
|
|
274
|
+
�
|
|
275
|
+
�
|
|
276
|
+
�
|
|
277
|
+
�
|
|
278
|
+
�
|
|
279
|
+
|
|
280
|
+
�
|
|
281
|
+
�
|
|
282
|
+
�
|
|
283
|
+
�
|
|
284
|
+
�
|
|
285
|
+
�
|
|
286
|
+
�
|
|
287
|
+
�
|
|
288
|
+
�
|
|
289
|
+
�
|
|
290
|
+
�
|
|
291
|
+
|
|
292
|
+
�
|
|
293
|
+
�
|
|
294
|
+
�
|
|
295
|
+
�
|
|
296
|
+
�
|
|
297
|
+
�
|
|
298
|
+
�
|
|
299
|
+
�
|
|
300
|
+
�
|
|
301
|
+
�
|
|
302
|
+
|
|
303
|
+
�
|
|
304
|
+
�
|
|
305
|
+
�
|
|
306
|
+
�
|
|
307
|
+
�
|
|
308
|
+
�
|
|
309
|
+
�
|
|
310
|
+
�
|
|
311
|
+
�
|
|
312
|
+
�
|
|
313
|
+
�
|
|
314
|
+
�
|
|
315
|
+
�
|
|
316
|
+
�
|
|
317
|
+
�
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
!
|
|
325
|
+
+ , -./ 01234 5 6789:;<=>?@ABCD
|
|
326
|
+
EFGH
|
|
327
|
+
IJKLMN OPQR
|
|
328
|
+
STUVWXY
|
|
329
|
+
Z[\]^_`abcdefghijklmnopqrstu
|
|
330
|
+
vwxyz{|}~������������������������������������ ��������������������������������������������������������������������������������������������
|
|
331
|
+
|
|
332
|
+
|
|
333
|
|
|
334
|
+
|
|
1
|
-
|
|
335
|
+
|
|
336
|
+
|
jaxspec/data/obsconf.py
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import xarray as xr
|
|
3
3
|
import sparse
|
|
4
|
+
import scipy
|
|
4
5
|
from .instrument import Instrument
|
|
5
6
|
from .observation import Observation
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
def densify_xarray(xarray):
|
|
9
|
-
return xr.DataArray(xarray.data.todense(), dims=xarray.dims, coords=xarray.coords, attrs=xarray.attrs, name=xarray.name)
|
|
10
|
-
|
|
11
|
-
|
|
12
9
|
class ObsConfiguration(xr.Dataset):
|
|
13
10
|
"""
|
|
14
11
|
Class to store the data of a folding model, which is the link between the unfolded and folded spectra.
|
|
@@ -56,8 +53,8 @@ class ObsConfiguration(xr.Dataset):
|
|
|
56
53
|
|
|
57
54
|
out_energies = np.stack(
|
|
58
55
|
(
|
|
59
|
-
np.asarray(self.coords["e_min_folded"].data
|
|
60
|
-
np.asarray(self.coords["e_max_folded"].data
|
|
56
|
+
np.asarray(self.coords["e_min_folded"].data, dtype=np.float64),
|
|
57
|
+
np.asarray(self.coords["e_max_folded"].data, dtype=np.float64),
|
|
61
58
|
)
|
|
62
59
|
)
|
|
63
60
|
|
|
@@ -67,34 +64,16 @@ class ObsConfiguration(xr.Dataset):
|
|
|
67
64
|
def from_pha_file(
|
|
68
65
|
cls, pha_path, rmf_path=None, arf_path=None, bkg_path=None, low_energy: float = 1e-20, high_energy: float = 1e20
|
|
69
66
|
):
|
|
70
|
-
from .util import
|
|
67
|
+
from .util import data_path_finder
|
|
71
68
|
|
|
72
|
-
|
|
69
|
+
arf_path_default, rmf_path_default, bkg_path_default = data_path_finder(pha_path)
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
rmf.energ_lo,
|
|
78
|
-
rmf.energ_hi,
|
|
79
|
-
rmf.e_min,
|
|
80
|
-
rmf.e_max,
|
|
81
|
-
)
|
|
71
|
+
arf_path = arf_path_default if arf_path is None else arf_path
|
|
72
|
+
rmf_path = rmf_path_default if rmf_path is None else rmf_path
|
|
73
|
+
bkg_path = bkg_path_default if bkg_path is None else bkg_path
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
else:
|
|
86
|
-
backratio = np.ones_like(pha.counts)
|
|
87
|
-
|
|
88
|
-
observation = Observation.from_matrix(
|
|
89
|
-
pha.counts,
|
|
90
|
-
pha.grouping,
|
|
91
|
-
pha.channel,
|
|
92
|
-
pha.quality,
|
|
93
|
-
pha.exposure,
|
|
94
|
-
background=bkg.counts if bkg is not None else None,
|
|
95
|
-
backratio=backratio,
|
|
96
|
-
attributes=metadata,
|
|
97
|
-
)
|
|
75
|
+
instrument = Instrument.from_ogip_file(rmf_path, arf_path=arf_path)
|
|
76
|
+
observation = Observation.from_pha_file(pha_path, bkg_path=bkg_path)
|
|
98
77
|
|
|
99
78
|
return cls.from_instrument(instrument, observation, low_energy=low_energy, high_energy=high_energy)
|
|
100
79
|
|
|
@@ -102,57 +81,108 @@ class ObsConfiguration(xr.Dataset):
|
|
|
102
81
|
def from_instrument(
|
|
103
82
|
cls, instrument: Instrument, observation: Observation, low_energy: float = 1e-20, high_energy: float = 1e20
|
|
104
83
|
):
|
|
105
|
-
#
|
|
106
|
-
|
|
107
|
-
|
|
84
|
+
# First we unpack all the xarray data to classical np array for efficiency
|
|
85
|
+
# We also exclude the bins that are flagged with bad quality on the instrument
|
|
86
|
+
quality_filter = observation.quality.data == 0
|
|
87
|
+
grouping = scipy.sparse.csr_array(observation.grouping.data.to_scipy_sparse()) * quality_filter
|
|
88
|
+
e_min_channel = instrument.coords["e_min_channel"].data
|
|
89
|
+
e_max_channel = instrument.coords["e_max_channel"].data
|
|
90
|
+
e_min_unfolded = instrument.coords["e_min_unfolded"].data
|
|
91
|
+
e_max_unfolded = instrument.coords["e_max_unfolded"].data
|
|
92
|
+
redistribution = scipy.sparse.csr_array(instrument.redistribution.data.to_scipy_sparse())
|
|
93
|
+
area = instrument.area.data
|
|
94
|
+
exposure = observation.exposure.data
|
|
108
95
|
|
|
109
96
|
# Computing the lower and upper energies of the bins after grouping
|
|
110
97
|
# This is just a trick to compute it without 10 lines of code
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
)
|
|
98
|
+
grouping_nan = observation.grouping.data * quality_filter
|
|
99
|
+
grouping_nan.fill_value = np.nan
|
|
100
|
+
e_min = sparse.nanmin(grouping_nan * e_min_channel, axis=1).todense()
|
|
101
|
+
e_max = sparse.nanmax(grouping_nan * e_max_channel, axis=1).todense()
|
|
114
102
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
transfer_matrix = grouping @ (instrument.redistribution * instrument.area * observation.exposure)
|
|
120
|
-
transfer_matrix = transfer_matrix.assign_coords({"e_min_folded": e_min, "e_max_folded": e_max})
|
|
103
|
+
# Compute the transfer matrix
|
|
104
|
+
transfer_matrix = grouping @ (redistribution * area * exposure)
|
|
121
105
|
|
|
122
106
|
# Exclude bins out of the considered energy range, and bins without contribution from the RMF
|
|
123
|
-
row_idx = densify_xarray(((e_min > low_energy) & (e_max < high_energy)) * (grouping.sum(dim="instrument_channel") > 0))
|
|
124
|
-
|
|
125
|
-
col_idx = densify_xarray(
|
|
126
|
-
(instrument.coords["e_min_unfolded"] > 0) * (instrument.redistribution.sum(dim="instrument_channel") > 0)
|
|
127
|
-
)
|
|
128
107
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
transfer_matrix_reduced = transfer_matrix_scipy[row_idx.data][:, col_idx.data]
|
|
132
|
-
transfer_matrix_reduced = sparse.COO.from_scipy_sparse(transfer_matrix_reduced)
|
|
108
|
+
row_idx = (e_min > low_energy) & (e_max < high_energy) & (grouping.sum(axis=1) > 0)
|
|
109
|
+
col_idx = (e_min_unfolded > 0) & (redistribution.sum(axis=0) > 0)
|
|
133
110
|
|
|
134
|
-
#
|
|
135
|
-
transfer_matrix
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
111
|
+
# Apply this reduction to all the relevant arrays
|
|
112
|
+
transfer_matrix = sparse.COO.from_scipy_sparse(transfer_matrix[row_idx][:, col_idx])
|
|
113
|
+
folded_counts = observation.folded_counts.data[row_idx]
|
|
114
|
+
folded_backratio = observation.folded_backratio.data[row_idx]
|
|
115
|
+
area = instrument.area.data[col_idx]
|
|
116
|
+
e_min_folded = e_min[row_idx]
|
|
117
|
+
e_max_folded = e_max[row_idx]
|
|
118
|
+
e_min_unfolded = e_min_unfolded[col_idx]
|
|
119
|
+
e_max_unfolded = e_max_unfolded[col_idx]
|
|
142
120
|
|
|
143
121
|
if observation.folded_background is not None:
|
|
144
|
-
folded_background = observation.folded_background.
|
|
145
|
-
|
|
122
|
+
folded_background = observation.folded_background.data[row_idx]
|
|
146
123
|
else:
|
|
147
|
-
folded_background =
|
|
124
|
+
folded_background = np.zeros_like(folded_counts)
|
|
125
|
+
|
|
126
|
+
data_dict = {
|
|
127
|
+
"transfer_matrix": (
|
|
128
|
+
["folded_channel", "unfolded_channel"],
|
|
129
|
+
transfer_matrix,
|
|
130
|
+
{
|
|
131
|
+
"description": "Transfer matrix to use to fold the incoming spectrum. It is built and restricted using the grouping, redistribution matrix, effective area, quality flags and energy bands defined by the user."
|
|
132
|
+
},
|
|
133
|
+
),
|
|
134
|
+
"area": (
|
|
135
|
+
["unfolded_channel"],
|
|
136
|
+
area,
|
|
137
|
+
{"description": "Effective area with the same restrictions as the transfer matrix.", "units": "cm^2"},
|
|
138
|
+
),
|
|
139
|
+
"exposure": ([], exposure, {"description": "Total exposure", "unit": "s"}),
|
|
140
|
+
"folded_counts": (
|
|
141
|
+
["folded_channel"],
|
|
142
|
+
folded_counts,
|
|
143
|
+
{
|
|
144
|
+
"description": "Folded counts after grouping, with the same restrictions as the transfer matrix.",
|
|
145
|
+
"unit": "photons",
|
|
146
|
+
},
|
|
147
|
+
),
|
|
148
|
+
"folded_backratio": (
|
|
149
|
+
["folded_channel"],
|
|
150
|
+
folded_backratio,
|
|
151
|
+
{"description": "Background scaling after grouping, with the same restrictions as the transfer matrix."},
|
|
152
|
+
),
|
|
153
|
+
"folded_background": (
|
|
154
|
+
["folded_channel"],
|
|
155
|
+
folded_background,
|
|
156
|
+
{
|
|
157
|
+
"description": "Folded background counts after grouping, with the same restrictions as the transfer matrix.",
|
|
158
|
+
"unit": "photons",
|
|
159
|
+
},
|
|
160
|
+
),
|
|
161
|
+
}
|
|
148
162
|
|
|
149
163
|
return cls(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
164
|
+
data_dict,
|
|
165
|
+
coords={
|
|
166
|
+
"e_min_folded": (
|
|
167
|
+
["folded_channel"],
|
|
168
|
+
e_min_folded,
|
|
169
|
+
{"description": "Low energy of folded channel"},
|
|
170
|
+
),
|
|
171
|
+
"e_max_folded": (
|
|
172
|
+
["folded_channel"],
|
|
173
|
+
e_max_folded,
|
|
174
|
+
{"description": "High energy of folded channel"},
|
|
175
|
+
),
|
|
176
|
+
"e_min_unfolded": (
|
|
177
|
+
["unfolded_channel"],
|
|
178
|
+
e_min_unfolded,
|
|
179
|
+
{"description": "Low energy of unfolded channel"},
|
|
180
|
+
),
|
|
181
|
+
"e_max_unfolded": (
|
|
182
|
+
["unfolded_channel"],
|
|
183
|
+
e_max_unfolded,
|
|
184
|
+
{"description": "High energy of unfolded channel"},
|
|
185
|
+
),
|
|
186
|
+
},
|
|
187
|
+
attrs=observation.attrs | instrument.attrs,
|
|
158
188
|
)
|
jaxspec/data/observation.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import numpy as np
|
|
3
2
|
import xarray as xr
|
|
3
|
+
from .ogip import DataPHA
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class Observation(xr.Dataset):
|
|
@@ -95,11 +95,7 @@ class Observation(xr.Dataset):
|
|
|
95
95
|
)
|
|
96
96
|
|
|
97
97
|
@classmethod
|
|
98
|
-
def
|
|
99
|
-
from .util import data_loader
|
|
100
|
-
|
|
101
|
-
pha, arf, rmf, bkg, metadata = data_loader(pha_file)
|
|
102
|
-
|
|
98
|
+
def from_ogip_container(cls, pha: DataPHA, bkg: DataPHA | None = None, **metadata):
|
|
103
99
|
if bkg is not None:
|
|
104
100
|
backratio = np.nan_to_num((pha.backscal * pha.exposure * pha.areascal) / (bkg.backscal * bkg.exposure * bkg.areascal))
|
|
105
101
|
else:
|
|
@@ -116,6 +112,28 @@ class Observation(xr.Dataset):
|
|
|
116
112
|
attributes=metadata,
|
|
117
113
|
)
|
|
118
114
|
|
|
115
|
+
@classmethod
|
|
116
|
+
def from_pha_file(cls, pha_path: str, bkg_path: str | None = None, **metadata):
|
|
117
|
+
from .util import data_path_finder
|
|
118
|
+
|
|
119
|
+
arf_path, rmf_path, bkg_path_default = data_path_finder(pha_path)
|
|
120
|
+
bkg_path = bkg_path_default if bkg_path is None else bkg_path
|
|
121
|
+
|
|
122
|
+
pha = DataPHA.from_file(pha_path)
|
|
123
|
+
bkg = DataPHA.from_file(bkg_path) if bkg_path is not None else None
|
|
124
|
+
|
|
125
|
+
if metadata is None:
|
|
126
|
+
metadata = {}
|
|
127
|
+
|
|
128
|
+
metadata.update(
|
|
129
|
+
observation_file=pha_path,
|
|
130
|
+
background_file=bkg_path,
|
|
131
|
+
response_matrix_file=rmf_path,
|
|
132
|
+
ancillary_response_file=arf_path,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
return cls.from_ogip_container(pha, bkg=bkg, **metadata)
|
|
136
|
+
|
|
119
137
|
def plot_counts(self, **kwargs):
|
|
120
138
|
"""
|
|
121
139
|
Plot the counts
|
jaxspec/data/util.py
CHANGED
|
@@ -6,9 +6,9 @@ import haiku as hk
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from numpy.typing import ArrayLike
|
|
8
8
|
from collections.abc import Mapping
|
|
9
|
-
from typing import TypeVar
|
|
9
|
+
from typing import TypeVar, Tuple
|
|
10
|
+
from astropy.io import fits
|
|
10
11
|
|
|
11
|
-
from .ogip import DataPHA, DataARF, DataRMF
|
|
12
12
|
from . import Observation, Instrument, ObsConfiguration
|
|
13
13
|
from ..model.abc import SpectralModel
|
|
14
14
|
from ..fit import CountForwardModel
|
|
@@ -201,46 +201,32 @@ def fakeit_for_multiple_parameters(
|
|
|
201
201
|
return fakeits[0] if len(fakeits) == 1 else fakeits
|
|
202
202
|
|
|
203
203
|
|
|
204
|
-
def
|
|
204
|
+
def data_path_finder(pha_path: str) -> Tuple[str | None, str | None, str | None]:
|
|
205
205
|
"""
|
|
206
|
-
This function
|
|
207
|
-
from a given PHA file, using either the ARF/RMF/BKG filenames in the header or the
|
|
208
|
-
specified filenames overwritten by the user.
|
|
209
|
-
|
|
206
|
+
This function tries its best to find the ARF, RMF and BKG files associated with a given PHA file.
|
|
210
207
|
Parameters:
|
|
211
208
|
pha_path: The PHA file path.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
212
211
|
arf_path: The ARF file path.
|
|
213
212
|
rmf_path: The RMF file path.
|
|
214
213
|
bkg_path: The BKG file path.
|
|
215
214
|
"""
|
|
216
215
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
arf_path = find_file_or_compressed_in_dir(pha.ancrfile, directory)
|
|
223
|
-
|
|
224
|
-
if rmf_path is None:
|
|
225
|
-
if pha.respfile != "none" and pha.respfile != "":
|
|
226
|
-
rmf_path = find_file_or_compressed_in_dir(pha.respfile, directory)
|
|
227
|
-
|
|
228
|
-
if bkg_path is None:
|
|
229
|
-
if pha.backfile.lower() != "none" and pha.backfile != "":
|
|
230
|
-
bkg_path = find_file_or_compressed_in_dir(pha.backfile, directory)
|
|
216
|
+
def find_path(file_name: str, directory: str) -> str | None:
|
|
217
|
+
if file_name.lower() != "none" and file_name != "":
|
|
218
|
+
return find_file_or_compressed_in_dir(file_name, directory)
|
|
219
|
+
else:
|
|
220
|
+
return None
|
|
231
221
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
bkg = DataPHA.from_file(bkg_path) if bkg_path is not None else None
|
|
222
|
+
header = fits.getheader(pha_path, "SPECTRUM")
|
|
223
|
+
directory = str(Path(pha_path).parent)
|
|
235
224
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
"response_matrix_file": rmf_path,
|
|
240
|
-
"ancillary_response_file": arf_path,
|
|
241
|
-
}
|
|
225
|
+
arf_path = find_path(header.get("ANCRFILE", "none"), directory)
|
|
226
|
+
rmf_path = find_path(header.get("RESPFILE", "none"), directory)
|
|
227
|
+
bkg_path = find_path(header.get("BACKFILE", "none"), directory)
|
|
242
228
|
|
|
243
|
-
return
|
|
229
|
+
return arf_path, rmf_path, bkg_path
|
|
244
230
|
|
|
245
231
|
|
|
246
232
|
def find_file_or_compressed_in_dir(path: str | Path, directory: str | Path) -> str:
|
jaxspec/model/additive.py
CHANGED
|
@@ -364,18 +364,17 @@ class Diskbb(AdditiveComponent):
|
|
|
364
364
|
`Diskpbb` with $p=0.75$
|
|
365
365
|
|
|
366
366
|
??? abstract "Parameters"
|
|
367
|
+
* $T_{\text{in}}$ : Temperature at inner disk radius $\left[ \mathrm{keV}\right]$
|
|
367
368
|
* $\text{norm}$ : $\cos i(r_{\text{in}}/d)^{2}$,
|
|
368
369
|
where $r_{\text{in}}$ is "an apparent" inner disk radius $\left[\text{km}\right]$,
|
|
369
|
-
|
|
370
|
-
* $i$ the angle of the disk ($i=0$ is face-on)
|
|
371
|
-
* $T_{\text{in}}$ : Temperature at inner disk radius $\left[ \mathrm{keV}\right]$
|
|
370
|
+
$d$ the distance to the source in units of $10 \text{kpc}$, $i$ the angle of the disk ($i=0$ is face-on)
|
|
372
371
|
"""
|
|
373
372
|
|
|
374
373
|
def continuum(self, energy):
|
|
375
|
-
norm = hk.get_parameter("norm", [], init=HaikuConstant(1))
|
|
376
374
|
p = 0.75
|
|
377
|
-
tin = hk.get_parameter("Tin", [], init=HaikuConstant(1))
|
|
378
375
|
tout = 0.0
|
|
376
|
+
tin = hk.get_parameter("Tin", [], init=HaikuConstant(1))
|
|
377
|
+
norm = hk.get_parameter("norm", [], init=HaikuConstant(1))
|
|
379
378
|
|
|
380
379
|
# Tout is set to 0 as it is evaluated at R=infinity
|
|
381
380
|
def integrand(kT, e, tin, p):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jaxspec
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: jaxspec is a bayesian spectral fitting library for X-ray astronomy.
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: sdupourque
|
|
@@ -10,7 +10,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
-
Requires-Dist: arviz (>=0.17.
|
|
13
|
+
Requires-Dist: arviz (>=0.17.1,<0.18.0)
|
|
14
14
|
Requires-Dist: astropy (>=6.0.0,<7.0.0)
|
|
15
15
|
Requires-Dist: chainconsumer (>=1.0.0,<2.0.0)
|
|
16
16
|
Requires-Dist: cmasher (>=1.6.3,<2.0.0)
|
|
@@ -25,6 +25,7 @@ Requires-Dist: networkx (>=3.1,<4.0)
|
|
|
25
25
|
Requires-Dist: numpy (>=1.26.1,<2.0.0)
|
|
26
26
|
Requires-Dist: numpyro (>=0.13.2,<0.15.0)
|
|
27
27
|
Requires-Dist: pandas (>=2.2.0,<3.0.0)
|
|
28
|
+
Requires-Dist: scipy (<1.13)
|
|
28
29
|
Requires-Dist: seaborn (>=0.13.1,<0.14.0)
|
|
29
30
|
Requires-Dist: simpleeval (>=0.9.13,<0.10.0)
|
|
30
31
|
Requires-Dist: sparse (>=0.15.1,<0.16.0)
|
|
@@ -33,8 +34,9 @@ Description-Content-Type: text/markdown
|
|
|
33
34
|
|
|
34
35
|
# jaxspec
|
|
35
36
|
|
|
36
|
-
[)](https://pypi.org/project/jaxspec/)
|
|
37
38
|
[](https://pypi.org/project/jaxspec/)
|
|
39
|
+
[](https://jaxspec.readthedocs.io/en/latest/)
|
|
38
40
|
[](https://app.codecov.io/gh/renecotyfanboy/jaxspec)
|
|
39
41
|
[](https://join.slack.com/t/jaxspec/shared_invite/zt-2cuxkdl2f-t0EEAKP~HBEHKvIUZJL2sg)
|
|
40
42
|
|
|
@@ -18,26 +18,26 @@ jaxspec/data/example_data/PN.pha,sha256=qYXgYHa_Bg06UzHyBBOvqSCKjXcfpsZx6JGKGGBX
|
|
|
18
18
|
jaxspec/data/example_data/PN.rmf,sha256=kbqe-C2oufc-anmd_gl7h8aKcCCsbFqg3NQGe_nLQoc,3962880
|
|
19
19
|
jaxspec/data/example_data/PN_spectrum_grp20.fits,sha256=qYXgYHa_Bg06UzHyBBOvqSCKjXcfpsZx6JGKGGBXfJA,138240
|
|
20
20
|
jaxspec/data/example_data/PNbackground_spectrum.fits,sha256=VeAX4MGbMkJF_vBJ3_KnouSbmjkWZ8qcT2Z8T2g7H0k,120960
|
|
21
|
+
jaxspec/data/example_data/fakeit.pha,sha256=IhkeWkE-b3ELECd_Uasjo9h3cXgcjCYH20wDpXJ8LMk,60480
|
|
21
22
|
jaxspec/data/grouping.py,sha256=hhgBt-voiH0DDSyePacaIGsaMnrYbJM_-ZeU66keC7I,622
|
|
22
23
|
jaxspec/data/instrument.py,sha256=0Ef3zhNT7ca-nHtRCGKXpbkyXpgVVpNtO8_XrMGWnyU,3984
|
|
23
|
-
jaxspec/data/obsconf.py,sha256=
|
|
24
|
-
jaxspec/data/observation.py,sha256=
|
|
24
|
+
jaxspec/data/obsconf.py,sha256=tnXCXim6eBjZbvNbx2ViRJ3wzQhNacXRcCrLZlPTdY0,7378
|
|
25
|
+
jaxspec/data/observation.py,sha256=1UnFu5ihZp9z-vP_I7tsFY8jhhIJunv46JyuE-acrg0,6394
|
|
25
26
|
jaxspec/data/ogip.py,sha256=d0OEEkznA7s8xPkqPrnfIvedTdIRsQuBnRK4wHoQ17M,8793
|
|
26
|
-
jaxspec/data/util.py,sha256=
|
|
27
|
+
jaxspec/data/util.py,sha256=BsIVpmx2kAvAn-w6uSjC793OmPAfmDKMGGLDuk9yztY,7923
|
|
27
28
|
jaxspec/fit.py,sha256=FhnedL7-_9eovErw2SESH5sbMhU-qJNdkqxkoVsLglo,9531
|
|
28
29
|
jaxspec/model/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
29
30
|
jaxspec/model/abc.py,sha256=O5DwgcXWfuGSYxTk_TmZcZXak1lLuEvBzJXUTd3E9tE,17851
|
|
30
|
-
jaxspec/model/additive.py,sha256=
|
|
31
|
+
jaxspec/model/additive.py,sha256=iu_n820tOdKbG5BKsFM-nVOa2_sKPWBSQ_TKS1bljSk,18656
|
|
31
32
|
jaxspec/model/background.py,sha256=zej99rVfcRb75T85o3u4qeYQIgnFwGtxK8niZJ8S5mM,6872
|
|
32
33
|
jaxspec/model/list.py,sha256=0RPAoscVz_zM1CWdx_Gd5wfrQWV5Nv4Kd4bSXu2ayUA,860
|
|
33
34
|
jaxspec/model/multiplicative.py,sha256=sAKDkiplhdY7TsaPk7gwkR18dcXmU2nytgBCiHNBPMk,7537
|
|
34
|
-
jaxspec/tables/apec.nc,sha256=JVsjJt2q0QwwDaEMpgeqA2RPCzxO2vVV6F7npk_Haec,74780226
|
|
35
35
|
jaxspec/tables/xsect_phabs_aspl.fits,sha256=Pq_7oqYuOmEeCk4f9KVzQtfVdvAj17u2MnENx1uaUBk,86400
|
|
36
36
|
jaxspec/tables/xsect_tbabs_wilm.fits,sha256=PPReRcnWccTE_BKDFLfDposw8Jbu3ms-sIv1UiSkSTU,86400
|
|
37
37
|
jaxspec/tables/xsect_wabs_angr.fits,sha256=mzBzpHejC1LiB_LEv3mvxq4Zq7qPIHGQrExpcCT3QHM,86400
|
|
38
38
|
jaxspec/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
39
|
jaxspec/util/integrate.py,sha256=6oGYhRTevgOo47hbzdcomOCShC2cpKgF8AP7bkx-Zsw,4379
|
|
40
|
-
jaxspec-0.0.
|
|
41
|
-
jaxspec-0.0.
|
|
42
|
-
jaxspec-0.0.
|
|
43
|
-
jaxspec-0.0.
|
|
40
|
+
jaxspec-0.0.4.dist-info/LICENSE.md,sha256=2q5XoWzddts5IqzIcgYYMOL21puU3MfO8gvT3Ype1eQ,1073
|
|
41
|
+
jaxspec-0.0.4.dist-info/METADATA,sha256=JSU_vEIQjYwXmTQBXPrXL4ZC8Xfg3s60ktPDmBoB_3E,3194
|
|
42
|
+
jaxspec-0.0.4.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
|
|
43
|
+
jaxspec-0.0.4.dist-info/RECORD,,
|
jaxspec/tables/apec.nc
DELETED
|
Binary file
|
|
File without changes
|
|
File without changes
|