dspin 1.3.0__tar.gz → 1.3.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dspin
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: Regulatory network models from single-cell perturbation profiling
5
5
  Home-page: https://github.com/JialongJiang/DSPIN
6
6
  Author: Jialong Jiang
@@ -76,7 +76,8 @@ import networkx as nx
76
76
 
77
77
  def summary_components(all_components: np.array,
78
78
  num_spin: int,
79
- summary_method: str = 'kmeans') -> List[np.array]:
79
+ summary_method: str = 'kmeans',
80
+ figure_folder: str=None) -> List[np.array]:
80
81
  """
81
82
  Summarize components using a clustering algorithm.
82
83
 
@@ -88,6 +89,8 @@ def summary_components(all_components: np.array,
88
89
  The number of clusters.
89
90
  summary_method : str, optional
90
91
  The method used for summarizing the components. Options are 'kmeans' or 'leiden'. Default is 'kmeans'.
92
+ figure_folder : str, optional
93
+ Folder in which to save the figure.
91
94
 
92
95
  Returns
93
96
  -------
@@ -99,7 +102,12 @@ def summary_components(all_components: np.array,
99
102
  if summary_method == 'kmeans':
100
103
  # Fit KMeans clustering to the components and to their transposed version.
101
104
  kmeans = KMeans(n_clusters=num_spin, random_state=0, n_init=50).fit(all_components)
102
- kmeans_gene = KMeans(n_clusters=2 * num_spin, random_state=0, n_init=10).fit(all_components.T)
105
+
106
+ # take the genes with larger weights for display only
107
+ gene_weight = np.sum(all_components ** 2, axis=0) ** 0.5
108
+ gene_sele_filt = gene_weight > np.mean(gene_weight)
109
+ all_components_sub = all_components[:, gene_sele_filt]
110
+ kmeans_gene = KMeans(n_clusters=2 * num_spin, random_state=0, n_init=10).fit(all_components_sub.T)
103
111
 
104
112
  # Initialize an array to store the average component for each cluster.
105
113
  components_kmeans = np.zeros((num_spin, num_gene))
@@ -115,6 +123,24 @@ def summary_components(all_components: np.array,
115
123
  for ii in range(num_spin):
116
124
  # Determine gene cluster assignments based on the maximum component values.
117
125
  gene_groups_ind.append(np.argmax(components_kmeans, axis=0) == ii)
126
+
127
+
128
+
129
+ sc.set_figure_params(figsize=(8, 4))
130
+
131
+ plt.subplot(1, 2, 1)
132
+ gene_order = np.argsort(kmeans_gene.labels_)
133
+ comp_order = np.argsort(kmeans.labels_)
134
+ plt.imshow(all_components_sub[comp_order, :][:, gene_order], aspect='auto', cmap='Blues', vmax=np.max(all_components) / 10, interpolation='none')
135
+ plt.title('All components')
136
+
137
+ plt.subplot(1, 2, 2)
138
+ plt.imshow(components_kmeans[:, gene_sele_filt][:, gene_order], aspect='auto', cmap='Blues', vmax=np.max(components_kmeans) / 10, interpolation='none')
139
+ plt.title('Kmeans components')
140
+
141
+ if figure_folder is not None:
142
+ plt.savefig(figure_folder + 'onmf_decomposition_summary.png', dpi=300, bbox_inches='tight')
143
+ plt.close()
118
144
 
119
145
  elif summary_method == 'leiden':
120
146
 
@@ -144,8 +170,25 @@ def summary_components(all_components: np.array,
144
170
  diff = optimiser.optimise_partition(partition, n_iterations=- 1, is_membership_fixed=list(membership_fixed))
145
171
 
146
172
  gene_groups_ind = []
173
+ cluster_label_full = np.nan * np.ones(consensus.shape[0])
174
+
147
175
  for ii, part in enumerate(partition):
148
176
  gene_groups_ind.append(part)
177
+ cluster_label_full[part] = ii
178
+
179
+ gene_order = np.argsort(cluster_label_full)
180
+ gene_list_size = np.array([np.sum(cluster_label_full == ii) for ii in range(num_spin)])
181
+
182
+ plt.figure(figsize=[8, 8])
183
+ plt.imshow(consensus[gene_order][:, gene_order], cmap='Blues', vmin=0, vmax=np.percentile(consensus.flatten(), 98))
184
+ for ii in range(1, num_spin):
185
+ plt.axvline(np.sum(gene_list_size[:ii]) - 0.5, color='k')
186
+ plt.axhline(np.sum(gene_list_size[:ii]) - 0.5, color='k')
187
+ plt.grid()
188
+
189
+ if figure_folder is not None:
190
+ plt.savefig(figure_folder + 'onmf_decomposition_summary.png', dpi=300, bbox_inches='tight')
191
+ plt.close()
149
192
 
150
193
  return gene_groups_ind
151
194
 
@@ -194,7 +237,9 @@ def onmf(X: np.array, rank: int, max_iter: int = 500) -> Tuple[np.array, np.arra
194
237
  # progress bar
195
238
  if itr % 10 == 0:
196
239
  error = np.linalg.norm(X - np.dot(A, S), 'fro')
197
- pbar.set_postfix({"Reconstruction Error": f"{error:.2f}"})
240
+ self_product = S.dot(S.T)
241
+ orthogonal_error = np.linalg.norm(self_product - np.diag(np.diag(self_product)), 'fro') / np.linalg.norm(S, 'fro')
242
+ pbar.set_postfix({"Reconstruction error": f"{error:.2f}", "Orthogonal error": f"{orthogonal_error:.4f}"})
198
243
 
199
244
  pbar.close()
200
245
 
@@ -927,6 +972,8 @@ def learn_network_adam(raw_data: Any,
927
972
  The trained h matrix.
928
973
  The training log.
929
974
  """
