OSCR

Human neuronal differentiation under Aβ exposure: a single-cell transcriptomic and epigenomic dataset.

Code ↔ Paper

10 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 10 matches
  1. [1] § Methods › scATAC-seq analysis: preprocessing and preparing Regulon Analysis ↔ Scripts/scATACseq/1_atac_scenic_pipeline_paper.py, lines 398–437 · score 0.83 · highly variable regions, Region topic probability, accessible regions, Otsu, Candidate, DARs
  2. [2] § Methods › Proportion analysis of neurogenesis between control and beta conditions ↔ Scripts/scRNAseq/2_Neurogenesis_lvl1_paper.R, lines 2031–2110 · score 0.77 · Ordinal logistic regression, chi square, contingency, subsampled, model, neurogenesis
  3. [3] § Technical Validation › Assessment of chromatin accessibility consistency and regulatory annotations ↔ Scripts/scATACseq/1_atac_scenic_pipeline_paper.py, lines 703–745 · score 0.71 · correlation coefficient, chromatin accessibility, TF expression, target genes, TFs, regulons
  4. [4] § Technical Validation › Validation of the neuronal lineage trajectory at single-cell level ↔ Scripts/scRNAseq/2_Neurogenesis_lvl1_paper.R, lines 2031–2110 · score 0.70 · ordinal logistic regression, chi square, subsampled, trajectory, cells
  5. [5] § Methods › Regulon Analysis: eGRN ↔ Scripts/scATACseq/1_atac_scenic_pipeline_paper.py, lines 533–584 · score 0.68 · gene regulatory network, scATAC, scRNA, enhancer, SCENIC, meta
  6. [6] § Methods › Regulon Analysis: eGRN ↔ Scripts/scATACseq/1_atac_scenic_pipeline_paper.py, lines 479–530 · score 0.66 · motif database, Motif scoring, cisTarget, hg38, SCENIC, ranks
  7. [7] § Methods › scRNA-seq analysis: quality control, preprocessing, filtering, integration, and global clustering ↔ Scripts/scRNAseq/1_Analysis_pipeline_preprocessing_and_overall_tests_paper.R, lines 267–314 · score 0.63 · SCTransform, SCT normalized, transformation, pipeline, Doublets, preprocessing
  8. [8] § Technical Validation › Assessment of chromatin accessibility consistency and regulatory annotations ↔ Scripts/scATACseq/1_atac_scenic_pipeline_paper.py, lines 533–584 · score 0.59 · gene regulatory network, scATAC, scRNA
  9. [9] § Methods › Human brain data analysis ↔ Scripts/scRNAseq/1_Analysis_pipeline_preprocessing_and_overall_tests_paper.R, lines 2279–2319 · score 0.55 · logFC, limma, covariates, sex, voom, model
  10. [10] § Technical Validation › Assessment of chromatin accessibility consistency and regulatory annotations ↔ Scripts/scATACseq/1_atac_scenic_pipeline_paper.py, lines 703–745 · score 0.53 · chromatin accessibility, motif enrichment, SCENIC, TF, regulon

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

