modulo-vki 2.1.4__py3-none-any.whl → 2.1.5__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.
- modulo_vki/core/spatial_structures.py +6 -7
- modulo_vki/modulo.py +7 -8
- {modulo_vki-2.1.4.dist-info → modulo_vki-2.1.5.dist-info}/METADATA +3 -2
- {modulo_vki-2.1.4.dist-info → modulo_vki-2.1.5.dist-info}/RECORD +7 -10
- {modulo_vki-2.1.4.dist-info → modulo_vki-2.1.5.dist-info}/WHEEL +1 -1
- modulo_vki-2.1.5.dist-info/top_level.txt +1 -0
- modulo_vki-2.1.4.dist-info/top_level.txt +0 -2
- modulo_vki_2/__init__.py +0 -0
- modulo_vki_2/modulo.py +0 -187
- modulo_vki_2/utils.py +0 -22
- {modulo_vki-2.1.4.dist-info → modulo_vki-2.1.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -51,9 +51,8 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING,
|
|
|
51
51
|
if verbose:
|
|
52
52
|
print("Completing Spatial Structures Modes: \n")
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Phi_P[:, i] = PHI_P_SIGMA_P[:, i] / Sigma_P[i]
|
|
54
|
+
Sigma_P[:] = np.linalg.norm(PHI_P_SIGMA_P, axis=0)
|
|
55
|
+
Phi_P = PHI_P_SIGMA_P / Sigma_P
|
|
57
56
|
|
|
58
57
|
else:
|
|
59
58
|
# We take only the first R modes.
|
|
@@ -156,7 +155,7 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING,
|
|
|
156
155
|
R1 = (i - 1) * dim_col
|
|
157
156
|
R2 = i * dim_col
|
|
158
157
|
|
|
159
|
-
if (b == tot_blocks_row) and (N_S - dim_row * N_PARTITIONS > 0):
|
|
158
|
+
if (b == tot_blocks_row) and (N_S - dim_row * N_PARTITIONS > 0):
|
|
160
159
|
C1 = C2
|
|
161
160
|
C2 = C1 + (N_S - dim_row * N_PARTITIONS)
|
|
162
161
|
else:
|
|
@@ -169,13 +168,13 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING,
|
|
|
169
168
|
if rescale:
|
|
170
169
|
for j in range(R1, R2):
|
|
171
170
|
jj = j - R1
|
|
172
|
-
Sigma_P[
|
|
173
|
-
Phi_P = dps[:, jj] / Sigma_P[
|
|
171
|
+
Sigma_P[j] = np.linalg.norm(dps[:, jj])
|
|
172
|
+
Phi_P = dps[:, jj] / Sigma_P[j]
|
|
174
173
|
np.savez(FOLDER_OUT + f"/phi_{j + 1}", phi_p=Phi_P)
|
|
175
174
|
else:
|
|
176
175
|
for j in range(R1, R2):
|
|
177
176
|
jj = j - R1
|
|
178
|
-
Phi_P = dps[:, jj] / Sigma_P[j]
|
|
177
|
+
Phi_P = dps[:, jj] / Sigma_P[j]
|
|
179
178
|
np.savez(FOLDER_OUT + f"/phi_{j + 1}", phi_p=Phi_P)
|
|
180
179
|
|
|
181
180
|
Phi_P_M = np.zeros((N_S, R))
|
modulo_vki/modulo.py
CHANGED
|
@@ -660,14 +660,13 @@ class ModuloVKI:
|
|
|
660
660
|
Sigma_sP : numpy.ndarray, shape (n_Modes,)
|
|
661
661
|
Modal energies (eigenvalues of the filtered covariance).
|
|
662
662
|
"""
|
|
663
|
-
|
|
664
|
-
D = np.load(self.FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
|
|
665
|
-
else:
|
|
666
|
-
D = self.D
|
|
667
|
-
|
|
663
|
+
|
|
668
664
|
self.K = CorrelationMatrix(self.N_T, self.N_PARTITIONS, self.MEMORY_SAVING,
|
|
669
|
-
self.FOLDER_OUT, self.SAVE_K, D=
|
|
670
|
-
|
|
665
|
+
self.FOLDER_OUT, self.SAVE_K, D=self.Dstar)
|
|
666
|
+
|
|
667
|
+
if self.MEMORY_SAVING:
|
|
668
|
+
self.K = np.load(self.FOLDER_OUT + '/correlation_matrix/k_matrix.npz')['K']
|
|
669
|
+
|
|
671
670
|
# additional step: diagonal spectral filter of K
|
|
672
671
|
K_F = spectral_filter(self.K, N_o=N_O, f_c=f_c)
|
|
673
672
|
|
|
@@ -675,7 +674,7 @@ class ModuloVKI:
|
|
|
675
674
|
Psi_P, Sigma_P = Temporal_basis_POD(K_F, SAVE_SPOD, self.FOLDER_OUT, n_Modes)
|
|
676
675
|
|
|
677
676
|
# but with a normalization aspect to handle the non-orthogonality of the SPOD modes
|
|
678
|
-
Phi_P = Spatial_basis_POD(D, N_T=self.K.shape[0],
|
|
677
|
+
Phi_P = Spatial_basis_POD(self.D, N_T=self.K.shape[0],
|
|
679
678
|
PSI_P=Psi_P, Sigma_P=Sigma_P,
|
|
680
679
|
MEMORY_SAVING=self.MEMORY_SAVING,
|
|
681
680
|
FOLDER_OUT=self.FOLDER_OUT,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modulo_vki
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.5
|
|
4
4
|
Summary: MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform Multiscale Modal Analysis of numerical and experimental data.
|
|
5
5
|
Home-page: https://github.com/mendezVKI/MODULO/tree/master/modulo_python_package/
|
|
6
6
|
Author: ['R. Poletti', 'L. Schena', 'D. Ninni', 'M. A. Mendez']
|
|
@@ -48,7 +48,8 @@ While the discontinued MATLAB version of MODULO is accessible in the “Old_Matl
|
|
|
48
48
|
it is no longer maintained. The latest decomposition techniques are exclusively available in the current Python version (`Poletti et al. (2024) <https://joss.theoj.org/papers/10.21105/joss.06753>`_).
|
|
49
49
|
|
|
50
50
|
As a part of the MODULO project, we provide a series of lectures on data-driven modal decomposition, and its applications.
|
|
51
|
-
These are available at the `MODULO YouTube channel <https://www.youtube.com/@modulompod5682>`_.
|
|
51
|
+
These are available at the `MODULO YouTube channel <https://www.youtube.com/@modulompod5682>`_.
|
|
52
|
+
The full package documentation can be found at: `MODULO ReadTheDocs <https://lorenzoschena.github.io/MODULO/intro.html>`_.
|
|
52
53
|
|
|
53
54
|
.. contents:: Table of contents
|
|
54
55
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
modulo_vki/__init__.py,sha256=AOjmeFjHj69m45iZzfTHM6-SLUelgKdGeu3VdSg9hIo,39
|
|
2
|
-
modulo_vki/modulo.py,sha256=
|
|
2
|
+
modulo_vki/modulo.py,sha256=XbPyzd5sugYHtgKsPZ220BoWT0L3iqi-JDYXlcFTu0g,38478
|
|
3
3
|
modulo_vki/modulo_old.py,sha256=3r_BBYQfbmZWGDyPukyJTVYVVcAVuEE0CmREEJkzsxU,59413
|
|
4
4
|
modulo_vki/core/__init__.py,sha256=y9mIqtmSg3o8TXMqFxoiMCoMSle6mK0LBrvNJCVM1Zg,226
|
|
5
5
|
modulo_vki/core/_dft.py,sha256=W98vC4HR1fivZjYRQXrFKV7RBa-O3RSRwq-nCKoxqjQ,4374
|
|
@@ -11,7 +11,7 @@ modulo_vki/core/_pod_space.py,sha256=A3dfv4Nzs9fx3qwOdlJR5HwyyfI-QcVer8P83xqa_C4
|
|
|
11
11
|
modulo_vki/core/_pod_time.py,sha256=JtiFGYFV-tBKTWHWHW8zynMoLt2q8bD1bd1LP9pyvjo,2169
|
|
12
12
|
modulo_vki/core/_spod_s.py,sha256=rxXSsNdSTLv3sjvlUErw3xjHk0eF8H7IkSJr5nMQ8Vo,4149
|
|
13
13
|
modulo_vki/core/_spod_t.py,sha256=csftCPRSqs-OghQa8l0mRDL7cy5eXXSCnW8O4pnXTCY,3866
|
|
14
|
-
modulo_vki/core/spatial_structures.py,sha256=
|
|
14
|
+
modulo_vki/core/spatial_structures.py,sha256=XRdhcZM0TdUW0PRaRKU8BU3u74H36WGEIx1YHLjrPs4,14620
|
|
15
15
|
modulo_vki/core/temporal_structures.py,sha256=0DQEdE9ssTnnfIC86VZPsNlym6fsjRAboPHHnv-9CI4,10645
|
|
16
16
|
modulo_vki/core/utils.py,sha256=Ac9Im9knlbZRByP6Qgv-LCDt5zEC8PbyidqXzVdeYtQ,17889
|
|
17
17
|
modulo_vki/utils/__init__.py,sha256=F5yy5R19dONK9oaBEpKzylorVJNcjT2kiJ5Og-ZX1ek,94
|
|
@@ -19,11 +19,8 @@ modulo_vki/utils/_plots.py,sha256=m43t08cVq-TY0BW0YPqT71hN-54hBphIYKZEn8Kw16E,14
|
|
|
19
19
|
modulo_vki/utils/_utils.py,sha256=WFD7nwjSzVHpevVwTEvMdjAmcbeqwoXT9M48tIIniJw,14355
|
|
20
20
|
modulo_vki/utils/others.py,sha256=9yZzD0_rZIOWYjV2Hbi74N5oXEYct7o5h9ZjNkmxHPw,17338
|
|
21
21
|
modulo_vki/utils/read_db.py,sha256=lJFauxJxS0_mYoxrbn-43UqZjOkr-qb9f6RTUq4IxZU,15149
|
|
22
|
-
modulo_vki-2.1.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
modulo_vki-2.1.
|
|
27
|
-
modulo_vki-2.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
28
|
-
modulo_vki-2.1.4.dist-info/top_level.txt,sha256=xP1gbt8FGvhIM5-zQagZXO7ut-yjUI4cXuM2GeypNuw,24
|
|
29
|
-
modulo_vki-2.1.4.dist-info/RECORD,,
|
|
22
|
+
modulo_vki-2.1.5.dist-info/licenses/LICENSE,sha256=5TivriXFErrYrJgBq3M72kHNHqtSiCft3xESM1zHc0k,1091
|
|
23
|
+
modulo_vki-2.1.5.dist-info/METADATA,sha256=J0fY2NItK7F6s1XfraHXgbRKjjxa5EIMstXUUoFs7ns,16857
|
|
24
|
+
modulo_vki-2.1.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
25
|
+
modulo_vki-2.1.5.dist-info/top_level.txt,sha256=4PA4AmafKU6M7us7gvt_Q976Khx3qjNUEThRRM5zxeA,11
|
|
26
|
+
modulo_vki-2.1.5.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
modulo_vki
|
modulo_vki_2/__init__.py
DELETED
|
File without changes
|
modulo_vki_2/modulo.py
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class ModuloVKI:
|
|
7
|
-
"""
|
|
8
|
-
MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute
|
|
9
|
-
to perform Multiscale Modal Analysis using Multiscale Proper Orthogonal Decomposition (mPOD)
|
|
10
|
-
on numerical and experimental data.
|
|
11
|
-
|
|
12
|
-
References
|
|
13
|
-
----------
|
|
14
|
-
- Theoretical foundation:
|
|
15
|
-
https://arxiv.org/abs/1804.09646
|
|
16
|
-
|
|
17
|
-
- MODULO framework presentation:
|
|
18
|
-
https://arxiv.org/pdf/2004.12123.pdf
|
|
19
|
-
|
|
20
|
-
- Hands-on tutorial videos:
|
|
21
|
-
https://youtube.com/playlist?list=PLEJZLD0-4PeKW6Ze984q08bNz28GTntkR
|
|
22
|
-
|
|
23
|
-
Notes
|
|
24
|
-
-----
|
|
25
|
-
MODULO operations assume the dataset is uniformly spaced in both space
|
|
26
|
-
(Cartesian grid) and time. For non-cartesian grids, the user must
|
|
27
|
-
provide a weights vector `[w_1, w_2, ..., w_Ns]` where `w_i = area_cell_i / area_grid`.
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
def __init__(self,
|
|
31
|
-
data: np.ndarray,
|
|
32
|
-
N_PARTITIONS: int = 1,
|
|
33
|
-
FOLDER_OUT: str = './',
|
|
34
|
-
SAVE_K: bool = False,
|
|
35
|
-
N_T: int = 100,
|
|
36
|
-
N_S: int = 200,
|
|
37
|
-
n_Modes: int = 10,
|
|
38
|
-
dtype: str = 'float32',
|
|
39
|
-
eig_solver: str = 'eigh',
|
|
40
|
-
svd_solver: str = 'svd_sklearn_truncated',
|
|
41
|
-
weights: np.ndarray = np.array([])):
|
|
42
|
-
"""
|
|
43
|
-
Initialize the MODULO analysis.
|
|
44
|
-
|
|
45
|
-
Parameters
|
|
46
|
-
----------
|
|
47
|
-
data : np.ndarray
|
|
48
|
-
Data matrix of shape (N_S, N_T) to factorize. If not yet formatted, use the `ReadData`
|
|
49
|
-
method provided by MODULO. When memory saving mode (N_PARTITIONS > 1) is active,
|
|
50
|
-
set this parameter to None and use prepared partitions instead.
|
|
51
|
-
|
|
52
|
-
N_PARTITIONS : int, default=1
|
|
53
|
-
Number of partitions used for memory-saving computation. If set greater than 1,
|
|
54
|
-
data must be partitioned in advance and `data` set to None.
|
|
55
|
-
|
|
56
|
-
FOLDER_OUT : str, default='./'
|
|
57
|
-
Directory path to store output (Phi, Sigma, Psi matrices) and intermediate
|
|
58
|
-
calculation files (e.g., partitions, correlation matrix).
|
|
59
|
-
|
|
60
|
-
SAVE_K : bool, default=False
|
|
61
|
-
Whether to store the correlation matrix K to disk in
|
|
62
|
-
`FOLDER_OUT/correlation_matrix`.
|
|
63
|
-
|
|
64
|
-
N_T : int, default=100
|
|
65
|
-
Number of temporal snapshots. Mandatory when using partitions (N_PARTITIONS > 1).
|
|
66
|
-
|
|
67
|
-
N_S : int, default=200
|
|
68
|
-
Number of spatial grid points. Mandatory when using partitions (N_PARTITIONS > 1).
|
|
69
|
-
|
|
70
|
-
n_Modes : int, default=10
|
|
71
|
-
Number of modes to compute.
|
|
72
|
-
|
|
73
|
-
dtype : str, default='float32'
|
|
74
|
-
Data type for casting input data.
|
|
75
|
-
|
|
76
|
-
eig_solver : str, default='eigh'
|
|
77
|
-
Solver for eigenvalue decomposition.
|
|
78
|
-
|
|
79
|
-
svd_solver : str, default='svd_sklearn_truncated'
|
|
80
|
-
Solver for Singular Value Decomposition (SVD).
|
|
81
|
-
|
|
82
|
-
weights : np.ndarray, default=np.array([])
|
|
83
|
-
Weights vector `[w_1, w_2, ..., w_Ns]` to account for non-uniform spatial grids.
|
|
84
|
-
Defined as `w_i = area_cell_i / area_grid`. Leave empty for uniform grids.
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
print("MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform "
|
|
88
|
-
"data driven modal decomposition of numerical and experimental data. \n")
|
|
89
|
-
|
|
90
|
-
if not isinstance(data, np.ndarray) and N_PARTITIONS == 1:
|
|
91
|
-
raise TypeError(
|
|
92
|
-
"Please check that your database is in an numpy array format. If D=None, then you must have memory saving (N_PARTITIONS>1)")
|
|
93
|
-
|
|
94
|
-
if N_PARTITIONS > 1:
|
|
95
|
-
self.MEMORY_SAVING = True
|
|
96
|
-
else:
|
|
97
|
-
self.MEMORY_SAVING = False
|
|
98
|
-
|
|
99
|
-
# Assign the number of modes
|
|
100
|
-
self.n_Modes = n_Modes
|
|
101
|
-
# If particular needs, override choice for svd and eigen solve
|
|
102
|
-
self.svd_solver = svd_solver.lower()
|
|
103
|
-
self.eig_solver = eig_solver.lower()
|
|
104
|
-
possible_svds = ['svd_numpy', 'svd_scipy_sparse', 'svd_sklearn_randomized', 'svd_sklearn_truncated']
|
|
105
|
-
possible_eigs = ['svd_sklearn_randomized', 'eigsh', 'eigh']
|
|
106
|
-
|
|
107
|
-
if self.svd_solver not in possible_svds:
|
|
108
|
-
raise NotImplementedError("The requested SVD solver is not implemented. Please pick one of the following:"
|
|
109
|
-
"which belongs to: \n {}".format(possible_svds))
|
|
110
|
-
|
|
111
|
-
if self.eig_solver not in possible_eigs:
|
|
112
|
-
raise NotImplementedError("The requested EIG solver is not implemented. Please pick one of the following: "
|
|
113
|
-
" \n {}".format(possible_eigs))
|
|
114
|
-
|
|
115
|
-
# if N_PARTITIONS >= self.N_T:
|
|
116
|
-
# raise AttributeError("The number of requested partitions is greater of the total columns (N_T). Please,"
|
|
117
|
-
# "try again.")
|
|
118
|
-
|
|
119
|
-
self.N_PARTITIONS = N_PARTITIONS
|
|
120
|
-
self.FOLDER_OUT = FOLDER_OUT
|
|
121
|
-
self.SAVE_K = SAVE_K
|
|
122
|
-
|
|
123
|
-
if self.MEMORY_SAVING:
|
|
124
|
-
os.makedirs(self.FOLDER_OUT, exist_ok=True)
|
|
125
|
-
|
|
126
|
-
# Load the data matrix
|
|
127
|
-
if isinstance(data, np.ndarray):
|
|
128
|
-
# Number of points in time and space
|
|
129
|
-
self.N_T = data.shape[1]
|
|
130
|
-
self.N_S = data.shape[0]
|
|
131
|
-
# Check the data type
|
|
132
|
-
self.D = data.astype(dtype)
|
|
133
|
-
else:
|
|
134
|
-
self.D = None # D is never saved when N_partitions >1
|
|
135
|
-
self.N_S = N_S # so N_S and N_t must be given as parameters of modulo
|
|
136
|
-
self.N_T = N_T
|
|
137
|
-
|
|
138
|
-
'''If the grid is not cartesian, ensure inner product is properly defined using weights.'''
|
|
139
|
-
|
|
140
|
-
if weights.size == 0:
|
|
141
|
-
print('Modulo assumes you have a uniform grid. If not, please provide weights as parameters.')
|
|
142
|
-
else:
|
|
143
|
-
if len(weights) == self.N_S:
|
|
144
|
-
print("The weights you have input have the size of the columns of D \n"
|
|
145
|
-
"MODULO has considered that you have already duplicated the dimensions of the weights "
|
|
146
|
-
"to match the dimensions of the D columns \n")
|
|
147
|
-
self.weights = weights
|
|
148
|
-
elif len(weights) == 2 * self.N_S:
|
|
149
|
-
print("Assuming 2D domain. Automatically duplicating the weights to match the dimension of the D columns \n")
|
|
150
|
-
self.weights = np.concatenate((weights, weights))
|
|
151
|
-
else:
|
|
152
|
-
raise AttributeError("Make sure the size of the weight array is twice smaller than the size of D")
|
|
153
|
-
|
|
154
|
-
if isinstance(data, np.ndarray):
|
|
155
|
-
# Apply the weights only if D exist.
|
|
156
|
-
# If not (i.e. N_partitions >1), weights are applied in _k_matrix.py when loading partitions of D
|
|
157
|
-
self.Dstar = np.transpose(np.transpose(self.D) * np.sqrt(self.weights))
|
|
158
|
-
else:
|
|
159
|
-
self.Dstar = None
|
|
160
|
-
|
|
161
|
-
def compute(
|
|
162
|
-
self,
|
|
163
|
-
kind: str,
|
|
164
|
-
**engine_kwargs
|
|
165
|
-
) -> tuple:
|
|
166
|
-
"""
|
|
167
|
-
Unified entry point for all decompositions: POD, SPOD, kPOD, DMD, DFT.
|
|
168
|
-
Any engine‐specific parameters (e.g. F_S, L_B, gamma…) can be passed here
|
|
169
|
-
and will be forwarded to the chosen engine’s constructor.
|
|
170
|
-
"""
|
|
171
|
-
engine_cls = self._engines.get(kind.lower())
|
|
172
|
-
if engine_cls is None:
|
|
173
|
-
raise ValueError(f"Unknown decomposition '{kind}'")
|
|
174
|
-
|
|
175
|
-
# pick the right data array
|
|
176
|
-
D_use = self.Dstar # or self.D if you want un-weighted
|
|
177
|
-
|
|
178
|
-
engine = engine_cls(
|
|
179
|
-
D=D_use,
|
|
180
|
-
folder_out=self.FOLDER_OUT,
|
|
181
|
-
save_k=self.SAVE_K,
|
|
182
|
-
memory_saving=self.MEMORY_SAVING,
|
|
183
|
-
n_partitions=self.N_PARTITIONS,
|
|
184
|
-
**engine_kwargs
|
|
185
|
-
)
|
|
186
|
-
return engine.run()
|
|
187
|
-
|
modulo_vki_2/utils.py
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
def apply_weights(D: np.ndarray, weights: np.ndarray) -> np.ndarray:
|
|
4
|
-
"""
|
|
5
|
-
If `weights` is empty, return D unchanged.
|
|
6
|
-
If `weights` has length n_s, assume 1D grid and tile automatically.
|
|
7
|
-
If `weights` has length 2*n_s, assume 2D grid and use directly.
|
|
8
|
-
Returns D_star = D * sqrt(w) applied column-wise.
|
|
9
|
-
"""
|
|
10
|
-
n_s, n_t = D.shape
|
|
11
|
-
if weights.size == 0:
|
|
12
|
-
return D
|
|
13
|
-
w = np.asarray(weights, dtype=D.dtype)
|
|
14
|
-
if w.size == n_s:
|
|
15
|
-
# 1D grid: automatically broadcast each weight to full time series
|
|
16
|
-
w_full = np.repeat(w, n_t//n_s) # or tile as needed for time dims
|
|
17
|
-
elif w.size == 2*n_s:
|
|
18
|
-
w_full = w
|
|
19
|
-
else:
|
|
20
|
-
raise ValueError(f"weights must be length {n_s} or {2*n_s}, got {w.size}")
|
|
21
|
-
# apply weights: scale each row i by sqrt(w_full[i])
|
|
22
|
-
return (D.T * np.sqrt(w_full)).T
|
|
File without changes
|