Using INSPIRE with lightweight graph convolutional networks (LGCNs)

INSPIRE provides two integrative analyses options: one based on graph attention networks (GATs) and the other on lightweight graph convolutional networks (LGCNs). For tissue sections profiled using low-resolution platforms such as Visium or ST, we recommend employing the graph attention network variant of INSPIRE to leverage the attention mechanism for improved modeling accuracy. For high-resolution datasets, the lightweight graph convolutional network variant is recommended, as it provides enhanced computational efficiency and scalability for large-scale analyses.

We use the integrative analysis of mouse whole-embryo sections profiled by seqFISH and Stereo-seq as an example to provide step-by-step instructions for applying INSPIRE with lightweight graph convolutional networks (LGCNs).

Import packages

[1]:
import numpy as np
import scanpy as sc
import umap
import INSPIRE
import warnings
warnings.filterwarnings("ignore")

Load data

The input to INSPIRE consists of raw gene expression count matrices and spatial coordinate matrices derived from multiple tissue sections, with each section represented as an individual AnnData object. Specifically, for each tissue section, the raw count matrix is stored in adata.X, and the spatial coordinates of the spatial spots are stored in adata.obsm[“spatial”].

The example seqFISH and Stereo-seq tissue sections used in this tutorial can be downloaded from https://drive.google.com/drive/folders/1fBVZiUnUEa31-P7AMmDyQ5UPU58VnIox?usp=sharing.

[2]:
data_dir = "/gpfs/gibbs/pi/zhao/jz874/project/jiazhao/inspire_revision/tutorials/example_analyses/example_LGCN_data"
adata_seqfish = sc.read_h5ad(data_dir + "/adata_seqfish.h5ad")
adata_stereoseq = sc.read_h5ad(data_dir + "/adata_stereoseq.h5ad")

adata_st_list = [adata_seqfish, adata_stereoseq]

Data preprocessing

For integrative analyses involving sections with a limited number of shared measured genes, we recommend removing non-shared genes prior to selecting num_hvgs highly variable genes per section by setting limit_num_genes=True. In this example, only 347 genes are shared between the seqFISH and Stereo-seq sections. As a result, no further feature selection is necessary, and num_hvgs is set to a value higher than the number of shared genes to avoid additional filtering. Users may adjust quality control thresholds by modifying the min_genes_qc and min_cell_qc parameters. Setting both parameters to 2 generally yields satisfactory performance when integrating sections with a limited number of shared genes. The spot_size parameter is used exclusively for visualization and determines the size of each spatial spot in the generated plots.

[3]:
adata_st_list, adata_full = INSPIRE.utils.preprocess(adata_st_list=adata_st_list,
                                                     num_hvgs=1000,
                                                     min_genes_qc=2,
                                                     min_cells_qc=2,
                                                     spot_size=1,
                                                     limit_num_genes=True)
Get shared genes among all datasets...
Find 347 shared genes among datasets.
Finding highly variable genes...
shape of adata 0 before quality control:  (14185, 347)
shape of adata 0 after quality control:  (14185, 347)
shape of adata 1 before quality control:  (5913, 347)
shape of adata 1 after quality control:  (5880, 344)
Find 344 shared highly variable genes among datasets.
Concatenate datasets as a full anndata for better visualization...
../_images/examples_INSPIRE_LGCN_11_1.png
Store counts and library sizes for Poisson modeling...
Normalize data...

Build spatial graph

INSPIRE constructs a spatial neighbor graph among spots to model spatial dependencies within each tissue section. When using the lightweight graph convolutional network (LGCN) variant, this graph is built using the INSPIRE.utils.build_graph_LGCN function, which accepts adata_st_list as input. Users can customize the radius cutoff for defining spatial neighbors in each section by modifying the values in rad_cutoff_list. In this example, we define eight natural neighbors per spot in the seqFISH section by setting the corresponding radius cutoff to 1.6. To account for differences in the scale of spatial coordinates between the two sections, we adjust the cutoff accordingly and use a value of 3 for defining spatial neighbors in the Stereo-seq section.

