pygeoinf 1.3.5__py3-none-any.whl → 1.3.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.
- pygeoinf/__init__.py +18 -0
- pygeoinf/linear_bayesian.py +53 -111
- pygeoinf/linear_optimisation.py +45 -226
- pygeoinf/linear_solvers.py +430 -0
- pygeoinf/preconditioners.py +140 -0
- pygeoinf/random_matrix.py +8 -5
- pygeoinf/subspaces.py +132 -40
- pygeoinf/symmetric_space/sh_tools.py +19 -7
- pygeoinf/symmetric_space/sphere.py +46 -58
- {pygeoinf-1.3.5.dist-info → pygeoinf-1.3.7.dist-info}/METADATA +1 -1
- {pygeoinf-1.3.5.dist-info → pygeoinf-1.3.7.dist-info}/RECORD +13 -12
- {pygeoinf-1.3.5.dist-info → pygeoinf-1.3.7.dist-info}/WHEEL +0 -0
- {pygeoinf-1.3.5.dist-info → pygeoinf-1.3.7.dist-info}/licenses/LICENSE +0 -0
pygeoinf/subspaces.py
CHANGED
|
@@ -3,29 +3,25 @@ Defines classes for representing affine and linear subspaces.
|
|
|
3
3
|
|
|
4
4
|
The primary abstraction is the `AffineSubspace`, which represents a subset of
|
|
5
5
|
a Hilbert space defined by a translation and a closed linear tangent space.
|
|
6
|
-
`LinearSubspace` is a specialization where the translation is zero.
|
|
7
6
|
"""
|
|
8
7
|
|
|
9
8
|
from __future__ import annotations
|
|
10
9
|
from typing import List, Optional, Any, Callable, TYPE_CHECKING
|
|
11
10
|
import numpy as np
|
|
11
|
+
import warnings
|
|
12
12
|
|
|
13
13
|
from .linear_operators import LinearOperator
|
|
14
14
|
from .hilbert_space import HilbertSpace, Vector, EuclideanSpace
|
|
15
15
|
from .linear_solvers import LinearSolver, CholeskySolver, IterativeLinearSolver
|
|
16
16
|
|
|
17
17
|
if TYPE_CHECKING:
|
|
18
|
-
|
|
19
|
-
pass
|
|
18
|
+
from .gaussian_measure import GaussianMeasure
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
class OrthogonalProjector(LinearOperator):
|
|
23
22
|
"""
|
|
24
23
|
Internal engine for subspace projections.
|
|
25
|
-
|
|
26
24
|
Represents an orthogonal projection operator P = P* = P^2.
|
|
27
|
-
While this class can be used directly, it is generally recommended to use
|
|
28
|
-
`AffineSubspace` or `LinearSubspace` for high-level problem definitions.
|
|
29
25
|
"""
|
|
30
26
|
|
|
31
27
|
def __init__(
|
|
@@ -52,9 +48,8 @@ class OrthogonalProjector(LinearOperator):
|
|
|
52
48
|
basis_vectors: List[Vector],
|
|
53
49
|
orthonormalize: bool = True,
|
|
54
50
|
) -> OrthogonalProjector:
|
|
55
|
-
"""Constructs P
|
|
51
|
+
"""Constructs a projector P onto the span of the provided basis vectors."""
|
|
56
52
|
if not basis_vectors:
|
|
57
|
-
# Return zero operator if basis is empty
|
|
58
53
|
return domain.zero_operator(domain)
|
|
59
54
|
|
|
60
55
|
if orthonormalize:
|
|
@@ -78,7 +73,12 @@ class AffineSubspace:
|
|
|
78
73
|
translation: Optional[Vector] = None,
|
|
79
74
|
constraint_operator: Optional[LinearOperator] = None,
|
|
80
75
|
constraint_value: Optional[Vector] = None,
|
|
76
|
+
solver: Optional[LinearSolver] = None,
|
|
77
|
+
preconditioner: Optional[LinearOperator] = None,
|
|
81
78
|
) -> None:
|
|
79
|
+
"""
|
|
80
|
+
Initializes the AffineSubspace.
|
|
81
|
+
"""
|
|
82
82
|
self._projector = projector
|
|
83
83
|
|
|
84
84
|
if translation is None:
|
|
@@ -91,6 +91,15 @@ class AffineSubspace:
|
|
|
91
91
|
self._constraint_operator = constraint_operator
|
|
92
92
|
self._constraint_value = constraint_value
|
|
93
93
|
|
|
94
|
+
# Logic: If explicit equation exists, default to Cholesky.
|
|
95
|
+
# If implicit, leave None (requires robust solver from user).
|
|
96
|
+
if self._constraint_operator is not None and solver is None:
|
|
97
|
+
self._solver = CholeskySolver(galerkin=True)
|
|
98
|
+
else:
|
|
99
|
+
self._solver = solver
|
|
100
|
+
|
|
101
|
+
self._preconditioner = preconditioner
|
|
102
|
+
|
|
94
103
|
@property
|
|
95
104
|
def domain(self) -> HilbertSpace:
|
|
96
105
|
return self._projector.domain
|
|
@@ -108,27 +117,39 @@ class AffineSubspace:
|
|
|
108
117
|
return LinearSubspace(self._projector)
|
|
109
118
|
|
|
110
119
|
@property
|
|
111
|
-
def
|
|
120
|
+
def has_explicit_equation(self) -> bool:
|
|
121
|
+
"""True if defined by B(u)=w, False if defined only by geometry."""
|
|
112
122
|
return self._constraint_operator is not None
|
|
113
123
|
|
|
114
124
|
@property
|
|
115
125
|
def constraint_operator(self) -> LinearOperator:
|
|
126
|
+
"""
|
|
127
|
+
Returns B for {u | B(u)=w}.
|
|
128
|
+
Falls back to (I - P) if no explicit operator exists.
|
|
129
|
+
"""
|
|
116
130
|
if self._constraint_operator is None:
|
|
117
|
-
|
|
131
|
+
return self._projector.complement
|
|
118
132
|
return self._constraint_operator
|
|
119
133
|
|
|
120
134
|
@property
|
|
121
135
|
def constraint_value(self) -> Vector:
|
|
136
|
+
"""
|
|
137
|
+
Returns w for {u | B(u)=w}.
|
|
138
|
+
Falls back to (I - P)x0 if no explicit operator exists.
|
|
139
|
+
"""
|
|
122
140
|
if self._constraint_value is None:
|
|
123
|
-
|
|
141
|
+
complement = self._projector.complement
|
|
142
|
+
return complement(self._translation)
|
|
124
143
|
return self._constraint_value
|
|
125
144
|
|
|
126
145
|
def project(self, x: Vector) -> Vector:
|
|
146
|
+
"""Orthogonally projects x onto the affine subspace."""
|
|
127
147
|
diff = self.domain.subtract(x, self.translation)
|
|
128
148
|
proj_diff = self.projector(diff)
|
|
129
149
|
return self.domain.add(self.translation, proj_diff)
|
|
130
150
|
|
|
131
151
|
def is_element(self, x: Vector, rtol: float = 1e-6) -> bool:
|
|
152
|
+
"""Returns True if x lies in the subspace."""
|
|
132
153
|
proj = self.project(x)
|
|
133
154
|
diff = self.domain.subtract(x, proj)
|
|
134
155
|
norm_diff = self.domain.norm(diff)
|
|
@@ -136,6 +157,46 @@ class AffineSubspace:
|
|
|
136
157
|
scale = norm_x if norm_x > 1e-12 else 1.0
|
|
137
158
|
return norm_diff <= rtol * scale
|
|
138
159
|
|
|
160
|
+
def condition_gaussian_measure(
|
|
161
|
+
self, prior: GaussianMeasure, geometric: bool = False
|
|
162
|
+
) -> GaussianMeasure:
|
|
163
|
+
"""
|
|
164
|
+
Conditions a Gaussian measure on this subspace.
|
|
165
|
+
"""
|
|
166
|
+
if geometric:
|
|
167
|
+
# Geometric Projection: u -> P(u - x0) + x0
|
|
168
|
+
# Affine Map: u -> P(u) + (I-P)x0
|
|
169
|
+
shift = self.domain.subtract(
|
|
170
|
+
self.translation, self.projector(self.translation)
|
|
171
|
+
)
|
|
172
|
+
return prior.affine_mapping(operator=self.projector, translation=shift)
|
|
173
|
+
|
|
174
|
+
else:
|
|
175
|
+
# Bayesian Conditioning: u | B(u)=w
|
|
176
|
+
|
|
177
|
+
# Check for singular implicit operator usage
|
|
178
|
+
if not self.has_explicit_equation and self._solver is None:
|
|
179
|
+
raise ValueError(
|
|
180
|
+
"This subspace defines the constraint implicitly as (I-P)u = (I-P)x0. "
|
|
181
|
+
"The operator (I-P) is singular. You must provide a solver "
|
|
182
|
+
"capable of handling singular systems (e.g. MinRes) to the "
|
|
183
|
+
"AffineSubspace constructor."
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Local imports
|
|
187
|
+
from .forward_problem import LinearForwardProblem
|
|
188
|
+
from .linear_bayesian import LinearBayesianInversion
|
|
189
|
+
|
|
190
|
+
solver = self._solver
|
|
191
|
+
preconditioner = self._preconditioner
|
|
192
|
+
|
|
193
|
+
constraint_problem = LinearForwardProblem(self.constraint_operator)
|
|
194
|
+
constraint_inversion = LinearBayesianInversion(constraint_problem, prior)
|
|
195
|
+
|
|
196
|
+
return constraint_inversion.model_posterior_measure(
|
|
197
|
+
self.constraint_value, solver, preconditioner=preconditioner
|
|
198
|
+
)
|
|
199
|
+
|
|
139
200
|
@classmethod
|
|
140
201
|
def from_linear_equation(
|
|
141
202
|
cls,
|
|
@@ -144,7 +205,7 @@ class AffineSubspace:
|
|
|
144
205
|
solver: Optional[LinearSolver] = None,
|
|
145
206
|
preconditioner: Optional[LinearOperator] = None,
|
|
146
207
|
) -> AffineSubspace:
|
|
147
|
-
"""Constructs
|
|
208
|
+
"""Constructs subspace from B(u)=w."""
|
|
148
209
|
domain = operator.domain
|
|
149
210
|
G = operator @ operator.adjoint
|
|
150
211
|
|
|
@@ -166,7 +227,12 @@ class AffineSubspace:
|
|
|
166
227
|
projector = OrthogonalProjector(domain, mapping, complement_projector=P_perp_op)
|
|
167
228
|
|
|
168
229
|
return cls(
|
|
169
|
-
projector,
|
|
230
|
+
projector,
|
|
231
|
+
translation,
|
|
232
|
+
constraint_operator=operator,
|
|
233
|
+
constraint_value=value,
|
|
234
|
+
solver=solver,
|
|
235
|
+
preconditioner=preconditioner,
|
|
170
236
|
)
|
|
171
237
|
|
|
172
238
|
@classmethod
|
|
@@ -176,18 +242,38 @@ class AffineSubspace:
|
|
|
176
242
|
basis_vectors: List[Vector],
|
|
177
243
|
translation: Optional[Vector] = None,
|
|
178
244
|
orthonormalize: bool = True,
|
|
245
|
+
solver: Optional[LinearSolver] = None,
|
|
246
|
+
preconditioner: Optional[LinearOperator] = None,
|
|
179
247
|
) -> AffineSubspace:
|
|
180
248
|
"""
|
|
181
|
-
Constructs
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
249
|
+
Constructs an affine subspace from a translation and a basis for the tangent space.
|
|
250
|
+
|
|
251
|
+
This method defines the subspace geometrically. The constraint is implicit:
|
|
252
|
+
(I - P)u = (I - P)x0.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
domain: The Hilbert space.
|
|
256
|
+
basis_vectors: Basis vectors for the tangent space V.
|
|
257
|
+
translation: A point x0 in the subspace.
|
|
258
|
+
orthonormalize: If True, orthonormalizes the basis.
|
|
259
|
+
solver: A linear solver capable of handling the singular operator (I-P).
|
|
260
|
+
Required if you intend to use this subspace for Bayesian conditioning.
|
|
261
|
+
preconditioner: Optional preconditioner for the solver.
|
|
186
262
|
"""
|
|
263
|
+
if solver is None:
|
|
264
|
+
warnings.warn(
|
|
265
|
+
"Constructing a subspace from a tangent basis without a solver. "
|
|
266
|
+
"This defines an implicit constraint with a singular operator. "
|
|
267
|
+
"Bayesian conditioning will fail; geometric projection remains available.",
|
|
268
|
+
UserWarning,
|
|
269
|
+
stacklevel=2,
|
|
270
|
+
)
|
|
271
|
+
|
|
187
272
|
projector = OrthogonalProjector.from_basis(
|
|
188
273
|
domain, basis_vectors, orthonormalize=orthonormalize
|
|
189
274
|
)
|
|
190
|
-
|
|
275
|
+
|
|
276
|
+
return cls(projector, translation, solver=solver, preconditioner=preconditioner)
|
|
191
277
|
|
|
192
278
|
@classmethod
|
|
193
279
|
def from_complement_basis(
|
|
@@ -198,24 +284,18 @@ class AffineSubspace:
|
|
|
198
284
|
orthonormalize: bool = True,
|
|
199
285
|
) -> AffineSubspace:
|
|
200
286
|
"""
|
|
201
|
-
Constructs
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
This automatically constructs the constraint operator B such that
|
|
205
|
-
the subspace is {u | B(u) = B(translation)}.
|
|
287
|
+
Constructs subspace from complement basis.
|
|
288
|
+
Constraint is explicit: <u, e_i> = <x0, e_i>.
|
|
206
289
|
"""
|
|
207
|
-
# 1. Orthonormalize basis for stability
|
|
208
290
|
if orthonormalize:
|
|
209
291
|
e_vectors = domain.gram_schmidt(basis_vectors)
|
|
210
292
|
else:
|
|
211
293
|
e_vectors = basis_vectors
|
|
212
294
|
|
|
213
|
-
# 2. Construct Projector P_perp
|
|
214
295
|
complement_projector = OrthogonalProjector.from_basis(
|
|
215
|
-
domain, e_vectors, orthonormalize=False
|
|
296
|
+
domain, e_vectors, orthonormalize=False
|
|
216
297
|
)
|
|
217
298
|
|
|
218
|
-
# 3. Construct Projector P = I - P_perp
|
|
219
299
|
def mapping(x: Any) -> Any:
|
|
220
300
|
return domain.subtract(x, complement_projector(x))
|
|
221
301
|
|
|
@@ -223,16 +303,12 @@ class AffineSubspace:
|
|
|
223
303
|
domain, mapping, complement_projector=complement_projector
|
|
224
304
|
)
|
|
225
305
|
|
|
226
|
-
# 4. Construct Constraint Operator B implicitly defined by the basis
|
|
227
|
-
# B: E -> R^k, u -> [<e_1, u>, ..., <e_k, u>]
|
|
228
|
-
# Since e_i are orthonormal, BB* = I, which is perfect for solvers.
|
|
229
306
|
codomain = EuclideanSpace(len(e_vectors))
|
|
230
307
|
|
|
231
308
|
def constraint_mapping(u: Vector) -> np.ndarray:
|
|
232
309
|
return np.array([domain.inner_product(e, u) for e in e_vectors])
|
|
233
310
|
|
|
234
311
|
def constraint_adjoint(c: np.ndarray) -> Vector:
|
|
235
|
-
# sum c_i e_i
|
|
236
312
|
res = domain.zero
|
|
237
313
|
for i, e in enumerate(e_vectors):
|
|
238
314
|
domain.axpy(c[i], e, res)
|
|
@@ -242,8 +318,6 @@ class AffineSubspace:
|
|
|
242
318
|
domain, codomain, constraint_mapping, adjoint_mapping=constraint_adjoint
|
|
243
319
|
)
|
|
244
320
|
|
|
245
|
-
# 5. Determine Constraint Value w = B(translation)
|
|
246
|
-
# If translation is None (zero), w is zero.
|
|
247
321
|
if translation is None:
|
|
248
322
|
_translation = domain.zero
|
|
249
323
|
w = codomain.zero
|
|
@@ -251,12 +325,20 @@ class AffineSubspace:
|
|
|
251
325
|
_translation = translation
|
|
252
326
|
w = B(_translation)
|
|
253
327
|
|
|
254
|
-
|
|
328
|
+
solver = CholeskySolver(galerkin=True)
|
|
329
|
+
|
|
330
|
+
return cls(
|
|
331
|
+
projector,
|
|
332
|
+
_translation,
|
|
333
|
+
constraint_operator=B,
|
|
334
|
+
constraint_value=w,
|
|
335
|
+
solver=solver,
|
|
336
|
+
)
|
|
255
337
|
|
|
256
338
|
|
|
257
339
|
class LinearSubspace(AffineSubspace):
|
|
258
340
|
"""
|
|
259
|
-
Represents a linear subspace (an affine subspace passing through
|
|
341
|
+
Represents a linear subspace (an affine subspace passing through the origin).
|
|
260
342
|
"""
|
|
261
343
|
|
|
262
344
|
def __init__(self, projector: OrthogonalProjector) -> None:
|
|
@@ -272,14 +354,19 @@ class LinearSubspace(AffineSubspace):
|
|
|
272
354
|
|
|
273
355
|
@classmethod
|
|
274
356
|
def from_kernel(
|
|
275
|
-
cls,
|
|
357
|
+
cls,
|
|
358
|
+
operator: LinearOperator,
|
|
359
|
+
solver: Optional[LinearSolver] = None,
|
|
360
|
+
preconditioner: Optional[LinearOperator] = None,
|
|
276
361
|
) -> LinearSubspace:
|
|
277
362
|
affine = AffineSubspace.from_linear_equation(
|
|
278
|
-
operator, operator.codomain.zero, solver
|
|
363
|
+
operator, operator.codomain.zero, solver, preconditioner
|
|
279
364
|
)
|
|
280
365
|
instance = cls(affine.projector)
|
|
281
366
|
instance._constraint_operator = operator
|
|
282
367
|
instance._constraint_value = operator.codomain.zero
|
|
368
|
+
instance._solver = affine._solver
|
|
369
|
+
instance._preconditioner = preconditioner
|
|
283
370
|
return instance
|
|
284
371
|
|
|
285
372
|
@classmethod
|
|
@@ -288,11 +375,16 @@ class LinearSubspace(AffineSubspace):
|
|
|
288
375
|
domain: HilbertSpace,
|
|
289
376
|
basis_vectors: List[Vector],
|
|
290
377
|
orthonormalize: bool = True,
|
|
378
|
+
solver: Optional[LinearSolver] = None,
|
|
379
|
+
preconditioner: Optional[LinearOperator] = None,
|
|
291
380
|
) -> LinearSubspace:
|
|
292
381
|
projector = OrthogonalProjector.from_basis(
|
|
293
382
|
domain, basis_vectors, orthonormalize=orthonormalize
|
|
294
383
|
)
|
|
295
|
-
|
|
384
|
+
instance = cls(projector)
|
|
385
|
+
instance._solver = solver
|
|
386
|
+
instance._preconditioner = preconditioner
|
|
387
|
+
return instance
|
|
296
388
|
|
|
297
389
|
@classmethod
|
|
298
390
|
def from_complement_basis(
|
|
@@ -304,8 +396,8 @@ class LinearSubspace(AffineSubspace):
|
|
|
304
396
|
affine = AffineSubspace.from_complement_basis(
|
|
305
397
|
domain, basis_vectors, translation=None, orthonormalize=orthonormalize
|
|
306
398
|
)
|
|
307
|
-
# Copy constraint info from the affine instance
|
|
308
399
|
instance = cls(affine.projector)
|
|
309
400
|
instance._constraint_operator = affine.constraint_operator
|
|
310
401
|
instance._constraint_value = affine.constraint_value
|
|
402
|
+
instance._solver = affine._solver
|
|
311
403
|
return instance
|
|
@@ -8,19 +8,31 @@ import numpy as np
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class SHVectorConverter:
|
|
11
|
-
"""
|
|
11
|
+
r"""
|
|
12
12
|
Handles conversion between pyshtools 3D coefficient arrays and 1D vectors.
|
|
13
13
|
|
|
14
|
-
This class
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
This class bridges the gap between the `pyshtools` 3D array format
|
|
15
|
+
(shape `[2, lmax+1, lmax+1]`) and the flat 1D vector format used in
|
|
16
|
+
linear algebra.
|
|
17
|
+
|
|
18
|
+
**Vector Layout:**
|
|
19
|
+
The output vector is ordered first by degree $l$ (ascending from `lmin` to `lmax`),
|
|
20
|
+
and then by order $m$ (ascending from $-l$ to $+l$).
|
|
21
|
+
|
|
22
|
+
The sequence of coefficients is:
|
|
23
|
+
|
|
24
|
+
.. math::
|
|
25
|
+
[u_{l_{min}, -l_{min}}, \dots, u_{l_{min}, l_{min}}, \quad
|
|
26
|
+
u_{l_{min}+1, -(l_{min}+1)}, \dots, u_{l_{min}+1, l_{min}+1}, \quad \dots]
|
|
27
|
+
|
|
28
|
+
**Example (lmin=0):**
|
|
17
29
|
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
.. math::
|
|
31
|
+
[u_{0,0}, \quad u_{1,-1}, u_{1,0}, u_{1,1}, \quad u_{2,-2}, u_{2,-1}, u_{2,0}, u_{2,1}, u_{2,2}, \dots]
|
|
20
32
|
|
|
21
33
|
Args:
|
|
22
34
|
lmax (int): The maximum spherical harmonic degree to include.
|
|
23
|
-
lmin (int): The minimum spherical harmonic degree to include. Defaults to
|
|
35
|
+
lmin (int): The minimum spherical harmonic degree to include. Defaults to 0.
|
|
24
36
|
"""
|
|
25
37
|
|
|
26
38
|
def __init__(self, lmax: int, lmin: int = 0):
|
|
@@ -532,30 +532,26 @@ class Lebesgue(SphereHelper, HilbertModule, AbstractInvariantLebesgueSpace):
|
|
|
532
532
|
)
|
|
533
533
|
|
|
534
534
|
def to_coefficient_operator(self, lmax: int, lmin: int = 0):
|
|
535
|
-
"""
|
|
536
|
-
Returns a LinearOperator
|
|
537
|
-
a vector of its spherical harmonic coefficients within the
|
|
538
|
-
specified range of degrees.
|
|
535
|
+
r"""
|
|
536
|
+
Returns a LinearOperator mapping a function to its spherical harmonic coefficients.
|
|
539
537
|
|
|
540
|
-
The
|
|
538
|
+
The operator maps an element of the Hilbert space to a vector in $\mathbb{R}^k$.
|
|
539
|
+
The coefficients in the output vector are ordered by degree $l$ (major)
|
|
540
|
+
and order $m$ (minor), from $-l$ to $+l$.
|
|
541
541
|
|
|
542
|
-
|
|
542
|
+
**Ordering:**
|
|
543
543
|
|
|
544
|
-
|
|
544
|
+
.. math::
|
|
545
|
+
u = [u_{0,0}, \quad u_{1,-1}, u_{1,0}, u_{1,1}, \quad u_{2,-2}, \dots, u_{2,2}, \quad \dots]
|
|
545
546
|
|
|
546
|
-
|
|
547
|
+
(assuming `lmin=0`).
|
|
547
548
|
|
|
548
549
|
Args:
|
|
549
550
|
lmax: The maximum spherical harmonic degree to include in the output.
|
|
550
|
-
lmin: The minimum spherical harmonic degree to include
|
|
551
|
-
Defaults to 0.
|
|
551
|
+
lmin: The minimum spherical harmonic degree to include. Defaults to 0.
|
|
552
552
|
|
|
553
553
|
Returns:
|
|
554
|
-
A LinearOperator
|
|
555
|
-
|
|
556
|
-
Notes:
|
|
557
|
-
This is a left inverse of the from_coefficient_operator so long a the
|
|
558
|
-
values for lmin and lmax are equal.
|
|
554
|
+
A LinearOperator mapping `SHGrid` -> `numpy.ndarray`.
|
|
559
555
|
"""
|
|
560
556
|
|
|
561
557
|
converter = SHVectorConverter(lmax, lmin)
|
|
@@ -577,27 +573,25 @@ class Lebesgue(SphereHelper, HilbertModule, AbstractInvariantLebesgueSpace):
|
|
|
577
573
|
return LinearOperator(self, codomain, mapping, adjoint_mapping=adjoint_mapping)
|
|
578
574
|
|
|
579
575
|
def from_coefficient_operator(self, lmax: int, lmin: int = 0):
|
|
580
|
-
"""
|
|
581
|
-
Returns a LinearOperator
|
|
582
|
-
to an element of the space.
|
|
576
|
+
r"""
|
|
577
|
+
Returns a LinearOperator mapping a vector of coefficients to a function.
|
|
583
578
|
|
|
584
|
-
The
|
|
579
|
+
The operator maps a vector in $\mathbb{R}^k$ to an element of the Hilbert space.
|
|
580
|
+
The input vector must follow the standard $l$-major, $m$-minor ordering.
|
|
585
581
|
|
|
586
|
-
|
|
582
|
+
**Ordering:**
|
|
587
583
|
|
|
588
|
-
|
|
584
|
+
.. math::
|
|
585
|
+
v = [u_{0,0}, \quad u_{1,-1}, u_{1,0}, u_{1,1}, \quad u_{2,-2}, \dots, u_{2,2}, \quad \dots]
|
|
586
|
+
|
|
587
|
+
(assuming `lmin=0`).
|
|
589
588
|
|
|
590
589
|
Args:
|
|
591
|
-
lmax: The maximum spherical harmonic degree
|
|
592
|
-
lmin: The minimum spherical harmonic degree
|
|
593
|
-
Defaults to 0.
|
|
590
|
+
lmax: The maximum spherical harmonic degree expected in the input.
|
|
591
|
+
lmin: The minimum spherical harmonic degree expected. Defaults to 0.
|
|
594
592
|
|
|
595
593
|
Returns:
|
|
596
|
-
A LinearOperator
|
|
597
|
-
|
|
598
|
-
Notes:
|
|
599
|
-
This is a right inverse of the to_coefficient_operator so long a the
|
|
600
|
-
values for lmin and lmax are equal.
|
|
594
|
+
A LinearOperator mapping `numpy.ndarray` -> `SHGrid`.
|
|
601
595
|
"""
|
|
602
596
|
|
|
603
597
|
converter = SHVectorConverter(lmax, lmin)
|
|
@@ -783,30 +777,26 @@ class Sobolev(SphereHelper, MassWeightedHilbertModule, AbstractInvariantSobolevS
|
|
|
783
777
|
)
|
|
784
778
|
|
|
785
779
|
def to_coefficient_operator(self, lmax: int, lmin: int = 0):
|
|
786
|
-
"""
|
|
787
|
-
Returns a LinearOperator
|
|
788
|
-
a vector of its spherical harmonic coefficients within the
|
|
789
|
-
specified range of degrees.
|
|
780
|
+
r"""
|
|
781
|
+
Returns a LinearOperator mapping a function to its spherical harmonic coefficients.
|
|
790
782
|
|
|
791
|
-
The
|
|
783
|
+
The operator maps an element of the Hilbert space to a vector in $\mathbb{R}^k$.
|
|
784
|
+
The coefficients in the output vector are ordered by degree $l$ (major)
|
|
785
|
+
and order $m$ (minor), from $-l$ to $+l$.
|
|
792
786
|
|
|
793
|
-
|
|
787
|
+
**Ordering:**
|
|
794
788
|
|
|
795
|
-
|
|
789
|
+
.. math::
|
|
790
|
+
u = [u_{0,0}, \quad u_{1,-1}, u_{1,0}, u_{1,1}, \quad u_{2,-2}, \dots, u_{2,2}, \quad \dots]
|
|
796
791
|
|
|
797
|
-
|
|
792
|
+
(assuming `lmin=0`).
|
|
798
793
|
|
|
799
794
|
Args:
|
|
800
795
|
lmax: The maximum spherical harmonic degree to include in the output.
|
|
801
|
-
lmin: The minimum spherical harmonic degree to include
|
|
802
|
-
Defaults to 0.
|
|
796
|
+
lmin: The minimum spherical harmonic degree to include. Defaults to 0.
|
|
803
797
|
|
|
804
798
|
Returns:
|
|
805
|
-
A LinearOperator
|
|
806
|
-
|
|
807
|
-
Notes:
|
|
808
|
-
This is a left inverse of the from_coefficient_operator so long a the
|
|
809
|
-
values for lmin and lmax are equal.
|
|
799
|
+
A LinearOperator mapping `SHGrid` -> `numpy.ndarray`.
|
|
810
800
|
"""
|
|
811
801
|
|
|
812
802
|
l2_operator = self.underlying_space.to_coefficient_operator(lmax, lmin)
|
|
@@ -816,27 +806,25 @@ class Sobolev(SphereHelper, MassWeightedHilbertModule, AbstractInvariantSobolevS
|
|
|
816
806
|
)
|
|
817
807
|
|
|
818
808
|
def from_coefficient_operator(self, lmax: int, lmin: int = 0):
|
|
819
|
-
"""
|
|
820
|
-
Returns a LinearOperator
|
|
821
|
-
to an element of the space.
|
|
809
|
+
r"""
|
|
810
|
+
Returns a LinearOperator mapping a vector of coefficients to a function.
|
|
822
811
|
|
|
823
|
-
The
|
|
812
|
+
The operator maps a vector in $\mathbb{R}^k$ to an element of the Hilbert space.
|
|
813
|
+
The input vector must follow the standard $l$-major, $m$-minor ordering.
|
|
824
814
|
|
|
825
|
-
|
|
815
|
+
**Ordering:**
|
|
826
816
|
|
|
827
|
-
|
|
817
|
+
.. math::
|
|
818
|
+
v = [u_{0,0}, \quad u_{1,-1}, u_{1,0}, u_{1,1}, \quad u_{2,-2}, \dots, u_{2,2}, \quad \dots]
|
|
819
|
+
|
|
820
|
+
(assuming `lmin=0`).
|
|
828
821
|
|
|
829
822
|
Args:
|
|
830
|
-
lmax: The maximum spherical harmonic degree
|
|
831
|
-
lmin: The minimum spherical harmonic degree
|
|
832
|
-
Defaults to 0.
|
|
823
|
+
lmax: The maximum spherical harmonic degree expected in the input.
|
|
824
|
+
lmin: The minimum spherical harmonic degree expected. Defaults to 0.
|
|
833
825
|
|
|
834
826
|
Returns:
|
|
835
|
-
A LinearOperator
|
|
836
|
-
|
|
837
|
-
Notes:
|
|
838
|
-
This is a right inverse of the to_coefficient_operator so long a the
|
|
839
|
-
values for lmin and lmax are equal.
|
|
827
|
+
A LinearOperator mapping `numpy.ndarray` -> `SHGrid`.
|
|
840
828
|
"""
|
|
841
829
|
|
|
842
830
|
l2_operator = self.underlying_space.from_coefficient_operator(lmax, lmin)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
pygeoinf/__init__.py,sha256=
|
|
1
|
+
pygeoinf/__init__.py,sha256=OdtIgD3aF4LQ4UzponWblw4nQihRntqnni7m1DPdd5I,4076
|
|
2
2
|
pygeoinf/auxiliary.py,sha256=lfoTt9ZH4y8SAV8dKZi5EWx1oF_JtxtBMSmlFYqJYfE,1610
|
|
3
3
|
pygeoinf/backus_gilbert.py,sha256=eFi4blSwOCsg_NuH6WD4gcgjvzvu5g5WpWahGobSBdM,3694
|
|
4
4
|
pygeoinf/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -10,24 +10,25 @@ pygeoinf/forward_problem.py,sha256=NnqWp7iMfkhHa9d-jBHzYHClaAfhKmO5D058AcJLLYg,1
|
|
|
10
10
|
pygeoinf/gaussian_measure.py,sha256=bBh64xHgmLFl27krn9hkf8qDQjop_39x69cyhJgUHN8,26219
|
|
11
11
|
pygeoinf/hilbert_space.py,sha256=Yc0Jw0A8Jo12Zpgb_9dhcF7CD77S1IDMrSTDFHpTRB8,27340
|
|
12
12
|
pygeoinf/inversion.py,sha256=RV0hG2bGnciWdja0oOPKPxnFhYzufqdj-mKYNr4JJ_o,6447
|
|
13
|
-
pygeoinf/linear_bayesian.py,sha256=
|
|
13
|
+
pygeoinf/linear_bayesian.py,sha256=qzWEVaNe9AwG5GBmGHgVHswEMFKBWvOOJDlS95ahyxc,8877
|
|
14
14
|
pygeoinf/linear_forms.py,sha256=mgZeDRegNKo8kviE68KrxkHR4gG9bf1RgsJz1MtDMCk,9181
|
|
15
15
|
pygeoinf/linear_operators.py,sha256=Bn-uzwUXi2kkWZ7wc9Uhj3vBHtocN17hnzc_r7DAzTk,64530
|
|
16
|
-
pygeoinf/linear_optimisation.py,sha256=
|
|
17
|
-
pygeoinf/linear_solvers.py,sha256=
|
|
16
|
+
pygeoinf/linear_optimisation.py,sha256=RhO-1OsEDGnVHBlCtYyqp8jmW4GeGnGWGPRYPSc5GSg,13922
|
|
17
|
+
pygeoinf/linear_solvers.py,sha256=tYBp_ysePnOgqgKhMXhNHxLM8xi3awiwwdnKXHhmlNk,31071
|
|
18
18
|
pygeoinf/nonlinear_forms.py,sha256=t7lk-Bha7Xdk9eiwXMmS0F47oTR6jW6qQ3HkgRGk54A,7012
|
|
19
19
|
pygeoinf/nonlinear_operators.py,sha256=AtkDTQfGDzAnfFDIgiKfdk7uPEI-j_ZA3CNvY5A3U8w,7144
|
|
20
20
|
pygeoinf/nonlinear_optimisation.py,sha256=skK1ikn9GrVYherD64Qt9WrEYHA2NAJ48msOu_J8Oig,7431
|
|
21
21
|
pygeoinf/parallel.py,sha256=VVFvNHszy4wSa9LuErIsch4NAkLaZezhdN9YpRROBJo,2267
|
|
22
22
|
pygeoinf/plot.py,sha256=Uw9PCdxymUiAkFF0BS0kUAZBRWL6sh89FJnSIxtp_2s,13664
|
|
23
|
-
pygeoinf/
|
|
24
|
-
pygeoinf/
|
|
23
|
+
pygeoinf/preconditioners.py,sha256=81PnzoQZzsf5mvXBYsHuadf1CdiGFlMbQn_tC2xPQ1k,4503
|
|
24
|
+
pygeoinf/random_matrix.py,sha256=-U_3-yrVos_86EfNy1flULsWY-Y9G9Yy1GKoSS2gn60,17828
|
|
25
|
+
pygeoinf/subspaces.py,sha256=FJobjDRr8JG1zz-TjBsncJ1M5phQYwbttlaGuJz9ycU,13779
|
|
25
26
|
pygeoinf/symmetric_space/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
27
|
pygeoinf/symmetric_space/circle.py,sha256=GuwVmLdHGTMxMrZfyXIPP3pz_y971ntlD5pl42lKJZ0,18796
|
|
27
|
-
pygeoinf/symmetric_space/sh_tools.py,sha256=
|
|
28
|
-
pygeoinf/symmetric_space/sphere.py,sha256=
|
|
28
|
+
pygeoinf/symmetric_space/sh_tools.py,sha256=EDZm0YRZefvCfDjAKZatZMM3UqeTi-Npiflnc1E5slk,3884
|
|
29
|
+
pygeoinf/symmetric_space/sphere.py,sha256=wYaZ2wqkQAHw9pn4vP_6LR9HAXSpzCncCh24xmSSC5A,28481
|
|
29
30
|
pygeoinf/symmetric_space/symmetric_space.py,sha256=pEIZZYWsdegrYCwUs3bo86JTz3d2LsXFWdRYFa0syFs,17963
|
|
30
|
-
pygeoinf-1.3.
|
|
31
|
-
pygeoinf-1.3.
|
|
32
|
-
pygeoinf-1.3.
|
|
33
|
-
pygeoinf-1.3.
|
|
31
|
+
pygeoinf-1.3.7.dist-info/METADATA,sha256=rJugIyw0YNv6ccIFCnXNmISbwUclP-V8Zt1ZDLbqPpw,16482
|
|
32
|
+
pygeoinf-1.3.7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
33
|
+
pygeoinf-1.3.7.dist-info/licenses/LICENSE,sha256=GrTQnKJemVi69FSbHprq60KN0OJGsOSR-joQoTq-oD8,1501
|
|
34
|
+
pygeoinf-1.3.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|