scMultiChat 0.1.0__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.
- MultiChat/Analysis/Intra_strength.py +1758 -0
- MultiChat/Analysis/Processing.py +152 -0
- MultiChat/Analysis/__init__.py +2 -0
- MultiChat/Heterogeneous_g_emb/__init__.py +13 -0
- MultiChat/Heterogeneous_g_emb/_settings.py +156 -0
- MultiChat/Heterogeneous_g_emb/_utils.py +143 -0
- MultiChat/Heterogeneous_g_emb/_version.py +3 -0
- MultiChat/Heterogeneous_g_emb/plotting/__init__.py +19 -0
- MultiChat/Heterogeneous_g_emb/plotting/_palettes.py +180 -0
- MultiChat/Heterogeneous_g_emb/plotting/_plot.py +1498 -0
- MultiChat/Heterogeneous_g_emb/plotting/_post_training.py +742 -0
- MultiChat/Heterogeneous_g_emb/plotting/_utils.py +103 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/__init__.py +26 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_general.py +91 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_pca.py +182 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_qc.py +727 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_utils.py +60 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_variable_genes.py +82 -0
- MultiChat/Heterogeneous_g_emb/readwrite.py +250 -0
- MultiChat/Heterogeneous_g_emb/tools/__init__.py +23 -0
- MultiChat/Heterogeneous_g_emb/tools/_gene_scores.py +346 -0
- MultiChat/Heterogeneous_g_emb/tools/_general.py +71 -0
- MultiChat/Heterogeneous_g_emb/tools/_integration.py +197 -0
- MultiChat/Heterogeneous_g_emb/tools/_pbg.py +1184 -0
- MultiChat/Heterogeneous_g_emb/tools/_post_training.py +919 -0
- MultiChat/Heterogeneous_g_emb/tools/_umap.py +58 -0
- MultiChat/Heterogeneous_g_emb/tools/_utils.py +253 -0
- MultiChat/Model/Layers.py +116 -0
- MultiChat/Model/__init__.py +3 -0
- MultiChat/Model/model_training.py +166 -0
- MultiChat/Model/modules.py +93 -0
- MultiChat/Model/utilities.py +234 -0
- MultiChat/Plot/Visualization.py +470 -0
- MultiChat/Plot/__init__.py +1 -0
- MultiChat/__init__.py +12 -0
- scmultichat-0.1.0.dist-info/METADATA +156 -0
- scmultichat-0.1.0.dist-info/RECORD +39 -0
- scmultichat-0.1.0.dist-info/WHEEL +5 -0
- scmultichat-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1498 @@
|
|
|
1
|
+
"""plotting functions"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
import matplotlib as mpl
|
|
8
|
+
from pandas.core.dtypes.common import is_numeric_dtype
|
|
9
|
+
import seaborn as sns
|
|
10
|
+
from adjustText import adjust_text
|
|
11
|
+
from pandas.api.types import (
|
|
12
|
+
is_string_dtype,
|
|
13
|
+
is_categorical_dtype,
|
|
14
|
+
)
|
|
15
|
+
from scipy.sparse import find
|
|
16
|
+
import warnings
|
|
17
|
+
import plotly.express as px
|
|
18
|
+
import plotly.graph_objects as go
|
|
19
|
+
|
|
20
|
+
from .._settings import settings
|
|
21
|
+
from ._utils import (
|
|
22
|
+
generate_palette
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def violin(adata,
|
|
27
|
+
list_obs=None,
|
|
28
|
+
list_var=None,
|
|
29
|
+
jitter=0.4,
|
|
30
|
+
size=1,
|
|
31
|
+
log=False,
|
|
32
|
+
pad=1.08,
|
|
33
|
+
w_pad=None,
|
|
34
|
+
h_pad=3,
|
|
35
|
+
fig_size=(3, 3),
|
|
36
|
+
fig_ncol=3,
|
|
37
|
+
save_fig=False,
|
|
38
|
+
fig_path=None,
|
|
39
|
+
fig_name='plot_violin.pdf',
|
|
40
|
+
**kwargs):
|
|
41
|
+
"""Violin plot
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
adata : `Anndata`
|
|
46
|
+
Annotated data matrix.
|
|
47
|
+
list_obs : `list`, optional (default: None)
|
|
48
|
+
A list of observations to plot.
|
|
49
|
+
list_var : `list`, optional (default: None)
|
|
50
|
+
A list of variables to plot.
|
|
51
|
+
jitter : `float`, optional (default: 0.4)
|
|
52
|
+
Amount of jitter to apply.
|
|
53
|
+
size : `int`, optional (default: 1)
|
|
54
|
+
The marker size
|
|
55
|
+
log : `bool`, optional (default: False)
|
|
56
|
+
If True, natural logarithm transformation will be performed.
|
|
57
|
+
pad: `float`, optional (default: 1.08)
|
|
58
|
+
Padding between the figure edge and the edges of subplots,
|
|
59
|
+
as a fraction of the font size.
|
|
60
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
61
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
62
|
+
as a fraction of the font size. Defaults to pad.
|
|
63
|
+
fig_size: `tuple`, optional (default: (3,3))
|
|
64
|
+
figure size.
|
|
65
|
+
fig_ncol: `int`, optional (default: 3)
|
|
66
|
+
the number of columns of the figure panel
|
|
67
|
+
save_fig: `bool`, optional (default: False)
|
|
68
|
+
if True,save the figure.
|
|
69
|
+
fig_path: `str`, optional (default: None)
|
|
70
|
+
If save_fig is True, specify figure path.
|
|
71
|
+
fig_name: `str`, optional (default: 'plot_violin.pdf')
|
|
72
|
+
if `save_fig` is True, specify figure name.
|
|
73
|
+
**kwargs: `dict`, optional
|
|
74
|
+
Other keyword arguments are passed through to ``sns.violinplot``
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
None
|
|
79
|
+
"""
|
|
80
|
+
if fig_size is None:
|
|
81
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
82
|
+
if save_fig is None:
|
|
83
|
+
save_fig = settings.save_fig
|
|
84
|
+
if fig_path is None:
|
|
85
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
86
|
+
if list_obs is None:
|
|
87
|
+
list_obs = []
|
|
88
|
+
if list_var is None:
|
|
89
|
+
list_var = []
|
|
90
|
+
for obs in list_obs:
|
|
91
|
+
if obs not in adata.obs_keys():
|
|
92
|
+
raise ValueError(f"could not find {obs} in `adata.obs_keys()`")
|
|
93
|
+
for var in list_var:
|
|
94
|
+
if var not in adata.var_keys():
|
|
95
|
+
raise ValueError(f"could not find {var} in `adata.var_keys()`")
|
|
96
|
+
if len(list_obs) > 0:
|
|
97
|
+
df_plot = adata.obs[list_obs].copy()
|
|
98
|
+
if log:
|
|
99
|
+
df_plot = pd.DataFrame(data=np.log1p(df_plot.values),
|
|
100
|
+
index=df_plot.index,
|
|
101
|
+
columns=df_plot.columns)
|
|
102
|
+
fig_nrow = int(np.ceil(len(list_obs)/fig_ncol))
|
|
103
|
+
fig = plt.figure(figsize=(fig_size[0]*fig_ncol*1.05,
|
|
104
|
+
fig_size[1]*fig_nrow))
|
|
105
|
+
for i, obs in enumerate(list_obs):
|
|
106
|
+
ax_i = fig.add_subplot(fig_nrow, fig_ncol, i+1)
|
|
107
|
+
sns.violinplot(ax=ax_i,
|
|
108
|
+
y=obs,
|
|
109
|
+
data=df_plot,
|
|
110
|
+
inner=None,
|
|
111
|
+
**kwargs)
|
|
112
|
+
sns.stripplot(ax=ax_i,
|
|
113
|
+
y=obs,
|
|
114
|
+
data=df_plot,
|
|
115
|
+
color='black',
|
|
116
|
+
jitter=jitter,
|
|
117
|
+
s=size)
|
|
118
|
+
|
|
119
|
+
ax_i.set_title(obs)
|
|
120
|
+
ax_i.set_ylabel('')
|
|
121
|
+
ax_i.locator_params(axis='y', nbins=6)
|
|
122
|
+
ax_i.tick_params(axis="y", pad=-2)
|
|
123
|
+
ax_i.spines['right'].set_visible(False)
|
|
124
|
+
ax_i.spines['top'].set_visible(False)
|
|
125
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
126
|
+
if save_fig:
|
|
127
|
+
if not os.path.exists(fig_path):
|
|
128
|
+
os.makedirs(fig_path)
|
|
129
|
+
plt.savefig(os.path.join(fig_path, fig_name),
|
|
130
|
+
pad_inches=1,
|
|
131
|
+
bbox_inches='tight')
|
|
132
|
+
plt.close(fig)
|
|
133
|
+
if len(list_var) > 0:
|
|
134
|
+
df_plot = adata.var[list_var].copy()
|
|
135
|
+
if log:
|
|
136
|
+
df_plot = pd.DataFrame(data=np.log1p(df_plot.values),
|
|
137
|
+
index=df_plot.index,
|
|
138
|
+
columns=df_plot.columns)
|
|
139
|
+
fig_nrow = int(np.ceil(len(list_obs)/fig_ncol))
|
|
140
|
+
fig = plt.figure(figsize=(fig_size[0]*fig_ncol*1.05,
|
|
141
|
+
fig_size[1]*fig_nrow))
|
|
142
|
+
for i, var in enumerate(list_var):
|
|
143
|
+
ax_i = fig.add_subplot(fig_nrow, fig_ncol, i+1)
|
|
144
|
+
sns.violinplot(ax=ax_i,
|
|
145
|
+
y=var,
|
|
146
|
+
data=df_plot,
|
|
147
|
+
inner=None,
|
|
148
|
+
**kwargs)
|
|
149
|
+
sns.stripplot(ax=ax_i,
|
|
150
|
+
y=var,
|
|
151
|
+
data=df_plot,
|
|
152
|
+
color='black',
|
|
153
|
+
jitter=jitter,
|
|
154
|
+
s=size)
|
|
155
|
+
|
|
156
|
+
ax_i.set_title(var)
|
|
157
|
+
ax_i.set_ylabel('')
|
|
158
|
+
ax_i.locator_params(axis='y', nbins=6)
|
|
159
|
+
ax_i.tick_params(axis="y", pad=-2)
|
|
160
|
+
ax_i.spines['right'].set_visible(False)
|
|
161
|
+
ax_i.spines['top'].set_visible(False)
|
|
162
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
163
|
+
if save_fig:
|
|
164
|
+
if not os.path.exists(fig_path):
|
|
165
|
+
os.makedirs(fig_path)
|
|
166
|
+
plt.savefig(os.path.join(fig_path, fig_name),
|
|
167
|
+
pad_inches=1,
|
|
168
|
+
bbox_inches='tight')
|
|
169
|
+
plt.close(fig)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def hist(adata,
|
|
173
|
+
list_obs=None,
|
|
174
|
+
list_var=None,
|
|
175
|
+
kde=True,
|
|
176
|
+
log=False,
|
|
177
|
+
pad=1.08,
|
|
178
|
+
w_pad=None,
|
|
179
|
+
h_pad=3,
|
|
180
|
+
fig_size=(3, 3),
|
|
181
|
+
fig_ncol=3,
|
|
182
|
+
save_fig=False,
|
|
183
|
+
fig_path=None,
|
|
184
|
+
fig_name='plot_histogram.pdf',
|
|
185
|
+
**kwargs
|
|
186
|
+
):
|
|
187
|
+
"""histogram plot
|
|
188
|
+
|
|
189
|
+
Parameters
|
|
190
|
+
----------
|
|
191
|
+
adata : `Anndata`
|
|
192
|
+
Annotated data matrix.
|
|
193
|
+
list_obs : `list`, optional (default: None)
|
|
194
|
+
A list of observations to plot.
|
|
195
|
+
list_var : `list`, optional (default: None)
|
|
196
|
+
A list of variables to plot.
|
|
197
|
+
kde : `bool`, optional (default: True)
|
|
198
|
+
If True, compute a kernel density estimate to smooth the distribution
|
|
199
|
+
and show on the plot
|
|
200
|
+
log : `bool`, optional (default: False)
|
|
201
|
+
If True, natural logarithm transformation will be performed.
|
|
202
|
+
pad: `float`, optional (default: 1.08)
|
|
203
|
+
Padding between the figure edge and the edges of subplots,
|
|
204
|
+
as a fraction of the font size.
|
|
205
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
206
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
207
|
+
as a fraction of the font size. Defaults to pad.
|
|
208
|
+
fig_size: `tuple`, optional (default: (3,3))
|
|
209
|
+
figure size.
|
|
210
|
+
fig_ncol: `int`, optional (default: 3)
|
|
211
|
+
the number of columns of the figure panel
|
|
212
|
+
save_fig: `bool`, optional (default: False)
|
|
213
|
+
if True,save the figure.
|
|
214
|
+
fig_path: `str`, optional (default: None)
|
|
215
|
+
If save_fig is True, specify figure path.
|
|
216
|
+
fig_name: `str`, optional (default: 'plot_violin.pdf')
|
|
217
|
+
if `save_fig` is True, specify figure name.
|
|
218
|
+
**kwargs: `dict`, optional
|
|
219
|
+
Other keyword arguments are passed through to ``sns.histplot``
|
|
220
|
+
|
|
221
|
+
Returns
|
|
222
|
+
-------
|
|
223
|
+
None
|
|
224
|
+
"""
|
|
225
|
+
if fig_size is None:
|
|
226
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
227
|
+
if save_fig is None:
|
|
228
|
+
save_fig = settings.save_fig
|
|
229
|
+
if fig_path is None:
|
|
230
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
231
|
+
if list_obs is None:
|
|
232
|
+
list_obs = []
|
|
233
|
+
if list_var is None:
|
|
234
|
+
list_var = []
|
|
235
|
+
for obs in list_obs:
|
|
236
|
+
if obs not in adata.obs_keys():
|
|
237
|
+
raise ValueError(f"could not find {obs} in `adata.obs_keys()`")
|
|
238
|
+
for var in list_var:
|
|
239
|
+
if var not in adata.var_keys():
|
|
240
|
+
raise ValueError(f"could not find {var} in `adata.var_keys()`")
|
|
241
|
+
|
|
242
|
+
if len(list_obs) > 0:
|
|
243
|
+
df_plot = adata.obs[list_obs].copy()
|
|
244
|
+
if log:
|
|
245
|
+
df_plot = pd.DataFrame(data=np.log1p(df_plot.values),
|
|
246
|
+
index=df_plot.index,
|
|
247
|
+
columns=df_plot.columns)
|
|
248
|
+
fig_nrow = int(np.ceil(len(list_obs)/fig_ncol))
|
|
249
|
+
fig = plt.figure(figsize=(fig_size[0]*fig_ncol*1.05,
|
|
250
|
+
fig_size[1]*fig_nrow))
|
|
251
|
+
for i, obs in enumerate(list_obs):
|
|
252
|
+
ax_i = fig.add_subplot(fig_nrow, fig_ncol, i+1)
|
|
253
|
+
sns.histplot(ax=ax_i,
|
|
254
|
+
x=obs,
|
|
255
|
+
data=df_plot,
|
|
256
|
+
kde=kde,
|
|
257
|
+
**kwargs)
|
|
258
|
+
ax_i.locator_params(axis='y', nbins=6)
|
|
259
|
+
ax_i.tick_params(axis="y", pad=-2)
|
|
260
|
+
ax_i.spines['right'].set_visible(False)
|
|
261
|
+
ax_i.spines['top'].set_visible(False)
|
|
262
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
263
|
+
if save_fig:
|
|
264
|
+
if not os.path.exists(fig_path):
|
|
265
|
+
os.makedirs(fig_path)
|
|
266
|
+
plt.savefig(os.path.join(fig_path, fig_name),
|
|
267
|
+
pad_inches=1,
|
|
268
|
+
bbox_inches='tight')
|
|
269
|
+
plt.close(fig)
|
|
270
|
+
if len(list_var) > 0:
|
|
271
|
+
df_plot = adata.var[list_var].copy()
|
|
272
|
+
if log:
|
|
273
|
+
df_plot = pd.DataFrame(data=np.log1p(df_plot.values),
|
|
274
|
+
index=df_plot.index,
|
|
275
|
+
columns=df_plot.columns)
|
|
276
|
+
fig_nrow = int(np.ceil(len(list_obs)/fig_ncol))
|
|
277
|
+
fig = plt.figure(figsize=(fig_size[0]*fig_ncol*1.05,
|
|
278
|
+
fig_size[1]*fig_nrow))
|
|
279
|
+
for i, var in enumerate(list_var):
|
|
280
|
+
ax_i = fig.add_subplot(fig_nrow, fig_ncol, i+1)
|
|
281
|
+
sns.histplot(ax=ax_i,
|
|
282
|
+
x=var,
|
|
283
|
+
data=df_plot,
|
|
284
|
+
kde=kde,
|
|
285
|
+
**kwargs)
|
|
286
|
+
ax_i.locator_params(axis='y', nbins=6)
|
|
287
|
+
ax_i.tick_params(axis="y", pad=-2)
|
|
288
|
+
ax_i.spines['right'].set_visible(False)
|
|
289
|
+
ax_i.spines['top'].set_visible(False)
|
|
290
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
291
|
+
if save_fig:
|
|
292
|
+
if not os.path.exists(fig_path):
|
|
293
|
+
os.makedirs(fig_path)
|
|
294
|
+
plt.savefig(os.path.join(fig_path, fig_name),
|
|
295
|
+
pad_inches=1,
|
|
296
|
+
bbox_inches='tight')
|
|
297
|
+
plt.close(fig)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def pca_variance_ratio(adata,
|
|
301
|
+
log=True,
|
|
302
|
+
show_cutoff=True,
|
|
303
|
+
fig_size=(4, 4),
|
|
304
|
+
save_fig=None,
|
|
305
|
+
fig_path=None,
|
|
306
|
+
fig_name='plot_variance_ratio.pdf',
|
|
307
|
+
pad=1.08,
|
|
308
|
+
w_pad=None,
|
|
309
|
+
h_pad=None,
|
|
310
|
+
**kwargs):
|
|
311
|
+
"""Plot the variance ratio.
|
|
312
|
+
|
|
313
|
+
Parameters
|
|
314
|
+
----------
|
|
315
|
+
adata : `Anndata`
|
|
316
|
+
Annotated data matrix.
|
|
317
|
+
log : `bool`, optional (default: True)
|
|
318
|
+
If True, variance_ratio will be log-transformed.
|
|
319
|
+
show_cutoff : `bool`, optional (default: True)
|
|
320
|
+
If True, cutoff on `n_pcs` will be shown
|
|
321
|
+
pad: `float`, optional (default: 1.08)
|
|
322
|
+
Padding between the figure edge and the edges of subplots,
|
|
323
|
+
as a fraction of the font size.
|
|
324
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
325
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
326
|
+
as a fraction of the font size. Defaults to pad.
|
|
327
|
+
fig_size: `tuple`, optional (default: (3,3))
|
|
328
|
+
figure size.
|
|
329
|
+
save_fig: `bool`, optional (default: False)
|
|
330
|
+
if True,save the figure.
|
|
331
|
+
fig_path: `str`, optional (default: None)
|
|
332
|
+
If save_fig is True, specify figure path.
|
|
333
|
+
fig_name: `str`, optional (default: 'plot_variance_ratio.pdf')
|
|
334
|
+
if `save_fig` is True, specify figure name.
|
|
335
|
+
**kwargs: `dict`, optional
|
|
336
|
+
Other keyword arguments are passed through to ``plt.plot``
|
|
337
|
+
|
|
338
|
+
Returns
|
|
339
|
+
-------
|
|
340
|
+
None
|
|
341
|
+
"""
|
|
342
|
+
if fig_size is None:
|
|
343
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
344
|
+
if save_fig is None:
|
|
345
|
+
save_fig = settings.save_fig
|
|
346
|
+
if fig_path is None:
|
|
347
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
348
|
+
|
|
349
|
+
n_components = len(adata.uns['pca']['variance_ratio'])
|
|
350
|
+
|
|
351
|
+
fig = plt.figure(figsize=fig_size)
|
|
352
|
+
if log:
|
|
353
|
+
plt.plot(range(n_components),
|
|
354
|
+
np.log(adata.uns['pca']['variance_ratio']),
|
|
355
|
+
**kwargs)
|
|
356
|
+
else:
|
|
357
|
+
plt.plot(range(n_components),
|
|
358
|
+
adata.uns['pca']['variance_ratio'],
|
|
359
|
+
**kwargs)
|
|
360
|
+
if show_cutoff:
|
|
361
|
+
n_pcs = adata.uns['pca']['n_pcs']
|
|
362
|
+
print(f'the number of selected PC is: {n_pcs}')
|
|
363
|
+
plt.axvline(n_pcs, ls='--', c='red')
|
|
364
|
+
plt.xlabel('Principal Component')
|
|
365
|
+
plt.ylabel('Variance Ratio')
|
|
366
|
+
plt.locator_params(axis='x', nbins=5)
|
|
367
|
+
plt.locator_params(axis='y', nbins=5)
|
|
368
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
369
|
+
if save_fig:
|
|
370
|
+
if not os.path.exists(fig_path):
|
|
371
|
+
os.makedirs(fig_path)
|
|
372
|
+
plt.savefig(os.path.join(fig_path, fig_name),
|
|
373
|
+
pad_inches=1,
|
|
374
|
+
bbox_inches='tight')
|
|
375
|
+
plt.close(fig)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def pcs_features(adata,
|
|
379
|
+
log=False,
|
|
380
|
+
size=3,
|
|
381
|
+
show_cutoff=True,
|
|
382
|
+
pad=1.08,
|
|
383
|
+
w_pad=None,
|
|
384
|
+
h_pad=None,
|
|
385
|
+
fig_size=(3, 3),
|
|
386
|
+
fig_ncol=3,
|
|
387
|
+
save_fig=None,
|
|
388
|
+
fig_path=None,
|
|
389
|
+
fig_name='plot_pcs_features.pdf',
|
|
390
|
+
**kwargs):
|
|
391
|
+
"""Plot features that contribute to the top PCs.
|
|
392
|
+
|
|
393
|
+
Parameters
|
|
394
|
+
----------
|
|
395
|
+
adata : `Anndata`
|
|
396
|
+
Annotated data matrix.
|
|
397
|
+
log : `bool`, optional (default: True)
|
|
398
|
+
If True, variance_ratio will be log-transformed.
|
|
399
|
+
show_cutoff : `bool`, optional (default: True)
|
|
400
|
+
If True, cutoff on `n_pcs` will be shown
|
|
401
|
+
size : `int`, optional (default: 3)
|
|
402
|
+
The marker size
|
|
403
|
+
pad: `float`, optional (default: 1.08)
|
|
404
|
+
Padding between the figure edge and the edges of subplots,
|
|
405
|
+
as a fraction of the font size.
|
|
406
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
407
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
408
|
+
as a fraction of the font size. Defaults to pad.
|
|
409
|
+
fig_size: `tuple`, optional (default: (3,3))
|
|
410
|
+
figure size.
|
|
411
|
+
fig_ncol: `int`, optional (default: 3)
|
|
412
|
+
the number of columns of the figure panel
|
|
413
|
+
save_fig: `bool`, optional (default: False)
|
|
414
|
+
if True,save the figure.
|
|
415
|
+
fig_path: `str`, optional (default: None)
|
|
416
|
+
If save_fig is True, specify figure path.
|
|
417
|
+
fig_name: `str`, optional (default: 'plot_pcs_features.pdf')
|
|
418
|
+
if `save_fig` is True, specify figure name.
|
|
419
|
+
**kwargs: `dict`, optional
|
|
420
|
+
Other keyword arguments are passed through to ``plt.scatter``
|
|
421
|
+
|
|
422
|
+
Returns
|
|
423
|
+
-------
|
|
424
|
+
None
|
|
425
|
+
"""
|
|
426
|
+
|
|
427
|
+
if fig_size is None:
|
|
428
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
429
|
+
if save_fig is None:
|
|
430
|
+
save_fig = settings.save_fig
|
|
431
|
+
if fig_path is None:
|
|
432
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
433
|
+
|
|
434
|
+
n_pcs = adata.uns['pca']['n_pcs']
|
|
435
|
+
n_features = adata.uns['pca']['PCs'].shape[0]
|
|
436
|
+
|
|
437
|
+
fig_nrow = int(np.ceil(n_pcs/fig_ncol))
|
|
438
|
+
fig = plt.figure(figsize=(fig_size[0]*fig_ncol*1.05, fig_size[1]*fig_nrow))
|
|
439
|
+
|
|
440
|
+
for i in range(n_pcs):
|
|
441
|
+
ax_i = fig.add_subplot(fig_nrow, fig_ncol, i+1)
|
|
442
|
+
if log:
|
|
443
|
+
ax_i.scatter(range(n_features),
|
|
444
|
+
np.log(np.sort(
|
|
445
|
+
np.abs(adata.uns['pca']['PCs'][:, i],))[::-1]),
|
|
446
|
+
s=size,
|
|
447
|
+
**kwargs)
|
|
448
|
+
else:
|
|
449
|
+
ax_i.scatter(range(n_features),
|
|
450
|
+
np.sort(
|
|
451
|
+
np.abs(adata.uns['pca']['PCs'][:, i],))[::-1],
|
|
452
|
+
s=size,
|
|
453
|
+
**kwargs)
|
|
454
|
+
n_ft_selected_i = len(adata.uns['pca']['features'][f'pc_{i}'])
|
|
455
|
+
if show_cutoff:
|
|
456
|
+
ax_i.axvline(n_ft_selected_i, ls='--', c='red')
|
|
457
|
+
ax_i.set_xlabel('Feautures')
|
|
458
|
+
ax_i.set_ylabel('Loadings')
|
|
459
|
+
ax_i.locator_params(axis='x', nbins=3)
|
|
460
|
+
ax_i.locator_params(axis='y', nbins=5)
|
|
461
|
+
ax_i.ticklabel_format(axis="x", style="sci", scilimits=(0, 0))
|
|
462
|
+
ax_i.set_title(f'PC {i}')
|
|
463
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
464
|
+
if save_fig:
|
|
465
|
+
if not os.path.exists(fig_path):
|
|
466
|
+
os.makedirs(fig_path)
|
|
467
|
+
plt.savefig(os.path.join(fig_path, fig_name),
|
|
468
|
+
pad_inches=1,
|
|
469
|
+
bbox_inches='tight')
|
|
470
|
+
plt.close(fig)
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def variable_genes(adata,
|
|
474
|
+
show_texts=False,
|
|
475
|
+
n_texts=10,
|
|
476
|
+
size=8,
|
|
477
|
+
text_size=10,
|
|
478
|
+
pad=1.08,
|
|
479
|
+
w_pad=None,
|
|
480
|
+
h_pad=None,
|
|
481
|
+
fig_size=(4, 4),
|
|
482
|
+
save_fig=None,
|
|
483
|
+
fig_path=None,
|
|
484
|
+
fig_name='plot_variable_genes.pdf',
|
|
485
|
+
**kwargs):
|
|
486
|
+
"""Plot highly variable genes.
|
|
487
|
+
|
|
488
|
+
Parameters
|
|
489
|
+
----------
|
|
490
|
+
adata : `Anndata`
|
|
491
|
+
Annotated data matrix.
|
|
492
|
+
show_texts : `bool`, optional (default: False)
|
|
493
|
+
If True, text annotation will be shown.
|
|
494
|
+
n_texts : `int`, optional (default: 10)
|
|
495
|
+
The number of texts to plot.
|
|
496
|
+
size : `int`, optional (default: 8)
|
|
497
|
+
The marker size
|
|
498
|
+
text_size : `int`, optional (default: 10)
|
|
499
|
+
The text size
|
|
500
|
+
pad: `float`, optional (default: 1.08)
|
|
501
|
+
Padding between the figure edge and the edges of subplots,
|
|
502
|
+
as a fraction of the font size.
|
|
503
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
504
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
505
|
+
as a fraction of the font size. Defaults to pad.
|
|
506
|
+
fig_size: `tuple`, optional (default: (3,3))
|
|
507
|
+
figure size.
|
|
508
|
+
save_fig: `bool`, optional (default: False)
|
|
509
|
+
if True,save the figure.
|
|
510
|
+
fig_path: `str`, optional (default: None)
|
|
511
|
+
If save_fig is True, specify figure path.
|
|
512
|
+
fig_name: `str`, optional (default: 'plot_variable_genes.pdf')
|
|
513
|
+
if `save_fig` is True, specify figure name.
|
|
514
|
+
**kwargs: `dict`, optional
|
|
515
|
+
Other keyword arguments are passed through to ``plt.scatter``
|
|
516
|
+
|
|
517
|
+
Returns
|
|
518
|
+
-------
|
|
519
|
+
None
|
|
520
|
+
"""
|
|
521
|
+
|
|
522
|
+
if fig_size is None:
|
|
523
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
524
|
+
if save_fig is None:
|
|
525
|
+
save_fig = settings.save_fig
|
|
526
|
+
if fig_path is None:
|
|
527
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
528
|
+
|
|
529
|
+
means = adata.var['means']
|
|
530
|
+
variances_norm = adata.var['variances_norm']
|
|
531
|
+
mask = adata.var['highly_variable']
|
|
532
|
+
genes = adata.var_names
|
|
533
|
+
|
|
534
|
+
fig, ax = plt.subplots(figsize=fig_size)
|
|
535
|
+
ax.scatter(means[~mask],
|
|
536
|
+
variances_norm[~mask],
|
|
537
|
+
s=size,
|
|
538
|
+
c='#1F2433',
|
|
539
|
+
**kwargs)
|
|
540
|
+
ax.scatter(means[mask],
|
|
541
|
+
variances_norm[mask],
|
|
542
|
+
s=size,
|
|
543
|
+
c='#ce3746',
|
|
544
|
+
**kwargs)
|
|
545
|
+
ax.set_xscale(value='log')
|
|
546
|
+
|
|
547
|
+
if show_texts:
|
|
548
|
+
ids = variances_norm.values.argsort()[-n_texts:][::-1]
|
|
549
|
+
texts = [plt.text(means.iloc[i], variances_norm.iloc[i], genes[i],
|
|
550
|
+
fontdict={'family': 'serif',
|
|
551
|
+
'color': 'black',
|
|
552
|
+
'weight': 'normal',
|
|
553
|
+
'size': text_size})
|
|
554
|
+
for i in ids]
|
|
555
|
+
adjust_text(texts,
|
|
556
|
+
arrowprops=dict(arrowstyle='-', color='black'))
|
|
557
|
+
|
|
558
|
+
ax.set_xlabel('average expression')
|
|
559
|
+
ax.set_ylabel('standardized variance')
|
|
560
|
+
ax.locator_params(axis='x', tight=True)
|
|
561
|
+
ax.locator_params(axis='y', tight=True)
|
|
562
|
+
ax.spines['right'].set_visible(False)
|
|
563
|
+
ax.spines['top'].set_visible(False)
|
|
564
|
+
fig.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
565
|
+
if save_fig:
|
|
566
|
+
if not os.path.exists(fig_path):
|
|
567
|
+
os.makedirs(fig_path)
|
|
568
|
+
fig.savefig(os.path.join(fig_path, fig_name),
|
|
569
|
+
pad_inches=1,
|
|
570
|
+
bbox_inches='tight')
|
|
571
|
+
plt.close(fig)
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def _scatterplot2d(df,
|
|
575
|
+
x,
|
|
576
|
+
y,
|
|
577
|
+
list_hue=None,
|
|
578
|
+
hue_palette=None,
|
|
579
|
+
drawing_order='sorted',
|
|
580
|
+
dict_drawing_order=None,
|
|
581
|
+
size=8,
|
|
582
|
+
show_texts=False,
|
|
583
|
+
texts=None,
|
|
584
|
+
text_size=10,
|
|
585
|
+
text_expand=(1.05, 1.2),
|
|
586
|
+
fig_size=None,
|
|
587
|
+
fig_ncol=3,
|
|
588
|
+
fig_legend_ncol=1,
|
|
589
|
+
fig_legend_order=None,
|
|
590
|
+
vmin=None,
|
|
591
|
+
vmax=None,
|
|
592
|
+
alpha=0.8,
|
|
593
|
+
pad=1.08,
|
|
594
|
+
w_pad=None,
|
|
595
|
+
h_pad=None,
|
|
596
|
+
save_fig=None,
|
|
597
|
+
fig_path=None,
|
|
598
|
+
fig_name='scatterplot2d.pdf',
|
|
599
|
+
copy=False,
|
|
600
|
+
**kwargs):
|
|
601
|
+
"""2d scatter plot
|
|
602
|
+
|
|
603
|
+
Parameters
|
|
604
|
+
----------
|
|
605
|
+
data: `pd.DataFrame`
|
|
606
|
+
Input data structure of shape (n_samples, n_features).
|
|
607
|
+
x: `str`
|
|
608
|
+
Variable in `data` that specify positions on the x axis.
|
|
609
|
+
y: `str`
|
|
610
|
+
Variable in `data` that specify positions on the x axis.
|
|
611
|
+
list_hue: `str`, optional (default: None)
|
|
612
|
+
A list of variables that will produce points with different colors.
|
|
613
|
+
drawing_order: `str` (default: 'sorted')
|
|
614
|
+
The order in which values are plotted, This can be
|
|
615
|
+
one of the following values
|
|
616
|
+
- 'original': plot points in the same order as in input dataframe
|
|
617
|
+
- 'sorted' : plot points with higher values on top.
|
|
618
|
+
- 'random' : plot points in a random order
|
|
619
|
+
fig_size: `tuple`, optional (default: None)
|
|
620
|
+
figure size.
|
|
621
|
+
fig_ncol: `int`, optional (default: 3)
|
|
622
|
+
the number of columns of the figure panel
|
|
623
|
+
fig_legend_order: `dict`,optional (default: None)
|
|
624
|
+
Specified order for the appearance of the annotation keys.
|
|
625
|
+
Only valid for categorical/string variable
|
|
626
|
+
e.g. fig_legend_order = {'ann1':['a','b','c'],'ann2':['aa','bb','cc']}
|
|
627
|
+
fig_legend_ncol: `int`, optional (default: 1)
|
|
628
|
+
The number of columns that the legend has.
|
|
629
|
+
vmin,vmax: `float`, optional (default: None)
|
|
630
|
+
The min and max values are used to normalize continuous values.
|
|
631
|
+
If None, the respective min and max of continuous values is used.
|
|
632
|
+
alpha: `float`, optional (default: 0.8)
|
|
633
|
+
0.0 transparent through 1.0 opaque
|
|
634
|
+
pad: `float`, optional (default: 1.08)
|
|
635
|
+
Padding between the figure edge and the edges of subplots,
|
|
636
|
+
as a fraction of the font size.
|
|
637
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
638
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
639
|
+
as a fraction of the font size. Defaults to pad.
|
|
640
|
+
save_fig: `bool`, optional (default: False)
|
|
641
|
+
if True,save the figure.
|
|
642
|
+
fig_path: `str`, optional (default: None)
|
|
643
|
+
If save_fig is True, specify figure path.
|
|
644
|
+
fig_name: `str`, optional (default: 'scatterplot2d.pdf')
|
|
645
|
+
if save_fig is True, specify figure name.
|
|
646
|
+
Returns
|
|
647
|
+
-------
|
|
648
|
+
None
|
|
649
|
+
"""
|
|
650
|
+
|
|
651
|
+
if fig_size is None:
|
|
652
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
653
|
+
if save_fig is None:
|
|
654
|
+
save_fig = settings.save_fig
|
|
655
|
+
if fig_path is None:
|
|
656
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
657
|
+
|
|
658
|
+
list_ax = list()
|
|
659
|
+
if list_hue is None:
|
|
660
|
+
list_hue = [None]
|
|
661
|
+
else:
|
|
662
|
+
for hue in list_hue:
|
|
663
|
+
if hue not in df.columns:
|
|
664
|
+
raise ValueError(f"could not find {hue}")
|
|
665
|
+
if hue_palette is None:
|
|
666
|
+
hue_palette = dict()
|
|
667
|
+
assert isinstance(hue_palette, dict), "`hue_palette` must be dict"
|
|
668
|
+
legend_order = {hue: np.unique(df[hue]) for hue in list_hue
|
|
669
|
+
if (is_string_dtype(df[hue])
|
|
670
|
+
or is_categorical_dtype(df[hue]))}
|
|
671
|
+
if fig_legend_order is not None:
|
|
672
|
+
if not isinstance(fig_legend_order, dict):
|
|
673
|
+
raise TypeError("`fig_legend_order` must be a dictionary")
|
|
674
|
+
for hue in fig_legend_order.keys():
|
|
675
|
+
if hue in legend_order.keys():
|
|
676
|
+
legend_order[hue] = fig_legend_order[hue]
|
|
677
|
+
else:
|
|
678
|
+
print(f"{hue} is ignored for ordering legend labels"
|
|
679
|
+
"due to incorrect name or data type")
|
|
680
|
+
|
|
681
|
+
if dict_drawing_order is None:
|
|
682
|
+
dict_drawing_order = dict()
|
|
683
|
+
assert drawing_order in ['sorted', 'random', 'original'],\
|
|
684
|
+
"`drawing_order` must be one of ['original', 'sorted', 'random']"
|
|
685
|
+
|
|
686
|
+
if len(list_hue) < fig_ncol:
|
|
687
|
+
fig_ncol = len(list_hue)
|
|
688
|
+
fig_nrow = int(np.ceil(len(list_hue)/fig_ncol))
|
|
689
|
+
fig = plt.figure(figsize=(fig_size[0]*fig_ncol*1.05, fig_size[1]*fig_nrow))
|
|
690
|
+
for i, hue in enumerate(list_hue):
|
|
691
|
+
ax_i = fig.add_subplot(fig_nrow, fig_ncol, i+1)
|
|
692
|
+
if hue is None:
|
|
693
|
+
sc_i = sns.scatterplot(ax=ax_i,
|
|
694
|
+
x=x,
|
|
695
|
+
y=y,
|
|
696
|
+
data=df,
|
|
697
|
+
alpha=alpha,
|
|
698
|
+
linewidth=0,
|
|
699
|
+
s=size,
|
|
700
|
+
**kwargs)
|
|
701
|
+
else:
|
|
702
|
+
if is_string_dtype(df[hue]) or is_categorical_dtype(df[hue]):
|
|
703
|
+
if hue in hue_palette.keys():
|
|
704
|
+
palette = hue_palette[hue]
|
|
705
|
+
else:
|
|
706
|
+
palette = None
|
|
707
|
+
if hue in dict_drawing_order.keys():
|
|
708
|
+
param_drawing_order = dict_drawing_order[hue]
|
|
709
|
+
else:
|
|
710
|
+
param_drawing_order = drawing_order
|
|
711
|
+
if param_drawing_order == 'sorted':
|
|
712
|
+
df_updated = df.sort_values(by=hue)
|
|
713
|
+
elif param_drawing_order == 'random':
|
|
714
|
+
df_updated = df.sample(frac=1, random_state=100)
|
|
715
|
+
else:
|
|
716
|
+
df_updated = df
|
|
717
|
+
sc_i = sns.scatterplot(ax=ax_i,
|
|
718
|
+
x=x,
|
|
719
|
+
y=y,
|
|
720
|
+
hue=hue,
|
|
721
|
+
hue_order=legend_order[hue],
|
|
722
|
+
data=df_updated,
|
|
723
|
+
alpha=alpha,
|
|
724
|
+
linewidth=0,
|
|
725
|
+
palette=palette,
|
|
726
|
+
s=size,
|
|
727
|
+
**kwargs)
|
|
728
|
+
ax_i.legend(bbox_to_anchor=(1, 0.5),
|
|
729
|
+
loc='center left',
|
|
730
|
+
ncol=fig_legend_ncol,
|
|
731
|
+
frameon=False,
|
|
732
|
+
)
|
|
733
|
+
else:
|
|
734
|
+
vmin_i = df[hue].min() if vmin is None else vmin
|
|
735
|
+
vmax_i = df[hue].max() if vmax is None else vmax
|
|
736
|
+
if hue in dict_drawing_order.keys():
|
|
737
|
+
param_drawing_order = dict_drawing_order[hue]
|
|
738
|
+
else:
|
|
739
|
+
param_drawing_order = drawing_order
|
|
740
|
+
if param_drawing_order == 'sorted':
|
|
741
|
+
df_updated = df.sort_values(by=hue)
|
|
742
|
+
elif param_drawing_order == 'random':
|
|
743
|
+
df_updated = df.sample(frac=1, random_state=100)
|
|
744
|
+
else:
|
|
745
|
+
df_updated = df
|
|
746
|
+
sc_i = ax_i.scatter(df_updated[x],
|
|
747
|
+
df_updated[y],
|
|
748
|
+
c=df_updated[hue],
|
|
749
|
+
vmin=vmin_i,
|
|
750
|
+
vmax=vmax_i,
|
|
751
|
+
alpha=alpha,
|
|
752
|
+
s=size,
|
|
753
|
+
**kwargs)
|
|
754
|
+
cbar = plt.colorbar(sc_i,
|
|
755
|
+
ax=ax_i,
|
|
756
|
+
pad=0.01,
|
|
757
|
+
fraction=0.05,
|
|
758
|
+
aspect=40)
|
|
759
|
+
cbar.solids.set_edgecolor("face")
|
|
760
|
+
cbar.ax.locator_params(nbins=5)
|
|
761
|
+
if show_texts:
|
|
762
|
+
if texts is not None:
|
|
763
|
+
plt_texts = [plt.text(df[x][t],
|
|
764
|
+
df[y][t],
|
|
765
|
+
t,
|
|
766
|
+
fontdict={'family': 'serif',
|
|
767
|
+
'color': 'black',
|
|
768
|
+
'weight': 'normal',
|
|
769
|
+
'size': text_size})
|
|
770
|
+
for t in texts]
|
|
771
|
+
adjust_text(plt_texts,
|
|
772
|
+
expand_text=text_expand,
|
|
773
|
+
expand_points=text_expand,
|
|
774
|
+
expand_objects=text_expand,
|
|
775
|
+
arrowprops=dict(arrowstyle='->', color='black'))
|
|
776
|
+
ax_i.set_xlabel(x)
|
|
777
|
+
ax_i.set_ylabel(y)
|
|
778
|
+
ax_i.locator_params(axis='x', nbins=5)
|
|
779
|
+
ax_i.locator_params(axis='y', nbins=5)
|
|
780
|
+
ax_i.tick_params(axis="both", labelbottom=True, labelleft=True)
|
|
781
|
+
ax_i.set_title(hue)
|
|
782
|
+
list_ax.append(ax_i)
|
|
783
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
784
|
+
if save_fig:
|
|
785
|
+
if not os.path.exists(fig_path):
|
|
786
|
+
os.makedirs(fig_path)
|
|
787
|
+
plt.savefig(os.path.join(fig_path, fig_name),
|
|
788
|
+
pad_inches=1,
|
|
789
|
+
bbox_inches='tight')
|
|
790
|
+
plt.close(fig)
|
|
791
|
+
if copy:
|
|
792
|
+
return list_ax
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
def _scatterplot2d_plotly(df,
|
|
796
|
+
x,
|
|
797
|
+
y,
|
|
798
|
+
list_hue=None,
|
|
799
|
+
hue_palette=None,
|
|
800
|
+
drawing_order='sorted',
|
|
801
|
+
fig_size=None,
|
|
802
|
+
fig_ncol=3,
|
|
803
|
+
fig_legend_order=None,
|
|
804
|
+
alpha=0.8,
|
|
805
|
+
save_fig=None,
|
|
806
|
+
fig_path=None,
|
|
807
|
+
**kwargs):
|
|
808
|
+
"""interactive 2d scatter plot by Plotly
|
|
809
|
+
|
|
810
|
+
Parameters
|
|
811
|
+
----------
|
|
812
|
+
data: `pd.DataFrame`
|
|
813
|
+
Input data structure of shape (n_samples, n_features).
|
|
814
|
+
x: `str`
|
|
815
|
+
Variable in `data` that specify positions on the x axis.
|
|
816
|
+
y: `str`
|
|
817
|
+
Variable in `data` that specify positions on the x axis.
|
|
818
|
+
list_hue: `str`, optional (default: None)
|
|
819
|
+
A list of variables that will produce points with different colors.
|
|
820
|
+
drawing_order: `str` (default: 'sorted')
|
|
821
|
+
The order in which values are plotted, This can be
|
|
822
|
+
one of the following values
|
|
823
|
+
- 'original': plot points in the same order as in input dataframe
|
|
824
|
+
- 'sorted' : plot points with higher values on top.
|
|
825
|
+
- 'random' : plot points in a random order
|
|
826
|
+
fig_size: `tuple`, optional (default: None)
|
|
827
|
+
figure size.
|
|
828
|
+
fig_ncol: `int`, optional (default: 3)
|
|
829
|
+
the number of columns of the figure panel
|
|
830
|
+
fig_legend_order: `dict`,optional (default: None)
|
|
831
|
+
Specified order for the appearance of the annotation keys.
|
|
832
|
+
Only valid for categorical/string variable
|
|
833
|
+
e.g. fig_legend_order = {'ann1':['a','b','c'],
|
|
834
|
+
'ann2':['aa','bb','cc']}
|
|
835
|
+
fig_legend_ncol: `int`, optional (default: 1)
|
|
836
|
+
The number of columns that the legend has.
|
|
837
|
+
vmin,vmax: `float`, optional (default: None)
|
|
838
|
+
The min and max values are used to normalize continuous values.
|
|
839
|
+
If None, the respective min and max of continuous values is used.
|
|
840
|
+
alpha: `float`, optional (default: 0.8)
|
|
841
|
+
0.0 transparent through 1.0 opaque
|
|
842
|
+
pad: `float`, optional (default: 1.08)
|
|
843
|
+
Padding between the figure edge and the edges of subplots,
|
|
844
|
+
as a fraction of the font size.
|
|
845
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
846
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
847
|
+
as a fraction of the font size. Defaults to pad.
|
|
848
|
+
save_fig: `bool`, optional (default: False)
|
|
849
|
+
if True,save the figure.
|
|
850
|
+
fig_path: `str`, optional (default: None)
|
|
851
|
+
If save_fig is True, specify figure path.
|
|
852
|
+
fig_name: `str`, optional (default: 'scatterplot2d.pdf')
|
|
853
|
+
if save_fig is True, specify figure name.
|
|
854
|
+
Returns
|
|
855
|
+
-------
|
|
856
|
+
None
|
|
857
|
+
"""
|
|
858
|
+
|
|
859
|
+
if fig_size is None:
|
|
860
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
861
|
+
if save_fig is None:
|
|
862
|
+
save_fig = settings.save_fig
|
|
863
|
+
if fig_path is None:
|
|
864
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
865
|
+
|
|
866
|
+
for hue in list_hue:
|
|
867
|
+
if(hue not in df.columns):
|
|
868
|
+
raise ValueError(f"could not find {hue} in `df.columns`")
|
|
869
|
+
if hue_palette is None:
|
|
870
|
+
hue_palette = dict()
|
|
871
|
+
assert isinstance(hue_palette, dict), "`hue_palette` must be dict"
|
|
872
|
+
|
|
873
|
+
assert drawing_order in ['sorted', 'random', 'original'],\
|
|
874
|
+
"`drawing_order` must be one of ['original', 'sorted', 'random']"
|
|
875
|
+
|
|
876
|
+
legend_order = {hue: np.unique(df[hue]) for hue in list_hue
|
|
877
|
+
if (is_string_dtype(df[hue])
|
|
878
|
+
or is_categorical_dtype(df[hue]))}
|
|
879
|
+
if(fig_legend_order is not None):
|
|
880
|
+
if(not isinstance(fig_legend_order, dict)):
|
|
881
|
+
raise TypeError("`fig_legend_order` must be a dictionary")
|
|
882
|
+
for hue in fig_legend_order.keys():
|
|
883
|
+
if(hue in legend_order.keys()):
|
|
884
|
+
legend_order[hue] = fig_legend_order[hue]
|
|
885
|
+
else:
|
|
886
|
+
print(f"{hue} is ignored for ordering legend labels"
|
|
887
|
+
"due to incorrect name or data type")
|
|
888
|
+
|
|
889
|
+
if(len(list_hue) < fig_ncol):
|
|
890
|
+
fig_ncol = len(list_hue)
|
|
891
|
+
fig_nrow = int(np.ceil(len(list_hue)/fig_ncol))
|
|
892
|
+
fig = plt.figure(figsize=(fig_size[0]*fig_ncol*1.05,
|
|
893
|
+
fig_size[1]*fig_nrow))
|
|
894
|
+
for hue in list_hue:
|
|
895
|
+
if hue in hue_palette.keys():
|
|
896
|
+
palette = hue_palette[hue]
|
|
897
|
+
else:
|
|
898
|
+
palette = None
|
|
899
|
+
if drawing_order == 'sorted':
|
|
900
|
+
df_updated = df.sort_values(by=hue)
|
|
901
|
+
elif drawing_order == 'random':
|
|
902
|
+
df_updated = df.sample(frac=1, random_state=100)
|
|
903
|
+
else:
|
|
904
|
+
df_updated = df
|
|
905
|
+
|
|
906
|
+
fig = px.scatter(df_updated,
|
|
907
|
+
x=x,
|
|
908
|
+
y=y,
|
|
909
|
+
color=hue,
|
|
910
|
+
opacity=alpha,
|
|
911
|
+
color_continuous_scale=px.colors.sequential.Viridis,
|
|
912
|
+
color_discrete_map=palette,
|
|
913
|
+
template = 'plotly_white',
|
|
914
|
+
**kwargs)
|
|
915
|
+
fig.update_layout(legend={'itemsizing': 'constant'},
|
|
916
|
+
width=fig_size[0]*100,
|
|
917
|
+
height=fig_size[1]*100,
|
|
918
|
+
)
|
|
919
|
+
fig.update_xaxes(mirror = True,
|
|
920
|
+
ticks = 'outside',
|
|
921
|
+
showline = True,
|
|
922
|
+
linecolor = 'black')
|
|
923
|
+
fig.update_yaxes(mirror = True,
|
|
924
|
+
ticks = 'outside',
|
|
925
|
+
showline = True,
|
|
926
|
+
linecolor = 'black')
|
|
927
|
+
|
|
928
|
+
fig.show(renderer="notebook")
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
# TO-DO add 3D plot
|
|
932
|
+
def umap(adata,
|
|
933
|
+
color=None,
|
|
934
|
+
dict_palette=None,
|
|
935
|
+
n_components=None,
|
|
936
|
+
size=8,
|
|
937
|
+
drawing_order='sorted',
|
|
938
|
+
dict_drawing_order=None,
|
|
939
|
+
show_texts=False,
|
|
940
|
+
texts=None,
|
|
941
|
+
text_size=10,
|
|
942
|
+
text_expand=(1.05, 1.2),
|
|
943
|
+
fig_size=None,
|
|
944
|
+
fig_ncol=3,
|
|
945
|
+
fig_legend_ncol=1,
|
|
946
|
+
fig_legend_order=None,
|
|
947
|
+
vmin=None,
|
|
948
|
+
vmax=None,
|
|
949
|
+
alpha=1,
|
|
950
|
+
pad=1.08,
|
|
951
|
+
w_pad=None,
|
|
952
|
+
h_pad=None,
|
|
953
|
+
save_fig=None,
|
|
954
|
+
fig_path=None,
|
|
955
|
+
fig_name='plot_umap.pdf',
|
|
956
|
+
plotly=False,
|
|
957
|
+
**kwargs):
|
|
958
|
+
""" Plot coordinates in UMAP
|
|
959
|
+
|
|
960
|
+
Parameters
|
|
961
|
+
----------
|
|
962
|
+
data: `pd.DataFrame`
|
|
963
|
+
Input data structure of shape (n_samples, n_features).
|
|
964
|
+
x: `str`
|
|
965
|
+
Variable in `data` that specify positions on the x axis.
|
|
966
|
+
y: `str`
|
|
967
|
+
Variable in `data` that specify positions on the x axis.
|
|
968
|
+
color: `list`, optional (default: None)
|
|
969
|
+
A list of variables that will produce points with different colors.
|
|
970
|
+
e.g. color = ['anno1', 'anno2']
|
|
971
|
+
dict_palette: `dict`,optional (default: None)
|
|
972
|
+
A dictionary of palettes for different variables in `color`.
|
|
973
|
+
Only valid for categorical/string variables
|
|
974
|
+
e.g. dict_palette = {'ann1': {},'ann2': {}}
|
|
975
|
+
drawing_order: `str` (default: 'sorted')
|
|
976
|
+
The order in which values are plotted, This can be
|
|
977
|
+
one of the following values
|
|
978
|
+
- 'original': plot points in the same order as in input dataframe
|
|
979
|
+
- 'sorted' : plot points with higher values on top.
|
|
980
|
+
- 'random' : plot points in a random order
|
|
981
|
+
dict_drawing_order: `dict`,optional (default: None)
|
|
982
|
+
A dictionary of drawing_order for different variables in `color`.
|
|
983
|
+
Only valid for categorical/string variables
|
|
984
|
+
e.g. dict_drawing_order = {'ann1': 'original','ann2': 'sorted'}
|
|
985
|
+
size: `int` (default: 8)
|
|
986
|
+
Point size.
|
|
987
|
+
show_texts : `bool`, optional (default: False)
|
|
988
|
+
If True, text annotation will be shown.
|
|
989
|
+
text_size : `int`, optional (default: 10)
|
|
990
|
+
The text size.
|
|
991
|
+
texts: `list` optional (default: None)
|
|
992
|
+
Point names to plot.
|
|
993
|
+
text_expand : `tuple`, optional (default: (1.05, 1.2))
|
|
994
|
+
Two multipliers (x, y) by which to expand the bounding box of texts
|
|
995
|
+
when repelling them from each other/points/other objects.
|
|
996
|
+
fig_size: `tuple`, optional (default: None)
|
|
997
|
+
figure size.
|
|
998
|
+
fig_ncol: `int`, optional (default: 3)
|
|
999
|
+
the number of columns of the figure panel
|
|
1000
|
+
fig_legend_order: `dict`,optional (default: None)
|
|
1001
|
+
Specified order for the appearance of the annotation keys.
|
|
1002
|
+
Only valid for categorical/string variable
|
|
1003
|
+
e.g. fig_legend_order = {'ann1':['a','b','c'],'ann2':['aa','bb','cc']}
|
|
1004
|
+
fig_legend_ncol: `int`, optional (default: 1)
|
|
1005
|
+
The number of columns that the legend has.
|
|
1006
|
+
vmin,vmax: `float`, optional (default: None)
|
|
1007
|
+
The min and max values are used to normalize continuous values.
|
|
1008
|
+
If None, the respective min and max of continuous values is used.
|
|
1009
|
+
alpha: `float`, optional (default: 0.8)
|
|
1010
|
+
0.0 transparent through 1.0 opaque
|
|
1011
|
+
pad: `float`, optional (default: 1.08)
|
|
1012
|
+
Padding between the figure edge and the edges of subplots,
|
|
1013
|
+
as a fraction of the font size.
|
|
1014
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
1015
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
1016
|
+
as a fraction of the font size. Defaults to pad.
|
|
1017
|
+
save_fig: `bool`, optional (default: False)
|
|
1018
|
+
if True,save the figure.
|
|
1019
|
+
fig_path: `str`, optional (default: None)
|
|
1020
|
+
If save_fig is True, specify figure path.
|
|
1021
|
+
fig_name: `str`, optional (default: 'plot_umap.pdf')
|
|
1022
|
+
if save_fig is True, specify figure name.
|
|
1023
|
+
Returns
|
|
1024
|
+
-------
|
|
1025
|
+
None
|
|
1026
|
+
"""
|
|
1027
|
+
|
|
1028
|
+
if fig_size is None:
|
|
1029
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
1030
|
+
if save_fig is None:
|
|
1031
|
+
save_fig = settings.save_fig
|
|
1032
|
+
if fig_path is None:
|
|
1033
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
1034
|
+
|
|
1035
|
+
if n_components is None:
|
|
1036
|
+
n_components = min(3, adata.obsm['X_umap'].shape[1])
|
|
1037
|
+
if n_components not in [2, 3]:
|
|
1038
|
+
raise ValueError("n_components should be 2 or 3")
|
|
1039
|
+
if n_components > adata.obsm['X_umap'].shape[1]:
|
|
1040
|
+
print(f"`n_components` is greater than the available dimension.\n"
|
|
1041
|
+
f"It is corrected to {adata.obsm['X_umap'].shape[1]}")
|
|
1042
|
+
n_components = adata.obsm['X_umap'].shape[1]
|
|
1043
|
+
|
|
1044
|
+
if dict_palette is None:
|
|
1045
|
+
dict_palette = dict()
|
|
1046
|
+
df_plot = pd.DataFrame(index=adata.obs.index,
|
|
1047
|
+
data=adata.obsm['X_umap'],
|
|
1048
|
+
columns=['UMAP'+str(x+1) for x in
|
|
1049
|
+
range(adata.obsm['X_umap'].shape[1])])
|
|
1050
|
+
if color is None:
|
|
1051
|
+
_scatterplot2d(df_plot,
|
|
1052
|
+
x='UMAP1',
|
|
1053
|
+
y='UMAP2',
|
|
1054
|
+
drawing_order=drawing_order,
|
|
1055
|
+
size=size,
|
|
1056
|
+
show_texts=show_texts,
|
|
1057
|
+
text_size=text_size,
|
|
1058
|
+
texts=texts,
|
|
1059
|
+
text_expand=text_expand,
|
|
1060
|
+
fig_size=fig_size,
|
|
1061
|
+
alpha=alpha,
|
|
1062
|
+
pad=pad,
|
|
1063
|
+
w_pad=w_pad,
|
|
1064
|
+
h_pad=h_pad,
|
|
1065
|
+
save_fig=save_fig,
|
|
1066
|
+
fig_path=fig_path,
|
|
1067
|
+
fig_name=fig_name,
|
|
1068
|
+
**kwargs)
|
|
1069
|
+
else:
|
|
1070
|
+
color = list(dict.fromkeys(color)) # remove duplicate keys
|
|
1071
|
+
for ann in color:
|
|
1072
|
+
if ann in adata.obs_keys():
|
|
1073
|
+
df_plot[ann] = adata.obs[ann]
|
|
1074
|
+
if not is_numeric_dtype(df_plot[ann]):
|
|
1075
|
+
if 'color' not in adata.uns_keys():
|
|
1076
|
+
adata.uns['color'] = dict()
|
|
1077
|
+
|
|
1078
|
+
if ann not in dict_palette.keys():
|
|
1079
|
+
if (ann+'_color' in adata.uns['color'].keys()) \
|
|
1080
|
+
and \
|
|
1081
|
+
(all(np.isin(np.unique(df_plot[ann]),
|
|
1082
|
+
list(adata.uns['color']
|
|
1083
|
+
[ann+'_color'].keys())))):
|
|
1084
|
+
dict_palette[ann] = \
|
|
1085
|
+
adata.uns['color'][ann+'_color']
|
|
1086
|
+
else:
|
|
1087
|
+
dict_palette[ann] = \
|
|
1088
|
+
generate_palette(adata.obs[ann])
|
|
1089
|
+
adata.uns['color'][ann+'_color'] = \
|
|
1090
|
+
dict_palette[ann].copy()
|
|
1091
|
+
else:
|
|
1092
|
+
if ann+'_color' not in adata.uns['color'].keys():
|
|
1093
|
+
adata.uns['color'][ann+'_color'] = \
|
|
1094
|
+
dict_palette[ann].copy()
|
|
1095
|
+
|
|
1096
|
+
elif ann in adata.var_names:
|
|
1097
|
+
df_plot[ann] = adata.obs_vector(ann)
|
|
1098
|
+
else:
|
|
1099
|
+
raise ValueError(f"could not find {ann} in `adata.obs.columns`"
|
|
1100
|
+
" and `adata.var_names`")
|
|
1101
|
+
if plotly:
|
|
1102
|
+
_scatterplot2d_plotly(df_plot,
|
|
1103
|
+
x='UMAP1',
|
|
1104
|
+
y='UMAP2',
|
|
1105
|
+
list_hue=color,
|
|
1106
|
+
hue_palette=dict_palette,
|
|
1107
|
+
drawing_order=drawing_order,
|
|
1108
|
+
fig_size=fig_size,
|
|
1109
|
+
fig_ncol=fig_ncol,
|
|
1110
|
+
fig_legend_order=fig_legend_order,
|
|
1111
|
+
alpha=alpha,
|
|
1112
|
+
save_fig=save_fig,
|
|
1113
|
+
fig_path=fig_path,
|
|
1114
|
+
**kwargs)
|
|
1115
|
+
else:
|
|
1116
|
+
_scatterplot2d(df_plot,
|
|
1117
|
+
x='UMAP1',
|
|
1118
|
+
y='UMAP2',
|
|
1119
|
+
list_hue=color,
|
|
1120
|
+
hue_palette=dict_palette,
|
|
1121
|
+
drawing_order=drawing_order,
|
|
1122
|
+
dict_drawing_order=dict_drawing_order,
|
|
1123
|
+
size=size,
|
|
1124
|
+
show_texts=show_texts,
|
|
1125
|
+
text_size=text_size,
|
|
1126
|
+
text_expand=text_expand,
|
|
1127
|
+
texts=texts,
|
|
1128
|
+
fig_size=fig_size,
|
|
1129
|
+
fig_ncol=fig_ncol,
|
|
1130
|
+
fig_legend_ncol=fig_legend_ncol,
|
|
1131
|
+
fig_legend_order=fig_legend_order,
|
|
1132
|
+
vmin=vmin,
|
|
1133
|
+
vmax=vmax,
|
|
1134
|
+
alpha=alpha,
|
|
1135
|
+
pad=pad,
|
|
1136
|
+
w_pad=w_pad,
|
|
1137
|
+
h_pad=h_pad,
|
|
1138
|
+
save_fig=save_fig,
|
|
1139
|
+
fig_path=fig_path,
|
|
1140
|
+
fig_name=fig_name,
|
|
1141
|
+
**kwargs)
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
def discretize(adata,
|
|
1145
|
+
kde=None,
|
|
1146
|
+
fig_size=(6, 6),
|
|
1147
|
+
pad=1.08,
|
|
1148
|
+
w_pad=None,
|
|
1149
|
+
h_pad=None,
|
|
1150
|
+
save_fig=None,
|
|
1151
|
+
fig_path=None,
|
|
1152
|
+
fig_name='plot_discretize.pdf',
|
|
1153
|
+
**kwargs):
|
|
1154
|
+
"""Plot original data VS discretized data
|
|
1155
|
+
|
|
1156
|
+
Parameters
|
|
1157
|
+
----------
|
|
1158
|
+
adata : `Anndata`
|
|
1159
|
+
Annotated data matrix.
|
|
1160
|
+
kde : `bool`, optional (default: None)
|
|
1161
|
+
If True, compute a kernel density estimate to smooth the distribution
|
|
1162
|
+
and show on the plot. Invalid as of v0.2.
|
|
1163
|
+
pad: `float`, optional (default: 1.08)
|
|
1164
|
+
Padding between the figure edge and the edges of subplots,
|
|
1165
|
+
as a fraction of the font size.
|
|
1166
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
1167
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
1168
|
+
as a fraction of the font size. Defaults to pad.
|
|
1169
|
+
fig_size: `tuple`, optional (default: (5,8))
|
|
1170
|
+
figure size.
|
|
1171
|
+
save_fig: `bool`, optional (default: False)
|
|
1172
|
+
if True,save the figure.
|
|
1173
|
+
fig_path: `str`, optional (default: None)
|
|
1174
|
+
If save_fig is True, specify figure path.
|
|
1175
|
+
fig_name: `str`, optional (default: 'plot_discretize.pdf')
|
|
1176
|
+
if `save_fig` is True, specify figure name.
|
|
1177
|
+
**kwargs: `dict`, optional
|
|
1178
|
+
Other keyword arguments are passed through to ``plt.hist()``
|
|
1179
|
+
|
|
1180
|
+
Returns
|
|
1181
|
+
-------
|
|
1182
|
+
None
|
|
1183
|
+
"""
|
|
1184
|
+
if kde is not None:
|
|
1185
|
+
warnings.warn("kde is not supported as of v0.2", DeprecationWarning)
|
|
1186
|
+
if fig_size is None:
|
|
1187
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
1188
|
+
if save_fig is None:
|
|
1189
|
+
save_fig = settings.save_fig
|
|
1190
|
+
if fig_path is None:
|
|
1191
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
1192
|
+
|
|
1193
|
+
assert 'disc' in adata.uns_keys(), \
|
|
1194
|
+
"please run `si.tl.discretize()` first"
|
|
1195
|
+
if kde is not None:
|
|
1196
|
+
warnings.warn("kde is no longer supported as of v1.1",
|
|
1197
|
+
DeprecationWarning)
|
|
1198
|
+
|
|
1199
|
+
hist_edges = adata.uns['disc']['hist_edges']
|
|
1200
|
+
hist_count = adata.uns['disc']['hist_count']
|
|
1201
|
+
bin_edges = adata.uns['disc']['bin_edges']
|
|
1202
|
+
bin_count = adata.uns['disc']['bin_count']
|
|
1203
|
+
|
|
1204
|
+
fig, ax = plt.subplots(2, 1, figsize=fig_size)
|
|
1205
|
+
_ = ax[0].hist(hist_edges[:-1],
|
|
1206
|
+
hist_edges,
|
|
1207
|
+
weights=hist_count,
|
|
1208
|
+
linewidth=0,
|
|
1209
|
+
**kwargs)
|
|
1210
|
+
_ = ax[1].hist(bin_edges[:-1],
|
|
1211
|
+
bin_edges,
|
|
1212
|
+
weights=bin_count,
|
|
1213
|
+
**kwargs)
|
|
1214
|
+
ax[0].set_xlabel('Non-zero values')
|
|
1215
|
+
ax[0].set_ylabel('Count')
|
|
1216
|
+
ax[0].set_title('Original')
|
|
1217
|
+
ax[1].set_xlabel('Non-zero values')
|
|
1218
|
+
ax[1].set_ylabel('Count')
|
|
1219
|
+
ax[1].set_title('Discretized')
|
|
1220
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
1221
|
+
if save_fig:
|
|
1222
|
+
if not os.path.exists(fig_path):
|
|
1223
|
+
os.makedirs(fig_path)
|
|
1224
|
+
plt.savefig(os.path.join(fig_path, fig_name),
|
|
1225
|
+
pad_inches=1,
|
|
1226
|
+
bbox_inches='tight')
|
|
1227
|
+
plt.close(fig)
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
def node_similarity(adata,
|
|
1231
|
+
bins=20,
|
|
1232
|
+
log=True,
|
|
1233
|
+
show_cutoff=True,
|
|
1234
|
+
cutoff=None,
|
|
1235
|
+
n_edges=5000,
|
|
1236
|
+
fig_size=(5, 3),
|
|
1237
|
+
pad=1.08,
|
|
1238
|
+
w_pad=None,
|
|
1239
|
+
h_pad=None,
|
|
1240
|
+
save_fig=None,
|
|
1241
|
+
fig_path=None,
|
|
1242
|
+
fig_name='plot_node_similarity.pdf',
|
|
1243
|
+
):
|
|
1244
|
+
"""Plot similarity scores of nodes
|
|
1245
|
+
|
|
1246
|
+
Parameters
|
|
1247
|
+
----------
|
|
1248
|
+
adata : `Anndata`
|
|
1249
|
+
Annotated data matrix.
|
|
1250
|
+
bins : `int`, optional (default: 20)
|
|
1251
|
+
The number of equal-width bins in the given range for histogram plot.
|
|
1252
|
+
log : `bool`, optional (default: True)
|
|
1253
|
+
If True, log scale will be used for y axis.
|
|
1254
|
+
show_cutoff : `bool`, optional (default: True)
|
|
1255
|
+
If True, cutoff on scores will be shown
|
|
1256
|
+
cutoff: `int`, optional (default: None)
|
|
1257
|
+
Cutoff used to select edges
|
|
1258
|
+
n_edges: `int`, optional (default: 5000)
|
|
1259
|
+
The number of edges to select.
|
|
1260
|
+
pad: `float`, optional (default: 1.08)
|
|
1261
|
+
Padding between the figure edge and the edges of subplots,
|
|
1262
|
+
as a fraction of the font size.
|
|
1263
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
1264
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
1265
|
+
as a fraction of the font size. Defaults to pad.
|
|
1266
|
+
fig_size: `tuple`, optional (default: (5,8))
|
|
1267
|
+
figure size.
|
|
1268
|
+
save_fig: `bool`, optional (default: False)
|
|
1269
|
+
if True,save the figure.
|
|
1270
|
+
fig_path: `str`, optional (default: None)
|
|
1271
|
+
If save_fig is True, specify figure path.
|
|
1272
|
+
fig_name: `str`, optional (default: 'plot_node_similarity.pdf')
|
|
1273
|
+
if `save_fig` is True, specify figure name.
|
|
1274
|
+
|
|
1275
|
+
Returns
|
|
1276
|
+
-------
|
|
1277
|
+
None
|
|
1278
|
+
"""
|
|
1279
|
+
if fig_size is None:
|
|
1280
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
1281
|
+
if save_fig is None:
|
|
1282
|
+
save_fig = settings.save_fig
|
|
1283
|
+
if fig_path is None:
|
|
1284
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
1285
|
+
|
|
1286
|
+
mat_sim = adata.X
|
|
1287
|
+
|
|
1288
|
+
fig, ax = plt.subplots(1, 1, figsize=fig_size)
|
|
1289
|
+
ax.hist(mat_sim.data, bins=bins)
|
|
1290
|
+
if log:
|
|
1291
|
+
ax.set_yscale('log')
|
|
1292
|
+
if show_cutoff:
|
|
1293
|
+
if cutoff is None:
|
|
1294
|
+
if n_edges is None:
|
|
1295
|
+
raise ValueError('"cutoff" or "n_edges" has to be specified')
|
|
1296
|
+
else:
|
|
1297
|
+
cutoff = \
|
|
1298
|
+
np.partition(mat_sim.data,
|
|
1299
|
+
(mat_sim.size-n_edges))[mat_sim.size-n_edges]
|
|
1300
|
+
id_x, id_y, _ = find(mat_sim > cutoff)
|
|
1301
|
+
print(f'#selected edges: {len(id_x)}')
|
|
1302
|
+
plt.axvline(cutoff, ls='--', c='red')
|
|
1303
|
+
ax.set_xlabel('similariy scores')
|
|
1304
|
+
ax.set_title('Node similarity')
|
|
1305
|
+
plt.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad)
|
|
1306
|
+
if save_fig:
|
|
1307
|
+
if not os.path.exists(fig_path):
|
|
1308
|
+
os.makedirs(fig_path)
|
|
1309
|
+
fig.savefig(os.path.join(fig_path, fig_name),
|
|
1310
|
+
pad_inches=1,
|
|
1311
|
+
bbox_inches='tight')
|
|
1312
|
+
plt.close(fig)
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
def svd_nodes(adata,
|
|
1316
|
+
comp1=1,
|
|
1317
|
+
comp2=2,
|
|
1318
|
+
color=None,
|
|
1319
|
+
dict_palette=None,
|
|
1320
|
+
cutoff=None,
|
|
1321
|
+
n_edges=5000,
|
|
1322
|
+
size=8,
|
|
1323
|
+
drawing_order='random',
|
|
1324
|
+
dict_drawing_order=None,
|
|
1325
|
+
fig_size=(4, 4),
|
|
1326
|
+
fig_ncol=3,
|
|
1327
|
+
fig_legend_ncol=1,
|
|
1328
|
+
fig_legend_order=None,
|
|
1329
|
+
alpha=1,
|
|
1330
|
+
pad=1.08,
|
|
1331
|
+
w_pad=None,
|
|
1332
|
+
h_pad=None,
|
|
1333
|
+
save_fig=None,
|
|
1334
|
+
fig_path=None,
|
|
1335
|
+
fig_name='plot_svd_nodes.pdf',
|
|
1336
|
+
vmin=None,
|
|
1337
|
+
vmax=None,
|
|
1338
|
+
**kwargs):
|
|
1339
|
+
"""Plot SVD coordinates
|
|
1340
|
+
|
|
1341
|
+
Parameters
|
|
1342
|
+
----------
|
|
1343
|
+
adata : `Anndata`
|
|
1344
|
+
Annotated data matrix.
|
|
1345
|
+
comp1: `int`, optional (default: 1)
|
|
1346
|
+
Component used for x axis.
|
|
1347
|
+
comp2: `int`, optional (default: 2)
|
|
1348
|
+
Component used for y axis.
|
|
1349
|
+
color: `list`, optional (default: None)
|
|
1350
|
+
A list of variables that will produce points with different colors.
|
|
1351
|
+
e.g. color = ['anno1', 'anno2']
|
|
1352
|
+
cutoff: `int`, optional (default: None)
|
|
1353
|
+
Cutoff used to select edges
|
|
1354
|
+
n_edges: `int`, optional (default: 5000)
|
|
1355
|
+
The number of edges to select
|
|
1356
|
+
dict_palette: `dict`,optional (default: None)
|
|
1357
|
+
A dictionary of palettes for different variables in `color`.
|
|
1358
|
+
Only valid for categorical/string variables
|
|
1359
|
+
e.g. dict_palette = {'ann1': {},'ann2': {}}
|
|
1360
|
+
drawing_order: `str` (default: 'random')
|
|
1361
|
+
The order in which values are plotted, This can be
|
|
1362
|
+
one of the following values
|
|
1363
|
+
- 'original': plot points in the same order as in input dataframe
|
|
1364
|
+
- 'sorted' : plot points with higher values on top.
|
|
1365
|
+
- 'random' : plot points in a random order
|
|
1366
|
+
dict_drawing_order: `dict`,optional (default: None)
|
|
1367
|
+
A dictionary of drawing_order for different variables in `color`.
|
|
1368
|
+
Only valid for categorical/string variables
|
|
1369
|
+
e.g. dict_drawing_order = {'ann1': 'original','ann2': 'sorted'}
|
|
1370
|
+
size: `int` (default: 8)
|
|
1371
|
+
Point size.
|
|
1372
|
+
fig_size: `tuple`, optional (default: (4, 4))
|
|
1373
|
+
figure size.
|
|
1374
|
+
fig_ncol: `int`, optional (default: 3)
|
|
1375
|
+
the number of columns of the figure panel
|
|
1376
|
+
fig_legend_order: `dict`,optional (default: None)
|
|
1377
|
+
Specified order for the appearance of the annotation keys.
|
|
1378
|
+
Only valid for categorical/string variable
|
|
1379
|
+
e.g. fig_legend_order = {'ann1':['a','b','c'],'ann2':['aa','bb','cc']}
|
|
1380
|
+
fig_legend_ncol: `int`, optional (default: 1)
|
|
1381
|
+
The number of columns that the legend has.
|
|
1382
|
+
vmin,vmax: `float`, optional (default: None)
|
|
1383
|
+
The min and max values are used to normalize continuous values.
|
|
1384
|
+
If None, the respective min and max of continuous values is used.
|
|
1385
|
+
alpha: `float`, optional (default: 1)
|
|
1386
|
+
0.0 transparent through 1.0 opaque
|
|
1387
|
+
pad: `float`, optional (default: 1.08)
|
|
1388
|
+
Padding between the figure edge and the edges of subplots,
|
|
1389
|
+
as a fraction of the font size.
|
|
1390
|
+
h_pad, w_pad: `float`, optional (default: None)
|
|
1391
|
+
Padding (height/width) between edges of adjacent subplots,
|
|
1392
|
+
as a fraction of the font size. Defaults to pad.
|
|
1393
|
+
save_fig: `bool`, optional (default: False)
|
|
1394
|
+
if True,save the figure.
|
|
1395
|
+
fig_path: `str`, optional (default: None)
|
|
1396
|
+
If save_fig is True, specify figure path.
|
|
1397
|
+
fig_name: `str`, optional (default: 'plot_umap.pdf')
|
|
1398
|
+
if save_fig is True, specify figure name.
|
|
1399
|
+
Returns
|
|
1400
|
+
-------
|
|
1401
|
+
None
|
|
1402
|
+
"""
|
|
1403
|
+
if fig_size is None:
|
|
1404
|
+
fig_size = mpl.rcParams['figure.figsize']
|
|
1405
|
+
if save_fig is None:
|
|
1406
|
+
save_fig = settings.save_fig
|
|
1407
|
+
if fig_path is None:
|
|
1408
|
+
fig_path = os.path.join(settings.workdir, 'figures')
|
|
1409
|
+
|
|
1410
|
+
mat_sim = adata.X
|
|
1411
|
+
if cutoff is None:
|
|
1412
|
+
if n_edges is None:
|
|
1413
|
+
raise ValueError('"cutoff" or "n_edges" has to be specified')
|
|
1414
|
+
else:
|
|
1415
|
+
cutoff = \
|
|
1416
|
+
np.partition(mat_sim.data,
|
|
1417
|
+
(mat_sim.size-n_edges))[mat_sim.size-n_edges]
|
|
1418
|
+
id_x, id_y, _ = find(mat_sim > cutoff)
|
|
1419
|
+
|
|
1420
|
+
X_cca_ref = adata.obsm['svd']
|
|
1421
|
+
X_cca_query = adata.varm['svd']
|
|
1422
|
+
|
|
1423
|
+
df_plot_ref = pd.DataFrame(data=X_cca_ref[:, [comp1-1, comp2-1]],
|
|
1424
|
+
index=adata.obs.index,
|
|
1425
|
+
columns=[f'Dim {comp1}', f'Dim {comp2}'])
|
|
1426
|
+
df_plot_ref['group'] = 'ref'
|
|
1427
|
+
df_plot_ref['selected'] = 'no'
|
|
1428
|
+
df_plot_ref.loc[df_plot_ref.index[id_x], 'selected'] = 'yes'
|
|
1429
|
+
df_plot_query = pd.DataFrame(data=X_cca_query[:, [comp1-1, comp2-1]],
|
|
1430
|
+
index=adata.var.index,
|
|
1431
|
+
columns=[f'Dim {comp1}', f'Dim {comp2}'])
|
|
1432
|
+
df_plot_query['group'] = 'query'
|
|
1433
|
+
df_plot_query['selected'] = 'no'
|
|
1434
|
+
df_plot_query.loc[df_plot_query.index[id_y], 'selected'] = 'yes'
|
|
1435
|
+
|
|
1436
|
+
df_plot = pd.concat([df_plot_ref, df_plot_query], axis=0)
|
|
1437
|
+
if dict_palette is None:
|
|
1438
|
+
dict_palette = dict()
|
|
1439
|
+
dict_palette['group'] = {'query': '#4c72b0', 'ref': '#dd8452'}
|
|
1440
|
+
dict_palette['selected'] = {'yes': '#000000', 'no': '#D4D3D3'}
|
|
1441
|
+
if dict_drawing_order is None:
|
|
1442
|
+
dict_drawing_order = dict()
|
|
1443
|
+
dict_drawing_order['group'] = 'random'
|
|
1444
|
+
dict_drawing_order['selected'] = 'sorted'
|
|
1445
|
+
|
|
1446
|
+
adata.uns['color'] = dict_palette.copy()
|
|
1447
|
+
if color is None:
|
|
1448
|
+
color = []
|
|
1449
|
+
else:
|
|
1450
|
+
color = list(dict.fromkeys(color)) # remove duplicate keys
|
|
1451
|
+
for ann in color:
|
|
1452
|
+
if (ann in adata.obs_keys()) and (ann in adata.var_keys()):
|
|
1453
|
+
df_plot[ann] = pd.concat([adata.obs[ann], adata.var[ann]], axis=0)
|
|
1454
|
+
if not is_numeric_dtype(df_plot[ann]):
|
|
1455
|
+
if ann not in dict_palette.keys():
|
|
1456
|
+
if (ann+'_color' in adata.uns['color'].keys()) \
|
|
1457
|
+
and \
|
|
1458
|
+
(all(np.isin(np.unique(df_plot[ann]),
|
|
1459
|
+
list(adata.uns['color']
|
|
1460
|
+
[ann+'_color'].keys())))):
|
|
1461
|
+
dict_palette[ann] = \
|
|
1462
|
+
adata.uns['color'][ann+'_color']
|
|
1463
|
+
else:
|
|
1464
|
+
dict_palette[ann] = \
|
|
1465
|
+
generate_palette(adata.obs[ann])
|
|
1466
|
+
adata.uns['color'][ann+'_color'] = \
|
|
1467
|
+
dict_palette[ann].copy()
|
|
1468
|
+
else:
|
|
1469
|
+
if ann+'_color' not in adata.uns['color'].keys():
|
|
1470
|
+
adata.uns['color'][ann+'_color'] = \
|
|
1471
|
+
dict_palette[ann].copy()
|
|
1472
|
+
else:
|
|
1473
|
+
raise ValueError(f"could not find {ann} in both "
|
|
1474
|
+
"`adata.obs.columns`"
|
|
1475
|
+
" and `adata.var.columns`")
|
|
1476
|
+
color = ['group', 'selected'] + color
|
|
1477
|
+
_scatterplot2d(df_plot,
|
|
1478
|
+
x=f'Dim {comp1}',
|
|
1479
|
+
y=f'Dim {comp2}',
|
|
1480
|
+
list_hue=color,
|
|
1481
|
+
hue_palette=dict_palette,
|
|
1482
|
+
drawing_order=drawing_order,
|
|
1483
|
+
dict_drawing_order=dict_drawing_order,
|
|
1484
|
+
size=size,
|
|
1485
|
+
fig_size=fig_size,
|
|
1486
|
+
fig_ncol=fig_ncol,
|
|
1487
|
+
fig_legend_ncol=fig_legend_ncol,
|
|
1488
|
+
fig_legend_order=fig_legend_order,
|
|
1489
|
+
vmin=vmin,
|
|
1490
|
+
vmax=vmax,
|
|
1491
|
+
alpha=alpha,
|
|
1492
|
+
pad=pad,
|
|
1493
|
+
w_pad=w_pad,
|
|
1494
|
+
h_pad=h_pad,
|
|
1495
|
+
save_fig=save_fig,
|
|
1496
|
+
fig_path=fig_path,
|
|
1497
|
+
fig_name=fig_name,
|
|
1498
|
+
**kwargs)
|