[4]:
adata_st_list = INSPIRE.utils.build_graph_LGCN(adata_st_list=adata_st_list,
                                               rad_cutoff_list=[3,1.6])
Start building graphs...
Build graphs and prepare node features for LGCN networks
Radius for graph connection is 3.0000.
26.7748 neighbors per cell on average.
Node features for slice 0 : (14185, 688)
Radius for graph connection is 1.6000.
7.7946 neighbors per cell on average.
Node features for slice 1 : (5880, 688)

Run INSPIRE model

The computational model for the LGCN variant of INSPIRE is constructed using the INSPIRE.model.Model_LGCN function, which takes adata_st_list as input. Four key parameters of this function include n_spatial_factors, n_training_steps, batch_size, and different_platforms. The n_spatial_factors parameter specifies the number of spatial factors to be inferred and should be selected based on the complexity of the tissue. A default setting of n_training_steps = 10,000 typically provides robust results. Increasing this value to 20,000 may be advantageous when modeling a larger number of spatial factors. For integrative analyses involving more than 20,000 cells or spots, we recommend setting batch_size = 2048. For datasets with fewer than 20,000 cells or spots, batch_size = 1024 is typically sufficient. The different_platforms parameter determines whether section-specific networks are used to generate spatial factors from cell or spot embeddings. When analyzing sections derived from different technologies, where strong platform-specific effects are expected, we recommend setting different_platforms = True. In all other cases, the default setting is False.

[6]:
model = INSPIRE.model.Model_LGCN(adata_st_list=adata_st_list,
                                 n_spatial_factors=40,
                                 n_training_steps=10000,
                                 batch_size=2048,
                                 different_platforms=True
                                 )

After constructing the computational model, training is performed using the model.train function.

[7]:
model.train(adata_st_list)
  0%|          | 6/10000 [00:00<08:30, 19.58it/s]
Step: 0, d_loss: 1.4992, Loss: 1364.8623, recon_loss: 552.5065, fe_loss: 44.9286, geom_loss: 165.7725, beta_loss: 763.3344, gan_loss: 0.7776
  5%|▌         | 506/10000 [00:12<03:39, 43.26it/s]
Step: 500, d_loss: 0.6237, Loss: 1167.3342, recon_loss: 433.0272, fe_loss: 28.1169, geom_loss: 87.4508, beta_loss: 702.1931, gan_loss: 2.2480
 10%|█         | 1006/10000 [00:23<03:29, 42.98it/s]
Step: 1000, d_loss: 0.3045, Loss: 1076.6626, recon_loss: 341.4729, fe_loss: 27.3702, geom_loss: 130.6975, beta_loss: 701.8184, gan_loss: 3.3872
 15%|█▌        | 1506/10000 [00:35<03:18, 42.72it/s]
Step: 1500, d_loss: 0.2098, Loss: 1014.6364, recon_loss: 279.4295, fe_loss: 26.9022, geom_loss: 131.7953, beta_loss: 701.8845, gan_loss: 3.7844
 20%|██        | 2006/10000 [00:47<03:02, 43.78it/s]
Step: 2000, d_loss: 0.2105, Loss: 973.4398, recon_loss: 237.6814, fe_loss: 26.6580, geom_loss: 124.8234, beta_loss: 702.2662, gan_loss: 4.3377
 25%|██▌       | 2506/10000 [00:59<02:52, 43.38it/s]
Step: 2500, d_loss: 0.2238, Loss: 949.7872, recon_loss: 214.8734, fe_loss: 26.5242, geom_loss: 119.8150, beta_loss: 702.2215, gan_loss: 3.7718
 30%|███       | 3006/10000 [01:10<02:39, 43.90it/s]
Step: 3000, d_loss: 0.1744, Loss: 928.3311, recon_loss: 194.4388, fe_loss: 26.3288, geom_loss: 109.8261, beta_loss: 701.8584, gan_loss: 3.5087
 35%|███▌      | 3506/10000 [01:22<02:30, 43.27it/s]
