OSCR

Generation of human appetite-regulating neurons and tanycytes from pluripotent stem cells.

Code ↔ Paper

17 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 17 matches
  1. [1] § STAR★Methods › Method details › Sequence alignment and sample assignment ↔ 01_d16_processing_annotation.ipynb, lines 336–405 · score 0.79 · HTODemux, CITE seq, single cell, d16, Seurat, hashing
  2. [2] § STAR★Methods › Method details › Trajectory inference ↔ 10_tanycyte_monocle3_pseudotime.ipynb, lines 289–347 · score 0.78 · polynomial fitting, tanycyte lineage, Monocle3, pseudotime, Gene expression, polyfit
  3. [3] § STAR★Methods › Method details › Sequence alignment and sample assignment ↔ 03_d25_d50_d70_processing.ipynb, lines 380–526 · score 0.77 · HTODemux, CITE seq, single cell, Seurat, hashing, v1
  4. [4] § Results › Duration of BMP stimulation controls ARC versus VMH identity ↔ 14_d16_bmp_annotation.ipynb, lines 107–154 · score 0.74 · anterior tuberal progenitors, posterior tuberal progenitors, NR5A1, ARX, LHX1, telencephalic
  5. [5] § Results › Duration of BMP stimulation controls ARC versus VMH identity ↔ 15_d50+_bmp_annotation.ipynb, lines 228–289 · score 0.72 · NR5A1, FEZF1, ARX, LHX1, LHX8, GPR149
  6. [6] § Results › In vitro-derived ARC cultures show transcriptional similarity to the human ARC ↔ 07_d50_d70_analysis.ipynb, lines 626–653 · score 0.71 · DLX6 AS1, NR5A2, CRABP1, FOXP2, NPFFR2, TRH
  7. [7] § Results › In vitro-derived ARC cultures show transcriptional similarity to the human ARC ↔ 15_d50+_bmp_annotation.ipynb, lines 228–289 · score 0.71 · DLX6 AS1, NR5A2, BNC2, FOXP2, NPFFR2, PRDM12
  8. [8] § Results › Different POMC subtypes are dependent on BMP timing ↔ 14_d16_bmp_annotation.ipynb, lines 107–154 · score 0.69 · anterior tuberal progenitors, posterior tuberal progenitors, NR5A1, ventral, PRDM12, SOX14
  9. [9] § Results › In vitro-derived tanycytes map to the β2 subtype and respond to FGF1 ↔ 10_tanycyte_monocle3_pseudotime.ipynb, lines 289–347 · score 0.68 · COL25A1, tanycytic lineage, Pseudotime, CRYM, SOX2, NFIA
  10. [10] § STAR★Methods › Method details › sc/snRNA-seq processing and clustering ↔ 03_d25_d50_d70_processing.ipynb, lines 616–697 · score 0.66 · scDblFinder, log normalized, d25, doublets, hashed, d50
  11. [11] § Results › In vitro-derived ARC cultures show transcriptional similarity to the human ARC ↔ 04_d25_annotation_analysis.ipynb, lines 163–192 · score 0.64 · DLX6 AS1, NR5A2, DIO2, ONECUT1, NFIA, OTP
  12. [12] § STAR★Methods › Method details › Transcriptomic comparison with human data ↔ 16_bmp_analysis.ipynb, lines 959–1014 · score 0.62 · NR5A1, NR5A2, POMC subtypes, TBX3, VMH, human
  13. [13] § STAR★Methods › Method details › sc/snRNA-seq processing and clustering ↔ 01_d16_processing_annotation.ipynb, lines 498–568 · score 0.62 · scDblFinder, log normalized, doublets, hashed, d16, clustering
  14. [14] § STAR★Methods › Method details › sc/snRNA-seq processing and clustering ↔ 04_d25_annotation_analysis.ipynb, lines 33–77 · score 0.57 · d25, RPCA, Seurat, selection, neighbor, UMAP
  15. [15] § Results › Different POMC subtypes are dependent on BMP timing ↔ 16_bmp_analysis.ipynb, lines 959–1014 · score 0.56 · NR5A1, NR5A2, DEGs, SOX14, TBX3, VMH
  16. [16] § STAR★Methods › Method details › sc/snRNA-seq processing and clustering ↔ 05_d50_d70_annotation.ipynb, lines 127–167 · score 0.55 · RPCA, Seurat, selection, neighbor, d50, UMAP
  17. [17] § STAR★Methods › Method details › Differential gene expression analysis ↔ 16_bmp_analysis.ipynb, lines 854–921 · score 0.54 · glmQLFTest, Seurat, batch, model, matrix, filtered

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

