Enrichment of Neural Crest Cells by Antibody Labeling and Flow Cytometry for Single-Cell Transcriptomics in a Lizard.
The 9 matches
- [1] § Material and Methods › Single Cell Transcriptomic Analysis › Assessment of NCC Enrichment ↔ 02_Analysis/08_scmapSmrtSOnCao_old.R, lines 2–44 · score 0.76 · likelihood threshold, variable features, Gene orthology, downloaded, Ensembl, scmap
- [2] § Material and Methods › Single Cell Transcriptomic Analysis › 10X Chromium ↔ 02_Analysis/04_IntAnalysis10XAndSmrtS.Rmd, lines 116–152 · score 0.75 · cell cycle scores, cell cycle state, SCTransform, v2, regression, human
- [3] § Results › Differential Expression Analysis in Unsorted Cells Reveals Putative Novel NCC Markers ↔ 02_Analysis/04_IntAnalysis10XAndSmrtS.Rmd, lines 564–581 · score 0.74 · TFAP2B, TFAP2A, Ets1, Sox8, Acbd7, Ednrb
- [4] § Material and Methods › Single Cell Transcriptomic Analysis › Assessment of NCC Enrichment ↔ 02_Analysis/04_IntAnalysis10XAndSmrtS.Rmd, lines 349–369 · score 0.72 · AddModuleScore, TFAP2A, Zic1, Pax3, Sox5, Pax7
- [5] § Material and Methods › Single Cell Transcriptomic Analysis › Smart‐seq3 ↔ 02_Analysis/04_IntAnalysis10XAndSmrtS.Rmd, lines 116–152 · score 0.69 · cell cycle scores, cell cycle state, SCTransform, regressed, predicted, genes
- [6] § Results › Characterization of HNK‐1 Positive Cells Using scRNA‐Seq ↔ 02_Analysis/04_IntAnalysis10XAndSmrtS.Rmd, lines 349–369 · score 0.68 · TFAP2A, median, leniently sorted, strictly sorted, Zic1, Pax3
- [7] § Material and Methods › Single Cell Transcriptomic Analysis › Assessment of NCC Enrichment ↔ 02_Analysis/04_IntAnalysis10XAndSmrtS.Rmd, lines 251–275 · score 0.65 · IntegrateLayers, SCTransform, UMAP, harmony
- [8] § Material and Methods › Single Cell Transcriptomic Analysis › 10X Chromium ↔ 02_Analysis/03_CompileAndFilter10X.Rmd, lines 355–373 · score 0.62 · reduced dimension, SCTransform, PCA, regression, space, UMAP
- [9] § Material and Methods › Single Cell Transcriptomic Analysis › Smart‐seq3 ↔ 02_Analysis/03_CompileAndFilter10X.Rmd, lines 355–373 · score 0.62 · reduced dimension, SCTransform, PCA, regressed, space, UMAP
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
R Markdown · 680 lines · 24 KB · no license · 6 matches
- ---
- title: ''
- output: html_document
- date: "2025-12-03"
- ---
- ```{r setup, include=FALSE}
- knitr::opts_chunk$set(echo = TRUE)
- ```
- # Set up
- ```{r}
- options(future.globals.maxSize = 120000 * 1024^2) # Change this to fit your
- Sys.setenv(R_MAX_VSIZE = "120Gb") # computer
- rm(list=ls());gc()
- start_time <- Sys.time()
- library(Seurat, lib.loc = "/usr/local/lib/R/site-library") #Change these to
- library(glmGamPoi, lib.loc = "/usr/local/lib/R/site-library") #mach the location
- library(dplyr, lib.loc = "/usr/local/lib/R/site-library") #of your libraries
- library(ggplot2, lib.loc = "/usr/local/lib/R/site-library")
- library(patchwork, lib.loc = "/usr/local/lib/R/site-library")
- library(latex2exp, lib.loc = "/home/pranter/R/x86_64-pc-linux-gnu-library/4.5")
- library(ggrepel, lib.loc = "/usr/local/lib/R/site-library")
- library(ggbreak, lib.loc = "/home/pranter/R/x86_64-pc-linux-gnu-library/4.5")
- library(ggridges, lib.loc = "/usr/local/lib/R/site-library")
- library(stringr, lib.loc = "/usr/local/lib/R/site-library")
- path <- "~/WorkDirs/PmurNCCPilot_10X_rerun/"
- ```
- # Read filtered 10X data
- ```{r}
- filename <- list.files(paste0(path, "02_Analysis/"),
- pattern = "03_CompileAndFilter10X_out_")
- if (length(filename) == 1) {
- TenX.SO <- readRDS(file=paste0(path, "02_Analysis/", filename))
- } else {
- print(paste0("You have two files matching the pattern.",
- "Choose one to read and remove the other from the directory."))
- print(filename)
- }
- rm(filename)
- TenX.SO
- ```
- # Read filtered SmartSeq data
- ```{r}
- filename <- list.files(paste0(path,"02_Analysis/"),
- pattern = "02_FilterSmrtS_output_")
- if (length(filename) == 1) {
- SmrtS.SO <- readRDS(file = paste0(path, "02_Analysis/", filename))
- } else {
- print(paste0("You have two files matching the pattern. ",
- "Choose one to read and remove the other from the directory."))
- print(filename)
- }
- rm(filename)
- SmrtS.SO
- ```
- # Merge objects
- ```{r}
- # Select metadata columns
- met.cols <- c("orig.ident", "type", "nCount_RNA","nFeature_RNA",
- "percent.mt", "percent.rb")
- SmrtS.SO$type <- "Strictly sorted"
- [email hidden] <- [email hidden] %>% select(all_of(met.cols))
- [email hidden] <- [email hidden] %>% select(all_of(met.cols))
- rm(met.cols)
- #Restor seurat objects to non-normalized form
- DefaultAssay(SmrtS.SO) <- "RNA"
- SmrtS.SO <- DietSeurat(object = SmrtS.SO,
- layers = "counts",
- assays = "RNA")
- DefaultAssay(TenX.SO) <- "RNA"
- TenX.SO <- DietSeurat(object = TenX.SO,
- layers = "counts",
- assays = "RNA")
- #Merge
- full.SO <- merge(TenX.SO, c(SmrtS.SO))
- full.SO[["RNA"]] <- JoinLayers(full.SO[["RNA"]])
- # Fix the type column in meta data (mostly for plotting)
- [email hidden]$type <- factor([email hidden]$type,
- levels = c("Unsort", "Sorted",
- "Strictly sorted"))
- [email hidden] <- [email hidden] %>%
- mutate(type = recode(type,
- "Unsort" = "Unsorted",
- "Sorted" = "Leniently sorted"),
- type.short = recode(type,
- "Unsorted" = "U",
- "Leniently sorted" = "L",
- "Strictly sorted" = "S"))
- full.SO
- [email hidden] %>% colnames()
- ```
- # Basic stats
- ```{r}
- [email hidden] %>%
- group_by(type) %>%
- summarize(n = n(),
- av_count = mean(nCount_RNA) %>% round(),
- sd_count = sd(nCount_RNA) %>% round(),
- av_genes = mean(nFeature_RNA) %>% round(),
- sd_genes = sd(nFeature_RNA) %>% round()) %>%
- t()
- ```
- # Calc Cell Cycl
- ```{r}
- # temporary normalisation for CC-scoring
- full.SO <- SCTransform(full.SO,
- assay = 'RNA',
- new.assay.name = 'temp_SCT',
- vars.to.regress = c('percent.mt'),
- vst.flavor = "v2",
- variable.features.n = 3000) #3000 is default
- # Load ortholog table
- Ortho.df <- read.csv(file=paste0(path, "01_Data/",
- "Pmur1.0Human_OrthoTable_BioMartManDL20241206.txt"))
- # Save S and G2M markers in Pmur
- G2M.genes <- Ortho.df[Ortho.df$Human.gene.name %in%
- cc.genes.updated.2019$g2m.genes, ]$Gene.name
- S.genes <- Ortho.df[Ortho.df$Human.gene.name %in%
- cc.genes.updated.2019$s.genes, ]$Gene.name
- #Check that the markers are present in the data
- print(paste0(full.SO %>% Features() %in% G2M.genes %>% sum(), "/",
- G2M.genes %>% length(),
- " G2M-markers are present in the data"))
- print(paste0(full.SO %>% Features() %in% S.genes %>% sum(), "/",
- S.genes %>% length(),
- " S-markers are present in the data"))
- #Subset only the genes that are present
- G2M.genes <- G2M.genes[G2M.genes %in% Features(full.SO)]
- S.genes <- S.genes[S.genes %in% Features(full.SO)]
- # Predict cell cycle state (make sure to specify the "assay" parameter)
- full.SO <- CellCycleScoring(full.SO,
- s.features = S.genes,
- g2m.features = G2M.genes,
- assay = 'temp_SCT',
- set.ident = TRUE)
- rm(G2M.genes, S.genes); gc()
- ```
- # Plot QCs
- ```{r}
- PQC <- c("nCount_RNA", "nFeature_RNA", "percent.mt", "percent.rb") %>%
- lapply(function(feats){
- ggplot([email hidden], aes(x = type, y = .data[[feats]], fill = type)) +
- geom_violin() +
- scale_fill_manual(values = c("Unsorted" = "#BDBDBD",
- "Leniently sorted" = "#53AC90",
- "Strictly sorted" = "#64EC09")) +
- labs(y = c("nCount_RNA" = "n counts",
- "nFeature_RNA" = "n genes",
- "percent.mt" = "% mitochondrial",
- "percent.rb" = "% ribosomal")[feats], fill = "") +
- theme_classic() +
- theme(plot.margin = margin(t=1.7, r=1, b=0, l=0.4, unit = "mm"),
- axis.text.y = element_text(size = 8, angle = 45),
- axis.title.y = element_text(size = 11),
- axis.text.x = element_blank(),
- axis.title.x = element_blank(),
- axis.ticks.x = element_blank(),
- legend.text = element_text(size = 8),
- legend.key.size = unit(3, "mm"),
- legend.title = element_text(size = 11),
- plot.title = element_blank())
- }) %>%
- wrap_plots(ncol = 4) +
- plot_layout(guides = "collect") &
- theme(legend.position = "bottom")
- PQC
- ggsave(filename = paste0(path, "03_Results/QCPlot.svg"),
- plot = PQC, height = 50, width = 180, units = "mm")
- ```
- # Table for manuscript
- ```{r}
- [email hidden] %>% select("type", "nCount_RNA", "nFeature_RNA") %>%
- group_by(type) %>%
- summarize(n = n(),
- av_count = mean(nCount_RNA) %>% round(),
- sd_count = sd(nCount_RNA) %>% round(),
- av_genes = mean(nFeature_RNA) %>% round(),
- sd_genes = sd(nFeature_RNA) %>% round()) %>%
- t()
- ```
- # Standard processing
- ## Without integration
- ```{r}
- #DefaultAssay(full.SO) <- "RNA"
- #full.SO[["temp_SCT"]] <- NULL
- ## Normalize
- #full.SO <- SCTransform(full.SO,
- # assay = 'RNA',
- # new.assay.name = 'SCT',
- # vars.to.regress =c("percent.mt", "S.Score", "G2M.Score"),
- # vst.flavor = "v2",
- # variable.features.n = 3000)
- #
- ## Inspect the normalization
- #cbind(Matrix::rowSums(full.SO[["RNA"]]$counts)[
- # rownames(full.SO[["RNA"]]$counts) %in%
- # rownames(full.SO[["SCT"]]$data)],
- # Matrix::rowSums(full.SO[["SCT"]]$data)) %>%
- # as.data.frame() %>%
- # dplyr::rename(raw = V1, norm = V2) %>%
- # ggplot(aes(raw, norm)) +
- # geom_point() +
- # labs(title = "Normalized data vs raw counts (each dot is a gene)") +
- # theme(text = element_text(size = 6))
- #
- ## Inspect HVG selection
- #VariableFeaturePlot(full.SO, assay = "SCT") %>%
- # LabelPoints(points = VariableFeatures(full.SO, assay = "SCT") %>% head(20),
- # repel = TRUE,
- # xnudge = 0, ynudge = 0, max.overlaps = 22) +
- # theme(text = element_text(size = 6))
- #
- ## Lin dim reduc
- #full.SO <- RunPCA(full.SO, assay = "SCT")
- #ElbowPlot(full.SO, reduction = "pca", ndims = 50)
- #
- #Non-lin dim reduc
- #full.SO <- RunUMAP(full.SO, dims = 1:20)#, spread = 0.4, min.dist = 0.4)
- # # dims = 11 seems good judgeing by the elbowplot and PC-heatmaps
- # # Changing the min.dist dramatically changes the umap. This requires some
- # # optimaization. Come back to this later.
- #
- ##Plot
- #DimPlot(full.SO, reduction = "umap", group.by = "type",
- # shuffle = TRUE, alpha = 0.5) + ggtitle("No integration")
- ##DimPlot(full.SO, group.by = "orig.ident", shuffle = TRUE, alpha = 0.5,
- ## cells = Cells(subset(full.SO, subset = type.short == "L")))
- ```
- ## With integration
- See insturctions here: https://github.com/satijalab/seurat/issues/7542
- and here: https://satijalab.org/seurat/articles/seurat5_integration
- ```{r}
- # Normalize each sample separately
- full.SO[["RNA"]] <- split(full.SO[["RNA"]], f = full.SO$orig.ident)
- DefaultAssay(full.SO) <- "RNA"
- full.SO <- SCTransform(full.SO,
- assay = "RNA",
- new.assay.name = "SCT_BySample",
- vars.to.regress =c("percent.mt", "G2M.Score", "S.Score"),
- vst.flavor = "v2",
- variable.features.n = 3000) %>%
- # Calculate PCA
- RunPCA(assay = "SCT_BySample", reduction.name = "pca_SCT_BySample") %>%
- # Integrate data sets
- IntegrateLayers(method = HarmonyIntegration,
- orig.reduction = "pca_SCT_BySample",
- new.reduction = 'harmony',
- assay = "SCT_BySample",
- normalization.method = "SCT",
- verbose = FALSE) %>%
- # Calc umap
- RunUMAP(dims = 1:30, reduction = "harmony", reduction.name = "umap_harmony")
- ```
- # Plot sort types in umap
- ```{r}
- P01 <- DimPlot(full.SO,
- reduction = "umap_harmony", group.by = "type",
- order = c("Strictly sorted", "Leniently sorted", "Unsorted"),
- alpha = 0.5, stroke.size = 0, pt.size = 1) +
- scale_color_manual(values = c("Unsorted" = "#BDBDBD",
- "Leniently sorted" = "#53AC90",
- "Strictly sorted" = "#64EC09")) +
- labs(y = "umap 2", x = "umap 1") +
- theme(plot.margin = margin(t=1.7, r=1, b=1.7, l=0.4, unit = "mm"),
- axis.text.y = element_text(size = 8, angle = 45),
- axis.title.y = element_text(size = 11),
- axis.text.x = element_text(size = 8, angle = 45),
- axis.title.x = element_text(size = 11),
- legend.text = element_text(size = 8),
- legend.key.size = unit(2.5, "mm"),
- legend.position = "inside",
- plot.title = element_blank())
- P01
- ggsave(paste0(path, "03_Results/UMAP_SortType.svg"),
- P01, height = 89, width = 89, units = "mm")
- ```
- # Plot marker exp in umap
- ```{r}
- # First normalize across samples to correct for sequencing depth
- full.SO[["RNA"]] <- JoinLayers(full.SO[["RNA"]])
- full.SO <- SCTransform(full.SO,
- assay = "RNA",
- new.assay.name = "SCT",
- vars.to.regress =c("percent.mt", "G2M.Score", "S.Score"),
- vst.flavor = "v2",
- variable.features.n = 3000)
- # It also seems to work to do PrepSCTFindMarkers
- ```
- ```{r}
- # Then plor using FeaturePlot
- P02 <- FeaturePlot(full.SO, c("SOX10", "TFAP2A",
- "SNAI2", "FOXD3"#,
- #"PAX7", "SOX9", "TWIST1", "PAX3", "GAPDH"
- ),
- order = TRUE, pt.size = 1, alpha = 0.5, keep.scale = "all") &
- NoAxes() &
- theme(legend.key.size = unit(3, "mm"),
- legend.text = element_text(size = 8))
- #Remove stroke arround points
- P02 <- lapply(P02, function(p) {
- p$layers[[1]]$aes_params$stroke <- 0
- old_title <- p$labels$title
- #Chance title font
- p <- p + ggtitle(str_to_sentence(old_title)) +
- theme(plot.title = element_text(face = "italic"))
- p
- })
- #Tidy up
- P02 <- wrap_plots(P02, ncol = 2, guides = "collect") &
- FontSize(main = 11) +
- NoAxes()
- P02
- ggsave(paste0(path, "03_Results/UMAP_MrkrExp.svg"),
- P02, height = 89, width = 89, units = "mm")
- ```
- # Calc NCC-ness score
- ```{r}
- full.SO <- AddModuleScore(object = full.SO,
- features = list(c("PAX3", "PAX7", "FOXD3", "SOX10",
- "SOX9", "WNT1", "TFAP2A", "SOX5",
- "SNAI2", "ZIC1")),
- name = "NCC_AMS",
- ctrl = 100)
- [email hidden] %>%
- select(type, NCC_AMS1) %>%
- group_by(type) %>%
- summarize(avg_NCCAMS = median(NCC_AMS1)) %>%
- t()
- wilcox.test(x = subset(full.SO, subset = type == "Strictly sorted")$NCC_AMS1,
- y = subset(full.SO, subset = type == "Leniently sorted")$NCC_AMS1)
- wilcox.test( x = subset(full.SO, subset = type == "Strictly sorted")$NCC_AMS1,
- y = subset(full.SO, subset = type == "Unsorted")$NCC_AMS1)
- wilcox.test( x = subset(full.SO, subset = type == "Leniently sorted")$NCC_AMS1,
- y = subset(full.SO, subset = type== "Unsorted")$NCC_AMS1)
- ```
- # NCC markers
- ## Def NCCs in unsorted samp
- ```{r}
- unsort.SO <- full.SO %>%
- subset(cells = Cells(subset(full.SO, subset = type == "Unsorted")))
- # Extract SOX10 expression (RNA assay, default data slot)
- sox10_expr <- GetAssayData(unsort.SO, assay = "SCT", layer = "data")["SOX10", ]
- # Create NCC classification
- unsort.SO$NCC <- ifelse(sox10_expr > 0, "NCC", "Other")
- rm(sox10_expr); gc()
- # Optionally make it a factor with defined order
- unsort.SO$NCC <- factor(unsort.SO$NCC, levels = c("Other", "NCC"))
- unsort.SO$NCC %>% table()
- ```
- ## Plot unsort samp in umap
- ```{r}
- Idents(unsort.SO) <- unsort.SO$type
- P03 <- DimPlot(unsort.SO,
- reduction = "umap_harmony", group.by = "NCC",
- order = c("NCC", "Other"),
- alpha = 0.7, stroke.size = 0, pt.size = 1) +
- scale_color_manual(values = c("Other" = "#BDBDBD",
- "NCC" = "#ffc64fff")) +
- labs(y = "umap 2", x = "umap 1") +
- theme(plot.margin = margin(t=1.7, r=1, b=1.7, l=0.4, unit = "mm"),
- axis.text.y = element_text(size = 8, angle = 45),
- axis.title.y = element_text(size = 11),
- axis.text.x = element_text(size = 8, angle = 45),
- axis.title.x = element_text(size = 11),
- legend.text = element_text(size = 11),
- legend.key.size = unit(2.5, "mm"),
- legend.title = element_text(size = 11),
- legend.position = "inside",
- plot.title = element_blank())
- P03
- ggsave(paste0(path, "03_Results/UMAP_Unsort.svg"),
- P03, height = 89, width = 89, units = "mm")
- ```
- ```{r}
- P03_inset <- FetchData(unsort.SO,
- vars = c("SOX10", "nCount_RNA"),
- assay = "RNA,",
- layer = "count") %>%
- mutate(Sox10_PM = SOX10 / (nCount_RNA / 1e6),
- logSox10_PM = log1p(Sox10_PM)) %>%
- ggplot(aes(x = logSox10_PM, fill = SOX10 == 0)) +
- geom_histogram(binwidth = 1) +
- scale_x_continuous(breaks = log1p(c(0, 200, 800)),
- labels = c("0", "200", "800")) +
- scale_y_break(breaks = c(150, 10450)) +
- scale_y_continuous(breaks = c(0, 100, 10500, 10600),
- labels = c("0", "100", "10500", "10600"),
- limits = c(0, 10610)) +
- scale_fill_manual(values = c(`TRUE` = "#BDBDBD", # bar at 0
- `FALSE` = "#ffc64fff"), # non-zero bars
- guide = "none") +
- #labs(x = "Sox10 per 1M", y = "Freq.") +
- theme_classic() +
- theme(plot.margin = margin(t=0, r=0, b=0, l=0),
- axis.text.y.right = element_blank(),
- axis.ticks.y.right = element_blank(),
- axis.line.y.right = element_blank(),
- axis.title = element_blank(),
- axis.text.x = element_text(size = 8, angle = 45, hjust = 1),
- axis.text.y = element_text(size = 8, angle = 45, vjust = 0.5))
- ggsave(paste0(path, "03_Results/UMAP_Unsort_hist.svg"),
- P03_inset, height = 35, width = 40, units = "mm")
- P03_inset
- ```
- ## Calc diff. exp.
- This does differential expression testing between NCCs (Sox10 positive cells)
- and all other cells in the unsorted samples.
- ```{r}
- Idents(unsort.SO) <- unsort.SO$NCC
- DEG.df <- FindMarkers(unsort.SO,
- ident.1 = "NCC",
- only.pos = FALSE,
- logfc.threshold = 0,
- min.pct = 0)
- DEG.df$gene <- rownames(DEG.df)
- #Add average normalized expression in NCCs to the dataframe
- avg_NCC_exp <- unsort.SO %>%
- subset(subset = NCC == "NCC") %>%
- GetAssayData(assay = "SCT", layer = "counts") %>%
- rowMeans()
- DEG.df <- DEG.df %>% mutate(avg_NCC_exp = avg_NCC_exp[rownames(DEG.df)])
- rm(avg_NCC_exp); gc()
- # Add negative log10 p column
- DEG.df$neg_log10p <- log10(DEG.df$p_val)*-1
- DEG.df %>% head()
- DEG.df %>% str()
- ```
- ## Def NCC markers
- ```{r}
- #Subset DE table
- NCCmrkrs.df <- DEG.df %>% #Use only:
- subset(avg_log2FC > 0.1) %>% # -Genes with relevant effect size
- subset(p_val_adj <= 0.05) %>% # -Significantly different genes
- subset(avg_NCC_exp > 0.05) #%>% # -Genes with informative mean exp in NCCs
- #subset(pct.1 >= 0.01)
- #Add column to label the NCC markers in DEG.df
- DEG.df$NCCmrkrs <- ifelse(DEG.df$gene %in% NCCmrkrs.df$gene, "Yes", "No")
- ##Save table for supplementary as .csv
- #DEG.df %>%
- # #Select the rellevant columns
- # select(gene, avg_log2FC, avg_NCC_exp, p_val_adj, NCCmrkrs) %>%
- # #Reorder the rows to make it easier to find the markers at a glance
- # arrange(factor(NCCmrkrs, levels = c("Yes", "No")),
- # p_val_adj,
- # desc(avg_log2FC)
- # ) %>%
- # # Round off all values
- # mutate(avg_log2FC = round(avg_log2FC, 3),
- # avg_NCC_exp = round(avg_NCC_exp, 3),
- # p_val_adj = case_when(
- # p_val_adj < 0.001 ~ "<0.001",
- # p_val_adj > 0.001 ~ as.character(round(p_val_adj, 3)))) %>%
- # # rename the columns for readability
- # rename("Gene" = gene,
- # "Average log2-fold change" = avg_log2FC,
- # "Average SCT counts in NCCs" = avg_NCC_exp,
- # "Adjusted p-value" = p_val_adj,
- # "NCC markers" = NCCmrkrs) %>%
- # write.csv(paste0(path, "03_Results/",
- # "DiffExpAll_", Sys.Date(), ".csv"),
- # row.names = FALSE)
- ```
- ## Plotting
- Here i plot differential expression in a few different ways for one of the
- figures in the paper.
- ## MA plot
- ```{r}
- #Plot
- P04 <- DEG.df %>%
- mutate(avg_log2FC = ifelse(avg_log2FC > 5, 5, avg_log2FC)) %>%
- mutate(avg_log2FC = ifelse(avg_log2FC < -5, -5, avg_log2FC)) %>%
- mutate(avg_NCC_exp = ifelse(avg_NCC_exp > 10, 10, avg_NCC_exp)) %>%
- arrange(NCCmrkrs == "Yes") %>%
- ggplot(aes(y = avg_log2FC, x = avg_NCC_exp, color = NCCmrkrs)) +
- geom_point(shape = 19, size = .7, alpha = .7) +
- scale_x_continuous(trans = scales::log1p_trans()) +
- scale_color_manual(values = c("Yes" = "#ffc64fff", "No" = "#BDBDBD")) +
- ylab(label = TeX('$log_{2}$(fold change)')) +
- xlab(label = "Mean expressin in putative NCCs, log(x+1)")+
- labs(title = "Differential expression",
- color = "NCC markers") +
- theme(plot.title = element_blank(),
- axis.title.y = element_text(size = 11),
- axis.title.x = element_text(size = 11),
- axis.text.y = element_text(size = 8),
- axis.text.x = element_text(size = 8),
- legend.title = element_text(size = 8),
- legend.key.size = unit(2.5, "mm"),
- legend.position = "none",
- #Background
- plot.background = element_rect(fill = "white", color = "white"),
- panel.background = element_rect(fill = "white", color = "white"),
- panel.border = element_rect(colour = "black", fill = NA)) +
- geom_vline(xintercept = .05, linetype = "dashed") +
- geom_hline(yintercept = .2, linetype = "dashed")
- P04
- ggsave(filename = paste0(path, "03_Results/MAPlot.svg"),
- plot = P04, height = 89, width = 89, units = "mm")
- ```
- ## Volcano plot
- ### Lebels
- ```{r}
- # Manually set some selected genes to label
- Volcano_labels <- c("SOX10", "EDNRB", "TFAP2A", "TFAP2B", "ZEB2",
- "PAX7", "ETS1", "SOX8", "SOX5",
- "GYPC", "ACBD7", "RAB19")
- Volcano_labels <- NCCmrkrs.df[Volcano_labels, ]
- Volcano_labels <- Volcano_labels %>%
- mutate(avg_log2FC = ifelse(avg_log2FC > 7, 7, avg_log2FC)) %>%
- mutate(avg_log2FC = ifelse(avg_log2FC < -7, -7, avg_log2FC)) %>%
- mutate(neg_log10p = ifelse(neg_log10p > 100, 100, neg_log10p))
- Volcano_labels
- ```
- ### Plot
- ```{r}
- # Set line for p value
- sig_line <- DEG.df %>%
- arrange(NCCmrkrs == "Yes") %>% {log10(0.05/nrow(.))*-1}
- #Construct the plot
- P05 <- DEG.df %>%
- mutate(avg_log2FC = ifelse(avg_log2FC > 7, 7, avg_log2FC)) %>%
- mutate(avg_log2FC = ifelse(avg_log2FC < -7, -7, avg_log2FC)) %>%
- mutate(neg_log10p = ifelse(neg_log10p > 100, 100, neg_log10p)) %>%
- arrange(NCCmrkrs == "Yes") %>%
- ggplot(aes(x = avg_log2FC, y = neg_log10p, color = NCCmrkrs)) +
- geom_point(shape = 19, size = .7, alpha = .7) +
- geom_vline(xintercept = 0.2, linetype = "dashed") +
- geom_hline(yintercept = sig_line, linetype = "dashed") +
- scale_color_manual(values = c("Yes" = "#ffc64fff", "No" = "#BDBDBD")) +
- ylab(label = TeX('$-log_{10}$(adj. p-value)')) +
- xlab(label = TeX('$log_{2}$(fold change)')) +
- labs(title = "NCC markers",
- color = "NCC markers") +
- geom_label_repel(data = Volcano_labels,
- #Italic lowercase gene names
- aes(label = paste0("italic(", str_to_sentence(gene), ")")),
- parse = TRUE,
- color = "black",
- max.overlaps = 20,
- nudge_x = -4,
- size = 3,
- label.padding = 0.1,
- label.r = .1) +
- theme(plot.title = element_blank(),
- axis.title.y = element_text(size = 11),
- axis.title.x = element_text(size = 11),
- axis.text.y = element_text(size = 8),
- axis.text.x = element_text(size = 8),
- #Background
- plot.background = element_rect(fill = "white", color = "white"),
- panel.background = element_rect(fill = "white", color = "white"),
- panel.border = element_rect(colour = "black", fill = NA),
- legend.position = "none")
- P05
- ggsave(filename = paste0(path, "03_Results/VolcanoPlot.svg"),
- plot = P05, height = 89, width = 89, units = "mm")
- ```
- ```{r}
- P05 + geom_point(
- data = DEG.df %>% filter(gene == "GYPC"), # Change gene to label the point
- aes(x = avg_log2FC, y = neg_log10p), # of your choice
- color = "red", size = 2)
- ```
- # Module score new NCC markers
- ```{r}
- full.SO <- AddModuleScore(full.SO,
- list(NCCmrkrs.df$gene),
- #Or, excluding Sox10:
- #list(NCCmrkrs.df$gene[2:length(NCCmrkrs.df$gene)]),
- name = "NewNCCmrkrsAMD")
- ```
- ```{r}
- P06 <- [email hidden] %>%
- ggplot(aes(x = type, fill = type, y = NewNCCmrkrsAMD1)) +
- geom_violin() +
- scale_fill_manual(values = c("Unsorted" = "#BDBDBD",
- "Leniently sorted" = "#53AC90",
- "Strictly sorted" = "#64EC09")) +
- labs(y = "NCC marker module score") +
- theme_classic() +
- theme(axis.title.x = element_blank(),
- axis.title.y = element_text(size = 11),
- axis.text = element_text(size = 8),
- legend.position = "none")
- ggsave(filename = paste0(path, "03_Results/NCCmrkrVln.svg"),
- plot = P06, height = 89, width = 89, units = "mm")
- P06
- ```
- # Save data
- Save the filtered data and meta data in an RDS file to be read by the next script in the pipeline (04_IntAnalysis10XAndSmrtS.Rmd)
- ```{r}
- full.SO
- saveRDS(full.SO, paste0(path,
- "02_Analysis/04_IntAnalysis_output_",
- Sys.Date(),
- ".Rds"))
- ```
- Calculated runtime:
- ```{r}
- end_time <- Sys.time()
- paste0("Elapsed time: ", end_time - start_time)
- ```
04_IntAnalysis10XAndSmrtS.Rmd at commit 11c8df9, no license · at the source
Overview
- Department of Biology, Lund University, Lund, Sweden
- Current address: Max Planck Institute for Evolutionary Biology, Plön, Germany
- Department of Diagnostic and Intervention, Umeå University, Umeå, Sweden
Abstract
Neural crest cells (NCCs) are a key component of the vertebrate body plan and contribute to a variety of different traits. Recent advances in single‐cell transcriptomics (scRNA‐seq) have significantly improved our understanding of NCC biology. However, their dynamic migratory behavior and spatiotemporal heterogeneity in the developing embryo pose significant challenges for their identification and isolation. Consequently, most studies of NCCs have been confined to model organisms with established transgenic tools or established methods for in ovo manipulation. To overcome this limitation, we present a novel approach that combines antibody labeling with fluorescence activated cell sorting to enrich for NCCs and we demonstrate the approach in the common wall lizard (Podarcis muralis). Through microscopy, reverse transcription quantitative polymerase chain reaction and single‐cell RNA sequencing, we show that the method enriches for NCCs as efficiently as methods relying on transgenic animals. Using this technique, we successfully characterize transcriptional profiles of NCCs in wall lizard embryos. We anticipate that this method can be applied to a wide range of vertebrates that lack transgenic tools, enabling deeper insights into the diverse roles of neural crest cells in development and evolution.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 9 matches between paragraphs and lines of code.
Zenodo 18544211
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
- 30 September 2026: the link answers (HTTP 200)
robinpranter/enrichment-of-neural-crest-cells---supplementary-code
11c8df99b76d3231d3fb5ba905b1e4adea11c4c7, 6 February 2026Availability: 1 check, the latest on 30 September 2026: the link answers
- 30 September 2026: the link answers
13 files
- 02_Analysis/
01_CompileSmrtS.Rmd , R, 286 lines - 02_Analysis/
02_FilterSmrtS.Rmd , R, 338 lines - 02_Analysis/
03_CompileAndFilter10X.R , R, 395 lines, 2 matchesmd - 02_Analysis/
04_IntAnalysis10XAndSmrt , R, 680 lines, 6 matchesS.Rmd - 02_Analysis/
05_RelExp10XAndSmrtS.Rmd , R, 364 lines - 02_Analysis/
06_scmap10XOnCao.R , R, 407 lines - 02_Analysis/
07_scmapSolOnCao.R , R, 408 lines - 02_Analysis/
08_scmapSmrtSOnCao.R , R, 388 lines - 02_Analysis/
08_scmapSmrtSOnCao_old.R , R, 382 lines, 1 match - 02_Analysis/
09_CountScmapClassificat , R, 173 linesions.Rmd - 02_Analysis/
FlowCytometry.Rmd , R, 705 lines - 02_Analysis/
qPCRAnalysis_AutoBT.Rmd , R, 704 lines - README.md, Text, 57 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 12 scripts, each with its path and the digest of its content;
- 9 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- geo:GSE319069, at NCBI GEO; found in “Data Availability Statement”
Data Availability Statement
All sequence data generated in this study have been deposited in NCBI GEO with accession number GSE319069 (https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 30 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 3 authors, 6 keywords, 8 MeSH terms, 4 funders, 56 references.
Cite
This paper
Pranter, R., Patthey, C., & Feiner, N. (2026). Enrichment of Neural Crest Cells by Antibody Labeling and Flow Cytometry for Single-Cell Transcriptomics in a Lizard. Evolution & development, 28(1), e70030. https://
BibTeX
@article{pranter2026enri
author = {Pranter, Robin and Patthey, Cedric and Feiner, Nathalie},
title = {{Enrichment of Neural Crest Cells by Antibody Labeling and Flow Cytometry for Single-Cell Transcriptomics in a Lizard}},
journal = {Evolution \& development},
year = {2026},
month = mar,
volume = {28},
number = {1},
pages = {e70030},
publisher = {Wiley},
issn = {1520-541X},
doi = {10.1111/
url = {https://
pmid = {41709476},
pmcid = {PMC12917300}
}
RIS
TY - JOUR
AU - Pranter, Robin
AU - Patthey, Cedric
AU - Feiner, Nathalie
TI - Enrichment of Neural Crest Cells by Antibody Labeling and Flow Cytometry for Single-Cell Transcriptomics in a Lizard
T2 - Evolution & development
J2 - Evol Dev
PY - 2026
DA - 2026/
VL - 28
IS - 1
SP - e70030
SN - 1520-541X
PB - Wiley
DO - 10.1111/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1111/
"type": "article-journal",
"title": "Enrichment of Neural Crest Cells by Antibody Labeling and Flow Cytometry for Single-Cell Transcriptomics in a Lizard",
"container-title": "Evolution & development",
"author": [
{
"family": "Pranter",
"given": "Robin"
},
{
"family": "Patthey",
"given": "Cedric"
},
{
"family": "Feiner",
"given": "Nathalie"
}
],
"container-title-short":
"volume": "28",
"issue": "1",
"page": "e70030",
"DOI": "10.1111/
"PMID": "41709476",
"PMCID": "PMC12917300",
"ISSN": "1520-541X",
"publisher": "Wiley",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
1
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1038/s41467-026-70232-6 [code]
- Gene expression dynamics of human and mouse craniofacial development at the single-cell level.Journal: Nature communicationsIn common: SingleCellExperiment, Seurat, reshape2, 3 other tools, genetics / omics, 7 references
- [2] doi:10.1016/j.xcrm.2026.102766 [code]
- A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.Journal: Cell reports. MedicineIn common: SingleCellExperiment, car, Seurat, 4 other tools, genetics / omics, 3 references
- [3] doi:10.1038/s41593-026-02367-0 [code]
- A reproducible three-dimensional model of human brain tissue to investigate physiological and disease-associated microglia phenotypes.Journal: Nature neuroscienceIn common: SingleCellExperiment, Seurat, reshape2, 3 other tools, 3 references
- [4] doi:10.1016/j.stemcr.2026.102997 [code]
- BDNF regulates pituitary stem cell engagement toward precursor state.Journal: Stem cell reportsIn common: SingleCellExperiment, Seurat, reshape2, 3 other tools, 3 references
- [5] doi:10.1016/j.stemcr.2026.102967 [code]
- Single-cell multiomic approaches define a gradual, spatially regulated epigenetic and transcriptional transition from embryonic to adult neural stem cells.Journal: Stem cell reportsIn common: SingleCellExperiment, Seurat, patchwork, 2 other tools, developmental, genetics / omics, 3 references
- [6] doi:10.1371/journal.pcbi.1014424 [code]
- Combinatorial multiomic analysis from a pedigree of Sox10Dom Hirschsprung mice identifies multiple high confidence candidate modifiers of Enteric Nervous System development.Journal: PLoS computational biologyIn common: Seurat, reshape2, patchwork, 2 other tools, genetics / omics, 4 references
- [7] doi:10.1038/s41467-026-71595-6 [code]
- A single-cell and spatial atlas of early human olfactory development.Journal: Nature communicationsIn common: SingleCellExperiment, Seurat, reshape2, 3 other tools, genetics / omics, 2 references
- [8] doi:10.1038/s41586-026-10490-y [code]
- Lineage and organ signals sequentially build organ intrinsic nervous systems.Journal: NatureIn common: Seurat, reshape2, patchwork, 2 other tools, developmental, 3 references
- [9] doi:10.1038/s41593-026-02384-z [code]
- cGAS-mediated type I IFN signaling contributes to disease progression in drug-refractory epilepsy.Journal: Nature neuroscienceIn common: SingleCellExperiment, Seurat, reshape2, 3 other tools, 2 references
- [10] doi:10.1038/s41398-026-04200-5 [code]
- Postmortem brain single-nucleus and bulk gene expression analyses identify shared and distinct abnormalities in bipolar disorder and major depressive disorder.Journal: Translational psychiatryIn common: SingleCellExperiment, Seurat, reshape2, 3 other tools, genetics / omics, 2 references
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 2 repositories of the authors' code, each at its verified commit and with its license, 12 scripts, and 9 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:c9cc1c6db38a000d…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