Step: 3500, d_loss: 0.1483, Loss: 922.0637, recon_loss: 187.6211, fe_loss: 26.2629, geom_loss: 105.1442, beta_loss: 701.8630, gan_loss: 4.2138
 40%|████      | 4006/10000 [01:34<02:18, 43.14it/s]
Step: 4000, d_loss: 0.2480, Loss: 909.9057, recon_loss: 176.3834, fe_loss: 26.1227, geom_loss: 100.0805, beta_loss: 701.8671, gan_loss: 3.5309
 45%|████▌     | 4506/10000 [01:45<02:05, 43.72it/s]
Step: 4500, d_loss: 0.2300, Loss: 910.6376, recon_loss: 177.2427, fe_loss: 26.1271, geom_loss: 98.9051, beta_loss: 701.7460, gan_loss: 3.5437
 50%|█████     | 5006/10000 [01:57<01:58, 42.19it/s]
Step: 5000, d_loss: 0.3022, Loss: 901.6885, recon_loss: 167.7816, fe_loss: 26.0828, geom_loss: 99.3437, beta_loss: 701.8264, gan_loss: 4.0109
 55%|█████▌    | 5506/10000 [02:09<01:47, 41.78it/s]
Step: 5500, d_loss: 0.2461, Loss: 903.7646, recon_loss: 170.3498, fe_loss: 26.1392, geom_loss: 91.4499, beta_loss: 701.7339, gan_loss: 3.7127
 60%|██████    | 6006/10000 [02:20<01:33, 42.82it/s]
Step: 6000, d_loss: 0.2192, Loss: 896.4146, recon_loss: 163.2331, fe_loss: 26.1898, geom_loss: 88.4344, beta_loss: 701.5472, gan_loss: 3.6757
 65%|██████▌   | 6506/10000 [02:32<01:25, 40.75it/s]
Step: 6500, d_loss: 0.2820, Loss: 899.3956, recon_loss: 166.6798, fe_loss: 26.2029, geom_loss: 80.5115, beta_loss: 701.5717, gan_loss: 3.3311
 70%|███████   | 7006/10000 [02:44<01:08, 43.64it/s]
Step: 7000, d_loss: 0.2347, Loss: 890.3608, recon_loss: 158.0955, fe_loss: 26.1279, geom_loss: 76.1080, beta_loss: 701.5854, gan_loss: 3.0298
 75%|███████▌  | 7506/10000 [02:55<00:59, 42.17it/s]
Step: 7500, d_loss: 0.2511, Loss: 889.9950, recon_loss: 157.2804, fe_loss: 26.1080, geom_loss: 72.4438, beta_loss: 701.7313, gan_loss: 3.4264
 80%|████████  | 8006/10000 [03:07<00:45, 43.52it/s]
Step: 8000, d_loss: 0.2183, Loss: 889.2778, recon_loss: 156.7681, fe_loss: 26.1152, geom_loss: 71.1025, beta_loss: 701.6929, gan_loss: 3.2796
 85%|████████▌ | 8506/10000 [03:19<00:34, 42.71it/s]
Step: 8500, d_loss: 0.2201, Loss: 883.6912, recon_loss: 151.7068, fe_loss: 26.0463, geom_loss: 66.4949, beta_loss: 701.5209, gan_loss: 3.0872
 90%|█████████ | 9006/10000 [03:31<00:24, 41.10it/s]
Step: 9000, d_loss: 0.2291, Loss: 884.2099, recon_loss: 151.7741, fe_loss: 26.0731, geom_loss: 65.6530, beta_loss: 701.6666, gan_loss: 3.3829
 95%|█████████▌| 9506/10000 [03:42<00:11, 43.67it/s]
Step: 9500, d_loss: 0.2348, Loss: 883.2949, recon_loss: 151.3600, fe_loss: 26.0523, geom_loss: 62.8923, beta_loss: 701.4165, gan_loss: 3.2083
100%|██████████| 10000/10000 [03:54<00:00, 42.66it/s]

