├── AssignGeneSignature.Rmd ├── DESCRIPTION ├── IndividualBatchEffectExploration.Rmd ├── LICENSE ├── README.md ├── ScrubletDoublet.Rmd ├── ScrubletDoubletValidation.Rmd ├── SeuratCellLevelFiltering.Rmd ├── SeuratProcess.Rmd ├── StackedVlnPlot.Rmd ├── _bookdown.yml ├── _output.yml ├── bookdown-demo.Rproj ├── docs ├── .nojekyll ├── assign-gene-signature.html ├── bookdown-demo_files │ └── figure-html │ │ ├── Dimplot-1.png │ │ ├── Dimplot-2.png │ │ ├── histogram-1.png │ │ ├── histogram-2.png │ │ ├── histogram-3.png │ │ ├── plot-1.png │ │ ├── plot-10.png │ │ ├── plot-11.png │ │ ├── plot-12.png │ │ ├── plot-13.png │ │ ├── plot-14.png │ │ ├── plot-15.png │ │ ├── plot-16.png │ │ ├── plot-2.png │ │ ├── plot-3.png │ │ ├── plot-4.png │ │ ├── plot-5.png │ │ ├── plot-6.png │ │ ├── plot-7.png │ │ ├── plot-8.png │ │ ├── plot-9.png │ │ ├── stackedvlnplot-1.png │ │ ├── unnamed-chunk-12-1.png │ │ ├── unnamed-chunk-13-1.png │ │ ├── unnamed-chunk-13-2.png │ │ ├── unnamed-chunk-13-3.png │ │ ├── unnamed-chunk-14-1.png │ │ ├── unnamed-chunk-14-2.png │ │ ├── unnamed-chunk-15-1.png │ │ ├── unnamed-chunk-16-1.png │ │ └── unnamed-chunk-16-2.png ├── find-doublet-using-scrublet.html ├── index.html ├── intro.html ├── libs │ ├── anchor-sections-1.0.1 │ │ ├── anchor-sections.css │ │ └── anchor-sections.js │ ├── clipboard-1.7.1 │ │ └── clipboard.min.js │ ├── gitbook-2.6.7 │ │ ├── css │ │ │ ├── fontawesome │ │ │ │ └── fontawesome-webfont.ttf │ │ │ ├── plugin-bookdown.css │ │ │ ├── plugin-clipboard.css │ │ │ ├── plugin-fontsettings.css │ │ │ ├── plugin-highlight.css │ │ │ ├── plugin-search.css │ │ │ ├── plugin-table.css │ │ │ └── style.css │ │ └── js │ │ │ ├── app.min.js │ │ │ ├── clipboard.min.js │ │ │ ├── jquery.highlight.js │ │ │ ├── lunr.js │ │ │ ├── plugin-bookdown.js │ │ │ ├── plugin-clipboard.js │ │ │ ├── plugin-fontsettings.js │ │ │ ├── plugin-search.js │ │ │ └── plugin-sharing.js │ ├── header-attrs-2.7 │ │ └── header-attrs.js │ ├── jquery-2.2.3 │ │ └── jquery.min.js │ ├── klippy-0.0.0.9500 │ │ ├── css │ │ │ └── klippy.min.css │ │ └── js │ │ │ └── klippy.min.js │ └── primer-tooltips-1.4.0 │ │ └── build.css ├── process-analysis.html ├── reference-keys.txt ├── scrublet-doublet-validation.html ├── search_index.json ├── seurat-individual-batch-effect-exploration.html ├── seurat-qc-cell-level-filtering.html ├── stacked-vlnplot-for-given-features-sets.html ├── style.css └── visualize.html ├── index.Rmd ├── scRNA-Process.Rmd ├── scRNA-Visualize.Rmd ├── scripts ├── process │ ├── N1_Seurat_QC-and-PreProcess_snRNA-seq.Rmd │ ├── N1_Seurat_QC-and-PreProcess_snRNA-seq.html │ ├── N2_Scrublet_Identify-Doublet.Rmd │ ├── N2_Scrublet_Identify-Doublet.html │ └── N2_Scrublet_Identify-Doublet.py └── visualize │ ├── Stacked-Vlnplot.R │ ├── V1_Seurat_QC-CellLevelFiltering.Rmd │ ├── V1_Seurat_QC-CellLevelFiltering.html │ ├── V2_Scrublet_Doublet_Validation.Rmd │ ├── V2_Scrublet_Doublet_Validation.html │ ├── V3_Seurat_Individual_BatchEffect_Explore.Rmd │ ├── V3_Seurat_Individual_BatchEffect_Explore.html │ ├── V4_Seurat_Assign_GeneSignature_GivenGeneList.Rmd │ ├── V4_Seurat_Assign_GeneSignature_GivenGeneList.html │ ├── V5_Seurat_StackedVlnPlot_GivenGeneSet.Rmd │ └── V5_Seurat_StackedVlnPlot_GivenGeneSet.html ├── style.css └── toc.css /AssignGeneSignature.Rmd: -------------------------------------------------------------------------------- 1 | # Assign Gene Signature 2 | 3 | ## Description 4 | 5 | Given a gene list, calculate gene signature by averaging gene expresion 6 | 7 | 8 | ## Load seurat object 9 | 10 | ```{r, cache=TRUE} 11 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 12 | Idents(combined) <- "cluster" 13 | ``` 14 | 15 | 16 | ## Load gene lists, here using the layer-enriched genes as examples 17 | 18 | ```{r loadgene, cache=TRUE} 19 | f.ls <- list.files( 20 | "data/GeneList/", 21 | pattern = "FDR001.upDEG.csv$", 22 | full.names = T, 23 | recursive = T 24 | ) 25 | names(f.ls) <- 26 | f.ls %>% map(basename) %>% map( ~ str_remove(.x, "vs.*")) 27 | 28 | layer.ls <- f.ls %>% map( ~ { 29 | df <- fread(.x) 30 | gn <- df$id[!is.na(df$id)] 31 | gn <- gn[which(gn %in% rownames(combined))] 32 | return(gn) 33 | }) 34 | ``` 35 | 36 | ## Calcuate gene signature per gene list 37 | 38 | ```{r genesignature, cache=TRUE} 39 | mean.ls <- layer.ls %>% map_dfc(~ colMeans(x = as.matrix(combined@assays$SCT[.x, ]), na.rm = TRUE)) 40 | rownames(mean.ls) <- rownames(combined@meta.data) 41 | combined <- AddMetaData(combined, mean.ls, col.name = colnames(mean.ls)) 42 | ``` 43 | 44 | ## Explore the gene signature by `FeaturePlot` and `VlnPlot` 45 | 46 | ```{r plot, cache=TRUE} 47 | names(layer.ls) %>% map(~ FeaturePlot(object = combined, features = .x, pt.size = 0.001)) 48 | names(layer.ls) %>% map(~ { 49 | VlnPlot(object = combined, features = .x, pt.size = 0) + NoLegend() 50 | }) 51 | ``` 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: placeholder 2 | Type: Book 3 | Title: Does not matter. 4 | Version: 0.0.1 5 | Imports: bookdown 6 | Remotes: rstudio/bookdown 7 | -------------------------------------------------------------------------------- /IndividualBatchEffectExploration.Rmd: -------------------------------------------------------------------------------- 1 | # Seurat Individual Batch Effect Exploration 2 | 3 | ## Descripiton 4 | 5 | Explore the individual batch effect by 6 | 7 | * Dimplot split by individual 8 | 9 | * Fractions of individuals per cluster 10 | 11 | 12 | ## Load seurat object 13 | 14 | ```{r, cache=TRUE} 15 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 16 | ``` 17 | 18 | ## Explore individual distribution by `Dimplot` 19 | 20 | ```{r Dimplot, cache=TRUE} 21 | Idents(object = combined) <- 'Individual' 22 | DimPlot(object = combined, reduction = "umap", label = T) 23 | DimPlot(object = combined, reduction = "tsne", label = T) 24 | ``` 25 | 26 | ## Calculate individual distribution per cluster with different resolution 27 | 28 | ```{r histogram, cache=TRUE} 29 | df <- data.table(combined@meta.data) 30 | sel.meta <- c("Individual", str_c('SCT_snn_res.', c(1, 1.5, 1.8))) 31 | df <- df[, sel.meta, with = FALSE] 32 | 33 | 34 | df[, 2:4] %>% imap(~ { 35 | freq1 <- df[, .N, keyby = .(.x, Individual)] 36 | freq1[, total := sum(N), by = .(.x)] 37 | freq1[, ratio := N / total] 38 | 39 | linesize = .35 40 | fontsize = 8 41 | 42 | ggplot(freq1, aes(fill = Individual, y = ratio, x = .x)) + 43 | geom_bar(position = "stack", stat = "identity") + 44 | scale_fill_brewer(palette = "Dark2") + 45 | xlab('Clsuter') + 46 | ggtitle(.y) + 47 | scale_y_continuous(breaks = seq(0, 1, 0.1), 48 | expand = c(0, 0), 49 | name = 'Percentage') + 50 | theme_bw() + 51 | theme( 52 | panel.grid.major.x = element_blank(), 53 | panel.grid.major.y = element_blank(), 54 | panel.grid.minor = element_blank(), 55 | strip.background = element_blank(), 56 | panel.border = element_rect(size = linesize), 57 | axis.ticks = element_blank(), 58 | axis.text.x = element_text(size = 5) 59 | ) + 60 | coord_flip() 61 | }) 62 | 63 | ``` 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SingleCell-Multiomics 2 | 3 | This is a collection for scRNA-seq and scATAC-seq analysis scripts. 4 | 5 | Demo-work is available at https://bookdown.org/ytliu13207/SingleCellMultiOmicsDataAnalysis/ 6 | 7 | Demo-data is availabe from Baidu Netdisk by url: https://pan.baidu.com/s/17o35HXmxtt3D4McJUGwfrw code: kcb1 8 | Alternative url: https://drive.google.com/file/d/1acAm2jwEPqgCKyzfFoNZc_R6DPdGSDEv/view?usp=sharing 9 | 10 | If you meet any question, please feel free to contact me by lyt17@pku.edu.cn 11 | 12 | -------------------------------------------------------------------------------- /ScrubletDoublet.Rmd: -------------------------------------------------------------------------------- 1 | # Find Doublet using Scrublet 2 | 3 | 4 | ## description 5 | 6 | Scoring and identify doublet using scrublet per samples 7 | 8 | 9 | 10 | ## input data 11 | 12 | filtered count matrix by cellRanger per samples 13 | 14 | ## process 15 | 16 | * running scrublet per samples 17 | 18 | * `N2-DoubletIdentify-Scurblet-Process.py -i Pre-A -r 0.02` 19 | * expected doublet ratio is calculated by ~ 0.8% per 1k cell 20 | * other parameters by default 21 | 22 | 23 | ## output 24 | 25 | * doublet scoring and identificaiton 26 | 27 | * `data/scrublet/*DoubletScores.csv` 28 | * `data/scrublet/*PredictedDoublets.csv` 29 | 30 | * validation plots 31 | 32 | * `data/scrublet/pdf` 33 | 34 | -------------------------------------------------------------------------------- /ScrubletDoubletValidation.Rmd: -------------------------------------------------------------------------------- 1 | # Scrublet Doublet Validation 2 | 3 | ## Description 4 | 5 | * check the doublet prediction from `scrublet` by 6 | 7 | * dimension reduction plot 8 | 9 | * nUMI distribution 10 | 11 | * judge the component for doublet cells by 12 | 13 | * DEG heatmap 14 | 15 | * canonical gene expression 16 | 17 | 18 | ## Load seurat object 19 | 20 | ```{r loaddata, cache=TRUE} 21 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 22 | Idents(combined) <- "cluster" 23 | ``` 24 | 25 | 26 | ## Validate the doublet prediction 27 | 28 | ```{r, cache=TRUE} 29 | # check whether the double cells cluster together 30 | FeaturePlot(combined, features = "DoubletScores", pt.size = 0.01) 31 | DimPlot( 32 | combined, 33 | group.by = "DoubletPrediction", 34 | pt.size = 0.01, 35 | cols = c("red", "azure3") 36 | ) 37 | 38 | # check the nUMI for doublet and singlet 39 | VlnPlot(combined, 40 | features = "nCount_RNA", 41 | pt.size = 0, 42 | group.by = "DoubletPrediction") + NoLegend() 43 | ``` 44 | 45 | ## Calculate factions of doublet per cluster 46 | 47 | ```{r, cache=TRUE} 48 | df <- data.table(combined@meta.data) 49 | sel.meta <- c("DoubletPrediction", "cluster", "Individual") 50 | df <- df[, sel.meta, with = FALSE] 51 | 52 | 53 | df[, 2:3] %>% map( ~ { 54 | freq1 <- df[, .N, keyby = .(.x, DoubletPrediction)] 55 | freq1[, total := sum(N), by = .(.x)] 56 | freq1[, ratio := N / total] 57 | 58 | linesize = .35 59 | fontsize = 8 60 | 61 | ggplot(freq1, aes(fill=DoubletPrediction, y=ratio, x= .x)) + 62 | geom_bar(position="stack", stat="identity")+ 63 | scale_fill_manual(values = c("Doublet" = 'red', "Singlet" = "grey")) + 64 | xlab('Clsuter') + 65 | scale_y_continuous(breaks = seq(0,1,0.1), expand = c(0,0), name = 'Percentage')+ 66 | theme_bw()+ 67 | theme( panel.grid.major.x = element_blank(), 68 | panel.grid.major.y = element_blank(), 69 | panel.grid.minor = element_blank(), 70 | strip.background = element_blank(),panel.border = element_rect(size = linesize), 71 | axis.ticks = element_blank(), 72 | axis.text.x = element_text(size = 5)) 73 | 74 | }) 75 | 76 | 77 | ``` 78 | 79 | ## Explore the component clusters for doublets by DEG 80 | 81 | * get the DEG for inferred source clusters. Here, for C33, InCGE and InMGE 82 | 83 | ```{r, cache=TRUE} 84 | 85 | # find DEG 86 | cluster.markers <- FindMarkers(combined, ident.1 = c("InMGE"), ident.2 = "InCGE", min.pct = 0.25) 87 | 88 | # subset cells of interest 89 | sel.idents <- c("InMGE", "InCGE", "D33") 90 | combined.small <- subset(combined, cells = WhichCells(combined, idents = sel.idents)) 91 | 92 | # check the expression for top DEG 93 | #sel.cells <- WhichCells(combined.small, idents = sel.idents, downsample = 355) # for large dataset 94 | DoHeatmap(combined.small, features = rownames(cluster.markers)[1:40], raster = F) 95 | 96 | ``` 97 | 98 | ## Explore the component clusters for doublets by canonical gene 99 | 100 | ```{r, cache=TRUE} 101 | sel.feature <- c("NXPH1", "PAM", "LHX6", "NR2F2", "ADARB2", "PROX1") 102 | FeaturePlot(combined, features = sel.feature, pt.size = 0.01, ncol = 3) 103 | VlnPlot(combined.small, features = sel.feature, pt.size = 0, ncol = 3, idents = sel.idents) 104 | ``` 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /SeuratCellLevelFiltering.Rmd: -------------------------------------------------------------------------------- 1 | # Seurat QC Cell-level Filtering 2 | 3 | 4 | 5 | 6 | ## Description 7 | 8 | Basic quality control for snRNA-seq: check the distribution of 9 | 10 | * number of UMIs per cell 11 | 12 | * should above 500 13 | 14 | * number of genes detected per cell 15 | 16 | * number of genes detected per UMI 17 | 18 | * check the complexity. outlier cells might be cells have less complex RNA species like red blood cells. 19 | expected higher than 0.8 20 | 21 | * mitochondrial ratio 22 | 23 | * dead or dying cells will cause large amount of mitochondrial contamination 24 | 25 | ## Load seurat object 26 | 27 | ```{r, cache=TRUE} 28 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 29 | ``` 30 | 31 | 32 | 33 | ## Add other meta info 34 | 35 | * fraction of reads mapping to mitochondrial gene 36 | 37 | ```{r, cache=TRUE} 38 | # for macaque, not all genes start with MT is mitochondrion genes 39 | mt.gene <- c("MTARC2","MTFR1L","MTERF1","MTFR2","MTRF1L","MTRES1", 40 | "MTO1","MTCH1","MTFMT","MTFR1","MTERF3","MTERF2","MTPAP", 41 | "MTERF4","MTCH2",'MTIF2',"MTG2","MTIF3","MTRF1","MTCL1") 42 | combined[["percent.mt"]] <- PercentageFeatureSet(combined, features = mt.gene ) 43 | ``` 44 | 45 | * number of genes detected per UMI 46 | 47 | ```{r} 48 | combined$log10GenesPerUMI <- log10(combined$nFeature_RNA) / log10(combined$nCount_RNA) 49 | ``` 50 | 51 | 52 | ## Violin plots to check 53 | 54 | * get the meta data 55 | 56 | ```{r, cache=TRUE} 57 | df <- as.data.table(combined@meta.data) 58 | sel <- c("orig.ident", "nCount_RNA", "nFeature_RNA", "percent.mt", "log10GenesPerUMI") 59 | df <- df[, sel, with = FALSE] 60 | df[1:3, ] 61 | ``` 62 | 63 | * define plotting function 64 | 65 | ```{r, cache=TRUE} 66 | fontsize <- 10 67 | linesize <- 0.35 68 | 69 | gp.ls <- df[, 2:5] %>% imap( ~ { 70 | 71 | # define lable fun 72 | give.n <- function(x) { 73 | return(c(y = median(x) + max(x) / 10, label = round(median(x), 2))) 74 | } 75 | 76 | # assign colors 77 | col.ls <- 78 | setNames( 79 | c('lightpink2', 'lightblue2', 'lightgreen', 'coral1'), 80 | c("nCount_RNA", "nFeature_RNA", "percent.mt", "log10GenesPerUMI") 81 | ) 82 | 83 | ggplot(data = df, aes(x = orig.ident, y = .x)) + 84 | geom_violin(trim = FALSE, fill = col.ls[.y]) + 85 | ggtitle(label = .y) + ylab(label = .y) + 86 | theme_bw() + 87 | theme( 88 | panel.grid.major = element_blank(), 89 | panel.grid.minor = element_blank(), 90 | strip.background = element_blank(), 91 | panel.border = element_blank() 92 | ) + 93 | theme( 94 | axis.text = element_text(size = fontsize), 95 | axis.line = element_line(colour = "black", size = linesize), 96 | axis.ticks = element_line(size = linesize), 97 | axis.title.x = element_blank(), 98 | axis.ticks.length = unit(.05, "cm"), 99 | plot.title = element_text(size = fontsize + 2, hjust = 0.5), 100 | legend.position = 'none' 101 | ) + 102 | stat_summary(fun = median, geom = "point", col = "black") + # Add points to plot 103 | stat_summary(fun.data = give.n, 104 | geom = "text", 105 | col = "black") 106 | }) 107 | 108 | grid.arrange(gp.ls[[1]], gp.ls[[2]], gp.ls[[3]], gp.ls[[4]], ncol = 2) 109 | ``` 110 | 111 | -------------------------------------------------------------------------------- /SeuratProcess.Rmd: -------------------------------------------------------------------------------- 1 | # Seurat Pre-process {#intro} 2 | 3 | 4 | 5 | ```{r setup, include=FALSE} 6 | library(Seurat) 7 | library(tidyverse) 8 | library(magrittr) 9 | library(data.table) 10 | library(ggplot2) 11 | library(gridExtra) 12 | library(stringr) 13 | ``` 14 | 15 | ```{r klippy, echo=FALSE, include=TRUE} 16 | klippy::klippy(lang = "markdown") 17 | ``` 18 | 19 | 20 | 21 | ## Load count matrix from CellRanger 22 | 23 | * for one experiment 24 | 25 | ```{r, eval = FALSE} 26 | pre <- Read10X(data.dir = 'cellranger-res/Pre-B/outs/filtered_feature_bc_matrix/') 27 | pre <- CreateSeuratObject(counts = pre, project = '11002C', min.cells = 3) 28 | ``` 29 | 30 | * for multiple experiments 31 | 32 | ```{r, eval = FALSE} 33 | # step1 list sample directories ---------------------------------------------- 34 | dir.ls <- list.dirs(path = 'cellranger-count/', 35 | full.names = T, 36 | recursive = F) 37 | dir.ls <- dir.ls[c(2:5)] 38 | dir.ls %<>% map( ~ paste0(.x, "/outs/filtered_feature_bc_matrix")) 39 | names(dir.ls) <- c('68A', '68B', '84B', '84C') 40 | 41 | # step2 check whether dir exist ------------------------------------------- 42 | dir.ls %>% map( ~ dir.exists(.x)) 43 | 44 | # step3 create seurat per samples ----------------------------------------- 45 | obj.ls <- dir.ls %>% map( ~ Read10X(.x)) %>% map( ~ CreateSeuratObject(.x, min.cells = 3)) 46 | ``` 47 | 48 | ### Quality control by visualization 49 | 50 | ```{bash, eval = FALSE} 51 | V1_Seurat_QC-CellLevelFiltering.R 52 | ``` 53 | 54 | ## Cell-level filtering 55 | 56 | ```{r, eval = FALSE} 57 | # filtering by nCount and nFeatures per individual 58 | filterCell <- function(combined){ 59 | # calculate the quantile range 60 | count.feature.ls <- combined@meta.data[, c("nCount_RNA", "nFeature_RNA")] 61 | count.feature.ls %<>% map(log10) %>% map(~c(10^(mean(.x) + 3*sd(.x)), 10^(mean(.x) - 3*sd(.x)))) 62 | 63 | # filter cells 64 | combined <- subset(combined, subset = nFeature_RNA > 200 & 65 | nFeature_RNA < count.feature.ls[[2]][1] & 66 | nCount_RNA < count.feature.ls[[1]][1]) 67 | return(combined) 68 | } 69 | obj.ls %<>% map(filterCell) 70 | ``` 71 | 72 | ## Merge individuals 73 | ```{r, eval = FALSE} 74 | combined <- merge(x = obj.ls[[1]], 75 | y = obj.ls[2:4], 76 | add.cell.ids = names(dir.ls)) 77 | ``` 78 | 79 | 80 | ## Normalize, scale, find variable genes and dimension reduciton 81 | 82 | * Choose the number of PC 83 | 84 | * SCT 85 | 86 | ```{r, eval = FALSE} 87 | combined %<>% 88 | SCTransform(return.only.var.genes = FALSE) %>% 89 | RunPCA(features = VariableFeatures(object = .)) %>% 90 | FindNeighbors(dims = 1:40) %>% 91 | FindClusters(resolution = c(0.5, 0.6, 0.8, 1, 1.2, 1.5, 1.8,2,2.5,3)) %>% 92 | RunUMAP(dims = 1:40) %>% 93 | RunTSNE(dims = 1:40) 94 | ``` 95 | 96 | * standard process 97 | 98 | ```{r, eval = FALSE} 99 | combined %<>% 100 | NormalizeData() %>% 101 | FindVariableFeatures(selection.method = 'vst', nfeatures = 2000) %>% 102 | ScaleData(features = rownames(.)) %>% 103 | RunPCA(features = VariableFeatures(object = .)) %>% 104 | FindNeighbors(dims = 1:30) %>% 105 | FindClusters(resolution = c(0.5, 0.6, 0.8, 1, 1.2, 1.5, 1.8,2,2.5,3)) %>% 106 | RunUMAP(dims = 1:30) %>% 107 | RunTSNE(dims = 1:30) 108 | ``` 109 | 110 | 111 | -------------------------------------------------------------------------------- /StackedVlnPlot.Rmd: -------------------------------------------------------------------------------- 1 | # Stacked Vlnplot for Given Features Sets 2 | 3 | ## Descripiton 4 | 5 | Stacked vlnplot for given gene set. `Seurat` V4 has provided the similar function 6 | 7 | 8 | ## Load seurat object 9 | 10 | ```{r, cache=TRUE} 11 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 12 | ``` 13 | 14 | ## Source stacked vlnplot funciton 15 | 16 | ```{r stackevlnfunc, cache=TRUE} 17 | source("scripts/visualize/Stacked-Vlnplot.R") 18 | ``` 19 | 20 | ## Stacked Vlnplot given gene set 21 | 22 | ```{r stackedvlnplot, cache=TRUE} 23 | sel.gene <- c("PAX6", "RBFOX1", "GAD1") 24 | 25 | StackedVlnPlot(combined, sel.gene, pt.size = 0) 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /_bookdown.yml: -------------------------------------------------------------------------------- 1 | book_filename: "bookdown-demo" 2 | language: 3 | ui: 4 | chapter_name: "Chapter " 5 | delete_merged_file: true 6 | output_dir: "docs" 7 | 8 | rmd_files: [ 9 | "index.Rmd", 10 | 11 | "scRNA-Process.Rmd", 12 | "SeuratProcess.Rmd", 13 | "ScrubletDoublet.Rmd", 14 | 15 | "scRNA-Visualize.Rmd", 16 | "SeuratCellLevelFiltering.Rmd", 17 | "ScrubletDoubletValidation.Rmd", 18 | "IndividualBatchEffectExploration.Rmd", 19 | "AssignGeneSignature.Rmd", 20 | "StackedVlnPlot.Rmd" 21 | 22 | ] 23 | -------------------------------------------------------------------------------- /_output.yml: -------------------------------------------------------------------------------- 1 | bookdown::gitbook: 2 | css: style.css 3 | config: 4 | toc: 5 | before: | 6 |
  • A Minimal Book Example
  • 7 | after: | 8 |
  • Published with bookdown
  • 9 | edit: https://github.com/rstudio/bookdown-demo/edit/master/%s 10 | download: ["pdf", "epub"] 11 | bookdown::pdf_book: 12 | includes: 13 | in_header: preamble.tex 14 | latex_engine: xelatex 15 | citation_package: natbib 16 | keep_tex: yes 17 | bookdown::epub_book: default 18 | -------------------------------------------------------------------------------- /bookdown-demo.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Website 19 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/.nojekyll -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/Dimplot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/Dimplot-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/Dimplot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/Dimplot-2.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/histogram-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/histogram-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/histogram-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/histogram-2.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/histogram-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/histogram-3.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-10.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-11.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-12.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-13.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-14.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-15.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-16.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-2.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-3.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-4.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-5.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-6.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-7.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-8.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/plot-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/plot-9.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/stackedvlnplot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/stackedvlnplot-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-12-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-13-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-13-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-13-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-13-2.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-13-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-13-3.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-14-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-14-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-14-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-14-2.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-15-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-15-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-16-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-16-1.png -------------------------------------------------------------------------------- /docs/bookdown-demo_files/figure-html/unnamed-chunk-16-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/bookdown-demo_files/figure-html/unnamed-chunk-16-2.png -------------------------------------------------------------------------------- /docs/libs/anchor-sections-1.0.1/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | a.anchor-section::before {content: '#';} 4 | .hasAnchor:hover a.anchor-section {visibility: visible;} 5 | ul > li > .anchor-section {display: none;} 6 | -------------------------------------------------------------------------------- /docs/libs/anchor-sections-1.0.1/anchor-sections.js: -------------------------------------------------------------------------------- 1 | // Anchor sections v1.0 written by Atsushi Yasumoto on Oct 3rd, 2020. 2 | document.addEventListener('DOMContentLoaded', function() { 3 | // Do nothing if AnchorJS is used 4 | if (typeof window.anchors === 'object' && anchors.hasOwnProperty('hasAnchorJSLink')) { 5 | return; 6 | } 7 | 8 | const h = document.querySelectorAll('h1, h2, h3, h4, h5, h6'); 9 | 10 | // Do nothing if sections are already anchored 11 | if (Array.from(h).some(x => x.classList.contains('hasAnchor'))) { 12 | return null; 13 | } 14 | 15 | // Use section id when pandoc runs with --section-divs 16 | const section_id = function(x) { 17 | return ((x.classList.contains('section') || (x.tagName === 'SECTION')) 18 | ? x.id : ''); 19 | }; 20 | 21 | // Add anchors 22 | h.forEach(function(x) { 23 | const id = x.id || section_id(x.parentElement); 24 | if (id === '' || x.matches(':empty')) { 25 | return null; 26 | } 27 | let anchor = document.createElement('a'); 28 | anchor.href = '#' + id; 29 | anchor.classList = ['anchor-section']; 30 | x.classList.add('hasAnchor'); 31 | x.appendChild(anchor); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /docs/libs/clipboard-1.7.1/clipboard.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * clipboard.js v1.7.1 3 | * https://zenorocha.github.io/clipboard.js 4 | * 5 | * Licensed MIT © Zeno Rocha 6 | */ 7 | !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function i(a,c){if(!n[a]){if(!e[a]){var l="function"==typeof require&&require;if(!c&&l)return l(a,!0);if(r)return r(a,!0);var s=new Error("Cannot find module '"+a+"'");throw s.code="MODULE_NOT_FOUND",s}var u=n[a]={exports:{}};e[a][0].call(u.exports,function(t){var n=e[a][1][t];return i(n||t)},u,u.exports,t,e,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function t(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function t(){var e=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px";var o=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=o+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,i.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function t(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function t(){this.selectedText=(0,i.default)(this.target),this.copyText()}},{key:"copyText",value:function t(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function t(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function t(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function t(){this.removeFake()}},{key:"action",set:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function t(){return this._action}},{key:"target",set:function t(e){if(void 0!==e){if(!e||"object"!==(void 0===e?"undefined":r(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function t(){return this._target}}]),t}();t.exports=c})},{select:5}],8:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if(void 0!==o)r(n,e("./clipboard-action"),e("tiny-emitter"),e("good-listener"));else{var a={exports:{}};r(a,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=a.exports}}(this,function(t,e,n,o){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function c(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function l(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}var s=i(e),u=i(n),f=i(o),d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},h=function(){function t(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===d(e.container)?e.container:document.body}},{key:"listenClick",value:function t(e){var n=this;this.listener=(0,f.default)(e,"click",function(t){return n.onClick(t)})}},{key:"onClick",value:function t(e){var n=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s.default({action:this.action(n),target:this.target(n),text:this.text(n),container:this.container,trigger:n,emitter:this})}},{key:"defaultAction",value:function t(e){return l("action",e)}},{key:"defaultTarget",value:function t(e){var n=l("target",e);if(n)return document.querySelector(n)}},{key:"defaultText",value:function t(e){return l("text",e)}},{key:"destroy",value:function t(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],n="string"==typeof e?[e]:e,o=!!document.queryCommandSupported;return n.forEach(function(t){o=o&&!!document.queryCommandSupported(t)}),o}}]),e}(u.default);t.exports=p})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)}); -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YutingPKU/SingleCell-Multiomics/161c48c7c0410bdc9e9f98edadfe11138c4ad13f/docs/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-bookdown.css: -------------------------------------------------------------------------------- 1 | .book .book-header h1 { 2 | padding-left: 20px; 3 | padding-right: 20px; 4 | } 5 | .book .book-header.fixed { 6 | position: fixed; 7 | right: 0; 8 | top: 0; 9 | left: 0; 10 | border-bottom: 1px solid rgba(0,0,0,.07); 11 | } 12 | span.search-highlight { 13 | background-color: #ffff88; 14 | } 15 | @media (min-width: 600px) { 16 | .book.with-summary .book-header.fixed { 17 | left: 300px; 18 | } 19 | } 20 | @media (max-width: 1240px) { 21 | .book .book-body.fixed { 22 | top: 50px; 23 | } 24 | .book .book-body.fixed .body-inner { 25 | top: auto; 26 | } 27 | } 28 | @media (max-width: 600px) { 29 | .book.with-summary .book-header.fixed { 30 | left: calc(100% - 60px); 31 | min-width: 300px; 32 | } 33 | .book.with-summary .book-body { 34 | transform: none; 35 | left: calc(100% - 60px); 36 | min-width: 300px; 37 | } 38 | .book .book-body.fixed { 39 | top: 0; 40 | } 41 | } 42 | 43 | .book .book-body.fixed .body-inner { 44 | top: 50px; 45 | } 46 | .book .book-body .page-wrapper .page-inner section.normal sub, .book .book-body .page-wrapper .page-inner section.normal sup { 47 | font-size: 85%; 48 | } 49 | 50 | @media print { 51 | .book .book-summary, .book .book-body .book-header, .fa { 52 | display: none !important; 53 | } 54 | .book .book-body.fixed { 55 | left: 0px; 56 | } 57 | .book .book-body,.book .book-body .body-inner, .book.with-summary { 58 | overflow: visible !important; 59 | } 60 | } 61 | .kable_wrapper { 62 | border-spacing: 20px 0; 63 | border-collapse: separate; 64 | border: none; 65 | margin: auto; 66 | } 67 | .kable_wrapper > tbody > tr > td { 68 | vertical-align: top; 69 | } 70 | .book .book-body .page-wrapper .page-inner section.normal table tr.header { 71 | border-top-width: 2px; 72 | } 73 | .book .book-body .page-wrapper .page-inner section.normal table tr:last-child td { 74 | border-bottom-width: 2px; 75 | } 76 | .book .book-body .page-wrapper .page-inner section.normal table td, .book .book-body .page-wrapper .page-inner section.normal table th { 77 | border-left: none; 78 | border-right: none; 79 | } 80 | .book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr, .book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr > td { 81 | border-top: none; 82 | } 83 | .book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr:last-child > td { 84 | border-bottom: none; 85 | } 86 | 87 | div.theorem, div.lemma, div.corollary, div.proposition, div.conjecture { 88 | font-style: italic; 89 | } 90 | span.theorem, span.lemma, span.corollary, span.proposition, span.conjecture { 91 | font-style: normal; 92 | } 93 | div.proof>*:last-child:after { 94 | content: "\25a2"; 95 | float: right; 96 | } 97 | .header-section-number { 98 | padding-right: .5em; 99 | } 100 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-clipboard.css: -------------------------------------------------------------------------------- 1 | div.sourceCode { 2 | position: relative; 3 | } 4 | 5 | .copy-to-clipboard-button { 6 | position: absolute; 7 | right: 0; 8 | top: 0; 9 | visibility: hidden; 10 | } 11 | 12 | .copy-to-clipboard-button:focus { 13 | outline: 0; 14 | } 15 | 16 | div.sourceCode:hover > .copy-to-clipboard-button { 17 | visibility: visible; 18 | } 19 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-fontsettings.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Theme 1 3 | */ 4 | .color-theme-1 .dropdown-menu { 5 | background-color: #111111; 6 | border-color: #7e888b; 7 | } 8 | .color-theme-1 .dropdown-menu .dropdown-caret .caret-inner { 9 | border-bottom: 9px solid #111111; 10 | } 11 | .color-theme-1 .dropdown-menu .buttons { 12 | border-color: #7e888b; 13 | } 14 | .color-theme-1 .dropdown-menu .button { 15 | color: #afa790; 16 | } 17 | .color-theme-1 .dropdown-menu .button:hover { 18 | color: #73553c; 19 | } 20 | /* 21 | * Theme 2 22 | */ 23 | .color-theme-2 .dropdown-menu { 24 | background-color: #2d3143; 25 | border-color: #272a3a; 26 | } 27 | .color-theme-2 .dropdown-menu .dropdown-caret .caret-inner { 28 | border-bottom: 9px solid #2d3143; 29 | } 30 | .color-theme-2 .dropdown-menu .buttons { 31 | border-color: #272a3a; 32 | } 33 | .color-theme-2 .dropdown-menu .button { 34 | color: #62677f; 35 | } 36 | .color-theme-2 .dropdown-menu .button:hover { 37 | color: #f4f4f5; 38 | } 39 | .book .book-header .font-settings .font-enlarge { 40 | line-height: 30px; 41 | font-size: 1.4em; 42 | } 43 | .book .book-header .font-settings .font-reduce { 44 | line-height: 30px; 45 | font-size: 1em; 46 | } 47 | 48 | /* sidebar transition background */ 49 | div.book.color-theme-1 { 50 | background: #f3eacb; 51 | } 52 | .book.color-theme-1 .book-body { 53 | color: #704214; 54 | background: #f3eacb; 55 | } 56 | .book.color-theme-1 .book-body .page-wrapper .page-inner section { 57 | background: #f3eacb; 58 | } 59 | 60 | /* sidebar transition background */ 61 | div.book.color-theme-2 { 62 | background: #1c1f2b; 63 | } 64 | 65 | .book.color-theme-2 .book-body { 66 | color: #bdcadb; 67 | background: #1c1f2b; 68 | } 69 | .book.color-theme-2 .book-body .page-wrapper .page-inner section { 70 | background: #1c1f2b; 71 | } 72 | .book.font-size-0 .book-body .page-inner section { 73 | font-size: 1.2rem; 74 | } 75 | .book.font-size-1 .book-body .page-inner section { 76 | font-size: 1.4rem; 77 | } 78 | .book.font-size-2 .book-body .page-inner section { 79 | font-size: 1.6rem; 80 | } 81 | .book.font-size-3 .book-body .page-inner section { 82 | font-size: 2.2rem; 83 | } 84 | .book.font-size-4 .book-body .page-inner section { 85 | font-size: 4rem; 86 | } 87 | .book.font-family-0 { 88 | font-family: Georgia, serif; 89 | } 90 | .book.font-family-1 { 91 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 92 | } 93 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal { 94 | color: #704214; 95 | } 96 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal a { 97 | color: inherit; 98 | } 99 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, 100 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2, 101 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h3, 102 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h4, 103 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h5, 104 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { 105 | color: inherit; 106 | } 107 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, 108 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2 { 109 | border-color: inherit; 110 | } 111 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { 112 | color: inherit; 113 | } 114 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal hr { 115 | background-color: inherit; 116 | } 117 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal blockquote { 118 | border-color: #c4b29f; 119 | opacity: 0.9; 120 | } 121 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, 122 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { 123 | background: #fdf6e3; 124 | color: #657b83; 125 | border-color: #f8df9c; 126 | } 127 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal .highlight { 128 | background-color: inherit; 129 | } 130 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table th, 131 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table td { 132 | border-color: #f5d06c; 133 | } 134 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr { 135 | color: inherit; 136 | background-color: #fdf6e3; 137 | border-color: #444444; 138 | } 139 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { 140 | background-color: #fbeecb; 141 | } 142 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal { 143 | color: #bdcadb; 144 | } 145 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal a { 146 | color: #3eb1d0; 147 | } 148 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, 149 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2, 150 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h3, 151 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h4, 152 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h5, 153 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { 154 | color: #fffffa; 155 | } 156 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, 157 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2 { 158 | border-color: #373b4e; 159 | } 160 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { 161 | color: #373b4e; 162 | } 163 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal hr { 164 | background-color: #373b4e; 165 | } 166 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal blockquote { 167 | border-color: #373b4e; 168 | } 169 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, 170 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { 171 | color: #9dbed8; 172 | background: #2d3143; 173 | border-color: #2d3143; 174 | } 175 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal .highlight { 176 | background-color: #282a39; 177 | } 178 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table th, 179 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table td { 180 | border-color: #3b3f54; 181 | } 182 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr { 183 | color: #b6c2d2; 184 | background-color: #2d3143; 185 | border-color: #3b3f54; 186 | } 187 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { 188 | background-color: #35394b; 189 | } 190 | .book.color-theme-1 .book-header { 191 | color: #afa790; 192 | background: transparent; 193 | } 194 | .book.color-theme-1 .book-header .btn { 195 | color: #afa790; 196 | } 197 | .book.color-theme-1 .book-header .btn:hover { 198 | color: #73553c; 199 | background: none; 200 | } 201 | .book.color-theme-1 .book-header h1 { 202 | color: #704214; 203 | } 204 | .book.color-theme-2 .book-header { 205 | color: #7e888b; 206 | background: transparent; 207 | } 208 | .book.color-theme-2 .book-header .btn { 209 | color: #3b3f54; 210 | } 211 | .book.color-theme-2 .book-header .btn:hover { 212 | color: #fffff5; 213 | background: none; 214 | } 215 | .book.color-theme-2 .book-header h1 { 216 | color: #bdcadb; 217 | } 218 | .book.color-theme-1 .book-body .navigation { 219 | color: #afa790; 220 | } 221 | .book.color-theme-1 .book-body .navigation:hover { 222 | color: #73553c; 223 | } 224 | .book.color-theme-2 .book-body .navigation { 225 | color: #383f52; 226 | } 227 | .book.color-theme-2 .book-body .navigation:hover { 228 | color: #fffff5; 229 | } 230 | /* 231 | * Theme 1 232 | */ 233 | .book.color-theme-1 .book-summary { 234 | color: #afa790; 235 | background: #111111; 236 | border-right: 1px solid rgba(0, 0, 0, 0.07); 237 | } 238 | .book.color-theme-1 .book-summary .book-search { 239 | background: transparent; 240 | } 241 | .book.color-theme-1 .book-summary .book-search input, 242 | .book.color-theme-1 .book-summary .book-search input:focus { 243 | border: 1px solid transparent; 244 | } 245 | .book.color-theme-1 .book-summary ul.summary li.divider { 246 | background: #7e888b; 247 | box-shadow: none; 248 | } 249 | .book.color-theme-1 .book-summary ul.summary li i.fa-check { 250 | color: #33cc33; 251 | } 252 | .book.color-theme-1 .book-summary ul.summary li.done > a { 253 | color: #877f6a; 254 | } 255 | .book.color-theme-1 .book-summary ul.summary li a, 256 | .book.color-theme-1 .book-summary ul.summary li span { 257 | color: #877f6a; 258 | background: transparent; 259 | font-weight: normal; 260 | } 261 | .book.color-theme-1 .book-summary ul.summary li.active > a, 262 | .book.color-theme-1 .book-summary ul.summary li a:hover { 263 | color: #704214; 264 | background: transparent; 265 | font-weight: normal; 266 | } 267 | /* 268 | * Theme 2 269 | */ 270 | .book.color-theme-2 .book-summary { 271 | color: #bcc1d2; 272 | background: #2d3143; 273 | border-right: none; 274 | } 275 | .book.color-theme-2 .book-summary .book-search { 276 | background: transparent; 277 | } 278 | .book.color-theme-2 .book-summary .book-search input, 279 | .book.color-theme-2 .book-summary .book-search input:focus { 280 | border: 1px solid transparent; 281 | } 282 | .book.color-theme-2 .book-summary ul.summary li.divider { 283 | background: #272a3a; 284 | box-shadow: none; 285 | } 286 | .book.color-theme-2 .book-summary ul.summary li i.fa-check { 287 | color: #33cc33; 288 | } 289 | .book.color-theme-2 .book-summary ul.summary li.done > a { 290 | color: #62687f; 291 | } 292 | .book.color-theme-2 .book-summary ul.summary li a, 293 | .book.color-theme-2 .book-summary ul.summary li span { 294 | color: #c1c6d7; 295 | background: transparent; 296 | font-weight: 600; 297 | } 298 | .book.color-theme-2 .book-summary ul.summary li.active > a, 299 | .book.color-theme-2 .book-summary ul.summary li a:hover { 300 | color: #f4f4f5; 301 | background: #252737; 302 | font-weight: 600; 303 | } 304 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-search.css: -------------------------------------------------------------------------------- 1 | .book .book-summary .book-search { 2 | padding: 6px; 3 | background: transparent; 4 | position: absolute; 5 | top: -50px; 6 | left: 0px; 7 | right: 0px; 8 | transition: top 0.5s ease; 9 | } 10 | .book .book-summary .book-search input, 11 | .book .book-summary .book-search input:focus, 12 | .book .book-summary .book-search input:hover { 13 | width: 100%; 14 | background: transparent; 15 | border: 1px solid #ccc; 16 | box-shadow: none; 17 | outline: none; 18 | line-height: 22px; 19 | padding: 7px 4px; 20 | color: inherit; 21 | box-sizing: border-box; 22 | } 23 | .book.with-search .book-summary .book-search { 24 | top: 0px; 25 | } 26 | .book.with-search .book-summary ul.summary { 27 | top: 50px; 28 | } 29 | .with-search .summary li[data-level] a[href*=".html#"] { 30 | display: none; 31 | } 32 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-table.css: -------------------------------------------------------------------------------- 1 | .book .book-body .page-wrapper .page-inner section.normal table{display:table;width:100%;border-collapse:collapse;border-spacing:0;overflow:auto}.book .book-body .page-wrapper .page-inner section.normal table td,.book .book-body .page-wrapper .page-inner section.normal table th{padding:6px 13px;border:1px solid #ddd}.book .book-body .page-wrapper .page-inner section.normal table tr{background-color:#fff;border-top:1px solid #ccc}.book .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n){background-color:#f8f8f8}.book .book-body .page-wrapper .page-inner section.normal table th{font-weight:700} 2 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/js/clipboard.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * clipboard.js v2.0.4 3 | * https://zenorocha.github.io/clipboard.js 4 | * 5 | * Licensed MIT © Zeno Rocha 6 | */ 7 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;no;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;n indicates arrow keys):', 82 | '/: navigate to previous/next page', 83 | 's: Toggle sidebar']; 84 | if (config.search !== false) info.push('f: Toggle search input ' + 85 | '(use //Enter in the search input to navigate through search matches; ' + 86 | 'press Esc to cancel search)'); 87 | if (config.info !== false) gitbook.toolbar.createButton({ 88 | icon: 'fa fa-info', 89 | label: 'Information about the toolbar', 90 | position: 'left', 91 | onClick: function(e) { 92 | e.preventDefault(); 93 | window.alert(info.join('\n\n')); 94 | } 95 | }); 96 | 97 | // highlight the current section in TOC 98 | var href = window.location.pathname; 99 | href = href.substr(href.lastIndexOf('/') + 1); 100 | // accentuated characters need to be decoded (#819) 101 | href = decodeURIComponent(href); 102 | if (href === '') href = 'index.html'; 103 | var li = $('a[href^="' + href + location.hash + '"]').parent('li.chapter').first(); 104 | var summary = $('ul.summary'), chaps = summary.find('li.chapter'); 105 | if (li.length === 0) li = chaps.first(); 106 | li.addClass('active'); 107 | chaps.on('click', function(e) { 108 | chaps.removeClass('active'); 109 | $(this).addClass('active'); 110 | gs.set('tocScrollTop', summary.scrollTop()); 111 | }); 112 | 113 | var toc = config.toc; 114 | // collapse TOC items that are not for the current chapter 115 | if (toc && toc.collapse) (function() { 116 | var type = toc.collapse; 117 | if (type === 'none') return; 118 | if (type !== 'section' && type !== 'subsection') return; 119 | // sections under chapters 120 | var toc_sub = summary.children('li[data-level]').children('ul'); 121 | if (type === 'section') { 122 | toc_sub.hide() 123 | .parent().has(li).children('ul').show(); 124 | } else { 125 | toc_sub.children('li').children('ul').hide() 126 | .parent().has(li).children('ul').show(); 127 | } 128 | li.children('ul').show(); 129 | var toc_sub2 = toc_sub.children('li'); 130 | if (type === 'section') toc_sub2.children('ul').hide(); 131 | summary.children('li[data-level]').find('a') 132 | .on('click.bookdown', function(e) { 133 | if (href === $(this).attr('href').replace(/#.*/, '')) 134 | $(this).parent('li').children('ul').toggle(); 135 | }); 136 | })(); 137 | 138 | // add tooltips to the 's that are truncated 139 | $('a').each(function(i, el) { 140 | if (el.offsetWidth >= el.scrollWidth) return; 141 | if (typeof el.title === 'undefined') return; 142 | el.title = el.text; 143 | }); 144 | 145 | // restore TOC scroll position 146 | var pos = gs.get('tocScrollTop'); 147 | if (typeof pos !== 'undefined') summary.scrollTop(pos); 148 | 149 | // highlight the TOC item that has same text as the heading in view as scrolling 150 | if (toc && toc.scroll_highlight !== false && li.length > 0) (function() { 151 | // scroll the current TOC item into viewport 152 | var ht = $(window).height(), rect = li[0].getBoundingClientRect(); 153 | if (rect.top >= ht || rect.top <= 0 || rect.bottom <= 0) { 154 | summary.scrollTop(li[0].offsetTop); 155 | } 156 | // current chapter TOC items 157 | var items = $('a[href^="' + href + '"]').parent('li.chapter'), 158 | m = items.length; 159 | if (m === 0) { 160 | items = summary.find('li.chapter'); 161 | m = items.length; 162 | } 163 | if (m === 0) return; 164 | // all section titles on current page 165 | var hs = bookInner.find('.page-inner').find('h1,h2,h3'), n = hs.length, 166 | ts = hs.map(function(i, el) { return $(el).text(); }); 167 | if (n === 0) return; 168 | var scrollHandler = function(e) { 169 | var ht = $(window).height(); 170 | clearTimeout($.data(this, 'scrollTimer')); 171 | $.data(this, 'scrollTimer', setTimeout(function() { 172 | // find the first visible title in the viewport 173 | for (var i = 0; i < n; i++) { 174 | var rect = hs[i].getBoundingClientRect(); 175 | if (rect.top >= 0 && rect.bottom <= ht) break; 176 | } 177 | if (i === n) return; 178 | items.removeClass('active'); 179 | for (var j = 0; j < m; j++) { 180 | if (items.eq(j).children('a').first().text() === ts[i]) break; 181 | } 182 | if (j === m) j = 0; // highlight the chapter title 183 | // search bottom-up for a visible TOC item to highlight; if an item is 184 | // hidden, we check if its parent is visible, and so on 185 | while (j > 0 && items.eq(j).is(':hidden')) j--; 186 | items.eq(j).addClass('active'); 187 | }, 250)); 188 | }; 189 | bookInner.on('scroll.bookdown', scrollHandler); 190 | bookBody.on('scroll.bookdown', scrollHandler); 191 | })(); 192 | 193 | // do not refresh the page if the TOC item points to the current page 194 | $('a[href="' + href + '"]').parent('li.chapter').children('a') 195 | .on('click', function(e) { 196 | bookInner.scrollTop(0); 197 | bookBody.scrollTop(0); 198 | return false; 199 | }); 200 | 201 | var toolbar = config.toolbar; 202 | if (!toolbar || toolbar.position !== 'static') { 203 | var bookHeader = $('.book-header'); 204 | bookBody.addClass('fixed'); 205 | bookHeader.addClass('fixed') 206 | .css('background-color', bookBody.css('background-color')) 207 | .on('click.bookdown', function(e) { 208 | // the theme may have changed after user clicks the theme button 209 | bookHeader.css('background-color', bookBody.css('background-color')); 210 | }); 211 | } 212 | 213 | }); 214 | 215 | gitbook.events.bind("page.change", function(e) { 216 | // store TOC scroll position 217 | var summary = $('ul.summary'); 218 | gs.set('tocScrollTop', summary.scrollTop()); 219 | }); 220 | 221 | var bookBody = $('.book-body'), bookInner = bookBody.find('.body-inner'); 222 | var chapterTitle = function() { 223 | return bookInner.find('.page-inner').find('h1,h2').first().text(); 224 | }; 225 | var saveScrollPos = function(e) { 226 | // save scroll position before page is reloaded 227 | gs.set('bodyScrollTop', { 228 | body: bookBody.scrollTop(), 229 | inner: bookInner.scrollTop(), 230 | focused: document.hasFocus(), 231 | title: chapterTitle() 232 | }); 233 | }; 234 | $(document).on('servr:reload', saveScrollPos); 235 | 236 | // check if the page is loaded in an iframe (e.g. the RStudio preview window) 237 | var inIFrame = function() { 238 | var inIframe = true; 239 | try { inIframe = window.self !== window.top; } catch (e) {} 240 | return inIframe; 241 | }; 242 | if (inIFrame()) { 243 | $(window).on('blur unload', saveScrollPos); 244 | } 245 | 246 | $(function(e) { 247 | var pos = gs.get('bodyScrollTop'); 248 | if (pos) { 249 | if (pos.title === chapterTitle()) { 250 | if (pos.body !== 0) bookBody.scrollTop(pos.body); 251 | if (pos.inner !== 0) bookInner.scrollTop(pos.inner); 252 | } 253 | } 254 | if ((pos && pos.focused) || !inIFrame()) bookInner.find('.page-wrapper').focus(); 255 | // clear book body scroll position 256 | gs.remove('bodyScrollTop'); 257 | }); 258 | 259 | }); 260 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/js/plugin-clipboard.js: -------------------------------------------------------------------------------- 1 | gitbook.require(["gitbook", "jQuery"], function(gitbook, $) { 2 | 3 | var copyButton = ''; 4 | var clipboard; 5 | 6 | gitbook.events.bind("page.change", function() { 7 | 8 | if (!ClipboardJS.isSupported()) return; 9 | 10 | // the page.change event is thrown twice: before and after the page changes 11 | if (clipboard) { 12 | // clipboard is already defined 13 | // we can deduct that we are before page changes 14 | clipboard.destroy(); // destroy the previous events listeners 15 | clipboard = undefined; // reset the clipboard object 16 | return; 17 | } 18 | 19 | $(copyButton).prependTo("div.sourceCode"); 20 | 21 | clipboard = new ClipboardJS(".copy-to-clipboard-button", { 22 | text: function(trigger) { 23 | return trigger.parentNode.textContent; 24 | } 25 | }); 26 | 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/js/plugin-fontsettings.js: -------------------------------------------------------------------------------- 1 | gitbook.require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { 2 | var fontState; 3 | 4 | var THEMES = { 5 | "white": 0, 6 | "sepia": 1, 7 | "night": 2 8 | }; 9 | 10 | var FAMILY = { 11 | "serif": 0, 12 | "sans": 1 13 | }; 14 | 15 | // Save current font settings 16 | function saveFontSettings() { 17 | gitbook.storage.set("fontState", fontState); 18 | update(); 19 | } 20 | 21 | // Increase font size 22 | function enlargeFontSize(e) { 23 | e.preventDefault(); 24 | if (fontState.size >= 4) return; 25 | 26 | fontState.size++; 27 | saveFontSettings(); 28 | }; 29 | 30 | // Decrease font size 31 | function reduceFontSize(e) { 32 | e.preventDefault(); 33 | if (fontState.size <= 0) return; 34 | 35 | fontState.size--; 36 | saveFontSettings(); 37 | }; 38 | 39 | // Change font family 40 | function changeFontFamily(index, e) { 41 | e.preventDefault(); 42 | 43 | fontState.family = index; 44 | saveFontSettings(); 45 | }; 46 | 47 | // Change type of color 48 | function changeColorTheme(index, e) { 49 | e.preventDefault(); 50 | 51 | var $book = $(".book"); 52 | 53 | if (fontState.theme !== 0) 54 | $book.removeClass("color-theme-"+fontState.theme); 55 | 56 | fontState.theme = index; 57 | if (fontState.theme !== 0) 58 | $book.addClass("color-theme-"+fontState.theme); 59 | 60 | saveFontSettings(); 61 | }; 62 | 63 | function update() { 64 | var $book = gitbook.state.$book; 65 | 66 | $(".font-settings .font-family-list li").removeClass("active"); 67 | $(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")").addClass("active"); 68 | 69 | $book[0].className = $book[0].className.replace(/\bfont-\S+/g, ''); 70 | $book.addClass("font-size-"+fontState.size); 71 | $book.addClass("font-family-"+fontState.family); 72 | 73 | if(fontState.theme !== 0) { 74 | $book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, ''); 75 | $book.addClass("color-theme-"+fontState.theme); 76 | } 77 | }; 78 | 79 | function init(config) { 80 | var $bookBody, $book; 81 | 82 | //Find DOM elements. 83 | $book = gitbook.state.$book; 84 | $bookBody = $book.find(".book-body"); 85 | 86 | // Instantiate font state object 87 | fontState = gitbook.storage.get("fontState", { 88 | size: config.size || 2, 89 | family: FAMILY[config.family || "sans"], 90 | theme: THEMES[config.theme || "white"] 91 | }); 92 | 93 | update(); 94 | }; 95 | 96 | 97 | gitbook.events.bind("start", function(e, config) { 98 | var opts = config.fontsettings; 99 | if (!opts) return; 100 | 101 | // Create buttons in toolbar 102 | gitbook.toolbar.createButton({ 103 | icon: 'fa fa-font', 104 | label: 'Font Settings', 105 | className: 'font-settings', 106 | dropdown: [ 107 | [ 108 | { 109 | text: 'A', 110 | className: 'font-reduce', 111 | onClick: reduceFontSize 112 | }, 113 | { 114 | text: 'A', 115 | className: 'font-enlarge', 116 | onClick: enlargeFontSize 117 | } 118 | ], 119 | [ 120 | { 121 | text: 'Serif', 122 | onClick: _.partial(changeFontFamily, 0) 123 | }, 124 | { 125 | text: 'Sans', 126 | onClick: _.partial(changeFontFamily, 1) 127 | } 128 | ], 129 | [ 130 | { 131 | text: 'White', 132 | onClick: _.partial(changeColorTheme, 0) 133 | }, 134 | { 135 | text: 'Sepia', 136 | onClick: _.partial(changeColorTheme, 1) 137 | }, 138 | { 139 | text: 'Night', 140 | onClick: _.partial(changeColorTheme, 2) 141 | } 142 | ] 143 | ] 144 | }); 145 | 146 | 147 | // Init current settings 148 | init(opts); 149 | }); 150 | }); 151 | 152 | 153 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/js/plugin-search.js: -------------------------------------------------------------------------------- 1 | gitbook.require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { 2 | var index = null; 3 | var $searchInput, $searchLabel, $searchForm; 4 | var $highlighted = [], hi, hiOpts = { className: 'search-highlight' }; 5 | var collapse = false, toc_visible = []; 6 | 7 | // Use a specific index 8 | function loadIndex(data) { 9 | // [Yihui] In bookdown, I use a character matrix to store the chapter 10 | // content, and the index is dynamically built on the client side. 11 | // Gitbook prebuilds the index data instead: https://github.com/GitbookIO/plugin-search 12 | // We can certainly do that via R packages V8 and jsonlite, but let's 13 | // see how slow it really is before improving it. On the other hand, 14 | // lunr cannot handle non-English text very well, e.g. the default 15 | // tokenizer cannot deal with Chinese text, so we may want to replace 16 | // lunr with a dumb simple text matching approach. 17 | index = lunr(function () { 18 | this.ref('url'); 19 | this.field('title', { boost: 10 }); 20 | this.field('body'); 21 | }); 22 | data.map(function(item) { 23 | index.add({ 24 | url: item[0], 25 | title: item[1], 26 | body: item[2] 27 | }); 28 | }); 29 | } 30 | 31 | // Fetch the search index 32 | function fetchIndex() { 33 | return $.getJSON(gitbook.state.basePath+"/search_index.json") 34 | .then(loadIndex); // [Yihui] we need to use this object later 35 | } 36 | 37 | // Search for a term and return results 38 | function search(q) { 39 | if (!index) return; 40 | 41 | var results = _.chain(index.search(q)) 42 | .map(function(result) { 43 | var parts = result.ref.split("#"); 44 | return { 45 | path: parts[0], 46 | hash: parts[1] 47 | }; 48 | }) 49 | .value(); 50 | 51 | // [Yihui] Highlight the search keyword on current page 52 | $highlighted = results.length === 0 ? [] : $('.page-inner') 53 | .unhighlight(hiOpts).highlight(q, hiOpts).find('span.search-highlight'); 54 | scrollToHighlighted(0); 55 | 56 | return results; 57 | } 58 | 59 | // [Yihui] Scroll the chapter body to the i-th highlighted string 60 | function scrollToHighlighted(d) { 61 | var n = $highlighted.length; 62 | hi = hi === undefined ? 0 : hi + d; 63 | // navignate to the previous/next page in the search results if reached the top/bottom 64 | var b = hi < 0; 65 | if (d !== 0 && (b || hi >= n)) { 66 | var path = currentPath(), n2 = toc_visible.length; 67 | if (n2 === 0) return; 68 | for (var i = b ? 0 : n2; (b && i < n2) || (!b && i >= 0); i += b ? 1 : -1) { 69 | if (toc_visible.eq(i).data('path') === path) break; 70 | } 71 | i += b ? -1 : 1; 72 | if (i < 0) i = n2 - 1; 73 | if (i >= n2) i = 0; 74 | var lnk = toc_visible.eq(i).find('a[href$=".html"]'); 75 | if (lnk.length) lnk[0].click(); 76 | return; 77 | } 78 | if (n === 0) return; 79 | var $p = $highlighted.eq(hi); 80 | $p[0].scrollIntoView(); 81 | $highlighted.css('background-color', ''); 82 | // an orange background color on the current item and removed later 83 | $p.css('background-color', 'orange'); 84 | setTimeout(function() { 85 | $p.css('background-color', ''); 86 | }, 2000); 87 | } 88 | 89 | function currentPath() { 90 | var href = window.location.pathname; 91 | href = href.substr(href.lastIndexOf('/') + 1); 92 | return href === '' ? 'index.html' : href; 93 | } 94 | 95 | // Create search form 96 | function createForm(value) { 97 | if ($searchForm) $searchForm.remove(); 98 | if ($searchLabel) $searchLabel.remove(); 99 | if ($searchInput) $searchInput.remove(); 100 | 101 | $searchForm = $('
    ', { 102 | 'class': 'book-search', 103 | 'role': 'search' 104 | }); 105 | 106 | $searchLabel = $('
    135 | 136 |
    137 | 207 |
    208 | 209 |
    210 |
    211 | 216 | 217 |
    218 |
    219 | 220 |
    221 |
    222 |

    Process Analysis

    223 | 224 |
    225 |
    226 | 227 |
    228 |
    229 |
    230 | 231 | 232 |
    233 |
    234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 281 | 282 | 283 | 284 | 285 | -------------------------------------------------------------------------------- /docs/reference-keys.txt: -------------------------------------------------------------------------------- 1 | preface 2 | intro 3 | load-count-matrix-from-cellranger 4 | quality-control-by-visualization 5 | cell-level-filtering 6 | merge-individuals 7 | normalize-scale-find-variable-genes-and-dimension-reduciton 8 | find-doublet-using-scrublet 9 | description 10 | input-data 11 | process 12 | output 13 | seurat-qc-cell-level-filtering 14 | description-1 15 | load-seurat-object 16 | add-other-meta-info 17 | violin-plots-to-check 18 | scrublet-doublet-validation 19 | description-2 20 | load-seurat-object-1 21 | validate-the-doublet-prediction 22 | calculate-factions-of-doublet-per-cluster 23 | explore-the-component-clusters-for-doublets-by-deg 24 | explore-the-component-clusters-for-doublets-by-canonical-gene 25 | seurat-individual-batch-effect-exploration 26 | descripiton 27 | load-seurat-object-2 28 | explore-individual-distribution-by-dimplot 29 | calculate-individual-distribution-per-cluster-with-different-resolution 30 | assign-gene-signature 31 | description-3 32 | load-seurat-object-3 33 | load-gene-lists-here-using-the-layer-enriched-genes-as-examples 34 | calcuate-gene-signature-per-gene-list 35 | explore-the-gene-signature-by-featureplot-and-vlnplot 36 | stacked-vlnplot-for-given-features-sets 37 | descripiton-1 38 | load-seurat-object-4 39 | source-stacked-vlnplot-funciton 40 | stacked-vlnplot-given-gene-set 41 | -------------------------------------------------------------------------------- /docs/search_index.json: -------------------------------------------------------------------------------- 1 | [["index.html", "Single Cell Multi-Omics Data Analysis Chapter 1 Preface", " Single Cell Multi-Omics Data Analysis Yuting Liu 2021-06-06 Chapter 1 Preface This book is a collect for pre-processing and visualizing scripts for single cell multi-omics data. The data is down-sampled from a real dataset. "],["process-analysis.html", "Process Analysis", " Process Analysis "],["intro.html", "Chapter 2 Seurat Pre-process 2.1 Load count matrix from CellRanger 2.2 Cell-level filtering 2.3 Merge individuals 2.4 Normalize, scale, find variable genes and dimension reduciton", " Chapter 2 Seurat Pre-process 2.1 Load count matrix from CellRanger for one experiment pre <- Read10X(data.dir = 'cellranger-res/Pre-B/outs/filtered_feature_bc_matrix/') pre <- CreateSeuratObject(counts = pre, project = '11002C', min.cells = 3) for multiple experiments # step1 list sample directories ---------------------------------------------- dir.ls <- list.dirs(path = 'cellranger-count/', full.names = T, recursive = F) dir.ls <- dir.ls[c(2:5)] dir.ls %<>% map( ~ paste0(.x, "/outs/filtered_feature_bc_matrix")) names(dir.ls) <- c('68A', '68B', '84B', '84C') # step2 check whether dir exist ------------------------------------------- dir.ls %>% map( ~ dir.exists(.x)) # step3 create seurat per samples ----------------------------------------- obj.ls <- dir.ls %>% map( ~ Read10X(.x)) %>% map( ~ CreateSeuratObject(.x, min.cells = 3)) 2.1.1 Quality control by visualization V1_Seurat_QC-CellLevelFiltering.R 2.2 Cell-level filtering # filtering by nCount and nFeatures per individual filterCell <- function(combined){ # calculate the quantile range count.feature.ls <- combined@meta.data[, c("nCount_RNA", "nFeature_RNA")] count.feature.ls %<>% map(log10) %>% map(~c(10^(mean(.x) + 3*sd(.x)), 10^(mean(.x) - 3*sd(.x)))) # filter cells combined <- subset(combined, subset = nFeature_RNA > 200 & nFeature_RNA < count.feature.ls[[2]][1] & nCount_RNA < count.feature.ls[[1]][1]) return(combined) } obj.ls %<>% map(filterCell) 2.3 Merge individuals combined <- merge(x = obj.ls[[1]], y = obj.ls[2:4], add.cell.ids = names(dir.ls)) 2.4 Normalize, scale, find variable genes and dimension reduciton Choose the number of PC SCT combined %<>% SCTransform(return.only.var.genes = FALSE) %>% RunPCA(features = VariableFeatures(object = .)) %>% FindNeighbors(dims = 1:40) %>% FindClusters(resolution = c(0.5, 0.6, 0.8, 1, 1.2, 1.5, 1.8,2,2.5,3)) %>% RunUMAP(dims = 1:40) %>% RunTSNE(dims = 1:40) standard process combined %<>% NormalizeData() %>% FindVariableFeatures(selection.method = 'vst', nfeatures = 2000) %>% ScaleData(features = rownames(.)) %>% RunPCA(features = VariableFeatures(object = .)) %>% FindNeighbors(dims = 1:30) %>% FindClusters(resolution = c(0.5, 0.6, 0.8, 1, 1.2, 1.5, 1.8,2,2.5,3)) %>% RunUMAP(dims = 1:30) %>% RunTSNE(dims = 1:30) "],["find-doublet-using-scrublet.html", "Chapter 3 Find Doublet using Scrublet 3.1 description 3.2 input data 3.3 process 3.4 output", " Chapter 3 Find Doublet using Scrublet 3.1 description Scoring and identify doublet using scrublet per samples 3.2 input data filtered count matrix by cellRanger per samples 3.3 process running scrublet per samples N2-DoubletIdentify-Scurblet-Process.py -i Pre-A -r 0.02 expected doublet ratio is calculated by ~ 0.8% per 1k cell other parameters by default 3.4 output doublet scoring and identificaiton data/scrublet/*DoubletScores.csv data/scrublet/*PredictedDoublets.csv validation plots data/scrublet/pdf "],["visualize.html", "Visualize", " Visualize "],["seurat-qc-cell-level-filtering.html", "Chapter 4 Seurat QC Cell-level Filtering 4.1 Description 4.2 Load seurat object 4.3 Add other meta info 4.4 Violin plots to check", " Chapter 4 Seurat QC Cell-level Filtering 4.1 Description Basic quality control for snRNA-seq: check the distribution of number of UMIs per cell should above 500 number of genes detected per cell number of genes detected per UMI check the complexity. outlier cells might be cells have less complex RNA species like red blood cells. expected higher than 0.8 mitochondrial ratio dead or dying cells will cause large amount of mitochondrial contamination 4.2 Load seurat object combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 4.3 Add other meta info fraction of reads mapping to mitochondrial gene # for macaque, not all genes start with MT is mitochondrion genes mt.gene <- c("MTARC2","MTFR1L","MTERF1","MTFR2","MTRF1L","MTRES1", "MTO1","MTCH1","MTFMT","MTFR1","MTERF3","MTERF2","MTPAP", "MTERF4","MTCH2",'MTIF2',"MTG2","MTIF3","MTRF1","MTCL1") combined[["percent.mt"]] <- PercentageFeatureSet(combined, features = mt.gene ) number of genes detected per UMI combined$log10GenesPerUMI <- log10(combined$nFeature_RNA) / log10(combined$nCount_RNA) 4.4 Violin plots to check get the meta data df <- as.data.table(combined@meta.data) sel <- c("orig.ident", "nCount_RNA", "nFeature_RNA", "percent.mt", "log10GenesPerUMI") df <- df[, sel, with = FALSE] df[1:3, ] ## orig.ident nCount_RNA nFeature_RNA percent.mt log10GenesPerUMI ## 1: SeuratProject 2740 1705 0.10795250 0.9400695 ## 2: SeuratProject 3140 1687 0.09593860 0.9228424 ## 3: SeuratProject 2539 1456 0.03738318 0.9290675 define plotting function fontsize <- 10 linesize <- 0.35 gp.ls <- df[, 2:5] %>% imap( ~ { # define lable fun give.n <- function(x) { return(c(y = median(x) + max(x) / 10, label = round(median(x), 2))) } # assign colors col.ls <- setNames( c('lightpink2', 'lightblue2', 'lightgreen', 'coral1'), c("nCount_RNA", "nFeature_RNA", "percent.mt", "log10GenesPerUMI") ) ggplot(data = df, aes(x = orig.ident, y = .x)) + geom_violin(trim = FALSE, fill = col.ls[.y]) + ggtitle(label = .y) + ylab(label = .y) + theme_bw() + theme( panel.grid.major = element_blank(), panel.grid.minor = element_blank(), strip.background = element_blank(), panel.border = element_blank() ) + theme( axis.text = element_text(size = fontsize), axis.line = element_line(colour = "black", size = linesize), axis.ticks = element_line(size = linesize), axis.title.x = element_blank(), axis.ticks.length = unit(.05, "cm"), plot.title = element_text(size = fontsize + 2, hjust = 0.5), legend.position = 'none' ) + stat_summary(fun = median, geom = "point", col = "black") + # Add points to plot stat_summary(fun.data = give.n, geom = "text", col = "black") }) grid.arrange(gp.ls[[1]], gp.ls[[2]], gp.ls[[3]], gp.ls[[4]], ncol = 2) "],["scrublet-doublet-validation.html", "Chapter 5 Scrublet Doublet Validation 5.1 Description 5.2 Load seurat object 5.3 Validate the doublet prediction 5.4 Calculate factions of doublet per cluster 5.5 Explore the component clusters for doublets by DEG 5.6 Explore the component clusters for doublets by canonical gene", " Chapter 5 Scrublet Doublet Validation 5.1 Description check the doublet prediction from scrublet by dimension reduction plot nUMI distribution judge the component for doublet cells by DEG heatmap canonical gene expression 5.2 Load seurat object combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) Idents(combined) <- "cluster" 5.3 Validate the doublet prediction # check whether the double cells cluster together FeaturePlot(combined, features = "DoubletScores", pt.size = 0.01) DimPlot( combined, group.by = "DoubletPrediction", pt.size = 0.01, cols = c("red", "azure3") ) # check the nUMI for doublet and singlet VlnPlot(combined, features = "nCount_RNA", pt.size = 0, group.by = "DoubletPrediction") + NoLegend() 5.4 Calculate factions of doublet per cluster df <- data.table(combined@meta.data) sel.meta <- c("DoubletPrediction", "cluster", "Individual") df <- df[, sel.meta, with = FALSE] df[, 2:3] %>% map( ~ { freq1 <- df[, .N, keyby = .(.x, DoubletPrediction)] freq1[, total := sum(N), by = .(.x)] freq1[, ratio := N / total] linesize = .35 fontsize = 8 ggplot(freq1, aes(fill=DoubletPrediction, y=ratio, x= .x)) + geom_bar(position="stack", stat="identity")+ scale_fill_manual(values = c("Doublet" = 'red', "Singlet" = "grey")) + xlab('Clsuter') + scale_y_continuous(breaks = seq(0,1,0.1), expand = c(0,0), name = 'Percentage')+ theme_bw()+ theme( panel.grid.major.x = element_blank(), panel.grid.major.y = element_blank(), panel.grid.minor = element_blank(), strip.background = element_blank(),panel.border = element_rect(size = linesize), axis.ticks = element_blank(), axis.text.x = element_text(size = 5)) }) ## $cluster ## ## $Individual 5.5 Explore the component clusters for doublets by DEG get the DEG for inferred source clusters. Here, for C33, InCGE and InMGE # find DEG cluster.markers <- FindMarkers(combined, ident.1 = c("InMGE"), ident.2 = "InCGE", min.pct = 0.25) # subset cells of interest sel.idents <- c("InMGE", "InCGE", "D33") combined.small <- subset(combined, cells = WhichCells(combined, idents = sel.idents)) # check the expression for top DEG #sel.cells <- WhichCells(combined.small, idents = sel.idents, downsample = 355) # for large dataset DoHeatmap(combined.small, features = rownames(cluster.markers)[1:40], raster = F) ## Warning in DoHeatmap(combined.small, features = rownames(cluster.markers)[1:40], : The following ## features were omitted as they were not found in the scale.data slot for the SCT assay: FNBP1 5.6 Explore the component clusters for doublets by canonical gene sel.feature <- c("NXPH1", "PAM", "LHX6", "NR2F2", "ADARB2", "PROX1") FeaturePlot(combined, features = sel.feature, pt.size = 0.01, ncol = 3) VlnPlot(combined.small, features = sel.feature, pt.size = 0, ncol = 3, idents = sel.idents) "],["seurat-individual-batch-effect-exploration.html", "Chapter 6 Seurat Individual Batch Effect Exploration 6.1 Descripiton 6.2 Load seurat object 6.3 Explore individual distribution by Dimplot 6.4 Calculate individual distribution per cluster with different resolution", " Chapter 6 Seurat Individual Batch Effect Exploration 6.1 Descripiton Explore the individual batch effect by Dimplot split by individual Fractions of individuals per cluster 6.2 Load seurat object combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 6.3 Explore individual distribution by Dimplot Idents(object = combined) <- 'Individual' DimPlot(object = combined, reduction = "umap", label = T) DimPlot(object = combined, reduction = "tsne", label = T) 6.4 Calculate individual distribution per cluster with different resolution df <- data.table(combined@meta.data) sel.meta <- c("Individual", str_c('SCT_snn_res.', c(1, 1.5, 1.8))) df <- df[, sel.meta, with = FALSE] df[, 2:4] %>% imap(~ { freq1 <- df[, .N, keyby = .(.x, Individual)] freq1[, total := sum(N), by = .(.x)] freq1[, ratio := N / total] linesize = .35 fontsize = 8 ggplot(freq1, aes(fill = Individual, y = ratio, x = .x)) + geom_bar(position = "stack", stat = "identity") + scale_fill_brewer(palette = "Dark2") + xlab('Clsuter') + ggtitle(.y) + scale_y_continuous(breaks = seq(0, 1, 0.1), expand = c(0, 0), name = 'Percentage') + theme_bw() + theme( panel.grid.major.x = element_blank(), panel.grid.major.y = element_blank(), panel.grid.minor = element_blank(), strip.background = element_blank(), panel.border = element_rect(size = linesize), axis.ticks = element_blank(), axis.text.x = element_text(size = 5) ) + coord_flip() }) ## $SCT_snn_res.1 ## ## $SCT_snn_res.1.5 ## ## $SCT_snn_res.1.8 "],["assign-gene-signature.html", "Chapter 7 Assign Gene Signature 7.1 Description 7.2 Load seurat object 7.3 Load gene lists, here using the layer-enriched genes as examples 7.4 Calcuate gene signature per gene list 7.5 Explore the gene signature by FeaturePlot and VlnPlot", " Chapter 7 Assign Gene Signature 7.1 Description Given a gene list, calculate gene signature by averaging gene expresion 7.2 Load seurat object combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) Idents(combined) <- "cluster" 7.3 Load gene lists, here using the layer-enriched genes as examples f.ls <- list.files( "data/GeneList/", pattern = "FDR001.upDEG.csv$", full.names = T, recursive = T ) names(f.ls) <- f.ls %>% map(basename) %>% map( ~ str_remove(.x, "vs.*")) layer.ls <- f.ls %>% map( ~ { df <- fread(.x) gn <- df$id[!is.na(df$id)] gn <- gn[which(gn %in% rownames(combined))] return(gn) }) 7.4 Calcuate gene signature per gene list mean.ls <- layer.ls %>% map_dfc(~ colMeans(x = as.matrix(combined@assays$SCT[.x, ]), na.rm = TRUE)) rownames(mean.ls) <- rownames(combined@meta.data) ## Warning: Setting row names on a tibble is deprecated. combined <- AddMetaData(combined, mean.ls, col.name = colnames(mean.ls)) 7.5 Explore the gene signature by FeaturePlot and VlnPlot names(layer.ls) %>% map(~ FeaturePlot(object = combined, features = .x, pt.size = 0.001)) ## [[1]] ## ## [[2]] ## ## [[3]] ## ## [[4]] ## ## [[5]] ## ## [[6]] ## ## [[7]] ## ## [[8]] names(layer.ls) %>% map(~ { VlnPlot(object = combined, features = .x, pt.size = 0) + NoLegend() }) ## [[1]] ## ## [[2]] ## ## [[3]] ## ## [[4]] ## ## [[5]] ## ## [[6]] ## ## [[7]] ## ## [[8]] "],["stacked-vlnplot-for-given-features-sets.html", "Chapter 8 Stacked Vlnplot for Given Features Sets 8.1 Descripiton 8.2 Load seurat object 8.3 Source stacked vlnplot funciton 8.4 Stacked Vlnplot given gene set", " Chapter 8 Stacked Vlnplot for Given Features Sets 8.1 Descripiton Stacked vlnplot for given gene set. Seurat V4 has provided the similar function 8.2 Load seurat object combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 8.3 Source stacked vlnplot funciton source("scripts/visualize/Stacked-Vlnplot.R") 8.4 Stacked Vlnplot given gene set sel.gene <- c("PAX6", "RBFOX1", "GAD1") StackedVlnPlot(combined, sel.gene, pt.size = 0) ## Scale for 'y' is already present. Adding another scale for 'y', which will replace the ## existing scale. ## Scale for 'y' is already present. Adding another scale for 'y', which will replace the ## existing scale. ## Scale for 'y' is already present. Adding another scale for 'y', which will replace the ## existing scale. "]] 2 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | p.caption { 2 | color: #777; 3 | margin-top: 10px; 4 | } 5 | p code { 6 | white-space: inherit; 7 | } 8 | pre { 9 | word-break: normal; 10 | word-wrap: normal; 11 | } 12 | pre code { 13 | white-space: inherit; 14 | } 15 | -------------------------------------------------------------------------------- /docs/visualize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Visualize | Single Cell Multi-Omics Data Analysis 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 |
    135 | 136 |
    137 | 207 |
    208 | 209 |
    210 |
    211 | 216 | 217 |
    218 |
    219 | 220 |
    221 |
    222 |

    Visualize

    223 | 224 |
    225 |
    226 | 227 |
    228 |
    229 |
    230 | 231 | 232 |
    233 |
    234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 281 | 282 | 283 | 284 | 285 | -------------------------------------------------------------------------------- /index.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Single Cell Multi-Omics Data Analysis" 3 | author: "Yuting Liu" 4 | date: "`r Sys.Date()`" 5 | site: bookdown::bookdown_site 6 | output: bookdown::gitbook 7 | documentclass: book 8 | bibliography: [book.bib, packages.bib] 9 | biblio-style: apalike 10 | link-citations: yes 11 | github-repo: rstudio/bookdown-demo 12 | description: "This book is a collection for pre-processing and visualizing scripts for single cell milti-omics data. The data is downsampled from a real dataset." 13 | --- 14 | 15 | # Preface 16 | 17 | This book is a collection for pre-processing and visualizing scripts for single cell multi-omics data. The data is down-sampled from a real dataset. 18 | 19 | 20 | -------------------------------------------------------------------------------- /scRNA-Process.Rmd: -------------------------------------------------------------------------------- 1 | # Process Analysis {.unnumbered} 2 | 3 | 4 | -------------------------------------------------------------------------------- /scRNA-Visualize.Rmd: -------------------------------------------------------------------------------- 1 | # Visualize {.unnumbered} 2 | 3 | 4 | -------------------------------------------------------------------------------- /scripts/process/N1_Seurat_QC-and-PreProcess_snRNA-seq.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Seurat Quality Control and Pre-Process for snRNA-seq" 3 | author: "Yuting Liu" 4 | date: "2021/5/28" 5 | output: 6 | html_document: 7 | toc: true 8 | toc_float: true 9 | --- 10 | 11 | 12 | ```{r setup, include=FALSE} 13 | knitr::opts_chunk$set(echo = TRUE, eval = FALSE) 14 | library(Seurat) 15 | library(tidyverse) 16 | library(magrittr) 17 | ``` 18 | 19 | ```{r klippy, echo=FALSE, include=TRUE} 20 | klippy::klippy(lang = "markdown") 21 | ``` 22 | 23 | ## Load count matrix from CellRanger 24 | 25 | * for one experiment 26 | 27 | ```{r} 28 | pre <- Read10X(data.dir = 'cellranger-res/Pre-B/outs/filtered_feature_bc_matrix/') 29 | pre <- CreateSeuratObject(counts = pre, project = '11002C', min.cells = 3) 30 | ``` 31 | 32 | * for multiple experiments 33 | 34 | ```{r} 35 | # step1 list sample directories ---------------------------------------------- 36 | dir.ls <- list.dirs(path = 'cellranger-count/', 37 | full.names = T, 38 | recursive = F) 39 | dir.ls <- dir.ls[c(2:5)] 40 | dir.ls %<>% map( ~ paste0(.x, "/outs/filtered_feature_bc_matrix")) 41 | names(dir.ls) <- c('68A', '68B', '84B', '84C') 42 | 43 | # step2 check whether dir exist ------------------------------------------- 44 | dir.ls %>% map( ~ dir.exists(.x)) 45 | 46 | # step3 create seurat per samples ----------------------------------------- 47 | obj.ls <- dir.ls %>% map( ~ Read10X(.x)) %>% map( ~ CreateSeuratObject(.x, min.cells = 3)) 48 | ``` 49 | 50 | ## Quality control by visualization 51 | 52 | ```{bash} 53 | V1_Seurat_QC-CellLevelFiltering.R 54 | ``` 55 | 56 | ## Cell-level filtering 57 | 58 | ```{r} 59 | # filtering by nCount and nFeatures per individual 60 | filterCell <- function(combined){ 61 | # calculate the quantile range 62 | count.feature.ls <- combined@meta.data[, c("nCount_RNA", "nFeature_RNA")] 63 | count.feature.ls %<>% map(log10) %>% map(~c(10^(mean(.x) + 3*sd(.x)), 10^(mean(.x) - 3*sd(.x)))) 64 | 65 | # filter cells 66 | combined <- subset(combined, subset = nFeature_RNA > 200 & 67 | nFeature_RNA < count.feature.ls[[2]][1] & 68 | nCount_RNA < count.feature.ls[[1]][1]) 69 | return(combined) 70 | } 71 | obj.ls %<>% map(filterCell) 72 | ``` 73 | 74 | ## Merge individuals 75 | ```{r} 76 | combined <- merge(x = obj.ls[[1]], 77 | y = obj.ls[2:4], 78 | add.cell.ids = names(dir.ls)) 79 | ``` 80 | 81 | 82 | ## Normalize, scale, find variable genes and dimension reduciton 83 | 84 | * Choose the number of PC 85 | 86 | * SCT 87 | 88 | ```{r} 89 | combined %<>% 90 | SCTransform(return.only.var.genes = FALSE) %>% 91 | RunPCA(features = VariableFeatures(object = .)) %>% 92 | FindNeighbors(dims = 1:40) %>% 93 | FindClusters(resolution = c(0.5, 0.6, 0.8, 1, 1.2, 1.5, 1.8,2,2.5,3)) %>% 94 | RunUMAP(dims = 1:40) %>% 95 | RunTSNE(dims = 1:40) 96 | ``` 97 | 98 | * standard process 99 | 100 | ```{r} 101 | combined %<>% 102 | NormalizeData() %>% 103 | FindVariableFeatures(selection.method = 'vst', nfeatures = 2000) %>% 104 | ScaleData(features = rownames(.)) %>% 105 | RunPCA(features = VariableFeatures(object = .)) %>% 106 | FindNeighbors(dims = 1:30) %>% 107 | FindClusters(resolution = c(0.5, 0.6, 0.8, 1, 1.2, 1.5, 1.8,2,2.5,3)) %>% 108 | RunUMAP(dims = 1:30) %>% 109 | RunTSNE(dims = 1:30) 110 | ``` 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /scripts/process/N2_Scrublet_Identify-Doublet.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Identify doublet by scrublet" 3 | author: "Yuting Liu" 4 | date: "2021/5/28" 5 | output: html_vignette 6 | --- 7 | 8 | ```{r setup, include=FALSE} 9 | knitr::opts_chunk$set(echo = TRUE, eval = FALSE) 10 | ``` 11 | 12 | ## description 13 | 14 | Scoring and identify doublet using scrublet per samples 15 | 16 | 17 | 18 | ## input data 19 | 20 | filtered count matrix by cellRanger per samples 21 | 22 | ## process 23 | 24 | * running scrublet per samples 25 | 26 | * `N2-DoubletIdentify-Scurblet-Process.py -i Pre-A -r 0.02` 27 | * expected doublet ratio is calculated by ~ 0.8% per 1k cell 28 | * other parameters by default 29 | 30 | 31 | ## output 32 | 33 | * doublet scoring and identificaiton 34 | 35 | * `data/scrublet/*DoubletScores.csv` 36 | * `data/scrublet/*PredictedDoublets.csv` 37 | 38 | * validation plots 39 | 40 | * `data/scrublet/pdf` 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /scripts/process/N2_Scrublet_Identify-Doublet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Identify doublet by scrublet 17 | 18 | 19 | 20 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |

    Identify doublet by scrublet

    47 |

    Yuting Liu

    48 |

    2021/5/28

    49 | 50 | 51 | 52 |
    53 |

    description

    54 |

    Scoring and identify doublet using scrublet per samples

    55 |
    56 |
    57 |

    input data

    58 |

    filtered count matrix by cellRanger per samples

    59 |
    60 |
    61 |

    process

    62 |
      63 |
    • running scrublet per samples

    • 64 |
    • N2-DoubletIdentify-Scurblet-Process.py -i Pre-A -r 0.02

      65 |
        66 |
      • expected doublet ratio is calculated by ~ 0.8% per 1k cell
      • 67 |
      • other parameters by default
      • 68 |
    • 69 |
    70 |
    71 |
    72 |

    output

    73 |
      74 |
    • doublet scoring and identificaiton

      75 |
        76 |
      • data/scrublet/*DoubletScores.csv
      • 77 |
      • data/scrublet/*PredictedDoublets.csv
      • 78 |
    • 79 |
    • validation plots

      80 |
        81 |
      • data/scrublet/pdf
      • 82 |
    • 83 |
    84 |
    85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /scripts/process/N2_Scrublet_Identify-Doublet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import scrublet as scr 4 | import scipy.io 5 | import matplotlib.pyplot as plt 6 | import numpy as np 7 | import os 8 | import sys 9 | import getopt 10 | 11 | 12 | def main(argv): 13 | inputdir = '' 14 | edr = '' 15 | try: 16 | opts, args = getopt.getopt(argv,"hi:r:",["inputdir=","edr="]) 17 | except getopt.GetoptError: 18 | print('test.py -i -r ') 19 | sys.exit(2) 20 | for opt, arg in opts: 21 | if opt == '-h': 22 | print('test.py -i -r ') 23 | sys.exit() 24 | elif opt in ("-i", "--inputdir"): 25 | inputdir = arg 26 | elif opt in ("-r", "--edr"): 27 | edr = arg 28 | 29 | # change the dir to your input data directory 30 | os.chdir('/lustre1/lch3000_pkuhpc/liuyt/SP/D200914-scRNA-data/cellranger-count/'+inputdir) 31 | sample = os.path.basename(os.getcwd()) 32 | 33 | # plt.rcParams['font.family'] = 'sans-serif' 34 | plt.rcParams['font.sans-serif'] = 'Arial' 35 | plt.rc('font', size=14) 36 | plt.rcParams['pdf.fonttype'] = 42 37 | 38 | input_dir = 'filtered_feature_bc_matrix' 39 | counts_matrix = scipy.io.mmread(input_dir + '/matrix.mtx.gz').T.tocsc() 40 | genes = np.array(scr.load_genes(input_dir + '/features.tsv', delimiter='\t', column=1)) 41 | print('Counts matrix shape: {} rows, {} columns'.format(counts_matrix.shape[0], counts_matrix.shape[1])) 42 | print('Number of genes in gene list: {}'.format(len(genes))) 43 | 44 | print('EDR: {}'.format(edr)) 45 | scrub = scr.Scrublet(counts_matrix, expected_doublet_rate = float(edr)) 46 | 47 | doublet_scores, predicted_doublets = scrub.scrub_doublets(min_counts=2, 48 | min_cells=3, 49 | min_gene_variability_pctl=85, 50 | n_prin_comps=30) 51 | 52 | scrub.plot_histogram(); 53 | plt.savefig(sample + '_scrublet_EDR' + edr + '_hist.pdf') 54 | 55 | print('Running UMAP...') 56 | scrub.set_embedding('UMAP', scr.get_umap(scrub.manifold_obs_, 10, min_dist=0.3)) 57 | scrub.plot_embedding('UMAP', order_points=True) 58 | plt.savefig(sample + '_scrublet_EDR0.02_umap.pdf') 59 | 60 | outf1 = sample + "_scrublet_EDR" + edr + "_DoubletScores.csv" 61 | outf2 = sample + "_scrublet_EDR" + edr + "_PredictedDoublets.csv" 62 | np.savetxt(outf1, doublet_scores, delimiter=',') 63 | np.savetxt(outf2, predicted_doublets, delimiter=',') 64 | 65 | 66 | if __name__ == "__main__": 67 | main(sys.argv[1:]) 68 | -------------------------------------------------------------------------------- /scripts/visualize/Stacked-Vlnplot.R: -------------------------------------------------------------------------------- 1 | library(Seurat) 2 | library(patchwork) 3 | library(ggplot2) 4 | 5 | ## remove the x-axis text and tick 6 | ## plot.margin to adjust the white space between each plot. 7 | ## ... pass any arguments to VlnPlot in Seurat 8 | modify_vlnplot<- function(obj, 9 | feature, 10 | pt.size = 0, 11 | plot.margin = unit(c(-0.75, 0, -0.75, 0), "cm"), 12 | ...) { 13 | p<- VlnPlot(obj, features = feature, pt.size = pt.size, ... ) + 14 | xlab("") + ylab(feature) + ggtitle("") + 15 | theme(legend.position = "none", 16 | axis.text.x = element_blank(), 17 | axis.ticks.x = element_blank(), 18 | axis.title.y = element_text(size = rel(1), angle = 0), 19 | axis.text.y = element_text(size = rel(0.5)), 20 | plot.margin = plot.margin ) 21 | return(p) 22 | } 23 | 24 | ## extract the max value of the y axis 25 | extract_max<- function(p){ 26 | ymax<- max(ggplot_build(p)$layout$panel_scales_y[[1]]$range$range) 27 | return(ceiling(ymax)) 28 | } 29 | 30 | 31 | ## main function 32 | StackedVlnPlot<- function(obj, features, 33 | pt.size = 0, 34 | plot.margin = unit(c(-0.75, 0, -0.75, 0), "cm"), 35 | ...) { 36 | 37 | plot_list<- purrr::map(features, function(x) modify_vlnplot(obj = obj,feature = x, ...)) 38 | 39 | # Add back x-axis title to bottom plot. patchwork is going to support this? 40 | plot_list[[length(plot_list)]]<- plot_list[[length(plot_list)]] + 41 | theme(axis.text.x=element_text(angle = 90), axis.ticks.x = element_line()) 42 | 43 | # change the y-axis tick to only max value 44 | ymaxs<- purrr::map_dbl(plot_list, extract_max) 45 | plot_list<- purrr::map2(plot_list, ymaxs, function(x,y) x + 46 | scale_y_continuous(breaks = c(y)) + 47 | expand_limits(y = y)) 48 | 49 | p<- patchwork::wrap_plots(plotlist = plot_list, ncol = 1) 50 | return(p) 51 | } -------------------------------------------------------------------------------- /scripts/visualize/V1_Seurat_QC-CellLevelFiltering.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Seurat Quality Control and Pre-Process for snRNA-seq" 3 | author: "Yuting Liu" 4 | date: "2021/5/28" 5 | output: 6 | html_document: 7 | toc: true 8 | toc_float: true 9 | 10 | --- 11 | 12 | 13 | 14 | ```{r setup, include=FALSE} 15 | knitr::opts_knit$set(root.dir = "~/lustrelyt/github/SingleCell-MultiOmics_Process_Visualization") 16 | knitr::opts_chunk$set(echo = TRUE) 17 | library(Seurat) 18 | library(tidyverse) 19 | library(magrittr) 20 | library(gridExtra) 21 | library(data.table) 22 | ``` 23 | 24 | ```{r klippy, echo=FALSE, include=TRUE} 25 | klippy::klippy(lang = "markdown") 26 | ``` 27 | 28 | ## Description 29 | 30 | Basic quality control for snRNA-seq: check the distribution of 31 | 32 | * number of UMIs per cell 33 | 34 | * should above 500 35 | 36 | * number of genes detected per cell 37 | 38 | * number of genes detected per UMI 39 | 40 | * check the complexity. outlier cells might be cells have less complex RNA species like red blood cells. 41 | expected higher than 0.8 42 | 43 | * mitochondrial ratio 44 | 45 | * dead or dying cells will cause large amount of mitochondrial contamination 46 | 47 | ## Load seurat object 48 | 49 | ```{r} 50 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 51 | ``` 52 | 53 | 54 | 55 | ## Add other meta info 56 | 57 | * fraction of reads mapping to mitochondrial gene 58 | 59 | ```{r} 60 | # for macaque, not all genes start with MT is mitochondrion genes 61 | mt.gene <- c("MTARC2","MTFR1L","MTERF1","MTFR2","MTRF1L","MTRES1", 62 | "MTO1","MTCH1","MTFMT","MTFR1","MTERF3","MTERF2","MTPAP", 63 | "MTERF4","MTCH2",'MTIF2',"MTG2","MTIF3","MTRF1","MTCL1") 64 | combined[["percent.mt"]] <- PercentageFeatureSet(combined, features = mt.gene ) 65 | ``` 66 | 67 | * number of genes detected per UMI 68 | 69 | ```{r} 70 | combined$log10GenesPerUMI <- log10(combined$nFeature_RNA) / log10(combined$nCount_RNA) 71 | ``` 72 | 73 | 74 | ## Violin plots to check 75 | 76 | * get the meta data 77 | 78 | ```{r} 79 | df <- as.data.table(combined@meta.data) 80 | sel <- c("orig.ident", "nCount_RNA", "nFeature_RNA", "percent.mt", "log10GenesPerUMI") 81 | df <- df[, sel, with = FALSE] 82 | df[1:3, ] 83 | ``` 84 | 85 | * define plotting function 86 | 87 | ```{r} 88 | fontsize <- 10 89 | linesize <- 0.35 90 | 91 | gp.ls <- df[, 2:5] %>% imap( ~ { 92 | 93 | # define lable fun 94 | give.n <- function(x) { 95 | return(c(y = median(x) + max(x) / 10, label = round(median(x), 2))) 96 | } 97 | 98 | # assign colors 99 | col.ls <- 100 | setNames( 101 | c('lightpink2', 'lightblue2', 'lightgreen', 'coral1'), 102 | c("nCount_RNA", "nFeature_RNA", "percent.mt", "log10GenesPerUMI") 103 | ) 104 | 105 | ggplot(data = df, aes(x = orig.ident, y = .x)) + 106 | geom_violin(trim = FALSE, fill = col.ls[.y]) + 107 | ggtitle(label = .y) + ylab(label = .y) + 108 | theme_bw() + 109 | theme( 110 | panel.grid.major = element_blank(), 111 | panel.grid.minor = element_blank(), 112 | strip.background = element_blank(), 113 | panel.border = element_blank() 114 | ) + 115 | theme( 116 | axis.text = element_text(size = fontsize), 117 | axis.line = element_line(colour = "black", size = linesize), 118 | axis.ticks = element_line(size = linesize), 119 | axis.title.x = element_blank(), 120 | axis.ticks.length = unit(.05, "cm"), 121 | plot.title = element_text(size = fontsize + 2, hjust = 0.5), 122 | legend.position = 'none' 123 | ) + 124 | stat_summary(fun = median, geom = "point", col = "black") + # Add points to plot 125 | stat_summary(fun.data = give.n, 126 | geom = "text", 127 | col = "black") 128 | }) 129 | 130 | grid.arrange(gp.ls[[1]], gp.ls[[2]], gp.ls[[3]], gp.ls[[4]], ncol = 2) 131 | ``` 132 | 133 | -------------------------------------------------------------------------------- /scripts/visualize/V2_Scrublet_Doublet_Validation.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Validate the doublet scores and prediction from scrublet" 3 | author: "Yuting Liu" 4 | date: "2021/5/28" 5 | output: 6 | html_document: 7 | toc: true 8 | toc_float: true 9 | 10 | --- 11 | 12 | 13 | 14 | ```{r setup, include=FALSE} 15 | knitr::opts_knit$set(root.dir = "~/lustrelyt/github/SingleCell-MultiOmics_Process_Visualization") 16 | knitr::opts_chunk$set(echo = TRUE) 17 | library(Seurat) 18 | library(tidyverse) 19 | library(magrittr) 20 | library(gridExtra) 21 | library(data.table) 22 | ``` 23 | 24 | ```{r klippy, echo=FALSE, include=TRUE} 25 | klippy::klippy(position = c("top", "right")) 26 | ``` 27 | 28 | ## Description 29 | 30 | * check the doublet prediction from `scrublet` by 31 | 32 | * dimension reduction plot 33 | 34 | * nUMI distribution 35 | 36 | * judge the component for doublet cells by 37 | 38 | * DEG heatmap 39 | 40 | * canonical gene expression 41 | 42 | 43 | ## Load seurat object 44 | 45 | ```{r loaddata} 46 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 47 | Idents(combined) <- "cluster" 48 | ``` 49 | 50 | 51 | ## Validate the doublet prediction 52 | 53 | ```{r} 54 | # check whether the double cells cluster together 55 | FeaturePlot(combined, features = "DoubletScores", pt.size = 0.01) 56 | DimPlot( 57 | combined, 58 | group.by = "DoubletPrediction", 59 | pt.size = 0.01, 60 | cols = c("red", "azure3") 61 | ) 62 | 63 | # check the nUMI for doublet and singlet 64 | VlnPlot(combined, 65 | features = "nCount_RNA", 66 | pt.size = 0, 67 | group.by = "DoubletPrediction") + NoLegend() 68 | ``` 69 | 70 | ## Calculate factions of doublet per cluster 71 | 72 | ```{r} 73 | df <- data.table(combined@meta.data) 74 | sel.meta <- c("DoubletPrediction", "cluster", "Individual") 75 | df <- df[, sel.meta, with = FALSE] 76 | 77 | 78 | df[, 2:3] %>% map( ~ { 79 | freq1 <- df[, .N, keyby = .(.x, DoubletPrediction)] 80 | freq1[, total := sum(N), by = .(.x)] 81 | freq1[, ratio := N / total] 82 | 83 | linesize = .35 84 | fontsize = 8 85 | 86 | ggplot(freq1, aes(fill=DoubletPrediction, y=ratio, x= .x)) + 87 | geom_bar(position="stack", stat="identity")+ 88 | scale_fill_manual(values = c("Doublet" = 'red', "Singlet" = "grey")) + 89 | xlab('Clsuter') + 90 | scale_y_continuous(breaks = seq(0,1,0.1), expand = c(0,0), name = 'Percentage')+ 91 | theme_bw()+ 92 | theme( panel.grid.major.x = element_blank(), 93 | panel.grid.major.y = element_blank(), 94 | panel.grid.minor = element_blank(), 95 | strip.background = element_blank(),panel.border = element_rect(size = linesize), 96 | axis.ticks = element_blank(), 97 | axis.text.x = element_text(size = 5)) 98 | 99 | }) 100 | 101 | 102 | ``` 103 | 104 | ## Explore the component clusters for doublets by DEG 105 | 106 | * get the DEG for inferred source clusters. Here, for C33, InCGE and InMGE 107 | 108 | ```{r} 109 | 110 | # find DEG 111 | cluster.markers <- FindMarkers(combined, ident.1 = c("InMGE"), ident.2 = "InCGE", min.pct = 0.25) 112 | 113 | # subset cells of interest 114 | sel.idents <- c("InMGE", "InCGE", "D33") 115 | combined.small <- subset(combined, cells = WhichCells(combined, idents = sel.idents)) 116 | 117 | # check the expression for top DEG 118 | #sel.cells <- WhichCells(combined.small, idents = sel.idents, downsample = 355) # for large dataset 119 | DoHeatmap(combined.small, features = rownames(cluster.markers)[1:40], raster = F) 120 | 121 | ``` 122 | 123 | ## Explore the component clusters for doublets by canonical gene 124 | 125 | ```{r} 126 | sel.feature <- c("NXPH1", "PAM", "LHX6", "NR2F2", "ADARB2", "PROX1") 127 | FeaturePlot(combined, features = sel.feature, pt.size = 0.01, ncol = 3) 128 | VlnPlot(combined.small, features = sel.feature, pt.size = 0, ncol = 3, idents = sel.idents) 129 | ``` 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /scripts/visualize/V3_Seurat_Individual_BatchEffect_Explore.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Explore the batch biases for individuals/samples" 3 | author: "Yuting Liu" 4 | date: "2021/5/29" 5 | output: 6 | html_document: 7 | toc: true 8 | toc_float: true 9 | 10 | --- 11 | 12 | 13 | 14 | ```{r setup, include=FALSE} 15 | knitr::opts_knit$set(root.dir = "~/lustrelyt/github/SingleCell-MultiOmics_Process_Visualization") 16 | knitr::opts_chunk$set(echo = TRUE) 17 | library(Seurat) 18 | library(tidyverse) 19 | library(magrittr) 20 | library(gridExtra) 21 | library(data.table) 22 | ``` 23 | 24 | ```{r klippy, echo=FALSE, include=TRUE} 25 | klippy::klippy(position = c("top", "right")) 26 | ``` 27 | 28 | ## Descripiton 29 | 30 | Explore the individual batch effect by 31 | 32 | * Dimplot split by individual 33 | 34 | * Fractions of individuals per cluster 35 | 36 | 37 | ## Load seurat object 38 | 39 | ```{r loaddata} 40 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 41 | ``` 42 | 43 | ## Explore individual distribution by `Dimplot` 44 | 45 | ```{r Dimplot} 46 | Idents(object = combined) <- 'Individual' 47 | DimPlot(object = combined, reduction = "umap", label = T) 48 | DimPlot(object = combined, reduction = "tsne", label = T) 49 | ``` 50 | 51 | ## Calculate individual distribution per cluster with different resolution 52 | 53 | ```{r histogram} 54 | df <- data.table(combined@meta.data) 55 | sel.meta <- c("Individual", str_c('SCT_snn_res.', c(1, 1.5, 1.8))) 56 | df <- df[, sel.meta, with = FALSE] 57 | 58 | 59 | df[, 2:4] %>% imap(~ { 60 | freq1 <- df[, .N, keyby = .(.x, Individual)] 61 | freq1[, total := sum(N), by = .(.x)] 62 | freq1[, ratio := N / total] 63 | 64 | linesize = .35 65 | fontsize = 8 66 | 67 | ggplot(freq1, aes(fill = Individual, y = ratio, x = .x)) + 68 | geom_bar(position = "stack", stat = "identity") + 69 | scale_fill_brewer(palette = "Dark2") + 70 | xlab('Clsuter') + 71 | ggtitle(.y) + 72 | scale_y_continuous(breaks = seq(0, 1, 0.1), 73 | expand = c(0, 0), 74 | name = 'Percentage') + 75 | theme_bw() + 76 | theme( 77 | panel.grid.major.x = element_blank(), 78 | panel.grid.major.y = element_blank(), 79 | panel.grid.minor = element_blank(), 80 | strip.background = element_blank(), 81 | panel.border = element_rect(size = linesize), 82 | axis.ticks = element_blank(), 83 | axis.text.x = element_text(size = 5) 84 | ) + 85 | coord_flip() 86 | }) 87 | 88 | ``` 89 | 90 | -------------------------------------------------------------------------------- /scripts/visualize/V4_Seurat_Assign_GeneSignature_GivenGeneList.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Assign gene signature given gene list" 3 | author: "Yuting Liu" 4 | date: "2021/5/29" 5 | output: 6 | html_document: 7 | toc: true 8 | toc_float: true 9 | 10 | --- 11 | 12 | 13 | 14 | ```{r setup, include=FALSE} 15 | knitr::opts_knit$set(root.dir = "~/lustrelyt/github/SingleCell-MultiOmics_Process_Visualization") 16 | knitr::opts_chunk$set(echo = TRUE) 17 | library(Seurat) 18 | library(tidyverse) 19 | library(magrittr) 20 | library(gridExtra) 21 | library(data.table) 22 | ``` 23 | 24 | ```{r klippy, echo=FALSE, include=TRUE} 25 | klippy::klippy(position = c("top", "right")) 26 | ``` 27 | 28 | ## Description 29 | 30 | Given a gene list, calculate gene signature by averaging gene expresion 31 | 32 | 33 | ## Load seurat object 34 | 35 | ```{r loaddata} 36 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 37 | Idents(combined) <- "cluster" 38 | ``` 39 | 40 | 41 | ## Load gene lists, here using the layer-enriched genes as examples 42 | 43 | ```{r loadgene} 44 | f.ls <- list.files( 45 | "data/GeneList/", 46 | pattern = "FDR001.upDEG.csv$", 47 | full.names = T, 48 | recursive = T 49 | ) 50 | names(f.ls) <- 51 | f.ls %>% map(basename) %>% map( ~ str_remove(.x, "vs.*")) 52 | 53 | layer.ls <- f.ls %>% map( ~ { 54 | df <- fread(.x) 55 | gn <- df$id[!is.na(df$id)] 56 | gn <- gn[which(gn %in% rownames(combined))] 57 | return(gn) 58 | }) 59 | ``` 60 | 61 | ## Calcuate gene signature per gene list 62 | 63 | ```{r genesignature} 64 | mean.ls <- layer.ls %>% map_dfc(~ colMeans(x = as.matrix(combined@assays$SCT[.x, ]), na.rm = TRUE)) 65 | rownames(mean.ls) <- rownames(combined@meta.data) 66 | combined <- AddMetaData(combined, mean.ls, col.name = colnames(mean.ls)) 67 | ``` 68 | 69 | ## Explore the gene signature by `FeaturePlot` and `VlnPlot` 70 | 71 | ```{r plot} 72 | names(layer.ls) %>% map(~ FeaturePlot(object = combined, features = .x, pt.size = 0.001)) 73 | names(layer.ls) %>% map(~ { 74 | VlnPlot(object = combined, features = .x, pt.size = 0) + NoLegend() 75 | }) 76 | ``` 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /scripts/visualize/V5_Seurat_StackedVlnPlot_GivenGeneSet.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Stacked vlnplot for given gene sets" 3 | author: "Yuting Liu" 4 | date: "2021/5/29" 5 | --- 6 | title: "Explore the batch biases for individuals/samples" 7 | author: "Yuting Liu" 8 | date: "2021/5/29" 9 | output: 10 | html_document: 11 | toc: true 12 | toc_float: true 13 | 14 | --- 15 | 16 | 17 | 18 | ```{r setup, include=FALSE} 19 | knitr::opts_knit$set(root.dir = "~/lustrelyt/github/SingleCell-MultiOmics_Process_Visualization") 20 | knitr::opts_chunk$set(echo = TRUE) 21 | library(Seurat) 22 | library(tidyverse) 23 | library(magrittr) 24 | library(data.table) 25 | ``` 26 | 27 | ```{r klippy, echo=FALSE, include=TRUE} 28 | klippy::klippy(position = c("top", "right")) 29 | ``` 30 | 31 | ## Descripiton 32 | 33 | Stacked vlnplot for given gene set 34 | 35 | 36 | ## Load seurat object 37 | 38 | ```{r loaddata} 39 | combined <- get(load('data/Demo_CombinedSeurat_SCT_Preprocess.RData')) 40 | ``` 41 | 42 | ## Source stacked vlnplot funciton 43 | 44 | ```{r stackevlnfunc} 45 | source("scripts/visualize/Stacked-Vlnplot.R") 46 | ``` 47 | 48 | ## Stacked Vlnplot given gene set 49 | 50 | ```{r stackedvlnplot} 51 | sel.gene <- c("PAX6", "RBFOX1", "GAD1") 52 | 53 | StackedVlnPlot(combined, sel.gene, pt.size = 0) 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | p.caption { 2 | color: #777; 3 | margin-top: 10px; 4 | } 5 | p code { 6 | white-space: inherit; 7 | } 8 | pre { 9 | word-break: normal; 10 | word-wrap: normal; 11 | } 12 | pre code { 13 | white-space: inherit; 14 | } 15 | -------------------------------------------------------------------------------- /toc.css: -------------------------------------------------------------------------------- 1 | #TOC ul, 2 | #TOC li, 3 | #TOC span, 4 | #TOC a { 5 | margin: 0; 6 | padding: 0; 7 | position: relative; 8 | } 9 | #TOC { 10 | line-height: 1; 11 | border-radius: 5px 5px 0 0; 12 | background: #141414; 13 | background: linear-gradient(to bottom, #333333 0%, #141414 100%); 14 | border-bottom: 2px solid #0fa1e0; 15 | width: auto; 16 | } 17 | #TOC:after, 18 | #TOC ul:after { 19 | content: ''; 20 | display: block; 21 | clear: both; 22 | } 23 | #TOC a { 24 | background: #141414; 25 | background: linear-gradient(to bottom, #333333 0%, #141414 100%); 26 | color: #ffffff; 27 | display: block; 28 | padding: 19px 20px; 29 | text-decoration: none; 30 | text-shadow: none; 31 | } 32 | #TOC ul { 33 | list-style: none; 34 | } 35 | #TOC > ul > li { 36 | display: inline-block; 37 | float: left; 38 | margin: 0; 39 | } 40 | #TOC > ul > li > a { 41 | color: #ffffff; 42 | } 43 | #TOC > ul > li:hover:after { 44 | content: ''; 45 | display: block; 46 | width: 0; 47 | height: 0; 48 | position: absolute; 49 | left: 50%; 50 | bottom: 0; 51 | border-left: 10px solid transparent; 52 | border-right: 10px solid transparent; 53 | border-bottom: 10px solid #0fa1e0; 54 | margin-left: -10px; 55 | } 56 | #TOC > ul > li:first-child > a { 57 | border-radius: 5px 0 0 0; 58 | } 59 | #TOC.align-right > ul > li:first-child > a, 60 | #TOC.align-center > ul > li:first-child > a { 61 | border-radius: 0; 62 | } 63 | #TOC.align-right > ul > li:last-child > a { 64 | border-radius: 0 5px 0 0; 65 | } 66 | #TOC > ul > li.active > a, 67 | #TOC > ul > li:hover > a { 68 | color: #ffffff; 69 | box-shadow: inset 0 0 3px #000000; 70 | background: #070707; 71 | background: linear-gradient(to bottom, #262626 0%, #070707 100%); 72 | } 73 | #TOC .has-sub { 74 | z-index: 1; 75 | } 76 | #TOC .has-sub:hover > ul { 77 | display: block; 78 | } 79 | #TOC .has-sub ul { 80 | display: none; 81 | position: absolute; 82 | width: 200px; 83 | top: 100%; 84 | left: 0; 85 | } 86 | #TOC .has-sub ul li a { 87 | background: #0fa1e0; 88 | border-bottom: 1px dotted #31b7f1; 89 | filter: none; 90 | display: block; 91 | line-height: 120%; 92 | padding: 10px; 93 | color: #ffffff; 94 | } 95 | #TOC .has-sub ul li:hover a { 96 | background: #0c7fb0; 97 | } 98 | #TOC ul ul li:hover > a { 99 | color: #ffffff; 100 | } 101 | #TOC .has-sub .has-sub:hover > ul { 102 | display: block; 103 | } 104 | #TOC .has-sub .has-sub ul { 105 | display: none; 106 | position: absolute; 107 | left: 100%; 108 | top: 0; 109 | } 110 | #TOC .has-sub .has-sub ul li a { 111 | background: #0c7fb0; 112 | border-bottom: 1px dotted #31b7f1; 113 | } 114 | #TOC .has-sub .has-sub ul li a:hover { 115 | background: #0a6d98; 116 | } 117 | #TOC ul ul li.last > a, 118 | #TOC ul ul li:last-child > a, 119 | #TOC ul ul ul li.last > a, 120 | #TOC ul ul ul li:last-child > a, 121 | #TOC .has-sub ul li:last-child > a, 122 | #TOC .has-sub ul li.last > a { 123 | border-bottom: 0; 124 | } 125 | #TOC ul { 126 | font-size: 1.2rem; 127 | } 128 | --------------------------------------------------------------------------------