SURE-tools 2.1.8__py3-none-any.whl → 2.1.10__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.

Potentially problematic release.


This version of SURE-tools might be problematic. Click here for more details.

SURE/flow/__init__.py CHANGED
@@ -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
SURE/flow/flow_stats.py CHANGED
@@ -1,6 +1,34 @@
1
1
  import numpy as np
2
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
3
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
+
4
32
  def calculate_movement_stats(vectors):
5
33
  """
6
34
  计算移动矢量的基本统计量
@@ -75,4 +103,196 @@ def calculate_movement_divergence(positions, vectors):
75
103
  return {
76
104
  'volume_expansion': volume_ratio, # >1扩张, <1收缩
77
105
  'expansion_factor': volume_ratio**(1/positions.shape[1])
78
- }
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
+
SURE/perturb/perturb.py CHANGED
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SURE-tools
3
- Version: 2.1.8
3
+ Version: 2.1.10
4
4
  Summary: Succinct Representation of Single Cells
5
5
  Home-page: https://github.com/ZengFLab/SURE
6
6
  Author: Feng Zeng
@@ -9,19 +9,19 @@ SURE/atac/__init__.py,sha256=3smP8IKHfwNCd1G_sZH3pKHXuLkLpFuLtjUTUSy7_As,34
9
9
  SURE/atac/utils.py,sha256=m4NYwpy9O5T1pXTzgCOCcmlwrC6GTi-cQ5sm2wZu2O8,4354
10
10
  SURE/codebook/__init__.py,sha256=2T5gjp8JIaBayrXAnOJYSebQHsWprOs87difpR1OPNw,243
11
11
  SURE/codebook/codebook.py,sha256=ZlN6gRX9Gj2D2u3P5KeOsbZri0MoMAiJo9lNeL-MK-I,17117
12
- SURE/flow/__init__.py,sha256=eIcHeeISEOXEB0zRW-uiRlDz5IEUbA7rZZ1htUxhLVU,167
13
- SURE/flow/flow_stats.py,sha256=wpIxmOpYPU7YcgxqXKS8EDmnZ3oGh-YdBjiBiEmHcoU,2360
12
+ SURE/flow/__init__.py,sha256=rsAjYsh1xVIrxBCuwOE0Q_6N5th1wBgjJceV0ABPG3c,183
13
+ SURE/flow/flow_stats.py,sha256=3F3waCuEbIQ7bsiGga4cUvJphYdWA307SyGwEh8EzM8,10514
14
14
  SURE/flow/plot_quiver.py,sha256=spcPC0BDpvC-FBk9XIu6rcJI64bS-U-IVmmKLYHHXgs,1865
15
15
  SURE/flow/quiver.py,sha256=_euFqSaRrDoZ_oOabOx20LOoUTJ__XPhLW-vzLNQfAo,1859
16
16
  SURE/perturb/__init__.py,sha256=ouxShhbxZM4r5Gf7GmKiutrsmtyq7QL8rHjhgF0BU08,32
17
- SURE/perturb/perturb.py,sha256=LhrQSZEka7GFc9x4YfMhzHEYE-oHWwDg5tlhIRXVtGg,3237
17
+ SURE/perturb/perturb.py,sha256=CqO3xPfNA3cG175tadDidKvGsTu_yKfJRRLn_93awKM,3303
18
18
  SURE/utils/__init__.py,sha256=Htqv4KqVKcRiaaTBsR-6yZ4LSlbhbzutjNKXGD9-uds,660
19
19
  SURE/utils/custom_mlp.py,sha256=07TYX1HgxfEjb_3i5MpiZfNhOhx3dKntuwGkrpteWiM,7036
20
20
  SURE/utils/queue.py,sha256=E_5PA5EWcBoGAZj8BkKQnkCK0p4C-4-xcTPqdIXaPXU,1892
21
21
  SURE/utils/utils.py,sha256=IUHjDDtYaAYllCWsZyIzqQwaLul6fJRvHRH4vIYcR-c,8462
22
- sure_tools-2.1.8.dist-info/licenses/LICENSE,sha256=TFHKwmrAViXQbSX5W-NDItkWFjm45HWOeUniDrqmnu0,1065
23
- sure_tools-2.1.8.dist-info/METADATA,sha256=DJqLBtteAneDszgl4HiVf-Fucqzn9thAXoXzPq6b6_Y,2650
24
- sure_tools-2.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- sure_tools-2.1.8.dist-info/entry_points.txt,sha256=-nJI8rVe_qqrR0HmfAODzj-JNfEqCcSsyVh6okSqyHk,83
26
- sure_tools-2.1.8.dist-info/top_level.txt,sha256=BtFTebdiJeqra4r6mm-uEtwVRFLZ_IjYsQ7OnalrOvY,5
27
- sure_tools-2.1.8.dist-info/RECORD,,
22
+ sure_tools-2.1.10.dist-info/licenses/LICENSE,sha256=TFHKwmrAViXQbSX5W-NDItkWFjm45HWOeUniDrqmnu0,1065
23
+ sure_tools-2.1.10.dist-info/METADATA,sha256=2KG05qwCqT3IfABXzhHK2_h0mjgUmVpOYw1mwy078MU,2651
24
+ sure_tools-2.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ sure_tools-2.1.10.dist-info/entry_points.txt,sha256=-nJI8rVe_qqrR0HmfAODzj-JNfEqCcSsyVh6okSqyHk,83
26
+ sure_tools-2.1.10.dist-info/top_level.txt,sha256=BtFTebdiJeqra4r6mm-uEtwVRFLZ_IjYsQ7OnalrOvY,5
27
+ sure_tools-2.1.10.dist-info/RECORD,,