Jupyter notebook · 1,077 lines · 38 KB · no license · 3 matches

  1. # %%
  2. import scanpy as sc
  3. import pandas as pd
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. import seaborn as sns
  7. pd.set_option('display.max_columns', 500)
  8. import warnings
  9. warnings.filterwarnings("ignore")
  10. from matplotlib.lines import Line2D
  11. from rpy2.robjects import pandas2ri
  12. from rpy2.robjects import r
  13. import rpy2.rinterface_lib.callbacks
  14. import anndata2ri
  15. import rpy2.robjects.numpy2ri
  16. #import numpy2ri
  17. import anndata
  18. from matplotlib.ticker import MaxNLocator
  19. pandas2ri.activate()
  20. anndata2ri.activate()
  21. rpy2.robjects.numpy2ri.activate()
  22. import matplotlib.lines as mlines
  23. plt.rcParams.update({
  24. 'font.family': 'Arial'
  25. })
  26. # Function determining cutoff for cell positive for marker
  27. from sklearn.mixture import GaussianMixture as GMM
  28. def expression_cutoff(gene, adata_temp):
  29. data = adata_temp[: , gene].X.toarray()
  30. gmm = GMM(n_components=2).fit(data)
  31. labels = gmm.predict(data)
  32. df = pd.DataFrame({'expression': data.ravel(), 'label': labels})
  33. label0 = df[df['label'].isin([0])]['expression'].values
  34. label1 = df[df['label'].isin([1])]['expression'].values
  35. #print(label0.min())
  36. if label0.min() > label1.min():
  37. return label0.min()
  38. return label1.min()
  39. %load_ext rpy2.ipython
  40. # %%
  41. adata_early = sc.read('../../Data/SC/parse_annotated_early_stage.h5ad')
  42. # %%
  43. adata_early.obs
  44. # %%
  45. adata_early.obs[['sample','cell_line','bmp_treatment']].value_counts()
  46. # %%
  47. bmp_dict = {'no BMP_BMP 25-50':'no BMP early/late', 'no BMP':'no BMP4', 'BMP 5-7':'BMP4 5-7', 'BMP 5-9':'BMP4 5-9', 'BMP 5-11':'BMP4 5-11','BMP 5-14':'BMP4 5-14'}
  48. adata_early.obs['bmp_treatment'] = adata_early.obs['bmp_treatment'].map(bmp_dict)
  49. adata_temp = adata_early[adata_early.obs.sample(frac=1, random_state=42).index].copy()
  50. with plt.rc_context({"figure.dpi": 300}):
  51. sc.pl.umap(adata_temp, color='bmp_treatment', frameon=False, size=10, save='_bmp_d16_timing.pdf')
  52. # %%
  53. adata_temp.uns['bmp_treatment_colors']
  54. # %% [markdown]
  55. # # Early stage
  56. # %% [markdown]
  57. # ## BArplot
  58. # %%
  59. count_l, count_dict = [], {}
  60. for sample in adata_early.obs.bmp_treatment.cat.categories.tolist():
  61. count_l = []
  62. for cell_type in adata_early.obs.Cell_types.cat.categories.tolist():
  63. count_l.append(adata_early[adata_early.obs['Cell_types'] == cell_type].obs['bmp_treatment'].value_counts().reindex(adata_early.obs.bmp_treatment.cat.categories, fill_value=0)[sample])
  64. count_l = [i/sum(count_l) for i in count_l]
  65. count_dict[sample] = count_l
  66. df = pd.DataFrame.from_dict(count_dict, orient='index', columns=adata_early.obs.Cell_types.cat.categories.tolist())
  67. df.loc[-1] = adata_early.uns['Cell_types_colors']
  68. df.index = ['color' if x==-1 else x for x in list(df.index)]
  69. # Sort the DF
  70. df = df[df.loc['no BMP4'].sort_values(ascending=False).index]
  71. df
  72. # %%
  73. bmp_conditions = df.iloc[:-1].index.tolist()
  74. # Create a subplot with 1 row and 4 columns
  75. fig, axes = plt.subplots(1, 5, figsize=(14, 5), dpi=400)
  76. for i, bmp in enumerate(bmp_conditions):
  77. df_flipped = df.iloc[:-1].loc[bmp].reset_index()
  78. df_flipped.columns = ['Cell_Type', 'Percentage']
  79. # Create the barplot on the respective axis
  80. sns.barplot(
  81. data=df_flipped,
  82. y="Cell_Type", # Cell types on the y-axis
  83. x="Percentage", # Percentages on the x-axis
  84. palette=df.loc['color'].values,
  85. ax=axes[i] # Specify the axis for each plot
  86. )
  87. # Set the title and other plot customizations
  88. axes[i].set_title(bmp, fontsize=22)
  89. axes[i].set_xlabel("")
  90. axes[i].set_ylabel("")
  91. cell_type_colors = dict(zip(df.columns, df.iloc[-1]))
  92. axes[i].tick_params(axis='x', labelsize=15)
  93. axes[i].tick_params(axis='y', labelsize=20)
  94. # Add a vertical color column next to the y-ticks in the first subplot
  95. #if i == 0:
  96. # ytick_positions = axes[i].get_yticks()
  97. # for y_pos, cell_type in zip(ytick_positions, df_flipped["Cell_Type"]):
  98. # color = cell_type_colors.get(cell_type, "black") # Get color or default to black
  99. # axes[i].add_patch(plt.Rectangle((-0.055, y_pos - 0.4), 0.03, 0.8, color=color, transform=axes[i].transData, clip_on=False))
  100. # axes[i].tick_params(axis='y', pad=11)
  101. # axes[i].tick_params(axis='y', length=3.5, width=2)
  102. if i != 0:
  103. axes[i].tick_params(axis='y', which='both', length=0) # Remove y-ticks
  104. axes[i].set_yticklabels([]) # Remove y-tick labels
  105. axes[i].set_xticks([0.2,0.4,0.6])
  106. axes[i].set_xlim(0,0.7)
  107. # Adjust layout and show the plot
  108. plt.tight_layout(pad=0.2)
  109. plt.savefig('figures/BMP_d16_cluster_proportions.pdf')
  110. plt.show()
  111. # %%
  112. adata_early.obs["Cell_types"] = pd.Categorical(
  113. values=adata_early.obs.Cell_types, categories=cell_type_colors.keys(), ordered=True
  114. )
  115. with plt.rc_context({"figure.dpi": 300}):
  116. sc.pl.umap(adata_early, color='Cell_types', palette = list(cell_type_colors.values()) ,frameon=False, size=10,save='_d16_legend.pdf' )
  117. # %%
  118. with plt.rc_context({"figure.dpi": 300}):
  119. sc.pl.umap(adata_early, color='cell_line' ,frameon=False, size=10 )
  120. # %%
  121. adata_arc_d16 = adata_early[(adata_early.obs.day == 'd16') & (adata_early.obs.bmp_treatment == 'BMP4 5-14')]
  122. # Group by 'diff_batch' and 'Cell_types' and count the number of occurrences
  123. counts = adata_arc_d16.obs.groupby(['cell_line', 'Cell_types']).size().reset_index(name='counts')
  124. # Calculate the total counts per batch
  125. totals = adata_arc_d16.obs.groupby('cell_line').size().reset_index(name='total_counts')
  126. # Merge the counts with the totals
  127. counts = counts.merge(totals, on='cell_line')
  128. # Normalize the counts
  129. counts['normalized_counts'] = counts['counts'] / counts['total_counts']
  130. counts['normalized_counts'] = counts['normalized_counts'].mul(100)
  131. # Colors dict
  132. #colors_dict = dict(zip(adata_early.obs.Cell_types.cat.categories, list(cell_type_colors.values())))
  133. counts['colors'] = counts['Cell_types'].map(cell_type_colors)
  134. # Print the result
  135. counts = counts.sort_values(['cell_line','Cell_types'])
  136. counts = counts[counts.groupby('Cell_types')['normalized_counts'].transform('max') > 2]
  137. counts
  138. # %%
  139. colors_dict = {k: v for k, v in cell_type_colors.items() if k in counts.Cell_types.unique()}
  140. labels = ['Bio-N', 'RC17', 'KOLF' ]
  141. category_names = colors_dict.keys()
  142. cumsum = np.array([0.0, 0.0, 0.0])
  143. legend_list = []
  144. with plt.rc_context({"figure.dpi": 250}):
  145. fig, ax = plt.subplots(figsize=(3.5, 2.5))
  146. #ax.set_xlim(0, np.sum(data, axis=1).max())
  147. ax.set_ylim(-0.5, len(labels) - 0.5)
  148. for i, ct in enumerate(category_names):
  149. width = [counts[(counts.cell_line == cl) & (counts.Cell_types == ct)].normalized_counts.values[0] for cl in labels]
  150. cumsum += width
  151. starts = cumsum-width
  152. color = counts[counts.Cell_types == ct].colors.values[0]
  153. rects = ax.barh(labels, width, left=starts, height=0.7,
  154. label=ct, color=color)
  155. legend_list.append(mlines.Line2D([], [], color="white", marker='o',label=ct, markersize=8, markerfacecolor=color))
  156. ax.legend(handles=legend_list, fontsize='small', frameon=False, loc='center left', bbox_to_anchor=(1, 0.5))
  157. plt.savefig('d16_bmp5-14_parse_barplot.pdf', bbox_inches='tight')
  158. plt.show()
  159. # %% [markdown]
  160. # # DEG analysis
  161. # %%
  162. %%R -i adata_early
  163. Csparse_validate = "CsparseMatrix_validate"
  164. library(Seurat)
  165. library(edgeR)
  166. seur <- as.Seurat(adata_early, counts = "counts", data = NULL)
  167. #seur <- readRDS("Data/d50_d70_neurons_seurat.rds")
  168. seur <- RenameAssays(seur, originalexp="RNA")
  169. y <- Seurat2PB(seur, sample = "sample", cluster = "Cell_types")
  170. keep.samples <- y$samples$lib.size > 5e4
  171. y <- y[, keep.samples]
  172. keep.genes <- filterByExpr(y, group=y$samples$cluster)
  173. y <- y[keep.genes, , keep=FALSE]
  174. y <- normLibSizes(y)
  175. cluster <- as.factor(y$samples$cluster)
  176. batch <- factor(y$samples$sample)
  177. #design <- model.matrix(~ cluster + batch)
  178. design <- model.matrix(~ cluster)
  179. colnames(design) <- gsub("batch", "", colnames(design))
  180. colnames(design)[1] <- "Int"
  181. head(design)
  182. y <- estimateDisp(y, design, robust=TRUE)
  183. fit <- glmQLFit(y, design, robust=TRUE)
  184. ncls <- nlevels(cluster)
  185. contr <- rbind( matrix(1/(1-ncls), ncls, ncls), matrix(0, ncol(design)-ncls, ncls) )
  186. diag(contr) <- 1
  187. contr[1,] <- 0
  188. rownames(contr) <- colnames(design)
  189. colnames(contr) <- paste0("cluster", levels(cluster))
  190. contr
  191. qlf <- list()
  192. for(i in 1:ncls){
  193. qlf[[i]] <- glmQLFTest(fit, contrast=contr[,i])
  194. qlf[[i]]$comparison <- paste0("cluster", levels(cluster)[i], "_vs_others")
  195. }
  196. top <- 500
  197. topMarkers <- list()
  198. de_df = data.frame(matrix(
  199. vector(), 0, 7, dimnames=list(c(), c("gene","logFC","logCPM","F","PValue","FDR",'comparison'))),
  200. stringsAsFactors=F)
  201. for(i in 1:ncls) {
  202. #print(head(qlf[[i]])$comparison)
  203. ord <- order(qlf[[i]]$table$PValue, decreasing=FALSE)
  204. up <- qlf[[i]]$table$logFC[ord] > 0
  205. topMarkers[[i]] <- rownames(y)[ord[up][1:top]]
  206. #genes =
  207. df = as.data.frame(topTags(qlf[[i]], n='all'))
  208. df =df[rownames(df) %in% rownames(y)[ord[up][1:top]], ]
  209. df$comparison <- head(qlf[[i]])$comparison
  210. de_df = rbind(de_df, df)
  211. }
  212. print(dim(de_df))
  213. write.csv(de_df, "parse_early_stage_bmp_deg.csv")
  214. # %%
  215. de_genes = pd.read_csv('parse_early_stage_bmp_deg.csv',index_col=0)
  216. de_genes['cluster'] = de_genes['comparison'].str.extract(r'cluster(.*?)_vs_others')
  217. de_genes = de_genes[['gene','logFC','logCPM','F','PValue','FDR','comparison','cluster']]
  218. de_genes = de_genes[(de_genes.FDR < 0.05) & (de_genes.logFC > 1)]
  219. de_genes.to_excel("ARC_VMH_analysis/DE_lists/d16_bmp_de_list.xlsx")
  220. de_genes
  221. # %% [markdown]
  222. # # Late stage
  223. # %%
  224. adata_late = sc.read('../../Data/SC/revision_bmp_timing_annotated.h5ad')
  225. adata_late.obs['Cell_types_2'].value_counts()
  226. # %%
  227. adata_late.obs[['sample','cell_line','day','bmp_treatment']].value_counts()
  228. # %%
  229. adata_late.obs.bmp_treatment.cat.categories
  230. # %%
  231. bmp_dict = {'no BMP early/late':'no BMP4 or 7', 'no BMP4':'no BMP4', 'BMP4 5-7':'BMP4 5-7', 'BMP4 5-9':'BMP4 5-9', 'BMP4 5-11':'BMP4 5-11','BMP4 5-14':'BMP4 5-14'}
  232. adata_late.obs['bmp_treatment'] = adata_late.obs['bmp_treatment'].map(bmp_dict)
  233. # %%
  234. adata_late.obs['bmp_treatment']
  235. # %%
  236. adata_temp = adata_late[adata_late.obs.sample(frac=1, random_state=42).index].copy()
  237. with plt.rc_context({ "figure.dpi": 300}):
  238. ax = sc.pl.umap(adata_temp, color=['bmp_treatment'], palette=['#fb9a99','#8b67ad', '#32a02d', '#b2df8a', '#2078b4', '#a6cee3'], frameon=False, size=10, colorbar_loc=None, layer='logcounts')
  239. #plt.savefig('figures/bmp_late_timing_umap.pdf',bbox_inches="tight")
  240. # %%
  241. adata_temp = adata_late[adata_late.obs.sample(frac=1, random_state=42).index].copy()
  242. with plt.rc_context({ "figure.dpi": 300}):
  243. ax = sc.pl.umap(adata_temp, color=['day'], frameon=False, size=10, colorbar_loc=None, layer='logcounts', show=False)
  244. plt.savefig('figures/bmp_late_day_umap.pdf',bbox_inches="tight")
  245. # %% [markdown]
  246. # # Barplot
  247. # %%
  248. colors_dict = {
  249. 'AGRP+/OTP+': '#3b89bf',
  250. 'Astrocytes': '#8b67ad',
  251. 'DLX6-AS1+/FOXP2+': '#bb9c8a',
  252. 'FEZF1+/SOX14+': '#fa8016',
  253. 'GHRH+/PNOC+': '#b15a27',
  254. 'GPR149+/LHX8+': '#71b09b',
  255. 'Immature ARC neurons': '#e85b3d',
  256. 'LHX1+/ARX+': '#8a2e35',
  257. 'NR5A2+/ONECUT1/3+': '#f4a989',
  258. 'OTP+/SST+/BNC2+': '#89969c',
  259. 'Optic area neurons': '#4f9e46',
  260. 'PNOC+/NPFFR2+': '#85c668',
  261. 'POMC+/SOX14+/NR5A1+': '#a11d02',
  262. 'POMC+/TBX3+/NR5A2+': '#eddb7e',
  263. 'Tanycytes': '#faaa4e',
  264. 'Telencephalic neurons': '#d0a9b7',
  265. 'Unassigned': '#a4cde0',
  266. 'VAX1+/GBX1+': '#d46abf',
  267. 'LMX1A+/LMX1B+': '#45bacc'
  268. }
  269. cell_types_order =['Astrocytes', 'Telencephalic neurons','Unassigned','DLX6-AS1+/FOXP2+','OTP+/SST+/BNC2+','NR5A2+/ONECUT1/3+','LMX1A+/LMX1B+','VAX1+/GBX1+','GHRH+/PNOC+','LHX1+/ARX+','GPR149+/LHX8+',
  270. 'POMC+/SOX14+/NR5A1+', 'FEZF1+/SOX14+','Immature ARC neurons', 'POMC+/TBX3+/NR5A2+','Tanycytes','AGRP+/OTP+','PNOC+/NPFFR2+','Optic area neurons']
  271. print(len(cell_types_order))
  272. #colors_dict = dict(zip(list(adata_late.obs.Cell_types_2.cat.categories), colors_dict.values()))
  273. colors_dict = {k: colors_dict[k] for k in cell_types_order if k in colors_dict}
  274. colors_dict
  275. adata_late.obs["Cell_types_2"] = pd.Categorical(
  276. values=adata_late.obs.Cell_types_2, categories=cell_types_order, ordered=True
  277. )
  278. # %%
  279. with plt.rc_context({"figure.dpi": 300}):
  280. sc.pl.umap(adata_late, color='Cell_types_2',palette = colors_dict,frameon=False, size=10 ,show = False)
  281. plt.savefig('figures/Revision/bmp_late_annotations_umap.pdf',bbox_inches="tight")
  282. plt.show()
  283. # %%
  284. count_l, count_dict = [], {}
  285. for sample in adata_late.obs.bmp_treatment.cat.categories.tolist():
  286. #if sample != 'no BMP_BMP 25-50':
  287. count_l = []
  288. for cell_type in adata_late.obs.Cell_types_2.cat.categories.tolist():
  289. count_l.append(adata_late[adata_late.obs['Cell_types_2'] == cell_type].obs['bmp_treatment'].value_counts().reindex(adata_late.obs.bmp_treatment.cat.categories, fill_value=0)[sample])
  290. count_l = [i/sum(count_l) for i in count_l]
  291. count_dict[sample] = count_l
  292. df = pd.DataFrame.from_dict(count_dict, orient='index', columns=adata_late.obs.Cell_types_2.cat.categories.tolist())
  293. df.loc[-1] = adata_late.uns['Cell_types_2_colors']
  294. df.index = ['color' if x==-1 else x for x in list(df.index)]
  295. # Sort the DF
  296. df = df[['Astrocytes', 'Telencephalic neurons','Unassigned','DLX6-AS1+/FOXP2+','OTP+/SST+/BNC2+','NR5A2+/ONECUT1/3+','LMX1A+/LMX1B+','VAX1+/GBX1+','GHRH+/PNOC+','LHX1+/ARX+','GPR149+/LHX8+',
  297. 'POMC+/SOX14+/NR5A1+', 'FEZF1+/SOX14+','Immature ARC neurons', 'POMC+/TBX3+/NR5A2+','Tanycytes','AGRP+/OTP+','PNOC+/NPFFR2+','Optic area neurons']]
  298. df
  299. # %%
  300. bmp_conditions = df.iloc[:-1].index.tolist()
  301. # Create a subplot with 1 row and 4 columns
  302. fig, axes = plt.subplots(1, 6, figsize=(14, 6), dpi=400)
  303. for i, bmp in enumerate(bmp_conditions):
  304. df_flipped = df.iloc[:-1].loc[bmp].reset_index()
  305. df_flipped.columns = ['Cell_Type', 'Percentage']
  306. # Create the barplot on the respective axis
  307. sns.barplot(
  308. data=df_flipped,
  309. y="Cell_Type", # Cell types on the y-axis
  310. x="Percentage", # Percentages on the x-axis
  311. palette=df.loc['color'].values,
  312. ax=axes[i] # Specify the axis for each plot
  313. )
  314. # Set the title and other plot customizations
  315. #axes[i].set_title(bmp, fontsize=22)
  316. if bmp == 'no BMP early/late': bmp = 'no BMP\nearly/late'
  317. axes[i].set_title(bmp, fontsize=21)
  318. axes[i].set_xlabel("")
  319. axes[i].set_ylabel("")
  320. cell_type_colors = dict(zip(df.columns, df.iloc[-1]))
  321. axes[i].tick_params(axis='x', labelsize=15)
  322. axes[i].tick_params(axis='y', labelsize=20)
  323. # Add a vertical color column next to the y-ticks in the first subplot
  324. #if i == 0:
  325. if i != 0:
  326. axes[i].tick_params(axis='y', which='both', length=0) # Remove y-ticks
  327. axes[i].set_yticklabels([]) # Remove y-tick labels
  328. axes[i].set_xticks([0.2,0.4])
  329. axes[i].set_xlim(0,0.5)
  330. # Adjust layout and show the plot
  331. plt.tight_layout(pad=0.3)
  332. plt.savefig('figures/Revision/bmp_late_barplot.pdf',bbox_inches="tight")
  333. plt.show()
  334. # %%
  335. adata_late.write('../../Data/SC/revision_bmp_timing_annotated.h5ad')
  336. # %% [markdown]
  337. # # Stacked barplot
  338. # %%
  339. adata_arc_d50 = adata_late[(adata_late.obs.day == 'd50') & (adata_late.obs.bmp_treatment == 'BMP4 5-14')]
  340. # %%
  341. with plt.rc_context({"figure.dpi": 300}):
  342. sc.pl.umap(adata_arc_d50, color=['cell_line', 'biological_replicate'],frameon=False, size=10)
  343. # %%
  344. # Group by 'diff_batch' and 'Cell_types' and count the number of occurrences
  345. counts = adata_arc_d50.obs.groupby(['cell_line', 'Cell_types_2']).size().reset_index(name='counts')
  346. # Calculate the total counts per batch
  347. totals = adata_arc_d50.obs.groupby('cell_line').size().reset_index(name='total_counts')
  348. # Merge the counts with the totals
  349. counts = counts.merge(totals, on='cell_line')
  350. # Normalize the counts
  351. counts['normalized_counts'] = counts['counts'] / counts['total_counts']
  352. counts['normalized_counts'] = counts['normalized_counts'].mul(100)
  353. # Colors dict
  354. counts['colors'] = counts['Cell_types_2'].map(colors_dict)
  355. # Print the result
  356. counts = counts.sort_values(['cell_line','Cell_types_2'])
  357. counts = counts[counts.groupby('Cell_types_2')['normalized_counts'].transform('max') > 2]
  358. counts
  359. # %%
  360. adata_arc_d50[adata_arc_d50.obs.cell_line == 'RC17'].obs.Cell_types_2.value_counts(normalize=True).mul(100)
  361. # %%
  362. colors_dict = {k: v for k, v in colors_dict.items() if k in counts.Cell_types_2.unique()}
  363. labels = ['Bio-N', 'RC17', 'KOLF' ]
  364. category_names = colors_dict.keys()
  365. cumsum = np.array([0.0, 0.0, 0.0])
  366. legend_list = []
  367. with plt.rc_context({"figure.dpi": 250}):
  368. fig, ax = plt.subplots(figsize=(3.5, 2.5))
  369. #ax.set_xlim(0, np.sum(data, axis=1).max())
  370. ax.set_ylim(-0.5, len(labels) - 0.5)
  371. for i, ct in enumerate(category_names):
  372. width = [counts[(counts.cell_line == cl) & (counts.Cell_types_2 == ct)].normalized_counts.values[0] for cl in labels]
  373. cumsum += width
  374. starts = cumsum-width
  375. color = counts[counts.Cell_types_2 == ct].colors.values[0]
  376. rects = ax.barh(labels, width, left=starts, height=0.7,
  377. label=ct, color=color)
  378. legend_list.append(mlines.Line2D([], [], color="white", marker='o',label=ct, markersize=8, markerfacecolor=color))
  379. ax.legend(handles=legend_list, fontsize='small', frameon=False, loc='center left', bbox_to_anchor=(1, 0.5))
  380. plt.savefig('d50_bmp5-14_parse_barplot.pdf', bbox_inches='tight')
  381. plt.show()
  382. # %% [markdown]
  383. # # DEG
  384. # %%
  385. %%R -i adata_late
  386. Csparse_validate = "CsparseMatrix_validate"
  387. library(Seurat)
  388. library(edgeR)
  389. seur <- as.Seurat(adata_late, counts = "counts", data = NULL)
  390. #seur <- readRDS("Data/d50_d70_neurons_seurat.rds")
  391. seur <- RenameAssays(seur, originalexp="RNA")
  392. y <- Seurat2PB(seur, sample = "sample", cluster = "Cell_types_2")
  393. keep.samples <- y$samples$lib.size > 5e4
  394. y <- y[, keep.samples]
  395. keep.genes <- filterByExpr(y, group=y$samples$cluster)
  396. y <- y[keep.genes, , keep=FALSE]
  397. y <- normLibSizes(y)
  398. cluster <- as.factor(y$samples$cluster)
  399. batch <- factor(y$samples$sample)
  400. #design <- model.matrix(~ cluster + batch)
  401. design <- model.matrix(~ cluster)
  402. colnames(design) <- gsub("batch", "", colnames(design))
  403. colnames(design)[1] <- "Int"
  404. head(design)
  405. y <- estimateDisp(y, design, robust=TRUE)
  406. fit <- glmQLFit(y, design, robust=TRUE)
  407. ncls <- nlevels(cluster)
  408. contr <- rbind( matrix(1/(1-ncls), ncls, ncls), matrix(0, ncol(design)-ncls, ncls) )
  409. diag(contr) <- 1
  410. contr[1,] <- 0
  411. rownames(contr) <- colnames(design)
  412. colnames(contr) <- paste0("cluster", levels(cluster))
  413. contr
  414. qlf <- list()
  415. for(i in 1:ncls){
  416. qlf[[i]] <- glmQLFTest(fit, contrast=contr[,i])
  417. qlf[[i]]$comparison <- paste0("cluster", levels(cluster)[i], "_vs_others")
  418. }
  419. top <- 500
  420. topMarkers <- list()
  421. de_df = data.frame(matrix(
  422. vector(), 0, 7, dimnames=list(c(), c("gene","logFC","logCPM","F","PValue","FDR",'comparison'))),
  423. stringsAsFactors=F)
  424. for(i in 1:ncls) {
  425. #print(head(qlf[[i]])$comparison)
  426. ord <- order(qlf[[i]]$table$PValue, decreasing=FALSE)
  427. up <- qlf[[i]]$table$logFC[ord] > 0
  428. topMarkers[[i]] <- rownames(y)[ord[up][1:top]]
  429. #genes =
  430. df = as.data.frame(topTags(qlf[[i]], n='all'))
  431. df =df[rownames(df) %in% rownames(y)[ord[up][1:top]], ]
  432. df$comparison <- head(qlf[[i]])$comparison
  433. de_df = rbind(de_df, df)
  434. }
  435. print(dim(de_df))
  436. write.csv(de_df, "DE_lists/revision_parse_late_stage_bmp_deg.csv")
  437. # %%
  438. de_genes = pd.read_csv('DE_lists/revision_parse_late_stage_bmp_deg.csv',index_col=0)
  439. de_genes['cluster'] = de_genes['comparison'].str.extract(r'cluster(.*?)_vs_others')
  440. de_genes = de_genes[['gene','logFC','logCPM','F','PValue','FDR','comparison','cluster']]
  441. de_genes = de_genes[(de_genes.FDR < 0.05) & (de_genes.logFC > 1)]
  442. #de_genes = de_genes[~de_genes['gene'].str.startswith(('ENSG', 'LINC'))]
  443. de_genes.to_excel("DE_lists/revision_parse_late_stage_bmp_deg.xlsx")
  444. de_genes
  445. # %% [markdown]
  446. # # Dotplot by POMC cluster
  447. # %%
  448. #adata_temp = adata_late[adata_late.obs.Cell_types_2.isin(['AGRP+/OTP+','POMC+/SOX14+/NR5A1+','POMC+/TBX3+/NR5A2+','GHRH+/PNOC+','PNOC+/NPFFR2+','FEZF1+/SOX14+', 'Tanycytes', 'Immature ARC neurons','DLX6-AS1+/FOXP2+','OTP+/SST+/BNC2+','NR5A2+/ONECUT1/3+','GPR149+/LHX8+','VAX1+/GBX1+'])]
  449. genes = ['POMC','PRDM12','AGRP','SST', 'GHRH', 'TBX3','NR5A2','PNOC', 'TRH',
  450. 'NPY', 'NR5A1','SOX14','GPR149','IL18R1','GLP1R','GLP2R','GHSR','GIPR','CCKAR','CCKBR','CALCR','RAMP1','RAMP2','RAMP3',"GRPR","SSTR1","SSTR2","SSTR5",
  451. 'NPFFR2','NPY1R',"NPY2R","NPY5R","NPY6R",'HCRTR2', 'LEPR','SORT1','SORL1',"VIPR1","VIPR2","CRHR1","CRHR2","SCTR", 'PRLHR']
  452. sc.pl.dotplot(adata_late, genes, 'Cell_types_2')
  453. # %%
  454. #genes = ['POMC']
  455. factor = 40
  456. #genes = ['POMC','GLP1R']
  457. non_zero_dict, expression_dict = {},{}
  458. for gene in genes:
  459. non_zero_list, expression_list = [], []
  460. for c in adata_late.obs['Cell_types_2'].cat.categories:
  461. # Calculate percentage of non-zero values, handling missing categories
  462. non_zero_count = adata_late[adata_late[:, gene].X > 0, :].obs['Cell_types_2'].value_counts().get(c, 0)
  463. total_count = adata_late[adata_late.obs['Cell_types_2'] == c].shape[0]
  464. percentage_non_zero = (non_zero_count / total_count) * 100 if total_count > 0 else 0
  465. non_zero_list.append(percentage_non_zero)
  466. # Calculate mean expression for the gene
  467. mean_expression = np.mean(adata_late[adata_late.obs['Cell_types_2'] == c, gene].X)
  468. expression_list.append(mean_expression)
  469. non_zero_dict.update({gene: non_zero_list})
  470. expression_dict.update({gene: expression_list})
  471. df_nonzero = pd.DataFrame.from_dict(non_zero_dict, orient='index', columns=adata_late.obs['Cell_types_2'].cat.categories)
  472. df_exp = pd.DataFrame.from_dict(expression_dict, orient='index', columns=adata_late.obs['Cell_types_2'].cat.categories)
  473. # Reverse the order of treatments
  474. treatments = df_nonzero.columns[::-1]
  475. sizes = []
  476. expression = []
  477. X = []
  478. Y = []
  479. # Iterate over the reversed treatments
  480. for r, treatment in enumerate(treatments):
  481. sizes.append(df_nonzero[treatment].values)
  482. expression.append(df_exp[treatment].values)
  483. Y.append(np.repeat(r, len(genes)))
  484. X.append(np.arange(len(genes)))
  485. sizes = np.array(sizes)
  486. expression = np.array(expression)
  487. X = np.array(X)
  488. Y = np.array(Y)
  489. # Filter out small dots
  490. mask = sizes * factor >= 1 # Only include dots above the threshold
  491. X = X[mask]
  492. Y = Y[mask]
  493. sizes = sizes[mask]
  494. expression = expression[mask]
  495. with plt.rc_context({"figure.dpi": 500, "figure.figsize": [12, 7 ]}):
  496. # Set figure size dynamically based on number of treatments and genes
  497. fig, ax = plt.subplots(figsize=(1 * len(genes), 1.3 * len(treatments)))
  498. # Adjust the scatter plot
  499. ax.set_xticks(np.arange(len(genes)), labels=genes, rotation=90, fontsize=30)
  500. ax.set_yticks(np.arange(len(treatments)), labels=treatments, fontsize=30)
  501. im = ax.scatter(X, Y, c=expression, s=factor * sizes, cmap='Blues', lw=0.5, vmin=0, edgecolors='black')
  502. ax.set_ylim([-0.7, len(treatments) - 0.3])
  503. ax.set_xlim([-0.5, len(genes) - 0.5])
  504. # Add a colorbar
  505. cbar = plt.colorbar(im, ax=ax, orientation='horizontal',aspect=5)
  506. cbar.ax.set_title('Mean expression', fontsize=20)
  507. cbar.ax.set_position([0.93, 0.3, 0.07, 0.15])
  508. # Set colorbar ticks to only min and max
  509. cbar.set_ticks([im.get_array().min(), im.get_array().max()])
  510. cbar.set_ticklabels(['Min', 'Max'], fontsize=20) # Format tick labels as needed
  511. # Add a size legend
  512. legend_sizes = [5, 25, 50] # Example sizes
  513. legend_labels = [f'{s}%' for s in legend_sizes]
  514. # Create custom legend handles for size legend
  515. handles = [Line2D([0], [0], marker='o', color='w', label=label,
  516. markersize=np.sqrt(s * factor), markerfacecolor='gray', lw=0)
  517. for s, label in zip(legend_sizes, legend_labels)]
  518. # Place the legend outside the plot
  519. ax.legend(handles=handles, title="Fraction of non-zero", loc='upper left', fontsize=18, title_fontsize=20,
  520. bbox_to_anchor=(1.012, 1), frameon=False)#, ncol=len(legend_sizes))
  521. #plt.tight_layout()
  522. #plt.savefig('figures/Revision/bmp_late_day_dotplot.pdf', bbox_inches="tight")
  523. plt.show()
  524. # %% [markdown]
  525. # # Dotplot by day
  526. # %%
  527. adata_late = sc.read('../../Data/SC/revision_bmp_timing_annotated.h5ad')
  528. adata_late.obs['Cell_types_2'].value_counts()
  529. # %%
  530. with plt.rc_context({"figure.dpi": 300}):
  531. ax = sc.pl.umap(adata_late, show=False,frameon=False, size=10 )
  532. sc.pl.umap(adata_late[(adata_late.obs.bmp_treatment=='BMP4 5-14') & (adata_late.obs.cell_line=='RC17')],ax = ax, color=['biological_replicate'],frameon=False, size=10 )
  533. with plt.rc_context({"figure.dpi": 300}):
  534. ax = sc.pl.umap(adata_late, show=False,frameon=False, size=10 )
  535. sc.pl.umap(adata_late[(adata_late.obs.bmp_treatment=='BMP4 5-14') & (adata_late.obs.cell_line=='RC17')],ax = ax, color=['day'],frameon=False, size=10 )
  536. # %%
  537. factor = 15
  538. cluster = 'POMC+/TBX3+/NR5A2+'
  539. adata_temp= adata_late[(adata_late.obs.cell_line == 'RC17') & (adata_late.obs.Cell_types_2 == cluster) & (adata_late.obs.bmp_treatment == 'BMP4 5-14')]
  540. genes = ["GRIA4", "NR5A2", "KCNQ3", "KCNJ3", "LEPR", "HTR2C", "SORT1", "GRPR", "PRDM12", "GHSR", "GIPR", "NPFFR2"]
  541. non_zero_dict, expression_dict = {},{}
  542. for gene in genes:
  543. non_zero_list, expression_list = [], []
  544. for c in adata_temp.obs['day'].cat.categories:
  545. # Calculate percentage of non-zero values, handling missing categories
  546. non_zero_count = adata_temp[adata_temp[:, gene].X > 0, :].obs['day'].value_counts().get(c, 0)
  547. total_count = adata_temp[adata_temp.obs['day'] == c].shape[0]
  548. percentage_non_zero = (non_zero_count / total_count) * 100 if total_count > 0 else 0
  549. non_zero_list.append(percentage_non_zero)
  550. # Calculate mean expression for the gene
  551. mean_expression = np.mean(adata_temp[adata_temp.obs['day'] == c, gene].X)
  552. expression_list.append(mean_expression)
  553. non_zero_dict.update({gene: non_zero_list})
  554. expression_dict.update({gene: expression_list})
  555. df_nonzero = pd.DataFrame.from_dict(non_zero_dict, orient='index', columns=adata_temp.obs['day'].cat.categories)
  556. df_exp = pd.DataFrame.from_dict(expression_dict, orient='index', columns=adata_temp.obs['day'].cat.categories)
  557. # Reverse the order of treatments
  558. treatments = df_nonzero.columns[::-1]
  559. sizes = []
  560. expression = []
  561. X = []
  562. Y = []
  563. # Iterate over the reversed treatments
  564. for r, treatment in enumerate(treatments):
  565. sizes.append(df_nonzero[treatment].values)
  566. expression.append(df_exp[treatment].values)
  567. Y.append(np.repeat(r, len(genes)))
  568. X.append(np.arange(len(genes)))
  569. sizes = np.array(sizes)
  570. expression = np.array(expression)
  571. X = np.array(X)
  572. Y = np.array(Y)
  573. # Filter out small dots
  574. mask = sizes * factor >= 1 # Only include dots above the threshold
  575. X = X[mask]
  576. Y = Y[mask]
  577. sizes = sizes[mask]
  578. expression = expression[mask]
  579. with plt.rc_context({"figure.dpi": 500, "figure.figsize": [12, 5 ]}):
  580. # Set figure size dynamically based on number of treatments and genes
  581. fig, ax = plt.subplots(figsize=(1 * len(genes), 1.3 * len(treatments)))
  582. # Adjust the scatter plot
  583. ax.set_xticks(np.arange(len(genes)), labels=genes, rotation=90, fontsize=30)
  584. ax.set_yticks(np.arange(len(treatments)), labels=treatments, fontsize=30)
  585. im = ax.scatter(X, Y, c=expression, s=factor * sizes, cmap='Blues', lw=0.5, vmin=0, edgecolors='black')
  586. ax.set_ylim([-0.5, len(treatments) - 0.5])
  587. ax.set_xlim([-0.5, len(genes) - 0.5])
  588. # Add a colorbar
  589. cbar = plt.colorbar(im, ax=ax, orientation='horizontal',aspect=5)
  590. cbar.ax.set_title('Mean expression', fontsize=20)
  591. cbar.ax.set_position([0.96, 0, 0.1, 0.2])
  592. # Set colorbar ticks to only min and max
  593. cbar.set_ticks([im.get_array().min(), im.get_array().max()])
  594. cbar.set_ticklabels(['Min', 'Max'], fontsize=20) # Format tick labels as needed
  595. # Add a size legend
  596. legend_sizes = [5, 25, 50] # Example sizes
  597. legend_labels = [f'{s}%' for s in legend_sizes]
  598. # Create custom legend handles for size legend
  599. handles = [Line2D([0], [0], marker='o', color='w', label=label,
  600. markersize=np.sqrt(s * factor), markerfacecolor='gray', lw=0)
  601. for s, label in zip(legend_sizes, legend_labels)]
  602. # Place the legend outside the plot
  603. ax.legend(handles=handles, title="Fraction of non-zero", loc='upper left', fontsize=18, title_fontsize=20,
  604. bbox_to_anchor=(1, 1), frameon=False)#, ncol=len(legend_sizes))
  605. #plt.tight_layout()
  606. plt.title(cluster, size=30)
  607. cluster_temp = cluster.replace('/','_')
  608. plt.savefig(f'figures/bmp_late_maturation_dotplot_{cluster_temp}.pdf', bbox_inches="tight")
  609. plt.show()
  610. # %% [markdown]
  611. # # POMC subtype DE analysis
  612. # %%
  613. adata_pomc = adata_late[adata_late.obs.Cell_types_2.isin(['POMC+/SOX14+/NR5A1+', 'POMC+/TBX3+/NR5A2+'])]
  614. #adata_pomc = adata_pomc[adata_pomc.obs.day == 'd50']
  615. adata_pomc
  616. # %%
  617. with plt.rc_context({ "figure.dpi": 300 }):
  618. ax = sc.pl.umap(adata_late, show=False, size=15, frameon=False)
  619. sc.pl.umap(adata_pomc, ax = ax, color="Cell_types_2", size=15, frameon=False, save='_POMC_populations.pdf')
  620. # %%
  621. %%R -i adata_pomc
  622. Csparse_validate = "CsparseMatrix_validate"
  623. library(Seurat)
  624. library(edgeR)
  625. seur <- as.Seurat(adata_pomc, counts = "counts", data = NULL)
  626. #seur <- readRDS("Data/d50_d70_neurons_seurat.rds")
  627. seur <- RenameAssays(seur, originalexp="RNA")
  628. y <- Seurat2PB(seur, sample = "cell_line", cluster = "Cell_types_2")
  629. keep.samples <- y$samples$lib.size > 5e4
  630. y <- y[, keep.samples]
  631. keep.genes <- filterByExpr(y, group=y$samples$cluster)
  632. y <- y[keep.genes, , keep=FALSE]
  633. y <- normLibSizes(y)
  634. print('OK')
  635. cluster <- as.factor(y$samples$cluster)
  636. batch <- factor(y$samples$sample)
  637. design <- model.matrix(~ cluster + batch)
  638. colnames(design) <- gsub("batch", "", colnames(design))
  639. colnames(design)[1] <- "Int"
  640. head(design)
  641. y <- estimateDisp(y, design, robust=TRUE)
  642. fit <- glmQLFit(y, design, robust=TRUE)
  643. print('OK')
  644. ncls <- nlevels(cluster)
  645. contr <- rbind( matrix(1/(1-ncls), ncls, ncls), matrix(0, ncol(design)-ncls, ncls) )
  646. diag(contr) <- 1
  647. contr[1,] <- 0
  648. rownames(contr) <- colnames(design)
  649. colnames(contr) <- paste0("cluster", levels(cluster))
  650. contr
  651. qlf <- list()
  652. for(i in 1:ncls){
  653. qlf[[i]] <- glmQLFTest(fit, contrast=contr[,i])
  654. qlf[[i]]$comparison <- paste0("cluster", levels(cluster)[i], "_vs_others")
  655. }
  656. print('OK')
  657. top <- 20000
  658. topMarkers <- list()
  659. de_df = data.frame(matrix(
  660. vector(), 0, 7, dimnames=list(c(), c("gene","logFC","logCPM","F","PValue","FDR",'comparison'))),
  661. stringsAsFactors=F)
  662. for(i in 1:ncls) {
  663. #print(head(qlf[[i]])$comparison)
  664. ord <- order(qlf[[i]]$table$PValue, decreasing=FALSE)
  665. up <- qlf[[i]]$table$logFC[ord] > 0
  666. topMarkers[[i]] <- rownames(y)[ord[up][1:top]]
  667. #genes =
  668. df = as.data.frame(topTags(qlf[[i]], n='all'))
  669. df =df[rownames(df) %in% rownames(y)[ord[up][1:top]], ]
  670. df$comparison <- head(qlf[[i]])$comparison
  671. de_df = rbind(de_df, df)
  672. }
  673. print(dim(de_df))
  674. write.csv(de_df, "parse_pomc.csv")
  675. # %%
  676. %%R -o markers
  677. library(Seurat)
  678. # Identify spatially variable genes in spatial human hypomap
  679. merged <- readRDS('../../Data/SC/humanHYPOMAP_spatial.rds')
  680. merged_subset = subset(x = merged, subset = regional_clusters_named %in% c('ARC',"VMH"))
  681. Idents(object = merged_subset) <- "regional_clusters_grouped"
  682. markers <- FindAllMarkers(object = merged_subset, features = rownames(merged_subset))
  683. # %%
  684. de_genes = pd.read_csv('parse_pomc.csv',index_col=0)
  685. de_genes['cluster'] = de_genes['comparison'].str.extract(r'cluster(.*?)_vs_others')
  686. de_genes = de_genes[['gene','logFC','logCPM','F','PValue','FDR','comparison','cluster']]
  687. de_genes['identity'] = de_genes.cluster.map({'POMC+/TBX3+/NR5A2+': 'ARC','POMC+/SOX14+/NR5A1+':'VMH'})
  688. arc_genes = list(markers[(markers.cluster == 'ARC') & (markers.p_val_adj < 0.05) & (markers.avg_log2FC >0.1)].gene.values)
  689. vmh_genes = list(markers[(markers.cluster == 'VMH') & (markers.p_val_adj < 0.05) & (markers.avg_log2FC >0.1)].gene.values)
  690. de_genes['spatial_hypomap_de_gene'] = '-'
  691. de_genes.loc[ (de_genes.gene.isin(arc_genes)), 'spatial_hypomap_de_gene'] = 'ARC'
  692. de_genes.loc[ (de_genes.gene.isin(vmh_genes)), 'spatial_hypomap_de_gene'] = 'VMH'
  693. top_genes = de_genes[(de_genes.FDR < 0.05) & (de_genes.logFC > 1)]
  694. top_genes.to_excel('arc_vmh_pomc_subtype_deg.xlsx')
  695. top_genes = (top_genes.loc[top_genes['spatial_hypomap_de_gene'].isin(['VMH','ARC'])].sort_values(by=['cluster', 'logFC'], ascending=[True, False]))
  696. de_genes.loc[de_genes.cluster == 'POMC+/SOX14+/NR5A1+','logFC'] = de_genes[de_genes.cluster == 'POMC+/SOX14+/NR5A1+']['logFC'] * -1
  697. # %%
  698. top_genes[top_genes.cluster == 'POMC+/SOX14+/NR5A1+'].spatial_hypomap_de_gene.value_counts()
  699. # %%
  700. #plt.clf()
  701. from adjustText import adjust_text
  702. with plt.rc_context({ "figure.dpi": 300, "figure.figsize": [5, 4 ] }):
  703. # highlight down- or up- regulated genes
  704. down = de_genes[(de_genes['logFC']<=-1)&(de_genes['FDR']<=0.05)]
  705. up = de_genes[(de_genes['logFC']>=1)&(de_genes['FDR']<=0.05)]
  706. plt.axvline(-1,color="grey",linestyle="--")
  707. plt.axvline(1,color="grey",linestyle="--")
  708. plt.axhline(-np.log10(0.05),color="grey",linestyle="--")
  709. plt.scatter(x=de_genes['logFC'],y=de_genes['FDR'].apply(lambda x:-np.log10(x)),s=4,label="Not significant",color="#bebebe")
  710. plt.scatter(x=down['logFC'],y=down['FDR'].apply(lambda x:-np.log10(x)),s=4,label='POMC+/SOX14+/NR5A1+',color="#a11d02")
  711. plt.scatter(x=up['logFC'],y=up['FDR'].apply(lambda x:-np.log10(x)),s=4,label='POMC+/TBX3+/NR5A2+',color="#eddb7e")
  712. highlight_df_vmh = de_genes[de_genes['gene'].isin(top_genes[top_genes.spatial_hypomap_de_gene == 'VMH'].gene)]
  713. highlight_df_arc = de_genes[de_genes['gene'].isin(top_genes[top_genes.spatial_hypomap_de_gene == 'ARC'].gene)]
  714. # Circle the selected genes (larger, transparent points)
  715. plt.scatter(highlight_df_vmh['logFC'], -np.log10(highlight_df_vmh['FDR']), s=6.5, facecolors='none', edgecolors='orange', linewidths=0.7, label="Spatial human VMH DEG")
  716. plt.scatter(highlight_df_arc['logFC'], -np.log10(highlight_df_arc['FDR']), s=6.5, facecolors='none', edgecolors='black', linewidths=0.7, label="Spatial human ARC DEG")
  717. gene_list =['NR5A1','SOX14','GPR149','CBLN1','GABRB2','SOX1','CA10','CNR1','HS3ST4','ST6GAL2','GABRE','ADGRL4','FGF10','RAX',
  718. 'IL13RA1','NR5A2','IL13RA2','ECEL1','LHX2','PROX1','NR3C1','CRH', 'SLC17A6', 'CALCR', 'VAX1', 'NR2F2-AS1']
  719. texts=[]
  720. for gene in gene_list:
  721. texts.append(plt.text(x=de_genes[de_genes.gene == gene]['logFC'],y=-np.log10(de_genes[de_genes.gene == gene]['FDR']),s=gene,fontsize=8,weight='bold'))
  722. adjust_text(texts, expand=(1.65, 1.7),arrowprops=dict(arrowstyle="-", color='black', lw=0.8, shrinkA=2, shrinkB=2))
  723. plt.ylim(0,7.8)
  724. plt.xlim(-11,6.5)
  725. plt.xlabel("logFC", size=14)
  726. plt.ylabel("-log10(p-value)", size=14)
  727. plt.title('POMC subtype DEG', fontsize=16)
  728. legend_handles = [
  729. Line2D([0], [0], marker='o', color='w', markerfacecolor='#bebebe', markersize=5, label="Not significant"),
  730. Line2D([0], [0], marker='o', color='w', markerfacecolor='#a11d02', markersize=5, label='POMC+/SOX14+/NR5A1+'),
  731. Line2D([0], [0], marker='o', color='w', markerfacecolor='#eddb7e', markersize=5, label='POMC+/TBX3+/NR5A2+'),
  732. Line2D([0], [0], marker='o', color='w', markerfacecolor='none', markeredgecolor='#F58024', markersize=4, markeredgewidth=2.5, label="Spatial hypomap VMH DEG"),
  733. Line2D([0], [0], marker='o', color='w', markerfacecolor='none', markeredgecolor='black', markersize=4, markeredgewidth=2.5, label="Spatial hypomap ARC DEG")
  734. ]
  735. # Add legend with increased linewidth
  736. plt.legend(handles=legend_handles, loc="upper left", bbox_to_anchor=(0.98, 0.75),
  737. fontsize=10, frameon=False, markerscale=3, handletextpad=0.05, handleheight=2, handlelength=2)
  738. #plt.tight_layout()
  739. plt.savefig('figures/Revision/POMC_DE_analysis.pdf',bbox_inches="tight")
  740. plt.show()
  741. # %%
  742. de_genes = de_genes[(de_genes.FDR < 0.05) & (de_genes.logFC > 1)]
  743. de_genes.to_excel("DE_lists/revision_parse_pomc_clusters_de_list.xlsx")
  744. de_genes
  745. # %%
  746. adata_pomc_arc = adata_late[(adata_late.obs.Cell_types_2.isin(['POMC+/TBX3+/NR5A2+'])) & (adata_late.obs.day == 'd50')]
  747. adata_pomc_vmh = adata_late[(adata_late.obs.Cell_types_2.isin(['POMC+/SOX14+/NR5A1+'])) & (adata_late.obs.day == 'd50')]
  748. # %%
  749. arc_pomc_dict = {'timing': adata_pomc_arc.obs.bmp_treatment.value_counts(normalize=True).mul(100).keys().values.tolist(), 'Percentage':adata_pomc_arc.obs.bmp_treatment.value_counts(normalize=True).mul(100).values.tolist() }
  750. df_arc = pd.DataFrame.from_dict(arc_pomc_dict)
  751. df_arc['cell_type'] = 'POMC+/TBX3+/NR5A2+'
  752. vmh_pomc_dict = {'timing': adata_pomc_vmh.obs.bmp_treatment.value_counts(normalize=True).mul(100).keys().values.tolist(), 'Percentage':adata_pomc_vmh.obs.bmp_treatment.value_counts(normalize=True).mul(100).values.tolist() }
  753. df_vmh = pd.DataFrame.from_dict(vmh_pomc_dict)
  754. df_vmh['cell_type'] = 'POMC+/SOX14+/NR5A1+'
  755. df_merge = pd.concat([df_vmh,df_arc], axis=0)
  756. df_merge.timing = df_merge.timing.astype('category')
  757. df_merge.timing = df_merge.timing.cat.reorder_categories(['no BMP4 or 7', 'no BMP4', 'BMP4 5-7', 'BMP4 5-9', 'BMP4 5-11', 'BMP4 5-14'])
  758. #df_merge.timing = df_merge.timing.cat.rename_categories({'no BMP_BMP 25-50':'25-50','BMP 5-7':'5-7','BMP 5-9':'5-9','BMP 5-11':'5-11','BMP 5-14':'5-14'})
  759. df_merge
  760. # %%
  761. # Create the bar plot
  762. from matplotlib.lines import Line2D
  763. with plt.rc_context({ "figure.dpi": 400, "figure.figsize": [3.5, 2.8 ]}):
  764. ax = sns.barplot(
  765. data=df_merge,
  766. x="timing",
  767. y="Percentage",
  768. hue="cell_type",
  769. palette=['#a11d02','#eddb7e']
  770. )
  771. ax.spines['right'].set_color('none')
  772. ax.spines['top'].set_color('none')
  773. line1 = Line2D([], [], color="white", marker='o', markerfacecolor='#eddb7e',markersize=12)
  774. line2 = Line2D([], [], color="white", marker='o', markerfacecolor='#a11d02',markersize=12)
  775. ax.legend((line2, line1), ('POMC+/SOX14+/NR5A1+','POMC+/TBX3+/NR5A2+'),loc='center left', bbox_to_anchor=(1, 0.5),frameon=False,handletextpad=-0.2, fontsize=12)
  776. # Customize the plot
  777. #plt.title("BMP timing", fontsize=16)
  778. plt.xlabel("")
  779. plt.ylabel("Fraction of POMC clusters", fontsize=14)
  780. #plt.legend(title="Cell Type", fontsize=8)
  781. plt.xticks( fontsize=18, rotation = 90)
  782. plt.yticks(fontsize=12)
  783. #plt.tight_layout()
  784. #plt.tight_layout()
  785. plt.savefig('figures/Revision/pomc_clusters_percentages.pdf', bbox_inches='tight')
  786. # Show the plot
  787. plt.show()

