dfm-python 0.2.5__py3-none-any.whl → 0.2.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.
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.5"
53
+ __version__ = "0.2.7"
54
54
 
55
55
  from .config import DFMConfig, SeriesConfig, BlockConfig, Params, DEFAULT_GLOBAL_BLOCK_NAME
56
56
  from .config import (
dfm_python/core/em.py CHANGED
@@ -368,7 +368,20 @@ def init_conditions(x, r, p, blocks, opt_nan, Rcon, q, nQ, i_idio, clock='m', te
368
368
  # Store loadings (only up to available columns in C_block)
369
369
  n_loadings = min(pC_freq * r_i, C_block.shape[1])
370
370
  if n_loadings > 0:
371
- C_block[j, :n_loadings] = loadings[:n_loadings]
371
+ # Clip initial loadings to prevent extreme values
372
+ # This helps prevent Q explosion during C normalization
373
+ max_loading_norm = safe_get_attr(config, "max_loading_norm", 10.0) if config is not None else 10.0
374
+ # Clip loadings: if norm is too large, scale down
375
+ loadings_to_store = loadings[:n_loadings]
376
+ if loadings_to_store.ndim == 1:
377
+ # Vector case: clip by norm
378
+ loading_norm = np.linalg.norm(loadings_to_store)
379
+ if loading_norm > max_loading_norm:
380
+ loadings_to_store = loadings_to_store * (max_loading_norm / loading_norm)
381
+ else:
382
+ # Multi-dimensional: clip each element
383
+ loadings_to_store = np.clip(loadings_to_store, -max_loading_norm, max_loading_norm)
384
+ C_block[j, :n_loadings] = loadings_to_store
372
385
  except Exception:
373
386
  # If constrained LS fails, use unconstrained (fallback)
374
387
  try:
@@ -377,7 +390,19 @@ def init_conditions(x, r, p, blocks, opt_nan, Rcon, q, nQ, i_idio, clock='m', te
377
390
  loadings = gram_inv @ factor_projection_clean.T @ series_data_clean
378
391
  n_loadings = min(pC_freq * r_i, C_block.shape[1])
379
392
  if n_loadings > 0:
380
- C_block[j, :n_loadings] = loadings[:n_loadings]
393
+ # Clip initial loadings to prevent extreme values
394
+ max_loading_norm = safe_get_attr(config, "max_loading_norm", 10.0) if config is not None else 10.0
395
+ # Clip loadings: if norm is too large, scale down
396
+ loadings_to_store = loadings[:n_loadings]
397
+ if loadings_to_store.ndim == 1:
398
+ # Vector case: clip by norm
399
+ loading_norm = np.linalg.norm(loadings_to_store)
400
+ if loading_norm > max_loading_norm:
401
+ loadings_to_store = loadings_to_store * (max_loading_norm / loading_norm)
402
+ else:
403
+ # Multi-dimensional: clip each element
404
+ loadings_to_store = np.clip(loadings_to_store, -max_loading_norm, max_loading_norm)
405
+ C_block[j, :n_loadings] = loadings_to_store
381
406
  except Exception:
382
407
  pass # Leave as zeros
383
408
  except Exception:
@@ -784,8 +809,8 @@ def em_step(params: EMStepParams) -> Tuple[np.ndarray, np.ndarray, np.ndarray, n
784
809
  lambda_ridge = (trace_val / size_val) * 1e-5 # Scale factor
785
810
  EZZ_lag_sub = EZZ_lag_sub + lambda_ridge * np.eye(size_val)
786
811
  # Recompute condition number after regularization
787
- eigenvals = np.linalg.eigvals(EZZ_lag_sub)
788
- cond_num = (np.max(eigenvals) / max(np.min(eigenvals), 1e-12)) if np.max(eigenvals) > 0 else 1.0
812
+ eigenvals = np.linalg.eigvals(EZZ_lag_sub)
813
+ cond_num = (np.max(eigenvals) / max(np.min(eigenvals), 1e-12)) if np.max(eigenvals) > 0 else 1.0
789
814
  EZZ_lag_inv = pinv(EZZ_lag_sub, rcond=1e-8) if cond_num > 1e12 else inv(EZZ_lag_sub)
790
815
  except _NUMERICAL_EXCEPTIONS:
791
816
  EZZ_lag_inv = pinv(EZZ_lag_sub)
@@ -924,55 +949,55 @@ def em_step(params: EMStepParams) -> Tuple[np.ndarray, np.ndarray, np.ndarray, n
924
949
  # Keep C fixed for idio components (not updated in M-step)
925
950
  else:
926
951
  # Fallback to old approach for backward compatibility
927
- i_subset = slice(idio_start_idx, idio_start_idx + n_idio)
928
- i_subset_slice = slice(i_subset.start, i_subset.stop)
929
- Z_idio = Zsmooth[i_subset_slice, 1:] if idio_start_idx < Zsmooth.shape[1] else np.zeros((n_idio, T))
930
- n_idio_actual = Z_idio.shape[0] if Z_idio.shape[0] > 0 else n_idio
931
- expected_idio_current_sq = np.sum(Z_idio**2, axis=1)
932
- vsmooth_idio_block = vsmooth[i_subset_slice, :, :][:, i_subset_slice, 1:]
933
- vsmooth_idio_sum = np.sum(vsmooth_idio_block, axis=2)
934
- if vsmooth_idio_sum.ndim == 2 and vsmooth_idio_sum.shape[0] >= n_idio_actual and vsmooth_idio_sum.shape[1] >= n_idio_actual:
935
- vsmooth_idio_diag = np.diag(vsmooth_idio_sum[:n_idio_actual, :n_idio_actual])
936
- else:
937
- vsmooth_idio_diag = np.zeros(n_idio_actual)
938
- expected_idio_current_sq = expected_idio_current_sq + vsmooth_idio_diag
939
- Z_idio_lag = Zsmooth[i_subset_slice, :-1]
940
- expected_idio_lag_sq = np.sum(Z_idio_lag**2, axis=1)
941
- vsmooth_lag_block = vsmooth[i_subset_slice, :, :][:, i_subset_slice, :-1]
942
- vsmooth_lag_sum = np.sum(vsmooth_lag_block, axis=2)
943
- if vsmooth_lag_sum.ndim == 2 and vsmooth_lag_sum.shape[0] >= n_idio_actual and vsmooth_lag_sum.shape[1] >= n_idio_actual:
944
- vsmooth_lag_diag = np.diag(vsmooth_lag_sum[:n_idio_actual, :n_idio_actual])
945
- else:
946
- vsmooth_lag_diag = np.zeros(n_idio_actual)
947
- expected_idio_lag_sq = expected_idio_lag_sq + vsmooth_lag_diag
948
- min_cols = min(Z_idio.shape[1], Z_idio_lag.shape[1])
949
- expected_idio_cross = np.sum(Z_idio[:, :min_cols] * Z_idio_lag[:, :min_cols], axis=1)
950
- vvsmooth_block = vvsmooth[i_subset_slice, :, :][:, i_subset_slice, :]
951
- vvsmooth_sum = np.sum(vvsmooth_block, axis=2)
952
- if vvsmooth_sum.ndim == 2 and vvsmooth_sum.shape[0] >= n_idio_actual and vvsmooth_sum.shape[1] >= n_idio_actual:
953
- vvsmooth_diag = np.diag(vvsmooth_sum[:n_idio_actual, :n_idio_actual])
954
- else:
955
- vvsmooth_diag = np.zeros(n_idio_actual)
956
- expected_idio_cross = expected_idio_cross + vvsmooth_diag
957
- ar_coeffs_diag, _ = _estimate_ar_coefficient(expected_idio_cross, expected_idio_lag_sq, vsmooth_sum=vsmooth_lag_diag)
958
- A_block_idio = np.diag(ar_coeffs_diag)
959
- innovation_cov_diag = (np.maximum(expected_idio_current_sq, 0.0) - ar_coeffs_diag * expected_idio_cross) / T
960
- innovation_cov_diag = np.maximum(innovation_cov_diag, MIN_INNOVATION_VARIANCE)
961
- Q_block_idio = np.diag(innovation_cov_diag)
962
- i_subset_size = i_subset.stop - i_subset.start
963
- if n_idio_actual == i_subset_size:
964
- A_new[i_subset, i_subset] = A_block_idio
965
- Q_new[i_subset, i_subset] = Q_block_idio
966
- elif n_idio_actual < i_subset_size:
967
- A_new[i_subset.start:i_subset.start + n_idio_actual, i_subset.start:i_subset.start + n_idio_actual] = A_block_idio
968
- Q_new[i_subset.start:i_subset.start + n_idio_actual, i_subset.start:i_subset.start + n_idio_actual] = Q_block_idio
969
- else:
970
- A_new[i_subset, i_subset] = A_block_idio[:i_subset_size, :i_subset_size]
971
- Q_new[i_subset, i_subset] = Q_block_idio[:i_subset_size, :i_subset_size]
972
- vsmooth_sub = vsmooth[i_subset_slice, :, :][:, i_subset_slice, 0]
973
- vsmooth_diag = np.diag(vsmooth_sub[:n_idio_actual, :n_idio_actual]) if vsmooth_sub.ndim == 2 else np.zeros(n_idio_actual)
974
- for idx in range(min(n_idio_actual, i_subset_size)):
975
- V_0_new[i_subset.start + idx, i_subset.start + idx] = vsmooth_diag[idx] if idx < len(vsmooth_diag) else 0.0
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
976
1001
 
977
1002
  Z_0 = Zsmooth[0, :].copy()
978
1003
  nanY = np.isnan(y)
@@ -1180,6 +1205,12 @@ def em_step(params: EMStepParams) -> Tuple[np.ndarray, np.ndarray, np.ndarray, n
1180
1205
  # Hard floor: enforce min diagonal on R (≥ 1e-8)
1181
1206
  idio_min_var = getattr(config, 'idio_min_var', 1e-8) if config is not None else 1e-8
1182
1207
  R_diag = np.maximum(R_diag, idio_min_var)
1208
+
1209
+ # R cap to prevent explosion: maximum allowed observation error variance
1210
+ # For standardized data, R should typically be < 10
1211
+ R_cap = safe_get_attr(config, "max_observation_variance", 10.0) if config is not None else 10.0
1212
+ R_diag = np.minimum(R_diag, R_cap)
1213
+
1183
1214
  R_new = np.diag(R_diag)
1184
1215
 
1185
1216
  # Final stability operations
@@ -1212,22 +1243,61 @@ def em_step(params: EMStepParams) -> Tuple[np.ndarray, np.ndarray, np.ndarray, n
1212
1243
  has_slower_freq = (frequencies is not None and
1213
1244
  any(freq != clock for freq in frequencies if freq is not None))
1214
1245
  num_clock_factors = int(np.sum(r)) # Only clock-frequency factors (ppC=1 part)
1215
- if num_clock_factors > 0 and not has_slower_freq:
1216
- # Only normalize if there are no slower-frequency series
1217
- # (to avoid violating tent weight constraints)
1218
- for j in range(num_clock_factors):
1219
- norm = np.linalg.norm(C_new[:, j])
1220
- if norm > 1e-8:
1221
- # Normalize C column
1222
- C_new[:, j] = C_new[:, j] / norm
1223
- # Adjust Q to preserve variance
1224
- # Diagonal: Q[j,j] *= norm^2
1225
- Q_new[j, j] = Q_new[j, j] * (norm ** 2)
1226
- # Off-diagonal: Q[j,k] and Q[k,j] *= norm (for k != j)
1227
- for k in range(Q_new.shape[0]):
1228
- if k != j:
1229
- Q_new[j, k] = Q_new[j, k] * norm
1230
- Q_new[k, j] = Q_new[k, j] * norm
1246
+
1247
+ # Q cap to prevent explosion: maximum allowed innovation variance for factors
1248
+ Q_cap_factor = safe_get_attr(config, "max_innovation_variance", 1.0) if config is not None else 1.0
1249
+
1250
+ # Normalize C for clock-frequency factors to prevent scale issues
1251
+ # Only normalize if C norm is in reasonable range (not too small, not too large)
1252
+ # This prevents Q from becoming too small (when C norm is small) or too large (when C norm is large)
1253
+ if num_clock_factors > 0:
1254
+ # Check if there are slower-frequency series (tent weight constraints)
1255
+ has_slower_freq = (frequencies is not None and
1256
+ any(freq != clock for freq in frequencies if freq is not None))
1257
+
1258
+ # Only normalize if no slower-frequency series (to avoid violating tent weight constraints)
1259
+ if not has_slower_freq:
1260
+ for j in range(num_clock_factors):
1261
+ norm = np.linalg.norm(C_new[:, j])
1262
+ if norm > 1e-8:
1263
+ # Only normalize if norm is in reasonable range
1264
+ # Too small norm (< 0.1) would make Q too small
1265
+ # Too large norm (> 10) would make Q too large
1266
+ C_norm_min = 0.1 # Minimum norm to normalize
1267
+ C_norm_cap = safe_get_attr(config, "max_loading_norm", 10.0) if config is not None else 10.0
1268
+
1269
+ if C_norm_min <= norm <= C_norm_cap:
1270
+ # Normalize C column
1271
+ C_new[:, j] = C_new[:, j] / norm
1272
+
1273
+ # Adjust Q to preserve variance: Q[j,j] *= norm^2
1274
+ Q_adjustment = norm ** 2
1275
+ Q_new[j, j] = Q_new[j, j] * Q_adjustment
1276
+
1277
+ # Off-diagonal: Q[j,k] and Q[k,j] *= norm (for k != j)
1278
+ for k in range(Q_new.shape[0]):
1279
+ if k != j:
1280
+ Q_new[j, k] = Q_new[j, k] * norm
1281
+ Q_new[k, j] = Q_new[k, j] * norm
1282
+ # If norm is too small or too large, skip normalization to preserve stability
1283
+
1284
+ # Re-apply Q floor and cap after C normalization to prevent extreme values
1285
+ # C normalization can make Q very large (if C norm was large) or very small (if C norm was small)
1286
+ Q_diag_after_norm = np.diag(Q_new).copy()
1287
+ if num_factors > 0:
1288
+ # Apply both floor and cap to factors after normalization
1289
+ Q_diag_after_norm[:num_factors] = np.clip(
1290
+ Q_diag_after_norm[:num_factors],
1291
+ Q_min_factor, # Floor: 0.01
1292
+ Q_cap_factor # Cap: 1.0 (configurable)
1293
+ )
1294
+ # Preserve idio components (only floor, no cap needed)
1295
+ if num_factors < len(Q_diag_after_norm):
1296
+ Q_diag_after_norm[num_factors:] = np.maximum(Q_diag_after_norm[num_factors:], idio_min_var)
1297
+ else:
1298
+ Q_diag_after_norm = np.maximum(Q_diag_after_norm, idio_min_var)
1299
+ # Update Q with re-applied floor and cap
1300
+ Q_new = np.diag(Q_diag_after_norm) + (Q_new - np.diag(np.diag(Q_new))) # Preserve off-diagonal
1231
1301
 
1232
1302
  # Spectral radius cap on A (< 0.99) with minimal shrinkage
1233
1303
  eigenvals_A = np.linalg.eigvals(A_new)
@@ -598,20 +598,23 @@ def _safe_determinant(M: np.ndarray, use_logdet: bool = True) -> float:
598
598
  if np.isfinite(det) and det > 0:
599
599
  return float(det)
600
600
  except np.linalg.LinAlgError:
601
- # Not PSD, use LU decomposition
602
- P, L, U = np.linalg.lu(M)
603
- log_det = np.sum(np.log(np.abs(np.diag(U))))
604
- # Check if log_det is too large to avoid overflow in exp
601
+ # Not PSD: fall back to slogdet for general matrices
602
+ try:
603
+ sign, log_det = np.linalg.slogdet(M)
604
+ # If determinant is non-positive or invalid, return 0.0
605
+ if not np.isfinite(log_det) or sign <= 0:
606
+ return 0.0
607
+ # Avoid overflow in exp
605
608
  if log_det > 700:
606
609
  _logger.debug("_safe_determinant: log_det too large, returning 0.0")
607
610
  return 0.0
608
- # Account for permutation sign
609
- sign = np.linalg.det(P) if P.shape[0] <= 10 else 1.0
610
611
  with warnings.catch_warnings():
611
612
  warnings.filterwarnings('ignore', category=RuntimeWarning)
612
- det = sign * np.exp(log_det)
613
+ det = np.exp(log_det)
613
614
  if np.isfinite(det):
614
615
  return float(det)
616
+ except Exception:
617
+ pass
615
618
  except (np.linalg.LinAlgError, ValueError, OverflowError, RuntimeWarning):
616
619
  pass
617
620
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dfm-python
3
- Version: 0.2.5
3
+ Version: 0.2.7
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
@@ -709,12 +709,29 @@ Demonstrates:
709
709
 
710
710
  ## Project Status
711
711
 
712
- **Version**: 0.2.5
712
+ **Version**: 0.2.7
713
713
  **Status**: Stable and production-ready
714
714
  **Python**: 3.10+
715
715
  **PyPI**: https://pypi.org/project/dfm-python/
716
716
 
717
- ### Recent Improvements (v0.2.5)
717
+ ### Recent Improvements (v0.2.7)
718
+
719
+ - ✅ **Fixed C normalization issue**: C normalization now only applies when C norm is in reasonable range (0.1 ~ 10)
720
+ - Prevents Q from becoming too small when C norm is very small
721
+ - Prevents factor values from becoming extreme
722
+ - ✅ **Improved stability**: Conditional C normalization prevents pathological factor paths
723
+ - ✅ **Better diagnostics**: Added variance guard binding checks in tutorial
724
+
725
+ ### Previous Improvements (v0.2.6)
726
+
727
+ - ✅ **Q matrix cap**: Factor innovation variances bounded above by 1.0 to prevent explosion
728
+ - ✅ **R matrix cap**: Observation error variances bounded above by 10.0 for standardized data
729
+ - ✅ **Improved C normalization**: C norm clipping prevents Q explosion during normalization
730
+ - ✅ **Enhanced initial values**: PCA loadings clipped to prevent extreme initial values
731
+ - ✅ **Bug fix**: Fixed `np.linalg.lu` error by using `np.linalg.slogdet` for determinant computation
732
+ - ✅ **Better stability**: Q and R caps ensure model convergence even with challenging data
733
+
734
+ ### Previous Improvements (v0.2.5)
718
735
 
719
736
  - ✅ **Q matrix floor**: Factor innovation variances bounded below by 0.01 to prevent scale issues
720
737
  - ✅ **C matrix normalization**: Clock-frequency factor loadings normalized (||C[:,j]|| = 1) for scale stability
@@ -749,7 +766,7 @@ If you use `dfm-python` in your research, please cite:
749
766
  author = {DFM Python Contributors},
750
767
  year = {2025},
751
768
  url = {https://pypi.org/project/dfm-python/},
752
- version = {0.2.5}
769
+ version = {0.2.7}
753
770
  }
754
771
  ```
755
772
 
@@ -1,4 +1,4 @@
1
- dfm_python/__init__.py,sha256=8_xxzeEMbtdKxcjH48IytqGh3uSaGJnl8Q8JnCFFLhs,5589
1
+ dfm_python/__init__.py,sha256=YYhRgV773DAFbaTrfF6LVF45rmbR8SpsH6LOYtDAHnU,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
@@ -9,10 +9,10 @@ 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
11
  dfm_python/core/diagnostics.py,sha256=2Cm8XIN5jE9jL3FssEUmZNQy12FPuKvYs1k3bYKAySw,20224
12
- dfm_python/core/em.py,sha256=Y1kICJfdNyAWsWYxxJANp4TAiQ__iVR5wwhNw6h0qC0,67571
12
+ dfm_python/core/em.py,sha256=ltMVW1izAVmMwwYKf3GIFLAP-nLAgGy9zdOenuK-SiU,72509
13
13
  dfm_python/core/helpers.py,sha256=XJvWWEZlUqozBfFNcENKgbOOFkwlm-tGwO-u0LnAf-E,31541
14
- dfm_python/core/numeric.py,sha256=CsufWu5feWdRjjrhGL7pKxwq5CFkaBn-1l3t1v35YQI,26323
15
- dfm_python-0.2.5.dist-info/METADATA,sha256=rmEAZQ0C4RPO7h4G3JJhu6Kq1itjD4dif_aH_2O121w,27552
16
- dfm_python-0.2.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
- dfm_python-0.2.5.dist-info/licenses/LICENSE,sha256=6e87br6LCDHjy2hdIR1-sdBQy351qdmSEbOg6jQ7ZXY,1063
18
- dfm_python-0.2.5.dist-info/RECORD,,
14
+ dfm_python/core/numeric.py,sha256=__uwDgRj3TV4S0vXhNc_93kk8U6ewtW8smk0OBZLbdg,26403
15
+ dfm_python-0.2.7.dist-info/METADATA,sha256=ZeeKWsk4BkRbihDNjkLkOq-DofODB9RhwG7dxMRIbQI,28599
16
+ dfm_python-0.2.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ dfm_python-0.2.7.dist-info/licenses/LICENSE,sha256=6e87br6LCDHjy2hdIR1-sdBQy351qdmSEbOg6jQ7ZXY,1063
18
+ dfm_python-0.2.7.dist-info/RECORD,,