Access spot representations, proportions of spatial factors in spots, and gene loading matrix

After training the model, INSPIRE infers latent representations of spatial spots, spatial factors, and gene loadings using the model.eval function. This function returns two main outputs: adata_full and basis_df. The inferred latent representations of spatial spots are stored in adata_full.obsm[‘latent’], while the metadata indicating the section origin of each spot is saved in adata_full.obs. The spatial factor values assigned to individual spots are also stored in adata_full.obs, where adata_full.obs[“Proportion of spatial factor i”] contains the proportion values corresponding to spatial factor i across all analyzed spots. The inferred gene loading matrix, shared across sections, is saved in basis_df, which is a data frame with spatial factors as rows and genes as columns.

[8]:
adata_full, basis_df = model.eval(adata_st_list, adata_full)
basis = np.array(basis_df.values)
Add cell/spot proportions of spatial factors into adata_full.obs...
Add cell/spot latent representations into adata_full.obsm['latent']...
[9]:
basis_df
[9]:
Abcc4 Acp5 Acvr1 Acvr2a Adora2b Afp Ahnak Akr1c19 Alas2 Aldh1a2 ... Wnt2 Wnt2b Wnt3 Wnt3a Wnt5a Wnt5b Xist Zfp444 Zfp57 Zic3
0 0.001891 0.001366 0.002146 0.004803 0.002764 0.000217 0.010406 0.002019 0.001362 0.000272 ... 0.001283 0.004060 0.002781 0.001003 0.001812 0.001912 0.005055 0.002338 0.004687 0.000627
1 0.003183 0.002417 0.003011 0.004382 0.001082 0.000150 0.002989 0.000668 0.001464 0.000549 ... 0.000207 0.001333 0.000405 0.000318 0.001675 0.003486 0.002006 0.003549 0.002554 0.000395
2 0.004902 0.000600 0.003478 0.002555 0.002423 0.000247 0.000607 0.002346 0.000360 0.000188 ... 0.000831 0.000727 0.001466 0.000815 0.006010 0.003184 0.005976 0.004026 0.001342 0.000686
3 0.000912 0.000695 0.001673 0.003136 0.001766 0.000839 0.001595 0.004923 0.000549 0.000417 ... 0.008992 0.001814 0.001504 0.001638 0.001265 0.001916 0.002699 0.003017 0.003812 0.001313
4 0.000860 0.000530 0.001736 0.004526 0.002501 0.000344 0.002866 0.001399 0.000554 0.001668 ... 0.000276 0.001178 0.000598 0.000327 0.001315 0.002891 0.002523 0.003816 0.006548 0.003307
5 0.001532 0.000907 0.003049 0.002254 0.000339 0.000186 0.010012 0.001599 0.000365 0.000450 ... 0.011739 0.001445 0.000424 0.000426 0.005618 0.002162 0.002492 0.001161 0.004623 0.000281
6 0.001340 0.027123 0.001011 0.001217 0.000822 0.000343 0.001018 0.000870 0.032075 0.000470 ... 0.001075 0.000731 0.000899 0.000899 0.000973 0.000759 0.001524 0.001717 0.000582 0.000385
7 0.001057 0.000748 0.002722 0.001763 0.002222 0.000770 0.005217 0.002182 0.000560 0.000417 ... 0.008314 0.001125 0.001206 0.001413 0.004243 0.001064 0.002376 0.002056 0.001966 0.001516
8 0.001288 0.000757 0.002876 0.001986 0.000985 0.000337 0.000235 0.002018 0.000598 0.040546 ... 0.000919 0.001234 0.001538 0.000568 0.002146 0.002673 0.002899 0.003108 0.002873 0.000436
9 0.001699 0.000830 0.002196 0.002979 0.002057 0.000231 0.008899 0.005001 0.001022 0.000505 ... 0.001070 0.000792 0.003840 0.001498 0.003215 0.001984 0.001237 0.003833 0.001507 0.000757
10 0.001731 0.001682 0.002734 0.001823 0.001336 0.000367 0.003338 0.002492 0.000605 0.000668 ... 0.001000 0.000854 0.001700 0.001182 0.000990 0.000651 0.002297 0.001618 0.003680 0.000847
11 0.003167 0.000366 0.002607 0.004497 0.000936 0.000140 0.000403 0.000802 0.000433 0.000195 ... 0.000509 0.001600 0.010185 0.019761 0.001492 0.002182 0.003328 0.002426 0.001706 0.006896
12 0.000831 0.001052 0.003102 0.004194 0.001321 0.000355 0.000834 0.001147 0.000276 0.009252 ... 0.001238 0.001730 0.000706 0.000474 0.004099 0.002161 0.001557 0.003819 0.003493 0.018908
13 0.001001 0.000537 0.003272 0.004739 0.000433 0.000318 0.000441 0.001158 0.000237 0.000340 ... 0.000561 0.003940 0.002967 0.002766 0.008093 0.005610 0.002654 0.005844 0.001636 0.009735
14 0.003780 0.000823 0.003053 0.002454 0.002668 0.000112 0.000994 0.001389 0.000547 0.000418 ... 0.000501 0.001340 0.000911 0.000584 0.016413 0.005847 0.002365 0.006627 0.003650 0.000948
15 0.002260 0.003124 0.001896 0.005446 0.002212 0.000678 0.006268 0.006401 0.001429 0.000672 ... 0.001024 0.001725 0.002718 0.001499 0.001896 0.004019 0.004406 0.003709 0.002559 0.001929
16 0.000809 0.000398 0.002962 0.002126 0.001388 0.000122 0.002413 0.000964 0.000421 0.000384 ... 0.004666 0.001220 0.000990 0.000399 0.002794 0.002913 0.002197 0.001869 0.002338 0.000207
17 0.001279 0.002426 0.005357 0.002301 0.001675 0.057006 0.002487 0.007357 0.000868 0.000867 ... 0.002189 0.001427 0.001068 0.000683 0.000765 0.001902 0.002651 0.003763 0.002250 0.000579
18 0.001737 0.001507 0.002164 0.003994 0.003465 0.000995 0.000549 0.005668 0.001914 0.000373 ... 0.001244 0.001375 0.002700 0.001576 0.001211 0.000876 0.002931 0.003631 0.001746 0.001963
19 0.001879 0.000655 0.001942 0.005235 0.004204 0.000143 0.005212 0.003036 0.001646 0.000230 ... 0.000539 0.002247 0.001090 0.000544 0.007391 0.004214 0.002895 0.003082 0.004702 0.000887
20 0.003214 0.001942 0.002438 0.002562 0.000483 0.000137 0.004137 0.000827 0.000731 0.000222 ... 0.000828 0.002340 0.007363 0.032066 0.000778 0.004229 0.001176 0.004002 0.004859 0.030024
21 0.001447 0.001041 0.002271 0.001449 0.001502 0.001549 0.002921 0.004316 0.000755 0.000455 ... 0.000543 0.001693 0.002291 0.000912 0.001149 0.001605 0.001703 0.004567 0.001377 0.001328
22 0.002555 0.000866 0.002141 0.005424 0.001019 0.000225 0.000489 0.005923 0.000619 0.000324 ... 0.000679 0.004510 0.001501 0.000830 0.002019 0.008841 0.003899 0.005046 0.001596 0.004279
23 0.001866 0.002413 0.003193 0.001704 0.004192 0.000111 0.013522 0.000331 0.003425 0.000319 ... 0.000341 0.001699 0.001133 0.001539 0.000988 0.003211 0.001061 0.002296 0.001893 0.002525
24 0.002995 0.000405 0.002249 0.003377 0.001469 0.000149 0.000959 0.001653 0.000470 0.000209 ... 0.000706 0.000790 0.000701 0.000605 0.002988 0.002924 0.001640 0.004695 0.003868 0.000563
25 0.006822 0.001068 0.001631 0.003223 0.001621 0.000303 0.002495 0.003249 0.000634 0.003525 ... 0.001089 0.001866 0.001219 0.000927 0.002491 0.003716 0.004975 0.008303 0.003237 0.000480
26 0.001232 0.000865 0.001737 0.000964 0.001881 0.000205 0.000842 0.001223 0.000408 0.001893 ... 0.001134 0.001148 0.001016 0.000617 0.000831 0.001163 0.002253 0.001762 0.003295 0.000916
27 0.001632 0.000963 0.002545 0.003741 0.002016 0.000161 0.003016 0.002040 0.000504 0.000191 ... 0.000671 0.000552 0.000618 0.000315 0.003914 0.001268 0.002297 0.004421 0.002323 0.000438
28 0.001044 0.000878 0.001356 0.000682 0.000644 0.000175 0.031114 0.001534 0.000844 0.000163 ... 0.003590 0.004340 0.001056 0.001455 0.004607 0.001219 0.000744 0.001378 0.001118 0.000513
29 0.000764 0.000551 0.002136 0.002169 0.001185 0.000237 0.000593 0.005202 0.000336 0.016792 ... 0.001304 0.001373 0.001166 0.001748 0.008200 0.003369 0.002557 0.003931 0.002888 0.000286
30 0.002445 0.000769 0.001065 0.002443 0.001933 0.000366 0.002514 0.005280 0.000435 0.007416 ... 0.000819 0.004649 0.002180 0.001244 0.010177 0.001059 0.004682 0.004578 0.002477 0.001315
31 0.001232 0.001937 0.001890 0.004328 0.000917 0.000538 0.005511 0.004348 0.000418 0.000213 ... 0.002603 0.003434 0.001291 0.001248 0.003663 0.002178 0.005222 0.002843 0.002514 0.000831
32 0.002137 0.000898 0.004264 0.005771 0.000868 0.000680 0.000874 0.000611 0.000658 0.000337 ... 0.000494 0.000854 0.002000 0.001049 0.000481 0.000852 0.001633 0.003443 0.002517 0.002292
33 0.005397 0.000433 0.003048 0.004035 0.001920 0.000203 0.000263 0.003862 0.000423 0.000468 ... 0.001010 0.000566 0.001718 0.000340 0.001793 0.010490 0.002119 0.004648 0.001898 0.014962
34 0.002471 0.001630 0.006478 0.002972 0.002530 0.000552 0.001293 0.000616 0.000842 0.000464 ... 0.001677 0.001442 0.001274 0.000907 0.000967 0.008255 0.001441 0.002773 0.004622 0.001387
35 0.002488 0.002157 0.002969 0.003047 0.000747 0.001007 0.000770 0.000437 0.000334 0.014770 ... 0.000810 0.000964 0.000810 0.002517 0.000800 0.001824 0.001311 0.002872 0.001096 0.001127
36 0.000609 0.002343 0.006526 0.002191 0.000434 0.000558 0.002223 0.000924 0.000708 0.000572 ... 0.004664 0.000579 0.000662 0.000248 0.003463 0.000928 0.001550 0.001739 0.002264 0.000209
37 0.019623 0.001587 0.002778 0.003041 0.001801 0.000373 0.000391 0.000883 0.000321 0.000282 ... 0.001410 0.000724 0.001440 0.001443 0.004026 0.006185 0.004489 0.004326 0.002361 0.001828
38 0.001220 0.006874 0.001400 0.002273 0.000631 0.000157 0.012084 0.001513 0.004599 0.019365 ... 0.016859 0.000850 0.001107 0.000362 0.000793 0.002272 0.000849 0.002893 0.001685 0.000210
39 0.001590 0.000357 0.003080 0.005897 0.001891 0.000161 0.000612 0.000347 0.000420 0.000233 ... 0.000512 0.000804 0.001405 0.000278 0.002522 0.002951 0.002390 0.004272 0.003145 0.000332