975
+ np.random.seed(train_dat['seed'])
976
+
930
977
  # Retrieve training parameters and data
931
978
  num_spin, num_round = train_dat['cur_h'].shape
932
979
  num_epoch, stepsz, rec_gap = (
@@ -936,10 +983,7 @@ def learn_network_adam(raw_data: Any,
936
983
  list_step = np.arange(num_epoch, 0, - rec_gap)[::-1]
937
984
  cur_j, cur_h = (train_dat.get(key, None) for key in ["cur_j", "cur_h"])
938
985
  save_path = train_dat.get('save_path', None)
939
- backtrack_gap, backtrack_tol = (
940
- train_dat.get(
941
- key, None) for key in [
942
- "backtrack_gap", "backtrack_tol"])
986
+ backtrack_gap, backtrack_tol = (train_dat.get(key, None) for key in ["backtrack_gap", "backtrack_tol"])
943
987
 
944
988
  # Initialize variables to store parameters, gradients, and other values
945
989
  # during training
@@ -993,7 +1037,7 @@ def learn_network_adam(raw_data: Any,
993
1037
  # print('Progress: %d, Network gradient: %f' % (
994
1038
  # np.round(100 * counter / num_epoch, 2), rec_jgrad_sum_norm[counter - 1]))
995
1039
  pbar.update(rec_gap)
996
- pbar.set_postfix({"Network Gradient": f"{rec_jgrad_sum_norm[counter - 1]:.4f}"})
1040
+ pbar.set_postfix({"Network Gradient": f"{rec_jgrad_sum_norm[counter - 1]:.6f}"})
997
1041
 
998
1042
  # Handle backtracking
999
1043
 
@@ -204,17 +204,18 @@ class AbstractDSPIN(ABC):
204
204
  self._raw_data = raw_data
205
205
 
206
206
  num_sample = len(raw_data)
207
- params = {'num_epoch': 200,
207
+ params = {'num_epoch': 400,
208
208
  'cur_j': np.zeros((num_spin, num_spin)),
209
209
  'cur_h': np.zeros((num_spin, num_sample)),
210
210
  'save_path': self.save_path,
211
- 'rec_gap': 10}
211
+ 'rec_gap': 10,
212
+ 'seed': 0}
212
213
  params.update({'lambda_l1_j': 0.01,
213
214
  'lambda_l1_h': 0,
214
215
  'lambda_l2_j': 0,
215
216
  'lambda_l2_h': 0.005})
216
- params.update({'backtrack_gap': 20,
217
- 'backtrack_tol': 4})
217
+ params.update({'backtrack_gap': 40,
218
+ 'backtrack_tol': 5})
218
219
 
219
220
  if method == 'maximum_likelihood':
220
221
  params['stepsz'] = 0.2
@@ -518,7 +519,7 @@ class ProgramDSPIN(AbstractDSPIN):
518
519
 
519
520
  all_components = rec_components.reshape(-1, np.sum(prior_programs_mask))
520
521
 
521
- gene_group_ind = summary_components(all_components, num_onmf_components, summary_method=summary_method)
522
+ gene_group_ind = summary_components(all_components, num_onmf_components, summary_method=summary_method, figure_folder=self.fig_folder)
522
523
 
523
524
  # Mask the prior programs and add them to the gene group indices
524
525
  sub_mask_ind = np.where(prior_programs_mask)[0]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dspin
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: Regulatory network models from single-cell perturbation profiling
5
5
  Home-page: https://github.com/JialongJiang/DSPIN
6
6
  Author: Jialong Jiang
@@ -21,7 +21,7 @@ install_requires = [
21
21
  # ]
22
22
 
23
23
  # Managing your version (adjust accordingly)
24
- version = "1.3.0" # You can manage versioning in a more sophisticated way if needed
24
+ version = "1.3.1" # You can manage versioning in a more sophisticated way if needed
25
25
 
26
26
  # Long description (usually a README file)
27
27
  readme = open("README_PyPI.md").read() # Adjust the file name if necessary
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