jaxspec 0.3.3__tar.gz → 0.3.4__tar.gz

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.
Files changed (121) hide show
  1. {jaxspec-0.3.3 → jaxspec-0.3.4}/PKG-INFO +3 -3
  2. {jaxspec-0.3.3 → jaxspec-0.3.4}/pyproject.toml +3 -3
  3. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/analysis/results.py +29 -16
  4. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/data/__init__.py +2 -0
  5. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/fit/_fitter.py +6 -1
  6. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/model/additive.py +17 -21
  7. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/model/multiplicative.py +54 -3
  8. {jaxspec-0.3.3 → jaxspec-0.3.4}/.dockerignore +0 -0
  9. {jaxspec-0.3.3 → jaxspec-0.3.4}/.github/dependabot.yml +0 -0
  10. {jaxspec-0.3.3 → jaxspec-0.3.4}/.github/workflows/documentation-links.yml +0 -0
  11. {jaxspec-0.3.3 → jaxspec-0.3.4}/.github/workflows/publish.yml +0 -0
  12. {jaxspec-0.3.3 → jaxspec-0.3.4}/.github/workflows/test-and-coverage.yml +0 -0
  13. {jaxspec-0.3.3 → jaxspec-0.3.4}/.gitignore +0 -0
  14. {jaxspec-0.3.3 → jaxspec-0.3.4}/.pre-commit-config.yaml +0 -0
  15. {jaxspec-0.3.3 → jaxspec-0.3.4}/.python-version +0 -0
  16. {jaxspec-0.3.3 → jaxspec-0.3.4}/.readthedocs.yaml +0 -0
  17. {jaxspec-0.3.3 → jaxspec-0.3.4}/CODE_OF_CONDUCT.md +0 -0
  18. {jaxspec-0.3.3 → jaxspec-0.3.4}/Dockerfile +0 -0
  19. {jaxspec-0.3.3 → jaxspec-0.3.4}/LICENSE.md +0 -0
  20. {jaxspec-0.3.3 → jaxspec-0.3.4}/README.md +0 -0
  21. {jaxspec-0.3.3 → jaxspec-0.3.4}/codecov.yml +0 -0
  22. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/contribute/index.md +0 -0
  23. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/contribute/internal.md +0 -0
  24. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/contribute/xspec.md +0 -0
  25. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/css/extra.css +0 -0
  26. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/css/material.css +0 -0
  27. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/css/mkdocstrings.css +0 -0
  28. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/css/xarray.css +0 -0
  29. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/dev/index.md +0 -0
  30. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/background.md +0 -0
  31. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/build_model.md +0 -0
  32. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/fakeits.md +0 -0
  33. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/fitting_example.md +0 -0
  34. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/index.md +0 -0
  35. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/background_comparison.png +0 -0
  36. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/background_gp.png +0 -0
  37. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/background_spectral.png +0 -0
  38. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/fakeits.png +0 -0
  39. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/fitting_example_corner.png +0 -0
  40. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/fitting_example_ppc.png +0 -0
  41. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/model.png +0 -0
  42. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/rmf.png +0 -0
  43. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/subtract_background.png +0 -0
  44. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/examples/statics/subtract_background_with_errors.png +0 -0
  45. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/faq/cookbook.md +0 -0
  46. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/faq/index.md +0 -0
  47. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/faq/statics/cstat_vs_chi2.png +0 -0
  48. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/frontpage/installation.md +0 -0
  49. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/index.md +0 -0
  50. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/javascripts/mathjax.js +0 -0
  51. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/logo/logo_small.svg +0 -0
  52. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/logo/xifu_mini.svg +0 -0
  53. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/abundance.md +0 -0
  54. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/additive.md +0 -0
  55. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/background.md +0 -0
  56. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/data.md +0 -0
  57. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/fitting.md +0 -0
  58. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/instrument.md +0 -0
  59. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/integrate.md +0 -0
  60. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/model.md +0 -0
  61. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/multiplicative.md +0 -0
  62. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/references/results.md +0 -0
  63. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/runtime/diagram.txt +0 -0
  64. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/runtime/result_table.txt +0 -0
  65. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/runtime/various_model_graphs/diagram.txt +0 -0
  66. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/runtime/various_model_graphs/model_complex.txt +0 -0
  67. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/runtime/various_model_graphs/model_simple.txt +0 -0
  68. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/theory/background.md +0 -0
  69. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/theory/bayesian_inference.md +0 -0
  70. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/theory/index.md +0 -0
  71. {jaxspec-0.3.3 → jaxspec-0.3.4}/docs/theory/instrument.md +0 -0
  72. {jaxspec-0.3.3 → jaxspec-0.3.4}/mkdocs.yml +0 -0
  73. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/__init__.py +0 -0
  74. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/analysis/__init__.py +0 -0
  75. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/analysis/_plot.py +0 -0
  76. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/analysis/compare.py +0 -0
  77. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/data/instrument.py +0 -0
  78. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/data/obsconf.py +0 -0
  79. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/data/observation.py +0 -0
  80. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/data/ogip.py +0 -0
  81. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/data/util.py +0 -0
  82. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/experimental/__init__.py +0 -0
  83. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/experimental/interpolator.py +0 -0
  84. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/experimental/interpolator_jax.py +0 -0
  85. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/experimental/intrument_models.py +0 -0
  86. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/experimental/nested_sampler.py +0 -0
  87. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/experimental/tabulated.py +0 -0
  88. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/fit/__init__.py +0 -0
  89. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/fit/_bayesian_model.py +0 -0
  90. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/fit/_build_model.py +0 -0
  91. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/model/__init__.py +0 -0
  92. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/model/_graph_util.py +0 -0
  93. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/model/abc.py +0 -0
  94. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/model/background.py +0 -0
  95. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/model/instrument.py +0 -0
  96. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/model/list.py +0 -0
  97. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/scripts/__init__.py +0 -0
  98. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/scripts/debug.py +0 -0
  99. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/util/__init__.py +0 -0
  100. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/util/abundance.py +0 -0
  101. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/util/integrate.py +0 -0
  102. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/util/misc.py +0 -0
  103. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/util/online_storage.py +0 -0
  104. {jaxspec-0.3.3 → jaxspec-0.3.4}/src/jaxspec/util/typing.py +0 -0
  105. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/conftest.py +0 -0
  106. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/data_files.yml +0 -0
  107. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/data_hash.yml +0 -0
  108. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_background.py +0 -0
  109. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_bayesian_model.py +0 -0
  110. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_bayesian_model_building.py +0 -0
  111. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_fakeit.py +0 -0
  112. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_instruments.py +0 -0
  113. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_integrate.py +0 -0
  114. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_mcmc.py +0 -0
  115. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_misc.py +0 -0
  116. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_models.py +0 -0
  117. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_observation.py +0 -0
  118. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_repr.py +0 -0
  119. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_results.py +0 -0
  120. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_xspec.py +0 -0
  121. {jaxspec-0.3.3 → jaxspec-0.3.4}/tests/test_xspec_models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jaxspec
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: jaxspec is a bayesian spectral fitting library for X-ray astronomy.
5
5
  Project-URL: Homepage, https://github.com/renecotyfanboy/jaxspec