40 rows × 344 columns

Spatial distributions of spatial factors in tissues

The proportion values corresponding to spatial factors across all analyzed spots are stored in adata_full.obs. These spatial patterns can be visualized using the sc.pl.spatial function from the Scanpy pipeline. The spot_size parameter controls the size of each spatial spot in the resulting plots.

[10]:
sc.pl.spatial(adata_full, color=["Proportion of spatial factor "+str(i+1) for i in range(40)], spot_size=1.)
../_images/examples_INSPIRE_LGCN_26_0.png

Spot representations and spatial domain identification

To visualize the spot representations learned by INSPIRE, we employ UMAP plots. The UMAP embedding is generated by first constructing a UMAP model using umap.UMAP, and then transforming the spot representations into two-dimensional coordinates using the fit_transform function from the umap package.

[11]:
reducer = umap.UMAP(n_neighbors=30,
                    n_components=2,
                    metric="correlation",
                    n_epochs=None,
                    learning_rate=1.0,
                    min_dist=0.3,
                    spread=1.0,
                    set_op_mix_ratio=1.0,
                    local_connectivity=1,
                    repulsion_strength=1,
                    negative_sample_rate=5,
                    a=None,
                    b=None,
                    random_state=1234,
                    metric_kwds=None,
                    angular_rp_forest=False,
                    verbose=True)
