spatialcore 0.1.9__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.
- spatialcore/__init__.py +122 -0
- spatialcore/annotation/__init__.py +253 -0
- spatialcore/annotation/acquisition.py +529 -0
- spatialcore/annotation/annotate.py +603 -0
- spatialcore/annotation/cellxgene.py +365 -0
- spatialcore/annotation/confidence.py +802 -0
- spatialcore/annotation/discovery.py +529 -0
- spatialcore/annotation/expression.py +363 -0
- spatialcore/annotation/loading.py +529 -0
- spatialcore/annotation/markers.py +297 -0
- spatialcore/annotation/ontology.py +1282 -0
- spatialcore/annotation/patterns.py +247 -0
- spatialcore/annotation/pipeline.py +620 -0
- spatialcore/annotation/synapse.py +380 -0
- spatialcore/annotation/training.py +1457 -0
- spatialcore/annotation/validation.py +422 -0
- spatialcore/core/__init__.py +34 -0
- spatialcore/core/cache.py +118 -0
- spatialcore/core/logging.py +135 -0
- spatialcore/core/metadata.py +149 -0
- spatialcore/core/utils.py +768 -0
- spatialcore/data/gene_mappings/ensembl_to_hugo_human.tsv +86372 -0
- spatialcore/data/markers/canonical_markers.json +83 -0
- spatialcore/data/ontology_mappings/ontology_index.json +63865 -0
- spatialcore/plotting/__init__.py +109 -0
- spatialcore/plotting/benchmark.py +477 -0
- spatialcore/plotting/celltype.py +329 -0
- spatialcore/plotting/confidence.py +413 -0
- spatialcore/plotting/spatial.py +505 -0
- spatialcore/plotting/utils.py +411 -0
- spatialcore/plotting/validation.py +1342 -0
- spatialcore-0.1.9.dist-info/METADATA +213 -0
- spatialcore-0.1.9.dist-info/RECORD +36 -0
- spatialcore-0.1.9.dist-info/WHEEL +5 -0
- spatialcore-0.1.9.dist-info/licenses/LICENSE +201 -0
- spatialcore-0.1.9.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Spatial visualization of cell types and confidence.
|
|
3
|
+
|
|
4
|
+
This module provides functions for visualizing cell annotations
|
|
5
|
+
on spatial coordinates.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Dict, List, Optional, Tuple, Union
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
from matplotlib.figure import Figure
|
|
14
|
+
from matplotlib.colors import Normalize
|
|
15
|
+
import matplotlib.cm as cm
|
|
16
|
+
import anndata as ad
|
|
17
|
+
|
|
18
|
+
from spatialcore.core.logging import get_logger
|
|
19
|
+
from spatialcore.plotting.utils import (
|
|
20
|
+
generate_celltype_palette,
|
|
21
|
+
setup_figure,
|
|
22
|
+
save_figure,
|
|
23
|
+
format_axis_labels,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
logger = get_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def plot_spatial_celltype(
|
|
30
|
+
adata: ad.AnnData,
|
|
31
|
+
label_column: str,
|
|
32
|
+
spatial_key: str = "spatial",
|
|
33
|
+
colors: Optional[Dict[str, str]] = None,
|
|
34
|
+
point_size: float = 1.0,
|
|
35
|
+
alpha: float = 0.8,
|
|
36
|
+
figsize: tuple = (10, 10),
|
|
37
|
+
dark_background: bool = True,
|
|
38
|
+
legend_loc: str = "right margin",
|
|
39
|
+
xlim: Optional[Tuple[float, float]] = None,
|
|
40
|
+
ylim: Optional[Tuple[float, float]] = None,
|
|
41
|
+
title: Optional[str] = None,
|
|
42
|
+
save: Optional[Union[str, Path]] = None,
|
|
43
|
+
) -> Figure:
|
|
44
|
+
"""
|
|
45
|
+
Plot cell types on spatial coordinates.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
adata : AnnData
|
|
50
|
+
Annotated data with spatial coordinates.
|
|
51
|
+
label_column : str
|
|
52
|
+
Column in adata.obs containing cell type labels.
|
|
53
|
+
spatial_key : str, default "spatial"
|
|
54
|
+
Key in adata.obsm for spatial coordinates.
|
|
55
|
+
colors : Dict[str, str], optional
|
|
56
|
+
Color mapping for cell types.
|
|
57
|
+
point_size : float, default 1.0
|
|
58
|
+
Size of points.
|
|
59
|
+
alpha : float, default 0.8
|
|
60
|
+
Point transparency.
|
|
61
|
+
figsize : tuple, default (10, 10)
|
|
62
|
+
Figure size.
|
|
63
|
+
dark_background : bool, default True
|
|
64
|
+
Use dark background (better for spatial data).
|
|
65
|
+
legend_loc : str, default "right margin"
|
|
66
|
+
Legend location: "right margin", "on data", "none".
|
|
67
|
+
xlim : Tuple[float, float], optional
|
|
68
|
+
X-axis limits.
|
|
69
|
+
ylim : Tuple[float, float], optional
|
|
70
|
+
Y-axis limits.
|
|
71
|
+
title : str, optional
|
|
72
|
+
Plot title.
|
|
73
|
+
save : str or Path, optional
|
|
74
|
+
Path to save figure.
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
Figure
|
|
79
|
+
Matplotlib figure.
|
|
80
|
+
|
|
81
|
+
Examples
|
|
82
|
+
--------
|
|
83
|
+
>>> from spatialcore.plotting.spatial import plot_spatial_celltype
|
|
84
|
+
>>> fig = plot_spatial_celltype(
|
|
85
|
+
... adata,
|
|
86
|
+
... label_column="cell_type",
|
|
87
|
+
... point_size=0.5,
|
|
88
|
+
... )
|
|
89
|
+
"""
|
|
90
|
+
if label_column not in adata.obs.columns:
|
|
91
|
+
raise ValueError(f"Label column '{label_column}' not found.")
|
|
92
|
+
|
|
93
|
+
if spatial_key not in adata.obsm:
|
|
94
|
+
raise ValueError(
|
|
95
|
+
f"Spatial key '{spatial_key}' not found. "
|
|
96
|
+
f"Available: {list(adata.obsm.keys())}"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
coords = adata.obsm[spatial_key]
|
|
100
|
+
cell_types = adata.obs[label_column].astype(str)
|
|
101
|
+
unique_types = sorted(cell_types.unique())
|
|
102
|
+
|
|
103
|
+
if colors is None:
|
|
104
|
+
colors = generate_celltype_palette(unique_types)
|
|
105
|
+
|
|
106
|
+
# Adjust figure size for legend
|
|
107
|
+
if legend_loc == "right margin":
|
|
108
|
+
figsize = (figsize[0] + 3, figsize[1])
|
|
109
|
+
|
|
110
|
+
if dark_background:
|
|
111
|
+
plt.style.use("dark_background")
|
|
112
|
+
|
|
113
|
+
fig, ax = setup_figure(figsize=figsize)
|
|
114
|
+
|
|
115
|
+
# Plot each cell type
|
|
116
|
+
for cell_type in unique_types:
|
|
117
|
+
mask = cell_types == cell_type
|
|
118
|
+
ax.scatter(
|
|
119
|
+
coords[mask, 0],
|
|
120
|
+
coords[mask, 1],
|
|
121
|
+
c=colors.get(cell_type, "#888888"),
|
|
122
|
+
label=cell_type,
|
|
123
|
+
s=point_size,
|
|
124
|
+
alpha=alpha,
|
|
125
|
+
rasterized=True,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
ax.set_xlabel("X")
|
|
129
|
+
ax.set_ylabel("Y")
|
|
130
|
+
ax.set_aspect("equal")
|
|
131
|
+
|
|
132
|
+
if xlim:
|
|
133
|
+
ax.set_xlim(xlim)
|
|
134
|
+
if ylim:
|
|
135
|
+
ax.set_ylim(ylim)
|
|
136
|
+
|
|
137
|
+
# Legend
|
|
138
|
+
if legend_loc == "right margin":
|
|
139
|
+
ax.legend(
|
|
140
|
+
bbox_to_anchor=(1.02, 1),
|
|
141
|
+
loc="upper left",
|
|
142
|
+
markerscale=5,
|
|
143
|
+
frameon=False,
|
|
144
|
+
)
|
|
145
|
+
elif legend_loc == "on data":
|
|
146
|
+
ax.legend(loc="best", markerscale=5)
|
|
147
|
+
|
|
148
|
+
if title is None:
|
|
149
|
+
title = f"Spatial Cell Types ({label_column})"
|
|
150
|
+
ax.set_title(title, color="white" if dark_background else "black")
|
|
151
|
+
|
|
152
|
+
plt.tight_layout()
|
|
153
|
+
|
|
154
|
+
if save:
|
|
155
|
+
save_figure(fig, save)
|
|
156
|
+
|
|
157
|
+
# Reset style
|
|
158
|
+
if dark_background:
|
|
159
|
+
plt.style.use("default")
|
|
160
|
+
|
|
161
|
+
return fig
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def plot_spatial_confidence(
|
|
165
|
+
adata: ad.AnnData,
|
|
166
|
+
confidence_column: str,
|
|
167
|
+
spatial_key: str = "spatial",
|
|
168
|
+
cmap: str = "viridis",
|
|
169
|
+
point_size: float = 1.0,
|
|
170
|
+
alpha: float = 0.8,
|
|
171
|
+
vmin: Optional[float] = None,
|
|
172
|
+
vmax: Optional[float] = None,
|
|
173
|
+
figsize: tuple = (10, 10),
|
|
174
|
+
dark_background: bool = True,
|
|
175
|
+
colorbar: bool = True,
|
|
176
|
+
xlim: Optional[Tuple[float, float]] = None,
|
|
177
|
+
ylim: Optional[Tuple[float, float]] = None,
|
|
178
|
+
title: Optional[str] = None,
|
|
179
|
+
save: Optional[Union[str, Path]] = None,
|
|
180
|
+
) -> Figure:
|
|
181
|
+
"""
|
|
182
|
+
Plot confidence scores on spatial coordinates.
|
|
183
|
+
|
|
184
|
+
Parameters
|
|
185
|
+
----------
|
|
186
|
+
adata : AnnData
|
|
187
|
+
Annotated data with spatial coordinates and confidence.
|
|
188
|
+
confidence_column : str
|
|
189
|
+
Column in adata.obs containing confidence values.
|
|
190
|
+
spatial_key : str, default "spatial"
|
|
191
|
+
Key in adata.obsm for spatial coordinates.
|
|
192
|
+
cmap : str, default "viridis"
|
|
193
|
+
Colormap name.
|
|
194
|
+
point_size : float, default 1.0
|
|
195
|
+
Size of points.
|
|
196
|
+
alpha : float, default 0.8
|
|
197
|
+
Point transparency.
|
|
198
|
+
vmin : float, optional
|
|
199
|
+
Minimum value for color scale.
|
|
200
|
+
vmax : float, optional
|
|
201
|
+
Maximum value for color scale.
|
|
202
|
+
figsize : tuple, default (10, 10)
|
|
203
|
+
Figure size.
|
|
204
|
+
dark_background : bool, default True
|
|
205
|
+
Use dark background.
|
|
206
|
+
colorbar : bool, default True
|
|
207
|
+
Show colorbar.
|
|
208
|
+
xlim : Tuple[float, float], optional
|
|
209
|
+
X-axis limits.
|
|
210
|
+
ylim : Tuple[float, float], optional
|
|
211
|
+
Y-axis limits.
|
|
212
|
+
title : str, optional
|
|
213
|
+
Plot title.
|
|
214
|
+
save : str or Path, optional
|
|
215
|
+
Path to save figure.
|
|
216
|
+
|
|
217
|
+
Returns
|
|
218
|
+
-------
|
|
219
|
+
Figure
|
|
220
|
+
Matplotlib figure.
|
|
221
|
+
|
|
222
|
+
Examples
|
|
223
|
+
--------
|
|
224
|
+
>>> from spatialcore.plotting.spatial import plot_spatial_confidence
|
|
225
|
+
>>> fig = plot_spatial_confidence(
|
|
226
|
+
... adata,
|
|
227
|
+
... confidence_column="confidence",
|
|
228
|
+
... cmap="plasma",
|
|
229
|
+
... )
|
|
230
|
+
"""
|
|
231
|
+
if confidence_column not in adata.obs.columns:
|
|
232
|
+
raise ValueError(f"Confidence column '{confidence_column}' not found.")
|
|
233
|
+
|
|
234
|
+
if spatial_key not in adata.obsm:
|
|
235
|
+
raise ValueError(f"Spatial key '{spatial_key}' not found.")
|
|
236
|
+
|
|
237
|
+
coords = adata.obsm[spatial_key]
|
|
238
|
+
confidence = adata.obs[confidence_column].values
|
|
239
|
+
|
|
240
|
+
if dark_background:
|
|
241
|
+
plt.style.use("dark_background")
|
|
242
|
+
|
|
243
|
+
fig, ax = setup_figure(figsize=figsize)
|
|
244
|
+
|
|
245
|
+
scatter = ax.scatter(
|
|
246
|
+
coords[:, 0],
|
|
247
|
+
coords[:, 1],
|
|
248
|
+
c=confidence,
|
|
249
|
+
cmap=cmap,
|
|
250
|
+
s=point_size,
|
|
251
|
+
alpha=alpha,
|
|
252
|
+
vmin=vmin,
|
|
253
|
+
vmax=vmax,
|
|
254
|
+
rasterized=True,
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
ax.set_xlabel("X")
|
|
258
|
+
ax.set_ylabel("Y")
|
|
259
|
+
ax.set_aspect("equal")
|
|
260
|
+
|
|
261
|
+
if xlim:
|
|
262
|
+
ax.set_xlim(xlim)
|
|
263
|
+
if ylim:
|
|
264
|
+
ax.set_ylim(ylim)
|
|
265
|
+
|
|
266
|
+
if colorbar:
|
|
267
|
+
cbar = plt.colorbar(scatter, ax=ax, shrink=0.6)
|
|
268
|
+
cbar.set_label("Confidence", fontsize=10)
|
|
269
|
+
|
|
270
|
+
if title is None:
|
|
271
|
+
title = f"Spatial Confidence ({confidence_column})"
|
|
272
|
+
ax.set_title(title, color="white" if dark_background else "black")
|
|
273
|
+
|
|
274
|
+
plt.tight_layout()
|
|
275
|
+
|
|
276
|
+
if save:
|
|
277
|
+
save_figure(fig, save)
|
|
278
|
+
|
|
279
|
+
if dark_background:
|
|
280
|
+
plt.style.use("default")
|
|
281
|
+
|
|
282
|
+
return fig
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def plot_spatial_gene(
|
|
286
|
+
adata: ad.AnnData,
|
|
287
|
+
gene: str,
|
|
288
|
+
spatial_key: str = "spatial",
|
|
289
|
+
layer: Optional[str] = None,
|
|
290
|
+
cmap: str = "Reds",
|
|
291
|
+
point_size: float = 1.0,
|
|
292
|
+
alpha: float = 0.8,
|
|
293
|
+
vmin: Optional[float] = None,
|
|
294
|
+
vmax: Optional[float] = None,
|
|
295
|
+
figsize: tuple = (10, 10),
|
|
296
|
+
dark_background: bool = True,
|
|
297
|
+
colorbar: bool = True,
|
|
298
|
+
title: Optional[str] = None,
|
|
299
|
+
save: Optional[Union[str, Path]] = None,
|
|
300
|
+
) -> Figure:
|
|
301
|
+
"""
|
|
302
|
+
Plot gene expression on spatial coordinates.
|
|
303
|
+
|
|
304
|
+
Parameters
|
|
305
|
+
----------
|
|
306
|
+
adata : AnnData
|
|
307
|
+
Annotated data with spatial coordinates.
|
|
308
|
+
gene : str
|
|
309
|
+
Gene name to plot.
|
|
310
|
+
spatial_key : str, default "spatial"
|
|
311
|
+
Key in adata.obsm for spatial coordinates.
|
|
312
|
+
layer : str, optional
|
|
313
|
+
Layer to use. If None, uses adata.X.
|
|
314
|
+
cmap : str, default "Reds"
|
|
315
|
+
Colormap name.
|
|
316
|
+
point_size : float, default 1.0
|
|
317
|
+
Size of points.
|
|
318
|
+
alpha : float, default 0.8
|
|
319
|
+
Point transparency.
|
|
320
|
+
vmin : float, optional
|
|
321
|
+
Minimum value for color scale.
|
|
322
|
+
vmax : float, optional
|
|
323
|
+
Maximum value for color scale.
|
|
324
|
+
figsize : tuple, default (10, 10)
|
|
325
|
+
Figure size.
|
|
326
|
+
dark_background : bool, default True
|
|
327
|
+
Use dark background.
|
|
328
|
+
colorbar : bool, default True
|
|
329
|
+
Show colorbar.
|
|
330
|
+
title : str, optional
|
|
331
|
+
Plot title.
|
|
332
|
+
save : str or Path, optional
|
|
333
|
+
Path to save figure.
|
|
334
|
+
|
|
335
|
+
Returns
|
|
336
|
+
-------
|
|
337
|
+
Figure
|
|
338
|
+
Matplotlib figure.
|
|
339
|
+
"""
|
|
340
|
+
if gene not in adata.var_names:
|
|
341
|
+
raise ValueError(
|
|
342
|
+
f"Gene '{gene}' not found. "
|
|
343
|
+
f"Available genes: {list(adata.var_names[:10])}..."
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
if spatial_key not in adata.obsm:
|
|
347
|
+
raise ValueError(f"Spatial key '{spatial_key}' not found.")
|
|
348
|
+
|
|
349
|
+
coords = adata.obsm[spatial_key]
|
|
350
|
+
|
|
351
|
+
# Get expression
|
|
352
|
+
gene_idx = adata.var_names.get_loc(gene)
|
|
353
|
+
if layer is not None:
|
|
354
|
+
expression = adata.layers[layer][:, gene_idx]
|
|
355
|
+
else:
|
|
356
|
+
X = adata.X
|
|
357
|
+
if hasattr(X, "toarray"):
|
|
358
|
+
expression = X[:, gene_idx].toarray().flatten()
|
|
359
|
+
else:
|
|
360
|
+
expression = X[:, gene_idx].flatten()
|
|
361
|
+
|
|
362
|
+
if dark_background:
|
|
363
|
+
plt.style.use("dark_background")
|
|
364
|
+
|
|
365
|
+
fig, ax = setup_figure(figsize=figsize)
|
|
366
|
+
|
|
367
|
+
scatter = ax.scatter(
|
|
368
|
+
coords[:, 0],
|
|
369
|
+
coords[:, 1],
|
|
370
|
+
c=expression,
|
|
371
|
+
cmap=cmap,
|
|
372
|
+
s=point_size,
|
|
373
|
+
alpha=alpha,
|
|
374
|
+
vmin=vmin,
|
|
375
|
+
vmax=vmax,
|
|
376
|
+
rasterized=True,
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
ax.set_xlabel("X")
|
|
380
|
+
ax.set_ylabel("Y")
|
|
381
|
+
ax.set_aspect("equal")
|
|
382
|
+
|
|
383
|
+
if colorbar:
|
|
384
|
+
cbar = plt.colorbar(scatter, ax=ax, shrink=0.6)
|
|
385
|
+
cbar.set_label("Expression", fontsize=10)
|
|
386
|
+
|
|
387
|
+
if title is None:
|
|
388
|
+
title = f"{gene} Expression"
|
|
389
|
+
ax.set_title(title, color="white" if dark_background else "black")
|
|
390
|
+
|
|
391
|
+
plt.tight_layout()
|
|
392
|
+
|
|
393
|
+
if save:
|
|
394
|
+
save_figure(fig, save)
|
|
395
|
+
|
|
396
|
+
if dark_background:
|
|
397
|
+
plt.style.use("default")
|
|
398
|
+
|
|
399
|
+
return fig
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def plot_spatial_multi_gene(
|
|
403
|
+
adata: ad.AnnData,
|
|
404
|
+
genes: List[str],
|
|
405
|
+
spatial_key: str = "spatial",
|
|
406
|
+
layer: Optional[str] = None,
|
|
407
|
+
cmap: str = "Reds",
|
|
408
|
+
point_size: float = 0.5,
|
|
409
|
+
ncols: int = 3,
|
|
410
|
+
figsize_per_panel: Tuple[float, float] = (4, 4),
|
|
411
|
+
dark_background: bool = True,
|
|
412
|
+
save: Optional[Union[str, Path]] = None,
|
|
413
|
+
) -> Figure:
|
|
414
|
+
"""
|
|
415
|
+
Plot multiple genes on spatial coordinates.
|
|
416
|
+
|
|
417
|
+
Parameters
|
|
418
|
+
----------
|
|
419
|
+
adata : AnnData
|
|
420
|
+
Annotated data with spatial coordinates.
|
|
421
|
+
genes : List[str]
|
|
422
|
+
List of gene names to plot.
|
|
423
|
+
spatial_key : str, default "spatial"
|
|
424
|
+
Key in adata.obsm for spatial coordinates.
|
|
425
|
+
layer : str, optional
|
|
426
|
+
Layer to use.
|
|
427
|
+
cmap : str, default "Reds"
|
|
428
|
+
Colormap name.
|
|
429
|
+
point_size : float, default 0.5
|
|
430
|
+
Size of points.
|
|
431
|
+
ncols : int, default 3
|
|
432
|
+
Number of columns in subplot grid.
|
|
433
|
+
figsize_per_panel : Tuple[float, float], default (4, 4)
|
|
434
|
+
Size per panel.
|
|
435
|
+
dark_background : bool, default True
|
|
436
|
+
Use dark background.
|
|
437
|
+
save : str or Path, optional
|
|
438
|
+
Path to save figure.
|
|
439
|
+
|
|
440
|
+
Returns
|
|
441
|
+
-------
|
|
442
|
+
Figure
|
|
443
|
+
Matplotlib figure.
|
|
444
|
+
"""
|
|
445
|
+
# Filter to available genes
|
|
446
|
+
available_genes = [g for g in genes if g in adata.var_names]
|
|
447
|
+
missing = set(genes) - set(available_genes)
|
|
448
|
+
if missing:
|
|
449
|
+
logger.warning(f"Genes not found: {missing}")
|
|
450
|
+
|
|
451
|
+
if not available_genes:
|
|
452
|
+
raise ValueError("No valid genes found.")
|
|
453
|
+
|
|
454
|
+
n_genes = len(available_genes)
|
|
455
|
+
nrows = int(np.ceil(n_genes / ncols))
|
|
456
|
+
|
|
457
|
+
figsize = (figsize_per_panel[0] * ncols, figsize_per_panel[1] * nrows)
|
|
458
|
+
|
|
459
|
+
if dark_background:
|
|
460
|
+
plt.style.use("dark_background")
|
|
461
|
+
|
|
462
|
+
fig, axes = plt.subplots(nrows, ncols, figsize=figsize)
|
|
463
|
+
axes = np.atleast_2d(axes).flatten()
|
|
464
|
+
|
|
465
|
+
coords = adata.obsm[spatial_key]
|
|
466
|
+
|
|
467
|
+
for i, gene in enumerate(available_genes):
|
|
468
|
+
ax = axes[i]
|
|
469
|
+
|
|
470
|
+
gene_idx = adata.var_names.get_loc(gene)
|
|
471
|
+
if layer is not None:
|
|
472
|
+
expression = adata.layers[layer][:, gene_idx]
|
|
473
|
+
else:
|
|
474
|
+
X = adata.X
|
|
475
|
+
if hasattr(X, "toarray"):
|
|
476
|
+
expression = X[:, gene_idx].toarray().flatten()
|
|
477
|
+
else:
|
|
478
|
+
expression = X[:, gene_idx].flatten()
|
|
479
|
+
|
|
480
|
+
ax.scatter(
|
|
481
|
+
coords[:, 0],
|
|
482
|
+
coords[:, 1],
|
|
483
|
+
c=expression,
|
|
484
|
+
cmap=cmap,
|
|
485
|
+
s=point_size,
|
|
486
|
+
rasterized=True,
|
|
487
|
+
)
|
|
488
|
+
ax.set_aspect("equal")
|
|
489
|
+
ax.set_title(gene, fontsize=10)
|
|
490
|
+
ax.set_xticks([])
|
|
491
|
+
ax.set_yticks([])
|
|
492
|
+
|
|
493
|
+
# Hide empty panels
|
|
494
|
+
for i in range(n_genes, len(axes)):
|
|
495
|
+
axes[i].set_visible(False)
|
|
496
|
+
|
|
497
|
+
plt.tight_layout()
|
|
498
|
+
|
|
499
|
+
if save:
|
|
500
|
+
save_figure(fig, save)
|
|
501
|
+
|
|
502
|
+
if dark_background:
|
|
503
|
+
plt.style.use("default")
|
|
504
|
+
|
|
505
|
+
return fig
|