16_bmp_analysis.ipynb at commit b31f478, no license · at the source

Overview

Authors: Zehra Abay-Nørgaard1, Anika K. Mueller1, Erno Hänninen1, Dylan Rausch2, Louise Piilgaard1, Lucía Sena Trujillo1, Lorenzo Fedrizzi1, Jens Bager Christensen1, Alison Salvador1, Alrik L. Schörling1, Noah Wulff Mottelson2, Qiuyu Qin1, Shruthi Sampath1, Bob Hersbach1, Jonas Henkenjohann1, Sofie Peeters1, Viktoriia Nikulina3, Charlotte Høy Kruse2, Yuan Li3, Kavitha Chinnaiya4, Marysia Placzek4, Janko Kajtez1, Tune H. Pers2, Agnete Kirkeby1
  1. Novo Nordisk Foundation Center for Stem Cell Medicine (reNEW), Department of Biomedical Sciences, Faculty of Health and Medical Sciences, University of Copenhagen, 2200 Copenhagen, Denmark
  2. Novo Nordisk Foundation Center for Basic Metabolic Research (CBMR), Faculty of Health and Medical Sciences, University of Copenhagen, 2200 Copenhagen, Denmark
  3. Department of Experimental Medical Sciences, Wallenberg Centre for Molecular Medicine (WCMM) and Lund Stem Cell Centre, Lund University, 221 84 Lund, Sweden
  4. School of Biosciences, University of Sheffield, Sheffield S10 2TN, UK