embedding = reducer.fit_transform(adata_full.obsm['latent'])
adata_full.obsm["X_umap"] = embedding
adata_full.obs["slice"] = adata_full.obs["slice"].values.astype(str)
UMAP(angular_rp_forest=True, local_connectivity=1, metric='correlation', min_dist=0.3, n_neighbors=30, random_state=1234, repulsion_strength=1, verbose=True)
Wed May 28 19:41:28 2025 Construct fuzzy simplicial set
Wed May 28 19:41:28 2025 Finding Nearest Neighbors
Wed May 28 19:41:28 2025 Building RP forest with 12 trees
Wed May 28 19:41:30 2025 NN descent for 14 iterations
         1  /  14
         2  /  14
         3  /  14
        Stopping threshold met -- exiting after 3 iterations
Wed May 28 19:41:40 2025 Finished Nearest Neighbor Search
Wed May 28 19:41:42 2025 Construct embedding
        completed  0  /  200 epochs
        completed  20  /  200 epochs
        completed  40  /  200 epochs
        completed  60  /  200 epochs
        completed  80  /  200 epochs
        completed  100  /  200 epochs
        completed  120  /  200 epochs
        completed  140  /  200 epochs
        completed  160  /  200 epochs
        completed  180  /  200 epochs
Wed May 28 19:42:02 2025 Finished embedding