6
6
  Project-URL: Documentation, https://jaxspec.readthedocs.io/en/latest/
@@ -8,7 +8,7 @@ Author-email: sdupourque <sdupourque@irap.omp.eu>
8
8
  License-Expression: MIT
9
9
  License-File: LICENSE.md
10
10
  Requires-Python: <3.13,>=3.10
11
- Requires-Dist: arviz<0.23.0,>=0.17.1
11
+ Requires-Dist: arviz<0.24.0,>=0.17.1
12
12
  Requires-Dist: astropy<8,>=6.0.0
13
13
  Requires-Dist: catppuccin<3,>=2.3.4
14
14
  Requires-Dist: chainconsumer<2,>=1.1.2
@@ -20,7 +20,7 @@ Requires-Dist: matplotlib<4,>=3.8.0
20
20
  Requires-Dist: mendeleev<1.2,>=0.15
21
21
  Requires-Dist: networkx~=3.1
22
22
  Requires-Dist: numpy<3.0.0
23
- Requires-Dist: numpyro<0.20,>=0.17.0
23
+ Requires-Dist: numpyro<0.21,>=0.17.0
24
24
  Requires-Dist: pandas<3,>=2.2.0
25
25
  Requires-Dist: pooch<2,>=1.8.2
26
26
  Requires-Dist: scipy<1.16
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "jaxspec"
3
- version = "0.3.3"
3
+ version = "0.3.4"
4
4
  description = "jaxspec is a bayesian spectral fitting library for X-ray astronomy."