Python · 1,156 lines · 57 KB · GPL-3.0 · 6 matches

  1. #SCENIC+ PIPELINE from current Seurat+Singac processed datasets (using un-paired data)
  2. export LD_LIBRARY_PATH="/opt/R/3.5.2/lib64/R/lib:$LD_LIBRARY_PATH"
  3. import os
  4. os.environ['R_HOME'] = "/opt/R/3.5.2/lib64/R/"
  5. #Quality control - required for later run SCENIC+
  6. import pybiomart as pbm
  7. dataset = pbm.Dataset(name='hsapiens_gene_ensembl', host='http://www.ensembl.org')
  8. annot = dataset.query(attributes=['chromosome_name', 'transcription_start_site', 'strand', 'external_gene_name', 'transcript_biotype'])
  9. annot['Chromosome/scaffold name'] = annot['Chromosome/scaffold name'].to_numpy(dtype = str)
  10. filter = annot['Chromosome/scaffold name'].str.contains('CHR|GL|JH|MT')
  11. annot = annot[~filter]
  12. annot['Chromosome/scaffold name'] = annot['Chromosome/scaffold name'].str.replace(r'(\b\S)', r'chr\1')
  13. annot.columns=['Chromosome', 'Start', 'Strand', 'Gene', 'Transcript_type']
  14. annot = annot[annot.Transcript_type == 'protein_coding']
  15. #############
  16. #R code to generate consensus.bed file for continue this pipeline
  17. df <- data.frame(seqnames=seqnames(combined.peaks),
  18. starts=start(combined.peaks)-1,
  19. ends=end(combined.peaks),
  20. names=c(rep(".", length(combined.peaks))),
  21. scores=c(rep(".", length(combined.peaks))),
  22. strands=strand(combined.peaks))
  23. write.table(df, file="combined_peaks_neurogenesis.bed", quote=F, sep="\t", row.names=F, col.names=F)
  24. #############
  25. #Generate fragments dictionary from each of the scATAC_samples
  26. fragments_dict = {
  27. 'basal': '/datos_2/output_basal_atac/_job/outs/fragments.tsv.gz',
  28. 'control_day7': "/datos_2/output_control_7_days_atac/_job/outs/fragments.tsv.gz",
  29. 'control_day13': "/datos_2/output_control_13_days_atac/outs/fragments.tsv.gz",
  30. 'control_day20': "/datos_2/output_control_20_days_atac/_job/outs/fragments.tsv.gz",
  31. 'ba_day7': "/datos_2/output_ba_7_days_atac/_job/outs/fragments.tsv.gz",
  32. 'ba_day13': "/datos_2/output_ba_13_days_atac/outs/fragments.tsv.gz",
  33. 'ba_day20': "/datos_2/output_ba_20_days_atac/_job/outs/fragments.tsv.gz",
  34. }
  35. #FOR IBEX KAUST SERVER PATHS
  36. fragments_dict = {
  37. 'basal': '/ibex/scratch/projects/c2169/Navarra/Neuro/fragments/fragments_basal.tsv.gz',
  38. 'control_day7': "/ibex/scratch/projects/c2169/Navarra/Neuro/fragments/fragments_c7.tsv.gz",
  39. 'control_day13': "/ibex/scratch/projects/c2169/Navarra/Neuro/fragments/fragments_c13.tsv.gz",
  40. 'control_day20': "/ibex/scratch/projects/c2169/Navarra/Neuro/fragments/fragments_c20.tsv.gz",
  41. 'ba_day7': "/ibex/scratch/projects/c2169/Navarra/Neuro/fragments/fragments_ba7.tsv.gz",
  42. 'ba_day13': "/ibex/scratch/projects/c2169/Navarra/Neuro/fragments/fragments_ba13.tsv.gz",
  43. 'ba_day20': "/ibex/scratch/projects/c2169/Navarra/Neuro/fragments/fragments_ba20.tsv.gz",
  44. }
  45. #COMPUTE the QC required for laters
  46. from pycisTopic.qc import *
  47. #path_to_regions = '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes/combined_peaks_neurogenesis.bed'
  48. path_to_regions = {'basal': '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/combined_peaks_neurogenesis.bed',
  49. 'control_day7': '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/combined_peaks_neurogenesis.bed',
  50. 'control_day13': '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/combined_peaks_neurogenesis.bed',
  51. 'control_day20': '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/combined_peaks_neurogenesis.bed',
  52. 'ba_day7': '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/combined_peaks_neurogenesis.bed',
  53. 'ba_day13': '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/combined_peaks_neurogenesis.bed',
  54. 'ba_day20': '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/combined_peaks_neurogenesis.bed',
  55. }
  56. #FOR IBEX KAUST SERVER PATHS
  57. path_to_regions = {'basal': '/ibex/scratch/projects/c2169/Navarra/Neuro/peaks/peaks_basal.bed',
  58. 'control_day7': '/ibex/scratch/projects/c2169/Navarra/Neuro/peaks/peaks_c7.bed',
  59. 'control_day13': '/ibex/scratch/projects/c2169/Navarra/Neuro/peaks/peaks_c13.bed',
  60. 'control_day20': '/ibex/scratch/projects/c2169/Navarra/Neuro/peaks/peaks_c20.bed',
  61. 'ba_day7': '/ibex/scratch/projects/c2169/Navarra/Neuro/peaks/peaks_ba7.bed',
  62. 'ba_day13': '/ibex/scratch/projects/c2169/Navarra/Neuro/peaks/peaks_ba13.bed',
  63. 'ba_day20': '/ibex/scratch/projects/c2169/Navarra/Neuro/peaks/peaks_ba20.bed',
  64. }
  65. metadata_bc, profile_data_dict = compute_qc_stats(
  66. fragments_dict = fragments_dict,
  67. tss_annotation = annot,
  68. stats=['barcode_rank_plot', 'duplicate_rate', 'insert_size_distribution', 'profile_tss', 'frip'],
  69. label_list = None,
  70. path_to_regions = path_to_regions,
  71. n_cpu = 1,
  72. valid_bc = None,
  73. n_frag = 100,
  74. n_bc = None,
  75. tss_flank_window = 1000,
  76. tss_window = 50,
  77. tss_minimum_signal_window = 100,
  78. tss_rolling_window = 10,
  79. remove_duplicates = True,
  80. _temp_dir = '/ibex/scratch/projects/c2169/temp2')
  81. #_temp_dir = '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/temp/')
  82. os.chdir("/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/")
  83. work_dir = "/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/"
  84. #FOR IBEX KAUST SERVER PATHS
  85. os.chdir("/ibex/scratch/projects/c2169/Navarra/Neuro/scenic_outputs")
  86. work_dir = "/ibex/scratch/projects/c2169/Navarra/Neuro/scenic_outputs"
  87. #Number of cells per condition and timepoint
  88. summary = []
  89. for key, df in metadata_bc.items():
  90. if "_" in key:
  91. condition, timepoint = key.split("_")
  92. else:
  93. condition = key
  94. timepoint = None
  95. summary.append((condition, timepoint, df.shape[0]))
  96. import pandas as pd
  97. summary_df = pd.DataFrame(summary, columns=["condition", "timepoint", "n_cells"])
  98. print(summary_df)
  99. sys.stderr = sys.__stderr__ # unsilence stderr
  100. if not os.path.exists(os.path.join(work_dir, 'quality_control')):
  101. os.makedirs(os.path.join(work_dir, 'quality_control'))
  102. pickle.dump(metadata_bc,
  103. open(os.path.join(work_dir, 'quality_control/metadata_bc.pkl'), 'wb'))
  104. pickle.dump(profile_data_dict,
  105. open(os.path.join(work_dir, 'quality_control/profile_data_dict.pkl'), 'wb'))
  106. # Return figure to plot together with other metrics. Figure will be saved as pdf.
  107. qc_filters = {
  108. 'basal': {
  109. 'Log_unique_nr_frag': [3.8, None],
  110. 'FRIP': [0.5, None],
  111. 'TSS_enrichment': [5, None],
  112. 'Dupl_rate': [None, None]
  113. },
  114. 'control_day7': {
  115. 'Log_unique_nr_frag': [3.8, None],
  116. 'FRIP': [0.5, None],
  117. 'TSS_enrichment': [5, None],
  118. 'Dupl_rate': [None, None]
  119. },
  120. 'control_day13': {
  121. 'Log_unique_nr_frag': [3.8, None],
  122. 'FRIP': [0.5, None],
  123. 'TSS_enrichment': [5, None],
  124. 'Dupl_rate': [None, None]
  125. },
  126. 'control_day20': {
  127. 'Log_unique_nr_frag': [3.8, None],
  128. 'FRIP': [0.5, None],
  129. 'TSS_enrichment': [5, None],
  130. 'Dupl_rate': [None, None]
  131. },
  132. 'ba_day7': {
  133. 'Log_unique_nr_frag': [3.8, None],
  134. 'FRIP': [0.5, None],
  135. 'TSS_enrichment': [5, None],
  136. 'Dupl_rate': [None, None]
  137. },
  138. 'ba_day13': {
  139. 'Log_unique_nr_frag': [3.8, None],
  140. 'FRIP': [0.5, None],
  141. 'TSS_enrichment': [5, None],
  142. 'Dupl_rate': [None, None]
  143. },
  144. 'ba_day20': {
  145. 'Log_unique_nr_frag': [3.8, None],
  146. 'FRIP': [0.5, None],
  147. 'TSS_enrichment': [5, None],
  148. 'Dupl_rate': [None, None]
  149. }
  150. }
  151. FRIP_NR_FRAG_filterDict = {}
  152. TSS_NR_FRAG_filterDict = {}
  153. FRIP_NR_FRAG_figDict = {}
  154. TSS_NR_FRAG_figDict = {}
  155. DR_NR_FRAG_figDict={}
  156. from pycisTopic.qc import *
  157. for runID in metadata_bc:
  158. FRIP_NR_FRAG_fig, FRIP_NR_FRAG_filter=plot_barcode_metrics(metadata_bc[runID],
  159. var_x='Log_unique_nr_frag',
  160. var_y='FRIP',
  161. min_x=qc_filters[runID]['Log_unique_nr_frag'][0],
  162. max_x=qc_filters[runID]['Log_unique_nr_frag'][1],
  163. min_y=qc_filters[runID]['FRIP'][0],
  164. max_y=qc_filters[runID]['FRIP'][1],
  165. return_cells=True,
  166. return_fig=True,
  167. plot=False)
  168. # Return figure to plot together with other metrics, and cells passing filters
  169. TSS_NR_FRAG_fig, TSS_NR_FRAG_filter=plot_barcode_metrics(metadata_bc[runID],
  170. var_x='Log_unique_nr_frag',
  171. var_y='TSS_enrichment',
  172. min_x=qc_filters[runID]['Log_unique_nr_frag'][0],
  173. max_x=qc_filters[runID]['Log_unique_nr_frag'][1],
  174. min_y=qc_filters[runID]['TSS_enrichment'][0],
  175. max_y=qc_filters[runID]['TSS_enrichment'][1],
  176. return_cells=True,
  177. return_fig=True,
  178. plot=False)
  179. # Return figure to plot together with other metrics, but not returning cells (no filter applied for the duplication rate per barcode)
  180. DR_NR_FRAG_fig=plot_barcode_metrics(metadata_bc[runID],
  181. var_x='Log_unique_nr_frag',
  182. var_y='Dupl_rate',
  183. min_x=qc_filters[runID]['Log_unique_nr_frag'][0],
  184. max_x=qc_filters[runID]['Log_unique_nr_frag'][1],
  185. min_y=qc_filters[runID]['Dupl_rate'][0],
  186. max_y=qc_filters[runID]['Dupl_rate'][1],
  187. return_cells=False,
  188. return_fig=True,
  189. plot=False,
  190. plot_as_hexbin = True)
  191. # Barcodes passing filters
  192. FRIP_NR_FRAG_filterDict[runID] = FRIP_NR_FRAG_filter
  193. TSS_NR_FRAG_filterDict[runID] = TSS_NR_FRAG_filter
  194. # Figs
  195. FRIP_NR_FRAG_figDict[runID] = FRIP_NR_FRAG_fig
  196. TSS_NR_FRAG_figDict[runID] = TSS_NR_FRAG_fig
  197. DR_NR_FRAG_figDict[runID]=DR_NR_FRAG_fig
  198. #PLOT QC for eah sample in pdf
  199. runID = 'basal'
  200. print("filter for sample: {runID}")
  201. full_name = work_dir + 'QC_sample' + runID + '.pdf'
  202. fig=plt.figure(figsize=(20, 10), dpi=800)
  203. plt.subplot(1, 3, 1)
  204. img = fig2img(FRIP_NR_FRAG_figDict[runID]) #To convert figures to plot together, see .utils.py
  205. plt.imshow(img)
  206. plt.axis('off')
  207. plt.subplot(1, 3, 2)
  208. img = fig2img(TSS_NR_FRAG_figDict[runID])
  209. plt.imshow(img)
  210. plt.axis('off')
  211. plt.subplot(1, 3, 3)
  212. img = fig2img(DR_NR_FRAG_figDict[runID])
  213. plt.imshow(img)
  214. plt.axis('off')
  215. plt.show()
  216. plt.savefig(full_name)
  217. plt.close()
  218. #############
  219. #Load list of barcodes from R (Seurat to python pipeline)
  220. #bc_passing_filters = pd.read_csv("barcodes_from_filtered_R.csv")
  221. #Al final usar los filtrados de esta manera
  222. bc_passing_filters = dict()
  223. for runID in metadata_bc:
  224. bc_passing_filters[runID] = list((set(FRIP_NR_FRAG_filterDict[runID]) & set(TSS_NR_FRAG_filterDict[runID])))
  225. print(f"{len(bc_passing_filters[runID])} barcodes passed filters for sample {runID}")
  226. #Creating a cisTopic object and topic modeling
  227. import pickle
  228. path_to_blacklist= '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/hg38-blacklist.v2.bed'
  229. #FOR IBEX KAUST SERVER PATHS
  230. path_to_blacklist='/ibex/scratch/projects/c2169/Navarra/Neuro/blacklist.v2.bed'
  231. #Next we will create a cisTopic object for each sample, and merge them into a single object
  232. from pycisTopic.cistopic_class import *
  233. cistopic_obj_list=[create_cistopic_object_from_fragments(path_to_fragments=fragments_dict[key],
  234. path_to_regions=path_to_regions[key],
  235. path_to_blacklist=path_to_blacklist,
  236. metrics=metadata_bc[key],
  237. valid_bc=bc_passing_filters[key],
  238. n_cpu=1,
  239. project=key) for key in fragments_dict.keys()]
  240. cistopic_obj = merge(cistopic_obj_list)
  241. print(cistopic_obj)
  242. pickle.dump(cistopic_obj,
  243. open(os.path.join(work_dir, 'quality_control/cistopic_obj.pkl'), 'wb'))
  244. #############
  245. #R code
  246. metadata = [email hidden]
  247. barcodes_metadata = sub('.*_', '', rownames(metadata))
  248. metadata["barcodes"] = barcodes_metadata
  249. metadata["batch"] = sub('.*atac_', '', metadata$batch)
  250. write.table(metadata, file="metadata_R.csv", sep= ",", row.names=T, col.names=T)
  251. #############
  252. #############
  253. #Adding cell metadata from Seurat
  254. cell_data = pd.read_csv("metadata_R.csv")
  255. #cistopic makes use of the sample_id to match the correct cell barcodes to the metadata, let's add the sample_id as a suffix to the cell barcodes
  256. cell_data['barcode'] = cell_data['barcodes'] +'___'+ cell_data['batch']
  257. print(cell_data['barcode'][0:5])
  258. cell_data = cell_data.set_index('barcode')
  259. cistopic_obj.add_cell_data(cell_data) #[['MMline']]) cell not contained will be filled with nan
  260. #############
  261. #Detect and remove doublets using Scrublet
  262. import scrublet as scr
  263. scrub = scr.Scrublet(cistopic_obj.fragment_matrix.T, expected_doublet_rate=0.1)
  264. doublet_scores, predicted_doublets = scrub.scrub_doublets()
  265. scrub.call_doublets(threshold=0.3)
  266. histogram_scrub = scrub.plot_histogram()
  267. plt.savefig('histogram_scrub.pdf')
  268. scrublet = pd.DataFrame([scrub.doublet_scores_obs_, scrub.predicted_doublets_], columns=cistopic_obj.cell_names, index=['Doublet_scores_fragments', 'Predicted_doublets_fragments']).T
  269. cistopic_obj.add_cell_data(scrublet)
  270. singlets = cistopic_obj.cell_data[cistopic_obj.cell_data.Predicted_doublets_fragments == False].index.tolist()
  271. cistopic_obj = cistopic_obj.subset(singlets, copy=True)
  272. #######################
  273. #######################
  274. #FROM NOW ON WE USE ONLY THE CELLS FOR THE TRANSITIONS GROUPS OF CELLS A-B-C-D-E
  275. #############
  276. #Subset
  277. #Remove unwanted clusters / keep wanted clusters of cell based on Seurat annotation from scRNA-seq
  278. our_transition_groups_cells = cistopic_obj.cell_data[cistopic_obj.cell_data['group_A'].isin(['A','B','C','D','E'])].index.tolist()
  279. # Subset cisTopic object
  280. cistopic_obj = cistopic_obj.subset(our_transition_groups_cells, copy=True, split_pattern='-')
  281. #Subset only CONTROL CELLS
  282. #our_transition_groups_cells = cistopic_obj_our_groups_only.cell_data[cistopic_obj_our_groups_only.cell_data['condition'].isin(['control'])].index.tolist()
  283. # Subset cisTopic object
  284. #cistopic_obj_our_groups_only = cistopic_obj_our_groups_only.subset(our_transition_groups_cells, copy=True, split_pattern='-')
  285. #lets try using all cells and use only contrasts we are interested in
  286. cistopic_obj_our_groups_only = cistopic_obj
  287. #######################
  288. #WE ARE WORKING ONLY WITH CONTROL CELLS FROM NEUROGENESIS BRUNCH NOW !!
  289. #######################
  290. #############
  291. #Run topic modeling
  292. import pickle
  293. from pycisTopic.cistopic_class import *
  294. tmp_dir = '/datos_2/temp/'
  295. sys.stderr = open(os.devnull, "w") # silence stderr
  296. models=run_cgs_models(cistopic_obj_our_groups_only,
  297. n_topics=[2,5,10,15,30,45],
  298. n_cpu=20,
  299. n_iter=500,
  300. random_state=555,
  301. alpha=50,
  302. alpha_by_topic=True,
  303. eta=0.1,
  304. eta_by_topic=False,
  305. save_path=None,
  306. _temp_dir = os.path.join(tmp_dir + 'ray_spill'))
  307. sys.stderr = sys.__stderr__ # unsilence stderr
  308. #ray.init()
  309. #ray.shutdown()
  310. #############
  311. #Model selection
  312. numTopics = 30
  313. model = evaluate_models(models,
  314. select_model = numTopics,
  315. return_model = True,
  316. metrics = ['Arun_2010','Cao_Juan_2009', 'Minmo_2011', 'loglikelihood'],
  317. plot_metrics = False)
  318. plt.tight_layout()
  319. plt.savefig('model_selection.pdf')
  320. #Add model to cistopic object.
  321. cistopic_obj_our_groups_only.add_LDA_model(model)
  322. #############
  323. #Visualization
  324. from pycisTopic.clust_vis import run_umap
  325. color_dict_line = {
  326. 'A': '#9A031E',
  327. 'B': '#C75146',
  328. 'C': '#FFA987',
  329. 'D': '#222E50',
  330. 'E': '#8BB174',
  331. }
  332. #Estos son los de python "#F8766D" "#A3A500" "#00BF7D" "#00B0F6" "#E76BF3"
  333. run_umap(cistopic_obj_our_groups_only, target = 'cell', scale = True)
  334. cistopic_obj_our_groups_only_for_umap = cistopic_obj_our_groups_only
  335. from pycisTopic.clust_vis import plot_metadata
  336. plot_metadata(
  337. cistopic_obj_our_groups_only,
  338. reduction_name = 'UMAP',
  339. color_dictionary = {'group_A': color_dict_line},
  340. variables = ['group_A'],
  341. figsize = (10, 10))
  342. plt.savefig('UMAP_cistopic_all_cells.pdf')
  343. #Colorear por d?as (QC)
  344. color_dict_state = {
  345. 'basal': '#9A031E',
  346. 'control_day7': '#f79489',
  347. 'control_day13': '#41729f',
  348. 'control_day20': '#32cd30',
  349. 'ba_day7': '#fac0b9',
  350. 'ba_day13': '#c3e0e5',
  351. 'ba_day20': '#b2d2a4',
  352. }
  353. from pycisTopic.clust_vis import plot_metadata
  354. plot_metadata(
  355. cistopic_obj_our_groups_only,
  356. reduction_name = 'UMAP',
  357. color_dictionary = {'batch': color_dict_state},
  358. variables = ['batch'],
  359. figsize = (10, 10))
  360. plt.savefig(work_dir + 'UMAP_cistopic_by_day_QC_all_cells.pdf')
  361. #CARGAMOS LOS PRIMEROS QUE GENERAMOS
  362. #cistopic_obj = pickle.load(open(os.path.join(work_dir + '/Session_objects/cistopic_obj.pkl'), 'rb'))
  363. #region_bin_topics_otsu = pickle.load(open(os.path.join(work_dir + '/Session_objects/region_bin_topics_otsu.pkl'), 'rb'))
  364. #markers_dict = pickle.load(open(os.path.join(work_dir + '/Session_objects/markers_dict.pkl'), 'rb'))
  365. #Inferring candidate enhancer regions
  366. #Next we will infer candidate enhancer regions by binarization of region-topic probabilities ad calculating differentially accessible regions.
  367. #These regions will be used for the next step, pycistarget, in which we will look wich motifs are enriched in these regions.
  368. from pycisTopic.topic_binarization import *
  369. region_bin_topics_otsu = binarize_topics(cistopic_obj_our_groups_only, method='otsu')
  370. #Calculate differential accessible regions (DARs).
  371. #We will calculate DARs for each line (i.e. each line vs all other lines),
  372. #for each state (i.e. each state vs all other states) and for the specific contrast.
  373. #Imputamos/normalizamos/buscamos regiones variables
  374. from pycisTopic.diff_features import *
  375. imputed_acc_obj = impute_accessibility(cistopic_obj_our_groups_only, selected_cells=None, selected_regions=None, scale_factor=10**6)
  376. normalized_imputed_acc_obj = normalize_scores(imputed_acc_obj, scale_factor=10**4)
  377. variable_regions = find_highly_variable_features(normalized_imputed_acc_obj, plot = False)
  378. #Compute contrasts
  379. #print('Calculating DARs for each group...')
  380. #markers_dict = find_diff_features(cistopic_obj, imputed_acc_obj, variable='group_A', var_features=variable_regions, split_pattern = '-', contrasts = contrasts)
  381. print('Calculating DARs for the contrast for C and T for the A-B-C-D-E developmental trajectory')
  382. contrasts = [[['C_group_B'], ['C_group_A']], [['C_group_C'], ['C_group_B']], [['C_group_D'], ['C_group_C']], [['C_group_E'], ['C_group_D']],
  383. [['T_group_B'], ['T_group_A']], [['T_group_C'], ['T_group_B']], [['T_group_D'], ['T_group_C']], [['T_group_E'], ['T_group_D']]]
  384. markers_dict = find_diff_features(cistopic_obj_our_groups_only, imputed_acc_obj, variable='contrasts_groups', var_features=variable_regions, split_pattern = '-', contrasts = contrasts)
  385. #############
  386. #Motif enrichment analysis using pycistarget
  387. ##########################################################################################
  388. #Save session and restore
  389. import pickle
  390. if not os.path.exists(os.path.join(work_dir + '/Session_objects')):
  391. os.makedirs(os.path.join(work_dir + '/Session_objects'))
  392. #Export cistopic object
  393. pickle.dump(cistopic_obj_our_groups_only, open(os.path.join(work_dir + '/Session_objects/cistopic_obj_our_groups_only.pkl'), 'wb'))
  394. #Export cistopic model
  395. pickle.dump(models,open(os.path.join(work_dir, 'Session_objects/models.pkl'), 'wb'))
  396. #Export otsu binarized
  397. pickle.dump(region_bin_topics_otsu, open(os.path.join(work_dir + '/Session_objects/region_bin_topics_otsu.pkl'), 'wb'))
  398. #Export cistopic markers
  399. pickle.dump(markers_dict, open(os.path.join(work_dir + '/Session_objects/markers_dict.pkl'), 'wb'))
  400. ##
  401. #Load session
  402. cistopic_obj_our_groups_only = pickle.load(open(os.path.join(work_dir + '/Session_objects/cistopic_obj.pkl'), 'rb'))
  403. models = pickle.load(open(os.path.join(work_dir + '/Session_objects/models.pkl'), 'rb'))
  404. region_bin_topics_otsu = pickle.load(open(os.path.join(work_dir + '/Session_objects/region_bin_topics_otsu.pkl'), 'rb'))
  405. markers_dict = pickle.load(open(os.path.join(work_dir + '/Session_objects/markers_dict.pkl'), 'rb'))
  406. ##########################################################################################
  407. ##############
  408. #Convert to dictionary of pyranges objects.
  409. import pyranges as pr
  410. from pycistarget.utils import region_names_to_coordinates
  411. region_sets = {}
  412. region_sets['topics_otsu'] = {}
  413. region_sets['DARs_contrasts'] = {}
  414. for topic in region_bin_topics_otsu.keys():
  415. regions = region_bin_topics_otsu[topic].index[region_bin_topics_otsu[topic].index.str.startswith('chr')] #only keep regions on known chromosomes
  416. region_sets['topics_otsu'][topic] = pr.PyRanges(region_names_to_coordinates(regions))
  417. for DAR in markers_dict.keys():
  418. regions = markers_dict[DAR].index[markers_dict[DAR].index.str.startswith('chr')] #only keep regions on known chromosomes
  419. region_sets['DARs_contrasts'][DAR] = pr.PyRanges(region_names_to_coordinates(regions))
  420. for key in region_sets.keys():
  421. print(f'{key}: {region_sets[key].keys()}')
  422. #Que base de datos de picos de referencia:
  423. #For this analysis we will make use a custom made cistarget database on the consensus peaks.
  424. #A database of motif-to-tf annotation database
  425. ##############
  426. #download resources
  427. ## Download motif database:
  428. #wget https://resources.aertslab.org/cistarget/databases/homo_sapiens/hg38/screen/mc_v10_clust/region_based/hg38_screen_v10_clust.regions_vs_motifs.rankings.feather -P /datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes/DB_resources/
  429. #Download scores database
  430. #wget https://resources.aertslab.org/cistarget/databases/homo_sapiens/hg38/screen/mc_v10_clust/region_based/hg38_screen_v10_clust.regions_vs_motifs.scores.feather -P /datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes/DB_resources/
  431. ##Download motif-to-tf annotation database
  432. #wget https://resources.aertslab.org/cistarget/motif2tf/motifs-v10nr_clust-nr.hgnc-m0.001-o0.0.tbl -P /datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes/DB_resources/
  433. ##############
  434. #Load resources
  435. db_path = '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/DB_resources/'
  436. rankings_db = os.path.join(db_path + 'hg38_screen_v10_clust.regions_vs_motifs.rankings.feather')
  437. scores_db = os.path.join(db_path + 'hg38_screen_v10_clust.regions_vs_motifs.scores.feather')
  438. motif_annotation = os.path.join(db_path + 'motifs-v10nr_clust-nr.hgnc-m0.001-o0.0.tbl')
  439. from scenicplus.wrappers.run_pycistarget import run_pycistarget
  440. sys.stderr = open(os.devnull, "w") # silence stderr
  441. run_pycistarget(
  442. region_sets = region_sets,
  443. species = 'homo_sapiens',
  444. save_path = os.path.join(work_dir + 'motifs'),
  445. ctx_db_path = rankings_db,
  446. dem_db_path = scores_db,
  447. path_to_motif_annotations = motif_annotation,
  448. run_without_promoters = True,
  449. n_cpu = 10,
  450. _temp_dir = os.path.join(tmp_dir + 'ray_spill'),
  451. annotation_version = 'v10nr_clust')
  452. sys.stderr = sys.__stderr__ # unsilence stderr
  453. ##############
  454. ##############
  455. #Inferring enhancer-driven Gene Regulatory Networks (eGRNs) using SCENIC+
  456. #We now have completed all the steps for running the SCENIC+ analysis.
  457. #We will start by creating a scenicplus object containing all the analysis we have done up to this point.
  458. import dill
  459. import scanpy as sc
  460. import os
  461. import warnings
  462. warnings.filterwarnings("ignore")
  463. import pandas
  464. import pyranges
  465. # Set stderr to null to avoid strange messages from ray
  466. import sys
  467. _stderr = sys.stderr
  468. null = open(os.devnull,'wb')
  469. work_dir = '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/'
  470. tmp_dir = '/datos_2/temp/'
  471. ##############
  472. #R code
  473. ##############
  474. #Generate h5.ad from seurat scRNAseq data
  475. library('SeuratDisk')
  476. setwd("/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/")
  477. load("temporal_2.RData")
  478. #First select ONLY NEURONS cells then generate 'group_A' on scRNA data metadata
  479. Idents(rna.combined.seurat) <- "seurat_clusters"
  480. neuro_clusters = c("0","1","2","3","4","6","7","8","13","15")
  481. rna.combined.seurat = subset(x = rna.combined.seurat, idents = neuro_clusters)
  482. [email hidden]$group_A = [email hidden]$seurat_clusters
  483. [email hidden]$group_A[[email hidden]$group_A == "4"] <- "A"
  484. [email hidden]$group_A[[email hidden]$group_A == "0"] <- "B"
  485. [email hidden]$group_A[[email hidden]$group_A == "7"] <- "C"
  486. [email hidden]$group_A[[email hidden]$group_A == "3"] <- "D"
  487. [email hidden]$group_A[[email hidden]$group_A == "13"] <- "E"
  488. [email hidden]$group_A[[email hidden]$group_A == "15"] <- "E"
  489. [email hidden]$group_A[[email hidden]$group_A == "1"] <- "E"
  490. [email hidden]$group_A[[email hidden]$group_A == "8"] <- "E"
  491. [email hidden]$group_A[[email hidden]$group_A == "2"] <- "E"
  492. [email hidden]$group_A[[email hidden]$group_A == "6"] <- "E"
  493. SaveH5Seurat(rna.combined.seurat, filename = "scRNA_Seurat_to_python.h5Seurat", assays = "RNA")
  494. Convert("scRNA_Seurat_to_python.h5Seurat", dest = "h5ad")
  495. ##############
  496. ##############
  497. adata = sc.read_h5ad(os.path.join('/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/scRNA_Seurat_to_python.h5ad'))
  498. cistopic_obj = cistopic_obj_our_groups_only #cistopic_obj = dill.load(open(os.path.join(work_dir, 'scATAC/cistopic_obj.pkl'), 'rb'))
  499. menr = dill.load(open(os.path.join(work_dir + 'motifs/menr.pkl'), 'rb'))
  500. #Before we are able to run SCENIC+ we have to combine the scATAC-seq and the scRNA-seq data into a pseudo multiome dataset.
  501. #The way we do this is by randomly sampling a number of cells from the scATAC-seq and scRNA-seq data for each cell type annotation (in this case this is each cell line).
  502. #We then average the scRNA-seq and scATAc-seq counts within these cells (of the same cell line) to generate metacells containing both scATAC-seq and scRNA-seq data.
  503. from scenicplus.scenicplus_class import create_SCENICPLUS_object
  504. import numpy as np
  505. scplus_obj = create_SCENICPLUS_object(
  506. GEX_anndata = adata,
  507. cisTopic_obj = cistopic_obj,
  508. menr = menr,
  509. multi_ome_mode = False,
  510. key_to_group_by = 'group_A',
  511. nr_cells_per_metacells = 5)
  512. #Print all cell_lines in this case STATES are mathching between both omics and will be used
  513. print(f"The cell lines for which we have scRNA-seq data are:\t{', '.join(set(adata.obs['group_A']) - set(['-']))}")
  514. print(f"The cell lines for which we have scATAC-seq data are:\t{', '.join(set(cistopic_obj.cell_data['group_A']))}")
  515. print(f"The cell lines for which we have both:\t{', '.join(set(cistopic_obj.cell_data['group_A']) & set(adata.obs['group_A']))}")
  516. #Now we can run SCENIC+ as usual.
  517. #First let?s check with which biomart host our gene names match.
  518. ensembl_version_dict = {'110': 'http://www.ensembl.org',
  519. '109': 'http://feb2023.archive.ensembl.org/',
  520. '108': 'http://oct2022.archive.ensembl.org/',
  521. '107': 'http://jul2022.archive.ensembl.org/',
  522. '106': 'http://apr2022.archive.ensembl.org/',
  523. '105': 'http://dec2021.archive.ensembl.org/',
  524. '104': 'http://may2021.archive.ensembl.org/',
  525. '103': 'http://feb2021.archive.ensembl.org/',
  526. '102': 'http://nov2020.archive.ensembl.org/',
  527. '101': 'http://aug2020.archive.ensembl.org/',
  528. '100': 'http://apr2020.archive.ensembl.org/',
  529. '99': 'http://jan2020.archive.ensembl.org/',
  530. '98': 'http://sep2019.archive.ensembl.org/',
  531. '97': 'http://jul2019.archive.ensembl.org/',
  532. '96': 'http://apr2019.archive.ensembl.org/',
  533. '95': 'http://jan2019.archive.ensembl.org/',
  534. '94': 'http://oct2018.archive.ensembl.org/',
  535. '93': 'http://jul2018.archive.ensembl.org/',
  536. '92': 'http://apr2018.archive.ensembl.org/',
  537. '91': 'http://dec2017.archive.ensembl.org/',
  538. '90': 'http://aug2017.archive.ensembl.org/',
  539. '89': 'http://may2017.archive.ensembl.org/',
  540. '88': 'http://mar2017.archive.ensembl.org/',
  541. '87': 'http://dec2016.archive.ensembl.org/',
  542. '86': 'http://oct2016.archive.ensembl.org/',
  543. '80': 'http://may2015.archive.ensembl.org/',
  544. '77': 'http://oct2014.archive.ensembl.org/',
  545. '75': 'http://feb2014.archive.ensembl.org/',
  546. '54': 'http://may2009.archive.ensembl.org/'}
  547. import pybiomart as pbm
  548. def test_ensembl_host(scplus_obj, host, species):
  549. dataset = pbm.Dataset(name=species+'_gene_ensembl', host=host)
  550. annot = dataset.query(attributes=['chromosome_name', 'transcription_start_site', 'strand', 'external_gene_name', 'transcript_biotype'])
  551. annot.columns = ['Chromosome', 'Start', 'Strand', 'Gene', 'Transcript_type']
  552. annot['Chromosome'] = annot['Chromosome'].astype('str')
  553. filter = annot['Chromosome'].str.contains('CHR|GL|JH|MT')
  554. annot = annot[~filter]
  555. annot.columns=['Chromosome', 'Start', 'Strand', 'Gene', 'Transcript_type']
  556. gene_names_release = set(annot['Gene'].tolist())
  557. ov=len([x for x in scplus_obj.gene_names if x in gene_names_release])
  558. print('Genes recovered: ' + str(ov) + ' out of ' + str(len(scplus_obj.gene_names)))
  559. return ov
  560. n_overlap = {}
  561. for version in ensembl_version_dict.keys():
  562. print(f'host: {version}')
  563. try:
  564. n_overlap[version] = test_ensembl_host(scplus_obj, ensembl_version_dict[version], 'hsapiens')
  565. except:
  566. print('Host not reachable')
  567. v = sorted(n_overlap.items(), key=lambda item: item[1], reverse=True)[0][0]
  568. print(f"version: {v} has the largest overlap, use {ensembl_version_dict[v]} as biomart host")
  569. #Lests select the more overlap
  570. biomart_host = "http://jul2018.archive.ensembl.org"
  571. #Before running we will also download a list of known human TFs from the human transcription factors database.
  572. #wget -O /datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes/DB_resources/utoronto_human_tfs_v_1.01.txt http://humantfs.ccbr.utoronto.ca/download/v_1.01/TF_names_v_1.01.txt
  573. #We will also download a the program bedToBigBed this will be used to generate files which can be uploaded to the UCSC genome browser
  574. #wget -O /datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes/bedToBigBed/bedToBigBed http://hgdownload.soe.ucsc.edu/admin/exe/linux.x86_64/bedToBigBed
  575. #chmod +x /datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes/bedToBigBed/bedToBigBed
  576. #NOT DONE YET !! only keep the first two columns of the PCA embedding in order to be able to visualize this in SCope
  577. #scplus_obj.dr_cell['GEX_X_pca'] = scplus_obj.dr_cell['GEX_X_pca'].iloc[:, 0:2]
  578. #scplus_obj.dr_cell['GEX_rep'] = scplus_obj.dr_cell['GEX_rep'].iloc[:, 0:2]
  579. #Now we are ready to run the analysis and let?s run the SCENIC+ workflow
  580. from scenicplus.wrappers.run_scenicplus import run_scenicplus
  581. from scenicplus.wrappers.run_scenicplus import run_scenicplus
  582. try:
  583. run_scenicplus(
  584. scplus_obj = scplus_obj,
  585. variable = ['group_A'],
  586. species = 'hsapiens',
  587. assembly = 'hg38',
  588. tf_file = '/datos_2/Analysis/ALL_DATA_ANALYSIS/final_final/removing_doublets/new_phase_plots/GSEA/PAPER_PLOTS/ATAC/lvl_1_neuro/scenic_outcomes_control/DB_resources/utoronto_human_tfs_v_1.01.txt',
  589. save_path = os.path.join(work_dir, 'scenicplus_objects'),
  590. biomart_host = biomart_host,
  591. upstream = [1000, 150000],
  592. downstream = [1000, 150000],
  593. calculate_TF_eGRN_correlation = True,
  594. calculate_DEGs_DARs = True,
  595. export_to_loom_file = True,
  596. export_to_UCSC_file = True,
  597. path_bedToBigBed = work_dir,
  598. n_cpu = 12,
  599. _temp_dir = os.path.join(tmp_dir, 'ray_spill'))
  600. except Exception as e:
  601. #in case of failure, still save the object
  602. dill.dump(scplus_obj, open(os.path.join(work_dir, 'scenicplus/scplus_obj.pkl'), 'wb'), protocol=-1)
  603. raise(e)
  604. ############
  605. #Note on the output of SCENIC+
  606. ############
  607. #Both the raw gene expression counts and chromatin accessibility data are stored in
  608. scplus_obj.to_df('EXP').head()
  609. scplus_obj.to_df('ACC').head()
  610. #Cell metatdata is stored in
  611. scplus_obj.metadata_cell.head()
  612. #Region metadata is stored in
  613. scplus_obj.metadata_regions.head()
  614. #Gene metadata is stored in
  615. scplus_obj.metadata_genes.head()
  616. #Motif enrichment data is stored in
  617. scplus_obj.menr.keys()
  618. #Dimensionality reductions of the cells are stored in
  619. scplus_obj.dr_cell.keys()
  620. #Additional unstructured data will be stored in
  621. #Pre-SCENIC+
  622. #Cistromes: this contains TFs together with target regions based on the motif enrichment analysis (i.e. prior to running SCENIC+)
  623. #search_space: this is a dataframe containing the search space for each gene.
  624. #region_to_gene: this is a dataframe containing region to gene links prior to running SCENIC+ (i.e unfiltered/raw region to gene importance scores and correlation coefficients).
  625. #TF2G_adj: this is a datafram containing TF to gene links prior to running SCENIC+ (i.e unfiltered/raw TF to gene importance scores and correlation coefficients).
  626. #POST-SCENIC+
  627. #eRegulons: this is the raw output from the SCENIC+ analysis. We will go into a bit more detail for these below.
  628. #eRegulon_metadata: this is a dataframe containing the same information as eRegulons bit in a format which is a bit easier to parse for a human.
  629. #eRegulon_signatures: this is a dictionary with target regions and genes for each eRegulon
  630. #eRegulon_AUC: this slot contains dataframes with eRegulon enrichment scores calculated using AUCell (see below).
  631. #pseudobulk: contains pseudobulked gene expression and chromatin accessibility data, this is used to calculated TF to eRegulon correlation values.
  632. #TF_cistrome_correlation: contains correlation values between TF expression and eRegulon enrichment scores (seperate entries for target gene and target region based scores).
  633. #eRegulon_AUC_thresholds: contains thresholds on the AUC values (eRegulon enrichment scores), this is necessary to be able to visualize the results in SCope
  634. #RSS: contains eRegulon Specificity Scores (RSS), a measure on how cell type specific an eRegulon is.
  635. #DEGs: contains Differentially Expressed Genes.
  636. #DARs: contains Differentially Accessibile Regions.
  637. scplus_obj.uns.keys()
  638. #The main output of SCENIC+ are eRegulons
  639. #This is initially stored in a list of eRegulon classes as depicted below
  640. scplus_obj.uns['eRegulons'][0:5]
  641. #each eRegulon has the following information (attributes):
  642. #cistrome_name: name of the cistrome (from scenicplus.uns['Cistromes']) from which this eRegulon was created.
  643. #context: specifies the binarization method(s) used for binarizing region to gene relationships and wether positive/negative region-to-gene and TF-to-gene relationships were used
  644. #gsea_adj_pval/gsea_enrichment_score/gsea_pval/in_leading_edge: are internal parameters used for generating the eRegulons. The values are lost when generating the final eRegulons because results from several analysis (different binarization methods) are combined.
  645. #is_extended: specifies wether extended (i.e. non-direct) motif-to-TF annotations were used.
  646. #n_target_genes: number of target genes.
  647. #n_target_regions: number of target regions.
  648. #regions2genes: region to gene links after running SCENIC+.
  649. #target_genes: target genes of the eRegulon
  650. #target_regions: target regions of the eRegulon
  651. #transcription_factor: TF name
  652. for attr in dir(scplus_obj.uns['eRegulons'][0]):
  653. if not attr.startswith('_'):
  654. print(f"{attr}: {getattr(scplus_obj.uns['eRegulons'][0], attr) if not type(getattr(scplus_obj.uns['eRegulons'][0], attr)) == list else getattr(scplus_obj.uns['eRegulons'][0], attr)[0:5]}")
  655. #The information of all eRegulons is combined in the eRegulon_metadata dataframe
  656. scplus_obj.uns['eRegulon_metadata'].head()
  657. #For the eRegulon names we use the following convetion:
  658. #<TF NAME>_<TF-TO-GENE RELATIONSHIP (+/-)>_<REGION-TO-GENE RELATIONSHIP (+/-)>_(NUMBER OF TARGET REGIONS(r)/GENES(g))
  659. #For example the name: ARID3A_+_+_(364r) and ARID3A_+_+_(278g) indicates that the we found an eRegulon for the TF ARID3A which has 364 target regions and 278 target genes, that expression of the TF correlates positively with the expression of all the target genes (first + sign) and that the accessibility of all target regions correlates positively with the expression of all target regions (seconf + sign).
  660. ###########
  661. #Downstream analysis
  662. ###########
  663. import warnings
  664. warnings.simplefilter(action='ignore', category=FutureWarning)
  665. import sys
  666. _stderr = sys.stderr
  667. null = open(os.devnull,'wb')
  668. import dill
  669. scplus_obj = dill.load(open(os.path.join(work_dir, 'scenicplus_objects/scplus_obj.pkl'), 'rb'))
  670. #Simplifying and filtering SCENIC+ output
  671. #Given the multitude of eRegulons that can be generated for each TF (see above) we will first simplify the result by:
  672. #1. Only keeping eRegulons with an extended annotation if there is no direct annotation available (given that the confidence of direct motif annotations is in genral higher).
  673. #2. Discarding eRegulons for which the region-to-gene correlation is negative (these are often noisy).
  674. #3. Renaming the eRegulons so that eRegulons with the suffix TF_+_+ become TF_+ and those with TF_-_+ become TF_-.
  675. from scenicplus.preprocessing.filtering import apply_std_filtering_to_eRegulons
  676. apply_std_filtering_to_eRegulons(scplus_obj)
  677. #This will create two new entries in the scenicplus object:
  678. #scplus_obj.uns['eRegulon_metadata_filtered']
  679. #scplus_obj.uns['eRegulon_signatures_filtered'] containing the simplified results. We will use these for downstream analysis.
  680. scplus_obj.uns['eRegulon_metadata_filtered'].head()
  681. #eRegulon enrichment scores
  682. #We can score the enrichment of eRegulons using the AUCell function
  683. #This function takes as input a gene or region based ranking (ranking of genes/regions based on the expression/accessibility per cell) and a list of eRegulons.
  684. #These values were already calculated in the wrapper function but let?s recalculate them using the filtered output.
  685. from scenicplus.eregulon_enrichment import score_eRegulons
  686. region_ranking = dill.load(open(os.path.join(work_dir, 'scenicplus_objects/region_ranking.pkl'), 'rb')) #load ranking calculated using the wrapper function
  687. gene_ranking = dill.load(open(os.path.join(work_dir, 'scenicplus_objects/gene_ranking.pkl'), 'rb')) #load ranking calculated using the wrapper function
  688. score_eRegulons(scplus_obj,
  689. ranking = region_ranking,
  690. eRegulon_signatures_key = 'eRegulon_signatures_filtered',
  691. key_added = 'eRegulon_AUC_filtered',
  692. enrichment_type= 'region',
  693. auc_threshold = 0.05,
  694. normalize = False,
  695. n_cpu = 5)
  696. score_eRegulons(scplus_obj,
  697. gene_ranking,
  698. eRegulon_signatures_key = 'eRegulon_signatures_filtered',
  699. key_added = 'eRegulon_AUC_filtered',
  700. enrichment_type = 'gene',
  701. auc_threshold = 0.05,
  702. normalize= False,
  703. n_cpu = 5)
  704. #eRegulon dimensionality reduction
  705. #Based on the enrichment scores calculated above we can generate dimensionality reductions (e.g. tSNE and UMAP).
  706. #To calculate these dimensionality reductions we use both the regions and gene based enrichment scores.
  707. from scenicplus.dimensionality_reduction import run_eRegulons_tsne, run_eRegulons_umap
  708. run_eRegulons_umap(
  709. scplus_obj = scplus_obj,
  710. auc_key = 'eRegulon_AUC_filtered',
  711. reduction_name = 'eRegulons_UMAP', #overwrite previously calculated UMAP
  712. )
  713. run_eRegulons_tsne(
  714. scplus_obj = scplus_obj,
  715. auc_key = 'eRegulon_AUC_filtered',
  716. reduction_name = 'eRegulons_tSNE', #overwrite previously calculated tSNE
  717. )
  718. #Let?s visualize the UMAP and tSNE stored respectively in eRegulons_UMAP and eRegulons_tSNE, these are calculated based on the combined region and gene AUC values described above.
  719. #Let?s also add some nice colours by specifying a color_dictionary.
  720. from scenicplus.dimensionality_reduction import plot_metadata_given_ax
  721. import matplotlib.pyplot as plt
  722. import seaborn as sns
  723. %matplotlib inline
  724. #specify color_dictionary
  725. color_dict = {
  726. 'A': "#065143",
  727. 'B': "#70B77E",
  728. 'C': "#E0A890",
  729. 'D': "#F56476",
  730. 'E': "#CE1483"
  731. }
  732. color_dict_line = {
  733. 'A': '#9A031E',
  734. 'B': '#C75146',
  735. 'C': '#FFA987',
  736. 'D': '#222E50',
  737. 'E': '#8BB174',
  738. }
  739. full_name = work_dir + 'SCENIC+' + '_eRegulon_UMAP_and_TSNE' + '.pdf'
  740. fig, axs = plt.subplots(ncols=2, figsize = (16, 8))
  741. plot_metadata_given_ax(
  742. scplus_obj=scplus_obj,
  743. ax = axs[0],
  744. reduction_name = 'eRegulons_UMAP',
  745. variable = 'group_A', #note the GEX_ prefix, this metadata originated from the gene expression metadata (on which we did the cell type annotation before)
  746. color_dictionary={'GEX_celltype': color_dict}
  747. )
  748. plot_metadata_given_ax(
  749. scplus_obj=scplus_obj,
  750. ax = axs[1],
  751. reduction_name = 'eRegulons_tSNE',
  752. variable = 'group_A', #note the GEX_ prefix, this metadata originated from the gene expression metadata (on which we did the cell type annotation before)
  753. color_dictionary={'GEX_celltype': color_dict}
  754. )
  755. fig.tight_layout()
  756. sns.despine(ax = axs[0]) #remove top and right edge of axis border
  757. sns.despine(ax = axs[1]) #remove top and right edge of axis border
  758. #plt.show()
  759. plt.savefig(full_name)
  760. plt.close()
  761. #plot the activity / expression of an eRegulon on the dimensionality reduction
  762. #Nex we visualize the gene expression and target gene and region activity of some eRegulons on the tSNE.
  763. scplus_obj.uns['eRegulon_metadata'].head()
  764. from scenicplus.dimensionality_reduction import plot_eRegulon
  765. full_name = work_dir + 'SCENIC+' + '_eRegulon_gene_geneExp_region_activity__Inpairment_1' + '.pdf'
  766. plot_eRegulon(
  767. scplus_obj = scplus_obj,
  768. reduction_name = 'eRegulons_tSNE',
  769. selected_regulons = ['EBF1_+','TCF7L1_+','FOS_+','ASCL1_+'],
  770. scale = True,
  771. auc_key = 'eRegulon_AUC_filtered')
  772. plt.savefig(full_name)
  773. plt.close()
  774. full_name = work_dir + 'SCENIC+' + '_eRegulon_gene_geneExp_region_activity__Inpairment_2' + '.pdf'
  775. plot_eRegulon(
  776. scplus_obj = scplus_obj,
  777. reduction_name = 'eRegulons_tSNE',
  778. selected_regulons = ['POU2F2_+','PAX6_+','SOX2_+','PBX3_+','EGR1_+','GATA2_+','ONECUT1_+','ONECUT2_+','MEIS1_+','NKX6-1_+'],
  779. scale = True,
  780. auc_key = 'eRegulon_AUC_filtered')
  781. plt.savefig(full_name)
  782. plt.close()
  783. full_name = work_dir + 'SCENIC+' + '_eRegulon_gene_geneExp_region_activity__Inpairment_3' + '.pdf'
  784. plot_eRegulon(
  785. scplus_obj = scplus_obj,
  786. reduction_name = 'eRegulons_tSNE',
  787. selected_regulons = ['GATA2_+','ONECUT1_+','ONECUT2_+','MEIS1_+','NKX6-1_+'],
  788. scale = True,
  789. auc_key = 'eRegulon_AUC_filtered')
  790. plt.savefig(full_name)
  791. plt.close()
  792. full_name = work_dir + 'SCENIC+' + '_eRegulon_gene_geneExp_region_activity__Inpairment_Mature' + '.pdf'
  793. plot_eRegulon(
  794. scplus_obj = scplus_obj,
  795. reduction_name = 'eRegulons_tSNE',
  796. selected_regulons = ['PAX6_+'],
  797. scale = True,
  798. auc_key = 'eRegulon_AUC_filtered')
  799. plt.savefig(full_name)
  800. plt.close()
  801. #We can also plot only the activity of an eRegulon
  802. fig, ax = plt.subplots(figsize = (8,8))
  803. plot_AUC_given_ax(
  804. scplus_obj = scplus_obj,
  805. reduction_name = 'eRegulons_tSNE',
  806. feature = 'PAX5_+_(119g)',
  807. ax = ax,
  808. auc_key = 'eRegulon_AUC_filtered',
  809. signature_key = 'Gene_based')
  810. sns.despine(ax = ax)
  811. plt.show()
  812. #For eRegulons it is often usefull to visualize both information on the TF/target genes expression and region accessibility at the same time.
  813. #dotplot-heatmap
  814. #A dotplot-heatmap is a useful way to visualize this. Here the color of the heatmap can be used to visualize one aspect of the eRegulon (for example TF expression) and the size of the dot can be used to visualize another aspect (for example the enrichment (AUC value) of eRegulon target regions).
  815. #Before we plot the the dotplot-heatmap let?s first select some high quality eRegulons to limit the amount of space we need for the plot. One metric which can be used for selecting eRegulons is the correlation between TF expression and target region enrichment scores (AUC values). Let?s (re)calculate this value based on the simplified eRegulons
  816. #We first generate pseudobulk gene expression and region accessibility data, per celltype, to limit the amount of noise for the correlation calculation.
  817. from scenicplus.cistromes import TF_cistrome_correlation, generate_pseudobulks
  818. generate_pseudobulks(
  819. scplus_obj = scplus_obj,
  820. variable = 'group_A',
  821. auc_key = 'eRegulon_AUC_filtered',
  822. signature_key = 'Gene_based')
  823. generate_pseudobulks(
  824. scplus_obj = scplus_obj,
  825. variable = 'group_A',
  826. auc_key = 'eRegulon_AUC_filtered',
  827. signature_key = 'Region_based')
  828. TF_cistrome_correlation(
  829. scplus_obj,
  830. use_pseudobulk = True,
  831. variable = 'group_A',
  832. auc_key = 'eRegulon_AUC_filtered',
  833. signature_key = 'Gene_based',
  834. out_key = 'filtered_gene_based')
  835. TF_cistrome_correlation(
  836. scplus_obj,
  837. use_pseudobulk = True,
  838. variable = 'group_A',
  839. auc_key = 'eRegulon_AUC_filtered',
  840. signature_key = 'Region_based',
  841. out_key = 'filtered_region_based')
  842. scplus_obj.uns['TF_cistrome_correlation']['filtered_region_based'].head()
  843. #Let?s visualize these correlations in a scatter plot and select eRegulons for which the correlaiton coefficient is above 0.70 or below -0.75
  844. import numpy as np
  845. n_targets = [int(x.split('(')[1].replace('r)', '')) for x in scplus_obj.uns['TF_cistrome_correlation']['filtered_region_based']['Cistrome']]
  846. rho = scplus_obj.uns['TF_cistrome_correlation']['filtered_region_based']['Rho'].to_list()
  847. adj_pval = scplus_obj.uns['TF_cistrome_correlation']['filtered_region_based']['Adjusted_p-value'].to_list()
  848. thresholds = {
  849. 'rho': [-0.75, 0.70],
  850. 'n_targets': 0
  851. }
  852. import seaborn as sns
  853. full_name = work_dir + 'SCENIC+' + '_eRegulon_Correlation_+0.70_antiCorrelation_-0.75' + '.pdf'
  854. fig, ax = plt.subplots(figsize = (10, 5))
  855. sc = ax.scatter(rho, n_targets, c = -np.log10(adj_pval), s = 5)
  856. ax.set_xlabel('Correlation coefficient')
  857. ax.set_ylabel('nr. target regions')
  858. #ax.hlines(y = thresholds['n_targets'], xmin = min(rho), xmax = max(rho), color = 'black', ls = 'dashed', lw = 1)
  859. ax.vlines(x = thresholds['rho'], ymin = 0, ymax = max(n_targets), color = 'black', ls = 'dashed', lw = 1)
  860. ax.text(x = thresholds['rho'][0], y = max(n_targets), s = str(thresholds['rho'][0]))
  861. ax.text(x = thresholds['rho'][1], y = max(n_targets), s = str(thresholds['rho'][1]))
  862. sns.despine(ax = ax)
  863. fig.colorbar(sc, label = '-log10(adjusted_pvalue)', ax = ax)
  864. plt.savefig(full_name)
  865. plt.close()
  866. #Select eRegulons base on correlation
  867. selected_cistromes = scplus_obj.uns['TF_cistrome_correlation']['filtered_region_based'].loc[
  868. np.logical_or(
  869. scplus_obj.uns['TF_cistrome_correlation']['filtered_region_based']['Rho'] > thresholds['rho'][1],
  870. scplus_obj.uns['TF_cistrome_correlation']['filtered_region_based']['Rho'] < thresholds['rho'][0]
  871. )]['Cistrome'].to_list()
  872. selected_eRegulons = [x.split('_(')[0] for x in selected_cistromes]
  873. selected_eRegulons_gene_sig = [
  874. x for x in scplus_obj.uns['eRegulon_signatures_filtered']['Gene_based'].keys()
  875. if x.split('_(')[0] in selected_eRegulons]
  876. selected_eRegulons_region_sig = [
  877. x for x in scplus_obj.uns['eRegulon_signatures_filtered']['Region_based'].keys()
  878. if x.split('_(')[0] in selected_eRegulons]
  879. #save the results in the scenicplus object
  880. scplus_obj.uns['selected_eRegulon'] = {'Gene_based': selected_eRegulons_gene_sig, 'Region_based': selected_eRegulons_region_sig}
  881. print(f'selected: {len(selected_eRegulons_gene_sig)} eRegulons')
  882. ###########
  883. #66 eRegulons selected base ion this filters
  884. ###########
  885. #Let?s save these changes we have made to the scenicplus_obj
  886. dill.dump(scplus_obj, open(os.path.join(work_dir, 'scenicplus_objects/scplus_obj_after_filtering.pkl'), 'wb'), protocol=-1)
  887. #Let?s plot the heatmap-dotplot for the selected most interesting eRegulons
  888. from scenicplus.plotting.dotplot import heatmap_dotplot
  889. full_name = work_dir + 'SCENIC+' + '_Heatmap_of_filtered_most_relevant_eRegulons' + '.pdf'
  890. heatmap_dotplot(
  891. scplus_obj = scplus_obj,
  892. size_matrix = scplus_obj.uns['eRegulon_AUC_filtered']['Region_based'], #specify what to plot as dot sizes, target region enrichment in this case
  893. color_matrix = scplus_obj.to_df('EXP'), #specify what to plot as colors, TF expression in this case
  894. scale_size_matrix = True,
  895. scale_color_matrix = True,
  896. group_variable = 'group_A',
  897. subset_eRegulons = scplus_obj.uns['selected_eRegulon']['Gene_based'],
  898. index_order = ['A', 'B', 'C', 'D', 'E'],
  899. figsize = (5, 20),
  900. orientation = 'vertical')
  901. plt.savefig(full_name)
  902. plt.close()
  903. #Overlap of predicted target regions
  904. #An interesting aspect of gene regulation is transcription factor cooperativity (i.e. multiple TFs cobinding the same enhancer together driving gene expression).
  905. #By looking at the overlap of predicted target regions of TFs we can infer potential cooperativity events.
  906. #Let?s look at the overlap of target regions of the top 5 TFs per cell type based on the Regulon Specificity Score (RSS).
  907. #First we calculate the RSS for the target regions of the selected eRegulons.
  908. from scenicplus.RSS import *
  909. regulon_specificity_scores(
  910. scplus_obj,
  911. variable = 'group_A',
  912. auc_key = 'eRegulon_AUC_filtered',
  913. signature_keys = ['Region_based'],
  914. selected_regulons = [x for x in scplus_obj.uns['selected_eRegulon']['Region_based'] if '-' not in x],
  915. out_key_suffix = '_filtered')
  916. #Let?s visualize the RSS values using a scatter plot
  917. full_name = work_dir + 'SCENIC+' + '_transcription_factor_cooperativity_RSS' + '.pdf'
  918. plot_rss(scplus_obj, 'group_A_filtered', num_columns=5, top_n=10, figsize = (60, 12))
  919. plt.savefig(full_name)
  920. plt.close()
  921. #Next we select the top 10 eRegulons per cell type (group_A)
  922. flat_list = lambda t: [item for sublist in t for item in sublist]
  923. selected_markers = list(set(flat_list(
  924. [scplus_obj.uns['RSS']['group_A_filtered'].loc[celltype].sort_values(ascending = False).head(10).index.to_list()
  925. for celltype in scplus_obj.uns['RSS']['group_A_filtered'].index])))
  926. from scenicplus.plotting.correlation_plot import *
  927. region_intersetc_data, Z = jaccard_heatmap(
  928. scplus_obj,
  929. method = 'intersect',
  930. gene_or_region_based = 'Region_based',
  931. use_plotly = True,
  932. selected_regulons = selected_markers,
  933. signature_key = 'eRegulon_signatures_filtered',
  934. figsize = (10, 10), return_data = True, vmax = 0.5, cmap = 'plasma')
  935. #Plot top 10 eRegulons per cell type
  936. import seaborn as sns
  937. full_name = work_dir + 'SCENIC+' + '_top10_RSS_eRegulons_per_group' + '.pdf'
  938. sns.heatmap(region_intersetc_data, cmap='plasma')
  939. plt.savefig(full_name)
  940. plt.close()
  941. #Plotting a network
  942. #eRegulons can also be visualized in a network. Simple plots can be made using python. For more complicated plots (i.e. containing many nodes and edges) we suggest exporting your network to cytoscape.
  943. #Let?s create a very simple network for a cell type. We will use the top 1000 highly variable regions and genes in this plot. If you want to use more feautures please export your nework to cytoscape.
  944. from pycisTopic.diff_features import find_highly_variable_features
  945. hvr = find_highly_variable_features(scplus_obj.to_df('ACC').loc[list(set(scplus_obj.uns['eRegulon_metadata_filtered']['Region']))], n_top_features=1000, plot = False)
  946. hvg = find_highly_variable_features(scplus_obj.to_df('EXP')[list(set(scplus_obj.uns['eRegulon_metadata_filtered']['Gene']))].T, n_top_features=1000, plot = False)
  947. #First we format the eRegulons into a table which can be used to create a network using the package 'networkx'
  948. from scenicplus.networks import create_nx_tables, create_nx_graph, plot_networkx, export_to_cytoscape
  949. nx_tables = create_nx_tables(
  950. scplus_obj = scplus_obj,
  951. eRegulon_metadata_key ='eRegulon_metadata_filtered',
  952. subset_eRegulons = ['PAX6', 'EBF1', 'SOX2'],
  953. subset_regions = hvr,
  954. subset_genes = hvg,
  955. add_differential_gene_expression = True,
  956. add_differential_region_accessibility = True,
  957. differential_variable = ['group_A'])
  958. #Next we layout the graph.
  959. G, pos, edge_tables, node_tables = create_nx_graph(nx_tables,
  960. use_edge_tables = ['TF2R','R2G'],
  961. color_edge_by = {'TF2R': {'variable' : 'TF', 'category_color' : {'PAX6': 'Orange', 'EBF1': 'Purple', 'SOX2': 'Red'}},
  962. 'R2G': {'variable' : 'R2G_rho', 'continuous_color' : 'viridis', 'v_min': -1, 'v_max': 1}},
  963. transparency_edge_by = {'R2G': {'variable' : 'R2G_importance', 'min_alpha': 0.1, 'v_min': 0}},
  964. width_edge_by = {'R2G': {'variable' : 'R2G_importance', 'max_size' : 1.5, 'min_size' : 1}},
  965. color_node_by = {'TF': {'variable': 'TF', 'category_color' : {'PAX6': 'Orange', 'EBF1': 'Purple', 'SOX2': 'Red'}},
  966. 'Gene': {'variable': 'group_A_Log2FC_A', 'continuous_color' : 'bwr'},
  967. 'Region': {'variable': 'group_A_Log2FC_A', 'continuous_color' : 'viridis'}},
  968. transparency_node_by = {'Region': {'variable' : 'group_A_Log2FC_A', 'min_alpha': 0.1},
  969. 'Gene': {'variable' : 'group_A_Log2FC_A', 'min_alpha': 0.1}},
  970. size_node_by = {'TF': {'variable': 'fixed_size', 'fixed_size': 30},
  971. 'Gene': {'variable': 'fixed_size', 'fixed_size': 15},
  972. 'Region': {'variable': 'fixed_size', 'fixed_size': 10}},
  973. shape_node_by = {'TF': {'variable': 'fixed_shape', 'fixed_shape': 'ellipse'},
  974. 'Gene': {'variable': 'fixed_shape', 'fixed_shape': 'ellipse'},
  975. 'Region': {'variable': 'fixed_shape', 'fixed_shape': 'diamond'}},
  976. label_size_by = {'TF': {'variable': 'fixed_label_size', 'fixed_label_size': 15.0},
  977. 'Gene': {'variable': 'fixed_label_size', 'fixed_label_size': 5.0},
  978. 'Region': {'variable': 'fixed_label_size', 'fixed_label_size': 0.0}},
  979. layout='kamada_kawai_layout',
  980. scale_position_by=250)
  981. #Finally we can visualize the network.
  982. #In this network diamond shapes represent regions and they are color coded by their log2fc value in a cell type target genes and TFs are visualized using circles and are labeled.
  983. full_name = work_dir + 'SCENIC+' + '_eRegulons_network_group__A' + '.pdf'
  984. plt.figure(figsize=(10,10))
  985. plot_networkx(G, pos)
  986. plt.savefig(full_name)
  987. plt.close()
  988. #We can also export this network to a format which can be opened in Cytoscape.
  989. export_to_cytoscape(G, pos, out_file = os.path.join(work_dir, 'scenicplus_objects/network_B_cells.cys'))

