SURE-tools 2.1.8__tar.gz → 2.1.10__tar.gz
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.
Potentially problematic release.
This version of SURE-tools might be problematic. Click here for more details.
- {sure_tools-2.1.8 → sure_tools-2.1.10}/PKG-INFO +1 -1
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/flow/__init__.py +1 -1
- sure_tools-2.1.10/SURE/flow/flow_stats.py +298 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/perturb/perturb.py +3 -1
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE_tools.egg-info/PKG-INFO +1 -1
- {sure_tools-2.1.8 → sure_tools-2.1.10}/setup.py +1 -1
- sure_tools-2.1.8/SURE/flow/flow_stats.py +0 -78
- {sure_tools-2.1.8 → sure_tools-2.1.10}/LICENSE +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/README.md +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/PerturbFlow.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/SURE.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/__init__.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/assembly/__init__.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/assembly/assembly.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/assembly/atlas.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/atac/__init__.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/atac/utils.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/codebook/__init__.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/codebook/codebook.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/flow/plot_quiver.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/perturb/__init__.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/utils/__init__.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/utils/custom_mlp.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/utils/queue.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE/utils/utils.py +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE_tools.egg-info/SOURCES.txt +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE_tools.egg-info/dependency_links.txt +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE_tools.egg-info/entry_points.txt +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE_tools.egg-info/requires.txt +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/SURE_tools.egg-info/top_level.txt +0 -0
- {sure_tools-2.1.8 → sure_tools-2.1.10}/setup.cfg +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
from .plot_quiver import plot_quiver
|
|
2
|
-
from .flow_stats import calculate_direction_stats,calculate_movement_stats,calculate_movement_energy,calculate_movement_divergence
|
|
2
|
+
from .flow_stats import calculate_direction_stats,calculate_movement_stats,calculate_movement_energy,calculate_movement_divergence,VectorFieldEval
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy.spatial.distance import pdist, squareform
|
|
3
|
+
from sklearn.decomposition import PCA
|
|
4
|
+
from scipy.stats import pearsonr
|
|
5
|
+
from sklearn.neighbors import NearestNeighbors
|
|
6
|
+
|
|
7
|
+
class VectorFieldEval:
|
|
8
|
+
def __init__(self):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
def directional_alignment(self, vectors, weighted=False):
|
|
12
|
+
if weighted:
|
|
13
|
+
return weighted_alignment(vectors=vectors)
|
|
14
|
+
else:
|
|
15
|
+
return directional_alignment(vectors=vectors)
|
|
16
|
+
|
|
17
|
+
def flow_coherence(self, vectors, pca=False):
|
|
18
|
+
if pca:
|
|
19
|
+
return pca_based_coherence(vectors=vectors)
|
|
20
|
+
else:
|
|
21
|
+
return flow_coherence_index(vectors=vectors)
|
|
22
|
+
|
|
23
|
+
def momentum_flow_metric(self, vectors, masses=None):
|
|
24
|
+
return momentum_flow_metric(vectors=vectors, masses=masses)
|
|
25
|
+
|
|
26
|
+
def multi_scale_coherence(self, vectors, positoins, scale_factors=[1.0, 0.5, 0.1]):
|
|
27
|
+
return multi_scale_coherence(vectors=vectors, positions=positoins, scale_factors=scale_factors)
|
|
28
|
+
|
|
29
|
+
def vector_field_coherence_score(self, vectors, positions=None, weights=None):
|
|
30
|
+
return vector_field_coherence_score(vectors=vectors, positions=positions, weights=weights)
|
|
31
|
+
|
|
32
|
+
def calculate_movement_stats(vectors):
|
|
33
|
+
"""
|
|
34
|
+
计算移动矢量的基本统计量
|
|
35
|
+
"""
|
|
36
|
+
# 计算每个矢量的模长(移动距离)
|
|
37
|
+
distances = np.linalg.norm(vectors, axis=1)
|
|
38
|
+
|
|
39
|
+
stats = {
|
|
40
|
+
'total_movement': np.sum(distances),
|
|
41
|
+
'mean_distance': np.mean(distances),
|
|
42
|
+
'median_distance': np.median(distances),
|
|
43
|
+
'std_distance': np.std(distances),
|
|
44
|
+
'max_distance': np.max(distances),
|
|
45
|
+
'min_distance': np.min(distances),
|
|
46
|
+
'total_points': len(vectors)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return stats, distances
|
|
50
|
+
|
|
51
|
+
def calculate_direction_stats(vectors):
|
|
52
|
+
"""
|
|
53
|
+
计算移动方向的一致性
|
|
54
|
+
"""
|
|
55
|
+
# 单位向量
|
|
56
|
+
unit_vectors = vectors / np.linalg.norm(vectors, axis=1, keepdims=True)
|
|
57
|
+
|
|
58
|
+
# 平均方向向量
|
|
59
|
+
mean_direction = np.mean(unit_vectors, axis=0)
|
|
60
|
+
mean_direction_norm = np.linalg.norm(mean_direction)
|
|
61
|
+
|
|
62
|
+
# 方向一致性(0-1,1表示完全一致)
|
|
63
|
+
direction_consistency = mean_direction_norm
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
'direction_consistency': direction_consistency,
|
|
67
|
+
'mean_direction': mean_direction,
|
|
68
|
+
'direction_variance': 1 - direction_consistency # 方向分散度
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
def calculate_movement_energy(vectors, masses=None):
|
|
72
|
+
"""
|
|
73
|
+
计算移动的能量(假设每个点有质量)
|
|
74
|
+
"""
|
|
75
|
+
if masses is None:
|
|
76
|
+
masses = np.ones(len(vectors)) # 默认单位质量
|
|
77
|
+
|
|
78
|
+
# 动能 = 0.5 * mass * velocity^2
|
|
79
|
+
speeds_squared = np.sum(vectors**2, axis=1)
|
|
80
|
+
kinetic_energy = 0.5 * masses * speeds_squared
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
'total_energy': np.sum(kinetic_energy),
|
|
84
|
+
'mean_energy': np.mean(kinetic_energy),
|
|
85
|
+
'energy_std': np.std(kinetic_energy)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
def calculate_movement_divergence(positions, vectors):
|
|
89
|
+
"""
|
|
90
|
+
计算移动的散度(衡量扩张/收缩)
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
# 计算移动前后的位置
|
|
94
|
+
new_positions = positions + vectors
|
|
95
|
+
|
|
96
|
+
# 计算位置变化的协方差
|
|
97
|
+
orig_cov = np.cov(positions.T)
|
|
98
|
+
new_cov = np.cov(new_positions.T)
|
|
99
|
+
|
|
100
|
+
# 体积变化(行列式比值)
|
|
101
|
+
volume_ratio = np.linalg.det(new_cov) / np.linalg.det(orig_cov)
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
'volume_expansion': volume_ratio, # >1扩张, <1收缩
|
|
105
|
+
'expansion_factor': volume_ratio**(1/positions.shape[1])
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def directional_alignment(vectors):
|
|
110
|
+
"""
|
|
111
|
+
计算向量场的方向一致性
|
|
112
|
+
返回值: 0-1之间,1表示完全一致
|
|
113
|
+
"""
|
|
114
|
+
# 归一化向量
|
|
115
|
+
norms = np.linalg.norm(vectors, axis=1, keepdims=True)
|
|
116
|
+
unit_vectors = vectors / (norms + 1e-8) # 避免除零
|
|
117
|
+
|
|
118
|
+
# 计算平均方向向量
|
|
119
|
+
mean_direction = np.mean(unit_vectors, axis=0)
|
|
120
|
+
mean_direction_norm = np.linalg.norm(mean_direction)
|
|
121
|
+
|
|
122
|
+
return mean_direction_norm
|
|
123
|
+
|
|
124
|
+
def weighted_alignment(vectors):
|
|
125
|
+
"""
|
|
126
|
+
根据移动强度加权的方向一致性
|
|
127
|
+
"""
|
|
128
|
+
norms = np.linalg.norm(vectors, axis=1)
|
|
129
|
+
unit_vectors = vectors / norms[:, np.newaxis]
|
|
130
|
+
|
|
131
|
+
# 用移动强度加权
|
|
132
|
+
weights = norms / np.sum(norms)
|
|
133
|
+
weighted_mean = np.sum(unit_vectors * weights[:, np.newaxis], axis=0)
|
|
134
|
+
|
|
135
|
+
return np.linalg.norm(weighted_mean)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def flow_coherence_index(vectors, alpha=0.5):
|
|
139
|
+
"""
|
|
140
|
+
流动一致性指数:综合方向和强度
|
|
141
|
+
Args:
|
|
142
|
+
alpha: 方向权重 (0-1),强度权重为 1-alpha
|
|
143
|
+
Returns:
|
|
144
|
+
0-1之间的值,越大表示越一致的大规模移动
|
|
145
|
+
"""
|
|
146
|
+
# 1. 方向一致性成分
|
|
147
|
+
norms = np.linalg.norm(vectors, axis=1)
|
|
148
|
+
unit_vectors = vectors / norms[:, np.newaxis]
|
|
149
|
+
direction_consistency = np.linalg.norm(np.mean(unit_vectors, axis=0))
|
|
150
|
+
|
|
151
|
+
# 2. 移动强度成分(标准化)
|
|
152
|
+
intensity = np.mean(norms) / (np.std(norms) + 1e-8) # 均值/标准差
|
|
153
|
+
normalized_intensity = 1 - np.exp(-intensity) # 映射到0-1
|
|
154
|
+
|
|
155
|
+
# 3. 综合指标
|
|
156
|
+
fci = alpha * direction_consistency + (1 - alpha) * normalized_intensity
|
|
157
|
+
return fci, direction_consistency, normalized_intensity
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def pca_based_coherence(vectors):
|
|
161
|
+
"""
|
|
162
|
+
基于PCA的流动一致性分析
|
|
163
|
+
"""
|
|
164
|
+
# 计算协方差矩阵的特征值
|
|
165
|
+
cov_matrix = np.cov(vectors.T)
|
|
166
|
+
eigenvalues = np.linalg.eigvals(cov_matrix)
|
|
167
|
+
eigenvalues = np.sort(eigenvalues)[::-1] # 降序排列
|
|
168
|
+
|
|
169
|
+
# 第一主成分解释的方差比例
|
|
170
|
+
explained_variance_ratio = eigenvalues[0] / np.sum(eigenvalues)
|
|
171
|
+
|
|
172
|
+
# 方向一致性(第一主成分的方向重要性)
|
|
173
|
+
pca = PCA(n_components=1)
|
|
174
|
+
pca.fit(vectors)
|
|
175
|
+
principal_component = pca.components_[0]
|
|
176
|
+
|
|
177
|
+
# 计算向量与主成分的夹角一致性
|
|
178
|
+
unit_vectors = vectors / np.linalg.norm(vectors, axis=1, keepdims=True)
|
|
179
|
+
cos_similarities = np.abs(np.dot(unit_vectors, principal_component))
|
|
180
|
+
alignment_with_pc = np.mean(cos_similarities)
|
|
181
|
+
|
|
182
|
+
return explained_variance_ratio, alignment_with_pc
|
|
183
|
+
|
|
184
|
+
def momentum_flow_metric(vectors, masses=None):
|
|
185
|
+
"""
|
|
186
|
+
类比物理动量的一致性度量
|
|
187
|
+
"""
|
|
188
|
+
if masses is None:
|
|
189
|
+
masses = np.ones(len(vectors)) # 默认单位质量
|
|
190
|
+
|
|
191
|
+
# 计算总动量
|
|
192
|
+
momenta = vectors * masses[:, np.newaxis] # p = m*v
|
|
193
|
+
total_momentum = np.sum(momenta, axis=0)
|
|
194
|
+
|
|
195
|
+
# 计算总动能
|
|
196
|
+
kinetic_energies = 0.5 * masses * np.sum(vectors**2, axis=1)
|
|
197
|
+
total_energy = np.sum(kinetic_energies)
|
|
198
|
+
|
|
199
|
+
# 一致性指标:总动量大小 / 总能量(类比速度一致性)
|
|
200
|
+
if total_energy > 0:
|
|
201
|
+
coherence = np.linalg.norm(total_momentum) / (2 * total_energy) ** 0.5
|
|
202
|
+
else:
|
|
203
|
+
coherence = 0
|
|
204
|
+
|
|
205
|
+
# 方向一致性(动量方向与个体方向的平均对齐)
|
|
206
|
+
if np.linalg.norm(total_momentum) > 0:
|
|
207
|
+
momentum_direction = total_momentum / np.linalg.norm(total_momentum)
|
|
208
|
+
unit_vectors = vectors / np.linalg.norm(vectors, axis=1, keepdims=True)
|
|
209
|
+
directional_alignment = np.mean(np.abs(np.dot(unit_vectors, momentum_direction)))
|
|
210
|
+
else:
|
|
211
|
+
directional_alignment = 0
|
|
212
|
+
|
|
213
|
+
return coherence, directional_alignment, np.linalg.norm(total_momentum)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def multi_scale_coherence(vectors, positions=None, scale_factors=[1.0, 0.5, 0.1]):
|
|
218
|
+
"""
|
|
219
|
+
多尺度一致性分析:检测不同空间尺度的一致性
|
|
220
|
+
"""
|
|
221
|
+
if positions is None:
|
|
222
|
+
positions = np.random.rand(len(vectors), 2) # 随机位置
|
|
223
|
+
|
|
224
|
+
coherence_scores = []
|
|
225
|
+
|
|
226
|
+
for scale in scale_factors:
|
|
227
|
+
# 根据空间距离加权
|
|
228
|
+
if len(positions) > 0:
|
|
229
|
+
distances = squareform(pdist(positions))
|
|
230
|
+
weights = np.exp(-distances / scale) # 距离衰减权重
|
|
231
|
+
|
|
232
|
+
# 计算加权方向一致性
|
|
233
|
+
unit_vectors = vectors / np.linalg.norm(vectors, axis=1, keepdims=True)
|
|
234
|
+
weighted_avg = np.zeros_like(unit_vectors[0])
|
|
235
|
+
|
|
236
|
+
for i in range(len(vectors)):
|
|
237
|
+
neighbor_weights = weights[i] / np.sum(weights[i])
|
|
238
|
+
weighted_avg += np.sum(unit_vectors * neighbor_weights[:, np.newaxis], axis=0)
|
|
239
|
+
|
|
240
|
+
scale_coherence = np.linalg.norm(weighted_avg) / len(vectors)
|
|
241
|
+
coherence_scores.append(scale_coherence)
|
|
242
|
+
else:
|
|
243
|
+
coherence_scores.append(directional_alignment(vectors))
|
|
244
|
+
|
|
245
|
+
return dict(zip(scale_factors, coherence_scores))
|
|
246
|
+
|
|
247
|
+
def vector_field_coherence_score(vectors, positions=None, weights=None):
|
|
248
|
+
"""
|
|
249
|
+
向量场一致性综合评分 (0-100分)
|
|
250
|
+
"""
|
|
251
|
+
# 1. 基础方向一致性 (0-1)
|
|
252
|
+
dir_consistency = directional_alignment(vectors)
|
|
253
|
+
|
|
254
|
+
# 2. 移动强度指标
|
|
255
|
+
magnitudes = np.linalg.norm(vectors, axis=1)
|
|
256
|
+
intensity_score = np.mean(magnitudes) / (np.std(magnitudes) + 1e-8)
|
|
257
|
+
intensity_score = min(1.0, intensity_score / 3.0) # 标准化到0-1
|
|
258
|
+
|
|
259
|
+
# 3. 空间相关性(如果有位置信息)
|
|
260
|
+
if positions is not None and len(positions) > 10:
|
|
261
|
+
nbrs = NearestNeighbors(n_neighbors=5).fit(positions)
|
|
262
|
+
distances, indices = nbrs.kneighbors(positions)
|
|
263
|
+
|
|
264
|
+
neighbor_correlations = []
|
|
265
|
+
for i, neighbors in enumerate(indices):
|
|
266
|
+
if len(neighbors) > 1:
|
|
267
|
+
# 计算与邻居的方向相似度
|
|
268
|
+
unit_vec = vectors[i] / np.linalg.norm(vectors[i])
|
|
269
|
+
neighbor_vecs = vectors[neighbors[1:]] # 排除自身
|
|
270
|
+
neighbor_units = neighbor_vecs / np.linalg.norm(neighbor_vecs, axis=1, keepdims=True)
|
|
271
|
+
correlations = np.abs(np.dot(neighbor_units, unit_vec))
|
|
272
|
+
neighbor_correlations.extend(correlations)
|
|
273
|
+
|
|
274
|
+
spatial_consistency = np.mean(neighbor_correlations) if neighbor_correlations else 0.5
|
|
275
|
+
else:
|
|
276
|
+
spatial_consistency = 0.5 # 默认值
|
|
277
|
+
|
|
278
|
+
# 4. 综合评分 (加权平均)
|
|
279
|
+
weights = weights or [0.4, 0.3, 0.3] # 方向、强度、空间权重
|
|
280
|
+
composite_score = (weights[0] * dir_consistency +
|
|
281
|
+
weights[1] * intensity_score +
|
|
282
|
+
weights[2] * spatial_consistency)
|
|
283
|
+
|
|
284
|
+
# 转换为0-100分
|
|
285
|
+
vfcs = composite_score * 100
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
'vfcs': vfcs,
|
|
289
|
+
'direction_consistency': dir_consistency * 100,
|
|
290
|
+
'intensity_score': intensity_score * 100,
|
|
291
|
+
'spatial_consistency': spatial_consistency * 100,
|
|
292
|
+
'components': {
|
|
293
|
+
'direction': dir_consistency,
|
|
294
|
+
'intensity': intensity_score,
|
|
295
|
+
'spatial': spatial_consistency
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
@@ -15,10 +15,12 @@ class LabelMatrix:
|
|
|
15
15
|
mat, self.labels_ = vectorized_label_to_matrix(labels=labels, sep_pattern=sep_pattern)
|
|
16
16
|
elif speedup=='parallel':
|
|
17
17
|
mat, self.labels_ = parallel_label_to_matrix(labels=labels, sep_pattern=sep_pattern)
|
|
18
|
+
|
|
19
|
+
self.labels_ = np.array(self.labels_)
|
|
18
20
|
return mat
|
|
19
21
|
|
|
20
22
|
def inverse_transform(self, matrix):
|
|
21
|
-
matrix_to_labels(matrix=matrix, unique_labels=self.labels_)
|
|
23
|
+
return matrix_to_labels(matrix=matrix, unique_labels=self.labels_)
|
|
22
24
|
|
|
23
25
|
def label_to_matrix(labels, sep_pattern=r'[;_\-\s]'):
|
|
24
26
|
"""
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from scipy.spatial.distance import pdist, squareform
|
|
3
|
-
|
|
4
|
-
def calculate_movement_stats(vectors):
|
|
5
|
-
"""
|
|
6
|
-
计算移动矢量的基本统计量
|
|
7
|
-
"""
|
|
8
|
-
# 计算每个矢量的模长(移动距离)
|
|
9
|
-
distances = np.linalg.norm(vectors, axis=1)
|
|
10
|
-
|
|
11
|
-
stats = {
|
|
12
|
-
'total_movement': np.sum(distances),
|
|
13
|
-
'mean_distance': np.mean(distances),
|
|
14
|
-
'median_distance': np.median(distances),
|
|
15
|
-
'std_distance': np.std(distances),
|
|
16
|
-
'max_distance': np.max(distances),
|
|
17
|
-
'min_distance': np.min(distances),
|
|
18
|
-
'total_points': len(vectors)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return stats, distances
|
|
22
|
-
|
|
23
|
-
def calculate_direction_stats(vectors):
|
|
24
|
-
"""
|
|
25
|
-
计算移动方向的一致性
|
|
26
|
-
"""
|
|
27
|
-
# 单位向量
|
|
28
|
-
unit_vectors = vectors / np.linalg.norm(vectors, axis=1, keepdims=True)
|
|
29
|
-
|
|
30
|
-
# 平均方向向量
|
|
31
|
-
mean_direction = np.mean(unit_vectors, axis=0)
|
|
32
|
-
mean_direction_norm = np.linalg.norm(mean_direction)
|
|
33
|
-
|
|
34
|
-
# 方向一致性(0-1,1表示完全一致)
|
|
35
|
-
direction_consistency = mean_direction_norm
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
'direction_consistency': direction_consistency,
|
|
39
|
-
'mean_direction': mean_direction,
|
|
40
|
-
'direction_variance': 1 - direction_consistency # 方向分散度
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
def calculate_movement_energy(vectors, masses=None):
|
|
44
|
-
"""
|
|
45
|
-
计算移动的能量(假设每个点有质量)
|
|
46
|
-
"""
|
|
47
|
-
if masses is None:
|
|
48
|
-
masses = np.ones(len(vectors)) # 默认单位质量
|
|
49
|
-
|
|
50
|
-
# 动能 = 0.5 * mass * velocity^2
|
|
51
|
-
speeds_squared = np.sum(vectors**2, axis=1)
|
|
52
|
-
kinetic_energy = 0.5 * masses * speeds_squared
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
'total_energy': np.sum(kinetic_energy),
|
|
56
|
-
'mean_energy': np.mean(kinetic_energy),
|
|
57
|
-
'energy_std': np.std(kinetic_energy)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
def calculate_movement_divergence(positions, vectors):
|
|
61
|
-
"""
|
|
62
|
-
计算移动的散度(衡量扩张/收缩)
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
# 计算移动前后的位置
|
|
66
|
-
new_positions = positions + vectors
|
|
67
|
-
|
|
68
|
-
# 计算位置变化的协方差
|
|
69
|
-
orig_cov = np.cov(positions.T)
|
|
70
|
-
new_cov = np.cov(new_positions.T)
|
|
71
|
-
|
|
72
|
-
# 体积变化(行列式比值)
|
|
73
|
-
volume_ratio = np.linalg.det(new_cov) / np.linalg.det(orig_cov)
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
'volume_expansion': volume_ratio, # >1扩张, <1收缩
|
|
77
|
-
'expansion_factor': volume_ratio**(1/positions.shape[1])
|
|
78
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|