5
5
  authors = [{ name = "sdupourque", email = "sdupourque@irap.omp.eu" }]
6
6
  requires-python = ">=3.10,<3.13"
@@ -11,10 +11,10 @@ dependencies = [
11
11
  "numpy<3.0.0",
12
12
  "pandas>=2.2.0,<3",
13
13
  "astropy>=6.0.0,<8",
14
- "numpyro>=0.17.0,<0.20",
14
+ "numpyro>=0.17.0,<0.21",
15
15
  "networkx~=3.1",
16
16
  "matplotlib>=3.8.0,<4",
17
- "arviz>=0.17.1,<0.23.0",
17
+ "arviz>=0.17.1,<0.24.0",
18
18
  "chainconsumer>=1.1.2,<2",
19
19
  "cmasher>=1.6.3,<2",
20
20
  "tinygp>=0.3.0,<0.4",
@@ -168,7 +168,8 @@ class FitResult:
168
168
  e_max: float,
169
169
  unit: Unit = u.photon / u.cm**2 / u.s,
170
170
  register: bool = False,
171
- n_points: int = 100,
171
+ n_points: int = 5,
172
+ n_grid: int = 1_000,
172
173
  ) -> ArrayLike:
173
174
  """
174
175
  Compute the unfolded photon flux in a given energy band. The flux is then added to
@@ -179,23 +180,26 @@ class FitResult:
179
180
  e_max: The upper bound of the energy band in observer frame.
180
181
  unit: The unit of the photon flux.
181
182
  register: Whether to register the flux with the other posterior parameters.
182
- n_points: The number of points to use for computing the unfolded spectrum.
183
+ n_points: The number of points per bin to use for computing the unfolded spectrum.
184
+ n_grid: The number of grid points to use for computing the unfolded spectrum.
183
185
 
184
186
  !!! warning
185
187
  Computation of the folded flux is not implemented yet. Feel free to open an
186
188
  [issue](https://github.com/renecotyfanboy/jaxspec/issues) in the GitHub repository.
187
189
  """
188
190
 
191
+ energy_grid = np.linspace(e_min, e_max, n_grid)
192
+
189
193
  @jax.jit
190
194
  @jnp.vectorize
191
195
  def vectorized_flux(*pars):
192
196
  parameters_pytree = jax.tree.unflatten(pytree_def, pars)
193
197
  return self.model.photon_flux(
194
- parameters_pytree, jnp.asarray([e_min]), jnp.asarray([e_max]), n_points=n_points
195
- )[0]
198
+ parameters_pytree, energy_grid[:-1], energy_grid[1:], n_points=n_points
199
+ )
196
200
 
197
201
  flat_tree, pytree_def = jax.tree.flatten(self.input_parameters)
198
- flux = vectorized_flux(*flat_tree)
202
+ flux = vectorized_flux(*flat_tree).sum(axis=-1) # Sum over all bins
199
203
  conversion_factor = float((u.photon / u.cm**2 / u.s).to(unit))
200
204
  value = np.asarray(flux * conversion_factor)
201
205
 
@@ -220,7 +224,8 @@ class FitResult:
220
224
  e_max: float,
221
225
  unit: Unit = u.erg / u.cm**2 / u.s,
222
226
  register: bool = False,
223
- n_points: int = 100,
227
+ n_points: int = 5,
228
+ n_grid: int = 1_000,
224
229
  ) -> ArrayLike:
