dfm-python 0.2.7__py3-none-any.whl → 0.2.8__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.
- dfm_python/__init__.py +1 -1
- dfm_python/core/diagnostics.py +215 -6
- dfm_python/core/em.py +49 -49
- dfm_python/core/numeric.py +7 -7
- {dfm_python-0.2.7.dist-info → dfm_python-0.2.8.dist-info}/METADATA +1 -1
- {dfm_python-0.2.7.dist-info → dfm_python-0.2.8.dist-info}/RECORD +8 -8
- {dfm_python-0.2.7.dist-info → dfm_python-0.2.8.dist-info}/WHEEL +0 -0
- {dfm_python-0.2.7.dist-info → dfm_python-0.2.8.dist-info}/licenses/LICENSE +0 -0
dfm_python/__init__.py
CHANGED
|
@@ -50,7 +50,7 @@ Example (Low-level API - For advanced usage):
|
|
|
50
50
|
For detailed documentation, see the README.md file and the tutorial notebooks/scripts.
|
|
51
51
|
"""
|
|
52
52
|
|
|
53
|
-
__version__ = "0.2.
|
|
53
|
+
__version__ = "0.2.8"
|
|
54
54
|
|
|
55
55
|
from .config import DFMConfig, SeriesConfig, BlockConfig, Params, DEFAULT_GLOBAL_BLOCK_NAME
|
|
56
56
|
from .config import (
|
dfm_python/core/diagnostics.py
CHANGED
|
@@ -4,12 +4,10 @@ from typing import Optional, Dict, Any, Tuple, TYPE_CHECKING
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import logging
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
PANDAS_AVAILABLE = False
|
|
12
|
-
pd = None
|
|
7
|
+
import pandas as pd
|
|
8
|
+
from scipy.linalg import orthogonal_procrustes
|
|
9
|
+
|
|
10
|
+
PANDAS_AVAILABLE = True
|
|
13
11
|
|
|
14
12
|
from ..config import DFMConfig
|
|
15
13
|
|
|
@@ -96,6 +94,217 @@ def calculate_rmse(actual: np.ndarray, predicted: np.ndarray,
|
|
|
96
94
|
return rmse_overall, rmse_per_series
|
|
97
95
|
|
|
98
96
|
|
|
97
|
+
def evaluate_factor_estimation(
|
|
98
|
+
true_factors: np.ndarray,
|
|
99
|
+
estimated_factors: np.ndarray,
|
|
100
|
+
use_procrustes: bool = True
|
|
101
|
+
) -> Dict[str, Any]:
|
|
102
|
+
"""Evaluate how well factors are estimated (synthetic-data diagnostic).
|
|
103
|
+
|
|
104
|
+
This function compares known ``true_factors`` with ``estimated_factors``
|
|
105
|
+
(typically ``result.Z[:, :num_factors]``) and returns:
|
|
106
|
+
|
|
107
|
+
- Per-factor correlations (before any rotation)
|
|
108
|
+
- Optionally Procrustes-rotated factors and an overall correlation
|
|
109
|
+
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
true_factors : np.ndarray
|
|
113
|
+
Array of shape (T, k) with generated factors used to build the data.
|
|
114
|
+
estimated_factors : np.ndarray
|
|
115
|
+
Array of shape (T, k_est) with estimated factors. Only the first
|
|
116
|
+
``k = min(k, k_est)`` columns are compared.
|
|
117
|
+
use_procrustes : bool, default True
|
|
118
|
+
If True and SciPy is available, apply orthogonal Procrustes rotation
|
|
119
|
+
to align estimated factors with true factors before computing the
|
|
120
|
+
overall correlation.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
Dict[str, Any]
|
|
125
|
+
{
|
|
126
|
+
'num_factors': int,
|
|
127
|
+
'correlation_per_factor': np.ndarray (k,),
|
|
128
|
+
'overall_correlation': float or None,
|
|
129
|
+
'rotation_matrix': np.ndarray (k, k) or None,
|
|
130
|
+
'aligned_factors': np.ndarray (T, k) or None,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
Notes
|
|
134
|
+
-----
|
|
135
|
+
- This is primarily intended for synthetic-data experiments where the
|
|
136
|
+
true latent factors are known.
|
|
137
|
+
- Correlations are computed factor-by-factor, ignoring any time points
|
|
138
|
+
with NaN values.
|
|
139
|
+
- Procrustes rotation is useful because factors are only identified up
|
|
140
|
+
to sign, scale (if not constrained), and rotation in general.
|
|
141
|
+
"""
|
|
142
|
+
if true_factors.ndim != 2 or estimated_factors.ndim != 2:
|
|
143
|
+
raise ValueError(
|
|
144
|
+
f"true_factors and estimated_factors must be 2D, "
|
|
145
|
+
f"got shapes {true_factors.shape} and {estimated_factors.shape}"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
T_true, k_true = true_factors.shape
|
|
149
|
+
T_est, k_est = estimated_factors.shape
|
|
150
|
+
if T_true != T_est:
|
|
151
|
+
raise ValueError(
|
|
152
|
+
f"Time dimension must match, got {T_true} and {T_est}"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
k = min(k_true, k_est)
|
|
156
|
+
if k == 0:
|
|
157
|
+
raise ValueError("At least one factor is required for comparison.")
|
|
158
|
+
|
|
159
|
+
F_true = np.asarray(true_factors[:, :k], dtype=float)
|
|
160
|
+
F_est = np.asarray(estimated_factors[:, :k], dtype=float)
|
|
161
|
+
|
|
162
|
+
# Per-factor correlations (no rotation)
|
|
163
|
+
corr_per_factor = np.full(k, np.nan, dtype=float)
|
|
164
|
+
for j in range(k):
|
|
165
|
+
mask_j = np.isfinite(F_true[:, j]) & np.isfinite(F_est[:, j])
|
|
166
|
+
if np.sum(mask_j) > 1:
|
|
167
|
+
corr = np.corrcoef(F_true[mask_j, j], F_est[mask_j, j])[0, 1]
|
|
168
|
+
corr_per_factor[j] = float(corr)
|
|
169
|
+
|
|
170
|
+
rotation_matrix = None
|
|
171
|
+
aligned_factors = None
|
|
172
|
+
overall_corr = None
|
|
173
|
+
|
|
174
|
+
if use_procrustes:
|
|
175
|
+
# Center factors before Procrustes to focus on shape, not level.
|
|
176
|
+
F_true_centered = F_true - np.nanmean(F_true, axis=0, keepdims=True)
|
|
177
|
+
F_est_centered = F_est - np.nanmean(F_est, axis=0, keepdims=True)
|
|
178
|
+
|
|
179
|
+
# Replace any remaining NaNs with 0 before Procrustes (rare in synthetic tests)
|
|
180
|
+
F_true_clean = np.where(np.isfinite(F_true_centered), F_true_centered, 0.0)
|
|
181
|
+
F_est_clean = np.where(np.isfinite(F_est_centered), F_est_centered, 0.0)
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
# Find R such that F_est_clean @ R ≈ F_true_clean
|
|
185
|
+
R, _ = orthogonal_procrustes(F_est_clean, F_true_clean) # type: ignore[arg-type]
|
|
186
|
+
rotation_matrix = R
|
|
187
|
+
aligned_factors = F_est @ R
|
|
188
|
+
|
|
189
|
+
mask_all = np.isfinite(F_true) & np.isfinite(aligned_factors)
|
|
190
|
+
if np.any(mask_all):
|
|
191
|
+
overall_corr = float(
|
|
192
|
+
np.corrcoef(
|
|
193
|
+
F_true[mask_all].ravel(),
|
|
194
|
+
aligned_factors[mask_all].ravel()
|
|
195
|
+
)[0, 1]
|
|
196
|
+
)
|
|
197
|
+
except Exception as e:
|
|
198
|
+
_logger.debug(f"Procrustes rotation failed in evaluate_factor_estimation: {e}")
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
"num_factors": k,
|
|
202
|
+
"correlation_per_factor": corr_per_factor,
|
|
203
|
+
"overall_correlation": overall_corr,
|
|
204
|
+
"rotation_matrix": rotation_matrix,
|
|
205
|
+
"aligned_factors": aligned_factors,
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def evaluate_loading_estimation(
|
|
210
|
+
true_loadings: np.ndarray,
|
|
211
|
+
estimated_loadings: np.ndarray,
|
|
212
|
+
rotation_matrix: Optional[np.ndarray] = None
|
|
213
|
+
) -> Dict[str, Any]:
|
|
214
|
+
"""Evaluate loading matrix estimation accuracy (synthetic-data diagnostic).
|
|
215
|
+
|
|
216
|
+
Parameters
|
|
217
|
+
----------
|
|
218
|
+
true_loadings : np.ndarray
|
|
219
|
+
Array of shape (N, k_true) with the loadings used to generate data.
|
|
220
|
+
estimated_loadings : np.ndarray
|
|
221
|
+
Array of shape (N, k_est) with estimated loadings from the model
|
|
222
|
+
(typically ``result.C[:, :num_factors]``).
|
|
223
|
+
rotation_matrix : np.ndarray, optional
|
|
224
|
+
Orthogonal rotation matrix of shape (k_est, k_rot) returned by
|
|
225
|
+
:func:`evaluate_factor_estimation`. If provided, the estimated
|
|
226
|
+
loadings are rotated as ``estimated_loadings @ rotation_matrix``
|
|
227
|
+
before comparison.
|
|
228
|
+
|
|
229
|
+
Returns
|
|
230
|
+
-------
|
|
231
|
+
Dict[str, Any]
|
|
232
|
+
{
|
|
233
|
+
'num_factors': int,
|
|
234
|
+
'correlation_per_factor': np.ndarray (k,),
|
|
235
|
+
'rmse_per_series': np.ndarray (N,),
|
|
236
|
+
'overall_rmse': float,
|
|
237
|
+
'aligned_loadings': np.ndarray (N, k),
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
Notes
|
|
241
|
+
-----
|
|
242
|
+
- RMSE is computed per series (row-wise) across factors.
|
|
243
|
+
- This function assumes synthetic data where ``true_loadings`` are known.
|
|
244
|
+
"""
|
|
245
|
+
if true_loadings.ndim != 2 or estimated_loadings.ndim != 2:
|
|
246
|
+
raise ValueError(
|
|
247
|
+
f"true_loadings and estimated_loadings must be 2D, "
|
|
248
|
+
f"got shapes {true_loadings.shape} and {estimated_loadings.shape}"
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
N_true, k_true = true_loadings.shape
|
|
252
|
+
N_est, k_est = estimated_loadings.shape
|
|
253
|
+
if N_true != N_est:
|
|
254
|
+
raise ValueError(
|
|
255
|
+
f"Number of series (rows) must match, got {N_true} and {N_est}"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
# Apply rotation if provided (align loadings with rotated factors)
|
|
259
|
+
L_est = np.asarray(estimated_loadings, dtype=float)
|
|
260
|
+
if rotation_matrix is not None:
|
|
261
|
+
if rotation_matrix.ndim != 2 or rotation_matrix.shape[0] != k_est:
|
|
262
|
+
raise ValueError(
|
|
263
|
+
f"rotation_matrix shape {rotation_matrix.shape} incompatible "
|
|
264
|
+
f"with estimated_loadings shape {estimated_loadings.shape}"
|
|
265
|
+
)
|
|
266
|
+
L_est = L_est @ rotation_matrix
|
|
267
|
+
|
|
268
|
+
k = min(k_true, L_est.shape[1])
|
|
269
|
+
if k == 0:
|
|
270
|
+
raise ValueError("At least one factor/loading column is required.")
|
|
271
|
+
|
|
272
|
+
L_true = np.asarray(true_loadings[:, :k], dtype=float)
|
|
273
|
+
L_est_k = np.asarray(L_est[:, :k], dtype=float)
|
|
274
|
+
|
|
275
|
+
# Per-factor loading correlations
|
|
276
|
+
corr_per_factor = np.full(k, np.nan, dtype=float)
|
|
277
|
+
for j in range(k):
|
|
278
|
+
mask_j = np.isfinite(L_true[:, j]) & np.isfinite(L_est_k[:, j])
|
|
279
|
+
if np.sum(mask_j) > 1:
|
|
280
|
+
corr = np.corrcoef(L_true[mask_j, j], L_est_k[mask_j, j])[0, 1]
|
|
281
|
+
corr_per_factor[j] = float(corr)
|
|
282
|
+
|
|
283
|
+
# RMSE per series (row-wise across factors)
|
|
284
|
+
diff = L_true - L_est_k
|
|
285
|
+
mask = np.isfinite(L_true) & np.isfinite(L_est_k)
|
|
286
|
+
rmse_per_series = np.full(N_true, np.nan, dtype=float)
|
|
287
|
+
for i in range(N_true):
|
|
288
|
+
mask_i = mask[i, :]
|
|
289
|
+
if np.any(mask_i):
|
|
290
|
+
rmse_per_series[i] = float(
|
|
291
|
+
np.sqrt(np.mean(diff[i, mask_i] ** 2))
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
if np.any(mask):
|
|
295
|
+
overall_rmse = float(np.sqrt(np.mean(diff[mask] ** 2)))
|
|
296
|
+
else:
|
|
297
|
+
overall_rmse = float("nan")
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
"num_factors": k,
|
|
301
|
+
"correlation_per_factor": corr_per_factor,
|
|
302
|
+
"rmse_per_series": rmse_per_series,
|
|
303
|
+
"overall_rmse": overall_rmse,
|
|
304
|
+
"aligned_loadings": L_est_k,
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
|
|
99
308
|
def _display_dfm_tables(Res: DFMResult, config: DFMConfig, nQ: int) -> None:
|
|
100
309
|
"""Display DFM estimation output tables.
|
|
101
310
|
|
dfm_python/core/em.py
CHANGED
|
@@ -949,55 +949,55 @@ def em_step(params: EMStepParams) -> Tuple[np.ndarray, np.ndarray, np.ndarray, n
|
|
|
949
949
|
# Keep C fixed for idio components (not updated in M-step)
|
|
950
950
|
else:
|
|
951
951
|
# Fallback to old approach for backward compatibility
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
952
|
+
i_subset = slice(idio_start_idx, idio_start_idx + n_idio)
|
|
953
|
+
i_subset_slice = slice(i_subset.start, i_subset.stop)
|
|
954
|
+
Z_idio = Zsmooth[i_subset_slice, 1:] if idio_start_idx < Zsmooth.shape[1] else np.zeros((n_idio, T))
|
|
955
|
+
n_idio_actual = Z_idio.shape[0] if Z_idio.shape[0] > 0 else n_idio
|
|
956
|
+
expected_idio_current_sq = np.sum(Z_idio**2, axis=1)
|
|
957
|
+
vsmooth_idio_block = vsmooth[i_subset_slice, :, :][:, i_subset_slice, 1:]
|
|
958
|
+
vsmooth_idio_sum = np.sum(vsmooth_idio_block, axis=2)
|
|
959
|
+
if vsmooth_idio_sum.ndim == 2 and vsmooth_idio_sum.shape[0] >= n_idio_actual and vsmooth_idio_sum.shape[1] >= n_idio_actual:
|
|
960
|
+
vsmooth_idio_diag = np.diag(vsmooth_idio_sum[:n_idio_actual, :n_idio_actual])
|
|
961
|
+
else:
|
|
962
|
+
vsmooth_idio_diag = np.zeros(n_idio_actual)
|
|
963
|
+
expected_idio_current_sq = expected_idio_current_sq + vsmooth_idio_diag
|
|
964
|
+
Z_idio_lag = Zsmooth[i_subset_slice, :-1]
|
|
965
|
+
expected_idio_lag_sq = np.sum(Z_idio_lag**2, axis=1)
|
|
966
|
+
vsmooth_lag_block = vsmooth[i_subset_slice, :, :][:, i_subset_slice, :-1]
|
|
967
|
+
vsmooth_lag_sum = np.sum(vsmooth_lag_block, axis=2)
|
|
968
|
+
if vsmooth_lag_sum.ndim == 2 and vsmooth_lag_sum.shape[0] >= n_idio_actual and vsmooth_lag_sum.shape[1] >= n_idio_actual:
|
|
969
|
+
vsmooth_lag_diag = np.diag(vsmooth_lag_sum[:n_idio_actual, :n_idio_actual])
|
|
970
|
+
else:
|
|
971
|
+
vsmooth_lag_diag = np.zeros(n_idio_actual)
|
|
972
|
+
expected_idio_lag_sq = expected_idio_lag_sq + vsmooth_lag_diag
|
|
973
|
+
min_cols = min(Z_idio.shape[1], Z_idio_lag.shape[1])
|
|
974
|
+
expected_idio_cross = np.sum(Z_idio[:, :min_cols] * Z_idio_lag[:, :min_cols], axis=1)
|
|
975
|
+
vvsmooth_block = vvsmooth[i_subset_slice, :, :][:, i_subset_slice, :]
|
|
976
|
+
vvsmooth_sum = np.sum(vvsmooth_block, axis=2)
|
|
977
|
+
if vvsmooth_sum.ndim == 2 and vvsmooth_sum.shape[0] >= n_idio_actual and vvsmooth_sum.shape[1] >= n_idio_actual:
|
|
978
|
+
vvsmooth_diag = np.diag(vvsmooth_sum[:n_idio_actual, :n_idio_actual])
|
|
979
|
+
else:
|
|
980
|
+
vvsmooth_diag = np.zeros(n_idio_actual)
|
|
981
|
+
expected_idio_cross = expected_idio_cross + vvsmooth_diag
|
|
982
|
+
ar_coeffs_diag, _ = _estimate_ar_coefficient(expected_idio_cross, expected_idio_lag_sq, vsmooth_sum=vsmooth_lag_diag)
|
|
983
|
+
A_block_idio = np.diag(ar_coeffs_diag)
|
|
984
|
+
innovation_cov_diag = (np.maximum(expected_idio_current_sq, 0.0) - ar_coeffs_diag * expected_idio_cross) / T
|
|
985
|
+
innovation_cov_diag = np.maximum(innovation_cov_diag, MIN_INNOVATION_VARIANCE)
|
|
986
|
+
Q_block_idio = np.diag(innovation_cov_diag)
|
|
987
|
+
i_subset_size = i_subset.stop - i_subset.start
|
|
988
|
+
if n_idio_actual == i_subset_size:
|
|
989
|
+
A_new[i_subset, i_subset] = A_block_idio
|
|
990
|
+
Q_new[i_subset, i_subset] = Q_block_idio
|
|
991
|
+
elif n_idio_actual < i_subset_size:
|
|
992
|
+
A_new[i_subset.start:i_subset.start + n_idio_actual, i_subset.start:i_subset.start + n_idio_actual] = A_block_idio
|
|
993
|
+
Q_new[i_subset.start:i_subset.start + n_idio_actual, i_subset.start:i_subset.start + n_idio_actual] = Q_block_idio
|
|
994
|
+
else:
|
|
995
|
+
A_new[i_subset, i_subset] = A_block_idio[:i_subset_size, :i_subset_size]
|
|
996
|
+
Q_new[i_subset, i_subset] = Q_block_idio[:i_subset_size, :i_subset_size]
|
|
997
|
+
vsmooth_sub = vsmooth[i_subset_slice, :, :][:, i_subset_slice, 0]
|
|
998
|
+
vsmooth_diag = np.diag(vsmooth_sub[:n_idio_actual, :n_idio_actual]) if vsmooth_sub.ndim == 2 else np.zeros(n_idio_actual)
|
|
999
|
+
for idx in range(min(n_idio_actual, i_subset_size)):
|
|
1000
|
+
V_0_new[i_subset.start + idx, i_subset.start + idx] = vsmooth_diag[idx] if idx < len(vsmooth_diag) else 0.0
|
|
1001
1001
|
|
|
1002
1002
|
Z_0 = Zsmooth[0, :].copy()
|
|
1003
1003
|
nanY = np.isnan(y)
|
dfm_python/core/numeric.py
CHANGED
|
@@ -605,14 +605,14 @@ def _safe_determinant(M: np.ndarray, use_logdet: bool = True) -> float:
|
|
|
605
605
|
if not np.isfinite(log_det) or sign <= 0:
|
|
606
606
|
return 0.0
|
|
607
607
|
# Avoid overflow in exp
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
608
|
+
if log_det > 700:
|
|
609
|
+
_logger.debug("_safe_determinant: log_det too large, returning 0.0")
|
|
610
|
+
return 0.0
|
|
611
|
+
with warnings.catch_warnings():
|
|
612
|
+
warnings.filterwarnings('ignore', category=RuntimeWarning)
|
|
613
613
|
det = np.exp(log_det)
|
|
614
|
-
|
|
615
|
-
|
|
614
|
+
if np.isfinite(det):
|
|
615
|
+
return float(det)
|
|
616
616
|
except Exception:
|
|
617
617
|
pass
|
|
618
618
|
except (np.linalg.LinAlgError, ValueError, OverflowError, RuntimeWarning):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dfm-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Dynamic Factor Model (DFM) estimation and nowcasting in Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/yourusername/dfm-python
|
|
6
6
|
Project-URL: Documentation, https://github.com/yourusername/dfm-python#readme
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
dfm_python/__init__.py,sha256=
|
|
1
|
+
dfm_python/__init__.py,sha256=oz0p9JreUg6D9SfU2vUAFMRwf7JwHaa3dQDy87YHtIw,5589
|
|
2
2
|
dfm_python/api.py,sha256=-mmV7aaXOAqVW9HPhTEut7T6wN1EyW0rS3J0y-z-MRs,16221
|
|
3
3
|
dfm_python/config.py,sha256=bBiKfoETohNVJ3brRbY1330C1nQROybCR3co9iagIKs,46978
|
|
4
4
|
dfm_python/config_sources.py,sha256=6LTK7k5WJpnayMmtxtYwZ9SQi_hGXoz-Vg4sRGTabI0,21798
|
|
@@ -8,11 +8,11 @@ dfm_python/kalman.py,sha256=EXhloLbpzy7GKG9KFrSZt9pRp0y3CZyvycPVbvUWxq8,18074
|
|
|
8
8
|
dfm_python/news.py,sha256=iXbJnsvH5FgKToPzKnqIpTosrZu-QHXBNHjsqwMYrHo,32583
|
|
9
9
|
dfm_python/utils.py,sha256=qOAJm2KG71yP2a29iJVDGOC-ZUS_HPL5oAo16EgNXA4,15709
|
|
10
10
|
dfm_python/core/__init__.py,sha256=oDrhAoc1W_ODohgufQ-gN0uri8-vZI0EXsF0dysth_A,331
|
|
11
|
-
dfm_python/core/diagnostics.py,sha256=
|
|
12
|
-
dfm_python/core/em.py,sha256=
|
|
11
|
+
dfm_python/core/diagnostics.py,sha256=1ninWcQlWhJmfUZq9kky7IQoRf_6fI_IlVzzSb7apRQ,28085
|
|
12
|
+
dfm_python/core/em.py,sha256=jbtsFHynMDtblZTtlzgodX04e86BBB9hPn20MMnV3w0,72705
|
|
13
13
|
dfm_python/core/helpers.py,sha256=XJvWWEZlUqozBfFNcENKgbOOFkwlm-tGwO-u0LnAf-E,31541
|
|
14
|
-
dfm_python/core/numeric.py,sha256=
|
|
15
|
-
dfm_python-0.2.
|
|
16
|
-
dfm_python-0.2.
|
|
17
|
-
dfm_python-0.2.
|
|
18
|
-
dfm_python-0.2.
|
|
14
|
+
dfm_python/core/numeric.py,sha256=IcIwcKtMhIoJ5-7Mz6UNYwTUtEa5W_ZMnQtF87v0SSc,26431
|
|
15
|
+
dfm_python-0.2.8.dist-info/METADATA,sha256=wY69TZa4fK9I4zY4t7hQUJksWuMCyxtGUS0Nr_C3SPk,28599
|
|
16
|
+
dfm_python-0.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
17
|
+
dfm_python-0.2.8.dist-info/licenses/LICENSE,sha256=6e87br6LCDHjy2hdIR1-sdBQy351qdmSEbOg6jQ7ZXY,1063
|
|
18
|
+
dfm_python-0.2.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|