OSCR

Enrichment of Neural Crest Cells by Antibody Labeling and Flow Cytometry for Single-Cell Transcriptomics in a Lizard.

Code ↔ Paper

9 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 9 matches
  1. [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. [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. [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. [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. [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. [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. [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. [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. [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

  1. ---
  2. title: ''
  3. output: html_document
  4. date: "2025-12-03"
  5. ---
  6. ```{r setup, include=FALSE}
  7. knitr::opts_chunk$set(echo = TRUE)
  8. ```
  9. # Set up
  10. ```{r}
  11. options(future.globals.maxSize = 120000 * 1024^2) # Change this to fit your
  12. Sys.setenv(R_MAX_VSIZE = "120Gb") # computer
  13. rm(list=ls());gc()
  14. start_time <- Sys.time()
  15. library(Seurat, lib.loc = "/usr/local/lib/R/site-library") #Change these to
  16. library(glmGamPoi, lib.loc = "/usr/local/lib/R/site-library") #mach the location
  17. library(dplyr, lib.loc = "/usr/local/lib/R/site-library") #of your libraries
  18. library(ggplot2, lib.loc = "/usr/local/lib/R/site-library")
  19. library(patchwork, lib.loc = "/usr/local/lib/R/site-library")
  20. library(latex2exp, lib.loc = "/home/pranter/R/x86_64-pc-linux-gnu-library/4.5")
  21. library(ggrepel, lib.loc = "/usr/local/lib/R/site-library")
  22. library(ggbreak, lib.loc = "/home/pranter/R/x86_64-pc-linux-gnu-library/4.5")
  23. library(ggridges, lib.loc = "/usr/local/lib/R/site-library")
  24. library(stringr, lib.loc = "/usr/local/lib/R/site-library")
  25. path <- "~/WorkDirs/PmurNCCPilot_10X_rerun/"
  26. ```
  27. # Read filtered 10X data
  28. ```{r}
  29. filename <- list.files(paste0(path, "02_Analysis/"),
  30. pattern = "03_CompileAndFilter10X_out_")
  31. if (length(filename) == 1) {
  32. TenX.SO <- readRDS(file=paste0(path, "02_Analysis/", filename))
  33. } else {
  34. print(paste0("You have two files matching the pattern.",
  35. "Choose one to read and remove the other from the directory."))
  36. print(filename)
  37. }
  38. rm(filename)
  39. TenX.SO
  40. ```
  41. # Read filtered SmartSeq data
  42. ```{r}
  43. filename <- list.files(paste0(path,"02_Analysis/"),
  44. pattern = "02_FilterSmrtS_output_")
  45. if (length(filename) == 1) {
  46. SmrtS.SO <- readRDS(file = paste0(path, "02_Analysis/", filename))
  47. } else {
  48. print(paste0("You have two files matching the pattern. ",
  49. "Choose one to read and remove the other from the directory."))
  50. print(filename)
  51. }
  52. rm(filename)
  53. SmrtS.SO
  54. ```
  55. # Merge objects
  56. ```{r}
  57. # Select metadata columns
  58. met.cols <- c("orig.ident", "type", "nCount_RNA","nFeature_RNA",
  59. "percent.mt", "percent.rb")
  60. SmrtS.SO$type <- "Strictly sorted"
  61. [email hidden] <- [email hidden] %>% select(all_of(met.cols))
  62. [email hidden] <- [email hidden] %>% select(all_of(met.cols))
  63. rm(met.cols)
  64. #Restor seurat objects to non-normalized form
  65. DefaultAssay(SmrtS.SO) <- "RNA"
  66. SmrtS.SO <- DietSeurat(object = SmrtS.SO,
  67. layers = "counts",
  68. assays = "RNA")
  69. DefaultAssay(TenX.SO) <- "RNA"
  70. TenX.SO <- DietSeurat(object = TenX.SO,
  71. layers = "counts",
  72. assays = "RNA")
  73. #Merge
  74. full.SO <- merge(TenX.SO, c(SmrtS.SO))
  75. full.SO[["RNA"]] <- JoinLayers(full.SO[["RNA"]])
  76. # Fix the type column in meta data (mostly for plotting)
  77. [email hidden]$type <- factor([email hidden]$type,
  78. levels = c("Unsort", "Sorted",
  79. "Strictly sorted"))
  80. [email hidden] <- [email hidden] %>%
  81. mutate(type = recode(type,
  82. "Unsort" = "Unsorted",
  83. "Sorted" = "Leniently sorted"),
  84. type.short = recode(type,
  85. "Unsorted" = "U",
  86. "Leniently sorted" = "L",
  87. "Strictly sorted" = "S"))
  88. full.SO
  89. [email hidden] %>% colnames()
  90. ```
  91. # Basic stats
  92. ```{r}
  93. [email hidden] %>%
  94. group_by(type) %>%
  95. summarize(n = n(),
  96. av_count = mean(nCount_RNA) %>% round(),
  97. sd_count = sd(nCount_RNA) %>% round(),
  98. av_genes = mean(nFeature_RNA) %>% round(),
  99. sd_genes = sd(nFeature_RNA) %>% round()) %>%
  100. t()
  101. ```
  102. # Calc Cell Cycl
  103. ```{r}
  104. # temporary normalisation for CC-scoring
  105. full.SO <- SCTransform(full.SO,
  106. assay = 'RNA',
  107. new.assay.name = 'temp_SCT',
  108. vars.to.regress = c('percent.mt'),
  109. vst.flavor = "v2",
  110. variable.features.n = 3000) #3000 is default
  111. # Load ortholog table
  112. Ortho.df <- read.csv(file=paste0(path, "01_Data/",
  113. "Pmur1.0Human_OrthoTable_BioMartManDL20241206.txt"))
  114. # Save S and G2M markers in Pmur
  115. G2M.genes <- Ortho.df[Ortho.df$Human.gene.name %in%
  116. cc.genes.updated.2019$g2m.genes, ]$Gene.name
  117. S.genes <- Ortho.df[Ortho.df$Human.gene.name %in%
  118. cc.genes.updated.2019$s.genes, ]$Gene.name
  119. #Check that the markers are present in the data
  120. print(paste0(full.SO %>% Features() %in% G2M.genes %>% sum(), "/",
  121. G2M.genes %>% length(),
  122. " G2M-markers are present in the data"))
  123. print(paste0(full.SO %>% Features() %in% S.genes %>% sum(), "/",
  124. S.genes %>% length(),
  125. " S-markers are present in the data"))
  126. #Subset only the genes that are present
  127. G2M.genes <- G2M.genes[G2M.genes %in% Features(full.SO)]
  128. S.genes <- S.genes[S.genes %in% Features(full.SO)]
  129. # Predict cell cycle state (make sure to specify the "assay" parameter)
  130. full.SO <- CellCycleScoring(full.SO,
  131. s.features = S.genes,
  132. g2m.features = G2M.genes,
  133. assay = 'temp_SCT',
  134. set.ident = TRUE)
  135. rm(G2M.genes, S.genes); gc()
  136. ```
  137. # Plot QCs
  138. ```{r}
  139. PQC <- c("nCount_RNA", "nFeature_RNA", "percent.mt", "percent.rb") %>%
  140. lapply(function(feats){
  141. ggplot([email hidden], aes(x = type, y = .data[[feats]], fill = type)) +
  142. geom_violin() +
  143. scale_fill_manual(values = c("Unsorted" = "#BDBDBD",
  144. "Leniently sorted" = "#53AC90",
  145. "Strictly sorted" = "#64EC09")) +
  146. labs(y = c("nCount_RNA" = "n counts",
  147. "nFeature_RNA" = "n genes",
  148. "percent.mt" = "% mitochondrial",
  149. "percent.rb" = "% ribosomal")[feats], fill = "") +
  150. theme_classic() +
  151. theme(plot.margin = margin(t=1.7, r=1, b=0, l=0.4, unit = "mm"),
  152. axis.text.y = element_text(size = 8, angle = 45),
  153. axis.title.y = element_text(size = 11),
  154. axis.text.x = element_blank(),
  155. axis.title.x = element_blank(),
  156. axis.ticks.x = element_blank(),
  157. legend.text = element_text(size = 8),
  158. legend.key.size = unit(3, "mm"),
  159. legend.title = element_text(size = 11),
  160. plot.title = element_blank())
  161. }) %>%
  162. wrap_plots(ncol = 4) +
  163. plot_layout(guides = "collect") &
  164. theme(legend.position = "bottom")
  165. PQC
  166. ggsave(filename = paste0(path, "03_Results/QCPlot.svg"),
  167. plot = PQC, height = 50, width = 180, units = "mm")
  168. ```
  169. # Table for manuscript
  170. ```{r}
  171. [email hidden] %>% select("type", "nCount_RNA", "nFeature_RNA") %>%
  172. group_by(type) %>%
  173. summarize(n = n(),
  174. av_count = mean(nCount_RNA) %>% round(),
  175. sd_count = sd(nCount_RNA) %>% round(),
  176. av_genes = mean(nFeature_RNA) %>% round(),
  177. sd_genes = sd(nFeature_RNA) %>% round()) %>%
  178. t()
  179. ```
  180. # Standard processing
  181. ## Without integration
  182. ```{r}
  183. #DefaultAssay(full.SO) <- "RNA"
  184. #full.SO[["temp_SCT"]] <- NULL
  185. ## Normalize
  186. #full.SO <- SCTransform(full.SO,
  187. # assay = 'RNA',
  188. # new.assay.name = 'SCT',
  189. # vars.to.regress =c("percent.mt", "S.Score", "G2M.Score"),
  190. # vst.flavor = "v2",
  191. # variable.features.n = 3000)
  192. #
  193. ## Inspect the normalization
  194. #cbind(Matrix::rowSums(full.SO[["RNA"]]$counts)[
  195. # rownames(full.SO[["RNA"]]$counts) %in%
  196. # rownames(full.SO[["SCT"]]$data)],
  197. # Matrix::rowSums(full.SO[["SCT"]]$data)) %>%
  198. # as.data.frame() %>%
  199. # dplyr::rename(raw = V1, norm = V2) %>%
  200. # ggplot(aes(raw, norm)) +
  201. # geom_point() +
  202. # labs(title = "Normalized data vs raw counts (each dot is a gene)") +
  203. # theme(text = element_text(size = 6))
  204. #
  205. ## Inspect HVG selection
  206. #VariableFeaturePlot(full.SO, assay = "SCT") %>%
  207. # LabelPoints(points = VariableFeatures(full.SO, assay = "SCT") %>% head(20),
  208. # repel = TRUE,
  209. # xnudge = 0, ynudge = 0, max.overlaps = 22) +
  210. # theme(text = element_text(size = 6))
  211. #
  212. ## Lin dim reduc
  213. #full.SO <- RunPCA(full.SO, assay = "SCT")
  214. #ElbowPlot(full.SO, reduction = "pca", ndims = 50)
  215. #
  216. #Non-lin dim reduc
  217. #full.SO <- RunUMAP(full.SO, dims = 1:20)#, spread = 0.4, min.dist = 0.4)
  218. # # dims = 11 seems good judgeing by the elbowplot and PC-heatmaps
  219. # # Changing the min.dist dramatically changes the umap. This requires some
  220. # # optimaization. Come back to this later.
  221. #
  222. ##Plot
  223. #DimPlot(full.SO, reduction = "umap", group.by = "type",
  224. # shuffle = TRUE, alpha = 0.5) + ggtitle("No integration")
  225. ##DimPlot(full.SO, group.by = "orig.ident", shuffle = TRUE, alpha = 0.5,
  226. ## cells = Cells(subset(full.SO, subset = type.short == "L")))
  227. ```
  228. ## With integration
  229. See insturctions here: https://github.com/satijalab/seurat/issues/7542
  230. and here: https://satijalab.org/seurat/articles/seurat5_integration
  231. ```{r}
  232. # Normalize each sample separately
  233. full.SO[["RNA"]] <- split(full.SO[["RNA"]], f = full.SO$orig.ident)
  234. DefaultAssay(full.SO) <- "RNA"
  235. full.SO <- SCTransform(full.SO,
  236. assay = "RNA",
  237. new.assay.name = "SCT_BySample",
  238. vars.to.regress =c("percent.mt", "G2M.Score", "S.Score"),
  239. vst.flavor = "v2",
  240. variable.features.n = 3000) %>%
  241. # Calculate PCA
  242. RunPCA(assay = "SCT_BySample", reduction.name = "pca_SCT_BySample") %>%
  243. # Integrate data sets
  244. IntegrateLayers(method = HarmonyIntegration,
  245. orig.reduction = "pca_SCT_BySample",
  246. new.reduction = 'harmony',
  247. assay = "SCT_BySample",
  248. normalization.method = "SCT",
  249. verbose = FALSE) %>%
  250. # Calc umap
  251. RunUMAP(dims = 1:30, reduction = "harmony", reduction.name = "umap_harmony")
  252. ```
  253. # Plot sort types in umap
  254. ```{r}
  255. P01 <- DimPlot(full.SO,
  256. reduction = "umap_harmony", group.by = "type",
  257. order = c("Strictly sorted", "Leniently sorted", "Unsorted"),
  258. alpha = 0.5, stroke.size = 0, pt.size = 1) +
  259. scale_color_manual(values = c("Unsorted" = "#BDBDBD",
  260. "Leniently sorted" = "#53AC90",
  261. "Strictly sorted" = "#64EC09")) +
  262. labs(y = "umap 2", x = "umap 1") +
  263. theme(plot.margin = margin(t=1.7, r=1, b=1.7, l=0.4, unit = "mm"),
  264. axis.text.y = element_text(size = 8, angle = 45),
  265. axis.title.y = element_text(size = 11),
  266. axis.text.x = element_text(size = 8, angle = 45),
  267. axis.title.x = element_text(size = 11),
  268. legend.text = element_text(size = 8),
  269. legend.key.size = unit(2.5, "mm"),
  270. legend.position = "inside",
  271. plot.title = element_blank())
  272. P01
  273. ggsave(paste0(path, "03_Results/UMAP_SortType.svg"),
  274. P01, height = 89, width = 89, units = "mm")
  275. ```
  276. # Plot marker exp in umap
  277. ```{r}
  278. # First normalize across samples to correct for sequencing depth
  279. full.SO[["RNA"]] <- JoinLayers(full.SO[["RNA"]])
  280. full.SO <- SCTransform(full.SO,
  281. assay = "RNA",
  282. new.assay.name = "SCT",
  283. vars.to.regress =c("percent.mt", "G2M.Score", "S.Score"),
  284. vst.flavor = "v2",
  285. variable.features.n = 3000)
  286. # It also seems to work to do PrepSCTFindMarkers
  287. ```
  288. ```{r}
  289. # Then plor using FeaturePlot
  290. P02 <- FeaturePlot(full.SO, c("SOX10", "TFAP2A",
  291. "SNAI2", "FOXD3"#,
  292. #"PAX7", "SOX9", "TWIST1", "PAX3", "GAPDH"
  293. ),
  294. order = TRUE, pt.size = 1, alpha = 0.5, keep.scale = "all") &
  295. NoAxes() &
  296. theme(legend.key.size = unit(3, "mm"),
  297. legend.text = element_text(size = 8))
  298. #Remove stroke arround points
  299. P02 <- lapply(P02, function(p) {
  300. p$layers[[1]]$aes_params$stroke <- 0
  301. old_title <- p$labels$title
  302. #Chance title font
  303. p <- p + ggtitle(str_to_sentence(old_title)) +
  304. theme(plot.title = element_text(face = "italic"))
  305. p
  306. })
  307. #Tidy up
  308. P02 <- wrap_plots(P02, ncol = 2, guides = "collect") &
  309. FontSize(main = 11) +
  310. NoAxes()
  311. P02
  312. ggsave(paste0(path, "03_Results/UMAP_MrkrExp.svg"),
  313. P02, height = 89, width = 89, units = "mm")
  314. ```
  315. # Calc NCC-ness score
  316. ```{r}
  317. full.SO <- AddModuleScore(object = full.SO,
  318. features = list(c("PAX3", "PAX7", "FOXD3", "SOX10",
  319. "SOX9", "WNT1", "TFAP2A", "SOX5",
  320. "SNAI2", "ZIC1")),
  321. name = "NCC_AMS",
  322. ctrl = 100)
  323. [email hidden] %>%
  324. select(type, NCC_AMS1) %>%
  325. group_by(type) %>%
  326. summarize(avg_NCCAMS = median(NCC_AMS1)) %>%
  327. t()
  328. wilcox.test(x = subset(full.SO, subset = type == "Strictly sorted")$NCC_AMS1,
  329. y = subset(full.SO, subset = type == "Leniently sorted")$NCC_AMS1)
  330. wilcox.test( x = subset(full.SO, subset = type == "Strictly sorted")$NCC_AMS1,
  331. y = subset(full.SO, subset = type == "Unsorted")$NCC_AMS1)
  332. wilcox.test( x = subset(full.SO, subset = type == "Leniently sorted")$NCC_AMS1,
  333. y = subset(full.SO, subset = type== "Unsorted")$NCC_AMS1)
  334. ```
  335. # NCC markers
  336. ## Def NCCs in unsorted samp
  337. ```{r}
  338. unsort.SO <- full.SO %>%
  339. subset(cells = Cells(subset(full.SO, subset = type == "Unsorted")))
  340. # Extract SOX10 expression (RNA assay, default data slot)
  341. sox10_expr <- GetAssayData(unsort.SO, assay = "SCT", layer = "data")["SOX10", ]
  342. # Create NCC classification
  343. unsort.SO$NCC <- ifelse(sox10_expr > 0, "NCC", "Other")
  344. rm(sox10_expr); gc()
  345. # Optionally make it a factor with defined order
  346. unsort.SO$NCC <- factor(unsort.SO$NCC, levels = c("Other", "NCC"))
  347. unsort.SO$NCC %>% table()
  348. ```
  349. ## Plot unsort samp in umap
  350. ```{r}
  351. Idents(unsort.SO) <- unsort.SO$type
  352. P03 <- DimPlot(unsort.SO,
  353. reduction = "umap_harmony", group.by = "NCC",
  354. order = c("NCC", "Other"),
  355. alpha = 0.7, stroke.size = 0, pt.size = 1) +
  356. scale_color_manual(values = c("Other" = "#BDBDBD",
  357. "NCC" = "#ffc64fff")) +
  358. labs(y = "umap 2", x = "umap 1") +
  359. theme(plot.margin = margin(t=1.7, r=1, b=1.7, l=0.4, unit = "mm"),
  360. axis.text.y = element_text(size = 8, angle = 45),
  361. axis.title.y = element_text(size = 11),
  362. axis.text.x = element_text(size = 8, angle = 45),
  363. axis.title.x = element_text(size = 11),
  364. legend.text = element_text(size = 11),
  365. legend.key.size = unit(2.5, "mm"),
  366. legend.title = element_text(size = 11),
  367. legend.position = "inside",
  368. plot.title = element_blank())
  369. P03
  370. ggsave(paste0(path, "03_Results/UMAP_Unsort.svg"),
  371. P03, height = 89, width = 89, units = "mm")
  372. ```
  373. ```{r}
  374. P03_inset <- FetchData(unsort.SO,
  375. vars = c("SOX10", "nCount_RNA"),
  376. assay = "RNA,",
  377. layer = "count") %>%
  378. mutate(Sox10_PM = SOX10 / (nCount_RNA / 1e6),
  379. logSox10_PM = log1p(Sox10_PM)) %>%
  380. ggplot(aes(x = logSox10_PM, fill = SOX10 == 0)) +
  381. geom_histogram(binwidth = 1) +
  382. scale_x_continuous(breaks = log1p(c(0, 200, 800)),
  383. labels = c("0", "200", "800")) +
  384. scale_y_break(breaks = c(150, 10450)) +
  385. scale_y_continuous(breaks = c(0, 100, 10500, 10600),
  386. labels = c("0", "100", "10500", "10600"),
  387. limits = c(0, 10610)) +
  388. scale_fill_manual(values = c(`TRUE` = "#BDBDBD", # bar at 0
  389. `FALSE` = "#ffc64fff"), # non-zero bars
  390. guide = "none") +
  391. #labs(x = "Sox10 per 1M", y = "Freq.") +
  392. theme_classic() +
  393. theme(plot.margin = margin(t=0, r=0, b=0, l=0),
  394. axis.text.y.right = element_blank(),
  395. axis.ticks.y.right = element_blank(),
  396. axis.line.y.right = element_blank(),
  397. axis.title = element_blank(),
  398. axis.text.x = element_text(size = 8, angle = 45, hjust = 1),
  399. axis.text.y = element_text(size = 8, angle = 45, vjust = 0.5))
  400. ggsave(paste0(path, "03_Results/UMAP_Unsort_hist.svg"),
  401. P03_inset, height = 35, width = 40, units = "mm")
  402. P03_inset
  403. ```
  404. ## Calc diff. exp.
  405. This does differential expression testing between NCCs (Sox10 positive cells)
  406. and all other cells in the unsorted samples.
  407. ```{r}
  408. Idents(unsort.SO) <- unsort.SO$NCC
  409. DEG.df <- FindMarkers(unsort.SO,
  410. ident.1 = "NCC",
  411. only.pos = FALSE,
  412. logfc.threshold = 0,
  413. min.pct = 0)
  414. DEG.df$gene <- rownames(DEG.df)
  415. #Add average normalized expression in NCCs to the dataframe
  416. avg_NCC_exp <- unsort.SO %>%
  417. subset(subset = NCC == "NCC") %>%
  418. GetAssayData(assay = "SCT", layer = "counts") %>%
  419. rowMeans()
  420. DEG.df <- DEG.df %>% mutate(avg_NCC_exp = avg_NCC_exp[rownames(DEG.df)])
  421. rm(avg_NCC_exp); gc()
  422. # Add negative log10 p column
  423. DEG.df$neg_log10p <- log10(DEG.df$p_val)*-1
  424. DEG.df %>% head()
  425. DEG.df %>% str()
  426. ```
  427. ## Def NCC markers
  428. ```{r}
  429. #Subset DE table
  430. NCCmrkrs.df <- DEG.df %>% #Use only:
  431. subset(avg_log2FC > 0.1) %>% # -Genes with relevant effect size
  432. subset(p_val_adj <= 0.05) %>% # -Significantly different genes
  433. subset(avg_NCC_exp > 0.05) #%>% # -Genes with informative mean exp in NCCs
  434. #subset(pct.1 >= 0.01)
  435. #Add column to label the NCC markers in DEG.df
  436. DEG.df$NCCmrkrs <- ifelse(DEG.df$gene %in% NCCmrkrs.df$gene, "Yes", "No")
  437. ##Save table for supplementary as .csv
  438. #DEG.df %>%
  439. # #Select the rellevant columns
  440. # select(gene, avg_log2FC, avg_NCC_exp, p_val_adj, NCCmrkrs) %>%
  441. # #Reorder the rows to make it easier to find the markers at a glance
  442. # arrange(factor(NCCmrkrs, levels = c("Yes", "No")),
  443. # p_val_adj,
  444. # desc(avg_log2FC)
  445. # ) %>%
  446. # # Round off all values
  447. # mutate(avg_log2FC = round(avg_log2FC, 3),
  448. # avg_NCC_exp = round(avg_NCC_exp, 3),
  449. # p_val_adj = case_when(
  450. # p_val_adj < 0.001 ~ "<0.001",
  451. # p_val_adj > 0.001 ~ as.character(round(p_val_adj, 3)))) %>%
  452. # # rename the columns for readability
  453. # rename("Gene" = gene,
  454. # "Average log2-fold change" = avg_log2FC,
  455. # "Average SCT counts in NCCs" = avg_NCC_exp,
  456. # "Adjusted p-value" = p_val_adj,
  457. # "NCC markers" = NCCmrkrs) %>%
  458. # write.csv(paste0(path, "03_Results/",
  459. # "DiffExpAll_", Sys.Date(), ".csv"),
  460. # row.names = FALSE)
  461. ```
  462. ## Plotting
  463. Here i plot differential expression in a few different ways for one of the
  464. figures in the paper.
  465. ## MA plot
  466. ```{r}
  467. #Plot
  468. P04 <- DEG.df %>%
  469. mutate(avg_log2FC = ifelse(avg_log2FC > 5, 5, avg_log2FC)) %>%
  470. mutate(avg_log2FC = ifelse(avg_log2FC < -5, -5, avg_log2FC)) %>%
  471. mutate(avg_NCC_exp = ifelse(avg_NCC_exp > 10, 10, avg_NCC_exp)) %>%
  472. arrange(NCCmrkrs == "Yes") %>%
  473. ggplot(aes(y = avg_log2FC, x = avg_NCC_exp, color = NCCmrkrs)) +
  474. geom_point(shape = 19, size = .7, alpha = .7) +
  475. scale_x_continuous(trans = scales::log1p_trans()) +
  476. scale_color_manual(values = c("Yes" = "#ffc64fff", "No" = "#BDBDBD")) +
  477. ylab(label = TeX('$log_{2}$(fold change)')) +
  478. xlab(label = "Mean expressin in putative NCCs, log(x+1)")+
  479. labs(title = "Differential expression",
  480. color = "NCC markers") +
  481. theme(plot.title = element_blank(),
  482. axis.title.y = element_text(size = 11),
  483. axis.title.x = element_text(size = 11),
  484. axis.text.y = element_text(size = 8),
  485. axis.text.x = element_text(size = 8),
  486. legend.title = element_text(size = 8),
  487. legend.key.size = unit(2.5, "mm"),
  488. legend.position = "none",
  489. #Background
  490. plot.background = element_rect(fill = "white", color = "white"),
  491. panel.background = element_rect(fill = "white", color = "white"),
  492. panel.border = element_rect(colour = "black", fill = NA)) +
  493. geom_vline(xintercept = .05, linetype = "dashed") +
  494. geom_hline(yintercept = .2, linetype = "dashed")
  495. P04
  496. ggsave(filename = paste0(path, "03_Results/MAPlot.svg"),
  497. plot = P04, height = 89, width = 89, units = "mm")
  498. ```
  499. ## Volcano plot
  500. ### Lebels
  501. ```{r}
  502. # Manually set some selected genes to label
  503. Volcano_labels <- c("SOX10", "EDNRB", "TFAP2A", "TFAP2B", "ZEB2",
  504. "PAX7", "ETS1", "SOX8", "SOX5",
  505. "GYPC", "ACBD7", "RAB19")
  506. Volcano_labels <- NCCmrkrs.df[Volcano_labels, ]
  507. Volcano_labels <- Volcano_labels %>%
  508. mutate(avg_log2FC = ifelse(avg_log2FC > 7, 7, avg_log2FC)) %>%
  509. mutate(avg_log2FC = ifelse(avg_log2FC < -7, -7, avg_log2FC)) %>%
  510. mutate(neg_log10p = ifelse(neg_log10p > 100, 100, neg_log10p))
  511. Volcano_labels
  512. ```
  513. ### Plot
  514. ```{r}
  515. # Set line for p value
  516. sig_line <- DEG.df %>%
  517. arrange(NCCmrkrs == "Yes") %>% {log10(0.05/nrow(.))*-1}
  518. #Construct the plot
  519. P05 <- DEG.df %>%
  520. mutate(avg_log2FC = ifelse(avg_log2FC > 7, 7, avg_log2FC)) %>%
  521. mutate(avg_log2FC = ifelse(avg_log2FC < -7, -7, avg_log2FC)) %>%
  522. mutate(neg_log10p = ifelse(neg_log10p > 100, 100, neg_log10p)) %>%
  523. arrange(NCCmrkrs == "Yes") %>%
  524. ggplot(aes(x = avg_log2FC, y = neg_log10p, color = NCCmrkrs)) +
  525. geom_point(shape = 19, size = .7, alpha = .7) +
  526. geom_vline(xintercept = 0.2, linetype = "dashed") +
  527. geom_hline(yintercept = sig_line, linetype = "dashed") +
  528. scale_color_manual(values = c("Yes" = "#ffc64fff", "No" = "#BDBDBD")) +
  529. ylab(label = TeX('$-log_{10}$(adj. p-value)')) +
  530. xlab(label = TeX('$log_{2}$(fold change)')) +
  531. labs(title = "NCC markers",
  532. color = "NCC markers") +
  533. geom_label_repel(data = Volcano_labels,
  534. #Italic lowercase gene names
  535. aes(label = paste0("italic(", str_to_sentence(gene), ")")),
  536. parse = TRUE,
  537. color = "black",
  538. max.overlaps = 20,
  539. nudge_x = -4,
  540. size = 3,
  541. label.padding = 0.1,
  542. label.r = .1) +
  543. theme(plot.title = element_blank(),
  544. axis.title.y = element_text(size = 11),
  545. axis.title.x = element_text(size = 11),
  546. axis.text.y = element_text(size = 8),
  547. axis.text.x = element_text(size = 8),
  548. #Background
  549. plot.background = element_rect(fill = "white", color = "white"),
  550. panel.background = element_rect(fill = "white", color = "white"),
  551. panel.border = element_rect(colour = "black", fill = NA),
  552. legend.position = "none")
  553. P05
  554. ggsave(filename = paste0(path, "03_Results/VolcanoPlot.svg"),
  555. plot = P05, height = 89, width = 89, units = "mm")
  556. ```
  557. ```{r}
  558. P05 + geom_point(
  559. data = DEG.df %>% filter(gene == "GYPC"), # Change gene to label the point
  560. aes(x = avg_log2FC, y = neg_log10p), # of your choice
  561. color = "red", size = 2)
  562. ```
  563. # Module score new NCC markers
  564. ```{r}
  565. full.SO <- AddModuleScore(full.SO,
  566. list(NCCmrkrs.df$gene),
  567. #Or, excluding Sox10:
  568. #list(NCCmrkrs.df$gene[2:length(NCCmrkrs.df$gene)]),
  569. name = "NewNCCmrkrsAMD")
  570. ```
  571. ```{r}
  572. P06 <- [email hidden] %>%
  573. ggplot(aes(x = type, fill = type, y = NewNCCmrkrsAMD1)) +
  574. geom_violin() +
  575. scale_fill_manual(values = c("Unsorted" = "#BDBDBD",
  576. "Leniently sorted" = "#53AC90",
  577. "Strictly sorted" = "#64EC09")) +
  578. labs(y = "NCC marker module score") +
  579. theme_classic() +
  580. theme(axis.title.x = element_blank(),
  581. axis.title.y = element_text(size = 11),
  582. axis.text = element_text(size = 8),
  583. legend.position = "none")
  584. ggsave(filename = paste0(path, "03_Results/NCCmrkrVln.svg"),
  585. plot = P06, height = 89, width = 89, units = "mm")
  586. P06
  587. ```
  588. # Save data
  589. Save the filtered data and meta data in an RDS file to be read by the next script in the pipeline (04_IntAnalysis10XAndSmrtS.Rmd)
  590. ```{r}
  591. full.SO
  592. saveRDS(full.SO, paste0(path,
  593. "02_Analysis/04_IntAnalysis_output_",
  594. Sys.Date(),
  595. ".Rds"))
  596. ```
  597. Calculated runtime:
  598. ```{r}
  599. end_time <- Sys.time()
  600. paste0("Elapsed time: ", end_time - start_time)
  601. ```

04_IntAnalysis10XAndSmrtS.Rmd at commit 11c8df9, no license · at the source

Overview

Authors: Robin Pranter1,2, Cedric Patthey3, Nathalie Feiner1,2
  1. Department of Biology, Lund University, Lund, Sweden
  2. Current address: Max Planck Institute for Evolutionary Biology, Plön, Germany
  3. Department of Diagnostic and Intervention, Umeå University, Umeå, Sweden
Journal: Evolution & development, volume 28, issue 1, article e70030
Dates: received 20 May 2025; accepted 4 February 2026; published online 18 February 2026; in print March 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1111/ede.70030 · PMID 41709476 · PMCID PMC12917300 · OpenAlex W7130504013
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), other (modality), other (organism), developmental (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions
Keywords: cell types, fluorescence‐activated cell sorting, HNK‐1 antibody, non‐model organism, scRNA‐seq, transcriptional profiles
MeSH: Flow Cytometry*, Lizards*, Neural Crest*, Single-Cell Analysis*, Transcriptome*, Animals, Antibodies, Single-Cell Gene Expression Analysis (* major topic)
Topic: Developmental Biology and Gene Regulation (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: Vetenskapsrådet (2020‐03650, 2020-03650); European Research Council (948126); Kungliga Fysiografiska Sällskapet i Lund (42010); Jörgen Lindströms stipendiefond
Citations: not cited yet (Europe PMC); 62 references in the paper

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

License: CC-BY-4.0
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Data Availability Statement”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
  • 30 September 2026: the link answers (HTTP 200)
At the source:

robinpranter/enrichment-of-neural-crest-cells---supplementary-code

License: none: the authors keep all their rights
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 11c8df99b76d3231d3fb5ba905b1e4adea11c4c7, 6 February 2026
Languages: R (12)
Size: 128 files, 12 scripts
Software Heritage: not archived
Found in: the Zenodo archive record
Holds: README, 8 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: tidyverse (12 files), Seurat (9 files), ggplot2 (7 files), SingleCellExperiment (4 files), patchwork (3 files), car (1 file), emmeans (1 file), reshape2 (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
13 files

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

Data Availability Statement

All sequence data generated in this study have been deposited in NCBI GEO with accession number GSE319069 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE319069). Code to reproduce the results presented in this study are deposited at Zenodo together with qPCR and flow cytometry data DOI:10.5281/zenodo.18544211.

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://doi.org/10.1111/ede.70030

BibTeX

@article{pranter2026enrichment,
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/ede.70030},
url = {https://doi.org/10.1111/ede.70030},
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/03/01
VL - 28
IS - 1
SP - e70030
SN - 1520-541X
PB - Wiley
DO - 10.1111/ede.70030
UR - https://doi.org/10.1111/ede.70030
LA - en
ER -

CSL-JSON

{
"id": "10.1111/ede.70030",
"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": "Evol Dev",
"volume": "28",
"issue": "1",
"page": "e70030",
"DOI": "10.1111/ede.70030",
"PMID": "41709476",
"PMCID": "PMC12917300",
"ISSN": "1520-541X",
"publisher": "Wiley",
"URL": "https://doi.org/10.1111/ede.70030",
"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 communications
In 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. Medicine
In 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 neuroscience
In 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 reports
In 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 reports
In 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 biology
In 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 communications
In 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: Nature
In 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 neuroscience
In 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 psychiatry
In 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.

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.