225
230
  """
226
231
  Compute the unfolded energy flux in a given energy band. The flux is then added to
@@ -231,26 +236,29 @@ class FitResult:
231
236
  e_max: The upper bound of the energy band in observer frame.
232
237
  unit: The unit of the energy flux.
233
238
  register: Whether to register the flux with the other posterior parameters.
234
- n_points: The number of points to use for computing the unfolded spectrum.
239
+ n_points: The number of points per bin to use for computing the unfolded spectrum.
240
+ n_grid: The number of grid points to use for computing the unfolded spectrum.
235
241
 
236
242
  !!! warning
237
243
  Computation of the folded flux is not implemented yet. Feel free to open an
238
244
  [issue](https://github.com/renecotyfanboy/jaxspec/issues) in the GitHub repository.
239
245
  """
240
246
 
247
+ energy_grid = np.linspace(e_min, e_max, n_grid)
248
+
241
249
  @jax.jit
242
250
  @jnp.vectorize
243
251
  def vectorized_flux(*pars):
244
252
  parameters_pytree = jax.tree.unflatten(pytree_def, pars)
245
253
  return self.model.energy_flux(
246
- parameters_pytree, jnp.asarray([e_min]), jnp.asarray([e_max]), n_points=n_points
247
- )[0]
254
+ parameters_pytree, energy_grid[:-1], energy_grid[1:], n_points=n_points
255
+ )
248
256
 
249
257
  flat_tree, pytree_def = jax.tree.flatten(self.input_parameters)
250
- flux = vectorized_flux(*flat_tree)
258
+ flux = vectorized_flux(*flat_tree).sum(axis=-1) # Sum over all bins
251
259
  conversion_factor = float((u.keV / u.cm**2 / u.s).to(unit))
252
260
  value = np.asarray(flux * conversion_factor)
253
-
261
+ # TODO : ADD TESTS WITH BACKGROUND
254
262
  if register:
255
263
  self.inference_data.posterior[f"mod/~/energy_flux_{e_min:.1f}_{e_max:.1f}"] = (
256
264
  xr.DataArray(
@@ -276,7 +284,8 @@ class FitResult:
276
284
  cosmology: Cosmology = Planck18,
277
285
  unit: Unit = u.erg / u.s,
278
286
  register: bool = False,
279
- n_points=100,
287
+ n_points: int = 5,
288
+ n_grid: int = 1_000,
280
289
  ) -> ArrayLike:
281
290
  """
282
291
  Compute the luminosity of the source specifying its redshift. The luminosity is then added to
@@ -290,8 +299,12 @@ class FitResult:
290
299
  cosmology: Chosen cosmology.
291
300
  unit: The unit of the luminosity.
292
301
  register: Whether to register the flux with the other posterior parameters.
302
+ n_points: The number of points per bin to use for computing the unfolded spectrum.
303
+ n_grid: The number of grid points to use for computing the unfolded spectrum.
293
304
  """
294
305
 
306
+ energy_grid = np.linspace(e_min, e_max, n_grid)
307
+
295
308
  if not observer_frame:
296
309
  raise NotImplementedError()
297
310
 
@@ -312,13 +325,13 @@ class FitResult:
312
325
  parameters_pytree = jax.tree.unflatten(pytree_def, pars)
313
326
  return self.model.energy_flux(
314
327
  parameters_pytree,
315
- jnp.asarray([e_min]) * (1 + redshift),
316
- jnp.asarray([e_max]) * (1 + redshift),
328
+ energy_grid[:-1] * (1 + redshift),
329
+ energy_grid[1:] * (1 + redshift),
317
330
  n_points=n_points,
318
- )[0]
331
+ )
319
332
 
320
333
  flat_tree, pytree_def = jax.tree.flatten(self.input_parameters)
321
- flux = vectorized_flux(*flat_tree) * (u.keV / u.cm**2 / u.s)
334
+ flux = vectorized_flux(*flat_tree).sum(axis=-1) * (u.keV / u.cm**2 / u.s)
322
335
  value = np.asarray(
323
336
  (flux * (4 * np.pi * cosmology.luminosity_distance(redshift) ** 2)).to(unit)
324
337
  )