1_atac_scenic_pipeline_paper.py at commit 96ee728, under GPL-3.0 · at the source

Overview

Authors: Idoia Blanco-Luquin1, Xabier Martínez-de-Morentin2, Amaia Vilas-Zornoza3,4,5, Daniel Mouzo6, Alejandro Lumbreras Lopez1, Mónica Macías1, Diego Alignani4,5, Alberto Maillo2, Ana Cecilia Gonzalez Alvarez2, Leena Ali Ibrahim2, Vincenzo Lagani2,7, Natalia Ramírez8, Jesper Tegner2,9,10,11, Felipe Prósper3,4,5,12,13, Maite Mendioroz1,14, David Gomez-Cabrero2
14 affiliations
  1. Neuroepigenetics Unit-Navarrabiomed, Hospital Universitario de Navarra (HUN), Universidad Pública de Navarra (UPNA), IdiSNA (Navarra Institute for Health Research), C/ Irunlarrea, 3, Pamplona, Navarra 31008 Spain
  2. Division of Biomedical Sciences, King Abdullah University of Science and Technology (KAUST), Thuwal, 23955 Saudi Arabia
  3. Advanced Genomics Laboratory, Program of Hemato-Oncology, Center for Applied Medical Research (CIMA), University of Navarra, Pamplona, Spain
  4. Hemato-Oncology Program, Center for Applied Medical Research (CIMA), IDISNA, University of Navarra, Pamplona, Spain
  5. Centro de Investigación Biomédica en Red de Cáncer (CIBERONC), Pamplona, Spain
  6. Centre for Haemato-Oncology, Barts Cancer Institute, Queen Mary University of London, Charterhouse Square, London, EC1M 6BQ UK
  7. SDAIA-KAUST Center of Excellence in Data Science and Artificial Intelligence, 4700 Thuwal, Jeddah, 23952 Saudi Arabia
  8. Oncohematology Research Group, Navarrabiomed, University Hospital of Navarra, Public University of Navarra, Navarra Medical Research Institute (IdiSNA), Pamplona, Spain
  9. Unit of Computational Medicine, Department of Medicine, Center for Molecular Medicine, Karolinska Institutet, Karolinska University Hospital, L8:05, SE-171 76 Stockholm, Sweden
  10. Computer, Electrical and Mathematical Sciences and Engineering Division, King Abdullah University of Science and Technology (KAUST), Thuwal, 23955-6900 Saudi Arabia
  11. Science for Life Laboratory, Tomtebodavagen 23A, SE-17165 Solna, Sweden
  12. Hematology Department, Clínica Universidad de Navarra, University of Navarra, Pamplona, Spain
  13. Program of Regenerative Medicine, Centre for Applied Medical Research (CIMA), University of Navarra, Pamplona, 31008, Spain; Instituto de Investigación Sanitaria de Navarra (IdiSNA), Pamplona, 31008 Spain
  14. Department of Neurology, Hospital Universitario de Navarra (HUN) - IdiSNA (Navarra Institute for Health Research), C/ Irunlarrea, 3, Pamplona, Navarra, 31008 Spain