Journal: Cell stem cell, volume 33, issue 7, pages 1174-1190.e11
Dates: received 26 June 2025; accepted 14 May 2026; published online 8 June 2026; in print 2 July 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1016/j.stem.2026.05.005 · PMID 42259293 · PMCID PMC13353052 · OpenAlex W7163876967
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), cellular / molecular (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions, Machine learning, Single-unit activity, calcium imaging
Keywords: hypothalamic development, arcuate nucleus, human pluripotent stem cells, organoids, BMP signaling, obesity, neuropeptidergic, orexigenic, energy homeostasis, POMC development
MeSH: Ependymoglial Cells*, Neurons*, Pluripotent Stem Cells*, Arcuate Nucleus of Hypothalamus, Cell Differentiation, Humans, Pro-Opiomelanocortin (* major topic)
Topic: Pluripotent Stem Cells Research (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: Danish Research Council (0169-00073B, 8045-00091B); European Union (874758); Novo Nordisk Foundation (NNF23SA0088590, NNF16OC0021496, NNF21CC0073729, NNF23SA0084103); Wellcome Trust (212247/Z/18/Z); Lundbeck Foundation (R350-2020-963, R380-2021-1267); Knut and Alice Wallenberg Foundation
Citations: cited by 4 papers (Europe PMC); 102 references in the paper
Research resources: OTP (Rabbit) RRID:AB_11164017, Vimentin (Chicken) RRID:AB_11212377, AQP4 (Rabbit) RRID:AB_1844967, CRH (Rabbit) RRID:AB_2084279, HuC/D (Mouse) RRID:AB_221448, NPY (Sheep) RRID:AB_2236176, AGRP (Goat) RRID:AB_2273824, Anti-Rabbit Cy3 RRID:AB_2307443, Anti-Rabbit Alexa 488 RRID:AB_2313584, AGRP (Rabbit) RRID:AB_2313908, Anti-Mouse Cy3 RRID:AB_2315777, Anti-Sheep Cy3 RRID:AB_2315778, Anti-Goat Alexa 488 RRID:AB_2336933, Anti-Goat Alexa 647 RRID:AB_2340437, Anti-Sheep Alexa 647 RRID:AB_2340751, Anti-Mouse Alexa 488 RRID:AB_2340846, NR5A1 (Mouse) RRID:AB_2532209, TRH (Rabbit) RRID:AB_2648903, PAX6 (Mouse) RRID:AB_2716656, RRID:AB_2739476, NKX2-1 (Rabbit) RRID:AB_2811263, POMC (Mouse) RRID:AB_2898516, NFIA (Rabbit) RRID:AB_2923081, GHRH (Rabbit) RRID:AB_3678595, MAP2 (Mouse) RRID:AB_477171, S100β (Mouse) RRID:AB_477499, TH (Mouse) RRID:AB_572268, hNCAM1 (Mouse) RRID:AB_627128, aMSH (Sheep) RRID:AB_91683, SCTi003-A hiPSC line RRID:CVCL_C1W7, BIONi010 hiPSC line RRID:CVCL_C9MC, RC17 hESC line RRID:CVCL_L206

Abstract

The arcuate nucleus (ARC) and ventromedial hypothalamus (VMH) are highly specialized hypothalamic nuclei controlling appetite and energy expenditure. Here, we demonstrate that human VMH and ARC neurons can be generated from pluripotent stem cells by fine-tuned timing and duration of bone morphogenetic protein (BMP) exposure. We identified SHH−/NKX2.1+/FGF10+/RAX+/TBX3+ posterior tuberal progenitors as the source of ARC cell types, including agouti-related peptide (AGRP)-, prepronociceptin (PNOC)-, growth-hormone-releasing hormone (GHRH)-, and thyrotropin-releasing hormone (TRH)-expressing neurons and β2-tanycytes. Differentiated ARC cultures showed high transcriptomic similarity to human ARC and responded to energy homeostasis-regulatory peptides including leptin, glucagon-like peptide 1 (GLP-1), ghrelin, and fibroblast growth factor 1 (FGF1). In contrast, anterior tuberal TBX3− progenitors generated VMH-associated neurons expressing NR5A1, SOX14, and GPR149. Strikingly, two transcriptionally distinct pro-opiomelanocortin (POMC) subpopulations emerged from these lineages, mapping spatially to either the ARC (POMC+/TBX3+/NR5A2+) or the VMH (POMC+/SOX14+/NR5A1+). This model provides a cellular platform to study human hypothalamic subtype specification and pathways involved in central appetite regulation.

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 17 matches between paragraphs and lines of code.

kirkebylab/In_vitro_ARC_VMH_analysis

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: b31f4789b26e407bac91bc65f53ab0a843973080, 26 February 2026
Languages: Jupyter (19), R (1)
Size: 21 files, 20 scripts
Software Heritage: not archived
Found in: “Data and code availability”
Holds: README, 20 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Seurat (19 files), tidyverse (11 files), edgeR (5 files), anndata (4 files), ggplot2 (4 files), Matplotlib (4 files), NumPy (4 files), pandas (4 files), Scanpy (4 files), seaborn (4 files), patchwork (3 files), rpy2 (3 files), SciPy (3 files), data.table (2 files), scikit-learn (2 files), igraph (1 file), Monocle 3 (1 file), Plotly (1 file), SingleCellExperiment (1 file), Squidpy (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
21 files

Zenodo 20118475

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Data and code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Seurat (19 files), tidyverse (11 files), edgeR (5 files), anndata (4 files), ggplot2 (4 files), Matplotlib (4 files), NumPy (4 files), pandas (4 files), Scanpy (4 files), seaborn (4 files), patchwork (3 files), rpy2 (3 files), SciPy (3 files), data.table (2 files), scikit-learn (2 files), igraph (1 file), Monocle 3 (1 file), Plotly (1 file), SingleCellExperiment (1 file), Squidpy (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
21 files

alexdobin/star

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: b1edc1208d91a53bf40ebae8669f71d50b994851, 25 January 2024
Languages: C++ (160), C/C++ (133), C (34), Shell (1), MATLAB (1)
Size: 389 files, 329 scripts
Software Heritage: not archived
Found in: the text, “Key resources table”
Holds: README, license file, environment (extras/docker/Dockerfile), continuous integration, documentation
Not found: CITATION.cff, tests
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
331 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:

  • 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 369 scripts, each with its path and the digest of its content;
  • 17 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

No dataset and no data link were found in the paper.

Data and code availability

All data necessary for the conclusions of the study are provided with the article. sc/snRNA-seq data are available at GEO under SuperSeries accession number GEO: GSE271235 (ARC protocol) and GSE296407 (BMP timing). DEG lists are available in Table S7. The scripts used to analyze the sc/snRNA-seq data are available at GitHub (https://github.com/kirkebylab/In_vitro_ARC_VMH_analysis) and Zenodo (https://doi.org/10.5281/zenodo.20118475).

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 2, 28 September 2026

  • Publisher: n/a → Elsevier BV

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 24 authors, 10 keywords, 7 MeSH terms, 6 funders, 101 references, 32 RRIDs.

Cite

This paper

Abay-Nørgaard, Z., Mueller, A. K., Hänninen, E., Rausch, D., Piilgaard, L., Trujillo, L. S., Fedrizzi, L., Christensen, J. B., Salvador, A., Schörling, A. L., Mottelson, N. W., Qin, Q., Sampath, S., Hersbach, B., Henkenjohann, J., Peeters, S., Nikulina, V., Kruse, C. H., Li, Y., . . . Kirkeby, A. (2026). Generation of human appetite-regulating neurons and tanycytes from pluripotent stem cells. Cell stem cell, 33(7), 1174-1190.e11. https://doi.org/10.1016/j.stem.2026.05.005

BibTeX

@article{abaynrgaard2026generation,
author = {Abay-Nørgaard, Zehra and Mueller, Anika K. and Hänninen, Erno and Rausch, Dylan and Piilgaard, Louise and Trujillo, Lucía Sena and Fedrizzi, Lorenzo and Christensen, Jens Bager and Salvador, Alison and Schörling, Alrik L. and Mottelson, Noah Wulff and Qin, Qiuyu and Sampath, Shruthi and Hersbach, Bob and Henkenjohann, Jonas and Peeters, Sofie and Nikulina, Viktoriia and Kruse, Charlotte Høy and Li, Yuan and Chinnaiya, Kavitha and Placzek, Marysia and Kajtez, Janko and Pers, Tune H. and Kirkeby, Agnete},
title = {{Generation of human appetite-regulating neurons and tanycytes from pluripotent stem cells}},
journal = {Cell stem cell},
year = {2026},
month = jun,
volume = {33},
number = {7},
pages = {1174--1190.e11},
publisher = {Elsevier BV},
issn = {1934-5909},
doi = {10.1016/j.stem.2026.05.005},
url = {https://doi.org/10.1016/j.stem.2026.05.005},
pmid = {42259293},
pmcid = {PMC13353052}
}

RIS

TY - JOUR
AU - Abay-Nørgaard, Zehra
AU - Mueller, Anika K.
AU - Hänninen, Erno
AU - Rausch, Dylan
AU - Piilgaard, Louise
AU - Trujillo, Lucía Sena
AU - Fedrizzi, Lorenzo
AU - Christensen, Jens Bager
AU - Salvador, Alison
AU - Schörling, Alrik L.
AU - Mottelson, Noah Wulff
AU - Qin, Qiuyu
AU - Sampath, Shruthi
AU - Hersbach, Bob
AU - Henkenjohann, Jonas
AU - Peeters, Sofie
AU - Nikulina, Viktoriia
AU - Kruse, Charlotte Høy
AU - Li, Yuan
AU - Chinnaiya, Kavitha
AU - Placzek, Marysia
AU - Kajtez, Janko
AU - Pers, Tune H.
AU - Kirkeby, Agnete
TI - Generation of human appetite-regulating neurons and tanycytes from pluripotent stem cells
T2 - Cell stem cell
J2 - Cell Stem Cell
PY - 2026
DA - 2026/06/08
VL - 33
IS - 7
SP - 1174
EP - 1190.e11
SN - 1934-5909
PB - Elsevier BV
DO - 10.1016/j.stem.2026.05.005
UR - https://doi.org/10.1016/j.stem.2026.05.005
LA - en
ER -

CSL-JSON

{
"id": "10.1016/j.stem.2026.05.005",
"type": "article-journal",
"title": "Generation of human appetite-regulating neurons and tanycytes from pluripotent stem cells",
"container-title": "Cell stem cell",
"author": [
{
"family": "Abay-Nørgaard",
"given": "Zehra"
},
{
"family": "Mueller",
"given": "Anika K."
},
{
"family": "Hänninen",
"given": "Erno"
},
{
"family": "Rausch",
"given": "Dylan"
},
{
"family": "Piilgaard",
"given": "Louise"
},
{
"family": "Trujillo",
"given": "Lucía Sena"
},
{
"family": "Fedrizzi",
"given": "Lorenzo"
},
{
"family": "Christensen",
"given": "Jens Bager"
},
{
"family": "Salvador",
"given": "Alison"
},
{
"family": "Schörling",
"given": "Alrik L."
},
{
"family": "Mottelson",
"given": "Noah Wulff"
},
{
"family": "Qin",
"given": "Qiuyu"
},
{
"family": "Sampath",
"given": "Shruthi"
},
{
"family": "Hersbach",
"given": "Bob"
},
{
"family": "Henkenjohann",
"given": "Jonas"
},
{
"family": "Peeters",
"given": "Sofie"
},
{
"family": "Nikulina",
"given": "Viktoriia"
},
{
"family": "Kruse",
"given": "Charlotte Høy"
},
{
"family": "Li",
"given": "Yuan"
},
{
"family": "Chinnaiya",
"given": "Kavitha"
},
{
"family": "Placzek",
"given": "Marysia"
},
{
"family": "Kajtez",
"given": "Janko"
},
{
"family": "Pers",
"given": "Tune H."
},
{
"family": "Kirkeby",
"given": "Agnete"
}
],
"container-title-short": "Cell Stem Cell",
"volume": "33",
"issue": "7",
"page": "1174-1190.e11",
"DOI": "10.1016/j.stem.2026.05.005",
"PMID": "42259293",
"PMCID": "PMC13353052",
"ISSN": "1934-5909",
"publisher": "Elsevier BV",
"URL": "https://doi.org/10.1016/j.stem.2026.05.005",
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
8
]
]
}
}

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.1016/j.stemcr.2026.102958 [code]
Scalable hypothalamic neuron differentiation from human pluripotent stem cells suitable for modeling metabolic disorders.
Journal: Stem cell reports
In common: cellular / molecular, 22 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: rpy2, Monocle 3, SingleCellExperiment, 16 other tools, cellular / molecular, 4 references
[3] doi:10.1016/j.isci.2026.116055 [code]
Mapping the transcriptional diversity of calcium signaling in the mouse and human brain.
Journal: iScience
In common: Squidpy, rpy2, Monocle 3, 14 other tools, 3 references
[4] doi:10.1038/s41586-026-10214-2 [code]
Multidimensional profiling of heterogeneity in supratentorial ependymomas.
Journal: Nature
In common: Squidpy, Monocle 3, SingleCellExperiment, 15 other tools, 1 reference
[5] doi:10.1186/s13059-026-04177-w [code]
Genomic sequence evolution underlying human neocortical interareal diversification.
Journal: Genome biology
In common: Squidpy, Monocle 3, anndata, 13 other tools, cellular / molecular, 3 references
[6] doi:10.1002/imt2.70163 [code]
Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.
Journal: iMeta
In common: Monocle 3, SingleCellExperiment, edgeR, 15 other tools, cellular / molecular
[7] doi:10.1016/j.cpblue.2026.100007 [code]
An integrated single-cell and spatial proteotranscriptomics atlas of fibroblast-driven immunoregulation within the human adult oral cavity.
Journal: Cell press blue
In common: rpy2, SingleCellExperiment, edgeR, 14 other tools, 1 reference
[8] doi:10.1038/s41592-026-03194-8 [code]
Beyond benchmarking: an expert-guided consensus approach to spatially aware clustering.
Journal: Nature methods
In common: Squidpy, rpy2, SingleCellExperiment, 13 other tools, 1 reference
[9] doi:10.1038/s44318-026-00818-9 [code]
FAM134B-mediated ER-phagy degrades APP and suppresses Alzheimer's disease pathology.
Journal: The EMBO journal
In common: Monocle 3, SingleCellExperiment, anndata, 14 other tools, cellular / molecular
[10] doi:10.1016/j.cell.2026.05.026 [code]
The critical role of the endogenous immune compartment after CAR T cell therapy in recurrent GBM.
Journal: Cell
In common: SingleCellExperiment, edgeR, anndata, 12 other tools, 3 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.