@@ -6,5 +6,7 @@ from .observation import Observation
6
6
 
7
7
  u.add_enabled_aliases({"counts": u.count})
8
8
  u.add_enabled_aliases({"channel": u.dimensionless_unscaled})
9
+ u.add_enabled_aliases({"ADU": u.dimensionless_unscaled}) # Appears in SIXTE outputs
10
+
9
11
  # Arbitrary units are found in .rsp files , let's hope it is compatible with what we would expect as the rmf x arf
10
12
  # u.add_enabled_aliases({"au": u.dimensionless_unscaled})
@@ -15,6 +15,7 @@ from numpyro.infer import AIES, ESS, MCMC, NUTS, SVI, Predictive, Trace_ELBO
15
15
  from numpyro.infer.autoguide import AutoMultivariateNormal
16
16
 
17
17
  from ..analysis.results import FitResult
18
+ from ..model.background import SubtractedBackground
18
19
  from ._bayesian_model import BayesianModel
19
20
 
20
21
 
@@ -58,7 +59,11 @@ class BayesianModelFitter(BayesianModel, ABC):
58
59
  log_likelihood["obs/~/all"] = concatenate(
59
60
  [ll for k, ll in log_likelihood.items() if "obs" in k], axis=1
60
61
  )
61
- if self.background_model is not None:
62
+
63
+ # Subtracted background is not fitted so there is no likelihood
64
+ if self.background_model is not None and not isinstance(
65
+ self.background_model, SubtractedBackground
66
+ ):
62
67
  log_likelihood["bkg/~/all"] = concatenate(
63
68
  [ll for k, ll in log_likelihood.items() if "bkg" in k], axis=1
64
69
  )
@@ -34,8 +34,10 @@ class Powerlaw(AdditiveComponent):
34
34
  self.alpha = nnx.Param(1.7)
35
35
  self.norm = nnx.Param(1e-4)
36
36
 
37
- def continuum(self, energy):
38
- return self.norm * energy ** (-self.alpha)
37
+ def integrated_continuum(self, e_low, e_high):
38
+ return (
39
+ self.norm / (1 - self.alpha) * (e_high ** (1 - self.alpha) - e_low ** (1 - self.alpha))
40
+ )
39
41
 
40
42
 
41
43
  class Additiveconstant(AdditiveComponent):
@@ -166,28 +168,22 @@ class Gauss(AdditiveComponent):
166
168
  self.sigma = nnx.Param(1e-2)
167
169
  self.norm = nnx.Param(1.0)
168
170
 