Journal: Scientific data, volume 13, issue 1, article 638
Dates: received 25 September 2025; accepted 24 February 2026; published online 10 March 2026
Type: Data paper · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s41597-026-06971-4 · PMID 41807428 · PMCID PMC13103403 · OpenAlex W7134809807
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), human (organism), Alzheimer's / dementia (population)
Methods: Statistics, Smoothing, state filtering, decompositions, Machine learning, Connectivity
Keywords: Adult neurogenesis, Developmental neurogenesis
MeSH: Amyloid beta-Peptides*, Cell Differentiation*, Neural Stem Cells*, Neurons*, Transcriptome*, Epigenomics, Humans, Induced Pluripotent Stem Cells, Sequence Analysis, RNA, Single-Cell Analysis, Single-Cell Gene Expression Analysis (* major topic)
Topic: Single-cell and spatial transcriptomics (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Citations: not cited yet (Europe PMC); 38 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repository

Its files are read in the Code ↔ Paper reader above, with 10 matches between paragraphs and lines of code.

TranslationalBioinformaticsUnit/Human-neuronal-differentiation-under-AB-exposure-a-single-cell-transcriptomic-and-epigenomic-datase

License: GPL-3.0
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 96ee728ace5384907fb89eb9afce45e8afaffdbb, 4 February 2026
Languages: R (4), Python (1)
Size: 13 files, 5 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: clusterProfiler (4 files), ComplexHeatmap (3 files), ggplot2 (3 files), limma (3 files), tidyverse (3 files), circlize (2 files), igraph (2 files), Monocle 3 (2 files), Seurat (2 files), caret (1 file), cowplot (1 file), data.table (1 file), edgeR (1 file), Matplotlib (1 file), NumPy (1 file), pandas (1 file), pROC (1 file), reshape2 (1 file), Scanpy (1 file), seaborn (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
7 files

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s41597-026-06971-4.

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:

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

The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s41597-026-06971-4.

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, 16 authors, 2 keywords, 11 MeSH terms, 36 references.

Cite

This paper

Blanco-Luquin, I., Martínez-de-Morentin, X., Vilas-Zornoza, A., Mouzo, D., Lopez, A. L., Macías, M., Alignani, D., Maillo, A., Gonzalez Alvarez, A. C., Ibrahim, L. A., Lagani, V., Ramírez, N., Tegner, J., Prósper, F., Mendioroz, M., & Gomez-Cabrero, D. (2026). Human neuronal differentiation under Aβ exposure: a single-cell transcriptomic and epigenomic dataset. Scientific data, 13(1), 638. https://doi.org/10.1038/s41597-026-06971-4

BibTeX

@article{blancoluquin2026human,
author = {Blanco-Luquin, Idoia and Martínez-de-Morentin, Xabier and Vilas-Zornoza, Amaia and Mouzo, Daniel and Lopez, Alejandro Lumbreras and Macías, Mónica and Alignani, Diego and Maillo, Alberto and Gonzalez Alvarez, Ana Cecilia and Ibrahim, Leena Ali and Lagani, Vincenzo and Ramírez, Natalia and Tegner, Jesper and Prósper, Felipe and Mendioroz, Maite and Gomez-Cabrero, David},
title = {{Human neuronal differentiation under Aβ exposure: a single-cell transcriptomic and epigenomic dataset}},
journal = {Scientific data},
year = {2026},
month = mar,
volume = {13},
number = {1},
pages = {638},
publisher = {Nature Publishing Group},
issn = {2052-4463},
doi = {10.1038/s41597-026-06971-4},
url = {https://doi.org/10.1038/s41597-026-06971-4},
pmid = {41807428},
pmcid = {PMC13103403}
}

RIS

TY - JOUR
AU - Blanco-Luquin, Idoia
AU - Martínez-de-Morentin, Xabier
AU - Vilas-Zornoza, Amaia
AU - Mouzo, Daniel
AU - Lopez, Alejandro Lumbreras
AU - Macías, Mónica
AU - Alignani, Diego
AU - Maillo, Alberto
AU - Gonzalez Alvarez, Ana Cecilia
AU - Ibrahim, Leena Ali
AU - Lagani, Vincenzo
AU - Ramírez, Natalia
AU - Tegner, Jesper
AU - Prósper, Felipe
AU - Mendioroz, Maite
AU - Gomez-Cabrero, David
TI - Human neuronal differentiation under Aβ exposure: a single-cell transcriptomic and epigenomic dataset
T2 - Scientific data
J2 - Sci Data
PY - 2026
DA - 2026/03/10
VL - 13
IS - 1
SP - 638
SN - 2052-4463
PB - Nature Publishing Group
DO - 10.1038/s41597-026-06971-4
UR - https://doi.org/10.1038/s41597-026-06971-4
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41597-026-06971-4",
"type": "article-journal",
"title": "Human neuronal differentiation under Aβ exposure: a single-cell transcriptomic and epigenomic dataset",
"container-title": "Scientific data",
"author": [
{
"family": "Blanco-Luquin",
"given": "Idoia"
},
{
"family": "Martínez-de-Morentin",
"given": "Xabier"
},
{
"family": "Vilas-Zornoza",
"given": "Amaia"
},
{
"family": "Mouzo",
"given": "Daniel"
},
{
"family": "Lopez",
"given": "Alejandro Lumbreras"
},
{
"family": "Macías",
"given": "Mónica"
},
{
"family": "Alignani",
"given": "Diego"
},
{
"family": "Maillo",
"given": "Alberto"
},
{
"family": "Gonzalez Alvarez",
"given": "Ana Cecilia"
},
{
"family": "Ibrahim",
"given": "Leena Ali"
},
{
"family": "Lagani",
"given": "Vincenzo"
},
{
"family": "Ramírez",
"given": "Natalia"
},
{
"family": "Tegner",
"given": "Jesper"
},
{
"family": "Prósper",
"given": "Felipe"
},
{
"family": "Mendioroz",
"given": "Maite"
},
{
"family": "Gomez-Cabrero",
"given": "David"
}
],
"container-title-short": "Sci Data",
"volume": "13",
"issue": "1",
"page": "638",
"DOI": "10.1038/s41597-026-06971-4",
"PMID": "41807428",
"PMCID": "PMC13103403",
"ISSN": "2052-4463",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41597-026-06971-4",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
10
]
]
}
}

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.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: pROC, Monocle 3, edgeR, 16 other tools, genetics / omics, 5 references
[2] doi:10.3390/ijms27104466 [code]
Uncovering the Key Circuit FOSL2/FOS/EGR3/EGR1, Contributing to the Hyperexcitability of Excitatory Neurons in the Epileptic Temporal Cortex and Hippocampus.
Journal: International journal of molecular sciences
In common: pROC, Monocle 3, caret, 13 other tools, genetics / omics, 2 references
[3] doi:10.1002/imt2.70163 [code]
Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.
Journal: iMeta
In common: Monocle 3, edgeR, limma, 15 other tools, genetics / omics
[4] doi:10.1038/s42003-026-10957-8 [code]
Brain defence by the extracellular matrix protein Cochlin.
Journal: Communications biology
In common: Monocle 3, caret, edgeR, 14 other tools
[5] doi:10.1093/bioinformatics/btag592 [code]
Network-based stratification of allele-specific expression reveals patient subgroups in Huntington's disease.
Journal: Bioinformatics (Oxford, England)
In common: pROC, edgeR, limma, 13 other tools, genetics / omics, 2 references
[6] doi:10.1038/s41586-026-10214-2 [code]
Multidimensional profiling of heterogeneity in supratentorial ependymomas.
Journal: Nature
In common: Monocle 3, edgeR, igraph, 14 other tools, genetics / omics
[7] doi:10.1101/gr.281113.125 [code]
Single-nucleus multiomic profiling of the aging mouse substantia nigra reveals conserved gene alterations linked to Parkinson's disease.
Journal: Genome research
In common: Monocle 3, edgeR, limma, 11 other tools, genetics / omics, 3 references
[8] doi:10.1186/s12967-026-08266-z [code]
Single-cell multi-omic integration analysis prioritizes druggable genes and reveals cell-type-specific causal effects in glioblastomagenesis.
Journal: Journal of translational medicine
In common: Monocle 3, edgeR, limma, 10 other tools, genetics / omics, 2 references
[9] doi:10.1186/s13059-026-04177-w [code]
Genomic sequence evolution underlying human neocortical interareal diversification.
Journal: Genome biology
In common: Monocle 3, igraph, circlize, 11 other tools, genetics / omics, 3 references
[10] 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: Monocle 3, edgeR, limma, 10 other tools, Alzheimer's / dementia, 1 reference

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.