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.
Files changed (68) hide show
  1. derivkit/__init__.py +22 -0
  2. derivkit/calculus/__init__.py +17 -0
  3. derivkit/calculus/calculus_core.py +152 -0
  4. derivkit/calculus/gradient.py +97 -0
  5. derivkit/calculus/hessian.py +528 -0
  6. derivkit/calculus/hyper_hessian.py +296 -0
  7. derivkit/calculus/jacobian.py +156 -0
  8. derivkit/calculus_kit.py +128 -0
  9. derivkit/derivative_kit.py +315 -0
  10. derivkit/derivatives/__init__.py +6 -0
  11. derivkit/derivatives/adaptive/__init__.py +5 -0
  12. derivkit/derivatives/adaptive/adaptive_fit.py +238 -0
  13. derivkit/derivatives/adaptive/batch_eval.py +179 -0
  14. derivkit/derivatives/adaptive/diagnostics.py +325 -0
  15. derivkit/derivatives/adaptive/grid.py +333 -0
  16. derivkit/derivatives/adaptive/polyfit_utils.py +513 -0
  17. derivkit/derivatives/adaptive/spacing.py +66 -0
  18. derivkit/derivatives/adaptive/transforms.py +245 -0
  19. derivkit/derivatives/autodiff/__init__.py +1 -0
  20. derivkit/derivatives/autodiff/jax_autodiff.py +95 -0
  21. derivkit/derivatives/autodiff/jax_core.py +217 -0
  22. derivkit/derivatives/autodiff/jax_utils.py +146 -0
  23. derivkit/derivatives/finite/__init__.py +5 -0
  24. derivkit/derivatives/finite/batch_eval.py +91 -0
  25. derivkit/derivatives/finite/core.py +84 -0
  26. derivkit/derivatives/finite/extrapolators.py +511 -0
  27. derivkit/derivatives/finite/finite_difference.py +247 -0
  28. derivkit/derivatives/finite/stencil.py +206 -0
  29. derivkit/derivatives/fornberg.py +245 -0
  30. derivkit/derivatives/local_polynomial_derivative/__init__.py +1 -0
  31. derivkit/derivatives/local_polynomial_derivative/diagnostics.py +90 -0
  32. derivkit/derivatives/local_polynomial_derivative/fit.py +199 -0
  33. derivkit/derivatives/local_polynomial_derivative/local_poly_config.py +95 -0
  34. derivkit/derivatives/local_polynomial_derivative/local_polynomial_derivative.py +205 -0
  35. derivkit/derivatives/local_polynomial_derivative/sampling.py +72 -0
  36. derivkit/derivatives/tabulated_model/__init__.py +1 -0
  37. derivkit/derivatives/tabulated_model/one_d.py +247 -0
  38. derivkit/forecast_kit.py +783 -0
  39. derivkit/forecasting/__init__.py +1 -0
  40. derivkit/forecasting/dali.py +78 -0
  41. derivkit/forecasting/expansions.py +486 -0
  42. derivkit/forecasting/fisher.py +298 -0
  43. derivkit/forecasting/fisher_gaussian.py +171 -0
  44. derivkit/forecasting/fisher_xy.py +357 -0
  45. derivkit/forecasting/forecast_core.py +313 -0
  46. derivkit/forecasting/getdist_dali_samples.py +429 -0
  47. derivkit/forecasting/getdist_fisher_samples.py +235 -0
  48. derivkit/forecasting/laplace.py +259 -0
  49. derivkit/forecasting/priors_core.py +860 -0
  50. derivkit/forecasting/sampling_utils.py +388 -0
  51. derivkit/likelihood_kit.py +114 -0
  52. derivkit/likelihoods/__init__.py +1 -0
  53. derivkit/likelihoods/gaussian.py +136 -0
  54. derivkit/likelihoods/poisson.py +176 -0
  55. derivkit/utils/__init__.py +13 -0
  56. derivkit/utils/concurrency.py +213 -0
  57. derivkit/utils/extrapolation.py +254 -0
  58. derivkit/utils/linalg.py +513 -0
  59. derivkit/utils/logger.py +26 -0
  60. derivkit/utils/numerics.py +262 -0
  61. derivkit/utils/sandbox.py +74 -0
  62. derivkit/utils/types.py +15 -0
  63. derivkit/utils/validate.py +811 -0
  64. derivkit-1.0.0.dist-info/METADATA +50 -0
  65. derivkit-1.0.0.dist-info/RECORD +68 -0
  66. derivkit-1.0.0.dist-info/WHEEL +5 -0
  67. derivkit-1.0.0.dist-info/licenses/LICENSE +21 -0
  68. 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