169
- def continuum(self, energy):
170
- return (
171
- self.norm
172
- * jsp.stats.norm.pdf(energy, loc=jnp.asarray(self.El), scale=jnp.asarray(self.sigma))
173
- / (1 - jsp.special.erf(-self.El / (self.sigma * jnp.sqrt(2))))
171
+ def integrated_continuum(self, e_low, e_high):
172
+ upper = jsp.stats.norm.cdf(
173
+ e_high,
174
+ loc=jnp.asarray(self.El),
175
+ scale=jnp.asarray(self.sigma),
174
176
  )
175
177
 
176
- """
177
- def integrated_continuum(self, e_low, e_high):
178
- return self.norm * (
179
- jsp.stats.norm.cdf(
180
- e_high,
181
- loc=jnp.asarray(self.El),
182
- scale=jnp.asarray(self.sigma),
183
- )
184
- - jsp.stats.norm.cdf(
185
- e_low,
186
- loc=jnp.asarray(self.El),
187
- scale=jnp.asarray(self.sigma),
188
- ) #/ (1 - jsp.special.erf(- self.El / (self.sigma * jnp.sqrt(2))))
178
+ lower = jsp.stats.norm.cdf(
179
+ e_low,
180
+ loc=jnp.asarray(self.El),
181
+ scale=jnp.asarray(self.sigma),
189
182
  )
190
- """
183
+
184
+ factor = 2 / (1 - jsp.special.erf(-self.El / (self.sigma * jnp.sqrt(2))))
185
+
186
+ return self.norm * (upper - lower) * factor
191
187
 
192
188
 
193
189
  class Cutoffpl(AdditiveComponent):
@@ -49,7 +49,9 @@ class Expfac(MultiplicativeComponent):
49
49
  self.E_c = nnx.Param(1.0)
50
50
 
51
51
  def factor(self, energy):
52
- return jnp.where(energy >= self.E_c, 1.0 + self.A * jnp.exp(-self.f * energy), 1.0)
52
+ return jnp.where(
53
+ energy >= self.E_c, 1.0 + self.A * jnp.exp(-self.f * energy), 1.0
54
+ )
53
55
 
54
56
 
55
57
  class Tbabs(MultiplicativeComponent):
@@ -91,6 +93,49 @@ class Tbabs(MultiplicativeComponent):
91
93
  return jnp.exp(-self.nh * sigma)
92
94
 
93
95
 
96
+ class zTbabs(MultiplicativeComponent):
97
+ r"""
98
+ The redshifted Tuebingen-Boulder ISM absorption model. See `Tbabs` for more details.
99
+ From Xspec manual:
100
+ This model assumes that 20% of the hydrogen is molecular
101
+ and that there is NO MATERIAL IN GRAINS.
102
+
103
+ $$
104
+ \mathcal{M}(E) = \exp^{-N_{\text{H}}\sigma(E)}
105
+ $$
106
+
107
+ !!! abstract "Parameters"
108
+ * $N_{\text{H}}$ (`nh`) $\left[\frac{\text{atoms}~10^{22}}{\text{cm}^2}\right]$ : Equivalent hydrogen column density
109
+ * $z$ (`z`) $\left[\text{dimensionless}\right]$ : Redshift
110
+
111
+
112
+ !!! note
113
+ Abundances and cross-sections $\sigma$ can be found in Wilms et al. (2000).
114
+
115
+ """
116
+
117
+ def __init__(self):
118
+ table = Table.read(table_manager.fetch("xsect_tbabs_wilm.fits"))
119
+ self._energy = np.asarray(table["ENERGY"], dtype=np.float64)
120
+ self._sigma = np.asarray(table["SIGMA"], dtype=np.float64)
121
+ self.nh = nnx.Param(1.0)
122
+ self.z = nnx.Param(1.0)
123
+
124
+ def factor(self, energy):
125
+ z = jnp.asarray(self.z)
126
+ sigma = jnp.exp(
127
+ jnp.interp(
128
+ jnp.log(energy) + jnp.log1p(z),
129
+ jnp.log(self._energy),
130
+ jnp.log(self._sigma),
131
+ left="extrapolate",
132
+ right="extrapolate",
133
+ )
134
+ )
135
+
136
+ return jnp.exp(-self.nh * sigma)
137
+
138
+
94
139
  class Phabs(MultiplicativeComponent):
95
140
  r"""
96
141
  A photoelectric absorption model.
@@ -215,7 +260,9 @@ class Zedge(MultiplicativeComponent):
215
260
 
216
261
  def factor(self, energy):
217
262
  return jnp.where(
218
- energy <= self.Ec, 1.0, jnp.exp(-self.D * (energy * (1 + self.z) / self.Ec) ** 3)
263
+ energy <= self.Ec,
264
+ 1.0,
265
+ jnp.exp(-self.D * (energy * (1 + self.z) / self.Ec) ** 3),
219
266
  )
220
267
 
221
268
 
@@ -246,7 +293,11 @@ class Tbpcf(MultiplicativeComponent):
246
293
  def factor(self, energy):
247
294
  sigma = jnp.exp(
248
295
  jnp.interp(
249
- energy, self._energy, jnp.log(self._sigma), left="extrapolate", right="extrapolate"
296
+ energy,
297
+ self._energy,
298
+ jnp.log(self._sigma),
299
+ left="extrapolate",
300
+ right="extrapolate",
250
301
  )
251
302
  )
252
303
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes