jaxspec 0.0.5__py3-none-any.whl → 0.0.7__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/analysis/results.py +250 -121
- jaxspec/data/__init__.py +4 -4
- jaxspec/data/obsconf.py +53 -8
- jaxspec/data/util.py +29 -20
- jaxspec/fit.py +329 -81
- jaxspec/model/__init__.py +0 -1
- jaxspec/model/_additive/apec.py +56 -117
- jaxspec/model/_additive/apec_loaders.py +42 -59
- jaxspec/model/additive.py +27 -13
- jaxspec/model/background.py +50 -16
- jaxspec/model/multiplicative.py +20 -25
- jaxspec/util/__init__.py +45 -0
- jaxspec/util/abundance.py +5 -3
- jaxspec/util/online_storage.py +15 -0
- jaxspec/util/typing.py +43 -0
- {jaxspec-0.0.5.dist-info → jaxspec-0.0.7.dist-info}/METADATA +12 -9
- {jaxspec-0.0.5.dist-info → jaxspec-0.0.7.dist-info}/RECORD +19 -22
- jaxspec/tables/abundances.dat +0 -31
- jaxspec/tables/new_apec.nc +0 -0
- jaxspec/tables/xsect_phabs_aspl.fits +0 -0
- jaxspec/tables/xsect_tbabs_wilm.fits +0 -0
- jaxspec/tables/xsect_wabs_angr.fits +0 -0
- {jaxspec-0.0.5.dist-info → jaxspec-0.0.7.dist-info}/LICENSE.md +0 -0
- {jaxspec-0.0.5.dist-info → jaxspec-0.0.7.dist-info}/WHEEL +0 -0
jaxspec/data/obsconf.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
-
import xarray as xr
|
|
3
|
-
import sparse
|
|
4
2
|
import scipy
|
|
3
|
+
import sparse
|
|
4
|
+
import xarray as xr
|
|
5
|
+
|
|
5
6
|
from .instrument import Instrument
|
|
6
7
|
from .observation import Observation
|
|
7
8
|
|
|
@@ -62,8 +63,26 @@ class ObsConfiguration(xr.Dataset):
|
|
|
62
63
|
|
|
63
64
|
@classmethod
|
|
64
65
|
def from_pha_file(
|
|
65
|
-
cls,
|
|
66
|
+
cls,
|
|
67
|
+
pha_path,
|
|
68
|
+
rmf_path: str | None = None,
|
|
69
|
+
arf_path: str | None = None,
|
|
70
|
+
bkg_path: str | None = None,
|
|
71
|
+
low_energy: float = 1e-20,
|
|
72
|
+
high_energy: float = 1e20,
|
|
66
73
|
):
|
|
74
|
+
r"""
|
|
75
|
+
Build the observation configuration from a PHA file.
|
|
76
|
+
|
|
77
|
+
Parameters:
|
|
78
|
+
pha_path: The path to the PHA file.
|
|
79
|
+
rmf_path: The path to the RMF file.
|
|
80
|
+
arf_path: The path to the ARF file.
|
|
81
|
+
bkg_path: The path to the background file.
|
|
82
|
+
low_energy: The lower bound of the energy range to consider.
|
|
83
|
+
high_energy: The upper bound of the energy range to consider.
|
|
84
|
+
"""
|
|
85
|
+
|
|
67
86
|
from .util import data_path_finder
|
|
68
87
|
|
|
69
88
|
arf_path_default, rmf_path_default, bkg_path_default = data_path_finder(pha_path)
|
|
@@ -75,16 +94,34 @@ class ObsConfiguration(xr.Dataset):
|
|
|
75
94
|
instrument = Instrument.from_ogip_file(rmf_path, arf_path=arf_path)
|
|
76
95
|
observation = Observation.from_pha_file(pha_path, bkg_path=bkg_path)
|
|
77
96
|
|
|
78
|
-
return cls.from_instrument(
|
|
97
|
+
return cls.from_instrument(
|
|
98
|
+
instrument, observation, low_energy=low_energy, high_energy=high_energy
|
|
99
|
+
)
|
|
79
100
|
|
|
80
101
|
@classmethod
|
|
81
102
|
def from_instrument(
|
|
82
|
-
cls,
|
|
103
|
+
cls,
|
|
104
|
+
instrument: Instrument,
|
|
105
|
+
observation: Observation,
|
|
106
|
+
low_energy: float = 1e-20,
|
|
107
|
+
high_energy: float = 1e20,
|
|
83
108
|
):
|
|
109
|
+
r"""
|
|
110
|
+
Build the observation configuration from an [`Instrument`][jaxspec.data.Instrument] and an [`Observation`][jaxspec.data.Observation] object.
|
|
111
|
+
|
|
112
|
+
Parameters:
|
|
113
|
+
instrument: The instrument object.
|
|
114
|
+
observation: The observation object.
|
|
115
|
+
low_energy: The lower bound of the energy range to consider.
|
|
116
|
+
high_energy: The upper bound of the energy range to consider.
|
|
117
|
+
|
|
118
|
+
"""
|
|
84
119
|
# First we unpack all the xarray data to classical np array for efficiency
|
|
85
120
|
# We also exclude the bins that are flagged with bad quality on the instrument
|
|
86
121
|
quality_filter = observation.quality.data == 0
|
|
87
|
-
grouping =
|
|
122
|
+
grouping = (
|
|
123
|
+
scipy.sparse.csr_array(observation.grouping.data.to_scipy_sparse()) * quality_filter
|
|
124
|
+
)
|
|
88
125
|
e_min_channel = instrument.coords["e_min_channel"].data
|
|
89
126
|
e_max_channel = instrument.coords["e_max_channel"].data
|
|
90
127
|
e_min_unfolded = instrument.coords["e_min_unfolded"].data
|
|
@@ -134,7 +171,10 @@ class ObsConfiguration(xr.Dataset):
|
|
|
134
171
|
"area": (
|
|
135
172
|
["unfolded_channel"],
|
|
136
173
|
area,
|
|
137
|
-
{
|
|
174
|
+
{
|
|
175
|
+
"description": "Effective area with the same restrictions as the transfer matrix.",
|
|
176
|
+
"units": "cm^2",
|
|
177
|
+
},
|
|
138
178
|
),
|
|
139
179
|
"exposure": ([], exposure, {"description": "Total exposure", "unit": "s"}),
|
|
140
180
|
"folded_counts": (
|
|
@@ -148,7 +188,9 @@ class ObsConfiguration(xr.Dataset):
|
|
|
148
188
|
"folded_backratio": (
|
|
149
189
|
["folded_channel"],
|
|
150
190
|
folded_backratio,
|
|
151
|
-
{
|
|
191
|
+
{
|
|
192
|
+
"description": "Background scaling after grouping, with the same restrictions as the transfer matrix."
|
|
193
|
+
},
|
|
152
194
|
),
|
|
153
195
|
"folded_background": (
|
|
154
196
|
["folded_channel"],
|
|
@@ -186,3 +228,6 @@ class ObsConfiguration(xr.Dataset):
|
|
|
186
228
|
},
|
|
187
229
|
attrs=observation.attrs | instrument.attrs,
|
|
188
230
|
)
|
|
231
|
+
|
|
232
|
+
def plot_counts(self, **kwargs):
|
|
233
|
+
return self.folded_counts.plot.step(x="e_min_folded", where="post", **kwargs)
|
jaxspec/data/util.py
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import importlib.resources
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TypeVar
|
|
6
|
+
|
|
7
|
+
import haiku as hk
|
|
3
8
|
import jax
|
|
4
9
|
import numpy as np
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
from numpy.typing import ArrayLike
|
|
8
|
-
from collections.abc import Mapping
|
|
9
|
-
from typing import TypeVar, Tuple
|
|
10
|
+
import numpyro
|
|
11
|
+
|
|
10
12
|
from astropy.io import fits
|
|
13
|
+
from numpy.typing import ArrayLike
|
|
14
|
+
from numpyro import handlers
|
|
11
15
|
|
|
12
|
-
from . import Observation, Instrument, ObsConfiguration
|
|
13
|
-
from ..model.abc import SpectralModel
|
|
14
16
|
from ..fit import CountForwardModel
|
|
15
|
-
from
|
|
17
|
+
from ..model.abc import SpectralModel
|
|
18
|
+
from . import Instrument, ObsConfiguration, Observation
|
|
16
19
|
|
|
17
20
|
K = TypeVar("K")
|
|
18
21
|
V = TypeVar("V")
|
|
@@ -80,7 +83,7 @@ def load_example_foldings():
|
|
|
80
83
|
example_instruments["PN"],
|
|
81
84
|
example_observations["PN"],
|
|
82
85
|
low_energy=0.3,
|
|
83
|
-
high_energy=
|
|
86
|
+
high_energy=8.0,
|
|
84
87
|
),
|
|
85
88
|
"MOS1": ObsConfiguration.from_instrument(
|
|
86
89
|
example_instruments["MOS1"],
|
|
@@ -107,12 +110,13 @@ def fakeit(
|
|
|
107
110
|
sparsify_matrix: bool = False,
|
|
108
111
|
) -> ArrayLike | list[ArrayLike]:
|
|
109
112
|
"""
|
|
110
|
-
|
|
113
|
+
Convenience function to simulate a spectrum from a given model and a set of parameters.
|
|
111
114
|
It requires an instrumental setup, and unlike in
|
|
112
115
|
[XSPEC's fakeit](https://heasarc.gsfc.nasa.gov/xanadu/xspec/manual/node72.html), the error on the counts is given
|
|
113
116
|
exclusively by Poisson statistics.
|
|
114
117
|
|
|
115
|
-
Parameters
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
116
120
|
instrument: The instrumental setup.
|
|
117
121
|
model: The model to use.
|
|
118
122
|
parameters: The parameters of the model.
|
|
@@ -125,7 +129,9 @@ def fakeit(
|
|
|
125
129
|
|
|
126
130
|
for i, instrument in enumerate(instruments):
|
|
127
131
|
transformed_model = hk.without_apply_rng(
|
|
128
|
-
hk.transform(
|
|
132
|
+
hk.transform(
|
|
133
|
+
lambda par: CountForwardModel(model, instrument, sparse=sparsify_matrix)(par)
|
|
134
|
+
)
|
|
129
135
|
)
|
|
130
136
|
|
|
131
137
|
def obs_model(p):
|
|
@@ -167,12 +173,12 @@ def fakeit_for_multiple_parameters(
|
|
|
167
173
|
sparsify_matrix: bool = False,
|
|
168
174
|
):
|
|
169
175
|
"""
|
|
170
|
-
|
|
171
|
-
set of parameters.
|
|
176
|
+
Convenience function to simulate multiple spectra from a given model and a set of parameters.
|
|
172
177
|
|
|
173
178
|
TODO : avoid redundancy, better doc and type hints
|
|
174
179
|
|
|
175
|
-
Parameters
|
|
180
|
+
Parameters
|
|
181
|
+
----------
|
|
176
182
|
instrument: The instrumental setup.
|
|
177
183
|
model: The model to use.
|
|
178
184
|
parameters: The parameters of the model.
|
|
@@ -209,13 +215,16 @@ def fakeit_for_multiple_parameters(
|
|
|
209
215
|
return fakeits[0] if len(fakeits) == 1 else fakeits
|
|
210
216
|
|
|
211
217
|
|
|
212
|
-
def data_path_finder(pha_path: str) ->
|
|
218
|
+
def data_path_finder(pha_path: str) -> tuple[str | None, str | None, str | None]:
|
|
213
219
|
"""
|
|
214
|
-
|
|
215
|
-
|
|
220
|
+
Function which tries its best to find the ARF, RMF and BKG files associated with a given PHA file.
|
|
221
|
+
|
|
222
|
+
Parameters
|
|
223
|
+
----------
|
|
216
224
|
pha_path: The PHA file path.
|
|
217
225
|
|
|
218
|
-
Returns
|
|
226
|
+
Returns
|
|
227
|
+
-------
|
|
219
228
|
arf_path: The ARF file path.
|
|
220
229
|
rmf_path: The RMF file path.
|
|
221
230
|
bkg_path: The BKG file path.
|