For visualizing UMAP plots, we utilizes the sc.pl.umap function from the Scanpy pipeline.

[12]:
sc.pl.umap(adata_full, color=["slice"])
../_images/examples_INSPIRE_LGCN_31_0.png

The learned spot representations enable the identification of spatial domains. When the number of spatial domains is known a priori, clustering is performed using a Gaussian Mixture Model implemented in the sklearn package. In the absence of such prior knowledge, spatial domains are identified using the Louvain clustering algorithm, implemented through the sc.pp.neighbors and sc.tl.louvain functions in the Scanpy package.

[13]:
sc.pp.neighbors(adata_full, use_rep="latent", n_neighbors=30)
sc.tl.louvain(adata_full, resolution=.7)

Spatial domain assignments are visualized on both the UMAP embedding and the spatial coordinates of the spots using the sc.pl.umap and sc.pl.spatial functions from the Scanpy pipeline, respectively.

[14]:
sc.pl.umap(adata_full, color=["louvain"])
sc.pl.spatial(adata_full, color=["louvain"], spot_size=1.)
../_images/examples_INSPIRE_LGCN_35_0.png
../_images/examples_INSPIRE_LGCN_35_1.png

Finally, we save the results from INSPIRE.

[15]:
res_path = "/gpfs/gibbs/pi/zhao/jz874/project/jiazhao/inspire_revision/tutorials/example_analyses/example_LGCN_data"
adata_full.write(res_path + "/adata_full_inspire.h5ad")
basis_df.to_csv(res_path + "/basis_df_inspire.csv")
[ ]: