pycyto 0.0.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.
pycyto-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,30 @@
1
+ Metadata-Version: 2.1
2
+ Name: pycyto
3
+ Version: 0.0.1
4
+ Summary: pycyto is designed to analyze Stereo-seq data.
5
+ Home-page: https://github.com/mgy520/pycyto
6
+ Author: Mao Guangyao
7
+ License: MIT License
8
+ Requires-Python: ==3.8.18
9
+ Requires-Dist: rpy2==3.5.15
10
+ Requires-Dist: anndata2ri==1.3.1
11
+ Requires-Dist: numpy==1.24.4
12
+ Requires-Dist: diffxpy==0.7.4
13
+ Requires-Dist: scipy==1.10.1
14
+ Requires-Dist: pandas==2.0.3
15
+ Requires-Dist: anndata==0.9.2
16
+ Requires-Dist: shapely==2.0.3
17
+ Requires-Dist: dask==2023.5.0
18
+ Requires-Dist: numba==0.58.1
19
+ Requires-Dist: pca==2.0.5
20
+ Requires-Dist: openTSNE==1.0.1
21
+ Requires-Dist: igraph==0.11.4
22
+ Requires-Dist: sinfonia==0.0.3
23
+ Requires-Dist: tangram==0.7.0
24
+ Requires-Dist: scanorama==1.7.4
25
+ Requires-Dist: matplotlib==3.7.4
26
+ Requires-Dist: seaborn==0.13.2
27
+ Requires-Dist: adjustText==1.1.1
28
+ Requires-Dist: scikit-learn==1.3.2
29
+ Requires-Dist: scikit-misc==0.2.0
30
+ Requires-Dist: scikit-image==0.21.0
@@ -0,0 +1,74 @@
1
+ import diffxpy.api as de
2
+ import numpy as np
3
+ from sklearn.utils.sparsefuncs import mean_variance_axis
4
+ from scipy.sparse import issparse
5
+
6
+
7
+ def findallmarkers(cdata, cluster_key, min_pct=0.1, only_pos=True):
8
+ """
9
+ Find marker genes for each cluster in cdata.
10
+
11
+ Parameters:
12
+ cdata (Anndata): An Anndata object.
13
+ cluster_key (str): The key representing the cell cluster annotations in the observation metadata of the Anndata object.
14
+ min_pct (float, optional): The minimum percentage threshold for filtering sparse genes. Defaults to 0.1.
15
+ only_pos (bool, optional): Whether to consider only genes with positive log2 fold change. Defaults to True.
16
+
17
+ Returns:
18
+ cdata (Anndata): An Anndata object with marker genes identified for each cell cluster. The marker genes and related statistical information are stored in the `uns` attribute of the Anndata object under the key 'markers_all'.
19
+ """
20
+ clusters = cdata.obs[cluster_key].unique()
21
+ cluster_markers = {}
22
+ for cluster in clusters:
23
+ cdata.obs['group'] = ['other' if x == cluster else 'current' for x in cdata.obs[cluster_key]]
24
+ cluster_cells = cdata[cdata.obs['group'] == 'current']
25
+ other_cells = cdata[cdata.obs['group'] == 'other']
26
+ pct1 = np.mean(cluster_cells.X > 0, axis=0).A1 if issparse(cluster_cells.X) else np.mean(cluster_cells.X > 0, axis=0)
27
+ pct2 = np.mean(other_cells.X > 0, axis=0).A1 if issparse(other_cells.X) else np.mean(other_cells.X > 0, axis=0)
28
+ if issparse(cdata.X):
29
+ mean1, _ = mean_variance_axis(axis=0, X=cluster_cells.X)
30
+ mean2, _ = mean_variance_axis(axis=0, X=other_cells.X)
31
+ else:
32
+ mean1 = cluster_cells.X.mean(axis=0)
33
+ mean2 = other_cells.X.mean(axis=0)
34
+
35
+ selected_genes = (pct1 >= min_pct) | (pct2 >= min_pct)
36
+ np.float = float
37
+ test_result = de.test.t_test(
38
+ data=cdata[:, selected_genes],
39
+ grouping=cdata.obs["group"],
40
+ is_logged=True
41
+ )
42
+ result = test_result.summary()
43
+ result['pct1'] = pct1[selected_genes]
44
+ result['pct2'] = pct2[selected_genes]
45
+ if only_pos:
46
+ result = result[result['log2fc'] > 0]
47
+
48
+ cluster_markers[cluster] = result
49
+ cdata.uns['markers_all'] = cluster_markers
50
+
51
+ return cdata
52
+
53
+
54
+ def find_markers_between_groups(cdata, cluster_key, group1, group2, min_pct=0.1, only_pos=True):
55
+ """
56
+ Find marker genes between two specified groups in cdata.
57
+
58
+ Parameters:
59
+ cdata (Anndata): An Anndata object containing the single-cell data.
60
+ cluster_key (str): The key representing the cell cluster annotations in the observation metadata of the Anndata object.
61
+ group1 (str): The name of the first group for comparison.
62
+ group2 (str): The name of the second group for comparison.
63
+ min_pct (float, optional): The minimum percentage threshold for filtering sparse genes. Defaults to 0.1.
64
+ only_pos (bool, optional): Whether to consider only genes with positive log2 fold change. Defaults to True.
65
+
66
+ Returns:
67
+ cdata(Anndata): An Anndata object with marker genes identified between the specified groups. The marker genes and related statistical information are stored in the `uns` attribute of the Anndata object under a key formatted as 'DGE_group1_group2'.
68
+ """
69
+ tmp = cdata[(cdata.obs[cluster_key] == group1) | (cdata.obs[cluster_key] == group2)].copy()
70
+ tmp = findallmarkers(cdata=tmp, cluster_key=cluster_key, min_pct=min_pct, only_pos=only_pos)
71
+ key_name = f"DGE_{group1}_{group2}"
72
+ cdata.uns[key_name] = tmp.uns['markers_all']
73
+
74
+ return cdata
@@ -0,0 +1,333 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ import seaborn as sns
4
+ from pycyto import function
5
+
6
+ def markers_detected_by_diff_ngenes_scatter(adata, markers, image_width=6, image_height=6, xlabel='n_genes',
7
+ ylabel='Markers detection rate',title=None,o=None, **kwargs):
8
+ """
9
+ Create a scatter plot to visualize the relationship between the number of genes (n_genes) and the detection rate of markers.
10
+
11
+ Parameters:
12
+ adata (AnnData):An AnnData object.
13
+ markers (list): A list of marker gene names.
14
+ image_width (int, optional): Width of the generated image. Default is 6.
15
+ image_height (int, optional): Height of the generated image. Default is 6.
16
+ xlabel (str, optional): Label for the X-axis. Default is 'n_genes'.
17
+ ylabel (str, optional): Label for the Y-axis. Default is 'Markers detection rate'.
18
+ title (str, optional): Title of the plot. If not provided, no title is displayed.
19
+ o (str, optional): Path and filename for saving the image. If not provided, the image will not be saved.
20
+ **kwargs (typing.Any): Additional keyword arguments to be passed to the plt.scatter function.
21
+ """
22
+ adata.obs['n_genes'] = (adata.X > 0).sum(axis=1)
23
+ p = []
24
+ for i in range(len(adata)):
25
+ genes = adata.var_names[adata.X[i].nonzero()[1]]
26
+ intersect = set(genes).intersection(set(markers))
27
+ p.append(len(intersect) / len(set(markers)))
28
+
29
+ adata.obs["Markers detection rate"] = p
30
+ plt.figure(figsize=(image_width, image_height))
31
+ plt.scatter(adata.obs['n_genes'], adata.obs['Markers detection rate'], **kwargs)
32
+ plt.xlabel(xlabel)
33
+ plt.ylabel(ylabel)
34
+ plt.title(title)
35
+
36
+ if o is not None and isinstance(o, str):
37
+ plt.savefig(o)
38
+
39
+ plt.show()
40
+
41
+ def markers_detected_by_diff_ngenes_bar(adata, markers, bin=50, image_width=12, image_height=6, xlabel='n_genes',
42
+ ylabel='Markers detection rate', title=None, o=None, **kwargs):
43
+ """
44
+ Create a bar plot to visualize the relationship between the number of genes (n_genes) and the detection rate of markers.
45
+
46
+ Parameters:
47
+ adata (AnnData): An AnnData object.
48
+ markers (list): A list of marker gene names.
49
+ bin (int, optional): The bin size for grouping n_genes values. Default is 50.
50
+ image_width (int, optional): Width of the generated image. Default is 12.
51
+ image_height (int, optional): Height of the generated image. Default is 6.
52
+ xlabel (str, optional): Label for the X-axis. Default is 'n_genes'.
53
+ ylabel (str, optional): Label for the Y-axis. Default is 'Markers detection rate'.
54
+ title (str, optional): Title of the plot. If not provided, no title is displayed.
55
+ o (str, optional): Path and filename for saving the image. If not provided, the image will not be saved.
56
+ **kwargs (typing.Any): Additional keyword arguments to be passed to the plt.bar function.
57
+ """
58
+ adata.obs['n_genes'] = (adata.X > 0).sum(axis=1)
59
+ bins = np.arange(0, np.ceil(adata.obs['n_genes'].max() / bin) * bin, bin).astype(int)
60
+ adata.obs['n_genes_subset'] = np.digitize(adata.obs['n_genes'], bins)
61
+
62
+ counts = []
63
+ for i in range(len(adata)):
64
+ genes = adata.var_names[adata.X[i].nonzero()[1]]
65
+ intersect = set(genes).intersection(set(markers))
66
+ counts.append(len(intersect))
67
+
68
+ adata.obs["Markers intersect counts"] = counts
69
+
70
+ subset_counts = []
71
+ for i in range(len(bins) - 1):
72
+ subset = adata[adata.obs['n_genes_subset'] == i + 1]
73
+ n = 0
74
+ for cell in subset.obs_names:
75
+ n += subset.obs.loc[cell, 'Markers intersect counts']
76
+ if len(subset.obs_names) > 0:
77
+ n = n / len(subset.obs_names)
78
+ p = n / len(set(markers))
79
+ subset_counts.append(p)
80
+ else:
81
+ subset_counts.append(0)
82
+
83
+ plt.figure(figsize=(image_width, image_height))
84
+ plt.bar([f"{bins[i]}-{bins[i+1]}" for i in range(len(bins) - 1)], subset_counts, color='#898989',**kwargs)
85
+ plt.xticks(rotation=90)
86
+ plt.ylabel(ylabel)
87
+ plt.xlabel(xlabel)
88
+ plt.title(title)
89
+
90
+ if o is not None and isinstance(o, str):
91
+ plt.savefig(o)
92
+
93
+ plt.show()
94
+
95
+ def detect_markers_by_filter_cells(adata, markers, min_genes_list=list(range(0, 1400, 50)), min_cells_list=[3],
96
+ image_width=5, image_height=5, xlabel='min_genes', ylabel='Percentage',
97
+ title='Percentage of markers remaining',o=None, **kwargs):
98
+ """
99
+ Create a line plot that shows how many of the marker genes are still present in the adata after filtering,
100
+ as you change the min_genes and the min_cells used for filtering.(The proportion of marker genes in markers)
101
+
102
+ Parameters:
103
+ adata (AnnData): An AnnData object.
104
+ markers (list): A list of marker gene names.
105
+ min_genes_list (list, optional): A list of min_genes to consider. Default list(range(0, 1400, 50)).
106
+ min_cells_list (list, optional): A list of min_cells for gene filtering. Default [3].
107
+ image_width (int, optional): Width of the generated image. Default is 5.
108
+ image_height (int, optional): Height of the generated image. Default is 5.
109
+ xlabel (str, optional): Label for the X-axis. Default is 'min_genes'.
110
+ ylabel (str, optional): Label for the Y-axis. Default is 'Percentage'.
111
+ title (str, optional): Title of the plot. Default is 'Percentage of markers remaining'.
112
+ o (str, optional): Path and filename for saving the image. If not provided, the image will not be saved.
113
+ **kwargs (typing.Any): Additional keyword arguments to be passed to the plt.plot function.
114
+ """
115
+ marker_overlap = {frac: [] for frac in min_cells_list}
116
+ for frac in min_cells_list:
117
+ for min_genes in min_genes_list:
118
+ adata_filtered = adata.copy()
119
+ adata_filtered = function.filter_cells(adata_filtered, min_genes=min_genes)
120
+ adata_filtered = function.filter_genes(adata_filtered, min_cells=frac)
121
+ remaining_genes = adata_filtered.var_names.tolist()
122
+ overlap_genes = set(remaining_genes).intersection(set(markers))
123
+ marker_overlap_percent = len(overlap_genes) / len(set(markers))
124
+ marker_overlap[frac].append(marker_overlap_percent)
125
+
126
+ plt.figure(figsize=(image_width, image_height))
127
+ for frac in min_cells_list:
128
+ plt.plot(min_genes_list, marker_overlap[frac], label=f'min_cells={frac}', **kwargs)
129
+ plt.xlabel(xlabel)
130
+ plt.ylabel(ylabel)
131
+ plt.title(title)
132
+ plt.legend(bbox_to_anchor=(1.05, 0.5), loc='center left')
133
+ if o is not None and isinstance(o, str):
134
+ plt.savefig(o)
135
+ plt.show()
136
+
137
+ def detect_markers_by_filter_cells2(adata, markers, min_genes_list=list(range(0, 1400, 50)), min_cells_list=[3],
138
+ image_width=5, image_height=5, xlabel='min_genes', ylabel='Percentage',
139
+ title='Percentage of markers detected',o=None, **kwargs):
140
+ """
141
+ Create a line plot that shows how many of the marker genes are still present in the adata after filtering,
142
+ as you change the min_genes and the min_cells used for filtering.(The proportion of marker genes in adata)
143
+
144
+ Parameters:
145
+ adata (AnnData): An AnnData object.
146
+ markers (list): A list of marker gene names.
147
+ min_genes_list (list, optional): List of minimum gene counts for filtering. Default list(range(0, 1400, 50)).
148
+ min_cells_list (list, optional): List of minimum cell counts for filtering. Default is [3].
149
+ image_width (int, optional): Width of the generated image. Default is 5.
150
+ image_height (int, optional): Height of the generated image. Default is 5.
151
+ xlabel (str, optional): Label for the X-axis. Default is 'min_genes'.
152
+ ylabel (str, optional): Label for the Y-axis. Default is 'Percentage'.
153
+ title (str, optional): Title of the plot. Default is 'Percentage of markers detected'.
154
+ o (str, optional): Path and filename for saving the image. If not provided, the image will not be saved.
155
+ **kwargs (typing.Any): Additional keyword arguments to be passed to the plt.plot function.
156
+ """
157
+ ...
158
+ gene_overlap = {frac: [] for frac in min_cells_list}
159
+ for frac in min_cells_list:
160
+ for min_genes in min_genes_list:
161
+ adata_filtered = adata.copy()
162
+ adata_filtered = function.filter_cells(adata_filtered, min_genes=min_genes)
163
+ adata_filtered = function.filter_genes(adata_filtered, min_cells=frac)
164
+ remaining_genes = adata_filtered.var_names.tolist()
165
+ overlap_genes = set(remaining_genes).intersection(set(markers))
166
+ overlap_percent = len(overlap_genes) / len(remaining_genes)
167
+ gene_overlap[frac].append(overlap_percent)
168
+
169
+ plt.figure(figsize=(image_width, image_height))
170
+ for frac in min_cells_list:
171
+ plt.plot(min_genes_list, gene_overlap[frac], label=f'min_cells={frac}', **kwargs)
172
+ plt.xlabel(xlabel)
173
+ plt.ylabel(ylabel)
174
+ plt.title(title)
175
+ plt.legend(bbox_to_anchor=(1.05, 0.5), loc='center left')
176
+ if o is not None and isinstance(o, str):
177
+ plt.savefig(o)
178
+ plt.show()
179
+
180
+ def cell_numbers_by_min_genes(adata, min_genes_list=list(range(0, 1400, 50)),
181
+ image_width=5, image_height=5, xlabel='min_genes', ylabel='cell number',
182
+ title=None,o=None, **kwargs):
183
+ """
184
+ Create a line plot reflecting the number of cells remaining after filtering with different min_genes
185
+
186
+ Parameters:
187
+ adata (AnnData): An AnnData object.
188
+ min_genes_list (list, optional): List of minimum gene counts used for filtering cells. Default list(range(0, 1400, 50)).
189
+ image_width (int, optional): Width of the generated plot image. Default is 5.
190
+ image_height (int, optional): Height of the generated plot image. Default is 5.
191
+ xlabel (str, optional): Label for the X-axis of the plot. Default is 'min_genes'.
192
+ ylabel (str, optional): Label for the Y-axis of the plot. Default is 'cell number'.
193
+ title (str, optional): Title of the plot. If not provided, no title will be displayed.
194
+ o (str, optional): Path and filename for saving the plot image. If not provided, the image will not be saved.
195
+ **kwargs (typing.Any): Additional keyword arguments to be passed to the plt.plot function.
196
+ """
197
+ num_cells = []
198
+ for min_gene in min_genes_list:
199
+ adata_filtered = adata.copy()
200
+ adata_filtered = function.filter_cells(adata_filtered, min_genes=min_gene)
201
+ num_cells.append(adata_filtered.shape[0])
202
+
203
+ plt.figure(figsize=(image_width, image_height))
204
+ plt.plot(min_genes_list, num_cells, **kwargs)
205
+ plt.xlabel(xlabel)
206
+ plt.ylabel(ylabel)
207
+ plt.title(title)
208
+ if o is not None and isinstance(o, str):
209
+ plt.savefig(o)
210
+ plt.show()
211
+
212
+ def valid_cells_per_slice(adata, min_genes_list=list(range(0, 800, 100)), image_width=5, image_height=5, xlabel='min_genes',
213
+ slice='id', library='current object', median_n_genes=[],ylabel='Percentage',title='Percentage of markers detected',
214
+ o=None, **kwargs):
215
+ """
216
+ Create line plots to illustrate the relationship between the library median n_genes and the percentage of valid cells per slice.
217
+
218
+ Parameters:
219
+ adata (AnnData): An AnnData object.
220
+ min_genes_list (list, optional): A list of minimum gene counts for cell filtering. Default is a list from 0 to 800 with a step of 100.
221
+ image_width (int, optional): Width of the generated image. Default is 5.
222
+ image_height (int, optional): Height of the generated image. Default is 5.
223
+ xlabel (str, optional): Label for the X-axis. Default is 'min_genes'.
224
+ slice (str): Column in the observation data used for grouping slices and analyzing the percentage of valid cells.
225
+ library (str): Source of data for calculating the median number of genes per slice. Default is 'current object', using the observation data of the current object. Alternatively, provide a list 'median_n_genes' as reference.
226
+ median_n_genes (list, optional): If 'library' is not 'current object', provide a list of Library median gene counts as reference.
227
+ ylabel (str, optional): Label for the Y-axis. Default is 'Percentage'.
228
+ title (str, optional): Title of the plot. Default is 'Percentage of markers detected'.
229
+ o (str, optional): Path and filename for saving the image. If not provided, the image will not be saved.
230
+ **kwargs (typing.Any): Additional keyword arguments to be passed to the sns.regplot function.
231
+ """
232
+ adata.obs['n_genes'] = (adata.X > 0).sum(axis=1)
233
+ if library == 'current object':
234
+ library_median_n_genes = adata.obs.groupby(slice)['n_genes'].median().tolist()
235
+ elif median_n_genes is not None:
236
+ if not isinstance(median_n_genes, list):
237
+ raise ValueError("'median_n_genes' must be a list.")
238
+ library_median_n_genes = median_n_genes
239
+ else:
240
+ raise ValueError("If 'library' is not 'current object', 'median_n_genes' must be provided as a list.")
241
+
242
+ plt.figure(figsize=(image_width, image_height))
243
+ #colors = ['red', 'blue', 'green', 'orange', 'purple', 'gray', 'cyan', 'magenta']
244
+ s1 = adata.obs.groupby(slice).size()
245
+ s2_list = []
246
+ for i, min_genes in enumerate(min_genes_list):
247
+ adata_filtered = adata.copy()
248
+ adata_filtered = function.filter_cells(adata_filtered, min_genes=min_genes)
249
+ s2 = adata_filtered.obs.groupby(slice).size()
250
+ s2_list.append(s2)
251
+ p = s2 / s1
252
+ index_mapping = list(range(len(s1.index)))
253
+ sns.regplot(x=[library_median_n_genes[index_mapping[j]] for j in range(len(index_mapping))], y=p,
254
+ scatter_kws={'s': 2},label=f'min_genes={min_genes}', **kwargs)
255
+ #sns.regplot(x=[library_median_n_genes[index_mapping[j]] for j in range(len(index_mapping))], y=p,scatter_kws={'s': 2}, label=f'min_genes={min_genes}', color=colors[i])
256
+
257
+ plt.xlabel(xlabel)
258
+ plt.ylabel(ylabel)
259
+ plt.legend(fontsize=6)
260
+ plt.title(title)
261
+ if o is not None and isinstance(o, str):
262
+ plt.savefig(o)
263
+ plt.show()
264
+
265
+ def additional_seq_vs_seq(adata1, adata2, min_genes_list=list(range(0, 800, 100)), image_width=5, image_height=5, xlabel='min_genes',
266
+ slice='id', min_cells=3, ylabel='valid cells P.',title='sequencing vs additional sequencing',slice_id=None,
267
+ color='blue', s=15, o=None):
268
+ """
269
+ Create a scatter plot to compare the percentage of valid cells in sequencing data and additional sequencing data.
270
+
271
+ Parameters:
272
+ adata1 (AnnData): An AnnData object representing the sequencing data.
273
+ adata2 (AnnData): An AnnData object representing the additional sequencing data.
274
+ min_genes_list (list, optional): A list of minimum gene counts for cell filtering. Default is a list from 0 to 800 with a step of 100.
275
+ image_width (int, optional): Width of the generated image. Default is 5.
276
+ image_height (int, optional): Height of the generated image. Default is 5.
277
+ xlabel (str, optional): Label for the X-axis. Default is 'min_genes'.
278
+ slice (str): Column in the observation data used for grouping slices.
279
+ min_cells (int): min_cells to filter genes.
280
+ ylabel (str, optional): Label for the Y-axis. Default is 'valid cells P.'.
281
+ title (str, optional): Title of the plot. Default is 'sequencing vs additional sequencing'.
282
+ slice_id (str): The ID of the slice to analyze.
283
+ color (str): Color for the scatter plot markers. Default is 'blue'.
284
+ s (int): Size of the scatter plot markers. Default is 15.
285
+ o (str, optional): Path and filename for saving the image. If not provided, the image will not be saved.
286
+ """
287
+ adata1 = adata1[(adata1.obs[slice] == slice_id),]
288
+ adata2 = adata2[(adata2.obs[slice] == slice_id),]
289
+ s1_adata1 = adata1.obs.groupby(slice).size()
290
+ s1_adata2 = adata2.obs.groupby(slice).size()
291
+ p_adata1_list = []
292
+ p_adata2_list = []
293
+ for min_genes in min_genes_list:
294
+ adata1_filtered = adata1.copy()
295
+ adata2_filtered = adata2.copy()
296
+ adata1_filtered = function.filter_cells(adata1_filtered, min_genes=min_genes)
297
+ adata1_filtered = function.filter_genes(adata1_filtered, min_cells=min_cells)
298
+ adata2_filtered = function.filter_cells(adata2_filtered, min_genes=min_genes)
299
+ adata2_filtered = function.filter_genes(adata2_filtered, min_cells=min_cells)
300
+
301
+ s2_adata1 = adata1_filtered.obs.groupby(slice).size()
302
+ s2_adata2 = adata2_filtered.obs.groupby(slice).size()
303
+
304
+ p_adata1 = s2_adata1 / s1_adata1
305
+ p_adata2 = s2_adata2 / s1_adata2
306
+ p_adata1_list.append(p_adata1)
307
+ p_adata2_list.append(p_adata2)
308
+
309
+ plt.figure(figsize=(image_width, image_height))
310
+ if slice_id is None:
311
+ raise ValueError("Please provide a valid slice_id.")
312
+
313
+ p_adata1 = [p_adata1_list[i][slice_id] for i in range(len(min_genes_list))]
314
+ p_adata2 = [p_adata2_list[i][slice_id] for i in range(len(min_genes_list))]
315
+
316
+ plt.scatter(min_genes_list, p_adata1, label=f'{slice_id}', marker='o',color=color,s=s)
317
+ plt.scatter(min_genes_list, p_adata2, label=f'{slice_id}', marker='^',color=color,s=s)
318
+
319
+ plt.xlabel(xlabel)
320
+ plt.ylabel(ylabel)
321
+ plt.title(title)
322
+
323
+ legend_elements = [
324
+ plt.Line2D([0], [0], marker='o', color='w', label=f'{slice_id}', markersize=8)]
325
+ legend_elements.append(
326
+ plt.Line2D([0], [0], marker='o', color='w', label='sequencing', markerfacecolor=color, markersize=8))
327
+ legend_elements.append(
328
+ plt.Line2D([0], [0], marker='^', color='w', label='additional sequencing', markerfacecolor=color, markersize=8))
329
+
330
+ plt.legend(handles=legend_elements,loc='center left', bbox_to_anchor=(1, 0.5))
331
+ if o is not None and isinstance(o, str):
332
+ plt.savefig(o)
333
+ plt.show()
@@ -0,0 +1,8 @@
1
+ from .plot import *
2
+ from .function import *
3
+ from .format import *
4
+ from .QC import *
5
+ from .labeltransfer import *
6
+ from .cluster import *
7
+ from .Findmarkers import *
8
+ from .spatial_metacell import *
@@ -0,0 +1,46 @@
1
+ import anndata2ri
2
+ from rpy2.robjects import r
3
+ import numpy as np
4
+
5
+ anndata2ri.activate()
6
+
7
+ def cluster(cdata, K_set, neighborhood_size, n_PCs):
8
+ """
9
+ Stereo-seq data spatial clustering.
10
+
11
+ Parameters:
12
+ cdata (Anndata): Anndata object containing the single-cell data.
13
+ K_set (list): List of integers specifying the range of cluster numbers to consider.
14
+ neighborhood_size (int): Size of the neighborhood for computing adjacency matrix.
15
+ n_PCs (int): Number of principal components to use.
16
+
17
+ Returns:
18
+ cdata (Anndata): An Anndata object with cluster labels assigned to observations.
19
+ """
20
+ r.assign("cdata", cdata)
21
+ r.assign("K_set", K_set)
22
+ r.assign("neighborhood_size", neighborhood_size)
23
+ r.assign("num_pca_components", n_PCs)
24
+ r('''
25
+ cdata <- as(cdata, "SingleCellExperiment")
26
+ library(SC.MEB)
27
+ library(SingleCellExperiment)
28
+ pos = as.matrix(colData(cdata)[,c("row","col")])
29
+ Adj_sp = getneighborhood_fast(pos, neighborhood_size)
30
+ y = reducedDim(cdata, "PCA")[,1:n_PCs]
31
+ set.seed(114)
32
+ beta_grid = seq(0,4,0.2)
33
+ parallel=TRUE
34
+ num_core = 3
35
+ PX = TRUE
36
+ maxIter_ICM = 10
37
+ maxIter = 50
38
+ fit = SC.MEB(y, Adj_sp, beta_grid = beta_grid, K_set= K_set, parallel=parallel, num_core = num_core, PX = PX, maxIter_ICM=maxIter_ICM, maxIter=maxIter)
39
+ selectKPlot(fit, K_set = K_set, criterion = "BIC")
40
+ out = selectK(fit, K_set = K_set, criterion = "BIC")
41
+ ''')
42
+ out = r['out']
43
+ best_K_label_flat = np.array(out.rx2('best_K_label')).flatten()
44
+ cdata.obs['cluster'] = best_K_label_flat.astype(str)
45
+
46
+ return cdata