├── AnalysisPaper ├── README.md ├── figures │ ├── figure1.Rmd │ ├── figure1.html │ ├── figure2.Rmd │ ├── figure2.html │ ├── figure3.Rmd │ ├── figure3.html │ ├── figure4.Rmd │ ├── figure4.html │ ├── figure5.Rmd │ ├── figure5.html │ ├── figure6.Rmd │ └── figure6.html ├── output │ ├── figure1 │ │ ├── all_res.csv │ │ └── sub_res.csv │ ├── figure2 │ │ ├── DEGs_slice151673.csv │ │ ├── DEGs_starmap.csv │ │ ├── distance_to_l1_151507_original.csv │ │ ├── distance_to_l1_151507_pseudo.csv │ │ ├── distance_to_l1_151508_original.csv │ │ ├── distance_to_l1_151508_pseudo.csv │ │ ├── distance_to_l1_151509_original.csv │ │ ├── distance_to_l1_151509_pseudo.csv │ │ ├── distance_to_l1_151510_original.csv │ │ ├── distance_to_l1_151510_pseudo.csv │ │ ├── distance_to_l1_151669_original.csv │ │ ├── distance_to_l1_151669_pseudo.csv │ │ ├── distance_to_l1_151670_original.csv │ │ ├── distance_to_l1_151670_pseudo.csv │ │ ├── distance_to_l1_151671_original.csv │ │ ├── distance_to_l1_151671_pseudo.csv │ │ ├── distance_to_l1_151672_original.csv │ │ ├── distance_to_l1_151672_pseudo.csv │ │ ├── distance_to_l1_151673_original.csv │ │ ├── distance_to_l1_151673_pseudo.csv │ │ ├── distance_to_l1_151674_original.csv │ │ ├── distance_to_l1_151674_pseudo.csv │ │ ├── distance_to_l1_151675_original.csv │ │ ├── distance_to_l1_151675_pseudo.csv │ │ ├── distance_to_l1_151676_original.csv │ │ ├── distance_to_l1_151676_pseudo.csv │ │ ├── distance_to_l1_starmap_original.csv │ │ ├── distance_to_l1_starmap_pseudo.csv │ │ ├── pairwise_distance_cor_DLPFC.csv │ │ └── pairwise_distance_cor_STARmap.csv │ ├── figure3 │ │ ├── ARI_for_different_cluster_numbers.csv │ │ ├── Clustering_result_for_cardiomyocytes.csv │ │ └── DEGs_for_three_clusters_scSpace.csv │ ├── figure4 │ │ └── ARI_all.csv │ ├── figure5 │ │ ├── DEGs_between_C3_C5.csv │ │ ├── GSEA_result.csv │ │ ├── RCTD_m1.csv │ │ └── RCTD_m2.csv │ └── figure6 │ │ ├── DEGs_between_MDM_subcluster.csv │ │ ├── DSP_limma_result.csv │ │ ├── Dist_change_ratio.csv │ │ ├── MT_gene_average_expression.csv │ │ ├── non_MT_gene_average_expression.csv │ │ └── ssGSEA_result.csv └── scripts │ ├── constructSimulations.R │ ├── figure1 │ ├── BayesSpace_DRSC_simulation.R │ ├── SpaGCN_STAGATE_simulation.ipynb │ ├── scCoGAPS_simulation.ipynb │ └── scSpace_simulation.ipynb │ ├── figure2 │ ├── DLPFC_aggregate.R │ ├── DLPFC_validate.ipynb │ └── STARmap.ipynb │ ├── figure3 │ ├── human_heart.ipynb │ └── human_heart_spatial_informed_clustering.R │ ├── figure4 │ └── hodge.ipynb │ ├── figure5 │ ├── melanoma.ipynb │ └── melanoma_validation.ipynb │ ├── figure6 │ ├── COVID19.ipynb │ └── MDM_spatial_informed_clustering.R │ └── utils.R ├── LICENSE ├── README.md ├── images └── workflow.jpg ├── requirements.txt ├── scSpace ├── __init__.py ├── models.py ├── scspace.py └── utils.py ├── setup.py └── vignettes ├── DLPFC_slice151674.ipynb ├── SCC_p2.ipynb ├── data ├── demo_sc_data.csv ├── demo_sc_meta.csv ├── demo_st_data.csv └── demo_st_meta.csv ├── demo.ipynb ├── intestines.ipynb └── melanoma.ipynb /AnalysisPaper/README.md: -------------------------------------------------------------------------------- 1 | # scSpace reproducibility 2 | Code to reproduce the analysis and figures in the paper [Reconstruction of the cell pseudo-space from 3 | single-cell RNA sequencing data with scSpace](https://www.biorxiv.org/content/10.1101/2022.05.07.491043v1). The scSpace 4 | python package is located [here](https://github.com/ZJUFanLab/scSpace). 5 | 6 | ## Obtaining Datasets 7 | The data used and/or generated in this study can be found on [Google Drive](https://drive.google.com/drive/folders/1_9qS78yDi0agT4x5HQuldg3I1a2WWdYc?usp=sharing). 8 | 9 | ## Running scSpace 10 | The analysis scripts to produced scSpace results can be accessed [here](scripts). For example, the script 11 | [constructSimulations.R](scripts/constructSimulations.R) is used to generate simulated scRNA-seq and spatial transcriptomics 12 | data in benchmarking step. 13 | 14 | ## Generating Main Figures 15 | We provide R Markdown files that were used to create the main figures, 16 | the results consistent with the figures can be accessed [here](output): 17 | * [Performance of scSpace compared with other methods on simulated datasets](https://raw.githack.com/ZJUFanLab/scSpace/master/AnalysisPaper/figures/figure1.html) (Figure 1) 18 | * [Validation of scSpace on human DLPFC 10x Visium data](https://raw.githack.com/ZJUFanLab/scSpace/master/AnalysisPaper/figures/figure2.html) (Figure 2) 19 | * [Validation of scSpace on mouse primary visual cortex STARmap data](https://raw.githack.com/ZJUFanLab/scSpace/master/AnalysisPaper/figures/figure2.html) (Figure 2) 20 | * [Validation of scSpace on human embryonic heart scRNA-seq data](https://raw.githack.com/ZJUFanLab/scSpace/master/AnalysisPaper/figures/figure3.html) (Figure 3) 21 | * [Validation of scSpace on human MTG scRNA-seq data](https://raw.githack.com/ZJUFanLab/scSpace/master/AnalysisPaper/figures/figure4.html) (Figure 4) 22 | * [Application of scSpace on human melanoma scRNA-seq data](https://raw.githack.com/ZJUFanLab/scSpace/master/AnalysisPaper/figures/figure5.html) (Figure 5) 23 | * [Application of scSpace on human COVID-19 scRNA-seq data](https://raw.githack.com/ZJUFanLab/scSpace/master/AnalysisPaper/figures/figure6.html) (Figure 6) 24 | 25 | 26 | -------------------------------------------------------------------------------- /AnalysisPaper/figures/figure1.Rmd: -------------------------------------------------------------------------------- 1 | 2 | ```{r setup, include=FALSE} 3 | knitr::opts_chunk$set(echo = TRUE) 4 | ``` 5 | 6 | # Benckmark scSpace with other methods on 140 simulated datasets 7 | ```{r} 8 | library(ggplot2) 9 | library(ggthemes) 10 | library(ggsignif) 11 | library(mclust) 12 | library(RColorBrewer) 13 | ``` 14 | 15 | 16 | ### Load data 17 | ```{r} 18 | # Ground Truth 19 | sim_gt <- readRDS('../data/simulation/sim_groundtruth.RDS') 20 | # scSpace 21 | sim_scspace <- readRDS('../data/simulation/sim_scSpace.RDS') 22 | # Louvain 23 | sim_louvain <- readRDS('../data/simulation/sim_louvain.RDS') 24 | # K-means 25 | sim_kmeans <- readRDS('../data/simulation/sim_kmeans.RDS') 26 | # Hierarchical clustering 27 | sim_hclust <- readRDS('../data/simulation/sim_hclust.RDS') 28 | # scCoGAPS 29 | sim_sccogaps <- readRDS('../data/simulation/sim_scCoGAPS.RDS') 30 | # DR.SC 31 | sim_drsc <- readRDS('../data/simulation/sim_DRSC.RDS') 32 | # BayesSpace 33 | sim_bayesspace <- readRDS('../data/simulation/sim_BayesSpace.RDS') 34 | # SpaGCN 35 | sim_spagcn <- readRDS('../data/simulation/sim_SpaGCN.RDS') 36 | # STAGATE 37 | sim_stagate <- readRDS('../data/simulation/sim_STAGATE.RDS') 38 | ``` 39 | 40 | ### Set output dir 41 | ```{r} 42 | output_dir <- '../output/figure1' 43 | if(!dir.exists(output_dir)){ 44 | dir.create(output_dir) 45 | } else { 46 | print('Dir already exists!') 47 | } 48 | ``` 49 | 50 | ### Calculate ARI of all celltypes 51 | ```{r} 52 | all_res <- data.frame() 53 | for (i in 1:140) { 54 | scspace_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_scspace[[i]]$scSpace) 55 | louvain_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_louvain[[i]]$louvain) 56 | kmeans_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_kmeans[[i]]$kmeans) 57 | hclust_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_hclust[[i]]$hclust) 58 | sccogaps_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_sccogaps[[i]]$scCoGAPS) 59 | drsc_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_drsc[[i]]$spatial.drsc.cluster) 60 | bayesspace_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_bayesspace[[i]]$spatial.cluster) 61 | spagcn_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_spagcn[[i]]$SpaGCN) 62 | stagate_tmp <- adjustedRandIndex(sim_gt[[i]]$Group, sim_stagate[[i]]$STAGATE) 63 | 64 | res_tmp <- data.frame( 65 | simulation = names(sim_gt)[i], 66 | ARI = c(scspace_tmp, louvain_tmp, kmeans_tmp, hclust_tmp, sccogaps_tmp, 67 | drsc_tmp, bayesspace_tmp, spagcn_tmp, stagate_tmp), 68 | method = c('scSpace', 'louvain', 'kmeans', 'hclust', 'scCoGAPS', 69 | 'DR.SC', 'BayesSpace', 'SpaGCN', 'STAGATE') 70 | ) 71 | 72 | all_res <- rbind(all_res, res_tmp) 73 | } 74 | 75 | write.csv(all_res, file = paste0(output_dir, '/all_res.csv')) 76 | ``` 77 | 78 | ### Plot boxplot of ARI for all celltypes 79 | ```{r fig.height = 4, fig.width = 6, fig.align = 'center'} 80 | all_res$method <- factor(all_res$method, levels = c('scSpace', 'louvain', 'kmeans', 'STAGATE', 'BayesSpace', 'DR.SC', 'scCoGAPS', 'SpaGCN', 'hclust')) 81 | 82 | p <- ggplot(all_res, aes(method, ARI, fill = method)) + 83 | geom_boxplot() + 84 | scale_fill_manual(values = c('#984EA3', '#4DAF4A', '#377EB8', '#FFFF33','#A65628', 85 | '#F781BF', '#10B981', '#999999', '#E41A1C')) + 86 | theme_classic() + 87 | geom_signif( 88 | comparisons = list(c('scSpace', 'louvain'),c('scSpace', 'kmeans'), c('scSpace', 'STAGATE'), 89 | c('scSpace', 'BayesSpace'), c('scSpace', 'DR.SC'),c('scSpace', 'scCoGAPS'), 90 | c('scSpace', 'SpaGCN'), c('scSpace', 'hclust')), 91 | test = 'wilcox.test', 92 | step_increase = 0.1) + 93 | theme(axis.text.x = element_text(angle = 45, hjust = 0.5, vjust = 0.5)) 94 | 95 | p 96 | ``` 97 | 98 | ### Calculate ARI of all celltypes 99 | ```{r} 100 | sub_res <- data.frame() 101 | for (i in 1:140) { 102 | 103 | if(i %in% c(1, 4, 7, 11, 14, 17, 21, 24, 27, 31, 34, 37, 41, 44, 47)){ 104 | subcluster_num <- 2 105 | } else if(i %in% c(2, 5, 8, 9, 12, 15, 18, 19, 22, 25, 28, 29, 32, 35, 38, 39, 42, 45, 48, 49)){ 106 | subcluster_num <- 3 107 | } else if(i %in% c(3, 6, 10, 13, 16, 20, 23, 26, 30, 33, 36, 40, 43, 46, 50)){ 108 | subcluster_num <- 4 109 | } else if(i %in% c(51:65)){ 110 | subcluster_num <- 5 111 | } else if(i %in% c(66:80)){ 112 | subcluster_num <- 6 113 | } else if(i %in% c(81:95)){ 114 | subcluster_num <- 7 115 | } else if(i %in% c(96:110)){ 116 | subcluster_num <- 8 117 | } else if(i %in% c(111:125)){ 118 | subcluster_num <- 9 119 | } else if(i %in% c(126:140)){ 120 | subcluster_num <- 10 121 | } 122 | 123 | cluster_num <- length(unique(sim_gt[[i]]$Group)) 124 | 125 | subcluster_name <- paste0('Group', (1 + cluster_num - subcluster_num):cluster_num) 126 | 127 | 128 | scspace_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_scspace[[i]][sim_scspace[[i]]$Group %in% subcluster_name, ]$scSpace) 129 | louvain_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_louvain[[i]][sim_louvain[[i]]$Group %in% subcluster_name, ]$louvain) 130 | kmeans_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_kmeans[[i]][sim_kmeans[[i]]$Group %in% subcluster_name, ]$kmeans) 131 | hclust_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_hclust[[i]][sim_hclust[[i]]$Group %in% subcluster_name, ]$hclust) 132 | sccogaps_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_sccogaps[[i]][sim_sccogaps[[i]]$Group %in% subcluster_name, ]$scCoGAPS) 133 | drsc_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_drsc[[i]][sim_drsc[[i]]$Group %in% subcluster_name, ]$spatial.drsc.cluster) 134 | bayesspace_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_bayesspace[[i]][sim_bayesspace[[i]]$Group %in% subcluster_name, ]$spatial.cluster) 135 | spagcn_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_spagcn[[i]][sim_spagcn[[i]]$Group %in% subcluster_name, ]$SpaGCN) 136 | stagate_tmp <- adjustedRandIndex(sim_gt[[i]][sim_gt[[i]]$Group %in% subcluster_name, ]$Group, sim_stagate[[i]][sim_stagate[[i]]$Group %in% subcluster_name, ]$STAGATE) 137 | 138 | res_tmp <- data.frame( 139 | simulation = names(sim_gt)[i], 140 | subcluster_num = subcluster_num, 141 | ARI = c(scspace_tmp, louvain_tmp, kmeans_tmp, hclust_tmp, sccogaps_tmp, 142 | drsc_tmp, bayesspace_tmp, spagcn_tmp, stagate_tmp), 143 | method = c('scSpace', 'louvain', 'kmeans', 'hclust', 'scCoGAPS', 144 | 'DR.SC', 'BayesSpace', 'SpaGCN', 'STAGATE') 145 | ) 146 | 147 | sub_res <- rbind(sub_res, res_tmp) 148 | } 149 | 150 | write.csv(sub_res, file = paste0(output_dir, '/sub_res.csv')) 151 | ``` 152 | 153 | ### Plot boxplot of ARI for spatial subclusters 154 | ```{r fig.height = 4, fig.width = 10, fig.align = 'center'} 155 | sub_res$method <- factor(sub_res$method, levels = c('scSpace', 'louvain', 'kmeans', 'STAGATE', 'BayesSpace', 'DR.SC', 'scCoGAPS', 'SpaGCN', 'hclust')) 156 | 157 | p <- ggplot(sub_res, aes(as.factor(subcluster_num), ARI, fill = method)) + 158 | geom_boxplot() + 159 | scale_fill_manual(values = c('#984EA3', '#4DAF4A', '#377EB8', '#FFFF33','#A65628', 160 | '#F781BF', '#10B981', '#999999', '#E41A1C')) + 161 | theme_classic() 162 | 163 | p 164 | ``` 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /AnalysisPaper/figures/figure5.Rmd: -------------------------------------------------------------------------------- 1 | 2 | ```{r setup, include=FALSE} 3 | knitr::opts_chunk$set(echo = TRUE) 4 | ``` 5 | 6 | # Sptial analysis of T cell subpopulations in melanoma 7 | ```{r} 8 | library(Seurat) 9 | library(ggplot2) 10 | library(ggthemes) 11 | library(ggsignif) 12 | library(cowplot) 13 | library(dplyr) 14 | library(ggpubr) 15 | library(viridis) 16 | library(cgdsr) 17 | library(survival) 18 | library(survminer) 19 | library(msigdbr) 20 | library(fgsea) 21 | library(tidyverse) 22 | library(spacexr) 23 | library(scatterpie) 24 | library(ggrepel) 25 | ``` 26 | 27 | 28 | ### Load data 29 | ```{r} 30 | # Ground Truth 31 | load('../data/melanoma/melanoma.RDS') 32 | ``` 33 | 34 | ### Load custom functions 35 | ```{r} 36 | source('../scripts/utils.R') 37 | ``` 38 | 39 | ### Set output dir 40 | ```{r} 41 | output_dir <- '../output/figure5' 42 | if(!dir.exists(output_dir)){ 43 | dir.create(output_dir) 44 | } else { 45 | print('Dir already exists!') 46 | } 47 | ``` 48 | 49 | ### Comparing the pseudo space of T subpopulations consturcted from different ST reference 50 | ```{r fig.height = 8, fig.width = 10, fig.align = 'center'} 51 | sc_meta$scSpace <- sc_meta$Cell_type 52 | sc_meta[sc_meta$Cell_type == 'T cell', ]$scSpace <- paste0('c', (tcell_scspace_sub$scSpace + 1)) 53 | sc_meta$m1_pseudo_space1 <- m1_pseudo_space[, 1] 54 | sc_meta$m1_pseudo_space2 <- m1_pseudo_space[, 2] 55 | sc_meta$m2_pseudo_space1 <- m2_pseudo_space[, 1] 56 | sc_meta$m2_pseudo_space2 <- m2_pseudo_space[, 2] 57 | sc_meta[sc_meta$Cell_type != 'T cell' & sc_meta$Cell_type != 'malignant', ]$scSpace <- 'Others' 58 | 59 | # calculate distance between T subpopulations and malignant 60 | sc_sub <- sc_meta[sc_meta$scSpace != 'Others', ] 61 | m1_dist <- cal_dist( 62 | meta = sc_sub, 63 | coord_index = c('m1_pseudo_space1', 'm1_pseudo_space2'), 64 | group_by = 'scSpace', 65 | selected_type = 'malignant', 66 | ignore_select_type = TRUE) 67 | m2_dist <- cal_dist( 68 | meta = sc_sub, 69 | coord_index = c('m2_pseudo_space1', 'm2_pseudo_space2'), 70 | group_by = 'scSpace', 71 | selected_type = 'malignant', 72 | ignore_select_type = TRUE) 73 | 74 | # m1 reference 75 | p1 <- ggplot() + 76 | geom_point(sc_meta[sc_meta$scSpace == 'Others', ], mapping = aes(m1_pseudo_space1, m1_pseudo_space2, color = scSpace), size = 2.5, color = 'grey90') + 77 | geom_point(sc_meta[sc_meta$Cell_type == 'malignant', ], mapping = aes(m1_pseudo_space1, m1_pseudo_space2, color = scSpace), size = 2.5) + 78 | geom_point(sc_meta[sc_meta$Cell_type == 'T cell', ], mapping = aes(m1_pseudo_space1, m1_pseudo_space2, color = scSpace), size = 2.5) + 79 | scale_color_manual(values = c('#3B82F6', '#EF4444', '#854D0E', '#EAB308', '#10B981', '#F97316')) + 80 | ggtitle('Pseudo space (m1)') + 81 | theme(plot.title = element_text(hjust = 0.5)) + 82 | theme_classic() 83 | 84 | m1_dist$group <- factor(m1_dist$group, levels = c('malignant_c5', 'malignant_c4', 'malignant_c2', 'malignant_c1', 'malignant_c3')) 85 | p2 <- ggplot(data=m1_dist, aes(x=group, y=dist, fill=group)) + 86 | geom_boxplot(outlier.shape = NA) + 87 | scale_fill_manual(values = c('#10B981', '#EAB308', '#EF4444', '#3B82F6', '#854D0E')) + 88 | geom_signif(comparisons = list(c('malignant_c5', 'malignant_c4'), 89 | c('malignant_c5', 'malignant_c2'), 90 | c('malignant_c5', 'malignant_c1'), 91 | c('malignant_c5', 'malignant_c3')), 92 | test = "wilcox.test", step_increase=0.1) + 93 | theme_classic() + 94 | ggtitle('Distance to malignant (m1)') + 95 | theme(plot.title = element_text(hjust = 0.5)) 96 | 97 | # m2 reference 98 | p3 <- ggplot() + 99 | geom_point(sc_meta[sc_meta$scSpace == 'Others', ], mapping = aes(m2_pseudo_space1, m2_pseudo_space2, color = scSpace), size = 2.5, color = 'grey90') + 100 | geom_point(sc_meta[sc_meta$Cell_type == 'malignant', ], mapping = aes(m2_pseudo_space1, m2_pseudo_space2, color = scSpace), size = 2.5) + 101 | geom_point(sc_meta[sc_meta$Cell_type == 'T cell', ], mapping = aes(m2_pseudo_space1, m2_pseudo_space2, color = scSpace), size = 2.5) + 102 | scale_color_manual(values = c('#3B82F6', '#EF4444', '#854D0E', '#EAB308', '#10B981', '#F97316')) + 103 | ggtitle('Pseudo space (m2)') + 104 | theme(plot.title = element_text(hjust = 0.5)) + 105 | theme_classic() 106 | 107 | 108 | m2_dist$group <- factor(m2_dist$group, levels = c('malignant_c5', 'malignant_c4', 'malignant_c2', 'malignant_c1', 'malignant_c3')) 109 | p4 <- ggplot(data=m2_dist, aes(x=group, y=dist, fill=group)) + 110 | geom_boxplot(outlier.shape = NA) + 111 | scale_fill_manual(values = c('#10B981', '#EAB308', '#EF4444', '#3B82F6', '#854D0E')) + 112 | geom_signif(comparisons = list(c('malignant_c5', 'malignant_c4'), 113 | c('malignant_c5', 'malignant_c2'), 114 | c('malignant_c5', 'malignant_c1'), 115 | c('malignant_c5', 'malignant_c3')), 116 | test = "wilcox.test", step_increase=0.1) + 117 | theme_classic() + 118 | ggtitle('Distance to malignant (m2)') + 119 | theme(plot.title = element_text(hjust = 0.5)) 120 | 121 | cowplot::plot_grid(p1, p2, p3, p4) 122 | 123 | ``` 124 | 125 | ### Compared with Seurat 126 | ```{r fig.height = 8, fig.width = 10, fig.align = 'center'} 127 | tcell_meta <- sc_meta[sc_meta$Cell_type == 'T cell', ] 128 | tcell_data <- sc_data[, rownames(tcell_meta)] 129 | 130 | # run seurat 131 | sc_obj <- run_Seurat(sc_meta = tcell_meta, 132 | sc_data = tcell_data, 133 | res = 0.36) 134 | 135 | p1 <- DimPlot(sc_obj, pt.size = 1.5, group.by = 'scSpace', cols = c('#3B82F6', '#EF4444', '#854D0E', '#EAB308', '#10B981')) 136 | p2 <- VlnPlot(sc_obj, group.by = 'scSpace', features = c('TK1', 'AURKB', 'BIRC5', 'KIFC1', 'MKI67'), pt.size = 0, cols = c('#3B82F6', '#EF4444', '#854D0E', '#EAB308', '#10B981')) 137 | p3 <- DimPlot(sc_obj, pt.size = 1.5, group.by = 'seurat_clusters', cols = c('#EF4444', '#3B82F6', '#10B981', '#EAB308', '#854D0E')) 138 | p4 <- VlnPlot(sc_obj, group.by = 'seurat_clusters', features = c('TK1', 'AURKB', 'BIRC5', 'KIFC1', 'MKI67'), pt.size = 0, cols = c('#EF4444', '#3B82F6', '#10B981', '#EAB308', '#854D0E')) 139 | 140 | cowplot::plot_grid(p1, p2, p3, p4) 141 | 142 | ``` 143 | 144 | ### RCTD results of m1 / m2 ST reference 145 | ```{r fig.height = 5, fig.width = 10, fig.align = 'center'} 146 | st_m1 <- CreateSeuratObject(m1_st_data, meta.data = m1_st_meta) 147 | st_m1 <- NormalizeData(st_m1) 148 | st_m2 <- CreateSeuratObject(m2_st_data, meta.data = m2_st_meta) 149 | st_m2 <- NormalizeData(st_m2) 150 | 151 | 152 | sc_meta[sc_meta$Cell_type == 'T cell', ]$Cell_type <- sc_meta[sc_meta$Cell_type == 'T cell', ]$scSpace 153 | res1 <- run_RCTD(sc_meta = sc_meta, sc_data = sc_data, st_meta = m1_st_meta, st_data = st_m1@assays$RNA@data, celltype_index = 'Cell_type') 154 | res2 <- run_RCTD(sc_meta = sc_meta, sc_data = sc_data, st_meta = m2_st_meta, st_data = st_m2@assays$RNA@data, celltype_index = 'Cell_type') 155 | 156 | res1$xcoord <- m1_st_meta[rownames(res1), ]$xcoord 157 | res1$ycoord <- m1_st_meta[rownames(res1), ]$ycoord 158 | res2$xcoord <- m2_st_meta[rownames(res2), ]$xcoord 159 | res2$ycoord <- m2_st_meta[rownames(res2), ]$ycoord 160 | 161 | write.csv(res1, file = paste0(output_dir, '/RCTD_m1.csv')) 162 | write.csv(res1, file = paste0(output_dir, '/RCTD_m2.csv')) 163 | 164 | colors = c('grey90', '#3B82F6', "#EF4444", "#854D0E", "#EAB308", "#10B981", 'grey90', 'grey90', 'grey90', 165 | '#F97316', 'grey90') 166 | 167 | 168 | p1 <- ggplot() + 169 | geom_scatterpie( 170 | aes(ycoord, xcoord, r=0.5), 171 | data = res1, cols = colnames(res1)[1:(ncol(res1) - 2)], 172 | size = 7, color =NA) + 173 | scale_fill_manual(values = colors) + 174 | coord_fixed() + 175 | theme_classic() 176 | 177 | p2 <- ggplot() + 178 | geom_scatterpie( 179 | aes(ycoord, xcoord, r=0.5), 180 | data = res2, cols = colnames(res1)[1:(ncol(res1) - 2)], 181 | size = 7, color =NA) + 182 | scale_fill_manual(values = colors) + 183 | coord_fixed() + 184 | theme_classic() 185 | 186 | cowplot::plot_grid(p1, p2) 187 | 188 | ``` 189 | 190 | ### C3, C5, and malignant proportions 191 | ```{r fig.height = 6, fig.width = 10, fig.align = 'center'} 192 | p1 <- ggplot(res1) + 193 | geom_point(aes(ycoord, xcoord, color = malignant), size = 2) + 194 | scale_color_viridis() + 195 | coord_fixed() + 196 | theme_classic() + 197 | ggtitle('malignant (m1)') + 198 | theme(plot.title = element_text(hjust = 0.5)) 199 | 200 | p2 <- ggplot(res1) + 201 | geom_point(aes(ycoord, xcoord, color = c5), size = 2) + 202 | scale_color_viridis() + 203 | coord_fixed() + 204 | theme_classic() + 205 | ggtitle('C5 (m1)') + 206 | theme(plot.title = element_text(hjust = 0.5)) 207 | 208 | p3 <- ggplot(res1) + 209 | geom_point(aes(ycoord, xcoord, color = c3), size = 2) + 210 | scale_color_viridis() + 211 | coord_fixed() + 212 | theme_classic() + 213 | ggtitle('C3 (m1)') + 214 | theme(plot.title = element_text(hjust = 0.5)) 215 | 216 | p4 <- ggplot(res2) + 217 | geom_point(aes(ycoord, xcoord, color = malignant), size = 2) + 218 | scale_color_viridis() + 219 | coord_fixed() + 220 | theme_classic() + 221 | ggtitle('malignant (m2)') + 222 | theme(plot.title = element_text(hjust = 0.5)) 223 | 224 | p5 <- ggplot(res2) + 225 | geom_point(aes(ycoord, xcoord, color = c5), size = 2) + 226 | scale_color_viridis() + 227 | coord_fixed() + 228 | theme_classic() + 229 | ggtitle('C5 (m2)') + 230 | theme(plot.title = element_text(hjust = 0.5)) 231 | 232 | p6 <- ggplot(res2) + 233 | geom_point(aes(ycoord, xcoord, color = c3), size = 2) + 234 | scale_color_viridis() + 235 | coord_fixed() + 236 | theme_classic() + 237 | ggtitle('C3 (m2)') + 238 | theme(plot.title = element_text(hjust = 0.5)) 239 | 240 | cowplot::plot_grid(p1, p2, p3, p4, p5, p6) 241 | 242 | ``` 243 | 244 | ### DEGs between C3 and C5 (volcano plot) 245 | ```{r fig.height = 6, fig.width = 8, fig.align = 'center'} 246 | Idents(sc_obj) <- 'scSpace' 247 | markers <- FindMarkers(sc_obj, ident.1 = 'c5', ident.2 = 'c3', logfc.threshold = 0, min.pct = 0) 248 | markers$gene <- rownames(markers) 249 | 250 | write.csv(markers, file = paste0(output_dir, '/DEGs_between_C3_C5.csv')) 251 | 252 | markers$logp <- -log10(markers$p_val_adj) 253 | markers$group <- 'no_sig' 254 | markers$group[which((markers$p_val_adj < 0.05) & (markers$avg_log2FC > 1))] <- 'up' 255 | markers$group[which((markers$p_val_adj < 0.05) & (markers$avg_log2FC < -1))] <- 'down' 256 | select_gene <- c('IL7R', 'TCF7', 'C3orf33', 'TK1', 'AURKB', 'BIRC5', 'KIFC1', 'MKI67', 257 | 'NME1', 'CDK1', 'TYMS', 'MCM2', 'TPX2', 'TOP2A') 258 | markers$anno <- NA 259 | markers[markers$gene %in% select_gene, ]$anno <- markers[markers$gene %in% select_gene, ]$gene 260 | 261 | p <- ggscatter(markers, x = 'avg_log2FC', y = 'logp', color = 'group', palette = c('#2f5688', 'grey80', '#CC0000'), size = 1.5) + 262 | geom_text_repel(aes(label=anno)) + 263 | theme_classic() + 264 | geom_hline(yintercept = 1.30, linetype = 'dashed') + 265 | geom_vline(xintercept = c(-1, 1), linetype = 'dashed') 266 | p 267 | ``` 268 | 269 | ### DEGs between C3 and C5 (heatmap) 270 | ```{r fig.height = 6, fig.width = 8, fig.align = 'center'} 271 | c5_genes <- c(markers[order(markers$avg_log2FC, decreasing = TRUE), ]$gene[1:20], 'CDK2') 272 | c3_genes <- c(markers[order(markers$avg_log2FC, decreasing = FALSE), ]$gene[1:20]) 273 | sc_obj_sub <- subset(sc_obj, idents = c('c3', 'c5')) 274 | DoHeatmap(sc_obj_sub, features = c(c3_genes, c5_genes), group.colors = c("#854D0E", "#10B981")) 275 | ``` 276 | 277 | 278 | ### Calculate T exhaustion score 279 | ```{r fig.height = 5, fig.width = 10, fig.align = 'center'} 280 | exhaustion_gene <- c('HAVCR2','PDCD1','ENTPD1','TNFRSF9','CCL3','PHLDA1','SIRPG', 281 | 'CTLA4','TIGIT','SNAP47','WARS','CD27','RGS1','TNFRSF1B', 282 | 'CD27-AS1','ACP5','AFAP1L2','MYO7A','AKAP5','ENTPD1-AS1', 283 | 'ADGRG1','TOX','LAYN','CD38','ITGAE','RGS2','CCND2','FKBP1A', 284 | 'MTHFD1','GALM','CSF1','SNX9','ICOS','LYST','MIR155HG','TPI1', 285 | 'SARDH','GZMB','CREM','HLA-DMA','PRDM1','PKM','MYO1E','FUT8','DUSP4','RAB27A', 286 | 'HLA-DRA','UBE2F-SCLY','IGFLR1','CXCL13','IFNG','UBE2F','ITM2A', 287 | 'ID3','CD2BP2','CHST12','CTSD','STAT3','BST2','CXCR6','RALGDS', 288 | 'VCAM1','TRAFD1','SYNGR2','VAPA','IFI35','CD63','NAB1','PARK7', 289 | 'MIR4632','YARS','PRKAR1A','IL2RB','DFNB31','HMGN3','MTHFD2', 290 | 'NDFIP2','PRF1','PRDX5','LAG3','MS4A6A','LINC00299') 291 | 292 | exhaustion_sig <- list(intersect(rownames(sc_obj_sub), exhaustion_gene)) 293 | sc_obj_sub <- AddModuleScore(sc_obj_sub, features = exhaustion_sig, name = 'exhaustion_score') 294 | 295 | p1 <- FeaturePlot(sc_obj_sub, features = 'exhaustion_score1', reduction = 'tsne', cols = viridis(9), pt.size = 2.5) 296 | 297 | exhaustion_plot <- data.frame(score = sc_obj_sub$exhaustion_score1, 298 | group = as.character(sc_obj_sub$scSpace)) 299 | 300 | p2 <- ggplot(data=exhaustion_plot, aes(x=group, y=score, fill=group)) + 301 | geom_boxplot() + 302 | theme_classic() + 303 | scale_fill_manual(values = c('#854D0E','#10B981')) + 304 | geom_signif(comparisons = list(c("c3","c5")), 305 | map_signif_level=F, 306 | textsize=6,test=wilcox.test,step_increase=0.2) 307 | 308 | cowplot::plot_grid(p1, p2) 309 | 310 | ``` 311 | 312 | 313 | ### GSEA 314 | ```{r fig.height = 6, fig.width = 10, fig.align = 'center'} 315 | m_df <- msigdbr(species = "Homo sapiens", category = "H") 316 | fgsea_sets <- m_df %>% split(x = .$gene_symbol, f = .$gs_name) 317 | c5_genes <- markers %>% arrange(desc(avg_log2FC)) %>% dplyr::select(gene, avg_log2FC) 318 | ranks <- deframe(c5_genes) 319 | fgseaRes <- fgsea(fgsea_sets, stats = ranks, nperm = 10000) 320 | fgseaRes_rep <- data.frame(fgseaRes[, c(1:7)]) 321 | write.csv(fgseaRes_rep, file = paste0(output_dir, '/GSEA_result.csv')) 322 | 323 | p1 <- plotEnrichment_new(fgsea_sets[["HALLMARK_E2F_TARGETS"]], ranks, ticksSize=0.5) + 324 | theme_classic() + 325 | ggtitle('E2F TARGETS') + 326 | theme(plot.title = element_text(hjust = 0.5)) 327 | 328 | p2 <- plotEnrichment_new(fgsea_sets[["HALLMARK_OXIDATIVE_PHOSPHORYLATION"]], ranks, ticksSize=0.5) + 329 | theme_classic() + 330 | ggtitle('OXIDATIVE PHOSPHORYLATION') + 331 | theme(plot.title = element_text(hjust = 0.5)) 332 | 333 | p3 <- plotEnrichment_new(fgsea_sets[["HALLMARK_G2M_CHECKPOINT"]], ranks, ticksSize=0.5) + 334 | theme_classic() + 335 | ggtitle('G2M CHECKPOINT') + 336 | theme(plot.title = element_text(hjust = 0.5)) 337 | 338 | p4 <- plotEnrichment_new(fgsea_sets[["HALLMARK_DNA_REPAIR"]], ranks, ticksSize=0.5) + 339 | theme_classic() + 340 | ggtitle('DNA REPAIR') + 341 | theme(plot.title = element_text(hjust = 0.5)) 342 | 343 | p5 <- plotEnrichment_new(fgsea_sets[["HALLMARK_MYC_TARGETS_V1"]], ranks, ticksSize=0.5) + 344 | theme_classic() + 345 | ggtitle('MYC TARGETS V1') + 346 | theme(plot.title = element_text(hjust = 0.5)) 347 | 348 | p6 <- plotEnrichment_new(fgsea_sets[["HALLMARK_MITOTIC_SPINDLE"]], ranks, ticksSize=0.5) + 349 | theme_classic() + 350 | ggtitle('MITOTIC SPINDLE') + 351 | theme(plot.title = element_text(hjust = 0.5)) 352 | 353 | cowplot::plot_grid(p1, p2, p3, p4, p5, p6) 354 | ``` 355 | 356 | ### Survival analysis 357 | ```{r fig.height = 12, fig.width = 10, fig.align = 'center'} 358 | mycgds <- CGDS('http://www.cbioportal.org/') 359 | all_tcga_studies <- getCancerStudies(mycgds) 360 | skcm_2015 <- 'skcm_tcga' 361 | mycaselist <- getCaseLists(mycgds, skcm_2015)[6,1] 362 | mygeneticprofile <- getGeneticProfiles(mycgds,skcm_2015)[7,1] 363 | 364 | choose_genes <- c('TK1', 'KIFC1', 'AURKB', 'BIRC5', 'MKI67', 'TPX2', 'NME1', 'CDK2') 365 | expr <- getProfileData(mycgds, choose_genes, mygeneticprofile, mycaselist) 366 | clinicaldata <- getClinicalData(mycgds, mycaselist) 367 | dat <- clinicaldata[clinicaldata$OS_MONTHS > 0, ] 368 | dat <- cbind(clinicaldata[, c('OS_STATUS', 'OS_MONTHS')], expr[rownames(clinicaldata), ]) 369 | dat <- dat[dat$OS_MONTHS > 0, ] 370 | dat <- dat[!is.na(dat$OS_STATUS), ] 371 | dat$OS_STATUS <- as.character(dat$OS_STATUS) 372 | dat[, -(1:2)] <- apply(dat[, -(1:2)], 2, function(x){ifelse(x > as.numeric(quantile(x)[4]), 'high', 'low')}) 373 | attach(dat) 374 | my.surv <- Surv(dat$OS_MONTHS, dat$OS_STATUS == '1:DECEASED') 375 | 376 | # TK1 377 | kmfit <- survfit(my.surv ~ TK1, data = dat) 378 | p1 <- ggsurvplot(kmfit, conf.int = FALSE, pval = TRUE, risk.table = FALSE, 379 | ncensor.plot = FALSE, palette = c('red','blue')) 380 | # KIFC1 381 | kmfit <- survfit(my.surv ~ KIFC1, data = dat) 382 | p2 <- ggsurvplot(kmfit, conf.int = FALSE, pval = TRUE, risk.table = FALSE, 383 | ncensor.plot = FALSE, palette = c('red','blue')) 384 | # AURKB 385 | kmfit <- survfit(my.surv ~ AURKB, data = dat) 386 | p3 <- ggsurvplot(kmfit, conf.int = FALSE, pval = TRUE, risk.table = FALSE, 387 | ncensor.plot = FALSE, palette = c('red','blue')) 388 | # BIRC5 389 | kmfit <- survfit(my.surv ~ BIRC5, data = dat) 390 | p4 <- ggsurvplot(kmfit, conf.int = FALSE, pval = TRUE, risk.table = FALSE, 391 | ncensor.plot = FALSE, palette = c('red','blue')) 392 | # MKI67 393 | kmfit <- survfit(my.surv ~ MKI67, data = dat) 394 | p5 <- ggsurvplot(kmfit, conf.int = FALSE, pval = TRUE, risk.table = FALSE, 395 | ncensor.plot = FALSE, palette = c('red','blue')) 396 | # TPX2 397 | kmfit <- survfit(my.surv ~ TPX2, data = dat) 398 | p6 <- ggsurvplot(kmfit, conf.int = FALSE, pval = TRUE, risk.table = FALSE, 399 | ncensor.plot = FALSE, palette = c('red','blue')) 400 | # NME1 401 | kmfit <- survfit(my.surv ~ NME1, data = dat) 402 | p7 <- ggsurvplot(kmfit, conf.int = FALSE, pval = TRUE, risk.table = FALSE, 403 | ncensor.plot = FALSE, palette = c('red','blue')) 404 | # CDK2 405 | kmfit <- survfit(my.surv ~ CDK2, data = dat) 406 | p8 <- ggsurvplot(kmfit, conf.int = FALSE, pval = TRUE, risk.table = FALSE, 407 | ncensor.plot = FALSE, palette = c('red','blue')) 408 | 409 | cowplot::plot_grid(p1$plot, p2$plot, p3$plot, p4$plot, p5$plot, p6$plot, p7$plot, p8$plot) 410 | ``` 411 | 412 | 413 | -------------------------------------------------------------------------------- /AnalysisPaper/figures/figure6.Rmd: -------------------------------------------------------------------------------- 1 | 2 | ```{r setup, include=FALSE} 3 | knitr::opts_chunk$set(echo = TRUE) 4 | ``` 5 | 6 | # Sptial analysis of the invasion of myeloid subpopulations in COVID-19 7 | ```{r} 8 | library(GSVA) 9 | library(Seurat) 10 | library(ggplot2) 11 | library(ggthemes) 12 | library(ggsignif) 13 | library(ggforce) 14 | library(dplyr) 15 | library(reshape2) 16 | library(ggbeeswarm) 17 | library(cowplot) 18 | library(limma) 19 | library(viridis) 20 | library(ggpubr) 21 | library(pheatmap) 22 | ``` 23 | 24 | 25 | ### Load data 26 | ```{r} 27 | # Ground Truth 28 | load('../data/covid19/covid19.RDS') 29 | ``` 30 | 31 | ### Load custom functions 32 | ```{r} 33 | source('../scripts/utils.R') 34 | ``` 35 | 36 | ### Set output dir 37 | ```{r} 38 | output_dir <- '../output/figure6' 39 | if(!dir.exists(output_dir)){ 40 | dir.create(output_dir) 41 | } else { 42 | print('Dir already exists!') 43 | } 44 | ``` 45 | 46 | ### scRNA-seq overview 47 | ```{r fig.height = 5, fig.width = 10, fig.align = 'center'} 48 | sc_seu <- run_Seurat(sc_meta = sc_meta, sc_data = sc_data, res = 1) 49 | tsne_obj <- sc_seu@meta.data 50 | tsne_obj$tsne1 <- sc_seu@reductions$tsne@cell.embeddings[, 1] 51 | tsne_obj$tsne2 <- sc_seu@reductions$tsne@cell.embeddings[, 2] 52 | 53 | p1 <- ggplot() + 54 | geom_point(tsne_obj, mapping = aes(tsne1,tsne2,color = cell_type_main), size = 2) + 55 | scale_color_manual(values = c('#EF4444', '#3B82F6', '#8B5CF6', '#10B981', '#F97316', 56 | '#84CC16', '#854D0E', '#EAB308', '#D946EF')) + 57 | theme_classic() + 58 | theme(legend.title = element_blank()) 59 | 60 | p2 <- ggplot() + 61 | geom_point(tsne_obj, mapping = aes(tsne1,tsne2,color = group), size = 2) + 62 | scale_color_manual(values =c('#A5B4FC', '#F97316')) + 63 | theme_classic() + 64 | theme(legend.title = element_blank()) 65 | 66 | cowplot::plot_grid(p1, p2) 67 | ``` 68 | 69 | ### Pseudo space of scRNA-seq 70 | ```{r fig.height = 8, fig.width = 10, fig.align = 'center'} 71 | sc_meta$pseudo_space1 <- pseudo_coords[,1] 72 | sc_meta$pseudo_space2 <- pseudo_coords[,2] 73 | sc_meta$cell_type_main_rep <- sc_meta$cell_type_main 74 | sc_meta[sc_meta$cell_type_main_rep %in% 75 | c('APC-like', 'B cells', 'Endothelial cells', 'Fibroblasts', 76 | 'Mast cells', 'Neuronal cells', 'T cells'), ]$cell_type_main_rep <- 'others' 77 | 78 | 79 | p1 <- ggplot() + 80 | geom_point(sc_meta[sc_meta$group == 'Control', ], 81 | mapping = aes(pseudo_space1, pseudo_space2, color = cell_type_main), size = 3) + 82 | scale_color_manual(values = c('#EF4444', '#3B82F6', '#8B5CF6', '#10B981', '#F97316', 83 | '#84CC16', '#854D0E', '#EAB308', '#D946EF')) + 84 | theme_classic() + 85 | ggtitle('Pseudo space (Control)') + 86 | theme(plot.title = element_text(hjust = 0.5)) + 87 | theme(legend.title = element_blank()) 88 | 89 | p2 <- ggplot() + 90 | geom_point(sc_meta[sc_meta$group == 'COVID-19', ], 91 | mapping = aes(pseudo_space1, pseudo_space2, color = cell_type_main), size = 3) + 92 | scale_color_manual(values = c('#EF4444', '#3B82F6', '#8B5CF6', '#10B981', '#F97316', 93 | '#84CC16', '#854D0E', '#EAB308', '#D946EF')) + 94 | theme_classic() + 95 | ggtitle('Pseudo space (COVID-19)') + 96 | theme(plot.title = element_text(hjust = 0.5)) + 97 | theme(legend.title = element_blank()) 98 | 99 | p3 <- ggplot() + 100 | geom_point(sc_meta[sc_meta$group == 'Control' & (sc_meta$cell_type_main_rep == 'others'), ], 101 | mapping = aes(pseudo_space1, pseudo_space2, color = cell_type_main_rep), size = 3) + 102 | geom_point(sc_meta[sc_meta$group == 'Control' & (sc_meta$cell_type_main_rep != 'others'), ], 103 | mapping = aes(pseudo_space1, pseudo_space2, color = cell_type_main_rep), size = 3) + 104 | scale_color_manual(values = c('#10B981', '#854D0E', 'grey90')) + 105 | theme_classic() + 106 | ggtitle('Pseudo space (Control)') + 107 | theme(plot.title = element_text(hjust = 0.5)) + 108 | theme(legend.title = element_blank()) 109 | 110 | p4 <- ggplot() + 111 | geom_point(sc_meta[sc_meta$group == 'COVID-19' & (sc_meta$cell_type_main_rep == 'others'), ], 112 | mapping = aes(pseudo_space1, pseudo_space2, color = cell_type_main_rep), size = 3) + 113 | geom_point(sc_meta[sc_meta$group == 'COVID-19' & (sc_meta$cell_type_main_rep != 'others'), ], 114 | mapping = aes(pseudo_space1, pseudo_space2, color = cell_type_main_rep), size = 3) + 115 | scale_color_manual(values = c('#10B981', '#854D0E', 'grey90')) + 116 | theme_classic() + 117 | ggtitle('Pseudo space (COVID-19)') + 118 | theme(plot.title = element_text(hjust = 0.5)) + 119 | theme(legend.title = element_blank()) 120 | 121 | cowplot::plot_grid(p1, p2, p3, p4) 122 | 123 | ``` 124 | 125 | ### Calculate distance between Myeloid cells and Alveolar/Airway Epithelial cells of Control and COVID-19 groups 126 | ```{r fig.height = 4, fig.width = 6, fig.align = 'center'} 127 | sc_meta$celltype <- sc_meta$cell_type_fine 128 | sc_meta[sc_meta$cell_type_main == 'T cells', ]$celltype <- 'T cells' 129 | sc_meta[sc_meta$cell_type_main == 'Endothelial cells', ]$celltype <- 'Endothelial cells' 130 | sc_meta[sc_meta$cell_type_main == 'B cells', ]$celltype <- 'B cells' 131 | sc_meta[sc_meta$cell_type_main == 'Fibroblasts', ]$celltype <- 'Fibroblasts' 132 | sc_meta[sc_meta$celltype %in% c('AT1', 'AT2'), ]$celltype <- 'alveolar epithelial cells' 133 | sc_meta[sc_meta$celltype %in% c('Airway basal', 'Airway ciliated', 'Airway club', 134 | 'Airway goblet', 'Airway mucous', 'Tuft-like'), ]$celltype <- 'airway epithelial cells' 135 | 136 | sc_meta$celltype1 <- sc_meta$celltype 137 | sc_meta[sc_meta$celltype1 %in% c('Monocyte-derived macrophages', 'Monocytes', 138 | 'Alveolar macrophages', 'Transitioning MDM') ,]$celltype1 <- 'Myeloid' 139 | sc_meta[sc_meta$celltype1 %in% c('alveolar epithelial cells', 'airway epithelial cells') ,]$celltype1 <- 'Alveolar/Airway Epithelial' 140 | 141 | # calculate pairwise distance 142 | con_dist <- cal_dist(meta = sc_meta[sc_meta$disease__ontology_label == 'normal' & 143 | sc_meta$celltype1 %in% c('Alveolar/Airway Epithelial', 'Myeloid'), ], 144 | coord_index = c('pseudo_space1', 'pseudo_space2'), 145 | group_by = 'celltype1', 146 | selected_type = 'Alveolar/Airway Epithelial', 147 | ignore_select_type = TRUE) 148 | 149 | cov_dist <- cal_dist(meta = sc_meta[sc_meta$disease__ontology_label == 'COVID-19' & 150 | sc_meta$celltype1 %in% c('Alveolar/Airway Epithelial', 'Myeloid'), ], 151 | coord_index = c('pseudo_space1', 'pseudo_space2'), 152 | group_by = 'celltype1', 153 | selected_type = 'Alveolar/Airway Epithelial', 154 | ignore_select_type = TRUE) 155 | 156 | con_dist$type <- 'Control' 157 | cov_dist$type <- 'COVID-19' 158 | 159 | dist_all <- rbind(con_dist, cov_dist) 160 | p <- ggplot(data=dist_all, aes(x=type, y=dist, fill=type)) + 161 | geom_boxplot(outlier.shape = NA) + 162 | scale_fill_manual(values = c('#A5B4FC', '#F97316') )+ 163 | theme_classic() + 164 | ggtitle('Distance between Myeloid and Alveolar/Airway Epithelial') + 165 | theme(plot.title = element_text(hjust = 0.5)) + 166 | ggsignif::geom_signif(test = 'wilcox.test', comparisons = list(c('COVID-19', 'Control'))) 167 | 168 | p 169 | 170 | ``` 171 | 172 | ### Validation using GeoMX DSP data generated by Rendeiro et al. 2021 (doi: 10.1038/s41586-021-03475-6) 173 | ```{r fig.height = 4, fig.width = 6, fig.align = 'center'} 174 | # ssGSEA (doi: 10.1038/s41586-021-03475-6) 175 | # create cell-type signature gene sets 176 | Idents(sc_seu) <- 'cell_type_main' 177 | marker <- FindAllMarkers(sc_seu, only.pos = TRUE, assay = 'RNA', logfc.threshold = 0.5) 178 | marker <- marker[marker$p_val_adj < 0.05, ] 179 | genesets <- list(Fibroblasts=marker[marker$cluster=='Fibroblasts', ]$gene, 180 | Mast=marker[marker$cluster=='Mast cells', ]$gene, 181 | Epithelial=marker[marker$cluster=='Epithelial cells', ]$gene, 182 | Tcells=marker[marker$cluster=='T cells', ]$gene, 183 | Myeloid=marker[marker$cluster=='Myeloid', ]$gene, 184 | Endothelial=marker[marker$cluster=='Endothelial cells', ]$gene, 185 | Bcells=marker[marker$cluster=='B cells', ]$gene, 186 | DC=marker[marker$cluster=='APC-like', ]$gene, 187 | Neuronal=marker[marker$cluster=='Neuronal cells', ]$gene) 188 | 189 | # DSP data 190 | colnames(dsp_data) <- rownames(dsp_meta) 191 | dsp_meta <-dsp_meta[dsp_meta$disease != 'Non-viral', ] 192 | dsp_meta[dsp_meta$disease != 'Normal', ]$disease <- 'COVID-19' 193 | dsp_meta[dsp_meta$disease == 'Normal', ]$disease <- 'Control' 194 | dsp_data <- dsp_data[, rownames(dsp_meta)] 195 | dsp_data <- as.matrix(dsp_data) 196 | # run ssGSEA 197 | ssgsea_score <- gsva(dsp_data, genesets, method = "ssgsea", ssgsea.norm = TRUE, verbose = TRUE) 198 | ssgsea_score <- data.frame(t(ssgsea_score)) 199 | ssgsea_score_plot <- ssgsea_score 200 | ssgsea_score_plot$disease <- dsp_meta$disease 201 | ssgsea_score_plot <- melt(ssgsea_score_plot) 202 | 203 | p <- ggplot(ssgsea_score_plot[ssgsea_score_plot$variable == 'Myeloid',], 204 | aes(disease, value, color = disease))+ 205 | geom_boxplot() + 206 | geom_beeswarm(aes(fill = disease), shape=21, colour = "black", size = 3, cex = 2)+ 207 | scale_color_manual(values= c('#A5B4FC', '#F97316')) + 208 | scale_fill_manual(values= c('#A5B4FC', '#F97316')) + 209 | theme_classic() + 210 | ggsignif::geom_signif(comparisons = list(c('Control', 'COVID-19')), 211 | step_increase = 0.3, color = "black", test = 'wilcox.test') 212 | p 213 | 214 | ssgsea_score_plot <- ssgsea_score_plot[ssgsea_score_plot$variable == 'Myeloid', ] 215 | write.csv(ssgsea_score_plot, file = paste0(output_dir, '/ssGSEA_result.csv')) 216 | ``` 217 | 218 | ```{r fig.height = 4, fig.width = 6, fig.align = 'center'} 219 | # CYBERSORTx 220 | cybersort_res <- read.csv('../data/covid19/CIBERSORTx_Job1_Results.csv', row.names = 1) 221 | cybersort_res <- cybersort_res[, 1:9] 222 | cybersort_res$disease <- dsp_meta[rownames(cybersort_res), ]$disease 223 | cybersort_res <- melt(cybersort_res) 224 | 225 | p <- ggplot(cybersort_res[cybersort_res$variable == 'Myeloid',], 226 | aes(disease, value, color = disease))+ 227 | geom_boxplot() + 228 | geom_beeswarm(aes(fill = disease), shape=21, colour = "black", size = 3, cex = 2)+ 229 | scale_color_manual(values= c('#A5B4FC', '#F97316')) + 230 | scale_fill_manual(values= c('#A5B4FC', '#F97316')) + 231 | theme_classic() + 232 | ggsignif::geom_signif(comparisons = list(c('Control', 'COVID-19')), 233 | step_increase = 0.3, color = "black", test = 'wilcox.test') 234 | p 235 | ``` 236 | 237 | ```{r fig.height = 4, fig.width = 6, fig.align = 'center'} 238 | # Calculate the COVID-19 signatures using DSP data 239 | # limma 240 | dsp_data <- dsp_data[intersect(rownames(dsp_data), rownames(sc_data)), ] 241 | list <- dsp_meta$disease %>% factor(., levels = c("Control", "COVID-19"), ordered = F) 242 | list <- model.matrix(~factor(list) + 0) 243 | colnames(list) <- c("Control", "COVID") 244 | df.fit <- lmFit(dsp_data, list) 245 | df.matrix <- makeContrasts(COVID - Control , levels = list) 246 | fit <- contrasts.fit(df.fit, df.matrix) 247 | fit <- eBayes(fit) 248 | limma_res <- topTable(fit,n = Inf, adjust = "fdr") 249 | 250 | # ggscatter 251 | limma_res_plot <- limma_res 252 | limma_res_plot$gene <- rownames(limma_res_plot) 253 | limma_res_plot$logp <- -log10(limma_res_plot$adj.P.Val) 254 | limma_res_plot$group <- 'no_sig' 255 | limma_res_plot$group[which((limma_res_plot$adj.P.Val < 0.05) & (limma_res_plot$logFC > 0.5))] <- 'up' 256 | limma_res_plot$group[which((limma_res_plot$adj.P.Val < 0.05) & (limma_res_plot$logFC < -0.5))] <- 'down' 257 | p <- ggscatter(limma_res_plot, x = 'logFC', y = 'logp', color = 'group', 258 | palette = c('#2f5688', 'grey80', '#CC0000'), size = 2, label = 'gene', 259 | label.select = rownames(limma_res)[order(limma_res$logFC, decreasing=TRUE)[1:10]], 260 | font.label = c(8, 'plain')) + 261 | theme_classic() + 262 | geom_hline(yintercept = 1.30, linetype = 'dashed') + 263 | geom_vline(xintercept = c(-0.5, 0.5), linetype = 'dashed') 264 | 265 | p 266 | 267 | write.csv(limma_res_plot, file = paste0(output_dir, '/DSP_limma_result.csv')) 268 | ``` 269 | 270 | ```{r fig.height = 4, fig.width = 6, fig.align = 'center'} 271 | # Compare the COVID-19 signatures score between Myeloid cells (near to Alveolar/Airway Epithelial) and Myeloid cells (far from Alveolar/Airway Epithelial) 272 | 273 | # COVID-19 signatures 274 | covid19_signatures <- list(rownames(limma_res[limma_res$logFC > 0.5, ])) 275 | 276 | # Extract Alveolar/Airway Epithelial cells and Myeloid cells from COVID-19 group 277 | mye_epi <- sc_meta[sc_meta$celltype %in% c('airway epithelial cells','alveolar epithelial cells') | 278 | sc_meta$celltype1 == 'Myeloid', ] 279 | mye_epi <- mye_epi[mye_epi$disease__ontology_label == 'COVID-19', ] 280 | dist_df <- data.frame(as.matrix(dist(mye_epi[, c('pseudo_space1', 'pseudo_space2')]))) 281 | 282 | # Myeloid to Alveolar/Airway Epithelial (far: distance > median(distance); near: distance <= median(distance)) 283 | dist_df <- dist_df[rownames(mye_epi[mye_epi$celltype1 == 'Myeloid', ]), 284 | rownames(mye_epi[mye_epi$celltype1 == 'Alveolar/Airway Epithelial', ])] 285 | dist_mean <- apply(dist_df, 1, mean) 286 | mye_near_to_epi <- names(dist_mean[dist_mean <= median(dist_mean)]) 287 | mye_far_from_epi <- names(dist_mean[dist_mean > median(dist_mean)]) 288 | 289 | mye_meta <- mye_epi[mye_epi$celltype1 == 'Myeloid', ] 290 | mye_meta$type <- NA 291 | mye_meta[mye_near_to_epi, ]$type <- 'Myeloid (Near)' 292 | mye_meta[mye_far_from_epi, ]$type <- 'Myeloid (Far)' 293 | 294 | # Calculate COVID-19 signatures socre 295 | mye_data <- sc_data[, rownames(mye_meta)] 296 | seu_obj <- CreateSeuratObject(mye_data, meta.data = mye_meta) 297 | seu_obj <- AddModuleScore(seu_obj, features = covid19_signatures, name = 'DSP') 298 | module_score_df <- seu_obj@meta.data 299 | 300 | p <- ggplot(data=module_score_df, aes(x=type, y=DSP1, fill=type)) + 301 | geom_boxplot(outlier.shape = NA) + 302 | theme_classic() + 303 | scale_fill_manual(values = c('#E41A1C','#377EB8')) + 304 | ggtitle('COVID-19 Signatures Socre') + 305 | theme(plot.title = element_text(hjust = 0.5)) + 306 | geom_signif(comparisons = list(c('Myeloid (Near)', 'Myeloid (Far)')), test = 'wilcox.test') 307 | p 308 | ``` 309 | 310 | ```{r fig.height = 6, fig.width = 8, fig.align = 'center'} 311 | # DEGs of Myeloid cells (near to Alveolar/Airway Epithelial) 312 | Idents(seu_obj) <- 'type' 313 | p <- VlnPlot(seu_obj, features = c('B2M', 'HLA-A', 'HLA-B', 'HLA-C', 'HLA-DRA', 'HLA-E'), cols = c('#E41A1C', '#377EB8'), pt.size = 0) 314 | p 315 | ``` 316 | 317 | ### Calculate distance between Myeloid subclusters and Alveolar/Airway Epithelial cells 318 | ```{r fig.height = 5, fig.width = 10, fig.align = 'center'} 319 | mye_epi <- sc_meta[sc_meta$celltype %in% c('airway epithelial cells','alveolar epithelial cells') | 320 | sc_meta$celltype1 == 'Myeloid', ] 321 | mye_epi$celltype2 <- mye_epi$celltype 322 | mye_epi[mye_epi$celltype1 == 'Alveolar/Airway Epithelial', ]$celltype2 <- 'Alveolar/Airway Epithelial' 323 | 324 | # calculate pairwise distance 325 | con_dist <- cal_dist(meta = mye_epi[mye_epi$disease__ontology_label == 'normal', ], 326 | coord_index = c('pseudo_space1', 'pseudo_space2'), 327 | group_by = 'celltype2', 328 | selected_type = 'Alveolar/Airway Epithelial', 329 | ignore_select_type = TRUE) 330 | 331 | cov_dist <- cal_dist(meta = mye_epi[mye_epi$disease__ontology_label == 'COVID-19', ], 332 | coord_index = c('pseudo_space1', 'pseudo_space2'), 333 | group_by = 'celltype2', 334 | selected_type = 'Alveolar/Airway Epithelial', 335 | ignore_select_type = TRUE) 336 | 337 | con_dist$type <- 'Control' 338 | cov_dist$type <- 'COVID-19' 339 | dist_all <- rbind(con_dist, cov_dist) 340 | 341 | dist_all$group <- gsub('Alveolar/Airway Epithelial_', '', dist_all$group) 342 | dist_all$group <- gsub('Alveolar macrophages', 'AM', dist_all$group) 343 | dist_all$group <- gsub('Monocyte-derived macrophages', 'MDM', dist_all$group) 344 | dist_all$group <- gsub('Monocytes', 'Mon', dist_all$group) 345 | dist_all$group <- gsub('Transitioning MDM', 'TMDM', dist_all$group) 346 | p1 <- ggplot(data=dist_all, aes(x=group, y=dist, fill=type)) + 347 | geom_boxplot(outlier.shape = NA) + 348 | scale_fill_manual(values = c('#A5B4FC', '#F97316') )+ 349 | theme_classic() + 350 | ggtitle('Distance between Myeloid subclusters and Alveolar/Airway Epithelial') + 351 | theme(plot.title = element_text(hjust = 0.5)) + 352 | ggpubr::stat_compare_means(aes(group=type), method = 'wilcox.test') 353 | 354 | # distance change ratio between COVID-19 and Control group 355 | distance_median_control <- aggregate(dist_all[dist_all$type == 'Control', ]$dist, 356 | by=list(dist_all[dist_all$type == 'Control', ]$group),median) 357 | distance_median_coviid19 <- aggregate(dist_all[dist_all$type == 'COVID-19', ]$dist, 358 | by=list(dist_all[dist_all$type == 'COVID-19', ]$group),median) 359 | 360 | distance_chage_ratio <- data.frame(celltype = distance_median_control$Group.1, 361 | control_median = distance_median_control$x, 362 | covid19_median = distance_median_coviid19$x) 363 | 364 | distance_chage_ratio$ratio <- (distance_chage_ratio$covid19_median - 365 | distance_chage_ratio$control_median) / distance_chage_ratio$control_median 366 | 367 | distance_chage_ratio$celltype <- factor(distance_chage_ratio$celltype, levels = c('TMDM', 'MDM', 'AM', 'Mon')) 368 | 369 | write.csv(distance_chage_ratio, file = paste0(output_dir, '/Dist_change_ratio.csv')) 370 | 371 | p2 <- ggplot(distance_chage_ratio) + 372 | geom_bar(aes(celltype, -ratio, fill=celltype, color=celltype), stat = 'identity') + 373 | scale_fill_manual(values = c('#8B5CF6', '#3B82F6', '#F97316', '#EAB308')) + 374 | scale_color_manual(values = c('black', 'black', 'black', 'black')) + 375 | ggtitle('Distance change') + 376 | theme(plot.title = element_text(hjust = 0.5)) + 377 | theme_classic() 378 | 379 | cowplot::plot_grid(p1, p2) 380 | 381 | ``` 382 | 383 | ### TMDM/MDM subclusters analysis 384 | ```{r fig.height = 5, fig.width = 10, fig.align = 'center'} 385 | sc_meta_mdm <- sc_meta[sc_meta$cell_type_fine == 'Monocyte-derived macrophages' | sc_meta$cell_type_fine == 'Transitioning MDM', ] 386 | sc_meta_mdm$scSpace <- mdm_meta$scspace 387 | sc_data_mdm <- sc_data[, rownames(sc_meta_mdm)] 388 | 389 | mdm <- run_Seurat(sc_meta = sc_meta_mdm, sc_data = sc_data_mdm, res = 0.35) 390 | mdm$scSpace <- paste0('C_', (mdm$scSpace + 1)) 391 | mdm$seurat_clusters <- paste0('C_', as.numeric(mdm$seurat_clusters)) 392 | mdm_meta_new <- mdm@meta.data 393 | mdm_meta_new$tsne1 <- mdm@reductions$tsne@cell.embeddings[, 1] 394 | mdm_meta_new$tsne2 <- mdm@reductions$tsne@cell.embeddings[, 2] 395 | 396 | p1 <- ggplot() + 397 | geom_point(mdm_meta_new, mapping = aes(tsne1,tsne2,color = scSpace), size = 3) + 398 | scale_color_manual(values = c('#3B82F6', '#EF4444', '#C798EE', '#EAB308', '#F97316', '#854D0E')) + 399 | theme_classic() + 400 | ggtitle('MDM/TMDM subclusters') + 401 | theme(plot.title = element_text(hjust = 0.5)) + 402 | theme(legend.title = element_blank()) 403 | 404 | # Calculate distance between MDM/TMDM subclusters and Alveolar/Airway Epithelial 405 | epi_meta <- sc_meta[sc_meta$celltype %in% c('airway epithelial cells','alveolar epithelial cells'), ] 406 | dist_df <- data.frame( 407 | pseudo_space1 = c(mdm_meta_new$pseudo_space1, epi_meta$pseudo_space1), 408 | pseudo_space2 = c(mdm_meta_new$pseudo_space2, epi_meta$pseudo_space2), 409 | celltype = c(mdm_meta_new$scSpace, epi_meta$celltype1)) 410 | 411 | dist_res <- cal_dist(meta = dist_df, 412 | coord_index = c('pseudo_space1', 'pseudo_space2'), 413 | group_by = 'celltype', 414 | selected_type = 'Alveolar/Airway Epithelial', 415 | ignore_select_type = TRUE) 416 | 417 | dist_res$group <- gsub('Alveolar/Airway Epithelial_', '', dist_res$group) 418 | dist_res$group <- factor(dist_res$group, levels = c('C_4', 'C_2', 'C_5', 'C_6', 'C_3', 'C_1')) 419 | p2 <- ggplot(data=dist_res, aes(x=group, y=dist, fill=group)) + 420 | geom_boxplot(outlier.shape = NA) + 421 | scale_fill_manual(values = c('#EAB308', '#EF4444', '#F97316', '#854D0E', '#C798EE', '#3B82F6')) + 422 | theme_classic() + 423 | ggtitle('Distance between MDM/TMDM subclusters and Alveolar/Airway Epithelial') + 424 | theme(plot.title = element_text(hjust = 0.5)) + 425 | geom_signif(comparisons = list(c('C_4', 'C_2'), c('C_4', 'C_5'), c('C_4', 'C_6'), 426 | c('C_4', 'C_3'), c('C_4', 'C_1')), 427 | test = 'wilcox.test', step_increase=0.1) 428 | 429 | cowplot::plot_grid(p1, p2) 430 | ``` 431 | 432 | ### DEGs between MDM/TMDM subclusters 433 | ```{r fig.height = 8, fig.width = 8, fig.align = 'center'} 434 | Idents(mdm) <- 'scSpace' 435 | mdm@active.ident <- factor(mdm@active.ident, levels = c('C_1', 'C_2', 'C_3', 'C_4', 'C_5', 'C_6')) 436 | all_markers <- FindAllMarkers(mdm, assay = 'RNA', only.pos = TRUE, logfc.threshold = 0.5) 437 | all_markers <- all_markers[all_markers$p_val_adj < 0.05, ] 438 | 439 | write.csv(all_markers, file = paste0(output_dir, '/DEGs_between_MDM_subcluster.csv')) 440 | 441 | top10 <- all_markers %>% group_by(cluster) %>% top_n(n = 10, wt = avg_log2FC) 442 | # heatmap 443 | DoHeatmap(mdm, features = top10$gene, group.colors = c('#EAB308', '#EF4444', '#F97316', '#854D0E', '#C798EE', '#3B82F6')) 444 | ``` 445 | 446 | ```{r fig.height = 9, fig.width = 6, fig.align = 'center'} 447 | # Featureplot 448 | p <- FeaturePlot(mdm, reduction = 'tsne', features = c('F13A1', 'SEMA3C', 'ZNF331', 'MT-ND3', 'HSP90AA1', 'LSAMP')) 449 | p 450 | ``` 451 | 452 | ### Average expression of MT genes (C4 markers) 453 | ```{r fig.height = 6, fig.width = 6, fig.align = 'center'} 454 | c4_marker_mito <- c("MT-ND1", "MT-ND4", "MT-CYB", "MT-ATP8", "MT-ND3", "MT-ND5", "MT-ND2", "MT-ATP6", "MT-CO3", 455 | "MT-ND6", "MT-ND4L", "MT-CO2", "MT-CO1") 456 | gene_to_heatmap <- AverageExpression(mdm, slot = 'count', features = c4_marker_mito)$RNA 457 | 458 | write.csv(gene_to_heatmap, file = paste0(output_dir, '/MT_gene_average_expression.csv')) 459 | 460 | pheatmap(t(gene_to_heatmap), 461 | cluster_rows = FALSE, 462 | cluster_cols = FALSE, 463 | border_color = 'white', 464 | color = colorRampPalette(viridis(9))(100), 465 | cellwidth = 20, 466 | cellheight = 20) 467 | ``` 468 | 469 | ### Average expression of non-MT genes (C4 markers) 470 | ```{r fig.height = 4, fig.width = 10, fig.align = 'center'} 471 | c4_marker_non_mito <- c("B2M", "APOE", "LNCAROD", "C1QA", "TMSB4X", "NUPR1", "TMEM51", "KCTD12", "RNASE1", 472 | "GRN", "ZBTB1", "SSBP3", "HLA-DRA", "CD74", "FTL", "CEBPD", "EPSTI1", "NLRC5", "ORMDL1", 473 | "SBNO2", "NUDCD3", "CORO2A", "QSOX1", "ST8SIA4", "MAFB", "CTSS", "BTG1", "CLIC4", 474 | "CD14", "CARD8", "NFATC3", "RAPGEF6", "INO80D", "ZNF292", "PIK3AP1") 475 | gene_to_heatmap <- AverageExpression(mdm, slot = 'count', features = c4_marker_non_mito)$RNA 476 | 477 | write.csv(gene_to_heatmap, file = paste0(output_dir, '/non_MT_gene_average_expression.csv')) 478 | 479 | pheatmap(t(gene_to_heatmap), 480 | cluster_rows = FALSE, 481 | cluster_cols = FALSE, 482 | border_color = 'white', 483 | color = colorRampPalette(viridis(9))(100), 484 | cellwidth = 15, 485 | cellheight = 15) 486 | ``` 487 | 488 | ### non-MT genes highly expressed in C4 (MHC I class genes) 489 | ```{r fig.height = 4, fig.width = 6, fig.align = 'center'} 490 | p <- VlnPlot(mdm, features = c('B2M', 'HLA-DRA', 'CD74', 'CTSS'), 491 | pt.size = 0, cols = c('#3B82F6', '#EF4444', '#C798EE', '#EAB308', '#F97316', '#854D0E')) 492 | p 493 | ``` 494 | 495 | ### MDM/TMDM subclusters analysis using Seurat 496 | ```{r fig.height = 4, fig.width = 10, fig.align = 'center'} 497 | p1 <- ggplot() + 498 | geom_point(mdm_meta_new, mapping = aes(tsne1,tsne2,color = seurat_clusters), size = 3) + 499 | scale_color_manual(values = c('#EAB308', '#EF4444', '#3B82F6', '#C798EE', '#F97316', '#854D0E')) + 500 | theme_classic() + 501 | ggtitle('MDM/TMDM subclusters (Seurat)') + 502 | theme(plot.title = element_text(hjust = 0.5)) + 503 | theme(legend.title = element_blank()) 504 | 505 | p2 <- VlnPlot(mdm, features = c('B2M', 'HLA-DRA', 'CD74', 'CTSS'), group.by = 'seurat_clusters', pt.size=0, cols = c('#EAB308', '#EF4444', '#3B82F6', '#C798EE', '#F97316', '#854D0E')) 506 | 507 | cowplot::plot_grid(p1, p2) 508 | 509 | ``` 510 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/DEGs_starmap.csv: -------------------------------------------------------------------------------- 1 | "","p_val","avg_log2FC","pct.1","pct.2","p_val_adj","cluster","gene" 2 | "Pcp4",5.52994783265023e-45,2.14650426368579,0.601,0.172,5.64054678930324e-42,"L6","Pcp4" 3 | "X3110035E14Rik",4.01884444373145e-42,1.99229587187926,0.695,0.291,4.09922133260608e-39,"L6","X3110035E14Rik" 4 | "Rprm",3.80508133010825e-21,1.38335707588428,0.646,0.364,3.88118295671041e-18,"L6","Rprm" 5 | "Tle4",9.76359623219227e-19,1.41189787161448,0.525,0.249,9.95886815683612e-16,"L6","Tle4" 6 | "Hpcal4",1.26760659436933e-18,0.717287724339745,0.928,0.736,1.29295872625671e-15,"L6","Hpcal4" 7 | "Arhgap25",2.03071679283173e-16,1.32215638665533,0.422,0.175,2.07133112868836e-13,"L6","Arhgap25" 8 | "Nptx1",3.02285737222327e-16,1.01613067268938,0.691,0.438,3.08331451966773e-13,"L6","Nptx1" 9 | "Ogfrl1",6.30335355817849e-14,0.929101107838621,0.637,0.387,6.42942062934206e-11,"L6","Ogfrl1" 10 | "Garnl3",2.5267891716968e-13,1.46823669830471,0.368,0.17,2.57732495513073e-10,"L6","Garnl3" 11 | "Arc",5.24910445857555e-13,0.938368694033685,0.753,0.574,5.35408654774706e-10,"L6","Arc" 12 | "Slc17a7",9.33369228767695e-12,0.640045149092102,0.839,0.672,9.52036613343049e-09,"L6","Slc17a7" 13 | "Col6a1",1.34832934315239e-11,1.43511676889979,0.341,0.159,1.37529593001543e-08,"L6","Col6a1" 14 | "Pcsk2",1.68230622939461e-11,0.634622280520908,0.812,0.603,1.7159523539825e-08,"L6","Pcsk2" 15 | "Pgm2l1",1.71995381460967e-11,0.632196090642059,0.834,0.647,1.75435289090187e-08,"L6","Pgm2l1" 16 | "Syn1",1.68039771849225e-10,0.666961869836484,0.74,0.568,1.7140056728621e-07,"L6","Syn1" 17 | "Ptk2",2.80486182555293e-09,0.937789176454751,0.448,0.257,2.86095906206399e-06,"L6","Ptk2" 18 | "Klf10",2.85192808382252e-09,0.922365890234871,0.475,0.294,2.90896664549897e-06,"L6","Klf10" 19 | "Arx",3.00366551661635e-09,0.578768261017132,0.776,0.585,3.06373882694868e-06,"L6","Arx" 20 | "Rasgrp1",3.1776179790911e-09,0.770750463889819,0.471,0.267,3.24117033867292e-06,"L6","Rasgrp1" 21 | "Nrp1",5.79254293303199e-09,1.07589974892201,0.274,0.123,5.90839379169263e-06,"L6","Nrp1" 22 | "Snx10",3.07952413188563e-08,0.555726175391807,0.659,0.449,3.14111461452334e-05,"L6","Snx10" 23 | "Cdh18",1.44025276618245e-07,0.994511489935334,0.238,0.106,0.00014690578215061,"L6","Cdh18" 24 | "X1110008P14Rik",1.48387553760045e-07,0.936185225805391,0.408,0.25,0.000151355304835246,"L6","X1110008P14Rik" 25 | "Plcxd3",2.85791361664326e-07,0.987137071844842,0.354,0.2,0.000291507188897612,"L6","Plcxd3" 26 | "Pdlim1",3.49683263388431e-07,1.11310764342433,0.188,0.076,0.000356676928656199,"L6","Pdlim1" 27 | "Fxyd7",3.77057349535427e-07,0.540734574028797,0.691,0.51,0.000384598496526135,"L6","Fxyd7" 28 | "St3gal5",9.810565435207e-07,0.56119788426824,0.65,0.493,0.00100067767439111,"L6","St3gal5" 29 | "Anapc13",1.2468493549096e-06,0.832238722199556,0.395,0.244,0.00127178634200779,"L6","Anapc13" 30 | "Rab26",2.03863279437458e-06,1.08226489770229,0.278,0.155,0.00207940545026207,"L6","Rab26" 31 | "Slc24a2",2.99283467895756e-06,0.54374838398548,0.543,0.387,0.00305269137253671,"L6","Slc24a2" 32 | "Homer1",3.25998016366246e-06,0.676263923446097,0.525,0.36,0.00332517976693571,"L6","Homer1" 33 | "Prkcg",8.39658181897297e-06,0.839148815086928,0.453,0.31,0.00856451345535243,"L6","Prkcg" 34 | "Efr3a",9.34775982027421e-06,0.620615662585939,0.475,0.331,0.00953471501667969,"L6","Efr3a" 35 | "Slc6a15",1.2327177432897e-05,0.596197445876438,0.466,0.315,0.012573720981555,"L6","Slc6a15" 36 | "X1700019D03Rik",2.35699978231705e-05,0.754883195165629,0.336,0.21,0.0240413977796339,"L6","X1700019D03Rik" 37 | "B3galt2",3.78852929036737e-05,0.914312636657826,0.26,0.154,0.0386429987617472,"L6","B3galt2" 38 | "Itm2c",4.6568506095821e-05,0.53073860520468,0.552,0.434,0.0474998762177374,"L6","Itm2c" 39 | "Gria3",0.000105689728680921,0.533071820105523,0.417,0.286,0.107803523254539,"L6","Gria3" 40 | "Pitpnc1",0.000113740426572601,0.503216410606073,0.341,0.214,0.116015235104053,"L6","Pitpnc1" 41 | "Stx1a",0.000121203590704647,0.602892453018783,0.359,0.236,0.12362766251874,"L6","Stx1a" 42 | "Ipcef1",0.000274614470795035,0.713712823938276,0.202,0.112,0.280106760210936,"L6","Ipcef1" 43 | "Slc5a7",0.000413472190189203,0.734668936645479,0.215,0.126,0.421741633992987,"L6","Slc5a7" 44 | "Syt6",0.000492628935010536,0.636619314346107,0.22,0.129,0.502481513710746,"L6","Syt6" 45 | "Ano3",0.000505046325819418,0.62834110694795,0.341,0.239,0.515147252335806,"L6","Ano3" 46 | "Gpr22",0.000551742062243723,0.56825842091206,0.318,0.216,0.562776903488597,"L6","Gpr22" 47 | "Nfia",0.000567165778978726,0.78746456448652,0.184,0.103,0.578509094558301,"L6","Nfia" 48 | "Tbr1",0.00107870041726061,0.67789846002236,0.296,0.203,1,"L6","Tbr1" 49 | "Obox3",0.00114014300069927,0.527086991842171,0.22,0.134,1,"L6","Obox3" 50 | "Idi1",0.00131945900486207,0.618532821972636,0.26,0.167,1,"L6","Idi1" 51 | "Npas4",0.00172380252273486,0.643812408640338,0.287,0.194,1,"L6","Npas4" 52 | "Mmp16",0.00225781853461978,0.662515738626931,0.283,0.2,1,"L6","Mmp16" 53 | "Ctxn3",0.0030870854586583,0.604855223724219,0.229,0.147,1,"L6","Ctxn3" 54 | "Cpne5",0.00565283875270732,0.521274481257476,0.309,0.227,1,"L6","Cpne5" 55 | "Sema3e",0.00576141333421758,0.605043697919634,0.157,0.095,1,"L6","Sema3e" 56 | "Lmo3",0.00618820693736147,0.519275898203543,0.309,0.224,1,"L6","Lmo3" 57 | "Pcdha5",0.00665565532364777,0.608560936580506,0.197,0.133,1,"L6","Pcdha5" 58 | "C730002L08Rik",0.00695294325652162,0.549213967101861,0.175,0.11,1,"L6","C730002L08Rik" 59 | "Efhd2",0.00925386620563434,0.570423288215215,0.242,0.171,1,"L6","Efhd2" 60 | "Nrsn1",7.23906161911071e-44,1.5741536073085,0.845,0.501,7.38384285149292e-41,"L4","Nrsn1" 61 | "Egr1",3.79101225916544e-29,1.41655810728683,0.763,0.455,3.86683250434874e-26,"L4","Egr1" 62 | "Camk2n1",1.28491966384878e-28,0.858983303373438,0.983,0.866,1.31061805712575e-25,"L4","Camk2n1" 63 | "Zmat4",4.38045134032699e-28,1.63294138245761,0.539,0.209,4.46806036713353e-25,"L4","Zmat4" 64 | "Nrep",9.42893292377221e-27,1.50071100124534,0.629,0.312,9.61751158224765e-24,"L4","Nrep" 65 | "Whrn",5.86551694734778e-17,1.37193715632531,0.478,0.227,5.98282728629473e-14,"L4","Whrn" 66 | "Arc1",2.15970340137585e-13,0.63734100855105,0.78,0.566,2.20289746940336e-10,"L4","Arc" 67 | "Mef2c",2.31932305330235e-10,0.821222643919695,0.565,0.374,2.3657095143684e-07,"L4","Mef2c" 68 | "Rorb",4.6325371455539e-10,1.13933628675489,0.358,0.183,4.72518788846497e-07,"L4","Rorb" 69 | "Nrn1",7.73119747920001e-10,0.727398775226397,0.586,0.385,7.88582142878401e-07,"L4","Nrn1" 70 | "Pamr1",9.2201287003694e-10,1.21277954965985,0.194,0.067,9.40453127437679e-07,"L4","Pamr1" 71 | "Cux2",1.18749980703972e-08,0.742381384763552,0.5,0.308,1.21124980318052e-05,"L4","Cux2" 72 | "Nell1",2.05438835008246e-08,0.93158053724283,0.552,0.388,2.09547611708411e-05,"L4","Nell1" 73 | "Snca",7.64163613941064e-08,0.61445017167414,0.694,0.555,7.79446886219885e-05,"L4","Snca" 74 | "Nudt4",8.11865848700165e-08,0.745260213807436,0.44,0.269,8.28103165674168e-05,"L4","Nudt4" 75 | "Epha4",9.40472428463228e-08,0.81149372803082,0.487,0.33,9.59281877032493e-05,"L4","Epha4" 76 | "Egr3",2.10853483874152e-07,0.686254813851037,0.565,0.396,0.000215070553551635,"L4","Egr3" 77 | "Ralyl",2.83345866174247e-07,0.671073314641947,0.5,0.348,0.000289012783497732,"L4","Ralyl" 78 | "Btbd3",4.59918275675397e-07,0.891226896514263,0.388,0.244,0.000469116641188905,"L4","Btbd3" 79 | "Osbpl1a",4.70814923537492e-07,0.781124551622579,0.384,0.238,0.000480231222008242,"L4","Osbpl1a" 80 | "Arpp21",8.47634052316421e-07,0.700300624929771,0.642,0.529,0.00086458673336275,"L4","Arpp21" 81 | "X2900055J20Rik",9.13626416089784e-07,0.763543290505279,0.453,0.302,0.00093189894441158,"L4","X2900055J20Rik" 82 | "Plcxd2",1.23530726556292e-06,1.05344946197166,0.19,0.084,0.00126001341087418,"L4","Plcxd2" 83 | "Satb2",1.75471539640686e-06,0.738125687267868,0.491,0.339,0.00178980970433499,"L4","Satb2" 84 | "Grik1",7.60301404609683e-06,1.01866392286873,0.237,0.124,0.00775507432701877,"L4","Grik1" 85 | "Nr4a1",8.06710506740604e-06,0.650611921038291,0.496,0.348,0.00822844716875416,"L4","Nr4a1" 86 | "Cpne9",1.68912386437158e-05,0.983244830505565,0.25,0.144,0.0172290634165901,"L4","Cpne9" 87 | "Foxp1",4.62596562247274e-05,0.784650175799453,0.28,0.165,0.047184849349222,"L4","Foxp1" 88 | "Spock3",5.00162465789816e-05,0.84420553134671,0.216,0.117,0.0510165715105612,"L4","Spock3" 89 | "Gfra2",8.80374892725387e-05,0.726605862558507,0.405,0.297,0.0897982390579895,"L4","Gfra2" 90 | "Egr2",9.57025671190647e-05,0.662484941475747,0.31,0.197,0.097616618461446,"L4","Egr2" 91 | "Vgf",0.000137765381294501,0.557640618124698,0.47,0.344,0.140520688920391,"L4","Vgf" 92 | "Fam19a2",0.000194078982778318,0.638680963937566,0.353,0.235,0.197960562433885,"L4","Fam19a2" 93 | "Rit2",0.000264442979414777,0.598366508504173,0.384,0.279,0.269731839003072,"L4","Rit2" 94 | "Syndig1",0.000344745093464633,0.596899732604372,0.284,0.182,0.351639995333926,"L4","Syndig1" 95 | "S100a10",0.0004371251574989,0.627061001736399,0.267,0.175,0.445867660648878,"L4","S100a10" 96 | "Hnrnph2",0.000677447555387016,0.532987048269152,0.392,0.287,0.690996506494757,"L4","Hnrnph2" 97 | "Nos1",0.000765474268739021,0.667445133473259,0.207,0.124,0.780783754113802,"L4","Nos1" 98 | "Dusp14",0.000811181823189736,0.711602550152013,0.25,0.165,0.827405459653531,"L4","Dusp14" 99 | "Hmgcr",0.0016904440648399,0.521995905746759,0.366,0.27,1,"L4","Hmgcr" 100 | "Cbln4",0.00178968993807231,0.66977878962358,0.177,0.105,1,"L4","Cbln4" 101 | "Cnih3",0.00182574750106368,0.514114838915157,0.345,0.253,1,"L4","Cnih3" 102 | "Rgs4",0.00201388656734114,0.513524893777207,0.384,0.288,1,"L4","Rgs4" 103 | "Chrm2",0.0029992796940059,0.513149812906267,0.267,0.181,1,"L4","Chrm2" 104 | "Fbxo11",0.00358487644903016,0.581720980312428,0.233,0.156,1,"L4","Fbxo11" 105 | "Lrrc4c",0.00463376447297917,0.649245341830728,0.237,0.166,1,"L4","Lrrc4c" 106 | "Pcdhb7",0.00543657920658995,0.658763268043111,0.112,0.061,1,"L4","Pcdhb7" 107 | "Scml4",0.00619755996308728,0.556724706765482,0.151,0.091,1,"L4","Scml4" 108 | "Camk4",0.0091161877797647,0.587944521112682,0.172,0.113,1,"L4","Camk4" 109 | "Lamp5",3.66980779111143e-49,1.91552193381508,0.744,0.308,3.74320394693366e-46,"L2/3","Lamp5" 110 | "Camk2n11",1.44411378662633e-36,0.87104473422646,0.981,0.862,1.47299606235885e-33,"L2/3","Camk2n1" 111 | "Cux21",5.06537141968682e-29,1.3226734710255,0.626,0.267,5.16667884808055e-26,"L2/3","Cux2" 112 | "Cpne51",2.16578701835151e-18,1.09612258963261,0.454,0.183,2.20910275871855e-15,"L2/3","Cpne5" 113 | "Nrgn",8.92359352276684e-18,0.707295492709649,0.897,0.697,9.10206539322218e-15,"L2/3","Nrgn" 114 | "Enc1",1.81427244126243e-16,0.83875109615125,0.618,0.334,1.85055789008768e-13,"L2/3","Enc1" 115 | "Calb1",3.41900215267736e-15,1.28716048359496,0.317,0.116,3.48738219573091e-12,"L2/3","Calb1" 116 | "Cbln2",2.53003186889626e-14,1.03074735225577,0.515,0.278,2.58063250627418e-11,"L2/3","Cbln2" 117 | "Gucy1b3",1.32118763191791e-13,0.830553661520547,0.607,0.364,1.34761138455627e-10,"L2/3","Gucy1b3" 118 | "Ddit4l",1.61490350916266e-13,1.13877873290154,0.244,0.076,1.64720157934591e-10,"L2/3","Ddit4l" 119 | "Pcsk21",9.27286108636596e-13,0.715928066135392,0.782,0.602,9.45831830809328e-10,"L2/3","Pcsk2" 120 | "Nr4a11",1.15430779019837e-10,0.729558199195297,0.546,0.329,1.17739394600234e-07,"L2/3","Nr4a1" 121 | "X2900055J20Rik1",1.30726611299039e-10,0.796159130339213,0.492,0.286,1.33341143525019e-07,"L2/3","X2900055J20Rik" 122 | "Camk2a",1.80713086129622e-10,0.558177675204675,0.786,0.543,1.84327347852215e-07,"L2/3","Camk2a" 123 | "Lrrtm4",2.5279410797104e-10,0.883639025025325,0.321,0.144,2.57849990130461e-07,"L2/3","Lrrtm4" 124 | "Cenpw",1.02917131199735e-09,0.999767868855619,0.317,0.153,1.0497547382373e-06,"L2/3","Cenpw" 125 | "Efna5",5.9088822010461e-09,0.901751044589718,0.359,0.186,6.02705984506702e-06,"L2/3","Efna5" 126 | "Trp53i11",2.33714644768813e-08,0.846937016759762,0.344,0.184,2.3838893766419e-05,"L2/3","Trp53i11" 127 | "Acvr1c",2.93653694330845e-08,0.719042401635915,0.355,0.192,2.99526768217462e-05,"L2/3","Acvr1c" 128 | "Atp2b4",8.24853388349099e-08,0.89709205742434,0.275,0.137,8.41350456116081e-05,"L2/3","Atp2b4" 129 | "Rbfox3",1.2758533016473e-07,0.750286245559642,0.45,0.281,0.000130137036768024,"L2/3","Rbfox3" 130 | "Chodl",1.53509446909417e-07,0.862885443834019,0.248,0.116,0.000156579635847605,"L2/3","Chodl" 131 | "Car10",1.67522080893593e-07,0.793210172078162,0.298,0.152,0.000170872522511465,"L2/3","Car10" 132 | "Nell2",1.77745919493807e-07,0.861392781632943,0.271,0.137,0.000181300837883683,"L2/3","Nell2" 133 | "Nectin3",1.81757126127172e-07,0.710117642582952,0.401,0.229,0.000185392268649716,"L2/3","Nectin3" 134 | "Rsph9",2.69257418555156e-07,0.927044782172142,0.168,0.065,0.000274642566926259,"L2/3","Rsph9" 135 | "Nrn11",3.05824356038805e-07,0.547187924576972,0.565,0.384,0.000311940843159581,"L2/3","Nrn1" 136 | "X6330403K07Rik",3.60096503051553e-07,0.686224646211152,0.279,0.139,0.000367298433112584,"L2/3","X6330403K07Rik" 137 | "Fam19a21",4.11014422625529e-07,0.586305436936738,0.389,0.221,0.00041923471107804,"L2/3","Fam19a2" 138 | "Lrrc4c1",4.944891738196e-07,0.716309517281832,0.29,0.149,0.000504378957295992,"L2/3","Lrrc4c" 139 | "Cd34",6.69335728682245e-07,0.658041391029057,0.321,0.175,0.00068272244325589,"L2/3","Cd34" 140 | "Ptpn2",8.14516106951469e-07,0.622756221051355,0.252,0.122,0.000830806429090499,"L2/3","Ptpn2" 141 | "Ptgs2",9.79933995863862e-07,0.972216029464756,0.225,0.105,0.000999532675781139,"L2/3","Ptgs2" 142 | "Fosl2",1.3744752940499e-06,0.747469393479483,0.332,0.19,0.00140196479993089,"L2/3","Fosl2" 143 | "Ptchd2",1.9194060951934e-06,0.710958940337194,0.225,0.111,0.00195779421709727,"L2/3","Ptchd2" 144 | "Ptk2b",2.14114612242775e-06,0.634772288334147,0.412,0.252,0.0021839690448763,"L2/3","Ptk2b" 145 | "X1700086L19Rik",2.21932885429204e-06,0.685815270666915,0.328,0.189,0.00226371543137788,"L2/3","X1700086L19Rik" 146 | "Arpp211",2.59562312679982e-06,0.509673637076189,0.66,0.521,0.00264753558933581,"L2/3","Arpp21" 147 | "Ralyl1",3.47076852394955e-06,0.573639326881924,0.508,0.341,0.00354018389442854,"L2/3","Ralyl" 148 | "Mef2c1",3.51288203834102e-06,0.512058701366271,0.542,0.375,0.00358313967910784,"L2/3","Mef2c" 149 | "B230216N24Rik",3.51775009115177e-06,0.719950142826318,0.221,0.108,0.0035881050929748,"L2/3","B230216N24Rik" 150 | "Gria31",3.84459195271401e-06,0.524123214714924,0.435,0.275,0.00392148379176829,"L2/3","Gria3" 151 | "Pcdhb19",4.45545801912821e-06,0.777926202128252,0.198,0.093,0.00454456717951077,"L2/3","Pcdhb19" 152 | "Pdlim3",4.50069319971527e-06,0.701152685855864,0.26,0.139,0.00459070706370958,"L2/3","Pdlim3" 153 | "Cyb5r1",4.56679478380407e-06,0.582783480254336,0.244,0.126,0.00465813067948015,"L2/3","Cyb5r1" 154 | "Glt8d2",4.79931327389878e-06,0.7170625209065,0.282,0.152,0.00489529953937675,"L2/3","Glt8d2" 155 | "Ptn",4.84979464424312e-06,0.519538015166196,0.378,0.219,0.00494679053712798,"L2/3","Ptn" 156 | "Arpp19",5.03947166512861e-06,0.51857480800012,0.519,0.357,0.00514026109843118,"L2/3","Arpp19" 157 | "Egr4",5.69820679624407e-06,0.720357569678328,0.24,0.125,0.00581217093216895,"L2/3","Egr4" 158 | "Wt1",6.23193753296308e-06,0.713705395975799,0.183,0.084,0.00635657628362235,"L2/3","Wt1" 159 | "Pdzrn3",7.2447410916497e-06,0.665707393094456,0.385,0.241,0.0073896359134827,"L2/3","Pdzrn3" 160 | "Skil",8.25876704905922e-06,0.550144210982253,0.298,0.167,0.0084239423900404,"L2/3","Skil" 161 | "Vip",9.5557040520132e-06,1.47967402193907,0.214,0.109,0.00974681813305346,"L2/3","Vip" 162 | "Herc3",1.36337419595036e-05,0.614905008635465,0.302,0.172,0.0139064167986936,"L2/3","Herc3" 163 | "Ttyh1",1.6240070197839e-05,0.651699088637335,0.382,0.243,0.0165648716017958,"L2/3","Ttyh1" 164 | "Pcdhb2",1.99628286344e-05,0.555915244580013,0.256,0.143,0.020362085207088,"L2/3","Pcdhb2" 165 | "Itm2a",2.29543945411187e-05,0.808307051110131,0.233,0.126,0.0234134824319411,"L2/3","Itm2a" 166 | "Adm",2.61019796877386e-05,0.885045963420287,0.118,0.048,0.0266240192814934,"L2/3","Adm" 167 | "Rasgef1b",2.7565796136891e-05,0.530893571096449,0.244,0.132,0.0281171120596288,"L2/3","Rasgef1b" 168 | "Adk",4.10704780305577e-05,0.736494938833014,0.176,0.087,0.0418918875911689,"L2/3","Adk" 169 | "Rgs41",4.68042469073209e-05,0.564254025933605,0.42,0.275,0.0477403318454673,"L2/3","Rgs4" 170 | "Cacng3",4.75243873399403e-05,0.644704086226482,0.355,0.232,0.0484748750867392,"L2/3","Cacng3" 171 | "Dlx1",5.20571339734539e-05,0.757455366795206,0.164,0.079,0.053098276652923,"L2/3","Dlx1" 172 | "Gpr88",9.83241402715632e-05,0.621038922295348,0.279,0.169,0.100290623076994,"L2/3","Gpr88" 173 | "Pcdhb9",0.000109120554995124,0.532100979552728,0.256,0.148,0.111302966095027,"L2/3","Pcdhb9" 174 | "Pcdhb11",0.000118667772873231,0.581169370481358,0.141,0.066,0.121041128330695,"L2/3","Pcdhb11" 175 | "Pcdhga8",0.000129853884124749,0.519033844272103,0.218,0.12,0.132450961807244,"L2/3","Pcdhga8" 176 | "Gpr151",0.000134181905403226,0.536002186805389,0.237,0.135,0.136865543511291,"L2/3","Gpr151" 177 | "Nptx2",0.000158602933300447,0.51797823872194,0.286,0.177,0.161774991966456,"L2/3","Nptx2" 178 | "Penk",0.000166091466861298,0.696394276589771,0.233,0.139,0.169413296198524,"L2/3","Penk" 179 | "Dcn",0.000176906706238821,0.605741286436307,0.134,0.062,0.180444840363598,"L2/3","Dcn" 180 | "Gm765",0.000231591566981269,0.793772756512939,0.29,0.186,0.236223398320894,"L2/3","Gm765" 181 | "Lin7b",0.000236371102995397,0.541122669822179,0.286,0.18,0.241098525055305,"L2/3","Lin7b" 182 | "Btbd10",0.000274578966976598,0.618655712968628,0.248,0.15,0.28007054631613,"L2/3","Btbd10" 183 | "Trim32",0.000298401757342806,0.507977152364097,0.366,0.249,0.304369792489662,"L2/3","Trim32" 184 | "Cited1",0.000345126744720481,0.545972202996576,0.149,0.075,0.352029279614891,"L2/3","Cited1" 185 | "Pcdha51",0.000359196303501419,0.510490026531889,0.218,0.125,0.366380229571448,"L2/3","Pcdha5" 186 | "Cck",0.000390776296517091,0.647476269938392,0.145,0.074,0.398591822447433,"L2/3","Cck" 187 | "Bcar3",0.00043066687308687,0.501751081583371,0.294,0.188,0.439280210548608,"L2/3","Bcar3" 188 | "Pcdhga7",0.000517547403219853,0.529543246258775,0.282,0.179,0.52789835128425,"L2/3","Pcdhga7" 189 | "Tmx1",0.000537195194089707,0.549789999715377,0.237,0.144,0.547939097971501,"L2/3","Tmx1" 190 | "Htr3a",0.0005530744733133,0.744872561034185,0.141,0.072,0.564135962779566,"L2/3","Htr3a" 191 | "Flpo",0.000584685161523634,0.553905335961613,0.145,0.074,0.596378864754106,"L2/3","Flpo" 192 | "Chrm21",0.000639873867750676,0.598510964009418,0.271,0.177,0.652671345105689,"L2/3","Chrm2" 193 | "Pcdhb17",0.000742055368751118,0.53815878984759,0.218,0.129,0.75689647612614,"L2/3","Pcdhb17" 194 | "Wfs1",0.000762388767740869,0.814841188930781,0.134,0.069,0.777636543095686,"L2/3","Wfs1" 195 | "Rgs8",0.00107943442052924,0.710316721058641,0.149,0.08,1,"L2/3","Rgs8" 196 | "Skap1",0.0011010687552351,0.582468514757153,0.282,0.187,1,"L2/3","Skap1" 197 | "Cbln41",0.00132499183169679,0.556977087754115,0.176,0.103,1,"L2/3","Cbln4" 198 | "Cd7",0.00151173510809438,0.654895518730535,0.172,0.102,1,"L2/3","Cd7" 199 | "Tmem215",0.001853332475003,0.519563515261213,0.198,0.122,1,"L2/3","Tmem215" 200 | "Cdk4",0.00229795516386357,0.50961903130755,0.141,0.078,1,"L2/3","Cdk4" 201 | "Ephx2",0.00294704088032987,0.513215611769445,0.172,0.103,1,"L2/3","Ephx2" 202 | "Thsd7a",0.00348807373082877,0.559983429558063,0.179,0.112,1,"L2/3","Thsd7a" 203 | "St3gal6",0.00360156812147586,0.550921900675123,0.118,0.063,1,"L2/3","St3gal6" 204 | "Smim8",0.0038728787715026,0.517842786311477,0.233,0.154,1,"L2/3","Smim8" 205 | "Crip2",0.00409499858185449,0.521480897254056,0.374,0.28,1,"L2/3","Crip2" 206 | "Mas1",0.00668626525260274,0.666878913872491,0.103,0.055,1,"L2/3","Mas1" 207 | "Dhrs3",0.00766310763187726,0.615109421178318,0.176,0.113,1,"L2/3","Dhrs3" 208 | "Foxp2",0.00852955197250509,0.545543019681397,0.111,0.062,1,"L2/3","Foxp2" 209 | "Camk2a1",9.81520121587716e-09,0.965872020354466,0.757,0.579,1.00115052401947e-05,"L1","Camk2a" 210 | "Fosb",3.09646910917638e-08,1.00058689941114,0.703,0.502,3.15839849135991e-05,"L1","Fosb" 211 | "Hpcal41",4.73709023720236e-08,0.895298670034147,0.874,0.761,4.8318320419464e-05,"L1","Hpcal4" 212 | "Camk2n12",5.97102985036036e-08,0.527531892635579,0.955,0.881,6.09045044736757e-05,"L1","Camk2n1" 213 | "Pcdhac2",1.52251038662404e-06,1.4076940892422,0.18,0.059,0.00155296059435652,"L1","Pcdhac2" 214 | "Cux22",1.36043963712507e-05,0.892146081052945,0.523,0.327,0.0138764842986757,"L1","Cux2" 215 | "Btbd11",2.37855620735035e-05,0.973043003195559,0.532,0.359,0.0242612733149736,"L1","Btbd11" 216 | "Bsg",6.53112507254391e-05,0.659848422286122,0.559,0.421,0.0666174757399479,"L1","Bsg" 217 | "Mapk3",9.7276951652946e-05,0.93761221444135,0.243,0.115,0.099222490686005,"L1","Mapk3" 218 | "Tmem176a",0.000110642398613413,1.11766297652847,0.297,0.158,0.112855246585681,"L1","Tmem176a" 219 | "Itm2a1",0.000251929731995325,0.919005146927914,0.261,0.138,0.256968326635232,"L1","Itm2a" 220 | "Pfn1",0.000263169403072857,1.08204983795012,0.252,0.134,0.268432791134314,"L1","Pfn1" 221 | "Sdc4",0.000268061329872921,0.745242331588592,0.604,0.465,0.27342255647038,"L1","Sdc4" 222 | "Wfs11",0.00029631495891192,0.98928383136213,0.171,0.074,0.302241258090158,"L1","Wfs1" 223 | "Glul",0.000298060326625853,0.503452757975648,0.892,0.901,0.30402153315837,"L1","Glul" 224 | "B2m",0.00040416362644854,0.716269682911794,0.432,0.278,0.412246898977511,"L1","B2m" 225 | "Sgk1",0.000533049496082616,1.06983510053123,0.324,0.203,0.543710486004268,"L1","Sgk1" 226 | "Nell21",0.000858621097127548,0.954794161389083,0.27,0.155,0.875793519070099,"L1","Nell2" 227 | "Pcdh8",0.00125571201654819,0.62195574382669,0.378,0.244,1,"L1","Pcdh8" 228 | "Myo5b",0.00179718935535024,0.90070579859649,0.162,0.078,1,"L1","Myo5b" 229 | "Abhd3",0.00182577127041894,0.905809253477873,0.243,0.142,1,"L1","Abhd3" 230 | "Slc38a3",0.00195386716508055,0.714677449834267,0.396,0.265,1,"L1","Slc38a3" 231 | "Gpm6b",0.00196566010503703,0.580869578027183,0.694,0.577,1,"L1","Gpm6b" 232 | "Aldh1l1",0.00210298085461146,1.12743497081162,0.207,0.115,1,"L1","Aldh1l1" 233 | "Nat8f1",0.00231197303168397,1.05302218895438,0.27,0.162,1,"L1","Nat8f1" 234 | "Inhba",0.00271758551204047,0.815773177187916,0.225,0.125,1,"L1","Inhba" 235 | "C1ql3",0.0027851153657435,0.639644212840066,0.378,0.253,1,"L1","C1ql3" 236 | "Nr2f2",0.00338392501263764,0.791983466933333,0.216,0.12,1,"L1","Nr2f2" 237 | "Sepp1",0.00429975152166601,0.821260994073221,0.468,0.376,1,"L1","Sepp1" 238 | "Prc1",0.00441091670242078,0.696924925762886,0.279,0.17,1,"L1","Prc1" 239 | "Slc1a3",0.004660436064834,0.955980102905765,0.586,0.507,1,"L1","Slc1a3" 240 | "Adarb2",0.00565075488436639,1.01822598311269,0.234,0.146,1,"L1","Adarb2" 241 | "Stx12",0.00577312232730529,0.768215659866426,0.171,0.09,1,"L1","Stx12" 242 | "Dgkb",0.00578102426201576,1.01262612333672,0.234,0.142,1,"L1","Dgkb" 243 | "Sparc",0.00643701155910009,0.716197392038294,0.261,0.162,1,"L1","Sparc" 244 | "Znhit3",0.00668606188525176,0.913540870272503,0.162,0.088,1,"L1","Znhit3" 245 | "S100a16",0.00746874317921263,0.740087287671085,0.342,0.246,1,"L1","S100a16" 246 | "Rgs81",0.00766765840187434,0.843395545842034,0.162,0.089,1,"L1","Rgs8" 247 | "Tmbim6",0.00966760815941394,0.602362481921111,0.432,0.323,1,"L1","Tmbim6" 248 | "Atp1b2",0.00973556273468001,0.611522750165142,0.36,0.256,1,"L1","Atp1b2" 249 | "Hlf",0.00974488018813224,0.502057754224952,0.91,0.904,1,"L1","Hlf" 250 | "Coro6",0.00982092969122705,0.550316648499994,0.252,0.157,1,"L1","Coro6" 251 | "Mbp",1.86447304010502e-92,3.67951761077413,0.987,0.373,1.90176250090712e-89,"CC","Mbp" 252 | "Mobp",1.75684021493073e-86,3.41546373895894,0.974,0.369,1.79197701922934e-83,"CC","Mobp" 253 | "Plp1",3.28010186457621e-71,3.64234712853681,0.922,0.349,3.34570390186773e-68,"CC","Plp1" 254 | "Gatm",1.01275762917043e-40,2.42423248169432,0.708,0.262,1.03301278175384e-37,"CC","Gatm" 255 | "Trf",4.71802980866908e-40,2.51821910142948,0.623,0.186,4.81239040484246e-37,"CC","Trf" 256 | "Mcts1",3.80353612677908e-33,2.65096869937628,0.539,0.171,3.87960684931466e-30,"CC","Mcts1" 257 | "Cav1",1.60843458683635e-31,2.10117169266395,0.584,0.197,1.64060327857307e-28,"CC","Cav1" 258 | "Mal",2.65397883065207e-30,2.67887844847499,0.526,0.174,2.70705840726511e-27,"CC","Mal" 259 | "Sept4",3.05798688879303e-27,2.15994723459124,0.656,0.323,3.11914662656889e-24,"CC","Sept4" 260 | "Plekhb1",1.10738532440604e-26,1.38534284276648,0.851,0.68,1.12953303089416e-23,"CC","Plekhb1" 261 | "Aprt",3.99024910570115e-26,2.5024279693756,0.396,0.104,4.07005408781518e-23,"CC","Aprt" 262 | "Sox2ot",1.51533081519137e-23,2.34635943658809,0.416,0.127,1.5456374314952e-20,"CC","Sox2ot" 263 | "Bcl6",3.09363799304412e-23,0.981970164839274,0.955,0.883,3.155510752905e-20,"CC","Bcl6" 264 | "Apod",3.57881831934528e-23,1.99036442053318,0.656,0.358,3.65039468573219e-20,"CC","Apod" 265 | "Qk",4.18121469900398e-23,1.43672435176165,0.812,0.642,4.26483899298406e-20,"CC","Qk" 266 | "Car2",6.05110789178984e-22,1.92304273899421,0.494,0.184,6.17213004962564e-19,"CC","Car2" 267 | "Kif5a",6.66214851399637e-21,1.11555120088842,0.883,0.764,6.7953914842763e-18,"CC","Kif5a" 268 | "Teddm3",5.92982042705849e-20,2.29315108123936,0.403,0.136,6.04841683559966e-17,"CC","Teddm3" 269 | "Esd",2.21712870136804e-18,1.85010794202163,0.494,0.22,2.2614712753954e-15,"CC","Esd" 270 | "Ptgds",5.63068836985463e-17,0.696032858370176,0.649,0.361,5.74330213725173e-14,"CC","Ptgds" 271 | "Gfap",2.71797939525523e-16,1.8973579384897,0.487,0.226,2.77233898316033e-13,"CC","Gfap" 272 | "Gstm6",1.46325530049324e-15,1.86176048592186,0.403,0.162,1.49252040650311e-12,"CC","Gstm6" 273 | "Lcat",1.60273465915533e-14,2.07230657848721,0.39,0.166,1.63478935233843e-11,"CC","Lcat" 274 | "Hlf1",5.19482007736139e-13,0.577063521366935,0.935,0.9,5.29871647890862e-10,"CC","Hlf" 275 | "Cd9",5.42446411708351e-12,1.16292462105661,0.623,0.408,5.53295339942519e-09,"CC","Cd9" 276 | "Gad2",4.33226867213496e-11,1.59674606374523,0.409,0.211,4.41891404557766e-08,"CC","Gad2" 277 | "Cend1",5.94350077437529e-11,0.867931667867409,0.799,0.648,6.06237078986279e-08,"CC","Cend1" 278 | "Rnf13",5.94428580633791e-11,1.34176100910094,0.448,0.243,6.06317152246467e-08,"CC","Rnf13" 279 | "Cryab",4.25380047831565e-10,1.55028408329782,0.461,0.274,4.33887648788196e-07,"CC","Cryab" 280 | "Spon1",1.6209506475699e-09,1.20750853401943,0.526,0.341,1.6533696605213e-06,"CC","Spon1" 281 | "Gsn",2.92329184278261e-09,1.64000653966246,0.37,0.195,2.98175767963827e-06,"CC","Gsn" 282 | "Pllp",4.72536305533494e-09,1.70709127302396,0.273,0.116,4.81987031644164e-06,"CC","Pllp" 283 | "Fam19a1",5.08393804040054e-09,1.46598934426218,0.409,0.242,5.18561680120855e-06,"CC","Fam19a1" 284 | "Igsf3",5.31896997309911e-08,1.10473319829479,0.461,0.292,5.42534937256109e-05,"CC","Igsf3" 285 | "Fosb1",7.13689996850097e-08,0.912610154316035,0.63,0.504,7.27963796787099e-05,"CC","Fosb" 286 | "Hsd3b7",1.19055119940377e-07,1.1456800589579,0.357,0.191,0.000121436222339185,"CC","Hsd3b7" 287 | "Slc32a1",1.5366281436928e-07,1.08200766510419,0.416,0.257,0.000156736070656666,"CC","Slc32a1" 288 | "Ddit3",2.7985335807829e-07,0.996717990885939,0.532,0.385,0.000285450425239856,"CC","Ddit3" 289 | "Adarb21",4.06356635202762e-07,1.14848668126005,0.279,0.136,0.000414483767906817,"CC","Adarb2" 290 | "Pcdhb8",9.25748508578578e-07,1.35459923154992,0.182,0.069,0.000944263478750149,"CC","Pcdhb8" 291 | "Tmeff2",2.17189150013305e-06,1.24056045242691,0.325,0.187,0.00221532933013572,"CC","Tmeff2" 292 | "Hs3st1",3.37745940470364e-06,1.31790064593983,0.422,0.302,0.00344500859279771,"CC","Hs3st1" 293 | "Dusp6",4.21147785526888e-06,0.711859904327854,0.708,0.631,0.00429570741237425,"CC","Dusp6" 294 | "Msmo1",5.04618254540657e-06,0.868490880068891,0.409,0.273,0.0051471061963147,"CC","Msmo1" 295 | "Cnp",9.03137705289469e-06,1.1527177143629,0.318,0.188,0.00921200459395258,"CC","Cnp" 296 | "Enpp2",1.31394477621298e-05,1.08895785264804,0.442,0.317,0.0134022367173724,"CC","Enpp2" 297 | "Mrpl22",2.09255627189844e-05,0.716278452719481,0.643,0.57,0.0213440739733641,"CC","Mrpl22" 298 | "Apoe",2.44670083499305e-05,0.935207830975052,0.617,0.613,0.0249563485169291,"CC","Apoe" 299 | "Mt2",2.65338130432553e-05,1.04020343034375,0.474,0.359,0.0270644893041204,"CC","Mt2" 300 | "Rbm18",3.16857731652534e-05,0.939633242784327,0.442,0.333,0.0323194886285585,"CC","Rbm18" 301 | "Vstm2a",4.26043787645261e-05,1.00329922189629,0.409,0.302,0.0434564663398166,"CC","Vstm2a" 302 | "Pon2",9.27167960658039e-05,0.718751782317697,0.474,0.365,0.09457113198712,"CC","Pon2" 303 | "Sepp11",9.75103050431475e-05,0.774639482974576,0.481,0.37,0.0994605111440105,"CC","Sepp1" 304 | "Ucma",0.000131100056515779,1.1870134062557,0.195,0.1,0.133722057646094,"CC","Ucma" 305 | "Tcerg1l",0.000180391428916735,1.16959131127731,0.351,0.253,0.18399925749507,"CC","Tcerg1l" 306 | "Cmtm5",0.000210017325491012,1.13885656502881,0.299,0.197,0.214217672000833,"CC","Cmtm5" 307 | "Nrsn2",0.000220286765012983,1.02886237090502,0.338,0.236,0.224692500313243,"CC","Nrsn2" 308 | "Psat1",0.000567891155603228,0.602869815830916,0.571,0.482,0.579248978715293,"CC","Psat1" 309 | "Fstl5",0.000851140701058514,1.00656117306921,0.188,0.104,0.868163515079684,"CC","Fstl5" 310 | "Htr5b",0.00106802986152974,1.03286863686677,0.279,0.189,1,"CC","Htr5b" 311 | "Pcdhga3",0.00116796219909119,0.520118761226462,0.649,0.655,1,"CC","Pcdhga3" 312 | "Trap1",0.0011714414124892,1.28812092293134,0.214,0.131,1,"CC","Trap1" 313 | "Dtwd1",0.0011971440362607,0.965129692013645,0.208,0.122,1,"CC","Dtwd1" 314 | "Pdlim11",0.00190455176268907,0.843455236803178,0.162,0.087,1,"CC","Pdlim1" 315 | "Pfkl",0.00202865786452909,0.869858196212576,0.357,0.281,1,"CC","Pfkl" 316 | "Spp1",0.00373085905510645,0.898780831430939,0.143,0.077,1,"CC","Spp1" 317 | "Resp18",0.00545987738733048,1.07862275499959,0.13,0.07,1,"CC","Resp18" 318 | "Coch",0.00591107273465872,0.671481870005505,0.331,0.254,1,"CC","Coch" 319 | "Lhx1",0.00613723026585372,0.626222594670639,0.37,0.3,1,"CC","Lhx1" 320 | "Lman1l",0.00630726126982367,0.598606440671149,0.591,0.568,1,"CC","Lman1l" 321 | "Sst",4.64496101658131e-08,2.76812340579502,0.304,0.1,4.73786023691294e-05,"HPC","Sst" 322 | "Gfap1",3.23877661251999e-06,1.0921160331023,0.478,0.246,0.00330355214477039,"HPC","Gfap" 323 | "Qpct",1.90042130234367e-05,1.29289796394232,0.217,0.073,0.0193842972839055,"HPC","Qpct" 324 | "Gemin7",2.07376939176232e-05,0.97043986953196,0.638,0.428,0.0211524477959756,"HPC","Gemin7" 325 | "Ptprz1",9.36479203190204e-05,1.13820577009249,0.565,0.399,0.0955208787254008,"HPC","Ptprz1" 326 | "Apoe1",0.000252258008727081,0.955618037483084,0.754,0.605,0.257303168901622,"HPC","Apoe" 327 | "Plpp3",0.000329703514279667,0.966425115060226,0.536,0.341,0.33629758456526,"HPC","Plpp3" 328 | "Mt21",0.000355371545493905,1.31131031785294,0.507,0.366,0.362478976403783,"HPC","Mt2" 329 | "Dbi",0.000430150658032958,1.03855439407146,0.551,0.373,0.438753671193617,"HPC","Dbi" 330 | "Ascl1",0.000460300076256422,1.1883199929704,0.232,0.102,0.469506077781551,"HPC","Ascl1" 331 | "Mt1",0.000511081399047552,0.903158545245094,0.696,0.616,0.521303027028503,"HPC","Mt1" 332 | "Tmem179b",0.00213054642633814,0.961644225089181,0.275,0.142,1,"HPC","Tmem179b" 333 | "Twistnb",0.00229167862409836,0.908109509860824,0.304,0.167,1,"HPC","Twistnb" 334 | "Htra1",0.00231142234085296,0.827423780616928,0.522,0.379,1,"HPC","Htra1" 335 | "Snrpb2",0.00256880042543693,1.02108108372555,0.159,0.065,1,"HPC","Snrpb2" 336 | "Slc1a2",0.00265237155825602,0.674589490655206,0.768,0.641,1,"HPC","Slc1a2" 337 | "Tnfrsf12a",0.00367599318866908,1.00216141381185,0.246,0.133,1,"HPC","Tnfrsf12a" 338 | "Dusp61",0.00525356548898912,0.510192840609576,0.739,0.634,1,"HPC","Dusp6" 339 | "Gng7",0.00606502978971731,0.613161011776317,0.29,0.163,1,"HPC","Gng7" 340 | "Mbp1",0.00616502895875102,0.777665668253011,0.565,0.445,1,"HPC","Mbp" 341 | "Gpr37l1",0.00716947296324967,0.634747899302053,0.464,0.325,1,"HPC","Gpr37l1" 342 | "St6galnac5",0.00720363878942158,1.3690414371527,0.391,0.283,1,"HPC","St6galnac5" 343 | "Ythdc1",0.00905594468705341,0.734015464459866,0.493,0.397,1,"HPC","Ythdc1" 344 | "Cplx1",2.89184576174634e-19,1.01040999714847,0.821,0.577,2.94968267698126e-16,"L5","Cplx1" 345 | "Rab3c",7.88616174854388e-19,1.70964840047491,0.5,0.208,8.04388498351476e-16,"L5","Rab3c" 346 | "Pcp41",5.58475931667256e-10,1.06507256587353,0.436,0.224,5.69645450300601e-07,"L5","Pcp4" 347 | "Nefl",2.23439682089166e-08,1.12010175998537,0.372,0.183,2.2790847573095e-05,"L5","Nefl" 348 | "Etv1",1.36619398687931e-07,0.981337318456533,0.321,0.151,0.00013935178666169,"L5","Etv1" 349 | "Fezf2",3.3904657315311e-06,0.980332055767206,0.378,0.216,0.00345827504616172,"L5","Fezf2" 350 | "Anapc131",3.49312885185784e-06,0.566151704288694,0.436,0.247,0.003562991428895,"L5","Anapc13" 351 | "Sulf2",3.68460915871754e-06,0.8274972940158,0.359,0.195,0.00375830134189189,"L5","Sulf2" 352 | "Tox",2.17930152947759e-05,0.678338214235714,0.365,0.202,0.0222288756006714,"L5","Tox" 353 | "Efr3a1",5.97591545550578e-05,0.680553230970455,0.487,0.339,0.060954337646159,"L5","Efr3a" 354 | "Tmsb10",6.61941667368351e-05,0.885410587943005,0.404,0.266,0.0675180500715718,"L5","Tmsb10" 355 | "Idi11",0.000114066445762561,0.521633027467969,0.301,0.167,0.116347774677813,"L5","Idi1" 356 | "Slc20a1",0.000125825064446289,0.614342391972575,0.571,0.445,0.128341565735214,"L5","Slc20a1" 357 | "Laptm4b",0.000175523696477438,0.563410610885911,0.378,0.231,0.179034170406987,"L5","Laptm4b" 358 | "Arhgap24",0.000189285439397162,0.718105721633704,0.308,0.181,0.193071148185106,"L5","Arhgap24" 359 | "Slc50a1",0.000270235187178041,0.663707875813582,0.353,0.211,0.275639890921602,"L5","Slc50a1" 360 | "Olfm3",0.000347181192399136,0.709102595125416,0.276,0.156,0.354124816247119,"L5","Olfm3" 361 | "Mal2",0.000502614732431163,0.570475303454775,0.526,0.395,0.512667027079787,"L5","Mal2" 362 | "Rit21",0.000645006013593175,0.612617572784265,0.41,0.283,0.657906133865039,"L5","Rit2" 363 | "Gprasp2",0.000681653207866171,0.65715363294497,0.404,0.276,0.695286272023494,"L5","Gprasp2" 364 | "Crhbp",0.000738715868197462,0.528558555166883,0.301,0.181,0.753490185561412,"L5","Crhbp" 365 | "Sgpp2",0.000969523887882986,0.63751746543519,0.244,0.141,0.988914365640645,"L5","Sgpp2" 366 | "Acot13",0.00116913906352585,0.51021454615469,0.436,0.311,1,"L5","Acot13" 367 | "Dnajc15",0.00119486002705249,0.565368628002348,0.551,0.42,1,"L5","Dnajc15" 368 | "Adgra1",0.00124569192967915,0.592656784359516,0.205,0.11,1,"L5","Adgra1" 369 | "Rab3b",0.00221183342026901,0.57936010409987,0.34,0.225,1,"L5","Rab3b" 370 | "Anxa5",0.0026573174079258,0.518306221201035,0.282,0.181,1,"L5","Anxa5" 371 | "Slc25a11",0.00266292891045283,0.598886733354276,0.359,0.247,1,"L5","Slc25a11" 372 | "Amph",0.0042849472289602,0.515273750924067,0.429,0.324,1,"L5","Amph" 373 | "Rab27b",0.00444507696220729,0.575662238664093,0.218,0.13,1,"L5","Rab27b" 374 | "Elavl2",0.00469807903023228,0.540392318558157,0.224,0.136,1,"L5","Elavl2" 375 | "Nr1d1",0.00494925643051289,0.655533203608875,0.16,0.088,1,"L5","Nr1d1" 376 | "Gad1",0.00543169346243443,0.721267485375603,0.423,0.306,1,"L5","Gad1" 377 | "Cd200",0.00588876263514452,0.548156648370005,0.256,0.166,1,"L5","Cd200" 378 | "Twistnb1",0.00592122977380668,0.599716893733918,0.256,0.163,1,"L5","Twistnb" 379 | "Pdgfra",0.00617371448792396,0.881090991840061,0.192,0.114,1,"L5","Pdgfra" 380 | "Fam3c",0.00656137317615804,0.61803666253139,0.301,0.208,1,"L5","Fam3c" 381 | "Plpp4",0.00692290544003753,0.634205777472684,0.224,0.141,1,"L5","Plpp4" 382 | "St6galnac51",0.00696752123081033,0.546678751519693,0.372,0.277,1,"L5","St6galnac5" 383 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151507_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.197329648331798,0.138248614724038 3 | "2","Layer2",0.240193568861839,0.141861819292885 4 | "3","Layer3",0.338599407477968,0.137529247776075 5 | "4","Layer4",0.440474973248037,0.111503487438145 6 | "5","Layer5",0.517061341457862,0.106592625325505 7 | "6","Layer6",0.60441227477659,0.0948704974081041 8 | "7","WM",0.668523321707473,0.0731724127707 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151507_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.212517556251342,0.15375562145406 3 | "2","Layer2",0.199590703756467,0.137133253784138 4 | "3","Layer3",0.249105617452126,0.143513436977813 5 | "4","Layer4",0.384913825671047,0.129044347097029 6 | "5","Layer5",0.496253533366634,0.117886051216469 7 | "6","Layer6",0.509793886120562,0.122359318351796 8 | "7","WM",0.645103658469303,0.129656513663322 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151508_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.198943870183798,0.140772876132374 3 | "2","Layer2",0.231014458895045,0.136595947249676 4 | "3","Layer3",0.335117027843194,0.138686300620042 5 | "4","Layer4",0.442452890131467,0.113800465674267 6 | "5","Layer5",0.526034673260964,0.113031374110587 7 | "6","Layer6",0.606788732365734,0.0865901558734091 8 | "7","WM",0.679455298601748,0.064470683959494 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151508_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.202865409148947,0.150255053656419 3 | "2","Layer2",0.196402708483338,0.142325436811784 4 | "3","Layer3",0.237407894907841,0.13896717744907 5 | "4","Layer4",0.377195042531555,0.125455029364853 6 | "5","Layer5",0.465464400260658,0.107794015139785 7 | "6","Layer6",0.475671031431022,0.126703329387119 8 | "7","WM",0.643373208698139,0.099459272644238 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151509_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.252530403204514,0.184798896186719 3 | "2","Layer2",0.263730088092511,0.166796003477036 4 | "3","Layer3",0.341144381242619,0.161180367970948 5 | "4","Layer4",0.414824202727001,0.120246299770432 6 | "5","Layer5",0.468893829390011,0.0975912354236254 7 | "6","Layer6",0.527435860991588,0.0773841371352227 8 | "7","WM",0.586847701219648,0.0662481899656655 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151509_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.225655560210892,0.159129720879418 3 | "2","Layer2",0.211424789985437,0.139624630253975 4 | "3","Layer3",0.33716323824874,0.152204558091647 5 | "4","Layer4",0.48293479743954,0.124066049233649 6 | "5","Layer5",0.565867716737722,0.113451241713318 7 | "6","Layer6",0.602508116180567,0.137504702339824 8 | "7","WM",0.750928506255946,0.0847669530980976 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151510_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.2470702882514,0.181520935269487 3 | "2","Layer2",0.262781383790348,0.164536341303683 4 | "3","Layer3",0.340610688561663,0.157089613956383 5 | "4","Layer4",0.406174683937556,0.117651037790995 6 | "5","Layer5",0.452262168904713,0.0993829574730475 7 | "6","Layer6",0.50233497936029,0.0805657395578744 8 | "7","WM",0.556258025801653,0.0753562265453451 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151510_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.222579644799859,0.145835589044463 3 | "2","Layer2",0.207459363595504,0.131429643171032 4 | "3","Layer3",0.306465000916702,0.145129086110078 5 | "4","Layer4",0.451865227685913,0.123848396513803 6 | "5","Layer5",0.516930692864692,0.112067547008295 7 | "6","Layer6",0.539881538336815,0.118542292450424 8 | "7","WM",0.691399433988576,0.11256861171043 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151669_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer3",0.30779397572519,0.172537942077569 3 | "2","Layer4",0.385190677341988,0.16749968907067 4 | "3","Layer5",0.451664873509091,0.160890189857129 5 | "4","Layer6",0.508141816371664,0.144347426435665 6 | "5","WM",0.5488848738229,0.122789497936516 7 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151669_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer3",0.245625923808809,0.152339643405181 3 | "2","Layer4",0.282990394396808,0.140249684897574 4 | "3","Layer5",0.384837298148449,0.126807106175433 5 | "4","Layer6",0.441589308665264,0.128721987656123 6 | "5","WM",0.483699066932084,0.128451184379793 7 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151670_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer3",0.322760272745806,0.181965977371495 3 | "2","Layer4",0.388221813038658,0.176040807366736 4 | "3","Layer5",0.444098793582816,0.165404655566769 5 | "4","Layer6",0.512184732436032,0.149717334978403 6 | "5","WM",0.53967518532328,0.126010261367522 7 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151670_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer3",0.238625487749596,0.139363157368343 3 | "2","Layer4",0.268367186389236,0.130141490719731 4 | "3","Layer5",0.379702513117907,0.129420187004209 5 | "4","Layer6",0.456349027301054,0.128506358617817 6 | "5","WM",0.518870373292317,0.130867526662178 7 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151671_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer3",0.276555298295095,0.167438211850936 3 | "2","Layer4",0.33390703086893,0.160356384532328 4 | "3","Layer5",0.389158060584608,0.155820607433449 5 | "4","Layer6",0.484958161328985,0.14571028717906 6 | "5","WM",0.542676479853011,0.11110714837842 7 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151671_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer3",0.227206257962406,0.136836901919176 3 | "2","Layer4",0.276954258650024,0.127134755649102 4 | "3","Layer5",0.351045497768639,0.124872810396624 5 | "4","Layer6",0.410705326063522,0.127413776612128 6 | "5","WM",0.440894459083027,0.151120784456534 7 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151672_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer3",0.253255192641948,0.152837074780972 3 | "2","Layer4",0.330805681821903,0.158162126860343 4 | "3","Layer5",0.386610503751046,0.150023949233117 5 | "4","Layer6",0.497851593912446,0.14214684331381 6 | "5","WM",0.552384182232836,0.108275078234417 7 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151672_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer3",0.191315896370629,0.118493493245797 3 | "2","Layer4",0.232051098863993,0.121775076038264 4 | "3","Layer5",0.30071982703756,0.118377193356874 5 | "4","Layer6",0.385275023816039,0.121931622021851 6 | "5","WM",0.439002679184076,0.148134754736176 7 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151673_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.154019448357396,0.17864538225862 3 | "2","Layer2",0.475068530427967,0.252204585853915 4 | "3","Layer3",0.424880605251649,0.218897679786899 5 | "4","Layer4",0.40806656671864,0.185124988772152 6 | "5","Layer5",0.421719908227849,0.156051334398587 7 | "6","Layer6",0.493921795961639,0.124685343780026 8 | "7","WM",0.626736688293506,0.111290469220495 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151673_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.208281053268522,0.139732872918143 3 | "2","Layer2",0.351957713674652,0.18622600289134 4 | "3","Layer3",0.363037044631935,0.186154628760291 5 | "4","Layer4",0.355365480062785,0.172475933030016 6 | "5","Layer5",0.384256607145443,0.14975876498441 7 | "6","Layer6",0.44325366585986,0.141320344200917 8 | "7","WM",0.626016853441947,0.118685455958056 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151674_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.182850006551085,0.156905104836389 3 | "2","Layer2",0.414142048912799,0.238987141184158 4 | "3","Layer3",0.404529800380053,0.212066928247357 5 | "4","Layer4",0.433713562003921,0.18155456009671 6 | "5","Layer5",0.422592168346491,0.155551355092788 7 | "6","Layer6",0.481337334019138,0.126933536748408 8 | "7","WM",0.623186508121396,0.11633167382103 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151674_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.19694634368247,0.161164597093986 3 | "2","Layer2",0.410318802748727,0.20864816467765 4 | "3","Layer3",0.375441140498556,0.201693492148243 5 | "4","Layer4",0.385932200675891,0.188369057989506 6 | "5","Layer5",0.366453398842157,0.172921072569737 7 | "6","Layer6",0.388615504088507,0.146628396986829 8 | "7","WM",0.53189854844803,0.106670532953122 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151675_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.185490805260873,0.170945852518 3 | "2","Layer2",0.501822127345392,0.237701798444282 4 | "3","Layer3",0.491261920947984,0.227663887879952 5 | "4","Layer4",0.469046838411899,0.197539680598819 6 | "5","Layer5",0.440762501866766,0.163991782139819 7 | "6","Layer6",0.462455401219036,0.122063406985138 8 | "7","WM",0.563868481550939,0.116735318013122 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151675_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.240255483126917,0.152601697488472 3 | "2","Layer2",0.353867531118287,0.183631984507315 4 | "3","Layer3",0.313657354383713,0.175096703514685 5 | "4","Layer4",0.316142939683562,0.165512787275421 6 | "5","Layer5",0.329445092871112,0.158000302950507 7 | "6","Layer6",0.370241108939219,0.155729000111993 8 | "7","WM",0.561472005763911,0.149685887044217 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151676_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.187514111252809,0.167648365392419 3 | "2","Layer2",0.40666475047655,0.246452953662222 4 | "3","Layer3",0.408384658107067,0.219309420733451 5 | "4","Layer4",0.45675376503599,0.188278691572407 6 | "5","Layer5",0.440555390729101,0.15894958820468 7 | "6","Layer6",0.488706349981301,0.122356649431308 8 | "7","WM",0.631659202672739,0.113713453525755 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_151676_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","Layer1",0.189178260633007,0.147671923495415 3 | "2","Layer2",0.306682267733961,0.170925778943968 4 | "3","Layer3",0.283823556147635,0.177371625129722 5 | "4","Layer4",0.310880781437735,0.16033475607749 6 | "5","Layer5",0.325589566076085,0.150248652008729 7 | "6","Layer6",0.37731238824046,0.134700679520405 8 | "7","WM",0.552764364605649,0.104304660092355 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_starmap_original.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","CC",0.74486579390643,0.0584519542032213 3 | "2","HPC",0.836426778051229,0.0472023701188707 4 | "3","L1",0.134292277045647,0.103583090594067 5 | "4","L2/3",0.215006428252274,0.0919557608314547 6 | "5","L4",0.337776728382412,0.0703287296483846 7 | "6","L5",0.471092163067811,0.0625243511350518 8 | "7","L6",0.614691196110052,0.0620040209675152 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/distance_to_l1_starmap_pseudo.csv: -------------------------------------------------------------------------------- 1 | "","group","median","sd" 2 | "1","CC",0.472490061538829,0.177424199444044 3 | "2","HPC",0.429075637809867,0.198787384844337 4 | "3","L1",0.170162009519315,0.137634938962064 5 | "4","L2/3",0.164081585991465,0.126112726257255 6 | "5","L4",0.191227613302833,0.12540786838298 7 | "6","L5",0.299002535909068,0.161034097302899 8 | "7","L6",0.370036477641814,0.166887067380849 9 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/pairwise_distance_cor_DLPFC.csv: -------------------------------------------------------------------------------- 1 | "","Slice","Donor","PCC" 2 | "1","151507","Donor 1",0.539 3 | "2","151508","Donor 1",0.547 4 | "3","151509","Donor 1",0.48 5 | "4","151510","Donor 1",0.448 6 | "5","151669","Donor 2",0.567 7 | "6","151670","Donor 2",0.493 8 | "7","151671","Donor 2",0.53 9 | "8","151672","Donor 2",0.527 10 | "9","151673","Donor 3",0.657 11 | "10","151674","Donor 3",0.696 12 | "11","151675","Donor 3",0.623 13 | "12","151676","Donor 3",0.664 14 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure2/pairwise_distance_cor_STARmap.csv: -------------------------------------------------------------------------------- 1 | "","Data","PCC" 2 | "1","STARmap",0.53 3 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure3/ARI_for_different_cluster_numbers.csv: -------------------------------------------------------------------------------- 1 | "","value","method","index" 2 | "1",0.907676034237221,"scSpace","ARI" 3 | "2",0.158238163332117,"Seurat","ARI" 4 | "3",0.846454495931088,"scSpace","NMI" 5 | "4",0.179361123288796,"Seurat","NMI" 6 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure3/Clustering_result_for_cardiomyocytes.csv: -------------------------------------------------------------------------------- 1 | "","value","method","index" 2 | "1",0.907676034237221,"scSpace","ARI" 3 | "2",0.158238163332117,"Seurat","ARI" 4 | "3",0.846454495931088,"scSpace","NMI" 5 | "4",0.179361123288796,"Seurat","NMI" 6 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure4/ARI_all.csv: -------------------------------------------------------------------------------- 1 | "","type","scSpace","Seurat" 2 | "1","RORB",0.813,0.681 3 | "2","FEZF2",0.919,0.714 4 | "3","THEMIS",0.414,0.251 5 | "4","L2–L3",0.362,0.175 6 | "5","LAMP5/PAX6",0.895,0.789 7 | "6","VIP",0.759,0.655 8 | "7","SST",0.708,0.614 9 | "8","PVALB",0.551,0.55 10 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure5/GSEA_result.csv: -------------------------------------------------------------------------------- 1 | "","pathway","pval","padj","ES","NES","nMoreExtreme","size" 2 | "1","HALLMARK_ADIPOGENESIS",0.000145985401459854,0.000815128790348875,0.473033230532222,1.7877373985269,0,188 3 | "2","HALLMARK_ALLOGRAFT_REJECTION",0.693736229146994,0.941716964694232,-0.230321433775538,-0.929794261472289,2203,184 4 | "3","HALLMARK_ANDROGEN_RESPONSE",0.838983050847458,1,0.240384308234869,0.832740962089934,5345,94 5 | "4","HALLMARK_ANGIOGENESIS",0.921779516010755,1,-0.242659442044373,-0.729923810500451,3770,31 6 | "5","HALLMARK_APICAL_JUNCTION",0.722256664600124,0.941716964694232,-0.230648766038081,-0.920341565910592,2329,167 7 | "6","HALLMARK_APICAL_SURFACE",0.946913580246914,1,-0.230754829346362,-0.705532645269124,3834,33 8 | "7","HALLMARK_APOPTOSIS",0.607763788968825,0.868233984241179,0.255452495633045,0.94298298879326,4054,153 9 | "8","HALLMARK_BILE_ACID_METABOLISM",0.548310704136407,0.820188777359323,0.278428717907793,0.959122346033931,3472,90 10 | "9","HALLMARK_CHOLESTEROL_HOMEOSTASIS",0.101239336874296,0.180784530132671,0.375665377942124,1.24754259758152,628,72 11 | "10","HALLMARK_COAGULATION",0.996125232486051,1,0.194838047983654,0.68480693756566,6426,103 12 | "11","HALLMARK_COMPLEMENT",0.970446232626189,1,0.208541812907261,0.784003177907402,6632,178 13 | "12","HALLMARK_DNA_REPAIR",0.000150875075437538,0.000815128790348875,0.571238664754423,2.09176854379379,0,144 14 | "13","HALLMARK_E2F_TARGETS",0.000145053669857847,0.000815128790348875,0.746754489313043,2.83311950662441,0,196 15 | "14","HALLMARK_EPITHELIAL_MESENCHYMAL_TRANSITION",0.999854545454545,1,0.182551716445376,0.691021205997203,6873,191 16 | "15","HALLMARK_ESTROGEN_RESPONSE_EARLY",0.716127004086765,0.941716964694232,-0.229982003189737,-0.922818536477217,2277,175 17 | "16","HALLMARK_ESTROGEN_RESPONSE_LATE",0.00691583284284873,0.0172895821071218,0.376487107815253,1.40554944849286,46,166 18 | "17","HALLMARK_FATTY_ACID_METABOLISM",0.000151285930408472,0.000815128790348875,0.550061058993861,2.00190689975318,0,136 19 | "18","HALLMARK_G2M_CHECKPOINT",0.000145666423889294,0.000815128790348875,0.685630341592884,2.59661796889665,0,193 20 | "19","HALLMARK_GLYCOLYSIS",0.00102519039250146,0.00341730130833822,0.404125303419109,1.51968744711401,6,179 21 | "20","HALLMARK_HEDGEHOG_SIGNALING",0.734539232461501,0.941716964694232,-0.280876433799936,-0.844881184559624,3004,31 22 | "21","HALLMARK_HEME_METABOLISM",0.856469201296787,1,0.227830996402504,0.852206677128784,5811,170 23 | "22","HALLMARK_HYPOXIA",0.521629302178718,0.819857570034624,-0.243257859386618,-0.976429677295414,1651,178 24 | "23","HALLMARK_IL2_STAT5_SIGNALING",0.954730713245997,1,0.213205460946534,0.806531043399431,6558,189 25 | "24","HALLMARK_IL6_JAK_STAT3_SIGNALING",0.55772836860434,0.820188777359323,-0.266723405557102,-0.954961834561975,2081,77 26 | "25","HALLMARK_INFLAMMATORY_RESPONSE",0.000310945273631841,0.00132992871582083,-0.396120014309669,-1.58495370495422,0,170 27 | "26","HALLMARK_INTERFERON_ALPHA_RESPONSE",0.0162856248042593,0.0354035321831724,0.406635151812164,1.41220514629079,103,96 28 | "27","HALLMARK_INTERFERON_GAMMA_RESPONSE",0.00480699198834669,0.0133527555231852,0.370842058249854,1.40445236107413,32,193 29 | "28","HALLMARK_KRAS_SIGNALING_DN",0.0369136830419095,0.0769035063373115,-0.348237028159594,-1.29460333704202,132,98 30 | "29","HALLMARK_KRAS_SIGNALING_UP",0.0772841051314143,0.143118713206323,-0.29747800429618,-1.19035713453346,246,171 31 | "30","HALLMARK_MITOTIC_SPINDLE",0.00058021467943139,0.00207219528368353,0.401881698958156,1.52470309448172,3,196 32 | "31","HALLMARK_MTORC1_SIGNALING",0.000144885540423066,0.000815128790348875,0.565078439556365,2.14591739905645,0,198 33 | "32","HALLMARK_MYC_TARGETS_V1",0.000145369966564908,0.000815128790348875,0.685685823478655,2.59956355879781,0,195 34 | "33","HALLMARK_MYC_TARGETS_V2",0.000163025758069775,0.000815128790348875,0.608147495501743,1.94663600162175,0,57 35 | "34","HALLMARK_MYOGENESIS",1,1,0.172768849882386,0.64151591566247,6717,160 36 | "35","HALLMARK_NOTCH_SIGNALING",0.356637466307278,0.61489218328841,0.368175611511476,1.05980956474155,2116,32 37 | "36","HALLMARK_OXIDATIVE_PHOSPHORYLATION",0.000144885540423066,0.000815128790348875,0.702532528567875,2.66790709204992,0,198 38 | "37","HALLMARK_P53_PATHWAY",0.524708844822159,0.819857570034624,-0.242205937172768,-0.977771311971033,1666,184 39 | "38","HALLMARK_PANCREAS_BETA_CELLS",0.410980256321441,0.684967093869068,0.408039673535848,1.03134693061056,2372,18 40 | "39","HALLMARK_PEROXISOME",0.00408035153797866,0.0120010339352313,0.442020584609729,1.53125072761329,25,94 41 | "40","HALLMARK_PI3K_AKT_MTOR_SIGNALING",0.0531333020784498,0.1062666041569,0.371710120212382,1.29521461323893,339,98 42 | "41","HALLMARK_PROTEIN_SECRETION",0.0108354271356784,0.0246259707629054,0.419783342356244,1.45546247633106,68,95 43 | "42","HALLMARK_REACTIVE_OXYGEN_SPECIES_PATHWAY",0.00858369098712446,0.0204373594931535,0.512171576348852,1.58614604691741,51,47 44 | "43","HALLMARK_SPERMATOGENESIS",0.00650587115201523,0.0171207135579348,0.444545915447562,1.50887888745246,40,82 45 | "44","HALLMARK_TGF_BETA_SIGNALING",0.968895800933126,1,-0.215820826890473,-0.722223553421729,3737,53 46 | "45","HALLMARK_TNFA_SIGNALING_VIA_NFKB",0.000319182891797,0.00132992871582083,-0.417460696110903,-1.69145406958398,0,190 47 | "46","HALLMARK_UNFOLDED_PROTEIN_RESPONSE",0.000153846153846154,0.000815128790348875,0.530195959960339,1.88468837520034,0,112 48 | "47","HALLMARK_UV_RESPONSE_DN",0.0731707317073171,0.140712945590994,-0.309426481747035,-1.20838117010628,245,139 49 | "48","HALLMARK_UV_RESPONSE_UP",0.000451807228915663,0.00173772011121409,0.434129173724031,1.58427783380834,2,139 50 | "49","HALLMARK_WNT_BETA_CATENIN_SIGNALING",0.853097345132743,1,-0.252073945252107,-0.795016771738154,3373,39 51 | "50","HALLMARK_XENOBIOTIC_METABOLISM",0.00282780175621372,0.00883688048816788,0.392116960983058,1.45427652382292,18,158 52 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure6/Dist_change_ratio.csv: -------------------------------------------------------------------------------- 1 | "","celltype","control_median","covid19_median","ratio" 2 | "1","AM",0.120679693639927,0.103153042608924,-0.145232810113827 3 | "2","MDM",0.181064172561014,0.134254102366538,-0.258527512828095 4 | "3","Mon",0.24632290261257,0.214764795923339,-0.128116818836238 5 | "4","TMDM",0.263944593316936,0.147072092370401,-0.44279179761867 6 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure6/MT_gene_average_expression.csv: -------------------------------------------------------------------------------- 1 | "","C_1","C_2","C_3","C_4","C_5","C_6" 2 | "MT-ND1",0.231297049586777,0.300897144329897,0.205432766497462,1.83146648924731,0.569228556962025,1.40658024242424 3 | "MT-ND4",0.329016198347107,0.660310189690722,0.406537649746193,2.6639996827957,0.777941708860759,1.46578881818182 4 | "MT-CYB",0.238227961432507,0.299283560137457,0.134386416243655,1.75342487634409,0.542693139240506,1.34050221212121 5 | "MT-ATP8",0.192374652892562,0.241697766323024,0.100858629441624,1.23616382795699,0.221698329113924,0.433765848484849 6 | "MT-ND3",0.586918834710744,0.616542810996564,0.525844345177665,2.9028886344086,0.779377848101266,1.96618639393939 7 | "MT-ND5",0.228334804407714,0.402755467353952,0.125502664974619,1.63429724731183,0.344462506329114,1.11634378787879 8 | "MT-ND2",0.319205289256198,0.527606914089347,0.339657010152284,1.96967562365591,0.465962544303798,1.57816006060606 9 | "MT-ATP6",0.496659537190083,0.748539594501718,0.443872756345178,2.76538243548387,1.00185181012658,1.49559603030303 10 | "MT-CO3",0.582996834710744,0.773146054982818,0.342607045685279,2.7347715,0.847773329113924,1.95953409090909 11 | "MT-ND6",0.21430179338843,0.330781594501718,0.223954411167513,1.34334100537634,0.60892382278481,0.722972272727273 12 | "MT-ND4L",0.17562176584022,0.266134797938144,0.156623294416244,0.954142010752688,0.328275772151899,0.626834060606061 13 | "MT-CO2",0.680547041322314,1.3395879862543,0.755080604060914,3.23587821505376,1.51485532911392,2.43138703030303 14 | "MT-CO1",0.728609961432507,1.52699816151203,0.694794659898477,3.00887181182796,1.66646802531646,2.31428633333333 15 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure6/non_MT_gene_average_expression.csv: -------------------------------------------------------------------------------- 1 | "","C_1","C_2","C_3","C_4","C_5","C_6" 2 | "B2M",0.20569564738292,0.404019859793814,0.494277878172589,0.824000564516129,0.542335012658228,0.187391818181818 3 | "APOE",0.168406462809917,0.580906350515464,0.523299964467005,0.891078338709678,0.346512835443038,0.0575426363636364 4 | "LNCAROD",0.434527327823692,0.384753319587629,0.152099426395939,0.833247704301075,0.239524,0.0688387272727273 5 | "C1QA",0.224390812208599,0.0997298176841053,0.211197040837158,0.566447863455948,0.0179016672334687,0.309833563254096 6 | "TMSB4X",0.0746418925619835,0.153975048109966,0.0747703807106599,0.347380005376344,0.0974386582278481,0.192052212121212 7 | "NUPR1",0.0598423195592287,0.0760115195876289,0.0599113654822335,0.311116129032258,0,0.165610757575758 8 | "TMEM51",0.356061094549742,0.344315162180966,0.319403707141553,0.737180528969658,0.325279006521117,0.285374091021088 9 | "KCTD12",0.136673619834711,0.0863965223367697,0.0978311269035533,0.384580865591398,0.182562227848101,0 10 | "RNASE1",0.0577471101928375,0.037775852233677,0.0254212994923858,0.229082532258065,0.0276699620253165,0 11 | "GRN",0.223368694214876,0.363502350515464,0.284514045685279,0.685795559139785,0.246496772151899,0.510545606060606 12 | "ZBTB1",0.262206438016529,0.192283454295533,0.30706321319797,0.633786526881721,0.196939189873418,0.337721848484848 13 | "SSBP3",0.127525822262054,0.175690991592525,0.0891139607982365,0.400137798461434,0.349862630838014,0.142280301563719 14 | "HLA-DRA",0.322114308539945,0.259609388316151,0.502133482233502,0.743136532258065,0.278202202531646,0.341613909090909 15 | "CD74",0.731048922865014,0.432302195876289,0.698672228426396,1.05026136021505,0.334772759493671,0.571854939393939 16 | "FTL",0.286124027548209,1.20050494158076,0.409344649746193,1.15431317204301,0.999123443037975,0.709243212121212 17 | "CEBPD",0.159908013774105,0.122629312714777,0.133116888324873,0.389841258064516,0.0965949873417722,0 18 | "EPSTI1",0.808204157024794,0.346208316838488,0.587017563451777,1.01788706989247,0.343794088607595,0.585042454545455 19 | "NLRC5",0.230640603305785,0.161142890034364,0.25049938071066,0.531693553763441,0.148480050632911,0.130398606060606 20 | "ORMDL1",0.252074280991736,0.106465107216495,0.140014319796954,0.419950392473118,0.116680240506329,0.124259454545455 21 | "SBNO2",0.121758013774105,0.120490079037801,0.12379585786802,0.344850204301075,0.211652746835443,0.302899121212121 22 | "NUDCD3",0.140784829201102,0.263814907216495,0.100575406091371,0.434911801075269,0.21045953164557,0.196487696969697 23 | "CORO2A",0.0464734573002755,0.089172618556701,0.0443793045685279,0.236807876344086,0.0511561518987342,0.214941939393939 24 | "QSOX1",0.0512611955922865,0.0815533848797251,0.100905284263959,0.237090080645161,0.0682135949367089,0 25 | "ST8SIA4",0.714221016528926,0.327679494845361,0.518003736040609,0.931495258064516,0.198146772151899,0.0601942121212121 26 | "MAFB",0.443195184573003,0.25336335395189,0.231706659898477,0.661798661290322,0.15651046835443,0 27 | "CTSS",0.630552463804256,0.643241499986499,0.657019272932963,1.1031355205923,0.456569204564005,0.384596233424328 28 | "BTG1",0.109431674931129,0.137119402061856,0.310012888324873,0.405936543010753,0.173253075949367,0.0601942121212121 29 | "CLIC4",0.24038246230117,0.287467930917675,0.100562321169233,0.514238484153576,0.228908002274329,0.361177083184399 30 | "CD14",0.150442917355372,0.0681905120274914,0.0577950710659898,0.270045870967742,0,0.0820338484848485 31 | "CARD8",0.437407666666666,0.282765055670103,0.322919091370558,0.674616935483871,0.266315075949367,0.116622333333333 32 | "NFATC3",0.211996033057851,0.150225890034364,0.17802276142132,0.444490478494624,0.0784791392405063,0.470149272727273 33 | "RAPGEF6",0.281813247933884,0.340403811683849,0.320305781725888,0.623271672043011,0.285229088607595,0.561532424242424 34 | "INO80D",0.0904273581267218,0.188884931271478,0.0689242436548223,0.317627005376344,0.0604965316455696,0.223075333333333 35 | "ZNF292",0.482683556473829,0.528319398625429,0.52599945177665,0.891786827956989,0.464949113924051,0.405262272727273 36 | "PIK3AP1",0.431094517906336,0.369089326460481,0.333376228426396,0.744498849462366,0.15869746835443,0.217925121212121 37 | -------------------------------------------------------------------------------- /AnalysisPaper/output/figure6/ssGSEA_result.csv: -------------------------------------------------------------------------------- 1 | "","disease","variable","value" 2 | "977","COVID-19","Myeloid",0.250216330522536 3 | "978","COVID-19","Myeloid",0.257042670080023 4 | "979","COVID-19","Myeloid",0.289877759408376 5 | "980","COVID-19","Myeloid",0.268328541506847 6 | "981","COVID-19","Myeloid",0.111003251728532 7 | "982","COVID-19","Myeloid",0.267138715197911 8 | "983","COVID-19","Myeloid",0.228118707508618 9 | "984","COVID-19","Myeloid",0.324611135278463 10 | "985","COVID-19","Myeloid",0.427299959002135 11 | "986","COVID-19","Myeloid",0.518426748201658 12 | "987","COVID-19","Myeloid",0.480363677375948 13 | "988","COVID-19","Myeloid",0.535119501410866 14 | "989","COVID-19","Myeloid",0.484038462224725 15 | "990","COVID-19","Myeloid",0.439226102753258 16 | "991","COVID-19","Myeloid",0.424029452116435 17 | "992","COVID-19","Myeloid",0.490584508473879 18 | "993","COVID-19","Myeloid",0.472840616793531 19 | "994","COVID-19","Myeloid",0.524088530108296 20 | "995","COVID-19","Myeloid",0.448073197984175 21 | "996","COVID-19","Myeloid",0.522415289098544 22 | "997","COVID-19","Myeloid",0.530102043416498 23 | "998","COVID-19","Myeloid",0.356594259033859 24 | "999","COVID-19","Myeloid",0.346930998997875 25 | "1000","Control","Myeloid",0.168869046379169 26 | "1001","Control","Myeloid",0.245231258396033 27 | "1002","Control","Myeloid",0.122239114804703 28 | "1003","Control","Myeloid",0.169053706320242 29 | "1004","Control","Myeloid",0.150840724629503 30 | "1005","Control","Myeloid",0.234373686768022 31 | "1006","Control","Myeloid",0.273242381218786 32 | "1007","Control","Myeloid",0.482515855658245 33 | "1008","Control","Myeloid",0.289627484488308 34 | "1009","Control","Myeloid",0.575287916540144 35 | "1010","Control","Myeloid",0.380250909947243 36 | "1011","Control","Myeloid",0.583735717250285 37 | "1012","Control","Myeloid",0.232988094882467 38 | "1013","Control","Myeloid",0.416593397636617 39 | "1014","Control","Myeloid",0.384827117077745 40 | "1015","Control","Myeloid",0.413502263569643 41 | "1016","Control","Myeloid",0.378917415358689 42 | "1017","Control","Myeloid",0.316027470767798 43 | "1018","Control","Myeloid",0.433736675807924 44 | "1019","Control","Myeloid",0.389311387490264 45 | "1020","Control","Myeloid",0.360968004220946 46 | "1021","Control","Myeloid",0.483531867821283 47 | "1022","COVID-19","Myeloid",0.132041418281901 48 | "1023","COVID-19","Myeloid",0.124312449514217 49 | "1024","COVID-19","Myeloid",0.0352520268314382 50 | "1025","COVID-19","Myeloid",0.129323638263956 51 | "1026","COVID-19","Myeloid",0.103168123312864 52 | "1027","COVID-19","Myeloid",0.070037622502905 53 | "1028","COVID-19","Myeloid",0.0651099221550926 54 | "1029","COVID-19","Myeloid",0.0901340629002115 55 | "1030","COVID-19","Myeloid",0.154368901200124 56 | "1031","COVID-19","Myeloid",0.0718807798869372 57 | "1032","COVID-19","Myeloid",0.0796683387190691 58 | "1033","COVID-19","Myeloid",0.0761774376456127 59 | "1034","COVID-19","Myeloid",0.113791091418718 60 | "1035","COVID-19","Myeloid",0.0766786429578902 61 | "1036","COVID-19","Myeloid",0.0630770918470935 62 | "1037","COVID-19","Myeloid",0.0937435285450163 63 | "1038","COVID-19","Myeloid",0.125570831682835 64 | "1039","COVID-19","Myeloid",0.0675352828007507 65 | "1040","COVID-19","Myeloid",0.113808896909273 66 | "1041","COVID-19","Myeloid",0.162003520854102 67 | "1042","COVID-19","Myeloid",0.0417663254765865 68 | "1043","COVID-19","Myeloid",0.0840876744815573 69 | "1044","COVID-19","Myeloid",0.08614513508155 70 | "1045","Control","Myeloid",0.124703237018605 71 | "1046","Control","Myeloid",0.103897824943501 72 | "1047","Control","Myeloid",0.253801606916278 73 | "1048","Control","Myeloid",0.0283000475640489 74 | "1049","Control","Myeloid",0.183491322546951 75 | "1050","Control","Myeloid",0.106036420219941 76 | "1051","Control","Myeloid",0.255134889784557 77 | "1052","Control","Myeloid",0.338627111657275 78 | "1053","Control","Myeloid",0.323499016345883 79 | "1054","Control","Myeloid",0.220200161460239 80 | "1055","Control","Myeloid",0.277929531634428 81 | "1056","Control","Myeloid",0.101284030410977 82 | "1057","Control","Myeloid",0.117984492788774 83 | "1058","Control","Myeloid",0.195380730903008 84 | "1059","Control","Myeloid",0.197285424541955 85 | "1060","Control","Myeloid",0.196936698646052 86 | "1061","Control","Myeloid",0.28077289086498 87 | "1062","Control","Myeloid",0.284140944300338 88 | "1063","Control","Myeloid",0.246389873100444 89 | "1064","Control","Myeloid",0.190000117825656 90 | "1065","Control","Myeloid",0.269913468744485 91 | "1066","Control","Myeloid",0.176122420058492 92 | "1067","Control","Myeloid",0.114078758876183 93 | "1068","COVID-19","Myeloid",0.352903451619908 94 | "1069","COVID-19","Myeloid",0.396026379179117 95 | "1070","COVID-19","Myeloid",0.479416105354856 96 | "1071","COVID-19","Myeloid",0.511804938597068 97 | "1072","COVID-19","Myeloid",0.391958385871834 98 | "1073","COVID-19","Myeloid",0.706366859783305 99 | "1074","COVID-19","Myeloid",0.760582338775417 100 | "1075","COVID-19","Myeloid",0.717121953461032 101 | "1076","COVID-19","Myeloid",0.674461062654381 102 | "1077","COVID-19","Myeloid",0.683925967550615 103 | "1078","COVID-19","Myeloid",0.659674528423622 104 | "1079","COVID-19","Myeloid",0.677603004153992 105 | "1080","COVID-19","Myeloid",0.65808146520862 106 | "1081","COVID-19","Myeloid",0.691979184396187 107 | "1082","COVID-19","Myeloid",0.6657007089639 108 | "1083","COVID-19","Myeloid",0.676918581636171 109 | "1084","COVID-19","Myeloid",0.70804725051815 110 | "1085","COVID-19","Myeloid",0.696858991737869 111 | "1086","COVID-19","Myeloid",0.678977311083836 112 | "1087","COVID-19","Myeloid",0.643803365954467 113 | "1088","COVID-19","Myeloid",0.635153265451139 114 | "1089","COVID-19","Myeloid",0.683930129529293 115 | "1090","COVID-19","Myeloid",0.648608973017835 116 | "1091","COVID-19","Myeloid",0.322311433439173 117 | "1092","COVID-19","Myeloid",0.240134801469837 118 | "1093","COVID-19","Myeloid",0.224110704652504 119 | "1094","COVID-19","Myeloid",0.324638839095094 120 | "1095","COVID-19","Myeloid",0.297156675017905 121 | "1096","COVID-19","Myeloid",0.401810298133974 122 | "1097","COVID-19","Myeloid",0.484282306394555 123 | "1098","COVID-19","Myeloid",0.279895270016135 124 | "1099","COVID-19","Myeloid",0.438087309857773 125 | "1100","COVID-19","Myeloid",0.448344259405202 126 | "1101","COVID-19","Myeloid",0.278110364099112 127 | "1102","COVID-19","Myeloid",0.452085684766527 128 | "1103","COVID-19","Myeloid",0.39278854677679 129 | "1104","COVID-19","Myeloid",0.503080694054639 130 | "1105","COVID-19","Myeloid",0.454262860267709 131 | "1106","COVID-19","Myeloid",0.507896433774613 132 | "1107","COVID-19","Myeloid",0.484190103850124 133 | "1108","COVID-19","Myeloid",0.419607011297767 134 | "1109","COVID-19","Myeloid",0.530664651688186 135 | "1110","COVID-19","Myeloid",0.375787300436132 136 | "1111","COVID-19","Myeloid",0.499902749912325 137 | "1112","COVID-19","Myeloid",0.427780655015945 138 | "1113","COVID-19","Myeloid",0.551283994038418 139 | "1114","COVID-19","Myeloid",0.3984555299099 140 | "1115","Control","Myeloid",0.190808567482629 141 | "1116","Control","Myeloid",0.165657072499745 142 | "1117","Control","Myeloid",0.114751047500808 143 | "1118","Control","Myeloid",0.0783549809056183 144 | "1119","Control","Myeloid",0.0951337847094103 145 | "1120","Control","Myeloid",0.116676605301746 146 | "1121","Control","Myeloid",0.329515436482466 147 | "1122","Control","Myeloid",0.229738102680809 148 | "1123","Control","Myeloid",0.161208479066802 149 | "1124","Control","Myeloid",0.128943791897934 150 | "1125","Control","Myeloid",0.148445712629508 151 | "1126","Control","Myeloid",0.187928185136822 152 | "1127","Control","Myeloid",0.212418972480923 153 | "1128","Control","Myeloid",0.205373719409626 154 | "1129","Control","Myeloid",0.176217741817391 155 | "1130","Control","Myeloid",0.145189331493049 156 | "1131","Control","Myeloid",0.253654750234779 157 | "1132","Control","Myeloid",0.172609335595715 158 | "1133","Control","Myeloid",0.220393576321199 159 | "1134","COVID-19","Myeloid",0.122734874366942 160 | "1135","COVID-19","Myeloid",0.162379679211496 161 | "1136","COVID-19","Myeloid",0.267936716799857 162 | "1137","COVID-19","Myeloid",0.330161096861377 163 | "1138","COVID-19","Myeloid",0.279987872876541 164 | "1139","COVID-19","Myeloid",0.288694592938034 165 | "1140","COVID-19","Myeloid",0.322998817331481 166 | "1141","COVID-19","Myeloid",0.354699236875367 167 | "1142","COVID-19","Myeloid",0.386074833143607 168 | "1143","COVID-19","Myeloid",0.316032944576154 169 | "1144","COVID-19","Myeloid",0.234522593289191 170 | "1145","COVID-19","Myeloid",0.308164813825833 171 | "1146","COVID-19","Myeloid",0.374465705690953 172 | "1147","COVID-19","Myeloid",0.388649534830557 173 | "1148","COVID-19","Myeloid",0.360904391419023 174 | "1149","COVID-19","Myeloid",0.43646601194628 175 | "1150","COVID-19","Myeloid",0.203511623947772 176 | "1151","COVID-19","Myeloid",0.28413996315672 177 | "1152","COVID-19","Myeloid",0.306348886656628 178 | "1153","COVID-19","Myeloid",0.264310390461167 179 | "1154","COVID-19","Myeloid",0.268629419672569 180 | "1155","COVID-19","Myeloid",0.318361003330723 181 | "1156","COVID-19","Myeloid",0.241281398125304 182 | "1157","COVID-19","Myeloid",0.190786891517348 183 | "1158","COVID-19","Myeloid",0.173572259878705 184 | "1159","COVID-19","Myeloid",0.16619620085323 185 | "1160","COVID-19","Myeloid",0.364068704499595 186 | "1161","COVID-19","Myeloid",0.420142244330761 187 | "1162","COVID-19","Myeloid",0.374681518804777 188 | "1163","COVID-19","Myeloid",0.387743691022963 189 | "1164","COVID-19","Myeloid",0.359830214635198 190 | "1165","COVID-19","Myeloid",0.397283781248179 191 | "1166","COVID-19","Myeloid",0.392123893264993 192 | "1167","COVID-19","Myeloid",0.39894671954036 193 | "1168","COVID-19","Myeloid",0.383558137985802 194 | "1169","COVID-19","Myeloid",0.355434364887422 195 | "1170","COVID-19","Myeloid",0.390890635146925 196 | "1171","COVID-19","Myeloid",0.333136742229492 197 | "1172","COVID-19","Myeloid",0.298683361347644 198 | "1173","COVID-19","Myeloid",0.335924869333058 199 | "1174","COVID-19","Myeloid",0.232075954406728 200 | "1175","COVID-19","Myeloid",0.288142521838553 201 | "1176","COVID-19","Myeloid",0.249506103063558 202 | "1177","COVID-19","Myeloid",0.243095654489006 203 | "1178","COVID-19","Myeloid",0.383920561216771 204 | "1179","COVID-19","Myeloid",0.367180949964583 205 | "1180","COVID-19","Myeloid",0.402326310126341 206 | "1181","COVID-19","Myeloid",0.418445969482157 207 | "1182","COVID-19","Myeloid",0.414221621546764 208 | "1183","COVID-19","Myeloid",0.358410423919427 209 | "1184","COVID-19","Myeloid",0.37318772192127 210 | "1185","COVID-19","Myeloid",0.397001262692416 211 | "1186","COVID-19","Myeloid",0.37802841563471 212 | "1187","COVID-19","Myeloid",0.381165986855117 213 | "1188","COVID-19","Myeloid",0.408798298383484 214 | "1189","COVID-19","Myeloid",0.389822405278572 215 | "1190","COVID-19","Myeloid",0.43578554088242 216 | "1191","COVID-19","Myeloid",0.416065415028555 217 | "1192","COVID-19","Myeloid",0.405674286198038 218 | "1193","COVID-19","Myeloid",0.394415327254388 219 | "1194","COVID-19","Myeloid",0.42402382902631 220 | "1195","COVID-19","Myeloid",0.378738820098843 221 | "1196","COVID-19","Myeloid",0.396622251712177 222 | "1197","COVID-19","Myeloid",0.383483240196884 223 | "1198","COVID-19","Myeloid",0.520028078763323 224 | "1199","COVID-19","Myeloid",0.521927331095218 225 | "1200","COVID-19","Myeloid",0.477922637522214 226 | "1201","COVID-19","Myeloid",0.506603776779542 227 | "1202","COVID-19","Myeloid",0.492876607430701 228 | "1203","COVID-19","Myeloid",0.574317130843211 229 | "1204","COVID-19","Myeloid",0.479750868996619 230 | "1205","COVID-19","Myeloid",0.528335689376677 231 | "1206","COVID-19","Myeloid",0.468555056002118 232 | "1207","COVID-19","Myeloid",0.525154153978563 233 | "1208","COVID-19","Myeloid",0.490596261899952 234 | "1209","COVID-19","Myeloid",0.503006631235982 235 | "1210","COVID-19","Myeloid",0.546966502093643 236 | "1211","COVID-19","Myeloid",0.471985707962497 237 | "1212","COVID-19","Myeloid",0.496829723343684 238 | "1213","COVID-19","Myeloid",0.465130568476482 239 | "1214","COVID-19","Myeloid",0.489212794371814 240 | "1215","COVID-19","Myeloid",0.483034091131162 241 | "1216","COVID-19","Myeloid",0.496234665050535 242 | "1217","COVID-19","Myeloid",0.534900407792933 243 | "1218","COVID-19","Myeloid",0.470689461981916 244 | "1219","COVID-19","Myeloid",0.432453262991519 245 | "1220","COVID-19","Myeloid",0.48796714848279 246 | -------------------------------------------------------------------------------- /AnalysisPaper/scripts/constructSimulations.R: -------------------------------------------------------------------------------- 1 | # simulating paired scRNA-seq and ST data using splatter. 2 | library(splatter) 3 | 4 | # generate gene expression data and spatial coordinates 5 | sim_data_construct <- function(gene_num = 5000, 6 | batch_cell_num_1 = 1000, 7 | batch_cell_num_2 = 1000, 8 | group_prob, 9 | de_prob, 10 | max_range = 20, 11 | seed = 123 12 | ){ 13 | 14 | params <- newSplatParams(seed = seed) 15 | params <- setParams( 16 | params, 17 | update = list(nGenes = gene_num, 18 | batchCells = c(batch_cell_num_1, batch_cell_num_2), 19 | group.prob = group_prob, 20 | de.prob = de_prob) 21 | ) 22 | 23 | message('Simulating data...') 24 | sim <- splatSimulate(params, method = "group", verbose = FALSE) 25 | counts <- data.frame(sim@assays@data@listData[["counts"]]) 26 | meta <- data.frame(sim@colData) 27 | meta$Group <- as.character(meta$Group) 28 | 29 | sc_meta <- meta[meta$Batch == 'Batch1', ] 30 | sc_data <- counts[, rownames(sc_meta)] 31 | message('ScRNA-seq data simulation done...') 32 | 33 | st_meta <- meta[meta$Batch == 'Batch2', ] 34 | st_data <- counts[, rownames(st_meta)] 35 | st_meta$pseudo_x <- 0 36 | st_meta$pseudo_y <- 0 37 | 38 | cell_type_num <- length(group_prob) 39 | cell_type_name <- names(table(st_meta$Group)) 40 | cell_num_per_ct <- as.vector(table(st_meta$Group)) 41 | 42 | x_center <- sample(-max_range:max_range, cell_type_num) 43 | y_center <- sample(-max_range:max_range, cell_type_num) 44 | 45 | for (i in 1:cell_type_num) { 46 | st_meta[st_meta$Group == cell_type_name[i],]$pseudo_x <- rnorm(cell_num_per_ct[i], x_center[i]) 47 | st_meta[st_meta$Group == cell_type_name[i],]$pseudo_y <- rnorm(cell_num_per_ct[i], y_center[i]) 48 | } 49 | 50 | message('SrT data simulation done...') 51 | message('Simulating done.') 52 | 53 | return(list(sc_data = sc_data, 54 | sc_meta = sc_meta, 55 | st_data = st_data, 56 | st_meta = st_meta)) 57 | } 58 | 59 | # generate proportion of each celltype randomly 60 | generate_ct_prob <- function(ct_num, 61 | seed = 123){ 62 | set.seed(seed) 63 | ct_prob <- runif(ct_num, min = 0, max = 1) 64 | ct_prob <- ct_prob / sum(ct_prob) 65 | return(ct_prob) 66 | } 67 | 68 | # generate group differential expression of each celltype randomly, 0.2 for main celltypes and 0.01 for spatial-subtypes 69 | generate_de_prob <- function(ct_num, 70 | sub_ct_num){ 71 | de_prob <- c(rep(0.2, (ct_num - sub_ct_num)), rep(0.01, sub_ct_num)) 72 | return(de_prob) 73 | } -------------------------------------------------------------------------------- /AnalysisPaper/scripts/figure1/BayesSpace_DRSC_simulation.R: -------------------------------------------------------------------------------- 1 | source('../scripts/utils.R') 2 | 3 | 4 | ################## DR.SC ################## 5 | sim_id <- paste0('sim', 1:140) 6 | time_df <- data.frame(matrix(ncol = 1, nrow = 140)) 7 | rownames(time_df) <- sim_id; colnames(time_df) <- 'run_time' 8 | res_list <- list() 9 | for (i in 1:length(sim_id)) { 10 | if(i <= 50){ 11 | data <- read.csv(paste0('~/workspace/scSpace/data/[0]simulated_data/original_data/', sim_id[i], '_sc_data.csv'), row.names = 1) 12 | meta <- read.csv(paste0('~/workspace/scSpace/data/[0]simulated_data/original_data/', sim_id[i], '_sc_meta.csv'), row.names = 1) 13 | pseudo_space <- read.csv(paste0('~/workspace/scSpace/data/[0]simulated_data/pseudo_space/pseudo_coords_', sim_id[i], '.csv'), row.names = 1) 14 | } else if(i > 50){ 15 | data <- read.csv(paste0('~/workspace/scSpace/data/add_subcluster/original_data/', sim_id[i], '_sc_data.csv'), row.names = 1) 16 | meta <- read.csv(paste0('~/workspace/scSpace/data/add_subcluster/original_data/', sim_id[i], '_sc_meta.csv'), row.names = 1) 17 | pseudo_space <- read.csv(paste0('~/workspace/scSpace/data/add_subcluster/result/', sim_id[i], '_pseudo_space.csv'), row.names = 1) 18 | } 19 | 20 | meta$row <- pseudo_space[, 1] 21 | meta$col <- pseudo_space[, 2] 22 | 23 | ct_num <- length(unique(meta$Group)) 24 | start_time <- Sys.time() 25 | res <- run_DRSC(data = data, meta = meta, cluster_num = ct_num) 26 | end_time <- Sys.time() 27 | time_df$run_time[i] <- as.numeric(difftime(end_time, start_time, units = 'secs')) 28 | res_list[[sim_id[i]]] <- res 29 | } 30 | 31 | save(res_list, file = '~/workspace/scSpace/data/bayesspace/drsc_sim140.Rdata') 32 | write.csv(time_df, file = '~/workspace/scSpace/data/bayesspace/drsc_sim140_runtime.csv') 33 | 34 | 35 | ################## BayesSpace ################## 36 | sim_id <- paste0('sim', 1:140) 37 | time_df <- data.frame(matrix(ncol = 1, nrow = 140)) 38 | rownames(time_df) <- sim_id; colnames(time_df) <- 'run_time' 39 | res_list <- list() 40 | for (i in 1:length(sim_id)) { 41 | if(i <= 50){ 42 | data <- read.csv(paste0('~/workspace/scSpace/data/[0]simulated_data/original_data/', sim_id[i], '_sc_data.csv'), row.names = 1) 43 | meta <- read.csv(paste0('~/workspace/scSpace/data/[0]simulated_data/original_data/', sim_id[i], '_sc_meta.csv'), row.names = 1) 44 | pseudo_space <- read.csv(paste0('~/workspace/scSpace/data/[0]simulated_data/pseudo_space/pseudo_coords_', sim_id[i], '.csv'), row.names = 1) 45 | } else if(i > 50){ 46 | data <- read.csv(paste0('~/workspace/scSpace/data/add_subcluster/original_data/', sim_id[i], '_sc_data.csv'), row.names = 1) 47 | meta <- read.csv(paste0('~/workspace/scSpace/data/add_subcluster/original_data/', sim_id[i], '_sc_meta.csv'), row.names = 1) 48 | pseudo_space <- read.csv(paste0('~/workspace/scSpace/data/add_subcluster/result/', sim_id[i], '_pseudo_space.csv'), row.names = 1) 49 | } 50 | 51 | meta$row <- pseudo_space[, 1] 52 | meta$col <- pseudo_space[, 2] 53 | 54 | ct_num <- length(unique(meta$Group)) 55 | start_time <- Sys.time() 56 | res <- run_BayesSpace(data = data, meta = meta, cluster_num = ct_num) 57 | end_time <- Sys.time() 58 | time_df$run_time[i] <- as.numeric(difftime(end_time, start_time, units = 'secs')) 59 | res_list[[sim_id[i]]] <- res 60 | } 61 | 62 | save(res_list, file = '~/workspace/scSpace/data/bayesspace/bayesspace_sim140.Rdata') 63 | write.csv(time_df, file = '~/workspace/scSpace/data/bayesspace/bayesspace_sim140_runtime.csv') 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /AnalysisPaper/scripts/figure2/DLPFC_aggregate.R: -------------------------------------------------------------------------------- 1 | slice_id <- c(151507, 151508, 151509, 151510, 151669, 151670, 151671, 151672, 151673, 151674, 151675, 151676) 2 | data_list <- list( 3 | test_slice = slice_id, 4 | train_slice = list(c(151508, 151509, 151510), c(151507, 151509, 151510), c(151507, 151508, 151510), c(151507, 151508, 151509), 5 | c(151670, 151671, 151672), c(151669, 151671, 151672), c(151669, 151670, 151672), c(151669, 151670, 151671), 6 | c(151674, 151675, 151676), c(151673, 151675, 151676), c(151673, 151674, 151676), c(151673, 151674, 151675))) 7 | 8 | 9 | # pseudo space aggregate 10 | for (i in 1:length(slice_id)) { 11 | test_slice <- data_list$test_slice[i] 12 | original_coord <- read.csv(paste0('~/workspace/scSpace/data/DLPFC_new/data/', test_slice, '_meta.csv'), row.names = 1) 13 | 14 | train_list_tmp <- data_list$train_slice[[i]] 15 | 16 | p1 <- read.csv(paste0('~/workspace/scSpace/data/DLPFC_new/result/', 17 | test_slice, '_pseudo_space(trained_on_', train_list_tmp[1], ').csv'), row.names = 1) 18 | p2 <- read.csv(paste0('~/workspace/scSpace/data/DLPFC_new/result/', 19 | test_slice, '_pseudo_space(trained_on_', train_list_tmp[2], ').csv'), row.names = 1) 20 | p3 <- read.csv(paste0('~/workspace/scSpace/data/DLPFC_new/result/', 21 | test_slice, '_pseudo_space(trained_on_', train_list_tmp[3], ').csv'), row.names = 1) 22 | 23 | p_new <- (p1 + p2 + p3) / 3 24 | 25 | original_coord$pseudo_space1 <- p_new$X0 26 | original_coord$pseudo_space2 <- p_new$X1 27 | 28 | write.csv(original_coord, file = paste0('~/workspace/scSpace/data/DLPFC_new/result/', test_slice, '_pseudo_space_aggregate.csv')) 29 | 30 | } -------------------------------------------------------------------------------- /AnalysisPaper/scripts/figure3/human_heart.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "import scipy.io\n", 11 | "import scipy.linalg\n", 12 | "import sklearn.metrics\n", 13 | "from sklearn.neighbors import KNeighborsClassifier\n", 14 | "from sklearn.model_selection import train_test_split\n", 15 | "import pandas as pd\n", 16 | "\n", 17 | "import anndata as ad\n", 18 | "import scanpy as sc\n", 19 | "from sklearn.neighbors import KDTree\n", 20 | "import igraph as ig\n", 21 | "from scipy import sparse\n", 22 | "from sklearn.neighbors import KDTree\n", 23 | "from itertools import chain\n", 24 | "\n", 25 | "import numpy as np\n", 26 | "import pandas as pd\n", 27 | "import torch\n", 28 | "import torch.optim as optim\n", 29 | "import warnings\n", 30 | "warnings.filterwarnings('ignore')\n", 31 | "import matplotlib.pyplot as plt\n", 32 | "%matplotlib inline" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 6, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "def kernel(ker, X1, X2, gamma):\n", 42 | " K = None\n", 43 | " if not ker or ker == 'primal':\n", 44 | " K = X1\n", 45 | " elif ker == 'linear':\n", 46 | " if X2 is not None:\n", 47 | " K = sklearn.metrics.pairwise.linear_kernel(\n", 48 | " np.asarray(X1).T, np.asarray(X2).T)\n", 49 | " else:\n", 50 | " K = sklearn.metrics.pairwise.linear_kernel(np.asarray(X1).T)\n", 51 | " elif ker == 'rbf':\n", 52 | " if X2 is not None:\n", 53 | " K = sklearn.metrics.pairwise.rbf_kernel(\n", 54 | " np.asarray(X1).T, np.asarray(X2).T, gamma)\n", 55 | " else:\n", 56 | " K = sklearn.metrics.pairwise.rbf_kernel(\n", 57 | " np.asarray(X1).T, None, gamma)\n", 58 | " return K\n", 59 | "\n", 60 | "\n", 61 | "class TCA:\n", 62 | " def __init__(self, kernel_type='primal', dim=30, lamb=1, gamma=1):\n", 63 | " '''\n", 64 | " Init func\n", 65 | " :param kernel_type: kernel, values: 'primal' | 'linear' | 'rbf'\n", 66 | " :param dim: dimension after transfer\n", 67 | " :param lamb: lambda value in equation\n", 68 | " :param gamma: kernel bandwidth for rbf kernel\n", 69 | " '''\n", 70 | " self.kernel_type = kernel_type\n", 71 | " self.dim = dim\n", 72 | " self.lamb = lamb\n", 73 | " self.gamma = gamma\n", 74 | "\n", 75 | " def fit(self, Xs, Xt):\n", 76 | " '''\n", 77 | " Transform Xs and Xt\n", 78 | " :param Xs: ns * n_feature, source feature\n", 79 | " :param Xt: nt * n_feature, target feature\n", 80 | " :return: Xs_new and Xt_new after TCA\n", 81 | " '''\n", 82 | " X = np.hstack((Xs.T, Xt.T))\n", 83 | " X /= np.linalg.norm(X, axis=0)\n", 84 | " m, n = X.shape\n", 85 | " ns, nt = len(Xs), len(Xt)\n", 86 | " e = np.vstack((1 / ns * np.ones((ns, 1)), -1 / nt * np.ones((nt, 1))))\n", 87 | " M = e * e.T\n", 88 | " M = M / np.linalg.norm(M, 'fro')\n", 89 | " H = np.eye(n) - 1 / n * np.ones((n, n))\n", 90 | " K = kernel(self.kernel_type, X, None, gamma=self.gamma)\n", 91 | " n_eye = m if self.kernel_type == 'primal' else n\n", 92 | " a, b = K @ M @ K.T + self.lamb * np.eye(n_eye), K @ H @ K.T\n", 93 | " w, V = scipy.linalg.eig(a, b)\n", 94 | " ind = np.argsort(w)\n", 95 | " A = V[:, ind[:self.dim]]\n", 96 | " Z = A.T @ K\n", 97 | " Z /= np.linalg.norm(Z, axis=0)\n", 98 | "\n", 99 | " Xs_new, Xt_new = Z[:, :ns].T, Z[:, ns:].T\n", 100 | " return Xs_new, Xt_new" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 2, 106 | "metadata": {}, 107 | "outputs": [ 108 | { 109 | "name": "stdout", 110 | "output_type": "stream", 111 | "text": [ 112 | "load data...\n" 113 | ] 114 | } 115 | ], 116 | "source": [ 117 | "# human heart\n", 118 | "# load data\n", 119 | "print('load data...')\n", 120 | "sc_data_processed = pd.read_csv('~/workspace/spatial_cluster/human_heart/sc_data_processed.csv', index_col=0)\n", 121 | "sc_meta_processed = pd.read_csv('~/workspace/spatial_cluster/human_heart/sc_meta_processed.csv', index_col=0)\n", 122 | "st_data_processed = pd.read_csv('~/workspace/spatial_cluster/human_heart/st_data_processed.csv', index_col=0)\n", 123 | "st_meta_processed = pd.read_csv('~/workspace/spatial_cluster/human_heart/st_meta_processed.csv', index_col=0)" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 12, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "# tca\n", 133 | "obj = TCA(kernel_type='primal', dim=50, lamb=1, gamma=1)\n", 134 | "sc_new, st_new = obj.fit(Xs=np.array(sc_data_processed.T), Xt=np.array(st_data_processed.T))" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 16, 140 | "metadata": {}, 141 | "outputs": [], 142 | "source": [ 143 | "label = np.array(st_meta_processed[['new_x','new_y']])\n", 144 | "input_size = st_new.shape[1]\n", 145 | "hidden_size = 128\n", 146 | "output_size = 2\n", 147 | "batch_size = 16\n", 148 | "my_nn = torch.nn.Sequential(\n", 149 | " torch.nn.Linear(input_size, hidden_size),\n", 150 | " torch.nn.Sigmoid(),\n", 151 | " torch.nn.Linear(hidden_size, output_size),\n", 152 | ")\n", 153 | "cost = torch.nn.MSELoss(reduction='mean')\n", 154 | "optimizer = torch.optim.Adam(my_nn.parameters(), lr = 0.01)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": 18, 160 | "metadata": {}, 161 | "outputs": [ 162 | { 163 | "name": "stdout", 164 | "output_type": "stream", 165 | "text": [ 166 | "0 118.557144\n", 167 | "100 7.5837355\n", 168 | "200 6.610284\n", 169 | "300 5.8897853\n", 170 | "400 5.2463884\n", 171 | "500 4.610996\n", 172 | "600 3.7047625\n", 173 | "700 2.787609\n", 174 | "800 2.7714293\n", 175 | "900 1.3030756\n" 176 | ] 177 | } 178 | ], 179 | "source": [ 180 | "losses = []\n", 181 | "for i in range(1000):\n", 182 | " batch_loss = []\n", 183 | " for start in range(0, len(st_new), batch_size):\n", 184 | " end = start + batch_size if start + batch_size < len(st_new) else len(st_new)\n", 185 | " xx = torch.tensor(st_new[start:end], dtype = torch.float, requires_grad = True)\n", 186 | " yy = torch.tensor(label[start:end], dtype = torch.float, requires_grad = True)\n", 187 | " prediction = my_nn(xx)\n", 188 | " loss = cost(prediction, yy)\n", 189 | " optimizer.zero_grad()\n", 190 | " loss.backward(retain_graph=True)\n", 191 | " optimizer.step()\n", 192 | " batch_loss.append(loss.data.numpy())\n", 193 | " \n", 194 | " if i % 100==0:\n", 195 | " losses.append(np.mean(batch_loss))\n", 196 | " print(i, np.mean(batch_loss))" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 19, 202 | "metadata": {}, 203 | "outputs": [], 204 | "source": [ 205 | "predict = my_nn(torch.tensor(np.array(sc_new), dtype = torch.float, requires_grad = True)).data.numpy()" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 22, 211 | "metadata": {}, 212 | "outputs": [], 213 | "source": [ 214 | "pd.DataFrame(predict).to_csv('~/workspace/spatial_cluster/human_heart/pseudo_coords.csv')" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": null, 220 | "metadata": {}, 221 | "outputs": [], 222 | "source": [] 223 | } 224 | ], 225 | "metadata": { 226 | "kernelspec": { 227 | "display_name": "scspace", 228 | "language": "python", 229 | "name": "scspace" 230 | }, 231 | "language_info": { 232 | "codemirror_mode": { 233 | "name": "ipython", 234 | "version": 3 235 | }, 236 | "file_extension": ".py", 237 | "mimetype": "text/x-python", 238 | "name": "python", 239 | "nbconvert_exporter": "python", 240 | "pygments_lexer": "ipython3", 241 | "version": "3.9.12" 242 | } 243 | }, 244 | "nbformat": 4, 245 | "nbformat_minor": 4 246 | } 247 | -------------------------------------------------------------------------------- /AnalysisPaper/scripts/figure3/human_heart_spatial_informed_clustering.R: -------------------------------------------------------------------------------- 1 | # this R script is for scSpace spatial-informed clustering step 2 | 3 | source('../scripts/utils.R') 4 | # parameters 5 | sc_data_file <- '~/workspace/spatial_cluster/human_heart/sc_data.csv' 6 | sc_meta_file <- '~/workspace/spatial_cluster/human_heart/sc_meta.csv' 7 | pseudo_coords_file <- '~/workspace/spatial_cluster/human_heart/pseudo_coords.csv' 8 | n_features <- 2000 9 | Ks <- 10 10 | Kg <- 20 11 | 12 | # load data 13 | print('load data...') 14 | sc_data <- read.csv(file = sc_data_file, row.names = 1) 15 | sc_meta <- read.csv(file = sc_meta_file, row.names = 1) 16 | pseudo_coords <- read.csv(file = pseudo_coords_file, row.names = 1) 17 | 18 | rownames(sc_meta) <- colnames(sc_data) 19 | sc_meta$pseudo_x <- pseudo_coords[,1] 20 | sc_meta$pseudo_y <- pseudo_coords[,2] 21 | 22 | sc_seu <- SeuratObject::CreateSeuratObject(sc_data, meta.data = sc_meta, verbose = FALSE) 23 | sc_seu <- NormalizeData(sc_seu, verbose = FALSE) 24 | sc_seu <- FindVariableFeatures(sc_seu, nfeatures = n_features, verbose = FALSE) 25 | sc_seu <- ScaleData(sc_seu) 26 | sc_seu <- RunPCA(sc_seu) 27 | 28 | sc_seu <- spa_cluster( 29 | sc_seu = sc_seu, 30 | coord_index = c('pseudo_x', 'pseudo_y'), 31 | Ks = 10, 32 | Kg = 20, 33 | res = 0.35 34 | ) 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /AnalysisPaper/scripts/figure6/COVID19.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "import scipy.io\n", 11 | "import scipy.linalg\n", 12 | "import sklearn.metrics\n", 13 | "from sklearn.neighbors import KNeighborsClassifier\n", 14 | "from sklearn.model_selection import train_test_split\n", 15 | "import pandas as pd\n", 16 | "\n", 17 | "import anndata as ad\n", 18 | "import scanpy as sc\n", 19 | "from sklearn.neighbors import KDTree\n", 20 | "import igraph as ig\n", 21 | "from scipy import sparse\n", 22 | "from sklearn.neighbors import KDTree\n", 23 | "from itertools import chain\n", 24 | "\n", 25 | "import numpy as np\n", 26 | "import pandas as pd\n", 27 | "import torch\n", 28 | "import torch.optim as optim\n", 29 | "import warnings\n", 30 | "warnings.filterwarnings('ignore')\n", 31 | "import matplotlib.pyplot as plt\n", 32 | "%matplotlib inline" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "def kernel(ker, X1, X2, gamma):\n", 42 | " K = None\n", 43 | " if not ker or ker == 'primal':\n", 44 | " K = X1\n", 45 | " elif ker == 'linear':\n", 46 | " if X2 is not None:\n", 47 | " K = sklearn.metrics.pairwise.linear_kernel(\n", 48 | " np.asarray(X1).T, np.asarray(X2).T)\n", 49 | " else:\n", 50 | " K = sklearn.metrics.pairwise.linear_kernel(np.asarray(X1).T)\n", 51 | " elif ker == 'rbf':\n", 52 | " if X2 is not None:\n", 53 | " K = sklearn.metrics.pairwise.rbf_kernel(\n", 54 | " np.asarray(X1).T, np.asarray(X2).T, gamma)\n", 55 | " else:\n", 56 | " K = sklearn.metrics.pairwise.rbf_kernel(\n", 57 | " np.asarray(X1).T, None, gamma)\n", 58 | " return K\n", 59 | "\n", 60 | "\n", 61 | "class TCA:\n", 62 | " def __init__(self, kernel_type='primal', dim=30, lamb=1, gamma=1):\n", 63 | " '''\n", 64 | " Init func\n", 65 | " :param kernel_type: kernel, values: 'primal' | 'linear' | 'rbf'\n", 66 | " :param dim: dimension after transfer\n", 67 | " :param lamb: lambda value in equation\n", 68 | " :param gamma: kernel bandwidth for rbf kernel\n", 69 | " '''\n", 70 | " self.kernel_type = kernel_type\n", 71 | " self.dim = dim\n", 72 | " self.lamb = lamb\n", 73 | " self.gamma = gamma\n", 74 | "\n", 75 | " def fit(self, Xs, Xt):\n", 76 | " '''\n", 77 | " Transform Xs and Xt\n", 78 | " :param Xs: ns * n_feature, source feature\n", 79 | " :param Xt: nt * n_feature, target feature\n", 80 | " :return: Xs_new and Xt_new after TCA\n", 81 | " '''\n", 82 | " X = np.hstack((Xs.T, Xt.T))\n", 83 | " X /= np.linalg.norm(X, axis=0)\n", 84 | " m, n = X.shape\n", 85 | " ns, nt = len(Xs), len(Xt)\n", 86 | " e = np.vstack((1 / ns * np.ones((ns, 1)), -1 / nt * np.ones((nt, 1))))\n", 87 | " M = e * e.T\n", 88 | " M = M / np.linalg.norm(M, 'fro')\n", 89 | " H = np.eye(n) - 1 / n * np.ones((n, n))\n", 90 | " K = kernel(self.kernel_type, X, None, gamma=self.gamma)\n", 91 | " n_eye = m if self.kernel_type == 'primal' else n\n", 92 | " a, b = K @ M @ K.T + self.lamb * np.eye(n_eye), K @ H @ K.T\n", 93 | " w, V = scipy.linalg.eig(a, b)\n", 94 | " ind = np.argsort(w)\n", 95 | " A = V[:, ind[:self.dim]]\n", 96 | " Z = A.T @ K\n", 97 | " Z /= np.linalg.norm(Z, axis=0)\n", 98 | "\n", 99 | " Xs_new, Xt_new = Z[:, :ns].T, Z[:, ns:].T\n", 100 | " return Xs_new, Xt_new" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [ 108 | { 109 | "name": "stdout", 110 | "output_type": "stream", 111 | "text": [ 112 | "load data...\n", 113 | "tca...\n" 114 | ] 115 | } 116 | ], 117 | "source": [ 118 | "# covid19 mdm\n", 119 | "# load data\n", 120 | "print('load data...')\n", 121 | "sc_data_processed = pd.read_csv('~/workspace/spatial_cluster/covid_19/sc_data_processed.csv', index_col=0)\n", 122 | "sc_meta_processed = pd.read_csv('~/workspace/spatial_cluster/covid_19/sc_meta_processed.csv', index_col=0)\n", 123 | "st_data_processed = pd.read_csv('~/workspace/spatial_cluster/covid_19/st_data_processed.csv', index_col=0)\n", 124 | "st_meta_processed = pd.read_csv('~/workspace/spatial_cluster/covid_19/st_meta_processed.csv', index_col=0)\n", 125 | "\n", 126 | "# tca\n", 127 | "print('tca...')\n", 128 | "obj = TCA(kernel_type='primal', dim=50, lamb=1, gamma=1)\n", 129 | "sc_new, st_new = obj.fit(Xs=np.array(sc_data_processed.T), Xt=np.array(st_data_processed.T))\n", 130 | "print('tca done.')" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 7, 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "name": "stdout", 140 | "output_type": "stream", 141 | "text": [ 142 | "mlp...\n", 143 | "0 2169.201\n", 144 | "100 148.96654\n", 145 | "200 126.64259\n", 146 | "300 113.56344\n", 147 | "400 104.2271\n", 148 | "500 96.40067\n", 149 | "600 89.60366\n", 150 | "700 83.597404\n", 151 | "800 78.12729\n", 152 | "900 73.05979\n", 153 | "saving...\n" 154 | ] 155 | } 156 | ], 157 | "source": [ 158 | "print('mlp...')\n", 159 | "label = np.array(st_meta_processed[['V3','V4']])\n", 160 | "input_size = st_new.shape[1]\n", 161 | "hidden_size = 128\n", 162 | "output_size = 2\n", 163 | "batch_size = 16\n", 164 | "my_nn = torch.nn.Sequential(\n", 165 | " torch.nn.Linear(input_size, hidden_size),\n", 166 | " torch.nn.Sigmoid(),\n", 167 | " torch.nn.Linear(hidden_size, output_size),\n", 168 | ")\n", 169 | "cost = torch.nn.MSELoss(reduction='mean')\n", 170 | "optimizer = torch.optim.Adam(my_nn.parameters(), lr = 0.001)\n", 171 | "\n", 172 | "losses = []\n", 173 | "for i in range(1000):\n", 174 | " batch_loss = []\n", 175 | " for start in range(0, len(st_new), batch_size):\n", 176 | " end = start + batch_size if start + batch_size < len(st_new) else len(st_new)\n", 177 | " xx = torch.tensor(st_new[start:end], dtype = torch.float, requires_grad = True)\n", 178 | " yy = torch.tensor(label[start:end], dtype = torch.float, requires_grad = True)\n", 179 | " prediction = my_nn(xx)\n", 180 | " loss = cost(prediction, yy)\n", 181 | " optimizer.zero_grad()\n", 182 | " loss.backward(retain_graph=True)\n", 183 | " optimizer.step()\n", 184 | " batch_loss.append(loss.data.numpy())\n", 185 | " \n", 186 | " if i % 100==0:\n", 187 | " losses.append(np.mean(batch_loss))\n", 188 | " print(i, np.mean(batch_loss))\n", 189 | "\n", 190 | "print('saving...') \n", 191 | "predict = my_nn(torch.tensor(np.array(sc_new), dtype = torch.float, requires_grad = True)).data.numpy()\n", 192 | "pd.DataFrame(predict).to_csv('~/workspace/spatial_cluster/covid_19/pseudo_coords.csv')" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [] 201 | } 202 | ], 203 | "metadata": { 204 | "kernelspec": { 205 | "display_name": "scspace", 206 | "language": "python", 207 | "name": "scspace" 208 | }, 209 | "language_info": { 210 | "codemirror_mode": { 211 | "name": "ipython", 212 | "version": 3 213 | }, 214 | "file_extension": ".py", 215 | "mimetype": "text/x-python", 216 | "name": "python", 217 | "nbconvert_exporter": "python", 218 | "pygments_lexer": "ipython3", 219 | "version": "3.9.12" 220 | } 221 | }, 222 | "nbformat": 4, 223 | "nbformat_minor": 4 224 | } 225 | -------------------------------------------------------------------------------- /AnalysisPaper/scripts/figure6/MDM_spatial_informed_clustering.R: -------------------------------------------------------------------------------- 1 | # this R script is for scSpace spatial-informed clustering step 2 | 3 | source('../scripts/utils.R') 4 | # parameters 5 | sc_data_file <- '~/workspace/scSpace/data/[9]human_covid19/original_data/sc_data_sampled.csv' 6 | sc_meta_file <- '~/workspace/scSpace/data/[9]human_covid19/original_data/sc_meta_sampled.csv' 7 | pseudo_coords_file <- '~/workspace/scSpace/data/[9]human_covid19/pseudo_space/pseudo_coords.csv' 8 | n_features <- 2000 9 | Ks <- 10 10 | Kg <- 20 11 | 12 | # load data 13 | print('load data...') 14 | sc_data <- read.csv(file = sc_data_file, row.names = 1) 15 | sc_meta <- read.csv(file = sc_meta_file, row.names = 1) 16 | pseudo_coords <- read.csv(file = pseudo_coords_file, row.names = 1) 17 | 18 | rownames(sc_meta) <- colnames(sc_data) 19 | sc_meta$pseudo_x <- pseudo_coords[,1] 20 | sc_meta$pseudo_y <- pseudo_coords[,2] 21 | 22 | mdm_meta <- sc_meta[sc_meta$cell_type_fine == 'Monocyte-derived macrophages' | sc_meta$cell_type_fine == 'Transitioning MDM', ] 23 | mdm_data <- sc_data[, rownames(mdm_meta)] 24 | sc_seu <- SeuratObject::CreateSeuratObject(mdm_data, meta.data = mdm_meta, verbose = FALSE) 25 | sc_seu <- FindVariableFeatures(sc_seu, nfeatures = n_features, verbose = FALSE) 26 | sc_seu <- ScaleData(sc_seu) 27 | sc_seu <- RunPCA(sc_seu) 28 | 29 | sc_seu <- spa_cluster( 30 | sc_seu = sc_seu, 31 | coord_index = c('pseudo_x', 'pseudo_y'), 32 | Ks = 10, 33 | Kg = 20, 34 | res = 0.6 35 | ) 36 | -------------------------------------------------------------------------------- /AnalysisPaper/scripts/utils.R: -------------------------------------------------------------------------------- 1 | # custom functions for downstream analysis 2 | 3 | 4 | run_RCTD <- function(sc_meta, 5 | sc_data, 6 | st_meta, 7 | st_data, 8 | celltype_index){ 9 | ### Create the Reference object 10 | cell_types <- as.factor(sc_meta[[celltype_index]]); names(cell_types) <- colnames(sc_data) 11 | reference <- Reference(sc_data, cell_types, require_int = FALSE) 12 | 13 | coords <- data.frame(x = st_meta$xcoord, y = st_meta$ycoord) 14 | rownames(coords) <- colnames(st_data) 15 | 16 | ### Create SpatialRNA object 17 | puck <- SpatialRNA(coords, st_data, require_int = FALSE) 18 | 19 | myRCTD <- create.RCTD(puck, reference, CELL_MIN_INSTANCE = 5) 20 | myRCTD <- run.RCTD(myRCTD, doublet_mode = 'full') 21 | results <- myRCTD@results 22 | # normalize the cell type proportions to sum to 1. 23 | norm_weights <- normalize_weights(results$weights) 24 | norm_weights <- data.frame(as.matrix(norm_weights)) 25 | 26 | return(norm_weights) 27 | } 28 | 29 | 30 | run_Seurat <- function(sc_meta, 31 | sc_data, 32 | res){ 33 | sc_seu <- CreateSeuratObject(sc_data, meta.data = sc_meta, verbose = FALSE) 34 | sc_seu <- NormalizeData(sc_seu, verbose = FALSE) 35 | sc_seu <- FindVariableFeatures(sc_seu, nfeatures = 2000, verbose = FALSE) 36 | sc_seu <- ScaleData(sc_seu, features = rownames(sc_seu), verbose = FALSE) 37 | sc_seu <- RunPCA(sc_seu, verbose = FALSE) 38 | sc_seu <- RunTSNE(sc_seu, dims = 1:20, verbose = FALSE) 39 | sc_seu <- FindNeighbors(sc_seu) 40 | sc_seu <- FindClusters(sc_seu, resolution = res) 41 | return(sc_seu) 42 | } 43 | 44 | 45 | cal_dist <- function(meta, 46 | coord_index, 47 | group_by, 48 | selected_type, 49 | ignore_select_type = FALSE){ 50 | dist <- as.matrix(dist(meta[, coord_index])) 51 | 52 | ct_type <- sort(unique(meta[[group_by]])) 53 | 54 | if(ignore_select_type){ 55 | ct_type <- setdiff(ct_type, selected_type) 56 | } 57 | 58 | select_ct_index <- which(meta[[group_by]] == selected_type) 59 | 60 | pseudo_dist_table <- data.frame() 61 | 62 | message('Beginning normalized distance calculating...') 63 | pb <- progress::progress_bar$new(format = ' Calculating [:bar] :percent eta: :eta', 64 | total = length(ct_type), clear = FALSE, width = 60, 65 | complete = "+", incomplete = "-") 66 | 67 | # dist 68 | for (i in ct_type) { 69 | ct_index <- which(meta[[group_by]] == i) 70 | dist_list <- c() 71 | if(i == selected_type){ 72 | for (j in ct_index) { 73 | col_index <- j 74 | dist_list <- c(dist_list, dist[ct_index, col_index]) 75 | ct_index <- setdiff(ct_index, col_index) 76 | } 77 | } 78 | else{ 79 | for (j in select_ct_index) { 80 | col_index <- j 81 | dist_list <- c(dist_list, dist[ct_index, col_index]) 82 | } 83 | } 84 | 85 | dist_table <- data.frame(dist = dist_list, 86 | group = rep(paste0(selected_type, '_', i), length(dist_list))) 87 | 88 | pseudo_dist_table <- rbind(pseudo_dist_table, dist_table) 89 | 90 | pb$tick() 91 | } 92 | print('Normalized distance calculating done.') 93 | 94 | pseudo_dist_table$dist <- pseudo_dist_table$dist / max(pseudo_dist_table$dist) 95 | return(pseudo_dist_table) 96 | 97 | } 98 | 99 | 100 | plotEnrichment_new <- function(pathway, stats, 101 | gseaParam=1, 102 | ticksSize=0.2) { 103 | 104 | rnk <- rank(-stats) 105 | ord <- order(rnk) 106 | 107 | statsAdj <- stats[ord] 108 | statsAdj <- sign(statsAdj) * (abs(statsAdj) ^ gseaParam) 109 | statsAdj <- statsAdj / max(abs(statsAdj)) 110 | 111 | pathway <- unname(as.vector(na.omit(match(pathway, names(statsAdj))))) 112 | pathway <- sort(pathway) 113 | 114 | gseaRes <- calcGseaStat(statsAdj, selectedStats = pathway, 115 | returnAllExtremes = TRUE) 116 | 117 | bottoms <- gseaRes$bottoms 118 | tops <- gseaRes$tops 119 | 120 | n <- length(statsAdj) 121 | xs <- as.vector(rbind(pathway - 1, pathway)) 122 | ys <- as.vector(rbind(bottoms, tops)) 123 | toPlot <- data.frame(x=c(0, xs, n + 1), y=c(0, ys, 0)) 124 | 125 | diff <- (max(tops) - min(bottoms)) / 8 126 | 127 | # Getting rid of NOTEs 128 | x=y=NULL 129 | g <- ggplot(toPlot, aes(x=x, y=y)) + 130 | # geom_point(color="blue", size=0.1) + 131 | # geom_hline(yintercept=max(tops), colour="red", linetype="dashed") + 132 | # geom_hline(yintercept=min(bottoms), colour="red", linetype="dashed") + 133 | geom_hline(yintercept=0, colour="black") + 134 | geom_line(color="#059669", size = 1.5) + theme_bw() + 135 | geom_segment(data=data.frame(x=pathway), 136 | mapping=aes(x=x, y=-diff/2, 137 | xend=x, yend=diff/2), 138 | size=ticksSize) + 139 | 140 | theme(panel.border=element_blank(), 141 | panel.grid.minor=element_blank()) + 142 | 143 | labs(x="rank", y="enrichment score") 144 | g 145 | } 146 | 147 | 148 | run_DRSC <- function(data, 149 | meta, 150 | cluster_num){ 151 | 152 | 153 | seu <- CreateSeuratObject(data, meta.data = meta) 154 | seu <- NormalizeData(seu, verbose = F) 155 | # choose 480 spatially variable features 156 | seu <- FindSVGs(seu, nfeatures = 480) 157 | ### Given K 158 | seu <- DR.SC(seu, K=cluster_num, platform = 'seqfish', verbose=F) 159 | 160 | res <- seu@meta.data 161 | 162 | return(res) 163 | } 164 | 165 | 166 | run_BayesSpace <- function(data, 167 | meta, 168 | cluster_num){ 169 | 170 | 171 | sce <- SingleCellExperiment(assays=list(counts=as(as.matrix(data), "dgCMatrix")), colData=meta) 172 | 173 | set.seed(102) 174 | sce <- spatialPreprocess(sce, platform="Visium", 175 | n.PCs=15, n.HVGs=2000, log.normalize=TRUE) 176 | set.seed(149) 177 | sce <- spatialCluster(sce, q=cluster_num, platform="Visium", d=15, 178 | init.method="mclust", model="t", gamma=2, 179 | nrep=10000, burn.in=100, 180 | save.chain=TRUE) 181 | 182 | res <- data.frame(sce@colData) 183 | 184 | return(res) 185 | } 186 | 187 | 188 | # evaluate clustering results in benchmarking step 189 | eva_function <- function(clu_obj, 190 | sim_id, 191 | method_choose, 192 | all_cluster = TRUE, 193 | select_spatial_cluster = NULL){ 194 | if(all_cluster){ 195 | print('calculating all clusters...') 196 | meta <- clu_obj 197 | } 198 | else{ 199 | print('calculating spatial clustering...') 200 | meta <- clu_obj 201 | meta <- meta[meta$Group %in% select_spatial_cluster, ] 202 | } 203 | 204 | meta[[method_choose]] <- as.factor(meta[[method_choose]]) 205 | 206 | ari <- mclust::adjustedRandIndex(meta$Group, meta[[method_choose]]) 207 | nmi <- NMI::NMI(data.frame(cell = 1:nrow(meta), clu = meta$Group), 208 | data.frame(cell = 1:nrow(meta), clu = meta[[method_choose]]))$value 209 | 210 | 211 | 212 | res_obj <- data.frame( 213 | sim = sim_id, 214 | method = method_choose, 215 | ari = ari, 216 | nmi = nmi) 217 | 218 | return(res_obj) 219 | } 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | # old spatial-informed clustering for scSpace 229 | spa_cluster <- function(sc_seu, 230 | coord_index, 231 | seeds = 100, 232 | res, 233 | Ks, 234 | Kg){ 235 | knn_idx <- data.frame(BiocNeighbors::findKNN(sc_seu@meta.data[,coord_index], k = Ks)$index) 236 | N <- nrow(knn_idx) 237 | W <- matrix(0, N, N) 238 | 239 | diag(W) <- 1 240 | for (i in 1:nrow(W)) { 241 | W[i, as.numeric(knn_idx[i,])] <- 1 242 | } 243 | 244 | colnames(W) <- rownames(W) <- colnames(sc_seu) 245 | 246 | sc_pca_ori <- sc_seu@reductions$pca@cell.embeddings 247 | 248 | 249 | # create gene expression k-nearest neighbors 250 | knn_idx <- BiocNeighbors::findKNN(sc_pca_ori, k = Kg)$index 251 | 252 | # create weights from binary adjacency matrix W 253 | sp_graph <- igraph::graph_from_adjacency_matrix(W) 254 | sp_graph <- igraph::simplify(sp_graph) 255 | sp_weight <- matrix(ncol = ncol(knn_idx), nrow = nrow(knn_idx)) 256 | for (i in 1:nrow(knn_idx)) { 257 | to_idx <- as.numeric(knn_idx[i,]) 258 | sp_weight[i,] <- igraph::distances(sp_graph, rownames(W)[i], colnames(W)[to_idx]) 259 | } 260 | 261 | weight <- 1/(0 + as.vector(sp_weight)) + 0 262 | 263 | # graph-based clustering with spatial weights 264 | df <- data.frame(from = rep(1:nrow(knn_idx), Kg), 265 | to = as.vector(knn_idx), 266 | weight = weight) 267 | 268 | g <- igraph::graph_from_data_frame(df, directed = FALSE) 269 | g <- igraph::simplify(g) 270 | 271 | set.seed(seeds) 272 | cluster <- leidenAlg::leiden.community(g, resolution = res, n.iterations = 2) 273 | sc_seu$scSpace <- cluster$membership 274 | 275 | return(sc_seu) 276 | } 277 | 278 | 279 | 280 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scSpace v1.0.0 2 | 3 | ## Reconstruction of cell pseudo space from single-cell RNA sequencing data 4 | 5 | [![python >=3.8](https://img.shields.io/badge/python-%3E%3D3.8-brightgreen)](https://www.python.org/) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7790754.svg)](https://doi.org/10.5281/zenodo.7790754) 6 | 7 | scSpace (**s**ingle-**c**ell and **s**patial **p**osition **a**ssociated **c**o-**e**mbeddings) is an integrative algorithm that integrates spatial transcriptome data to reconstruct spatial associations of single cells within scRNA-seq data. Using [transfer component analysis (TCA)](https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=5640675&tag=1), scSpace could extract the characteristic matrixes of spatial transcriptomics and scRNA-seq, and project single cells into a pseudo space via a [multiple layer perceptron (MLP)](https://en.wikipedia.org/wiki/Multilayer_perceptron) model, so that gene expression and spatial weight of cells can be embedded jointly for the further cell typing with higher accuracy and precision. 8 | 9 | ![avatar](images/workflow.jpg) 10 | 11 | Code for generating the figures in this study can be found [here](AnalysisPaper). 12 | 13 | ## Requirements and Installation 14 | [![numpy 1.23.4](https://img.shields.io/badge/numpy-1.23.4-green)](https://pypi.org/project/numpy/) [![pandas 1.5.0](https://img.shields.io/badge/pandas-1.5.0-yellowgreen)](https://pypi.org/project/pandas/) [![scikit-learn 1.1.2](https://img.shields.io/badge/scikit--learn-1.1.2-yellow)](https://pypi.org/project/scikit-learn/) [![scipy 1.9.2](https://img.shields.io/badge/scipy-1.9.2-orange)](https://pypi.org/project/scipy/) [![scanpy 1.9.1](https://img.shields.io/badge/scanpy-1.9.1-red)](https://github.com/scverse/scanpy) [![matplotlib 3.6.3](https://img.shields.io/badge/matplotlib-3.6.3-blueviolet)](https://pypi.org/project/matplotlib/) [![igraph 0.10.2](https://img.shields.io/badge/igraph-0.10.2-blue)](https://pypi.org/project/igraph/) [![leidenalg 0.9.0](https://img.shields.io/badge/leidenalg-0.9.0-9cf)](https://pypi.org/project/leidenalg/) [![tqdm 4.64.1](https://img.shields.io/badge/tqdm-4.64.1-lightgrey)](https://pypi.org/project/tqdm/) 15 | 16 | ### Create and activate Python environment 17 | For scSpace, the python version need is over 3.8. If you have installed Python3.6 or Python3.7, consider installing Anaconda, and then you can create a new environment. 18 | ``` 19 | conda create -n scspace python=3.8 20 | conda activate scspace 21 | ``` 22 | ### Install pytorch 23 | The version of pytorch should be suitable to the CUDA version of your machine. You can find the appropriate version on the [PyTorch website](https://pytorch.org/get-started/locally/). 24 | Here is an example with CUDA11.6: 25 | ``` 26 | pip install torch --extra-index-url https://download.pytorch.org/whl/cu116 27 | ``` 28 | ### Install other requirements 29 | ``` 30 | cd scSpace-master 31 | pip install -r requirements.txt 32 | ``` 33 | ### Install scSpace 34 | ``` 35 | python setup.py build 36 | python setup.py install 37 | ``` 38 | 39 | ## Quick Start 40 | To use scSpace we require five formatted `.csv` files as input (i.e. read in by pandas). We have included a toy dataset 41 | in the [vignettes/data folder](vignettes/data) of this repository as examples to show how to use scSpace: 42 | * [Demonstration of scSpace on demo dataset](vignettes/demo.ipynb) 43 | 44 | 45 | ## Tutorials 46 | Additional step-by-step tutorials now available! Preprocessed datasets used can be downloaded from [Google Drive](https://drive.google.com/drive/folders/1a0dPYYFITrhmMhSeNc1HSWLfx6-bDy65?usp=sharing). 47 | 48 | 1. [Spatial reconstruction of human DLPFC spatial transcriptomics data](vignettes/DLPFC_slice151674.ipynb) 49 | 50 | 2. [Spatial reconstruction of human SCC spatial transcriptomics data](vignettes/SCC_p2.ipynb) 51 | 52 | 3. [Spatial reconstruction of mouse intestine scRNA-seq data](vignettes/intestines.ipynb) 53 | 54 | 4. [Spatial analysis of T cells subpopulations in melanoma](vignettes/melanoma.ipynb) 55 | 56 | 57 | ## About 58 | scSpace was developed by Jie Liao and Jingyang Qian. Should you have any questions, please contact Jie Liao at liaojie@zju.edu.cn, or Jingyang Qian at qianjingyang@zju.edu.cn 59 | 60 | ## References 61 | Qian, J., Liao, J., Liu, Z. et al. Reconstruction of the cell pseudo-space from single-cell RNA sequencing data with scSpace. Nat Commun 14, 2484 (2023). [https://doi.org/10.1038/s41467-023-38121-4](https://doi.org/10.1038/s41467-023-38121-4) 62 | -------------------------------------------------------------------------------- /images/workflow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZJUFanLab/scSpace/ab7cfff007289873fa38a06e528660772b235393/images/workflow.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | igraph==0.10.2 2 | leidenalg==0.9.0 3 | numpy==1.23.4 4 | pandas==1.5.0 5 | scanpy==1.9.1 6 | matplotlib==3.6.3 7 | scikit-learn==1.1.2 8 | scipy==1.9.2 9 | tqdm==4.64.1 10 | scikit-misc==0.1.4 11 | -------------------------------------------------------------------------------- /scSpace/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # @Time : 2022/7/20 9:41 上午 4 | # @Author : qjy 5 | # @Site : 6 | # @File : __init__.py.py 7 | # @Software: PyCharm 8 | 9 | 10 | __author__ = "Jingyang Qian" 11 | __email__ = "qianjingyang@zju.edu.cn" 12 | 13 | from .utils import * 14 | from .scspace import * 15 | from .models import * 16 | -------------------------------------------------------------------------------- /scSpace/models.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.io 3 | import scipy.linalg 4 | import sklearn.metrics 5 | from torch import nn 6 | 7 | 8 | def kernel(ker, X1, X2, gamma): 9 | K = None 10 | if not ker or ker == 'primal': 11 | K = X1 12 | elif ker == 'linear': 13 | if X2 is not None: 14 | K = sklearn.metrics.pairwise.linear_kernel( 15 | np.asarray(X1).T, np.asarray(X2).T) 16 | else: 17 | K = sklearn.metrics.pairwise.linear_kernel(np.asarray(X1).T) 18 | elif ker == 'rbf': 19 | if X2 is not None: 20 | K = sklearn.metrics.pairwise.rbf_kernel( 21 | np.asarray(X1).T, np.asarray(X2).T, gamma) 22 | else: 23 | K = sklearn.metrics.pairwise.rbf_kernel( 24 | np.asarray(X1).T, None, gamma) 25 | return K 26 | 27 | 28 | class TCA: 29 | def __init__(self, kernel_type='primal', dim=30, lamb=1, gamma=1): 30 | ''' 31 | Init func 32 | :param kernel_type: kernel, values: 'primal' | 'linear' | 'rbf' 33 | :param dim: dimension after transfer 34 | :param lamb: lambda value in equation 35 | :param gamma: kernel bandwidth for rbf kernel 36 | ''' 37 | self.kernel_type = kernel_type 38 | self.dim = dim 39 | self.lamb = lamb 40 | self.gamma = gamma 41 | 42 | def fit(self, Xs, Xt): 43 | ''' 44 | Transform Xs and Xt 45 | :param Xs: ns * n_feature, source feature 46 | :param Xt: nt * n_feature, target feature 47 | :return: Xs_new and Xt_new after TCA 48 | ''' 49 | X = np.hstack((Xs.T, Xt.T)) 50 | X /= np.linalg.norm(X, axis=0) 51 | m, n = X.shape 52 | ns, nt = len(Xs), len(Xt) 53 | e = np.vstack((1 / ns * np.ones((ns, 1)), -1 / nt * np.ones((nt, 1)))) 54 | M = e * e.T 55 | M = M / np.linalg.norm(M, 'fro') 56 | H = np.eye(n) - 1 / n * np.ones((n, n)) 57 | K = kernel(self.kernel_type, X, None, gamma=self.gamma) 58 | n_eye = m if self.kernel_type == 'primal' else n 59 | a, b = K @ M @ K.T + self.lamb * np.eye(n_eye), K @ H @ K.T 60 | w, V = scipy.linalg.eig(a, b) 61 | ind = np.argsort(w) 62 | A = V[:, ind[:self.dim]] 63 | Z = A.T @ K 64 | Z /= np.linalg.norm(Z, axis=0) 65 | 66 | Xs_new, Xt_new = Z[:, :ns].T, Z[:, ns:].T 67 | return Xs_new, Xt_new 68 | 69 | 70 | activation_dict = { 71 | 'relu': nn.ReLU, 72 | 'sigmoid': nn.Sigmoid 73 | } 74 | 75 | 76 | class sample_MLPEncoder(nn.Module): 77 | """sample MLPEncoder encoder model for scSpace.""" 78 | 79 | def __init__(self, input_size, common_size, hidden_size, activation): 80 | """Init MLP encoder.""" 81 | super(sample_MLPEncoder, self).__init__() 82 | self.restored = False 83 | common_size = common_size 84 | self.linear = nn.Sequential( 85 | nn.Linear(input_size, hidden_size), 86 | activation_dict[activation](), 87 | nn.Linear(hidden_size, common_size) 88 | ) 89 | 90 | def forward(self, x): 91 | out = self.linear(x) 92 | return out 93 | 94 | 95 | -------------------------------------------------------------------------------- /scSpace/scspace.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from .models import * 4 | from .utils import * 5 | from natsort import natsorted 6 | 7 | 8 | def construct_pseudo_space( 9 | sc_adata, 10 | st_adata, 11 | kernel_type: str = 'primal', 12 | dim: int = 50, 13 | lamb: int = 1, 14 | gamma: int = 1, 15 | batch_size: int = 16, 16 | hidden_size: int = 128, 17 | common_size: int = 2, 18 | activation: str = 'sigmoid', 19 | lr: float = 0.001, 20 | epoch_num: int = 1000, 21 | log_epoch: int = 100 22 | ): 23 | sc_data = sc_adata.X 24 | st_data = st_adata.X 25 | print('Beginning Transfer Component Analysis...') 26 | tca = TCA(kernel_type=kernel_type, dim=dim, lamb=lamb, gamma=gamma) 27 | sc_new, st_new = tca.fit(Xs=sc_data, Xt=st_data) 28 | print("Transfer Component Analysis done.") 29 | sc_adata.obsm['TCA'] = sc_new 30 | st_adata.obsm['TCA'] = st_new 31 | 32 | st_dataloader = get_data_loader(st_adata=st_adata, batch_size=batch_size) 33 | mlp = init_model(net=sample_MLPEncoder(input_size=dim, common_size=common_size, hidden_size=hidden_size, 34 | activation=activation)) 35 | # mlp = init_model(net=MLPEncoder(input_size=dim)) 36 | print('Beginning training encoder for source domain...') 37 | losses = [] 38 | encoder = train(encoder=mlp, losses=losses, data_loader=st_dataloader, 39 | lr=lr, epoch_num=epoch_num, log_epoch=log_epoch) 40 | print('Encoder for source domain training finished.') 41 | 42 | encoder.eval() 43 | sc_tca = np.array(sc_adata.obsm['TCA']) 44 | predict = encoder(make_cuda(torch.tensor(sc_tca).to(torch.float32))) 45 | pseudo_space = predict.cpu().detach().numpy() 46 | sc_adata.obsm['pseudo_space'] = pseudo_space 47 | 48 | return sc_adata, st_adata 49 | 50 | 51 | def spatial_cluster( 52 | sc_adata, 53 | use_neighbors: bool = True, 54 | l: float = 10, 55 | Ks: int = 10, 56 | Kg: int = 20, 57 | n_comps: int = 50, 58 | alpha: int = 0, 59 | beta: int = 0, 60 | res: float = 0.5, 61 | target_num: Optional[int] = None, 62 | step: float = 0.1, 63 | max_run: int = 20, 64 | random_seed: int = 123, 65 | use_weights: bool = True, 66 | partition_type: Optional[Type[MutableVertexPartition]] = None, 67 | n_iterations: int = -1 68 | ): 69 | 70 | # create space graph 71 | _, knn_idx = knn(data=sc_adata.obsm['pseudo_space'], query=sc_adata.obsm['pseudo_space'], k=Ks+1) 72 | knn_idx = np.delete(knn_idx, 0, axis=1) 73 | N = knn_idx.shape[0] 74 | W = np.diag([1] * N) 75 | for i in range(N): 76 | W[i, knn_idx[i]] = 1 77 | 78 | # create gene expression graph 79 | sc_adata_raw = sc_adata.raw.to_adata() 80 | sc_adata_raw = sc_adata_raw[:, sc_adata_raw.var.highly_variable] 81 | # sc.tl.pca(sc_adata_raw, svd_solver='arpack') 82 | sc.tl.pca(sc_adata_raw, svd_solver='arpack', n_comps=n_comps) 83 | sc_adata.obsm['X_pca'] = sc_adata_raw.obsm['X_pca'] 84 | 85 | _, knn_idx_2 = knn(data=sc_adata.obsm['X_pca'], query=sc_adata.obsm['X_pca'], k=Kg+1) 86 | knn_idx_2 = np.delete(knn_idx_2, 0, axis=1) 87 | 88 | if use_neighbors: 89 | print('Calculating spatial weights using the neighbours of spots...') 90 | # create spatial-weighted gene expression graph 91 | sp_weight = np.zeros((knn_idx_2.shape[0], knn_idx_2.shape[1])) 92 | sp_graph = ig.Graph.Adjacency((W > 0).tolist()) 93 | sp_graph = ig.Graph.simplify(sp_graph) 94 | for i in range(knn_idx_2.shape[0]): 95 | to_idx = knn_idx_2[i, ] 96 | sp_weight[i, ] = sp_graph.shortest_paths(i, to_idx, mode='all')[0] 97 | 98 | sp_weight = 1 / (alpha + sp_weight) + beta 99 | adjacency = np.zeros((sp_weight.shape[0], sp_weight.shape[0])) 100 | for i in range(N): 101 | adjacency[i, knn_idx_2[i]] = sp_weight[i] 102 | else: 103 | print('Calculating spatial weights using the distances across spots...') 104 | pairwise_dist = euclid_dist(coord=sc_adata.obsm['pseudo_space']) 105 | sp_weight = np.exp(-1 * (pairwise_dist**2) / (2 * (l**2))) 106 | adjacency = np.zeros((knn_idx_2.shape[0], knn_idx_2.shape[0])) 107 | for i in range(knn_idx_2.shape[0]): 108 | to_idx = knn_idx_2[i, ] 109 | adjacency[i, knn_idx_2[i]] = sp_weight[i][to_idx] 110 | 111 | g = get_igraph_from_adjacency(adjacency=adjacency, directed=None) 112 | 113 | if target_num is None: 114 | print('Unsupervised clustering with res = ', res, '...') 115 | cluster = run_leiden(g=g, resolution=res, random_state=random_seed, use_weights=use_weights, 116 | n_iterations=n_iterations, partition_type=partition_type) 117 | else: 118 | assert target_num > 1, 'Target cluster number must be greater than 1!' 119 | recommended_res = search_res(g=g, target_num=target_num, start=res, step=step, 120 | random_state=random_seed, max_run=max_run) 121 | cluster = run_leiden(g=g, resolution=recommended_res, random_state=random_seed, use_weights=use_weights, 122 | n_iterations=n_iterations, partition_type=partition_type) 123 | 124 | sc_adata.obs['scSpace'] = pd.Categorical( 125 | values=cluster.astype('U'), 126 | categories=natsorted(map(str, np.unique(cluster))), 127 | ) 128 | 129 | return sc_adata 130 | 131 | 132 | # def spatial_cluster_sub( 133 | # sc_adata, 134 | # celltype_key: str, 135 | # select_cell_type: list, 136 | # Ks: int = 10, 137 | # Kg: int = 20, 138 | # alpha: int = 0, 139 | # beta: int = 0, 140 | # res: float = 0.5, 141 | # target_num: Optional[int] = None, 142 | # step: float = 0.1, 143 | # random_seed: int = 123, 144 | # use_weights: bool = True, 145 | # partition_type: Optional[Type[MutableVertexPartition]] = None, 146 | # n_iterations: int = -1 147 | # ): 148 | # sc_adata_sub = sc_adata[sc_adata.obs[celltype_key].isin(select_cell_type)] 149 | # sc_adata_sub = spatial_cluster(sc_adata=sc_adata_sub, Ks=Ks, Kg=Kg, alpha=alpha, beta=beta, res=res, 150 | # target_num=target_num, step=step, random_seed=random_seed, use_weights=use_weights, 151 | # partition_type=partition_type, n_iterations=n_iterations) 152 | # 153 | # sc_adata.obs['scSpace'] = sc_adata.obs[celltype_key] 154 | # sc_adata.obs.loc[sc_adata_sub.obs.index, 'scSpace'] = sc_adata_sub.obs['scSpace'] 155 | # 156 | # return sc_adata 157 | 158 | 159 | -------------------------------------------------------------------------------- /scSpace/utils.py: -------------------------------------------------------------------------------- 1 | import math 2 | from typing import Optional, Tuple, Sequence, Type 3 | import numpy as np 4 | import scanpy as sc 5 | import anndata as ad 6 | import pandas as pd 7 | from torch.utils.data import Dataset, DataLoader 8 | from torch import nn 9 | import torch 10 | import torch.backends.cudnn as cudnn 11 | import torch.optim as optim 12 | from sklearn.neighbors import KDTree 13 | from sklearn.neighbors import NearestNeighbors 14 | from tqdm import tqdm 15 | import igraph as ig 16 | import leidenalg 17 | import logging as logg 18 | 19 | try: 20 | from leidenalg.VertexPartition import MutableVertexPartition 21 | except ImportError: 22 | 23 | class MutableVertexPartition: 24 | pass 25 | 26 | 27 | MutableVertexPartition.__module__ = 'leidenalg.VertexPartition' 28 | 29 | 30 | class MyDataset(Dataset): # 需要继承data.Dataset 31 | def __init__(self, data, label): 32 | # 1. Initialize file path or list of file names. 33 | self.data = data 34 | self.label = label 35 | 36 | def __getitem__(self, idx): 37 | # TODO 38 | tmp_x = self.data[idx] 39 | tmp_y_tag = self.label[idx] 40 | 41 | return (tmp_x, tmp_y_tag) # tag 分类 42 | 43 | def __len__(self): 44 | # You should change 0 to the total size of your dataset. 45 | return self.label.shape[0] 46 | 47 | 48 | def load_data( 49 | sc_data_path: str, 50 | sc_meta_path: str, 51 | st_data_path: str, 52 | st_meta_path: str, 53 | spatial_key: list = ['xcoord', 'ycoord'] 54 | ): 55 | """ 56 | load scRNA-seq data and spatial transcriptomic data, and return to AnnData objects 57 | :param sc_data_path: input scRNA-seq data file path 58 | :param sc_meta_path: input scRNA-seq meta file path 59 | :param st_data_path: input spatial transcriptomic data file path 60 | :param st_meta_path: input spatial transcriptomic data file path 61 | :param spatial_key: the columns of spatial coordinates 62 | :return: AnnData objects of scRNA-seq data and spatial transcriptomic data 63 | """ 64 | 65 | print('Loading data...') 66 | sc_meta = pd.read_csv(sc_meta_path, index_col=0) 67 | sc_data = pd.read_csv(sc_data_path, index_col=0) 68 | st_meta = pd.read_csv(st_meta_path, index_col=0) 69 | st_data = pd.read_csv(st_data_path, index_col=0) 70 | print('Data have been loaded.') 71 | 72 | sc_adata = ad.AnnData(sc_data.T) 73 | sc_adata.obs = sc_meta 74 | 75 | st_adata = ad.AnnData(st_data.T) 76 | st_adata.obs = st_meta 77 | st_adata.obsm['spatial'] = np.array(st_meta[spatial_key]) 78 | 79 | return sc_adata, st_adata 80 | 81 | 82 | # sc_obj, st_obj = load_data(sc_data_path='/home/qjy321/workspace/scspace_dev/scSpace/data/demo_sc_data.csv', 83 | # sc_meta_path='/home/qjy321/workspace/scspace_dev/scSpace/data/demo_sc_meta.csv', 84 | # st_data_path='/home/qjy321/workspace/scspace_dev/scSpace/data/demo_st_data.csv', 85 | # st_meta_path='/home/qjy321/workspace/scspace_dev/scSpace/data/demo_st_meta.csv') 86 | 87 | 88 | def preporcess( 89 | sc_adata, 90 | st_adata, 91 | st_type: str = 'spot', 92 | n_features: int = 2000, 93 | normalize: bool = True, 94 | select_hvg: str = 'intersection' 95 | ): 96 | """ 97 | pre-process the scRNA-seq and spatial transcriptomics data (find HVGs and normalized the data) 98 | :param select_hvg: 'intersection' or 'union' 99 | :param sc_adata: AnnData object of scRNA-seq data 100 | :param st_adata: AnnData object of spatial transcriptomics data 101 | :param st_type: the type of spatial transcriptomics data, `spot` or `image` 102 | :param n_features: the number of HVGs to select 103 | :param normalize: whether to normalize the data or not 104 | :return: AnnData object of processed scRNA-seq data and spatial transcriptomic data 105 | """ 106 | 107 | assert sc_adata.shape[1] >= n_features, 'There are too few genes in scRNA-seq data, please check again!' 108 | sc.pp.highly_variable_genes(sc_adata, flavor="seurat_v3", n_top_genes=n_features) 109 | 110 | assert st_type in ['spot', 111 | 'image'], 'Please select the correct type of spatial transcriptomic data, `spot` or `image`!' 112 | 113 | if st_type == 'spot': 114 | assert st_adata.shape[1] >= n_features, 'There are too few genes in ST data, please check again!' 115 | sc.pp.highly_variable_genes(st_adata, flavor="seurat_v3", n_top_genes=n_features) 116 | elif st_type == 'image': 117 | if st_adata.shape[1] >= n_features: 118 | sc.pp.highly_variable_genes(st_adata, flavor="seurat_v3", n_top_genes=n_features) 119 | else: 120 | sc.pp.highly_variable_genes(st_adata, flavor="seurat_v3", n_top_genes=st_adata.shape[1]) 121 | 122 | if normalize: 123 | # sc_adata 124 | sc.pp.normalize_total(sc_adata, target_sum=1e4) 125 | sc.pp.log1p(sc_adata) 126 | # st_adata 127 | sc.pp.normalize_total(st_adata, target_sum=1e4) 128 | sc.pp.log1p(st_adata) 129 | 130 | sc_adata.raw = sc_adata 131 | st_adata.raw = st_adata 132 | 133 | sc_hvg = sc_adata.var['highly_variable'][sc_adata.var['highly_variable'] == True].index 134 | st_hvg = st_adata.var['highly_variable'][st_adata.var['highly_variable'] == True].index 135 | if select_hvg == 'intersection': 136 | inter_gene = set(sc_hvg).intersection(set(st_hvg)) 137 | elif select_hvg == 'union': 138 | sc_gene = set(sc_adata.var_names) 139 | st_gene = set(st_adata.var_names) 140 | common_gene = set(sc_gene).intersection(set(st_gene)) 141 | 142 | inter_gene = set(sc_hvg).union(set(st_hvg)) 143 | inter_gene = set(inter_gene).intersection(set(common_gene)) 144 | 145 | sc_adata = sc_adata[:, list(inter_gene)] 146 | st_adata = st_adata[:, list(inter_gene)] 147 | 148 | print('Data have been pre-processed.') 149 | 150 | return sc_adata, st_adata 151 | 152 | 153 | # sc_obj, st_obj = preporcess(sc_adata=sc_obj, st_adata=st_obj, st_type='image', n_features=2000, normalize=True) 154 | 155 | 156 | def init_model(net): 157 | """Init models with cuda.""" 158 | 159 | # check if cuda is available 160 | if torch.cuda.is_available(): 161 | cudnn.benchmark = True 162 | net.cuda() 163 | 164 | return net 165 | 166 | 167 | def make_cuda(tensor): 168 | """Use CUDA if it's available.""" 169 | if torch.cuda.is_available(): 170 | tensor = tensor.cuda() 171 | return tensor 172 | 173 | 174 | def get_data_loader( 175 | st_adata, 176 | batch_size: int = 16, 177 | ): 178 | """Get dataset loader.""" 179 | # dataset 180 | data = torch.tensor(np.array(st_adata.obsm['TCA'])).to(torch.float32) 181 | label = torch.tensor(np.array(st_adata.obsm['spatial'])).to(torch.float32) 182 | 183 | # data loader 184 | dataloader = DataLoader( 185 | dataset=MyDataset(data=data, label=label), 186 | batch_size=batch_size, 187 | shuffle=True) 188 | 189 | return dataloader 190 | 191 | 192 | def train( 193 | encoder, 194 | data_loader, 195 | losses, 196 | lr: float = 0.001, 197 | epoch_num: int = 1000, 198 | log_epoch: int = 100 199 | ): 200 | """Train source domain.""" 201 | #################### 202 | # 1. setup network # 203 | #################### 204 | 205 | # set train state for Dropout and BN layers 206 | encoder.train() 207 | 208 | # setup criterion and optimizer 209 | optimizer = optim.Adam(encoder.parameters(), lr=lr) 210 | criterion = nn.MSELoss(reduction='mean') 211 | 212 | #################### 213 | # 2. train network # 214 | #################### 215 | 216 | for epoch in tqdm(range(epoch_num)): 217 | batch_loss = [] 218 | for step, data in enumerate(data_loader): 219 | features, labels = data 220 | 221 | features = make_cuda(features) 222 | labels = make_cuda(labels) 223 | 224 | # zero gradients for optimizer 225 | optimizer.zero_grad() 226 | 227 | # compute loss for critic 228 | pred = encoder(features) 229 | loss = criterion(pred, labels) 230 | 231 | # optimize source classifier 232 | loss.backward() 233 | optimizer.step() 234 | 235 | batch_loss.append(loss.cpu().data.numpy()) 236 | 237 | # print 238 | if (epoch + 1) % log_epoch == 0: 239 | losses.append(np.mean(batch_loss)) 240 | print("Epoch [{}/{}]: Batch loss={}" 241 | .format(epoch + 1, 242 | epoch_num, 243 | np.mean(batch_loss))) 244 | 245 | return encoder 246 | 247 | 248 | def knn(data, query, k): 249 | tree = KDTree(data) 250 | dist, ind = tree.query(query, k) 251 | return dist, ind 252 | 253 | 254 | def euclid_dist(coord): 255 | """ 256 | Calculate Euclidean distance between points 257 | """ 258 | dis = [] 259 | for i in range(len(coord)): 260 | dis.append([]) 261 | for j in range(len(coord)): 262 | dis[i].append(math.dist(coord[i], coord[j])) 263 | dis = np.array(dis) 264 | return dis 265 | 266 | 267 | def get_igraph_from_adjacency(adjacency, directed=None): 268 | """Get igraph graph from adjacency matrix.""" 269 | 270 | sources, targets = adjacency.nonzero() 271 | weights = adjacency[sources, targets] 272 | if isinstance(weights, np.matrix): 273 | weights = weights.A1 274 | g = ig.Graph(directed=directed) 275 | g.add_vertices(adjacency.shape[0]) # this adds adjacency.shape[0] vertices 276 | g.add_edges(list(zip(sources, targets))) 277 | try: 278 | g.es['weight'] = weights 279 | except KeyError: 280 | pass 281 | if g.vcount() != adjacency.shape[0]: 282 | logg.warning( 283 | f'The constructed graph has only {g.vcount()} nodes. ' 284 | 'Your adjacency matrix contained redundant nodes.' 285 | ) 286 | return g 287 | 288 | 289 | def run_leiden( 290 | g, 291 | resolution: float = 0.5, 292 | random_state: int = 123, 293 | use_weights: bool = True, 294 | n_iterations: int = -1, 295 | partition_type: Optional[Type[MutableVertexPartition]] = None, 296 | ): 297 | """ 298 | run Leiden clustering algorithm 299 | :param g: spatial-weighted gene expression graph 300 | :param resolution: A parameter value controlling the coarseness of the clustering. 301 | Higher values lead to more clusters. 302 | :param random_state: Change the initialization of the optimization. 303 | :param use_weights: If `True`, edge weights from the graph are used in the computation 304 | :param n_iterations: How many iterations of the Leiden clustering algorithm to perform. 305 | Positive values above 2 define the total number of iterations to perform, 306 | -1 has the algorithm run until it reaches its optimal clustering. 307 | :param partition_type: Type of partition to use. Defaults to :class:`~leidenalg.RBConfigurationVertexPartition`. 308 | For the available options, consult the documentation for :func:`~leidenalg.find_partition`. 309 | :return: clustering results 310 | """ 311 | 312 | partition_kwargs = dict() 313 | 314 | if partition_type is None: 315 | partition_type = leidenalg.RBConfigurationVertexPartition 316 | if use_weights: 317 | partition_kwargs['weights'] = np.array(g.es['weight']).astype(np.float64) 318 | partition_kwargs['n_iterations'] = n_iterations 319 | partition_kwargs['seed'] = random_state 320 | if resolution is not None: 321 | partition_kwargs['resolution_parameter'] = resolution 322 | # clustering proper 323 | part = leidenalg.find_partition(g, partition_type, **partition_kwargs) 324 | groups = np.array(part.membership) 325 | 326 | return groups 327 | 328 | 329 | def search_res( 330 | g, 331 | target_num, 332 | start: float = 0.5, 333 | step: float = 0.1, 334 | random_state: int = 123, 335 | max_run: int = 10, 336 | 337 | ): 338 | res = start 339 | print("Start at res = ", res, "step = ", step) 340 | original_group = run_leiden(g=g, resolution=res, random_state=random_state) 341 | original_num = len(np.unique(original_group)) 342 | print("Res = ", res, "number of clusters = ", original_num) 343 | run = 0 344 | 345 | while original_num != target_num: 346 | sign = 1 if (original_num < target_num) else -1 347 | new_group = run_leiden(g=g, resolution=(res + step * sign), random_state=random_state) 348 | new_num = len(np.unique(new_group)) 349 | print("Res = ", (res + step * sign), "number of clusters = ", new_num) 350 | 351 | if new_num == target_num: 352 | res = res + step * sign 353 | print("Recommended res = ", res) 354 | return res 355 | 356 | new_sign = 1 if (new_num < target_num) else -1 357 | if new_sign == sign: 358 | res = res + step * sign 359 | print("Res changed to", res) 360 | original_num = new_num 361 | else: 362 | step = step / 2 363 | print("Step changed to", step) 364 | 365 | assert res > 0, 'Res must be positive! Please increase the number of target clusters!' 366 | 367 | if run > max_run: 368 | print('No resolution found, recommended res = ', res) 369 | return res 370 | run += 1 371 | 372 | print("Recommended res = ", res) 373 | 374 | return res 375 | 376 | 377 | # TODO: Add comments 378 | def cal_dist(coord, 379 | normalize: bool = True): 380 | dist = [] 381 | for i in tqdm(range(len(coord))): 382 | xi, yi = coord[i, :] 383 | for j in range(len(coord)): 384 | if i >= j: 385 | continue 386 | xj, yj = coord[j, :] 387 | dist_tmp = np.sqrt((xi - xj) ** 2 + (yi - yj) ** 2) 388 | dist.append(dist_tmp) 389 | 390 | if normalize: 391 | dist = dist / max(dist) 392 | 393 | return dist 394 | 395 | 396 | def cal_dist_group(sc_adata, group_key, select_group): 397 | coord_all = sc_adata.obsm['pseudo_space'] 398 | 399 | group_df = sc_adata.obs[group_key] 400 | group_df = group_df.reset_index() 401 | group = list(np.unique(group_df[group_key])) 402 | assert select_group in group, 'Please select the correct group!' 403 | 404 | select_idx = group_df[group_df[group_key] == select_group].index 405 | selsct_coord = coord_all[select_idx] 406 | 407 | # dist_all = pd.DataFrame(columns=['dist', 'group']) 408 | dist_all = [] 409 | for g in group: 410 | print('Calculating all cell pairs between', select_group, 'and', g, '...') 411 | dist_group = [] 412 | tmp_idx = group_df[group_df[group_key] == g].index 413 | tmp_coord = coord_all[tmp_idx] 414 | 415 | if g == select_group: 416 | for i in tqdm(range(len(tmp_coord))): 417 | xi, yi = tmp_coord[i, :] 418 | for j in range(len(selsct_coord)): 419 | if i >= j: 420 | continue 421 | xj, yj = selsct_coord[j, :] 422 | dist_tmp = np.sqrt((xi - xj) ** 2 + (yi - yj) ** 2) 423 | dist_group.append(dist_tmp) 424 | else: 425 | for i in tqdm(range(len(tmp_coord))): 426 | xi, yi = tmp_coord[i, :] 427 | for j in range(len(selsct_coord)): 428 | xj, yj = selsct_coord[j, :] 429 | dist_tmp = np.sqrt((xi - xj) ** 2 + (yi - yj) ** 2) 430 | dist_group.append(dist_tmp) 431 | 432 | dist_all.append(dist_group) 433 | 434 | return dist_all 435 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | setup( 5 | name="scSpace", 6 | version="1.0.0", 7 | description='Reconstruction of cell pseudo space from single-cell RNA sequencing data', 8 | author='Jingyang Qian', 9 | author_email='qianjingyang@zju.edu.cn', 10 | url='https://github.com/ZJUFanLab/scSpace', 11 | packages=['scSpace'], 12 | install_requires=[], 13 | python_requires='>=3.8', 14 | license='GNU General Public License v3.0', 15 | ) 16 | 17 | 18 | 19 | --------------------------------------------------------------------------------