derivkit 1.0.0__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.
- derivkit/__init__.py +22 -0
- derivkit/calculus/__init__.py +17 -0
- derivkit/calculus/calculus_core.py +152 -0
- derivkit/calculus/gradient.py +97 -0
- derivkit/calculus/hessian.py +528 -0
- derivkit/calculus/hyper_hessian.py +296 -0
- derivkit/calculus/jacobian.py +156 -0
- derivkit/calculus_kit.py +128 -0
- derivkit/derivative_kit.py +315 -0
- derivkit/derivatives/__init__.py +6 -0
- derivkit/derivatives/adaptive/__init__.py +5 -0
- derivkit/derivatives/adaptive/adaptive_fit.py +238 -0
- derivkit/derivatives/adaptive/batch_eval.py +179 -0
- derivkit/derivatives/adaptive/diagnostics.py +325 -0
- derivkit/derivatives/adaptive/grid.py +333 -0
- derivkit/derivatives/adaptive/polyfit_utils.py +513 -0
- derivkit/derivatives/adaptive/spacing.py +66 -0
- derivkit/derivatives/adaptive/transforms.py +245 -0
- derivkit/derivatives/autodiff/__init__.py +1 -0
- derivkit/derivatives/autodiff/jax_autodiff.py +95 -0
- derivkit/derivatives/autodiff/jax_core.py +217 -0
- derivkit/derivatives/autodiff/jax_utils.py +146 -0
- derivkit/derivatives/finite/__init__.py +5 -0
- derivkit/derivatives/finite/batch_eval.py +91 -0
- derivkit/derivatives/finite/core.py +84 -0
- derivkit/derivatives/finite/extrapolators.py +511 -0
- derivkit/derivatives/finite/finite_difference.py +247 -0
- derivkit/derivatives/finite/stencil.py +206 -0
- derivkit/derivatives/fornberg.py +245 -0
- derivkit/derivatives/local_polynomial_derivative/__init__.py +1 -0
- derivkit/derivatives/local_polynomial_derivative/diagnostics.py +90 -0
- derivkit/derivatives/local_polynomial_derivative/fit.py +199 -0
- derivkit/derivatives/local_polynomial_derivative/local_poly_config.py +95 -0
- derivkit/derivatives/local_polynomial_derivative/local_polynomial_derivative.py +205 -0
- derivkit/derivatives/local_polynomial_derivative/sampling.py +72 -0
- derivkit/derivatives/tabulated_model/__init__.py +1 -0
- derivkit/derivatives/tabulated_model/one_d.py +247 -0
- derivkit/forecast_kit.py +783 -0
- derivkit/forecasting/__init__.py +1 -0
- derivkit/forecasting/dali.py +78 -0
- derivkit/forecasting/expansions.py +486 -0
- derivkit/forecasting/fisher.py +298 -0
- derivkit/forecasting/fisher_gaussian.py +171 -0
- derivkit/forecasting/fisher_xy.py +357 -0
- derivkit/forecasting/forecast_core.py +313 -0
- derivkit/forecasting/getdist_dali_samples.py +429 -0
- derivkit/forecasting/getdist_fisher_samples.py +235 -0
- derivkit/forecasting/laplace.py +259 -0
- derivkit/forecasting/priors_core.py +860 -0
- derivkit/forecasting/sampling_utils.py +388 -0
- derivkit/likelihood_kit.py +114 -0
- derivkit/likelihoods/__init__.py +1 -0
- derivkit/likelihoods/gaussian.py +136 -0
- derivkit/likelihoods/poisson.py +176 -0
- derivkit/utils/__init__.py +13 -0
- derivkit/utils/concurrency.py +213 -0
- derivkit/utils/extrapolation.py +254 -0
- derivkit/utils/linalg.py +513 -0
- derivkit/utils/logger.py +26 -0
- derivkit/utils/numerics.py +262 -0
- derivkit/utils/sandbox.py +74 -0
- derivkit/utils/types.py +15 -0
- derivkit/utils/validate.py +811 -0
- derivkit-1.0.0.dist-info/METADATA +50 -0
- derivkit-1.0.0.dist-info/RECORD +68 -0
- derivkit-1.0.0.dist-info/WHEEL +5 -0
- derivkit-1.0.0.dist-info/licenses/LICENSE +21 -0
- derivkit-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""Interpolation utilities for 1D tabulated functions.
|
|
2
|
+
|
|
3
|
+
Provides a lightweight wrapper around ``numpy.interp`` for interpolating
|
|
4
|
+
tabulated ``y(x)`` data, supporting scalar as well as vector- and
|
|
5
|
+
tensor-valued outputs.
|
|
6
|
+
|
|
7
|
+
Two common entry points are:
|
|
8
|
+
|
|
9
|
+
* Direct construction with ``(x, y)`` arrays of shape ``(N,)`` and ``(N, ...)``.
|
|
10
|
+
* :func:`derivkit.tabulated_model.one_d.tabulated1d_from_table` for simple 2D
|
|
11
|
+
tables containing x and one or more y components in columns.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
from numpy.typing import ArrayLike, NDArray
|
|
19
|
+
|
|
20
|
+
from derivkit.utils.validate import validate_tabulated_xy
|
|
21
|
+
|
|
22
|
+
__all__ = ["Tabulated1DModel", "tabulated1d_from_table"]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Tabulated1DModel:
|
|
26
|
+
"""1D interpolator for tabulated data.
|
|
27
|
+
|
|
28
|
+
Interpolates a tabulated function ``y(x)`` using ``numpy.interp``.
|
|
29
|
+
|
|
30
|
+
Here ``x`` is a one-dimensional grid of length ``N``, and the first
|
|
31
|
+
dimension of ``y`` must also have length ``N``. All remaining
|
|
32
|
+
dimensions of ``y`` are treated as the output shape.
|
|
33
|
+
|
|
34
|
+
For example:
|
|
35
|
+
* ``x`` has shape ``(N,)`` and ``y`` has shape ``(N,)`` -> scalar output
|
|
36
|
+
* ``x`` has shape ``(N,)`` and ``y`` has shape ``(N, M)`` -> vector output of length ``M``
|
|
37
|
+
* ``x`` has shape ``(N,)`` and ``y`` has shape ``(N, d1, d2)`` -> tensor output with shape ``(d1, d2)``
|
|
38
|
+
|
|
39
|
+
This class handles interpolation for functions of a single scalar input ``x``.
|
|
40
|
+
Support for tabulated functions with multi-dimensional inputs would require
|
|
41
|
+
a different interface and can be added in a future extension.
|
|
42
|
+
|
|
43
|
+
Attributes:
|
|
44
|
+
x: Tabulated x grid, strictly increasing.
|
|
45
|
+
y_flat: Flattened tabulated values with shape ``(N, n_out_flat)``.
|
|
46
|
+
_out_shape: Original trailing output shape of ``y``.
|
|
47
|
+
extrapolate: Whether evaluation outside the tabulated x range is allowed.
|
|
48
|
+
fill_value: Value used for out-of-range evaluation when extrapolation is off.
|
|
49
|
+
|
|
50
|
+
Example:
|
|
51
|
+
>>> import numpy as np
|
|
52
|
+
>>> from derivkit.derivatives.tabulated_model.one_d import Tabulated1DModel
|
|
53
|
+
>>>
|
|
54
|
+
>>> x_tab = np.array([0.0, 1.0, 2.0, 3.0])
|
|
55
|
+
>>> y_tab = np.array([[0.0, 0.0],
|
|
56
|
+
... [1.0, 1.0],
|
|
57
|
+
... [4.0, 8.0],
|
|
58
|
+
... [9.0, 27.0]]) # shape (4, 2)
|
|
59
|
+
>>> # Create model with extrapolation disabled and fill_value = -1.0
|
|
60
|
+
>>> model = Tabulated1DModel(x_tab, y_tab,
|
|
61
|
+
... extrapolate=False, fill_value=-1.0)
|
|
62
|
+
>>> # Evaluate at new points
|
|
63
|
+
>>> x_new = np.array([-1.0, 0.5, 1.5, 2.5, 4.0])
|
|
64
|
+
>>> y_new = model(x_new)
|
|
65
|
+
>>> expected = np.array([
|
|
66
|
+
... [-1.0, -1.0],
|
|
67
|
+
... [0.5, 0.5],
|
|
68
|
+
... [2.5, 4.5],
|
|
69
|
+
... [6.5, 17.5],
|
|
70
|
+
... [-1.0, -1.0],
|
|
71
|
+
... ])
|
|
72
|
+
>>> np.allclose(y_new, expected)
|
|
73
|
+
True
|
|
74
|
+
"""
|
|
75
|
+
def __init__(
|
|
76
|
+
self,
|
|
77
|
+
x: ArrayLike,
|
|
78
|
+
y: ArrayLike,
|
|
79
|
+
*,
|
|
80
|
+
extrapolate: bool = False,
|
|
81
|
+
fill_value: float | None = None,
|
|
82
|
+
) -> None:
|
|
83
|
+
"""Initializes a tabulated 1D interpolation model.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
x: Strictly increasing tabulated x values with shape ``(N,)``.
|
|
87
|
+
y: Tabulated y values with shape ``(N,)`` (scalar) or ``(N, ...)``
|
|
88
|
+
(vector/tensor). The first dimension must match ``x``.
|
|
89
|
+
extrapolate: Whether to allow evaluation outside the x range.
|
|
90
|
+
Default is ``False``.
|
|
91
|
+
fill_value: Value for out-of-bounds evaluation when extrapolation is
|
|
92
|
+
disabled. If ``None``, a ``ValueError`` is raised instead.
|
|
93
|
+
"""
|
|
94
|
+
x_arr, y_arr = validate_tabulated_xy(x, y)
|
|
95
|
+
|
|
96
|
+
self.x = x_arr
|
|
97
|
+
|
|
98
|
+
if y_arr.ndim == 1:
|
|
99
|
+
self._out_shape: tuple[int, ...] = ()
|
|
100
|
+
y_flat = y_arr[:, np.newaxis]
|
|
101
|
+
else:
|
|
102
|
+
self._out_shape = tuple(y_arr.shape[1:])
|
|
103
|
+
y_flat = y_arr.reshape(y_arr.shape[0], -1)
|
|
104
|
+
|
|
105
|
+
self.y_flat = np.asarray(y_flat, dtype=float)
|
|
106
|
+
self.extrapolate = extrapolate
|
|
107
|
+
self.fill_value = fill_value
|
|
108
|
+
|
|
109
|
+
def __call__(self, x_new: ArrayLike) -> NDArray[np.floating]:
|
|
110
|
+
"""Evaluates the interpolated function at the given x values.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
x_new: Points where the function should be interpolated.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Interpolated values with shape matching ``x_new`` and the original
|
|
117
|
+
y output shape.
|
|
118
|
+
|
|
119
|
+
Raises:
|
|
120
|
+
ValueError: If evaluating outside the x range with extrapolation
|
|
121
|
+
disabled and no fill_value is provided.
|
|
122
|
+
"""
|
|
123
|
+
x_new_arr = np.asarray(x_new, dtype=float)
|
|
124
|
+
flat_x = x_new_arr.ravel()
|
|
125
|
+
n_out_flat = self.y_flat.shape[1]
|
|
126
|
+
|
|
127
|
+
flat_y = np.empty((flat_x.size, n_out_flat), dtype=float)
|
|
128
|
+
for k in range(n_out_flat):
|
|
129
|
+
flat_y[:, k] = np.interp(flat_x, self.x, self.y_flat[:, k])
|
|
130
|
+
|
|
131
|
+
if self._out_shape:
|
|
132
|
+
new_shape = x_new_arr.shape + self._out_shape
|
|
133
|
+
else:
|
|
134
|
+
new_shape = x_new_arr.shape
|
|
135
|
+
|
|
136
|
+
y_interp = flat_y.reshape(new_shape)
|
|
137
|
+
|
|
138
|
+
if not self.extrapolate:
|
|
139
|
+
mask = (x_new_arr < self.x[0]) | (x_new_arr > self.x[-1])
|
|
140
|
+
if np.any(mask):
|
|
141
|
+
if self.fill_value is None:
|
|
142
|
+
raise ValueError(
|
|
143
|
+
"Requested x outside tabulated range and extrapolate=False."
|
|
144
|
+
)
|
|
145
|
+
y_interp = np.asarray(y_interp)
|
|
146
|
+
y_interp[mask, ...] = self.fill_value
|
|
147
|
+
|
|
148
|
+
return np.asarray(y_interp, dtype=float)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def tabulated1d_from_table(
|
|
152
|
+
table: ArrayLike,
|
|
153
|
+
*,
|
|
154
|
+
extrapolate: bool = False,
|
|
155
|
+
fill_value: float | None = None,
|
|
156
|
+
) -> Tabulated1DModel:
|
|
157
|
+
"""Creates a ``Tabulated1DModel`` from a simple 2D ``(x, y)`` table.
|
|
158
|
+
|
|
159
|
+
This helper covers the common case where data are stored in a 2D array
|
|
160
|
+
or text file with x in one column and one or more y components in the
|
|
161
|
+
remaining columns.
|
|
162
|
+
|
|
163
|
+
Supported layouts:
|
|
164
|
+
* ``(N, 2)``: column 0 = x, column 1 = scalar y.
|
|
165
|
+
* ``(N, M+1)``: column 0 = x, columns 1..M = components of y.
|
|
166
|
+
* ``(2, N)``: row 0 = x, row 1 = scalar y.
|
|
167
|
+
|
|
168
|
+
For multi-component tables, the resulting ``y`` has shape ``(N, M)``.
|
|
169
|
+
Higher-rank outputs (for example matrices or tensors associated with
|
|
170
|
+
each x) are not encoded via this table format. Such data must be loaded
|
|
171
|
+
and reshaped prior to constructing a
|
|
172
|
+
:class:`derivkit.tabulated_model.one_d.Tabulated1DModel` directly
|
|
173
|
+
from ``(x, y)``.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
table: 2D array containing x and y columns.
|
|
177
|
+
extrapolate: Whether to allow evaluation outside the tabulated x range.
|
|
178
|
+
If False (default), any x outside [x.min(), x.max()] either raises
|
|
179
|
+
a ValueError (when fill_value is None) or is set to fill_value.
|
|
180
|
+
If True, out-of-range x are handled using numpy.interp’s standard
|
|
181
|
+
edge behaviour.
|
|
182
|
+
fill_value: Value for out-of-range evaluation when extrapolation is
|
|
183
|
+
disabled.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
A :class:`derivkit.tabulated_model.one_d.Tabulated1DModel` constructed
|
|
187
|
+
from the parsed table.
|
|
188
|
+
"""
|
|
189
|
+
x, y = parse_xy_table(table)
|
|
190
|
+
return Tabulated1DModel(x, y, extrapolate=extrapolate, fill_value=fill_value)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def parse_xy_table(
|
|
194
|
+
table: ArrayLike,
|
|
195
|
+
) -> tuple[NDArray[np.floating], NDArray[np.floating]]:
|
|
196
|
+
"""Parses a 2D table into ``(x, y)`` arrays.
|
|
197
|
+
|
|
198
|
+
Supported layouts:
|
|
199
|
+
|
|
200
|
+
* ``(N, 2)``:
|
|
201
|
+
Column 0 = x, column 1 = scalar y.
|
|
202
|
+
* ``(N, M+1)``:
|
|
203
|
+
Column 0 = x, columns 1..M = components of y, returned with shape ``(N, M)``.
|
|
204
|
+
* ``(2, N)``:
|
|
205
|
+
Row 0 = x, row 1 = scalar y.
|
|
206
|
+
|
|
207
|
+
In all cases ``x`` is returned as a 1D array of length ``N``. For
|
|
208
|
+
multi-component tables, ``y`` is returned as a 2D array of shape ``(N, M)``.
|
|
209
|
+
|
|
210
|
+
This function does not handle tensor-valued outputs directly.
|
|
211
|
+
When each x corresponds to a matrix or higher-rank object, the data
|
|
212
|
+
must be parsed and reshaped prior to constructing a
|
|
213
|
+
:class:`derivkit.tabulated_model.one_d.Tabulated1DModel`.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
table: 2D array containing x and y columns (e.g. data loaded from a text
|
|
217
|
+
file with shape (N, 2) or (N, M+1)). For higher-rank outputs,
|
|
218
|
+
reshape your data into (N, ...) and call ``Tabulated1DModel(x, y)``
|
|
219
|
+
directly.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
A tuple ``(x, y)`` as NumPy arrays.
|
|
223
|
+
|
|
224
|
+
Raises:
|
|
225
|
+
ValueError: If the input does not match any of the supported layouts.
|
|
226
|
+
"""
|
|
227
|
+
arr = np.asarray(table, dtype=float)
|
|
228
|
+
if arr.ndim != 2:
|
|
229
|
+
raise ValueError("table must be a 2D array.")
|
|
230
|
+
|
|
231
|
+
n_rows, n_cols = arr.shape
|
|
232
|
+
|
|
233
|
+
match (n_rows, n_cols):
|
|
234
|
+
case (2, n) if n >= 2:
|
|
235
|
+
# row 0 = x, row 1 = y
|
|
236
|
+
x = arr[0, :]
|
|
237
|
+
y = arr[1, :]
|
|
238
|
+
case (n, m) if n >= 2 and m >= 2:
|
|
239
|
+
# column 0 = x, remaining columns = y components
|
|
240
|
+
x = arr[:, 0]
|
|
241
|
+
y = arr[:, 1] if m == 2 else arr[:, 1:]
|
|
242
|
+
case _:
|
|
243
|
+
raise ValueError(
|
|
244
|
+
f"Unexpected table shape {arr.shape}; expected (N, 2), (N, M+1) or (2, N)."
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
return x, y
|